@kynetic-ai/spec 0.1.2 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (540) hide show
  1. package/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 +107 -0
  32. package/dist/cli/batch-exec.d.ts.map +1 -0
  33. package/dist/cli/batch-exec.js +706 -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 +141 -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 +58 -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 +534 -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 +547 -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 +1109 -170
  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 +810 -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 +1267 -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 +56 -0
  156. package/dist/cli/commands/skill-install.d.ts.map +1 -0
  157. package/dist/cli/commands/skill-install.js +509 -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 +584 -350
  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 +225 -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 +483 -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 +237 -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 +402 -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 +457 -0
  309. package/dist/parser/config.d.ts.map +1 -0
  310. package/dist/parser/config.js +373 -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 +197 -0
  345. package/dist/parser/plan-document.d.ts.map +1 -0
  346. package/dist/parser/plan-document.js +341 -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 +301 -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 +94 -0
  401. package/dist/ralph/subagent.d.ts.map +1 -0
  402. package/dist/ralph/subagent.js +193 -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 +97 -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 +8 -2
  413. package/dist/schema/common.d.ts.map +1 -1
  414. package/dist/schema/common.js +42 -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 +241 -1
  448. package/dist/sessions/store.d.ts.map +1 -1
  449. package/dist/sessions/store.js +810 -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 +55 -0
  456. package/dist/strings/errors.d.ts.map +1 -1
  457. package/dist/strings/errors.js +138 -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/triage/actions.d.ts +27 -0
  474. package/dist/triage/actions.d.ts.map +1 -0
  475. package/dist/triage/actions.js +95 -0
  476. package/dist/triage/actions.js.map +1 -0
  477. package/dist/triage/constants.d.ts +6 -0
  478. package/dist/triage/constants.d.ts.map +1 -0
  479. package/dist/triage/constants.js +7 -0
  480. package/dist/triage/constants.js.map +1 -0
  481. package/dist/triage/index.d.ts +3 -0
  482. package/dist/triage/index.d.ts.map +1 -0
  483. package/dist/triage/index.js +3 -0
  484. package/dist/triage/index.js.map +1 -0
  485. package/dist/utils/commit.d.ts +1 -1
  486. package/dist/utils/commit.d.ts.map +1 -1
  487. package/dist/utils/commit.js +28 -26
  488. package/dist/utils/commit.js.map +1 -1
  489. package/dist/utils/git.d.ts +1 -1
  490. package/dist/utils/git.d.ts.map +1 -1
  491. package/dist/utils/git.js +40 -38
  492. package/dist/utils/git.js.map +1 -1
  493. package/dist/utils/grep.js +11 -11
  494. package/dist/utils/grep.js.map +1 -1
  495. package/dist/utils/index.d.ts +7 -7
  496. package/dist/utils/index.d.ts.map +1 -1
  497. package/dist/utils/index.js +4 -4
  498. package/dist/utils/index.js.map +1 -1
  499. package/dist/utils/time.d.ts.map +1 -1
  500. package/dist/utils/time.js +10 -10
  501. package/dist/utils/time.js.map +1 -1
  502. package/package.json +28 -5
  503. package/plugin/.claude-plugin/marketplace.json +17 -0
  504. package/plugin/.claude-plugin/plugin.json +5 -0
  505. package/plugin/plugins/kspec/skills/create-workflow/SKILL.md +235 -0
  506. package/plugin/plugins/kspec/skills/help/SKILL.md +42 -0
  507. package/plugin/plugins/kspec/skills/observations/SKILL.md +143 -0
  508. package/plugin/plugins/kspec/skills/plan/SKILL.md +343 -0
  509. package/plugin/plugins/kspec/skills/reflect/SKILL.md +161 -0
  510. package/plugin/plugins/kspec/skills/review/SKILL.md +193 -0
  511. package/plugin/plugins/kspec/skills/task-work/SKILL.md +303 -0
  512. package/plugin/plugins/kspec/skills/triage/SKILL.md +206 -0
  513. package/plugin/plugins/kspec/skills/triage/docs/automation.md +120 -0
  514. package/plugin/plugins/kspec/skills/triage/docs/inbox.md +144 -0
  515. package/plugin/plugins/kspec/skills/triage/docs/observations.md +85 -0
  516. package/plugin/plugins/kspec/skills/triage-automation/SKILL.md +140 -0
  517. package/plugin/plugins/kspec/skills/triage-inbox/SKILL.md +232 -0
  518. package/plugin/plugins/kspec/skills/writing-specs/SKILL.md +340 -0
  519. package/templates/agents-sections/01-quick-start.md +22 -0
  520. package/templates/agents-sections/02-shadow-branch.md +34 -0
  521. package/templates/agents-sections/03-task-lifecycle.md +48 -0
  522. package/templates/agents-sections/04-pr-workflow.md +17 -0
  523. package/templates/agents-sections/05-commit-convention.md +27 -0
  524. package/templates/agents-sections/06-ralph-loop.md +45 -0
  525. package/templates/hooks/pre-commit +34 -0
  526. package/templates/skills/create-workflow/SKILL.md +228 -0
  527. package/templates/skills/help/SKILL.md +37 -0
  528. package/templates/skills/manifest.yaml +60 -0
  529. package/templates/skills/observations/SKILL.md +137 -0
  530. package/templates/skills/plan/SKILL.md +336 -0
  531. package/templates/skills/reflect/SKILL.md +155 -0
  532. package/templates/skills/review/SKILL.md +186 -0
  533. package/templates/skills/task-work/SKILL.md +296 -0
  534. package/templates/skills/triage/SKILL.md +199 -0
  535. package/templates/skills/triage/docs/automation.md +120 -0
  536. package/templates/skills/triage/docs/inbox.md +144 -0
  537. package/templates/skills/triage/docs/observations.md +85 -0
  538. package/templates/skills/triage-automation/SKILL.md +134 -0
  539. package/templates/skills/triage-inbox/SKILL.md +225 -0
  540. package/templates/skills/writing-specs/SKILL.md +333 -0
@@ -0,0 +1,402 @@
1
+ /**
2
+ * Triage API Routes
3
+ *
4
+ * REST endpoints for triage operations:
5
+ * - GET /api/triage - list records with filters and pagination
6
+ * - GET /api/triage/export - export records for agent handoff
7
+ * - POST /api/triage - record a triage decision
8
+ * - GET /api/triage/:ref - get single record
9
+ * - POST /api/triage/:ref/override - override a decision
10
+ * - POST /api/triage/:ref/act - execute a triage action
11
+ *
12
+ * AC Coverage:
13
+ * - @triage-daemon-api ac-1: GET list sorted by created_at desc
14
+ * - @triage-daemon-api ac-2: Status filter on GET list
15
+ * - @triage-daemon-api ac-3: POST creates record with snapshot
16
+ * - @triage-daemon-api ac-4: PUT override sets override fields
17
+ * - @triage-daemon-api ac-5: PUT act executes and transitions
18
+ * - @triage-daemon-api ac-6: GET export with format parameter
19
+ * - @triage-daemon-api ac-7: POST 404 for nonexistent inbox item
20
+ * - @triage-daemon-api ac-8: PUT act 409 for already acted
21
+ * - @triage-daemon-api ac-9: PUT act 422 for pending record
22
+ */
23
+
24
+ import { Elysia, t } from 'elysia';
25
+ import { ulid } from 'ulidx';
26
+ import {
27
+ initContext,
28
+ loadTriageRecords,
29
+ saveTriageRecord,
30
+ findTriageRecordByRef,
31
+ findTriageRecordByInboxRef,
32
+ loadInboxItems,
33
+ findInboxItemByRef,
34
+ getAuthor,
35
+ type LoadedTriageRecord,
36
+ } from '../../parser/index.js';
37
+ import { commitIfShadow } from '../../parser/shadow.js';
38
+ import { normalizeRefInput } from '../../schema/index.js';
39
+ import type { TriageAction } from '../../schema/index.js';
40
+ import { exportTriageRecords } from '../../export/triage.js';
41
+ import { executeTriageAction, VALID_ACTIONS } from '../../triage/index.js';
42
+ import type { PubSubManager } from '../websocket/pubsub';
43
+
44
+ interface TriageRouteOptions {
45
+ pubsub: PubSubManager;
46
+ }
47
+
48
+ // VALID_ACTIONS and executeTriageAction imported from shared triage module
49
+
50
+ export function createTriageRoutes(options: TriageRouteOptions) {
51
+ const { pubsub } = options;
52
+
53
+ return new Elysia({ prefix: '/api/triage' })
54
+ // AC: @triage-daemon-api ac-1, ac-2 - List triage records with filters and pagination
55
+ // AC: @trait-api-endpoint ac-1, ac-4 - JSON response with pagination wrapper
56
+ .get(
57
+ '/',
58
+ async ({ query, projectContext }) => {
59
+ // AC: @multi-directory-daemon ac-1, ac-24 - Use project context from middleware
60
+ const ctx = await initContext(projectContext.path);
61
+ const records = await loadTriageRecords(ctx);
62
+
63
+ // Apply filters
64
+ let filtered = records;
65
+
66
+ // AC: @triage-daemon-api ac-2 - Status filter
67
+ if (query.status) {
68
+ const statusFilters = Array.isArray(query.status) ? query.status : [query.status];
69
+ filtered = filtered.filter((r) => statusFilters.includes(r.status));
70
+ }
71
+
72
+ // Action filter
73
+ if (query.action) {
74
+ const actionFilters = Array.isArray(query.action) ? query.action : [query.action];
75
+ filtered = filtered.filter((r) => r.action && actionFilters.includes(r.action));
76
+ }
77
+
78
+ // AC: @triage-daemon-api ac-1 - Sort by created_at descending (newest first)
79
+ filtered.sort(
80
+ (a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime()
81
+ );
82
+
83
+ // AC: @trait-api-endpoint ac-4 - Pagination with limit and offset
84
+ const total = filtered.length;
85
+ const offset = Number(query.offset) || 0;
86
+ const limit = Number(query.limit) || total;
87
+
88
+ const paginated = filtered.slice(offset, offset + limit);
89
+
90
+ return {
91
+ items: paginated,
92
+ total,
93
+ offset,
94
+ limit,
95
+ };
96
+ },
97
+ {
98
+ query: t.Object({
99
+ status: t.Optional(t.Union([t.String(), t.Array(t.String())])),
100
+ action: t.Optional(t.Union([t.String(), t.Array(t.String())])),
101
+ limit: t.Optional(t.String()),
102
+ offset: t.Optional(t.String()),
103
+ }),
104
+ }
105
+ )
106
+
107
+ // AC: @triage-daemon-api ac-6 - Export triage records
108
+ // NOTE: This route MUST be defined before /:ref to avoid "export" being parsed as a ref
109
+ .get(
110
+ '/export',
111
+ async ({ query, projectContext }) => {
112
+ // AC: @multi-directory-daemon ac-1, ac-24 - Use project context from middleware
113
+ const ctx = await initContext(projectContext.path);
114
+ let records = await loadTriageRecords(ctx);
115
+
116
+ // Optional status filter on export
117
+ if (query.status) {
118
+ const statusFilters = Array.isArray(query.status) ? query.status : [query.status];
119
+ records = records.filter((r) => statusFilters.includes(r.status));
120
+ }
121
+
122
+ const format = (query.format || 'json') as 'json' | 'context';
123
+
124
+ // AC: @triage-daemon-api ac-6 - Export via shared formatter
125
+ // AC: @triage-agent-export ac-1, ac-2, ac-3, ac-4
126
+ return exportTriageRecords(records, format);
127
+ },
128
+ {
129
+ query: t.Object({
130
+ format: t.Optional(t.String()),
131
+ status: t.Optional(t.Union([t.String(), t.Array(t.String())])),
132
+ }),
133
+ }
134
+ )
135
+
136
+ // AC: @triage-daemon-api ac-3 - Record a triage decision
137
+ // AC: @trait-api-endpoint ac-1, ac-3, ac-5 - JSON response, validation, shadow commit
138
+ .post(
139
+ '/',
140
+ async ({ body, error: errorResponse, projectContext }) => {
141
+ // AC: @multi-directory-daemon ac-1, ac-24 - Use project context from middleware
142
+ const ctx = await initContext(projectContext.path);
143
+
144
+ // AC: @trait-api-endpoint ac-3 - Validate action
145
+ if (!VALID_ACTIONS.includes(body.action)) {
146
+ return errorResponse(400, {
147
+ error: 'validation_error',
148
+ details: [
149
+ {
150
+ field: 'action',
151
+ message: `Action must be one of: ${VALID_ACTIONS.join(', ')}`,
152
+ },
153
+ ],
154
+ });
155
+ }
156
+
157
+ // AC: @triage-daemon-api ac-7 - Validate inbox item exists
158
+ const inboxItems = await loadInboxItems(ctx);
159
+ const inboxItem = findInboxItemByRef(inboxItems, body.inbox_ref);
160
+ if (!inboxItem) {
161
+ // AC: @trait-api-endpoint ac-2 - 404 with error guidance
162
+ return errorResponse(404, {
163
+ error: 'not_found',
164
+ message: `Inbox item reference "${body.inbox_ref}" not found`,
165
+ suggestion: 'Use kspec inbox list or GET /api/inbox to find valid inbox item references',
166
+ });
167
+ }
168
+
169
+ const author = body.decided_by || getAuthor(ctx.config?.identity?.author);
170
+ const evidenceRefs = body.evidence_refs
171
+ ? body.evidence_refs.map(normalizeRefInput)
172
+ : [];
173
+
174
+ // Check if a record already exists for this inbox item (upsert case)
175
+ const existingRecords = await loadTriageRecords(ctx);
176
+ const existing = findTriageRecordByInboxRef(existingRecords, inboxItem._ulid);
177
+
178
+ // AC: @triage-daemon-api ac-3 - Create record with item_snapshot
179
+ const record: LoadedTriageRecord = {
180
+ _ulid: existing?._ulid || ulid(),
181
+ inbox_ref: inboxItem._ulid,
182
+ item_snapshot: inboxItem.text,
183
+ status: 'triaged',
184
+ action: body.action as TriageAction,
185
+ reasoning: body.reasoning,
186
+ decided_by: author,
187
+ evidence_refs: evidenceRefs,
188
+ created_at: existing?.created_at || new Date().toISOString(),
189
+ };
190
+
191
+ await saveTriageRecord(ctx, record);
192
+
193
+ // Reload to get the persisted record (saveTriageRecord may upsert by inbox_ref)
194
+ const savedRecords = await loadTriageRecords(ctx);
195
+ const savedRecord = findTriageRecordByInboxRef(savedRecords, inboxItem._ulid) || record;
196
+
197
+ // AC: @trait-api-endpoint ac-5 - Shadow commit
198
+ await commitIfShadow(ctx.shadow, `triage: record ${savedRecord._ulid.slice(0, 8)} as ${savedRecord.action}`);
199
+
200
+ // AC: @triage-daemon-api ac-3 - Broadcast triage:updates via WebSocket
201
+ // AC: @trait-websocket-protocol ac-3 - Broadcast event
202
+ pubsub.broadcast('triage:updates', 'triage_record_created', {
203
+ ulid: savedRecord._ulid,
204
+ inbox_ref: savedRecord.inbox_ref,
205
+ action: savedRecord.action,
206
+ }, projectContext.path);
207
+
208
+ // AC: @trait-api-endpoint ac-1 - Return 2xx with JSON body
209
+ return {
210
+ success: true,
211
+ record: savedRecord,
212
+ };
213
+ },
214
+ {
215
+ body: t.Object({
216
+ inbox_ref: t.String(),
217
+ action: t.String(),
218
+ reasoning: t.String(),
219
+ decided_by: t.Optional(t.String()),
220
+ evidence_refs: t.Optional(t.Array(t.String())),
221
+ }),
222
+ }
223
+ )
224
+
225
+ // GET single triage record
226
+ .get(
227
+ '/:ref',
228
+ async ({ params, error: errorResponse, projectContext }) => {
229
+ // AC: @multi-directory-daemon ac-1, ac-24 - Use project context from middleware
230
+ const ctx = await initContext(projectContext.path);
231
+ const records = await loadTriageRecords(ctx);
232
+
233
+ // AC: @trait-api-endpoint ac-2 - Resolve ref
234
+ const record = findTriageRecordByRef(records, params.ref);
235
+ if (!record) {
236
+ return errorResponse(404, {
237
+ error: 'not_found',
238
+ message: `Triage record reference "${params.ref}" not found`,
239
+ suggestion: 'Use kspec triage list or GET /api/triage to find valid triage record references',
240
+ });
241
+ }
242
+
243
+ return record;
244
+ },
245
+ {
246
+ params: t.Object({
247
+ ref: t.String(),
248
+ }),
249
+ }
250
+ )
251
+
252
+ // AC: @triage-daemon-api ac-4 - Override a triage decision
253
+ // AC: @trait-api-endpoint ac-1, ac-5 - JSON response, shadow commit
254
+ .post(
255
+ '/:ref/override',
256
+ async ({ params, body, error: errorResponse, projectContext }) => {
257
+ // AC: @multi-directory-daemon ac-1, ac-24 - Use project context from middleware
258
+ const ctx = await initContext(projectContext.path);
259
+ const records = await loadTriageRecords(ctx);
260
+
261
+ // AC: @trait-api-endpoint ac-2 - Resolve ref
262
+ const record = findTriageRecordByRef(records, params.ref);
263
+ if (!record) {
264
+ return errorResponse(404, {
265
+ error: 'not_found',
266
+ message: `Triage record reference "${params.ref}" not found`,
267
+ suggestion: 'Use kspec triage list or GET /api/triage to find valid triage record references',
268
+ });
269
+ }
270
+
271
+ // AC: @trait-api-endpoint ac-3 - Validate action
272
+ if (!VALID_ACTIONS.includes(body.action)) {
273
+ return errorResponse(400, {
274
+ error: 'validation_error',
275
+ details: [
276
+ {
277
+ field: 'action',
278
+ message: `Action must be one of: ${VALID_ACTIONS.join(', ')}`,
279
+ },
280
+ ],
281
+ });
282
+ }
283
+
284
+ const overrideBy = body.override_by || getAuthor(ctx.config?.identity?.author);
285
+
286
+ // AC: @triage-daemon-api ac-4 - Set override fields and update action
287
+ record.override_reasoning = body.reasoning;
288
+ record.override_by = overrideBy;
289
+ record.override_at = new Date().toISOString();
290
+ record.action = body.action as TriageAction;
291
+ record.updated_at = new Date().toISOString();
292
+
293
+ // Re-triage if already acted on (allows re-acting with new action)
294
+ // Clear stale execution metadata to avoid leaking previous action results
295
+ if (record.status === 'acted_on') {
296
+ record.status = 'triaged';
297
+ record.acted_at = undefined;
298
+ record.result_ref = undefined;
299
+ }
300
+
301
+ await saveTriageRecord(ctx, record);
302
+
303
+ // AC: @trait-api-endpoint ac-5 - Shadow commit
304
+ await commitIfShadow(ctx.shadow, `triage: override ${record._ulid.slice(0, 8)}`);
305
+
306
+ // AC: @triage-daemon-api ac-4 - Broadcast triage:updates
307
+ pubsub.broadcast('triage:updates', 'triage_record_updated', {
308
+ ulid: record._ulid,
309
+ action: 'override',
310
+ new_action: record.action,
311
+ }, projectContext.path);
312
+
313
+ return {
314
+ success: true,
315
+ record,
316
+ };
317
+ },
318
+ {
319
+ params: t.Object({
320
+ ref: t.String(),
321
+ }),
322
+ body: t.Object({
323
+ action: t.String(),
324
+ reasoning: t.String(),
325
+ override_by: t.Optional(t.String()),
326
+ }),
327
+ }
328
+ )
329
+
330
+ // AC: @triage-daemon-api ac-5, ac-8, ac-9 - Execute a triage action
331
+ // AC: @trait-api-endpoint ac-1, ac-5 - JSON response, shadow commit
332
+ .post(
333
+ '/:ref/act',
334
+ async ({ params, error: errorResponse, projectContext }) => {
335
+ // AC: @multi-directory-daemon ac-1, ac-24 - Use project context from middleware
336
+ const ctx = await initContext(projectContext.path);
337
+ const records = await loadTriageRecords(ctx);
338
+
339
+ // AC: @trait-api-endpoint ac-2 - Resolve ref
340
+ const record = findTriageRecordByRef(records, params.ref);
341
+ if (!record) {
342
+ return errorResponse(404, {
343
+ error: 'not_found',
344
+ message: `Triage record reference "${params.ref}" not found`,
345
+ suggestion: 'Use kspec triage list or GET /api/triage to find valid triage record references',
346
+ });
347
+ }
348
+
349
+ // AC: @triage-daemon-api ac-8 - Already acted on → 409
350
+ if (record.status === 'acted_on') {
351
+ return errorResponse(409, {
352
+ error: 'invalid_transition',
353
+ message: 'Triage record has already been acted on',
354
+ current: record.status,
355
+ suggestion: 'Use override to change the decision before acting again',
356
+ });
357
+ }
358
+
359
+ // AC: @triage-daemon-api ac-9 - Pending (no decision) → 422
360
+ if (record.status === 'pending') {
361
+ return errorResponse(422, {
362
+ error: 'incomplete_record',
363
+ message: 'No decision has been recorded for this triage record. Complete triage first.',
364
+ suggestion: 'Use POST /api/triage to record a decision, or kspec triage record <inbox-ref> --action <action> --reasoning <text>',
365
+ });
366
+ }
367
+
368
+ // AC: @triage-daemon-api ac-5 - Execute the action
369
+ const result = await executeTriageAction(record, ctx);
370
+
371
+ // Transition to acted_on
372
+ record.status = 'acted_on';
373
+ record.acted_at = new Date().toISOString();
374
+ if (result.resultRef) {
375
+ record.result_ref = result.resultRef;
376
+ }
377
+ record.updated_at = new Date().toISOString();
378
+
379
+ await saveTriageRecord(ctx, record);
380
+
381
+ // AC: @trait-api-endpoint ac-5 - Shadow commit
382
+ await commitIfShadow(ctx.shadow, `triage: act ${record._ulid.slice(0, 8)}`);
383
+
384
+ // AC: @triage-daemon-api ac-5 - Broadcast triage:updates
385
+ pubsub.broadcast('triage:updates', 'triage_record_acted', {
386
+ ulid: record._ulid,
387
+ action: record.action,
388
+ result_ref: record.result_ref,
389
+ }, projectContext.path);
390
+
391
+ return {
392
+ success: true,
393
+ record,
394
+ };
395
+ },
396
+ {
397
+ params: t.Object({
398
+ ref: t.String(),
399
+ }),
400
+ }
401
+ );
402
+ }
@@ -0,0 +1,248 @@
1
+ /**
2
+ * Validation and Search API Routes
3
+ *
4
+ * REST endpoints for search and validation operations:
5
+ * - GET /api/search?q=query - Search across all items/tasks/inbox/meta
6
+ * - GET /api/validate - Run full validation
7
+ * - GET /api/alignment - Get alignment stats and warnings
8
+ *
9
+ * AC Coverage:
10
+ * - ac-19: GET /api/search?q=query searches across all entities
11
+ * - ac-20: GET /api/validate returns ValidationResult
12
+ * - ac-21: GET /api/alignment returns AlignmentIndex stats
13
+ */
14
+
15
+ import { Elysia, t } from 'elysia';
16
+ import {
17
+ initContext,
18
+ buildIndexes,
19
+ loadInboxItems,
20
+ loadMetaContext,
21
+ validate,
22
+ AlignmentIndex,
23
+ type LoadedSpecItem,
24
+ type LoadedTask,
25
+ type LoadedInboxItem,
26
+ } from '../../parser/index.js';
27
+ import type {
28
+ LoadedAgent,
29
+ LoadedWorkflow,
30
+ LoadedObservation,
31
+ LoadedConvention,
32
+ } from '../../parser/meta.js';
33
+ import { grepItem } from '../../utils/grep.js';
34
+
35
+ interface ValidationRouteOptions {}
36
+
37
+ export function createValidationRoutes(options: ValidationRouteOptions = {}) {
38
+ // No closure-scoped kspecDir needed - comes from middleware
39
+
40
+ return new Elysia({ prefix: '/api' })
41
+ // AC: @api-contract ac-19 - Search across all entities
42
+ .get(
43
+ '/search',
44
+ async ({ query, projectContext }) => {
45
+ // AC: @multi-directory-daemon ac-1, ac-24 - Use project context from middleware
46
+ const ctx = await initContext(projectContext.path);
47
+ const { tasks, items } = await buildIndexes(ctx);
48
+
49
+ const pattern = query.q;
50
+ if (!pattern) {
51
+ return {
52
+ results: [],
53
+ total: 0,
54
+ };
55
+ }
56
+
57
+ const limit = query.limit ? parseInt(query.limit, 10) : 50;
58
+
59
+ interface SearchResult {
60
+ type:
61
+ | 'item'
62
+ | 'task'
63
+ | 'inbox'
64
+ | 'observation'
65
+ | 'agent'
66
+ | 'workflow'
67
+ | 'convention';
68
+ ulid: string;
69
+ title: string;
70
+ matchedFields: string[];
71
+ }
72
+
73
+ const results: SearchResult[] = [];
74
+
75
+ // AC: @api-contract ac-19 - Search spec items
76
+ if (!query.tasksOnly) {
77
+ for (const item of items) {
78
+ // Apply type filter if provided
79
+ if (query.type && item.type !== query.type) continue;
80
+
81
+ const match = grepItem(item as unknown as Record<string, unknown>, pattern);
82
+ if (match) {
83
+ results.push({
84
+ type: 'item',
85
+ ulid: item._ulid,
86
+ title: item.title,
87
+ matchedFields: match.matchedFields,
88
+ });
89
+ }
90
+ }
91
+ }
92
+
93
+ // AC: @api-contract ac-19 - Search tasks
94
+ if (!query.itemsOnly) {
95
+ for (const task of tasks) {
96
+ // Apply status filter if provided
97
+ if (query.status && task.status !== query.status) continue;
98
+
99
+ const match = grepItem(task as unknown as Record<string, unknown>, pattern);
100
+ if (match) {
101
+ results.push({
102
+ type: 'task',
103
+ ulid: task._ulid,
104
+ title: task.title,
105
+ matchedFields: match.matchedFields,
106
+ });
107
+ }
108
+ }
109
+ }
110
+
111
+ // AC: @api-contract ac-19 - Search inbox items
112
+ if (!query.itemsOnly && !query.tasksOnly) {
113
+ const inboxItems = await loadInboxItems(ctx);
114
+ for (const inboxItem of inboxItems) {
115
+ const match = grepItem(inboxItem as unknown as Record<string, unknown>, pattern);
116
+ if (match) {
117
+ results.push({
118
+ type: 'inbox',
119
+ ulid: inboxItem._ulid,
120
+ title: inboxItem.text,
121
+ matchedFields: match.matchedFields,
122
+ });
123
+ }
124
+ }
125
+ }
126
+
127
+ // AC: @api-contract ac-19 - Search meta entities
128
+ if (!query.itemsOnly && !query.tasksOnly) {
129
+ const metaCtx = await loadMetaContext(ctx);
130
+
131
+ // Search observations
132
+ for (const observation of metaCtx.observations) {
133
+ const match = grepItem(observation as unknown as Record<string, unknown>, pattern);
134
+ if (match) {
135
+ results.push({
136
+ type: 'observation',
137
+ ulid: observation._ulid,
138
+ title: observation.content,
139
+ matchedFields: match.matchedFields,
140
+ });
141
+ }
142
+ }
143
+
144
+ // Search agents
145
+ for (const agent of metaCtx.agents) {
146
+ const match = grepItem(agent as unknown as Record<string, unknown>, pattern);
147
+ if (match) {
148
+ results.push({
149
+ type: 'agent',
150
+ ulid: agent._ulid,
151
+ title: `${agent.id} - ${agent.name}`,
152
+ matchedFields: match.matchedFields,
153
+ });
154
+ }
155
+ }
156
+
157
+ // Search workflows
158
+ for (const workflow of metaCtx.workflows) {
159
+ const match = grepItem(workflow as unknown as Record<string, unknown>, pattern);
160
+ if (match) {
161
+ results.push({
162
+ type: 'workflow',
163
+ ulid: workflow._ulid,
164
+ title: workflow.id,
165
+ matchedFields: match.matchedFields,
166
+ });
167
+ }
168
+ }
169
+
170
+ // Search conventions
171
+ for (const convention of metaCtx.conventions) {
172
+ const match = grepItem(convention as unknown as Record<string, unknown>, pattern);
173
+ if (match) {
174
+ results.push({
175
+ type: 'convention',
176
+ ulid: convention._ulid,
177
+ title: convention.domain,
178
+ matchedFields: match.matchedFields,
179
+ });
180
+ }
181
+ }
182
+ }
183
+
184
+ // Apply limit
185
+ const limitedResults = results.slice(0, limit);
186
+
187
+ // AC: @api-contract ac-19 - Return search results with matched fields
188
+ return {
189
+ results: limitedResults,
190
+ total: results.length,
191
+ showing: limitedResults.length,
192
+ };
193
+ },
194
+ {
195
+ query: t.Object({
196
+ q: t.Optional(t.String()),
197
+ type: t.Optional(t.String()),
198
+ status: t.Optional(t.String()),
199
+ itemsOnly: t.Optional(t.String()),
200
+ tasksOnly: t.Optional(t.String()),
201
+ limit: t.Optional(t.String()),
202
+ }),
203
+ }
204
+ )
205
+
206
+ // AC: @api-contract ac-20 - Run full validation
207
+ .get('/validate', async ({ projectContext }) => {
208
+ // AC: @multi-directory-daemon ac-1, ac-24 - Use project context from middleware
209
+ const ctx = await initContext(projectContext.path);
210
+
211
+ // AC: @api-contract ac-20 - Run validation and return ValidationResult
212
+ const result = await validate(ctx);
213
+
214
+ return {
215
+ valid: result.valid,
216
+ schemaErrors: result.schemaErrors,
217
+ refErrors: result.refErrors,
218
+ refWarnings: result.refWarnings,
219
+ orphans: result.orphans,
220
+ completenessWarnings: result.completenessWarnings,
221
+ traitCycles: result.traitCycles,
222
+ };
223
+ })
224
+
225
+ // AC: @api-contract ac-21 - Get alignment stats and warnings
226
+ .get('/alignment', async ({ projectContext }) => {
227
+ // AC: @multi-directory-daemon ac-1, ac-24 - Use project context from middleware
228
+ const ctx = await initContext(projectContext.path);
229
+ const { tasks, items, refIndex } = await buildIndexes(ctx);
230
+
231
+ // AC: @api-contract ac-21 - Create AlignmentIndex and get stats
232
+ const alignIndex = new AlignmentIndex(tasks, items);
233
+ alignIndex.buildLinks(refIndex);
234
+
235
+ const stats = alignIndex.getStats();
236
+ const warnings = alignIndex.findAlignmentWarnings();
237
+
238
+ return {
239
+ stats: {
240
+ totalSpecs: stats.totalSpecs,
241
+ specsWithTasks: stats.specsWithTasks,
242
+ alignedSpecs: stats.alignedSpecs,
243
+ orphanedSpecs: stats.orphanedSpecs,
244
+ },
245
+ warnings,
246
+ };
247
+ });
248
+ }