@taskforcehq/taskforce 0.3.327 → 0.3.329

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 (360) hide show
  1. package/dist/Taskforce.module.css +257 -87
  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/activity/EntityActivityTimeline.js +15 -5
  8. package/dist/components/context/AttachmentPreviewHost.js +1 -1
  9. package/dist/components/context/ContextAttachmentManager.d.ts +3 -0
  10. package/dist/components/context/ContextAttachmentManager.js +116 -20
  11. package/dist/components/features/AnnotatedAttachmentWorkspace.js +24 -8
  12. package/dist/components/features/TaskSettings.d.ts +12 -1
  13. package/dist/components/features/TaskSettings.js +147 -40
  14. package/dist/components/features/agentCapabilities/AgentCapabilitiesPrototype.d.ts +1 -1
  15. package/dist/components/features/planning/PlanningEntitySummary.d.ts +3 -1
  16. package/dist/components/features/planning/PlanningEntitySummary.js +3 -2
  17. package/dist/components/features/planning/PlanningLinkPicker.d.ts +3 -1
  18. package/dist/components/features/planning/PlanningLinkPicker.js +5 -3
  19. package/dist/components/features/planning/PlanningModule.js +28 -14
  20. package/dist/components/features/planning/PlanningTaskOrderList.d.ts +1 -1
  21. package/dist/components/features/planning/PlanningTaskOrderList.js +17 -6
  22. package/dist/components/features/planning/PlanningVisualIdentity.d.ts +14 -0
  23. package/dist/components/features/planning/PlanningVisualIdentity.js +106 -0
  24. package/dist/components/features/planning/planningTaskArrangement.d.ts +1 -0
  25. package/dist/components/features/planning/planningTaskArrangement.js +5 -5
  26. package/dist/components/features/planning/planningWorkspaceModel.d.ts +11 -0
  27. package/dist/components/features/taskforceAgentEditorModel.js +3 -1
  28. package/dist/components/task/TaskActionHeader.d.ts +2 -1
  29. package/dist/components/task/TaskActionHeader.js +2 -2
  30. package/dist/components/task/TaskCard.d.ts +5 -0
  31. package/dist/components/task/TaskCard.js +101 -13
  32. package/dist/components/task/TaskContextUpload.d.ts +3 -0
  33. package/dist/components/task/TaskContextUpload.js +2 -2
  34. package/dist/components/task/TaskForm.d.ts +4 -0
  35. package/dist/components/task/TaskForm.js +32 -7
  36. package/dist/components/task/TaskImageReviews.js +28 -19
  37. package/dist/components/task/TaskKanban.d.ts +6 -1
  38. package/dist/components/task/TaskKanban.js +152 -6
  39. package/dist/components/task/TaskList.d.ts +5 -0
  40. package/dist/components/task/TaskList.js +3 -3
  41. package/dist/components/task/TaskStatusActions.js +11 -2
  42. package/dist/components/task/TaskWorkstreamPicker.js +2 -1
  43. package/dist/components/ui/DocumentTypeIcon.d.ts +7 -0
  44. package/dist/components/ui/DocumentTypeIcon.js +8 -0
  45. package/dist/components/ui/PasswordInput.d.ts +6 -0
  46. package/dist/components/ui/PasswordInput.js +11 -0
  47. package/dist/components/ui/TaxonomyDropdown.d.ts +9 -1
  48. package/dist/components/ui/TaxonomyDropdown.js +30 -3
  49. package/dist/components/ui/TopNoticeLayer.js +1 -1
  50. package/dist/components/views/AppShellHeader.js +32 -11
  51. package/dist/components/views/PlanComparisonPage.js +12 -0
  52. package/dist/components/views/StandaloneLayout.js +68 -39
  53. package/dist/components/views/WidgetView.js +10 -7
  54. package/dist/components/views/panels/PlanningDrawer.d.ts +7 -1
  55. package/dist/components/views/panels/PlanningDrawer.js +51 -54
  56. package/dist/components/views/standalone/modals/AccountSettingsModal.js +26 -17
  57. package/dist/config/envSchema.js +13 -0
  58. package/dist/config/localServiceCloudTarget.d.ts +10 -0
  59. package/dist/config/localServiceCloudTarget.js +76 -0
  60. package/dist/config/localServiceRuntimeContract.d.ts +13 -0
  61. package/dist/config/localServiceRuntimeContract.js +135 -0
  62. package/dist/core/AiProfileService.d.ts +1 -0
  63. package/dist/core/AiProfileService.js +48 -9
  64. package/dist/core/AttachmentLinkService.js +7 -4
  65. package/dist/core/DeletedTaskLifecycleService.d.ts +5 -0
  66. package/dist/core/DeletedTaskLifecycleService.js +55 -3
  67. package/dist/core/McpTokenService.d.ts +4 -0
  68. package/dist/core/McpTokenService.js +52 -0
  69. package/dist/core/TaskAttachmentLinksDurableMutationService.d.ts +8 -2
  70. package/dist/core/TaskAttachmentLinksDurableMutationService.js +51 -18
  71. package/dist/core/Taskforce.d.ts +124 -2
  72. package/dist/core/Taskforce.js +1175 -87
  73. package/dist/core/types.d.ts +8 -1
  74. package/dist/documentReviews/DocumentReviewCommentStore.d.ts +11 -0
  75. package/dist/documentReviews/DocumentReviewCommentStore.js +35 -2
  76. package/dist/documentReviews/service.d.ts +4 -0
  77. package/dist/documentReviews/service.js +141 -46
  78. package/dist/hooks/sync/useDurableLocalOutboxDrain.d.ts +1 -1
  79. package/dist/hooks/sync/useDurableTaskCreateMutation.js +1 -1
  80. package/dist/hooks/sync/useDurableTaskMetadataMutation.d.ts +1 -0
  81. package/dist/hooks/sync/useDurableTaskMetadataMutation.js +1 -0
  82. package/dist/hooks/sync/useDurableTaskStatusMutation.d.ts +1 -0
  83. package/dist/hooks/tasks/taskHttpMutation.js +1 -0
  84. package/dist/hooks/tasks/useCloudTaskSearch.d.ts +12 -0
  85. package/dist/hooks/tasks/useCloudTaskSearch.js +71 -0
  86. package/dist/hooks/tasks/useTaskDescriptionImageDraftRecovery.d.ts +16 -0
  87. package/dist/hooks/tasks/useTaskDescriptionImageDraftRecovery.js +197 -0
  88. package/dist/hooks/tasks/useTaskEditorNavigation.d.ts +16 -3
  89. package/dist/hooks/tasks/useTaskEditorNavigation.js +72 -13
  90. package/dist/hooks/tasks/useTaskFormActions.d.ts +9 -0
  91. package/dist/hooks/tasks/useTaskFormActions.js +96 -17
  92. package/dist/hooks/ui/useSettingsModel.d.ts +24 -2
  93. package/dist/hooks/ui/useSettingsModel.js +13 -2
  94. package/dist/hooks/ui/useSettingsPersistence.d.ts +12 -1
  95. package/dist/hooks/ui/useSettingsPersistence.js +74 -47
  96. package/dist/hooks/useFilterSort.d.ts +7 -3
  97. package/dist/hooks/useFilterSort.js +15 -5
  98. package/dist/hooks/useTaskData.d.ts +10 -1
  99. package/dist/hooks/useTaskData.js +216 -7
  100. package/dist/hooks/useTaskMutations.d.ts +10 -2
  101. package/dist/hooks/useTaskMutations.js +223 -43
  102. package/dist/hooks/useTaskforce.d.ts +94 -57
  103. package/dist/hooks/useTaskforce.js +428 -16
  104. package/dist/hooks/useUiNotice.d.ts +4 -0
  105. package/dist/hooks/useUiNotice.js +4 -0
  106. package/dist/mcp/adminWorkspaceRegistrar.js +3 -3
  107. package/dist/mcp/canonicalAssetHelpers.d.ts +13 -0
  108. package/dist/mcp/canonicalAssetHelpers.js +39 -5
  109. package/dist/mcp/collaborationRegistrar.js +15 -13
  110. package/dist/mcp/documentAssetRegistrar.js +60 -44
  111. package/dist/mcp/documentHelpers.d.ts +1 -0
  112. package/dist/mcp/documentHelpers.js +7 -3
  113. package/dist/mcp/localServiceProxy.js +4 -1
  114. package/dist/mcp/runtime.d.ts +16 -0
  115. package/dist/mcp/runtime.js +735 -210
  116. package/dist/mcp/taskAttachmentCommandAdapter.d.ts +2 -0
  117. package/dist/mcp/taskAttachmentCommandAdapter.js +14 -8
  118. package/dist/mcp/taskPlanningRegistrar.js +78 -67
  119. package/dist/mcp/toolCallCompatibility.js +38 -1
  120. package/dist/mcp/toolCatalog.d.ts +1 -0
  121. package/dist/mcp/toolRegistry.js +2 -2
  122. package/dist/migrations/taskSchemaMigrations.js +47 -0
  123. package/dist/runtime/appGateDefinitions.d.ts +30 -6
  124. package/dist/runtime/appGateDefinitions.js +6 -6
  125. package/dist/runtime/appGates.d.ts +12 -13
  126. package/dist/runtime/appGates.js +29 -13
  127. package/dist/runtime/nodeAppGates.d.ts +8 -0
  128. package/dist/runtime/nodeAppGates.js +27 -0
  129. package/dist/server/appAccess.d.ts +12 -0
  130. package/dist/server/appAccess.js +21 -0
  131. package/dist/server/authorizedWorkspaceAccess.d.ts +12 -0
  132. package/dist/server/authorizedWorkspaceAccess.js +40 -0
  133. package/dist/server/cloudCollectionRead.d.ts +25 -0
  134. package/dist/server/cloudCollectionRead.js +120 -0
  135. package/dist/server/cloudCollectionReadPool.d.ts +52 -0
  136. package/dist/server/cloudCollectionReadPool.js +140 -0
  137. package/dist/server/cloudCollectionReadWorker.d.ts +1 -0
  138. package/dist/server/cloudCollectionReadWorker.js +36 -0
  139. package/dist/server/index.d.ts +6 -11
  140. package/dist/server/index.js +67 -42
  141. package/dist/server/localServiceLease.d.ts +6 -0
  142. package/dist/server/localServiceLease.js +17 -1
  143. package/dist/server/localWorkspaceSyncServerRuntime.js +10 -3
  144. package/dist/server/rateLimit.d.ts +1 -0
  145. package/dist/server/rateLimit.js +4 -0
  146. package/dist/server/realtimeSyncWs.js +36 -12
  147. package/dist/server/routes/admin.js +1 -0
  148. package/dist/server/routes/agentRoles.js +3 -2
  149. package/dist/server/routes/agentSkills.js +3 -2
  150. package/dist/server/routes/agents.js +118 -16
  151. package/dist/server/routes/annotatedAttachments.js +3 -2
  152. package/dist/server/routes/auth.js +3 -1
  153. package/dist/server/routes/documents.d.ts +5 -2
  154. package/dist/server/routes/documents.js +160 -13
  155. package/dist/server/routes/durableTaskHttpRouters.d.ts +11 -2
  156. package/dist/server/routes/durableTaskHttpRouters.js +2 -2
  157. package/dist/server/routes/localService.js +4 -0
  158. package/dist/server/routes/primitives.d.ts +4 -0
  159. package/dist/server/routes/shared.d.ts +24 -0
  160. package/dist/server/routes/shared.js +114 -18
  161. package/dist/server/routes/sync.js +22 -0
  162. package/dist/server/routes/syncAuxRoutes.js +5 -2
  163. package/dist/server/routes/syncPullApplyRoutes.js +23 -4
  164. package/dist/server/routes/syncV3FeedRoutes.js +22 -18
  165. package/dist/server/routes/syncV3LocalCaptureRoutes.js +48 -4
  166. package/dist/server/routes/syncV3LocalFeedApplyRoutes.d.ts +1 -0
  167. package/dist/server/routes/syncV3LocalFeedApplyRoutes.js +26 -0
  168. package/dist/server/routes/syncV3OperationRoutes.js +27 -2
  169. package/dist/server/routes/tasks.js +299 -97
  170. package/dist/server/routes/workspaces.js +43 -1
  171. package/dist/server/routes.js +35 -7
  172. package/dist/server/workspaceDeletionAdmission.d.ts +23 -0
  173. package/dist/server/workspaceDeletionAdmission.js +50 -0
  174. package/dist/service/localServiceCli.js +52 -25
  175. package/dist/service/localServiceClientLifecycle.js +93 -6
  176. package/dist/services/codexAppServerModelGateway.d.ts +112 -0
  177. package/dist/services/codexAppServerModelGateway.js +438 -0
  178. package/dist/services/taskforceAgentMcpBridge.d.ts +7 -1
  179. package/dist/services/taskforceAgentMcpBridge.js +23 -3
  180. package/dist/shared/planningIdentity.d.ts +20 -0
  181. package/dist/shared/planningIdentity.js +79 -0
  182. package/dist/shared/taskforceAgentDefinition.js +7 -1
  183. package/dist/shared/taskforceAgentModels.d.ts +1 -0
  184. package/dist/shared/taskforceAgentModels.js +30 -1
  185. package/dist/storage/postgresAdapter.d.ts +20 -3
  186. package/dist/storage/postgresAdapter.js +110 -14
  187. package/dist/storage/postgresRequestDiagnostics.d.ts +8 -0
  188. package/dist/storage/postgresRequestDiagnostics.js +24 -0
  189. package/dist/storage/postgresWorker.js +13 -4
  190. package/dist/storage/postgresWorkerProtocol.d.ts +29 -0
  191. package/dist/storage/postgresWorkerProtocol.js +30 -0
  192. package/dist/storage/workspaceAssetStore.d.ts +32 -0
  193. package/dist/storage/workspaceAssetStore.js +70 -0
  194. package/dist/sync/cloudSyncApi.d.ts +4 -1
  195. package/dist/sync/cloudSyncApi.js +7 -2
  196. package/dist/sync/contentSyncState.d.ts +1 -1
  197. package/dist/sync/coordinator/localSyncExecutionPermitStore.d.ts +17 -0
  198. package/dist/sync/coordinator/localSyncExecutionPermitStore.js +77 -23
  199. package/dist/sync/coordinator/localWorkspaceSyncRunner.js +6 -2
  200. package/dist/sync/coordinator/workspaceSyncTransportGateway.js +4 -2
  201. package/dist/sync/engine/workspaceSyncEngineBrowserGatewayRemoteServices.js +20 -2
  202. package/dist/sync/engine/workspaceSyncEngineLocalServices.d.ts +4 -0
  203. package/dist/sync/engine/workspaceSyncEngineLocalServices.js +11 -0
  204. package/dist/sync/engine/workspaceSyncEngineRemoteServices.d.ts +16 -0
  205. package/dist/sync/engine/workspaceSyncEngineRemoteServices.js +2 -1
  206. package/dist/sync/engine/workspaceSyncEngineServerRemoteServices.d.ts +1 -1
  207. package/dist/sync/engine/workspaceSyncEngineServerRemoteServices.js +46 -4
  208. package/dist/sync/engine/workspaceSyncEngineServerRunnerOperations.d.ts +3 -1
  209. package/dist/sync/engine/workspaceSyncEngineServerRunnerOperations.js +51 -11
  210. package/dist/sync/engine/workspaceSyncEngineTransfers.d.ts +1 -1
  211. package/dist/sync/engine/workspaceSyncEngineTransfers.js +8 -3
  212. package/dist/sync/engine/workspaceSyncV2ChangeDispatcher.js +2 -0
  213. package/dist/sync/syncApplyHandlers.d.ts +3 -1
  214. package/dist/sync/syncApplyHandlers.js +29 -0
  215. package/dist/sync/syncService.d.ts +2 -0
  216. package/dist/sync/syncService.js +13 -1
  217. package/dist/sync/taskSyncPayload.d.ts +1 -0
  218. package/dist/sync/taskSyncPayload.js +6 -0
  219. package/dist/sync/v3/combinedFeedCapability.js +4 -0
  220. package/dist/sync/v3/durableTaskAttachmentLinksMutationRouter.d.ts +3 -0
  221. package/dist/sync/v3/durableTaskAttachmentLinksMutationRouter.js +31 -3
  222. package/dist/sync/v3/durableTaskChecklistMutationRouter.d.ts +2 -0
  223. package/dist/sync/v3/durableTaskChecklistMutationRouter.js +4 -0
  224. package/dist/sync/v3/durableTaskHttpBulkMutationRouter.d.ts +1 -0
  225. package/dist/sync/v3/durableTaskHttpBulkMutationRouter.js +47 -12
  226. package/dist/sync/v3/durableTaskHttpRootMutationRouter.d.ts +5 -3
  227. package/dist/sync/v3/durableTaskHttpRootMutationRouter.js +27 -2
  228. package/dist/sync/v3/localInitiativeOutboxService.js +4 -2
  229. package/dist/sync/v3/localOutboxDispatcher.js +5 -1
  230. package/dist/sync/v3/localTaskAttachmentLinksOutboxHandler.js +12 -2
  231. package/dist/sync/v3/localTaskAttachmentLinksOutboxService.d.ts +3 -0
  232. package/dist/sync/v3/localTaskAttachmentLinksOutboxService.js +62 -10
  233. package/dist/sync/v3/localTaskCreateOutboxService.js +15 -6
  234. package/dist/sync/v3/localTaskMetadataClient.d.ts +1 -0
  235. package/dist/sync/v3/localTaskMetadataClient.js +1 -0
  236. package/dist/sync/v3/localTaskMetadataOutboxHandler.js +5 -1
  237. package/dist/sync/v3/localTaskMetadataOutboxService.d.ts +2 -0
  238. package/dist/sync/v3/localTaskMetadataOutboxService.js +7 -0
  239. package/dist/sync/v3/localTaskRestoreOutboxService.js +14 -6
  240. package/dist/sync/v3/localTaskStatusClient.d.ts +1 -0
  241. package/dist/sync/v3/localTaskStatusClient.js +6 -1
  242. package/dist/sync/v3/localTaskStatusOutboxService.d.ts +2 -0
  243. package/dist/sync/v3/localTaskStatusOutboxService.js +54 -13
  244. package/dist/sync/v3/localWorkstreamOutboxService.js +4 -2
  245. package/dist/sync/v3/syncDurabilityStore.d.ts +15 -0
  246. package/dist/sync/v3/syncDurabilityStore.js +201 -43
  247. package/dist/sync/v3/taskAttachmentLinksMutationService.d.ts +7 -4
  248. package/dist/sync/v3/taskAttachmentLinksMutationService.js +37 -12
  249. package/dist/sync/v3/taskChecklistMutationService.d.ts +4 -2
  250. package/dist/sync/v3/taskChecklistMutationService.js +4 -0
  251. package/dist/sync/v3/taskCreateMutationService.d.ts +2 -2
  252. package/dist/sync/v3/taskCreateMutationService.js +7 -4
  253. package/dist/sync/v3/taskMetadataCoexistence.js +4 -0
  254. package/dist/sync/v3/taskMetadataMutationService.d.ts +3 -0
  255. package/dist/sync/v3/taskMetadataMutationService.js +4 -0
  256. package/dist/sync/v3/taskRestoreMutationService.d.ts +2 -2
  257. package/dist/sync/v3/taskRestoreMutationService.js +7 -4
  258. package/dist/sync/v3/taskStatusMutationService.d.ts +2 -0
  259. package/dist/sync/v3/taskStatusMutationService.js +4 -0
  260. package/dist/sync/v3/workflowAssignmentSync.d.ts +1 -0
  261. package/dist/sync/v3/workflowAssignmentSync.js +3 -0
  262. package/dist/sync/v3/workspaceSyncV2ProjectionExclusions.d.ts +1 -1
  263. package/dist/sync/v3/workspaceSyncV2ProjectionExclusions.js +14 -12
  264. package/dist/sync/v3/workspaceSyncV3AttachmentApplyObligationStore.d.ts +11 -0
  265. package/dist/sync/v3/workspaceSyncV3AttachmentApplyObligationStore.js +27 -10
  266. package/dist/sync/v3/workspaceSyncV3AttachmentAssetHydration.d.ts +2 -1
  267. package/dist/sync/v3/workspaceSyncV3AttachmentAssetHydration.js +52 -10
  268. package/dist/sync/v3/workspaceSyncV3CloudOperationHandler.js +10 -1
  269. package/dist/sync/v3/workspaceSyncV3CombinedFeedOrchestrator.js +15 -4
  270. package/dist/sync/v3/workspaceSyncV3CombinedLocalApply.js +66 -13
  271. package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.d.ts +11 -0
  272. package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.js +57 -22
  273. package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.d.ts +10 -4
  274. package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.js +124 -51
  275. package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.d.ts +10 -0
  276. package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.js +120 -28
  277. package/dist/sync/v3/workspaceSyncV3CombinedWireContract.d.ts +3 -1
  278. package/dist/sync/v3/workspaceSyncV3CombinedWireContract.js +18 -0
  279. package/dist/sync/v3/workspaceSyncV3CoverageRegistry.js +6 -0
  280. package/dist/sync/v3/workspaceSyncV3FeedProfile.d.ts +1 -1
  281. package/dist/sync/v3/workspaceSyncV3LegacyBoundaryAttestation.d.ts +1 -0
  282. package/dist/sync/v3/workspaceSyncV3LegacyBoundaryAttestation.js +23 -10
  283. package/dist/sync/v3/workspaceSyncV3NestedTaskApply.d.ts +3 -0
  284. package/dist/sync/v3/workspaceSyncV3NestedTaskApply.js +64 -13
  285. package/dist/sync/v3/workspaceSyncV3NestedTaskCodecs.d.ts +9 -0
  286. package/dist/sync/v3/workspaceSyncV3NestedTaskCodecs.js +26 -0
  287. package/dist/sync/v3/workspaceSyncV3NestedTaskProjection.d.ts +15 -5
  288. package/dist/sync/v3/workspaceSyncV3NestedTaskProjection.js +50 -14
  289. package/dist/sync/v3/workspaceSyncV3NestedTaskRepairSnapshot.d.ts +2 -1
  290. package/dist/sync/v3/workspaceSyncV3NestedTaskRepairSnapshot.js +11 -3
  291. package/dist/sync/v3/workspaceSyncV3OperationProtocol.d.ts +3 -0
  292. package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.d.ts +2 -0
  293. package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.js +19 -7
  294. package/dist/sync/v3/workspaceSyncV3RepairSqlBatching.d.ts +2 -0
  295. package/dist/sync/v3/workspaceSyncV3RepairSqlBatching.js +10 -0
  296. package/dist/sync/v3/workspaceSyncV3TaskCommentAudit.js +9 -2
  297. package/dist/sync/v3/workspaceSyncV3TaskCoverCoverage.d.ts +7 -0
  298. package/dist/sync/v3/workspaceSyncV3TaskCoverCoverage.js +37 -0
  299. package/dist/sync/v3/workspaceSyncV3TaskCoverWireContract.d.ts +6 -0
  300. package/dist/sync/v3/workspaceSyncV3TaskCoverWireContract.js +9 -0
  301. package/dist/sync/v3/workspaceSyncV3TaskRootProjection.d.ts +1 -1
  302. package/dist/sync/v3/workspaceSyncV3TaskRootProjection.js +1 -1
  303. package/dist/sync/workspacePullFeed.d.ts +6 -1
  304. package/dist/sync/workspacePullFeed.js +174 -162
  305. package/dist/sync/workspaceRepair.d.ts +3 -0
  306. package/dist/sync/workspaceRepair.js +67 -6
  307. package/dist/sync/workspaceSyncModel.d.ts +11 -0
  308. package/dist/sync/workspaceSyncModel.js +27 -2
  309. package/dist/types.d.ts +55 -1
  310. package/dist/types.js +6 -0
  311. package/dist/ui/assets/{AiIdentityRosterCard-DB1BLO_j.js → AiIdentityRosterCard-BZM4aQnM.js} +1 -1
  312. package/dist/ui/assets/AiProfilesModule-BbAEWtHH.js +1 -0
  313. package/dist/ui/assets/AnnotatedAttachmentWorkspace-B68Wg-RV.js +3 -0
  314. package/dist/ui/assets/AnnotatedAttachmentWorkspace-TzYu7pkG.css +1 -0
  315. package/dist/ui/assets/AssetTraySortControl-C8Rztyal.js +1 -0
  316. package/dist/ui/assets/ContextAttachmentManager-Cj3c7X9y.js +3 -0
  317. package/dist/ui/assets/{DocumentWorkspace-BC7sy5TG.js → DocumentWorkspace-B5uvzems.js} +4 -4
  318. package/dist/ui/assets/EntityActivityTimeline-BVFvCB5R.js +1 -0
  319. package/dist/ui/assets/PlanningModule-B5DWQOGz.js +1 -0
  320. package/dist/ui/assets/PlanningModule-CoIR9hbV.css +1 -0
  321. package/dist/ui/assets/PlansPage-AY4cGWco.js +1 -0
  322. package/dist/ui/assets/TaskContextUpload-DZxTVesW.js +1 -0
  323. package/dist/ui/assets/TaskContextUpload-qmBeUw3u.css +1 -0
  324. package/dist/ui/assets/TaskSettings-BeWAuyZj.js +12 -0
  325. package/dist/ui/assets/{TaskforceAgentsModule-CkAxW19K.js → TaskforceAgentsModule-BifCYtjR.js} +6 -6
  326. package/dist/ui/assets/WorkflowManagerModule-DEr5di_r.js +1 -0
  327. package/dist/ui/assets/index-I5zhdtgt.js +7 -0
  328. package/dist/ui/assets/index-VRFsx3wz.css +1 -0
  329. package/dist/ui/assets/{vendor-icons-B8ZNsH1g.js → vendor-icons-D9Lpw-j4.js} +1 -1
  330. package/dist/ui/index.html +3 -3
  331. package/dist/utils/constants.d.ts +2 -2
  332. package/dist/utils/constants.js +1 -1
  333. package/dist/utils/contextAttachmentUpload.d.ts +2 -0
  334. package/dist/utils/contextAttachmentUpload.js +7 -0
  335. package/dist/utils/contextFiles.d.ts +1 -1
  336. package/dist/utils/contextFiles.js +4 -4
  337. package/dist/utils/taskActivity.d.ts +3 -2
  338. package/dist/utils/taskActivity.js +19 -2
  339. package/dist/utils/taskEditorReconciliation.d.ts +40 -0
  340. package/dist/utils/taskEditorReconciliation.js +217 -0
  341. package/dist/utils/taskNormalization.d.ts +1 -0
  342. package/dist/utils/taskNormalization.js +39 -0
  343. package/dist/utils/taskSearch.js +2 -2
  344. package/dist/utils/uiNotice.d.ts +4 -0
  345. package/package.json +21 -4
  346. package/dist/ui/assets/AiProfilesModule-DPxQeF9N.js +0 -1
  347. package/dist/ui/assets/AnnotatedAttachmentWorkspace-CBRZ8rca.css +0 -1
  348. package/dist/ui/assets/AnnotatedAttachmentWorkspace-DHNYaNg6.js +0 -3
  349. package/dist/ui/assets/AssetTraySortControl-DphbyHVc.js +0 -1
  350. package/dist/ui/assets/ContextAttachmentManager-CMxSzHqc.js +0 -3
  351. package/dist/ui/assets/EntityActivityTimeline-pJ2ZjZ-k.js +0 -1
  352. package/dist/ui/assets/PlanningModule-CeTqXMMz.css +0 -1
  353. package/dist/ui/assets/PlanningModule-t5GbvVR9.js +0 -1
  354. package/dist/ui/assets/PlansPage-BVH_NfgT.js +0 -1
  355. package/dist/ui/assets/TaskContextUpload-Ds4LnDzV.css +0 -1
  356. package/dist/ui/assets/TaskContextUpload-bl4fOOUz.js +0 -1
  357. package/dist/ui/assets/TaskSettings-xVsxSa0g.js +0 -12
  358. package/dist/ui/assets/WorkflowManagerModule-BKqIGVnF.js +0 -1
  359. package/dist/ui/assets/index-BzJlVnNS.css +0 -1
  360. package/dist/ui/assets/index-Cx7vZJHL.js +0 -7
@@ -8,13 +8,13 @@
8
8
  <link rel="icon" type="image/png" sizes="16x16" href="/favicon/favicon-16x16.png" />
9
9
  <link rel="apple-touch-icon" href="/taskforce/favicon/apple-touch-icon.png" />
10
10
  <title>Taskforce</title>
11
- <script type="module" crossorigin src="/taskforce/assets/index-Cx7vZJHL.js"></script>
11
+ <script type="module" crossorigin src="/taskforce/assets/index-I5zhdtgt.js"></script>
12
12
  <link rel="modulepreload" crossorigin href="/taskforce/assets/vendor-react-CKJs5o3c.js">
13
- <link rel="modulepreload" crossorigin href="/taskforce/assets/vendor-icons-B8ZNsH1g.js">
13
+ <link rel="modulepreload" crossorigin href="/taskforce/assets/vendor-icons-D9Lpw-j4.js">
14
14
  <link rel="modulepreload" crossorigin href="/taskforce/assets/vendor-markdown-_lhNCyq-.js">
15
15
  <link rel="modulepreload" crossorigin href="/taskforce/assets/vendor-dnd-CJ-AjP-Y.js">
16
16
  <link rel="modulepreload" crossorigin href="/taskforce/assets/vendor-router-AqJMU8Lz.js">
17
- <link rel="stylesheet" crossorigin href="/taskforce/assets/index-BzJlVnNS.css">
17
+ <link rel="stylesheet" crossorigin href="/taskforce/assets/index-VRFsx3wz.css">
18
18
  </head>
19
19
  <body>
20
20
  <div id="root"></div>
@@ -14,10 +14,10 @@ export declare const STATUS_OPTIONS: {
14
14
  color: string | undefined;
15
15
  }[];
16
16
  export declare function getStatusDefinition(status?: string | null): StatusDefinition;
17
- declare const curatedIcons: readonly ["Folder", "Code", "FileText", "Terminal", "Database", "Cpu", "Globe", "Layout", "Server", "Search", "Settings", "Zap", "Shield", "Star", "Layers", "Bug", "Box", "Book", "MessageSquare", "Image", "Music", "Video", "Map", "Mail", "Camera", "Heart", "Anchor", "Rocket", "Target", "Flag", "Bookmark", "Briefcase", "Puzzle", "SquareUserRound", "Users", "User", "Unplug", "Clock", "Lock", "Pencil", "TrafficCone", "CircleDollarSign", "Activity", "Wrench", "Microscope", "Palette", "Webhook", "FlaskConical", "Bot", "Cloud", "Kanban", "Infinity", "Monitor", "Smartphone", "History", "Brain", "Calendar", "Play", "Pause", "Sparkles", "Check", "Ban", "Circle", "CheckCircle", "Wind", "Github", "Square", "SquareCheck", "CheckSquare", "Package", "AlertCircle", "Lightbulb", "ClipboardCheck", "ScanSearch", "Inbox", "HelpCircle", "Gauge", "FileCode", "ArrowDown", "Minus", "ArrowUp", "AlertTriangle", "CircleQuestionMark", "TriangleAlert"];
17
+ declare const curatedIcons: readonly ["Folder", "Code", "FileText", "Terminal", "Database", "Cpu", "Globe", "Layout", "Server", "Search", "Settings", "Zap", "Shield", "Star", "Layers", "Bug", "Box", "Book", "MessageSquare", "Image", "Music", "Video", "Map", "Mail", "Camera", "Heart", "Anchor", "Rocket", "Target", "Flag", "Bookmark", "Briefcase", "Puzzle", "SquareUserRound", "Users", "User", "Unplug", "Clock", "Lock", "Pencil", "TrafficCone", "CircleDollarSign", "Activity", "Wrench", "Microscope", "Palette", "Webhook", "FlaskConical", "Route", "Compass", "Landmark", "BookOpen", "Bot", "Cloud", "Kanban", "Infinity", "Monitor", "Smartphone", "History", "Brain", "Calendar", "Play", "Pause", "Sparkles", "Check", "Ban", "Circle", "CheckCircle", "Wind", "Github", "Square", "SquareCheck", "CheckSquare", "Package", "AlertCircle", "Lightbulb", "ClipboardCheck", "ScanSearch", "Inbox", "HelpCircle", "Gauge", "FileCode", "ArrowDown", "Minus", "ArrowUp", "AlertTriangle", "CircleQuestionMark", "TriangleAlert"];
18
18
  export type IconName = typeof curatedIcons[number];
19
19
  export declare const IconMap: Record<string, any>;
20
- export declare const AVAILABLE_ICONS: readonly ["Folder", "Code", "FileText", "Terminal", "Database", "Cpu", "Globe", "Layout", "Server", "Search", "Settings", "Zap", "Shield", "Star", "Layers", "Bug", "Box", "Book", "MessageSquare", "Image", "Music", "Video", "Map", "Mail", "Camera", "Heart", "Anchor", "Rocket", "Target", "Flag", "Bookmark", "Briefcase", "Puzzle", "SquareUserRound", "Users", "User", "Unplug", "Clock", "Lock", "Pencil", "TrafficCone", "CircleDollarSign", "Activity", "Wrench", "Microscope", "Palette", "Webhook", "FlaskConical", "Bot", "Cloud", "Kanban", "Infinity", "Monitor", "Smartphone", "History", "Brain", "Calendar", "Play", "Pause", "Sparkles", "Check", "Ban", "Circle", "CheckCircle", "Wind", "Github", "Square", "SquareCheck", "CheckSquare", "Package", "AlertCircle", "Lightbulb", "ClipboardCheck", "ScanSearch", "Inbox", "HelpCircle", "Gauge", "FileCode", "ArrowDown", "Minus", "ArrowUp", "AlertTriangle", "CircleQuestionMark", "TriangleAlert"];
20
+ export declare const AVAILABLE_ICONS: readonly ["Folder", "Code", "FileText", "Terminal", "Database", "Cpu", "Globe", "Layout", "Server", "Search", "Settings", "Zap", "Shield", "Star", "Layers", "Bug", "Box", "Book", "MessageSquare", "Image", "Music", "Video", "Map", "Mail", "Camera", "Heart", "Anchor", "Rocket", "Target", "Flag", "Bookmark", "Briefcase", "Puzzle", "SquareUserRound", "Users", "User", "Unplug", "Clock", "Lock", "Pencil", "TrafficCone", "CircleDollarSign", "Activity", "Wrench", "Microscope", "Palette", "Webhook", "FlaskConical", "Route", "Compass", "Landmark", "BookOpen", "Bot", "Cloud", "Kanban", "Infinity", "Monitor", "Smartphone", "History", "Brain", "Calendar", "Play", "Pause", "Sparkles", "Check", "Ban", "Circle", "CheckCircle", "Wind", "Github", "Square", "SquareCheck", "CheckSquare", "Package", "AlertCircle", "Lightbulb", "ClipboardCheck", "ScanSearch", "Inbox", "HelpCircle", "Gauge", "FileCode", "ArrowDown", "Minus", "ArrowUp", "AlertTriangle", "CircleQuestionMark", "TriangleAlert"];
21
21
  export declare const TypeMeta: Record<string, {
22
22
  icon: string;
23
23
  color: string;
@@ -39,7 +39,7 @@ const curatedIcons = [
39
39
  'Zap', 'Shield', 'Star', 'Layers', 'Bug', 'Box', 'Book', 'MessageSquare', 'Image', 'Music', 'Video', 'Map',
40
40
  'Mail', 'Camera', 'Heart', 'Anchor', 'Rocket', 'Target', 'Flag', 'Bookmark', 'Briefcase',
41
41
  'Puzzle', 'SquareUserRound', 'Users', 'User', 'Unplug', 'Clock', 'Lock', 'Pencil', 'TrafficCone', 'CircleDollarSign',
42
- 'Activity', 'Wrench', 'Microscope', 'Palette', 'Webhook', 'FlaskConical',
42
+ 'Activity', 'Wrench', 'Microscope', 'Palette', 'Webhook', 'FlaskConical', 'Route', 'Compass', 'Landmark', 'BookOpen',
43
43
  'Bot', 'Cloud', 'Kanban', 'Infinity', 'Monitor', 'Smartphone', 'History', 'Brain', 'Calendar',
44
44
  'Play', 'Pause', 'Sparkles', 'Check', 'Ban', 'Circle', 'CheckCircle', 'Wind', 'Github',
45
45
  'Square', 'SquareCheck', 'CheckSquare',
@@ -4,5 +4,7 @@ export interface UploadContextAttachmentOptions {
4
4
  ownerType: ContextAttachmentOwnerType;
5
5
  ownerId?: string | null;
6
6
  workspaceId?: string | null;
7
+ draftUploadId?: string | null;
8
+ uploadPurpose?: 'task-description-draft' | null;
7
9
  }
8
10
  export declare function uploadContextAttachment(file: File, options: UploadContextAttachmentOptions): Promise<AttachmentItem>;
@@ -38,6 +38,10 @@ export async function uploadContextAttachment(file, options) {
38
38
  ownerId: ownerId || null,
39
39
  taskId: options.ownerType === 'task' ? (ownerId || null) : null,
40
40
  };
41
+ const draftUploadId = String(options.draftUploadId || '').trim();
42
+ const draftPayload = draftUploadId && options.uploadPurpose
43
+ ? { draftUploadId, uploadPurpose: options.uploadPurpose }
44
+ : {};
41
45
  const operationId = globalThis.crypto?.randomUUID?.()
42
46
  || `context-upload-${Date.now()}-${Math.random().toString(16).slice(2)}`;
43
47
  const buildHeaders = () => ({
@@ -55,6 +59,7 @@ export async function uploadContextAttachment(file, options) {
55
59
  mimeType: file.type || 'application/octet-stream',
56
60
  size: file.size,
57
61
  ...ownerPayload,
62
+ ...draftPayload,
58
63
  workspaceId: workspaceId || null,
59
64
  }),
60
65
  });
@@ -82,6 +87,7 @@ export async function uploadContextAttachment(file, options) {
82
87
  originalName: file.name,
83
88
  size: file.size,
84
89
  ...ownerPayload,
90
+ ...draftPayload,
85
91
  workspaceId: workspaceId || null,
86
92
  }),
87
93
  });
@@ -113,6 +119,7 @@ export async function uploadContextAttachment(file, options) {
113
119
  file: encoded,
114
120
  originalName: file.name,
115
121
  ...ownerPayload,
122
+ ...draftPayload,
116
123
  workspaceId: workspaceId || null,
117
124
  }),
118
125
  });
@@ -1,6 +1,6 @@
1
1
  export interface OpenMarkdownEditorDetail {
2
2
  path: string;
3
- fsPath: string;
3
+ fsPath?: string;
4
4
  assetId?: string;
5
5
  taskId?: string | null;
6
6
  }
@@ -68,15 +68,15 @@ export function isMarkdownContextFile(target, fsPath) {
68
68
  export function dispatchOpenMarkdownDocument(target, fsPath) {
69
69
  const sourcePath = resolveSourcePath(target);
70
70
  const resolvedFsPath = resolveContextFsPath(target, fsPath);
71
- if (!resolvedFsPath)
71
+ const assetId = resolveContextAssetId(target);
72
+ if (!resolvedFsPath && !assetId)
72
73
  return false;
73
- if (!isMarkdownContextFile(target, resolvedFsPath))
74
+ if (!isMarkdownContextFile(target, resolvedFsPath || undefined))
74
75
  return false;
75
- const assetId = resolveContextAssetId(target);
76
76
  const event = new CustomEvent('taskforce:open-markdown-document', {
77
77
  detail: {
78
78
  path: sourcePath,
79
- fsPath: resolvedFsPath,
79
+ ...(resolvedFsPath ? { fsPath: resolvedFsPath } : {}),
80
80
  ...(assetId ? { assetId } : {}),
81
81
  ...((typeof target !== 'string' && target.taskId) ? { taskId: target.taskId } : {})
82
82
  },
@@ -1,4 +1,4 @@
1
- import type { EntityActivityItem, EntityEvent, TaskActivityItem, TaskEvent, TaskItem } from '../types';
1
+ import type { EntityActivityItem, EntityEvent, TaskActivityItem, TaskActivitySummaryItem, TaskEvent, TaskItem } from '../types';
2
2
  export type TaskEventValueFormatter = (field: string, value: unknown) => string | undefined;
3
3
  type AttachmentChange = {
4
4
  from?: unknown;
@@ -11,6 +11,7 @@ type AttachmentChange = {
11
11
  };
12
12
  export declare function summarizeTaskChange(field: string, change: AttachmentChange | undefined, formatter?: TaskEventValueFormatter): string;
13
13
  export declare function summarizeTaskEvent(event: TaskEvent, formatter?: TaskEventValueFormatter): string;
14
+ export declare function summarizeTaskEvent(event: Pick<TaskEvent, 'action' | 'details'>, formatter?: TaskEventValueFormatter): string;
14
15
  export declare function summarizeEntityEvent(event: EntityEvent, formatter?: TaskEventValueFormatter): string;
15
16
  export declare function getTaskEventPrimaryChangeField(event: TaskEvent): string | null;
16
17
  export declare function getEntityEventPrimaryChangeField(event: EntityEvent): string | null;
@@ -20,5 +21,5 @@ export declare function getEntityActivityItems(task: {
20
21
  }): EntityActivityItem[];
21
22
  export declare function getTaskActivityItems(task: Pick<TaskItem, 'activity' | 'comments'>): TaskActivityItem[];
22
23
  export declare function getLatestTaskActivity(task: Pick<TaskItem, 'activity' | 'comments'>): TaskActivityItem | null;
23
- export declare function summarizeTaskActivity(item: TaskActivityItem | null, formatter?: TaskEventValueFormatter): string;
24
+ export declare function summarizeTaskActivity(item: TaskActivityItem | TaskActivitySummaryItem | null, formatter?: TaskEventValueFormatter): string;
24
25
  export {};
@@ -5,8 +5,6 @@ function getActivityFieldLabel(field) {
5
5
  return 'Title';
6
6
  if (field === 'description')
7
7
  return 'Description';
8
- if (field === 'assignee')
9
- return 'Assigned to';
10
8
  if (field === 'ownerId')
11
9
  return 'Owner';
12
10
  if (field === 'status')
@@ -21,6 +19,14 @@ function getActivityFieldLabel(field) {
21
19
  return 'Initiative';
22
20
  return field;
23
21
  }
22
+ function isUnassignedActivityValue(value) {
23
+ const normalized = String(value ?? '').trim().toLowerCase();
24
+ return !normalized
25
+ || normalized === 'none'
26
+ || normalized === 'null'
27
+ || normalized === 'unassigned'
28
+ || normalized === 'user';
29
+ }
24
30
  function formatStatusValue(value) {
25
31
  if (value === 'task')
26
32
  return 'Task';
@@ -277,6 +283,17 @@ export function summarizeTaskChange(field, change, formatter) {
277
283
  if (field === 'attachments') {
278
284
  return summarizeAttachmentChange(change);
279
285
  }
286
+ if (field === 'assignee') {
287
+ const previousAssignee = formatValue(change?.from, field, formatter);
288
+ const nextAssignee = formatValue(change?.to, field, formatter);
289
+ if (isUnassignedActivityValue(change?.from) && !isUnassignedActivityValue(change?.to)) {
290
+ return `Assigned to ${nextAssignee}`;
291
+ }
292
+ if (!isUnassignedActivityValue(change?.from) && isUnassignedActivityValue(change?.to)) {
293
+ return `Unassigned from ${previousAssignee}`;
294
+ }
295
+ return `Reassigned: ${previousAssignee} → ${nextAssignee}`;
296
+ }
280
297
  const label = getActivityFieldLabel(field);
281
298
  if (field === 'title') {
282
299
  return `${label}: updated`;
@@ -0,0 +1,40 @@
1
+ import type { AttachmentItem, ChecklistItem, TaskAssignee, TaskItem, TaskStatus } from '../types';
2
+ export interface TaskEditorDraft {
3
+ title: string;
4
+ description: string;
5
+ category: string;
6
+ type: string;
7
+ priority: number | string;
8
+ complexity: number;
9
+ status: TaskStatus;
10
+ assignee: TaskAssignee;
11
+ scheduledDate: string;
12
+ dueDate: string;
13
+ workstreamId: string;
14
+ taxonomies: Record<string, string | number | string[] | number[]>;
15
+ checklistItems: ChecklistItem[];
16
+ attachments: Array<string | AttachmentItem>;
17
+ }
18
+ export type TaskEditorScalarField = Exclude<keyof TaskEditorDraft, 'taxonomies' | 'checklistItems' | 'attachments'>;
19
+ export type TaskEditorConflict = {
20
+ field: TaskEditorScalarField;
21
+ } | {
22
+ field: 'taxonomies';
23
+ key: string;
24
+ } | {
25
+ field: 'checklistItems' | 'attachments';
26
+ key: string;
27
+ };
28
+ export interface TaskEditorReconciliation {
29
+ merged: TaskEditorDraft;
30
+ conflicts: TaskEditorConflict[];
31
+ remoteChangedFields: string[];
32
+ }
33
+ export declare function taskToEditorDraft(task: TaskItem): TaskEditorDraft;
34
+ export declare function applyEditorDraftToTask(task: TaskItem, draft: TaskEditorDraft): TaskItem;
35
+ export declare function reconcileTaskEditorDraft(base: TaskEditorDraft, local: TaskEditorDraft, remote: TaskEditorDraft): TaskEditorReconciliation;
36
+ export declare function resolveTaskEditorConflicts(reconciliation: TaskEditorReconciliation, remote: TaskEditorDraft, resolution: 'latest' | 'local', current?: TaskEditorDraft): TaskEditorDraft;
37
+ export declare function isTaskEditorConflictAligned(conflict: TaskEditorConflict, local: TaskEditorDraft, remote: TaskEditorDraft): boolean;
38
+ export declare function taskEditorConflictKey(conflict: TaskEditorConflict): string;
39
+ export declare function preserveUnresolvedTaskEditorConflicts(existing: TaskEditorConflict[], next: TaskEditorConflict[], local: TaskEditorDraft, remote: TaskEditorDraft): TaskEditorConflict[];
40
+ export declare function formatTaskEditorConflictFields(conflicts: TaskEditorConflict[]): string[];
@@ -0,0 +1,217 @@
1
+ import { canonicalWorkspaceSyncJson } from '../sync/v3/canonicalWorkspaceSyncJson.js';
2
+ const SCALAR_FIELDS = [
3
+ 'title',
4
+ 'description',
5
+ 'category',
6
+ 'type',
7
+ 'priority',
8
+ 'complexity',
9
+ 'status',
10
+ 'assignee',
11
+ 'scheduledDate',
12
+ 'dueDate',
13
+ 'workstreamId',
14
+ ];
15
+ export function taskToEditorDraft(task) {
16
+ return {
17
+ title: task.title || '',
18
+ description: task.description || '',
19
+ category: task.category || '',
20
+ type: task.type || '',
21
+ priority: task.priority,
22
+ complexity: Number(task.complexity) || 3,
23
+ status: task.status || 'task',
24
+ assignee: task.assignee || 'unassigned',
25
+ scheduledDate: task.scheduledDate || '',
26
+ dueDate: task.dueDate || '',
27
+ workstreamId: task.workstreamId || '',
28
+ taxonomies: { ...(task.taxonomies || {}) },
29
+ checklistItems: [...(task.checklistItems || [])],
30
+ attachments: [...(task.attachments || [])],
31
+ };
32
+ }
33
+ export function applyEditorDraftToTask(task, draft) {
34
+ return {
35
+ ...task,
36
+ title: draft.title,
37
+ description: draft.description || null,
38
+ category: draft.category,
39
+ type: draft.type,
40
+ priority: draft.priority,
41
+ complexity: draft.complexity,
42
+ status: draft.status,
43
+ assignee: draft.assignee,
44
+ scheduledDate: draft.scheduledDate || null,
45
+ dueDate: draft.dueDate || null,
46
+ workstreamId: draft.workstreamId || null,
47
+ taxonomies: draft.taxonomies,
48
+ checklistItems: draft.checklistItems,
49
+ attachments: draft.attachments,
50
+ };
51
+ }
52
+ function equal(left, right) {
53
+ return canonicalWorkspaceSyncJson(left ?? null) === canonicalWorkspaceSyncJson(right ?? null);
54
+ }
55
+ function mergeValue(base, local, remote) {
56
+ const localChanged = !equal(local, base);
57
+ const remoteChanged = !equal(remote, base);
58
+ if (!localChanged)
59
+ return { value: remote, conflict: false, remoteChanged };
60
+ if (!remoteChanged || equal(local, remote))
61
+ return { value: local, conflict: false, remoteChanged };
62
+ return { value: local, conflict: true, remoteChanged };
63
+ }
64
+ function attachmentKey(attachment) {
65
+ if (typeof attachment === 'string')
66
+ return `path:${attachment}`;
67
+ if (attachment.assetId)
68
+ return `asset:${attachment.assetId}`;
69
+ if (attachment.referenceLabel)
70
+ return `reference:${attachment.referenceLabel}`;
71
+ if (attachment.referenceNumber != null)
72
+ return `number:${attachment.referenceNumber}`;
73
+ return `path:${attachment.path || attachment.fsPath || canonicalWorkspaceSyncJson(attachment)}`;
74
+ }
75
+ function mergeKeyedCollection(baseItems, localItems, remoteItems, getKey) {
76
+ const base = new Map(baseItems.map((item) => [getKey(item), item]));
77
+ const local = new Map(localItems.map((item) => [getKey(item), item]));
78
+ const remote = new Map(remoteItems.map((item) => [getKey(item), item]));
79
+ const keys = new Set([...base.keys(), ...remote.keys(), ...local.keys()]);
80
+ const merged = new Map();
81
+ const conflictKeys = [];
82
+ for (const key of keys) {
83
+ const baseItem = base.get(key);
84
+ const localItem = local.get(key);
85
+ const remoteItem = remote.get(key);
86
+ const result = mergeValue(baseItem, localItem, remoteItem);
87
+ if (result.value !== undefined)
88
+ merged.set(key, result.value);
89
+ if (result.conflict)
90
+ conflictKeys.push(key);
91
+ }
92
+ const orderedKeys = [
93
+ ...remoteItems.map(getKey),
94
+ ...localItems.map(getKey).filter((key) => !remote.has(key)),
95
+ ].filter((key, index, all) => all.indexOf(key) === index && merged.has(key));
96
+ return {
97
+ items: orderedKeys.map((key) => merged.get(key)),
98
+ conflictKeys,
99
+ remoteChanged: !equal(baseItems, remoteItems),
100
+ };
101
+ }
102
+ export function reconcileTaskEditorDraft(base, local, remote) {
103
+ const merged = { ...remote };
104
+ const conflicts = [];
105
+ const remoteChangedFields = new Set();
106
+ for (const field of SCALAR_FIELDS) {
107
+ const result = mergeValue(base[field], local[field], remote[field]);
108
+ merged[field] = result.value;
109
+ if (result.conflict)
110
+ conflicts.push({ field });
111
+ if (result.remoteChanged)
112
+ remoteChangedFields.add(field);
113
+ }
114
+ const taxonomyKeys = new Set([
115
+ ...Object.keys(base.taxonomies),
116
+ ...Object.keys(local.taxonomies),
117
+ ...Object.keys(remote.taxonomies),
118
+ ]);
119
+ const mergedTaxonomies = {};
120
+ for (const key of taxonomyKeys) {
121
+ const result = mergeValue(base.taxonomies[key], local.taxonomies[key], remote.taxonomies[key]);
122
+ if (result.value !== undefined)
123
+ mergedTaxonomies[key] = result.value;
124
+ if (result.conflict)
125
+ conflicts.push({ field: 'taxonomies', key });
126
+ if (result.remoteChanged)
127
+ remoteChangedFields.add(`taxonomies.${key}`);
128
+ }
129
+ merged.taxonomies = mergedTaxonomies;
130
+ const checklist = mergeKeyedCollection(base.checklistItems, local.checklistItems, remote.checklistItems, (item) => item.id);
131
+ merged.checklistItems = checklist.items;
132
+ checklist.conflictKeys.forEach((key) => conflicts.push({ field: 'checklistItems', key }));
133
+ if (checklist.remoteChanged)
134
+ remoteChangedFields.add('checklistItems');
135
+ const attachments = mergeKeyedCollection(base.attachments, local.attachments, remote.attachments, attachmentKey);
136
+ merged.attachments = attachments.items;
137
+ attachments.conflictKeys.forEach((key) => conflicts.push({ field: 'attachments', key }));
138
+ if (attachments.remoteChanged)
139
+ remoteChangedFields.add('attachments');
140
+ return { merged, conflicts, remoteChangedFields: [...remoteChangedFields] };
141
+ }
142
+ export function resolveTaskEditorConflicts(reconciliation, remote, resolution, current = reconciliation.merged) {
143
+ if (resolution === 'local')
144
+ return current;
145
+ const resolved = {
146
+ ...current,
147
+ taxonomies: { ...current.taxonomies },
148
+ checklistItems: [...current.checklistItems],
149
+ attachments: [...current.attachments],
150
+ };
151
+ for (const conflict of reconciliation.conflicts) {
152
+ if (conflict.field === 'taxonomies') {
153
+ const value = remote.taxonomies[conflict.key];
154
+ if (value === undefined)
155
+ delete resolved.taxonomies[conflict.key];
156
+ else
157
+ resolved.taxonomies[conflict.key] = value;
158
+ continue;
159
+ }
160
+ if (conflict.field === 'checklistItems' || conflict.field === 'attachments') {
161
+ const getKey = conflict.field === 'checklistItems'
162
+ ? (item) => item.id
163
+ : (item) => attachmentKey(item);
164
+ const current = resolved[conflict.field];
165
+ const latest = remote[conflict.field];
166
+ const latestItem = latest.find((item) => getKey(item) === conflict.key);
167
+ const withoutConflict = current.filter((item) => getKey(item) !== conflict.key);
168
+ resolved[conflict.field] = latestItem
169
+ ? [...withoutConflict, latestItem]
170
+ : withoutConflict;
171
+ continue;
172
+ }
173
+ resolved[conflict.field] = remote[conflict.field];
174
+ }
175
+ return resolved;
176
+ }
177
+ export function isTaskEditorConflictAligned(conflict, local, remote) {
178
+ if (conflict.field === 'taxonomies') {
179
+ return equal(local.taxonomies[conflict.key], remote.taxonomies[conflict.key]);
180
+ }
181
+ if (conflict.field === 'checklistItems') {
182
+ return equal(local.checklistItems.find((item) => item.id === conflict.key), remote.checklistItems.find((item) => item.id === conflict.key));
183
+ }
184
+ if (conflict.field === 'attachments') {
185
+ return equal(local.attachments.find((item) => attachmentKey(item) === conflict.key), remote.attachments.find((item) => attachmentKey(item) === conflict.key));
186
+ }
187
+ return equal(local[conflict.field], remote[conflict.field]);
188
+ }
189
+ export function taskEditorConflictKey(conflict) {
190
+ return 'key' in conflict ? `${conflict.field}:${conflict.key}` : conflict.field;
191
+ }
192
+ export function preserveUnresolvedTaskEditorConflicts(existing, next, local, remote) {
193
+ const conflictsByKey = new Map([
194
+ ...existing.filter((conflict) => !isTaskEditorConflictAligned(conflict, local, remote)),
195
+ ...next,
196
+ ].map((conflict) => [taskEditorConflictKey(conflict), conflict]));
197
+ return [...conflictsByKey.values()];
198
+ }
199
+ export function formatTaskEditorConflictFields(conflicts) {
200
+ const labels = {
201
+ title: 'title',
202
+ description: 'description',
203
+ category: 'category',
204
+ type: 'type',
205
+ priority: 'priority',
206
+ complexity: 'complexity',
207
+ status: 'status',
208
+ assignee: 'assignee',
209
+ scheduledDate: 'scheduled date',
210
+ dueDate: 'due date',
211
+ workstreamId: 'workstream',
212
+ taxonomies: 'taxonomy',
213
+ checklistItems: 'checklist',
214
+ attachments: 'attachments',
215
+ };
216
+ return [...new Set(conflicts.map((conflict) => labels[conflict.field] || String(conflict.field)))];
217
+ }
@@ -13,6 +13,7 @@ export declare function normalizePriorityDefinitions(priorities: PriorityDefinit
13
13
  changed: boolean;
14
14
  };
15
15
  export declare function normalizeTaskFromApi(task: any): TaskItem;
16
+ export declare function toTaskCollectionSummary(task: TaskItem): TaskItem;
16
17
  export declare function getTaskContentRevision(task: TaskItem): string;
17
18
  export declare function reconcileTaskCollection(previous: TaskItem[], incoming: TaskItem[]): TaskItem[];
18
19
  export declare function mergeNormalizedTaskIntoCollections(task: unknown, tasks: TaskItem[], archivedTasks: TaskItem[]): {
@@ -1,5 +1,6 @@
1
1
  import { cloneDefaultPriorityDefinitions } from '../shared/taxonomyDefaults.js';
2
2
  import { formatLocalTaskReference, formatTaskReference } from './taskReferences.js';
3
+ import { getLatestTaskActivity } from './taskActivity.js';
3
4
  export const DEFAULT_PRIORITY_DEFINITIONS = cloneDefaultPriorityDefinitions();
4
5
  const PRIORITY_VALUE_BY_LABEL = {
5
6
  low: 1,
@@ -96,6 +97,44 @@ export function normalizeTaskFromApi(task) {
96
97
  status: normalizeTaskStatus(task.status)
97
98
  };
98
99
  }
100
+ export function toTaskCollectionSummary(task) {
101
+ const { description: _description, comments, activity: _activity, taskEvents: _taskEvents, attachments, checklistItems, createdByActor: _createdByActor, assigneeActor: _assigneeActor, ...summary } = task;
102
+ const latestRevision = (values) => values.reduce((latest, value) => String(value || '') > latest ? String(value || '') : latest, '');
103
+ const commentCount = task.commentCount ?? comments?.length ?? 0;
104
+ const checklistCount = task.checklistCount ?? checklistItems?.length ?? 0;
105
+ const completedChecklistCount = task.completedChecklistCount
106
+ ?? checklistItems?.filter((item) => item.isCompleted).length
107
+ ?? 0;
108
+ const attachmentCount = task.attachmentCount ?? attachments?.length ?? 0;
109
+ const relationshipCount = task.relationshipCount ?? 0;
110
+ const latestActivity = task.latestActivity ?? getLatestTaskActivity(task);
111
+ return {
112
+ ...summary,
113
+ cardCoverAttachment: task.cardCoverAttachment ?? (task.cardCoverAssetId
114
+ ? attachments?.find((attachment) => (typeof attachment !== 'string' && attachment.assetId === task.cardCoverAssetId)) || null
115
+ : null),
116
+ isSummary: true,
117
+ commentCount,
118
+ checklistCount,
119
+ completedChecklistCount,
120
+ attachmentCount,
121
+ relationshipCount,
122
+ latestActivity,
123
+ detailRevision: task.detailRevision || JSON.stringify([
124
+ String(task.updatedAt || task.createdAt || ''),
125
+ commentCount,
126
+ latestRevision(comments?.map((comment) => comment.timestamp) || []),
127
+ checklistCount,
128
+ completedChecklistCount,
129
+ latestRevision(checklistItems?.map((item) => item.updatedAt || item.createdAt) || []),
130
+ attachmentCount,
131
+ latestRevision(attachments?.map((attachment) => typeof attachment === 'string' ? '' : attachment.timestamp) || []),
132
+ relationshipCount,
133
+ latestActivity?.timestamp || '',
134
+ latestActivity?.id || '',
135
+ ]),
136
+ };
137
+ }
99
138
  export function getTaskContentRevision(task) {
100
139
  // Use the complete normalized snapshot: some task changes can arrive without a
101
140
  // distinct updatedAt value, so a timestamp-only key could retain stale UI data.
@@ -1,5 +1,5 @@
1
- import { STATUS_OPTIONS } from './constants';
2
- import { getTaskReferenceLabel } from './taskReferences';
1
+ import { STATUS_OPTIONS } from './constants.js';
2
+ import { getTaskReferenceLabel } from './taskReferences.js';
3
3
  const DASH_LIKE_PATTERN = /[\u2010-\u2015\u2212]/g;
4
4
  export function normalizeSearchText(value) {
5
5
  return String(value ?? '')
@@ -5,6 +5,10 @@ export interface UiNotice {
5
5
  ttlMs?: number;
6
6
  actionLabel?: string;
7
7
  onAction?: () => void;
8
+ actionPrimary?: boolean;
9
+ secondaryActionLabel?: string;
10
+ onSecondaryAction?: () => void;
11
+ dismissible?: boolean;
8
12
  ownerKey?: string;
9
13
  }
10
14
  export declare function resolveUiNoticeTtl(tone: UiNoticeTone, ttlMs?: number): number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@taskforcehq/taskforce",
3
- "version": "0.3.327",
3
+ "version": "0.3.329",
4
4
  "description": "Shared task and planning workspace for humans collaborating with AI (public beta)",
5
5
  "author": "Taskforce HQ <hello@taskforcehq.ai> (https://taskforcehq.ai)",
6
6
  "license": "SEE LICENSE IN LICENSE.md",
@@ -67,6 +67,7 @@
67
67
  "mcp": "node dist/cli.js mcp",
68
68
  "gen:mcp-contract": "node --import tsx scripts/generate-mcp-contract.ts",
69
69
  "check:mcp-contract": "node --import tsx scripts/generate-mcp-contract.ts --check",
70
+ "measure:agent-prefix-cost": "node scripts/measure-agent-prefix-cost.mjs",
70
71
  "cleanup:legacy-ai-avatars": "node --import tsx scripts/cleanup-legacy-ai-profile-avatar-assets.ts",
71
72
  "db:export:postgres": "node scripts/export-sqlite-to-postgres.mjs",
72
73
  "check:localization-strings": "node scripts/check-localization-strings.mjs",
@@ -87,7 +88,7 @@
87
88
  "test:sync:recovery:coordinator": "vitest run src/test/syncRecoveryGate.test.ts src/test/syncRecoveryCoordinatorOwnership.test.ts src/test/syncRecoveryExecutionPermitExpiry.test.ts",
88
89
  "test:sqlite:multiprocess": "TASKFORCE_SQLITE_MULTIPROCESS_GATE=true vitest run src/storage/sqliteWalMultiprocess.integration.test.ts",
89
90
  "test:mcp:shared-local:gate-b": "npm run build && TASKFORCE_SHARED_LOCAL_MCP_GATE_B=true vitest run src/mcp/proxyServerBoundary.test.ts src/mcp/sharedLocalService.acceptance.test.ts",
90
- "test:mcp:shared-local:gate-c": "npm run build && TASKFORCE_SHARED_LOCAL_OPEN_GATE_C=true vitest run src/service/localServiceClientLifecycle.test.ts src/server/localServiceLease.test.ts src/service/localServiceOpen.test.ts src/service/localServiceOpen.acceptance.test.ts",
91
+ "test:mcp:shared-local:gate-c": "npm run build && TASKFORCE_SHARED_LOCAL_OPEN_GATE_C=true vitest run --exclude '.worktrees/**' src/service/localServiceClientLifecycle.test.ts src/server/localServiceLease.test.ts src/service/localServiceOpen.test.ts src/service/localServiceOpen.acceptance.test.ts",
91
92
  "test:mcp:shared-local:gate-d": "vitest run src/mcp/sharedLocalService.gateD.acceptance.test.ts",
92
93
  "gate:mcp:shared-local:d:init": "node --import tsx scripts/run-shared-local-mcp-gate-d.ts --init",
93
94
  "gate:mcp:shared-local:d:prerequisites": "node --import tsx scripts/run-shared-local-mcp-gate-d.ts --run-prerequisites",
@@ -97,17 +98,31 @@
97
98
  "test:sync:program-scaffold:postgres": "vitest run src/sync/v3/programScaffoldService.postgres.integration.test.ts",
98
99
  "test:postgres:run": "node scripts/run-with-disposable-postgres.mjs --",
99
100
  "test:postgres:smoke": "node scripts/run-with-disposable-postgres.mjs -- npm run test:sync:coordinator:postgres",
101
+ "test:cloud-read-workers:postgres": "npm run build && node scripts/run-with-disposable-postgres.mjs -- node scripts/run-cloud-collection-read-worker-gate.mjs",
100
102
  "test:soak": "sh scripts/run-soak.sh",
101
103
  "test:soak:smoke": "SYNC_SOAK_PROFILE=smoke sh scripts/run-soak.sh",
102
104
  "test:soak:stress": "SYNC_SOAK_PROFILE=stress sh scripts/run-soak.sh",
103
105
  "test:soak:overnight": "SYNC_SOAK_PROFILE=overnight sh scripts/run-soak.sh",
106
+ "test:aqr:contract": "vitest run scripts/aqr/execution-capsule.test.ts",
107
+ "test:aqr:sync-coverage": "vitest run scripts/aqr/sync-coverage-contract.test.ts",
108
+ "test:aqr:multi-client": "vitest run scripts/aqr/multi-client-replay.test.ts scripts/aqr/qa-multi-client-adapter.test.ts",
109
+ "test:aqr:convergence": "vitest run scripts/aqr/convergence-oracle.test.ts",
110
+ "test:aqr:pr-sync-gate:contract": "vitest run scripts/aqr/pr-sync-gate.test.ts",
111
+ "test:aqr:pr-sync-gate": "node --import tsx scripts/aqr/pr-sync-gate.ts",
112
+ "test:aqr:sync-fault-matrix:contract": "vitest run scripts/aqr/sync-fault-matrix.test.ts",
113
+ "test:aqr:sync-fault-matrix": "node --import tsx scripts/aqr/sync-fault-matrix.ts",
114
+ "test:aqr:cloud-writers:contract": "vitest run scripts/aqr/cloud-writer-acceptance.test.ts",
115
+ "test:aqr:cloud-writers": "node --import tsx scripts/aqr/cloud-writer-acceptance.ts",
116
+ "test:aqr:remote-sync:contract": "vitest run scripts/aqr/remote-sync-run.test.ts",
117
+ "test:aqr:remote-sync": "node --import tsx scripts/aqr/remote-sync-run.ts",
118
+ "aqr:smoke": "node --import tsx scripts/run-aqr-capsule.ts --contract-smoke",
104
119
  "test:e2e:realtime": "sh scripts/run-e2e-realtime.sh",
105
120
  "test:e2e:realtime:release": "npm run test:e2e:realtime -- tests/e2e/attachment-sync.spec.ts tests/e2e/realtime-multiclient.spec.ts tests/e2e/realtime-reconnect.spec.ts",
106
121
  "test:e2e:realtime:attachments": "npm run test:e2e:realtime -- tests/e2e/attachment-sync.spec.ts",
107
122
  "test:e2e:realtime:multiclient": "npm run test:e2e:realtime -- tests/e2e/realtime-multiclient.spec.ts",
108
123
  "test:e2e:realtime:reconnect": "npm run test:e2e:realtime -- tests/e2e/realtime-reconnect.spec.ts",
109
124
  "test:e2e:sync-coordinator": "SYNC_COORDINATOR_CANARY_ENABLED=true npm run test:e2e:realtime -- tests/e2e/sync-coordinator-multiclient.spec.ts",
110
- "test:e2e:sync-coordinator:workspace-switch": "SYNC_COORDINATOR_WORKSPACE_SWITCH_CANARY_ENABLED=true npm run test:e2e:realtime -- tests/e2e/sync-coordinator-workspace-switch.spec.ts",
125
+ "test:e2e:sync-coordinator:workspace-switch": "SYNC_SOAK_CLOUD_BASE_URL=${SYNC_SOAK_CLOUD_BASE_URL:-https://staging-app.taskforcehq.ai} SYNC_COORDINATOR_WORKSPACE_SWITCH_CANARY_ENABLED=true npm run test:e2e:realtime -- tests/e2e/sync-coordinator-workspace-switch.spec.ts",
111
126
  "test:e2e:sync-coordinator:process": "npm run test:e2e:realtime -- tests/e2e/sync-coordinator-process-ownership.spec.ts",
112
127
  "test:e2e:realtime:durable-task-metadata": "npm run test:e2e:realtime -- tests/e2e/durable-task-metadata-canary.spec.ts",
113
128
  "test:e2e:realtime:durable-task-create": "npm run test:e2e:realtime -- tests/e2e/durable-task-create-canary.spec.ts",
@@ -139,6 +154,8 @@
139
154
  "check:env:soak": "node --import tsx scripts/check-env.ts --target=soak --strict=true",
140
155
  "check:mcp-smoke": "node scripts/check-cloud-mcp.mjs",
141
156
  "check:mcp-connection": "node scripts/check-authenticated-mcp.mjs",
157
+ "check:mcp-latency": "node scripts/run-mcp-latency-gate.mjs",
158
+ "check:cloud-performance": "sh scripts/run-cloud-performance-gate.sh",
142
159
  "check:committed-mcp-secrets": "node scripts/check-committed-mcp-secrets.mjs",
143
160
  "test:committed-mcp-secrets": "node --test scripts/check-committed-mcp-secrets.test.mjs",
144
161
  "check:native-deps": "node scripts/check-native-deps.cjs",
@@ -166,6 +183,7 @@
166
183
  "ajv": "~8.18.0",
167
184
  "better-sqlite3": "^12.6.2",
168
185
  "chokidar": "^3.6.0",
186
+ "lucide-react": "^0.474.0",
169
187
  "nodemailer": "^9.0.3",
170
188
  "openai": "^6.45.0",
171
189
  "pg": "^8.18.0",
@@ -192,7 +210,6 @@
192
210
  "concurrently": "^8.2.2",
193
211
  "html2canvas": "^1.4.1",
194
212
  "jsdom": "^27.4.0",
195
- "lucide-react": "^0.474.0",
196
213
  "react": "^19.0.0",
197
214
  "react-dom": "^19.0.0",
198
215
  "react-markdown": "^9.1.0",