@polderlabs/bizar 6.2.5 → 7.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (540) hide show
  1. package/.claude/CLAUDE.md +15 -0
  2. package/.claude/agents/_shared/AGENT_BASELINE.md +168 -0
  3. package/.claude/agents/_shared/CLAUDE_TOOLS.md +412 -0
  4. package/.claude/agents/_shared/SKILLS.md +109 -0
  5. package/.claude/agents/agent-browser.md +80 -0
  6. package/.claude/agents/baldr.md +49 -0
  7. package/.claude/agents/forseti.md +51 -0
  8. package/.claude/agents/frigg.md +42 -0
  9. package/.claude/agents/heimdall.md +33 -0
  10. package/.claude/agents/hermod.md +53 -0
  11. package/.claude/agents/mimir.md +49 -0
  12. package/.claude/agents/odin.md +287 -0
  13. package/.claude/agents/quick.md +34 -0
  14. package/.claude/agents/semble-search.md +50 -0
  15. package/.claude/agents/thor.md +53 -0
  16. package/.claude/agents/tyr.md +56 -0
  17. package/.claude/agents/vidarr.md +54 -0
  18. package/.claude/agents/vor.md +53 -0
  19. package/.claude/commands/audit.md +25 -0
  20. package/.claude/commands/bizar.md +22 -0
  21. package/.claude/commands/explain.md +17 -0
  22. package/.claude/commands/init.md +29 -0
  23. package/.claude/commands/learn.md +44 -0
  24. package/.claude/commands/plan.md +35 -0
  25. package/.claude/commands/plow-through.md +50 -0
  26. package/.claude/commands/pr-review.md +49 -0
  27. package/.claude/commands/setup-provider.md +96 -0
  28. package/.claude/commands/tailscale-serve.md +100 -0
  29. package/.claude/commands/team.md +132 -0
  30. package/.claude/commands/test.md +62 -0
  31. package/.claude/commands/validate.md +68 -0
  32. package/.claude/commands/visual-plan.md +24 -0
  33. package/.claude/hooks/README.md +92 -0
  34. package/.claude/hooks/posttooluse-editwrite.mjs +91 -0
  35. package/.claude/hooks/pretooluse-bash.mjs +81 -0
  36. package/.claude/hooks/pretooluse-editwrite.mjs +139 -0
  37. package/.claude/hooks/sessionend-recall.mjs +74 -0
  38. package/.claude/hooks/sessionstart-prime.mjs +80 -0
  39. package/.claude/hooks/userpromptsubmit-tag.mjs +80 -0
  40. package/.claude/hooks/worker-suggest.mjs +110 -0
  41. package/.claude/settings.json +125 -0
  42. package/.claude/skills/9router/SKILL.md +80 -0
  43. package/.claude/skills/9router-chat/SKILL.md +73 -0
  44. package/.claude/skills/9router-embeddings/SKILL.md +69 -0
  45. package/.claude/skills/9router-image/SKILL.md +86 -0
  46. package/.claude/skills/9router-stt/SKILL.md +79 -0
  47. package/.claude/skills/9router-tts/SKILL.md +80 -0
  48. package/.claude/skills/9router-web-fetch/SKILL.md +99 -0
  49. package/.claude/skills/9router-web-search/SKILL.md +91 -0
  50. package/.claude/skills/bizar/README.md +9 -0
  51. package/.claude/skills/bizar/SKILL.md +450 -0
  52. package/.claude/skills/cpp-coding-standards/README.md +28 -0
  53. package/.claude/skills/cpp-coding-standards/SKILL.md +634 -0
  54. package/.claude/skills/cpp-coding-standards/references/concurrency.md +320 -0
  55. package/.claude/skills/cpp-coding-standards/references/error-handling.md +229 -0
  56. package/.claude/skills/cpp-coding-standards/references/memory-safety.md +216 -0
  57. package/.claude/skills/cpp-coding-standards/references/modern-idioms.md +282 -0
  58. package/.claude/skills/cpp-coding-standards/references/review-checklist.md +96 -0
  59. package/.claude/skills/cpp-testing/README.md +28 -0
  60. package/.claude/skills/cpp-testing/SKILL.md +304 -0
  61. package/.claude/skills/cpp-testing/references/coverage.md +370 -0
  62. package/.claude/skills/cpp-testing/references/framework-compare.md +175 -0
  63. package/.claude/skills/cpp-testing/references/host-test-for-embedded.md +499 -0
  64. package/.claude/skills/cpp-testing/references/mocking.md +364 -0
  65. package/.claude/skills/cpp-testing/references/tdd-workflow.md +308 -0
  66. package/.claude/skills/cubesandbox/SKILL.md +148 -0
  67. package/.claude/skills/embedded-esp-idf/README.md +41 -0
  68. package/.claude/skills/embedded-esp-idf/SKILL.md +439 -0
  69. package/.claude/skills/embedded-esp-idf/references/freertos-patterns.md +214 -0
  70. package/.claude/skills/embedded-esp-idf/references/host-tests.md +164 -0
  71. package/.claude/skills/embedded-esp-idf/references/idf-py-commands.md +157 -0
  72. package/.claude/skills/embedded-esp-idf/references/kconfig.md +159 -0
  73. package/.claude/skills/embedded-esp-idf/references/logging-discipline.md +118 -0
  74. package/.claude/skills/embedded-esp-idf/references/memory-and-iram.md +137 -0
  75. package/.claude/skills/embedded-esp-idf/references/nvs.md +121 -0
  76. package/.claude/skills/embedded-esp-idf/references/packed-structs.md +192 -0
  77. package/.claude/skills/embedded-esp-idf/scripts/idf_env.sh +47 -0
  78. package/.claude/skills/embedded-esp-idf/scripts/size_check.sh +77 -0
  79. package/.claude/skills/glyph/SKILL.md +163 -0
  80. package/.claude/skills/harness-engineering/SKILL.md +143 -0
  81. package/.claude/skills/lightrag/SKILL.md +81 -0
  82. package/.claude/skills/memory-protocol/SKILL.md +105 -0
  83. package/.claude/skills/obsidian/SKILL.md +306 -0
  84. package/.claude/skills/read-the-damn-docs/SKILL.md +113 -0
  85. package/.claude/skills/self-improvement/SKILL.md +64 -0
  86. package/README.md +87 -59
  87. package/bizar-dash/dist/assets/{EnvVarsSection-DXM8gRm_.js → EnvVarsSection-CW6fWKds.js} +3 -3
  88. package/bizar-dash/dist/assets/{EnvVarsSection-DXM8gRm_.js.map → EnvVarsSection-CW6fWKds.js.map} +1 -1
  89. package/bizar-dash/dist/assets/MobileChat-D7zRhU9K.js +1 -0
  90. package/bizar-dash/dist/assets/{MobileChat-BnKN_Ks_.js.map → MobileChat-D7zRhU9K.js.map} +1 -1
  91. package/bizar-dash/dist/assets/MobileSettings-K-sNsn_r.js +1 -0
  92. package/bizar-dash/dist/assets/{MobileSettings-DjCPxC-Q.js.map → MobileSettings-K-sNsn_r.js.map} +1 -1
  93. package/bizar-dash/dist/assets/{Toast-Cpl6-E63.js → Toast-WTxc3m2g.js} +1 -1
  94. package/bizar-dash/dist/assets/{Toast-Cpl6-E63.js.map → Toast-WTxc3m2g.js.map} +1 -1
  95. package/bizar-dash/dist/assets/flow-BpU0-gK2.js +1 -0
  96. package/bizar-dash/dist/assets/flow-BpU0-gK2.js.map +1 -0
  97. package/bizar-dash/dist/assets/fuzzy-l0sNRNKZ.js +1 -0
  98. package/bizar-dash/dist/assets/fuzzy-l0sNRNKZ.js.map +1 -0
  99. package/bizar-dash/dist/assets/{icons-Do5N2jmX.js → icons-B0AKnYI3.js} +98 -103
  100. package/bizar-dash/dist/assets/icons-B0AKnYI3.js.map +1 -0
  101. package/bizar-dash/dist/assets/main-C-Md3DaY.css +1 -0
  102. package/bizar-dash/dist/assets/main-CO8fIxQK.js +18 -0
  103. package/bizar-dash/dist/assets/main-CO8fIxQK.js.map +1 -0
  104. package/bizar-dash/dist/assets/markdown-w2bDDkAH.js +1 -0
  105. package/bizar-dash/dist/assets/{markdown-C6mXtQxD.js.map → markdown-w2bDDkAH.js.map} +1 -1
  106. package/bizar-dash/dist/assets/mobile-DXYCA0hC.js +1 -0
  107. package/bizar-dash/dist/assets/{mobile-CMHqtLV2.js.map → mobile-DXYCA0hC.js.map} +1 -1
  108. package/bizar-dash/dist/assets/mobile-layout-DSmtNPja.js +2 -0
  109. package/bizar-dash/dist/assets/mobile-layout-DSmtNPja.js.map +1 -0
  110. package/bizar-dash/dist/assets/react-vendor-BnuhLJ6X.css +1 -0
  111. package/bizar-dash/dist/assets/react-vendor-D3pra6w-.js +46 -0
  112. package/bizar-dash/dist/assets/react-vendor-D3pra6w-.js.map +1 -0
  113. package/bizar-dash/dist/assets/useSlashCommands-3DFLOfpk.js +2 -0
  114. package/bizar-dash/dist/assets/useSlashCommands-3DFLOfpk.js.map +1 -0
  115. package/bizar-dash/dist/assets/vendor-Di7Cp-rw.js +45 -0
  116. package/bizar-dash/dist/assets/vendor-Di7Cp-rw.js.map +1 -0
  117. package/bizar-dash/dist/index.html +12 -10
  118. package/bizar-dash/dist/mobile.html +7 -4
  119. package/bizar-dash/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
  120. package/bizar-dash/src/server/api.mjs +15 -4
  121. package/bizar-dash/src/server/background-store.mjs +15 -16
  122. package/bizar-dash/src/server/bg-poller.mjs +25 -35
  123. package/bizar-dash/src/server/bg-retry.mjs +66 -194
  124. package/bizar-dash/src/server/claude-bg-spawner.mjs +390 -0
  125. package/bizar-dash/src/server/claude-info.mjs +412 -0
  126. package/bizar-dash/src/server/{cline-runner.mjs → claude-runner.mjs} +53 -48
  127. package/bizar-dash/src/server/claude-sdk.mjs +191 -0
  128. package/bizar-dash/src/server/memory-consolidator.mjs +218 -0
  129. package/bizar-dash/src/server/memory-distillation.mjs +296 -0
  130. package/bizar-dash/src/server/providers-store.mjs +22 -49
  131. package/bizar-dash/src/server/routes/background.mjs +24 -20
  132. package/bizar-dash/src/server/routes/chat.mjs +223 -326
  133. package/bizar-dash/src/server/routes/claude-session-detail.mjs +329 -0
  134. package/bizar-dash/src/server/routes/claude-sessions.mjs +259 -0
  135. package/bizar-dash/src/server/routes/distill.mjs +129 -0
  136. package/bizar-dash/src/server/routes/goal-planner.mjs +236 -0
  137. package/bizar-dash/src/server/routes/tasks.mjs +20 -28
  138. package/bizar-dash/src/server/task-delegator.mjs +76 -77
  139. package/bizar-dash/src/web/App.tsx +4 -0
  140. package/bizar-dash/src/web/components/Tag.tsx +18 -5
  141. package/bizar-dash/src/web/components/Topbar.tsx +3 -0
  142. package/bizar-dash/src/web/components/agents/CommunicationLog.tsx +126 -0
  143. package/bizar-dash/src/web/components/agents/DependencyGraph.tsx +163 -0
  144. package/bizar-dash/src/web/components/agents/QualityGates.tsx +123 -0
  145. package/bizar-dash/src/web/components/agents/RealTimeEventLog.tsx +127 -0
  146. package/bizar-dash/src/web/components/agents/RoutingDecisions.test.tsx +148 -0
  147. package/bizar-dash/src/web/components/agents/RoutingDecisions.tsx +160 -0
  148. package/bizar-dash/src/web/components/chat/useChat.ts +23 -27
  149. package/bizar-dash/src/web/components/goals/GoalInput.tsx +86 -0
  150. package/bizar-dash/src/web/components/goals/PlanVisualization.tsx +111 -0
  151. package/bizar-dash/src/web/lib/goapPlanner.ts +614 -0
  152. package/bizar-dash/src/web/lib/types.ts +25 -0
  153. package/bizar-dash/src/web/styles/agents-redesign.css +311 -0
  154. package/bizar-dash/src/web/styles/main.css +251 -0
  155. package/bizar-dash/src/web/styles/tasks-redesign.css +231 -0
  156. package/bizar-dash/src/web/ui/controls/Button.tsx +77 -0
  157. package/bizar-dash/src/web/ui/controls/Checkbox.tsx +95 -0
  158. package/bizar-dash/src/web/ui/controls/IconButton.tsx +66 -0
  159. package/bizar-dash/src/web/ui/controls/Kbd.tsx +24 -0
  160. package/bizar-dash/src/web/ui/controls/NumberInput.tsx +77 -0
  161. package/bizar-dash/src/web/ui/controls/RadioGroup.tsx +109 -0
  162. package/bizar-dash/src/web/ui/controls/SearchInput.tsx +91 -0
  163. package/bizar-dash/src/web/ui/controls/Select.tsx +92 -0
  164. package/bizar-dash/src/web/ui/controls/Slider.tsx +70 -0
  165. package/bizar-dash/src/web/ui/controls/TextInput.tsx +67 -0
  166. package/bizar-dash/src/web/ui/controls/Toggle.tsx +79 -0
  167. package/bizar-dash/src/web/ui/controls/controls.css +454 -0
  168. package/bizar-dash/src/web/ui/controls/index.ts +33 -0
  169. package/bizar-dash/src/web/ui/data/BarChart.tsx +60 -0
  170. package/bizar-dash/src/web/ui/data/DataTable.tsx +216 -0
  171. package/bizar-dash/src/web/ui/data/EmptyState.tsx +60 -0
  172. package/bizar-dash/src/web/ui/data/ErrorState.tsx +56 -0
  173. package/bizar-dash/src/web/ui/data/KeyValueList.tsx +106 -0
  174. package/bizar-dash/src/web/ui/data/LoadingState.tsx +65 -0
  175. package/bizar-dash/src/web/ui/data/Sparkline.tsx +87 -0
  176. package/bizar-dash/src/web/ui/data/StatTile.tsx +87 -0
  177. package/bizar-dash/src/web/ui/data/data.css +535 -0
  178. package/bizar-dash/src/web/ui/data/index.ts +31 -0
  179. package/bizar-dash/src/web/ui/feedback/Badge.tsx +49 -0
  180. package/bizar-dash/src/web/ui/feedback/Dialog.tsx +209 -0
  181. package/bizar-dash/src/web/ui/feedback/ProgressBar.tsx +69 -0
  182. package/bizar-dash/src/web/ui/feedback/StatusDot.tsx +50 -0
  183. package/bizar-dash/src/web/ui/feedback/Toast.tsx +200 -0
  184. package/bizar-dash/src/web/ui/feedback/Tooltip.tsx +126 -0
  185. package/bizar-dash/src/web/ui/feedback/feedback.css +314 -0
  186. package/bizar-dash/src/web/ui/feedback/index.ts +43 -0
  187. package/bizar-dash/src/web/ui/index.ts +56 -0
  188. package/bizar-dash/src/web/ui/layout/AppShell.tsx +51 -0
  189. package/bizar-dash/src/web/ui/layout/Breadcrumbs.tsx +97 -0
  190. package/bizar-dash/src/web/ui/layout/Panel.tsx +73 -0
  191. package/bizar-dash/src/web/ui/layout/PanelHeader.tsx +39 -0
  192. package/bizar-dash/src/web/ui/layout/Sidebar.tsx +131 -0
  193. package/bizar-dash/src/web/ui/layout/Tabs.tsx +133 -0
  194. package/bizar-dash/src/web/ui/layout/Topbar.tsx +42 -0
  195. package/bizar-dash/src/web/ui/layout/index.ts +33 -0
  196. package/bizar-dash/src/web/ui/layout/layout.css +413 -0
  197. package/bizar-dash/src/web/ui/navigation/CommandPalette.tsx +199 -0
  198. package/bizar-dash/src/web/ui/navigation/NavGroup.tsx +95 -0
  199. package/bizar-dash/src/web/ui/navigation/NavLink.tsx +93 -0
  200. package/bizar-dash/src/web/ui/navigation/index.ts +17 -0
  201. package/bizar-dash/src/web/ui/navigation/navigation.css +343 -0
  202. package/bizar-dash/src/web/ui/primitives/Box.tsx +91 -0
  203. package/bizar-dash/src/web/ui/primitives/Grid.tsx +49 -0
  204. package/bizar-dash/src/web/ui/primitives/Inline.tsx +55 -0
  205. package/bizar-dash/src/web/ui/primitives/Separator.tsx +46 -0
  206. package/bizar-dash/src/web/ui/primitives/Stack.tsx +54 -0
  207. package/bizar-dash/src/web/ui/primitives/VisuallyHidden.tsx +26 -0
  208. package/bizar-dash/src/web/ui/primitives/index.ts +23 -0
  209. package/bizar-dash/src/web/ui/primitives/primitives.css +183 -0
  210. package/bizar-dash/src/web/ui/styles/globals.css +86 -0
  211. package/bizar-dash/src/web/ui/styles/reset.css +125 -0
  212. package/bizar-dash/src/web/ui/styles/tokens.css +195 -0
  213. package/bizar-dash/src/web/ui/theme/ThemeProvider.tsx +142 -0
  214. package/bizar-dash/src/web/ui/theme/tokens.ts +131 -0
  215. package/bizar-dash/src/web/ui/theme/useTheme.ts +22 -0
  216. package/bizar-dash/src/web/ui/utils/cx.ts +42 -0
  217. package/bizar-dash/src/web/views/Agents.tsx +506 -266
  218. package/bizar-dash/src/web/views/Chat.tsx +8 -8
  219. package/bizar-dash/src/web/views/GoalPlanner.tsx +158 -0
  220. package/bizar-dash/src/web/views/Overview.tsx +996 -448
  221. package/bizar-dash/src/web/views/Tasks.tsx +277 -273
  222. package/bizar-dash/tests/communication-log.test.tsx +67 -0
  223. package/bizar-dash/tests/dep-graph.test.tsx +40 -0
  224. package/bizar-dash/tests/event-log.test.tsx +61 -0
  225. package/bizar-dash/tests/goal-input.test.tsx +72 -0
  226. package/bizar-dash/tests/goap-planner.test.ts +68 -0
  227. package/bizar-dash/tests/quality-gates.test.tsx +59 -0
  228. package/bizar-dash/tests/setup.ts +31 -1
  229. package/bizar-dash/tests/ui/controls/Button.test.tsx +50 -0
  230. package/bizar-dash/tests/ui/controls/Checkbox.test.tsx +44 -0
  231. package/bizar-dash/tests/ui/controls/IconButton.test.tsx +37 -0
  232. package/bizar-dash/tests/ui/controls/Kbd.test.tsx +39 -0
  233. package/bizar-dash/tests/ui/controls/NumberInput.test.tsx +56 -0
  234. package/bizar-dash/tests/ui/controls/RadioGroup.test.tsx +58 -0
  235. package/bizar-dash/tests/ui/controls/SearchInput.test.tsx +52 -0
  236. package/bizar-dash/tests/ui/controls/Select.test.tsx +66 -0
  237. package/bizar-dash/tests/ui/controls/Slider.test.tsx +41 -0
  238. package/bizar-dash/tests/ui/controls/TextInput.test.tsx +44 -0
  239. package/bizar-dash/tests/ui/controls/Toggle.test.tsx +39 -0
  240. package/bizar-dash/tests/ui/data/BarChart.test.tsx +55 -0
  241. package/bizar-dash/tests/ui/data/DataTable.test.tsx +112 -0
  242. package/bizar-dash/tests/ui/data/EmptyState.test.tsx +57 -0
  243. package/bizar-dash/tests/ui/data/ErrorState.test.tsx +47 -0
  244. package/bizar-dash/tests/ui/data/KeyValueList.test.tsx +59 -0
  245. package/bizar-dash/tests/ui/data/LoadingState.test.tsx +37 -0
  246. package/bizar-dash/tests/ui/data/Sparkline.test.tsx +56 -0
  247. package/bizar-dash/tests/ui/data/StatTile.test.tsx +69 -0
  248. package/bizar-dash/tests/ui/feedback/Badge.test.tsx +41 -0
  249. package/bizar-dash/tests/ui/feedback/Dialog.test.tsx +99 -0
  250. package/bizar-dash/tests/ui/feedback/ProgressBar.test.tsx +66 -0
  251. package/bizar-dash/tests/ui/feedback/StatusDot.test.tsx +41 -0
  252. package/bizar-dash/tests/ui/feedback/Toast.test.tsx +124 -0
  253. package/bizar-dash/tests/ui/feedback/Tooltip.test.tsx +102 -0
  254. package/bizar-dash/tests/ui/layout/AppShell.test.tsx +50 -0
  255. package/bizar-dash/tests/ui/layout/Breadcrumbs.test.tsx +85 -0
  256. package/bizar-dash/tests/ui/layout/Panel.test.tsx +52 -0
  257. package/bizar-dash/tests/ui/layout/PanelHeader.test.tsx +32 -0
  258. package/bizar-dash/tests/ui/layout/Sidebar.test.tsx +95 -0
  259. package/bizar-dash/tests/ui/layout/Tabs.test.tsx +87 -0
  260. package/bizar-dash/tests/ui/layout/Topbar.test.tsx +41 -0
  261. package/bizar-dash/tests/ui/navigation/CommandPalette.test.tsx +105 -0
  262. package/bizar-dash/tests/ui/navigation/NavGroup.test.tsx +55 -0
  263. package/bizar-dash/tests/ui/navigation/NavLink.test.tsx +61 -0
  264. package/bizar-dash/tests/ui/primitives/Box.test.tsx +49 -0
  265. package/bizar-dash/tests/ui/primitives/Grid.test.tsx +37 -0
  266. package/bizar-dash/tests/ui/primitives/Inline.test.tsx +33 -0
  267. package/bizar-dash/tests/ui/primitives/Separator.test.tsx +34 -0
  268. package/bizar-dash/tests/ui/primitives/Stack.test.tsx +45 -0
  269. package/bizar-dash/tests/ui/primitives/VisuallyHidden.test.tsx +27 -0
  270. package/bizar-dash/tests/views/Agents.test.tsx +359 -0
  271. package/bizar-dash/tests/views/Overview.test.tsx +413 -0
  272. package/bizar-dash/tests/views/Tasks.test.tsx +250 -0
  273. package/bizar-dash/vitest.config.ts +3 -1
  274. package/cli/__tests__/cost-gate.test.mjs +301 -0
  275. package/cli/__tests__/feature-list-bridge.test.mjs +371 -0
  276. package/cli/bin.mjs +55 -18
  277. package/cli/commands/claim.mjs +282 -0
  278. package/cli/commands/claude-cmd.mjs +348 -0
  279. package/cli/commands/cost.mjs +279 -0
  280. package/cli/commands/install.mjs +12 -11
  281. package/cli/commands/validate.mjs +252 -325
  282. package/cli/cost-gate.mjs +501 -0
  283. package/cli/dev-link.test.mjs +11 -11
  284. package/cli/doctor.mjs +131 -213
  285. package/cli/feature-list-bridge.mjs +400 -0
  286. package/cli/install.mjs +33 -37
  287. package/cli/install.test.mjs +9 -9
  288. package/cli/memory-constants.mjs +17 -0
  289. package/cli/provision-claude.mjs +893 -0
  290. package/cli/provision.mjs +224 -227
  291. package/cli/utils.mjs +72 -58
  292. package/cli/worker-dispatcher.mjs +259 -0
  293. package/cli/worker-dispatcher.test.mjs +204 -0
  294. package/config/AGENTS.md +28 -28
  295. package/config/trigger-patterns.json +186 -0
  296. package/install.sh +66 -44
  297. package/package.json +19 -11
  298. package/packages/sdk/ARCHITECTURE.md +40 -36
  299. package/packages/sdk/package.json +15 -5
  300. package/packages/sdk/src/agent-registry.ts +304 -0
  301. package/packages/sdk/src/consensus/byzantine.ts +587 -0
  302. package/packages/sdk/src/consensus/index.ts +147 -0
  303. package/packages/sdk/src/consensus/queen.ts +173 -0
  304. package/packages/sdk/src/consensus/types.ts +199 -0
  305. package/{plugins/bizar → packages/sdk}/src/dangerous-patterns.ts +6 -28
  306. package/packages/sdk/src/federation/audit.ts +156 -0
  307. package/packages/sdk/src/federation/budget.ts +269 -0
  308. package/packages/sdk/src/federation/envelope.ts +144 -0
  309. package/packages/sdk/src/federation/hmac.ts +160 -0
  310. package/packages/sdk/src/federation/index.ts +443 -0
  311. package/packages/sdk/src/federation/pii.ts +241 -0
  312. package/packages/sdk/src/federation/policy.ts +112 -0
  313. package/packages/sdk/src/federation/trust.ts +146 -0
  314. package/packages/sdk/src/fingerprint.ts +0 -0
  315. package/packages/sdk/src/index.ts +101 -69
  316. package/packages/sdk/src/mcp/bin.ts +51 -0
  317. package/packages/sdk/src/mcp/server.ts +848 -0
  318. package/{plugins/bizar/src/memory-vault.ts → packages/sdk/src/memory/index.ts} +18 -21
  319. package/packages/sdk/src/router/codemod-intent.ts +125 -0
  320. package/packages/sdk/src/router/index.ts +247 -0
  321. package/packages/sdk/src/router/memory-distillation-shim.mjs +18 -0
  322. package/packages/sdk/src/router/memory-distillation.ts +249 -0
  323. package/packages/sdk/src/router/model-router.ts +235 -0
  324. package/packages/sdk/src/router/q-learning-router.ts +304 -0
  325. package/packages/sdk/src/swarm-topology.ts +279 -0
  326. package/packages/sdk/tests/agent-registry.test.ts +285 -0
  327. package/packages/sdk/tests/consensus.test.ts +376 -0
  328. package/packages/sdk/tests/federation/audit.test.ts +164 -0
  329. package/packages/sdk/tests/federation/budget.test.ts +189 -0
  330. package/packages/sdk/tests/federation/envelope.test.ts +120 -0
  331. package/packages/sdk/tests/federation/hmac.test.ts +194 -0
  332. package/packages/sdk/tests/federation/orchestrator.test.ts +176 -0
  333. package/packages/sdk/tests/federation/pii.test.ts +106 -0
  334. package/packages/sdk/tests/federation/policy.test.ts +140 -0
  335. package/packages/sdk/tests/federation/trust.test.ts +124 -0
  336. package/packages/sdk/tests/mcp-tools.test.ts +204 -0
  337. package/packages/sdk/tests/memory-distillation.test.mjs +186 -0
  338. package/packages/sdk/tests/model-router.test.mjs +108 -0
  339. package/packages/sdk/tests/q-learning-router.test.mjs +100 -0
  340. package/packages/sdk/tests/router-orchestrator.test.mjs +172 -0
  341. package/packages/sdk/tests/router.test.mjs +91 -0
  342. package/packages/sdk/tests/sdk.test.mjs +172 -0
  343. package/packages/sdk/tests/swarm-topology.test.ts +258 -0
  344. package/packages/sdk/vitest.config.ts +1 -1
  345. package/scripts/bh-full-e2e.mjs +167 -368
  346. package/scripts/check-deps.mjs +28 -46
  347. package/scripts/mirror-claude-md.sh +78 -0
  348. package/scripts/test-in-container.sh +31 -9
  349. package/templates/clean-state-checklist.md +3 -3
  350. package/templates/sprint-contract.md +2 -2
  351. package/bizar-dash/.bizar/activity.log +0 -3
  352. package/bizar-dash/.omx/logs/omx-2026-07-07.jsonl +0 -1
  353. package/bizar-dash/.omx/state/session.json +0 -10
  354. package/bizar-dash/bizar-design/EXPLANATION.md +0 -307
  355. package/bizar-dash/bizar-design/INSTRUCTIONS.md +0 -149
  356. package/bizar-dash/bizar-design/canvas.html +0 -281
  357. package/bizar-dash/bizar-design/canvas.html.artifact.json +0 -19
  358. package/bizar-dash/bizar-design/components.css +0 -1665
  359. package/bizar-dash/bizar-design/components.html +0 -557
  360. package/bizar-dash/bizar-design/components.html.artifact.json +0 -19
  361. package/bizar-dash/bizar-design/desktop/agents.html +0 -74
  362. package/bizar-dash/bizar-design/desktop/agents.html.artifact.json +0 -19
  363. package/bizar-dash/bizar-design/desktop/memory.html +0 -75
  364. package/bizar-dash/bizar-design/desktop/memory.html.artifact.json +0 -19
  365. package/bizar-dash/bizar-design/desktop/metrics.html +0 -63
  366. package/bizar-dash/bizar-design/desktop/metrics.html.artifact.json +0 -19
  367. package/bizar-dash/bizar-design/desktop/overview.html +0 -95
  368. package/bizar-dash/bizar-design/desktop/overview.html.artifact.json +0 -19
  369. package/bizar-dash/bizar-design/desktop/settings.html +0 -70
  370. package/bizar-dash/bizar-design/desktop/settings.html.artifact.json +0 -19
  371. package/bizar-dash/bizar-design/icons.svg +0 -44
  372. package/bizar-dash/bizar-design/index.html +0 -192
  373. package/bizar-dash/bizar-design/index.html.artifact.json +0 -19
  374. package/bizar-dash/bizar-design/mobile/agents.html +0 -29
  375. package/bizar-dash/bizar-design/mobile/agents.html.artifact.json +0 -19
  376. package/bizar-dash/bizar-design/mobile/memory.html +0 -28
  377. package/bizar-dash/bizar-design/mobile/memory.html.artifact.json +0 -19
  378. package/bizar-dash/bizar-design/mobile/metrics.html +0 -29
  379. package/bizar-dash/bizar-design/mobile/metrics.html.artifact.json +0 -19
  380. package/bizar-dash/bizar-design/mobile/overview.html +0 -33
  381. package/bizar-dash/bizar-design/mobile/overview.html.artifact.json +0 -19
  382. package/bizar-dash/bizar-design/mobile/settings.html +0 -28
  383. package/bizar-dash/bizar-design/mobile/settings.html.artifact.json +0 -19
  384. package/bizar-dash/bizar-design/prototype.js +0 -114
  385. package/bizar-dash/bizar-design/tokens.css +0 -106
  386. package/bizar-dash/dist/assets/MobileChat-BnKN_Ks_.js +0 -1
  387. package/bizar-dash/dist/assets/MobileSettings-DjCPxC-Q.js +0 -1
  388. package/bizar-dash/dist/assets/icons-Do5N2jmX.js.map +0 -1
  389. package/bizar-dash/dist/assets/main-DYiZqMrn.js +0 -18
  390. package/bizar-dash/dist/assets/main-DYiZqMrn.js.map +0 -1
  391. package/bizar-dash/dist/assets/main-ietCEg_R.css +0 -1
  392. package/bizar-dash/dist/assets/markdown-C6mXtQxD.js +0 -1
  393. package/bizar-dash/dist/assets/mobile-CMHqtLV2.js +0 -1
  394. package/bizar-dash/dist/assets/mobile-layout-3jIhHX_p.js +0 -2
  395. package/bizar-dash/dist/assets/mobile-layout-3jIhHX_p.js.map +0 -1
  396. package/bizar-dash/dist/assets/react-vendor-Dn4wqh4Z.js +0 -40
  397. package/bizar-dash/dist/assets/react-vendor-Dn4wqh4Z.js.map +0 -1
  398. package/bizar-dash/dist/assets/useSlashCommands-DtITw8Xv.js +0 -2
  399. package/bizar-dash/dist/assets/useSlashCommands-DtITw8Xv.js.map +0 -1
  400. package/bizar-dash/dist/assets/vendor-CeHGtduv.js +0 -29
  401. package/bizar-dash/dist/assets/vendor-CeHGtduv.js.map +0 -1
  402. package/bizar-dash/node_modules/.package-lock.json +0 -6
  403. package/bizar-dash/package-lock.json +0 -6
  404. package/bizar-dash/src/server/cline-sdk.mjs +0 -132
  405. package/bizar-dash/src/server/routes/cline-session-detail.mjs +0 -559
  406. package/bizar-dash/src/server/routes/cline-sessions.mjs +0 -291
  407. package/cli/commands/cline-cmd.mjs +0 -289
  408. package/cli/commands/validate.test.mjs +0 -379
  409. package/cli/doctor.test.mjs +0 -350
  410. package/config/cline.json.template +0 -342
  411. package/packages/sdk/src/client.ts +0 -188
  412. package/packages/sdk/src/cline-events.ts +0 -134
  413. package/packages/sdk/src/cline-types.ts +0 -66
  414. package/packages/sdk/src/cline.ts +0 -339
  415. package/packages/sdk/src/errors.ts +0 -129
  416. package/packages/sdk/src/events.ts +0 -153
  417. package/packages/sdk/src/types.ts +0 -176
  418. package/packages/sdk/tests/client.test.ts +0 -217
  419. package/packages/sdk/tests/errors.test.ts +0 -108
  420. package/packages/sdk/tests/events.test.ts +0 -139
  421. package/packages/sdk/tests/fixtures/fetch-mock.ts +0 -152
  422. package/packages/sdk/tests/fixtures/sse-mock.ts +0 -30
  423. package/plugins/bizar/ARCHITECTURE.md +0 -142
  424. package/plugins/bizar/CONSTRAINTS.md +0 -67
  425. package/plugins/bizar/LICENSE +0 -21
  426. package/plugins/bizar/README.md +0 -448
  427. package/plugins/bizar/index.ts +0 -925
  428. package/plugins/bizar/package.json +0 -39
  429. package/plugins/bizar/scripts/check-forbidden-imports.sh +0 -33
  430. package/plugins/bizar/src/background-state.ts +0 -641
  431. package/plugins/bizar/src/background.ts +0 -1806
  432. package/plugins/bizar/src/cline-runner.ts +0 -203
  433. package/plugins/bizar/src/clineruntime.ts +0 -227
  434. package/plugins/bizar/src/commands-impl.ts +0 -151
  435. package/plugins/bizar/src/commands.ts +0 -1799
  436. package/plugins/bizar/src/compaction.d.mts +0 -48
  437. package/plugins/bizar/src/compaction.mjs +0 -192
  438. package/plugins/bizar/src/dashboard-client.ts +0 -233
  439. package/plugins/bizar/src/event-stream.ts +0 -606
  440. package/plugins/bizar/src/fingerprint.ts +0 -120
  441. package/plugins/bizar/src/handoff.ts +0 -79
  442. package/plugins/bizar/src/hooks/memory-flush-on-compact.ts +0 -123
  443. package/plugins/bizar/src/hooks/memory-inject.ts +0 -247
  444. package/plugins/bizar/src/hooks/memory-write-on-end.ts +0 -188
  445. package/plugins/bizar/src/hooks/skill-curator.ts +0 -180
  446. package/plugins/bizar/src/http-client.ts +0 -467
  447. package/plugins/bizar/src/key-rotation.ts +0 -218
  448. package/plugins/bizar/src/logger.ts +0 -144
  449. package/plugins/bizar/src/loop-engineering.ts +0 -241
  450. package/plugins/bizar/src/loop.ts +0 -176
  451. package/plugins/bizar/src/mistake-recovery.ts +0 -98
  452. package/plugins/bizar/src/odin.ts +0 -227
  453. package/plugins/bizar/src/options.ts +0 -470
  454. package/plugins/bizar/src/plan-fs.ts +0 -323
  455. package/plugins/bizar/src/reasoning-clean.ts +0 -454
  456. package/plugins/bizar/src/report.ts +0 -178
  457. package/plugins/bizar/src/research-prompt.ts +0 -35
  458. package/plugins/bizar/src/serve-info.ts +0 -228
  459. package/plugins/bizar/src/serve.ts +0 -496
  460. package/plugins/bizar/src/settings.ts +0 -349
  461. package/plugins/bizar/src/state.ts +0 -298
  462. package/plugins/bizar/src/tool-discipline.ts +0 -105
  463. package/plugins/bizar/src/tools/agent-browser.ts +0 -315
  464. package/plugins/bizar/src/tools/bg-collect.ts +0 -131
  465. package/plugins/bizar/src/tools/bg-get-comments.ts +0 -266
  466. package/plugins/bizar/src/tools/bg-kill.ts +0 -116
  467. package/plugins/bizar/src/tools/bg-pause.ts +0 -99
  468. package/plugins/bizar/src/tools/bg-report-progress.ts +0 -115
  469. package/plugins/bizar/src/tools/bg-resume.ts +0 -94
  470. package/plugins/bizar/src/tools/bg-send-message.ts +0 -223
  471. package/plugins/bizar/src/tools/bg-spawn.ts +0 -502
  472. package/plugins/bizar/src/tools/bg-status.ts +0 -130
  473. package/plugins/bizar/src/tools/graph-query.ts +0 -278
  474. package/plugins/bizar/src/tools/loop-engineering.ts +0 -193
  475. package/plugins/bizar/src/tools/memory-list.ts +0 -43
  476. package/plugins/bizar/src/tools/memory-read.ts +0 -69
  477. package/plugins/bizar/src/tools/memory-search.ts +0 -47
  478. package/plugins/bizar/src/tools/memory-write.ts +0 -54
  479. package/plugins/bizar/src/tools/open-kb.ts +0 -198
  480. package/plugins/bizar/src/tools/plan-action.ts +0 -785
  481. package/plugins/bizar/src/tools/read-glyph-feedback.ts +0 -191
  482. package/plugins/bizar/src/tools/sandbox.ts +0 -232
  483. package/plugins/bizar/src/tools/team-spawn.ts +0 -73
  484. package/plugins/bizar/src/tools/team-status.ts +0 -76
  485. package/plugins/bizar/src/tools/wait-for-feedback.ts +0 -415
  486. package/plugins/bizar/src/trajectory.ts +0 -104
  487. package/plugins/bizar/tests/README.md +0 -99
  488. package/plugins/bizar/tests/attach-handler-bug.test.ts +0 -169
  489. package/plugins/bizar/tests/background-state.test.ts +0 -277
  490. package/plugins/bizar/tests/background.test.ts +0 -402
  491. package/plugins/bizar/tests/block.test.ts +0 -195
  492. package/plugins/bizar/tests/canonical-key-order.test.ts +0 -75
  493. package/plugins/bizar/tests/clineruntime-config.test.ts +0 -283
  494. package/plugins/bizar/tests/commands-impl.test.ts +0 -316
  495. package/plugins/bizar/tests/commands.test.ts +0 -584
  496. package/plugins/bizar/tests/compaction.test.ts +0 -264
  497. package/plugins/bizar/tests/config.test.ts +0 -128
  498. package/plugins/bizar/tests/dashboard-client.test.ts +0 -159
  499. package/plugins/bizar/tests/dispose.test.ts +0 -336
  500. package/plugins/bizar/tests/event-stream.test.ts +0 -409
  501. package/plugins/bizar/tests/event.test.ts +0 -262
  502. package/plugins/bizar/tests/fingerprint.test.ts +0 -190
  503. package/plugins/bizar/tests/http-client.test.ts +0 -404
  504. package/plugins/bizar/tests/init-helpers.test.ts +0 -203
  505. package/plugins/bizar/tests/integration/slash-command.test.ts +0 -349
  506. package/plugins/bizar/tests/integration/tool-routing.test.ts +0 -98
  507. package/plugins/bizar/tests/key-rotation.test.ts +0 -396
  508. package/plugins/bizar/tests/loop-engineering.test.ts +0 -168
  509. package/plugins/bizar/tests/loop.test.ts +0 -397
  510. package/plugins/bizar/tests/memory-write-on-end.test.ts +0 -92
  511. package/plugins/bizar/tests/mistake-recovery.test.ts +0 -116
  512. package/plugins/bizar/tests/odin.test.ts +0 -125
  513. package/plugins/bizar/tests/options.test.ts +0 -329
  514. package/plugins/bizar/tests/reasoning-clean.test.ts +0 -422
  515. package/plugins/bizar/tests/safety.test.ts +0 -281
  516. package/plugins/bizar/tests/serve.test.ts +0 -339
  517. package/plugins/bizar/tests/settings.test.ts +0 -351
  518. package/plugins/bizar/tests/stall-think.test.ts +0 -750
  519. package/plugins/bizar/tests/state.test.ts +0 -276
  520. package/plugins/bizar/tests/tool-discipline.test.ts +0 -77
  521. package/plugins/bizar/tests/tools/agent-browser.test.ts +0 -98
  522. package/plugins/bizar/tests/tools/bg-collect.test.ts +0 -337
  523. package/plugins/bizar/tests/tools/bg-get-comments.test.ts +0 -485
  524. package/plugins/bizar/tests/tools/bg-kill.test.ts +0 -235
  525. package/plugins/bizar/tests/tools/bg-pause.test.ts +0 -61
  526. package/plugins/bizar/tests/tools/bg-report-progress.test.ts +0 -79
  527. package/plugins/bizar/tests/tools/bg-resume.test.ts +0 -40
  528. package/plugins/bizar/tests/tools/bg-send-message.test.ts +0 -116
  529. package/plugins/bizar/tests/tools/bg-spawn-delegation.test.ts +0 -147
  530. package/plugins/bizar/tests/tools/bg-spawn-http.test.ts +0 -233
  531. package/plugins/bizar/tests/tools/bg-spawn.test.ts +0 -311
  532. package/plugins/bizar/tests/tools/bg-status.test.ts +0 -217
  533. package/plugins/bizar/tests/tools/cline-runner.test.ts +0 -115
  534. package/plugins/bizar/tests/tools/plan-action.test.ts +0 -599
  535. package/plugins/bizar/tests/tools/read-glyph-feedback.test.ts +0 -253
  536. package/plugins/bizar/tests/tools/sandbox.test.ts +0 -117
  537. package/plugins/bizar/tests/tools/wait-for-feedback.test.ts +0 -390
  538. package/plugins/bizar/tests/update-deadlock.test.ts +0 -151
  539. package/plugins/bizar/tsconfig.json +0 -29
  540. package/scripts/mirror-agents-md.sh +0 -69
@@ -0,0 +1,67 @@
1
+ // tests/communication-log.test.tsx — F-036 Goal Planner UI.
2
+ // Renders the CommunicationLog component with a mocked Ws class so
3
+ // we can drive agent:* events through the handler without opening a
4
+ // real socket.
5
+ import { describe, it, expect, beforeEach, vi } from 'vitest';
6
+ import { render, screen, act } from '@testing-library/react';
7
+ import { ToastProvider } from '../src/web/components/Toast';
8
+ import { CommunicationLog } from '../src/web/components/agents/CommunicationLog';
9
+
10
+ type Handler = (msg: { type: string; ts?: number } & Record<string, unknown>) => void;
11
+
12
+ let registeredHandler: Handler | null = null;
13
+
14
+ vi.mock('../src/web/lib/ws', () => ({
15
+ Ws: class {
16
+ constructor() {}
17
+ on(handler: Handler) {
18
+ registeredHandler = handler;
19
+ return () => { registeredHandler = null; };
20
+ }
21
+ close() {}
22
+ },
23
+ }));
24
+
25
+ function wrap(node: React.ReactNode) {
26
+ return <ToastProvider>{node}</ToastProvider>;
27
+ }
28
+
29
+ function emit(type: string, payload: Record<string, unknown> = {}) {
30
+ if (!registeredHandler) throw new Error('no ws handler registered');
31
+ act(() => {
32
+ registeredHandler!({ type, ts: Date.now(), ...payload });
33
+ });
34
+ }
35
+
36
+ beforeEach(() => {
37
+ registeredHandler = null;
38
+ });
39
+
40
+ describe('CommunicationLog', () => {
41
+ it('renders empty state when no messages have arrived', () => {
42
+ render(wrap(<CommunicationLog />));
43
+ expect(screen.getByTestId('communication-log-empty')).toBeInTheDocument();
44
+ expect(screen.getByTestId('communication-log-count').textContent?.trim()).toBe('0');
45
+ });
46
+
47
+ it('renders a single agent:status message', () => {
48
+ render(wrap(<CommunicationLog />));
49
+ emit('agent:status', { agent: { name: 'Odin', status: 'working' } });
50
+ expect(screen.getByTestId('communication-log-count').textContent?.trim()).toBe('1');
51
+ const rows = screen.getAllByTestId('communication-log-row');
52
+ expect(rows.length).toBe(1);
53
+ expect(rows[0].getAttribute('data-kind')).toBe('status');
54
+ });
55
+
56
+ it('renders multiple agent:* messages in reverse order', () => {
57
+ render(wrap(<CommunicationLog />));
58
+ emit('agent:status', { agent: { name: 'Odin', status: 'working' } });
59
+ emit('agent:restarted', { agent: { name: 'Thor' } });
60
+ emit('agent:message', { message: { from: 'Thor', to: 'Odin', text: 'done' } });
61
+ const rows = screen.getAllByTestId('communication-log-row');
62
+ expect(rows.length).toBe(3);
63
+ expect(rows[0].getAttribute('data-kind')).toBe('message');
64
+ expect(rows[1].getAttribute('data-kind')).toBe('restarted');
65
+ expect(rows[2].getAttribute('data-kind')).toBe('status');
66
+ });
67
+ });
@@ -0,0 +1,40 @@
1
+ // tests/dep-graph.test.tsx — F-036 Goal Planner UI.
2
+ // Renders the DependencyGraph component with and without a plan.
3
+ import { describe, it, expect } from 'vitest';
4
+ import { render, screen } from '@testing-library/react';
5
+ import { DependencyGraph } from '../src/web/components/agents/DependencyGraph';
6
+ import type { Plan } from '../src/web/lib/goapPlanner';
7
+
8
+ function makePlan(): Plan {
9
+ return {
10
+ id: 'plan_x',
11
+ goal: 'Build it, test it, deploy it.',
12
+ steps: [
13
+ { id: 's1', action: 'build', title: 'Build the artifact', agent: 'Thor', description: 'Construct the artifact end-to-end.', effects: ['artifact_built'], deps: [], status: 'pending', estimatedCost: 3, estimatedDurationMs: 120000 },
14
+ { id: 's2', action: 'test', title: 'Run the tests', agent: 'Forseti', description: 'Run the test suite.', effects: ['tests_passing'], deps: ['s1'], status: 'pending', estimatedCost: 2, estimatedDurationMs: 60000 },
15
+ { id: 's3', action: 'deploy', title: 'Deploy to production', agent: 'Heimdall', description: 'Promote the artifact to production.', effects: ['deployed'], deps: ['s2'], status: 'pending', estimatedCost: 2, estimatedDurationMs: 60000 },
16
+ ],
17
+ totalCost: 7,
18
+ totalDurationMs: 240000,
19
+ goalEffects: ['artifact_built', 'tests_passing', 'deployed'],
20
+ };
21
+ }
22
+
23
+ describe('DependencyGraph', () => {
24
+ it('renders an empty-state card when no plan is supplied', () => {
25
+ render(<DependencyGraph plan={null} />);
26
+ expect(screen.getByTestId('dep-graph')).toBeInTheDocument();
27
+ expect(screen.getByText(/Submit a goal/i)).toBeInTheDocument();
28
+ });
29
+
30
+ it('renders the canvas when a plan is supplied', () => {
31
+ render(<DependencyGraph plan={makePlan()} />);
32
+ expect(screen.getByTestId('dep-graph-canvas')).toBeInTheDocument();
33
+ });
34
+
35
+ it('renders three step nodes when a three-step plan is supplied', () => {
36
+ render(<DependencyGraph plan={makePlan()} />);
37
+ const nodes = document.querySelectorAll('.dep-node');
38
+ expect(nodes.length).toBe(3);
39
+ });
40
+ });
@@ -0,0 +1,61 @@
1
+ // tests/event-log.test.tsx — F-036 Goal Planner UI.
2
+ // Renders the RealTimeEventLog with a mocked Ws class.
3
+ import { describe, it, expect, beforeEach, vi } from 'vitest';
4
+ import { render, screen, act } from '@testing-library/react';
5
+ import { ToastProvider } from '../src/web/components/Toast';
6
+ import { RealTimeEventLog } from '../src/web/components/agents/RealTimeEventLog';
7
+
8
+ type Handler = (msg: { type: string; ts?: number } & Record<string, unknown>) => void;
9
+ let registeredHandler: Handler | null = null;
10
+
11
+ vi.mock('../src/web/lib/ws', () => ({
12
+ Ws: class {
13
+ constructor() {}
14
+ on(handler: Handler) {
15
+ registeredHandler = handler;
16
+ return () => { registeredHandler = null; };
17
+ }
18
+ close() {}
19
+ },
20
+ }));
21
+
22
+ function wrap(node: React.ReactNode) {
23
+ return <ToastProvider>{node}</ToastProvider>;
24
+ }
25
+
26
+ function emit(type: string, payload: Record<string, unknown> = {}) {
27
+ if (!registeredHandler) throw new Error('no ws handler registered');
28
+ act(() => {
29
+ registeredHandler!({ type, ts: Date.now(), ...payload });
30
+ });
31
+ }
32
+
33
+ beforeEach(() => {
34
+ registeredHandler = null;
35
+ });
36
+
37
+ describe('RealTimeEventLog', () => {
38
+ it('renders empty state when no events arrived', () => {
39
+ render(wrap(<RealTimeEventLog />));
40
+ expect(screen.getByTestId('event-log-empty')).toBeInTheDocument();
41
+ expect(screen.getByTestId('event-log-count').textContent?.trim()).toBe('0');
42
+ });
43
+
44
+ it('renders a single info event', () => {
45
+ render(wrap(<RealTimeEventLog />));
46
+ emit('tasks:change', { task: { id: 't1' } });
47
+ const rows = screen.getAllByTestId('event-log-row');
48
+ expect(rows.length).toBe(1);
49
+ expect(rows[0].getAttribute('data-severity')).toBe('info');
50
+ });
51
+
52
+ it('renders multiple events with severity coding', () => {
53
+ render(wrap(<RealTimeEventLog />));
54
+ emit('task:progress', { taskId: 't1', progress: 50 });
55
+ emit('agent:stuck', { agents: [{ name: 'Odin' }] });
56
+ emit('goal:planned', { planId: 'p1' });
57
+ const rows = screen.getAllByTestId('event-log-row');
58
+ expect(rows.length).toBe(3);
59
+ expect(screen.getByTestId('event-log-count').textContent?.trim()).toBe('3');
60
+ });
61
+ });
@@ -0,0 +1,72 @@
1
+ // tests/goal-input.test.tsx — F-036 Goal Planner UI.
2
+ // Renders the GoalInput textarea + submit, mocks the API client,
3
+ // and verifies the planner endpoint is called with the trimmed
4
+ // goal text.
5
+ import { describe, it, expect, beforeEach, vi } from 'vitest';
6
+ import { render, screen, waitFor } from '@testing-library/react';
7
+ import userEvent from '@testing-library/user-event';
8
+ import { ToastProvider } from '../src/web/components/Toast';
9
+ import { GoalInput } from '../src/web/components/goals/GoalInput';
10
+ import type { Plan } from '../src/web/lib/goapPlanner';
11
+
12
+ const mockApiPost = vi.fn();
13
+
14
+ vi.mock('../src/web/lib/api', () => ({
15
+ api: {
16
+ post: (...args: unknown[]) => mockApiPost(...args),
17
+ },
18
+ }));
19
+
20
+ function makePlan(): Plan {
21
+ return {
22
+ id: 'plan_test',
23
+ goal: 'Build it',
24
+ steps: [
25
+ { id: 's1', action: 'build', title: 'Build', agent: 'Thor', description: 'Build.', effects: ['artifact_built'], deps: [], status: 'pending', estimatedCost: 3, estimatedDurationMs: 120000 },
26
+ ],
27
+ totalCost: 3,
28
+ totalDurationMs: 120000,
29
+ goalEffects: ['artifact_built'],
30
+ };
31
+ }
32
+
33
+ function wrap(node: React.ReactNode) {
34
+ return <ToastProvider>{node}</ToastProvider>;
35
+ }
36
+
37
+ beforeEach(() => {
38
+ mockApiPost.mockReset();
39
+ mockApiPost.mockResolvedValue(makePlan());
40
+ });
41
+
42
+ describe('GoalInput', () => {
43
+ it('renders a textarea and a submit button', () => {
44
+ render(wrap(<GoalInput />));
45
+ expect(screen.getByTestId('goal-input-textarea')).toBeInTheDocument();
46
+ expect(screen.getByTestId('goal-input-submit')).toBeInTheDocument();
47
+ expect(screen.getByTestId('goal-input-counter').textContent).toMatch(/0 \/ 4000/);
48
+ });
49
+
50
+ it('submits the trimmed goal to the planner endpoint and emits the plan', async () => {
51
+ const user = userEvent.setup();
52
+ const onPlan = vi.fn();
53
+ render(wrap(<GoalInput onPlan={onPlan} />));
54
+ const textarea = screen.getByTestId('goal-input-textarea');
55
+ await user.type(textarea, ' Research quantum. ');
56
+ const submit = screen.getByTestId('goal-input-submit');
57
+ await user.click(submit);
58
+ await waitFor(() => expect(mockApiPost).toHaveBeenCalledTimes(1));
59
+ expect(mockApiPost).toHaveBeenCalledWith('/goal-planner/plan', { goal: 'Research quantum.' });
60
+ await waitFor(() => expect(onPlan).toHaveBeenCalledTimes(1));
61
+ expect(onPlan.mock.calls[0][0].id).toBe('plan_test');
62
+ });
63
+
64
+ it('does not submit when the textarea is empty', async () => {
65
+ const user = userEvent.setup();
66
+ render(wrap(<GoalInput />));
67
+ const submit = screen.getByTestId('goal-input-submit');
68
+ expect(submit).toBeDisabled();
69
+ await user.click(submit).catch(() => undefined);
70
+ expect(mockApiPost).not.toHaveBeenCalled();
71
+ });
72
+ });
@@ -0,0 +1,68 @@
1
+ // tests/goap-planner.test.ts — F-036 Goal Planner UI.
2
+ // Verifies the pure-TS A* planner: clause split, verb mapping,
3
+ // dependency link, total cost rollup.
4
+ import { describe, it, expect } from 'vitest';
5
+ import {
6
+ planGoal,
7
+ splitGoalClauses,
8
+ extractVerb,
9
+ clauseToAction,
10
+ planDependencyEdges,
11
+ type Plan,
12
+ } from '../src/web/lib/goapPlanner';
13
+
14
+ describe('goapPlanner — clauses', () => {
15
+ it('splits a multi-clause goal on sentence boundaries', () => {
16
+ const clauses = splitGoalClauses('Research quantum. Then build a demo. Finally deploy it.');
17
+ expect(clauses.length).toBe(3);
18
+ });
19
+
20
+ it('extracts the leading verb after stripping polite prefixes', () => {
21
+ expect(extractVerb('Research the topic')).toBe('research');
22
+ expect(extractVerb('Please build it')).toBe('build');
23
+ expect(extractVerb('We should test the change')).toBe('test');
24
+ });
25
+
26
+ it('maps known verbs to action templates with effects', () => {
27
+ const t = clauseToAction('Deploy the artifact');
28
+ expect(t.name).toBe('deploy');
29
+ expect(t.effect).toBe('deployed');
30
+ });
31
+ });
32
+
33
+ describe('goapPlanner — planGoal', () => {
34
+ it('produces a plan with at least one step for a simple goal', () => {
35
+ const plan = planGoal('Research quantum computing.');
36
+ expect(plan.id.length).toBeGreaterThan(0);
37
+ expect(plan.goal).toBe('Research quantum computing.');
38
+ expect(plan.steps.length).toBeGreaterThan(0);
39
+ expect(plan.totalCost).toBeGreaterThan(0);
40
+ expect(plan.totalDurationMs).toBeGreaterThan(0);
41
+ });
42
+
43
+ it('links dep steps via effect-to-id resolution', () => {
44
+ const plan = planGoal('Design, build, test, and deploy the API.');
45
+ // Build depends on design_drafted (from the design step).
46
+ const build = plan.steps.find((s) => s.action === 'build' || s.action === 'implement');
47
+ expect(build).toBeDefined();
48
+ expect(build!.deps.length).toBeGreaterThan(0);
49
+ });
50
+
51
+ it('returns a plan whose dependency edges cover the dep list', () => {
52
+ const plan: Plan = planGoal('Plan it, build it, test it.');
53
+ const edges = planDependencyEdges(plan);
54
+ expect(edges.length).toBeGreaterThan(0);
55
+ // Every edge must reference a known step id.
56
+ const ids = new Set(plan.steps.map((s) => s.id));
57
+ for (const e of edges) {
58
+ expect(ids.has(e.from)).toBe(true);
59
+ expect(ids.has(e.to)).toBe(true);
60
+ }
61
+ });
62
+
63
+ it('caps step count at 8 to keep A* tractable', () => {
64
+ const goal = 'Research. Investigate. Analyze. Plan. Design. Architect. Build. Implement. Create. Add. Test. Review. Document. Deploy. Commit. Publish.';
65
+ const plan = planGoal(goal);
66
+ expect(plan.steps.length).toBeLessThanOrEqual(8);
67
+ });
68
+ });
@@ -0,0 +1,59 @@
1
+ // tests/quality-gates.test.tsx — F-036 Goal Planner UI.
2
+ // Renders the QualityGates panel with empty, single, and multi
3
+ // metrics so the pass/warn/fail logic is observable.
4
+ import { describe, it, expect } from 'vitest';
5
+ import { render, screen } from '@testing-library/react';
6
+ import { QualityGates } from '../src/web/components/agents/QualityGates';
7
+
8
+ const baseMetrics = {
9
+ compileCheck: false,
10
+ testCoverage: 0,
11
+ archScore: 0,
12
+ evidencePresent: false,
13
+ };
14
+
15
+ describe('QualityGates', () => {
16
+ it('renders four gate rows when metrics are empty', () => {
17
+ render(<QualityGates plan={null} metrics={baseMetrics} />);
18
+ const rows = screen.getAllByTestId('quality-gates-row');
19
+ expect(rows.length).toBe(4);
20
+ // None of the gates should be passing on a fresh install.
21
+ expect(rows.every((r) => r.getAttribute('data-status') !== 'passed')).toBe(true);
22
+ });
23
+
24
+ it('renders all gates as passing when metrics are at threshold', () => {
25
+ render(
26
+ <QualityGates
27
+ plan={null}
28
+ metrics={{
29
+ compileCheck: true,
30
+ testCoverage: 85,
31
+ archScore: 92,
32
+ evidencePresent: true,
33
+ }}
34
+ />,
35
+ );
36
+ const rows = screen.getAllByTestId('quality-gates-row');
37
+ expect(rows.length).toBe(4);
38
+ expect(rows.every((r) => r.getAttribute('data-status') === 'passed')).toBe(true);
39
+ });
40
+
41
+ it('renders mixed pass/warn/fail when metrics are heterogeneous', () => {
42
+ render(
43
+ <QualityGates
44
+ plan={null}
45
+ metrics={{
46
+ compileCheck: true,
47
+ testCoverage: 65, // warning
48
+ archScore: 50, // failed
49
+ evidencePresent: false,
50
+ }}
51
+ />,
52
+ );
53
+ const rows = screen.getAllByTestId('quality-gates-row');
54
+ const statuses = rows.map((r) => r.getAttribute('data-status'));
55
+ expect(statuses).toContain('passed');
56
+ expect(statuses).toContain('warning');
57
+ expect(statuses).toContain('failed');
58
+ });
59
+ });
@@ -1,6 +1,36 @@
1
1
  import '@testing-library/jest-dom/vitest';
2
2
  import { cleanup } from '@testing-library/react';
3
- import { afterEach } from 'vitest';
3
+ import { afterEach, vi } from 'vitest';
4
+
5
+ // jsdom doesn't ship ResizeObserver, but @xyflow/react (and other
6
+ // layout libs) expect it to be present. Stub a no-op so React renders
7
+ // don't crash when a component mounts a graph.
8
+ if (typeof globalThis.ResizeObserver === 'undefined') {
9
+ globalThis.ResizeObserver = class {
10
+ observe() {}
11
+ unobserve() {}
12
+ disconnect() {}
13
+ } as unknown as typeof ResizeObserver;
14
+ }
15
+
16
+ // Similarly for matchMedia — used by some component libs that the
17
+ // dashboard pulls in. jsdom ships an empty stub but it lacks the
18
+ // addEventListener/removeEventListener pair that React 18 expects.
19
+ if (typeof window !== 'undefined' && !window.matchMedia) {
20
+ Object.defineProperty(window, 'matchMedia', {
21
+ writable: true,
22
+ value: vi.fn().mockImplementation((query: string) => ({
23
+ matches: false,
24
+ media: query,
25
+ onchange: null,
26
+ addListener: vi.fn(),
27
+ removeListener: vi.fn(),
28
+ addEventListener: vi.fn(),
29
+ removeEventListener: vi.fn(),
30
+ dispatchEvent: vi.fn(),
31
+ })),
32
+ });
33
+ }
4
34
 
5
35
  afterEach(() => {
6
36
  cleanup();
@@ -0,0 +1,50 @@
1
+ import { describe, it, expect, vi } from 'vitest';
2
+ import { render, screen } from '@testing-library/react';
3
+ import userEvent from '@testing-library/user-event';
4
+ import { Button } from '../../../src/web/ui/controls/Button';
5
+
6
+ describe('Button', () => {
7
+ it('renders its children', () => {
8
+ render(<Button>Click me</Button>);
9
+ expect(screen.getByRole('button', { name: 'Click me' })).toBeInTheDocument();
10
+ });
11
+
12
+ it('fires onClick when clicked', async () => {
13
+ const onClick = vi.fn();
14
+ const user = userEvent.setup();
15
+ render(<Button onClick={onClick}>Go</Button>);
16
+ await user.click(screen.getByRole('button'));
17
+ expect(onClick).toHaveBeenCalledTimes(1);
18
+ });
19
+
20
+ it('is disabled when disabled prop is set', () => {
21
+ render(<Button disabled>Off</Button>);
22
+ expect(screen.getByRole('button')).toBeDisabled();
23
+ });
24
+
25
+ it('shows the spinner and disables clicks when loading', async () => {
26
+ const onClick = vi.fn();
27
+ const user = userEvent.setup();
28
+ render(<Button loading onClick={onClick}>Saving</Button>);
29
+ const btn = screen.getByRole('button');
30
+ expect(btn).toBeDisabled();
31
+ expect(btn.querySelector('.btn-spinner')).toBeInTheDocument();
32
+ await user.click(btn);
33
+ expect(onClick).not.toHaveBeenCalled();
34
+ });
35
+
36
+ it('applies variant and size classes', () => {
37
+ const { container } = render(
38
+ <Button variant="primary" size="lg">
39
+ Primary
40
+ </Button>,
41
+ );
42
+ const btn = container.firstChild as HTMLElement;
43
+ expect(btn).toHaveClass('btn-primary', 'btn-size-lg');
44
+ });
45
+
46
+ it('renders as full-width when fullWidth is true', () => {
47
+ render(<Button fullWidth>Wide</Button>);
48
+ expect(screen.getByRole('button')).toHaveClass('btn-full');
49
+ });
50
+ });
@@ -0,0 +1,44 @@
1
+ import { describe, it, expect, vi } from 'vitest';
2
+ import { render, screen } from '@testing-library/react';
3
+ import userEvent from '@testing-library/user-event';
4
+ import { Checkbox } from '../../../src/web/ui/controls/Checkbox';
5
+
6
+ describe('Checkbox', () => {
7
+ it('renders with the supplied label', () => {
8
+ render(<Checkbox checked={false} onChange={() => {}} label="Accept" />);
9
+ expect(screen.getByRole('checkbox', { name: 'Accept' })).toBeInTheDocument();
10
+ });
11
+
12
+ it('fires onChange(true) when clicked', async () => {
13
+ const onChange = vi.fn();
14
+ const user = userEvent.setup();
15
+ render(<Checkbox checked={false} onChange={onChange} label="X" />);
16
+ await user.click(screen.getByRole('checkbox'));
17
+ expect(onChange).toHaveBeenCalledWith(true);
18
+ });
19
+
20
+ it('toggles checked visually when checked is true', () => {
21
+ render(<Checkbox checked onChange={() => {}} label="X" data-testid="c" />);
22
+ expect(screen.getByTestId('c')).toHaveClass('checkbox-checked');
23
+ });
24
+
25
+ it('renders indeterminate state class', () => {
26
+ render(
27
+ <Checkbox
28
+ checked={false}
29
+ indeterminate
30
+ onChange={() => {}}
31
+ label="X"
32
+ data-testid="c"
33
+ />,
34
+ );
35
+ expect(screen.getByTestId('c')).toHaveClass('checkbox-indeterminate');
36
+ });
37
+
38
+ it('is disabled when disabled is set', () => {
39
+ render(
40
+ <Checkbox checked={false} onChange={() => {}} label="X" disabled />,
41
+ );
42
+ expect(screen.getByRole('checkbox')).toBeDisabled();
43
+ });
44
+ });
@@ -0,0 +1,37 @@
1
+ import { describe, it, expect, vi } from 'vitest';
2
+ import { render, screen } from '@testing-library/react';
3
+ import userEvent from '@testing-library/user-event';
4
+ import { Star } from 'lucide-react';
5
+ import { IconButton } from '../../../src/web/ui/controls/IconButton';
6
+
7
+ describe('IconButton', () => {
8
+ it('renders an accessible button with the supplied label', () => {
9
+ render(<IconButton aria-label="Star" icon={<Star data-testid="i" />} />);
10
+ expect(screen.getByRole('button', { name: 'Star' })).toBeInTheDocument();
11
+ });
12
+
13
+ it('forwards onClick', async () => {
14
+ const onClick = vi.fn();
15
+ const user = userEvent.setup();
16
+ render(
17
+ <IconButton aria-label="X" icon={<Star />} onClick={onClick} />,
18
+ );
19
+ await user.click(screen.getByRole('button'));
20
+ expect(onClick).toHaveBeenCalledTimes(1);
21
+ });
22
+
23
+ it('applies variant + size classes', () => {
24
+ const { container } = render(
25
+ <IconButton aria-label="X" icon={<Star />} variant="danger" size="lg" />,
26
+ );
27
+ const btn = container.firstChild as HTMLElement;
28
+ expect(btn).toHaveClass('icon-btn-danger', 'icon-btn-size-lg');
29
+ });
30
+
31
+ it('is disabled when disabled is set', () => {
32
+ render(
33
+ <IconButton aria-label="X" icon={<Star />} disabled />,
34
+ );
35
+ expect(screen.getByRole('button')).toBeDisabled();
36
+ });
37
+ });
@@ -0,0 +1,39 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { render, screen } from '@testing-library/react';
3
+ import { Kbd } from '../../../src/web/ui/controls/Kbd';
4
+
5
+ describe('Kbd', () => {
6
+ it('renders its children as text content', () => {
7
+ render(<Kbd>K</Kbd>);
8
+ expect(screen.getByText('K')).toBeInTheDocument();
9
+ });
10
+
11
+ it('renders a <kbd> element with the kbd class', () => {
12
+ const { container } = render(<Kbd>X</Kbd>);
13
+ const el = container.querySelector('kbd');
14
+ expect(el).toBeInTheDocument();
15
+ expect(el).toHaveClass('kbd');
16
+ });
17
+
18
+ it('passes through HTML attributes', () => {
19
+ render(
20
+ <Kbd id="shortcut-1" data-testid="k">
21
+
22
+ </Kbd>,
23
+ );
24
+ const el = screen.getByTestId('k');
25
+ expect(el.id).toBe('shortcut-1');
26
+ expect(el.tagName).toBe('KBD');
27
+ });
28
+
29
+ it('combines user className with the kbd class via cx', () => {
30
+ render(
31
+ <Kbd data-testid="k" className="extra">
32
+ K
33
+ </Kbd>,
34
+ );
35
+ const el = screen.getByTestId('k');
36
+ expect(el).toHaveClass('kbd');
37
+ expect(el).toHaveClass('extra');
38
+ });
39
+ });
@@ -0,0 +1,56 @@
1
+ import { describe, it, expect, vi } from 'vitest';
2
+ import { render, screen } from '@testing-library/react';
3
+ import userEvent from '@testing-library/user-event';
4
+ import { NumberInput } from '../../../src/web/ui/controls/NumberInput';
5
+
6
+ describe('NumberInput', () => {
7
+ it('renders a spinbox with the numeric value', () => {
8
+ render(<NumberInput value={5} onChange={() => {}} />);
9
+ const input = screen.getByRole('spinbutton');
10
+ expect(input).toHaveValue(5);
11
+ });
12
+
13
+ it('accepts a string value', () => {
14
+ render(<NumberInput value="12" onChange={() => {}} />);
15
+ const input = screen.getByRole('spinbutton');
16
+ expect(input).toHaveValue(12);
17
+ });
18
+
19
+ it('fires onChange with a number when typing digits', async () => {
20
+ const onChange = vi.fn();
21
+ const user = userEvent.setup();
22
+ render(<NumberInput value={0} onChange={onChange} />);
23
+ const input = screen.getByRole('spinbutton');
24
+ input.focus();
25
+ await user.type(input, '7');
26
+ expect(onChange).toHaveBeenCalled();
27
+ const lastCall = onChange.mock.calls[onChange.mock.calls.length - 1]?.[0];
28
+ expect(typeof lastCall === 'number' || lastCall === '07').toBe(true);
29
+ });
30
+
31
+ it('forwards min/max/step', () => {
32
+ render(
33
+ <NumberInput
34
+ value={1}
35
+ onChange={() => {}}
36
+ min={0}
37
+ max={10}
38
+ step={0.5}
39
+ />,
40
+ );
41
+ const input = screen.getByRole('spinbutton') as HTMLInputElement;
42
+ expect(input.min).toBe('0');
43
+ expect(input.max).toBe('10');
44
+ expect(input.step).toBe('0.5');
45
+ });
46
+
47
+ it('applies error class when error is set', () => {
48
+ render(<NumberInput value={1} onChange={() => {}} error="bad" />);
49
+ expect(screen.getByRole('spinbutton')).toHaveClass('field-error');
50
+ });
51
+
52
+ it('is disabled when disabled is set', () => {
53
+ render(<NumberInput value={1} onChange={() => {}} disabled />);
54
+ expect(screen.getByRole('spinbutton')).toBeDisabled();
55
+ });
56
+ });