@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
@@ -52,6 +52,7 @@ export interface SaveTaskAttachmentInput {
52
52
  sizeBytes?: unknown;
53
53
  expectedSizeBytes?: unknown;
54
54
  expectedSha256?: unknown;
55
+ displayName?: unknown;
55
56
  caption?: unknown;
56
57
  overwrite?: unknown;
57
58
  overwriteAssetId?: unknown;
@@ -69,6 +70,7 @@ export type SaveTaskAttachmentResult = {
69
70
  expiresAt: string;
70
71
  uploadUrl: string;
71
72
  uploadedPath: string;
73
+ displayName?: string;
72
74
  caption?: string;
73
75
  overwrite: boolean;
74
76
  expectedSizeBytes?: unknown;
@@ -20,7 +20,7 @@ export function createTaskAttachmentCommandAdapter(deps) {
20
20
  return {
21
21
  buildAttachmentResponse,
22
22
  async save(input) {
23
- const { id: inputId, filename, content, sourcePath, uploadedPath, uploadDraftId, mimeType, sizeBytes, expectedSizeBytes, expectedSha256, caption, overwrite = false, overwriteAssetId, } = input;
23
+ const { id: inputId, filename, content, sourcePath, uploadedPath, uploadDraftId, mimeType, sizeBytes, expectedSizeBytes, expectedSha256, displayName, caption, overwrite = false, overwriteAssetId, } = input;
24
24
  const { id, task } = deps.resolveTask(inputId);
25
25
  const durableAttachmentLinksEnabled = deps.durableAttachmentLinksEnabled(id);
26
26
  if (!filename || typeof filename !== 'string')
@@ -38,6 +38,9 @@ export function createTaskAttachmentCommandAdapter(deps) {
38
38
  ? caption.trim()
39
39
  : undefined;
40
40
  const safeFilename = deps.sanitizeFilename(filename);
41
+ const safeDisplayName = typeof displayName === 'string' && displayName.trim().length > 0
42
+ ? displayName.trim()
43
+ : safeFilename;
41
44
  const stableAttachmentAssetId = deps.stableRequestId('operation', `task-attachment-asset:${id}:${safeFilename}`)?.replace(/^operation-/, 'asset-') || `asset-${randomUUID().replace(/-/g, '')}`;
42
45
  const safeMimeType = typeof mimeType === 'string' && mimeType.trim().length > 0
43
46
  ? mimeType.trim().toLowerCase()
@@ -53,7 +56,7 @@ export function createTaskAttachmentCommandAdapter(deps) {
53
56
  const overwriteTitle = overwriteTarget
54
57
  ? deps.workspaceAssetStore?.getDocument?.(overwriteTarget.asset.assetId, deps.activeWorkspaceId)?.title
55
58
  : null;
56
- const canonicalName = safeCaption || overwriteTitle || safeFilename;
59
+ const canonicalName = safeCaption || overwriteTitle || overwriteTarget?.asset.logicalName || safeFilename;
57
60
  const persistedCaption = isMarkdownDocument
58
61
  ? canonicalName
59
62
  : (safeCaption || overwriteTarget?.attachment.caption || safeFilename);
@@ -63,7 +66,7 @@ export function createTaskAttachmentCommandAdapter(deps) {
63
66
  : `/api/taskforce/context/${encodeURIComponent(storageKey)}`),
64
67
  fsPath: asset?.storageKey || overwriteTarget?.attachment.fsPath || storageKey,
65
68
  caption: isMarkdownDocument ? canonicalName : persistedCaption,
66
- displayName: isMarkdownDocument ? canonicalName : safeFilename,
69
+ displayName: safeDisplayName,
67
70
  originalFilename: safeFilename,
68
71
  ...(asset?.assetId ? { assetId: asset.assetId } : {}),
69
72
  timestamp: now,
@@ -110,6 +113,7 @@ export function createTaskAttachmentCommandAdapter(deps) {
110
113
  expiresAt,
111
114
  uploadUrl: objectStorageClient.createSignedPutUrl(stagedAsset.relativePath, uploadExpiresInSeconds, safeMimeType),
112
115
  uploadedPath: stagedAsset.relativePath,
116
+ ...(safeDisplayName !== safeFilename ? { displayName: safeDisplayName } : {}),
113
117
  ...(safeCaption ? { caption: safeCaption } : {}),
114
118
  overwrite: overwrite === true,
115
119
  ...(expectedSizeBytes !== undefined ? { expectedSizeBytes } : {}),
@@ -218,7 +222,8 @@ export function createTaskAttachmentCommandAdapter(deps) {
218
222
  const overwriteTitle = overwriteTarget
219
223
  ? deps.workspaceAssetStore?.getDocument?.(overwriteTarget.asset.assetId, deps.activeWorkspaceId)?.title
220
224
  : null;
221
- const canonicalName = safeCaption || overwriteTitle || safeFilename;
225
+ const canonicalName = safeCaption || overwriteTitle || overwriteTarget?.asset.logicalName
226
+ || existingUploadedAsset?.logicalName || safeFilename;
222
227
  const persistedCaption = isMarkdownDocument
223
228
  ? canonicalName
224
229
  : (safeCaption || overwriteTarget?.attachment.caption || safeFilename);
@@ -234,7 +239,7 @@ export function createTaskAttachmentCommandAdapter(deps) {
234
239
  assetId: overwriteTarget?.asset.assetId || existingUploadedAsset?.assetId || embeddedAssetId || `asset-${randomUUID().replace(/-/g, '')}`,
235
240
  workspaceId: deps.activeWorkspaceId,
236
241
  kind,
237
- logicalName: isMarkdownDocument ? canonicalName : safeFilename,
242
+ logicalName: canonicalName,
238
243
  originalFilename: safeFilename,
239
244
  mimeType: resolvedMimeType,
240
245
  storageProvider: 'r2',
@@ -269,7 +274,7 @@ export function createTaskAttachmentCommandAdapter(deps) {
269
274
  assetId: asset.assetId,
270
275
  taskId: id,
271
276
  role: 'attachment',
272
- displayName: kind === 'document' ? null : persistedCaption,
277
+ displayName: kind === 'document' ? null : safeDisplayName,
273
278
  updatedAt: now,
274
279
  deletedAt: null,
275
280
  });
@@ -324,13 +329,14 @@ export function createTaskAttachmentCommandAdapter(deps) {
324
329
  const overwriteTitle = overwriteTarget
325
330
  ? deps.workspaceAssetStore?.getDocument?.(overwriteTarget.asset.assetId, deps.activeWorkspaceId)?.title
326
331
  : null;
327
- const canonicalName = safeCaption || overwriteTitle || safeFilename;
332
+ const canonicalName = safeCaption || overwriteTitle || overwriteTarget?.asset.logicalName || safeFilename;
328
333
  const persistedCaption = isMarkdownDocument
329
334
  ? canonicalName
330
335
  : (safeCaption || overwriteTarget?.attachment.caption || safeFilename);
331
336
  asset = await deps.canonicalAssetHelpers.ensureCanonicalTaskAttachment(relativePath, id, persistedCaption, now, 'attachment', {
332
337
  originalFilename: safeFilename,
333
- logicalName: isMarkdownDocument ? canonicalName : safeFilename,
338
+ logicalName: canonicalName,
339
+ displayName: safeDisplayName,
334
340
  ...(!overwriteTarget ? { assetId: stableAttachmentAssetId } : {}),
335
341
  ...(overwriteTarget
336
342
  ? {
@@ -11,8 +11,16 @@ function nullableStringProperty(description) {
11
11
  ],
12
12
  };
13
13
  }
14
- function numberProperty(description) {
15
- return { type: 'number', description };
14
+ function integerProperty(description, minimum, maximum) {
15
+ return {
16
+ type: 'integer',
17
+ description,
18
+ ...(minimum === undefined ? {} : { minimum }),
19
+ ...(maximum === undefined ? {} : { maximum }),
20
+ };
21
+ }
22
+ function integerEnumProperty(description, values) {
23
+ return { type: 'integer', description, enum: values };
16
24
  }
17
25
  function booleanProperty(description) {
18
26
  return { type: 'boolean', description };
@@ -57,7 +65,7 @@ export function registerTaskPlanningTools(registerTool, executeTool) {
57
65
  title: stringProperty('Initiative title.'),
58
66
  description: stringProperty('Optional initiative description.'),
59
67
  ownerId: stringProperty(`${context.assigneeHint} Call list_assignees to inspect eligible IDs.`),
60
- order: numberProperty('Optional initiative order.'),
68
+ order: integerProperty('Optional non-negative initiative order.', 0),
61
69
  },
62
70
  required: ['title'],
63
71
  },
@@ -71,7 +79,7 @@ export function registerTaskPlanningTools(registerTool, executeTool) {
71
79
  title: stringProperty('Workstream title.'),
72
80
  description: stringProperty('Optional workstream description.'),
73
81
  ownerId: stringProperty(`${context.assigneeHint} Call list_assignees to inspect eligible IDs.`),
74
- order: numberProperty('Optional workstream order.'),
82
+ order: integerProperty('Optional non-negative workstream order.', 0),
75
83
  tasks: {
76
84
  type: 'array', maxItems: 50,
77
85
  items: {
@@ -83,8 +91,8 @@ export function registerTaskPlanningTools(registerTool, executeTool) {
83
91
  assignee: stringProperty(`${context.assigneeHint} Call list_assignees to inspect eligible IDs.`),
84
92
  category: stringProperty('Task category.', context.categoryEnum),
85
93
  type: stringProperty('Task type.', context.typeEnum),
86
- priority: numberProperty(context.priorityDesc),
87
- complexity: numberProperty(context.complexityDesc),
94
+ priority: integerEnumProperty(context.priorityDesc, context.priorityEnum),
95
+ complexity: integerProperty(context.complexityDesc, 1, 5),
88
96
  scheduledDate: stringProperty('Optional schedule date (YYYY-MM-DD).'),
89
97
  dueDate: stringProperty('Optional due date (YYYY-MM-DD).'),
90
98
  },
@@ -112,30 +120,32 @@ export function registerTaskPlanningTools(registerTool, executeTool) {
112
120
  },
113
121
  }));
114
122
  register('list_tasks', (context) => ({
115
- description: context.describeTool('List active tasks with optional filters, including workstreamId (an ID or WS-123 reference). Use offset and limit for bounded pagination. Use openOnly=true to exclude done/cancelled. Use format=json for programmatic use. Returns compact task summaries without descriptions, comments, activity, attachments, or event streams. When a task URL is provided, preserve it when presenting the task so the user can open it directly. Use get_task for one task’s details.'),
123
+ description: context.describeTool('List active tasks with filters and bounded pagination. Use workstreamId with an ID or WS-123 and openOnly=true to exclude done/cancelled. Use format=json for programmatic use. Returns compact summaries; use get_task for details. When a task URL is returned, preserve it when presenting the task.'),
116
124
  inputSchema: {
117
125
  properties: {
118
126
  format: stringProperty('Toggle output format (default: markdown).', ['markdown', 'json']),
119
127
  category: stringProperty('Filter by category.'),
120
128
  status: stringProperty('Filter by status.', ['task', 'on-hold', 'in-progress', 'review', 'done', 'cancelled']),
121
129
  openOnly: booleanProperty('When true, only include open tasks (task, on-hold, in-progress, review).'),
122
- assignee: stringProperty(`${context.assigneeHint} Call list_assignees to inspect the current eligible IDs.`),
123
- priority: numberProperty('Filter by priority level.'),
130
+ assignee: stringProperty(context.assigneeHint),
131
+ priority: integerEnumProperty(context.priorityDesc, context.priorityEnum),
124
132
  type: stringProperty('Filter by task type.', context.typeEnum),
125
133
  workstreamId: stringProperty('Filter by workstream ID or workstream reference such as WS-123.'),
126
134
  sort: stringProperty('Sort field (default: created).', ['priority', 'created', 'updated']),
127
135
  order: stringProperty('Sort order (default: desc).', ['asc', 'desc']),
128
- limit: numberProperty('Max tasks to return.'),
129
- offset: numberProperty('Non-negative result offset for pagination (default: 0).'),
136
+ limit: integerProperty('Max tasks to return (max 200).', 1, 200),
137
+ offset: integerProperty('Non-negative result offset for pagination (default: 0).', 0),
130
138
  },
131
139
  },
132
140
  }));
133
141
  register('search_tasks', (context) => ({
134
- description: context.describeTool('Search active and archived tasks by keyword or exact task reference. Matches title, description, internal ID, canonical T-* references, and provisional local LT-* references. Results use linked task references when an application URL is available; preserve those links when presenting tasks. Use scope=\'active\' or scope=\'archive\' to narrow results. Prefer this over list_tasks when looking for a specific task by name.'),
142
+ description: context.describeTool('Search active and archived tasks by keyword, ID, T-* reference, or provisional LT-* reference. Use scope to narrow results and offset/limit to continue broad searches. Prefer this over list_tasks when looking for a specific task by name. When results include links, preserve those links when presenting tasks.'),
135
143
  inputSchema: {
136
144
  properties: {
137
145
  query: stringProperty('Search term or exact task reference such as T-123 or LT-123.'),
138
146
  scope: stringProperty('Search scope (default: all).', ['all', 'active', 'archive']),
147
+ limit: integerProperty('Page size (default 25; max 50).', 1, 50),
148
+ offset: integerProperty('Non-negative result offset (default 0).', 0),
139
149
  },
140
150
  required: ['query'],
141
151
  },
@@ -150,6 +160,7 @@ export function registerTaskPlanningTools(registerTool, executeTool) {
150
160
  }));
151
161
  register('link_task_relationship', (context) => ({
152
162
  description: context.describeTool('Create an idempotent structured relationship between two tasks. blocks(A,B) is the inverse view of depends_on(B,A). Rejects self-links, missing tasks, and dependency/supersession cycles.'),
163
+ annotations: { idempotentHint: true },
153
164
  inputSchema: { properties: {
154
165
  sourceTaskId: stringProperty('Source task ID or reference.'),
155
166
  targetTaskId: stringProperty('Target task ID or reference.'),
@@ -159,6 +170,7 @@ export function registerTaskPlanningTools(registerTool, executeTool) {
159
170
  }));
160
171
  register('unlink_task_relationship', (context) => ({
161
172
  description: context.describeTool('Idempotently remove a structured task relationship. The relationship is tombstoned so deletion converges across sync.'),
173
+ annotations: { idempotentHint: true },
162
174
  inputSchema: { properties: {
163
175
  sourceTaskId: stringProperty('Source task ID or reference.'),
164
176
  targetTaskId: stringProperty('Target task ID or reference.'),
@@ -167,43 +179,45 @@ export function registerTaskPlanningTools(registerTool, executeTool) {
167
179
  }, required: ['sourceTaskId', 'targetTaskId', 'type'] },
168
180
  }));
169
181
  register('get_task', (context) => ({
170
- description: context.describeTool('Get one task by ID or T-123 reference. The default compact response returns scalar task fields and collection counts without comments, history, checklist items, or attachments. When the response includes url, preserve it in any task reference you present so the user can open the task directly. Pass detail=full for comments and attachment/checklist metadata, or detail=history for one chronological comment/event stream. Use get_task_attachments for attachment bodies; use D-123/I-123 tools for documents/images. When showing this task to the user in a client that supports rich inline rendering, prefer a compact visual summary that retains the task link.'),
182
+ description: context.describeTool('Get one task by ID or T-123 reference. The default compact response returns scalar fields and collection counts. Use detail=full for comments and attachment/checklist metadata, or detail=history for chronology. Use get_task_attachments for attachment bodies; use D-123/I-123 tools for documents/images. When url is returned, preserve it in any task reference you present.'),
171
183
  inputSchema: {
172
184
  properties: {
173
185
  id: stringProperty('Task ID or task reference such as T-123.'),
174
- detail: stringProperty('Response detail level (default: compact). Use full for comments and attachment/checklist metadata, or history for chronological task events.', ['compact', 'full', 'history']),
186
+ detail: stringProperty('Response detail: compact, full, or chronological history.', ['compact', 'full', 'history']),
175
187
  },
176
188
  required: ['id'],
177
189
  },
178
190
  }));
179
191
  register('list_initiatives', (context) => ({
180
- description: context.describeTool('List or search initiatives for the active workspace. Pass query to search by initiative title, description, ID/reference, owner, or linked workstream title. Returns compact initiative summaries with workstream and task counts.'),
192
+ description: context.describeTool('List or search initiatives for the active workspace. Pass query to search by initiative title, description, ID/reference, owner, or linked workstream title. Use offset/limit to continue through compact summaries.'),
181
193
  inputSchema: {
182
194
  properties: {
183
195
  query: stringProperty('Optional search term for initiative title, description, ID/reference such as IN-123, owner, or linked workstream title.'),
196
+ limit: { type: 'integer', minimum: 1, maximum: 100, description: 'Page size (default 25; max 100).' },
197
+ offset: { type: 'integer', minimum: 0, description: 'Non-negative result offset (default 0).' },
184
198
  },
185
199
  },
186
200
  }));
187
201
  register('get_initiative', (context) => ({
188
- description: context.describeTool('Get one initiative by ID or IN-123 reference. The default compact response returns summary counts. Use detail=planning for current attachments plus paginated active/archived workstream summaries and historical task counts, detail=history for bounded chronological history, or detail=full for the compatible rich response.'),
202
+ description: context.describeTool('Get one initiative by ID or IN-123. Compact returns counts; detail=planning adds attachments, paginated workstreams, and historical task counts; detail=history returns bounded chronology; full returns the compatible rich response.'),
189
203
  inputSchema: {
190
204
  properties: {
191
205
  id: stringProperty('Initiative ID or initiative reference such as IN-123.'),
192
- detail: stringProperty('Response detail level (default: compact). Planning excludes history; history is chronological and bounded; full preserves the rich response.', ['compact', 'planning', 'history', 'full']),
193
- limit: { type: 'integer', minimum: 1, maximum: 100, description: 'Page size for planning workstreams or history entries (default: 25, max: 100).' },
194
- offset: { type: 'integer', minimum: 0, description: 'Non-negative page offset for planning workstreams or history entries (default: 0).' },
206
+ detail: stringProperty('Response detail: compact, planning, history, or full.', ['compact', 'planning', 'history', 'full']),
207
+ limit: { type: 'integer', minimum: 1, maximum: 100, description: 'Planning/history page size (default 25; max 100).' },
208
+ offset: { type: 'integer', minimum: 0, description: 'Planning/history page offset (default 0).' },
195
209
  },
196
210
  required: ['id'],
197
211
  },
198
212
  }));
199
213
  register('create_initiative', (context) => ({
200
- description: context.describeTool('Create a new initiative. Use this for the top planning layer when a body of work should coordinate multiple workstreams.'),
214
+ description: context.describeTool('Create a new initiative. Pass idempotencyKey when retrying after an ambiguous timeout; reuse it only with the exact same payload.'),
201
215
  inputSchema: {
202
216
  properties: {
203
217
  title: stringProperty('Initiative title.'),
204
218
  description: stringProperty('Optional initiative description.'),
205
- ownerId: stringProperty(`${context.assigneeHint} Call list_assignees to inspect the current eligible IDs.`),
206
- order: numberProperty('Optional sort order among initiatives.'),
219
+ ownerId: stringProperty(context.assigneeHint),
220
+ order: integerProperty('Optional non-negative sort order among initiatives.', 0),
207
221
  attachments: arrayProperty('Optional attachment descriptors to store on the initiative. Prefer save_initiative_attachment for generated content or files.', {
208
222
  type: 'object',
209
223
  properties: {
@@ -216,6 +230,7 @@ export function registerTaskPlanningTools(registerTool, executeTool) {
216
230
  },
217
231
  required: ['path'],
218
232
  }),
233
+ idempotencyKey: { type: 'string', minLength: 1, maxLength: 128, description: 'Optional opaque retry key scoped to the active workspace, actor, and tool.' },
219
234
  },
220
235
  required: ['title'],
221
236
  },
@@ -227,9 +242,9 @@ export function registerTaskPlanningTools(registerTool, executeTool) {
227
242
  id: stringProperty('Initiative ID or initiative reference such as IN-123.'),
228
243
  title: stringProperty('Updated initiative title.'),
229
244
  description: stringProperty('Updated initiative description.'),
230
- ownerId: stringProperty(`${context.assigneeHint} Call list_assignees to inspect the current eligible IDs.`),
231
- order: numberProperty('Optional sort order among initiatives.'),
232
- attachments: arrayProperty('Replacement attachment descriptors for the initiative. Prefer save_initiative_attachment and delete_initiative_attachment for generated content or files.', {
245
+ ownerId: stringProperty(context.assigneeHint),
246
+ order: integerProperty('Optional non-negative sort order among initiatives.', 0),
247
+ attachments: arrayProperty('Replacement attachment descriptors for the initiative. Prefer save_initiative_attachment for generated content or files. Removing managed attachments requires delete_initiative_attachment in the extended profile.', {
233
248
  type: 'object',
234
249
  properties: {
235
250
  path: { type: 'string' },
@@ -246,11 +261,12 @@ export function registerTaskPlanningTools(registerTool, executeTool) {
246
261
  },
247
262
  }));
248
263
  register('add_initiative_comment', (context) => ({
249
- description: context.describeTool('Add a comment to an initiative. Use this for initiative-level progress notes, decisions, coordination context, and audit trails. Comments appear in the initiative activity feed.'),
264
+ description: context.describeTool('Add a comment to an initiative. Pass idempotencyKey when retrying after an ambiguous timeout; reuse it only with the exact same target and text.'),
250
265
  inputSchema: {
251
266
  properties: {
252
267
  id: stringProperty('Initiative ID or initiative reference such as IN-123.'),
253
268
  text: stringProperty('Comment text.'),
269
+ idempotencyKey: { type: 'string', minLength: 1, maxLength: 128, description: 'Optional opaque retry key scoped to the active workspace, actor, and tool.' },
254
270
  },
255
271
  required: ['id', 'text'],
256
272
  },
@@ -274,34 +290,36 @@ export function registerTaskPlanningTools(registerTool, executeTool) {
274
290
  },
275
291
  }));
276
292
  register('list_workstreams', (context) => ({
277
- description: context.describeTool('List or search workstreams for the active workspace. Pass query to search by workstream title, description, ID/reference, owner, or linked initiative title/reference. Returns compact workstream summaries with task counts.'),
293
+ description: context.describeTool('List or search workstreams for the active workspace. Pass query to search by workstream title, description, ID/reference, owner, or linked initiative title/reference. Use offset/limit to continue through compact summaries.'),
278
294
  inputSchema: {
279
295
  properties: {
280
296
  query: stringProperty('Optional search term for workstream title, description, ID/reference such as WS-123, owner, or linked initiative title/reference.'),
297
+ limit: { type: 'integer', minimum: 1, maximum: 100, description: 'Page size (default 25; max 100).' },
298
+ offset: { type: 'integer', minimum: 0, description: 'Non-negative result offset (default 0).' },
281
299
  },
282
300
  },
283
301
  }));
284
302
  register('get_workstream', (context) => ({
285
- description: context.describeTool('Get one workstream by ID or WS-123 reference. The default compact response returns a summary and task count. Use detail=planning for current attachments and explicit historical task counts without nested tasks, detail=history for bounded chronological history, or detail=full for the compatible rich response. Use list_tasks with workstreamId for bounded active task discovery.'),
303
+ description: context.describeTool('Get one workstream by ID or WS-123. Compact returns a summary and task count; detail=planning adds attachments and historical counts; detail=history returns bounded chronology; full returns the compatible rich response. Use list_tasks with workstreamId for active tasks.'),
286
304
  inputSchema: {
287
305
  properties: {
288
306
  id: stringProperty('Workstream ID or workstream reference such as WS-123.'),
289
- detail: stringProperty('Response detail level (default: compact). Planning excludes history and nested tasks; history is chronological and bounded; full preserves the rich response.', ['compact', 'planning', 'history', 'full']),
290
- limit: { type: 'integer', minimum: 1, maximum: 100, description: 'Page size for history entries (default: 25, max: 100).' },
291
- offset: { type: 'integer', minimum: 0, description: 'Non-negative history page offset (default: 0).' },
307
+ detail: stringProperty('Response detail: compact, planning, history, or full.', ['compact', 'planning', 'history', 'full']),
308
+ limit: { type: 'integer', minimum: 1, maximum: 100, description: 'History page size (default 25; max 100).' },
309
+ offset: { type: 'integer', minimum: 0, description: 'History page offset (default 0).' },
292
310
  },
293
311
  required: ['id'],
294
312
  },
295
313
  }));
296
314
  register('create_workstream', (context) => ({
297
- description: context.describeTool('Create a new workstream. Use initiativeId to link it to an initiative, or omit initiativeId to create a standalone workstream.'),
315
+ description: context.describeTool('Create a new workstream. Pass idempotencyKey when retrying after an ambiguous timeout; reuse it only with the exact same payload.'),
298
316
  inputSchema: {
299
317
  properties: {
300
318
  title: stringProperty('Workstream title.'),
301
319
  description: stringProperty('Optional workstream description.'),
302
- ownerId: stringProperty(`${context.assigneeHint} Call list_assignees to inspect the current eligible IDs.`),
320
+ ownerId: stringProperty(context.assigneeHint),
303
321
  initiativeId: stringProperty('Optional initiative ID or initiative reference such as IN-123.'),
304
- order: numberProperty('Optional sort order among workstreams.'),
322
+ order: integerProperty('Optional non-negative sort order among workstreams.', 0),
305
323
  attachments: arrayProperty('Optional attachment descriptors to store on the workstream. Prefer save_workstream_attachment for generated content or files.', {
306
324
  type: 'object',
307
325
  properties: {
@@ -314,6 +332,7 @@ export function registerTaskPlanningTools(registerTool, executeTool) {
314
332
  },
315
333
  required: ['path'],
316
334
  }),
335
+ idempotencyKey: { type: 'string', minLength: 1, maxLength: 128, description: 'Optional opaque retry key scoped to the active workspace, actor, and tool.' },
317
336
  },
318
337
  required: ['title'],
319
338
  },
@@ -325,10 +344,10 @@ export function registerTaskPlanningTools(registerTool, executeTool) {
325
344
  id: stringProperty('Workstream ID or workstream reference such as WS-123.'),
326
345
  title: stringProperty('Updated workstream title.'),
327
346
  description: stringProperty('Updated workstream description.'),
328
- ownerId: stringProperty(`${context.assigneeHint} Call list_assignees to inspect the current eligible IDs.`),
347
+ ownerId: stringProperty(context.assigneeHint),
329
348
  initiativeId: stringProperty('Optional initiative ID or initiative reference such as IN-123. Pass an empty string to unlink.'),
330
- order: numberProperty('Optional sort order among workstreams.'),
331
- attachments: arrayProperty('Replacement attachment descriptors for the workstream. Prefer save_workstream_attachment and delete_workstream_attachment for generated content or files.', {
349
+ order: integerProperty('Optional non-negative sort order among workstreams.', 0),
350
+ attachments: arrayProperty('Replacement attachment descriptors for the workstream. Prefer save_workstream_attachment for generated content or files. Removing managed attachments requires delete_workstream_attachment in the extended profile.', {
332
351
  type: 'object',
333
352
  properties: {
334
353
  path: { type: 'string' },
@@ -345,11 +364,12 @@ export function registerTaskPlanningTools(registerTool, executeTool) {
345
364
  },
346
365
  }));
347
366
  register('add_workstream_comment', (context) => ({
348
- description: context.describeTool('Add a comment to a workstream. Use this for workstream-level progress notes, decisions, coordination context, and audit trails. Comments appear in the workstream activity feed.'),
367
+ description: context.describeTool('Add a comment to a workstream. Pass idempotencyKey when retrying after an ambiguous timeout; reuse it only with the exact same target and text.'),
349
368
  inputSchema: {
350
369
  properties: {
351
370
  id: stringProperty('Workstream ID or workstream reference such as WS-123.'),
352
371
  text: stringProperty('Comment text.'),
372
+ idempotencyKey: { type: 'string', minLength: 1, maxLength: 128, description: 'Optional opaque retry key scoped to the active workspace, actor, and tool.' },
353
373
  },
354
374
  required: ['id', 'text'],
355
375
  },
@@ -374,12 +394,13 @@ export function registerTaskPlanningTools(registerTool, executeTool) {
374
394
  }));
375
395
  register('update_task_workstream', (context) => ({
376
396
  description: context.describeTool('Set or clear the workstream for one task. Pass workstreamId to assign or reassign; pass an empty string or null to unlink the task from its current workstream.'),
397
+ annotations: { idempotentHint: true },
377
398
  inputSchema: {
378
399
  properties: {
379
400
  taskId: stringProperty('Task ID or task reference such as T-123.'),
380
- id: stringProperty('Alias for taskId. Task ID or task reference such as T-123.'),
381
401
  workstreamId: nullableStringProperty('Workstream ID or workstream reference such as WS-123. Pass an empty string or null to unlink.'),
382
402
  },
403
+ required: ['taskId', 'workstreamId'],
383
404
  },
384
405
  }));
385
406
  register('update_workstream_initiative', (context) => ({
@@ -387,9 +408,9 @@ export function registerTaskPlanningTools(registerTool, executeTool) {
387
408
  inputSchema: {
388
409
  properties: {
389
410
  workstreamId: stringProperty('Workstream ID or workstream reference such as WS-123.'),
390
- id: stringProperty('Alias for workstreamId. Workstream ID or workstream reference such as WS-123.'),
391
411
  initiativeId: nullableStringProperty('Initiative ID or initiative reference such as IN-123. Pass an empty string or null to unlink.'),
392
412
  },
413
+ required: ['workstreamId', 'initiativeId'],
393
414
  },
394
415
  }));
395
416
  register('get_task_checklist', (context) => ({
@@ -423,7 +444,7 @@ export function registerTaskPlanningTools(registerTool, executeTool) {
423
444
  id: { type: 'string', description: 'Stable checklist item ID. Reuse it when reordering or updating an existing item.' },
424
445
  text: { type: 'string' },
425
446
  done: { type: 'boolean' },
426
- order: { type: 'number', description: 'Optional zero-based display order.' },
447
+ order: { type: 'integer', minimum: 0, description: 'Optional zero-based display order.' },
427
448
  createdAt: { type: 'string', description: 'Optional canonical ISO creation timestamp.' },
428
449
  updatedAt: { type: 'string', description: 'Optional canonical ISO last-change timestamp.' },
429
450
  },
@@ -447,28 +468,17 @@ export function registerTaskPlanningTools(registerTool, executeTool) {
447
468
  inputSchema: {
448
469
  properties: {
449
470
  taskId: stringProperty('Task ID or task reference such as T-123.'),
450
- id: stringProperty('Alias for taskId. Task ID or task reference such as T-123.'),
451
- date: nullableStringProperty('Target date in YYYY-MM-DD format. Pass an empty string or null with taskId to unschedule.'),
452
- scheduledDate: nullableStringProperty('Alias for date. Target date in YYYY-MM-DD format. Pass an empty string or null with taskId to unschedule.'),
453
- order: numberProperty('Optional position within that day.'),
454
- orderInDay: numberProperty('Alias for order. Optional position within that day.'),
455
- taskIds: arrayProperty('Ordered task IDs or task references for replacing one scheduled day order.', { type: 'string' }),
456
- moves: arrayProperty('Advanced reorder moves. Each move may include id or taskId, date or scheduledDate, and order or orderInDay.', {
471
+ date: nullableStringProperty('YYYY-MM-DD; null or empty with taskId unschedules.'),
472
+ order: integerProperty('Optional non-negative position within that day.', 0),
473
+ taskIds: arrayProperty('Ordered task IDs or references replacing one day.', { type: 'string' }),
474
+ moves: arrayProperty('Advanced reorder moves using canonical taskId, date, and order fields.', {
457
475
  type: 'object',
458
476
  properties: {
459
- id: { type: 'string' },
460
477
  taskId: { type: 'string' },
461
478
  date: { type: 'string' },
462
- scheduledDate: { type: 'string' },
463
- order: { type: 'number' },
464
- orderInDay: { type: 'number' },
479
+ order: { type: 'integer', minimum: 0 },
465
480
  },
466
- anyOf: [
467
- { required: ['id', 'date'] },
468
- { required: ['id', 'scheduledDate'] },
469
- { required: ['taskId', 'date'] },
470
- { required: ['taskId', 'scheduledDate'] },
471
- ],
481
+ required: ['taskId', 'date'],
472
482
  }),
473
483
  },
474
484
  },
@@ -513,7 +523,7 @@ export function registerTaskPlanningTools(registerTool, executeTool) {
513
523
  },
514
524
  }));
515
525
  register('create_task', (context) => ({
516
- description: context.describeTool('Create a new task. Pass idempotencyKey when the call may be retried after a timeout; the same key and payload return the original task, while a changed payload is rejected. Current taxonomy values are included in this schema; call get_config only for richer metadata or after a validation mismatch.'),
526
+ description: context.describeTool('Create a task. For retries, the same idempotencyKey and payload return the original; changed payloads conflict. Taxonomy enums are current; use get_config for metadata or after validation errors.'),
517
527
  inputSchema: {
518
528
  properties: {
519
529
  title: stringProperty('Task title.'),
@@ -524,13 +534,13 @@ export function registerTaskPlanningTools(registerTool, executeTool) {
524
534
  description: 'Optional opaque retry key scoped to the active workspace and AI profile.',
525
535
  },
526
536
  description: stringProperty('Optional task description.'),
527
- assignee: stringProperty(`${context.assigneeHint} Call list_assignees to inspect the current eligible IDs.`),
528
- workstreamId: stringProperty('Optional workstream ID or workstream reference such as WS-123. Use this to create the task directly inside a workstream without a separate update_task_workstream call. Call list_workstreams with query first if you only know the workstream name.'),
537
+ assignee: stringProperty(context.assigneeHint),
538
+ workstreamId: stringProperty('Workstream ID or WS-123; use to create the task directly inside a workstream. Search list_workstreams if needed.'),
529
539
  category: stringProperty('Task category value.', context.categoryEnum),
530
540
  type: stringProperty('Task type value.', context.typeEnum),
531
- priority: numberProperty(context.priorityDesc),
541
+ priority: integerEnumProperty(context.priorityDesc, context.priorityEnum),
532
542
  status: stringProperty('Initial task status.', ['task', 'on-hold', 'in-progress', 'review', 'done', 'cancelled']),
533
- complexity: numberProperty(context.complexityDesc),
543
+ complexity: integerProperty(context.complexityDesc, 1, 5),
534
544
  scheduledDate: stringProperty('Optional scheduled date in YYYY-MM-DD format.'),
535
545
  dueDate: stringProperty('Optional due date in YYYY-MM-DD format.'),
536
546
  },
@@ -548,6 +558,7 @@ export function registerTaskPlanningTools(registerTool, executeTool) {
548
558
  }));
549
559
  register('reopen_task', (context) => ({
550
560
  description: context.describeTool('Safely resume reviewed work in one call. Reopens archived done tasks or active/archived review tasks to in-progress, preserves an existing assignee, and claims only unassigned work. Cancelled tasks are rejected. Already in-progress tasks are idempotent no-ops.'),
561
+ annotations: { idempotentHint: true },
551
562
  inputSchema: {
552
563
  properties: {
553
564
  id: stringProperty('Task ID or task reference such as T-123.'),
@@ -562,13 +573,13 @@ export function registerTaskPlanningTools(registerTool, executeTool) {
562
573
  id: stringProperty('Task ID or task reference such as T-123.'),
563
574
  title: stringProperty('Updated task title.'),
564
575
  description: stringProperty('Updated task description.'),
565
- assignee: stringProperty(`${context.assigneeHint} Call list_assignees to inspect the current eligible IDs.`),
576
+ assignee: stringProperty(context.assigneeHint),
566
577
  workstreamId: stringProperty('Updated workstream ID or workstream reference such as WS-123. Pass an empty string to unlink the task. Call list_workstreams with query first if you only know the workstream name.'),
567
578
  category: stringProperty('Updated category value.', context.categoryEnum),
568
579
  type: stringProperty('Updated task type value.', context.typeEnum),
569
- priority: numberProperty(context.priorityDesc),
580
+ priority: integerEnumProperty(context.priorityDesc, context.priorityEnum),
570
581
  status: stringProperty('Updated task status.', ['task', 'on-hold', 'in-progress', 'review', 'done', 'cancelled']),
571
- complexity: numberProperty(context.complexityDesc),
582
+ complexity: integerProperty(context.complexityDesc, 1, 5),
572
583
  scheduledDate: stringProperty('Updated scheduled date in YYYY-MM-DD format. Pass an empty string to clear.'),
573
584
  dueDate: stringProperty('Updated due date in YYYY-MM-DD format. Pass an empty string to clear.'),
574
585
  },
@@ -576,7 +587,7 @@ export function registerTaskPlanningTools(registerTool, executeTool) {
576
587
  },
577
588
  }));
578
589
  register('finish_task', (context) => ({
579
- description: context.describeTool('default end-of-task handoff for active work. Archived tasks are rejected; call reopen_task first. Use outcome=\'done\' when work is complete and outcome=\'review\' when human validation or approval is needed. If you report completed work on a tracked task, either finish it with this tool or explain why it remains open. Both outcomes remain active and unarchived. This tool never archives automatically; use archive_task separately to move work to history. The response always reports completion.archived from persisted state.'),
590
+ description: context.describeTool('Default end-of-task handoff. Use outcome=\'done\' for completed work or outcome=\'review\' for validation. Both remain active and unarchived; use archive_task for history. Archived tasks require reopen_task first.'),
580
591
  inputSchema: {
581
592
  properties: {
582
593
  id: stringProperty('Task ID or task reference such as T-123.'),
@@ -10,7 +10,44 @@ export function resolveCanonicalMcpToolName(nameRaw) {
10
10
  export function resolveMcpToolCallCompatibility(nameRaw, argsRaw) {
11
11
  const name = resolveCanonicalMcpToolName(nameRaw);
12
12
  const args = argsRaw && typeof argsRaw === 'object' && !Array.isArray(argsRaw)
13
- ? argsRaw
13
+ ? { ...argsRaw }
14
14
  : {};
15
+ const moveAlias = (alias, canonical) => {
16
+ if (args[canonical] === undefined && args[alias] !== undefined)
17
+ args[canonical] = args[alias];
18
+ delete args[alias];
19
+ };
20
+ if (name === 'get_image')
21
+ moveAlias('id', 'imageId');
22
+ if (name === 'get_image_annotations')
23
+ moveAlias('imageAssetId', 'imageId');
24
+ if (name === 'get_task_attachments')
25
+ moveAlias('id', 'taskId');
26
+ if (name === 'update_task_workstream')
27
+ moveAlias('id', 'taskId');
28
+ if (name === 'update_workstream_initiative')
29
+ moveAlias('id', 'workstreamId');
30
+ if (name === 'update_schedule') {
31
+ moveAlias('id', 'taskId');
32
+ moveAlias('scheduledDate', 'date');
33
+ moveAlias('orderInDay', 'order');
34
+ if (Array.isArray(args.moves)) {
35
+ args.moves = args.moves.map((move) => {
36
+ if (!move || typeof move !== 'object' || Array.isArray(move))
37
+ return move;
38
+ const normalized = { ...move };
39
+ const normalizeMoveAlias = (alias, canonical) => {
40
+ if (normalized[canonical] === undefined && normalized[alias] !== undefined) {
41
+ normalized[canonical] = normalized[alias];
42
+ }
43
+ delete normalized[alias];
44
+ };
45
+ normalizeMoveAlias('id', 'taskId');
46
+ normalizeMoveAlias('scheduledDate', 'date');
47
+ normalizeMoveAlias('orderInDay', 'order');
48
+ return normalized;
49
+ });
50
+ }
51
+ }
15
52
  return { name, arguments: args };
16
53
  }
@@ -22,6 +22,7 @@ export type McpToolDescriptorContext = {
22
22
  describeTool: (text: string) => string;
23
23
  assigneeHint: string;
24
24
  categoryEnum: string[];
25
+ priorityEnum: number[];
25
26
  priorityDesc: string;
26
27
  typeEnum: string[];
27
28
  complexityDesc: string;
@@ -52,10 +52,10 @@ export const MCP_TOOL_REGISTRY = Object.freeze({
52
52
  replace_task_checklist: defaultTool({ kind: 'scope', scope: 'tasks:write' }, true),
53
53
  get_task_attachments: defaultTool({ kind: 'scope', scope: 'tasks:read' }, false),
54
54
  get_workstream_attachments: extendedTool({ kind: 'scope', scope: 'tasks:read' }, false),
55
- save_workstream_attachment: extendedTool({ kind: 'scope', scope: 'tasks:write' }, true),
55
+ save_workstream_attachment: defaultTool({ kind: 'scope', scope: 'tasks:write' }, true),
56
56
  delete_workstream_attachment: extendedTool({ kind: 'scope', scope: 'tasks:write' }, true),
57
57
  get_initiative_attachments: extendedTool({ kind: 'scope', scope: 'tasks:read' }, false),
58
- save_initiative_attachment: extendedTool({ kind: 'scope', scope: 'tasks:write' }, true),
58
+ save_initiative_attachment: defaultTool({ kind: 'scope', scope: 'tasks:write' }, true),
59
59
  delete_initiative_attachment: extendedTool({ kind: 'scope', scope: 'tasks:write' }, true),
60
60
  search_images: defaultTool({ kind: 'scope', scope: 'tasks:read' }, false),
61
61
  get_image: defaultTool({ kind: 'scope', scope: 'tasks:read' }, false),