@taskforcehq/taskforce 0.3.329 → 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 (321) hide show
  1. package/dist/Taskforce.module.css +290 -45
  2. package/dist/components/features/AiProfilesModule.js +3 -5
  3. package/dist/components/features/TaskSettings.js +70 -14
  4. package/dist/components/features/TaskforceAgentsModule.d.ts +1 -2
  5. package/dist/components/features/TaskforceAgentsModule.js +586 -116
  6. package/dist/components/features/agentConnections/AgentConnectionControl.d.ts +15 -0
  7. package/dist/components/features/agentConnections/AgentConnectionControl.js +125 -0
  8. package/dist/components/features/agentConnections/ModelConnectionsPanel.d.ts +18 -0
  9. package/dist/components/features/agentConnections/ModelConnectionsPanel.js +393 -0
  10. package/dist/components/features/agentConnections/modelConnectionsApi.d.ts +65 -0
  11. package/dist/components/features/agentConnections/modelConnectionsApi.js +129 -0
  12. package/dist/components/features/taskforceAgentAssignments/AgentBehaviorAssignments.js +15 -24
  13. package/dist/components/features/taskforceAgentEditorModel.d.ts +2 -1
  14. package/dist/components/features/taskforceAgentEditorModel.js +3 -1
  15. package/dist/components/features/workflowManager/workflowManagerApi.d.ts +1 -1
  16. package/dist/components/features/workflowManager/workflowManagerApi.js +3 -0
  17. package/dist/components/task/TaskWorkflowAssignmentField.js +68 -10
  18. package/dist/components/views/StandaloneLayout.js +27 -26
  19. package/dist/components/views/standalone/modals/SyncStatusModal.d.ts +4 -3
  20. package/dist/components/views/standalone/modals/SyncStatusModal.js +33 -38
  21. package/dist/config/envSchema.js +48 -1
  22. package/dist/core/McpTokenService.d.ts +23 -1
  23. package/dist/core/McpTokenService.js +93 -10
  24. package/dist/core/TaskChecklistCommandService.d.ts +27 -0
  25. package/dist/core/TaskChecklistCommandService.js +83 -5
  26. package/dist/core/TaskLifecycleCommandService.d.ts +3 -1
  27. package/dist/core/TaskLifecycleCommandService.js +6 -2
  28. package/dist/core/Taskforce.d.ts +32 -0
  29. package/dist/core/Taskforce.js +125 -4
  30. package/dist/core/types.d.ts +8 -0
  31. package/dist/documentReviews/commandService.d.ts +2 -1
  32. package/dist/documentReviews/commandService.js +6 -3
  33. package/dist/hooks/sync/orchestratorShared.d.ts +1 -0
  34. package/dist/hooks/sync/orchestratorShared.js +2 -0
  35. package/dist/hooks/sync/useLocalSyncCoordinatorSnapshot.d.ts +3 -0
  36. package/dist/hooks/sync/useLocalSyncCoordinatorSnapshot.js +85 -9
  37. package/dist/hooks/sync/useSyncStatusControls.d.ts +4 -1
  38. package/dist/hooks/sync/useSyncStatusControls.js +47 -11
  39. package/dist/hooks/useSyncOrchestrator.d.ts +3 -0
  40. package/dist/hooks/useSyncOrchestrator.js +111 -2
  41. package/dist/hooks/useTaskData.d.ts +31 -1
  42. package/dist/hooks/useTaskData.js +29 -7
  43. package/dist/hooks/useTaskMutations.d.ts +3 -1
  44. package/dist/hooks/useTaskMutations.js +46 -12
  45. package/dist/hooks/useTaskforce.d.ts +2 -0
  46. package/dist/hooks/useTaskforce.js +11 -2
  47. package/dist/mcp/clientRegistry.d.ts +2 -2
  48. package/dist/mcp/clientRegistry.js +1 -1
  49. package/dist/mcp/documentAssetRegistrar.js +9 -6
  50. package/dist/mcp/durableTaskMutationRouter.d.ts +4 -1
  51. package/dist/mcp/durableTaskMutationRouter.js +10 -0
  52. package/dist/mcp/durableTaskRelationshipMutationRouter.js +4 -0
  53. package/dist/mcp/httpProtocolRouting.d.ts +10 -0
  54. package/dist/mcp/httpProtocolRouting.js +19 -0
  55. package/dist/mcp/localCliHealth.d.ts +2 -2
  56. package/dist/mcp/localCliHealth.js +2 -2
  57. package/dist/mcp/localServiceProxy.d.ts +1 -0
  58. package/dist/mcp/localServiceProxy.js +530 -68
  59. package/dist/mcp/planningAttachmentCommandAdapter.d.ts +3 -1
  60. package/dist/mcp/planningAttachmentCommandAdapter.js +20 -2
  61. package/dist/mcp/runtime.d.ts +54 -79
  62. package/dist/mcp/runtime.js +384 -97
  63. package/dist/mcp/taskPlanningRegistrar.js +23 -4
  64. package/dist/mcp/toolProfiles.d.ts +2 -0
  65. package/dist/mcp/toolProfiles.js +10 -0
  66. package/dist/mcp/toolRegistry.d.ts +1 -0
  67. package/dist/mcp/toolRegistry.js +1 -0
  68. package/dist/mcp/workflowExecutionRegistrar.js +4 -4
  69. package/dist/migrations/taskSchemaMigrations.d.ts +5 -0
  70. package/dist/migrations/taskSchemaMigrations.js +415 -0
  71. package/dist/runtime/appGates.d.ts +2 -1
  72. package/dist/runtime/appGates.js +7 -0
  73. package/dist/server/index.d.ts +3 -0
  74. package/dist/server/index.js +108 -11
  75. package/dist/server/localDatabaseIdentity.js +4 -1
  76. package/dist/server/localServiceLease.js +2 -1
  77. package/dist/server/localServiceSessions.d.ts +14 -17
  78. package/dist/server/localServiceSessions.js +308 -94
  79. package/dist/server/localWorkspaceSyncServerRuntime.js +12 -14
  80. package/dist/server/routes/admin.d.ts +4 -0
  81. package/dist/server/routes/admin.js +112 -3
  82. package/dist/server/routes/agents.d.ts +7 -0
  83. package/dist/server/routes/agents.js +277 -24
  84. package/dist/server/routes/billing.js +5 -1
  85. package/dist/server/routes/durableTaskHttpRouters.d.ts +2 -0
  86. package/dist/server/routes/executorPhaseAApprovals.d.ts +19 -0
  87. package/dist/server/routes/executorPhaseAApprovals.js +140 -0
  88. package/dist/server/routes/executorPhaseAIssuerRedemptions.d.ts +11 -0
  89. package/dist/server/routes/executorPhaseAIssuerRedemptions.js +24 -0
  90. package/dist/server/routes/githubReviewEvidence.d.ts +19 -0
  91. package/dist/server/routes/githubReviewEvidence.js +116 -0
  92. package/dist/server/routes/localService.d.ts +15 -4
  93. package/dist/server/routes/localService.js +136 -40
  94. package/dist/server/routes/modelConnections.d.ts +24 -0
  95. package/dist/server/routes/modelConnections.js +205 -0
  96. package/dist/server/routes/shared.d.ts +19 -0
  97. package/dist/server/routes/shared.js +95 -19
  98. package/dist/server/routes/sync.js +1 -0
  99. package/dist/server/routes/syncAuxRoutes.js +5 -1
  100. package/dist/server/routes/syncPushRoutes.d.ts +1 -0
  101. package/dist/server/routes/syncPushRoutes.js +1 -0
  102. package/dist/server/routes/syncV3FeedRoutes.js +10 -1
  103. package/dist/server/routes/syncV3OperationRoutes.js +35 -9
  104. package/dist/server/routes/tasks.js +21 -2
  105. package/dist/server/routes/workflows.js +9 -1
  106. package/dist/server/routes.js +59 -0
  107. package/dist/services/codexAppServerModelGateway.d.ts +54 -5
  108. package/dist/services/codexAppServerModelGateway.js +246 -21
  109. package/dist/services/codexDeviceCodeLoginManager.d.ts +39 -0
  110. package/dist/services/codexDeviceCodeLoginManager.js +265 -0
  111. package/dist/services/codexModelProviderConnectionLifecycle.d.ts +8 -0
  112. package/dist/services/codexModelProviderConnectionLifecycle.js +73 -0
  113. package/dist/services/executorPhaseAApprovalRuntime.d.ts +14 -0
  114. package/dist/services/executorPhaseAApprovalRuntime.js +24 -0
  115. package/dist/services/executorPhaseAApprovalService.d.ts +40 -0
  116. package/dist/services/executorPhaseAApprovalService.js +609 -0
  117. package/dist/services/executorPhaseADriftEvaluator.d.ts +78 -0
  118. package/dist/services/executorPhaseADriftEvaluator.js +93 -0
  119. package/dist/services/executorPhaseAIssuerCore.d.ts +126 -0
  120. package/dist/services/executorPhaseAIssuerCore.js +295 -0
  121. package/dist/services/executorPhaseAIssuerRedemptionService.d.ts +34 -0
  122. package/dist/services/executorPhaseAIssuerRedemptionService.js +158 -0
  123. package/dist/services/githubReviewEvidenceRuntime.d.ts +14 -0
  124. package/dist/services/githubReviewEvidenceRuntime.js +30 -0
  125. package/dist/services/githubReviewEvidenceService.d.ts +93 -0
  126. package/dist/services/githubReviewEvidenceService.js +336 -0
  127. package/dist/services/modelGateway.d.ts +7 -0
  128. package/dist/services/modelProviderConnectionService.d.ts +71 -0
  129. package/dist/services/modelProviderConnectionService.js +279 -0
  130. package/dist/services/modelProviderCredentialHome.d.ts +32 -0
  131. package/dist/services/modelProviderCredentialHome.js +271 -0
  132. package/dist/services/ownerScopedModelConnectionGateway.d.ts +12 -0
  133. package/dist/services/ownerScopedModelConnectionGateway.js +30 -0
  134. package/dist/services/taskforceAgentConnectionBindingService.d.ts +66 -0
  135. package/dist/services/taskforceAgentConnectionBindingService.js +185 -0
  136. package/dist/services/taskforceAgentMcpBridge.d.ts +1 -1
  137. package/dist/services/taskforceAgentMcpBridge.js +7 -24
  138. package/dist/shared/adminEdgeProxy.d.ts +5 -0
  139. package/dist/shared/adminEdgeProxy.js +94 -0
  140. package/dist/shared/adminProxySessionCookies.d.ts +16 -0
  141. package/dist/shared/adminProxySessionCookies.js +86 -0
  142. package/dist/shared/aiProfileColors.d.ts +31 -1
  143. package/dist/shared/aiProfileColors.js +14 -6
  144. package/dist/shared/executorPhaseAApprovalGoldenVector.json +269 -0
  145. package/dist/shared/executorPhaseAApprovalReceipt.d.ts +112 -0
  146. package/dist/shared/executorPhaseAApprovalReceipt.js +58 -0
  147. package/dist/shared/executorPhaseAApprovalTrustPolicy.json +10 -0
  148. package/dist/shared/executorPhaseADriftContracts.d.ts +37 -0
  149. package/dist/shared/executorPhaseADriftContracts.js +63 -0
  150. package/dist/shared/executorPhaseAIssuerContracts.d.ts +75 -0
  151. package/dist/shared/executorPhaseAIssuerContracts.js +90 -0
  152. package/dist/shared/executorPhaseARunAuthorization.d.ts +120 -0
  153. package/dist/shared/executorPhaseARunAuthorization.js +232 -0
  154. package/dist/shared/executorPhaseASchemaValidation.d.ts +7 -0
  155. package/dist/shared/executorPhaseASchemaValidation.js +53 -0
  156. package/dist/shared/executorPhaseASchemas/approval-receipt.schema.json +106 -0
  157. package/dist/shared/executorPhaseASchemas/drift-attestation.schema.json +54 -0
  158. package/dist/shared/executorPhaseASchemas/drift-request.schema.json +47 -0
  159. package/dist/shared/executorPhaseASchemas/foundation-manifest.schema.json +29 -0
  160. package/dist/shared/executorPhaseASchemas/issuer-audit-record.schema.json +24 -0
  161. package/dist/shared/executorPhaseASchemas/issuer-proof.schema.json +43 -0
  162. package/dist/shared/executorPhaseASchemas/issuer-redemption-request.schema.json +18 -0
  163. package/dist/shared/executorPhaseASchemas/issuer-redemption-response.schema.json +39 -0
  164. package/dist/shared/executorPhaseASchemas/logical-envelope.schema.json +149 -0
  165. package/dist/shared/executorPhaseASchemas/preflight-report.schema.json +216 -0
  166. package/dist/shared/executorPhaseASchemas/run-capability.schema.json +111 -0
  167. package/dist/shared/executorPhaseASchemas/sender-proof.schema.json +37 -0
  168. package/dist/shared/executorPhaseASchemas/workload-grant.schema.json +68 -0
  169. package/dist/shared/executorPhaseASchemas/workload-jwt-claims.schema.json +67 -0
  170. package/dist/shared/executorPhaseATiming.d.ts +1 -0
  171. package/dist/shared/executorPhaseATiming.js +1 -0
  172. package/dist/shared/planningIdentity.js +1 -1
  173. package/dist/shared/productLogoKeys.d.ts +2 -0
  174. package/dist/shared/productLogoKeys.js +18 -0
  175. package/dist/shared/taskforceAgentDefinition.d.ts +0 -1
  176. package/dist/shared/taskforceAgentDefinition.js +6 -9
  177. package/dist/shared/taskforceAgentModels.js +7 -3
  178. package/dist/shared/userFeatureGrants.d.ts +4 -0
  179. package/dist/shared/userFeatureGrants.js +7 -0
  180. package/dist/storage/executorPhaseAApprovalReceiptStore.d.ts +37 -0
  181. package/dist/storage/executorPhaseAApprovalReceiptStore.js +81 -0
  182. package/dist/storage/executorPhaseARunAuthorizationStore.d.ts +103 -0
  183. package/dist/storage/executorPhaseARunAuthorizationStore.js +492 -0
  184. package/dist/storage/githubReviewEvidenceInstallationStore.d.ts +26 -0
  185. package/dist/storage/githubReviewEvidenceInstallationStore.js +89 -0
  186. package/dist/storage/modelProviderConnectionStore.d.ts +99 -0
  187. package/dist/storage/modelProviderConnectionStore.js +446 -0
  188. package/dist/storage/postgresAdapter.d.ts +4 -0
  189. package/dist/storage/postgresAdapter.js +11 -0
  190. package/dist/storage/postgresWorker.js +9 -1
  191. package/dist/storage/postgresWorkerProtocol.d.ts +1 -0
  192. package/dist/storage/taskforceAgentConnectionBindingStore.d.ts +31 -0
  193. package/dist/storage/taskforceAgentConnectionBindingStore.js +84 -0
  194. package/dist/sync/coordinator/localSyncExecutionPermitStore.js +60 -29
  195. package/dist/sync/coordinator/localWorkspaceSyncPendingV2PushProgress.d.ts +10 -0
  196. package/dist/sync/coordinator/localWorkspaceSyncPendingV2PushProgress.js +29 -0
  197. package/dist/sync/coordinator/localWorkspaceSyncRunnerState.d.ts +15 -1
  198. package/dist/sync/coordinator/localWorkspaceSyncRunnerState.js +99 -2
  199. package/dist/sync/coordinator/workspaceSyncCredentialBroker.d.ts +1 -0
  200. package/dist/sync/coordinator/workspaceSyncCredentialBroker.js +33 -4
  201. package/dist/sync/engine/workspaceSyncContentLifecycleAdapter.d.ts +2 -1
  202. package/dist/sync/engine/workspaceSyncContentVersionStore.d.ts +38 -0
  203. package/dist/sync/engine/workspaceSyncContentVersionStore.js +50 -1
  204. package/dist/sync/engine/workspaceSyncEngineLifecyclePolicy.js +6 -6
  205. package/dist/sync/engine/workspaceSyncEnginePushCompletion.d.ts +14 -0
  206. package/dist/sync/engine/workspaceSyncEnginePushCompletion.js +84 -0
  207. package/dist/sync/engine/workspaceSyncEngineRecovery.js +1 -0
  208. package/dist/sync/engine/workspaceSyncEngineRuntime.d.ts +1 -0
  209. package/dist/sync/engine/workspaceSyncEngineRuntime.js +1 -0
  210. package/dist/sync/engine/workspaceSyncEngineServerRunnerOperations.js +112 -38
  211. package/dist/sync/engine/workspaceSyncEngineServerSnapshotReader.js +6 -0
  212. package/dist/sync/engine/workspaceSyncEngineTransfers.js +3 -1
  213. package/dist/sync/engine/workspaceSyncV2ChangeDispatcher.d.ts +1 -0
  214. package/dist/sync/engine/workspaceSyncV2ChangeDispatcher.js +29 -0
  215. package/dist/sync/syncApplyHandlers.d.ts +2 -0
  216. package/dist/sync/syncApplyHandlers.js +10 -1
  217. package/dist/sync/syncService.d.ts +15 -0
  218. package/dist/sync/syncService.js +83 -18
  219. package/dist/sync/taskforceAgentSyncAuthorization.d.ts +16 -0
  220. package/dist/sync/taskforceAgentSyncAuthorization.js +20 -0
  221. package/dist/sync/v3/combinedFeedCapability.js +4 -0
  222. package/dist/sync/v3/durableInitiativeMutationRouter.js +18 -10
  223. package/dist/sync/v3/durableOperationReplay.d.ts +14 -0
  224. package/dist/sync/v3/durableOperationReplay.js +18 -0
  225. package/dist/sync/v3/durableTaskAttachmentLinksMutationRouter.js +3 -0
  226. package/dist/sync/v3/durableTaskChecklistMutationRouter.d.ts +2 -1
  227. package/dist/sync/v3/durableTaskChecklistMutationRouter.js +58 -15
  228. package/dist/sync/v3/durableTaskCommentMutationRouter.js +3 -0
  229. package/dist/sync/v3/durableTaskHttpRootMutationRouter.d.ts +1 -1
  230. package/dist/sync/v3/durableTaskHttpRootMutationRouter.js +10 -0
  231. package/dist/sync/v3/durableTaxonomyMutationRouter.js +5 -0
  232. package/dist/sync/v3/durableWorkflowRuntimeMutationRouter.d.ts +11 -0
  233. package/dist/sync/v3/durableWorkflowRuntimeMutationRouter.js +39 -10
  234. package/dist/sync/v3/durableWorkstreamMutationRouter.js +18 -10
  235. package/dist/sync/v3/durableWorkstreamTaskOrderMutationRouter.js +16 -5
  236. package/dist/sync/v3/localOutboxDispatchRuntime.js +2 -2
  237. package/dist/sync/v3/localTaskChecklistOutboxHandler.js +16 -2
  238. package/dist/sync/v3/localTaskChecklistOutboxService.d.ts +4 -0
  239. package/dist/sync/v3/localTaskChecklistOutboxService.js +14 -1
  240. package/dist/sync/v3/localTaskStatusOutboxService.d.ts +8 -0
  241. package/dist/sync/v3/localTaskStatusOutboxService.js +219 -12
  242. package/dist/sync/v3/syncDurabilityStore.d.ts +34 -0
  243. package/dist/sync/v3/syncDurabilityStore.js +168 -2
  244. package/dist/sync/v3/taskChecklistMutationService.d.ts +11 -0
  245. package/dist/sync/v3/taskChecklistMutationService.js +44 -1
  246. package/dist/sync/v3/taskStatusMutationService.d.ts +29 -1
  247. package/dist/sync/v3/taskStatusMutationService.js +119 -3
  248. package/dist/sync/v3/workflowAssignmentSync.d.ts +5 -0
  249. package/dist/sync/v3/workflowAssignmentSync.js +27 -0
  250. package/dist/sync/v3/workspaceSyncJournalReader.js +1 -1
  251. package/dist/sync/v3/workspaceSyncOperationRetentionService.d.ts +16 -0
  252. package/dist/sync/v3/workspaceSyncOperationRetentionService.js +83 -0
  253. package/dist/sync/v3/workspaceSyncV3CloudOperationHandler.d.ts +1 -0
  254. package/dist/sync/v3/workspaceSyncV3CloudOperationHandler.js +9 -2
  255. package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.d.ts +7 -0
  256. package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.js +44 -32
  257. package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.d.ts +9 -5
  258. package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.js +54 -38
  259. package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.d.ts +10 -0
  260. package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.js +70 -31
  261. package/dist/sync/v3/workspaceSyncV3CombinedWireContract.d.ts +2 -1
  262. package/dist/sync/v3/workspaceSyncV3CombinedWireContract.js +16 -0
  263. package/dist/sync/v3/workspaceSyncV3CoverageRegistry.js +6 -0
  264. package/dist/sync/v3/workspaceSyncV3OperationProtocol.d.ts +3 -0
  265. package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.d.ts +5 -0
  266. package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.js +36 -2
  267. package/dist/sync/v3/workspaceSyncV3RepairSnapshotRetentionService.d.ts +17 -0
  268. package/dist/sync/v3/workspaceSyncV3RepairSnapshotRetentionService.js +64 -0
  269. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverCoverage.d.ts +7 -0
  270. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverCoverage.js +33 -0
  271. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverWireContract.d.ts +7 -0
  272. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverWireContract.js +8 -0
  273. package/dist/sync/workspaceRepair.d.ts +5 -2
  274. package/dist/sync/workspaceRepair.js +161 -6
  275. package/dist/sync/workspaceSyncModel.d.ts +21 -0
  276. package/dist/sync/workspaceSyncModel.js +35 -7
  277. package/dist/sync/workspaceSyncState.d.ts +1 -0
  278. package/dist/sync/workspaceSyncV2SnapshotBuilder.d.ts +6 -0
  279. package/dist/sync/workspaceSyncV2SnapshotBuilder.js +5 -0
  280. package/dist/ui/assets/AiIdentityRosterCard-OcSz1PkK.js +1 -0
  281. package/dist/ui/assets/AiProfilesModule-ByhYW5Xi.js +1 -0
  282. package/dist/ui/assets/{AnnotatedAttachmentWorkspace-B68Wg-RV.js → AnnotatedAttachmentWorkspace-BTM6nIg_.js} +1 -1
  283. package/dist/ui/assets/{AssetTraySortControl-C8Rztyal.js → AssetTraySortControl-DabEG8L4.js} +1 -1
  284. package/dist/ui/assets/{ContextAttachmentManager-Cj3c7X9y.js → ContextAttachmentManager-Coa8yVGM.js} +1 -1
  285. package/dist/ui/assets/{DocumentWorkspace-B5uvzems.js → DocumentWorkspace-BB0qhdix.js} +1 -1
  286. package/dist/ui/assets/{EntityActivityTimeline-BVFvCB5R.js → EntityActivityTimeline-CZ8x4UJE.js} +1 -1
  287. package/dist/ui/assets/{PlanningModule-B5DWQOGz.js → PlanningModule-pRPjR7v5.js} +1 -1
  288. package/dist/ui/assets/{PlansPage-AY4cGWco.js → PlansPage-D86pZSSl.js} +1 -1
  289. package/dist/ui/assets/{TaskContextUpload-DZxTVesW.js → TaskContextUpload-BVIkU9yT.js} +1 -1
  290. package/dist/ui/assets/TaskSettings-Cv1mNhv_.js +12 -0
  291. package/dist/ui/assets/TaskforceAgentsModule-b-8R25cJ.css +1 -0
  292. package/dist/ui/assets/TaskforceAgentsModule-gmH-PD2q.js +24 -0
  293. package/dist/ui/assets/{WorkflowManagerModule-DEr5di_r.js → WorkflowManagerModule-DbfnHJ-f.js} +1 -1
  294. package/dist/ui/assets/index-BZ-hdZSk.css +1 -0
  295. package/dist/ui/assets/index-CTsDBaef.js +7 -0
  296. package/dist/ui/assets/{vendor-icons-D9Lpw-j4.js → vendor-icons-Bsq-mcEn.js} +1 -1
  297. package/dist/ui/branding/logos/letterhead_dark.png +0 -0
  298. package/dist/ui/branding/logos/letterhead_light.png +0 -0
  299. package/dist/ui/branding/logos/signature_dark.png +0 -0
  300. package/dist/ui/branding/logos/signature_light.png +0 -0
  301. package/dist/ui/index.html +3 -3
  302. package/dist/utils/aiProfileDefaultLogo.js +16 -48
  303. package/dist/utils/httpSetCookie.d.ts +1 -0
  304. package/dist/utils/httpSetCookie.js +4 -1
  305. package/dist/utils/localRuntimeUrl.d.ts +1 -0
  306. package/dist/utils/localRuntimeUrl.js +14 -0
  307. package/dist/utils/productLogoRegistry.d.ts +2 -0
  308. package/dist/utils/productLogoRegistry.js +36 -0
  309. package/dist/utils/syncStatusPresentation.d.ts +4 -0
  310. package/dist/utils/syncStatusPresentation.js +17 -0
  311. package/dist/utils/taskEvents.d.ts +2 -0
  312. package/dist/utils/workspaceSyncPresentation.d.ts +1 -1
  313. package/dist/utils/workspaceSyncPresentation.js +23 -17
  314. package/package.json +22 -4
  315. package/dist/ui/assets/AiIdentityRosterCard-BZM4aQnM.js +0 -1
  316. package/dist/ui/assets/AiProfilesModule-BbAEWtHH.js +0 -1
  317. package/dist/ui/assets/TaskSettings-BeWAuyZj.js +0 -12
  318. package/dist/ui/assets/TaskforceAgentsModule-BifCYtjR.js +0 -21
  319. package/dist/ui/assets/TaskforceAgentsModule-D6IC0S7Q.css +0 -1
  320. package/dist/ui/assets/index-I5zhdtgt.js +0 -7
  321. package/dist/ui/assets/index-VRFsx3wz.css +0 -1
@@ -1,12 +1,15 @@
1
1
  import { applyTaskStatusMutationForDurableSync, validateDurableTaskStatusMutationPayload, } from '../../core/TaskDurableStatusMutationService.js';
2
2
  import { serializeTaskForSync } from '../taskSyncPayload.js';
3
3
  import { buildTaskLifecycleActivityEventId } from './taskLifecycleActivityIdentity.js';
4
+ import { buildTaskCommentActivityEventId } from './taskCommentActivityIdentity.js';
4
5
  import { validateTaskActivityAuthoritativeRevision } from './taskActivityAuthoritativeRevision.js';
5
6
  import { serializeEntityActivityForSync, serializeTaskActivityForSync, WORKSPACE_SYNC_ENTITY_EVENT_APPEND, WORKSPACE_SYNC_ENTITY_EVENT_DOMAIN, } from './taskActivityJournal.js';
6
7
  import { fingerprintWorkspaceSyncPayload, } from './syncDurabilityStore.js';
7
8
  import { WorkflowStore } from '../../storage/workflowStore.js';
8
9
  import { normalizeTaskStatusOperationWithWorkflowAssignment, normalizeWorkflowAssignmentSyncRecord, } from './workflowAssignmentSync.js';
9
10
  import { withOriginActorPayload } from './workspaceSyncV3OriginActor.js';
11
+ import { mergeWorkspaceSyncV3TaskCommentsPayload, serializeWorkspaceSyncV3TaskCommentsPayload, } from './workspaceSyncV3NestedTaskCodecs.js';
12
+ import { canonicalWorkspaceSyncJson } from './canonicalWorkspaceSyncJson.js';
10
13
  export class LocalAuthoritativeTaskStatusError extends Error {
11
14
  code = 'WORKSPACE_SYNC_AUTHORITATIVE_RESPONSE_INVALID';
12
15
  constructor(message) {
@@ -19,6 +22,16 @@ function isCanonicalIso(value) {
19
22
  && Number.isFinite(Date.parse(value))
20
23
  && new Date(value).toISOString() === value;
21
24
  }
25
+ function nextTaskUpdatedAt(current, requested) {
26
+ const currentMs = Date.parse(current);
27
+ const requestedMs = Date.parse(requested);
28
+ if (!Number.isFinite(requestedMs) || new Date(requestedMs).toISOString() !== requested) {
29
+ throw new LocalAuthoritativeTaskStatusError('Task status operation timestamp is invalid.');
30
+ }
31
+ return Number.isFinite(currentMs) && currentMs >= requestedMs
32
+ ? new Date(currentMs + 1).toISOString()
33
+ : requested;
34
+ }
22
35
  function normalizeAssignee(value) {
23
36
  const normalized = typeof value === 'string' ? value.trim() : '';
24
37
  return normalized && normalized.toLowerCase() !== 'unassigned' ? normalized : null;
@@ -46,13 +59,27 @@ export function enqueueLocalTaskStatusMutation(input) {
46
59
  const taskId = String(input.taskId || '').trim();
47
60
  if (!taskId)
48
61
  throw new LocalAuthoritativeTaskStatusError('Task id is required.');
49
- const statusPayload = validateDurableTaskStatusMutationPayload(input.payload);
62
+ const operationPayload = normalizeTaskStatusOperationWithWorkflowAssignment(input.payload);
63
+ const statusPayload = validateDurableTaskStatusMutationPayload({
64
+ status: operationPayload.status,
65
+ assigneeIntent: operationPayload.assigneeIntent,
66
+ canceledReason: operationPayload.canceledReason,
67
+ metadataPatch: operationPayload.metadataPatch,
68
+ });
50
69
  const assignment = statusPayload.status === 'in-progress'
51
70
  ? new WorkflowStore(input.core.getDatabaseAdapter(), input.core.getTenantId())
52
71
  .getAssignmentForTaskSync(input.identity.workspaceId, taskId)
53
72
  : null;
73
+ const reviewHandoff = operationPayload.reviewHandoff ? {
74
+ comment: {
75
+ ...operationPayload.reviewHandoff.comment,
76
+ author: input.actorRef,
77
+ submittedAuthor: input.actorRef,
78
+ },
79
+ } : null;
54
80
  const payload = {
55
- ...statusPayload,
81
+ ...operationPayload,
82
+ ...(reviewHandoff ? { reviewHandoff } : {}),
56
83
  ...(assignment?.execution.status === 'pending' ? { workflowAssignment: assignment } : {}),
57
84
  };
58
85
  const activityEventId = buildTaskLifecycleActivityEventId({
@@ -62,6 +89,23 @@ export function enqueueLocalTaskStatusMutation(input) {
62
89
  taskId,
63
90
  mutationKind: 'set-status',
64
91
  });
92
+ const reviewComment = payload.reviewHandoff ? {
93
+ ...payload.reviewHandoff.comment,
94
+ timestamp: input.now,
95
+ } : null;
96
+ const reviewCommentActivityEventId = reviewComment ? buildTaskCommentActivityEventId({
97
+ workspaceId: input.identity.workspaceId,
98
+ clientId: input.identity.clientId,
99
+ operationId: input.identity.operationId,
100
+ taskId,
101
+ commentId: reviewComment.id,
102
+ }) : null;
103
+ const reviewCommentRevision = reviewComment ? input.store.readEntityRevisionCoordinates({
104
+ tenantId: input.identity.tenantId,
105
+ workspaceId: input.identity.workspaceId,
106
+ domain: 'task-comments',
107
+ entityId: taskId,
108
+ }) : null;
65
109
  const result = input.store.enqueueLocalOperation({
66
110
  identity: input.identity,
67
111
  domain: 'task',
@@ -74,6 +118,15 @@ export function enqueueLocalTaskStatusMutation(input) {
74
118
  taskLifecycle: true,
75
119
  taskAssignee: payload.assigneeIntent.kind !== 'preserve',
76
120
  },
121
+ ...(reviewComment ? {
122
+ additionalTargets: [{
123
+ domain: 'task-comments',
124
+ entityId: taskId,
125
+ mutationKind: 'append',
126
+ baseEntityRevision: reviewCommentRevision.entityRevision,
127
+ baseLifecycleRevision: reviewCommentRevision.lifecycleRevision,
128
+ }],
129
+ } : {}),
77
130
  payload: withOriginActorPayload({
78
131
  ...payload,
79
132
  ...(input.expectedDetailRevision
@@ -92,7 +145,7 @@ export function enqueueLocalTaskStatusMutation(input) {
92
145
  }
93
146
  input.core.assertTaskDetailRevisionForUpdate(taskId, input.expectedDetailRevision, input.identity.workspaceId);
94
147
  }
95
- return applyTaskStatusMutationForDurableSync({
148
+ let mutation = applyTaskStatusMutationForDurableSync({
96
149
  core: input.core,
97
150
  workspaceId: input.identity.workspaceId,
98
151
  taskId,
@@ -104,6 +157,35 @@ export function enqueueLocalTaskStatusMutation(input) {
104
157
  actorRef: input.actorRef,
105
158
  taskEventId: activityEventId,
106
159
  });
160
+ if (reviewComment) {
161
+ const comments = serializeWorkspaceSyncV3TaskCommentsPayload({
162
+ taskId,
163
+ comments: mutation.task.comments || [],
164
+ }).comments;
165
+ if (comments.some((comment) => comment.id === reviewComment.id)) {
166
+ throw new LocalAuthoritativeTaskStatusError(`Review handoff comment identity conflict: ${reviewComment.id}.`);
167
+ }
168
+ const updatedAt = nextTaskUpdatedAt(String(mutation.task.updatedAt || mutation.task.createdAt), input.now);
169
+ const updated = input.core.updateTask(taskId, { comments: [...comments, reviewComment] }, input.identity.workspaceId, {
170
+ persistBackup: false,
171
+ emitRealtime: false,
172
+ skipTaskEvents: true,
173
+ syncUpdatedAt: updatedAt,
174
+ allowV3OwnedMetadataWrite: true,
175
+ });
176
+ if (!updated)
177
+ throw new LocalAuthoritativeTaskStatusError('Review handoff task disappeared.');
178
+ input.core.addTaskCommentEventForDurableSync({
179
+ taskId,
180
+ workspaceId: input.identity.workspaceId,
181
+ actor: input.actorRef,
182
+ eventId: reviewCommentActivityEventId,
183
+ createdAt: String(updated.updatedAt),
184
+ comment: reviewComment,
185
+ });
186
+ mutation = { ...mutation, task: updated };
187
+ }
188
+ return mutation;
107
189
  },
108
190
  buildCanonicalIntent: (result) => ({
109
191
  metadataPatch: Object.fromEntries(Object.keys(payload.metadataPatch).map((key) => [
@@ -117,7 +199,7 @@ export function enqueueLocalTaskStatusMutation(input) {
117
199
  const mutationResult = result.mutationResult;
118
200
  if (!mutationResult)
119
201
  throw new LocalAuthoritativeTaskStatusError('Local task status mutation result is missing.');
120
- if (!mutationResult.noOp) {
202
+ if (!mutationResult.noOp || reviewComment) {
121
203
  try {
122
204
  input.core.notifyDurableTaskLifecycleCommitted(input.identity.workspaceId, taskId);
123
205
  }
@@ -174,6 +256,66 @@ export function applyAuthoritativeTaskStatusAndAck(input) {
174
256
  throw new LocalAuthoritativeTaskStatusError('Persisted task status payload fingerprint is invalid.');
175
257
  }
176
258
  const operationPayload = normalizeTaskStatusOperationWithWorkflowAssignment(persistedPayload);
259
+ const requestedReviewHandoff = operationPayload.reviewHandoff || null;
260
+ const reviewHandoff = response.reviewHandoff || null;
261
+ if (Boolean(requestedReviewHandoff) !== Boolean(reviewHandoff)) {
262
+ throw new LocalAuthoritativeTaskStatusError('Authoritative review handoff presence is invalid.');
263
+ }
264
+ let reviewCommentsPayload = null;
265
+ let reviewCommentActivity = null;
266
+ let reviewCommentTimestamp = null;
267
+ if (requestedReviewHandoff && reviewHandoff) {
268
+ reviewCommentsPayload = serializeWorkspaceSyncV3TaskCommentsPayload({
269
+ taskId: task.id,
270
+ comments: reviewHandoff.comments.payload.comments,
271
+ });
272
+ reviewCommentActivity = reviewHandoff.activity;
273
+ const requestedComment = requestedReviewHandoff.comment;
274
+ const authoritativeComment = reviewCommentsPayload.comments.find((comment) => comment.id === requestedComment.id);
275
+ reviewCommentTimestamp = authoritativeComment?.timestamp || null;
276
+ const expectedActivityId = buildTaskCommentActivityEventId({
277
+ workspaceId: input.identity.workspaceId,
278
+ clientId: input.identity.clientId,
279
+ operationId: input.identity.operationId,
280
+ taskId: task.id,
281
+ commentId: requestedComment.id,
282
+ });
283
+ const reviewCommentActivityDetails = reviewCommentActivity.details;
284
+ if (reviewHandoff.comments.domain !== 'task-comments'
285
+ || reviewHandoff.comments.entityId !== task.id
286
+ || reviewHandoff.comments.mutationKind !== 'append'
287
+ || !/^(0|[1-9]\d*)$/.test(reviewHandoff.comments.sequence)
288
+ || !/^(0|[1-9]\d*)$/.test(reviewHandoff.comments.entityRevision)
289
+ || reviewHandoff.comments.lifecycleRevision !== '0'
290
+ || reviewCommentsPayload.taskId !== task.id
291
+ || !authoritativeComment
292
+ || authoritativeComment.author !== requestedComment.author
293
+ || authoritativeComment.submittedAuthor !== requestedComment.submittedAuthor
294
+ || authoritativeComment.text !== requestedComment.text
295
+ || !isCanonicalIso(authoritativeComment.timestamp)
296
+ || reviewCommentActivity.id !== expectedActivityId
297
+ || reviewCommentActivity.workspaceId !== input.identity.workspaceId
298
+ || reviewCommentActivity.entityType !== 'task'
299
+ || reviewCommentActivity.entityId !== task.id
300
+ || reviewCommentActivity.taskId !== task.id
301
+ || reviewCommentActivity.action !== 'task-comment-added'
302
+ || !String(reviewCommentActivity.actor || '').trim()
303
+ || !['human', 'ai', 'system'].includes(reviewCommentActivity.actorType)
304
+ || reviewCommentActivity.createdAt !== task.updatedAt
305
+ || !reviewCommentActivityDetails
306
+ || Object.keys(reviewCommentActivityDetails).sort().join(',') !== 'commentId,preview,submittedAuthor'
307
+ || reviewCommentActivityDetails.commentId !== authoritativeComment.id
308
+ || reviewCommentActivityDetails.submittedAuthor !== authoritativeComment.submittedAuthor
309
+ || reviewCommentActivityDetails.preview !== authoritativeComment.text.slice(0, 160)
310
+ || reviewHandoff.activityRevision.domain !== 'entity-event'
311
+ || reviewHandoff.activityRevision.entityId !== expectedActivityId
312
+ || !/^(0|[1-9]\d*)$/.test(reviewHandoff.activityRevision.sequence)
313
+ || reviewHandoff.activityRevision.entityRevision !== '1'
314
+ || reviewHandoff.activityRevision.lifecycleRevision !== '0'
315
+ || canonicalWorkspaceSyncJson(reviewCommentsPayload) !== canonicalWorkspaceSyncJson(serializeWorkspaceSyncV3TaskCommentsPayload({ taskId: task.id, comments: task.comments || [] }))) {
316
+ throw new LocalAuthoritativeTaskStatusError('Authoritative review handoff is invalid.');
317
+ }
318
+ }
177
319
  const requestedWorkflowAssignment = operationPayload.workflowAssignment || null;
178
320
  const workflowIdentityMismatch = (expected, actual) => expected.template.id !== actual.template.id
179
321
  || expected.version.id !== actual.version.id
@@ -269,7 +411,7 @@ export function applyAuthoritativeTaskStatusAndAck(input) {
269
411
  || activity.taskId !== task.id
270
412
  || activity.action !== 'task-status-changed'
271
413
  || !isCanonicalIso(activity.createdAt)
272
- || activity.createdAt !== task.updatedAt
414
+ || activity.createdAt !== (reviewCommentTimestamp || task.updatedAt)
273
415
  || typeof activity.actor !== 'string' || !activity.actor.trim()
274
416
  || !['human', 'ai', 'system'].includes(activity.actorType)
275
417
  || !activity.details || typeof activity.details !== 'object' || Array.isArray(activity.details)
@@ -279,12 +421,37 @@ export function applyAuthoritativeTaskStatusAndAck(input) {
279
421
  throw new LocalAuthoritativeTaskStatusError('Authoritative task status activity is invalid.');
280
422
  }
281
423
  }
282
- const revision = validateTaskActivityAuthoritativeRevision({
283
- response: response,
284
- authoritative: authoritative,
285
- activityId: activity?.id || null,
286
- invalid: (message) => new LocalAuthoritativeTaskStatusError(message),
287
- });
424
+ const reviewIntermediateRevisions = reviewHandoff ? [
425
+ { sequence: reviewHandoff.comments.sequence },
426
+ { sequence: reviewHandoff.activityRevision.sequence },
427
+ ] : [];
428
+ const revision = activity === null && reviewHandoff
429
+ ? (() => {
430
+ const taskSequence = authoritative.sequence;
431
+ const commentsSequence = reviewHandoff.comments.sequence;
432
+ const commentActivitySequence = reviewHandoff.activityRevision.sequence;
433
+ if (!/^(0|[1-9]\d*)$/.test(taskSequence)
434
+ || BigInt(commentsSequence) !== BigInt(taskSequence) + 1n
435
+ || BigInt(commentActivitySequence) !== BigInt(commentsSequence) + 1n
436
+ || response.operationHighWatermark !== commentActivitySequence
437
+ || response.dependentActivityRevisions !== undefined) {
438
+ throw new LocalAuthoritativeTaskStatusError('Authoritative review handoff revisions are not in canonical sequence order.');
439
+ }
440
+ return {
441
+ taskSequence,
442
+ operationHighWatermark: commentActivitySequence,
443
+ activityRevision: null,
444
+ legacySingleEntry: false,
445
+ dependentActivityRevisions: [],
446
+ };
447
+ })()
448
+ : validateTaskActivityAuthoritativeRevision({
449
+ response: response,
450
+ authoritative: authoritative,
451
+ activityId: activity?.id || null,
452
+ invalid: (message) => new LocalAuthoritativeTaskStatusError(message),
453
+ intermediateRevisions: reviewIntermediateRevisions,
454
+ });
288
455
  const dependentActivities = Array.isArray(response.dependentActivities)
289
456
  ? response.dependentActivities
290
457
  : [];
@@ -373,7 +540,23 @@ export function applyAuthoritativeTaskStatusAndAck(input) {
373
540
  canonicalFingerprint,
374
541
  metadataOwned: authoritative.metadataOwned,
375
542
  reopenAssigneeOwned: authoritative.assigneeOwned,
376
- }, ...(!revision.legacySingleEntry && revision.activityRevision && activity ? [{
543
+ }, ...(reviewHandoff && reviewCommentsPayload && reviewCommentActivity ? [{
544
+ domain: 'task-comments',
545
+ entityId: task.id,
546
+ mutationKind: 'append',
547
+ entityRevision: reviewHandoff.comments.entityRevision,
548
+ lifecycleRevision: reviewHandoff.comments.lifecycleRevision,
549
+ sequence: reviewHandoff.comments.sequence,
550
+ canonicalFingerprint: fingerprintWorkspaceSyncPayload(reviewCommentsPayload),
551
+ }, {
552
+ domain: WORKSPACE_SYNC_ENTITY_EVENT_DOMAIN,
553
+ entityId: reviewCommentActivity.id,
554
+ mutationKind: WORKSPACE_SYNC_ENTITY_EVENT_APPEND,
555
+ entityRevision: reviewHandoff.activityRevision.entityRevision,
556
+ lifecycleRevision: reviewHandoff.activityRevision.lifecycleRevision,
557
+ sequence: reviewHandoff.activityRevision.sequence,
558
+ canonicalFingerprint: fingerprintWorkspaceSyncPayload(serializeTaskActivityForSync(reviewCommentActivity)),
559
+ }] : []), ...(!revision.legacySingleEntry && revision.activityRevision && activity ? [{
377
560
  domain: WORKSPACE_SYNC_ENTITY_EVENT_DOMAIN,
378
561
  entityId: activity.id,
379
562
  mutationKind: WORKSPACE_SYNC_ENTITY_EVENT_APPEND,
@@ -405,6 +588,30 @@ export function applyAuthoritativeTaskStatusAndAck(input) {
405
588
  : input.core.installDurableTaskStatusAuthoritativeForSync(task, payload, installAssignee, input.identity.workspaceId);
406
589
  if (!updated)
407
590
  throw new LocalAuthoritativeTaskStatusError('Local task status projection is missing.');
591
+ if (reviewHandoff && reviewCommentsPayload && reviewCommentActivity) {
592
+ const localComments = serializeWorkspaceSyncV3TaskCommentsPayload({
593
+ taskId: updated.id,
594
+ comments: updated.comments || [],
595
+ });
596
+ const installedComments = hasSuccessor
597
+ ? mergeWorkspaceSyncV3TaskCommentsPayload({
598
+ taskId: updated.id,
599
+ left: reviewCommentsPayload.comments,
600
+ right: localComments.comments.filter((comment) => (!reviewCommentsPayload.comments.some((accepted) => accepted.id === comment.id))),
601
+ })
602
+ : reviewCommentsPayload;
603
+ updated = input.core.updateTask(task.id, { comments: installedComments.comments }, input.identity.workspaceId, {
604
+ persistBackup: false,
605
+ emitRealtime: false,
606
+ skipTaskEvents: true,
607
+ syncUpdatedAt: updated.updatedAt,
608
+ allowV3OwnedMetadataWrite: true,
609
+ });
610
+ if (!updated)
611
+ throw new LocalAuthoritativeTaskStatusError('Review handoff task disappeared locally.');
612
+ input.core.upsertEntityEventForSync(reviewCommentActivity, { allowAuthoritativeReplacement: true });
613
+ activityReconciled = true;
614
+ }
408
615
  if (hasSuccessor
409
616
  && installAssignee
410
617
  && !successors.some((successor) => successor.ownsTaskAssignee)
@@ -91,6 +91,15 @@ export type WorkspaceSyncOutboxRecord = WorkspaceSyncOperationIdentity & {
91
91
  leaseOwner: string | null;
92
92
  leaseExpiresAt: string | null;
93
93
  };
94
+ export type WorkspaceSyncOutboxOperationLookup = WorkspaceSyncOperationIdentity & {
95
+ status: string;
96
+ createdAt: string;
97
+ domain: string;
98
+ entityId: string;
99
+ mutationKind: string;
100
+ payloadFingerprint: string;
101
+ authoritativeResponseJson: string | null;
102
+ };
94
103
  export type WorkspaceSyncOutboxSupersession = {
95
104
  recoveryBatchId: string;
96
105
  operationIds: string[];
@@ -325,6 +334,31 @@ export declare class WorkspaceSyncDurabilityStore {
325
334
  createdAt: string;
326
335
  } | null;
327
336
  readOutboxOperation(identity: WorkspaceSyncOperationIdentity): WorkspaceSyncOutboxRecord | null;
337
+ assertOutboxOperationIdentity(record: Readonly<WorkspaceSyncOutboxRecord>, expected: {
338
+ domain: string;
339
+ entityId: string;
340
+ mutationKind: string;
341
+ payloadFingerprint?: string;
342
+ }): void;
343
+ readOutboxOperationLookup(identity: WorkspaceSyncOperationIdentity): WorkspaceSyncOutboxOperationLookup | null;
344
+ pruneTerminalOutboxOperations(input: {
345
+ tenantId: string;
346
+ workspaceId: string;
347
+ terminalBefore: string;
348
+ limit?: number;
349
+ }): {
350
+ deleted: number;
351
+ remainingEligible: number;
352
+ };
353
+ pruneCommittedOperationResults(input: {
354
+ tenantId: string;
355
+ workspaceId: string;
356
+ terminalBefore: string;
357
+ limit?: number;
358
+ }): {
359
+ deleted: number;
360
+ remainingEligible: number;
361
+ };
328
362
  readV3DispatchSettlementEvidence(identity: WorkspaceSyncOperationIdentity): WorkspaceSyncV3DispatchSettlementEvidence | null;
329
363
  listBlockedInvalidOutboxOperations(input: {
330
364
  tenantId: string;
@@ -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;
@@ -800,6 +801,130 @@ export class WorkspaceSyncDurabilityStore {
800
801
  `).get(...operationParams(identity));
801
802
  return row ? this.mapOutboxRow(row) : null;
802
803
  }
804
+ assertOutboxOperationIdentity(record, expected) {
805
+ assertDurableOperationIdentity({
806
+ operationId: record.operationId,
807
+ domain: record.domain,
808
+ entityId: record.entityId,
809
+ mutationKind: record.mutationKind,
810
+ payloadFingerprint: record.payloadFingerprint,
811
+ }, {
812
+ operationId: record.operationId,
813
+ domain: expected.domain,
814
+ entityId: expected.entityId,
815
+ mutationKind: expected.mutationKind,
816
+ payloadFingerprint: expected.payloadFingerprint || record.payloadFingerprint,
817
+ });
818
+ }
819
+ readOutboxOperationLookup(identity) {
820
+ const row = this.db.prepare(`
821
+ SELECT status, authoritative_response_json, created_at,
822
+ mutation_kind, payload_fingerprint, domain, entity_id
823
+ FROM workspace_sync_outbox
824
+ WHERE tenant_id = ? AND workspace_id = ? AND client_id = ? AND operation_id = ?
825
+ LIMIT 1
826
+ `).get(...operationParams(identity));
827
+ if (!row)
828
+ return null;
829
+ return {
830
+ ...identity,
831
+ status: requireText(row.status, 'Outbox status'),
832
+ createdAt: requireIsoTimestamp(row.created_at, 'Outbox creation time'),
833
+ domain: requireText(row.domain, 'Outbox domain'),
834
+ entityId: requireText(row.entity_id, 'Outbox entity id'),
835
+ mutationKind: requireText(row.mutation_kind, 'Outbox mutation kind'),
836
+ payloadFingerprint: requireText(row.payload_fingerprint, 'Outbox payload fingerprint'),
837
+ authoritativeResponseJson: row.authoritative_response_json == null
838
+ ? null
839
+ : requireText(row.authoritative_response_json, 'Outbox authoritative response'),
840
+ };
841
+ }
842
+ pruneTerminalOutboxOperations(input) {
843
+ const tenantId = requireText(input.tenantId, 'Tenant id');
844
+ const workspaceId = requireText(input.workspaceId, 'Workspace id');
845
+ const terminalBefore = requireIsoTimestamp(input.terminalBefore, 'Operation retention cutoff');
846
+ const limit = Math.max(1, Math.min(1_000, Math.floor(input.limit ?? 100)));
847
+ const eligibility = `
848
+ candidate.tenant_id = ? AND candidate.workspace_id = ?
849
+ AND candidate.status IN ('accepted', 'superseded')
850
+ AND candidate.updated_at < ?
851
+ AND NOT EXISTS (
852
+ SELECT 1
853
+ FROM workspace_sync_outbox AS replay
854
+ WHERE replay.tenant_id = candidate.tenant_id
855
+ AND replay.workspace_id = candidate.workspace_id
856
+ AND replay.replay_of_client_id = candidate.client_id
857
+ AND replay.replay_of_operation_id = candidate.operation_id
858
+ )
859
+ `;
860
+ return this.db.transaction(() => {
861
+ const candidates = this.db.prepare(`
862
+ SELECT candidate.client_id, candidate.operation_id
863
+ FROM workspace_sync_outbox AS candidate
864
+ WHERE ${eligibility}
865
+ ORDER BY candidate.updated_at, candidate.client_id, candidate.operation_id
866
+ LIMIT ?
867
+ `).all(tenantId, workspaceId, terminalBefore, limit);
868
+ let deleted = 0;
869
+ for (const candidate of candidates) {
870
+ const clientId = requireText(candidate.client_id, 'Retention client id');
871
+ const operationId = requireText(candidate.operation_id, 'Retention operation id');
872
+ const result = this.db.prepare(`
873
+ DELETE FROM workspace_sync_outbox AS candidate
874
+ WHERE ${eligibility}
875
+ AND candidate.client_id = ? AND candidate.operation_id = ?
876
+ `).run(tenantId, workspaceId, terminalBefore, clientId, operationId);
877
+ if (Number(result.changes || 0) !== 1)
878
+ continue;
879
+ this.db.prepare(`
880
+ DELETE FROM workspace_sync_outbox_targets
881
+ WHERE tenant_id = ? AND workspace_id = ? AND client_id = ? AND operation_id = ?
882
+ `).run(tenantId, workspaceId, clientId, operationId);
883
+ deleted += 1;
884
+ }
885
+ const remaining = this.db.prepare(`
886
+ SELECT COUNT(*) AS count
887
+ FROM workspace_sync_outbox AS candidate
888
+ WHERE ${eligibility}
889
+ `).get(tenantId, workspaceId, terminalBefore);
890
+ return { deleted, remainingEligible: Number(remaining?.count || 0) };
891
+ })();
892
+ }
893
+ pruneCommittedOperationResults(input) {
894
+ const tenantId = requireText(input.tenantId, 'Tenant id');
895
+ const workspaceId = requireText(input.workspaceId, 'Workspace id');
896
+ const terminalBefore = requireIsoTimestamp(input.terminalBefore, 'Operation retention cutoff');
897
+ const limit = Math.max(1, Math.min(1_000, Math.floor(input.limit ?? 100)));
898
+ return this.db.transaction(() => {
899
+ const candidates = this.db.prepare(`
900
+ SELECT client_id, operation_id
901
+ FROM workspace_sync_operation_results
902
+ WHERE tenant_id = ? AND workspace_id = ?
903
+ AND status = 'committed' AND updated_at < ?
904
+ ORDER BY updated_at, client_id, operation_id
905
+ LIMIT ?
906
+ `).all(tenantId, workspaceId, terminalBefore, limit);
907
+ let deleted = 0;
908
+ for (const candidate of candidates) {
909
+ const clientId = requireText(candidate.client_id, 'Retention client id');
910
+ const operationId = requireText(candidate.operation_id, 'Retention operation id');
911
+ const result = this.db.prepare(`
912
+ DELETE FROM workspace_sync_operation_results
913
+ WHERE tenant_id = ? AND workspace_id = ?
914
+ AND client_id = ? AND operation_id = ?
915
+ AND status = 'committed' AND updated_at < ?
916
+ `).run(tenantId, workspaceId, clientId, operationId, terminalBefore);
917
+ deleted += Number(result.changes || 0);
918
+ }
919
+ const remaining = this.db.prepare(`
920
+ SELECT COUNT(*) AS count
921
+ FROM workspace_sync_operation_results
922
+ WHERE tenant_id = ? AND workspace_id = ?
923
+ AND status = 'committed' AND updated_at < ?
924
+ `).get(tenantId, workspaceId, terminalBefore);
925
+ return { deleted, remainingEligible: Number(remaining?.count || 0) };
926
+ })();
927
+ }
803
928
  readV3DispatchSettlementEvidence(identity) {
804
929
  const row = this.db.prepare(`
805
930
  SELECT outbox.status, outbox.authoritative_response_json,
@@ -2457,9 +2582,15 @@ export class WorkspaceSyncDurabilityStore {
2457
2582
  })()
2458
2583
  : null;
2459
2584
  const taskAggregateRootTarget = additionalTargets[0];
2585
+ const queueableTaskReviewHandoff = domain === 'task'
2586
+ && mutationKind === 'set-status'
2587
+ && additionalTargets.length === 1
2588
+ && taskAggregateRootTarget.domain === 'task-comments'
2589
+ && taskAggregateRootTarget.entityId === entityId
2590
+ && taskAggregateRootTarget.mutationKind === 'append';
2460
2591
  const queueableTaskRoot = domain === 'task'
2461
2592
  && TASK_ROOT_SUCCESSOR_MUTATIONS.has(mutationKind)
2462
- && additionalTargets.length === 0;
2593
+ && (additionalTargets.length === 0 || queueableTaskReviewHandoff);
2463
2594
  const queueableTaskAggregate = Boolean(TASK_AGGREGATE_SUCCESSOR_MUTATIONS.get(domain)?.has(mutationKind))
2464
2595
  && ((domain === 'task-comments' && mutationKind === 'reconcile' && additionalTargets.length === 0)
2465
2596
  || (additionalTargets.length === 1
@@ -2786,6 +2917,32 @@ export class WorkspaceSyncDurabilityStore {
2786
2917
  FROM workspace_sync_outbox
2787
2918
  WHERE tenant_id = ? AND workspace_id = ? AND client_id = ? AND operation_id = ?
2788
2919
  `).get(...ids);
2920
+ if (existing) {
2921
+ try {
2922
+ const existingPayloadFingerprint = String(existing.payload_fingerprint || '');
2923
+ assertDurableOperationIdentity({
2924
+ operationId: ids[3],
2925
+ domain: String(existing.domain || ''),
2926
+ entityId: String(existing.entity_id || ''),
2927
+ mutationKind: String(existing.mutation_kind || ''),
2928
+ payloadFingerprint: existingPayloadFingerprint,
2929
+ }, {
2930
+ operationId: ids[3],
2931
+ domain,
2932
+ entityId,
2933
+ mutationKind,
2934
+ payloadFingerprint: existingPayloadFingerprint === coalescedWorkflowPayloadFingerprint
2935
+ ? coalescedWorkflowPayloadFingerprint
2936
+ : payloadFingerprint,
2937
+ });
2938
+ }
2939
+ catch (error) {
2940
+ if (error instanceof DurableOperationReplayIdentityConflictError) {
2941
+ throw new WorkspaceSyncIdempotencyConflictError();
2942
+ }
2943
+ throw error;
2944
+ }
2945
+ }
2789
2946
  const matches = existing
2790
2947
  && Number(existing.contract_version) === WORKSPACE_SYNC_CONTRACT_VERSION
2791
2948
  && existing.dispatch_class === dispatchClass
@@ -4715,9 +4872,18 @@ export class WorkspaceSyncDurabilityStore {
4715
4872
  assertMatchingOperation(row, requestFingerprint) {
4716
4873
  if (!row)
4717
4874
  throw new Error('Workspace sync operation does not exist.');
4718
- if (Number(row.contract_version) !== WORKSPACE_SYNC_CONTRACT_VERSION || row.request_fingerprint !== requestFingerprint) {
4875
+ if (Number(row.contract_version) !== WORKSPACE_SYNC_CONTRACT_VERSION) {
4719
4876
  throw new WorkspaceSyncIdempotencyConflictError();
4720
4877
  }
4878
+ try {
4879
+ assertDurableOperationFingerprint(String(row.request_fingerprint || ''), requestFingerprint);
4880
+ }
4881
+ catch (error) {
4882
+ if (error instanceof DurableOperationReplayIdentityConflictError) {
4883
+ throw new WorkspaceSyncIdempotencyConflictError();
4884
+ }
4885
+ throw error;
4886
+ }
4721
4887
  }
4722
4888
  mapOutboxRow(row) {
4723
4889
  return {
@@ -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;