@bosun-sh/logbook 1.1.0 → 2.0.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 (457) hide show
  1. package/CHANGELOG.md +139 -0
  2. package/README.md +248 -318
  3. package/bin/logbook.cjs +18 -0
  4. package/dist/context/attachments.d.ts +55 -0
  5. package/dist/context/attachments.d.ts.map +1 -0
  6. package/dist/context/attachments.js +329 -0
  7. package/dist/context/attachments.js.map +1 -0
  8. package/dist/context/create.d.ts +31 -0
  9. package/dist/context/create.d.ts.map +1 -0
  10. package/dist/context/create.js +101 -0
  11. package/dist/context/create.js.map +1 -0
  12. package/dist/context/delete.d.ts +20 -0
  13. package/dist/context/delete.d.ts.map +1 -0
  14. package/dist/context/delete.js +55 -0
  15. package/dist/context/delete.js.map +1 -0
  16. package/dist/context/get.d.ts +20 -0
  17. package/dist/context/get.d.ts.map +1 -0
  18. package/dist/context/get.js +55 -0
  19. package/dist/context/get.js.map +1 -0
  20. package/dist/context/list.d.ts +30 -0
  21. package/dist/context/list.d.ts.map +1 -0
  22. package/dist/context/list.js +172 -0
  23. package/dist/context/list.js.map +1 -0
  24. package/dist/context/schema.d.ts +156 -0
  25. package/dist/context/schema.d.ts.map +1 -0
  26. package/dist/context/schema.js +34 -0
  27. package/dist/context/schema.js.map +1 -0
  28. package/dist/context/search.d.ts +27 -0
  29. package/dist/context/search.d.ts.map +1 -0
  30. package/dist/context/search.js +266 -0
  31. package/dist/context/search.js.map +1 -0
  32. package/dist/context/topics.d.ts +4 -0
  33. package/dist/context/topics.d.ts.map +1 -0
  34. package/dist/context/topics.js +54 -0
  35. package/dist/context/topics.js.map +1 -0
  36. package/dist/context/update.d.ts +29 -0
  37. package/dist/context/update.d.ts.map +1 -0
  38. package/dist/context/update.js +134 -0
  39. package/dist/context/update.js.map +1 -0
  40. package/dist/epic/cascade-delete.d.ts +30 -0
  41. package/dist/epic/cascade-delete.d.ts.map +1 -0
  42. package/dist/epic/cascade-delete.js +173 -0
  43. package/dist/epic/cascade-delete.js.map +1 -0
  44. package/dist/epic/create.d.ts +24 -0
  45. package/dist/epic/create.d.ts.map +1 -0
  46. package/dist/epic/create.js +54 -0
  47. package/dist/epic/create.js.map +1 -0
  48. package/dist/epic/delete.d.ts +21 -0
  49. package/dist/epic/delete.d.ts.map +1 -0
  50. package/dist/epic/delete.js +42 -0
  51. package/dist/epic/delete.js.map +1 -0
  52. package/dist/epic/get.d.ts +19 -0
  53. package/dist/epic/get.d.ts.map +1 -0
  54. package/dist/epic/get.js +31 -0
  55. package/dist/epic/get.js.map +1 -0
  56. package/dist/epic/list.d.ts +25 -0
  57. package/dist/epic/list.d.ts.map +1 -0
  58. package/dist/epic/list.js +114 -0
  59. package/dist/epic/list.js.map +1 -0
  60. package/dist/epic/rules.d.ts +34 -0
  61. package/dist/epic/rules.d.ts.map +1 -0
  62. package/dist/epic/rules.js +127 -0
  63. package/dist/epic/rules.js.map +1 -0
  64. package/dist/epic/schema.d.ts +85 -0
  65. package/dist/epic/schema.d.ts.map +1 -0
  66. package/dist/epic/schema.js +14 -0
  67. package/dist/epic/schema.js.map +1 -0
  68. package/dist/epic/update.d.ts +25 -0
  69. package/dist/epic/update.d.ts.map +1 -0
  70. package/dist/epic/update.js +69 -0
  71. package/dist/epic/update.js.map +1 -0
  72. package/dist/hook/list.d.ts +71 -0
  73. package/dist/hook/list.d.ts.map +1 -0
  74. package/dist/hook/list.js +364 -0
  75. package/dist/hook/list.js.map +1 -0
  76. package/dist/hook/ports.d.ts +16 -0
  77. package/dist/hook/ports.d.ts.map +1 -0
  78. package/dist/hook/ports.js +3 -0
  79. package/dist/hook/ports.js.map +1 -0
  80. package/dist/hook/run.d.ts +24 -0
  81. package/dist/hook/run.d.ts.map +1 -0
  82. package/dist/hook/run.js +185 -0
  83. package/dist/hook/run.js.map +1 -0
  84. package/dist/index.d.ts +31 -0
  85. package/dist/index.d.ts.map +1 -0
  86. package/dist/index.js +31 -0
  87. package/dist/index.js.map +1 -0
  88. package/dist/plugin/hook-tools.d.ts +8 -0
  89. package/dist/plugin/hook-tools.d.ts.map +1 -0
  90. package/dist/plugin/hook-tools.js +31 -0
  91. package/dist/plugin/hook-tools.js.map +1 -0
  92. package/dist/plugin/linear-pull-tool.d.ts +20 -0
  93. package/dist/plugin/linear-pull-tool.d.ts.map +1 -0
  94. package/dist/plugin/linear-pull-tool.js +19 -0
  95. package/dist/plugin/linear-pull-tool.js.map +1 -0
  96. package/dist/plugin/linear-push-tool.d.ts +20 -0
  97. package/dist/plugin/linear-push-tool.d.ts.map +1 -0
  98. package/dist/plugin/linear-push-tool.js +27 -0
  99. package/dist/plugin/linear-push-tool.js.map +1 -0
  100. package/dist/plugin/linear-setup-tool.d.ts +2 -0
  101. package/dist/plugin/linear-setup-tool.d.ts.map +1 -0
  102. package/dist/plugin/linear-setup-tool.js +22 -0
  103. package/dist/plugin/linear-setup-tool.js.map +1 -0
  104. package/dist/plugin/linear-status-tool.d.ts +10 -0
  105. package/dist/plugin/linear-status-tool.d.ts.map +1 -0
  106. package/dist/plugin/linear-status-tool.js +10 -0
  107. package/dist/plugin/linear-status-tool.js.map +1 -0
  108. package/dist/plugin/list.d.ts +15 -0
  109. package/dist/plugin/list.d.ts.map +1 -0
  110. package/dist/plugin/list.js +87 -0
  111. package/dist/plugin/list.js.map +1 -0
  112. package/dist/plugin/public-schemas.d.ts +42 -0
  113. package/dist/plugin/public-schemas.d.ts.map +1 -0
  114. package/dist/plugin/public-schemas.js +577 -0
  115. package/dist/plugin/public-schemas.js.map +1 -0
  116. package/dist/plugin/registry.d.ts +3 -0
  117. package/dist/plugin/registry.d.ts.map +1 -0
  118. package/dist/plugin/registry.js +3 -0
  119. package/dist/plugin/registry.js.map +1 -0
  120. package/dist/plugin/results.d.ts +8 -0
  121. package/dist/plugin/results.d.ts.map +1 -0
  122. package/dist/plugin/results.js +114 -0
  123. package/dist/plugin/results.js.map +1 -0
  124. package/dist/plugin/sync-conflict-tools.d.ts +2 -0
  125. package/dist/plugin/sync-conflict-tools.d.ts.map +1 -0
  126. package/dist/plugin/sync-conflict-tools.js +5 -0
  127. package/dist/plugin/sync-conflict-tools.js.map +1 -0
  128. package/dist/plugin/tool-registry.d.ts +23 -0
  129. package/dist/plugin/tool-registry.d.ts.map +1 -0
  130. package/dist/plugin/tool-registry.js +251 -0
  131. package/dist/plugin/tool-registry.js.map +1 -0
  132. package/dist/plugin/workspace-init-tool.d.ts +2 -0
  133. package/dist/plugin/workspace-init-tool.d.ts.map +1 -0
  134. package/dist/plugin/workspace-init-tool.js +16 -0
  135. package/dist/plugin/workspace-init-tool.js.map +1 -0
  136. package/dist/plugin/workspace-status-tool.d.ts +2 -0
  137. package/dist/plugin/workspace-status-tool.d.ts.map +1 -0
  138. package/dist/plugin/workspace-status-tool.js +15 -0
  139. package/dist/plugin/workspace-status-tool.js.map +1 -0
  140. package/dist/shared/ids.d.ts +3 -0
  141. package/dist/shared/ids.d.ts.map +1 -0
  142. package/dist/shared/ids.js +15 -0
  143. package/dist/shared/ids.js.map +1 -0
  144. package/dist/shared/pagination.d.ts +19 -0
  145. package/dist/shared/pagination.d.ts.map +1 -0
  146. package/dist/shared/pagination.js +110 -0
  147. package/dist/shared/pagination.js.map +1 -0
  148. package/dist/shared/result.d.ts +20 -0
  149. package/dist/shared/result.d.ts.map +1 -0
  150. package/dist/shared/result.js +6 -0
  151. package/dist/shared/result.js.map +1 -0
  152. package/dist/shared/schema/value-objects.d.ts +363 -0
  153. package/dist/shared/schema/value-objects.d.ts.map +1 -0
  154. package/dist/shared/schema/value-objects.js +112 -0
  155. package/dist/shared/schema/value-objects.js.map +1 -0
  156. package/dist/shared/storage/atomic-write.d.ts +25 -0
  157. package/dist/shared/storage/atomic-write.d.ts.map +1 -0
  158. package/dist/shared/storage/atomic-write.js +71 -0
  159. package/dist/shared/storage/atomic-write.js.map +1 -0
  160. package/dist/shared/storage/jsonl-repository.d.ts +85 -0
  161. package/dist/shared/storage/jsonl-repository.d.ts.map +1 -0
  162. package/dist/shared/storage/jsonl-repository.js +278 -0
  163. package/dist/shared/storage/jsonl-repository.js.map +1 -0
  164. package/dist/shared/storage/transaction.d.ts +3 -0
  165. package/dist/shared/storage/transaction.d.ts.map +1 -0
  166. package/dist/shared/storage/transaction.js +22 -0
  167. package/dist/shared/storage/transaction.js.map +1 -0
  168. package/dist/shared/time.d.ts +3 -0
  169. package/dist/shared/time.d.ts.map +1 -0
  170. package/dist/shared/time.js +3 -0
  171. package/dist/shared/time.js.map +1 -0
  172. package/dist/story/cascade-delete.d.ts +22 -0
  173. package/dist/story/cascade-delete.d.ts.map +1 -0
  174. package/dist/story/cascade-delete.js +117 -0
  175. package/dist/story/cascade-delete.js.map +1 -0
  176. package/dist/story/create.d.ts +30 -0
  177. package/dist/story/create.d.ts.map +1 -0
  178. package/dist/story/create.js +69 -0
  179. package/dist/story/create.js.map +1 -0
  180. package/dist/story/delete.d.ts +21 -0
  181. package/dist/story/delete.d.ts.map +1 -0
  182. package/dist/story/delete.js +42 -0
  183. package/dist/story/delete.js.map +1 -0
  184. package/dist/story/get.d.ts +19 -0
  185. package/dist/story/get.d.ts.map +1 -0
  186. package/dist/story/get.js +31 -0
  187. package/dist/story/get.js.map +1 -0
  188. package/dist/story/hierarchy.d.ts +20 -0
  189. package/dist/story/hierarchy.d.ts.map +1 -0
  190. package/dist/story/hierarchy.js +30 -0
  191. package/dist/story/hierarchy.js.map +1 -0
  192. package/dist/story/list.d.ts +25 -0
  193. package/dist/story/list.d.ts.map +1 -0
  194. package/dist/story/list.js +118 -0
  195. package/dist/story/list.js.map +1 -0
  196. package/dist/story/rules.d.ts +34 -0
  197. package/dist/story/rules.d.ts.map +1 -0
  198. package/dist/story/rules.js +100 -0
  199. package/dist/story/rules.js.map +1 -0
  200. package/dist/story/schema.d.ts +65 -0
  201. package/dist/story/schema.d.ts.map +1 -0
  202. package/dist/story/schema.js +14 -0
  203. package/dist/story/schema.js.map +1 -0
  204. package/dist/story/update.d.ts +23 -0
  205. package/dist/story/update.d.ts.map +1 -0
  206. package/dist/story/update.js +67 -0
  207. package/dist/story/update.js.map +1 -0
  208. package/dist/sync/base-snapshot.d.ts +38 -0
  209. package/dist/sync/base-snapshot.d.ts.map +1 -0
  210. package/dist/sync/base-snapshot.js +86 -0
  211. package/dist/sync/base-snapshot.js.map +1 -0
  212. package/dist/sync/conflict-tools.d.ts +75 -0
  213. package/dist/sync/conflict-tools.d.ts.map +1 -0
  214. package/dist/sync/conflict-tools.js +53 -0
  215. package/dist/sync/conflict-tools.js.map +1 -0
  216. package/dist/sync/conflicts.d.ts +201 -0
  217. package/dist/sync/conflicts.d.ts.map +1 -0
  218. package/dist/sync/conflicts.js +526 -0
  219. package/dist/sync/conflicts.js.map +1 -0
  220. package/dist/sync/deferred-providers.d.ts +2 -0
  221. package/dist/sync/deferred-providers.d.ts.map +1 -0
  222. package/dist/sync/deferred-providers.js +6 -0
  223. package/dist/sync/deferred-providers.js.map +1 -0
  224. package/dist/sync/events.d.ts +401 -0
  225. package/dist/sync/events.d.ts.map +1 -0
  226. package/dist/sync/events.js +357 -0
  227. package/dist/sync/events.js.map +1 -0
  228. package/dist/sync/external-links.d.ts +154 -0
  229. package/dist/sync/external-links.d.ts.map +1 -0
  230. package/dist/sync/external-links.js +306 -0
  231. package/dist/sync/external-links.js.map +1 -0
  232. package/dist/sync/linear/config.d.ts +60 -0
  233. package/dist/sync/linear/config.d.ts.map +1 -0
  234. package/dist/sync/linear/config.js +302 -0
  235. package/dist/sync/linear/config.js.map +1 -0
  236. package/dist/sync/linear/mapping.d.ts +115 -0
  237. package/dist/sync/linear/mapping.d.ts.map +1 -0
  238. package/dist/sync/linear/mapping.js +159 -0
  239. package/dist/sync/linear/mapping.js.map +1 -0
  240. package/dist/sync/linear/pull.d.ts +33 -0
  241. package/dist/sync/linear/pull.d.ts.map +1 -0
  242. package/dist/sync/linear/pull.js +376 -0
  243. package/dist/sync/linear/pull.js.map +1 -0
  244. package/dist/sync/linear/push.d.ts +34 -0
  245. package/dist/sync/linear/push.d.ts.map +1 -0
  246. package/dist/sync/linear/push.js +681 -0
  247. package/dist/sync/linear/push.js.map +1 -0
  248. package/dist/sync/linear/setup.d.ts +33 -0
  249. package/dist/sync/linear/setup.d.ts.map +1 -0
  250. package/dist/sync/linear/setup.js +129 -0
  251. package/dist/sync/linear/setup.js.map +1 -0
  252. package/dist/sync/linear/status.d.ts +35 -0
  253. package/dist/sync/linear/status.d.ts.map +1 -0
  254. package/dist/sync/linear/status.js +138 -0
  255. package/dist/sync/linear/status.js.map +1 -0
  256. package/dist/sync/linear/transport.d.ts +47 -0
  257. package/dist/sync/linear/transport.d.ts.map +1 -0
  258. package/dist/sync/linear/transport.js +249 -0
  259. package/dist/sync/linear/transport.js.map +1 -0
  260. package/dist/sync/provider-port.d.ts +81 -0
  261. package/dist/sync/provider-port.d.ts.map +1 -0
  262. package/dist/sync/provider-port.js +16 -0
  263. package/dist/sync/provider-port.js.map +1 -0
  264. package/dist/sync/provider-registry.d.ts +38 -0
  265. package/dist/sync/provider-registry.d.ts.map +1 -0
  266. package/dist/sync/provider-registry.js +115 -0
  267. package/dist/sync/provider-registry.js.map +1 -0
  268. package/dist/sync/schema.d.ts +147 -0
  269. package/dist/sync/schema.d.ts.map +1 -0
  270. package/dist/sync/schema.js +28 -0
  271. package/dist/sync/schema.js.map +1 -0
  272. package/dist/task/comments.d.ts +9 -0
  273. package/dist/task/comments.d.ts.map +1 -0
  274. package/dist/task/comments.js +79 -0
  275. package/dist/task/comments.js.map +1 -0
  276. package/dist/task/create.d.ts +34 -0
  277. package/dist/task/create.d.ts.map +1 -0
  278. package/dist/task/create.js +126 -0
  279. package/dist/task/create.js.map +1 -0
  280. package/dist/task/current.d.ts +18 -0
  281. package/dist/task/current.d.ts.map +1 -0
  282. package/dist/task/current.js +105 -0
  283. package/dist/task/current.js.map +1 -0
  284. package/dist/task/edit.d.ts +22 -0
  285. package/dist/task/edit.d.ts.map +1 -0
  286. package/dist/task/edit.js +105 -0
  287. package/dist/task/edit.js.map +1 -0
  288. package/dist/task/estimate.d.ts +20 -0
  289. package/dist/task/estimate.d.ts.map +1 -0
  290. package/dist/task/estimate.js +141 -0
  291. package/dist/task/estimate.js.map +1 -0
  292. package/dist/task/get.d.ts +13 -0
  293. package/dist/task/get.d.ts.map +1 -0
  294. package/dist/task/get.js +29 -0
  295. package/dist/task/get.js.map +1 -0
  296. package/dist/task/hierarchy.d.ts +18 -0
  297. package/dist/task/hierarchy.d.ts.map +1 -0
  298. package/dist/task/hierarchy.js +56 -0
  299. package/dist/task/hierarchy.js.map +1 -0
  300. package/dist/task/lifecycle.d.ts +14 -0
  301. package/dist/task/lifecycle.d.ts.map +1 -0
  302. package/dist/task/lifecycle.js +80 -0
  303. package/dist/task/lifecycle.js.map +1 -0
  304. package/dist/task/list.d.ts +24 -0
  305. package/dist/task/list.d.ts.map +1 -0
  306. package/dist/task/list.js +116 -0
  307. package/dist/task/list.js.map +1 -0
  308. package/dist/task/model-assignment.d.ts +33 -0
  309. package/dist/task/model-assignment.d.ts.map +1 -0
  310. package/dist/task/model-assignment.js +145 -0
  311. package/dist/task/model-assignment.js.map +1 -0
  312. package/dist/task/ordering.d.ts +4 -0
  313. package/dist/task/ordering.d.ts.map +1 -0
  314. package/dist/task/ordering.js +14 -0
  315. package/dist/task/ordering.js.map +1 -0
  316. package/dist/task/ports.d.ts +37 -0
  317. package/dist/task/ports.d.ts.map +1 -0
  318. package/dist/task/ports.js +3 -0
  319. package/dist/task/ports.js.map +1 -0
  320. package/dist/task/schema.d.ts +447 -0
  321. package/dist/task/schema.d.ts.map +1 -0
  322. package/dist/task/schema.js +35 -0
  323. package/dist/task/schema.js.map +1 -0
  324. package/dist/task/session-assignment.d.ts +23 -0
  325. package/dist/task/session-assignment.d.ts.map +1 -0
  326. package/dist/task/session-assignment.js +197 -0
  327. package/dist/task/session-assignment.js.map +1 -0
  328. package/dist/task/session-registry.d.ts +8 -0
  329. package/dist/task/session-registry.d.ts.map +1 -0
  330. package/dist/task/session-registry.js +3 -0
  331. package/dist/task/session-registry.js.map +1 -0
  332. package/dist/task/update.d.ts +23 -0
  333. package/dist/task/update.d.ts.map +1 -0
  334. package/dist/task/update.js +92 -0
  335. package/dist/task/update.js.map +1 -0
  336. package/dist/task/v1-compat.d.ts +94 -0
  337. package/dist/task/v1-compat.d.ts.map +1 -0
  338. package/dist/task/v1-compat.js +181 -0
  339. package/dist/task/v1-compat.js.map +1 -0
  340. package/dist/workspace/bin-cli.d.ts +2 -0
  341. package/dist/workspace/bin-cli.d.ts.map +1 -0
  342. package/dist/workspace/bin-cli.js +36 -0
  343. package/dist/workspace/bin-cli.js.map +1 -0
  344. package/dist/workspace/cli-adapter.d.ts +16 -0
  345. package/dist/workspace/cli-adapter.d.ts.map +1 -0
  346. package/dist/workspace/cli-adapter.js +229 -0
  347. package/dist/workspace/cli-adapter.js.map +1 -0
  348. package/dist/workspace/cli-commands.d.ts +11 -0
  349. package/dist/workspace/cli-commands.d.ts.map +1 -0
  350. package/dist/workspace/cli-commands.js +12 -0
  351. package/dist/workspace/cli-commands.js.map +1 -0
  352. package/dist/workspace/duckdb-index.d.ts +56 -0
  353. package/dist/workspace/duckdb-index.d.ts.map +1 -0
  354. package/dist/workspace/duckdb-index.js +178 -0
  355. package/dist/workspace/duckdb-index.js.map +1 -0
  356. package/dist/workspace/hook-templates/need-info-notify/config.json +10 -0
  357. package/dist/workspace/hook-templates/need-info-notify/script.mjs +68 -0
  358. package/dist/workspace/hook-templates/review-spawn/config.json +10 -0
  359. package/dist/workspace/hook-templates/review-spawn/script.mjs +100 -0
  360. package/dist/workspace/init-onboarding.d.ts +9 -0
  361. package/dist/workspace/init-onboarding.d.ts.map +1 -0
  362. package/dist/workspace/init-onboarding.js +259 -0
  363. package/dist/workspace/init-onboarding.js.map +1 -0
  364. package/dist/workspace/init.d.ts +20 -0
  365. package/dist/workspace/init.d.ts.map +1 -0
  366. package/dist/workspace/init.js +288 -0
  367. package/dist/workspace/init.js.map +1 -0
  368. package/dist/workspace/layers.d.ts +127 -0
  369. package/dist/workspace/layers.d.ts.map +1 -0
  370. package/dist/workspace/layers.js +50 -0
  371. package/dist/workspace/layers.js.map +1 -0
  372. package/dist/workspace/mcp-server.d.ts +28 -0
  373. package/dist/workspace/mcp-server.d.ts.map +1 -0
  374. package/dist/workspace/mcp-server.js +190 -0
  375. package/dist/workspace/mcp-server.js.map +1 -0
  376. package/dist/workspace/mcp-stdio.d.ts +2 -0
  377. package/dist/workspace/mcp-stdio.d.ts.map +1 -0
  378. package/dist/workspace/mcp-stdio.js +66 -0
  379. package/dist/workspace/mcp-stdio.js.map +1 -0
  380. package/dist/workspace/mcp-tools.d.ts +24 -0
  381. package/dist/workspace/mcp-tools.d.ts.map +1 -0
  382. package/dist/workspace/mcp-tools.js +43 -0
  383. package/dist/workspace/mcp-tools.js.map +1 -0
  384. package/dist/workspace/migrate-v1.d.ts +12 -0
  385. package/dist/workspace/migrate-v1.d.ts.map +1 -0
  386. package/dist/workspace/migrate-v1.js +301 -0
  387. package/dist/workspace/migrate-v1.js.map +1 -0
  388. package/dist/workspace/ohtools-app.d.ts +3 -0
  389. package/dist/workspace/ohtools-app.d.ts.map +1 -0
  390. package/dist/workspace/ohtools-app.js +10 -0
  391. package/dist/workspace/ohtools-app.js.map +1 -0
  392. package/dist/workspace/repositories.d.ts +25 -0
  393. package/dist/workspace/repositories.d.ts.map +1 -0
  394. package/dist/workspace/repositories.js +76 -0
  395. package/dist/workspace/repositories.js.map +1 -0
  396. package/dist/workspace/runtime.d.ts +123 -0
  397. package/dist/workspace/runtime.d.ts.map +1 -0
  398. package/dist/workspace/runtime.js +4 -0
  399. package/dist/workspace/runtime.js.map +1 -0
  400. package/dist/workspace/session-liveness.d.ts +6 -0
  401. package/dist/workspace/session-liveness.d.ts.map +1 -0
  402. package/dist/workspace/session-liveness.js +3 -0
  403. package/dist/workspace/session-liveness.js.map +1 -0
  404. package/dist/workspace/status.d.ts +46 -0
  405. package/dist/workspace/status.d.ts.map +1 -0
  406. package/dist/workspace/status.js +345 -0
  407. package/dist/workspace/status.js.map +1 -0
  408. package/dist/workspace/storage-layout.d.ts +19 -0
  409. package/dist/workspace/storage-layout.d.ts.map +1 -0
  410. package/dist/workspace/storage-layout.js +55 -0
  411. package/dist/workspace/storage-layout.js.map +1 -0
  412. package/dist/workspace/storage-paths.d.ts +16 -0
  413. package/dist/workspace/storage-paths.d.ts.map +1 -0
  414. package/dist/workspace/storage-paths.js +15 -0
  415. package/dist/workspace/storage-paths.js.map +1 -0
  416. package/dist/workspace/v1-cli-aliases.d.ts +18 -0
  417. package/dist/workspace/v1-cli-aliases.d.ts.map +1 -0
  418. package/dist/workspace/v1-cli-aliases.js +223 -0
  419. package/dist/workspace/v1-cli-aliases.js.map +1 -0
  420. package/dist/workspace/v1-cli-task.d.ts +2 -0
  421. package/dist/workspace/v1-cli-task.d.ts.map +1 -0
  422. package/dist/workspace/v1-cli-task.js +53 -0
  423. package/dist/workspace/v1-cli-task.js.map +1 -0
  424. package/package.json +28 -12
  425. package/quickstart.md +163 -0
  426. package/hooks/need-info-notify/config.yml +0 -3
  427. package/hooks/need-info-notify/script.ts +0 -69
  428. package/hooks/review-spawn/config.yml +0 -3
  429. package/hooks/review-spawn/script.ts +0 -96
  430. package/src/cli/cli.ts +0 -489
  431. package/src/cli/init.ts +0 -230
  432. package/src/domain/fibonacci.ts +0 -39
  433. package/src/domain/kTokens.ts +0 -65
  434. package/src/domain/status-machine.ts +0 -49
  435. package/src/domain/types.ts +0 -66
  436. package/src/hook/hook-executor.ts +0 -70
  437. package/src/hook/ports.ts +0 -16
  438. package/src/infra/hook-config-loader.ts +0 -111
  439. package/src/infra/jsonl-task-repository.ts +0 -157
  440. package/src/infra/layer.ts +0 -34
  441. package/src/infra/logger.ts +0 -40
  442. package/src/infra/pid-session-registry.ts +0 -67
  443. package/src/mcp/error-codes.ts +0 -213
  444. package/src/mcp/server.ts +0 -396
  445. package/src/mcp/session.ts +0 -1
  446. package/src/mcp/tool-create-task.ts +0 -28
  447. package/src/mcp/tool-current-task.ts +0 -19
  448. package/src/mcp/tool-edit-task.ts +0 -40
  449. package/src/mcp/tool-list-tasks.ts +0 -34
  450. package/src/mcp/tool-update-task.ts +0 -55
  451. package/src/task/create-task.ts +0 -67
  452. package/src/task/current-task.ts +0 -111
  453. package/src/task/edit-task.ts +0 -59
  454. package/src/task/list-tasks.ts +0 -35
  455. package/src/task/ports.ts +0 -15
  456. package/src/task/session-registry.ts +0 -9
  457. package/src/task/update-task.ts +0 -160
package/src/mcp/server.ts DELETED
@@ -1,396 +0,0 @@
1
- #!/usr/bin/env bun
2
- import { createInterface } from "node:readline"
3
- import { Effect } from "effect"
4
- import { runInit } from "../cli/init.js"
5
- import { createLayer } from "../infra/layer.js"
6
- import { PidSessionRegistry } from "../infra/pid-session-registry.js"
7
- import { taskErrorToMcpError } from "./error-codes.js"
8
- import { newSessionId } from "./session.js"
9
- import { toolCreateTask } from "./tool-create-task.js"
10
- import { toolCurrentTask } from "./tool-current-task.js"
11
- import { toolEditTask } from "./tool-edit-task.js"
12
- import { toolListTasks } from "./tool-list-tasks.js"
13
- import { toolUpdateTask } from "./tool-update-task.js"
14
-
15
- // ---------------------------------------------------------------------------
16
- // JSON-RPC 2.0 types
17
- // ---------------------------------------------------------------------------
18
-
19
- interface JsonRpcRequest {
20
- jsonrpc: "2.0"
21
- id?: string | number | null
22
- method: string
23
- params?: unknown
24
- }
25
-
26
- interface JsonRpcSuccess {
27
- jsonrpc: "2.0"
28
- id: string | number | null
29
- result: unknown
30
- }
31
-
32
- interface JsonRpcError {
33
- jsonrpc: "2.0"
34
- id: string | number | null
35
- error: {
36
- code: number
37
- message: string
38
- data?: unknown
39
- }
40
- }
41
-
42
- type JsonRpcResponse = JsonRpcSuccess | JsonRpcError
43
-
44
- // ---------------------------------------------------------------------------
45
- // Response helpers (pure)
46
- // ---------------------------------------------------------------------------
47
-
48
- const successResponse = (id: string | number | null, result: unknown): JsonRpcSuccess => ({
49
- jsonrpc: "2.0",
50
- id,
51
- result,
52
- })
53
-
54
- const errorResponse = (
55
- id: string | number | null,
56
- code: number,
57
- message: string,
58
- data?: unknown
59
- ): JsonRpcError => ({
60
- jsonrpc: "2.0",
61
- id,
62
- error: data !== undefined ? { code, message, data } : { code, message },
63
- })
64
-
65
- const parseError = (id: string | number | null): JsonRpcError =>
66
- errorResponse(id, -32700, "Parse error")
67
- const methodNotFound = (id: string | number | null, method: string): JsonRpcError =>
68
- errorResponse(id, -32601, `Method not found: ${method}`)
69
- const internalError = (id: string | number | null, message: string): JsonRpcError =>
70
- errorResponse(id, -32603, message)
71
-
72
- // ---------------------------------------------------------------------------
73
- // Agent instructions injected into the MCP initialize response
74
- // ---------------------------------------------------------------------------
75
-
76
- const AGENT_INSTRUCTIONS = `\
77
- You are connected to the logbook MCP server. You MUST use it to track all tasks in this session.
78
-
79
- ## Session start
80
- Call \`current_task\` immediately. If it returns \`no_current_task\`, pick a task from \`list_tasks\` with status \`todo\` and move it to \`in_progress\`, or create a new one with \`create_task\` then advance it: backlog → todo → in_progress.
81
-
82
- ## Task lifecycle
83
- backlog → todo → in_progress → pending_review → done
84
- Side-exits from in_progress: → need_info (awaiting clarification) or → blocked (external dependency). Return to in_progress once resolved.
85
- Always attach a comment when moving to pending_review.
86
-
87
- ## Model selection when spawning sub-agents
88
- Base the choice on the \`predictedKTokens\` you set at task creation:
89
-
90
- | predictedKTokens | model | use for |
91
- |------------------|----------------------------|----------------------------------|
92
- | ≤ 5 | claude-haiku-4-5-20251001 | rote / mechanical tasks |
93
- | 6 – 15 | claude-sonnet-4-6 | moderate complexity |
94
- | 16+ | claude-sonnet-4-6 | large but well-scoped tasks |
95
-
96
- Override to \`claude-opus-4-6\` regardless of size when the task involves: architectural design, security analysis, creative problem-solving, or complex multi-step reasoning.`
97
-
98
- // ---------------------------------------------------------------------------
99
- // MCP tools manifest (static, derived from Zod schemas in each tool file)
100
- // ---------------------------------------------------------------------------
101
-
102
- const STATUS_ENUM = [
103
- "backlog",
104
- "todo",
105
- "need_info",
106
- "blocked",
107
- "in_progress",
108
- "pending_review",
109
- "done",
110
- ]
111
-
112
- const TOOLS_LIST = [
113
- {
114
- name: "list_tasks",
115
- description: "List tasks, optionally filtered by status. Defaults to in_progress.",
116
- inputSchema: {
117
- type: "object",
118
- properties: {
119
- status: {
120
- oneOf: [
121
- { type: "string", enum: STATUS_ENUM },
122
- { type: "string", enum: ["*"] },
123
- ],
124
- description: "Status filter. Use '*' for all tasks. Defaults to 'in_progress'.",
125
- },
126
- },
127
- },
128
- },
129
- {
130
- name: "current_task",
131
- description:
132
- "Return the highest-priority in_progress task for this session. Call this at session start before doing any work.",
133
- inputSchema: { type: "object", properties: {} },
134
- },
135
- {
136
- name: "create_task",
137
- description:
138
- "Create a new task in backlog. Set predictedKTokens to your estimated context use — this drives the Fibonacci estimation and model selection for sub-agents.",
139
- inputSchema: {
140
- type: "object",
141
- required: [
142
- "project",
143
- "milestone",
144
- "title",
145
- "definition_of_done",
146
- "description",
147
- "predictedKTokens",
148
- ],
149
- properties: {
150
- project: { type: "string" },
151
- milestone: { type: "string" },
152
- title: { type: "string" },
153
- definition_of_done: { type: "string" },
154
- description: { type: "string" },
155
- predictedKTokens: { type: "number" },
156
- },
157
- },
158
- },
159
- {
160
- name: "update_task",
161
- description:
162
- "Transition a task's status. Attach a comment when moving to pending_review. Use need_info or blocked for side-exits from in_progress.",
163
- inputSchema: {
164
- type: "object",
165
- required: ["id", "new_status"],
166
- properties: {
167
- id: { type: "string" },
168
- new_status: { type: "string", enum: STATUS_ENUM },
169
- comment: {
170
- type: "object",
171
- properties: {
172
- id: {
173
- type: "string",
174
- format: "uuid",
175
- description:
176
- "Existing comment id — provide only when replying to a need_info comment.",
177
- },
178
- title: { type: "string" },
179
- content: { type: "string" },
180
- reply: {
181
- type: "string",
182
- description: "Reply text — only meaningful when id refers to a need_info comment.",
183
- },
184
- kind: { type: "string", enum: ["need_info", "regular"] },
185
- },
186
- },
187
- },
188
- },
189
- },
190
- {
191
- name: "edit_task",
192
- description: "Edit mutable fields of a task without changing its status.",
193
- inputSchema: {
194
- type: "object",
195
- required: ["id"],
196
- properties: {
197
- id: { type: "string" },
198
- title: { type: "string" },
199
- description: { type: "string" },
200
- definition_of_done: { type: "string" },
201
- predictedKTokens: { type: "number" },
202
- },
203
- },
204
- },
205
- ]
206
-
207
- // ---------------------------------------------------------------------------
208
- // Server bootstrap
209
- // ---------------------------------------------------------------------------
210
-
211
- export const startServer = async (): Promise<void> => {
212
- const tasksFile = process.env.LOGBOOK_TASKS_FILE ?? "./tasks.jsonl"
213
- const hooksDir = process.env.LOGBOOK_HOOKS_DIR ?? "./hooks"
214
-
215
- const fullLayer = await createLayer({ tasksFile, hooksDir })
216
- const registry = new PidSessionRegistry(tasksFile)
217
-
218
- const sessionId = newSessionId()
219
- await Effect.runPromise(registry.register(sessionId, process.pid))
220
-
221
- // ---------------------------------------------------------------------------
222
- // Tool dispatch
223
- // ---------------------------------------------------------------------------
224
-
225
- const dispatch = async (method: string, params: unknown): Promise<unknown> => {
226
- switch (method) {
227
- case "initialize":
228
- return {
229
- protocolVersion: "2024-11-05",
230
- capabilities: { tools: {} },
231
- serverInfo: { name: "logbook", version: "1.0.0" },
232
- instructions: AGENT_INSTRUCTIONS,
233
- }
234
- case "tools/list":
235
- return { tools: TOOLS_LIST }
236
- case "tools/call": {
237
- const p = params as { name: string; arguments?: unknown }
238
- const result = await dispatch(p.name, p.arguments ?? {})
239
- return { content: [{ type: "text", text: JSON.stringify(result) }] }
240
- }
241
- case "list_tasks":
242
- return toolListTasks(params, fullLayer)
243
- case "current_task":
244
- return toolCurrentTask(sessionId, fullLayer)
245
- case "update_task":
246
- return toolUpdateTask(params, sessionId, fullLayer)
247
- case "create_task":
248
- return toolCreateTask(params, sessionId, fullLayer)
249
- case "edit_task":
250
- return toolEditTask(params, fullLayer)
251
- default:
252
- return Promise.reject(new MethodNotFoundError(method))
253
- }
254
- }
255
-
256
- // ---------------------------------------------------------------------------
257
- // stdio JSON-RPC loop
258
- // ---------------------------------------------------------------------------
259
-
260
- const rl = createInterface({ input: process.stdin, terminal: false })
261
-
262
- const send = (response: JsonRpcResponse): void => {
263
- process.stdout.write(`${JSON.stringify(response)}\n`)
264
- }
265
-
266
- rl.on("line", (line) => {
267
- const trimmed = line.trim()
268
- if (trimmed === "") return
269
-
270
- let request: JsonRpcRequest
271
- try {
272
- request = JSON.parse(trimmed) as JsonRpcRequest
273
- } catch {
274
- send(parseError(null))
275
- return
276
- }
277
-
278
- // MCP notifications have no `id` field — do not send a response
279
- if (!("id" in request)) {
280
- void dispatch(request.method, request.params ?? {}).catch(() => {})
281
- return
282
- }
283
-
284
- const id = request.id ?? null
285
-
286
- dispatch(request.method, request.params ?? {})
287
- .then((result) => {
288
- send(successResponse(id, result))
289
- })
290
- .catch((err: unknown) => {
291
- if (err instanceof MethodNotFoundError) {
292
- send(methodNotFound(id, err.method))
293
- return
294
- }
295
- // Task domain errors come through Effect.runPromise rejections
296
- if (isTaskError(err)) {
297
- const mcpErr = taskErrorToMcpError(err)
298
- send(errorResponse(id, mcpErr.code, mcpErr.message, mcpErr.data))
299
- return
300
- }
301
- // Zod parse errors from tool input validation
302
- if (isZodError(err)) {
303
- send(errorResponse(id, -32602, "Invalid params", { issues: err.errors }))
304
- return
305
- }
306
- send(internalError(id, String(err)))
307
- })
308
- })
309
-
310
- rl.on("close", () => {
311
- void Effect.runPromise(registry.deregister(sessionId)).then(() => process.exit(0))
312
- })
313
- }
314
-
315
- // ---------------------------------------------------------------------------
316
- // Internal error sentinel
317
- // ---------------------------------------------------------------------------
318
-
319
- class MethodNotFoundError extends Error {
320
- constructor(readonly method: string) {
321
- super(`Method not found: ${method}`)
322
- }
323
- }
324
-
325
- // ---------------------------------------------------------------------------
326
- // Type narrowing helpers (pure)
327
- // ---------------------------------------------------------------------------
328
-
329
- const isTaskError = (e: unknown): e is import("../domain/types.js").TaskError =>
330
- typeof e === "object" &&
331
- e !== null &&
332
- typeof (e as { _tag?: unknown })._tag === "string" &&
333
- [
334
- "not_found",
335
- "transition_not_allowed",
336
- "validation_error",
337
- "missing_comment",
338
- "conflict",
339
- "no_current_task",
340
- ].includes((e as { _tag: string })._tag)
341
-
342
- interface ZodError {
343
- errors: unknown[]
344
- }
345
-
346
- const isZodError = (e: unknown): e is ZodError =>
347
- typeof e === "object" &&
348
- e !== null &&
349
- Array.isArray((e as { errors?: unknown }).errors) &&
350
- "name" in (e as object) &&
351
- (e as { name: string }).name === "ZodError"
352
-
353
- // ---------------------------------------------------------------------------
354
- // CLI flag handling (before server startup)
355
- // ---------------------------------------------------------------------------
356
-
357
- const handleCliFlags = async (): Promise<void> => {
358
- const arg = process.argv[2]
359
-
360
- if (arg === "init") {
361
- await runInit()
362
- process.exit(0)
363
- }
364
-
365
- if (arg === "--version" || arg === "-v") {
366
- const pkg = await import("../../package.json", { with: { type: "json" } })
367
- process.stdout.write(`${pkg.default.version}\n`)
368
- process.exit(0)
369
- }
370
-
371
- if (arg === "--help" || arg === "-h") {
372
- process.stdout.write(`logbook-mcp [command]
373
-
374
- Commands:
375
- init Scaffold tasks.jsonl, hooks/, and emit client config snippets
376
- (default) Start the MCP server (stdio transport)
377
-
378
- Options:
379
- --version Print version
380
- --help Show this help
381
-
382
- Environment:
383
- LOGBOOK_TASKS_FILE Path to JSONL task store (default: ./tasks.jsonl)
384
- LOGBOOK_HOOKS_DIR Directory for hook definitions (default: ./hooks)
385
- LOGBOOK_LOG_LEVEL Log level: debug|info|warn|error (default: warn)
386
- `)
387
- process.exit(0)
388
- }
389
- }
390
-
391
- // ---------------------------------------------------------------------------
392
- // Entry point
393
- // ---------------------------------------------------------------------------
394
-
395
- await handleCliFlags()
396
- await startServer()
@@ -1 +0,0 @@
1
- export const newSessionId = (): string => crypto.randomUUID()
@@ -1,28 +0,0 @@
1
- import { Effect, Either, type Layer } from "effect"
2
- import { z } from "zod"
3
- import { createTask } from "../task/create-task.js"
4
- import type { TaskRepository } from "../task/ports.js"
5
-
6
- const InputSchema = z.object({
7
- project: z.string().min(1),
8
- milestone: z.string().min(1),
9
- title: z.string().min(1),
10
- definition_of_done: z.string().min(1),
11
- description: z.string().min(1),
12
- predictedKTokens: z.number().positive(),
13
- priority: z.number().int().min(0).default(0),
14
- })
15
-
16
- export const toolCreateTask = (
17
- rawInput: unknown,
18
- _sessionId: string,
19
- layer: Layer.Layer<TaskRepository>
20
- ): Promise<{ task: unknown }> => {
21
- const input = InputSchema.parse(rawInput)
22
- return Effect.runPromise(
23
- Effect.provide(Effect.either(createTask(input).pipe(Effect.map((task) => ({ task })))), layer)
24
- ).then((either) => {
25
- if (Either.isLeft(either)) throw either.left
26
- return either.right
27
- })
28
- }
@@ -1,19 +0,0 @@
1
- import { Effect, Either, type Layer } from "effect"
2
- import { currentTask } from "../task/current-task.js"
3
- import type { TaskRepository } from "../task/ports.js"
4
- import type { SessionRegistry } from "../task/session-registry.js"
5
-
6
- export const toolCurrentTask = (
7
- sessionId: string,
8
- layer: Layer.Layer<TaskRepository | SessionRegistry>
9
- ): Promise<{ task: unknown }> => {
10
- return Effect.runPromise(
11
- Effect.provide(
12
- Effect.either(currentTask(sessionId).pipe(Effect.map((task) => ({ task })))),
13
- layer
14
- )
15
- ).then((either) => {
16
- if (Either.isLeft(either)) throw either.left
17
- return either.right
18
- })
19
- }
@@ -1,40 +0,0 @@
1
- import { Effect, Either, type Layer } from "effect"
2
- import { z } from "zod"
3
- import type { EditTaskInput } from "../task/edit-task.js"
4
- import { editTask } from "../task/edit-task.js"
5
- import type { TaskRepository } from "../task/ports.js"
6
-
7
- const InputSchema = z.object({
8
- id: z.string().min(1),
9
- title: z.string().optional(),
10
- description: z.string().optional(),
11
- definition_of_done: z.string().optional(),
12
- predictedKTokens: z.number().positive().optional(),
13
- priority: z.number().int().min(0).optional(),
14
- })
15
-
16
- export const toolEditTask = (
17
- rawInput: unknown,
18
- layer: Layer.Layer<TaskRepository>
19
- ): Promise<{ task: unknown }> => {
20
- const parsed = InputSchema.parse(rawInput)
21
- const { id } = parsed
22
- // Build updates by omitting undefined fields (exact optional property types compliance)
23
- const updates: EditTaskInput = {}
24
- if (parsed.title !== undefined) updates.title = parsed.title
25
- if (parsed.description !== undefined) updates.description = parsed.description
26
- if (parsed.definition_of_done !== undefined)
27
- updates.definition_of_done = parsed.definition_of_done
28
- if (parsed.predictedKTokens !== undefined) updates.predictedKTokens = parsed.predictedKTokens
29
- if (parsed.priority !== undefined) updates.priority = parsed.priority
30
-
31
- return Effect.runPromise(
32
- Effect.provide(
33
- Effect.either(editTask(id, updates).pipe(Effect.map((task) => ({ task })))),
34
- layer
35
- )
36
- ).then((either) => {
37
- if (Either.isLeft(either)) throw either.left
38
- return either.right
39
- })
40
- }
@@ -1,34 +0,0 @@
1
- import { Effect, Either, type Layer } from "effect"
2
- import { z } from "zod"
3
- import { StatusSchema } from "../domain/types.js"
4
- import { listTasks } from "../task/list-tasks.js"
5
- import type { TaskRepository } from "../task/ports.js"
6
-
7
- const InputSchema = z.object({
8
- status: z.union([StatusSchema, z.literal("*")]).default("in_progress"),
9
- project: z.string().optional(),
10
- milestone: z.string().optional(),
11
- })
12
-
13
- export const toolListTasks = (
14
- rawInput: unknown,
15
- layer: Layer.Layer<TaskRepository>
16
- ): Promise<{ tasks: unknown[] }> => {
17
- const input = InputSchema.parse(rawInput)
18
- const options = {
19
- status: input.status,
20
- ...(input.project !== undefined ? { project: input.project } : {}),
21
- ...(input.milestone !== undefined ? { milestone: input.milestone } : {}),
22
- }
23
- return Effect.runPromise(
24
- Effect.provide(
25
- Effect.either(
26
- listTasks(options).pipe(Effect.map((tasks) => ({ tasks: tasks as unknown[] })))
27
- ),
28
- layer
29
- )
30
- ).then((either) => {
31
- if (Either.isLeft(either)) throw either.left
32
- return either.right
33
- })
34
- }
@@ -1,55 +0,0 @@
1
- import { Effect, Either, type Layer } from "effect"
2
- import { z } from "zod"
3
- import { CommentKindSchema, StatusSchema } from "../domain/types.js"
4
- import type { HookRunner } from "../hook/ports.js"
5
- import type { TaskRepository } from "../task/ports.js"
6
- import type { SessionRegistry } from "../task/session-registry.js"
7
- import { updateTask } from "../task/update-task.js"
8
-
9
- const CommentInputSchema = z
10
- .object({
11
- id: z.string().uuid().optional(), // provided only when replying to an existing comment
12
- title: z.string().min(1),
13
- content: z.string(),
14
- reply: z.string().optional(), // reply text; only meaningful when id is provided
15
- kind: CommentKindSchema,
16
- })
17
- .optional()
18
-
19
- const InputSchema = z.object({
20
- id: z.string().min(1),
21
- new_status: StatusSchema,
22
- comment: CommentInputSchema,
23
- })
24
-
25
- export const toolUpdateTask = (
26
- rawInput: unknown,
27
- sessionId: string,
28
- layer: Layer.Layer<TaskRepository | HookRunner | SessionRegistry>
29
- ): Promise<{ ok: boolean }> => {
30
- const input = InputSchema.parse(rawInput)
31
- const comment = input.comment
32
- ? {
33
- id: input.comment.id ?? crypto.randomUUID(),
34
- timestamp: new Date(),
35
- title: input.comment.title,
36
- content: input.comment.content,
37
- reply: input.comment.reply ?? "",
38
- kind: input.comment.kind,
39
- }
40
- : null
41
-
42
- return Effect.runPromise(
43
- Effect.provide(
44
- Effect.either(
45
- updateTask(input.id, input.new_status, comment, sessionId).pipe(
46
- Effect.map(() => ({ ok: true }))
47
- )
48
- ),
49
- layer
50
- )
51
- ).then((either) => {
52
- if (Either.isLeft(either)) throw either.left
53
- return either.right
54
- })
55
- }
@@ -1,67 +0,0 @@
1
- import { Effect } from "effect"
2
- import { estimateFromKTokens } from "../domain/kTokens.js"
3
- import type { Task, TaskError } from "../domain/types.js"
4
- import { TaskRepository } from "./ports.js"
5
-
6
- export interface CreateTaskInput {
7
- project: string
8
- milestone: string
9
- title: string
10
- definition_of_done: string
11
- description: string
12
- predictedKTokens: number
13
- priority?: number
14
- }
15
-
16
- /**
17
- * Creates a new task in `backlog` status with no assignee.
18
- * Validates all fields and derives a Fibonacci estimation from predictedKTokens.
19
- */
20
- export const createTask = (
21
- input: CreateTaskInput
22
- ): Effect.Effect<Task, TaskError, TaskRepository> => {
23
- // Validate required string fields
24
- const requiredStringFields: Array<keyof CreateTaskInput> = [
25
- "project",
26
- "milestone",
27
- "title",
28
- "definition_of_done",
29
- "description",
30
- ]
31
-
32
- for (const field of requiredStringFields) {
33
- if (typeof input[field] !== "string" || input[field] === "") {
34
- return Effect.fail({
35
- _tag: "validation_error" as const,
36
- message: `${field} is required`,
37
- })
38
- }
39
- }
40
-
41
- // Validate predictedKTokens is defined and a number
42
- if (input.predictedKTokens === undefined || input.predictedKTokens === null) {
43
- return Effect.fail({
44
- _tag: "validation_error" as const,
45
- message: "predictedKTokens is required",
46
- })
47
- }
48
-
49
- // Derive Fibonacci estimation from kTokens
50
- return Effect.flatMap(estimateFromKTokens(input.predictedKTokens), (estimation) => {
51
- const id = crypto.randomUUID()
52
- const task: Task = {
53
- project: input.project,
54
- milestone: input.milestone,
55
- id,
56
- title: input.title,
57
- definition_of_done: input.definition_of_done,
58
- description: input.description,
59
- estimation,
60
- comments: [],
61
- status: "backlog" as const,
62
- priority: input.priority ?? 0,
63
- }
64
-
65
- return Effect.flatMap(TaskRepository, (repo) => repo.save(task)).pipe(Effect.map(() => task))
66
- })
67
- }