opentasks 0.0.4 → 0.0.6

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 (373) hide show
  1. package/README.md +40 -0
  2. package/dist/cli.d.ts.map +1 -1
  3. package/dist/cli.js +183 -21
  4. package/dist/cli.js.map +1 -1
  5. package/dist/client/client.d.ts.map +1 -1
  6. package/dist/client/client.js +14 -1
  7. package/dist/client/client.js.map +1 -1
  8. package/dist/config/schema.d.ts +139 -3
  9. package/dist/config/schema.d.ts.map +1 -1
  10. package/dist/config/schema.js +118 -2
  11. package/dist/config/schema.js.map +1 -1
  12. package/dist/core/discover.d.ts.map +1 -1
  13. package/dist/core/discover.js +55 -39
  14. package/dist/core/discover.js.map +1 -1
  15. package/dist/core/init.js +1 -1
  16. package/dist/core/init.js.map +1 -1
  17. package/dist/core/merge-driver.d.ts +6 -2
  18. package/dist/core/merge-driver.d.ts.map +1 -1
  19. package/dist/core/merge-driver.js +11 -7
  20. package/dist/core/merge-driver.js.map +1 -1
  21. package/dist/core/worktree.js +1 -1
  22. package/dist/core/worktree.js.map +1 -1
  23. package/dist/daemon/entire-linker.d.ts.map +1 -1
  24. package/dist/daemon/entire-linker.js +48 -42
  25. package/dist/daemon/entire-linker.js.map +1 -1
  26. package/dist/daemon/entire-watcher.d.ts +12 -1
  27. package/dist/daemon/entire-watcher.d.ts.map +1 -1
  28. package/dist/daemon/entire-watcher.js +34 -3
  29. package/dist/daemon/entire-watcher.js.map +1 -1
  30. package/dist/daemon/ipc.d.ts +9 -1
  31. package/dist/daemon/ipc.d.ts.map +1 -1
  32. package/dist/daemon/ipc.js +45 -2
  33. package/dist/daemon/ipc.js.map +1 -1
  34. package/dist/daemon/lifecycle.d.ts.map +1 -1
  35. package/dist/daemon/lifecycle.js +77 -3
  36. package/dist/daemon/lifecycle.js.map +1 -1
  37. package/dist/daemon/location-state.d.ts +3 -0
  38. package/dist/daemon/location-state.d.ts.map +1 -1
  39. package/dist/daemon/location-state.js +49 -2
  40. package/dist/daemon/location-state.js.map +1 -1
  41. package/dist/daemon/methods/watch.d.ts +23 -0
  42. package/dist/daemon/methods/watch.d.ts.map +1 -0
  43. package/dist/daemon/methods/watch.js +172 -0
  44. package/dist/daemon/methods/watch.js.map +1 -0
  45. package/dist/daemon/registry.d.ts.map +1 -1
  46. package/dist/daemon/registry.js +2 -1
  47. package/dist/daemon/registry.js.map +1 -1
  48. package/dist/entire/index.d.ts +1 -0
  49. package/dist/entire/index.d.ts.map +1 -1
  50. package/dist/entire/index.js.map +1 -1
  51. package/dist/entire/store/native-store.d.ts +1 -1
  52. package/dist/entire/store/native-store.d.ts.map +1 -1
  53. package/dist/entire/store/provider-types.d.ts +78 -0
  54. package/dist/entire/store/provider-types.d.ts.map +1 -0
  55. package/dist/entire/store/provider-types.js +12 -0
  56. package/dist/entire/store/provider-types.js.map +1 -0
  57. package/dist/graph/expansion.d.ts +3 -1
  58. package/dist/graph/expansion.d.ts.map +1 -1
  59. package/dist/graph/expansion.js +32 -2
  60. package/dist/graph/expansion.js.map +1 -1
  61. package/dist/graph/git-graph-syncer.d.ts +72 -0
  62. package/dist/graph/git-graph-syncer.d.ts.map +1 -0
  63. package/dist/graph/git-graph-syncer.js +205 -0
  64. package/dist/graph/git-graph-syncer.js.map +1 -0
  65. package/dist/graph/store.d.ts +4 -0
  66. package/dist/graph/store.d.ts.map +1 -1
  67. package/dist/graph/store.js +97 -2
  68. package/dist/graph/store.js.map +1 -1
  69. package/dist/providers/entire.d.ts +34 -69
  70. package/dist/providers/entire.d.ts.map +1 -1
  71. package/dist/providers/entire.js +63 -9
  72. package/dist/providers/entire.js.map +1 -1
  73. package/dist/providers/from-config.d.ts +3 -0
  74. package/dist/providers/from-config.d.ts.map +1 -1
  75. package/dist/providers/from-config.js +45 -20
  76. package/dist/providers/from-config.js.map +1 -1
  77. package/dist/providers/global.d.ts +2 -1
  78. package/dist/providers/global.d.ts.map +1 -1
  79. package/dist/providers/global.js +52 -1
  80. package/dist/providers/global.js.map +1 -1
  81. package/dist/providers/index.d.ts +3 -0
  82. package/dist/providers/index.d.ts.map +1 -1
  83. package/dist/providers/index.js +6 -0
  84. package/dist/providers/index.js.map +1 -1
  85. package/dist/providers/map-client-factory.d.ts +55 -0
  86. package/dist/providers/map-client-factory.d.ts.map +1 -0
  87. package/dist/providers/map-client-factory.js +123 -0
  88. package/dist/providers/map-client-factory.js.map +1 -0
  89. package/dist/providers/map-event-bridge.d.ts +146 -0
  90. package/dist/providers/map-event-bridge.d.ts.map +1 -0
  91. package/dist/providers/map-event-bridge.js +208 -0
  92. package/dist/providers/map-event-bridge.js.map +1 -0
  93. package/dist/providers/map.d.ts +115 -0
  94. package/dist/providers/map.d.ts.map +1 -0
  95. package/dist/providers/map.js +376 -0
  96. package/dist/providers/map.js.map +1 -0
  97. package/dist/tracking/index.d.ts +0 -4
  98. package/dist/tracking/index.d.ts.map +1 -1
  99. package/dist/tracking/index.js +0 -2
  100. package/dist/tracking/index.js.map +1 -1
  101. package/dist/tracking/transcript-extractor.d.ts +0 -6
  102. package/dist/tracking/transcript-extractor.d.ts.map +1 -1
  103. package/dist/tracking/transcript-extractor.js +3 -12
  104. package/dist/tracking/transcript-extractor.js.map +1 -1
  105. package/package.json +3 -1
  106. package/dist/__tests__/cli-tools.test.d.ts +0 -8
  107. package/dist/__tests__/cli-tools.test.d.ts.map +0 -1
  108. package/dist/__tests__/cli-tools.test.js +0 -546
  109. package/dist/__tests__/cli-tools.test.js.map +0 -1
  110. package/dist/__tests__/cli.test.d.ts +0 -5
  111. package/dist/__tests__/cli.test.d.ts.map +0 -1
  112. package/dist/__tests__/cli.test.js +0 -77
  113. package/dist/__tests__/cli.test.js.map +0 -1
  114. package/dist/__tests__/p1-p3-gaps.test.d.ts +0 -2
  115. package/dist/__tests__/p1-p3-gaps.test.d.ts.map +0 -1
  116. package/dist/__tests__/p1-p3-gaps.test.js +0 -463
  117. package/dist/__tests__/p1-p3-gaps.test.js.map +0 -1
  118. package/dist/client/__tests__/client-crud.test.d.ts +0 -7
  119. package/dist/client/__tests__/client-crud.test.d.ts.map +0 -1
  120. package/dist/client/__tests__/client-crud.test.js +0 -404
  121. package/dist/client/__tests__/client-crud.test.js.map +0 -1
  122. package/dist/client/__tests__/client.test.d.ts +0 -5
  123. package/dist/client/__tests__/client.test.d.ts.map +0 -1
  124. package/dist/client/__tests__/client.test.js +0 -518
  125. package/dist/client/__tests__/client.test.js.map +0 -1
  126. package/dist/config/__tests__/defaults.test.d.ts +0 -2
  127. package/dist/config/__tests__/defaults.test.d.ts.map +0 -1
  128. package/dist/config/__tests__/defaults.test.js +0 -57
  129. package/dist/config/__tests__/defaults.test.js.map +0 -1
  130. package/dist/config/__tests__/env.test.d.ts +0 -2
  131. package/dist/config/__tests__/env.test.d.ts.map +0 -1
  132. package/dist/config/__tests__/env.test.js +0 -136
  133. package/dist/config/__tests__/env.test.js.map +0 -1
  134. package/dist/config/__tests__/index.test.d.ts +0 -2
  135. package/dist/config/__tests__/index.test.d.ts.map +0 -1
  136. package/dist/config/__tests__/index.test.js +0 -113
  137. package/dist/config/__tests__/index.test.js.map +0 -1
  138. package/dist/config/__tests__/loader.test.d.ts +0 -2
  139. package/dist/config/__tests__/loader.test.d.ts.map +0 -1
  140. package/dist/config/__tests__/loader.test.js +0 -128
  141. package/dist/config/__tests__/loader.test.js.map +0 -1
  142. package/dist/config/__tests__/merge.test.d.ts +0 -2
  143. package/dist/config/__tests__/merge.test.d.ts.map +0 -1
  144. package/dist/config/__tests__/merge.test.js +0 -79
  145. package/dist/config/__tests__/merge.test.js.map +0 -1
  146. package/dist/config/__tests__/schema.test.d.ts +0 -2
  147. package/dist/config/__tests__/schema.test.d.ts.map +0 -1
  148. package/dist/config/__tests__/schema.test.js +0 -300
  149. package/dist/config/__tests__/schema.test.js.map +0 -1
  150. package/dist/core/__tests__/conditional-redirects.test.d.ts +0 -2
  151. package/dist/core/__tests__/conditional-redirects.test.d.ts.map +0 -1
  152. package/dist/core/__tests__/conditional-redirects.test.js +0 -83
  153. package/dist/core/__tests__/conditional-redirects.test.js.map +0 -1
  154. package/dist/core/__tests__/connections.test.d.ts +0 -2
  155. package/dist/core/__tests__/connections.test.d.ts.map +0 -1
  156. package/dist/core/__tests__/connections.test.js +0 -158
  157. package/dist/core/__tests__/connections.test.js.map +0 -1
  158. package/dist/core/__tests__/hash.test.d.ts +0 -2
  159. package/dist/core/__tests__/hash.test.d.ts.map +0 -1
  160. package/dist/core/__tests__/hash.test.js +0 -139
  161. package/dist/core/__tests__/hash.test.js.map +0 -1
  162. package/dist/core/__tests__/id.test.d.ts +0 -2
  163. package/dist/core/__tests__/id.test.d.ts.map +0 -1
  164. package/dist/core/__tests__/id.test.js +0 -142
  165. package/dist/core/__tests__/id.test.js.map +0 -1
  166. package/dist/core/__tests__/location.test.d.ts +0 -2
  167. package/dist/core/__tests__/location.test.d.ts.map +0 -1
  168. package/dist/core/__tests__/location.test.js +0 -77
  169. package/dist/core/__tests__/location.test.js.map +0 -1
  170. package/dist/core/__tests__/merge-driver.test.d.ts +0 -2
  171. package/dist/core/__tests__/merge-driver.test.d.ts.map +0 -1
  172. package/dist/core/__tests__/merge-driver.test.js +0 -218
  173. package/dist/core/__tests__/merge-driver.test.js.map +0 -1
  174. package/dist/core/__tests__/redirects.test.d.ts +0 -2
  175. package/dist/core/__tests__/redirects.test.d.ts.map +0 -1
  176. package/dist/core/__tests__/redirects.test.js +0 -123
  177. package/dist/core/__tests__/redirects.test.js.map +0 -1
  178. package/dist/core/__tests__/resolve-location-target.test.d.ts +0 -8
  179. package/dist/core/__tests__/resolve-location-target.test.d.ts.map +0 -1
  180. package/dist/core/__tests__/resolve-location-target.test.js +0 -303
  181. package/dist/core/__tests__/resolve-location-target.test.js.map +0 -1
  182. package/dist/core/__tests__/uri.test.d.ts +0 -2
  183. package/dist/core/__tests__/uri.test.d.ts.map +0 -1
  184. package/dist/core/__tests__/uri.test.js +0 -159
  185. package/dist/core/__tests__/uri.test.js.map +0 -1
  186. package/dist/core/__tests__/worktree.test.d.ts +0 -2
  187. package/dist/core/__tests__/worktree.test.d.ts.map +0 -1
  188. package/dist/core/__tests__/worktree.test.js +0 -120
  189. package/dist/core/__tests__/worktree.test.js.map +0 -1
  190. package/dist/daemon/__tests__/flush.test.d.ts +0 -5
  191. package/dist/daemon/__tests__/flush.test.d.ts.map +0 -1
  192. package/dist/daemon/__tests__/flush.test.js +0 -213
  193. package/dist/daemon/__tests__/flush.test.js.map +0 -1
  194. package/dist/daemon/__tests__/integration.test.d.ts +0 -7
  195. package/dist/daemon/__tests__/integration.test.d.ts.map +0 -1
  196. package/dist/daemon/__tests__/integration.test.js +0 -276
  197. package/dist/daemon/__tests__/integration.test.js.map +0 -1
  198. package/dist/daemon/__tests__/ipc.test.d.ts +0 -5
  199. package/dist/daemon/__tests__/ipc.test.d.ts.map +0 -1
  200. package/dist/daemon/__tests__/ipc.test.js +0 -314
  201. package/dist/daemon/__tests__/ipc.test.js.map +0 -1
  202. package/dist/daemon/__tests__/lifecycle.test.d.ts +0 -5
  203. package/dist/daemon/__tests__/lifecycle.test.d.ts.map +0 -1
  204. package/dist/daemon/__tests__/lifecycle.test.js +0 -301
  205. package/dist/daemon/__tests__/lifecycle.test.js.map +0 -1
  206. package/dist/daemon/__tests__/lock.test.d.ts +0 -5
  207. package/dist/daemon/__tests__/lock.test.d.ts.map +0 -1
  208. package/dist/daemon/__tests__/lock.test.js +0 -192
  209. package/dist/daemon/__tests__/lock.test.js.map +0 -1
  210. package/dist/daemon/__tests__/methods/graph.test.d.ts +0 -5
  211. package/dist/daemon/__tests__/methods/graph.test.d.ts.map +0 -1
  212. package/dist/daemon/__tests__/methods/graph.test.js +0 -309
  213. package/dist/daemon/__tests__/methods/graph.test.js.map +0 -1
  214. package/dist/daemon/__tests__/methods/provider.test.d.ts +0 -7
  215. package/dist/daemon/__tests__/methods/provider.test.d.ts.map +0 -1
  216. package/dist/daemon/__tests__/methods/provider.test.js +0 -181
  217. package/dist/daemon/__tests__/methods/provider.test.js.map +0 -1
  218. package/dist/daemon/__tests__/methods/tools.test.d.ts +0 -5
  219. package/dist/daemon/__tests__/methods/tools.test.d.ts.map +0 -1
  220. package/dist/daemon/__tests__/methods/tools.test.js +0 -587
  221. package/dist/daemon/__tests__/methods/tools.test.js.map +0 -1
  222. package/dist/daemon/__tests__/multi-location.test.d.ts +0 -8
  223. package/dist/daemon/__tests__/multi-location.test.d.ts.map +0 -1
  224. package/dist/daemon/__tests__/multi-location.test.js +0 -669
  225. package/dist/daemon/__tests__/multi-location.test.js.map +0 -1
  226. package/dist/daemon/__tests__/registry.test.d.ts +0 -5
  227. package/dist/daemon/__tests__/registry.test.d.ts.map +0 -1
  228. package/dist/daemon/__tests__/registry.test.js +0 -208
  229. package/dist/daemon/__tests__/registry.test.js.map +0 -1
  230. package/dist/daemon/__tests__/watcher.test.d.ts +0 -5
  231. package/dist/daemon/__tests__/watcher.test.d.ts.map +0 -1
  232. package/dist/daemon/__tests__/watcher.test.js +0 -234
  233. package/dist/daemon/__tests__/watcher.test.js.map +0 -1
  234. package/dist/daemon/methods/__tests__/graph.test.d.ts +0 -5
  235. package/dist/daemon/methods/__tests__/graph.test.d.ts.map +0 -1
  236. package/dist/daemon/methods/__tests__/graph.test.js +0 -274
  237. package/dist/daemon/methods/__tests__/graph.test.js.map +0 -1
  238. package/dist/daemon/methods/__tests__/provider.test.d.ts +0 -5
  239. package/dist/daemon/methods/__tests__/provider.test.d.ts.map +0 -1
  240. package/dist/daemon/methods/__tests__/provider.test.js +0 -184
  241. package/dist/daemon/methods/__tests__/provider.test.js.map +0 -1
  242. package/dist/daemon/methods/__tests__/tools.test.d.ts +0 -5
  243. package/dist/daemon/methods/__tests__/tools.test.d.ts.map +0 -1
  244. package/dist/daemon/methods/__tests__/tools.test.js +0 -295
  245. package/dist/daemon/methods/__tests__/tools.test.js.map +0 -1
  246. package/dist/graph/__tests__/EdgeTypeRegistry.test.d.ts +0 -2
  247. package/dist/graph/__tests__/EdgeTypeRegistry.test.d.ts.map +0 -1
  248. package/dist/graph/__tests__/EdgeTypeRegistry.test.js +0 -212
  249. package/dist/graph/__tests__/EdgeTypeRegistry.test.js.map +0 -1
  250. package/dist/graph/__tests__/FederatedGraph.test.d.ts +0 -2
  251. package/dist/graph/__tests__/FederatedGraph.test.d.ts.map +0 -1
  252. package/dist/graph/__tests__/FederatedGraph.test.js +0 -661
  253. package/dist/graph/__tests__/FederatedGraph.test.js.map +0 -1
  254. package/dist/graph/__tests__/GraphologyAdapter.test.d.ts +0 -2
  255. package/dist/graph/__tests__/GraphologyAdapter.test.d.ts.map +0 -1
  256. package/dist/graph/__tests__/GraphologyAdapter.test.js +0 -326
  257. package/dist/graph/__tests__/GraphologyAdapter.test.js.map +0 -1
  258. package/dist/graph/__tests__/HydratingFederatedGraph.test.d.ts +0 -2
  259. package/dist/graph/__tests__/HydratingFederatedGraph.test.d.ts.map +0 -1
  260. package/dist/graph/__tests__/HydratingFederatedGraph.test.js +0 -587
  261. package/dist/graph/__tests__/HydratingFederatedGraph.test.js.map +0 -1
  262. package/dist/graph/__tests__/debounce.test.d.ts +0 -5
  263. package/dist/graph/__tests__/debounce.test.d.ts.map +0 -1
  264. package/dist/graph/__tests__/debounce.test.js +0 -195
  265. package/dist/graph/__tests__/debounce.test.js.map +0 -1
  266. package/dist/graph/__tests__/edge-cases.test.d.ts +0 -8
  267. package/dist/graph/__tests__/edge-cases.test.d.ts.map +0 -1
  268. package/dist/graph/__tests__/edge-cases.test.js +0 -472
  269. package/dist/graph/__tests__/edge-cases.test.js.map +0 -1
  270. package/dist/graph/__tests__/expansion.test.d.ts +0 -2
  271. package/dist/graph/__tests__/expansion.test.d.ts.map +0 -1
  272. package/dist/graph/__tests__/expansion.test.js +0 -105
  273. package/dist/graph/__tests__/expansion.test.js.map +0 -1
  274. package/dist/graph/__tests__/provider-store.test.d.ts +0 -5
  275. package/dist/graph/__tests__/provider-store.test.d.ts.map +0 -1
  276. package/dist/graph/__tests__/provider-store.test.js +0 -791
  277. package/dist/graph/__tests__/provider-store.test.js.map +0 -1
  278. package/dist/graph/__tests__/query.test.d.ts +0 -5
  279. package/dist/graph/__tests__/query.test.d.ts.map +0 -1
  280. package/dist/graph/__tests__/query.test.js +0 -774
  281. package/dist/graph/__tests__/query.test.js.map +0 -1
  282. package/dist/graph/__tests__/store.test.d.ts +0 -5
  283. package/dist/graph/__tests__/store.test.d.ts.map +0 -1
  284. package/dist/graph/__tests__/store.test.js +0 -489
  285. package/dist/graph/__tests__/store.test.js.map +0 -1
  286. package/dist/graph/__tests__/sync.test.d.ts +0 -5
  287. package/dist/graph/__tests__/sync.test.d.ts.map +0 -1
  288. package/dist/graph/__tests__/sync.test.js +0 -129
  289. package/dist/graph/__tests__/sync.test.js.map +0 -1
  290. package/dist/graph/__tests__/validation.test.d.ts +0 -2
  291. package/dist/graph/__tests__/validation.test.d.ts.map +0 -1
  292. package/dist/graph/__tests__/validation.test.js +0 -521
  293. package/dist/graph/__tests__/validation.test.js.map +0 -1
  294. package/dist/providers/__tests__/beads.test.d.ts +0 -5
  295. package/dist/providers/__tests__/beads.test.d.ts.map +0 -1
  296. package/dist/providers/__tests__/beads.test.js +0 -591
  297. package/dist/providers/__tests__/beads.test.js.map +0 -1
  298. package/dist/providers/__tests__/claude-tasks.test.d.ts +0 -5
  299. package/dist/providers/__tests__/claude-tasks.test.d.ts.map +0 -1
  300. package/dist/providers/__tests__/claude-tasks.test.js +0 -392
  301. package/dist/providers/__tests__/claude-tasks.test.js.map +0 -1
  302. package/dist/providers/__tests__/from-config.test.d.ts +0 -5
  303. package/dist/providers/__tests__/from-config.test.d.ts.map +0 -1
  304. package/dist/providers/__tests__/from-config.test.js +0 -152
  305. package/dist/providers/__tests__/from-config.test.js.map +0 -1
  306. package/dist/providers/__tests__/materialization.test.d.ts +0 -5
  307. package/dist/providers/__tests__/materialization.test.d.ts.map +0 -1
  308. package/dist/providers/__tests__/materialization.test.js +0 -407
  309. package/dist/providers/__tests__/materialization.test.js.map +0 -1
  310. package/dist/providers/__tests__/native.test.d.ts +0 -5
  311. package/dist/providers/__tests__/native.test.d.ts.map +0 -1
  312. package/dist/providers/__tests__/native.test.js +0 -566
  313. package/dist/providers/__tests__/native.test.js.map +0 -1
  314. package/dist/providers/__tests__/registry.test.d.ts +0 -5
  315. package/dist/providers/__tests__/registry.test.d.ts.map +0 -1
  316. package/dist/providers/__tests__/registry.test.js +0 -183
  317. package/dist/providers/__tests__/registry.test.js.map +0 -1
  318. package/dist/providers/traits/__tests__/RelationshipQueryable.test.d.ts +0 -2
  319. package/dist/providers/traits/__tests__/RelationshipQueryable.test.d.ts.map +0 -1
  320. package/dist/providers/traits/__tests__/RelationshipQueryable.test.js +0 -169
  321. package/dist/providers/traits/__tests__/RelationshipQueryable.test.js.map +0 -1
  322. package/dist/providers/traits/__tests__/TaskManageable.test.d.ts +0 -2
  323. package/dist/providers/traits/__tests__/TaskManageable.test.d.ts.map +0 -1
  324. package/dist/providers/traits/__tests__/TaskManageable.test.js +0 -172
  325. package/dist/providers/traits/__tests__/TaskManageable.test.js.map +0 -1
  326. package/dist/schema/__tests__/validation.test.d.ts +0 -2
  327. package/dist/schema/__tests__/validation.test.d.ts.map +0 -1
  328. package/dist/schema/__tests__/validation.test.js +0 -241
  329. package/dist/schema/__tests__/validation.test.js.map +0 -1
  330. package/dist/storage/__tests__/atomic-write.test.d.ts +0 -5
  331. package/dist/storage/__tests__/atomic-write.test.d.ts.map +0 -1
  332. package/dist/storage/__tests__/atomic-write.test.js +0 -170
  333. package/dist/storage/__tests__/atomic-write.test.js.map +0 -1
  334. package/dist/storage/__tests__/file-lock.test.d.ts +0 -2
  335. package/dist/storage/__tests__/file-lock.test.d.ts.map +0 -1
  336. package/dist/storage/__tests__/file-lock.test.js +0 -89
  337. package/dist/storage/__tests__/file-lock.test.js.map +0 -1
  338. package/dist/storage/__tests__/jsonl.test.d.ts +0 -2
  339. package/dist/storage/__tests__/jsonl.test.d.ts.map +0 -1
  340. package/dist/storage/__tests__/jsonl.test.js +0 -228
  341. package/dist/storage/__tests__/jsonl.test.js.map +0 -1
  342. package/dist/storage/__tests__/locked-writer.test.d.ts +0 -2
  343. package/dist/storage/__tests__/locked-writer.test.d.ts.map +0 -1
  344. package/dist/storage/__tests__/locked-writer.test.js +0 -109
  345. package/dist/storage/__tests__/locked-writer.test.js.map +0 -1
  346. package/dist/storage/__tests__/sqlite.test.d.ts +0 -2
  347. package/dist/storage/__tests__/sqlite.test.d.ts.map +0 -1
  348. package/dist/storage/__tests__/sqlite.test.js +0 -470
  349. package/dist/storage/__tests__/sqlite.test.js.map +0 -1
  350. package/dist/tools/__tests__/annotate.test.d.ts +0 -5
  351. package/dist/tools/__tests__/annotate.test.d.ts.map +0 -1
  352. package/dist/tools/__tests__/annotate.test.js +0 -314
  353. package/dist/tools/__tests__/annotate.test.js.map +0 -1
  354. package/dist/tools/__tests__/link.test.d.ts +0 -5
  355. package/dist/tools/__tests__/link.test.d.ts.map +0 -1
  356. package/dist/tools/__tests__/link.test.js +0 -245
  357. package/dist/tools/__tests__/link.test.js.map +0 -1
  358. package/dist/tools/__tests__/query.test.d.ts +0 -5
  359. package/dist/tools/__tests__/query.test.d.ts.map +0 -1
  360. package/dist/tools/__tests__/query.test.js +0 -288
  361. package/dist/tools/__tests__/query.test.js.map +0 -1
  362. package/dist/tools/__tests__/task.test.d.ts +0 -5
  363. package/dist/tools/__tests__/task.test.d.ts.map +0 -1
  364. package/dist/tools/__tests__/task.test.js +0 -178
  365. package/dist/tools/__tests__/task.test.js.map +0 -1
  366. package/dist/tracking/claude-task-reconstructor.d.ts +0 -41
  367. package/dist/tracking/claude-task-reconstructor.d.ts.map +0 -1
  368. package/dist/tracking/claude-task-reconstructor.js +0 -91
  369. package/dist/tracking/claude-task-reconstructor.js.map +0 -1
  370. package/dist/tracking/plan-mode-tracker.d.ts +0 -20
  371. package/dist/tracking/plan-mode-tracker.d.ts.map +0 -1
  372. package/dist/tracking/plan-mode-tracker.js +0 -35
  373. package/dist/tracking/plan-mode-tracker.js.map +0 -1
@@ -1,669 +0,0 @@
1
- /**
2
- * Tests for Multi-Location Daemon (Phase B)
3
- *
4
- * Tests the multi-location daemon mode where a single daemon
5
- * manages multiple worktree locations under one git repo.
6
- */
7
- import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
8
- import * as fs from 'node:fs/promises';
9
- import * as path from 'node:path';
10
- import * as os from 'node:os';
11
- import { createDaemon, } from '../lifecycle.js';
12
- import { createIPCClient } from '../ipc.js';
13
- import { DaemonError } from '../types.js';
14
- import { createSingleLocationResolver, createMultiLocationResolver, } from '../location-state.js';
15
- // ============================================================================
16
- // Mock Helpers
17
- // ============================================================================
18
- function createMockStore() {
19
- const nodes = new Map();
20
- return {
21
- initialize: vi.fn().mockResolvedValue(undefined),
22
- close: vi.fn().mockResolvedValue(undefined),
23
- flush: vi.fn().mockResolvedValue(undefined),
24
- createNode: vi.fn().mockImplementation(async (input) => {
25
- const node = {
26
- id: `i-${Date.now().toString(36)}${Math.random().toString(36).slice(2, 5)}`,
27
- uuid: '550e8400-e29b-41d4-a716-446655440000',
28
- type: input.type || 'issue',
29
- title: input.title,
30
- status: input.status || 'open',
31
- created_at: new Date().toISOString(),
32
- updated_at: new Date().toISOString(),
33
- ...input,
34
- };
35
- nodes.set(node.id, node);
36
- return node;
37
- }),
38
- getNode: vi.fn().mockImplementation(async (id) => {
39
- return nodes.get(id) ?? null;
40
- }),
41
- updateNode: vi.fn().mockImplementation(async (id, updates) => {
42
- const node = nodes.get(id);
43
- if (!node)
44
- throw new Error(`Node not found: ${id}`);
45
- const updated = { ...node, ...updates, updated_at: new Date().toISOString() };
46
- nodes.set(id, updated);
47
- return updated;
48
- }),
49
- deleteNode: vi.fn().mockResolvedValue(undefined),
50
- restoreNode: vi.fn(),
51
- createEdge: vi.fn().mockImplementation(async (input) => {
52
- const edge = {
53
- id: `x-${Date.now().toString(36)}`,
54
- uuid: '550e8400-e29b-41d4-a716-446655440001',
55
- from_id: input.from_id,
56
- to_id: input.to_id,
57
- type: input.type || 'blocks',
58
- created_at: new Date().toISOString(),
59
- };
60
- return edge;
61
- }),
62
- getEdge: vi.fn().mockResolvedValue(null),
63
- deleteEdge: vi.fn().mockResolvedValue(undefined),
64
- addTags: vi.fn(),
65
- removeTags: vi.fn(),
66
- setTags: vi.fn(),
67
- query: {
68
- nodes: vi.fn().mockResolvedValue([]),
69
- edges: vi.fn().mockResolvedValue([]),
70
- edgesFrom: vi.fn().mockResolvedValue([]),
71
- edgesTo: vi.fn().mockResolvedValue([]),
72
- edgesFor: vi.fn().mockResolvedValue([]),
73
- blockers: vi.fn().mockResolvedValue([]),
74
- blocking: vi.fn().mockResolvedValue([]),
75
- isBlocking: vi.fn().mockResolvedValue(false),
76
- implementers: vi.fn().mockResolvedValue([]),
77
- specs: vi.fn().mockResolvedValue([]),
78
- children: vi.fn().mockResolvedValue([]),
79
- parent: vi.fn().mockResolvedValue(null),
80
- ancestors: vi.fn().mockResolvedValue([]),
81
- descendants: vi.fn().mockResolvedValue([]),
82
- ready: vi.fn().mockResolvedValue([]),
83
- feedback: vi.fn().mockResolvedValue([]),
84
- unresolvedFeedback: vi.fn().mockResolvedValue([]),
85
- },
86
- transaction: vi.fn(),
87
- };
88
- }
89
- function createMockFlushManager() {
90
- return {
91
- markDirty: vi.fn(),
92
- schedule: vi.fn(),
93
- flush: vi.fn().mockResolvedValue(undefined),
94
- pause: vi.fn(),
95
- resume: vi.fn(),
96
- finalFlush: vi.fn().mockResolvedValue(undefined),
97
- hasPendingChanges: vi.fn().mockReturnValue(false),
98
- getDirtyNodes: vi.fn().mockReturnValue([]),
99
- paused: false,
100
- };
101
- }
102
- function createMockWatcher() {
103
- return {
104
- start: vi.fn().mockResolvedValue(undefined),
105
- stop: vi.fn().mockResolvedValue(undefined),
106
- pause: vi.fn(),
107
- resume: vi.fn(),
108
- onchange: vi.fn(),
109
- paused: false,
110
- };
111
- }
112
- function createMockLocationState(hash, opentasksPath, primary = false) {
113
- return {
114
- hash,
115
- opentasksPath,
116
- store: createMockStore(),
117
- flushManager: createMockFlushManager(),
118
- watcher: createMockWatcher(),
119
- primary,
120
- healthy: true,
121
- };
122
- }
123
- // ============================================================================
124
- // LocationResolver Unit Tests
125
- // ============================================================================
126
- describe('LocationResolver', () => {
127
- describe('createSingleLocationResolver', () => {
128
- it('should resolve any hash to the single state', () => {
129
- const state = createMockLocationState('abc12345', '/tmp/.opentasks', true);
130
- const resolver = createSingleLocationResolver(state);
131
- expect(resolver.resolve()).toBe(state);
132
- expect(resolver.resolve('abc12345')).toBe(state);
133
- expect(resolver.resolve('anything')).toBe(state);
134
- });
135
- it('should return state as default', () => {
136
- const state = createMockLocationState('abc12345', '/tmp/.opentasks', true);
137
- const resolver = createSingleLocationResolver(state);
138
- expect(resolver.getDefault()).toBe(state);
139
- });
140
- it('should list single location', () => {
141
- const state = createMockLocationState('abc12345', '/tmp/.opentasks', true);
142
- const resolver = createSingleLocationResolver(state);
143
- const list = resolver.list();
144
- expect(list).toHaveLength(1);
145
- expect(list[0].hash).toBe('abc12345');
146
- expect(list[0].primary).toBe(true);
147
- expect(list[0].healthy).toBe(true);
148
- });
149
- it('should reject add in single-location mode', () => {
150
- const state = createMockLocationState('abc12345', '/tmp/.opentasks', true);
151
- const resolver = createSingleLocationResolver(state);
152
- const newState = createMockLocationState('def67890', '/tmp2/.opentasks');
153
- expect(() => resolver.add(newState)).toThrow('Cannot add locations');
154
- });
155
- it('should reject remove in single-location mode', async () => {
156
- const state = createMockLocationState('abc12345', '/tmp/.opentasks', true);
157
- const resolver = createSingleLocationResolver(state);
158
- await expect(resolver.remove('abc12345')).rejects.toThrow('Cannot remove locations');
159
- });
160
- });
161
- describe('createMultiLocationResolver', () => {
162
- it('should resolve primary hash as default', () => {
163
- const resolver = createMultiLocationResolver('primary1');
164
- const state = createMockLocationState('primary1', '/repo/.opentasks', true);
165
- resolver.add(state);
166
- expect(resolver.resolve()).toBe(state);
167
- expect(resolver.getDefault()).toBe(state);
168
- });
169
- it('should resolve specific location by hash', () => {
170
- const resolver = createMultiLocationResolver('primary1');
171
- const state1 = createMockLocationState('primary1', '/repo/.opentasks', true);
172
- const state2 = createMockLocationState('worktree', '/wt/.opentasks');
173
- resolver.add(state1);
174
- resolver.add(state2);
175
- expect(resolver.resolve('primary1')).toBe(state1);
176
- expect(resolver.resolve('worktree')).toBe(state2);
177
- });
178
- it('should throw LOCATION_NOT_FOUND for unknown hash', () => {
179
- const resolver = createMultiLocationResolver('primary1');
180
- const state = createMockLocationState('primary1', '/repo/.opentasks', true);
181
- resolver.add(state);
182
- expect(() => resolver.resolve('unknown')).toThrow(DaemonError);
183
- expect(() => resolver.resolve('unknown')).toThrow('Location not found');
184
- });
185
- it('should list all locations', () => {
186
- const resolver = createMultiLocationResolver('primary1');
187
- resolver.add(createMockLocationState('primary1', '/repo/.opentasks', true));
188
- resolver.add(createMockLocationState('wt1', '/wt1/.opentasks'));
189
- resolver.add(createMockLocationState('wt2', '/wt2/.opentasks'));
190
- const list = resolver.list();
191
- expect(list).toHaveLength(3);
192
- expect(list.map(l => l.hash).sort()).toEqual(['primary1', 'wt1', 'wt2']);
193
- });
194
- it('should check has()', () => {
195
- const resolver = createMultiLocationResolver('primary1');
196
- resolver.add(createMockLocationState('primary1', '/repo/.opentasks', true));
197
- expect(resolver.has('primary1')).toBe(true);
198
- expect(resolver.has('unknown')).toBe(false);
199
- });
200
- it('should add and remove locations', async () => {
201
- const resolver = createMultiLocationResolver('primary1');
202
- resolver.add(createMockLocationState('primary1', '/repo/.opentasks', true));
203
- const wt = createMockLocationState('wt1', '/wt1/.opentasks');
204
- resolver.add(wt);
205
- expect(resolver.list()).toHaveLength(2);
206
- await resolver.remove('wt1');
207
- expect(resolver.list()).toHaveLength(1);
208
- expect(resolver.has('wt1')).toBe(false);
209
- });
210
- it('should call teardown on remove', async () => {
211
- const resolver = createMultiLocationResolver('primary1');
212
- const wt = createMockLocationState('wt1', '/wt1/.opentasks');
213
- resolver.add(wt);
214
- await resolver.remove('wt1');
215
- // Watcher stop should have been called
216
- expect(wt.watcher.stop).toHaveBeenCalled();
217
- // Final flush should have been called
218
- expect(wt.flushManager.finalFlush).toHaveBeenCalled();
219
- // Store close should have been called
220
- expect(wt.store.close).toHaveBeenCalled();
221
- });
222
- it('should fallback to first location if primary not found', () => {
223
- const resolver = createMultiLocationResolver('missing');
224
- const state = createMockLocationState('fallback', '/fb/.opentasks');
225
- resolver.add(state);
226
- expect(resolver.getDefault()).toBe(state);
227
- });
228
- it('should throw when no locations available', () => {
229
- const resolver = createMultiLocationResolver('primary1');
230
- expect(() => resolver.resolve()).toThrow('No locations available');
231
- });
232
- it('should be idempotent on remove of non-existent hash', async () => {
233
- const resolver = createMultiLocationResolver('primary1');
234
- // Should not throw
235
- await resolver.remove('nonexistent');
236
- });
237
- });
238
- });
239
- // ============================================================================
240
- // Multi-Location Daemon Integration Tests
241
- // ============================================================================
242
- describe('Multi-Location Daemon', () => {
243
- let tempDir;
244
- let gitCommonDir;
245
- let primaryPath;
246
- let worktreePath;
247
- let registryPath;
248
- let daemon;
249
- let client;
250
- /**
251
- * Setup a simulated git repo structure with multiple worktree locations.
252
- */
253
- async function setupGitRepoStructure() {
254
- tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'opentasks-multi-loc-'));
255
- // Simulated repo structure:
256
- // tempDir/repo/.git/ ← gitCommonDir
257
- // tempDir/repo/.git/opentasks/worktrees.json
258
- // tempDir/repo/.opentasks/ ← primary location
259
- // tempDir/worktree1/.opentasks/ ← secondary location
260
- gitCommonDir = path.join(tempDir, 'repo', '.git');
261
- primaryPath = path.join(tempDir, 'repo', '.opentasks');
262
- worktreePath = path.join(tempDir, 'worktree1', '.opentasks');
263
- registryPath = path.join(tempDir, 'registry', 'registry.json');
264
- // Create directories
265
- await fs.mkdir(gitCommonDir, { recursive: true });
266
- await fs.mkdir(path.join(gitCommonDir, 'opentasks'), { recursive: true });
267
- await fs.mkdir(primaryPath, { recursive: true });
268
- await fs.mkdir(worktreePath, { recursive: true });
269
- // Create empty graph.jsonl files
270
- await fs.writeFile(path.join(primaryPath, 'graph.jsonl'), '', 'utf-8');
271
- await fs.writeFile(path.join(worktreePath, 'graph.jsonl'), '', 'utf-8');
272
- // Create worktree registry
273
- const worktreeRegistry = {
274
- worktrees: [
275
- {
276
- path: path.join(tempDir, 'repo'),
277
- opentasksPath: primaryPath,
278
- hash: 'pr1m4ry1',
279
- role: 'manager',
280
- },
281
- {
282
- path: path.join(tempDir, 'worktree1'),
283
- opentasksPath: worktreePath,
284
- hash: 'w0rktrs1',
285
- role: 'worker',
286
- redirectTarget: 'pr1m4ry1',
287
- },
288
- ],
289
- };
290
- await fs.writeFile(path.join(gitCommonDir, 'opentasks', 'worktrees.json'), JSON.stringify(worktreeRegistry, null, 2), 'utf-8');
291
- }
292
- function createMultiConfig(overrides = {}) {
293
- return {
294
- gitCommonDir,
295
- version: '1.0.0-test',
296
- registryPath,
297
- shutdownTimeoutMs: 3000,
298
- primaryLocationPath: primaryPath,
299
- ...overrides,
300
- };
301
- }
302
- beforeEach(async () => {
303
- await setupGitRepoStructure();
304
- daemon = null;
305
- client = null;
306
- });
307
- afterEach(async () => {
308
- if (client?.connected) {
309
- client.disconnect();
310
- client = null;
311
- }
312
- if (daemon) {
313
- try {
314
- await daemon.stop();
315
- }
316
- catch { /* ignore */ }
317
- daemon = null;
318
- }
319
- try {
320
- await fs.rm(tempDir, { recursive: true, force: true });
321
- }
322
- catch { /* ignore */ }
323
- });
324
- describe('creation', () => {
325
- it('should create multi-location daemon with correct paths', () => {
326
- daemon = createDaemon(createMultiConfig());
327
- const expectedSocketPath = path.join(gitCommonDir, 'opentasks', 'daemon.sock');
328
- expect(daemon.socketPath).toBe(expectedSocketPath);
329
- expect(daemon.locationPath).toBe(path.join(gitCommonDir, 'opentasks'));
330
- });
331
- it('should start in stopped state', () => {
332
- daemon = createDaemon(createMultiConfig());
333
- const status = daemon.getStatus();
334
- expect(status.state).toBe('stopped');
335
- });
336
- });
337
- describe('start and stop', () => {
338
- it('should start and initialize locations', async () => {
339
- daemon = createDaemon(createMultiConfig());
340
- await daemon.start();
341
- const status = daemon.getStatus();
342
- expect(status.state).toBe('running');
343
- expect(status.locationCount).toBeGreaterThanOrEqual(1);
344
- });
345
- it('should stop cleanly', async () => {
346
- daemon = createDaemon(createMultiConfig());
347
- await daemon.start();
348
- await daemon.stop();
349
- const status = daemon.getStatus();
350
- expect(status.state).toBe('stopped');
351
- });
352
- it('should reject double start', async () => {
353
- daemon = createDaemon(createMultiConfig());
354
- await daemon.start();
355
- await expect(daemon.start()).rejects.toThrow(DaemonError);
356
- });
357
- it('should be idempotent on stop', async () => {
358
- daemon = createDaemon(createMultiConfig());
359
- await daemon.start();
360
- await daemon.stop();
361
- await daemon.stop();
362
- await daemon.stop();
363
- expect(daemon.getStatus().state).toBe('stopped');
364
- });
365
- });
366
- describe('IPC operations', () => {
367
- it('should accept IPC connections', async () => {
368
- daemon = createDaemon(createMultiConfig());
369
- await daemon.start();
370
- client = createIPCClient(daemon.socketPath);
371
- await client.connect();
372
- const result = await client.request('ping');
373
- expect(result.pong).toBe(true);
374
- });
375
- it('should report location count in status', async () => {
376
- daemon = createDaemon(createMultiConfig());
377
- await daemon.start();
378
- client = createIPCClient(daemon.socketPath);
379
- await client.connect();
380
- const status = await client.request('status');
381
- expect(status.state).toBe('running');
382
- expect(status.locationCount).toBeGreaterThanOrEqual(1);
383
- });
384
- it('should report healthy status when all locations are up', async () => {
385
- daemon = createDaemon(createMultiConfig());
386
- await daemon.start();
387
- client = createIPCClient(daemon.socketPath);
388
- await client.connect();
389
- const health = await client.request('health');
390
- expect(health.status).toBe('healthy');
391
- });
392
- it('should handle graph.create on default location', async () => {
393
- daemon = createDaemon(createMultiConfig());
394
- await daemon.start();
395
- client = createIPCClient(daemon.socketPath);
396
- await client.connect();
397
- const node = await client.request('graph.create', {
398
- type: 'issue',
399
- title: 'Test Issue',
400
- status: 'open',
401
- });
402
- expect(node.title).toBe('Test Issue');
403
- expect(node.id).toBeTruthy();
404
- });
405
- it('should handle graph.create with explicit location', async () => {
406
- daemon = createDaemon(createMultiConfig());
407
- await daemon.start();
408
- client = createIPCClient(daemon.socketPath);
409
- await client.connect();
410
- // Create on primary location explicitly
411
- const node = await client.request('graph.create', {
412
- type: 'issue',
413
- title: 'Primary Issue',
414
- status: 'open',
415
- location: 'pr1m4ry1',
416
- });
417
- expect(node.title).toBe('Primary Issue');
418
- });
419
- it('should route graph operations to specific worktree', async () => {
420
- daemon = createDaemon(createMultiConfig());
421
- await daemon.start();
422
- client = createIPCClient(daemon.socketPath);
423
- await client.connect();
424
- // Create on worktree location
425
- const node = await client.request('graph.create', {
426
- type: 'issue',
427
- title: 'Worktree Issue',
428
- status: 'open',
429
- location: 'w0rktrs1',
430
- });
431
- expect(node.title).toBe('Worktree Issue');
432
- });
433
- it('should return error for unknown location', async () => {
434
- daemon = createDaemon(createMultiConfig());
435
- await daemon.start();
436
- client = createIPCClient(daemon.socketPath);
437
- await client.connect();
438
- // The IPC server wraps DaemonError as JSON-RPC Internal error
439
- await expect(client.request('graph.create', {
440
- type: 'issue',
441
- title: 'Bad Location',
442
- status: 'open',
443
- location: 'unknown1',
444
- })).rejects.toThrow('Internal error');
445
- });
446
- });
447
- describe('location IPC methods', () => {
448
- it('should list locations', async () => {
449
- daemon = createDaemon(createMultiConfig());
450
- await daemon.start();
451
- client = createIPCClient(daemon.socketPath);
452
- await client.connect();
453
- const locations = await client.request('location.list');
454
- expect(locations.length).toBeGreaterThanOrEqual(1);
455
- // Primary should be in the list
456
- const primary = locations.find(l => l.primary);
457
- expect(primary).toBeTruthy();
458
- });
459
- it('should list all registered worktrees', async () => {
460
- daemon = createDaemon(createMultiConfig());
461
- await daemon.start();
462
- client = createIPCClient(daemon.socketPath);
463
- await client.connect();
464
- const locations = await client.request('location.list');
465
- const hashes = locations.map(l => l.hash);
466
- // Should have both primary and worktree
467
- expect(hashes).toContain('pr1m4ry1');
468
- expect(hashes).toContain('w0rktrs1');
469
- });
470
- it('should unregister a location', async () => {
471
- daemon = createDaemon(createMultiConfig());
472
- await daemon.start();
473
- client = createIPCClient(daemon.socketPath);
474
- await client.connect();
475
- // Unregister worktree
476
- const result = await client.request('location.unregister', {
477
- hash: 'w0rktrs1',
478
- });
479
- expect(result.success).toBe(true);
480
- // Verify it's gone
481
- const locations = await client.request('location.list');
482
- const hashes = locations.map(l => l.hash);
483
- expect(hashes).not.toContain('w0rktrs1');
484
- });
485
- it('should dynamically register a new location', async () => {
486
- daemon = createDaemon(createMultiConfig());
487
- await daemon.start();
488
- client = createIPCClient(daemon.socketPath);
489
- await client.connect();
490
- // Create a new worktree location
491
- const newWorktrePath = path.join(tempDir, 'worktree2', '.opentasks');
492
- await fs.mkdir(newWorktrePath, { recursive: true });
493
- await fs.writeFile(path.join(newWorktrePath, 'graph.jsonl'), '', 'utf-8');
494
- // Register it
495
- const result = await client.request('location.register', {
496
- hash: 'n3wloc01',
497
- opentasksPath: newWorktrePath,
498
- });
499
- expect(result.success).toBe(true);
500
- // Verify it's in the list
501
- const locations = await client.request('location.list');
502
- const hashes = locations.map(l => l.hash);
503
- expect(hashes).toContain('n3wloc01');
504
- });
505
- it('should fail to register invalid location path', async () => {
506
- daemon = createDaemon(createMultiConfig());
507
- await daemon.start();
508
- client = createIPCClient(daemon.socketPath);
509
- await client.connect();
510
- // Try to register a path that doesn't exist
511
- await expect(client.request('location.register', {
512
- hash: 'bad1loc1',
513
- opentasksPath: '/nonexistent/path/.opentasks',
514
- })).rejects.toThrow();
515
- });
516
- it('should be idempotent for already-registered location', async () => {
517
- daemon = createDaemon(createMultiConfig());
518
- await daemon.start();
519
- client = createIPCClient(daemon.socketPath);
520
- await client.connect();
521
- // Re-register an existing location
522
- const result = await client.request('location.register', {
523
- hash: 'pr1m4ry1',
524
- opentasksPath: primaryPath,
525
- });
526
- expect(result.success).toBe(true);
527
- });
528
- });
529
- describe('graceful degradation', () => {
530
- it('should start even if secondary location is unreachable', async () => {
531
- // Remove the worktree .opentasks dir to make it fail
532
- await fs.rm(worktreePath, { recursive: true, force: true });
533
- daemon = createDaemon(createMultiConfig());
534
- await daemon.start();
535
- const status = daemon.getStatus();
536
- expect(status.state).toBe('running');
537
- // At least primary should be initialized
538
- expect(status.locationCount).toBeGreaterThanOrEqual(1);
539
- });
540
- it('should fail if no locations can be initialized', async () => {
541
- // Remove both locations
542
- await fs.rm(primaryPath, { recursive: true, force: true });
543
- await fs.rm(worktreePath, { recursive: true, force: true });
544
- daemon = createDaemon(createMultiConfig());
545
- await expect(daemon.start()).rejects.toThrow('No locations could be initialized');
546
- expect(daemon.getStatus().state).toBe('stopped');
547
- });
548
- });
549
- describe('flush operations', () => {
550
- it('should flush specific location', async () => {
551
- daemon = createDaemon(createMultiConfig());
552
- await daemon.start();
553
- client = createIPCClient(daemon.socketPath);
554
- await client.connect();
555
- const result = await client.request('flush', {
556
- location: 'pr1m4ry1',
557
- });
558
- expect(result.success).toBe(true);
559
- });
560
- it('should flush default location when no location specified', async () => {
561
- daemon = createDaemon(createMultiConfig());
562
- await daemon.start();
563
- client = createIPCClient(daemon.socketPath);
564
- await client.connect();
565
- const result = await client.request('flush');
566
- expect(result.success).toBe(true);
567
- });
568
- });
569
- describe('shutdown via IPC', () => {
570
- it('should shutdown multi-location daemon via IPC', async () => {
571
- daemon = createDaemon(createMultiConfig());
572
- await daemon.start();
573
- client = createIPCClient(daemon.socketPath);
574
- await client.connect();
575
- const result = await client.request('shutdown');
576
- expect(result.success).toBe(true);
577
- client.disconnect();
578
- client = null;
579
- // Wait for shutdown
580
- await new Promise((r) => setTimeout(r, 300));
581
- expect(daemon.getStatus().state).toBe('stopped');
582
- });
583
- });
584
- });
585
- // ============================================================================
586
- // Backward Compatibility Tests
587
- // ============================================================================
588
- describe('Backward Compatibility', () => {
589
- let tempDir;
590
- let locationPath;
591
- let registryPath;
592
- let daemon;
593
- let client;
594
- beforeEach(async () => {
595
- tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'opentasks-compat-'));
596
- locationPath = path.join(tempDir, '.opentasks');
597
- registryPath = path.join(tempDir, 'registry', 'registry.json');
598
- await fs.mkdir(locationPath, { recursive: true });
599
- daemon = null;
600
- client = null;
601
- });
602
- afterEach(async () => {
603
- if (client?.connected) {
604
- client.disconnect();
605
- client = null;
606
- }
607
- if (daemon) {
608
- try {
609
- await daemon.stop();
610
- }
611
- catch { /* ignore */ }
612
- daemon = null;
613
- }
614
- try {
615
- await fs.rm(tempDir, { recursive: true, force: true });
616
- }
617
- catch { /* ignore */ }
618
- });
619
- it('should still work with single-location config (no gitCommonDir)', async () => {
620
- const store = createMockStore();
621
- daemon = createDaemon({
622
- locationPath,
623
- version: '1.0.0-test',
624
- store,
625
- registryPath,
626
- shutdownTimeoutMs: 2000,
627
- });
628
- await daemon.start();
629
- client = createIPCClient(daemon.socketPath);
630
- await client.connect();
631
- const result = await client.request('ping');
632
- expect(result.pong).toBe(true);
633
- const node = await client.request('graph.create', {
634
- type: 'issue',
635
- title: 'Compat Test',
636
- status: 'open',
637
- });
638
- expect(node.title).toBe('Compat Test');
639
- expect(store.createNode).toHaveBeenCalledOnce();
640
- client.disconnect();
641
- client = null;
642
- await daemon.stop();
643
- expect(daemon.getStatus().state).toBe('stopped');
644
- expect(store.close).toHaveBeenCalledOnce();
645
- });
646
- it('single-location config should ignore location param', async () => {
647
- const store = createMockStore();
648
- daemon = createDaemon({
649
- locationPath,
650
- version: '1.0.0-test',
651
- store,
652
- registryPath,
653
- shutdownTimeoutMs: 2000,
654
- });
655
- await daemon.start();
656
- client = createIPCClient(daemon.socketPath);
657
- await client.connect();
658
- // Even with a location param, single-location resolves to the only store
659
- const node = await client.request('graph.create', {
660
- type: 'issue',
661
- title: 'With Location',
662
- status: 'open',
663
- location: 'anyhash1',
664
- });
665
- expect(node.title).toBe('With Location');
666
- expect(store.createNode).toHaveBeenCalledOnce();
667
- });
668
- });
669
- //# sourceMappingURL=multi-location.test.js.map