@taskforcehq/taskforce 0.3.329 → 0.3.332

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (363) hide show
  1. package/README.md +7 -2
  2. package/dist/Taskforce.module.css +290 -45
  3. package/dist/components/features/AiProfilesModule.js +3 -5
  4. package/dist/components/features/TaskSettings.js +70 -14
  5. package/dist/components/features/TaskforceAgentsModule.d.ts +1 -2
  6. package/dist/components/features/TaskforceAgentsModule.js +586 -116
  7. package/dist/components/features/agentCapabilities/AgentCapabilitiesPrototype.d.ts +2 -2
  8. package/dist/components/features/agentCapabilities/AgentCapabilitiesPrototype.js +2 -2
  9. package/dist/components/features/agentConnections/AgentConnectionControl.d.ts +15 -0
  10. package/dist/components/features/agentConnections/AgentConnectionControl.js +125 -0
  11. package/dist/components/features/agentConnections/ModelConnectionsPanel.d.ts +18 -0
  12. package/dist/components/features/agentConnections/ModelConnectionsPanel.js +393 -0
  13. package/dist/components/features/agentConnections/modelConnectionsApi.d.ts +65 -0
  14. package/dist/components/features/agentConnections/modelConnectionsApi.js +129 -0
  15. package/dist/components/features/planning/PlanningModule.js +15 -3
  16. package/dist/components/features/planning/planningMetadata.d.ts +10 -0
  17. package/dist/components/features/planning/planningMetadata.js +8 -0
  18. package/dist/components/features/taskforceAgentAssignments/AgentBehaviorAssignments.js +15 -24
  19. package/dist/components/features/taskforceAgentEditorModel.d.ts +2 -1
  20. package/dist/components/features/taskforceAgentEditorModel.js +3 -1
  21. package/dist/components/features/workflowManager/workflowManagerApi.d.ts +1 -1
  22. package/dist/components/features/workflowManager/workflowManagerApi.js +3 -0
  23. package/dist/components/task/TaskWorkflowAssignmentField.js +68 -10
  24. package/dist/components/views/StandaloneLayout.js +62 -27
  25. package/dist/components/views/panels/PlanningDrawer.d.ts +2 -1
  26. package/dist/components/views/panels/PlanningDrawer.js +12 -8
  27. package/dist/components/views/standalone/modals/SyncStatusModal.d.ts +4 -3
  28. package/dist/components/views/standalone/modals/SyncStatusModal.js +33 -38
  29. package/dist/config/envSchema.js +55 -1
  30. package/dist/core/McpTokenService.d.ts +25 -1
  31. package/dist/core/McpTokenService.js +106 -15
  32. package/dist/core/TaskChecklistCommandService.d.ts +27 -0
  33. package/dist/core/TaskChecklistCommandService.js +83 -5
  34. package/dist/core/TaskLifecycleCommandService.d.ts +3 -1
  35. package/dist/core/TaskLifecycleCommandService.js +6 -2
  36. package/dist/core/Taskforce.d.ts +43 -3
  37. package/dist/core/Taskforce.js +158 -7
  38. package/dist/core/types.d.ts +9 -0
  39. package/dist/documentReviews/DocumentReviewCommentStore.d.ts +2 -0
  40. package/dist/documentReviews/DocumentReviewCommentStore.js +28 -9
  41. package/dist/documentReviews/commandService.d.ts +2 -1
  42. package/dist/documentReviews/commandService.js +6 -3
  43. package/dist/hooks/sync/orchestratorShared.d.ts +1 -0
  44. package/dist/hooks/sync/orchestratorShared.js +2 -0
  45. package/dist/hooks/sync/useLocalSyncCoordinatorSnapshot.d.ts +3 -0
  46. package/dist/hooks/sync/useLocalSyncCoordinatorSnapshot.js +85 -9
  47. package/dist/hooks/sync/useSyncStatusControls.d.ts +4 -1
  48. package/dist/hooks/sync/useSyncStatusControls.js +47 -11
  49. package/dist/hooks/useSyncOrchestrator.d.ts +3 -0
  50. package/dist/hooks/useSyncOrchestrator.js +111 -2
  51. package/dist/hooks/useTaskData.d.ts +31 -1
  52. package/dist/hooks/useTaskData.js +29 -7
  53. package/dist/hooks/useTaskMutations.d.ts +3 -1
  54. package/dist/hooks/useTaskMutations.js +46 -12
  55. package/dist/hooks/useTaskforce.d.ts +2 -0
  56. package/dist/hooks/useTaskforce.js +11 -2
  57. package/dist/mcp/clientRegistry.d.ts +2 -2
  58. package/dist/mcp/clientRegistry.js +1 -1
  59. package/dist/mcp/documentAssetRegistrar.js +9 -6
  60. package/dist/mcp/durableTaskMutationRouter.d.ts +4 -1
  61. package/dist/mcp/durableTaskMutationRouter.js +10 -0
  62. package/dist/mcp/durableTaskRelationshipMutationRouter.js +4 -0
  63. package/dist/mcp/httpProtocolRouting.d.ts +11 -0
  64. package/dist/mcp/httpProtocolRouting.js +22 -0
  65. package/dist/mcp/localCliHealth.d.ts +2 -2
  66. package/dist/mcp/localCliHealth.js +2 -2
  67. package/dist/mcp/localServiceProxy.d.ts +1 -0
  68. package/dist/mcp/localServiceProxy.js +530 -68
  69. package/dist/mcp/planningAttachmentCommandAdapter.d.ts +3 -1
  70. package/dist/mcp/planningAttachmentCommandAdapter.js +20 -2
  71. package/dist/mcp/runtime.d.ts +54 -79
  72. package/dist/mcp/runtime.js +408 -102
  73. package/dist/mcp/taskPlanningRegistrar.js +25 -6
  74. package/dist/mcp/toolProfiles.d.ts +2 -0
  75. package/dist/mcp/toolProfiles.js +11 -0
  76. package/dist/mcp/toolRegistry.d.ts +1 -0
  77. package/dist/mcp/toolRegistry.js +9 -8
  78. package/dist/mcp/workflowExecutionRegistrar.js +4 -4
  79. package/dist/migrations/taskSchemaMigrations.d.ts +5 -0
  80. package/dist/migrations/taskSchemaMigrations.js +415 -0
  81. package/dist/runtime/appGates.d.ts +2 -1
  82. package/dist/runtime/appGates.js +7 -0
  83. package/dist/server/buildInfo.d.ts +1 -0
  84. package/dist/server/buildInfo.js +5 -1
  85. package/dist/server/cloudMcpCapacityTelemetry.d.ts +68 -0
  86. package/dist/server/cloudMcpCapacityTelemetry.js +221 -0
  87. package/dist/server/index.d.ts +3 -0
  88. package/dist/server/index.js +108 -11
  89. package/dist/server/localDatabaseIdentity.js +4 -1
  90. package/dist/server/localServiceLease.js +2 -1
  91. package/dist/server/localServiceSessions.d.ts +14 -17
  92. package/dist/server/localServiceSessions.js +308 -94
  93. package/dist/server/localWorkspaceSyncServerRuntime.js +25 -19
  94. package/dist/server/routes/admin.d.ts +4 -0
  95. package/dist/server/routes/admin.js +126 -5
  96. package/dist/server/routes/agents.d.ts +7 -0
  97. package/dist/server/routes/agents.js +277 -24
  98. package/dist/server/routes/billing.js +5 -1
  99. package/dist/server/routes/durableTaskHttpRouters.d.ts +2 -0
  100. package/dist/server/routes/executorPhaseAApprovals.d.ts +19 -0
  101. package/dist/server/routes/executorPhaseAApprovals.js +140 -0
  102. package/dist/server/routes/executorPhaseAIssuerRedemptions.d.ts +11 -0
  103. package/dist/server/routes/executorPhaseAIssuerRedemptions.js +24 -0
  104. package/dist/server/routes/githubReviewEvidence.d.ts +19 -0
  105. package/dist/server/routes/githubReviewEvidence.js +116 -0
  106. package/dist/server/routes/localService.d.ts +15 -4
  107. package/dist/server/routes/localService.js +136 -40
  108. package/dist/server/routes/modelConnections.d.ts +24 -0
  109. package/dist/server/routes/modelConnections.js +205 -0
  110. package/dist/server/routes/shared.d.ts +22 -0
  111. package/dist/server/routes/shared.js +298 -182
  112. package/dist/server/routes/sync.js +1 -0
  113. package/dist/server/routes/syncAuxRoutes.js +5 -1
  114. package/dist/server/routes/syncPushRoutes.d.ts +1 -0
  115. package/dist/server/routes/syncPushRoutes.js +1 -0
  116. package/dist/server/routes/syncV3FeedRoutes.js +10 -1
  117. package/dist/server/routes/syncV3OperationRoutes.js +35 -9
  118. package/dist/server/routes/tasks.js +21 -2
  119. package/dist/server/routes/workflows.js +9 -1
  120. package/dist/server/routes.js +59 -0
  121. package/dist/service/localServiceCli.d.ts +2 -2
  122. package/dist/service/localServiceCli.js +4 -3
  123. package/dist/services/codexAppServerModelGateway.d.ts +54 -5
  124. package/dist/services/codexAppServerModelGateway.js +246 -21
  125. package/dist/services/codexDeviceCodeLoginManager.d.ts +39 -0
  126. package/dist/services/codexDeviceCodeLoginManager.js +265 -0
  127. package/dist/services/codexModelProviderConnectionLifecycle.d.ts +8 -0
  128. package/dist/services/codexModelProviderConnectionLifecycle.js +73 -0
  129. package/dist/services/executorPhaseAApprovalRuntime.d.ts +14 -0
  130. package/dist/services/executorPhaseAApprovalRuntime.js +24 -0
  131. package/dist/services/executorPhaseAApprovalService.d.ts +40 -0
  132. package/dist/services/executorPhaseAApprovalService.js +609 -0
  133. package/dist/services/executorPhaseADriftEvaluator.d.ts +78 -0
  134. package/dist/services/executorPhaseADriftEvaluator.js +93 -0
  135. package/dist/services/executorPhaseAIssuerCore.d.ts +139 -0
  136. package/dist/services/executorPhaseAIssuerCore.js +402 -0
  137. package/dist/services/executorPhaseAIssuerRedemptionService.d.ts +34 -0
  138. package/dist/services/executorPhaseAIssuerRedemptionService.js +158 -0
  139. package/dist/services/githubReviewEvidenceRuntime.d.ts +14 -0
  140. package/dist/services/githubReviewEvidenceRuntime.js +30 -0
  141. package/dist/services/githubReviewEvidenceService.d.ts +93 -0
  142. package/dist/services/githubReviewEvidenceService.js +336 -0
  143. package/dist/services/modelGateway.d.ts +7 -0
  144. package/dist/services/modelProviderConnectionService.d.ts +71 -0
  145. package/dist/services/modelProviderConnectionService.js +279 -0
  146. package/dist/services/modelProviderCredentialHome.d.ts +32 -0
  147. package/dist/services/modelProviderCredentialHome.js +271 -0
  148. package/dist/services/ownerScopedModelConnectionGateway.d.ts +12 -0
  149. package/dist/services/ownerScopedModelConnectionGateway.js +30 -0
  150. package/dist/services/taskforceAgentConnectionBindingService.d.ts +66 -0
  151. package/dist/services/taskforceAgentConnectionBindingService.js +185 -0
  152. package/dist/services/taskforceAgentMcpBridge.d.ts +2 -2
  153. package/dist/services/taskforceAgentMcpBridge.js +42 -29
  154. package/dist/shared/adminEdgeProxy.d.ts +5 -0
  155. package/dist/shared/adminEdgeProxy.js +94 -0
  156. package/dist/shared/adminProxySessionCookies.d.ts +16 -0
  157. package/dist/shared/adminProxySessionCookies.js +86 -0
  158. package/dist/shared/aiProfileColors.d.ts +31 -1
  159. package/dist/shared/aiProfileColors.js +14 -6
  160. package/dist/shared/executorPhaseAApprovalGoldenVector.json +269 -0
  161. package/dist/shared/executorPhaseAApprovalReceipt.d.ts +112 -0
  162. package/dist/shared/executorPhaseAApprovalReceipt.js +58 -0
  163. package/dist/shared/executorPhaseAApprovalTrustPolicy.json +10 -0
  164. package/dist/shared/executorPhaseADriftContracts.d.ts +37 -0
  165. package/dist/shared/executorPhaseADriftContracts.js +63 -0
  166. package/dist/shared/executorPhaseAIssuerContracts.d.ts +75 -0
  167. package/dist/shared/executorPhaseAIssuerContracts.js +90 -0
  168. package/dist/shared/executorPhaseARunAuthorization.d.ts +120 -0
  169. package/dist/shared/executorPhaseARunAuthorization.js +232 -0
  170. package/dist/shared/executorPhaseASchemaValidation.d.ts +7 -0
  171. package/dist/shared/executorPhaseASchemaValidation.js +53 -0
  172. package/dist/shared/executorPhaseASchemas/approval-receipt.schema.json +106 -0
  173. package/dist/shared/executorPhaseASchemas/drift-attestation.schema.json +54 -0
  174. package/dist/shared/executorPhaseASchemas/drift-request.schema.json +47 -0
  175. package/dist/shared/executorPhaseASchemas/foundation-manifest.schema.json +29 -0
  176. package/dist/shared/executorPhaseASchemas/issuer-audit-record.schema.json +24 -0
  177. package/dist/shared/executorPhaseASchemas/issuer-proof.schema.json +43 -0
  178. package/dist/shared/executorPhaseASchemas/issuer-redemption-request.schema.json +18 -0
  179. package/dist/shared/executorPhaseASchemas/issuer-redemption-response.schema.json +39 -0
  180. package/dist/shared/executorPhaseASchemas/logical-envelope.schema.json +149 -0
  181. package/dist/shared/executorPhaseASchemas/preflight-report.schema.json +216 -0
  182. package/dist/shared/executorPhaseASchemas/run-capability.schema.json +111 -0
  183. package/dist/shared/executorPhaseASchemas/sender-proof.schema.json +37 -0
  184. package/dist/shared/executorPhaseASchemas/workload-grant.schema.json +68 -0
  185. package/dist/shared/executorPhaseASchemas/workload-jwt-claims.schema.json +67 -0
  186. package/dist/shared/executorPhaseATiming.d.ts +1 -0
  187. package/dist/shared/executorPhaseATiming.js +1 -0
  188. package/dist/shared/planningIdentity.js +1 -1
  189. package/dist/shared/productLogoKeys.d.ts +2 -0
  190. package/dist/shared/productLogoKeys.js +18 -0
  191. package/dist/shared/taskforceAgentDefinition.d.ts +0 -1
  192. package/dist/shared/taskforceAgentDefinition.js +6 -9
  193. package/dist/shared/taskforceAgentModels.js +7 -3
  194. package/dist/shared/userFeatureGrants.d.ts +4 -0
  195. package/dist/shared/userFeatureGrants.js +7 -0
  196. package/dist/storage/executorPhaseAApprovalReceiptStore.d.ts +37 -0
  197. package/dist/storage/executorPhaseAApprovalReceiptStore.js +81 -0
  198. package/dist/storage/executorPhaseARunAuthorizationStore.d.ts +103 -0
  199. package/dist/storage/executorPhaseARunAuthorizationStore.js +492 -0
  200. package/dist/storage/githubReviewEvidenceInstallationStore.d.ts +26 -0
  201. package/dist/storage/githubReviewEvidenceInstallationStore.js +89 -0
  202. package/dist/storage/modelProviderConnectionStore.d.ts +99 -0
  203. package/dist/storage/modelProviderConnectionStore.js +446 -0
  204. package/dist/storage/postgresAdapter.d.ts +4 -0
  205. package/dist/storage/postgresAdapter.js +14 -1
  206. package/dist/storage/postgresRequestDiagnostics.d.ts +9 -1
  207. package/dist/storage/postgresRequestDiagnostics.js +15 -2
  208. package/dist/storage/postgresWorker.js +20 -2
  209. package/dist/storage/postgresWorkerProtocol.d.ts +7 -0
  210. package/dist/storage/taskforceAgentConnectionBindingStore.d.ts +31 -0
  211. package/dist/storage/taskforceAgentConnectionBindingStore.js +84 -0
  212. package/dist/storage/workflowStore.d.ts +2 -0
  213. package/dist/storage/workflowStore.js +39 -2
  214. package/dist/sync/cloudSyncApi.js +4 -2
  215. package/dist/sync/collaborationSyncState.js +5 -0
  216. package/dist/sync/coordinator/localSyncExecutionPermitStore.js +60 -29
  217. package/dist/sync/coordinator/localWorkspaceSyncPendingV2PushProgress.d.ts +10 -0
  218. package/dist/sync/coordinator/localWorkspaceSyncPendingV2PushProgress.js +29 -0
  219. package/dist/sync/coordinator/localWorkspaceSyncRunner.d.ts +3 -1
  220. package/dist/sync/coordinator/localWorkspaceSyncRunner.js +18 -0
  221. package/dist/sync/coordinator/localWorkspaceSyncRunnerState.d.ts +15 -1
  222. package/dist/sync/coordinator/localWorkspaceSyncRunnerState.js +99 -2
  223. package/dist/sync/coordinator/workspaceSyncCredentialBroker.d.ts +1 -0
  224. package/dist/sync/coordinator/workspaceSyncCredentialBroker.js +33 -4
  225. package/dist/sync/engine/workspaceSyncContentLifecycleAdapter.d.ts +2 -1
  226. package/dist/sync/engine/workspaceSyncContentVersionStore.d.ts +38 -0
  227. package/dist/sync/engine/workspaceSyncContentVersionStore.js +50 -1
  228. package/dist/sync/engine/workspaceSyncEngineLifecyclePolicy.js +6 -6
  229. package/dist/sync/engine/workspaceSyncEnginePushCompletion.d.ts +14 -0
  230. package/dist/sync/engine/workspaceSyncEnginePushCompletion.js +84 -0
  231. package/dist/sync/engine/workspaceSyncEngineRecovery.js +1 -0
  232. package/dist/sync/engine/workspaceSyncEngineRuntime.d.ts +1 -0
  233. package/dist/sync/engine/workspaceSyncEngineRuntime.js +1 -0
  234. package/dist/sync/engine/workspaceSyncEngineServerRunnerOperations.js +112 -38
  235. package/dist/sync/engine/workspaceSyncEngineServerSnapshotReader.js +6 -0
  236. package/dist/sync/engine/workspaceSyncEngineTransfers.js +3 -1
  237. package/dist/sync/engine/workspaceSyncV2ChangeDispatcher.d.ts +1 -0
  238. package/dist/sync/engine/workspaceSyncV2ChangeDispatcher.js +31 -0
  239. package/dist/sync/syncApplyHandlers.d.ts +3 -0
  240. package/dist/sync/syncApplyHandlers.js +81 -15
  241. package/dist/sync/syncService.d.ts +15 -0
  242. package/dist/sync/syncService.js +83 -18
  243. package/dist/sync/taskforceAgentSyncAuthorization.d.ts +16 -0
  244. package/dist/sync/taskforceAgentSyncAuthorization.js +20 -0
  245. package/dist/sync/v3/combinedFeedCapability.js +4 -0
  246. package/dist/sync/v3/durableInitiativeMutationRouter.js +18 -10
  247. package/dist/sync/v3/durableOperationReplay.d.ts +14 -0
  248. package/dist/sync/v3/durableOperationReplay.js +18 -0
  249. package/dist/sync/v3/durableTaskAttachmentLinksMutationRouter.js +3 -0
  250. package/dist/sync/v3/durableTaskChecklistMutationRouter.d.ts +2 -1
  251. package/dist/sync/v3/durableTaskChecklistMutationRouter.js +58 -15
  252. package/dist/sync/v3/durableTaskCommentMutationRouter.js +3 -0
  253. package/dist/sync/v3/durableTaskHttpRootMutationRouter.d.ts +1 -1
  254. package/dist/sync/v3/durableTaskHttpRootMutationRouter.js +10 -0
  255. package/dist/sync/v3/durableTaxonomyMutationRouter.js +5 -0
  256. package/dist/sync/v3/durableWorkflowRuntimeMutationRouter.d.ts +18 -7
  257. package/dist/sync/v3/durableWorkflowRuntimeMutationRouter.js +89 -23
  258. package/dist/sync/v3/durableWorkstreamMutationRouter.js +18 -10
  259. package/dist/sync/v3/durableWorkstreamTaskOrderMutationRouter.js +16 -5
  260. package/dist/sync/v3/localOutboxDispatchRuntime.js +2 -2
  261. package/dist/sync/v3/localOutboxRecoveryPreparationService.js +8 -2
  262. package/dist/sync/v3/localTaskChecklistOutboxHandler.js +16 -2
  263. package/dist/sync/v3/localTaskChecklistOutboxService.d.ts +4 -0
  264. package/dist/sync/v3/localTaskChecklistOutboxService.js +14 -1
  265. package/dist/sync/v3/localTaskCreateOutboxService.d.ts +3 -1
  266. package/dist/sync/v3/localTaskCreateOutboxService.js +6 -1
  267. package/dist/sync/v3/localTaskDeleteOutboxService.js +1 -0
  268. package/dist/sync/v3/localTaskLifecycleOutboxService.d.ts +2 -1
  269. package/dist/sync/v3/localTaskLifecycleOutboxService.js +5 -1
  270. package/dist/sync/v3/localTaskMetadataOutboxService.d.ts +2 -1
  271. package/dist/sync/v3/localTaskMetadataOutboxService.js +6 -2
  272. package/dist/sync/v3/localTaskStatusOutboxService.d.ts +10 -1
  273. package/dist/sync/v3/localTaskStatusOutboxService.js +238 -16
  274. package/dist/sync/v3/syncDurabilityStore.d.ts +36 -1
  275. package/dist/sync/v3/syncDurabilityStore.js +202 -8
  276. package/dist/sync/v3/taskChecklistMutationService.d.ts +11 -0
  277. package/dist/sync/v3/taskChecklistMutationService.js +44 -1
  278. package/dist/sync/v3/taskStatusMutationService.d.ts +29 -1
  279. package/dist/sync/v3/taskStatusMutationService.js +119 -3
  280. package/dist/sync/v3/workflowAssignmentSync.d.ts +5 -0
  281. package/dist/sync/v3/workflowAssignmentSync.js +27 -0
  282. package/dist/sync/v3/workflowRuntimeMutationService.d.ts +5 -0
  283. package/dist/sync/v3/workflowRuntimeMutationService.js +124 -71
  284. package/dist/sync/v3/workspaceSyncJournalReader.js +1 -1
  285. package/dist/sync/v3/workspaceSyncOperationRetentionService.d.ts +16 -0
  286. package/dist/sync/v3/workspaceSyncOperationRetentionService.js +83 -0
  287. package/dist/sync/v3/workspaceSyncV3CloudOperationHandler.d.ts +1 -0
  288. package/dist/sync/v3/workspaceSyncV3CloudOperationHandler.js +9 -2
  289. package/dist/sync/v3/workspaceSyncV3CombinedLocalApply.js +25 -3
  290. package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.d.ts +7 -0
  291. package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.js +44 -32
  292. package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.d.ts +9 -5
  293. package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.js +54 -38
  294. package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.d.ts +10 -0
  295. package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.js +70 -31
  296. package/dist/sync/v3/workspaceSyncV3CombinedWireContract.d.ts +2 -1
  297. package/dist/sync/v3/workspaceSyncV3CombinedWireContract.js +16 -0
  298. package/dist/sync/v3/workspaceSyncV3CoverageRegistry.js +6 -0
  299. package/dist/sync/v3/workspaceSyncV3Feed.d.ts +1 -0
  300. package/dist/sync/v3/workspaceSyncV3Feed.js +6 -1
  301. package/dist/sync/v3/workspaceSyncV3NestedTaskProjection.d.ts +2 -0
  302. package/dist/sync/v3/workspaceSyncV3NestedTaskProjection.js +49 -18
  303. package/dist/sync/v3/workspaceSyncV3OperationProtocol.d.ts +3 -0
  304. package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.d.ts +5 -0
  305. package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.js +36 -2
  306. package/dist/sync/v3/workspaceSyncV3RepairSnapshotRetentionService.d.ts +17 -0
  307. package/dist/sync/v3/workspaceSyncV3RepairSnapshotRetentionService.js +64 -0
  308. package/dist/sync/v3/workspaceSyncV3WorkflowRuntimeApply.d.ts +1 -0
  309. package/dist/sync/v3/workspaceSyncV3WorkflowRuntimeApply.js +50 -5
  310. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverCoverage.d.ts +7 -0
  311. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverCoverage.js +33 -0
  312. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverWireContract.d.ts +7 -0
  313. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverWireContract.js +8 -0
  314. package/dist/sync/workspaceRepair.d.ts +5 -2
  315. package/dist/sync/workspaceRepair.js +161 -6
  316. package/dist/sync/workspaceSyncModel.d.ts +21 -0
  317. package/dist/sync/workspaceSyncModel.js +35 -7
  318. package/dist/sync/workspaceSyncState.d.ts +1 -0
  319. package/dist/sync/workspaceSyncV2SnapshotBuilder.d.ts +6 -0
  320. package/dist/sync/workspaceSyncV2SnapshotBuilder.js +5 -0
  321. package/dist/ui/assets/AiIdentityRosterCard-CDMPtnbC.js +1 -0
  322. package/dist/ui/assets/AiProfilesModule-Cww85C4E.js +1 -0
  323. package/dist/ui/assets/{AnnotatedAttachmentWorkspace-B68Wg-RV.js → AnnotatedAttachmentWorkspace-Dt9TKYSH.js} +1 -1
  324. package/dist/ui/assets/{AssetTraySortControl-C8Rztyal.js → AssetTraySortControl-CKgapnxu.js} +1 -1
  325. package/dist/ui/assets/{ContextAttachmentManager-Cj3c7X9y.js → ContextAttachmentManager-T-cEVcOZ.js} +2 -2
  326. package/dist/ui/assets/{DocumentWorkspace-B5uvzems.js → DocumentWorkspace-HD4MUjAZ.js} +1 -1
  327. package/dist/ui/assets/{EntityActivityTimeline-BVFvCB5R.js → EntityActivityTimeline-_V0zfMuh.js} +1 -1
  328. package/dist/ui/assets/PlanningModule-mTkBygsB.js +1 -0
  329. package/dist/ui/assets/{PlansPage-AY4cGWco.js → PlansPage-Btiq06VO.js} +1 -1
  330. package/dist/ui/assets/{TaskContextUpload-DZxTVesW.js → TaskContextUpload-C00NVUpn.js} +1 -1
  331. package/dist/ui/assets/TaskSettings-Cp-L-4xh.js +12 -0
  332. package/dist/ui/assets/TaskforceAgentsModule-Coq9-PUp.js +24 -0
  333. package/dist/ui/assets/TaskforceAgentsModule-b-8R25cJ.css +1 -0
  334. package/dist/ui/assets/{WorkflowManagerModule-DEr5di_r.js → WorkflowManagerModule-CuqRzMmM.js} +1 -1
  335. package/dist/ui/assets/index-BZ-hdZSk.css +1 -0
  336. package/dist/ui/assets/index-DSQINwt9.js +7 -0
  337. package/dist/ui/assets/{vendor-icons-D9Lpw-j4.js → vendor-icons-Bsq-mcEn.js} +1 -1
  338. package/dist/ui/branding/logos/letterhead_dark.png +0 -0
  339. package/dist/ui/branding/logos/letterhead_light.png +0 -0
  340. package/dist/ui/branding/logos/signature_dark.png +0 -0
  341. package/dist/ui/branding/logos/signature_light.png +0 -0
  342. package/dist/ui/index.html +3 -3
  343. package/dist/utils/aiProfileDefaultLogo.js +16 -48
  344. package/dist/utils/httpSetCookie.d.ts +1 -0
  345. package/dist/utils/httpSetCookie.js +4 -1
  346. package/dist/utils/localRuntimeUrl.d.ts +1 -0
  347. package/dist/utils/localRuntimeUrl.js +14 -0
  348. package/dist/utils/productLogoRegistry.d.ts +2 -0
  349. package/dist/utils/productLogoRegistry.js +36 -0
  350. package/dist/utils/syncStatusPresentation.d.ts +4 -0
  351. package/dist/utils/syncStatusPresentation.js +17 -0
  352. package/dist/utils/taskEvents.d.ts +2 -0
  353. package/dist/utils/workspaceSyncPresentation.d.ts +1 -1
  354. package/dist/utils/workspaceSyncPresentation.js +23 -17
  355. package/package.json +24 -4
  356. package/dist/ui/assets/AiIdentityRosterCard-BZM4aQnM.js +0 -1
  357. package/dist/ui/assets/AiProfilesModule-BbAEWtHH.js +0 -1
  358. package/dist/ui/assets/PlanningModule-B5DWQOGz.js +0 -1
  359. package/dist/ui/assets/TaskSettings-BeWAuyZj.js +0 -12
  360. package/dist/ui/assets/TaskforceAgentsModule-BifCYtjR.js +0 -21
  361. package/dist/ui/assets/TaskforceAgentsModule-D6IC0S7Q.css +0 -1
  362. package/dist/ui/assets/index-I5zhdtgt.js +0 -7
  363. package/dist/ui/assets/index-VRFsx3wz.css +0 -1
@@ -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;
@@ -1,4 +1,4 @@
1
- import { createHash } from 'crypto';
1
+ import { createHash, randomUUID } from 'crypto';
2
2
  import { compareWorkspaceMutationOrdering } from '../workspaceSyncSurface.js';
3
3
  import { canonicalWorkspaceSyncJson } from '../v3/canonicalWorkspaceSyncJson.js';
4
4
  export class WorkspaceSyncContentVersionConflictError extends Error {
@@ -577,9 +577,58 @@ export class WorkspaceSyncContentVersionStore {
577
577
  contentSha256: null,
578
578
  sizeBytes: null,
579
579
  });
580
+ // Only a tombstone that's actually newly accepted (didn't early-return
581
+ // above as superseded/no-op) gets a provenance record — provenance
582
+ // tracks admission events, not every replayed/no-op call.
583
+ this.recordTombstoneProvenance(input);
580
584
  return this.requireHead(input);
581
585
  })();
582
586
  }
587
+ recordTombstoneProvenance(input) {
588
+ const provenance = input.provenance;
589
+ this.db.prepare(`
590
+ INSERT INTO workspace_sync_content_tombstone_provenance (
591
+ id, tenant_id, workspace_id, kind, logical_path, source,
592
+ operation_id, actor_id, source_runtime, source_updated_at,
593
+ repair_involved, recorded_at
594
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
595
+ `).run(randomUUID(), input.tenantId, input.workspaceId, input.kind, input.logicalPath, provenance?.source || 'unknown', provenance?.operationId || null, provenance?.actorId || null, provenance?.sourceRuntime || null, input.sourceUpdatedAt, provenance?.repairInvolved === true ? 1 : 0, input.publishedAt);
596
+ }
597
+ /** Queryable read side for tombstone provenance — most recent admission first. */
598
+ listTombstoneProvenance(input) {
599
+ const limit = Math.max(1, Math.min(500, Math.floor(Number(input.limit) || 100)));
600
+ const conditions = ['tenant_id = ?', 'workspace_id = ?'];
601
+ const params = [input.tenantId, input.workspaceId];
602
+ if (input.kind) {
603
+ conditions.push('kind = ?');
604
+ params.push(input.kind);
605
+ }
606
+ if (input.logicalPath) {
607
+ conditions.push('logical_path = ?');
608
+ params.push(input.logicalPath);
609
+ }
610
+ const rows = this.db.prepare(`
611
+ SELECT *
612
+ FROM workspace_sync_content_tombstone_provenance
613
+ WHERE ${conditions.join(' AND ')}
614
+ ORDER BY recorded_at DESC
615
+ LIMIT ?
616
+ `).all(...params, limit);
617
+ return rows.map((row) => ({
618
+ id: String(row.id || ''),
619
+ tenantId: String(row.tenant_id || ''),
620
+ workspaceId: String(row.workspace_id || ''),
621
+ kind: row.kind === 'document' ? 'document' : 'asset',
622
+ logicalPath: String(row.logical_path || ''),
623
+ source: String(row.source || 'unknown'),
624
+ operationId: row.operation_id == null ? null : String(row.operation_id),
625
+ actorId: row.actor_id == null ? null : String(row.actor_id),
626
+ sourceRuntime: row.source_runtime == null ? null : String(row.source_runtime),
627
+ sourceUpdatedAt: String(row.source_updated_at || ''),
628
+ repairInvolved: Number(row.repair_involved) === 1,
629
+ recordedAt: String(row.recorded_at || ''),
630
+ }));
631
+ }
583
632
  resolveHead(input) {
584
633
  const head = this.getHead(input);
585
634
  return head ? { source: 'versioned', head } : { source: 'legacy' };
@@ -25,7 +25,7 @@ export function resolveWorkspaceSyncPresentation({ enabled, phase, busy, retryAt
25
25
  summary: busy
26
26
  ? 'Uploading this workspace to cloud for the first time.'
27
27
  : 'Preparing the first upload to cloud.',
28
- recommendedAction: 'Keep this window open while the first upload finishes. If it seems stalled, press Sync.'
28
+ recommendedAction: 'Keep this window open while the first upload finishes.'
29
29
  };
30
30
  }
31
31
  if (phase === 'attach-cloud') {
@@ -71,14 +71,14 @@ export function resolveWorkspaceSyncPresentation({ enabled, phase, busy, retryAt
71
71
  return {
72
72
  status: 'attention',
73
73
  summary: 'Sync hit a temporary problem and will retry automatically.',
74
- recommendedAction: 'Wait for the automatic retry, or press Sync to retry now.'
74
+ recommendedAction: 'Wait for the automatic retry.'
75
75
  };
76
76
  }
77
77
  if (lastErrorMessage || phase === 'error') {
78
78
  return {
79
79
  status: 'attention',
80
80
  summary: 'Sync needs attention before it can continue.',
81
- recommendedAction: 'Press Sync to retry. If the same error keeps returning, press Repair.'
81
+ recommendedAction: 'Keep sync enabled. If the same error keeps returning, press Repair.'
82
82
  };
83
83
  }
84
84
  if (pendingChanges > 0 || (durableOutbox?.pending || 0) > 0 || (durableOutbox?.inFlight || 0) > 0) {
@@ -104,14 +104,14 @@ export function resolveWorkspaceSyncPresentation({ enabled, phase, busy, retryAt
104
104
  summary: lastPushMs === null
105
105
  ? 'This device has not completed its first cloud pull.'
106
106
  : 'Cloud uploads are working, but this device has not completed a cloud pull.',
107
- recommendedAction: 'Press Retry now. If the cloud check still does not complete, press Repair and copy the report.'
107
+ recommendedAction: 'Keep sync enabled. If the cloud check still does not complete, press Repair and copy the report.'
108
108
  };
109
109
  }
110
110
  if (lastErrorMs !== null && lastErrorMs > lastPullMs) {
111
111
  return {
112
112
  status: 'attention',
113
113
  summary: 'A sync issue occurred after the last successful cloud pull.',
114
- recommendedAction: 'Press Retry now to verify cloud changes can still be received. If the issue returns, copy the report.'
114
+ recommendedAction: 'Wait for the automatic retry. If the issue returns, copy the report.'
115
115
  };
116
116
  }
117
117
  const pullIsStale = Number.isFinite(nowMs)
@@ -122,7 +122,7 @@ export function resolveWorkspaceSyncPresentation({ enabled, phase, busy, retryAt
122
122
  summary: lastPushMs !== null && lastPushMs > lastPullMs
123
123
  ? 'Cloud uploads are succeeding, but this device has not received cloud changes recently.'
124
124
  : 'This device has not checked for cloud changes recently.',
125
- recommendedAction: 'Press Retry now to check cloud changes. If Last cloud check does not advance, press Repair and copy the report.'
125
+ recommendedAction: 'Keep sync enabled. If Last cloud check does not advance, press Repair and copy the report.'
126
126
  };
127
127
  }
128
128
  return {
@@ -1,4 +1,5 @@
1
1
  import type { WorkspaceSyncChange, WorkspaceSyncDurableTaskRevision, WorkspaceSyncTaskSnapshot } from '../workspaceSyncModel.js';
2
+ import type { WorkspaceSyncV2ProjectionExclusion } from '../v3/workspaceSyncV2ProjectionExclusions.js';
2
3
  export declare const WORKSPACE_SYNC_ENGINE_V2_PUSH_BOUNDARY_VERSION: 1;
3
4
  /**
4
5
  * Stable attempt-wide boundary shared by every V2 push batch. Individual
@@ -18,3 +19,16 @@ export interface WorkspaceSyncEngineAppliedTaskUpsert {
18
19
  }
19
20
  export declare function workspaceSyncEngineExpectedTaskEchoIds(changes: readonly WorkspaceSyncChange[]): string[];
20
21
  export declare function parseWorkspaceSyncEngineAppliedTaskUpserts(value: unknown, expectedTaskIds: readonly string[]): WorkspaceSyncEngineAppliedTaskUpsert[];
22
+ export declare function createWorkspaceSyncEngineV2SettlementIdentityProjection(input: {
23
+ operationIdentity: string;
24
+ changes: readonly WorkspaceSyncChange[];
25
+ appliedTaskUpserts: readonly WorkspaceSyncEngineAppliedTaskUpsert[];
26
+ excludedProjections?: readonly WorkspaceSyncV2ProjectionExclusion[];
27
+ }): {
28
+ version: 1;
29
+ operationIdentity: string;
30
+ taskUpserts: Array<{
31
+ archived: boolean;
32
+ task: Record<string, unknown>;
33
+ }>;
34
+ };
@@ -1,3 +1,4 @@
1
+ import { canonicalWorkspaceSyncJson } from '../v3/canonicalWorkspaceSyncJson.js';
1
2
  export const WORKSPACE_SYNC_ENGINE_V2_PUSH_BOUNDARY_VERSION = 1;
2
3
  export function createWorkspaceSyncEngineV2PushBoundary(batchOperationIdentities) {
3
4
  if (!Array.isArray(batchOperationIdentities)
@@ -85,3 +86,86 @@ export function parseWorkspaceSyncEngineAppliedTaskUpserts(value, expectedTaskId
85
86
  }
86
87
  return normalized;
87
88
  }
89
+ function taskSettlementProjection(task, preserveReferenceNumber) {
90
+ const { updatedAt: _updatedAt, ...stableTask } = structuredClone(task);
91
+ if (!preserveReferenceNumber)
92
+ delete stableTask.referenceNumber;
93
+ return stableTask;
94
+ }
95
+ function taskSettlementOwnedProjection(input) {
96
+ // The cloud echo is authoritative for the complete task row, but this V2
97
+ // page may own only carrier fields. Validate exactly that remaining V2
98
+ // surface; V3-owned fields are checked by their own acknowledgement/feed.
99
+ const task = taskSettlementProjection(input.task, input.preserveReferenceNumber);
100
+ const rootOwnedByV3 = input.excludedProjections.has('task/root-v1');
101
+ const commentsOwnedByV3 = input.excludedProjections.has('task-comments/full-v1');
102
+ const checklistOwnedByV3 = input.excludedProjections.has('task-checklist/full-v1');
103
+ const attachmentLinksV1OwnedByV3 = input.excludedProjections
104
+ .has('task-attachment-links/full-v1');
105
+ const attachmentLinksV2OwnedByV3 = input.excludedProjections
106
+ .has('task-attachment-links/full-v2');
107
+ if (rootOwnedByV3) {
108
+ for (const key of Object.keys(task)) {
109
+ if (![
110
+ 'id',
111
+ 'comments',
112
+ 'checklistItems',
113
+ 'attachments',
114
+ 'cardCoverAssetId',
115
+ ].includes(key)) {
116
+ delete task[key];
117
+ }
118
+ }
119
+ }
120
+ if (commentsOwnedByV3)
121
+ delete task.comments;
122
+ if (checklistOwnedByV3)
123
+ delete task.checklistItems;
124
+ if (attachmentLinksV1OwnedByV3 || attachmentLinksV2OwnedByV3) {
125
+ delete task.attachments;
126
+ }
127
+ if (attachmentLinksV2OwnedByV3)
128
+ delete task.cardCoverAssetId;
129
+ return {
130
+ ...(rootOwnedByV3 ? {} : { archived: input.archived }),
131
+ task,
132
+ };
133
+ }
134
+ export function createWorkspaceSyncEngineV2SettlementIdentityProjection(input) {
135
+ const operationIdentity = String(input.operationIdentity || '').trim();
136
+ if (!operationIdentity || operationIdentity !== input.operationIdentity) {
137
+ throw new TypeError('The V2 push settlement operation identity is invalid.');
138
+ }
139
+ const expectedTaskUpserts = input.changes.filter((change) => change.op === 'upsert');
140
+ if (expectedTaskUpserts.length !== input.appliedTaskUpserts.length) {
141
+ throw new TypeError('The V2 push authoritative settlement projection is incomplete.');
142
+ }
143
+ const expectedProjection = expectedTaskUpserts.map((change) => ({
144
+ archived: change.archived,
145
+ task: taskSettlementProjection(change.task, change.task.referenceNumber !== undefined && change.task.referenceNumber !== null),
146
+ }));
147
+ const excludedProjections = new Set(input.excludedProjections || []);
148
+ const expectedOwnedProjection = expectedTaskUpserts.map((change) => (taskSettlementOwnedProjection({
149
+ archived: change.archived,
150
+ task: change.task,
151
+ preserveReferenceNumber: change.task.referenceNumber !== undefined
152
+ && change.task.referenceNumber !== null,
153
+ excludedProjections,
154
+ })));
155
+ const authoritativeOwnedProjection = input.appliedTaskUpserts.map((entry, index) => (taskSettlementOwnedProjection({
156
+ archived: entry.archived,
157
+ task: entry.task,
158
+ preserveReferenceNumber: expectedTaskUpserts[index]?.task.referenceNumber !== undefined
159
+ && expectedTaskUpserts[index]?.task.referenceNumber !== null,
160
+ excludedProjections,
161
+ })));
162
+ if (canonicalWorkspaceSyncJson(authoritativeOwnedProjection)
163
+ !== canonicalWorkspaceSyncJson(expectedOwnedProjection)) {
164
+ throw new TypeError('The V2 push authoritative settlement does not match the canonical request state.');
165
+ }
166
+ return {
167
+ version: 1,
168
+ operationIdentity,
169
+ taskUpserts: expectedProjection,
170
+ };
171
+ }
@@ -10,6 +10,7 @@ function resetWorkspaceSyncStatePushBaselines(runtime) {
10
10
  runtime.lastPushedInitiativeWatermarks.current = new Map();
11
11
  runtime.lastPushedWorkstreamIds.current = new Set();
12
12
  runtime.lastPushedWorkstreamWatermarks.current = new Map();
13
+ runtime.lastPushedPlanningIdentityWatermarks.current = new Map();
13
14
  runtime.lastPushedAiProfileIds.current = new Set();
14
15
  runtime.lastPushedAiProfileWatermarks.current = new Map();
15
16
  runtime.lastPushedAiProfileChangeKeys.current = new Map();
@@ -26,6 +26,7 @@ export interface WorkspaceSyncEngineRuntime {
26
26
  lastPushedInitiativeWatermarks: WorkspaceSyncMutableValue<Map<string, string>>;
27
27
  lastPushedWorkstreamIds: WorkspaceSyncMutableValue<Set<string>>;
28
28
  lastPushedWorkstreamWatermarks: WorkspaceSyncMutableValue<Map<string, string>>;
29
+ lastPushedPlanningIdentityWatermarks: WorkspaceSyncMutableValue<Map<string, string>>;
29
30
  lastPushedAiProfileIds: WorkspaceSyncMutableValue<Set<string>>;
30
31
  lastPushedAiProfileWatermarks: WorkspaceSyncMutableValue<Map<string, string>>;
31
32
  lastPushedAiProfileChangeKeys: WorkspaceSyncMutableValue<Map<string, string>>;
@@ -24,6 +24,7 @@ export function createWorkspaceSyncEngineRuntime() {
24
24
  lastPushedInitiativeWatermarks: mutable(new Map()),
25
25
  lastPushedWorkstreamIds: mutable(new Set()),
26
26
  lastPushedWorkstreamWatermarks: mutable(new Map()),
27
+ lastPushedPlanningIdentityWatermarks: mutable(new Map()),
27
28
  lastPushedAiProfileIds: mutable(new Set()),
28
29
  lastPushedAiProfileWatermarks: mutable(new Map()),
29
30
  lastPushedAiProfileChangeKeys: mutable(new Map()),