@taskforcehq/taskforce 0.3.305 → 0.3.307

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 (440) hide show
  1. package/README.md +0 -2
  2. package/dist/Taskforce.module.css +603 -107
  3. package/dist/TaskforceCore.js +216 -43
  4. package/dist/TaskforceCore.test.js +611 -28
  5. package/dist/assets/fonts/CourierPrime-Bold.woff2 +0 -0
  6. package/dist/assets/fonts/CourierPrime-BoldItalic.woff2 +0 -0
  7. package/dist/assets/fonts/CourierPrime-Italic.woff2 +0 -0
  8. package/dist/assets/fonts/CourierPrime-Regular.woff2 +0 -0
  9. package/dist/assets/fonts/Noir_medium.woff2 +0 -0
  10. package/dist/assets/fonts/Noir_regular.woff2 +0 -0
  11. package/dist/assets/fonts/RussoOne-Regular.woff2 +0 -0
  12. package/dist/assets/fonts/SpecialElite-Regular.woff2 +0 -0
  13. package/dist/compat/workspaceSyncCompat.js +46 -2
  14. package/dist/compat/workspaceSyncCompat.test.js +38 -1
  15. package/dist/components/activity/EntityActivityTimeline.d.ts +34 -0
  16. package/dist/components/activity/EntityActivityTimeline.js +81 -0
  17. package/dist/components/context/ContextAttachmentManager.d.ts +14 -0
  18. package/dist/components/context/ContextAttachmentManager.js +561 -0
  19. package/dist/components/features/AgentsModule.d.ts +14 -1
  20. package/dist/components/features/AgentsModule.js +366 -18
  21. package/dist/components/features/AgentsModule.test.js +507 -8
  22. package/dist/components/features/AnnotatedAttachmentWorkspace.d.ts +3 -1
  23. package/dist/components/features/AnnotatedAttachmentWorkspace.js +118 -4
  24. package/dist/components/features/AnnotatedAttachmentWorkspace.test.js +52 -0
  25. package/dist/components/features/DocumentIndex.d.ts +2 -2
  26. package/dist/components/features/DocumentIndex.js +3 -4
  27. package/dist/components/features/DocumentViewer.d.ts +7 -1
  28. package/dist/components/features/DocumentViewer.js +62 -4
  29. package/dist/components/features/DocumentWorkspace.d.ts +10 -2
  30. package/dist/components/features/DocumentWorkspace.js +15 -4
  31. package/dist/components/features/DocumentWorkspace.test.js +51 -1
  32. package/dist/components/features/TaskSettings.d.ts +2 -0
  33. package/dist/components/features/TaskSettings.js +83 -78
  34. package/dist/components/features/TaskSettings.test.js +171 -82
  35. package/dist/components/features/documentWorkspaceModel.d.ts +1 -1
  36. package/dist/components/task/TaskActionHeader.js +11 -5
  37. package/dist/components/task/TaskActionHeader.test.js +10 -0
  38. package/dist/components/task/TaskCard.js +24 -29
  39. package/dist/components/task/TaskCard.test.js +38 -3
  40. package/dist/components/task/TaskContextUpload.js +4 -526
  41. package/dist/components/task/TaskContextUpload.test.js +3 -3
  42. package/dist/components/task/TaskForm.js +61 -116
  43. package/dist/components/task/TaskForm.test.js +110 -8
  44. package/dist/components/task/TaskKanban.d.ts +2 -1
  45. package/dist/components/task/TaskKanban.js +94 -21
  46. package/dist/components/task/TaskKanban.test.js +36 -0
  47. package/dist/components/task/TaskList.js +5 -1
  48. package/dist/components/task/TaskList.test.js +4 -0
  49. package/dist/components/ui/EditableAvatarButton.d.ts +18 -0
  50. package/dist/components/ui/EditableAvatarButton.js +18 -0
  51. package/dist/components/ui/HierarchyActionBadge.d.ts +10 -0
  52. package/dist/components/ui/HierarchyActionBadge.js +5 -0
  53. package/dist/components/views/AppShellHeader.d.ts +3 -1
  54. package/dist/components/views/AppShellHeader.js +27 -11
  55. package/dist/components/views/AppShellHeader.test.js +18 -1
  56. package/dist/components/views/PlanComparisonPage.d.ts +9 -1
  57. package/dist/components/views/PlanComparisonPage.js +78 -14
  58. package/dist/components/views/PlanComparisonPage.test.js +257 -0
  59. package/dist/components/views/PlansPage.js +127 -36
  60. package/dist/components/views/PlansPage.test.js +294 -12
  61. package/dist/components/views/StandaloneLayout.js +529 -592
  62. package/dist/components/views/WidgetView.js +10 -8
  63. package/dist/components/views/panels/PlanningDrawer.d.ts +25 -5
  64. package/dist/components/views/panels/PlanningDrawer.js +270 -55
  65. package/dist/components/views/panels/PlanningDrawer.test.d.ts +1 -0
  66. package/dist/components/views/panels/PlanningDrawer.test.js +529 -0
  67. package/dist/components/views/planningScope.d.ts +20 -0
  68. package/dist/components/views/planningScope.js +25 -0
  69. package/dist/components/views/planningScope.test.d.ts +1 -0
  70. package/dist/components/views/planningScope.test.js +60 -0
  71. package/dist/components/views/standalone/modals/AccountHubModal.d.ts +26 -1
  72. package/dist/components/views/standalone/modals/AccountHubModal.js +76 -2
  73. package/dist/components/views/standalone/modals/AccountHubModal.test.js +20 -3
  74. package/dist/components/views/standalone/modals/AvatarImageManagerModal.d.ts +20 -0
  75. package/dist/components/views/standalone/modals/AvatarImageManagerModal.js +127 -0
  76. package/dist/components/views/standalone/modals/EditProfileModal.d.ts +2 -9
  77. package/dist/components/views/standalone/modals/EditProfileModal.js +3 -2
  78. package/dist/components/views/standalone/modals/SyncEnableWarningModal.d.ts +9 -0
  79. package/dist/components/views/standalone/modals/SyncEnableWarningModal.js +6 -0
  80. package/dist/components/views/standalone/modals/SyncEnableWarningModal.test.d.ts +1 -0
  81. package/dist/components/views/standalone/modals/SyncEnableWarningModal.test.js +24 -0
  82. package/dist/components/views/standalone/modals/SyncStatusModal.d.ts +2 -1
  83. package/dist/components/views/standalone/modals/SyncStatusModal.js +2 -2
  84. package/dist/config/envSchema.js +1 -0
  85. package/dist/core/AiProfileService.d.ts +46 -2
  86. package/dist/core/AiProfileService.js +1073 -82
  87. package/dist/core/AiProfileService.test.js +19 -1
  88. package/dist/core/AiProfiles.test.js +1249 -44
  89. package/dist/core/AttachmentLinkService.d.ts +3 -0
  90. package/dist/core/AttachmentLinkService.js +110 -23
  91. package/dist/core/AuthIdentityService.d.ts +107 -0
  92. package/dist/core/AuthIdentityService.js +284 -0
  93. package/dist/core/AuthTokenService.d.ts +4 -0
  94. package/dist/core/AuthTokenService.js +34 -6
  95. package/dist/core/AuthTokenService.test.js +3 -3
  96. package/dist/core/EntitlementsPolicy.test.js +2 -2
  97. package/dist/core/GlobalSettingsService.js +127 -6
  98. package/dist/core/McpTokenService.d.ts +12 -0
  99. package/dist/core/McpTokenService.js +44 -1
  100. package/dist/core/PlanEntitlementService.d.ts +23 -2
  101. package/dist/core/PlanEntitlementService.js +343 -57
  102. package/dist/core/PlanFeatureCatalog.test.d.ts +1 -0
  103. package/dist/core/PlanFeatureCatalog.test.js +84 -0
  104. package/dist/core/PlanVersionPolicy.test.js +35 -2
  105. package/dist/core/PlanningEntities.test.js +418 -4
  106. package/dist/core/SignupMonetizationSettings.test.js +199 -27
  107. package/dist/core/SyncReconciliationService.js +2 -65
  108. package/dist/core/SystemAdmin.test.js +42 -42
  109. package/dist/core/TaskActivityService.d.ts +28 -1
  110. package/dist/core/TaskActivityService.js +227 -46
  111. package/dist/core/TaskActivitySync.test.d.ts +1 -0
  112. package/dist/core/TaskActivitySync.test.js +90 -0
  113. package/dist/core/TaskAttachmentsCanonical.test.js +51 -1
  114. package/dist/core/TaskAuditTimeline.test.js +96 -0
  115. package/dist/core/Taskforce.d.ts +415 -40
  116. package/dist/core/Taskforce.ids.test.js +58 -0
  117. package/dist/core/Taskforce.js +1543 -266
  118. package/dist/core/Taskforce.listTasksSlim.test.d.ts +1 -0
  119. package/dist/core/Taskforce.listTasksSlim.test.js +91 -0
  120. package/dist/core/Taskforce.mcpAuth.test.js +109 -0
  121. package/dist/core/UserProfileAvatarDrafts.test.js +30 -3
  122. package/dist/core/WorkspaceLifecycleService.js +0 -5
  123. package/dist/core/WorkspacePermissions.test.js +25 -1
  124. package/dist/core/WorkspacePlanMode.test.js +117 -16
  125. package/dist/core/shared.d.ts +1 -1
  126. package/dist/core/shared.js +5 -1
  127. package/dist/core/types.d.ts +75 -2
  128. package/dist/hooks/auth/useTaskforceAuthBootstrap.js +28 -2
  129. package/dist/hooks/bootstrapTimeouts.d.ts +4 -0
  130. package/dist/hooks/bootstrapTimeouts.js +8 -0
  131. package/dist/hooks/bootstrapTimeouts.test.d.ts +1 -0
  132. package/dist/hooks/bootstrapTimeouts.test.js +12 -0
  133. package/dist/hooks/sync/bootstrap.js +2 -0
  134. package/dist/hooks/sync/controlPlane.d.ts +37 -0
  135. package/dist/hooks/sync/controlPlane.js +78 -0
  136. package/dist/hooks/sync/controlPlane.test.d.ts +1 -0
  137. package/dist/hooks/sync/controlPlane.test.js +121 -0
  138. package/dist/hooks/sync/lifecyclePolicy.d.ts +45 -0
  139. package/dist/hooks/sync/lifecyclePolicy.js +93 -0
  140. package/dist/hooks/sync/lifecyclePolicy.test.d.ts +1 -0
  141. package/dist/hooks/sync/lifecyclePolicy.test.js +124 -0
  142. package/dist/hooks/sync/orchestratorShared.d.ts +13 -4
  143. package/dist/hooks/sync/orchestratorShared.js +129 -48
  144. package/dist/hooks/sync/orchestratorShared.test.js +50 -1
  145. package/dist/hooks/sync/pullLifecycle.d.ts +31 -0
  146. package/dist/hooks/sync/pullLifecycle.js +24 -0
  147. package/dist/hooks/sync/pullLifecycle.test.d.ts +1 -0
  148. package/dist/hooks/sync/pullLifecycle.test.js +80 -0
  149. package/dist/hooks/sync/recovery.d.ts +16 -2
  150. package/dist/hooks/sync/recovery.js +179 -53
  151. package/dist/hooks/sync/recovery.test.d.ts +1 -0
  152. package/dist/hooks/sync/recovery.test.js +292 -0
  153. package/dist/hooks/sync/transfers.d.ts +16 -3
  154. package/dist/hooks/sync/transfers.js +210 -66
  155. package/dist/hooks/sync/transfers.test.d.ts +1 -0
  156. package/dist/hooks/sync/transfers.test.js +928 -0
  157. package/dist/hooks/sync/useRecentSyncEvents.d.ts +21 -0
  158. package/dist/hooks/sync/useRecentSyncEvents.js +92 -0
  159. package/dist/hooks/sync/useRecentSyncEvents.test.d.ts +1 -0
  160. package/dist/hooks/sync/useRecentSyncEvents.test.js +124 -0
  161. package/dist/hooks/sync/useSyncStatusActions.d.ts +30 -0
  162. package/dist/hooks/sync/useSyncStatusActions.js +88 -0
  163. package/dist/hooks/sync/useSyncStatusActions.test.d.ts +1 -0
  164. package/dist/hooks/sync/useSyncStatusActions.test.js +133 -0
  165. package/dist/hooks/sync/useSyncStatusControls.d.ts +25 -0
  166. package/dist/hooks/sync/useSyncStatusControls.js +60 -0
  167. package/dist/hooks/sync/useSyncStatusControls.test.d.ts +1 -0
  168. package/dist/hooks/sync/useSyncStatusControls.test.js +88 -0
  169. package/dist/hooks/useFilterSort.js +13 -13
  170. package/dist/hooks/useFilterSort.test.js +87 -1
  171. package/dist/hooks/useSyncOrchestrator.aiProfiles.test.js +12 -0
  172. package/dist/hooks/useSyncOrchestrator.d.ts +9 -2
  173. package/dist/hooks/useSyncOrchestrator.js +409 -183
  174. package/dist/hooks/useSyncOrchestrator.retry-closure.test.js +407 -0
  175. package/dist/hooks/useTaskData.js +8 -3
  176. package/dist/hooks/useTaskData.test.js +45 -0
  177. package/dist/hooks/useTaskforce.d.ts +145 -52
  178. package/dist/hooks/useTaskforce.js +592 -253
  179. package/dist/hooks/useTaskforce.runtime-routing.test.d.ts +1 -0
  180. package/dist/hooks/useTaskforce.runtime-routing.test.js +246 -0
  181. package/dist/hooks/useTaskforce.sync-behavior.test.js +2468 -201
  182. package/dist/hooks/useWorkspaceSyncController.d.ts +1 -0
  183. package/dist/hooks/useWorkspaceSyncController.js +13 -2
  184. package/dist/hooks/useWorkspaceSyncController.test.js +48 -0
  185. package/dist/hooks/workspace/useTaskforceWorkspaceBootstrap.d.ts +16 -0
  186. package/dist/hooks/workspace/useTaskforceWorkspaceBootstrap.js +328 -40
  187. package/dist/localization/locales/en-US.d.ts +0 -1
  188. package/dist/localization/locales/en-US.js +0 -1
  189. package/dist/localization/locales/es-419.js +0 -1
  190. package/dist/localization/locales/pt-BR.js +0 -1
  191. package/dist/mcp/canonicalAssetHelpers.d.ts +16 -4
  192. package/dist/mcp/canonicalAssetHelpers.js +18 -10
  193. package/dist/mcp/canonicalAssetHelpers.test.d.ts +1 -0
  194. package/dist/mcp/canonicalAssetHelpers.test.js +67 -0
  195. package/dist/mcp/clientIntegrations.d.ts +1 -0
  196. package/dist/mcp/clientIntegrations.js +25 -0
  197. package/dist/mcp/clientIntegrations.test.js +14 -3
  198. package/dist/mcp/clientProfileDefaults.js +3 -3
  199. package/dist/mcp/collaborationRegistrar.js +7 -7
  200. package/dist/mcp/documentAssetRegistrar.js +116 -10
  201. package/dist/mcp/runtime.d.ts +3 -0
  202. package/dist/mcp/runtime.js +1099 -185
  203. package/dist/mcp/runtime.test.js +1491 -140
  204. package/dist/mcp/taskAttachmentTypes.d.ts +1 -1
  205. package/dist/mcp/taskPlanningRegistrar.js +48 -0
  206. package/dist/mcp/toolRegistry.d.ts +56 -0
  207. package/dist/mcp/toolRegistry.js +8 -0
  208. package/dist/mcp/toolRegistry.test.js +4 -0
  209. package/dist/migrations/taskSchemaMigrations.d.ts +1 -1
  210. package/dist/migrations/taskSchemaMigrations.js +192 -61
  211. package/dist/migrations/taskSchemaMigrations.test.js +15 -0
  212. package/dist/resources/templates/workflow-sources/workflowDocs.mjs +6 -6
  213. package/dist/resources/templates/workflows/collaborate.yaml +1 -1
  214. package/dist/resources/templates/workflows/evaluate.yaml +2 -2
  215. package/dist/resources/templates/workflows/plan.yaml +1 -1
  216. package/dist/resources/templates/workflows/review.yaml +2 -2
  217. package/dist/server/aiProfileAvatarAssets.d.ts +49 -0
  218. package/dist/server/aiProfileAvatarAssets.js +319 -0
  219. package/dist/server/aiProfileAvatarAssets.test.d.ts +1 -0
  220. package/dist/server/aiProfileAvatarAssets.test.js +213 -0
  221. package/dist/server/annotatedAttachmentsRoutes.test.js +69 -10
  222. package/dist/server/auth/providers/apple.d.ts +33 -0
  223. package/dist/server/auth/providers/apple.js +82 -0
  224. package/dist/server/auth/providers/appleClientSecret.d.ts +37 -0
  225. package/dist/server/auth/providers/appleClientSecret.js +65 -0
  226. package/dist/server/auth/providers/github.d.ts +26 -0
  227. package/dist/server/auth/providers/github.js +86 -0
  228. package/dist/server/auth/providers/google.d.ts +21 -0
  229. package/dist/server/auth/providers/google.js +56 -0
  230. package/dist/server/auth/providers/types.d.ts +21 -0
  231. package/dist/server/auth/providers/types.js +1 -0
  232. package/dist/server/auth.d.ts +2 -0
  233. package/dist/server/auth.js +6 -3
  234. package/dist/server/documentReviewRoutes.test.js +36 -3
  235. package/dist/server/index.cookieProxy.test.js +1 -0
  236. package/dist/server/index.d.ts +12 -0
  237. package/dist/server/index.js +124 -9
  238. package/dist/server/index.rateLimit.test.js +3 -0
  239. package/dist/server/index.test.js +111 -3
  240. package/dist/server/routes/admin.d.ts +3 -0
  241. package/dist/server/routes/admin.js +459 -28
  242. package/dist/server/routes/annotatedAttachments.js +51 -0
  243. package/dist/server/routes/auth.d.ts +26 -2
  244. package/dist/server/routes/auth.js +1170 -71
  245. package/dist/server/routes/authSupport.d.ts +5 -1
  246. package/dist/server/routes/authSupport.js +13 -2
  247. package/dist/server/routes/billing.js +372 -35
  248. package/dist/server/routes/billing.test.js +595 -12
  249. package/dist/server/routes/documents.d.ts +1 -0
  250. package/dist/server/routes/documents.js +182 -70
  251. package/dist/server/routes/shared.d.ts +28 -2
  252. package/dist/server/routes/shared.js +69 -14
  253. package/dist/server/routes/sync.integration.test.js +658 -39
  254. package/dist/server/routes/sync.js +74 -608
  255. package/dist/server/routes/syncAuxRoutes.d.ts +15 -0
  256. package/dist/server/routes/syncAuxRoutes.js +91 -0
  257. package/dist/server/routes/syncAuxRoutes.test.d.ts +1 -0
  258. package/dist/server/routes/syncAuxRoutes.test.js +158 -0
  259. package/dist/server/routes/syncPullApplyRoutes.d.ts +36 -0
  260. package/dist/server/routes/syncPullApplyRoutes.js +204 -0
  261. package/dist/server/routes/syncPushRoutes.d.ts +24 -0
  262. package/dist/server/routes/syncPushRoutes.js +212 -0
  263. package/dist/server/routes/syncRouteGuards.d.ts +36 -0
  264. package/dist/server/routes/syncRouteGuards.js +67 -0
  265. package/dist/server/routes/syncRouteGuards.test.d.ts +1 -0
  266. package/dist/server/routes/syncRouteGuards.test.js +94 -0
  267. package/dist/server/routes/syncRouteTypes.d.ts +13 -0
  268. package/dist/server/routes/syncRouteTypes.js +1 -0
  269. package/dist/server/routes/syncSnapshotRoutes.d.ts +66 -0
  270. package/dist/server/routes/syncSnapshotRoutes.js +182 -0
  271. package/dist/server/routes/tasks.js +55 -10
  272. package/dist/server/routes/workspaces.js +36 -5
  273. package/dist/server/routes.js +147 -11
  274. package/dist/server/routes.test.js +2704 -183
  275. package/dist/services/workflowExportSnapshots.test.js +2 -0
  276. package/dist/shared/aiProfileSeatScope.d.ts +5 -0
  277. package/dist/shared/aiProfileSeatScope.js +21 -0
  278. package/dist/shared/aiProfileSurfaceType.d.ts +1 -1
  279. package/dist/shared/aiProfileSurfaceType.js +10 -8
  280. package/dist/shared/passwordPolicy.d.ts +13 -0
  281. package/dist/shared/passwordPolicy.js +84 -0
  282. package/dist/shared/passwordPolicy.test.d.ts +1 -0
  283. package/dist/shared/passwordPolicy.test.js +34 -0
  284. package/dist/storage/objectStorage.d.ts +1 -0
  285. package/dist/storage/objectStorage.js +2 -1
  286. package/dist/storage/objectStorageClient.d.ts +1 -0
  287. package/dist/storage/objectStorageClient.js +41 -8
  288. package/dist/storage/objectStorageClient.test.js +26 -1
  289. package/dist/storage/objectStorageConfig.js +3 -1
  290. package/dist/storage/objectStorageConfig.test.js +13 -1
  291. package/dist/storage/workspaceAssetStore.d.ts +15 -3
  292. package/dist/storage/workspaceAssetStore.js +132 -44
  293. package/dist/storage/workspaceAssetStore.test.js +93 -6
  294. package/dist/styles/fonts.css +70 -0
  295. package/dist/sync/collaborationSyncPayload.d.ts +6 -1
  296. package/dist/sync/collaborationSyncPayload.js +19 -11
  297. package/dist/sync/collaborationSyncPayload.test.js +14 -1
  298. package/dist/sync/collaborationSyncState.d.ts +3 -3
  299. package/dist/sync/collaborationSyncState.js +19 -12
  300. package/dist/sync/contentSyncPayload.d.ts +5 -1
  301. package/dist/sync/contentSyncPayload.js +9 -0
  302. package/dist/sync/contentSyncPayload.test.js +39 -0
  303. package/dist/sync/contentSyncState.d.ts +9 -9
  304. package/dist/sync/contentSyncState.js +248 -107
  305. package/dist/sync/planningSyncPayload.js +5 -0
  306. package/dist/sync/planningSyncPayload.test.js +24 -0
  307. package/dist/sync/syncApplyHandlers.d.ts +11 -4
  308. package/dist/sync/syncApplyHandlers.js +115 -42
  309. package/dist/sync/syncApplyHandlers.test.js +251 -4
  310. package/dist/sync/syncFieldSemantics.d.ts +12 -0
  311. package/dist/sync/syncFieldSemantics.js +55 -0
  312. package/dist/sync/syncResourceAdapters.d.ts +46 -0
  313. package/dist/sync/syncResourceAdapters.js +79 -0
  314. package/dist/sync/syncService.d.ts +6 -0
  315. package/dist/sync/syncService.js +65 -1
  316. package/dist/sync/syncService.test.js +96 -3
  317. package/dist/sync/taskSyncChangeKey.d.ts +2 -0
  318. package/dist/sync/taskSyncChangeKey.js +143 -0
  319. package/dist/sync/taskSyncPayload.js +3 -8
  320. package/dist/sync/workspacePullFeed.d.ts +4 -0
  321. package/dist/sync/workspacePullFeed.js +132 -72
  322. package/dist/sync/workspacePullFeed.test.js +92 -0
  323. package/dist/sync/workspaceRepair.js +5 -2
  324. package/dist/sync/workspaceSyncModel.d.ts +73 -6
  325. package/dist/sync/workspaceSyncModel.js +342 -73
  326. package/dist/sync/workspaceSyncModel.test.js +559 -14
  327. package/dist/sync/workspaceSyncState.d.ts +17 -0
  328. package/dist/sync/workspaceSyncState.js +2 -1
  329. package/dist/sync/workspaceSyncSurface.js +3 -8
  330. package/dist/types.d.ts +50 -2
  331. package/dist/ui/assets/AgentsModule-2y82_3DO.js +1 -0
  332. package/dist/ui/assets/AnnotatedAttachmentWorkspace-BTLZZCiQ.js +3 -0
  333. package/dist/ui/assets/AnnotatedAttachmentWorkspace-BVKew-mH.css +1 -0
  334. package/dist/ui/assets/ContextAttachmentManager-D2epuNnG.js +3 -0
  335. package/dist/ui/assets/CourierPrime-Bold-BuLj_dpw.woff2 +0 -0
  336. package/dist/ui/assets/CourierPrime-BoldItalic-BrK2pUkZ.woff2 +0 -0
  337. package/dist/ui/assets/CourierPrime-Italic-DFUZK5Ey.woff2 +0 -0
  338. package/dist/ui/assets/CourierPrime-Regular-BsKphzVf.woff2 +0 -0
  339. package/dist/ui/assets/DocumentWorkspace-D4rJKXzd.css +1 -0
  340. package/dist/ui/assets/DocumentWorkspace-sVa-3Do6.js +252 -0
  341. package/dist/ui/assets/EntityActivityTimeline-DyqvvhuF.css +1 -0
  342. package/dist/ui/assets/EntityActivityTimeline-Zods27y_.js +1 -0
  343. package/dist/ui/assets/{InitiativesModule-Dhm7M8e7.js → InitiativesModule-D4XseTwW.js} +1 -1
  344. package/dist/ui/assets/Noir_medium-bxQwKGzB.woff2 +0 -0
  345. package/dist/ui/assets/Noir_regular-ojf2kxlG.woff2 +0 -0
  346. package/dist/ui/assets/PlansPage-D5AcbO0L.js +1 -0
  347. package/dist/ui/assets/PlansPage-Dvqsz5zc.css +1 -0
  348. package/dist/ui/assets/RussoOne-Regular-Cu_qq_qC.woff2 +0 -0
  349. package/dist/ui/assets/SpecialElite-Regular-Di6gSvAS.woff2 +0 -0
  350. package/dist/ui/assets/TaskContextUpload-uC5qx4Bv.js +1 -0
  351. package/dist/ui/assets/TaskSettings-CqvPAsTv.js +9 -0
  352. package/dist/ui/assets/{WorkflowsModule-BcS4afRn.js → WorkflowsModule-oOA9bcdK.js} +4 -4
  353. package/dist/ui/assets/documentReferences-DPZuTgHh.js +1 -0
  354. package/dist/ui/assets/index-607WPo_X.js +4 -0
  355. package/dist/ui/assets/index-CYyodXsg.css +1 -0
  356. package/dist/ui/assets/{vendor-icons-BSUaRwF8.js → vendor-icons-B32hGuF2.js} +1 -1
  357. package/dist/ui/fonts/CourierPrime-Bold.ttf +0 -0
  358. package/dist/ui/fonts/CourierPrime-Bold.woff2 +0 -0
  359. package/dist/ui/fonts/CourierPrime-BoldItalic.ttf +0 -0
  360. package/dist/ui/fonts/CourierPrime-BoldItalic.woff2 +0 -0
  361. package/dist/ui/fonts/CourierPrime-Italic.ttf +0 -0
  362. package/dist/ui/fonts/CourierPrime-Italic.woff2 +0 -0
  363. package/dist/ui/fonts/CourierPrime-Regular.ttf +0 -0
  364. package/dist/ui/fonts/CourierPrime-Regular.woff2 +0 -0
  365. package/dist/ui/fonts/Noir_medium.otf +0 -0
  366. package/dist/ui/fonts/Noir_medium.woff2 +0 -0
  367. package/dist/ui/fonts/Noir_regular.otf +0 -0
  368. package/dist/ui/fonts/Noir_regular.woff2 +0 -0
  369. package/dist/ui/fonts/RussoOne-Regular.woff2 +0 -0
  370. package/dist/ui/fonts/SpecialElite-Regular.ttf +0 -0
  371. package/dist/ui/fonts/SpecialElite-Regular.woff2 +0 -0
  372. package/dist/ui/index.html +3 -3
  373. package/dist/ui/product/agent manager.png +0 -0
  374. package/dist/ui/product/agent_manager_02.png +0 -0
  375. package/dist/utils/accountProfileSummaryCache.d.ts +5 -0
  376. package/dist/utils/aiProfileEvents.d.ts +7 -0
  377. package/dist/utils/aiProfileEvents.js +6 -0
  378. package/dist/utils/assignees.d.ts +8 -0
  379. package/dist/utils/assignees.js +10 -1
  380. package/dist/utils/assignees.test.d.ts +1 -0
  381. package/dist/utils/assignees.test.js +25 -0
  382. package/dist/utils/avatarDisplay.d.ts +1 -0
  383. package/dist/utils/avatarDisplay.js +15 -0
  384. package/dist/utils/avatarUpload.d.ts +27 -0
  385. package/dist/utils/avatarUpload.js +132 -0
  386. package/dist/utils/avatarUpload.test.d.ts +1 -0
  387. package/dist/utils/avatarUpload.test.js +40 -0
  388. package/dist/utils/bootstrapTrace.d.ts +7 -0
  389. package/dist/utils/bootstrapTrace.js +29 -0
  390. package/dist/utils/commercialLifecyclePresentation.js +3 -0
  391. package/dist/utils/contextAssetEvents.d.ts +2 -0
  392. package/dist/utils/contextFiles.d.ts +3 -1
  393. package/dist/utils/contextFiles.js +2 -1
  394. package/dist/utils/syncEventDetails.d.ts +3 -0
  395. package/dist/utils/syncEventDetails.js +64 -0
  396. package/dist/utils/syncEventDetails.test.d.ts +1 -0
  397. package/dist/utils/syncEventDetails.test.js +23 -0
  398. package/dist/utils/syncEventPresentation.d.ts +15 -0
  399. package/dist/utils/syncEventPresentation.js +129 -0
  400. package/dist/utils/syncEventPresentation.test.d.ts +1 -0
  401. package/dist/utils/syncEventPresentation.test.js +64 -0
  402. package/dist/utils/syncStatusPresentation.d.ts +72 -0
  403. package/dist/utils/syncStatusPresentation.js +217 -0
  404. package/dist/utils/syncStatusPresentation.test.d.ts +1 -0
  405. package/dist/utils/syncStatusPresentation.test.js +164 -0
  406. package/dist/utils/taskActivity.d.ts +9 -1
  407. package/dist/utils/taskActivity.js +290 -22
  408. package/dist/utils/taskActivity.test.js +141 -8
  409. package/dist/utils/taskSearch.d.ts +22 -0
  410. package/dist/utils/taskSearch.js +87 -0
  411. package/dist/utils/taskSearch.test.d.ts +1 -0
  412. package/dist/utils/taskSearch.test.js +69 -0
  413. package/dist/utils/taskUtils.js +10 -3
  414. package/dist/utils/taskUtils.test.d.ts +1 -0
  415. package/dist/utils/taskUtils.test.js +19 -0
  416. package/dist/utils/workspaceSyncPresentation.d.ts +4 -0
  417. package/dist/utils/workspaceSyncPresentation.js +68 -2
  418. package/dist/utils/workspaceSyncPresentation.test.js +36 -1
  419. package/package.json +3 -2
  420. package/scripts/export-sqlite-to-postgres.mjs +7 -9
  421. package/scripts/run-e2e-realtime.sh +17 -3
  422. package/scripts/run-smoke.sh +17 -5
  423. package/scripts/run-soak.sh +17 -5
  424. package/src/resources/templates/workflow-sources/workflowDocs.mjs +6 -6
  425. package/src/resources/templates/workflows/collaborate.yaml +1 -1
  426. package/src/resources/templates/workflows/evaluate.yaml +2 -2
  427. package/src/resources/templates/workflows/plan.yaml +1 -1
  428. package/src/resources/templates/workflows/review.yaml +2 -2
  429. package/dist/ui/assets/AgentsModule-N2MnQBZk.js +0 -1
  430. package/dist/ui/assets/AnnotatedAttachmentWorkspace-BG6P_GVW.js +0 -3
  431. package/dist/ui/assets/AnnotatedAttachmentWorkspace-BaS2VwIr.css +0 -1
  432. package/dist/ui/assets/DocumentWorkspace-B3nV_Gc5.css +0 -1
  433. package/dist/ui/assets/DocumentWorkspace-DRbDMwh8.js +0 -252
  434. package/dist/ui/assets/PlansPage-C2dd2n1X.css +0 -1
  435. package/dist/ui/assets/PlansPage-Cq0zXj3I.js +0 -1
  436. package/dist/ui/assets/RussoOne-Regular-C3BxZIj7.ttf +0 -0
  437. package/dist/ui/assets/TaskSettings-ln0aF7xc.js +0 -9
  438. package/dist/ui/assets/index-C2-OXZV7.css +0 -1
  439. package/dist/ui/assets/index-DcSI5F86.js +0 -6
  440. package/scripts/migrate-planning-model.ts +0 -233
@@ -15,6 +15,14 @@ function resolveWorkspaceAccessConflictMessage(data, fallbackStatus) {
15
15
  }
16
16
  return rawError || `Workspace provisioning failed (${fallbackStatus})`;
17
17
  }
18
+ function isMissingCloudWorkspaceSelection(data, status) {
19
+ if (status !== 400)
20
+ return false;
21
+ const code = String(data.code || '').trim().toUpperCase();
22
+ const rawError = String(data.error || '').trim().toLowerCase();
23
+ return code === 'WORKSPACE_ID_REQUIRED'
24
+ && rawError.includes('no cloud workspace is selected');
25
+ }
18
26
  export async function ensureCloudWorkspaceReadyForSyncService(input) {
19
27
  if (!input.cloudAuthConfigured)
20
28
  return { success: false, error: 'Cloud auth endpoint is not configured.' };
@@ -44,6 +52,39 @@ export async function ensureCloudWorkspaceReadyForSyncService(input) {
44
52
  error: String(data.error || 'Workspace sync rate limited. Please retry later.')
45
53
  };
46
54
  }
55
+ if (isMissingCloudWorkspaceSelection(data, handshakeResult.status)) {
56
+ const provisionResult = await provisionWorkspace(input.resolveCloudAuthUrl, {
57
+ workspaceId: input.workspaceId,
58
+ name: input.workspaceName || input.workspaceId
59
+ });
60
+ if (!provisionResult.ok) {
61
+ const provisionError = asObjectRecord(provisionResult.data);
62
+ return {
63
+ success: false,
64
+ statusCode: provisionResult.status,
65
+ transient: isTransientWorkspaceSyncStatus(provisionResult.status),
66
+ retryAfterMs: provisionResult.retryAfterMs,
67
+ error: resolveWorkspaceAccessConflictMessage(provisionError, provisionResult.status)
68
+ };
69
+ }
70
+ handshakeResult = await handshakeWorkspace(input.resolveCloudAuthUrl, input.workspaceId);
71
+ if (!handshakeResult.ok) {
72
+ const retryData = asObjectRecord(handshakeResult.data);
73
+ if (handshakeResult.status === 401) {
74
+ return { success: false, statusCode: 401, transient: false, error: String(retryData.error || 'Authentication required for workspace sync.') };
75
+ }
76
+ if (handshakeResult.status === 429) {
77
+ return { success: false, statusCode: 429, retryAfterMs: handshakeResult.retryAfterMs, transient: true, error: String(retryData.error || 'Workspace sync rate limited. Please retry later.') };
78
+ }
79
+ return {
80
+ success: false,
81
+ statusCode: handshakeResult.status,
82
+ transient: isTransientWorkspaceSyncStatus(handshakeResult.status),
83
+ error: String(retryData.error || `Workspace sync handshake failed (${handshakeResult.status})`)
84
+ };
85
+ }
86
+ return { success: true, provisioned: true };
87
+ }
47
88
  if (handshakeResult.status === 409 && data.code === 'WORKSPACE_ID_MISMATCH') {
48
89
  if (input.allowProvisionOnMismatch === false) {
49
90
  return {
@@ -173,6 +214,8 @@ export async function runWorkspacePushSyncService(input) {
173
214
  changeCount,
174
215
  deleteCount,
175
216
  currentTaskIds: input.payload.currentTaskIds,
217
+ currentTaskWatermarks: input.payload.currentTaskWatermarks ?? new Map(),
218
+ currentTaskChangeKeys: input.payload.currentTaskChangeKeys ?? new Map(),
176
219
  deleteTaskIds: input.payload.deleteTaskIds,
177
220
  currentInitiativeIds: input.payload.currentInitiativeIds,
178
221
  currentInitiativeWatermarks: input.payload.currentInitiativeWatermarks,
@@ -180,6 +223,7 @@ export async function runWorkspacePushSyncService(input) {
180
223
  currentWorkstreamWatermarks: input.payload.currentWorkstreamWatermarks,
181
224
  currentAiProfileIds: input.payload.currentAiProfileIds,
182
225
  currentAiProfileWatermarks: input.payload.currentAiProfileWatermarks,
226
+ currentAiProfileChangeKeys: input.payload.currentAiProfileChangeKeys ?? new Map(),
183
227
  currentDocumentPaths: input.payload.currentDocumentPaths,
184
228
  deleteDocumentPaths: input.payload.deleteDocumentPaths,
185
229
  currentDocumentWatermarks: input.payload.currentDocumentWatermarks,
@@ -197,6 +241,7 @@ export async function runWorkspacePushSyncService(input) {
197
241
  currentAnnotatedAttachmentSessionWatermarks: input.payload.currentAnnotatedAttachmentSessionWatermarks,
198
242
  currentTaskEventWatermarks: input.payload.currentTaskEventWatermarks,
199
243
  pushedWatermarks: new Map(),
244
+ pushedTaskChangeKeys: new Map(),
200
245
  emittedEventIds: [],
201
246
  appliedTaskUpserts: []
202
247
  };
@@ -231,6 +276,8 @@ export async function runWorkspacePushSyncService(input) {
231
276
  changeCount,
232
277
  deleteCount,
233
278
  currentTaskIds: input.payload.currentTaskIds,
279
+ currentTaskWatermarks: input.payload.currentTaskWatermarks ?? new Map(),
280
+ currentTaskChangeKeys: input.payload.currentTaskChangeKeys ?? new Map(),
234
281
  deleteTaskIds: input.payload.deleteTaskIds,
235
282
  currentInitiativeIds: input.payload.currentInitiativeIds,
236
283
  currentInitiativeWatermarks: input.payload.currentInitiativeWatermarks,
@@ -238,6 +285,7 @@ export async function runWorkspacePushSyncService(input) {
238
285
  currentWorkstreamWatermarks: input.payload.currentWorkstreamWatermarks,
239
286
  currentAiProfileIds: input.payload.currentAiProfileIds,
240
287
  currentAiProfileWatermarks: input.payload.currentAiProfileWatermarks,
288
+ currentAiProfileChangeKeys: input.payload.currentAiProfileChangeKeys ?? new Map(),
241
289
  currentDocumentPaths: input.payload.currentDocumentPaths,
242
290
  deleteDocumentPaths: input.payload.deleteDocumentPaths,
243
291
  currentDocumentWatermarks: input.payload.currentDocumentWatermarks,
@@ -255,6 +303,7 @@ export async function runWorkspacePushSyncService(input) {
255
303
  currentAnnotatedAttachmentSessionWatermarks: input.payload.currentAnnotatedAttachmentSessionWatermarks,
256
304
  currentTaskEventWatermarks: input.payload.currentTaskEventWatermarks,
257
305
  pushedWatermarks: input.payload.pushedWatermarks,
306
+ pushedTaskChangeKeys: input.payload.pushedTaskChangeKeys ?? new Map(),
258
307
  emittedEventIds,
259
308
  appliedTaskUpserts
260
309
  };
@@ -270,6 +319,7 @@ export async function runWorkspacePullSyncService(input) {
270
319
  let pulledActiveUpserts = false;
271
320
  let pulledArchivedUpserts = false;
272
321
  let pulledTaskEventUpserts = false;
322
+ let pulledPlanningUpserts = false;
273
323
  const documentDecryptFailures = new Set();
274
324
  const emittedEventIds = new Set();
275
325
  const pulledAnnotatedAttachmentSessionIds = new Set();
@@ -296,10 +346,13 @@ export async function runWorkspacePullSyncService(input) {
296
346
  }
297
347
  }
298
348
  if (!pullRes.ok) {
349
+ const pullErrorData = asObjectRecord(pullRes.data);
299
350
  return {
300
351
  success: false,
301
352
  kind: 'pull_http',
302
353
  status: pullRes.status,
354
+ errorCode: typeof pullErrorData.code === 'string' ? pullErrorData.code : undefined,
355
+ error: typeof pullErrorData.error === 'string' ? pullErrorData.error : undefined,
303
356
  retryAfterMs: pullRes.retryAfterMs,
304
357
  transient: isTransientWorkspaceSyncStatus(pullRes.status),
305
358
  cursor,
@@ -311,6 +364,7 @@ export async function runWorkspacePullSyncService(input) {
311
364
  pulledActiveUpserts,
312
365
  pulledArchivedUpserts,
313
366
  pulledTaskEventUpserts,
367
+ pulledPlanningUpserts,
314
368
  documentDecryptFailures: Array.from(documentDecryptFailures),
315
369
  serverDiagnostics: null
316
370
  };
@@ -340,10 +394,14 @@ export async function runWorkspacePullSyncService(input) {
340
394
  pulledAnnotatedAttachmentSessionIds.add(sessionId);
341
395
  continue;
342
396
  }
343
- if (change.op === 'task-event-upsert') {
397
+ if (change.op === 'task-event-upsert' || change.op === 'entity-event-upsert') {
344
398
  pulledTaskEventUpserts = true;
345
399
  continue;
346
400
  }
401
+ if (change.op === 'initiative-upsert' || change.op === 'workstream-upsert') {
402
+ pulledPlanningUpserts = true;
403
+ continue;
404
+ }
347
405
  if (change.op === 'document-upsert') {
348
406
  if (typeof change.content === 'string' && typeof process !== 'undefined' && process.env?.TASKFORCE_SYNC_KEY) {
349
407
  try {
@@ -435,6 +493,7 @@ export async function runWorkspacePullSyncService(input) {
435
493
  pulledActiveUpserts,
436
494
  pulledArchivedUpserts,
437
495
  pulledTaskEventUpserts,
496
+ pulledPlanningUpserts,
438
497
  documentDecryptFailures: Array.from(documentDecryptFailures),
439
498
  emittedEventIds: Array.from(emittedEventIds),
440
499
  serverDiagnostics: lastServerDiagnostics
@@ -457,6 +516,7 @@ export async function runWorkspacePullSyncService(input) {
457
516
  pulledActiveUpserts,
458
517
  pulledArchivedUpserts,
459
518
  pulledTaskEventUpserts,
519
+ pulledPlanningUpserts,
460
520
  documentDecryptFailures: Array.from(documentDecryptFailures),
461
521
  emittedEventIds: Array.from(emittedEventIds),
462
522
  serverDiagnostics: lastServerDiagnostics
@@ -508,6 +568,7 @@ export async function runWorkspacePullSyncService(input) {
508
568
  pulledActiveUpserts,
509
569
  pulledArchivedUpserts,
510
570
  pulledTaskEventUpserts,
571
+ pulledPlanningUpserts,
511
572
  documentDecryptFailures: Array.from(documentDecryptFailures),
512
573
  emittedEventIds: Array.from(emittedEventIds),
513
574
  serverDiagnostics: lastServerDiagnostics
@@ -537,6 +598,7 @@ export async function runWorkspacePullSyncService(input) {
537
598
  pulledActiveUpserts,
538
599
  pulledArchivedUpserts,
539
600
  pulledTaskEventUpserts,
601
+ pulledPlanningUpserts,
540
602
  documentDecryptFailures: Array.from(documentDecryptFailures),
541
603
  emittedEventIds: Array.from(emittedEventIds),
542
604
  serverDiagnostics: lastServerDiagnostics
@@ -556,6 +618,7 @@ export async function runWorkspacePullSyncService(input) {
556
618
  pulledActiveUpserts,
557
619
  pulledArchivedUpserts,
558
620
  pulledTaskEventUpserts,
621
+ pulledPlanningUpserts,
559
622
  documentDecryptFailures: Array.from(documentDecryptFailures),
560
623
  emittedEventIds: Array.from(emittedEventIds),
561
624
  serverDiagnostics: lastServerDiagnostics
@@ -577,6 +640,7 @@ export async function runWorkspacePullSyncService(input) {
577
640
  pulledActiveUpserts,
578
641
  pulledArchivedUpserts,
579
642
  pulledTaskEventUpserts,
643
+ pulledPlanningUpserts,
580
644
  documentDecryptFailures: Array.from(documentDecryptFailures),
581
645
  emittedEventIds: Array.from(emittedEventIds),
582
646
  serverDiagnostics: null
@@ -443,7 +443,7 @@ describe('syncService', () => {
443
443
  status: 200,
444
444
  data: {
445
445
  success: true,
446
- changes: [{ op: 'upsert', task: { id: 't-parent', title: 'Parent', status: 'done', updatedAt: '2026-03-15T20:27:08.000Z' } }],
446
+ changes: [{ op: 'upsert', task: { id: 'task-apply-error', title: 'Apply error', status: 'done', updatedAt: '2026-03-15T20:27:08.000Z' } }],
447
447
  nextCursor: null,
448
448
  hasMore: false
449
449
  }
@@ -452,7 +452,7 @@ describe('syncService', () => {
452
452
  ok: false,
453
453
  status: 400,
454
454
  failures: ['/api/taskforce/sync/workspace/apply-local:400'],
455
- data: { error: 'Parent tasks cannot be marked done manually; completion is derived from descendants' }
455
+ data: { error: 'Task apply rejected by local validation' }
456
456
  });
457
457
  const res = await runWorkspacePullSyncService({
458
458
  resolveCloudAuthUrl: mockResolveCloudAuthUrl,
@@ -463,7 +463,7 @@ describe('syncService', () => {
463
463
  expect(res.success).toBe(false);
464
464
  expect(res.kind).toBe('apply_all_candidates');
465
465
  expect(res.status).toBe(400);
466
- expect(res.error).toBe('Parent tasks cannot be marked done manually; completion is derived from descendants');
466
+ expect(res.error).toBe('Task apply rejected by local validation');
467
467
  });
468
468
  it('surfaces document decryption failures without failing pull', async () => {
469
469
  const previousKey = process.env.TASKFORCE_SYNC_KEY;
@@ -548,6 +548,45 @@ describe('syncService', () => {
548
548
  expect(res.pulledActiveUpserts).toBe(false);
549
549
  expect(res.pulledArchivedUpserts).toBe(false);
550
550
  });
551
+ it('marks planning upserts when the pull contains initiative or workstream changes', async () => {
552
+ vi.mocked(pullWorkspaceChanges).mockResolvedValueOnce({
553
+ ok: true,
554
+ status: 200,
555
+ data: {
556
+ success: true,
557
+ changes: [{
558
+ op: 'workstream-upsert',
559
+ updatedAt: '2026-04-27T22:00:00.000Z',
560
+ workstream: {
561
+ id: 'ws-123',
562
+ title: 'Planning sync workstream',
563
+ description: 'Contains planning attachments',
564
+ createdAt: '2026-04-27T21:00:00.000Z',
565
+ updatedAt: '2026-04-27T22:00:00.000Z',
566
+ attachments: []
567
+ }
568
+ }],
569
+ nextCursor: null,
570
+ hasMore: false
571
+ }
572
+ });
573
+ vi.mocked(applyLocalWorkspaceChanges).mockResolvedValueOnce({
574
+ ok: true,
575
+ failures: [],
576
+ appliedCount: 1,
577
+ data: { success: true }
578
+ });
579
+ const res = await runWorkspacePullSyncService({
580
+ resolveCloudAuthUrl: mockResolveCloudAuthUrl,
581
+ workspaceId: 'ws-1',
582
+ cursor: null,
583
+ bootstrap: false
584
+ });
585
+ expect(res.success).toBe(true);
586
+ expect(res.pulledPlanningUpserts).toBe(true);
587
+ expect(res.pulledActiveUpserts).toBe(false);
588
+ expect(res.pulledArchivedUpserts).toBe(false);
589
+ });
551
590
  it('zero-change bootstrap pull (no changes, hasMore false) returns success true', async () => {
552
591
  vi.mocked(pullWorkspaceChanges).mockResolvedValueOnce({
553
592
  ok: true,
@@ -702,6 +741,60 @@ describe('syncService', () => {
702
741
  expect(res.statusCode).toBe(0);
703
742
  expect(res.transient).toBe(true);
704
743
  });
744
+ it('recovers from missing cloud workspace selection by provisioning and retrying handshake', async () => {
745
+ vi.mocked(handshakeWorkspace)
746
+ .mockResolvedValueOnce({
747
+ ok: false,
748
+ status: 400,
749
+ data: {
750
+ code: 'WORKSPACE_ID_REQUIRED',
751
+ error: 'No cloud workspace is selected. Complete workspace setup first.'
752
+ }
753
+ })
754
+ .mockResolvedValueOnce({
755
+ ok: true,
756
+ status: 200,
757
+ data: {}
758
+ });
759
+ vi.mocked(provisionWorkspace).mockResolvedValueOnce({
760
+ ok: true,
761
+ status: 200,
762
+ data: {
763
+ success: true,
764
+ existing: true
765
+ }
766
+ });
767
+ const res = await ensureCloudWorkspaceReadyForSyncService(baseHandshakeInput);
768
+ expect(res.success).toBe(true);
769
+ expect(res.provisioned).toBe(true);
770
+ expect(provisionWorkspace).toHaveBeenCalledWith(mockResolveCloudAuthUrl, {
771
+ workspaceId: 'ws-test',
772
+ name: 'Test Workspace'
773
+ });
774
+ expect(handshakeWorkspace).toHaveBeenCalledTimes(2);
775
+ });
776
+ it('surfaces provisioning failure when recovering missing cloud workspace selection', async () => {
777
+ vi.mocked(handshakeWorkspace).mockResolvedValueOnce({
778
+ ok: false,
779
+ status: 400,
780
+ data: {
781
+ code: 'WORKSPACE_ID_REQUIRED',
782
+ error: 'No cloud workspace is selected. Complete workspace setup first.'
783
+ }
784
+ });
785
+ vi.mocked(provisionWorkspace).mockResolvedValueOnce({
786
+ ok: false,
787
+ status: 409,
788
+ data: {
789
+ code: 'WORKSPACE_ID_ALREADY_EXISTS',
790
+ error: 'Workspace ID already exists'
791
+ }
792
+ });
793
+ const res = await ensureCloudWorkspaceReadyForSyncService(baseHandshakeInput);
794
+ expect(res.success).toBe(false);
795
+ expect(res.statusCode).toBe(409);
796
+ expect(res.error).toContain('already linked to another cloud account');
797
+ });
705
798
  it('returns failure when cloudAuthConfigured is false', async () => {
706
799
  const res = await ensureCloudWorkspaceReadyForSyncService({
707
800
  ...baseHandshakeInput,
@@ -0,0 +1,2 @@
1
+ import type { TaskItem } from '../types.js';
2
+ export declare function buildTaskSyncChangeKey(task: Partial<TaskItem> | null | undefined, archivedValue: boolean): string;
@@ -0,0 +1,143 @@
1
+ import { serializeTaskForSync } from './taskSyncPayload.js';
2
+ import { normalizeSyncNullableId, normalizeSyncNullableIsoString, normalizeSyncNullableString, normalizeSyncOptionalId, normalizeSyncOptionalString, } from './syncFieldSemantics.js';
3
+ function normalizeConflictTaxonomies(value) {
4
+ if (!value || typeof value !== 'object' || Array.isArray(value))
5
+ return {};
6
+ const entries = Object.entries(value)
7
+ .filter(([key]) => String(key || '').trim().length > 0)
8
+ .sort(([left], [right]) => left.localeCompare(right));
9
+ const normalized = {};
10
+ for (const [key, raw] of entries) {
11
+ if (Array.isArray(raw)) {
12
+ normalized[key] = raw.map((entry) => String(entry ?? '')).sort((left, right) => left.localeCompare(right));
13
+ continue;
14
+ }
15
+ if (raw === undefined || raw === null)
16
+ continue;
17
+ normalized[key] = String(raw);
18
+ }
19
+ return normalized;
20
+ }
21
+ function normalizeConflictChecklistItems(value) {
22
+ if (!Array.isArray(value))
23
+ return [];
24
+ return value
25
+ .map((item) => {
26
+ const entry = item && typeof item === 'object' ? item : {};
27
+ return {
28
+ id: String(entry.id || '').trim(),
29
+ title: String(entry.title || '').trim(),
30
+ isCompleted: Boolean(entry.isCompleted),
31
+ order: entry.order === undefined || entry.order === null ? '' : String(entry.order),
32
+ };
33
+ })
34
+ .sort((left, right) => {
35
+ const leftOrder = Number.parseInt(left.order, 10);
36
+ const rightOrder = Number.parseInt(right.order, 10);
37
+ if (Number.isFinite(leftOrder) && Number.isFinite(rightOrder) && leftOrder !== rightOrder) {
38
+ return leftOrder - rightOrder;
39
+ }
40
+ if (left.title !== right.title)
41
+ return left.title.localeCompare(right.title);
42
+ return left.id.localeCompare(right.id);
43
+ });
44
+ }
45
+ function normalizeSyncComments(value) {
46
+ if (!Array.isArray(value))
47
+ return [];
48
+ return value
49
+ .map((entry) => {
50
+ const comment = entry && typeof entry === 'object' ? entry : null;
51
+ return {
52
+ id: String(comment?.id || '').trim(),
53
+ author: String(comment?.author || '').trim(),
54
+ submittedAuthor: normalizeSyncOptionalString(comment?.submittedAuthor) || '',
55
+ text: String(comment?.text || ''),
56
+ timestamp: normalizeSyncNullableIsoString(comment?.timestamp) || '',
57
+ actor: comment?.actor ?? null,
58
+ };
59
+ })
60
+ .sort((left, right) => {
61
+ if (left.timestamp !== right.timestamp)
62
+ return left.timestamp.localeCompare(right.timestamp);
63
+ if (left.id !== right.id)
64
+ return left.id.localeCompare(right.id);
65
+ if (left.author !== right.author)
66
+ return left.author.localeCompare(right.author);
67
+ return left.text.localeCompare(right.text);
68
+ });
69
+ }
70
+ function normalizeSyncAttachments(value) {
71
+ if (!Array.isArray(value))
72
+ return [];
73
+ return value
74
+ .map((entry) => {
75
+ if (typeof entry === 'string') {
76
+ const path = entry.trim();
77
+ return {
78
+ path,
79
+ fsPath: '',
80
+ caption: '',
81
+ displayName: '',
82
+ originalFilename: '',
83
+ assetId: '',
84
+ referenceNumber: '',
85
+ taskId: '',
86
+ timestamp: '',
87
+ };
88
+ }
89
+ const attachment = entry && typeof entry === 'object' ? entry : null;
90
+ return {
91
+ path: String(attachment?.path || '').trim(),
92
+ fsPath: normalizeSyncOptionalString(attachment?.fsPath) || '',
93
+ caption: normalizeSyncOptionalString(attachment?.caption) || '',
94
+ displayName: normalizeSyncOptionalString(attachment?.displayName) || '',
95
+ originalFilename: normalizeSyncOptionalString(attachment?.originalFilename) || '',
96
+ assetId: normalizeSyncOptionalId(attachment?.assetId) || '',
97
+ referenceNumber: attachment?.referenceNumber === undefined || attachment.referenceNumber === null
98
+ ? ''
99
+ : String(attachment.referenceNumber),
100
+ taskId: normalizeSyncNullableId(attachment?.taskId) || '',
101
+ timestamp: normalizeSyncNullableIsoString(attachment?.timestamp) || '',
102
+ };
103
+ })
104
+ .sort((left, right) => {
105
+ if (left.path !== right.path)
106
+ return left.path.localeCompare(right.path);
107
+ if (left.assetId !== right.assetId)
108
+ return left.assetId.localeCompare(right.assetId);
109
+ if (left.timestamp !== right.timestamp)
110
+ return left.timestamp.localeCompare(right.timestamp);
111
+ return JSON.stringify(left).localeCompare(JSON.stringify(right));
112
+ });
113
+ }
114
+ export function buildTaskSyncChangeKey(task, archivedValue) {
115
+ const source = serializeTaskForSync(task);
116
+ return JSON.stringify({
117
+ id: source.id,
118
+ title: source.title,
119
+ description: normalizeSyncNullableString(source.description) || '',
120
+ category: source.category,
121
+ type: source.type,
122
+ priority: source.priority === undefined || source.priority === null ? '' : String(source.priority),
123
+ complexity: source.complexity === undefined || source.complexity === null ? '' : String(source.complexity),
124
+ status: source.status,
125
+ approach: normalizeSyncOptionalString(source.approach) || '',
126
+ canceledReason: normalizeSyncNullableString(source.canceledReason) || '',
127
+ createdAt: source.createdAt,
128
+ completedAt: normalizeSyncNullableIsoString(source.completedAt) || '',
129
+ taxonomies: normalizeConflictTaxonomies(source.taxonomies),
130
+ createdBy: normalizeSyncOptionalId(source.createdBy) || '',
131
+ assignee: normalizeSyncOptionalId(source.assignee) || '',
132
+ scheduledDate: normalizeSyncNullableString(source.scheduledDate) || '',
133
+ dueDate: normalizeSyncNullableString(source.dueDate) || '',
134
+ scheduledWeekKey: normalizeSyncNullableString(source.scheduledWeekKey) || '',
135
+ orderInDay: source.orderInDay === undefined || source.orderInDay === null ? '' : String(source.orderInDay),
136
+ workstreamId: normalizeSyncNullableId(source.workstreamId) || '',
137
+ referenceNumber: source.referenceNumber === undefined || source.referenceNumber === null ? '' : String(source.referenceNumber),
138
+ comments: normalizeSyncComments(source.comments),
139
+ attachments: normalizeSyncAttachments(source.attachments),
140
+ checklistItems: normalizeConflictChecklistItems(source.checklistItems),
141
+ isArchived: archivedValue ? '1' : '0'
142
+ });
143
+ }
@@ -1,16 +1,11 @@
1
+ import { normalizeSyncNullableString, normalizeSyncOptionalString, } from './syncFieldSemantics.js';
1
2
  function toOptionalString(value) {
2
- if (value === undefined || value === null)
3
- return undefined;
4
- const normalized = String(value).trim();
5
- return normalized.length > 0 ? normalized : undefined;
3
+ return normalizeSyncOptionalString(value);
6
4
  }
7
5
  function toNullableString(value) {
8
6
  if (value === undefined)
9
7
  return undefined;
10
- if (value === null)
11
- return null;
12
- const normalized = String(value).trim();
13
- return normalized.length > 0 ? normalized : null;
8
+ return normalizeSyncNullableString(value);
14
9
  }
15
10
  function toOptionalBoolean(value) {
16
11
  return typeof value === 'boolean' ? value : undefined;
@@ -25,6 +25,10 @@ export interface WorkspacePullFeedResult {
25
25
  hydrationMs: number;
26
26
  encodeMs: number;
27
27
  buildMs: number;
28
+ snapshotErrors: Array<{
29
+ domain: string;
30
+ error: string;
31
+ }>;
28
32
  };
29
33
  }
30
34
  export declare function buildWorkspacePullFeed(input: {