ccjk 14.2.2 → 15.1.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 (532) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +75 -338
  3. package/dist/cli.js +89 -0
  4. package/dist/cli.js.map +1 -0
  5. package/dist/commands/detect.js +15 -0
  6. package/dist/commands/detect.js.map +1 -0
  7. package/dist/commands/doctor.js +68 -0
  8. package/dist/commands/doctor.js.map +1 -0
  9. package/dist/commands/git-install.js +50 -0
  10. package/dist/commands/git-install.js.map +1 -0
  11. package/dist/commands/init.js +165 -0
  12. package/dist/commands/init.js.map +1 -0
  13. package/dist/commands/mcp.js +66 -0
  14. package/dist/commands/mcp.js.map +1 -0
  15. package/dist/commands/menu.js +42 -0
  16. package/dist/commands/menu.js.map +1 -0
  17. package/dist/commands/profile.js +138 -0
  18. package/dist/commands/profile.js.map +1 -0
  19. package/dist/core/detect.js +24 -0
  20. package/dist/core/detect.js.map +1 -0
  21. package/dist/core/lint.js +49 -0
  22. package/dist/core/lint.js.map +1 -0
  23. package/dist/core/mcp.js +41 -0
  24. package/dist/core/mcp.js.map +1 -0
  25. package/dist/core/paths.js +9 -0
  26. package/dist/core/paths.js.map +1 -0
  27. package/dist/core/profiles.js +104 -0
  28. package/dist/core/profiles.js.map +1 -0
  29. package/dist/core/providers.js +53 -0
  30. package/dist/core/providers.js.map +1 -0
  31. package/dist/core/settings.js +31 -0
  32. package/dist/core/settings.js.map +1 -0
  33. package/dist/core/slash-templates.js +56 -0
  34. package/dist/core/slash-templates.js.map +1 -0
  35. package/dist/core/tools.js +27 -0
  36. package/dist/core/tools.js.map +1 -0
  37. package/package.json +43 -164
  38. package/README.HONEST.md +0 -176
  39. package/README.en.md +0 -67
  40. package/README.ja.md +0 -67
  41. package/README.ko.md +0 -67
  42. package/README.zh-CN.md +0 -86
  43. package/bin/ccjk.mjs +0 -5
  44. package/bin/ccjk.ts +0 -222
  45. package/dist/chunks/agent-teams.mjs +0 -145
  46. package/dist/chunks/agent.mjs +0 -1439
  47. package/dist/chunks/agents.mjs +0 -3783
  48. package/dist/chunks/api-cli.mjs +0 -135
  49. package/dist/chunks/api-config-selector.mjs +0 -159
  50. package/dist/chunks/api-providers.mjs +0 -144
  51. package/dist/chunks/api.mjs +0 -115
  52. package/dist/chunks/auto-bootstrap.mjs +0 -358
  53. package/dist/chunks/auto-fixer.mjs +0 -95
  54. package/dist/chunks/auto-updater.mjs +0 -507
  55. package/dist/chunks/banner.mjs +0 -173
  56. package/dist/chunks/bash.mjs +0 -187
  57. package/dist/chunks/boost.mjs +0 -474
  58. package/dist/chunks/brain-config.mjs +0 -75
  59. package/dist/chunks/brain-status.mjs +0 -89
  60. package/dist/chunks/ccjk-agents.mjs +0 -416
  61. package/dist/chunks/ccjk-all.mjs +0 -1046
  62. package/dist/chunks/ccjk-config.mjs +0 -445
  63. package/dist/chunks/ccjk-hooks.mjs +0 -1074
  64. package/dist/chunks/ccjk-mcp.mjs +0 -763
  65. package/dist/chunks/ccjk-setup.mjs +0 -765
  66. package/dist/chunks/ccjk-skills.mjs +0 -518
  67. package/dist/chunks/ccr.mjs +0 -109
  68. package/dist/chunks/ccu.mjs +0 -40
  69. package/dist/chunks/check-updates.mjs +0 -117
  70. package/dist/chunks/claude-code-incremental-manager.mjs +0 -761
  71. package/dist/chunks/claude-config.mjs +0 -606
  72. package/dist/chunks/claude-config2.mjs +0 -62
  73. package/dist/chunks/claude-wrapper.mjs +0 -85
  74. package/dist/chunks/clavue-config.mjs +0 -1454
  75. package/dist/chunks/cleanup-migration.mjs +0 -20
  76. package/dist/chunks/cli-hook.mjs +0 -4096
  77. package/dist/chunks/cloud-sync.mjs +0 -29
  78. package/dist/chunks/code-type-resolver.mjs +0 -880
  79. package/dist/chunks/codex-config-switch.mjs +0 -452
  80. package/dist/chunks/codex-provider-manager.mjs +0 -238
  81. package/dist/chunks/codex-uninstaller.mjs +0 -404
  82. package/dist/chunks/codex.mjs +0 -2141
  83. package/dist/chunks/commands.mjs +0 -108
  84. package/dist/chunks/commands2.mjs +0 -421
  85. package/dist/chunks/commit.mjs +0 -140
  86. package/dist/chunks/completion.mjs +0 -517
  87. package/dist/chunks/config-consolidator.mjs +0 -172
  88. package/dist/chunks/config-switch.mjs +0 -334
  89. package/dist/chunks/config.mjs +0 -558
  90. package/dist/chunks/config2.mjs +0 -484
  91. package/dist/chunks/config3.mjs +0 -486
  92. package/dist/chunks/constants.mjs +0 -323
  93. package/dist/chunks/context-opt.mjs +0 -444
  94. package/dist/chunks/context.mjs +0 -974
  95. package/dist/chunks/dashboard.mjs +0 -481
  96. package/dist/chunks/doctor.mjs +0 -1301
  97. package/dist/chunks/eval.mjs +0 -502
  98. package/dist/chunks/evolution.mjs +0 -322
  99. package/dist/chunks/features.mjs +0 -715
  100. package/dist/chunks/fish.mjs +0 -181
  101. package/dist/chunks/fs-operations.mjs +0 -180
  102. package/dist/chunks/health-alerts.mjs +0 -830
  103. package/dist/chunks/help.mjs +0 -341
  104. package/dist/chunks/hook-installer.mjs +0 -48
  105. package/dist/chunks/impact.mjs +0 -651
  106. package/dist/chunks/index.mjs +0 -23
  107. package/dist/chunks/index10.mjs +0 -19
  108. package/dist/chunks/index11.mjs +0 -1171
  109. package/dist/chunks/index12.mjs +0 -218
  110. package/dist/chunks/index13.mjs +0 -679
  111. package/dist/chunks/index14.mjs +0 -1009
  112. package/dist/chunks/index15.mjs +0 -194
  113. package/dist/chunks/index2.mjs +0 -7637
  114. package/dist/chunks/index3.mjs +0 -171
  115. package/dist/chunks/index4.mjs +0 -26
  116. package/dist/chunks/index5.mjs +0 -19
  117. package/dist/chunks/index6.mjs +0 -19092
  118. package/dist/chunks/index7.mjs +0 -616
  119. package/dist/chunks/index8.mjs +0 -1602
  120. package/dist/chunks/index9.mjs +0 -5384
  121. package/dist/chunks/init.mjs +0 -1911
  122. package/dist/chunks/installer.mjs +0 -757
  123. package/dist/chunks/installer2.mjs +0 -103
  124. package/dist/chunks/interview.mjs +0 -2927
  125. package/dist/chunks/json-config.mjs +0 -60
  126. package/dist/chunks/linux.mjs +0 -3863
  127. package/dist/chunks/macos.mjs +0 -69
  128. package/dist/chunks/main.mjs +0 -635
  129. package/dist/chunks/manager.mjs +0 -1048
  130. package/dist/chunks/marketplace.mjs +0 -265
  131. package/dist/chunks/mcp-cli.mjs +0 -205
  132. package/dist/chunks/mcp-performance.mjs +0 -187
  133. package/dist/chunks/mcp.mjs +0 -667
  134. package/dist/chunks/memory-check.mjs +0 -2973
  135. package/dist/chunks/memory-paths.mjs +0 -259
  136. package/dist/chunks/memory-sync.mjs +0 -209
  137. package/dist/chunks/memory.mjs +0 -354
  138. package/dist/chunks/metrics-display.mjs +0 -153
  139. package/dist/chunks/monitor.mjs +0 -1856
  140. package/dist/chunks/notification.mjs +0 -1864
  141. package/dist/chunks/onboarding.mjs +0 -386
  142. package/dist/chunks/package.mjs +0 -3
  143. package/dist/chunks/paradigm.mjs +0 -74
  144. package/dist/chunks/permission-manager.mjs +0 -250
  145. package/dist/chunks/permissions.mjs +0 -265
  146. package/dist/chunks/persistence-manager.mjs +0 -801
  147. package/dist/chunks/persistence.mjs +0 -707
  148. package/dist/chunks/platform.mjs +0 -395
  149. package/dist/chunks/plugin.mjs +0 -1936
  150. package/dist/chunks/powershell.mjs +0 -213
  151. package/dist/chunks/prompts.mjs +0 -244
  152. package/dist/chunks/providers.mjs +0 -263
  153. package/dist/chunks/quick-actions.mjs +0 -335
  154. package/dist/chunks/quick-provider.mjs +0 -755
  155. package/dist/chunks/quick-setup.mjs +0 -421
  156. package/dist/chunks/remote.mjs +0 -497
  157. package/dist/chunks/research.mjs +0 -1904
  158. package/dist/chunks/rollback.mjs +0 -38
  159. package/dist/chunks/session-manager.mjs +0 -1371
  160. package/dist/chunks/session.mjs +0 -878
  161. package/dist/chunks/sessions.mjs +0 -106
  162. package/dist/chunks/silent-updater.mjs +0 -396
  163. package/dist/chunks/simple-config.mjs +0 -122
  164. package/dist/chunks/skill.mjs +0 -117
  165. package/dist/chunks/skill2.mjs +0 -9052
  166. package/dist/chunks/skills-sync.mjs +0 -1343
  167. package/dist/chunks/skills.mjs +0 -577
  168. package/dist/chunks/slash-commands.mjs +0 -208
  169. package/dist/chunks/smart-guide.mjs +0 -247
  170. package/dist/chunks/snapshot.mjs +0 -58
  171. package/dist/chunks/startup.mjs +0 -487
  172. package/dist/chunks/stats.mjs +0 -191
  173. package/dist/chunks/status.mjs +0 -471
  174. package/dist/chunks/team.mjs +0 -63
  175. package/dist/chunks/thinking.mjs +0 -626
  176. package/dist/chunks/trace.mjs +0 -57
  177. package/dist/chunks/uninstall.mjs +0 -852
  178. package/dist/chunks/update.mjs +0 -174
  179. package/dist/chunks/upgrade-manager.mjs +0 -204
  180. package/dist/chunks/upgrade.mjs +0 -133
  181. package/dist/chunks/version-checker.mjs +0 -891
  182. package/dist/chunks/vim.mjs +0 -903
  183. package/dist/chunks/windows.mjs +0 -14
  184. package/dist/chunks/workflows.mjs +0 -633
  185. package/dist/chunks/wsl.mjs +0 -129
  186. package/dist/chunks/zero-config.mjs +0 -871
  187. package/dist/chunks/zsh.mjs +0 -182
  188. package/dist/cli.d.mts +0 -1
  189. package/dist/cli.d.ts +0 -1
  190. package/dist/cli.mjs +0 -2684
  191. package/dist/i18n/locales/en/agent-teams.json +0 -18
  192. package/dist/i18n/locales/en/agentBrowser.json +0 -80
  193. package/dist/i18n/locales/en/agents.json +0 -135
  194. package/dist/i18n/locales/en/api.json +0 -63
  195. package/dist/i18n/locales/en/ccjk-agents.json +0 -33
  196. package/dist/i18n/locales/en/ccjk-all.json +0 -23
  197. package/dist/i18n/locales/en/ccjk-skills.json +0 -22
  198. package/dist/i18n/locales/en/ccjk.json +0 -276
  199. package/dist/i18n/locales/en/ccr.json +0 -65
  200. package/dist/i18n/locales/en/claude-md.json +0 -73
  201. package/dist/i18n/locales/en/cli.json +0 -148
  202. package/dist/i18n/locales/en/cloud-setup.json +0 -31
  203. package/dist/i18n/locales/en/cloud-sync.json +0 -147
  204. package/dist/i18n/locales/en/cloud.json +0 -40
  205. package/dist/i18n/locales/en/cloudPlugins.json +0 -118
  206. package/dist/i18n/locales/en/codex.json +0 -184
  207. package/dist/i18n/locales/en/cometix.json +0 -29
  208. package/dist/i18n/locales/en/common.json +0 -68
  209. package/dist/i18n/locales/en/config.json +0 -108
  210. package/dist/i18n/locales/en/configuration.json +0 -236
  211. package/dist/i18n/locales/en/context.json +0 -85
  212. package/dist/i18n/locales/en/dashboard.json +0 -78
  213. package/dist/i18n/locales/en/errors.json +0 -26
  214. package/dist/i18n/locales/en/evolution.json +0 -54
  215. package/dist/i18n/locales/en/hooks.json +0 -74
  216. package/dist/i18n/locales/en/hooksSync.json +0 -133
  217. package/dist/i18n/locales/en/installation.json +0 -83
  218. package/dist/i18n/locales/en/interview.json +0 -104
  219. package/dist/i18n/locales/en/language.json +0 -19
  220. package/dist/i18n/locales/en/lsp.json +0 -78
  221. package/dist/i18n/locales/en/marketplace.json +0 -116
  222. package/dist/i18n/locales/en/mcp.json +0 -180
  223. package/dist/i18n/locales/en/memory.json +0 -23
  224. package/dist/i18n/locales/en/menu.json +0 -299
  225. package/dist/i18n/locales/en/multi-config.json +0 -79
  226. package/dist/i18n/locales/en/notification.json +0 -307
  227. package/dist/i18n/locales/en/permissions.json +0 -95
  228. package/dist/i18n/locales/en/persistence.json +0 -127
  229. package/dist/i18n/locales/en/plugins.json +0 -146
  230. package/dist/i18n/locales/en/quick-actions.json +0 -78
  231. package/dist/i18n/locales/en/registry.json +0 -54
  232. package/dist/i18n/locales/en/remote.json +0 -93
  233. package/dist/i18n/locales/en/sandbox.json +0 -44
  234. package/dist/i18n/locales/en/setup.json +0 -44
  235. package/dist/i18n/locales/en/shencha.json +0 -14
  236. package/dist/i18n/locales/en/skills.json +0 -100
  237. package/dist/i18n/locales/en/skillsSync.json +0 -74
  238. package/dist/i18n/locales/en/smartGuide.json +0 -49
  239. package/dist/i18n/locales/en/stats.json +0 -20
  240. package/dist/i18n/locales/en/subagent.json +0 -69
  241. package/dist/i18n/locales/en/superpowers.json +0 -117
  242. package/dist/i18n/locales/en/team.json +0 -7
  243. package/dist/i18n/locales/en/thinking.json +0 -65
  244. package/dist/i18n/locales/en/tools.json +0 -42
  245. package/dist/i18n/locales/en/uninstall.json +0 -56
  246. package/dist/i18n/locales/en/updater.json +0 -29
  247. package/dist/i18n/locales/en/vim.json +0 -169
  248. package/dist/i18n/locales/en/workflow.json +0 -55
  249. package/dist/i18n/locales/en/workspace.json +0 -108
  250. package/dist/i18n/locales/zh-CN/agent-teams.json +0 -18
  251. package/dist/i18n/locales/zh-CN/agentBrowser.json +0 -80
  252. package/dist/i18n/locales/zh-CN/agents.json +0 -135
  253. package/dist/i18n/locales/zh-CN/api.json +0 -63
  254. package/dist/i18n/locales/zh-CN/ccjk-agents.json +0 -33
  255. package/dist/i18n/locales/zh-CN/ccjk-all.json +0 -23
  256. package/dist/i18n/locales/zh-CN/ccjk-skills.json +0 -22
  257. package/dist/i18n/locales/zh-CN/ccjk.json +0 -276
  258. package/dist/i18n/locales/zh-CN/ccr.json +0 -65
  259. package/dist/i18n/locales/zh-CN/claude-md.json +0 -73
  260. package/dist/i18n/locales/zh-CN/cli.json +0 -148
  261. package/dist/i18n/locales/zh-CN/cloud-setup.json +0 -31
  262. package/dist/i18n/locales/zh-CN/cloud-sync.json +0 -147
  263. package/dist/i18n/locales/zh-CN/cloud.json +0 -40
  264. package/dist/i18n/locales/zh-CN/cloudPlugins.json +0 -118
  265. package/dist/i18n/locales/zh-CN/codex.json +0 -184
  266. package/dist/i18n/locales/zh-CN/cometix.json +0 -29
  267. package/dist/i18n/locales/zh-CN/common.json +0 -68
  268. package/dist/i18n/locales/zh-CN/config.json +0 -108
  269. package/dist/i18n/locales/zh-CN/configuration.json +0 -234
  270. package/dist/i18n/locales/zh-CN/context.json +0 -85
  271. package/dist/i18n/locales/zh-CN/dashboard.json +0 -78
  272. package/dist/i18n/locales/zh-CN/errors.json +0 -26
  273. package/dist/i18n/locales/zh-CN/evolution.json +0 -54
  274. package/dist/i18n/locales/zh-CN/hooks.json +0 -74
  275. package/dist/i18n/locales/zh-CN/hooksSync.json +0 -133
  276. package/dist/i18n/locales/zh-CN/installation.json +0 -83
  277. package/dist/i18n/locales/zh-CN/interview.json +0 -104
  278. package/dist/i18n/locales/zh-CN/language.json +0 -19
  279. package/dist/i18n/locales/zh-CN/lsp.json +0 -78
  280. package/dist/i18n/locales/zh-CN/marketplace.json +0 -116
  281. package/dist/i18n/locales/zh-CN/mcp.json +0 -180
  282. package/dist/i18n/locales/zh-CN/memory.json +0 -23
  283. package/dist/i18n/locales/zh-CN/menu.json +0 -299
  284. package/dist/i18n/locales/zh-CN/multi-config.json +0 -79
  285. package/dist/i18n/locales/zh-CN/notification.json +0 -307
  286. package/dist/i18n/locales/zh-CN/permissions.json +0 -95
  287. package/dist/i18n/locales/zh-CN/persistence.json +0 -127
  288. package/dist/i18n/locales/zh-CN/plugins.json +0 -146
  289. package/dist/i18n/locales/zh-CN/quick-actions.json +0 -78
  290. package/dist/i18n/locales/zh-CN/registry.json +0 -54
  291. package/dist/i18n/locales/zh-CN/remote.json +0 -93
  292. package/dist/i18n/locales/zh-CN/sandbox.json +0 -44
  293. package/dist/i18n/locales/zh-CN/setup.json +0 -44
  294. package/dist/i18n/locales/zh-CN/shencha.json +0 -14
  295. package/dist/i18n/locales/zh-CN/skills.json +0 -100
  296. package/dist/i18n/locales/zh-CN/skillsSync.json +0 -74
  297. package/dist/i18n/locales/zh-CN/smartGuide.json +0 -49
  298. package/dist/i18n/locales/zh-CN/stats.json +0 -20
  299. package/dist/i18n/locales/zh-CN/subagent.json +0 -69
  300. package/dist/i18n/locales/zh-CN/superpowers.json +0 -117
  301. package/dist/i18n/locales/zh-CN/team.json +0 -7
  302. package/dist/i18n/locales/zh-CN/thinking.json +0 -65
  303. package/dist/i18n/locales/zh-CN/tools.json +0 -42
  304. package/dist/i18n/locales/zh-CN/uninstall.json +0 -56
  305. package/dist/i18n/locales/zh-CN/updater.json +0 -29
  306. package/dist/i18n/locales/zh-CN/vim.json +0 -169
  307. package/dist/i18n/locales/zh-CN/workflow.json +0 -55
  308. package/dist/i18n/locales/zh-CN/workspace.json +0 -108
  309. package/dist/index.d.mts +0 -5658
  310. package/dist/index.d.ts +0 -5658
  311. package/dist/index.mjs +0 -3732
  312. package/dist/shared/ccjk.5bEolFrk.mjs +0 -254
  313. package/dist/shared/ccjk.8oaxX4iR.mjs +0 -90
  314. package/dist/shared/ccjk.B2U7DsPy.mjs +0 -31
  315. package/dist/shared/ccjk.B2f-cwUP.mjs +0 -468
  316. package/dist/shared/ccjk.BAGoDD49.mjs +0 -36
  317. package/dist/shared/ccjk.BBtCGd_g.mjs +0 -899
  318. package/dist/shared/ccjk.BFQ7yr5S.mjs +0 -16
  319. package/dist/shared/ccjk.BLsIiTqO.mjs +0 -449
  320. package/dist/shared/ccjk.BXv8aYs1.mjs +0 -170
  321. package/dist/shared/ccjk.BnsY5WxD.mjs +0 -171
  322. package/dist/shared/ccjk.BoApaI4j.mjs +0 -28
  323. package/dist/shared/ccjk.Bq8TqZG_.mjs +0 -189
  324. package/dist/shared/ccjk.BtrioX1Z.mjs +0 -25
  325. package/dist/shared/ccjk.Bx_rmYfN.mjs +0 -69
  326. package/dist/shared/ccjk.BzPbSEP2.mjs +0 -115
  327. package/dist/shared/ccjk.C0WLUnFV.mjs +0 -293
  328. package/dist/shared/ccjk.C1hANZTu.mjs +0 -19
  329. package/dist/shared/ccjk.C2jHOZVP.mjs +0 -52
  330. package/dist/shared/ccjk.CNhnT6uQ.mjs +0 -636
  331. package/dist/shared/ccjk.COweQ1RR.mjs +0 -5
  332. package/dist/shared/ccjk.CfKKcvWy.mjs +0 -126
  333. package/dist/shared/ccjk.Cjgrln_h.mjs +0 -297
  334. package/dist/shared/ccjk.CoCHVXl3.mjs +0 -3951
  335. package/dist/shared/ccjk.CwGZSTAK.mjs +0 -319
  336. package/dist/shared/ccjk.CxpGa6MC.mjs +0 -2724
  337. package/dist/shared/ccjk.D-magaEx.mjs +0 -763
  338. package/dist/shared/ccjk.D0g2ABGg.mjs +0 -171
  339. package/dist/shared/ccjk.D6ycHbak.mjs +0 -270
  340. package/dist/shared/ccjk.D75wivnp.mjs +0 -142
  341. package/dist/shared/ccjk.DDL-4C-k.mjs +0 -100
  342. package/dist/shared/ccjk.DFRPtmK_.mjs +0 -75
  343. package/dist/shared/ccjk.DMV3x5Sd.mjs +0 -299
  344. package/dist/shared/ccjk.DZ2LLOa-.mjs +0 -2195
  345. package/dist/shared/ccjk.DbigonEQ.mjs +0 -698
  346. package/dist/shared/ccjk.DcMvE7lf.mjs +0 -618
  347. package/dist/shared/ccjk.DeWpAShp.mjs +0 -1828
  348. package/dist/shared/ccjk.DhJ1kyDR.mjs +0 -30
  349. package/dist/shared/ccjk.DlTXS9rP.mjs +0 -224
  350. package/dist/shared/ccjk.DopKzo3z.mjs +0 -305
  351. package/dist/shared/ccjk.DsZsc4LR.mjs +0 -1280
  352. package/dist/shared/ccjk.DuzJZlgj.mjs +0 -418
  353. package/dist/shared/ccjk.Dxgd2vjc.mjs +0 -444
  354. package/dist/shared/ccjk.J8YiPsOw.mjs +0 -259
  355. package/dist/shared/ccjk.KfSWcGlE.mjs +0 -38
  356. package/dist/shared/ccjk.L7yC58_i.mjs +0 -225
  357. package/dist/shared/ccjk.MwtjAULc.mjs +0 -1447
  358. package/dist/shared/ccjk.OJKHVSOb.mjs +0 -2005
  359. package/dist/shared/ccjk.OTnevPNE.mjs +0 -225
  360. package/dist/shared/ccjk.RyizuzOI.mjs +0 -21
  361. package/dist/shared/ccjk.T_cX87dY.mjs +0 -15
  362. package/dist/shared/ccjk.bQ7Dh1g4.mjs +0 -249
  363. package/dist/shared/ccjk.gDEDGD_t.mjs +0 -38
  364. package/dist/shared/ccjk.hoqrwWdN.mjs +0 -333
  365. package/dist/shared/ccjk.i_vn-9C3.mjs +0 -317
  366. package/dist/shared/ccjk.lG3ccFjm.mjs +0 -885
  367. package/dist/shared/ccjk.wLJHO0Af.mjs +0 -244
  368. package/dist/shared/ccjk.y-a_1vK4.mjs +0 -5127
  369. package/dist/templates/agents/README.md +0 -78
  370. package/dist/templates/agents/fullstack-developer.json +0 -70
  371. package/dist/templates/agents/go-expert.json +0 -69
  372. package/dist/templates/agents/index.json +0 -64
  373. package/dist/templates/agents/python-expert.json +0 -69
  374. package/dist/templates/agents/react-specialist.json +0 -69
  375. package/dist/templates/agents/testing-automation-expert.json +0 -70
  376. package/dist/templates/agents/typescript-architect.json +0 -69
  377. package/dist/templates/claude-code/common/settings.json +0 -109
  378. package/dist/templates/common/error-prevention.md +0 -267
  379. package/dist/templates/common/karpathy-baseline.md +0 -83
  380. package/dist/templates/common/output-styles/zh-CN/carmack-mode.md +0 -381
  381. package/dist/templates/common/output-styles/zh-CN/codex-rigor-mode.md +0 -114
  382. package/dist/templates/common/output-styles/zh-CN/dhh-mode.md +0 -265
  383. package/dist/templates/common/output-styles/zh-CN/evan-you-mode.md +0 -539
  384. package/dist/templates/common/output-styles/zh-CN/jobs-mode.md +0 -369
  385. package/dist/templates/common/output-styles/zh-CN/linus-mode.md +0 -135
  386. package/dist/templates/common/output-styles/zh-CN/uncle-bob-mode.md +0 -221
  387. package/dist/templates/common/workflow/continuousDelivery/en/continuous-delivery.md +0 -628
  388. package/dist/templates/common/workflow/continuousDelivery/zh-CN/continuous-delivery.md +0 -628
  389. package/dist/templates/common/workflow/essential/en/agents/ccjk-config-agent.md +0 -187
  390. package/dist/templates/common/workflow/essential/en/agents/ccjk-mcp-agent.md +0 -191
  391. package/dist/templates/common/workflow/essential/en/agents/ccjk-skill-agent.md +0 -249
  392. package/dist/templates/common/workflow/essential/en/agents/ccjk-workflow-agent.md +0 -277
  393. package/dist/templates/common/workflow/essential/en/agents/get-current-datetime.md +0 -29
  394. package/dist/templates/common/workflow/essential/en/agents/init-architect.md +0 -115
  395. package/dist/templates/common/workflow/essential/en/agents/ui-ux-designer.md +0 -91
  396. package/dist/templates/common/workflow/essential/en/feat.md +0 -92
  397. package/dist/templates/common/workflow/essential/en/goal.md +0 -147
  398. package/dist/templates/common/workflow/essential/en/init-project.md +0 -53
  399. package/dist/templates/common/workflow/essential/zh-CN/agents/get-current-datetime.md +0 -29
  400. package/dist/templates/common/workflow/essential/zh-CN/agents/init-architect.md +0 -115
  401. package/dist/templates/common/workflow/essential/zh-CN/agents/ui-ux-designer.md +0 -91
  402. package/dist/templates/common/workflow/essential/zh-CN/feat.md +0 -315
  403. package/dist/templates/common/workflow/essential/zh-CN/goal.md +0 -146
  404. package/dist/templates/common/workflow/essential/zh-CN/init-project.md +0 -53
  405. package/dist/templates/common/workflow/git/en/git-cleanBranches.md +0 -102
  406. package/dist/templates/common/workflow/git/en/git-commit.md +0 -205
  407. package/dist/templates/common/workflow/git/en/git-rollback.md +0 -90
  408. package/dist/templates/common/workflow/git/en/git-worktree.md +0 -276
  409. package/dist/templates/common/workflow/git/zh-CN/git-cleanBranches.md +0 -102
  410. package/dist/templates/common/workflow/git/zh-CN/git-commit.md +0 -205
  411. package/dist/templates/common/workflow/git/zh-CN/git-rollback.md +0 -90
  412. package/dist/templates/common/workflow/git/zh-CN/git-worktree.md +0 -276
  413. package/dist/templates/common/workflow/interview/en/interview.md +0 -67
  414. package/dist/templates/common/workflow/interview/zh-CN/interview.md +0 -67
  415. package/dist/templates/common/workflow/linearMethod/en/linear-method.md +0 -651
  416. package/dist/templates/common/workflow/linearMethod/zh-CN/linear-method.md +0 -752
  417. package/dist/templates/common/workflow/refactoringMaster/en/refactoring-master.md +0 -516
  418. package/dist/templates/common/workflow/refactoringMaster/zh-CN/refactoring-master.md +0 -812
  419. package/dist/templates/common/workflow/sixStep/en/workflow.md +0 -83
  420. package/dist/templates/common/workflow/sixStep/zh-CN/workflow.md +0 -359
  421. package/dist/templates/common/workflow/specFirstTDD/en/spec-first-tdd.md +0 -364
  422. package/dist/templates/common/workflow/specFirstTDD/zh-CN/spec-first-tdd.md +0 -366
  423. package/dist/templates/hooks/README.md +0 -212
  424. package/dist/templates/hooks/git-workflow-hooks.md +0 -551
  425. package/dist/templates/hooks/post-test/coverage.json +0 -21
  426. package/dist/templates/hooks/post-test/summary.json +0 -21
  427. package/dist/templates/hooks/post-test-coverage.md +0 -434
  428. package/dist/templates/hooks/pre-commit/eslint.json +0 -22
  429. package/dist/templates/hooks/pre-commit/prettier.json +0 -22
  430. package/dist/templates/hooks/pre-commit-black.md +0 -274
  431. package/dist/templates/hooks/pre-commit-eslint.md +0 -153
  432. package/dist/templates/hooks/pre-commit-gofmt.md +0 -284
  433. package/dist/templates/hooks/pre-commit-prettier.md +0 -212
  434. package/dist/templates/hooks/pre-commit-type-check.md +0 -377
  435. package/dist/templates/skills/ccjk-init.md +0 -154
  436. package/dist/templates/skills/ccjk-mcp-setup.md +0 -205
  437. package/dist/templates/skills/ccjk-troubleshoot.md +0 -228
  438. package/dist/templates/skills/django-patterns.md +0 -1016
  439. package/dist/templates/skills/git-workflow.md +0 -748
  440. package/dist/templates/skills/go-idioms.md +0 -963
  441. package/dist/templates/skills/index.json +0 -132
  442. package/dist/templates/skills/nextjs-optimization.md +0 -694
  443. package/dist/templates/skills/python-pep8.md +0 -852
  444. package/dist/templates/skills/react-patterns.md +0 -686
  445. package/dist/templates/skills/rust-patterns.md +0 -1057
  446. package/dist/templates/skills/security-best-practices.md +0 -1413
  447. package/dist/templates/skills/testing-best-practices.md +0 -1315
  448. package/dist/templates/skills/ts-best-practices.md +0 -354
  449. package/templates/agents/README.md +0 -78
  450. package/templates/agents/fullstack-developer.json +0 -70
  451. package/templates/agents/go-expert.json +0 -69
  452. package/templates/agents/index.json +0 -64
  453. package/templates/agents/python-expert.json +0 -69
  454. package/templates/agents/react-specialist.json +0 -69
  455. package/templates/agents/testing-automation-expert.json +0 -70
  456. package/templates/agents/typescript-architect.json +0 -69
  457. package/templates/claude-code/common/settings.json +0 -109
  458. package/templates/common/error-prevention.md +0 -267
  459. package/templates/common/karpathy-baseline.md +0 -83
  460. package/templates/common/output-styles/zh-CN/carmack-mode.md +0 -381
  461. package/templates/common/output-styles/zh-CN/codex-rigor-mode.md +0 -114
  462. package/templates/common/output-styles/zh-CN/dhh-mode.md +0 -265
  463. package/templates/common/output-styles/zh-CN/evan-you-mode.md +0 -539
  464. package/templates/common/output-styles/zh-CN/jobs-mode.md +0 -369
  465. package/templates/common/output-styles/zh-CN/linus-mode.md +0 -135
  466. package/templates/common/output-styles/zh-CN/uncle-bob-mode.md +0 -221
  467. package/templates/common/workflow/continuousDelivery/en/continuous-delivery.md +0 -628
  468. package/templates/common/workflow/continuousDelivery/zh-CN/continuous-delivery.md +0 -628
  469. package/templates/common/workflow/essential/en/agents/ccjk-config-agent.md +0 -187
  470. package/templates/common/workflow/essential/en/agents/ccjk-mcp-agent.md +0 -191
  471. package/templates/common/workflow/essential/en/agents/ccjk-skill-agent.md +0 -249
  472. package/templates/common/workflow/essential/en/agents/ccjk-workflow-agent.md +0 -277
  473. package/templates/common/workflow/essential/en/agents/get-current-datetime.md +0 -29
  474. package/templates/common/workflow/essential/en/agents/init-architect.md +0 -115
  475. package/templates/common/workflow/essential/en/agents/ui-ux-designer.md +0 -91
  476. package/templates/common/workflow/essential/en/feat.md +0 -92
  477. package/templates/common/workflow/essential/en/goal.md +0 -147
  478. package/templates/common/workflow/essential/en/init-project.md +0 -53
  479. package/templates/common/workflow/essential/zh-CN/agents/get-current-datetime.md +0 -29
  480. package/templates/common/workflow/essential/zh-CN/agents/init-architect.md +0 -115
  481. package/templates/common/workflow/essential/zh-CN/agents/ui-ux-designer.md +0 -91
  482. package/templates/common/workflow/essential/zh-CN/feat.md +0 -315
  483. package/templates/common/workflow/essential/zh-CN/goal.md +0 -146
  484. package/templates/common/workflow/essential/zh-CN/init-project.md +0 -53
  485. package/templates/common/workflow/git/en/git-cleanBranches.md +0 -102
  486. package/templates/common/workflow/git/en/git-commit.md +0 -205
  487. package/templates/common/workflow/git/en/git-rollback.md +0 -90
  488. package/templates/common/workflow/git/en/git-worktree.md +0 -276
  489. package/templates/common/workflow/git/zh-CN/git-cleanBranches.md +0 -102
  490. package/templates/common/workflow/git/zh-CN/git-commit.md +0 -205
  491. package/templates/common/workflow/git/zh-CN/git-rollback.md +0 -90
  492. package/templates/common/workflow/git/zh-CN/git-worktree.md +0 -276
  493. package/templates/common/workflow/interview/en/interview.md +0 -67
  494. package/templates/common/workflow/interview/zh-CN/interview.md +0 -67
  495. package/templates/common/workflow/linearMethod/en/linear-method.md +0 -651
  496. package/templates/common/workflow/linearMethod/zh-CN/linear-method.md +0 -752
  497. package/templates/common/workflow/refactoringMaster/en/refactoring-master.md +0 -516
  498. package/templates/common/workflow/refactoringMaster/zh-CN/refactoring-master.md +0 -812
  499. package/templates/common/workflow/sixStep/en/workflow.md +0 -83
  500. package/templates/common/workflow/sixStep/zh-CN/workflow.md +0 -359
  501. package/templates/common/workflow/specFirstTDD/en/spec-first-tdd.md +0 -364
  502. package/templates/common/workflow/specFirstTDD/zh-CN/spec-first-tdd.md +0 -366
  503. package/templates/hooks/README.md +0 -212
  504. package/templates/hooks/git-workflow-hooks.md +0 -551
  505. package/templates/hooks/post-test/coverage.json +0 -21
  506. package/templates/hooks/post-test/summary.json +0 -21
  507. package/templates/hooks/post-test-coverage.md +0 -434
  508. package/templates/hooks/pre-commit/eslint.json +0 -22
  509. package/templates/hooks/pre-commit/prettier.json +0 -22
  510. package/templates/hooks/pre-commit-black.md +0 -274
  511. package/templates/hooks/pre-commit-eslint.md +0 -153
  512. package/templates/hooks/pre-commit-gofmt.md +0 -284
  513. package/templates/hooks/pre-commit-prettier.md +0 -212
  514. package/templates/hooks/pre-commit-type-check.md +0 -377
  515. package/templates/skills/basic.hbs +0 -72
  516. package/templates/skills/ccjk-init.md +0 -154
  517. package/templates/skills/ccjk-mcp-setup.md +0 -205
  518. package/templates/skills/ccjk-troubleshoot.md +0 -228
  519. package/templates/skills/code-refactor.hbs +0 -133
  520. package/templates/skills/code-review.hbs +0 -141
  521. package/templates/skills/django-patterns.md +0 -1016
  522. package/templates/skills/git-workflow.md +0 -748
  523. package/templates/skills/go-idioms.md +0 -963
  524. package/templates/skills/index.json +0 -132
  525. package/templates/skills/nextjs-optimization.md +0 -694
  526. package/templates/skills/python-pep8.md +0 -852
  527. package/templates/skills/react-patterns.md +0 -686
  528. package/templates/skills/rust-patterns.md +0 -1057
  529. package/templates/skills/security-best-practices.md +0 -1413
  530. package/templates/skills/testing-best-practices.md +0 -1315
  531. package/templates/skills/ts-best-practices.md +0 -354
  532. package/templates/skills/type-fix.hbs +0 -132
@@ -1,1904 +0,0 @@
1
- import a from './index5.mjs';
2
- import { n as nanoid } from '../shared/ccjk.BoApaI4j.mjs';
3
- import { T as TaskPersistence } from '../shared/ccjk.CNhnT6uQ.mjs';
4
- import { m as matter } from '../shared/ccjk.y-a_1vK4.mjs';
5
- import { writeFile, readFile } from './fs-operations.mjs';
6
- import { j as join, d as dirname } from '../shared/ccjk.bQ7Dh1g4.mjs';
7
- import { existsSync, readFileSync, appendFileSync, writeFileSync, mkdirSync } from 'node:fs';
8
- import { homedir } from 'node:os';
9
- import { e as executeCommand } from '../shared/ccjk.BnsY5WxD.mjs';
10
- import '../shared/ccjk.BAGoDD49.mjs';
11
- import 'node:crypto';
12
- import 'better-sqlite3';
13
- import 'fs';
14
- import '../shared/ccjk.COweQ1RR.mjs';
15
- import 'node:fs/promises';
16
- import 'node:child_process';
17
- import 'node:util';
18
-
19
- const DEFAULT_RESEARCH_PROGRAM_PATH = ".ccjk/research/program.md";
20
- const DEFAULT_RESEARCH_MAX_ROUNDS = 10;
21
- const DEFAULT_RESEARCH_MAX_NO_IMPROVE_ROUNDS = 3;
22
- const DEFAULT_RESEARCH_BUDGET_MS = 5 * 60 * 1e3;
23
- function normalizePositiveInteger(value, fallback) {
24
- if (typeof value === "number" && Number.isInteger(value) && value > 0) {
25
- return value;
26
- }
27
- if (typeof value === "string" && value.trim()) {
28
- const parsed = Number.parseInt(value.trim(), 10);
29
- if (Number.isInteger(parsed) && parsed > 0) {
30
- return parsed;
31
- }
32
- }
33
- return fallback;
34
- }
35
- function normalizeOptionalNumber(value) {
36
- if (typeof value === "number" && Number.isFinite(value)) {
37
- return value;
38
- }
39
- if (typeof value === "string" && value.trim()) {
40
- const parsed = Number.parseFloat(value.trim());
41
- if (Number.isFinite(parsed)) {
42
- return parsed;
43
- }
44
- }
45
- return void 0;
46
- }
47
- function normalizeObjective(value) {
48
- return value === "maximize" || value === "minimize" || value === "auto" ? value : "auto";
49
- }
50
- function normalizeString(value) {
51
- if (typeof value !== "string") {
52
- return void 0;
53
- }
54
- const trimmed = value.trim();
55
- return trimmed || void 0;
56
- }
57
- function resolveResearchProgramPath(programPath, cwd) {
58
- return programPath ? join(cwd || process.cwd(), programPath) : join(cwd || process.cwd(), DEFAULT_RESEARCH_PROGRAM_PATH);
59
- }
60
- function createDefaultResearchProgramTemplate(cwd) {
61
- const workingDirectory = cwd || process.cwd();
62
- return `---
63
- name: repo-research
64
- metric: test_pass_rate
65
- objective: maximize
66
- baselineCommand: pnpm test:run
67
- candidateCommand: pnpm test:run
68
- cwd: ${workingDirectory}
69
- maxRounds: ${DEFAULT_RESEARCH_MAX_ROUNDS}
70
- maxNoImproveRounds: ${DEFAULT_RESEARCH_MAX_NO_IMPROVE_ROUNDS}
71
- budgetMs: ${DEFAULT_RESEARCH_BUDGET_MS}
72
- targetMetric:
73
- ---
74
-
75
- # Research Goal
76
-
77
- Describe the optimization target for this repository.
78
-
79
- ## Guardrails
80
-
81
- - Keep changes scoped and measurable.
82
- - Prefer one candidate change per round.
83
- - Stop when the target metric is reached or repeated no-improvement rounds occur.
84
-
85
- ## Notes
86
-
87
- Document hypotheses, constraints, and any files or modules that must not change.
88
- `;
89
- }
90
- function parseResearchProgram(content, programPath = DEFAULT_RESEARCH_PROGRAM_PATH) {
91
- const parsed = matter(content);
92
- const data = parsed.data || {};
93
- const baselineCommand = normalizeString(data.baselineCommand);
94
- if (!baselineCommand) {
95
- throw new Error(`Missing required 'baselineCommand' in ${programPath}`);
96
- }
97
- const candidateCommand = normalizeString(data.candidateCommand);
98
- if (!candidateCommand) {
99
- throw new Error(`Missing required 'candidateCommand' in ${programPath}`);
100
- }
101
- return {
102
- name: normalizeString(data.name) || "repo-research",
103
- metric: normalizeString(data.metric),
104
- objective: normalizeObjective(data.objective),
105
- baselineCommand,
106
- candidateCommand,
107
- cwd: normalizeString(data.cwd) || process.cwd(),
108
- maxRounds: normalizePositiveInteger(data.maxRounds, DEFAULT_RESEARCH_MAX_ROUNDS),
109
- maxNoImproveRounds: normalizePositiveInteger(data.maxNoImproveRounds, DEFAULT_RESEARCH_MAX_NO_IMPROVE_ROUNDS),
110
- budgetMs: normalizePositiveInteger(data.budgetMs, DEFAULT_RESEARCH_BUDGET_MS),
111
- targetMetric: normalizeOptionalNumber(data.targetMetric),
112
- notes: parsed.content.trim(),
113
- programPath
114
- };
115
- }
116
- function readResearchProgram(programPath, cwd) {
117
- const resolvedPath = resolveResearchProgramPath(programPath, cwd);
118
- const content = readFile(resolvedPath);
119
- return parseResearchProgram(content, resolvedPath);
120
- }
121
- function initResearchProgram(programPath, cwd) {
122
- const resolvedPath = resolveResearchProgramPath(programPath, cwd);
123
- const content = createDefaultResearchProgramTemplate(cwd);
124
- writeFile(resolvedPath, content);
125
- return {
126
- programPath: resolvedPath,
127
- content
128
- };
129
- }
130
-
131
- class TaskQueue {
132
- queue = [];
133
- runningTasks = /* @__PURE__ */ new Set();
134
- stats;
135
- options;
136
- taskIdCounter = 0;
137
- executionTimes = [];
138
- processing = false;
139
- paused = false;
140
- constructor(options = {}) {
141
- this.options = {
142
- concurrency: options.concurrency ?? Number.POSITIVE_INFINITY,
143
- defaultTimeout: options.defaultTimeout ?? 3e4,
144
- defaultMaxRetries: options.defaultMaxRetries ?? 0,
145
- defaultRetryDelay: options.defaultRetryDelay ?? 1e3,
146
- autoStart: options.autoStart ?? true
147
- };
148
- this.stats = {
149
- totalTasks: 0,
150
- pendingTasks: 0,
151
- runningTasks: 0,
152
- completedTasks: 0,
153
- failedTasks: 0,
154
- timeoutTasks: 0,
155
- averageExecutionTime: 0,
156
- createdAt: Date.now()
157
- };
158
- if (this.options.autoStart) {
159
- this.start();
160
- }
161
- }
162
- /**
163
- * Add a task to the queue
164
- */
165
- add(execute, options = {}) {
166
- return new Promise((resolve, reject) => {
167
- const task = {
168
- id: this.generateTaskId(),
169
- execute,
170
- options: {
171
- priority: options.priority ?? "normal",
172
- timeout: options.timeout ?? this.options.defaultTimeout,
173
- maxRetries: options.maxRetries ?? this.options.defaultMaxRetries,
174
- retryDelay: options.retryDelay ?? this.options.defaultRetryDelay,
175
- retryBackoff: options.retryBackoff ?? 1,
176
- metadata: options.metadata ?? {}
177
- },
178
- createdAt: Date.now(),
179
- retryCount: 0,
180
- status: "pending",
181
- resolve,
182
- reject
183
- };
184
- this.queue.push(task);
185
- this.stats.totalTasks++;
186
- this.stats.pendingTasks++;
187
- this.sortQueue();
188
- if (!this.paused) {
189
- this.processQueue();
190
- }
191
- });
192
- }
193
- /**
194
- * Start queue processing
195
- */
196
- start() {
197
- this.paused = false;
198
- this.processQueue();
199
- }
200
- /**
201
- * Pause queue processing
202
- */
203
- pause() {
204
- this.paused = true;
205
- }
206
- /**
207
- * Resume queue processing
208
- */
209
- resume() {
210
- this.start();
211
- }
212
- /**
213
- * Clear all pending tasks
214
- */
215
- clear() {
216
- const pendingTasks = this.queue.filter((task) => task.status === "pending");
217
- pendingTasks.forEach((task) => {
218
- task.status = "failed";
219
- task.reject(new Error("Task cancelled: queue cleared"));
220
- });
221
- this.queue = this.queue.filter((task) => task.status === "running");
222
- this.stats.pendingTasks = 0;
223
- }
224
- /**
225
- * Wait for all tasks to complete
226
- */
227
- async drain() {
228
- while (this.queue.length > 0 || this.runningTasks.size > 0) {
229
- await new Promise((resolve) => setTimeout(resolve, 100));
230
- }
231
- }
232
- /**
233
- * Get queue statistics
234
- */
235
- getStats() {
236
- return { ...this.stats };
237
- }
238
- /**
239
- * Get current queue size
240
- */
241
- size() {
242
- return this.queue.length;
243
- }
244
- /**
245
- * Check if queue is empty
246
- */
247
- isEmpty() {
248
- return this.queue.length === 0 && this.runningTasks.size === 0;
249
- }
250
- /**
251
- * Check if queue is paused
252
- */
253
- isPaused() {
254
- return this.paused;
255
- }
256
- /**
257
- * Process tasks in the queue
258
- */
259
- async processQueue() {
260
- if (this.processing || this.paused) {
261
- return;
262
- }
263
- this.processing = true;
264
- while (!this.paused && this.queue.length > 0 && this.runningTasks.size < this.options.concurrency) {
265
- const task = this.queue.find((t) => t.status === "pending");
266
- if (!task) {
267
- break;
268
- }
269
- task.status = "running";
270
- this.stats.pendingTasks--;
271
- this.stats.runningTasks++;
272
- this.runningTasks.add(task.id);
273
- this.executeTask(task).catch(() => {
274
- });
275
- }
276
- this.processing = false;
277
- }
278
- /**
279
- * Execute a single task with timeout and retry support
280
- */
281
- async executeTask(task) {
282
- const startTime = Date.now();
283
- try {
284
- const timeoutPromise = new Promise((_, reject) => {
285
- setTimeout(() => {
286
- reject(new Error(`Task timeout after ${task.options.timeout}ms`));
287
- }, task.options.timeout);
288
- });
289
- const result = await Promise.race([
290
- task.execute(),
291
- timeoutPromise
292
- ]);
293
- const executionTime = Date.now() - startTime;
294
- this.recordExecutionTime(executionTime);
295
- task.status = "completed";
296
- this.stats.completedTasks++;
297
- task.resolve(result);
298
- } catch (error) {
299
- const isTimeout = error instanceof Error && error.message.includes("timeout");
300
- if (isTimeout) {
301
- task.status = "timeout";
302
- this.stats.timeoutTasks++;
303
- }
304
- if (task.retryCount < task.options.maxRetries) {
305
- task.retryCount++;
306
- task.status = "pending";
307
- const delay = task.options.retryDelay * task.options.retryBackoff ** (task.retryCount - 1);
308
- setTimeout(() => {
309
- this.stats.pendingTasks++;
310
- this.sortQueue();
311
- this.processQueue();
312
- }, delay);
313
- } else {
314
- task.status = "failed";
315
- this.stats.failedTasks++;
316
- task.reject(error instanceof Error ? error : new Error(String(error)));
317
- }
318
- } finally {
319
- this.runningTasks.delete(task.id);
320
- this.stats.runningTasks--;
321
- if (task.status === "completed" || task.status === "failed" || task.status === "timeout") {
322
- this.queue = this.queue.filter((t) => t.id !== task.id);
323
- }
324
- this.processQueue();
325
- }
326
- }
327
- /**
328
- * Sort queue by priority
329
- */
330
- sortQueue() {
331
- const priorityOrder = {
332
- critical: 0,
333
- high: 1,
334
- normal: 2,
335
- low: 3
336
- };
337
- this.queue.sort((a, b) => {
338
- const priorityDiff = priorityOrder[a.options.priority] - priorityOrder[b.options.priority];
339
- if (priorityDiff !== 0) {
340
- return priorityDiff;
341
- }
342
- return a.createdAt - b.createdAt;
343
- });
344
- }
345
- /**
346
- * Generate unique task ID
347
- */
348
- generateTaskId() {
349
- return `task_${++this.taskIdCounter}_${Date.now()}`;
350
- }
351
- /**
352
- * Record task execution time for statistics
353
- */
354
- recordExecutionTime(time) {
355
- this.executionTimes.push(time);
356
- if (this.executionTimes.length > 100) {
357
- this.executionTimes.shift();
358
- }
359
- const sum = this.executionTimes.reduce((acc, t) => acc + t, 0);
360
- this.stats.averageExecutionTime = sum / this.executionTimes.length;
361
- }
362
- }
363
-
364
- const DEFAULT_BUDGET_MS = 5 * 60 * 1e3;
365
- const DEFAULT_SESSION_LIMIT = 10;
366
- const RESEARCH_SESSION_KIND = "research";
367
- const RESULTS_LEDGER_FILE = "research-results.tsv";
368
- const RESULTS_LEDGER_HEADERS = [
369
- "timestamp",
370
- "sessionId",
371
- "taskId",
372
- "name",
373
- "phase",
374
- "verdict",
375
- "status",
376
- "exitCode",
377
- "metricName",
378
- "metricValue",
379
- "durationMs",
380
- "cwd",
381
- "command"
382
- ];
383
- class ResearchCommandError extends Error {
384
- constructor(result) {
385
- super(result.error || `Command exited with code ${result.exitCode}`);
386
- this.result = result;
387
- this.name = "ResearchCommandError";
388
- }
389
- }
390
- function createPersistence$1(dbPath) {
391
- return new TaskPersistence(dbPath);
392
- }
393
- function getResearchDataDir(dbPath) {
394
- const resolvedDbPath = dbPath || join(homedir(), ".ccjk", "brain.db");
395
- const dir = dirname(resolvedDbPath);
396
- if (!existsSync(dir)) {
397
- mkdirSync(dir, { recursive: true });
398
- }
399
- return dir;
400
- }
401
- function getResultsLedgerPath(dbPath) {
402
- return join(getResearchDataDir(dbPath), RESULTS_LEDGER_FILE);
403
- }
404
- function escapeRegex(value) {
405
- return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
406
- }
407
- function extractMetricValue(output, metricName) {
408
- if (!metricName) {
409
- return void 0;
410
- }
411
- const matcher = new RegExp(`(?:^|\\b)${escapeRegex(metricName)}\\s*[:=]\\s*(-?\\d+(?:\\.\\d+)?)`, "im");
412
- const match = output.match(matcher);
413
- if (!match) {
414
- return void 0;
415
- }
416
- const value = Number.parseFloat(match[1]);
417
- return Number.isFinite(value) ? value : void 0;
418
- }
419
- function getFailureStatus(result, error) {
420
- const message = [result.error, result.stderr, error?.message].filter(Boolean).join(" ");
421
- return /timed out/i.test(message) ? "timeout" : "failed";
422
- }
423
- function inferResearchPhase(name) {
424
- return /baseline/i.test(name) ? "baseline" : "experiment";
425
- }
426
- function buildPhaseHistory(runPhase) {
427
- return ["brief", runPhase, "verify", "report"];
428
- }
429
- function sanitizeLedgerField(value) {
430
- if (value === void 0 || value === null) {
431
- return "";
432
- }
433
- return String(value).replace(/\t/g, " ").replace(/\r?\n/g, " ").trim();
434
- }
435
- function ensureResultsLedger(dbPath) {
436
- const ledgerPath = getResultsLedgerPath(dbPath);
437
- if (!existsSync(ledgerPath)) {
438
- writeFileSync(ledgerPath, `${RESULTS_LEDGER_HEADERS.join(" ")}
439
- `, "utf8");
440
- }
441
- return ledgerPath;
442
- }
443
- function serializeResultRow(row) {
444
- const values = {
445
- timestamp: sanitizeLedgerField(row.timestamp),
446
- sessionId: sanitizeLedgerField(row.sessionId),
447
- taskId: sanitizeLedgerField(row.taskId),
448
- name: sanitizeLedgerField(row.name),
449
- phase: sanitizeLedgerField(row.phase),
450
- verdict: sanitizeLedgerField(row.verdict),
451
- status: sanitizeLedgerField(row.status),
452
- exitCode: sanitizeLedgerField(row.exitCode),
453
- metricName: sanitizeLedgerField(row.metricName),
454
- metricValue: sanitizeLedgerField(row.metricValue),
455
- durationMs: sanitizeLedgerField(row.durationMs),
456
- cwd: sanitizeLedgerField(row.cwd),
457
- command: sanitizeLedgerField(row.command)
458
- };
459
- return RESULTS_LEDGER_HEADERS.map((header) => values[header]).join(" ");
460
- }
461
- function parseResultRow(line) {
462
- if (!line.trim()) {
463
- return null;
464
- }
465
- const columns = line.split(" ");
466
- if (columns.length < RESULTS_LEDGER_HEADERS.length) {
467
- return null;
468
- }
469
- const [
470
- timestamp,
471
- sessionId,
472
- taskId,
473
- name,
474
- phase,
475
- verdict,
476
- status,
477
- exitCode,
478
- metricName,
479
- metricValue,
480
- durationMs,
481
- cwd,
482
- command
483
- ] = columns;
484
- const parsedMetric = metricValue ? Number.parseFloat(metricValue) : void 0;
485
- return {
486
- timestamp,
487
- sessionId,
488
- taskId,
489
- name,
490
- phase: phase || "experiment",
491
- verdict: verdict || "PARTIAL",
492
- status,
493
- exitCode: Number.parseInt(exitCode, 10) || 0,
494
- metricName: metricName || void 0,
495
- metricValue: Number.isFinite(parsedMetric) ? parsedMetric : void 0,
496
- durationMs: Number.parseInt(durationMs, 10) || 0,
497
- cwd,
498
- command
499
- };
500
- }
501
- function appendResultRow(row, dbPath) {
502
- const ledgerPath = ensureResultsLedger(dbPath);
503
- appendFileSync(ledgerPath, `${serializeResultRow(row)}
504
- `, "utf8");
505
- }
506
- function readAllResultRows(dbPath) {
507
- const ledgerPath = getResultsLedgerPath(dbPath);
508
- if (!existsSync(ledgerPath)) {
509
- return [];
510
- }
511
- const content = readFileSync(ledgerPath, "utf8");
512
- const lines = content.split(/\r?\n/).filter(Boolean);
513
- if (lines.length <= 1) {
514
- return [];
515
- }
516
- return lines.slice(1).map(parseResultRow).filter((row) => Boolean(row));
517
- }
518
- function resolveResearchObjective(metricName, objective = "auto") {
519
- if (objective === "maximize" || objective === "minimize") {
520
- return objective;
521
- }
522
- const normalized = (metricName || "").toLowerCase();
523
- if (!normalized) {
524
- return "maximize";
525
- }
526
- const lowerIsBetter = ["loss", "error", "bpb", "perplexity", "ppl", "latency", "duration", "time", "cost", "price", "wer", "cer"];
527
- if (lowerIsBetter.some((keyword) => normalized.includes(keyword))) {
528
- return "minimize";
529
- }
530
- return "maximize";
531
- }
532
- function compareMetricValues(baselineMetricValue, candidateMetricValue, objective) {
533
- if (baselineMetricValue === void 0 || candidateMetricValue === void 0) {
534
- return "unknown";
535
- }
536
- if (candidateMetricValue === baselineMetricValue) {
537
- return "equal";
538
- }
539
- if (objective === "minimize") {
540
- return candidateMetricValue < baselineMetricValue ? "better" : "worse";
541
- }
542
- return candidateMetricValue > baselineMetricValue ? "better" : "worse";
543
- }
544
- function formatSignedNumber(value) {
545
- if (value === void 0) {
546
- return "unknown";
547
- }
548
- return `${value > 0 ? "+" : ""}${value}`;
549
- }
550
- function formatPercent(value) {
551
- if (value === void 0) {
552
- return "unknown";
553
- }
554
- return `${value > 0 ? "+" : ""}${value.toFixed(2)}%`;
555
- }
556
- function buildComparisonSummary(input) {
557
- const result = compareMetricValues(input.baselineMetricValue, input.candidateMetricValue, input.objective);
558
- const delta = input.baselineMetricValue !== void 0 && input.candidateMetricValue !== void 0 ? input.candidateMetricValue - input.baselineMetricValue : void 0;
559
- const percentDelta = input.baselineMetricValue !== void 0 && input.baselineMetricValue !== 0 && delta !== void 0 ? delta / input.baselineMetricValue * 100 : void 0;
560
- const goal = input.objective === "minimize" ? "lower" : "higher";
561
- let summary = `Needs ${goal} ${input.objective === "minimize" ? "metric reduction" : "metric lift"} data.`;
562
- if (result === "better") {
563
- summary = `Candidate is better than baseline (${input.candidateMetricValue} vs ${input.baselineMetricValue}, \u0394 ${formatSignedNumber(delta)} / ${formatPercent(percentDelta)}).`;
564
- } else if (result === "worse") {
565
- summary = `Candidate is worse than baseline (${input.candidateMetricValue} vs ${input.baselineMetricValue}, \u0394 ${formatSignedNumber(delta)} / ${formatPercent(percentDelta)}).`;
566
- } else if (result === "equal") {
567
- summary = `Candidate matches baseline (${input.candidateMetricValue}).`;
568
- }
569
- return {
570
- baselineSessionId: input.baselineSessionId,
571
- baselineName: input.baselineName,
572
- objective: input.objective,
573
- result,
574
- baselineMetricValue: input.baselineMetricValue,
575
- candidateMetricValue: input.candidateMetricValue,
576
- delta,
577
- percentDelta,
578
- summary
579
- };
580
- }
581
- function determineVerdict(args) {
582
- if (!args.success) {
583
- return {
584
- verdict: "FAIL",
585
- reason: "Command execution failed."
586
- };
587
- }
588
- if (args.metricName && args.metricValue === void 0) {
589
- return {
590
- verdict: "PARTIAL",
591
- reason: `Metric ${args.metricName} was configured but not found in output.`
592
- };
593
- }
594
- if (args.comparison?.result === "worse") {
595
- return {
596
- verdict: "FAIL",
597
- reason: args.comparison.summary
598
- };
599
- }
600
- if (args.comparison?.result === "unknown") {
601
- return {
602
- verdict: "PARTIAL",
603
- reason: args.comparison.summary
604
- };
605
- }
606
- if (args.comparison?.result === "equal") {
607
- return {
608
- verdict: "PARTIAL",
609
- reason: args.comparison.summary
610
- };
611
- }
612
- if (args.comparison?.result === "better") {
613
- return {
614
- verdict: "PASS",
615
- reason: args.comparison.summary
616
- };
617
- }
618
- if (args.metricName && args.metricValue !== void 0) {
619
- return {
620
- verdict: "PASS",
621
- reason: `Metric ${args.metricName}=${args.metricValue} was captured successfully.`
622
- };
623
- }
624
- return {
625
- verdict: "PASS",
626
- reason: "Command completed successfully."
627
- };
628
- }
629
- function selectBestByMetric(rows) {
630
- const newestMetricRow = [...rows].reverse().find((row) => row.metricName && row.metricValue !== void 0);
631
- if (!newestMetricRow?.metricName) {
632
- return [...rows].reverse().find((row) => row.verdict === "PASS") || rows[rows.length - 1];
633
- }
634
- const candidates = rows.filter((row) => row.metricName === newestMetricRow.metricName && row.metricValue !== void 0);
635
- if (candidates.length === 0) {
636
- return newestMetricRow;
637
- }
638
- const objective = resolveResearchObjective(newestMetricRow.metricName);
639
- return candidates.reduce((best, current) => {
640
- if (best.metricValue === void 0 || current.metricValue === void 0) {
641
- return best;
642
- }
643
- if (objective === "minimize") {
644
- return current.metricValue < best.metricValue ? current : best;
645
- }
646
- return current.metricValue > best.metricValue ? current : best;
647
- });
648
- }
649
- function buildResearchTask(taskId, options) {
650
- return {
651
- id: taskId,
652
- name: options.name,
653
- description: `Run research command: ${options.command}`,
654
- type: "research-run",
655
- priority: "normal",
656
- status: "pending",
657
- requiredCapabilities: [],
658
- input: {
659
- parameters: {
660
- command: options.command,
661
- cwd: options.cwd,
662
- metricName: options.metricName,
663
- budgetMs: options.budgetMs
664
- },
665
- instructions: "Execute the configured research command and capture its metric output."
666
- },
667
- dependencies: [],
668
- maxRetries: options.maxRetries,
669
- retryCount: 0,
670
- timeout: options.budgetMs,
671
- metadata: {
672
- tags: ["research", "experiment"],
673
- category: "research",
674
- createdBy: "ccjk research",
675
- custom: {
676
- metricName: options.metricName,
677
- cwd: options.cwd,
678
- baselineSessionId: options.baselineSessionId
679
- }
680
- },
681
- createdAt: (/* @__PURE__ */ new Date()).toISOString(),
682
- progress: 0
683
- };
684
- }
685
- function normalizeRunOptions(options) {
686
- return {
687
- command: options.command,
688
- name: options.name || `research-${Date.now()}`,
689
- cwd: options.cwd || process.cwd(),
690
- budgetMs: options.budgetMs || DEFAULT_BUDGET_MS,
691
- maxRetries: options.maxRetries ?? 0,
692
- metricName: options.metricName,
693
- baselineSessionId: options.baselineSessionId,
694
- objective: options.objective || "auto",
695
- dbPath: options.dbPath
696
- };
697
- }
698
- async function runResearchExperiment(options) {
699
- const normalized = normalizeRunOptions(options);
700
- const persistence = createPersistence$1(normalized.dbPath);
701
- const queue = new TaskQueue({
702
- concurrency: 1,
703
- defaultTimeout: normalized.budgetMs,
704
- defaultMaxRetries: normalized.maxRetries
705
- });
706
- const createdAt = (/* @__PURE__ */ new Date()).toISOString();
707
- const runPhase = inferResearchPhase(normalized.name);
708
- const phaseHistory = buildPhaseHistory(runPhase);
709
- const sessionId = `research-${Date.now()}-${nanoid(6)}`;
710
- const taskId = `research-task-${nanoid(8)}`;
711
- const task = buildResearchTask(taskId, normalized);
712
- const objective = resolveResearchObjective(normalized.metricName, normalized.objective);
713
- let baselineSummary;
714
- let comparison;
715
- let baselineMetricValue;
716
- if (normalized.baselineSessionId) {
717
- baselineSummary = listResearchSessions(Number.MAX_SAFE_INTEGER, normalized.dbPath).find((session) => session.id === normalized.baselineSessionId);
718
- const baselineReport = getResearchReport(normalized.baselineSessionId, normalized.dbPath);
719
- if (baselineReport) {
720
- baselineMetricValue = baselineReport.metricValue;
721
- comparison = buildComparisonSummary({
722
- baselineSessionId: baselineReport.sessionId,
723
- baselineName: baselineReport.name,
724
- baselineMetricValue,
725
- candidateMetricValue: void 0,
726
- objective
727
- });
728
- }
729
- }
730
- persistence.saveSession(sessionId, {
731
- kind: RESEARCH_SESSION_KIND,
732
- name: normalized.name,
733
- command: normalized.command,
734
- cwd: normalized.cwd,
735
- metricName: normalized.metricName,
736
- budgetMs: normalized.budgetMs,
737
- objective,
738
- baselineSessionId: normalized.baselineSessionId,
739
- currentPhase: runPhase,
740
- phaseHistory: ["brief", runPhase],
741
- createdAt
742
- });
743
- persistence.saveTask(task, sessionId);
744
- let attempts = 0;
745
- let commandResult;
746
- let error;
747
- const startedAt = Date.now();
748
- persistence.updateTaskStatus(taskId, "running");
749
- try {
750
- commandResult = await queue.add(async () => {
751
- attempts += 1;
752
- const result = await executeCommand(normalized.command, [], {
753
- cwd: normalized.cwd,
754
- timeout: normalized.budgetMs,
755
- shell: true
756
- });
757
- if (!result.success) {
758
- throw new ResearchCommandError(result);
759
- }
760
- return result;
761
- }, {
762
- timeout: normalized.budgetMs,
763
- maxRetries: normalized.maxRetries,
764
- metadata: {
765
- sessionId,
766
- command: normalized.command
767
- }
768
- });
769
- } catch (caughtError) {
770
- error = caughtError instanceof Error ? caughtError : new Error(String(caughtError));
771
- if (caughtError instanceof ResearchCommandError) {
772
- commandResult = caughtError.result;
773
- }
774
- }
775
- const durationMs = Date.now() - startedAt;
776
- const finalizedResult = commandResult || {
777
- success: false,
778
- stdout: "",
779
- stderr: "",
780
- exitCode: 1,
781
- error: error?.message || "Research command failed"
782
- };
783
- const status = finalizedResult.success ? "completed" : getFailureStatus(finalizedResult, error);
784
- const combinedOutput = [finalizedResult.stdout, finalizedResult.stderr].filter(Boolean).join("\n");
785
- const metricValue = extractMetricValue(combinedOutput, normalized.metricName);
786
- if (normalized.baselineSessionId) {
787
- comparison = buildComparisonSummary({
788
- baselineSessionId: normalized.baselineSessionId,
789
- baselineName: baselineSummary?.name || normalized.baselineSessionId,
790
- baselineMetricValue,
791
- candidateMetricValue: metricValue,
792
- objective
793
- });
794
- }
795
- const verdictDecision = determineVerdict({
796
- success: finalizedResult.success,
797
- metricName: normalized.metricName,
798
- metricValue,
799
- comparison
800
- });
801
- const verdict = verdictDecision.verdict;
802
- const verdictReason = verdictDecision.reason;
803
- const output = {
804
- data: {
805
- command: normalized.command,
806
- cwd: normalized.cwd,
807
- status,
808
- exitCode: finalizedResult.exitCode,
809
- stdout: finalizedResult.stdout,
810
- stderr: finalizedResult.stderr,
811
- metricName: normalized.metricName,
812
- metricValue,
813
- durationMs,
814
- attempts,
815
- phase: runPhase,
816
- objective,
817
- verdict,
818
- verdictReason,
819
- baselineSessionId: normalized.baselineSessionId,
820
- comparison
821
- },
822
- logs: combinedOutput ? combinedOutput.split(/\r?\n/) : [],
823
- metadata: {
824
- status,
825
- success: finalizedResult.success,
826
- verdict,
827
- objective
828
- }
829
- };
830
- persistence.updateTaskStatus(
831
- taskId,
832
- finalizedResult.success ? "completed" : "failed",
833
- output,
834
- finalizedResult.success ? void 0 : error
835
- );
836
- persistence.recordMetrics({
837
- taskId,
838
- sessionId,
839
- executionTime: durationMs,
840
- retryCount: Math.max(0, attempts - 1),
841
- success: finalizedResult.success,
842
- errorType: finalizedResult.success ? void 0 : status
843
- });
844
- persistence.logDecision({
845
- id: `decision-${nanoid(8)}`,
846
- sessionId,
847
- taskId,
848
- decision: "record research run",
849
- reasoning: normalized.metricName ? `Executed the research command and evaluated metric ${normalized.metricName} with objective ${objective}.` : "Executed the research command without a configured metric parser.",
850
- context: JSON.stringify({
851
- command: normalized.command,
852
- cwd: normalized.cwd,
853
- budgetMs: normalized.budgetMs,
854
- metricName: normalized.metricName,
855
- phase: runPhase,
856
- objective,
857
- baselineSessionId: normalized.baselineSessionId
858
- }),
859
- outcome: verdictReason
860
- });
861
- persistence.saveSession(sessionId, {
862
- kind: RESEARCH_SESSION_KIND,
863
- name: normalized.name,
864
- command: normalized.command,
865
- cwd: normalized.cwd,
866
- metricName: normalized.metricName,
867
- budgetMs: normalized.budgetMs,
868
- objective,
869
- baselineSessionId: normalized.baselineSessionId,
870
- currentPhase: "report",
871
- phaseHistory,
872
- runPhase,
873
- verdict,
874
- verdictReason,
875
- status,
876
- exitCode: finalizedResult.exitCode,
877
- metricValue,
878
- comparison,
879
- durationMs,
880
- createdAt
881
- });
882
- appendResultRow({
883
- timestamp: createdAt,
884
- sessionId,
885
- taskId,
886
- name: normalized.name,
887
- phase: runPhase,
888
- verdict,
889
- status,
890
- exitCode: finalizedResult.exitCode,
891
- metricName: normalized.metricName,
892
- metricValue,
893
- durationMs,
894
- cwd: normalized.cwd,
895
- command: normalized.command
896
- }, normalized.dbPath);
897
- return {
898
- sessionId,
899
- taskId,
900
- name: normalized.name,
901
- command: normalized.command,
902
- cwd: normalized.cwd,
903
- metricName: normalized.metricName,
904
- metricValue,
905
- success: finalizedResult.success,
906
- status,
907
- exitCode: finalizedResult.exitCode,
908
- stdout: finalizedResult.stdout,
909
- stderr: finalizedResult.stderr,
910
- durationMs,
911
- phase: runPhase,
912
- objective,
913
- verdict,
914
- verdictReason,
915
- baselineSessionId: normalized.baselineSessionId,
916
- comparison,
917
- phaseHistory,
918
- createdAt
919
- };
920
- }
921
- function listResearchSessions(limit = DEFAULT_SESSION_LIMIT, dbPath) {
922
- const persistence = createPersistence$1(dbPath);
923
- return persistence.listSessions(Math.max(limit * 5, 50)).filter((session) => session.metadata?.kind === RESEARCH_SESSION_KIND).slice(0, limit).map((session) => ({
924
- id: session.id,
925
- createdAt: session.createdAt,
926
- name: session.metadata.name || session.id,
927
- command: session.metadata.command || "",
928
- cwd: session.metadata.cwd || process.cwd(),
929
- metricName: session.metadata.metricName,
930
- budgetMs: session.metadata.budgetMs || DEFAULT_BUDGET_MS,
931
- currentPhase: session.metadata.currentPhase || "experiment",
932
- objective: session.metadata.objective,
933
- verdict: session.metadata.verdict,
934
- baselineSessionId: session.metadata.baselineSessionId
935
- }));
936
- }
937
- function getLatestResearchSession(dbPath) {
938
- return listResearchSessions(1, dbPath)[0];
939
- }
940
- function getResearchSessionStatus(sessionId, dbPath) {
941
- const persistence = createPersistence$1(dbPath);
942
- const restored = persistence.restoreContext(sessionId);
943
- if (!restored) {
944
- return null;
945
- }
946
- return {
947
- sessionId,
948
- metadata: restored.metadata,
949
- tasks: restored.tasks,
950
- metrics: persistence.getSessionMetrics(sessionId),
951
- decisions: persistence.getDecisionLog(sessionId),
952
- recovery: persistence.recoverExecutionState(sessionId)
953
- };
954
- }
955
- function listResearchResults(limit = DEFAULT_SESSION_LIMIT, dbPath) {
956
- return readAllResultRows(dbPath).reverse().slice(0, limit);
957
- }
958
- function getBestResearchResult(dbPath) {
959
- const rows = readAllResultRows(dbPath);
960
- if (rows.length === 0) {
961
- return void 0;
962
- }
963
- return selectBestByMetric(rows);
964
- }
965
- function getResearchReport(sessionId, dbPath) {
966
- const resolvedSessionId = sessionId || getLatestResearchSession(dbPath)?.id;
967
- if (!resolvedSessionId) {
968
- return null;
969
- }
970
- const status = getResearchSessionStatus(resolvedSessionId, dbPath);
971
- if (!status) {
972
- return null;
973
- }
974
- const latestTask = status.tasks[status.tasks.length - 1];
975
- const outputData = latestTask?.output?.data || {};
976
- const phaseHistory = status.metadata.phaseHistory || [];
977
- const comparison = status.metadata.comparison;
978
- const verdictDecision = determineVerdict({
979
- success: status.metrics.failedTasks === 0,
980
- metricName: status.metadata.metricName,
981
- metricValue: outputData.metricValue,
982
- comparison
983
- });
984
- const verdict = status.metadata.verdict || verdictDecision.verdict;
985
- const verdictReason = String(status.metadata.verdictReason || verdictDecision.reason);
986
- const currentPhase = status.metadata.currentPhase || "report";
987
- const createdAt = String(status.metadata.createdAt || "");
988
- const outcome = String(
989
- status.decisions[status.decisions.length - 1]?.outcome || status.decisions[status.decisions.length - 1]?.decision || outputData.stderr || outputData.status || "unknown"
990
- ).replace(/\s+/g, " ").trim().slice(0, 160);
991
- const lines = [];
992
- lines.push("# CCJK Research Report");
993
- lines.push("");
994
- lines.push(`**Session**: ${resolvedSessionId}`);
995
- lines.push(`**Name**: ${status.metadata.name || resolvedSessionId}`);
996
- lines.push(`**Created**: ${createdAt || "unknown"}`);
997
- lines.push(`**Phase**: ${currentPhase}`);
998
- lines.push(`**Verdict**: ${verdict}`);
999
- lines.push(`**Command**: ${status.metadata.command || outputData.command || "unknown"}`);
1000
- lines.push(`**CWD**: ${status.metadata.cwd || outputData.cwd || process.cwd()}`);
1001
- lines.push(`**Exit Code**: ${outputData.exitCode ?? "unknown"}`);
1002
- lines.push(`**Status**: ${outputData.status || status.metadata.status || "unknown"}`);
1003
- lines.push(`**Metric**: ${status.metadata.metricName ? `${status.metadata.metricName}=${outputData.metricValue ?? "not found"}` : "not configured"}`);
1004
- lines.push(`**Objective**: ${status.metadata.objective || outputData.objective || "unknown"}`);
1005
- lines.push(`**Duration**: ${outputData.durationMs ?? status.metadata.durationMs ?? 0}ms`);
1006
- lines.push(`**Reason**: ${verdictReason}`);
1007
- lines.push(`**Outcome**: ${outcome}`);
1008
- if (comparison) {
1009
- lines.push("");
1010
- lines.push("## Comparison");
1011
- lines.push("");
1012
- lines.push(`- Baseline: ${comparison.baselineName} (${comparison.baselineSessionId})`);
1013
- lines.push(`- Objective: ${comparison.objective}`);
1014
- lines.push(`- Result: ${comparison.result}`);
1015
- lines.push(`- Summary: ${comparison.summary}`);
1016
- }
1017
- if (phaseHistory.length > 0) {
1018
- lines.push("");
1019
- lines.push("## Phase History");
1020
- lines.push("");
1021
- lines.push(`- ${phaseHistory.join(" \u2192 ")}`);
1022
- }
1023
- return {
1024
- sessionId: resolvedSessionId,
1025
- name: status.metadata.name || resolvedSessionId,
1026
- createdAt,
1027
- currentPhase,
1028
- verdict,
1029
- verdictReason,
1030
- command: status.metadata.command || outputData.command || "unknown",
1031
- cwd: status.metadata.cwd || outputData.cwd || process.cwd(),
1032
- status: String(outputData.status || status.metadata.status || "unknown"),
1033
- exitCode: Number(outputData.exitCode ?? 0),
1034
- metricName: status.metadata.metricName,
1035
- metricValue: typeof outputData.metricValue === "number" ? outputData.metricValue : void 0,
1036
- objective: status.metadata.objective,
1037
- baselineSessionId: status.metadata.baselineSessionId,
1038
- comparison,
1039
- durationMs: Number(outputData.durationMs ?? status.metadata.durationMs ?? 0),
1040
- phaseHistory,
1041
- outcome,
1042
- content: lines.join("\n")
1043
- };
1044
- }
1045
-
1046
- const RESEARCH_LOOP_SESSION_KIND = "research-loop";
1047
- const DEFAULT_FAILURE_STREAK_LIMIT = 2;
1048
- function createPersistence(dbPath) {
1049
- return new TaskPersistence(dbPath);
1050
- }
1051
- function toPositiveInteger(value, fallback) {
1052
- return typeof value === "number" && Number.isInteger(value) && value > 0 ? value : fallback;
1053
- }
1054
- function toOptionalFiniteNumber(value) {
1055
- return typeof value === "number" && Number.isFinite(value) ? value : void 0;
1056
- }
1057
- function applyProgramOverrides(program, overrides = {}) {
1058
- return {
1059
- ...program,
1060
- cwd: overrides.cwd || program.cwd,
1061
- budgetMs: toPositiveInteger(overrides.budgetMs, program.budgetMs),
1062
- maxRounds: toPositiveInteger(overrides.maxRounds, program.maxRounds),
1063
- maxNoImproveRounds: toPositiveInteger(overrides.maxNoImproveRounds, program.maxNoImproveRounds),
1064
- targetMetric: toOptionalFiniteNumber(overrides.targetMetric) ?? program.targetMetric
1065
- };
1066
- }
1067
- function nowIso() {
1068
- return (/* @__PURE__ */ new Date()).toISOString();
1069
- }
1070
- function toObjective(value, metricName) {
1071
- if (value === "maximize" || value === "minimize") {
1072
- return value;
1073
- }
1074
- const normalized = (metricName || "").toLowerCase();
1075
- if (!normalized) {
1076
- return "maximize";
1077
- }
1078
- const lowerIsBetter = ["loss", "error", "bpb", "perplexity", "ppl", "latency", "duration", "time", "cost", "price", "wer", "cer"];
1079
- return lowerIsBetter.some((keyword) => normalized.includes(keyword)) ? "minimize" : "maximize";
1080
- }
1081
- function isAcceptedResult(result) {
1082
- return result.verdict === "PASS";
1083
- }
1084
- function cloneLoopMetadata(metadata, patch = {}) {
1085
- return {
1086
- ...metadata,
1087
- ...patch,
1088
- acceptedRoundSessionIds: patch.acceptedRoundSessionIds || [...metadata.acceptedRoundSessionIds],
1089
- rejectedRoundSessionIds: patch.rejectedRoundSessionIds || [...metadata.rejectedRoundSessionIds],
1090
- roundSessionIds: patch.roundSessionIds || [...metadata.roundSessionIds],
1091
- updatedAt: patch.updatedAt || nowIso()
1092
- };
1093
- }
1094
- function ensureLoopMetadata(raw, sessionId) {
1095
- const createdAt = typeof raw.createdAt === "string" && raw.createdAt ? raw.createdAt : nowIso();
1096
- return {
1097
- kind: "research-loop",
1098
- name: typeof raw.name === "string" && raw.name ? raw.name : sessionId,
1099
- programPath: typeof raw.programPath === "string" ? raw.programPath : ".ccjk/research/program.md",
1100
- metric: typeof raw.metric === "string" && raw.metric ? raw.metric : void 0,
1101
- objective: raw.objective === "maximize" || raw.objective === "minimize" || raw.objective === "auto" ? raw.objective : "auto",
1102
- cwd: typeof raw.cwd === "string" && raw.cwd ? raw.cwd : process.cwd(),
1103
- budgetMs: toPositiveInteger(raw.budgetMs, 5 * 60 * 1e3),
1104
- maxRounds: toPositiveInteger(raw.maxRounds, 10),
1105
- maxNoImproveRounds: toPositiveInteger(raw.maxNoImproveRounds, 3),
1106
- targetMetric: typeof raw.targetMetric === "number" && Number.isFinite(raw.targetMetric) ? raw.targetMetric : void 0,
1107
- status: raw.status === "running" || raw.status === "stopped" || raw.status === "completed" || raw.status === "failed" ? raw.status : "running",
1108
- baselineSessionId: typeof raw.baselineSessionId === "string" && raw.baselineSessionId ? raw.baselineSessionId : void 0,
1109
- currentRound: toPositiveInteger(raw.currentRound, 0) - 1 >= 0 ? toPositiveInteger(raw.currentRound, 0) : 0,
1110
- bestSessionId: typeof raw.bestSessionId === "string" && raw.bestSessionId ? raw.bestSessionId : void 0,
1111
- bestMetricValue: typeof raw.bestMetricValue === "number" && Number.isFinite(raw.bestMetricValue) ? raw.bestMetricValue : void 0,
1112
- acceptedRoundSessionIds: Array.isArray(raw.acceptedRoundSessionIds) ? raw.acceptedRoundSessionIds.filter((value) => typeof value === "string") : [],
1113
- rejectedRoundSessionIds: Array.isArray(raw.rejectedRoundSessionIds) ? raw.rejectedRoundSessionIds.filter((value) => typeof value === "string") : [],
1114
- roundSessionIds: Array.isArray(raw.roundSessionIds) ? raw.roundSessionIds.filter((value) => typeof value === "string") : [],
1115
- noImproveStreak: typeof raw.noImproveStreak === "number" && raw.noImproveStreak >= 0 ? raw.noImproveStreak : 0,
1116
- failureStreak: typeof raw.failureStreak === "number" && raw.failureStreak >= 0 ? raw.failureStreak : 0,
1117
- stopReason: raw.stopReason,
1118
- createdAt,
1119
- updatedAt: typeof raw.updatedAt === "string" && raw.updatedAt ? raw.updatedAt : createdAt,
1120
- lastRoundSessionId: typeof raw.lastRoundSessionId === "string" && raw.lastRoundSessionId ? raw.lastRoundSessionId : void 0,
1121
- notes: typeof raw.notes === "string" && raw.notes ? raw.notes : void 0
1122
- };
1123
- }
1124
- function getLoopSessionRecord(sessionId, dbPath) {
1125
- const persistence = createPersistence(dbPath);
1126
- const session = persistence.getSession(sessionId);
1127
- if (!session || session.metadata?.kind !== RESEARCH_LOOP_SESSION_KIND) {
1128
- return null;
1129
- }
1130
- return {
1131
- id: session.id,
1132
- createdAt: session.createdAt,
1133
- updatedAt: session.updatedAt,
1134
- metadata: ensureLoopMetadata(session.metadata, session.id)
1135
- };
1136
- }
1137
- function getLatestLoopSession(dbPath) {
1138
- const persistence = createPersistence(dbPath);
1139
- const session = persistence.listSessions(100).find((item) => item.metadata?.kind === RESEARCH_LOOP_SESSION_KIND);
1140
- if (!session) {
1141
- return null;
1142
- }
1143
- return {
1144
- id: session.id,
1145
- createdAt: session.createdAt,
1146
- metadata: ensureLoopMetadata(session.metadata, session.id)
1147
- };
1148
- }
1149
- function getResolvedLoopSessionId(sessionId, dbPath) {
1150
- return sessionId || getLatestLoopSession(dbPath)?.id;
1151
- }
1152
- function saveLoopMetadata(sessionId, metadata, dbPath) {
1153
- const persistence = createPersistence(dbPath);
1154
- const normalized = ensureLoopMetadata({ ...metadata, updatedAt: nowIso() }, sessionId);
1155
- persistence.saveSession(sessionId, normalized);
1156
- return normalized;
1157
- }
1158
- function buildRoundRecord(round, result) {
1159
- return {
1160
- round,
1161
- sessionId: result.sessionId,
1162
- name: result.name,
1163
- status: result.status,
1164
- verdict: result.verdict,
1165
- metricName: result.metricName,
1166
- metricValue: result.metricValue,
1167
- accepted: isAcceptedResult(result),
1168
- objective: result.objective,
1169
- command: result.command,
1170
- reason: result.verdictReason,
1171
- baselineSessionId: result.baselineSessionId,
1172
- comparison: result.comparison,
1173
- createdAt: result.createdAt
1174
- };
1175
- }
1176
- function getRoundRecords(metadata, dbPath) {
1177
- return metadata.roundSessionIds.map((sessionId, index) => {
1178
- const report = getResearchReport(sessionId, dbPath);
1179
- if (!report) {
1180
- return null;
1181
- }
1182
- const record = {
1183
- round: index + 1,
1184
- sessionId,
1185
- name: report.name,
1186
- status: report.status,
1187
- verdict: report.verdict,
1188
- metricName: report.metricName,
1189
- metricValue: report.metricValue,
1190
- accepted: metadata.acceptedRoundSessionIds.includes(sessionId),
1191
- objective: report.objective || toObjective(metadata.objective, metadata.metric),
1192
- command: report.command,
1193
- reason: report.verdictReason,
1194
- baselineSessionId: report.baselineSessionId,
1195
- comparison: report.comparison,
1196
- createdAt: report.createdAt
1197
- };
1198
- return record;
1199
- }).filter((value) => value !== null);
1200
- }
1201
- function isTargetReached(metricValue, objective, targetMetric) {
1202
- if (metricValue === void 0 || targetMetric === void 0) {
1203
- return false;
1204
- }
1205
- return objective === "minimize" ? metricValue <= targetMetric : metricValue >= targetMetric;
1206
- }
1207
- function evaluateLoopStopCondition(input) {
1208
- const objective = toObjective(input.metadata.objective, input.metadata.metric);
1209
- if (input.metadata.status === "completed" || input.metadata.status === "failed") {
1210
- return { shouldStop: true, reason: input.metadata.stopReason, status: input.metadata.status };
1211
- }
1212
- if (input.metadata.status === "stopped") {
1213
- return { shouldStop: true, reason: input.metadata.stopReason || "manual-stop", status: "stopped" };
1214
- }
1215
- if (input.phase === "baseline" && input.latestResult && !input.latestResult.success) {
1216
- return { shouldStop: true, reason: "baseline-failed", status: "failed" };
1217
- }
1218
- if (input.metadata.currentRound >= input.program.maxRounds) {
1219
- return { shouldStop: true, reason: "max-rounds-reached", status: "completed" };
1220
- }
1221
- if (input.metadata.noImproveStreak >= input.program.maxNoImproveRounds) {
1222
- return { shouldStop: true, reason: "max-no-improve-rounds-reached", status: "completed" };
1223
- }
1224
- if (isTargetReached(input.metadata.bestMetricValue, objective, input.program.targetMetric)) {
1225
- return { shouldStop: true, reason: "target-metric-reached", status: "completed" };
1226
- }
1227
- if (input.phase === "round" && input.metadata.failureStreak >= DEFAULT_FAILURE_STREAK_LIMIT) {
1228
- return { shouldStop: true, reason: "candidate-failed-repeatedly", status: "failed" };
1229
- }
1230
- return { shouldStop: false };
1231
- }
1232
- function createLoopSession(program, dbPath) {
1233
- const sessionId = `research-loop-${Date.now()}-${nanoid(6)}`;
1234
- const createdAt = nowIso();
1235
- const metadata = {
1236
- kind: "research-loop",
1237
- name: program.name,
1238
- programPath: program.programPath,
1239
- metric: program.metric,
1240
- objective: program.objective,
1241
- cwd: program.cwd,
1242
- budgetMs: program.budgetMs,
1243
- maxRounds: program.maxRounds,
1244
- maxNoImproveRounds: program.maxNoImproveRounds,
1245
- targetMetric: program.targetMetric,
1246
- status: "running",
1247
- baselineSessionId: void 0,
1248
- currentRound: 0,
1249
- bestSessionId: void 0,
1250
- bestMetricValue: void 0,
1251
- acceptedRoundSessionIds: [],
1252
- rejectedRoundSessionIds: [],
1253
- roundSessionIds: [],
1254
- noImproveStreak: 0,
1255
- failureStreak: 0,
1256
- createdAt,
1257
- updatedAt: createdAt,
1258
- notes: program.notes
1259
- };
1260
- return {
1261
- sessionId,
1262
- metadata: saveLoopMetadata(sessionId, metadata, dbPath)
1263
- };
1264
- }
1265
- async function ensureBaseline(sessionId, metadata, program, dbPath) {
1266
- if (metadata.baselineSessionId) {
1267
- const report = getResearchReport(metadata.baselineSessionId, dbPath);
1268
- if (report) {
1269
- return {
1270
- metadata,
1271
- baseline: {
1272
- sessionId: report.sessionId,
1273
- taskId: "",
1274
- name: report.name,
1275
- command: report.command,
1276
- cwd: report.cwd,
1277
- metricName: report.metricName,
1278
- metricValue: report.metricValue,
1279
- success: report.status === "completed",
1280
- status: report.status,
1281
- exitCode: report.exitCode,
1282
- stdout: "",
1283
- stderr: "",
1284
- durationMs: report.durationMs,
1285
- phase: "baseline",
1286
- objective: report.objective || toObjective(program.objective, program.metric),
1287
- verdict: report.verdict,
1288
- verdictReason: report.verdictReason,
1289
- baselineSessionId: report.baselineSessionId,
1290
- comparison: report.comparison,
1291
- phaseHistory: report.phaseHistory,
1292
- createdAt: report.createdAt
1293
- }
1294
- };
1295
- }
1296
- }
1297
- const baseline = await runResearchExperiment({
1298
- name: `${program.name}-baseline`,
1299
- command: program.baselineCommand,
1300
- metricName: program.metric,
1301
- budgetMs: program.budgetMs,
1302
- cwd: program.cwd,
1303
- objective: program.objective,
1304
- dbPath
1305
- });
1306
- const nextMetadata = cloneLoopMetadata(metadata, {
1307
- baselineSessionId: baseline.sessionId,
1308
- bestSessionId: baseline.sessionId,
1309
- bestMetricValue: baseline.metricValue,
1310
- failureStreak: baseline.success ? 0 : metadata.failureStreak + 1
1311
- });
1312
- return {
1313
- metadata: saveLoopMetadata(sessionId, nextMetadata, dbPath),
1314
- baseline
1315
- };
1316
- }
1317
- async function executeResearchRound(sessionId, metadata, program, dbPath) {
1318
- const roundNumber = metadata.currentRound + 1;
1319
- const baselineSessionId = metadata.bestSessionId || metadata.baselineSessionId;
1320
- const result = await runResearchExperiment({
1321
- name: `${program.name}-round-${roundNumber}`,
1322
- command: program.candidateCommand,
1323
- metricName: program.metric,
1324
- budgetMs: program.budgetMs,
1325
- cwd: program.cwd,
1326
- objective: program.objective,
1327
- baselineSessionId,
1328
- dbPath
1329
- });
1330
- const accepted = isAcceptedResult(result);
1331
- const acceptedRoundSessionIds = accepted ? [...metadata.acceptedRoundSessionIds, result.sessionId] : [...metadata.acceptedRoundSessionIds];
1332
- const rejectedRoundSessionIds = accepted ? [...metadata.rejectedRoundSessionIds] : [...metadata.rejectedRoundSessionIds, result.sessionId];
1333
- const bestSessionId = accepted ? result.sessionId : metadata.bestSessionId;
1334
- const bestMetricValue = accepted ? result.metricValue : metadata.bestMetricValue;
1335
- const nextMetadata = cloneLoopMetadata(metadata, {
1336
- currentRound: roundNumber,
1337
- bestSessionId,
1338
- bestMetricValue,
1339
- roundSessionIds: [...metadata.roundSessionIds, result.sessionId],
1340
- acceptedRoundSessionIds,
1341
- rejectedRoundSessionIds,
1342
- noImproveStreak: accepted ? 0 : metadata.noImproveStreak + 1,
1343
- failureStreak: result.success ? 0 : metadata.failureStreak + 1,
1344
- lastRoundSessionId: result.sessionId
1345
- });
1346
- return {
1347
- metadata: saveLoopMetadata(sessionId, nextMetadata, dbPath),
1348
- result,
1349
- round: buildRoundRecord(roundNumber, result)
1350
- };
1351
- }
1352
- function getResearchLoopStatusInternal(sessionId, dbPath) {
1353
- const loopSession = getLoopSessionRecord(sessionId, dbPath);
1354
- if (!loopSession) {
1355
- return null;
1356
- }
1357
- const baselineReport = loopSession.metadata.baselineSessionId ? getResearchReport(loopSession.metadata.baselineSessionId, dbPath) : null;
1358
- const rounds = getRoundRecords(loopSession.metadata, dbPath);
1359
- return {
1360
- sessionId,
1361
- metadata: loopSession.metadata,
1362
- baseline: baselineReport ? {
1363
- sessionId: baselineReport.sessionId,
1364
- taskId: "",
1365
- name: baselineReport.name,
1366
- command: baselineReport.command,
1367
- cwd: baselineReport.cwd,
1368
- metricName: baselineReport.metricName,
1369
- metricValue: baselineReport.metricValue,
1370
- success: baselineReport.status === "completed",
1371
- status: baselineReport.status,
1372
- exitCode: baselineReport.exitCode,
1373
- stdout: "",
1374
- stderr: "",
1375
- durationMs: baselineReport.durationMs,
1376
- phase: "baseline",
1377
- objective: baselineReport.objective || toObjective(loopSession.metadata.objective, loopSession.metadata.metric),
1378
- verdict: baselineReport.verdict,
1379
- verdictReason: baselineReport.verdictReason,
1380
- baselineSessionId: baselineReport.baselineSessionId,
1381
- comparison: baselineReport.comparison,
1382
- phaseHistory: baselineReport.phaseHistory,
1383
- createdAt: baselineReport.createdAt
1384
- } : null,
1385
- latestRound: rounds[rounds.length - 1],
1386
- rounds
1387
- };
1388
- }
1389
- async function startResearchLoop(options = {}) {
1390
- const program = applyProgramOverrides(readResearchProgram(options.programPath, options.cwd), options.overrides);
1391
- const { sessionId } = createLoopSession(program, options.dbPath);
1392
- return await resumeResearchLoop({ ...options, sessionId });
1393
- }
1394
- async function runResearchRound(options = {}) {
1395
- const resolvedSessionId = getResolvedLoopSessionId(options.sessionId, options.dbPath);
1396
- if (!resolvedSessionId) {
1397
- throw new Error("No research loop session found.");
1398
- }
1399
- const loopSession = getLoopSessionRecord(resolvedSessionId, options.dbPath);
1400
- if (!loopSession) {
1401
- throw new Error(`Research loop session not found: ${resolvedSessionId}`);
1402
- }
1403
- const program = applyProgramOverrides(readResearchProgram(loopSession.metadata.programPath, options.cwd), options.overrides);
1404
- let metadata = saveLoopMetadata(resolvedSessionId, cloneLoopMetadata(loopSession.metadata, { status: "running", stopReason: void 0 }), options.dbPath);
1405
- const baselineState = await ensureBaseline(resolvedSessionId, metadata, program, options.dbPath);
1406
- metadata = baselineState.metadata;
1407
- const stopAfterBaseline = evaluateLoopStopCondition({ metadata, latestResult: baselineState.baseline, program, phase: "baseline" });
1408
- if (stopAfterBaseline.shouldStop) {
1409
- metadata = saveLoopMetadata(resolvedSessionId, cloneLoopMetadata(metadata, {
1410
- status: stopAfterBaseline.status || metadata.status,
1411
- stopReason: stopAfterBaseline.reason
1412
- }), options.dbPath);
1413
- return getResearchLoopStatusInternal(resolvedSessionId, options.dbPath);
1414
- }
1415
- const roundState = await executeResearchRound(resolvedSessionId, metadata, program, options.dbPath);
1416
- metadata = roundState.metadata;
1417
- const stopState = evaluateLoopStopCondition({ metadata, latestResult: roundState.result, program, phase: "round" });
1418
- if (stopState.shouldStop) {
1419
- metadata = saveLoopMetadata(resolvedSessionId, cloneLoopMetadata(metadata, {
1420
- status: stopState.status || metadata.status,
1421
- stopReason: stopState.reason
1422
- }), options.dbPath);
1423
- }
1424
- return getResearchLoopStatusInternal(resolvedSessionId, options.dbPath);
1425
- }
1426
- async function resumeResearchLoop(options = {}) {
1427
- const resolvedSessionId = getResolvedLoopSessionId(options.sessionId, options.dbPath);
1428
- if (!resolvedSessionId) {
1429
- throw new Error("No research loop session found.");
1430
- }
1431
- const loopSession = getLoopSessionRecord(resolvedSessionId, options.dbPath);
1432
- if (!loopSession) {
1433
- throw new Error(`Research loop session not found: ${resolvedSessionId}`);
1434
- }
1435
- const program = applyProgramOverrides(readResearchProgram(loopSession.metadata.programPath, options.cwd), options.overrides);
1436
- let metadata = saveLoopMetadata(resolvedSessionId, cloneLoopMetadata(loopSession.metadata, {
1437
- status: loopSession.metadata.status === "completed" || loopSession.metadata.status === "failed" ? loopSession.metadata.status : "running",
1438
- stopReason: loopSession.metadata.status === "stopped" ? void 0 : loopSession.metadata.stopReason
1439
- }), options.dbPath);
1440
- const baselineState = await ensureBaseline(resolvedSessionId, metadata, program, options.dbPath);
1441
- metadata = baselineState.metadata;
1442
- while (true) {
1443
- const stopBeforeRound = evaluateLoopStopCondition({ metadata, program });
1444
- if (stopBeforeRound.shouldStop) {
1445
- metadata = saveLoopMetadata(resolvedSessionId, cloneLoopMetadata(metadata, {
1446
- status: stopBeforeRound.status || metadata.status,
1447
- stopReason: stopBeforeRound.reason
1448
- }), options.dbPath);
1449
- return getResearchLoopStatusInternal(resolvedSessionId, options.dbPath);
1450
- }
1451
- const roundState = await executeResearchRound(resolvedSessionId, metadata, program, options.dbPath);
1452
- metadata = roundState.metadata;
1453
- const stopAfterRound = evaluateLoopStopCondition({ metadata, latestResult: roundState.result, program, phase: "round" });
1454
- if (stopAfterRound.shouldStop) {
1455
- metadata = saveLoopMetadata(resolvedSessionId, cloneLoopMetadata(metadata, {
1456
- status: stopAfterRound.status || metadata.status,
1457
- stopReason: stopAfterRound.reason || "resume-complete"
1458
- }), options.dbPath);
1459
- return getResearchLoopStatusInternal(resolvedSessionId, options.dbPath);
1460
- }
1461
- }
1462
- }
1463
- function stopResearchLoop(options = {}) {
1464
- const resolvedSessionId = getResolvedLoopSessionId(options.sessionId, options.dbPath);
1465
- if (!resolvedSessionId) {
1466
- return null;
1467
- }
1468
- const loopSession = getLoopSessionRecord(resolvedSessionId, options.dbPath);
1469
- if (!loopSession) {
1470
- return null;
1471
- }
1472
- saveLoopMetadata(resolvedSessionId, cloneLoopMetadata(loopSession.metadata, {
1473
- status: "stopped",
1474
- stopReason: "manual-stop"
1475
- }), options.dbPath);
1476
- return getResearchLoopStatusInternal(resolvedSessionId, options.dbPath);
1477
- }
1478
- function getResearchLoopStatus(sessionId, dbPath) {
1479
- const resolvedSessionId = getResolvedLoopSessionId(sessionId, dbPath);
1480
- if (!resolvedSessionId) {
1481
- return null;
1482
- }
1483
- return getResearchLoopStatusInternal(resolvedSessionId, dbPath);
1484
- }
1485
- function getResearchLoopReport(sessionId, dbPath) {
1486
- const status = getResearchLoopStatus(sessionId, dbPath);
1487
- if (!status) {
1488
- return null;
1489
- }
1490
- const lines = [];
1491
- lines.push("# CCJK Research Loop Report");
1492
- lines.push("");
1493
- lines.push(`**Session**: ${status.sessionId}`);
1494
- lines.push(`**Name**: ${status.metadata.name}`);
1495
- lines.push(`**Status**: ${status.metadata.status}`);
1496
- lines.push(`**Stop Reason**: ${status.metadata.stopReason || "running"}`);
1497
- lines.push(`**Rounds**: ${status.metadata.currentRound}/${status.metadata.maxRounds}`);
1498
- lines.push(`**No-Improve Streak**: ${status.metadata.noImproveStreak}/${status.metadata.maxNoImproveRounds}`);
1499
- lines.push(`**Metric**: ${status.metadata.metric || "not configured"}`);
1500
- lines.push(`**Objective**: ${status.metadata.objective}`);
1501
- lines.push(`**Target Metric**: ${status.metadata.targetMetric ?? "not configured"}`);
1502
- lines.push(`**Best Session**: ${status.metadata.bestSessionId || "none"}`);
1503
- lines.push(`**Best Metric**: ${status.metadata.bestMetricValue ?? "not found"}`);
1504
- lines.push(`**Created**: ${status.metadata.createdAt}`);
1505
- lines.push(`**Updated**: ${status.metadata.updatedAt}`);
1506
- if (status.baseline) {
1507
- lines.push("");
1508
- lines.push("## Baseline");
1509
- lines.push("");
1510
- lines.push(`- Session: ${status.baseline.sessionId}`);
1511
- lines.push(`- Verdict: ${status.baseline.verdict}`);
1512
- lines.push(`- Metric: ${status.baseline.metricName ? `${status.baseline.metricName}=${status.baseline.metricValue ?? "not found"}` : "not configured"}`);
1513
- lines.push(`- Reason: ${status.baseline.verdictReason}`);
1514
- }
1515
- if (status.rounds.length > 0) {
1516
- lines.push("");
1517
- lines.push("## Rounds");
1518
- lines.push("");
1519
- for (const round of status.rounds) {
1520
- lines.push(`- Round ${round.round}: ${round.sessionId} \xB7 ${round.verdict} \xB7 ${round.metricName ? `${round.metricName}=${round.metricValue ?? "not found"}` : "no metric"} \xB7 ${round.accepted ? "accepted" : "rejected"}`);
1521
- }
1522
- }
1523
- return {
1524
- sessionId: status.sessionId,
1525
- name: status.metadata.name,
1526
- status: status.metadata.status,
1527
- stopReason: status.metadata.stopReason,
1528
- currentRound: status.metadata.currentRound,
1529
- maxRounds: status.metadata.maxRounds,
1530
- noImproveStreak: status.metadata.noImproveStreak,
1531
- maxNoImproveRounds: status.metadata.maxNoImproveRounds,
1532
- acceptedRounds: status.metadata.acceptedRoundSessionIds.length,
1533
- rejectedRounds: status.metadata.rejectedRoundSessionIds.length,
1534
- bestSessionId: status.metadata.bestSessionId,
1535
- bestMetricValue: status.metadata.bestMetricValue,
1536
- metric: status.metadata.metric,
1537
- objective: status.metadata.objective,
1538
- targetMetric: status.metadata.targetMetric,
1539
- baselineSessionId: status.metadata.baselineSessionId,
1540
- createdAt: status.metadata.createdAt,
1541
- updatedAt: status.metadata.updatedAt,
1542
- content: lines.join("\n")
1543
- };
1544
- }
1545
-
1546
- function printDivider() {
1547
- console.log(a.dim("\u2500".repeat(60)));
1548
- }
1549
- function formatMetric(metricName, metricValue) {
1550
- if (!metricName) {
1551
- return "not configured";
1552
- }
1553
- if (metricValue === void 0) {
1554
- return `${metricName} (not found)`;
1555
- }
1556
- return `${metricName}=${metricValue}`;
1557
- }
1558
- function formatTimestamp(value) {
1559
- if (!value) {
1560
- return "unknown";
1561
- }
1562
- const date = new Date(value);
1563
- return Number.isNaN(date.getTime()) ? value : date.toISOString();
1564
- }
1565
- function previewCommand(command, maxLength = 48) {
1566
- if (command.length <= maxLength) {
1567
- return command;
1568
- }
1569
- return `${command.slice(0, maxLength - 1)}\u2026`;
1570
- }
1571
- function getLatestTaskData(status) {
1572
- if (!status || status.tasks.length === 0) {
1573
- return {};
1574
- }
1575
- const latestTask = status.tasks[status.tasks.length - 1];
1576
- return latestTask?.output?.data || {};
1577
- }
1578
- function getLoopOverrides(options) {
1579
- return {
1580
- cwd: options.cwd,
1581
- budgetMs: options.budgetMs,
1582
- maxRounds: options.maxRounds,
1583
- maxNoImproveRounds: options.maxNoImproveRounds,
1584
- targetMetric: options.targetMetric
1585
- };
1586
- }
1587
- function printResearchLoopStatus(status) {
1588
- console.log("");
1589
- console.log(a.bold.cyan("\u{1F501} Research Loop Status"));
1590
- printDivider();
1591
- console.log(a.gray(`Session: ${status.sessionId}`));
1592
- console.log(a.gray(`Name: ${status.metadata.name}`));
1593
- console.log(a.gray(`Status: ${status.metadata.status}`));
1594
- console.log(a.gray(`Stop: ${status.metadata.stopReason || "running"}`));
1595
- console.log(a.gray(`Rounds: ${status.metadata.currentRound}/${status.metadata.maxRounds}`));
1596
- console.log(a.gray(`Objective: ${status.metadata.objective}`));
1597
- console.log(a.gray(`Metric: ${formatMetric(status.metadata.metric, status.metadata.bestMetricValue)}`));
1598
- console.log(a.gray(`Baseline: ${status.metadata.baselineSessionId || "none"}`));
1599
- console.log(a.gray(`Best: ${status.metadata.bestSessionId || "none"}`));
1600
- console.log(a.gray(`Accepted: ${status.metadata.acceptedRoundSessionIds.length}`));
1601
- console.log(a.gray(`Rejected: ${status.metadata.rejectedRoundSessionIds.length}`));
1602
- console.log(a.gray(`Streak: ${status.metadata.noImproveStreak}/${status.metadata.maxNoImproveRounds}`));
1603
- if (status.latestRound) {
1604
- console.log(a.gray(`Latest: round ${status.latestRound.round} \xB7 ${status.latestRound.verdict} \xB7 ${formatMetric(status.latestRound.metricName, status.latestRound.metricValue)}`));
1605
- }
1606
- console.log("");
1607
- }
1608
- async function researchCommand(action, args = [], options = {}) {
1609
- switch (action) {
1610
- case "run":
1611
- await runResearchCommand(options);
1612
- return;
1613
- case "init":
1614
- await initResearchCommand(options);
1615
- return;
1616
- case "loop":
1617
- await startResearchLoopCommand(options);
1618
- return;
1619
- case "round":
1620
- await runResearchRoundCommand(args[0] || void 0, options);
1621
- return;
1622
- case "resume":
1623
- await resumeResearchLoopCommand(args[0] || void 0, options);
1624
- return;
1625
- case "stop":
1626
- await stopResearchLoopCommand(args[0] || void 0, options);
1627
- return;
1628
- case "status":
1629
- await showResearchStatus(args[0] || void 0, options);
1630
- return;
1631
- case "sessions":
1632
- case "list":
1633
- await listResearchCommand(options);
1634
- return;
1635
- case "results":
1636
- await showResearchResults(options);
1637
- return;
1638
- case "report":
1639
- await showResearchReport(args[0] || void 0, options);
1640
- return;
1641
- case "help":
1642
- case "":
1643
- showResearchHelp();
1644
- return;
1645
- default:
1646
- console.error(a.red(`Unknown research action: ${action}`));
1647
- showResearchHelp();
1648
- }
1649
- }
1650
- async function runResearchCommand(options) {
1651
- if (!options.cmd) {
1652
- console.error(a.red("Error: --cmd is required for `ccjk research run`"));
1653
- console.log(a.dim('Example: ccjk research run --name baseline --cmd "python train.py" --metric val_bpb'));
1654
- return;
1655
- }
1656
- const result = await runResearchExperiment({
1657
- name: options.name,
1658
- command: options.cmd,
1659
- metricName: options.metric,
1660
- budgetMs: options.budgetMs,
1661
- cwd: options.cwd,
1662
- baselineSessionId: options.baseline,
1663
- objective: options.objective,
1664
- dbPath: options.dbPath
1665
- });
1666
- console.log("");
1667
- console.log(a.bold.cyan("\u{1F52C} Research Run"));
1668
- printDivider();
1669
- console.log(a.gray(`Session: ${result.sessionId}`));
1670
- console.log(a.gray(`Task: ${result.taskId}`));
1671
- console.log(a.gray(`Name: ${result.name}`));
1672
- console.log(a.gray(`Phase: ${result.phase}`));
1673
- console.log(a.gray(`Objective: ${result.objective}`));
1674
- console.log(a.gray(`Verdict: ${result.verdict}`));
1675
- console.log(a.gray(`Reason: ${result.verdictReason}`));
1676
- console.log(a.gray(`Command: ${result.command}`));
1677
- console.log(a.gray(`CWD: ${result.cwd}`));
1678
- console.log(a.gray(`Status: ${result.status}`));
1679
- console.log(a.gray(`Exit code: ${result.exitCode}`));
1680
- console.log(a.gray(`Metric: ${formatMetric(result.metricName, result.metricValue)}`));
1681
- if (result.comparison) {
1682
- console.log(a.gray(`Baseline: ${result.comparison.baselineName} (${result.comparison.baselineSessionId})`));
1683
- console.log(a.gray(`Compare: ${result.comparison.result}`));
1684
- }
1685
- console.log(a.gray(`Duration: ${result.durationMs}ms`));
1686
- if (result.stderr) {
1687
- console.log("");
1688
- console.log(a.bold("stderr"));
1689
- console.log(a.dim(result.stderr));
1690
- }
1691
- if (result.stdout) {
1692
- console.log("");
1693
- console.log(a.bold("stdout"));
1694
- console.log(a.dim(result.stdout));
1695
- }
1696
- console.log("");
1697
- }
1698
- async function initResearchCommand(options) {
1699
- const { programPath } = initResearchProgram(options.program, options.cwd);
1700
- console.log("");
1701
- console.log(a.bold.cyan("\u{1F9ED} Research Program"));
1702
- printDivider();
1703
- console.log(a.gray(`Program: ${programPath}`));
1704
- console.log("");
1705
- }
1706
- async function startResearchLoopCommand(options) {
1707
- const status = await startResearchLoop({
1708
- programPath: options.program,
1709
- cwd: options.cwd,
1710
- dbPath: options.dbPath,
1711
- overrides: getLoopOverrides(options)
1712
- });
1713
- printResearchLoopStatus(status);
1714
- }
1715
- async function runResearchRoundCommand(sessionId, options) {
1716
- const status = await runResearchRound({
1717
- sessionId,
1718
- cwd: options.cwd,
1719
- dbPath: options.dbPath,
1720
- overrides: getLoopOverrides(options)
1721
- });
1722
- printResearchLoopStatus(status);
1723
- }
1724
- async function resumeResearchLoopCommand(sessionId, options) {
1725
- const status = await resumeResearchLoop({
1726
- sessionId,
1727
- cwd: options.cwd,
1728
- dbPath: options.dbPath,
1729
- overrides: getLoopOverrides(options)
1730
- });
1731
- printResearchLoopStatus(status);
1732
- }
1733
- async function stopResearchLoopCommand(sessionId, options) {
1734
- const status = stopResearchLoop({ sessionId, dbPath: options.dbPath });
1735
- if (!status) {
1736
- console.log(a.yellow(sessionId ? `Research loop session not found: ${sessionId}` : "No research loop sessions found."));
1737
- console.log("");
1738
- return;
1739
- }
1740
- printResearchLoopStatus(status);
1741
- }
1742
- async function showResearchStatus(sessionId, options) {
1743
- const loopStatus = getResearchLoopStatus(sessionId, options.dbPath);
1744
- if (loopStatus) {
1745
- printResearchLoopStatus(loopStatus);
1746
- return;
1747
- }
1748
- const resolvedSessionId = sessionId || getLatestResearchSession(options.dbPath)?.id;
1749
- if (!resolvedSessionId) {
1750
- console.log(a.yellow("No research sessions found."));
1751
- console.log("");
1752
- return;
1753
- }
1754
- const status = getResearchSessionStatus(resolvedSessionId, options.dbPath);
1755
- if (!status) {
1756
- console.log(a.yellow(`Research session not found: ${resolvedSessionId}`));
1757
- console.log("");
1758
- return;
1759
- }
1760
- const outputData = getLatestTaskData(status);
1761
- const metricValue = typeof outputData.metricValue === "number" ? outputData.metricValue : typeof status.metadata.metricValue === "number" ? status.metadata.metricValue : void 0;
1762
- console.log("");
1763
- console.log(a.bold.cyan("\u{1F9EA} Research Status"));
1764
- printDivider();
1765
- console.log(a.gray(`Session: ${status.sessionId}`));
1766
- console.log(a.gray(`Name: ${status.metadata.name || status.sessionId}`));
1767
- console.log(a.gray(`Phase: ${status.metadata.currentPhase || "unknown"}`));
1768
- console.log(a.gray(`Objective: ${status.metadata.objective || "unknown"}`));
1769
- console.log(a.gray(`Verdict: ${status.metadata.verdict || "unknown"}`));
1770
- console.log(a.gray(`Reason: ${status.metadata.verdictReason || "unknown"}`));
1771
- console.log(a.gray(`Command: ${status.metadata.command || "unknown"}`));
1772
- console.log(a.gray(`Metric: ${formatMetric(status.metadata.metricName, metricValue)}`));
1773
- console.log(a.gray(`Status: ${outputData.status || status.metadata.status || "unknown"}`));
1774
- console.log(a.gray(`Exit code: ${outputData.exitCode ?? status.metadata.exitCode ?? "unknown"}`));
1775
- console.log(a.gray(`Duration: ${outputData.durationMs ?? status.metadata.durationMs ?? "unknown"}ms`));
1776
- console.log(a.gray(`Tasks: ${status.metrics.completedTasks}/${status.metrics.totalTasks} completed`));
1777
- console.log(a.gray(`Success: ${Math.round((status.metrics.successRate || 0) * 100)}%`));
1778
- console.log(a.gray(`Avg ms: ${status.metrics.avgExecutionTime}`));
1779
- console.log(a.gray(`Next: ${status.recovery.nextExecutable.length}`));
1780
- if (status.metadata.comparison) {
1781
- const comparison = status.metadata.comparison;
1782
- console.log(a.gray(`Baseline: ${comparison.baselineName || comparison.baselineSessionId || "unknown"}`));
1783
- console.log(a.gray(`Compare: ${comparison.result || "unknown"}`));
1784
- console.log(a.gray(`Summary: ${comparison.summary || "unknown"}`));
1785
- }
1786
- if (status.decisions.length > 0) {
1787
- const lastDecision = status.decisions[status.decisions.length - 1];
1788
- console.log(a.gray(`Decision: ${lastDecision.outcome || lastDecision.decision}`));
1789
- }
1790
- console.log("");
1791
- }
1792
- async function listResearchCommand(options) {
1793
- const sessions = listResearchSessions(options.limit || 10, options.dbPath);
1794
- console.log("");
1795
- console.log(a.bold.cyan("\u{1F4DA} Research Sessions"));
1796
- printDivider();
1797
- if (sessions.length === 0) {
1798
- console.log(a.yellow("No research sessions found."));
1799
- console.log("");
1800
- return;
1801
- }
1802
- for (const session of sessions) {
1803
- console.log(a.bold(session.name));
1804
- console.log(a.gray(` ${session.id}`));
1805
- console.log(a.gray(` phase: ${session.currentPhase}`));
1806
- console.log(a.gray(` objective: ${session.objective || "unknown"}`));
1807
- console.log(a.gray(` verdict: ${session.verdict || "unknown"}`));
1808
- if (session.baselineSessionId) {
1809
- console.log(a.gray(` baseline: ${session.baselineSessionId}`));
1810
- }
1811
- console.log(a.gray(` cmd: ${session.command}`));
1812
- console.log(a.gray(` metric: ${session.metricName || "not configured"}`));
1813
- console.log(a.gray(` cwd: ${session.cwd}`));
1814
- }
1815
- console.log("");
1816
- }
1817
- async function showResearchResults(options) {
1818
- const rows = listResearchResults(options.limit || 10, options.dbPath);
1819
- const best = getBestResearchResult(options.dbPath);
1820
- console.log("");
1821
- console.log(a.bold.cyan("\u{1F4C8} Research Results"));
1822
- printDivider();
1823
- if (rows.length === 0) {
1824
- console.log(a.yellow("No research results found."));
1825
- console.log("");
1826
- return;
1827
- }
1828
- if (best) {
1829
- console.log(a.bold("Best"));
1830
- console.log(a.gray(` ${best.name} \xB7 ${formatMetric(best.metricName, best.metricValue)} \xB7 ${best.status} \xB7 ${best.durationMs}ms`));
1831
- console.log(a.gray(` objective: ${best.metricName ? ["loss", "error", "bpb", "perplexity", "ppl", "latency", "duration", "time", "cost", "price", "wer", "cer"].some((keyword) => best.metricName?.toLowerCase().includes(keyword)) ? "minimize" : "maximize" : "unknown"}`));
1832
- console.log(a.gray(` ${previewCommand(best.command)}`));
1833
- console.log("");
1834
- }
1835
- console.log(a.bold("Recent"));
1836
- for (const row of rows) {
1837
- console.log(a.gray(`${formatTimestamp(row.timestamp)} \xB7 ${row.name} \xB7 ${row.status} \xB7 ${formatMetric(row.metricName, row.metricValue)} \xB7 ${row.durationMs}ms \xB7 ${previewCommand(row.command)}`));
1838
- }
1839
- console.log("");
1840
- }
1841
- async function showResearchReport(sessionId, options) {
1842
- const loopReport = getResearchLoopReport(sessionId, options.dbPath);
1843
- if (loopReport) {
1844
- console.log("");
1845
- console.log(a.bold.cyan("\u{1F4DD} Research Loop Report"));
1846
- printDivider();
1847
- console.log(loopReport.content);
1848
- console.log("");
1849
- return;
1850
- }
1851
- const report = getResearchReport(sessionId, options.dbPath);
1852
- if (!report) {
1853
- console.log(a.yellow(sessionId ? `Research session not found: ${sessionId}` : "No research sessions found."));
1854
- console.log("");
1855
- return;
1856
- }
1857
- console.log("");
1858
- console.log(a.bold.cyan("\u{1F4DD} Research Report"));
1859
- printDivider();
1860
- console.log(a.gray(`Session: ${report.sessionId}`));
1861
- console.log(a.gray(`Name: ${report.name}`));
1862
- console.log(a.gray(`Created: ${formatTimestamp(report.createdAt)}`));
1863
- console.log(a.gray(`Command: ${report.command}`));
1864
- console.log(a.gray(`CWD: ${report.cwd}`));
1865
- console.log(a.gray(`Status: ${report.status}`));
1866
- console.log(a.gray(`Exit code: ${report.exitCode}`));
1867
- console.log(a.gray(`Duration: ${report.durationMs}ms`));
1868
- console.log(a.gray(`Metric: ${formatMetric(report.metricName, report.metricValue)}`));
1869
- console.log(a.gray(`Objective: ${report.objective || "unknown"}`));
1870
- console.log(a.gray(`Reason: ${report.verdictReason}`));
1871
- if (report.comparison) {
1872
- console.log(a.gray(`Baseline: ${report.comparison.baselineName} (${report.comparison.baselineSessionId})`));
1873
- console.log(a.gray(`Compare: ${report.comparison.result}`));
1874
- }
1875
- console.log(a.gray(`Outcome: ${report.outcome}`));
1876
- if (report.phaseHistory.length > 0) {
1877
- console.log(a.gray(`Phases: ${report.phaseHistory.join(" \u2192 ")}`));
1878
- }
1879
- console.log("");
1880
- }
1881
- function showResearchHelp() {
1882
- console.log("");
1883
- console.log(a.bold.cyan("ccjk research"));
1884
- printDivider();
1885
- console.log(" init Create a research program template");
1886
- console.log(" loop Start a persisted research loop");
1887
- console.log(" round Run one candidate round for a loop");
1888
- console.log(" resume Continue a persisted research loop until stop");
1889
- console.log(" stop Stop a running research loop");
1890
- console.log(" run Run a persisted research experiment with optional baseline comparison");
1891
- console.log(" status Show the latest or selected research session status");
1892
- console.log(" sessions List recent research sessions");
1893
- console.log(" results Show recent result rows and the current best run");
1894
- console.log(" report Render a compact persisted research report");
1895
- console.log("");
1896
- console.log(a.dim("Example: ccjk research init"));
1897
- console.log(a.dim("Example: ccjk research loop --program .ccjk/research/program.md"));
1898
- console.log(a.dim("Example: ccjk research round research-loop-123"));
1899
- console.log(a.dim('Example: ccjk research run --name baseline --cmd "python train.py" --metric val_bpb --objective minimize'));
1900
- console.log(a.dim("Example: ccjk research report research-123"));
1901
- console.log("");
1902
- }
1903
-
1904
- export { researchCommand, showResearchHelp };