opentasks 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (662) hide show
  1. package/README.md +344 -1
  2. package/dist/__tests__/cli-tools.test.d.ts +8 -0
  3. package/dist/__tests__/cli-tools.test.d.ts.map +1 -0
  4. package/dist/__tests__/cli-tools.test.js +546 -0
  5. package/dist/__tests__/cli-tools.test.js.map +1 -0
  6. package/dist/__tests__/cli.test.d.ts +5 -0
  7. package/dist/__tests__/cli.test.d.ts.map +1 -0
  8. package/dist/__tests__/cli.test.js +77 -0
  9. package/dist/__tests__/cli.test.js.map +1 -0
  10. package/dist/__tests__/p1-p3-gaps.test.d.ts +2 -0
  11. package/dist/__tests__/p1-p3-gaps.test.d.ts.map +1 -0
  12. package/dist/__tests__/p1-p3-gaps.test.js +463 -0
  13. package/dist/__tests__/p1-p3-gaps.test.js.map +1 -0
  14. package/dist/cli.d.ts +19 -1
  15. package/dist/cli.d.ts.map +1 -1
  16. package/dist/cli.js +702 -23
  17. package/dist/cli.js.map +1 -1
  18. package/dist/client/__tests__/client-crud.test.d.ts +7 -0
  19. package/dist/client/__tests__/client-crud.test.d.ts.map +1 -0
  20. package/dist/client/__tests__/client-crud.test.js +404 -0
  21. package/dist/client/__tests__/client-crud.test.js.map +1 -0
  22. package/dist/client/__tests__/client.test.d.ts +5 -0
  23. package/dist/client/__tests__/client.test.d.ts.map +1 -0
  24. package/dist/client/__tests__/client.test.js +518 -0
  25. package/dist/client/__tests__/client.test.js.map +1 -0
  26. package/dist/client/client.d.ts +228 -0
  27. package/dist/client/client.d.ts.map +1 -0
  28. package/dist/client/client.js +393 -0
  29. package/dist/client/client.js.map +1 -0
  30. package/dist/client/index.d.ts +11 -0
  31. package/dist/client/index.d.ts.map +1 -0
  32. package/dist/client/index.js +9 -0
  33. package/dist/client/index.js.map +1 -0
  34. package/dist/config/__tests__/defaults.test.d.ts +2 -0
  35. package/dist/config/__tests__/defaults.test.d.ts.map +1 -0
  36. package/dist/config/__tests__/defaults.test.js +57 -0
  37. package/dist/config/__tests__/defaults.test.js.map +1 -0
  38. package/dist/config/__tests__/env.test.d.ts +2 -0
  39. package/dist/config/__tests__/env.test.d.ts.map +1 -0
  40. package/dist/config/__tests__/env.test.js +136 -0
  41. package/dist/config/__tests__/env.test.js.map +1 -0
  42. package/dist/config/__tests__/index.test.d.ts +2 -0
  43. package/dist/config/__tests__/index.test.d.ts.map +1 -0
  44. package/dist/config/__tests__/index.test.js +113 -0
  45. package/dist/config/__tests__/index.test.js.map +1 -0
  46. package/dist/config/__tests__/loader.test.d.ts +2 -0
  47. package/dist/config/__tests__/loader.test.d.ts.map +1 -0
  48. package/dist/config/__tests__/loader.test.js +128 -0
  49. package/dist/config/__tests__/loader.test.js.map +1 -0
  50. package/dist/config/__tests__/merge.test.d.ts +2 -0
  51. package/dist/config/__tests__/merge.test.d.ts.map +1 -0
  52. package/dist/config/__tests__/merge.test.js +79 -0
  53. package/dist/config/__tests__/merge.test.js.map +1 -0
  54. package/dist/config/__tests__/schema.test.d.ts +2 -0
  55. package/dist/config/__tests__/schema.test.d.ts.map +1 -0
  56. package/dist/config/__tests__/schema.test.js +300 -0
  57. package/dist/config/__tests__/schema.test.js.map +1 -0
  58. package/dist/config/defaults.d.ts +13 -0
  59. package/dist/config/defaults.d.ts.map +1 -0
  60. package/dist/config/defaults.js +15 -0
  61. package/dist/config/defaults.js.map +1 -0
  62. package/dist/config/env.d.ts +14 -0
  63. package/dist/config/env.d.ts.map +1 -0
  64. package/dist/config/env.js +130 -0
  65. package/dist/config/env.js.map +1 -0
  66. package/dist/config/errors.d.ts +21 -0
  67. package/dist/config/errors.d.ts.map +1 -0
  68. package/dist/config/errors.js +30 -0
  69. package/dist/config/errors.js.map +1 -0
  70. package/dist/config/index.d.ts +21 -0
  71. package/dist/config/index.d.ts.map +1 -0
  72. package/dist/config/index.js +41 -0
  73. package/dist/config/index.js.map +1 -0
  74. package/dist/config/loader.d.ts +8 -0
  75. package/dist/config/loader.d.ts.map +1 -0
  76. package/dist/config/loader.js +87 -0
  77. package/dist/config/loader.js.map +1 -0
  78. package/dist/config/merge.d.ts +12 -0
  79. package/dist/config/merge.d.ts.map +1 -0
  80. package/dist/config/merge.js +54 -0
  81. package/dist/config/merge.js.map +1 -0
  82. package/dist/config/schema.d.ts +644 -0
  83. package/dist/config/schema.d.ts.map +1 -0
  84. package/dist/config/schema.js +491 -0
  85. package/dist/config/schema.js.map +1 -0
  86. package/dist/core/__tests__/conditional-redirects.test.d.ts +2 -0
  87. package/dist/core/__tests__/conditional-redirects.test.d.ts.map +1 -0
  88. package/dist/core/__tests__/conditional-redirects.test.js +83 -0
  89. package/dist/core/__tests__/conditional-redirects.test.js.map +1 -0
  90. package/dist/core/__tests__/connections.test.d.ts +2 -0
  91. package/dist/core/__tests__/connections.test.d.ts.map +1 -0
  92. package/dist/core/__tests__/connections.test.js +158 -0
  93. package/dist/core/__tests__/connections.test.js.map +1 -0
  94. package/dist/core/__tests__/hash.test.d.ts +2 -0
  95. package/dist/core/__tests__/hash.test.d.ts.map +1 -0
  96. package/dist/core/__tests__/hash.test.js +139 -0
  97. package/dist/core/__tests__/hash.test.js.map +1 -0
  98. package/dist/core/__tests__/id.test.d.ts +2 -0
  99. package/dist/core/__tests__/id.test.d.ts.map +1 -0
  100. package/dist/core/__tests__/id.test.js +142 -0
  101. package/dist/core/__tests__/id.test.js.map +1 -0
  102. package/dist/core/__tests__/location.test.d.ts +2 -0
  103. package/dist/core/__tests__/location.test.d.ts.map +1 -0
  104. package/dist/core/__tests__/location.test.js +77 -0
  105. package/dist/core/__tests__/location.test.js.map +1 -0
  106. package/dist/core/__tests__/merge-driver.test.d.ts +2 -0
  107. package/dist/core/__tests__/merge-driver.test.d.ts.map +1 -0
  108. package/dist/core/__tests__/merge-driver.test.js +218 -0
  109. package/dist/core/__tests__/merge-driver.test.js.map +1 -0
  110. package/dist/core/__tests__/redirects.test.d.ts +2 -0
  111. package/dist/core/__tests__/redirects.test.d.ts.map +1 -0
  112. package/dist/core/__tests__/redirects.test.js +123 -0
  113. package/dist/core/__tests__/redirects.test.js.map +1 -0
  114. package/dist/core/__tests__/resolve-location-target.test.d.ts +8 -0
  115. package/dist/core/__tests__/resolve-location-target.test.d.ts.map +1 -0
  116. package/dist/core/__tests__/resolve-location-target.test.js +303 -0
  117. package/dist/core/__tests__/resolve-location-target.test.js.map +1 -0
  118. package/dist/core/__tests__/uri.test.d.ts +2 -0
  119. package/dist/core/__tests__/uri.test.d.ts.map +1 -0
  120. package/dist/core/__tests__/uri.test.js +159 -0
  121. package/dist/core/__tests__/uri.test.js.map +1 -0
  122. package/dist/core/__tests__/worktree.test.d.ts +2 -0
  123. package/dist/core/__tests__/worktree.test.d.ts.map +1 -0
  124. package/dist/core/__tests__/worktree.test.js +120 -0
  125. package/dist/core/__tests__/worktree.test.js.map +1 -0
  126. package/dist/core/conditional-redirects.d.ts +42 -0
  127. package/dist/core/conditional-redirects.d.ts.map +1 -0
  128. package/dist/core/conditional-redirects.js +59 -0
  129. package/dist/core/conditional-redirects.js.map +1 -0
  130. package/dist/core/connections.d.ts +87 -0
  131. package/dist/core/connections.d.ts.map +1 -0
  132. package/dist/core/connections.js +160 -0
  133. package/dist/core/connections.js.map +1 -0
  134. package/dist/core/discover.d.ts +39 -0
  135. package/dist/core/discover.d.ts.map +1 -0
  136. package/dist/core/discover.js +136 -0
  137. package/dist/core/discover.js.map +1 -0
  138. package/dist/core/hash.d.ts +25 -0
  139. package/dist/core/hash.d.ts.map +1 -0
  140. package/dist/core/hash.js +62 -0
  141. package/dist/core/hash.js.map +1 -0
  142. package/dist/core/id.d.ts +79 -0
  143. package/dist/core/id.d.ts.map +1 -0
  144. package/dist/core/id.js +141 -0
  145. package/dist/core/id.js.map +1 -0
  146. package/dist/core/index.d.ts +15 -0
  147. package/dist/core/index.d.ts.map +1 -0
  148. package/dist/core/index.js +24 -0
  149. package/dist/core/index.js.map +1 -0
  150. package/dist/core/location.d.ts +70 -0
  151. package/dist/core/location.d.ts.map +1 -0
  152. package/dist/core/location.js +121 -0
  153. package/dist/core/location.js.map +1 -0
  154. package/dist/core/merge-driver.d.ts +50 -0
  155. package/dist/core/merge-driver.d.ts.map +1 -0
  156. package/dist/core/merge-driver.js +258 -0
  157. package/dist/core/merge-driver.js.map +1 -0
  158. package/dist/core/redirects.d.ts +91 -0
  159. package/dist/core/redirects.d.ts.map +1 -0
  160. package/dist/core/redirects.js +113 -0
  161. package/dist/core/redirects.js.map +1 -0
  162. package/dist/core/uri.d.ts +105 -0
  163. package/dist/core/uri.d.ts.map +1 -0
  164. package/dist/core/uri.js +190 -0
  165. package/dist/core/uri.js.map +1 -0
  166. package/dist/core/worktree.d.ts +106 -0
  167. package/dist/core/worktree.d.ts.map +1 -0
  168. package/dist/core/worktree.js +394 -0
  169. package/dist/core/worktree.js.map +1 -0
  170. package/dist/daemon/__tests__/flush.test.d.ts +5 -0
  171. package/dist/daemon/__tests__/flush.test.d.ts.map +1 -0
  172. package/dist/daemon/__tests__/flush.test.js +213 -0
  173. package/dist/daemon/__tests__/flush.test.js.map +1 -0
  174. package/dist/daemon/__tests__/integration.test.d.ts +7 -0
  175. package/dist/daemon/__tests__/integration.test.d.ts.map +1 -0
  176. package/dist/daemon/__tests__/integration.test.js +276 -0
  177. package/dist/daemon/__tests__/integration.test.js.map +1 -0
  178. package/dist/daemon/__tests__/ipc.test.d.ts +5 -0
  179. package/dist/daemon/__tests__/ipc.test.d.ts.map +1 -0
  180. package/dist/daemon/__tests__/ipc.test.js +314 -0
  181. package/dist/daemon/__tests__/ipc.test.js.map +1 -0
  182. package/dist/daemon/__tests__/lifecycle.test.d.ts +5 -0
  183. package/dist/daemon/__tests__/lifecycle.test.d.ts.map +1 -0
  184. package/dist/daemon/__tests__/lifecycle.test.js +301 -0
  185. package/dist/daemon/__tests__/lifecycle.test.js.map +1 -0
  186. package/dist/daemon/__tests__/lock.test.d.ts +5 -0
  187. package/dist/daemon/__tests__/lock.test.d.ts.map +1 -0
  188. package/dist/daemon/__tests__/lock.test.js +192 -0
  189. package/dist/daemon/__tests__/lock.test.js.map +1 -0
  190. package/dist/daemon/__tests__/methods/graph.test.d.ts +5 -0
  191. package/dist/daemon/__tests__/methods/graph.test.d.ts.map +1 -0
  192. package/dist/daemon/__tests__/methods/graph.test.js +309 -0
  193. package/dist/daemon/__tests__/methods/graph.test.js.map +1 -0
  194. package/dist/daemon/__tests__/methods/provider.test.d.ts +7 -0
  195. package/dist/daemon/__tests__/methods/provider.test.d.ts.map +1 -0
  196. package/dist/daemon/__tests__/methods/provider.test.js +181 -0
  197. package/dist/daemon/__tests__/methods/provider.test.js.map +1 -0
  198. package/dist/daemon/__tests__/methods/tools.test.d.ts +5 -0
  199. package/dist/daemon/__tests__/methods/tools.test.d.ts.map +1 -0
  200. package/dist/daemon/__tests__/methods/tools.test.js +587 -0
  201. package/dist/daemon/__tests__/methods/tools.test.js.map +1 -0
  202. package/dist/daemon/__tests__/multi-location.test.d.ts +8 -0
  203. package/dist/daemon/__tests__/multi-location.test.d.ts.map +1 -0
  204. package/dist/daemon/__tests__/multi-location.test.js +669 -0
  205. package/dist/daemon/__tests__/multi-location.test.js.map +1 -0
  206. package/dist/daemon/__tests__/registry.test.d.ts +5 -0
  207. package/dist/daemon/__tests__/registry.test.d.ts.map +1 -0
  208. package/dist/daemon/__tests__/registry.test.js +208 -0
  209. package/dist/daemon/__tests__/registry.test.js.map +1 -0
  210. package/dist/daemon/__tests__/watcher.test.d.ts +5 -0
  211. package/dist/daemon/__tests__/watcher.test.d.ts.map +1 -0
  212. package/dist/daemon/__tests__/watcher.test.js +234 -0
  213. package/dist/daemon/__tests__/watcher.test.js.map +1 -0
  214. package/dist/daemon/entire-linker.d.ts +68 -0
  215. package/dist/daemon/entire-linker.d.ts.map +1 -0
  216. package/dist/daemon/entire-linker.js +439 -0
  217. package/dist/daemon/entire-linker.js.map +1 -0
  218. package/dist/daemon/entire-watcher.d.ts +66 -0
  219. package/dist/daemon/entire-watcher.d.ts.map +1 -0
  220. package/dist/daemon/entire-watcher.js +258 -0
  221. package/dist/daemon/entire-watcher.js.map +1 -0
  222. package/dist/daemon/factory.d.ts +59 -0
  223. package/dist/daemon/factory.d.ts.map +1 -0
  224. package/dist/daemon/factory.js +72 -0
  225. package/dist/daemon/factory.js.map +1 -0
  226. package/dist/daemon/flush.d.ts +51 -0
  227. package/dist/daemon/flush.d.ts.map +1 -0
  228. package/dist/daemon/flush.js +89 -0
  229. package/dist/daemon/flush.js.map +1 -0
  230. package/dist/daemon/index.d.ts +39 -0
  231. package/dist/daemon/index.d.ts.map +1 -0
  232. package/dist/daemon/index.js +24 -0
  233. package/dist/daemon/index.js.map +1 -0
  234. package/dist/daemon/ipc.d.ts +97 -0
  235. package/dist/daemon/ipc.d.ts.map +1 -0
  236. package/dist/daemon/ipc.js +304 -0
  237. package/dist/daemon/ipc.js.map +1 -0
  238. package/dist/daemon/lifecycle.d.ts +85 -0
  239. package/dist/daemon/lifecycle.d.ts.map +1 -0
  240. package/dist/daemon/lifecycle.js +754 -0
  241. package/dist/daemon/lifecycle.js.map +1 -0
  242. package/dist/daemon/location-state.d.ts +85 -0
  243. package/dist/daemon/location-state.d.ts.map +1 -0
  244. package/dist/daemon/location-state.js +291 -0
  245. package/dist/daemon/location-state.js.map +1 -0
  246. package/dist/daemon/lock.d.ts +29 -0
  247. package/dist/daemon/lock.d.ts.map +1 -0
  248. package/dist/daemon/lock.js +131 -0
  249. package/dist/daemon/lock.js.map +1 -0
  250. package/dist/daemon/methods/__tests__/graph.test.d.ts +5 -0
  251. package/dist/daemon/methods/__tests__/graph.test.d.ts.map +1 -0
  252. package/dist/daemon/methods/__tests__/graph.test.js +274 -0
  253. package/dist/daemon/methods/__tests__/graph.test.js.map +1 -0
  254. package/dist/daemon/methods/__tests__/provider.test.d.ts +5 -0
  255. package/dist/daemon/methods/__tests__/provider.test.d.ts.map +1 -0
  256. package/dist/daemon/methods/__tests__/provider.test.js +184 -0
  257. package/dist/daemon/methods/__tests__/provider.test.js.map +1 -0
  258. package/dist/daemon/methods/__tests__/tools.test.d.ts +5 -0
  259. package/dist/daemon/methods/__tests__/tools.test.d.ts.map +1 -0
  260. package/dist/daemon/methods/__tests__/tools.test.js +295 -0
  261. package/dist/daemon/methods/__tests__/tools.test.js.map +1 -0
  262. package/dist/daemon/methods/archive.d.ts +22 -0
  263. package/dist/daemon/methods/archive.d.ts.map +1 -0
  264. package/dist/daemon/methods/archive.js +107 -0
  265. package/dist/daemon/methods/archive.js.map +1 -0
  266. package/dist/daemon/methods/graph.d.ts +26 -0
  267. package/dist/daemon/methods/graph.d.ts.map +1 -0
  268. package/dist/daemon/methods/graph.js +157 -0
  269. package/dist/daemon/methods/graph.js.map +1 -0
  270. package/dist/daemon/methods/lifecycle.d.ts +54 -0
  271. package/dist/daemon/methods/lifecycle.d.ts.map +1 -0
  272. package/dist/daemon/methods/lifecycle.js +46 -0
  273. package/dist/daemon/methods/lifecycle.js.map +1 -0
  274. package/dist/daemon/methods/location.d.ts +24 -0
  275. package/dist/daemon/methods/location.d.ts.map +1 -0
  276. package/dist/daemon/methods/location.js +72 -0
  277. package/dist/daemon/methods/location.js.map +1 -0
  278. package/dist/daemon/methods/provider.d.ts +22 -0
  279. package/dist/daemon/methods/provider.d.ts.map +1 -0
  280. package/dist/daemon/methods/provider.js +72 -0
  281. package/dist/daemon/methods/provider.js.map +1 -0
  282. package/dist/daemon/methods/tools.d.ts +23 -0
  283. package/dist/daemon/methods/tools.d.ts.map +1 -0
  284. package/dist/daemon/methods/tools.js +111 -0
  285. package/dist/daemon/methods/tools.js.map +1 -0
  286. package/dist/daemon/registry.d.ts +35 -0
  287. package/dist/daemon/registry.d.ts.map +1 -0
  288. package/dist/daemon/registry.js +189 -0
  289. package/dist/daemon/registry.js.map +1 -0
  290. package/dist/daemon/types.d.ts +101 -0
  291. package/dist/daemon/types.d.ts.map +1 -0
  292. package/dist/daemon/types.js +19 -0
  293. package/dist/daemon/types.js.map +1 -0
  294. package/dist/daemon/watcher.d.ts +62 -0
  295. package/dist/daemon/watcher.d.ts.map +1 -0
  296. package/dist/daemon/watcher.js +142 -0
  297. package/dist/daemon/watcher.js.map +1 -0
  298. package/dist/graph/EdgeTypeRegistry.d.ts +134 -0
  299. package/dist/graph/EdgeTypeRegistry.d.ts.map +1 -0
  300. package/dist/graph/EdgeTypeRegistry.js +255 -0
  301. package/dist/graph/EdgeTypeRegistry.js.map +1 -0
  302. package/dist/graph/FederatedGraph.d.ts +296 -0
  303. package/dist/graph/FederatedGraph.d.ts.map +1 -0
  304. package/dist/graph/FederatedGraph.js +406 -0
  305. package/dist/graph/FederatedGraph.js.map +1 -0
  306. package/dist/graph/GraphologyAdapter.d.ts +151 -0
  307. package/dist/graph/GraphologyAdapter.d.ts.map +1 -0
  308. package/dist/graph/GraphologyAdapter.js +209 -0
  309. package/dist/graph/GraphologyAdapter.js.map +1 -0
  310. package/dist/graph/HydratingFederatedGraph.d.ts +151 -0
  311. package/dist/graph/HydratingFederatedGraph.d.ts.map +1 -0
  312. package/dist/graph/HydratingFederatedGraph.js +327 -0
  313. package/dist/graph/HydratingFederatedGraph.js.map +1 -0
  314. package/dist/graph/__tests__/EdgeTypeRegistry.test.d.ts +2 -0
  315. package/dist/graph/__tests__/EdgeTypeRegistry.test.d.ts.map +1 -0
  316. package/dist/graph/__tests__/EdgeTypeRegistry.test.js +212 -0
  317. package/dist/graph/__tests__/EdgeTypeRegistry.test.js.map +1 -0
  318. package/dist/graph/__tests__/FederatedGraph.test.d.ts +2 -0
  319. package/dist/graph/__tests__/FederatedGraph.test.d.ts.map +1 -0
  320. package/dist/graph/__tests__/FederatedGraph.test.js +661 -0
  321. package/dist/graph/__tests__/FederatedGraph.test.js.map +1 -0
  322. package/dist/graph/__tests__/GraphologyAdapter.test.d.ts +2 -0
  323. package/dist/graph/__tests__/GraphologyAdapter.test.d.ts.map +1 -0
  324. package/dist/graph/__tests__/GraphologyAdapter.test.js +326 -0
  325. package/dist/graph/__tests__/GraphologyAdapter.test.js.map +1 -0
  326. package/dist/graph/__tests__/HydratingFederatedGraph.test.d.ts +2 -0
  327. package/dist/graph/__tests__/HydratingFederatedGraph.test.d.ts.map +1 -0
  328. package/dist/graph/__tests__/HydratingFederatedGraph.test.js +587 -0
  329. package/dist/graph/__tests__/HydratingFederatedGraph.test.js.map +1 -0
  330. package/dist/graph/__tests__/debounce.test.d.ts +5 -0
  331. package/dist/graph/__tests__/debounce.test.d.ts.map +1 -0
  332. package/dist/graph/__tests__/debounce.test.js +195 -0
  333. package/dist/graph/__tests__/debounce.test.js.map +1 -0
  334. package/dist/graph/__tests__/edge-cases.test.d.ts +8 -0
  335. package/dist/graph/__tests__/edge-cases.test.d.ts.map +1 -0
  336. package/dist/graph/__tests__/edge-cases.test.js +472 -0
  337. package/dist/graph/__tests__/edge-cases.test.js.map +1 -0
  338. package/dist/graph/__tests__/expansion.test.d.ts +2 -0
  339. package/dist/graph/__tests__/expansion.test.d.ts.map +1 -0
  340. package/dist/graph/__tests__/expansion.test.js +105 -0
  341. package/dist/graph/__tests__/expansion.test.js.map +1 -0
  342. package/dist/graph/__tests__/provider-store.test.d.ts +5 -0
  343. package/dist/graph/__tests__/provider-store.test.d.ts.map +1 -0
  344. package/dist/graph/__tests__/provider-store.test.js +791 -0
  345. package/dist/graph/__tests__/provider-store.test.js.map +1 -0
  346. package/dist/graph/__tests__/query.test.d.ts +5 -0
  347. package/dist/graph/__tests__/query.test.d.ts.map +1 -0
  348. package/dist/graph/__tests__/query.test.js +774 -0
  349. package/dist/graph/__tests__/query.test.js.map +1 -0
  350. package/dist/graph/__tests__/store.test.d.ts +5 -0
  351. package/dist/graph/__tests__/store.test.d.ts.map +1 -0
  352. package/dist/graph/__tests__/store.test.js +489 -0
  353. package/dist/graph/__tests__/store.test.js.map +1 -0
  354. package/dist/graph/__tests__/sync.test.d.ts +5 -0
  355. package/dist/graph/__tests__/sync.test.d.ts.map +1 -0
  356. package/dist/graph/__tests__/sync.test.js +129 -0
  357. package/dist/graph/__tests__/sync.test.js.map +1 -0
  358. package/dist/graph/__tests__/validation.test.d.ts +2 -0
  359. package/dist/graph/__tests__/validation.test.d.ts.map +1 -0
  360. package/dist/graph/__tests__/validation.test.js +521 -0
  361. package/dist/graph/__tests__/validation.test.js.map +1 -0
  362. package/dist/graph/coordination.d.ts +190 -0
  363. package/dist/graph/coordination.d.ts.map +1 -0
  364. package/dist/graph/coordination.js +180 -0
  365. package/dist/graph/coordination.js.map +1 -0
  366. package/dist/graph/debounce.d.ts +47 -0
  367. package/dist/graph/debounce.d.ts.map +1 -0
  368. package/dist/graph/debounce.js +95 -0
  369. package/dist/graph/debounce.js.map +1 -0
  370. package/dist/graph/expansion.d.ts +64 -0
  371. package/dist/graph/expansion.d.ts.map +1 -0
  372. package/dist/graph/expansion.js +205 -0
  373. package/dist/graph/expansion.js.map +1 -0
  374. package/dist/graph/history.d.ts +186 -0
  375. package/dist/graph/history.d.ts.map +1 -0
  376. package/dist/graph/history.js +155 -0
  377. package/dist/graph/history.js.map +1 -0
  378. package/dist/graph/index.d.ts +35 -0
  379. package/dist/graph/index.d.ts.map +1 -0
  380. package/dist/graph/index.js +22 -0
  381. package/dist/graph/index.js.map +1 -0
  382. package/dist/graph/provider-store.d.ts +211 -0
  383. package/dist/graph/provider-store.d.ts.map +1 -0
  384. package/dist/graph/provider-store.js +568 -0
  385. package/dist/graph/provider-store.js.map +1 -0
  386. package/dist/graph/query.d.ts +90 -0
  387. package/dist/graph/query.d.ts.map +1 -0
  388. package/dist/graph/query.js +463 -0
  389. package/dist/graph/query.js.map +1 -0
  390. package/dist/graph/store.d.ts +71 -0
  391. package/dist/graph/store.d.ts.map +1 -0
  392. package/dist/graph/store.js +530 -0
  393. package/dist/graph/store.js.map +1 -0
  394. package/dist/graph/sync.d.ts +48 -0
  395. package/dist/graph/sync.d.ts.map +1 -0
  396. package/dist/graph/sync.js +60 -0
  397. package/dist/graph/sync.js.map +1 -0
  398. package/dist/graph/types.d.ts +289 -0
  399. package/dist/graph/types.d.ts.map +1 -0
  400. package/dist/graph/types.js +19 -0
  401. package/dist/graph/types.js.map +1 -0
  402. package/dist/graph/validation.d.ts +26 -0
  403. package/dist/graph/validation.d.ts.map +1 -0
  404. package/dist/graph/validation.js +338 -0
  405. package/dist/graph/validation.js.map +1 -0
  406. package/dist/index.d.ts +25 -14
  407. package/dist/index.d.ts.map +1 -1
  408. package/dist/index.js +22 -25
  409. package/dist/index.js.map +1 -1
  410. package/dist/materialization/archiver.d.ts +12 -0
  411. package/dist/materialization/archiver.d.ts.map +1 -0
  412. package/dist/materialization/archiver.js +273 -0
  413. package/dist/materialization/archiver.js.map +1 -0
  414. package/dist/materialization/git-archive-store.d.ts +17 -0
  415. package/dist/materialization/git-archive-store.d.ts.map +1 -0
  416. package/dist/materialization/git-archive-store.js +509 -0
  417. package/dist/materialization/git-archive-store.js.map +1 -0
  418. package/dist/materialization/git-remote-store.d.ts +22 -0
  419. package/dist/materialization/git-remote-store.d.ts.map +1 -0
  420. package/dist/materialization/git-remote-store.js +448 -0
  421. package/dist/materialization/git-remote-store.js.map +1 -0
  422. package/dist/materialization/graph-id.d.ts +53 -0
  423. package/dist/materialization/graph-id.d.ts.map +1 -0
  424. package/dist/materialization/graph-id.js +163 -0
  425. package/dist/materialization/graph-id.js.map +1 -0
  426. package/dist/materialization/http-remote-store.d.ts +12 -0
  427. package/dist/materialization/http-remote-store.d.ts.map +1 -0
  428. package/dist/materialization/http-remote-store.js +143 -0
  429. package/dist/materialization/http-remote-store.js.map +1 -0
  430. package/dist/materialization/index.d.ts +15 -0
  431. package/dist/materialization/index.d.ts.map +1 -0
  432. package/dist/materialization/index.js +17 -0
  433. package/dist/materialization/index.js.map +1 -0
  434. package/dist/materialization/remote-store-factory.d.ts +17 -0
  435. package/dist/materialization/remote-store-factory.d.ts.map +1 -0
  436. package/dist/materialization/remote-store-factory.js +46 -0
  437. package/dist/materialization/remote-store-factory.js.map +1 -0
  438. package/dist/materialization/snapshot.d.ts +34 -0
  439. package/dist/materialization/snapshot.d.ts.map +1 -0
  440. package/dist/materialization/snapshot.js +177 -0
  441. package/dist/materialization/snapshot.js.map +1 -0
  442. package/dist/materialization/types.d.ts +300 -0
  443. package/dist/materialization/types.d.ts.map +1 -0
  444. package/dist/materialization/types.js +17 -0
  445. package/dist/materialization/types.js.map +1 -0
  446. package/dist/providers/__tests__/beads.test.d.ts +5 -0
  447. package/dist/providers/__tests__/beads.test.d.ts.map +1 -0
  448. package/dist/providers/__tests__/beads.test.js +591 -0
  449. package/dist/providers/__tests__/beads.test.js.map +1 -0
  450. package/dist/providers/__tests__/claude-tasks.test.d.ts +5 -0
  451. package/dist/providers/__tests__/claude-tasks.test.d.ts.map +1 -0
  452. package/dist/providers/__tests__/claude-tasks.test.js +392 -0
  453. package/dist/providers/__tests__/claude-tasks.test.js.map +1 -0
  454. package/dist/providers/__tests__/from-config.test.d.ts +5 -0
  455. package/dist/providers/__tests__/from-config.test.d.ts.map +1 -0
  456. package/dist/providers/__tests__/from-config.test.js +152 -0
  457. package/dist/providers/__tests__/from-config.test.js.map +1 -0
  458. package/dist/providers/__tests__/materialization.test.d.ts +5 -0
  459. package/dist/providers/__tests__/materialization.test.d.ts.map +1 -0
  460. package/dist/providers/__tests__/materialization.test.js +407 -0
  461. package/dist/providers/__tests__/materialization.test.js.map +1 -0
  462. package/dist/providers/__tests__/native.test.d.ts +5 -0
  463. package/dist/providers/__tests__/native.test.d.ts.map +1 -0
  464. package/dist/providers/__tests__/native.test.js +566 -0
  465. package/dist/providers/__tests__/native.test.js.map +1 -0
  466. package/dist/providers/__tests__/registry.test.d.ts +5 -0
  467. package/dist/providers/__tests__/registry.test.d.ts.map +1 -0
  468. package/dist/providers/__tests__/registry.test.js +183 -0
  469. package/dist/providers/__tests__/registry.test.js.map +1 -0
  470. package/dist/providers/beads.d.ts +46 -0
  471. package/dist/providers/beads.d.ts.map +1 -0
  472. package/dist/providers/beads.js +865 -0
  473. package/dist/providers/beads.js.map +1 -0
  474. package/dist/providers/claude-tasks.d.ts +56 -0
  475. package/dist/providers/claude-tasks.d.ts.map +1 -0
  476. package/dist/providers/claude-tasks.js +282 -0
  477. package/dist/providers/claude-tasks.js.map +1 -0
  478. package/dist/providers/entire.d.ts +88 -0
  479. package/dist/providers/entire.d.ts.map +1 -0
  480. package/dist/providers/entire.js +409 -0
  481. package/dist/providers/entire.js.map +1 -0
  482. package/dist/providers/from-config.d.ts +47 -0
  483. package/dist/providers/from-config.d.ts.map +1 -0
  484. package/dist/providers/from-config.js +150 -0
  485. package/dist/providers/from-config.js.map +1 -0
  486. package/dist/providers/index.d.ts +26 -0
  487. package/dist/providers/index.d.ts.map +1 -0
  488. package/dist/providers/index.js +29 -0
  489. package/dist/providers/index.js.map +1 -0
  490. package/dist/providers/location.d.ts +44 -0
  491. package/dist/providers/location.d.ts.map +1 -0
  492. package/dist/providers/location.js +157 -0
  493. package/dist/providers/location.js.map +1 -0
  494. package/dist/providers/materialization.d.ts +46 -0
  495. package/dist/providers/materialization.d.ts.map +1 -0
  496. package/dist/providers/materialization.js +237 -0
  497. package/dist/providers/materialization.js.map +1 -0
  498. package/dist/providers/native.d.ts +32 -0
  499. package/dist/providers/native.d.ts.map +1 -0
  500. package/dist/providers/native.js +552 -0
  501. package/dist/providers/native.js.map +1 -0
  502. package/dist/providers/registry.d.ts +11 -0
  503. package/dist/providers/registry.d.ts.map +1 -0
  504. package/dist/providers/registry.js +97 -0
  505. package/dist/providers/registry.js.map +1 -0
  506. package/dist/providers/sudocode.d.ts +49 -0
  507. package/dist/providers/sudocode.d.ts.map +1 -0
  508. package/dist/providers/sudocode.js +945 -0
  509. package/dist/providers/sudocode.js.map +1 -0
  510. package/dist/providers/sync.d.ts +299 -0
  511. package/dist/providers/sync.d.ts.map +1 -0
  512. package/dist/providers/sync.js +93 -0
  513. package/dist/providers/sync.js.map +1 -0
  514. package/dist/providers/traits/RelationshipQueryable.d.ts +129 -0
  515. package/dist/providers/traits/RelationshipQueryable.d.ts.map +1 -0
  516. package/dist/providers/traits/RelationshipQueryable.js +68 -0
  517. package/dist/providers/traits/RelationshipQueryable.js.map +1 -0
  518. package/dist/providers/traits/TaskManageable.d.ts +157 -0
  519. package/dist/providers/traits/TaskManageable.d.ts.map +1 -0
  520. package/dist/providers/traits/TaskManageable.js +37 -0
  521. package/dist/providers/traits/TaskManageable.js.map +1 -0
  522. package/dist/providers/traits/Watchable.d.ts +216 -0
  523. package/dist/providers/traits/Watchable.d.ts.map +1 -0
  524. package/dist/providers/traits/Watchable.js +37 -0
  525. package/dist/providers/traits/Watchable.js.map +1 -0
  526. package/dist/providers/traits/__tests__/RelationshipQueryable.test.d.ts +2 -0
  527. package/dist/providers/traits/__tests__/RelationshipQueryable.test.d.ts.map +1 -0
  528. package/dist/providers/traits/__tests__/RelationshipQueryable.test.js +169 -0
  529. package/dist/providers/traits/__tests__/RelationshipQueryable.test.js.map +1 -0
  530. package/dist/providers/traits/__tests__/TaskManageable.test.d.ts +2 -0
  531. package/dist/providers/traits/__tests__/TaskManageable.test.d.ts.map +1 -0
  532. package/dist/providers/traits/__tests__/TaskManageable.test.js +172 -0
  533. package/dist/providers/traits/__tests__/TaskManageable.test.js.map +1 -0
  534. package/dist/providers/traits/index.d.ts +13 -0
  535. package/dist/providers/traits/index.d.ts.map +1 -0
  536. package/dist/providers/traits/index.js +10 -0
  537. package/dist/providers/traits/index.js.map +1 -0
  538. package/dist/providers/types.d.ts +284 -0
  539. package/dist/providers/types.d.ts.map +1 -0
  540. package/dist/providers/types.js +30 -0
  541. package/dist/providers/types.js.map +1 -0
  542. package/dist/schema/__tests__/validation.test.d.ts +2 -0
  543. package/dist/schema/__tests__/validation.test.d.ts.map +1 -0
  544. package/dist/schema/__tests__/validation.test.js +241 -0
  545. package/dist/schema/__tests__/validation.test.js.map +1 -0
  546. package/dist/schema/base.d.ts +68 -0
  547. package/dist/schema/base.d.ts.map +1 -0
  548. package/dist/schema/base.js +5 -0
  549. package/dist/schema/base.js.map +1 -0
  550. package/dist/schema/edges.d.ts +49 -0
  551. package/dist/schema/edges.d.ts.map +1 -0
  552. package/dist/schema/edges.js +9 -0
  553. package/dist/schema/edges.js.map +1 -0
  554. package/dist/schema/index.d.ts +11 -0
  555. package/dist/schema/index.d.ts.map +1 -0
  556. package/dist/schema/index.js +8 -0
  557. package/dist/schema/index.js.map +1 -0
  558. package/dist/schema/nodes.d.ts +97 -0
  559. package/dist/schema/nodes.d.ts.map +1 -0
  560. package/dist/schema/nodes.js +5 -0
  561. package/dist/schema/nodes.js.map +1 -0
  562. package/dist/schema/storage.d.ts +107 -0
  563. package/dist/schema/storage.d.ts.map +1 -0
  564. package/dist/schema/storage.js +10 -0
  565. package/dist/schema/storage.js.map +1 -0
  566. package/dist/schema/validation.d.ts +61 -0
  567. package/dist/schema/validation.d.ts.map +1 -0
  568. package/dist/schema/validation.js +170 -0
  569. package/dist/schema/validation.js.map +1 -0
  570. package/dist/storage/__tests__/atomic-write.test.d.ts +5 -0
  571. package/dist/storage/__tests__/atomic-write.test.d.ts.map +1 -0
  572. package/dist/storage/__tests__/atomic-write.test.js +170 -0
  573. package/dist/storage/__tests__/atomic-write.test.js.map +1 -0
  574. package/dist/storage/__tests__/file-lock.test.d.ts +2 -0
  575. package/dist/storage/__tests__/file-lock.test.d.ts.map +1 -0
  576. package/dist/storage/__tests__/file-lock.test.js +89 -0
  577. package/dist/storage/__tests__/file-lock.test.js.map +1 -0
  578. package/dist/storage/__tests__/jsonl.test.d.ts +2 -0
  579. package/dist/storage/__tests__/jsonl.test.d.ts.map +1 -0
  580. package/dist/storage/__tests__/jsonl.test.js +228 -0
  581. package/dist/storage/__tests__/jsonl.test.js.map +1 -0
  582. package/dist/storage/__tests__/locked-writer.test.d.ts +2 -0
  583. package/dist/storage/__tests__/locked-writer.test.d.ts.map +1 -0
  584. package/dist/storage/__tests__/locked-writer.test.js +109 -0
  585. package/dist/storage/__tests__/locked-writer.test.js.map +1 -0
  586. package/dist/storage/__tests__/sqlite.test.d.ts +2 -0
  587. package/dist/storage/__tests__/sqlite.test.d.ts.map +1 -0
  588. package/dist/storage/__tests__/sqlite.test.js +470 -0
  589. package/dist/storage/__tests__/sqlite.test.js.map +1 -0
  590. package/dist/storage/atomic-write.d.ts +38 -0
  591. package/dist/storage/atomic-write.d.ts.map +1 -0
  592. package/dist/storage/atomic-write.js +83 -0
  593. package/dist/storage/atomic-write.js.map +1 -0
  594. package/dist/storage/file-lock.d.ts +66 -0
  595. package/dist/storage/file-lock.d.ts.map +1 -0
  596. package/dist/storage/file-lock.js +176 -0
  597. package/dist/storage/file-lock.js.map +1 -0
  598. package/dist/storage/index.d.ts +11 -0
  599. package/dist/storage/index.d.ts.map +1 -0
  600. package/dist/storage/index.js +13 -0
  601. package/dist/storage/index.js.map +1 -0
  602. package/dist/storage/interface.d.ts +219 -0
  603. package/dist/storage/interface.d.ts.map +1 -0
  604. package/dist/storage/interface.js +22 -0
  605. package/dist/storage/interface.js.map +1 -0
  606. package/dist/storage/jsonl.d.ts +106 -0
  607. package/dist/storage/jsonl.d.ts.map +1 -0
  608. package/dist/storage/jsonl.js +218 -0
  609. package/dist/storage/jsonl.js.map +1 -0
  610. package/dist/storage/locked-writer.d.ts +67 -0
  611. package/dist/storage/locked-writer.d.ts.map +1 -0
  612. package/dist/storage/locked-writer.js +105 -0
  613. package/dist/storage/locked-writer.js.map +1 -0
  614. package/dist/storage/sqlite-schema.d.ts +48 -0
  615. package/dist/storage/sqlite-schema.d.ts.map +1 -0
  616. package/dist/storage/sqlite-schema.js +169 -0
  617. package/dist/storage/sqlite-schema.js.map +1 -0
  618. package/dist/storage/sqlite.d.ts +73 -0
  619. package/dist/storage/sqlite.d.ts.map +1 -0
  620. package/dist/storage/sqlite.js +698 -0
  621. package/dist/storage/sqlite.js.map +1 -0
  622. package/dist/tools/__tests__/annotate.test.d.ts +5 -0
  623. package/dist/tools/__tests__/annotate.test.d.ts.map +1 -0
  624. package/dist/tools/__tests__/annotate.test.js +314 -0
  625. package/dist/tools/__tests__/annotate.test.js.map +1 -0
  626. package/dist/tools/__tests__/link.test.d.ts +5 -0
  627. package/dist/tools/__tests__/link.test.d.ts.map +1 -0
  628. package/dist/tools/__tests__/link.test.js +245 -0
  629. package/dist/tools/__tests__/link.test.js.map +1 -0
  630. package/dist/tools/__tests__/query.test.d.ts +5 -0
  631. package/dist/tools/__tests__/query.test.d.ts.map +1 -0
  632. package/dist/tools/__tests__/query.test.js +288 -0
  633. package/dist/tools/__tests__/query.test.js.map +1 -0
  634. package/dist/tools/__tests__/task.test.d.ts +5 -0
  635. package/dist/tools/__tests__/task.test.d.ts.map +1 -0
  636. package/dist/tools/__tests__/task.test.js +178 -0
  637. package/dist/tools/__tests__/task.test.js.map +1 -0
  638. package/dist/tools/annotate.d.ts +17 -0
  639. package/dist/tools/annotate.d.ts.map +1 -0
  640. package/dist/tools/annotate.js +218 -0
  641. package/dist/tools/annotate.js.map +1 -0
  642. package/dist/tools/index.d.ts +14 -0
  643. package/dist/tools/index.d.ts.map +1 -0
  644. package/dist/tools/index.js +14 -0
  645. package/dist/tools/index.js.map +1 -0
  646. package/dist/tools/link.d.ts +17 -0
  647. package/dist/tools/link.d.ts.map +1 -0
  648. package/dist/tools/link.js +127 -0
  649. package/dist/tools/link.js.map +1 -0
  650. package/dist/tools/query.d.ts +17 -0
  651. package/dist/tools/query.d.ts.map +1 -0
  652. package/dist/tools/query.js +342 -0
  653. package/dist/tools/query.js.map +1 -0
  654. package/dist/tools/task.d.ts +20 -0
  655. package/dist/tools/task.d.ts.map +1 -0
  656. package/dist/tools/task.js +161 -0
  657. package/dist/tools/task.js.map +1 -0
  658. package/dist/tools/types.d.ts +334 -0
  659. package/dist/tools/types.d.ts.map +1 -0
  660. package/dist/tools/types.js +19 -0
  661. package/dist/tools/types.js.map +1 -0
  662. package/package.json +40 -5
@@ -0,0 +1,258 @@
1
+ /**
2
+ * Custom JSONL Merge Driver for OpenTasks (Phase 3)
3
+ *
4
+ * Three-way merge for graph.jsonl files with field-level resolution.
5
+ * Registered as a git merge driver via .gitattributes.
6
+ */
7
+ import * as fs from 'node:fs';
8
+ import { execSync } from 'node:child_process';
9
+ /**
10
+ * Parse a JSONL file into a Map keyed by ID
11
+ *
12
+ * For entries with the same ID, keeps the one with the latest updated_at.
13
+ */
14
+ export function parseJsonlToMap(filePath) {
15
+ const map = new Map();
16
+ let content;
17
+ try {
18
+ content = fs.readFileSync(filePath, 'utf-8');
19
+ }
20
+ catch {
21
+ return map;
22
+ }
23
+ for (const line of content.split('\n')) {
24
+ const trimmed = line.trim();
25
+ if (!trimmed)
26
+ continue;
27
+ try {
28
+ const obj = JSON.parse(trimmed);
29
+ const id = obj.id;
30
+ if (!id)
31
+ continue;
32
+ const existing = map.get(id);
33
+ if (!existing || obj.updated_at > existing.updated_at) {
34
+ map.set(id, obj);
35
+ }
36
+ }
37
+ catch {
38
+ // Skip malformed lines
39
+ }
40
+ }
41
+ return map;
42
+ }
43
+ /**
44
+ * Write a map of entries back to a JSONL file
45
+ */
46
+ export function writeJsonlFromMap(filePath, entries) {
47
+ const lines = [];
48
+ // Write nodes first (non x- prefix), then edges (x- prefix)
49
+ const nodes = [];
50
+ const edges = [];
51
+ for (const entry of entries.values()) {
52
+ if (entry.id.startsWith('x-')) {
53
+ edges.push(entry);
54
+ }
55
+ else {
56
+ nodes.push(entry);
57
+ }
58
+ }
59
+ for (const entry of [...nodes, ...edges]) {
60
+ lines.push(JSON.stringify(entry));
61
+ }
62
+ fs.writeFileSync(filePath, lines.join('\n') + (lines.length > 0 ? '\n' : ''), 'utf-8');
63
+ }
64
+ /**
65
+ * Deep equality check for JSON values
66
+ */
67
+ export function deepEqual(a, b) {
68
+ if (a === b)
69
+ return true;
70
+ if (a === null || b === null)
71
+ return false;
72
+ if (a === undefined || b === undefined)
73
+ return a === b;
74
+ if (typeof a !== typeof b)
75
+ return false;
76
+ if (Array.isArray(a)) {
77
+ if (!Array.isArray(b))
78
+ return false;
79
+ if (a.length !== b.length)
80
+ return false;
81
+ return a.every((val, i) => deepEqual(val, b[i]));
82
+ }
83
+ if (typeof a === 'object') {
84
+ const aObj = a;
85
+ const bObj = b;
86
+ const aKeys = Object.keys(aObj);
87
+ const bKeys = Object.keys(bObj);
88
+ if (aKeys.length !== bKeys.length)
89
+ return false;
90
+ return aKeys.every((key) => deepEqual(aObj[key], bObj[key]));
91
+ }
92
+ return false;
93
+ }
94
+ /**
95
+ * Pick entry with newer timestamp
96
+ */
97
+ function pickByNewerTimestamp(a, b) {
98
+ const aTime = a.updated_at || a.created_at || '';
99
+ const bTime = b.updated_at || b.created_at || '';
100
+ return aTime >= bTime ? a : b;
101
+ }
102
+ /**
103
+ * Field-level three-way merge
104
+ *
105
+ * For each field:
106
+ * - Both sides agree → use that value
107
+ * - Only one side changed → use the changed value
108
+ * - Both changed differently → last-writer-wins by updated_at
109
+ */
110
+ export function fieldLevelMerge(base, ours, theirs) {
111
+ const result = { ...base };
112
+ const allKeys = new Set([...Object.keys(base), ...Object.keys(ours), ...Object.keys(theirs)]);
113
+ for (const key of allKeys) {
114
+ const bVal = base[key];
115
+ const oVal = ours[key];
116
+ const tVal = theirs[key];
117
+ if (deepEqual(oVal, tVal)) {
118
+ // Both agree — take either
119
+ if (oVal !== undefined) {
120
+ result[key] = oVal;
121
+ }
122
+ else {
123
+ delete result[key];
124
+ }
125
+ }
126
+ else if (deepEqual(bVal, oVal)) {
127
+ // Only theirs changed
128
+ if (tVal !== undefined) {
129
+ result[key] = tVal;
130
+ }
131
+ else {
132
+ delete result[key];
133
+ }
134
+ }
135
+ else if (deepEqual(bVal, tVal)) {
136
+ // Only ours changed
137
+ if (oVal !== undefined) {
138
+ result[key] = oVal;
139
+ }
140
+ else {
141
+ delete result[key];
142
+ }
143
+ }
144
+ else {
145
+ // Both changed differently — last writer wins
146
+ const oursTime = ours.updated_at || '';
147
+ const theirsTime = theirs.updated_at || '';
148
+ const winner = oursTime >= theirsTime ? oVal : tVal;
149
+ if (winner !== undefined) {
150
+ result[key] = winner;
151
+ }
152
+ else {
153
+ delete result[key];
154
+ }
155
+ }
156
+ }
157
+ // Ensure updated_at is the latest
158
+ const times = [ours.updated_at, theirs.updated_at].filter(Boolean);
159
+ if (times.length > 0) {
160
+ result.updated_at = times.sort().pop();
161
+ }
162
+ return result;
163
+ }
164
+ /**
165
+ * Three-way merge of JSONL files
166
+ *
167
+ * @param basePath - Base version (common ancestor)
168
+ * @param oursPath - Our version (current branch)
169
+ * @param theirsPath - Their version (merging branch)
170
+ * @returns 0 on success, 1 on conflict (should not happen with this algorithm)
171
+ */
172
+ export function mergeJsonl(basePath, oursPath, theirsPath) {
173
+ const base = parseJsonlToMap(basePath);
174
+ const ours = parseJsonlToMap(oursPath);
175
+ const theirs = parseJsonlToMap(theirsPath);
176
+ const result = new Map();
177
+ const allIds = new Set([...base.keys(), ...ours.keys(), ...theirs.keys()]);
178
+ for (const id of allIds) {
179
+ const b = base.get(id);
180
+ const o = ours.get(id);
181
+ const t = theirs.get(id);
182
+ // Both sides agree — take either
183
+ if (deepEqual(o, t)) {
184
+ if (o)
185
+ result.set(id, o);
186
+ continue;
187
+ }
188
+ // Only theirs changed — take theirs
189
+ if (deepEqual(b, o)) {
190
+ if (t)
191
+ result.set(id, t);
192
+ continue;
193
+ }
194
+ // Only ours changed — take ours
195
+ if (deepEqual(b, t)) {
196
+ if (o)
197
+ result.set(id, o);
198
+ continue;
199
+ }
200
+ // Both added same ID with different content
201
+ if (!b && o && t) {
202
+ result.set(id, pickByNewerTimestamp(o, t));
203
+ continue;
204
+ }
205
+ // True conflict: both modified differently
206
+ if (b && o && t) {
207
+ result.set(id, fieldLevelMerge(b, o, t));
208
+ continue;
209
+ }
210
+ // One side deleted, other modified — keep modification
211
+ if (!o && t) {
212
+ result.set(id, t);
213
+ continue;
214
+ }
215
+ if (o && !t) {
216
+ result.set(id, o);
217
+ continue;
218
+ }
219
+ }
220
+ // Write merged result to ours path (git convention)
221
+ writeJsonlFromMap(oursPath, result);
222
+ return 0;
223
+ }
224
+ /**
225
+ * Install the merge driver in git config and .gitattributes
226
+ *
227
+ * @param worktreePath - Path to the worktree root
228
+ */
229
+ export function installMergeDriver(worktreePath) {
230
+ // 1. Add to .gitattributes
231
+ const attrPath = `${worktreePath}/.gitattributes`;
232
+ let attrContent = '';
233
+ try {
234
+ attrContent = fs.readFileSync(attrPath, 'utf-8');
235
+ }
236
+ catch {
237
+ // File doesn't exist yet
238
+ }
239
+ if (!attrContent.includes('merge=opentasks')) {
240
+ const addition = '\n# OpenTasks merge driver for graph.jsonl\n' + '.opentasks/graph.jsonl merge=opentasks\n';
241
+ fs.writeFileSync(attrPath, attrContent + addition, 'utf-8');
242
+ }
243
+ // 2. Configure merge driver in git config
244
+ try {
245
+ execSync('git config merge.opentasks.name "OpenTasks JSONL merge driver"', {
246
+ cwd: worktreePath,
247
+ stdio: ['pipe', 'pipe', 'pipe'],
248
+ });
249
+ execSync('git config merge.opentasks.driver "opentasks merge-driver %O %A %B %L %P"', {
250
+ cwd: worktreePath,
251
+ stdio: ['pipe', 'pipe', 'pipe'],
252
+ });
253
+ }
254
+ catch {
255
+ // Non-fatal: git config might not be available
256
+ }
257
+ }
258
+ //# sourceMappingURL=merge-driver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merge-driver.js","sourceRoot":"","sources":["../../src/core/merge-driver.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Redirect Rules System for OpenTasks (Phase 2)
3
+ *
4
+ * Routes operations to configured target locations based on
5
+ * pattern matching and priority.
6
+ */
7
+ import type { Connection } from './connections.js';
8
+ import type { LocationIdentity } from './location.js';
9
+ import { type ResolvedLocationTarget } from './uri.js';
10
+ import { type RedirectContext } from './conditional-redirects.js';
11
+ /**
12
+ * Operations that can be redirected
13
+ */
14
+ export type RedirectOperation = 'read' | 'write';
15
+ /**
16
+ * Redirect rule configuration
17
+ */
18
+ export interface RedirectRule {
19
+ /** Operations this rule applies to */
20
+ operations: RedirectOperation[];
21
+ /** Glob pattern for node IDs (e.g., "*", "i-*", "s-*") */
22
+ pattern: string;
23
+ /** Target location (opentasks:// URI or location hash) */
24
+ target: string;
25
+ /** Priority: lower = higher priority (default: 100) */
26
+ priority: number;
27
+ /** Fallback behavior when target is unreachable */
28
+ fallback: 'local' | 'error';
29
+ }
30
+ /**
31
+ * Result of redirect resolution
32
+ */
33
+ export interface RedirectResult {
34
+ /** Whether a redirect was found */
35
+ redirected: boolean;
36
+ /** The matching rule (if redirected) */
37
+ rule?: RedirectRule;
38
+ /** Resolved target location (if redirected) */
39
+ targetLocation?: ResolvedLocationTarget;
40
+ }
41
+ /**
42
+ * Simple glob matcher for node ID patterns
43
+ *
44
+ * Supports:
45
+ * "*" - matches anything
46
+ * "i-*" - matches IDs starting with "i-"
47
+ * "s-*" - matches IDs starting with "s-"
48
+ * exact - exact match
49
+ */
50
+ export declare function matchPattern(pattern: string, nodeId: string): boolean;
51
+ /**
52
+ * Find the first matching redirect rule for an operation
53
+ *
54
+ * Rules are sorted by priority (ascending, lower = higher priority).
55
+ * First match wins.
56
+ *
57
+ * @param operation - The operation type ('read' or 'write')
58
+ * @param nodeId - The node ID being operated on
59
+ * @param rules - Available redirect rules
60
+ * @returns The matching rule or null
61
+ */
62
+ export declare function findRedirectRule(operation: RedirectOperation, nodeId: string, rules: RedirectRule[]): RedirectRule | null;
63
+ /**
64
+ * Resolve a redirect rule to a target location
65
+ *
66
+ * @param rule - The redirect rule to resolve
67
+ * @param connections - Available connections
68
+ * @param currentLocation - Current location identity
69
+ * @param currentOpentasksPath - Path to current .opentasks directory
70
+ * @param depth - Current redirect depth (for loop prevention)
71
+ * @returns Resolved location target or null on failure
72
+ */
73
+ export declare function resolveRedirect(rule: RedirectRule, connections: Connection[], currentLocation: LocationIdentity, currentOpentasksPath: string, depth?: number): ResolvedLocationTarget | null;
74
+ /**
75
+ * Resolve a complete redirect for an operation
76
+ *
77
+ * When a RedirectContext is provided, rules are evaluated as
78
+ * ConditionalRedirectRules (conditions on role/branch). Without
79
+ * context, only base pattern matching is used.
80
+ *
81
+ * @param operation - The operation type
82
+ * @param nodeId - The node ID
83
+ * @param rules - Redirect rules (may include `when` conditions)
84
+ * @param connections - Available connections
85
+ * @param currentLocation - Current location identity
86
+ * @param currentOpentasksPath - Path to current .opentasks directory
87
+ * @param context - Optional redirect context for condition evaluation
88
+ * @returns Redirect result
89
+ */
90
+ export declare function resolveOperationRedirect(operation: RedirectOperation, nodeId: string, rules: RedirectRule[], connections: Connection[], currentLocation: LocationIdentity, currentOpentasksPath: string, context?: RedirectContext): RedirectResult;
91
+ //# sourceMappingURL=redirects.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redirects.d.ts","sourceRoot":"","sources":["../../src/core/redirects.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,EAAyB,KAAK,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAC9E,OAAO,EAEL,KAAK,eAAe,EAErB,MAAM,4BAA4B,CAAC;AAEpC;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,OAAO,CAAC;AAEjD;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,sCAAsC;IACtC,UAAU,EAAE,iBAAiB,EAAE,CAAC;IAChC,0DAA0D;IAC1D,OAAO,EAAE,MAAM,CAAC;IAChB,0DAA0D;IAC1D,MAAM,EAAE,MAAM,CAAC;IACf,uDAAuD;IACvD,QAAQ,EAAE,MAAM,CAAC;IACjB,mDAAmD;IACnD,QAAQ,EAAE,OAAO,GAAG,OAAO,CAAC;CAC7B;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,mCAAmC;IACnC,UAAU,EAAE,OAAO,CAAC;IACpB,wCAAwC;IACxC,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,+CAA+C;IAC/C,cAAc,CAAC,EAAE,sBAAsB,CAAC;CACzC;AAOD;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CASrE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAC9B,SAAS,EAAE,iBAAiB,EAC5B,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,YAAY,EAAE,GACpB,YAAY,GAAG,IAAI,CAWrB;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,YAAY,EAClB,WAAW,EAAE,UAAU,EAAE,EACzB,eAAe,EAAE,gBAAgB,EACjC,oBAAoB,EAAE,MAAM,EAC5B,KAAK,GAAE,MAAU,GAChB,sBAAsB,GAAG,IAAI,CAU/B;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,iBAAiB,EAC5B,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,YAAY,EAAE,EACrB,WAAW,EAAE,UAAU,EAAE,EACzB,eAAe,EAAE,gBAAgB,EACjC,oBAAoB,EAAE,MAAM,EAC5B,OAAO,CAAC,EAAE,eAAe,GACxB,cAAc,CA2BhB"}
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Redirect Rules System for OpenTasks (Phase 2)
3
+ *
4
+ * Routes operations to configured target locations based on
5
+ * pattern matching and priority.
6
+ */
7
+ import { resolveLocationTarget } from './uri.js';
8
+ import { findConditionalRedirectRule, } from './conditional-redirects.js';
9
+ /**
10
+ * Maximum redirect depth to prevent infinite loops
11
+ */
12
+ const MAX_REDIRECT_DEPTH = 3;
13
+ /**
14
+ * Simple glob matcher for node ID patterns
15
+ *
16
+ * Supports:
17
+ * "*" - matches anything
18
+ * "i-*" - matches IDs starting with "i-"
19
+ * "s-*" - matches IDs starting with "s-"
20
+ * exact - exact match
21
+ */
22
+ export function matchPattern(pattern, nodeId) {
23
+ if (pattern === '*')
24
+ return true;
25
+ if (pattern.endsWith('*')) {
26
+ const prefix = pattern.slice(0, -1);
27
+ return nodeId.startsWith(prefix);
28
+ }
29
+ return pattern === nodeId;
30
+ }
31
+ /**
32
+ * Find the first matching redirect rule for an operation
33
+ *
34
+ * Rules are sorted by priority (ascending, lower = higher priority).
35
+ * First match wins.
36
+ *
37
+ * @param operation - The operation type ('read' or 'write')
38
+ * @param nodeId - The node ID being operated on
39
+ * @param rules - Available redirect rules
40
+ * @returns The matching rule or null
41
+ */
42
+ export function findRedirectRule(operation, nodeId, rules) {
43
+ // Sort by priority (ascending)
44
+ const sorted = [...rules].sort((a, b) => a.priority - b.priority);
45
+ for (const rule of sorted) {
46
+ if (!rule.operations.includes(operation))
47
+ continue;
48
+ if (!matchPattern(rule.pattern, nodeId))
49
+ continue;
50
+ return rule;
51
+ }
52
+ return null;
53
+ }
54
+ /**
55
+ * Resolve a redirect rule to a target location
56
+ *
57
+ * @param rule - The redirect rule to resolve
58
+ * @param connections - Available connections
59
+ * @param currentLocation - Current location identity
60
+ * @param currentOpentasksPath - Path to current .opentasks directory
61
+ * @param depth - Current redirect depth (for loop prevention)
62
+ * @returns Resolved location target or null on failure
63
+ */
64
+ export function resolveRedirect(rule, connections, currentLocation, currentOpentasksPath, depth = 0) {
65
+ if (depth >= MAX_REDIRECT_DEPTH) {
66
+ throw new Error(`Redirect depth exceeded maximum of ${MAX_REDIRECT_DEPTH} hops`);
67
+ }
68
+ try {
69
+ return resolveLocationTarget(rule.target, connections, currentLocation, currentOpentasksPath);
70
+ }
71
+ catch {
72
+ return null;
73
+ }
74
+ }
75
+ /**
76
+ * Resolve a complete redirect for an operation
77
+ *
78
+ * When a RedirectContext is provided, rules are evaluated as
79
+ * ConditionalRedirectRules (conditions on role/branch). Without
80
+ * context, only base pattern matching is used.
81
+ *
82
+ * @param operation - The operation type
83
+ * @param nodeId - The node ID
84
+ * @param rules - Redirect rules (may include `when` conditions)
85
+ * @param connections - Available connections
86
+ * @param currentLocation - Current location identity
87
+ * @param currentOpentasksPath - Path to current .opentasks directory
88
+ * @param context - Optional redirect context for condition evaluation
89
+ * @returns Redirect result
90
+ */
91
+ export function resolveOperationRedirect(operation, nodeId, rules, connections, currentLocation, currentOpentasksPath, context) {
92
+ const rule = context
93
+ ? findConditionalRedirectRule(operation, nodeId, rules, context)
94
+ : findRedirectRule(operation, nodeId, rules);
95
+ if (!rule) {
96
+ return { redirected: false };
97
+ }
98
+ const targetLocation = resolveRedirect(rule, connections, currentLocation, currentOpentasksPath);
99
+ if (!targetLocation) {
100
+ // Target unreachable — apply fallback
101
+ if (rule.fallback === 'error') {
102
+ throw new Error(`Redirect target unreachable for rule (pattern: ${rule.pattern}, target: ${rule.target})`);
103
+ }
104
+ // fallback === 'local' — operate locally
105
+ return { redirected: false };
106
+ }
107
+ return {
108
+ redirected: true,
109
+ rule,
110
+ targetLocation,
111
+ };
112
+ }
113
+ //# sourceMappingURL=redirects.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redirects.js","sourceRoot":"","sources":["../../src/core/redirects.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,105 @@
1
+ /**
2
+ * OpenTasks URI scheme parser and resolver (Phase 2)
3
+ *
4
+ * Handles opentasks:// URIs for cross-location node references.
5
+ *
6
+ * URI formats:
7
+ * opentasks://k7m2x9p4/i-x7k9 - By location hash (preferred)
8
+ * opentasks://./i-x7k9 - Current location
9
+ * opentasks:///abs/path/.opentasks/s-g8h9 - Absolute path (fallback)
10
+ */
11
+ import type { Connection } from './connections.js';
12
+ import type { LocationIdentity } from './location.js';
13
+ /**
14
+ * Parsed opentasks:// URI
15
+ */
16
+ export interface ParsedOpentasksUri {
17
+ scheme: 'opentasks';
18
+ /** Location hash (e.g., "k7m2x9p4") */
19
+ locationHash?: string;
20
+ /** Relative path (e.g., "./") */
21
+ relativePath?: string;
22
+ /** Absolute path (e.g., "/abs/path/.opentasks/") */
23
+ absolutePath?: string;
24
+ /** Node ID (e.g., "i-x7k9") */
25
+ nodeId: string;
26
+ }
27
+ /**
28
+ * Resolved location target (without node ID)
29
+ *
30
+ * Used by the redirect system and daemon routing where
31
+ * only the location needs to be resolved, not a specific node.
32
+ */
33
+ export interface ResolvedLocationTarget {
34
+ /** Path to the .opentasks directory */
35
+ opentasksPath: string;
36
+ /** Location hash */
37
+ hash: string;
38
+ /** Whether this is the current location */
39
+ isLocal: boolean;
40
+ }
41
+ /**
42
+ * Resolved location result (with node ID)
43
+ */
44
+ export interface ResolvedLocation extends ResolvedLocationTarget {
45
+ /** Node ID to access */
46
+ nodeId: string;
47
+ }
48
+ /**
49
+ * Parse an opentasks:// URI
50
+ *
51
+ * @param uri - The URI to parse
52
+ * @returns Parsed URI or null if invalid
53
+ */
54
+ export declare function parseOpentasksUri(uri: string): ParsedOpentasksUri | null;
55
+ /**
56
+ * Check if a string is an opentasks:// URI
57
+ */
58
+ export declare function isOpentasksUri(uri: string): boolean;
59
+ /**
60
+ * Resolve a location target to a location (without node ID)
61
+ *
62
+ * Accepts a location specifier in any of these forms:
63
+ * - Bare hash: "k7m2x9p4"
64
+ * - Current-location shorthand: "."
65
+ * - Hash-based URI: "opentasks://k7m2x9p4/" or "opentasks://k7m2x9p4/node-id"
66
+ * - Absolute path URI: "opentasks:///abs/path/.opentasks/"
67
+ *
68
+ * Used by the redirect system, daemon routing, and worktree lookup.
69
+ *
70
+ * @param target - Location specifier (hash, ".", or opentasks:// URI)
71
+ * @param connections - Available connections
72
+ * @param currentLocation - Current location identity
73
+ * @param currentOpentasksPath - Path to current .opentasks directory
74
+ * @returns Resolved location target or throws on error
75
+ */
76
+ export declare function resolveLocationTarget(target: string, connections: Connection[], currentLocation: LocationIdentity, currentOpentasksPath: string): ResolvedLocationTarget;
77
+ /**
78
+ * Resolve an opentasks:// URI to a location and node ID
79
+ *
80
+ * Delegates to resolveLocationTarget for the location part,
81
+ * then attaches the node ID from the URI.
82
+ *
83
+ * @param uri - The URI to resolve
84
+ * @param connections - Available connections
85
+ * @param currentLocation - Current location identity
86
+ * @param currentOpentasksPath - Path to current .opentasks directory
87
+ * @returns Resolved location or throws on error
88
+ */
89
+ export declare function resolveOpentasksUri(uri: string, connections: Connection[], currentLocation: LocationIdentity, currentOpentasksPath: string): ResolvedLocation;
90
+ /**
91
+ * Build an opentasks:// URI from components
92
+ *
93
+ * @param locationHash - Location hash
94
+ * @param nodeId - Node ID
95
+ * @returns Formatted URI string
96
+ */
97
+ export declare function buildOpentasksUri(locationHash: string, nodeId: string): string;
98
+ /**
99
+ * Build a current-location opentasks:// URI
100
+ *
101
+ * @param nodeId - Node ID
102
+ * @returns Formatted URI string
103
+ */
104
+ export declare function buildLocalUri(nodeId: string): string;
105
+ //# sourceMappingURL=uri.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uri.d.ts","sourceRoot":"","sources":["../../src/core/uri.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAGtD;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,WAAW,CAAC;IACpB,uCAAuC;IACvC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iCAAiC;IACjC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,oDAAoD;IACpD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,+BAA+B;IAC/B,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;GAKG;AACH,MAAM,WAAW,sBAAsB;IACrC,uCAAuC;IACvC,aAAa,EAAE,MAAM,CAAC;IACtB,oBAAoB;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,2CAA2C;IAC3C,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAiB,SAAQ,sBAAsB;IAC9D,wBAAwB;IACxB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,kBAAkB,GAAG,IAAI,CAqDxE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEnD;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,UAAU,EAAE,EACzB,eAAe,EAAE,gBAAgB,EACjC,oBAAoB,EAAE,MAAM,GAC3B,sBAAsB,CAoDxB;AAuBD;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,MAAM,EACX,WAAW,EAAE,UAAU,EAAE,EACzB,eAAe,EAAE,gBAAgB,EACjC,oBAAoB,EAAE,MAAM,GAC3B,gBAAgB,CAYlB;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAE9E;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEpD"}