@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
@@ -1,6 +1,6 @@
1
- import { jsxs as _jsxs, jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import React from 'react';
3
- import { AlertTriangle, Archive, ArrowUpDown, ChevronLeft, Eye, EyeOff, Filter, Link2, Loader2, Pencil, Plus, RotateCcw, Search, Unlink, X, } from 'lucide-react';
3
+ import { AlertTriangle, Archive, ArrowUpDown, ChevronLeft, Eye, EyeOff, Filter, Loader2, Pencil, Plus, RotateCcw, Search, Unlink, X, } from 'lucide-react';
4
4
  import { TASK_ASSIGNEE_UNASSIGNED_COLOR, TASK_ASSIGNEE_UNASSIGNED_ICON, } from '../../../utils/assignees';
5
5
  import { resolvePlanningArchiveDetailState } from '../../../utils/planningArchivePresentation';
6
6
  import { formatInitiativeReference, formatWorkstreamReference, } from '../../../utils/planningReferences';
@@ -10,6 +10,7 @@ import { TaxonomyDropdown } from '../../ui/TaxonomyDropdown';
10
10
  import { PlanningOwnerDropdown, normalizePlanningOwnerOptions, } from './PlanningOwnerDropdown';
11
11
  import { buildPlanningNavigatorResults, PLANNING_NAVIGATOR_SORT_OPTIONS, } from './planningNavigator';
12
12
  import { PlanningEntitySummary, PlanningReferenceBadge, } from './PlanningEntitySummary';
13
+ import { PlanningVisualIdentity } from './PlanningVisualIdentity';
13
14
  import { PlanningTaskCard } from './PlanningTaskCard';
14
15
  import { PlanningTaskArrangeControl } from './PlanningTaskArrangeControl';
15
16
  import planningDropdownStyles from './PlanningDropdownControl.module.css';
@@ -29,6 +30,8 @@ function PlanningWorkspaceEditor({ entityType, mode, initialTitle = '', initialD
29
30
  const [title, setTitle] = React.useState(initialTitle);
30
31
  const [description, setDescription] = React.useState(initialDescription);
31
32
  const [ownerId, setOwnerId] = React.useState('');
33
+ const [icon, setIcon] = React.useState(null);
34
+ const [color, setColor] = React.useState(null);
32
35
  const [titleError, setTitleError] = React.useState(null);
33
36
  const [saveError, setSaveError] = React.useState(null);
34
37
  const [isSaving, setIsSaving] = React.useState(false);
@@ -57,6 +60,7 @@ function PlanningWorkspaceEditor({ entityType, mode, initialTitle = '', initialD
57
60
  ...(entityType === 'workstream' && mode === 'create'
58
61
  ? { initiativeId: fixedInitiativeId || null }
59
62
  : {}),
63
+ ...(mode === 'create' && (icon || color) ? { icon, color } : {}),
60
64
  });
61
65
  }
62
66
  catch (error) {
@@ -72,7 +76,12 @@ function PlanningWorkspaceEditor({ entityType, mode, initialTitle = '', initialD
72
76
  return;
73
77
  event.preventDefault();
74
78
  onCancel();
75
- }, noValidate: true, children: [_jsxs("div", { className: styles.workspaceEditorField, children: [_jsxs("label", { htmlFor: titleInputId, children: [label, " title"] }), _jsx("input", { ref: titleInputRef, id: titleInputId, value: title, disabled: isSaving, required: true, "aria-invalid": titleError ? 'true' : undefined, "aria-describedby": titleError ? titleErrorId : undefined, onChange: (event) => {
79
+ }, noValidate: true, children: [mode === 'create' ? (_jsxs("div", { className: styles.workspaceEditorIdentity, children: [_jsx(PlanningVisualIdentity, { entityType: entityType, entityId: "create-preview", icon: icon, color: color || 'blue', size: "detail", onChange: (patch) => {
80
+ if (Object.prototype.hasOwnProperty.call(patch, 'icon'))
81
+ setIcon(patch.icon ?? null);
82
+ if (Object.prototype.hasOwnProperty.call(patch, 'color'))
83
+ setColor(patch.color ?? null);
84
+ } }), _jsx("span", { children: "Choose an icon and color" })] })) : null, _jsxs("div", { className: styles.workspaceEditorField, children: [_jsxs("label", { htmlFor: titleInputId, children: [label, " title"] }), _jsx("input", { ref: titleInputRef, id: titleInputId, value: title, disabled: isSaving, required: true, "aria-invalid": titleError ? 'true' : undefined, "aria-describedby": titleError ? titleErrorId : undefined, onChange: (event) => {
76
85
  setTitle(event.target.value);
77
86
  if (titleError)
78
87
  setTitleError(null);
@@ -80,24 +89,24 @@ function PlanningWorkspaceEditor({ entityType, mode, initialTitle = '', initialD
80
89
  ? 'Describe the broader outcome this initiative is meant to achieve.'
81
90
  : 'Describe the lane of work this workstream will coordinate.' })] }), mode === 'create' && ownerOptions ? (_jsxs("div", { className: styles.workspaceEditorField, children: [_jsxs("span", { children: [label, " owner"] }), _jsx(PlanningOwnerDropdown, { value: ownerId, options: ownerOptions, onChange: setOwnerId, disabled: isSaving, ariaLabel: `${label} owner`, className: `${planningDropdownStyles.control} ${styles.selectedEntityOwnerDropdown}` })] })) : null, saveError ? _jsx("p", { className: "tf-text-error", role: "alert", children: saveError }) : null, showActions ? _jsxs("div", { className: styles.workspaceEditorActions, children: [_jsx("button", { type: "button", className: "tf-button-secondary tf-button-compact", onClick: onCancel, disabled: isSaving, children: "Cancel" }), _jsxs("button", { type: "submit", className: "tf-button-primary tf-button-compact", disabled: isSaving, children: [isSaving ? _jsx(Loader2, { size: 14, className: styles.spinner, "aria-hidden": "true" }) : null, mode === 'create' ? `Create ${label}` : 'Save'] })] }) : null] }));
82
91
  }
83
- function InitiativeButton({ initiative, ownerOption, ownerOptions, workstreamCount, selected, onSelect, onChangeOwner, }) {
92
+ function InitiativeButton({ initiative, ownerOption, ownerOptions, workstreamCount, selected, onSelect, onChangeOwner, onChangeIdentity, }) {
84
93
  return (_jsxs("div", { className: `${styles.entityCard} ${initiative.isArchived ? styles.entityCardArchived : ''} ${selected ? styles.entityCardSelected : ''}`.trim(), children: [_jsx(PlanningReferenceBadge, { label: formatInitiativeReference(initiative), entityType: "initiative", entityName: initiative.title, interactive: false }), _jsx("div", { className: styles.entityCardBody, children: _jsx("div", { role: "button", tabIndex: 0, className: styles.entityCardContentButton, onClick: onSelect, onKeyDown: (event) => {
85
94
  if (event.key !== 'Enter' && event.key !== ' ')
86
95
  return;
87
96
  event.preventDefault();
88
97
  onSelect();
89
- }, "aria-pressed": selected, children: _jsx(PlanningEntitySummary, { item: initiative, entityType: "initiative", workstreamCount: workstreamCount, ownerOption: ownerOption, ownerOptions: ownerOptions, onChangeOwner: onChangeOwner }) }) })] }));
98
+ }, "aria-pressed": selected, children: _jsx(PlanningEntitySummary, { item: initiative, entityType: "initiative", workstreamCount: workstreamCount, ownerOption: ownerOption, ownerOptions: ownerOptions, onChangeOwner: onChangeOwner, onChangeIdentity: onChangeIdentity }) }) })] }));
90
99
  }
91
- function WorkstreamButton({ workstream, ownerOption, ownerOptions, selected, onSelect, onChangeOwner, referenceAction, feedback, }) {
100
+ function WorkstreamButton({ workstream, ownerOption, ownerOptions, selected, onSelect, onChangeOwner, onChangeIdentity, referenceAction, feedback, }) {
92
101
  const referenceLabel = formatWorkstreamReference(workstream);
93
102
  return (_jsxs("div", { className: `${styles.entityCard} ${workstream.isArchived ? styles.entityCardArchived : ''} ${selected ? styles.entityCardSelected : ''}`.trim(), children: [_jsxs("div", { className: styles.entityCardTopRow, children: [referenceAction, _jsx(PlanningReferenceBadge, { label: referenceLabel || 'Reference pending', entityType: "workstream", entityName: workstream.title, interactive: false, pending: !referenceLabel })] }), feedback, _jsx("div", { className: styles.entityCardBody, children: _jsx("div", { role: "button", tabIndex: 0, className: styles.entityCardContentButton, onClick: onSelect, onKeyDown: (event) => {
94
103
  if (event.key !== 'Enter' && event.key !== ' ')
95
104
  return;
96
105
  event.preventDefault();
97
106
  onSelect();
98
- }, "aria-pressed": selected, children: _jsx(PlanningEntitySummary, { item: workstream, entityType: "workstream", ownerOption: ownerOption, ownerOptions: ownerOptions, onChangeOwner: onChangeOwner }) }) })] }));
107
+ }, "aria-pressed": selected, children: _jsx(PlanningEntitySummary, { item: workstream, entityType: "workstream", ownerOption: ownerOption, ownerOptions: ownerOptions, onChangeOwner: onChangeOwner, onChangeIdentity: onChangeIdentity }) }) })] }));
99
108
  }
100
- function SelectedEntityContext({ item, entityType, ownerOptions, onChangeOwner, workspaceId, currentActorId, taskReferences, hydrationState, onRetryHydration, onAddContextFile, onRemoveContextFile, onUpdateContextCaption, onUpdate, onArchive, onUnarchive, referenceAction, relationshipActions, relationshipContent, }) {
109
+ function SelectedEntityContext({ item, entityType, ownerOptions, onChangeOwner, onChangeIdentity, workspaceId, currentActorId, taskReferences, hydrationState, onRetryHydration, onAddContextFile, onRemoveContextFile, onUpdateContextCaption, onUpdate, onArchive, onUnarchive, referenceAction, relationshipActions, relationshipContent, }) {
101
110
  const label = entityType === 'initiative' ? 'Initiative' : 'Workstream';
102
111
  const referenceLabel = entityType === 'initiative'
103
112
  ? formatInitiativeReference(item)
@@ -181,7 +190,9 @@ function SelectedEntityContext({ item, entityType, ownerOptions, onChangeOwner,
181
190
  setArchiveBusy(false);
182
191
  }
183
192
  };
184
- return (_jsxs("section", { className: `${styles.selectedEntityContext} ${item.isArchived ? styles.selectedEntityContextArchived : ''}`.trim(), "aria-label": `Selected ${label.toLowerCase()}`, "aria-busy": hydrationState?.status === 'loading', children: [_jsxs("div", { className: styles.selectedEntityReferenceRow, children: [_jsxs("div", { className: styles.selectedEntityReferenceIdentity, children: [referenceAction, _jsx(PlanningReferenceBadge, { label: referenceLabel || 'Reference pending', entityType: entityType, entityName: item.title, interactive: false, pending: !referenceLabel })] }), _jsxs("div", { className: styles.selectedEntityReferenceActions, children: [_jsx("span", { children: label }), relationshipActions, !isEditing && (onArchive || onUnarchive) ? (_jsx("button", { type: "button", className: "tf-control-icon", disabled: archiveBusy
193
+ return (_jsxs("section", { className: `${styles.selectedEntityContext} ${item.isArchived ? styles.selectedEntityContextArchived : ''}`.trim(), "aria-label": `Selected ${label.toLowerCase()}`, "aria-busy": hydrationState?.status === 'loading', children: [_jsxs("div", { className: styles.selectedEntityReferenceRow, children: [_jsxs("div", { className: styles.selectedEntityReferenceIdentity, children: [_jsx(PlanningVisualIdentity, { entityType: entityType, entityId: item.id, icon: item.icon, color: item.color, size: "detail", disabled: Boolean(item.isArchived), onChange: onChangeIdentity
194
+ ? (patch) => onChangeIdentity(entityType, item.id, patch)
195
+ : undefined }), referenceAction, _jsx(PlanningReferenceBadge, { label: referenceLabel || 'Reference pending', entityType: entityType, entityName: item.title, interactive: false, pending: !referenceLabel })] }), _jsxs("div", { className: styles.selectedEntityReferenceActions, children: [_jsx("span", { children: label }), relationshipActions, !isEditing && (onArchive || onUnarchive) ? (_jsx("button", { type: "button", className: "tf-control-icon", disabled: archiveBusy
185
196
  || archiveState.mode === 'blocked'
186
197
  || archiveState.mode === 'checking'
187
198
  || (archiveState.mode === 'archived' ? !onUnarchive : !onArchive), onClick: () => void handleArchiveAction(), "aria-label": archiveActionLabel, title: archiveActionLabel, "aria-expanded": archiveState.mode === 'ready'
@@ -212,7 +223,6 @@ export function PlanningModule({ model }) {
212
223
  const [showArchivedPlanning, setShowArchivedPlanning] = React.useState(false);
213
224
  const taskArrangeMode = model.taskArrangeMode || 'execution';
214
225
  const [createState, setCreateState] = React.useState(null);
215
- const [showParentLinkPicker, setShowParentLinkPicker] = React.useState(false);
216
226
  const [pendingUnlink, setPendingUnlink] = React.useState(null);
217
227
  const [relationshipRecovery, setRelationshipRecovery] = React.useState(null);
218
228
  const [isChangingRelationship, setIsChangingRelationship] = React.useState(false);
@@ -338,7 +348,6 @@ export function PlanningModule({ model }) {
338
348
  void model.hydrateEntity(selectedEntityType, selectedEntityId);
339
349
  }, [model.hydrateEntity, selectedEntityId, selectedEntityType]);
340
350
  React.useEffect(() => {
341
- setShowParentLinkPicker(false);
342
351
  setPendingUnlink(null);
343
352
  setRelationshipRecovery(null);
344
353
  setIsChangingRelationship(false);
@@ -423,7 +432,6 @@ export function PlanningModule({ model }) {
423
432
  const result = await model.assignWorkstreamToInitiative(selectedWorkstream.id, option.referenceLabel);
424
433
  if (result !== false) {
425
434
  setSelectedInitiativeId(option.id);
426
- setShowParentLinkPicker(false);
427
435
  }
428
436
  }
429
437
  finally {
@@ -500,12 +508,16 @@ export function PlanningModule({ model }) {
500
508
  return (_jsxs("main", { className: styles.module, "aria-label": "Planning workspace", "aria-busy": model.loadState.isRefreshing, children: [model.loadState.isRefreshing ? (_jsx("span", { className: styles.visuallyHidden, role: "status", "aria-live": "polite", children: "Refreshing planning" })) : null, (model.loadState.status === 'partial' || model.loadState.status === 'error') && (_jsxs("div", { className: styles.inlineError, role: "alert", children: [_jsx(AlertTriangle, { size: 16 }), _jsx("span", { children: model.loadState.error || 'Some planning information could not be loaded.' }), _jsx("button", { type: "button", className: "tf-button-secondary tf-button-compact", onClick: model.retry, children: "Retry" })] })), _jsxs("div", { className: styles.columns, "data-active-pane": activePane, children: [_jsxs("section", { className: `${styles.column} ${styles.columnPortfolio} ${activePane === 'portfolio' ? styles.columnActive : ''}`.trim(), "aria-labelledby": "planning-portfolio-heading", children: [_jsxs("div", { className: styles.columnHeader, children: [_jsx("h2", { ref: portfolioHeadingRef, id: "planning-portfolio-heading", className: `tf-heading-section ${styles.paneHeading}`, tabIndex: -1, children: "Portfolio" }), _jsxs("div", { className: styles.headerActions, children: [_jsx("span", { children: visibleInitiatives.length + visibleStandaloneWorkstreams.length }), _jsx("button", { type: "button", className: `tf-control-icon ${showArchivedPlanning ? styles.controlActive : ''}`.trim(), onClick: () => setShowArchivedPlanning((current) => !current), disabled: !hasArchivedPlanning, "aria-label": showArchivedPlanning ? 'Hide archived planning items' : 'Show archived planning items', "aria-pressed": showArchivedPlanning, title: hasArchivedPlanning ? (showArchivedPlanning ? 'Hide archived planning items' : 'Show archived planning items') : 'No archived planning items', children: showArchivedPlanning ? _jsx(EyeOff, { size: 15, "aria-hidden": "true" }) : _jsx(Eye, { size: 15, "aria-hidden": "true" }) })] })] }), _jsxs("div", { className: styles.portfolioControls, children: [_jsxs("div", { className: styles.searchRow, children: [_jsxs("div", { className: styles.searchShell, children: [_jsx(Search, { size: 14, "aria-hidden": "true" }), _jsx("input", { type: "search", value: searchQuery, onChange: (event) => setSearchQuery(event.target.value), placeholder: "Search initiatives and workstreams", "aria-label": "Search planning" }), searchQuery ? (_jsx("button", { type: "button", className: styles.clearSearch, onClick: () => setSearchQuery(''), "aria-label": "Clear planning search", title: "Clear search", children: _jsx(X, { size: 13, "aria-hidden": "true" }) })) : null] }), _jsx("button", { type: "button", className: `tf-control-icon ${filtersExpanded || ownerFilter !== 'all' || sort !== 'default' ? styles.controlActive : ''}`.trim(), "aria-label": "Filter and sort planning", title: "Filter and sort planning", "aria-expanded": filtersExpanded, "aria-controls": "planning-workspace-navigator-options", onClick: () => setFiltersExpanded((current) => !current), children: _jsx(Filter, { size: 15, "aria-hidden": "true" }) })] }), filtersExpanded ? (_jsxs("div", { id: "planning-workspace-navigator-options", className: styles.filterPanel, children: [_jsxs("div", { className: styles.filterField, children: [_jsx("span", { className: styles.filterLabel, children: "Owner" }), _jsx(PlanningOwnerDropdown, { value: ownerFilter, options: model.assigneeOptions, leadingOptions: ownerFilterLeadingOptions, includeUnassigned: false, onChange: setOwnerFilter, disabled: false, ariaLabel: "Filter planning by owner", className: styles.filterDropdown })] }), _jsxs("div", { className: styles.filterField, children: [_jsx("span", { className: styles.filterLabel, children: "Sort" }), _jsx(TaxonomyDropdown, { value: sort, options: PLANNING_NAVIGATOR_SORT_OPTIONS, onChange: (value) => setSort(String(value)), ariaLabel: "Sort planning", className: styles.filterDropdown, portalPanel: true, panelAlign: "start", triggerContent: (_jsxs("span", { className: styles.sortTrigger, children: [_jsx(ArrowUpDown, { size: 14, "aria-hidden": "true" }), _jsx("span", { children: PLANNING_NAVIGATOR_SORT_OPTIONS.find((option) => option.value === sort)?.label })] })), renderOptionContent: (option) => option.label })] }), _jsx("button", { type: "button", className: "tf-control-icon", onClick: clearNavigator, disabled: !hasAdjustedNavigator, "aria-label": "Reset planning filters and sort", title: "Reset planning filters and sort", children: _jsx(RotateCcw, { size: 14, "aria-hidden": "true" }) })] })) : null] }), _jsxs("div", { className: styles.scrollRegion, children: [_jsxs("div", { className: styles.sectionHeadingRow, children: [_jsx("h3", { className: `tf-heading-section ${styles.sectionLabel}`, children: "Initiatives" }), model.createEntity ? (_jsx("button", { type: "button", className: "tf-control-icon", onClick: () => setCreateState({ entityType: 'initiative' }), "aria-label": "Create initiative", title: "Create initiative", children: _jsx(Plus, { size: 15, "aria-hidden": "true" }) })) : null] }), createState?.entityType === 'initiative' ? (_jsx(PlanningWorkspaceEditor, { entityType: "initiative", mode: "create", ownerOptions: model.assigneeOptions, onCancel: () => setCreateState(null), onSave: createPlanningEntity })) : null, navigatorResults.initiatives.map(({ initiative, workstreams: resultWorkstreams }) => {
501
509
  return (_jsx(InitiativeButton, { initiative: initiative, workstreamCount: resultWorkstreams.length, ownerOption: initiative.ownerId ? assigneeOptionByValue.get(initiative.ownerId) : undefined, ownerOptions: model.assigneeOptions, selected: selectedInitiativeId === initiative.id, onSelect: () => selectInitiative(initiative.id), onChangeOwner: model.changeOwner
502
510
  ? (ownerId) => model.changeOwner?.('initiative', initiative.id, ownerId === 'unassigned' ? '' : ownerId)
511
+ : undefined, onChangeIdentity: model.changeIdentity
512
+ ? (patch) => model.changeIdentity?.('initiative', initiative.id, patch)
503
513
  : undefined }, initiative.id));
504
514
  }), _jsxs("div", { className: styles.sectionHeadingRow, children: [_jsx("h3", { className: `tf-heading-section ${styles.sectionLabel}`, children: "Standalone workstreams" }), model.createEntity ? (_jsx("button", { type: "button", className: "tf-control-icon", onClick: () => setCreateState({ entityType: 'workstream', initiativeId: null }), "aria-label": "Create standalone workstream", title: "Create standalone workstream", children: _jsx(Plus, { size: 15, "aria-hidden": "true" }) })) : null] }), createState?.entityType === 'workstream' && !createState.initiativeId ? (_jsx(PlanningWorkspaceEditor, { entityType: "workstream", mode: "create", ownerOptions: model.assigneeOptions, fixedInitiativeId: null, onCancel: () => setCreateState(null), onSave: createPlanningEntity })) : null, visibleStandaloneWorkstreams.map((workstream) => (_jsx(WorkstreamButton, { workstream: workstream, ownerOption: workstream.ownerId ? assigneeOptionByValue.get(workstream.ownerId) : undefined, ownerOptions: model.assigneeOptions, selected: selectedWorkstreamId === workstream.id, onSelect: () => selectWorkstream(workstream), onChangeOwner: model.changeOwner
505
515
  ? (ownerId) => model.changeOwner?.('workstream', workstream.id, ownerId === 'unassigned' ? '' : ownerId)
516
+ : undefined, onChangeIdentity: model.changeIdentity
517
+ ? (patch) => model.changeIdentity?.('workstream', workstream.id, patch)
506
518
  : undefined }, workstream.id))), visibleInitiatives.length === 0 && visibleStandaloneWorkstreams.length === 0 && (_jsx("p", { className: `tf-text-helper ${styles.empty}`, children: navigatorResults.hasCriteria ? 'No planning matches.' : 'No planning items yet.' }))] })] }), _jsxs("section", { className: `${styles.column} ${styles.columnWorkstreams} ${activePane === 'workstreams' ? styles.columnActive : ''}`.trim(), "aria-labelledby": "planning-workstreams-heading", children: [_jsxs("div", { className: styles.columnHeader, children: [_jsxs("div", { className: styles.columnHeadingGroup, children: [_jsx("button", { type: "button", className: `tf-control-icon ${styles.responsiveBack}`.trim(), onClick: () => navigateToPane('portfolio'), "aria-label": "Back to Portfolio", title: "Back to Portfolio", children: _jsx(ChevronLeft, { size: 15, "aria-hidden": "true" }) }), _jsxs("h2", { ref: workstreamsHeadingRef, id: "planning-workstreams-heading", className: `tf-heading-section ${styles.paneHeading}`, tabIndex: -1, children: ["Workstreams (", workstreams.length, ")"] })] }), _jsx("div", { className: styles.headerActions, children: selectedInitiative && model.createEntity ? (_jsx("button", { type: "button", className: "tf-control-icon", onClick: () => setCreateState({ entityType: 'workstream', initiativeId: selectedInitiative.id }), "aria-label": `Create workstream in ${selectedInitiative.title}`, title: "Create workstream", children: _jsx(Plus, { size: 15, "aria-hidden": "true" }) })) : null })] }), _jsxs("div", { className: styles.scrollRegion, children: [selectedInitiative ? (_jsxs(_Fragment, { children: [_jsx(SelectedEntityContext, { item: selectedInitiative, entityType: "initiative", ownerOptions: model.assigneeOptions, onChangeOwner: model.changeOwner
507
519
  ? (ownerId) => model.changeOwner?.('initiative', selectedInitiative.id, ownerId)
508
- : undefined, workspaceId: model.currentWorkspaceId, currentActorId: model.currentOwnerId, taskReferences: model.taskReferences, hydrationState: selectedWorkstream ? undefined : selectedEntityHydrationState, onRetryHydration: model.hydrateEntity
520
+ : undefined, onChangeIdentity: model.changeIdentity, workspaceId: model.currentWorkspaceId, currentActorId: model.currentOwnerId, taskReferences: model.taskReferences, hydrationState: selectedWorkstream ? undefined : selectedEntityHydrationState, onRetryHydration: model.hydrateEntity
509
521
  ? () => { void model.hydrateEntity?.('initiative', selectedInitiative.id); }
510
522
  : undefined, onAddContextFile: model.addContextFile, onRemoveContextFile: model.removeContextFile, onUpdateContextCaption: model.updateContextCaption, onUpdate: model.updateEntity
511
523
  ? (input) => model.updateEntity('initiative', selectedInitiative.id, input)
@@ -515,6 +527,8 @@ export function PlanningModule({ model }) {
515
527
  ? () => model.unarchiveEntity('initiative', selectedInitiative.id)
516
528
  : undefined }), _jsx(PlanningLinkPicker, { options: availableWorkstreamLinks, entityLabel: "workstream", onSelect: (option) => attachRelationship('workstream', option), disabled: !model.attachWorkstreamToInitiative || isChangingRelationship })] })) : null, createState?.entityType === 'workstream' && createState.initiativeId === selectedInitiative?.id ? (_jsx(PlanningWorkspaceEditor, { entityType: "workstream", mode: "create", ownerOptions: model.assigneeOptions, fixedInitiativeId: selectedInitiative.id, onCancel: () => setCreateState(null), onSave: createPlanningEntity })) : null, workstreams.map((workstream) => (_jsx(WorkstreamButton, { workstream: workstream, ownerOption: workstream.ownerId ? assigneeOptionByValue.get(workstream.ownerId) : undefined, ownerOptions: model.assigneeOptions, selected: selectedWorkstreamId === workstream.id, onSelect: () => selectWorkstream(workstream), onChangeOwner: model.changeOwner
517
529
  ? (ownerId) => model.changeOwner?.('workstream', workstream.id, ownerId === 'unassigned' ? '' : ownerId)
530
+ : undefined, onChangeIdentity: model.changeIdentity
531
+ ? (patch) => model.changeIdentity?.('workstream', workstream.id, patch)
518
532
  : undefined, referenceAction: selectedInitiative ? (_jsx(HierarchyActionBadge, { disabled: !model.assignWorkstreamToInitiative || isChangingRelationship, onClick: () => setPendingUnlink({
519
533
  entityType: 'workstream',
520
534
  id: workstream.id,
@@ -545,7 +559,7 @@ export function PlanningModule({ model }) {
545
559
  ? `${formatInitiativeReference(selectedInitiative)} ${selectedInitiative.title}`.trim()
546
560
  : 'its initiative',
547
561
  });
548
- }, title: "Unlink workstream from initiative", ariaLabel: "Unlink workstream from initiative", children: _jsx(Unlink, { size: 14, "aria-hidden": "true" }) })) : (_jsx(HierarchyActionBadge, { disabled: !model.assignWorkstreamToInitiative || isChangingRelationship, onClick: () => setShowParentLinkPicker((current) => !current), title: "Link initiative", ariaLabel: "Link initiative", ariaExpanded: showParentLinkPicker, children: _jsx(Link2, { size: 14, "aria-hidden": "true" }) })), relationshipContent: (_jsx(_Fragment, { children: !selectedWorkstream.initiativeId && showParentLinkPicker ? (_jsxs("div", { className: styles.relationshipPickerRow, children: [_jsx(PlanningLinkPicker, { options: model.linkOptions.initiatives, entityLabel: "initiative", onSelect: linkSelectedWorkstreamToInitiative, disabled: isChangingRelationship }), _jsx("button", { type: "button", className: "tf-control-icon tf-control-icon-compact", disabled: isChangingRelationship, onClick: () => setShowParentLinkPicker(false), title: "Cancel initiative link", "aria-label": "Cancel initiative link", children: _jsx(X, { size: 14, "aria-hidden": "true" }) })] })) : null })) }), _jsx(PlanningLinkPicker, { options: availableTaskLinks, entityLabel: "task", onSelect: (option) => attachRelationship('task', option), disabled: !model.attachTaskToWorkstream || isChangingRelationship }), model.setTaskArrangeMode ? (_jsx(PlanningTaskArrangeControl, { value: taskArrangeMode, onChange: model.setTaskArrangeMode })) : null] })) : null, _jsx(PlanningTaskOrderList, { tasks: visibleTasks, mode: taskArrangeMode, onReorder: selectedWorkstream && model.reorderWorkstreamTasks
562
+ }, title: "Unlink workstream from initiative", ariaLabel: "Unlink workstream from initiative", children: _jsx(Unlink, { size: 14, "aria-hidden": "true" }) })) : (_jsx(PlanningLinkPicker, { options: model.linkOptions.initiatives, entityLabel: "initiative", onSelect: linkSelectedWorkstreamToInitiative, disabled: !model.assignWorkstreamToInitiative || isChangingRelationship, iconTrigger: true, triggerTitle: "Link initiative" })) }), _jsx(PlanningLinkPicker, { options: availableTaskLinks, entityLabel: "task", onSelect: (option) => attachRelationship('task', option), disabled: !model.attachTaskToWorkstream || isChangingRelationship }), model.setTaskArrangeMode ? (_jsx(PlanningTaskArrangeControl, { value: taskArrangeMode, onChange: model.setTaskArrangeMode })) : null] })) : null, _jsx(PlanningTaskOrderList, { tasks: visibleTasks, mode: taskArrangeMode, onReorder: selectedWorkstream && model.reorderWorkstreamTasks
549
563
  ? (taskIds) => model.reorderWorkstreamTasks?.(selectedWorkstream.id, mergeVisiblePlanningTaskOrder(arrangePlanningTasks(selectedWorkstream.tasks ?? [], 'execution'), taskIds))
550
564
  : undefined, children: (task) => {
551
565
  const referenceLabel = getTaskReferenceLabel(task);
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import type { PlanningTaskPreview } from './planningWorkspaceModel';
3
- import type { PlanningTaskArrangeMode } from './planningTaskArrangement';
3
+ import { type PlanningTaskArrangeMode } from './planningTaskArrangement';
4
4
  export declare function PlanningTaskOrderList(props: {
5
5
  tasks: PlanningTaskPreview[];
6
6
  mode: PlanningTaskArrangeMode;
@@ -4,10 +4,14 @@ import { DndContext, KeyboardSensor, PointerSensor, closestCenter, useSensor, us
4
4
  import { SortableContext, arrayMove, sortableKeyboardCoordinates, useSortable, verticalListSortingStrategy, } from '@dnd-kit/sortable';
5
5
  import { CSS } from '@dnd-kit/utilities';
6
6
  import { GripVertical } from 'lucide-react';
7
+ import { isPlanningTaskTerminal } from './planningTaskArrangement';
7
8
  import styles from './PlanningTaskOrderList.module.css';
8
9
  function SortableTask(props) {
9
10
  const sortable = useSortable({ id: props.task.id, disabled: props.disabled });
10
- return (_jsxs("div", { ref: sortable.setNodeRef, className: styles.item, style: { transform: CSS.Transform.toString(sortable.transform), transition: sortable.transition }, children: [_jsx("button", { type: "button", className: styles.grip, disabled: props.disabled, "aria-label": `Reorder ${props.task.title}`, title: "Drag to change execution order", ...sortable.attributes, ...sortable.listeners, children: _jsx(GripVertical, { size: 15, "aria-hidden": "true" }) }), _jsx("div", { className: styles.card, children: props.children })] }));
11
+ const reorderLabel = props.disabledReason
12
+ ? `Reorder ${props.task.title} — ${props.disabledReason}`
13
+ : `Reorder ${props.task.title}`;
14
+ return (_jsxs("div", { ref: sortable.setNodeRef, className: styles.item, style: { transform: CSS.Transform.toString(sortable.transform), transition: sortable.transition }, children: [_jsx("button", { ref: sortable.setActivatorNodeRef, type: "button", className: styles.grip, disabled: props.disabled, "aria-label": reorderLabel, title: props.disabledReason || 'Drag to change execution order', ...sortable.attributes, ...sortable.listeners, children: _jsx(GripVertical, { size: 15, "aria-hidden": "true" }) }), _jsx("div", { className: styles.card, children: props.children })] }));
11
15
  }
12
16
  export function PlanningTaskOrderList(props) {
13
17
  const [orderedIds, setOrderedIds] = React.useState(() => props.tasks.map((task) => task.id));
@@ -19,7 +23,8 @@ export function PlanningTaskOrderList(props) {
19
23
  const byId = new Map(props.tasks.map((task) => [task.id, task]));
20
24
  return orderedIds.map((id) => byId.get(id)).filter((task) => Boolean(task));
21
25
  }, [orderedIds, props.tasks]);
22
- const draggable = props.mode === 'execution' && Boolean(props.onReorder);
26
+ const hasReorderAction = Boolean(props.onReorder);
27
+ const draggable = props.mode === 'execution' && hasReorderAction;
23
28
  const handleDragEnd = React.useCallback(async (event) => {
24
29
  if (!draggable || saving || !event.over || event.active.id === event.over.id)
25
30
  return;
@@ -29,8 +34,11 @@ export function PlanningTaskOrderList(props) {
29
34
  if (from < 0 || to < 0)
30
35
  return;
31
36
  const byId = new Map(orderedTasks.map((task) => [task.id, task]));
32
- const terminal = (task) => task?.status === 'done' || task?.status === 'cancelled';
33
- if (terminal(byId.get(previous[from])) !== terminal(byId.get(previous[to])))
37
+ const sourceTask = byId.get(previous[from]);
38
+ const targetTask = byId.get(previous[to]);
39
+ if (!sourceTask || !targetTask)
40
+ return;
41
+ if (isPlanningTaskTerminal(sourceTask) !== isPlanningTaskTerminal(targetTask))
34
42
  return;
35
43
  const next = arrayMove(previous, from, to);
36
44
  setOrderedIds(next);
@@ -45,8 +53,11 @@ export function PlanningTaskOrderList(props) {
45
53
  setSaving(false);
46
54
  }
47
55
  }, [draggable, orderedIds, orderedTasks, props, saving]);
48
- if (!draggable) {
56
+ if (!hasReorderAction) {
49
57
  return _jsx("div", { className: `${styles.list} ${props.className || ''}`.trim(), children: props.tasks.map((task) => (_jsx(React.Fragment, { children: props.children(task) }, task.id))) });
50
58
  }
51
- return (_jsx(DndContext, { sensors: sensors, collisionDetection: closestCenter, onDragEnd: (event) => void handleDragEnd(event), children: _jsx(SortableContext, { items: orderedIds, strategy: verticalListSortingStrategy, children: _jsx("div", { className: `${styles.list} ${props.className || ''}`.trim(), "aria-busy": saving || undefined, children: orderedTasks.map((task) => (_jsx(SortableTask, { task: task, disabled: saving, children: props.children(task) }, task.id))) }) }) }));
59
+ const disabledReason = props.mode === 'execution'
60
+ ? undefined
61
+ : 'Switch to Execution order to reorder tasks';
62
+ return (_jsx(DndContext, { sensors: sensors, collisionDetection: closestCenter, onDragEnd: (event) => void handleDragEnd(event), children: _jsx(SortableContext, { items: orderedIds, strategy: verticalListSortingStrategy, children: _jsx("div", { className: `${styles.list} ${props.className || ''}`.trim(), "aria-busy": saving || undefined, children: orderedTasks.map((task) => (_jsx(SortableTask, { task: task, disabled: !draggable || saving, disabledReason: disabledReason || (saving ? 'Saving execution order' : undefined), children: props.children(task) }, task.id))) }) }) }));
52
63
  }
@@ -0,0 +1,14 @@
1
+ import { type PlanningIdentityColor, type PlanningIdentityEntityType, type PlanningIdentityIcon } from '../../../shared/planningIdentity';
2
+ export type PlanningIdentityPatch = {
3
+ icon?: PlanningIdentityIcon | null;
4
+ color?: PlanningIdentityColor | null;
5
+ };
6
+ export declare function PlanningVisualIdentity({ entityType, entityId, icon, color, disabled, size, onChange, }: {
7
+ entityType: PlanningIdentityEntityType;
8
+ entityId: string;
9
+ icon?: PlanningIdentityIcon | null;
10
+ color?: PlanningIdentityColor | null;
11
+ disabled?: boolean;
12
+ size?: 'card' | 'inline' | 'detail';
13
+ onChange?: (patch: PlanningIdentityPatch) => void | Promise<void>;
14
+ }): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,106 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import React from 'react';
3
+ import { createPortal } from 'react-dom';
4
+ import { BookOpen, Briefcase, Bug, Camera, Code, Compass, Flag, FlaskConical, Folder, Globe, Heart, Landmark, Layers, Lightbulb, Map, Music, Palette, Rocket, Route, Shield, Sparkles, Target, Users, Wrench, } from 'lucide-react';
5
+ import { PLANNING_IDENTITY_COLORS, PLANNING_IDENTITY_ICONS, planningIdentityColorToken, resolvePlanningIdentity, } from '../../../shared/planningIdentity';
6
+ import styles from './PlanningVisualIdentity.module.css';
7
+ const ICONS = {
8
+ Target, Route, Flag, Rocket, Briefcase, Folder, Layers, Map, Compass, Landmark,
9
+ BookOpen, Lightbulb, Wrench, Shield, Bug, Palette, Camera, Music, Heart, Globe,
10
+ Users, Sparkles, FlaskConical, Code,
11
+ };
12
+ export function PlanningVisualIdentity({ entityType, entityId, icon, color, disabled = false, size = 'card', onChange, }) {
13
+ const [open, setOpen] = React.useState(false);
14
+ const [pending, setPending] = React.useState(false);
15
+ const [optimisticPatch, setOptimisticPatch] = React.useState(null);
16
+ const [portalTheme, setPortalTheme] = React.useState();
17
+ const [popoverPosition, setPopoverPosition] = React.useState({ top: 0, left: 0 });
18
+ const rootRef = React.useRef(null);
19
+ const triggerRef = React.useRef(null);
20
+ const popoverRef = React.useRef(null);
21
+ const optimisticIcon = optimisticPatch && Object.prototype.hasOwnProperty.call(optimisticPatch, 'icon')
22
+ ? optimisticPatch.icon
23
+ : icon;
24
+ const optimisticColor = optimisticPatch && Object.prototype.hasOwnProperty.call(optimisticPatch, 'color')
25
+ ? optimisticPatch.color
26
+ : color;
27
+ const resolved = resolvePlanningIdentity({
28
+ entityType,
29
+ entityId,
30
+ icon: optimisticIcon,
31
+ color: optimisticColor,
32
+ });
33
+ const Icon = ICONS[resolved.icon];
34
+ const editable = !disabled && Boolean(onChange);
35
+ React.useEffect(() => {
36
+ if (!open)
37
+ return undefined;
38
+ const close = (event) => {
39
+ const target = event.target;
40
+ if (!rootRef.current?.contains(target) && !popoverRef.current?.contains(target))
41
+ setOpen(false);
42
+ };
43
+ document.addEventListener('pointerdown', close);
44
+ return () => document.removeEventListener('pointerdown', close);
45
+ }, [open]);
46
+ React.useLayoutEffect(() => {
47
+ if (!open)
48
+ return undefined;
49
+ const positionPopover = () => {
50
+ const triggerRect = triggerRef.current?.getBoundingClientRect();
51
+ if (!triggerRect)
52
+ return;
53
+ setPortalTheme(triggerRef.current?.closest('[data-theme]')?.dataset.theme);
54
+ const popoverRect = popoverRef.current?.getBoundingClientRect();
55
+ const width = popoverRect?.width || 248;
56
+ const height = popoverRect?.height || 320;
57
+ const gap = 8;
58
+ const viewportPadding = 8;
59
+ const left = Math.max(viewportPadding, Math.min(triggerRect.left, window.innerWidth - width - viewportPadding));
60
+ const preferredTop = triggerRect.bottom + gap;
61
+ const top = preferredTop + height <= window.innerHeight - viewportPadding
62
+ ? preferredTop
63
+ : Math.max(viewportPadding, triggerRect.top - height - gap);
64
+ setPopoverPosition({ top, left });
65
+ };
66
+ positionPopover();
67
+ window.addEventListener('resize', positionPopover);
68
+ window.addEventListener('scroll', positionPopover, true);
69
+ return () => {
70
+ window.removeEventListener('resize', positionPopover);
71
+ window.removeEventListener('scroll', positionPopover, true);
72
+ };
73
+ }, [open]);
74
+ React.useEffect(() => {
75
+ if (!optimisticPatch)
76
+ return;
77
+ const iconSettled = !Object.prototype.hasOwnProperty.call(optimisticPatch, 'icon')
78
+ || (optimisticPatch.icon ?? null) === (icon ?? null);
79
+ const colorSettled = !Object.prototype.hasOwnProperty.call(optimisticPatch, 'color')
80
+ || (optimisticPatch.color ?? null) === (color ?? null);
81
+ if (iconSettled && colorSettled)
82
+ setOptimisticPatch(null);
83
+ }, [color, icon, optimisticPatch]);
84
+ const commit = async (patch) => {
85
+ if (!onChange || pending)
86
+ return;
87
+ setOptimisticPatch((current) => ({ ...current, ...patch }));
88
+ setPending(true);
89
+ try {
90
+ await onChange(patch);
91
+ }
92
+ catch {
93
+ setOptimisticPatch(null);
94
+ }
95
+ finally {
96
+ setPending(false);
97
+ }
98
+ };
99
+ const marker = (_jsx("span", { className: `${styles.marker} ${styles[size]} ${disabled ? styles.disabled : ''}`.trim(), style: { color: planningIdentityColorToken(resolved.color) }, "aria-hidden": "true", children: _jsx(Icon, { size: size === 'detail' ? 26 : size === 'inline' ? 18 : 24, strokeWidth: 1.9 }) }));
100
+ if (!editable)
101
+ return marker;
102
+ return (_jsxs("div", { ref: rootRef, className: styles.root, onClick: (event) => event.stopPropagation(), children: [_jsx("button", { ref: triggerRef, type: "button", className: styles.trigger, onClick: () => setOpen((current) => !current), onKeyDown: (event) => event.stopPropagation(), "aria-label": `Change ${entityType} icon and color`, "aria-expanded": open, disabled: pending, children: marker }), open ? createPortal((_jsxs("div", { ref: popoverRef, className: styles.popover, role: "dialog", "aria-label": `${entityType} icon and color`, "aria-busy": pending, "data-theme": portalTheme, style: popoverPosition, onClick: (event) => event.stopPropagation(), onKeyDown: (event) => event.stopPropagation(), children: [_jsx("div", { className: styles.colorGrid, "aria-label": "Colors", children: PLANNING_IDENTITY_COLORS.map((option) => (_jsx("button", { type: "button", className: `${styles.colorOption} ${resolved.color === option ? styles.selected : ''}`.trim(), style: { backgroundColor: planningIdentityColorToken(option) }, onClick: () => void commit({ color: option }), "aria-label": `${option} color`, "aria-pressed": resolved.color === option, disabled: pending }, option))) }), _jsx("div", { className: styles.divider }), _jsx("div", { className: styles.iconGrid, "aria-label": "Icons", children: PLANNING_IDENTITY_ICONS.map((option) => {
103
+ const OptionIcon = ICONS[option];
104
+ return (_jsx("button", { type: "button", className: `${styles.iconOption} ${resolved.icon === option ? styles.selected : ''}`.trim(), onClick: () => void commit({ icon: option }), "aria-label": option, "aria-pressed": resolved.icon === option, disabled: pending, children: _jsx(OptionIcon, { size: 18, strokeWidth: 1.8 }) }, option));
105
+ }) }), _jsx("div", { className: styles.divider }), _jsx("button", { type: "button", className: styles.reset, onClick: () => void commit({ icon: null, color: null }), disabled: !resolved.customized || pending, children: "Reset to default" })] })), document.body) : null] }));
106
+ }
@@ -15,4 +15,5 @@ export declare const PLANNING_TASK_ARRANGE_OPTIONS: readonly ({
15
15
  })[];
16
16
  export declare function normalizePlanningTaskArrangeMode(value: unknown): PlanningTaskArrangeMode;
17
17
  export declare function mergeVisiblePlanningTaskOrder(allTasks: readonly PlanningTaskPreview[], reorderedVisibleTaskIds: readonly string[]): string[];
18
+ export declare function isPlanningTaskTerminal(task: PlanningTaskPreview): boolean;
18
19
  export declare function arrangePlanningTasks(tasks: readonly PlanningTaskPreview[], mode: PlanningTaskArrangeMode): PlanningTaskPreview[];
@@ -19,7 +19,7 @@ export function mergeVisiblePlanningTaskOrder(allTasks, reorderedVisibleTaskIds)
19
19
  let visibleIndex = 0;
20
20
  return allTasks.map((task) => (visible.has(task.id) ? reorderedVisibleTaskIds[visibleIndex++] : task.id));
21
21
  }
22
- function isTerminal(task) {
22
+ export function isPlanningTaskTerminal(task) {
23
23
  const status = getStatusDefinition(task.status).value;
24
24
  return status === 'done' || status === 'cancelled';
25
25
  }
@@ -50,7 +50,7 @@ function arrangeBlockedTasks(tasks, allTasksById) {
50
50
  for (const task of tasks) {
51
51
  for (const prerequisiteId of task.prerequisiteTaskIds || []) {
52
52
  const prerequisite = allTasksById.get(prerequisiteId);
53
- if (!prerequisite || isTerminal(prerequisite) || !taskIds.has(prerequisiteId))
53
+ if (!prerequisite || isPlanningTaskTerminal(prerequisite) || !taskIds.has(prerequisiteId))
54
54
  continue;
55
55
  dependentsByPrerequisite.set(prerequisiteId, [
56
56
  ...(dependentsByPrerequisite.get(prerequisiteId) || []),
@@ -85,15 +85,15 @@ function arrangeBlockedTasks(tasks, allTasksById) {
85
85
  export function arrangePlanningTasks(tasks, mode) {
86
86
  const taskById = new Map(tasks.map((task) => [task.id, task]));
87
87
  if (mode === 'ready') {
88
- const active = tasks.filter((task) => !isTerminal(task));
88
+ const active = tasks.filter((task) => !isPlanningTaskTerminal(task));
89
89
  const ready = sortByExecutionOrder(active.filter((task) => isReady(task, taskById)));
90
90
  const blocked = arrangeBlockedTasks(active.filter((task) => !isReady(task, taskById)), taskById);
91
- return [...ready, ...blocked, ...sortByExecutionOrder(tasks.filter(isTerminal))];
91
+ return [...ready, ...blocked, ...sortByExecutionOrder(tasks.filter(isPlanningTaskTerminal))];
92
92
  }
93
93
  return tasks.map((task, index) => ({ task, index })).sort((leftEntry, rightEntry) => {
94
94
  const left = leftEntry.task;
95
95
  const right = rightEntry.task;
96
- const terminalComparison = Number(isTerminal(left)) - Number(isTerminal(right));
96
+ const terminalComparison = Number(isPlanningTaskTerminal(left)) - Number(isPlanningTaskTerminal(right));
97
97
  if (terminalComparison)
98
98
  return terminalComparison;
99
99
  if (mode === 'priority') {
@@ -3,6 +3,7 @@ import type { TaskAssigneeOption } from '../../../utils/assignees';
3
3
  import type { TaskReferenceContract } from '../../../utils/taskReferences';
4
4
  import type { TaskforceTheme } from '../../../utils/theme';
5
5
  import type { PlanningTaskArrangeMode } from './planningTaskArrangement';
6
+ import type { PlanningIdentityColor, PlanningIdentityIcon } from '../../../shared/planningIdentity';
6
7
  export type PlanningStatusCounts = Record<TaskStatus, number>;
7
8
  export declare function shouldUsePlanningBootstrapTaskSummaries(input: {
8
9
  taskScope: 'open' | 'archived' | 'deleted';
@@ -34,6 +35,8 @@ export type PlanningNodeSummary = {
34
35
  description?: string;
35
36
  ownerId?: string | null;
36
37
  ownerLabel?: string | null;
38
+ icon?: PlanningIdentityIcon | null;
39
+ color?: PlanningIdentityColor | null;
37
40
  progressPercent: number;
38
41
  taskCount: number;
39
42
  completedTaskCount: number;
@@ -67,12 +70,16 @@ export type PlanningEntitySaveInput = {
67
70
  description: string | null;
68
71
  ownerId?: string | null;
69
72
  initiativeId?: string | null;
73
+ icon?: PlanningIdentityIcon | null;
74
+ color?: PlanningIdentityColor | null;
70
75
  };
71
76
  export type PlanningLinkOption = {
72
77
  id: string;
73
78
  referenceLabel: string;
74
79
  title: string;
75
80
  meta?: string;
81
+ icon?: PlanningIdentityIcon | null;
82
+ color?: PlanningIdentityColor | null;
76
83
  };
77
84
  export type PlanningLinkOptions = {
78
85
  initiatives: PlanningLinkOption[];
@@ -107,6 +114,10 @@ export type PlanningWorkspaceModel = {
107
114
  archiveEntity?: (entityType: 'initiative' | 'workstream', entityId: string) => boolean | Promise<boolean>;
108
115
  unarchiveEntity?: (entityType: 'initiative' | 'workstream', entityId: string) => boolean | Promise<boolean>;
109
116
  changeOwner?: (entityType: 'initiative' | 'workstream', entityId: string, ownerId: string) => void | Promise<void>;
117
+ changeIdentity?: (entityType: 'initiative' | 'workstream', entityId: string, patch: {
118
+ icon?: PlanningIdentityIcon | null;
119
+ color?: PlanningIdentityColor | null;
120
+ }) => void | Promise<void>;
110
121
  createEntity?: (entityType: 'initiative' | 'workstream', input: PlanningEntitySaveInput) => Promise<{
111
122
  id: string;
112
123
  }>;
@@ -96,6 +96,7 @@ export function buildTaskforceAgentDefinitionFromDraft(input) {
96
96
  const artStyle = selectedAvatarArtStyle(draft.avatarArtStyleSelection, draft.avatarArtStyleCustom);
97
97
  const requestedCapabilities = draft.requestedCapabilities
98
98
  .filter((capability) => DEFAULT_AGENT_TOOL_CAPABILITY_SET.has(capability));
99
+ const selectedModel = getTaskforceAgentModel(input.modelKey);
99
100
  return {
100
101
  ...(baseDefinition || {}),
101
102
  schemaVersion: AGENT_DEFINITION_SCHEMA_VERSION,
@@ -104,8 +105,9 @@ export function buildTaskforceAgentDefinitionFromDraft(input) {
104
105
  model: {
105
106
  providerKey: input.providerKey,
106
107
  modelKey: input.modelKey,
107
- modelSource: getTaskforceAgentModel(input.modelKey)?.source || 'bedrock',
108
+ modelSource: selectedModel?.source || 'bedrock',
108
109
  tier: input.tier,
110
+ ...(selectedModel?.source === 'subscription_dev' ? { connectionScope: 'local_dev' } : {}),
109
111
  },
110
112
  behavior: {
111
113
  ...(personality ? { personality } : {}),
@@ -4,6 +4,7 @@ import type { TaskAutoSaveState } from '../../hooks/tasks/useTaskFormActions';
4
4
  interface TaskActionHeaderProps {
5
5
  editingTaskId: string | null;
6
6
  loading: boolean;
7
+ submitDisabled?: boolean;
7
8
  autoSaveState?: TaskAutoSaveState;
8
9
  title: string;
9
10
  status?: TaskStatus;
@@ -30,5 +31,5 @@ interface TaskActionHeaderProps {
30
31
  handlePermanentlyDeleteDeletedTask?: (deletedRecordId: string) => void;
31
32
  onAskAgent?: (task: TaskItem) => void;
32
33
  }
33
- export declare function TaskActionHeader({ editingTaskId, loading, autoSaveState, title, status, onStatusChange, showCreateSubmit, handleSubmit, handleCopyId, copiedId, tasks, currentTask: currentTaskProp, currentTaskWorkstream, currentTaskInitiative, workstreams, onWorkstreamInputChange, onSetWorkstreamForCurrentTask, handleToggleInProgress, handleToggleReview, handleToggleComplete, handleToggleCancel, handleSetStatus, handleArchiveTask, handleUnarchiveTask, handleRestoreDeletedTask, handlePermanentlyDeleteDeletedTask, onAskAgent }: TaskActionHeaderProps): import("react/jsx-runtime").JSX.Element;
34
+ export declare function TaskActionHeader({ editingTaskId, loading, submitDisabled, autoSaveState, title, status, onStatusChange, showCreateSubmit, handleSubmit, handleCopyId, copiedId, tasks, currentTask: currentTaskProp, currentTaskWorkstream, currentTaskInitiative, workstreams, onWorkstreamInputChange, onSetWorkstreamForCurrentTask, handleToggleInProgress, handleToggleReview, handleToggleComplete, handleToggleCancel, handleSetStatus, handleArchiveTask, handleUnarchiveTask, handleRestoreDeletedTask, handlePermanentlyDeleteDeletedTask, onAskAgent }: TaskActionHeaderProps): import("react/jsx-runtime").JSX.Element;
34
35
  export {};
@@ -9,7 +9,7 @@ import { TaskReferenceBadge } from './TaskReferenceBadge';
9
9
  import { HierarchyActionBadge } from '../ui/HierarchyActionBadge';
10
10
  import { formatInitiativeReference, getWorkstreamReferenceLabel } from '../../utils/planningReferences';
11
11
  import { TaskWorkstreamPicker } from './TaskWorkstreamPicker';
12
- export function TaskActionHeader({ editingTaskId, loading, autoSaveState = 'idle', title, status = 'task', onStatusChange, showCreateSubmit = true, handleSubmit, handleCopyId, copiedId, tasks, currentTask: currentTaskProp, currentTaskWorkstream, currentTaskInitiative, workstreams = [], onWorkstreamInputChange, onSetWorkstreamForCurrentTask, handleToggleInProgress, handleToggleReview, handleToggleComplete, handleToggleCancel, handleSetStatus, handleArchiveTask, handleUnarchiveTask, handleRestoreDeletedTask, handlePermanentlyDeleteDeletedTask, onAskAgent }) {
12
+ export function TaskActionHeader({ editingTaskId, loading, submitDisabled = false, autoSaveState = 'idle', title, status = 'task', onStatusChange, showCreateSubmit = true, handleSubmit, handleCopyId, copiedId, tasks, currentTask: currentTaskProp, currentTaskWorkstream, currentTaskInitiative, workstreams = [], onWorkstreamInputChange, onSetWorkstreamForCurrentTask, handleToggleInProgress, handleToggleReview, handleToggleComplete, handleToggleCancel, handleSetStatus, handleArchiveTask, handleUnarchiveTask, handleRestoreDeletedTask, handlePermanentlyDeleteDeletedTask, onAskAgent }) {
13
13
  const currentTask = currentTaskProp ?? (editingTaskId ? tasks.find(t => t.id === editingTaskId) || null : null);
14
14
  const isArchivedReadOnly = Boolean(currentTask?.isArchived);
15
15
  const isDeletedReadOnly = Boolean(currentTask?.isDeleted);
@@ -67,5 +67,5 @@ export function TaskActionHeader({ editingTaskId, loading, autoSaveState = 'idle
67
67
  if (status === 'cancelled') {
68
68
  handleToggleCancel(task);
69
69
  }
70
- }, onArchiveTask: handleArchiveTask, onUnarchiveTask: (task) => handleUnarchiveTask?.(task.id) }))] })] })) : (_jsxs(_Fragment, { children: [_jsx("div", { className: styles.taskSaveStatusCenter }), _jsxs("div", { className: styles.editActionsGroup, children: [_jsx(TaskStatusActions, { status: status, disabled: loading, archiveActionMode: "none", onStatusChange: onStatusChange }), showCreateSubmit ? (_jsxs("button", { type: "button", onClick: (e) => handleSubmit(e), disabled: loading || !title.trim(), className: styles.primaryUpdateBtn, title: t('actionHeader.addTaskTitle'), children: [loading ? _jsx(Loader2, { size: 16, className: styles.spinner }) : _jsx(Plus, { size: 16 }), t('actionHeader.addTask')] })) : null] })] }))] }));
70
+ }, onArchiveTask: handleArchiveTask, onUnarchiveTask: (task) => handleUnarchiveTask?.(task.id) }))] })] })) : (_jsxs(_Fragment, { children: [_jsx("div", { className: styles.taskSaveStatusCenter }), _jsxs("div", { className: styles.editActionsGroup, children: [_jsx(TaskStatusActions, { status: status, disabled: loading, archiveActionMode: "none", onStatusChange: onStatusChange }), showCreateSubmit ? (_jsxs("button", { type: "button", onClick: (e) => handleSubmit(e), disabled: loading || submitDisabled || !title.trim(), className: styles.primaryUpdateBtn, title: t('actionHeader.addTaskTitle'), children: [loading ? _jsx(Loader2, { size: 16, className: styles.spinner }) : _jsx(Plus, { size: 16 }), t('actionHeader.addTask')] })) : null] })] }))] }));
71
71
  }
@@ -48,6 +48,11 @@ interface TaskCardProps {
48
48
  onWorkstreamChange?: (task: TaskItem, workstreamId: string | null) => boolean | void | Promise<boolean | void>;
49
49
  compressed?: boolean;
50
50
  showStatusLabel?: boolean;
51
+ showDescription?: boolean;
52
+ showAttachments?: boolean;
53
+ showChecklistProgress?: boolean;
54
+ showLatestActivity?: boolean;
55
+ tintActivityBackground?: boolean;
51
56
  }
52
57
  export declare const TaskCard: React.NamedExoticComponent<TaskCardProps>;
53
58
  export {};