@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
@@ -0,0 +1,84 @@
1
+ function normalizeRequired(value, label) {
2
+ const normalized = String(value || '').trim();
3
+ if (!normalized)
4
+ throw new Error(`${label} is required.`);
5
+ return normalized;
6
+ }
7
+ function mapRow(row) {
8
+ return {
9
+ tenantId: String(row.tenant_id || ''),
10
+ workspaceId: String(row.workspace_id || ''),
11
+ agentId: String(row.agent_id || ''),
12
+ connectionId: String(row.connection_id || ''),
13
+ ownerUserId: String(row.owner_user_id || ''),
14
+ providerKey: String(row.provider_key || ''),
15
+ modelSource: String(row.model_source || ''),
16
+ createdByUserId: String(row.created_by_user_id || ''),
17
+ updatedByUserId: String(row.updated_by_user_id || ''),
18
+ createdAt: String(row.created_at || ''),
19
+ updatedAt: String(row.updated_at || ''),
20
+ };
21
+ }
22
+ export class TaskforceAgentConnectionBindingStore {
23
+ db;
24
+ tenantId;
25
+ now;
26
+ constructor(db, tenantId, now = () => new Date()) {
27
+ this.db = db;
28
+ this.tenantId = tenantId;
29
+ this.now = now;
30
+ }
31
+ get(workspaceIdRaw, agentIdRaw) {
32
+ const workspaceId = String(workspaceIdRaw || '').trim();
33
+ const agentId = String(agentIdRaw || '').trim();
34
+ if (!workspaceId || !agentId)
35
+ return null;
36
+ const row = this.db.prepare(`
37
+ SELECT *
38
+ FROM taskforce_agent_connection_bindings
39
+ WHERE tenant_id = ? AND workspace_id = ? AND agent_id = ?
40
+ LIMIT 1
41
+ `).get(this.tenantId, workspaceId, agentId);
42
+ return row ? mapRow(row) : null;
43
+ }
44
+ bind(input) {
45
+ const workspaceId = normalizeRequired(input.workspaceId, 'Workspace ID');
46
+ const agentId = normalizeRequired(input.agentId, 'Agent ID');
47
+ const connectionId = normalizeRequired(input.connectionId, 'Connection ID');
48
+ const ownerUserId = normalizeRequired(input.ownerUserId, 'Connection owner');
49
+ const providerKey = normalizeRequired(input.providerKey, 'Provider key');
50
+ const modelSource = normalizeRequired(input.modelSource, 'Model source');
51
+ const actorUserId = normalizeRequired(input.actorUserId, 'Actor user');
52
+ const now = this.now().toISOString();
53
+ const result = this.db.prepare(`
54
+ INSERT INTO taskforce_agent_connection_bindings (
55
+ tenant_id, workspace_id, agent_id, connection_id, owner_user_id,
56
+ provider_key, model_source, created_by_user_id, updated_by_user_id,
57
+ created_at, updated_at
58
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
59
+ ON CONFLICT (tenant_id, workspace_id, agent_id) DO UPDATE SET
60
+ connection_id = excluded.connection_id,
61
+ owner_user_id = excluded.owner_user_id,
62
+ provider_key = excluded.provider_key,
63
+ model_source = excluded.model_source,
64
+ updated_by_user_id = excluded.updated_by_user_id,
65
+ updated_at = excluded.updated_at
66
+ WHERE taskforce_agent_connection_bindings.owner_user_id = excluded.owner_user_id
67
+ `).run(this.tenantId, workspaceId, agentId, connectionId, ownerUserId, providerKey, modelSource, actorUserId, actorUserId, now, now);
68
+ if (Number(result.changes || 0) === 0)
69
+ return null;
70
+ return this.get(workspaceId, agentId);
71
+ }
72
+ clear(workspaceIdRaw, agentIdRaw, ownerUserIdRaw) {
73
+ const workspaceId = String(workspaceIdRaw || '').trim();
74
+ const agentId = String(agentIdRaw || '').trim();
75
+ const ownerUserId = String(ownerUserIdRaw || '').trim();
76
+ if (!workspaceId || !agentId || !ownerUserId)
77
+ return false;
78
+ const result = this.db.prepare(`
79
+ DELETE FROM taskforce_agent_connection_bindings
80
+ WHERE tenant_id = ? AND workspace_id = ? AND agent_id = ? AND owner_user_id = ?
81
+ `).run(this.tenantId, workspaceId, agentId, ownerUserId);
82
+ return Number(result.changes || 0) > 0;
83
+ }
84
+ }
@@ -1,4 +1,4 @@
1
- import { randomUUID } from 'crypto';
1
+ import { createHash, randomUUID } from 'crypto';
2
2
  import { assertSynchronousTransactionResult, } from '../../storage/databaseAdapter.js';
3
3
  import { validateWorkspaceSyncEngineTransferCompletionGroup, } from '../engine/workspaceSyncEngineTransferCompletion.js';
4
4
  import { canonicalWorkspaceSyncJson } from '../v3/canonicalWorkspaceSyncJson.js';
@@ -1407,36 +1407,67 @@ export class LocalSyncExecutionPermitStore {
1407
1407
  const requiredAction = mutationReplay
1408
1408
  ? 'replay-operation-then-reconcile'
1409
1409
  : 'refetch-from-committed-cursor';
1410
- const coalescesRepeatedApplyFailure = errorCode === 'WORKSPACE_SYNC_V3_APPLY_NOT_COMMITTED'
1410
+ const coalescesLegacyApplyFailure = errorCode === 'WORKSPACE_SYNC_V3_APPLY_NOT_COMMITTED'
1411
1411
  || errorCode === 'WORKSPACE_SYNC_V3_ATTACHMENT_HYDRATION_NOT_COMMITTED';
1412
- if (coalescesRepeatedApplyFailure) {
1413
- const committedBoundary = canonicalWorkspaceSyncJson(permit.lastCommittedCursor);
1414
- const equivalentOpenObligation = this.db.prepare(`
1415
- SELECT obligation.*
1416
- FROM local_sync_recovery_obligations AS obligation
1417
- INNER JOIN local_sync_execution_permits AS origin
1418
- ON origin.permit_id = obligation.permit_id
1419
- WHERE obligation.workspace_id = ?
1420
- AND obligation.operation_class = ?
1421
- AND obligation.upstream_disposition = ?
1422
- AND obligation.required_action = ?
1423
- AND obligation.resolved_at IS NULL
1424
- AND origin.error_code = ?
1425
- ORDER BY obligation.created_at ASC
1426
- `).all(permit.workspaceId, permit.operationClass, disposition, requiredAction, errorCode).map(mapObligation).some((obligation) => ((obligation.operationIdentity || null) === (permit.operationIdentity || null)
1427
- && canonicalWorkspaceSyncJson(obligation.lastCommittedCursor) === committedBoundary));
1428
- if (equivalentOpenObligation)
1429
- return;
1412
+ const coalescingKey = mutationReplay || coalescesLegacyApplyFailure
1413
+ ? createHash('sha256').update(canonicalWorkspaceSyncJson(mutationReplay ? {
1414
+ workspaceId: permit.workspaceId,
1415
+ operationClass: permit.operationClass,
1416
+ operationIdentity: permit.operationIdentity || null,
1417
+ lastCommittedCursor: permit.lastCommittedCursor,
1418
+ requiredAction,
1419
+ } : {
1420
+ workspaceId: permit.workspaceId,
1421
+ operationClass: permit.operationClass,
1422
+ operationIdentity: permit.operationIdentity || null,
1423
+ upstreamDisposition: disposition,
1424
+ lastCommittedCursor: permit.lastCommittedCursor,
1425
+ requiredAction,
1426
+ errorCode,
1427
+ })).digest('hex')
1428
+ : null;
1429
+ // This store method normally runs inside the permit transition
1430
+ // transaction. The nested transaction gives PostgreSQL a savepoint
1431
+ // boundary while the partial unique index arbitrates concurrent
1432
+ // equivalent inserts without poisoning the outer transaction.
1433
+ let inserted = false;
1434
+ try {
1435
+ this.db.transaction(() => {
1436
+ this.db.prepare(`
1437
+ INSERT INTO local_sync_recovery_obligations (
1438
+ obligation_id, permit_id, workspace_id, operation_class,
1439
+ operation_identity, upstream_disposition,
1440
+ last_committed_cursor_json, required_action, coalescing_key,
1441
+ created_at, resolved_at
1442
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NULL)
1443
+ `).run(this.createId(), permit.permitId, permit.workspaceId, permit.operationClass, permit.operationIdentity, disposition, permit.lastCommittedCursor === null
1444
+ ? null
1445
+ : JSON.stringify(permit.lastCommittedCursor), requiredAction, coalescingKey, this.now());
1446
+ inserted = true;
1447
+ })();
1448
+ }
1449
+ catch (error) {
1450
+ const existing = coalescingKey
1451
+ ? this.db.prepare(`
1452
+ SELECT obligation_id
1453
+ FROM local_sync_recovery_obligations
1454
+ WHERE coalescing_key = ? AND resolved_at IS NULL
1455
+ `).get(coalescingKey)
1456
+ : undefined;
1457
+ if (!existing?.obligation_id)
1458
+ throw error;
1430
1459
  }
1460
+ if (inserted || !coalescingKey)
1461
+ return;
1431
1462
  this.db.prepare(`
1432
- INSERT INTO local_sync_recovery_obligations (
1433
- obligation_id, permit_id, workspace_id, operation_class,
1434
- operation_identity, upstream_disposition, last_committed_cursor_json,
1435
- required_action, created_at, resolved_at
1436
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL)
1437
- ON CONFLICT (permit_id) DO NOTHING
1438
- `).run(this.createId(), permit.permitId, permit.workspaceId, permit.operationClass, permit.operationIdentity, disposition, permit.lastCommittedCursor === null
1439
- ? null
1440
- : JSON.stringify(permit.lastCommittedCursor), requiredAction, this.now());
1463
+ UPDATE local_sync_recovery_obligations
1464
+ SET upstream_disposition = CASE
1465
+ WHEN upstream_disposition = 'accepted' OR ? = 'accepted' THEN 'accepted'
1466
+ WHEN upstream_disposition = 'unknown' OR ? = 'unknown' THEN 'unknown'
1467
+ WHEN upstream_disposition = 'rejected' OR ? = 'rejected' THEN 'rejected'
1468
+ ELSE upstream_disposition
1469
+ END
1470
+ WHERE coalescing_key = ? AND resolved_at IS NULL
1471
+ `).run(disposition, disposition, disposition, coalescingKey);
1441
1472
  }
1442
1473
  }
@@ -0,0 +1,10 @@
1
+ import type { LocalWorkspaceSyncPendingV2Push } from './localWorkspaceSyncRunnerState.js';
2
+ export interface LocalWorkspaceSyncPendingV2PushProgress {
3
+ effectiveTotalBatches: number;
4
+ settledBatches: number;
5
+ effectiveTotalChanges: number;
6
+ settledChanges: number;
7
+ remainingChanges: number;
8
+ firstUnsettledBatchIndex: number | null;
9
+ }
10
+ export declare function resolveLocalWorkspaceSyncPendingV2PushProgress(pending: LocalWorkspaceSyncPendingV2Push | null | undefined): LocalWorkspaceSyncPendingV2PushProgress | null;
@@ -0,0 +1,29 @@
1
+ export function resolveLocalWorkspaceSyncPendingV2PushProgress(pending) {
2
+ const plan = pending?.preparedPlan;
3
+ const settledIdentities = pending?.settledBatchOperationIdentities;
4
+ if (pending?.settlementVersion !== 1
5
+ || !plan
6
+ || !Array.isArray(settledIdentities)
7
+ || plan.batches.length !== plan.batchOperationIdentities.length
8
+ || new Set(plan.batchOperationIdentities).size !== plan.batchOperationIdentities.length
9
+ || new Set(settledIdentities).size !== settledIdentities.length
10
+ || settledIdentities.some((identity) => !plan.batchOperationIdentities.includes(identity))) {
11
+ return null;
12
+ }
13
+ const settled = new Set(settledIdentities);
14
+ const effectiveTotalChanges = plan.batches.reduce((total, batch) => total + batch.length, 0);
15
+ const settledChanges = plan.batches.reduce((total, batch, index) => (settled.has(plan.batchOperationIdentities[index])
16
+ ? total + batch.length
17
+ : total), 0);
18
+ const firstUnsettledBatchIndex = plan.batchOperationIdentities.findIndex((identity) => !settled.has(identity));
19
+ return {
20
+ effectiveTotalBatches: plan.batches.length,
21
+ settledBatches: settled.size,
22
+ effectiveTotalChanges,
23
+ settledChanges,
24
+ remainingChanges: effectiveTotalChanges - settledChanges,
25
+ firstUnsettledBatchIndex: firstUnsettledBatchIndex < 0
26
+ ? null
27
+ : firstUnsettledBatchIndex,
28
+ };
29
+ }
@@ -1,5 +1,5 @@
1
1
  import type { DatabaseAdapter } from '../../storage/databaseAdapter.js';
2
- import type { WorkspaceSyncDeltaDiagnostics, WorkspaceSyncPayload } from '../workspaceSyncModel.js';
2
+ import type { WorkspaceSyncDeltaDiagnostics, WorkspaceSyncDurableTaskRevision, WorkspaceSyncPayload, WorkspaceSyncTaskSnapshot } from '../workspaceSyncModel.js';
3
3
  import { type WorkspacePushPreparedPlan } from '../workspacePushPreparedPlan.js';
4
4
  import type { WorkspaceSyncPhase, WorkspaceSyncPushBaselineSnapshot } from '../workspaceSyncState.js';
5
5
  import type { LocalSyncCoordinatorCommandStatus } from './localSyncCoordinatorTypes.js';
@@ -30,6 +30,7 @@ export interface EncodedWorkspaceSyncPayload {
30
30
  currentInitiativeWatermarks: EncodedStringMap;
31
31
  currentWorkstreamIds: string[];
32
32
  currentWorkstreamWatermarks: EncodedStringMap;
33
+ currentPlanningIdentityWatermarks?: EncodedStringMap;
33
34
  currentAiProfileIds: string[];
34
35
  currentAiProfileWatermarks: EncodedStringMap;
35
36
  currentAiProfileChangeKeys?: EncodedStringMap;
@@ -68,8 +69,20 @@ export interface LocalWorkspaceSyncPendingV2Push {
68
69
  preparedPlan: WorkspacePushPreparedPlan | null;
69
70
  preparedPlanFingerprint: string | null;
70
71
  acknowledgedNonApplyingBatchOperationIdentities: string[];
72
+ settlementVersion?: 1;
73
+ settledBatchOperationIdentities?: string[];
74
+ settledBatchContributions?: LocalWorkspaceSyncSettledV2PushBatch[];
71
75
  lastBatchProgress: LocalWorkspaceSyncPendingV2PushBatchProgress | null;
72
76
  }
77
+ export interface LocalWorkspaceSyncSettledV2PushBatch {
78
+ operationIdentity: string;
79
+ settlementIdentityFingerprint: string;
80
+ appliedTaskUpserts: Array<{
81
+ archived: boolean;
82
+ task: WorkspaceSyncTaskSnapshot;
83
+ durableRevision?: WorkspaceSyncDurableTaskRevision;
84
+ }>;
85
+ }
73
86
  export interface LocalWorkspaceSyncPendingV2PushBatchProgress {
74
87
  totalBatches: number;
75
88
  completedBatches: number;
@@ -144,6 +157,7 @@ export declare function createLocalWorkspaceSyncPendingV2Push(input: {
144
157
  repairMode: boolean;
145
158
  }): LocalWorkspaceSyncPendingV2Push;
146
159
  export declare function fingerprintLocalWorkspaceSyncPreparedPlan(plan: WorkspacePushPreparedPlan): string;
160
+ export declare function upgradeLocalWorkspaceSyncPendingV2PushSettlement(pending: LocalWorkspaceSyncPendingV2Push): LocalWorkspaceSyncPendingV2Push;
147
161
  export declare function createDefaultLocalWorkspaceSyncRunnerCheckpoint(): LocalWorkspaceSyncRunnerCheckpoint;
148
162
  export declare class LocalWorkspaceSyncRunnerStateStore {
149
163
  private readonly db;
@@ -1,6 +1,7 @@
1
1
  import { fingerprintWorkspaceSyncPayload, } from '../v3/syncDurabilityStore.js';
2
2
  import { canonicalWorkspaceSyncJson } from '../v3/canonicalWorkspaceSyncJson.js';
3
3
  import { WORKSPACE_SYNC_V2_EXCLUDABLE_PROJECTIONS, } from '../v3/workspaceSyncV2ProjectionExclusions.js';
4
+ import { createWorkspaceSyncEngineV2SettlementIdentityProjection } from '../engine/workspaceSyncEnginePushCompletion.js';
4
5
  import { WORKSPACE_PUSH_PREPARED_PLAN_VERSION, } from '../workspacePushPreparedPlan.js';
5
6
  import { LOCAL_SYNC_COORDINATOR_ID } from './localSyncCoordinatorTypes.js';
6
7
  export const LOCAL_WORKSPACE_SYNC_RUNNER_STATE_VERSION = 1;
@@ -123,6 +124,7 @@ const ENCODED_PAYLOAD_OPTIONAL_KEYS = [
123
124
  'currentTaskChangeKeys',
124
125
  'currentTaskRelationshipChangeKeys',
125
126
  'currentTaxonomyChangeKey',
127
+ 'currentPlanningIdentityWatermarks',
126
128
  'currentAiProfileChangeKeys',
127
129
  'currentTaskforceAgentIds',
128
130
  'currentTaskforceAgentWatermarks',
@@ -176,6 +178,7 @@ const OPTIONAL_DIAGNOSTIC_DOMAINS = [
176
178
  'taskforceAgents',
177
179
  'taskforceAgentSkills',
178
180
  'agentConversations',
181
+ 'planningIdentities',
179
182
  ];
180
183
  function isDeltaDiagnostics(value) {
181
184
  if (!isRecord(value) || !hasExactKeys(value, [
@@ -240,6 +243,7 @@ function isEncodedWorkspaceSyncPayload(value) {
240
243
  'currentTaskWatermarks',
241
244
  'currentTaskChangeKeys',
242
245
  'currentTaskRelationshipChangeKeys',
246
+ 'currentPlanningIdentityWatermarks',
243
247
  'currentAiProfileChangeKeys',
244
248
  'currentTaskforceAgentWatermarks',
245
249
  'currentTaskforceAgentSkillWatermarks',
@@ -302,6 +306,7 @@ export function encodeWorkspaceSyncPayload(payload) {
302
306
  currentInitiativeWatermarks: encodeStringMap(payload.currentInitiativeWatermarks, 'Initiative watermarks'),
303
307
  currentWorkstreamIds: encodeStringSet(payload.currentWorkstreamIds, 'Current workstream ids'),
304
308
  currentWorkstreamWatermarks: encodeStringMap(payload.currentWorkstreamWatermarks, 'Workstream watermarks'),
309
+ currentPlanningIdentityWatermarks: encodeStringMap(payload.currentPlanningIdentityWatermarks || new Map(), 'Planning identity watermarks'),
305
310
  currentAiProfileIds: encodeStringSet(payload.currentAiProfileIds, 'Current AI profile ids'),
306
311
  currentAiProfileWatermarks: encodeStringMap(payload.currentAiProfileWatermarks, 'AI profile watermarks'),
307
312
  currentAiProfileChangeKeys: encodeOptionalStringMap(payload.currentAiProfileChangeKeys, 'AI profile change keys'),
@@ -356,6 +361,7 @@ export function decodeWorkspaceSyncPayload(encoded) {
356
361
  currentInitiativeWatermarks: new Map(encoded.currentInitiativeWatermarks),
357
362
  currentWorkstreamIds: new Set(encoded.currentWorkstreamIds),
358
363
  currentWorkstreamWatermarks: new Map(encoded.currentWorkstreamWatermarks),
364
+ currentPlanningIdentityWatermarks: new Map(encoded.currentPlanningIdentityWatermarks || []),
359
365
  currentAiProfileIds: new Set(encoded.currentAiProfileIds),
360
366
  currentAiProfileWatermarks: new Map(encoded.currentAiProfileWatermarks),
361
367
  currentAiProfileChangeKeys: encoded.currentAiProfileChangeKeys
@@ -411,6 +417,21 @@ export function createLocalWorkspaceSyncPendingV2Push(input) {
411
417
  export function fingerprintLocalWorkspaceSyncPreparedPlan(plan) {
412
418
  return fingerprintWorkspaceSyncPayload(plan);
413
419
  }
420
+ export function upgradeLocalWorkspaceSyncPendingV2PushSettlement(pending) {
421
+ if (pending.settlementVersion === 1)
422
+ return structuredClone(pending);
423
+ if (!pending.preparedPlan || !pending.preparedPlanFingerprint) {
424
+ throw new Error('The frozen V2 push must have a prepared plan before settlement activation.');
425
+ }
426
+ return {
427
+ ...structuredClone(pending),
428
+ settlementVersion: 1,
429
+ settledBatchOperationIdentities: [
430
+ ...pending.acknowledgedNonApplyingBatchOperationIdentities,
431
+ ],
432
+ settledBatchContributions: [],
433
+ };
434
+ }
414
435
  function isPushBaseline(value) {
415
436
  if (!isRecord(value))
416
437
  return false;
@@ -421,6 +442,7 @@ function isPushBaseline(value) {
421
442
  'taskRelationshipChangeKeys',
422
443
  'initiativeWatermarks',
423
444
  'workstreamWatermarks',
445
+ 'planningIdentityWatermarks',
424
446
  'aiProfileWatermarks',
425
447
  'aiProfileChangeKeys',
426
448
  'taskforceAgentWatermarks',
@@ -458,6 +480,7 @@ function isPushBaseline(value) {
458
480
  'taskforceAgentWatermarks',
459
481
  'taskforceAgentSkillWatermarks',
460
482
  'agentConversationWatermarks',
483
+ 'planningIdentityWatermarks',
461
484
  ];
462
485
  if (optionalPairs.some((key) => value[key] !== undefined && !isStringPairArray(value[key])))
463
486
  return false;
@@ -470,7 +493,9 @@ function isPushBaseline(value) {
470
493
  return true;
471
494
  }
472
495
  function isPendingV2Push(value) {
473
- if (!isRecord(value) || !hasExactKeys(value, [
496
+ if (!isRecord(value))
497
+ return false;
498
+ const legacyKeys = [
474
499
  'signature',
475
500
  'payloadFingerprint',
476
501
  'frozenPayload',
@@ -480,8 +505,71 @@ function isPendingV2Push(value) {
480
505
  'preparedPlanFingerprint',
481
506
  'acknowledgedNonApplyingBatchOperationIdentities',
482
507
  'lastBatchProgress',
483
- ]))
508
+ ];
509
+ const settlementKeys = [
510
+ ...legacyKeys,
511
+ 'settlementVersion',
512
+ 'settledBatchOperationIdentities',
513
+ 'settledBatchContributions',
514
+ ];
515
+ const hasLegacyShape = hasExactKeys(value, legacyKeys);
516
+ const hasSettlementShape = hasExactKeys(value, settlementKeys);
517
+ if (!hasLegacyShape && !hasSettlementShape)
484
518
  return false;
519
+ const settledBatchOperationIdentities = isStringArray(value.settledBatchOperationIdentities) ? value.settledBatchOperationIdentities : null;
520
+ const settledBatchContributions = Array.isArray(value.settledBatchContributions) ? value.settledBatchContributions : null;
521
+ const preparedPlan = isPreparedV2PushPlan(value.preparedPlan)
522
+ ? value.preparedPlan
523
+ : null;
524
+ const settlementValid = hasLegacyShape || (value.settlementVersion === 1
525
+ && settledBatchOperationIdentities !== null
526
+ && new Set(settledBatchOperationIdentities).size
527
+ === settledBatchOperationIdentities.length
528
+ && settledBatchOperationIdentities.every((identity) => /^[a-f0-9]{64}$/.test(identity))
529
+ && settledBatchContributions !== null
530
+ && settledBatchContributions.every((entry) => (isRecord(entry)
531
+ && hasExactKeys(entry, [
532
+ 'operationIdentity',
533
+ 'settlementIdentityFingerprint',
534
+ 'appliedTaskUpserts',
535
+ ])
536
+ && typeof entry.operationIdentity === 'string'
537
+ && /^[a-f0-9]{64}$/.test(entry.operationIdentity)
538
+ && typeof entry.settlementIdentityFingerprint === 'string'
539
+ && /^[a-f0-9]{64}$/.test(entry.settlementIdentityFingerprint)
540
+ && Array.isArray(entry.appliedTaskUpserts)
541
+ && entry.appliedTaskUpserts.every((upsert) => (isRecord(upsert)
542
+ && hasRequiredAndAllowedKeys(upsert, ['archived', 'task'], ['durableRevision'])
543
+ && typeof upsert.archived === 'boolean'
544
+ && isRecord(upsert.task)
545
+ && isNonEmptyText(upsert.task.id)
546
+ && isJson(upsert.task)
547
+ && (upsert.durableRevision === undefined
548
+ || (isRecord(upsert.durableRevision) && isJson(upsert.durableRevision)))))))
549
+ && new Set(settledBatchContributions.map((entry) => entry.operationIdentity)).size === settledBatchContributions.length
550
+ && settledBatchContributions.every((entry) => (settledBatchOperationIdentities.includes(entry.operationIdentity))));
551
+ const settlementContributionsMatchPlan = hasLegacyShape || (preparedPlan !== null
552
+ && settledBatchContributions !== null
553
+ && settledBatchContributions.every((rawEntry) => {
554
+ const entry = rawEntry;
555
+ const batchIndex = preparedPlan.batchOperationIdentities.indexOf(entry.operationIdentity);
556
+ if (batchIndex < 0)
557
+ return false;
558
+ const changes = preparedPlan.batches[batchIndex].map((planEntry) => (planEntry.preparedChange
559
+ || value.frozenPayload
560
+ .changes[planEntry.sourceChangeIndex]));
561
+ try {
562
+ return fingerprintWorkspaceSyncPayload(createWorkspaceSyncEngineV2SettlementIdentityProjection({
563
+ operationIdentity: entry.operationIdentity,
564
+ changes,
565
+ appliedTaskUpserts: entry.appliedTaskUpserts,
566
+ excludedProjections: preparedPlan.ownership.combinedExcludedProjections,
567
+ })) === entry.settlementIdentityFingerprint;
568
+ }
569
+ catch {
570
+ return false;
571
+ }
572
+ }));
485
573
  return isNonEmptyText(value.signature)
486
574
  && typeof value.payloadFingerprint === 'string'
487
575
  && /^[a-f0-9]{64}$/.test(value.payloadFingerprint)
@@ -499,6 +587,12 @@ function isPendingV2Push(value) {
499
587
  < value.frozenPayload.changes.length))))
500
588
  && isStringArray(value.acknowledgedNonApplyingBatchOperationIdentities)
501
589
  && value.acknowledgedNonApplyingBatchOperationIdentities.every((identity) => /^[a-f0-9]{64}$/.test(identity))
590
+ && settlementValid
591
+ && settlementContributionsMatchPlan
592
+ && (!hasSettlementShape
593
+ || (preparedPlan !== null
594
+ && settledBatchOperationIdentities !== null
595
+ && settledBatchOperationIdentities.every((identity) => preparedPlan.batchOperationIdentities.includes(identity))))
502
596
  && (value.lastBatchProgress === null
503
597
  || (isPendingV2PushBatchProgress(value.lastBatchProgress)
504
598
  && value.lastBatchProgress.completedChanges <= value.frozenPayload.changes.length
@@ -582,6 +676,9 @@ function normalizePendingV2Push(value) {
582
676
  'preparedPlan',
583
677
  'preparedPlanFingerprint',
584
678
  'acknowledgedNonApplyingBatchOperationIdentities',
679
+ 'settlementVersion',
680
+ 'settledBatchOperationIdentities',
681
+ 'settledBatchContributions',
585
682
  'lastBatchProgress',
586
683
  ])) {
587
684
  return value;
@@ -43,6 +43,7 @@ export declare class WorkspaceSyncCredentialBrokerError extends Error {
43
43
  export declare class WorkspaceSyncCredentialBroker {
44
44
  private readonly options;
45
45
  private capability;
46
+ private boundIdentity;
46
47
  private blockedReason;
47
48
  constructor(options: {
48
49
  sessionCookieName: string;
@@ -12,6 +12,9 @@ export class WorkspaceSyncCredentialBrokerError extends Error {
12
12
  export class WorkspaceSyncCredentialBroker {
13
13
  options;
14
14
  capability = null;
15
+ // Retain the non-secret principal fence while auth is blocked so a logout or
16
+ // expired cookie cannot let another account adopt the live coordinator.
17
+ boundIdentity = null;
15
18
  blockedReason = 'server-restart';
16
19
  constructor(options) {
17
20
  this.options = options;
@@ -39,16 +42,21 @@ export class WorkspaceSyncCredentialBroker {
39
42
  throw new WorkspaceSyncCredentialBrokerError('The Taskforce session is not valid for the requested workspace.', 'SYNC_COORDINATOR_AUTH_INVALID');
40
43
  }
41
44
  const existing = this.capability;
45
+ const identity = existing || this.boundIdentity;
42
46
  const samePrincipal = existing
43
47
  && existing.workspaceId === validated.workspaceId
44
48
  && existing.principal.userId === validated.principal.userId
45
49
  && existing.principal.tenantId === validated.principal.tenantId;
46
- if (existing && !samePrincipal && !input.allowPrincipalRebind) {
50
+ const sameBoundIdentity = identity
51
+ && identity.workspaceId === validated.workspaceId
52
+ && identity.principal.userId === validated.principal.userId
53
+ && identity.principal.tenantId === validated.principal.tenantId;
54
+ if (identity && !sameBoundIdentity && !input.allowPrincipalRebind) {
47
55
  throw new WorkspaceSyncCredentialBrokerError('A different Taskforce principal is already bound to this workspace coordinator.', 'SYNC_COORDINATOR_PRINCIPAL_CONFLICT');
48
56
  }
49
- if (samePrincipal
50
- && input.coordinatorGeneration < existing.coordinatorGeneration) {
51
- throw new WorkspaceSyncCredentialBrokerError(`Coordinator generation ${input.coordinatorGeneration} is stale; current generation is ${existing.coordinatorGeneration}.`, 'SYNC_COORDINATOR_STALE_GENERATION');
57
+ if (sameBoundIdentity
58
+ && input.coordinatorGeneration < identity.coordinatorGeneration) {
59
+ throw new WorkspaceSyncCredentialBrokerError(`Coordinator generation ${input.coordinatorGeneration} is stale; current generation is ${identity.coordinatorGeneration}.`, 'SYNC_COORDINATOR_STALE_GENERATION');
52
60
  }
53
61
  const authorizedCookies = samePrincipal
54
62
  ? new Map(existing.authorizedCookies)
@@ -67,6 +75,11 @@ export class WorkspaceSyncCredentialBroker {
67
75
  cookieHeader,
68
76
  authorizedCookies,
69
77
  };
78
+ this.boundIdentity = {
79
+ workspaceId: validated.workspaceId,
80
+ coordinatorGeneration: input.coordinatorGeneration,
81
+ principal: validated.principal,
82
+ };
70
83
  this.blockedReason = null;
71
84
  return this.readSnapshot();
72
85
  }
@@ -143,6 +156,11 @@ export class WorkspaceSyncCredentialBroker {
143
156
  cookieHeader: prepared.cookieHeader,
144
157
  authorizedCookies: new Map([[cookieValue, prepared.validation]]),
145
158
  };
159
+ this.boundIdentity = {
160
+ workspaceId: prepared.targetWorkspaceId,
161
+ coordinatorGeneration: prepared.targetCoordinatorGeneration,
162
+ principal: prepared.principal,
163
+ };
146
164
  prepared.activated = true;
147
165
  this.blockedReason = null;
148
166
  return this.readSnapshot();
@@ -159,6 +177,11 @@ export class WorkspaceSyncCredentialBroker {
159
177
  coordinatorGeneration,
160
178
  authorizedCookies: new Map(prepared.sourceCapability.authorizedCookies),
161
179
  };
180
+ this.boundIdentity = {
181
+ workspaceId: prepared.sourceWorkspaceId,
182
+ coordinatorGeneration,
183
+ principal: prepared.sourceCapability.principal,
184
+ };
162
185
  prepared.activated = false;
163
186
  this.blockedReason = null;
164
187
  }
@@ -175,6 +198,9 @@ export class WorkspaceSyncCredentialBroker {
175
198
  throw new WorkspaceSyncCredentialBrokerError('The coordinator generation transition is invalid.', 'SYNC_COORDINATOR_STALE_GENERATION');
176
199
  }
177
200
  this.capability.coordinatorGeneration = input.toCoordinatorGeneration;
201
+ if (this.boundIdentity) {
202
+ this.boundIdentity.coordinatorGeneration = input.toCoordinatorGeneration;
203
+ }
178
204
  return this.readSnapshot();
179
205
  }
180
206
  /**
@@ -197,6 +223,9 @@ export class WorkspaceSyncCredentialBroker {
197
223
  throw new WorkspaceSyncCredentialBrokerError('The coordinator generation transition is stale or non-adjacent.', 'SYNC_COORDINATOR_STALE_GENERATION');
198
224
  }
199
225
  capability.coordinatorGeneration = input.toCoordinatorGeneration;
226
+ if (this.boundIdentity) {
227
+ this.boundIdentity.coordinatorGeneration = input.toCoordinatorGeneration;
228
+ }
200
229
  return this.readSnapshot();
201
230
  }
202
231
  authorizeCookieHeader(input) {
@@ -1,4 +1,4 @@
1
- import { type WorkspaceSyncContentHead, type WorkspaceSyncContentKind, type WorkspaceSyncContentScope, type WorkspaceSyncContentVersionStore } from './workspaceSyncContentVersionStore.js';
1
+ import { type WorkspaceSyncContentHead, type WorkspaceSyncContentKind, type WorkspaceSyncContentScope, type WorkspaceSyncContentTombstoneProvenance, type WorkspaceSyncContentVersionStore } from './workspaceSyncContentVersionStore.js';
2
2
  export type WorkspaceSyncContentTombstoneInput = WorkspaceSyncContentScope & {
3
3
  kind: WorkspaceSyncContentKind;
4
4
  logicalPath: string;
@@ -6,6 +6,7 @@ export type WorkspaceSyncContentTombstoneInput = WorkspaceSyncContentScope & {
6
6
  publishedAt: string;
7
7
  deletedAt: string;
8
8
  retireGcAfter?: string | null;
9
+ provenance?: WorkspaceSyncContentTombstoneProvenance;
9
10
  };
10
11
  export interface WorkspaceSyncContentLifecyclePort {
11
12
  tombstone(input: WorkspaceSyncContentTombstoneInput): WorkspaceSyncContentHead;
@@ -48,6 +48,36 @@ export type WorkspaceSyncContentHead = WorkspaceSyncContentScope & {
48
48
  publishedAt: string;
49
49
  deletedAt: string | null;
50
50
  };
51
+ /**
52
+ * Durable, queryable attribution for an accepted content tombstone. operationId/
53
+ * actorId are optional because the current WorkspaceSyncChange wire format and
54
+ * apply pipeline don't yet carry per-change requester identity from origin
55
+ * through to this layer — threading that through is a larger, separate change
56
+ * (it would mean extending the delete-change payload and every intermediate
57
+ * outbox/apply layer, not just this store). What IS reliably knowable at the
58
+ * point a tombstone is admitted is recorded: which admission path produced it,
59
+ * the source revision it was admitted at, which runtime applied it, and
60
+ * whether workspace repair was involved.
61
+ */
62
+ export type WorkspaceSyncContentTombstoneProvenance = {
63
+ source: 'explicit-delete' | 'synchronized-tombstone' | 'repair';
64
+ operationId?: string | null;
65
+ actorId?: string | null;
66
+ sourceRuntime?: string | null;
67
+ repairInvolved?: boolean;
68
+ };
69
+ export type WorkspaceSyncContentTombstoneProvenanceRecord = WorkspaceSyncContentScope & {
70
+ id: string;
71
+ kind: WorkspaceSyncContentKind;
72
+ logicalPath: string;
73
+ source: string;
74
+ operationId: string | null;
75
+ actorId: string | null;
76
+ sourceRuntime: string | null;
77
+ sourceUpdatedAt: string;
78
+ repairInvolved: boolean;
79
+ recordedAt: string;
80
+ };
51
81
  export type WorkspaceSyncContentLegacyFallback = {
52
82
  source: 'legacy';
53
83
  };
@@ -141,7 +171,15 @@ export declare class WorkspaceSyncContentVersionStore {
141
171
  publishedAt: string;
142
172
  deletedAt: string;
143
173
  retireGcAfter?: string | null;
174
+ provenance?: WorkspaceSyncContentTombstoneProvenance;
144
175
  }): WorkspaceSyncContentHead;
176
+ private recordTombstoneProvenance;
177
+ /** Queryable read side for tombstone provenance — most recent admission first. */
178
+ listTombstoneProvenance(input: WorkspaceSyncContentScope & {
179
+ kind?: WorkspaceSyncContentKind;
180
+ logicalPath?: string;
181
+ limit?: number;
182
+ }): WorkspaceSyncContentTombstoneProvenanceRecord[];
145
183
  resolveHead(input: WorkspaceSyncContentScope & {
146
184
  kind: WorkspaceSyncContentKind;
147
185
  logicalPath: string;