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,661 +0,0 @@
1
- import { describe, it, expect, beforeEach } from 'vitest';
2
- import { createFederatedGraph, } from '../FederatedGraph.js';
3
- import { createGraphologyAdapter } from '../GraphologyAdapter.js';
4
- describe('FederatedGraph', () => {
5
- let adapter;
6
- let graph;
7
- beforeEach(() => {
8
- adapter = createGraphologyAdapter();
9
- graph = createFederatedGraph(adapter);
10
- });
11
- // Test fixtures - a simple graph:
12
- //
13
- // s-spec1 ──implements──> i-issue1 ──blocks──> i-issue2 ──blocks──> i-issue3
14
- // │
15
- // └──blocks──> i-issue4
16
- //
17
- const spec1 = {
18
- id: 's-spec1',
19
- uuid: 'uuid-spec1',
20
- type: 'spec',
21
- title: 'Spec 1',
22
- created_at: '2025-01-01T00:00:00Z',
23
- updated_at: '2025-01-01T00:00:00Z',
24
- };
25
- const issue1 = {
26
- id: 'i-issue1',
27
- uuid: 'uuid-issue1',
28
- type: 'issue',
29
- title: 'Issue 1',
30
- status: 'open',
31
- created_at: '2025-01-01T00:00:00Z',
32
- updated_at: '2025-01-01T00:00:00Z',
33
- };
34
- const issue2 = {
35
- id: 'i-issue2',
36
- uuid: 'uuid-issue2',
37
- type: 'issue',
38
- title: 'Issue 2',
39
- status: 'open',
40
- created_at: '2025-01-01T00:00:00Z',
41
- updated_at: '2025-01-01T00:00:00Z',
42
- };
43
- const issue3 = {
44
- id: 'i-issue3',
45
- uuid: 'uuid-issue3',
46
- type: 'issue',
47
- title: 'Issue 3',
48
- status: 'closed',
49
- created_at: '2025-01-01T00:00:00Z',
50
- updated_at: '2025-01-01T00:00:00Z',
51
- };
52
- const issue4 = {
53
- id: 'i-issue4',
54
- uuid: 'uuid-issue4',
55
- type: 'issue',
56
- title: 'Issue 4',
57
- status: 'open',
58
- created_at: '2025-01-01T00:00:00Z',
59
- updated_at: '2025-01-01T00:00:00Z',
60
- };
61
- const edgeImplements = {
62
- id: 'e-impl',
63
- uuid: 'uuid-impl',
64
- from_id: 'i-issue1',
65
- to_id: 's-spec1',
66
- type: 'implements',
67
- created_at: '2025-01-01T00:00:00Z',
68
- };
69
- const edgeBlocks1 = {
70
- id: 'e-blocks1',
71
- uuid: 'uuid-blocks1',
72
- from_id: 'i-issue1',
73
- to_id: 'i-issue2',
74
- type: 'blocks',
75
- created_at: '2025-01-01T00:00:00Z',
76
- };
77
- const edgeBlocks2 = {
78
- id: 'e-blocks2',
79
- uuid: 'uuid-blocks2',
80
- from_id: 'i-issue2',
81
- to_id: 'i-issue3',
82
- type: 'blocks',
83
- created_at: '2025-01-01T00:00:00Z',
84
- };
85
- const edgeBlocks3 = {
86
- id: 'e-blocks3',
87
- uuid: 'uuid-blocks3',
88
- from_id: 'i-issue1',
89
- to_id: 'i-issue4',
90
- type: 'blocks',
91
- created_at: '2025-01-01T00:00:00Z',
92
- };
93
- function setupGraph() {
94
- adapter.onNodeCreated(spec1);
95
- adapter.onNodeCreated(issue1);
96
- adapter.onNodeCreated(issue2);
97
- adapter.onNodeCreated(issue3);
98
- adapter.onNodeCreated(issue4);
99
- adapter.onEdgeCreated(edgeImplements);
100
- adapter.onEdgeCreated(edgeBlocks1);
101
- adapter.onEdgeCreated(edgeBlocks2);
102
- adapter.onEdgeCreated(edgeBlocks3);
103
- }
104
- describe('related()', () => {
105
- beforeEach(setupGraph);
106
- it('returns outgoing neighbors', () => {
107
- const result = graph.related('native://i-issue1', { direction: 'out' });
108
- expect(result).toHaveLength(3);
109
- expect(result).toContain('native://s-spec1');
110
- expect(result).toContain('native://i-issue2');
111
- expect(result).toContain('native://i-issue4');
112
- });
113
- it('returns incoming neighbors', () => {
114
- const result = graph.related('native://i-issue2', { direction: 'in' });
115
- expect(result).toHaveLength(1);
116
- expect(result).toContain('native://i-issue1');
117
- });
118
- it('returns both directions by default', () => {
119
- const result = graph.related('native://i-issue2');
120
- expect(result).toHaveLength(2);
121
- expect(result).toContain('native://i-issue1'); // incoming
122
- expect(result).toContain('native://i-issue3'); // outgoing
123
- });
124
- it('filters by edge type (string)', () => {
125
- const result = graph.related('native://i-issue1', {
126
- direction: 'out',
127
- edgeType: 'blocks',
128
- });
129
- expect(result).toHaveLength(2);
130
- expect(result).toContain('native://i-issue2');
131
- expect(result).toContain('native://i-issue4');
132
- expect(result).not.toContain('native://s-spec1');
133
- });
134
- it('filters by edge type (array)', () => {
135
- const result = graph.related('native://i-issue1', {
136
- direction: 'out',
137
- edgeType: ['implements'],
138
- });
139
- expect(result).toHaveLength(1);
140
- expect(result).toContain('native://s-spec1');
141
- });
142
- it('returns empty for non-existent node', () => {
143
- const result = graph.related('native://non-existent');
144
- expect(result).toHaveLength(0);
145
- });
146
- it('removes duplicates with both direction', () => {
147
- // Create a bidirectional relationship
148
- adapter.onEdgeCreated({
149
- id: 'e-related1',
150
- uuid: 'uuid-related1',
151
- from_id: 'i-issue2',
152
- to_id: 'i-issue1',
153
- type: 'related',
154
- created_at: '2025-01-01T00:00:00Z',
155
- });
156
- const result = graph.related('native://i-issue1', {
157
- direction: 'both',
158
- edgeType: ['blocks', 'related'],
159
- });
160
- // issue2 should only appear once even though there are edges in both directions
161
- const issue2Count = result.filter((r) => r === 'native://i-issue2').length;
162
- expect(issue2Count).toBe(1);
163
- });
164
- });
165
- describe('reachable()', () => {
166
- beforeEach(setupGraph);
167
- it('returns transitively reachable nodes (out)', () => {
168
- const result = graph.reachable('native://i-issue1', {
169
- direction: 'out',
170
- edgeType: 'blocks',
171
- });
172
- expect(result).toHaveLength(3);
173
- expect(result).toContain('native://i-issue2');
174
- expect(result).toContain('native://i-issue3');
175
- expect(result).toContain('native://i-issue4');
176
- });
177
- it('returns transitively reachable nodes (in)', () => {
178
- const result = graph.reachable('native://i-issue3', {
179
- direction: 'in',
180
- edgeType: 'blocks',
181
- });
182
- expect(result).toHaveLength(2);
183
- expect(result).toContain('native://i-issue2');
184
- expect(result).toContain('native://i-issue1');
185
- });
186
- it('respects maxDepth', () => {
187
- const result = graph.reachable('native://i-issue1', {
188
- direction: 'out',
189
- edgeType: 'blocks',
190
- maxDepth: 1,
191
- });
192
- expect(result).toHaveLength(2);
193
- expect(result).toContain('native://i-issue2');
194
- expect(result).toContain('native://i-issue4');
195
- expect(result).not.toContain('native://i-issue3'); // 2 hops away
196
- });
197
- it('does not include start node', () => {
198
- const result = graph.reachable('native://i-issue1', { direction: 'out' });
199
- expect(result).not.toContain('native://i-issue1');
200
- });
201
- it('handles cycles without infinite loop', () => {
202
- // Create a cycle: issue3 -> issue1
203
- adapter.onEdgeCreated({
204
- id: 'e-cycle',
205
- uuid: 'uuid-cycle',
206
- from_id: 'i-issue3',
207
- to_id: 'i-issue1',
208
- type: 'blocks',
209
- created_at: '2025-01-01T00:00:00Z',
210
- });
211
- const result = graph.reachable('native://i-issue1', {
212
- direction: 'out',
213
- edgeType: 'blocks',
214
- });
215
- // Should terminate and include all reachable nodes exactly once
216
- expect(result).toHaveLength(3);
217
- });
218
- it('returns empty for non-existent node', () => {
219
- const result = graph.reachable('native://non-existent');
220
- expect(result).toHaveLength(0);
221
- });
222
- it('filters by multiple edge types', () => {
223
- const result = graph.reachable('native://i-issue1', {
224
- direction: 'out',
225
- edgeType: ['blocks', 'implements'],
226
- });
227
- expect(result).toHaveLength(4);
228
- expect(result).toContain('native://s-spec1');
229
- expect(result).toContain('native://i-issue2');
230
- expect(result).toContain('native://i-issue3');
231
- expect(result).toContain('native://i-issue4');
232
- });
233
- });
234
- describe('shortestPath()', () => {
235
- beforeEach(setupGraph);
236
- it('finds shortest path', () => {
237
- const result = graph.shortestPath('native://i-issue1', 'native://i-issue3');
238
- expect(result).not.toBeNull();
239
- expect(result).toHaveLength(3);
240
- expect(result[0]).toBe('native://i-issue1');
241
- expect(result[1]).toBe('native://i-issue2');
242
- expect(result[2]).toBe('native://i-issue3');
243
- });
244
- it('returns path of length 1 for adjacent nodes', () => {
245
- const result = graph.shortestPath('native://i-issue1', 'native://i-issue2');
246
- expect(result).toHaveLength(2);
247
- });
248
- it('returns path of length 0 for same node', () => {
249
- const result = graph.shortestPath('native://i-issue1', 'native://i-issue1');
250
- expect(result).toHaveLength(1);
251
- expect(result[0]).toBe('native://i-issue1');
252
- });
253
- it('returns null for non-existent start node', () => {
254
- const result = graph.shortestPath('native://non-existent', 'native://i-issue1');
255
- expect(result).toBeNull();
256
- });
257
- it('returns null for non-existent end node', () => {
258
- const result = graph.shortestPath('native://i-issue1', 'native://non-existent');
259
- expect(result).toBeNull();
260
- });
261
- it('returns null when no path exists', () => {
262
- // Create an isolated node
263
- adapter.onNodeCreated({
264
- id: 'i-isolated',
265
- uuid: 'uuid-isolated',
266
- type: 'issue',
267
- title: 'Isolated',
268
- created_at: '2025-01-01T00:00:00Z',
269
- updated_at: '2025-01-01T00:00:00Z',
270
- });
271
- const result = graph.shortestPath('native://i-issue1', 'native://i-isolated');
272
- expect(result).toBeNull();
273
- });
274
- it('filters by edge types', () => {
275
- // issue1 -> issue2 is via 'blocks'
276
- // There's no 'implements' path from issue1 to issue2
277
- const result = graph.shortestPath('native://i-issue1', 'native://i-issue2', {
278
- edgeTypes: ['implements'],
279
- });
280
- expect(result).toBeNull();
281
- });
282
- });
283
- describe('hasPath()', () => {
284
- beforeEach(setupGraph);
285
- it('returns true when path exists', () => {
286
- expect(graph.hasPath('native://i-issue1', 'native://i-issue3')).toBe(true);
287
- });
288
- it('returns false when no path exists', () => {
289
- adapter.onNodeCreated({
290
- id: 'i-isolated',
291
- uuid: 'uuid-isolated',
292
- type: 'issue',
293
- title: 'Isolated',
294
- created_at: '2025-01-01T00:00:00Z',
295
- updated_at: '2025-01-01T00:00:00Z',
296
- });
297
- expect(graph.hasPath('native://i-issue1', 'native://i-isolated')).toBe(false);
298
- });
299
- });
300
- describe('getNode()', () => {
301
- beforeEach(setupGraph);
302
- it('returns node attributes', () => {
303
- const node = graph.getNode('native://i-issue1');
304
- expect(node).not.toBeNull();
305
- expect(node.title).toBe('Issue 1');
306
- expect(node.type).toBe('issue');
307
- });
308
- it('returns null for non-existent node', () => {
309
- expect(graph.getNode('native://non-existent')).toBeNull();
310
- });
311
- });
312
- describe('hasNode()', () => {
313
- beforeEach(setupGraph);
314
- it('returns true for existing node', () => {
315
- expect(graph.hasNode('native://i-issue1')).toBe(true);
316
- });
317
- it('returns false for non-existent node', () => {
318
- expect(graph.hasNode('native://non-existent')).toBe(false);
319
- });
320
- });
321
- describe('nodes()', () => {
322
- beforeEach(setupGraph);
323
- it('returns all node URIs', () => {
324
- const nodes = graph.nodes();
325
- expect(nodes).toHaveLength(5);
326
- expect(nodes).toContain('native://s-spec1');
327
- expect(nodes).toContain('native://i-issue1');
328
- expect(nodes).toContain('native://i-issue2');
329
- expect(nodes).toContain('native://i-issue3');
330
- expect(nodes).toContain('native://i-issue4');
331
- });
332
- });
333
- describe('stats()', () => {
334
- beforeEach(setupGraph);
335
- it('returns correct node and edge counts', () => {
336
- const stats = graph.stats();
337
- expect(stats.nodes).toBe(5);
338
- expect(stats.edges).toBe(4);
339
- });
340
- });
341
- describe('traverse()', () => {
342
- beforeEach(setupGraph);
343
- it('traverses single step pattern', async () => {
344
- const results = [];
345
- for await (const result of graph.traverse('native://i-issue1', {
346
- steps: [{ type: 'blocks', direction: 'out' }],
347
- })) {
348
- results.push(result.uri);
349
- }
350
- expect(results).toContain('native://i-issue2');
351
- expect(results).toContain('native://i-issue4');
352
- expect(results).not.toContain('native://s-spec1'); // implements, not blocks
353
- });
354
- it('traverses multi-step pattern', async () => {
355
- // First find specs, then issues that implement them
356
- const results = [];
357
- for await (const result of graph.traverse('native://i-issue1', {
358
- steps: [
359
- { type: 'implements', direction: 'out' }, // i-issue1 -> s-spec1
360
- { type: 'implements', direction: 'in' }, // s-spec1 <- other issues
361
- ],
362
- })) {
363
- results.push(result.uri);
364
- }
365
- // Should find s-spec1 first, then back to i-issue1
366
- expect(results).toContain('native://s-spec1');
367
- expect(results).toContain('native://i-issue1');
368
- });
369
- it('traverses with maxHops=Infinity for transitive closure', async () => {
370
- const results = [];
371
- for await (const result of graph.traverse('native://i-issue1', {
372
- steps: [{ type: 'blocks', direction: 'out', maxHops: Infinity }],
373
- })) {
374
- results.push(result.uri);
375
- }
376
- // Should find all transitively blocked issues
377
- expect(results).toContain('native://i-issue2');
378
- expect(results).toContain('native://i-issue3');
379
- expect(results).toContain('native://i-issue4');
380
- });
381
- it('respects limit option', async () => {
382
- const results = [];
383
- for await (const result of graph.traverse('native://i-issue1', {
384
- steps: [{ type: 'blocks', direction: 'out', maxHops: Infinity }],
385
- limit: 2,
386
- })) {
387
- results.push(result.uri);
388
- }
389
- expect(results).toHaveLength(2);
390
- });
391
- it('tracks depth correctly', async () => {
392
- const depths = [];
393
- for await (const result of graph.traverse('native://i-issue1', {
394
- steps: [{ type: 'blocks', direction: 'out', maxHops: Infinity }],
395
- })) {
396
- depths.push(result.depth);
397
- }
398
- // issue2 and issue4 are depth 1, issue3 is depth 2
399
- expect(depths).toContain(1);
400
- expect(depths).toContain(2);
401
- });
402
- it('tracks path correctly', async () => {
403
- let issue3Path = [];
404
- for await (const result of graph.traverse('native://i-issue1', {
405
- steps: [{ type: 'blocks', direction: 'out', maxHops: Infinity }],
406
- })) {
407
- if (result.uri === 'native://i-issue3') {
408
- issue3Path = result.path;
409
- break;
410
- }
411
- }
412
- // Path should be: issue1 -> issue2 -> issue3
413
- expect(issue3Path).toEqual([
414
- 'native://i-issue1',
415
- 'native://i-issue2',
416
- 'native://i-issue3',
417
- ]);
418
- });
419
- it('handles multiple start URIs', async () => {
420
- const results = [];
421
- for await (const result of graph.traverse(['native://i-issue1', 'native://i-issue2'], { steps: [{ type: 'blocks', direction: 'out' }] })) {
422
- results.push(result.uri);
423
- }
424
- // issue1 blocks issue2 and issue4
425
- // issue2 blocks issue3
426
- expect(results).toContain('native://i-issue2');
427
- expect(results).toContain('native://i-issue3');
428
- expect(results).toContain('native://i-issue4');
429
- });
430
- it('handles non-existent start URI', async () => {
431
- const results = [];
432
- for await (const result of graph.traverse('native://non-existent', {
433
- steps: [{ type: 'blocks', direction: 'out' }],
434
- })) {
435
- results.push(result.uri);
436
- }
437
- expect(results).toHaveLength(0);
438
- });
439
- it('handles empty steps', async () => {
440
- const results = [];
441
- for await (const result of graph.traverse('native://i-issue1', {
442
- steps: [],
443
- })) {
444
- results.push(result.uri);
445
- }
446
- expect(results).toHaveLength(0);
447
- });
448
- it('respects minHops option', async () => {
449
- const results = [];
450
- for await (const result of graph.traverse('native://i-issue1', {
451
- steps: [{ type: 'blocks', direction: 'out', minHops: 2, maxHops: 2 }],
452
- })) {
453
- results.push(result.uri);
454
- }
455
- // Only issue3 is exactly 2 hops away via blocks
456
- expect(results).toContain('native://i-issue3');
457
- expect(results).not.toContain('native://i-issue2'); // 1 hop
458
- expect(results).not.toContain('native://i-issue4'); // 1 hop
459
- });
460
- it('handles cycles without infinite loop', async () => {
461
- // Add a cycle: issue3 -> issue1
462
- adapter.onEdgeCreated({
463
- id: 'e-cycle',
464
- uuid: 'uuid-cycle',
465
- from_id: 'i-issue3',
466
- to_id: 'i-issue1',
467
- type: 'blocks',
468
- created_at: '2025-01-01T00:00:00Z',
469
- });
470
- const results = [];
471
- for await (const result of graph.traverse('native://i-issue1', {
472
- steps: [{ type: 'blocks', direction: 'out', maxHops: 10 }],
473
- })) {
474
- results.push(result.uri);
475
- }
476
- // Should not hang, and should not include duplicates
477
- expect(results.length).toBeLessThanOrEqual(4);
478
- });
479
- it('includes stepIndex and edgeType in results', async () => {
480
- for await (const result of graph.traverse('native://i-issue1', {
481
- steps: [{ type: 'blocks', direction: 'out' }],
482
- })) {
483
- expect(result.stepIndex).toBe(0);
484
- expect(result.edgeType).toBe('blocks');
485
- break;
486
- }
487
- });
488
- it('applies filter predicate to exclude nodes', async () => {
489
- const results = [];
490
- for await (const result of graph.traverse('native://i-issue1', {
491
- steps: [{ type: 'blocks', direction: 'out', maxHops: Infinity }],
492
- filter: (uri, attrs) => {
493
- // Only include open issues
494
- return attrs?.data?.status === 'open';
495
- },
496
- })) {
497
- results.push(result.uri);
498
- }
499
- // Should include issue2 and issue4 (open) but not issue3 (closed)
500
- expect(results).toContain('native://i-issue2');
501
- expect(results).toContain('native://i-issue4');
502
- expect(results).not.toContain('native://i-issue3');
503
- });
504
- it('filter continues traversal through filtered nodes', async () => {
505
- // Add another edge: issue3 -> issue5
506
- adapter.onNodeCreated({
507
- id: 'i-issue5',
508
- uuid: 'uuid-issue5',
509
- type: 'issue',
510
- title: 'Issue 5',
511
- status: 'open',
512
- created_at: '2025-01-01T00:00:00Z',
513
- updated_at: '2025-01-01T00:00:00Z',
514
- });
515
- adapter.onEdgeCreated({
516
- id: 'e-blocks4',
517
- uuid: 'uuid-blocks4',
518
- from_id: 'i-issue3',
519
- to_id: 'i-issue5',
520
- type: 'blocks',
521
- created_at: '2025-01-01T00:00:00Z',
522
- });
523
- const results = [];
524
- for await (const result of graph.traverse('native://i-issue1', {
525
- steps: [{ type: 'blocks', direction: 'out', maxHops: Infinity }],
526
- filter: (uri, attrs) => attrs?.data?.status === 'open',
527
- })) {
528
- results.push(result.uri);
529
- }
530
- // Should find issue5 even though it goes through filtered issue3
531
- expect(results).toContain('native://i-issue5');
532
- expect(results).not.toContain('native://i-issue3');
533
- });
534
- });
535
- describe('parseSelector()', () => {
536
- it('parses children selector (+uri)', () => {
537
- const result = graph.parseSelector('+native://s-spec1');
538
- expect(result.type).toBe('children');
539
- expect(result.uri).toBe('native://s-spec1');
540
- expect(result.original).toBe('+native://s-spec1');
541
- });
542
- it('parses descendants selector (uri+)', () => {
543
- const result = graph.parseSelector('native://i-issue1+');
544
- expect(result.type).toBe('descendants');
545
- expect(result.uri).toBe('native://i-issue1');
546
- expect(result.original).toBe('native://i-issue1+');
547
- });
548
- it('parses neighbors selector (@uri)', () => {
549
- const result = graph.parseSelector('@native://i-issue2');
550
- expect(result.type).toBe('neighbors');
551
- expect(result.uri).toBe('native://i-issue2');
552
- expect(result.original).toBe('@native://i-issue2');
553
- });
554
- it('parses literal URI', () => {
555
- const result = graph.parseSelector('native://i-issue1');
556
- expect(result.type).toBe('literal');
557
- expect(result.uri).toBe('native://i-issue1');
558
- expect(result.original).toBe('native://i-issue1');
559
- });
560
- });
561
- describe('expandSelector()', () => {
562
- beforeEach(setupGraph);
563
- it('expands literal to the node if exists', () => {
564
- const result = graph.expandSelector('native://i-issue1');
565
- expect(result).toEqual(['native://i-issue1']);
566
- });
567
- it('expands literal to empty if not exists', () => {
568
- const result = graph.expandSelector('native://non-existent');
569
- expect(result).toEqual([]);
570
- });
571
- it('expands children selector to direct outgoing neighbors', () => {
572
- const result = graph.expandSelector('+native://i-issue1');
573
- expect(result).toHaveLength(3);
574
- expect(result).toContain('native://s-spec1');
575
- expect(result).toContain('native://i-issue2');
576
- expect(result).toContain('native://i-issue4');
577
- });
578
- it('expands children selector with edge type filter', () => {
579
- const result = graph.expandSelector('+native://i-issue1', { edgeType: 'blocks' });
580
- expect(result).toHaveLength(2);
581
- expect(result).toContain('native://i-issue2');
582
- expect(result).toContain('native://i-issue4');
583
- expect(result).not.toContain('native://s-spec1');
584
- });
585
- it('expands descendants selector transitively', () => {
586
- const result = graph.expandSelector('native://i-issue1+');
587
- // Should include all transitively reachable nodes
588
- expect(result).toContain('native://s-spec1');
589
- expect(result).toContain('native://i-issue2');
590
- expect(result).toContain('native://i-issue3');
591
- expect(result).toContain('native://i-issue4');
592
- });
593
- it('expands descendants with edge type filter', () => {
594
- const result = graph.expandSelector('native://i-issue1+', { edgeType: 'blocks' });
595
- expect(result).toHaveLength(3);
596
- expect(result).toContain('native://i-issue2');
597
- expect(result).toContain('native://i-issue3');
598
- expect(result).toContain('native://i-issue4');
599
- expect(result).not.toContain('native://s-spec1');
600
- });
601
- it('expands neighbors selector to all connected nodes', () => {
602
- const result = graph.expandSelector('@native://i-issue2');
603
- expect(result).toHaveLength(2);
604
- expect(result).toContain('native://i-issue1'); // incoming
605
- expect(result).toContain('native://i-issue3'); // outgoing
606
- });
607
- it('expands neighbors with edge type filter', () => {
608
- const result = graph.expandSelector('@native://i-issue1', { edgeType: 'implements' });
609
- expect(result).toHaveLength(1);
610
- expect(result).toContain('native://s-spec1');
611
- });
612
- it('returns empty for non-existent node selectors', () => {
613
- expect(graph.expandSelector('+native://non-existent')).toEqual([]);
614
- expect(graph.expandSelector('native://non-existent+')).toEqual([]);
615
- expect(graph.expandSelector('@native://non-existent')).toEqual([]);
616
- });
617
- });
618
- describe('edgeTypes()', () => {
619
- it('returns all registered edge types', () => {
620
- const types = graph.edgeTypes();
621
- expect(types.length).toBeGreaterThan(0);
622
- // Should include built-in types
623
- const typeNames = types.map((t) => t.name);
624
- expect(typeNames).toContain('blocks');
625
- expect(typeNames).toContain('implements');
626
- expect(typeNames).toContain('parent-of');
627
- expect(typeNames).toContain('related');
628
- });
629
- it('includes edge type metadata', () => {
630
- const types = graph.edgeTypes();
631
- const blocksType = types.find((t) => t.name === 'blocks');
632
- expect(blocksType).toBeDefined();
633
- expect(blocksType.description).toBeDefined();
634
- expect(blocksType.inverseOf).toBe('blocked-by');
635
- expect(blocksType.affectsReady).toBe(true);
636
- expect(blocksType.direction).toBe('directed');
637
- });
638
- });
639
- describe('capabilities()', () => {
640
- it('returns graph capabilities', () => {
641
- const caps = graph.capabilities();
642
- expect(caps.edgeTypes).toBeDefined();
643
- expect(caps.edgeTypes.length).toBeGreaterThan(0);
644
- });
645
- it('includes ready-affecting types', () => {
646
- const caps = graph.capabilities();
647
- expect(caps.readyAffectingTypes).toContain('blocks');
648
- expect(caps.readyAffectingTypes).toContain('blocked-by');
649
- });
650
- it('includes provider-specific capabilities', () => {
651
- const caps = graph.capabilities();
652
- expect(caps.providers).toBeDefined();
653
- expect(caps.providers.get('native')).toBeDefined();
654
- const nativeTypes = caps.providers.get('native');
655
- const nativeTypeNames = nativeTypes.map((t) => t.name);
656
- expect(nativeTypeNames).toContain('blocks');
657
- expect(nativeTypeNames).toContain('implements');
658
- });
659
- });
660
- });
661
- //# sourceMappingURL=FederatedGraph.test.js.map