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