@taskforcehq/taskforce 0.3.328 → 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 (485) hide show
  1. package/dist/Taskforce.module.css +523 -79
  2. package/dist/TaskforceCore.js +237 -230
  3. package/dist/annotatedAttachments/AnnotatedAttachmentSessionStore.js +1 -1
  4. package/dist/cli.js +34 -0
  5. package/dist/cliCloudTargetGuard.d.ts +5 -0
  6. package/dist/cliCloudTargetGuard.js +11 -0
  7. package/dist/components/features/AiProfilesModule.js +3 -5
  8. package/dist/components/features/AnnotatedAttachmentWorkspace.js +24 -8
  9. package/dist/components/features/TaskSettings.d.ts +12 -1
  10. package/dist/components/features/TaskSettings.js +217 -54
  11. package/dist/components/features/TaskforceAgentsModule.d.ts +1 -2
  12. package/dist/components/features/TaskforceAgentsModule.js +586 -116
  13. package/dist/components/features/agentCapabilities/AgentCapabilitiesPrototype.d.ts +1 -1
  14. package/dist/components/features/agentConnections/AgentConnectionControl.d.ts +15 -0
  15. package/dist/components/features/agentConnections/AgentConnectionControl.js +125 -0
  16. package/dist/components/features/agentConnections/ModelConnectionsPanel.d.ts +18 -0
  17. package/dist/components/features/agentConnections/ModelConnectionsPanel.js +393 -0
  18. package/dist/components/features/agentConnections/modelConnectionsApi.d.ts +65 -0
  19. package/dist/components/features/agentConnections/modelConnectionsApi.js +129 -0
  20. package/dist/components/features/planning/PlanningModule.js +2 -5
  21. package/dist/components/features/planning/PlanningTaskOrderList.d.ts +1 -1
  22. package/dist/components/features/planning/PlanningTaskOrderList.js +17 -6
  23. package/dist/components/features/planning/planningTaskArrangement.d.ts +1 -0
  24. package/dist/components/features/planning/planningTaskArrangement.js +5 -5
  25. package/dist/components/features/taskforceAgentAssignments/AgentBehaviorAssignments.js +15 -24
  26. package/dist/components/features/taskforceAgentEditorModel.d.ts +2 -1
  27. package/dist/components/features/taskforceAgentEditorModel.js +5 -1
  28. package/dist/components/features/workflowManager/workflowManagerApi.d.ts +1 -1
  29. package/dist/components/features/workflowManager/workflowManagerApi.js +3 -0
  30. package/dist/components/task/TaskCard.d.ts +5 -0
  31. package/dist/components/task/TaskCard.js +65 -10
  32. package/dist/components/task/TaskImageReviews.js +14 -5
  33. package/dist/components/task/TaskKanban.d.ts +6 -1
  34. package/dist/components/task/TaskKanban.js +152 -6
  35. package/dist/components/task/TaskList.d.ts +5 -0
  36. package/dist/components/task/TaskList.js +3 -3
  37. package/dist/components/task/TaskWorkflowAssignmentField.js +68 -10
  38. package/dist/components/ui/PasswordInput.d.ts +6 -0
  39. package/dist/components/ui/PasswordInput.js +11 -0
  40. package/dist/components/ui/TopNoticeLayer.js +1 -1
  41. package/dist/components/views/AppShellHeader.js +32 -11
  42. package/dist/components/views/PlanComparisonPage.js +12 -0
  43. package/dist/components/views/StandaloneLayout.js +32 -55
  44. package/dist/components/views/WidgetView.js +3 -3
  45. package/dist/components/views/panels/PlanningDrawer.js +5 -12
  46. package/dist/components/views/standalone/modals/AccountSettingsModal.js +26 -17
  47. package/dist/components/views/standalone/modals/SyncStatusModal.d.ts +4 -3
  48. package/dist/components/views/standalone/modals/SyncStatusModal.js +33 -38
  49. package/dist/config/envSchema.js +60 -1
  50. package/dist/config/localServiceRuntimeContract.d.ts +13 -0
  51. package/dist/config/localServiceRuntimeContract.js +135 -0
  52. package/dist/core/AiProfileService.js +46 -8
  53. package/dist/core/DeletedTaskLifecycleService.d.ts +1 -0
  54. package/dist/core/DeletedTaskLifecycleService.js +37 -6
  55. package/dist/core/McpTokenService.d.ts +23 -1
  56. package/dist/core/McpTokenService.js +93 -10
  57. package/dist/core/TaskAttachmentLinksDurableMutationService.d.ts +3 -2
  58. package/dist/core/TaskAttachmentLinksDurableMutationService.js +33 -9
  59. package/dist/core/TaskChecklistCommandService.d.ts +27 -0
  60. package/dist/core/TaskChecklistCommandService.js +83 -5
  61. package/dist/core/TaskLifecycleCommandService.d.ts +3 -1
  62. package/dist/core/TaskLifecycleCommandService.js +6 -2
  63. package/dist/core/Taskforce.d.ts +94 -2
  64. package/dist/core/Taskforce.js +760 -36
  65. package/dist/core/types.d.ts +14 -0
  66. package/dist/documentReviews/commandService.d.ts +2 -1
  67. package/dist/documentReviews/commandService.js +6 -3
  68. package/dist/hooks/sync/orchestratorShared.d.ts +1 -0
  69. package/dist/hooks/sync/orchestratorShared.js +2 -0
  70. package/dist/hooks/sync/useDurableLocalOutboxDrain.d.ts +1 -1
  71. package/dist/hooks/sync/useDurableTaskCreateMutation.js +1 -1
  72. package/dist/hooks/sync/useDurableTaskMetadataMutation.d.ts +1 -0
  73. package/dist/hooks/sync/useDurableTaskMetadataMutation.js +1 -0
  74. package/dist/hooks/sync/useDurableTaskStatusMutation.d.ts +1 -0
  75. package/dist/hooks/sync/useLocalSyncCoordinatorSnapshot.d.ts +3 -0
  76. package/dist/hooks/sync/useLocalSyncCoordinatorSnapshot.js +85 -9
  77. package/dist/hooks/sync/useSyncStatusControls.d.ts +4 -1
  78. package/dist/hooks/sync/useSyncStatusControls.js +47 -11
  79. package/dist/hooks/tasks/taskHttpMutation.js +1 -0
  80. package/dist/hooks/tasks/useCloudTaskSearch.d.ts +12 -0
  81. package/dist/hooks/tasks/useCloudTaskSearch.js +71 -0
  82. package/dist/hooks/tasks/useTaskDescriptionImageDraftRecovery.d.ts +16 -0
  83. package/dist/hooks/tasks/useTaskDescriptionImageDraftRecovery.js +197 -0
  84. package/dist/hooks/tasks/useTaskEditorNavigation.d.ts +16 -3
  85. package/dist/hooks/tasks/useTaskEditorNavigation.js +72 -13
  86. package/dist/hooks/tasks/useTaskFormActions.d.ts +6 -0
  87. package/dist/hooks/tasks/useTaskFormActions.js +65 -12
  88. package/dist/hooks/ui/useSettingsModel.d.ts +24 -2
  89. package/dist/hooks/ui/useSettingsModel.js +13 -2
  90. package/dist/hooks/ui/useSettingsPersistence.d.ts +12 -1
  91. package/dist/hooks/ui/useSettingsPersistence.js +74 -47
  92. package/dist/hooks/useFilterSort.d.ts +7 -3
  93. package/dist/hooks/useFilterSort.js +15 -5
  94. package/dist/hooks/useSyncOrchestrator.d.ts +3 -0
  95. package/dist/hooks/useSyncOrchestrator.js +111 -2
  96. package/dist/hooks/useTaskData.d.ts +40 -1
  97. package/dist/hooks/useTaskData.js +240 -9
  98. package/dist/hooks/useTaskMutations.d.ts +12 -2
  99. package/dist/hooks/useTaskMutations.js +266 -52
  100. package/dist/hooks/useTaskforce.d.ts +39 -9
  101. package/dist/hooks/useTaskforce.js +359 -40
  102. package/dist/hooks/useUiNotice.d.ts +4 -0
  103. package/dist/hooks/useUiNotice.js +4 -0
  104. package/dist/mcp/adminWorkspaceRegistrar.js +3 -3
  105. package/dist/mcp/clientRegistry.d.ts +2 -2
  106. package/dist/mcp/clientRegistry.js +1 -1
  107. package/dist/mcp/documentAssetRegistrar.js +53 -41
  108. package/dist/mcp/documentHelpers.d.ts +1 -0
  109. package/dist/mcp/documentHelpers.js +7 -3
  110. package/dist/mcp/durableTaskMutationRouter.d.ts +4 -1
  111. package/dist/mcp/durableTaskMutationRouter.js +10 -0
  112. package/dist/mcp/durableTaskRelationshipMutationRouter.js +4 -0
  113. package/dist/mcp/httpProtocolRouting.d.ts +10 -0
  114. package/dist/mcp/httpProtocolRouting.js +19 -0
  115. package/dist/mcp/localCliHealth.d.ts +2 -2
  116. package/dist/mcp/localCliHealth.js +2 -2
  117. package/dist/mcp/localServiceProxy.d.ts +1 -0
  118. package/dist/mcp/localServiceProxy.js +530 -68
  119. package/dist/mcp/planningAttachmentCommandAdapter.d.ts +3 -1
  120. package/dist/mcp/planningAttachmentCommandAdapter.js +20 -2
  121. package/dist/mcp/runtime.d.ts +54 -79
  122. package/dist/mcp/runtime.js +556 -139
  123. package/dist/mcp/taskPlanningRegistrar.js +64 -42
  124. package/dist/mcp/toolCallCompatibility.js +38 -1
  125. package/dist/mcp/toolCatalog.d.ts +1 -0
  126. package/dist/mcp/toolProfiles.d.ts +2 -0
  127. package/dist/mcp/toolProfiles.js +10 -0
  128. package/dist/mcp/toolRegistry.d.ts +1 -0
  129. package/dist/mcp/toolRegistry.js +1 -0
  130. package/dist/mcp/workflowExecutionRegistrar.js +4 -4
  131. package/dist/migrations/taskSchemaMigrations.d.ts +5 -0
  132. package/dist/migrations/taskSchemaMigrations.js +427 -0
  133. package/dist/runtime/appGateDefinitions.d.ts +30 -6
  134. package/dist/runtime/appGateDefinitions.js +6 -6
  135. package/dist/runtime/appGates.d.ts +13 -13
  136. package/dist/runtime/appGates.js +36 -13
  137. package/dist/runtime/nodeAppGates.d.ts +8 -0
  138. package/dist/runtime/nodeAppGates.js +27 -0
  139. package/dist/server/cloudCollectionRead.d.ts +1 -1
  140. package/dist/server/cloudCollectionRead.js +2 -2
  141. package/dist/server/index.d.ts +6 -0
  142. package/dist/server/index.js +123 -14
  143. package/dist/server/localDatabaseIdentity.js +4 -1
  144. package/dist/server/localServiceLease.d.ts +3 -0
  145. package/dist/server/localServiceLease.js +11 -2
  146. package/dist/server/localServiceSessions.d.ts +14 -17
  147. package/dist/server/localServiceSessions.js +308 -94
  148. package/dist/server/localWorkspaceSyncServerRuntime.js +12 -7
  149. package/dist/server/rateLimit.d.ts +1 -0
  150. package/dist/server/rateLimit.js +4 -0
  151. package/dist/server/realtimeSyncWs.js +36 -12
  152. package/dist/server/routes/admin.d.ts +4 -0
  153. package/dist/server/routes/admin.js +113 -3
  154. package/dist/server/routes/agentRoles.js +3 -2
  155. package/dist/server/routes/agentSkills.js +3 -2
  156. package/dist/server/routes/agents.d.ts +7 -0
  157. package/dist/server/routes/agents.js +394 -39
  158. package/dist/server/routes/annotatedAttachments.js +3 -2
  159. package/dist/server/routes/auth.js +3 -1
  160. package/dist/server/routes/billing.js +5 -1
  161. package/dist/server/routes/durableTaskHttpRouters.d.ts +11 -2
  162. package/dist/server/routes/executorPhaseAApprovals.d.ts +19 -0
  163. package/dist/server/routes/executorPhaseAApprovals.js +140 -0
  164. package/dist/server/routes/executorPhaseAIssuerRedemptions.d.ts +11 -0
  165. package/dist/server/routes/executorPhaseAIssuerRedemptions.js +24 -0
  166. package/dist/server/routes/githubReviewEvidence.d.ts +19 -0
  167. package/dist/server/routes/githubReviewEvidence.js +116 -0
  168. package/dist/server/routes/localService.d.ts +15 -4
  169. package/dist/server/routes/localService.js +138 -40
  170. package/dist/server/routes/modelConnections.d.ts +24 -0
  171. package/dist/server/routes/modelConnections.js +205 -0
  172. package/dist/server/routes/primitives.d.ts +2 -0
  173. package/dist/server/routes/shared.d.ts +19 -0
  174. package/dist/server/routes/shared.js +95 -19
  175. package/dist/server/routes/sync.js +1 -0
  176. package/dist/server/routes/syncAuxRoutes.js +9 -2
  177. package/dist/server/routes/syncPullApplyRoutes.js +23 -4
  178. package/dist/server/routes/syncPushRoutes.d.ts +1 -0
  179. package/dist/server/routes/syncPushRoutes.js +1 -0
  180. package/dist/server/routes/syncV3FeedRoutes.js +27 -16
  181. package/dist/server/routes/syncV3LocalCaptureRoutes.js +28 -2
  182. package/dist/server/routes/syncV3LocalFeedApplyRoutes.d.ts +1 -0
  183. package/dist/server/routes/syncV3LocalFeedApplyRoutes.js +26 -0
  184. package/dist/server/routes/syncV3OperationRoutes.js +45 -9
  185. package/dist/server/routes/tasks.js +124 -13
  186. package/dist/server/routes/workflows.js +9 -1
  187. package/dist/server/routes/workspaces.js +43 -1
  188. package/dist/server/routes.js +59 -0
  189. package/dist/server/workspaceDeletionAdmission.d.ts +23 -0
  190. package/dist/server/workspaceDeletionAdmission.js +50 -0
  191. package/dist/service/localServiceCli.js +16 -0
  192. package/dist/service/localServiceClientLifecycle.js +36 -10
  193. package/dist/services/codexAppServerModelGateway.d.ts +161 -0
  194. package/dist/services/codexAppServerModelGateway.js +663 -0
  195. package/dist/services/codexDeviceCodeLoginManager.d.ts +39 -0
  196. package/dist/services/codexDeviceCodeLoginManager.js +265 -0
  197. package/dist/services/codexModelProviderConnectionLifecycle.d.ts +8 -0
  198. package/dist/services/codexModelProviderConnectionLifecycle.js +73 -0
  199. package/dist/services/executorPhaseAApprovalRuntime.d.ts +14 -0
  200. package/dist/services/executorPhaseAApprovalRuntime.js +24 -0
  201. package/dist/services/executorPhaseAApprovalService.d.ts +40 -0
  202. package/dist/services/executorPhaseAApprovalService.js +609 -0
  203. package/dist/services/executorPhaseADriftEvaluator.d.ts +78 -0
  204. package/dist/services/executorPhaseADriftEvaluator.js +93 -0
  205. package/dist/services/executorPhaseAIssuerCore.d.ts +126 -0
  206. package/dist/services/executorPhaseAIssuerCore.js +295 -0
  207. package/dist/services/executorPhaseAIssuerRedemptionService.d.ts +34 -0
  208. package/dist/services/executorPhaseAIssuerRedemptionService.js +158 -0
  209. package/dist/services/githubReviewEvidenceRuntime.d.ts +14 -0
  210. package/dist/services/githubReviewEvidenceRuntime.js +30 -0
  211. package/dist/services/githubReviewEvidenceService.d.ts +93 -0
  212. package/dist/services/githubReviewEvidenceService.js +336 -0
  213. package/dist/services/modelGateway.d.ts +7 -0
  214. package/dist/services/modelProviderConnectionService.d.ts +71 -0
  215. package/dist/services/modelProviderConnectionService.js +279 -0
  216. package/dist/services/modelProviderCredentialHome.d.ts +32 -0
  217. package/dist/services/modelProviderCredentialHome.js +271 -0
  218. package/dist/services/ownerScopedModelConnectionGateway.d.ts +12 -0
  219. package/dist/services/ownerScopedModelConnectionGateway.js +30 -0
  220. package/dist/services/taskforceAgentConnectionBindingService.d.ts +66 -0
  221. package/dist/services/taskforceAgentConnectionBindingService.js +185 -0
  222. package/dist/services/taskforceAgentMcpBridge.d.ts +8 -2
  223. package/dist/services/taskforceAgentMcpBridge.js +30 -27
  224. package/dist/shared/adminEdgeProxy.d.ts +5 -0
  225. package/dist/shared/adminEdgeProxy.js +94 -0
  226. package/dist/shared/adminProxySessionCookies.d.ts +16 -0
  227. package/dist/shared/adminProxySessionCookies.js +86 -0
  228. package/dist/shared/aiProfileColors.d.ts +31 -1
  229. package/dist/shared/aiProfileColors.js +14 -6
  230. package/dist/shared/executorPhaseAApprovalGoldenVector.json +269 -0
  231. package/dist/shared/executorPhaseAApprovalReceipt.d.ts +112 -0
  232. package/dist/shared/executorPhaseAApprovalReceipt.js +58 -0
  233. package/dist/shared/executorPhaseAApprovalTrustPolicy.json +10 -0
  234. package/dist/shared/executorPhaseADriftContracts.d.ts +37 -0
  235. package/dist/shared/executorPhaseADriftContracts.js +63 -0
  236. package/dist/shared/executorPhaseAIssuerContracts.d.ts +75 -0
  237. package/dist/shared/executorPhaseAIssuerContracts.js +90 -0
  238. package/dist/shared/executorPhaseARunAuthorization.d.ts +120 -0
  239. package/dist/shared/executorPhaseARunAuthorization.js +232 -0
  240. package/dist/shared/executorPhaseASchemaValidation.d.ts +7 -0
  241. package/dist/shared/executorPhaseASchemaValidation.js +53 -0
  242. package/dist/shared/executorPhaseASchemas/approval-receipt.schema.json +106 -0
  243. package/dist/shared/executorPhaseASchemas/drift-attestation.schema.json +54 -0
  244. package/dist/shared/executorPhaseASchemas/drift-request.schema.json +47 -0
  245. package/dist/shared/executorPhaseASchemas/foundation-manifest.schema.json +29 -0
  246. package/dist/shared/executorPhaseASchemas/issuer-audit-record.schema.json +24 -0
  247. package/dist/shared/executorPhaseASchemas/issuer-proof.schema.json +43 -0
  248. package/dist/shared/executorPhaseASchemas/issuer-redemption-request.schema.json +18 -0
  249. package/dist/shared/executorPhaseASchemas/issuer-redemption-response.schema.json +39 -0
  250. package/dist/shared/executorPhaseASchemas/logical-envelope.schema.json +149 -0
  251. package/dist/shared/executorPhaseASchemas/preflight-report.schema.json +216 -0
  252. package/dist/shared/executorPhaseASchemas/run-capability.schema.json +111 -0
  253. package/dist/shared/executorPhaseASchemas/sender-proof.schema.json +37 -0
  254. package/dist/shared/executorPhaseASchemas/workload-grant.schema.json +68 -0
  255. package/dist/shared/executorPhaseASchemas/workload-jwt-claims.schema.json +67 -0
  256. package/dist/shared/executorPhaseATiming.d.ts +1 -0
  257. package/dist/shared/executorPhaseATiming.js +1 -0
  258. package/dist/shared/planningIdentity.js +1 -1
  259. package/dist/shared/productLogoKeys.d.ts +2 -0
  260. package/dist/shared/productLogoKeys.js +18 -0
  261. package/dist/shared/taskforceAgentDefinition.d.ts +0 -1
  262. package/dist/shared/taskforceAgentDefinition.js +6 -3
  263. package/dist/shared/taskforceAgentModels.d.ts +1 -0
  264. package/dist/shared/taskforceAgentModels.js +36 -3
  265. package/dist/shared/userFeatureGrants.d.ts +4 -0
  266. package/dist/shared/userFeatureGrants.js +7 -0
  267. package/dist/storage/executorPhaseAApprovalReceiptStore.d.ts +37 -0
  268. package/dist/storage/executorPhaseAApprovalReceiptStore.js +81 -0
  269. package/dist/storage/executorPhaseARunAuthorizationStore.d.ts +103 -0
  270. package/dist/storage/executorPhaseARunAuthorizationStore.js +492 -0
  271. package/dist/storage/githubReviewEvidenceInstallationStore.d.ts +26 -0
  272. package/dist/storage/githubReviewEvidenceInstallationStore.js +89 -0
  273. package/dist/storage/modelProviderConnectionStore.d.ts +99 -0
  274. package/dist/storage/modelProviderConnectionStore.js +446 -0
  275. package/dist/storage/postgresAdapter.d.ts +24 -3
  276. package/dist/storage/postgresAdapter.js +117 -14
  277. package/dist/storage/postgresWorker.js +22 -5
  278. package/dist/storage/postgresWorkerProtocol.d.ts +30 -0
  279. package/dist/storage/postgresWorkerProtocol.js +30 -0
  280. package/dist/storage/taskforceAgentConnectionBindingStore.d.ts +31 -0
  281. package/dist/storage/taskforceAgentConnectionBindingStore.js +84 -0
  282. package/dist/sync/cloudSyncApi.d.ts +4 -1
  283. package/dist/sync/cloudSyncApi.js +7 -2
  284. package/dist/sync/contentSyncState.d.ts +1 -1
  285. package/dist/sync/coordinator/localSyncExecutionPermitStore.d.ts +1 -0
  286. package/dist/sync/coordinator/localSyncExecutionPermitStore.js +67 -30
  287. package/dist/sync/coordinator/localWorkspaceSyncPendingV2PushProgress.d.ts +10 -0
  288. package/dist/sync/coordinator/localWorkspaceSyncPendingV2PushProgress.js +29 -0
  289. package/dist/sync/coordinator/localWorkspaceSyncRunner.js +6 -2
  290. package/dist/sync/coordinator/localWorkspaceSyncRunnerState.d.ts +15 -1
  291. package/dist/sync/coordinator/localWorkspaceSyncRunnerState.js +99 -2
  292. package/dist/sync/coordinator/workspaceSyncCredentialBroker.d.ts +1 -0
  293. package/dist/sync/coordinator/workspaceSyncCredentialBroker.js +33 -4
  294. package/dist/sync/engine/workspaceSyncContentLifecycleAdapter.d.ts +2 -1
  295. package/dist/sync/engine/workspaceSyncContentVersionStore.d.ts +38 -0
  296. package/dist/sync/engine/workspaceSyncContentVersionStore.js +50 -1
  297. package/dist/sync/engine/workspaceSyncEngineBrowserGatewayRemoteServices.js +20 -2
  298. package/dist/sync/engine/workspaceSyncEngineLifecyclePolicy.js +6 -6
  299. package/dist/sync/engine/workspaceSyncEngineLocalServices.d.ts +4 -0
  300. package/dist/sync/engine/workspaceSyncEngineLocalServices.js +11 -0
  301. package/dist/sync/engine/workspaceSyncEnginePushCompletion.d.ts +14 -0
  302. package/dist/sync/engine/workspaceSyncEnginePushCompletion.js +84 -0
  303. package/dist/sync/engine/workspaceSyncEngineRecovery.js +1 -0
  304. package/dist/sync/engine/workspaceSyncEngineRemoteServices.d.ts +11 -0
  305. package/dist/sync/engine/workspaceSyncEngineRemoteServices.js +2 -1
  306. package/dist/sync/engine/workspaceSyncEngineRuntime.d.ts +1 -0
  307. package/dist/sync/engine/workspaceSyncEngineRuntime.js +1 -0
  308. package/dist/sync/engine/workspaceSyncEngineServerRemoteServices.js +31 -4
  309. package/dist/sync/engine/workspaceSyncEngineServerRunnerOperations.d.ts +3 -1
  310. package/dist/sync/engine/workspaceSyncEngineServerRunnerOperations.js +134 -43
  311. package/dist/sync/engine/workspaceSyncEngineServerSnapshotReader.js +6 -0
  312. package/dist/sync/engine/workspaceSyncEngineTransfers.d.ts +1 -1
  313. package/dist/sync/engine/workspaceSyncEngineTransfers.js +11 -4
  314. package/dist/sync/engine/workspaceSyncV2ChangeDispatcher.d.ts +1 -0
  315. package/dist/sync/engine/workspaceSyncV2ChangeDispatcher.js +29 -0
  316. package/dist/sync/syncApplyHandlers.d.ts +2 -0
  317. package/dist/sync/syncApplyHandlers.js +10 -1
  318. package/dist/sync/syncService.d.ts +17 -0
  319. package/dist/sync/syncService.js +87 -19
  320. package/dist/sync/taskforceAgentSyncAuthorization.d.ts +16 -0
  321. package/dist/sync/taskforceAgentSyncAuthorization.js +20 -0
  322. package/dist/sync/v3/combinedFeedCapability.js +8 -0
  323. package/dist/sync/v3/durableInitiativeMutationRouter.js +18 -10
  324. package/dist/sync/v3/durableOperationReplay.d.ts +14 -0
  325. package/dist/sync/v3/durableOperationReplay.js +18 -0
  326. package/dist/sync/v3/durableTaskAttachmentLinksMutationRouter.d.ts +2 -0
  327. package/dist/sync/v3/durableTaskAttachmentLinksMutationRouter.js +14 -1
  328. package/dist/sync/v3/durableTaskChecklistMutationRouter.d.ts +4 -1
  329. package/dist/sync/v3/durableTaskChecklistMutationRouter.js +62 -15
  330. package/dist/sync/v3/durableTaskCommentMutationRouter.js +3 -0
  331. package/dist/sync/v3/durableTaskHttpBulkMutationRouter.d.ts +1 -0
  332. package/dist/sync/v3/durableTaskHttpBulkMutationRouter.js +30 -8
  333. package/dist/sync/v3/durableTaskHttpRootMutationRouter.d.ts +5 -3
  334. package/dist/sync/v3/durableTaskHttpRootMutationRouter.js +37 -2
  335. package/dist/sync/v3/durableTaxonomyMutationRouter.js +5 -0
  336. package/dist/sync/v3/durableWorkflowRuntimeMutationRouter.d.ts +11 -0
  337. package/dist/sync/v3/durableWorkflowRuntimeMutationRouter.js +39 -10
  338. package/dist/sync/v3/durableWorkstreamMutationRouter.js +18 -10
  339. package/dist/sync/v3/durableWorkstreamTaskOrderMutationRouter.js +16 -5
  340. package/dist/sync/v3/localOutboxDispatchRuntime.js +2 -2
  341. package/dist/sync/v3/localTaskAttachmentLinksOutboxService.d.ts +2 -0
  342. package/dist/sync/v3/localTaskAttachmentLinksOutboxService.js +47 -7
  343. package/dist/sync/v3/localTaskChecklistOutboxHandler.js +16 -2
  344. package/dist/sync/v3/localTaskChecklistOutboxService.d.ts +4 -0
  345. package/dist/sync/v3/localTaskChecklistOutboxService.js +14 -1
  346. package/dist/sync/v3/localTaskCreateOutboxService.js +15 -6
  347. package/dist/sync/v3/localTaskMetadataClient.d.ts +1 -0
  348. package/dist/sync/v3/localTaskMetadataClient.js +1 -0
  349. package/dist/sync/v3/localTaskMetadataOutboxHandler.js +5 -1
  350. package/dist/sync/v3/localTaskMetadataOutboxService.d.ts +2 -0
  351. package/dist/sync/v3/localTaskMetadataOutboxService.js +7 -0
  352. package/dist/sync/v3/localTaskRestoreOutboxService.js +14 -6
  353. package/dist/sync/v3/localTaskStatusClient.d.ts +1 -0
  354. package/dist/sync/v3/localTaskStatusClient.js +6 -1
  355. package/dist/sync/v3/localTaskStatusOutboxService.d.ts +10 -0
  356. package/dist/sync/v3/localTaskStatusOutboxService.js +272 -24
  357. package/dist/sync/v3/syncDurabilityStore.d.ts +41 -0
  358. package/dist/sync/v3/syncDurabilityStore.js +199 -13
  359. package/dist/sync/v3/taskAttachmentLinksMutationService.d.ts +6 -4
  360. package/dist/sync/v3/taskAttachmentLinksMutationService.js +19 -10
  361. package/dist/sync/v3/taskChecklistMutationService.d.ts +15 -2
  362. package/dist/sync/v3/taskChecklistMutationService.js +48 -1
  363. package/dist/sync/v3/taskCreateMutationService.d.ts +2 -2
  364. package/dist/sync/v3/taskCreateMutationService.js +7 -4
  365. package/dist/sync/v3/taskMetadataMutationService.d.ts +3 -0
  366. package/dist/sync/v3/taskMetadataMutationService.js +4 -0
  367. package/dist/sync/v3/taskRestoreMutationService.d.ts +2 -2
  368. package/dist/sync/v3/taskRestoreMutationService.js +7 -4
  369. package/dist/sync/v3/taskStatusMutationService.d.ts +31 -1
  370. package/dist/sync/v3/taskStatusMutationService.js +123 -3
  371. package/dist/sync/v3/workflowAssignmentSync.d.ts +6 -0
  372. package/dist/sync/v3/workflowAssignmentSync.js +30 -0
  373. package/dist/sync/v3/workspaceSyncJournalReader.js +1 -1
  374. package/dist/sync/v3/workspaceSyncOperationRetentionService.d.ts +16 -0
  375. package/dist/sync/v3/workspaceSyncOperationRetentionService.js +83 -0
  376. package/dist/sync/v3/workspaceSyncV2ProjectionExclusions.d.ts +1 -1
  377. package/dist/sync/v3/workspaceSyncV2ProjectionExclusions.js +13 -3
  378. package/dist/sync/v3/workspaceSyncV3AttachmentApplyObligationStore.d.ts +11 -0
  379. package/dist/sync/v3/workspaceSyncV3AttachmentApplyObligationStore.js +27 -10
  380. package/dist/sync/v3/workspaceSyncV3AttachmentAssetHydration.d.ts +2 -1
  381. package/dist/sync/v3/workspaceSyncV3AttachmentAssetHydration.js +52 -10
  382. package/dist/sync/v3/workspaceSyncV3CloudOperationHandler.d.ts +1 -0
  383. package/dist/sync/v3/workspaceSyncV3CloudOperationHandler.js +18 -3
  384. package/dist/sync/v3/workspaceSyncV3CombinedFeedOrchestrator.js +8 -3
  385. package/dist/sync/v3/workspaceSyncV3CombinedLocalApply.js +51 -10
  386. package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.d.ts +14 -0
  387. package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.js +49 -25
  388. package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.d.ts +13 -4
  389. package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.js +124 -57
  390. package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.d.ts +20 -0
  391. package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.js +106 -30
  392. package/dist/sync/v3/workspaceSyncV3CombinedWireContract.d.ts +4 -1
  393. package/dist/sync/v3/workspaceSyncV3CombinedWireContract.js +34 -0
  394. package/dist/sync/v3/workspaceSyncV3CoverageRegistry.js +12 -0
  395. package/dist/sync/v3/workspaceSyncV3FeedProfile.d.ts +1 -1
  396. package/dist/sync/v3/workspaceSyncV3LegacyBoundaryAttestation.d.ts +1 -0
  397. package/dist/sync/v3/workspaceSyncV3LegacyBoundaryAttestation.js +23 -10
  398. package/dist/sync/v3/workspaceSyncV3NestedTaskApply.d.ts +3 -0
  399. package/dist/sync/v3/workspaceSyncV3NestedTaskApply.js +64 -13
  400. package/dist/sync/v3/workspaceSyncV3NestedTaskCodecs.d.ts +9 -0
  401. package/dist/sync/v3/workspaceSyncV3NestedTaskCodecs.js +26 -0
  402. package/dist/sync/v3/workspaceSyncV3NestedTaskProjection.d.ts +15 -5
  403. package/dist/sync/v3/workspaceSyncV3NestedTaskProjection.js +50 -14
  404. package/dist/sync/v3/workspaceSyncV3NestedTaskRepairSnapshot.d.ts +2 -1
  405. package/dist/sync/v3/workspaceSyncV3NestedTaskRepairSnapshot.js +11 -3
  406. package/dist/sync/v3/workspaceSyncV3OperationProtocol.d.ts +5 -0
  407. package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.d.ts +7 -0
  408. package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.js +55 -9
  409. package/dist/sync/v3/workspaceSyncV3RepairSnapshotRetentionService.d.ts +17 -0
  410. package/dist/sync/v3/workspaceSyncV3RepairSnapshotRetentionService.js +64 -0
  411. package/dist/sync/v3/workspaceSyncV3TaskCommentAudit.js +9 -2
  412. package/dist/sync/v3/workspaceSyncV3TaskCoverCoverage.d.ts +7 -0
  413. package/dist/sync/v3/workspaceSyncV3TaskCoverCoverage.js +37 -0
  414. package/dist/sync/v3/workspaceSyncV3TaskCoverWireContract.d.ts +6 -0
  415. package/dist/sync/v3/workspaceSyncV3TaskCoverWireContract.js +9 -0
  416. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverCoverage.d.ts +7 -0
  417. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverCoverage.js +33 -0
  418. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverWireContract.d.ts +7 -0
  419. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverWireContract.js +8 -0
  420. package/dist/sync/workspacePullFeed.js +2 -1
  421. package/dist/sync/workspaceRepair.d.ts +8 -2
  422. package/dist/sync/workspaceRepair.js +222 -6
  423. package/dist/sync/workspaceSyncModel.d.ts +21 -0
  424. package/dist/sync/workspaceSyncModel.js +35 -7
  425. package/dist/sync/workspaceSyncState.d.ts +1 -0
  426. package/dist/sync/workspaceSyncV2SnapshotBuilder.d.ts +6 -0
  427. package/dist/sync/workspaceSyncV2SnapshotBuilder.js +5 -0
  428. package/dist/types.d.ts +47 -1
  429. package/dist/types.js +6 -0
  430. package/dist/ui/assets/AiIdentityRosterCard-OcSz1PkK.js +1 -0
  431. package/dist/ui/assets/AiProfilesModule-ByhYW5Xi.js +1 -0
  432. package/dist/ui/assets/AnnotatedAttachmentWorkspace-BTM6nIg_.js +3 -0
  433. package/dist/ui/assets/AnnotatedAttachmentWorkspace-TzYu7pkG.css +1 -0
  434. package/dist/ui/assets/{AssetTraySortControl-Kf1pelSy.js → AssetTraySortControl-DabEG8L4.js} +1 -1
  435. package/dist/ui/assets/{ContextAttachmentManager-B8boOs6Q.js → ContextAttachmentManager-Coa8yVGM.js} +2 -2
  436. package/dist/ui/assets/{DocumentWorkspace-DXH4XUsB.js → DocumentWorkspace-BB0qhdix.js} +1 -1
  437. package/dist/ui/assets/{EntityActivityTimeline-BtSTq0ON.js → EntityActivityTimeline-CZ8x4UJE.js} +1 -1
  438. package/dist/ui/assets/PlanningModule-pRPjR7v5.js +1 -0
  439. package/dist/ui/assets/PlansPage-D86pZSSl.js +1 -0
  440. package/dist/ui/assets/TaskContextUpload-BVIkU9yT.js +1 -0
  441. package/dist/ui/assets/TaskSettings-Cv1mNhv_.js +12 -0
  442. package/dist/ui/assets/TaskforceAgentsModule-b-8R25cJ.css +1 -0
  443. package/dist/ui/assets/TaskforceAgentsModule-gmH-PD2q.js +24 -0
  444. package/dist/ui/assets/{WorkflowManagerModule-DWFspC-o.js → WorkflowManagerModule-DbfnHJ-f.js} +1 -1
  445. package/dist/ui/assets/index-BZ-hdZSk.css +1 -0
  446. package/dist/ui/assets/index-CTsDBaef.js +7 -0
  447. package/dist/ui/assets/{vendor-icons-BkFLXavV.js → vendor-icons-Bsq-mcEn.js} +1 -1
  448. package/dist/ui/branding/logos/letterhead_dark.png +0 -0
  449. package/dist/ui/branding/logos/letterhead_light.png +0 -0
  450. package/dist/ui/branding/logos/signature_dark.png +0 -0
  451. package/dist/ui/branding/logos/signature_light.png +0 -0
  452. package/dist/ui/index.html +3 -3
  453. package/dist/utils/aiProfileDefaultLogo.js +16 -48
  454. package/dist/utils/httpSetCookie.d.ts +1 -0
  455. package/dist/utils/httpSetCookie.js +4 -1
  456. package/dist/utils/localRuntimeUrl.d.ts +1 -0
  457. package/dist/utils/localRuntimeUrl.js +14 -0
  458. package/dist/utils/productLogoRegistry.d.ts +2 -0
  459. package/dist/utils/productLogoRegistry.js +36 -0
  460. package/dist/utils/syncStatusPresentation.d.ts +4 -0
  461. package/dist/utils/syncStatusPresentation.js +17 -0
  462. package/dist/utils/taskActivity.d.ts +3 -2
  463. package/dist/utils/taskActivity.js +19 -2
  464. package/dist/utils/taskEditorReconciliation.d.ts +40 -0
  465. package/dist/utils/taskEditorReconciliation.js +217 -0
  466. package/dist/utils/taskEvents.d.ts +2 -0
  467. package/dist/utils/taskNormalization.d.ts +1 -0
  468. package/dist/utils/taskNormalization.js +39 -0
  469. package/dist/utils/taskSearch.js +2 -2
  470. package/dist/utils/uiNotice.d.ts +4 -0
  471. package/dist/utils/workspaceSyncPresentation.d.ts +1 -1
  472. package/dist/utils/workspaceSyncPresentation.js +23 -17
  473. package/package.json +36 -6
  474. package/dist/ui/assets/AiIdentityRosterCard-MZs7lVED.js +0 -1
  475. package/dist/ui/assets/AiProfilesModule-C3i0LOxe.js +0 -1
  476. package/dist/ui/assets/AnnotatedAttachmentWorkspace-CBRZ8rca.css +0 -1
  477. package/dist/ui/assets/AnnotatedAttachmentWorkspace-DVZk5Tln.js +0 -3
  478. package/dist/ui/assets/PlanningModule-BPVyEa-f.js +0 -1
  479. package/dist/ui/assets/PlansPage-ChqgxALc.js +0 -1
  480. package/dist/ui/assets/TaskContextUpload-CB3ol0sN.js +0 -1
  481. package/dist/ui/assets/TaskSettings-g4ECKNOz.js +0 -12
  482. package/dist/ui/assets/TaskforceAgentsModule-BazdUwxZ.js +0 -21
  483. package/dist/ui/assets/TaskforceAgentsModule-D6IC0S7Q.css +0 -1
  484. package/dist/ui/assets/index-BUplSsv_.js +0 -7
  485. package/dist/ui/assets/index-gz2EXuoK.css +0 -1
@@ -41,6 +41,8 @@ import { resolveRuntimeModeContract } from '../shared/runtimeContract';
41
41
  import { DEFAULT_TYPE_VALUE } from '../shared/taxonomyDefaults.js';
42
42
  import { resolveClientDeploymentConfig } from '../config/clientDeployment';
43
43
  import { resolveTaskforceMcpBaseUrlFromBaseUrl } from '../config/cloudEnvironment';
44
+ import { applyEditorDraftToTask, formatTaskEditorConflictFields, preserveUnresolvedTaskEditorConflicts, reconcileTaskEditorDraft, resolveTaskEditorConflicts, taskToEditorDraft, } from '../utils/taskEditorReconciliation';
45
+ import { isResolvedFeatureAccessMap, } from '../runtime/appGates';
44
46
  import { buildBootstrapTraceId, withBootstrapTraceHeader } from '../utils/bootstrapTrace';
45
47
  import { buildTaskforceCredentialLoginPayload } from '../utils/authLogin';
46
48
  import { createDefaultAssigneeOptions } from '../utils/assignees';
@@ -59,6 +61,7 @@ import { useCurrentTaskRelations } from './tasks/useCurrentTaskRelations';
59
61
  import { useTaskEditorNavigation } from './tasks/useTaskEditorNavigation';
60
62
  import { useTaskFilters } from './tasks/useTaskFilters';
61
63
  import { useTaskFormActions } from './tasks/useTaskFormActions';
64
+ import { useTaskDescriptionImageDraftRecovery } from './tasks/useTaskDescriptionImageDraftRecovery';
62
65
  import { useTaskRelationships } from './tasks/useTaskRelationships';
63
66
  import { useTaskActions } from './tasks/useTaskActions';
64
67
  import { clearPersistedWorkspaceId, logBootstrapDebug, readPersistedWorkspaceId, writePersistedWorkspaceId } from './workspace/workspaceLocalState';
@@ -80,6 +83,19 @@ import { createTaskInvalidationScope, mergeTaskInvalidationScopes, resolveTaskIn
80
83
  import { createCloudWorkstreamHttpMutationClient, fetchWorkstreamHttpMutation, isConclusiveWorkstreamHttpResponse, selectCreatedWorkstreamAfterRefresh, } from './workstreams/workstreamHttpMutation';
81
84
  import { dispatchTaskforceWorkspaceResourcesInvalidated } from '../utils/workspaceResourceEvents';
82
85
  import { dispatchTaskforceAuthSessionChanged } from '../utils/authSessionEvents';
86
+ export function buildRelationshipTasks(tasks, archivedTasks, taskDetails, editingTaskId) {
87
+ const byId = new Map();
88
+ for (const task of archivedTasks)
89
+ byId.set(task.id, task);
90
+ for (const task of tasks)
91
+ byId.set(task.id, task);
92
+ if (editingTaskId && byId.has(editingTaskId)) {
93
+ const currentDetail = taskDetails.find((task) => task.id === editingTaskId);
94
+ if (currentDetail)
95
+ byId.set(editingTaskId, currentDetail);
96
+ }
97
+ return Array.from(byId.values());
98
+ }
83
99
  function upsertEntityById(items, nextItem) {
84
100
  const existingIndex = items.findIndex((item) => item.id === nextItem.id);
85
101
  if (existingIndex === -1) {
@@ -208,6 +224,7 @@ export function useTaskforce({ config = {}, initialTaskId, initialActivityEntryI
208
224
  authSource: '',
209
225
  workspaceMode: '',
210
226
  workspaceSwitchingEnabled: null,
227
+ appGates: undefined,
211
228
  syncV3TaskMetadataActivation: false,
212
229
  syncV3TaskCreateActivation: false,
213
230
  syncV3TaskStatusActivation: false,
@@ -267,6 +284,9 @@ export function useTaskforce({ config = {}, initialTaskId, initialActivityEntryI
267
284
  workspaceSwitchingEnabled: typeof cfg.workspaceSwitchingEnabled === 'boolean'
268
285
  ? Boolean(cfg.workspaceSwitchingEnabled)
269
286
  : (workspaceMode === 'multi-cloud'),
287
+ appGates: isResolvedFeatureAccessMap(cfg.appGates)
288
+ ? cfg.appGates
289
+ : undefined,
270
290
  syncV3TaskMetadataActivation: cfg.syncV3?.taskMetadataActivation === true,
271
291
  syncV3TaskCreateActivation: cfg.syncV3?.taskCreateActivation === true,
272
292
  syncV3TaskStatusActivation: cfg.syncV3?.taskStatusActivation === true,
@@ -375,6 +395,9 @@ export function useTaskforce({ config = {}, initialTaskId, initialActivityEntryI
375
395
  const isCloudScopedPath = path.startsWith('/api/taskforce/auth/')
376
396
  || path.startsWith('/api/taskforce/account/')
377
397
  || path.startsWith('/api/taskforce/billing/')
398
+ || /^\/api\/taskforce\/model-connections(?:[/?]|$)/i.test(path)
399
+ || /^\/api\/taskforce\/agents\/model-catalog(?:\?|$)/i.test(path)
400
+ || /^\/api\/taskforce\/agents\/[^/]+\/connection-binding(?:\?|$)/i.test(path)
378
401
  || path.startsWith('/api/taskforce/sync/')
379
402
  || path.startsWith('/api/taskforce/settings/mcp/');
380
403
  if (!isCloudHost && isCloudScopedPath) {
@@ -619,6 +642,11 @@ export function useTaskforce({ config = {}, initialTaskId, initialActivityEntryI
619
642
  const [manualComplexityEnabled, setManualComplexityEnabled] = useState(false);
620
643
  const [checklistDropdownEnabled, setChecklistDropdownEnabled] = useState(true);
621
644
  const [showTaskCardStatusLabel, setShowTaskCardStatusLabel] = useState(false);
645
+ const [showTaskCardDescription, setShowTaskCardDescription] = useState(true);
646
+ const [showTaskCardAttachments, setShowTaskCardAttachments] = useState(true);
647
+ const [showTaskCardChecklistProgress, setShowTaskCardChecklistProgress] = useState(true);
648
+ const [showTaskCardLatestActivity, setShowTaskCardLatestActivity] = useState(true);
649
+ const [tintTaskCardActivityBackground, setTintTaskCardActivityBackground] = useState(false);
622
650
  const [serverHostRoot, setServerHostRoot] = useState('');
623
651
  const [returnTab, setReturnTab] = useState(null);
624
652
  useTaskforceApiRouting({
@@ -666,6 +694,12 @@ export function useTaskforce({ config = {}, initialTaskId, initialActivityEntryI
666
694
  const deletedHydrationRequestRef = useRef(null);
667
695
  const [loadingTasks, setLoadingTasks] = useState(false);
668
696
  const [editingTaskId, setEditingTaskId] = useState(null);
697
+ const editorBaselineRef = useRef(null);
698
+ const [editorBaseline, setEditorBaseline] = useState(null);
699
+ const [editingTaskRevisionConflict, setEditingTaskRevisionConflict] = useState(null);
700
+ const editingTaskRevisionConflictRef = useRef(null);
701
+ const reconcileOpenTaskWithRemoteRef = useRef(() => null);
702
+ const refreshingTaskRevisionRef = useRef(null);
669
703
  const [pendingOpenTaskId, setPendingOpenTaskId] = useState(null);
670
704
  const setPendingOpenTaskIdFromPersistedState = useCallback((taskId) => {
671
705
  if (String(initialTaskId || '').trim())
@@ -852,7 +886,8 @@ export function useTaskforce({ config = {}, initialTaskId, initialActivityEntryI
852
886
  }, [AUTH_REQUIRED_ERROR, runtimeMode]);
853
887
  // === SECTION: Task Data ===
854
888
  // Delegated to useTaskData — see src/hooks/useTaskData.ts
855
- const { tasksRef, archivedTasksRef, recentlyChangedTaskIds, markRecentlyChangedTasks, fetchTasks: fetchTasksBase, fetchArchive: fetchArchiveBase, refreshTaskCollections: refreshTaskCollectionsBase, refreshTaskCollectionsFromInvalidation: refreshTaskCollectionsFromInvalidationBase, mergeTaskFromServer, getTaskRevisionKey } = useTaskData({
889
+ const pendingTaskMetadataOverlaysRef = useRef(new Map());
890
+ const { tasksRef, archivedTasksRef, taskDetails, staleTaskDetailRevisions, recentlyChangedTaskIds, markRecentlyChangedTasks, fetchTasks: fetchTasksBase, fetchArchive: fetchArchiveBase, loadTaskDetail, cancelTaskDetailLoad, refreshTaskCollections: refreshTaskCollectionsBase, refreshTaskCollectionsFromInvalidation: refreshTaskCollectionsFromInvalidationBase, mergeTaskFromServer, getTaskRevisionKey } = useTaskData({
856
891
  tasks,
857
892
  archivedTasks,
858
893
  setTasks,
@@ -863,7 +898,10 @@ export function useTaskforce({ config = {}, initialTaskId, initialActivityEntryI
863
898
  shouldDeferProtectedApiCalls,
864
899
  shouldBlockProtectedApiCalls,
865
900
  handleUnauthorized,
866
- authRequiredForApi
901
+ authRequiredForApi,
902
+ setError,
903
+ setLoading,
904
+ pendingTaskMetadataOverlaysRef,
867
905
  });
868
906
  useEffect(() => {
869
907
  if (workspaceTransitionEpoch === 0)
@@ -885,6 +923,7 @@ export function useTaskforce({ config = {}, initialTaskId, initialActivityEntryI
885
923
  deletedHydrationRequestRef.current = null;
886
924
  setTasks([]);
887
925
  setArchivedTasks([]);
926
+ pendingTaskMetadataOverlaysRef.current.clear();
888
927
  setInitiatives([]);
889
928
  setWorkstreams([]);
890
929
  setPlanningBootstrapTaskSummaries([]);
@@ -1330,7 +1369,7 @@ export function useTaskforce({ config = {}, initialTaskId, initialActivityEntryI
1330
1369
  const setUserGlobalSyncErrorRef = useRef(() => undefined);
1331
1370
  const checkAuthSessionImplRef = useRef(async () => false);
1332
1371
  const checkAuthSession = useCallback((options) => checkAuthSessionImplRef.current(options), []);
1333
- const { userGlobalSyncStatus, setUserGlobalSyncStatus, userGlobalSyncError, setUserGlobalSyncError, workspaceLastPullAt, workspaceLastPushAt, workspaceLastErrorAt, workspaceLastErrorMessage, workspaceLastSuccessfulSyncAt, workspaceCloudSyncEnabled, workspaceSyncPhase, workspaceSyncSetupIntent, workspaceSyncStatus, workspaceSyncSummary, workspaceSyncRecommendedAction, workspaceSyncBusy, workspaceSyncPendingChanges, workspaceTaskRelationships, localCoordinatorDataVersion, localCoordinatorStatus, switchLocalCoordinatorWorkspace, transferLocalCoordinatorOwnership, workspacePushInFlightRef, workspacePullInFlightRef, workspaceLastPushedSignatureRef, workspacePendingSignatureRef, workspaceLastPushedTaskIdsRef, workspaceDeletedTaskIdsRef, workspaceDeletedTaskWatermarksRef, workspacePullCursorRef, clearWorkspaceRetry, persistWorkspaceSyncPatch, loadWorkspaceSyncState, applyWorkspaceSyncStateSnapshot, syncUserGlobalSettings, buildWorkspaceSyncSignature, pushWorkspaceChangesToCloud, saveWorkspaceCloudSyncSettings, retryUserGlobalSettingsSync, retryWorkspaceCloudSync, resetWorkspaceSyncCursorAndPull, getWorkspaceSyncDiagnostics } = useSyncOrchestrator({
1372
+ const { userGlobalSyncStatus, setUserGlobalSyncStatus, userGlobalSyncError, setUserGlobalSyncError, workspaceLastPullAt, workspaceLastPushAt, workspaceLastErrorAt, workspaceLastErrorMessage, workspaceLastSuccessfulSyncAt, workspaceCloudSyncEnabled, workspaceSyncPhase, workspaceSyncSetupIntent, workspaceSyncStatus, workspaceSyncSummary, workspaceSyncRecommendedAction, workspaceSyncBusy, workspaceSyncPendingChanges, workspaceTaskRelationships, localCoordinatorDataVersion, localCoordinatorStatus, switchLocalCoordinatorWorkspace, transferLocalCoordinatorOwnership, clearLocalCoordinatorCredential, workspacePushInFlightRef, workspacePullInFlightRef, workspaceLastPushedSignatureRef, workspacePendingSignatureRef, workspaceLastPushedTaskIdsRef, workspaceDeletedTaskIdsRef, workspaceDeletedTaskWatermarksRef, workspacePullCursorRef, clearWorkspaceRetry, persistWorkspaceSyncPatch, loadWorkspaceSyncState, applyWorkspaceSyncStateSnapshot, syncUserGlobalSettings, buildWorkspaceSyncSignature, pushWorkspaceChangesToCloud, saveWorkspaceCloudSyncSettings, retryUserGlobalSettingsSync, retryWorkspaceCloudSync, resetWorkspaceSyncCursorAndPull, getWorkspaceSyncDiagnostics } = useSyncOrchestrator({
1334
1373
  currentWorkspaceId,
1335
1374
  cloudAuthConfigured,
1336
1375
  runtimeMode,
@@ -1445,7 +1484,15 @@ export function useTaskforce({ config = {}, initialTaskId, initialActivityEntryI
1445
1484
  configLoaded,
1446
1485
  referenceDataLoaded,
1447
1486
  assigneeOptionsLoaded,
1448
- assigneeOptions
1487
+ assigneeOptions,
1488
+ runtimeMode,
1489
+ workspaceId: currentWorkspaceId,
1490
+ cloudTaskSearchEnabled: runtimeMode === 'cloud'
1491
+ && isAuthenticated
1492
+ && taskScope !== 'deleted'
1493
+ && !shouldDeferProtectedApiCalls
1494
+ && !shouldBlockProtectedApiCalls,
1495
+ cloudTaskSearchScope: taskScope === 'archived' ? 'archive' : 'active',
1449
1496
  });
1450
1497
  setUserGlobalSyncStatusRef.current = setUserGlobalSyncStatus;
1451
1498
  setUserGlobalSyncErrorRef.current = setUserGlobalSyncError;
@@ -1549,7 +1596,7 @@ export function useTaskforce({ config = {}, initialTaskId, initialActivityEntryI
1549
1596
  const referenceDataRequestRef = useRef(null);
1550
1597
  const workspaceListHydratedRef = useRef(false);
1551
1598
  const hasBootstrappedDataRef = useRef(false);
1552
- const { handleSaveSettings, handleSaveTheme, handleSaveGlobalTheme, handleJsonBackupEnabledChange, handleSaveGlobalJsonBackupEnabled, handleSaveGlobalWeekStartsOn, handleSaveLocale, handleManualComplexityEnabledChange, handleChecklistDropdownEnabledChange, handleShowTaskCardStatusLabelChange, handleResetProjectToGlobal } = useSettingsPersistence({
1599
+ const { handleSaveSettings, handleSaveTheme, handleSaveGlobalTheme, handleUseGlobalThemeDefault, handleJsonBackupEnabledChange, handleSaveGlobalJsonBackupEnabled, handleUseGlobalJsonBackupDefault, handleSaveGlobalWeekStartsOn, handleSaveLocale, handleManualComplexityEnabledChange, handleChecklistDropdownEnabledChange, handleShowTaskCardStatusLabelChange, handleShowTaskCardDescriptionChange, handleShowTaskCardAttachmentsChange, handleShowTaskCardChecklistProgressChange, handleShowTaskCardLatestActivityChange, handleTintTaskCardActivityBackgroundChange } = useSettingsPersistence({
1553
1600
  keyShortcut,
1554
1601
  themeUseGlobalDefault,
1555
1602
  runtimeMode,
@@ -1566,7 +1613,12 @@ export function useTaskforce({ config = {}, initialTaskId, initialActivityEntryI
1566
1613
  setLocale,
1567
1614
  setManualComplexityEnabled,
1568
1615
  setChecklistDropdownEnabled,
1569
- setShowTaskCardStatusLabel
1616
+ setShowTaskCardStatusLabel,
1617
+ setShowTaskCardDescription,
1618
+ setShowTaskCardAttachments,
1619
+ setShowTaskCardChecklistProgress,
1620
+ setShowTaskCardLatestActivity,
1621
+ setTintTaskCardActivityBackground
1570
1622
  });
1571
1623
  useEffect(() => {
1572
1624
  if (runtimeMode !== 'cloud')
@@ -1767,6 +1819,36 @@ export function useTaskforce({ config = {}, initialTaskId, initialActivityEntryI
1767
1819
  else {
1768
1820
  setShowTaskCardStatusLabel(false);
1769
1821
  }
1822
+ if (typeof data.showTaskCardDescription === 'boolean') {
1823
+ setShowTaskCardDescription(data.showTaskCardDescription);
1824
+ }
1825
+ else {
1826
+ setShowTaskCardDescription(true);
1827
+ }
1828
+ if (typeof data.showTaskCardAttachments === 'boolean') {
1829
+ setShowTaskCardAttachments(data.showTaskCardAttachments);
1830
+ }
1831
+ else {
1832
+ setShowTaskCardAttachments(true);
1833
+ }
1834
+ if (typeof data.showTaskCardChecklistProgress === 'boolean') {
1835
+ setShowTaskCardChecklistProgress(data.showTaskCardChecklistProgress);
1836
+ }
1837
+ else {
1838
+ setShowTaskCardChecklistProgress(true);
1839
+ }
1840
+ if (typeof data.showTaskCardLatestActivity === 'boolean') {
1841
+ setShowTaskCardLatestActivity(data.showTaskCardLatestActivity);
1842
+ }
1843
+ else {
1844
+ setShowTaskCardLatestActivity(true);
1845
+ }
1846
+ if (typeof data.tintTaskCardActivityBackground === 'boolean') {
1847
+ setTintTaskCardActivityBackground(data.tintTaskCardActivityBackground);
1848
+ }
1849
+ else {
1850
+ setTintTaskCardActivityBackground(false);
1851
+ }
1770
1852
  }, [applyResolvedWorkspaceId, commitCurrentWorkspaceId, configLoaded, currentWorkspaceIdRef]);
1771
1853
  const fetchBuildInfo = useCallback(async () => {
1772
1854
  const startedAt = typeof performance !== 'undefined' ? performance.now() : Date.now();
@@ -2693,6 +2775,7 @@ export function useTaskforce({ config = {}, initialTaskId, initialActivityEntryI
2693
2775
  }, [abortWorkspaceScopedRequests, resetPersistedUiStateLoad, setArchivedTasks, setTasks]);
2694
2776
  const logout = useCallback(async () => {
2695
2777
  try {
2778
+ await clearLocalCoordinatorCredential().catch(() => false);
2696
2779
  if (cloudAuthConfigured) {
2697
2780
  await fetch(resolveCloudAuthUrl('/api/taskforce/auth/logout'), {
2698
2781
  method: 'POST',
@@ -2750,6 +2833,7 @@ export function useTaskforce({ config = {}, initialTaskId, initialActivityEntryI
2750
2833
  }, [
2751
2834
  abortWorkspaceScopedRequests,
2752
2835
  authRequiredForApi,
2836
+ clearLocalCoordinatorCredential,
2753
2837
  clearPersistedWorkspaceId,
2754
2838
  commitCurrentWorkspaceId,
2755
2839
  resolveCloudAuthUrl,
@@ -3301,13 +3385,8 @@ export function useTaskforce({ config = {}, initialTaskId, initialActivityEntryI
3301
3385
  coordinatorDataVersion: localCoordinatorDataVersion,
3302
3386
  });
3303
3387
  const relationshipTasks = useMemo(() => {
3304
- const byId = new Map();
3305
- for (const task of archivedTasks)
3306
- byId.set(task.id, task);
3307
- for (const task of tasks)
3308
- byId.set(task.id, task);
3309
- return Array.from(byId.values());
3310
- }, [tasks, archivedTasks]);
3388
+ return buildRelationshipTasks(tasks, archivedTasks, taskDetails, editingTaskId);
3389
+ }, [tasks, archivedTasks, taskDetails, editingTaskId]);
3311
3390
  const deletedRelationshipTasks = useMemo(() => deletedTasks.map((entry) => ({
3312
3391
  ...entry.taskSnapshot,
3313
3392
  isDeleted: true,
@@ -3463,13 +3542,25 @@ export function useTaskforce({ config = {}, initialTaskId, initialActivityEntryI
3463
3542
  setActiveTab__internal(tab);
3464
3543
  }, [activeTab]);
3465
3544
  const flushAutoSaveRef = useRef(async () => true);
3466
- const { handleNavigation, handleClose, resetForm, resolveTaskIdInput, resolveWorkstreamIdInput, handleEdit, handleOpenTaskById, returnToPreviousTask, clearReturnToParentTask } = useTaskEditorNavigation({
3545
+ const adoptTaskEditorBaseline = useCallback((task) => {
3546
+ const baseline = {
3547
+ taskId: task.id,
3548
+ task,
3549
+ draft: taskToEditorDraft(task),
3550
+ };
3551
+ editorBaselineRef.current = baseline;
3552
+ setEditorBaseline(baseline);
3553
+ editingTaskRevisionConflictRef.current = null;
3554
+ setEditingTaskRevisionConflict(null);
3555
+ }, []);
3556
+ const { handleNavigation, handleClose, resetForm, resolveTaskIdInput, resolveWorkstreamIdInput, handleEdit, applyTaskToEditor, handleOpenTaskById, returnToPreviousTask, clearReturnToParentTask } = useTaskEditorNavigation({
3467
3557
  activeCategories,
3468
3558
  activeTypes,
3469
3559
  activeTab,
3470
3560
  attachments,
3471
3561
  checklistItems,
3472
3562
  comments,
3563
+ cancelTaskDetailLoad,
3473
3564
  description,
3474
3565
  editingTaskId,
3475
3566
  flushPendingAutoSave: () => flushAutoSaveRef.current(),
@@ -3477,7 +3568,9 @@ export function useTaskforce({ config = {}, initialTaskId, initialActivityEntryI
3477
3568
  getPreferredCategoryValue,
3478
3569
  getTitleDraft,
3479
3570
  lastUsedCategory,
3571
+ loadTaskDetail,
3480
3572
  newCommentText,
3573
+ onTaskApplied: adoptTaskEditorBaseline,
3481
3574
  relationshipTasks,
3482
3575
  workstreams,
3483
3576
  showArchive,
@@ -3510,6 +3603,43 @@ export function useTaskforce({ config = {}, initialTaskId, initialActivityEntryI
3510
3603
  taskReturnTrail,
3511
3604
  title,
3512
3605
  });
3606
+ const readCurrentTaskEditorDraft = useCallback(() => {
3607
+ const resolvedWorkstream = workstreamInput.trim()
3608
+ ? resolveWorkstreamIdInput(workstreamInput)
3609
+ : null;
3610
+ return {
3611
+ title: getTitleDraft(),
3612
+ description: getDescriptionDraft(),
3613
+ category: typeof category === 'string' ? category : String(category.label || ''),
3614
+ type: typeof type === 'string' ? type : String(type.label || ''),
3615
+ priority,
3616
+ complexity: Number(complexity) || 3,
3617
+ status,
3618
+ assignee,
3619
+ scheduledDate,
3620
+ dueDate,
3621
+ workstreamId: resolvedWorkstream?.id || workstreamInput.trim(),
3622
+ taxonomies: { ...formTaxonomies },
3623
+ checklistItems: [...checklistItems],
3624
+ attachments: getAttachmentsDraft(),
3625
+ };
3626
+ }, [
3627
+ assignee,
3628
+ category,
3629
+ checklistItems,
3630
+ complexity,
3631
+ dueDate,
3632
+ formTaxonomies,
3633
+ getAttachmentsDraft,
3634
+ getDescriptionDraft,
3635
+ getTitleDraft,
3636
+ priority,
3637
+ resolveWorkstreamIdInput,
3638
+ scheduledDate,
3639
+ status,
3640
+ type,
3641
+ workstreamInput,
3642
+ ]);
3513
3643
  useEffect(() => {
3514
3644
  const normalizedTaskId = String(pendingOpenTaskId || '').trim();
3515
3645
  if (!uiStateReady || !normalizedTaskId)
@@ -3805,10 +3935,45 @@ export function useTaskforce({ config = {}, initialTaskId, initialActivityEntryI
3805
3935
  isAuthenticated,
3806
3936
  dispatchEnabled: workspaceCloudSyncEnabled,
3807
3937
  });
3938
+ const handleTaskRevisionConflict = useCallback(async (taskId, _currentDetailRevision) => {
3939
+ if (taskId !== editingTaskId)
3940
+ return { handled: false };
3941
+ const task = [...tasks, ...archivedTasks].find((candidate) => candidate.id === taskId);
3942
+ if (!task)
3943
+ return { handled: false };
3944
+ const detail = await loadTaskDetail(task, {
3945
+ force: true,
3946
+ shouldCommit: () => editorBaselineRef.current?.taskId === taskId,
3947
+ });
3948
+ if (!detail || editorBaselineRef.current?.taskId !== taskId)
3949
+ return { handled: false };
3950
+ const reconciliation = reconcileOpenTaskWithRemoteRef.current(detail, 'save');
3951
+ return {
3952
+ handled: true,
3953
+ retryDetailRevision: reconciliation?.conflicts.length === 0
3954
+ ? detail.detailRevision
3955
+ : undefined,
3956
+ retryPatch: reconciliation?.conflicts.length === 0
3957
+ ? applyEditorDraftToTask(detail, reconciliation.merged)
3958
+ : undefined,
3959
+ };
3960
+ }, [archivedTasks, editingTaskId, loadTaskDetail, tasks]);
3961
+ const handleTaskMutationAccepted = useCallback((task) => {
3962
+ if (task.id !== editingTaskId)
3963
+ return;
3964
+ if (editingTaskRevisionConflictRef.current?.taskId === task.id) {
3965
+ reconcileOpenTaskWithRemoteRef.current(task, 'refresh');
3966
+ return;
3967
+ }
3968
+ adoptTaskEditorBaseline(task);
3969
+ }, [adoptTaskEditorBaseline, editingTaskId]);
3808
3970
  const { copiedId, handleDelete, handleUpdateTask, handleSetStatus, handleToggleComplete, handleToggleCancel, handleToggleInProgress, handleToggleReview, handleArchiveTask, handleBulkArchive, handleUnarchive, handleRestoreDeletedTask, handleRestoreSelectedDeletedTasks, handlePermanentlyDeleteDeletedTask, handleEmptyDeletedTasks, handleCopyId, queueWorkspaceSyncFromAuthoritativeTaskState, } = useTaskActions({
3809
3971
  tasks,
3810
3972
  archivedTasks,
3811
3973
  editingTaskId,
3974
+ editingTaskDetailRevision: editorBaseline?.taskId === editingTaskId
3975
+ ? editorBaseline.task.detailRevision || null
3976
+ : null,
3812
3977
  setTasks,
3813
3978
  setArchivedTasks,
3814
3979
  setDeletedTasks,
@@ -3840,24 +4005,20 @@ export function useTaskforce({ config = {}, initialTaskId, initialActivityEntryI
3840
4005
  durableTaskDeleteActivationEnabled: taskDeleteActivationEnabled,
3841
4006
  durableTaskHttpRootActivationEnabled: runtimeConfigOverride.syncV3TaskCloudHttpRootActivation,
3842
4007
  workspaceId: currentWorkspaceId,
4008
+ onTaskRevisionConflict: handleTaskRevisionConflict,
4009
+ onTaskMutationAccepted: handleTaskMutationAccepted,
4010
+ pendingTaskMetadataOverlaysRef,
3843
4011
  });
4012
+ const { resolveDraft: resolveDescriptionImageDraft } = useTaskDescriptionImageDraftRecovery(currentWorkspaceId, authUserId);
3844
4013
  const promoteDescriptionImageDraft = useCallback(async () => {
3845
4014
  const draftId = descriptionImageDraftIdRef.current;
3846
- const response = await fetch('/api/taskforce/context-upload/draft/promote', {
3847
- method: 'POST',
3848
- headers: { 'Content-Type': 'application/json' },
3849
- body: JSON.stringify({
3850
- workspaceId: currentWorkspaceId,
3851
- draftUploadId: draftId,
3852
- uploadPurpose: 'task-description-draft',
3853
- }),
3854
- });
3855
- if (!response.ok) {
3856
- throw new Error('Task was created, but its draft upload records could not be finalized.');
3857
- }
3858
4015
  rotateDescriptionImageDraftId();
3859
- }, [currentWorkspaceId, rotateDescriptionImageDraftId]);
3860
- const { autoSaveState, flushAutoSave, scheduleWarningPrompt, handleSubmit, confirmScheduleWarning, cancelScheduleWarning, handleAddComment } = useTaskFormActions({
4016
+ await resolveDescriptionImageDraft({
4017
+ draftUploadId: draftId,
4018
+ resolution: 'promote',
4019
+ });
4020
+ }, [resolveDescriptionImageDraft, rotateDescriptionImageDraftId]);
4021
+ const { autoSaveState, hasUnsavedChanges, flushAutoSave, scheduleWarningPrompt, handleSubmit, confirmScheduleWarning, cancelScheduleWarning, handleAddComment } = useTaskFormActions({
3861
4022
  activeCategories,
3862
4023
  activeTab,
3863
4024
  apiEndpoint,
@@ -3875,6 +4036,8 @@ export function useTaskforce({ config = {}, initialTaskId, initialActivityEntryI
3875
4036
  workspaceId: currentWorkspaceId,
3876
4037
  updateTask: handleUpdateTask,
3877
4038
  editingTaskId,
4039
+ editorBaselineDraft: editorBaseline?.taskId === editingTaskId ? editorBaseline.draft : null,
4040
+ revisionConflict: editingTaskRevisionConflict?.taskId === editingTaskId,
3878
4041
  fetchTasks,
3879
4042
  formTaxonomies,
3880
4043
  getAttachmentsDraft,
@@ -3907,27 +4070,166 @@ export function useTaskforce({ config = {}, initialTaskId, initialActivityEntryI
3907
4070
  textDraftOccupied,
3908
4071
  type
3909
4072
  });
4073
+ const reconcileOpenTaskWithRemote = useCallback((remoteTask, source) => {
4074
+ if (!editingTaskId || remoteTask.id !== editingTaskId)
4075
+ return null;
4076
+ const previousBaseline = editorBaselineRef.current?.taskId === editingTaskId
4077
+ ? editorBaselineRef.current
4078
+ : { taskId: editingTaskId, task: remoteTask, draft: taskToEditorDraft(remoteTask) };
4079
+ const localDraft = readCurrentTaskEditorDraft();
4080
+ const remoteDraft = taskToEditorDraft(remoteTask);
4081
+ const nextReconciliation = reconcileTaskEditorDraft(previousBaseline.draft, localDraft, remoteDraft);
4082
+ const unresolvedConflicts = editingTaskRevisionConflictRef.current?.taskId === editingTaskId
4083
+ ? editingTaskRevisionConflictRef.current.reconciliation.conflicts
4084
+ : [];
4085
+ const reconciliation = {
4086
+ ...nextReconciliation,
4087
+ conflicts: preserveUnresolvedTaskEditorConflicts(unresolvedConflicts, nextReconciliation.conflicts, localDraft, remoteDraft),
4088
+ };
4089
+ const mergedTask = applyEditorDraftToTask(remoteTask, reconciliation.merged);
4090
+ const nextBaseline = { taskId: editingTaskId, task: remoteTask, draft: remoteDraft };
4091
+ editorBaselineRef.current = nextBaseline;
4092
+ setEditorBaseline(nextBaseline);
4093
+ applyTaskToEditor(mergedTask, { preserveReturnTrail: true, adoptAsBaseline: false });
4094
+ setAttachmentsDirty(JSON.stringify(reconciliation.merged.attachments) !== JSON.stringify(remoteDraft.attachments));
4095
+ setError('');
4096
+ if (reconciliation.conflicts.length > 0) {
4097
+ const nextConflict = {
4098
+ taskId: editingTaskId,
4099
+ detailRevision: remoteTask.detailRevision || 'unknown',
4100
+ source,
4101
+ reconciliation,
4102
+ remoteTask,
4103
+ remoteDraft,
4104
+ };
4105
+ editingTaskRevisionConflictRef.current = nextConflict;
4106
+ setEditingTaskRevisionConflict(nextConflict);
4107
+ }
4108
+ else {
4109
+ editingTaskRevisionConflictRef.current = null;
4110
+ setEditingTaskRevisionConflict(null);
4111
+ if (reconciliation.remoteChangedFields.length > 0) {
4112
+ pushNotice('Task updated', 'info', 2200);
4113
+ }
4114
+ }
4115
+ return reconciliation;
4116
+ }, [
4117
+ applyTaskToEditor,
4118
+ editingTaskId,
4119
+ pushNotice,
4120
+ readCurrentTaskEditorDraft,
4121
+ setAttachmentsDirty,
4122
+ setError,
4123
+ ]);
4124
+ reconcileOpenTaskWithRemoteRef.current = reconcileOpenTaskWithRemote;
4125
+ const resolveEditingTaskConflict = useCallback((resolution) => {
4126
+ const conflict = editingTaskRevisionConflict;
4127
+ if (!conflict || conflict.taskId !== editingTaskId)
4128
+ return;
4129
+ const resolvedDraft = resolveTaskEditorConflicts(conflict.reconciliation, conflict.remoteDraft, resolution, readCurrentTaskEditorDraft());
4130
+ const resolvedTask = applyEditorDraftToTask(conflict.remoteTask, resolvedDraft);
4131
+ applyTaskToEditor(resolvedTask, { preserveReturnTrail: true, adoptAsBaseline: false });
4132
+ setAttachmentsDirty(JSON.stringify(resolvedDraft.attachments) !== JSON.stringify(conflict.remoteDraft.attachments));
4133
+ editingTaskRevisionConflictRef.current = null;
4134
+ setEditingTaskRevisionConflict(null);
4135
+ setError('');
4136
+ clearNotice();
4137
+ const statusWasConflicted = conflict.reconciliation.conflicts.some((item) => item.field === 'status');
4138
+ if (resolution === 'local'
4139
+ && statusWasConflicted
4140
+ && resolvedDraft.status !== conflict.remoteDraft.status) {
4141
+ void handleSetStatus(conflict.remoteTask, resolvedDraft.status);
4142
+ }
4143
+ }, [
4144
+ applyTaskToEditor,
4145
+ clearNotice,
4146
+ editingTaskId,
4147
+ editingTaskRevisionConflict,
4148
+ handleSetStatus,
4149
+ readCurrentTaskEditorDraft,
4150
+ setAttachmentsDirty,
4151
+ setError,
4152
+ ]);
4153
+ useEffect(() => {
4154
+ const conflict = editingTaskRevisionConflict;
4155
+ if (!conflict || conflict.taskId !== editingTaskId)
4156
+ return;
4157
+ const fields = formatTaskEditorConflictFields(conflict.reconciliation.conflicts);
4158
+ const fieldSummary = fields.length > 0 ? fields.join(', ') : 'task fields';
4159
+ pushNotice(`${fieldSummary.charAt(0).toUpperCase()}${fieldSummary.slice(1)} also changed elsewhere.`, 'info', undefined, {
4160
+ label: 'Use latest',
4161
+ primary: true,
4162
+ onAction: () => resolveEditingTaskConflict('latest'),
4163
+ secondaryLabel: 'Keep mine',
4164
+ onSecondaryAction: () => resolveEditingTaskConflict('local'),
4165
+ dismissible: false,
4166
+ ownerKey: `task-editor-conflict:${conflict.taskId}:${conflict.detailRevision}`,
4167
+ });
4168
+ }, [editingTaskId, editingTaskRevisionConflict, pushNotice, resolveEditingTaskConflict]);
4169
+ useEffect(() => {
4170
+ if (!editingTaskId) {
4171
+ refreshingTaskRevisionRef.current = null;
4172
+ setEditingTaskRevisionConflict(null);
4173
+ editingTaskRevisionConflictRef.current = null;
4174
+ editorBaselineRef.current = null;
4175
+ setEditorBaseline(null);
4176
+ return;
4177
+ }
4178
+ const staleRevision = staleTaskDetailRevisions[editingTaskId];
4179
+ if (!staleRevision) {
4180
+ refreshingTaskRevisionRef.current = null;
4181
+ return;
4182
+ }
4183
+ const summary = [...tasks, ...archivedTasks].find((task) => task.id === editingTaskId);
4184
+ if (!summary)
4185
+ return;
4186
+ const refreshKey = `${editingTaskId}:${staleRevision}`;
4187
+ if (refreshingTaskRevisionRef.current === refreshKey)
4188
+ return;
4189
+ refreshingTaskRevisionRef.current = refreshKey;
4190
+ void loadTaskDetail(summary, {
4191
+ shouldCommit: () => editorBaselineRef.current?.taskId === editingTaskId,
4192
+ }).then((detail) => {
4193
+ if (editorBaselineRef.current?.taskId !== editingTaskId)
4194
+ return;
4195
+ if (!detail) {
4196
+ setError('The latest task update could not be loaded. Your local draft has been preserved.');
4197
+ return;
4198
+ }
4199
+ reconcileOpenTaskWithRemote(detail, 'refresh');
4200
+ }).finally(() => {
4201
+ if (refreshingTaskRevisionRef.current === refreshKey) {
4202
+ refreshingTaskRevisionRef.current = null;
4203
+ }
4204
+ });
4205
+ }, [
4206
+ archivedTasks,
4207
+ editingTaskId,
4208
+ loadTaskDetail,
4209
+ reconcileOpenTaskWithRemote,
4210
+ setError,
4211
+ staleTaskDetailRevisions,
4212
+ tasks,
4213
+ ]);
3910
4214
  const discardDescriptionImageDraft = useCallback(async () => {
3911
4215
  const draftId = descriptionImageDraftIdRef.current;
3912
4216
  rotateDescriptionImageDraftId();
3913
4217
  try {
3914
4218
  await awaitPendingDescriptionImageUpload();
3915
- const response = await fetch('/api/taskforce/context-upload/draft/discard', {
3916
- method: 'POST',
3917
- headers: { 'Content-Type': 'application/json' },
3918
- body: JSON.stringify({
3919
- workspaceId: currentWorkspaceId,
3920
- draftUploadId: draftId,
3921
- uploadPurpose: 'task-description-draft',
3922
- }),
4219
+ }
4220
+ catch (error) {
4221
+ console.warn('[Taskforce] Description image upload failed while the draft was being discarded.', error);
4222
+ }
4223
+ try {
4224
+ await resolveDescriptionImageDraft({
4225
+ draftUploadId: draftId,
4226
+ resolution: 'discard',
3923
4227
  });
3924
- if (!response.ok)
3925
- throw new Error('Draft upload cleanup was rejected.');
3926
4228
  }
3927
4229
  catch (error) {
3928
4230
  console.warn('[Taskforce] Failed to clean discarded Description image uploads.', error);
3929
4231
  }
3930
- }, [awaitPendingDescriptionImageUpload, currentWorkspaceId, rotateDescriptionImageDraftId]);
4232
+ }, [awaitPendingDescriptionImageUpload, resolveDescriptionImageDraft, rotateDescriptionImageDraftId]);
3931
4233
  useEffect(() => {
3932
4234
  flushAutoSaveRef.current = flushAutoSave;
3933
4235
  }, [flushAutoSave]);
@@ -3974,6 +4276,11 @@ export function useTaskforce({ config = {}, initialTaskId, initialActivityEntryI
3974
4276
  manualComplexityEnabled,
3975
4277
  checklistDropdownEnabled,
3976
4278
  showTaskCardStatusLabel,
4279
+ showTaskCardDescription,
4280
+ showTaskCardAttachments,
4281
+ showTaskCardChecklistProgress,
4282
+ showTaskCardLatestActivity,
4283
+ tintTaskCardActivityBackground,
3977
4284
  pathSaved,
3978
4285
  settingsSection,
3979
4286
  setupState,
@@ -3983,15 +4290,21 @@ export function useTaskforce({ config = {}, initialTaskId, initialActivityEntryI
3983
4290
  setCurrentTheme,
3984
4291
  handleSaveTheme,
3985
4292
  handleSaveGlobalTheme,
4293
+ handleUseGlobalThemeDefault,
3986
4294
  setKeyShortcut,
3987
4295
  handleJsonBackupEnabledChange,
3988
4296
  handleSaveGlobalJsonBackupEnabled,
4297
+ handleUseGlobalJsonBackupDefault,
3989
4298
  handleSaveGlobalWeekStartsOn,
3990
4299
  handleSaveLocale,
3991
4300
  handleManualComplexityEnabledChange,
3992
4301
  handleChecklistDropdownEnabledChange,
3993
4302
  handleShowTaskCardStatusLabelChange,
3994
- handleResetProjectToGlobal,
4303
+ handleShowTaskCardDescriptionChange,
4304
+ handleShowTaskCardAttachmentsChange,
4305
+ handleShowTaskCardChecklistProgressChange,
4306
+ handleShowTaskCardLatestActivityChange,
4307
+ handleTintTaskCardActivityBackgroundChange,
3995
4308
  handleSaveSettings,
3996
4309
  initiativeTemplates,
3997
4310
  fetchInitiativeTemplates,
@@ -4091,6 +4404,7 @@ export function useTaskforce({ config = {}, initialTaskId, initialActivityEntryI
4091
4404
  const effectiveConfig = {
4092
4405
  ...mergedConfig,
4093
4406
  cloudEnvironment: runtimeConfigOverride.cloudEnvironment || mergedConfig.cloudEnvironment || '',
4407
+ appGates: runtimeConfigOverride.appGates || mergedConfig.appGates,
4094
4408
  apiBaseUrl: normalizedApiBaseUrl || mergedConfig.apiBaseUrl,
4095
4409
  cloudAuthBaseUrl: normalizedCloudAuthBaseUrl || mergedConfig.cloudAuthBaseUrl,
4096
4410
  wsBaseUrl: effectiveWsBaseUrl || mergedConfig.wsBaseUrl
@@ -4121,6 +4435,11 @@ export function useTaskforce({ config = {}, initialTaskId, initialActivityEntryI
4121
4435
  manualComplexityEnabled,
4122
4436
  checklistDropdownEnabled,
4123
4437
  showTaskCardStatusLabel,
4438
+ showTaskCardDescription,
4439
+ showTaskCardAttachments,
4440
+ showTaskCardChecklistProgress,
4441
+ showTaskCardLatestActivity,
4442
+ tintTaskCardActivityBackground,
4124
4443
  setManualComplexityEnabled,
4125
4444
  mcpHostRoot,
4126
4445
  setMcpHostRoot,
@@ -14,6 +14,10 @@ export declare function useUiNotice(): {
14
14
  pushNotice: (message: string, tone?: UiNotice["tone"], ttlMs?: number, action?: {
15
15
  label: string;
16
16
  onAction: () => void;
17
+ primary?: boolean;
18
+ secondaryLabel?: string;
19
+ onSecondaryAction?: () => void;
20
+ dismissible?: boolean;
17
21
  ownerKey?: string;
18
22
  }) => void;
19
23
  clearNotice: () => void;
@@ -35,6 +35,10 @@ export function useUiNotice() {
35
35
  ttlMs,
36
36
  actionLabel: action?.label,
37
37
  onAction: action?.onAction,
38
+ actionPrimary: action?.primary,
39
+ secondaryActionLabel: action?.secondaryLabel,
40
+ onSecondaryAction: action?.onSecondaryAction,
41
+ dismissible: action?.dismissible,
38
42
  ownerKey: action?.ownerKey
39
43
  });
40
44
  // Actionable notices stay available until the action or explicit