zyflow 0.6.4

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 (705) hide show
  1. package/.claude-flow/metrics/agent-metrics.json +1 -0
  2. package/.claude-flow/metrics/performance.json +87 -0
  3. package/.claude-flow/metrics/system-metrics.json +4370 -0
  4. package/.claude-flow/metrics/task-metrics.json +10 -0
  5. package/.claude-plugin/marketplace.json +18 -0
  6. package/.claude-plugin/plugin.json +17 -0
  7. package/.gitleaks.toml +69 -0
  8. package/.hive-mind/config/queens.json +59 -0
  9. package/.hive-mind/config/workers.json +72 -0
  10. package/.hive-mind/config.json +111 -0
  11. package/.hive-mind/hive.db +0 -0
  12. package/.hive-mind/hive.db-shm +0 -0
  13. package/.hive-mind/hive.db-wal +0 -0
  14. package/.leann/indexes/zyflow/documents.ids.txt +2078 -0
  15. package/.leann/indexes/zyflow/documents.index +0 -0
  16. package/.leann/indexes/zyflow/documents.leann.meta.json +25 -0
  17. package/.leann/indexes/zyflow/documents.leann.passages.idx +0 -0
  18. package/.leann/indexes/zyflow/documents.leann.passages.jsonl +2078 -0
  19. package/.mcp.json +41 -0
  20. package/.moai-backups/20260126_231508/.mcp.json +11 -0
  21. package/.moai-backups/20260126_231508/backup_metadata.json +34 -0
  22. package/.moai-backups/20260129_145438/.mcp.json +41 -0
  23. package/.moai-backups/20260129_145438/backup_metadata.json +53 -0
  24. package/.moai-backups/20260129_145504/.mcp.json +41 -0
  25. package/.moai-backups/20260129_145504/backup_metadata.json +20 -0
  26. package/.moai-backups/20260201_140004/.mcp.json +41 -0
  27. package/.moai-backups/20260201_140004/backup_metadata.json +51 -0
  28. package/.moai-backups/backup/.mcp.json +12 -0
  29. package/.moai-backups/settings-backup/settings.local.json +61 -0
  30. package/.pre-commit-config.yaml +74 -0
  31. package/.prettierignore +3 -0
  32. package/.prettierrc +7 -0
  33. package/.scannerwork/.sonar_lock +0 -0
  34. package/.scannerwork/report-task.txt +6 -0
  35. package/.serena/project.yml +105 -0
  36. package/.shadcn-admin-ref/.env.example +1 -0
  37. package/.shadcn-admin-ref/.prettierignore +18 -0
  38. package/.shadcn-admin-ref/.prettierrc +50 -0
  39. package/.shadcn-admin-ref/LICENSE +21 -0
  40. package/.shadcn-admin-ref/components.json +21 -0
  41. package/.shadcn-admin-ref/cz.yaml +7 -0
  42. package/.shadcn-admin-ref/eslint.config.js +59 -0
  43. package/.shadcn-admin-ref/index.html +80 -0
  44. package/.shadcn-admin-ref/knip.config.ts +8 -0
  45. package/.shadcn-admin-ref/netlify.toml +4 -0
  46. package/.shadcn-admin-ref/package.json +83 -0
  47. package/.shadcn-admin-ref/public/images/favicon.png +0 -0
  48. package/.shadcn-admin-ref/public/images/favicon.svg +4 -0
  49. package/.shadcn-admin-ref/public/images/favicon_light.png +0 -0
  50. package/.shadcn-admin-ref/public/images/favicon_light.svg +1 -0
  51. package/.shadcn-admin-ref/public/images/shadcn-admin.png +0 -0
  52. package/.shadcn-admin-ref/src/assets/brand-icons/icon-discord.tsx +28 -0
  53. package/.shadcn-admin-ref/src/assets/brand-icons/icon-docker.tsx +33 -0
  54. package/.shadcn-admin-ref/src/assets/brand-icons/icon-facebook.tsx +25 -0
  55. package/.shadcn-admin-ref/src/assets/brand-icons/icon-figma.tsx +27 -0
  56. package/.shadcn-admin-ref/src/assets/brand-icons/icon-github.tsx +25 -0
  57. package/.shadcn-admin-ref/src/assets/brand-icons/icon-gitlab.tsx +25 -0
  58. package/.shadcn-admin-ref/src/assets/brand-icons/icon-gmail.tsx +28 -0
  59. package/.shadcn-admin-ref/src/assets/brand-icons/icon-medium.tsx +30 -0
  60. package/.shadcn-admin-ref/src/assets/brand-icons/icon-notion.tsx +28 -0
  61. package/.shadcn-admin-ref/src/assets/brand-icons/icon-skype.tsx +26 -0
  62. package/.shadcn-admin-ref/src/assets/brand-icons/icon-slack.tsx +28 -0
  63. package/.shadcn-admin-ref/src/assets/brand-icons/icon-stripe.tsx +25 -0
  64. package/.shadcn-admin-ref/src/assets/brand-icons/icon-telegram.tsx +25 -0
  65. package/.shadcn-admin-ref/src/assets/brand-icons/icon-trello.tsx +27 -0
  66. package/.shadcn-admin-ref/src/assets/brand-icons/icon-whatsapp.tsx +26 -0
  67. package/.shadcn-admin-ref/src/assets/brand-icons/icon-zoom.tsx +26 -0
  68. package/.shadcn-admin-ref/src/assets/brand-icons/index.ts +16 -0
  69. package/.shadcn-admin-ref/src/assets/clerk-full-logo.tsx +41 -0
  70. package/.shadcn-admin-ref/src/assets/clerk-logo.tsx +23 -0
  71. package/.shadcn-admin-ref/src/assets/custom/icon-dir.tsx +110 -0
  72. package/.shadcn-admin-ref/src/assets/custom/icon-layout-compact.tsx +131 -0
  73. package/.shadcn-admin-ref/src/assets/custom/icon-layout-default.tsx +124 -0
  74. package/.shadcn-admin-ref/src/assets/custom/icon-layout-full.tsx +100 -0
  75. package/.shadcn-admin-ref/src/assets/custom/icon-sidebar-floating.tsx +82 -0
  76. package/.shadcn-admin-ref/src/assets/custom/icon-sidebar-inset.tsx +58 -0
  77. package/.shadcn-admin-ref/src/assets/custom/icon-sidebar-sidebar.tsx +53 -0
  78. package/.shadcn-admin-ref/src/assets/custom/icon-theme-dark.tsx +79 -0
  79. package/.shadcn-admin-ref/src/assets/custom/icon-theme-light.tsx +78 -0
  80. package/.shadcn-admin-ref/src/assets/custom/icon-theme-system.tsx +116 -0
  81. package/.shadcn-admin-ref/src/assets/logo.tsx +24 -0
  82. package/.shadcn-admin-ref/src/components/coming-soon.tsx +16 -0
  83. package/.shadcn-admin-ref/src/components/command-menu.tsx +91 -0
  84. package/.shadcn-admin-ref/src/components/config-drawer.tsx +354 -0
  85. package/.shadcn-admin-ref/src/components/confirm-dialog.tsx +67 -0
  86. package/.shadcn-admin-ref/src/components/data-table/bulk-actions.tsx +213 -0
  87. package/.shadcn-admin-ref/src/components/data-table/column-header.tsx +74 -0
  88. package/.shadcn-admin-ref/src/components/data-table/faceted-filter.tsx +146 -0
  89. package/.shadcn-admin-ref/src/components/data-table/index.ts +6 -0
  90. package/.shadcn-admin-ref/src/components/data-table/pagination.tsx +130 -0
  91. package/.shadcn-admin-ref/src/components/data-table/toolbar.tsx +85 -0
  92. package/.shadcn-admin-ref/src/components/data-table/view-options.tsx +56 -0
  93. package/.shadcn-admin-ref/src/components/date-picker.tsx +51 -0
  94. package/.shadcn-admin-ref/src/components/layout/app-sidebar.tsx +37 -0
  95. package/.shadcn-admin-ref/src/components/layout/app-title.tsx +64 -0
  96. package/.shadcn-admin-ref/src/components/layout/authenticated-layout.tsx +42 -0
  97. package/.shadcn-admin-ref/src/components/layout/data/sidebar-data.ts +205 -0
  98. package/.shadcn-admin-ref/src/components/layout/header.tsx +50 -0
  99. package/.shadcn-admin-ref/src/components/layout/main.tsx +27 -0
  100. package/.shadcn-admin-ref/src/components/layout/nav-group.tsx +185 -0
  101. package/.shadcn-admin-ref/src/components/layout/nav-user.tsx +124 -0
  102. package/.shadcn-admin-ref/src/components/layout/team-switcher.tsx +86 -0
  103. package/.shadcn-admin-ref/src/components/layout/top-nav.tsx +67 -0
  104. package/.shadcn-admin-ref/src/components/layout/types.ts +44 -0
  105. package/.shadcn-admin-ref/src/components/learn-more.tsx +44 -0
  106. package/.shadcn-admin-ref/src/components/long-text.tsx +84 -0
  107. package/.shadcn-admin-ref/src/components/navigation-progress.tsx +25 -0
  108. package/.shadcn-admin-ref/src/components/password-input.tsx +42 -0
  109. package/.shadcn-admin-ref/src/components/profile-dropdown.tsx +75 -0
  110. package/.shadcn-admin-ref/src/components/search.tsx +37 -0
  111. package/.shadcn-admin-ref/src/components/select-dropdown.tsx +62 -0
  112. package/.shadcn-admin-ref/src/components/sign-out-dialog.tsx +38 -0
  113. package/.shadcn-admin-ref/src/components/skip-to-main.tsx +10 -0
  114. package/.shadcn-admin-ref/src/components/theme-switch.tsx +58 -0
  115. package/.shadcn-admin-ref/src/components/ui/alert-dialog.tsx +154 -0
  116. package/.shadcn-admin-ref/src/components/ui/alert.tsx +65 -0
  117. package/.shadcn-admin-ref/src/components/ui/avatar.tsx +50 -0
  118. package/.shadcn-admin-ref/src/components/ui/badge.tsx +45 -0
  119. package/.shadcn-admin-ref/src/components/ui/button.tsx +58 -0
  120. package/.shadcn-admin-ref/src/components/ui/calendar.tsx +210 -0
  121. package/.shadcn-admin-ref/src/components/ui/card.tsx +91 -0
  122. package/.shadcn-admin-ref/src/components/ui/checkbox.tsx +29 -0
  123. package/.shadcn-admin-ref/src/components/ui/collapsible.tsx +31 -0
  124. package/.shadcn-admin-ref/src/components/ui/command.tsx +181 -0
  125. package/.shadcn-admin-ref/src/components/ui/dialog.tsx +142 -0
  126. package/.shadcn-admin-ref/src/components/ui/dropdown-menu.tsx +254 -0
  127. package/.shadcn-admin-ref/src/components/ui/form.tsx +164 -0
  128. package/.shadcn-admin-ref/src/components/ui/input-otp.tsx +74 -0
  129. package/.shadcn-admin-ref/src/components/ui/input.tsx +20 -0
  130. package/.shadcn-admin-ref/src/components/ui/label.tsx +23 -0
  131. package/.shadcn-admin-ref/src/components/ui/popover.tsx +45 -0
  132. package/.shadcn-admin-ref/src/components/ui/radio-group.tsx +42 -0
  133. package/.shadcn-admin-ref/src/components/ui/scroll-area.tsx +65 -0
  134. package/.shadcn-admin-ref/src/components/ui/select.tsx +182 -0
  135. package/.shadcn-admin-ref/src/components/ui/separator.tsx +25 -0
  136. package/.shadcn-admin-ref/src/components/ui/sheet.tsx +136 -0
  137. package/.shadcn-admin-ref/src/components/ui/sidebar.tsx +728 -0
  138. package/.shadcn-admin-ref/src/components/ui/skeleton.tsx +13 -0
  139. package/.shadcn-admin-ref/src/components/ui/sonner.tsx +21 -0
  140. package/.shadcn-admin-ref/src/components/ui/switch.tsx +28 -0
  141. package/.shadcn-admin-ref/src/components/ui/table.tsx +113 -0
  142. package/.shadcn-admin-ref/src/components/ui/tabs.tsx +63 -0
  143. package/.shadcn-admin-ref/src/components/ui/textarea.tsx +17 -0
  144. package/.shadcn-admin-ref/src/components/ui/tooltip.tsx +60 -0
  145. package/.shadcn-admin-ref/src/config/fonts.ts +19 -0
  146. package/.shadcn-admin-ref/src/context/direction-provider.tsx +61 -0
  147. package/.shadcn-admin-ref/src/context/font-provider.tsx +58 -0
  148. package/.shadcn-admin-ref/src/context/layout-provider.tsx +85 -0
  149. package/.shadcn-admin-ref/src/context/search-provider.tsx +46 -0
  150. package/.shadcn-admin-ref/src/context/theme-provider.tsx +110 -0
  151. package/.shadcn-admin-ref/src/features/apps/data/apps.tsx +110 -0
  152. package/.shadcn-admin-ref/src/features/apps/index.tsx +179 -0
  153. package/.shadcn-admin-ref/src/features/auth/auth-layout.tsx +19 -0
  154. package/.shadcn-admin-ref/src/features/auth/forgot-password/components/forgot-password-form.tsx +82 -0
  155. package/.shadcn-admin-ref/src/features/auth/forgot-password/index.tsx +44 -0
  156. package/.shadcn-admin-ref/src/features/auth/otp/components/otp-form.tsx +100 -0
  157. package/.shadcn-admin-ref/src/features/auth/otp/index.tsx +44 -0
  158. package/.shadcn-admin-ref/src/features/auth/sign-in/assets/dashboard-dark.png +0 -0
  159. package/.shadcn-admin-ref/src/features/auth/sign-in/assets/dashboard-light.png +0 -0
  160. package/.shadcn-admin-ref/src/features/auth/sign-in/components/user-auth-form.tsx +150 -0
  161. package/.shadcn-admin-ref/src/features/auth/sign-in/index.tsx +51 -0
  162. package/.shadcn-admin-ref/src/features/auth/sign-in/sign-in-2.tsx +69 -0
  163. package/.shadcn-admin-ref/src/features/auth/sign-up/components/sign-up-form.tsx +143 -0
  164. package/.shadcn-admin-ref/src/features/auth/sign-up/index.tsx +57 -0
  165. package/.shadcn-admin-ref/src/features/chats/components/new-chat.tsx +127 -0
  166. package/.shadcn-admin-ref/src/features/chats/data/chat-types.ts +4 -0
  167. package/.shadcn-admin-ref/src/features/chats/data/convo.json +309 -0
  168. package/.shadcn-admin-ref/src/features/chats/index.tsx +349 -0
  169. package/.shadcn-admin-ref/src/features/dashboard/components/analytics-chart.tsx +77 -0
  170. package/.shadcn-admin-ref/src/features/dashboard/components/analytics.tsx +189 -0
  171. package/.shadcn-admin-ref/src/features/dashboard/components/overview.tsx +82 -0
  172. package/.shadcn-admin-ref/src/features/dashboard/components/recent-sales.tsx +83 -0
  173. package/.shadcn-admin-ref/src/features/dashboard/index.tsx +220 -0
  174. package/.shadcn-admin-ref/src/features/errors/forbidden.tsx +25 -0
  175. package/.shadcn-admin-ref/src/features/errors/general-error.tsx +36 -0
  176. package/.shadcn-admin-ref/src/features/errors/maintenance-error.tsx +19 -0
  177. package/.shadcn-admin-ref/src/features/errors/not-found-error.tsx +25 -0
  178. package/.shadcn-admin-ref/src/features/errors/unauthorized-error.tsx +25 -0
  179. package/.shadcn-admin-ref/src/features/settings/account/account-form.tsx +173 -0
  180. package/.shadcn-admin-ref/src/features/settings/account/index.tsx +14 -0
  181. package/.shadcn-admin-ref/src/features/settings/appearance/appearance-form.tsx +162 -0
  182. package/.shadcn-admin-ref/src/features/settings/appearance/index.tsx +14 -0
  183. package/.shadcn-admin-ref/src/features/settings/components/content-section.tsx +22 -0
  184. package/.shadcn-admin-ref/src/features/settings/components/sidebar-nav.tsx +84 -0
  185. package/.shadcn-admin-ref/src/features/settings/display/display-form.tsx +121 -0
  186. package/.shadcn-admin-ref/src/features/settings/display/index.tsx +13 -0
  187. package/.shadcn-admin-ref/src/features/settings/index.tsx +74 -0
  188. package/.shadcn-admin-ref/src/features/settings/notifications/index.tsx +13 -0
  189. package/.shadcn-admin-ref/src/features/settings/notifications/notifications-form.tsx +220 -0
  190. package/.shadcn-admin-ref/src/features/settings/profile/index.tsx +13 -0
  191. package/.shadcn-admin-ref/src/features/settings/profile/profile-form.tsx +177 -0
  192. package/.shadcn-admin-ref/src/features/tasks/components/data-table-bulk-actions.tsx +193 -0
  193. package/.shadcn-admin-ref/src/features/tasks/components/data-table-row-actions.tsx +83 -0
  194. package/.shadcn-admin-ref/src/features/tasks/components/tasks-columns.tsx +123 -0
  195. package/.shadcn-admin-ref/src/features/tasks/components/tasks-dialogs.tsx +72 -0
  196. package/.shadcn-admin-ref/src/features/tasks/components/tasks-import-dialog.tsx +110 -0
  197. package/.shadcn-admin-ref/src/features/tasks/components/tasks-multi-delete-dialog.tsx +95 -0
  198. package/.shadcn-admin-ref/src/features/tasks/components/tasks-mutate-drawer.tsx +212 -0
  199. package/.shadcn-admin-ref/src/features/tasks/components/tasks-primary-buttons.tsx +21 -0
  200. package/.shadcn-admin-ref/src/features/tasks/components/tasks-provider.tsx +36 -0
  201. package/.shadcn-admin-ref/src/features/tasks/components/tasks-table.tsx +197 -0
  202. package/.shadcn-admin-ref/src/features/tasks/data/data.tsx +77 -0
  203. package/.shadcn-admin-ref/src/features/tasks/data/schema.ts +13 -0
  204. package/.shadcn-admin-ref/src/features/tasks/data/tasks.ts +29 -0
  205. package/.shadcn-admin-ref/src/features/tasks/index.tsx +41 -0
  206. package/.shadcn-admin-ref/src/features/users/components/data-table-bulk-actions.tsx +139 -0
  207. package/.shadcn-admin-ref/src/features/users/components/data-table-row-actions.tsx +63 -0
  208. package/.shadcn-admin-ref/src/features/users/components/users-action-dialog.tsx +326 -0
  209. package/.shadcn-admin-ref/src/features/users/components/users-columns.tsx +138 -0
  210. package/.shadcn-admin-ref/src/features/users/components/users-delete-dialog.tsx +81 -0
  211. package/.shadcn-admin-ref/src/features/users/components/users-dialogs.tsx +51 -0
  212. package/.shadcn-admin-ref/src/features/users/components/users-invite-dialog.tsx +150 -0
  213. package/.shadcn-admin-ref/src/features/users/components/users-multi-delete-dialog.tsx +95 -0
  214. package/.shadcn-admin-ref/src/features/users/components/users-primary-buttons.tsx +21 -0
  215. package/.shadcn-admin-ref/src/features/users/components/users-provider.tsx +36 -0
  216. package/.shadcn-admin-ref/src/features/users/components/users-table.tsx +194 -0
  217. package/.shadcn-admin-ref/src/features/users/data/data.ts +35 -0
  218. package/.shadcn-admin-ref/src/features/users/data/schema.ts +32 -0
  219. package/.shadcn-admin-ref/src/features/users/data/users.ts +33 -0
  220. package/.shadcn-admin-ref/src/features/users/index.tsx +47 -0
  221. package/.shadcn-admin-ref/src/hooks/use-dialog-state.tsx +18 -0
  222. package/.shadcn-admin-ref/src/hooks/use-mobile.tsx +19 -0
  223. package/.shadcn-admin-ref/src/hooks/use-table-url-state.ts +219 -0
  224. package/.shadcn-admin-ref/src/lib/cookies.ts +43 -0
  225. package/.shadcn-admin-ref/src/lib/handle-server-error.ts +24 -0
  226. package/.shadcn-admin-ref/src/lib/show-submitted-data.tsx +15 -0
  227. package/.shadcn-admin-ref/src/lib/utils.ts +60 -0
  228. package/.shadcn-admin-ref/src/main.tsx +107 -0
  229. package/.shadcn-admin-ref/src/routeTree.gen.ts +719 -0
  230. package/.shadcn-admin-ref/src/routes/(auth)/forgot-password.tsx +6 -0
  231. package/.shadcn-admin-ref/src/routes/(auth)/otp.tsx +6 -0
  232. package/.shadcn-admin-ref/src/routes/(auth)/sign-in-2.tsx +6 -0
  233. package/.shadcn-admin-ref/src/routes/(auth)/sign-in.tsx +12 -0
  234. package/.shadcn-admin-ref/src/routes/(auth)/sign-up.tsx +6 -0
  235. package/.shadcn-admin-ref/src/routes/(errors)/401.tsx +6 -0
  236. package/.shadcn-admin-ref/src/routes/(errors)/403.tsx +6 -0
  237. package/.shadcn-admin-ref/src/routes/(errors)/404.tsx +6 -0
  238. package/.shadcn-admin-ref/src/routes/(errors)/500.tsx +6 -0
  239. package/.shadcn-admin-ref/src/routes/(errors)/503.tsx +6 -0
  240. package/.shadcn-admin-ref/src/routes/__root.tsx +30 -0
  241. package/.shadcn-admin-ref/src/routes/_authenticated/apps/index.tsx +17 -0
  242. package/.shadcn-admin-ref/src/routes/_authenticated/chats/index.tsx +6 -0
  243. package/.shadcn-admin-ref/src/routes/_authenticated/errors/$error.tsx +45 -0
  244. package/.shadcn-admin-ref/src/routes/_authenticated/help-center/index.tsx +6 -0
  245. package/.shadcn-admin-ref/src/routes/_authenticated/index.tsx +6 -0
  246. package/.shadcn-admin-ref/src/routes/_authenticated/route.tsx +6 -0
  247. package/.shadcn-admin-ref/src/routes/_authenticated/settings/account.tsx +6 -0
  248. package/.shadcn-admin-ref/src/routes/_authenticated/settings/appearance.tsx +6 -0
  249. package/.shadcn-admin-ref/src/routes/_authenticated/settings/display.tsx +6 -0
  250. package/.shadcn-admin-ref/src/routes/_authenticated/settings/index.tsx +6 -0
  251. package/.shadcn-admin-ref/src/routes/_authenticated/settings/notifications.tsx +6 -0
  252. package/.shadcn-admin-ref/src/routes/_authenticated/settings/route.tsx +6 -0
  253. package/.shadcn-admin-ref/src/routes/_authenticated/tasks/index.tsx +23 -0
  254. package/.shadcn-admin-ref/src/routes/_authenticated/users/index.tsx +32 -0
  255. package/.shadcn-admin-ref/src/routes/clerk/(auth)/route.tsx +60 -0
  256. package/.shadcn-admin-ref/src/routes/clerk/(auth)/sign-in.tsx +14 -0
  257. package/.shadcn-admin-ref/src/routes/clerk/(auth)/sign-up.tsx +9 -0
  258. package/.shadcn-admin-ref/src/routes/clerk/_authenticated/route.tsx +6 -0
  259. package/.shadcn-admin-ref/src/routes/clerk/_authenticated/user-management.tsx +184 -0
  260. package/.shadcn-admin-ref/src/routes/clerk/route.tsx +135 -0
  261. package/.shadcn-admin-ref/src/stores/auth-store.ts +53 -0
  262. package/.shadcn-admin-ref/src/styles/index.css +87 -0
  263. package/.shadcn-admin-ref/src/styles/theme.css +102 -0
  264. package/.shadcn-admin-ref/src/tanstack-table.d.ts +10 -0
  265. package/.shadcn-admin-ref/src/vite-env.d.ts +1 -0
  266. package/.swarm/memory.db +0 -0
  267. package/.swarm/memory.db-shm +0 -0
  268. package/.swarm/memory.db-wal +0 -0
  269. package/.zyflow/cli-settings.json +30 -0
  270. package/.zyflow/db.sqlite +0 -0
  271. package/.zyflow/logs/add-gitdiagram-integration/1633-1765491505852.json +10 -0
  272. package/.zyflow/logs/add-gitdiagram-integration/1633-1765491622627.json +10 -0
  273. package/.zyflow/logs/add-gitdiagram-integration/1633-1765491794652.json +10 -0
  274. package/.zyflow/logs/add-gitdiagram-integration/1633-1765491890392.json +10 -0
  275. package/.zyflow/logs/add-gitdiagram-integration/1633-1765494002879.json +10 -0
  276. package/.zyflow/logs/add-gitdiagram-integration/1633-1765494183887.json +10 -0
  277. package/.zyflow/logs/add-gitdiagram-integration/1633-1765494342052.json +10 -0
  278. package/.zyflow/logs/add-gitdiagram-integration/1633-1765494387244.json +10 -0
  279. package/.zyflow/logs/add-gitdiagram-integration/1633-1765494387245.json +10 -0
  280. package/.zyflow/logs/add-gitdiagram-integration/1633-1765494606176.json +10 -0
  281. package/.zyflow/logs/add-gitdiagram-integration/1633-1765495967542.json +16 -0
  282. package/.zyflow/logs/add-gitdiagram-integration/1633-1765495967629.json +16 -0
  283. package/.zyflow/logs/add-gitdiagram-integration/1633-1765497861143.json +16 -0
  284. package/.zyflow/logs/add-gitdiagram-integration/1633-1765497861870.json +20 -0
  285. package/.zyflow/logs/add-gitdiagram-integration/1633-1765498021377.json +18 -0
  286. package/.zyflow/logs/add-gitdiagram-integration/1633-1765498021660.json +18 -0
  287. package/.zyflow/logs/add-gitdiagram-integration/1633-1765503255525.json +13 -0
  288. package/.zyflow/logs/add-gitdiagram-integration/1633-1765503256018.json +13 -0
  289. package/.zyflow/logs/add-gitdiagram-integration/1633-1765504009102.json +16 -0
  290. package/.zyflow/logs/add-gitdiagram-integration/1633-1765504492051.json +18 -0
  291. package/.zyflow/logs/add-gitdiagram-integration/1633-1765504946437.json +16 -0
  292. package/.zyflow/logs/add-gitdiagram-integration/1633-1765504946640.json +16 -0
  293. package/.zyflow/logs/add-gitdiagram-integration/1634-1765505950215.json +16 -0
  294. package/.zyflow/logs/add-gitdiagram-integration/1634-1765505950948.json +18 -0
  295. package/.zyflow/logs/add-gitdiagram-integration/1635-1765505971712.json +18 -0
  296. package/.zyflow/logs/add-gitdiagram-integration/1635-1765505971976.json +18 -0
  297. package/.zyflow/logs/add-gitdiagram-integration/1636-1765505986208.json +18 -0
  298. package/.zyflow/logs/add-gitdiagram-integration/1636-1765505986620.json +16 -0
  299. package/.zyflow/logs/integrate-claude-flow/3580-1765996816612.json +10 -0
  300. package/.zyflow/logs/integrate-claude-flow/3580-1766014825819.json +10 -0
  301. package/.zyflow/logs/integrate-claude-flow/3580-1766015183794.json +12 -0
  302. package/.zyflow/logs/integrate-claude-flow/3580-1766015474608.json +12 -0
  303. package/.zyflow/logs/integrate-claude-flow/3581-1766016502824.json +63 -0
  304. package/.zyflow/logs/integrate-claude-flow/3581-1766016576008.json +60 -0
  305. package/.zyflow/logs/integrate-claude-flow/3582-1766022737754.json +110 -0
  306. package/.zyflow/logs/integrate-claude-flow/3582-1766022809327.json +135 -0
  307. package/.zyflow/sessions.json +242 -0
  308. package/.zyflow/settings.json +6 -0
  309. package/.zyflow/tasks.db +0 -0
  310. package/.zyflow/tasks.db-shm +0 -0
  311. package/.zyflow/tasks.db-wal +0 -0
  312. package/.zyflow/zyflow.sqlite +0 -0
  313. package/Dockerfile +82 -0
  314. package/LICENSE +21 -0
  315. package/README.md +506 -0
  316. package/claude-flow +34 -0
  317. package/components.json +21 -0
  318. package/config/ports.ts +28 -0
  319. package/docker-compose.yml +52 -0
  320. package/eslint.config.js +34 -0
  321. package/index.html +19 -0
  322. package/logs/mcp-error.log +55 -0
  323. package/logs/mcp-out.log +0 -0
  324. package/logs/pm2-error.log +0 -0
  325. package/logs/pm2-out.log +265 -0
  326. package/logs/py-error.log +22 -0
  327. package/logs/py-out.log +0 -0
  328. package/logs/server-error.log +11000 -0
  329. package/logs/server-out.log +8117 -0
  330. package/logs/vite-error.log +404 -0
  331. package/logs/vite-out.log +311 -0
  332. package/mcp-server/agent-tools.ts +375 -0
  333. package/mcp-server/cli-models.ts +193 -0
  334. package/mcp-server/context.ts +110 -0
  335. package/mcp-server/diagram-tools.ts +341 -0
  336. package/mcp-server/index.ts +2014 -0
  337. package/mcp-server/integration-tools.ts +909 -0
  338. package/mcp-server/moai-spec-tools.ts +416 -0
  339. package/mcp-server/parser.ts +422 -0
  340. package/mcp-server/post-task-runner.ts +253 -0
  341. package/mcp-server/post-task-types.ts +426 -0
  342. package/mcp-server/quarantine-manager.ts +479 -0
  343. package/mcp-server/report-generator.ts +386 -0
  344. package/mcp-server/task-tools.ts +619 -0
  345. package/mcp-server/trigger-config.ts +288 -0
  346. package/mcp-server/trigger-router.ts +305 -0
  347. package/mcp-server/triggers/event-listener.ts +331 -0
  348. package/mcp-server/triggers/git-hooks.ts +283 -0
  349. package/mcp-server/triggers/scheduler.ts +289 -0
  350. package/mcp-server/types.ts +55 -0
  351. package/memory/claude-flow@alpha-data.json +5 -0
  352. package/nginx/zyflow.conf +144 -0
  353. package/openspec/config.yaml +78 -0
  354. package/openspec-backup.tar.gz +0 -0
  355. package/package.json +154 -0
  356. package/packages/gitdiagram-core/.claude-flow/metrics/agent-metrics.json +1 -0
  357. package/packages/gitdiagram-core/.claude-flow/metrics/performance.json +87 -0
  358. package/packages/gitdiagram-core/.claude-flow/metrics/task-metrics.json +10 -0
  359. package/packages/gitdiagram-core/package.json +41 -0
  360. package/packages/gitdiagram-core/src/file-tree.ts +272 -0
  361. package/packages/gitdiagram-core/src/generator.ts +283 -0
  362. package/packages/gitdiagram-core/src/index.ts +78 -0
  363. package/packages/gitdiagram-core/src/llm-adapter.ts +235 -0
  364. package/packages/gitdiagram-core/src/mermaid-utils.ts +304 -0
  365. package/packages/gitdiagram-core/src/prompts.ts +281 -0
  366. package/packages/zyflow-parser/package.json +34 -0
  367. package/packages/zyflow-parser/src/index.ts +26 -0
  368. package/packages/zyflow-parser/src/moai-parser.ts +603 -0
  369. package/packages/zyflow-parser/src/moai-types.ts +110 -0
  370. package/packages/zyflow-remote-plugin/.claude-flow/metrics/agent-metrics.json +1 -0
  371. package/packages/zyflow-remote-plugin/.claude-flow/metrics/performance.json +87 -0
  372. package/packages/zyflow-remote-plugin/.claude-flow/metrics/task-metrics.json +10 -0
  373. package/packages/zyflow-remote-plugin/package.json +31 -0
  374. package/packages/zyflow-remote-plugin/src/index.ts +71 -0
  375. package/packages/zyflow-remote-plugin/src/remote-config.ts +232 -0
  376. package/packages/zyflow-remote-plugin/src/router.ts +535 -0
  377. package/packages/zyflow-remote-plugin/src/ssh-config-parser.ts +123 -0
  378. package/packages/zyflow-remote-plugin/src/ssh-manager.ts +598 -0
  379. package/packages/zyflow-remote-plugin/src/types.ts +149 -0
  380. package/plugin/manifest.json +26 -0
  381. package/plugin/package.json +13 -0
  382. package/public/favicon.svg +4 -0
  383. package/server/adk/agents/error-analyzer.ts +223 -0
  384. package/server/adk/agents/fix-generator.ts +187 -0
  385. package/server/adk/agents/pr-agent.ts +264 -0
  386. package/server/adk/agents/validator.ts +187 -0
  387. package/server/adk/config.ts +43 -0
  388. package/server/adk/index.ts +69 -0
  389. package/server/adk/integration.ts +297 -0
  390. package/server/adk/orchestrator.ts +405 -0
  391. package/server/adk/tools/build-tools.ts +290 -0
  392. package/server/adk/tools/file-tools.ts +351 -0
  393. package/server/adk/tools/git-tools.ts +280 -0
  394. package/server/adk/tools/github-tools.ts +249 -0
  395. package/server/agents/agent-monitor.ts +416 -0
  396. package/server/agents/alert-integration.ts +312 -0
  397. package/server/agents/error-analyzer.ts +472 -0
  398. package/server/agents/error-detector.ts +442 -0
  399. package/server/agents/fix-generator.ts +421 -0
  400. package/server/agents/fix-validator.ts +428 -0
  401. package/server/agents/merge-policy.ts +362 -0
  402. package/server/agents/pr-workflow.ts +476 -0
  403. package/server/agents/prompts/error-analysis.ts +393 -0
  404. package/server/ai/gemini-client.ts +499 -0
  405. package/server/ai/index.ts +317 -0
  406. package/server/ai/types.ts +137 -0
  407. package/server/app.ts +3693 -0
  408. package/server/archive-manager.ts +604 -0
  409. package/server/backlog/index.ts +7 -0
  410. package/server/backlog/migration.ts +331 -0
  411. package/server/backlog/parser.ts +323 -0
  412. package/server/backlog/sync.ts +325 -0
  413. package/server/change-log.ts +868 -0
  414. package/server/claude-flow/index.ts +12 -0
  415. package/server/claude-flow/prompt-builder.ts +407 -0
  416. package/server/claude-flow/types.ts +33 -0
  417. package/server/cli-adapter/index.ts +11 -0
  418. package/server/cli-adapter/process-manager.ts +612 -0
  419. package/server/cli-adapter/profile-manager.ts +286 -0
  420. package/server/cli-adapter/routes.ts +561 -0
  421. package/server/cli-adapter/types.ts +226 -0
  422. package/server/config.d.ts +18 -0
  423. package/server/config.js +79 -0
  424. package/server/config.ts +262 -0
  425. package/server/flow-sync.ts +543 -0
  426. package/server/git/change-workflow.ts +446 -0
  427. package/server/git/commands.ts +370 -0
  428. package/server/git/github.ts +247 -0
  429. package/server/git/index.ts +1202 -0
  430. package/server/git/status.ts +322 -0
  431. package/server/index.ts +136 -0
  432. package/server/integrations/crypto.ts +142 -0
  433. package/server/integrations/db/client.ts +169 -0
  434. package/server/integrations/db/schema.ts +167 -0
  435. package/server/integrations/env-parser.ts +365 -0
  436. package/server/integrations/index.ts +101 -0
  437. package/server/integrations/keychain.ts +239 -0
  438. package/server/integrations/local/file-utils.ts +383 -0
  439. package/server/integrations/local/index.ts +64 -0
  440. package/server/integrations/local/resolver.ts +439 -0
  441. package/server/integrations/local/types.ts +122 -0
  442. package/server/integrations/routes.ts +1100 -0
  443. package/server/integrations/service-patterns.ts +771 -0
  444. package/server/integrations/services/accounts.ts +356 -0
  445. package/server/integrations/services/env-import.ts +279 -0
  446. package/server/integrations/services/projects.ts +552 -0
  447. package/server/integrations/services/system-import.ts +1110 -0
  448. package/server/migrations/ears-generator.ts +491 -0
  449. package/server/migrations/gherkin-generator.ts +605 -0
  450. package/server/migrations/index.ts +73 -0
  451. package/server/migrations/migrate-spec-format.ts +492 -0
  452. package/server/migrations/openspec-parser.ts +542 -0
  453. package/server/migrations/tag-generator.ts +474 -0
  454. package/server/moai-specs.ts +487 -0
  455. package/server/moai-watcher.ts +145 -0
  456. package/server/parser-debug.ts +37 -0
  457. package/server/parser-utils.ts +316 -0
  458. package/server/parser.d.ts +17 -0
  459. package/server/parser.js +221 -0
  460. package/server/parser.ts +342 -0
  461. package/server/remote-watcher.ts +367 -0
  462. package/server/replay-engine.ts +915 -0
  463. package/server/routes/alerts.ts +1028 -0
  464. package/server/routes/changes.ts +812 -0
  465. package/server/routes/docs.ts +898 -0
  466. package/server/routes/flow.ts +2814 -0
  467. package/server/routes/global-chat.ts +162 -0
  468. package/server/routes/leann.ts +327 -0
  469. package/server/routes/projects.ts +1282 -0
  470. package/server/routes/search.ts +266 -0
  471. package/server/routes/specs.ts +482 -0
  472. package/server/routes/webhooks.ts +579 -0
  473. package/server/server/parser.js +265 -0
  474. package/server/services/githubActionsPoller.ts +797 -0
  475. package/server/services/slackNotifier.ts +476 -0
  476. package/server/src/types/index.js +1 -0
  477. package/server/sync-tasks.ts +741 -0
  478. package/server/tasks/cli/commands.ts +269 -0
  479. package/server/tasks/cli/index.ts +152 -0
  480. package/server/tasks/core/search.ts +81 -0
  481. package/server/tasks/core/task.ts +307 -0
  482. package/server/tasks/db/client.ts +1008 -0
  483. package/server/tasks/db/schema.ts +572 -0
  484. package/server/tasks/index.ts +24 -0
  485. package/server/tasks.db +0 -0
  486. package/server/types/archive.ts +136 -0
  487. package/server/types/change-log.ts +643 -0
  488. package/server/types/spec.ts +188 -0
  489. package/server/unified-spec-scanner.ts +753 -0
  490. package/server/utils/crypto.ts +179 -0
  491. package/server/utils/webhook-verify.ts +216 -0
  492. package/server/watcher.ts +132 -0
  493. package/server/websocket.ts +99 -0
  494. package/server-output.log +6 -0
  495. package/sonar-project.properties +18 -0
  496. package/src/App.tsx +386 -0
  497. package/src/api/client.ts +346 -0
  498. package/src/api/error-interceptor.ts +366 -0
  499. package/src/api/errors.ts +123 -0
  500. package/src/api/flow.ts +233 -0
  501. package/src/api/offline-queue.ts +351 -0
  502. package/src/api/retry-logic.ts +233 -0
  503. package/src/components/OfflineModeBanner.tsx +159 -0
  504. package/src/components/SSEStatusIndicator.tsx +194 -0
  505. package/src/components/agent/AgentChat.tsx +243 -0
  506. package/src/components/agent/AgentPage.tsx +182 -0
  507. package/src/components/agent/AgentSidebar.tsx +231 -0
  508. package/src/components/agent/index.ts +7 -0
  509. package/src/components/alerts/AlertCenter.tsx +239 -0
  510. package/src/components/alerts/AlertDashboard.tsx +211 -0
  511. package/src/components/alerts/AlertDetail.tsx +474 -0
  512. package/src/components/alerts/AlertList.tsx +113 -0
  513. package/src/components/alerts/AlertSettings.tsx +336 -0
  514. package/src/components/alerts/index.ts +5 -0
  515. package/src/components/chat/ChatPanel.tsx +642 -0
  516. package/src/components/chat/index.ts +1 -0
  517. package/src/components/cli/AddCustomCLIDialog.tsx +210 -0
  518. package/src/components/cli/CLISelector.tsx +187 -0
  519. package/src/components/cli/index.ts +8 -0
  520. package/src/components/dashboard/ArchivedChangeList.tsx +102 -0
  521. package/src/components/dashboard/ArchivedChangeViewer.tsx +184 -0
  522. package/src/components/dashboard/ArchivedChangesPage.tsx +31 -0
  523. package/src/components/dashboard/ChangeList.tsx +86 -0
  524. package/src/components/dashboard/ThemeToggle.tsx +33 -0
  525. package/src/components/diagram/DiagramViewer.tsx +256 -0
  526. package/src/components/diagram/MermaidRenderer.tsx +163 -0
  527. package/src/components/diagram/ProjectDiagramTab.tsx +161 -0
  528. package/src/components/diagram/index.ts +13 -0
  529. package/src/components/errors/ErrorBoundary.tsx +276 -0
  530. package/src/components/errors/ErrorFallback.tsx +198 -0
  531. package/src/components/errors/ErrorToast.tsx +221 -0
  532. package/src/components/flow/BacklogView.tsx +1142 -0
  533. package/src/components/flow/ChangeDetail.tsx +475 -0
  534. package/src/components/flow/ChangeItem.tsx +230 -0
  535. package/src/components/flow/ChangeList.tsx +92 -0
  536. package/src/components/flow/ExecutionHistoryDialog.tsx +224 -0
  537. package/src/components/flow/FlowContent.tsx +212 -0
  538. package/src/components/flow/FlowPage.tsx +9 -0
  539. package/src/components/flow/PipelineBar.tsx +214 -0
  540. package/src/components/flow/ProjectDashboard.tsx +222 -0
  541. package/src/components/flow/SpecDetail.tsx +138 -0
  542. package/src/components/flow/SpecDetailTabs.tsx +176 -0
  543. package/src/components/flow/SpecItem.tsx +93 -0
  544. package/src/components/flow/SpecProgressBar.tsx +47 -0
  545. package/src/components/flow/StageContent.tsx +620 -0
  546. package/src/components/flow/StandaloneTasks.tsx +960 -0
  547. package/src/components/flow/TaskExecutionDialog.tsx +1204 -0
  548. package/src/components/flow/index.ts +9 -0
  549. package/src/components/flow/task-execution/AgentSlider.tsx +37 -0
  550. package/src/components/flow/task-execution/ConsensusSettings.tsx +129 -0
  551. package/src/components/flow/task-execution/ExecutionOutput.tsx +398 -0
  552. package/src/components/flow/task-execution/ModelSelector.tsx +134 -0
  553. package/src/components/flow/task-execution/ProviderSelector.tsx +137 -0
  554. package/src/components/flow/task-execution/RecommendationBanner.tsx +71 -0
  555. package/src/components/flow/task-execution/StatusBadge.tsx +43 -0
  556. package/src/components/flow/task-execution/StrategySelector.tsx +48 -0
  557. package/src/components/flow/task-execution/SwarmSummary.tsx +55 -0
  558. package/src/components/flow/task-execution/index.ts +14 -0
  559. package/src/components/flow/task-execution/types.ts +56 -0
  560. package/src/components/git/ChangeWorkflowDialog.tsx +582 -0
  561. package/src/components/git/ConflictResolutionDialog.tsx +398 -0
  562. package/src/components/git/GitBranchSelector.tsx +212 -0
  563. package/src/components/git/GitCommitDialog.tsx +254 -0
  564. package/src/components/git/GitStatusBadge.tsx +148 -0
  565. package/src/components/git/GitSyncButton.tsx +128 -0
  566. package/src/components/git/RemoteStatusBanner.tsx +143 -0
  567. package/src/components/git/index.ts +9 -0
  568. package/src/components/integrations/EnvImportDialog.tsx +524 -0
  569. package/src/components/integrations/EnvironmentDialog.tsx +227 -0
  570. package/src/components/integrations/IntegrationBadges.tsx +91 -0
  571. package/src/components/integrations/IntegrationsSettings.tsx +55 -0
  572. package/src/components/integrations/ProjectIntegrations.tsx +481 -0
  573. package/src/components/integrations/ServiceAccountDialog.tsx +422 -0
  574. package/src/components/integrations/ServiceAccountList.tsx +305 -0
  575. package/src/components/integrations/SystemImportDialog.tsx +436 -0
  576. package/src/components/integrations/TestAccountDialog.tsx +162 -0
  577. package/src/components/integrations/index.ts +6 -0
  578. package/src/components/layout/AppSidebar.tsx +284 -0
  579. package/src/components/layout/FlowSidebar.tsx +435 -0
  580. package/src/components/layout/GlobalCommandPalette.tsx +410 -0
  581. package/src/components/layout/MenuBar.tsx +227 -0
  582. package/src/components/layout/StatusBar.tsx +226 -0
  583. package/src/components/monitoring/ErrorDashboard.tsx +274 -0
  584. package/src/components/monitoring/ErrorDetailPanel.tsx +200 -0
  585. package/src/components/monitoring/ErrorFilters.tsx +219 -0
  586. package/src/components/monitoring/ErrorHistoryList.tsx +141 -0
  587. package/src/components/monitoring/ErrorStats.tsx +249 -0
  588. package/src/components/remote/RemoteFileBrowser.tsx +249 -0
  589. package/src/components/remote/RemoteServerDialog.tsx +234 -0
  590. package/src/components/remote/RemoteServerList.tsx +366 -0
  591. package/src/components/remote/index.ts +7 -0
  592. package/src/components/settings/CLISettings.tsx +522 -0
  593. package/src/components/settings/CustomCLIDialog.tsx +548 -0
  594. package/src/components/settings/IntegrationsSettings.tsx +51 -0
  595. package/src/components/settings/ProjectSettings.tsx +441 -0
  596. package/src/components/settings/ProjectsSettings.tsx +541 -0
  597. package/src/components/settings/SearchSettings.tsx +272 -0
  598. package/src/components/settings/SettingsPage.tsx +68 -0
  599. package/src/components/settings/index.ts +5 -0
  600. package/src/components/swarm/ExecutionPanel.tsx +284 -0
  601. package/src/components/swarm/LogViewer.tsx +196 -0
  602. package/src/components/swarm/ProgressIndicator.tsx +111 -0
  603. package/src/components/swarm/index.ts +3 -0
  604. package/src/components/tasks/ArchiveTable.tsx +203 -0
  605. package/src/components/tasks/KanbanBoard.tsx +264 -0
  606. package/src/components/tasks/TaskCard.tsx +138 -0
  607. package/src/components/tasks/TaskColumn.tsx +81 -0
  608. package/src/components/tasks/TaskDialog.tsx +274 -0
  609. package/src/components/tasks/index.ts +5 -0
  610. package/src/components/tasks/types.ts +43 -0
  611. package/src/components/ui/alert-dialog.tsx +154 -0
  612. package/src/components/ui/alert.tsx +65 -0
  613. package/src/components/ui/badge.tsx +45 -0
  614. package/src/components/ui/button.tsx +58 -0
  615. package/src/components/ui/card.tsx +91 -0
  616. package/src/components/ui/checkbox.tsx +29 -0
  617. package/src/components/ui/collapsible.tsx +31 -0
  618. package/src/components/ui/command.tsx +184 -0
  619. package/src/components/ui/confirm-dialog.tsx +55 -0
  620. package/src/components/ui/dialog.tsx +142 -0
  621. package/src/components/ui/dropdown-menu.tsx +254 -0
  622. package/src/components/ui/input.tsx +20 -0
  623. package/src/components/ui/label.tsx +22 -0
  624. package/src/components/ui/markdown.tsx +100 -0
  625. package/src/components/ui/progress.tsx +27 -0
  626. package/src/components/ui/resizable-sidebar.tsx +156 -0
  627. package/src/components/ui/resizable.tsx +54 -0
  628. package/src/components/ui/right-resizable-sidebar.tsx +158 -0
  629. package/src/components/ui/scroll-area.tsx +64 -0
  630. package/src/components/ui/select.tsx +185 -0
  631. package/src/components/ui/separator.tsx +25 -0
  632. package/src/components/ui/sheet.tsx +136 -0
  633. package/src/components/ui/sidebar.tsx +726 -0
  634. package/src/components/ui/skeleton.tsx +13 -0
  635. package/src/components/ui/slider.tsx +56 -0
  636. package/src/components/ui/switch.tsx +29 -0
  637. package/src/components/ui/table.tsx +113 -0
  638. package/src/components/ui/tabs.tsx +63 -0
  639. package/src/components/ui/textarea.tsx +17 -0
  640. package/src/components/ui/tooltip.tsx +60 -0
  641. package/src/config/api.ts +83 -0
  642. package/src/constants/error-codes.ts +255 -0
  643. package/src/constants/stages.ts +27 -0
  644. package/src/context/ErrorContext.tsx +185 -0
  645. package/src/context/theme-provider.tsx +63 -0
  646. package/src/hooks/use-mobile.tsx +19 -0
  647. package/src/hooks/useAI.ts +206 -0
  648. package/src/hooks/useAgentSession.ts +431 -0
  649. package/src/hooks/useAlerts.ts +935 -0
  650. package/src/hooks/useArchivedChanges.ts +39 -0
  651. package/src/hooks/useAsyncError.ts +45 -0
  652. package/src/hooks/useChangeGit.ts +727 -0
  653. package/src/hooks/useChanges.ts +20 -0
  654. package/src/hooks/useClaude.ts +130 -0
  655. package/src/hooks/useDocs.ts +182 -0
  656. package/src/hooks/useErrorDashboard.ts +243 -0
  657. package/src/hooks/useErrorHandler.ts +150 -0
  658. package/src/hooks/useExecutionHistory.ts +55 -0
  659. package/src/hooks/useFlowChanges.ts +850 -0
  660. package/src/hooks/useFlowItems.ts +205 -0
  661. package/src/hooks/useGit.ts +427 -0
  662. package/src/hooks/useHideCompletedSpecs.ts +15 -0
  663. package/src/hooks/useInstance.ts +40 -0
  664. package/src/hooks/useIntegrations.ts +737 -0
  665. package/src/hooks/useLeannStatus.ts +93 -0
  666. package/src/hooks/useNetworkStatus.ts +167 -0
  667. package/src/hooks/useProjects.ts +353 -0
  668. package/src/hooks/useRemoteServers.ts +383 -0
  669. package/src/hooks/useSSEConnection.ts +346 -0
  670. package/src/hooks/useSpecs.ts +39 -0
  671. package/src/hooks/useSwarm.ts +462 -0
  672. package/src/hooks/useTasks.ts +137 -0
  673. package/src/hooks/useURLSync.ts +122 -0
  674. package/src/hooks/useWebSocket.ts +262 -0
  675. package/src/lib/utils.ts +121 -0
  676. package/src/main.tsx +22 -0
  677. package/src/stores/errorStore.ts +301 -0
  678. package/src/stores/offlineStore.ts +266 -0
  679. package/src/stores/sseStore.ts +247 -0
  680. package/src/stores/useHideCompletedStore.ts +21 -0
  681. package/src/styles/index.css +87 -0
  682. package/src/styles/theme.css +102 -0
  683. package/src/types/ai.ts +191 -0
  684. package/src/types/errors.ts +253 -0
  685. package/src/types/flow.ts +382 -0
  686. package/src/types/index.ts +614 -0
  687. package/src/utils/error-logger.ts +399 -0
  688. package/src/utils/error-statistics.ts +305 -0
  689. package/src/utils/logger.ts +280 -0
  690. package/src/utils/task-routing.ts +795 -0
  691. package/src/vite-env.d.ts +1 -0
  692. package/test-results/.last-run.json +4 -0
  693. package/tmp/check-docker-final.ts +48 -0
  694. package/tmp/check-docker-tasks.ts +58 -0
  695. package/tmp/check-docker-tasks2.ts +48 -0
  696. package/tmp/check-docker-tasks3.ts +42 -0
  697. package/tmp/check-mobile-tasks.ts +57 -0
  698. package/tmp/check-zywiki-tasks.ts +49 -0
  699. package/tmp/sync-mobile.ts +11 -0
  700. package/tmp/sync-zywiki.ts +68 -0
  701. package/tmp/test-docker-parser.ts +15 -0
  702. package/tmp/test-mobile-parser.ts +28 -0
  703. package/tmp/test-parser.ts +27 -0
  704. package/tmp/test-unnumbered.ts +35 -0
  705. package/zyflow.db +0 -0
@@ -0,0 +1,812 @@
1
+ /**
2
+ * Changes Router
3
+ *
4
+ * OpenSpec Changes 관련 API 라우터
5
+ */
6
+
7
+ import { Router } from 'express'
8
+ import { readdir, readFile, writeFile, access, stat } from 'fs/promises'
9
+ import { join } from 'path'
10
+ import { exec } from 'child_process'
11
+ import { promisify } from 'util'
12
+ import { getActiveProject, getProjectById } from '../config.js'
13
+ import { parseTasksFile, toggleTaskInFile } from '../parser.js'
14
+ import { initDb, getSqlite } from '../tasks/db/client.js'
15
+ // NOTE: TAG-014 - OpenSpec CLI functions removed
16
+ // Import removed: getChangeStatus, validateChange, archiveChange, getInstructions, isOpenSpecAvailable, getOpenSpecVersion
17
+ // These functions are deprecated. Use MoAI SPEC system instead.
18
+ import {
19
+ getCachedArtifactStatus,
20
+ updateArtifactStatusCache,
21
+ } from '../sync-tasks.js'
22
+ import { scanMoaiSpecs, isValidSpecId } from '../moai-specs.js'
23
+
24
+ // Remote plugin is optional - only load if installed
25
+ let remotePlugin: {
26
+ getRemoteServerById: (id: string) => Promise<unknown>
27
+ listDirectory: (server: unknown, path: string) => Promise<{ entries: Array<{ type: string; name: string; modifiedAt?: string }> }>
28
+ readRemoteFile: (server: unknown, path: string) => Promise<string>
29
+ executeCommand: (server: unknown, cmd: string, opts?: { cwd?: string }) => Promise<{ stdout: string }>
30
+ } | null = null
31
+
32
+ async function getRemotePlugin() {
33
+ if (remotePlugin) return remotePlugin
34
+ try {
35
+ const mod = await import('@zyflow/remote-plugin')
36
+ remotePlugin = mod
37
+ return remotePlugin
38
+ } catch {
39
+ return null
40
+ }
41
+ }
42
+
43
+ const execAsync = promisify(exec)
44
+
45
+ export const changesRouter = Router()
46
+
47
+ // Helper to get paths for active project
48
+ async function getProjectPaths() {
49
+ const project = await getActiveProject()
50
+ if (!project) {
51
+ return null
52
+ }
53
+ return {
54
+ projectPath: project.path,
55
+ openspecDir: join(project.path, 'openspec', 'changes'),
56
+ specsDir: join(project.path, 'openspec', 'specs'),
57
+ plansDir: join(project.path, '.zyflow', 'plans'),
58
+ // Archive directories (three possible locations)
59
+ archiveDir: join(project.path, 'openspec', 'changes', 'archive'), // openspec/changes/archive/
60
+ legacyArchiveDir: join(project.path, 'openspec', 'archive'), // openspec/archive/
61
+ archivedDir: join(project.path, 'openspec', 'archived'), // openspec/archived/
62
+ }
63
+ }
64
+
65
+ // GET / - List all changes
66
+ changesRouter.get('/', async (_req, res) => {
67
+ try {
68
+ const project = await getActiveProject()
69
+ if (!project) {
70
+ return res.json({ success: true, data: { changes: [] } })
71
+ }
72
+
73
+ // 원격 프로젝트인 경우
74
+ if (project.remote) {
75
+ const plugin = await getRemotePlugin()
76
+ if (!plugin) {
77
+ return res.json({ success: true, data: { changes: [] } })
78
+ }
79
+
80
+ const server = await plugin.getRemoteServerById(project.remote.serverId)
81
+ if (!server) {
82
+ return res.json({ success: true, data: { changes: [] } })
83
+ }
84
+
85
+ const openspecDir = `${project.path}/openspec/changes`
86
+
87
+ // 원격 디렉토리 목록 조회
88
+ let listing
89
+ try {
90
+ listing = await plugin.listDirectory(server, openspecDir)
91
+ } catch {
92
+ return res.json({ success: true, data: { changes: [] } })
93
+ }
94
+
95
+ // 디렉토리만 필터링 (archive 제외)
96
+ const validEntries = listing.entries.filter(
97
+ (entry) => entry.type === 'directory' && entry.name !== 'archive'
98
+ )
99
+
100
+ // 병렬로 각 change 처리
101
+ const changes = await Promise.all(
102
+ validEntries.map(async (entry) => {
103
+ const changeId = entry.name
104
+ const changeDir = `${openspecDir}/${changeId}`
105
+
106
+ // 원격에서 proposal.md, tasks.md 읽기 및 git log 실행
107
+ const [proposalResult, tasksResult, gitResult] = await Promise.allSettled([
108
+ plugin.readRemoteFile(server, `${changeDir}/proposal.md`),
109
+ plugin.readRemoteFile(server, `${changeDir}/tasks.md`),
110
+ plugin.executeCommand(server, `git log -1 --format="%aI" -- "openspec/changes/${changeId}"`, {
111
+ cwd: project.path,
112
+ }),
113
+ ])
114
+
115
+ // Parse proposal
116
+ let title = changeId
117
+ if (proposalResult.status === 'fulfilled') {
118
+ const titleMatch = proposalResult.value.match(/^#\s+Change:\s+(.+)$/m)
119
+ if (titleMatch) title = titleMatch[1].trim()
120
+ }
121
+
122
+ // Parse tasks
123
+ let totalTasks = 0
124
+ let completedTasks = 0
125
+ if (tasksResult.status === 'fulfilled') {
126
+ const parsed = parseTasksFile(changeId, tasksResult.value)
127
+ for (const group of parsed.groups) {
128
+ totalTasks += group.tasks.length
129
+ completedTasks += group.tasks.filter((t) => t.completed).length
130
+ }
131
+ }
132
+
133
+ const progress = totalTasks > 0 ? Math.round((completedTasks / totalTasks) * 100) : 0
134
+
135
+ // Get updatedAt from git log or file modifiedAt
136
+ let updatedAt: string | null = null
137
+ if (gitResult.status === 'fulfilled' && gitResult.value.stdout.trim()) {
138
+ updatedAt = gitResult.value.stdout.trim()
139
+ } else {
140
+ // 폴백: listDirectory에서 가져온 modifiedAt 사용
141
+ updatedAt = entry.modifiedAt || new Date().toISOString()
142
+ }
143
+
144
+ return { id: changeId, title, progress, totalTasks, completedTasks, updatedAt, type: 'openspec' as const }
145
+ })
146
+ )
147
+
148
+ // TODO: Add MoAI SPEC support for remote projects
149
+ return res.json({ success: true, data: { changes } })
150
+ }
151
+
152
+ // 로컬 프로젝트인 경우
153
+ const paths = await getProjectPaths()
154
+ if (!paths) {
155
+ return res.json({ success: true, data: { changes: [] } })
156
+ }
157
+
158
+ let entries
159
+ try {
160
+ entries = await readdir(paths.openspecDir, { withFileTypes: true })
161
+ } catch {
162
+ return res.json({ success: true, data: { changes: [] } })
163
+ }
164
+
165
+ // Filter valid entries
166
+ const validEntries = entries.filter(
167
+ (entry) => entry.isDirectory() && entry.name !== 'archive'
168
+ )
169
+
170
+ // Process all changes in parallel
171
+ const changes = await Promise.all(
172
+ validEntries.map(async (entry) => {
173
+ const changeId = entry.name
174
+ const changeDir = join(paths.openspecDir, changeId)
175
+
176
+ // Read proposal, tasks, and git log in parallel
177
+ const [proposalResult, tasksResult, gitResult] = await Promise.allSettled([
178
+ readFile(join(changeDir, 'proposal.md'), 'utf-8'),
179
+ readFile(join(changeDir, 'tasks.md'), 'utf-8'),
180
+ execAsync(`git log -1 --format="%aI" -- "openspec/changes/${changeId}"`, {
181
+ cwd: paths.projectPath,
182
+ }),
183
+ ])
184
+
185
+ // Parse proposal
186
+ let title = changeId
187
+ if (proposalResult.status === 'fulfilled') {
188
+ const titleMatch = proposalResult.value.match(/^#\s+Change:\s+(.+)$/m)
189
+ if (titleMatch) title = titleMatch[1].trim()
190
+ }
191
+
192
+ // Parse tasks
193
+ let totalTasks = 0
194
+ let completedTasks = 0
195
+ if (tasksResult.status === 'fulfilled') {
196
+ const parsed = parseTasksFile(changeId, tasksResult.value)
197
+ for (const group of parsed.groups) {
198
+ totalTasks += group.tasks.length
199
+ completedTasks += group.tasks.filter((t) => t.completed).length
200
+ }
201
+ }
202
+
203
+ const progress = totalTasks > 0 ? Math.round((completedTasks / totalTasks) * 100) : 0
204
+
205
+ // Get updatedAt
206
+ let updatedAt: string | null = null
207
+ if (gitResult.status === 'fulfilled' && gitResult.value.stdout.trim()) {
208
+ updatedAt = gitResult.value.stdout.trim()
209
+ } else {
210
+ try {
211
+ const s = await stat(join(changeDir, 'tasks.md'))
212
+ updatedAt = s.mtime.toISOString()
213
+ } catch {
214
+ try {
215
+ const s = await stat(join(changeDir, 'proposal.md'))
216
+ updatedAt = s.mtime.toISOString()
217
+ } catch {
218
+ updatedAt = new Date().toISOString()
219
+ }
220
+ }
221
+ }
222
+
223
+ return { id: changeId, title, progress, totalTasks, completedTasks, updatedAt, type: 'openspec' as const }
224
+ })
225
+ )
226
+
227
+ // Also scan for MoAI SPECs
228
+ let moaiSpecs: Array<{ id: string; title: string; progress: number; totalTasks: number; completedTasks: number; updatedAt: string; type: 'moai-spec' }> = []
229
+ try {
230
+ const moaiSpecList = await scanMoaiSpecs(paths.projectPath)
231
+ moaiSpecs = moaiSpecList.map((spec) => ({
232
+ id: spec.id,
233
+ title: spec.title,
234
+ progress: spec.tagCount > 0 ? Math.round((spec.completedTags / spec.tagCount) * 100) : 0,
235
+ totalTasks: spec.tagCount,
236
+ completedTasks: spec.completedTags,
237
+ updatedAt: spec.updatedAt || new Date().toISOString(),
238
+ type: 'moai-spec' as const,
239
+ }))
240
+ } catch (err) {
241
+ console.warn('Failed to scan MoAI SPECs:', err)
242
+ }
243
+
244
+ // Merge OpenSpec changes and MoAI SPECs, sorted by updatedAt
245
+ const allChanges = [...changes, ...moaiSpecs].sort((a, b) => {
246
+ const aTime = new Date(a.updatedAt).getTime()
247
+ const bTime = new Date(b.updatedAt).getTime()
248
+ return bTime - aTime // Most recent first
249
+ })
250
+
251
+ res.json({ success: true, data: { changes: allChanges } })
252
+ } catch (error) {
253
+ console.error('Error listing changes:', error)
254
+ res.status(500).json({ success: false, error: 'Failed to list changes' })
255
+ }
256
+ })
257
+
258
+ // GET /archived - List all archived changes
259
+ changesRouter.get('/archived', async (_req, res) => {
260
+ try {
261
+ const project = await getActiveProject()
262
+ if (!project) {
263
+ return res.json({ success: true, data: { changes: [] } })
264
+ }
265
+
266
+ initDb()
267
+ const sqlite = getSqlite()
268
+
269
+ // DB에서 archived 상태인 changes 조회 (archived_at 포함)
270
+ const dbChanges = sqlite.prepare(`
271
+ SELECT c.id, c.title, c.progress, c.archived_at, c.updated_at,
272
+ (SELECT COUNT(*) FROM tasks t WHERE t.change_id = c.id AND t.status != 'archived') as totalTasks,
273
+ (SELECT COUNT(*) FROM tasks t WHERE t.change_id = c.id AND t.status = 'done') as completedTasks
274
+ FROM changes c
275
+ WHERE c.project_id = ? AND c.status = 'archived'
276
+ ORDER BY COALESCE(c.archived_at, c.updated_at) DESC
277
+ `).all(project.id) as Array<{
278
+ id: string
279
+ title: string
280
+ progress: number
281
+ archived_at: number | null
282
+ updated_at: number
283
+ totalTasks: number
284
+ completedTasks: number
285
+ }>
286
+
287
+ const archivedChanges = dbChanges.map(change => ({
288
+ id: change.id,
289
+ title: change.title,
290
+ progress: change.progress,
291
+ totalTasks: change.totalTasks,
292
+ completedTasks: change.completedTasks,
293
+ archivedAt: change.archived_at
294
+ ? new Date(change.archived_at).toISOString()
295
+ : new Date(change.updated_at).toISOString(),
296
+ source: 'db' as const
297
+ }))
298
+
299
+ res.json({ success: true, data: { changes: archivedChanges } })
300
+ } catch (error) {
301
+ console.error('Error listing archived changes:', error)
302
+ res.status(500).json({ success: false, error: 'Failed to list archived changes' })
303
+ }
304
+ })
305
+
306
+ // GET /archived/:id - Get archived change detail
307
+ changesRouter.get('/archived/:id', async (req, res) => {
308
+ try {
309
+ const project = await getActiveProject()
310
+ if (!project) {
311
+ return res.status(400).json({ success: false, error: 'No active project' })
312
+ }
313
+
314
+ const changeId = req.params.id
315
+ const files: Record<string, string> = {}
316
+
317
+ // Remote project: use SSH plugin
318
+ if (project.remote) {
319
+ const plugin = await getRemotePlugin()
320
+ if (!plugin) {
321
+ return res.status(400).json({ success: false, error: 'Remote plugin not available' })
322
+ }
323
+
324
+ const server = await plugin.getRemoteServerById(project.remote.serverId)
325
+ if (!server) {
326
+ return res.status(400).json({ success: false, error: 'Remote server not found' })
327
+ }
328
+
329
+ // Archive locations for remote projects
330
+ const archiveLocations = [
331
+ `${project.path}/openspec/changes/archive`,
332
+ `${project.path}/openspec/archive`,
333
+ `${project.path}/openspec/archived`,
334
+ ]
335
+
336
+ let changeDir: string | null = null
337
+
338
+ // Search for the change folder in archive locations
339
+ for (const archiveBase of archiveLocations) {
340
+ try {
341
+ const listing = await plugin.listDirectory(server, archiveBase)
342
+ // Look for exact match or date-prefixed match (e.g., 2026-01-17-change-id)
343
+ const matchingFolder = listing.entries.find(
344
+ (entry) => entry.type === 'directory' && (entry.name === changeId || entry.name.endsWith(`-${changeId}`))
345
+ )
346
+ if (matchingFolder) {
347
+ changeDir = `${archiveBase}/${matchingFolder.name}`
348
+ break
349
+ }
350
+ } catch {
351
+ // Archive location not found, try next
352
+ }
353
+ }
354
+
355
+ if (!changeDir) {
356
+ return res.status(404).json({ success: false, error: 'Archived change not found' })
357
+ }
358
+
359
+ // Read all .md files in the change directory
360
+ try {
361
+ const entries = await plugin.listDirectory(server, changeDir)
362
+ for (const entry of entries.entries) {
363
+ if (entry.type === 'file' && entry.name.endsWith('.md')) {
364
+ try {
365
+ const content = await plugin.readRemoteFile(server, `${changeDir}/${entry.name}`)
366
+ files[entry.name] = content
367
+ } catch {
368
+ // Skip unreadable files
369
+ }
370
+ }
371
+ // Also check specs subdirectory
372
+ if (entry.type === 'directory' && entry.name === 'specs') {
373
+ try {
374
+ const specsDir = `${changeDir}/specs`
375
+ const specEntries = await plugin.listDirectory(server, specsDir)
376
+ for (const specEntry of specEntries.entries) {
377
+ if (specEntry.type === 'directory') {
378
+ // Each spec is in its own folder
379
+ try {
380
+ const specPath = `${specsDir}/${specEntry.name}/spec.md`
381
+ const content = await plugin.readRemoteFile(server, specPath)
382
+ files[`specs/${specEntry.name}/spec.md`] = content
383
+ } catch {
384
+ // Skip unreadable spec files
385
+ }
386
+ } else if (specEntry.type === 'file' && specEntry.name.endsWith('.md')) {
387
+ try {
388
+ const content = await plugin.readRemoteFile(server, `${specsDir}/${specEntry.name}`)
389
+ files[`specs/${specEntry.name}`] = content
390
+ } catch {
391
+ // Skip unreadable files
392
+ }
393
+ }
394
+ }
395
+ } catch {
396
+ // Skip if specs dir not accessible
397
+ }
398
+ }
399
+ }
400
+ } catch (error) {
401
+ console.error('Error reading remote archived change:', error)
402
+ return res.status(500).json({ success: false, error: 'Failed to read archived change' })
403
+ }
404
+
405
+ return res.json({
406
+ success: true,
407
+ data: {
408
+ id: changeId,
409
+ files,
410
+ },
411
+ })
412
+ }
413
+
414
+ // Local project: use filesystem
415
+ const archiveLocations = [
416
+ join(project.path, 'openspec', 'changes', 'archive'),
417
+ join(project.path, 'openspec', 'archive'),
418
+ join(project.path, 'openspec', 'archived'),
419
+ ]
420
+
421
+ let changeDir: string | null = null
422
+
423
+ for (const archiveBase of archiveLocations) {
424
+ // First try exact match
425
+ const candidatePath = join(archiveBase, changeId)
426
+ try {
427
+ await access(candidatePath)
428
+ changeDir = candidatePath
429
+ break
430
+ } catch {
431
+ // Not found with exact match, try date-prefixed pattern
432
+ }
433
+
434
+ // Try date-prefixed pattern (e.g., 2025-10-20-change-id)
435
+ try {
436
+ const entries = await readdir(archiveBase, { withFileTypes: true })
437
+ const matchingFolder = entries.find(
438
+ (entry) => entry.isDirectory() && (entry.name === changeId || entry.name.endsWith(`-${changeId}`))
439
+ )
440
+ if (matchingFolder) {
441
+ changeDir = join(archiveBase, matchingFolder.name)
442
+ break
443
+ }
444
+ } catch {
445
+ // Archive location not found, try next
446
+ }
447
+ }
448
+
449
+ if (!changeDir) {
450
+ return res.status(404).json({ success: false, error: 'Archived change not found' })
451
+ }
452
+
453
+ // Read all files in the change directory
454
+ const entries = await readdir(changeDir, { withFileTypes: true })
455
+
456
+ for (const entry of entries) {
457
+ if (entry.isFile() && entry.name.endsWith('.md')) {
458
+ const filePath = join(changeDir, entry.name)
459
+ const content = await readFile(filePath, 'utf-8')
460
+ files[entry.name] = content
461
+ }
462
+ // Also check specs subdirectory
463
+ if (entry.isDirectory() && entry.name === 'specs') {
464
+ const specsDir = join(changeDir, 'specs')
465
+ const specEntries = await readdir(specsDir, { withFileTypes: true })
466
+ for (const specEntry of specEntries) {
467
+ if (specEntry.isFile() && specEntry.name.endsWith('.md')) {
468
+ const specPath = join(specsDir, specEntry.name)
469
+ const content = await readFile(specPath, 'utf-8')
470
+ files[`specs/${specEntry.name}`] = content
471
+ }
472
+ }
473
+ }
474
+ }
475
+
476
+ res.json({
477
+ success: true,
478
+ data: {
479
+ id: changeId,
480
+ files,
481
+ },
482
+ })
483
+ } catch (error) {
484
+ console.error('Error getting archived change:', error)
485
+ res.status(500).json({ success: false, error: 'Failed to get archived change' })
486
+ }
487
+ })
488
+
489
+ // GET /:id/tasks - Get tasks for a change
490
+ changesRouter.get('/:id/tasks', async (req, res) => {
491
+ try {
492
+ // projectId 쿼리 파라미터가 있으면 해당 프로젝트 사용, 없으면 활성 프로젝트
493
+ const projectId = req.query.projectId as string | undefined
494
+ const project = projectId
495
+ ? await getProjectById(projectId)
496
+ : await getActiveProject()
497
+
498
+ if (!project) {
499
+ return res.status(400).json({ success: false, error: 'No active project' })
500
+ }
501
+
502
+ const changeId = req.params.id
503
+
504
+ // 원격 프로젝트인 경우 DB에서 tasks 조회
505
+ if (project.remote) {
506
+ initDb()
507
+ const sqlite = getSqlite()
508
+
509
+ const tasks = sqlite.prepare(`
510
+ SELECT id, title, status, group_title, group_order, task_order,
511
+ major_title, sub_order, priority, stage, created_at, updated_at
512
+ FROM tasks
513
+ WHERE change_id = ? AND project_id = ?
514
+ ORDER BY group_order ASC, task_order ASC
515
+ `).all(changeId, project.id) as Array<{
516
+ id: string
517
+ title: string
518
+ status: string
519
+ group_title: string | null
520
+ group_order: number
521
+ task_order: number
522
+ major_title: string | null
523
+ sub_order: number | null
524
+ priority: string
525
+ stage: string
526
+ created_at: number
527
+ updated_at: number
528
+ }>
529
+
530
+ // 그룹별로 정리
531
+ const groupMap = new Map<string, {
532
+ title: string
533
+ order: number
534
+ tasks: Array<{
535
+ id: string
536
+ title: string
537
+ completed: boolean
538
+ order: number
539
+ }>
540
+ }>()
541
+
542
+ for (const task of tasks) {
543
+ const groupTitle = task.group_title || 'Tasks'
544
+ if (!groupMap.has(groupTitle)) {
545
+ groupMap.set(groupTitle, {
546
+ title: groupTitle,
547
+ order: task.group_order,
548
+ tasks: []
549
+ })
550
+ }
551
+ groupMap.get(groupTitle)!.tasks.push({
552
+ id: task.id,
553
+ title: task.title,
554
+ completed: task.status === 'done',
555
+ order: task.task_order
556
+ })
557
+ }
558
+
559
+ const groups = Array.from(groupMap.values())
560
+ .sort((a, b) => a.order - b.order)
561
+ .map(g => ({
562
+ ...g,
563
+ tasks: g.tasks.sort((a, b) => a.order - b.order)
564
+ }))
565
+
566
+ return res.json({
567
+ success: true,
568
+ data: {
569
+ changeId,
570
+ groups,
571
+ remote: true
572
+ }
573
+ })
574
+ }
575
+
576
+ // 로컬 프로젝트인 경우 파일에서 직접 읽기
577
+ const openspecDir = join(project.path, 'openspec', 'changes')
578
+ const tasksPath = join(openspecDir, changeId, 'tasks.md')
579
+ const content = await readFile(tasksPath, 'utf-8')
580
+ const parsed = parseTasksFile(changeId, content)
581
+
582
+ res.json({ success: true, data: parsed })
583
+ } catch (error) {
584
+ console.error('Error reading tasks:', error)
585
+ res.status(500).json({ success: false, error: 'Failed to read tasks' })
586
+ }
587
+ })
588
+
589
+ // ==================== TASKS ====================
590
+
591
+ // PATCH /tasks/:changeId/:taskId - Toggle task checkbox
592
+ changesRouter.patch('/tasks/:changeId/:taskId', async (req, res) => {
593
+ try {
594
+ const paths = await getProjectPaths()
595
+ if (!paths) {
596
+ return res.status(400).json({ success: false, error: 'No active project' })
597
+ }
598
+
599
+ const { changeId, taskId } = req.params
600
+ const tasksPath = join(paths.openspecDir, changeId, 'tasks.md')
601
+
602
+ // Read current content
603
+ const content = await readFile(tasksPath, 'utf-8')
604
+
605
+ // Toggle the task
606
+ const { newContent, task } = toggleTaskInFile(content, taskId)
607
+
608
+ // Write back
609
+ await writeFile(tasksPath, newContent, 'utf-8')
610
+
611
+ res.json({ success: true, data: { task } })
612
+ } catch (error) {
613
+ console.error('Error toggling task:', error)
614
+ res.status(500).json({ success: false, error: 'Failed to toggle task' })
615
+ }
616
+ })
617
+
618
+ // ==================== OPENSPEC CLI INTEGRATION ====================
619
+
620
+ // GET /cli/available - Check if OpenSpec CLI is available
621
+ // TAG-014: OpenSpec CLI support removed - returns always false
622
+ changesRouter.get('/cli/available', async (_req, res) => {
623
+ try {
624
+ res.json({
625
+ success: true,
626
+ data: {
627
+ available: false,
628
+ version: null,
629
+ note: 'OpenSpec CLI support deprecated. Use MoAI SPEC system instead.',
630
+ },
631
+ })
632
+ } catch (error) {
633
+ console.error('Error checking OpenSpec CLI:', error)
634
+ res.status(500).json({ success: false, error: 'Failed to check OpenSpec CLI' })
635
+ }
636
+ })
637
+
638
+ // GET /:id/status - Get artifact completion status for a change
639
+ changesRouter.get('/:id/status', async (req, res) => {
640
+ try {
641
+ const project = await getActiveProject()
642
+ if (!project) {
643
+ return res.status(400).json({ success: false, error: 'No active project' })
644
+ }
645
+
646
+ const changeId = req.params.id
647
+ const forceRefresh = req.query.refresh === 'true'
648
+
649
+ // 캐시 우선 확인 (refresh 파라미터가 없는 경우)
650
+ if (!forceRefresh) {
651
+ const cached = getCachedArtifactStatus(changeId, project.id)
652
+ if (cached) {
653
+ return res.json({
654
+ success: true,
655
+ data: {
656
+ changeId,
657
+ artifacts: cached.artifacts || [],
658
+ progress: cached.progress || { completed: 0, total: 0, percentage: 0 },
659
+ cached: true,
660
+ },
661
+ })
662
+ }
663
+ }
664
+
665
+ // TAG-006: OpenSpec CLI is deprecated, return empty status
666
+ // Graceful degradation: return empty artifacts and zero progress
667
+ // Clients should use MoAI SPEC system for actual status
668
+ res.json({
669
+ success: true,
670
+ data: {
671
+ changeId,
672
+ artifacts: [],
673
+ progress: { completed: 0, total: 0, percentage: 0 },
674
+ cached: false,
675
+ note: 'OpenSpec CLI support deprecated. Use MoAI SPEC system for current status tracking.',
676
+ },
677
+ })
678
+ } catch (error) {
679
+ console.error('Error getting change status:', error)
680
+ res.status(500).json({ success: false, error: 'Failed to get change status' })
681
+ }
682
+ })
683
+
684
+ // POST /:id/validate - Validate a change
685
+ changesRouter.post('/:id/validate', async (req, res) => {
686
+ try {
687
+ const project = await getActiveProject()
688
+ if (!project) {
689
+ return res.status(400).json({ success: false, error: 'No active project' })
690
+ }
691
+
692
+ const changeId = req.params.id
693
+ // TAG-006: OpenSpec CLI validation is deprecated
694
+ // Return graceful empty validation response
695
+ res.json({
696
+ success: true,
697
+ data: {
698
+ changeId,
699
+ valid: true,
700
+ errors: [],
701
+ warnings: [],
702
+ note: 'OpenSpec CLI validation deprecated. Use MoAI SPEC system validation.',
703
+ },
704
+ })
705
+ } catch (error) {
706
+ console.error('Error validating change:', error)
707
+ res.status(500).json({ success: false, error: 'Failed to validate change' })
708
+ }
709
+ })
710
+
711
+ // POST /:id/archive - Archive a completed change
712
+ changesRouter.post('/:id/archive', async (req, res) => {
713
+ try {
714
+ const project = await getActiveProject()
715
+ if (!project) {
716
+ return res.status(400).json({ success: false, error: 'No active project' })
717
+ }
718
+
719
+ const changeId = req.params.id
720
+ const syncSpecs = req.body?.syncSpecs !== false // Default to sync specs
721
+
722
+ // TAG-006: OpenSpec CLI archiving is deprecated
723
+ // Only update DB status to archived (CLI operation skipped)
724
+ try {
725
+ initDb()
726
+ const sqlite = getSqlite()
727
+ sqlite.prepare(`
728
+ UPDATE changes
729
+ SET status = 'archived', archived_at = ?
730
+ WHERE id = ? AND project_id = ?
731
+ `).run(Date.now(), changeId, project.id)
732
+ } catch (dbError) {
733
+ console.error('Failed to update DB archive status:', dbError)
734
+ return res.status(500).json({
735
+ success: false,
736
+ error: 'Failed to archive change in database',
737
+ })
738
+ }
739
+
740
+ res.json({
741
+ success: true,
742
+ data: {
743
+ changeId,
744
+ archived: true,
745
+ syncSpecs,
746
+ note: 'OpenSpec CLI archiving deprecated. Archived in database only.',
747
+ },
748
+ })
749
+ } catch (error) {
750
+ console.error('Error archiving change:', error)
751
+ res.status(500).json({ success: false, error: 'Failed to archive change' })
752
+ }
753
+ })
754
+
755
+ // GET /:id/instructions/:artifact - Get dynamic instructions for an artifact
756
+ changesRouter.get('/:id/instructions/:artifact', async (req, res) => {
757
+ try {
758
+ const project = await getActiveProject()
759
+ if (!project) {
760
+ return res.status(400).json({ success: false, error: 'No active project' })
761
+ }
762
+
763
+ const { id: changeId, artifact } = req.params
764
+
765
+ // TAG-006: OpenSpec CLI instructions are deprecated
766
+ // Return empty instructions response
767
+ res.json({
768
+ success: true,
769
+ data: {
770
+ changeId,
771
+ artifact,
772
+ content: '',
773
+ context: {},
774
+ note: 'OpenSpec CLI instructions deprecated. Use MoAI SPEC system for artifact instructions.',
775
+ },
776
+ })
777
+ } catch (error) {
778
+ console.error('Error getting instructions:', error)
779
+ res.status(500).json({ success: false, error: 'Failed to get instructions' })
780
+ }
781
+ })
782
+
783
+ // ==================== PLANS ====================
784
+
785
+ // GET /plans/:changeId/:taskId - Get detail plan
786
+ changesRouter.get('/plans/:changeId/:taskId', async (req, res) => {
787
+ try {
788
+ const paths = await getProjectPaths()
789
+ if (!paths) {
790
+ return res.status(400).json({ success: false, error: 'No active project' })
791
+ }
792
+
793
+ const { changeId, taskId } = req.params
794
+ const planPath = join(paths.plansDir, changeId, `${taskId}.md`)
795
+
796
+ try {
797
+ const content = await readFile(planPath, 'utf-8')
798
+ res.json({
799
+ success: true,
800
+ data: { taskId, changeId, content, exists: true },
801
+ })
802
+ } catch {
803
+ res.json({
804
+ success: true,
805
+ data: { taskId, changeId, content: null, exists: false },
806
+ })
807
+ }
808
+ } catch (error) {
809
+ console.error('Error reading plan:', error)
810
+ res.status(500).json({ success: false, error: 'Failed to read plan' })
811
+ }
812
+ })