crewswarm 0.8.1-beta

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 (362) hide show
  1. package/.env.example +155 -0
  2. package/LICENSE +21 -0
  3. package/README.md +316 -0
  4. package/apps/dashboard/dist/assets/chat-core-BwSoInmZ.js +1 -0
  5. package/apps/dashboard/dist/assets/chat-core-BwSoInmZ.js.br +0 -0
  6. package/apps/dashboard/dist/assets/cli-process-COMRNPqr.js +1 -0
  7. package/apps/dashboard/dist/assets/cli-process-COMRNPqr.js.br +0 -0
  8. package/apps/dashboard/dist/assets/components-CSUb80ze.js +1 -0
  9. package/apps/dashboard/dist/assets/components-CSUb80ze.js.br +0 -0
  10. package/apps/dashboard/dist/assets/core-utils-CAVnDoe1.js +1 -0
  11. package/apps/dashboard/dist/assets/core-utils-CAVnDoe1.js.br +0 -0
  12. package/apps/dashboard/dist/assets/index-CF0aJRtC.css +1 -0
  13. package/apps/dashboard/dist/assets/index-CF0aJRtC.css.br +0 -0
  14. package/apps/dashboard/dist/assets/index-Px49zu76.js +2 -0
  15. package/apps/dashboard/dist/assets/index-Px49zu76.js.br +0 -0
  16. package/apps/dashboard/dist/assets/orchestration-Ca2DLWN-.js +1 -0
  17. package/apps/dashboard/dist/assets/orchestration-Ca2DLWN-.js.br +0 -0
  18. package/apps/dashboard/dist/assets/setup-wizard-i3eEixlo.js +1 -0
  19. package/apps/dashboard/dist/assets/setup-wizard-i3eEixlo.js.br +0 -0
  20. package/apps/dashboard/dist/assets/tab-agents-tab-BThdsdJY.js +1 -0
  21. package/apps/dashboard/dist/assets/tab-agents-tab-BThdsdJY.js.br +0 -0
  22. package/apps/dashboard/dist/assets/tab-benchmarks-tab-DfCuAClu.js +1 -0
  23. package/apps/dashboard/dist/assets/tab-comms-tab-eHpOSBhG.js +1 -0
  24. package/apps/dashboard/dist/assets/tab-comms-tab-eHpOSBhG.js.br +0 -0
  25. package/apps/dashboard/dist/assets/tab-contacts-tab-yEegNyO4.js +1 -0
  26. package/apps/dashboard/dist/assets/tab-contacts-tab-yEegNyO4.js.br +0 -0
  27. package/apps/dashboard/dist/assets/tab-engines-tab-C3DYxTwy.js +1 -0
  28. package/apps/dashboard/dist/assets/tab-engines-tab-C3DYxTwy.js.br +0 -0
  29. package/apps/dashboard/dist/assets/tab-memory-tab-C59BYFQD.js +1 -0
  30. package/apps/dashboard/dist/assets/tab-memory-tab-C59BYFQD.js.br +0 -0
  31. package/apps/dashboard/dist/assets/tab-models-tab-9Ur7pXWA.js +1 -0
  32. package/apps/dashboard/dist/assets/tab-models-tab-9Ur7pXWA.js.br +0 -0
  33. package/apps/dashboard/dist/assets/tab-pm-loop-tab-D7mnDelU.js +1 -0
  34. package/apps/dashboard/dist/assets/tab-pm-loop-tab-D7mnDelU.js.br +0 -0
  35. package/apps/dashboard/dist/assets/tab-projects-tab-C6h2Mv1K.js +1 -0
  36. package/apps/dashboard/dist/assets/tab-projects-tab-C6h2Mv1K.js.br +0 -0
  37. package/apps/dashboard/dist/assets/tab-prompts-tab-C0wZvWK3.js +1 -0
  38. package/apps/dashboard/dist/assets/tab-prompts-tab-C0wZvWK3.js.br +0 -0
  39. package/apps/dashboard/dist/assets/tab-services-tab-DBj_w3bc.js +1 -0
  40. package/apps/dashboard/dist/assets/tab-services-tab-DBj_w3bc.js.br +0 -0
  41. package/apps/dashboard/dist/assets/tab-settings-tab-ezeqAjZk.js +1 -0
  42. package/apps/dashboard/dist/assets/tab-settings-tab-ezeqAjZk.js.br +0 -0
  43. package/apps/dashboard/dist/assets/tab-skills-tab-BYdU2whk.js +1 -0
  44. package/apps/dashboard/dist/assets/tab-skills-tab-BYdU2whk.js.br +0 -0
  45. package/apps/dashboard/dist/assets/tab-spending-tab-Bg6w9t_p.js +1 -0
  46. package/apps/dashboard/dist/assets/tab-spending-tab-Bg6w9t_p.js.br +0 -0
  47. package/apps/dashboard/dist/assets/tab-swarm-chat-tab-BBV9HB2X.js +1 -0
  48. package/apps/dashboard/dist/assets/tab-swarm-chat-tab-BBV9HB2X.js.br +0 -0
  49. package/apps/dashboard/dist/assets/tab-swarm-tab-ChqLlEVs.js +1 -0
  50. package/apps/dashboard/dist/assets/tab-swarm-tab-ChqLlEVs.js.br +0 -0
  51. package/apps/dashboard/dist/assets/tab-usage-tab-B2UWXenJ.js +1 -0
  52. package/apps/dashboard/dist/assets/tab-usage-tab-B2UWXenJ.js.br +0 -0
  53. package/apps/dashboard/dist/assets/tab-waves-tab-SaJDkb4x.js +1 -0
  54. package/apps/dashboard/dist/assets/tab-waves-tab-SaJDkb4x.js.br +0 -0
  55. package/apps/dashboard/dist/assets/tab-workflows-tab-6QSXLJ0i.js +1 -0
  56. package/apps/dashboard/dist/assets/tab-workflows-tab-6QSXLJ0i.js.br +0 -0
  57. package/apps/dashboard/dist/favicon.png +0 -0
  58. package/apps/dashboard/dist/index.html +6466 -0
  59. package/apps/dashboard/dist/index.html.br +0 -0
  60. package/apps/dashboard/dist/index.html.gz +0 -0
  61. package/apps/dashboard/dist/signup.html +446 -0
  62. package/apps/dashboard/index.html +6442 -0
  63. package/apps/dashboard/package.json +15 -0
  64. package/apps/dashboard/src/app.js +2823 -0
  65. package/apps/dashboard/src/app.js.br +0 -0
  66. package/apps/dashboard/src/app.js.gz +0 -0
  67. package/apps/dashboard/src/chat/chat-actions.js +1847 -0
  68. package/apps/dashboard/src/chat/chat-actions.js.br +0 -0
  69. package/apps/dashboard/src/chat/unified-messages.js +327 -0
  70. package/apps/dashboard/src/chat/unified-messages.js.br +0 -0
  71. package/apps/dashboard/src/cli-process.js +208 -0
  72. package/apps/dashboard/src/cli-process.js.br +0 -0
  73. package/apps/dashboard/src/cli-process.js.gz +0 -0
  74. package/apps/dashboard/src/components/active-tasks-panel.js +175 -0
  75. package/apps/dashboard/src/components/active-tasks-panel.js.br +0 -0
  76. package/apps/dashboard/src/core/api.js +18 -0
  77. package/apps/dashboard/src/core/api.js.br +0 -0
  78. package/apps/dashboard/src/core/dom.js +220 -0
  79. package/apps/dashboard/src/core/dom.js.br +0 -0
  80. package/apps/dashboard/src/core/state.js +91 -0
  81. package/apps/dashboard/src/core/state.js.br +0 -0
  82. package/apps/dashboard/src/core/task-manager.js +134 -0
  83. package/apps/dashboard/src/core/task-manager.js.br +0 -0
  84. package/apps/dashboard/src/orchestration-status.js +127 -0
  85. package/apps/dashboard/src/orchestration-status.js.br +0 -0
  86. package/apps/dashboard/src/setup-wizard.js +555 -0
  87. package/apps/dashboard/src/setup-wizard.js.br +0 -0
  88. package/apps/dashboard/src/styles.css +2085 -0
  89. package/apps/dashboard/src/styles.css.br +0 -0
  90. package/apps/dashboard/src/styles.css.gz +0 -0
  91. package/apps/dashboard/src/tabs/agents-tab.js +2237 -0
  92. package/apps/dashboard/src/tabs/agents-tab.js.br +0 -0
  93. package/apps/dashboard/src/tabs/benchmarks-tab.js +229 -0
  94. package/apps/dashboard/src/tabs/benchmarks-tab.js.br +0 -0
  95. package/apps/dashboard/src/tabs/comms-tab.js +955 -0
  96. package/apps/dashboard/src/tabs/comms-tab.js.br +0 -0
  97. package/apps/dashboard/src/tabs/contacts-tab.js +654 -0
  98. package/apps/dashboard/src/tabs/contacts-tab.js.br +0 -0
  99. package/apps/dashboard/src/tabs/engines-tab.js +175 -0
  100. package/apps/dashboard/src/tabs/engines-tab.js.br +0 -0
  101. package/apps/dashboard/src/tabs/memory-tab.js +182 -0
  102. package/apps/dashboard/src/tabs/memory-tab.js.br +0 -0
  103. package/apps/dashboard/src/tabs/models-tab.js +441 -0
  104. package/apps/dashboard/src/tabs/models-tab.js.br +0 -0
  105. package/apps/dashboard/src/tabs/pm-loop-tab.js +185 -0
  106. package/apps/dashboard/src/tabs/pm-loop-tab.js.br +0 -0
  107. package/apps/dashboard/src/tabs/projects-tab.js +663 -0
  108. package/apps/dashboard/src/tabs/projects-tab.js.br +0 -0
  109. package/apps/dashboard/src/tabs/projects-tab.js.gz +0 -0
  110. package/apps/dashboard/src/tabs/prompts-tab.js +160 -0
  111. package/apps/dashboard/src/tabs/prompts-tab.js.br +0 -0
  112. package/apps/dashboard/src/tabs/services-tab.js +202 -0
  113. package/apps/dashboard/src/tabs/services-tab.js.br +0 -0
  114. package/apps/dashboard/src/tabs/settings-tab.js +803 -0
  115. package/apps/dashboard/src/tabs/settings-tab.js.br +0 -0
  116. package/apps/dashboard/src/tabs/skills-tab.js +284 -0
  117. package/apps/dashboard/src/tabs/skills-tab.js.br +0 -0
  118. package/apps/dashboard/src/tabs/spending-tab.js +173 -0
  119. package/apps/dashboard/src/tabs/spending-tab.js.br +0 -0
  120. package/apps/dashboard/src/tabs/swarm-chat-tab.js +660 -0
  121. package/apps/dashboard/src/tabs/swarm-chat-tab.js.br +0 -0
  122. package/apps/dashboard/src/tabs/swarm-tab.js +538 -0
  123. package/apps/dashboard/src/tabs/swarm-tab.js.br +0 -0
  124. package/apps/dashboard/src/tabs/usage-tab.js +390 -0
  125. package/apps/dashboard/src/tabs/usage-tab.js.br +0 -0
  126. package/apps/dashboard/src/tabs/waves-tab.js +238 -0
  127. package/apps/dashboard/src/tabs/waves-tab.js.br +0 -0
  128. package/apps/dashboard/src/tabs/workflows-tab.js +747 -0
  129. package/apps/dashboard/src/tabs/workflows-tab.js.br +0 -0
  130. package/apps/vibe/.crew/agent-memory/pipeline.json +249 -0
  131. package/apps/vibe/.crew/cost.json +17 -0
  132. package/apps/vibe/.crew/json-parse-metrics.jsonl +22 -0
  133. package/apps/vibe/.crew/pipeline-metrics.jsonl +22 -0
  134. package/apps/vibe/.crew/pipeline-runs/pipeline-0f90c392-2425-4ae5-850c-bd9d17b1d690.jsonl +5 -0
  135. package/apps/vibe/.crew/pipeline-runs/pipeline-1c269dd9-a63f-4fba-af81-5cf08048ef06.jsonl +5 -0
  136. package/apps/vibe/.crew/pipeline-runs/pipeline-288a7765-da24-4a22-89bc-1f3cc9b0562c.jsonl +1 -0
  137. package/apps/vibe/.crew/pipeline-runs/pipeline-2c78fd22-a657-4bd1-bc49-0679fb384409.jsonl +5 -0
  138. package/apps/vibe/.crew/pipeline-runs/pipeline-3e6fe08d-3264-404a-8df3-aab7efef10e7.jsonl +5 -0
  139. package/apps/vibe/.crew/pipeline-runs/pipeline-42eec610-57fe-4e09-9e7e-b315038495c2.jsonl +5 -0
  140. package/apps/vibe/.crew/pipeline-runs/pipeline-4438eb4c-ae13-42b1-90e2-b043d8983be8.jsonl +5 -0
  141. package/apps/vibe/.crew/pipeline-runs/pipeline-4740a9f5-86e7-44b6-a394-de433e291727.jsonl +5 -0
  142. package/apps/vibe/.crew/pipeline-runs/pipeline-49e1da6a-957e-48fd-9220-415019e4f8e2.jsonl +5 -0
  143. package/apps/vibe/.crew/pipeline-runs/pipeline-4c9251db-be68-427b-a3fc-a264f2b5778d.jsonl +5 -0
  144. package/apps/vibe/.crew/pipeline-runs/pipeline-65e29a57-664d-4196-8109-017e364f182e.jsonl +5 -0
  145. package/apps/vibe/.crew/pipeline-runs/pipeline-6aa04bc5-9593-4b1f-b58d-3bf2978cb602.jsonl +5 -0
  146. package/apps/vibe/.crew/pipeline-runs/pipeline-6e1cba53-9b70-457e-99e0-59199149dd21.jsonl +5 -0
  147. package/apps/vibe/.crew/pipeline-runs/pipeline-749f41cc-4dac-4204-be64-873a6080a0d2.jsonl +5 -0
  148. package/apps/vibe/.crew/pipeline-runs/pipeline-74d68121-e181-4864-bd9a-c3211341dfaf.jsonl +5 -0
  149. package/apps/vibe/.crew/pipeline-runs/pipeline-8509bc24-142d-4e07-b44a-a50bf99d1103.jsonl +5 -0
  150. package/apps/vibe/.crew/pipeline-runs/pipeline-960339c6-07ca-43ce-9900-f6e1702b39b9.jsonl +5 -0
  151. package/apps/vibe/.crew/pipeline-runs/pipeline-9c6480a9-7031-4146-b241-825b9a2d1de1.jsonl +5 -0
  152. package/apps/vibe/.crew/pipeline-runs/pipeline-9fd42426-8492-4157-9d5f-e1537c060489.jsonl +2 -0
  153. package/apps/vibe/.crew/pipeline-runs/pipeline-ad6d40a3-2f5e-46a9-a345-47caaccc51aa.jsonl +5 -0
  154. package/apps/vibe/.crew/pipeline-runs/pipeline-bc606133-8d5b-4535-8d85-f1a29cdaa981.jsonl +5 -0
  155. package/apps/vibe/.crew/pipeline-runs/pipeline-c1a13ccd-634a-4d01-a4a7-1177b8a752ff.jsonl +5 -0
  156. package/apps/vibe/.crew/pipeline-runs/pipeline-c7d27b42-249e-4bd4-8f26-6aa998110b8a.jsonl +5 -0
  157. package/apps/vibe/.crew/pipeline-runs/pipeline-cca2e9b9-4a34-4d25-a311-5c793fa7e91e.jsonl +5 -0
  158. package/apps/vibe/.crew/sandbox.json +7 -0
  159. package/apps/vibe/.crew/session.json +285 -0
  160. package/apps/vibe/.crew/training-data.jsonl +0 -0
  161. package/apps/vibe/.github/workflows/studio-quality.yml +37 -0
  162. package/apps/vibe/.studio-data/project-messages/chuck-norris.jsonl +12 -0
  163. package/apps/vibe/.studio-data/project-messages/general.jsonl +54 -0
  164. package/apps/vibe/.studio-data/project-messages/studio-local.jsonl +10 -0
  165. package/apps/vibe/ARCHITECTURE.md +3393 -0
  166. package/apps/vibe/QUICK-REFERENCE.md +211 -0
  167. package/apps/vibe/README.md +76 -0
  168. package/apps/vibe/ROADMAP.md +41 -0
  169. package/apps/vibe/STUDIO-SETUP-COMPLETE.md +35 -0
  170. package/apps/vibe/VISUAL-GUIDE.md +378 -0
  171. package/apps/vibe/capture-demo.mjs +160 -0
  172. package/apps/vibe/capture-vibe-assets.mjs +71 -0
  173. package/apps/vibe/capture-vibe-video.mjs +260 -0
  174. package/apps/vibe/check-buttons.js +41 -0
  175. package/apps/vibe/diagnose.html +106 -0
  176. package/apps/vibe/fix-buttons.js +103 -0
  177. package/apps/vibe/index.html +3401 -0
  178. package/apps/vibe/package-lock.json +920 -0
  179. package/apps/vibe/package.json +31 -0
  180. package/apps/vibe/public/favicon.png +0 -0
  181. package/apps/vibe/scripts/studio-pty-host.py +117 -0
  182. package/apps/vibe/server.mjs +1835 -0
  183. package/apps/vibe/src/main.js +2846 -0
  184. package/apps/vibe/src/register-all-languages.js +98 -0
  185. package/apps/vibe/start-studio.sh +11 -0
  186. package/apps/vibe/test/accessibility-tests.js +77 -0
  187. package/apps/vibe/test/browser-performance-audit.mjs +205 -0
  188. package/apps/vibe/test/performance-tests.js +120 -0
  189. package/apps/vibe/test/security-tests.js +213 -0
  190. package/apps/vibe/tests/e2e.local.mjs +54 -0
  191. package/apps/vibe/tests/server.smoke.mjs +106 -0
  192. package/apps/vibe/update_website.mjs +74 -0
  193. package/apps/vibe/vite.config.js +19 -0
  194. package/apps/vibe/watch-server.mjs +108 -0
  195. package/contrib/openclaw-plugin/README.md +199 -0
  196. package/contrib/openclaw-plugin/index.ts +306 -0
  197. package/contrib/openclaw-plugin/openclaw.plugin.json +41 -0
  198. package/contrib/openclaw-plugin/package.json +27 -0
  199. package/contrib/openclaw-plugin/skills/crewswarm/SKILL.md +88 -0
  200. package/crew-lead.mjs +649 -0
  201. package/engines/claude-code.json +36 -0
  202. package/engines/codex.json +37 -0
  203. package/engines/crew-cli.json +42 -0
  204. package/engines/cursor.json +40 -0
  205. package/engines/docker-sandbox.json +38 -0
  206. package/engines/gemini-cli.json +75 -0
  207. package/engines/opencode.json +31 -0
  208. package/gateway-bridge.mjs +1575 -0
  209. package/install.sh +738 -0
  210. package/lib/agent-registry.mjs +232 -0
  211. package/lib/agents/daemon.mjs +121 -0
  212. package/lib/agents/dispatch.mjs +225 -0
  213. package/lib/agents/permissions.mjs +90 -0
  214. package/lib/agents/platform-formatting.mjs +102 -0
  215. package/lib/agents/registry.mjs +81 -0
  216. package/lib/agents/tool-instructions.mjs +257 -0
  217. package/lib/agents/validation.mjs +75 -0
  218. package/lib/approval/policy-manager.mjs +221 -0
  219. package/lib/autoharness/index.mjs +391 -0
  220. package/lib/bridges/cli-executor.mjs +332 -0
  221. package/lib/bridges/gateway-ws.mjs +345 -0
  222. package/lib/bridges/integration.mjs +229 -0
  223. package/lib/bridges/rag-helper.mjs +90 -0
  224. package/lib/browser/opencode-passthrough-filter.js +44 -0
  225. package/lib/browser/passthrough-stderr.js +109 -0
  226. package/lib/chat/autonomous-mentions.mjs +373 -0
  227. package/lib/chat/history.mjs +82 -0
  228. package/lib/chat/mention-routing-intent.mjs +136 -0
  229. package/lib/chat/participants.mjs +95 -0
  230. package/lib/chat/project-messages-rag.mjs +265 -0
  231. package/lib/chat/project-messages.mjs +479 -0
  232. package/lib/chat/shared-chat-prompt-overlay.mjs +52 -0
  233. package/lib/chat/thread-binding.mjs +34 -0
  234. package/lib/chat/unified-history.mjs +223 -0
  235. package/lib/chat/unified-wrapper.mjs +41 -0
  236. package/lib/cli-process-tracker.mjs +228 -0
  237. package/lib/collections/index.mjs +433 -0
  238. package/lib/contacts/identity-linker.mjs +248 -0
  239. package/lib/contacts/index.mjs +341 -0
  240. package/lib/crew-judge/PROMPT.md +93 -0
  241. package/lib/crew-judge/judge.mjs +260 -0
  242. package/lib/crew-lead/agent-manager.mjs +125 -0
  243. package/lib/crew-lead/background.mjs +270 -0
  244. package/lib/crew-lead/brain.mjs +110 -0
  245. package/lib/crew-lead/chat-handler.mjs +2603 -0
  246. package/lib/crew-lead/chat-handler.mjs.bak +1274 -0
  247. package/lib/crew-lead/classifier.mjs +83 -0
  248. package/lib/crew-lead/http-server.mjs +4824 -0
  249. package/lib/crew-lead/intent.mjs +102 -0
  250. package/lib/crew-lead/interval-manager.mjs +41 -0
  251. package/lib/crew-lead/llm-caller.mjs +544 -0
  252. package/lib/crew-lead/prompts.mjs +392 -0
  253. package/lib/crew-lead/retry-manager.mjs +118 -0
  254. package/lib/crew-lead/tools.mjs +318 -0
  255. package/lib/crew-lead/wave-dispatcher.mjs +798 -0
  256. package/lib/crew-lead/waves-config.json +73 -0
  257. package/lib/crew-lead/waves-loader.mjs +110 -0
  258. package/lib/crew-lead/ws-router.mjs +428 -0
  259. package/lib/dispatch/parsers.mjs +299 -0
  260. package/lib/domain-planning/detector.mjs +196 -0
  261. package/lib/domain-planning/prompts/crew-pm-cli.md +96 -0
  262. package/lib/domain-planning/prompts/crew-pm-core.md +122 -0
  263. package/lib/domain-planning/prompts/crew-pm-frontend.md +111 -0
  264. package/lib/engines/crew-cli-sandbox.mjs +422 -0
  265. package/lib/engines/crew-cli.mjs +155 -0
  266. package/lib/engines/cursor-launcher.mjs +110 -0
  267. package/lib/engines/engine-registry.mjs +253 -0
  268. package/lib/engines/llm-direct.mjs +184 -0
  269. package/lib/engines/opencode.mjs +256 -0
  270. package/lib/engines/ouroboros.mjs +114 -0
  271. package/lib/engines/rt-envelope.mjs +1643 -0
  272. package/lib/engines/rt-envelope.mjs.backup-current +870 -0
  273. package/lib/engines/runners.mjs +1367 -0
  274. package/lib/gemini-cli-passthrough-noise.mjs +37 -0
  275. package/lib/integrations/code-search.mjs +259 -0
  276. package/lib/integrations/greptile.mjs +148 -0
  277. package/lib/integrations/multimodal.mjs +313 -0
  278. package/lib/integrations/telegram-streaming.mjs +153 -0
  279. package/lib/integrations/tts.mjs +312 -0
  280. package/lib/integrations/twitter-links.mjs +294 -0
  281. package/lib/memory/shared-adapter.mjs +296 -0
  282. package/lib/pipeline/manager.mjs +539 -0
  283. package/lib/preferences/extractor.mjs +347 -0
  284. package/lib/project-dir.mjs +20 -0
  285. package/lib/runtime/config.mjs +388 -0
  286. package/lib/runtime/dlq.mjs +170 -0
  287. package/lib/runtime/log-rotation.mjs +82 -0
  288. package/lib/runtime/logger.mjs +58 -0
  289. package/lib/runtime/memory.mjs +421 -0
  290. package/lib/runtime/paths.mjs +76 -0
  291. package/lib/runtime/project-dir.mjs +127 -0
  292. package/lib/runtime/spending.mjs +204 -0
  293. package/lib/runtime/startup-guard.mjs +291 -0
  294. package/lib/runtime/task-lease.mjs +234 -0
  295. package/lib/runtime/telemetry-schema.mjs +208 -0
  296. package/lib/runtime/telemetry.mjs +101 -0
  297. package/lib/runtime/utils.mjs +64 -0
  298. package/lib/skills/index.mjs +265 -0
  299. package/lib/tools/browser.mjs +135 -0
  300. package/lib/tools/executor.mjs +913 -0
  301. package/lib/types.d.ts +57 -0
  302. package/package.json +106 -0
  303. package/pm-loop.mjs +1626 -0
  304. package/prompts/coder-back.md +27 -0
  305. package/prompts/coder-front.md +27 -0
  306. package/prompts/coder.md +28 -0
  307. package/prompts/copywriter.md +17 -0
  308. package/prompts/fixer.md +39 -0
  309. package/prompts/frontend.md +23 -0
  310. package/prompts/github.md +24 -0
  311. package/prompts/main.md +39 -0
  312. package/prompts/pm-cli.md +95 -0
  313. package/prompts/pm-core.md +121 -0
  314. package/prompts/pm-frontend.md +110 -0
  315. package/prompts/pm.md +234 -0
  316. package/prompts/qa.md +44 -0
  317. package/prompts/security.md +19 -0
  318. package/scripts/build-crew-chat.sh +28 -0
  319. package/scripts/build-llms-full.mjs +52 -0
  320. package/scripts/chatmock-login.sh +16 -0
  321. package/scripts/chatmock-serve.sh +16 -0
  322. package/scripts/check-dashboard.mjs +88 -0
  323. package/scripts/crew-scribe.mjs +326 -0
  324. package/scripts/dashboard-helpers.mjs +391 -0
  325. package/scripts/dashboard-validation.mjs +198 -0
  326. package/scripts/dashboard.mjs +9717 -0
  327. package/scripts/dlq-replay.mjs +61 -0
  328. package/scripts/doctor.mjs +196 -0
  329. package/scripts/file-lock.mjs +186 -0
  330. package/scripts/fresh-machine-smoke.sh +323 -0
  331. package/scripts/generate-changelog.mjs +227 -0
  332. package/scripts/generate-openapi.mjs +334 -0
  333. package/scripts/health-check.mjs +229 -0
  334. package/scripts/install-docker.sh +213 -0
  335. package/scripts/mcp-server.mjs +1625 -0
  336. package/scripts/opencrew-rt-daemon.mjs +568 -0
  337. package/scripts/openswitchctl +646 -0
  338. package/scripts/refactor-configs.mjs +39 -0
  339. package/scripts/release-check.sh +46 -0
  340. package/scripts/resolve-node-bin.sh +25 -0
  341. package/scripts/restart-all-from-repo.sh +329 -0
  342. package/scripts/restart-crew-lead.sh +98 -0
  343. package/scripts/restart-dashboard.sh +104 -0
  344. package/scripts/restart-service.sh +274 -0
  345. package/scripts/run-accessibility-audit.mjs +356 -0
  346. package/scripts/run-integration-bounded.mjs +188 -0
  347. package/scripts/run-scheduled-pipeline.mjs +230 -0
  348. package/scripts/run.mjs +41 -0
  349. package/scripts/scan-skills.mjs +79 -0
  350. package/scripts/setup-firewall.sh +128 -0
  351. package/scripts/smoke-dispatch.mjs +149 -0
  352. package/scripts/smoke.sh +163 -0
  353. package/scripts/start-crew.mjs +328 -0
  354. package/scripts/start.mjs +146 -0
  355. package/scripts/swiftbar-restart-service.sh +19 -0
  356. package/scripts/sync-agents.mjs +152 -0
  357. package/scripts/sync-prompts.mjs +79 -0
  358. package/scripts/validate-config.mjs +337 -0
  359. package/scripts/wow.mjs +89 -0
  360. package/telegram-bridge.mjs +2421 -0
  361. package/unified-orchestrator.mjs +519 -0
  362. package/whatsapp-bridge.mjs +1481 -0
@@ -0,0 +1,323 @@
1
+ #!/usr/bin/env bash
2
+ # fresh-machine-smoke.sh — Clone-to-first-build verification on a clean environment.
3
+ #
4
+ # Simulates a brand-new machine: temp dir, no existing config, fresh install.
5
+ # Requires GROQ_API_KEY in the environment (only external dependency).
6
+ #
7
+ # Usage:
8
+ # GROQ_API_KEY=gsk_... bash scripts/fresh-machine-smoke.sh
9
+ #
10
+ # Exit codes:
11
+ # 0 — all checks passed
12
+ # 1 — one or more checks failed
13
+ #
14
+ # What it tests:
15
+ # 1. Prerequisites (Node ≥ 20, git)
16
+ # 2. Clone into a temp dir
17
+ # 3. npm ci
18
+ # 4. Bootstrap minimal config (token + Groq key)
19
+ # 5. openswitchctl doctor (config blockers only — services not started yet)
20
+ # 6. Start the full stack
21
+ # 7. Wait for agents to connect
22
+ # 8. Dispatch one task to crew-coder → verify output file
23
+ # 9. Dispatch one task to crew-main → verify text reply
24
+ # 10. Teardown
25
+ #
26
+ # Transcript is printed to stdout; pipe to tee to capture:
27
+ # GROQ_API_KEY=... bash scripts/fresh-machine-smoke.sh | tee /tmp/fresh-machine-run.txt
28
+
29
+ set -euo pipefail
30
+
31
+ # ── Colour helpers ──────────────────────────────────────────────────────────
32
+ GRN="\033[32m" RED="\033[31m" YLW="\033[33m" BLD="\033[1m" RST="\033[0m" DIM="\033[2m"
33
+ pass() { printf "${GRN}✅ ${RST}%s\n" "$1"; }
34
+ fail() { printf "${RED}❌ ${RST}${BLD}%s${RST}\n" "$1"; FAILED=$((FAILED+1)); }
35
+ warn() { printf "${YLW}⚠️ ${RST}%s\n" "$1"; }
36
+ step() { printf "\n${BLD}${DIM}── %s ──${RST}\n" "$1"; }
37
+ banner(){ printf "\n${BLD}%s${RST}\n" "$1"; }
38
+ FAILED=0
39
+
40
+ local_repo_path() {
41
+ local src="$1"
42
+ if [[ "$src" == file://* ]]; then
43
+ printf "%s\n" "${src#file://}"
44
+ return 0
45
+ fi
46
+ if [[ -d "$src/.git" ]]; then
47
+ printf "%s\n" "$src"
48
+ return 0
49
+ fi
50
+ return 1
51
+ }
52
+
53
+ export_repo_snapshot() {
54
+ local src="$1"
55
+ local dest="$2"
56
+ local archive_file
57
+ archive_file="$(mktemp "${TMPDIR:-/tmp}/fresh-smoke-archive.XXXXXX.tar")"
58
+ mkdir -p "$dest"
59
+ git -C "$src" archive --format=tar -o "$archive_file" HEAD
60
+ tar -xf "$archive_file" -C "$dest"
61
+ rm -f "$archive_file"
62
+ }
63
+
64
+ run_npm_ci() {
65
+ local log_file="$1"
66
+ : > "$log_file"
67
+ npm ci --prefer-offline >"$log_file" 2>&1 &
68
+ local pid=$!
69
+ local ticks=0
70
+ printf " Installing dependencies"
71
+ while kill -0 "$pid" 2>/dev/null; do
72
+ printf "."
73
+ sleep 2
74
+ ticks=$((ticks + 1))
75
+ if (( ticks % 10 == 0 )); then
76
+ local last_line
77
+ last_line="$(tail -n 1 "$log_file" 2>/dev/null || true)"
78
+ if [[ -n "$last_line" ]]; then
79
+ printf "\n${DIM} %s${RST}\n" "$last_line"
80
+ printf " Installing dependencies"
81
+ fi
82
+ fi
83
+ done
84
+ wait "$pid"
85
+ }
86
+
87
+ # ── Config ──────────────────────────────────────────────────────────────────
88
+ REPO_URL="${FRESH_SMOKE_REPO:-https://github.com/CrewSwarm/CrewSwarm.git}"
89
+ GROQ_API_KEY="${GROQ_API_KEY:-}"
90
+ RT_TOKEN="fresh-smoke-$(openssl rand -hex 8 2>/dev/null || echo 'testtoken')"
91
+ TIMEOUT_AGENTS=120 # seconds to wait for agents to connect
92
+ TIMEOUT_TASK=90 # seconds to wait for smoke dispatch
93
+ RT_PORT="${FRESH_SMOKE_RT_PORT:-18989}"
94
+ CREW_LEAD_PORT="${FRESH_SMOKE_CREW_LEAD_PORT:-5110}"
95
+
96
+ banner "🧪 CrewSwarm Fresh-Machine Smoke $(date -u '+%Y-%m-%d %H:%M UTC')"
97
+ printf "${DIM}Repo: %s${RST}\n" "$REPO_URL"
98
+ printf "${DIM}Token: %s${RST}\n" "$RT_TOKEN"
99
+
100
+ # ── 1. Prerequisites ────────────────────────────────────────────────────────
101
+ step "1 · Prerequisites"
102
+
103
+ NODE="${NODE:-node}"
104
+ if ! command -v "$NODE" &>/dev/null; then
105
+ fail "Node.js not found — install v20+: https://nodejs.org"
106
+ exit 1
107
+ fi
108
+ NODE_VER=$("$NODE" --version | sed 's/v//')
109
+ NODE_MAJOR=$(echo "$NODE_VER" | cut -d. -f1)
110
+ if [[ "$NODE_MAJOR" -lt 20 ]]; then
111
+ fail "Node.js v$NODE_VER — need v20+"; exit 1
112
+ fi
113
+ pass "Node.js v$NODE_VER"
114
+
115
+ if ! command -v git &>/dev/null; then
116
+ fail "git not found"; exit 1
117
+ fi
118
+ pass "git $(git --version | awk '{print $3}')"
119
+
120
+ if [[ -z "$GROQ_API_KEY" ]]; then
121
+ warn "GROQ_API_KEY not set — LLM calls will fail. Set it and re-run."
122
+ warn " export GROQ_API_KEY=gsk_..."
123
+ # Don't exit — doctor/config checks can still run
124
+ fi
125
+
126
+ # ── 2. Clone ────────────────────────────────────────────────────────────────
127
+ step "2 · Clone"
128
+ WORK_DIR=$(mktemp -d)
129
+ CLONE_DIR="$WORK_DIR/CrewSwarm"
130
+ export TMPDIR="$WORK_DIR/tmp"
131
+ mkdir -p "$TMPDIR"
132
+ trap 'echo ""; warn "Cleaning up $WORK_DIR ..."; kill $(jobs -p) 2>/dev/null || true; rm -rf "$WORK_DIR"' EXIT
133
+
134
+ printf "${DIM} Cloning into %s ...${RST}\n" "$CLONE_DIR"
135
+ if LOCAL_REPO="$(local_repo_path "$REPO_URL")"; then
136
+ if export_repo_snapshot "$LOCAL_REPO" "$CLONE_DIR"; then
137
+ pass "Exported local HEAD snapshot $LOCAL_REPO → $CLONE_DIR"
138
+ else
139
+ fail "local snapshot export failed"; exit 1
140
+ fi
141
+ elif git clone --depth=1 "$REPO_URL" "$CLONE_DIR" --quiet 2>&1; then
142
+ pass "Cloned $REPO_URL → $CLONE_DIR"
143
+ else
144
+ fail "git clone failed"; exit 1
145
+ fi
146
+
147
+ cd "$CLONE_DIR"
148
+
149
+ # ── 3. npm install ──────────────────────────────────────────────────────────
150
+ step "3 · npm install"
151
+ NPM_LOG="$WORK_DIR/fresh-smoke-npm.log"
152
+ if run_npm_ci "$NPM_LOG"; then
153
+ printf "\n"
154
+ tail -3 "$NPM_LOG" 2>/dev/null || true
155
+ pass "npm ci succeeded"
156
+ else
157
+ printf "\n${DIM}npm log:${RST}\n"
158
+ tail -40 "$NPM_LOG" 2>/dev/null || true
159
+ fail "npm ci failed"; exit 1
160
+ fi
161
+
162
+ # ── 4. Bootstrap config ─────────────────────────────────────────────────────
163
+ step "4 · Bootstrap config"
164
+ CFG_DIR="$WORK_DIR/.crewswarm"
165
+ mkdir -p "$CFG_DIR"
166
+
167
+ # Redirect config to temp dir for isolation
168
+ export HOME="$WORK_DIR"
169
+ export CREWSWARM_DIR="$CLONE_DIR"
170
+ export CREWSWARM_CONFIG_DIR="$CFG_DIR"
171
+
172
+ # config.json — RT token
173
+ printf '{"rt":{"authToken":"%s"}}\n' "$RT_TOKEN" > "$CFG_DIR/config.json"
174
+ pass "config.json — RT token written"
175
+
176
+ # crewswarm.json — Groq provider + 5 core agents
177
+ node -e "
178
+ const fs = require('fs');
179
+ const key = process.env.GROQ_API_KEY || '';
180
+ const cfg = {
181
+ _note: 'fresh-machine-smoke bootstrap',
182
+ agents: [
183
+ { id: 'crew-lead', model: 'groq/llama-3.3-70b-versatile' },
184
+ { id: 'crew-main', model: 'groq/llama-3.3-70b-versatile' },
185
+ { id: 'crew-coder', model: 'groq/llama-3.3-70b-versatile' },
186
+ { id: 'crew-qa', model: 'groq/llama-3.3-70b-versatile' },
187
+ { id: 'crew-fixer', model: 'groq/llama-3.3-70b-versatile' },
188
+ { id: 'crew-pm', model: 'groq/llama-3.3-70b-versatile' },
189
+ { id: 'crew-orchestrator', model: 'groq/llama-3.3-70b-versatile' },
190
+ { id: 'crew-judge', model: 'groq/llama-3.3-70b-versatile' },
191
+ ],
192
+ providers: {
193
+ groq: { apiKey: key, baseUrl: 'https://api.groq.com/openai/v1' }
194
+ }
195
+ };
196
+ fs.writeFileSync(process.env.CREWSWARM_CONFIG_DIR + '/crewswarm.json', JSON.stringify(cfg, null, 2));
197
+ "
198
+ pass "crewswarm.json — Groq + 5 agents written"
199
+
200
+ # cmd-allowlist
201
+ printf '{"patterns":["npm *","node *","npx *"]}\n' > "$CFG_DIR/cmd-allowlist.json"
202
+ printf '{}' > "$CFG_DIR/agent-prompts.json"
203
+ pass "cmd-allowlist.json + agent-prompts.json written"
204
+
205
+ # ── 5. openswitchctl doctor (config only — services not started) ────────────
206
+ step "5 · openswitchctl doctor"
207
+ CTL="$CLONE_DIR/scripts/openswitchctl"
208
+ chmod +x "$CTL"
209
+
210
+ # doctor exits 1 if blockers exist; warnings about services down are expected here
211
+ if bash "$CTL" doctor 2>&1; then
212
+ pass "doctor — all config checks passed"
213
+ else
214
+ # Warnings about services not running are normal at this stage — check if any CONFIG blockers
215
+ doctor_out=$(bash "$CTL" doctor 2>&1 || true)
216
+ echo "$doctor_out"
217
+ if echo "$doctor_out" | grep -q "❌"; then
218
+ fail "doctor — config blockers present (see above)"
219
+ exit 1
220
+ else
221
+ pass "doctor — config OK (services not yet started, as expected)"
222
+ fi
223
+ fi
224
+
225
+ # ── 6. Start the stack ──────────────────────────────────────────────────────
226
+ step "6 · Start stack"
227
+ export CREWSWARM_RT_AUTH_TOKEN="$RT_TOKEN"
228
+ export CREWSWARM_RT_REQUIRE_TOKEN=1
229
+ export CREWSWARM_RT_PORT="$RT_PORT"
230
+ export CREWSWARM_RT_URL="ws://127.0.0.1:${RT_PORT}"
231
+ export CREWSWARM_OPENCODE_ENABLED=0
232
+ export CREW_LEAD_PORT="$CREW_LEAD_PORT"
233
+ export CREW_LEAD_URL="http://127.0.0.1:${CREW_LEAD_PORT}"
234
+ export CREWSWARM_DISABLE_PGREP_FALLBACK=1
235
+
236
+ "$NODE" "$CLONE_DIR/scripts/opencrew-rt-daemon.mjs" >> /tmp/fresh-smoke-rt.log 2>&1 &
237
+ sleep 3
238
+ "$NODE" "$CLONE_DIR/crew-lead.mjs" >> /tmp/fresh-smoke-lead.log 2>&1 &
239
+ sleep 2
240
+ "$NODE" "$CLONE_DIR/scripts/start-crew.mjs" >> /tmp/fresh-smoke-bridges.log 2>&1
241
+ sleep 5
242
+ pass "Stack processes started"
243
+
244
+ # ── 7. Wait for agents ──────────────────────────────────────────────────────
245
+ step "7 · Wait for agents to connect"
246
+ T_END=$((SECONDS + TIMEOUT_AGENTS))
247
+ CONNECTED=false
248
+ printf " Polling RT bus"
249
+ while [[ $SECONDS -lt $T_END ]]; do
250
+ STATUS=$(curl -sf "http://127.0.0.1:${RT_PORT}/status" 2>/dev/null || echo '{}')
251
+ if echo "$STATUS" | grep -q '"crew-coder"' && echo "$STATUS" | grep -q '"crew-main"'; then
252
+ CONNECTED=true
253
+ printf "\n"
254
+ break
255
+ fi
256
+ printf "."
257
+ sleep 3
258
+ done
259
+
260
+ if [[ "$CONNECTED" == "true" ]]; then
261
+ AGENT_COUNT=$(echo "$STATUS" | "$NODE" -e "let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>{try{const j=JSON.parse(d);console.log((j.agents||[]).length);}catch{console.log(0);}})" 2>/dev/null || echo "?")
262
+ pass "Agents connected ($AGENT_COUNT online)"
263
+ else
264
+ fail "Agents did not connect within ${TIMEOUT_AGENTS}s"
265
+ printf "${DIM}RT log:${RST}\n"; tail -20 /tmp/fresh-smoke-rt.log || true
266
+ printf "${DIM}Bridge log:${RST}\n"; tail -20 /tmp/fresh-smoke-bridges.log || true
267
+ exit 1
268
+ fi
269
+
270
+ # ── 8. Dispatch → crew-coder ─────────────────────────────────────────────────
271
+ step "8 · Dispatch → crew-coder (file write)"
272
+ RUN_ID="fm$(date +%s | tail -c 6)"
273
+ OUT_FILE="$CLONE_DIR/test-output/fresh-smoke/coder-${RUN_ID}.txt"
274
+ EXPECTED="FRESH_SMOKE_OK_${RUN_ID}"
275
+ mkdir -p "$(dirname "$OUT_FILE")"
276
+
277
+ TASK_TEXT="Create this file with @@WRITE_FILE: ${OUT_FILE}
278
+ Write exactly one line: ${EXPECTED}
279
+ No extra text."
280
+
281
+ printf " Dispatching to crew-coder ...\n"
282
+ DISPATCH_REPLY=$(
283
+ timeout "$TIMEOUT_TASK" "$NODE" "$CLONE_DIR/gateway-bridge.mjs" \
284
+ --send crew-coder "$TASK_TEXT" 2>/dev/null || echo ""
285
+ )
286
+
287
+ # Give file system a moment
288
+ sleep 3
289
+
290
+ if [[ -f "$OUT_FILE" ]] && grep -q "$EXPECTED" "$OUT_FILE" 2>/dev/null; then
291
+ pass "crew-coder wrote $OUT_FILE with correct content"
292
+ else
293
+ fail "crew-coder did not produce $OUT_FILE with '$EXPECTED'"
294
+ printf "${DIM}Reply: %s${RST}\n" "${DISPATCH_REPLY:0:200}"
295
+ FAILED=$((FAILED+1))
296
+ fi
297
+
298
+ # ── 9. Dispatch → crew-main (text reply) ────────────────────────────────────
299
+ step "9 · Dispatch → crew-main (text reply)"
300
+ MARKER="MAIN_OK_${RUN_ID}"
301
+ printf " Dispatching to crew-main ...\n"
302
+ MAIN_REPLY=$(
303
+ timeout "$TIMEOUT_TASK" "$NODE" "$CLONE_DIR/gateway-bridge.mjs" \
304
+ --send crew-main "Reply with exactly: $MARKER" 2>/dev/null || echo ""
305
+ )
306
+
307
+ if echo "$MAIN_REPLY" | grep -q "$MARKER"; then
308
+ pass "crew-main replied with $MARKER"
309
+ else
310
+ fail "crew-main did not reply with '$MARKER'"
311
+ printf "${DIM}Reply: %s${RST}\n" "${MAIN_REPLY:0:200}"
312
+ FAILED=$((FAILED+1))
313
+ fi
314
+
315
+ # ── 10. Summary ──────────────────────────────────────────────────────────────
316
+ banner "━━━ Fresh-Machine Smoke Results ━━━"
317
+ if [[ "$FAILED" -eq 0 ]]; then
318
+ printf "${GRN}${BLD}✅ All checks passed — CrewSwarm works on a clean install.${RST}\n\n"
319
+ exit 0
320
+ else
321
+ printf "${RED}${BLD}❌ $FAILED check(s) failed.${RST}\n\n"
322
+ exit 1
323
+ fi
@@ -0,0 +1,227 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { execFileSync } from 'node:child_process';
4
+ import fs from 'node:fs';
5
+ import path from 'node:path';
6
+
7
+ const repoRoot = process.cwd();
8
+ const changelogPath = path.join(repoRoot, 'CHANGELOG.md');
9
+ const packagePath = path.join(repoRoot, 'package.json');
10
+ const args = new Set(process.argv.slice(2));
11
+ const releaseMode = args.has('--release');
12
+
13
+ const CATEGORY_MAP = new Map([
14
+ ['feat', 'Added'],
15
+ ['feature', 'Added'],
16
+ ['fix', 'Fixed'],
17
+ ['bugfix', 'Fixed'],
18
+ ['perf', 'Changed'],
19
+ ['refactor', 'Changed'],
20
+ ['change', 'Changed'],
21
+ ['chore', 'Changed'],
22
+ ['docs', 'Documentation'],
23
+ ['doc', 'Documentation'],
24
+ ['test', 'Testing'],
25
+ ['build', 'Infrastructure'],
26
+ ['ci', 'Infrastructure'],
27
+ ['infra', 'Infrastructure'],
28
+ ['security', 'Security'],
29
+ ['sec', 'Security'],
30
+ ['deps', 'Changed']
31
+ ]);
32
+
33
+ function readJson(filePath) {
34
+ return JSON.parse(fs.readFileSync(filePath, 'utf8'));
35
+ }
36
+
37
+ function git(argsList) {
38
+ return execFileSync('git', argsList, { cwd: repoRoot, encoding: 'utf8' }).trim();
39
+ }
40
+
41
+ function escapeRegExp(value) {
42
+ return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
43
+ }
44
+
45
+ function getTrackedIssuesFromEvent() {
46
+ const eventPath = process.env.GITHUB_EVENT_PATH;
47
+ if (!eventPath || !fs.existsSync(eventPath)) {
48
+ return new Map();
49
+ }
50
+
51
+ try {
52
+ const payload = readJson(eventPath);
53
+ const issues = new Map();
54
+ const addIssue = (number, title) => {
55
+ if (!number || !title) {
56
+ return;
57
+ }
58
+ issues.set(String(number), title.trim());
59
+ };
60
+
61
+ addIssue(payload.pull_request?.number, payload.pull_request?.title);
62
+ addIssue(payload.issue?.number, payload.issue?.title);
63
+
64
+ for (const commit of payload.commits ?? []) {
65
+ const matches = commit.message?.match(/#(\d+)/g) ?? [];
66
+ for (const match of matches) {
67
+ const issueNumber = match.slice(1);
68
+ addIssue(issueNumber, commit.message.split('\n')[0]);
69
+ }
70
+ }
71
+
72
+ return issues;
73
+ } catch {
74
+ return new Map();
75
+ }
76
+ }
77
+
78
+ function getLatestVersionSection(changelog) {
79
+ const matches = [...changelog.matchAll(/^## \[(?!Unreleased\])([^\]]+)\]/gm)];
80
+ return matches[0]?.[1] ?? null;
81
+ }
82
+
83
+ function normalizeVersionTag(version) {
84
+ if (!version) {
85
+ return null;
86
+ }
87
+ return version.startsWith('v') ? version : `v${version}`;
88
+ }
89
+
90
+ function getCommitRange(baseTag) {
91
+ if (!baseTag) {
92
+ return 'HEAD';
93
+ }
94
+
95
+ try {
96
+ git(['rev-parse', '--verify', baseTag]);
97
+ return `${baseTag}..HEAD`;
98
+ } catch {
99
+ return 'HEAD';
100
+ }
101
+ }
102
+
103
+ function parseCommit(raw, eventIssues) {
104
+ const [hash, subject, date] = raw.split('\x1f');
105
+ const conventional = subject.match(/^([A-Za-z]+)(?:\(([^)]+)\))?!?:\s+(.+)$/);
106
+ const token = conventional?.[1]?.toLowerCase();
107
+ const scope = conventional?.[2]?.trim();
108
+ const summary = (conventional?.[3] ?? subject).trim();
109
+ const category = CATEGORY_MAP.get(token) ?? 'Changed';
110
+ const issueRefs = [...new Set((subject.match(/#(\d+)/g) ?? []).map((match) => match.slice(1)))];
111
+ const issueNotes = issueRefs.map((issue) => `#${issue}${eventIssues.get(issue) ? ` ${eventIssues.get(issue)}` : ''}`);
112
+
113
+ let line = `- ${summary}`;
114
+ if (scope) {
115
+ line += ` (${scope})`;
116
+ }
117
+ if (issueNotes.length > 0) {
118
+ line += ` — ${issueNotes.join(', ')}`;
119
+ }
120
+ line += ` (${date})`;
121
+
122
+ return { hash, category, line };
123
+ }
124
+
125
+ function buildSections(commits) {
126
+ const buckets = new Map();
127
+
128
+ for (const category of ['Added', 'Changed', 'Fixed', 'Security', 'Documentation', 'Testing', 'Infrastructure']) {
129
+ buckets.set(category, []);
130
+ }
131
+
132
+ for (const commit of commits) {
133
+ buckets.get(commit.category)?.push(commit.line);
134
+ }
135
+
136
+ return [...buckets.entries()].filter(([, entries]) => entries.length > 0);
137
+ }
138
+
139
+ function buildUnreleasedSection(commits, generatedOn) {
140
+ const sections = buildSections(commits);
141
+ const lines = [
142
+ '## [Unreleased]',
143
+ '',
144
+ `> Auto-generated from git history${process.env.GITHUB_EVENT_NAME ? ' and GitHub event metadata' : ''}.`,
145
+ `> Last generated: ${generatedOn}. Run \`npm run changelog:generate\` to refresh this section.`,
146
+ ''
147
+ ];
148
+
149
+ if (sections.length === 0) {
150
+ lines.push('No unreleased changes detected since the last tagged release.', '');
151
+ return lines.join('\n');
152
+ }
153
+
154
+ for (const [category, entries] of sections) {
155
+ lines.push(`### ${category}`, '');
156
+ lines.push(...entries, '');
157
+ }
158
+
159
+ return lines.join('\n').trimEnd();
160
+ }
161
+
162
+ function replaceUnreleasedSection(changelog, newSection) {
163
+ const unreleasedPattern = /^## \[Unreleased\][\s\S]*?(?=^## \[|\Z)/m;
164
+ if (unreleasedPattern.test(changelog)) {
165
+ return changelog.replace(unreleasedPattern, newSection + '\n\n');
166
+ }
167
+
168
+ return changelog.replace(
169
+ /^(The format is based on .*?\.\n)/s,
170
+ `$1\n${newSection}\n\n`
171
+ );
172
+ }
173
+
174
+ function finalizeRelease(changelog, version, releaseDate) {
175
+ const unreleasedPattern = /^## \[Unreleased\][\s\S]*?(?=^## \[|\Z)/m;
176
+ const unreleasedMatch = changelog.match(unreleasedPattern);
177
+ if (!unreleasedMatch) {
178
+ return changelog;
179
+ }
180
+
181
+ const unreleasedBody = unreleasedMatch[0]
182
+ .replace(/^## \[Unreleased\]\n*/m, '')
183
+ .replace(/^> .*$/gm, '')
184
+ .trim();
185
+
186
+ const releaseHeading = `## [${version}] - ${releaseDate}`;
187
+ const releaseBlock = unreleasedBody
188
+ ? `${releaseHeading}\n\n${unreleasedBody}\n`
189
+ : `${releaseHeading}\n\n- No categorized changes.\n`;
190
+
191
+ return changelog.replace(
192
+ unreleasedPattern,
193
+ `## [Unreleased]\n\n> Auto-generated from git history and GitHub event metadata.\n> Last generated: ${releaseDate}. Run \`npm run changelog:generate\` to refresh this section.\n\n${releaseBlock}\n`
194
+ );
195
+ }
196
+
197
+ const changelog = fs.readFileSync(changelogPath, 'utf8');
198
+ const pkg = readJson(packagePath);
199
+ const latestVersion = getLatestVersionSection(changelog);
200
+ const latestTag = normalizeVersionTag(latestVersion);
201
+ const commitRange = getCommitRange(latestTag);
202
+ const rawLog = git([
203
+ 'log',
204
+ '--reverse',
205
+ '--date=short',
206
+ `--pretty=format:%H%x1f%s%x1f%ad`,
207
+ commitRange
208
+ ]);
209
+
210
+ const eventIssues = getTrackedIssuesFromEvent();
211
+ const commits = rawLog
212
+ .split('\n')
213
+ .filter(Boolean)
214
+ .map((line) => parseCommit(line, eventIssues))
215
+ .filter((entry) => entry.hash);
216
+
217
+ const generatedOn = new Date().toISOString().slice(0, 10);
218
+ let nextChangelog = replaceUnreleasedSection(changelog, buildUnreleasedSection(commits, generatedOn));
219
+
220
+ if (releaseMode) {
221
+ nextChangelog = finalizeRelease(nextChangelog, pkg.version, generatedOn);
222
+ }
223
+
224
+ fs.writeFileSync(changelogPath, nextChangelog);
225
+ process.stdout.write(
226
+ `Updated CHANGELOG.md using ${commits.length} commit${commits.length === 1 ? '' : 's'} from ${commitRange}.\n`
227
+ );