@taskforcehq/taskforce 0.3.170 → 0.3.301

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 (698) hide show
  1. package/README.md +71 -21
  2. package/dist/Taskforce.module.css +3394 -5981
  3. package/dist/TaskforceCore.CategoryFallback.test.js +5 -2
  4. package/dist/TaskforceCore.filter-persistence.test.js +402 -0
  5. package/dist/TaskforceCore.js +388 -71
  6. package/dist/TaskforceCore.routing.test.js +311 -0
  7. package/dist/TaskforceCore.test.js +3344 -615
  8. package/dist/TaskforceWidget.js +3 -2
  9. package/dist/__tests__/localizationCatalogs.test.js +48 -31
  10. package/dist/__tests__/workflowSimulation.test.js +2 -2
  11. package/dist/annotatedAttachments/AnnotatedAttachmentSessionStore.d.ts +60 -0
  12. package/dist/annotatedAttachments/AnnotatedAttachmentSessionStore.js +324 -0
  13. package/dist/annotatedAttachments/AnnotatedAttachmentSessionStore.test.js +278 -0
  14. package/dist/annotatedAttachments/payload.d.ts +2 -0
  15. package/dist/annotatedAttachments/payload.js +54 -0
  16. package/dist/annotatedAttachments/payload.test.js +67 -0
  17. package/dist/annotatedAttachments/service.d.ts +49 -0
  18. package/dist/annotatedAttachments/service.js +121 -0
  19. package/dist/annotatedAttachments/types.d.ts +86 -0
  20. package/dist/cli.js +74 -25
  21. package/dist/compat/deploymentCompat.d.ts +12 -0
  22. package/dist/compat/deploymentCompat.js +43 -0
  23. package/dist/compat/workspaceSyncCompat.d.ts +6 -0
  24. package/dist/compat/workspaceSyncCompat.js +79 -0
  25. package/dist/compat/workspaceSyncCompat.test.js +87 -0
  26. package/dist/components/features/AgentsModule.d.ts +5 -0
  27. package/dist/components/features/AgentsModule.js +131 -0
  28. package/dist/components/features/AgentsModule.test.js +102 -0
  29. package/dist/components/features/AnnotatedAttachmentWorkspace.d.ts +24 -0
  30. package/dist/components/features/AnnotatedAttachmentWorkspace.js +1942 -0
  31. package/dist/components/features/AnnotatedAttachmentWorkspace.test.js +2831 -0
  32. package/dist/components/features/DocumentGenerateModal.js +8 -16
  33. package/dist/components/features/DocumentIndex.d.ts +3 -4
  34. package/dist/components/features/DocumentIndex.js +22 -10
  35. package/dist/components/features/DocumentViewer.d.ts +6 -2
  36. package/dist/components/features/DocumentViewer.js +1000 -18
  37. package/dist/components/features/DocumentWorkspace.d.ts +40 -2
  38. package/dist/components/features/DocumentWorkspace.js +96 -16
  39. package/dist/components/features/DocumentWorkspace.test.js +1202 -0
  40. package/dist/components/features/InitiativesModule.d.ts +22 -0
  41. package/dist/components/features/InitiativesModule.js +33 -0
  42. package/dist/components/features/TaskSettings.d.ts +41 -32
  43. package/dist/components/features/TaskSettings.js +798 -313
  44. package/dist/components/features/TaskSettings.test.js +1221 -47
  45. package/dist/components/features/WorkflowsModule.d.ts +27 -0
  46. package/dist/components/features/WorkflowsModule.js +21 -0
  47. package/dist/components/features/documentWorkspaceFilters.d.ts +10 -0
  48. package/dist/components/features/documentWorkspaceFilters.js +11 -0
  49. package/dist/components/features/settings/CategoryManager.d.ts +2 -0
  50. package/dist/components/features/settings/CategoryManager.js +15 -8
  51. package/dist/components/features/settings/PriorityManager.d.ts +18 -0
  52. package/dist/components/features/settings/PriorityManager.js +51 -0
  53. package/dist/components/features/settings/TaxonomyEditor.d.ts +2 -1
  54. package/dist/components/features/settings/TaxonomyEditor.js +41 -18
  55. package/dist/components/features/settings/TaxonomyLibraryManager.d.ts +26 -0
  56. package/dist/components/features/settings/TaxonomyLibraryManager.js +301 -0
  57. package/dist/components/features/settings/TaxonomyLibraryManager.test.js +141 -0
  58. package/dist/components/features/settings/TaxonomyManager.d.ts +35 -12
  59. package/dist/components/features/settings/TaxonomyManager.js +59 -27
  60. package/dist/components/features/settings/TypeManager.d.ts +11 -0
  61. package/dist/components/features/settings/TypeManager.js +48 -11
  62. package/dist/components/features/settings/{WorkflowEditorPrototype.d.ts → WorkflowEditor.d.ts} +2 -2
  63. package/dist/components/features/settings/{WorkflowEditorPrototype.js → WorkflowEditor.js} +3 -3
  64. package/dist/components/task/TaskActionHeader.d.ts +12 -2
  65. package/dist/components/task/TaskActionHeader.js +64 -8
  66. package/dist/components/task/TaskActionHeader.test.js +73 -0
  67. package/dist/components/task/TaskCard.d.ts +14 -16
  68. package/dist/components/task/TaskCard.js +144 -174
  69. package/dist/components/task/TaskCard.test.js +416 -64
  70. package/dist/components/task/TaskContextUpload.d.ts +6 -5
  71. package/dist/components/task/TaskContextUpload.js +199 -64
  72. package/dist/components/task/TaskContextUpload.test.js +331 -14
  73. package/dist/components/task/TaskForm.d.ts +23 -29
  74. package/dist/components/task/TaskForm.js +348 -169
  75. package/dist/components/task/TaskForm.test.js +419 -23
  76. package/dist/components/task/TaskKanban.d.ts +20 -21
  77. package/dist/components/task/TaskKanban.js +176 -316
  78. package/dist/components/task/TaskKanban.planning-drop.test.js +93 -0
  79. package/dist/components/task/TaskList.d.ts +22 -11
  80. package/dist/components/task/TaskList.js +98 -12
  81. package/dist/components/task/TaskList.test.js +206 -7
  82. package/dist/components/task/TaskReferenceBadge.d.ts +12 -0
  83. package/dist/components/task/TaskReferenceBadge.js +5 -0
  84. package/dist/components/task/TaskStatusActions.d.ts +12 -0
  85. package/dist/components/task/TaskStatusActions.js +18 -0
  86. package/dist/components/task/TaskStatusActions.test.js +45 -0
  87. package/dist/components/ui/ImageReferenceBadge.d.ts +12 -0
  88. package/dist/components/ui/ImageReferenceBadge.js +5 -0
  89. package/dist/components/ui/LevelSelector.d.ts +2 -1
  90. package/dist/components/ui/LevelSelector.js +2 -2
  91. package/dist/components/ui/Markdown.d.ts +1 -2
  92. package/dist/components/ui/Markdown.js +2 -13
  93. package/dist/components/ui/Modal.d.ts +3 -2
  94. package/dist/components/ui/Modal.js +4 -3
  95. package/dist/components/ui/MultiSelectFilter.d.ts +3 -1
  96. package/dist/components/ui/MultiSelectFilter.js +2 -2
  97. package/dist/components/ui/ReferenceBadgeButton.d.ts +13 -0
  98. package/dist/components/ui/ReferenceBadgeButton.js +6 -0
  99. package/dist/components/ui/TaxonomyDropdown.d.ts +7 -1
  100. package/dist/components/ui/TaxonomyDropdown.js +58 -23
  101. package/dist/components/ui/TopNoticeLayer.d.ts +7 -0
  102. package/dist/components/ui/TopNoticeLayer.js +14 -0
  103. package/dist/components/ui/TopNoticeLayer.test.js +25 -0
  104. package/dist/components/views/AppShellHeader.d.ts +13 -0
  105. package/dist/components/views/AppShellHeader.js +19 -0
  106. package/dist/components/views/AppShellHeader.test.js +21 -0
  107. package/dist/components/views/PlanComparisonPage.d.ts +73 -0
  108. package/dist/components/views/PlanComparisonPage.js +196 -0
  109. package/dist/components/views/PlanComparisonPage.test.js +251 -0
  110. package/dist/components/views/PlansPage.d.ts +14 -0
  111. package/dist/components/views/PlansPage.js +355 -0
  112. package/dist/components/views/StandaloneLayout.d.ts +2 -2
  113. package/dist/components/views/StandaloneLayout.js +2227 -1188
  114. package/dist/components/views/WidgetView.d.ts +2 -2
  115. package/dist/components/views/WidgetView.js +149 -43
  116. package/dist/components/views/chrome/WorkspaceChromeSections.d.ts +57 -0
  117. package/dist/components/views/chrome/WorkspaceChromeSections.js +38 -0
  118. package/dist/components/views/chrome/WorkspaceChromeSections.test.js +54 -0
  119. package/dist/components/views/chrome/workspaceChrome.d.ts +31 -0
  120. package/dist/components/views/chrome/workspaceChrome.js +108 -0
  121. package/dist/components/views/chrome/workspaceChrome.test.js +52 -0
  122. package/dist/components/views/panels/DocumentFilterToolbar.d.ts +10 -0
  123. package/dist/components/views/panels/DocumentFilterToolbar.js +7 -0
  124. package/dist/components/views/panels/DocumentFilterToolbar.test.js +19 -0
  125. package/dist/components/views/panels/FilterToolbar.d.ts +68 -0
  126. package/dist/components/views/panels/FilterToolbar.js +21 -0
  127. package/dist/components/views/panels/FilterToolbar.test.d.ts +1 -0
  128. package/dist/components/views/panels/FilterToolbar.test.js +45 -0
  129. package/dist/components/views/panels/FilterToolbarControls.d.ts +47 -0
  130. package/dist/components/views/panels/FilterToolbarControls.js +61 -0
  131. package/dist/components/views/panels/PlanningDrawer.d.ts +115 -0
  132. package/dist/components/views/panels/PlanningDrawer.js +220 -0
  133. package/dist/components/views/panels/ScheduleSidebar.d.ts +52 -0
  134. package/dist/components/views/panels/ScheduleSidebar.js +127 -0
  135. package/dist/components/views/panels/scheduleUtils.d.ts +14 -0
  136. package/dist/components/views/panels/scheduleUtils.js +79 -0
  137. package/dist/components/views/teamManagementAccess.d.ts +6 -0
  138. package/dist/components/views/teamManagementAccess.js +18 -0
  139. package/dist/components/views/teamManagementAccess.test.d.ts +1 -0
  140. package/dist/components/views/teamManagementAccess.test.js +44 -0
  141. package/dist/config/clientDeployment.d.ts +2 -0
  142. package/dist/config/clientDeployment.js +13 -0
  143. package/dist/config/cloudEnvironment.d.ts +15 -0
  144. package/dist/config/cloudEnvironment.js +60 -0
  145. package/dist/config/deployment.d.ts +20 -0
  146. package/dist/config/deployment.js +67 -0
  147. package/dist/config/deployment.test.d.ts +1 -0
  148. package/dist/config/deployment.test.js +88 -0
  149. package/dist/config/envSchema.js +36 -8
  150. package/dist/config/envSchema.test.js +28 -0
  151. package/dist/core/AiProfileService.d.ts +66 -0
  152. package/dist/core/AiProfileService.js +320 -0
  153. package/dist/core/AiProfileService.test.d.ts +1 -0
  154. package/dist/core/AiProfileService.test.js +164 -0
  155. package/dist/core/AiProfiles.test.d.ts +1 -0
  156. package/dist/core/AiProfiles.test.js +449 -0
  157. package/dist/core/AttachmentLinkService.d.ts +15 -0
  158. package/dist/core/AttachmentLinkService.js +157 -0
  159. package/dist/core/AuthTokenService.d.ts +44 -0
  160. package/dist/core/AuthTokenService.js +207 -0
  161. package/dist/core/CreatedBy.test.js +134 -6
  162. package/dist/core/DeletedTaskLifecycleService.d.ts +33 -0
  163. package/dist/core/DeletedTaskLifecycleService.js +158 -0
  164. package/dist/core/DeletedTaskTrash.test.d.ts +1 -0
  165. package/dist/core/DeletedTaskTrash.test.js +104 -0
  166. package/dist/core/EntitlementsPolicy.test.js +78 -5
  167. package/dist/core/GlobalSettingsService.d.ts +16 -0
  168. package/dist/core/GlobalSettingsService.js +370 -0
  169. package/dist/core/JsonBackupRuntime.test.d.ts +1 -0
  170. package/dist/core/JsonBackupRuntime.test.js +155 -0
  171. package/dist/core/McpTokenService.d.ts +118 -0
  172. package/dist/core/McpTokenService.js +921 -0
  173. package/dist/core/PlanEntitlementService.d.ts +201 -0
  174. package/dist/core/PlanEntitlementService.js +1442 -0
  175. package/dist/core/PlanVersionPolicy.test.d.ts +1 -0
  176. package/dist/core/PlanVersionPolicy.test.js +178 -0
  177. package/dist/core/PlanningEntities.test.d.ts +1 -0
  178. package/dist/core/PlanningEntities.test.js +95 -0
  179. package/dist/core/ScheduleFields.test.js +15 -19
  180. package/dist/core/SignupMonetizationSettings.test.d.ts +1 -0
  181. package/dist/core/SignupMonetizationSettings.test.js +159 -0
  182. package/dist/core/Stats.test.d.ts +1 -0
  183. package/dist/core/Stats.test.js +36 -0
  184. package/dist/core/SyncReconciliationService.d.ts +93 -0
  185. package/dist/core/SyncReconciliationService.js +406 -0
  186. package/dist/core/SystemAdmin.test.js +578 -13
  187. package/dist/core/TaskActivityService.d.ts +21 -0
  188. package/dist/core/TaskActivityService.js +130 -0
  189. package/dist/core/TaskAttachmentsCanonical.test.d.ts +1 -0
  190. package/dist/core/TaskAttachmentsCanonical.test.js +306 -0
  191. package/dist/core/TaskAuditTimeline.test.d.ts +1 -0
  192. package/dist/core/TaskAuditTimeline.test.js +132 -0
  193. package/dist/core/TaskTaxonomyValidation.test.js +338 -15
  194. package/dist/core/Taskforce.d.ts +930 -183
  195. package/dist/core/Taskforce.ids.test.js +252 -0
  196. package/dist/core/Taskforce.js +3848 -2532
  197. package/dist/core/Taskforce.mcpAuth.test.d.ts +1 -0
  198. package/dist/core/Taskforce.mcpAuth.test.js +343 -0
  199. package/dist/core/Taskforce.realtimeMutation.test.js +57 -2
  200. package/dist/core/TaxonomySettingsService.d.ts +18 -0
  201. package/dist/core/TaxonomySettingsService.js +162 -0
  202. package/dist/core/WorkspaceDelete.test.js +32 -13
  203. package/dist/core/WorkspaceLifecycleService.d.ts +11 -0
  204. package/dist/core/WorkspaceLifecycleService.js +88 -0
  205. package/dist/core/WorkspacePermissions.test.js +95 -0
  206. package/dist/core/WorkspacePlanMode.test.js +114 -1
  207. package/dist/core/WorkspacePreferenceService.d.ts +41 -0
  208. package/dist/core/WorkspacePreferenceService.js +246 -0
  209. package/dist/core/WorkspaceSyncSettings.test.d.ts +1 -0
  210. package/dist/core/WorkspaceSyncSettings.test.js +65 -0
  211. package/dist/core/__tests__/TaskAttachmentsCanonical.test.d.ts +1 -0
  212. package/dist/core/__tests__/TaskAttachmentsCanonical.test.js +212 -0
  213. package/dist/core/shared.d.ts +36 -0
  214. package/dist/core/shared.js +128 -0
  215. package/dist/core/types.d.ts +614 -0
  216. package/dist/core/types.js +27 -0
  217. package/dist/documentReviews/DocumentReviewCommentStore.d.ts +56 -0
  218. package/dist/documentReviews/DocumentReviewCommentStore.js +230 -0
  219. package/dist/documentReviews/DocumentReviewSessionStore.d.ts +52 -0
  220. package/dist/documentReviews/DocumentReviewSessionStore.js +193 -0
  221. package/dist/documentReviews/DocumentReviewSessionStore.test.d.ts +1 -0
  222. package/dist/documentReviews/DocumentReviewSessionStore.test.js +127 -0
  223. package/dist/documentReviews/service.d.ts +68 -0
  224. package/dist/documentReviews/service.js +210 -0
  225. package/dist/documentReviews/types.d.ts +58 -0
  226. package/dist/documentReviews/types.js +1 -0
  227. package/dist/hooks/auth/useAuthGuardPolicy.d.ts +2 -0
  228. package/dist/hooks/auth/useAuthGuardPolicy.js +1 -0
  229. package/dist/hooks/tasks/useCurrentTaskRelations.d.ts +15 -0
  230. package/dist/hooks/tasks/useCurrentTaskRelations.js +37 -0
  231. package/dist/hooks/tasks/useTaskActions.d.ts +3 -0
  232. package/dist/hooks/tasks/useTaskActions.js +2 -0
  233. package/dist/hooks/tasks/useTaskEditorNavigation.d.ts +65 -0
  234. package/dist/hooks/tasks/useTaskEditorNavigation.js +235 -0
  235. package/dist/hooks/tasks/useTaskFilters.d.ts +2 -0
  236. package/dist/hooks/tasks/useTaskFilters.js +2 -0
  237. package/dist/hooks/tasks/useTaskFormActions.d.ts +58 -0
  238. package/dist/hooks/tasks/useTaskFormActions.js +365 -0
  239. package/dist/hooks/tasks/useTaskRelationships.d.ts +16 -0
  240. package/dist/hooks/tasks/useTaskRelationships.js +64 -0
  241. package/dist/hooks/ui/useResourceExport.d.ts +19 -0
  242. package/dist/hooks/ui/useResourceExport.js +84 -0
  243. package/dist/hooks/ui/useSettingsModel.d.ts +203 -0
  244. package/dist/hooks/ui/useSettingsModel.js +125 -0
  245. package/dist/hooks/ui/useSettingsPersistence.d.ts +36 -0
  246. package/dist/hooks/ui/useSettingsPersistence.js +254 -0
  247. package/dist/hooks/ui/useSettingsTaxonomyManagement.d.ts +119 -0
  248. package/dist/hooks/ui/useSettingsTaxonomyManagement.js +536 -0
  249. package/dist/hooks/ui/useUiNotice.d.ts +1 -0
  250. package/dist/hooks/ui/useUiNotice.js +1 -0
  251. package/dist/hooks/ui/useWorkflowTemplates.d.ts +37 -0
  252. package/dist/hooks/ui/useWorkflowTemplates.js +111 -0
  253. package/dist/hooks/ui/useZenMode.d.ts +5 -0
  254. package/dist/hooks/ui/useZenMode.js +32 -0
  255. package/dist/hooks/useFilterSort.d.ts +60 -0
  256. package/dist/hooks/useFilterSort.js +362 -0
  257. package/dist/hooks/useFilterSort.test.d.ts +1 -0
  258. package/dist/hooks/useFilterSort.test.js +333 -0
  259. package/dist/hooks/useRealtimeSync.d.ts +1 -0
  260. package/dist/hooks/useRealtimeSync.js +24 -9
  261. package/dist/hooks/useRealtimeSync.test.js +28 -1
  262. package/dist/hooks/useSyncOrchestrator.aiProfiles.test.d.ts +1 -0
  263. package/dist/hooks/useSyncOrchestrator.aiProfiles.test.js +34 -0
  264. package/dist/hooks/useSyncOrchestrator.d.ts +65 -103
  265. package/dist/hooks/useSyncOrchestrator.js +1538 -670
  266. package/dist/hooks/useSyncOrchestrator.retry-closure.test.js +700 -174
  267. package/dist/hooks/useTaskData.d.ts +35 -0
  268. package/dist/hooks/useTaskData.js +243 -0
  269. package/dist/hooks/useTaskData.test.d.ts +1 -0
  270. package/dist/hooks/useTaskData.test.js +180 -0
  271. package/dist/hooks/useTaskMutations.d.ts +46 -0
  272. package/dist/hooks/useTaskMutations.js +472 -0
  273. package/dist/hooks/useTaskMutations.test.d.ts +1 -0
  274. package/dist/hooks/useTaskMutations.test.js +80 -0
  275. package/dist/hooks/useTaskforce.contract.test.d.ts +1 -0
  276. package/dist/hooks/useTaskforce.contract.test.js +7 -0
  277. package/dist/hooks/useTaskforce.d.ts +260 -295
  278. package/dist/hooks/useTaskforce.js +1954 -2623
  279. package/dist/hooks/useTaskforce.priority-filters.test.js +6 -11
  280. package/dist/hooks/useTaskforce.sync-behavior.test.d.ts +1 -0
  281. package/dist/hooks/useTaskforce.sync-behavior.test.js +1120 -0
  282. package/dist/hooks/useUiNotice.d.ts +16 -0
  283. package/dist/hooks/useUiNotice.js +49 -0
  284. package/dist/hooks/useWorkspaceSyncController.d.ts +23 -46
  285. package/dist/hooks/useWorkspaceSyncController.js +280 -461
  286. package/dist/hooks/useWorkspaceSyncController.test.js +106 -199
  287. package/dist/hooks/workspace/useTaskforceApiRouting.d.ts +8 -0
  288. package/dist/hooks/workspace/useTaskforceApiRouting.js +91 -0
  289. package/dist/hooks/workspace/useTaskforceApiRouting.test.d.ts +1 -0
  290. package/dist/hooks/workspace/useTaskforceApiRouting.test.js +60 -0
  291. package/dist/hooks/workspace/useWorkspaceSyncController.d.ts +1 -0
  292. package/dist/hooks/workspace/useWorkspaceSyncController.js +1 -0
  293. package/dist/hooks/workspace/workspaceLocalState.d.ts +30 -0
  294. package/dist/hooks/workspace/workspaceLocalState.js +101 -0
  295. package/dist/localization/locales/en-US.d.ts +1 -8
  296. package/dist/localization/locales/en-US.js +4 -11
  297. package/dist/localization/locales/es-419.js +2 -9
  298. package/dist/localization/locales/pt-BR.js +2 -9
  299. package/dist/localization/localizationCatalogs.test.d.ts +1 -0
  300. package/dist/localization/localizationCatalogs.test.js +37 -0
  301. package/dist/main.d.ts +1 -0
  302. package/dist/main.js +9 -15
  303. package/dist/mcp/clientIntegrations.d.ts +33 -0
  304. package/dist/mcp/clientIntegrations.js +199 -0
  305. package/dist/mcp/clientIntegrations.test.d.ts +1 -0
  306. package/dist/mcp/clientIntegrations.test.js +110 -0
  307. package/dist/mcp/index.d.ts +2 -0
  308. package/dist/mcp/index.js +2 -0
  309. package/dist/mcp/optionResolution.test.js +6 -2
  310. package/dist/mcp/runtime.d.ts +120 -0
  311. package/dist/mcp/runtime.js +5668 -0
  312. package/dist/mcp/runtime.test.d.ts +1 -0
  313. package/dist/mcp/runtime.test.js +3299 -0
  314. package/dist/mcp/server.js +2 -1793
  315. package/dist/mcp/structuredCommentValidation.test.d.ts +1 -0
  316. package/dist/{__tests__ → mcp}/structuredCommentValidation.test.js +1 -1
  317. package/dist/mcp/structuredDocValidation.js +1 -2
  318. package/dist/mcp/structuredDocValidation.test.d.ts +1 -0
  319. package/dist/{__tests__ → mcp}/structuredDocValidation.test.js +9 -4
  320. package/dist/mcp/toolRegistry.d.ts +570 -0
  321. package/dist/mcp/toolRegistry.js +90 -0
  322. package/dist/mcp/toolRegistry.test.d.ts +1 -0
  323. package/dist/mcp/toolRegistry.test.js +30 -0
  324. package/dist/migrations/billingSchemaParity.test.js +111 -0
  325. package/dist/migrations/taskSchemaMigrations.d.ts +5 -0
  326. package/dist/migrations/taskSchemaMigrations.js +681 -39
  327. package/dist/migrations/taskSchemaMigrations.test.d.ts +1 -0
  328. package/dist/migrations/taskSchemaMigrations.test.js +210 -0
  329. package/dist/plugins/vite.js +13 -7
  330. package/dist/public/apple-touch-icon.png +0 -0
  331. package/dist/public/archive/phoenix/apple-touch-icon.png +0 -0
  332. package/dist/public/archive/phoenix/favicon.ico +0 -0
  333. package/dist/public/archive/phoenix/site.webmanifest +1 -0
  334. package/dist/public/favicon-96x96.png +0 -0
  335. package/dist/public/favicon.ico +0 -0
  336. package/dist/public/favicon.svg +17 -0
  337. package/dist/public/site.webmanifest +21 -1
  338. package/dist/public/web-app-manifest-192x192.png +0 -0
  339. package/dist/public/web-app-manifest-512x512.png +0 -0
  340. package/dist/releaseVersion.test.d.ts +1 -0
  341. package/dist/{__tests__/releaseVersion.test.js → releaseVersion.test.js} +1 -1
  342. package/dist/resources/templates/WORKFLOW_V2_POLICY.md +1 -1
  343. package/dist/resources/templates/workflow-sources/workflowDocs.mjs +62 -52
  344. package/dist/resources/templates/workflows/collaborate.yaml +11 -5
  345. package/dist/resources/templates/workflows/do.yaml +8 -2
  346. package/dist/resources/templates/workflows/evaluate.yaml +13 -7
  347. package/dist/resources/templates/workflows/execute.yaml +40 -23
  348. package/dist/resources/templates/workflows/plan.yaml +15 -8
  349. package/dist/resources/templates/workflows/review.yaml +14 -8
  350. package/dist/runtime/appGateDefinitions.d.ts +32 -0
  351. package/dist/runtime/appGateDefinitions.js +32 -0
  352. package/dist/runtime/appGates.d.ts +29 -0
  353. package/dist/runtime/appGates.js +53 -0
  354. package/dist/runtime/appGates.test.d.ts +1 -0
  355. package/dist/runtime/appGates.test.js +42 -0
  356. package/dist/runtime/migrationFlags.d.ts +1 -0
  357. package/dist/runtime/migrationFlags.js +1 -0
  358. package/dist/server/annotatedAttachmentsRoutes.test.d.ts +1 -0
  359. package/dist/server/annotatedAttachmentsRoutes.test.js +473 -0
  360. package/dist/server/auth.js +14 -2
  361. package/dist/server/auth.test.js +21 -1
  362. package/dist/server/cors.js +11 -5
  363. package/dist/server/cors.test.js +6 -0
  364. package/dist/server/documentReviewRoutes.test.d.ts +1 -0
  365. package/dist/server/documentReviewRoutes.test.js +157 -0
  366. package/dist/server/index.cookieProxy.test.js +46 -1
  367. package/dist/server/index.d.ts +20 -0
  368. package/dist/server/index.js +168 -41
  369. package/dist/server/index.rateLimit.test.js +6 -0
  370. package/dist/server/index.test.js +133 -2
  371. package/dist/server/mockStripe.d.ts +72 -0
  372. package/dist/server/mockStripe.js +357 -0
  373. package/dist/server/realtimeSyncWs.js +4 -0
  374. package/dist/server/routes/admin.d.ts +114 -0
  375. package/dist/server/routes/admin.js +2226 -0
  376. package/dist/server/routes/annotatedAttachments.d.ts +24 -0
  377. package/dist/server/routes/annotatedAttachments.js +235 -0
  378. package/dist/server/routes/auth.d.ts +61 -0
  379. package/dist/server/routes/auth.js +1296 -0
  380. package/dist/server/{routes.billing.d.ts → routes/billing.d.ts} +3 -2
  381. package/dist/server/routes/billing.js +2001 -0
  382. package/dist/server/routes/billing.test.d.ts +1 -0
  383. package/dist/server/routes/billing.test.js +1631 -0
  384. package/dist/server/routes/documentReviews.d.ts +11 -0
  385. package/dist/server/routes/documentReviews.js +191 -0
  386. package/dist/server/routes/documents.d.ts +118 -0
  387. package/dist/server/routes/documents.js +1113 -0
  388. package/dist/server/routes/resources.d.ts +25 -0
  389. package/dist/server/routes/resources.js +225 -0
  390. package/dist/server/routes/shared.d.ts +35 -0
  391. package/dist/server/routes/shared.js +305 -0
  392. package/dist/server/routes/shared.test.d.ts +1 -0
  393. package/dist/server/routes/shared.test.js +32 -0
  394. package/dist/server/{routes.sync.d.ts → routes/sync.d.ts} +5 -5
  395. package/dist/server/routes/sync.integration.test.d.ts +1 -0
  396. package/dist/server/routes/sync.integration.test.js +2003 -0
  397. package/dist/server/routes/sync.js +3143 -0
  398. package/dist/server/routes/tasks.d.ts +72 -0
  399. package/dist/server/routes/tasks.js +1252 -0
  400. package/dist/server/routes/workspaces.d.ts +32 -0
  401. package/dist/server/routes/workspaces.js +307 -0
  402. package/dist/server/routes.d.ts +8 -9
  403. package/dist/server/routes.js +968 -4092
  404. package/dist/server/routes.test.js +9043 -2415
  405. package/dist/server/runtimeMode.d.ts +1 -1
  406. package/dist/server/runtimeMode.js +3 -18
  407. package/dist/server/runtimeMode.test.js +3 -3
  408. package/dist/server/securityHeaders.d.ts +1 -1
  409. package/dist/server/securityHeaders.js +65 -6
  410. package/dist/server/securityHeaders.test.js +40 -2
  411. package/dist/services/templateEngine.test.d.ts +1 -0
  412. package/dist/{__tests__ → services}/templateEngine.test.js +1 -1
  413. package/dist/services/templates.test.d.ts +1 -0
  414. package/dist/{__tests__ → services}/templates.test.js +1 -1
  415. package/dist/services/workflowDocumentFixtures.test.d.ts +1 -0
  416. package/dist/{__tests__ → services}/workflowDocumentFixtures.test.js +4 -4
  417. package/dist/services/workflowExportMatrix.test.d.ts +1 -0
  418. package/dist/{__tests__ → services}/workflowExportMatrix.test.js +1 -1
  419. package/dist/services/workflowExportSnapshots.test.d.ts +1 -0
  420. package/dist/services/workflowGeneration.test.d.ts +1 -0
  421. package/dist/services/workflowSimulation.test.d.ts +1 -0
  422. package/dist/services/workflowSimulation.test.js +113 -0
  423. package/dist/services/workflowV2Policy.test.d.ts +1 -0
  424. package/dist/{__tests__ → services}/workflowV2Policy.test.js +2 -2
  425. package/dist/shared/aiProfileSurfaceType.d.ts +9 -0
  426. package/dist/shared/aiProfileSurfaceType.js +49 -0
  427. package/dist/shared/customTaxonomyLibrary.d.ts +11 -0
  428. package/dist/shared/customTaxonomyLibrary.js +276 -0
  429. package/dist/shared/customTaxonomyLibrary.test.d.ts +1 -0
  430. package/dist/shared/customTaxonomyLibrary.test.js +20 -0
  431. package/dist/shared/taxonomyCatalog.d.ts +19 -0
  432. package/dist/shared/taxonomyCatalog.js +36 -0
  433. package/dist/shared/taxonomyDefaults.d.ts +29 -0
  434. package/dist/shared/taxonomyDefaults.js +26 -0
  435. package/dist/shared/taxonomyLibrary.d.ts +15 -0
  436. package/dist/shared/taxonomyLibrary.js +98 -0
  437. package/dist/shared/taxonomyLibrary.test.d.ts +1 -0
  438. package/dist/shared/taxonomyLibrary.test.js +26 -0
  439. package/dist/shared/taxonomyState.d.ts +36 -0
  440. package/dist/shared/taxonomyState.js +73 -0
  441. package/dist/shared/taxonomyState.test.d.ts +1 -0
  442. package/dist/shared/taxonomyState.test.js +71 -0
  443. package/dist/shared/workflowDefaults.d.ts +9 -0
  444. package/dist/shared/workflowDefaults.js +11 -0
  445. package/dist/storage/documentIntegrity.d.ts +2 -0
  446. package/dist/storage/documentIntegrity.js +34 -17
  447. package/dist/storage/documentPurge.d.ts +2 -1
  448. package/dist/storage/documentPurge.js +35 -8
  449. package/dist/storage/index.d.ts +4 -0
  450. package/dist/storage/index.js +2 -0
  451. package/dist/storage/objectStorage.d.ts +1 -1
  452. package/dist/storage/objectStorageClient.d.ts +6 -4
  453. package/dist/storage/objectStorageClient.js +77 -29
  454. package/dist/storage/objectStorageClient.test.d.ts +1 -0
  455. package/dist/storage/objectStorageClient.test.js +57 -0
  456. package/dist/storage/objectStorageConfig.js +3 -1
  457. package/dist/storage/objectStorageConfig.test.d.ts +1 -0
  458. package/dist/storage/objectStorageConfig.test.js +38 -0
  459. package/dist/storage/postgresAdapter.d.ts +5 -0
  460. package/dist/storage/postgresAdapter.js +2 -2
  461. package/dist/storage/postgresAdapter.test.d.ts +1 -0
  462. package/dist/storage/postgresAdapter.test.js +29 -0
  463. package/dist/storage/taskAssetStore.d.ts +7 -4
  464. package/dist/storage/taskAssetStore.js +65 -60
  465. package/dist/storage/workspaceAssetStore.d.ts +122 -0
  466. package/dist/storage/workspaceAssetStore.js +496 -0
  467. package/dist/storage/workspaceAssetStore.test.d.ts +1 -0
  468. package/dist/storage/workspaceAssetStore.test.js +501 -0
  469. package/dist/sync/cloudSyncApi.d.ts +33 -2
  470. package/dist/sync/cloudSyncApi.js +37 -15
  471. package/dist/sync/cloudSyncApi.test.js +60 -3
  472. package/dist/sync/index.d.ts +2 -0
  473. package/dist/sync/index.js +3 -0
  474. package/dist/sync/syncService.d.ts +25 -0
  475. package/dist/sync/syncService.js +184 -16
  476. package/dist/sync/syncService.test.js +289 -25
  477. package/dist/sync/workspaceRepair.d.ts +114 -0
  478. package/dist/sync/workspaceRepair.js +566 -0
  479. package/dist/sync/workspaceSyncModel.d.ts +230 -2
  480. package/dist/sync/workspaceSyncModel.js +456 -17
  481. package/dist/sync/workspaceSyncModel.test.js +642 -0
  482. package/dist/sync/workspaceSyncState.d.ts +12 -0
  483. package/dist/sync/workspaceSyncState.js +12 -0
  484. package/dist/sync/workspaceSyncSurface.d.ts +33 -0
  485. package/dist/sync/workspaceSyncSurface.js +74 -0
  486. package/dist/types.d.ts +143 -18
  487. package/dist/types.js +9 -24
  488. package/dist/ui/assets/AgentsModule-Bdq3T1Ts.js +1 -0
  489. package/dist/ui/assets/AnnotatedAttachmentWorkspace-BaS2VwIr.css +1 -0
  490. package/dist/ui/assets/AnnotatedAttachmentWorkspace-jKUVo-PJ.js +3 -0
  491. package/dist/ui/assets/DocumentWorkspace-C_8T8oz-.css +1 -0
  492. package/dist/ui/assets/DocumentWorkspace-DuQa-uIC.js +250 -0
  493. package/dist/ui/assets/InitiativesModule-C8Pi2VTk.js +1 -0
  494. package/dist/ui/assets/PlansPage-B6BDECSi.js +1 -0
  495. package/dist/ui/assets/PlansPage-BlVC_lRq.css +1 -0
  496. package/dist/ui/assets/TaskSettings-BwB9NtmJ.css +1 -0
  497. package/dist/ui/assets/TaskSettings-DUJgRTPU.js +8 -0
  498. package/dist/ui/assets/WorkflowsModule-b6TLuHwJ.js +5 -0
  499. package/dist/ui/assets/index-BiiF1cLQ.css +1 -0
  500. package/dist/ui/assets/index-xBWLPOEb.js +6 -0
  501. package/dist/ui/assets/vendor-dnd-DRzYolkg.js +5 -0
  502. package/dist/ui/assets/{vendor-icons-ZFG3SGwo.js → vendor-icons-QZyhEwgT.js} +1 -1
  503. package/dist/ui/assets/{vendor-markdown-CKYkQHfj.js → vendor-markdown-BUxTU7dS.js} +1 -1
  504. package/dist/ui/assets/vendor-react-CKJs5o3c.js +61 -0
  505. package/dist/ui/assets/vendor-router-BbWMxlnO.js +3 -0
  506. package/dist/ui/branding/logos/logo.png +0 -0
  507. package/dist/ui/branding/logos/logo_dark.svg +27 -0
  508. package/dist/ui/branding/logos/logo_favicon.svg +35 -0
  509. package/dist/ui/branding/logos/logo_light.svg +27 -0
  510. package/dist/ui/favicon/apple-touch-icon.png +0 -0
  511. package/dist/ui/favicon/archive/phoenix/apple-touch-icon.png +0 -0
  512. package/dist/ui/favicon/archive/phoenix/favicon.ico +0 -0
  513. package/dist/ui/favicon/archive/phoenix/site.webmanifest +1 -0
  514. package/dist/ui/favicon/favicon-96x96.png +0 -0
  515. package/dist/ui/favicon/favicon.ico +0 -0
  516. package/dist/ui/favicon/favicon.svg +17 -0
  517. package/dist/ui/favicon/site.webmanifest +21 -1
  518. package/dist/ui/favicon/web-app-manifest-192x192.png +0 -0
  519. package/dist/ui/favicon/web-app-manifest-512x512.png +0 -0
  520. package/dist/ui/index.html +10 -7
  521. package/dist/ui/product/screen_01.png +0 -0
  522. package/dist/ui/product/screen_02.png +0 -0
  523. package/dist/ui/product/screen_03.png +0 -0
  524. package/dist/utils/annotatedAttachments.d.ts +20 -0
  525. package/dist/utils/annotatedAttachments.js +74 -0
  526. package/dist/utils/annotatedAttachments.test.d.ts +1 -0
  527. package/dist/utils/annotatedAttachments.test.js +108 -0
  528. package/dist/utils/assignees.d.ts +26 -0
  529. package/dist/utils/assignees.js +132 -0
  530. package/dist/utils/canonicalAssetKind.d.ts +16 -0
  531. package/dist/utils/canonicalAssetKind.js +39 -0
  532. package/dist/utils/canonicalAssetKind.test.d.ts +1 -0
  533. package/dist/utils/canonicalAssetKind.test.js +24 -0
  534. package/dist/utils/coalescedRefresh.d.ts +5 -0
  535. package/dist/utils/coalescedRefresh.js +16 -0
  536. package/dist/utils/coalescedRefresh.test.d.ts +1 -0
  537. package/dist/utils/coalescedRefresh.test.js +30 -0
  538. package/dist/utils/constants.d.ts +16 -3
  539. package/dist/utils/constants.icons.test.js +2 -1
  540. package/dist/utils/constants.js +70 -13
  541. package/dist/utils/contextAssetEvents.d.ts +7 -0
  542. package/dist/utils/contextAssetEvents.js +6 -0
  543. package/dist/utils/contextFiles.d.ts +14 -3
  544. package/dist/utils/contextFiles.js +40 -8
  545. package/dist/utils/documentManagerApi.d.ts +6 -0
  546. package/dist/utils/documentManagerApi.js +19 -0
  547. package/dist/utils/documentNames.d.ts +24 -0
  548. package/dist/utils/documentNames.js +91 -0
  549. package/dist/utils/documentReferences.d.ts +9 -0
  550. package/dist/utils/documentReferences.js +11 -0
  551. package/dist/utils/entityReferences.d.ts +9 -0
  552. package/dist/utils/entityReferences.js +32 -0
  553. package/dist/utils/imageReferences.d.ts +9 -0
  554. package/dist/utils/imageReferences.js +11 -0
  555. package/dist/utils/planParser.d.ts +2 -2
  556. package/dist/utils/planParser.js +11 -11
  557. package/dist/utils/planParser.test.d.ts +1 -0
  558. package/dist/{__tests__ → utils}/planParser.test.js +22 -22
  559. package/dist/utils/planningReferences.d.ts +17 -0
  560. package/dist/utils/planningReferences.js +30 -0
  561. package/dist/utils/planningReferences.test.d.ts +1 -0
  562. package/dist/utils/planningReferences.test.js +17 -0
  563. package/dist/utils/taskActivity.d.ts +9 -0
  564. package/dist/utils/taskActivity.js +147 -0
  565. package/dist/utils/taskActivity.test.d.ts +1 -0
  566. package/dist/utils/taskActivity.test.js +34 -0
  567. package/dist/utils/taskDraftDefaults.d.ts +21 -0
  568. package/dist/utils/taskDraftDefaults.js +40 -0
  569. package/dist/utils/taskDraftDefaults.test.d.ts +1 -0
  570. package/dist/utils/taskDraftDefaults.test.js +34 -0
  571. package/dist/utils/taskNormalization.d.ts +25 -0
  572. package/dist/utils/taskNormalization.js +161 -0
  573. package/dist/utils/taskNormalization.test.d.ts +1 -0
  574. package/dist/utils/taskNormalization.test.js +158 -0
  575. package/dist/utils/taskReferences.d.ts +5 -0
  576. package/dist/utils/taskReferences.js +11 -0
  577. package/dist/utils/taskforceApiClient.d.ts +2 -0
  578. package/dist/utils/taskforceApiClient.js +101 -3
  579. package/dist/utils/taskforceApiClient.test.d.ts +1 -0
  580. package/dist/utils/taskforceApiClient.test.js +44 -0
  581. package/dist/utils/taxonomyFilterOptions.d.ts +2 -0
  582. package/dist/utils/taxonomyFilterOptions.js +17 -0
  583. package/dist/utils/taxonomyFormDefaults.d.ts +3 -0
  584. package/dist/utils/taxonomyFormDefaults.js +28 -0
  585. package/dist/utils/taxonomyFormDefaults.test.d.ts +1 -0
  586. package/dist/utils/taxonomyFormDefaults.test.js +63 -0
  587. package/dist/utils/taxonomyLifecycle.d.ts +3 -0
  588. package/dist/utils/taxonomyLifecycle.js +17 -0
  589. package/dist/utils/taxonomySorting.d.ts +7 -0
  590. package/dist/utils/taxonomySorting.js +74 -0
  591. package/dist/utils/theme.d.ts +15 -0
  592. package/dist/utils/theme.js +23 -0
  593. package/dist/utils/uiNotice.d.ts +7 -0
  594. package/dist/utils/uiNotice.js +6 -0
  595. package/dist/utils/uiNotice.test.d.ts +1 -0
  596. package/dist/utils/uiNotice.test.js +18 -0
  597. package/dist/utils/workspaceIdentity.d.ts +14 -0
  598. package/dist/utils/workspaceIdentity.js +21 -0
  599. package/dist/utils/workspaceIdentity.test.js +30 -1
  600. package/dist/utils/workspaceSyncPresentation.d.ts +20 -0
  601. package/dist/utils/workspaceSyncPresentation.js +21 -0
  602. package/dist/utils/workspaceSyncPresentation.test.d.ts +1 -0
  603. package/dist/utils/workspaceSyncPresentation.test.js +36 -0
  604. package/package.json +30 -23
  605. package/scripts/bootstrap-playwright-auth.mjs +155 -0
  606. package/scripts/check-compat-boundaries.mjs +41 -0
  607. package/scripts/check-env.ts +9 -2
  608. package/scripts/debug-login.mjs +32 -0
  609. package/scripts/deploy-prod.sh +41 -0
  610. package/scripts/deploy-staging.sh +23 -0
  611. package/scripts/migrate-planning-model.ts +233 -0
  612. package/scripts/migrate-task-data-assets.mjs +408 -0
  613. package/scripts/playwright-auth.sh +11 -0
  614. package/scripts/run-dev-proxy.sh +2 -0
  615. package/scripts/update-homebrew-formula.sh +2 -2
  616. package/scripts/with-esbuild.sh +11 -0
  617. package/src/resources/templates/WORKFLOW_V2_POLICY.md +1 -1
  618. package/src/resources/templates/workflow-sources/workflowDocs.mjs +62 -52
  619. package/src/resources/templates/workflows/collaborate.yaml +11 -5
  620. package/src/resources/templates/workflows/do.yaml +8 -2
  621. package/src/resources/templates/workflows/evaluate.yaml +13 -7
  622. package/src/resources/templates/workflows/execute.yaml +40 -23
  623. package/src/resources/templates/workflows/plan.yaml +15 -8
  624. package/src/resources/templates/workflows/review.yaml +14 -8
  625. package/dist/TaskforceScreenshot.d.ts +0 -11
  626. package/dist/TaskforceScreenshot.js +0 -113
  627. package/dist/compat/priorityCompat.d.ts +0 -2
  628. package/dist/compat/priorityCompat.js +0 -24
  629. package/dist/components/features/settings/TaxonomyManager 2.d.ts +0 -52
  630. package/dist/components/features/settings/TaxonomyManager 2.js +0 -75
  631. package/dist/components/task/TaskKanban 2.d.ts +0 -76
  632. package/dist/components/task/TaskKanban 2.js +0 -1004
  633. package/dist/components/task/TaskScreenshotSection.d.ts +0 -15
  634. package/dist/components/task/TaskScreenshotSection.js +0 -22
  635. package/dist/components/views/StandaloneLayout 2.d.ts +0 -8
  636. package/dist/components/views/StandaloneLayout 2.js +0 -1660
  637. package/dist/core/InitiativeTemplates.test.js +0 -50
  638. package/dist/core/ParentLifecycle.test.js +0 -98
  639. package/dist/migrations/clientMigrations.d.ts +0 -9
  640. package/dist/migrations/clientMigrations.js +0 -74
  641. package/dist/migrations/flags.d.ts +0 -6
  642. package/dist/migrations/flags.js +0 -8
  643. package/dist/migrations/taskMigrations.d.ts +0 -71
  644. package/dist/migrations/taskMigrations.js +0 -236
  645. package/dist/migrations/taskMigrations.test.js +0 -34
  646. package/dist/server/routes.billing.js +0 -991
  647. package/dist/server/routes.billing.test.js +0 -387
  648. package/dist/server/routes.sync.integration.test.js +0 -470
  649. package/dist/server/routes.sync.js +0 -1141
  650. package/dist/soak/syncSoakHarness.d.ts +0 -6
  651. package/dist/soak/syncSoakHarness.js +0 -10
  652. package/dist/ui/assets/index-0W5vyCpn.css +0 -1
  653. package/dist/ui/assets/index-MCZuNNfn.js +0 -23
  654. package/dist/ui/assets/logo_white_01-0Vx-iIIv.png +0 -0
  655. package/dist/ui/assets/vendor-dnd-BI1K77C1.js +0 -5
  656. package/dist/ui/assets/vendor-react-DdIDsh7f.js +0 -9
  657. package/dist/ui/assets/vendor-router-BtiNU7Dl.js +0 -3
  658. package/dist/utils/taskHierarchy.d.ts +0 -4
  659. package/dist/utils/taskHierarchy.js +0 -69
  660. package/dist/utils/taskHierarchy.test.js +0 -38
  661. package/dist/utils/taskParenting.d.ts +0 -3
  662. package/dist/utils/taskParenting.js +0 -24
  663. package/dist/utils/taskParenting.test.js +0 -21
  664. package/dist/utils/taskRelations.d.ts +0 -6
  665. package/dist/utils/taskRelations.js +0 -24
  666. package/dist/utils/taskRelations.test.js +0 -34
  667. package/scripts/check-compat-boundaries.js +0 -48
  668. /package/dist/{__tests__/planParser.test.d.ts → TaskforceCore.filter-persistence.test.d.ts} +0 -0
  669. /package/dist/{__tests__/releaseVersion.test.d.ts → TaskforceCore.routing.test.d.ts} +0 -0
  670. /package/dist/{__tests__/structuredCommentValidation.test.d.ts → annotatedAttachments/AnnotatedAttachmentSessionStore.test.d.ts} +0 -0
  671. /package/dist/{__tests__/structuredDocValidation.test.d.ts → annotatedAttachments/payload.test.d.ts} +0 -0
  672. /package/dist/{__tests__/templateEngine.test.d.ts → annotatedAttachments/types.js} +0 -0
  673. /package/dist/{__tests__/templates.test.d.ts → compat/workspaceSyncCompat.test.d.ts} +0 -0
  674. /package/dist/{__tests__/workflowDocumentFixtures.test.d.ts → components/features/AgentsModule.test.d.ts} +0 -0
  675. /package/dist/{__tests__/workflowExportMatrix.test.d.ts → components/features/AnnotatedAttachmentWorkspace.test.d.ts} +0 -0
  676. /package/dist/{__tests__/workflowExportSnapshots.test.d.ts → components/features/DocumentWorkspace.test.d.ts} +0 -0
  677. /package/dist/{__tests__/workflowGeneration.test.d.ts → components/features/settings/TaxonomyLibraryManager.test.d.ts} +0 -0
  678. /package/dist/{__tests__/workflowV2Policy.test.d.ts → components/task/TaskActionHeader.test.d.ts} +0 -0
  679. /package/dist/{core/InitiativeTemplates.test.d.ts → components/task/TaskKanban.planning-drop.test.d.ts} +0 -0
  680. /package/dist/{core/ParentLifecycle.test.d.ts → components/task/TaskStatusActions.test.d.ts} +0 -0
  681. /package/dist/{migrations/taskMigrations.test.d.ts → components/ui/TopNoticeLayer.test.d.ts} +0 -0
  682. /package/dist/{server/routes.billing.test.d.ts → components/views/AppShellHeader.test.d.ts} +0 -0
  683. /package/dist/{server/routes.sync.integration.test.d.ts → components/views/PlanComparisonPage.test.d.ts} +0 -0
  684. /package/dist/{utils/taskHierarchy.test.d.ts → components/views/chrome/WorkspaceChromeSections.test.d.ts} +0 -0
  685. /package/dist/{utils/taskParenting.test.d.ts → components/views/chrome/workspaceChrome.test.d.ts} +0 -0
  686. /package/dist/{utils/taskRelations.test.d.ts → components/views/panels/DocumentFilterToolbar.test.d.ts} +0 -0
  687. /package/dist/public/{android-chrome-192x192.png → archive/phoenix/android-chrome-192x192.png} +0 -0
  688. /package/dist/public/{android-chrome-512x512.png → archive/phoenix/android-chrome-512x512.png} +0 -0
  689. /package/dist/public/{favicon-16x16.png → archive/phoenix/favicon-16x16.png} +0 -0
  690. /package/dist/public/{favicon-32x32.png → archive/phoenix/favicon-32x32.png} +0 -0
  691. /package/dist/public/{favicon.png → archive/phoenix/favicon.png} +0 -0
  692. /package/dist/{__tests__ → services}/workflowExportSnapshots.test.js +0 -0
  693. /package/dist/{__tests__ → services}/workflowGeneration.test.js +0 -0
  694. /package/dist/ui/favicon/{android-chrome-192x192.png → archive/phoenix/android-chrome-192x192.png} +0 -0
  695. /package/dist/ui/favicon/{android-chrome-512x512.png → archive/phoenix/android-chrome-512x512.png} +0 -0
  696. /package/dist/ui/favicon/{favicon-16x16.png → archive/phoenix/favicon-16x16.png} +0 -0
  697. /package/dist/ui/favicon/{favicon-32x32.png → archive/phoenix/favicon-32x32.png} +0 -0
  698. /package/dist/ui/favicon/{favicon.png → archive/phoenix/favicon.png} +0 -0
@@ -1,75 +1,101 @@
1
1
  import { useCallback, useEffect, useRef, useState } from 'react';
2
2
  import { calculateWorkspaceRetryDelayMs } from '../sync/syncService';
3
- import { bootstrapPushWorkspaceSnapshot } from '../sync/cloudSyncApi';
4
- const WORKSPACE_PULL_LEASE_KEY_PREFIX = 'taskforce.sync.pullLease.v1';
5
- const WORKSPACE_PULL_COOLDOWN_KEY_PREFIX = 'taskforce.sync.pullCooldown.v1';
6
- const WORKSPACE_PULL_LEASE_MS = 30_000;
7
- const WORKSPACE_PULL_MIN_INTERVAL_MS = 10_000;
8
- const SYNC_DEBUG_LOG_KEY = 'taskforce.syncDebug.v1';
9
- function isSyncDebugLoggingEnabled() {
10
- if (typeof window === 'undefined')
11
- return false;
3
+ import { normalizeWorkspaceSyncStateCompat } from '../compat/workspaceSyncCompat';
4
+ import { createDefaultWorkspaceSyncState } from '../sync/workspaceSyncState';
5
+ const WORKSPACE_SYNC_LEASE_KEY_PREFIX = 'taskforce.sync.lease.v1';
6
+ const WORKSPACE_SYNC_LEASE_CHANNEL = 'taskforce.sync.lease.v1';
7
+ const WORKSPACE_SYNC_LEASE_HEARTBEAT_MS = 2500;
8
+ const WORKSPACE_SYNC_LEASE_TTL_MS = 9000;
9
+ function isValidWorkspaceKey(workspaceId) {
10
+ const workspaceKey = String(workspaceId || '').trim();
11
+ return workspaceKey.length > 0 && workspaceKey.toLowerCase() !== 'default';
12
+ }
13
+ function normalizeCursor(value) {
14
+ const normalized = String(value || '').trim();
15
+ return normalized.length > 0 ? normalized : null;
16
+ }
17
+ function getWorkspaceSyncLeaseKey(workspaceId) {
18
+ return `${WORKSPACE_SYNC_LEASE_KEY_PREFIX}.${workspaceId}`;
19
+ }
20
+ function parseWorkspaceSyncLeaseRecord(raw) {
21
+ if (!raw)
22
+ return null;
12
23
  try {
13
- const raw = String(window.localStorage.getItem(SYNC_DEBUG_LOG_KEY) || '').trim().toLowerCase();
14
- return raw === '1' || raw === 'true' || raw === 'on' || raw === 'yes';
24
+ const parsed = JSON.parse(raw);
25
+ const ownerId = String(parsed?.ownerId || '').trim();
26
+ const workspaceId = String(parsed?.workspaceId || '').trim();
27
+ const operation = String(parsed?.operation || '').trim();
28
+ const heartbeatAt = String(parsed?.heartbeatAt || '').trim();
29
+ const expiresAt = String(parsed?.expiresAt || '').trim();
30
+ if (!ownerId || !workspaceId || !heartbeatAt || !expiresAt)
31
+ return null;
32
+ if (operation !== 'pull' && operation !== 'push' && operation !== 'repair')
33
+ return null;
34
+ return { ownerId, workspaceId, operation, heartbeatAt, expiresAt };
15
35
  }
16
36
  catch {
17
- return false;
37
+ return null;
18
38
  }
19
39
  }
20
- function logSyncDebug(event, details) {
21
- if (!isSyncDebugLoggingEnabled())
22
- return;
23
- const payload = details && typeof details === 'object' ? details : {};
24
- console.info('[Taskforce Sync]', event, payload);
25
- }
26
- function getWorkspacePullLeaseStorageKey(workspaceId) {
27
- return `${WORKSPACE_PULL_LEASE_KEY_PREFIX}.${workspaceId}`;
40
+ function createWorkspaceSyncLeaseRecord(ownerId, workspaceId, operation, nowMs) {
41
+ return {
42
+ ownerId,
43
+ workspaceId,
44
+ operation,
45
+ heartbeatAt: new Date(nowMs).toISOString(),
46
+ expiresAt: new Date(nowMs + WORKSPACE_SYNC_LEASE_TTL_MS).toISOString()
47
+ };
28
48
  }
29
- function getWorkspacePullCooldownStorageKey(workspaceId) {
30
- return `${WORKSPACE_PULL_COOLDOWN_KEY_PREFIX}.${workspaceId}`;
49
+ function isLeaseExpired(record, nowMs = Date.now()) {
50
+ if (!record)
51
+ return true;
52
+ const expiresAtMs = Date.parse(record.expiresAt);
53
+ return !Number.isFinite(expiresAtMs) || expiresAtMs <= nowMs;
31
54
  }
32
- function isValidWorkspaceKey(workspaceId) {
33
- const workspaceKey = String(workspaceId || '').trim();
34
- return workspaceKey.length > 0 && workspaceKey.toLowerCase() !== 'default';
55
+ function buildWorkspaceSyncStatePatch(current, patch) {
56
+ const next = {
57
+ ...current,
58
+ ...patch,
59
+ version: 2,
60
+ phase: patch.phase || current.phase,
61
+ pullCursor: patch.pullCursor === undefined ? current.pullCursor : normalizeCursor(patch.pullCursor),
62
+ lastPullAt: patch.lastPullAt === undefined ? current.lastPullAt : normalizeCursor(patch.lastPullAt),
63
+ lastPushAt: patch.lastPushAt === undefined ? current.lastPushAt : normalizeCursor(patch.lastPushAt),
64
+ lastSyncedAt: patch.lastSyncedAt === undefined ? current.lastSyncedAt : normalizeCursor(patch.lastSyncedAt),
65
+ lastErrorMessage: patch.lastErrorMessage === undefined ? current.lastErrorMessage : (patch.lastErrorMessage ?? null)
66
+ };
67
+ if (!next.enabled) {
68
+ next.phase = 'idle';
69
+ next.pullCursor = null;
70
+ }
71
+ return next;
35
72
  }
36
73
  export function useWorkspaceSyncController(input) {
37
- const { currentWorkspaceId, setWorkspaceSyncReady, setWorkspaceCloudHydrated, setWorkspaceCloudSyncEnabled, setWorkspaceSyncSourceOfTruth, setWorkspaceSyncOnboardingCompleted, setUserGlobalLastSyncedAt, setWorkspaceLastPullAt, setWorkspaceLastPushAt } = input;
74
+ const { currentWorkspaceId, setWorkspaceCloudSyncEnabled, setWorkspaceSyncPhase, setWorkspaceLastPullAt, setWorkspaceLastPushAt, setWorkspaceLastErrorMessage } = input;
38
75
  const [workspaceRetryAt, setWorkspaceRetryAt] = useState(null);
39
- const [workspaceBootstrapSyncInProgress, setWorkspaceBootstrapSyncInProgress] = useState(false);
40
- const [workspaceBootstrapSyncPages, setWorkspaceBootstrapSyncPages] = useState(0);
41
- const [workspaceBootstrapSyncAppliedChanges, setWorkspaceBootstrapSyncAppliedChanges] = useState(0);
42
- const [workspaceSyncFailureCount, setWorkspaceSyncFailureCount] = useState(0);
43
- const [workspaceSyncRetryScheduledCount, setWorkspaceSyncRetryScheduledCount] = useState(0);
44
- const [workspaceSyncAuthFailureCount, setWorkspaceSyncAuthFailureCount] = useState(0);
45
- const [workspaceSyncLastFailureSource, setWorkspaceSyncLastFailureSource] = useState(null);
46
- const [workspaceSyncLastFailureStatusCode, setWorkspaceSyncLastFailureStatusCode] = useState(null);
47
- const workspacePushInFlightRef = useRef(false);
48
- const workspacePullInFlightRef = useRef(false);
49
76
  const workspaceRetryTimerRef = useRef(null);
50
77
  const workspaceRetryAtMsRef = useRef(null);
51
78
  const workspaceRetryAttemptRef = useRef(0);
79
+ // Current product support is one active syncing local window per workspace.
80
+ // These refs guard same-window reentry, while the lease helpers below
81
+ // coordinate sync ownership across local windows on the same machine.
82
+ const workspacePushInFlightRef = useRef(false);
83
+ const workspacePullInFlightRef = useRef(false);
52
84
  const workspaceLastPushedSignatureRef = useRef('');
53
85
  const workspacePendingSignatureRef = useRef('');
54
86
  const workspaceLastPushedTaskIdsRef = useRef(new Set());
55
87
  const workspaceDeletedTaskIdsRef = useRef(new Set());
56
88
  const workspacePullCursorRef = useRef(null);
57
- const workspacePullBootstrapDoneRef = useRef(false);
58
- const workspaceBackfillForcedRef = useRef(new Set());
59
- const workspaceSyncReadyRef = useRef(new Set());
60
- const workspaceCloudHydratedRef = useRef(new Set());
61
- const workspaceSyncStateReadCountRef = useRef(0);
62
- const workspacePullLeaseOwnerRef = useRef('');
63
- const activeLockWorkspaceIdRef = useRef(null);
64
- const activeLockAbortControllerRef = useRef(null);
65
- const onFailureRecordedRef = useRef(input.onFailureRecorded);
66
- useEffect(() => {
67
- onFailureRecordedRef.current = input.onFailureRecorded;
68
- }, [input.onFailureRecorded]);
69
- if (!workspacePullLeaseOwnerRef.current) {
89
+ const workspaceSyncStateRef = useRef(createDefaultWorkspaceSyncState());
90
+ const workspaceSyncLeaseOwnerIdRef = useRef('');
91
+ const workspaceSyncLeaseWorkspaceRef = useRef(null);
92
+ const workspaceSyncLeaseOperationRef = useRef(null);
93
+ const workspaceSyncLeaseHeartbeatTimerRef = useRef(null);
94
+ const workspaceSyncLeaseChannelRef = useRef(null);
95
+ if (!workspaceSyncLeaseOwnerIdRef.current) {
70
96
  const now = Date.now().toString(36);
71
97
  const rand = Math.random().toString(36).slice(2, 10);
72
- workspacePullLeaseOwnerRef.current = `pull-${now}-${rand}`;
98
+ workspaceSyncLeaseOwnerIdRef.current = `sync-lease-${now}-${rand}`;
73
99
  }
74
100
  const clearWorkspaceRetry = useCallback(() => {
75
101
  workspaceRetryAttemptRef.current = 0;
@@ -80,35 +106,19 @@ export function useWorkspaceSyncController(input) {
80
106
  }
81
107
  setWorkspaceRetryAt(null);
82
108
  }, []);
83
- const scheduleWorkspacePullRetry = useCallback((invokePull, options) => {
109
+ const scheduleWorkspaceRetry = useCallback((invokeSync, options) => {
84
110
  if (typeof window === 'undefined')
85
111
  return;
86
- setWorkspaceSyncRetryScheduledCount((prev) => prev + 1);
87
- const attempt = workspaceRetryAttemptRef.current + 1;
88
- workspaceRetryAttemptRef.current = attempt;
89
- const computedDelayMs = calculateWorkspaceRetryDelayMs(attempt);
112
+ const nextAttempt = Math.max(1, workspaceRetryAttemptRef.current + 1);
113
+ workspaceRetryAttemptRef.current = nextAttempt;
114
+ const computedDelayMs = calculateWorkspaceRetryDelayMs(nextAttempt);
90
115
  const explicitDelayMs = Number(options?.minDelayMs);
91
116
  const delayMs = Number.isFinite(explicitDelayMs) && explicitDelayMs > 0
92
117
  ? Math.max(computedDelayMs, Math.floor(explicitDelayMs))
93
118
  : computedDelayMs;
94
119
  const retryAtMs = Date.now() + delayMs;
95
- const retryAtIso = new Date(Date.now() + delayMs).toISOString();
96
- const workspaceKey = String(options?.workspaceId || '').trim();
97
- if (workspaceKey) {
98
- try {
99
- const cooldownKey = getWorkspacePullCooldownStorageKey(workspaceKey);
100
- const raw = window.localStorage.getItem(cooldownKey);
101
- const parsed = raw ? JSON.parse(raw) : null;
102
- const existingNextAt = Number(parsed?.nextAllowedAt || 0);
103
- const nextAllowedAt = Math.max(existingNextAt, retryAtMs);
104
- window.localStorage.setItem(cooldownKey, JSON.stringify({ nextAllowedAt }));
105
- }
106
- catch {
107
- // best-effort only
108
- }
109
- }
110
120
  workspaceRetryAtMsRef.current = retryAtMs;
111
- setWorkspaceRetryAt(retryAtIso);
121
+ setWorkspaceRetryAt(new Date(retryAtMs).toISOString());
112
122
  if (workspaceRetryTimerRef.current !== null) {
113
123
  window.clearTimeout(workspaceRetryTimerRef.current);
114
124
  }
@@ -116,461 +126,276 @@ export function useWorkspaceSyncController(input) {
116
126
  workspaceRetryTimerRef.current = null;
117
127
  workspaceRetryAtMsRef.current = null;
118
128
  setWorkspaceRetryAt(null);
119
- if (workspaceKey) {
120
- try {
121
- const cooldownKey = getWorkspacePullCooldownStorageKey(workspaceKey);
122
- const raw = window.localStorage.getItem(cooldownKey);
123
- const parsed = raw ? JSON.parse(raw) : null;
124
- const nextAllowedAt = Number(parsed?.nextAllowedAt || 0);
125
- if (Number.isFinite(nextAllowedAt) && nextAllowedAt <= retryAtMs) {
126
- window.localStorage.setItem(cooldownKey, JSON.stringify({ nextAllowedAt: Date.now() - 1 }));
127
- }
128
- }
129
- catch {
130
- // best-effort only
131
- }
132
- }
133
- void invokePull();
129
+ void invokeSync();
134
130
  }, delayMs);
135
131
  }, []);
136
- const isWorkspacePullRetryPending = useCallback(() => {
132
+ const isWorkspaceRetryPending = useCallback(() => {
137
133
  const retryAtMs = workspaceRetryAtMsRef.current;
138
134
  return typeof retryAtMs === 'number' && Number.isFinite(retryAtMs) && retryAtMs > Date.now();
139
135
  }, []);
140
- const isWorkspacePullCooldownActive = useCallback((workspaceId) => {
136
+ const readWorkspaceSyncLease = useCallback((workspaceId) => {
141
137
  if (typeof window === 'undefined')
142
- return false;
138
+ return null;
143
139
  const workspaceKey = String(workspaceId || '').trim();
144
- if (!workspaceKey)
145
- return false;
146
- try {
147
- const raw = window.localStorage.getItem(getWorkspacePullCooldownStorageKey(workspaceKey));
148
- const parsed = raw ? JSON.parse(raw) : null;
149
- const nextAllowedAt = Number(parsed?.nextAllowedAt || 0);
150
- return Number.isFinite(nextAllowedAt) && nextAllowedAt > Date.now();
151
- }
152
- catch {
153
- return false;
154
- }
140
+ if (!isValidWorkspaceKey(workspaceKey))
141
+ return null;
142
+ return parseWorkspaceSyncLeaseRecord(window.localStorage.getItem(getWorkspaceSyncLeaseKey(workspaceKey)));
155
143
  }, []);
156
- const markWorkspacePullCooldown = useCallback((workspaceId, minDelayMs) => {
157
- if (typeof window === 'undefined')
158
- return;
144
+ const broadcastWorkspaceSyncLeaseUpdate = useCallback((workspaceId) => {
159
145
  const workspaceKey = String(workspaceId || '').trim();
160
146
  if (!workspaceKey)
161
147
  return;
162
148
  try {
163
- const cooldownKey = getWorkspacePullCooldownStorageKey(workspaceKey);
164
- const raw = window.localStorage.getItem(cooldownKey);
165
- const parsed = raw ? JSON.parse(raw) : null;
166
- const existingNextAt = Number(parsed?.nextAllowedAt || 0);
167
- const explicitDelayMs = Number(minDelayMs);
168
- const baselineDelay = Number.isFinite(explicitDelayMs) && explicitDelayMs > 0
169
- ? Math.max(WORKSPACE_PULL_MIN_INTERVAL_MS, Math.floor(explicitDelayMs))
170
- : WORKSPACE_PULL_MIN_INTERVAL_MS;
171
- const nextAllowedAt = Math.max(existingNextAt, Date.now() + baselineDelay);
172
- window.localStorage.setItem(cooldownKey, JSON.stringify({ nextAllowedAt }));
149
+ workspaceSyncLeaseChannelRef.current?.postMessage({ workspaceId: workspaceKey });
173
150
  }
174
151
  catch {
175
152
  // best-effort only
176
153
  }
177
154
  }, []);
178
- const tryAcquireWorkspacePullLease = useCallback(async (workspaceId) => {
155
+ const writeWorkspaceSyncLease = useCallback((workspaceId, operation) => {
156
+ if (typeof window === 'undefined')
157
+ return null;
179
158
  const workspaceKey = String(workspaceId || '').trim();
180
- if (!workspaceKey)
181
- return true;
182
- const fallbackAcquire = () => {
183
- if (typeof window === 'undefined')
184
- return true;
185
- try {
186
- const leaseKey = getWorkspacePullLeaseStorageKey(workspaceKey);
187
- const ownerId = workspacePullLeaseOwnerRef.current;
188
- const now = Date.now();
189
- const raw = window.localStorage.getItem(leaseKey);
190
- const parsed = raw ? JSON.parse(raw) : null;
191
- const existingOwner = typeof parsed?.owner === 'string' ? parsed.owner : '';
192
- const existingExpiresAt = Number(parsed?.expiresAt || 0);
193
- const leaseActive = Number.isFinite(existingExpiresAt) && existingExpiresAt > now;
194
- if (leaseActive && existingOwner && existingOwner !== ownerId)
195
- return false;
196
- const nextLease = {
197
- owner: ownerId,
198
- acquiredAt: now,
199
- expiresAt: now + WORKSPACE_PULL_LEASE_MS
200
- };
201
- window.localStorage.setItem(leaseKey, JSON.stringify(nextLease));
202
- const verifyRaw = window.localStorage.getItem(leaseKey);
203
- const verify = verifyRaw ? JSON.parse(verifyRaw) : null;
204
- return verify?.owner === ownerId;
205
- }
206
- catch {
207
- return true;
208
- }
209
- };
210
- if (typeof window === 'undefined' || typeof navigator === 'undefined' || !navigator.locks) {
211
- return fallbackAcquire();
212
- }
213
- if (activeLockAbortControllerRef.current) {
214
- return activeLockWorkspaceIdRef.current === workspaceKey; // Already holding the lock for this workspace
215
- }
216
- const lockName = `taskforce.sync.pullLock.${workspaceKey}`;
217
- const controller = new AbortController();
159
+ if (!isValidWorkspaceKey(workspaceKey))
160
+ return null;
161
+ const record = createWorkspaceSyncLeaseRecord(workspaceSyncLeaseOwnerIdRef.current, workspaceKey, operation, Date.now());
218
162
  try {
219
- const acquired = await new Promise((resolve) => {
220
- navigator.locks.request(lockName, { mode: 'exclusive', ifAvailable: true, signal: controller.signal }, async (lock) => {
221
- if (!lock) {
222
- resolve(false);
223
- return;
224
- }
225
- activeLockAbortControllerRef.current = controller;
226
- activeLockWorkspaceIdRef.current = workspaceKey;
227
- resolve(true);
228
- // Hold the lock indefinitely until aborted
229
- return new Promise(() => { });
230
- }).catch(() => {
231
- resolve(false);
232
- });
233
- });
234
- return acquired;
163
+ window.localStorage.setItem(getWorkspaceSyncLeaseKey(workspaceKey), JSON.stringify(record));
235
164
  }
236
165
  catch {
237
- return fallbackAcquire();
166
+ return null;
167
+ }
168
+ broadcastWorkspaceSyncLeaseUpdate(workspaceKey);
169
+ return record;
170
+ }, [broadcastWorkspaceSyncLeaseUpdate]);
171
+ const stopWorkspaceSyncLeaseHeartbeat = useCallback(() => {
172
+ if (workspaceSyncLeaseHeartbeatTimerRef.current !== null && typeof window !== 'undefined') {
173
+ window.clearInterval(workspaceSyncLeaseHeartbeatTimerRef.current);
174
+ workspaceSyncLeaseHeartbeatTimerRef.current = null;
238
175
  }
239
176
  }, []);
240
- const releaseWorkspacePullLease = useCallback((workspaceId) => {
241
- const workspaceKey = String(workspaceId || '').trim();
242
- if (workspaceKey
243
- && activeLockWorkspaceIdRef.current
244
- && activeLockWorkspaceIdRef.current !== workspaceKey) {
177
+ const releaseWorkspaceSyncLease = useCallback((workspaceId, options) => {
178
+ if (typeof window === 'undefined')
245
179
  return;
246
- }
247
- if (activeLockAbortControllerRef.current) {
248
- activeLockAbortControllerRef.current.abort();
249
- activeLockAbortControllerRef.current = null;
250
- }
251
- activeLockWorkspaceIdRef.current = null;
252
- if (!workspaceKey || typeof window === 'undefined')
180
+ const workspaceKey = String(workspaceId || workspaceSyncLeaseWorkspaceRef.current || '').trim();
181
+ if (!workspaceKey)
253
182
  return;
183
+ const current = readWorkspaceSyncLease(workspaceKey);
184
+ const ownedByThisWindow = current?.ownerId === workspaceSyncLeaseOwnerIdRef.current;
185
+ if (!options?.force && current && !ownedByThisWindow)
186
+ return;
187
+ stopWorkspaceSyncLeaseHeartbeat();
254
188
  try {
255
- const leaseKey = getWorkspacePullLeaseStorageKey(workspaceKey);
256
- const raw = window.localStorage.getItem(leaseKey);
257
- const parsed = raw ? JSON.parse(raw) : null;
258
- if (parsed?.owner === workspacePullLeaseOwnerRef.current) {
259
- window.localStorage.removeItem(leaseKey);
260
- }
189
+ window.localStorage.removeItem(getWorkspaceSyncLeaseKey(workspaceKey));
261
190
  }
262
191
  catch {
263
192
  // best-effort only
264
193
  }
265
- }, []);
266
- const recordWorkspaceSyncFailure = useCallback((source, statusCode) => {
267
- const normalizedStatusCode = typeof statusCode === 'number' && Number.isFinite(statusCode) ? statusCode : null;
268
- setWorkspaceSyncFailureCount((prev) => prev + 1);
269
- setWorkspaceSyncLastFailureSource(source);
270
- setWorkspaceSyncLastFailureStatusCode(normalizedStatusCode);
271
- const onFailureRecorded = onFailureRecordedRef.current;
272
- if (onFailureRecorded)
273
- onFailureRecorded(source, normalizedStatusCode);
274
- }, []);
275
- const incrementWorkspaceSyncAuthFailure = useCallback(() => {
276
- setWorkspaceSyncAuthFailureCount((prev) => prev + 1);
277
- }, []);
278
- const persistWorkspaceSyncPatch = useCallback(async (patch) => {
279
- if (!isValidWorkspaceKey(currentWorkspaceId))
194
+ workspaceSyncLeaseWorkspaceRef.current = null;
195
+ workspaceSyncLeaseOperationRef.current = null;
196
+ broadcastWorkspaceSyncLeaseUpdate(workspaceKey);
197
+ }, [broadcastWorkspaceSyncLeaseUpdate, readWorkspaceSyncLease, stopWorkspaceSyncLeaseHeartbeat]);
198
+ const startWorkspaceSyncLeaseHeartbeat = useCallback((workspaceId, operation) => {
199
+ if (typeof window === 'undefined')
280
200
  return;
281
- try {
282
- await fetch('/api/taskforce/ui-state', {
283
- method: 'POST',
284
- headers: { 'Content-Type': 'application/json' },
285
- credentials: 'include',
286
- body: JSON.stringify({
287
- workspaceId: currentWorkspaceId,
288
- stateKey: 'workspace-sync',
289
- patch: {
290
- ...patch,
291
- updatedAt: new Date().toISOString()
292
- }
293
- })
294
- });
201
+ stopWorkspaceSyncLeaseHeartbeat();
202
+ workspaceSyncLeaseHeartbeatTimerRef.current = window.setInterval(() => {
203
+ const workspaceKey = String(workspaceSyncLeaseWorkspaceRef.current || '').trim();
204
+ const activeOperation = workspaceSyncLeaseOperationRef.current;
205
+ if (!workspaceKey || !activeOperation) {
206
+ stopWorkspaceSyncLeaseHeartbeat();
207
+ return;
208
+ }
209
+ const current = readWorkspaceSyncLease(workspaceKey);
210
+ if (current?.ownerId !== workspaceSyncLeaseOwnerIdRef.current) {
211
+ stopWorkspaceSyncLeaseHeartbeat();
212
+ workspaceSyncLeaseWorkspaceRef.current = null;
213
+ workspaceSyncLeaseOperationRef.current = null;
214
+ return;
215
+ }
216
+ void writeWorkspaceSyncLease(workspaceKey, activeOperation);
217
+ }, WORKSPACE_SYNC_LEASE_HEARTBEAT_MS);
218
+ workspaceSyncLeaseWorkspaceRef.current = workspaceId;
219
+ workspaceSyncLeaseOperationRef.current = operation;
220
+ }, [readWorkspaceSyncLease, stopWorkspaceSyncLeaseHeartbeat, writeWorkspaceSyncLease]);
221
+ const acquireWorkspaceSyncLease = useCallback(async (workspaceId, operation) => {
222
+ if (typeof window === 'undefined')
223
+ return true;
224
+ const workspaceKey = String(workspaceId || '').trim();
225
+ if (!isValidWorkspaceKey(workspaceKey))
226
+ return false;
227
+ const current = readWorkspaceSyncLease(workspaceKey);
228
+ const ownedByThisWindow = current?.ownerId === workspaceSyncLeaseOwnerIdRef.current;
229
+ if (ownedByThisWindow) {
230
+ const refreshed = writeWorkspaceSyncLease(workspaceKey, operation);
231
+ if (!refreshed)
232
+ return false;
233
+ startWorkspaceSyncLeaseHeartbeat(workspaceKey, operation);
234
+ return true;
295
235
  }
296
- catch {
297
- // ignore persistence errors
236
+ if (current && !isLeaseExpired(current)) {
237
+ return false;
238
+ }
239
+ const written = writeWorkspaceSyncLease(workspaceKey, operation);
240
+ if (!written)
241
+ return false;
242
+ const confirmed = readWorkspaceSyncLease(workspaceKey);
243
+ if (!confirmed || confirmed.ownerId !== workspaceSyncLeaseOwnerIdRef.current) {
244
+ return false;
298
245
  }
299
- }, [currentWorkspaceId]);
246
+ startWorkspaceSyncLeaseHeartbeat(workspaceKey, operation);
247
+ return true;
248
+ }, [readWorkspaceSyncLease, startWorkspaceSyncLeaseHeartbeat, writeWorkspaceSyncLease]);
249
+ const forceClearWorkspaceSyncLease = useCallback((workspaceId) => {
250
+ releaseWorkspaceSyncLease(workspaceId, { force: true });
251
+ }, [releaseWorkspaceSyncLease]);
252
+ const applyWorkspaceSyncStateSnapshot = useCallback((nextState) => {
253
+ const current = workspaceSyncStateRef.current;
254
+ const next = buildWorkspaceSyncStatePatch(current, {
255
+ enabled: Boolean(nextState.enabled),
256
+ phase: nextState.phase || current.phase,
257
+ pullCursor: nextState.pullCursor,
258
+ lastPullAt: nextState.lastPullAt,
259
+ lastPushAt: nextState.lastPushAt,
260
+ lastSyncedAt: nextState.lastSyncedAt,
261
+ lastErrorMessage: nextState.lastErrorMessage
262
+ });
263
+ workspaceSyncStateRef.current = next;
264
+ workspacePullCursorRef.current = next.pullCursor;
265
+ setWorkspaceCloudSyncEnabled(next.enabled);
266
+ setWorkspaceSyncPhase(next.phase);
267
+ setWorkspaceLastPullAt(next.lastPullAt);
268
+ setWorkspaceLastPushAt(next.lastPushAt);
269
+ setWorkspaceLastErrorMessage(next.lastErrorMessage ?? null);
270
+ }, [
271
+ setWorkspaceCloudSyncEnabled,
272
+ setWorkspaceSyncPhase,
273
+ setWorkspaceLastPullAt,
274
+ setWorkspaceLastPushAt,
275
+ setWorkspaceLastErrorMessage
276
+ ]);
277
+ const persistWorkspaceSyncPatch = useCallback(async (patch) => {
278
+ const next = buildWorkspaceSyncStatePatch(workspaceSyncStateRef.current, patch);
279
+ workspaceSyncStateRef.current = next;
280
+ workspacePullCursorRef.current = next.pullCursor;
281
+ const res = await fetch('/api/taskforce/ui-state', {
282
+ method: 'POST',
283
+ headers: { 'Content-Type': 'application/json' },
284
+ credentials: 'include',
285
+ body: JSON.stringify({
286
+ workspaceId: currentWorkspaceId,
287
+ stateKey: 'workspace-sync',
288
+ patch: next
289
+ })
290
+ });
291
+ const payload = await res.json().catch(() => ({}));
292
+ if (!res.ok || payload?.success === false) {
293
+ throw new Error(payload?.error || `Failed to persist workspace sync state (${res.status})`);
294
+ }
295
+ applyWorkspaceSyncStateSnapshot(next);
296
+ return next;
297
+ }, [applyWorkspaceSyncStateSnapshot, currentWorkspaceId]);
300
298
  const loadWorkspaceSyncState = useCallback(async () => {
301
- const workspaceId = String(currentWorkspaceId || '').trim();
302
- if (!isValidWorkspaceKey(workspaceId)) {
303
- setWorkspaceCloudSyncEnabled(false);
304
- setWorkspaceSyncSourceOfTruth(null);
305
- setWorkspaceSyncOnboardingCompleted(false);
306
- workspacePullCursorRef.current = null;
307
- workspacePullBootstrapDoneRef.current = false;
308
- logSyncDebug('workspace_sync_state_read_skipped_invalid_workspace', { workspaceId });
299
+ if (!isValidWorkspaceKey(currentWorkspaceId)) {
300
+ const initialState = createDefaultWorkspaceSyncState();
301
+ workspaceSyncStateRef.current = initialState;
302
+ applyWorkspaceSyncStateSnapshot(initialState);
309
303
  return;
310
304
  }
311
- workspaceSyncStateReadCountRef.current += 1;
312
- const readCount = workspaceSyncStateReadCountRef.current;
313
305
  try {
314
- const res = await fetch(`/api/taskforce/ui-state?key=workspace-sync&workspaceId=${encodeURIComponent(workspaceId)}`, {
306
+ const res = await fetch(`/api/taskforce/ui-state?key=workspace-sync&workspaceId=${encodeURIComponent(currentWorkspaceId)}`, {
315
307
  method: 'GET',
316
308
  credentials: 'include'
317
309
  });
318
- if (!res.ok) {
319
- logSyncDebug('workspace_sync_state_read_failed', {
320
- workspaceId,
321
- readCount,
322
- status: res.status
323
- });
324
- if (res.status === 429) {
325
- logSyncDebug('workspace_sync_state_rate_limited', {
326
- workspaceId,
327
- readCount
328
- });
329
- }
310
+ if (!res.ok)
330
311
  return;
331
- }
332
312
  const data = await res.json().catch(() => ({}));
333
- const state = (data?.state && typeof data.state === 'object')
313
+ const normalized = normalizeWorkspaceSyncStateCompat(data?.state && typeof data.state === 'object'
334
314
  ? data.state
335
- : null;
336
- if (!state) {
337
- logSyncDebug('workspace_sync_state_read_empty', {
338
- workspaceId,
339
- readCount
340
- });
341
- return;
342
- }
343
- setWorkspaceCloudSyncEnabled(Boolean(state.cloudSyncEnabled));
344
- const source = String(state.sourceOfTruth || '').trim().toLowerCase();
345
- if (source === 'cloud' || source === 'local') {
346
- setWorkspaceSyncSourceOfTruth(source);
347
- }
348
- else {
349
- setWorkspaceSyncSourceOfTruth(null);
315
+ : null);
316
+ workspaceSyncStateRef.current = normalized.state;
317
+ applyWorkspaceSyncStateSnapshot(normalized.state);
318
+ if (normalized.changed) {
319
+ void persistWorkspaceSyncPatch(normalized.state);
350
320
  }
351
- setWorkspaceSyncOnboardingCompleted(Boolean(state.onboardingCompleted));
352
- const lastSyncedAt = typeof state.lastSyncedAt === 'string' ? state.lastSyncedAt : '';
353
- if (lastSyncedAt.trim().length > 0) {
354
- setUserGlobalLastSyncedAt(lastSyncedAt.trim());
355
- }
356
- const lastPullAt = typeof state.lastPullAt === 'string' ? state.lastPullAt : '';
357
- if (lastPullAt.trim().length > 0) {
358
- setWorkspaceLastPullAt(lastPullAt.trim());
359
- }
360
- const lastPushAt = typeof state.lastPushAt === 'string' ? state.lastPushAt : '';
361
- if (lastPushAt.trim().length > 0) {
362
- setWorkspaceLastPushAt(lastPushAt.trim());
363
- }
364
- const pullCursor = typeof state.pullCursor === 'string' ? state.pullCursor : '';
365
- const trimmedCursor = pullCursor.trim();
366
- workspacePullCursorRef.current = trimmedCursor.length > 0 ? trimmedCursor : null;
367
- // Only mark bootstrap done if we actually have a valid persisted cursor.
368
- // An empty cursor means the previous bootstrap was incomplete; let it re-run.
369
- workspacePullBootstrapDoneRef.current = trimmedCursor.length > 0;
370
- logSyncDebug('workspace_sync_state_read_ok', {
371
- workspaceId,
372
- readCount,
373
- sourceOfTruth: source === 'cloud' || source === 'local' ? source : null,
374
- cloudSyncEnabled: Boolean(state.cloudSyncEnabled)
375
- });
376
321
  }
377
322
  catch {
378
- logSyncDebug('workspace_sync_state_read_exception', {
379
- workspaceId,
380
- readCount
381
- });
382
- }
383
- }, [
384
- currentWorkspaceId,
385
- setWorkspaceCloudSyncEnabled,
386
- setWorkspaceSyncSourceOfTruth,
387
- setWorkspaceSyncOnboardingCompleted,
388
- setUserGlobalLastSyncedAt,
389
- setWorkspaceLastPullAt,
390
- setWorkspaceLastPushAt
391
- ]);
392
- const applyWorkspaceSyncStateSnapshot = useCallback((nextState) => {
393
- const enabled = Boolean(nextState.cloudSyncEnabled);
394
- setWorkspaceCloudSyncEnabled(enabled);
395
- const source = nextState.sourceOfTruth === 'cloud' || nextState.sourceOfTruth === 'local'
396
- ? nextState.sourceOfTruth
397
- : null;
398
- setWorkspaceSyncSourceOfTruth(source);
399
- setWorkspaceSyncOnboardingCompleted(Boolean(nextState.onboardingCompleted));
400
- if (typeof nextState.pullCursor === 'string') {
401
- const trimmed = nextState.pullCursor.trim();
402
- workspacePullCursorRef.current = trimmed.length > 0 ? trimmed : null;
323
+ // best-effort only; local runtime should continue
403
324
  }
404
- else if (nextState.pullCursor === null) {
405
- workspacePullCursorRef.current = null;
406
- }
407
- }, [
408
- setWorkspaceCloudSyncEnabled,
409
- setWorkspaceSyncSourceOfTruth,
410
- setWorkspaceSyncOnboardingCompleted
411
- ]);
325
+ }, [applyWorkspaceSyncStateSnapshot, currentWorkspaceId, persistWorkspaceSyncPatch]);
412
326
  const saveWorkspaceCloudSyncSettings = useCallback(async (nextState, deps) => {
413
327
  if (!isValidWorkspaceKey(currentWorkspaceId)) {
414
328
  return { success: false, error: 'Workspace setup is required before enabling sync.' };
415
329
  }
416
- const nextEnabled = Boolean(nextState.enabled);
417
- const nextSource = nextState.sourceOfTruth === 'cloud' || nextState.sourceOfTruth === 'local'
418
- ? nextState.sourceOfTruth
419
- : null;
420
- let resolvedSource = nextSource;
421
- // I6: when enabling sync, always start with onboardingCompleted=false so the
422
- // orchestrator can verify the first pull succeeds before marking it complete.
423
- // When disabling, preserve whatever the caller passes (usually the current value).
424
- const nextOnboardingCompleted = nextEnabled ? false : Boolean(nextState.onboardingCompleted);
425
330
  try {
426
- if (nextEnabled) {
427
- if (!deps.isAuthenticated) {
428
- return { success: false, error: 'Sign in is required before enabling workspace sync.' };
429
- }
430
- if (!deps.cloudAuthConfigured) {
431
- return { success: false, error: 'Cloud authentication endpoint is not configured.' };
432
- }
433
- const ensured = await deps.ensureCloudWorkspaceReadyForSync();
434
- if (!ensured.success) {
435
- return { success: false, error: ensured.error || 'Workspace sync handshake failed.' };
436
- }
437
- const shouldBootstrapLocal = nextSource === 'local'
438
- || (nextSource === null && ensured.provisioned === true);
439
- if (resolvedSource === null) {
440
- resolvedSource = shouldBootstrapLocal ? 'local' : 'cloud';
441
- }
442
- if (shouldBootstrapLocal) {
443
- const snapshot = await deps.fetchLocalWorkspaceSnapshot();
444
- if (snapshot.error) {
445
- return { success: false, error: snapshot.error };
446
- }
447
- const [taxonomiesRes, documentsRes] = await Promise.allSettled([
448
- fetch('/api/taskforce/taxonomies', { method: 'GET', credentials: 'include' })
449
- .then((r) => r.ok
450
- ? r.json().catch(() => ({}))
451
- : Promise.resolve({}))
452
- .catch(() => ({})),
453
- fetch('/api/taskforce/sync/workspace/documents', { method: 'GET', credentials: 'include' })
454
- .then((r) => r.ok
455
- ? r.json().catch(() => ({}))
456
- : Promise.resolve({}))
457
- .catch(() => ({}))
458
- ]);
459
- const taxonomies = taxonomiesRes.status === 'fulfilled' && Array.isArray(taxonomiesRes.value?.taxonomies)
460
- ? taxonomiesRes.value.taxonomies
461
- : undefined;
462
- const documents = documentsRes.status === 'fulfilled' && Array.isArray(documentsRes.value?.documents)
463
- ? documentsRes.value.documents
464
- .filter((doc) => {
465
- if (!doc || typeof doc !== 'object')
466
- return false;
467
- const candidate = doc;
468
- return typeof candidate.path === 'string'
469
- && typeof candidate.updatedAt === 'string'
470
- && typeof candidate.content === 'string';
471
- })
472
- : undefined;
473
- const bootstrapRes = await bootstrapPushWorkspaceSnapshot(deps.resolveCloudAuthUrl, {
474
- workspaceId: currentWorkspaceId,
475
- tasks: snapshot.tasks,
476
- archived: snapshot.archived,
477
- taxonomies,
478
- documents
479
- });
480
- if (!bootstrapRes.ok) {
481
- const data = (bootstrapRes.data && typeof bootstrapRes.data === 'object')
482
- ? bootstrapRes.data
483
- : {};
484
- return {
485
- success: false,
486
- error: String(data.error || `Workspace bootstrap push failed (${bootstrapRes.status})`)
487
- };
488
- }
489
- }
331
+ if (!nextState.enabled) {
332
+ await persistWorkspaceSyncPatch({
333
+ enabled: false,
334
+ phase: 'idle',
335
+ pullCursor: null
336
+ });
337
+ return { success: true };
338
+ }
339
+ if (!deps.isAuthenticated) {
340
+ return { success: false, error: 'Sign in is required before enabling workspace sync.' };
341
+ }
342
+ if (!deps.cloudAuthConfigured) {
343
+ return { success: false, error: 'Cloud authentication endpoint is not configured.' };
344
+ }
345
+ const ensured = await deps.ensureCloudWorkspaceReadyForSync();
346
+ if (!ensured.success) {
347
+ return { success: false, error: ensured.error || 'Workspace sync handshake failed.' };
490
348
  }
491
349
  await persistWorkspaceSyncPatch({
492
- cloudSyncEnabled: nextEnabled,
493
- sourceOfTruth: resolvedSource,
494
- onboardingCompleted: nextOnboardingCompleted
350
+ enabled: true,
351
+ phase: ensured.provisioned ? 'provision-local' : 'attach-cloud',
352
+ pullCursor: null,
353
+ lastPullAt: null,
354
+ lastPushAt: null,
355
+ lastSyncedAt: null
495
356
  });
496
- setWorkspaceCloudSyncEnabled(nextEnabled);
497
- setWorkspaceSyncSourceOfTruth(resolvedSource);
498
- setWorkspaceSyncOnboardingCompleted(nextOnboardingCompleted);
499
357
  return { success: true };
500
358
  }
501
359
  catch {
502
360
  return { success: false, error: 'Failed to save workspace sync settings.' };
503
361
  }
504
- }, [
505
- setWorkspaceCloudSyncEnabled,
506
- setWorkspaceSyncSourceOfTruth,
507
- setWorkspaceSyncOnboardingCompleted,
508
- persistWorkspaceSyncPatch
509
- ]);
362
+ }, [currentWorkspaceId, persistWorkspaceSyncPatch]);
510
363
  useEffect(() => {
511
364
  workspaceLastPushedSignatureRef.current = '';
512
365
  workspacePendingSignatureRef.current = '';
513
366
  workspaceLastPushedTaskIdsRef.current = new Set();
514
367
  workspaceDeletedTaskIdsRef.current = new Set();
515
368
  workspacePullCursorRef.current = null;
516
- workspacePullBootstrapDoneRef.current = false;
517
- workspaceSyncStateReadCountRef.current = 0;
518
- workspaceBackfillForcedRef.current.delete(currentWorkspaceId);
519
- workspaceSyncReadyRef.current.delete(currentWorkspaceId);
520
- workspaceCloudHydratedRef.current.delete(currentWorkspaceId);
521
- workspaceRetryAttemptRef.current = 0;
522
- workspaceRetryAtMsRef.current = null;
369
+ workspaceSyncStateRef.current = createDefaultWorkspaceSyncState();
523
370
  workspacePushInFlightRef.current = false;
524
371
  workspacePullInFlightRef.current = false;
525
- setWorkspaceSyncReady(false);
526
- setWorkspaceCloudHydrated(false);
527
- setWorkspaceSyncFailureCount(0);
528
- setWorkspaceSyncRetryScheduledCount(0);
529
- setWorkspaceSyncAuthFailureCount(0);
530
- setWorkspaceSyncLastFailureSource(null);
531
- setWorkspaceSyncLastFailureStatusCode(null);
532
- setWorkspaceBootstrapSyncInProgress(false);
533
- setWorkspaceBootstrapSyncPages(0);
534
- setWorkspaceBootstrapSyncAppliedChanges(0);
535
- if (workspaceRetryTimerRef.current !== null && typeof window !== 'undefined') {
536
- window.clearTimeout(workspaceRetryTimerRef.current);
537
- workspaceRetryTimerRef.current = null;
538
- }
539
- if (activeLockAbortControllerRef.current) {
540
- activeLockAbortControllerRef.current.abort();
541
- activeLockAbortControllerRef.current = null;
542
- }
543
- activeLockWorkspaceIdRef.current = null;
544
- setWorkspaceRetryAt(null);
545
- }, [currentWorkspaceId, setWorkspaceSyncReady, setWorkspaceCloudHydrated]);
372
+ releaseWorkspaceSyncLease();
373
+ clearWorkspaceRetry();
374
+ }, [clearWorkspaceRetry, currentWorkspaceId, releaseWorkspaceSyncLease]);
375
+ useEffect(() => {
376
+ if (typeof window === 'undefined' || typeof BroadcastChannel === 'undefined')
377
+ return;
378
+ const channel = new BroadcastChannel(WORKSPACE_SYNC_LEASE_CHANNEL);
379
+ workspaceSyncLeaseChannelRef.current = channel;
380
+ return () => {
381
+ channel.close();
382
+ if (workspaceSyncLeaseChannelRef.current === channel) {
383
+ workspaceSyncLeaseChannelRef.current = null;
384
+ }
385
+ };
386
+ }, []);
546
387
  useEffect(() => {
547
388
  return () => {
548
389
  if (workspaceRetryTimerRef.current !== null && typeof window !== 'undefined') {
549
390
  window.clearTimeout(workspaceRetryTimerRef.current);
550
391
  workspaceRetryTimerRef.current = null;
551
392
  }
552
- if (activeLockAbortControllerRef.current) {
553
- activeLockAbortControllerRef.current.abort();
554
- activeLockAbortControllerRef.current = null;
555
- }
556
- activeLockWorkspaceIdRef.current = null;
393
+ releaseWorkspaceSyncLease();
557
394
  };
558
- }, []);
395
+ }, [releaseWorkspaceSyncLease]);
559
396
  return {
560
397
  workspaceRetryAt,
561
- setWorkspaceRetryAt,
562
- isWorkspacePullRetryPending,
563
- workspaceBootstrapSyncInProgress,
564
- setWorkspaceBootstrapSyncInProgress,
565
- workspaceBootstrapSyncPages,
566
- setWorkspaceBootstrapSyncPages,
567
- workspaceBootstrapSyncAppliedChanges,
568
- setWorkspaceBootstrapSyncAppliedChanges,
569
- workspaceSyncFailureCount,
570
- workspaceSyncRetryScheduledCount,
571
- workspaceSyncAuthFailureCount,
572
- workspaceSyncLastFailureSource,
573
- workspaceSyncLastFailureStatusCode,
398
+ isWorkspaceRetryPending,
574
399
  workspacePushInFlightRef,
575
400
  workspacePullInFlightRef,
576
401
  workspaceLastPushedSignatureRef,
@@ -578,21 +403,15 @@ export function useWorkspaceSyncController(input) {
578
403
  workspaceLastPushedTaskIdsRef,
579
404
  workspaceDeletedTaskIdsRef,
580
405
  workspacePullCursorRef,
581
- workspacePullBootstrapDoneRef,
582
- workspaceBackfillForcedRef,
583
- workspaceSyncReadyRef,
584
- workspaceCloudHydratedRef,
585
406
  clearWorkspaceRetry,
586
- scheduleWorkspacePullRetry,
587
- isWorkspacePullCooldownActive,
588
- markWorkspacePullCooldown,
589
- tryAcquireWorkspacePullLease,
590
- releaseWorkspacePullLease,
591
- recordWorkspaceSyncFailure,
592
- incrementWorkspaceSyncAuthFailure,
407
+ scheduleWorkspaceRetry,
593
408
  persistWorkspaceSyncPatch,
594
409
  loadWorkspaceSyncState,
595
410
  applyWorkspaceSyncStateSnapshot,
596
- saveWorkspaceCloudSyncSettings
411
+ saveWorkspaceCloudSyncSettings,
412
+ acquireWorkspaceSyncLease,
413
+ releaseWorkspaceSyncLease,
414
+ forceClearWorkspaceSyncLease,
415
+ readWorkspaceSyncLease
597
416
  };
598
417
  }