@taskforcehq/taskforce 0.3.309 → 0.3.313

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 (470) hide show
  1. package/README.md +89 -127
  2. package/dist/TaskforceCore.js +1 -1
  3. package/dist/components/context/ContextAttachmentManager.js +4 -3
  4. package/dist/components/features/InitiativesModule.js +1 -1
  5. package/dist/components/features/TaskSettings.js +1 -1
  6. package/dist/components/ui/DisclosureSectionHeader.d.ts +12 -0
  7. package/dist/components/ui/DisclosureSectionHeader.js +8 -0
  8. package/dist/components/views/PlanComparisonPage.js +1 -1
  9. package/dist/components/views/StandaloneLayout.js +18 -4
  10. package/dist/components/views/panels/PlanningDrawer.js +2 -1
  11. package/dist/components/views/standalone/modals/AccountHubModal.js +1 -1
  12. package/dist/components/views/standalone/modals/HelpModal.d.ts +3 -1
  13. package/dist/components/views/standalone/modals/HelpModal.js +17 -2
  14. package/dist/core/PlanEntitlementService.d.ts +2 -0
  15. package/dist/core/PlanEntitlementService.js +57 -4
  16. package/dist/hooks/useFilterSort.js +1 -1
  17. package/dist/hooks/useTaskforce.js +2 -2
  18. package/dist/hooks/workspace/useTaskforceWorkspaceBootstrap.js +5 -2
  19. package/dist/localization/locales/en-US.js +1 -1
  20. package/dist/localization/locales/es-419.js +1 -1
  21. package/dist/localization/locales/pt-BR.js +1 -1
  22. package/dist/mcp/runtime.js +49 -14
  23. package/dist/server/routes/billing.js +0 -1
  24. package/dist/ui/assets/AgentsModule-BULqIo8e.js +1 -0
  25. package/dist/ui/assets/{AnnotatedAttachmentWorkspace-CCckzWYZ.js → AnnotatedAttachmentWorkspace-DHr4rHK9.js} +1 -1
  26. package/dist/ui/assets/ContextAttachmentManager-DoMe2OpY.js +3 -0
  27. package/dist/ui/assets/{DocumentWorkspace-BVaWPA25.js → DocumentWorkspace-DumBWhvb.js} +1 -1
  28. package/dist/ui/assets/{EntityActivityTimeline-DSj0ThaK.js → EntityActivityTimeline-sHk8Nzbq.js} +1 -1
  29. package/dist/ui/assets/{InitiativesModule-AxMkWtxH.js → InitiativesModule-3X9UNzHh.js} +1 -1
  30. package/dist/ui/assets/PlansPage-C3A3EYaV.js +1 -0
  31. package/dist/ui/assets/PlansPage-DeAzWYTb.css +1 -0
  32. package/dist/ui/assets/{TaskContextUpload-Dw4rTF4i.js → TaskContextUpload-C8G7pWkX.js} +1 -1
  33. package/dist/ui/assets/{TaskSettings-f2ga42_V.js → TaskSettings-DM1o9Wla.js} +2 -2
  34. package/dist/ui/assets/{WorkflowsModule-E4UL3mov.js → WorkflowsModule-CW0crzvD.js} +1 -1
  35. package/dist/ui/assets/documentReferences-BZB3nMRb.js +1 -0
  36. package/dist/ui/assets/index-BWFQ9mGn.js +5 -0
  37. package/dist/ui/assets/{index-BvAbqx5Q.css → index-DcK_8tuE.css} +1 -1
  38. package/dist/ui/assets/{vendor-icons-B32hGuF2.js → vendor-icons-CLnehDTw.js} +1 -1
  39. package/dist/ui/index.html +3 -3
  40. package/dist/utils/supportContact.d.ts +9 -0
  41. package/dist/utils/supportContact.js +32 -0
  42. package/package.json +12 -4
  43. package/scripts/postinstall.js +4 -3
  44. package/dist/TaskforceCore.CategoryFallback.test.d.ts +0 -1
  45. package/dist/TaskforceCore.CategoryFallback.test.js +0 -101
  46. package/dist/TaskforceCore.filter-persistence.test.d.ts +0 -1
  47. package/dist/TaskforceCore.filter-persistence.test.js +0 -402
  48. package/dist/TaskforceCore.routing.test.d.ts +0 -1
  49. package/dist/TaskforceCore.routing.test.js +0 -311
  50. package/dist/TaskforceCore.test.d.ts +0 -1
  51. package/dist/TaskforceCore.test.js +0 -7910
  52. package/dist/TaskforceWidget.test.d.ts +0 -1
  53. package/dist/TaskforceWidget.test.js +0 -92
  54. package/dist/UnsavedChangesRelaxed.test.d.ts +0 -1
  55. package/dist/UnsavedChangesRelaxed.test.js +0 -16
  56. package/dist/__tests__/localizationCatalogs.test.d.ts +0 -1
  57. package/dist/__tests__/localizationCatalogs.test.js +0 -54
  58. package/dist/__tests__/workflowSimulation.test.d.ts +0 -1
  59. package/dist/__tests__/workflowSimulation.test.js +0 -113
  60. package/dist/annotatedAttachments/AnnotatedAttachmentSessionStore.test.d.ts +0 -1
  61. package/dist/annotatedAttachments/AnnotatedAttachmentSessionStore.test.js +0 -278
  62. package/dist/annotatedAttachments/payload.test.d.ts +0 -1
  63. package/dist/annotatedAttachments/payload.test.js +0 -67
  64. package/dist/compat/workspaceSyncCompat.test.d.ts +0 -1
  65. package/dist/compat/workspaceSyncCompat.test.js +0 -124
  66. package/dist/components/features/AgentsModule.test.d.ts +0 -1
  67. package/dist/components/features/AgentsModule.test.js +0 -601
  68. package/dist/components/features/AnnotatedAttachmentWorkspace.test.d.ts +0 -1
  69. package/dist/components/features/AnnotatedAttachmentWorkspace.test.js +0 -2883
  70. package/dist/components/features/DocumentWorkspace.test.d.ts +0 -1
  71. package/dist/components/features/DocumentWorkspace.test.js +0 -1439
  72. package/dist/components/features/TaskSettings.test.d.ts +0 -1
  73. package/dist/components/features/TaskSettings.test.js +0 -1674
  74. package/dist/components/features/settings/TaxonomyLibraryManager.test.d.ts +0 -1
  75. package/dist/components/features/settings/TaxonomyLibraryManager.test.js +0 -141
  76. package/dist/components/task/TaskActionHeader.test.d.ts +0 -1
  77. package/dist/components/task/TaskActionHeader.test.js +0 -91
  78. package/dist/components/task/TaskCard.test.d.ts +0 -1
  79. package/dist/components/task/TaskCard.test.js +0 -513
  80. package/dist/components/task/TaskContextUpload.test.d.ts +0 -1
  81. package/dist/components/task/TaskContextUpload.test.js +0 -506
  82. package/dist/components/task/TaskForm.test.d.ts +0 -1
  83. package/dist/components/task/TaskForm.test.js +0 -946
  84. package/dist/components/task/TaskKanban.empty-column-drop.test.d.ts +0 -1
  85. package/dist/components/task/TaskKanban.empty-column-drop.test.js +0 -66
  86. package/dist/components/task/TaskKanban.planning-drop.test.d.ts +0 -1
  87. package/dist/components/task/TaskKanban.planning-drop.test.js +0 -93
  88. package/dist/components/task/TaskKanban.test.d.ts +0 -1
  89. package/dist/components/task/TaskKanban.test.js +0 -99
  90. package/dist/components/task/TaskList.test.d.ts +0 -1
  91. package/dist/components/task/TaskList.test.js +0 -473
  92. package/dist/components/task/TaskStatusActions.test.d.ts +0 -1
  93. package/dist/components/task/TaskStatusActions.test.js +0 -54
  94. package/dist/components/task/taskKanbanDropRules.test.d.ts +0 -1
  95. package/dist/components/task/taskKanbanDropRules.test.js +0 -114
  96. package/dist/components/ui/LevelSelector.test.d.ts +0 -1
  97. package/dist/components/ui/LevelSelector.test.js +0 -55
  98. package/dist/components/ui/Markdown.test.d.ts +0 -1
  99. package/dist/components/ui/Markdown.test.js +0 -38
  100. package/dist/components/ui/MultiSelectFilter.test.d.ts +0 -1
  101. package/dist/components/ui/MultiSelectFilter.test.js +0 -74
  102. package/dist/components/ui/TaxonomyDropdown.test.d.ts +0 -1
  103. package/dist/components/ui/TaxonomyDropdown.test.js +0 -130
  104. package/dist/components/ui/TopNoticeLayer.test.d.ts +0 -1
  105. package/dist/components/ui/TopNoticeLayer.test.js +0 -25
  106. package/dist/components/views/AppShellHeader.test.d.ts +0 -1
  107. package/dist/components/views/AppShellHeader.test.js +0 -42
  108. package/dist/components/views/PlanComparisonPage.test.d.ts +0 -1
  109. package/dist/components/views/PlanComparisonPage.test.js +0 -757
  110. package/dist/components/views/PlansPage.test.d.ts +0 -1
  111. package/dist/components/views/PlansPage.test.js +0 -710
  112. package/dist/components/views/chrome/WorkspaceChromeSections.test.d.ts +0 -1
  113. package/dist/components/views/chrome/WorkspaceChromeSections.test.js +0 -54
  114. package/dist/components/views/chrome/workspaceChrome.test.d.ts +0 -1
  115. package/dist/components/views/chrome/workspaceChrome.test.js +0 -52
  116. package/dist/components/views/panels/DocumentFilterToolbar.test.d.ts +0 -1
  117. package/dist/components/views/panels/DocumentFilterToolbar.test.js +0 -19
  118. package/dist/components/views/panels/FilterToolbar.test.d.ts +0 -1
  119. package/dist/components/views/panels/FilterToolbar.test.js +0 -47
  120. package/dist/components/views/panels/PlanningDrawer.test.d.ts +0 -1
  121. package/dist/components/views/panels/PlanningDrawer.test.js +0 -529
  122. package/dist/components/views/planningScope.test.d.ts +0 -1
  123. package/dist/components/views/planningScope.test.js +0 -60
  124. package/dist/components/views/standalone/modals/AccountHubModal.test.d.ts +0 -1
  125. package/dist/components/views/standalone/modals/AccountHubModal.test.js +0 -66
  126. package/dist/components/views/standalone/modals/SyncEnableWarningModal.test.d.ts +0 -1
  127. package/dist/components/views/standalone/modals/SyncEnableWarningModal.test.js +0 -24
  128. package/dist/components/views/teamManagementAccess.test.d.ts +0 -1
  129. package/dist/components/views/teamManagementAccess.test.js +0 -44
  130. package/dist/config/deployment.test.d.ts +0 -1
  131. package/dist/config/deployment.test.js +0 -90
  132. package/dist/config/envSchema.test.d.ts +0 -1
  133. package/dist/config/envSchema.test.js +0 -125
  134. package/dist/core/AiProfileService.test.d.ts +0 -1
  135. package/dist/core/AiProfileService.test.js +0 -184
  136. package/dist/core/AiProfiles.test.d.ts +0 -1
  137. package/dist/core/AiProfiles.test.js +0 -1873
  138. package/dist/core/AuthTokenService.test.d.ts +0 -1
  139. package/dist/core/AuthTokenService.test.js +0 -78
  140. package/dist/core/BulkUpdateFieldsPreview.test.d.ts +0 -1
  141. package/dist/core/BulkUpdateFieldsPreview.test.js +0 -62
  142. package/dist/core/CompletedAt.test.d.ts +0 -1
  143. package/dist/core/CompletedAt.test.js +0 -44
  144. package/dist/core/CreatedBy.test.d.ts +0 -1
  145. package/dist/core/CreatedBy.test.js +0 -188
  146. package/dist/core/DeletedTaskTrash.test.d.ts +0 -1
  147. package/dist/core/DeletedTaskTrash.test.js +0 -104
  148. package/dist/core/EntitlementsPolicy.test.d.ts +0 -1
  149. package/dist/core/EntitlementsPolicy.test.js +0 -280
  150. package/dist/core/GlobalSettingsService.test.d.ts +0 -1
  151. package/dist/core/GlobalSettingsService.test.js +0 -45
  152. package/dist/core/JsonBackupRuntime.test.d.ts +0 -1
  153. package/dist/core/JsonBackupRuntime.test.js +0 -155
  154. package/dist/core/PlanFeatureCatalog.test.d.ts +0 -1
  155. package/dist/core/PlanFeatureCatalog.test.js +0 -139
  156. package/dist/core/PlanVersionPolicy.test.d.ts +0 -1
  157. package/dist/core/PlanVersionPolicy.test.js +0 -204
  158. package/dist/core/PlanningEntities.test.d.ts +0 -1
  159. package/dist/core/PlanningEntities.test.js +0 -509
  160. package/dist/core/ScheduleFields.test.d.ts +0 -1
  161. package/dist/core/ScheduleFields.test.js +0 -193
  162. package/dist/core/SetupState.test.d.ts +0 -1
  163. package/dist/core/SetupState.test.js +0 -113
  164. package/dist/core/SignupMonetizationSettings.test.d.ts +0 -1
  165. package/dist/core/SignupMonetizationSettings.test.js +0 -515
  166. package/dist/core/Stats.test.d.ts +0 -1
  167. package/dist/core/Stats.test.js +0 -36
  168. package/dist/core/SystemAdmin.test.d.ts +0 -1
  169. package/dist/core/SystemAdmin.test.js +0 -1106
  170. package/dist/core/TaskActivitySync.test.d.ts +0 -1
  171. package/dist/core/TaskActivitySync.test.js +0 -90
  172. package/dist/core/TaskAttachmentsCanonical.test.d.ts +0 -1
  173. package/dist/core/TaskAttachmentsCanonical.test.js +0 -356
  174. package/dist/core/TaskAuditTimeline.test.d.ts +0 -1
  175. package/dist/core/TaskAuditTimeline.test.js +0 -319
  176. package/dist/core/TaskTaxonomyValidation.test.d.ts +0 -1
  177. package/dist/core/TaskTaxonomyValidation.test.js +0 -440
  178. package/dist/core/Taskforce.ids.test.d.ts +0 -1
  179. package/dist/core/Taskforce.ids.test.js +0 -611
  180. package/dist/core/Taskforce.listTasksSlim.test.d.ts +0 -1
  181. package/dist/core/Taskforce.listTasksSlim.test.js +0 -91
  182. package/dist/core/Taskforce.mcpAuth.test.d.ts +0 -1
  183. package/dist/core/Taskforce.mcpAuth.test.js +0 -450
  184. package/dist/core/Taskforce.realtimeMutation.test.d.ts +0 -1
  185. package/dist/core/Taskforce.realtimeMutation.test.js +0 -131
  186. package/dist/core/UserProfileAvatarDrafts.test.d.ts +0 -1
  187. package/dist/core/UserProfileAvatarDrafts.test.js +0 -138
  188. package/dist/core/WorkspaceDelete.test.d.ts +0 -1
  189. package/dist/core/WorkspaceDelete.test.js +0 -159
  190. package/dist/core/WorkspacePermissions.test.d.ts +0 -1
  191. package/dist/core/WorkspacePermissions.test.js +0 -270
  192. package/dist/core/WorkspacePlanMode.test.d.ts +0 -1
  193. package/dist/core/WorkspacePlanMode.test.js +0 -383
  194. package/dist/core/WorkspaceSyncSettings.test.d.ts +0 -1
  195. package/dist/core/WorkspaceSyncSettings.test.js +0 -65
  196. package/dist/core/__tests__/TaskAttachmentsCanonical.test.d.ts +0 -1
  197. package/dist/core/__tests__/TaskAttachmentsCanonical.test.js +0 -212
  198. package/dist/documentReviews/DocumentReviewSessionStore.test.d.ts +0 -1
  199. package/dist/documentReviews/DocumentReviewSessionStore.test.js +0 -127
  200. package/dist/hooks/authGuardPolicy.test.d.ts +0 -1
  201. package/dist/hooks/authGuardPolicy.test.js +0 -76
  202. package/dist/hooks/bootstrapTimeouts.test.d.ts +0 -1
  203. package/dist/hooks/bootstrapTimeouts.test.js +0 -12
  204. package/dist/hooks/sync/controlPlane.test.d.ts +0 -1
  205. package/dist/hooks/sync/controlPlane.test.js +0 -121
  206. package/dist/hooks/sync/lifecyclePolicy.test.d.ts +0 -1
  207. package/dist/hooks/sync/lifecyclePolicy.test.js +0 -124
  208. package/dist/hooks/sync/orchestratorShared.test.d.ts +0 -1
  209. package/dist/hooks/sync/orchestratorShared.test.js +0 -98
  210. package/dist/hooks/sync/pullLifecycle.test.d.ts +0 -1
  211. package/dist/hooks/sync/pullLifecycle.test.js +0 -80
  212. package/dist/hooks/sync/recovery.test.d.ts +0 -1
  213. package/dist/hooks/sync/recovery.test.js +0 -292
  214. package/dist/hooks/sync/transfers.test.d.ts +0 -1
  215. package/dist/hooks/sync/transfers.test.js +0 -928
  216. package/dist/hooks/sync/useRecentSyncEvents.test.d.ts +0 -1
  217. package/dist/hooks/sync/useRecentSyncEvents.test.js +0 -124
  218. package/dist/hooks/sync/useSyncStatusActions.test.d.ts +0 -1
  219. package/dist/hooks/sync/useSyncStatusActions.test.js +0 -133
  220. package/dist/hooks/sync/useSyncStatusControls.test.d.ts +0 -1
  221. package/dist/hooks/sync/useSyncStatusControls.test.js +0 -88
  222. package/dist/hooks/useFilterSort.test.d.ts +0 -1
  223. package/dist/hooks/useFilterSort.test.js +0 -419
  224. package/dist/hooks/useRealtimeSync.test.d.ts +0 -1
  225. package/dist/hooks/useRealtimeSync.test.js +0 -311
  226. package/dist/hooks/useSyncOrchestrator.aiProfiles.test.d.ts +0 -1
  227. package/dist/hooks/useSyncOrchestrator.aiProfiles.test.js +0 -54
  228. package/dist/hooks/useSyncOrchestrator.context-assets.test.d.ts +0 -1
  229. package/dist/hooks/useSyncOrchestrator.context-assets.test.js +0 -228
  230. package/dist/hooks/useSyncOrchestrator.retry-closure.test.d.ts +0 -1
  231. package/dist/hooks/useSyncOrchestrator.retry-closure.test.js +0 -2027
  232. package/dist/hooks/useTaskData.test.d.ts +0 -1
  233. package/dist/hooks/useTaskData.test.js +0 -291
  234. package/dist/hooks/useTaskMutations.test.d.ts +0 -1
  235. package/dist/hooks/useTaskMutations.test.js +0 -256
  236. package/dist/hooks/useTaskforce.contract.test.d.ts +0 -1
  237. package/dist/hooks/useTaskforce.contract.test.js +0 -7
  238. package/dist/hooks/useTaskforce.priority-filters.test.d.ts +0 -1
  239. package/dist/hooks/useTaskforce.priority-filters.test.js +0 -28
  240. package/dist/hooks/useTaskforce.runtime-routing.test.d.ts +0 -1
  241. package/dist/hooks/useTaskforce.runtime-routing.test.js +0 -246
  242. package/dist/hooks/useTaskforce.sync-behavior.test.d.ts +0 -1
  243. package/dist/hooks/useTaskforce.sync-behavior.test.js +0 -3644
  244. package/dist/hooks/useWorkspaceSyncController.test.d.ts +0 -1
  245. package/dist/hooks/useWorkspaceSyncController.test.js +0 -192
  246. package/dist/hooks/workspace/useTaskforceApiRouting.test.d.ts +0 -1
  247. package/dist/hooks/workspace/useTaskforceApiRouting.test.js +0 -77
  248. package/dist/hooks/workspace/workspaceLocalState.test.d.ts +0 -1
  249. package/dist/hooks/workspace/workspaceLocalState.test.js +0 -59
  250. package/dist/localization/localizationCatalogs.test.d.ts +0 -1
  251. package/dist/localization/localizationCatalogs.test.js +0 -37
  252. package/dist/mcp/aiProfileBootstrap.test.d.ts +0 -1
  253. package/dist/mcp/aiProfileBootstrap.test.js +0 -68
  254. package/dist/mcp/canonicalAssetHelpers.test.d.ts +0 -1
  255. package/dist/mcp/canonicalAssetHelpers.test.js +0 -67
  256. package/dist/mcp/clientIntegrations.test.d.ts +0 -1
  257. package/dist/mcp/clientIntegrations.test.js +0 -219
  258. package/dist/mcp/optionResolution.test.d.ts +0 -1
  259. package/dist/mcp/optionResolution.test.js +0 -43
  260. package/dist/mcp/runtime.test.d.ts +0 -1
  261. package/dist/mcp/runtime.test.js +0 -5120
  262. package/dist/mcp/structuredCommentValidation.test.d.ts +0 -1
  263. package/dist/mcp/structuredCommentValidation.test.js +0 -31
  264. package/dist/mcp/structuredDocValidation.test.d.ts +0 -1
  265. package/dist/mcp/structuredDocValidation.test.js +0 -35
  266. package/dist/mcp/toolRegistry.test.d.ts +0 -1
  267. package/dist/mcp/toolRegistry.test.js +0 -34
  268. package/dist/migrations/billingSchemaParity.test.d.ts +0 -1
  269. package/dist/migrations/billingSchemaParity.test.js +0 -160
  270. package/dist/migrations/taskSchemaMigrations.test.d.ts +0 -1
  271. package/dist/migrations/taskSchemaMigrations.test.js +0 -225
  272. package/dist/qaOpen.test.d.ts +0 -1
  273. package/dist/qaOpen.test.js +0 -56
  274. package/dist/releaseVersion.test.d.ts +0 -1
  275. package/dist/releaseVersion.test.js +0 -32
  276. package/dist/runtime/appGates.test.d.ts +0 -1
  277. package/dist/runtime/appGates.test.js +0 -42
  278. package/dist/server/aiProfileAvatarAssets.test.d.ts +0 -1
  279. package/dist/server/aiProfileAvatarAssets.test.js +0 -213
  280. package/dist/server/annotatedAttachmentsRoutes.test.d.ts +0 -1
  281. package/dist/server/annotatedAttachmentsRoutes.test.js +0 -532
  282. package/dist/server/auth.test.d.ts +0 -1
  283. package/dist/server/auth.test.js +0 -131
  284. package/dist/server/buildInfo.test.d.ts +0 -1
  285. package/dist/server/buildInfo.test.js +0 -29
  286. package/dist/server/cors.test.d.ts +0 -1
  287. package/dist/server/cors.test.js +0 -77
  288. package/dist/server/documentReviewRoutes.test.d.ts +0 -1
  289. package/dist/server/documentReviewRoutes.test.js +0 -190
  290. package/dist/server/email.test.d.ts +0 -1
  291. package/dist/server/email.test.js +0 -113
  292. package/dist/server/index.cookieProxy.test.d.ts +0 -1
  293. package/dist/server/index.cookieProxy.test.js +0 -67
  294. package/dist/server/index.rateLimit.test.d.ts +0 -1
  295. package/dist/server/index.rateLimit.test.js +0 -22
  296. package/dist/server/index.test.d.ts +0 -1
  297. package/dist/server/index.test.js +0 -283
  298. package/dist/server/rateLimit.test.d.ts +0 -1
  299. package/dist/server/rateLimit.test.js +0 -107
  300. package/dist/server/realtimeSync.auth.test.d.ts +0 -1
  301. package/dist/server/realtimeSync.auth.test.js +0 -62
  302. package/dist/server/realtimeSync.replay.test.d.ts +0 -1
  303. package/dist/server/realtimeSync.replay.test.js +0 -192
  304. package/dist/server/realtimeSync.workspaceIsolation.test.d.ts +0 -1
  305. package/dist/server/realtimeSync.workspaceIsolation.test.js +0 -101
  306. package/dist/server/routes/billing.test.d.ts +0 -1
  307. package/dist/server/routes/billing.test.js +0 -3455
  308. package/dist/server/routes/shared.test.d.ts +0 -1
  309. package/dist/server/routes/shared.test.js +0 -32
  310. package/dist/server/routes/sync.integration.test.d.ts +0 -1
  311. package/dist/server/routes/sync.integration.test.js +0 -2932
  312. package/dist/server/routes/syncAuxRoutes.test.d.ts +0 -1
  313. package/dist/server/routes/syncAuxRoutes.test.js +0 -158
  314. package/dist/server/routes/syncRouteGuards.test.d.ts +0 -1
  315. package/dist/server/routes/syncRouteGuards.test.js +0 -94
  316. package/dist/server/routes.test.d.ts +0 -1
  317. package/dist/server/routes.test.js +0 -15612
  318. package/dist/server/runtimeMode.test.d.ts +0 -1
  319. package/dist/server/runtimeMode.test.js +0 -26
  320. package/dist/server/securityHeaders.test.d.ts +0 -1
  321. package/dist/server/securityHeaders.test.js +0 -70
  322. package/dist/services/templateEngine.test.d.ts +0 -1
  323. package/dist/services/templateEngine.test.js +0 -150
  324. package/dist/services/templates.test.d.ts +0 -1
  325. package/dist/services/templates.test.js +0 -45
  326. package/dist/services/workflowDocumentFixtures.test.d.ts +0 -1
  327. package/dist/services/workflowDocumentFixtures.test.js +0 -78
  328. package/dist/services/workflowExportMatrix.test.d.ts +0 -1
  329. package/dist/services/workflowExportMatrix.test.js +0 -113
  330. package/dist/services/workflowExportSnapshots.test.d.ts +0 -1
  331. package/dist/services/workflowExportSnapshots.test.js +0 -30
  332. package/dist/services/workflowGeneration.test.d.ts +0 -1
  333. package/dist/services/workflowGeneration.test.js +0 -12
  334. package/dist/services/workflowSimulation.test.d.ts +0 -1
  335. package/dist/services/workflowSimulation.test.js +0 -113
  336. package/dist/services/workflowV2Policy.test.d.ts +0 -1
  337. package/dist/services/workflowV2Policy.test.js +0 -80
  338. package/dist/shared/customTaxonomyLibrary.test.d.ts +0 -1
  339. package/dist/shared/customTaxonomyLibrary.test.js +0 -20
  340. package/dist/shared/passwordPolicy.test.d.ts +0 -1
  341. package/dist/shared/passwordPolicy.test.js +0 -34
  342. package/dist/shared/runtimeContract.test.d.ts +0 -1
  343. package/dist/shared/runtimeContract.test.js +0 -23
  344. package/dist/shared/taxonomyLibrary.test.d.ts +0 -1
  345. package/dist/shared/taxonomyLibrary.test.js +0 -26
  346. package/dist/shared/taxonomyState.test.d.ts +0 -1
  347. package/dist/shared/taxonomyState.test.js +0 -71
  348. package/dist/soak/preflight.cli.d.ts +0 -1
  349. package/dist/soak/preflight.cli.js +0 -28
  350. package/dist/soak/preflight.d.ts +0 -26
  351. package/dist/soak/preflight.js +0 -113
  352. package/dist/soak/preflight.test.d.ts +0 -1
  353. package/dist/soak/preflight.test.js +0 -39
  354. package/dist/storage/objectStorageClient.test.d.ts +0 -1
  355. package/dist/storage/objectStorageClient.test.js +0 -82
  356. package/dist/storage/objectStorageConfig.test.d.ts +0 -1
  357. package/dist/storage/objectStorageConfig.test.js +0 -50
  358. package/dist/storage/postgresAdapter.test.d.ts +0 -1
  359. package/dist/storage/postgresAdapter.test.js +0 -29
  360. package/dist/storage/workspaceAssetStore.test.d.ts +0 -1
  361. package/dist/storage/workspaceAssetStore.test.js +0 -588
  362. package/dist/sync/cloudSyncApi.test.d.ts +0 -1
  363. package/dist/sync/cloudSyncApi.test.js +0 -111
  364. package/dist/sync/collaborationSyncPayload.test.d.ts +0 -1
  365. package/dist/sync/collaborationSyncPayload.test.js +0 -125
  366. package/dist/sync/contentSyncPayload.test.d.ts +0 -1
  367. package/dist/sync/contentSyncPayload.test.js +0 -143
  368. package/dist/sync/encryptionService.test.d.ts +0 -1
  369. package/dist/sync/encryptionService.test.js +0 -52
  370. package/dist/sync/planningSyncPayload.test.d.ts +0 -1
  371. package/dist/sync/planningSyncPayload.test.js +0 -92
  372. package/dist/sync/realtimeFeature.test.d.ts +0 -1
  373. package/dist/sync/realtimeFeature.test.js +0 -30
  374. package/dist/sync/realtimeReconcile.test.d.ts +0 -1
  375. package/dist/sync/realtimeReconcile.test.js +0 -43
  376. package/dist/sync/syncApplyHandlers.test.d.ts +0 -1
  377. package/dist/sync/syncApplyHandlers.test.js +0 -626
  378. package/dist/sync/syncService.test.d.ts +0 -1
  379. package/dist/sync/syncService.test.js +0 -903
  380. package/dist/sync/taskSyncPayload.test.d.ts +0 -1
  381. package/dist/sync/taskSyncPayload.test.js +0 -54
  382. package/dist/sync/workspacePullFeed.test.d.ts +0 -1
  383. package/dist/sync/workspacePullFeed.test.js +0 -438
  384. package/dist/sync/workspaceSyncModel.test.d.ts +0 -1
  385. package/dist/sync/workspaceSyncModel.test.js +0 -1442
  386. package/dist/test/setup.d.ts +0 -1
  387. package/dist/test/setup.js +0 -15
  388. package/dist/ui/assets/AgentsModule-BS4Pi_nC.js +0 -1
  389. package/dist/ui/assets/ContextAttachmentManager-CfG_ER7C.js +0 -3
  390. package/dist/ui/assets/PlansPage-B_z-D6Nh.css +0 -1
  391. package/dist/ui/assets/PlansPage-Ndt7mYfo.js +0 -1
  392. package/dist/ui/assets/documentReferences-BOUcJm6-.js +0 -1
  393. package/dist/ui/assets/index-MAHKvFqp.js +0 -4
  394. package/dist/utils/accountProfileSummaryCache.test.d.ts +0 -1
  395. package/dist/utils/accountProfileSummaryCache.test.js +0 -63
  396. package/dist/utils/annotatedAttachments.test.d.ts +0 -1
  397. package/dist/utils/annotatedAttachments.test.js +0 -108
  398. package/dist/utils/assignees.test.d.ts +0 -1
  399. package/dist/utils/assignees.test.js +0 -25
  400. package/dist/utils/avatarUpload.test.d.ts +0 -1
  401. package/dist/utils/avatarUpload.test.js +0 -40
  402. package/dist/utils/canonicalAssetKind.test.d.ts +0 -1
  403. package/dist/utils/canonicalAssetKind.test.js +0 -24
  404. package/dist/utils/coalescedRefresh.test.d.ts +0 -1
  405. package/dist/utils/coalescedRefresh.test.js +0 -30
  406. package/dist/utils/constants.icons.test.d.ts +0 -1
  407. package/dist/utils/constants.icons.test.js +0 -41
  408. package/dist/utils/planParser.test.d.ts +0 -1
  409. package/dist/utils/planParser.test.js +0 -183
  410. package/dist/utils/planningReferences.test.d.ts +0 -1
  411. package/dist/utils/planningReferences.test.js +0 -17
  412. package/dist/utils/syncEventDetails.test.d.ts +0 -1
  413. package/dist/utils/syncEventDetails.test.js +0 -23
  414. package/dist/utils/syncEventPresentation.test.d.ts +0 -1
  415. package/dist/utils/syncEventPresentation.test.js +0 -64
  416. package/dist/utils/syncStatusPresentation.test.d.ts +0 -1
  417. package/dist/utils/syncStatusPresentation.test.js +0 -164
  418. package/dist/utils/taskActivity.test.d.ts +0 -1
  419. package/dist/utils/taskActivity.test.js +0 -218
  420. package/dist/utils/taskDraftDefaults.test.d.ts +0 -1
  421. package/dist/utils/taskDraftDefaults.test.js +0 -34
  422. package/dist/utils/taskDragZones.test.d.ts +0 -1
  423. package/dist/utils/taskDragZones.test.js +0 -14
  424. package/dist/utils/taskNormalization.test.d.ts +0 -1
  425. package/dist/utils/taskNormalization.test.js +0 -158
  426. package/dist/utils/taskSearch.test.d.ts +0 -1
  427. package/dist/utils/taskSearch.test.js +0 -69
  428. package/dist/utils/taskUtils.test.d.ts +0 -1
  429. package/dist/utils/taskUtils.test.js +0 -19
  430. package/dist/utils/taskforceApiClient.test.d.ts +0 -1
  431. package/dist/utils/taskforceApiClient.test.js +0 -44
  432. package/dist/utils/taxonomyFormDefaults.test.d.ts +0 -1
  433. package/dist/utils/taxonomyFormDefaults.test.js +0 -63
  434. package/dist/utils/uiNotice.test.d.ts +0 -1
  435. package/dist/utils/uiNotice.test.js +0 -18
  436. package/dist/utils/workspaceIdentity.test.d.ts +0 -1
  437. package/dist/utils/workspaceIdentity.test.js +0 -61
  438. package/dist/utils/workspaceLifecycle.test.d.ts +0 -1
  439. package/dist/utils/workspaceLifecycle.test.js +0 -64
  440. package/dist/utils/workspaceSyncPresentation.test.d.ts +0 -1
  441. package/dist/utils/workspaceSyncPresentation.test.js +0 -71
  442. package/scripts/bootstrap-playwright-auth.mjs +0 -155
  443. package/scripts/check-cloud-mcp.mjs +0 -83
  444. package/scripts/check-compat-boundaries.mjs +0 -41
  445. package/scripts/check-env.ts +0 -31
  446. package/scripts/check-localization-strings.mjs +0 -49
  447. package/scripts/check-runtime-boundaries.mjs +0 -44
  448. package/scripts/debug-global.mjs +0 -34
  449. package/scripts/debug-login.mjs +0 -32
  450. package/scripts/debug-server.mjs +0 -36
  451. package/scripts/deploy-prod.sh +0 -41
  452. package/scripts/deploy-staging.sh +0 -23
  453. package/scripts/export-sqlite-to-postgres.mjs +0 -123
  454. package/scripts/generate-env-example.ts +0 -8
  455. package/scripts/mcp-stdio-adapter.mjs +0 -160
  456. package/scripts/migrate-task-data-assets.mjs +0 -408
  457. package/scripts/playwright-auth.sh +0 -19
  458. package/scripts/qa-open-lib.mjs +0 -175
  459. package/scripts/qa-open-lib.mjs.d.ts +0 -49
  460. package/scripts/qa-open.mjs +0 -352
  461. package/scripts/release-version-lib.mjs +0 -88
  462. package/scripts/release-version.mjs +0 -72
  463. package/scripts/run-billing-performance-smoke.sh +0 -24
  464. package/scripts/run-dev-proxy.sh +0 -51
  465. package/scripts/run-e2e-realtime.sh +0 -30
  466. package/scripts/run-smoke.sh +0 -35
  467. package/scripts/run-soak.sh +0 -41
  468. package/scripts/test-global.js +0 -143
  469. package/scripts/update-homebrew-formula.sh +0 -108
  470. package/scripts/with-esbuild.sh +0 -11
@@ -1,928 +0,0 @@
1
- import { beforeEach, describe, expect, it, vi } from 'vitest';
2
- import { createWorkspaceTransferCoordinator } from './transfers';
3
- const { runWorkspacePullSyncServiceMock, runWorkspacePushSyncServiceMock } = vi.hoisted(() => ({
4
- runWorkspacePullSyncServiceMock: vi.fn(),
5
- runWorkspacePushSyncServiceMock: vi.fn()
6
- }));
7
- vi.mock('../../sync/syncService', async () => {
8
- const actual = await vi.importActual('../../sync/syncService');
9
- return {
10
- ...actual,
11
- runWorkspacePullSyncService: runWorkspacePullSyncServiceMock,
12
- runWorkspacePushSyncService: runWorkspacePushSyncServiceMock
13
- };
14
- });
15
- function ref(current) {
16
- return { current };
17
- }
18
- function createCoordinator(overrides) {
19
- const persistWorkspaceSyncPatchSafely = (overrides?.persistWorkspaceSyncPatchSafely ?? vi.fn());
20
- const scheduleWorkspaceSyncRetry = (overrides?.scheduleWorkspaceSyncRetry ?? vi.fn());
21
- const reportSyncEvent = vi.fn();
22
- const workspacePendingPushReplayRef = ref(null);
23
- const coordinator = createWorkspaceTransferCoordinator({
24
- cloudAuthConfigured: true,
25
- runtimeMode: 'local',
26
- workspaceCloudSyncEnabled: true,
27
- currentWorkspaceId: 'workspace-local-active',
28
- workspaceSyncPhase: 'active',
29
- isAuthenticated: true,
30
- checkAuthSession: vi.fn(async () => true),
31
- resolveCloudAuthUrl: (path) => `https://cloud.example.com${path}`,
32
- ensureCloudWorkspaceReadyForSync: vi.fn(async () => ({ success: true })),
33
- ensureWorkspaceSyncReady: vi.fn(async () => true),
34
- handleSyncAuthFailure: vi.fn(async () => { }),
35
- clearWorkspaceRetry: vi.fn(),
36
- clearWorkspaceIssue: vi.fn(),
37
- isWorkspaceRetryPending: vi.fn(() => false),
38
- scheduleWorkspaceSyncRetry,
39
- persistWorkspaceSyncPatchSafely,
40
- persistWorkspaceSyncPatchBestEffort: vi.fn(async () => { }),
41
- persistWorkspaceSyncWatermarksSnapshotBestEffort: vi.fn(() => true),
42
- reportSyncEvent,
43
- acquireWorkspaceSyncLease: vi.fn(async () => true),
44
- releaseWorkspaceSyncLease: vi.fn(),
45
- reportWorkspaceWindowContention: vi.fn(),
46
- refreshWorkspaceSyncMarkdownDocumentsSnapshot: vi.fn(async () => { }),
47
- refreshWorkspaceSyncAiProfilesSnapshot: vi.fn(async () => { }),
48
- refreshWorkspaceSyncAssetsSnapshot: vi.fn(async () => { }),
49
- refreshWorkspaceSyncPlanningEntitiesSnapshot: overrides?.refreshWorkspaceSyncPlanningEntitiesSnapshot ?? vi.fn(async () => { }),
50
- refreshWorkspaceSyncDocumentReviewSessionsSnapshot: vi.fn(async () => { }),
51
- refreshWorkspaceSyncAnnotatedAttachmentSessionsSnapshot: vi.fn(async () => { }),
52
- refreshLocalWorkspaceTaskCollections: overrides?.refreshLocalWorkspaceTaskCollections ?? vi.fn(async () => { }),
53
- buildWorkspaceSyncPayload: (overrides?.buildWorkspaceSyncPayload ?? vi.fn(() => ({
54
- changes: [],
55
- currentTaskIds: new Set(),
56
- deleteTaskIds: new Set(),
57
- currentInitiativeIds: new Set(),
58
- currentInitiativeWatermarks: new Map(),
59
- currentWorkstreamIds: new Set(),
60
- currentWorkstreamWatermarks: new Map(),
61
- currentAiProfileIds: new Set(),
62
- currentAiProfileWatermarks: new Map(),
63
- currentDocumentPaths: new Set(),
64
- deleteDocumentPaths: new Set(),
65
- currentDocumentWatermarks: new Map(),
66
- currentAssetPaths: new Set(),
67
- deleteAssetPaths: new Set(),
68
- currentAssetWatermarks: new Map(),
69
- currentDocumentReviewSessionIds: new Set(),
70
- deleteDocumentReviewSessionIds: new Set(),
71
- currentDocumentReviewSessionWatermarks: new Map(),
72
- currentDocumentReviewCommentIds: new Set(),
73
- deleteDocumentReviewCommentIds: new Set(),
74
- currentDocumentReviewCommentWatermarks: new Map(),
75
- currentAnnotatedAttachmentSessionIds: new Set(),
76
- deleteAnnotatedAttachmentSessionIds: new Set(),
77
- currentAnnotatedAttachmentSessionWatermarks: new Map(),
78
- currentTaskEventWatermarks: new Map(),
79
- pushedWatermarks: new Map()
80
- }))),
81
- buildWorkspaceSyncSignature: overrides?.buildWorkspaceSyncSignature ?? vi.fn(() => 'sync-signature'),
82
- seedWorkspaceSnapshotPushBaseline: vi.fn(),
83
- shouldSuppressAttachBootstrapPush: vi.fn(() => false),
84
- recordSuppressedEventIds: vi.fn(),
85
- workspaceRepairModeRef: ref(false),
86
- workspaceForceFullAiProfilePushRef: ref(false),
87
- workspacePushInFlightRef: ref(false),
88
- workspacePullInFlightRef: ref(false),
89
- workspacePendingPushReplayRef,
90
- workspaceLastPushedSignatureRef: ref(''),
91
- workspacePendingSignatureRef: ref(''),
92
- workspaceLastPushedTaskIdsRef: ref(new Set()),
93
- workspaceDeletedTaskIdsRef: ref(new Set()),
94
- workspaceDeletedTaskWatermarksRef: ref(new Map()),
95
- workspacePullCursorRef: ref('stale-cursor'),
96
- workspaceLastPushedWatermarksRef: ref(new Map()),
97
- workspaceLastPushedTaskChangeKeysRef: ref(new Map()),
98
- workspaceLastPushedInitiativeIdsRef: ref(new Set()),
99
- workspaceLastPushedInitiativeWatermarksRef: ref(new Map()),
100
- workspaceLastPushedWorkstreamIdsRef: ref(new Set()),
101
- workspaceLastPushedWorkstreamWatermarksRef: ref(new Map()),
102
- workspaceLastPushedAiProfileIdsRef: ref(new Set()),
103
- workspaceLastPushedAiProfileWatermarksRef: ref(new Map()),
104
- workspaceLastPushedAiProfileChangeKeysRef: ref(new Map()),
105
- workspaceLastPushedDocumentPathsRef: ref(new Set()),
106
- workspaceLastPushedDocumentWatermarksRef: ref(new Map()),
107
- workspaceLastPushedAssetPathsRef: ref(new Set()),
108
- workspaceLastPushedAssetWatermarksRef: ref(new Map()),
109
- workspaceLastPushedDocumentReviewSessionIdsRef: ref(new Set()),
110
- workspaceLastPushedDocumentReviewSessionWatermarksRef: ref(new Map()),
111
- workspaceLastPushedDocumentReviewCommentIdsRef: ref(new Set()),
112
- workspaceLastPushedDocumentReviewCommentWatermarksRef: ref(new Map()),
113
- workspaceLastPushedAnnotatedAttachmentSessionIdsRef: ref(new Set()),
114
- workspaceLastPushedAnnotatedAttachmentSessionWatermarksRef: ref(new Map()),
115
- workspaceLastPushedTaskEventWatermarksRef: ref(new Map()),
116
- workspaceBaselineResetReasonRef: ref(null),
117
- workspaceCaptureAttachBootstrapBaselineRef: ref(false),
118
- workspaceStartupFullReconcileRanRef: ref(false),
119
- workspaceFullReconcileInFlightRef: ref(false),
120
- bootstrapLastProgressAtRef: ref(null),
121
- realtimeSuppressedEventQueueRef: ref([]),
122
- setWorkspaceSyncBusy: vi.fn(),
123
- setUserGlobalSyncStatus: vi.fn(),
124
- setUserGlobalSyncError: vi.fn(),
125
- setWorkspaceLastErrorMessage: vi.fn(),
126
- setWorkspaceLastErrorAt: vi.fn(),
127
- setWorkspaceLastPullAt: vi.fn(),
128
- setWorkspaceLastPushAt: vi.fn(),
129
- setWorkspaceSyncPendingChanges: vi.fn(),
130
- setTasks: vi.fn(),
131
- setArchivedTasks: vi.fn()
132
- });
133
- return { coordinator, persistWorkspaceSyncPatchSafely, scheduleWorkspaceSyncRetry, reportSyncEvent, workspacePendingPushReplayRef };
134
- }
135
- describe('createWorkspaceTransferCoordinator', () => {
136
- beforeEach(() => {
137
- runWorkspacePullSyncServiceMock.mockReset();
138
- runWorkspacePushSyncServiceMock.mockReset();
139
- });
140
- it('refreshes planning entity snapshots before building a push payload', async () => {
141
- const callOrder = [];
142
- const refreshWorkspaceSyncPlanningEntitiesSnapshot = vi.fn(async () => {
143
- callOrder.push('planning-refresh');
144
- });
145
- const buildWorkspaceSyncPayload = vi.fn(() => {
146
- callOrder.push('build-payload');
147
- return {
148
- changes: [],
149
- currentTaskIds: new Set(),
150
- deleteTaskIds: new Set(),
151
- currentInitiativeIds: new Set(),
152
- currentInitiativeWatermarks: new Map(),
153
- currentWorkstreamIds: new Set(),
154
- currentWorkstreamWatermarks: new Map(),
155
- currentAiProfileIds: new Set(),
156
- currentAiProfileWatermarks: new Map(),
157
- currentDocumentPaths: new Set(),
158
- deleteDocumentPaths: new Set(),
159
- currentDocumentWatermarks: new Map(),
160
- currentAssetPaths: new Set(),
161
- deleteAssetPaths: new Set(),
162
- currentAssetWatermarks: new Map(),
163
- currentDocumentReviewSessionIds: new Set(),
164
- deleteDocumentReviewSessionIds: new Set(),
165
- currentDocumentReviewSessionWatermarks: new Map(),
166
- currentDocumentReviewCommentIds: new Set(),
167
- deleteDocumentReviewCommentIds: new Set(),
168
- currentDocumentReviewCommentWatermarks: new Map(),
169
- currentAnnotatedAttachmentSessionIds: new Set(),
170
- deleteAnnotatedAttachmentSessionIds: new Set(),
171
- currentAnnotatedAttachmentSessionWatermarks: new Map(),
172
- currentTaskEventWatermarks: new Map(),
173
- pushedWatermarks: new Map()
174
- };
175
- });
176
- runWorkspacePushSyncServiceMock.mockResolvedValueOnce({
177
- success: true,
178
- syncedAt: '2026-04-27T16:00:00.000Z',
179
- requestMs: 1,
180
- changeCount: 0,
181
- deleteCount: 0,
182
- currentTaskIds: new Set(),
183
- currentTaskWatermarks: new Map(),
184
- currentTaskChangeKeys: new Map(),
185
- deleteTaskIds: new Set(),
186
- currentInitiativeIds: new Set(),
187
- currentInitiativeWatermarks: new Map(),
188
- currentWorkstreamIds: new Set(),
189
- currentWorkstreamWatermarks: new Map(),
190
- currentAiProfileIds: new Set(),
191
- currentAiProfileWatermarks: new Map(),
192
- currentAiProfileChangeKeys: new Map(),
193
- currentDocumentPaths: new Set(),
194
- currentDocumentWatermarks: new Map(),
195
- currentAssetPaths: new Set(),
196
- currentAssetWatermarks: new Map(),
197
- currentDocumentReviewSessionIds: new Set(),
198
- currentDocumentReviewSessionWatermarks: new Map(),
199
- currentDocumentReviewCommentIds: new Set(),
200
- currentDocumentReviewCommentWatermarks: new Map(),
201
- currentAnnotatedAttachmentSessionIds: new Set(),
202
- currentAnnotatedAttachmentSessionWatermarks: new Map(),
203
- currentTaskEventWatermarks: new Map(),
204
- pushedWatermarks: new Map(),
205
- emittedEventIds: [],
206
- appliedTaskUpserts: []
207
- });
208
- const { coordinator } = createCoordinator({
209
- buildWorkspaceSyncPayload,
210
- refreshWorkspaceSyncPlanningEntitiesSnapshot
211
- });
212
- const result = await coordinator.pushWorkspaceChangesToCloud('signature-1');
213
- expect(result).toBe(true);
214
- expect(refreshWorkspaceSyncPlanningEntitiesSnapshot).toHaveBeenCalledTimes(1);
215
- expect(buildWorkspaceSyncPayload).toHaveBeenCalledTimes(1);
216
- expect(callOrder).toEqual(['planning-refresh', 'build-payload']);
217
- });
218
- it('persists a cleared cursor before scheduling an invalid-cursor retry', async () => {
219
- runWorkspacePullSyncServiceMock.mockResolvedValueOnce({
220
- success: false,
221
- kind: 'pull_http',
222
- status: 400,
223
- errorCode: 'INVALID_SYNC_CURSOR',
224
- error: 'Invalid sync cursor.',
225
- cursor: 'stale-cursor',
226
- pages: 0,
227
- appliedChanges: 0,
228
- pullRequestMs: 1,
229
- applyMs: 0,
230
- pulledDeleteTaskIds: new Set(),
231
- pulledActiveUpserts: false,
232
- pulledArchivedUpserts: false,
233
- documentDecryptFailures: []
234
- });
235
- const { coordinator, persistWorkspaceSyncPatchSafely, scheduleWorkspaceSyncRetry } = createCoordinator();
236
- const result = await coordinator.pullWorkspaceChangesFromCloud();
237
- expect(result).toBe(false);
238
- expect(runWorkspacePullSyncServiceMock).toHaveBeenCalledWith(expect.objectContaining({
239
- cursor: 'stale-cursor'
240
- }));
241
- expect(persistWorkspaceSyncPatchSafely).toHaveBeenCalledWith({ pullCursor: null });
242
- expect(scheduleWorkspaceSyncRetry).toHaveBeenCalledWith(150);
243
- });
244
- it('refreshes local planning collections after planning-only pull changes', async () => {
245
- const refreshLocalWorkspaceTaskCollections = vi.fn(async () => { });
246
- runWorkspacePullSyncServiceMock.mockResolvedValueOnce({
247
- success: true,
248
- syncedAt: '2026-04-27T22:00:00.000Z',
249
- cursor: 'planning-cursor',
250
- pages: 1,
251
- appliedChanges: 1,
252
- pullRequestMs: 1,
253
- applyMs: 1,
254
- pulledDeleteTaskIds: new Set(),
255
- pulledActiveUpserts: false,
256
- pulledArchivedUpserts: false,
257
- pulledTaskEventUpserts: false,
258
- pulledPlanningUpserts: true,
259
- documentDecryptFailures: [],
260
- emittedEventIds: []
261
- });
262
- const { coordinator } = createCoordinator({ refreshLocalWorkspaceTaskCollections });
263
- const result = await coordinator.pullWorkspaceChangesFromCloud();
264
- expect(result).toBe(true);
265
- expect(refreshLocalWorkspaceTaskCollections).toHaveBeenCalledTimes(1);
266
- });
267
- it('reasserts all AI profiles after a full reconcile pull', async () => {
268
- vi.useFakeTimers();
269
- runWorkspacePullSyncServiceMock.mockResolvedValueOnce({
270
- success: true,
271
- syncedAt: '2026-03-15T19:30:00.000Z',
272
- cursor: 'fresh-cursor',
273
- pages: 1,
274
- appliedChanges: 0,
275
- pullRequestMs: 1,
276
- applyMs: 0,
277
- pulledDeleteTaskIds: new Set(),
278
- pulledActiveUpserts: false,
279
- pulledArchivedUpserts: false,
280
- documentDecryptFailures: []
281
- });
282
- runWorkspacePushSyncServiceMock.mockResolvedValueOnce({
283
- success: true,
284
- syncedAt: '2026-03-15T19:30:01.000Z',
285
- requestMs: 1,
286
- changeCount: 1,
287
- deleteCount: 0,
288
- currentTaskIds: new Set(),
289
- currentTaskWatermarks: new Map(),
290
- currentTaskChangeKeys: new Map(),
291
- deleteTaskIds: new Set(),
292
- currentInitiativeIds: new Set(),
293
- currentInitiativeWatermarks: new Map(),
294
- currentWorkstreamIds: new Set(),
295
- currentWorkstreamWatermarks: new Map(),
296
- currentAiProfileIds: new Set(['ai-profile-john-drake']),
297
- currentAiProfileWatermarks: new Map([['ai-profile-john-drake', '2026-03-15T19:00:00.000Z']]),
298
- currentAiProfileChangeKeys: new Map([['ai-profile-john-drake', 'john-change-key']]),
299
- currentDocumentPaths: new Set(),
300
- currentDocumentWatermarks: new Map(),
301
- currentAssetPaths: new Set(),
302
- currentAssetWatermarks: new Map(),
303
- currentDocumentReviewSessionIds: new Set(),
304
- currentDocumentReviewSessionWatermarks: new Map(),
305
- currentDocumentReviewCommentIds: new Set(),
306
- currentDocumentReviewCommentWatermarks: new Map(),
307
- currentAnnotatedAttachmentSessionIds: new Set(),
308
- currentAnnotatedAttachmentSessionWatermarks: new Map(),
309
- currentTaskEventWatermarks: new Map(),
310
- pushedWatermarks: new Map(),
311
- emittedEventIds: [],
312
- appliedTaskUpserts: []
313
- });
314
- const buildWorkspaceSyncPayload = vi.fn(() => ({
315
- changes: [{
316
- op: 'ai-profile-upsert',
317
- profile: {
318
- id: 'ai-profile-john-drake',
319
- workspaceId: 'workspace-local-active',
320
- profileToken: 'token-john',
321
- name: 'John Drake',
322
- username: 'john-drake',
323
- icon: 'Bot',
324
- color: '#8b5cf6',
325
- avatarUrl: null,
326
- avatarSourceUrl: null,
327
- description: null,
328
- role: null,
329
- provider: null,
330
- model: null,
331
- surfaceType: null,
332
- seatScope: null,
333
- providerMetadata: null,
334
- archivedAt: null,
335
- archivedBy: null,
336
- archivedReason: null,
337
- mergedIntoProfileId: null,
338
- rosterStateUpdatedAt: null,
339
- createdAt: '2026-03-15T19:00:00.000Z',
340
- updatedAt: '2026-03-15T19:00:00.000Z',
341
- lastActiveAt: null
342
- }
343
- }],
344
- currentTaskIds: new Set(),
345
- deleteTaskIds: new Set(),
346
- currentInitiativeIds: new Set(),
347
- currentInitiativeWatermarks: new Map(),
348
- currentWorkstreamIds: new Set(),
349
- currentWorkstreamWatermarks: new Map(),
350
- currentAiProfileIds: new Set(['ai-profile-john-drake']),
351
- currentAiProfileWatermarks: new Map([['ai-profile-john-drake', '2026-03-15T19:00:00.000Z']]),
352
- currentAiProfileChangeKeys: new Map([['ai-profile-john-drake', 'john-change-key']]),
353
- currentDocumentPaths: new Set(),
354
- deleteDocumentPaths: new Set(),
355
- currentDocumentWatermarks: new Map(),
356
- currentAssetPaths: new Set(),
357
- deleteAssetPaths: new Set(),
358
- currentAssetWatermarks: new Map(),
359
- currentDocumentReviewSessionIds: new Set(),
360
- deleteDocumentReviewSessionIds: new Set(),
361
- currentDocumentReviewSessionWatermarks: new Map(),
362
- currentDocumentReviewCommentIds: new Set(),
363
- deleteDocumentReviewCommentIds: new Set(),
364
- currentDocumentReviewCommentWatermarks: new Map(),
365
- currentAnnotatedAttachmentSessionIds: new Set(),
366
- deleteAnnotatedAttachmentSessionIds: new Set(),
367
- currentAnnotatedAttachmentSessionWatermarks: new Map(),
368
- currentTaskEventWatermarks: new Map(),
369
- pushedWatermarks: new Map()
370
- }));
371
- const { coordinator } = createCoordinator({ buildWorkspaceSyncPayload });
372
- await coordinator.pullWorkspaceChangesFromCloud({ forceCursorNull: true });
373
- await vi.advanceTimersByTimeAsync(130);
374
- await Promise.resolve();
375
- expect(runWorkspacePushSyncServiceMock).toHaveBeenCalledTimes(1);
376
- expect(buildWorkspaceSyncPayload).toHaveBeenCalledWith({ forceAllAiProfiles: true });
377
- expect(runWorkspacePushSyncServiceMock).toHaveBeenCalledWith(expect.objectContaining({
378
- payload: expect.objectContaining({
379
- changes: expect.arrayContaining([
380
- expect.objectContaining({
381
- op: 'ai-profile-upsert',
382
- profile: expect.objectContaining({
383
- id: 'ai-profile-john-drake',
384
- name: 'John Drake'
385
- })
386
- })
387
- ])
388
- })
389
- }));
390
- });
391
- it('reports push payload diagnostics when a push fails', async () => {
392
- runWorkspacePushSyncServiceMock.mockResolvedValueOnce({
393
- success: false,
394
- status: 524,
395
- error: '524 unknown',
396
- transient: true,
397
- requestMs: 125000,
398
- changeCount: 3,
399
- deleteCount: 0,
400
- currentTaskIds: new Set(),
401
- deleteTaskIds: new Set(),
402
- currentInitiativeIds: new Set(),
403
- currentInitiativeWatermarks: new Map(),
404
- currentWorkstreamIds: new Set(),
405
- currentWorkstreamWatermarks: new Map(),
406
- currentAiProfileIds: new Set(),
407
- currentAiProfileWatermarks: new Map(),
408
- currentDocumentPaths: new Set(),
409
- deleteDocumentPaths: new Set(),
410
- currentDocumentWatermarks: new Map(),
411
- currentAssetPaths: new Set(),
412
- deleteAssetPaths: new Set(),
413
- currentAssetWatermarks: new Map(),
414
- currentDocumentReviewSessionIds: new Set(),
415
- deleteDocumentReviewSessionIds: new Set(),
416
- currentDocumentReviewSessionWatermarks: new Map(),
417
- currentDocumentReviewCommentIds: new Set(),
418
- deleteDocumentReviewCommentIds: new Set(),
419
- currentDocumentReviewCommentWatermarks: new Map(),
420
- currentAnnotatedAttachmentSessionIds: new Set(),
421
- deleteAnnotatedAttachmentSessionIds: new Set(),
422
- currentAnnotatedAttachmentSessionWatermarks: new Map(),
423
- currentTaskEventWatermarks: new Map(),
424
- pushedWatermarks: new Map(),
425
- emittedEventIds: [],
426
- appliedTaskUpserts: []
427
- });
428
- const payloadDiagnostics = {
429
- totalChanges: 3,
430
- byOp: { 'document-upsert': 2, 'asset-upsert': 1 },
431
- baselineResetReason: 'repair-reset',
432
- domains: {
433
- tasks: { mode: 'none', reason: null, currentCount: 0, baselineCount: 0, changeCount: 0 },
434
- initiatives: { mode: 'none', reason: null, currentCount: 0, baselineCount: 0, changeCount: 0 },
435
- workstreams: { mode: 'none', reason: null, currentCount: 0, baselineCount: 0, changeCount: 0 },
436
- aiProfiles: { mode: 'none', reason: null, currentCount: 0, baselineCount: 0, changeCount: 0 },
437
- documents: { mode: 'send-all', reason: 'repair-reset', currentCount: 2, baselineCount: 0, changeCount: 2 },
438
- assets: { mode: 'send-all', reason: 'repair-reset', currentCount: 1, baselineCount: 0, changeCount: 1 },
439
- documentReviewSessions: { mode: 'none', reason: null, currentCount: 0, baselineCount: 0, changeCount: 0 },
440
- documentReviewComments: { mode: 'none', reason: null, currentCount: 0, baselineCount: 0, changeCount: 0 },
441
- annotatedAttachmentSessions: { mode: 'none', reason: null, currentCount: 0, baselineCount: 0, changeCount: 0 },
442
- taskEvents: { mode: 'none', reason: null, currentCount: 0, baselineCount: 0, changeCount: 0 },
443
- taxonomy: { mode: 'none', reason: null, currentCount: 0, baselineCount: 0, changeCount: 0 }
444
- }
445
- };
446
- const buildWorkspaceSyncPayload = vi.fn(() => ({
447
- changes: [],
448
- currentTaskIds: new Set(),
449
- deleteTaskIds: new Set(),
450
- currentInitiativeIds: new Set(),
451
- currentInitiativeWatermarks: new Map(),
452
- currentWorkstreamIds: new Set(),
453
- currentWorkstreamWatermarks: new Map(),
454
- currentAiProfileIds: new Set(),
455
- currentAiProfileWatermarks: new Map(),
456
- currentDocumentPaths: new Set(),
457
- deleteDocumentPaths: new Set(),
458
- currentDocumentWatermarks: new Map(),
459
- currentAssetPaths: new Set(),
460
- deleteAssetPaths: new Set(),
461
- currentAssetWatermarks: new Map(),
462
- currentDocumentReviewSessionIds: new Set(),
463
- deleteDocumentReviewSessionIds: new Set(),
464
- currentDocumentReviewSessionWatermarks: new Map(),
465
- currentDocumentReviewCommentIds: new Set(),
466
- deleteDocumentReviewCommentIds: new Set(),
467
- currentDocumentReviewCommentWatermarks: new Map(),
468
- currentAnnotatedAttachmentSessionIds: new Set(),
469
- deleteAnnotatedAttachmentSessionIds: new Set(),
470
- currentAnnotatedAttachmentSessionWatermarks: new Map(),
471
- currentTaskEventWatermarks: new Map(),
472
- pushedWatermarks: new Map(),
473
- deltaDiagnostics: payloadDiagnostics
474
- }));
475
- const { coordinator, reportSyncEvent } = createCoordinator({ buildWorkspaceSyncPayload });
476
- await coordinator.pushWorkspaceChangesToCloud('signature-1');
477
- expect(buildWorkspaceSyncPayload).toHaveBeenCalled();
478
- expect(reportSyncEvent).toHaveBeenCalledWith('workspace-local-active', expect.objectContaining({
479
- eventType: 'push',
480
- status: 'error',
481
- details: expect.objectContaining({
482
- payloadDiagnostics
483
- })
484
- }));
485
- });
486
- it('replays the same payload after a transient push failure before rebuilding a fresh one', async () => {
487
- const firstPayload = {
488
- changes: [],
489
- currentTaskIds: new Set(),
490
- deleteTaskIds: new Set(),
491
- currentInitiativeIds: new Set(),
492
- currentInitiativeWatermarks: new Map(),
493
- currentWorkstreamIds: new Set(),
494
- currentWorkstreamWatermarks: new Map(),
495
- currentAiProfileIds: new Set(),
496
- currentAiProfileWatermarks: new Map(),
497
- currentDocumentPaths: new Set(),
498
- deleteDocumentPaths: new Set(),
499
- currentDocumentWatermarks: new Map(),
500
- currentAssetPaths: new Set(),
501
- deleteAssetPaths: new Set(),
502
- currentAssetWatermarks: new Map(),
503
- currentDocumentReviewSessionIds: new Set(),
504
- deleteDocumentReviewSessionIds: new Set(),
505
- currentDocumentReviewSessionWatermarks: new Map(),
506
- currentDocumentReviewCommentIds: new Set(),
507
- deleteDocumentReviewCommentIds: new Set(),
508
- currentDocumentReviewCommentWatermarks: new Map(),
509
- currentAnnotatedAttachmentSessionIds: new Set(),
510
- deleteAnnotatedAttachmentSessionIds: new Set(),
511
- currentAnnotatedAttachmentSessionWatermarks: new Map(),
512
- currentTaskEventWatermarks: new Map(),
513
- pushedWatermarks: new Map()
514
- };
515
- const secondPayload = {
516
- ...firstPayload,
517
- deltaDiagnostics: {
518
- totalChanges: 9,
519
- byOp: { 'task-upsert': 9 },
520
- baselineResetReason: 'missing-baseline',
521
- domains: {
522
- tasks: { mode: 'delta', reason: null, currentCount: 9, baselineCount: 8, changeCount: 1 },
523
- initiatives: { mode: 'none', reason: null, currentCount: 0, baselineCount: 0, changeCount: 0 },
524
- workstreams: { mode: 'none', reason: null, currentCount: 0, baselineCount: 0, changeCount: 0 },
525
- aiProfiles: { mode: 'none', reason: null, currentCount: 0, baselineCount: 0, changeCount: 0 },
526
- documents: { mode: 'none', reason: null, currentCount: 0, baselineCount: 0, changeCount: 0 },
527
- assets: { mode: 'none', reason: null, currentCount: 0, baselineCount: 0, changeCount: 0 },
528
- documentReviewSessions: { mode: 'none', reason: null, currentCount: 0, baselineCount: 0, changeCount: 0 },
529
- documentReviewComments: { mode: 'none', reason: null, currentCount: 0, baselineCount: 0, changeCount: 0 },
530
- annotatedAttachmentSessions: { mode: 'none', reason: null, currentCount: 0, baselineCount: 0, changeCount: 0 },
531
- taskEvents: { mode: 'none', reason: null, currentCount: 0, baselineCount: 0, changeCount: 0 },
532
- taxonomy: { mode: 'none', reason: null, currentCount: 0, baselineCount: 0, changeCount: 0 }
533
- }
534
- }
535
- };
536
- const buildWorkspaceSyncPayload = vi.fn()
537
- .mockReturnValueOnce(firstPayload)
538
- .mockReturnValueOnce(secondPayload);
539
- runWorkspacePushSyncServiceMock
540
- .mockResolvedValueOnce({
541
- success: false,
542
- status: 524,
543
- error: '524 unknown',
544
- transient: true,
545
- requestMs: 125000,
546
- changeCount: 1,
547
- deleteCount: 0,
548
- currentTaskIds: new Set(),
549
- deleteTaskIds: new Set(),
550
- currentInitiativeIds: new Set(),
551
- currentInitiativeWatermarks: new Map(),
552
- currentWorkstreamIds: new Set(),
553
- currentWorkstreamWatermarks: new Map(),
554
- currentAiProfileIds: new Set(),
555
- currentAiProfileWatermarks: new Map(),
556
- currentDocumentPaths: new Set(),
557
- deleteDocumentPaths: new Set(),
558
- currentDocumentWatermarks: new Map(),
559
- currentAssetPaths: new Set(),
560
- deleteAssetPaths: new Set(),
561
- currentAssetWatermarks: new Map(),
562
- currentDocumentReviewSessionIds: new Set(),
563
- deleteDocumentReviewSessionIds: new Set(),
564
- currentDocumentReviewSessionWatermarks: new Map(),
565
- currentDocumentReviewCommentIds: new Set(),
566
- deleteDocumentReviewCommentIds: new Set(),
567
- currentDocumentReviewCommentWatermarks: new Map(),
568
- currentAnnotatedAttachmentSessionIds: new Set(),
569
- deleteAnnotatedAttachmentSessionIds: new Set(),
570
- currentAnnotatedAttachmentSessionWatermarks: new Map(),
571
- currentTaskEventWatermarks: new Map(),
572
- pushedWatermarks: new Map(),
573
- emittedEventIds: [],
574
- appliedTaskUpserts: []
575
- })
576
- .mockResolvedValueOnce({
577
- success: true,
578
- syncedAt: '2026-04-21T12:00:00.000Z',
579
- requestMs: 200,
580
- changeCount: 1,
581
- deleteCount: 0,
582
- currentTaskIds: new Set(['task-1']),
583
- deleteTaskIds: new Set(),
584
- currentInitiativeIds: new Set(),
585
- currentInitiativeWatermarks: new Map(),
586
- currentWorkstreamIds: new Set(),
587
- currentWorkstreamWatermarks: new Map(),
588
- currentAiProfileIds: new Set(),
589
- currentAiProfileWatermarks: new Map(),
590
- currentDocumentPaths: new Set(),
591
- currentDocumentWatermarks: new Map(),
592
- currentAssetPaths: new Set(),
593
- currentAssetWatermarks: new Map(),
594
- currentDocumentReviewSessionIds: new Set(),
595
- currentDocumentReviewSessionWatermarks: new Map(),
596
- currentDocumentReviewCommentIds: new Set(),
597
- currentDocumentReviewCommentWatermarks: new Map(),
598
- currentAnnotatedAttachmentSessionIds: new Set(),
599
- currentAnnotatedAttachmentSessionWatermarks: new Map(),
600
- currentTaskEventWatermarks: new Map(),
601
- pushedWatermarks: new Map([['task-1', '2026-04-21T12:00:00.000Z']]),
602
- emittedEventIds: [],
603
- appliedTaskUpserts: []
604
- });
605
- const { coordinator, workspacePendingPushReplayRef, reportSyncEvent } = createCoordinator({ buildWorkspaceSyncPayload });
606
- const firstResult = await coordinator.pushWorkspaceChangesToCloud('signature-1');
607
- const secondResult = await coordinator.pushWorkspaceChangesToCloud('signature-1');
608
- expect(firstResult).toBe(false);
609
- expect(secondResult).toBe(true);
610
- expect(buildWorkspaceSyncPayload).toHaveBeenCalledTimes(1);
611
- expect(runWorkspacePushSyncServiceMock.mock.calls[0]?.[0]?.payload).toBe(firstPayload);
612
- expect(runWorkspacePushSyncServiceMock.mock.calls[1]?.[0]?.payload).toBe(firstPayload);
613
- expect(workspacePendingPushReplayRef.current).toBeNull();
614
- expect(reportSyncEvent).toHaveBeenLastCalledWith('workspace-local-active', expect.objectContaining({
615
- eventType: 'push',
616
- status: 'success',
617
- details: expect.objectContaining({
618
- replayedPayload: true
619
- })
620
- }));
621
- });
622
- it('rebuilds a transient replay payload when refreshed sync state changes the signature before retry', async () => {
623
- const stalePayload = {
624
- changes: [{
625
- op: 'workstream-upsert',
626
- workstream: {
627
- id: 'workstream-1',
628
- referenceNumber: 701,
629
- title: 'Stale workstream',
630
- description: null,
631
- ownerId: null,
632
- initiativeId: null,
633
- createdAt: '2026-04-21T12:00:00.000Z',
634
- updatedAt: '2026-04-21T12:00:00.000Z',
635
- order: null,
636
- attachments: [],
637
- isArchived: false
638
- }
639
- }],
640
- currentTaskIds: new Set(),
641
- deleteTaskIds: new Set(),
642
- currentInitiativeIds: new Set(),
643
- currentInitiativeWatermarks: new Map(),
644
- currentWorkstreamIds: new Set(['workstream-1']),
645
- currentWorkstreamWatermarks: new Map([['workstream-1', '2026-04-21T12:00:00.000Z']]),
646
- currentAiProfileIds: new Set(),
647
- currentAiProfileWatermarks: new Map(),
648
- currentDocumentPaths: new Set(),
649
- deleteDocumentPaths: new Set(),
650
- currentDocumentWatermarks: new Map(),
651
- currentAssetPaths: new Set(),
652
- deleteAssetPaths: new Set(),
653
- currentAssetWatermarks: new Map(),
654
- currentDocumentReviewSessionIds: new Set(),
655
- deleteDocumentReviewSessionIds: new Set(),
656
- currentDocumentReviewSessionWatermarks: new Map(),
657
- currentDocumentReviewCommentIds: new Set(),
658
- deleteDocumentReviewCommentIds: new Set(),
659
- currentDocumentReviewCommentWatermarks: new Map(),
660
- currentAnnotatedAttachmentSessionIds: new Set(),
661
- deleteAnnotatedAttachmentSessionIds: new Set(),
662
- currentAnnotatedAttachmentSessionWatermarks: new Map(),
663
- currentTaskEventWatermarks: new Map(),
664
- pushedWatermarks: new Map()
665
- };
666
- const refreshedPayload = {
667
- ...stalePayload,
668
- changes: [{
669
- op: 'workstream-upsert',
670
- workstream: {
671
- id: 'workstream-1',
672
- referenceNumber: 701,
673
- title: 'Stale workstream',
674
- description: null,
675
- ownerId: null,
676
- initiativeId: null,
677
- createdAt: '2026-04-21T12:00:00.000Z',
678
- updatedAt: '2026-04-21T12:00:05.000Z',
679
- order: null,
680
- attachments: [{
681
- path: '/api/taskforce/documents/asset-doc-1/content',
682
- fsPath: 'workspaces/workspace-local-active/assets/documents/doc-1.md',
683
- assetId: 'asset-doc-1',
684
- caption: 'Plan',
685
- timestamp: '2026-04-21T12:00:05.000Z'
686
- }],
687
- isArchived: false
688
- }
689
- }],
690
- currentWorkstreamWatermarks: new Map([['workstream-1', '2026-04-21T12:00:05.000Z']])
691
- };
692
- const buildWorkspaceSyncPayload = vi.fn()
693
- .mockReturnValueOnce(stalePayload)
694
- .mockReturnValueOnce(refreshedPayload);
695
- const buildWorkspaceSyncSignature = vi.fn()
696
- .mockReturnValueOnce('signature-stale')
697
- .mockReturnValueOnce('signature-fresh')
698
- .mockReturnValue('signature-fresh');
699
- runWorkspacePushSyncServiceMock
700
- .mockResolvedValueOnce({
701
- success: false,
702
- status: 524,
703
- error: '524 unknown',
704
- transient: true,
705
- requestMs: 125000,
706
- changeCount: 1,
707
- deleteCount: 0,
708
- currentTaskIds: new Set(),
709
- deleteTaskIds: new Set(),
710
- currentInitiativeIds: new Set(),
711
- currentInitiativeWatermarks: new Map(),
712
- currentWorkstreamIds: new Set(['workstream-1']),
713
- currentWorkstreamWatermarks: new Map([['workstream-1', '2026-04-21T12:00:00.000Z']]),
714
- currentAiProfileIds: new Set(),
715
- currentAiProfileWatermarks: new Map(),
716
- currentDocumentPaths: new Set(),
717
- deleteDocumentPaths: new Set(),
718
- currentDocumentWatermarks: new Map(),
719
- currentAssetPaths: new Set(),
720
- deleteAssetPaths: new Set(),
721
- currentAssetWatermarks: new Map(),
722
- currentDocumentReviewSessionIds: new Set(),
723
- currentDocumentReviewSessionWatermarks: new Map(),
724
- currentDocumentReviewCommentIds: new Set(),
725
- currentDocumentReviewCommentWatermarks: new Map(),
726
- currentAnnotatedAttachmentSessionIds: new Set(),
727
- currentAnnotatedAttachmentSessionWatermarks: new Map(),
728
- currentTaskEventWatermarks: new Map(),
729
- pushedWatermarks: new Map(),
730
- emittedEventIds: [],
731
- appliedTaskUpserts: []
732
- })
733
- .mockResolvedValueOnce({
734
- success: true,
735
- syncedAt: '2026-04-21T12:00:10.000Z',
736
- requestMs: 200,
737
- changeCount: 1,
738
- deleteCount: 0,
739
- currentTaskIds: new Set(),
740
- deleteTaskIds: new Set(),
741
- currentInitiativeIds: new Set(),
742
- currentInitiativeWatermarks: new Map(),
743
- currentWorkstreamIds: new Set(['workstream-1']),
744
- currentWorkstreamWatermarks: new Map([['workstream-1', '2026-04-21T12:00:05.000Z']]),
745
- currentAiProfileIds: new Set(),
746
- currentAiProfileWatermarks: new Map(),
747
- currentDocumentPaths: new Set(),
748
- currentDocumentWatermarks: new Map(),
749
- currentAssetPaths: new Set(),
750
- currentAssetWatermarks: new Map(),
751
- currentDocumentReviewSessionIds: new Set(),
752
- currentDocumentReviewSessionWatermarks: new Map(),
753
- currentDocumentReviewCommentIds: new Set(),
754
- currentDocumentReviewCommentWatermarks: new Map(),
755
- currentAnnotatedAttachmentSessionIds: new Set(),
756
- currentAnnotatedAttachmentSessionWatermarks: new Map(),
757
- currentTaskEventWatermarks: new Map(),
758
- pushedWatermarks: new Map(),
759
- emittedEventIds: [],
760
- appliedTaskUpserts: []
761
- });
762
- const { coordinator, reportSyncEvent } = createCoordinator({
763
- buildWorkspaceSyncPayload,
764
- buildWorkspaceSyncSignature
765
- });
766
- const firstResult = await coordinator.pushWorkspaceChangesToCloud('signature-stale');
767
- const secondResult = await coordinator.pushWorkspaceChangesToCloud('signature-stale');
768
- expect(firstResult).toBe(false);
769
- expect(secondResult).toBe(true);
770
- expect(buildWorkspaceSyncPayload).toHaveBeenCalledTimes(2);
771
- expect(runWorkspacePushSyncServiceMock.mock.calls[0]?.[0]?.payload).toBe(stalePayload);
772
- expect(runWorkspacePushSyncServiceMock.mock.calls[1]?.[0]?.payload).toBe(refreshedPayload);
773
- expect(reportSyncEvent).toHaveBeenLastCalledWith('workspace-local-active', expect.objectContaining({
774
- eventType: 'push',
775
- status: 'success',
776
- details: expect.objectContaining({
777
- replayedPayload: false
778
- })
779
- }));
780
- });
781
- it('rebuilds a transient replay payload when a later retry forces all AI profiles', async () => {
782
- const firstPayload = {
783
- changes: [],
784
- currentTaskIds: new Set(),
785
- deleteTaskIds: new Set(),
786
- currentInitiativeIds: new Set(),
787
- currentInitiativeWatermarks: new Map(),
788
- currentWorkstreamIds: new Set(),
789
- currentWorkstreamWatermarks: new Map(),
790
- currentAiProfileIds: new Set(),
791
- currentAiProfileWatermarks: new Map(),
792
- currentDocumentPaths: new Set(),
793
- deleteDocumentPaths: new Set(),
794
- currentDocumentWatermarks: new Map(),
795
- currentAssetPaths: new Set(),
796
- deleteAssetPaths: new Set(),
797
- currentAssetWatermarks: new Map(),
798
- currentDocumentReviewSessionIds: new Set(),
799
- deleteDocumentReviewSessionIds: new Set(),
800
- currentDocumentReviewSessionWatermarks: new Map(),
801
- currentDocumentReviewCommentIds: new Set(),
802
- deleteDocumentReviewCommentIds: new Set(),
803
- currentDocumentReviewCommentWatermarks: new Map(),
804
- currentAnnotatedAttachmentSessionIds: new Set(),
805
- deleteAnnotatedAttachmentSessionIds: new Set(),
806
- currentAnnotatedAttachmentSessionWatermarks: new Map(),
807
- currentTaskEventWatermarks: new Map(),
808
- pushedWatermarks: new Map()
809
- };
810
- const forcedAiProfilePayload = {
811
- ...firstPayload,
812
- changes: [{
813
- op: 'ai-profile-upsert',
814
- profile: {
815
- id: 'ai-profile-codex',
816
- workspaceId: 'workspace-local-active',
817
- profileToken: 'tfp_codex',
818
- name: 'Codex',
819
- username: 'codex',
820
- icon: 'Bot',
821
- color: '#8b5cf6',
822
- avatarUrl: null,
823
- avatarSourceUrl: null,
824
- description: null,
825
- role: null,
826
- provider: null,
827
- model: null,
828
- surfaceType: null,
829
- seatScope: 'cloud_metered',
830
- providerMetadata: null,
831
- archivedAt: null,
832
- archivedBy: null,
833
- archivedReason: null,
834
- mergedIntoProfileId: null,
835
- rosterStateUpdatedAt: '2026-04-21T12:00:00.000Z',
836
- createdAt: '2026-04-21T12:00:00.000Z',
837
- updatedAt: '2026-04-21T12:00:00.000Z',
838
- lastActiveAt: null
839
- }
840
- }],
841
- currentAiProfileIds: new Set(['ai-profile-codex']),
842
- currentAiProfileWatermarks: new Map([['ai-profile-codex', '2026-04-21T12:00:00.000Z']]),
843
- currentAiProfileChangeKeys: new Map([['ai-profile-codex', 'codex-change-key']])
844
- };
845
- const buildWorkspaceSyncPayload = vi.fn()
846
- .mockReturnValueOnce(firstPayload)
847
- .mockReturnValueOnce(forcedAiProfilePayload);
848
- runWorkspacePushSyncServiceMock
849
- .mockResolvedValueOnce({
850
- success: false,
851
- status: 524,
852
- error: '524 unknown',
853
- transient: true,
854
- requestMs: 125000,
855
- changeCount: 0,
856
- deleteCount: 0,
857
- currentTaskIds: new Set(),
858
- deleteTaskIds: new Set(),
859
- currentInitiativeIds: new Set(),
860
- currentInitiativeWatermarks: new Map(),
861
- currentWorkstreamIds: new Set(),
862
- currentWorkstreamWatermarks: new Map(),
863
- currentAiProfileIds: new Set(),
864
- currentAiProfileWatermarks: new Map(),
865
- currentDocumentPaths: new Set(),
866
- deleteDocumentPaths: new Set(),
867
- currentDocumentWatermarks: new Map(),
868
- currentAssetPaths: new Set(),
869
- deleteAssetPaths: new Set(),
870
- currentAssetWatermarks: new Map(),
871
- currentDocumentReviewSessionIds: new Set(),
872
- deleteDocumentReviewSessionIds: new Set(),
873
- currentDocumentReviewSessionWatermarks: new Map(),
874
- currentDocumentReviewCommentIds: new Set(),
875
- deleteDocumentReviewCommentIds: new Set(),
876
- currentDocumentReviewCommentWatermarks: new Map(),
877
- currentAnnotatedAttachmentSessionIds: new Set(),
878
- deleteAnnotatedAttachmentSessionIds: new Set(),
879
- currentAnnotatedAttachmentSessionWatermarks: new Map(),
880
- currentTaskEventWatermarks: new Map(),
881
- pushedWatermarks: new Map(),
882
- emittedEventIds: [],
883
- appliedTaskUpserts: []
884
- })
885
- .mockResolvedValueOnce({
886
- success: true,
887
- syncedAt: '2026-04-21T12:00:00.000Z',
888
- requestMs: 200,
889
- changeCount: 1,
890
- deleteCount: 0,
891
- currentTaskIds: new Set(),
892
- currentTaskWatermarks: new Map(),
893
- currentTaskChangeKeys: new Map(),
894
- deleteTaskIds: new Set(),
895
- currentInitiativeIds: new Set(),
896
- currentInitiativeWatermarks: new Map(),
897
- currentWorkstreamIds: new Set(),
898
- currentWorkstreamWatermarks: new Map(),
899
- currentAiProfileIds: new Set(['ai-profile-codex']),
900
- currentAiProfileWatermarks: new Map([['ai-profile-codex', '2026-04-21T12:00:00.000Z']]),
901
- currentAiProfileChangeKeys: new Map([['ai-profile-codex', 'codex-change-key']]),
902
- currentDocumentPaths: new Set(),
903
- currentDocumentWatermarks: new Map(),
904
- currentAssetPaths: new Set(),
905
- currentAssetWatermarks: new Map(),
906
- currentDocumentReviewSessionIds: new Set(),
907
- currentDocumentReviewSessionWatermarks: new Map(),
908
- currentDocumentReviewCommentIds: new Set(),
909
- currentDocumentReviewCommentWatermarks: new Map(),
910
- currentAnnotatedAttachmentSessionIds: new Set(),
911
- currentAnnotatedAttachmentSessionWatermarks: new Map(),
912
- currentTaskEventWatermarks: new Map(),
913
- pushedWatermarks: new Map(),
914
- emittedEventIds: [],
915
- appliedTaskUpserts: []
916
- });
917
- const { coordinator } = createCoordinator({ buildWorkspaceSyncPayload });
918
- const firstResult = await coordinator.pushWorkspaceChangesToCloud('signature-1');
919
- const secondResult = await coordinator.pushWorkspaceChangesToCloud('signature-1', { forceAllAiProfiles: true });
920
- expect(firstResult).toBe(false);
921
- expect(secondResult).toBe(true);
922
- expect(buildWorkspaceSyncPayload).toHaveBeenCalledTimes(2);
923
- expect(buildWorkspaceSyncPayload).toHaveBeenNthCalledWith(1, { forceAllAiProfiles: false });
924
- expect(buildWorkspaceSyncPayload).toHaveBeenNthCalledWith(2, { forceAllAiProfiles: true });
925
- expect(runWorkspacePushSyncServiceMock.mock.calls[0]?.[0]?.payload).toBe(firstPayload);
926
- expect(runWorkspacePushSyncServiceMock.mock.calls[1]?.[0]?.payload).toBe(forcedAiProfilePayload);
927
- });
928
- });