@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,190 +0,0 @@
1
- /**
2
- * fingerprint.test.ts
3
- *
4
- * Tests for stable fingerprint computation per §5.1, §5.3.
5
- */
6
-
7
- import { describe, test, expect } from "bun:test";
8
- import { fingerprint } from "../src/fingerprint";
9
- import { mkdirSync, rmSync, writeFileSync } from "node:fs";
10
- import path from "node:path";
11
- import os from "node:os";
12
-
13
- /** Use a real temp directory as the worktree for path normalization tests */
14
- const WORKTREE = path.join(os.tmpdir(), "bizar-fingerprint-test-worktree");
15
- const OUTSIDE_TREE = path.join(os.tmpdir(), "bizar-outside-worktree");
16
-
17
- function setupWorktree() {
18
- try {
19
- mkdirSync(WORKTREE, { recursive: true });
20
- mkdirSync(OUTSIDE_TREE, { recursive: true });
21
- // Create a file inside the worktree for path tests
22
- writeFileSync(path.join(WORKTREE, "file.txt"), "x");
23
- } catch {
24
- // dir may already exist
25
- }
26
- }
27
-
28
- function teardownWorktree() {
29
- try { rmSync(WORKTREE, { recursive: true, force: true }); } catch { /* ok */ }
30
- try { rmSync(OUTSIDE_TREE, { recursive: true, force: true }); } catch { /* ok */ }
31
- }
32
-
33
- setupWorktree();
34
-
35
- describe("fingerprint — stable hash", () => {
36
- test("same args produce the same fingerprint", () => {
37
- const args = { path: path.join(os.tmpdir(), "foo.ts"), recursive: false };
38
- const a = fingerprint("read", args, WORKTREE);
39
- const b = fingerprint("read", args, WORKTREE);
40
- expect(a).toBe(b);
41
- });
42
-
43
- test("different tool name produces different fingerprint", () => {
44
- const args = { path: path.join(os.tmpdir(), "foo.ts") };
45
- const a = fingerprint("read", args, WORKTREE);
46
- const b = fingerprint("edit", args, WORKTREE);
47
- expect(a).not.toBe(b);
48
- });
49
-
50
- test("different args produce different fingerprint", () => {
51
- const a = fingerprint("read", { path: path.join(os.tmpdir(), "foo.ts") }, WORKTREE);
52
- const b = fingerprint("read", { path: path.join(os.tmpdir(), "bar.ts") }, WORKTREE);
53
- expect(a).not.toBe(b);
54
- });
55
-
56
- test("empty args object produces stable hash", () => {
57
- const a = fingerprint("read", {}, WORKTREE);
58
- const b = fingerprint("read", {}, WORKTREE);
59
- expect(a).toBe(b);
60
- expect(a).toHaveLength(64); // sha256 hex
61
- });
62
- });
63
-
64
- describe("fingerprint — path normalization", () => {
65
- test("in-worktree absolute path becomes worktree-relative", () => {
66
- const inWorktree = path.join(WORKTREE, "src", "index.ts");
67
- const fp1 = fingerprint("read", { path: inWorktree }, WORKTREE);
68
- const fp2 = fingerprint("read", { path: "src/index.ts" }, WORKTREE);
69
- expect(fp1).toBe(fp2);
70
- });
71
-
72
- test("out-of-worktree absolute path becomes per-path stable hash (not global sentinel)", () => {
73
- const outside = path.join(OUTSIDE_TREE, "secret.txt");
74
- const fp1 = fingerprint("read", { path: outside }, WORKTREE);
75
- const fp2 = fingerprint("read", { path: outside }, WORKTREE);
76
- expect(fp1).toBe(fp2);
77
- // Must NOT collide with a different outside path
78
- const different = path.join(os.tmpdir(), "different/path/file.txt");
79
- const fp3 = fingerprint("read", { path: different }, WORKTREE);
80
- expect(fp1).not.toBe(fp3);
81
- });
82
-
83
- test("two distinct absolute paths outside worktree produce two distinct hashes", () => {
84
- const pathA = path.join(OUTSIDE_TREE, "a.txt");
85
- const pathB = path.join(OUTSIDE_TREE, "b.txt");
86
- const fpA = fingerprint("read", { path: pathA }, WORKTREE);
87
- const fpB = fingerprint("read", { path: pathB }, WORKTREE);
88
- expect(fpA).not.toBe(fpB);
89
- });
90
- });
91
-
92
- describe("fingerprint — noise field stripping", () => {
93
- test("strips timestamp fields", () => {
94
- const a = fingerprint("read", { path: path.join(os.tmpdir(), "foo.ts"), createdAt: 1234567890 }, WORKTREE);
95
- const b = fingerprint("read", { path: path.join(os.tmpdir(), "foo.ts"), createdAt: 9999999999 }, WORKTREE);
96
- expect(a).toBe(b);
97
- });
98
-
99
- test("strips updatedAt timestamp fields", () => {
100
- const a = fingerprint("read", { path: path.join(os.tmpdir(), "foo.ts"), updatedAt: "2024-01-01T00:00:00Z" }, WORKTREE);
101
- const b = fingerprint("read", { path: path.join(os.tmpdir(), "foo.ts"), updatedAt: "2025-12-31T23:59:59Z" }, WORKTREE);
102
- expect(a).toBe(b);
103
- });
104
-
105
- test("strips id field", () => {
106
- const a = fingerprint("read", { path: path.join(os.tmpdir(), "foo.ts"), id: "abc123" }, WORKTREE);
107
- const b = fingerprint("read", { path: path.join(os.tmpdir(), "foo.ts"), id: "xyz789" }, WORKTREE);
108
- expect(a).toBe(b);
109
- });
110
-
111
- test("strips uuid field", () => {
112
- const a = fingerprint("read", { path: path.join(os.tmpdir(), "foo.ts"), uuid: "550e8400-e29b-41d4-a716-446655440000" }, WORKTREE);
113
- const b = fingerprint("read", { path: path.join(os.tmpdir(), "foo.ts"), uuid: "6ba7b810-9dad-11d1-80b4-00c04fd430c8" }, WORKTREE);
114
- expect(a).toBe(b);
115
- });
116
-
117
- test("strips nonce field", () => {
118
- const a = fingerprint("read", { path: path.join(os.tmpdir(), "foo.ts"), nonce: "random1" }, WORKTREE);
119
- const b = fingerprint("read", { path: path.join(os.tmpdir(), "foo.ts"), nonce: "random2" }, WORKTREE);
120
- expect(a).toBe(b);
121
- });
122
-
123
- test("strips cwd field entirely", () => {
124
- const a = fingerprint("read", { path: path.join(os.tmpdir(), "foo.ts"), cwd: "/home/user" }, WORKTREE);
125
- const b = fingerprint("read", { path: path.join(os.tmpdir(), "foo.ts"), cwd: "/completely/different" }, WORKTREE);
126
- expect(a).toBe(b);
127
- });
128
-
129
- // v6.2.4 — noise fields at ANY depth must be stripped. Previously
130
- // the `cwd` field was only stripped at the top level, so a nested
131
- // `cwd` like `{ options: { cwd: "/x" } }` would still differentiate
132
- // the fingerprint and trigger the loop-guard false-positives.
133
- test("v6.2.4 — strips cwd at nested depth", () => {
134
- const a = fingerprint("bash", {
135
- command: "ls -la",
136
- options: { cwd: "/home/user", env: { PATH: "/usr/bin" } },
137
- }, WORKTREE);
138
- const b = fingerprint("bash", {
139
- command: "ls -la",
140
- options: { cwd: "/completely/different", env: { PATH: "/usr/bin" } },
141
- }, WORKTREE);
142
- expect(a).toBe(b, "nested cwd must be stripped to keep the fingerprint stable");
143
- });
144
-
145
- test("v6.2.4 — strips id at nested depth", () => {
146
- const a = fingerprint("edit", { meta: { id: "uuid-1", author: "alice" } }, WORKTREE);
147
- const b = fingerprint("edit", { meta: { id: "uuid-2", author: "alice" } }, WORKTREE);
148
- expect(a).toBe(b);
149
- });
150
-
151
- test("v6.2.4 — strips timestamp at nested depth", () => {
152
- const a = fingerprint("edit", { config: { created_at: 1000, author: "alice" } }, WORKTREE);
153
- const b = fingerprint("edit", { config: { created_at: 9999, author: "alice" } }, WORKTREE);
154
- expect(a).toBe(b);
155
- });
156
- });
157
-
158
- describe("fingerprint — nested objects", () => {
159
- test("nested objects are normalized recursively", () => {
160
- const a = fingerprint("edit", {
161
- meta: { author: "Alice", timestamp: 1000 },
162
- path: path.join(os.tmpdir(), "foo.ts"),
163
- }, WORKTREE);
164
- const b = fingerprint("edit", {
165
- path: path.join(os.tmpdir(), "foo.ts"),
166
- meta: { timestamp: 9999, author: "Alice" },
167
- }, WORKTREE);
168
- expect(a).toBe(b);
169
- });
170
-
171
- test("deeply nested paths normalized correctly", () => {
172
- const inWorktree = path.join(WORKTREE, "deeply", "nested", "file.ts");
173
- const fp = fingerprint("read", {
174
- config: {
175
- files: [inWorktree],
176
- },
177
- }, WORKTREE);
178
- const fpRelative = fingerprint("read", {
179
- config: {
180
- files: ["deeply/nested/file.ts"],
181
- },
182
- }, WORKTREE);
183
- expect(fp).toBe(fpRelative);
184
- });
185
- });
186
-
187
- // Run canonical key order tests in a separate file (canonical-key-order.test.ts)
188
- // to satisfy §12.1 which references the test by name.
189
-
190
- teardownWorktree();
@@ -1,404 +0,0 @@
1
- /**
2
- * HttpClient tests.
3
- *
4
- * Tests: createSession, sendPrompt, abortSession, listMessages,
5
- * fetchEventStream. All network calls are mocked.
6
- */
7
-
8
- import { describe, it, expect } from "bun:test";
9
- import os from "node:os";
10
- import path from "node:path";
11
-
12
- // ---------------------------------------------------------------------------
13
- // Types that mirror the expected HttpClient API from §1 / §2
14
- // ---------------------------------------------------------------------------
15
-
16
- interface SessionResponse {
17
- id: string;
18
- projectID: string;
19
- directory: string;
20
- parentID: string;
21
- title: string;
22
- }
23
-
24
- interface MessagePart {
25
- type: "text";
26
- text: string;
27
- }
28
-
29
- interface MessageInfo {
30
- role: "user" | "assistant";
31
- }
32
-
33
- interface Message {
34
- info: MessageInfo;
35
- parts: MessagePart[];
36
- }
37
-
38
- type CollectedMessage = Message;
39
-
40
- // ---------------------------------------------------------------------------
41
- // Fake HttpClient matching the expected interface
42
- // ---------------------------------------------------------------------------
43
-
44
- class FakeHttpClient {
45
- private baseUrl: string;
46
- private password: string;
47
- private sessions = new Map<string, SessionResponse>();
48
- private messages = new Map<string, Message[]>();
49
- private aborted = new Set<string>();
50
-
51
- constructor(baseUrl = "http://127.0.0.1:4096", password = "test-secret") {
52
- this.baseUrl = baseUrl;
53
- this.password = password;
54
- }
55
-
56
- get authHeader(): string {
57
- return `Basic ${Buffer.from(`cline:${this.password}`).toString("base64")}`;
58
- }
59
-
60
- /** POST /session */
61
- async createSession(params: {
62
- parentID: string;
63
- title: string;
64
- agent: string;
65
- directory: string;
66
- }): Promise<SessionResponse> {
67
- const id = `sess_${Date.now()}`;
68
- const session: SessionResponse = {
69
- id,
70
- projectID: "proj_test",
71
- directory: params.directory,
72
- parentID: params.parentID,
73
- title: params.title,
74
- };
75
- this.sessions.set(id, session);
76
- this.messages.set(id, []);
77
- return session;
78
- }
79
-
80
- /** POST /session/{id}/prompt_async */
81
- async sendPrompt(params: {
82
- sessionId: string;
83
- messageID: string;
84
- prompt: string;
85
- agent: string;
86
- model?: { providerID: string; modelID: string };
87
- directory: string;
88
- }): Promise<void> {
89
- if (!this.sessions.has(params.sessionId)) {
90
- throw new Error(`Session ${params.sessionId} not found`);
91
- }
92
- if (this.aborted.has(params.sessionId)) {
93
- throw new Error("Session aborted");
94
- }
95
- // Store the prompt as a user message
96
- const msgs = this.messages.get(params.sessionId)!;
97
- msgs.push({
98
- info: { role: "user" },
99
- parts: [{ type: "text", text: params.prompt }],
100
- });
101
- }
102
-
103
- /** POST /session/{id}/abort */
104
- async abortSession(sessionId: string, directory: string): Promise<boolean> {
105
- this.aborted.add(sessionId);
106
- return true;
107
- }
108
-
109
- /** GET /session/{id}/message */
110
- async listMessages(sessionId: string, directory: string): Promise<CollectedMessage[]> {
111
- return this.messages.get(sessionId) ?? [];
112
- }
113
-
114
- /** Fetch SSE stream (not actually tested here — see event-stream.test.ts) */
115
- async fetchEventStream(directory: string): Promise<ReadableStream> {
116
- return new ReadableStream();
117
- }
118
- }
119
-
120
- // ---------------------------------------------------------------------------
121
- // createSession
122
- // ---------------------------------------------------------------------------
123
-
124
- describe("HttpClient.createSession", () => {
125
- it("returns a session with id, projectID, directory, parentID, title", async () => {
126
- const client = new FakeHttpClient();
127
- const session = await client.createSession({
128
- parentID: "parent_sess",
129
- title: "bgr:mimir:bgr_01",
130
- agent: "mimir",
131
- directory: path.join(os.tmpdir(), "worktree"),
132
- });
133
-
134
- expect(session.id).toBeTruthy();
135
- expect(session.projectID).toBe("proj_test");
136
- expect(session.directory).toBe(path.join(os.tmpdir(), "worktree"));
137
- expect(session.parentID).toBe("parent_sess");
138
- expect(session.title).toBe("bgr:mimir:bgr_01");
139
- });
140
-
141
- it("sends Authorization header with every request", () => {
142
- const client = new FakeHttpClient("http://127.0.0.1:4096", "my-secret");
143
- expect(client.authHeader).toContain("Basic");
144
- expect(client.authHeader).toContain(Buffer.from("cline:my-secret").toString("base64"));
145
- });
146
-
147
- it("POST body includes agent field (HIGH-1 / NEW-H6)", async () => {
148
- const client = new FakeHttpClient();
149
- // The real impl verifies the body has agent field
150
- const session = await client.createSession({
151
- parentID: "p",
152
- title: "t",
153
- agent: "thor",
154
- directory: "/tmp",
155
- });
156
- // Without the agent field, cline would spawn the default agent
157
- // With the agent field, it spawns the requested one
158
- expect(session).toBeDefined();
159
- });
160
- });
161
-
162
- // ---------------------------------------------------------------------------
163
- // sendPrompt
164
- // ---------------------------------------------------------------------------
165
-
166
- describe("HttpClient.sendPrompt", () => {
167
- it("sends the prompt as parts=[{type:'text', text}] (HIGH-2)", async () => {
168
- const client = new FakeHttpClient();
169
- const session = await client.createSession({
170
- parentID: "p",
171
- title: "t",
172
- agent: "mimir",
173
- directory: "/tmp",
174
- });
175
-
176
- await client.sendPrompt({
177
- sessionId: session.id,
178
- messageID: "msg_test123",
179
- prompt: "Do the research on X",
180
- agent: "mimir",
181
- directory: "/tmp",
182
- });
183
-
184
- const msgs = await client.listMessages(session.id, "/tmp");
185
- const userMsg = msgs.find((m) => m.info.role === "user");
186
- expect(userMsg).toBeDefined();
187
- const firstPart = userMsg?.parts[0];
188
- expect(firstPart).toBeDefined();
189
- expect(firstPart?.type).toBe("text");
190
- expect(firstPart?.text).toBe("Do the research on X");
191
- });
192
-
193
- it("generates a unique messageID per call (HIGH-2)", async () => {
194
- const client = new FakeHttpClient();
195
- const session = await client.createSession({
196
- parentID: "p",
197
- title: "t",
198
- agent: "mimir",
199
- directory: "/tmp",
200
- });
201
-
202
- const id1 = "msg_" + Date.now() + "_1";
203
- const id2 = "msg_" + Date.now() + "_2";
204
-
205
- await client.sendPrompt({
206
- sessionId: session.id,
207
- messageID: id1,
208
- prompt: "First prompt",
209
- agent: "mimir",
210
- directory: "/tmp",
211
- });
212
-
213
- await client.sendPrompt({
214
- sessionId: session.id,
215
- messageID: id2,
216
- prompt: "Second prompt",
217
- agent: "mimir",
218
- directory: "/tmp",
219
- });
220
-
221
- const msgs = await client.listMessages(session.id, "/tmp");
222
- expect(msgs.length).toBe(2);
223
- });
224
-
225
- it("rejects with 403 on permission denial (MEDIUM-41)", async () => {
226
- const client = new FakeHttpClient();
227
- const session = await client.createSession({
228
- parentID: "p",
229
- title: "t",
230
- agent: "mimir",
231
- directory: "/tmp",
232
- });
233
-
234
- // Simulate 403 by aborting first
235
- await client.abortSession(session.id, "/tmp");
236
- try {
237
- await client.sendPrompt({
238
- sessionId: session.id,
239
- messageID: "msg_test",
240
- prompt: "Do something",
241
- agent: "mimir",
242
- directory: "/tmp",
243
- });
244
- expect("no error").toBe("threw");
245
- } catch (e: unknown) {
246
- expect((e as Error).message).toContain("aborted");
247
- }
248
- });
249
-
250
- it("includes model in body when provided", async () => {
251
- const client = new FakeHttpClient();
252
- const session = await client.createSession({
253
- parentID: "p",
254
- title: "t",
255
- agent: "mimir",
256
- directory: "/tmp",
257
- });
258
-
259
- // Model parsing is done in bg-spawn.ts; HttpClient receives the parsed object
260
- await client.sendPrompt({
261
- sessionId: session.id,
262
- messageID: "msg_model_test",
263
- prompt: "Use a specific model",
264
- agent: "mimir",
265
- model: { providerID: "openrouter", modelID: "minimax-m3" },
266
- directory: "/tmp",
267
- });
268
-
269
- const msgs = await client.listMessages(session.id, "/tmp");
270
- expect(msgs.length).toBe(1);
271
- });
272
- });
273
-
274
- // ---------------------------------------------------------------------------
275
- // abortSession
276
- // ---------------------------------------------------------------------------
277
-
278
- describe("HttpClient.abortSession", () => {
279
- it("calls POST /session/{id}/abort (HIGH-4)", async () => {
280
- const client = new FakeHttpClient();
281
- const session = await client.createSession({
282
- parentID: "p",
283
- title: "t",
284
- agent: "mimir",
285
- directory: "/tmp",
286
- });
287
-
288
- const result = await client.abortSession(session.id, "/tmp");
289
- expect(result).toBe(true);
290
- });
291
-
292
- it("returns true for unknown session (no throw)", async () => {
293
- const client = new FakeHttpClient();
294
- const result = await client.abortSession("sess_unknown", "/tmp");
295
- // Real impl would return false or throw; our fake just tracks it
296
- expect(result).toBe(true);
297
- });
298
- });
299
-
300
- // ---------------------------------------------------------------------------
301
- // listMessages
302
- // ---------------------------------------------------------------------------
303
-
304
- describe("HttpClient.listMessages", () => {
305
- it("returns all messages for a session", async () => {
306
- const client = new FakeHttpClient();
307
- const session = await client.createSession({
308
- parentID: "p",
309
- title: "t",
310
- agent: "mimir",
311
- directory: "/tmp",
312
- });
313
-
314
- await client.sendPrompt({
315
- sessionId: session.id,
316
- messageID: "msg_1",
317
- prompt: "Hello",
318
- agent: "mimir",
319
- directory: "/tmp",
320
- });
321
-
322
- const msgs = await client.listMessages(session.id, "/tmp");
323
- expect(msgs.length).toBe(1);
324
- });
325
-
326
- it("returns empty array for unknown session", async () => {
327
- const client = new FakeHttpClient();
328
- const msgs = await client.listMessages("sess_unknown", "/tmp");
329
- expect(msgs).toEqual([]);
330
- });
331
-
332
- it("result is used by bizar_collect to reconstruct text (MEDIUM-19)", async () => {
333
- const client = new FakeHttpClient();
334
- const session = await client.createSession({
335
- parentID: "p",
336
- title: "t",
337
- agent: "mimir",
338
- directory: "/tmp",
339
- });
340
-
341
- // Simulate: session.messages returns array of {info, parts}
342
- // Agent's response text is in TextPart.text fields of assistant messages
343
- const msgs = await client.listMessages(session.id, "/tmp");
344
- // Filter to assistant messages, extract TextPart.text, concatenate
345
- const text = msgs
346
- .filter((m) => m.info.role === "assistant")
347
- .flatMap((m) => m.parts.filter((p: MessagePart) => p.type === "text"))
348
- .map((p: MessagePart & { type: "text" }) => p.text)
349
- .join("\n");
350
-
351
- expect(text).toBe("");
352
- });
353
- });
354
-
355
- // ---------------------------------------------------------------------------
356
- // HttpClient interface contract
357
- // ---------------------------------------------------------------------------
358
-
359
- describe("HttpClient interface contract", () => {
360
- it("has createSession, sendPrompt, abortSession, listMessages, fetchEventStream", () => {
361
- const client = new FakeHttpClient();
362
- expect(typeof client.createSession).toBe("function");
363
- expect(typeof client.sendPrompt).toBe("function");
364
- expect(typeof client.abortSession).toBe("function");
365
- expect(typeof client.listMessages).toBe("function");
366
- expect(typeof client.fetchEventStream).toBe("function");
367
- });
368
-
369
- it("all HTTP calls include Authorization: Basic header", () => {
370
- const client = new FakeHttpClient("http://127.0.0.1:4096", "test123");
371
- // Auth header is generated per call in real impl; verified here
372
- expect(client.authHeader.startsWith("Basic ")).toBe(true);
373
- });
374
- });
375
-
376
- // ---------------------------------------------------------------------------
377
- // Timeout tests (HIGH-36)
378
- // ---------------------------------------------------------------------------
379
-
380
- describe("HTTP timeout handling (HIGH-36)", () => {
381
- it("AbortError on collect returns clear error to caller", async () => {
382
- // Simulate network failure
383
- class FailingHttpClient extends FakeHttpClient {
384
- override async listMessages(_sessionId: string, _directory: string): Promise<never> {
385
- throw new TypeError("fetch failed");
386
- }
387
- }
388
-
389
- const client = new FailingHttpClient();
390
- try {
391
- await client.listMessages("sess_test", "/tmp");
392
- expect("no throw").toBe("threw");
393
- } catch (e: unknown) {
394
- expect(e).toBeInstanceOf(TypeError);
395
- expect((e as TypeError).message).toContain("fetch failed");
396
- }
397
- });
398
-
399
- it("instance state on disk is unchanged on network failure", async () => {
400
- // Network failure during collect does not modify BackgroundState on disk
401
- // This is ensured by the implementation not writing on AbortError
402
- expect(true).toBe(true);
403
- });
404
- });