@taskforcehq/taskforce 0.3.304 → 0.3.306

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 (383) hide show
  1. package/README.md +140 -247
  2. package/dist/Taskforce.module.css +295 -89
  3. package/dist/TaskforceCore.js +378 -111
  4. package/dist/TaskforceCore.test.js +1221 -107
  5. package/dist/assets/fonts/CourierPrime-Bold.woff2 +0 -0
  6. package/dist/assets/fonts/CourierPrime-BoldItalic.woff2 +0 -0
  7. package/dist/assets/fonts/CourierPrime-Italic.woff2 +0 -0
  8. package/dist/assets/fonts/CourierPrime-Regular.woff2 +0 -0
  9. package/dist/assets/fonts/Noir_medium.woff2 +0 -0
  10. package/dist/assets/fonts/Noir_regular.woff2 +0 -0
  11. package/dist/assets/fonts/RussoOne-Regular.woff2 +0 -0
  12. package/dist/assets/fonts/SpecialElite-Regular.woff2 +0 -0
  13. package/dist/compat/workspaceSyncCompat.js +52 -2
  14. package/dist/compat/workspaceSyncCompat.test.js +38 -1
  15. package/dist/components/context/ContextAttachmentManager.d.ts +14 -0
  16. package/dist/components/context/ContextAttachmentManager.js +549 -0
  17. package/dist/components/features/AgentsModule.d.ts +10 -1
  18. package/dist/components/features/AgentsModule.js +260 -15
  19. package/dist/components/features/AgentsModule.test.js +255 -5
  20. package/dist/components/features/DocumentIndex.d.ts +1 -1
  21. package/dist/components/features/DocumentIndex.js +1 -1
  22. package/dist/components/features/DocumentViewer.d.ts +6 -2
  23. package/dist/components/features/DocumentViewer.js +90 -10
  24. package/dist/components/features/DocumentWorkspace.d.ts +5 -22
  25. package/dist/components/features/DocumentWorkspace.js +12 -155
  26. package/dist/components/features/DocumentWorkspace.test.js +226 -6
  27. package/dist/components/features/TaskSettings.js +29 -3
  28. package/dist/components/features/TaskSettings.test.js +42 -1
  29. package/dist/components/features/documentWorkspaceModel.d.ts +24 -0
  30. package/dist/components/features/documentWorkspaceModel.js +57 -0
  31. package/dist/components/features/useDocumentWorkspaceController.d.ts +34 -0
  32. package/dist/components/features/useDocumentWorkspaceController.js +113 -0
  33. package/dist/components/task/TaskCard.js +19 -28
  34. package/dist/components/task/TaskCard.test.js +38 -3
  35. package/dist/components/task/TaskContextUpload.js +4 -526
  36. package/dist/components/task/TaskForm.d.ts +8 -8
  37. package/dist/components/task/TaskForm.js +362 -230
  38. package/dist/components/task/TaskForm.test.js +558 -381
  39. package/dist/components/task/TaskKanban.d.ts +2 -1
  40. package/dist/components/task/TaskKanban.js +96 -14
  41. package/dist/components/task/TaskKanban.test.js +36 -0
  42. package/dist/components/ui/EditableAvatarButton.d.ts +18 -0
  43. package/dist/components/ui/EditableAvatarButton.js +18 -0
  44. package/dist/components/views/PlanComparisonPage.d.ts +9 -1
  45. package/dist/components/views/PlanComparisonPage.js +70 -17
  46. package/dist/components/views/PlanComparisonPage.test.js +289 -41
  47. package/dist/components/views/PlansPage.js +239 -106
  48. package/dist/components/views/PlansPage.test.js +593 -42
  49. package/dist/components/views/StandaloneLayout.js +310 -554
  50. package/dist/components/views/panels/FilterToolbar.test.js +6 -4
  51. package/dist/components/views/panels/PlanningDrawer.d.ts +8 -1
  52. package/dist/components/views/panels/PlanningDrawer.js +18 -11
  53. package/dist/components/views/panels/PlanningDrawer.test.d.ts +1 -0
  54. package/dist/components/views/panels/PlanningDrawer.test.js +141 -0
  55. package/dist/components/views/planningScope.d.ts +20 -0
  56. package/dist/components/views/planningScope.js +25 -0
  57. package/dist/components/views/planningScope.test.d.ts +1 -0
  58. package/dist/components/views/planningScope.test.js +60 -0
  59. package/dist/components/views/standalone/modals/AccountHubModal.d.ts +27 -14
  60. package/dist/components/views/standalone/modals/AccountHubModal.js +87 -15
  61. package/dist/components/views/standalone/modals/AccountHubModal.test.js +42 -2
  62. package/dist/components/views/standalone/modals/AvatarImageManagerModal.d.ts +20 -0
  63. package/dist/components/views/standalone/modals/AvatarImageManagerModal.js +127 -0
  64. package/dist/components/views/standalone/modals/EditProfileModal.d.ts +2 -9
  65. package/dist/components/views/standalone/modals/EditProfileModal.js +3 -2
  66. package/dist/components/views/standalone/modals/SyncEnableWarningModal.d.ts +9 -0
  67. package/dist/components/views/standalone/modals/SyncEnableWarningModal.js +6 -0
  68. package/dist/components/views/standalone/modals/SyncEnableWarningModal.test.d.ts +1 -0
  69. package/dist/components/views/standalone/modals/SyncEnableWarningModal.test.js +24 -0
  70. package/dist/components/views/standalone/modals/SyncStatusModal.d.ts +2 -1
  71. package/dist/components/views/standalone/modals/SyncStatusModal.js +2 -2
  72. package/dist/config/envSchema.js +1 -1
  73. package/dist/core/AiProfileService.d.ts +45 -3
  74. package/dist/core/AiProfileService.js +774 -63
  75. package/dist/core/AiProfileService.test.js +22 -2
  76. package/dist/core/AiProfiles.test.js +761 -2
  77. package/dist/core/AttachmentLinkService.js +57 -15
  78. package/dist/core/AuthIdentityService.d.ts +107 -0
  79. package/dist/core/AuthIdentityService.js +284 -0
  80. package/dist/core/AuthTokenService.d.ts +4 -0
  81. package/dist/core/AuthTokenService.js +34 -6
  82. package/dist/core/AuthTokenService.test.d.ts +1 -0
  83. package/dist/core/AuthTokenService.test.js +78 -0
  84. package/dist/core/EntitlementsPolicy.test.js +77 -15
  85. package/dist/core/GlobalSettingsService.js +115 -6
  86. package/dist/core/PlanEntitlementService.d.ts +30 -3
  87. package/dist/core/PlanEntitlementService.js +454 -93
  88. package/dist/core/PlanFeatureCatalog.test.d.ts +1 -0
  89. package/dist/core/PlanFeatureCatalog.test.js +84 -0
  90. package/dist/core/PlanVersionPolicy.test.js +54 -28
  91. package/dist/core/PlanningEntities.test.js +52 -0
  92. package/dist/core/SignupMonetizationSettings.test.js +241 -44
  93. package/dist/core/SyncReconciliationService.js +2 -65
  94. package/dist/core/SystemAdmin.test.js +244 -88
  95. package/dist/core/TaskAttachmentsCanonical.test.js +51 -1
  96. package/dist/core/TaskTaxonomyValidation.test.js +53 -0
  97. package/dist/core/Taskforce.d.ts +228 -14
  98. package/dist/core/Taskforce.js +814 -201
  99. package/dist/core/Taskforce.listTasksSlim.test.d.ts +1 -0
  100. package/dist/core/Taskforce.listTasksSlim.test.js +91 -0
  101. package/dist/core/UserProfileAvatarDrafts.test.js +30 -3
  102. package/dist/core/WorkspaceLifecycleService.js +0 -5
  103. package/dist/core/WorkspacePermissions.test.js +25 -1
  104. package/dist/core/WorkspacePlanMode.test.js +128 -27
  105. package/dist/core/shared.d.ts +3 -1
  106. package/dist/core/shared.js +16 -1
  107. package/dist/core/types.d.ts +68 -2
  108. package/dist/hooks/auth/useTaskforceAuthBootstrap.js +26 -1
  109. package/dist/hooks/sync/auth.js +3 -1
  110. package/dist/hooks/sync/bootstrap.js +2 -0
  111. package/dist/hooks/sync/controlPlane.d.ts +37 -0
  112. package/dist/hooks/sync/controlPlane.js +78 -0
  113. package/dist/hooks/sync/controlPlane.test.d.ts +1 -0
  114. package/dist/hooks/sync/controlPlane.test.js +121 -0
  115. package/dist/hooks/sync/lifecyclePolicy.d.ts +45 -0
  116. package/dist/hooks/sync/lifecyclePolicy.js +93 -0
  117. package/dist/hooks/sync/lifecyclePolicy.test.d.ts +1 -0
  118. package/dist/hooks/sync/lifecyclePolicy.test.js +124 -0
  119. package/dist/hooks/sync/orchestratorShared.d.ts +10 -1
  120. package/dist/hooks/sync/orchestratorShared.js +68 -47
  121. package/dist/hooks/sync/orchestratorShared.test.js +50 -1
  122. package/dist/hooks/sync/pullLifecycle.d.ts +31 -0
  123. package/dist/hooks/sync/pullLifecycle.js +24 -0
  124. package/dist/hooks/sync/pullLifecycle.test.d.ts +1 -0
  125. package/dist/hooks/sync/pullLifecycle.test.js +80 -0
  126. package/dist/hooks/sync/recovery.d.ts +16 -2
  127. package/dist/hooks/sync/recovery.js +171 -53
  128. package/dist/hooks/sync/recovery.test.d.ts +1 -0
  129. package/dist/hooks/sync/recovery.test.js +292 -0
  130. package/dist/hooks/sync/transfers.d.ts +16 -3
  131. package/dist/hooks/sync/transfers.js +186 -65
  132. package/dist/hooks/sync/transfers.test.d.ts +1 -0
  133. package/dist/hooks/sync/transfers.test.js +396 -0
  134. package/dist/hooks/sync/useRecentSyncEvents.d.ts +21 -0
  135. package/dist/hooks/sync/useRecentSyncEvents.js +92 -0
  136. package/dist/hooks/sync/useRecentSyncEvents.test.d.ts +1 -0
  137. package/dist/hooks/sync/useRecentSyncEvents.test.js +124 -0
  138. package/dist/hooks/sync/useSyncStatusActions.d.ts +30 -0
  139. package/dist/hooks/sync/useSyncStatusActions.js +88 -0
  140. package/dist/hooks/sync/useSyncStatusActions.test.d.ts +1 -0
  141. package/dist/hooks/sync/useSyncStatusActions.test.js +133 -0
  142. package/dist/hooks/sync/useSyncStatusControls.d.ts +25 -0
  143. package/dist/hooks/sync/useSyncStatusControls.js +60 -0
  144. package/dist/hooks/sync/useSyncStatusControls.test.d.ts +1 -0
  145. package/dist/hooks/sync/useSyncStatusControls.test.js +88 -0
  146. package/dist/hooks/useSyncOrchestrator.aiProfiles.test.js +12 -0
  147. package/dist/hooks/useSyncOrchestrator.d.ts +16 -6
  148. package/dist/hooks/useSyncOrchestrator.js +424 -175
  149. package/dist/hooks/useSyncOrchestrator.retry-closure.test.js +487 -10
  150. package/dist/hooks/useTaskData.js +8 -3
  151. package/dist/hooks/useTaskData.test.js +45 -0
  152. package/dist/hooks/useTaskMutations.d.ts +2 -1
  153. package/dist/hooks/useTaskMutations.js +12 -1
  154. package/dist/hooks/useTaskMutations.test.js +30 -1
  155. package/dist/hooks/useTaskforce.d.ts +65 -4
  156. package/dist/hooks/useTaskforce.js +564 -243
  157. package/dist/hooks/useTaskforce.runtime-routing.test.d.ts +1 -0
  158. package/dist/hooks/useTaskforce.runtime-routing.test.js +152 -0
  159. package/dist/hooks/useTaskforce.sync-behavior.test.js +2454 -208
  160. package/dist/hooks/useWorkspaceSyncController.d.ts +4 -1
  161. package/dist/hooks/useWorkspaceSyncController.js +17 -2
  162. package/dist/hooks/useWorkspaceSyncController.test.js +1 -0
  163. package/dist/hooks/workspace/useTaskforceWorkspaceBootstrap.d.ts +16 -0
  164. package/dist/hooks/workspace/useTaskforceWorkspaceBootstrap.js +316 -35
  165. package/dist/localization/locales/en-US.d.ts +0 -1
  166. package/dist/localization/locales/en-US.js +0 -1
  167. package/dist/localization/locales/es-419.js +0 -1
  168. package/dist/localization/locales/pt-BR.js +0 -1
  169. package/dist/mcp/adminWorkspaceRegistrar.d.ts +2 -0
  170. package/dist/mcp/adminWorkspaceRegistrar.js +154 -0
  171. package/dist/mcp/collaborationRegistrar.d.ts +2 -0
  172. package/dist/mcp/collaborationRegistrar.js +71 -0
  173. package/dist/mcp/documentAssetRegistrar.d.ts +2 -0
  174. package/dist/mcp/documentAssetRegistrar.js +346 -0
  175. package/dist/mcp/runtime.d.ts +2 -0
  176. package/dist/mcp/runtime.js +2433 -3534
  177. package/dist/mcp/runtime.test.js +440 -2
  178. package/dist/mcp/taskPlanningRegistrar.d.ts +2 -0
  179. package/dist/mcp/taskPlanningRegistrar.js +418 -0
  180. package/dist/mcp/toolCatalog.d.ts +35 -0
  181. package/dist/mcp/toolCatalog.js +3 -0
  182. package/dist/migrations/taskSchemaMigrations.d.ts +1 -1
  183. package/dist/migrations/taskSchemaMigrations.js +171 -61
  184. package/dist/migrations/taskSchemaMigrations.test.js +15 -0
  185. package/dist/resources/templates/workflow-sources/workflowDocs.mjs +6 -6
  186. package/dist/resources/templates/workflows/collaborate.yaml +1 -1
  187. package/dist/resources/templates/workflows/evaluate.yaml +2 -2
  188. package/dist/resources/templates/workflows/plan.yaml +1 -1
  189. package/dist/resources/templates/workflows/review.yaml +2 -2
  190. package/dist/server/annotatedAttachmentsRoutes.test.js +3 -3
  191. package/dist/server/auth/providers/apple.d.ts +33 -0
  192. package/dist/server/auth/providers/apple.js +82 -0
  193. package/dist/server/auth/providers/appleClientSecret.d.ts +37 -0
  194. package/dist/server/auth/providers/appleClientSecret.js +65 -0
  195. package/dist/server/auth/providers/github.d.ts +26 -0
  196. package/dist/server/auth/providers/github.js +86 -0
  197. package/dist/server/auth/providers/google.d.ts +21 -0
  198. package/dist/server/auth/providers/google.js +56 -0
  199. package/dist/server/auth/providers/types.d.ts +21 -0
  200. package/dist/server/auth/providers/types.js +1 -0
  201. package/dist/server/auth.d.ts +2 -0
  202. package/dist/server/auth.js +6 -3
  203. package/dist/server/documentReviewRoutes.test.js +36 -3
  204. package/dist/server/index.cookieProxy.test.js +1 -0
  205. package/dist/server/index.d.ts +12 -0
  206. package/dist/server/index.js +120 -9
  207. package/dist/server/index.rateLimit.test.js +3 -0
  208. package/dist/server/index.test.js +106 -3
  209. package/dist/server/routes/admin.d.ts +4 -5
  210. package/dist/server/routes/admin.js +410 -80
  211. package/dist/server/routes/annotatedAttachments.d.ts +1 -1
  212. package/dist/server/routes/annotatedAttachments.js +1 -1
  213. package/dist/server/routes/auth.d.ts +16 -6
  214. package/dist/server/routes/auth.js +1015 -118
  215. package/dist/server/routes/authSupport.d.ts +30 -0
  216. package/dist/server/routes/authSupport.js +81 -0
  217. package/dist/server/routes/billing.d.ts +1 -1
  218. package/dist/server/routes/billing.js +276 -34
  219. package/dist/server/routes/billing.test.js +760 -52
  220. package/dist/server/routes/documentReviews.d.ts +1 -1
  221. package/dist/server/routes/documentReviews.js +1 -1
  222. package/dist/server/routes/documents.d.ts +5 -2
  223. package/dist/server/routes/documents.js +242 -74
  224. package/dist/server/routes/primitives.d.ts +11 -0
  225. package/dist/server/routes/primitives.js +73 -0
  226. package/dist/server/routes/resources.d.ts +1 -1
  227. package/dist/server/routes/resources.js +1 -1
  228. package/dist/server/routes/shared.d.ts +29 -3
  229. package/dist/server/routes/shared.js +69 -4
  230. package/dist/server/routes/sync.d.ts +1 -1
  231. package/dist/server/routes/sync.integration.test.js +437 -39
  232. package/dist/server/routes/sync.js +62 -606
  233. package/dist/server/routes/syncAuxRoutes.d.ts +15 -0
  234. package/dist/server/routes/syncAuxRoutes.js +91 -0
  235. package/dist/server/routes/syncAuxRoutes.test.d.ts +1 -0
  236. package/dist/server/routes/syncAuxRoutes.test.js +158 -0
  237. package/dist/server/routes/syncPullApplyRoutes.d.ts +36 -0
  238. package/dist/server/routes/syncPullApplyRoutes.js +204 -0
  239. package/dist/server/routes/syncPushRoutes.d.ts +24 -0
  240. package/dist/server/routes/syncPushRoutes.js +212 -0
  241. package/dist/server/routes/syncRouteGuards.d.ts +36 -0
  242. package/dist/server/routes/syncRouteGuards.js +67 -0
  243. package/dist/server/routes/syncRouteGuards.test.d.ts +1 -0
  244. package/dist/server/routes/syncRouteGuards.test.js +94 -0
  245. package/dist/server/routes/syncRouteTypes.d.ts +13 -0
  246. package/dist/server/routes/syncRouteTypes.js +1 -0
  247. package/dist/server/routes/syncSnapshotRoutes.d.ts +66 -0
  248. package/dist/server/routes/syncSnapshotRoutes.js +180 -0
  249. package/dist/server/routes/tasks.d.ts +1 -1
  250. package/dist/server/routes/tasks.js +44 -2
  251. package/dist/server/routes/workspaces.d.ts +1 -1
  252. package/dist/server/routes/workspaces.js +37 -6
  253. package/dist/server/routes.d.ts +2 -9
  254. package/dist/server/routes.js +136 -165
  255. package/dist/server/routes.test.js +2457 -162
  256. package/dist/services/workflowExportSnapshots.test.js +2 -0
  257. package/dist/shared/aiProfileSeatScope.d.ts +5 -0
  258. package/dist/shared/aiProfileSeatScope.js +21 -0
  259. package/dist/shared/passwordPolicy.d.ts +13 -0
  260. package/dist/shared/passwordPolicy.js +84 -0
  261. package/dist/shared/passwordPolicy.test.d.ts +1 -0
  262. package/dist/shared/passwordPolicy.test.js +34 -0
  263. package/dist/storage/workspaceAssetStore.d.ts +15 -3
  264. package/dist/storage/workspaceAssetStore.js +132 -44
  265. package/dist/storage/workspaceAssetStore.test.js +93 -6
  266. package/dist/styles/fonts.css +70 -0
  267. package/dist/sync/collaborationSyncPayload.d.ts +6 -1
  268. package/dist/sync/collaborationSyncPayload.js +17 -11
  269. package/dist/sync/collaborationSyncPayload.test.js +13 -1
  270. package/dist/sync/contentSyncState.d.ts +4 -8
  271. package/dist/sync/contentSyncState.js +33 -77
  272. package/dist/sync/syncApplyHandlers.d.ts +7 -0
  273. package/dist/sync/syncApplyHandlers.js +28 -13
  274. package/dist/sync/syncApplyHandlers.test.js +72 -3
  275. package/dist/sync/syncFieldSemantics.d.ts +12 -0
  276. package/dist/sync/syncFieldSemantics.js +55 -0
  277. package/dist/sync/syncResourceAdapters.d.ts +44 -0
  278. package/dist/sync/syncResourceAdapters.js +77 -0
  279. package/dist/sync/syncService.d.ts +6 -0
  280. package/dist/sync/syncService.js +60 -0
  281. package/dist/sync/syncService.test.js +71 -3
  282. package/dist/sync/taskSyncChangeKey.d.ts +2 -0
  283. package/dist/sync/taskSyncChangeKey.js +143 -0
  284. package/dist/sync/taskSyncPayload.js +3 -8
  285. package/dist/sync/workspacePullFeed.js +4 -3
  286. package/dist/sync/workspacePullFeed.test.js +43 -0
  287. package/dist/sync/workspaceRepair.js +5 -2
  288. package/dist/sync/workspaceSyncModel.d.ts +48 -0
  289. package/dist/sync/workspaceSyncModel.js +195 -31
  290. package/dist/sync/workspaceSyncModel.test.js +325 -12
  291. package/dist/sync/workspaceSyncState.d.ts +19 -0
  292. package/dist/sync/workspaceSyncState.js +3 -1
  293. package/dist/sync/workspaceSyncSurface.js +3 -8
  294. package/dist/types.d.ts +17 -0
  295. package/dist/ui/assets/AgentsModule-DrLawwNl.js +1 -0
  296. package/dist/ui/assets/{AnnotatedAttachmentWorkspace-BlS-cqnl.js → AnnotatedAttachmentWorkspace-Z9_whf7F.js} +1 -1
  297. package/dist/ui/assets/CourierPrime-Bold-BuLj_dpw.woff2 +0 -0
  298. package/dist/ui/assets/CourierPrime-BoldItalic-BrK2pUkZ.woff2 +0 -0
  299. package/dist/ui/assets/CourierPrime-Italic-DFUZK5Ey.woff2 +0 -0
  300. package/dist/ui/assets/CourierPrime-Regular-BsKphzVf.woff2 +0 -0
  301. package/dist/ui/assets/DocumentWorkspace-B03MaSkw.js +252 -0
  302. package/dist/ui/assets/DocumentWorkspace-Dhdso07p.css +1 -0
  303. package/dist/ui/assets/{InitiativesModule-BjR6iBf9.js → InitiativesModule-9E6ParrY.js} +1 -1
  304. package/dist/ui/assets/Noir_medium-bxQwKGzB.woff2 +0 -0
  305. package/dist/ui/assets/Noir_regular-ojf2kxlG.woff2 +0 -0
  306. package/dist/ui/assets/PlansPage-CvfnMiWq.css +1 -0
  307. package/dist/ui/assets/PlansPage-DRXscYxH.js +1 -0
  308. package/dist/ui/assets/RussoOne-Regular-Cu_qq_qC.woff2 +0 -0
  309. package/dist/ui/assets/SpecialElite-Regular-Di6gSvAS.woff2 +0 -0
  310. package/dist/ui/assets/TaskSettings-DZX4jk7e.js +9 -0
  311. package/dist/ui/assets/{WorkflowsModule-DnFqdUME.js → WorkflowsModule-BA7jcEpH.js} +1 -1
  312. package/dist/ui/assets/index-9eT8e0Lu.css +1 -0
  313. package/dist/ui/assets/index-C6k75jr8.js +6 -0
  314. package/dist/ui/assets/{vendor-icons-I7ZwG1z_.js → vendor-icons-DuEd_65c.js} +1 -1
  315. package/dist/ui/fonts/CourierPrime-Bold.ttf +0 -0
  316. package/dist/ui/fonts/CourierPrime-Bold.woff2 +0 -0
  317. package/dist/ui/fonts/CourierPrime-BoldItalic.ttf +0 -0
  318. package/dist/ui/fonts/CourierPrime-BoldItalic.woff2 +0 -0
  319. package/dist/ui/fonts/CourierPrime-Italic.ttf +0 -0
  320. package/dist/ui/fonts/CourierPrime-Italic.woff2 +0 -0
  321. package/dist/ui/fonts/CourierPrime-Regular.ttf +0 -0
  322. package/dist/ui/fonts/CourierPrime-Regular.woff2 +0 -0
  323. package/dist/ui/fonts/Noir_medium.otf +0 -0
  324. package/dist/ui/fonts/Noir_medium.woff2 +0 -0
  325. package/dist/ui/fonts/Noir_regular.otf +0 -0
  326. package/dist/ui/fonts/Noir_regular.woff2 +0 -0
  327. package/dist/ui/fonts/RussoOne-Regular.woff2 +0 -0
  328. package/dist/ui/fonts/SpecialElite-Regular.ttf +0 -0
  329. package/dist/ui/fonts/SpecialElite-Regular.woff2 +0 -0
  330. package/dist/ui/index.html +3 -3
  331. package/dist/utils/accountProfileSummaryCache.d.ts +5 -0
  332. package/dist/utils/assignees.d.ts +2 -0
  333. package/dist/utils/assignees.js +2 -0
  334. package/dist/utils/avatarUpload.d.ts +27 -0
  335. package/dist/utils/avatarUpload.js +132 -0
  336. package/dist/utils/avatarUpload.test.d.ts +1 -0
  337. package/dist/utils/avatarUpload.test.js +40 -0
  338. package/dist/utils/bootstrapTrace.d.ts +7 -0
  339. package/dist/utils/bootstrapTrace.js +29 -0
  340. package/dist/utils/commercialLifecyclePresentation.d.ts +19 -0
  341. package/dist/utils/commercialLifecyclePresentation.js +199 -0
  342. package/dist/utils/contextAssetEvents.d.ts +2 -0
  343. package/dist/utils/syncEventDetails.d.ts +3 -0
  344. package/dist/utils/syncEventDetails.js +64 -0
  345. package/dist/utils/syncEventDetails.test.d.ts +1 -0
  346. package/dist/utils/syncEventDetails.test.js +23 -0
  347. package/dist/utils/syncEventPresentation.d.ts +15 -0
  348. package/dist/utils/syncEventPresentation.js +129 -0
  349. package/dist/utils/syncEventPresentation.test.d.ts +1 -0
  350. package/dist/utils/syncEventPresentation.test.js +64 -0
  351. package/dist/utils/syncStatusPresentation.d.ts +72 -0
  352. package/dist/utils/syncStatusPresentation.js +217 -0
  353. package/dist/utils/syncStatusPresentation.test.d.ts +1 -0
  354. package/dist/utils/syncStatusPresentation.test.js +164 -0
  355. package/dist/utils/taskActivity.d.ts +2 -0
  356. package/dist/utils/taskActivity.js +228 -22
  357. package/dist/utils/taskActivity.test.js +119 -8
  358. package/dist/utils/workspaceSyncPresentation.d.ts +4 -0
  359. package/dist/utils/workspaceSyncPresentation.js +68 -2
  360. package/dist/utils/workspaceSyncPresentation.test.js +36 -1
  361. package/package.json +10 -2
  362. package/scripts/check-cloud-mcp.mjs +83 -0
  363. package/scripts/export-sqlite-to-postgres.mjs +7 -9
  364. package/scripts/playwright-auth.sh +5 -1
  365. package/scripts/run-billing-performance-smoke.sh +24 -0
  366. package/scripts/run-e2e-realtime.sh +17 -3
  367. package/scripts/run-smoke.sh +17 -5
  368. package/scripts/run-soak.sh +17 -5
  369. package/src/resources/templates/workflow-sources/workflowDocs.mjs +6 -6
  370. package/src/resources/templates/workflows/collaborate.yaml +1 -1
  371. package/src/resources/templates/workflows/evaluate.yaml +2 -2
  372. package/src/resources/templates/workflows/plan.yaml +1 -1
  373. package/src/resources/templates/workflows/review.yaml +2 -2
  374. package/dist/ui/assets/AgentsModule-BLWVbuKP.js +0 -1
  375. package/dist/ui/assets/DocumentWorkspace-BH_6DF6x.js +0 -250
  376. package/dist/ui/assets/DocumentWorkspace-C_8T8oz-.css +0 -1
  377. package/dist/ui/assets/PlansPage-C2dd2n1X.css +0 -1
  378. package/dist/ui/assets/PlansPage-CSDQ4sLa.js +0 -1
  379. package/dist/ui/assets/RussoOne-Regular-C3BxZIj7.ttf +0 -0
  380. package/dist/ui/assets/TaskSettings-CEDy34Jo.js +0 -9
  381. package/dist/ui/assets/index-DXUdtH1B.js +0 -6
  382. package/dist/ui/assets/index-Ii0B0rTO.css +0 -1
  383. package/scripts/migrate-planning-model.ts +0 -233
@@ -1,35 +1,54 @@
1
1
  import { applyLocalWorkspaceChanges } from '../../sync/cloudSyncApi';
2
2
  import { isTransientWorkspaceSyncStatus, runWorkspacePullSyncService, runWorkspacePushSyncService } from '../../sync/syncService';
3
- import { logSyncDebug, savePersistedSyncWatermarks, isValidWorkspaceKey } from './orchestratorShared';
4
- export function createWorkspaceTransferCoordinator({ cloudAuthConfigured, runtimeMode, workspaceCloudSyncEnabled, currentWorkspaceId, workspaceSyncPhase, taxonomyStateFingerprint, isAuthenticated, checkAuthSession, resolveCloudAuthUrl, ensureCloudWorkspaceReadyForSync, ensureWorkspaceSyncReady, handleSyncAuthFailure, clearWorkspaceRetry, clearWorkspaceIssue, isWorkspaceRetryPending, scheduleWorkspaceSyncRetry, persistWorkspaceSyncPatchSafely, persistWorkspaceSyncPatchBestEffort, reportSyncEvent, acquireWorkspaceSyncLease, releaseWorkspaceSyncLease, reportWorkspaceWindowContention, refreshWorkspaceSyncMarkdownDocumentsSnapshot, refreshWorkspaceSyncAiProfilesSnapshot, refreshWorkspaceSyncAssetsSnapshot, refreshWorkspaceSyncDocumentReviewSessionsSnapshot, refreshWorkspaceSyncAnnotatedAttachmentSessionsSnapshot, refreshLocalWorkspaceTaskCollections, buildWorkspaceSyncPayload, buildWorkspaceSyncSignature, seedWorkspaceSnapshotPushBaseline, shouldSuppressAttachBootstrapPush, recordSuppressedEventIds, workspaceRepairModeRef, workspaceForceFullAiProfilePushRef, workspacePushInFlightRef, workspacePullInFlightRef, workspaceLastPushedSignatureRef, workspacePendingSignatureRef, workspaceLastPushedTaskIdsRef, workspaceDeletedTaskIdsRef, workspacePullCursorRef, workspaceLastPushedWatermarksRef, workspaceLastPushedInitiativeIdsRef, workspaceLastPushedInitiativeWatermarksRef, workspaceLastPushedWorkstreamIdsRef, workspaceLastPushedWorkstreamWatermarksRef, workspaceLastPushedAiProfileIdsRef, workspaceLastPushedAiProfileWatermarksRef, workspaceLastPushedDocumentPathsRef, workspaceLastPushedDocumentWatermarksRef, workspaceLastPushedAssetPathsRef, workspaceLastPushedAssetWatermarksRef, workspaceLastPushedDocumentReviewSessionIdsRef, workspaceLastPushedDocumentReviewSessionWatermarksRef, workspaceLastPushedDocumentReviewCommentIdsRef, workspaceLastPushedDocumentReviewCommentWatermarksRef, workspaceLastPushedAnnotatedAttachmentSessionIdsRef, workspaceLastPushedAnnotatedAttachmentSessionWatermarksRef, workspaceLastPushedTaskEventWatermarksRef, workspaceCaptureAttachBootstrapBaselineRef, workspaceStartupFullReconcileRanRef, workspaceFullReconcileInFlightRef, bootstrapLastProgressAtRef, realtimeSuppressedEventQueueRef, setWorkspaceSyncBusy, setUserGlobalSyncStatus, setUserGlobalSyncError, setWorkspaceLastErrorMessage, setWorkspaceLastErrorAt, setWorkspaceLastPullAt, setWorkspaceLastPushAt, setWorkspaceSyncPendingChanges, setTasks, setArchivedTasks }) {
3
+ import { createWorkspaceSyncLeaseHeldDecision, resolvePullSyncReadiness, resolvePushSyncReadiness } from './controlPlane';
4
+ import { resolveWorkspacePullRequestPlan, resolveWorkspacePullSuccessPlan } from './pullLifecycle';
5
+ import { logSyncDebug } from './orchestratorShared';
6
+ export function createWorkspaceTransferCoordinator({ cloudAuthConfigured, runtimeMode, workspaceCloudSyncEnabled, currentWorkspaceId, workspaceSyncPhase, isAuthenticated, checkAuthSession, resolveCloudAuthUrl, ensureCloudWorkspaceReadyForSync, ensureWorkspaceSyncReady, handleSyncAuthFailure, clearWorkspaceRetry, clearWorkspaceIssue, isWorkspaceRetryPending, scheduleWorkspaceSyncRetry, persistWorkspaceSyncPatchSafely, persistWorkspaceSyncPatchBestEffort, persistWorkspaceSyncWatermarksSnapshotBestEffort, reportSyncEvent, acquireWorkspaceSyncLease, releaseWorkspaceSyncLease, reportWorkspaceWindowContention, refreshWorkspaceSyncMarkdownDocumentsSnapshot, refreshWorkspaceSyncAiProfilesSnapshot, refreshWorkspaceSyncAssetsSnapshot, refreshWorkspaceSyncDocumentReviewSessionsSnapshot, refreshWorkspaceSyncAnnotatedAttachmentSessionsSnapshot, refreshLocalWorkspaceTaskCollections, buildWorkspaceSyncPayload, buildWorkspaceSyncSignature, seedWorkspaceSnapshotPushBaseline, shouldSuppressAttachBootstrapPush, recordSuppressedEventIds, workspaceRepairModeRef, workspaceForceFullAiProfilePushRef, workspacePushInFlightRef, workspacePullInFlightRef, workspacePendingPushReplayRef, workspaceLastPushedSignatureRef, workspacePendingSignatureRef, workspaceLastPushedTaskIdsRef, workspaceDeletedTaskIdsRef, workspaceDeletedTaskWatermarksRef, workspacePullCursorRef, workspaceLastPushedWatermarksRef, workspaceLastPushedTaskChangeKeysRef, workspaceLastPushedInitiativeIdsRef, workspaceLastPushedInitiativeWatermarksRef, workspaceLastPushedWorkstreamIdsRef, workspaceLastPushedWorkstreamWatermarksRef, workspaceLastPushedAiProfileIdsRef, workspaceLastPushedAiProfileWatermarksRef, workspaceLastPushedAiProfileChangeKeysRef, workspaceLastPushedDocumentPathsRef, workspaceLastPushedDocumentWatermarksRef, workspaceLastPushedAssetPathsRef, workspaceLastPushedAssetWatermarksRef, workspaceLastPushedDocumentReviewSessionIdsRef, workspaceLastPushedDocumentReviewSessionWatermarksRef, workspaceLastPushedDocumentReviewCommentIdsRef, workspaceLastPushedDocumentReviewCommentWatermarksRef, workspaceLastPushedAnnotatedAttachmentSessionIdsRef, workspaceLastPushedAnnotatedAttachmentSessionWatermarksRef, workspaceLastPushedTaskEventWatermarksRef, workspaceBaselineResetReasonRef, workspaceCaptureAttachBootstrapBaselineRef, workspaceStartupFullReconcileRanRef, workspaceFullReconcileInFlightRef, bootstrapLastProgressAtRef, realtimeSuppressedEventQueueRef, setWorkspaceSyncBusy, setUserGlobalSyncStatus, setUserGlobalSyncError, setWorkspaceLastErrorMessage, setWorkspaceLastErrorAt, setWorkspaceLastPullAt, setWorkspaceLastPushAt, setWorkspaceSyncPendingChanges, setTasks, setArchivedTasks }) {
5
7
  const pushWorkspaceChangesToCloud = async (signature, options) => {
6
- if (!cloudAuthConfigured || runtimeMode !== 'local' || !workspaceCloudSyncEnabled)
7
- return false;
8
- if (!isValidWorkspaceKey(currentWorkspaceId))
9
- return false;
10
- if (workspaceRepairModeRef.current === true && options?.repairMode !== true) {
11
- workspacePendingSignatureRef.current = signature;
12
- return false;
13
- }
14
- if (workspaceSyncPhase === 'attach-cloud') {
15
- workspacePendingSignatureRef.current = signature;
16
- return false;
17
- }
18
- if (!isAuthenticated) {
8
+ let pushReadiness = resolvePushSyncReadiness({
9
+ cloudAuthConfigured,
10
+ runtimeMode,
11
+ workspaceCloudSyncEnabled,
12
+ currentWorkspaceId,
13
+ workspaceSyncPhase,
14
+ isAuthenticated,
15
+ repairModeActive: workspaceRepairModeRef.current === true,
16
+ repairModeBypass: options?.repairMode === true,
17
+ pushInFlight: workspacePushInFlightRef.current,
18
+ pullInFlight: workspacePullInFlightRef.current
19
+ });
20
+ if (!pushReadiness.allowed && pushReadiness.reason === 'auth-required') {
19
21
  const authed = await checkAuthSession();
20
22
  if (!authed)
21
23
  return false;
24
+ pushReadiness = resolvePushSyncReadiness({
25
+ cloudAuthConfigured,
26
+ runtimeMode,
27
+ workspaceCloudSyncEnabled,
28
+ currentWorkspaceId,
29
+ workspaceSyncPhase,
30
+ isAuthenticated: true,
31
+ repairModeActive: workspaceRepairModeRef.current === true,
32
+ repairModeBypass: options?.repairMode === true,
33
+ pushInFlight: workspacePushInFlightRef.current,
34
+ pullInFlight: workspacePullInFlightRef.current
35
+ });
22
36
  }
23
- if (shouldSuppressAttachBootstrapPush(signature)) {
37
+ if (!pushReadiness.allowed) {
38
+ if (pushReadiness.retainPendingSignature) {
39
+ workspacePendingSignatureRef.current = signature;
40
+ }
24
41
  return false;
25
42
  }
26
- if (workspacePushInFlightRef.current || workspacePullInFlightRef.current) {
27
- workspacePendingSignatureRef.current = signature;
43
+ if (shouldSuppressAttachBootstrapPush(signature)) {
28
44
  return false;
29
45
  }
30
46
  const leaseAcquired = await acquireWorkspaceSyncLease(currentWorkspaceId, 'push');
31
47
  if (!leaseAcquired) {
32
- workspacePendingSignatureRef.current = signature;
48
+ const leaseDecision = createWorkspaceSyncLeaseHeldDecision('push');
49
+ if (!leaseDecision.allowed && leaseDecision.retainPendingSignature) {
50
+ workspacePendingSignatureRef.current = signature;
51
+ }
33
52
  reportWorkspaceWindowContention('push');
34
53
  return false;
35
54
  }
@@ -39,6 +58,9 @@ export function createWorkspaceTransferCoordinator({ cloudAuthConfigured, runtim
39
58
  setUserGlobalSyncError(null);
40
59
  const pushStartedAtMs = Date.now();
41
60
  const forceAllAiProfiles = options?.forceAllAiProfiles === true || workspaceForceFullAiProfilePushRef.current === true;
61
+ const repairMode = options?.repairMode === true || workspaceRepairModeRef.current === true;
62
+ let payloadForAttempt = null;
63
+ let replayedPayload = false;
42
64
  try {
43
65
  await refreshWorkspaceSyncMarkdownDocumentsSnapshot();
44
66
  await refreshWorkspaceSyncAiProfilesSnapshot();
@@ -47,17 +69,24 @@ export function createWorkspaceTransferCoordinator({ cloudAuthConfigured, runtim
47
69
  const ready = await ensureWorkspaceSyncReady();
48
70
  if (!ready)
49
71
  return false;
50
- const payload = buildWorkspaceSyncPayload({ forceAllAiProfiles });
72
+ const pendingReplay = workspacePendingPushReplayRef.current;
73
+ const replayPayload = pendingReplay && pendingReplay.signature === signature
74
+ ? pendingReplay
75
+ : null;
76
+ const payload = replayPayload?.payload || buildWorkspaceSyncPayload({ forceAllAiProfiles });
77
+ payloadForAttempt = payload;
78
+ replayedPayload = replayPayload !== null;
51
79
  setWorkspaceSyncPendingChanges(payload.changes.length);
52
80
  const pushResult = await runWorkspacePushSyncService({
53
81
  resolveCloudAuthUrl,
54
82
  workspaceId: currentWorkspaceId,
55
83
  payload,
56
84
  ensureCloudWorkspaceReadyForSync,
57
- repairMode: options?.repairMode === true || workspaceRepairModeRef.current === true
85
+ repairMode: replayPayload?.repairMode ?? repairMode
58
86
  });
59
87
  if (!pushResult.success) {
60
88
  if (pushResult.status === 401) {
89
+ workspacePendingPushReplayRef.current = null;
61
90
  await handleSyncAuthFailure('push', 401);
62
91
  return false;
63
92
  }
@@ -76,25 +105,48 @@ export function createWorkspaceTransferCoordinator({ cloudAuthConfigured, runtim
76
105
  status: 'error',
77
106
  statusCode: pushResult.status,
78
107
  errorMessage: message,
79
- requestMs: pushResult.requestMs
108
+ requestMs: pushResult.requestMs,
109
+ details: {
110
+ payloadDiagnostics: payload.deltaDiagnostics || null,
111
+ replayedPayload
112
+ }
80
113
  });
81
114
  workspacePendingSignatureRef.current = signature;
82
115
  if (pushResult.transient || isTransientWorkspaceSyncStatus(pushResult.status)) {
116
+ workspacePendingPushReplayRef.current = {
117
+ signature,
118
+ payload,
119
+ forceAllAiProfiles: replayPayload?.forceAllAiProfiles ?? forceAllAiProfiles,
120
+ repairMode: replayPayload?.repairMode ?? repairMode
121
+ };
83
122
  scheduleWorkspaceSyncRetry(pushResult.retryAfterMs);
84
123
  }
85
- else if (workspaceSyncPhase === 'active') {
86
- persistWorkspaceSyncPatchSafely({ phase: 'error', lastErrorMessage: message });
124
+ else {
125
+ workspacePendingPushReplayRef.current = null;
126
+ if (workspaceSyncPhase === 'active') {
127
+ persistWorkspaceSyncPatchSafely({ phase: 'error', lastErrorMessage: message });
128
+ }
87
129
  }
88
130
  return false;
89
131
  }
132
+ workspacePendingPushReplayRef.current = null;
90
133
  workspaceLastPushedSignatureRef.current = signature;
91
134
  workspaceLastPushedTaskIdsRef.current = pushResult.currentTaskIds;
135
+ workspaceLastPushedWatermarksRef.current = pushResult.currentTaskWatermarks
136
+ ? new Map(pushResult.currentTaskWatermarks)
137
+ : new Map(workspaceLastPushedWatermarksRef.current);
138
+ workspaceLastPushedTaskChangeKeysRef.current = pushResult.currentTaskChangeKeys
139
+ ? new Map(pushResult.currentTaskChangeKeys)
140
+ : new Map(workspaceLastPushedTaskChangeKeysRef.current);
92
141
  workspaceLastPushedInitiativeIdsRef.current = new Set(pushResult.currentInitiativeIds);
93
142
  workspaceLastPushedInitiativeWatermarksRef.current = new Map(pushResult.currentInitiativeWatermarks);
94
143
  workspaceLastPushedWorkstreamIdsRef.current = new Set(pushResult.currentWorkstreamIds);
95
144
  workspaceLastPushedWorkstreamWatermarksRef.current = new Map(pushResult.currentWorkstreamWatermarks);
96
145
  workspaceLastPushedAiProfileIdsRef.current = new Set(pushResult.currentAiProfileIds);
97
146
  workspaceLastPushedAiProfileWatermarksRef.current = new Map(pushResult.currentAiProfileWatermarks);
147
+ workspaceLastPushedAiProfileChangeKeysRef.current = pushResult.currentAiProfileChangeKeys
148
+ ? new Map(pushResult.currentAiProfileChangeKeys)
149
+ : new Map(workspaceLastPushedAiProfileChangeKeysRef.current);
98
150
  workspaceLastPushedDocumentPathsRef.current = new Set(pushResult.currentDocumentPaths);
99
151
  workspaceLastPushedDocumentWatermarksRef.current = new Map(pushResult.currentDocumentWatermarks);
100
152
  workspaceLastPushedAssetPathsRef.current = new Set(pushResult.currentAssetPaths);
@@ -112,24 +164,19 @@ export function createWorkspaceTransferCoordinator({ cloudAuthConfigured, runtim
112
164
  for (const [taskId, watermark] of pushResult.pushedWatermarks) {
113
165
  workspaceLastPushedWatermarksRef.current.set(taskId, watermark);
114
166
  }
167
+ for (const [taskId, changeKey] of (pushResult.pushedTaskChangeKeys || new Map())) {
168
+ workspaceLastPushedTaskChangeKeysRef.current.set(taskId, changeKey);
169
+ }
115
170
  if (pushResult.deleteTaskIds.size > 0) {
116
171
  for (const taskId of pushResult.deleteTaskIds) {
117
172
  workspaceDeletedTaskIdsRef.current.delete(taskId);
173
+ workspaceDeletedTaskWatermarksRef.current.delete(taskId);
118
174
  workspaceLastPushedWatermarksRef.current.delete(taskId);
175
+ workspaceLastPushedTaskChangeKeysRef.current.delete(taskId);
119
176
  }
120
177
  }
121
- savePersistedSyncWatermarks(currentWorkspaceId, {
122
- taskWatermarks: workspaceLastPushedWatermarksRef.current,
123
- initiativeWatermarks: workspaceLastPushedInitiativeWatermarksRef.current,
124
- workstreamWatermarks: workspaceLastPushedWorkstreamWatermarksRef.current,
125
- documentWatermarks: workspaceLastPushedDocumentWatermarksRef.current,
126
- assetWatermarks: workspaceLastPushedAssetWatermarksRef.current,
127
- documentReviewSessionWatermarks: workspaceLastPushedDocumentReviewSessionWatermarksRef.current,
128
- documentReviewCommentWatermarks: workspaceLastPushedDocumentReviewCommentWatermarksRef.current,
129
- annotatedAttachmentSessionWatermarks: workspaceLastPushedAnnotatedAttachmentSessionWatermarksRef.current,
130
- taskEventWatermarks: workspaceLastPushedTaskEventWatermarksRef.current,
131
- taxonomyStateFingerprint
132
- });
178
+ const persisted = await persistWorkspaceSyncWatermarksSnapshotBestEffort();
179
+ workspaceBaselineResetReasonRef.current = persisted ? null : 'storage-write-failed';
133
180
  if (Array.isArray(pushResult.emittedEventIds) && pushResult.emittedEventIds.length > 0) {
134
181
  recordSuppressedEventIds(pushResult.emittedEventIds, {
135
182
  queueRef: realtimeSuppressedEventQueueRef,
@@ -186,7 +233,11 @@ export function createWorkspaceTransferCoordinator({ cloudAuthConfigured, runtim
186
233
  eventType: workspaceSyncPhase === 'provision-local' ? 'bootstrap' : 'push',
187
234
  status: 'success',
188
235
  changeCount: pushResult.changeCount,
189
- requestMs: pushResult.requestMs
236
+ requestMs: pushResult.requestMs,
237
+ details: {
238
+ payloadDiagnostics: payload.deltaDiagnostics || null,
239
+ replayedPayload
240
+ }
190
241
  });
191
242
  return true;
192
243
  }
@@ -197,11 +248,22 @@ export function createWorkspaceTransferCoordinator({ cloudAuthConfigured, runtim
197
248
  setWorkspaceLastErrorMessage(message);
198
249
  setWorkspaceLastErrorAt(new Date().toISOString());
199
250
  workspacePendingSignatureRef.current = signature;
251
+ if (payloadForAttempt) {
252
+ workspacePendingPushReplayRef.current = {
253
+ signature,
254
+ payload: payloadForAttempt,
255
+ forceAllAiProfiles,
256
+ repairMode
257
+ };
258
+ }
200
259
  scheduleWorkspaceSyncRetry();
201
260
  reportSyncEvent(currentWorkspaceId, {
202
261
  eventType: 'push',
203
262
  status: 'error',
204
- errorMessage: `${message} ${String(error?.message || '').trim()}`.trim()
263
+ errorMessage: `${message} ${String(error?.message || '').trim()}`.trim(),
264
+ details: {
265
+ replayedPayload
266
+ }
205
267
  });
206
268
  logSyncDebug('push_failed_exception', {
207
269
  workspaceId: currentWorkspaceId,
@@ -214,34 +276,54 @@ export function createWorkspaceTransferCoordinator({ cloudAuthConfigured, runtim
214
276
  setWorkspaceSyncBusy(workspacePullInFlightRef.current);
215
277
  releaseWorkspaceSyncLease(currentWorkspaceId);
216
278
  const pendingSignature = workspacePendingSignatureRef.current;
279
+ const latestSignature = buildWorkspaceSyncSignature();
217
280
  if (pendingSignature
218
- && pendingSignature !== workspaceLastPushedSignatureRef.current
219
- && !workspacePullInFlightRef.current) {
281
+ && latestSignature
282
+ && latestSignature !== workspaceLastPushedSignatureRef.current
283
+ && !workspacePullInFlightRef.current
284
+ && !isWorkspaceRetryPending()) {
220
285
  workspacePendingSignatureRef.current = '';
221
286
  window.setTimeout(() => {
222
- void pushWorkspaceChangesToCloud(pendingSignature);
287
+ void pushWorkspaceChangesToCloud(latestSignature);
223
288
  }, 120);
224
289
  }
225
290
  }
226
291
  };
227
292
  const pullWorkspaceChangesFromCloud = async (options) => {
228
- if (!cloudAuthConfigured || runtimeMode !== 'local' || !workspaceCloudSyncEnabled)
229
- return false;
230
- if (!isValidWorkspaceKey(currentWorkspaceId))
231
- return false;
232
- if (workspaceRepairModeRef.current === true && options?.repairMode !== true)
233
- return false;
234
- if (workspaceSyncPhase === 'provision-local')
235
- return false;
236
- if (isWorkspaceRetryPending())
237
- return false;
238
- if (!isAuthenticated) {
293
+ let pullReadiness = resolvePullSyncReadiness({
294
+ cloudAuthConfigured,
295
+ runtimeMode,
296
+ workspaceCloudSyncEnabled,
297
+ currentWorkspaceId,
298
+ workspaceSyncPhase,
299
+ isAuthenticated,
300
+ repairModeActive: workspaceRepairModeRef.current === true,
301
+ repairModeBypass: options?.repairMode === true,
302
+ retryPending: isWorkspaceRetryPending(),
303
+ pullInFlight: workspacePullInFlightRef.current,
304
+ pushInFlight: workspacePushInFlightRef.current
305
+ });
306
+ if (!pullReadiness.allowed && pullReadiness.reason === 'auth-required') {
239
307
  const authed = await checkAuthSession();
240
308
  if (!authed)
241
309
  return false;
310
+ pullReadiness = resolvePullSyncReadiness({
311
+ cloudAuthConfigured,
312
+ runtimeMode,
313
+ workspaceCloudSyncEnabled,
314
+ currentWorkspaceId,
315
+ workspaceSyncPhase,
316
+ isAuthenticated: true,
317
+ repairModeActive: workspaceRepairModeRef.current === true,
318
+ repairModeBypass: options?.repairMode === true,
319
+ retryPending: isWorkspaceRetryPending(),
320
+ pullInFlight: workspacePullInFlightRef.current,
321
+ pushInFlight: workspacePushInFlightRef.current
322
+ });
242
323
  }
243
- if (workspacePullInFlightRef.current || workspacePushInFlightRef.current)
324
+ if (!pullReadiness.allowed) {
244
325
  return false;
326
+ }
245
327
  const leaseAcquired = await acquireWorkspaceSyncLease(currentWorkspaceId, 'pull');
246
328
  if (!leaseAcquired) {
247
329
  reportWorkspaceWindowContention('pull');
@@ -256,13 +338,16 @@ export function createWorkspaceTransferCoordinator({ cloudAuthConfigured, runtim
256
338
  const ready = await ensureWorkspaceSyncReady();
257
339
  if (!ready)
258
340
  return false;
259
- const bootstrap = workspaceSyncPhase === 'attach-cloud';
260
- const cursor = bootstrap || options?.forceCursorNull === true ? null : workspacePullCursorRef.current;
341
+ const pullRequestPlan = resolveWorkspacePullRequestPlan({
342
+ workspaceSyncPhase,
343
+ forceCursorNull: options?.forceCursorNull === true,
344
+ currentCursor: workspacePullCursorRef.current
345
+ });
261
346
  const pullResult = await runWorkspacePullSyncService({
262
347
  resolveCloudAuthUrl,
263
348
  workspaceId: currentWorkspaceId,
264
- cursor,
265
- bootstrap,
349
+ cursor: pullRequestPlan.cursor,
350
+ bootstrap: pullRequestPlan.bootstrap,
266
351
  ensureCloudWorkspaceReadyForSync,
267
352
  maxPages: 20,
268
353
  repairMode: options?.repairMode === true || workspaceRepairModeRef.current === true,
@@ -278,6 +363,28 @@ export function createWorkspaceTransferCoordinator({ cloudAuthConfigured, runtim
278
363
  await handleSyncAuthFailure('apply', 401);
279
364
  return false;
280
365
  }
366
+ if (pullResult.kind === 'pull_http' && pullResult.errorCode === 'INVALID_SYNC_CURSOR') {
367
+ const message = 'Saved sync cursor was invalid. Clearing it and retrying from the beginning.';
368
+ workspacePullCursorRef.current = null;
369
+ persistWorkspaceSyncPatchSafely({ pullCursor: null });
370
+ setUserGlobalSyncStatus('error');
371
+ setUserGlobalSyncError(message);
372
+ setWorkspaceLastErrorMessage(message);
373
+ setWorkspaceLastErrorAt(new Date().toISOString());
374
+ reportSyncEvent(currentWorkspaceId, {
375
+ eventType: 'pull',
376
+ status: 'error',
377
+ statusCode: pullResult.status,
378
+ errorMessage: message,
379
+ requestMs: pullResult.pullRequestMs,
380
+ details: {
381
+ recovery: 'cursor-reset',
382
+ ...(pullResult.serverDiagnostics ? { serverPullDiagnostics: pullResult.serverDiagnostics } : {})
383
+ }
384
+ });
385
+ scheduleWorkspaceSyncRetry(150);
386
+ return false;
387
+ }
281
388
  let message = pullResult.kind === 'apply_payload' || pullResult.kind === 'apply_all_candidates' || pullResult.kind === 'exception'
282
389
  ? String(pullResult.error || 'Workspace sync apply failed.')
283
390
  : `Workspace sync pull failed (${pullResult.status || 0})`;
@@ -345,9 +452,20 @@ export function createWorkspaceTransferCoordinator({ cloudAuthConfigured, runtim
345
452
  setWorkspaceLastPullAt(syncedAt);
346
453
  setWorkspaceSyncPendingChanges(0);
347
454
  setUserGlobalSyncStatus('idle');
348
- if (workspaceSyncPhase === 'attach-cloud') {
455
+ const pullSuccessPlan = resolveWorkspacePullSuccessPlan({
456
+ workspaceSyncPhase,
457
+ forceCursorNull: options?.forceCursorNull === true,
458
+ startupFullReconcileRan: workspaceStartupFullReconcileRanRef.current,
459
+ pendingSignature: workspacePendingSignatureRef.current,
460
+ fallbackSignature: buildWorkspaceSyncSignature(),
461
+ lastPushedSignature: workspaceLastPushedSignatureRef.current
462
+ });
463
+ if (pullSuccessPlan.shouldCaptureAttachBootstrapBaseline) {
349
464
  workspaceCaptureAttachBootstrapBaselineRef.current = true;
465
+ }
466
+ if (pullSuccessPlan.shouldClearPendingSignature) {
350
467
  workspacePendingSignatureRef.current = '';
468
+ workspacePendingPushReplayRef.current = null;
351
469
  }
352
470
  await persistWorkspaceSyncPatchBestEffort({
353
471
  phase: 'active',
@@ -357,7 +475,7 @@ export function createWorkspaceTransferCoordinator({ cloudAuthConfigured, runtim
357
475
  lastErrorMessage: null
358
476
  });
359
477
  reportSyncEvent(currentWorkspaceId, {
360
- eventType: workspaceSyncPhase === 'attach-cloud' ? 'bootstrap' : 'pull',
478
+ eventType: pullSuccessPlan.successEventType,
361
479
  status: 'success',
362
480
  changeCount: pullResult.appliedChanges,
363
481
  requestMs: pullResult.pullRequestMs,
@@ -367,15 +485,19 @@ export function createWorkspaceTransferCoordinator({ cloudAuthConfigured, runtim
367
485
  ...(pullResult.serverDiagnostics ? { serverPullDiagnostics: pullResult.serverDiagnostics } : {})
368
486
  }
369
487
  });
370
- if (workspaceSyncPhase === 'attach-cloud') {
488
+ if (pullSuccessPlan.shouldRefreshReferenceSnapshots) {
371
489
  await refreshWorkspaceSyncMarkdownDocumentsSnapshot();
372
490
  await refreshWorkspaceSyncAssetsSnapshot();
373
491
  await refreshWorkspaceSyncDocumentReviewSessionsSnapshot();
374
492
  await refreshWorkspaceSyncAnnotatedAttachmentSessionsSnapshot();
493
+ }
494
+ if (pullSuccessPlan.shouldSeedWorkspaceSnapshotPushBaseline) {
375
495
  seedWorkspaceSnapshotPushBaseline();
496
+ }
497
+ if (pullSuccessPlan.shouldRefreshReferenceSnapshots || pullSuccessPlan.shouldSeedWorkspaceSnapshotPushBaseline) {
376
498
  return true;
377
499
  }
378
- if (!options?.forceCursorNull && !bootstrap && !workspaceStartupFullReconcileRanRef.current) {
500
+ if (pullSuccessPlan.shouldScheduleStartupFullReconcile) {
379
501
  workspaceStartupFullReconcileRanRef.current = true;
380
502
  window.setTimeout(() => {
381
503
  if (workspaceFullReconcileInFlightRef.current)
@@ -386,11 +508,10 @@ export function createWorkspaceTransferCoordinator({ cloudAuthConfigured, runtim
386
508
  });
387
509
  }, 250);
388
510
  }
389
- const pendingSignature = workspacePendingSignatureRef.current || buildWorkspaceSyncSignature();
390
- if (pendingSignature && pendingSignature !== workspaceLastPushedSignatureRef.current) {
391
- workspacePendingSignatureRef.current = '';
511
+ if (pullSuccessPlan.deferredPushSignature) {
512
+ const deferredPushSignature = pullSuccessPlan.deferredPushSignature;
392
513
  window.setTimeout(() => {
393
- void pushWorkspaceChangesToCloud(pendingSignature);
514
+ void pushWorkspaceChangesToCloud(deferredPushSignature);
394
515
  }, 120);
395
516
  }
396
517
  return true;
@@ -0,0 +1 @@
1
+ export {};