@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
@@ -116,7 +116,13 @@ export function buildWorkspaceSyncV3OperatorDiagnostics(input) {
116
116
  `).all(tenantId, workspaceId, since, eventLimit + 1);
117
117
  const truncated = eventRows.length > eventLimit;
118
118
  const events = eventRows.slice(0, eventLimit);
119
- const transfer = { pull: { success: 0, error: 0 }, apply: { success: 0, error: 0 }, server5xx: 0, nonTest409: 0 };
119
+ const transfer = {
120
+ pull: { success: 0, error: 0 },
121
+ apply: { success: 0, error: 0 },
122
+ server5xx: 0,
123
+ nonTest409: 0,
124
+ cursorExpiredResets: 0,
125
+ };
120
126
  const requestTimes = [];
121
127
  const observedResponseBytes = [];
122
128
  for (const row of events) {
@@ -131,7 +137,10 @@ export function buildWorkspaceSyncV3OperatorDiagnostics(input) {
131
137
  const requestMs = Number(row.request_ms);
132
138
  if (Number.isFinite(requestMs) && requestMs >= 0)
133
139
  requestTimes.push(requestMs);
134
- const bytes = responseBytes(parseDetails(row.details_json));
140
+ const details = parseDetails(row.details_json);
141
+ if (JSON.stringify(details).includes('CURSOR_EXPIRED'))
142
+ transfer.cursorExpiredResets += 1;
143
+ const bytes = responseBytes(details);
135
144
  if (bytes !== null)
136
145
  observedResponseBytes.push(bytes);
137
146
  }
@@ -143,6 +152,27 @@ export function buildWorkspaceSyncV3OperatorDiagnostics(input) {
143
152
  AND coverage_profile_id = ? AND coverage_version = ? AND coverage_digest = ?
144
153
  AND created_at >= ?
145
154
  `).get(nowIso, tenantId, workspaceId, projection.coverageProfileId, projection.coverageVersion, projection.coverageDigest, since);
155
+ const storedRepairMaterialization = input.db.prepare(`
156
+ SELECT
157
+ COUNT(*) AS count,
158
+ COALESCE(SUM(CASE WHEN expires_at < ? THEN 1 ELSE 0 END), 0) AS expired,
159
+ (SELECT COUNT(*)
160
+ FROM workspace_sync_repair_snapshot_entries entry
161
+ WHERE entry.tenant_id = ? AND entry.workspace_id = ?) AS entries,
162
+ (SELECT COUNT(*)
163
+ FROM workspace_sync_repair_snapshot_entries entry
164
+ WHERE entry.tenant_id = ? AND entry.workspace_id = ?
165
+ AND EXISTS (
166
+ SELECT 1
167
+ FROM workspace_sync_repair_snapshots snapshot
168
+ WHERE snapshot.tenant_id = entry.tenant_id
169
+ AND snapshot.workspace_id = entry.workspace_id
170
+ AND snapshot.snapshot_id = entry.snapshot_id
171
+ AND snapshot.expires_at < ?
172
+ )) AS expired_entries
173
+ FROM workspace_sync_repair_snapshots
174
+ WHERE tenant_id = ? AND workspace_id = ?
175
+ `).get(nowIso, tenantId, workspaceId, tenantId, workspaceId, nowIso, tenantId, workspaceId);
146
176
  const stagedEntry = projection.repair ? input.db.prepare(`
147
177
  SELECT COUNT(*) AS count
148
178
  FROM workspace_sync_coverage_repair_entries
@@ -346,6 +376,10 @@ export function buildWorkspaceSyncV3OperatorDiagnostics(input) {
346
376
  materializationsInWindow: integer(repairMaterialization?.count),
347
377
  materializedEntriesInWindow: integer(repairMaterialization?.entries),
348
378
  unexpiredMaterializations: integer(repairMaterialization?.unexpired),
379
+ storedMaterializations: integer(storedRepairMaterialization?.count),
380
+ storedEntries: integer(storedRepairMaterialization?.entries),
381
+ expiredMaterializations: integer(storedRepairMaterialization?.expired),
382
+ expiredEntries: integer(storedRepairMaterialization?.expired_entries),
349
383
  },
350
384
  outbox: {
351
385
  captureConfigured, dispatchConfigured, automaticSyncEnabled: automaticSync.enabled,
@@ -0,0 +1,17 @@
1
+ import type { DatabaseAdapter } from '../../storage/databaseAdapter.js';
2
+ export declare const DEFAULT_WORKSPACE_SYNC_REPAIR_SNAPSHOT_RETENTION_BATCH_SIZE = 500;
3
+ export interface WorkspaceSyncRepairSnapshotRetentionPolicy {
4
+ batchSize: number;
5
+ }
6
+ export interface WorkspaceSyncRepairSnapshotRetentionResult {
7
+ deletedEntries: number;
8
+ deletedSnapshots: number;
9
+ remainingExpiredSnapshots: number;
10
+ }
11
+ export declare function resolveWorkspaceSyncRepairSnapshotRetentionPolicy(env?: NodeJS.ProcessEnv): WorkspaceSyncRepairSnapshotRetentionPolicy;
12
+ export declare function pruneExpiredWorkspaceSyncRepairSnapshots(input: {
13
+ db: DatabaseAdapter;
14
+ tenantId: string;
15
+ now?: Date;
16
+ policy?: WorkspaceSyncRepairSnapshotRetentionPolicy;
17
+ }): WorkspaceSyncRepairSnapshotRetentionResult;
@@ -0,0 +1,64 @@
1
+ export const DEFAULT_WORKSPACE_SYNC_REPAIR_SNAPSHOT_RETENTION_BATCH_SIZE = 500;
2
+ function positiveInteger(value, fallback) {
3
+ const parsed = Number.parseInt(String(value ?? '').trim(), 10);
4
+ return Number.isSafeInteger(parsed) && parsed > 0 ? parsed : fallback;
5
+ }
6
+ export function resolveWorkspaceSyncRepairSnapshotRetentionPolicy(env = process.env) {
7
+ return {
8
+ batchSize: Math.min(10_000, positiveInteger(env.TASKFORCE_SYNC_REPAIR_SNAPSHOT_RETENTION_BATCH_SIZE, DEFAULT_WORKSPACE_SYNC_REPAIR_SNAPSHOT_RETENTION_BATCH_SIZE)),
9
+ };
10
+ }
11
+ export function pruneExpiredWorkspaceSyncRepairSnapshots(input) {
12
+ const now = (input.now || new Date()).toISOString();
13
+ const policy = input.policy || resolveWorkspaceSyncRepairSnapshotRetentionPolicy();
14
+ return input.db.transaction(() => {
15
+ const snapshot = input.db.prepare(`
16
+ SELECT workspace_id, snapshot_id
17
+ FROM workspace_sync_repair_snapshots
18
+ WHERE tenant_id = ? AND expires_at < ?
19
+ ORDER BY expires_at ASC, workspace_id ASC, snapshot_id ASC
20
+ LIMIT 1
21
+ `).get(input.tenantId, now);
22
+ const workspaceId = String(snapshot?.workspace_id || '').trim();
23
+ const snapshotId = String(snapshot?.snapshot_id || '').trim();
24
+ let deletedEntries = 0;
25
+ let deletedSnapshots = 0;
26
+ if (workspaceId && snapshotId) {
27
+ const entries = input.db.prepare(`
28
+ SELECT entry_index
29
+ FROM workspace_sync_repair_snapshot_entries
30
+ WHERE tenant_id = ? AND workspace_id = ? AND snapshot_id = ?
31
+ ORDER BY entry_index ASC
32
+ LIMIT ?
33
+ `).all(input.tenantId, workspaceId, snapshotId, policy.batchSize);
34
+ if (entries.length > 0) {
35
+ const result = input.db.prepare(`
36
+ DELETE FROM workspace_sync_repair_snapshot_entries
37
+ WHERE tenant_id = ? AND workspace_id = ? AND snapshot_id = ?
38
+ AND entry_index IN (${entries.map(() => '?').join(', ')})
39
+ `).run(input.tenantId, workspaceId, snapshotId, ...entries.map((entry) => entry.entry_index));
40
+ deletedEntries = Number(result.changes || 0);
41
+ }
42
+ const snapshotResult = input.db.prepare(`
43
+ DELETE FROM workspace_sync_repair_snapshots
44
+ WHERE tenant_id = ? AND workspace_id = ? AND snapshot_id = ? AND expires_at < ?
45
+ AND NOT EXISTS (
46
+ SELECT 1
47
+ FROM workspace_sync_repair_snapshot_entries
48
+ WHERE tenant_id = ? AND workspace_id = ? AND snapshot_id = ?
49
+ )
50
+ `).run(input.tenantId, workspaceId, snapshotId, now, input.tenantId, workspaceId, snapshotId);
51
+ deletedSnapshots = Number(snapshotResult.changes || 0);
52
+ }
53
+ const remaining = input.db.prepare(`
54
+ SELECT COUNT(*) AS count
55
+ FROM workspace_sync_repair_snapshots
56
+ WHERE tenant_id = ? AND expires_at < ?
57
+ `).get(input.tenantId, now);
58
+ return {
59
+ deletedEntries,
60
+ deletedSnapshots,
61
+ remainingExpiredSnapshots: Number(remaining?.count || 0),
62
+ };
63
+ })();
64
+ }
@@ -0,0 +1,7 @@
1
+ import type { WorkspaceSyncV3FeedCoveragePolicy, WorkspaceSyncV3FeedEntry, WorkspaceSyncV3FeedOperationProjector } from './workspaceSyncV3Feed.js';
2
+ import type { WorkspaceSyncV3CoverageProfile } from './workspaceSyncV3FeedProfile.js';
3
+ /** Dark v8 candidate: active v7 task-cover ownership plus workflow runtime. */
4
+ export declare const WORKSPACE_SYNC_V3_WORKFLOW_TASK_COVER_COVERAGE_PROFILE: WorkspaceSyncV3CoverageProfile;
5
+ export declare const projectWorkspaceSyncV3WorkflowTaskCoverCoverageOperation: WorkspaceSyncV3FeedOperationProjector;
6
+ export declare const WORKSPACE_SYNC_V3_WORKFLOW_TASK_COVER_COVERAGE_POLICY: WorkspaceSyncV3FeedCoveragePolicy;
7
+ export declare function validateWorkspaceSyncV3WorkflowTaskCoverCoverageFeedEntry(entry: WorkspaceSyncV3FeedEntry): void;
@@ -0,0 +1,33 @@
1
+ import { createHash } from 'crypto';
2
+ import { canonicalWorkspaceSyncJson } from './canonicalWorkspaceSyncJson.js';
3
+ import { projectWorkspaceSyncV3TaskCoverCoverageOperation, validateWorkspaceSyncV3TaskCoverCoverageFeedEntry, WORKSPACE_SYNC_V3_TASK_COVER_COVERAGE_PROFILE, } from './workspaceSyncV3TaskCoverCoverage.js';
4
+ import { WORKSPACE_SYNC_V3_WORKFLOW_RUNTIME_PROJECTIONS } from './workflowRuntimeSync.js';
5
+ import { projectWorkspaceSyncV3WorkflowRuntimeOperation, validateWorkspaceSyncV3WorkflowRuntimeFeedEntry, } from './workspaceSyncV3WorkflowRuntimeProjection.js';
6
+ const projections = Object.freeze([
7
+ ...WORKSPACE_SYNC_V3_TASK_COVER_COVERAGE_PROFILE.projections,
8
+ ...WORKSPACE_SYNC_V3_WORKFLOW_RUNTIME_PROJECTIONS,
9
+ ]);
10
+ const identity = Object.freeze({
11
+ coverageProfileId: 'task-planning-metadata',
12
+ coverageVersion: 8,
13
+ projections,
14
+ });
15
+ /** Dark v8 candidate: active v7 task-cover ownership plus workflow runtime. */
16
+ export const WORKSPACE_SYNC_V3_WORKFLOW_TASK_COVER_COVERAGE_PROFILE = Object.freeze({
17
+ ...identity,
18
+ coverageDigest: createHash('sha256').update(canonicalWorkspaceSyncJson(identity)).digest('hex'),
19
+ });
20
+ export const projectWorkspaceSyncV3WorkflowTaskCoverCoverageOperation = (input) => {
21
+ const workflow = projectWorkspaceSyncV3WorkflowRuntimeOperation(input);
22
+ return workflow || projectWorkspaceSyncV3TaskCoverCoverageOperation(input);
23
+ };
24
+ export const WORKSPACE_SYNC_V3_WORKFLOW_TASK_COVER_COVERAGE_POLICY = Object.freeze({
25
+ profile: WORKSPACE_SYNC_V3_WORKFLOW_TASK_COVER_COVERAGE_PROFILE,
26
+ projectOperation: projectWorkspaceSyncV3WorkflowTaskCoverCoverageOperation,
27
+ });
28
+ export function validateWorkspaceSyncV3WorkflowTaskCoverCoverageFeedEntry(entry) {
29
+ if (entry.projection.startsWith('workflow-')) {
30
+ return validateWorkspaceSyncV3WorkflowRuntimeFeedEntry(entry);
31
+ }
32
+ return validateWorkspaceSyncV3TaskCoverCoverageFeedEntry(entry);
33
+ }
@@ -0,0 +1,7 @@
1
+ export declare const WORKSPACE_SYNC_V3_WORKFLOW_TASK_COVER_COVERAGE_SELECTOR: Readonly<{
2
+ coverageProfileId: "task-planning-metadata";
3
+ coverageVersion: 8;
4
+ coverageDigest: "344c3360d36d383241b212192fe6c2ac1a7694fe521d3b6636559043b7e58253";
5
+ }>;
6
+ /** V2 has neither workflow runtime nor explicit task card-cover projections. */
7
+ export declare const WORKSPACE_SYNC_V3_WORKFLOW_TASK_COVER_EXCLUDED_V2_PROJECTIONS: readonly ("initiative/full-v1" | "taxonomy/full-v1" | "task/root-v1" | "task-relationship/full-v1" | "workstream/full-v1" | "task-comments/full-v1" | "task-checklist/full-v1" | "task-attachment-links/full-v2" | "entity-event/full-v1")[];
@@ -0,0 +1,8 @@
1
+ import { WORKSPACE_SYNC_V3_TASK_COVER_EXCLUDED_V2_PROJECTIONS } from './workspaceSyncV3TaskCoverWireContract.js';
2
+ export const WORKSPACE_SYNC_V3_WORKFLOW_TASK_COVER_COVERAGE_SELECTOR = Object.freeze({
3
+ coverageProfileId: 'task-planning-metadata',
4
+ coverageVersion: 8,
5
+ coverageDigest: '344c3360d36d383241b212192fe6c2ac1a7694fe521d3b6636559043b7e58253',
6
+ });
7
+ /** V2 has neither workflow runtime nor explicit task card-cover projections. */
8
+ export const WORKSPACE_SYNC_V3_WORKFLOW_TASK_COVER_EXCLUDED_V2_PROJECTIONS = WORKSPACE_SYNC_V3_TASK_COVER_EXCLUDED_V2_PROJECTIONS;
@@ -2,6 +2,7 @@ import type { TaskItem } from '../types.js';
2
2
  import type { WorkspaceAssetLinkRole, WorkspaceAssetStore } from '../storage/workspaceAssetStore.js';
3
3
  import { type AiProfileAvatarPathSource } from './aiProfileAvatarSyncPaths.js';
4
4
  import { type WorkspaceSyncPublishedContentResolver } from './engine/workspaceSyncPublishedContentResolver.js';
5
+ import type { WorkspaceSyncContentPullObligationStore } from './engine/workspaceSyncContentPullObligationStore.js';
5
6
  export interface WorkspaceRepairManifestTaskEntry {
6
7
  id: string;
7
8
  archived: boolean;
@@ -52,7 +53,7 @@ export interface WorkspaceRepairManifest {
52
53
  assets: WorkspaceRepairManifestAssetEntry[];
53
54
  assetDeletes: WorkspaceRepairManifestDeleteEntry[];
54
55
  }
55
- export type WorkspaceRepairIssueCode = 'missing_document_metadata' | 'missing_document_file' | 'stale_document_tombstone' | 'published_document_tombstone_conflict' | 'published_document_live_head_conflict' | 'invalid_published_document_content' | 'missing_asset_metadata' | 'missing_asset_file' | 'stale_asset_tombstone' | 'published_asset_tombstone_conflict' | 'published_asset_live_head_conflict' | 'invalid_published_asset_content' | 'stale_asset_link' | 'missing_asset_link';
56
+ export type WorkspaceRepairIssueCode = 'missing_document_metadata' | 'missing_document_file' | 'stale_document_tombstone' | 'published_document_tombstone_conflict' | 'published_document_live_head_conflict' | 'invalid_published_document_content' | 'document_content_unverified' | 'missing_asset_metadata' | 'missing_asset_file' | 'stale_asset_tombstone' | 'published_asset_tombstone_conflict' | 'published_asset_live_head_conflict' | 'invalid_published_asset_content' | 'asset_content_unverified' | 'stale_asset_link' | 'missing_asset_link';
56
57
  export interface WorkspaceRepairIssue {
57
58
  code: WorkspaceRepairIssueCode;
58
59
  entityKind: 'document' | 'asset' | 'link';
@@ -61,7 +62,7 @@ export interface WorkspaceRepairIssue {
61
62
  taskId?: string | null;
62
63
  role?: WorkspaceAssetLinkRole;
63
64
  repairable: boolean;
64
- recommendedAction: 'create-metadata' | 'mark-deleted' | 'revive-metadata' | 'delete-link' | 'create-link' | 'inspect-published-content';
65
+ recommendedAction: 'create-metadata' | 'mark-deleted' | 'revive-metadata' | 'delete-link' | 'create-link' | 'inspect-published-content' | 'retry-pull';
65
66
  detail: string;
66
67
  }
67
68
  export interface WorkspaceRepairScanResult {
@@ -106,4 +107,6 @@ export declare function applyWorkspaceRepair(input: WorkspaceRepairInput & {
106
107
  upsertDocumentWatermark: (workspaceId: string, path: string, contentHash: string, updatedAt: string) => void;
107
108
  repairMissingAssetLinks?: boolean;
108
109
  repairMissingContentFiles?: boolean;
110
+ contentPullObligationStore?: WorkspaceSyncContentPullObligationStore;
111
+ now?: () => string;
109
112
  }): WorkspaceRepairApplyResult;
@@ -6,6 +6,7 @@ import { resolveStorageKeyPathInsideRoot } from '../utils/pathSafety.js';
6
6
  import { compareWorkspaceMutationOrdering } from './workspaceSyncSurface.js';
7
7
  import { relativePathWithinRoot } from '../utils/pathContainment.js';
8
8
  import { listReferencedAiProfileAvatarAssetPaths, } from './aiProfileAvatarSyncPaths.js';
9
+ import { WORKSPACE_CONTENT_MANIFEST_VERSION, createWorkspaceContentMetadataFingerprintV1, } from './workspaceContentManifest.js';
9
10
  function normalizeWorkspaceId(raw) {
10
11
  return String(raw || '').trim() || 'default';
11
12
  }
@@ -110,6 +111,68 @@ function getPrimaryTaskId(store, assetId, workspaceId) {
110
111
  const links = store.listLinksForAsset(assetId, workspaceId, { includeDeleted: false });
111
112
  return links[0]?.taskId || null;
112
113
  }
114
+ function buildContentPullObligationInputForAsset(input) {
115
+ const links = input.store.listLinksForAsset(input.entry.assetId, input.workspaceId, { includeDeleted: false });
116
+ const primaryLink = links[0] || null;
117
+ // Mirrors resolveSyncLinkTarget (src/sync/contentSyncState.ts): a task link has no
118
+ // explicit targetType on the row (it's implied), so it must default to 'task' here
119
+ // rather than null — otherwise this fingerprint diverges from the one a real content
120
+ // manifest read (workspacePullFeed.ts) computes for the same task-linked asset, and
121
+ // the 'exact-version' obligation-resolution path can never match it.
122
+ const primaryLinkTargetId = String(primaryLink?.targetId || primaryLink?.taskId || '').trim();
123
+ const linkTargetType = primaryLinkTargetId
124
+ ? (primaryLink.targetType === 'initiative' || primaryLink.targetType === 'workstream' ? primaryLink.targetType : 'task')
125
+ : null;
126
+ const linkTargetId = linkTargetType ? primaryLinkTargetId : null;
127
+ const taskId = linkTargetType === 'task' ? linkTargetId : null;
128
+ const metadataFingerprint = input.kind === 'document'
129
+ ? createWorkspaceContentMetadataFingerprintV1({
130
+ kind: 'document',
131
+ metadata: {
132
+ assetId: input.entry.assetId,
133
+ documentId: input.entry.documentId,
134
+ referenceNumber: input.entry.referenceNumber,
135
+ version: input.entry.version,
136
+ taskId,
137
+ linkTargetType,
138
+ linkTargetId,
139
+ logicalName: input.entry.logicalName,
140
+ caption: null,
141
+ originalFilename: input.entry.originalFilename,
142
+ linkRole: primaryLink?.role === 'reference' ? 'reference' : 'attachment',
143
+ },
144
+ })
145
+ : createWorkspaceContentMetadataFingerprintV1({
146
+ kind: 'asset',
147
+ metadata: {
148
+ assetId: input.entry.assetId,
149
+ assetKind: input.entry.kind === 'image' ? 'image' : 'file',
150
+ mimeType: input.entry.mimeType,
151
+ referenceNumber: input.entry.referenceNumber,
152
+ taskId,
153
+ linkTargetType,
154
+ linkTargetId,
155
+ logicalName: input.entry.logicalName,
156
+ caption: null,
157
+ originalFilename: input.entry.originalFilename,
158
+ linkRole: primaryLink?.role || 'attachment',
159
+ },
160
+ });
161
+ const manifest = {
162
+ manifestVersion: WORKSPACE_CONTENT_MANIFEST_VERSION,
163
+ kind: input.kind,
164
+ path: input.path,
165
+ sha256: String(input.entry.contentSha256 || ''),
166
+ sizeBytes: Number(input.entry.sizeBytes || 0),
167
+ updatedAt: input.entry.updatedAt,
168
+ metadataFingerprint,
169
+ existsLocally: false,
170
+ };
171
+ return {
172
+ manifest,
173
+ sourceWatermark: input.entry.updatedAt,
174
+ };
175
+ }
113
176
  function decodePathSegment(raw) {
114
177
  try {
115
178
  return decodeURIComponent(raw);
@@ -492,14 +555,14 @@ export function scanWorkspaceRepair(input) {
492
555
  if (!document.existsLocally) {
493
556
  if (!document.contentCheckReliable) {
494
557
  issues.push({
495
- code: 'invalid_published_document_content',
558
+ code: 'document_content_unverified',
496
559
  entityKind: 'document',
497
560
  path: document.path,
498
561
  assetId: document.assetId,
499
562
  taskId: document.taskId,
500
563
  repairable: false,
501
- recommendedAction: 'inspect-published-content',
502
- detail: 'Local document file could not be confirmed missing — the storage root was unreachable or the check was inconclusive. Skipped to avoid converting unavailable content into an authoritative deletion.'
564
+ recommendedAction: 'retry-pull',
565
+ detail: 'Local document file could not be confirmed missing — the storage root was unreachable or the check was inconclusive. Skipped to avoid converting unavailable content into an authoritative deletion; queued for durable retry instead.'
503
566
  });
504
567
  continue;
505
568
  }
@@ -603,14 +666,14 @@ export function scanWorkspaceRepair(input) {
603
666
  continue;
604
667
  if (!asset.contentCheckReliable) {
605
668
  issues.push({
606
- code: 'invalid_published_asset_content',
669
+ code: 'asset_content_unverified',
607
670
  entityKind: 'asset',
608
671
  path: asset.path,
609
672
  assetId: asset.assetId,
610
673
  taskId: asset.taskId,
611
674
  repairable: false,
612
- recommendedAction: 'inspect-published-content',
613
- detail: 'Local asset file could not be confirmed missing — the storage root was unreachable or the check was inconclusive. Skipped to avoid converting unavailable content into an authoritative deletion.'
675
+ recommendedAction: 'retry-pull',
676
+ detail: 'Local asset file could not be confirmed missing — the storage root was unreachable or the check was inconclusive. Skipped to avoid converting unavailable content into an authoritative deletion; queued for durable retry instead.'
614
677
  });
615
678
  continue;
616
679
  }
@@ -771,6 +834,7 @@ export function applyWorkspaceRepair(input) {
771
834
  const actionsApplied = [];
772
835
  const workspaceId = normalizeWorkspaceId(input.workspaceId);
773
836
  const activeTaskIds = new Set((input.tasks || []).map((task) => String(task.id || '').trim()).filter(Boolean));
837
+ const nowIso = () => (input.now ? input.now() : new Date().toISOString());
774
838
  const deletedMetadataByPath = new Map();
775
839
  if (input.workspaceAssetStore) {
776
840
  for (const entry of input.workspaceAssetStore.listAllByWorkspace(workspaceId, { includeDeleted: true })) {
@@ -780,6 +844,69 @@ export function applyWorkspaceRepair(input) {
780
844
  }
781
845
  }
782
846
  for (const issue of scan.issues) {
847
+ if (issue.code === 'document_content_unverified' || issue.code === 'asset_content_unverified') {
848
+ if (!input.contentPullObligationStore || !input.workspaceAssetStore || !issue.assetId || !issue.path) {
849
+ actionsApplied.push({
850
+ code: issue.code,
851
+ path: issue.path,
852
+ assetId: issue.assetId,
853
+ taskId: issue.taskId,
854
+ action: issue.recommendedAction,
855
+ status: 'skipped',
856
+ detail: 'No durable content-pull obligation store is available in this runtime; content-availability uncertainty was reported but not queued for retry.'
857
+ });
858
+ continue;
859
+ }
860
+ try {
861
+ const assetEntry = input.workspaceAssetStore.get(issue.assetId, workspaceId);
862
+ if (!assetEntry) {
863
+ actionsApplied.push({
864
+ code: issue.code,
865
+ path: issue.path,
866
+ assetId: issue.assetId,
867
+ taskId: issue.taskId,
868
+ action: issue.recommendedAction,
869
+ status: 'skipped',
870
+ detail: 'Canonical metadata for this asset was no longer present; skipped queuing a recovery obligation.'
871
+ });
872
+ continue;
873
+ }
874
+ const obligationInput = buildContentPullObligationInputForAsset({
875
+ kind: issue.code === 'document_content_unverified' ? 'document' : 'asset',
876
+ path: issue.path,
877
+ entry: assetEntry,
878
+ store: input.workspaceAssetStore,
879
+ workspaceId,
880
+ });
881
+ input.contentPullObligationStore.upsertMany({
882
+ tenantId: input.tenantId,
883
+ workspaceId,
884
+ obligations: [obligationInput],
885
+ now: nowIso(),
886
+ });
887
+ actionsApplied.push({
888
+ code: issue.code,
889
+ path: issue.path,
890
+ assetId: issue.assetId,
891
+ taskId: issue.taskId,
892
+ action: issue.recommendedAction,
893
+ status: 'applied',
894
+ detail: 'Queued a durable content-pull recovery obligation instead of treating unavailable content as deleted.'
895
+ });
896
+ }
897
+ catch (error) {
898
+ actionsApplied.push({
899
+ code: issue.code,
900
+ path: issue.path,
901
+ assetId: issue.assetId,
902
+ taskId: issue.taskId,
903
+ action: issue.recommendedAction,
904
+ status: 'failed',
905
+ detail: String(error?.message || error || 'Failed to queue a recovery obligation.')
906
+ });
907
+ }
908
+ continue;
909
+ }
783
910
  if (!issue.repairable) {
784
911
  actionsApplied.push({
785
912
  code: issue.code,
@@ -947,6 +1074,34 @@ export function applyWorkspaceRepair(input) {
947
1074
  });
948
1075
  }
949
1076
  }
1077
+ if (input.contentPullObligationStore) {
1078
+ const resolutionClaims = [
1079
+ ...scan.snapshot.documents
1080
+ .filter((entry) => entry.existsLocally && entry.assetId)
1081
+ .map((entry) => ({
1082
+ kind: 'document',
1083
+ path: entry.path,
1084
+ sourceWatermark: entry.updatedAt,
1085
+ resolution: 'at-or-before-watermark',
1086
+ })),
1087
+ ...scan.snapshot.assets
1088
+ .filter((entry) => entry.existsLocally && entry.assetId)
1089
+ .map((entry) => ({
1090
+ kind: 'asset',
1091
+ path: entry.path,
1092
+ sourceWatermark: entry.updatedAt,
1093
+ resolution: 'at-or-before-watermark',
1094
+ })),
1095
+ ];
1096
+ if (resolutionClaims.length > 0) {
1097
+ input.contentPullObligationStore.resolveMany({
1098
+ tenantId: input.tenantId,
1099
+ workspaceId,
1100
+ claims: resolutionClaims,
1101
+ now: nowIso(),
1102
+ });
1103
+ }
1104
+ }
950
1105
  const refreshed = scanWorkspaceRepair(input);
951
1106
  return {
952
1107
  ...refreshed,
@@ -229,6 +229,9 @@ export interface WorkspaceSyncInitiativeSnapshot {
229
229
  order?: number | null;
230
230
  attachments?: Array<string | AttachmentItem>;
231
231
  isArchived?: boolean;
232
+ icon?: PlanningIdentityIcon | null;
233
+ color?: PlanningIdentityColor | null;
234
+ identityUpdatedAt?: string | null;
232
235
  durableRevision?: WorkspaceSyncDurablePlanningRevision<'initiative'>;
233
236
  }
234
237
  export interface WorkspaceSyncWorkstreamSnapshot {
@@ -245,6 +248,9 @@ export interface WorkspaceSyncWorkstreamSnapshot {
245
248
  order?: number | null;
246
249
  attachments?: Array<string | AttachmentItem>;
247
250
  isArchived?: boolean;
251
+ icon?: PlanningIdentityIcon | null;
252
+ color?: PlanningIdentityColor | null;
253
+ identityUpdatedAt?: string | null;
248
254
  durableRevision?: WorkspaceSyncDurablePlanningRevision<'workstream'>;
249
255
  }
250
256
  export interface WorkspaceSyncPlanningIdentitySnapshot {
@@ -425,6 +431,7 @@ export interface WorkspaceSyncPayload {
425
431
  currentInitiativeWatermarks: Map<string, string>;
426
432
  currentWorkstreamIds: Set<string>;
427
433
  currentWorkstreamWatermarks: Map<string, string>;
434
+ currentPlanningIdentityWatermarks?: Map<string, string>;
428
435
  currentAiProfileIds: Set<string>;
429
436
  currentAiProfileWatermarks: Map<string, string>;
430
437
  currentAiProfileChangeKeys?: Map<string, string>;
@@ -472,6 +479,7 @@ export interface WorkspaceSyncDeltaDiagnostics {
472
479
  taskRelationships?: WorkspaceSyncDomainDeltaDiagnostics;
473
480
  initiatives: WorkspaceSyncDomainDeltaDiagnostics;
474
481
  workstreams: WorkspaceSyncDomainDeltaDiagnostics;
482
+ planningIdentities?: WorkspaceSyncDomainDeltaDiagnostics;
475
483
  aiProfiles: WorkspaceSyncDomainDeltaDiagnostics;
476
484
  documents: WorkspaceSyncDomainDeltaDiagnostics;
477
485
  assets: WorkspaceSyncDomainDeltaDiagnostics;
@@ -537,6 +545,18 @@ export declare function buildWorkspaceSyncPayloadModel(input: {
537
545
  assets?: WorkspaceSyncAssetSnapshot[];
538
546
  currentDocumentPaths?: Iterable<string>;
539
547
  currentAssetPaths?: Iterable<string>;
548
+ /**
549
+ * Positive completeness signal for the current-workspace document/asset
550
+ * snapshot used to compute deleteDocumentPaths/deleteAssetPaths. Explicit
551
+ * `false` means the snapshot is known failed, partial, stale, for the wrong
552
+ * workspace, or not yet hydrated — the delete-diff for that domain is
553
+ * suppressed entirely rather than trusted. Omitted/undefined defaults to
554
+ * `true` for callers (tests, other pure-function consumers) that don't model
555
+ * hydration state; the real browser sync orchestrator always passes the
556
+ * verified value.
557
+ */
558
+ documentsSnapshotComplete?: boolean;
559
+ assetsSnapshotComplete?: boolean;
540
560
  documentReviewSessions?: WorkspaceSyncDocumentReviewSessionSnapshot[];
541
561
  documentReviewComments?: WorkspaceSyncDocumentReviewCommentSnapshot[];
542
562
  annotatedAttachmentSessions?: WorkspaceSyncAnnotatedAttachmentSessionSnapshot[];
@@ -549,6 +569,7 @@ export declare function buildWorkspaceSyncPayloadModel(input: {
549
569
  lastPushedInitiativeWatermarks?: Map<string, string>;
550
570
  lastPushedWorkstreamIds?: Set<string>;
551
571
  lastPushedWorkstreamWatermarks?: Map<string, string>;
572
+ lastPushedPlanningIdentityWatermarks?: Map<string, string>;
552
573
  lastPushedAiProfileIds?: Set<string>;
553
574
  lastPushedAiProfileWatermarks?: Map<string, string>;
554
575
  lastPushedDocumentPaths?: Set<string>;
@@ -223,6 +223,8 @@ export function buildWorkspaceSyncPayloadModel(input) {
223
223
  return true;
224
224
  return previousWorkstreamWatermarks.get(change.workstream.id) !== change.workstream.updatedAt;
225
225
  });
226
+ const previousPlanningIdentityWatermarks = input.lastPushedPlanningIdentityWatermarks;
227
+ const currentPlanningIdentityWatermarks = new Map();
226
228
  const planningIdentityUpsertChanges = [
227
229
  ...(Array.isArray(input.initiatives) ? input.initiatives : []).map((initiative) => ({
228
230
  entityType: 'initiative',
@@ -240,7 +242,13 @@ export function buildWorkspaceSyncPayloadModel(input) {
240
242
  })),
241
243
  ]
242
244
  .filter((identity) => identity.entityId.length > 0 && Number.isFinite(Date.parse(identity.updatedAt)))
243
- .map((identity) => ({ op: 'planning-identity-upsert', identity }));
245
+ .map((identity) => {
246
+ const identityKey = `${identity.entityType}:${identity.entityId}`;
247
+ currentPlanningIdentityWatermarks.set(identityKey, identity.updatedAt);
248
+ return { op: 'planning-identity-upsert', identity, identityKey };
249
+ })
250
+ .filter((change) => previousPlanningIdentityWatermarks?.get(change.identityKey) !== change.identity.updatedAt)
251
+ .map(({ identityKey: _identityKey, ...change }) => change);
244
252
  const currentAiProfileIds = new Set((Array.isArray(input.aiProfiles) ? input.aiProfiles : [])
245
253
  .map((profile) => String(profile?.id || '').trim())
246
254
  .filter((profileId) => profileId.length > 0));
@@ -312,9 +320,18 @@ export function buildWorkspaceSyncPayloadModel(input) {
312
320
  });
313
321
  const currentDocumentPaths = normalizeWorkspaceSyncPathSet(input.currentDocumentPaths, (Array.isArray(input.documents) ? input.documents : [])
314
322
  .map((doc) => String(doc?.path || '').trim()));
315
- const deleteDocumentPaths = new Set(Array.from(input.lastPushedDocumentPaths || new Set())
316
- .map((docPath) => String(docPath || '').trim())
317
- .filter((docPath) => docPath.length > 0 && !currentDocumentPaths.has(docPath)));
323
+ // A raw set-difference against the previous push is only trustworthy when the
324
+ // current snapshot is a verified-complete, current-workspace read. A failed,
325
+ // partial, stale, or not-yet-hydrated snapshot must never be interpreted as
326
+ // deletion intent — so documentsSnapshotComplete === false suppresses the
327
+ // entire delete-diff for this cycle rather than trusting a plausible-looking
328
+ // but potentially wrong difference.
329
+ const documentsSnapshotComplete = input.documentsSnapshotComplete !== false;
330
+ const deleteDocumentPaths = documentsSnapshotComplete
331
+ ? new Set(Array.from(input.lastPushedDocumentPaths || new Set())
332
+ .map((docPath) => String(docPath || '').trim())
333
+ .filter((docPath) => docPath.length > 0 && !currentDocumentPaths.has(docPath)))
334
+ : new Set();
318
335
  const currentDocumentWatermarks = new Map((Array.isArray(input.documents) ? input.documents : [])
319
336
  .map((doc) => [String(doc?.path || '').trim(), String(doc?.updatedAt || '').trim()])
320
337
  .filter(([docPath]) => docPath.length > 0));
@@ -349,9 +366,14 @@ export function buildWorkspaceSyncPayloadModel(input) {
349
366
  });
350
367
  const currentAssetPaths = normalizeWorkspaceSyncPathSet(input.currentAssetPaths, (Array.isArray(input.assets) ? input.assets : [])
351
368
  .map((asset) => String(asset?.path || '').trim()));
352
- const deleteAssetPaths = new Set(Array.from(input.lastPushedAssetPaths || new Set())
353
- .map((assetPath) => String(assetPath || '').trim())
354
- .filter((assetPath) => assetPath.length > 0 && !currentAssetPaths.has(assetPath)));
369
+ // See documentsSnapshotComplete above the same admission boundary applies
370
+ // to assets.
371
+ const assetsSnapshotComplete = input.assetsSnapshotComplete !== false;
372
+ const deleteAssetPaths = assetsSnapshotComplete
373
+ ? new Set(Array.from(input.lastPushedAssetPaths || new Set())
374
+ .map((assetPath) => String(assetPath || '').trim())
375
+ .filter((assetPath) => assetPath.length > 0 && !currentAssetPaths.has(assetPath)))
376
+ : new Set();
355
377
  const currentAssetWatermarks = new Map((Array.isArray(input.assets) ? input.assets : [])
356
378
  .map((asset) => [String(asset?.path || '').trim(), String(asset?.updatedAt || '').trim()])
357
379
  .filter(([assetPath]) => assetPath.length > 0));
@@ -958,6 +980,7 @@ export function buildWorkspaceSyncPayloadModel(input) {
958
980
  currentInitiativeWatermarks,
959
981
  currentWorkstreamIds,
960
982
  currentWorkstreamWatermarks,
983
+ currentPlanningIdentityWatermarks,
961
984
  currentAiProfileIds,
962
985
  currentAiProfileWatermarks,
963
986
  currentAiProfileChangeKeys,
@@ -1012,6 +1035,11 @@ export function buildWorkspaceSyncPayloadModel(input) {
1012
1035
  baselineCount: previousWorkstreamWatermarks?.size || 0,
1013
1036
  upsertCount: workstreamUpsertChanges.length
1014
1037
  }),
1038
+ planningIdentities: resolveDomainDeltaDiagnostics({
1039
+ currentCount: currentPlanningIdentityWatermarks.size,
1040
+ baselineCount: previousPlanningIdentityWatermarks?.size || 0,
1041
+ upsertCount: planningIdentityUpsertChanges.length
1042
+ }),
1015
1043
  aiProfiles: resolveDomainDeltaDiagnostics({
1016
1044
  currentCount: currentAiProfileIds.size,
1017
1045
  baselineCount: previousAiProfileWatermarks?.size || 0,
@@ -11,6 +11,7 @@ export interface WorkspaceSyncPushBaselineSnapshot {
11
11
  taskRelationshipChangeKeys?: Array<[string, string]>;
12
12
  initiativeWatermarks: Array<[string, string]>;
13
13
  workstreamWatermarks: Array<[string, string]>;
14
+ planningIdentityWatermarks?: Array<[string, string]>;
14
15
  aiProfileWatermarks: Array<[string, string]>;
15
16
  aiProfileChangeKeys?: Array<[string, string]>;
16
17
  taskforceAgentWatermarks?: Array<[string, string]>;
@@ -19,6 +19,9 @@ export interface WorkspaceSyncV2SnapshotInput {
19
19
  assets?: readonly WorkspaceSyncAssetSnapshot[];
20
20
  currentDocumentPaths?: ReadonlySet<string>;
21
21
  currentAssetPaths?: ReadonlySet<string>;
22
+ /** See WorkspaceSyncPayloadModel's documentsSnapshotComplete/assetsSnapshotComplete. */
23
+ documentsSnapshotComplete?: boolean;
24
+ assetsSnapshotComplete?: boolean;
22
25
  documentReviewSessions?: readonly WorkspaceSyncDocumentReviewSessionSnapshot[];
23
26
  documentReviewComments?: readonly WorkspaceSyncDocumentReviewCommentSnapshot[];
24
27
  annotatedAttachmentSessions?: readonly WorkspaceSyncAnnotatedAttachmentSessionSnapshot[];
@@ -45,6 +48,8 @@ export interface WorkspaceSyncV2FrozenSnapshot {
45
48
  readonly assets: readonly WorkspaceSyncAssetSnapshot[];
46
49
  readonly currentDocumentPaths: ReadonlySet<string>;
47
50
  readonly currentAssetPaths: ReadonlySet<string>;
51
+ readonly documentsSnapshotComplete: boolean;
52
+ readonly assetsSnapshotComplete: boolean;
48
53
  readonly documentReviewSessions: readonly WorkspaceSyncDocumentReviewSessionSnapshot[];
49
54
  readonly documentReviewComments: readonly WorkspaceSyncDocumentReviewCommentSnapshot[];
50
55
  readonly annotatedAttachmentSessions: readonly WorkspaceSyncAnnotatedAttachmentSessionSnapshot[];
@@ -64,6 +69,7 @@ export interface WorkspaceSyncV2PushBaseline {
64
69
  readonly lastPushedInitiativeWatermarks: ReadonlyMap<string, string>;
65
70
  readonly lastPushedWorkstreamIds: ReadonlySet<string>;
66
71
  readonly lastPushedWorkstreamWatermarks: ReadonlyMap<string, string>;
72
+ readonly lastPushedPlanningIdentityWatermarks?: ReadonlyMap<string, string>;
67
73
  readonly lastPushedAiProfileIds: ReadonlySet<string>;
68
74
  readonly lastPushedAiProfileWatermarks: ReadonlyMap<string, string>;
69
75
  readonly lastPushedAiProfileChangeKeys: ReadonlyMap<string, string>;