@polderlabs/bizar 6.2.4 → 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 (332) 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 +31 -18
  125. package/cli/commands/claude-cmd.mjs +348 -0
  126. package/cli/commands/install.mjs +12 -11
  127. package/cli/commands/sandbox.mjs +220 -0
  128. package/cli/commands/validate.mjs +252 -288
  129. package/cli/dev-link.test.mjs +11 -11
  130. package/cli/doctor.mjs +131 -213
  131. package/cli/install.mjs +33 -37
  132. package/cli/install.test.mjs +9 -9
  133. package/cli/provision-claude.mjs +893 -0
  134. package/cli/provision.mjs +330 -226
  135. package/cli/provision.test.mjs +102 -0
  136. package/cli/utils.mjs +72 -58
  137. package/config/AGENTS.md +28 -28
  138. package/config/agents/_shared/AGENT_BASELINE.md +104 -684
  139. package/config/skills/bizar/SKILL.md +197 -0
  140. package/config/skills/cubesandbox/SKILL.md +148 -0
  141. package/config/skills/harness-engineering/SKILL.md +142 -0
  142. package/install.sh +66 -44
  143. package/package.json +19 -11
  144. package/packages/sdk/ARCHITECTURE.md +40 -36
  145. package/packages/sdk/package-lock.json +32 -0
  146. package/packages/sdk/package.json +15 -5
  147. package/{plugins/bizar → packages/sdk}/src/dangerous-patterns.ts +6 -28
  148. package/packages/sdk/src/fingerprint.ts +0 -0
  149. package/packages/sdk/src/index.ts +38 -73
  150. package/packages/sdk/src/mcp/bin.ts +51 -0
  151. package/packages/sdk/src/mcp/server.ts +498 -0
  152. package/{plugins/bizar/src/memory-vault.ts → packages/sdk/src/memory/index.ts} +18 -21
  153. package/packages/sdk/tests/sdk.test.mjs +148 -0
  154. package/packages/sdk/vitest.config.ts +1 -1
  155. package/scripts/bh-full-e2e.mjs +166 -363
  156. package/scripts/check-deps.mjs +28 -46
  157. package/scripts/mirror-claude-md.sh +78 -0
  158. package/scripts/test-in-container.sh +157 -0
  159. package/templates/clean-state-checklist.md +3 -3
  160. package/templates/sprint-contract.md +2 -2
  161. package/bizar-dash/.bizar/activity.log +0 -3
  162. package/bizar-dash/.omx/logs/omx-2026-07-07.jsonl +0 -1
  163. package/bizar-dash/.omx/state/session.json +0 -10
  164. package/bizar-dash/bizar-design/EXPLANATION.md +0 -307
  165. package/bizar-dash/bizar-design/INSTRUCTIONS.md +0 -149
  166. package/bizar-dash/bizar-design/canvas.html +0 -281
  167. package/bizar-dash/bizar-design/canvas.html.artifact.json +0 -19
  168. package/bizar-dash/bizar-design/components.css +0 -1665
  169. package/bizar-dash/bizar-design/components.html +0 -557
  170. package/bizar-dash/bizar-design/components.html.artifact.json +0 -19
  171. package/bizar-dash/bizar-design/desktop/agents.html +0 -74
  172. package/bizar-dash/bizar-design/desktop/agents.html.artifact.json +0 -19
  173. package/bizar-dash/bizar-design/desktop/memory.html +0 -75
  174. package/bizar-dash/bizar-design/desktop/memory.html.artifact.json +0 -19
  175. package/bizar-dash/bizar-design/desktop/metrics.html +0 -63
  176. package/bizar-dash/bizar-design/desktop/metrics.html.artifact.json +0 -19
  177. package/bizar-dash/bizar-design/desktop/overview.html +0 -95
  178. package/bizar-dash/bizar-design/desktop/overview.html.artifact.json +0 -19
  179. package/bizar-dash/bizar-design/desktop/settings.html +0 -70
  180. package/bizar-dash/bizar-design/desktop/settings.html.artifact.json +0 -19
  181. package/bizar-dash/bizar-design/icons.svg +0 -44
  182. package/bizar-dash/bizar-design/index.html +0 -192
  183. package/bizar-dash/bizar-design/index.html.artifact.json +0 -19
  184. package/bizar-dash/bizar-design/mobile/agents.html +0 -29
  185. package/bizar-dash/bizar-design/mobile/agents.html.artifact.json +0 -19
  186. package/bizar-dash/bizar-design/mobile/memory.html +0 -28
  187. package/bizar-dash/bizar-design/mobile/memory.html.artifact.json +0 -19
  188. package/bizar-dash/bizar-design/mobile/metrics.html +0 -29
  189. package/bizar-dash/bizar-design/mobile/metrics.html.artifact.json +0 -19
  190. package/bizar-dash/bizar-design/mobile/overview.html +0 -33
  191. package/bizar-dash/bizar-design/mobile/overview.html.artifact.json +0 -19
  192. package/bizar-dash/bizar-design/mobile/settings.html +0 -28
  193. package/bizar-dash/bizar-design/mobile/settings.html.artifact.json +0 -19
  194. package/bizar-dash/bizar-design/prototype.js +0 -114
  195. package/bizar-dash/bizar-design/tokens.css +0 -106
  196. package/bizar-dash/dist/assets/vendor-CeHGtduv.js.map +0 -1
  197. package/bizar-dash/node_modules/.package-lock.json +0 -6
  198. package/bizar-dash/package-lock.json +0 -6
  199. package/bizar-dash/src/server/cline-sdk.mjs +0 -132
  200. package/bizar-dash/src/server/routes/cline-session-detail.mjs +0 -559
  201. package/bizar-dash/src/server/routes/cline-sessions.mjs +0 -291
  202. package/cli/commands/cline-cmd.mjs +0 -289
  203. package/cli/commands/validate.test.mjs +0 -344
  204. package/cli/doctor.test.mjs +0 -350
  205. package/config/cline.json.template +0 -342
  206. package/packages/sdk/src/client.ts +0 -188
  207. package/packages/sdk/src/cline-events.ts +0 -134
  208. package/packages/sdk/src/cline-types.ts +0 -66
  209. package/packages/sdk/src/cline.ts +0 -339
  210. package/packages/sdk/src/errors.ts +0 -129
  211. package/packages/sdk/src/events.ts +0 -153
  212. package/packages/sdk/src/types.ts +0 -176
  213. package/packages/sdk/tests/client.test.ts +0 -217
  214. package/packages/sdk/tests/errors.test.ts +0 -108
  215. package/packages/sdk/tests/events.test.ts +0 -139
  216. package/packages/sdk/tests/fixtures/fetch-mock.ts +0 -152
  217. package/packages/sdk/tests/fixtures/sse-mock.ts +0 -30
  218. package/plugins/bizar/ARCHITECTURE.md +0 -142
  219. package/plugins/bizar/CONSTRAINTS.md +0 -67
  220. package/plugins/bizar/LICENSE +0 -21
  221. package/plugins/bizar/README.md +0 -448
  222. package/plugins/bizar/index.ts +0 -872
  223. package/plugins/bizar/package.json +0 -39
  224. package/plugins/bizar/scripts/check-forbidden-imports.sh +0 -33
  225. package/plugins/bizar/src/background-state.ts +0 -641
  226. package/plugins/bizar/src/background.ts +0 -1806
  227. package/plugins/bizar/src/cline-runner.ts +0 -203
  228. package/plugins/bizar/src/clineruntime.ts +0 -227
  229. package/plugins/bizar/src/commands-impl.ts +0 -151
  230. package/plugins/bizar/src/commands.ts +0 -1799
  231. package/plugins/bizar/src/compaction.d.mts +0 -48
  232. package/plugins/bizar/src/compaction.mjs +0 -192
  233. package/plugins/bizar/src/dashboard-client.ts +0 -233
  234. package/plugins/bizar/src/event-stream.ts +0 -606
  235. package/plugins/bizar/src/fingerprint.ts +0 -120
  236. package/plugins/bizar/src/handoff.ts +0 -79
  237. package/plugins/bizar/src/hooks/memory-flush-on-compact.ts +0 -123
  238. package/plugins/bizar/src/hooks/memory-inject.ts +0 -247
  239. package/plugins/bizar/src/hooks/memory-write-on-end.ts +0 -188
  240. package/plugins/bizar/src/hooks/skill-curator.ts +0 -180
  241. package/plugins/bizar/src/http-client.ts +0 -467
  242. package/plugins/bizar/src/key-rotation.ts +0 -218
  243. package/plugins/bizar/src/logger.ts +0 -144
  244. package/plugins/bizar/src/loop-engineering.ts +0 -241
  245. package/plugins/bizar/src/loop.ts +0 -176
  246. package/plugins/bizar/src/mistake-recovery.ts +0 -98
  247. package/plugins/bizar/src/odin.ts +0 -227
  248. package/plugins/bizar/src/options.ts +0 -470
  249. package/plugins/bizar/src/plan-fs.ts +0 -323
  250. package/plugins/bizar/src/reasoning-clean.ts +0 -454
  251. package/plugins/bizar/src/report.ts +0 -178
  252. package/plugins/bizar/src/research-prompt.ts +0 -35
  253. package/plugins/bizar/src/serve-info.ts +0 -228
  254. package/plugins/bizar/src/serve.ts +0 -496
  255. package/plugins/bizar/src/settings.ts +0 -349
  256. package/plugins/bizar/src/state.ts +0 -298
  257. package/plugins/bizar/src/tool-discipline.ts +0 -105
  258. package/plugins/bizar/src/tools/agent-browser.ts +0 -315
  259. package/plugins/bizar/src/tools/bg-collect.ts +0 -131
  260. package/plugins/bizar/src/tools/bg-get-comments.ts +0 -266
  261. package/plugins/bizar/src/tools/bg-kill.ts +0 -116
  262. package/plugins/bizar/src/tools/bg-pause.ts +0 -99
  263. package/plugins/bizar/src/tools/bg-report-progress.ts +0 -115
  264. package/plugins/bizar/src/tools/bg-resume.ts +0 -94
  265. package/plugins/bizar/src/tools/bg-send-message.ts +0 -223
  266. package/plugins/bizar/src/tools/bg-spawn.ts +0 -502
  267. package/plugins/bizar/src/tools/bg-status.ts +0 -130
  268. package/plugins/bizar/src/tools/graph-query.ts +0 -278
  269. package/plugins/bizar/src/tools/loop-engineering.ts +0 -193
  270. package/plugins/bizar/src/tools/memory-list.ts +0 -43
  271. package/plugins/bizar/src/tools/memory-read.ts +0 -69
  272. package/plugins/bizar/src/tools/memory-search.ts +0 -47
  273. package/plugins/bizar/src/tools/memory-write.ts +0 -54
  274. package/plugins/bizar/src/tools/open-kb.ts +0 -198
  275. package/plugins/bizar/src/tools/plan-action.ts +0 -785
  276. package/plugins/bizar/src/tools/read-glyph-feedback.ts +0 -191
  277. package/plugins/bizar/src/tools/team-spawn.ts +0 -73
  278. package/plugins/bizar/src/tools/team-status.ts +0 -76
  279. package/plugins/bizar/src/tools/wait-for-feedback.ts +0 -415
  280. package/plugins/bizar/src/trajectory.ts +0 -104
  281. package/plugins/bizar/tests/README.md +0 -99
  282. package/plugins/bizar/tests/attach-handler-bug.test.ts +0 -169
  283. package/plugins/bizar/tests/background-state.test.ts +0 -277
  284. package/plugins/bizar/tests/background.test.ts +0 -402
  285. package/plugins/bizar/tests/block.test.ts +0 -195
  286. package/plugins/bizar/tests/canonical-key-order.test.ts +0 -75
  287. package/plugins/bizar/tests/clineruntime-config.test.ts +0 -283
  288. package/plugins/bizar/tests/commands-impl.test.ts +0 -316
  289. package/plugins/bizar/tests/commands.test.ts +0 -584
  290. package/plugins/bizar/tests/compaction.test.ts +0 -264
  291. package/plugins/bizar/tests/config.test.ts +0 -128
  292. package/plugins/bizar/tests/dashboard-client.test.ts +0 -159
  293. package/plugins/bizar/tests/dispose.test.ts +0 -336
  294. package/plugins/bizar/tests/event-stream.test.ts +0 -409
  295. package/plugins/bizar/tests/event.test.ts +0 -262
  296. package/plugins/bizar/tests/fingerprint.test.ts +0 -162
  297. package/plugins/bizar/tests/http-client.test.ts +0 -404
  298. package/plugins/bizar/tests/init-helpers.test.ts +0 -203
  299. package/plugins/bizar/tests/integration/slash-command.test.ts +0 -349
  300. package/plugins/bizar/tests/integration/tool-routing.test.ts +0 -98
  301. package/plugins/bizar/tests/key-rotation.test.ts +0 -396
  302. package/plugins/bizar/tests/loop-engineering.test.ts +0 -168
  303. package/plugins/bizar/tests/loop.test.ts +0 -397
  304. package/plugins/bizar/tests/memory-write-on-end.test.ts +0 -92
  305. package/plugins/bizar/tests/mistake-recovery.test.ts +0 -116
  306. package/plugins/bizar/tests/odin.test.ts +0 -125
  307. package/plugins/bizar/tests/options.test.ts +0 -329
  308. package/plugins/bizar/tests/reasoning-clean.test.ts +0 -422
  309. package/plugins/bizar/tests/safety.test.ts +0 -256
  310. package/plugins/bizar/tests/serve.test.ts +0 -339
  311. package/plugins/bizar/tests/settings.test.ts +0 -351
  312. package/plugins/bizar/tests/stall-think.test.ts +0 -750
  313. package/plugins/bizar/tests/state.test.ts +0 -276
  314. package/plugins/bizar/tests/tool-discipline.test.ts +0 -77
  315. package/plugins/bizar/tests/tools/agent-browser.test.ts +0 -98
  316. package/plugins/bizar/tests/tools/bg-collect.test.ts +0 -337
  317. package/plugins/bizar/tests/tools/bg-get-comments.test.ts +0 -485
  318. package/plugins/bizar/tests/tools/bg-kill.test.ts +0 -235
  319. package/plugins/bizar/tests/tools/bg-pause.test.ts +0 -61
  320. package/plugins/bizar/tests/tools/bg-report-progress.test.ts +0 -79
  321. package/plugins/bizar/tests/tools/bg-resume.test.ts +0 -40
  322. package/plugins/bizar/tests/tools/bg-send-message.test.ts +0 -116
  323. package/plugins/bizar/tests/tools/bg-spawn-delegation.test.ts +0 -147
  324. package/plugins/bizar/tests/tools/bg-spawn-http.test.ts +0 -233
  325. package/plugins/bizar/tests/tools/bg-spawn.test.ts +0 -311
  326. package/plugins/bizar/tests/tools/bg-status.test.ts +0 -217
  327. package/plugins/bizar/tests/tools/cline-runner.test.ts +0 -115
  328. package/plugins/bizar/tests/tools/plan-action.test.ts +0 -599
  329. package/plugins/bizar/tests/tools/read-glyph-feedback.test.ts +0 -253
  330. package/plugins/bizar/tests/tools/wait-for-feedback.test.ts +0 -390
  331. package/plugins/bizar/tests/update-deadlock.test.ts +0 -151
  332. package/plugins/bizar/tsconfig.json +0 -29
@@ -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.1Cline-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.0Claude 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(', ')}`;
186
+ }
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');
170
224
  }
171
- return `runtime deps present (${REQUIRED_RUNTIME_DEPS.join(', ')})`;
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);
@@ -230,7 +294,7 @@ const CHECKS = {
230
294
  },
231
295
 
232
296
  'rules-installed': async () => {
233
- const dir = join(clineDir(), 'rules');
297
+ const dir = join(claudeDir(), 'rules');
234
298
  if (!existsSync(dir)) throw new Error(`rules dir missing: ${dir} — run \`bizar update\``);
235
299
  const entries = readdirSync(dir).filter((f) => f.endsWith('.md') || f.endsWith('.txt'));
236
300
  if (entries.length === 0) throw new Error('no rules installed — run `bizar update`');
@@ -238,17 +302,15 @@ const CHECKS = {
238
302
  },
239
303
 
240
304
  'hooks-installed': async () => {
241
- const dir = join(clineDir(), 'hooks');
305
+ const dir = join(claudeDir(), 'hooks');
242
306
  if (!existsSync(dir)) throw new Error(`hooks dir missing: ${dir} — run \`bizar update\``);
243
307
  const missing = REQUIRED_HOOKS.filter((f) => !existsSync(join(dir, f)));
244
308
  if (missing.length > 0) {
245
309
  throw new Error(`missing: ${missing.join(', ')} — run \`bizar update\``);
246
310
  }
247
- // Verify hooks are executable (Cline silently skips non-executable
248
- // hook files per the official contract). On Windows, chmod is a
249
- // 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.
250
313
  if (process.platform !== 'win32') {
251
- const { statSync } = await import('node:fs');
252
314
  const nonExec = [];
253
315
  for (const f of REQUIRED_HOOKS) {
254
316
  try {
@@ -260,89 +322,49 @@ const CHECKS = {
260
322
  }
261
323
  }
262
324
  if (nonExec.length > 0) {
263
- 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/*\``);
264
326
  }
265
327
  }
266
- 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}`;
267
329
  },
268
330
 
269
- 'hooks-canonical-location': async () => {
270
- // Cline's default global hooks location per the official docs:
271
- // `~/Documents/Cline/Hooks/`. Verify our hooks are also there
272
- // (Bizar install puts them in BOTH ~/.cline/hooks/ and
273
- // ~/Documents/Cline/Hooks/ for max compatibility).
274
- const canonical = join(homedir(), 'Documents', 'Cline', 'Hooks');
275
- if (!existsSync(canonical)) {
276
- return `optional: ${canonical} does not exist yet — \`bizar install\` creates it`;
277
- }
278
- const missing = REQUIRED_HOOKS.filter((f) => !existsSync(join(canonical, f)));
279
- if (missing.length > 0) {
280
- 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\``);
281
335
  }
282
- return `canonical hooks dir ${canonical} has all ${REQUIRED_HOOKS.length} hook(s)`;
336
+ return `BIZAR_HOME = ${h}`;
283
337
  },
284
338
 
285
- 'provider-config': async () => {
286
- // v6.2.2 The installer no longer adds a provider block. The user
287
- // must configure their own provider. This check is therefore
288
- // ALWAYS lenient (returns a hint, never fails). It just reports
289
- // what's in cline.json so the user can see the current state.
290
- const cfg = readJsonSafe(clineJsonPath());
291
- if (!cfg?.provider || Object.keys(cfg.provider).length === 0) {
292
- 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\``);
293
343
  }
294
- const names = Object.keys(cfg.provider);
295
- const summary = names.map((n) => {
296
- const p = cfg.provider[n];
297
- const url = p?.baseUrl || p?.options?.baseURL || '(no baseUrl)';
298
- const modelCount = Object.keys(p?.models || {}).length;
299
- return `${n} (${modelCount} models, baseUrl=${url})`;
300
- });
301
- return `user-configured providers: ${summary.join('; ')}`;
344
+ return `memory vault = ${vault}`;
302
345
  },
303
346
 
304
- 'cline-settings-provider': async () => {
305
- // v6.2.3The Cline CLI and kanban mode read from
306
- // `~/.cline/data/settings/providers.json`. The harness config
307
- // (`cline.json`) is a separate thing. This check inspects the
308
- // actual settings file and:
309
- // 1. Warns if the user has a legacy `openai-compatible` providerId
310
- // (from the v6.0.1 Cline auto-migration shim). Kanban mode
311
- // fails on this with "Unknown or disabled provider". Run
312
- // `bizar setup-provider` to auto-migrate.
313
- // 2. Reports the active `lastUsedProvider` so the user can
314
- // see which provider Cline will actually use on the next
315
- // session.
316
- const file = join(homedir(), '.cline', 'data', 'settings', 'providers.json');
317
- if (!existsSync(file)) {
318
- return 'no settings file at ~/.cline/data/settings/providers.json — run `bizar setup-provider` to add one';
319
- }
320
- const settings = readJsonSafe(file);
321
- if (!settings || !settings.providers) {
322
- return 'settings file is empty or invalid — run `bizar setup-provider`';
323
- }
324
- const names = Object.keys(settings.providers);
325
- if (names.length === 0) {
326
- throw new Error('no providers configured in Cline settings — run `bizar setup-provider`');
327
- }
328
- const issues = [];
329
- if (names.includes('openai-compatible')) {
330
- issues.push(`legacy 'openai-compatible' providerId present (broken in kanban mode) — run \`bizar setup-provider\` to auto-migrate to 'litellm'`);
331
- }
332
- // Check for any providerId that's not in Cline's built-in catalog.
333
- for (const n of names) {
334
- if (n === 'openai-compatible') continue; // handled above
335
- if (!OPENAI_COMPATIBLE_BUILTIN_IDS.has(n)) {
336
- 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.0for 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)`;
337
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)`;
338
367
  }
339
- const lastUsed = settings.lastUsedProvider || '(none)';
340
- if (issues.length > 0) {
341
- // Throw so the ⚠ marker shows up; the check is in LENIENT_CHECKS
342
- // so this won't cause `bizar validate` to exit non-zero.
343
- throw new Error(`WARN: ${issues.join('; ')}. lastUsedProvider=${lastUsed} (${names.join(', ')})`);
344
- }
345
- return `lastUsedProvider=${lastUsed}; providers: ${names.join(', ')}`;
346
368
  },
347
369
 
348
370
  '9router-reachable': async () => {
@@ -362,92 +384,33 @@ const CHECKS = {
362
384
  }
363
385
  },
364
386
 
365
- // v6.2.4 Warn if the user's clineruntimeMaxConsecutiveMistakes is
366
- // below the plugin's recommended minimum. Cline's CLI default is 3
367
- // which aborts sessions on the 3rd tool mistake. The Bizar plugin
368
- // recommends 10 (or `--retries N` with N 10).
369
- 'mistake-limit-floor': async () => {
370
- const MIN = 10;
371
- const cfg = readJsonSafe(clineJsonPath());
372
- if (!cfg?.plugin || !Array.isArray(cfg.plugin)) {
373
- return 'no plugin entries in cline.json — skip mistake-limit check';
374
- }
375
- const bizarEntry = cfg.plugin.find((p) => Array.isArray(p) && p[0] && p[0].includes('plugins/bizar'));
376
- if (!bizarEntry) {
377
- return 'Bizar plugin not registered — 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`);
378
391
  }
379
- const opts = (Array.isArray(bizarEntry) && bizarEntry[1]) || {};
380
- const raw = opts.clineruntimeMaxConsecutiveMistakes;
381
- if (typeof raw !== 'number' || raw >= MIN) {
382
- return `clineruntimeMaxConsecutiveMistakes=${raw ?? 'default 10'} (≥ ${MIN}) — OK`;
383
- }
384
- throw new Error(
385
- `clineruntimeMaxConsecutiveMistakes=${raw} is BELOW the recommended minimum (${MIN}). ` +
386
- `Cline's default of 3 aborts the session on the 3rd tool mistake. ` +
387
- `Edit ~/.cline/cline.json plugin[1].clineruntimeMaxConsecutiveMistakes to ${MIN}, or run ` +
388
- `\`bizar install\` to reset to defaults. (See _shared/CLINE_TOOLS.md for the top-5 mistakes.)`,
389
- );
390
- },
391
-
392
- 'default-agent-set': async () => {
393
- const cfg = readJsonSafe(clineJsonPath());
394
- if (!cfg?.default_agent) {
395
- throw new Error('no default_agent in cline.json — should be "odin"');
396
- }
397
- return `default_agent=${cfg.default_agent}`;
398
- },
399
-
400
- 'instructions-loaded': async () => {
401
- const cfg = readJsonSafe(clineJsonPath());
402
- if (!cfg?.instructions || (Array.isArray(cfg.instructions) && cfg.instructions.length === 0)) {
403
- throw new Error('no instructions[] in cline.json — Cline won\'t load the tools reference');
404
- }
405
- const ins = Array.isArray(cfg.instructions) ? cfg.instructions : [cfg.instructions];
406
- return `${ins.length} instruction file(s) referenced`;
407
- },
408
-
409
- 'plugin-index-loadable': async () => {
410
- // Spot-check that the deployed plugin's index.ts is on disk and looks
411
- // like a Cline plugin (has the `setup` function + registerTool pattern).
412
- const idx = join(clineDir(), 'plugins', 'bizar', 'index.ts');
413
- if (!existsSync(idx)) {
414
- throw new Error(`${idx} missing — plugin not copied`);
415
- }
416
- const stat = statSync(idx);
417
- if (stat.size < 100) {
418
- throw new Error(`${idx} is suspiciously small (${stat.size} bytes)`);
419
- }
420
- return `plugin index.ts: ${stat.size} bytes`;
421
- },
422
-
423
- 'enable-agent-teams': async () => {
424
- // The /team command depends on `enableAgentTeams: true` in
425
- // plugins/bizar/src/clineruntime.ts. Static check by reading the
426
- // source file from the deployed plugin dir.
427
- const rt = join(clineDir(), 'plugins', 'bizar', 'src', 'clineruntime.ts');
428
- if (!existsSync(rt)) {
429
- // Source-only install (npm bundled): can't check here, skip leniently.
430
- return 'skipped (bundled install)';
431
- }
432
- const text = readFileSync(rt, 'utf8');
433
- if (!/enableAgentTeams:\s*true/.test(text)) {
434
- throw new Error('enableAgentTeams is not true in clineruntime.ts — /team will not work');
435
- }
436
- 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)`;
437
395
  },
438
396
  };
439
397
 
440
398
  const CHECK_ORDER = [
441
- 'cline-cli-reachable',
442
- 'cline-json-exists',
443
- 'cline-json-parses',
444
- 'plugin-entry-present',
445
- 'plugin-path-resolves',
446
- 'plugin-runtime-deps',
447
- 'plugin-index-loadable',
448
- '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',
449
412
  'agent-files-installed',
450
- 'agent-yaml-format',
413
+ 'agent-frontmatter-format',
451
414
  'slash-commands-installed',
452
415
  'team-command-present',
453
416
  'test-command-present',
@@ -455,20 +418,20 @@ const CHECK_ORDER = [
455
418
  'skills-installed',
456
419
  'rules-installed',
457
420
  'hooks-installed',
458
- 'hooks-canonical-location',
459
- 'default-agent-set',
460
- 'instructions-loaded',
461
- 'provider-config',
462
- 'cline-settings-provider',
421
+ 'bizar-home-exists',
422
+ 'bizar-memory-vault-exists',
423
+ 'claude-md-mirrored',
424
+ 'plugin-runtime-deps',
463
425
  '9router-reachable',
464
- 'mistake-limit-floor',
465
426
  ];
466
427
 
467
428
  const LENIENT_CHECKS = new Set([
429
+ 'claude-cli-reachable', // Claude Code CLI is normally on $PATH only on dev hosts; CI containers without it shouldn't fail validation
468
430
  '9router-reachable',
469
- 'provider-config', // v6.2.2+ installer no longer touches provider config; user must configure
470
- 'cline-settings-provider', // v6.2.3warns about legacy/fake providerIds; non-blocking
471
- 'mistake-limit-floor', // v6.2.4warns about low mistake limit; non-blocking
431
+ 'plugin-runtime-deps', // best-effort probe via `npm root -g`
432
+ 'permissions-deny-dangerous', // advisoryuser may have intentionally customized
433
+ 'hooks-sessionend-wired', // advisorySessionEnd is optional
434
+ 'claude-settings-schema', // advisory — schema field is documentation
472
435
  ]);
473
436
 
474
437
  export function showValidateHelp() {
@@ -484,19 +447,20 @@ export function showValidateHelp() {
484
447
 
485
448
  Description:
486
449
  A 21-point health check that confirms the Bizar install is fully
487
- integrated with Cline:
488
- cline CLI reachable + version
489
- cline.json parses + plugin entry + path resolves
490
- plugin runtime deps (zod, @cline/sdk, @cline/core) wired
491
- plugin index.ts + enableAgentTeams plumbing
492
- all 14 agent files installed + Cline .yaml format
493
- • 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,
494
459
  /plan, /plow-through, /pr-review, /tailscale-serve,
495
460
  /visual-plan, /team, /test, /validate)
496
- • all skills / rules / hooks mirrored to ~/.cline/
497
- provider.9router (preferred) or provider.minimax (legacy)
461
+ • all skills / rules / hooks mirrored to ~/.claude/
462
+ ~/.bizar_home/ + memory vault ready
498
463
  • 9Router gateway reachable (lenient unless --strict)
499
- • default_agent + instructions[] in cline.json
500
464
 
501
465
  Exit codes:
502
466
  0 All checks passed (or only lenient ones failed)
@@ -505,7 +469,7 @@ export function showValidateHelp() {
505
469
 
506
470
  Related:
507
471
  bizar doctor Simpler 8-point check (legacy)
508
- bizar update Refresh the install (re-runs syncConfigExtras)
472
+ bizar update Refresh the install (re-runs the provisioner)
509
473
  bizar repair Fix common issues (stale symlinks, version drift)
510
474
  `);
511
475
  }
@@ -541,7 +505,7 @@ export async function runValidate(opts = {}) {
541
505
  for (const r of results) {
542
506
  const isLenient = LENIENT_CHECKS.has(r.name);
543
507
  const marker = r.ok ? chalk.green('✓') : (isLenient ? chalk.yellow('⚠') : chalk.red('✗'));
544
- const label = r.name.padEnd(28);
508
+ const label = r.name.padEnd(32);
545
509
  const msg = r.ok ? chalk.dim(` ${r.message}`) : (isLenient ? chalk.yellow(` ${r.message}`) : chalk.red(` ${r.message}`));
546
510
  console.log(` ${marker} ${label}${msg}`);
547
511
  }