@waymakeros/cli 2.0.0

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 (390) hide show
  1. package/README.md +158 -0
  2. package/dist/cli/cli.d.ts +7 -0
  3. package/dist/cli/cli.d.ts.map +1 -0
  4. package/dist/cli/cli.js +703 -0
  5. package/dist/cli/cli.js.map +1 -0
  6. package/dist/cli/commands/auth.d.ts +14 -0
  7. package/dist/cli/commands/auth.d.ts.map +1 -0
  8. package/dist/cli/commands/auth.js +507 -0
  9. package/dist/cli/commands/auth.js.map +1 -0
  10. package/dist/cli/commands/init.d.ts +13 -0
  11. package/dist/cli/commands/init.d.ts.map +1 -0
  12. package/dist/cli/commands/init.js +297 -0
  13. package/dist/cli/commands/init.js.map +1 -0
  14. package/dist/cli/commands/kanban.d.ts +12 -0
  15. package/dist/cli/commands/kanban.d.ts.map +1 -0
  16. package/dist/cli/commands/kanban.js +71 -0
  17. package/dist/cli/commands/kanban.js.map +1 -0
  18. package/dist/cli/commands/serve.d.ts +12 -0
  19. package/dist/cli/commands/serve.d.ts.map +1 -0
  20. package/dist/cli/commands/serve.js +170 -0
  21. package/dist/cli/commands/serve.js.map +1 -0
  22. package/dist/cli/commands/sync.d.ts +12 -0
  23. package/dist/cli/commands/sync.d.ts.map +1 -0
  24. package/dist/cli/commands/sync.js +222 -0
  25. package/dist/cli/commands/sync.js.map +1 -0
  26. package/dist/cli/daemon.d.ts +106 -0
  27. package/dist/cli/daemon.d.ts.map +1 -0
  28. package/dist/cli/daemon.js +393 -0
  29. package/dist/cli/daemon.js.map +1 -0
  30. package/dist/cli/index.d.ts +13 -0
  31. package/dist/cli/index.d.ts.map +1 -0
  32. package/dist/cli/index.js +90 -0
  33. package/dist/cli/index.js.map +1 -0
  34. package/dist/index.d.ts +10 -0
  35. package/dist/index.d.ts.map +1 -0
  36. package/dist/index.js +238 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/simple-server.d.ts +7 -0
  39. package/dist/simple-server.d.ts.map +1 -0
  40. package/dist/simple-server.js +157 -0
  41. package/dist/simple-server.js.map +1 -0
  42. package/dist/sync/commander-client.d.ts +161 -0
  43. package/dist/sync/commander-client.d.ts.map +1 -0
  44. package/dist/sync/commander-client.js +405 -0
  45. package/dist/sync/commander-client.js.map +1 -0
  46. package/dist/sync/config-manager.d.ts +48 -0
  47. package/dist/sync/config-manager.d.ts.map +1 -0
  48. package/dist/sync/config-manager.js +169 -0
  49. package/dist/sync/config-manager.js.map +1 -0
  50. package/dist/sync/file-watcher.d.ts +53 -0
  51. package/dist/sync/file-watcher.d.ts.map +1 -0
  52. package/dist/sync/file-watcher.js +228 -0
  53. package/dist/sync/file-watcher.js.map +1 -0
  54. package/dist/sync/folder-service.d.ts +110 -0
  55. package/dist/sync/folder-service.d.ts.map +1 -0
  56. package/dist/sync/folder-service.js +298 -0
  57. package/dist/sync/folder-service.js.map +1 -0
  58. package/dist/sync/folder-status-mapper.d.ts +106 -0
  59. package/dist/sync/folder-status-mapper.d.ts.map +1 -0
  60. package/dist/sync/folder-status-mapper.js +235 -0
  61. package/dist/sync/folder-status-mapper.js.map +1 -0
  62. package/dist/sync/layer-resolver.d.ts +54 -0
  63. package/dist/sync/layer-resolver.d.ts.map +1 -0
  64. package/dist/sync/layer-resolver.js +206 -0
  65. package/dist/sync/layer-resolver.js.map +1 -0
  66. package/dist/sync/markdown-parser.d.ts +49 -0
  67. package/dist/sync/markdown-parser.d.ts.map +1 -0
  68. package/dist/sync/markdown-parser.js +202 -0
  69. package/dist/sync/markdown-parser.js.map +1 -0
  70. package/dist/sync/reverse-sync.d.ts +139 -0
  71. package/dist/sync/reverse-sync.d.ts.map +1 -0
  72. package/dist/sync/reverse-sync.js +773 -0
  73. package/dist/sync/reverse-sync.js.map +1 -0
  74. package/dist/sync/sync-engine.d.ts +157 -0
  75. package/dist/sync/sync-engine.d.ts.map +1 -0
  76. package/dist/sync/sync-engine.js +875 -0
  77. package/dist/sync/sync-engine.js.map +1 -0
  78. package/dist/sync/sync-index.d.ts +150 -0
  79. package/dist/sync/sync-index.d.ts.map +1 -0
  80. package/dist/sync/sync-index.js +287 -0
  81. package/dist/sync/sync-index.js.map +1 -0
  82. package/dist/sync/trinity-mapper.d.ts +62 -0
  83. package/dist/sync/trinity-mapper.d.ts.map +1 -0
  84. package/dist/sync/trinity-mapper.js +548 -0
  85. package/dist/sync/trinity-mapper.js.map +1 -0
  86. package/dist/sync/types.d.ts +176 -0
  87. package/dist/sync/types.d.ts.map +1 -0
  88. package/dist/sync/types.js +6 -0
  89. package/dist/sync/types.js.map +1 -0
  90. package/dist/tools/apply-framework.d.ts +7 -0
  91. package/dist/tools/apply-framework.d.ts.map +1 -0
  92. package/dist/tools/apply-framework.js +30 -0
  93. package/dist/tools/apply-framework.js.map +1 -0
  94. package/dist/tools/commander-comment-create.d.ts +7 -0
  95. package/dist/tools/commander-comment-create.d.ts.map +1 -0
  96. package/dist/tools/commander-comment-create.js +100 -0
  97. package/dist/tools/commander-comment-create.js.map +1 -0
  98. package/dist/tools/commander-comment-list.d.ts +7 -0
  99. package/dist/tools/commander-comment-list.d.ts.map +1 -0
  100. package/dist/tools/commander-comment-list.js +110 -0
  101. package/dist/tools/commander-comment-list.js.map +1 -0
  102. package/dist/tools/commander-document-create.d.ts +7 -0
  103. package/dist/tools/commander-document-create.d.ts.map +1 -0
  104. package/dist/tools/commander-document-create.js +168 -0
  105. package/dist/tools/commander-document-create.js.map +1 -0
  106. package/dist/tools/commander-document-get.d.ts +7 -0
  107. package/dist/tools/commander-document-get.d.ts.map +1 -0
  108. package/dist/tools/commander-document-get.js +104 -0
  109. package/dist/tools/commander-document-get.js.map +1 -0
  110. package/dist/tools/commander-document-list.d.ts +7 -0
  111. package/dist/tools/commander-document-list.d.ts.map +1 -0
  112. package/dist/tools/commander-document-list.js +117 -0
  113. package/dist/tools/commander-document-list.js.map +1 -0
  114. package/dist/tools/commander-document-update.d.ts +7 -0
  115. package/dist/tools/commander-document-update.d.ts.map +1 -0
  116. package/dist/tools/commander-document-update.js +133 -0
  117. package/dist/tools/commander-document-update.js.map +1 -0
  118. package/dist/tools/commander-folder-create.d.ts +7 -0
  119. package/dist/tools/commander-folder-create.d.ts.map +1 -0
  120. package/dist/tools/commander-folder-create.js +157 -0
  121. package/dist/tools/commander-folder-create.js.map +1 -0
  122. package/dist/tools/commander-folder-delete.d.ts +7 -0
  123. package/dist/tools/commander-folder-delete.d.ts.map +1 -0
  124. package/dist/tools/commander-folder-delete.js +85 -0
  125. package/dist/tools/commander-folder-delete.js.map +1 -0
  126. package/dist/tools/commander-folder-get.d.ts +7 -0
  127. package/dist/tools/commander-folder-get.d.ts.map +1 -0
  128. package/dist/tools/commander-folder-get.js +94 -0
  129. package/dist/tools/commander-folder-get.js.map +1 -0
  130. package/dist/tools/commander-folder-list.d.ts +7 -0
  131. package/dist/tools/commander-folder-list.d.ts.map +1 -0
  132. package/dist/tools/commander-folder-list.js +96 -0
  133. package/dist/tools/commander-folder-list.js.map +1 -0
  134. package/dist/tools/commander-folder-update.d.ts +7 -0
  135. package/dist/tools/commander-folder-update.d.ts.map +1 -0
  136. package/dist/tools/commander-folder-update.js +120 -0
  137. package/dist/tools/commander-folder-update.js.map +1 -0
  138. package/dist/tools/commander-framework-apply.d.ts +7 -0
  139. package/dist/tools/commander-framework-apply.d.ts.map +1 -0
  140. package/dist/tools/commander-framework-apply.js +110 -0
  141. package/dist/tools/commander-framework-apply.js.map +1 -0
  142. package/dist/tools/commander-framework-categories.d.ts +7 -0
  143. package/dist/tools/commander-framework-categories.d.ts.map +1 -0
  144. package/dist/tools/commander-framework-categories.js +90 -0
  145. package/dist/tools/commander-framework-categories.js.map +1 -0
  146. package/dist/tools/commander-framework-get.d.ts +7 -0
  147. package/dist/tools/commander-framework-get.d.ts.map +1 -0
  148. package/dist/tools/commander-framework-get.js +124 -0
  149. package/dist/tools/commander-framework-get.js.map +1 -0
  150. package/dist/tools/commander-framework-list.d.ts +7 -0
  151. package/dist/tools/commander-framework-list.d.ts.map +1 -0
  152. package/dist/tools/commander-framework-list.js +103 -0
  153. package/dist/tools/commander-framework-list.js.map +1 -0
  154. package/dist/tools/commander-goal-create.d.ts +7 -0
  155. package/dist/tools/commander-goal-create.d.ts.map +1 -0
  156. package/dist/tools/commander-goal-create.js +130 -0
  157. package/dist/tools/commander-goal-create.js.map +1 -0
  158. package/dist/tools/commander-goal-get.d.ts +7 -0
  159. package/dist/tools/commander-goal-get.d.ts.map +1 -0
  160. package/dist/tools/commander-goal-get.js +83 -0
  161. package/dist/tools/commander-goal-get.js.map +1 -0
  162. package/dist/tools/commander-goal-list.d.ts +7 -0
  163. package/dist/tools/commander-goal-list.d.ts.map +1 -0
  164. package/dist/tools/commander-goal-list.js +111 -0
  165. package/dist/tools/commander-goal-list.js.map +1 -0
  166. package/dist/tools/commander-goal-update.d.ts +7 -0
  167. package/dist/tools/commander-goal-update.d.ts.map +1 -0
  168. package/dist/tools/commander-goal-update.js +110 -0
  169. package/dist/tools/commander-goal-update.js.map +1 -0
  170. package/dist/tools/commander-key-result-create.d.ts +7 -0
  171. package/dist/tools/commander-key-result-create.d.ts.map +1 -0
  172. package/dist/tools/commander-key-result-create.js +134 -0
  173. package/dist/tools/commander-key-result-create.js.map +1 -0
  174. package/dist/tools/commander-key-result-update.d.ts +7 -0
  175. package/dist/tools/commander-key-result-update.d.ts.map +1 -0
  176. package/dist/tools/commander-key-result-update.js +119 -0
  177. package/dist/tools/commander-key-result-update.js.map +1 -0
  178. package/dist/tools/commander-layer-create.d.ts +7 -0
  179. package/dist/tools/commander-layer-create.d.ts.map +1 -0
  180. package/dist/tools/commander-layer-create.js +167 -0
  181. package/dist/tools/commander-layer-create.js.map +1 -0
  182. package/dist/tools/commander-layer-delete.d.ts +7 -0
  183. package/dist/tools/commander-layer-delete.d.ts.map +1 -0
  184. package/dist/tools/commander-layer-delete.js +141 -0
  185. package/dist/tools/commander-layer-delete.js.map +1 -0
  186. package/dist/tools/commander-layer-list.d.ts +7 -0
  187. package/dist/tools/commander-layer-list.d.ts.map +1 -0
  188. package/dist/tools/commander-layer-list.js +102 -0
  189. package/dist/tools/commander-layer-list.js.map +1 -0
  190. package/dist/tools/commander-presentation.d.ts +7 -0
  191. package/dist/tools/commander-presentation.d.ts.map +1 -0
  192. package/dist/tools/commander-presentation.js +185 -0
  193. package/dist/tools/commander-presentation.js.map +1 -0
  194. package/dist/tools/commander-project-create.d.ts +7 -0
  195. package/dist/tools/commander-project-create.d.ts.map +1 -0
  196. package/dist/tools/commander-project-create.js +130 -0
  197. package/dist/tools/commander-project-create.js.map +1 -0
  198. package/dist/tools/commander-project-get.d.ts +7 -0
  199. package/dist/tools/commander-project-get.d.ts.map +1 -0
  200. package/dist/tools/commander-project-get.js +107 -0
  201. package/dist/tools/commander-project-get.js.map +1 -0
  202. package/dist/tools/commander-project-list.d.ts +7 -0
  203. package/dist/tools/commander-project-list.d.ts.map +1 -0
  204. package/dist/tools/commander-project-list.js +104 -0
  205. package/dist/tools/commander-project-list.js.map +1 -0
  206. package/dist/tools/commander-project-update.d.ts +7 -0
  207. package/dist/tools/commander-project-update.d.ts.map +1 -0
  208. package/dist/tools/commander-project-update.js +126 -0
  209. package/dist/tools/commander-project-update.js.map +1 -0
  210. package/dist/tools/commander-project.d.ts +7 -0
  211. package/dist/tools/commander-project.d.ts.map +1 -0
  212. package/dist/tools/commander-project.js +144 -0
  213. package/dist/tools/commander-project.js.map +1 -0
  214. package/dist/tools/commander-role-assign.d.ts +7 -0
  215. package/dist/tools/commander-role-assign.d.ts.map +1 -0
  216. package/dist/tools/commander-role-assign.js +115 -0
  217. package/dist/tools/commander-role-assign.js.map +1 -0
  218. package/dist/tools/commander-role-create.d.ts +7 -0
  219. package/dist/tools/commander-role-create.d.ts.map +1 -0
  220. package/dist/tools/commander-role-create.js +130 -0
  221. package/dist/tools/commander-role-create.js.map +1 -0
  222. package/dist/tools/commander-role-get.d.ts +7 -0
  223. package/dist/tools/commander-role-get.d.ts.map +1 -0
  224. package/dist/tools/commander-role-get.js +108 -0
  225. package/dist/tools/commander-role-get.js.map +1 -0
  226. package/dist/tools/commander-role-list.d.ts +7 -0
  227. package/dist/tools/commander-role-list.d.ts.map +1 -0
  228. package/dist/tools/commander-role-list.js +106 -0
  229. package/dist/tools/commander-role-list.js.map +1 -0
  230. package/dist/tools/commander-role-update.d.ts +7 -0
  231. package/dist/tools/commander-role-update.d.ts.map +1 -0
  232. package/dist/tools/commander-role-update.js +126 -0
  233. package/dist/tools/commander-role-update.js.map +1 -0
  234. package/dist/tools/commander-search.d.ts +7 -0
  235. package/dist/tools/commander-search.d.ts.map +1 -0
  236. package/dist/tools/commander-search.js +146 -0
  237. package/dist/tools/commander-search.js.map +1 -0
  238. package/dist/tools/commander-sheet-create.d.ts +7 -0
  239. package/dist/tools/commander-sheet-create.d.ts.map +1 -0
  240. package/dist/tools/commander-sheet-create.js +160 -0
  241. package/dist/tools/commander-sheet-create.js.map +1 -0
  242. package/dist/tools/commander-sheet-get.d.ts +7 -0
  243. package/dist/tools/commander-sheet-get.d.ts.map +1 -0
  244. package/dist/tools/commander-sheet-get.js +128 -0
  245. package/dist/tools/commander-sheet-get.js.map +1 -0
  246. package/dist/tools/commander-sheet-list.d.ts +7 -0
  247. package/dist/tools/commander-sheet-list.d.ts.map +1 -0
  248. package/dist/tools/commander-sheet-list.js +108 -0
  249. package/dist/tools/commander-sheet-list.js.map +1 -0
  250. package/dist/tools/commander-sheet-update.d.ts +7 -0
  251. package/dist/tools/commander-sheet-update.d.ts.map +1 -0
  252. package/dist/tools/commander-sheet-update.js +163 -0
  253. package/dist/tools/commander-sheet-update.js.map +1 -0
  254. package/dist/tools/commander-status-list.d.ts +7 -0
  255. package/dist/tools/commander-status-list.d.ts.map +1 -0
  256. package/dist/tools/commander-status-list.js +103 -0
  257. package/dist/tools/commander-status-list.js.map +1 -0
  258. package/dist/tools/commander-task-assign.d.ts +7 -0
  259. package/dist/tools/commander-task-assign.d.ts.map +1 -0
  260. package/dist/tools/commander-task-assign.js +91 -0
  261. package/dist/tools/commander-task-assign.js.map +1 -0
  262. package/dist/tools/commander-task-create.d.ts +7 -0
  263. package/dist/tools/commander-task-create.d.ts.map +1 -0
  264. package/dist/tools/commander-task-create.js +142 -0
  265. package/dist/tools/commander-task-create.js.map +1 -0
  266. package/dist/tools/commander-task-delete.d.ts +7 -0
  267. package/dist/tools/commander-task-delete.d.ts.map +1 -0
  268. package/dist/tools/commander-task-delete.js +88 -0
  269. package/dist/tools/commander-task-delete.js.map +1 -0
  270. package/dist/tools/commander-task-list-mine.d.ts +7 -0
  271. package/dist/tools/commander-task-list-mine.d.ts.map +1 -0
  272. package/dist/tools/commander-task-list-mine.js +109 -0
  273. package/dist/tools/commander-task-list-mine.js.map +1 -0
  274. package/dist/tools/commander-task-read.d.ts +10 -0
  275. package/dist/tools/commander-task-read.d.ts.map +1 -0
  276. package/dist/tools/commander-task-read.js +96 -0
  277. package/dist/tools/commander-task-read.js.map +1 -0
  278. package/dist/tools/commander-task-update.d.ts +7 -0
  279. package/dist/tools/commander-task-update.d.ts.map +1 -0
  280. package/dist/tools/commander-task-update.js +159 -0
  281. package/dist/tools/commander-task-update.js.map +1 -0
  282. package/dist/tools/commander-taskboard-tasks.d.ts +7 -0
  283. package/dist/tools/commander-taskboard-tasks.d.ts.map +1 -0
  284. package/dist/tools/commander-taskboard-tasks.js +97 -0
  285. package/dist/tools/commander-taskboard-tasks.js.map +1 -0
  286. package/dist/tools/commander-team-add-member.d.ts +7 -0
  287. package/dist/tools/commander-team-add-member.d.ts.map +1 -0
  288. package/dist/tools/commander-team-add-member.js +104 -0
  289. package/dist/tools/commander-team-add-member.js.map +1 -0
  290. package/dist/tools/commander-team-create.d.ts +7 -0
  291. package/dist/tools/commander-team-create.d.ts.map +1 -0
  292. package/dist/tools/commander-team-create.js +117 -0
  293. package/dist/tools/commander-team-create.js.map +1 -0
  294. package/dist/tools/commander-team-list.d.ts +7 -0
  295. package/dist/tools/commander-team-list.d.ts.map +1 -0
  296. package/dist/tools/commander-team-list.js +94 -0
  297. package/dist/tools/commander-team-list.js.map +1 -0
  298. package/dist/tools/commander-team-remove-member.d.ts +7 -0
  299. package/dist/tools/commander-team-remove-member.d.ts.map +1 -0
  300. package/dist/tools/commander-team-remove-member.js +98 -0
  301. package/dist/tools/commander-team-remove-member.js.map +1 -0
  302. package/dist/tools/commander-user-get.d.ts +7 -0
  303. package/dist/tools/commander-user-get.d.ts.map +1 -0
  304. package/dist/tools/commander-user-get.js +101 -0
  305. package/dist/tools/commander-user-get.js.map +1 -0
  306. package/dist/tools/commander-user-invite.d.ts +7 -0
  307. package/dist/tools/commander-user-invite.d.ts.map +1 -0
  308. package/dist/tools/commander-user-invite.js +119 -0
  309. package/dist/tools/commander-user-invite.js.map +1 -0
  310. package/dist/tools/commander-user-list.d.ts +7 -0
  311. package/dist/tools/commander-user-list.d.ts.map +1 -0
  312. package/dist/tools/commander-user-list.js +108 -0
  313. package/dist/tools/commander-user-list.js.map +1 -0
  314. package/dist/tools/commander-workspace-create.d.ts +7 -0
  315. package/dist/tools/commander-workspace-create.d.ts.map +1 -0
  316. package/dist/tools/commander-workspace-create.js +124 -0
  317. package/dist/tools/commander-workspace-create.js.map +1 -0
  318. package/dist/tools/commander-workspace-list.d.ts +7 -0
  319. package/dist/tools/commander-workspace-list.d.ts.map +1 -0
  320. package/dist/tools/commander-workspace-list.js +95 -0
  321. package/dist/tools/commander-workspace-list.js.map +1 -0
  322. package/dist/tools/commander-workspace-update.d.ts +7 -0
  323. package/dist/tools/commander-workspace-update.d.ts.map +1 -0
  324. package/dist/tools/commander-workspace-update.js +118 -0
  325. package/dist/tools/commander-workspace-update.js.map +1 -0
  326. package/dist/tools/commander-workspace.d.ts +7 -0
  327. package/dist/tools/commander-workspace.d.ts.map +1 -0
  328. package/dist/tools/commander-workspace.js +131 -0
  329. package/dist/tools/commander-workspace.js.map +1 -0
  330. package/dist/tools/create-kanban.d.ts +7 -0
  331. package/dist/tools/create-kanban.d.ts.map +1 -0
  332. package/dist/tools/create-kanban.js +32 -0
  333. package/dist/tools/create-kanban.js.map +1 -0
  334. package/dist/tools/create-table.d.ts +7 -0
  335. package/dist/tools/create-table.d.ts.map +1 -0
  336. package/dist/tools/create-table.js +188 -0
  337. package/dist/tools/create-table.js.map +1 -0
  338. package/dist/tools/search-knowledge.d.ts +7 -0
  339. package/dist/tools/search-knowledge.d.ts.map +1 -0
  340. package/dist/tools/search-knowledge.js +33 -0
  341. package/dist/tools/search-knowledge.js.map +1 -0
  342. package/dist/tools/waymaker-kanban-view.d.ts +7 -0
  343. package/dist/tools/waymaker-kanban-view.d.ts.map +1 -0
  344. package/dist/tools/waymaker-kanban-view.js +255 -0
  345. package/dist/tools/waymaker-kanban-view.js.map +1 -0
  346. package/dist/tools/waymaker-sync-configure.d.ts +13 -0
  347. package/dist/tools/waymaker-sync-configure.d.ts.map +1 -0
  348. package/dist/tools/waymaker-sync-configure.js +291 -0
  349. package/dist/tools/waymaker-sync-configure.js.map +1 -0
  350. package/dist/tools/waymaker-sync-file.d.ts +7 -0
  351. package/dist/tools/waymaker-sync-file.d.ts.map +1 -0
  352. package/dist/tools/waymaker-sync-file.js +79 -0
  353. package/dist/tools/waymaker-sync-file.js.map +1 -0
  354. package/dist/tools/waymaker-sync-poll.d.ts +8 -0
  355. package/dist/tools/waymaker-sync-poll.d.ts.map +1 -0
  356. package/dist/tools/waymaker-sync-poll.js +398 -0
  357. package/dist/tools/waymaker-sync-poll.js.map +1 -0
  358. package/dist/tools/waymaker-sync-start.d.ts +7 -0
  359. package/dist/tools/waymaker-sync-start.d.ts.map +1 -0
  360. package/dist/tools/waymaker-sync-start.js +56 -0
  361. package/dist/tools/waymaker-sync-start.js.map +1 -0
  362. package/dist/tools/waymaker-sync-status.d.ts +7 -0
  363. package/dist/tools/waymaker-sync-status.d.ts.map +1 -0
  364. package/dist/tools/waymaker-sync-status.js +45 -0
  365. package/dist/tools/waymaker-sync-status.js.map +1 -0
  366. package/dist/tools/waymaker-sync-stop.d.ts +7 -0
  367. package/dist/tools/waymaker-sync-stop.d.ts.map +1 -0
  368. package/dist/tools/waymaker-sync-stop.js +56 -0
  369. package/dist/tools/waymaker-sync-stop.js.map +1 -0
  370. package/dist/tools/waymaker-sync-workspace.d.ts +26 -0
  371. package/dist/tools/waymaker-sync-workspace.d.ts.map +1 -0
  372. package/dist/tools/waymaker-sync-workspace.js +148 -0
  373. package/dist/tools/waymaker-sync-workspace.js.map +1 -0
  374. package/dist/tools/waymaker-sync-workspace.tool.d.ts +9 -0
  375. package/dist/tools/waymaker-sync-workspace.tool.d.ts.map +1 -0
  376. package/dist/tools/waymaker-sync-workspace.tool.js +68 -0
  377. package/dist/tools/waymaker-sync-workspace.tool.js.map +1 -0
  378. package/dist/types/tool.d.ts +13 -0
  379. package/dist/types/tool.d.ts.map +1 -0
  380. package/dist/types/tool.js +2 -0
  381. package/dist/types/tool.js.map +1 -0
  382. package/dist/utils/daemon-health.d.ts +21 -0
  383. package/dist/utils/daemon-health.d.ts.map +1 -0
  384. package/dist/utils/daemon-health.js +40 -0
  385. package/dist/utils/daemon-health.js.map +1 -0
  386. package/dist/utils/fetch-ipv4.d.ts +36 -0
  387. package/dist/utils/fetch-ipv4.d.ts.map +1 -0
  388. package/dist/utils/fetch-ipv4.js +91 -0
  389. package/dist/utils/fetch-ipv4.js.map +1 -0
  390. package/package.json +62 -0
@@ -0,0 +1,773 @@
1
+ /**
2
+ * ReverseSync: Commander → IDE Synchronization
3
+ *
4
+ * Subscribes to Commander taskboard changes and syncs them to IDE filesystem.
5
+ * Part of bidirectional Waymaker Sync.
6
+ */
7
+ // Polyfill WebSocket for Node.js (required by Supabase Realtime)
8
+ import WebSocket from 'ws';
9
+ if (typeof globalThis.WebSocket === 'undefined') {
10
+ globalThis.WebSocket = WebSocket;
11
+ }
12
+ import { createClient } from '@supabase/supabase-js';
13
+ import * as path from 'path';
14
+ import * as fs from 'fs/promises';
15
+ import { EventEmitter } from 'events';
16
+ export class ReverseSync extends EventEmitter {
17
+ config;
18
+ supabase;
19
+ channel = null;
20
+ running = false;
21
+ fileMap = new Map(); // task_id → file_path
22
+ sectionMap = new Map(); // status_section_id → folder_name
23
+ pendingChanges = new Map();
24
+ syncTimer = null;
25
+ reconnectAttempts = 0;
26
+ maxReconnectAttempts = 10;
27
+ reconnectTimer = null;
28
+ supabaseToken = null;
29
+ tokenExpiresAt = null;
30
+ tokenRefreshTimer = null;
31
+ recentEvents = new Map(); // "taskId:eventType" → timestamp
32
+ dedupeWindowMs = 2000; // Ignore duplicate events within 2s
33
+ constructor(config) {
34
+ super();
35
+ this.config = config;
36
+ // Initialize Supabase client with anon key
37
+ // After token exchange, we'll call setAuth() with the Supabase JWT
38
+ this.supabase = createClient(config.supabaseUrl, config.supabaseKey);
39
+ }
40
+ /**
41
+ * Exchange OAuth token (wm_at_*) for a Supabase-compatible JWT
42
+ * This allows Realtime subscriptions to pass RLS policies
43
+ */
44
+ async exchangeTokenForSupabaseJWT() {
45
+ if (!this.config.apiKey?.startsWith('wm_at_')) {
46
+ console.error('[ReverseSync] No OAuth token available for exchange');
47
+ return false;
48
+ }
49
+ console.error('[ReverseSync] Exchanging OAuth token for Supabase JWT...');
50
+ try {
51
+ const response = await fetch(`${this.config.supabaseUrl}/functions/v1/auth-token-exchange`, {
52
+ method: 'POST',
53
+ headers: {
54
+ 'Content-Type': 'application/json',
55
+ 'Authorization': `Bearer ${this.config.apiKey}`,
56
+ },
57
+ });
58
+ if (!response.ok) {
59
+ const errorText = await response.text();
60
+ console.error(`[ReverseSync] Token exchange failed (${response.status}):`, errorText);
61
+ return false;
62
+ }
63
+ const data = await response.json();
64
+ if (!data.success || !data.supabaseToken) {
65
+ console.error('[ReverseSync] Token exchange response invalid:', data);
66
+ return false;
67
+ }
68
+ // Store the token and expiry
69
+ this.supabaseToken = data.supabaseToken;
70
+ this.tokenExpiresAt = new Date(data.expiresAt);
71
+ // Set the JWT for Realtime authentication
72
+ // The anon key remains as the API key, JWT is used for auth via setAuth()
73
+ this.supabase.realtime.setAuth(this.supabaseToken);
74
+ console.error('[ReverseSync] ✅ Token exchanged successfully');
75
+ console.error(`[ReverseSync] User: ${data.userId}`);
76
+ console.error(`[ReverseSync] Org: ${data.organizationId || 'none'}`);
77
+ console.error(`[ReverseSync] Expires: ${data.expiresAt}`);
78
+ // Schedule token refresh before expiry (5 minutes before)
79
+ this.scheduleTokenRefresh();
80
+ return true;
81
+ }
82
+ catch (error) {
83
+ console.error('[ReverseSync] Token exchange error:', error);
84
+ return false;
85
+ }
86
+ }
87
+ /**
88
+ * Schedule automatic token refresh before expiry
89
+ */
90
+ scheduleTokenRefresh() {
91
+ // Clear any existing refresh timer
92
+ if (this.tokenRefreshTimer) {
93
+ clearTimeout(this.tokenRefreshTimer);
94
+ this.tokenRefreshTimer = null;
95
+ }
96
+ if (!this.tokenExpiresAt) {
97
+ return;
98
+ }
99
+ // Refresh 5 minutes before expiry
100
+ const refreshTime = this.tokenExpiresAt.getTime() - Date.now() - 5 * 60 * 1000;
101
+ if (refreshTime <= 0) {
102
+ // Token expires soon, refresh immediately
103
+ console.error('[ReverseSync] Token expiring soon, refreshing immediately...');
104
+ this.exchangeTokenForSupabaseJWT();
105
+ return;
106
+ }
107
+ console.error(`[ReverseSync] Token refresh scheduled in ${Math.round(refreshTime / 60000)} minutes`);
108
+ this.tokenRefreshTimer = setTimeout(async () => {
109
+ console.error('[ReverseSync] Refreshing Supabase token...');
110
+ const success = await this.exchangeTokenForSupabaseJWT();
111
+ if (success) {
112
+ // Re-authenticate the realtime channel
113
+ this.supabase.realtime.setAuth(this.supabaseToken);
114
+ }
115
+ }, refreshTime);
116
+ }
117
+ /**
118
+ * Start reverse sync - subscribe to task changes
119
+ */
120
+ async start() {
121
+ if (this.running) {
122
+ throw new Error('ReverseSync already running');
123
+ }
124
+ console.error('[ReverseSync] Starting...');
125
+ // Exchange OAuth token for Supabase JWT (required for Realtime RLS)
126
+ if (this.config.apiKey?.startsWith('wm_at_')) {
127
+ const tokenOk = await this.exchangeTokenForSupabaseJWT();
128
+ if (!tokenOk) {
129
+ console.error('[ReverseSync] ⚠️ Token exchange failed - Realtime may be blocked by RLS');
130
+ console.error('[ReverseSync] Initial sync will still work, but live updates may not');
131
+ }
132
+ }
133
+ else {
134
+ console.error('[ReverseSync] ⚠️ No OAuth token - using anon key (RLS may block)');
135
+ }
136
+ // Load section mappings from database
137
+ await this.loadSectionMappings();
138
+ // Load existing task files to build file map
139
+ await this.loadExistingFiles();
140
+ // Perform initial sync of existing tasks
141
+ await this.performInitialSync();
142
+ // Subscribe to task changes
143
+ await this.subscribeToTaskChanges();
144
+ this.running = true;
145
+ console.error('[ReverseSync] ✅ Started');
146
+ this.emit('started');
147
+ }
148
+ /**
149
+ * Stop reverse sync
150
+ */
151
+ async stop() {
152
+ if (!this.running) {
153
+ return;
154
+ }
155
+ console.error('[ReverseSync] Stopping...');
156
+ // Unsubscribe from realtime
157
+ if (this.channel) {
158
+ await this.channel.unsubscribe();
159
+ this.channel = null;
160
+ }
161
+ // Clear pending changes
162
+ if (this.syncTimer) {
163
+ clearTimeout(this.syncTimer);
164
+ this.syncTimer = null;
165
+ }
166
+ // Clear reconnection timer
167
+ if (this.reconnectTimer) {
168
+ clearTimeout(this.reconnectTimer);
169
+ this.reconnectTimer = null;
170
+ }
171
+ // Clear token refresh timer
172
+ if (this.tokenRefreshTimer) {
173
+ clearTimeout(this.tokenRefreshTimer);
174
+ this.tokenRefreshTimer = null;
175
+ }
176
+ this.running = false;
177
+ this.reconnectAttempts = 0;
178
+ this.supabaseToken = null;
179
+ this.tokenExpiresAt = null;
180
+ console.error('[ReverseSync] ✅ Stopped');
181
+ this.emit('stopped');
182
+ }
183
+ /**
184
+ * Subscribe to Supabase realtime for task changes
185
+ */
186
+ async subscribeToTaskChanges() {
187
+ console.error(`[ReverseSync] Subscribing to Realtime for board: ${this.config.taskboardId}`);
188
+ this.channel = this.supabase
189
+ .channel('task-changes')
190
+ .on('postgres_changes', {
191
+ event: '*', // Listen to INSERT, UPDATE, DELETE
192
+ schema: 'public',
193
+ table: 'tasks',
194
+ filter: `board_id=eq.${this.config.taskboardId}`,
195
+ }, (payload) => {
196
+ this.handleRealtimeEvent(payload);
197
+ })
198
+ .subscribe(async (status, err) => {
199
+ // Log ALL status changes for debugging
200
+ console.error(`[ReverseSync] Realtime status: ${status}${err ? ` (error: ${JSON.stringify(err)})` : ''}`);
201
+ if (status === 'SUBSCRIBED') {
202
+ console.error('[ReverseSync] ✅ Subscribed to task changes');
203
+ // Reset reconnect attempts on successful connection
204
+ this.reconnectAttempts = 0;
205
+ // Update board settings to reflect sync is active
206
+ await this.updateBoardSyncStatus(true);
207
+ }
208
+ else if (status === 'CLOSED') {
209
+ console.error('[ReverseSync] ⚠️ Subscription closed, reconnecting...');
210
+ this.handleReconnect();
211
+ }
212
+ else if (status === 'CHANNEL_ERROR') {
213
+ console.error('[ReverseSync] ❌ Subscription error, reconnecting...');
214
+ this.handleReconnect();
215
+ }
216
+ else if (status === 'TIMED_OUT') {
217
+ console.error('[ReverseSync] ⏰ Subscription timed out, reconnecting...');
218
+ this.handleReconnect();
219
+ }
220
+ });
221
+ // Log channel state after setup
222
+ console.error(`[ReverseSync] Channel created, waiting for connection...`);
223
+ }
224
+ /**
225
+ * Handle reconnection with exponential backoff
226
+ */
227
+ async handleReconnect() {
228
+ // Don't reconnect if we're not running
229
+ if (!this.running) {
230
+ return;
231
+ }
232
+ // Check if we've exceeded max attempts
233
+ if (this.reconnectAttempts >= this.maxReconnectAttempts) {
234
+ console.error(`[ReverseSync] ❌ Max reconnection attempts (${this.maxReconnectAttempts}) reached. Giving up.`);
235
+ console.error('[ReverseSync] Please restart the sync daemon manually.');
236
+ return;
237
+ }
238
+ this.reconnectAttempts++;
239
+ // Calculate backoff: 2^attempts seconds, capped at 60s
240
+ const backoffSeconds = Math.min(Math.pow(2, this.reconnectAttempts), 60);
241
+ console.error(`[ReverseSync] Reconnection attempt ${this.reconnectAttempts}/${this.maxReconnectAttempts} in ${backoffSeconds}s...`);
242
+ // Clear existing channel
243
+ if (this.channel) {
244
+ try {
245
+ await this.channel.unsubscribe();
246
+ }
247
+ catch (error) {
248
+ // Ignore unsubscribe errors
249
+ }
250
+ this.channel = null;
251
+ }
252
+ // Schedule reconnection
253
+ this.reconnectTimer = setTimeout(async () => {
254
+ try {
255
+ await this.subscribeToTaskChanges();
256
+ }
257
+ catch (error) {
258
+ console.error('[ReverseSync] Reconnection failed:', error);
259
+ // Try again
260
+ this.handleReconnect();
261
+ }
262
+ }, backoffSeconds * 1000);
263
+ }
264
+ /**
265
+ * Update board sync status via edge function
266
+ */
267
+ async updateBoardSyncStatus(enabled) {
268
+ if (!this.config.apiKey) {
269
+ console.error('[ReverseSync] No API key configured - skipping board sync status update');
270
+ return;
271
+ }
272
+ try {
273
+ const edgeFunctionUrl = `${this.config.supabaseUrl}/functions/v1/commander-task-board-operations`;
274
+ const response = await fetch(edgeFunctionUrl, {
275
+ method: 'POST',
276
+ headers: {
277
+ 'Content-Type': 'application/json',
278
+ 'Authorization': `Bearer ${this.config.apiKey}`,
279
+ },
280
+ body: JSON.stringify({
281
+ action: 'update_board',
282
+ id: this.config.taskboardId,
283
+ settings: {
284
+ sync_enabled: enabled,
285
+ last_sync_at: new Date().toISOString(),
286
+ },
287
+ }),
288
+ });
289
+ if (!response.ok) {
290
+ const error = await response.text();
291
+ console.error('[ReverseSync] Failed to update board sync status:', error);
292
+ }
293
+ else {
294
+ console.error(`[ReverseSync] ✅ Board sync status updated: ${enabled ? 'enabled' : 'disabled'}`);
295
+ }
296
+ }
297
+ catch (error) {
298
+ console.error('[ReverseSync] Error updating board sync status:', error);
299
+ }
300
+ }
301
+ /**
302
+ * Handle realtime event from Supabase
303
+ */
304
+ handleRealtimeEvent(payload) {
305
+ const { eventType, new: newRecord, old: oldRecord } = payload;
306
+ // Use newRecord if it has an id, otherwise use oldRecord (for DELETE events)
307
+ const taskData = (newRecord?.id) ? newRecord : oldRecord;
308
+ if (!taskData || !taskData.id) {
309
+ console.error(`[ReverseSync] Error: Missing task data in ${eventType} event`, { newRecord, oldRecord });
310
+ return;
311
+ }
312
+ // Deduplicate: Supabase Realtime can fire 2 UPDATE events per change
313
+ const dedupeKey = `${taskData.id}:${eventType}`;
314
+ const now = Date.now();
315
+ const lastSeen = this.recentEvents.get(dedupeKey);
316
+ if (lastSeen && (now - lastSeen) < this.dedupeWindowMs) {
317
+ console.error(`[ReverseSync] Skipping duplicate ${eventType} for task ${taskData.id}`);
318
+ return;
319
+ }
320
+ this.recentEvents.set(dedupeKey, now);
321
+ // Clean up old entries periodically
322
+ if (this.recentEvents.size > 100) {
323
+ for (const [key, ts] of this.recentEvents) {
324
+ if (now - ts > this.dedupeWindowMs)
325
+ this.recentEvents.delete(key);
326
+ }
327
+ }
328
+ console.error(`[ReverseSync] Received ${eventType} event for task:`, taskData.id);
329
+ const change = {
330
+ type: eventType,
331
+ task: taskData,
332
+ old: oldRecord,
333
+ };
334
+ // Queue change for processing (debounce rapid changes)
335
+ this.handleTaskChange(change);
336
+ }
337
+ /**
338
+ * Load section mappings from database for folder organization
339
+ */
340
+ async loadSectionMappings() {
341
+ console.error(`[ReverseSync] Loading section mappings for board: ${this.config.taskboardId}`);
342
+ try {
343
+ const { data: sections, error } = await this.supabase
344
+ .from('task_status_sections')
345
+ .select('id, name, board_id, position')
346
+ .eq('board_id', this.config.taskboardId)
347
+ .order('position', { ascending: true });
348
+ if (error) {
349
+ console.error('[ReverseSync] Error loading sections:', error);
350
+ throw error;
351
+ }
352
+ if (!sections || sections.length === 0) {
353
+ console.error('[ReverseSync] WARNING: No sections found for board');
354
+ return;
355
+ }
356
+ // Build section_id → folder_name mapping
357
+ for (const section of sections) {
358
+ const folderName = this.slugifyName(section.name);
359
+ this.sectionMap.set(section.id, folderName);
360
+ console.error(`[ReverseSync] Section: ${section.name} → ${folderName}/`);
361
+ }
362
+ console.error(`[ReverseSync] ✅ Loaded ${this.sectionMap.size} section mappings`);
363
+ }
364
+ catch (error) {
365
+ console.error('[ReverseSync] Error loading section mappings:', error);
366
+ // Non-fatal, continue without folder organization
367
+ }
368
+ }
369
+ /**
370
+ * Load existing task markdown files to build task_id → file_path map
371
+ * Scans tasks folder and all subdirectories (section folders)
372
+ */
373
+ async loadExistingFiles() {
374
+ const tasksDir = path.join(this.config.projectPath, this.config.tasksFolder);
375
+ try {
376
+ // Ensure directory exists
377
+ await fs.mkdir(tasksDir, { recursive: true });
378
+ // Read all items (files + directories)
379
+ const items = await fs.readdir(tasksDir, { withFileTypes: true });
380
+ // Process root-level .md files
381
+ const rootMdFiles = items.filter(item => item.isFile() && item.name.endsWith('.md'));
382
+ console.error(`[ReverseSync] Loading existing task files...`);
383
+ console.error(`[ReverseSync] Found ${rootMdFiles.length} files in root`);
384
+ for (const file of rootMdFiles) {
385
+ await this.loadTaskFile(file.name, tasksDir);
386
+ }
387
+ // Process subdirectories (section folders)
388
+ const subdirs = items.filter(item => item.isDirectory());
389
+ console.error(`[ReverseSync] Found ${subdirs.length} section folders`);
390
+ for (const dir of subdirs) {
391
+ const sectionPath = path.join(tasksDir, dir.name);
392
+ const sectionFiles = await fs.readdir(sectionPath);
393
+ const mdFiles = sectionFiles.filter(f => f.endsWith('.md'));
394
+ console.error(`[ReverseSync] Scanning ${dir.name}/ (${mdFiles.length} files)`);
395
+ for (const filename of mdFiles) {
396
+ // Store relative path with section folder
397
+ const relativePath = `${dir.name}/${filename}`;
398
+ await this.loadTaskFile(relativePath, tasksDir);
399
+ }
400
+ }
401
+ console.error(`[ReverseSync] ✅ Loaded ${this.fileMap.size} task files`);
402
+ }
403
+ catch (error) {
404
+ console.error(`[ReverseSync] Error loading existing files:`, error);
405
+ // Non-fatal, continue with empty map
406
+ }
407
+ }
408
+ /**
409
+ * Load a single task file and add to file map
410
+ */
411
+ async loadTaskFile(relativePath, tasksDir) {
412
+ const fullPath = path.join(tasksDir, relativePath);
413
+ try {
414
+ const content = await fs.readFile(fullPath, 'utf-8');
415
+ // Parse frontmatter to get task_id
416
+ const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
417
+ if (!frontmatterMatch) {
418
+ console.error(`[ReverseSync] No frontmatter in ${relativePath}, skipping`);
419
+ return;
420
+ }
421
+ const frontmatter = frontmatterMatch[1];
422
+ // Match both formats:
423
+ // Old: task_id: "uuid" or task_id: 'uuid'
424
+ // New: task_id: uuid (under sync block, no quotes)
425
+ const taskIdMatch = frontmatter.match(/task_id: ["']?([a-f0-9-]+)["']?/);
426
+ if (taskIdMatch) {
427
+ const taskId = taskIdMatch[1];
428
+ this.fileMap.set(taskId, relativePath);
429
+ console.error(`[ReverseSync] Loaded: ${relativePath} → ${taskId}`);
430
+ }
431
+ }
432
+ catch (error) {
433
+ console.error(`[ReverseSync] Error reading ${relativePath}:`, error);
434
+ }
435
+ }
436
+ /**
437
+ * Perform initial sync of all existing tasks in the taskboard
438
+ *
439
+ * IMPORTANT: This does NOT create conflict files. On startup we simply:
440
+ * - Create files for tasks that exist in Commander but not locally
441
+ * - Skip files that already exist locally (trust local state)
442
+ *
443
+ * Conflict detection only happens on LIVE Realtime events (changes while daemon runs).
444
+ */
445
+ async performInitialSync() {
446
+ console.error('[ReverseSync] Performing initial sync (skip-if-exists mode)...');
447
+ try {
448
+ const { data: tasks, error } = await this.supabase
449
+ .from('tasks')
450
+ .select('id, title, description, status, status_section_id, priority, board_id, updated_at, created_at, metadata')
451
+ .eq('board_id', this.config.taskboardId)
452
+ .order('created_at', { ascending: false });
453
+ if (error) {
454
+ console.error('[ReverseSync] Error querying tasks:', error);
455
+ throw error;
456
+ }
457
+ if (!tasks || tasks.length === 0) {
458
+ console.error('[ReverseSync] No existing tasks found in taskboard');
459
+ return;
460
+ }
461
+ console.error(`[ReverseSync] Found ${tasks.length} tasks in Commander`);
462
+ // Create all section folders first
463
+ const tasksDir = path.join(this.config.projectPath, this.config.tasksFolder);
464
+ for (const [_sectionId, folderName] of this.sectionMap.entries()) {
465
+ const sectionPath = path.join(tasksDir, folderName);
466
+ try {
467
+ await fs.mkdir(sectionPath, { recursive: true });
468
+ }
469
+ catch {
470
+ // Folder may already exist
471
+ }
472
+ }
473
+ // Track statistics
474
+ let created = 0;
475
+ let skipped = 0;
476
+ // Process each task - simple logic: create if missing, skip if exists
477
+ for (const task of tasks) {
478
+ const existingFilePath = this.fileMap.get(task.id);
479
+ if (!existingFilePath) {
480
+ // Task exists in Commander but no file in IDE → Create file
481
+ await this.syncTaskToFile(task);
482
+ created++;
483
+ }
484
+ else {
485
+ // File already exists locally → Trust it, skip
486
+ skipped++;
487
+ }
488
+ }
489
+ console.error('[ReverseSync] ✅ Initial sync complete:');
490
+ console.error(`[ReverseSync] Created: ${created} files (new from Commander)`);
491
+ console.error(`[ReverseSync] Skipped: ${skipped} files (already exist locally)`);
492
+ console.error(`[ReverseSync] Watching for live changes...`);
493
+ }
494
+ catch (error) {
495
+ console.error('[ReverseSync] Error during initial sync:', error);
496
+ // Non-fatal, continue with realtime sync
497
+ }
498
+ }
499
+ /**
500
+ * Handle task change from Commander (debounced)
501
+ */
502
+ async handleTaskChange(change) {
503
+ const taskId = change.task.id;
504
+ // Add to pending changes (newer changes override older ones)
505
+ this.pendingChanges.set(taskId, change);
506
+ // Debounce: wait for sync interval before processing
507
+ if (this.syncTimer) {
508
+ clearTimeout(this.syncTimer);
509
+ }
510
+ this.syncTimer = setTimeout(() => {
511
+ this.processQueuedChanges();
512
+ }, this.config.syncIntervalMs);
513
+ }
514
+ /**
515
+ * Process all queued task changes
516
+ */
517
+ async processQueuedChanges() {
518
+ if (this.pendingChanges.size === 0) {
519
+ return;
520
+ }
521
+ console.error(`[ReverseSync] Processing ${this.pendingChanges.size} queued changes...`);
522
+ for (const [taskId, change] of this.pendingChanges) {
523
+ try {
524
+ switch (change.type) {
525
+ case 'INSERT':
526
+ case 'UPDATE':
527
+ await this.syncTaskToFile(change.task);
528
+ break;
529
+ case 'DELETE':
530
+ await this.deleteTaskFile(taskId);
531
+ break;
532
+ }
533
+ }
534
+ catch (error) {
535
+ console.error(`[ReverseSync] Error processing ${change.type} for ${taskId}:`, error);
536
+ this.emit('error', error);
537
+ }
538
+ }
539
+ // Clear queue
540
+ this.pendingChanges.clear();
541
+ this.syncTimer = null;
542
+ }
543
+ /**
544
+ * Sync task to file (create or update)
545
+ */
546
+ async syncTaskToFile(task) {
547
+ // Get section folder (e.g., "backlog", "to-do", "in-progress")
548
+ const sectionFolder = task.status_section_id
549
+ ? this.sectionMap.get(task.status_section_id)
550
+ : null;
551
+ // Generate filename
552
+ const filename = this.generateFilename(task.title, task.id);
553
+ // Build new file path with section folder
554
+ const newFilePath = sectionFolder
555
+ ? `${sectionFolder}/${filename}`
556
+ : filename;
557
+ // Check if file exists
558
+ const existingFilePath = this.fileMap.get(task.id);
559
+ if (existingFilePath) {
560
+ // UPDATE: Check for conflicts
561
+ const hasConflict = await this.checkConflict(task.id, task);
562
+ if (hasConflict) {
563
+ console.error(`[ReverseSync] ⚠️ Conflict detected for task ${task.id}, applying latest timestamp wins`);
564
+ // Will overwrite - conflict resolution logs to sync_transactions
565
+ }
566
+ // Check if section changed (file needs to move)
567
+ if (existingFilePath !== newFilePath) {
568
+ console.error(`[ReverseSync] Task moved sections, relocating file: ${existingFilePath} → ${newFilePath}`);
569
+ // Delete old file
570
+ await this.deleteTaskFile(task.id);
571
+ // Write to new location
572
+ await this.writeTaskFile(task, newFilePath);
573
+ }
574
+ else {
575
+ // Update existing file (same location)
576
+ await this.writeTaskFile(task, existingFilePath);
577
+ }
578
+ }
579
+ else {
580
+ // INSERT: Create new file
581
+ await this.writeTaskFile(task, newFilePath);
582
+ }
583
+ this.emit('task-synced', {
584
+ taskId: task.id,
585
+ title: task.title,
586
+ operation: existingFilePath ? 'update' : 'create',
587
+ });
588
+ }
589
+ /**
590
+ * Convert task to markdown format
591
+ */
592
+ taskToMarkdown(task, existingDocumentId) {
593
+ const { id, title, description, status, priority, updated_at } = task;
594
+ // Convert status to checkbox
595
+ const checkbox = status === 'done' ? '[x]' : '[ ]';
596
+ // Map task status to sync status
597
+ const syncStatus = status === 'done' ? 'completed' : 'active';
598
+ // Build frontmatter with sync block for SyncEngine compatibility
599
+ // NOTE: Do NOT set ide_modified_at here - that field tracks actual IDE edits
600
+ // ReverseSync only sets commander_modified_at to track Commander's version
601
+ const frontmatter = [
602
+ '---',
603
+ 'sync:',
604
+ ' type: task',
605
+ ` status: ${syncStatus}`,
606
+ ` task_id: ${id}`,
607
+ existingDocumentId ? ` document_id: ${existingDocumentId}` : null,
608
+ ` last_synced: '${new Date().toISOString()}'`,
609
+ `title: "${title.replace(/"/g, '\\"')}"`,
610
+ `status: "${status}"`,
611
+ priority ? `priority: "${priority}"` : null,
612
+ `commander_modified_at: "${updated_at}"`,
613
+ '---',
614
+ ].filter(Boolean).join('\n');
615
+ // Clean description - remove any existing ## Task, ## Notes, # Title sections
616
+ // to prevent accumulation from sync loop
617
+ let cleanDescription = description || '';
618
+ // Remove repeated title headers
619
+ cleanDescription = cleanDescription.replace(new RegExp(`^# ${title.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\s*`, 'gm'), '');
620
+ // Remove ## Task sections and everything after (our template sections)
621
+ cleanDescription = cleanDescription.replace(/## Task[\s\S]*$/m, '').trim();
622
+ // Build content
623
+ const content = [
624
+ `# ${title}`,
625
+ '',
626
+ cleanDescription,
627
+ '',
628
+ '## Task',
629
+ '',
630
+ `- ${checkbox} ${title}`,
631
+ '',
632
+ '## Notes',
633
+ '',
634
+ '_Add your notes here_',
635
+ ].join('\n');
636
+ return `${frontmatter}\n\n${content}\n`;
637
+ }
638
+ /**
639
+ * Slugify a name for use in folder/file names
640
+ */
641
+ slugifyName(name) {
642
+ return name
643
+ .toLowerCase()
644
+ .replace(/[^a-z0-9]+/g, '-')
645
+ .replace(/^-+|-+$/g, '');
646
+ }
647
+ /**
648
+ * Generate filename from task title (slugified)
649
+ */
650
+ generateFilename(title, taskId) {
651
+ // Slugify: lowercase, replace spaces/special chars with hyphens
652
+ const slug = this.slugifyName(title).substring(0, 50); // Limit length
653
+ // Ensure uniqueness with short UUID suffix if needed
654
+ const filename = `${slug}.md`;
655
+ // Check if file exists with different task_id
656
+ const existingTaskId = Array.from(this.fileMap.entries()).find(([id, file]) => file === filename && id !== taskId)?.[0];
657
+ if (existingTaskId) {
658
+ // Add short UUID to make unique
659
+ const shortId = taskId.substring(0, 8);
660
+ return `${slug}-${shortId}.md`;
661
+ }
662
+ return filename;
663
+ }
664
+ /**
665
+ * Write task to markdown file
666
+ */
667
+ async writeTaskFile(task, filePath) {
668
+ const fullPath = path.join(this.config.projectPath, this.config.tasksFolder, filePath);
669
+ // Try to read existing file to preserve document_id
670
+ let existingDocumentId;
671
+ try {
672
+ const existingContent = await fs.readFile(fullPath, 'utf-8');
673
+ const frontmatterMatch = existingContent.match(/^---\n([\s\S]*?)\n---/);
674
+ if (frontmatterMatch) {
675
+ const docIdMatch = frontmatterMatch[1].match(/document_id: ["']?([a-f0-9-]+)["']?/);
676
+ if (docIdMatch) {
677
+ existingDocumentId = docIdMatch[1];
678
+ }
679
+ }
680
+ }
681
+ catch {
682
+ // File doesn't exist yet, that's fine
683
+ }
684
+ const markdown = this.taskToMarkdown(task, existingDocumentId);
685
+ // Ensure directory exists
686
+ await fs.mkdir(path.dirname(fullPath), { recursive: true });
687
+ // Write file
688
+ await fs.writeFile(fullPath, markdown, 'utf-8');
689
+ // Update file map
690
+ this.fileMap.set(task.id, filePath);
691
+ console.error(`[ReverseSync] ✅ Created/Updated: ${filePath}`);
692
+ }
693
+ /**
694
+ * Delete task markdown file
695
+ */
696
+ async deleteTaskFile(taskId) {
697
+ const filePath = this.fileMap.get(taskId);
698
+ if (!filePath) {
699
+ console.error(`[ReverseSync] No file found for task: ${taskId}`);
700
+ return;
701
+ }
702
+ const fullPath = path.join(this.config.projectPath, this.config.tasksFolder, filePath);
703
+ try {
704
+ await fs.unlink(fullPath);
705
+ this.fileMap.delete(taskId);
706
+ console.error(`[ReverseSync] ✅ Deleted: ${filePath}`);
707
+ }
708
+ catch (error) {
709
+ console.error(`[ReverseSync] Failed to delete ${filePath}:`, error);
710
+ }
711
+ }
712
+ /**
713
+ * Check for conflicts between IDE file and Commander task
714
+ * Returns true if IDE file was modified after Commander task
715
+ */
716
+ async checkConflict(taskId, _task) {
717
+ const filePath = this.fileMap.get(taskId);
718
+ if (!filePath) {
719
+ return false; // No existing file, no conflict
720
+ }
721
+ const fullPath = path.join(this.config.projectPath, this.config.tasksFolder, filePath);
722
+ try {
723
+ // Read existing file
724
+ const content = await fs.readFile(fullPath, 'utf-8');
725
+ // Parse frontmatter to get ide_modified_at
726
+ const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
727
+ if (!frontmatterMatch) {
728
+ return false; // No frontmatter, no conflict detection possible
729
+ }
730
+ const frontmatter = frontmatterMatch[1];
731
+ const ideModifiedMatch = frontmatter.match(/ide_modified_at: ["']([^"']+)["']/);
732
+ const commanderModifiedMatch = frontmatter.match(/commander_modified_at: ["']([^"']+)["']/);
733
+ // If no ide_modified_at, file was created by ReverseSync - no IDE edits, no conflict
734
+ if (!ideModifiedMatch) {
735
+ return false;
736
+ }
737
+ if (!commanderModifiedMatch) {
738
+ return false; // Missing commander timestamp, can't compare
739
+ }
740
+ const ideModifiedAt = new Date(ideModifiedMatch[1]);
741
+ const lastKnownCommander = new Date(commanderModifiedMatch[1]);
742
+ // Conflict if IDE was modified after the last known Commander timestamp we stored
743
+ const hasConflict = ideModifiedAt > lastKnownCommander;
744
+ if (hasConflict) {
745
+ console.error(`[ReverseSync] Conflict: IDE modified at ${ideModifiedAt.toISOString()}, last synced Commander at ${lastKnownCommander.toISOString()}`);
746
+ // Log conflict (latest wins, but we record it happened)
747
+ this.emit('conflict', {
748
+ taskId,
749
+ ideModifiedAt: ideModifiedAt.toISOString(),
750
+ commanderModifiedAt: lastKnownCommander.toISOString(),
751
+ resolution: 'commander-wins', // We're overwriting with Commander version
752
+ });
753
+ }
754
+ return hasConflict;
755
+ }
756
+ catch (error) {
757
+ console.error(`[ReverseSync] Error checking conflict for ${taskId}:`, error);
758
+ return false;
759
+ }
760
+ }
761
+ /**
762
+ * Get current status
763
+ */
764
+ getStatus() {
765
+ return {
766
+ running: this.running,
767
+ subscribedTo: this.config.taskboardId,
768
+ filesTracked: this.fileMap.size,
769
+ pendingChanges: this.pendingChanges.size,
770
+ };
771
+ }
772
+ }
773
+ //# sourceMappingURL=reverse-sync.js.map