@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
@@ -7,6 +7,7 @@ import { WorkspaceSyncDurabilityStore } from '../v3/syncDurabilityStore.js';
7
7
  import { assertWorkspaceSyncV2TaskCarrierRootsExist, prepareWorkspaceSyncV2TaskCarriers, } from '../v3/workspaceSyncV2ProjectionExclusions.js';
8
8
  import { resolveV3OwnedTaskDeleteIds, resolveV3OwnedTaskLifecycleIds, resolveV3OwnedTaskMetadataIds, resolveV3OwnedTaskReopenAssigneeIds, resolveV3OwnedTaskTaxonomyIds, } from '../v3/taskMetadataCoexistence.js';
9
9
  import { assertWorkspaceSyncV2MetadataOnlyApplyPreflight, } from './workspaceSyncEngineLocalApply.js';
10
+ import { assertTaskforceAgentSyncPushAccess } from '../taskforceAgentSyncAuthorization.js';
10
11
  function createSyncRouteError(message, details, options) {
11
12
  const error = new Error(message);
12
13
  error.code = options?.code || 'SYNC_APPLY_FAILED';
@@ -132,6 +133,14 @@ export function createWorkspaceSyncV2ChangeDispatcher(dependencies) {
132
133
  normalizeTaskEventSyncPayload,
133
134
  recordSyncDiagnostic,
134
135
  });
136
+ if (options.coexistenceDirection === 'cloud-push') {
137
+ assertTaskforceAgentSyncPushAccess({
138
+ agents: applyModel.collaboration.incomingTaskforceAgents.values(),
139
+ actorUserId: String(options.actorUserId || '').trim() || null,
140
+ hasUserFeatureGrant: (userId, featureKey) => core.hasUserFeatureGrant(userId, featureKey),
141
+ createSyncRouteError,
142
+ });
143
+ }
135
144
  if (metadataOnly) {
136
145
  assertWorkspaceSyncV2MetadataOnlyApplyPreflight(incomingChanges);
137
146
  }
@@ -304,6 +313,10 @@ export function createWorkspaceSyncV2ChangeDispatcher(dependencies) {
304
313
  incomingAgentRoles: applyModel.collaboration.incomingAgentRoles,
305
314
  incomingTaskforceAgentSkills: applyModel.collaboration.incomingTaskforceAgentSkills,
306
315
  incomingAgentConversations: applyModel.collaboration.incomingAgentConversations,
316
+ ...(options.coexistenceDirection === 'cloud-push' ? {
317
+ taskforceAgentPushActorUserId: String(options.actorUserId || '').trim() || null,
318
+ taskforceAgentPushAccessPreflighted: true,
319
+ } : {}),
307
320
  recordSyncDiagnostic,
308
321
  createSyncRouteError,
309
322
  });
@@ -633,6 +646,18 @@ export function createWorkspaceSyncV2ChangeDispatcher(dependencies) {
633
646
  sourceUpdatedAt: intent.sourceUpdatedAt,
634
647
  publishedAt: now().toISOString(),
635
648
  deletedAt: intent.sourceUpdatedAt,
649
+ // This dispatch path only ever runs from an explicit document-delete/
650
+ // asset-delete WorkspaceSyncChange (see workspaceSyncV2PreparedContent.ts)
651
+ // — never from workspace repair, which is intentionally routed to a
652
+ // durable retry obligation instead (see workspaceRepair.ts) rather than
653
+ // ever reaching this admission boundary. operationId/actorId are not yet
654
+ // threaded through the WorkspaceSyncChange wire format from origin to this
655
+ // layer — see the type's doc comment.
656
+ provenance: {
657
+ source: 'explicit-delete',
658
+ sourceRuntime: 'server',
659
+ repairInvolved: false,
660
+ },
636
661
  });
637
662
  if (tombstone.versionId !== null
638
663
  || tombstone.sourceUpdatedAt !== intent.sourceUpdatedAt
@@ -748,6 +773,10 @@ export function createWorkspaceSyncV2ChangeDispatcher(dependencies) {
748
773
  incomingAgentRoles: applyModel.collaboration.incomingAgentRoles,
749
774
  incomingTaskforceAgentSkills: applyModel.collaboration.incomingTaskforceAgentSkills,
750
775
  incomingAgentConversations: applyModel.collaboration.incomingAgentConversations,
776
+ ...(options.coexistenceDirection === 'cloud-push' ? {
777
+ taskforceAgentPushActorUserId: String(options.actorUserId || '').trim() || null,
778
+ taskforceAgentPushAccessPreflighted: true,
779
+ } : {}),
751
780
  recordSyncDiagnostic,
752
781
  createSyncRouteError,
753
782
  });
@@ -255,6 +255,8 @@ export declare function applyCollaborationSyncChanges(input: {
255
255
  incomingAgentRoles?: Map<string, WorkspaceSyncAgentRoleSnapshot>;
256
256
  incomingTaskforceAgentSkills?: Map<string, WorkspaceSyncTaskforceAgentSkillSnapshot>;
257
257
  incomingAgentConversations?: Map<string, WorkspaceSyncAgentConversationSnapshot>;
258
+ taskforceAgentPushActorUserId?: string | null;
259
+ taskforceAgentPushAccessPreflighted?: boolean;
258
260
  recordSyncDiagnostic: RecordSyncDiagnostic;
259
261
  createSyncRouteError: CreateSyncRouteError;
260
262
  }): void;
@@ -18,6 +18,7 @@ import { TaskforceAgentStore } from '../storage/taskforceAgentStore.js';
18
18
  import { TaskforceAgentSkillStore } from '../storage/taskforceAgentSkillStore.js';
19
19
  import { TaskforceAgentConversationStore } from '../storage/taskforceAgentConversationStore.js';
20
20
  import { AgentRoleStore } from '../storage/agentRoleStore.js';
21
+ import { assertTaskforceAgentSyncPushAccess } from './taskforceAgentSyncAuthorization.js';
21
22
  import { preserveV3OwnedTaskRoot, preserveV3OwnedTaskLifecycle, preserveV3OwnedTaskMetadata, preserveV3OwnedTaskReopenAssignee, preserveV3OwnedTaskTaxonomy, } from './v3/taskMetadataCoexistence.js';
22
23
  function createIncomingApplyModel() {
23
24
  return {
@@ -1052,7 +1053,15 @@ export async function applyContentSyncChanges(input) {
1052
1053
  }
1053
1054
  }
1054
1055
  export function applyCollaborationSyncChanges(input) {
1055
- const { core, workspaceId, incomingDocumentReviewSessions, incomingDocumentReviewSessionDeletes, incomingDocumentReviewComments, incomingDocumentReviewCommentDeletes, incomingAnnotatedAttachmentSessions, incomingAnnotatedAttachmentSessionDeletes, incomingTaskforceAgents = new Map(), incomingAgentRoles = new Map(), incomingTaskforceAgentSkills = new Map(), incomingAgentConversations = new Map(), recordSyncDiagnostic, createSyncRouteError, } = input;
1056
+ const { core, workspaceId, incomingDocumentReviewSessions, incomingDocumentReviewSessionDeletes, incomingDocumentReviewComments, incomingDocumentReviewCommentDeletes, incomingAnnotatedAttachmentSessions, incomingAnnotatedAttachmentSessionDeletes, incomingTaskforceAgents = new Map(), incomingAgentRoles = new Map(), incomingTaskforceAgentSkills = new Map(), incomingAgentConversations = new Map(), taskforceAgentPushActorUserId, taskforceAgentPushAccessPreflighted = false, recordSyncDiagnostic, createSyncRouteError, } = input;
1057
+ if (taskforceAgentPushActorUserId !== undefined && !taskforceAgentPushAccessPreflighted) {
1058
+ assertTaskforceAgentSyncPushAccess({
1059
+ agents: incomingTaskforceAgents.values(),
1060
+ actorUserId: taskforceAgentPushActorUserId,
1061
+ hasUserFeatureGrant: (userId, featureKey) => core.hasUserFeatureGrant(userId, featureKey),
1062
+ createSyncRouteError,
1063
+ });
1064
+ }
1056
1065
  if (incomingDocumentReviewSessions.size > 0) {
1057
1066
  for (const session of incomingDocumentReviewSessions.values()) {
1058
1067
  try {
@@ -52,6 +52,12 @@ export interface WorkspacePushSyncInput {
52
52
  remoteServices?: WorkspaceSyncEngineRemoteServices;
53
53
  localServices?: Pick<WorkspaceSyncEngineLocalServices, 'readPushOwnership'>;
54
54
  acknowledgedNonApplyingBatchOperationIdentities?: readonly string[];
55
+ /**
56
+ * Server-owned pages whose remote receipt, authoritative task echo, and
57
+ * runner checkpoint contribution committed atomically. Browser callers
58
+ * must not use this recovery boundary.
59
+ */
60
+ settledBatchOperationIdentities?: readonly string[];
55
61
  preparedPlan?: WorkspacePushPreparedPlan | null;
56
62
  onPreparedPlan?: (input: {
57
63
  plan: WorkspacePushPreparedPlan;
@@ -62,6 +68,14 @@ export interface WorkspacePushSyncInput {
62
68
  operationIdentity: string;
63
69
  acknowledgedOperationIdentities: readonly string[];
64
70
  }) => void | Promise<void>;
71
+ onAcceptedBatchSettled?: (input: {
72
+ operationIdentity: string;
73
+ settlementIdentityFingerprint: string;
74
+ appliedTaskUpserts: WorkspacePushSyncResult['appliedTaskUpserts'];
75
+ transferReceipt: WorkspaceSyncEngineRemoteTransferReceipt;
76
+ pushBoundary: WorkspaceSyncEngineV2PushBoundary;
77
+ excludedProjections?: readonly WorkspaceSyncV2ProjectionExclusion[];
78
+ }) => void | Promise<void>;
65
79
  }
66
80
  export interface WorkspacePushSyncResult {
67
81
  success: boolean;
@@ -90,6 +104,7 @@ export interface WorkspacePushSyncResult {
90
104
  currentInitiativeWatermarks: Map<string, string>;
91
105
  currentWorkstreamIds: Set<string>;
92
106
  currentWorkstreamWatermarks: Map<string, string>;
107
+ currentPlanningIdentityWatermarks?: Map<string, string>;
93
108
  currentAiProfileIds: Set<string>;
94
109
  currentAiProfileWatermarks: Map<string, string>;
95
110
  currentAiProfileChangeKeys?: Map<string, string>;
@@ -1,7 +1,7 @@
1
1
  import { applyLocalWorkspaceChanges, getLocalWorkspaceContentPullObligations, recordLocalWorkspaceContentPullObligationFailures, getLocalWorkspaceContentManifest, pullUserSettings, pushUserSettings, prepareWorkspacePushChanges, } from './cloudSyncApi.js';
2
2
  import { workspaceSyncContentPullObligationId, } from './engine/workspaceSyncContentPullObligationStore.js';
3
3
  import { createBrowserWorkspaceSyncEngineRemoteServices, } from './engine/workspaceSyncEngineRemoteServices.js';
4
- import { createWorkspaceSyncEngineV2PushBoundary, parseWorkspaceSyncEngineAppliedTaskUpserts, workspaceSyncEngineExpectedTaskEchoIds, } from './engine/workspaceSyncEnginePushCompletion.js';
4
+ import { createWorkspaceSyncEngineV2SettlementIdentityProjection, createWorkspaceSyncEngineV2PushBoundary, parseWorkspaceSyncEngineAppliedTaskUpserts, workspaceSyncEngineExpectedTaskEchoIds, } from './engine/workspaceSyncEnginePushCompletion.js';
5
5
  import { encryptDocument } from './encryptionService.js';
6
6
  import { decryptWorkspaceSyncContentChangeInPlace } from './workspaceSyncContentDecryption.js';
7
7
  import { decideWorkspaceContentFetch, fingerprintWorkspaceContentBody, } from './workspaceContentManifest.js';
@@ -181,13 +181,8 @@ function buildEffectiveWorkspacePushDiagnostics(diagnostics, changes, ownership)
181
181
  : {}),
182
182
  };
183
183
  }
184
- async function computeIdempotencyKey(workspaceId, changes, repairMode) {
185
- const text = canonicalWorkspaceSyncJson({
186
- contractVersion: 1,
187
- workspaceId,
188
- repairMode,
189
- changes
190
- });
184
+ async function computeCanonicalWorkspaceSyncSha256(value, fallbackNamespace) {
185
+ const text = canonicalWorkspaceSyncJson(value);
191
186
  try {
192
187
  const buffer = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(text));
193
188
  return Array.from(new Uint8Array(buffer)).map(b => b.toString(16).padStart(2, '0')).join('');
@@ -202,9 +197,19 @@ async function computeIdempotencyKey(workspaceId, changes, repairMode) {
202
197
  hash = Math.imul(hash, 0x01000193);
203
198
  }
204
199
  const hex = (hash >>> 0).toString(16).padStart(8, '0');
205
- return `${workspaceId}:fallback:${hex}`;
200
+ return fallbackNamespace
201
+ ? `${fallbackNamespace}:fallback:${hex}`
202
+ : hex.repeat(8);
206
203
  }
207
204
  }
205
+ async function computeIdempotencyKey(workspaceId, changes, repairMode) {
206
+ return computeCanonicalWorkspaceSyncSha256({
207
+ contractVersion: 1,
208
+ workspaceId,
209
+ repairMode,
210
+ changes
211
+ }, workspaceId);
212
+ }
208
213
  const MAX_WORKSPACE_PUSH_CHANGES_PER_REQUEST = 64;
209
214
  const MAX_WORKSPACE_PUSH_BYTES_PER_REQUEST = 4 * 1024 * 1024;
210
215
  const MAX_WORKSPACE_PUSH_SINGLE_CHANGE_BYTES = 45 * 1024 * 1024;
@@ -428,6 +433,7 @@ export async function runWorkspacePushSyncService(input) {
428
433
  currentInitiativeWatermarks: input.payload.currentInitiativeWatermarks,
429
434
  currentWorkstreamIds: input.payload.currentWorkstreamIds,
430
435
  currentWorkstreamWatermarks: input.payload.currentWorkstreamWatermarks,
436
+ currentPlanningIdentityWatermarks: input.payload.currentPlanningIdentityWatermarks,
431
437
  currentAiProfileIds: input.payload.currentAiProfileIds,
432
438
  currentAiProfileWatermarks: input.payload.currentAiProfileWatermarks,
433
439
  currentAiProfileChangeKeys: input.payload.currentAiProfileChangeKeys ?? new Map(),
@@ -491,6 +497,7 @@ export async function runWorkspacePushSyncService(input) {
491
497
  currentInitiativeWatermarks: input.payload.currentInitiativeWatermarks,
492
498
  currentWorkstreamIds: input.payload.currentWorkstreamIds,
493
499
  currentWorkstreamWatermarks: input.payload.currentWorkstreamWatermarks,
500
+ currentPlanningIdentityWatermarks: input.payload.currentPlanningIdentityWatermarks,
494
501
  currentAiProfileIds: input.payload.currentAiProfileIds,
495
502
  currentAiProfileWatermarks: input.payload.currentAiProfileWatermarks,
496
503
  currentAiProfileChangeKeys: input.payload.currentAiProfileChangeKeys ?? new Map(),
@@ -583,6 +590,7 @@ export async function runWorkspacePushSyncService(input) {
583
590
  currentInitiativeWatermarks: input.payload.currentInitiativeWatermarks,
584
591
  currentWorkstreamIds: input.payload.currentWorkstreamIds,
585
592
  currentWorkstreamWatermarks: input.payload.currentWorkstreamWatermarks,
593
+ currentPlanningIdentityWatermarks: input.payload.currentPlanningIdentityWatermarks,
586
594
  currentAiProfileIds: input.payload.currentAiProfileIds,
587
595
  currentAiProfileWatermarks: input.payload.currentAiProfileWatermarks,
588
596
  currentAiProfileChangeKeys: input.payload.currentAiProfileChangeKeys ?? new Map(),
@@ -670,8 +678,18 @@ export async function runWorkspacePushSyncService(input) {
670
678
  && acknowledgedNonApplyingBatchOperationIdentities.size !== requestedAcknowledgements.length) {
671
679
  throw new Error('Persisted V2 push batch acknowledgement state does not match the frozen push plan.');
672
680
  }
681
+ const requestedSettledBatchOperationIdentities = input.settledBatchOperationIdentities || [];
682
+ if ((requestedSettledBatchOperationIdentities.length > 0
683
+ && !input.onAcceptedBatchSettled)
684
+ || new Set(requestedSettledBatchOperationIdentities).size
685
+ !== requestedSettledBatchOperationIdentities.length
686
+ || requestedSettledBatchOperationIdentities.some((identity) => !batchOperationIdentities.includes(identity))) {
687
+ throw new Error('Persisted V2 push batch settlement state does not match the frozen push plan.');
688
+ }
689
+ const settledBatchOperationIdentities = new Set(requestedSettledBatchOperationIdentities);
673
690
  let completedBatchCount = 0;
674
691
  let completedChangeCount = 0;
692
+ let firstPushFailure = null;
675
693
  const pushTransferReceipts = [];
676
694
  const abandonRetainedPushReceipts = async (errorCode) => {
677
695
  if (pushTransferReceipts.length === 0)
@@ -689,7 +707,8 @@ export async function runWorkspacePushSyncService(input) {
689
707
  const safeBatchChanges = batch.map((entry) => entry.safe);
690
708
  const expectedTaskEchoIds = workspaceSyncEngineExpectedTaskEchoIds(plainBatchChanges);
691
709
  const idempotencyKey = batchOperationIdentities[batchIndex];
692
- if (acknowledgedNonApplyingBatchOperationIdentities.has(idempotencyKey)) {
710
+ if (settledBatchOperationIdentities.has(idempotencyKey)
711
+ || acknowledgedNonApplyingBatchOperationIdentities.has(idempotencyKey)) {
693
712
  completedBatchCount += 1;
694
713
  completedChangeCount += plainBatchChanges.length;
695
714
  continue;
@@ -732,7 +751,12 @@ export async function runWorkspacePushSyncService(input) {
732
751
  const data = asObjectRecord(pushResult.data);
733
752
  const failedOperations = Array.from(new Set(plainBatchChanges.map((change) => change.op)));
734
753
  const failedContentChanges = plainBatchChanges.filter(isWorkspacePushContentChange).length;
735
- return {
754
+ const failureDomain = failedContentChanges === plainBatchChanges.length
755
+ ? 'content'
756
+ : failedContentChanges === 0
757
+ ? 'metadata'
758
+ : 'mixed';
759
+ const failureResult = {
736
760
  success: false,
737
761
  status: pushResult.status,
738
762
  error: typeof data.error === 'string' ? data.error : undefined,
@@ -744,11 +768,7 @@ export async function runWorkspacePushSyncService(input) {
744
768
  failedBatchIndex: batchIndex,
745
769
  failedChangeCount: plainBatchChanges.length,
746
770
  failedOperations,
747
- failureDomain: failedContentChanges === plainBatchChanges.length
748
- ? 'content'
749
- : failedContentChanges === 0
750
- ? 'metadata'
751
- : 'mixed',
771
+ failureDomain,
752
772
  },
753
773
  retryAfterMs: pushResult.retryAfterMs,
754
774
  transient: pushInProgress || isTransientWorkspaceSyncStatus(pushResult.status),
@@ -765,6 +785,7 @@ export async function runWorkspacePushSyncService(input) {
765
785
  currentInitiativeWatermarks: input.payload.currentInitiativeWatermarks,
766
786
  currentWorkstreamIds: input.payload.currentWorkstreamIds,
767
787
  currentWorkstreamWatermarks: input.payload.currentWorkstreamWatermarks,
788
+ currentPlanningIdentityWatermarks: input.payload.currentPlanningIdentityWatermarks,
768
789
  currentAiProfileIds: input.payload.currentAiProfileIds,
769
790
  currentAiProfileWatermarks: input.payload.currentAiProfileWatermarks,
770
791
  currentAiProfileChangeKeys: input.payload.currentAiProfileChangeKeys ?? new Map(),
@@ -793,8 +814,18 @@ export async function runWorkspacePushSyncService(input) {
793
814
  pushedWatermarks: new Map(),
794
815
  pushedTaskChangeKeys: new Map(),
795
816
  emittedEventIds: [],
796
- appliedTaskUpserts: []
817
+ appliedTaskUpserts: [],
797
818
  };
819
+ firstPushFailure ||= failureResult;
820
+ // Only content is isolated from later durable projections.
821
+ // Ownership, auth, and metadata failures can invalidate phase
822
+ // dependencies, so they still stop the attempt immediately.
823
+ if (failureDomain !== 'content')
824
+ return failureResult;
825
+ // Later phases contain independent relationships, events, and
826
+ // comments. Let them settle and checkpoint their non-applying
827
+ // receipts even though this attempt reports the content failure.
828
+ continue;
798
829
  }
799
830
  const pushData = asObjectRecord(pushResult.data);
800
831
  if (Array.isArray(pushData.emittedEventIds)) {
@@ -806,7 +837,29 @@ export async function runWorkspacePushSyncService(input) {
806
837
  }
807
838
  const normalizedTaskUpserts = parseWorkspaceSyncEngineAppliedTaskUpserts(pushData, expectedTaskEchoIds);
808
839
  appliedTaskUpserts.push(...normalizedTaskUpserts);
809
- if (pushResult.transferReceipt && normalizedTaskUpserts.length === 0) {
840
+ if (input.onAcceptedBatchSettled) {
841
+ if (!pushResult.transferReceipt) {
842
+ throw new Error('Accepted V2 push batch is missing its atomic settlement receipt.');
843
+ }
844
+ await input.onAcceptedBatchSettled({
845
+ operationIdentity: idempotencyKey,
846
+ settlementIdentityFingerprint: await computeCanonicalWorkspaceSyncSha256(createWorkspaceSyncEngineV2SettlementIdentityProjection({
847
+ operationIdentity: idempotencyKey,
848
+ changes: plainBatchChanges,
849
+ appliedTaskUpserts: normalizedTaskUpserts,
850
+ excludedProjections: effectiveV2ExcludedProjections,
851
+ })),
852
+ appliedTaskUpserts: normalizedTaskUpserts,
853
+ transferReceipt: pushResult.transferReceipt,
854
+ pushBoundary,
855
+ excludedProjections: effectiveV2ExcludedProjections,
856
+ });
857
+ const receiptIndex = pushTransferReceipts.indexOf(pushResult.transferReceipt);
858
+ if (receiptIndex >= 0)
859
+ pushTransferReceipts.splice(receiptIndex, 1);
860
+ settledBatchOperationIdentities.add(idempotencyKey);
861
+ }
862
+ else if (pushResult.transferReceipt && normalizedTaskUpserts.length === 0) {
810
863
  await remoteServices.acknowledgeNonApplyingTransferReceipts({
811
864
  workspaceId: input.workspaceId,
812
865
  receipts: [pushResult.transferReceipt],
@@ -828,6 +881,17 @@ export async function runWorkspacePushSyncService(input) {
828
881
  await abandonRetainedPushReceipts('WORKSPACE_SYNC_V2_PUSH_ATTEMPT_FAILED');
829
882
  throw error;
830
883
  }
884
+ if (firstPushFailure) {
885
+ return {
886
+ ...firstPushFailure,
887
+ batchProgress: {
888
+ ...firstPushFailure.batchProgress,
889
+ completedBatches: completedBatchCount,
890
+ completedChanges: completedChangeCount,
891
+ },
892
+ requestMs,
893
+ };
894
+ }
831
895
  return {
832
896
  success: true,
833
897
  syncedAt: new Date().toISOString(),
@@ -855,6 +919,7 @@ export async function runWorkspacePushSyncService(input) {
855
919
  currentInitiativeWatermarks: input.payload.currentInitiativeWatermarks,
856
920
  currentWorkstreamIds: input.payload.currentWorkstreamIds,
857
921
  currentWorkstreamWatermarks: input.payload.currentWorkstreamWatermarks,
922
+ currentPlanningIdentityWatermarks: input.payload.currentPlanningIdentityWatermarks,
858
923
  currentAiProfileIds: input.payload.currentAiProfileIds,
859
924
  currentAiProfileWatermarks: input.payload.currentAiProfileWatermarks,
860
925
  currentAiProfileChangeKeys: input.payload.currentAiProfileChangeKeys ?? new Map(),
@@ -0,0 +1,16 @@
1
+ import type { WorkspaceSyncTaskforceAgentSnapshot } from './workspaceSyncModel.js';
2
+ type SyncAuthorizationError = Error & {
3
+ code?: string;
4
+ statusCode?: number;
5
+ details?: Record<string, unknown>;
6
+ };
7
+ export declare function assertTaskforceAgentSyncPushAccess(input: {
8
+ agents: Iterable<WorkspaceSyncTaskforceAgentSnapshot>;
9
+ actorUserId: string | null;
10
+ hasUserFeatureGrant: (userId: string, featureKey: unknown) => boolean;
11
+ createSyncRouteError: (message: string, details: Record<string, unknown>, options?: {
12
+ code?: string;
13
+ statusCode?: number;
14
+ }) => SyncAuthorizationError;
15
+ }): void;
16
+ export {};
@@ -0,0 +1,20 @@
1
+ import { getTaskforceAgentModel } from '../shared/taskforceAgentModels.js';
2
+ import { INTERNAL_SUBSCRIPTION_MODEL_FEATURE_KEY } from '../shared/userFeatureGrants.js';
3
+ export function assertTaskforceAgentSyncPushAccess(input) {
4
+ const actorUserId = String(input.actorUserId || '').trim();
5
+ for (const agent of input.agents) {
6
+ if (agent.deletedAt)
7
+ continue;
8
+ const modelKey = String(agent.definition?.model?.modelKey || agent.modelKey || '').trim();
9
+ if (getTaskforceAgentModel(modelKey)?.source !== 'subscription_dev')
10
+ continue;
11
+ if (actorUserId && input.hasUserFeatureGrant(actorUserId, INTERNAL_SUBSCRIPTION_MODEL_FEATURE_KEY))
12
+ continue;
13
+ throw input.createSyncRouteError(`Subscription-backed Taskforce Agent ${agent.id} requires an internal user grant.`, {
14
+ source: 'apply.taskforceAgentUpsert',
15
+ agentId: agent.id,
16
+ actorUserId: actorUserId || null,
17
+ featureKey: INTERNAL_SUBSCRIPTION_MODEL_FEATURE_KEY,
18
+ }, { code: 'SUBSCRIPTION_MODEL_ACCESS_REQUIRED', statusCode: 403 });
19
+ }
20
+ }
@@ -4,6 +4,7 @@ import { WORKSPACE_SYNC_V3_NESTED_COVERAGE_SELECTOR } from './workspaceSyncV3Nes
4
4
  import { WORKSPACE_SYNC_V3_WORKFLOW_COVERAGE_SELECTOR } from './workspaceSyncV3WorkflowWireContract.js';
5
5
  import { WORKSPACE_SYNC_V3_PLANNING_ORDER_COVERAGE_SELECTOR } from './workspaceSyncV3PlanningOrderWireContract.js';
6
6
  import { WORKSPACE_SYNC_V3_TASK_COVER_COVERAGE_SELECTOR } from './workspaceSyncV3TaskCoverWireContract.js';
7
+ import { WORKSPACE_SYNC_V3_WORKFLOW_TASK_COVER_COVERAGE_SELECTOR } from './workspaceSyncV3WorkflowTaskCoverWireContract.js';
7
8
  export { WORKSPACE_SYNC_V3_COMBINED_CAPABILITY_VERSION } from './workspaceSyncV3CombinedWireContract.js';
8
9
  export function resolveRequestedCombinedFeedCoverage(env = process.env) {
9
10
  const requestedVersion = String(env.TASKFORCE_SYNC_V3_COMBINED_FEED_COVERAGE_VERSION || '').trim();
@@ -22,6 +23,9 @@ export function resolveRequestedCombinedFeedCoverage(env = process.env) {
22
23
  if (requestedVersion === String(WORKSPACE_SYNC_V3_TASK_COVER_COVERAGE_SELECTOR.coverageVersion)) {
23
24
  return WORKSPACE_SYNC_V3_TASK_COVER_COVERAGE_SELECTOR;
24
25
  }
26
+ if (requestedVersion === String(WORKSPACE_SYNC_V3_WORKFLOW_TASK_COVER_COVERAGE_SELECTOR.coverageVersion)) {
27
+ return WORKSPACE_SYNC_V3_WORKFLOW_TASK_COVER_COVERAGE_SELECTOR;
28
+ }
25
29
  throw new Error(`Unsupported TASKFORCE_SYNC_V3_COMBINED_FEED_COVERAGE_VERSION: ${requestedVersion}.`);
26
30
  }
27
31
  export function resolveCombinedFeedCapability(input) {
@@ -7,6 +7,7 @@ import { enqueueLocalInitiativeMutation, } from './localInitiativeOutboxService.
7
7
  import { isWorkspaceSyncV3PlanningActivationEnabled } from './planningActivation.js';
8
8
  import { serializeEntityActivityForSync } from './taskActivityJournal.js';
9
9
  import { WorkspaceSyncDurabilityStore, WorkspaceSyncIdempotencyConflictError } from './syncDurabilityStore.js';
10
+ import { readDurableOperationReplay } from './durableOperationReplay.js';
10
11
  import { buildInitiativeActivityEventId } from './initiativeActivityIdentity.js';
11
12
  const OPERATION_LEASE_MS = 30_000;
12
13
  export class DurableInitiativeMutationRouterDisabledError extends Error {
@@ -85,6 +86,9 @@ export function createDurableInitiativeMutationRouter(input) {
85
86
  if (persistedOutbox.domain !== 'initiative' || persistedOutbox.entityId !== initiativeId) {
86
87
  throw new WorkspaceSyncIdempotencyConflictError();
87
88
  }
89
+ store.assertOutboxOperationIdentity(persistedOutbox, {
90
+ domain: 'initiative', entityId: initiativeId, mutationKind: persistedOutbox.mutationKind,
91
+ });
88
92
  return {
89
93
  revisions: {
90
94
  entityRevision: persistedOutbox.baseEntityRevision,
@@ -99,18 +103,22 @@ export function createDurableInitiativeMutationRouter(input) {
99
103
  if (operationState?.status === 'committed') {
100
104
  if (!operationState.responseJson)
101
105
  throw new Error('Committed operation is missing its response.');
102
- const response = JSON.parse(operationState.responseJson);
103
- if (response.authoritative.entityId !== initiativeId) {
104
- throw new WorkspaceSyncIdempotencyConflictError();
105
- }
106
- const lifecycleMutation = response.authoritative.mutationKind === 'archive'
107
- || response.authoritative.mutationKind === 'unarchive';
106
+ const parsed = JSON.parse(operationState.responseJson);
107
+ const lifecycleMutation = parsed.authoritative.mutationKind === 'archive'
108
+ || parsed.authoritative.mutationKind === 'unarchive';
109
+ const replay = readDurableOperationReplay({
110
+ responseJson: operationState.responseJson,
111
+ operationId,
112
+ domain: 'initiative',
113
+ entityId: initiativeId,
114
+ mutationKind: parsed.authoritative.mutationKind,
115
+ revisionMode: lifecycleMutation ? 'both' : 'metadata',
116
+ });
117
+ const response = replay.response;
108
118
  return {
109
119
  revisions: {
110
- entityRevision: String(BigInt(response.authoritative.entityRevision) - 1n),
111
- lifecycleRevision: lifecycleMutation
112
- ? String(BigInt(response.authoritative.lifecycleRevision) - 1n)
113
- : response.authoritative.lifecycleRevision,
120
+ entityRevision: replay.baseEntityRevision,
121
+ lifecycleRevision: replay.baseLifecycleRevision,
114
122
  },
115
123
  persistedOutbox: null,
116
124
  committedResponse: response,
@@ -15,6 +15,20 @@ export declare class DurableOperationReplayIdentityConflictError extends Error {
15
15
  readonly code = "DURABLE_OPERATION_REPLAY_IDENTITY_CONFLICT";
16
16
  constructor(message?: string);
17
17
  }
18
+ export interface DurableOperationIdentityRecord {
19
+ operationId: string;
20
+ domain: string;
21
+ entityId: string;
22
+ mutationKind: string;
23
+ payloadFingerprint: string;
24
+ }
25
+ /**
26
+ * Canonical identity comparison for durable mutation records. Storage lanes may
27
+ * retain different reservation metadata, but an accepted operation can have
28
+ * only one exact domain/entity/mutation/payload meaning.
29
+ */
30
+ export declare function assertDurableOperationIdentity(actual: Readonly<DurableOperationIdentityRecord>, expected: Readonly<DurableOperationIdentityRecord>): void;
31
+ export declare function assertDurableOperationFingerprint(actual: string, expected: string): void;
18
32
  export interface DurableOperationReplayResult<Payload = unknown> {
19
33
  response: Readonly<Record<string, unknown>>;
20
34
  authoritative: DurableOperationAuthoritativeEntry<Payload>;
@@ -12,6 +12,24 @@ export class DurableOperationReplayIdentityConflictError extends Error {
12
12
  this.name = 'DurableOperationReplayIdentityConflictError';
13
13
  }
14
14
  }
15
+ /**
16
+ * Canonical identity comparison for durable mutation records. Storage lanes may
17
+ * retain different reservation metadata, but an accepted operation can have
18
+ * only one exact domain/entity/mutation/payload meaning.
19
+ */
20
+ export function assertDurableOperationIdentity(actual, expected) {
21
+ if (actual.operationId !== expected.operationId
22
+ || actual.domain !== expected.domain
23
+ || actual.entityId !== expected.entityId
24
+ || actual.mutationKind !== expected.mutationKind
25
+ || actual.payloadFingerprint !== expected.payloadFingerprint) {
26
+ throw new DurableOperationReplayIdentityConflictError();
27
+ }
28
+ }
29
+ export function assertDurableOperationFingerprint(actual, expected) {
30
+ if (!actual || actual !== expected)
31
+ throw new DurableOperationReplayIdentityConflictError();
32
+ }
15
33
  const DEFAULT_MAX_AUTHORITATIVE_ENTRIES = 1_024;
16
34
  const POSITIVE_REVISION = /^[1-9]\d*$/;
17
35
  const NON_NEGATIVE_REVISION = /^(0|[1-9]\d*)$/;
@@ -150,6 +150,9 @@ export function createDurableTaskAttachmentLinksMutationRouter(input) {
150
150
  || String(payload.cardCoverAssetId || '') !== String(cardCoverAssetId || '')) {
151
151
  throw new DurableTaskAttachmentLinksMutationError('Operation identity is assigned to different task attachment links.', 'TASK_ATTACHMENT_LINKS_IDENTITY_CONFLICT', 409);
152
152
  }
153
+ store.assertOutboxOperationIdentity(existing, {
154
+ domain: 'task-attachment-links', entityId: taskId, mutationKind: 'replace',
155
+ });
153
156
  const task = input.core.getTask(taskId, workspaceId);
154
157
  if (!task)
155
158
  throw new DurableTaskAttachmentLinksMutationError('Task not found.', 'TASK_NOT_FOUND', 404);
@@ -1,7 +1,7 @@
1
1
  import type { ChecklistItem, TaskItem } from '../../core/Taskforce.js';
2
2
  import type { DatabaseAdapter } from '../../storage/databaseAdapter.js';
3
3
  import { type LocalTaskChecklistOutboxCore } from './localTaskChecklistOutboxService.js';
4
- import { type DurableTaskChecklistServiceCore } from './taskChecklistMutationService.js';
4
+ import { type DurableTaskChecklistServiceCore, type TaskChecklistItemUpdateIntent } from './taskChecklistMutationService.js';
5
5
  export declare function resolveTaskChecklistMutationCapability(input: {
6
6
  runtimeMode: 'local' | 'cloud';
7
7
  surface: 'http' | 'mcp';
@@ -40,6 +40,7 @@ export declare function createDurableTaskChecklistMutationRouter(input: {
40
40
  taskId: string;
41
41
  items: readonly Partial<ChecklistItem>[];
42
42
  expectedDetailRevision?: string;
43
+ itemUpdateIntent?: TaskChecklistItemUpdateIntent;
43
44
  }): {
44
45
  state: "pending" | "committed";
45
46
  route: "local-outbox" | "cloud-acceptance";