@taskforcehq/taskforce 0.3.327 → 0.3.329

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 (360) hide show
  1. package/dist/Taskforce.module.css +257 -87
  2. package/dist/TaskforceCore.js +237 -230
  3. package/dist/annotatedAttachments/AnnotatedAttachmentSessionStore.js +1 -1
  4. package/dist/cli.js +34 -0
  5. package/dist/cliCloudTargetGuard.d.ts +5 -0
  6. package/dist/cliCloudTargetGuard.js +11 -0
  7. package/dist/components/activity/EntityActivityTimeline.js +15 -5
  8. package/dist/components/context/AttachmentPreviewHost.js +1 -1
  9. package/dist/components/context/ContextAttachmentManager.d.ts +3 -0
  10. package/dist/components/context/ContextAttachmentManager.js +116 -20
  11. package/dist/components/features/AnnotatedAttachmentWorkspace.js +24 -8
  12. package/dist/components/features/TaskSettings.d.ts +12 -1
  13. package/dist/components/features/TaskSettings.js +147 -40
  14. package/dist/components/features/agentCapabilities/AgentCapabilitiesPrototype.d.ts +1 -1
  15. package/dist/components/features/planning/PlanningEntitySummary.d.ts +3 -1
  16. package/dist/components/features/planning/PlanningEntitySummary.js +3 -2
  17. package/dist/components/features/planning/PlanningLinkPicker.d.ts +3 -1
  18. package/dist/components/features/planning/PlanningLinkPicker.js +5 -3
  19. package/dist/components/features/planning/PlanningModule.js +28 -14
  20. package/dist/components/features/planning/PlanningTaskOrderList.d.ts +1 -1
  21. package/dist/components/features/planning/PlanningTaskOrderList.js +17 -6
  22. package/dist/components/features/planning/PlanningVisualIdentity.d.ts +14 -0
  23. package/dist/components/features/planning/PlanningVisualIdentity.js +106 -0
  24. package/dist/components/features/planning/planningTaskArrangement.d.ts +1 -0
  25. package/dist/components/features/planning/planningTaskArrangement.js +5 -5
  26. package/dist/components/features/planning/planningWorkspaceModel.d.ts +11 -0
  27. package/dist/components/features/taskforceAgentEditorModel.js +3 -1
  28. package/dist/components/task/TaskActionHeader.d.ts +2 -1
  29. package/dist/components/task/TaskActionHeader.js +2 -2
  30. package/dist/components/task/TaskCard.d.ts +5 -0
  31. package/dist/components/task/TaskCard.js +101 -13
  32. package/dist/components/task/TaskContextUpload.d.ts +3 -0
  33. package/dist/components/task/TaskContextUpload.js +2 -2
  34. package/dist/components/task/TaskForm.d.ts +4 -0
  35. package/dist/components/task/TaskForm.js +32 -7
  36. package/dist/components/task/TaskImageReviews.js +28 -19
  37. package/dist/components/task/TaskKanban.d.ts +6 -1
  38. package/dist/components/task/TaskKanban.js +152 -6
  39. package/dist/components/task/TaskList.d.ts +5 -0
  40. package/dist/components/task/TaskList.js +3 -3
  41. package/dist/components/task/TaskStatusActions.js +11 -2
  42. package/dist/components/task/TaskWorkstreamPicker.js +2 -1
  43. package/dist/components/ui/DocumentTypeIcon.d.ts +7 -0
  44. package/dist/components/ui/DocumentTypeIcon.js +8 -0
  45. package/dist/components/ui/PasswordInput.d.ts +6 -0
  46. package/dist/components/ui/PasswordInput.js +11 -0
  47. package/dist/components/ui/TaxonomyDropdown.d.ts +9 -1
  48. package/dist/components/ui/TaxonomyDropdown.js +30 -3
  49. package/dist/components/ui/TopNoticeLayer.js +1 -1
  50. package/dist/components/views/AppShellHeader.js +32 -11
  51. package/dist/components/views/PlanComparisonPage.js +12 -0
  52. package/dist/components/views/StandaloneLayout.js +68 -39
  53. package/dist/components/views/WidgetView.js +10 -7
  54. package/dist/components/views/panels/PlanningDrawer.d.ts +7 -1
  55. package/dist/components/views/panels/PlanningDrawer.js +51 -54
  56. package/dist/components/views/standalone/modals/AccountSettingsModal.js +26 -17
  57. package/dist/config/envSchema.js +13 -0
  58. package/dist/config/localServiceCloudTarget.d.ts +10 -0
  59. package/dist/config/localServiceCloudTarget.js +76 -0
  60. package/dist/config/localServiceRuntimeContract.d.ts +13 -0
  61. package/dist/config/localServiceRuntimeContract.js +135 -0
  62. package/dist/core/AiProfileService.d.ts +1 -0
  63. package/dist/core/AiProfileService.js +48 -9
  64. package/dist/core/AttachmentLinkService.js +7 -4
  65. package/dist/core/DeletedTaskLifecycleService.d.ts +5 -0
  66. package/dist/core/DeletedTaskLifecycleService.js +55 -3
  67. package/dist/core/McpTokenService.d.ts +4 -0
  68. package/dist/core/McpTokenService.js +52 -0
  69. package/dist/core/TaskAttachmentLinksDurableMutationService.d.ts +8 -2
  70. package/dist/core/TaskAttachmentLinksDurableMutationService.js +51 -18
  71. package/dist/core/Taskforce.d.ts +124 -2
  72. package/dist/core/Taskforce.js +1175 -87
  73. package/dist/core/types.d.ts +8 -1
  74. package/dist/documentReviews/DocumentReviewCommentStore.d.ts +11 -0
  75. package/dist/documentReviews/DocumentReviewCommentStore.js +35 -2
  76. package/dist/documentReviews/service.d.ts +4 -0
  77. package/dist/documentReviews/service.js +141 -46
  78. package/dist/hooks/sync/useDurableLocalOutboxDrain.d.ts +1 -1
  79. package/dist/hooks/sync/useDurableTaskCreateMutation.js +1 -1
  80. package/dist/hooks/sync/useDurableTaskMetadataMutation.d.ts +1 -0
  81. package/dist/hooks/sync/useDurableTaskMetadataMutation.js +1 -0
  82. package/dist/hooks/sync/useDurableTaskStatusMutation.d.ts +1 -0
  83. package/dist/hooks/tasks/taskHttpMutation.js +1 -0
  84. package/dist/hooks/tasks/useCloudTaskSearch.d.ts +12 -0
  85. package/dist/hooks/tasks/useCloudTaskSearch.js +71 -0
  86. package/dist/hooks/tasks/useTaskDescriptionImageDraftRecovery.d.ts +16 -0
  87. package/dist/hooks/tasks/useTaskDescriptionImageDraftRecovery.js +197 -0
  88. package/dist/hooks/tasks/useTaskEditorNavigation.d.ts +16 -3
  89. package/dist/hooks/tasks/useTaskEditorNavigation.js +72 -13
  90. package/dist/hooks/tasks/useTaskFormActions.d.ts +9 -0
  91. package/dist/hooks/tasks/useTaskFormActions.js +96 -17
  92. package/dist/hooks/ui/useSettingsModel.d.ts +24 -2
  93. package/dist/hooks/ui/useSettingsModel.js +13 -2
  94. package/dist/hooks/ui/useSettingsPersistence.d.ts +12 -1
  95. package/dist/hooks/ui/useSettingsPersistence.js +74 -47
  96. package/dist/hooks/useFilterSort.d.ts +7 -3
  97. package/dist/hooks/useFilterSort.js +15 -5
  98. package/dist/hooks/useTaskData.d.ts +10 -1
  99. package/dist/hooks/useTaskData.js +216 -7
  100. package/dist/hooks/useTaskMutations.d.ts +10 -2
  101. package/dist/hooks/useTaskMutations.js +223 -43
  102. package/dist/hooks/useTaskforce.d.ts +94 -57
  103. package/dist/hooks/useTaskforce.js +428 -16
  104. package/dist/hooks/useUiNotice.d.ts +4 -0
  105. package/dist/hooks/useUiNotice.js +4 -0
  106. package/dist/mcp/adminWorkspaceRegistrar.js +3 -3
  107. package/dist/mcp/canonicalAssetHelpers.d.ts +13 -0
  108. package/dist/mcp/canonicalAssetHelpers.js +39 -5
  109. package/dist/mcp/collaborationRegistrar.js +15 -13
  110. package/dist/mcp/documentAssetRegistrar.js +60 -44
  111. package/dist/mcp/documentHelpers.d.ts +1 -0
  112. package/dist/mcp/documentHelpers.js +7 -3
  113. package/dist/mcp/localServiceProxy.js +4 -1
  114. package/dist/mcp/runtime.d.ts +16 -0
  115. package/dist/mcp/runtime.js +735 -210
  116. package/dist/mcp/taskAttachmentCommandAdapter.d.ts +2 -0
  117. package/dist/mcp/taskAttachmentCommandAdapter.js +14 -8
  118. package/dist/mcp/taskPlanningRegistrar.js +78 -67
  119. package/dist/mcp/toolCallCompatibility.js +38 -1
  120. package/dist/mcp/toolCatalog.d.ts +1 -0
  121. package/dist/mcp/toolRegistry.js +2 -2
  122. package/dist/migrations/taskSchemaMigrations.js +47 -0
  123. package/dist/runtime/appGateDefinitions.d.ts +30 -6
  124. package/dist/runtime/appGateDefinitions.js +6 -6
  125. package/dist/runtime/appGates.d.ts +12 -13
  126. package/dist/runtime/appGates.js +29 -13
  127. package/dist/runtime/nodeAppGates.d.ts +8 -0
  128. package/dist/runtime/nodeAppGates.js +27 -0
  129. package/dist/server/appAccess.d.ts +12 -0
  130. package/dist/server/appAccess.js +21 -0
  131. package/dist/server/authorizedWorkspaceAccess.d.ts +12 -0
  132. package/dist/server/authorizedWorkspaceAccess.js +40 -0
  133. package/dist/server/cloudCollectionRead.d.ts +25 -0
  134. package/dist/server/cloudCollectionRead.js +120 -0
  135. package/dist/server/cloudCollectionReadPool.d.ts +52 -0
  136. package/dist/server/cloudCollectionReadPool.js +140 -0
  137. package/dist/server/cloudCollectionReadWorker.d.ts +1 -0
  138. package/dist/server/cloudCollectionReadWorker.js +36 -0
  139. package/dist/server/index.d.ts +6 -11
  140. package/dist/server/index.js +67 -42
  141. package/dist/server/localServiceLease.d.ts +6 -0
  142. package/dist/server/localServiceLease.js +17 -1
  143. package/dist/server/localWorkspaceSyncServerRuntime.js +10 -3
  144. package/dist/server/rateLimit.d.ts +1 -0
  145. package/dist/server/rateLimit.js +4 -0
  146. package/dist/server/realtimeSyncWs.js +36 -12
  147. package/dist/server/routes/admin.js +1 -0
  148. package/dist/server/routes/agentRoles.js +3 -2
  149. package/dist/server/routes/agentSkills.js +3 -2
  150. package/dist/server/routes/agents.js +118 -16
  151. package/dist/server/routes/annotatedAttachments.js +3 -2
  152. package/dist/server/routes/auth.js +3 -1
  153. package/dist/server/routes/documents.d.ts +5 -2
  154. package/dist/server/routes/documents.js +160 -13
  155. package/dist/server/routes/durableTaskHttpRouters.d.ts +11 -2
  156. package/dist/server/routes/durableTaskHttpRouters.js +2 -2
  157. package/dist/server/routes/localService.js +4 -0
  158. package/dist/server/routes/primitives.d.ts +4 -0
  159. package/dist/server/routes/shared.d.ts +24 -0
  160. package/dist/server/routes/shared.js +114 -18
  161. package/dist/server/routes/sync.js +22 -0
  162. package/dist/server/routes/syncAuxRoutes.js +5 -2
  163. package/dist/server/routes/syncPullApplyRoutes.js +23 -4
  164. package/dist/server/routes/syncV3FeedRoutes.js +22 -18
  165. package/dist/server/routes/syncV3LocalCaptureRoutes.js +48 -4
  166. package/dist/server/routes/syncV3LocalFeedApplyRoutes.d.ts +1 -0
  167. package/dist/server/routes/syncV3LocalFeedApplyRoutes.js +26 -0
  168. package/dist/server/routes/syncV3OperationRoutes.js +27 -2
  169. package/dist/server/routes/tasks.js +299 -97
  170. package/dist/server/routes/workspaces.js +43 -1
  171. package/dist/server/routes.js +35 -7
  172. package/dist/server/workspaceDeletionAdmission.d.ts +23 -0
  173. package/dist/server/workspaceDeletionAdmission.js +50 -0
  174. package/dist/service/localServiceCli.js +52 -25
  175. package/dist/service/localServiceClientLifecycle.js +93 -6
  176. package/dist/services/codexAppServerModelGateway.d.ts +112 -0
  177. package/dist/services/codexAppServerModelGateway.js +438 -0
  178. package/dist/services/taskforceAgentMcpBridge.d.ts +7 -1
  179. package/dist/services/taskforceAgentMcpBridge.js +23 -3
  180. package/dist/shared/planningIdentity.d.ts +20 -0
  181. package/dist/shared/planningIdentity.js +79 -0
  182. package/dist/shared/taskforceAgentDefinition.js +7 -1
  183. package/dist/shared/taskforceAgentModels.d.ts +1 -0
  184. package/dist/shared/taskforceAgentModels.js +30 -1
  185. package/dist/storage/postgresAdapter.d.ts +20 -3
  186. package/dist/storage/postgresAdapter.js +110 -14
  187. package/dist/storage/postgresRequestDiagnostics.d.ts +8 -0
  188. package/dist/storage/postgresRequestDiagnostics.js +24 -0
  189. package/dist/storage/postgresWorker.js +13 -4
  190. package/dist/storage/postgresWorkerProtocol.d.ts +29 -0
  191. package/dist/storage/postgresWorkerProtocol.js +30 -0
  192. package/dist/storage/workspaceAssetStore.d.ts +32 -0
  193. package/dist/storage/workspaceAssetStore.js +70 -0
  194. package/dist/sync/cloudSyncApi.d.ts +4 -1
  195. package/dist/sync/cloudSyncApi.js +7 -2
  196. package/dist/sync/contentSyncState.d.ts +1 -1
  197. package/dist/sync/coordinator/localSyncExecutionPermitStore.d.ts +17 -0
  198. package/dist/sync/coordinator/localSyncExecutionPermitStore.js +77 -23
  199. package/dist/sync/coordinator/localWorkspaceSyncRunner.js +6 -2
  200. package/dist/sync/coordinator/workspaceSyncTransportGateway.js +4 -2
  201. package/dist/sync/engine/workspaceSyncEngineBrowserGatewayRemoteServices.js +20 -2
  202. package/dist/sync/engine/workspaceSyncEngineLocalServices.d.ts +4 -0
  203. package/dist/sync/engine/workspaceSyncEngineLocalServices.js +11 -0
  204. package/dist/sync/engine/workspaceSyncEngineRemoteServices.d.ts +16 -0
  205. package/dist/sync/engine/workspaceSyncEngineRemoteServices.js +2 -1
  206. package/dist/sync/engine/workspaceSyncEngineServerRemoteServices.d.ts +1 -1
  207. package/dist/sync/engine/workspaceSyncEngineServerRemoteServices.js +46 -4
  208. package/dist/sync/engine/workspaceSyncEngineServerRunnerOperations.d.ts +3 -1
  209. package/dist/sync/engine/workspaceSyncEngineServerRunnerOperations.js +51 -11
  210. package/dist/sync/engine/workspaceSyncEngineTransfers.d.ts +1 -1
  211. package/dist/sync/engine/workspaceSyncEngineTransfers.js +8 -3
  212. package/dist/sync/engine/workspaceSyncV2ChangeDispatcher.js +2 -0
  213. package/dist/sync/syncApplyHandlers.d.ts +3 -1
  214. package/dist/sync/syncApplyHandlers.js +29 -0
  215. package/dist/sync/syncService.d.ts +2 -0
  216. package/dist/sync/syncService.js +13 -1
  217. package/dist/sync/taskSyncPayload.d.ts +1 -0
  218. package/dist/sync/taskSyncPayload.js +6 -0
  219. package/dist/sync/v3/combinedFeedCapability.js +4 -0
  220. package/dist/sync/v3/durableTaskAttachmentLinksMutationRouter.d.ts +3 -0
  221. package/dist/sync/v3/durableTaskAttachmentLinksMutationRouter.js +31 -3
  222. package/dist/sync/v3/durableTaskChecklistMutationRouter.d.ts +2 -0
  223. package/dist/sync/v3/durableTaskChecklistMutationRouter.js +4 -0
  224. package/dist/sync/v3/durableTaskHttpBulkMutationRouter.d.ts +1 -0
  225. package/dist/sync/v3/durableTaskHttpBulkMutationRouter.js +47 -12
  226. package/dist/sync/v3/durableTaskHttpRootMutationRouter.d.ts +5 -3
  227. package/dist/sync/v3/durableTaskHttpRootMutationRouter.js +27 -2
  228. package/dist/sync/v3/localInitiativeOutboxService.js +4 -2
  229. package/dist/sync/v3/localOutboxDispatcher.js +5 -1
  230. package/dist/sync/v3/localTaskAttachmentLinksOutboxHandler.js +12 -2
  231. package/dist/sync/v3/localTaskAttachmentLinksOutboxService.d.ts +3 -0
  232. package/dist/sync/v3/localTaskAttachmentLinksOutboxService.js +62 -10
  233. package/dist/sync/v3/localTaskCreateOutboxService.js +15 -6
  234. package/dist/sync/v3/localTaskMetadataClient.d.ts +1 -0
  235. package/dist/sync/v3/localTaskMetadataClient.js +1 -0
  236. package/dist/sync/v3/localTaskMetadataOutboxHandler.js +5 -1
  237. package/dist/sync/v3/localTaskMetadataOutboxService.d.ts +2 -0
  238. package/dist/sync/v3/localTaskMetadataOutboxService.js +7 -0
  239. package/dist/sync/v3/localTaskRestoreOutboxService.js +14 -6
  240. package/dist/sync/v3/localTaskStatusClient.d.ts +1 -0
  241. package/dist/sync/v3/localTaskStatusClient.js +6 -1
  242. package/dist/sync/v3/localTaskStatusOutboxService.d.ts +2 -0
  243. package/dist/sync/v3/localTaskStatusOutboxService.js +54 -13
  244. package/dist/sync/v3/localWorkstreamOutboxService.js +4 -2
  245. package/dist/sync/v3/syncDurabilityStore.d.ts +15 -0
  246. package/dist/sync/v3/syncDurabilityStore.js +201 -43
  247. package/dist/sync/v3/taskAttachmentLinksMutationService.d.ts +7 -4
  248. package/dist/sync/v3/taskAttachmentLinksMutationService.js +37 -12
  249. package/dist/sync/v3/taskChecklistMutationService.d.ts +4 -2
  250. package/dist/sync/v3/taskChecklistMutationService.js +4 -0
  251. package/dist/sync/v3/taskCreateMutationService.d.ts +2 -2
  252. package/dist/sync/v3/taskCreateMutationService.js +7 -4
  253. package/dist/sync/v3/taskMetadataCoexistence.js +4 -0
  254. package/dist/sync/v3/taskMetadataMutationService.d.ts +3 -0
  255. package/dist/sync/v3/taskMetadataMutationService.js +4 -0
  256. package/dist/sync/v3/taskRestoreMutationService.d.ts +2 -2
  257. package/dist/sync/v3/taskRestoreMutationService.js +7 -4
  258. package/dist/sync/v3/taskStatusMutationService.d.ts +2 -0
  259. package/dist/sync/v3/taskStatusMutationService.js +4 -0
  260. package/dist/sync/v3/workflowAssignmentSync.d.ts +1 -0
  261. package/dist/sync/v3/workflowAssignmentSync.js +3 -0
  262. package/dist/sync/v3/workspaceSyncV2ProjectionExclusions.d.ts +1 -1
  263. package/dist/sync/v3/workspaceSyncV2ProjectionExclusions.js +14 -12
  264. package/dist/sync/v3/workspaceSyncV3AttachmentApplyObligationStore.d.ts +11 -0
  265. package/dist/sync/v3/workspaceSyncV3AttachmentApplyObligationStore.js +27 -10
  266. package/dist/sync/v3/workspaceSyncV3AttachmentAssetHydration.d.ts +2 -1
  267. package/dist/sync/v3/workspaceSyncV3AttachmentAssetHydration.js +52 -10
  268. package/dist/sync/v3/workspaceSyncV3CloudOperationHandler.js +10 -1
  269. package/dist/sync/v3/workspaceSyncV3CombinedFeedOrchestrator.js +15 -4
  270. package/dist/sync/v3/workspaceSyncV3CombinedLocalApply.js +66 -13
  271. package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.d.ts +11 -0
  272. package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.js +57 -22
  273. package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.d.ts +10 -4
  274. package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.js +124 -51
  275. package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.d.ts +10 -0
  276. package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.js +120 -28
  277. package/dist/sync/v3/workspaceSyncV3CombinedWireContract.d.ts +3 -1
  278. package/dist/sync/v3/workspaceSyncV3CombinedWireContract.js +18 -0
  279. package/dist/sync/v3/workspaceSyncV3CoverageRegistry.js +6 -0
  280. package/dist/sync/v3/workspaceSyncV3FeedProfile.d.ts +1 -1
  281. package/dist/sync/v3/workspaceSyncV3LegacyBoundaryAttestation.d.ts +1 -0
  282. package/dist/sync/v3/workspaceSyncV3LegacyBoundaryAttestation.js +23 -10
  283. package/dist/sync/v3/workspaceSyncV3NestedTaskApply.d.ts +3 -0
  284. package/dist/sync/v3/workspaceSyncV3NestedTaskApply.js +64 -13
  285. package/dist/sync/v3/workspaceSyncV3NestedTaskCodecs.d.ts +9 -0
  286. package/dist/sync/v3/workspaceSyncV3NestedTaskCodecs.js +26 -0
  287. package/dist/sync/v3/workspaceSyncV3NestedTaskProjection.d.ts +15 -5
  288. package/dist/sync/v3/workspaceSyncV3NestedTaskProjection.js +50 -14
  289. package/dist/sync/v3/workspaceSyncV3NestedTaskRepairSnapshot.d.ts +2 -1
  290. package/dist/sync/v3/workspaceSyncV3NestedTaskRepairSnapshot.js +11 -3
  291. package/dist/sync/v3/workspaceSyncV3OperationProtocol.d.ts +3 -0
  292. package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.d.ts +2 -0
  293. package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.js +19 -7
  294. package/dist/sync/v3/workspaceSyncV3RepairSqlBatching.d.ts +2 -0
  295. package/dist/sync/v3/workspaceSyncV3RepairSqlBatching.js +10 -0
  296. package/dist/sync/v3/workspaceSyncV3TaskCommentAudit.js +9 -2
  297. package/dist/sync/v3/workspaceSyncV3TaskCoverCoverage.d.ts +7 -0
  298. package/dist/sync/v3/workspaceSyncV3TaskCoverCoverage.js +37 -0
  299. package/dist/sync/v3/workspaceSyncV3TaskCoverWireContract.d.ts +6 -0
  300. package/dist/sync/v3/workspaceSyncV3TaskCoverWireContract.js +9 -0
  301. package/dist/sync/v3/workspaceSyncV3TaskRootProjection.d.ts +1 -1
  302. package/dist/sync/v3/workspaceSyncV3TaskRootProjection.js +1 -1
  303. package/dist/sync/workspacePullFeed.d.ts +6 -1
  304. package/dist/sync/workspacePullFeed.js +174 -162
  305. package/dist/sync/workspaceRepair.d.ts +3 -0
  306. package/dist/sync/workspaceRepair.js +67 -6
  307. package/dist/sync/workspaceSyncModel.d.ts +11 -0
  308. package/dist/sync/workspaceSyncModel.js +27 -2
  309. package/dist/types.d.ts +55 -1
  310. package/dist/types.js +6 -0
  311. package/dist/ui/assets/{AiIdentityRosterCard-DB1BLO_j.js → AiIdentityRosterCard-BZM4aQnM.js} +1 -1
  312. package/dist/ui/assets/AiProfilesModule-BbAEWtHH.js +1 -0
  313. package/dist/ui/assets/AnnotatedAttachmentWorkspace-B68Wg-RV.js +3 -0
  314. package/dist/ui/assets/AnnotatedAttachmentWorkspace-TzYu7pkG.css +1 -0
  315. package/dist/ui/assets/AssetTraySortControl-C8Rztyal.js +1 -0
  316. package/dist/ui/assets/ContextAttachmentManager-Cj3c7X9y.js +3 -0
  317. package/dist/ui/assets/{DocumentWorkspace-BC7sy5TG.js → DocumentWorkspace-B5uvzems.js} +4 -4
  318. package/dist/ui/assets/EntityActivityTimeline-BVFvCB5R.js +1 -0
  319. package/dist/ui/assets/PlanningModule-B5DWQOGz.js +1 -0
  320. package/dist/ui/assets/PlanningModule-CoIR9hbV.css +1 -0
  321. package/dist/ui/assets/PlansPage-AY4cGWco.js +1 -0
  322. package/dist/ui/assets/TaskContextUpload-DZxTVesW.js +1 -0
  323. package/dist/ui/assets/TaskContextUpload-qmBeUw3u.css +1 -0
  324. package/dist/ui/assets/TaskSettings-BeWAuyZj.js +12 -0
  325. package/dist/ui/assets/{TaskforceAgentsModule-CkAxW19K.js → TaskforceAgentsModule-BifCYtjR.js} +6 -6
  326. package/dist/ui/assets/WorkflowManagerModule-DEr5di_r.js +1 -0
  327. package/dist/ui/assets/index-I5zhdtgt.js +7 -0
  328. package/dist/ui/assets/index-VRFsx3wz.css +1 -0
  329. package/dist/ui/assets/{vendor-icons-B8ZNsH1g.js → vendor-icons-D9Lpw-j4.js} +1 -1
  330. package/dist/ui/index.html +3 -3
  331. package/dist/utils/constants.d.ts +2 -2
  332. package/dist/utils/constants.js +1 -1
  333. package/dist/utils/contextAttachmentUpload.d.ts +2 -0
  334. package/dist/utils/contextAttachmentUpload.js +7 -0
  335. package/dist/utils/contextFiles.d.ts +1 -1
  336. package/dist/utils/contextFiles.js +4 -4
  337. package/dist/utils/taskActivity.d.ts +3 -2
  338. package/dist/utils/taskActivity.js +19 -2
  339. package/dist/utils/taskEditorReconciliation.d.ts +40 -0
  340. package/dist/utils/taskEditorReconciliation.js +217 -0
  341. package/dist/utils/taskNormalization.d.ts +1 -0
  342. package/dist/utils/taskNormalization.js +39 -0
  343. package/dist/utils/taskSearch.js +2 -2
  344. package/dist/utils/uiNotice.d.ts +4 -0
  345. package/package.json +21 -4
  346. package/dist/ui/assets/AiProfilesModule-DPxQeF9N.js +0 -1
  347. package/dist/ui/assets/AnnotatedAttachmentWorkspace-CBRZ8rca.css +0 -1
  348. package/dist/ui/assets/AnnotatedAttachmentWorkspace-DHNYaNg6.js +0 -3
  349. package/dist/ui/assets/AssetTraySortControl-DphbyHVc.js +0 -1
  350. package/dist/ui/assets/ContextAttachmentManager-CMxSzHqc.js +0 -3
  351. package/dist/ui/assets/EntityActivityTimeline-pJ2ZjZ-k.js +0 -1
  352. package/dist/ui/assets/PlanningModule-CeTqXMMz.css +0 -1
  353. package/dist/ui/assets/PlanningModule-t5GbvVR9.js +0 -1
  354. package/dist/ui/assets/PlansPage-BVH_NfgT.js +0 -1
  355. package/dist/ui/assets/TaskContextUpload-Ds4LnDzV.css +0 -1
  356. package/dist/ui/assets/TaskContextUpload-bl4fOOUz.js +0 -1
  357. package/dist/ui/assets/TaskSettings-xVsxSa0g.js +0 -12
  358. package/dist/ui/assets/WorkflowManagerModule-BKqIGVnF.js +0 -1
  359. package/dist/ui/assets/index-BzJlVnNS.css +0 -1
  360. package/dist/ui/assets/index-Cx7vZJHL.js +0 -7
@@ -3,7 +3,7 @@ import type { WorkspaceSyncPayload } from '../workspaceSyncModel.js';
3
3
  import type { WorkspaceSyncPhase } from '../workspaceSyncState.js';
4
4
  import type { WorkspaceSyncV3CombinedCoverageSelector } from '../v3/workspaceSyncV3CombinedWireContract.js';
5
5
  import type { WorkspaceSyncEngineRuntime } from './workspaceSyncEngineRuntime.js';
6
- import type { WorkspaceSyncEngineLocalServices } from './workspaceSyncEngineLocalServices.js';
6
+ import { type WorkspaceSyncEngineLocalServices } from './workspaceSyncEngineLocalServices.js';
7
7
  import type { WorkspaceSyncEngineRemoteServices, WorkspaceSyncEngineRemoteTransferReceipt } from './workspaceSyncEngineRemoteServices.js';
8
8
  export type { PendingWorkspacePushReplay } from './workspaceSyncEngineTransferTypes.js';
9
9
  type StateSetter<T> = (value: T | ((current: T) => T)) => void;
@@ -4,6 +4,7 @@ import { resolveWorkspacePullRequestPlan, resolveWorkspacePullSuccessPlan } from
4
4
  import { runWorkspaceSyncV3InitiativeProjectionCycle } from '../v3/workspaceSyncV3FeedOrchestrator.js';
5
5
  import { runWorkspaceSyncV3CombinedProjectionCycle } from '../v3/workspaceSyncV3CombinedFeedOrchestrator.js';
6
6
  import { hydrateWorkspaceSyncV3AttachmentAsset } from '../v3/workspaceSyncV3AttachmentAssetHydration.js';
7
+ import { authoritativeV2ApplyFailureMessage, } from './workspaceSyncEngineLocalServices.js';
7
8
  import { WORKSPACE_SYNC_V3_APPLY_NOT_COMMITTED } from './workspaceSyncEngineRemoteServices.js';
8
9
  export function combinedAttachmentAssetHydrationId(input) {
9
10
  if (input.causeCode === 'TASK_ATTACHMENT_ASSET_NOT_READY' && input.causeAssetId) {
@@ -391,6 +392,10 @@ export function createWorkspaceTransferCoordinator({ cloudAuthConfigured, runtim
391
392
  }
392
393
  let applyResult;
393
394
  try {
395
+ const applyOptions = {
396
+ repairMode: replayPayload?.repairMode ?? repairMode,
397
+ excludedProjections: pushResult.effectiveV2ExcludedProjections,
398
+ };
394
399
  const authoritativeChanges = appliedTaskUpserts.map((entry) => ({
395
400
  op: 'upsert',
396
401
  archived: entry.archived === true,
@@ -398,8 +403,8 @@ export function createWorkspaceTransferCoordinator({ cloudAuthConfigured, runtim
398
403
  ...(entry.durableRevision ? { durableRevision: entry.durableRevision } : {}),
399
404
  }));
400
405
  applyResult = completionGroup
401
- ? await localServices.applyV2Batch(currentWorkspaceId, authoritativeChanges, { completionGroup })
402
- : await localServices.applyV2Batch(currentWorkspaceId, authoritativeChanges);
406
+ ? await localServices.applyV2Batch(currentWorkspaceId, authoritativeChanges, { ...applyOptions, completionGroup })
407
+ : await localServices.applyV2Batch(currentWorkspaceId, authoritativeChanges, applyOptions);
403
408
  }
404
409
  catch (error) {
405
410
  if (pushTransferReceipts.length > 0) {
@@ -419,7 +424,7 @@ export function createWorkspaceTransferCoordinator({ cloudAuthConfigured, runtim
419
424
  errorCode: 'WORKSPACE_SYNC_V2_PUSH_AUTHORITATIVE_APPLY_FAILED',
420
425
  });
421
426
  }
422
- throw new Error(`Authoritative V2 push echo apply failed (${applyResult.status || 0}).`);
427
+ throw new Error(authoritativeV2ApplyFailureMessage(applyResult));
423
428
  }
424
429
  for (const entry of appliedTaskUpserts) {
425
430
  const taskId = String(entry.task.id || '').trim();
@@ -279,6 +279,7 @@ export function createWorkspaceSyncV2ChangeDispatcher(dependencies) {
279
279
  workspaceId,
280
280
  incomingInitiatives: applyModel.planning.incomingInitiatives,
281
281
  incomingWorkstreams: applyModel.planning.incomingWorkstreams,
282
+ incomingIdentities: applyModel.planning.incomingIdentities,
282
283
  recordSyncDiagnostic,
283
284
  ...(options.coexistenceDirection ? {
284
285
  coexistenceDirection: options.coexistenceDirection,
@@ -722,6 +723,7 @@ export function createWorkspaceSyncV2ChangeDispatcher(dependencies) {
722
723
  workspaceId,
723
724
  incomingInitiatives: applyModel.planning.incomingInitiatives,
724
725
  incomingWorkstreams: applyModel.planning.incomingWorkstreams,
726
+ incomingIdentities: applyModel.planning.incomingIdentities,
725
727
  recordSyncDiagnostic,
726
728
  ...(options.coexistenceDirection ? {
727
729
  coexistenceDirection: options.coexistenceDirection,
@@ -1,6 +1,6 @@
1
1
  import type { TaskforceCore, TaskforceSyncCapable } from '../core/Taskforce.js';
2
2
  import type { DeletedTaskDetails, DeletedTaskSource, TaskRelationshipRecord } from '../core/Taskforce.js';
3
- import type { WorkspaceSyncAiProfileSnapshot, WorkspaceSyncAgentConversationSnapshot, WorkspaceSyncAgentRoleSnapshot, WorkspaceSyncAnnotatedAttachmentSessionSnapshot, WorkspaceSyncChange, WorkspaceSyncDocumentReviewCommentSnapshot, WorkspaceSyncDocumentReviewSessionSnapshot, WorkspaceSyncDurableTaskRevision, WorkspaceSyncDurableTaxonomyRevision, WorkspaceSyncEntityEventSnapshot, WorkspaceSyncInitiativeSnapshot, WorkspaceSyncTaskforceAgentSnapshot, WorkspaceSyncTaskforceAgentSkillSnapshot, WorkspaceSyncTaskSnapshot, WorkspaceSyncWorkspaceMemberSnapshot, WorkspaceSyncWorkstreamSnapshot } from './workspaceSyncModel.js';
3
+ import type { WorkspaceSyncAiProfileSnapshot, WorkspaceSyncAgentConversationSnapshot, WorkspaceSyncAgentRoleSnapshot, WorkspaceSyncAnnotatedAttachmentSessionSnapshot, WorkspaceSyncChange, WorkspaceSyncDocumentReviewCommentSnapshot, WorkspaceSyncDocumentReviewSessionSnapshot, WorkspaceSyncDurableTaskRevision, WorkspaceSyncDurableTaxonomyRevision, WorkspaceSyncEntityEventSnapshot, WorkspaceSyncInitiativeSnapshot, WorkspaceSyncPlanningIdentitySnapshot, WorkspaceSyncTaskforceAgentSnapshot, WorkspaceSyncTaskforceAgentSkillSnapshot, WorkspaceSyncTaskSnapshot, WorkspaceSyncWorkspaceMemberSnapshot, WorkspaceSyncWorkstreamSnapshot } from './workspaceSyncModel.js';
4
4
  import type { BinaryAssetSyncPayload, DocumentSyncPayload } from './contentSyncPayload.js';
5
5
  import type { WorkspaceTaxonomyState } from '../shared/taxonomyState.js';
6
6
  import { WorkspaceSyncDurabilityStore } from './v3/syncDurabilityStore.js';
@@ -55,6 +55,7 @@ export interface WorkspaceSyncIncomingApplyModel {
55
55
  incomingTaxonomyDurableRevision: WorkspaceSyncDurableTaxonomyRevision | null;
56
56
  incomingInitiatives: Map<string, WorkspaceSyncInitiativeSnapshot>;
57
57
  incomingWorkstreams: Map<string, WorkspaceSyncWorkstreamSnapshot>;
58
+ incomingIdentities: Map<string, WorkspaceSyncPlanningIdentitySnapshot>;
58
59
  };
59
60
  profiles: {
60
61
  incomingAiProfiles: Map<string, WorkspaceSyncAiProfileSnapshot>;
@@ -163,6 +164,7 @@ export declare function applyPlanningSyncChanges(input: {
163
164
  workspaceId: string;
164
165
  incomingInitiatives: Map<string, WorkspaceSyncInitiativeSnapshot>;
165
166
  incomingWorkstreams: Map<string, WorkspaceSyncWorkstreamSnapshot>;
167
+ incomingIdentities?: Map<string, WorkspaceSyncPlanningIdentitySnapshot>;
166
168
  recordSyncDiagnostic: RecordSyncDiagnostic;
167
169
  coexistenceDirection?: TaskMetadataCoexistenceDirection;
168
170
  assertedActiveV3InitiativeIds?: ReadonlySet<string>;
@@ -1,6 +1,7 @@
1
1
  import * as fs from 'fs';
2
2
  import * as path from 'path';
3
3
  import { createHash } from 'crypto';
4
+ import { assertPlanningIdentityColor, assertPlanningIdentityIcon } from '../shared/planningIdentity.js';
4
5
  import { parseAiProfileColorSource } from '../shared/aiProfileColors.js';
5
6
  import { normalizeBinaryAssetDeleteSyncPayload, normalizeBinaryAssetSyncPayload, normalizeDocumentDeleteSyncPayload, normalizeDocumentSyncPayload, } from './contentSyncPayload.js';
6
7
  import { normalizeAiProfileSyncPayload, normalizeAgentConversationSyncPayload, normalizeAgentRoleSyncPayload, normalizeAnnotatedAttachmentSessionSyncPayload, normalizeDeleteSyncPayload, normalizeDocumentReviewCommentSyncPayload, normalizeDocumentReviewSessionSyncPayload, normalizeTaskforceAgentSkillSyncPayload, normalizeTaskforceAgentSyncPayload, } from './collaborationSyncPayload.js';
@@ -32,6 +33,7 @@ function createIncomingApplyModel() {
32
33
  incomingTaxonomyDurableRevision: null,
33
34
  incomingInitiatives: new Map(),
34
35
  incomingWorkstreams: new Map(),
36
+ incomingIdentities: new Map(),
35
37
  },
36
38
  profiles: {
37
39
  incomingAiProfiles: new Map(),
@@ -68,6 +70,7 @@ function shouldSkipTaskClassification(op) {
68
70
  || op === 'task-relationship-delete'
69
71
  || op === 'initiative-upsert'
70
72
  || op === 'workstream-upsert'
73
+ || op === 'planning-identity-upsert'
71
74
  || op === 'document-upsert'
72
75
  || op === 'document-delete'
73
76
  || op === 'asset-upsert'
@@ -185,6 +188,26 @@ export function classifyWorkspaceSyncChanges(input) {
185
188
  model.planning.incomingWorkstreams.set(workstream.id, workstream);
186
189
  continue;
187
190
  }
191
+ if (op === 'planning-identity-upsert') {
192
+ const value = raw.identity;
193
+ const entityType = value?.entityType === 'initiative' || value?.entityType === 'workstream'
194
+ ? value.entityType
195
+ : null;
196
+ const entityId = String(value?.entityId || '').trim();
197
+ const updatedAt = String(value?.updatedAt || raw.updatedAt || raw.watermark || '').trim();
198
+ if (!entityType || !entityId || !Number.isFinite(Date.parse(updatedAt))) {
199
+ throw new Error('Planning identity sync payload is invalid.');
200
+ }
201
+ const identity = {
202
+ entityType,
203
+ entityId,
204
+ icon: assertPlanningIdentityIcon(value?.icon),
205
+ color: assertPlanningIdentityColor(value?.color),
206
+ updatedAt,
207
+ };
208
+ model.planning.incomingIdentities.set(`${entityType}:${entityId}`, identity);
209
+ continue;
210
+ }
188
211
  if (op === 'ai-profile-upsert') {
189
212
  const profile = normalizeAiProfileSyncPayload(raw.profile, workspaceId, normalizeIncomingAiProfileSurfaceType, normalizeIncomingAiProfileSeatScope, 'apply.aiProfileUpsert');
190
213
  const profileId = String(profile?.id || '').trim();
@@ -690,6 +713,12 @@ export function applyPlanningSyncChanges(input) {
690
713
  }
691
714
  }
692
715
  }
716
+ for (const identity of input.incomingIdentities?.values() || []) {
717
+ const applied = core.applyPlanningEntityIdentityForSync(identity, workspaceId);
718
+ if (!applied) {
719
+ throw new Error(`Planning identity parent is missing: ${identity.entityType}:${identity.entityId}`);
720
+ }
721
+ }
693
722
  }
694
723
  export function applyTaxonomySyncChanges(input) {
695
724
  const hasTaxonomy = Boolean(input.incomingTaxonomyState) || Array.isArray(input.incomingTaxonomies);
@@ -77,6 +77,8 @@ export interface WorkspacePushSyncResult {
77
77
  effectiveDeltaDiagnostics?: WorkspaceSyncDeltaDiagnostics & {
78
78
  combinedV3SuppressedChangeCount?: number;
79
79
  };
80
+ /** Exact V3-owned projections excluded while preparing this V2 attempt. */
81
+ effectiveV2ExcludedProjections?: readonly WorkspaceSyncV2ProjectionExclusion[];
80
82
  deleteCount: number;
81
83
  currentTaskIds: Set<string>;
82
84
  currentTaskWatermarks?: Map<string, string>;
@@ -5,7 +5,7 @@ import { createWorkspaceSyncEngineV2PushBoundary, parseWorkspaceSyncEngineApplie
5
5
  import { encryptDocument } from './encryptionService.js';
6
6
  import { decryptWorkspaceSyncContentChangeInPlace } from './workspaceSyncContentDecryption.js';
7
7
  import { decideWorkspaceContentFetch, fingerprintWorkspaceContentBody, } from './workspaceContentManifest.js';
8
- import { workspaceSyncV2ProjectionExclusionsEqual, } from './v3/workspaceSyncV2ProjectionExclusions.js';
8
+ import { normalizeWorkspaceSyncV2ProjectionExclusions, workspaceSyncV2ProjectionExclusionsEqual, } from './v3/workspaceSyncV2ProjectionExclusions.js';
9
9
  import { WORKSPACE_PUSH_PREPARED_PLAN_VERSION, } from './workspacePushPreparedPlan.js';
10
10
  import { canonicalWorkspaceSyncJson } from './v3/canonicalWorkspaceSyncJson.js';
11
11
  function asObjectRecord(value) {
@@ -217,6 +217,7 @@ function workspacePushChangeStableIdentity(change) {
217
217
  case 'task-relationship-delete': return `${change.op}:${change.relationship.id}`;
218
218
  case 'initiative-upsert': return `${change.op}:${change.initiative.id}`;
219
219
  case 'workstream-upsert': return `${change.op}:${change.workstream.id}`;
220
+ case 'planning-identity-upsert': return `${change.op}:${change.identity.entityType}:${change.identity.entityId}`;
220
221
  case 'taxonomy-upsert': return change.op;
221
222
  case 'ai-profile-upsert': return `${change.op}:${change.profile.id}`;
222
223
  case 'document-upsert':
@@ -284,6 +285,8 @@ function resolveWorkspacePushPhase(change) {
284
285
  return 0;
285
286
  case 'workstream-upsert':
286
287
  return 1;
288
+ case 'planning-identity-upsert':
289
+ return 2;
287
290
  case 'upsert':
288
291
  return 2;
289
292
  case 'document-upsert':
@@ -461,6 +464,7 @@ export async function runWorkspacePushSyncService(input) {
461
464
  }
462
465
  const changeCount = preparedChanges.length;
463
466
  const effectiveDeltaDiagnostics = buildEffectiveWorkspacePushDiagnostics(input.payload.deltaDiagnostics, preparedChanges, preparedOwnership);
467
+ const effectiveV2ExcludedProjections = normalizeWorkspaceSyncV2ProjectionExclusions(preparedOwnership.combinedExcludedProjections || []);
464
468
  const deleteCount = input.payload.deleteTaskIds.size;
465
469
  let requestMs = 0;
466
470
  const canElideSteadyStateRequest = changeCount === 0
@@ -475,6 +479,7 @@ export async function runWorkspacePushSyncService(input) {
475
479
  requestMs: 0,
476
480
  changeCount: 0,
477
481
  effectiveDeltaDiagnostics,
482
+ effectiveV2ExcludedProjections,
478
483
  deleteCount,
479
484
  currentTaskIds: input.payload.currentTaskIds,
480
485
  currentTaskWatermarks: input.payload.currentTaskWatermarks ?? new Map(),
@@ -689,6 +694,12 @@ export async function runWorkspacePushSyncService(input) {
689
694
  completedChangeCount += plainBatchChanges.length;
690
695
  continue;
691
696
  }
697
+ if (pushTransferReceipts.length > 0) {
698
+ await remoteServices.retainTransferReceipts?.({
699
+ workspaceId: input.workspaceId,
700
+ receipts: pushTransferReceipts,
701
+ });
702
+ }
692
703
  const sendPush = async () => {
693
704
  const requestStartedAtMs = Date.now();
694
705
  const result = await remoteServices.pushWorkspaceChanges({
@@ -832,6 +843,7 @@ export async function runWorkspacePushSyncService(input) {
832
843
  failureDomain: null,
833
844
  },
834
845
  effectiveDeltaDiagnostics,
846
+ effectiveV2ExcludedProjections,
835
847
  deleteCount,
836
848
  currentTaskIds: input.payload.currentTaskIds,
837
849
  currentTaskWatermarks: input.payload.currentTaskWatermarks ?? new Map(),
@@ -25,6 +25,7 @@ export interface TaskSyncPayload {
25
25
  referenceNumber?: number | null;
26
26
  comments?: Comment[];
27
27
  attachments?: Array<string | AttachmentItem>;
28
+ cardCoverAssetId?: string | null;
28
29
  checklistItems?: ChecklistItem[];
29
30
  }
30
31
  export declare function serializeTaskForSync(task: Partial<TaskItem> | null | undefined): TaskSyncPayload;
@@ -64,6 +64,7 @@ function cloneChecklistItems(value) {
64
64
  }
65
65
  export function serializeTaskForSync(task) {
66
66
  const source = task && typeof task === 'object' ? task : {};
67
+ const hasCardCoverAssetId = Object.prototype.hasOwnProperty.call(source, 'cardCoverAssetId');
67
68
  return {
68
69
  id: String(source.id || '').trim(),
69
70
  title: String(source.title || '').trim(),
@@ -89,6 +90,9 @@ export function serializeTaskForSync(task) {
89
90
  referenceNumber: toOptionalInteger(source.referenceNumber, { min: 1, nullable: true }),
90
91
  comments: cloneComments(source.comments),
91
92
  attachments: cloneAttachments(source.attachments),
93
+ ...(hasCardCoverAssetId
94
+ ? { cardCoverAssetId: toNullableString(source.cardCoverAssetId) }
95
+ : {}),
92
96
  checklistItems: cloneChecklistItems(source.checklistItems),
93
97
  };
94
98
  }
@@ -102,6 +106,7 @@ export function normalizeTaskSyncPayload(raw) {
102
106
  return serializeTaskForSync(source);
103
107
  }
104
108
  export function taskSyncPayloadToCoreTask(task) {
109
+ const hasCardCoverAssetId = Object.prototype.hasOwnProperty.call(task, 'cardCoverAssetId');
105
110
  return {
106
111
  id: task.id,
107
112
  title: task.title,
@@ -127,6 +132,7 @@ export function taskSyncPayloadToCoreTask(task) {
127
132
  referenceNumber: task.referenceNumber ?? undefined,
128
133
  comments: task.comments,
129
134
  attachments: task.attachments,
135
+ ...(hasCardCoverAssetId ? { cardCoverAssetId: task.cardCoverAssetId } : {}),
130
136
  checklistItems: task.checklistItems
131
137
  };
132
138
  }
@@ -3,6 +3,7 @@ import { WORKSPACE_SYNC_V3_COMBINED_CAPABILITY_VERSION, WORKSPACE_SYNC_V3_COMBIN
3
3
  import { WORKSPACE_SYNC_V3_NESTED_COVERAGE_SELECTOR } from './workspaceSyncV3NestedWireContract.js';
4
4
  import { WORKSPACE_SYNC_V3_WORKFLOW_COVERAGE_SELECTOR } from './workspaceSyncV3WorkflowWireContract.js';
5
5
  import { WORKSPACE_SYNC_V3_PLANNING_ORDER_COVERAGE_SELECTOR } from './workspaceSyncV3PlanningOrderWireContract.js';
6
+ import { WORKSPACE_SYNC_V3_TASK_COVER_COVERAGE_SELECTOR } from './workspaceSyncV3TaskCoverWireContract.js';
6
7
  export { WORKSPACE_SYNC_V3_COMBINED_CAPABILITY_VERSION } from './workspaceSyncV3CombinedWireContract.js';
7
8
  export function resolveRequestedCombinedFeedCoverage(env = process.env) {
8
9
  const requestedVersion = String(env.TASKFORCE_SYNC_V3_COMBINED_FEED_COVERAGE_VERSION || '').trim();
@@ -18,6 +19,9 @@ export function resolveRequestedCombinedFeedCoverage(env = process.env) {
18
19
  if (requestedVersion === String(WORKSPACE_SYNC_V3_PLANNING_ORDER_COVERAGE_SELECTOR.coverageVersion)) {
19
20
  return WORKSPACE_SYNC_V3_PLANNING_ORDER_COVERAGE_SELECTOR;
20
21
  }
22
+ if (requestedVersion === String(WORKSPACE_SYNC_V3_TASK_COVER_COVERAGE_SELECTOR.coverageVersion)) {
23
+ return WORKSPACE_SYNC_V3_TASK_COVER_COVERAGE_SELECTOR;
24
+ }
21
25
  throw new Error(`Unsupported TASKFORCE_SYNC_V3_COMBINED_FEED_COVERAGE_VERSION: ${requestedVersion}.`);
22
26
  }
23
27
  export function resolveCombinedFeedCapability(input) {
@@ -12,6 +12,7 @@ export declare function resolveTaskAttachmentLinksMutationCapability(input: {
12
12
  export type DurableTaskAttachmentLinksMutationRouterCore = DurableTaskAttachmentLinksServiceCore & LocalTaskAttachmentLinksOutboxCore & {
13
13
  getDatabaseAdapter(): DatabaseAdapter;
14
14
  getTask(id: string, workspaceId?: string): TaskItem | null;
15
+ assertTaskDetailRevisionForUpdate(id: string, expected: string, workspaceId?: string): void;
15
16
  };
16
17
  export declare class DurableTaskAttachmentLinksRouterDisabledError extends Error {
17
18
  readonly code = "WORKSPACE_SYNC_V3_TASK_ATTACHMENT_LINKS_ROUTER_DISABLED";
@@ -40,6 +41,8 @@ export declare function createDurableTaskAttachmentLinksMutationRouter(input: {
40
41
  replace(args: {
41
42
  taskId: string;
42
43
  links: readonly WorkspaceSyncV3TaskAttachmentLink[];
44
+ cardCoverAssetId?: string | null;
45
+ expectedDetailRevision?: string;
43
46
  }): {
44
47
  state: "pending" | "committed";
45
48
  route: "local-outbox" | "cloud-acceptance";
@@ -4,6 +4,7 @@ import { enqueueLocalTaskAttachmentLinksMutation, } from './localTaskAttachmentL
4
4
  import { DurableTaskAttachmentLinksMutationError, runDurableTaskAttachmentLinksReplace, } from './taskAttachmentLinksMutationService.js';
5
5
  import { WorkspaceSyncDurabilityStore, WorkspaceSyncEntityBusyError } from './syncDurabilityStore.js';
6
6
  import { serializeWorkspaceSyncV3TaskAttachmentLinksPayload, } from './workspaceSyncV3NestedTaskCodecs.js';
7
+ import { resolveTaskCardCoverAssetIdForLinks } from '../../core/TaskAttachmentLinksDurableMutationService.js';
7
8
  const OPERATION_LEASE_MS = 30_000;
8
9
  function enabled(value) {
9
10
  return /^(1|true|on|yes)$/i.test(String(value || '').trim());
@@ -93,6 +94,22 @@ export function createDurableTaskAttachmentLinksMutationRouter(input) {
93
94
  catch (error) {
94
95
  throw new DurableTaskAttachmentLinksMutationError(error instanceof Error ? error.message : 'Task attachment links are invalid.', 'TASK_ATTACHMENT_LINKS_INVALID', 400);
95
96
  }
97
+ const currentTask = input.core.getTask(taskId, workspaceId);
98
+ if (!currentTask)
99
+ throw new DurableTaskAttachmentLinksMutationError('Task not found.', 'TASK_NOT_FOUND', 404);
100
+ let cardCoverAssetId;
101
+ try {
102
+ cardCoverAssetId = resolveTaskCardCoverAssetIdForLinks({
103
+ currentCardCoverAssetId: currentTask.cardCoverAssetId,
104
+ ...(Object.prototype.hasOwnProperty.call(args, 'cardCoverAssetId')
105
+ ? { requestedCardCoverAssetId: args.cardCoverAssetId }
106
+ : {}),
107
+ links,
108
+ });
109
+ }
110
+ catch (error) {
111
+ throw new DurableTaskAttachmentLinksMutationError(error instanceof Error ? error.message : 'Task card cover is invalid.', 'TASK_ATTACHMENT_LINKS_INVALID', Number(error?.statusCode) || 400);
112
+ }
96
113
  const acceptedAt = now();
97
114
  const acceptedAtIso = acceptedAt.toISOString();
98
115
  const operationId = operationIdRequired(input.operationId);
@@ -123,7 +140,14 @@ export function createDurableTaskAttachmentLinksMutationRouter(input) {
123
140
  catch {
124
141
  throw new DurableTaskAttachmentLinksMutationError('Captured task attachment-link payload is invalid.', 'TASK_ATTACHMENT_LINKS_IDENTITY_CONFLICT', 409);
125
142
  }
126
- if (canonicalWorkspaceSyncJson(frozen) !== canonicalWorkspaceSyncJson(links)) {
143
+ const relationshipIntent = (entries) => entries.map((link) => ({
144
+ assetId: link.assetId,
145
+ role: link.role,
146
+ order: link.order,
147
+ }));
148
+ if (canonicalWorkspaceSyncJson(relationshipIntent(frozen))
149
+ !== canonicalWorkspaceSyncJson(relationshipIntent(links))
150
+ || String(payload.cardCoverAssetId || '') !== String(cardCoverAssetId || '')) {
127
151
  throw new DurableTaskAttachmentLinksMutationError('Operation identity is assigned to different task attachment links.', 'TASK_ATTACHMENT_LINKS_IDENTITY_CONFLICT', 409);
128
152
  }
129
153
  const task = input.core.getTask(taskId, workspaceId);
@@ -138,7 +162,7 @@ export function createDurableTaskAttachmentLinksMutationRouter(input) {
138
162
  let result;
139
163
  try {
140
164
  result = enqueueLocalTaskAttachmentLinksMutation({
141
- store, core: serviceCore, identity, taskId, links, now: acceptedAtIso,
165
+ store, core: serviceCore, identity, taskId, links, cardCoverAssetId, now: acceptedAtIso,
142
166
  actorRef, onPostCommitError: input.onPostCommitError,
143
167
  requireV3CombinedOwnership: persistedOwnershipChecked,
144
168
  });
@@ -182,10 +206,14 @@ export function createDurableTaskAttachmentLinksMutationRouter(input) {
182
206
  });
183
207
  }
184
208
  const result = runDurableTaskAttachmentLinksReplace({
185
- store, core: serviceCore, tenantId, workspaceId, clientId, operationId, taskId, links,
209
+ store, core: serviceCore, tenantId, workspaceId, clientId, operationId, taskId, links, cardCoverAssetId,
186
210
  baseEntityRevision: coordinates.entityRevision, baseLifecycleRevision: coordinates.lifecycleRevision,
187
211
  now: acceptedAtIso, leaseExpiresAt: new Date(acceptedAt.getTime() + OPERATION_LEASE_MS).toISOString(),
188
212
  actorRef, onPostCommitError: input.onPostCommitError,
213
+ expectedDetailRevision: args.expectedDetailRevision,
214
+ assertPrecondition: args.expectedDetailRevision
215
+ ? () => input.core.assertTaskDetailRevisionForUpdate(taskId, args.expectedDetailRevision, workspaceId)
216
+ : undefined,
189
217
  });
190
218
  if (result.state === 'in_progress')
191
219
  throw new DurableTaskAttachmentLinksRouterInProgressError(result.retryAt);
@@ -11,6 +11,7 @@ export declare function resolveTaskChecklistMutationCapability(input: {
11
11
  export type DurableTaskChecklistMutationRouterCore = DurableTaskChecklistServiceCore & LocalTaskChecklistOutboxCore & {
12
12
  getDatabaseAdapter(): DatabaseAdapter;
13
13
  getTask(id: string, workspaceId?: string): TaskItem | null;
14
+ assertTaskDetailRevisionForUpdate(id: string, expected: string, workspaceId?: string): void;
14
15
  };
15
16
  export declare class DurableTaskChecklistRouterDisabledError extends Error {
16
17
  readonly code = "WORKSPACE_SYNC_V3_TASK_CHECKLIST_ROUTER_DISABLED";
@@ -38,6 +39,7 @@ export declare function createDurableTaskChecklistMutationRouter(input: {
38
39
  replace(args: {
39
40
  taskId: string;
40
41
  items: readonly Partial<ChecklistItem>[];
42
+ expectedDetailRevision?: string;
41
43
  }): {
42
44
  state: "pending" | "committed";
43
45
  route: "local-outbox" | "cloud-acceptance";
@@ -170,6 +170,10 @@ export function createDurableTaskChecklistMutationRouter(input) {
170
170
  baseEntityRevision: coordinates.entityRevision, baseLifecycleRevision: coordinates.lifecycleRevision,
171
171
  now: acceptedAtIso, leaseExpiresAt: new Date(acceptedAt.getTime() + OPERATION_LEASE_MS).toISOString(),
172
172
  actorRef, onPostCommitError: input.onPostCommitError,
173
+ expectedDetailRevision: args.expectedDetailRevision,
174
+ assertPrecondition: args.expectedDetailRevision
175
+ ? () => input.core.assertTaskDetailRevisionForUpdate(taskId, args.expectedDetailRevision, workspaceId)
176
+ : undefined,
173
177
  });
174
178
  if (result.state === 'in_progress')
175
179
  throw new DurableTaskChecklistRouterInProgressError(result.retryAt);
@@ -51,6 +51,7 @@ export declare function createDurableTaskHttpBulkMutationRouter(input: {
51
51
  }>, options?: {
52
52
  saveSource?: "manual" | "autosave";
53
53
  atomicItemFailures?: boolean;
54
+ expectedDetailRevision?: string;
54
55
  }): {
55
56
  preview: import("../../core/Taskforce.js").BulkUpdateFieldsPreview;
56
57
  results: TaskItem[];
@@ -222,7 +222,12 @@ export function createDurableTaskHttpBulkMutationRouter(input) {
222
222
  }, { atomicRecovery: true });
223
223
  },
224
224
  updateFields(updates, options = {}) {
225
- return input.rootRouter.runBatch('bulk-update-fields', { updates }, (batch) => {
225
+ return input.rootRouter.runBatch('bulk-update-fields', {
226
+ updates,
227
+ ...(options.expectedDetailRevision
228
+ ? { expectedDetailRevision: options.expectedDetailRevision }
229
+ : {}),
230
+ }, (batch) => {
226
231
  const preview = input.core.bulkUpdateFieldsPreview(updates, input.workspaceId);
227
232
  const results = [];
228
233
  const errors = preview.skipped
@@ -245,15 +250,22 @@ export function createDurableTaskHttpBulkMutationRouter(input) {
245
250
  if (hasAttachments && !Array.isArray(item.fields.attachments)) {
246
251
  throw new TaskforceRuleError('attachments must be an array.', 400, 'TASK_ATTACHMENT_LINKS_INVALID');
247
252
  }
248
- const attachmentOperationId = hasAttachments
253
+ const hasCardCover = Object.prototype.hasOwnProperty.call(item.fields, 'cardCoverAssetId');
254
+ if (hasCardCover && item.fields.cardCoverAssetId !== null
255
+ && (typeof item.fields.cardCoverAssetId !== 'string' || !item.fields.cardCoverAssetId.trim())) {
256
+ throw new TaskforceRuleError('cardCoverAssetId must be a non-empty string or null.', 400, 'TASK_CARD_COVER_INVALID');
257
+ }
258
+ const attachmentOperationId = hasAttachments || hasCardCover
249
259
  ? input.deriveChildOperationId('bulk-update-fields-attachments', item.index, item.id)
250
260
  : '';
251
- const attachmentLinks = hasAttachments
261
+ const attachmentLinks = hasAttachments || hasCardCover
252
262
  ? input.createAttachmentLinksRouter(attachmentOperationId)
253
263
  : null;
254
264
  const durableAttachmentLinks = attachmentLinks?.enabled === true;
255
265
  const normalizedAttachmentLinks = durableAttachmentLinks
256
- ? normalizeAttachmentLinks(item.fields.attachments)
266
+ ? normalizeAttachmentLinks(hasAttachments
267
+ ? item.fields.attachments
268
+ : input.core.getTask(item.id, input.workspaceId)?.attachments || [])
257
269
  : [];
258
270
  const checklistOperationId = hasChecklist
259
271
  ? input.deriveChildOperationId('bulk-update-fields-checklist', item.index, item.id)
@@ -262,17 +274,25 @@ export function createDurableTaskHttpBulkMutationRouter(input) {
262
274
  const durableChecklist = checklist?.enabled === true;
263
275
  const rootFields = durableChecklist || durableAttachmentLinks
264
276
  ? Object.fromEntries(Object.entries(item.fields).filter(([key]) => (!(durableChecklist && key === 'checklistItems')
265
- && !(durableAttachmentLinks && key === 'attachments'))))
277
+ && !(durableAttachmentLinks && key === 'attachments')
278
+ && !(durableAttachmentLinks && key === 'cardCoverAssetId'))))
266
279
  : item.fields;
267
280
  let updated = input.core.getTask(item.id, input.workspaceId);
281
+ let expectedDetailRevision = options.expectedDetailRevision;
268
282
  if (Object.keys(rootFields).length > 0) {
269
283
  const child = input.createChildRouter(input.deriveChildOperationId('bulk-update-fields-root', item.index, item.id), () => { });
270
284
  updated = child.enabled
271
- ? batch.runChild(() => child.update(item.id, rootFields, options.saveSource || 'manual'))
272
- : input.core.updateTask(item.id, rootFields, input.workspaceId, {
273
- actorRef: 'user',
274
- saveSource: options.saveSource || 'manual',
275
- });
285
+ ? batch.runChild(() => child.update(item.id, rootFields, options.saveSource || 'manual', undefined, expectedDetailRevision))
286
+ : (() => {
287
+ if (expectedDetailRevision) {
288
+ input.core.assertTaskDetailRevisionForUpdate(item.id, expectedDetailRevision, input.workspaceId);
289
+ }
290
+ return input.core.updateTask(item.id, rootFields, input.workspaceId, {
291
+ actorRef: 'user',
292
+ saveSource: options.saveSource || 'manual',
293
+ });
294
+ })();
295
+ expectedDetailRevision = undefined;
276
296
  }
277
297
  if (durableChecklist && checklist) {
278
298
  const currentTask = input.core.getTask(item.id, input.workspaceId) || updated;
@@ -293,13 +313,25 @@ export function createDurableTaskHttpBulkMutationRouter(input) {
293
313
  updatedAt: String(unchanged ? existing.updatedAt : existing ? now : source.updatedAt || createdAt),
294
314
  };
295
315
  });
296
- updated = batch.runChild(() => checklist.replace({ taskId: item.id, items: normalizedChecklist }).task);
316
+ updated = batch.runChild(() => checklist.replace({
317
+ taskId: item.id,
318
+ items: normalizedChecklist,
319
+ expectedDetailRevision,
320
+ }).task);
321
+ expectedDetailRevision = undefined;
297
322
  }
298
323
  if (durableAttachmentLinks && attachmentLinks) {
299
324
  updated = batch.runChild(() => attachmentLinks.replace({
300
325
  taskId: item.id,
301
326
  links: normalizedAttachmentLinks,
327
+ ...(hasCardCover ? {
328
+ cardCoverAssetId: item.fields.cardCoverAssetId === null
329
+ ? null
330
+ : String(item.fields.cardCoverAssetId).trim(),
331
+ } : {}),
332
+ expectedDetailRevision,
302
333
  }).task);
334
+ expectedDetailRevision = undefined;
303
335
  }
304
336
  if (updated)
305
337
  results.push(updated);
@@ -314,7 +346,10 @@ export function createDurableTaskHttpBulkMutationRouter(input) {
314
346
  }
315
347
  batch.deferPostCommitNotification(() => input.core.notifyDurableTaskBatchCommitted(input.workspaceId, results.map((task) => task.id)));
316
348
  return { preview, results, errors };
317
- }, { atomicRecovery: true, allowIndependentNestedOwnership: true });
349
+ }, {
350
+ atomicRecovery: true,
351
+ allowIndependentNestedOwnership: true,
352
+ });
318
353
  },
319
354
  };
320
355
  }
@@ -3,7 +3,8 @@ import type { TaskRestoreDestination } from '../../shared/taskRestoreDestination
3
3
  export declare class DurableTaskHttpRootMutationError extends Error {
4
4
  readonly code: string;
5
5
  readonly statusCode: number;
6
- constructor(message: string, code: string, statusCode: number);
6
+ readonly details?: Record<string, unknown> | undefined;
7
+ constructor(message: string, code: string, statusCode: number, details?: Record<string, unknown> | undefined);
7
8
  }
8
9
  export declare function resolveTaskHttpRootMutationCapability(input: {
9
10
  runtimeMode: 'local' | 'cloud';
@@ -22,8 +23,9 @@ export declare function createDurableTaskHttpRootMutationRouter(input: {
22
23
  deferPostCommitNotification?: (notify: () => void) => void;
23
24
  }): {
24
25
  enabled: boolean;
26
+ hasCommittedOperation(): boolean;
25
27
  create(candidate: unknown): TaskItem;
26
- update(taskIdInput: string, candidate: unknown, saveSource: "manual" | "autosave", activityAction?: "task-updated" | "task-schedule-changed"): TaskItem;
28
+ update(taskIdInput: string, candidate: unknown, saveSource: "manual" | "autosave", activityAction?: "task-updated" | "task-schedule-changed", expectedDetailRevision?: string): TaskItem;
27
29
  runBatch<T>(routeInput: string, request: unknown, apply: (context: {
28
30
  runChild<R>(mutation: () => R): R;
29
31
  deferPostCommitNotification(notify: () => void): void;
@@ -36,5 +38,5 @@ export declare function createDurableTaskHttpRootMutationRouter(input: {
36
38
  restore(deletedRecordIdInput: string, restoreDestination?: TaskRestoreDestination): TaskItem;
37
39
  delete(taskIdInput: string): DeletedTaskRecord;
38
40
  };
39
- type TaskforceCoreForHttpRootMutation = Pick<import('../../core/Taskforce.js').TaskforceCore, 'getDatabaseAdapter' | 'getTask' | 'listAssignableActors' | 'getDeletedTask' | 'updateTask' | 'hasTaskDeletionMarkerForSync' | 'createTask' | 'listTaskAttachmentLinksForDurableSync' | 'resolveTaskAttachmentLinksForDurableSync' | 'normalizeTaskAttachmentDescriptorsForDurableSync' | 'notifyDurableTaskCreateCommitted' | 'notifyDurableTaskBatchCommitted' | 'notifyDurableTaskMetadataCommitted' | 'notifyDurableTaskLifecycleCommitted' | 'notifyDurableTaskDeleteCommitted' | 'getTaskEventForSync' | 'getEntityEventForSync' | 'lockTaskLifecycleMutationDomain' | 'archiveTask' | 'unarchiveTask' | 'restoreDeletedTask' | 'addTaskStatusEventsForDurableSync' | 'lockTaskRelationshipMutationDomain' | 'listTaskRelationships' | 'getTaskRelationshipForSync' | 'deleteTaskForSync'>;
41
+ type TaskforceCoreForHttpRootMutation = Pick<import('../../core/Taskforce.js').TaskforceCore, 'getDatabaseAdapter' | 'getTask' | 'getTaskDetailRevision' | 'assertTaskDetailRevisionForUpdate' | 'listAssignableActors' | 'getDeletedTask' | 'updateTask' | 'hasTaskDeletionMarkerForSync' | 'createTask' | 'listTaskAttachmentLinksForDurableSync' | 'resolveTaskAttachmentLinksForDurableSync' | 'normalizeTaskAttachmentDescriptorsForDurableSync' | 'notifyDurableTaskCreateCommitted' | 'notifyDurableTaskBatchCommitted' | 'notifyDurableTaskMetadataCommitted' | 'notifyDurableTaskLifecycleCommitted' | 'notifyDurableTaskDeleteCommitted' | 'getTaskEventForSync' | 'getEntityEventForSync' | 'lockTaskLifecycleMutationDomain' | 'archiveTask' | 'unarchiveTask' | 'restoreDeletedTask' | 'addTaskStatusEventsForDurableSync' | 'lockTaskRelationshipMutationDomain' | 'listTaskRelationships' | 'getTaskRelationshipForSync' | 'deleteTaskForSync'>;
40
42
  export {};