opentasks 0.0.1 → 0.0.2

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 (662) hide show
  1. package/README.md +344 -1
  2. package/dist/__tests__/cli-tools.test.d.ts +8 -0
  3. package/dist/__tests__/cli-tools.test.d.ts.map +1 -0
  4. package/dist/__tests__/cli-tools.test.js +546 -0
  5. package/dist/__tests__/cli-tools.test.js.map +1 -0
  6. package/dist/__tests__/cli.test.d.ts +5 -0
  7. package/dist/__tests__/cli.test.d.ts.map +1 -0
  8. package/dist/__tests__/cli.test.js +77 -0
  9. package/dist/__tests__/cli.test.js.map +1 -0
  10. package/dist/__tests__/p1-p3-gaps.test.d.ts +2 -0
  11. package/dist/__tests__/p1-p3-gaps.test.d.ts.map +1 -0
  12. package/dist/__tests__/p1-p3-gaps.test.js +463 -0
  13. package/dist/__tests__/p1-p3-gaps.test.js.map +1 -0
  14. package/dist/cli.d.ts +19 -1
  15. package/dist/cli.d.ts.map +1 -1
  16. package/dist/cli.js +702 -23
  17. package/dist/cli.js.map +1 -1
  18. package/dist/client/__tests__/client-crud.test.d.ts +7 -0
  19. package/dist/client/__tests__/client-crud.test.d.ts.map +1 -0
  20. package/dist/client/__tests__/client-crud.test.js +404 -0
  21. package/dist/client/__tests__/client-crud.test.js.map +1 -0
  22. package/dist/client/__tests__/client.test.d.ts +5 -0
  23. package/dist/client/__tests__/client.test.d.ts.map +1 -0
  24. package/dist/client/__tests__/client.test.js +518 -0
  25. package/dist/client/__tests__/client.test.js.map +1 -0
  26. package/dist/client/client.d.ts +228 -0
  27. package/dist/client/client.d.ts.map +1 -0
  28. package/dist/client/client.js +393 -0
  29. package/dist/client/client.js.map +1 -0
  30. package/dist/client/index.d.ts +11 -0
  31. package/dist/client/index.d.ts.map +1 -0
  32. package/dist/client/index.js +9 -0
  33. package/dist/client/index.js.map +1 -0
  34. package/dist/config/__tests__/defaults.test.d.ts +2 -0
  35. package/dist/config/__tests__/defaults.test.d.ts.map +1 -0
  36. package/dist/config/__tests__/defaults.test.js +57 -0
  37. package/dist/config/__tests__/defaults.test.js.map +1 -0
  38. package/dist/config/__tests__/env.test.d.ts +2 -0
  39. package/dist/config/__tests__/env.test.d.ts.map +1 -0
  40. package/dist/config/__tests__/env.test.js +136 -0
  41. package/dist/config/__tests__/env.test.js.map +1 -0
  42. package/dist/config/__tests__/index.test.d.ts +2 -0
  43. package/dist/config/__tests__/index.test.d.ts.map +1 -0
  44. package/dist/config/__tests__/index.test.js +113 -0
  45. package/dist/config/__tests__/index.test.js.map +1 -0
  46. package/dist/config/__tests__/loader.test.d.ts +2 -0
  47. package/dist/config/__tests__/loader.test.d.ts.map +1 -0
  48. package/dist/config/__tests__/loader.test.js +128 -0
  49. package/dist/config/__tests__/loader.test.js.map +1 -0
  50. package/dist/config/__tests__/merge.test.d.ts +2 -0
  51. package/dist/config/__tests__/merge.test.d.ts.map +1 -0
  52. package/dist/config/__tests__/merge.test.js +79 -0
  53. package/dist/config/__tests__/merge.test.js.map +1 -0
  54. package/dist/config/__tests__/schema.test.d.ts +2 -0
  55. package/dist/config/__tests__/schema.test.d.ts.map +1 -0
  56. package/dist/config/__tests__/schema.test.js +300 -0
  57. package/dist/config/__tests__/schema.test.js.map +1 -0
  58. package/dist/config/defaults.d.ts +13 -0
  59. package/dist/config/defaults.d.ts.map +1 -0
  60. package/dist/config/defaults.js +15 -0
  61. package/dist/config/defaults.js.map +1 -0
  62. package/dist/config/env.d.ts +14 -0
  63. package/dist/config/env.d.ts.map +1 -0
  64. package/dist/config/env.js +130 -0
  65. package/dist/config/env.js.map +1 -0
  66. package/dist/config/errors.d.ts +21 -0
  67. package/dist/config/errors.d.ts.map +1 -0
  68. package/dist/config/errors.js +30 -0
  69. package/dist/config/errors.js.map +1 -0
  70. package/dist/config/index.d.ts +21 -0
  71. package/dist/config/index.d.ts.map +1 -0
  72. package/dist/config/index.js +41 -0
  73. package/dist/config/index.js.map +1 -0
  74. package/dist/config/loader.d.ts +8 -0
  75. package/dist/config/loader.d.ts.map +1 -0
  76. package/dist/config/loader.js +87 -0
  77. package/dist/config/loader.js.map +1 -0
  78. package/dist/config/merge.d.ts +12 -0
  79. package/dist/config/merge.d.ts.map +1 -0
  80. package/dist/config/merge.js +54 -0
  81. package/dist/config/merge.js.map +1 -0
  82. package/dist/config/schema.d.ts +644 -0
  83. package/dist/config/schema.d.ts.map +1 -0
  84. package/dist/config/schema.js +491 -0
  85. package/dist/config/schema.js.map +1 -0
  86. package/dist/core/__tests__/conditional-redirects.test.d.ts +2 -0
  87. package/dist/core/__tests__/conditional-redirects.test.d.ts.map +1 -0
  88. package/dist/core/__tests__/conditional-redirects.test.js +83 -0
  89. package/dist/core/__tests__/conditional-redirects.test.js.map +1 -0
  90. package/dist/core/__tests__/connections.test.d.ts +2 -0
  91. package/dist/core/__tests__/connections.test.d.ts.map +1 -0
  92. package/dist/core/__tests__/connections.test.js +158 -0
  93. package/dist/core/__tests__/connections.test.js.map +1 -0
  94. package/dist/core/__tests__/hash.test.d.ts +2 -0
  95. package/dist/core/__tests__/hash.test.d.ts.map +1 -0
  96. package/dist/core/__tests__/hash.test.js +139 -0
  97. package/dist/core/__tests__/hash.test.js.map +1 -0
  98. package/dist/core/__tests__/id.test.d.ts +2 -0
  99. package/dist/core/__tests__/id.test.d.ts.map +1 -0
  100. package/dist/core/__tests__/id.test.js +142 -0
  101. package/dist/core/__tests__/id.test.js.map +1 -0
  102. package/dist/core/__tests__/location.test.d.ts +2 -0
  103. package/dist/core/__tests__/location.test.d.ts.map +1 -0
  104. package/dist/core/__tests__/location.test.js +77 -0
  105. package/dist/core/__tests__/location.test.js.map +1 -0
  106. package/dist/core/__tests__/merge-driver.test.d.ts +2 -0
  107. package/dist/core/__tests__/merge-driver.test.d.ts.map +1 -0
  108. package/dist/core/__tests__/merge-driver.test.js +218 -0
  109. package/dist/core/__tests__/merge-driver.test.js.map +1 -0
  110. package/dist/core/__tests__/redirects.test.d.ts +2 -0
  111. package/dist/core/__tests__/redirects.test.d.ts.map +1 -0
  112. package/dist/core/__tests__/redirects.test.js +123 -0
  113. package/dist/core/__tests__/redirects.test.js.map +1 -0
  114. package/dist/core/__tests__/resolve-location-target.test.d.ts +8 -0
  115. package/dist/core/__tests__/resolve-location-target.test.d.ts.map +1 -0
  116. package/dist/core/__tests__/resolve-location-target.test.js +303 -0
  117. package/dist/core/__tests__/resolve-location-target.test.js.map +1 -0
  118. package/dist/core/__tests__/uri.test.d.ts +2 -0
  119. package/dist/core/__tests__/uri.test.d.ts.map +1 -0
  120. package/dist/core/__tests__/uri.test.js +159 -0
  121. package/dist/core/__tests__/uri.test.js.map +1 -0
  122. package/dist/core/__tests__/worktree.test.d.ts +2 -0
  123. package/dist/core/__tests__/worktree.test.d.ts.map +1 -0
  124. package/dist/core/__tests__/worktree.test.js +120 -0
  125. package/dist/core/__tests__/worktree.test.js.map +1 -0
  126. package/dist/core/conditional-redirects.d.ts +42 -0
  127. package/dist/core/conditional-redirects.d.ts.map +1 -0
  128. package/dist/core/conditional-redirects.js +59 -0
  129. package/dist/core/conditional-redirects.js.map +1 -0
  130. package/dist/core/connections.d.ts +87 -0
  131. package/dist/core/connections.d.ts.map +1 -0
  132. package/dist/core/connections.js +160 -0
  133. package/dist/core/connections.js.map +1 -0
  134. package/dist/core/discover.d.ts +39 -0
  135. package/dist/core/discover.d.ts.map +1 -0
  136. package/dist/core/discover.js +136 -0
  137. package/dist/core/discover.js.map +1 -0
  138. package/dist/core/hash.d.ts +25 -0
  139. package/dist/core/hash.d.ts.map +1 -0
  140. package/dist/core/hash.js +62 -0
  141. package/dist/core/hash.js.map +1 -0
  142. package/dist/core/id.d.ts +79 -0
  143. package/dist/core/id.d.ts.map +1 -0
  144. package/dist/core/id.js +141 -0
  145. package/dist/core/id.js.map +1 -0
  146. package/dist/core/index.d.ts +15 -0
  147. package/dist/core/index.d.ts.map +1 -0
  148. package/dist/core/index.js +24 -0
  149. package/dist/core/index.js.map +1 -0
  150. package/dist/core/location.d.ts +70 -0
  151. package/dist/core/location.d.ts.map +1 -0
  152. package/dist/core/location.js +121 -0
  153. package/dist/core/location.js.map +1 -0
  154. package/dist/core/merge-driver.d.ts +50 -0
  155. package/dist/core/merge-driver.d.ts.map +1 -0
  156. package/dist/core/merge-driver.js +258 -0
  157. package/dist/core/merge-driver.js.map +1 -0
  158. package/dist/core/redirects.d.ts +91 -0
  159. package/dist/core/redirects.d.ts.map +1 -0
  160. package/dist/core/redirects.js +113 -0
  161. package/dist/core/redirects.js.map +1 -0
  162. package/dist/core/uri.d.ts +105 -0
  163. package/dist/core/uri.d.ts.map +1 -0
  164. package/dist/core/uri.js +190 -0
  165. package/dist/core/uri.js.map +1 -0
  166. package/dist/core/worktree.d.ts +106 -0
  167. package/dist/core/worktree.d.ts.map +1 -0
  168. package/dist/core/worktree.js +394 -0
  169. package/dist/core/worktree.js.map +1 -0
  170. package/dist/daemon/__tests__/flush.test.d.ts +5 -0
  171. package/dist/daemon/__tests__/flush.test.d.ts.map +1 -0
  172. package/dist/daemon/__tests__/flush.test.js +213 -0
  173. package/dist/daemon/__tests__/flush.test.js.map +1 -0
  174. package/dist/daemon/__tests__/integration.test.d.ts +7 -0
  175. package/dist/daemon/__tests__/integration.test.d.ts.map +1 -0
  176. package/dist/daemon/__tests__/integration.test.js +276 -0
  177. package/dist/daemon/__tests__/integration.test.js.map +1 -0
  178. package/dist/daemon/__tests__/ipc.test.d.ts +5 -0
  179. package/dist/daemon/__tests__/ipc.test.d.ts.map +1 -0
  180. package/dist/daemon/__tests__/ipc.test.js +314 -0
  181. package/dist/daemon/__tests__/ipc.test.js.map +1 -0
  182. package/dist/daemon/__tests__/lifecycle.test.d.ts +5 -0
  183. package/dist/daemon/__tests__/lifecycle.test.d.ts.map +1 -0
  184. package/dist/daemon/__tests__/lifecycle.test.js +301 -0
  185. package/dist/daemon/__tests__/lifecycle.test.js.map +1 -0
  186. package/dist/daemon/__tests__/lock.test.d.ts +5 -0
  187. package/dist/daemon/__tests__/lock.test.d.ts.map +1 -0
  188. package/dist/daemon/__tests__/lock.test.js +192 -0
  189. package/dist/daemon/__tests__/lock.test.js.map +1 -0
  190. package/dist/daemon/__tests__/methods/graph.test.d.ts +5 -0
  191. package/dist/daemon/__tests__/methods/graph.test.d.ts.map +1 -0
  192. package/dist/daemon/__tests__/methods/graph.test.js +309 -0
  193. package/dist/daemon/__tests__/methods/graph.test.js.map +1 -0
  194. package/dist/daemon/__tests__/methods/provider.test.d.ts +7 -0
  195. package/dist/daemon/__tests__/methods/provider.test.d.ts.map +1 -0
  196. package/dist/daemon/__tests__/methods/provider.test.js +181 -0
  197. package/dist/daemon/__tests__/methods/provider.test.js.map +1 -0
  198. package/dist/daemon/__tests__/methods/tools.test.d.ts +5 -0
  199. package/dist/daemon/__tests__/methods/tools.test.d.ts.map +1 -0
  200. package/dist/daemon/__tests__/methods/tools.test.js +587 -0
  201. package/dist/daemon/__tests__/methods/tools.test.js.map +1 -0
  202. package/dist/daemon/__tests__/multi-location.test.d.ts +8 -0
  203. package/dist/daemon/__tests__/multi-location.test.d.ts.map +1 -0
  204. package/dist/daemon/__tests__/multi-location.test.js +669 -0
  205. package/dist/daemon/__tests__/multi-location.test.js.map +1 -0
  206. package/dist/daemon/__tests__/registry.test.d.ts +5 -0
  207. package/dist/daemon/__tests__/registry.test.d.ts.map +1 -0
  208. package/dist/daemon/__tests__/registry.test.js +208 -0
  209. package/dist/daemon/__tests__/registry.test.js.map +1 -0
  210. package/dist/daemon/__tests__/watcher.test.d.ts +5 -0
  211. package/dist/daemon/__tests__/watcher.test.d.ts.map +1 -0
  212. package/dist/daemon/__tests__/watcher.test.js +234 -0
  213. package/dist/daemon/__tests__/watcher.test.js.map +1 -0
  214. package/dist/daemon/entire-linker.d.ts +68 -0
  215. package/dist/daemon/entire-linker.d.ts.map +1 -0
  216. package/dist/daemon/entire-linker.js +439 -0
  217. package/dist/daemon/entire-linker.js.map +1 -0
  218. package/dist/daemon/entire-watcher.d.ts +66 -0
  219. package/dist/daemon/entire-watcher.d.ts.map +1 -0
  220. package/dist/daemon/entire-watcher.js +258 -0
  221. package/dist/daemon/entire-watcher.js.map +1 -0
  222. package/dist/daemon/factory.d.ts +59 -0
  223. package/dist/daemon/factory.d.ts.map +1 -0
  224. package/dist/daemon/factory.js +72 -0
  225. package/dist/daemon/factory.js.map +1 -0
  226. package/dist/daemon/flush.d.ts +51 -0
  227. package/dist/daemon/flush.d.ts.map +1 -0
  228. package/dist/daemon/flush.js +89 -0
  229. package/dist/daemon/flush.js.map +1 -0
  230. package/dist/daemon/index.d.ts +39 -0
  231. package/dist/daemon/index.d.ts.map +1 -0
  232. package/dist/daemon/index.js +24 -0
  233. package/dist/daemon/index.js.map +1 -0
  234. package/dist/daemon/ipc.d.ts +97 -0
  235. package/dist/daemon/ipc.d.ts.map +1 -0
  236. package/dist/daemon/ipc.js +304 -0
  237. package/dist/daemon/ipc.js.map +1 -0
  238. package/dist/daemon/lifecycle.d.ts +85 -0
  239. package/dist/daemon/lifecycle.d.ts.map +1 -0
  240. package/dist/daemon/lifecycle.js +754 -0
  241. package/dist/daemon/lifecycle.js.map +1 -0
  242. package/dist/daemon/location-state.d.ts +85 -0
  243. package/dist/daemon/location-state.d.ts.map +1 -0
  244. package/dist/daemon/location-state.js +291 -0
  245. package/dist/daemon/location-state.js.map +1 -0
  246. package/dist/daemon/lock.d.ts +29 -0
  247. package/dist/daemon/lock.d.ts.map +1 -0
  248. package/dist/daemon/lock.js +131 -0
  249. package/dist/daemon/lock.js.map +1 -0
  250. package/dist/daemon/methods/__tests__/graph.test.d.ts +5 -0
  251. package/dist/daemon/methods/__tests__/graph.test.d.ts.map +1 -0
  252. package/dist/daemon/methods/__tests__/graph.test.js +274 -0
  253. package/dist/daemon/methods/__tests__/graph.test.js.map +1 -0
  254. package/dist/daemon/methods/__tests__/provider.test.d.ts +5 -0
  255. package/dist/daemon/methods/__tests__/provider.test.d.ts.map +1 -0
  256. package/dist/daemon/methods/__tests__/provider.test.js +184 -0
  257. package/dist/daemon/methods/__tests__/provider.test.js.map +1 -0
  258. package/dist/daemon/methods/__tests__/tools.test.d.ts +5 -0
  259. package/dist/daemon/methods/__tests__/tools.test.d.ts.map +1 -0
  260. package/dist/daemon/methods/__tests__/tools.test.js +295 -0
  261. package/dist/daemon/methods/__tests__/tools.test.js.map +1 -0
  262. package/dist/daemon/methods/archive.d.ts +22 -0
  263. package/dist/daemon/methods/archive.d.ts.map +1 -0
  264. package/dist/daemon/methods/archive.js +107 -0
  265. package/dist/daemon/methods/archive.js.map +1 -0
  266. package/dist/daemon/methods/graph.d.ts +26 -0
  267. package/dist/daemon/methods/graph.d.ts.map +1 -0
  268. package/dist/daemon/methods/graph.js +157 -0
  269. package/dist/daemon/methods/graph.js.map +1 -0
  270. package/dist/daemon/methods/lifecycle.d.ts +54 -0
  271. package/dist/daemon/methods/lifecycle.d.ts.map +1 -0
  272. package/dist/daemon/methods/lifecycle.js +46 -0
  273. package/dist/daemon/methods/lifecycle.js.map +1 -0
  274. package/dist/daemon/methods/location.d.ts +24 -0
  275. package/dist/daemon/methods/location.d.ts.map +1 -0
  276. package/dist/daemon/methods/location.js +72 -0
  277. package/dist/daemon/methods/location.js.map +1 -0
  278. package/dist/daemon/methods/provider.d.ts +22 -0
  279. package/dist/daemon/methods/provider.d.ts.map +1 -0
  280. package/dist/daemon/methods/provider.js +72 -0
  281. package/dist/daemon/methods/provider.js.map +1 -0
  282. package/dist/daemon/methods/tools.d.ts +23 -0
  283. package/dist/daemon/methods/tools.d.ts.map +1 -0
  284. package/dist/daemon/methods/tools.js +111 -0
  285. package/dist/daemon/methods/tools.js.map +1 -0
  286. package/dist/daemon/registry.d.ts +35 -0
  287. package/dist/daemon/registry.d.ts.map +1 -0
  288. package/dist/daemon/registry.js +189 -0
  289. package/dist/daemon/registry.js.map +1 -0
  290. package/dist/daemon/types.d.ts +101 -0
  291. package/dist/daemon/types.d.ts.map +1 -0
  292. package/dist/daemon/types.js +19 -0
  293. package/dist/daemon/types.js.map +1 -0
  294. package/dist/daemon/watcher.d.ts +62 -0
  295. package/dist/daemon/watcher.d.ts.map +1 -0
  296. package/dist/daemon/watcher.js +142 -0
  297. package/dist/daemon/watcher.js.map +1 -0
  298. package/dist/graph/EdgeTypeRegistry.d.ts +134 -0
  299. package/dist/graph/EdgeTypeRegistry.d.ts.map +1 -0
  300. package/dist/graph/EdgeTypeRegistry.js +255 -0
  301. package/dist/graph/EdgeTypeRegistry.js.map +1 -0
  302. package/dist/graph/FederatedGraph.d.ts +296 -0
  303. package/dist/graph/FederatedGraph.d.ts.map +1 -0
  304. package/dist/graph/FederatedGraph.js +406 -0
  305. package/dist/graph/FederatedGraph.js.map +1 -0
  306. package/dist/graph/GraphologyAdapter.d.ts +151 -0
  307. package/dist/graph/GraphologyAdapter.d.ts.map +1 -0
  308. package/dist/graph/GraphologyAdapter.js +209 -0
  309. package/dist/graph/GraphologyAdapter.js.map +1 -0
  310. package/dist/graph/HydratingFederatedGraph.d.ts +151 -0
  311. package/dist/graph/HydratingFederatedGraph.d.ts.map +1 -0
  312. package/dist/graph/HydratingFederatedGraph.js +327 -0
  313. package/dist/graph/HydratingFederatedGraph.js.map +1 -0
  314. package/dist/graph/__tests__/EdgeTypeRegistry.test.d.ts +2 -0
  315. package/dist/graph/__tests__/EdgeTypeRegistry.test.d.ts.map +1 -0
  316. package/dist/graph/__tests__/EdgeTypeRegistry.test.js +212 -0
  317. package/dist/graph/__tests__/EdgeTypeRegistry.test.js.map +1 -0
  318. package/dist/graph/__tests__/FederatedGraph.test.d.ts +2 -0
  319. package/dist/graph/__tests__/FederatedGraph.test.d.ts.map +1 -0
  320. package/dist/graph/__tests__/FederatedGraph.test.js +661 -0
  321. package/dist/graph/__tests__/FederatedGraph.test.js.map +1 -0
  322. package/dist/graph/__tests__/GraphologyAdapter.test.d.ts +2 -0
  323. package/dist/graph/__tests__/GraphologyAdapter.test.d.ts.map +1 -0
  324. package/dist/graph/__tests__/GraphologyAdapter.test.js +326 -0
  325. package/dist/graph/__tests__/GraphologyAdapter.test.js.map +1 -0
  326. package/dist/graph/__tests__/HydratingFederatedGraph.test.d.ts +2 -0
  327. package/dist/graph/__tests__/HydratingFederatedGraph.test.d.ts.map +1 -0
  328. package/dist/graph/__tests__/HydratingFederatedGraph.test.js +587 -0
  329. package/dist/graph/__tests__/HydratingFederatedGraph.test.js.map +1 -0
  330. package/dist/graph/__tests__/debounce.test.d.ts +5 -0
  331. package/dist/graph/__tests__/debounce.test.d.ts.map +1 -0
  332. package/dist/graph/__tests__/debounce.test.js +195 -0
  333. package/dist/graph/__tests__/debounce.test.js.map +1 -0
  334. package/dist/graph/__tests__/edge-cases.test.d.ts +8 -0
  335. package/dist/graph/__tests__/edge-cases.test.d.ts.map +1 -0
  336. package/dist/graph/__tests__/edge-cases.test.js +472 -0
  337. package/dist/graph/__tests__/edge-cases.test.js.map +1 -0
  338. package/dist/graph/__tests__/expansion.test.d.ts +2 -0
  339. package/dist/graph/__tests__/expansion.test.d.ts.map +1 -0
  340. package/dist/graph/__tests__/expansion.test.js +105 -0
  341. package/dist/graph/__tests__/expansion.test.js.map +1 -0
  342. package/dist/graph/__tests__/provider-store.test.d.ts +5 -0
  343. package/dist/graph/__tests__/provider-store.test.d.ts.map +1 -0
  344. package/dist/graph/__tests__/provider-store.test.js +791 -0
  345. package/dist/graph/__tests__/provider-store.test.js.map +1 -0
  346. package/dist/graph/__tests__/query.test.d.ts +5 -0
  347. package/dist/graph/__tests__/query.test.d.ts.map +1 -0
  348. package/dist/graph/__tests__/query.test.js +774 -0
  349. package/dist/graph/__tests__/query.test.js.map +1 -0
  350. package/dist/graph/__tests__/store.test.d.ts +5 -0
  351. package/dist/graph/__tests__/store.test.d.ts.map +1 -0
  352. package/dist/graph/__tests__/store.test.js +489 -0
  353. package/dist/graph/__tests__/store.test.js.map +1 -0
  354. package/dist/graph/__tests__/sync.test.d.ts +5 -0
  355. package/dist/graph/__tests__/sync.test.d.ts.map +1 -0
  356. package/dist/graph/__tests__/sync.test.js +129 -0
  357. package/dist/graph/__tests__/sync.test.js.map +1 -0
  358. package/dist/graph/__tests__/validation.test.d.ts +2 -0
  359. package/dist/graph/__tests__/validation.test.d.ts.map +1 -0
  360. package/dist/graph/__tests__/validation.test.js +521 -0
  361. package/dist/graph/__tests__/validation.test.js.map +1 -0
  362. package/dist/graph/coordination.d.ts +190 -0
  363. package/dist/graph/coordination.d.ts.map +1 -0
  364. package/dist/graph/coordination.js +180 -0
  365. package/dist/graph/coordination.js.map +1 -0
  366. package/dist/graph/debounce.d.ts +47 -0
  367. package/dist/graph/debounce.d.ts.map +1 -0
  368. package/dist/graph/debounce.js +95 -0
  369. package/dist/graph/debounce.js.map +1 -0
  370. package/dist/graph/expansion.d.ts +64 -0
  371. package/dist/graph/expansion.d.ts.map +1 -0
  372. package/dist/graph/expansion.js +205 -0
  373. package/dist/graph/expansion.js.map +1 -0
  374. package/dist/graph/history.d.ts +186 -0
  375. package/dist/graph/history.d.ts.map +1 -0
  376. package/dist/graph/history.js +155 -0
  377. package/dist/graph/history.js.map +1 -0
  378. package/dist/graph/index.d.ts +35 -0
  379. package/dist/graph/index.d.ts.map +1 -0
  380. package/dist/graph/index.js +22 -0
  381. package/dist/graph/index.js.map +1 -0
  382. package/dist/graph/provider-store.d.ts +211 -0
  383. package/dist/graph/provider-store.d.ts.map +1 -0
  384. package/dist/graph/provider-store.js +568 -0
  385. package/dist/graph/provider-store.js.map +1 -0
  386. package/dist/graph/query.d.ts +90 -0
  387. package/dist/graph/query.d.ts.map +1 -0
  388. package/dist/graph/query.js +463 -0
  389. package/dist/graph/query.js.map +1 -0
  390. package/dist/graph/store.d.ts +71 -0
  391. package/dist/graph/store.d.ts.map +1 -0
  392. package/dist/graph/store.js +530 -0
  393. package/dist/graph/store.js.map +1 -0
  394. package/dist/graph/sync.d.ts +48 -0
  395. package/dist/graph/sync.d.ts.map +1 -0
  396. package/dist/graph/sync.js +60 -0
  397. package/dist/graph/sync.js.map +1 -0
  398. package/dist/graph/types.d.ts +289 -0
  399. package/dist/graph/types.d.ts.map +1 -0
  400. package/dist/graph/types.js +19 -0
  401. package/dist/graph/types.js.map +1 -0
  402. package/dist/graph/validation.d.ts +26 -0
  403. package/dist/graph/validation.d.ts.map +1 -0
  404. package/dist/graph/validation.js +338 -0
  405. package/dist/graph/validation.js.map +1 -0
  406. package/dist/index.d.ts +25 -14
  407. package/dist/index.d.ts.map +1 -1
  408. package/dist/index.js +22 -25
  409. package/dist/index.js.map +1 -1
  410. package/dist/materialization/archiver.d.ts +12 -0
  411. package/dist/materialization/archiver.d.ts.map +1 -0
  412. package/dist/materialization/archiver.js +273 -0
  413. package/dist/materialization/archiver.js.map +1 -0
  414. package/dist/materialization/git-archive-store.d.ts +17 -0
  415. package/dist/materialization/git-archive-store.d.ts.map +1 -0
  416. package/dist/materialization/git-archive-store.js +509 -0
  417. package/dist/materialization/git-archive-store.js.map +1 -0
  418. package/dist/materialization/git-remote-store.d.ts +22 -0
  419. package/dist/materialization/git-remote-store.d.ts.map +1 -0
  420. package/dist/materialization/git-remote-store.js +448 -0
  421. package/dist/materialization/git-remote-store.js.map +1 -0
  422. package/dist/materialization/graph-id.d.ts +53 -0
  423. package/dist/materialization/graph-id.d.ts.map +1 -0
  424. package/dist/materialization/graph-id.js +163 -0
  425. package/dist/materialization/graph-id.js.map +1 -0
  426. package/dist/materialization/http-remote-store.d.ts +12 -0
  427. package/dist/materialization/http-remote-store.d.ts.map +1 -0
  428. package/dist/materialization/http-remote-store.js +143 -0
  429. package/dist/materialization/http-remote-store.js.map +1 -0
  430. package/dist/materialization/index.d.ts +15 -0
  431. package/dist/materialization/index.d.ts.map +1 -0
  432. package/dist/materialization/index.js +17 -0
  433. package/dist/materialization/index.js.map +1 -0
  434. package/dist/materialization/remote-store-factory.d.ts +17 -0
  435. package/dist/materialization/remote-store-factory.d.ts.map +1 -0
  436. package/dist/materialization/remote-store-factory.js +46 -0
  437. package/dist/materialization/remote-store-factory.js.map +1 -0
  438. package/dist/materialization/snapshot.d.ts +34 -0
  439. package/dist/materialization/snapshot.d.ts.map +1 -0
  440. package/dist/materialization/snapshot.js +177 -0
  441. package/dist/materialization/snapshot.js.map +1 -0
  442. package/dist/materialization/types.d.ts +300 -0
  443. package/dist/materialization/types.d.ts.map +1 -0
  444. package/dist/materialization/types.js +17 -0
  445. package/dist/materialization/types.js.map +1 -0
  446. package/dist/providers/__tests__/beads.test.d.ts +5 -0
  447. package/dist/providers/__tests__/beads.test.d.ts.map +1 -0
  448. package/dist/providers/__tests__/beads.test.js +591 -0
  449. package/dist/providers/__tests__/beads.test.js.map +1 -0
  450. package/dist/providers/__tests__/claude-tasks.test.d.ts +5 -0
  451. package/dist/providers/__tests__/claude-tasks.test.d.ts.map +1 -0
  452. package/dist/providers/__tests__/claude-tasks.test.js +392 -0
  453. package/dist/providers/__tests__/claude-tasks.test.js.map +1 -0
  454. package/dist/providers/__tests__/from-config.test.d.ts +5 -0
  455. package/dist/providers/__tests__/from-config.test.d.ts.map +1 -0
  456. package/dist/providers/__tests__/from-config.test.js +152 -0
  457. package/dist/providers/__tests__/from-config.test.js.map +1 -0
  458. package/dist/providers/__tests__/materialization.test.d.ts +5 -0
  459. package/dist/providers/__tests__/materialization.test.d.ts.map +1 -0
  460. package/dist/providers/__tests__/materialization.test.js +407 -0
  461. package/dist/providers/__tests__/materialization.test.js.map +1 -0
  462. package/dist/providers/__tests__/native.test.d.ts +5 -0
  463. package/dist/providers/__tests__/native.test.d.ts.map +1 -0
  464. package/dist/providers/__tests__/native.test.js +566 -0
  465. package/dist/providers/__tests__/native.test.js.map +1 -0
  466. package/dist/providers/__tests__/registry.test.d.ts +5 -0
  467. package/dist/providers/__tests__/registry.test.d.ts.map +1 -0
  468. package/dist/providers/__tests__/registry.test.js +183 -0
  469. package/dist/providers/__tests__/registry.test.js.map +1 -0
  470. package/dist/providers/beads.d.ts +46 -0
  471. package/dist/providers/beads.d.ts.map +1 -0
  472. package/dist/providers/beads.js +865 -0
  473. package/dist/providers/beads.js.map +1 -0
  474. package/dist/providers/claude-tasks.d.ts +56 -0
  475. package/dist/providers/claude-tasks.d.ts.map +1 -0
  476. package/dist/providers/claude-tasks.js +282 -0
  477. package/dist/providers/claude-tasks.js.map +1 -0
  478. package/dist/providers/entire.d.ts +88 -0
  479. package/dist/providers/entire.d.ts.map +1 -0
  480. package/dist/providers/entire.js +409 -0
  481. package/dist/providers/entire.js.map +1 -0
  482. package/dist/providers/from-config.d.ts +47 -0
  483. package/dist/providers/from-config.d.ts.map +1 -0
  484. package/dist/providers/from-config.js +150 -0
  485. package/dist/providers/from-config.js.map +1 -0
  486. package/dist/providers/index.d.ts +26 -0
  487. package/dist/providers/index.d.ts.map +1 -0
  488. package/dist/providers/index.js +29 -0
  489. package/dist/providers/index.js.map +1 -0
  490. package/dist/providers/location.d.ts +44 -0
  491. package/dist/providers/location.d.ts.map +1 -0
  492. package/dist/providers/location.js +157 -0
  493. package/dist/providers/location.js.map +1 -0
  494. package/dist/providers/materialization.d.ts +46 -0
  495. package/dist/providers/materialization.d.ts.map +1 -0
  496. package/dist/providers/materialization.js +237 -0
  497. package/dist/providers/materialization.js.map +1 -0
  498. package/dist/providers/native.d.ts +32 -0
  499. package/dist/providers/native.d.ts.map +1 -0
  500. package/dist/providers/native.js +552 -0
  501. package/dist/providers/native.js.map +1 -0
  502. package/dist/providers/registry.d.ts +11 -0
  503. package/dist/providers/registry.d.ts.map +1 -0
  504. package/dist/providers/registry.js +97 -0
  505. package/dist/providers/registry.js.map +1 -0
  506. package/dist/providers/sudocode.d.ts +49 -0
  507. package/dist/providers/sudocode.d.ts.map +1 -0
  508. package/dist/providers/sudocode.js +945 -0
  509. package/dist/providers/sudocode.js.map +1 -0
  510. package/dist/providers/sync.d.ts +299 -0
  511. package/dist/providers/sync.d.ts.map +1 -0
  512. package/dist/providers/sync.js +93 -0
  513. package/dist/providers/sync.js.map +1 -0
  514. package/dist/providers/traits/RelationshipQueryable.d.ts +129 -0
  515. package/dist/providers/traits/RelationshipQueryable.d.ts.map +1 -0
  516. package/dist/providers/traits/RelationshipQueryable.js +68 -0
  517. package/dist/providers/traits/RelationshipQueryable.js.map +1 -0
  518. package/dist/providers/traits/TaskManageable.d.ts +157 -0
  519. package/dist/providers/traits/TaskManageable.d.ts.map +1 -0
  520. package/dist/providers/traits/TaskManageable.js +37 -0
  521. package/dist/providers/traits/TaskManageable.js.map +1 -0
  522. package/dist/providers/traits/Watchable.d.ts +216 -0
  523. package/dist/providers/traits/Watchable.d.ts.map +1 -0
  524. package/dist/providers/traits/Watchable.js +37 -0
  525. package/dist/providers/traits/Watchable.js.map +1 -0
  526. package/dist/providers/traits/__tests__/RelationshipQueryable.test.d.ts +2 -0
  527. package/dist/providers/traits/__tests__/RelationshipQueryable.test.d.ts.map +1 -0
  528. package/dist/providers/traits/__tests__/RelationshipQueryable.test.js +169 -0
  529. package/dist/providers/traits/__tests__/RelationshipQueryable.test.js.map +1 -0
  530. package/dist/providers/traits/__tests__/TaskManageable.test.d.ts +2 -0
  531. package/dist/providers/traits/__tests__/TaskManageable.test.d.ts.map +1 -0
  532. package/dist/providers/traits/__tests__/TaskManageable.test.js +172 -0
  533. package/dist/providers/traits/__tests__/TaskManageable.test.js.map +1 -0
  534. package/dist/providers/traits/index.d.ts +13 -0
  535. package/dist/providers/traits/index.d.ts.map +1 -0
  536. package/dist/providers/traits/index.js +10 -0
  537. package/dist/providers/traits/index.js.map +1 -0
  538. package/dist/providers/types.d.ts +284 -0
  539. package/dist/providers/types.d.ts.map +1 -0
  540. package/dist/providers/types.js +30 -0
  541. package/dist/providers/types.js.map +1 -0
  542. package/dist/schema/__tests__/validation.test.d.ts +2 -0
  543. package/dist/schema/__tests__/validation.test.d.ts.map +1 -0
  544. package/dist/schema/__tests__/validation.test.js +241 -0
  545. package/dist/schema/__tests__/validation.test.js.map +1 -0
  546. package/dist/schema/base.d.ts +68 -0
  547. package/dist/schema/base.d.ts.map +1 -0
  548. package/dist/schema/base.js +5 -0
  549. package/dist/schema/base.js.map +1 -0
  550. package/dist/schema/edges.d.ts +49 -0
  551. package/dist/schema/edges.d.ts.map +1 -0
  552. package/dist/schema/edges.js +9 -0
  553. package/dist/schema/edges.js.map +1 -0
  554. package/dist/schema/index.d.ts +11 -0
  555. package/dist/schema/index.d.ts.map +1 -0
  556. package/dist/schema/index.js +8 -0
  557. package/dist/schema/index.js.map +1 -0
  558. package/dist/schema/nodes.d.ts +97 -0
  559. package/dist/schema/nodes.d.ts.map +1 -0
  560. package/dist/schema/nodes.js +5 -0
  561. package/dist/schema/nodes.js.map +1 -0
  562. package/dist/schema/storage.d.ts +107 -0
  563. package/dist/schema/storage.d.ts.map +1 -0
  564. package/dist/schema/storage.js +10 -0
  565. package/dist/schema/storage.js.map +1 -0
  566. package/dist/schema/validation.d.ts +61 -0
  567. package/dist/schema/validation.d.ts.map +1 -0
  568. package/dist/schema/validation.js +170 -0
  569. package/dist/schema/validation.js.map +1 -0
  570. package/dist/storage/__tests__/atomic-write.test.d.ts +5 -0
  571. package/dist/storage/__tests__/atomic-write.test.d.ts.map +1 -0
  572. package/dist/storage/__tests__/atomic-write.test.js +170 -0
  573. package/dist/storage/__tests__/atomic-write.test.js.map +1 -0
  574. package/dist/storage/__tests__/file-lock.test.d.ts +2 -0
  575. package/dist/storage/__tests__/file-lock.test.d.ts.map +1 -0
  576. package/dist/storage/__tests__/file-lock.test.js +89 -0
  577. package/dist/storage/__tests__/file-lock.test.js.map +1 -0
  578. package/dist/storage/__tests__/jsonl.test.d.ts +2 -0
  579. package/dist/storage/__tests__/jsonl.test.d.ts.map +1 -0
  580. package/dist/storage/__tests__/jsonl.test.js +228 -0
  581. package/dist/storage/__tests__/jsonl.test.js.map +1 -0
  582. package/dist/storage/__tests__/locked-writer.test.d.ts +2 -0
  583. package/dist/storage/__tests__/locked-writer.test.d.ts.map +1 -0
  584. package/dist/storage/__tests__/locked-writer.test.js +109 -0
  585. package/dist/storage/__tests__/locked-writer.test.js.map +1 -0
  586. package/dist/storage/__tests__/sqlite.test.d.ts +2 -0
  587. package/dist/storage/__tests__/sqlite.test.d.ts.map +1 -0
  588. package/dist/storage/__tests__/sqlite.test.js +470 -0
  589. package/dist/storage/__tests__/sqlite.test.js.map +1 -0
  590. package/dist/storage/atomic-write.d.ts +38 -0
  591. package/dist/storage/atomic-write.d.ts.map +1 -0
  592. package/dist/storage/atomic-write.js +83 -0
  593. package/dist/storage/atomic-write.js.map +1 -0
  594. package/dist/storage/file-lock.d.ts +66 -0
  595. package/dist/storage/file-lock.d.ts.map +1 -0
  596. package/dist/storage/file-lock.js +176 -0
  597. package/dist/storage/file-lock.js.map +1 -0
  598. package/dist/storage/index.d.ts +11 -0
  599. package/dist/storage/index.d.ts.map +1 -0
  600. package/dist/storage/index.js +13 -0
  601. package/dist/storage/index.js.map +1 -0
  602. package/dist/storage/interface.d.ts +219 -0
  603. package/dist/storage/interface.d.ts.map +1 -0
  604. package/dist/storage/interface.js +22 -0
  605. package/dist/storage/interface.js.map +1 -0
  606. package/dist/storage/jsonl.d.ts +106 -0
  607. package/dist/storage/jsonl.d.ts.map +1 -0
  608. package/dist/storage/jsonl.js +218 -0
  609. package/dist/storage/jsonl.js.map +1 -0
  610. package/dist/storage/locked-writer.d.ts +67 -0
  611. package/dist/storage/locked-writer.d.ts.map +1 -0
  612. package/dist/storage/locked-writer.js +105 -0
  613. package/dist/storage/locked-writer.js.map +1 -0
  614. package/dist/storage/sqlite-schema.d.ts +48 -0
  615. package/dist/storage/sqlite-schema.d.ts.map +1 -0
  616. package/dist/storage/sqlite-schema.js +169 -0
  617. package/dist/storage/sqlite-schema.js.map +1 -0
  618. package/dist/storage/sqlite.d.ts +73 -0
  619. package/dist/storage/sqlite.d.ts.map +1 -0
  620. package/dist/storage/sqlite.js +698 -0
  621. package/dist/storage/sqlite.js.map +1 -0
  622. package/dist/tools/__tests__/annotate.test.d.ts +5 -0
  623. package/dist/tools/__tests__/annotate.test.d.ts.map +1 -0
  624. package/dist/tools/__tests__/annotate.test.js +314 -0
  625. package/dist/tools/__tests__/annotate.test.js.map +1 -0
  626. package/dist/tools/__tests__/link.test.d.ts +5 -0
  627. package/dist/tools/__tests__/link.test.d.ts.map +1 -0
  628. package/dist/tools/__tests__/link.test.js +245 -0
  629. package/dist/tools/__tests__/link.test.js.map +1 -0
  630. package/dist/tools/__tests__/query.test.d.ts +5 -0
  631. package/dist/tools/__tests__/query.test.d.ts.map +1 -0
  632. package/dist/tools/__tests__/query.test.js +288 -0
  633. package/dist/tools/__tests__/query.test.js.map +1 -0
  634. package/dist/tools/__tests__/task.test.d.ts +5 -0
  635. package/dist/tools/__tests__/task.test.d.ts.map +1 -0
  636. package/dist/tools/__tests__/task.test.js +178 -0
  637. package/dist/tools/__tests__/task.test.js.map +1 -0
  638. package/dist/tools/annotate.d.ts +17 -0
  639. package/dist/tools/annotate.d.ts.map +1 -0
  640. package/dist/tools/annotate.js +218 -0
  641. package/dist/tools/annotate.js.map +1 -0
  642. package/dist/tools/index.d.ts +14 -0
  643. package/dist/tools/index.d.ts.map +1 -0
  644. package/dist/tools/index.js +14 -0
  645. package/dist/tools/index.js.map +1 -0
  646. package/dist/tools/link.d.ts +17 -0
  647. package/dist/tools/link.d.ts.map +1 -0
  648. package/dist/tools/link.js +127 -0
  649. package/dist/tools/link.js.map +1 -0
  650. package/dist/tools/query.d.ts +17 -0
  651. package/dist/tools/query.d.ts.map +1 -0
  652. package/dist/tools/query.js +342 -0
  653. package/dist/tools/query.js.map +1 -0
  654. package/dist/tools/task.d.ts +20 -0
  655. package/dist/tools/task.d.ts.map +1 -0
  656. package/dist/tools/task.js +161 -0
  657. package/dist/tools/task.js.map +1 -0
  658. package/dist/tools/types.d.ts +334 -0
  659. package/dist/tools/types.d.ts.map +1 -0
  660. package/dist/tools/types.js +19 -0
  661. package/dist/tools/types.js.map +1 -0
  662. package/package.json +40 -5
@@ -0,0 +1,865 @@
1
+ /**
2
+ * Beads Provider
3
+ *
4
+ * Provider that integrates with Beads via CLI.
5
+ * Handles beads:// and bd:// URI schemes.
6
+ */
7
+ import { exec as execCallback } from 'child_process';
8
+ import { promisify } from 'util';
9
+ import chokidar from 'chokidar';
10
+ import { ProviderError as ProviderErrorClass } from './types.js';
11
+ import { filterEdgesByType, filterEdgesByDirection } from './traits/RelationshipQueryable.js';
12
+ const execAsync = promisify(execCallback);
13
+ // ============================================================================
14
+ // Constants
15
+ // ============================================================================
16
+ /**
17
+ * Pattern for beads:// or bd:// URIs
18
+ * Format: beads://[workspace/]id or bd://[workspace/]id
19
+ */
20
+ const BEADS_URI_PATTERN = /^(beads|bd):\/\/(?:([^/]+)\/)?(.+)$/i;
21
+ /**
22
+ * Pattern for Beads issue IDs
23
+ */
24
+ const BEADS_ID_PATTERN = /^bd-[a-z0-9]+$/i;
25
+ // ============================================================================
26
+ // Helper Functions
27
+ // ============================================================================
28
+ /**
29
+ * Map Beads priority to normalized 0-4 scale
30
+ */
31
+ function mapPriority(priority) {
32
+ if (priority === undefined)
33
+ return undefined;
34
+ if (typeof priority === 'number') {
35
+ // Assume already 0-4 scale
36
+ return Math.max(0, Math.min(4, priority));
37
+ }
38
+ // Map string priorities
39
+ switch (priority.toLowerCase()) {
40
+ case 'critical':
41
+ case 'highest':
42
+ return 0;
43
+ case 'high':
44
+ return 1;
45
+ case 'medium':
46
+ case 'normal':
47
+ return 2;
48
+ case 'low':
49
+ return 3;
50
+ case 'lowest':
51
+ return 4;
52
+ default:
53
+ return 2;
54
+ }
55
+ }
56
+ /**
57
+ * Valid task actions for each status state
58
+ */
59
+ function validActionsForStatus(status) {
60
+ switch (status) {
61
+ case 'open':
62
+ return ['start', 'block', 'close'];
63
+ case 'in_progress':
64
+ return ['complete', 'block', 'close'];
65
+ case 'blocked':
66
+ return ['reopen', 'close'];
67
+ case 'closed':
68
+ return ['reopen'];
69
+ default:
70
+ return ['start', 'complete', 'block', 'reopen', 'close'];
71
+ }
72
+ }
73
+ /**
74
+ * Convert Beads issue to ProviderNode
75
+ */
76
+ function beadsIssueToProviderNode(issue, workspace = '.') {
77
+ return {
78
+ id: issue.id,
79
+ uri: `beads://${workspace}/${issue.id}`,
80
+ type: 'issue',
81
+ title: issue.title,
82
+ content: issue.description,
83
+ status: issue.status,
84
+ priority: mapPriority(issue.priority),
85
+ rawData: issue,
86
+ fetchedAt: new Date().toISOString(),
87
+ };
88
+ }
89
+ // ============================================================================
90
+ // Beads Provider Implementation
91
+ // ============================================================================
92
+ /**
93
+ * Create a Beads provider with relationship querying and optional watching support
94
+ */
95
+ export function createBeadsProvider(config = {}) {
96
+ const executable = config.executable ?? 'bd';
97
+ const cwd = config.cwd;
98
+ const timeout = config.timeout ?? 30000;
99
+ const extraArgs = config.extraArgs ?? [];
100
+ const watchPath = config.watchPath;
101
+ const watchDebounceMs = config.watchDebounceMs ?? 200;
102
+ const capabilities = {
103
+ read: true,
104
+ write: true,
105
+ search: true,
106
+ watch: !!watchPath,
107
+ mount: true,
108
+ feedback: false,
109
+ };
110
+ // =========================================================================
111
+ // Watch State (only active when watchPath is configured)
112
+ // =========================================================================
113
+ /** Cached content hashes for change diffing: beads issue id → hash of serialized data */
114
+ const cachedHashes = new Map();
115
+ /** Cached edge signatures for edge change detection: "from:to:type" → true */
116
+ const cachedEdgeKeys = new Set();
117
+ /** chokidar watcher instance */
118
+ let fileWatcher = null;
119
+ /** Current watch callback */
120
+ let watchCallback = null;
121
+ /** Debounce timer for coalescing rapid file changes */
122
+ let debounceTimer = null;
123
+ /**
124
+ * Simple hash for diffing (not cryptographic — just for detecting changes).
125
+ * Uses the same approach as sync.ts calculateContentHash.
126
+ */
127
+ function quickHash(input) {
128
+ let hash = 0;
129
+ for (let i = 0; i < input.length; i++) {
130
+ const char = input.charCodeAt(i);
131
+ hash = (hash << 5) - hash + char;
132
+ hash = hash & hash;
133
+ }
134
+ return hash.toString(16);
135
+ }
136
+ /**
137
+ * Build a stable hash key for a Beads issue (substantive fields only)
138
+ */
139
+ function issueHashKey(issue) {
140
+ const substantive = {
141
+ title: issue.title,
142
+ description: issue.description,
143
+ status: issue.status,
144
+ priority: issue.priority,
145
+ tags: issue.tags ? [...issue.tags].sort() : undefined,
146
+ blocks: issue.blocks ? [...issue.blocks].sort() : undefined,
147
+ blockedBy: issue.blockedBy ? [...issue.blockedBy].sort() : undefined,
148
+ // Structured format (bd v0.49+)
149
+ dependency_count: issue.dependency_count,
150
+ dependent_count: issue.dependent_count,
151
+ parent: issue.parent,
152
+ children: issue.children ? [...issue.children].sort() : undefined,
153
+ };
154
+ return quickHash(JSON.stringify(substantive));
155
+ }
156
+ /**
157
+ * Compute the set of edge keys from an issue's relationship fields
158
+ */
159
+ function issueEdgeKeys(issue) {
160
+ const keys = new Set();
161
+ // Legacy format: blocks/blockedBy string arrays
162
+ if (issue.blocks) {
163
+ for (const id of issue.blocks)
164
+ keys.add(`${issue.id}:${id}:blocks`);
165
+ }
166
+ if (issue.blockedBy) {
167
+ for (const id of issue.blockedBy)
168
+ keys.add(`${id}:${issue.id}:blocks`);
169
+ }
170
+ // Structured format (bd v0.49+): dependencies array with {issue_id, depends_on_id, type}
171
+ if (issue.dependencies) {
172
+ for (const dep of issue.dependencies) {
173
+ // dep.depends_on_id blocks dep.issue_id
174
+ keys.add(`${dep.depends_on_id}:${dep.issue_id}:blocks`);
175
+ }
176
+ }
177
+ if (issue.parent) {
178
+ keys.add(`${issue.parent}:${issue.id}:parent-child`);
179
+ }
180
+ if (issue.children) {
181
+ for (const id of issue.children)
182
+ keys.add(`${issue.id}:${id}:parent-child`);
183
+ }
184
+ return keys;
185
+ }
186
+ /**
187
+ * Diff current Beads state against cached hashes and emit change events.
188
+ * Called when file watcher detects a change.
189
+ */
190
+ async function diffAndEmit() {
191
+ if (!watchCallback)
192
+ return;
193
+ try {
194
+ const output = await execBd(['list', '--json']);
195
+ const issues = parseJson(output);
196
+ const currentIds = new Set();
197
+ const currentEdgeKeys = new Set();
198
+ for (const issue of issues) {
199
+ // Beads uses "tombstone" status for soft-deleted issues — treat as deleted
200
+ const isTombstone = issue.status === 'tombstone';
201
+ if (isTombstone) {
202
+ // Only emit 'deleted' if we previously knew about this issue
203
+ if (cachedHashes.has(issue.id)) {
204
+ watchCallback({
205
+ kind: 'node',
206
+ event: {
207
+ type: 'deleted',
208
+ nodeId: issue.id,
209
+ uri: `beads://./${issue.id}`,
210
+ timestamp: new Date().toISOString(),
211
+ },
212
+ });
213
+ cachedHashes.delete(issue.id);
214
+ }
215
+ continue;
216
+ }
217
+ currentIds.add(issue.id);
218
+ const hash = issueHashKey(issue);
219
+ const prevHash = cachedHashes.get(issue.id);
220
+ const providerNode = beadsIssueToProviderNode(issue);
221
+ if (!prevHash) {
222
+ // New issue
223
+ watchCallback({
224
+ kind: 'node',
225
+ event: {
226
+ type: 'created',
227
+ nodeId: issue.id,
228
+ uri: providerNode.uri,
229
+ node: providerNode,
230
+ timestamp: new Date().toISOString(),
231
+ },
232
+ });
233
+ }
234
+ else if (prevHash !== hash) {
235
+ // Changed issue — compute changed fields if possible
236
+ const event = {
237
+ type: 'updated',
238
+ nodeId: issue.id,
239
+ uri: providerNode.uri,
240
+ node: providerNode,
241
+ timestamp: new Date().toISOString(),
242
+ };
243
+ // We can report changed fields by comparing against cached data
244
+ // but we only store hashes, not full data. For field-level we'd
245
+ // need to cache full issue objects. For now, we report the node
246
+ // change without field detail — consumers can diff themselves.
247
+ watchCallback({ kind: 'node', event });
248
+ }
249
+ cachedHashes.set(issue.id, hash);
250
+ // Collect current edges
251
+ for (const key of issueEdgeKeys(issue)) {
252
+ currentEdgeKeys.add(key);
253
+ }
254
+ }
255
+ // Detect deleted issues
256
+ for (const [id] of cachedHashes) {
257
+ if (!currentIds.has(id)) {
258
+ watchCallback({
259
+ kind: 'node',
260
+ event: {
261
+ type: 'deleted',
262
+ nodeId: id,
263
+ uri: `beads://./${id}`,
264
+ timestamp: new Date().toISOString(),
265
+ },
266
+ });
267
+ cachedHashes.delete(id);
268
+ }
269
+ }
270
+ // Detect edge changes
271
+ // New edges
272
+ for (const key of currentEdgeKeys) {
273
+ if (!cachedEdgeKeys.has(key)) {
274
+ const [from, to, type] = key.split(':');
275
+ const event = {
276
+ type: 'created',
277
+ edge: { from, to, type },
278
+ sourceUri: `beads://./${from}`,
279
+ targetUri: `beads://./${to}`,
280
+ timestamp: new Date().toISOString(),
281
+ };
282
+ watchCallback({ kind: 'edge', event });
283
+ }
284
+ }
285
+ // Deleted edges
286
+ for (const key of cachedEdgeKeys) {
287
+ if (!currentEdgeKeys.has(key)) {
288
+ const [from, to, type] = key.split(':');
289
+ const event = {
290
+ type: 'deleted',
291
+ edge: { from, to, type },
292
+ sourceUri: `beads://./${from}`,
293
+ targetUri: `beads://./${to}`,
294
+ timestamp: new Date().toISOString(),
295
+ };
296
+ watchCallback({ kind: 'edge', event });
297
+ }
298
+ }
299
+ // Update cached edge state
300
+ cachedEdgeKeys.clear();
301
+ for (const key of currentEdgeKeys) {
302
+ cachedEdgeKeys.add(key);
303
+ }
304
+ }
305
+ catch {
306
+ // Resilient — log internally but don't crash the watcher
307
+ }
308
+ }
309
+ /**
310
+ * Handle a raw file change event with debouncing
311
+ */
312
+ function onFileChange() {
313
+ if (debounceTimer) {
314
+ clearTimeout(debounceTimer);
315
+ }
316
+ debounceTimer = setTimeout(() => {
317
+ debounceTimer = null;
318
+ void diffAndEmit();
319
+ }, watchDebounceMs);
320
+ }
321
+ /**
322
+ * Seed the cached hashes from current Beads state (so the first
323
+ * diff only emits genuine changes, not the entire existing dataset)
324
+ */
325
+ async function seedCache() {
326
+ try {
327
+ const output = await execBd(['list', '--json']);
328
+ const issues = parseJson(output);
329
+ cachedHashes.clear();
330
+ cachedEdgeKeys.clear();
331
+ for (const issue of issues) {
332
+ // Skip tombstoned (deleted) issues when seeding cache
333
+ if (issue.status === 'tombstone')
334
+ continue;
335
+ cachedHashes.set(issue.id, issueHashKey(issue));
336
+ for (const key of issueEdgeKeys(issue)) {
337
+ cachedEdgeKeys.add(key);
338
+ }
339
+ }
340
+ }
341
+ catch {
342
+ // If we can't seed, first diff will treat everything as 'created'
343
+ }
344
+ }
345
+ /**
346
+ * Shell-escape a single argument
347
+ */
348
+ function shellEscape(arg) {
349
+ // If arg contains spaces, quotes, or special shell chars, wrap in single quotes
350
+ // and escape any existing single quotes
351
+ if (/['\s"\\$`!]/.test(arg)) {
352
+ return `'${arg.replace(/'/g, "'\\''")}'`;
353
+ }
354
+ return arg;
355
+ }
356
+ /**
357
+ * Execute a bd CLI command
358
+ * @param args - Command arguments
359
+ * @param context - Optional operational context for per-call overrides (cwd, timeout)
360
+ */
361
+ async function execBd(args, context) {
362
+ const command = [executable, ...extraArgs, ...args.map(shellEscape)].join(' ');
363
+ try {
364
+ const { stdout } = await execAsync(command, {
365
+ cwd: context?.cwd ?? cwd,
366
+ timeout: context?.timeout ?? timeout,
367
+ env: { ...process.env },
368
+ });
369
+ return stdout.trim();
370
+ }
371
+ catch (error) {
372
+ const err = error;
373
+ if (err.code === 'ENOENT') {
374
+ throw new ProviderErrorClass('PROVIDER_ERROR', `Beads CLI not found: ${executable}`, 'beads');
375
+ }
376
+ if (err.killed) {
377
+ throw new ProviderErrorClass('TIMEOUT', `Command timed out: ${command}`, 'beads');
378
+ }
379
+ // Extract error details from stdout if available (bd returns JSON errors)
380
+ let errorMessage = err.message ?? 'Unknown error';
381
+ if (err.stdout) {
382
+ try {
383
+ const parsed = JSON.parse(err.stdout);
384
+ if (parsed.error) {
385
+ errorMessage = parsed.error;
386
+ }
387
+ }
388
+ catch {
389
+ // Not JSON, use stdout as-is if it has content
390
+ if (err.stdout.trim()) {
391
+ errorMessage = err.stdout.trim();
392
+ }
393
+ }
394
+ }
395
+ throw new ProviderErrorClass('OPERATION_FAILED', `Beads CLI error: ${errorMessage}`, 'beads', error instanceof Error ? error : undefined);
396
+ }
397
+ }
398
+ /**
399
+ * Parse JSON output from bd CLI
400
+ */
401
+ function parseJson(output) {
402
+ try {
403
+ return JSON.parse(output);
404
+ }
405
+ catch {
406
+ throw new ProviderErrorClass('PROVIDER_ERROR', 'Failed to parse Beads CLI output as JSON', 'beads');
407
+ }
408
+ }
409
+ return {
410
+ name: 'beads',
411
+ schemes: ['beads', 'bd'],
412
+ capabilities,
413
+ // =========================================================================
414
+ // URI Operations
415
+ // =========================================================================
416
+ parseUri(uri) {
417
+ // Check for beads:// or bd:// URI
418
+ const match = uri.match(BEADS_URI_PATTERN);
419
+ if (match) {
420
+ const scheme = match[1].toLowerCase();
421
+ const workspace = match[2] || '.';
422
+ const id = match[3];
423
+ return {
424
+ scheme,
425
+ workspace,
426
+ id,
427
+ isRelative: workspace === '.',
428
+ };
429
+ }
430
+ // Check for bare Beads ID
431
+ if (BEADS_ID_PATTERN.test(uri)) {
432
+ return {
433
+ scheme: 'beads',
434
+ workspace: '.',
435
+ id: uri,
436
+ isRelative: true,
437
+ };
438
+ }
439
+ return null;
440
+ },
441
+ buildUri(id, options) {
442
+ const workspace = options?.workspace ?? '.';
443
+ if (options?.relative) {
444
+ return id;
445
+ }
446
+ return `beads://${workspace}/${id}`;
447
+ },
448
+ isValidUri(uri) {
449
+ return this.parseUri(uri) !== null;
450
+ },
451
+ // =========================================================================
452
+ // CRUD Operations
453
+ // =========================================================================
454
+ async get(id, context) {
455
+ // Parse URI if full URI is passed
456
+ const parsed = this.parseUri(id);
457
+ const issueId = parsed?.id ?? id;
458
+ const workspace = parsed?.workspace ?? '.';
459
+ try {
460
+ const output = await execBd(['show', issueId, '--json'], context);
461
+ // bd show returns an array, take the first element
462
+ const issues = parseJson(output);
463
+ if (!issues || issues.length === 0) {
464
+ return null;
465
+ }
466
+ // Treat tombstoned (soft-deleted) issues as not found
467
+ if (issues[0].status === 'tombstone') {
468
+ return null;
469
+ }
470
+ return beadsIssueToProviderNode(issues[0], workspace);
471
+ }
472
+ catch (error) {
473
+ // Return null for not found, re-throw other errors
474
+ if (error instanceof ProviderErrorClass && error.code === 'OPERATION_FAILED') {
475
+ const message = error.message.toLowerCase();
476
+ if (message.includes('not found') ||
477
+ message.includes('does not exist') ||
478
+ message.includes('no issue found matching')) {
479
+ return null;
480
+ }
481
+ }
482
+ throw error;
483
+ }
484
+ },
485
+ async list(filter, context) {
486
+ const args = ['list', '--json'];
487
+ // Add filters if supported by bd CLI
488
+ if (filter?.status) {
489
+ args.push('--status', filter.status);
490
+ }
491
+ if (filter?.limit) {
492
+ args.push('--limit', String(filter.limit));
493
+ }
494
+ const output = await execBd(args, context);
495
+ const issues = parseJson(output);
496
+ return issues
497
+ .filter((issue) => issue.status !== 'tombstone')
498
+ .map((issue) => beadsIssueToProviderNode(issue));
499
+ },
500
+ async create(input, context) {
501
+ const args = ['create', input.title];
502
+ if (input.content) {
503
+ args.push('--description', input.content);
504
+ }
505
+ if (input.status) {
506
+ args.push('--status', input.status);
507
+ }
508
+ if (input.priority !== undefined) {
509
+ args.push('--priority', String(input.priority));
510
+ }
511
+ args.push('--json');
512
+ const output = await execBd(args, context);
513
+ const issue = parseJson(output);
514
+ return beadsIssueToProviderNode(issue);
515
+ },
516
+ async update(id, updates, context) {
517
+ // Parse URI if full URI is passed
518
+ const parsed = this.parseUri(id);
519
+ const issueId = parsed?.id ?? id;
520
+ const args = ['update', issueId];
521
+ if (updates.title) {
522
+ args.push('--title', updates.title);
523
+ }
524
+ if (updates.content) {
525
+ args.push('--description', updates.content);
526
+ }
527
+ if (updates.status) {
528
+ args.push('--status', updates.status);
529
+ }
530
+ if (updates.priority !== undefined) {
531
+ args.push('--priority', String(updates.priority));
532
+ }
533
+ args.push('--json');
534
+ const output = await execBd(args, context);
535
+ // bd update returns an array, take the first element
536
+ const issues = parseJson(output);
537
+ if (!issues || issues.length === 0) {
538
+ throw new ProviderErrorClass('OPERATION_FAILED', 'Update returned no results', 'beads');
539
+ }
540
+ return beadsIssueToProviderNode(issues[0]);
541
+ },
542
+ async delete(id, context) {
543
+ // Parse URI if full URI is passed
544
+ const parsed = this.parseUri(id);
545
+ const issueId = parsed?.id ?? id;
546
+ await execBd(['delete', issueId, '--force'], context);
547
+ },
548
+ // =========================================================================
549
+ // Search
550
+ // =========================================================================
551
+ async search(query, options) {
552
+ const args = ['search', query, '--json'];
553
+ if (options?.limit) {
554
+ args.push('--limit', String(options.limit));
555
+ }
556
+ const output = await execBd(args);
557
+ const issues = parseJson(output);
558
+ return issues
559
+ .filter((issue) => issue.status !== 'tombstone')
560
+ .map((issue) => beadsIssueToProviderNode(issue));
561
+ },
562
+ // =========================================================================
563
+ // RelationshipQueryable Implementation
564
+ // =========================================================================
565
+ async queryEdges(nodeId, options) {
566
+ // Parse URI if full URI is passed
567
+ const parsed = this.parseUri(nodeId);
568
+ const issueId = parsed?.id ?? nodeId;
569
+ try {
570
+ const output = await execBd(['show', issueId, '--json']);
571
+ const issues = parseJson(output);
572
+ if (!issues || issues.length === 0) {
573
+ return [];
574
+ }
575
+ const issue = issues[0];
576
+ // Tombstoned issues have no meaningful edges
577
+ if (issue.status === 'tombstone') {
578
+ return [];
579
+ }
580
+ let edges = [];
581
+ // --- Legacy format: blocks/blockedBy string arrays ---
582
+ if (issue.blocks && Array.isArray(issue.blocks)) {
583
+ for (const blockedId of issue.blocks) {
584
+ edges.push({ from: issueId, to: blockedId, type: 'blocks' });
585
+ }
586
+ }
587
+ if (issue.blockedBy && Array.isArray(issue.blockedBy)) {
588
+ for (const blockerId of issue.blockedBy) {
589
+ edges.push({ from: blockerId, to: issueId, type: 'blocks' });
590
+ }
591
+ }
592
+ // --- bd v0.49+ format from `bd show --json` ---
593
+ // `dependencies` = issues THIS issue depends on (they block this)
594
+ // Each element is a full issue object with an `id` field
595
+ if (issue.dependencies && Array.isArray(issue.dependencies)) {
596
+ for (const dep of issue.dependencies) {
597
+ if (dep.id) {
598
+ // Full object format from `bd show` — dep.id is the blocker
599
+ edges.push({ from: dep.id, to: issueId, type: 'blocks' });
600
+ }
601
+ else if (dep.depends_on_id && dep.issue_id) {
602
+ // Compact format from `bd list` — depends_on_id blocks issue_id
603
+ edges.push({ from: dep.depends_on_id, to: dep.issue_id, type: 'blocks' });
604
+ }
605
+ }
606
+ }
607
+ // `dependents` = issues that depend on THIS issue (this blocks them)
608
+ if (issue.dependents && Array.isArray(issue.dependents)) {
609
+ for (const dep of issue.dependents) {
610
+ if (dep.id) {
611
+ edges.push({ from: issueId, to: dep.id, type: 'blocks' });
612
+ }
613
+ }
614
+ }
615
+ // --- Parent/children ---
616
+ if (issue.parent) {
617
+ edges.push({ from: issue.parent, to: issueId, type: 'parent-child' });
618
+ }
619
+ if (issue.children && Array.isArray(issue.children)) {
620
+ for (const childId of issue.children) {
621
+ edges.push({ from: issueId, to: childId, type: 'parent-child' });
622
+ }
623
+ }
624
+ // Deduplicate edges (multiple formats may report the same relationship)
625
+ const seen = new Set();
626
+ edges = edges.filter((edge) => {
627
+ const key = `${edge.from}:${edge.to}:${edge.type}`;
628
+ if (seen.has(key))
629
+ return false;
630
+ seen.add(key);
631
+ return true;
632
+ });
633
+ // Apply filters if specified
634
+ if (options?.edgeType) {
635
+ edges = filterEdgesByType(edges, options.edgeType);
636
+ }
637
+ if (options?.direction) {
638
+ edges = filterEdgesByDirection(edges, issueId, options.direction);
639
+ }
640
+ if (options?.limit && edges.length > options.limit) {
641
+ edges = edges.slice(0, options.limit);
642
+ }
643
+ return edges;
644
+ }
645
+ catch (error) {
646
+ // Return empty for not found, re-throw other errors
647
+ if (error instanceof ProviderErrorClass && error.code === 'OPERATION_FAILED') {
648
+ const message = error.message.toLowerCase();
649
+ if (message.includes('not found') ||
650
+ message.includes('does not exist') ||
651
+ message.includes('no issue found matching')) {
652
+ return [];
653
+ }
654
+ }
655
+ throw error;
656
+ }
657
+ },
658
+ supportedEdgeTypes() {
659
+ return [
660
+ { type: 'blocks', canQuery: true, canCreate: true, canDelete: true },
661
+ { type: 'parent-child', canQuery: true, canCreate: true, canDelete: true },
662
+ ];
663
+ },
664
+ // =========================================================================
665
+ // Watchable Implementation (only functional when watchPath is configured)
666
+ // =========================================================================
667
+ watchGranularity: {
668
+ // Beads diffs at the node level. We can detect which nodes changed
669
+ // but don't track individual field changes (would require caching
670
+ // full issue objects rather than just hashes).
671
+ reportsChangedFields: false,
672
+ reportsPreviousValues: false,
673
+ // Beads embeds relationships in the node (blocks/blockedBy/parent/children).
674
+ // We extract and diff these separately, so we can emit edge events.
675
+ reportsEdgeChanges: true,
676
+ mechanism: 'file-watch',
677
+ },
678
+ startWatching(callback) {
679
+ if (!watchPath) {
680
+ return; // Watching not configured — silently no-op
681
+ }
682
+ // Replace callback if already watching
683
+ watchCallback = callback;
684
+ if (fileWatcher) {
685
+ return; // Already watching, just updated callback
686
+ }
687
+ // Seed cache before starting watcher so we only emit real changes
688
+ void seedCache().then(() => {
689
+ if (!watchCallback)
690
+ return; // Stopped before seed completed
691
+ fileWatcher = chokidar.watch(watchPath, {
692
+ ignoreInitial: true,
693
+ persistent: true,
694
+ awaitWriteFinish: {
695
+ stabilityThreshold: 100,
696
+ pollInterval: 20,
697
+ },
698
+ });
699
+ fileWatcher.on('add', onFileChange);
700
+ fileWatcher.on('change', onFileChange);
701
+ fileWatcher.on('unlink', onFileChange);
702
+ fileWatcher.on('error', () => {
703
+ // Resilient — continue watching despite transient errors
704
+ });
705
+ });
706
+ },
707
+ stopWatching() {
708
+ watchCallback = null;
709
+ if (debounceTimer) {
710
+ clearTimeout(debounceTimer);
711
+ debounceTimer = null;
712
+ }
713
+ if (fileWatcher) {
714
+ void fileWatcher.close();
715
+ fileWatcher = null;
716
+ }
717
+ },
718
+ get isWatching() {
719
+ return fileWatcher !== null && watchCallback !== null;
720
+ },
721
+ // =========================================================================
722
+ // TaskManageable Implementation
723
+ // =========================================================================
724
+ taskCapabilities: {
725
+ actions: ['start', 'complete', 'block', 'reopen', 'close'],
726
+ supportsAssignment: true,
727
+ supportsReadyQuery: true,
728
+ statusModel: ['open', 'in_progress', 'blocked', 'closed'],
729
+ },
730
+ async transitionTask(id, action, context) {
731
+ const statusMap = {
732
+ start: 'in_progress',
733
+ complete: 'closed',
734
+ block: 'blocked',
735
+ reopen: 'open',
736
+ close: 'closed',
737
+ };
738
+ const targetStatus = statusMap[action];
739
+ if (!targetStatus) {
740
+ throw new ProviderErrorClass('NOT_SUPPORTED', `Unsupported task action: ${action}`, 'beads');
741
+ }
742
+ const parsed = this.parseUri(id);
743
+ const issueId = parsed?.id ?? id;
744
+ // Validate transition is allowed from current state
745
+ const current = await this.get(issueId, context);
746
+ if (current) {
747
+ const currentStatus = current.status ?? 'open';
748
+ const allowed = validActionsForStatus(currentStatus);
749
+ if (!allowed.includes(action)) {
750
+ throw new ProviderErrorClass('NOT_SUPPORTED', `Cannot ${action} an issue in '${currentStatus}' state. Valid actions: ${allowed.join(', ')}`, 'beads');
751
+ }
752
+ }
753
+ const output = await execBd(['update', issueId, '--status', targetStatus, '--json'], context);
754
+ const issues = parseJson(output);
755
+ if (!issues || issues.length === 0) {
756
+ throw new ProviderErrorClass('OPERATION_FAILED', 'Transition returned no results', 'beads');
757
+ }
758
+ return beadsIssueToProviderNode(issues[0]);
759
+ },
760
+ async readyTasks(options, context) {
761
+ const output = await execBd(['list', '--json'], context);
762
+ const issues = parseJson(output);
763
+ const readyIssues = [];
764
+ for (const issue of issues) {
765
+ // Skip tombstoned and non-open issues
766
+ if (issue.status === 'tombstone' || issue.status !== 'open')
767
+ continue;
768
+ // Apply tag filter
769
+ if (options?.tags) {
770
+ const issueTags = issue.tags ?? [];
771
+ if (!options.tags.every((t) => issueTags.includes(t)))
772
+ continue;
773
+ }
774
+ // Apply priority filter
775
+ if (options?.priority !== undefined) {
776
+ const normalized = mapPriority(issue.priority);
777
+ if (normalized === undefined || normalized > options.priority)
778
+ continue;
779
+ }
780
+ // Apply assignee filter
781
+ if (options?.assignee) {
782
+ if (issue.assignee !== options.assignee)
783
+ continue;
784
+ }
785
+ // Check for active blockers
786
+ let hasActiveBlocker = false;
787
+ // Legacy format: blockedBy
788
+ if (issue.blockedBy && issue.blockedBy.length > 0) {
789
+ // Need to check if blockers are still active
790
+ for (const blockerId of issue.blockedBy) {
791
+ try {
792
+ const blockerOutput = await execBd(['show', blockerId, '--json'], context);
793
+ const blockerIssues = parseJson(blockerOutput);
794
+ if (blockerIssues?.[0] &&
795
+ blockerIssues[0].status !== 'closed' &&
796
+ blockerIssues[0].status !== 'tombstone') {
797
+ hasActiveBlocker = true;
798
+ break;
799
+ }
800
+ }
801
+ catch {
802
+ // If we can't resolve the blocker, assume it's active
803
+ hasActiveBlocker = true;
804
+ break;
805
+ }
806
+ }
807
+ }
808
+ // Structured format (bd v0.49+): dependencies
809
+ if (!hasActiveBlocker && issue.dependencies && issue.dependencies.length > 0) {
810
+ for (const dep of issue.dependencies) {
811
+ const depId = dep.id ?? dep.depends_on_id;
812
+ if (!depId)
813
+ continue;
814
+ try {
815
+ const depOutput = await execBd(['show', depId, '--json'], context);
816
+ const depIssues = parseJson(depOutput);
817
+ if (depIssues?.[0] &&
818
+ depIssues[0].status !== 'closed' &&
819
+ depIssues[0].status !== 'tombstone') {
820
+ hasActiveBlocker = true;
821
+ break;
822
+ }
823
+ }
824
+ catch {
825
+ hasActiveBlocker = true;
826
+ break;
827
+ }
828
+ }
829
+ }
830
+ if (!hasActiveBlocker) {
831
+ readyIssues.push(beadsIssueToProviderNode(issue));
832
+ }
833
+ }
834
+ // Sort by priority (lower number = higher priority)
835
+ readyIssues.sort((a, b) => {
836
+ const aPriority = a.priority ?? Infinity;
837
+ const bPriority = b.priority ?? Infinity;
838
+ return aPriority - bPriority;
839
+ });
840
+ // Apply limit
841
+ if (options?.limit && readyIssues.length > options.limit) {
842
+ return readyIssues.slice(0, options.limit);
843
+ }
844
+ return readyIssues;
845
+ },
846
+ async assignTask(id, assignee, context) {
847
+ const parsed = this.parseUri(id);
848
+ const issueId = parsed?.id ?? id;
849
+ const output = await execBd(['update', issueId, '--assignee', assignee, '--json'], context);
850
+ const issues = parseJson(output);
851
+ if (!issues || issues.length === 0) {
852
+ throw new ProviderErrorClass('OPERATION_FAILED', 'Assign returned no results', 'beads');
853
+ }
854
+ return beadsIssueToProviderNode(issues[0]);
855
+ },
856
+ async validActions(id, context) {
857
+ const node = await this.get(id, context);
858
+ if (!node) {
859
+ throw new ProviderErrorClass('NOT_FOUND', `Issue not found: ${id}`, 'beads');
860
+ }
861
+ return validActionsForStatus(node.status ?? 'open');
862
+ },
863
+ };
864
+ }
865
+ //# sourceMappingURL=beads.js.map