@taskforcehq/taskforce 0.3.329 → 0.3.332

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 (363) hide show
  1. package/README.md +7 -2
  2. package/dist/Taskforce.module.css +290 -45
  3. package/dist/components/features/AiProfilesModule.js +3 -5
  4. package/dist/components/features/TaskSettings.js +70 -14
  5. package/dist/components/features/TaskforceAgentsModule.d.ts +1 -2
  6. package/dist/components/features/TaskforceAgentsModule.js +586 -116
  7. package/dist/components/features/agentCapabilities/AgentCapabilitiesPrototype.d.ts +2 -2
  8. package/dist/components/features/agentCapabilities/AgentCapabilitiesPrototype.js +2 -2
  9. package/dist/components/features/agentConnections/AgentConnectionControl.d.ts +15 -0
  10. package/dist/components/features/agentConnections/AgentConnectionControl.js +125 -0
  11. package/dist/components/features/agentConnections/ModelConnectionsPanel.d.ts +18 -0
  12. package/dist/components/features/agentConnections/ModelConnectionsPanel.js +393 -0
  13. package/dist/components/features/agentConnections/modelConnectionsApi.d.ts +65 -0
  14. package/dist/components/features/agentConnections/modelConnectionsApi.js +129 -0
  15. package/dist/components/features/planning/PlanningModule.js +15 -3
  16. package/dist/components/features/planning/planningMetadata.d.ts +10 -0
  17. package/dist/components/features/planning/planningMetadata.js +8 -0
  18. package/dist/components/features/taskforceAgentAssignments/AgentBehaviorAssignments.js +15 -24
  19. package/dist/components/features/taskforceAgentEditorModel.d.ts +2 -1
  20. package/dist/components/features/taskforceAgentEditorModel.js +3 -1
  21. package/dist/components/features/workflowManager/workflowManagerApi.d.ts +1 -1
  22. package/dist/components/features/workflowManager/workflowManagerApi.js +3 -0
  23. package/dist/components/task/TaskWorkflowAssignmentField.js +68 -10
  24. package/dist/components/views/StandaloneLayout.js +62 -27
  25. package/dist/components/views/panels/PlanningDrawer.d.ts +2 -1
  26. package/dist/components/views/panels/PlanningDrawer.js +12 -8
  27. package/dist/components/views/standalone/modals/SyncStatusModal.d.ts +4 -3
  28. package/dist/components/views/standalone/modals/SyncStatusModal.js +33 -38
  29. package/dist/config/envSchema.js +55 -1
  30. package/dist/core/McpTokenService.d.ts +25 -1
  31. package/dist/core/McpTokenService.js +106 -15
  32. package/dist/core/TaskChecklistCommandService.d.ts +27 -0
  33. package/dist/core/TaskChecklistCommandService.js +83 -5
  34. package/dist/core/TaskLifecycleCommandService.d.ts +3 -1
  35. package/dist/core/TaskLifecycleCommandService.js +6 -2
  36. package/dist/core/Taskforce.d.ts +43 -3
  37. package/dist/core/Taskforce.js +158 -7
  38. package/dist/core/types.d.ts +9 -0
  39. package/dist/documentReviews/DocumentReviewCommentStore.d.ts +2 -0
  40. package/dist/documentReviews/DocumentReviewCommentStore.js +28 -9
  41. package/dist/documentReviews/commandService.d.ts +2 -1
  42. package/dist/documentReviews/commandService.js +6 -3
  43. package/dist/hooks/sync/orchestratorShared.d.ts +1 -0
  44. package/dist/hooks/sync/orchestratorShared.js +2 -0
  45. package/dist/hooks/sync/useLocalSyncCoordinatorSnapshot.d.ts +3 -0
  46. package/dist/hooks/sync/useLocalSyncCoordinatorSnapshot.js +85 -9
  47. package/dist/hooks/sync/useSyncStatusControls.d.ts +4 -1
  48. package/dist/hooks/sync/useSyncStatusControls.js +47 -11
  49. package/dist/hooks/useSyncOrchestrator.d.ts +3 -0
  50. package/dist/hooks/useSyncOrchestrator.js +111 -2
  51. package/dist/hooks/useTaskData.d.ts +31 -1
  52. package/dist/hooks/useTaskData.js +29 -7
  53. package/dist/hooks/useTaskMutations.d.ts +3 -1
  54. package/dist/hooks/useTaskMutations.js +46 -12
  55. package/dist/hooks/useTaskforce.d.ts +2 -0
  56. package/dist/hooks/useTaskforce.js +11 -2
  57. package/dist/mcp/clientRegistry.d.ts +2 -2
  58. package/dist/mcp/clientRegistry.js +1 -1
  59. package/dist/mcp/documentAssetRegistrar.js +9 -6
  60. package/dist/mcp/durableTaskMutationRouter.d.ts +4 -1
  61. package/dist/mcp/durableTaskMutationRouter.js +10 -0
  62. package/dist/mcp/durableTaskRelationshipMutationRouter.js +4 -0
  63. package/dist/mcp/httpProtocolRouting.d.ts +11 -0
  64. package/dist/mcp/httpProtocolRouting.js +22 -0
  65. package/dist/mcp/localCliHealth.d.ts +2 -2
  66. package/dist/mcp/localCliHealth.js +2 -2
  67. package/dist/mcp/localServiceProxy.d.ts +1 -0
  68. package/dist/mcp/localServiceProxy.js +530 -68
  69. package/dist/mcp/planningAttachmentCommandAdapter.d.ts +3 -1
  70. package/dist/mcp/planningAttachmentCommandAdapter.js +20 -2
  71. package/dist/mcp/runtime.d.ts +54 -79
  72. package/dist/mcp/runtime.js +408 -102
  73. package/dist/mcp/taskPlanningRegistrar.js +25 -6
  74. package/dist/mcp/toolProfiles.d.ts +2 -0
  75. package/dist/mcp/toolProfiles.js +11 -0
  76. package/dist/mcp/toolRegistry.d.ts +1 -0
  77. package/dist/mcp/toolRegistry.js +9 -8
  78. package/dist/mcp/workflowExecutionRegistrar.js +4 -4
  79. package/dist/migrations/taskSchemaMigrations.d.ts +5 -0
  80. package/dist/migrations/taskSchemaMigrations.js +415 -0
  81. package/dist/runtime/appGates.d.ts +2 -1
  82. package/dist/runtime/appGates.js +7 -0
  83. package/dist/server/buildInfo.d.ts +1 -0
  84. package/dist/server/buildInfo.js +5 -1
  85. package/dist/server/cloudMcpCapacityTelemetry.d.ts +68 -0
  86. package/dist/server/cloudMcpCapacityTelemetry.js +221 -0
  87. package/dist/server/index.d.ts +3 -0
  88. package/dist/server/index.js +108 -11
  89. package/dist/server/localDatabaseIdentity.js +4 -1
  90. package/dist/server/localServiceLease.js +2 -1
  91. package/dist/server/localServiceSessions.d.ts +14 -17
  92. package/dist/server/localServiceSessions.js +308 -94
  93. package/dist/server/localWorkspaceSyncServerRuntime.js +25 -19
  94. package/dist/server/routes/admin.d.ts +4 -0
  95. package/dist/server/routes/admin.js +126 -5
  96. package/dist/server/routes/agents.d.ts +7 -0
  97. package/dist/server/routes/agents.js +277 -24
  98. package/dist/server/routes/billing.js +5 -1
  99. package/dist/server/routes/durableTaskHttpRouters.d.ts +2 -0
  100. package/dist/server/routes/executorPhaseAApprovals.d.ts +19 -0
  101. package/dist/server/routes/executorPhaseAApprovals.js +140 -0
  102. package/dist/server/routes/executorPhaseAIssuerRedemptions.d.ts +11 -0
  103. package/dist/server/routes/executorPhaseAIssuerRedemptions.js +24 -0
  104. package/dist/server/routes/githubReviewEvidence.d.ts +19 -0
  105. package/dist/server/routes/githubReviewEvidence.js +116 -0
  106. package/dist/server/routes/localService.d.ts +15 -4
  107. package/dist/server/routes/localService.js +136 -40
  108. package/dist/server/routes/modelConnections.d.ts +24 -0
  109. package/dist/server/routes/modelConnections.js +205 -0
  110. package/dist/server/routes/shared.d.ts +22 -0
  111. package/dist/server/routes/shared.js +298 -182
  112. package/dist/server/routes/sync.js +1 -0
  113. package/dist/server/routes/syncAuxRoutes.js +5 -1
  114. package/dist/server/routes/syncPushRoutes.d.ts +1 -0
  115. package/dist/server/routes/syncPushRoutes.js +1 -0
  116. package/dist/server/routes/syncV3FeedRoutes.js +10 -1
  117. package/dist/server/routes/syncV3OperationRoutes.js +35 -9
  118. package/dist/server/routes/tasks.js +21 -2
  119. package/dist/server/routes/workflows.js +9 -1
  120. package/dist/server/routes.js +59 -0
  121. package/dist/service/localServiceCli.d.ts +2 -2
  122. package/dist/service/localServiceCli.js +4 -3
  123. package/dist/services/codexAppServerModelGateway.d.ts +54 -5
  124. package/dist/services/codexAppServerModelGateway.js +246 -21
  125. package/dist/services/codexDeviceCodeLoginManager.d.ts +39 -0
  126. package/dist/services/codexDeviceCodeLoginManager.js +265 -0
  127. package/dist/services/codexModelProviderConnectionLifecycle.d.ts +8 -0
  128. package/dist/services/codexModelProviderConnectionLifecycle.js +73 -0
  129. package/dist/services/executorPhaseAApprovalRuntime.d.ts +14 -0
  130. package/dist/services/executorPhaseAApprovalRuntime.js +24 -0
  131. package/dist/services/executorPhaseAApprovalService.d.ts +40 -0
  132. package/dist/services/executorPhaseAApprovalService.js +609 -0
  133. package/dist/services/executorPhaseADriftEvaluator.d.ts +78 -0
  134. package/dist/services/executorPhaseADriftEvaluator.js +93 -0
  135. package/dist/services/executorPhaseAIssuerCore.d.ts +139 -0
  136. package/dist/services/executorPhaseAIssuerCore.js +402 -0
  137. package/dist/services/executorPhaseAIssuerRedemptionService.d.ts +34 -0
  138. package/dist/services/executorPhaseAIssuerRedemptionService.js +158 -0
  139. package/dist/services/githubReviewEvidenceRuntime.d.ts +14 -0
  140. package/dist/services/githubReviewEvidenceRuntime.js +30 -0
  141. package/dist/services/githubReviewEvidenceService.d.ts +93 -0
  142. package/dist/services/githubReviewEvidenceService.js +336 -0
  143. package/dist/services/modelGateway.d.ts +7 -0
  144. package/dist/services/modelProviderConnectionService.d.ts +71 -0
  145. package/dist/services/modelProviderConnectionService.js +279 -0
  146. package/dist/services/modelProviderCredentialHome.d.ts +32 -0
  147. package/dist/services/modelProviderCredentialHome.js +271 -0
  148. package/dist/services/ownerScopedModelConnectionGateway.d.ts +12 -0
  149. package/dist/services/ownerScopedModelConnectionGateway.js +30 -0
  150. package/dist/services/taskforceAgentConnectionBindingService.d.ts +66 -0
  151. package/dist/services/taskforceAgentConnectionBindingService.js +185 -0
  152. package/dist/services/taskforceAgentMcpBridge.d.ts +2 -2
  153. package/dist/services/taskforceAgentMcpBridge.js +42 -29
  154. package/dist/shared/adminEdgeProxy.d.ts +5 -0
  155. package/dist/shared/adminEdgeProxy.js +94 -0
  156. package/dist/shared/adminProxySessionCookies.d.ts +16 -0
  157. package/dist/shared/adminProxySessionCookies.js +86 -0
  158. package/dist/shared/aiProfileColors.d.ts +31 -1
  159. package/dist/shared/aiProfileColors.js +14 -6
  160. package/dist/shared/executorPhaseAApprovalGoldenVector.json +269 -0
  161. package/dist/shared/executorPhaseAApprovalReceipt.d.ts +112 -0
  162. package/dist/shared/executorPhaseAApprovalReceipt.js +58 -0
  163. package/dist/shared/executorPhaseAApprovalTrustPolicy.json +10 -0
  164. package/dist/shared/executorPhaseADriftContracts.d.ts +37 -0
  165. package/dist/shared/executorPhaseADriftContracts.js +63 -0
  166. package/dist/shared/executorPhaseAIssuerContracts.d.ts +75 -0
  167. package/dist/shared/executorPhaseAIssuerContracts.js +90 -0
  168. package/dist/shared/executorPhaseARunAuthorization.d.ts +120 -0
  169. package/dist/shared/executorPhaseARunAuthorization.js +232 -0
  170. package/dist/shared/executorPhaseASchemaValidation.d.ts +7 -0
  171. package/dist/shared/executorPhaseASchemaValidation.js +53 -0
  172. package/dist/shared/executorPhaseASchemas/approval-receipt.schema.json +106 -0
  173. package/dist/shared/executorPhaseASchemas/drift-attestation.schema.json +54 -0
  174. package/dist/shared/executorPhaseASchemas/drift-request.schema.json +47 -0
  175. package/dist/shared/executorPhaseASchemas/foundation-manifest.schema.json +29 -0
  176. package/dist/shared/executorPhaseASchemas/issuer-audit-record.schema.json +24 -0
  177. package/dist/shared/executorPhaseASchemas/issuer-proof.schema.json +43 -0
  178. package/dist/shared/executorPhaseASchemas/issuer-redemption-request.schema.json +18 -0
  179. package/dist/shared/executorPhaseASchemas/issuer-redemption-response.schema.json +39 -0
  180. package/dist/shared/executorPhaseASchemas/logical-envelope.schema.json +149 -0
  181. package/dist/shared/executorPhaseASchemas/preflight-report.schema.json +216 -0
  182. package/dist/shared/executorPhaseASchemas/run-capability.schema.json +111 -0
  183. package/dist/shared/executorPhaseASchemas/sender-proof.schema.json +37 -0
  184. package/dist/shared/executorPhaseASchemas/workload-grant.schema.json +68 -0
  185. package/dist/shared/executorPhaseASchemas/workload-jwt-claims.schema.json +67 -0
  186. package/dist/shared/executorPhaseATiming.d.ts +1 -0
  187. package/dist/shared/executorPhaseATiming.js +1 -0
  188. package/dist/shared/planningIdentity.js +1 -1
  189. package/dist/shared/productLogoKeys.d.ts +2 -0
  190. package/dist/shared/productLogoKeys.js +18 -0
  191. package/dist/shared/taskforceAgentDefinition.d.ts +0 -1
  192. package/dist/shared/taskforceAgentDefinition.js +6 -9
  193. package/dist/shared/taskforceAgentModels.js +7 -3
  194. package/dist/shared/userFeatureGrants.d.ts +4 -0
  195. package/dist/shared/userFeatureGrants.js +7 -0
  196. package/dist/storage/executorPhaseAApprovalReceiptStore.d.ts +37 -0
  197. package/dist/storage/executorPhaseAApprovalReceiptStore.js +81 -0
  198. package/dist/storage/executorPhaseARunAuthorizationStore.d.ts +103 -0
  199. package/dist/storage/executorPhaseARunAuthorizationStore.js +492 -0
  200. package/dist/storage/githubReviewEvidenceInstallationStore.d.ts +26 -0
  201. package/dist/storage/githubReviewEvidenceInstallationStore.js +89 -0
  202. package/dist/storage/modelProviderConnectionStore.d.ts +99 -0
  203. package/dist/storage/modelProviderConnectionStore.js +446 -0
  204. package/dist/storage/postgresAdapter.d.ts +4 -0
  205. package/dist/storage/postgresAdapter.js +14 -1
  206. package/dist/storage/postgresRequestDiagnostics.d.ts +9 -1
  207. package/dist/storage/postgresRequestDiagnostics.js +15 -2
  208. package/dist/storage/postgresWorker.js +20 -2
  209. package/dist/storage/postgresWorkerProtocol.d.ts +7 -0
  210. package/dist/storage/taskforceAgentConnectionBindingStore.d.ts +31 -0
  211. package/dist/storage/taskforceAgentConnectionBindingStore.js +84 -0
  212. package/dist/storage/workflowStore.d.ts +2 -0
  213. package/dist/storage/workflowStore.js +39 -2
  214. package/dist/sync/cloudSyncApi.js +4 -2
  215. package/dist/sync/collaborationSyncState.js +5 -0
  216. package/dist/sync/coordinator/localSyncExecutionPermitStore.js +60 -29
  217. package/dist/sync/coordinator/localWorkspaceSyncPendingV2PushProgress.d.ts +10 -0
  218. package/dist/sync/coordinator/localWorkspaceSyncPendingV2PushProgress.js +29 -0
  219. package/dist/sync/coordinator/localWorkspaceSyncRunner.d.ts +3 -1
  220. package/dist/sync/coordinator/localWorkspaceSyncRunner.js +18 -0
  221. package/dist/sync/coordinator/localWorkspaceSyncRunnerState.d.ts +15 -1
  222. package/dist/sync/coordinator/localWorkspaceSyncRunnerState.js +99 -2
  223. package/dist/sync/coordinator/workspaceSyncCredentialBroker.d.ts +1 -0
  224. package/dist/sync/coordinator/workspaceSyncCredentialBroker.js +33 -4
  225. package/dist/sync/engine/workspaceSyncContentLifecycleAdapter.d.ts +2 -1
  226. package/dist/sync/engine/workspaceSyncContentVersionStore.d.ts +38 -0
  227. package/dist/sync/engine/workspaceSyncContentVersionStore.js +50 -1
  228. package/dist/sync/engine/workspaceSyncEngineLifecyclePolicy.js +6 -6
  229. package/dist/sync/engine/workspaceSyncEnginePushCompletion.d.ts +14 -0
  230. package/dist/sync/engine/workspaceSyncEnginePushCompletion.js +84 -0
  231. package/dist/sync/engine/workspaceSyncEngineRecovery.js +1 -0
  232. package/dist/sync/engine/workspaceSyncEngineRuntime.d.ts +1 -0
  233. package/dist/sync/engine/workspaceSyncEngineRuntime.js +1 -0
  234. package/dist/sync/engine/workspaceSyncEngineServerRunnerOperations.js +112 -38
  235. package/dist/sync/engine/workspaceSyncEngineServerSnapshotReader.js +6 -0
  236. package/dist/sync/engine/workspaceSyncEngineTransfers.js +3 -1
  237. package/dist/sync/engine/workspaceSyncV2ChangeDispatcher.d.ts +1 -0
  238. package/dist/sync/engine/workspaceSyncV2ChangeDispatcher.js +31 -0
  239. package/dist/sync/syncApplyHandlers.d.ts +3 -0
  240. package/dist/sync/syncApplyHandlers.js +81 -15
  241. package/dist/sync/syncService.d.ts +15 -0
  242. package/dist/sync/syncService.js +83 -18
  243. package/dist/sync/taskforceAgentSyncAuthorization.d.ts +16 -0
  244. package/dist/sync/taskforceAgentSyncAuthorization.js +20 -0
  245. package/dist/sync/v3/combinedFeedCapability.js +4 -0
  246. package/dist/sync/v3/durableInitiativeMutationRouter.js +18 -10
  247. package/dist/sync/v3/durableOperationReplay.d.ts +14 -0
  248. package/dist/sync/v3/durableOperationReplay.js +18 -0
  249. package/dist/sync/v3/durableTaskAttachmentLinksMutationRouter.js +3 -0
  250. package/dist/sync/v3/durableTaskChecklistMutationRouter.d.ts +2 -1
  251. package/dist/sync/v3/durableTaskChecklistMutationRouter.js +58 -15
  252. package/dist/sync/v3/durableTaskCommentMutationRouter.js +3 -0
  253. package/dist/sync/v3/durableTaskHttpRootMutationRouter.d.ts +1 -1
  254. package/dist/sync/v3/durableTaskHttpRootMutationRouter.js +10 -0
  255. package/dist/sync/v3/durableTaxonomyMutationRouter.js +5 -0
  256. package/dist/sync/v3/durableWorkflowRuntimeMutationRouter.d.ts +18 -7
  257. package/dist/sync/v3/durableWorkflowRuntimeMutationRouter.js +89 -23
  258. package/dist/sync/v3/durableWorkstreamMutationRouter.js +18 -10
  259. package/dist/sync/v3/durableWorkstreamTaskOrderMutationRouter.js +16 -5
  260. package/dist/sync/v3/localOutboxDispatchRuntime.js +2 -2
  261. package/dist/sync/v3/localOutboxRecoveryPreparationService.js +8 -2
  262. package/dist/sync/v3/localTaskChecklistOutboxHandler.js +16 -2
  263. package/dist/sync/v3/localTaskChecklistOutboxService.d.ts +4 -0
  264. package/dist/sync/v3/localTaskChecklistOutboxService.js +14 -1
  265. package/dist/sync/v3/localTaskCreateOutboxService.d.ts +3 -1
  266. package/dist/sync/v3/localTaskCreateOutboxService.js +6 -1
  267. package/dist/sync/v3/localTaskDeleteOutboxService.js +1 -0
  268. package/dist/sync/v3/localTaskLifecycleOutboxService.d.ts +2 -1
  269. package/dist/sync/v3/localTaskLifecycleOutboxService.js +5 -1
  270. package/dist/sync/v3/localTaskMetadataOutboxService.d.ts +2 -1
  271. package/dist/sync/v3/localTaskMetadataOutboxService.js +6 -2
  272. package/dist/sync/v3/localTaskStatusOutboxService.d.ts +10 -1
  273. package/dist/sync/v3/localTaskStatusOutboxService.js +238 -16
  274. package/dist/sync/v3/syncDurabilityStore.d.ts +36 -1
  275. package/dist/sync/v3/syncDurabilityStore.js +202 -8
  276. package/dist/sync/v3/taskChecklistMutationService.d.ts +11 -0
  277. package/dist/sync/v3/taskChecklistMutationService.js +44 -1
  278. package/dist/sync/v3/taskStatusMutationService.d.ts +29 -1
  279. package/dist/sync/v3/taskStatusMutationService.js +119 -3
  280. package/dist/sync/v3/workflowAssignmentSync.d.ts +5 -0
  281. package/dist/sync/v3/workflowAssignmentSync.js +27 -0
  282. package/dist/sync/v3/workflowRuntimeMutationService.d.ts +5 -0
  283. package/dist/sync/v3/workflowRuntimeMutationService.js +124 -71
  284. package/dist/sync/v3/workspaceSyncJournalReader.js +1 -1
  285. package/dist/sync/v3/workspaceSyncOperationRetentionService.d.ts +16 -0
  286. package/dist/sync/v3/workspaceSyncOperationRetentionService.js +83 -0
  287. package/dist/sync/v3/workspaceSyncV3CloudOperationHandler.d.ts +1 -0
  288. package/dist/sync/v3/workspaceSyncV3CloudOperationHandler.js +9 -2
  289. package/dist/sync/v3/workspaceSyncV3CombinedLocalApply.js +25 -3
  290. package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.d.ts +7 -0
  291. package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.js +44 -32
  292. package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.d.ts +9 -5
  293. package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.js +54 -38
  294. package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.d.ts +10 -0
  295. package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.js +70 -31
  296. package/dist/sync/v3/workspaceSyncV3CombinedWireContract.d.ts +2 -1
  297. package/dist/sync/v3/workspaceSyncV3CombinedWireContract.js +16 -0
  298. package/dist/sync/v3/workspaceSyncV3CoverageRegistry.js +6 -0
  299. package/dist/sync/v3/workspaceSyncV3Feed.d.ts +1 -0
  300. package/dist/sync/v3/workspaceSyncV3Feed.js +6 -1
  301. package/dist/sync/v3/workspaceSyncV3NestedTaskProjection.d.ts +2 -0
  302. package/dist/sync/v3/workspaceSyncV3NestedTaskProjection.js +49 -18
  303. package/dist/sync/v3/workspaceSyncV3OperationProtocol.d.ts +3 -0
  304. package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.d.ts +5 -0
  305. package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.js +36 -2
  306. package/dist/sync/v3/workspaceSyncV3RepairSnapshotRetentionService.d.ts +17 -0
  307. package/dist/sync/v3/workspaceSyncV3RepairSnapshotRetentionService.js +64 -0
  308. package/dist/sync/v3/workspaceSyncV3WorkflowRuntimeApply.d.ts +1 -0
  309. package/dist/sync/v3/workspaceSyncV3WorkflowRuntimeApply.js +50 -5
  310. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverCoverage.d.ts +7 -0
  311. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverCoverage.js +33 -0
  312. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverWireContract.d.ts +7 -0
  313. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverWireContract.js +8 -0
  314. package/dist/sync/workspaceRepair.d.ts +5 -2
  315. package/dist/sync/workspaceRepair.js +161 -6
  316. package/dist/sync/workspaceSyncModel.d.ts +21 -0
  317. package/dist/sync/workspaceSyncModel.js +35 -7
  318. package/dist/sync/workspaceSyncState.d.ts +1 -0
  319. package/dist/sync/workspaceSyncV2SnapshotBuilder.d.ts +6 -0
  320. package/dist/sync/workspaceSyncV2SnapshotBuilder.js +5 -0
  321. package/dist/ui/assets/AiIdentityRosterCard-CDMPtnbC.js +1 -0
  322. package/dist/ui/assets/AiProfilesModule-Cww85C4E.js +1 -0
  323. package/dist/ui/assets/{AnnotatedAttachmentWorkspace-B68Wg-RV.js → AnnotatedAttachmentWorkspace-Dt9TKYSH.js} +1 -1
  324. package/dist/ui/assets/{AssetTraySortControl-C8Rztyal.js → AssetTraySortControl-CKgapnxu.js} +1 -1
  325. package/dist/ui/assets/{ContextAttachmentManager-Cj3c7X9y.js → ContextAttachmentManager-T-cEVcOZ.js} +2 -2
  326. package/dist/ui/assets/{DocumentWorkspace-B5uvzems.js → DocumentWorkspace-HD4MUjAZ.js} +1 -1
  327. package/dist/ui/assets/{EntityActivityTimeline-BVFvCB5R.js → EntityActivityTimeline-_V0zfMuh.js} +1 -1
  328. package/dist/ui/assets/PlanningModule-mTkBygsB.js +1 -0
  329. package/dist/ui/assets/{PlansPage-AY4cGWco.js → PlansPage-Btiq06VO.js} +1 -1
  330. package/dist/ui/assets/{TaskContextUpload-DZxTVesW.js → TaskContextUpload-C00NVUpn.js} +1 -1
  331. package/dist/ui/assets/TaskSettings-Cp-L-4xh.js +12 -0
  332. package/dist/ui/assets/TaskforceAgentsModule-Coq9-PUp.js +24 -0
  333. package/dist/ui/assets/TaskforceAgentsModule-b-8R25cJ.css +1 -0
  334. package/dist/ui/assets/{WorkflowManagerModule-DEr5di_r.js → WorkflowManagerModule-CuqRzMmM.js} +1 -1
  335. package/dist/ui/assets/index-BZ-hdZSk.css +1 -0
  336. package/dist/ui/assets/index-DSQINwt9.js +7 -0
  337. package/dist/ui/assets/{vendor-icons-D9Lpw-j4.js → vendor-icons-Bsq-mcEn.js} +1 -1
  338. package/dist/ui/branding/logos/letterhead_dark.png +0 -0
  339. package/dist/ui/branding/logos/letterhead_light.png +0 -0
  340. package/dist/ui/branding/logos/signature_dark.png +0 -0
  341. package/dist/ui/branding/logos/signature_light.png +0 -0
  342. package/dist/ui/index.html +3 -3
  343. package/dist/utils/aiProfileDefaultLogo.js +16 -48
  344. package/dist/utils/httpSetCookie.d.ts +1 -0
  345. package/dist/utils/httpSetCookie.js +4 -1
  346. package/dist/utils/localRuntimeUrl.d.ts +1 -0
  347. package/dist/utils/localRuntimeUrl.js +14 -0
  348. package/dist/utils/productLogoRegistry.d.ts +2 -0
  349. package/dist/utils/productLogoRegistry.js +36 -0
  350. package/dist/utils/syncStatusPresentation.d.ts +4 -0
  351. package/dist/utils/syncStatusPresentation.js +17 -0
  352. package/dist/utils/taskEvents.d.ts +2 -0
  353. package/dist/utils/workspaceSyncPresentation.d.ts +1 -1
  354. package/dist/utils/workspaceSyncPresentation.js +23 -17
  355. package/package.json +24 -4
  356. package/dist/ui/assets/AiIdentityRosterCard-BZM4aQnM.js +0 -1
  357. package/dist/ui/assets/AiProfilesModule-BbAEWtHH.js +0 -1
  358. package/dist/ui/assets/PlanningModule-B5DWQOGz.js +0 -1
  359. package/dist/ui/assets/TaskSettings-BeWAuyZj.js +0 -12
  360. package/dist/ui/assets/TaskforceAgentsModule-BifCYtjR.js +0 -21
  361. package/dist/ui/assets/TaskforceAgentsModule-D6IC0S7Q.css +0 -1
  362. package/dist/ui/assets/index-I5zhdtgt.js +0 -7
  363. package/dist/ui/assets/index-VRFsx3wz.css +0 -1
@@ -11,6 +11,7 @@ import { WorkspaceSyncJournalReader } from './workspaceSyncJournalReader.js';
11
11
  import { isLegacyEntityEventAdoptionIdentity, LEGACY_ENTITY_EVENT_ADOPTION_MAX_PAYLOAD_BYTES, } from './entityEventLegacyAdoptionContract.js';
12
12
  import { validateWorkspaceSyncV3EntityEventPayload } from './workspaceSyncV3NestedTaskCodecs.js';
13
13
  import { fingerprintWorkspaceSyncPayload } from './workspaceSyncPayloadFingerprint.js';
14
+ import { assertDurableOperationFingerprint, assertDurableOperationIdentity, DurableOperationReplayIdentityConflictError, } from './durableOperationReplay.js';
14
15
  export { canonicalWorkspaceSyncJson } from './canonicalWorkspaceSyncJson.js';
15
16
  export { fingerprintWorkspaceSyncPayload } from './workspaceSyncPayloadFingerprint.js';
16
17
  export const WORKSPACE_SYNC_CONTRACT_VERSION = 3;
@@ -26,6 +27,7 @@ const TASK_AGGREGATE_SUCCESSOR_MUTATIONS = new Map([
26
27
  const TASK_ROOT_SUCCESSOR_MUTATIONS = new Set([
27
28
  'metadata-update', 'set-status', 'archive', 'unarchive', 'complete', 'reopen',
28
29
  ]);
30
+ const TASK_TERMINAL_SUCCESSOR_MUTATIONS = new Set(['delete']);
29
31
  const TASK_CREATE_RECOVERY_ERROR_CODES = new Set([
30
32
  'TASK_CREATE_ID_CONFLICT',
31
33
  'WORKSPACE_SYNC_REVISION_CONFLICT',
@@ -794,12 +796,137 @@ export class WorkspaceSyncDurabilityStore {
794
796
  payload_json, payload_fingerprint, canonical_intent_json, status, attempt_count,
795
797
  initial_not_found_attempt_count,
796
798
  CAST(enqueue_sequence AS TEXT) AS enqueue_sequence,
797
- rebase_before_first_attempt, lease_owner, lease_expires_at
799
+ rebase_before_first_attempt, lease_owner, lease_expires_at,
800
+ last_error_code
798
801
  FROM workspace_sync_outbox
799
802
  WHERE tenant_id = ? AND workspace_id = ? AND client_id = ? AND operation_id = ?
800
803
  `).get(...operationParams(identity));
801
804
  return row ? this.mapOutboxRow(row) : null;
802
805
  }
806
+ assertOutboxOperationIdentity(record, expected) {
807
+ assertDurableOperationIdentity({
808
+ operationId: record.operationId,
809
+ domain: record.domain,
810
+ entityId: record.entityId,
811
+ mutationKind: record.mutationKind,
812
+ payloadFingerprint: record.payloadFingerprint,
813
+ }, {
814
+ operationId: record.operationId,
815
+ domain: expected.domain,
816
+ entityId: expected.entityId,
817
+ mutationKind: expected.mutationKind,
818
+ payloadFingerprint: expected.payloadFingerprint || record.payloadFingerprint,
819
+ });
820
+ }
821
+ readOutboxOperationLookup(identity) {
822
+ const row = this.db.prepare(`
823
+ SELECT status, authoritative_response_json, created_at,
824
+ mutation_kind, payload_fingerprint, domain, entity_id
825
+ FROM workspace_sync_outbox
826
+ WHERE tenant_id = ? AND workspace_id = ? AND client_id = ? AND operation_id = ?
827
+ LIMIT 1
828
+ `).get(...operationParams(identity));
829
+ if (!row)
830
+ return null;
831
+ return {
832
+ ...identity,
833
+ status: requireText(row.status, 'Outbox status'),
834
+ createdAt: requireIsoTimestamp(row.created_at, 'Outbox creation time'),
835
+ domain: requireText(row.domain, 'Outbox domain'),
836
+ entityId: requireText(row.entity_id, 'Outbox entity id'),
837
+ mutationKind: requireText(row.mutation_kind, 'Outbox mutation kind'),
838
+ payloadFingerprint: requireText(row.payload_fingerprint, 'Outbox payload fingerprint'),
839
+ authoritativeResponseJson: row.authoritative_response_json == null
840
+ ? null
841
+ : requireText(row.authoritative_response_json, 'Outbox authoritative response'),
842
+ };
843
+ }
844
+ pruneTerminalOutboxOperations(input) {
845
+ const tenantId = requireText(input.tenantId, 'Tenant id');
846
+ const workspaceId = requireText(input.workspaceId, 'Workspace id');
847
+ const terminalBefore = requireIsoTimestamp(input.terminalBefore, 'Operation retention cutoff');
848
+ const limit = Math.max(1, Math.min(1_000, Math.floor(input.limit ?? 100)));
849
+ const eligibility = `
850
+ candidate.tenant_id = ? AND candidate.workspace_id = ?
851
+ AND candidate.status IN ('accepted', 'superseded')
852
+ AND candidate.updated_at < ?
853
+ AND NOT EXISTS (
854
+ SELECT 1
855
+ FROM workspace_sync_outbox AS replay
856
+ WHERE replay.tenant_id = candidate.tenant_id
857
+ AND replay.workspace_id = candidate.workspace_id
858
+ AND replay.replay_of_client_id = candidate.client_id
859
+ AND replay.replay_of_operation_id = candidate.operation_id
860
+ )
861
+ `;
862
+ return this.db.transaction(() => {
863
+ const candidates = this.db.prepare(`
864
+ SELECT candidate.client_id, candidate.operation_id
865
+ FROM workspace_sync_outbox AS candidate
866
+ WHERE ${eligibility}
867
+ ORDER BY candidate.updated_at, candidate.client_id, candidate.operation_id
868
+ LIMIT ?
869
+ `).all(tenantId, workspaceId, terminalBefore, limit);
870
+ let deleted = 0;
871
+ for (const candidate of candidates) {
872
+ const clientId = requireText(candidate.client_id, 'Retention client id');
873
+ const operationId = requireText(candidate.operation_id, 'Retention operation id');
874
+ const result = this.db.prepare(`
875
+ DELETE FROM workspace_sync_outbox AS candidate
876
+ WHERE ${eligibility}
877
+ AND candidate.client_id = ? AND candidate.operation_id = ?
878
+ `).run(tenantId, workspaceId, terminalBefore, clientId, operationId);
879
+ if (Number(result.changes || 0) !== 1)
880
+ continue;
881
+ this.db.prepare(`
882
+ DELETE FROM workspace_sync_outbox_targets
883
+ WHERE tenant_id = ? AND workspace_id = ? AND client_id = ? AND operation_id = ?
884
+ `).run(tenantId, workspaceId, clientId, operationId);
885
+ deleted += 1;
886
+ }
887
+ const remaining = this.db.prepare(`
888
+ SELECT COUNT(*) AS count
889
+ FROM workspace_sync_outbox AS candidate
890
+ WHERE ${eligibility}
891
+ `).get(tenantId, workspaceId, terminalBefore);
892
+ return { deleted, remainingEligible: Number(remaining?.count || 0) };
893
+ })();
894
+ }
895
+ pruneCommittedOperationResults(input) {
896
+ const tenantId = requireText(input.tenantId, 'Tenant id');
897
+ const workspaceId = requireText(input.workspaceId, 'Workspace id');
898
+ const terminalBefore = requireIsoTimestamp(input.terminalBefore, 'Operation retention cutoff');
899
+ const limit = Math.max(1, Math.min(1_000, Math.floor(input.limit ?? 100)));
900
+ return this.db.transaction(() => {
901
+ const candidates = this.db.prepare(`
902
+ SELECT client_id, operation_id
903
+ FROM workspace_sync_operation_results
904
+ WHERE tenant_id = ? AND workspace_id = ?
905
+ AND status = 'committed' AND updated_at < ?
906
+ ORDER BY updated_at, client_id, operation_id
907
+ LIMIT ?
908
+ `).all(tenantId, workspaceId, terminalBefore, limit);
909
+ let deleted = 0;
910
+ for (const candidate of candidates) {
911
+ const clientId = requireText(candidate.client_id, 'Retention client id');
912
+ const operationId = requireText(candidate.operation_id, 'Retention operation id');
913
+ const result = this.db.prepare(`
914
+ DELETE FROM workspace_sync_operation_results
915
+ WHERE tenant_id = ? AND workspace_id = ?
916
+ AND client_id = ? AND operation_id = ?
917
+ AND status = 'committed' AND updated_at < ?
918
+ `).run(tenantId, workspaceId, clientId, operationId, terminalBefore);
919
+ deleted += Number(result.changes || 0);
920
+ }
921
+ const remaining = this.db.prepare(`
922
+ SELECT COUNT(*) AS count
923
+ FROM workspace_sync_operation_results
924
+ WHERE tenant_id = ? AND workspace_id = ?
925
+ AND status = 'committed' AND updated_at < ?
926
+ `).get(tenantId, workspaceId, terminalBefore);
927
+ return { deleted, remainingEligible: Number(remaining?.count || 0) };
928
+ })();
929
+ }
803
930
  readV3DispatchSettlementEvidence(identity) {
804
931
  const row = this.db.prepare(`
805
932
  SELECT outbox.status, outbox.authoritative_response_json,
@@ -1218,6 +1345,17 @@ export class WorkspaceSyncDurabilityStore {
1218
1345
  }
1219
1346
  }
1220
1347
  }
1348
+ else if (input.replayPolicy === 'authoritative-workflow-runtime') {
1349
+ if (selected.length !== 1) {
1350
+ throw new Error('Workflow runtime recovery has intersecting intent that requires semantic history reconciliation.');
1351
+ }
1352
+ const candidate = selected[0];
1353
+ if (candidate.domain !== 'workflow-execution'
1354
+ || candidate.mutation_kind !== 'complete-step'
1355
+ || candidate.last_error_code !== 'WORKFLOW_RUNTIME_SEMANTIC_REPLAY_REQUIRED') {
1356
+ throw new Error('Workflow runtime recovery requires an exact authoritative semantic replay conflict.');
1357
+ }
1358
+ }
1221
1359
  this.db.prepare(`
1222
1360
  INSERT INTO workspace_sync_outbox_recoveries (
1223
1361
  tenant_id, workspace_id, recovery_batch_id,
@@ -1486,6 +1624,11 @@ export class WorkspaceSyncDurabilityStore {
1486
1624
  }
1487
1625
  }
1488
1626
  const sources = recoverySources.filter((source) => {
1627
+ if (source.domain === 'workflow-execution'
1628
+ && source.mutation_kind === 'complete-step'
1629
+ && source.last_error_code === 'WORKFLOW_RUNTIME_SEMANTIC_REPLAY_REQUIRED') {
1630
+ return false;
1631
+ }
1489
1632
  if (source.domain === 'task-comments' && source.mutation_kind === 'append') {
1490
1633
  return !this.isTaskCommentAppendRecoveryIntentSatisfied(tenantId, workspaceId, source);
1491
1634
  }
@@ -2457,9 +2600,21 @@ export class WorkspaceSyncDurabilityStore {
2457
2600
  })()
2458
2601
  : null;
2459
2602
  const taskAggregateRootTarget = additionalTargets[0];
2603
+ const queueableTaskReviewHandoff = domain === 'task'
2604
+ && mutationKind === 'set-status'
2605
+ && additionalTargets.length === 1
2606
+ && taskAggregateRootTarget.domain === 'task-comments'
2607
+ && taskAggregateRootTarget.entityId === entityId
2608
+ && taskAggregateRootTarget.mutationKind === 'append';
2460
2609
  const queueableTaskRoot = domain === 'task'
2461
2610
  && TASK_ROOT_SUCCESSOR_MUTATIONS.has(mutationKind)
2462
- && additionalTargets.length === 0;
2611
+ && (additionalTargets.length === 0 || queueableTaskReviewHandoff);
2612
+ const queueableTaskDelete = domain === 'task'
2613
+ && TASK_TERMINAL_SUCCESSOR_MUTATIONS.has(mutationKind)
2614
+ && additionalTargets.length === 0
2615
+ && ownsTaskMetadata
2616
+ && ownsTaskLifecycle
2617
+ && !ownsTaskAssignee;
2463
2618
  const queueableTaskAggregate = Boolean(TASK_AGGREGATE_SUCCESSOR_MUTATIONS.get(domain)?.has(mutationKind))
2464
2619
  && ((domain === 'task-comments' && mutationKind === 'reconcile' && additionalTargets.length === 0)
2465
2620
  || (additionalTargets.length === 1
@@ -2470,7 +2625,8 @@ export class WorkspaceSyncDurabilityStore {
2470
2625
  && !taskAggregateRootTarget.ownsTaskLifecycle
2471
2626
  && !taskAggregateRootTarget.ownsTaskAssignee))
2472
2627
  && !ownsTaskMetadata && !ownsTaskLifecycle && !ownsTaskAssignee;
2473
- if (queuedTaskSuccessor && (input.revisionSource !== 'current' || (!queueableTaskRoot && !queueableTaskAggregate))) {
2628
+ if (queuedTaskSuccessor && (input.revisionSource !== 'current'
2629
+ || (!queueableTaskRoot && !queueableTaskDelete && !queueableTaskAggregate))) {
2474
2630
  throw new Error('Queued task successors require a recognized task root or aggregate operation.');
2475
2631
  }
2476
2632
  const additionalTargetKeys = new Set();
@@ -2682,11 +2838,13 @@ export class WorkspaceSyncDurabilityStore {
2682
2838
  const isTaskRoot = activeDomain === 'task'
2683
2839
  && row.entity_id === entityId
2684
2840
  && (TASK_ROOT_SUCCESSOR_MUTATIONS.has(activeMutationKind)
2685
- || (queueableTaskAggregate && activeMutationKind === 'create'))
2841
+ || (activeMutationKind === 'create'
2842
+ && Number(row.owns_task_metadata) === 0
2843
+ && Number(row.owns_task_lifecycle) === 0
2844
+ && Number(row.owns_task_assignee) === 0))
2686
2845
  && Number(row.target_count) === 1;
2687
- return isTaskRoot
2688
- || isCompatibleTaskAggregate(row)
2689
- || isCompatibleWorkflowRuntimeAggregate(row);
2846
+ return isTaskRoot || (!queueableTaskDelete && (isCompatibleTaskAggregate(row)
2847
+ || isCompatibleWorkflowRuntimeAggregate(row)));
2690
2848
  });
2691
2849
  const compatibleWorkflowRuntimeSuccessor = queuedWorkflowRuntimeSuccessor
2692
2850
  && active.every((row) => (row.domain === 'workflow-execution'
@@ -2786,6 +2944,32 @@ export class WorkspaceSyncDurabilityStore {
2786
2944
  FROM workspace_sync_outbox
2787
2945
  WHERE tenant_id = ? AND workspace_id = ? AND client_id = ? AND operation_id = ?
2788
2946
  `).get(...ids);
2947
+ if (existing) {
2948
+ try {
2949
+ const existingPayloadFingerprint = String(existing.payload_fingerprint || '');
2950
+ assertDurableOperationIdentity({
2951
+ operationId: ids[3],
2952
+ domain: String(existing.domain || ''),
2953
+ entityId: String(existing.entity_id || ''),
2954
+ mutationKind: String(existing.mutation_kind || ''),
2955
+ payloadFingerprint: existingPayloadFingerprint,
2956
+ }, {
2957
+ operationId: ids[3],
2958
+ domain,
2959
+ entityId,
2960
+ mutationKind,
2961
+ payloadFingerprint: existingPayloadFingerprint === coalescedWorkflowPayloadFingerprint
2962
+ ? coalescedWorkflowPayloadFingerprint
2963
+ : payloadFingerprint,
2964
+ });
2965
+ }
2966
+ catch (error) {
2967
+ if (error instanceof DurableOperationReplayIdentityConflictError) {
2968
+ throw new WorkspaceSyncIdempotencyConflictError();
2969
+ }
2970
+ throw error;
2971
+ }
2972
+ }
2789
2973
  const matches = existing
2790
2974
  && Number(existing.contract_version) === WORKSPACE_SYNC_CONTRACT_VERSION
2791
2975
  && existing.dispatch_class === dispatchClass
@@ -4715,9 +4899,18 @@ export class WorkspaceSyncDurabilityStore {
4715
4899
  assertMatchingOperation(row, requestFingerprint) {
4716
4900
  if (!row)
4717
4901
  throw new Error('Workspace sync operation does not exist.');
4718
- if (Number(row.contract_version) !== WORKSPACE_SYNC_CONTRACT_VERSION || row.request_fingerprint !== requestFingerprint) {
4902
+ if (Number(row.contract_version) !== WORKSPACE_SYNC_CONTRACT_VERSION) {
4719
4903
  throw new WorkspaceSyncIdempotencyConflictError();
4720
4904
  }
4905
+ try {
4906
+ assertDurableOperationFingerprint(String(row.request_fingerprint || ''), requestFingerprint);
4907
+ }
4908
+ catch (error) {
4909
+ if (error instanceof DurableOperationReplayIdentityConflictError) {
4910
+ throw new WorkspaceSyncIdempotencyConflictError();
4911
+ }
4912
+ throw error;
4913
+ }
4721
4914
  }
4722
4915
  mapOutboxRow(row) {
4723
4916
  return {
@@ -4748,6 +4941,7 @@ export class WorkspaceSyncDurabilityStore {
4748
4941
  initiativeMetadataRevisionRebaseCount: Number(row.initiative_metadata_revision_rebase_count || 0),
4749
4942
  leaseOwner: row.lease_owner == null ? null : String(row.lease_owner),
4750
4943
  leaseExpiresAt: row.lease_expires_at == null ? null : String(row.lease_expires_at),
4944
+ lastErrorCode: row.last_error_code == null ? null : String(row.last_error_code),
4751
4945
  };
4752
4946
  }
4753
4947
  }
@@ -52,6 +52,16 @@ export type DurableTaskChecklistMutationResult = {
52
52
  responseJson: string;
53
53
  response: DurableTaskChecklistResponse;
54
54
  };
55
+ export type TaskChecklistItemUpdateIntent = {
56
+ kind: 'item-update';
57
+ itemId: string;
58
+ patch: {
59
+ text?: string;
60
+ done?: boolean;
61
+ order?: number;
62
+ };
63
+ };
64
+ export declare function validateTaskChecklistItemUpdateIntent(value: unknown): TaskChecklistItemUpdateIntent;
55
65
  export interface DurableTaskChecklistServiceCore {
56
66
  getTask(id: string, workspaceId?: string): TaskItem | null;
57
67
  updateTask(id: string, updates: Partial<TaskItem>, workspaceId?: string, options?: {
@@ -89,6 +99,7 @@ export declare function runDurableTaskChecklistReplace(input: {
89
99
  resolveActorRef?: () => string;
90
100
  originActorRef?: string;
91
101
  expectedDetailRevision?: string;
102
+ itemUpdateIntent?: TaskChecklistItemUpdateIntent;
92
103
  assertPrecondition?: () => void;
93
104
  onPostCommitError?: (error: unknown) => void;
94
105
  }): DurableTaskChecklistMutationResult;
@@ -22,6 +22,37 @@ export class DurableTaskChecklistMutationError extends Error {
22
22
  this.name = 'DurableTaskChecklistMutationError';
23
23
  }
24
24
  }
25
+ export function validateTaskChecklistItemUpdateIntent(value) {
26
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
27
+ throw new DurableTaskChecklistMutationError('Task checklist item update intent is invalid.', 'TASK_CHECKLIST_INVALID', 400);
28
+ }
29
+ const source = value;
30
+ const patch = source.patch;
31
+ if (source.kind !== 'item-update'
32
+ || Object.keys(source).some((key) => key !== 'kind' && key !== 'itemId' && key !== 'patch')
33
+ || typeof source.itemId !== 'string' || !source.itemId.trim()
34
+ || !patch || typeof patch !== 'object' || Array.isArray(patch)) {
35
+ throw new DurableTaskChecklistMutationError('Task checklist item update intent is invalid.', 'TASK_CHECKLIST_INVALID', 400);
36
+ }
37
+ const patchSource = patch;
38
+ if (Object.keys(patchSource).some((key) => key !== 'text' && key !== 'done' && key !== 'order')
39
+ || Object.keys(patchSource).length === 0
40
+ || (patchSource.text !== undefined && (typeof patchSource.text !== 'string' || !patchSource.text.trim()))
41
+ || (patchSource.done !== undefined && typeof patchSource.done !== 'boolean')
42
+ || (patchSource.order !== undefined
43
+ && (!Number.isInteger(patchSource.order) || Number(patchSource.order) < 0))) {
44
+ throw new DurableTaskChecklistMutationError('Task checklist item update intent is invalid.', 'TASK_CHECKLIST_INVALID', 400);
45
+ }
46
+ return {
47
+ kind: 'item-update',
48
+ itemId: source.itemId.trim(),
49
+ patch: {
50
+ ...(patchSource.text !== undefined ? { text: patchSource.text.trim() } : {}),
51
+ ...(patchSource.done !== undefined ? { done: patchSource.done } : {}),
52
+ ...(patchSource.order !== undefined ? { order: Number(patchSource.order) } : {}),
53
+ },
54
+ };
55
+ }
25
56
  function canonicalItems(taskId, items) {
26
57
  try {
27
58
  return serializeWorkspaceSyncV3TaskChecklistPayload({ taskId, items }).items;
@@ -46,6 +77,18 @@ function revision(revisions, domain) {
46
77
  }
47
78
  export function runDurableTaskChecklistReplace(input) {
48
79
  const items = canonicalItems(input.taskId, input.items);
80
+ const itemUpdateIntent = input.itemUpdateIntent
81
+ ? validateTaskChecklistItemUpdateIntent(input.itemUpdateIntent)
82
+ : undefined;
83
+ if (itemUpdateIntent) {
84
+ const target = items.find((item) => item.id === itemUpdateIntent.itemId);
85
+ if (!target
86
+ || (itemUpdateIntent.patch.text !== undefined && target.title !== itemUpdateIntent.patch.text)
87
+ || (itemUpdateIntent.patch.done !== undefined && target.isCompleted !== itemUpdateIntent.patch.done)
88
+ || (itemUpdateIntent.patch.order !== undefined && target.order !== itemUpdateIntent.patch.order)) {
89
+ throw new DurableTaskChecklistMutationError('Task checklist item update intent does not match the replacement aggregate.', 'TASK_CHECKLIST_INVALID', 400);
90
+ }
91
+ }
49
92
  const identity = {
50
93
  tenantId: input.tenantId, workspaceId: input.workspaceId, clientId: input.clientId, operationId: input.operationId,
51
94
  };
@@ -56,7 +99,7 @@ export function runDurableTaskChecklistReplace(input) {
56
99
  domain: 'task-checklist', entityId: input.taskId, mutationKind: 'replace',
57
100
  baseEntityRevision: String(input.baseEntityRevision),
58
101
  baseLifecycleRevision: String(input.baseLifecycleRevision),
59
- items,
102
+ ...(itemUpdateIntent ? { itemUpdateIntent } : { items }),
60
103
  ...(input.originActorRef ? { originActorRef: input.originActorRef } : {}),
61
104
  ...(input.expectedDetailRevision
62
105
  ? { expectedDetailRevision: input.expectedDetailRevision }
@@ -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,7 @@ export declare function runDurableTaskStatusMutation(input: {
64
91
  resolveActorRef?: () => string;
65
92
  originActorRef?: string;
66
93
  includeWorkflowRuntimeJournal?: boolean;
94
+ rejectWorkflowRuntimeActivation?: boolean;
67
95
  expectedDetailRevision?: string;
68
96
  assertPrecondition?: () => void;
69
97
  onPostCommitError?: (error: unknown) => void;
@@ -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({
@@ -48,10 +68,24 @@ export function runDurableTaskStatusMutation(input) {
48
68
  });
49
69
  const membershipRemovedEventId = `${activityEventId}:workstream-removed`;
50
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;
51
80
  const workflowStore = new WorkflowStore(input.core.getDatabaseAdapter(), input.tenantId);
52
81
  const workflowActivationService = new WorkflowTaskActivationService(workflowStore, (workspaceId) => input.core.listAssignableActors(workspaceId));
53
82
  const pendingAssignment = operationPayload.workflowAssignment
54
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
+ }
55
89
  const workflowStartEventId = buildWorkflowRuntimeEventId({
56
90
  workspaceId: input.workspaceId,
57
91
  clientId: input.clientId,
@@ -95,6 +129,16 @@ export function runDurableTaskStatusMutation(input) {
95
129
  throw new Error('Task status activity was not committed.');
96
130
  return activity;
97
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
+ };
98
142
  const workflowAssignmentAfterMutation = () => {
99
143
  const assignment = workflowStore.getAssignmentForTaskSync(input.workspaceId, input.taskId);
100
144
  if (!assignment || assignment.execution.id !== pendingAssignment?.execution.id) {
@@ -158,7 +202,22 @@ export function runDurableTaskStatusMutation(input) {
158
202
  reopenAssigneeOwned: (result) => result.assigneeOwned,
159
203
  buildCanonicalFingerprint: (result) => (fingerprintWorkspaceSyncPayload(serializeTaskForSync(result.task))),
160
204
  buildAuthoritativePayload: (result) => serializeTaskForSync(result.task),
161
- }, {
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
+ })] : []), {
162
221
  ...buildTaskActivityJournalEntry({ eventId: activityEventId, readEvent: readActivity }),
163
222
  include: (result) => !result.noOp,
164
223
  }, {
@@ -208,7 +267,7 @@ export function runDurableTaskStatusMutation(input) {
208
267
  })
209
268
  : null;
210
269
  const actorRef = resolveDeferredMutationActorRef(input);
211
- const result = applyTaskStatusMutationForDurableSync({
270
+ let result = applyTaskStatusMutationForDurableSync({
212
271
  core: input.core,
213
272
  workspaceId: input.workspaceId,
214
273
  taskId: input.taskId,
@@ -224,6 +283,42 @@ export function runDurableTaskStatusMutation(input) {
224
283
  actorRef,
225
284
  taskEventId: activityEventId,
226
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
+ }
227
322
  if (activation) {
228
323
  workflowActivationService.start({
229
324
  workspaceId: input.workspaceId,
@@ -261,6 +356,9 @@ export function runDurableTaskStatusMutation(input) {
261
356
  throw new Error('Dependent task status activity was not committed.');
262
357
  return event;
263
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;
264
362
  return {
265
363
  success: true,
266
364
  contractVersion: WORKSPACE_SYNC_CONTRACT_VERSION,
@@ -285,6 +383,24 @@ export function runDurableTaskStatusMutation(input) {
285
383
  activityRevision,
286
384
  ...(dependentActivities.length > 0 ? { dependentActivities } : {}),
287
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
+ } : {}),
288
404
  ...(workflowStore.getAssignmentForTaskSync(input.workspaceId, result.task.id)
289
405
  ? { workflowAssignment: workflowStore.getAssignmentForTaskSync(input.workspaceId, result.task.id) }
290
406
  : {}),
@@ -292,7 +408,7 @@ export function runDurableTaskStatusMutation(input) {
292
408
  },
293
409
  });
294
410
  const response = JSON.parse(accepted.responseJson);
295
- if (response.activity) {
411
+ if (response.activity || response.reviewHandoff) {
296
412
  try {
297
413
  input.core.notifyDurableTaskLifecycleCommitted(input.workspaceId, input.taskId);
298
414
  }
@@ -1,8 +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;
5
9
  expectedDetailRevision?: string;
10
+ reviewHandoff?: TaskStatusReviewHandoff;
6
11
  };
7
12
  export declare class WorkflowAssignmentSyncError extends Error {
8
13
  readonly code = "WORKFLOW_ASSIGNMENT_SYNC_INVALID";