@polderlabs/bizar 6.2.5 → 7.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (540) hide show
  1. package/.claude/CLAUDE.md +15 -0
  2. package/.claude/agents/_shared/AGENT_BASELINE.md +168 -0
  3. package/.claude/agents/_shared/CLAUDE_TOOLS.md +412 -0
  4. package/.claude/agents/_shared/SKILLS.md +109 -0
  5. package/.claude/agents/agent-browser.md +80 -0
  6. package/.claude/agents/baldr.md +49 -0
  7. package/.claude/agents/forseti.md +51 -0
  8. package/.claude/agents/frigg.md +42 -0
  9. package/.claude/agents/heimdall.md +33 -0
  10. package/.claude/agents/hermod.md +53 -0
  11. package/.claude/agents/mimir.md +49 -0
  12. package/.claude/agents/odin.md +287 -0
  13. package/.claude/agents/quick.md +34 -0
  14. package/.claude/agents/semble-search.md +50 -0
  15. package/.claude/agents/thor.md +53 -0
  16. package/.claude/agents/tyr.md +56 -0
  17. package/.claude/agents/vidarr.md +54 -0
  18. package/.claude/agents/vor.md +53 -0
  19. package/.claude/commands/audit.md +25 -0
  20. package/.claude/commands/bizar.md +22 -0
  21. package/.claude/commands/explain.md +17 -0
  22. package/.claude/commands/init.md +29 -0
  23. package/.claude/commands/learn.md +44 -0
  24. package/.claude/commands/plan.md +35 -0
  25. package/.claude/commands/plow-through.md +50 -0
  26. package/.claude/commands/pr-review.md +49 -0
  27. package/.claude/commands/setup-provider.md +96 -0
  28. package/.claude/commands/tailscale-serve.md +100 -0
  29. package/.claude/commands/team.md +132 -0
  30. package/.claude/commands/test.md +62 -0
  31. package/.claude/commands/validate.md +68 -0
  32. package/.claude/commands/visual-plan.md +24 -0
  33. package/.claude/hooks/README.md +92 -0
  34. package/.claude/hooks/posttooluse-editwrite.mjs +91 -0
  35. package/.claude/hooks/pretooluse-bash.mjs +81 -0
  36. package/.claude/hooks/pretooluse-editwrite.mjs +139 -0
  37. package/.claude/hooks/sessionend-recall.mjs +74 -0
  38. package/.claude/hooks/sessionstart-prime.mjs +80 -0
  39. package/.claude/hooks/userpromptsubmit-tag.mjs +80 -0
  40. package/.claude/hooks/worker-suggest.mjs +110 -0
  41. package/.claude/settings.json +125 -0
  42. package/.claude/skills/9router/SKILL.md +80 -0
  43. package/.claude/skills/9router-chat/SKILL.md +73 -0
  44. package/.claude/skills/9router-embeddings/SKILL.md +69 -0
  45. package/.claude/skills/9router-image/SKILL.md +86 -0
  46. package/.claude/skills/9router-stt/SKILL.md +79 -0
  47. package/.claude/skills/9router-tts/SKILL.md +80 -0
  48. package/.claude/skills/9router-web-fetch/SKILL.md +99 -0
  49. package/.claude/skills/9router-web-search/SKILL.md +91 -0
  50. package/.claude/skills/bizar/README.md +9 -0
  51. package/.claude/skills/bizar/SKILL.md +450 -0
  52. package/.claude/skills/cpp-coding-standards/README.md +28 -0
  53. package/.claude/skills/cpp-coding-standards/SKILL.md +634 -0
  54. package/.claude/skills/cpp-coding-standards/references/concurrency.md +320 -0
  55. package/.claude/skills/cpp-coding-standards/references/error-handling.md +229 -0
  56. package/.claude/skills/cpp-coding-standards/references/memory-safety.md +216 -0
  57. package/.claude/skills/cpp-coding-standards/references/modern-idioms.md +282 -0
  58. package/.claude/skills/cpp-coding-standards/references/review-checklist.md +96 -0
  59. package/.claude/skills/cpp-testing/README.md +28 -0
  60. package/.claude/skills/cpp-testing/SKILL.md +304 -0
  61. package/.claude/skills/cpp-testing/references/coverage.md +370 -0
  62. package/.claude/skills/cpp-testing/references/framework-compare.md +175 -0
  63. package/.claude/skills/cpp-testing/references/host-test-for-embedded.md +499 -0
  64. package/.claude/skills/cpp-testing/references/mocking.md +364 -0
  65. package/.claude/skills/cpp-testing/references/tdd-workflow.md +308 -0
  66. package/.claude/skills/cubesandbox/SKILL.md +148 -0
  67. package/.claude/skills/embedded-esp-idf/README.md +41 -0
  68. package/.claude/skills/embedded-esp-idf/SKILL.md +439 -0
  69. package/.claude/skills/embedded-esp-idf/references/freertos-patterns.md +214 -0
  70. package/.claude/skills/embedded-esp-idf/references/host-tests.md +164 -0
  71. package/.claude/skills/embedded-esp-idf/references/idf-py-commands.md +157 -0
  72. package/.claude/skills/embedded-esp-idf/references/kconfig.md +159 -0
  73. package/.claude/skills/embedded-esp-idf/references/logging-discipline.md +118 -0
  74. package/.claude/skills/embedded-esp-idf/references/memory-and-iram.md +137 -0
  75. package/.claude/skills/embedded-esp-idf/references/nvs.md +121 -0
  76. package/.claude/skills/embedded-esp-idf/references/packed-structs.md +192 -0
  77. package/.claude/skills/embedded-esp-idf/scripts/idf_env.sh +47 -0
  78. package/.claude/skills/embedded-esp-idf/scripts/size_check.sh +77 -0
  79. package/.claude/skills/glyph/SKILL.md +163 -0
  80. package/.claude/skills/harness-engineering/SKILL.md +143 -0
  81. package/.claude/skills/lightrag/SKILL.md +81 -0
  82. package/.claude/skills/memory-protocol/SKILL.md +105 -0
  83. package/.claude/skills/obsidian/SKILL.md +306 -0
  84. package/.claude/skills/read-the-damn-docs/SKILL.md +113 -0
  85. package/.claude/skills/self-improvement/SKILL.md +64 -0
  86. package/README.md +87 -59
  87. package/bizar-dash/dist/assets/{EnvVarsSection-DXM8gRm_.js → EnvVarsSection-CW6fWKds.js} +3 -3
  88. package/bizar-dash/dist/assets/{EnvVarsSection-DXM8gRm_.js.map → EnvVarsSection-CW6fWKds.js.map} +1 -1
  89. package/bizar-dash/dist/assets/MobileChat-D7zRhU9K.js +1 -0
  90. package/bizar-dash/dist/assets/{MobileChat-BnKN_Ks_.js.map → MobileChat-D7zRhU9K.js.map} +1 -1
  91. package/bizar-dash/dist/assets/MobileSettings-K-sNsn_r.js +1 -0
  92. package/bizar-dash/dist/assets/{MobileSettings-DjCPxC-Q.js.map → MobileSettings-K-sNsn_r.js.map} +1 -1
  93. package/bizar-dash/dist/assets/{Toast-Cpl6-E63.js → Toast-WTxc3m2g.js} +1 -1
  94. package/bizar-dash/dist/assets/{Toast-Cpl6-E63.js.map → Toast-WTxc3m2g.js.map} +1 -1
  95. package/bizar-dash/dist/assets/flow-BpU0-gK2.js +1 -0
  96. package/bizar-dash/dist/assets/flow-BpU0-gK2.js.map +1 -0
  97. package/bizar-dash/dist/assets/fuzzy-l0sNRNKZ.js +1 -0
  98. package/bizar-dash/dist/assets/fuzzy-l0sNRNKZ.js.map +1 -0
  99. package/bizar-dash/dist/assets/{icons-Do5N2jmX.js → icons-B0AKnYI3.js} +98 -103
  100. package/bizar-dash/dist/assets/icons-B0AKnYI3.js.map +1 -0
  101. package/bizar-dash/dist/assets/main-C-Md3DaY.css +1 -0
  102. package/bizar-dash/dist/assets/main-CO8fIxQK.js +18 -0
  103. package/bizar-dash/dist/assets/main-CO8fIxQK.js.map +1 -0
  104. package/bizar-dash/dist/assets/markdown-w2bDDkAH.js +1 -0
  105. package/bizar-dash/dist/assets/{markdown-C6mXtQxD.js.map → markdown-w2bDDkAH.js.map} +1 -1
  106. package/bizar-dash/dist/assets/mobile-DXYCA0hC.js +1 -0
  107. package/bizar-dash/dist/assets/{mobile-CMHqtLV2.js.map → mobile-DXYCA0hC.js.map} +1 -1
  108. package/bizar-dash/dist/assets/mobile-layout-DSmtNPja.js +2 -0
  109. package/bizar-dash/dist/assets/mobile-layout-DSmtNPja.js.map +1 -0
  110. package/bizar-dash/dist/assets/react-vendor-BnuhLJ6X.css +1 -0
  111. package/bizar-dash/dist/assets/react-vendor-D3pra6w-.js +46 -0
  112. package/bizar-dash/dist/assets/react-vendor-D3pra6w-.js.map +1 -0
  113. package/bizar-dash/dist/assets/useSlashCommands-3DFLOfpk.js +2 -0
  114. package/bizar-dash/dist/assets/useSlashCommands-3DFLOfpk.js.map +1 -0
  115. package/bizar-dash/dist/assets/vendor-Di7Cp-rw.js +45 -0
  116. package/bizar-dash/dist/assets/vendor-Di7Cp-rw.js.map +1 -0
  117. package/bizar-dash/dist/index.html +12 -10
  118. package/bizar-dash/dist/mobile.html +7 -4
  119. package/bizar-dash/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
  120. package/bizar-dash/src/server/api.mjs +15 -4
  121. package/bizar-dash/src/server/background-store.mjs +15 -16
  122. package/bizar-dash/src/server/bg-poller.mjs +25 -35
  123. package/bizar-dash/src/server/bg-retry.mjs +66 -194
  124. package/bizar-dash/src/server/claude-bg-spawner.mjs +390 -0
  125. package/bizar-dash/src/server/claude-info.mjs +412 -0
  126. package/bizar-dash/src/server/{cline-runner.mjs → claude-runner.mjs} +53 -48
  127. package/bizar-dash/src/server/claude-sdk.mjs +191 -0
  128. package/bizar-dash/src/server/memory-consolidator.mjs +218 -0
  129. package/bizar-dash/src/server/memory-distillation.mjs +296 -0
  130. package/bizar-dash/src/server/providers-store.mjs +22 -49
  131. package/bizar-dash/src/server/routes/background.mjs +24 -20
  132. package/bizar-dash/src/server/routes/chat.mjs +223 -326
  133. package/bizar-dash/src/server/routes/claude-session-detail.mjs +329 -0
  134. package/bizar-dash/src/server/routes/claude-sessions.mjs +259 -0
  135. package/bizar-dash/src/server/routes/distill.mjs +129 -0
  136. package/bizar-dash/src/server/routes/goal-planner.mjs +236 -0
  137. package/bizar-dash/src/server/routes/tasks.mjs +20 -28
  138. package/bizar-dash/src/server/task-delegator.mjs +76 -77
  139. package/bizar-dash/src/web/App.tsx +4 -0
  140. package/bizar-dash/src/web/components/Tag.tsx +18 -5
  141. package/bizar-dash/src/web/components/Topbar.tsx +3 -0
  142. package/bizar-dash/src/web/components/agents/CommunicationLog.tsx +126 -0
  143. package/bizar-dash/src/web/components/agents/DependencyGraph.tsx +163 -0
  144. package/bizar-dash/src/web/components/agents/QualityGates.tsx +123 -0
  145. package/bizar-dash/src/web/components/agents/RealTimeEventLog.tsx +127 -0
  146. package/bizar-dash/src/web/components/agents/RoutingDecisions.test.tsx +148 -0
  147. package/bizar-dash/src/web/components/agents/RoutingDecisions.tsx +160 -0
  148. package/bizar-dash/src/web/components/chat/useChat.ts +23 -27
  149. package/bizar-dash/src/web/components/goals/GoalInput.tsx +86 -0
  150. package/bizar-dash/src/web/components/goals/PlanVisualization.tsx +111 -0
  151. package/bizar-dash/src/web/lib/goapPlanner.ts +614 -0
  152. package/bizar-dash/src/web/lib/types.ts +25 -0
  153. package/bizar-dash/src/web/styles/agents-redesign.css +311 -0
  154. package/bizar-dash/src/web/styles/main.css +251 -0
  155. package/bizar-dash/src/web/styles/tasks-redesign.css +231 -0
  156. package/bizar-dash/src/web/ui/controls/Button.tsx +77 -0
  157. package/bizar-dash/src/web/ui/controls/Checkbox.tsx +95 -0
  158. package/bizar-dash/src/web/ui/controls/IconButton.tsx +66 -0
  159. package/bizar-dash/src/web/ui/controls/Kbd.tsx +24 -0
  160. package/bizar-dash/src/web/ui/controls/NumberInput.tsx +77 -0
  161. package/bizar-dash/src/web/ui/controls/RadioGroup.tsx +109 -0
  162. package/bizar-dash/src/web/ui/controls/SearchInput.tsx +91 -0
  163. package/bizar-dash/src/web/ui/controls/Select.tsx +92 -0
  164. package/bizar-dash/src/web/ui/controls/Slider.tsx +70 -0
  165. package/bizar-dash/src/web/ui/controls/TextInput.tsx +67 -0
  166. package/bizar-dash/src/web/ui/controls/Toggle.tsx +79 -0
  167. package/bizar-dash/src/web/ui/controls/controls.css +454 -0
  168. package/bizar-dash/src/web/ui/controls/index.ts +33 -0
  169. package/bizar-dash/src/web/ui/data/BarChart.tsx +60 -0
  170. package/bizar-dash/src/web/ui/data/DataTable.tsx +216 -0
  171. package/bizar-dash/src/web/ui/data/EmptyState.tsx +60 -0
  172. package/bizar-dash/src/web/ui/data/ErrorState.tsx +56 -0
  173. package/bizar-dash/src/web/ui/data/KeyValueList.tsx +106 -0
  174. package/bizar-dash/src/web/ui/data/LoadingState.tsx +65 -0
  175. package/bizar-dash/src/web/ui/data/Sparkline.tsx +87 -0
  176. package/bizar-dash/src/web/ui/data/StatTile.tsx +87 -0
  177. package/bizar-dash/src/web/ui/data/data.css +535 -0
  178. package/bizar-dash/src/web/ui/data/index.ts +31 -0
  179. package/bizar-dash/src/web/ui/feedback/Badge.tsx +49 -0
  180. package/bizar-dash/src/web/ui/feedback/Dialog.tsx +209 -0
  181. package/bizar-dash/src/web/ui/feedback/ProgressBar.tsx +69 -0
  182. package/bizar-dash/src/web/ui/feedback/StatusDot.tsx +50 -0
  183. package/bizar-dash/src/web/ui/feedback/Toast.tsx +200 -0
  184. package/bizar-dash/src/web/ui/feedback/Tooltip.tsx +126 -0
  185. package/bizar-dash/src/web/ui/feedback/feedback.css +314 -0
  186. package/bizar-dash/src/web/ui/feedback/index.ts +43 -0
  187. package/bizar-dash/src/web/ui/index.ts +56 -0
  188. package/bizar-dash/src/web/ui/layout/AppShell.tsx +51 -0
  189. package/bizar-dash/src/web/ui/layout/Breadcrumbs.tsx +97 -0
  190. package/bizar-dash/src/web/ui/layout/Panel.tsx +73 -0
  191. package/bizar-dash/src/web/ui/layout/PanelHeader.tsx +39 -0
  192. package/bizar-dash/src/web/ui/layout/Sidebar.tsx +131 -0
  193. package/bizar-dash/src/web/ui/layout/Tabs.tsx +133 -0
  194. package/bizar-dash/src/web/ui/layout/Topbar.tsx +42 -0
  195. package/bizar-dash/src/web/ui/layout/index.ts +33 -0
  196. package/bizar-dash/src/web/ui/layout/layout.css +413 -0
  197. package/bizar-dash/src/web/ui/navigation/CommandPalette.tsx +199 -0
  198. package/bizar-dash/src/web/ui/navigation/NavGroup.tsx +95 -0
  199. package/bizar-dash/src/web/ui/navigation/NavLink.tsx +93 -0
  200. package/bizar-dash/src/web/ui/navigation/index.ts +17 -0
  201. package/bizar-dash/src/web/ui/navigation/navigation.css +343 -0
  202. package/bizar-dash/src/web/ui/primitives/Box.tsx +91 -0
  203. package/bizar-dash/src/web/ui/primitives/Grid.tsx +49 -0
  204. package/bizar-dash/src/web/ui/primitives/Inline.tsx +55 -0
  205. package/bizar-dash/src/web/ui/primitives/Separator.tsx +46 -0
  206. package/bizar-dash/src/web/ui/primitives/Stack.tsx +54 -0
  207. package/bizar-dash/src/web/ui/primitives/VisuallyHidden.tsx +26 -0
  208. package/bizar-dash/src/web/ui/primitives/index.ts +23 -0
  209. package/bizar-dash/src/web/ui/primitives/primitives.css +183 -0
  210. package/bizar-dash/src/web/ui/styles/globals.css +86 -0
  211. package/bizar-dash/src/web/ui/styles/reset.css +125 -0
  212. package/bizar-dash/src/web/ui/styles/tokens.css +195 -0
  213. package/bizar-dash/src/web/ui/theme/ThemeProvider.tsx +142 -0
  214. package/bizar-dash/src/web/ui/theme/tokens.ts +131 -0
  215. package/bizar-dash/src/web/ui/theme/useTheme.ts +22 -0
  216. package/bizar-dash/src/web/ui/utils/cx.ts +42 -0
  217. package/bizar-dash/src/web/views/Agents.tsx +506 -266
  218. package/bizar-dash/src/web/views/Chat.tsx +8 -8
  219. package/bizar-dash/src/web/views/GoalPlanner.tsx +158 -0
  220. package/bizar-dash/src/web/views/Overview.tsx +996 -448
  221. package/bizar-dash/src/web/views/Tasks.tsx +277 -273
  222. package/bizar-dash/tests/communication-log.test.tsx +67 -0
  223. package/bizar-dash/tests/dep-graph.test.tsx +40 -0
  224. package/bizar-dash/tests/event-log.test.tsx +61 -0
  225. package/bizar-dash/tests/goal-input.test.tsx +72 -0
  226. package/bizar-dash/tests/goap-planner.test.ts +68 -0
  227. package/bizar-dash/tests/quality-gates.test.tsx +59 -0
  228. package/bizar-dash/tests/setup.ts +31 -1
  229. package/bizar-dash/tests/ui/controls/Button.test.tsx +50 -0
  230. package/bizar-dash/tests/ui/controls/Checkbox.test.tsx +44 -0
  231. package/bizar-dash/tests/ui/controls/IconButton.test.tsx +37 -0
  232. package/bizar-dash/tests/ui/controls/Kbd.test.tsx +39 -0
  233. package/bizar-dash/tests/ui/controls/NumberInput.test.tsx +56 -0
  234. package/bizar-dash/tests/ui/controls/RadioGroup.test.tsx +58 -0
  235. package/bizar-dash/tests/ui/controls/SearchInput.test.tsx +52 -0
  236. package/bizar-dash/tests/ui/controls/Select.test.tsx +66 -0
  237. package/bizar-dash/tests/ui/controls/Slider.test.tsx +41 -0
  238. package/bizar-dash/tests/ui/controls/TextInput.test.tsx +44 -0
  239. package/bizar-dash/tests/ui/controls/Toggle.test.tsx +39 -0
  240. package/bizar-dash/tests/ui/data/BarChart.test.tsx +55 -0
  241. package/bizar-dash/tests/ui/data/DataTable.test.tsx +112 -0
  242. package/bizar-dash/tests/ui/data/EmptyState.test.tsx +57 -0
  243. package/bizar-dash/tests/ui/data/ErrorState.test.tsx +47 -0
  244. package/bizar-dash/tests/ui/data/KeyValueList.test.tsx +59 -0
  245. package/bizar-dash/tests/ui/data/LoadingState.test.tsx +37 -0
  246. package/bizar-dash/tests/ui/data/Sparkline.test.tsx +56 -0
  247. package/bizar-dash/tests/ui/data/StatTile.test.tsx +69 -0
  248. package/bizar-dash/tests/ui/feedback/Badge.test.tsx +41 -0
  249. package/bizar-dash/tests/ui/feedback/Dialog.test.tsx +99 -0
  250. package/bizar-dash/tests/ui/feedback/ProgressBar.test.tsx +66 -0
  251. package/bizar-dash/tests/ui/feedback/StatusDot.test.tsx +41 -0
  252. package/bizar-dash/tests/ui/feedback/Toast.test.tsx +124 -0
  253. package/bizar-dash/tests/ui/feedback/Tooltip.test.tsx +102 -0
  254. package/bizar-dash/tests/ui/layout/AppShell.test.tsx +50 -0
  255. package/bizar-dash/tests/ui/layout/Breadcrumbs.test.tsx +85 -0
  256. package/bizar-dash/tests/ui/layout/Panel.test.tsx +52 -0
  257. package/bizar-dash/tests/ui/layout/PanelHeader.test.tsx +32 -0
  258. package/bizar-dash/tests/ui/layout/Sidebar.test.tsx +95 -0
  259. package/bizar-dash/tests/ui/layout/Tabs.test.tsx +87 -0
  260. package/bizar-dash/tests/ui/layout/Topbar.test.tsx +41 -0
  261. package/bizar-dash/tests/ui/navigation/CommandPalette.test.tsx +105 -0
  262. package/bizar-dash/tests/ui/navigation/NavGroup.test.tsx +55 -0
  263. package/bizar-dash/tests/ui/navigation/NavLink.test.tsx +61 -0
  264. package/bizar-dash/tests/ui/primitives/Box.test.tsx +49 -0
  265. package/bizar-dash/tests/ui/primitives/Grid.test.tsx +37 -0
  266. package/bizar-dash/tests/ui/primitives/Inline.test.tsx +33 -0
  267. package/bizar-dash/tests/ui/primitives/Separator.test.tsx +34 -0
  268. package/bizar-dash/tests/ui/primitives/Stack.test.tsx +45 -0
  269. package/bizar-dash/tests/ui/primitives/VisuallyHidden.test.tsx +27 -0
  270. package/bizar-dash/tests/views/Agents.test.tsx +359 -0
  271. package/bizar-dash/tests/views/Overview.test.tsx +413 -0
  272. package/bizar-dash/tests/views/Tasks.test.tsx +250 -0
  273. package/bizar-dash/vitest.config.ts +3 -1
  274. package/cli/__tests__/cost-gate.test.mjs +301 -0
  275. package/cli/__tests__/feature-list-bridge.test.mjs +371 -0
  276. package/cli/bin.mjs +55 -18
  277. package/cli/commands/claim.mjs +282 -0
  278. package/cli/commands/claude-cmd.mjs +348 -0
  279. package/cli/commands/cost.mjs +279 -0
  280. package/cli/commands/install.mjs +12 -11
  281. package/cli/commands/validate.mjs +252 -325
  282. package/cli/cost-gate.mjs +501 -0
  283. package/cli/dev-link.test.mjs +11 -11
  284. package/cli/doctor.mjs +131 -213
  285. package/cli/feature-list-bridge.mjs +400 -0
  286. package/cli/install.mjs +33 -37
  287. package/cli/install.test.mjs +9 -9
  288. package/cli/memory-constants.mjs +17 -0
  289. package/cli/provision-claude.mjs +893 -0
  290. package/cli/provision.mjs +224 -227
  291. package/cli/utils.mjs +72 -58
  292. package/cli/worker-dispatcher.mjs +259 -0
  293. package/cli/worker-dispatcher.test.mjs +204 -0
  294. package/config/AGENTS.md +28 -28
  295. package/config/trigger-patterns.json +186 -0
  296. package/install.sh +66 -44
  297. package/package.json +19 -11
  298. package/packages/sdk/ARCHITECTURE.md +40 -36
  299. package/packages/sdk/package.json +15 -5
  300. package/packages/sdk/src/agent-registry.ts +304 -0
  301. package/packages/sdk/src/consensus/byzantine.ts +587 -0
  302. package/packages/sdk/src/consensus/index.ts +147 -0
  303. package/packages/sdk/src/consensus/queen.ts +173 -0
  304. package/packages/sdk/src/consensus/types.ts +199 -0
  305. package/{plugins/bizar → packages/sdk}/src/dangerous-patterns.ts +6 -28
  306. package/packages/sdk/src/federation/audit.ts +156 -0
  307. package/packages/sdk/src/federation/budget.ts +269 -0
  308. package/packages/sdk/src/federation/envelope.ts +144 -0
  309. package/packages/sdk/src/federation/hmac.ts +160 -0
  310. package/packages/sdk/src/federation/index.ts +443 -0
  311. package/packages/sdk/src/federation/pii.ts +241 -0
  312. package/packages/sdk/src/federation/policy.ts +112 -0
  313. package/packages/sdk/src/federation/trust.ts +146 -0
  314. package/packages/sdk/src/fingerprint.ts +0 -0
  315. package/packages/sdk/src/index.ts +101 -69
  316. package/packages/sdk/src/mcp/bin.ts +51 -0
  317. package/packages/sdk/src/mcp/server.ts +848 -0
  318. package/{plugins/bizar/src/memory-vault.ts → packages/sdk/src/memory/index.ts} +18 -21
  319. package/packages/sdk/src/router/codemod-intent.ts +125 -0
  320. package/packages/sdk/src/router/index.ts +247 -0
  321. package/packages/sdk/src/router/memory-distillation-shim.mjs +18 -0
  322. package/packages/sdk/src/router/memory-distillation.ts +249 -0
  323. package/packages/sdk/src/router/model-router.ts +235 -0
  324. package/packages/sdk/src/router/q-learning-router.ts +304 -0
  325. package/packages/sdk/src/swarm-topology.ts +279 -0
  326. package/packages/sdk/tests/agent-registry.test.ts +285 -0
  327. package/packages/sdk/tests/consensus.test.ts +376 -0
  328. package/packages/sdk/tests/federation/audit.test.ts +164 -0
  329. package/packages/sdk/tests/federation/budget.test.ts +189 -0
  330. package/packages/sdk/tests/federation/envelope.test.ts +120 -0
  331. package/packages/sdk/tests/federation/hmac.test.ts +194 -0
  332. package/packages/sdk/tests/federation/orchestrator.test.ts +176 -0
  333. package/packages/sdk/tests/federation/pii.test.ts +106 -0
  334. package/packages/sdk/tests/federation/policy.test.ts +140 -0
  335. package/packages/sdk/tests/federation/trust.test.ts +124 -0
  336. package/packages/sdk/tests/mcp-tools.test.ts +204 -0
  337. package/packages/sdk/tests/memory-distillation.test.mjs +186 -0
  338. package/packages/sdk/tests/model-router.test.mjs +108 -0
  339. package/packages/sdk/tests/q-learning-router.test.mjs +100 -0
  340. package/packages/sdk/tests/router-orchestrator.test.mjs +172 -0
  341. package/packages/sdk/tests/router.test.mjs +91 -0
  342. package/packages/sdk/tests/sdk.test.mjs +172 -0
  343. package/packages/sdk/tests/swarm-topology.test.ts +258 -0
  344. package/packages/sdk/vitest.config.ts +1 -1
  345. package/scripts/bh-full-e2e.mjs +167 -368
  346. package/scripts/check-deps.mjs +28 -46
  347. package/scripts/mirror-claude-md.sh +78 -0
  348. package/scripts/test-in-container.sh +31 -9
  349. package/templates/clean-state-checklist.md +3 -3
  350. package/templates/sprint-contract.md +2 -2
  351. package/bizar-dash/.bizar/activity.log +0 -3
  352. package/bizar-dash/.omx/logs/omx-2026-07-07.jsonl +0 -1
  353. package/bizar-dash/.omx/state/session.json +0 -10
  354. package/bizar-dash/bizar-design/EXPLANATION.md +0 -307
  355. package/bizar-dash/bizar-design/INSTRUCTIONS.md +0 -149
  356. package/bizar-dash/bizar-design/canvas.html +0 -281
  357. package/bizar-dash/bizar-design/canvas.html.artifact.json +0 -19
  358. package/bizar-dash/bizar-design/components.css +0 -1665
  359. package/bizar-dash/bizar-design/components.html +0 -557
  360. package/bizar-dash/bizar-design/components.html.artifact.json +0 -19
  361. package/bizar-dash/bizar-design/desktop/agents.html +0 -74
  362. package/bizar-dash/bizar-design/desktop/agents.html.artifact.json +0 -19
  363. package/bizar-dash/bizar-design/desktop/memory.html +0 -75
  364. package/bizar-dash/bizar-design/desktop/memory.html.artifact.json +0 -19
  365. package/bizar-dash/bizar-design/desktop/metrics.html +0 -63
  366. package/bizar-dash/bizar-design/desktop/metrics.html.artifact.json +0 -19
  367. package/bizar-dash/bizar-design/desktop/overview.html +0 -95
  368. package/bizar-dash/bizar-design/desktop/overview.html.artifact.json +0 -19
  369. package/bizar-dash/bizar-design/desktop/settings.html +0 -70
  370. package/bizar-dash/bizar-design/desktop/settings.html.artifact.json +0 -19
  371. package/bizar-dash/bizar-design/icons.svg +0 -44
  372. package/bizar-dash/bizar-design/index.html +0 -192
  373. package/bizar-dash/bizar-design/index.html.artifact.json +0 -19
  374. package/bizar-dash/bizar-design/mobile/agents.html +0 -29
  375. package/bizar-dash/bizar-design/mobile/agents.html.artifact.json +0 -19
  376. package/bizar-dash/bizar-design/mobile/memory.html +0 -28
  377. package/bizar-dash/bizar-design/mobile/memory.html.artifact.json +0 -19
  378. package/bizar-dash/bizar-design/mobile/metrics.html +0 -29
  379. package/bizar-dash/bizar-design/mobile/metrics.html.artifact.json +0 -19
  380. package/bizar-dash/bizar-design/mobile/overview.html +0 -33
  381. package/bizar-dash/bizar-design/mobile/overview.html.artifact.json +0 -19
  382. package/bizar-dash/bizar-design/mobile/settings.html +0 -28
  383. package/bizar-dash/bizar-design/mobile/settings.html.artifact.json +0 -19
  384. package/bizar-dash/bizar-design/prototype.js +0 -114
  385. package/bizar-dash/bizar-design/tokens.css +0 -106
  386. package/bizar-dash/dist/assets/MobileChat-BnKN_Ks_.js +0 -1
  387. package/bizar-dash/dist/assets/MobileSettings-DjCPxC-Q.js +0 -1
  388. package/bizar-dash/dist/assets/icons-Do5N2jmX.js.map +0 -1
  389. package/bizar-dash/dist/assets/main-DYiZqMrn.js +0 -18
  390. package/bizar-dash/dist/assets/main-DYiZqMrn.js.map +0 -1
  391. package/bizar-dash/dist/assets/main-ietCEg_R.css +0 -1
  392. package/bizar-dash/dist/assets/markdown-C6mXtQxD.js +0 -1
  393. package/bizar-dash/dist/assets/mobile-CMHqtLV2.js +0 -1
  394. package/bizar-dash/dist/assets/mobile-layout-3jIhHX_p.js +0 -2
  395. package/bizar-dash/dist/assets/mobile-layout-3jIhHX_p.js.map +0 -1
  396. package/bizar-dash/dist/assets/react-vendor-Dn4wqh4Z.js +0 -40
  397. package/bizar-dash/dist/assets/react-vendor-Dn4wqh4Z.js.map +0 -1
  398. package/bizar-dash/dist/assets/useSlashCommands-DtITw8Xv.js +0 -2
  399. package/bizar-dash/dist/assets/useSlashCommands-DtITw8Xv.js.map +0 -1
  400. package/bizar-dash/dist/assets/vendor-CeHGtduv.js +0 -29
  401. package/bizar-dash/dist/assets/vendor-CeHGtduv.js.map +0 -1
  402. package/bizar-dash/node_modules/.package-lock.json +0 -6
  403. package/bizar-dash/package-lock.json +0 -6
  404. package/bizar-dash/src/server/cline-sdk.mjs +0 -132
  405. package/bizar-dash/src/server/routes/cline-session-detail.mjs +0 -559
  406. package/bizar-dash/src/server/routes/cline-sessions.mjs +0 -291
  407. package/cli/commands/cline-cmd.mjs +0 -289
  408. package/cli/commands/validate.test.mjs +0 -379
  409. package/cli/doctor.test.mjs +0 -350
  410. package/config/cline.json.template +0 -342
  411. package/packages/sdk/src/client.ts +0 -188
  412. package/packages/sdk/src/cline-events.ts +0 -134
  413. package/packages/sdk/src/cline-types.ts +0 -66
  414. package/packages/sdk/src/cline.ts +0 -339
  415. package/packages/sdk/src/errors.ts +0 -129
  416. package/packages/sdk/src/events.ts +0 -153
  417. package/packages/sdk/src/types.ts +0 -176
  418. package/packages/sdk/tests/client.test.ts +0 -217
  419. package/packages/sdk/tests/errors.test.ts +0 -108
  420. package/packages/sdk/tests/events.test.ts +0 -139
  421. package/packages/sdk/tests/fixtures/fetch-mock.ts +0 -152
  422. package/packages/sdk/tests/fixtures/sse-mock.ts +0 -30
  423. package/plugins/bizar/ARCHITECTURE.md +0 -142
  424. package/plugins/bizar/CONSTRAINTS.md +0 -67
  425. package/plugins/bizar/LICENSE +0 -21
  426. package/plugins/bizar/README.md +0 -448
  427. package/plugins/bizar/index.ts +0 -925
  428. package/plugins/bizar/package.json +0 -39
  429. package/plugins/bizar/scripts/check-forbidden-imports.sh +0 -33
  430. package/plugins/bizar/src/background-state.ts +0 -641
  431. package/plugins/bizar/src/background.ts +0 -1806
  432. package/plugins/bizar/src/cline-runner.ts +0 -203
  433. package/plugins/bizar/src/clineruntime.ts +0 -227
  434. package/plugins/bizar/src/commands-impl.ts +0 -151
  435. package/plugins/bizar/src/commands.ts +0 -1799
  436. package/plugins/bizar/src/compaction.d.mts +0 -48
  437. package/plugins/bizar/src/compaction.mjs +0 -192
  438. package/plugins/bizar/src/dashboard-client.ts +0 -233
  439. package/plugins/bizar/src/event-stream.ts +0 -606
  440. package/plugins/bizar/src/fingerprint.ts +0 -120
  441. package/plugins/bizar/src/handoff.ts +0 -79
  442. package/plugins/bizar/src/hooks/memory-flush-on-compact.ts +0 -123
  443. package/plugins/bizar/src/hooks/memory-inject.ts +0 -247
  444. package/plugins/bizar/src/hooks/memory-write-on-end.ts +0 -188
  445. package/plugins/bizar/src/hooks/skill-curator.ts +0 -180
  446. package/plugins/bizar/src/http-client.ts +0 -467
  447. package/plugins/bizar/src/key-rotation.ts +0 -218
  448. package/plugins/bizar/src/logger.ts +0 -144
  449. package/plugins/bizar/src/loop-engineering.ts +0 -241
  450. package/plugins/bizar/src/loop.ts +0 -176
  451. package/plugins/bizar/src/mistake-recovery.ts +0 -98
  452. package/plugins/bizar/src/odin.ts +0 -227
  453. package/plugins/bizar/src/options.ts +0 -470
  454. package/plugins/bizar/src/plan-fs.ts +0 -323
  455. package/plugins/bizar/src/reasoning-clean.ts +0 -454
  456. package/plugins/bizar/src/report.ts +0 -178
  457. package/plugins/bizar/src/research-prompt.ts +0 -35
  458. package/plugins/bizar/src/serve-info.ts +0 -228
  459. package/plugins/bizar/src/serve.ts +0 -496
  460. package/plugins/bizar/src/settings.ts +0 -349
  461. package/plugins/bizar/src/state.ts +0 -298
  462. package/plugins/bizar/src/tool-discipline.ts +0 -105
  463. package/plugins/bizar/src/tools/agent-browser.ts +0 -315
  464. package/plugins/bizar/src/tools/bg-collect.ts +0 -131
  465. package/plugins/bizar/src/tools/bg-get-comments.ts +0 -266
  466. package/plugins/bizar/src/tools/bg-kill.ts +0 -116
  467. package/plugins/bizar/src/tools/bg-pause.ts +0 -99
  468. package/plugins/bizar/src/tools/bg-report-progress.ts +0 -115
  469. package/plugins/bizar/src/tools/bg-resume.ts +0 -94
  470. package/plugins/bizar/src/tools/bg-send-message.ts +0 -223
  471. package/plugins/bizar/src/tools/bg-spawn.ts +0 -502
  472. package/plugins/bizar/src/tools/bg-status.ts +0 -130
  473. package/plugins/bizar/src/tools/graph-query.ts +0 -278
  474. package/plugins/bizar/src/tools/loop-engineering.ts +0 -193
  475. package/plugins/bizar/src/tools/memory-list.ts +0 -43
  476. package/plugins/bizar/src/tools/memory-read.ts +0 -69
  477. package/plugins/bizar/src/tools/memory-search.ts +0 -47
  478. package/plugins/bizar/src/tools/memory-write.ts +0 -54
  479. package/plugins/bizar/src/tools/open-kb.ts +0 -198
  480. package/plugins/bizar/src/tools/plan-action.ts +0 -785
  481. package/plugins/bizar/src/tools/read-glyph-feedback.ts +0 -191
  482. package/plugins/bizar/src/tools/sandbox.ts +0 -232
  483. package/plugins/bizar/src/tools/team-spawn.ts +0 -73
  484. package/plugins/bizar/src/tools/team-status.ts +0 -76
  485. package/plugins/bizar/src/tools/wait-for-feedback.ts +0 -415
  486. package/plugins/bizar/src/trajectory.ts +0 -104
  487. package/plugins/bizar/tests/README.md +0 -99
  488. package/plugins/bizar/tests/attach-handler-bug.test.ts +0 -169
  489. package/plugins/bizar/tests/background-state.test.ts +0 -277
  490. package/plugins/bizar/tests/background.test.ts +0 -402
  491. package/plugins/bizar/tests/block.test.ts +0 -195
  492. package/plugins/bizar/tests/canonical-key-order.test.ts +0 -75
  493. package/plugins/bizar/tests/clineruntime-config.test.ts +0 -283
  494. package/plugins/bizar/tests/commands-impl.test.ts +0 -316
  495. package/plugins/bizar/tests/commands.test.ts +0 -584
  496. package/plugins/bizar/tests/compaction.test.ts +0 -264
  497. package/plugins/bizar/tests/config.test.ts +0 -128
  498. package/plugins/bizar/tests/dashboard-client.test.ts +0 -159
  499. package/plugins/bizar/tests/dispose.test.ts +0 -336
  500. package/plugins/bizar/tests/event-stream.test.ts +0 -409
  501. package/plugins/bizar/tests/event.test.ts +0 -262
  502. package/plugins/bizar/tests/fingerprint.test.ts +0 -190
  503. package/plugins/bizar/tests/http-client.test.ts +0 -404
  504. package/plugins/bizar/tests/init-helpers.test.ts +0 -203
  505. package/plugins/bizar/tests/integration/slash-command.test.ts +0 -349
  506. package/plugins/bizar/tests/integration/tool-routing.test.ts +0 -98
  507. package/plugins/bizar/tests/key-rotation.test.ts +0 -396
  508. package/plugins/bizar/tests/loop-engineering.test.ts +0 -168
  509. package/plugins/bizar/tests/loop.test.ts +0 -397
  510. package/plugins/bizar/tests/memory-write-on-end.test.ts +0 -92
  511. package/plugins/bizar/tests/mistake-recovery.test.ts +0 -116
  512. package/plugins/bizar/tests/odin.test.ts +0 -125
  513. package/plugins/bizar/tests/options.test.ts +0 -329
  514. package/plugins/bizar/tests/reasoning-clean.test.ts +0 -422
  515. package/plugins/bizar/tests/safety.test.ts +0 -281
  516. package/plugins/bizar/tests/serve.test.ts +0 -339
  517. package/plugins/bizar/tests/settings.test.ts +0 -351
  518. package/plugins/bizar/tests/stall-think.test.ts +0 -750
  519. package/plugins/bizar/tests/state.test.ts +0 -276
  520. package/plugins/bizar/tests/tool-discipline.test.ts +0 -77
  521. package/plugins/bizar/tests/tools/agent-browser.test.ts +0 -98
  522. package/plugins/bizar/tests/tools/bg-collect.test.ts +0 -337
  523. package/plugins/bizar/tests/tools/bg-get-comments.test.ts +0 -485
  524. package/plugins/bizar/tests/tools/bg-kill.test.ts +0 -235
  525. package/plugins/bizar/tests/tools/bg-pause.test.ts +0 -61
  526. package/plugins/bizar/tests/tools/bg-report-progress.test.ts +0 -79
  527. package/plugins/bizar/tests/tools/bg-resume.test.ts +0 -40
  528. package/plugins/bizar/tests/tools/bg-send-message.test.ts +0 -116
  529. package/plugins/bizar/tests/tools/bg-spawn-delegation.test.ts +0 -147
  530. package/plugins/bizar/tests/tools/bg-spawn-http.test.ts +0 -233
  531. package/plugins/bizar/tests/tools/bg-spawn.test.ts +0 -311
  532. package/plugins/bizar/tests/tools/bg-status.test.ts +0 -217
  533. package/plugins/bizar/tests/tools/cline-runner.test.ts +0 -115
  534. package/plugins/bizar/tests/tools/plan-action.test.ts +0 -599
  535. package/plugins/bizar/tests/tools/read-glyph-feedback.test.ts +0 -253
  536. package/plugins/bizar/tests/tools/sandbox.test.ts +0 -117
  537. package/plugins/bizar/tests/tools/wait-for-feedback.test.ts +0 -390
  538. package/plugins/bizar/tests/update-deadlock.test.ts +0 -151
  539. package/plugins/bizar/tsconfig.json +0 -29
  540. package/scripts/mirror-agents-md.sh +0 -69
@@ -1,227 +0,0 @@
1
- /**
2
- * plugins/bizar/src/odin.ts
3
- *
4
- * v6.0.0 — Odin orchestrator module.
5
- *
6
- * Odin is the top-level user-facing agent in the Bizar Norse pantheon. It
7
- * receives a user prompt, decomposes it into 2–6 subtasks, and dispatches
8
- * them to teammates via the existing `bizar_spawn_team` tool.
9
- *
10
- * Decomposition is rule-based for v1 — pattern matches on task keywords
11
- * to suggest a team composition (researcher + implementer + reviewer, etc.).
12
- * v2 can replace this with an LLM-driven decomposer.
13
- *
14
- * Public API:
15
- * decomposeTask(task) -> { subtasks[], roles[], estimatedAgents }
16
- * buildOdinPrompt(task, decomposition) -> string
17
- */
18
-
19
- export interface OdinSubtask {
20
- /** Short verb-led action description (e.g. "research auth libraries"). */
21
- title: string;
22
- /** Detailed prompt for the subtask agent. */
23
- prompt: string;
24
- /** Suggested agent role (odin, mimir, thor, heimdall, vidarr, forseti). */
25
- role: string;
26
- /** If true, this subtask blocks downstream subtasks. */
27
- blocking?: boolean;
28
- }
29
-
30
- export interface OdinDecomposition {
31
- subtasks: OdinSubtask[];
32
- /** Total agent count (lead + subtask teammates). */
33
- estimatedAgents: number;
34
- /** Reasoning summary for the decomposition. */
35
- rationale: string;
36
- }
37
-
38
- interface RoleTemplate {
39
- role: string;
40
- keywords: RegExp[];
41
- description: string;
42
- }
43
-
44
- const ROLE_TEMPLATES: RoleTemplate[] = [
45
- {
46
- role: "mimir",
47
- keywords: [/\bresearch\b/i, /\binvestigate\b/i, /\bexplore\b/i, /\bsurvey\b/i, /\banalyze\b/i, /\bunderstand\b/i, /\bdocs?\b/i],
48
- description: "Research & knowledge synthesis",
49
- },
50
- {
51
- role: "heimdall",
52
- keywords: [/\bquick\b/i, /\bsimple\b/i, /\bsmall\b/i, /\btweak\b/i, /\bfix\b/i, /\btypo\b/i, /\brename\b/i],
53
- description: "Small mechanical changes",
54
- },
55
- {
56
- role: "thor",
57
- keywords: [/\bimplement\b/i, /\bbuild\b/i, /\bcode\b/i, /\bfunction\b/i, /\bclass\b/i, /\bapi\b/i, /\bservice\b/i, /\bfeature\b/i],
58
- description: "Implementation & coding",
59
- },
60
- {
61
- role: "forseti",
62
- keywords: [/\btest\b/i, /\bverify\b/i, /\bvalidate\b/i, /\bspec\b/i, /\bcoverage\b/i, /\bassert/i, /\bcheck\b/i],
63
- description: "Verification & testing",
64
- },
65
- {
66
- role: "vidarr",
67
- keywords: [/\brefactor\b/i, /\barchitect\b/i, /\bdesign\b/i, /\bbig\b/i, /\bsystem\b/i, /\bcross.cutting\b/i, /\bperformance\b/i, /\bscale\b/i],
68
- description: "Architecture & deep refactors",
69
- },
70
- {
71
- role: "tyr",
72
- keywords: [/\bdebug\b/i, /\bbug\b/i, /\bfix\b/i, /\binvestigate\b/i, /\broot cause\b/i],
73
- description: "Hardest debugging tasks",
74
- },
75
- {
76
- role: "frigg",
77
- keywords: [/\bdocument\b/i, /\bwrite up\b/i, /\bREADME\b/i, /\bcomment\b/i, /\bguide\b/i],
78
- description: "Documentation",
79
- },
80
- {
81
- role: "baldr",
82
- keywords: [/\bui\b/i, /\bdesign\b/i, /\bvisual\b/i, /\bstyle\b/i, /\bcss\b/i, /\banimation\b/i, /\bux\b/i, /\bfrontend\b/i],
83
- description: "Frontend & UI work",
84
- },
85
- ];
86
-
87
- const DEFAULT_MAX_SUBTASKS = 4;
88
- const MIN_SUBTASKS = 2;
89
-
90
- /**
91
- * Heuristic sentence splitter — splits on `. `, `! `, `? `, `\n`, or `; `.
92
- * Filters out sentences shorter than 8 chars.
93
- */
94
- function splitSentences(text: string): string[] {
95
- return text
96
- .split(/(?<=[.!?])\s+|\n|;\s+/)
97
- .map((s) => s.trim())
98
- .filter((s) => s.length >= 8);
99
- }
100
-
101
- /**
102
- * Pick the best role for a sentence based on keyword matches.
103
- */
104
- function pickRole(sentence: string): string {
105
- let bestRole = "thor";
106
- let bestScore = 0;
107
- for (const t of ROLE_TEMPLATES) {
108
- let score = 0;
109
- for (const re of t.keywords) {
110
- const m = sentence.match(re);
111
- if (m) score += m[0].length;
112
- }
113
- if (score > bestScore) {
114
- bestScore = score;
115
- bestRole = t.role;
116
- }
117
- }
118
- return bestRole;
119
- }
120
-
121
- /**
122
- * Decompose a user task into 2-6 subtasks with assigned roles.
123
- */
124
- export function decomposeTask(task: string, maxSubtasks: number = DEFAULT_MAX_SUBTASKS): OdinDecomposition {
125
- const trimmed = task.trim();
126
- if (!trimmed) {
127
- return { subtasks: [], estimatedAgents: 0, rationale: "Empty task." };
128
- }
129
-
130
- let sentences = splitSentences(trimmed);
131
-
132
- // Special case: split on " and " / " then " if it gives us enough parts.
133
- if (sentences.length < MIN_SUBTASKS) {
134
- const lower = trimmed.toLowerCase();
135
- const hasAnd = /\b and \b/i.test(lower) || /,\s*and\b/i.test(lower);
136
- const hasThen = /\b then \b/i.test(lower);
137
- if (hasAnd || hasThen) {
138
- const parts = trimmed.split(/\b(?:and|then)\b/i).map((s) => s.trim()).filter(Boolean);
139
- if (parts.length >= MIN_SUBTASKS) sentences = parts;
140
- }
141
- }
142
-
143
- // Too few → default 2-step plan.
144
- if (sentences.length < MIN_SUBTASKS) {
145
- return {
146
- subtasks: [
147
- {
148
- title: "Research the problem space",
149
- prompt: `Research the following task and report back with findings + a recommended approach:\n\n${trimmed}`,
150
- role: "mimir",
151
- blocking: true,
152
- },
153
- {
154
- title: "Implement the solution",
155
- prompt: `Given the research findings above, implement the requested change:\n\n${trimmed}\n\nApply coding conventions from the existing codebase.`,
156
- role: "thor",
157
- },
158
- ],
159
- estimatedAgents: 3,
160
- rationale: "Single-sentence task — defaulted to research + implement.",
161
- };
162
- }
163
-
164
- // Too many → cap at maxSubtasks by merging adjacent same-role sentences.
165
- if (sentences.length > maxSubtasks) {
166
- const grouped: { role: string; sentences: string[] }[] = [];
167
- for (const s of sentences) {
168
- const role = pickRole(s);
169
- const last = grouped[grouped.length - 1];
170
- // Merge into the previous group if same role AND we're already at/over
171
- // the half-way mark (so we don't waste group slots on adjacent same-role
172
- // pairs early — only consolidate once we have headroom pressure).
173
- if (last && last.role === role && grouped.length >= Math.ceil(maxSubtasks / 2)) {
174
- last.sentences.push(s);
175
- } else {
176
- grouped.push({ role, sentences: [s] });
177
- }
178
- }
179
- while (grouped.length > maxSubtasks) {
180
- const dropIdx = Math.floor(grouped.length / 2);
181
- grouped.splice(dropIdx, 1);
182
- }
183
- sentences = grouped.map((g) => `${g.sentences.join(" ")}`);
184
- }
185
-
186
- const subtasks: OdinSubtask[] = sentences.map((s, i) => {
187
- const role = pickRole(s);
188
- return {
189
- title: s.length > 60 ? `${s.slice(0, 57)}…` : s,
190
- prompt: `${s}\n\nThis is subtask ${i + 1} of ${sentences.length} of the larger task: ${trimmed}`,
191
- role,
192
- blocking: i === 0,
193
- };
194
- });
195
-
196
- return {
197
- subtasks,
198
- estimatedAgents: subtasks.length + 1,
199
- rationale: `Decomposed into ${subtasks.length} subtasks. Roles: ${subtasks.map((s) => s.role).join(", ")}.`,
200
- };
201
- }
202
-
203
- /**
204
- * Build the Odin system prompt for the spawn_team tool call.
205
- */
206
- export function buildOdinPrompt(task: string, decomposition: OdinDecomposition): string {
207
- const lines: string[] = [
208
- "You are Odin, the lead agent of a Bizar agent team.",
209
- "",
210
- `## Mission`,
211
- task,
212
- "",
213
- `## Subtasks`,
214
- ...decomposition.subtasks.map(
215
- (s, i) => `${i + 1}. **${s.title}** (${s.role}${s.blocking ? ", blocking" : ""})\n ${s.prompt}`,
216
- ),
217
- "",
218
- `## Coordination`,
219
- "- Coordinate via TeamSendMessage.",
220
- "- Wait for blocking subtasks before dispatching downstream ones.",
221
- "- Aggregate results into a final report when all subtasks complete.",
222
- "",
223
- `## Rationale`,
224
- decomposition.rationale,
225
- ];
226
- return lines.join("\n");
227
- }
@@ -1,470 +0,0 @@
1
- /**
2
- * Options — plugin option validation, clamping, and secret-dir refusal.
3
- *
4
- * Spec requirements satisfied here:
5
- * - §6.1 — plugin option shape (defaults listed below).
6
- * - §6.2 — clamping rules. The plugin NEVER throws on bad config.
7
- * - §6.3 — threshold/window constraint (`loopThresholdBlock <= loopWindowSize + 2`).
8
- * - §6.4 — secret-directory refusal. The plugin refuses to start if `logDir`
9
- * or `stateDir` resolves inside `~/.ssh/`, `~/.gnupg/`, `~/.aws/`, or
10
- * `~/.kube/`. Matching uses the spec's exact algorithm: `path.resolve`
11
- * on both sides, then test equality OR `startsWith(resolved + path.sep)`.
12
- * The `+ path.sep` is critical — without it, `~/.ssh-foo` would falsely
13
- * match the `~/.ssh` prefix.
14
- * - §6.5 — environment-variable overrides (`BIZAR_DISABLE`,
15
- * `BIZAR_DISABLE_LOOP`, `BIZAR_DISABLE_LOG`, `BIZAR_LOG_LEVEL`,
16
- * `BIZAR_SERVE_PORT`, `BIZAR_MAX_CONCURRENT_INSTANCES`,
17
- * `BIZAR_SERVE_DISABLE`, `BIZAR_BACKGROUND_TOOL_CALL_CAP`,
18
- * `BIZAR_BACKGROUND_SKIP_PERMISSIONS`,
19
- * `BIZAR_STALL_TIMEOUT_MS`, `BIZAR_THINKING_LOOP_TIMEOUT_MS`,
20
- * `BIZAR_MAX_INTERVENTIONS`, `BIZAR_MAX_CONSECUTIVE_MISTAKES`).
21
- * Env vars are read once at init; mid-session changes are ignored.
22
- */
23
-
24
- import path from "node:path";
25
- import os from "node:os";
26
-
27
- /** Raw plugin options as they appear in `cline.json` (before clamping). */
28
- export interface RawOptions {
29
- loopThresholdWarn?: unknown;
30
- loopThresholdEscalate?: unknown;
31
- loopThresholdBlock?: unknown;
32
- loopWindowSize?: unknown;
33
- logDir?: unknown;
34
- stateDir?: unknown;
35
- logRotationBytes?: unknown;
36
- servePort?: unknown;
37
- maxConcurrentInstances?: unknown;
38
- serveDisabled?: unknown;
39
- backgroundToolCallCap?: unknown;
40
- backgroundSkipPermissions?: unknown;
41
- httpTimeoutMs?: unknown;
42
- // v0.3.0 — stall and thinking-loop protection
43
- backgroundStallTimeoutMs?: unknown;
44
- backgroundThinkingLoopTimeoutMs?: unknown;
45
- backgroundMaxInterventions?: unknown;
46
- // v0.3.1 — ClineRuntime execution surface
47
- /**
48
- * Override Cline's `execution.maxConsecutiveMistakes` (CLI default 3;
49
- * SDK default 6). Bizar ships 6 by default and additionally wires the
50
- * `onConsecutiveMistakeLimitReached` recovery callback so a single
51
- * bad turn doesn't abort the session. Range [3, 20]; out-of-range
52
- * values are clamped and a note is emitted.
53
- */
54
- clineruntimeMaxConsecutiveMistakes?: unknown;
55
- }
56
-
57
- /**
58
- * Normalized options — the output of `normalizeOptions`. Every field has a
59
- * safe, valid value. The loop guard and logger consume this shape.
60
- */
61
- export interface NormalizedOptions {
62
- loopThresholdWarn: number;
63
- loopThresholdEscalate: number;
64
- loopThresholdBlock: number;
65
- loopWindowSize: number;
66
- logDir: string;
67
- stateDir: string;
68
- logRotationBytes: number;
69
- servePort: number;
70
- maxConcurrentInstances: number;
71
- serveDisabled: boolean;
72
- backgroundToolCallCap: number;
73
- backgroundSkipPermissions: boolean;
74
- httpTimeoutMs: number;
75
- // v0.3.0 — stall and thinking-loop protection
76
- /** ms without any SSE event before a non-terminal instance is aborted as stalled (default 180000 = 3 min, range [10000, 600000]). */
77
- backgroundStallTimeoutMs: number;
78
- /** ms without any tool/text part before a `running` instance is flagged as a thinking loop (default 300000 = 5 min, range [30000, 900000]). */
79
- backgroundThinkingLoopTimeoutMs: number;
80
- /** max number of research interventions sent before forcing an abort (default 1, range [1, 3]). */
81
- backgroundMaxInterventions: number;
82
- // v0.3.1 — ClineRuntime execution surface
83
- /** Override Cline's `execution.maxConsecutiveMistakes` (default 6, range [3, 20]). */
84
- clineruntimeMaxConsecutiveMistakes: number;
85
- }
86
-
87
- /** Environment-variable override flags. */
88
- export interface EnvFlags {
89
- disable: boolean;
90
- disableLoop: boolean;
91
- disableLog: boolean;
92
- }
93
-
94
- /** Default values per spec §6.1 / §8. */
95
- export const DEFAULT_OPTIONS: NormalizedOptions = {
96
- loopThresholdWarn: 5,
97
- loopThresholdEscalate: 8,
98
- loopThresholdBlock: 12,
99
- loopWindowSize: 10,
100
- logDir: "~/.cache/bizar/logs",
101
- stateDir: "~/.cache/bizar",
102
- logRotationBytes: 10_485_760, // 10 MB
103
- servePort: 0, // 0 = random OS-assigned port (§1.1)
104
- maxConcurrentInstances: 8, // §8
105
- serveDisabled: false, // §8
106
- backgroundToolCallCap: 500, // §8 / §6.2
107
- backgroundSkipPermissions: false, // §8 / §6.4
108
- httpTimeoutMs: 30_000, // §2.3 / §8
109
- // v0.3.0 — stall and thinking-loop protection
110
- backgroundStallTimeoutMs: 180_000, // 3 min
111
- backgroundThinkingLoopTimeoutMs: 300_000, // 5 min
112
- backgroundMaxInterventions: 1,
113
- // v0.3.1 — ClineRuntime execution surface
114
- // SDK default `??6`; CLI overrides to 3. We pick 10 so several
115
- // malformed tool calls don't kill the session; the recovery
116
- // callback (mistake-recovery.ts) gives the model guidance on the
117
- // way back. v6.2.4 — bumped from 6 → 10 because the Cline CLI's
118
- // --retries default of 3 was previously overriding this entirely.
119
- // Now `buildExecution` uses Math.max(plugin_default, caller_value)
120
- // so this acts as a FLOOR, not a default.
121
- clineruntimeMaxConsecutiveMistakes: 10,
122
- };
123
-
124
- const SECRET_DIRS: readonly string[] = [
125
- "~/.ssh",
126
- "~/.gnupg",
127
- "~/.aws",
128
- "~/.kube",
129
- ] as const;
130
-
131
- /**
132
- * Expand a leading `~` to the user's home directory. The spec's default
133
- * paths use `~/.cache/bizar`; we honor that.
134
- */
135
- export function expandHome(p: string): string {
136
- if (p === "~") return os.homedir();
137
- if (p.startsWith("~/") || p.startsWith("~\\")) {
138
- return path.join(os.homedir(), p.slice(2));
139
- }
140
- return p;
141
- }
142
-
143
- /**
144
- * Spec §6.4 matching algorithm. Returns the secret-dir kind that `target`
145
- * matches (e.g. `~/.ssh`), or `null` if `target` is safe.
146
- *
147
- * resolvedTarget === resolvedSecret → equal
148
- * resolvedTarget.startsWith(resolvedSecret + sep) → strict descendant
149
- */
150
- export function findSecretDirMatch(target: string): string | null {
151
- const resolvedTarget = path.resolve(expandHome(target));
152
- for (const secret of SECRET_DIRS) {
153
- const resolvedSecret = path.resolve(expandHome(secret));
154
- if (resolvedTarget === resolvedSecret) return secret;
155
- if (resolvedTarget.startsWith(resolvedSecret + path.sep)) return secret;
156
- }
157
- return null;
158
- }
159
-
160
- /** Coerce an unknown value to a finite integer, or return `undefined`. */
161
- function toFiniteInt(value: unknown): number | undefined {
162
- if (typeof value === "number" && Number.isFinite(value)) {
163
- return Math.floor(value);
164
- }
165
- if (typeof value === "string" && value.trim() !== "") {
166
- const n = Number(value);
167
- if (Number.isFinite(n)) return Math.floor(n);
168
- }
169
- return undefined;
170
- }
171
-
172
- /** Coerce to a string path; return `undefined` if the value is not a string. */
173
- function toStringPath(value: unknown): string | undefined {
174
- if (typeof value === "string" && value !== "") return value;
175
- return undefined;
176
- }
177
-
178
- /**
179
- * Apply the clamping rules from spec §6.2. Returns the normalized options
180
- * and a list of "clamp notes" — human-readable strings describing each
181
- * non-default normalization applied. The caller is expected to log these
182
- * via `client.app.log` at warn level (spec §6.2: "After clamping, log a
183
- * `client.app.log` warning if any non-default normalization was applied").
184
- */
185
- export function normalizeOptions(raw: RawOptions | undefined): {
186
- options: NormalizedOptions;
187
- notes: string[];
188
- } {
189
- const notes: string[] = [];
190
- const r = raw ?? {};
191
-
192
- // --- Numeric thresholds (§6.2) ---
193
- const rawWarn = toFiniteInt(r.loopThresholdWarn);
194
- const rawEscalate = toFiniteInt(r.loopThresholdEscalate);
195
- const rawBlock = toFiniteInt(r.loopThresholdBlock);
196
-
197
- let warn = rawWarn !== undefined ? Math.max(1, rawWarn) : DEFAULT_OPTIONS.loopThresholdWarn;
198
- let escalate = rawEscalate !== undefined ? Math.max(1, rawEscalate) : DEFAULT_OPTIONS.loopThresholdEscalate;
199
- let block = rawBlock !== undefined ? Math.max(1, rawBlock) : DEFAULT_OPTIONS.loopThresholdBlock;
200
-
201
- if (rawWarn !== undefined && rawWarn < 1) {
202
- notes.push(`loopThresholdWarn ${rawWarn} clamped to 1`);
203
- } else if (rawWarn === undefined) {
204
- notes.push(`loopThresholdWarn defaulted to ${warn}`);
205
- }
206
-
207
- // --- Ordering: warn < escalate < block (§6.2) ---
208
- if (warn >= escalate) {
209
- const newEscalate = warn + 1;
210
- notes.push(`loopThresholdEscalate adjusted from ${escalate} to ${newEscalate} (must be > loopThresholdWarn)`);
211
- escalate = newEscalate;
212
- }
213
- if (escalate >= block) {
214
- const newBlock = escalate + 1;
215
- notes.push(`loopThresholdBlock adjusted from ${block} to ${newBlock} (must be > loopThresholdEscalate)`);
216
- block = newBlock;
217
- }
218
-
219
- // --- Window size (§6.2: clamped to [3, 50]) ---
220
- const rawWindow = toFiniteInt(r.loopWindowSize);
221
- let window: number;
222
- if (rawWindow === undefined) {
223
- window = DEFAULT_OPTIONS.loopWindowSize;
224
- } else if (rawWindow < 3) {
225
- window = 3;
226
- notes.push(`loopWindowSize ${rawWindow} clamped to 3 (minimum)`);
227
- } else if (rawWindow > 50) {
228
- window = 50;
229
- notes.push(`loopWindowSize ${rawWindow} clamped to 50 (maximum)`);
230
- } else {
231
- window = rawWindow;
232
- }
233
-
234
- // --- Threshold/window constraint (§6.3) ---
235
- if (block > window + 2) {
236
- const newBlock = window + 2;
237
- notes.push(
238
- `loopThresholdBlock ${block} adjusted to ${newBlock} (must be <= loopWindowSize + 2)`,
239
- );
240
- block = newBlock;
241
- }
242
-
243
- // --- logRotationBytes (§6.2: minimum 1024) ---
244
- const rawBytes = toFiniteInt(r.logRotationBytes);
245
- let bytes: number;
246
- if (rawBytes === undefined) {
247
- bytes = DEFAULT_OPTIONS.logRotationBytes;
248
- } else if (rawBytes < 1024) {
249
- bytes = 1024;
250
- notes.push(`logRotationBytes ${rawBytes} clamped to 1024 (minimum)`);
251
- } else {
252
- bytes = rawBytes;
253
- }
254
-
255
- // --- Background agent options (§6.5 / §8) ---
256
- // servePort: default 0 (random); env BIZAR_SERVE_PORT overrides
257
- const rawServePort = toFiniteInt(r.servePort);
258
- const envServePort = toFiniteInt(process.env.BIZAR_SERVE_PORT);
259
- const servePort = rawServePort !== undefined
260
- ? (rawServePort < 0 ? (notes.push(`servePort ${rawServePort} clamped to 0 (minimum)`), 0) : rawServePort)
261
- : envServePort !== undefined
262
- ? envServePort
263
- : DEFAULT_OPTIONS.servePort;
264
-
265
- // maxConcurrentInstances: default 8, max 32 (§6.5)
266
- const rawMaxInstances = toFiniteInt(r.maxConcurrentInstances);
267
- const envMaxInstances = toFiniteInt(process.env.BIZAR_MAX_CONCURRENT_INSTANCES);
268
- let maxConcurrentInstances: number;
269
- if (rawMaxInstances !== undefined) {
270
- maxConcurrentInstances = Math.min(Math.max(1, rawMaxInstances), 32);
271
- if (rawMaxInstances !== maxConcurrentInstances) {
272
- notes.push(`maxConcurrentInstances ${rawMaxInstances} clamped to ${maxConcurrentInstances} (range [1, 32])`);
273
- }
274
- } else if (envMaxInstances !== undefined) {
275
- maxConcurrentInstances = Math.min(Math.max(1, envMaxInstances), 32);
276
- if (envMaxInstances !== maxConcurrentInstances) {
277
- notes.push(`maxConcurrentInstances ${envMaxInstances} (env) clamped to ${maxConcurrentInstances} (range [1, 32])`);
278
- }
279
- } else {
280
- maxConcurrentInstances = DEFAULT_OPTIONS.maxConcurrentInstances;
281
- }
282
-
283
- // serveDisabled: default false; env BIZAR_SERVE_DISABLE=1 sets true (§8)
284
- const serveDisabled = process.env.BIZAR_SERVE_DISABLE === "1"
285
- ? true
286
- : (r.serveDisabled === true || r.serveDisabled === "true");
287
-
288
- // backgroundToolCallCap: default 500, max 5000 (§6.5)
289
- const rawToolCap = toFiniteInt(r.backgroundToolCallCap);
290
- const envToolCap = toFiniteInt(process.env.BIZAR_BACKGROUND_TOOL_CALL_CAP);
291
- let backgroundToolCallCap: number;
292
- if (rawToolCap !== undefined) {
293
- backgroundToolCallCap = Math.min(Math.max(1, rawToolCap), 5000);
294
- if (rawToolCap !== backgroundToolCallCap) {
295
- notes.push(`backgroundToolCallCap ${rawToolCap} clamped to ${backgroundToolCallCap} (range [1, 5000])`);
296
- }
297
- } else if (envToolCap !== undefined) {
298
- backgroundToolCallCap = Math.min(Math.max(1, envToolCap), 5000);
299
- if (envToolCap !== backgroundToolCallCap) {
300
- notes.push(`backgroundToolCallCap ${envToolCap} (env) clamped to ${backgroundToolCallCap} (range [1, 5000])`);
301
- }
302
- } else {
303
- backgroundToolCallCap = DEFAULT_OPTIONS.backgroundToolCallCap;
304
- }
305
-
306
- // backgroundSkipPermissions: default false; env BIZAR_BACKGROUND_SKIP_PERMISSIONS=1 sets true (§6.4)
307
- const backgroundSkipPermissions = process.env.BIZAR_BACKGROUND_SKIP_PERMISSIONS === "1"
308
- ? true
309
- : (r.backgroundSkipPermissions === true || r.backgroundSkipPermissions === "true");
310
-
311
- // httpTimeoutMs: default 30000, range [5000, 120000] (§2.3)
312
- const rawHttpTimeout = toFiniteInt(r.httpTimeoutMs);
313
- const envHttpTimeout = toFiniteInt(process.env.BIZAR_HTTP_TIMEOUT_MS);
314
- let httpTimeoutMs: number;
315
- if (rawHttpTimeout !== undefined) {
316
- httpTimeoutMs = Math.min(Math.max(5000, rawHttpTimeout), 120_000);
317
- if (rawHttpTimeout !== httpTimeoutMs) {
318
- notes.push(`httpTimeoutMs ${rawHttpTimeout} clamped to ${httpTimeoutMs} (range [5000, 120000])`);
319
- }
320
- } else if (envHttpTimeout !== undefined) {
321
- httpTimeoutMs = Math.min(Math.max(5000, envHttpTimeout), 120_000);
322
- if (envHttpTimeout !== httpTimeoutMs) {
323
- notes.push(`httpTimeoutMs ${envHttpTimeout} (env) clamped to ${httpTimeoutMs} (range [5000, 120000])`);
324
- }
325
- } else {
326
- httpTimeoutMs = DEFAULT_OPTIONS.httpTimeoutMs;
327
- }
328
-
329
- // --- v0.3.0 stall and thinking-loop protection -------------------------
330
-
331
- // backgroundStallTimeoutMs: default 180000, range [10000, 600000] (10s..10min)
332
- const rawStallTimeout = toFiniteInt(r.backgroundStallTimeoutMs);
333
- const envStallTimeout = toFiniteInt(process.env.BIZAR_STALL_TIMEOUT_MS);
334
- let backgroundStallTimeoutMs: number;
335
- if (rawStallTimeout !== undefined) {
336
- backgroundStallTimeoutMs = Math.min(Math.max(10_000, rawStallTimeout), 600_000);
337
- if (rawStallTimeout !== backgroundStallTimeoutMs) {
338
- notes.push(`backgroundStallTimeoutMs ${rawStallTimeout} clamped to ${backgroundStallTimeoutMs} (range [10000, 600000])`);
339
- }
340
- } else if (envStallTimeout !== undefined) {
341
- backgroundStallTimeoutMs = Math.min(Math.max(10_000, envStallTimeout), 600_000);
342
- if (envStallTimeout !== backgroundStallTimeoutMs) {
343
- notes.push(`backgroundStallTimeoutMs ${envStallTimeout} (env) clamped to ${backgroundStallTimeoutMs} (range [10000, 600000])`);
344
- }
345
- } else {
346
- backgroundStallTimeoutMs = DEFAULT_OPTIONS.backgroundStallTimeoutMs;
347
- }
348
-
349
- // backgroundThinkingLoopTimeoutMs: default 300000, range [30000, 900000] (30s..15min)
350
- const rawThinkingTimeout = toFiniteInt(r.backgroundThinkingLoopTimeoutMs);
351
- const envThinkingTimeout = toFiniteInt(process.env.BIZAR_THINKING_LOOP_TIMEOUT_MS);
352
- let backgroundThinkingLoopTimeoutMs: number;
353
- if (rawThinkingTimeout !== undefined) {
354
- backgroundThinkingLoopTimeoutMs = Math.min(Math.max(30_000, rawThinkingTimeout), 900_000);
355
- if (rawThinkingTimeout !== backgroundThinkingLoopTimeoutMs) {
356
- notes.push(`backgroundThinkingLoopTimeoutMs ${rawThinkingTimeout} clamped to ${backgroundThinkingLoopTimeoutMs} (range [30000, 900000])`);
357
- }
358
- } else if (envThinkingTimeout !== undefined) {
359
- backgroundThinkingLoopTimeoutMs = Math.min(Math.max(30_000, envThinkingTimeout), 900_000);
360
- if (envThinkingTimeout !== backgroundThinkingLoopTimeoutMs) {
361
- notes.push(`backgroundThinkingLoopTimeoutMs ${envThinkingTimeout} (env) clamped to ${backgroundThinkingLoopTimeoutMs} (range [30000, 900000])`);
362
- }
363
- } else {
364
- backgroundThinkingLoopTimeoutMs = DEFAULT_OPTIONS.backgroundThinkingLoopTimeoutMs;
365
- }
366
-
367
- // backgroundMaxInterventions: default 1, range [1, 3]
368
- const rawMaxInterventions = toFiniteInt(r.backgroundMaxInterventions);
369
- const envMaxInterventions = toFiniteInt(process.env.BIZAR_MAX_INTERVENTIONS);
370
- let backgroundMaxInterventions: number;
371
- if (rawMaxInterventions !== undefined) {
372
- backgroundMaxInterventions = Math.min(Math.max(1, rawMaxInterventions), 3);
373
- if (rawMaxInterventions !== backgroundMaxInterventions) {
374
- notes.push(`backgroundMaxInterventions ${rawMaxInterventions} clamped to ${backgroundMaxInterventions} (range [1, 3])`);
375
- }
376
- } else if (envMaxInterventions !== undefined) {
377
- backgroundMaxInterventions = Math.min(Math.max(1, envMaxInterventions), 3);
378
- if (envMaxInterventions !== backgroundMaxInterventions) {
379
- notes.push(`backgroundMaxInterventions ${envMaxInterventions} (env) clamped to ${backgroundMaxInterventions} (range [1, 3])`);
380
- }
381
- } else {
382
- backgroundMaxInterventions = DEFAULT_OPTIONS.backgroundMaxInterventions;
383
- }
384
-
385
- // --- v0.3.1 ClineRuntime execution surface -------------------------------
386
-
387
- // clineruntimeMaxConsecutiveMistakes: default 10, range [3, 20]
388
- // v6.2.4 — bumped from 6 to 10. CLI default is 3 which aborts
389
- // sessions on the FIRST 3 malformed tool calls (editor { new_text:
390
- // undefined }, run_commands exit code != 0, ask_question { options:
391
- // null }, …). With the v6.2.4 buildExecution fix (Math.max floor),
392
- // our higher default now always wins on plain `cline` invocations.
393
- // The harness wires a recovery callback that keeps the session alive on
394
- // recoverable mistakes, so we only need a slightly-larger ceiling.
395
- const rawMaxConsecutive = toFiniteInt(r.clineruntimeMaxConsecutiveMistakes);
396
- const envMaxConsecutive = toFiniteInt(process.env.BIZAR_MAX_CONSECUTIVE_MISTAKES);
397
- let clineruntimeMaxConsecutiveMistakes: number;
398
- if (rawMaxConsecutive !== undefined) {
399
- clineruntimeMaxConsecutiveMistakes = Math.min(Math.max(3, rawMaxConsecutive), 20);
400
- if (rawMaxConsecutive !== clineruntimeMaxConsecutiveMistakes) {
401
- notes.push(`clineruntimeMaxConsecutiveMistakes ${rawMaxConsecutive} clamped to ${clineruntimeMaxConsecutiveMistakes} (range [3, 20])`);
402
- }
403
- } else if (envMaxConsecutive !== undefined) {
404
- clineruntimeMaxConsecutiveMistakes = Math.min(Math.max(3, envMaxConsecutive), 20);
405
- if (envMaxConsecutive !== clineruntimeMaxConsecutiveMistakes) {
406
- notes.push(`clineruntimeMaxConsecutiveMistakes ${envMaxConsecutive} (env) clamped to ${clineruntimeMaxConsecutiveMistakes} (range [3, 20])`);
407
- }
408
- } else {
409
- clineruntimeMaxConsecutiveMistakes = DEFAULT_OPTIONS.clineruntimeMaxConsecutiveMistakes;
410
- }
411
-
412
- // --- Paths (§6.1 defaults) ---
413
- const logDir = toStringPath(r.logDir) ?? DEFAULT_OPTIONS.logDir;
414
- const stateDir = toStringPath(r.stateDir) ?? DEFAULT_OPTIONS.stateDir;
415
-
416
- return {
417
- options: {
418
- loopThresholdWarn: warn,
419
- loopThresholdEscalate: escalate,
420
- loopThresholdBlock: block,
421
- loopWindowSize: window,
422
- logDir,
423
- stateDir,
424
- logRotationBytes: bytes,
425
- servePort,
426
- maxConcurrentInstances,
427
- serveDisabled,
428
- backgroundToolCallCap,
429
- backgroundSkipPermissions,
430
- httpTimeoutMs,
431
- backgroundStallTimeoutMs,
432
- backgroundThinkingLoopTimeoutMs,
433
- backgroundMaxInterventions,
434
- clineruntimeMaxConsecutiveMistakes,
435
- },
436
- notes,
437
- };
438
- }
439
-
440
- /**
441
- * Read environment-variable override flags per spec §6.5. Read once at
442
- * plugin init. Mid-session changes are ignored.
443
- */
444
- export function readEnvFlags(): EnvFlags {
445
- return {
446
- disable: process.env.BIZAR_DISABLE === "1",
447
- disableLoop: process.env.BIZAR_DISABLE_LOOP === "1",
448
- disableLog: process.env.BIZAR_DISABLE_LOG === "1",
449
- };
450
- }
451
-
452
- /**
453
- * Spec §6.4: refuse to start if `logDir` or `stateDir` is inside a secret
454
- * directory. Returns the offending path and the matched secret kind, or
455
- * `null` if both paths are safe.
456
- */
457
- export function findOffendingPath(options: NormalizedOptions): {
458
- path: string;
459
- kind: string;
460
- } | null {
461
- const logMatch = findSecretDirMatch(options.logDir);
462
- if (logMatch !== null) {
463
- return { path: path.resolve(expandHome(options.logDir)), kind: logMatch };
464
- }
465
- const stateMatch = findSecretDirMatch(options.stateDir);
466
- if (stateMatch !== null) {
467
- return { path: path.resolve(expandHome(options.stateDir)), kind: stateMatch };
468
- }
469
- return null;
470
- }