opentasks 0.0.5 → 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 (311) hide show
  1. package/README.md +40 -0
  2. package/dist/cli.d.ts.map +1 -1
  3. package/dist/cli.js +153 -8
  4. package/dist/cli.js.map +1 -1
  5. package/dist/config/schema.d.ts +54 -0
  6. package/dist/config/schema.d.ts.map +1 -1
  7. package/dist/config/schema.js +52 -0
  8. package/dist/config/schema.js.map +1 -1
  9. package/dist/core/merge-driver.d.ts +6 -2
  10. package/dist/core/merge-driver.d.ts.map +1 -1
  11. package/dist/core/merge-driver.js +11 -7
  12. package/dist/core/merge-driver.js.map +1 -1
  13. package/dist/core/worktree.js +1 -1
  14. package/dist/core/worktree.js.map +1 -1
  15. package/dist/daemon/ipc.d.ts.map +1 -1
  16. package/dist/daemon/ipc.js +4 -1
  17. package/dist/daemon/ipc.js.map +1 -1
  18. package/dist/daemon/lifecycle.d.ts.map +1 -1
  19. package/dist/daemon/lifecycle.js +5 -0
  20. package/dist/daemon/lifecycle.js.map +1 -1
  21. package/dist/graph/git-graph-syncer.js +1 -1
  22. package/dist/graph/git-graph-syncer.js.map +1 -1
  23. package/dist/providers/from-config.d.ts +3 -0
  24. package/dist/providers/from-config.d.ts.map +1 -1
  25. package/dist/providers/from-config.js +29 -0
  26. package/dist/providers/from-config.js.map +1 -1
  27. package/dist/providers/index.d.ts +3 -0
  28. package/dist/providers/index.d.ts.map +1 -1
  29. package/dist/providers/index.js +6 -0
  30. package/dist/providers/index.js.map +1 -1
  31. package/dist/providers/map-client-factory.d.ts +55 -0
  32. package/dist/providers/map-client-factory.d.ts.map +1 -0
  33. package/dist/providers/map-client-factory.js +123 -0
  34. package/dist/providers/map-client-factory.js.map +1 -0
  35. package/dist/providers/map-event-bridge.d.ts +146 -0
  36. package/dist/providers/map-event-bridge.d.ts.map +1 -0
  37. package/dist/providers/map-event-bridge.js +208 -0
  38. package/dist/providers/map-event-bridge.js.map +1 -0
  39. package/dist/providers/map.d.ts +115 -0
  40. package/dist/providers/map.d.ts.map +1 -0
  41. package/dist/providers/map.js +376 -0
  42. package/dist/providers/map.js.map +1 -0
  43. package/package.json +1 -1
  44. package/dist/__tests__/cli-tools.test.d.ts +0 -8
  45. package/dist/__tests__/cli-tools.test.d.ts.map +0 -1
  46. package/dist/__tests__/cli-tools.test.js +0 -546
  47. package/dist/__tests__/cli-tools.test.js.map +0 -1
  48. package/dist/__tests__/cli.test.d.ts +0 -5
  49. package/dist/__tests__/cli.test.d.ts.map +0 -1
  50. package/dist/__tests__/cli.test.js +0 -77
  51. package/dist/__tests__/cli.test.js.map +0 -1
  52. package/dist/__tests__/p1-p3-gaps.test.d.ts +0 -2
  53. package/dist/__tests__/p1-p3-gaps.test.d.ts.map +0 -1
  54. package/dist/__tests__/p1-p3-gaps.test.js +0 -463
  55. package/dist/__tests__/p1-p3-gaps.test.js.map +0 -1
  56. package/dist/client/__tests__/client-crud.test.d.ts +0 -7
  57. package/dist/client/__tests__/client-crud.test.d.ts.map +0 -1
  58. package/dist/client/__tests__/client-crud.test.js +0 -404
  59. package/dist/client/__tests__/client-crud.test.js.map +0 -1
  60. package/dist/client/__tests__/client.test.d.ts +0 -5
  61. package/dist/client/__tests__/client.test.d.ts.map +0 -1
  62. package/dist/client/__tests__/client.test.js +0 -518
  63. package/dist/client/__tests__/client.test.js.map +0 -1
  64. package/dist/config/__tests__/defaults.test.d.ts +0 -2
  65. package/dist/config/__tests__/defaults.test.d.ts.map +0 -1
  66. package/dist/config/__tests__/defaults.test.js +0 -57
  67. package/dist/config/__tests__/defaults.test.js.map +0 -1
  68. package/dist/config/__tests__/env.test.d.ts +0 -2
  69. package/dist/config/__tests__/env.test.d.ts.map +0 -1
  70. package/dist/config/__tests__/env.test.js +0 -136
  71. package/dist/config/__tests__/env.test.js.map +0 -1
  72. package/dist/config/__tests__/index.test.d.ts +0 -2
  73. package/dist/config/__tests__/index.test.d.ts.map +0 -1
  74. package/dist/config/__tests__/index.test.js +0 -113
  75. package/dist/config/__tests__/index.test.js.map +0 -1
  76. package/dist/config/__tests__/loader.test.d.ts +0 -2
  77. package/dist/config/__tests__/loader.test.d.ts.map +0 -1
  78. package/dist/config/__tests__/loader.test.js +0 -128
  79. package/dist/config/__tests__/loader.test.js.map +0 -1
  80. package/dist/config/__tests__/merge.test.d.ts +0 -2
  81. package/dist/config/__tests__/merge.test.d.ts.map +0 -1
  82. package/dist/config/__tests__/merge.test.js +0 -79
  83. package/dist/config/__tests__/merge.test.js.map +0 -1
  84. package/dist/config/__tests__/schema.test.d.ts +0 -2
  85. package/dist/config/__tests__/schema.test.d.ts.map +0 -1
  86. package/dist/config/__tests__/schema.test.js +0 -300
  87. package/dist/config/__tests__/schema.test.js.map +0 -1
  88. package/dist/core/__tests__/conditional-redirects.test.d.ts +0 -2
  89. package/dist/core/__tests__/conditional-redirects.test.d.ts.map +0 -1
  90. package/dist/core/__tests__/conditional-redirects.test.js +0 -83
  91. package/dist/core/__tests__/conditional-redirects.test.js.map +0 -1
  92. package/dist/core/__tests__/connections.test.d.ts +0 -2
  93. package/dist/core/__tests__/connections.test.d.ts.map +0 -1
  94. package/dist/core/__tests__/connections.test.js +0 -158
  95. package/dist/core/__tests__/connections.test.js.map +0 -1
  96. package/dist/core/__tests__/hash.test.d.ts +0 -2
  97. package/dist/core/__tests__/hash.test.d.ts.map +0 -1
  98. package/dist/core/__tests__/hash.test.js +0 -139
  99. package/dist/core/__tests__/hash.test.js.map +0 -1
  100. package/dist/core/__tests__/id.test.d.ts +0 -2
  101. package/dist/core/__tests__/id.test.d.ts.map +0 -1
  102. package/dist/core/__tests__/id.test.js +0 -142
  103. package/dist/core/__tests__/id.test.js.map +0 -1
  104. package/dist/core/__tests__/location.test.d.ts +0 -2
  105. package/dist/core/__tests__/location.test.d.ts.map +0 -1
  106. package/dist/core/__tests__/location.test.js +0 -77
  107. package/dist/core/__tests__/location.test.js.map +0 -1
  108. package/dist/core/__tests__/merge-driver.test.d.ts +0 -2
  109. package/dist/core/__tests__/merge-driver.test.d.ts.map +0 -1
  110. package/dist/core/__tests__/merge-driver.test.js +0 -218
  111. package/dist/core/__tests__/merge-driver.test.js.map +0 -1
  112. package/dist/core/__tests__/redirects.test.d.ts +0 -2
  113. package/dist/core/__tests__/redirects.test.d.ts.map +0 -1
  114. package/dist/core/__tests__/redirects.test.js +0 -123
  115. package/dist/core/__tests__/redirects.test.js.map +0 -1
  116. package/dist/core/__tests__/resolve-location-target.test.d.ts +0 -8
  117. package/dist/core/__tests__/resolve-location-target.test.d.ts.map +0 -1
  118. package/dist/core/__tests__/resolve-location-target.test.js +0 -303
  119. package/dist/core/__tests__/resolve-location-target.test.js.map +0 -1
  120. package/dist/core/__tests__/uri.test.d.ts +0 -2
  121. package/dist/core/__tests__/uri.test.d.ts.map +0 -1
  122. package/dist/core/__tests__/uri.test.js +0 -159
  123. package/dist/core/__tests__/uri.test.js.map +0 -1
  124. package/dist/core/__tests__/worktree.test.d.ts +0 -2
  125. package/dist/core/__tests__/worktree.test.d.ts.map +0 -1
  126. package/dist/core/__tests__/worktree.test.js +0 -120
  127. package/dist/core/__tests__/worktree.test.js.map +0 -1
  128. package/dist/daemon/__tests__/flush.test.d.ts +0 -5
  129. package/dist/daemon/__tests__/flush.test.d.ts.map +0 -1
  130. package/dist/daemon/__tests__/flush.test.js +0 -213
  131. package/dist/daemon/__tests__/flush.test.js.map +0 -1
  132. package/dist/daemon/__tests__/integration.test.d.ts +0 -7
  133. package/dist/daemon/__tests__/integration.test.d.ts.map +0 -1
  134. package/dist/daemon/__tests__/integration.test.js +0 -276
  135. package/dist/daemon/__tests__/integration.test.js.map +0 -1
  136. package/dist/daemon/__tests__/ipc.test.d.ts +0 -5
  137. package/dist/daemon/__tests__/ipc.test.d.ts.map +0 -1
  138. package/dist/daemon/__tests__/ipc.test.js +0 -314
  139. package/dist/daemon/__tests__/ipc.test.js.map +0 -1
  140. package/dist/daemon/__tests__/lifecycle.test.d.ts +0 -5
  141. package/dist/daemon/__tests__/lifecycle.test.d.ts.map +0 -1
  142. package/dist/daemon/__tests__/lifecycle.test.js +0 -301
  143. package/dist/daemon/__tests__/lifecycle.test.js.map +0 -1
  144. package/dist/daemon/__tests__/lock.test.d.ts +0 -5
  145. package/dist/daemon/__tests__/lock.test.d.ts.map +0 -1
  146. package/dist/daemon/__tests__/lock.test.js +0 -192
  147. package/dist/daemon/__tests__/lock.test.js.map +0 -1
  148. package/dist/daemon/__tests__/methods/graph.test.d.ts +0 -5
  149. package/dist/daemon/__tests__/methods/graph.test.d.ts.map +0 -1
  150. package/dist/daemon/__tests__/methods/graph.test.js +0 -309
  151. package/dist/daemon/__tests__/methods/graph.test.js.map +0 -1
  152. package/dist/daemon/__tests__/methods/provider.test.d.ts +0 -7
  153. package/dist/daemon/__tests__/methods/provider.test.d.ts.map +0 -1
  154. package/dist/daemon/__tests__/methods/provider.test.js +0 -181
  155. package/dist/daemon/__tests__/methods/provider.test.js.map +0 -1
  156. package/dist/daemon/__tests__/methods/tools.test.d.ts +0 -5
  157. package/dist/daemon/__tests__/methods/tools.test.d.ts.map +0 -1
  158. package/dist/daemon/__tests__/methods/tools.test.js +0 -587
  159. package/dist/daemon/__tests__/methods/tools.test.js.map +0 -1
  160. package/dist/daemon/__tests__/multi-location.test.d.ts +0 -8
  161. package/dist/daemon/__tests__/multi-location.test.d.ts.map +0 -1
  162. package/dist/daemon/__tests__/multi-location.test.js +0 -669
  163. package/dist/daemon/__tests__/multi-location.test.js.map +0 -1
  164. package/dist/daemon/__tests__/registry.test.d.ts +0 -5
  165. package/dist/daemon/__tests__/registry.test.d.ts.map +0 -1
  166. package/dist/daemon/__tests__/registry.test.js +0 -208
  167. package/dist/daemon/__tests__/registry.test.js.map +0 -1
  168. package/dist/daemon/__tests__/watcher.test.d.ts +0 -5
  169. package/dist/daemon/__tests__/watcher.test.d.ts.map +0 -1
  170. package/dist/daemon/__tests__/watcher.test.js +0 -234
  171. package/dist/daemon/__tests__/watcher.test.js.map +0 -1
  172. package/dist/daemon/methods/__tests__/graph.test.d.ts +0 -5
  173. package/dist/daemon/methods/__tests__/graph.test.d.ts.map +0 -1
  174. package/dist/daemon/methods/__tests__/graph.test.js +0 -274
  175. package/dist/daemon/methods/__tests__/graph.test.js.map +0 -1
  176. package/dist/daemon/methods/__tests__/provider.test.d.ts +0 -5
  177. package/dist/daemon/methods/__tests__/provider.test.d.ts.map +0 -1
  178. package/dist/daemon/methods/__tests__/provider.test.js +0 -184
  179. package/dist/daemon/methods/__tests__/provider.test.js.map +0 -1
  180. package/dist/daemon/methods/__tests__/tools.test.d.ts +0 -5
  181. package/dist/daemon/methods/__tests__/tools.test.d.ts.map +0 -1
  182. package/dist/daemon/methods/__tests__/tools.test.js +0 -295
  183. package/dist/daemon/methods/__tests__/tools.test.js.map +0 -1
  184. package/dist/graph/__tests__/EdgeTypeRegistry.test.d.ts +0 -2
  185. package/dist/graph/__tests__/EdgeTypeRegistry.test.d.ts.map +0 -1
  186. package/dist/graph/__tests__/EdgeTypeRegistry.test.js +0 -212
  187. package/dist/graph/__tests__/EdgeTypeRegistry.test.js.map +0 -1
  188. package/dist/graph/__tests__/FederatedGraph.test.d.ts +0 -2
  189. package/dist/graph/__tests__/FederatedGraph.test.d.ts.map +0 -1
  190. package/dist/graph/__tests__/FederatedGraph.test.js +0 -661
  191. package/dist/graph/__tests__/FederatedGraph.test.js.map +0 -1
  192. package/dist/graph/__tests__/GraphologyAdapter.test.d.ts +0 -2
  193. package/dist/graph/__tests__/GraphologyAdapter.test.d.ts.map +0 -1
  194. package/dist/graph/__tests__/GraphologyAdapter.test.js +0 -326
  195. package/dist/graph/__tests__/GraphologyAdapter.test.js.map +0 -1
  196. package/dist/graph/__tests__/HydratingFederatedGraph.test.d.ts +0 -2
  197. package/dist/graph/__tests__/HydratingFederatedGraph.test.d.ts.map +0 -1
  198. package/dist/graph/__tests__/HydratingFederatedGraph.test.js +0 -587
  199. package/dist/graph/__tests__/HydratingFederatedGraph.test.js.map +0 -1
  200. package/dist/graph/__tests__/debounce.test.d.ts +0 -5
  201. package/dist/graph/__tests__/debounce.test.d.ts.map +0 -1
  202. package/dist/graph/__tests__/debounce.test.js +0 -195
  203. package/dist/graph/__tests__/debounce.test.js.map +0 -1
  204. package/dist/graph/__tests__/edge-cases.test.d.ts +0 -8
  205. package/dist/graph/__tests__/edge-cases.test.d.ts.map +0 -1
  206. package/dist/graph/__tests__/edge-cases.test.js +0 -472
  207. package/dist/graph/__tests__/edge-cases.test.js.map +0 -1
  208. package/dist/graph/__tests__/expansion.test.d.ts +0 -2
  209. package/dist/graph/__tests__/expansion.test.d.ts.map +0 -1
  210. package/dist/graph/__tests__/expansion.test.js +0 -105
  211. package/dist/graph/__tests__/expansion.test.js.map +0 -1
  212. package/dist/graph/__tests__/provider-store.test.d.ts +0 -5
  213. package/dist/graph/__tests__/provider-store.test.d.ts.map +0 -1
  214. package/dist/graph/__tests__/provider-store.test.js +0 -791
  215. package/dist/graph/__tests__/provider-store.test.js.map +0 -1
  216. package/dist/graph/__tests__/query.test.d.ts +0 -5
  217. package/dist/graph/__tests__/query.test.d.ts.map +0 -1
  218. package/dist/graph/__tests__/query.test.js +0 -774
  219. package/dist/graph/__tests__/query.test.js.map +0 -1
  220. package/dist/graph/__tests__/store.test.d.ts +0 -5
  221. package/dist/graph/__tests__/store.test.d.ts.map +0 -1
  222. package/dist/graph/__tests__/store.test.js +0 -489
  223. package/dist/graph/__tests__/store.test.js.map +0 -1
  224. package/dist/graph/__tests__/sync.test.d.ts +0 -5
  225. package/dist/graph/__tests__/sync.test.d.ts.map +0 -1
  226. package/dist/graph/__tests__/sync.test.js +0 -129
  227. package/dist/graph/__tests__/sync.test.js.map +0 -1
  228. package/dist/graph/__tests__/validation.test.d.ts +0 -2
  229. package/dist/graph/__tests__/validation.test.d.ts.map +0 -1
  230. package/dist/graph/__tests__/validation.test.js +0 -521
  231. package/dist/graph/__tests__/validation.test.js.map +0 -1
  232. package/dist/providers/__tests__/beads.test.d.ts +0 -5
  233. package/dist/providers/__tests__/beads.test.d.ts.map +0 -1
  234. package/dist/providers/__tests__/beads.test.js +0 -591
  235. package/dist/providers/__tests__/beads.test.js.map +0 -1
  236. package/dist/providers/__tests__/claude-tasks.test.d.ts +0 -5
  237. package/dist/providers/__tests__/claude-tasks.test.d.ts.map +0 -1
  238. package/dist/providers/__tests__/claude-tasks.test.js +0 -392
  239. package/dist/providers/__tests__/claude-tasks.test.js.map +0 -1
  240. package/dist/providers/__tests__/from-config.test.d.ts +0 -5
  241. package/dist/providers/__tests__/from-config.test.d.ts.map +0 -1
  242. package/dist/providers/__tests__/from-config.test.js +0 -152
  243. package/dist/providers/__tests__/from-config.test.js.map +0 -1
  244. package/dist/providers/__tests__/materialization.test.d.ts +0 -5
  245. package/dist/providers/__tests__/materialization.test.d.ts.map +0 -1
  246. package/dist/providers/__tests__/materialization.test.js +0 -407
  247. package/dist/providers/__tests__/materialization.test.js.map +0 -1
  248. package/dist/providers/__tests__/native.test.d.ts +0 -5
  249. package/dist/providers/__tests__/native.test.d.ts.map +0 -1
  250. package/dist/providers/__tests__/native.test.js +0 -566
  251. package/dist/providers/__tests__/native.test.js.map +0 -1
  252. package/dist/providers/__tests__/registry.test.d.ts +0 -5
  253. package/dist/providers/__tests__/registry.test.d.ts.map +0 -1
  254. package/dist/providers/__tests__/registry.test.js +0 -183
  255. package/dist/providers/__tests__/registry.test.js.map +0 -1
  256. package/dist/providers/traits/__tests__/RelationshipQueryable.test.d.ts +0 -2
  257. package/dist/providers/traits/__tests__/RelationshipQueryable.test.d.ts.map +0 -1
  258. package/dist/providers/traits/__tests__/RelationshipQueryable.test.js +0 -169
  259. package/dist/providers/traits/__tests__/RelationshipQueryable.test.js.map +0 -1
  260. package/dist/providers/traits/__tests__/TaskManageable.test.d.ts +0 -2
  261. package/dist/providers/traits/__tests__/TaskManageable.test.d.ts.map +0 -1
  262. package/dist/providers/traits/__tests__/TaskManageable.test.js +0 -172
  263. package/dist/providers/traits/__tests__/TaskManageable.test.js.map +0 -1
  264. package/dist/schema/__tests__/validation.test.d.ts +0 -2
  265. package/dist/schema/__tests__/validation.test.d.ts.map +0 -1
  266. package/dist/schema/__tests__/validation.test.js +0 -241
  267. package/dist/schema/__tests__/validation.test.js.map +0 -1
  268. package/dist/storage/__tests__/atomic-write.test.d.ts +0 -5
  269. package/dist/storage/__tests__/atomic-write.test.d.ts.map +0 -1
  270. package/dist/storage/__tests__/atomic-write.test.js +0 -170
  271. package/dist/storage/__tests__/atomic-write.test.js.map +0 -1
  272. package/dist/storage/__tests__/file-lock.test.d.ts +0 -2
  273. package/dist/storage/__tests__/file-lock.test.d.ts.map +0 -1
  274. package/dist/storage/__tests__/file-lock.test.js +0 -89
  275. package/dist/storage/__tests__/file-lock.test.js.map +0 -1
  276. package/dist/storage/__tests__/jsonl.test.d.ts +0 -2
  277. package/dist/storage/__tests__/jsonl.test.d.ts.map +0 -1
  278. package/dist/storage/__tests__/jsonl.test.js +0 -228
  279. package/dist/storage/__tests__/jsonl.test.js.map +0 -1
  280. package/dist/storage/__tests__/locked-writer.test.d.ts +0 -2
  281. package/dist/storage/__tests__/locked-writer.test.d.ts.map +0 -1
  282. package/dist/storage/__tests__/locked-writer.test.js +0 -109
  283. package/dist/storage/__tests__/locked-writer.test.js.map +0 -1
  284. package/dist/storage/__tests__/sqlite.test.d.ts +0 -2
  285. package/dist/storage/__tests__/sqlite.test.d.ts.map +0 -1
  286. package/dist/storage/__tests__/sqlite.test.js +0 -470
  287. package/dist/storage/__tests__/sqlite.test.js.map +0 -1
  288. package/dist/tools/__tests__/annotate.test.d.ts +0 -5
  289. package/dist/tools/__tests__/annotate.test.d.ts.map +0 -1
  290. package/dist/tools/__tests__/annotate.test.js +0 -314
  291. package/dist/tools/__tests__/annotate.test.js.map +0 -1
  292. package/dist/tools/__tests__/link.test.d.ts +0 -5
  293. package/dist/tools/__tests__/link.test.d.ts.map +0 -1
  294. package/dist/tools/__tests__/link.test.js +0 -245
  295. package/dist/tools/__tests__/link.test.js.map +0 -1
  296. package/dist/tools/__tests__/query.test.d.ts +0 -5
  297. package/dist/tools/__tests__/query.test.d.ts.map +0 -1
  298. package/dist/tools/__tests__/query.test.js +0 -288
  299. package/dist/tools/__tests__/query.test.js.map +0 -1
  300. package/dist/tools/__tests__/task.test.d.ts +0 -5
  301. package/dist/tools/__tests__/task.test.d.ts.map +0 -1
  302. package/dist/tools/__tests__/task.test.js +0 -178
  303. package/dist/tools/__tests__/task.test.js.map +0 -1
  304. package/dist/tracking/claude-task-reconstructor.d.ts +0 -41
  305. package/dist/tracking/claude-task-reconstructor.d.ts.map +0 -1
  306. package/dist/tracking/claude-task-reconstructor.js +0 -91
  307. package/dist/tracking/claude-task-reconstructor.js.map +0 -1
  308. package/dist/tracking/plan-mode-tracker.d.ts +0 -20
  309. package/dist/tracking/plan-mode-tracker.d.ts.map +0 -1
  310. package/dist/tracking/plan-mode-tracker.js +0 -35
  311. 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