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