@kynetic-ai/spec 0.10.0 → 0.12.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 (487) hide show
  1. package/README.md +55 -455
  2. package/dist/agent-runtime/bootstrap.d.ts +31 -0
  3. package/dist/agent-runtime/bootstrap.d.ts.map +1 -0
  4. package/dist/agent-runtime/bootstrap.js +302 -0
  5. package/dist/agent-runtime/bootstrap.js.map +1 -0
  6. package/dist/agent-runtime/dispatch.d.ts +150 -10
  7. package/dist/agent-runtime/dispatch.d.ts.map +1 -1
  8. package/dist/agent-runtime/dispatch.js +1248 -244
  9. package/dist/agent-runtime/dispatch.js.map +1 -1
  10. package/dist/agent-runtime/invocation.d.ts +28 -1
  11. package/dist/agent-runtime/invocation.d.ts.map +1 -1
  12. package/dist/agent-runtime/invocation.js +172 -60
  13. package/dist/agent-runtime/invocation.js.map +1 -1
  14. package/dist/agent-runtime/prompts.d.ts +9 -0
  15. package/dist/agent-runtime/prompts.d.ts.map +1 -1
  16. package/dist/agent-runtime/prompts.js +42 -7
  17. package/dist/agent-runtime/prompts.js.map +1 -1
  18. package/dist/agent-runtime/session-event-accumulator.d.ts +83 -0
  19. package/dist/agent-runtime/session-event-accumulator.d.ts.map +1 -0
  20. package/dist/agent-runtime/session-event-accumulator.js +203 -0
  21. package/dist/agent-runtime/session-event-accumulator.js.map +1 -0
  22. package/dist/agent-runtime/session-event-types.d.ts +67 -0
  23. package/dist/agent-runtime/session-event-types.d.ts.map +1 -0
  24. package/dist/agent-runtime/session-event-types.js +13 -0
  25. package/dist/agent-runtime/session-event-types.js.map +1 -0
  26. package/dist/agent-runtime/workspace.d.ts +244 -0
  27. package/dist/agent-runtime/workspace.d.ts.map +1 -0
  28. package/dist/agent-runtime/workspace.js +2025 -0
  29. package/dist/agent-runtime/workspace.js.map +1 -0
  30. package/dist/agents/adapters.d.ts.map +1 -1
  31. package/dist/agents/adapters.js +58 -13
  32. package/dist/agents/adapters.js.map +1 -1
  33. package/dist/agents/spawner.d.ts +8 -0
  34. package/dist/agents/spawner.d.ts.map +1 -1
  35. package/dist/agents/spawner.js +25 -3
  36. package/dist/agents/spawner.js.map +1 -1
  37. package/dist/cli/batch-exec.js +1 -1
  38. package/dist/cli/batch-exec.js.map +1 -1
  39. package/dist/cli/command-annotations.d.ts +15 -3
  40. package/dist/cli/command-annotations.d.ts.map +1 -1
  41. package/dist/cli/command-annotations.js +23 -3
  42. package/dist/cli/command-annotations.js.map +1 -1
  43. package/dist/cli/commands/agent.d.ts +2 -0
  44. package/dist/cli/commands/agent.d.ts.map +1 -1
  45. package/dist/cli/commands/agent.js +144 -27
  46. package/dist/cli/commands/agent.js.map +1 -1
  47. package/dist/cli/commands/agents.d.ts.map +1 -1
  48. package/dist/cli/commands/agents.js +5 -5
  49. package/dist/cli/commands/agents.js.map +1 -1
  50. package/dist/cli/commands/derive.d.ts.map +1 -1
  51. package/dist/cli/commands/derive.js +118 -3
  52. package/dist/cli/commands/derive.js.map +1 -1
  53. package/dist/cli/commands/guard.d.ts.map +1 -1
  54. package/dist/cli/commands/guard.js +8 -6
  55. package/dist/cli/commands/guard.js.map +1 -1
  56. package/dist/cli/commands/index.d.ts +1 -0
  57. package/dist/cli/commands/index.d.ts.map +1 -1
  58. package/dist/cli/commands/index.js +1 -0
  59. package/dist/cli/commands/index.js.map +1 -1
  60. package/dist/cli/commands/init.d.ts.map +1 -1
  61. package/dist/cli/commands/init.js +20 -0
  62. package/dist/cli/commands/init.js.map +1 -1
  63. package/dist/cli/commands/item.d.ts.map +1 -1
  64. package/dist/cli/commands/item.js +205 -47
  65. package/dist/cli/commands/item.js.map +1 -1
  66. package/dist/cli/commands/log.d.ts.map +1 -1
  67. package/dist/cli/commands/log.js +24 -10
  68. package/dist/cli/commands/log.js.map +1 -1
  69. package/dist/cli/commands/meta.d.ts.map +1 -1
  70. package/dist/cli/commands/meta.js +10 -1
  71. package/dist/cli/commands/meta.js.map +1 -1
  72. package/dist/cli/commands/plan-import.d.ts +3 -3
  73. package/dist/cli/commands/plan-import.d.ts.map +1 -1
  74. package/dist/cli/commands/plan-import.js +213 -528
  75. package/dist/cli/commands/plan-import.js.map +1 -1
  76. package/dist/cli/commands/plan.d.ts.map +1 -1
  77. package/dist/cli/commands/plan.js +533 -83
  78. package/dist/cli/commands/plan.js.map +1 -1
  79. package/dist/cli/commands/review.d.ts +14 -0
  80. package/dist/cli/commands/review.d.ts.map +1 -0
  81. package/dist/cli/commands/review.js +1142 -0
  82. package/dist/cli/commands/review.js.map +1 -0
  83. package/dist/cli/commands/serve.d.ts +1 -0
  84. package/dist/cli/commands/serve.d.ts.map +1 -1
  85. package/dist/cli/commands/serve.js +33 -10
  86. package/dist/cli/commands/serve.js.map +1 -1
  87. package/dist/cli/commands/session/checkpoint.d.ts +2 -4
  88. package/dist/cli/commands/session/checkpoint.d.ts.map +1 -1
  89. package/dist/cli/commands/session/checkpoint.js +6 -107
  90. package/dist/cli/commands/session/checkpoint.js.map +1 -1
  91. package/dist/cli/commands/session/commands.d.ts.map +1 -1
  92. package/dist/cli/commands/session/commands.js +33 -23
  93. package/dist/cli/commands/session/commands.js.map +1 -1
  94. package/dist/cli/commands/session/compact.js +4 -4
  95. package/dist/cli/commands/session/compact.js.map +1 -1
  96. package/dist/cli/commands/session/create.js +2 -2
  97. package/dist/cli/commands/session/create.js.map +1 -1
  98. package/dist/cli/commands/session/format.d.ts.map +1 -1
  99. package/dist/cli/commands/session/format.js +1 -6
  100. package/dist/cli/commands/session/format.js.map +1 -1
  101. package/dist/cli/commands/session/log.d.ts +32 -7
  102. package/dist/cli/commands/session/log.d.ts.map +1 -1
  103. package/dist/cli/commands/session/log.js +166 -60
  104. package/dist/cli/commands/session/log.js.map +1 -1
  105. package/dist/cli/commands/session/migrate.d.ts +9 -0
  106. package/dist/cli/commands/session/migrate.d.ts.map +1 -0
  107. package/dist/cli/commands/session/migrate.js +46 -0
  108. package/dist/cli/commands/session/migrate.js.map +1 -0
  109. package/dist/cli/commands/session/stale-close.d.ts.map +1 -1
  110. package/dist/cli/commands/session/stale-close.js +5 -8
  111. package/dist/cli/commands/session/stale-close.js.map +1 -1
  112. package/dist/cli/commands/session/types.d.ts +1 -1
  113. package/dist/cli/commands/session/types.d.ts.map +1 -1
  114. package/dist/cli/commands/setup.d.ts +2 -2
  115. package/dist/cli/commands/setup.d.ts.map +1 -1
  116. package/dist/cli/commands/setup.js +287 -257
  117. package/dist/cli/commands/setup.js.map +1 -1
  118. package/dist/cli/commands/shadow.d.ts.map +1 -1
  119. package/dist/cli/commands/shadow.js +147 -31
  120. package/dist/cli/commands/shadow.js.map +1 -1
  121. package/dist/cli/commands/skill-crud.d.ts +7 -0
  122. package/dist/cli/commands/skill-crud.d.ts.map +1 -1
  123. package/dist/cli/commands/skill-crud.js +41 -18
  124. package/dist/cli/commands/skill-crud.js.map +1 -1
  125. package/dist/cli/commands/skill-diff.d.ts.map +1 -1
  126. package/dist/cli/commands/skill-diff.js +29 -3
  127. package/dist/cli/commands/skill-diff.js.map +1 -1
  128. package/dist/cli/commands/skill-install.d.ts.map +1 -1
  129. package/dist/cli/commands/skill-install.js +5 -4
  130. package/dist/cli/commands/skill-install.js.map +1 -1
  131. package/dist/cli/commands/task.d.ts.map +1 -1
  132. package/dist/cli/commands/task.js +359 -49
  133. package/dist/cli/commands/task.js.map +1 -1
  134. package/dist/cli/commands/trait.d.ts.map +1 -1
  135. package/dist/cli/commands/trait.js +5 -27
  136. package/dist/cli/commands/trait.js.map +1 -1
  137. package/dist/cli/commands/validate.d.ts.map +1 -1
  138. package/dist/cli/commands/validate.js +113 -52
  139. package/dist/cli/commands/validate.js.map +1 -1
  140. package/dist/cli/index.d.ts.map +1 -1
  141. package/dist/cli/index.js +69 -2
  142. package/dist/cli/index.js.map +1 -1
  143. package/dist/cli/output.d.ts +26 -0
  144. package/dist/cli/output.d.ts.map +1 -1
  145. package/dist/cli/output.js +108 -1
  146. package/dist/cli/output.js.map +1 -1
  147. package/dist/cli/sync-mode.d.ts +44 -0
  148. package/dist/cli/sync-mode.d.ts.map +1 -0
  149. package/dist/cli/sync-mode.js +64 -0
  150. package/dist/cli/sync-mode.js.map +1 -0
  151. package/dist/daemon/middleware/project-context.ts +25 -7
  152. package/dist/daemon/project-context.ts +18 -0
  153. package/dist/daemon/routes/agent-dispatch.ts +107 -23
  154. package/dist/daemon/routes/aggregation.ts +184 -0
  155. package/dist/daemon/routes/inbox.ts +5 -0
  156. package/dist/daemon/routes/items.ts +167 -0
  157. package/dist/daemon/routes/meta.ts +141 -1
  158. package/dist/daemon/routes/plans.ts +147 -0
  159. package/dist/daemon/routes/projects.ts +28 -6
  160. package/dist/daemon/routes/ref-resolution.ts +119 -0
  161. package/dist/daemon/routes/refs.ts +42 -0
  162. package/dist/daemon/routes/session-related.ts +140 -0
  163. package/dist/daemon/routes/sessions.ts +581 -0
  164. package/dist/daemon/routes/tasks.ts +257 -2
  165. package/dist/daemon/routes/triage.ts +40 -1
  166. package/dist/daemon/routes/validation.ts +1 -1
  167. package/dist/daemon/server.ts +165 -50
  168. package/dist/daemon/session-sync.ts +11 -0
  169. package/dist/daemon/shadow-sync.ts +11 -0
  170. package/dist/daemon/watcher.ts +56 -5
  171. package/dist/daemon/websocket/project-resolution.ts +77 -0
  172. package/dist/export/json.d.ts.map +1 -1
  173. package/dist/export/json.js +104 -1
  174. package/dist/export/json.js.map +1 -1
  175. package/dist/export/types.d.ts +52 -1
  176. package/dist/export/types.d.ts.map +1 -1
  177. package/dist/index.d.ts +1 -0
  178. package/dist/index.d.ts.map +1 -1
  179. package/dist/index.js +1 -0
  180. package/dist/index.js.map +1 -1
  181. package/dist/parser/agent-detection.d.ts +1 -1
  182. package/dist/parser/agent-detection.d.ts.map +1 -1
  183. package/dist/parser/agent-detection.js +10 -0
  184. package/dist/parser/agent-detection.js.map +1 -1
  185. package/dist/parser/alignment.d.ts.map +1 -1
  186. package/dist/parser/alignment.js +4 -2
  187. package/dist/parser/alignment.js.map +1 -1
  188. package/dist/parser/config.d.ts +397 -2
  189. package/dist/parser/config.d.ts.map +1 -1
  190. package/dist/parser/config.js +125 -3
  191. package/dist/parser/config.js.map +1 -1
  192. package/dist/parser/dispatch-workspaces.d.ts +18 -0
  193. package/dist/parser/dispatch-workspaces.d.ts.map +1 -0
  194. package/dist/parser/dispatch-workspaces.js +209 -0
  195. package/dist/parser/dispatch-workspaces.js.map +1 -0
  196. package/dist/parser/doctor.d.ts.map +1 -1
  197. package/dist/parser/doctor.js +27 -8
  198. package/dist/parser/doctor.js.map +1 -1
  199. package/dist/parser/file-lock.d.ts.map +1 -1
  200. package/dist/parser/file-lock.js +9 -2
  201. package/dist/parser/file-lock.js.map +1 -1
  202. package/dist/parser/index.d.ts +6 -0
  203. package/dist/parser/index.d.ts.map +1 -1
  204. package/dist/parser/index.js +6 -0
  205. package/dist/parser/index.js.map +1 -1
  206. package/dist/parser/plans.d.ts.map +1 -1
  207. package/dist/parser/plans.js +1 -0
  208. package/dist/parser/plans.js.map +1 -1
  209. package/dist/parser/refs.d.ts +8 -1
  210. package/dist/parser/refs.d.ts.map +1 -1
  211. package/dist/parser/refs.js +27 -1
  212. package/dist/parser/refs.js.map +1 -1
  213. package/dist/parser/review-operations.d.ts +72 -0
  214. package/dist/parser/review-operations.d.ts.map +1 -0
  215. package/dist/parser/review-operations.js +185 -0
  216. package/dist/parser/review-operations.js.map +1 -0
  217. package/dist/parser/review-task-integration.d.ts +78 -0
  218. package/dist/parser/review-task-integration.d.ts.map +1 -0
  219. package/dist/parser/review-task-integration.js +173 -0
  220. package/dist/parser/review-task-integration.js.map +1 -0
  221. package/dist/parser/review-threads.d.ts +101 -0
  222. package/dist/parser/review-threads.d.ts.map +1 -0
  223. package/dist/parser/review-threads.js +222 -0
  224. package/dist/parser/review-threads.js.map +1 -0
  225. package/dist/parser/review-validation.d.ts +69 -0
  226. package/dist/parser/review-validation.d.ts.map +1 -0
  227. package/dist/parser/review-validation.js +207 -0
  228. package/dist/parser/review-validation.js.map +1 -0
  229. package/dist/parser/reviews.d.ts +58 -0
  230. package/dist/parser/reviews.d.ts.map +1 -0
  231. package/dist/parser/reviews.js +230 -0
  232. package/dist/parser/reviews.js.map +1 -0
  233. package/dist/parser/session-branch.d.ts +91 -0
  234. package/dist/parser/session-branch.d.ts.map +1 -0
  235. package/dist/parser/session-branch.js +565 -0
  236. package/dist/parser/session-branch.js.map +1 -0
  237. package/dist/parser/session-sync-scheduler.d.ts +53 -0
  238. package/dist/parser/session-sync-scheduler.d.ts.map +1 -0
  239. package/dist/parser/session-sync-scheduler.js +100 -0
  240. package/dist/parser/session-sync-scheduler.js.map +1 -0
  241. package/dist/parser/setup-status.d.ts +7 -1
  242. package/dist/parser/setup-status.d.ts.map +1 -1
  243. package/dist/parser/setup-status.js +104 -39
  244. package/dist/parser/setup-status.js.map +1 -1
  245. package/dist/parser/shadow-sync-scheduler.d.ts +71 -0
  246. package/dist/parser/shadow-sync-scheduler.d.ts.map +1 -0
  247. package/dist/parser/shadow-sync-scheduler.js +139 -0
  248. package/dist/parser/shadow-sync-scheduler.js.map +1 -0
  249. package/dist/parser/shadow.d.ts +121 -14
  250. package/dist/parser/shadow.d.ts.map +1 -1
  251. package/dist/parser/shadow.js +752 -27
  252. package/dist/parser/shadow.js.map +1 -1
  253. package/dist/parser/skill-render.d.ts +24 -0
  254. package/dist/parser/skill-render.d.ts.map +1 -1
  255. package/dist/parser/skill-render.js +98 -26
  256. package/dist/parser/skill-render.js.map +1 -1
  257. package/dist/parser/validate.d.ts +43 -3
  258. package/dist/parser/validate.d.ts.map +1 -1
  259. package/dist/parser/validate.js +204 -30
  260. package/dist/parser/validate.js.map +1 -1
  261. package/dist/parser/yaml.d.ts +47 -11
  262. package/dist/parser/yaml.d.ts.map +1 -1
  263. package/dist/parser/yaml.js +329 -149
  264. package/dist/parser/yaml.js.map +1 -1
  265. package/dist/review/checks.d.ts +97 -0
  266. package/dist/review/checks.d.ts.map +1 -0
  267. package/dist/review/checks.js +175 -0
  268. package/dist/review/checks.js.map +1 -0
  269. package/dist/review/index.d.ts +3 -0
  270. package/dist/review/index.d.ts.map +1 -0
  271. package/dist/review/index.js +3 -0
  272. package/dist/review/index.js.map +1 -0
  273. package/dist/review/subject-bindings.d.ts +83 -0
  274. package/dist/review/subject-bindings.d.ts.map +1 -0
  275. package/dist/review/subject-bindings.js +175 -0
  276. package/dist/review/subject-bindings.js.map +1 -0
  277. package/dist/schema/common.d.ts +26 -0
  278. package/dist/schema/common.d.ts.map +1 -1
  279. package/dist/schema/common.js +13 -0
  280. package/dist/schema/common.js.map +1 -1
  281. package/dist/schema/dispatch-workspace.d.ts +2643 -0
  282. package/dist/schema/dispatch-workspace.d.ts.map +1 -0
  283. package/dist/schema/dispatch-workspace.js +187 -0
  284. package/dist/schema/dispatch-workspace.js.map +1 -0
  285. package/dist/schema/inbox.d.ts +8 -8
  286. package/dist/schema/index.d.ts +2 -0
  287. package/dist/schema/index.d.ts.map +1 -1
  288. package/dist/schema/index.js +2 -0
  289. package/dist/schema/index.js.map +1 -1
  290. package/dist/schema/meta.d.ts +663 -116
  291. package/dist/schema/meta.d.ts.map +1 -1
  292. package/dist/schema/meta.js +28 -0
  293. package/dist/schema/meta.js.map +1 -1
  294. package/dist/schema/plan.d.ts +30 -19
  295. package/dist/schema/plan.d.ts.map +1 -1
  296. package/dist/schema/plan.js +3 -1
  297. package/dist/schema/plan.js.map +1 -1
  298. package/dist/schema/review-records.d.ts +2676 -0
  299. package/dist/schema/review-records.d.ts.map +1 -0
  300. package/dist/schema/review-records.js +232 -0
  301. package/dist/schema/review-records.js.map +1 -0
  302. package/dist/schema/spec.d.ts +32 -14
  303. package/dist/schema/spec.d.ts.map +1 -1
  304. package/dist/schema/spec.js +5 -0
  305. package/dist/schema/spec.js.map +1 -1
  306. package/dist/schema/task.d.ts +187 -29
  307. package/dist/schema/task.d.ts.map +1 -1
  308. package/dist/schema/task.js +12 -2
  309. package/dist/schema/task.js.map +1 -1
  310. package/dist/schema/triage.d.ts +22 -22
  311. package/dist/sessions/cache.d.ts +119 -0
  312. package/dist/sessions/cache.d.ts.map +1 -0
  313. package/dist/sessions/cache.js +284 -0
  314. package/dist/sessions/cache.js.map +1 -0
  315. package/dist/sessions/index.d.ts +1 -0
  316. package/dist/sessions/index.d.ts.map +1 -1
  317. package/dist/sessions/index.js +2 -0
  318. package/dist/sessions/index.js.map +1 -1
  319. package/dist/sessions/legacy.d.ts +77 -0
  320. package/dist/sessions/legacy.d.ts.map +1 -0
  321. package/dist/sessions/legacy.js +146 -0
  322. package/dist/sessions/legacy.js.map +1 -0
  323. package/dist/sessions/store.d.ts +115 -71
  324. package/dist/sessions/store.d.ts.map +1 -1
  325. package/dist/sessions/store.js +357 -182
  326. package/dist/sessions/store.js.map +1 -1
  327. package/dist/sessions/types.d.ts +44 -16
  328. package/dist/sessions/types.d.ts.map +1 -1
  329. package/dist/sessions/types.js +11 -2
  330. package/dist/sessions/types.js.map +1 -1
  331. package/dist/strings/errors.d.ts +32 -0
  332. package/dist/strings/errors.d.ts.map +1 -1
  333. package/dist/strings/errors.js +17 -0
  334. package/dist/strings/errors.js.map +1 -1
  335. package/dist/strings/labels.d.ts +1 -0
  336. package/dist/strings/labels.d.ts.map +1 -1
  337. package/dist/strings/labels.js +1 -0
  338. package/dist/strings/labels.js.map +1 -1
  339. package/dist/utils/activity.d.ts +101 -0
  340. package/dist/utils/activity.d.ts.map +1 -0
  341. package/dist/utils/activity.js +408 -0
  342. package/dist/utils/activity.js.map +1 -0
  343. package/dist/utils/git.d.ts +31 -0
  344. package/dist/utils/git.d.ts.map +1 -1
  345. package/dist/utils/git.js +87 -0
  346. package/dist/utils/git.js.map +1 -1
  347. package/dist/utils/index.d.ts +2 -0
  348. package/dist/utils/index.d.ts.map +1 -1
  349. package/dist/utils/index.js +1 -0
  350. package/dist/utils/index.js.map +1 -1
  351. package/dist/web-ui/_app/immutable/assets/0.tmlwn-Ih.css +1 -0
  352. package/dist/web-ui/_app/immutable/assets/9.BwwJybWx.css +1 -0
  353. package/dist/web-ui/_app/immutable/chunks/2KqE8gtn.js +1 -0
  354. package/dist/web-ui/_app/immutable/chunks/70-t_QvE.js +1 -0
  355. package/dist/web-ui/_app/immutable/chunks/AiWQj974.js +1 -0
  356. package/dist/web-ui/_app/immutable/chunks/B25nWFyA.js +5 -0
  357. package/dist/web-ui/_app/immutable/chunks/B2bcA_Q_.js +1 -0
  358. package/dist/web-ui/_app/immutable/chunks/B5e5HYyB.js +1 -0
  359. package/dist/web-ui/_app/immutable/chunks/B7-5z6eA.js +1 -0
  360. package/dist/web-ui/_app/immutable/chunks/B7bGmhK0.js +1 -0
  361. package/dist/web-ui/_app/immutable/chunks/B8tYZKAE.js +1 -0
  362. package/dist/web-ui/_app/immutable/chunks/BFGAyJjD.js +1 -0
  363. package/dist/web-ui/_app/immutable/chunks/BG0850zf.js +1 -0
  364. package/dist/web-ui/_app/immutable/chunks/BG8eSzAd.js +1 -0
  365. package/dist/web-ui/_app/immutable/chunks/BIMxXS8I.js +1 -0
  366. package/dist/web-ui/_app/immutable/chunks/BSzL1fpU.js +1 -0
  367. package/dist/web-ui/_app/immutable/chunks/BYtjHfeq.js +1 -0
  368. package/dist/web-ui/_app/immutable/chunks/{D1ArdqNb.js → Bp5pFYXL.js} +1 -1
  369. package/dist/web-ui/_app/immutable/chunks/BsJFsuAT.js +1 -0
  370. package/dist/web-ui/_app/immutable/chunks/BvpNHcD6.js +1 -0
  371. package/dist/web-ui/_app/immutable/chunks/BypqA25-.js +1 -0
  372. package/dist/web-ui/_app/immutable/chunks/C0w6WDm5.js +1 -0
  373. package/dist/web-ui/_app/immutable/chunks/C5_PAZ0y.js +1 -0
  374. package/dist/web-ui/_app/immutable/chunks/CDRO15Iv.js +1 -0
  375. package/dist/web-ui/_app/immutable/chunks/CF1CoqD5.js +1 -0
  376. package/dist/web-ui/_app/immutable/chunks/CS2sa4_m.js +1 -0
  377. package/dist/web-ui/_app/immutable/chunks/CWUQwB9H.js +1 -0
  378. package/dist/web-ui/_app/immutable/chunks/CY5FDdSU.js +1 -0
  379. package/dist/web-ui/_app/immutable/chunks/C_7MTDoj.js +1 -0
  380. package/dist/web-ui/_app/immutable/chunks/CaAJD3dl.js +1 -0
  381. package/dist/web-ui/_app/immutable/chunks/{i-XnOIX0.js → ChB5iyEL.js} +1 -1
  382. package/dist/web-ui/_app/immutable/chunks/ChQD-6N8.js +1 -0
  383. package/dist/web-ui/_app/immutable/chunks/{BCkp8Hs8.js → CqbsoCwA.js} +1 -1
  384. package/dist/web-ui/_app/immutable/chunks/DCeJW50p.js +1 -0
  385. package/dist/web-ui/_app/immutable/chunks/DJtZNgcs.js +1 -0
  386. package/dist/web-ui/_app/immutable/chunks/DKIeaprD.js +1 -0
  387. package/dist/web-ui/_app/immutable/chunks/DLd2uVIA.js +1 -0
  388. package/dist/web-ui/_app/immutable/chunks/DW_subyT.js +2 -0
  389. package/dist/web-ui/_app/immutable/chunks/DbU6lVn0.js +1 -0
  390. package/dist/web-ui/_app/immutable/chunks/Dc7ZCC5m.js +1 -0
  391. package/dist/web-ui/_app/immutable/chunks/Dd5umPsk.js +2 -0
  392. package/dist/web-ui/_app/immutable/chunks/Dg_zDpDS.js +1 -0
  393. package/dist/web-ui/_app/immutable/chunks/Dgqu8Yuc.js +1 -0
  394. package/dist/web-ui/_app/immutable/chunks/DmxsPZTB.js +1 -0
  395. package/dist/web-ui/_app/immutable/chunks/DphTaFUB.js +1 -0
  396. package/dist/web-ui/_app/immutable/chunks/DqK4iHp0.js +1 -0
  397. package/dist/web-ui/_app/immutable/chunks/DqT6OH_u.js +2 -0
  398. package/dist/web-ui/_app/immutable/chunks/Ds9I9wQb.js +1 -0
  399. package/dist/web-ui/_app/immutable/chunks/Du5ng3u4.js +1 -0
  400. package/dist/web-ui/_app/immutable/chunks/DxJw79Wi.js +1 -0
  401. package/dist/web-ui/_app/immutable/chunks/GFTX8GgV.js +1 -0
  402. package/dist/web-ui/_app/immutable/chunks/HNjs76Zz.js +1 -0
  403. package/dist/web-ui/_app/immutable/chunks/HVMjDi4_.js +1 -0
  404. package/dist/web-ui/_app/immutable/chunks/P0A_fJvS.js +1 -0
  405. package/dist/web-ui/_app/immutable/chunks/T3vGWjIL.js +1 -0
  406. package/dist/web-ui/_app/immutable/chunks/VTmrX9Qu.js +1 -0
  407. package/dist/web-ui/_app/immutable/chunks/Xvwhx_F1.js +1 -0
  408. package/dist/web-ui/_app/immutable/chunks/Yyz1XMQA.js +1 -0
  409. package/dist/web-ui/_app/immutable/chunks/dh5HeqUr.js +1 -0
  410. package/dist/web-ui/_app/immutable/chunks/fZMteyca.js +62 -0
  411. package/dist/web-ui/_app/immutable/chunks/{D28BF5MJ.js → gPrj-hqC.js} +1 -1
  412. package/dist/web-ui/_app/immutable/chunks/htcWMiYN.js +1 -0
  413. package/dist/web-ui/_app/immutable/chunks/oTsvd9y4.js +1 -0
  414. package/dist/web-ui/_app/immutable/chunks/qJfLUwU4.js +1 -0
  415. package/dist/web-ui/_app/immutable/chunks/xCtiO_JE.js +1 -0
  416. package/dist/web-ui/_app/immutable/chunks/y4GeEH6k.js +1 -0
  417. package/dist/web-ui/_app/immutable/entry/app.C4h_eOn6.js +2 -0
  418. package/dist/web-ui/_app/immutable/entry/start.CQFTf9ep.js +1 -0
  419. package/dist/web-ui/_app/immutable/nodes/0.Dh1xO970.js +1 -0
  420. package/dist/web-ui/_app/immutable/nodes/1.l75D3Opx.js +1 -0
  421. package/dist/web-ui/_app/immutable/nodes/10.DBidBPc-.js +1 -0
  422. package/dist/web-ui/_app/immutable/nodes/11.Ab0gUKWe.js +1 -0
  423. package/dist/web-ui/_app/immutable/nodes/12.CMsnoxfs.js +1 -0
  424. package/dist/web-ui/_app/immutable/nodes/13.D8YKuknB.js +1 -0
  425. package/dist/web-ui/_app/immutable/nodes/14.DZ0aan7y.js +1 -0
  426. package/dist/web-ui/_app/immutable/nodes/15.CUIKreDL.js +2 -0
  427. package/dist/web-ui/_app/immutable/nodes/16.BWc8--BO.js +1 -0
  428. package/dist/web-ui/_app/immutable/nodes/2.CDUonbuh.js +1 -0
  429. package/dist/web-ui/_app/immutable/nodes/3.Ctg3M00i.js +1 -0
  430. package/dist/web-ui/_app/immutable/nodes/4.Ci-JDwbA.js +2 -0
  431. package/dist/web-ui/_app/immutable/nodes/5.CTyEDAq0.js +1 -0
  432. package/dist/web-ui/_app/immutable/nodes/6.BTZZqsAb.js +1 -0
  433. package/dist/web-ui/_app/immutable/nodes/7.BI52g_Jo.js +137 -0
  434. package/dist/web-ui/_app/immutable/nodes/8.3hZPaB9x.js +1 -0
  435. package/dist/web-ui/_app/immutable/nodes/9.DS49kvwl.js +29 -0
  436. package/dist/web-ui/_app/version.json +1 -1
  437. package/dist/web-ui/favicon-192.png +0 -0
  438. package/dist/web-ui/favicon-32.png +0 -0
  439. package/dist/web-ui/favicon.ico +0 -0
  440. package/dist/web-ui/index.html +14 -11
  441. package/package.json +14 -7
  442. package/plugin/.claude-plugin/marketplace.json +1 -1
  443. package/plugin/.claude-plugin/plugin.json +1 -1
  444. package/plugin/plugins/kspec/skills/merge/SKILL.md +127 -0
  445. package/plugin/plugins/kspec/skills/plan/SKILL.md +55 -26
  446. package/plugin/plugins/kspec/skills/review/SKILL.md +350 -133
  447. package/plugin/plugins/kspec/skills/task-work/SKILL.md +96 -106
  448. package/templates/agents-sections/04-pr-workflow.md +15 -12
  449. package/templates/agents-sections/06-ralph-loop.md +15 -10
  450. package/templates/skills/manifest.yaml +25 -7
  451. package/templates/skills/merge/SKILL.md +120 -0
  452. package/templates/skills/plan/SKILL.md +55 -26
  453. package/templates/skills/review/SKILL.md +346 -130
  454. package/templates/skills/task-work/SKILL.md +93 -103
  455. package/dist/web-ui/_app/immutable/assets/0.BxCxvrZR.css +0 -1
  456. package/dist/web-ui/_app/immutable/chunks/B-CZR0q8.js +0 -1
  457. package/dist/web-ui/_app/immutable/chunks/B1IR5Su5.js +0 -1
  458. package/dist/web-ui/_app/immutable/chunks/B_Cvvtc4.js +0 -1
  459. package/dist/web-ui/_app/immutable/chunks/BtFaGGII.js +0 -1
  460. package/dist/web-ui/_app/immutable/chunks/Bu8JVsCH.js +0 -1
  461. package/dist/web-ui/_app/immutable/chunks/C87u-CNA.js +0 -1
  462. package/dist/web-ui/_app/immutable/chunks/CrFkBTYp.js +0 -1
  463. package/dist/web-ui/_app/immutable/chunks/D6RtLpzL.js +0 -1
  464. package/dist/web-ui/_app/immutable/chunks/D7FHSgx2.js +0 -1
  465. package/dist/web-ui/_app/immutable/chunks/DBXrsxZQ.js +0 -2
  466. package/dist/web-ui/_app/immutable/chunks/Da_hHMuA.js +0 -1
  467. package/dist/web-ui/_app/immutable/chunks/Do6LchSF.js +0 -1
  468. package/dist/web-ui/_app/immutable/chunks/DoNPtcAw.js +0 -1
  469. package/dist/web-ui/_app/immutable/chunks/DtUbXRZz.js +0 -1
  470. package/dist/web-ui/_app/immutable/chunks/DyFPRlLl.js +0 -1
  471. package/dist/web-ui/_app/immutable/chunks/DzAP8lRM.js +0 -1
  472. package/dist/web-ui/_app/immutable/chunks/DzVXElzN.js +0 -2
  473. package/dist/web-ui/_app/immutable/chunks/aoPBFken.js +0 -1
  474. package/dist/web-ui/_app/immutable/chunks/laxtrUO3.js +0 -1
  475. package/dist/web-ui/_app/immutable/chunks/q1nIWgqB.js +0 -1
  476. package/dist/web-ui/_app/immutable/chunks/sTLbk5Nm.js +0 -1
  477. package/dist/web-ui/_app/immutable/chunks/vwKgQu5P.js +0 -5
  478. package/dist/web-ui/_app/immutable/entry/app.BCwMcqnT.js +0 -2
  479. package/dist/web-ui/_app/immutable/entry/start.wKCQH-tt.js +0 -1
  480. package/dist/web-ui/_app/immutable/nodes/0.CjGVMG74.js +0 -1
  481. package/dist/web-ui/_app/immutable/nodes/1.B6_AIPan.js +0 -1
  482. package/dist/web-ui/_app/immutable/nodes/2.q4oCS7Ws.js +0 -1
  483. package/dist/web-ui/_app/immutable/nodes/3.rTKZf9o2.js +0 -1
  484. package/dist/web-ui/_app/immutable/nodes/4.DVIDRu1d.js +0 -1
  485. package/dist/web-ui/_app/immutable/nodes/5.8PtPXIOd.js +0 -1
  486. package/dist/web-ui/_app/immutable/nodes/6.ZZrTemy_.js +0 -1
  487. package/dist/web-ui/_app/immutable/nodes/7.IP-gxCxi.js +0 -1
@@ -14,6 +14,9 @@
14
14
  * - ac-5: GET /api/tasks/:ref resolves via ReferenceIndex
15
15
  * - ac-6: POST /api/tasks/:ref/start transitions state
16
16
  * - ac-7: POST /api/tasks/:ref/note appends note
17
+ * - @ui-task-board ac-6: POST /api/tasks/:ref/submit transitions to pending_review
18
+ * - @ui-task-board ac-6: POST /api/tasks/:ref/complete transitions to completed
19
+ * - @ui-task-board ac-6: POST /api/tasks/:ref/block transitions to blocked
17
20
  */
18
21
 
19
22
  import { Elysia, t } from 'elysia';
@@ -21,6 +24,7 @@ import {
21
24
  initContext,
22
25
  loadAllTasks,
23
26
  loadAllItems,
27
+ loadPlans,
24
28
  ReferenceIndex,
25
29
  createNote,
26
30
  saveTask,
@@ -30,6 +34,8 @@ import {
30
34
  } from '../../parser/index.js';
31
35
  import { commitIfShadow } from '../../parser/shadow.js';
32
36
  import type { PubSubManager } from '../websocket/pubsub';
37
+ import { getRelatedSessionsForTask } from './session-related.js';
38
+ import { resolveRefTitle, resolveRefEntries } from './ref-resolution.js';
33
39
 
34
40
  interface TasksRouteOptions {
35
41
  pubsub: PubSubManager;
@@ -72,6 +78,31 @@ export function createTasksRoutes(options: TasksRouteOptions) {
72
78
  );
73
79
  }
74
80
 
81
+ // Automation filter — filter by automation eligibility status
82
+ if (query.automation) {
83
+ filtered = filtered.filter((task) => task.automation === query.automation);
84
+ }
85
+
86
+ // Plan filter — show only tasks derived from a given plan
87
+ if (query.plan) {
88
+ const plans = await loadPlans(ctx);
89
+ const plan = plans.find(
90
+ (p) => p._ulid === query.plan || p.slugs.includes(query.plan!)
91
+ );
92
+ if (plan) {
93
+ const derivedRefs = new Set(
94
+ plan.derived_tasks.map((r) => (r.startsWith('@') ? r.slice(1) : r))
95
+ );
96
+ filtered = filtered.filter(
97
+ (task) =>
98
+ derivedRefs.has(task._ulid) ||
99
+ task.slugs.some((s) => derivedRefs.has(s))
100
+ );
101
+ } else {
102
+ filtered = [];
103
+ }
104
+ }
105
+
75
106
  // AC: @api-contract ac-4 - Pagination
76
107
  const total = filtered.length;
77
108
  const offset = Number(query.offset) || 0;
@@ -81,16 +112,20 @@ export function createTasksRoutes(options: TasksRouteOptions) {
81
112
 
82
113
  // AC: @api-contract ac-2 - Return with status, priority, spec_ref, notes count
83
114
  // AC: @web-dashboard ac-1 - Include depends_on for blocked task computation
115
+ // AC: @ui-api-ref-resolution ac-1 - Include spec_title resolved server-side
84
116
  const items = paginated.map((task) => ({
85
117
  _ulid: task._ulid,
86
118
  slugs: task.slugs,
87
119
  title: task.title,
120
+ type: task.type || 'task',
88
121
  status: task.status,
89
122
  priority: task.priority,
90
123
  spec_ref: task.spec_ref,
124
+ spec_title: resolveRefTitle(index, task.spec_ref),
91
125
  meta_ref: task.meta_ref,
92
126
  tags: task.tags,
93
127
  depends_on: task.depends_on || [],
128
+ automation: task.automation,
94
129
  notes_count: task.notes?.length || 0,
95
130
  todos_count: task.todos?.length || 0,
96
131
  started_at: task.started_at,
@@ -111,6 +146,8 @@ export function createTasksRoutes(options: TasksRouteOptions) {
111
146
  status: t.Optional(t.Union([t.String(), t.Array(t.String())])),
112
147
  type: t.Optional(t.Union([t.String(), t.Array(t.String())])),
113
148
  tag: t.Optional(t.Union([t.String(), t.Array(t.String())])),
149
+ automation: t.Optional(t.String()),
150
+ plan: t.Optional(t.String()),
114
151
  limit: t.Optional(t.String()),
115
152
  offset: t.Optional(t.String()),
116
153
  }),
@@ -125,7 +162,8 @@ export function createTasksRoutes(options: TasksRouteOptions) {
125
162
  const ctx = await initContext(projectContext.path);
126
163
  const tasks = await loadAllTasks(ctx);
127
164
  const items = await loadAllItems(ctx);
128
- const index = new ReferenceIndex(tasks, items);
165
+ const plans = await loadPlans(ctx);
166
+ const index = new ReferenceIndex(tasks, items, [], plans);
129
167
 
130
168
  // AC: @api-contract ac-5, @trait-api-endpoint ac-2 - Resolve ref via ReferenceIndex
131
169
  const result = index.resolve(params.ref);
@@ -150,19 +188,36 @@ export function createTasksRoutes(options: TasksRouteOptions) {
150
188
  }
151
189
 
152
190
  // AC: @api-contract ac-5 - Return full task with notes, todos, dependencies
191
+ // AC: @ui-task-board ac-3 - Include type, description, blocked_by, vcs_refs, plan_ref, session_ref
192
+ // AC: @ui-api-ref-resolution ac-1, ac-2 - Include resolved titles for refs
153
193
  return {
154
194
  _ulid: task._ulid,
155
195
  slugs: task.slugs,
156
196
  title: task.title,
197
+ type: task.type || 'task',
157
198
  status: task.status,
158
199
  priority: task.priority,
159
200
  spec_ref: task.spec_ref,
201
+ spec_title: resolveRefTitle(index, task.spec_ref),
160
202
  meta_ref: task.meta_ref,
161
203
  tags: task.tags,
162
204
  description: task.description,
205
+ derivation: task.derivation,
163
206
  depends_on: task.depends_on,
207
+ resolved_depends_on: resolveRefEntries(index, task.depends_on),
208
+ blocked_by: task.blocked_by || [],
209
+ resolved_blocked_by: resolveRefEntries(index, task.blocked_by),
210
+ context: task.context || [],
211
+ vcs_refs: (task.vcs_refs || []).map((v) =>
212
+ typeof v === 'string' ? v : v.type ? `${v.type}:${v.ref}` : v.ref
213
+ ),
214
+ plan_ref: task.plan_ref,
215
+ plan_title: resolveRefTitle(index, task.plan_ref),
216
+ session_ref: task.session_id,
164
217
  notes: task.notes,
218
+ notes_count: task.notes?.length || 0,
165
219
  todos: task.todos,
220
+ todos_count: task.todos?.length || 0,
166
221
  started_at: task.started_at,
167
222
  completed_at: task.completed_at,
168
223
  cancelled_at: task.cancelled_at,
@@ -178,6 +233,37 @@ export function createTasksRoutes(options: TasksRouteOptions) {
178
233
  }
179
234
  )
180
235
 
236
+ .get(
237
+ '/:ref/sessions',
238
+ async ({ params, error: errorResponse, projectContext }) => {
239
+ const ctx = await initContext(projectContext.path);
240
+ const tasks = await loadAllTasks(ctx);
241
+ const items = await loadAllItems(ctx);
242
+ const result = await getRelatedSessionsForTask({
243
+ taskRef: params.ref,
244
+ tasks,
245
+ items,
246
+ sessionsDir: ctx.sessionsDir,
247
+ });
248
+
249
+ if ('error' in result) {
250
+ return errorResponse(404, result.error);
251
+ }
252
+
253
+ return {
254
+ items: result.sessions,
255
+ total: result.sessions.length,
256
+ offset: 0,
257
+ limit: result.sessions.length,
258
+ };
259
+ },
260
+ {
261
+ params: t.Object({
262
+ ref: t.String(),
263
+ }),
264
+ }
265
+ )
266
+
181
267
  // AC: @api-contract ac-6 - Start task
182
268
  .post(
183
269
  '/:ref/start',
@@ -229,12 +315,15 @@ export function createTasksRoutes(options: TasksRouteOptions) {
229
315
  await commitIfShadow(ctx.shadow, `task: start ${params.ref}`);
230
316
 
231
317
  // AC: @api-contract ac-6, @trait-api-endpoint ac-5 - WebSocket broadcast
318
+ // AC: @ui-api-aggregation ac-4 - Include title and old/new status
232
319
  // AC: @multi-directory-daemon ac-18 - Broadcast scoped to request project
233
320
  pubsub.broadcast('tasks:updates', 'task_updated', {
234
321
  ref: params.ref,
235
322
  ulid: task._ulid,
236
323
  action: 'start',
237
- status: 'in_progress',
324
+ title: task.title,
325
+ old_status: task.status,
326
+ new_status: 'in_progress',
238
327
  }, projectContext.path);
239
328
 
240
329
  // AC: @api-contract ac-6 - Return updated task
@@ -301,11 +390,15 @@ export function createTasksRoutes(options: TasksRouteOptions) {
301
390
  await commitIfShadow(ctx.shadow, `task: add note to ${params.ref}`);
302
391
 
303
392
  // AC: @api-contract ac-7 - WebSocket broadcast
393
+ // AC: @ui-api-aggregation ac-4 - Include title (no status change for notes)
304
394
  // AC: @multi-directory-daemon ac-18 - Broadcast scoped to request project
305
395
  pubsub.broadcast('tasks:updates', 'task_updated', {
306
396
  ref: params.ref,
307
397
  ulid: task._ulid,
308
398
  action: 'note_added',
399
+ title: task.title,
400
+ old_status: null,
401
+ new_status: null,
309
402
  note_ulid: note._ulid,
310
403
  }, projectContext.path);
311
404
 
@@ -323,5 +416,167 @@ export function createTasksRoutes(options: TasksRouteOptions) {
323
416
  content: t.String(),
324
417
  }),
325
418
  }
419
+ )
420
+
421
+ // AC: @ui-task-board ac-6 - Submit task for review
422
+ .post(
423
+ '/:ref/submit',
424
+ async ({ params, error: errorResponse, projectContext }) => {
425
+ const ctx = await initContext(projectContext.path);
426
+ const tasks = await loadAllTasks(ctx);
427
+ const items = await loadAllItems(ctx);
428
+ const index = new ReferenceIndex(tasks, items);
429
+
430
+ const result = index.resolve(params.ref);
431
+ if (!result.ok) {
432
+ return errorResponse(404, {
433
+ error: 'not_found',
434
+ message: `Task reference "${params.ref}" not found`,
435
+ });
436
+ }
437
+
438
+ const task = tasks.find((t) => t._ulid === result.ulid);
439
+ if (!task) {
440
+ return errorResponse(404, {
441
+ error: 'not_found',
442
+ message: `Reference "${params.ref}" is not a task`,
443
+ });
444
+ }
445
+
446
+ if (task.status !== 'in_progress' && task.status !== 'needs_work') {
447
+ return errorResponse(409, {
448
+ error: 'invalid_transition',
449
+ message: `Cannot submit task with status "${task.status}". Must be in_progress or needs_work.`,
450
+ current: task.status,
451
+ valid_transitions: ['pending_review'],
452
+ });
453
+ }
454
+
455
+ const updatedTask: LoadedTask = { ...task, status: 'pending_review' };
456
+ await saveTask(ctx, updatedTask);
457
+ await syncSpecImplementationStatus(ctx, updatedTask, tasks, items, index);
458
+ await commitIfShadow(ctx.shadow, `task: submit ${params.ref}`);
459
+
460
+ // AC: @ui-api-aggregation ac-4 - Include title and old/new status
461
+ pubsub.broadcast('tasks:updates', 'task_updated', {
462
+ ref: params.ref,
463
+ ulid: task._ulid,
464
+ action: 'submit',
465
+ title: task.title,
466
+ old_status: task.status,
467
+ new_status: 'pending_review',
468
+ }, projectContext.path);
469
+
470
+ return updatedTask;
471
+ },
472
+ { params: t.Object({ ref: t.String() }) }
473
+ )
474
+
475
+ // AC: @ui-task-board ac-6 - Complete task
476
+ .post(
477
+ '/:ref/complete',
478
+ async ({ params, body, error: errorResponse, projectContext }) => {
479
+ const ctx = await initContext(projectContext.path);
480
+ const tasks = await loadAllTasks(ctx);
481
+ const items = await loadAllItems(ctx);
482
+ const index = new ReferenceIndex(tasks, items);
483
+
484
+ const result = index.resolve(params.ref);
485
+ if (!result.ok) {
486
+ return errorResponse(404, {
487
+ error: 'not_found',
488
+ message: `Task reference "${params.ref}" not found`,
489
+ });
490
+ }
491
+
492
+ const task = tasks.find((t) => t._ulid === result.ulid);
493
+ if (!task) {
494
+ return errorResponse(404, {
495
+ error: 'not_found',
496
+ message: `Reference "${params.ref}" is not a task`,
497
+ });
498
+ }
499
+
500
+ const updatedTask: LoadedTask = {
501
+ ...task,
502
+ status: 'completed',
503
+ completed_at: new Date().toISOString(),
504
+ closed_reason: body.reason,
505
+ };
506
+ await saveTask(ctx, updatedTask);
507
+ await syncSpecImplementationStatus(ctx, updatedTask, tasks, items, index);
508
+ await commitIfShadow(ctx.shadow, `task: complete ${params.ref}`);
509
+
510
+ // AC: @ui-api-aggregation ac-4 - Include title and old/new status
511
+ pubsub.broadcast('tasks:updates', 'task_updated', {
512
+ ref: params.ref,
513
+ ulid: task._ulid,
514
+ action: 'complete',
515
+ title: task.title,
516
+ old_status: task.status,
517
+ new_status: 'completed',
518
+ }, projectContext.path);
519
+
520
+ return updatedTask;
521
+ },
522
+ {
523
+ params: t.Object({ ref: t.String() }),
524
+ body: t.Object({ reason: t.String() }),
525
+ }
526
+ )
527
+
528
+ // AC: @ui-task-board ac-6 - Block task
529
+ .post(
530
+ '/:ref/block',
531
+ async ({ params, body, error: errorResponse, projectContext }) => {
532
+ const ctx = await initContext(projectContext.path);
533
+ const tasks = await loadAllTasks(ctx);
534
+ const items = await loadAllItems(ctx);
535
+ const index = new ReferenceIndex(tasks, items);
536
+
537
+ const result = index.resolve(params.ref);
538
+ if (!result.ok) {
539
+ return errorResponse(404, {
540
+ error: 'not_found',
541
+ message: `Task reference "${params.ref}" not found`,
542
+ });
543
+ }
544
+
545
+ const task = tasks.find((t) => t._ulid === result.ulid);
546
+ if (!task) {
547
+ return errorResponse(404, {
548
+ error: 'not_found',
549
+ message: `Reference "${params.ref}" is not a task`,
550
+ });
551
+ }
552
+
553
+ const author = getAuthor(ctx.config?.identity?.author);
554
+ const note = createNote(`Blocked: ${body.reason}`, author);
555
+
556
+ const updatedTask: LoadedTask = {
557
+ ...task,
558
+ status: 'blocked',
559
+ notes: [...(task.notes || []), note],
560
+ };
561
+ await saveTask(ctx, updatedTask);
562
+ await syncSpecImplementationStatus(ctx, updatedTask, tasks, items, index);
563
+ await commitIfShadow(ctx.shadow, `task: block ${params.ref}`);
564
+
565
+ // AC: @ui-api-aggregation ac-4 - Include title and old/new status
566
+ pubsub.broadcast('tasks:updates', 'task_updated', {
567
+ ref: params.ref,
568
+ ulid: task._ulid,
569
+ action: 'block',
570
+ title: task.title,
571
+ old_status: task.status,
572
+ new_status: 'blocked',
573
+ }, projectContext.path);
574
+
575
+ return updatedTask;
576
+ },
577
+ {
578
+ params: t.Object({ ref: t.String() }),
579
+ body: t.Object({ reason: t.String() }),
580
+ }
326
581
  );
327
582
  }
@@ -25,6 +25,9 @@ import { Elysia, t } from 'elysia';
25
25
  import { ulid } from 'ulidx';
26
26
  import {
27
27
  initContext,
28
+ loadAllTasks,
29
+ loadAllItems,
30
+ ReferenceIndex,
28
31
  loadTriageRecords,
29
32
  saveTriageRecord,
30
33
  findTriageRecordByRef,
@@ -34,6 +37,7 @@ import {
34
37
  getAuthor,
35
38
  type LoadedTriageRecord,
36
39
  } from '../../parser/index.js';
40
+ import { resolveRefEntries } from './ref-resolution.js';
37
41
  import { commitIfShadow } from '../../parser/shadow.js';
38
42
  import { normalizeRefInput } from '../../schema/index.js';
39
43
  import type { TriageAction } from '../../schema/index.js';
@@ -87,8 +91,27 @@ export function createTriageRoutes(options: TriageRouteOptions) {
87
91
 
88
92
  const paginated = filtered.slice(offset, offset + limit);
89
93
 
94
+ // AC: @ui-api-ref-resolution ac-2 - Resolve evidence_refs titles
95
+ const hasEvidenceRefs = paginated.some((r) => r.evidence_refs?.length > 0);
96
+ let refIndex: ReferenceIndex | null = null;
97
+ if (hasEvidenceRefs) {
98
+ try {
99
+ const tasks = await loadAllTasks(ctx);
100
+ const items = await loadAllItems(ctx);
101
+ refIndex = new ReferenceIndex(tasks, items);
102
+ } catch {
103
+ // Non-critical
104
+ }
105
+ }
106
+ const enriched = refIndex
107
+ ? paginated.map((r) => ({
108
+ ...r,
109
+ resolved_evidence_refs: resolveRefEntries(refIndex!, r.evidence_refs),
110
+ }))
111
+ : paginated;
112
+
90
113
  return {
91
- items: paginated,
114
+ items: enriched,
92
115
  total,
93
116
  offset,
94
117
  limit,
@@ -223,6 +246,7 @@ export function createTriageRoutes(options: TriageRouteOptions) {
223
246
  )
224
247
 
225
248
  // GET single triage record
249
+ // AC: @ui-api-ref-resolution ac-2 - Resolve evidence_refs titles
226
250
  .get(
227
251
  '/:ref',
228
252
  async ({ params, error: errorResponse, projectContext }) => {
@@ -240,6 +264,21 @@ export function createTriageRoutes(options: TriageRouteOptions) {
240
264
  });
241
265
  }
242
266
 
267
+ // AC: @ui-api-ref-resolution ac-2 - Resolve evidence_refs
268
+ if (record.evidence_refs?.length > 0) {
269
+ try {
270
+ const tasks = await loadAllTasks(ctx);
271
+ const items = await loadAllItems(ctx);
272
+ const refIndex = new ReferenceIndex(tasks, items);
273
+ return {
274
+ ...record,
275
+ resolved_evidence_refs: resolveRefEntries(refIndex, record.evidence_refs),
276
+ };
277
+ } catch {
278
+ // Non-critical
279
+ }
280
+ }
281
+
243
282
  return record;
244
283
  },
245
284
  {
@@ -218,7 +218,7 @@ export function createValidationRoutes(options: ValidationRouteOptions = {}) {
218
218
  refWarnings: result.refWarnings,
219
219
  orphans: result.orphans,
220
220
  completenessWarnings: result.completenessWarnings,
221
- traitCycles: result.traitCycles,
221
+ traitCycles: result.traitCycleErrors,
222
222
  };
223
223
  })
224
224