@taskforcehq/taskforce 0.3.328 → 0.3.330

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 (485) hide show
  1. package/dist/Taskforce.module.css +523 -79
  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/features/AiProfilesModule.js +3 -5
  8. package/dist/components/features/AnnotatedAttachmentWorkspace.js +24 -8
  9. package/dist/components/features/TaskSettings.d.ts +12 -1
  10. package/dist/components/features/TaskSettings.js +217 -54
  11. package/dist/components/features/TaskforceAgentsModule.d.ts +1 -2
  12. package/dist/components/features/TaskforceAgentsModule.js +586 -116
  13. package/dist/components/features/agentCapabilities/AgentCapabilitiesPrototype.d.ts +1 -1
  14. package/dist/components/features/agentConnections/AgentConnectionControl.d.ts +15 -0
  15. package/dist/components/features/agentConnections/AgentConnectionControl.js +125 -0
  16. package/dist/components/features/agentConnections/ModelConnectionsPanel.d.ts +18 -0
  17. package/dist/components/features/agentConnections/ModelConnectionsPanel.js +393 -0
  18. package/dist/components/features/agentConnections/modelConnectionsApi.d.ts +65 -0
  19. package/dist/components/features/agentConnections/modelConnectionsApi.js +129 -0
  20. package/dist/components/features/planning/PlanningModule.js +2 -5
  21. package/dist/components/features/planning/PlanningTaskOrderList.d.ts +1 -1
  22. package/dist/components/features/planning/PlanningTaskOrderList.js +17 -6
  23. package/dist/components/features/planning/planningTaskArrangement.d.ts +1 -0
  24. package/dist/components/features/planning/planningTaskArrangement.js +5 -5
  25. package/dist/components/features/taskforceAgentAssignments/AgentBehaviorAssignments.js +15 -24
  26. package/dist/components/features/taskforceAgentEditorModel.d.ts +2 -1
  27. package/dist/components/features/taskforceAgentEditorModel.js +5 -1
  28. package/dist/components/features/workflowManager/workflowManagerApi.d.ts +1 -1
  29. package/dist/components/features/workflowManager/workflowManagerApi.js +3 -0
  30. package/dist/components/task/TaskCard.d.ts +5 -0
  31. package/dist/components/task/TaskCard.js +65 -10
  32. package/dist/components/task/TaskImageReviews.js +14 -5
  33. package/dist/components/task/TaskKanban.d.ts +6 -1
  34. package/dist/components/task/TaskKanban.js +152 -6
  35. package/dist/components/task/TaskList.d.ts +5 -0
  36. package/dist/components/task/TaskList.js +3 -3
  37. package/dist/components/task/TaskWorkflowAssignmentField.js +68 -10
  38. package/dist/components/ui/PasswordInput.d.ts +6 -0
  39. package/dist/components/ui/PasswordInput.js +11 -0
  40. package/dist/components/ui/TopNoticeLayer.js +1 -1
  41. package/dist/components/views/AppShellHeader.js +32 -11
  42. package/dist/components/views/PlanComparisonPage.js +12 -0
  43. package/dist/components/views/StandaloneLayout.js +32 -55
  44. package/dist/components/views/WidgetView.js +3 -3
  45. package/dist/components/views/panels/PlanningDrawer.js +5 -12
  46. package/dist/components/views/standalone/modals/AccountSettingsModal.js +26 -17
  47. package/dist/components/views/standalone/modals/SyncStatusModal.d.ts +4 -3
  48. package/dist/components/views/standalone/modals/SyncStatusModal.js +33 -38
  49. package/dist/config/envSchema.js +60 -1
  50. package/dist/config/localServiceRuntimeContract.d.ts +13 -0
  51. package/dist/config/localServiceRuntimeContract.js +135 -0
  52. package/dist/core/AiProfileService.js +46 -8
  53. package/dist/core/DeletedTaskLifecycleService.d.ts +1 -0
  54. package/dist/core/DeletedTaskLifecycleService.js +37 -6
  55. package/dist/core/McpTokenService.d.ts +23 -1
  56. package/dist/core/McpTokenService.js +93 -10
  57. package/dist/core/TaskAttachmentLinksDurableMutationService.d.ts +3 -2
  58. package/dist/core/TaskAttachmentLinksDurableMutationService.js +33 -9
  59. package/dist/core/TaskChecklistCommandService.d.ts +27 -0
  60. package/dist/core/TaskChecklistCommandService.js +83 -5
  61. package/dist/core/TaskLifecycleCommandService.d.ts +3 -1
  62. package/dist/core/TaskLifecycleCommandService.js +6 -2
  63. package/dist/core/Taskforce.d.ts +94 -2
  64. package/dist/core/Taskforce.js +760 -36
  65. package/dist/core/types.d.ts +14 -0
  66. package/dist/documentReviews/commandService.d.ts +2 -1
  67. package/dist/documentReviews/commandService.js +6 -3
  68. package/dist/hooks/sync/orchestratorShared.d.ts +1 -0
  69. package/dist/hooks/sync/orchestratorShared.js +2 -0
  70. package/dist/hooks/sync/useDurableLocalOutboxDrain.d.ts +1 -1
  71. package/dist/hooks/sync/useDurableTaskCreateMutation.js +1 -1
  72. package/dist/hooks/sync/useDurableTaskMetadataMutation.d.ts +1 -0
  73. package/dist/hooks/sync/useDurableTaskMetadataMutation.js +1 -0
  74. package/dist/hooks/sync/useDurableTaskStatusMutation.d.ts +1 -0
  75. package/dist/hooks/sync/useLocalSyncCoordinatorSnapshot.d.ts +3 -0
  76. package/dist/hooks/sync/useLocalSyncCoordinatorSnapshot.js +85 -9
  77. package/dist/hooks/sync/useSyncStatusControls.d.ts +4 -1
  78. package/dist/hooks/sync/useSyncStatusControls.js +47 -11
  79. package/dist/hooks/tasks/taskHttpMutation.js +1 -0
  80. package/dist/hooks/tasks/useCloudTaskSearch.d.ts +12 -0
  81. package/dist/hooks/tasks/useCloudTaskSearch.js +71 -0
  82. package/dist/hooks/tasks/useTaskDescriptionImageDraftRecovery.d.ts +16 -0
  83. package/dist/hooks/tasks/useTaskDescriptionImageDraftRecovery.js +197 -0
  84. package/dist/hooks/tasks/useTaskEditorNavigation.d.ts +16 -3
  85. package/dist/hooks/tasks/useTaskEditorNavigation.js +72 -13
  86. package/dist/hooks/tasks/useTaskFormActions.d.ts +6 -0
  87. package/dist/hooks/tasks/useTaskFormActions.js +65 -12
  88. package/dist/hooks/ui/useSettingsModel.d.ts +24 -2
  89. package/dist/hooks/ui/useSettingsModel.js +13 -2
  90. package/dist/hooks/ui/useSettingsPersistence.d.ts +12 -1
  91. package/dist/hooks/ui/useSettingsPersistence.js +74 -47
  92. package/dist/hooks/useFilterSort.d.ts +7 -3
  93. package/dist/hooks/useFilterSort.js +15 -5
  94. package/dist/hooks/useSyncOrchestrator.d.ts +3 -0
  95. package/dist/hooks/useSyncOrchestrator.js +111 -2
  96. package/dist/hooks/useTaskData.d.ts +40 -1
  97. package/dist/hooks/useTaskData.js +240 -9
  98. package/dist/hooks/useTaskMutations.d.ts +12 -2
  99. package/dist/hooks/useTaskMutations.js +266 -52
  100. package/dist/hooks/useTaskforce.d.ts +39 -9
  101. package/dist/hooks/useTaskforce.js +359 -40
  102. package/dist/hooks/useUiNotice.d.ts +4 -0
  103. package/dist/hooks/useUiNotice.js +4 -0
  104. package/dist/mcp/adminWorkspaceRegistrar.js +3 -3
  105. package/dist/mcp/clientRegistry.d.ts +2 -2
  106. package/dist/mcp/clientRegistry.js +1 -1
  107. package/dist/mcp/documentAssetRegistrar.js +53 -41
  108. package/dist/mcp/documentHelpers.d.ts +1 -0
  109. package/dist/mcp/documentHelpers.js +7 -3
  110. package/dist/mcp/durableTaskMutationRouter.d.ts +4 -1
  111. package/dist/mcp/durableTaskMutationRouter.js +10 -0
  112. package/dist/mcp/durableTaskRelationshipMutationRouter.js +4 -0
  113. package/dist/mcp/httpProtocolRouting.d.ts +10 -0
  114. package/dist/mcp/httpProtocolRouting.js +19 -0
  115. package/dist/mcp/localCliHealth.d.ts +2 -2
  116. package/dist/mcp/localCliHealth.js +2 -2
  117. package/dist/mcp/localServiceProxy.d.ts +1 -0
  118. package/dist/mcp/localServiceProxy.js +530 -68
  119. package/dist/mcp/planningAttachmentCommandAdapter.d.ts +3 -1
  120. package/dist/mcp/planningAttachmentCommandAdapter.js +20 -2
  121. package/dist/mcp/runtime.d.ts +54 -79
  122. package/dist/mcp/runtime.js +556 -139
  123. package/dist/mcp/taskPlanningRegistrar.js +64 -42
  124. package/dist/mcp/toolCallCompatibility.js +38 -1
  125. package/dist/mcp/toolCatalog.d.ts +1 -0
  126. package/dist/mcp/toolProfiles.d.ts +2 -0
  127. package/dist/mcp/toolProfiles.js +10 -0
  128. package/dist/mcp/toolRegistry.d.ts +1 -0
  129. package/dist/mcp/toolRegistry.js +1 -0
  130. package/dist/mcp/workflowExecutionRegistrar.js +4 -4
  131. package/dist/migrations/taskSchemaMigrations.d.ts +5 -0
  132. package/dist/migrations/taskSchemaMigrations.js +427 -0
  133. package/dist/runtime/appGateDefinitions.d.ts +30 -6
  134. package/dist/runtime/appGateDefinitions.js +6 -6
  135. package/dist/runtime/appGates.d.ts +13 -13
  136. package/dist/runtime/appGates.js +36 -13
  137. package/dist/runtime/nodeAppGates.d.ts +8 -0
  138. package/dist/runtime/nodeAppGates.js +27 -0
  139. package/dist/server/cloudCollectionRead.d.ts +1 -1
  140. package/dist/server/cloudCollectionRead.js +2 -2
  141. package/dist/server/index.d.ts +6 -0
  142. package/dist/server/index.js +123 -14
  143. package/dist/server/localDatabaseIdentity.js +4 -1
  144. package/dist/server/localServiceLease.d.ts +3 -0
  145. package/dist/server/localServiceLease.js +11 -2
  146. package/dist/server/localServiceSessions.d.ts +14 -17
  147. package/dist/server/localServiceSessions.js +308 -94
  148. package/dist/server/localWorkspaceSyncServerRuntime.js +12 -7
  149. package/dist/server/rateLimit.d.ts +1 -0
  150. package/dist/server/rateLimit.js +4 -0
  151. package/dist/server/realtimeSyncWs.js +36 -12
  152. package/dist/server/routes/admin.d.ts +4 -0
  153. package/dist/server/routes/admin.js +113 -3
  154. package/dist/server/routes/agentRoles.js +3 -2
  155. package/dist/server/routes/agentSkills.js +3 -2
  156. package/dist/server/routes/agents.d.ts +7 -0
  157. package/dist/server/routes/agents.js +394 -39
  158. package/dist/server/routes/annotatedAttachments.js +3 -2
  159. package/dist/server/routes/auth.js +3 -1
  160. package/dist/server/routes/billing.js +5 -1
  161. package/dist/server/routes/durableTaskHttpRouters.d.ts +11 -2
  162. package/dist/server/routes/executorPhaseAApprovals.d.ts +19 -0
  163. package/dist/server/routes/executorPhaseAApprovals.js +140 -0
  164. package/dist/server/routes/executorPhaseAIssuerRedemptions.d.ts +11 -0
  165. package/dist/server/routes/executorPhaseAIssuerRedemptions.js +24 -0
  166. package/dist/server/routes/githubReviewEvidence.d.ts +19 -0
  167. package/dist/server/routes/githubReviewEvidence.js +116 -0
  168. package/dist/server/routes/localService.d.ts +15 -4
  169. package/dist/server/routes/localService.js +138 -40
  170. package/dist/server/routes/modelConnections.d.ts +24 -0
  171. package/dist/server/routes/modelConnections.js +205 -0
  172. package/dist/server/routes/primitives.d.ts +2 -0
  173. package/dist/server/routes/shared.d.ts +19 -0
  174. package/dist/server/routes/shared.js +95 -19
  175. package/dist/server/routes/sync.js +1 -0
  176. package/dist/server/routes/syncAuxRoutes.js +9 -2
  177. package/dist/server/routes/syncPullApplyRoutes.js +23 -4
  178. package/dist/server/routes/syncPushRoutes.d.ts +1 -0
  179. package/dist/server/routes/syncPushRoutes.js +1 -0
  180. package/dist/server/routes/syncV3FeedRoutes.js +27 -16
  181. package/dist/server/routes/syncV3LocalCaptureRoutes.js +28 -2
  182. package/dist/server/routes/syncV3LocalFeedApplyRoutes.d.ts +1 -0
  183. package/dist/server/routes/syncV3LocalFeedApplyRoutes.js +26 -0
  184. package/dist/server/routes/syncV3OperationRoutes.js +45 -9
  185. package/dist/server/routes/tasks.js +124 -13
  186. package/dist/server/routes/workflows.js +9 -1
  187. package/dist/server/routes/workspaces.js +43 -1
  188. package/dist/server/routes.js +59 -0
  189. package/dist/server/workspaceDeletionAdmission.d.ts +23 -0
  190. package/dist/server/workspaceDeletionAdmission.js +50 -0
  191. package/dist/service/localServiceCli.js +16 -0
  192. package/dist/service/localServiceClientLifecycle.js +36 -10
  193. package/dist/services/codexAppServerModelGateway.d.ts +161 -0
  194. package/dist/services/codexAppServerModelGateway.js +663 -0
  195. package/dist/services/codexDeviceCodeLoginManager.d.ts +39 -0
  196. package/dist/services/codexDeviceCodeLoginManager.js +265 -0
  197. package/dist/services/codexModelProviderConnectionLifecycle.d.ts +8 -0
  198. package/dist/services/codexModelProviderConnectionLifecycle.js +73 -0
  199. package/dist/services/executorPhaseAApprovalRuntime.d.ts +14 -0
  200. package/dist/services/executorPhaseAApprovalRuntime.js +24 -0
  201. package/dist/services/executorPhaseAApprovalService.d.ts +40 -0
  202. package/dist/services/executorPhaseAApprovalService.js +609 -0
  203. package/dist/services/executorPhaseADriftEvaluator.d.ts +78 -0
  204. package/dist/services/executorPhaseADriftEvaluator.js +93 -0
  205. package/dist/services/executorPhaseAIssuerCore.d.ts +126 -0
  206. package/dist/services/executorPhaseAIssuerCore.js +295 -0
  207. package/dist/services/executorPhaseAIssuerRedemptionService.d.ts +34 -0
  208. package/dist/services/executorPhaseAIssuerRedemptionService.js +158 -0
  209. package/dist/services/githubReviewEvidenceRuntime.d.ts +14 -0
  210. package/dist/services/githubReviewEvidenceRuntime.js +30 -0
  211. package/dist/services/githubReviewEvidenceService.d.ts +93 -0
  212. package/dist/services/githubReviewEvidenceService.js +336 -0
  213. package/dist/services/modelGateway.d.ts +7 -0
  214. package/dist/services/modelProviderConnectionService.d.ts +71 -0
  215. package/dist/services/modelProviderConnectionService.js +279 -0
  216. package/dist/services/modelProviderCredentialHome.d.ts +32 -0
  217. package/dist/services/modelProviderCredentialHome.js +271 -0
  218. package/dist/services/ownerScopedModelConnectionGateway.d.ts +12 -0
  219. package/dist/services/ownerScopedModelConnectionGateway.js +30 -0
  220. package/dist/services/taskforceAgentConnectionBindingService.d.ts +66 -0
  221. package/dist/services/taskforceAgentConnectionBindingService.js +185 -0
  222. package/dist/services/taskforceAgentMcpBridge.d.ts +8 -2
  223. package/dist/services/taskforceAgentMcpBridge.js +30 -27
  224. package/dist/shared/adminEdgeProxy.d.ts +5 -0
  225. package/dist/shared/adminEdgeProxy.js +94 -0
  226. package/dist/shared/adminProxySessionCookies.d.ts +16 -0
  227. package/dist/shared/adminProxySessionCookies.js +86 -0
  228. package/dist/shared/aiProfileColors.d.ts +31 -1
  229. package/dist/shared/aiProfileColors.js +14 -6
  230. package/dist/shared/executorPhaseAApprovalGoldenVector.json +269 -0
  231. package/dist/shared/executorPhaseAApprovalReceipt.d.ts +112 -0
  232. package/dist/shared/executorPhaseAApprovalReceipt.js +58 -0
  233. package/dist/shared/executorPhaseAApprovalTrustPolicy.json +10 -0
  234. package/dist/shared/executorPhaseADriftContracts.d.ts +37 -0
  235. package/dist/shared/executorPhaseADriftContracts.js +63 -0
  236. package/dist/shared/executorPhaseAIssuerContracts.d.ts +75 -0
  237. package/dist/shared/executorPhaseAIssuerContracts.js +90 -0
  238. package/dist/shared/executorPhaseARunAuthorization.d.ts +120 -0
  239. package/dist/shared/executorPhaseARunAuthorization.js +232 -0
  240. package/dist/shared/executorPhaseASchemaValidation.d.ts +7 -0
  241. package/dist/shared/executorPhaseASchemaValidation.js +53 -0
  242. package/dist/shared/executorPhaseASchemas/approval-receipt.schema.json +106 -0
  243. package/dist/shared/executorPhaseASchemas/drift-attestation.schema.json +54 -0
  244. package/dist/shared/executorPhaseASchemas/drift-request.schema.json +47 -0
  245. package/dist/shared/executorPhaseASchemas/foundation-manifest.schema.json +29 -0
  246. package/dist/shared/executorPhaseASchemas/issuer-audit-record.schema.json +24 -0
  247. package/dist/shared/executorPhaseASchemas/issuer-proof.schema.json +43 -0
  248. package/dist/shared/executorPhaseASchemas/issuer-redemption-request.schema.json +18 -0
  249. package/dist/shared/executorPhaseASchemas/issuer-redemption-response.schema.json +39 -0
  250. package/dist/shared/executorPhaseASchemas/logical-envelope.schema.json +149 -0
  251. package/dist/shared/executorPhaseASchemas/preflight-report.schema.json +216 -0
  252. package/dist/shared/executorPhaseASchemas/run-capability.schema.json +111 -0
  253. package/dist/shared/executorPhaseASchemas/sender-proof.schema.json +37 -0
  254. package/dist/shared/executorPhaseASchemas/workload-grant.schema.json +68 -0
  255. package/dist/shared/executorPhaseASchemas/workload-jwt-claims.schema.json +67 -0
  256. package/dist/shared/executorPhaseATiming.d.ts +1 -0
  257. package/dist/shared/executorPhaseATiming.js +1 -0
  258. package/dist/shared/planningIdentity.js +1 -1
  259. package/dist/shared/productLogoKeys.d.ts +2 -0
  260. package/dist/shared/productLogoKeys.js +18 -0
  261. package/dist/shared/taskforceAgentDefinition.d.ts +0 -1
  262. package/dist/shared/taskforceAgentDefinition.js +6 -3
  263. package/dist/shared/taskforceAgentModels.d.ts +1 -0
  264. package/dist/shared/taskforceAgentModels.js +36 -3
  265. package/dist/shared/userFeatureGrants.d.ts +4 -0
  266. package/dist/shared/userFeatureGrants.js +7 -0
  267. package/dist/storage/executorPhaseAApprovalReceiptStore.d.ts +37 -0
  268. package/dist/storage/executorPhaseAApprovalReceiptStore.js +81 -0
  269. package/dist/storage/executorPhaseARunAuthorizationStore.d.ts +103 -0
  270. package/dist/storage/executorPhaseARunAuthorizationStore.js +492 -0
  271. package/dist/storage/githubReviewEvidenceInstallationStore.d.ts +26 -0
  272. package/dist/storage/githubReviewEvidenceInstallationStore.js +89 -0
  273. package/dist/storage/modelProviderConnectionStore.d.ts +99 -0
  274. package/dist/storage/modelProviderConnectionStore.js +446 -0
  275. package/dist/storage/postgresAdapter.d.ts +24 -3
  276. package/dist/storage/postgresAdapter.js +117 -14
  277. package/dist/storage/postgresWorker.js +22 -5
  278. package/dist/storage/postgresWorkerProtocol.d.ts +30 -0
  279. package/dist/storage/postgresWorkerProtocol.js +30 -0
  280. package/dist/storage/taskforceAgentConnectionBindingStore.d.ts +31 -0
  281. package/dist/storage/taskforceAgentConnectionBindingStore.js +84 -0
  282. package/dist/sync/cloudSyncApi.d.ts +4 -1
  283. package/dist/sync/cloudSyncApi.js +7 -2
  284. package/dist/sync/contentSyncState.d.ts +1 -1
  285. package/dist/sync/coordinator/localSyncExecutionPermitStore.d.ts +1 -0
  286. package/dist/sync/coordinator/localSyncExecutionPermitStore.js +67 -30
  287. package/dist/sync/coordinator/localWorkspaceSyncPendingV2PushProgress.d.ts +10 -0
  288. package/dist/sync/coordinator/localWorkspaceSyncPendingV2PushProgress.js +29 -0
  289. package/dist/sync/coordinator/localWorkspaceSyncRunner.js +6 -2
  290. package/dist/sync/coordinator/localWorkspaceSyncRunnerState.d.ts +15 -1
  291. package/dist/sync/coordinator/localWorkspaceSyncRunnerState.js +99 -2
  292. package/dist/sync/coordinator/workspaceSyncCredentialBroker.d.ts +1 -0
  293. package/dist/sync/coordinator/workspaceSyncCredentialBroker.js +33 -4
  294. package/dist/sync/engine/workspaceSyncContentLifecycleAdapter.d.ts +2 -1
  295. package/dist/sync/engine/workspaceSyncContentVersionStore.d.ts +38 -0
  296. package/dist/sync/engine/workspaceSyncContentVersionStore.js +50 -1
  297. package/dist/sync/engine/workspaceSyncEngineBrowserGatewayRemoteServices.js +20 -2
  298. package/dist/sync/engine/workspaceSyncEngineLifecyclePolicy.js +6 -6
  299. package/dist/sync/engine/workspaceSyncEngineLocalServices.d.ts +4 -0
  300. package/dist/sync/engine/workspaceSyncEngineLocalServices.js +11 -0
  301. package/dist/sync/engine/workspaceSyncEnginePushCompletion.d.ts +14 -0
  302. package/dist/sync/engine/workspaceSyncEnginePushCompletion.js +84 -0
  303. package/dist/sync/engine/workspaceSyncEngineRecovery.js +1 -0
  304. package/dist/sync/engine/workspaceSyncEngineRemoteServices.d.ts +11 -0
  305. package/dist/sync/engine/workspaceSyncEngineRemoteServices.js +2 -1
  306. package/dist/sync/engine/workspaceSyncEngineRuntime.d.ts +1 -0
  307. package/dist/sync/engine/workspaceSyncEngineRuntime.js +1 -0
  308. package/dist/sync/engine/workspaceSyncEngineServerRemoteServices.js +31 -4
  309. package/dist/sync/engine/workspaceSyncEngineServerRunnerOperations.d.ts +3 -1
  310. package/dist/sync/engine/workspaceSyncEngineServerRunnerOperations.js +134 -43
  311. package/dist/sync/engine/workspaceSyncEngineServerSnapshotReader.js +6 -0
  312. package/dist/sync/engine/workspaceSyncEngineTransfers.d.ts +1 -1
  313. package/dist/sync/engine/workspaceSyncEngineTransfers.js +11 -4
  314. package/dist/sync/engine/workspaceSyncV2ChangeDispatcher.d.ts +1 -0
  315. package/dist/sync/engine/workspaceSyncV2ChangeDispatcher.js +29 -0
  316. package/dist/sync/syncApplyHandlers.d.ts +2 -0
  317. package/dist/sync/syncApplyHandlers.js +10 -1
  318. package/dist/sync/syncService.d.ts +17 -0
  319. package/dist/sync/syncService.js +87 -19
  320. package/dist/sync/taskforceAgentSyncAuthorization.d.ts +16 -0
  321. package/dist/sync/taskforceAgentSyncAuthorization.js +20 -0
  322. package/dist/sync/v3/combinedFeedCapability.js +8 -0
  323. package/dist/sync/v3/durableInitiativeMutationRouter.js +18 -10
  324. package/dist/sync/v3/durableOperationReplay.d.ts +14 -0
  325. package/dist/sync/v3/durableOperationReplay.js +18 -0
  326. package/dist/sync/v3/durableTaskAttachmentLinksMutationRouter.d.ts +2 -0
  327. package/dist/sync/v3/durableTaskAttachmentLinksMutationRouter.js +14 -1
  328. package/dist/sync/v3/durableTaskChecklistMutationRouter.d.ts +4 -1
  329. package/dist/sync/v3/durableTaskChecklistMutationRouter.js +62 -15
  330. package/dist/sync/v3/durableTaskCommentMutationRouter.js +3 -0
  331. package/dist/sync/v3/durableTaskHttpBulkMutationRouter.d.ts +1 -0
  332. package/dist/sync/v3/durableTaskHttpBulkMutationRouter.js +30 -8
  333. package/dist/sync/v3/durableTaskHttpRootMutationRouter.d.ts +5 -3
  334. package/dist/sync/v3/durableTaskHttpRootMutationRouter.js +37 -2
  335. package/dist/sync/v3/durableTaxonomyMutationRouter.js +5 -0
  336. package/dist/sync/v3/durableWorkflowRuntimeMutationRouter.d.ts +11 -0
  337. package/dist/sync/v3/durableWorkflowRuntimeMutationRouter.js +39 -10
  338. package/dist/sync/v3/durableWorkstreamMutationRouter.js +18 -10
  339. package/dist/sync/v3/durableWorkstreamTaskOrderMutationRouter.js +16 -5
  340. package/dist/sync/v3/localOutboxDispatchRuntime.js +2 -2
  341. package/dist/sync/v3/localTaskAttachmentLinksOutboxService.d.ts +2 -0
  342. package/dist/sync/v3/localTaskAttachmentLinksOutboxService.js +47 -7
  343. package/dist/sync/v3/localTaskChecklistOutboxHandler.js +16 -2
  344. package/dist/sync/v3/localTaskChecklistOutboxService.d.ts +4 -0
  345. package/dist/sync/v3/localTaskChecklistOutboxService.js +14 -1
  346. package/dist/sync/v3/localTaskCreateOutboxService.js +15 -6
  347. package/dist/sync/v3/localTaskMetadataClient.d.ts +1 -0
  348. package/dist/sync/v3/localTaskMetadataClient.js +1 -0
  349. package/dist/sync/v3/localTaskMetadataOutboxHandler.js +5 -1
  350. package/dist/sync/v3/localTaskMetadataOutboxService.d.ts +2 -0
  351. package/dist/sync/v3/localTaskMetadataOutboxService.js +7 -0
  352. package/dist/sync/v3/localTaskRestoreOutboxService.js +14 -6
  353. package/dist/sync/v3/localTaskStatusClient.d.ts +1 -0
  354. package/dist/sync/v3/localTaskStatusClient.js +6 -1
  355. package/dist/sync/v3/localTaskStatusOutboxService.d.ts +10 -0
  356. package/dist/sync/v3/localTaskStatusOutboxService.js +272 -24
  357. package/dist/sync/v3/syncDurabilityStore.d.ts +41 -0
  358. package/dist/sync/v3/syncDurabilityStore.js +199 -13
  359. package/dist/sync/v3/taskAttachmentLinksMutationService.d.ts +6 -4
  360. package/dist/sync/v3/taskAttachmentLinksMutationService.js +19 -10
  361. package/dist/sync/v3/taskChecklistMutationService.d.ts +15 -2
  362. package/dist/sync/v3/taskChecklistMutationService.js +48 -1
  363. package/dist/sync/v3/taskCreateMutationService.d.ts +2 -2
  364. package/dist/sync/v3/taskCreateMutationService.js +7 -4
  365. package/dist/sync/v3/taskMetadataMutationService.d.ts +3 -0
  366. package/dist/sync/v3/taskMetadataMutationService.js +4 -0
  367. package/dist/sync/v3/taskRestoreMutationService.d.ts +2 -2
  368. package/dist/sync/v3/taskRestoreMutationService.js +7 -4
  369. package/dist/sync/v3/taskStatusMutationService.d.ts +31 -1
  370. package/dist/sync/v3/taskStatusMutationService.js +123 -3
  371. package/dist/sync/v3/workflowAssignmentSync.d.ts +6 -0
  372. package/dist/sync/v3/workflowAssignmentSync.js +30 -0
  373. package/dist/sync/v3/workspaceSyncJournalReader.js +1 -1
  374. package/dist/sync/v3/workspaceSyncOperationRetentionService.d.ts +16 -0
  375. package/dist/sync/v3/workspaceSyncOperationRetentionService.js +83 -0
  376. package/dist/sync/v3/workspaceSyncV2ProjectionExclusions.d.ts +1 -1
  377. package/dist/sync/v3/workspaceSyncV2ProjectionExclusions.js +13 -3
  378. package/dist/sync/v3/workspaceSyncV3AttachmentApplyObligationStore.d.ts +11 -0
  379. package/dist/sync/v3/workspaceSyncV3AttachmentApplyObligationStore.js +27 -10
  380. package/dist/sync/v3/workspaceSyncV3AttachmentAssetHydration.d.ts +2 -1
  381. package/dist/sync/v3/workspaceSyncV3AttachmentAssetHydration.js +52 -10
  382. package/dist/sync/v3/workspaceSyncV3CloudOperationHandler.d.ts +1 -0
  383. package/dist/sync/v3/workspaceSyncV3CloudOperationHandler.js +18 -3
  384. package/dist/sync/v3/workspaceSyncV3CombinedFeedOrchestrator.js +8 -3
  385. package/dist/sync/v3/workspaceSyncV3CombinedLocalApply.js +51 -10
  386. package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.d.ts +14 -0
  387. package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.js +49 -25
  388. package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.d.ts +13 -4
  389. package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.js +124 -57
  390. package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.d.ts +20 -0
  391. package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.js +106 -30
  392. package/dist/sync/v3/workspaceSyncV3CombinedWireContract.d.ts +4 -1
  393. package/dist/sync/v3/workspaceSyncV3CombinedWireContract.js +34 -0
  394. package/dist/sync/v3/workspaceSyncV3CoverageRegistry.js +12 -0
  395. package/dist/sync/v3/workspaceSyncV3FeedProfile.d.ts +1 -1
  396. package/dist/sync/v3/workspaceSyncV3LegacyBoundaryAttestation.d.ts +1 -0
  397. package/dist/sync/v3/workspaceSyncV3LegacyBoundaryAttestation.js +23 -10
  398. package/dist/sync/v3/workspaceSyncV3NestedTaskApply.d.ts +3 -0
  399. package/dist/sync/v3/workspaceSyncV3NestedTaskApply.js +64 -13
  400. package/dist/sync/v3/workspaceSyncV3NestedTaskCodecs.d.ts +9 -0
  401. package/dist/sync/v3/workspaceSyncV3NestedTaskCodecs.js +26 -0
  402. package/dist/sync/v3/workspaceSyncV3NestedTaskProjection.d.ts +15 -5
  403. package/dist/sync/v3/workspaceSyncV3NestedTaskProjection.js +50 -14
  404. package/dist/sync/v3/workspaceSyncV3NestedTaskRepairSnapshot.d.ts +2 -1
  405. package/dist/sync/v3/workspaceSyncV3NestedTaskRepairSnapshot.js +11 -3
  406. package/dist/sync/v3/workspaceSyncV3OperationProtocol.d.ts +5 -0
  407. package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.d.ts +7 -0
  408. package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.js +55 -9
  409. package/dist/sync/v3/workspaceSyncV3RepairSnapshotRetentionService.d.ts +17 -0
  410. package/dist/sync/v3/workspaceSyncV3RepairSnapshotRetentionService.js +64 -0
  411. package/dist/sync/v3/workspaceSyncV3TaskCommentAudit.js +9 -2
  412. package/dist/sync/v3/workspaceSyncV3TaskCoverCoverage.d.ts +7 -0
  413. package/dist/sync/v3/workspaceSyncV3TaskCoverCoverage.js +37 -0
  414. package/dist/sync/v3/workspaceSyncV3TaskCoverWireContract.d.ts +6 -0
  415. package/dist/sync/v3/workspaceSyncV3TaskCoverWireContract.js +9 -0
  416. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverCoverage.d.ts +7 -0
  417. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverCoverage.js +33 -0
  418. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverWireContract.d.ts +7 -0
  419. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverWireContract.js +8 -0
  420. package/dist/sync/workspacePullFeed.js +2 -1
  421. package/dist/sync/workspaceRepair.d.ts +8 -2
  422. package/dist/sync/workspaceRepair.js +222 -6
  423. package/dist/sync/workspaceSyncModel.d.ts +21 -0
  424. package/dist/sync/workspaceSyncModel.js +35 -7
  425. package/dist/sync/workspaceSyncState.d.ts +1 -0
  426. package/dist/sync/workspaceSyncV2SnapshotBuilder.d.ts +6 -0
  427. package/dist/sync/workspaceSyncV2SnapshotBuilder.js +5 -0
  428. package/dist/types.d.ts +47 -1
  429. package/dist/types.js +6 -0
  430. package/dist/ui/assets/AiIdentityRosterCard-OcSz1PkK.js +1 -0
  431. package/dist/ui/assets/AiProfilesModule-ByhYW5Xi.js +1 -0
  432. package/dist/ui/assets/AnnotatedAttachmentWorkspace-BTM6nIg_.js +3 -0
  433. package/dist/ui/assets/AnnotatedAttachmentWorkspace-TzYu7pkG.css +1 -0
  434. package/dist/ui/assets/{AssetTraySortControl-Kf1pelSy.js → AssetTraySortControl-DabEG8L4.js} +1 -1
  435. package/dist/ui/assets/{ContextAttachmentManager-B8boOs6Q.js → ContextAttachmentManager-Coa8yVGM.js} +2 -2
  436. package/dist/ui/assets/{DocumentWorkspace-DXH4XUsB.js → DocumentWorkspace-BB0qhdix.js} +1 -1
  437. package/dist/ui/assets/{EntityActivityTimeline-BtSTq0ON.js → EntityActivityTimeline-CZ8x4UJE.js} +1 -1
  438. package/dist/ui/assets/PlanningModule-pRPjR7v5.js +1 -0
  439. package/dist/ui/assets/PlansPage-D86pZSSl.js +1 -0
  440. package/dist/ui/assets/TaskContextUpload-BVIkU9yT.js +1 -0
  441. package/dist/ui/assets/TaskSettings-Cv1mNhv_.js +12 -0
  442. package/dist/ui/assets/TaskforceAgentsModule-b-8R25cJ.css +1 -0
  443. package/dist/ui/assets/TaskforceAgentsModule-gmH-PD2q.js +24 -0
  444. package/dist/ui/assets/{WorkflowManagerModule-DWFspC-o.js → WorkflowManagerModule-DbfnHJ-f.js} +1 -1
  445. package/dist/ui/assets/index-BZ-hdZSk.css +1 -0
  446. package/dist/ui/assets/index-CTsDBaef.js +7 -0
  447. package/dist/ui/assets/{vendor-icons-BkFLXavV.js → vendor-icons-Bsq-mcEn.js} +1 -1
  448. package/dist/ui/branding/logos/letterhead_dark.png +0 -0
  449. package/dist/ui/branding/logos/letterhead_light.png +0 -0
  450. package/dist/ui/branding/logos/signature_dark.png +0 -0
  451. package/dist/ui/branding/logos/signature_light.png +0 -0
  452. package/dist/ui/index.html +3 -3
  453. package/dist/utils/aiProfileDefaultLogo.js +16 -48
  454. package/dist/utils/httpSetCookie.d.ts +1 -0
  455. package/dist/utils/httpSetCookie.js +4 -1
  456. package/dist/utils/localRuntimeUrl.d.ts +1 -0
  457. package/dist/utils/localRuntimeUrl.js +14 -0
  458. package/dist/utils/productLogoRegistry.d.ts +2 -0
  459. package/dist/utils/productLogoRegistry.js +36 -0
  460. package/dist/utils/syncStatusPresentation.d.ts +4 -0
  461. package/dist/utils/syncStatusPresentation.js +17 -0
  462. package/dist/utils/taskActivity.d.ts +3 -2
  463. package/dist/utils/taskActivity.js +19 -2
  464. package/dist/utils/taskEditorReconciliation.d.ts +40 -0
  465. package/dist/utils/taskEditorReconciliation.js +217 -0
  466. package/dist/utils/taskEvents.d.ts +2 -0
  467. package/dist/utils/taskNormalization.d.ts +1 -0
  468. package/dist/utils/taskNormalization.js +39 -0
  469. package/dist/utils/taskSearch.js +2 -2
  470. package/dist/utils/uiNotice.d.ts +4 -0
  471. package/dist/utils/workspaceSyncPresentation.d.ts +1 -1
  472. package/dist/utils/workspaceSyncPresentation.js +23 -17
  473. package/package.json +36 -6
  474. package/dist/ui/assets/AiIdentityRosterCard-MZs7lVED.js +0 -1
  475. package/dist/ui/assets/AiProfilesModule-C3i0LOxe.js +0 -1
  476. package/dist/ui/assets/AnnotatedAttachmentWorkspace-CBRZ8rca.css +0 -1
  477. package/dist/ui/assets/AnnotatedAttachmentWorkspace-DVZk5Tln.js +0 -3
  478. package/dist/ui/assets/PlanningModule-BPVyEa-f.js +0 -1
  479. package/dist/ui/assets/PlansPage-ChqgxALc.js +0 -1
  480. package/dist/ui/assets/TaskContextUpload-CB3ol0sN.js +0 -1
  481. package/dist/ui/assets/TaskSettings-g4ECKNOz.js +0 -12
  482. package/dist/ui/assets/TaskforceAgentsModule-BazdUwxZ.js +0 -21
  483. package/dist/ui/assets/TaskforceAgentsModule-D6IC0S7Q.css +0 -1
  484. package/dist/ui/assets/index-BUplSsv_.js +0 -7
  485. package/dist/ui/assets/index-gz2EXuoK.css +0 -1
@@ -35,6 +35,9 @@ export function runDurableTaskMetadataUpdate(input) {
35
35
  ...(input.activityAction && input.activityAction !== 'task-updated'
36
36
  ? { activityAction: input.activityAction }
37
37
  : {}),
38
+ ...(input.expectedDetailRevision
39
+ ? { expectedDetailRevision: input.expectedDetailRevision }
40
+ : {}),
38
41
  },
39
42
  });
40
43
  const activityEventId = buildTaskMetadataActivityEventId({
@@ -112,6 +115,7 @@ export function runDurableTaskMetadataUpdate(input) {
112
115
  })),
113
116
  }],
114
117
  applyMutation: () => {
118
+ input.assertPrecondition?.();
115
119
  const actorRef = resolveDeferredMutationActorRef(input);
116
120
  if (!carriers)
117
121
  return applyTaskMetadataUpdateForDurableSync({
@@ -2,7 +2,7 @@ import type { TaskEvent } from '../../core/Taskforce.js';
2
2
  import type { TaskRestoreDestination } from '../../shared/taskRestoreDestination.js';
3
3
  import { type DurableTaskRestoreCore } from '../../core/TaskDurableRestoreMutationService.js';
4
4
  import { serializeTaskForSync } from '../taskSyncPayload.js';
5
- import { serializeWorkspaceSyncV3TaskAttachmentLinksPayload, serializeWorkspaceSyncV3TaskChecklistPayload, serializeWorkspaceSyncV3TaskCommentsPayload, type WorkspaceSyncV3TaskAttachmentLink } from './workspaceSyncV3NestedTaskCodecs.js';
5
+ import { serializeWorkspaceSyncV3TaskAttachmentLinksV2Payload, serializeWorkspaceSyncV3TaskChecklistPayload, serializeWorkspaceSyncV3TaskCommentsPayload, type WorkspaceSyncV3TaskAttachmentLink } from './workspaceSyncV3NestedTaskCodecs.js';
6
6
  import { type WorkspaceSyncActivityRevision } from './taskActivityJournal.js';
7
7
  import { WorkspaceSyncDurabilityStore } from './syncDurabilityStore.js';
8
8
  export interface DurableTaskRestoreServiceCore extends DurableTaskRestoreCore {
@@ -57,7 +57,7 @@ export type DurableTaskRestoreResponse = {
57
57
  sequence: string;
58
58
  entityRevision: string;
59
59
  lifecycleRevision: string;
60
- payload: ReturnType<typeof serializeWorkspaceSyncV3TaskAttachmentLinksPayload>;
60
+ payload: ReturnType<typeof serializeWorkspaceSyncV3TaskAttachmentLinksV2Payload>;
61
61
  };
62
62
  activity: TaskEvent;
63
63
  activityRevision: WorkspaceSyncActivityRevision;
@@ -1,7 +1,7 @@
1
1
  import { applyTaskRestoreForDurableSync, } from '../../core/TaskDurableRestoreMutationService.js';
2
2
  import { serializeTaskForSync } from '../taskSyncPayload.js';
3
3
  import { buildTaskLifecycleActivityEventId } from './taskLifecycleActivityIdentity.js';
4
- import { serializeWorkspaceSyncV3TaskAttachmentLinksPayload, serializeWorkspaceSyncV3TaskChecklistPayload, serializeWorkspaceSyncV3TaskCommentsPayload, } from './workspaceSyncV3NestedTaskCodecs.js';
4
+ import { serializeWorkspaceSyncV3TaskAttachmentLinksV2Payload, serializeWorkspaceSyncV3TaskChecklistPayload, serializeWorkspaceSyncV3TaskCommentsPayload, } from './workspaceSyncV3NestedTaskCodecs.js';
5
5
  import { asWorkspaceSyncActivityRevision, buildTaskActivityJournalEntry, } from './taskActivityJournal.js';
6
6
  import { fingerprintWorkspaceSyncPayload, WORKSPACE_SYNC_CONTRACT_VERSION, } from './syncDurabilityStore.js';
7
7
  export function runDurableTaskRestore(input) {
@@ -90,13 +90,15 @@ export function runDurableTaskRestore(input) {
90
90
  domain: 'task-attachment-links', entityId: input.taskId, mutationKind: 'replace', revisionKind: 'metadata',
91
91
  baseEntityRevision: 0, baseLifecycleRevision: 0,
92
92
  baseRevisionPolicy: 'current',
93
- buildCanonicalFingerprint: (task) => fingerprintWorkspaceSyncPayload(serializeWorkspaceSyncV3TaskAttachmentLinksPayload({
93
+ buildCanonicalFingerprint: (task) => fingerprintWorkspaceSyncPayload(serializeWorkspaceSyncV3TaskAttachmentLinksV2Payload({
94
94
  taskId: task.id,
95
95
  links: input.core.listTaskAttachmentLinksForDurableSync(task.id, input.workspaceId),
96
+ cardCoverAssetId: task.cardCoverAssetId ?? null,
96
97
  })),
97
- buildAuthoritativePayload: (task) => serializeWorkspaceSyncV3TaskAttachmentLinksPayload({
98
+ buildAuthoritativePayload: (task) => serializeWorkspaceSyncV3TaskAttachmentLinksV2Payload({
98
99
  taskId: task.id,
99
100
  links: input.core.listTaskAttachmentLinksForDurableSync(task.id, input.workspaceId),
101
+ cardCoverAssetId: task.cardCoverAssetId ?? null,
100
102
  }),
101
103
  }, buildTaskActivityJournalEntry({ eventId: activityEventId, readEvent: readActivity })],
102
104
  applyMutation: () => applyTaskRestoreForDurableSync({
@@ -151,9 +153,10 @@ export function runDurableTaskRestore(input) {
151
153
  domain: 'task-attachment-links', entityId: task.id, mutationKind: 'replace',
152
154
  sequence: attachmentRevision.sequence, entityRevision: attachmentRevision.entityRevision,
153
155
  lifecycleRevision: attachmentRevision.lifecycleRevision,
154
- payload: serializeWorkspaceSyncV3TaskAttachmentLinksPayload({
156
+ payload: serializeWorkspaceSyncV3TaskAttachmentLinksV2Payload({
155
157
  taskId: task.id,
156
158
  links: input.core.listTaskAttachmentLinksForDurableSync(task.id, input.workspaceId),
159
+ cardCoverAssetId: task.cardCoverAssetId ?? null,
157
160
  }),
158
161
  },
159
162
  activity: readActivity(),
@@ -1,4 +1,4 @@
1
- import type { EntityEvent, TaskEvent } from '../../core/Taskforce.js';
1
+ import type { Comment, EntityEvent, TaskEvent } from '../../core/Taskforce.js';
2
2
  import type { DatabaseAdapter } from '../../storage/databaseAdapter.js';
3
3
  import type { TaskActor } from '../../types.js';
4
4
  import { type DurableTaskStatusMutationCore } from '../../core/TaskDurableStatusMutationService.js';
@@ -6,6 +6,7 @@ import { serializeTaskForSync } from '../taskSyncPayload.js';
6
6
  import type { WorkflowAssignmentSyncRecord } from '../../storage/workflowStore.js';
7
7
  import { type WorkspaceSyncActivityRevision } from './taskActivityJournal.js';
8
8
  import { WorkspaceSyncDurabilityStore } from './syncDurabilityStore.js';
9
+ import { type WorkspaceSyncV3TaskCommentsPayload } from './workspaceSyncV3NestedTaskCodecs.js';
9
10
  export interface DurableTaskStatusServiceCore extends DurableTaskStatusMutationCore {
10
11
  notifyDurableTaskLifecycleCommitted(workspaceId: string, taskId: string): void;
11
12
  getTaskEventForSync(input: {
@@ -19,6 +20,14 @@ export interface DurableTaskStatusServiceCore extends DurableTaskStatusMutationC
19
20
  }): EntityEvent | null;
20
21
  listAssignableActors(workspaceId: string): TaskActor[];
21
22
  getDatabaseAdapter(): DatabaseAdapter;
23
+ addTaskCommentEventForDurableSync(event: {
24
+ taskId: string;
25
+ workspaceId: string;
26
+ actor: string;
27
+ eventId: string;
28
+ createdAt: string;
29
+ comment: Comment;
30
+ }): void;
22
31
  }
23
32
  export type DurableTaskStatusResponse = {
24
33
  success: true;
@@ -45,7 +54,25 @@ export type DurableTaskStatusResponse = {
45
54
  dependentActivities?: EntityEvent[];
46
55
  dependentActivityRevisions?: WorkspaceSyncActivityRevision[];
47
56
  workflowAssignment?: WorkflowAssignmentSyncRecord;
57
+ reviewHandoff?: {
58
+ comments: {
59
+ domain: 'task-comments';
60
+ entityId: string;
61
+ mutationKind: 'append';
62
+ sequence: string;
63
+ entityRevision: string;
64
+ lifecycleRevision: string;
65
+ payload: WorkspaceSyncV3TaskCommentsPayload;
66
+ };
67
+ activity: TaskEvent;
68
+ activityRevision: WorkspaceSyncActivityRevision;
69
+ };
48
70
  };
71
+ export declare class WorkflowRuntimeActivationFencedError extends Error {
72
+ readonly code = "WORKFLOW_RUNTIME_MUTATIONS_FENCED";
73
+ readonly statusCode = 503;
74
+ constructor();
75
+ }
49
76
  export declare function runDurableTaskStatusMutation(input: {
50
77
  store: WorkspaceSyncDurabilityStore;
51
78
  core: DurableTaskStatusServiceCore;
@@ -64,6 +91,9 @@ export declare function runDurableTaskStatusMutation(input: {
64
91
  resolveActorRef?: () => string;
65
92
  originActorRef?: string;
66
93
  includeWorkflowRuntimeJournal?: boolean;
94
+ rejectWorkflowRuntimeActivation?: boolean;
95
+ expectedDetailRevision?: string;
96
+ assertPrecondition?: () => void;
67
97
  onPostCommitError?: (error: unknown) => void;
68
98
  }): {
69
99
  state: 'in_progress';
@@ -8,7 +8,27 @@ import { asWorkspaceSyncActivityRevision, buildEntityActivityJournalEntry, build
8
8
  import { fingerprintWorkspaceSyncPayload, WORKSPACE_SYNC_CONTRACT_VERSION, } from './syncDurabilityStore.js';
9
9
  import { resolveDeferredMutationActorRef } from './workspaceSyncV3OriginActor.js';
10
10
  import { buildWorkflowRuntimeEventId } from './workflowRuntimeOperationIdentity.js';
11
+ import { buildTaskCommentActivityEventId } from './taskCommentActivityIdentity.js';
12
+ import { serializeWorkspaceSyncV3TaskCommentAppendPayload, serializeWorkspaceSyncV3TaskCommentsPayload, } from './workspaceSyncV3NestedTaskCodecs.js';
11
13
  import { fingerprintWorkflowRuntimePayload, serializeWorkflowExecutionEventSyncPayload, serializeWorkflowExecutionRootSyncPayload, serializeWorkflowPublishedDefinitionSyncPayload, } from './workflowRuntimeSync.js';
14
+ export class WorkflowRuntimeActivationFencedError extends Error {
15
+ code = 'WORKFLOW_RUNTIME_MUTATIONS_FENCED';
16
+ statusCode = 503;
17
+ constructor() {
18
+ super('Workflow execution changes are temporarily paused.');
19
+ this.name = 'WorkflowRuntimeActivationFencedError';
20
+ }
21
+ }
22
+ function nextTaskUpdatedAt(current, requested) {
23
+ const currentMs = Date.parse(current);
24
+ const requestedMs = Date.parse(requested);
25
+ if (!Number.isFinite(requestedMs) || new Date(requestedMs).toISOString() !== requested) {
26
+ throw new Error('Task status operation timestamp is invalid.');
27
+ }
28
+ return Number.isFinite(currentMs) && currentMs >= requestedMs
29
+ ? new Date(currentMs + 1).toISOString()
30
+ : requested;
31
+ }
12
32
  export function runDurableTaskStatusMutation(input) {
13
33
  const operationPayload = normalizeTaskStatusOperationWithWorkflowAssignment(input.payload);
14
34
  const payload = validateDurableTaskStatusMutationPayload({
@@ -34,6 +54,9 @@ export function runDurableTaskStatusMutation(input) {
34
54
  baseLifecycleRevision: String(input.baseLifecycleRevision),
35
55
  payload: operationPayload,
36
56
  ...(input.originActorRef ? { originActorRef: input.originActorRef } : {}),
57
+ ...(input.expectedDetailRevision
58
+ ? { expectedDetailRevision: input.expectedDetailRevision }
59
+ : {}),
37
60
  },
38
61
  });
39
62
  const activityEventId = buildTaskLifecycleActivityEventId({
@@ -45,10 +68,24 @@ export function runDurableTaskStatusMutation(input) {
45
68
  });
46
69
  const membershipRemovedEventId = `${activityEventId}:workstream-removed`;
47
70
  const membershipAddedEventId = `${activityEventId}:workstream-added`;
71
+ const requestedReviewComment = operationPayload.reviewHandoff?.comment || null;
72
+ let reviewComment = null;
73
+ const reviewCommentActivityEventId = requestedReviewComment ? buildTaskCommentActivityEventId({
74
+ workspaceId: input.workspaceId,
75
+ clientId: input.clientId,
76
+ operationId: input.operationId,
77
+ taskId: input.taskId,
78
+ commentId: requestedReviewComment.id,
79
+ }) : null;
48
80
  const workflowStore = new WorkflowStore(input.core.getDatabaseAdapter(), input.tenantId);
49
81
  const workflowActivationService = new WorkflowTaskActivationService(workflowStore, (workspaceId) => input.core.listAssignableActors(workspaceId));
50
82
  const pendingAssignment = operationPayload.workflowAssignment
51
83
  || workflowStore.getAssignmentForTaskSync(input.workspaceId, input.taskId);
84
+ if (input.rejectWorkflowRuntimeActivation === true
85
+ && payload.status === 'in-progress'
86
+ && pendingAssignment?.execution.status === 'pending') {
87
+ throw new WorkflowRuntimeActivationFencedError();
88
+ }
52
89
  const workflowStartEventId = buildWorkflowRuntimeEventId({
53
90
  workspaceId: input.workspaceId,
54
91
  clientId: input.clientId,
@@ -92,6 +129,16 @@ export function runDurableTaskStatusMutation(input) {
92
129
  throw new Error('Task status activity was not committed.');
93
130
  return activity;
94
131
  };
132
+ const readReviewCommentActivity = () => {
133
+ const activity = input.core.getTaskEventForSync({
134
+ workspaceId: input.workspaceId,
135
+ taskId: input.taskId,
136
+ eventId: reviewCommentActivityEventId,
137
+ });
138
+ if (!activity)
139
+ throw new Error('Review handoff comment activity was not committed.');
140
+ return activity;
141
+ };
95
142
  const workflowAssignmentAfterMutation = () => {
96
143
  const assignment = workflowStore.getAssignmentForTaskSync(input.workspaceId, input.taskId);
97
144
  if (!assignment || assignment.execution.id !== pendingAssignment?.execution.id) {
@@ -155,7 +202,22 @@ export function runDurableTaskStatusMutation(input) {
155
202
  reopenAssigneeOwned: (result) => result.assigneeOwned,
156
203
  buildCanonicalFingerprint: (result) => (fingerprintWorkspaceSyncPayload(serializeTaskForSync(result.task))),
157
204
  buildAuthoritativePayload: (result) => serializeTaskForSync(result.task),
158
- }, {
205
+ }, ...(requestedReviewComment ? [{
206
+ domain: 'task-comments', entityId: input.taskId, mutationKind: 'append', revisionKind: 'metadata',
207
+ baseEntityRevision: 0, baseLifecycleRevision: 0, baseRevisionPolicy: 'current',
208
+ buildCanonicalFingerprint: (result) => fingerprintWorkspaceSyncPayload(serializeWorkspaceSyncV3TaskCommentsPayload({
209
+ taskId: result.task.id,
210
+ comments: result.task.comments || [],
211
+ })),
212
+ buildAuthoritativePayload: (result) => (serializeWorkspaceSyncV3TaskCommentAppendPayload({
213
+ taskId: result.task.id,
214
+ comment: reviewComment,
215
+ commentsAfterAppend: result.task.comments || [],
216
+ })),
217
+ }, buildTaskActivityJournalEntry({
218
+ eventId: reviewCommentActivityEventId,
219
+ readEvent: readReviewCommentActivity,
220
+ })] : []), {
159
221
  ...buildTaskActivityJournalEntry({ eventId: activityEventId, readEvent: readActivity }),
160
222
  include: (result) => !result.noOp,
161
223
  }, {
@@ -184,6 +246,7 @@ export function runDurableTaskStatusMutation(input) {
184
246
  })),
185
247
  }, ...workflowEntries],
186
248
  applyMutation: () => {
249
+ input.assertPrecondition?.();
187
250
  const currentTask = input.core.getTask(input.taskId, input.workspaceId);
188
251
  if (operationPayload.workflowAssignment) {
189
252
  if (payload.status !== 'in-progress'
@@ -204,7 +267,7 @@ export function runDurableTaskStatusMutation(input) {
204
267
  })
205
268
  : null;
206
269
  const actorRef = resolveDeferredMutationActorRef(input);
207
- const result = applyTaskStatusMutationForDurableSync({
270
+ let result = applyTaskStatusMutationForDurableSync({
208
271
  core: input.core,
209
272
  workspaceId: input.workspaceId,
210
273
  taskId: input.taskId,
@@ -220,6 +283,42 @@ export function runDurableTaskStatusMutation(input) {
220
283
  actorRef,
221
284
  taskEventId: activityEventId,
222
285
  });
286
+ if (requestedReviewComment) {
287
+ const authoritativeReviewComment = {
288
+ ...requestedReviewComment,
289
+ author: actorRef,
290
+ submittedAuthor: actorRef,
291
+ timestamp: input.now,
292
+ };
293
+ reviewComment = authoritativeReviewComment;
294
+ const existingComments = serializeWorkspaceSyncV3TaskCommentsPayload({
295
+ taskId: result.task.id,
296
+ comments: result.task.comments || [],
297
+ }).comments;
298
+ const collision = existingComments.find((comment) => comment.id === authoritativeReviewComment.id);
299
+ if (collision) {
300
+ throw new Error(`Review handoff comment identity conflict: ${authoritativeReviewComment.id}.`);
301
+ }
302
+ const updatedAt = nextTaskUpdatedAt(String(result.task.updatedAt || result.task.createdAt), input.now);
303
+ const updated = input.core.updateTask(result.task.id, { comments: [...existingComments, authoritativeReviewComment] }, input.workspaceId, {
304
+ persistBackup: false,
305
+ emitRealtime: false,
306
+ skipTaskEvents: true,
307
+ syncUpdatedAt: updatedAt,
308
+ allowV3OwnedMetadataWrite: true,
309
+ });
310
+ if (!updated)
311
+ throw new Error('Review handoff task disappeared during comment persistence.');
312
+ input.core.addTaskCommentEventForDurableSync({
313
+ taskId: updated.id,
314
+ workspaceId: input.workspaceId,
315
+ actor: actorRef,
316
+ eventId: reviewCommentActivityEventId,
317
+ createdAt: String(updated.updatedAt),
318
+ comment: authoritativeReviewComment,
319
+ });
320
+ result = { ...result, task: updated };
321
+ }
223
322
  if (activation) {
224
323
  workflowActivationService.start({
225
324
  workspaceId: input.workspaceId,
@@ -257,6 +356,9 @@ export function runDurableTaskStatusMutation(input) {
257
356
  throw new Error('Dependent task status activity was not committed.');
258
357
  return event;
259
358
  });
359
+ const reviewCommentsRevision = reviewComment ? revisions.find((revision) => (revision.domain === 'task-comments' && revision.entityId === input.taskId)) : null;
360
+ const reviewActivityRevisionValue = reviewComment ? revisions.find((revision) => (revision.domain === 'entity-event' && revision.entityId === reviewCommentActivityEventId)) : null;
361
+ const reviewActivity = reviewComment ? readReviewCommentActivity() : null;
260
362
  return {
261
363
  success: true,
262
364
  contractVersion: WORKSPACE_SYNC_CONTRACT_VERSION,
@@ -281,6 +383,24 @@ export function runDurableTaskStatusMutation(input) {
281
383
  activityRevision,
282
384
  ...(dependentActivities.length > 0 ? { dependentActivities } : {}),
283
385
  ...(dependentActivityRevisions.length > 0 ? { dependentActivityRevisions } : {}),
386
+ ...(reviewComment && reviewCommentsRevision && reviewActivityRevisionValue && reviewActivity ? {
387
+ reviewHandoff: {
388
+ comments: {
389
+ domain: 'task-comments',
390
+ entityId: result.task.id,
391
+ mutationKind: 'append',
392
+ sequence: reviewCommentsRevision.sequence,
393
+ entityRevision: reviewCommentsRevision.entityRevision,
394
+ lifecycleRevision: reviewCommentsRevision.lifecycleRevision,
395
+ payload: serializeWorkspaceSyncV3TaskCommentsPayload({
396
+ taskId: result.task.id,
397
+ comments: result.task.comments || [],
398
+ }),
399
+ },
400
+ activity: reviewActivity,
401
+ activityRevision: asWorkspaceSyncActivityRevision(reviewActivityRevisionValue),
402
+ },
403
+ } : {}),
284
404
  ...(workflowStore.getAssignmentForTaskSync(input.workspaceId, result.task.id)
285
405
  ? { workflowAssignment: workflowStore.getAssignmentForTaskSync(input.workspaceId, result.task.id) }
286
406
  : {}),
@@ -288,7 +408,7 @@ export function runDurableTaskStatusMutation(input) {
288
408
  },
289
409
  });
290
410
  const response = JSON.parse(accepted.responseJson);
291
- if (response.activity) {
411
+ if (response.activity || response.reviewHandoff) {
292
412
  try {
293
413
  input.core.notifyDurableTaskLifecycleCommitted(input.workspaceId, input.taskId);
294
414
  }
@@ -1,7 +1,13 @@
1
1
  import type { WorkflowAssignmentSyncRecord, WorkflowExecutionEventRecord, WorkflowExecutionRecord, WorkflowStepRecord, WorkflowTemplateRecord, WorkflowVersionRecord } from '../../storage/workflowStore.js';
2
+ import type { Comment } from '../../core/Taskforce.js';
2
3
  import { type DurableTaskStatusMutationPayload } from '../../core/TaskDurableStatusMutationService.js';
4
+ export type TaskStatusReviewHandoff = {
5
+ comment: Pick<Comment, 'id' | 'author' | 'submittedAuthor' | 'text'>;
6
+ };
3
7
  export type TaskStatusOperationWithWorkflowAssignment = DurableTaskStatusMutationPayload & {
4
8
  workflowAssignment?: WorkflowAssignmentSyncRecord;
9
+ expectedDetailRevision?: string;
10
+ reviewHandoff?: TaskStatusReviewHandoff;
5
11
  };
6
12
  export declare class WorkflowAssignmentSyncError extends Error {
7
13
  readonly code = "WORKFLOW_ASSIGNMENT_SYNC_INVALID";
@@ -203,11 +203,41 @@ export function normalizeTaskStatusOperationWithWorkflowAssignment(raw) {
203
203
  }
204
204
  originActor = { kind: 'ai-profile', profileId };
205
205
  }
206
+ let reviewHandoff;
207
+ if (source.reviewHandoff !== undefined) {
208
+ if (status.status !== 'review') {
209
+ throw new WorkflowAssignmentSyncError('reviewHandoff is valid only when status is review.');
210
+ }
211
+ const handoff = object(source.reviewHandoff, 'reviewHandoff');
212
+ if (Object.keys(handoff).join(',') !== 'comment') {
213
+ throw new WorkflowAssignmentSyncError('reviewHandoff must contain exactly comment.');
214
+ }
215
+ const comment = object(handoff.comment, 'reviewHandoff.comment');
216
+ if (Object.keys(comment).sort().join(',') !== 'author,id,submittedAuthor,text') {
217
+ throw new WorkflowAssignmentSyncError('reviewHandoff.comment must contain exactly id, author, submittedAuthor, and text.');
218
+ }
219
+ const author = text(comment.author, 'reviewHandoff.comment.author');
220
+ const submittedAuthor = text(comment.submittedAuthor, 'reviewHandoff.comment.submittedAuthor');
221
+ const commentText = text(comment.text, 'reviewHandoff.comment.text');
222
+ if (author !== submittedAuthor) {
223
+ throw new WorkflowAssignmentSyncError('reviewHandoff comment authorship is invalid.');
224
+ }
225
+ reviewHandoff = { comment: {
226
+ id: text(comment.id, 'reviewHandoff.comment.id'),
227
+ author,
228
+ submittedAuthor,
229
+ text: commentText,
230
+ } };
231
+ }
206
232
  return {
207
233
  ...status,
208
234
  ...(source.workflowAssignment === undefined
209
235
  ? {}
210
236
  : { workflowAssignment: normalizeWorkflowAssignmentSyncRecord(source.workflowAssignment) }),
237
+ ...(reviewHandoff ? { reviewHandoff } : {}),
211
238
  ...(originActor ? { originActor } : {}),
239
+ ...(typeof source.expectedDetailRevision === 'string' && source.expectedDetailRevision.trim()
240
+ ? { expectedDetailRevision: source.expectedDetailRevision.trim() }
241
+ : {}),
212
242
  };
213
243
  }
@@ -31,7 +31,7 @@ export class WorkspaceSyncJournalReader {
31
31
  CAST(lifecycle_revision AS TEXT) AS lifecycle_revision, content_sha256,
32
32
  CAST(size_bytes AS TEXT) AS size_bytes, payload_json, occurred_at FROM workspace_sync_journal
33
33
  WHERE tenant_id = ? AND workspace_id = ? AND sequence > ? AND sequence <= ?
34
- ORDER BY sequence ASC LIMIT ?`).all(input.tenantId, input.workspaceId, sequence(input.afterSequence), sequence(input.throughSequence), Math.max(1, Math.min(10_101, Math.floor(input.limit))));
34
+ ORDER BY workspace_sync_journal.sequence ASC LIMIT ?`).all(input.tenantId, input.workspaceId, sequence(input.afterSequence), sequence(input.throughSequence), Math.max(1, Math.min(10_101, Math.floor(input.limit))));
35
35
  return rows.map((row) => ({
36
36
  sequence: sequence(row.sequence), contractVersion: Number(row.contract_version), clientId: String(row.client_id || ''),
37
37
  operationId: String(row.operation_id || ''), domain: String(row.domain || ''),
@@ -0,0 +1,16 @@
1
+ import type { DatabaseAdapter } from '../../storage/databaseAdapter.js';
2
+ export declare const WORKSPACE_SYNC_OPERATION_RETENTION_DAYS = 90;
3
+ export declare const WORKSPACE_SYNC_OPERATION_RETENTION_INTERVAL_MS: number;
4
+ export declare const WORKSPACE_SYNC_OPERATION_RETENTION_BATCH_SIZE = 100;
5
+ export declare const WORKSPACE_SYNC_OPERATION_RETENTION_WORKSPACE_LIMIT = 100;
6
+ export interface WorkspaceSyncOperationRetentionResult {
7
+ deletedOutbox: number;
8
+ deletedResults: number;
9
+ remainingEligible: number;
10
+ workspacesProcessed: number;
11
+ }
12
+ export declare function pruneRetainedWorkspaceSyncOperations(input: {
13
+ db: DatabaseAdapter;
14
+ tenantId: string;
15
+ now?: Date;
16
+ }): WorkspaceSyncOperationRetentionResult;
@@ -0,0 +1,83 @@
1
+ import { WorkspaceSyncDurabilityStore } from './syncDurabilityStore.js';
2
+ export const WORKSPACE_SYNC_OPERATION_RETENTION_DAYS = 90;
3
+ export const WORKSPACE_SYNC_OPERATION_RETENTION_INTERVAL_MS = 24 * 60 * 60_000;
4
+ export const WORKSPACE_SYNC_OPERATION_RETENTION_BATCH_SIZE = 100;
5
+ export const WORKSPACE_SYNC_OPERATION_RETENTION_WORKSPACE_LIMIT = 100;
6
+ export function pruneRetainedWorkspaceSyncOperations(input) {
7
+ const now = input.now || new Date();
8
+ const cutoff = new Date(now.getTime() - WORKSPACE_SYNC_OPERATION_RETENTION_DAYS * 24 * 60 * 60_000).toISOString();
9
+ const workspaceRows = input.db.prepare(`
10
+ SELECT eligible.workspace_id
11
+ FROM (
12
+ SELECT candidate.workspace_id, candidate.updated_at AS terminal_at
13
+ FROM workspace_sync_outbox AS candidate
14
+ WHERE candidate.tenant_id = ?
15
+ AND candidate.status IN ('accepted', 'superseded')
16
+ AND candidate.updated_at < ?
17
+ AND NOT EXISTS (
18
+ SELECT 1
19
+ FROM workspace_sync_outbox AS replay
20
+ WHERE replay.tenant_id = candidate.tenant_id
21
+ AND replay.workspace_id = candidate.workspace_id
22
+ AND replay.replay_of_client_id = candidate.client_id
23
+ AND replay.replay_of_operation_id = candidate.operation_id
24
+ )
25
+ UNION ALL
26
+ SELECT workspace_id, updated_at AS terminal_at
27
+ FROM workspace_sync_operation_results
28
+ WHERE tenant_id = ? AND status = 'committed' AND updated_at < ?
29
+ ) AS eligible
30
+ GROUP BY eligible.workspace_id
31
+ ORDER BY MIN(eligible.terminal_at), eligible.workspace_id
32
+ LIMIT ?
33
+ `).all(input.tenantId, cutoff, input.tenantId, cutoff, WORKSPACE_SYNC_OPERATION_RETENTION_WORKSPACE_LIMIT);
34
+ const store = new WorkspaceSyncDurabilityStore(input.db);
35
+ let deletedOutbox = 0;
36
+ let deletedResults = 0;
37
+ for (const row of workspaceRows) {
38
+ const workspaceId = String(row.workspace_id || '').trim();
39
+ if (!workspaceId)
40
+ continue;
41
+ const outboxResult = store.pruneTerminalOutboxOperations({
42
+ tenantId: input.tenantId,
43
+ workspaceId,
44
+ terminalBefore: cutoff,
45
+ limit: WORKSPACE_SYNC_OPERATION_RETENTION_BATCH_SIZE,
46
+ });
47
+ deletedOutbox += outboxResult.deleted;
48
+ const result = store.pruneCommittedOperationResults({
49
+ tenantId: input.tenantId,
50
+ workspaceId,
51
+ terminalBefore: cutoff,
52
+ limit: WORKSPACE_SYNC_OPERATION_RETENTION_BATCH_SIZE,
53
+ });
54
+ deletedResults += result.deleted;
55
+ }
56
+ const remaining = input.db.prepare(`
57
+ SELECT (
58
+ SELECT COUNT(*)
59
+ FROM workspace_sync_outbox AS candidate
60
+ WHERE candidate.tenant_id = ?
61
+ AND candidate.status IN ('accepted', 'superseded')
62
+ AND candidate.updated_at < ?
63
+ AND NOT EXISTS (
64
+ SELECT 1
65
+ FROM workspace_sync_outbox AS replay
66
+ WHERE replay.tenant_id = candidate.tenant_id
67
+ AND replay.workspace_id = candidate.workspace_id
68
+ AND replay.replay_of_client_id = candidate.client_id
69
+ AND replay.replay_of_operation_id = candidate.operation_id
70
+ )
71
+ ) + (
72
+ SELECT COUNT(*)
73
+ FROM workspace_sync_operation_results
74
+ WHERE tenant_id = ? AND status = 'committed' AND updated_at < ?
75
+ ) AS count
76
+ `).get(input.tenantId, cutoff, input.tenantId, cutoff);
77
+ return {
78
+ deletedOutbox,
79
+ deletedResults,
80
+ remainingEligible: Number(remaining?.count || 0),
81
+ workspacesProcessed: workspaceRows.length,
82
+ };
83
+ }
@@ -1,6 +1,6 @@
1
1
  import type { WorkspaceSyncIncomingTaskApplyModel } from '../syncApplyHandlers.js';
2
2
  import type { WorkspaceSyncChange } from '../workspaceSyncModel.js';
3
- export declare const WORKSPACE_SYNC_V2_EXCLUDABLE_PROJECTIONS: readonly ["task/root-v1", "task-relationship/full-v1", "taxonomy/full-v1", "initiative/full-v1", "workstream/full-v1", "task-comments/full-v1", "task-checklist/full-v1", "task-attachment-links/full-v1", "entity-event/full-v1", "workstream-task-order/full-v1"];
3
+ export declare const WORKSPACE_SYNC_V2_EXCLUDABLE_PROJECTIONS: readonly ["task/root-v1", "task-relationship/full-v1", "taxonomy/full-v1", "initiative/full-v1", "workstream/full-v1", "task-comments/full-v1", "task-checklist/full-v1", "task-attachment-links/full-v1", "task-attachment-links/full-v2", "entity-event/full-v1", "workstream-task-order/full-v1"];
4
4
  export type WorkspaceSyncV2ProjectionExclusion = typeof WORKSPACE_SYNC_V2_EXCLUDABLE_PROJECTIONS[number];
5
5
  export declare const WORKSPACE_SYNC_V3_COMBINED_V2_EXCLUSIONS: readonly WorkspaceSyncV2ProjectionExclusion[];
6
6
  export declare function normalizeWorkspaceSyncV2ProjectionExclusions(values: Iterable<unknown> | null | undefined): WorkspaceSyncV2ProjectionExclusion[];
@@ -8,6 +8,7 @@ export const WORKSPACE_SYNC_V2_EXCLUDABLE_PROJECTIONS = Object.freeze([
8
8
  'task-comments/full-v1',
9
9
  'task-checklist/full-v1',
10
10
  'task-attachment-links/full-v1',
11
+ 'task-attachment-links/full-v2',
11
12
  'entity-event/full-v1',
12
13
  'workstream-task-order/full-v1',
13
14
  ]);
@@ -49,7 +50,9 @@ export function prepareWorkspaceSyncV2TaskCarriers(taskMutations, excludedProjec
49
50
  return taskMutations;
50
51
  const commentsOwned = excludedProjections.has('task-comments/full-v1');
51
52
  const checklistOwned = excludedProjections.has('task-checklist/full-v1');
52
- const attachmentsOwned = excludedProjections.has('task-attachment-links/full-v1');
53
+ const cardCoverOwned = excludedProjections.has('task-attachment-links/full-v2');
54
+ const attachmentsOwned = excludedProjections.has('task-attachment-links/full-v1')
55
+ || cardCoverOwned;
53
56
  return {
54
57
  upserts: taskMutations.upserts.map(({ archived, task }) => {
55
58
  const existing = readExistingTask?.(String(task.id || '').trim());
@@ -63,6 +66,7 @@ export function prepareWorkspaceSyncV2TaskCarriers(taskMutations, excludedProjec
63
66
  ...(commentsOwned ? { comments: existing.comments || [] } : {}),
64
67
  ...(checklistOwned ? { checklistItems: existing.checklistItems || [] } : {}),
65
68
  ...(attachmentsOwned ? { attachments: existing.attachments || [] } : {}),
69
+ ...(cardCoverOwned ? { cardCoverAssetId: existing.cardCoverAssetId ?? null } : {}),
66
70
  },
67
71
  };
68
72
  }),
@@ -100,7 +104,10 @@ export function partitionWorkspaceSyncV2LegacyChanges(changes, excludedProjectio
100
104
  if (change.op === 'upsert') {
101
105
  const commentsOwned = excludedProjections.has('task-comments/full-v1');
102
106
  const checklistOwned = excludedProjections.has('task-checklist/full-v1');
103
- const attachmentsOwned = excludedProjections.has('task-attachment-links/full-v1');
107
+ const attachmentProjection = excludedProjections.has('task-attachment-links/full-v2')
108
+ ? 'task-attachment-links/full-v2'
109
+ : 'task-attachment-links/full-v1';
110
+ const attachmentsOwned = excludedProjections.has(attachmentProjection);
104
111
  if (excludedProjections.has('task/root-v1'))
105
112
  suppress('task/root-v1');
106
113
  if (commentsOwned || checklistOwned || attachmentsOwned) {
@@ -115,7 +122,10 @@ export function partitionWorkspaceSyncV2LegacyChanges(changes, excludedProjectio
115
122
  }
116
123
  if (attachmentsOwned) {
117
124
  delete task.attachments;
118
- suppress('task-attachment-links/full-v1');
125
+ if (attachmentProjection === 'task-attachment-links/full-v2') {
126
+ delete task.cardCoverAssetId;
127
+ }
128
+ suppress(attachmentProjection);
119
129
  }
120
130
  accepted.push({ ...change, task });
121
131
  continue;
@@ -15,10 +15,13 @@ export interface WorkspaceSyncV3AttachmentApplyObligation {
15
15
  createdAt: string;
16
16
  updatedAt: string;
17
17
  nextAttemptAt: string;
18
+ terminalAt: string | null;
19
+ terminalReason: string | null;
18
20
  resolvedAt: string | null;
19
21
  }
20
22
  export interface WorkspaceSyncV3AttachmentApplyObligationSummary {
21
23
  open: number;
24
+ terminal: number;
22
25
  due: number;
23
26
  oldestOpenCreatedAt: string | null;
24
27
  nextAttemptAt: string | null;
@@ -70,6 +73,14 @@ export declare class WorkspaceSyncV3AttachmentApplyObligationStore {
70
73
  taskId: string;
71
74
  now: string;
72
75
  }): void;
76
+ markTerminalUnavailable(input: {
77
+ tenantId: string;
78
+ workspaceId: string;
79
+ taskId: string;
80
+ canonicalFingerprint: string;
81
+ reason: string;
82
+ now: string;
83
+ }): void;
73
84
  recordAttemptFailure(input: {
74
85
  tenantId: string;
75
86
  workspaceId: string;