@kynetic-ai/spec 0.1.2 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (510) hide show
  1. package/README.md +250 -17
  2. package/dist/acp/client.d.ts +18 -4
  3. package/dist/acp/client.d.ts.map +1 -1
  4. package/dist/acp/client.js +44 -26
  5. package/dist/acp/client.js.map +1 -1
  6. package/dist/acp/framing.d.ts +2 -2
  7. package/dist/acp/framing.d.ts.map +1 -1
  8. package/dist/acp/framing.js +37 -29
  9. package/dist/acp/framing.js.map +1 -1
  10. package/dist/acp/index.d.ts +6 -7
  11. package/dist/acp/index.d.ts.map +1 -1
  12. package/dist/acp/index.js +3 -3
  13. package/dist/acp/index.js.map +1 -1
  14. package/dist/acp/types.d.ts +5 -5
  15. package/dist/acp/types.d.ts.map +1 -1
  16. package/dist/acp/types.js +18 -18
  17. package/dist/acp/types.js.map +1 -1
  18. package/dist/agents/adapters.d.ts.map +1 -1
  19. package/dist/agents/adapters.js +24 -13
  20. package/dist/agents/adapters.js.map +1 -1
  21. package/dist/agents/index.d.ts +2 -2
  22. package/dist/agents/index.js +2 -2
  23. package/dist/agents/spawner.d.ts +4 -4
  24. package/dist/agents/spawner.d.ts.map +1 -1
  25. package/dist/agents/spawner.js +6 -6
  26. package/dist/agents/spawner.js.map +1 -1
  27. package/dist/cli/batch-context.d.ts +43 -0
  28. package/dist/cli/batch-context.d.ts.map +1 -0
  29. package/dist/cli/batch-context.js +93 -0
  30. package/dist/cli/batch-context.js.map +1 -0
  31. package/dist/cli/batch-exec.d.ts +116 -0
  32. package/dist/cli/batch-exec.d.ts.map +1 -0
  33. package/dist/cli/batch-exec.js +694 -0
  34. package/dist/cli/batch-exec.js.map +1 -0
  35. package/dist/cli/batch.d.ts +4 -2
  36. package/dist/cli/batch.d.ts.map +1 -1
  37. package/dist/cli/batch.js +15 -14
  38. package/dist/cli/batch.js.map +1 -1
  39. package/dist/cli/command-annotations.d.ts +23 -0
  40. package/dist/cli/command-annotations.d.ts.map +1 -0
  41. package/dist/cli/command-annotations.js +27 -0
  42. package/dist/cli/command-annotations.js.map +1 -0
  43. package/dist/cli/commands/agents.d.ts +46 -0
  44. package/dist/cli/commands/agents.d.ts.map +1 -0
  45. package/dist/cli/commands/agents.js +377 -0
  46. package/dist/cli/commands/agents.js.map +1 -0
  47. package/dist/cli/commands/batch.d.ts +20 -0
  48. package/dist/cli/commands/batch.d.ts.map +1 -0
  49. package/dist/cli/commands/batch.js +214 -0
  50. package/dist/cli/commands/batch.js.map +1 -0
  51. package/dist/cli/commands/clone-for-testing.d.ts +1 -1
  52. package/dist/cli/commands/clone-for-testing.d.ts.map +1 -1
  53. package/dist/cli/commands/clone-for-testing.js +37 -47
  54. package/dist/cli/commands/clone-for-testing.js.map +1 -1
  55. package/dist/cli/commands/derive.d.ts +1 -1
  56. package/dist/cli/commands/derive.d.ts.map +1 -1
  57. package/dist/cli/commands/derive.js +140 -88
  58. package/dist/cli/commands/derive.js.map +1 -1
  59. package/dist/cli/commands/doctor.d.ts +11 -0
  60. package/dist/cli/commands/doctor.d.ts.map +1 -0
  61. package/dist/cli/commands/doctor.js +152 -0
  62. package/dist/cli/commands/doctor.js.map +1 -0
  63. package/dist/cli/commands/export.d.ts +12 -0
  64. package/dist/cli/commands/export.d.ts.map +1 -0
  65. package/dist/cli/commands/export.js +134 -0
  66. package/dist/cli/commands/export.js.map +1 -0
  67. package/dist/cli/commands/help.d.ts +1 -1
  68. package/dist/cli/commands/help.d.ts.map +1 -1
  69. package/dist/cli/commands/help.js +163 -37
  70. package/dist/cli/commands/help.js.map +1 -1
  71. package/dist/cli/commands/inbox.d.ts +1 -1
  72. package/dist/cli/commands/inbox.d.ts.map +1 -1
  73. package/dist/cli/commands/inbox.js +178 -56
  74. package/dist/cli/commands/inbox.js.map +1 -1
  75. package/dist/cli/commands/index.d.ts +31 -19
  76. package/dist/cli/commands/index.d.ts.map +1 -1
  77. package/dist/cli/commands/index.js +31 -19
  78. package/dist/cli/commands/index.js.map +1 -1
  79. package/dist/cli/commands/init.d.ts +5 -1
  80. package/dist/cli/commands/init.d.ts.map +1 -1
  81. package/dist/cli/commands/init.js +108 -57
  82. package/dist/cli/commands/init.js.map +1 -1
  83. package/dist/cli/commands/item.d.ts +1 -1
  84. package/dist/cli/commands/item.d.ts.map +1 -1
  85. package/dist/cli/commands/item.js +557 -274
  86. package/dist/cli/commands/item.js.map +1 -1
  87. package/dist/cli/commands/link.d.ts +1 -1
  88. package/dist/cli/commands/link.d.ts.map +1 -1
  89. package/dist/cli/commands/link.js +55 -46
  90. package/dist/cli/commands/link.js.map +1 -1
  91. package/dist/cli/commands/log.d.ts +1 -1
  92. package/dist/cli/commands/log.d.ts.map +1 -1
  93. package/dist/cli/commands/log.js +57 -51
  94. package/dist/cli/commands/log.js.map +1 -1
  95. package/dist/cli/commands/merge-driver.d.ts +19 -0
  96. package/dist/cli/commands/merge-driver.d.ts.map +1 -0
  97. package/dist/cli/commands/merge-driver.js +398 -0
  98. package/dist/cli/commands/merge-driver.js.map +1 -0
  99. package/dist/cli/commands/meta.d.ts +1 -1
  100. package/dist/cli/commands/meta.d.ts.map +1 -1
  101. package/dist/cli/commands/meta.js +533 -399
  102. package/dist/cli/commands/meta.js.map +1 -1
  103. package/dist/cli/commands/module.d.ts +1 -1
  104. package/dist/cli/commands/module.d.ts.map +1 -1
  105. package/dist/cli/commands/module.js +30 -25
  106. package/dist/cli/commands/module.js.map +1 -1
  107. package/dist/cli/commands/plan-import.d.ts +11 -0
  108. package/dist/cli/commands/plan-import.d.ts.map +1 -0
  109. package/dist/cli/commands/plan-import.js +516 -0
  110. package/dist/cli/commands/plan-import.js.map +1 -0
  111. package/dist/cli/commands/plan.d.ts +10 -0
  112. package/dist/cli/commands/plan.d.ts.map +1 -0
  113. package/dist/cli/commands/plan.js +421 -0
  114. package/dist/cli/commands/plan.js.map +1 -0
  115. package/dist/cli/commands/ralph.d.ts +1 -1
  116. package/dist/cli/commands/ralph.d.ts.map +1 -1
  117. package/dist/cli/commands/ralph.js +1097 -169
  118. package/dist/cli/commands/ralph.js.map +1 -1
  119. package/dist/cli/commands/refs.d.ts +13 -0
  120. package/dist/cli/commands/refs.d.ts.map +1 -0
  121. package/dist/cli/commands/refs.js +283 -0
  122. package/dist/cli/commands/refs.js.map +1 -0
  123. package/dist/cli/commands/search.d.ts +1 -1
  124. package/dist/cli/commands/search.d.ts.map +1 -1
  125. package/dist/cli/commands/search.js +199 -37
  126. package/dist/cli/commands/search.js.map +1 -1
  127. package/dist/cli/commands/serve.d.ts +10 -0
  128. package/dist/cli/commands/serve.d.ts.map +1 -0
  129. package/dist/cli/commands/serve.js +491 -0
  130. package/dist/cli/commands/serve.js.map +1 -0
  131. package/dist/cli/commands/session.d.ts +25 -6
  132. package/dist/cli/commands/session.d.ts.map +1 -1
  133. package/dist/cli/commands/session.js +811 -127
  134. package/dist/cli/commands/session.js.map +1 -1
  135. package/dist/cli/commands/setup-seeding.d.ts +81 -0
  136. package/dist/cli/commands/setup-seeding.d.ts.map +1 -0
  137. package/dist/cli/commands/setup-seeding.js +292 -0
  138. package/dist/cli/commands/setup-seeding.js.map +1 -0
  139. package/dist/cli/commands/setup.d.ts +77 -3
  140. package/dist/cli/commands/setup.d.ts.map +1 -1
  141. package/dist/cli/commands/setup.js +1233 -274
  142. package/dist/cli/commands/setup.js.map +1 -1
  143. package/dist/cli/commands/shadow.d.ts +1 -1
  144. package/dist/cli/commands/shadow.d.ts.map +1 -1
  145. package/dist/cli/commands/shadow.js +70 -50
  146. package/dist/cli/commands/shadow.js.map +1 -1
  147. package/dist/cli/commands/skill-crud.d.ts +58 -0
  148. package/dist/cli/commands/skill-crud.d.ts.map +1 -0
  149. package/dist/cli/commands/skill-crud.js +753 -0
  150. package/dist/cli/commands/skill-crud.js.map +1 -0
  151. package/dist/cli/commands/skill-diff.d.ts +27 -0
  152. package/dist/cli/commands/skill-diff.d.ts.map +1 -0
  153. package/dist/cli/commands/skill-diff.js +840 -0
  154. package/dist/cli/commands/skill-diff.js.map +1 -0
  155. package/dist/cli/commands/skill-install.d.ts +53 -0
  156. package/dist/cli/commands/skill-install.d.ts.map +1 -0
  157. package/dist/cli/commands/skill-install.js +452 -0
  158. package/dist/cli/commands/skill-install.js.map +1 -0
  159. package/dist/cli/commands/skill.d.ts +20 -0
  160. package/dist/cli/commands/skill.d.ts.map +1 -0
  161. package/dist/cli/commands/skill.js +36 -0
  162. package/dist/cli/commands/skill.js.map +1 -0
  163. package/dist/cli/commands/task.d.ts +1 -1
  164. package/dist/cli/commands/task.d.ts.map +1 -1
  165. package/dist/cli/commands/task.js +569 -346
  166. package/dist/cli/commands/task.js.map +1 -1
  167. package/dist/cli/commands/tasks.d.ts +26 -1
  168. package/dist/cli/commands/tasks.d.ts.map +1 -1
  169. package/dist/cli/commands/tasks.js +227 -122
  170. package/dist/cli/commands/tasks.js.map +1 -1
  171. package/dist/cli/commands/trait.d.ts +1 -1
  172. package/dist/cli/commands/trait.d.ts.map +1 -1
  173. package/dist/cli/commands/trait.js +166 -101
  174. package/dist/cli/commands/trait.js.map +1 -1
  175. package/dist/cli/commands/triage.d.ts +7 -0
  176. package/dist/cli/commands/triage.d.ts.map +1 -0
  177. package/dist/cli/commands/triage.js +569 -0
  178. package/dist/cli/commands/triage.js.map +1 -0
  179. package/dist/cli/commands/util.d.ts +7 -0
  180. package/dist/cli/commands/util.d.ts.map +1 -0
  181. package/dist/cli/commands/util.js +30 -0
  182. package/dist/cli/commands/util.js.map +1 -0
  183. package/dist/cli/commands/validate.d.ts +1 -1
  184. package/dist/cli/commands/validate.d.ts.map +1 -1
  185. package/dist/cli/commands/validate.js +264 -83
  186. package/dist/cli/commands/validate.js.map +1 -1
  187. package/dist/cli/commands/workflow.d.ts +16 -0
  188. package/dist/cli/commands/workflow.d.ts.map +1 -0
  189. package/dist/cli/commands/workflow.js +851 -0
  190. package/dist/cli/commands/workflow.js.map +1 -0
  191. package/dist/cli/exit-codes.d.ts +7 -0
  192. package/dist/cli/exit-codes.d.ts.map +1 -1
  193. package/dist/cli/exit-codes.js +26 -18
  194. package/dist/cli/exit-codes.js.map +1 -1
  195. package/dist/cli/help/content.d.ts.map +1 -1
  196. package/dist/cli/help/content.js +86 -71
  197. package/dist/cli/help/content.js.map +1 -1
  198. package/dist/cli/index.d.ts +1 -1
  199. package/dist/cli/index.d.ts.map +1 -1
  200. package/dist/cli/index.js +131 -19
  201. package/dist/cli/index.js.map +1 -1
  202. package/dist/cli/introspection.d.ts +6 -2
  203. package/dist/cli/introspection.d.ts.map +1 -1
  204. package/dist/cli/introspection.js +11 -8
  205. package/dist/cli/introspection.js.map +1 -1
  206. package/dist/cli/output.d.ts +64 -4
  207. package/dist/cli/output.d.ts.map +1 -1
  208. package/dist/cli/output.js +235 -85
  209. package/dist/cli/output.js.map +1 -1
  210. package/dist/cli/parse-utils.d.ts +21 -0
  211. package/dist/cli/parse-utils.d.ts.map +1 -0
  212. package/dist/cli/parse-utils.js +32 -0
  213. package/dist/cli/parse-utils.js.map +1 -0
  214. package/dist/cli/pid-utils.d.ts +72 -0
  215. package/dist/cli/pid-utils.d.ts.map +1 -0
  216. package/dist/cli/pid-utils.js +174 -0
  217. package/dist/cli/pid-utils.js.map +1 -0
  218. package/dist/cli/suggest.d.ts.map +1 -1
  219. package/dist/cli/suggest.js +1 -2
  220. package/dist/cli/suggest.js.map +1 -1
  221. package/dist/cli/validators.d.ts +43 -0
  222. package/dist/cli/validators.d.ts.map +1 -0
  223. package/dist/cli/validators.js +84 -0
  224. package/dist/cli/validators.js.map +1 -0
  225. package/dist/daemon/index.ts +52 -0
  226. package/dist/daemon/middleware/project-context.ts +126 -0
  227. package/dist/daemon/pid.ts +179 -0
  228. package/dist/daemon/project-context.ts +343 -0
  229. package/dist/daemon/routes/inbox.ts +164 -0
  230. package/dist/daemon/routes/items.ts +322 -0
  231. package/dist/daemon/routes/meta.ts +118 -0
  232. package/dist/daemon/routes/projects.ts +162 -0
  233. package/dist/daemon/routes/tasks.ts +327 -0
  234. package/dist/daemon/routes/triage.ts +468 -0
  235. package/dist/daemon/routes/validation.ts +248 -0
  236. package/dist/daemon/server.ts +408 -0
  237. package/dist/daemon/watcher.ts +195 -0
  238. package/dist/daemon/websocket/handler.ts +138 -0
  239. package/dist/daemon/websocket/heartbeat.ts +71 -0
  240. package/dist/daemon/websocket/pubsub.ts +125 -0
  241. package/dist/daemon/websocket/types.ts +66 -0
  242. package/dist/export/html.d.ts +19 -0
  243. package/dist/export/html.d.ts.map +1 -0
  244. package/dist/export/html.js +239 -0
  245. package/dist/export/html.js.map +1 -0
  246. package/dist/export/index.d.ts +10 -0
  247. package/dist/export/index.d.ts.map +1 -0
  248. package/dist/export/index.js +10 -0
  249. package/dist/export/index.js.map +1 -0
  250. package/dist/export/json.d.ts +24 -0
  251. package/dist/export/json.d.ts.map +1 -0
  252. package/dist/export/json.js +198 -0
  253. package/dist/export/json.js.map +1 -0
  254. package/dist/export/triage.d.ts +51 -0
  255. package/dist/export/triage.d.ts.map +1 -0
  256. package/dist/export/triage.js +83 -0
  257. package/dist/export/triage.js.map +1 -0
  258. package/dist/export/types.d.ts +122 -0
  259. package/dist/export/types.d.ts.map +1 -0
  260. package/dist/export/types.js +9 -0
  261. package/dist/export/types.js.map +1 -0
  262. package/dist/index.d.ts +2 -2
  263. package/dist/index.js +2 -2
  264. package/dist/lib/claude-plugin-registry.d.ts +66 -0
  265. package/dist/lib/claude-plugin-registry.d.ts.map +1 -0
  266. package/dist/lib/claude-plugin-registry.js +318 -0
  267. package/dist/lib/claude-plugin-registry.js.map +1 -0
  268. package/dist/merge/arrays.d.ts +87 -0
  269. package/dist/merge/arrays.d.ts.map +1 -0
  270. package/dist/merge/arrays.js +164 -0
  271. package/dist/merge/arrays.js.map +1 -0
  272. package/dist/merge/file-type.d.ts +32 -0
  273. package/dist/merge/file-type.d.ts.map +1 -0
  274. package/dist/merge/file-type.js +70 -0
  275. package/dist/merge/file-type.js.map +1 -0
  276. package/dist/merge/index.d.ts +14 -0
  277. package/dist/merge/index.d.ts.map +1 -0
  278. package/dist/merge/index.js +11 -0
  279. package/dist/merge/index.js.map +1 -0
  280. package/dist/merge/objects.d.ts +46 -0
  281. package/dist/merge/objects.d.ts.map +1 -0
  282. package/dist/merge/objects.js +193 -0
  283. package/dist/merge/objects.js.map +1 -0
  284. package/dist/merge/parse.d.ts +23 -0
  285. package/dist/merge/parse.d.ts.map +1 -0
  286. package/dist/merge/parse.js +78 -0
  287. package/dist/merge/parse.js.map +1 -0
  288. package/dist/merge/resolve.d.ts +66 -0
  289. package/dist/merge/resolve.d.ts.map +1 -0
  290. package/dist/merge/resolve.js +189 -0
  291. package/dist/merge/resolve.js.map +1 -0
  292. package/dist/merge/types.d.ts +82 -0
  293. package/dist/merge/types.d.ts.map +1 -0
  294. package/dist/merge/types.js +8 -0
  295. package/dist/merge/types.js.map +1 -0
  296. package/dist/parser/agent-data-sections.d.ts +53 -0
  297. package/dist/parser/agent-data-sections.d.ts.map +1 -0
  298. package/dist/parser/agent-data-sections.js +118 -0
  299. package/dist/parser/agent-data-sections.js.map +1 -0
  300. package/dist/parser/alignment.d.ts +4 -4
  301. package/dist/parser/alignment.d.ts.map +1 -1
  302. package/dist/parser/alignment.js +27 -22
  303. package/dist/parser/alignment.js.map +1 -1
  304. package/dist/parser/assess.d.ts +5 -5
  305. package/dist/parser/assess.d.ts.map +1 -1
  306. package/dist/parser/assess.js +36 -32
  307. package/dist/parser/assess.js.map +1 -1
  308. package/dist/parser/config.d.ts +351 -0
  309. package/dist/parser/config.d.ts.map +1 -0
  310. package/dist/parser/config.js +326 -0
  311. package/dist/parser/config.js.map +1 -0
  312. package/dist/parser/convention-validation.d.ts +1 -1
  313. package/dist/parser/convention-validation.d.ts.map +1 -1
  314. package/dist/parser/convention-validation.js +21 -16
  315. package/dist/parser/convention-validation.js.map +1 -1
  316. package/dist/parser/coverage-cache.d.ts +49 -0
  317. package/dist/parser/coverage-cache.d.ts.map +1 -0
  318. package/dist/parser/coverage-cache.js +123 -0
  319. package/dist/parser/coverage-cache.js.map +1 -0
  320. package/dist/parser/daemon-status.d.ts +37 -0
  321. package/dist/parser/daemon-status.d.ts.map +1 -0
  322. package/dist/parser/daemon-status.js +67 -0
  323. package/dist/parser/daemon-status.js.map +1 -0
  324. package/dist/parser/doctor.d.ts +107 -0
  325. package/dist/parser/doctor.d.ts.map +1 -0
  326. package/dist/parser/doctor.js +366 -0
  327. package/dist/parser/doctor.js.map +1 -0
  328. package/dist/parser/fix.d.ts +1 -1
  329. package/dist/parser/fix.d.ts.map +1 -1
  330. package/dist/parser/fix.js +31 -27
  331. package/dist/parser/fix.js.map +1 -1
  332. package/dist/parser/index.d.ts +16 -11
  333. package/dist/parser/index.d.ts.map +1 -1
  334. package/dist/parser/index.js +16 -11
  335. package/dist/parser/index.js.map +1 -1
  336. package/dist/parser/items.d.ts +8 -2
  337. package/dist/parser/items.d.ts.map +1 -1
  338. package/dist/parser/items.js +71 -35
  339. package/dist/parser/items.js.map +1 -1
  340. package/dist/parser/meta.d.ts +167 -9
  341. package/dist/parser/meta.d.ts.map +1 -1
  342. package/dist/parser/meta.js +379 -46
  343. package/dist/parser/meta.js.map +1 -1
  344. package/dist/parser/plan-document.d.ts +189 -0
  345. package/dist/parser/plan-document.d.ts.map +1 -0
  346. package/dist/parser/plan-document.js +340 -0
  347. package/dist/parser/plan-document.js.map +1 -0
  348. package/dist/parser/plans.d.ts +59 -0
  349. package/dist/parser/plans.d.ts.map +1 -0
  350. package/dist/parser/plans.js +239 -0
  351. package/dist/parser/plans.js.map +1 -0
  352. package/dist/parser/refs.d.ts +22 -9
  353. package/dist/parser/refs.d.ts.map +1 -1
  354. package/dist/parser/refs.js +102 -50
  355. package/dist/parser/refs.js.map +1 -1
  356. package/dist/parser/setup-status.d.ts +71 -0
  357. package/dist/parser/setup-status.d.ts.map +1 -0
  358. package/dist/parser/setup-status.js +269 -0
  359. package/dist/parser/setup-status.js.map +1 -0
  360. package/dist/parser/shadow.d.ts +150 -19
  361. package/dist/parser/shadow.d.ts.map +1 -1
  362. package/dist/parser/shadow.js +548 -187
  363. package/dist/parser/shadow.js.map +1 -1
  364. package/dist/parser/skill-render.d.ts +317 -0
  365. package/dist/parser/skill-render.d.ts.map +1 -0
  366. package/dist/parser/skill-render.js +943 -0
  367. package/dist/parser/skill-render.js.map +1 -0
  368. package/dist/parser/traits.d.ts +3 -3
  369. package/dist/parser/traits.d.ts.map +1 -1
  370. package/dist/parser/traits.js +2 -2
  371. package/dist/parser/traits.js.map +1 -1
  372. package/dist/parser/validate-skills.d.ts +32 -0
  373. package/dist/parser/validate-skills.d.ts.map +1 -0
  374. package/dist/parser/validate-skills.js +202 -0
  375. package/dist/parser/validate-skills.js.map +1 -0
  376. package/dist/parser/validate.d.ts +45 -3
  377. package/dist/parser/validate.d.ts.map +1 -1
  378. package/dist/parser/validate.js +622 -105
  379. package/dist/parser/validate.js.map +1 -1
  380. package/dist/parser/yaml.d.ts +83 -19
  381. package/dist/parser/yaml.d.ts.map +1 -1
  382. package/dist/parser/yaml.js +478 -173
  383. package/dist/parser/yaml.js.map +1 -1
  384. package/dist/ralph/cli-renderer.d.ts +8 -1
  385. package/dist/ralph/cli-renderer.d.ts.map +1 -1
  386. package/dist/ralph/cli-renderer.js +105 -34
  387. package/dist/ralph/cli-renderer.js.map +1 -1
  388. package/dist/ralph/events.d.ts +10 -10
  389. package/dist/ralph/events.d.ts.map +1 -1
  390. package/dist/ralph/events.js +277 -98
  391. package/dist/ralph/events.js.map +1 -1
  392. package/dist/ralph/index.d.ts +5 -2
  393. package/dist/ralph/index.d.ts.map +1 -1
  394. package/dist/ralph/index.js +9 -3
  395. package/dist/ralph/index.js.map +1 -1
  396. package/dist/ralph/loop-errors.d.ts +83 -0
  397. package/dist/ralph/loop-errors.d.ts.map +1 -0
  398. package/dist/ralph/loop-errors.js +150 -0
  399. package/dist/ralph/loop-errors.js.map +1 -0
  400. package/dist/ralph/subagent.d.ts +83 -0
  401. package/dist/ralph/subagent.d.ts.map +1 -0
  402. package/dist/ralph/subagent.js +174 -0
  403. package/dist/ralph/subagent.js.map +1 -0
  404. package/dist/ralph/wrap-up.d.ts +125 -0
  405. package/dist/ralph/wrap-up.d.ts.map +1 -0
  406. package/dist/ralph/wrap-up.js +270 -0
  407. package/dist/ralph/wrap-up.js.map +1 -0
  408. package/dist/schema/batch.d.ts +95 -0
  409. package/dist/schema/batch.d.ts.map +1 -0
  410. package/dist/schema/batch.js +24 -0
  411. package/dist/schema/batch.js.map +1 -0
  412. package/dist/schema/common.d.ts +2 -2
  413. package/dist/schema/common.d.ts.map +1 -1
  414. package/dist/schema/common.js +34 -31
  415. package/dist/schema/common.js.map +1 -1
  416. package/dist/schema/inbox.d.ts +12 -12
  417. package/dist/schema/inbox.js +4 -4
  418. package/dist/schema/inbox.js.map +1 -1
  419. package/dist/schema/index.d.ts +8 -5
  420. package/dist/schema/index.d.ts.map +1 -1
  421. package/dist/schema/index.js +8 -5
  422. package/dist/schema/index.js.map +1 -1
  423. package/dist/schema/meta.d.ts +1454 -27
  424. package/dist/schema/meta.d.ts.map +1 -1
  425. package/dist/schema/meta.js +198 -21
  426. package/dist/schema/meta.js.map +1 -1
  427. package/dist/schema/plan.d.ts +285 -0
  428. package/dist/schema/plan.d.ts.map +1 -0
  429. package/dist/schema/plan.js +81 -0
  430. package/dist/schema/plan.js.map +1 -0
  431. package/dist/schema/spec.d.ts +72 -33
  432. package/dist/schema/spec.d.ts.map +1 -1
  433. package/dist/schema/spec.js +22 -9
  434. package/dist/schema/spec.js.map +1 -1
  435. package/dist/schema/task.d.ts +172 -161
  436. package/dist/schema/task.d.ts.map +1 -1
  437. package/dist/schema/task.js +21 -12
  438. package/dist/schema/task.js.map +1 -1
  439. package/dist/schema/triage.d.ts +266 -0
  440. package/dist/schema/triage.d.ts.map +1 -0
  441. package/dist/schema/triage.js +134 -0
  442. package/dist/schema/triage.js.map +1 -0
  443. package/dist/sessions/index.d.ts +2 -2
  444. package/dist/sessions/index.d.ts.map +1 -1
  445. package/dist/sessions/index.js +3 -3
  446. package/dist/sessions/index.js.map +1 -1
  447. package/dist/sessions/store.d.ts +233 -1
  448. package/dist/sessions/store.d.ts.map +1 -1
  449. package/dist/sessions/store.js +628 -31
  450. package/dist/sessions/store.js.map +1 -1
  451. package/dist/sessions/types.d.ts +10 -10
  452. package/dist/sessions/types.d.ts.map +1 -1
  453. package/dist/sessions/types.js +10 -9
  454. package/dist/sessions/types.js.map +1 -1
  455. package/dist/strings/errors.d.ts +51 -0
  456. package/dist/strings/errors.d.ts.map +1 -1
  457. package/dist/strings/errors.js +136 -106
  458. package/dist/strings/errors.js.map +1 -1
  459. package/dist/strings/guidance.d.ts.map +1 -1
  460. package/dist/strings/guidance.js +16 -16
  461. package/dist/strings/guidance.js.map +1 -1
  462. package/dist/strings/index.d.ts +4 -4
  463. package/dist/strings/index.d.ts.map +1 -1
  464. package/dist/strings/index.js +4 -4
  465. package/dist/strings/index.js.map +1 -1
  466. package/dist/strings/labels.d.ts +4 -0
  467. package/dist/strings/labels.d.ts.map +1 -1
  468. package/dist/strings/labels.js +45 -41
  469. package/dist/strings/labels.js.map +1 -1
  470. package/dist/strings/validation.d.ts.map +1 -1
  471. package/dist/strings/validation.js +71 -71
  472. package/dist/strings/validation.js.map +1 -1
  473. package/dist/utils/commit.d.ts +1 -1
  474. package/dist/utils/commit.d.ts.map +1 -1
  475. package/dist/utils/commit.js +28 -26
  476. package/dist/utils/commit.js.map +1 -1
  477. package/dist/utils/git.d.ts +1 -1
  478. package/dist/utils/git.d.ts.map +1 -1
  479. package/dist/utils/git.js +40 -38
  480. package/dist/utils/git.js.map +1 -1
  481. package/dist/utils/grep.js +11 -11
  482. package/dist/utils/grep.js.map +1 -1
  483. package/dist/utils/index.d.ts +7 -7
  484. package/dist/utils/index.d.ts.map +1 -1
  485. package/dist/utils/index.js +4 -4
  486. package/dist/utils/index.js.map +1 -1
  487. package/dist/utils/time.d.ts.map +1 -1
  488. package/dist/utils/time.js +10 -10
  489. package/dist/utils/time.js.map +1 -1
  490. package/package.json +28 -5
  491. package/plugin/.claude-plugin/marketplace.json +17 -0
  492. package/plugin/.claude-plugin/plugin.json +5 -0
  493. package/plugin/plugins/kspec/skills/help/SKILL.md +42 -0
  494. package/plugin/plugins/kspec/skills/triage/SKILL.md +206 -0
  495. package/plugin/plugins/kspec/skills/triage/docs/automation.md +120 -0
  496. package/plugin/plugins/kspec/skills/triage/docs/inbox.md +144 -0
  497. package/plugin/plugins/kspec/skills/triage/docs/observations.md +85 -0
  498. package/templates/agents-sections/01-quick-start.md +22 -0
  499. package/templates/agents-sections/02-shadow-branch.md +34 -0
  500. package/templates/agents-sections/03-task-lifecycle.md +48 -0
  501. package/templates/agents-sections/04-pr-workflow.md +17 -0
  502. package/templates/agents-sections/05-commit-convention.md +27 -0
  503. package/templates/agents-sections/06-ralph-loop.md +45 -0
  504. package/templates/hooks/pre-commit +34 -0
  505. package/templates/skills/help/SKILL.md +37 -0
  506. package/templates/skills/manifest.yaml +15 -0
  507. package/templates/skills/triage/SKILL.md +199 -0
  508. package/templates/skills/triage/docs/automation.md +120 -0
  509. package/templates/skills/triage/docs/inbox.md +144 -0
  510. package/templates/skills/triage/docs/observations.md +85 -0
@@ -0,0 +1,694 @@
1
+ /**
2
+ * Batch command parsing, validation, execution, and error reporting.
3
+ *
4
+ * Parses JSON batch input from stdin/file/inline, validates command paths
5
+ * against the CLI's introspection tree, executes in atomic or immediate
6
+ * mode, and produces helpful error messages.
7
+ */
8
+ import * as fs from "node:fs/promises";
9
+ import * as path from "node:path";
10
+ import * as os from "node:os";
11
+ import chalk from "chalk";
12
+ import { ZodError } from "zod";
13
+ import { BatchInputSchema, } from "../schema/batch.js";
14
+ import { initContext } from "../parser/yaml.js";
15
+ import { shadowAutoCommit, shadowPushAsync } from "../parser/shadow.js";
16
+ import { extractCommandTree, findCommand, flattenCommandTree } from "./introspection.js";
17
+ import { findClosestCommand } from "./suggest.js";
18
+ import { createBatchCommandFilter } from "./command-annotations.js";
19
+ import { setJsonMode, setVerboseMode } from "./output.js";
20
+ import { BatchExitError, OutputCapture, installExitInterceptor, uninstallExitInterceptor, setBatchMode, } from "./batch-context.js";
21
+ // ── Error Types ─────────────────────────────────────────────────────
22
+ export class BatchParseError extends Error {
23
+ constructor(message) {
24
+ super(message);
25
+ this.name = "BatchParseError";
26
+ }
27
+ }
28
+ // ── Parsing ─────────────────────────────────────────────────────────
29
+ /**
30
+ * Read raw text from a batch input source.
31
+ */
32
+ async function readSource(source) {
33
+ switch (source.type) {
34
+ case "inline":
35
+ return source.json;
36
+ case "file":
37
+ try {
38
+ return await fs.readFile(source.path, "utf-8");
39
+ }
40
+ catch (err) {
41
+ throw new BatchParseError(`Failed to read batch file: ${err.message}`);
42
+ }
43
+ case "stdin": {
44
+ const chunks = [];
45
+ for await (const chunk of process.stdin) {
46
+ chunks.push(chunk);
47
+ }
48
+ const text = Buffer.concat(chunks).toString("utf-8");
49
+ if (!text.trim()) {
50
+ throw new BatchParseError("No input received on stdin");
51
+ }
52
+ return text;
53
+ }
54
+ }
55
+ }
56
+ /**
57
+ * Parse batch input from a source, returning validated commands.
58
+ *
59
+ * @throws {BatchParseError} on invalid JSON, empty array, or schema violations
60
+ */
61
+ export async function parseBatchInput(source) {
62
+ const raw = await readSource(source);
63
+ // Parse JSON — preserve the native error message which includes position
64
+ let parsed;
65
+ try {
66
+ parsed = JSON.parse(raw);
67
+ }
68
+ catch (err) {
69
+ throw new BatchParseError(`Invalid JSON: ${err.message}`);
70
+ }
71
+ // Validate against schema
72
+ try {
73
+ return BatchInputSchema.parse(parsed);
74
+ }
75
+ catch (err) {
76
+ if (err instanceof ZodError) {
77
+ const messages = err.errors.map((e) => {
78
+ const path = e.path.length > 0 ? ` at ${e.path.join(".")}` : "";
79
+ return `${e.message}${path}`;
80
+ });
81
+ throw new BatchParseError(`Batch validation failed: ${messages.join("; ")}`);
82
+ }
83
+ throw err;
84
+ }
85
+ }
86
+ // ── Validation ──────────────────────────────────────────────────────
87
+ /**
88
+ * Extract the option name from Commander flag syntax.
89
+ * e.g. "-f, --force" → "force", "--spec-ref <value>" → "spec-ref"
90
+ */
91
+ function extractOptionName(flags) {
92
+ const match = flags.match(/--([a-zA-Z0-9-]+)/);
93
+ return match ? match[1] : null;
94
+ }
95
+ /**
96
+ * Convert a kebab-case string to camelCase.
97
+ * e.g. "spec-ref" → "specRef"
98
+ */
99
+ function kebabToCamel(s) {
100
+ return s.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
101
+ }
102
+ /**
103
+ * Get all known argument and option names for a command, returning both
104
+ * kebab-case and camelCase variants.
105
+ */
106
+ function getKnownArgNames(cmd) {
107
+ const names = new Set();
108
+ const required = [];
109
+ // Positional arguments
110
+ for (const arg of cmd.arguments) {
111
+ names.add(arg.name);
112
+ names.add(kebabToCamel(arg.name));
113
+ if (arg.required) {
114
+ required.push(arg.name);
115
+ }
116
+ }
117
+ // Options
118
+ for (const opt of cmd.options) {
119
+ const optName = extractOptionName(opt.flags);
120
+ if (optName) {
121
+ names.add(optName);
122
+ names.add(kebabToCamel(optName));
123
+ if (opt.mandatory) {
124
+ required.push(optName);
125
+ }
126
+ }
127
+ }
128
+ return { names, required };
129
+ }
130
+ /**
131
+ * Collect all leaf command paths from a command tree as space-joined strings.
132
+ */
133
+ function collectLeafCommandPaths(tree) {
134
+ const flat = flattenCommandTree(tree);
135
+ return flat
136
+ .filter((cmd) => cmd.subcommands.length === 0)
137
+ .map((cmd) => cmd.fullPath.slice(1).join(" ")) // skip root name
138
+ .filter((path) => path.length > 0);
139
+ }
140
+ /**
141
+ * Validate batch commands against the CLI's command tree.
142
+ *
143
+ * AC: @batch-command-schema ac-command-field — validates command paths
144
+ * AC: @batch-command-schema ac-args-mapping — validates arg names
145
+ * AC: @batch-command-schema ac-unknown-command — suggests similar commands
146
+ * AC: @batch-command-schema ac-missing-required — identifies missing args
147
+ * AC: @batch-command-schema ac-id-field — preserves id in errors
148
+ */
149
+ export function validateBatchCommands(commands, program, options) {
150
+ const errors = [];
151
+ const validLeafPaths = collectLeafCommandPaths(program);
152
+ for (let i = 0; i < commands.length; i++) {
153
+ const cmd = commands[i];
154
+ const parts = cmd.command.trim().split(/\s+/);
155
+ // 1. Resolve command path
156
+ const found = findCommand(program, parts);
157
+ if (!found) {
158
+ // Unknown command — suggest closest
159
+ const suggestion = findClosestCommand(cmd.command, validLeafPaths);
160
+ errors.push({
161
+ index: i,
162
+ id: cmd.id,
163
+ command: cmd.command,
164
+ type: "unknown_command",
165
+ message: `Unknown command: "${cmd.command}"`,
166
+ suggestion: suggestion ?? undefined,
167
+ });
168
+ continue;
169
+ }
170
+ // Reject command groups (non-leaf nodes)
171
+ if (found.subcommands.length > 0) {
172
+ const suggestion = findClosestCommand(cmd.command, validLeafPaths);
173
+ errors.push({
174
+ index: i,
175
+ id: cmd.id,
176
+ command: cmd.command,
177
+ type: "unknown_command",
178
+ message: `"${cmd.command}" is a command group, not an executable command`,
179
+ suggestion: suggestion ?? undefined,
180
+ });
181
+ continue;
182
+ }
183
+ // 2. Reject nested batch commands (batch or any subcommands like batch commands)
184
+ // AC: @batch-allowed-commands ac-batch-itself
185
+ if (found.fullPath[1] === "batch") {
186
+ errors.push({
187
+ index: i,
188
+ id: cmd.id,
189
+ command: cmd.command,
190
+ type: "rejected_command",
191
+ message: "Nested batch commands are not allowed",
192
+ });
193
+ continue;
194
+ }
195
+ // 3. Apply command filter if provided
196
+ // AC: @batch-allowed-commands ac-denylist
197
+ if (options?.commandFilter && !options.commandFilter(found)) {
198
+ errors.push({
199
+ index: i,
200
+ id: cmd.id,
201
+ command: cmd.command,
202
+ type: "rejected_command",
203
+ message: `Command "${cmd.command}" is not allowed in batch mode. Only mutating commands can be used in batch.`,
204
+ });
205
+ continue;
206
+ }
207
+ // 4. Check for unknown args
208
+ const { names: knownNames, required: requiredNames } = getKnownArgNames(found);
209
+ // Collect all known names as flat array for suggestion matching
210
+ const knownNamesArray = Array.from(knownNames);
211
+ for (const argKey of Object.keys(cmd.args)) {
212
+ // Accept both kebab-case and camelCase
213
+ if (!knownNames.has(argKey)) {
214
+ const suggestion = findClosestCommand(argKey, knownNamesArray);
215
+ errors.push({
216
+ index: i,
217
+ id: cmd.id,
218
+ command: cmd.command,
219
+ type: "unknown_arg",
220
+ message: `Unknown argument "${argKey}" for command "${cmd.command}"`,
221
+ suggestion: suggestion ?? undefined,
222
+ });
223
+ }
224
+ }
225
+ // 5. Check for missing required args
226
+ for (const reqName of requiredNames) {
227
+ const camelName = kebabToCamel(reqName);
228
+ if (!(reqName in cmd.args) &&
229
+ !(camelName in cmd.args) &&
230
+ // Skip if provided via positional alias
231
+ !Object.keys(cmd.args).some((k) => kebabToCamel(k) === camelName)) {
232
+ errors.push({
233
+ index: i,
234
+ id: cmd.id,
235
+ command: cmd.command,
236
+ type: "missing_required",
237
+ message: `Missing required argument "${reqName}" for command "${cmd.command}"`,
238
+ });
239
+ }
240
+ }
241
+ }
242
+ return {
243
+ valid: errors.length === 0,
244
+ commands,
245
+ errors,
246
+ };
247
+ }
248
+ // ── Error Reporting ─────────────────────────────────────────────────
249
+ /**
250
+ * Format validation errors for human or JSON output.
251
+ *
252
+ * @param result - Validation result containing errors
253
+ * @param json - If true, return JSON string; otherwise human-readable lines
254
+ * @returns Formatted error string
255
+ */
256
+ export function reportBatchValidationErrors(result, json = false) {
257
+ if (result.valid) {
258
+ return json ? JSON.stringify({ valid: true, errors: [] }) : "";
259
+ }
260
+ if (json) {
261
+ return JSON.stringify({
262
+ valid: false,
263
+ errors: result.errors,
264
+ }, null, 2);
265
+ }
266
+ // Human-readable format
267
+ const lines = [];
268
+ for (const err of result.errors) {
269
+ const label = err.id ?? `#${err.index}`;
270
+ lines.push(`[${label}] ${err.message}`);
271
+ if (err.suggestion) {
272
+ lines.push(` Did you mean: ${err.suggestion}?`);
273
+ }
274
+ }
275
+ // Add helpful hint for discoverability
276
+ lines.push("");
277
+ lines.push("Run 'kspec batch commands' for a list of available commands.");
278
+ return lines.join("\n");
279
+ }
280
+ /**
281
+ * Build Commander argv from a BatchCommand and its CommandMeta.
282
+ *
283
+ * Translates { command: "inbox add", args: { content: "hello", tag: ["a","b"] } }
284
+ * into ["inbox", "add", "hello", "--tag", "a", "--tag", "b"]
285
+ *
286
+ * Positional args are emitted in Commander definition order (not JSON key order)
287
+ * to ensure correct argument mapping regardless of how the JSON was serialized.
288
+ */
289
+ export function buildCommandArgv(cmd, cmdMeta) {
290
+ const argv = [...cmd.command.trim().split(/\s+/)];
291
+ // Build sets for classification
292
+ const positionalDefs = cmdMeta.arguments; // ordered by Commander definition
293
+ const positionalNameSet = new Set();
294
+ for (const arg of positionalDefs) {
295
+ positionalNameSet.add(arg.name);
296
+ positionalNameSet.add(kebabToCamel(arg.name));
297
+ }
298
+ const optionMap = new Map();
299
+ for (const opt of cmdMeta.options) {
300
+ const name = extractOptionName(opt.flags);
301
+ if (name) {
302
+ optionMap.set(name, { flags: opt.flags, variadic: opt.variadic });
303
+ optionMap.set(kebabToCamel(name), { flags: opt.flags, variadic: opt.variadic });
304
+ }
305
+ }
306
+ // Phase 1: Emit positional args in Commander definition order
307
+ for (const argDef of positionalDefs) {
308
+ const name = argDef.name;
309
+ const camelName = kebabToCamel(name);
310
+ const value = cmd.args[name] ?? cmd.args[camelName];
311
+ if (value === undefined)
312
+ continue;
313
+ if (Array.isArray(value)) {
314
+ for (const v of value)
315
+ argv.push(String(v));
316
+ }
317
+ else {
318
+ argv.push(String(value));
319
+ }
320
+ }
321
+ // Phase 2: Emit options from remaining keys
322
+ for (const [key, value] of Object.entries(cmd.args)) {
323
+ const camelKey = kebabToCamel(key);
324
+ // Skip positional args (already emitted)
325
+ if (positionalNameSet.has(key) || positionalNameSet.has(camelKey)) {
326
+ continue;
327
+ }
328
+ // Convert camelCase key back to kebab-case for CLI
329
+ const kebabKey = key.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`);
330
+ const flagName = `--${kebabKey}`;
331
+ if (typeof value === "boolean") {
332
+ if (value) {
333
+ argv.push(flagName);
334
+ }
335
+ // false booleans: omit (Commander treats absence as false)
336
+ }
337
+ else if (Array.isArray(value)) {
338
+ // Variadic or repeated options
339
+ for (const v of value) {
340
+ argv.push(flagName, String(v));
341
+ }
342
+ }
343
+ else if (value !== null && value !== undefined) {
344
+ argv.push(flagName, String(value));
345
+ }
346
+ }
347
+ return argv;
348
+ }
349
+ /**
350
+ * Reset Commander command tree state between dispatches.
351
+ * Commander retains _optionValues between parseAsync calls.
352
+ */
353
+ export function resetCommandTree(cmd) {
354
+ cmd._optionValues = {};
355
+ cmd._optionValueSources = {};
356
+ cmd.processedArgs = [];
357
+ for (const sub of cmd.commands) {
358
+ resetCommandTree(sub);
359
+ }
360
+ }
361
+ /**
362
+ * Check if a CommandMeta supports the --force option.
363
+ */
364
+ function commandHasForce(cmdMeta) {
365
+ return cmdMeta.options.some((opt) => {
366
+ const name = extractOptionName(opt.flags);
367
+ return name === "force";
368
+ });
369
+ }
370
+ /**
371
+ * Execute a batch of commands.
372
+ *
373
+ * AC: @batch-exec ac-default-atomic — atomic mode by default
374
+ * AC: @batch-exec ac-no-atomic-flag — immediate mode with --no-atomic
375
+ * AC: @batch-exec ac-stop-on-error — stop on first failure (default)
376
+ * AC: @batch-exec ac-continue — continue on error with --continue
377
+ * AC: @batch-exec ac-dry-run — validate without executing
378
+ * AC: @batch-exec ac-prevalidate — validation before any execution
379
+ * AC: @batch-exec ac-confirmation-suppressed — auto-append --force
380
+ */
381
+ export async function executeBatch(commands, program, options) {
382
+ const mode = options.atomic ? "atomic" : "immediate";
383
+ // Build command tree for validation
384
+ const tree = extractCommandTree(program);
385
+ const commandFilter = createBatchCommandFilter();
386
+ // AC: ac-prevalidate — validate all commands before executing any
387
+ const validation = validateBatchCommands(commands, tree, { commandFilter });
388
+ if (!validation.valid) {
389
+ return {
390
+ success: false,
391
+ mode,
392
+ summary: {
393
+ total: commands.length,
394
+ succeeded: 0,
395
+ failed: validation.errors.length,
396
+ },
397
+ results: validation.errors.map((err) => ({
398
+ index: err.index,
399
+ id: err.id,
400
+ command: err.command,
401
+ success: false,
402
+ error: err.message,
403
+ suggestion: err.suggestion,
404
+ })),
405
+ validationFailed: true,
406
+ };
407
+ }
408
+ // AC: ac-dry-run — validate without executing
409
+ if (options.dryRun) {
410
+ return {
411
+ success: true,
412
+ mode,
413
+ summary: { total: commands.length, succeeded: commands.length, failed: 0 },
414
+ results: commands.map((cmd, i) => ({
415
+ index: i,
416
+ id: cmd.id,
417
+ command: cmd.command,
418
+ success: true,
419
+ output: "dry-run: would execute",
420
+ })),
421
+ };
422
+ }
423
+ if (options.atomic) {
424
+ return executeAtomic(commands, program, tree, options);
425
+ }
426
+ else {
427
+ return executeImmediate(commands, program, tree, options);
428
+ }
429
+ }
430
+ /**
431
+ * Atomic execution: copy specDir to temp, run all, copy back on success.
432
+ *
433
+ * AC: @batch-exec ac-default-atomic
434
+ * AC: @batch-exec ac-atomic-rollback
435
+ * AC: @batch-exec ac-atomic-isolation
436
+ * AC: @batch-exec ac-single-commit
437
+ */
438
+ async function executeAtomic(commands, program, tree, options) {
439
+ // Get the real context for copy-back
440
+ const ctx = await initContext();
441
+ const realSpecDir = ctx.specDir;
442
+ // Create temp copy using mkdtemp for safe, collision-free naming
443
+ const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "kspec-batch-"));
444
+ await fs.cp(realSpecDir, tempDir, { recursive: true });
445
+ // Remove .git from temp copy to prevent worktree pointer leaks
446
+ await fs.rm(path.join(tempDir, ".git"), { force: true, recursive: true });
447
+ // Set up atomic context
448
+ const savedChalkLevel = chalk.level;
449
+ const savedSpecDir = process.env.KSPEC_SPEC_DIR;
450
+ const savedBatchProjectRoot = process.env.KSPEC_BATCH_PROJECT_ROOT;
451
+ // AC: @project-config ac-7 — set real project root before redirecting spec dir
452
+ process.env.KSPEC_BATCH_PROJECT_ROOT = ctx.rootDir;
453
+ process.env.KSPEC_SPEC_DIR = tempDir;
454
+ setBatchMode(true);
455
+ chalk.level = 0;
456
+ const results = [];
457
+ let allSucceeded = true;
458
+ let copyBackFailed = false;
459
+ try {
460
+ for (let i = 0; i < commands.length; i++) {
461
+ const cmd = commands[i];
462
+ const result = await dispatchCommand(cmd, i, program, tree);
463
+ results.push(result);
464
+ if (!result.success) {
465
+ allSucceeded = false;
466
+ // Atomic mode: stop on first failure, discard everything
467
+ // Fill remaining as not-executed
468
+ for (let j = i + 1; j < commands.length; j++) {
469
+ results.push({
470
+ index: j,
471
+ id: commands[j].id,
472
+ command: commands[j].command,
473
+ success: false,
474
+ error: "Not executed (prior command failed in atomic mode)",
475
+ });
476
+ }
477
+ break;
478
+ }
479
+ }
480
+ // Copy back on success
481
+ if (allSucceeded) {
482
+ try {
483
+ // Clear real specDir contents (except .git and .gitattributes) before copy-back
484
+ const entries = await fs.readdir(realSpecDir);
485
+ for (const entry of entries) {
486
+ if (entry === ".git" || entry === ".gitattributes")
487
+ continue;
488
+ await fs.rm(path.join(realSpecDir, entry), { recursive: true, force: true });
489
+ }
490
+ // Copy temp contents back
491
+ const tempEntries = await fs.readdir(tempDir);
492
+ for (const entry of tempEntries) {
493
+ await fs.cp(path.join(tempDir, entry), path.join(realSpecDir, entry), { recursive: true });
494
+ }
495
+ // Single shadow commit for all changes
496
+ if (ctx.shadow?.enabled) {
497
+ const successCount = results.filter((r) => r.success).length;
498
+ await shadowAutoCommit(ctx.shadow.worktreeDir, `batch: ${successCount} command${successCount !== 1 ? "s" : ""}`);
499
+ shadowPushAsync(ctx.shadow.worktreeDir);
500
+ }
501
+ }
502
+ catch (copyErr) {
503
+ // Copy-back failed — preserve tempDir for manual recovery
504
+ copyBackFailed = true;
505
+ allSucceeded = false;
506
+ console.error(`Batch copy-back failed: ${copyErr instanceof Error ? copyErr.message : copyErr}`);
507
+ console.error(`Temp dir preserved for recovery: ${tempDir}`);
508
+ }
509
+ }
510
+ }
511
+ finally {
512
+ // Clean up
513
+ setBatchMode(false);
514
+ chalk.level = savedChalkLevel;
515
+ if (savedSpecDir !== undefined) {
516
+ process.env.KSPEC_SPEC_DIR = savedSpecDir;
517
+ }
518
+ else {
519
+ delete process.env.KSPEC_SPEC_DIR;
520
+ }
521
+ // AC: @project-config ac-7 — restore batch project root env var
522
+ if (savedBatchProjectRoot !== undefined) {
523
+ process.env.KSPEC_BATCH_PROJECT_ROOT = savedBatchProjectRoot;
524
+ }
525
+ else {
526
+ delete process.env.KSPEC_BATCH_PROJECT_ROOT;
527
+ }
528
+ // Only remove temp dir if copy-back succeeded (or commands failed)
529
+ if (!copyBackFailed) {
530
+ await fs.rm(tempDir, { recursive: true, force: true }).catch(() => { });
531
+ }
532
+ }
533
+ const succeeded = results.filter((r) => r.success).length;
534
+ const failed = results.filter((r) => !r.success).length;
535
+ return {
536
+ success: allSucceeded,
537
+ mode: "atomic",
538
+ summary: { total: commands.length, succeeded, failed },
539
+ results,
540
+ };
541
+ }
542
+ /**
543
+ * Immediate execution: execute against real state, per-command commits.
544
+ *
545
+ * AC: @batch-exec ac-no-atomic-flag
546
+ * AC: @batch-exec ac-immediate-per-commit
547
+ * AC: @batch-exec ac-immediate-no-rollback
548
+ */
549
+ async function executeImmediate(commands, program, tree, options) {
550
+ const savedChalkLevel = chalk.level;
551
+ chalk.level = 0;
552
+ const results = [];
553
+ try {
554
+ for (let i = 0; i < commands.length; i++) {
555
+ const cmd = commands[i];
556
+ const result = await dispatchCommand(cmd, i, program, tree);
557
+ results.push(result);
558
+ if (!result.success && !options.continueOnError) {
559
+ // Stop on first failure, remaining not executed
560
+ for (let j = i + 1; j < commands.length; j++) {
561
+ results.push({
562
+ index: j,
563
+ id: commands[j].id,
564
+ command: commands[j].command,
565
+ success: false,
566
+ error: "Not executed (prior command failed)",
567
+ });
568
+ }
569
+ break;
570
+ }
571
+ }
572
+ }
573
+ finally {
574
+ chalk.level = savedChalkLevel;
575
+ }
576
+ const succeeded = results.filter((r) => r.success).length;
577
+ const failed = results.filter((r) => !r.success).length;
578
+ return {
579
+ success: failed === 0,
580
+ mode: "immediate",
581
+ summary: { total: commands.length, succeeded, failed },
582
+ results,
583
+ };
584
+ }
585
+ /**
586
+ * Dispatch a single command through Commander's parseAsync.
587
+ */
588
+ async function dispatchCommand(cmd, index, program, tree) {
589
+ const parts = cmd.command.trim().split(/\s+/);
590
+ const cmdMeta = findCommand(tree, parts);
591
+ if (!cmdMeta) {
592
+ return {
593
+ index,
594
+ id: cmd.id,
595
+ command: cmd.command,
596
+ success: false,
597
+ error: `Command not found: ${cmd.command}`,
598
+ };
599
+ }
600
+ // Build argv, auto-appending --force if supported
601
+ // AC: ac-confirmation-suppressed
602
+ const enrichedCmd = { ...cmd, args: { ...cmd.args } };
603
+ if (commandHasForce(cmdMeta) && !("force" in enrichedCmd.args)) {
604
+ enrichedCmd.args.force = true;
605
+ }
606
+ const argv = buildCommandArgv(enrichedCmd, cmdMeta);
607
+ // Reset Commander state
608
+ resetCommandTree(program);
609
+ setJsonMode(false);
610
+ setVerboseMode(false);
611
+ const capture = new OutputCapture();
612
+ capture.start();
613
+ installExitInterceptor();
614
+ let caughtError = undefined;
615
+ let succeeded = false;
616
+ try {
617
+ await program.parseAsync(argv, { from: "user" });
618
+ succeeded = true;
619
+ }
620
+ catch (err) {
621
+ caughtError = err;
622
+ }
623
+ finally {
624
+ capture.stop();
625
+ uninstallExitInterceptor();
626
+ }
627
+ if (succeeded) {
628
+ const output = capture.getOutput();
629
+ // Try to parse output as JSON for structured results
630
+ let parsedOutput = output;
631
+ try {
632
+ parsedOutput = JSON.parse(output);
633
+ }
634
+ catch {
635
+ // Not JSON, keep as string
636
+ }
637
+ return {
638
+ index,
639
+ id: cmd.id,
640
+ command: cmd.command,
641
+ success: true,
642
+ output: parsedOutput,
643
+ };
644
+ }
645
+ // Handle errors
646
+ const err = caughtError;
647
+ if (err instanceof BatchExitError) {
648
+ // Filter out BatchExitError noise from captured output (handlers may
649
+ // catch and re-log the error before calling process.exit again)
650
+ const capturedOutput = capture
651
+ .getOutput()
652
+ .split("\n")
653
+ .filter((line) => !line.includes("BatchExitError"))
654
+ .join("\n")
655
+ .trim();
656
+ if (err.code === 0) {
657
+ return {
658
+ index,
659
+ id: cmd.id,
660
+ command: cmd.command,
661
+ success: true,
662
+ output: capturedOutput,
663
+ };
664
+ }
665
+ return {
666
+ index,
667
+ id: cmd.id,
668
+ command: cmd.command,
669
+ success: false,
670
+ error: capturedOutput || `Command exited with code ${err.code}`,
671
+ };
672
+ }
673
+ // Commander errors (e.g., missing required arg at runtime)
674
+ const isCommanderError = err && typeof err === "object" && "code" in err && "exitCode" in err;
675
+ if (isCommanderError) {
676
+ const cmdErr = err;
677
+ return {
678
+ index,
679
+ id: cmd.id,
680
+ command: cmd.command,
681
+ success: false,
682
+ error: cmdErr.message || capture.getOutput(),
683
+ };
684
+ }
685
+ // Generic errors
686
+ return {
687
+ index,
688
+ id: cmd.id,
689
+ command: cmd.command,
690
+ success: false,
691
+ error: err instanceof Error ? err.message : String(err),
692
+ };
693
+ }
694
+ //# sourceMappingURL=batch-exec.js.map