@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/README.md CHANGED
@@ -1,361 +1,341 @@
1
- # logbook: kanban for ai agents
1
+ # logbook kanban for ai agents
2
2
 
3
- logbook is a kanban board implementation for autonomous agentic development, focusing on autonomous development and context window management.
3
+ logbook is a file-system kanban board for autonomous AI agents. It tracks epics, stories, tasks, and context entries across a structured lifecycle so agents and humans share a single source of truth without context bloat.
4
4
 
5
- → **new here?** see [quickstart.md](quickstart.md) to get running in 2 minutes.
5
+ → **new here?** see [quickstart.md](quickstart.md) to get running in 5 minutes.
6
6
 
7
- ## problem
7
+ ## why logbook
8
8
 
9
- ai agents changed the way software teams worked, and with specification-driven development we encounter a rift: **agents don't manage their tasks as we do**.
9
+ autonomous agents work in parallel, forget context across sessions, and have no shared task state. logbook solves three problems:
10
10
 
11
- ### what's the issue with this?
11
+ - **human visibility** — agents record every task they touch in a file the whole team can read and diff
12
+ - **agent coordination** — `task.current` resolves FIFO per-session, so multiple agents can't claim the same task
13
+ - **context budget** — structured JSONL with a DuckDB optional query layer lets agents find relevant records without loading the whole store
12
14
 
13
- - hard for humans to track autonomous work properly: **"do you know what specific tasks your agent did?"**
14
- - hard for agents to track tasks in-progress and done: **not a centralized way to track tasks so each instance haves to figure this out**
15
- - existing tools add too much overload and are human-centered: **if an agent is going to use it, then it should be tailored for agents**
15
+ v2 adds: *epics stories tasks* hierarchy, reusable *context entries* (knowledge that survives across tasks), and Linear two-way sync as a first-class plugin.
16
16
 
17
- ## solution
17
+ ## quickstart
18
18
 
19
- logbook is a file-system based kanban board that uses jsonl files to enter one task per line in a structured and clean approach and gives the agent the right tools to use it:
20
-
21
- ### tools
22
-
23
- - the agent can call `list_tasks(status)` and receive a list of the tasks in that status _(in_progress by default)_
24
- - the agent can call `current_task()` and receive the highest-priority in_progress task for the current session, resolved via this priority chain:
25
-
26
- | priority | condition | action |
27
- |----------|-----------|--------|
28
- | 1 | task already assigned to this session | return highest priority (tie-break: oldest) |
29
- | 2 | unassigned `in_progress` task | claim highest priority, return |
30
- | 3 | `in_progress` task with a dead-session assignee | claim highest priority, return |
31
- | 4 | `todo` task | auto-transition highest priority to `in_progress`, claim, return |
32
- | 5 | nothing available | fail with `no_current_task` |
33
- - the agent can call `update_task(id, new_status, comment)` to transition a task, add a comment, or reply to a `need_info` blocking comment
34
- - the agent can call `create_task(input)` to open a new task in `backlog`, passing `predictedKTokens` so the server derives a Fibonacci estimation automatically
35
- - the agent can call `edit_task(id, updates)` to change mutable fields without altering status
36
-
37
- each one of these tools has the sole purpose of removing overload from the agent context, handling the _"heavy load"_ programmatically on the MCP server.
38
-
39
- ## walkthrough
40
-
41
- a complete agent session from start to done:
42
-
43
- **1. agent starts — get current task**
44
-
45
- ```
46
- current_task()
47
- → { id: "abc-123", title: "implement login endpoint", status: "in_progress", ... }
19
+ ```bash
20
+ npm install -g @bosun-sh/logbook # install the CLI
21
+ logbook init # scaffold .logbook/, configure MCP, optionally set up Linear
22
+ logbook task:create \
23
+ --title "Implement login endpoint" \
24
+ --description "JWT auth, see docs/auth.md" \
25
+ --definition-of-done "Tests pass and endpoint is documented" \
26
+ --project myapp --milestone v1
27
+ logbook task:list --status "*"
48
28
  ```
49
29
 
50
- **2. agent needs clarification blocks on a question**
30
+ see [quickstart.md](quickstart.md) for the full walkthrough including Linear sync.
51
31
 
52
- ```
53
- update_task("abc-123", "need_info", {
54
- title: "which auth provider?",
55
- content: "should i use jwt or session-based auth? the spec doesn't say.",
56
- kind: "need_info"
57
- })
58
- → hook fires: user is notified with the comment
59
- ```
32
+ for one-off local use, run commands through your package manager, for example
33
+ `npx @bosun-sh/logbook --help` or `bunx @bosun-sh/logbook --help`.
60
34
 
61
- **3. user replies — task unblocked**
62
-
63
- ```
64
- update_task("abc-123", "in_progress", {
65
- id: "<comment-id>",
66
- reply: "use jwt, see the auth spec in docs/auth.md",
67
- title: "jwt confirmed",
68
- content: "jwt confirmed",
69
- kind: "need_info"
70
- })
71
- → task returns to in_progress
72
- ```
35
+ ## workspace layout
73
36
 
74
- **4. agent finishes submits for review**
37
+ `logbook init` creates the following structure through `workspace.init`:
75
38
 
76
39
  ```
77
- update_task("abc-123", "pending_review", {
78
- title: "implementation complete",
79
- content: "jwt login endpoint implemented, tests passing",
80
- kind: "regular"
81
- })
82
- review-spawn hook fires: review task created, reviewer agent spawned
40
+ .logbook/
41
+ ├── config.json # workspace config (Linear credentials, hook overrides)
42
+ ├── workspace.json # workspace metadata
43
+ ├── hooks/
44
+ │ ├── review-spawn/ # spawns a reviewer agent on pending_review
45
+ │ │ ├── config.json
46
+ │ │ └── script.mjs
47
+ │ └── need-info-notify/ # notifies user when a task needs info
48
+ │ ├── config.json
49
+ │ └── script.mjs
50
+ └── storage/
51
+ ├── epics.jsonl
52
+ ├── stories.jsonl
53
+ ├── tasks.jsonl
54
+ ├── context-entries.jsonl
55
+ ├── external-links.jsonl
56
+ ├── sync-events.jsonl
57
+ └── sync-conflicts.jsonl
83
58
  ```
84
59
 
85
- **5. reviewer approves task closed**
60
+ add `.logbook/storage/` to `.gitignore` to keep runtime data out of version control:
86
61
 
87
- ```
88
- # reviewer agent calls:
89
- current_task() → gets the review task
90
- update_task("<review-task-id>", "done")
91
- → original task abc-123 → done automatically
62
+ ```gitignore
63
+ .logbook/storage/
92
64
  ```
93
65
 
94
- ### how the agent knows logbook exists
66
+ ## mcp tools by plugin
95
67
 
96
- add the logbook MCP server to your AI client config (see [configuration](#configuration)), then include these instructions in your agent's system prompt or `CLAUDE.md`:
68
+ connect `logbook mcp` as an MCP server and call any of the 38 tools below.
97
69
 
98
- ```
99
- You are connected to the logbook MCP server. Call current_task() immediately at session start.
100
- ```
70
+ ### task plugin
101
71
 
102
- the full system prompt is injected automatically when the MCP server connects.
72
+ | Tool ID | Purpose |
73
+ |---------|---------|
74
+ | `task.create` | Create a task in backlog |
75
+ | `task.get` | Load one task by id |
76
+ | `task.list` | List tasks (default status: `in_progress`) |
77
+ | `task.current` | Claim and return the highest-priority in-progress task for this session |
78
+ | `task.update` | Transition task status, add comments, reply to need_info |
79
+ | `task.edit` | Edit mutable fields without status change |
80
+ | `task.assign.session` | Assign a session to a task |
81
+ | `task.assign.model` | Assign a model to a task |
82
+ | `task.assign.phase-model` | Set a per-phase model override |
83
+ | `task.estimate` | Compute or re-compute a Fibonacci estimation |
103
84
 
104
- ## architecture
85
+ `task.current` priority chain: session-owned in_progress → unassigned in_progress → orphaned in_progress (dead session) → highest-priority todo (auto-transitions) → `no_current_task` error.
105
86
 
106
- - **runtime**: Bun / TypeScript
107
- - **effect system**: Effect.ts — all async operations and errors are modeled as `Effect<A, E, R>`
108
- - **architecture**: hexagonal (ports & adapters), organized by vertical slices per domain concept (task, hook)
109
- - **validation**: Zod at every system boundary (MCP input, filesystem reads)
110
- - **persistence**: JSONL — one task per line, append-only writes, full file scan for reads
87
+ ### epic plugin
111
88
 
112
- JSONL was chosen for simplicity and agent-friendliness: a single line = a single task makes partial reads and diffs readable without tooling.
89
+ | Tool ID | Purpose |
90
+ |---------|---------|
91
+ | `epic.create` | Create an epic |
92
+ | `epic.get` | Load one epic |
93
+ | `epic.list` | List epics |
94
+ | `epic.update` | Update an epic |
95
+ | `epic.delete` | Tombstone an epic |
113
96
 
114
- ### hooks
97
+ ### story plugin
115
98
 
116
- besides the tools that the agent call manually, each action performed in the kanban can have automatic _hooks_ executed right before or after.
117
- the default hooks include:
99
+ | Tool ID | Purpose |
100
+ |---------|---------|
101
+ | `story.create` | Create a story within an epic |
102
+ | `story.get` | Load one story |
103
+ | `story.list` | List stories |
104
+ | `story.update` | Update a story |
105
+ | `story.delete` | Tombstone a story |
118
106
 
119
- - after moving a task to `need_info`, the user receives a notification with the comment left to be able to answer the question.
120
- - after moving a task to `pending_review`, a reviewer sub-agent spawns and a review task is automatically generated for it.
121
- - when a second task is moved to `in_progress`, a built-in hook fires and requires a comment justifying the overlap before proceeding.
107
+ ### context plugin
122
108
 
123
- but hooks can also be defined by the user as scripts in any language as long as it's installed in the system, under the "hooks/" directory, following this structure:
109
+ | Tool ID | Purpose |
110
+ |---------|---------|
111
+ | `context.create` | Create a reusable context entry |
112
+ | `context.get` | Load one context entry |
113
+ | `context.list` | List context entries |
114
+ | `context.update` | Update a context entry |
115
+ | `context.delete` | Tombstone a context entry |
116
+ | `context.attach` | Attach a context entry to an epic, story, or task |
117
+ | `context.detach` | Remove an attachment |
118
+ | `context.search` | Full-text search over context entries |
124
119
 
125
- ```
126
- hooks/
127
- └── example_hook/
128
- ├── config.yml
129
- └── script.ts
130
- ```
120
+ ### sync plugin (Linear)
131
121
 
132
- a minimal `config.yml` looks like:
122
+ | Tool ID | Purpose |
123
+ |---------|---------|
124
+ | `sync.linear.pull` | Pull issues from Linear into logbook (since-cursor pagination) |
125
+ | `sync.linear.push` | Push logbook tasks to Linear |
126
+ | `sync.linear.setup` | Configure Linear sync from a team URL or explicit ids |
127
+ | `sync.linear.status` | Check Linear configuration and connectivity |
128
+ | `sync.conflicts.list` | List unresolved sync conflicts |
129
+ | `sync.conflicts.resolve` | Resolve a conflict (`use_local`, `use_remote`, or `manual`) |
133
130
 
134
- ```yaml
135
- # config.yml
136
- event: task.status_changed # lifecycle event that triggers the hook
137
- condition: "new_status == 'need_info'" # optional; JS-like expression
138
- timeout_ms: 5000 # optional; default 5000
139
- ```
131
+ ### workspace plugin
140
132
 
141
- you can base your config.yml in the default hooks-which have complete configuration files.
133
+ | Tool ID | Purpose |
134
+ |---------|---------|
135
+ | `workspace.init` | Initialize or re-scaffold the `.logbook/` workspace |
136
+ | `workspace.status` | Report workspace health and provider status |
142
137
 
143
- > note: as mentioned, you can change .ts for any language, but the .yml / .yaml is required for configuration.
138
+ ### hook plugin
144
139
 
145
- #### review flow
140
+ | Tool ID | Purpose |
141
+ |---------|---------|
142
+ | `hook.list` | List registered hooks |
143
+ | `hook.run` | Run a hook manually |
146
144
 
147
- when a task is moved to `pending_review`, the built-in `review-spawn` hook automatically creates a review task and spawns a reviewer sub-agent. the reviewer classifies every finding before acting:
145
+ ### plugin plugin
148
146
 
149
- ```mermaid
150
- flowchart TD
151
- PR[task: pending_review]
152
- PR -->|review-spawn hook| SPAWN[review task created\nreviewer agent spawned]
153
- SPAWN --> CL{classify findings}
147
+ | Tool ID | Purpose |
148
+ |---------|---------|
149
+ | `plugin.list` | List all registered plugins and their tool IDs |
154
150
 
155
- CL -->|nice-to-have findings| TD["[tech debt] tasks created\nin backlog — silently"]
151
+ ## cli
156
152
 
157
- CL -->|must-fix found| MF[original in_progress\nneed_info: must fix before re-submitting]
158
- CL -->|consider only| CO[original → in_progress\nneed_info: implementer decides\nfix now or backlog]
159
- CL -->|clean| DONE[original → done]
153
+ every tool is available as `logbook <tool-id-with-colons>`:
160
154
 
161
- MF --> RD[review task → done]
162
- CO --> RD
163
- DONE --> RD
155
+ ```bash
156
+ # preferred onboarding
157
+ logbook init
158
+ logbook init --mcp-client claude --no-linear
159
+
160
+ # workspace
161
+ logbook workspace:init
162
+ logbook workspace:status
163
+
164
+ # tasks
165
+ logbook task:create --title "x" --description "y" --definition-of-done "z" --project p --milestone m
166
+ logbook task:list --status "*"
167
+ logbook task:list --status in_progress
168
+ logbook task:current
169
+ logbook task:update --id <uuid> --new-status pending_review
170
+ logbook task:edit --id <uuid> --title "New title"
171
+
172
+ # epics and stories
173
+ logbook epic:create --title "Auth" --description "Login and session management" --outcome "Users can log in"
174
+ logbook story:create --epic-id <uuid> --title "JWT login" --description "..." --user-value "Users can authenticate"
175
+
176
+ # context
177
+ logbook context:create --title "Auth spec" --body "Use JWT RS256. See docs/auth.md."
178
+ logbook context:attach --context-entry-id <uuid> --task-id <uuid>
179
+
180
+ # Linear sync
181
+ logbook sync:linear:setup --team-url https://linear.app/<workspace>/team/<team>
182
+ logbook sync:linear:pull
183
+ logbook sync:linear:push --dry-run
184
+ logbook sync:linear:status
185
+
186
+ # v1 aliases (still work, emit a compatibility warning)
187
+ logbook create-task --title "..." --definition-of-done "..." --predicted-k-tokens 3
188
+ logbook list-tasks --status in_progress
189
+ ```
164
190
 
165
- TD -.->|accompanies any outcome| RD
191
+ all commands write a single-line JSON envelope to stdout:
192
+
193
+ ```json
194
+ {"ok":true,"data":{"task":{...}}}
195
+ {"ok":false,"error":{"code":"not_found","message":"task abc was not found"}}
166
196
  ```
167
197
 
168
- | finding severity | original task | review task | side effect |
169
- |-----------------|---------------|-------------|-------------|
170
- | **must-fix** | `→ in_progress` + `need_info` | `→ done` | — |
171
- | **consider** | `→ in_progress` + `need_info` | `→ done` | implementer replies: fix now or backlog |
172
- | **nice-to-have** | unchanged | — | `[tech debt]` backlog task created |
173
- | **clean** | `→ done` | `→ done` | — |
198
+ ## linear integration
174
199
 
175
- nice-to-have findings are always handled silently — they never block progress or ping the implementer.
200
+ ### setup
176
201
 
177
- #### why hooks?
202
+ The preferred setup path is `logbook init`, which prompts for Linear sync setup.
203
+ To configure Linear separately:
178
204
 
179
- hooks don't need to store information from one execution to the other, so the main principle here is: **"execute and forget"**, this way we can focus on the kanban and actual tasks.
205
+ 1. create a Linear API key at **Linear Settings API Personal API keys**
206
+ 2. add it to `.env` or export it in your shell:
207
+ ```bash
208
+ echo "LINEAR_API_KEY=lin_api_..." >> .env
209
+ ```
210
+ 3. configure Logbook from your Linear team URL:
211
+ ```bash
212
+ logbook sync:linear:setup --team-url https://linear.app/bosun/team/BOSUN
213
+ ```
180
214
 
181
- ## contracts
215
+ The setup command resolves the workspace and team ids and writes the public config to `.logbook/config.json`.
216
+ It never writes the API key there. To let setup write `.env` for you, pass the token once:
182
217
 
183
- the core types the server operates on:
218
+ ```bash
219
+ logbook sync:linear:setup \
220
+ --team-url https://linear.app/bosun/team/BOSUN \
221
+ --api-token lin_api_... \
222
+ --write-env
223
+ ```
184
224
 
185
- ```ts
186
- type Agent = {
187
- id: string, // session_id assigned by the server on connection
188
- title: string,
189
- description: string
190
- }
225
+ Manual setup is also supported:
191
226
 
192
- type Status = 'backlog' | 'todo' | 'need_info' | 'blocked' | 'in_progress' | 'pending_review' | 'done'
227
+ ```bash
228
+ logbook sync:linear:setup \
229
+ --workspace-id <workspace-id> \
230
+ --team-id <team-id>
231
+ ```
193
232
 
194
- type Comment = {
195
- id: string,
196
- timestamp: Date,
197
- title: string,
198
- content: string,
199
- reply: string, // user's reply, populated when responding to a need_info comment
200
- kind: 'need_info' | 'regular' // drives the reply cycle — only need_info comments accept replies
201
- }
233
+ This produces a `linear` block like:
202
234
 
203
- type Task = {
204
- project: string,
205
- milestone: string,
206
- id: string,
207
- title: string,
208
- definition_of_done: string,
209
- description: string,
210
- estimation: number, // fibonacci number derived from predictedKTokens at creation time
211
- comments: Comment[],
212
- assignee: Agent,
213
- status: Status,
214
- in_progress_since?: Date // set when task enters in_progress; used as tie-breaker in current_task
215
- priority: number // integer ≥ 0; higher = more urgent; defaults to 0
216
- }
235
+ ```json
236
+ {
237
+ "linear": {
238
+ "apiTokenEnv": "LINEAR_API_KEY",
239
+ "workspaceId": "your-workspace-id",
240
+ "defaultTeamId": "your-team-id"
241
+ }
242
+ }
243
+ ```
217
244
 
218
- // status defaults to 'in_progress'; results ordered by priority DESC
219
- // project and milestone are optional; all provided filters compose (AND semantics)
220
- type ListTasks = (options: { status: Status | '*', project?: string, milestone?: string }) => Task[]
221
-
222
- // returns the highest-priority task for the current session using a priority chain:
223
- // 1. own in_progress → 2. unassigned in_progress → 3. orphaned in_progress
224
- // (dead-session assignee) → 4. highest-priority todo (auto-transitioned) → 5. no_current_task error.
225
- // within each step, tasks are ordered by priority DESC, tie-broken by in_progress_since ASC.
226
- // if a second task is moved to in_progress, a built-in hook fires and
227
- // requires a comment justifying the overlap.
228
- type GetCurrentTask = () => Task
229
-
230
- // transitions a task to a new status; sessionId is injected server-side.
231
- // to reply to a need_info comment, pass a comment with the existing comment's id and a reply string.
232
- type UpdateTask = (id: string, new_status: Status, comment: CommentInput | null, sessionId: string) => void
233
-
234
- type CommentInput = {
235
- id?: string, // existing comment id — only when replying to a need_info comment
236
- title: string,
237
- content: string,
238
- reply?: string, // reply text — only meaningful when id refers to a need_info comment
239
- kind: 'need_info' | 'regular'
240
- }
245
+ ### pull / push
241
246
 
242
- // creates a new task in backlog assigned to the calling session.
243
- // predictedKTokens is mapped to a Fibonacci estimation by the server.
244
- type CreateTask = (input: CreateTaskInput, sessionId: string) => Task
245
-
246
- type CreateTaskInput = {
247
- project: string,
248
- milestone: string,
249
- title: string,
250
- definition_of_done: string,
251
- description: string,
252
- predictedKTokens: number, // positive number; server maps this to a Fibonacci estimation (max 20)
253
- priority?: number // integer ≥ 0; defaults to 0
254
- }
247
+ when Logbook runs through MCP, task-facing tools automatically pull before the call and push successful task writes back to Linear. the explicit commands below are still available for manual refreshes, dry runs, and targeted syncs.
255
248
 
256
- // edits mutable fields without changing status
257
- type EditTask = (id: string, updates: EditTaskInput) => Task
249
+ ```bash
250
+ # pull issues from Linear since the last cursor
251
+ logbook sync:linear:pull
258
252
 
259
- type EditTaskInput = {
260
- title?: string,
261
- description?: string,
262
- definition_of_done?: string,
263
- predictedKTokens?: number, // re-derives estimation if provided
264
- priority?: number // integer ≥ 0; re-assigns priority if provided
265
- }
266
- ```
253
+ # pull with options
254
+ logbook sync:linear:pull --dry-run --team-id <id>
267
255
 
268
- each MCP session is treated as a distinct agent instance. the server assigns a `session_id` on connection and uses it to scope `GetCurrentTask` — no explicit agent ID needs to be passed by the caller.
256
+ # push logbook tasks to Linear
257
+ logbook sync:linear:push
269
258
 
270
- ## install
259
+ # push only specific tasks
260
+ logbook sync:linear:push --task-ids '["task_abc","task_xyz"]' --dry-run
271
261
 
272
- ```bash
273
- npm install -g @bosun-sh/logbook
262
+ # check status (connectivity + cursor position)
263
+ logbook sync:linear:status --check-provider
274
264
  ```
275
265
 
276
- requires **bun ≥ 1.0.0** as the runtime ([install bun](https://bun.sh)).
266
+ ### conflicts
277
267
 
278
- verify the installation:
268
+ when the same record is modified in both logbook and Linear, a conflict entry is written to `sync-conflicts.jsonl`:
279
269
 
280
270
  ```bash
281
- logbook-mcp --version
271
+ logbook sync:conflicts:list
272
+ logbook sync:conflicts:resolve --id <conflict-uuid> --resolution use_local
273
+ # resolutions: use_local | use_remote | manual
282
274
  ```
283
275
 
284
- for a full onboarding walkthrough see [quickstart.md](quickstart.md).
276
+ conflict states: `open` `resolved` or `ignored`.
285
277
 
286
- ## configuration
278
+ ### external links
287
279
 
288
- ### quick setup
280
+ bidirectional `linear:<id>` mappings are stored in `external-links.jsonl` and updated automatically by pull/push.
289
281
 
290
- run `logbook-mcp init` in your project directory to scaffold `tasks.jsonl`, `hooks/`, and print the config snippets for your AI client.
282
+ ## hooks
291
283
 
292
- ### environment variables
284
+ hooks execute shell commands on task lifecycle events. configuration lives in `.logbook/hooks/<id>/config.json`:
293
285
 
294
- | Variable | Default | Description |
295
- |----------|---------|-------------|
296
- | `LOGBOOK_TASKS_FILE` | `./tasks.jsonl` | path to the JSONL task store |
297
- | `LOGBOOK_HOOKS_DIR` | `./hooks` | directory scanned for custom hook definitions |
298
- | `LOGBOOK_LOG_LEVEL` | `warn` | structured logger level: `debug`, `info`, `warn`, or `error` |
299
-
300
- ### gitignore
286
+ ```json
287
+ {
288
+ "id": "need-info-notify",
289
+ "event": "task.status_changed",
290
+ "condition": { "status": "need_info" },
291
+ "command": ["node", ".logbook/hooks/need-info-notify/script.mjs"],
292
+ "timeoutMs": 5000
293
+ }
294
+ ```
301
295
 
302
- `tasks.jsonl` and `sessions.json` are runtime files generated by the MCP server — they should not be committed to version control:
296
+ two hooks are materialized by `workspace.init`:
303
297
 
304
- ```gitignore
305
- tasks.jsonl
306
- sessions.json
307
- ```
298
+ - **`need-info-notify`** — prints the blocking comment when a task moves to `need_info`
299
+ - **`review-spawn`** — creates a review task and spawns a reviewer agent when a task moves to `pending_review`
308
300
 
309
- > note: the logbook repo itself intentionally commits these files for dogfooding that is the exception, not the rule.
301
+ hooks are stateless execute and forget. the `command` field is an argv array; no shell expansion is performed.
310
302
 
311
- ### client setup
303
+ ## environment variables
312
304
 
313
- **Claude Code** add to `.claude/settings.json`:
305
+ | Variable | Default | Description |
306
+ |----------|---------|-------------|
307
+ | `LOGBOOK_WORKSPACE_ROOT` | `process.cwd()` | workspace root used by the compiled binaries |
308
+ | `LOGBOOK_LOG_LEVEL` | `warn` | log level: `debug`, `info`, `warn`, `error` |
309
+ | `LINEAR_API_KEY` | — | Linear API token (or the env var named in `linear.apiTokenEnv`) |
314
310
 
315
- ```json
316
- {
317
- "mcpServers": {
318
- "logbook": {
319
- "command": "logbook-mcp"
320
- }
321
- }
322
- }
323
- ```
311
+ ## optional duckdb index
324
312
 
325
- **OpenCode** add to `opencode.json`:
313
+ logbook uses `@duckdb/node-api` to run ad-hoc SQL over the canonical JSONL files. the index is in-memory — no separate index file is written or maintained:
326
314
 
327
- ```json
328
- {
329
- "mcp": {
330
- "logbook": {
331
- "type": "local",
332
- "command": ["logbook-mcp"],
333
- "enabled": true
334
- }
335
- }
336
- }
315
+ ```sql
316
+ -- example: find all in_progress tasks for a specific project
317
+ SELECT id, title, status FROM read_json_auto('.logbook/storage/tasks.jsonl', format='newline_delimited')
318
+ WHERE status = 'in_progress' AND project = 'myapp'
337
319
  ```
338
320
 
339
- ## security
340
-
341
- ### hook conditions are trusted code
321
+ the DuckDB path is opt-in via `workspace.status` and is non-canonical — the JSONL files remain the source of truth.
342
322
 
343
- hook `config.yml` files support an optional `condition` field (e.g. `"new_status == 'pending_review'"`). these conditions are compiled and evaluated as live JavaScript at runtime — equivalent in trust level to a shell script.
323
+ ## migrating from v1
344
324
 
345
- **what this means for you:**
325
+ if your project has a `tasks.jsonl` at the repository root, `workspace.init` detects it and migrates all records to `.logbook/storage/tasks.jsonl` automatically:
346
326
 
347
- - **only add hooks from sources you trust.** a malicious `config.yml` condition can execute arbitrary code in the process that runs the MCP server.
348
- - **do not expose `LOGBOOK_HOOKS_DIR` to external write access.** if an untrusted process can write files under the hooks directory, it can inject conditions that execute as the MCP server's user.
349
- - the built-in hooks shipped with logbook are safe — they use simple equality checks (`new_status == 'need_info'`).
350
- - if a condition throws or is malformed, the hook is skipped silently and execution continues — it fails safe.
327
+ - field names renamed from `snake_case` to `camelCase`
328
+ - `kind: "task"` injected on every record
329
+ - v1 comment shape converted to v2 shape
351
330
 
352
- the security model here is the same as running a `Makefile` or a `.husky/` script: filesystem-level trust. as long as you control what goes into your hooks directory, you are safe.
331
+ v1 CLI commands (`create-task`, `list-tasks`, `current-task`, `update-task`, `edit-task`, `init`) remain registered and emit a `compatibility_mapping_applied` warning. remove the deprecated commands from your scripts when ready.
353
332
 
354
- ## stability
333
+ see `CHANGELOG.md` for the full v2.0.0 breaking-change list.
355
334
 
356
- logbook follows semantic versioning. here is what is stable at v1.0.0:
335
+ ## stack
357
336
 
358
- - **mcp api**: tool names and required parameters will not change within a major version. optional parameters may be added.
359
- - **jsonl format**: the serialized `Task` type in `tasks.jsonl` is stable. new optional fields may be added; existing fields will not be removed or renamed within a major version.
360
- - **hook config schema**: the `event`, `condition`, and `timeout_ms` keys in `config.yml` are stable. new optional keys may be added.
361
- - **breaking changes**: any breaking change will be preceded by a deprecation notice in the prior minor release and documented in `CHANGELOG.md`.
337
+ - **runtime**: Node.js / TypeScript
338
+ - **effect system**: Effect.ts all async operations and errors modeled as `Effect<A, E, R>`
339
+ - **architecture**: ohtools plugin registry, hexagonal adapters (CLI + MCP), vertical slices per entity
340
+ - **persistence**: JSONL append-only, one record per line, full-scan reads; DuckDB for optional ad-hoc queries
341
+ - **validation**: Zod at every public boundary (MCP input, CLI flags, filesystem reads)
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env node
2
+ const { spawnSync } = require("node:child_process")
3
+ const { existsSync } = require("node:fs")
4
+ const path = require("node:path")
5
+
6
+ const entry = path.join(__dirname, "..", "dist", "workspace", "bin-cli.js")
7
+ if (!existsSync(entry)) {
8
+ console.error(
9
+ `logbook entrypoint not found at ${entry}. Reinstall the package or run the build step before publishing.`
10
+ )
11
+ process.exit(1)
12
+ }
13
+
14
+ const result = spawnSync(process.execPath, [entry, ...process.argv.slice(2)], { stdio: "inherit" })
15
+ if (result.error) {
16
+ throw result.error
17
+ }
18
+ process.exit(result.status ?? 0)