@taskforcehq/taskforce 0.3.305 → 0.3.307

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 (440) hide show
  1. package/README.md +0 -2
  2. package/dist/Taskforce.module.css +603 -107
  3. package/dist/TaskforceCore.js +216 -43
  4. package/dist/TaskforceCore.test.js +611 -28
  5. package/dist/assets/fonts/CourierPrime-Bold.woff2 +0 -0
  6. package/dist/assets/fonts/CourierPrime-BoldItalic.woff2 +0 -0
  7. package/dist/assets/fonts/CourierPrime-Italic.woff2 +0 -0
  8. package/dist/assets/fonts/CourierPrime-Regular.woff2 +0 -0
  9. package/dist/assets/fonts/Noir_medium.woff2 +0 -0
  10. package/dist/assets/fonts/Noir_regular.woff2 +0 -0
  11. package/dist/assets/fonts/RussoOne-Regular.woff2 +0 -0
  12. package/dist/assets/fonts/SpecialElite-Regular.woff2 +0 -0
  13. package/dist/compat/workspaceSyncCompat.js +46 -2
  14. package/dist/compat/workspaceSyncCompat.test.js +38 -1
  15. package/dist/components/activity/EntityActivityTimeline.d.ts +34 -0
  16. package/dist/components/activity/EntityActivityTimeline.js +81 -0
  17. package/dist/components/context/ContextAttachmentManager.d.ts +14 -0
  18. package/dist/components/context/ContextAttachmentManager.js +561 -0
  19. package/dist/components/features/AgentsModule.d.ts +14 -1
  20. package/dist/components/features/AgentsModule.js +366 -18
  21. package/dist/components/features/AgentsModule.test.js +507 -8
  22. package/dist/components/features/AnnotatedAttachmentWorkspace.d.ts +3 -1
  23. package/dist/components/features/AnnotatedAttachmentWorkspace.js +118 -4
  24. package/dist/components/features/AnnotatedAttachmentWorkspace.test.js +52 -0
  25. package/dist/components/features/DocumentIndex.d.ts +2 -2
  26. package/dist/components/features/DocumentIndex.js +3 -4
  27. package/dist/components/features/DocumentViewer.d.ts +7 -1
  28. package/dist/components/features/DocumentViewer.js +62 -4
  29. package/dist/components/features/DocumentWorkspace.d.ts +10 -2
  30. package/dist/components/features/DocumentWorkspace.js +15 -4
  31. package/dist/components/features/DocumentWorkspace.test.js +51 -1
  32. package/dist/components/features/TaskSettings.d.ts +2 -0
  33. package/dist/components/features/TaskSettings.js +83 -78
  34. package/dist/components/features/TaskSettings.test.js +171 -82
  35. package/dist/components/features/documentWorkspaceModel.d.ts +1 -1
  36. package/dist/components/task/TaskActionHeader.js +11 -5
  37. package/dist/components/task/TaskActionHeader.test.js +10 -0
  38. package/dist/components/task/TaskCard.js +24 -29
  39. package/dist/components/task/TaskCard.test.js +38 -3
  40. package/dist/components/task/TaskContextUpload.js +4 -526
  41. package/dist/components/task/TaskContextUpload.test.js +3 -3
  42. package/dist/components/task/TaskForm.js +61 -116
  43. package/dist/components/task/TaskForm.test.js +110 -8
  44. package/dist/components/task/TaskKanban.d.ts +2 -1
  45. package/dist/components/task/TaskKanban.js +94 -21
  46. package/dist/components/task/TaskKanban.test.js +36 -0
  47. package/dist/components/task/TaskList.js +5 -1
  48. package/dist/components/task/TaskList.test.js +4 -0
  49. package/dist/components/ui/EditableAvatarButton.d.ts +18 -0
  50. package/dist/components/ui/EditableAvatarButton.js +18 -0
  51. package/dist/components/ui/HierarchyActionBadge.d.ts +10 -0
  52. package/dist/components/ui/HierarchyActionBadge.js +5 -0
  53. package/dist/components/views/AppShellHeader.d.ts +3 -1
  54. package/dist/components/views/AppShellHeader.js +27 -11
  55. package/dist/components/views/AppShellHeader.test.js +18 -1
  56. package/dist/components/views/PlanComparisonPage.d.ts +9 -1
  57. package/dist/components/views/PlanComparisonPage.js +78 -14
  58. package/dist/components/views/PlanComparisonPage.test.js +257 -0
  59. package/dist/components/views/PlansPage.js +127 -36
  60. package/dist/components/views/PlansPage.test.js +294 -12
  61. package/dist/components/views/StandaloneLayout.js +529 -592
  62. package/dist/components/views/WidgetView.js +10 -8
  63. package/dist/components/views/panels/PlanningDrawer.d.ts +25 -5
  64. package/dist/components/views/panels/PlanningDrawer.js +270 -55
  65. package/dist/components/views/panels/PlanningDrawer.test.d.ts +1 -0
  66. package/dist/components/views/panels/PlanningDrawer.test.js +529 -0
  67. package/dist/components/views/planningScope.d.ts +20 -0
  68. package/dist/components/views/planningScope.js +25 -0
  69. package/dist/components/views/planningScope.test.d.ts +1 -0
  70. package/dist/components/views/planningScope.test.js +60 -0
  71. package/dist/components/views/standalone/modals/AccountHubModal.d.ts +26 -1
  72. package/dist/components/views/standalone/modals/AccountHubModal.js +76 -2
  73. package/dist/components/views/standalone/modals/AccountHubModal.test.js +20 -3
  74. package/dist/components/views/standalone/modals/AvatarImageManagerModal.d.ts +20 -0
  75. package/dist/components/views/standalone/modals/AvatarImageManagerModal.js +127 -0
  76. package/dist/components/views/standalone/modals/EditProfileModal.d.ts +2 -9
  77. package/dist/components/views/standalone/modals/EditProfileModal.js +3 -2
  78. package/dist/components/views/standalone/modals/SyncEnableWarningModal.d.ts +9 -0
  79. package/dist/components/views/standalone/modals/SyncEnableWarningModal.js +6 -0
  80. package/dist/components/views/standalone/modals/SyncEnableWarningModal.test.d.ts +1 -0
  81. package/dist/components/views/standalone/modals/SyncEnableWarningModal.test.js +24 -0
  82. package/dist/components/views/standalone/modals/SyncStatusModal.d.ts +2 -1
  83. package/dist/components/views/standalone/modals/SyncStatusModal.js +2 -2
  84. package/dist/config/envSchema.js +1 -0
  85. package/dist/core/AiProfileService.d.ts +46 -2
  86. package/dist/core/AiProfileService.js +1073 -82
  87. package/dist/core/AiProfileService.test.js +19 -1
  88. package/dist/core/AiProfiles.test.js +1249 -44
  89. package/dist/core/AttachmentLinkService.d.ts +3 -0
  90. package/dist/core/AttachmentLinkService.js +110 -23
  91. package/dist/core/AuthIdentityService.d.ts +107 -0
  92. package/dist/core/AuthIdentityService.js +284 -0
  93. package/dist/core/AuthTokenService.d.ts +4 -0
  94. package/dist/core/AuthTokenService.js +34 -6
  95. package/dist/core/AuthTokenService.test.js +3 -3
  96. package/dist/core/EntitlementsPolicy.test.js +2 -2
  97. package/dist/core/GlobalSettingsService.js +127 -6
  98. package/dist/core/McpTokenService.d.ts +12 -0
  99. package/dist/core/McpTokenService.js +44 -1
  100. package/dist/core/PlanEntitlementService.d.ts +23 -2
  101. package/dist/core/PlanEntitlementService.js +343 -57
  102. package/dist/core/PlanFeatureCatalog.test.d.ts +1 -0
  103. package/dist/core/PlanFeatureCatalog.test.js +84 -0
  104. package/dist/core/PlanVersionPolicy.test.js +35 -2
  105. package/dist/core/PlanningEntities.test.js +418 -4
  106. package/dist/core/SignupMonetizationSettings.test.js +199 -27
  107. package/dist/core/SyncReconciliationService.js +2 -65
  108. package/dist/core/SystemAdmin.test.js +42 -42
  109. package/dist/core/TaskActivityService.d.ts +28 -1
  110. package/dist/core/TaskActivityService.js +227 -46
  111. package/dist/core/TaskActivitySync.test.d.ts +1 -0
  112. package/dist/core/TaskActivitySync.test.js +90 -0
  113. package/dist/core/TaskAttachmentsCanonical.test.js +51 -1
  114. package/dist/core/TaskAuditTimeline.test.js +96 -0
  115. package/dist/core/Taskforce.d.ts +415 -40
  116. package/dist/core/Taskforce.ids.test.js +58 -0
  117. package/dist/core/Taskforce.js +1543 -266
  118. package/dist/core/Taskforce.listTasksSlim.test.d.ts +1 -0
  119. package/dist/core/Taskforce.listTasksSlim.test.js +91 -0
  120. package/dist/core/Taskforce.mcpAuth.test.js +109 -0
  121. package/dist/core/UserProfileAvatarDrafts.test.js +30 -3
  122. package/dist/core/WorkspaceLifecycleService.js +0 -5
  123. package/dist/core/WorkspacePermissions.test.js +25 -1
  124. package/dist/core/WorkspacePlanMode.test.js +117 -16
  125. package/dist/core/shared.d.ts +1 -1
  126. package/dist/core/shared.js +5 -1
  127. package/dist/core/types.d.ts +75 -2
  128. package/dist/hooks/auth/useTaskforceAuthBootstrap.js +28 -2
  129. package/dist/hooks/bootstrapTimeouts.d.ts +4 -0
  130. package/dist/hooks/bootstrapTimeouts.js +8 -0
  131. package/dist/hooks/bootstrapTimeouts.test.d.ts +1 -0
  132. package/dist/hooks/bootstrapTimeouts.test.js +12 -0
  133. package/dist/hooks/sync/bootstrap.js +2 -0
  134. package/dist/hooks/sync/controlPlane.d.ts +37 -0
  135. package/dist/hooks/sync/controlPlane.js +78 -0
  136. package/dist/hooks/sync/controlPlane.test.d.ts +1 -0
  137. package/dist/hooks/sync/controlPlane.test.js +121 -0
  138. package/dist/hooks/sync/lifecyclePolicy.d.ts +45 -0
  139. package/dist/hooks/sync/lifecyclePolicy.js +93 -0
  140. package/dist/hooks/sync/lifecyclePolicy.test.d.ts +1 -0
  141. package/dist/hooks/sync/lifecyclePolicy.test.js +124 -0
  142. package/dist/hooks/sync/orchestratorShared.d.ts +13 -4
  143. package/dist/hooks/sync/orchestratorShared.js +129 -48
  144. package/dist/hooks/sync/orchestratorShared.test.js +50 -1
  145. package/dist/hooks/sync/pullLifecycle.d.ts +31 -0
  146. package/dist/hooks/sync/pullLifecycle.js +24 -0
  147. package/dist/hooks/sync/pullLifecycle.test.d.ts +1 -0
  148. package/dist/hooks/sync/pullLifecycle.test.js +80 -0
  149. package/dist/hooks/sync/recovery.d.ts +16 -2
  150. package/dist/hooks/sync/recovery.js +179 -53
  151. package/dist/hooks/sync/recovery.test.d.ts +1 -0
  152. package/dist/hooks/sync/recovery.test.js +292 -0
  153. package/dist/hooks/sync/transfers.d.ts +16 -3
  154. package/dist/hooks/sync/transfers.js +210 -66
  155. package/dist/hooks/sync/transfers.test.d.ts +1 -0
  156. package/dist/hooks/sync/transfers.test.js +928 -0
  157. package/dist/hooks/sync/useRecentSyncEvents.d.ts +21 -0
  158. package/dist/hooks/sync/useRecentSyncEvents.js +92 -0
  159. package/dist/hooks/sync/useRecentSyncEvents.test.d.ts +1 -0
  160. package/dist/hooks/sync/useRecentSyncEvents.test.js +124 -0
  161. package/dist/hooks/sync/useSyncStatusActions.d.ts +30 -0
  162. package/dist/hooks/sync/useSyncStatusActions.js +88 -0
  163. package/dist/hooks/sync/useSyncStatusActions.test.d.ts +1 -0
  164. package/dist/hooks/sync/useSyncStatusActions.test.js +133 -0
  165. package/dist/hooks/sync/useSyncStatusControls.d.ts +25 -0
  166. package/dist/hooks/sync/useSyncStatusControls.js +60 -0
  167. package/dist/hooks/sync/useSyncStatusControls.test.d.ts +1 -0
  168. package/dist/hooks/sync/useSyncStatusControls.test.js +88 -0
  169. package/dist/hooks/useFilterSort.js +13 -13
  170. package/dist/hooks/useFilterSort.test.js +87 -1
  171. package/dist/hooks/useSyncOrchestrator.aiProfiles.test.js +12 -0
  172. package/dist/hooks/useSyncOrchestrator.d.ts +9 -2
  173. package/dist/hooks/useSyncOrchestrator.js +409 -183
  174. package/dist/hooks/useSyncOrchestrator.retry-closure.test.js +407 -0
  175. package/dist/hooks/useTaskData.js +8 -3
  176. package/dist/hooks/useTaskData.test.js +45 -0
  177. package/dist/hooks/useTaskforce.d.ts +145 -52
  178. package/dist/hooks/useTaskforce.js +592 -253
  179. package/dist/hooks/useTaskforce.runtime-routing.test.d.ts +1 -0
  180. package/dist/hooks/useTaskforce.runtime-routing.test.js +246 -0
  181. package/dist/hooks/useTaskforce.sync-behavior.test.js +2468 -201
  182. package/dist/hooks/useWorkspaceSyncController.d.ts +1 -0
  183. package/dist/hooks/useWorkspaceSyncController.js +13 -2
  184. package/dist/hooks/useWorkspaceSyncController.test.js +48 -0
  185. package/dist/hooks/workspace/useTaskforceWorkspaceBootstrap.d.ts +16 -0
  186. package/dist/hooks/workspace/useTaskforceWorkspaceBootstrap.js +328 -40
  187. package/dist/localization/locales/en-US.d.ts +0 -1
  188. package/dist/localization/locales/en-US.js +0 -1
  189. package/dist/localization/locales/es-419.js +0 -1
  190. package/dist/localization/locales/pt-BR.js +0 -1
  191. package/dist/mcp/canonicalAssetHelpers.d.ts +16 -4
  192. package/dist/mcp/canonicalAssetHelpers.js +18 -10
  193. package/dist/mcp/canonicalAssetHelpers.test.d.ts +1 -0
  194. package/dist/mcp/canonicalAssetHelpers.test.js +67 -0
  195. package/dist/mcp/clientIntegrations.d.ts +1 -0
  196. package/dist/mcp/clientIntegrations.js +25 -0
  197. package/dist/mcp/clientIntegrations.test.js +14 -3
  198. package/dist/mcp/clientProfileDefaults.js +3 -3
  199. package/dist/mcp/collaborationRegistrar.js +7 -7
  200. package/dist/mcp/documentAssetRegistrar.js +116 -10
  201. package/dist/mcp/runtime.d.ts +3 -0
  202. package/dist/mcp/runtime.js +1099 -185
  203. package/dist/mcp/runtime.test.js +1491 -140
  204. package/dist/mcp/taskAttachmentTypes.d.ts +1 -1
  205. package/dist/mcp/taskPlanningRegistrar.js +48 -0
  206. package/dist/mcp/toolRegistry.d.ts +56 -0
  207. package/dist/mcp/toolRegistry.js +8 -0
  208. package/dist/mcp/toolRegistry.test.js +4 -0
  209. package/dist/migrations/taskSchemaMigrations.d.ts +1 -1
  210. package/dist/migrations/taskSchemaMigrations.js +192 -61
  211. package/dist/migrations/taskSchemaMigrations.test.js +15 -0
  212. package/dist/resources/templates/workflow-sources/workflowDocs.mjs +6 -6
  213. package/dist/resources/templates/workflows/collaborate.yaml +1 -1
  214. package/dist/resources/templates/workflows/evaluate.yaml +2 -2
  215. package/dist/resources/templates/workflows/plan.yaml +1 -1
  216. package/dist/resources/templates/workflows/review.yaml +2 -2
  217. package/dist/server/aiProfileAvatarAssets.d.ts +49 -0
  218. package/dist/server/aiProfileAvatarAssets.js +319 -0
  219. package/dist/server/aiProfileAvatarAssets.test.d.ts +1 -0
  220. package/dist/server/aiProfileAvatarAssets.test.js +213 -0
  221. package/dist/server/annotatedAttachmentsRoutes.test.js +69 -10
  222. package/dist/server/auth/providers/apple.d.ts +33 -0
  223. package/dist/server/auth/providers/apple.js +82 -0
  224. package/dist/server/auth/providers/appleClientSecret.d.ts +37 -0
  225. package/dist/server/auth/providers/appleClientSecret.js +65 -0
  226. package/dist/server/auth/providers/github.d.ts +26 -0
  227. package/dist/server/auth/providers/github.js +86 -0
  228. package/dist/server/auth/providers/google.d.ts +21 -0
  229. package/dist/server/auth/providers/google.js +56 -0
  230. package/dist/server/auth/providers/types.d.ts +21 -0
  231. package/dist/server/auth/providers/types.js +1 -0
  232. package/dist/server/auth.d.ts +2 -0
  233. package/dist/server/auth.js +6 -3
  234. package/dist/server/documentReviewRoutes.test.js +36 -3
  235. package/dist/server/index.cookieProxy.test.js +1 -0
  236. package/dist/server/index.d.ts +12 -0
  237. package/dist/server/index.js +124 -9
  238. package/dist/server/index.rateLimit.test.js +3 -0
  239. package/dist/server/index.test.js +111 -3
  240. package/dist/server/routes/admin.d.ts +3 -0
  241. package/dist/server/routes/admin.js +459 -28
  242. package/dist/server/routes/annotatedAttachments.js +51 -0
  243. package/dist/server/routes/auth.d.ts +26 -2
  244. package/dist/server/routes/auth.js +1170 -71
  245. package/dist/server/routes/authSupport.d.ts +5 -1
  246. package/dist/server/routes/authSupport.js +13 -2
  247. package/dist/server/routes/billing.js +372 -35
  248. package/dist/server/routes/billing.test.js +595 -12
  249. package/dist/server/routes/documents.d.ts +1 -0
  250. package/dist/server/routes/documents.js +182 -70
  251. package/dist/server/routes/shared.d.ts +28 -2
  252. package/dist/server/routes/shared.js +69 -14
  253. package/dist/server/routes/sync.integration.test.js +658 -39
  254. package/dist/server/routes/sync.js +74 -608
  255. package/dist/server/routes/syncAuxRoutes.d.ts +15 -0
  256. package/dist/server/routes/syncAuxRoutes.js +91 -0
  257. package/dist/server/routes/syncAuxRoutes.test.d.ts +1 -0
  258. package/dist/server/routes/syncAuxRoutes.test.js +158 -0
  259. package/dist/server/routes/syncPullApplyRoutes.d.ts +36 -0
  260. package/dist/server/routes/syncPullApplyRoutes.js +204 -0
  261. package/dist/server/routes/syncPushRoutes.d.ts +24 -0
  262. package/dist/server/routes/syncPushRoutes.js +212 -0
  263. package/dist/server/routes/syncRouteGuards.d.ts +36 -0
  264. package/dist/server/routes/syncRouteGuards.js +67 -0
  265. package/dist/server/routes/syncRouteGuards.test.d.ts +1 -0
  266. package/dist/server/routes/syncRouteGuards.test.js +94 -0
  267. package/dist/server/routes/syncRouteTypes.d.ts +13 -0
  268. package/dist/server/routes/syncRouteTypes.js +1 -0
  269. package/dist/server/routes/syncSnapshotRoutes.d.ts +66 -0
  270. package/dist/server/routes/syncSnapshotRoutes.js +182 -0
  271. package/dist/server/routes/tasks.js +55 -10
  272. package/dist/server/routes/workspaces.js +36 -5
  273. package/dist/server/routes.js +147 -11
  274. package/dist/server/routes.test.js +2704 -183
  275. package/dist/services/workflowExportSnapshots.test.js +2 -0
  276. package/dist/shared/aiProfileSeatScope.d.ts +5 -0
  277. package/dist/shared/aiProfileSeatScope.js +21 -0
  278. package/dist/shared/aiProfileSurfaceType.d.ts +1 -1
  279. package/dist/shared/aiProfileSurfaceType.js +10 -8
  280. package/dist/shared/passwordPolicy.d.ts +13 -0
  281. package/dist/shared/passwordPolicy.js +84 -0
  282. package/dist/shared/passwordPolicy.test.d.ts +1 -0
  283. package/dist/shared/passwordPolicy.test.js +34 -0
  284. package/dist/storage/objectStorage.d.ts +1 -0
  285. package/dist/storage/objectStorage.js +2 -1
  286. package/dist/storage/objectStorageClient.d.ts +1 -0
  287. package/dist/storage/objectStorageClient.js +41 -8
  288. package/dist/storage/objectStorageClient.test.js +26 -1
  289. package/dist/storage/objectStorageConfig.js +3 -1
  290. package/dist/storage/objectStorageConfig.test.js +13 -1
  291. package/dist/storage/workspaceAssetStore.d.ts +15 -3
  292. package/dist/storage/workspaceAssetStore.js +132 -44
  293. package/dist/storage/workspaceAssetStore.test.js +93 -6
  294. package/dist/styles/fonts.css +70 -0
  295. package/dist/sync/collaborationSyncPayload.d.ts +6 -1
  296. package/dist/sync/collaborationSyncPayload.js +19 -11
  297. package/dist/sync/collaborationSyncPayload.test.js +14 -1
  298. package/dist/sync/collaborationSyncState.d.ts +3 -3
  299. package/dist/sync/collaborationSyncState.js +19 -12
  300. package/dist/sync/contentSyncPayload.d.ts +5 -1
  301. package/dist/sync/contentSyncPayload.js +9 -0
  302. package/dist/sync/contentSyncPayload.test.js +39 -0
  303. package/dist/sync/contentSyncState.d.ts +9 -9
  304. package/dist/sync/contentSyncState.js +248 -107
  305. package/dist/sync/planningSyncPayload.js +5 -0
  306. package/dist/sync/planningSyncPayload.test.js +24 -0
  307. package/dist/sync/syncApplyHandlers.d.ts +11 -4
  308. package/dist/sync/syncApplyHandlers.js +115 -42
  309. package/dist/sync/syncApplyHandlers.test.js +251 -4
  310. package/dist/sync/syncFieldSemantics.d.ts +12 -0
  311. package/dist/sync/syncFieldSemantics.js +55 -0
  312. package/dist/sync/syncResourceAdapters.d.ts +46 -0
  313. package/dist/sync/syncResourceAdapters.js +79 -0
  314. package/dist/sync/syncService.d.ts +6 -0
  315. package/dist/sync/syncService.js +65 -1
  316. package/dist/sync/syncService.test.js +96 -3
  317. package/dist/sync/taskSyncChangeKey.d.ts +2 -0
  318. package/dist/sync/taskSyncChangeKey.js +143 -0
  319. package/dist/sync/taskSyncPayload.js +3 -8
  320. package/dist/sync/workspacePullFeed.d.ts +4 -0
  321. package/dist/sync/workspacePullFeed.js +132 -72
  322. package/dist/sync/workspacePullFeed.test.js +92 -0
  323. package/dist/sync/workspaceRepair.js +5 -2
  324. package/dist/sync/workspaceSyncModel.d.ts +73 -6
  325. package/dist/sync/workspaceSyncModel.js +342 -73
  326. package/dist/sync/workspaceSyncModel.test.js +559 -14
  327. package/dist/sync/workspaceSyncState.d.ts +17 -0
  328. package/dist/sync/workspaceSyncState.js +2 -1
  329. package/dist/sync/workspaceSyncSurface.js +3 -8
  330. package/dist/types.d.ts +50 -2
  331. package/dist/ui/assets/AgentsModule-2y82_3DO.js +1 -0
  332. package/dist/ui/assets/AnnotatedAttachmentWorkspace-BTLZZCiQ.js +3 -0
  333. package/dist/ui/assets/AnnotatedAttachmentWorkspace-BVKew-mH.css +1 -0
  334. package/dist/ui/assets/ContextAttachmentManager-D2epuNnG.js +3 -0
  335. package/dist/ui/assets/CourierPrime-Bold-BuLj_dpw.woff2 +0 -0
  336. package/dist/ui/assets/CourierPrime-BoldItalic-BrK2pUkZ.woff2 +0 -0
  337. package/dist/ui/assets/CourierPrime-Italic-DFUZK5Ey.woff2 +0 -0
  338. package/dist/ui/assets/CourierPrime-Regular-BsKphzVf.woff2 +0 -0
  339. package/dist/ui/assets/DocumentWorkspace-D4rJKXzd.css +1 -0
  340. package/dist/ui/assets/DocumentWorkspace-sVa-3Do6.js +252 -0
  341. package/dist/ui/assets/EntityActivityTimeline-DyqvvhuF.css +1 -0
  342. package/dist/ui/assets/EntityActivityTimeline-Zods27y_.js +1 -0
  343. package/dist/ui/assets/{InitiativesModule-Dhm7M8e7.js → InitiativesModule-D4XseTwW.js} +1 -1
  344. package/dist/ui/assets/Noir_medium-bxQwKGzB.woff2 +0 -0
  345. package/dist/ui/assets/Noir_regular-ojf2kxlG.woff2 +0 -0
  346. package/dist/ui/assets/PlansPage-D5AcbO0L.js +1 -0
  347. package/dist/ui/assets/PlansPage-Dvqsz5zc.css +1 -0
  348. package/dist/ui/assets/RussoOne-Regular-Cu_qq_qC.woff2 +0 -0
  349. package/dist/ui/assets/SpecialElite-Regular-Di6gSvAS.woff2 +0 -0
  350. package/dist/ui/assets/TaskContextUpload-uC5qx4Bv.js +1 -0
  351. package/dist/ui/assets/TaskSettings-CqvPAsTv.js +9 -0
  352. package/dist/ui/assets/{WorkflowsModule-BcS4afRn.js → WorkflowsModule-oOA9bcdK.js} +4 -4
  353. package/dist/ui/assets/documentReferences-DPZuTgHh.js +1 -0
  354. package/dist/ui/assets/index-607WPo_X.js +4 -0
  355. package/dist/ui/assets/index-CYyodXsg.css +1 -0
  356. package/dist/ui/assets/{vendor-icons-BSUaRwF8.js → vendor-icons-B32hGuF2.js} +1 -1
  357. package/dist/ui/fonts/CourierPrime-Bold.ttf +0 -0
  358. package/dist/ui/fonts/CourierPrime-Bold.woff2 +0 -0
  359. package/dist/ui/fonts/CourierPrime-BoldItalic.ttf +0 -0
  360. package/dist/ui/fonts/CourierPrime-BoldItalic.woff2 +0 -0
  361. package/dist/ui/fonts/CourierPrime-Italic.ttf +0 -0
  362. package/dist/ui/fonts/CourierPrime-Italic.woff2 +0 -0
  363. package/dist/ui/fonts/CourierPrime-Regular.ttf +0 -0
  364. package/dist/ui/fonts/CourierPrime-Regular.woff2 +0 -0
  365. package/dist/ui/fonts/Noir_medium.otf +0 -0
  366. package/dist/ui/fonts/Noir_medium.woff2 +0 -0
  367. package/dist/ui/fonts/Noir_regular.otf +0 -0
  368. package/dist/ui/fonts/Noir_regular.woff2 +0 -0
  369. package/dist/ui/fonts/RussoOne-Regular.woff2 +0 -0
  370. package/dist/ui/fonts/SpecialElite-Regular.ttf +0 -0
  371. package/dist/ui/fonts/SpecialElite-Regular.woff2 +0 -0
  372. package/dist/ui/index.html +3 -3
  373. package/dist/ui/product/agent manager.png +0 -0
  374. package/dist/ui/product/agent_manager_02.png +0 -0
  375. package/dist/utils/accountProfileSummaryCache.d.ts +5 -0
  376. package/dist/utils/aiProfileEvents.d.ts +7 -0
  377. package/dist/utils/aiProfileEvents.js +6 -0
  378. package/dist/utils/assignees.d.ts +8 -0
  379. package/dist/utils/assignees.js +10 -1
  380. package/dist/utils/assignees.test.d.ts +1 -0
  381. package/dist/utils/assignees.test.js +25 -0
  382. package/dist/utils/avatarDisplay.d.ts +1 -0
  383. package/dist/utils/avatarDisplay.js +15 -0
  384. package/dist/utils/avatarUpload.d.ts +27 -0
  385. package/dist/utils/avatarUpload.js +132 -0
  386. package/dist/utils/avatarUpload.test.d.ts +1 -0
  387. package/dist/utils/avatarUpload.test.js +40 -0
  388. package/dist/utils/bootstrapTrace.d.ts +7 -0
  389. package/dist/utils/bootstrapTrace.js +29 -0
  390. package/dist/utils/commercialLifecyclePresentation.js +3 -0
  391. package/dist/utils/contextAssetEvents.d.ts +2 -0
  392. package/dist/utils/contextFiles.d.ts +3 -1
  393. package/dist/utils/contextFiles.js +2 -1
  394. package/dist/utils/syncEventDetails.d.ts +3 -0
  395. package/dist/utils/syncEventDetails.js +64 -0
  396. package/dist/utils/syncEventDetails.test.d.ts +1 -0
  397. package/dist/utils/syncEventDetails.test.js +23 -0
  398. package/dist/utils/syncEventPresentation.d.ts +15 -0
  399. package/dist/utils/syncEventPresentation.js +129 -0
  400. package/dist/utils/syncEventPresentation.test.d.ts +1 -0
  401. package/dist/utils/syncEventPresentation.test.js +64 -0
  402. package/dist/utils/syncStatusPresentation.d.ts +72 -0
  403. package/dist/utils/syncStatusPresentation.js +217 -0
  404. package/dist/utils/syncStatusPresentation.test.d.ts +1 -0
  405. package/dist/utils/syncStatusPresentation.test.js +164 -0
  406. package/dist/utils/taskActivity.d.ts +9 -1
  407. package/dist/utils/taskActivity.js +290 -22
  408. package/dist/utils/taskActivity.test.js +141 -8
  409. package/dist/utils/taskSearch.d.ts +22 -0
  410. package/dist/utils/taskSearch.js +87 -0
  411. package/dist/utils/taskSearch.test.d.ts +1 -0
  412. package/dist/utils/taskSearch.test.js +69 -0
  413. package/dist/utils/taskUtils.js +10 -3
  414. package/dist/utils/taskUtils.test.d.ts +1 -0
  415. package/dist/utils/taskUtils.test.js +19 -0
  416. package/dist/utils/workspaceSyncPresentation.d.ts +4 -0
  417. package/dist/utils/workspaceSyncPresentation.js +68 -2
  418. package/dist/utils/workspaceSyncPresentation.test.js +36 -1
  419. package/package.json +3 -2
  420. package/scripts/export-sqlite-to-postgres.mjs +7 -9
  421. package/scripts/run-e2e-realtime.sh +17 -3
  422. package/scripts/run-smoke.sh +17 -5
  423. package/scripts/run-soak.sh +17 -5
  424. package/src/resources/templates/workflow-sources/workflowDocs.mjs +6 -6
  425. package/src/resources/templates/workflows/collaborate.yaml +1 -1
  426. package/src/resources/templates/workflows/evaluate.yaml +2 -2
  427. package/src/resources/templates/workflows/plan.yaml +1 -1
  428. package/src/resources/templates/workflows/review.yaml +2 -2
  429. package/dist/ui/assets/AgentsModule-N2MnQBZk.js +0 -1
  430. package/dist/ui/assets/AnnotatedAttachmentWorkspace-BG6P_GVW.js +0 -3
  431. package/dist/ui/assets/AnnotatedAttachmentWorkspace-BaS2VwIr.css +0 -1
  432. package/dist/ui/assets/DocumentWorkspace-B3nV_Gc5.css +0 -1
  433. package/dist/ui/assets/DocumentWorkspace-DRbDMwh8.js +0 -252
  434. package/dist/ui/assets/PlansPage-C2dd2n1X.css +0 -1
  435. package/dist/ui/assets/PlansPage-Cq0zXj3I.js +0 -1
  436. package/dist/ui/assets/RussoOne-Regular-C3BxZIj7.ttf +0 -0
  437. package/dist/ui/assets/TaskSettings-ln0aF7xc.js +0 -9
  438. package/dist/ui/assets/index-C2-OXZV7.css +0 -1
  439. package/dist/ui/assets/index-DcSI5F86.js +0 -6
  440. package/scripts/migrate-planning-model.ts +0 -233
@@ -14,12 +14,21 @@ import { Markdown } from "../ui/Markdown";
14
14
  import { IconMap, resolveColor } from "../../utils/constants";
15
15
  import { formatDate } from "../../utils/formatting";
16
16
  import { t } from "../../localization";
17
- import { TaskContextUpload } from "./TaskContextUpload";
18
- import { summarizeTaskChange, summarizeTaskEvent, } from "../../utils/taskActivity";
17
+ import { getTaskActivityItems } from "../../utils/taskActivity";
19
18
  import { ensureAssigneeOptionPresent, getAssigneeKind, getAssigneeLabel, } from "../../utils/assignees";
20
19
  import { getTaskReferenceLabel } from "../../utils/taskReferences";
21
20
  import { getVisibleTaskFormTaxonomies } from "../../utils/taxonomyFormDefaults.js";
22
21
  import { getInitiativeReferenceLabel, getWorkstreamReferenceLabel, } from "../../utils/planningReferences";
22
+ const DeferredEntityActivityTimeline = React.lazy(() => (import("../activity/EntityActivityTimeline").then((module) => ({
23
+ default: module.EntityActivityTimeline,
24
+ }))));
25
+ const DeferredTaskContextUpload = React.lazy(() => (import("./TaskContextUpload").then((module) => ({
26
+ default: module.TaskContextUpload,
27
+ }))));
28
+ function ActivityTimelineFallback({ count }) {
29
+ const placeholderCount = Math.max(2, Math.min(count || 3, 4));
30
+ return (_jsx("div", { className: `${formStyles.commentThread} ${formStyles.activityLoadingThread}`.trim(), "aria-busy": "true", "aria-live": "polite", "aria-label": "Loading activity", children: Array.from({ length: placeholderCount }, (_, index) => (_jsxs("div", { className: formStyles.activitySkeletonItem, children: [_jsx("div", { className: formStyles.activitySkeletonMeta }), _jsx("div", { className: formStyles.activitySkeletonBody })] }, index))) }));
31
+ }
23
32
  function SortableChecklistRow({ id, item, onToggle, onRemove, }) {
24
33
  const { attributes, listeners, setNodeRef, transform, transition, isDragging, } = useSortable({ id });
25
34
  const style = {
@@ -31,12 +40,6 @@ function SortableChecklistRow({ id, item, onToggle, onRemove, }) {
31
40
  ? "Mark checklist item incomplete"
32
41
  : "Mark checklist item complete", children: item.isCompleted ? _jsx(Check, { size: 14, strokeWidth: 2.1 }) : null }), _jsx("span", { className: `${formStyles.checklistItemText} ${item.isCompleted ? formStyles.checklistItemTextCompleted : ""}`.trim(), children: item.title }), _jsx("button", { type: "button", className: formStyles.checklistRemoveBtn, onClick: onRemove, title: "Remove checklist item", "aria-label": "Remove checklist item", children: _jsx(X, { size: 15, strokeWidth: 1.9 }) })] }));
33
42
  }
34
- function hexToRgba(hex, opacity) {
35
- const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
36
- if (!result)
37
- return "";
38
- return `rgba(${parseInt(result[1], 16)}, ${parseInt(result[2], 16)}, ${parseInt(result[3], 16)}, ${opacity})`;
39
- }
40
43
  export function TaskForm(props) {
41
44
  const { editingTaskId, error, title, description, category, type, priority, complexity, manualComplexityEnabled = false, assignee, scheduledDate, dueDate, workstreamInput = "", checklistItems, comments, newCommentText, contextFiles, currentWorkspaceId, apiBaseUrl, descriptionFocused, showMarkdownHelp, showChecklist = false, checklistEnabled = true, formTaxonomies, onTaxonomyChange, onOpenSettings, categories, types, priorities, taxonomyDisplayLabels, assigneeOptions, taxonomies, workstreams = [], initiatives = [], copiedId, onTitleChange, onDescriptionChange, onCategoryChange, onTypeChange, onPriorityChange, onComplexityChange, onAssigneeChange, onScheduledDateChange, onDueDateChange, onWorkstreamInputChange = () => { }, onChecklistItemsChange, onNewCommentTextChange, onDescriptionFocusedChange, onShowMarkdownHelpChange, onShowChecklistChange = () => { }, onSubmit, onAddComment, onAddContextFile, onRemoveContextFile, onUpdateContextCaption, onCopyId, onToggleInProgress, onToggleReview, onToggleComplete, onToggleCancel, onSetStatus, onArchiveTask, onUnarchive, onOpenTaskById, currentTask, commentsEndRef, } = props;
42
45
  const currentTaskReferenceLabel = getTaskReferenceLabel(currentTask);
@@ -235,18 +238,7 @@ export function TaskForm(props) {
235
238
  initiative.id,
236
239
  getInitiativeReferenceLabel(initiative) || initiative.id,
237
240
  ])), [initiatives]);
238
- const taskActivityItems = React.useMemo(() => {
239
- if (Array.isArray(currentTask?.activity) &&
240
- currentTask.activity.length > 0) {
241
- return currentTask.activity;
242
- }
243
- return comments.map((comment) => ({
244
- id: `comment:${comment.id}`,
245
- type: "comment",
246
- timestamp: comment.timestamp,
247
- comment,
248
- }));
249
- }, [comments, currentTask?.activity]);
241
+ const taskActivityItems = React.useMemo(() => getTaskActivityItems({ activity: currentTask?.activity, comments }), [comments, currentTask?.activity]);
250
242
  const formatActivityFieldValue = (field, value) => {
251
243
  const normalizedValue = String(value || "").trim();
252
244
  if (!normalizedValue)
@@ -284,8 +276,53 @@ export function TaskForm(props) {
284
276
  formatAiAuthorLabel,
285
277
  resolvedAssigneeOptions,
286
278
  ]);
279
+ const resolveActivityActorPresentation = React.useCallback(({ actorId, actorType, actorProfile, fallbackKind, }) => {
280
+ const actorRef = String(actorId || "").trim();
281
+ const normalizedActor = actorRef.toLowerCase();
282
+ const actorFallback = actorFallbackById.get(actorRef);
283
+ const actorOption = actorOptionByValue.get(actorRef) ||
284
+ actorOptionByValue.get(normalizedActor);
285
+ const resolvedActor = actorProfile || actorFallback || actorOption || null;
286
+ const resolvedKind = actorType === "system"
287
+ ? "system"
288
+ : actorType === "ai" || resolvedActor?.kind === "ai"
289
+ ? "agent"
290
+ : actorType === "human" || resolvedActor?.kind === "human"
291
+ ? "member"
292
+ : actorOption?.kind === "agent"
293
+ ? "agent"
294
+ : actorOption?.kind === "member"
295
+ ? "member"
296
+ : fallbackKind ||
297
+ (normalizedActor === "" ||
298
+ normalizedActor === "user" ||
299
+ normalizedActor === "human"
300
+ ? "member"
301
+ : "agent");
302
+ const label = resolvedKind === "system"
303
+ ? "System"
304
+ : resolveActorLabel(actorRef, resolvedKind === "agent" ? "ai" : "human", resolvedActor?.label || null);
305
+ const color = resolvedActor?.color;
306
+ const iconName = String(resolvedActor?.icon ||
307
+ (resolvedKind === "agent"
308
+ ? "Bot"
309
+ : resolvedKind === "member"
310
+ ? "User"
311
+ : "ClipboardList"));
312
+ const ActorIcon = IconMap[iconName] ||
313
+ (resolvedKind === "agent"
314
+ ? Bot
315
+ : resolvedKind === "member"
316
+ ? User
317
+ : ClipboardList);
318
+ return { kind: resolvedKind, label, color, ActorIcon };
319
+ }, [
320
+ actorFallbackById,
321
+ actorOptionByValue,
322
+ resolveActorLabel,
323
+ ]);
287
324
  const latestActivityActorLabel = React.useMemo(() => {
288
- const latestItem = taskActivityItems[0];
325
+ const latestItem = taskActivityItems[taskActivityItems.length - 1];
289
326
  if (!latestItem)
290
327
  return null;
291
328
  if (latestItem.type === "comment") {
@@ -347,104 +384,12 @@ export function TaskForm(props) {
347
384
  const frame = window.requestAnimationFrame(scrollToLatest);
348
385
  return () => window.cancelAnimationFrame(frame);
349
386
  }, [activityCount, commentsEndRef, currentTask?.id, editingTaskId]);
350
- const activitySidebar = editingTaskId ? (_jsxs("aside", { className: formStyles.activitySidebar, "aria-label": t("taskForm.commentsSectionTitle"), children: [_jsxs("div", { className: formStyles.activitySidebarHeader, children: [_jsx("h2", { className: formStyles.activitySidebarTitle, children: t("taskForm.commentsSectionTitle") }), _jsx("span", { className: formStyles.activitySidebarCount, children: activityCount })] }), _jsxs("div", { className: `${formStyles.commentPanel} ${formStyles.activitySidebarPanel}`.trim(), children: [_jsxs("div", { className: formStyles.commentThread, children: [activityCount === 0 && (_jsx("div", { className: formStyles.emptyComments, children: t("taskForm.noComments") })), taskActivityItems.map((item) => {
351
- if (item.type === "comment") {
352
- const c = item.comment;
353
- const authorRef = String(c.author || "").trim();
354
- const normalizedAuthor = authorRef.toLowerCase();
355
- const actorFallback = actorFallbackById.get(authorRef);
356
- const actorOption = actorOptionByValue.get(authorRef) ||
357
- actorOptionByValue.get(normalizedAuthor);
358
- const resolvedActor = c.actor || actorFallback || actorOption || null;
359
- const commentKind = c.actor?.kind === "human"
360
- ? "member"
361
- : c.actor?.kind === "ai"
362
- ? "agent"
363
- : actorFallback?.kind === "human"
364
- ? "member"
365
- : actorFallback?.kind === "ai"
366
- ? "agent"
367
- : actorOption?.kind ||
368
- (normalizedAuthor === "" ||
369
- normalizedAuthor === "user" ||
370
- normalizedAuthor === "human"
371
- ? "member"
372
- : "agent");
373
- const authorLabel = c.actor?.label ||
374
- actorFallback?.label ||
375
- actorOption?.label ||
376
- (authorRef
377
- ? getAssigneeLabel(authorRef, resolvedAssigneeOptions)
378
- : "") ||
379
- (commentKind === "agent"
380
- ? formatAiAuthorLabel(authorRef || "ai")
381
- : t("taskForm.you"));
382
- const authorColor = c.actor?.color || actorFallback?.color || actorOption?.color;
383
- const iconName = String(resolvedActor?.icon ||
384
- (commentKind === "agent" ? "Bot" : "User"));
385
- const CommentActorIcon = IconMap[iconName] || (commentKind === "agent" ? Bot : User);
386
- return (_jsxs("div", { className: `${formStyles.comment} ${commentKind === "agent" ? formStyles.commentAi : formStyles.commentUser}`, children: [_jsxs("div", { className: formStyles.commentHeader, children: [_jsx("span", { className: formStyles.commentAuthor, style: authorColor ? { color: authorColor } : undefined, children: _jsxs(_Fragment, { children: [_jsx(CommentActorIcon, { size: 12, strokeWidth: 1.5 }), " ", authorLabel] }) }), _jsx("span", { className: formStyles.commentTime, children: formatDate(c.timestamp, {
387
- month: "short",
388
- day: "numeric",
389
- hour: "2-digit",
390
- minute: "2-digit",
391
- }) })] }), _jsx("div", { className: formStyles.commentText, style: authorColor
392
- ? {
393
- background: `linear-gradient(135deg, ${hexToRgba(authorColor, 0.18)} 0%, ${hexToRgba(authorColor, 0.1)} 100%)`,
394
- borderColor: hexToRgba(authorColor, 0.35),
395
- }
396
- : undefined, children: _jsx(Markdown, { onTaskIdClick: onOpenTaskById, children: c.text }) })] }, c.id));
397
- }
398
- const event = item.event;
399
- const actorRef = String(event.actor || "").trim();
400
- const normalizedAuthor = actorRef.toLowerCase();
401
- const actorFallback = actorFallbackById.get(actorRef);
402
- const actorOption = actorOptionByValue.get(actorRef) ||
403
- actorOptionByValue.get(normalizedAuthor);
404
- const resolvedActor = event.actorProfile || actorFallback || actorOption || null;
405
- const eventKind = event.actorType === "ai"
406
- ? "agent"
407
- : event.actorType === "human"
408
- ? "member"
409
- : "system";
410
- const authorLabel = event.actorProfile?.label ||
411
- actorFallback?.label ||
412
- actorOption?.label ||
413
- (eventKind === "system"
414
- ? "System"
415
- : actorRef
416
- ? getAssigneeLabel(actorRef, resolvedAssigneeOptions)
417
- : eventKind === "agent"
418
- ? formatAiAuthorLabel("ai")
419
- : t("taskForm.you"));
420
- const authorColor = event.actorProfile?.color ||
421
- actorFallback?.color ||
422
- actorOption?.color;
423
- const iconName = String(resolvedActor?.icon ||
424
- (eventKind === "agent"
425
- ? "Bot"
426
- : eventKind === "member"
427
- ? "User"
428
- : "ClipboardList"));
429
- const EventActorIcon = IconMap[iconName] ||
430
- (eventKind === "agent"
431
- ? Bot
432
- : eventKind === "member"
433
- ? User
434
- : ClipboardList);
435
- const changeEntries = Object.entries(event.details?.changes || {});
436
- return (_jsxs("div", { className: `${formStyles.comment} ${formStyles.activityEvent} ${eventKind === "system" ? formStyles.activityEventSystem : ""}`, children: [_jsxs("div", { className: `${formStyles.commentHeader} ${formStyles.activityEventHeader}`, children: [_jsx("span", { className: formStyles.commentAuthor, style: authorColor ? { color: authorColor } : undefined, children: _jsxs(_Fragment, { children: [_jsx(EventActorIcon, { size: 12, strokeWidth: 1.5 }), " ", authorLabel] }) }), _jsx("span", { className: formStyles.commentTime, children: formatDate(event.createdAt, {
437
- month: "short",
438
- day: "numeric",
439
- hour: "2-digit",
440
- minute: "2-digit",
441
- }) })] }), _jsxs("div", { className: formStyles.activityEventText, children: [_jsx("div", { children: summarizeTaskEvent(event, formatActivityFieldValue) }), changeEntries.length > 1 && (_jsx("div", { className: formStyles.activityEventChanges, children: changeEntries.map(([field, change]) => (_jsx("span", { className: formStyles.activityEventChange, children: summarizeTaskChange(field, change, formatActivityFieldValue) }, field))) }))] })] }, item.id));
442
- }), _jsx("div", { ref: commentsEndRef })] }), _jsxs("div", { className: formStyles.commentInputArea, children: [_jsx("textarea", { className: formStyles.commentInput, placeholder: t("taskForm.commentPlaceholder"), value: newCommentText, onChange: (e) => onNewCommentTextChange(e.target.value), onKeyDown: (e) => {
387
+ const activitySidebar = editingTaskId ? (_jsxs("aside", { className: formStyles.activitySidebar, "aria-label": t("taskForm.commentsSectionTitle"), children: [_jsxs("div", { className: formStyles.activitySidebarHeader, children: [_jsx("h2", { className: formStyles.activitySidebarTitle, children: t("taskForm.commentsSectionTitle") }), _jsx("span", { className: formStyles.activitySidebarCount, children: activityCount })] }), _jsxs("div", { className: `${formStyles.commentPanel} ${formStyles.activitySidebarPanel}`.trim(), children: [_jsx(React.Suspense, { fallback: _jsx(ActivityTimelineFallback, { count: activityCount }), children: _jsx(DeferredEntityActivityTimeline, { activity: currentTask?.activity, comments: comments, formatFieldValue: formatActivityFieldValue, resolveActorPresentation: resolveActivityActorPresentation, onOpenTaskById: onOpenTaskById, emptyMessage: t("taskForm.noComments"), listClassName: formStyles.commentThread, emptyClassName: formStyles.emptyComments, endRef: commentsEndRef }) }), _jsxs("div", { className: formStyles.commentInputArea, children: [_jsx("textarea", { className: formStyles.commentInput, placeholder: t("taskForm.commentPlaceholder"), value: newCommentText, onChange: (e) => onNewCommentTextChange(e.target.value), onKeyDown: (e) => {
443
388
  if (e.key === "Enter" && !e.shiftKey) {
444
389
  e.preventDefault();
445
390
  onAddComment();
446
391
  }
447
- }, rows: 1 }), _jsx("button", { type: "button", className: formStyles.sendCommentBtn, onClick: onAddComment, disabled: !newCommentText.trim(), "aria-label": "Send comment", title: "Send comment", children: _jsx(Send, { size: 16 }) })] })] })] })) : null;
392
+ }, rows: 4 }), _jsx("button", { type: "button", className: formStyles.sendCommentBtn, onClick: onAddComment, disabled: !newCommentText.trim(), "aria-label": "Send comment", title: "Send comment", children: _jsx(Send, { size: 16 }) })] })] })] })) : null;
448
393
  return (_jsxs("form", { ref: formRef, onSubmit: onSubmit, className: `${styles.form} ${styles.appScrollbar} tf-scrollbar`, children: [error && _jsx("div", { className: formStyles.error, children: error }), isReadOnly && (_jsx("div", { className: `${formStyles.formNotice} tf-text-helper`, children: isDeletedReadOnly
449
394
  ? "Deleted tasks are read-only. Restore the task to make changes."
450
395
  : "Archived tasks are read-only. Unarchive the task to make changes." })), _jsxs("fieldset", { disabled: isReadOnly, className: `${formStyles.formFieldsetReset} ${editingTaskId ? formStyles.formLayoutWithSidebar : formStyles.formLayout}`.trim(), children: [_jsxs("div", { className: formStyles.formMainColumn, children: [_jsxs("div", { className: styles.field, children: [_jsxs("div", { className: styles.labelRow, children: [_jsx("label", { className: styles.label, children: "Title" }), assignee && (_jsx("span", { title: `Assigned to: ${currentAssigneeLabel}`, className: [
@@ -565,7 +510,7 @@ export function TaskForm(props) {
565
510
  .map((entry, entryIndex) => ({
566
511
  ...entry,
567
512
  order: entryIndex,
568
- }))) }, item.id || `checklist-${index}`))) }) })) : (_jsx("div", { className: `${formStyles.settingsHint} tf-text-helper`, children: "No checklist items yet." }))] }))] }))] }), _jsxs("div", { children: [_jsx(TaskContextUpload, { taskId: editingTaskId, taskReferenceLabel: currentTaskReferenceLabel, workspaceId: currentWorkspaceId, apiBaseUrl: apiBaseUrl, contextFiles: contextFiles, onAddContextFile: onAddContextFile, onRemoveContextFile: onRemoveContextFile, onUpdateContextCaption: onUpdateContextCaption }), _jsx("div", { className: `${formStyles.taskFormLifecycle} ${formStyles.taskFormMetaDivider}`, children: _jsx("div", { className: formStyles.taskFormMetaGrid, children: currentTask && (_jsxs(_Fragment, { children: [_jsxs("div", { className: formStyles.taskFormDateRow, children: [_jsx("span", { className: formStyles.taskFormDateLabel, children: t("taskForm.createdLabel") }), _jsxs("span", { className: formStyles.taskFormMetaStack, children: [_jsx("span", { className: formStyles.taskFormDateValue, children: createdLabel || t("taskForm.emptyValue") }), _jsx("span", { className: formStyles.taskFormMetaActor, children: createdByLabel
513
+ }))) }, item.id || `checklist-${index}`))) }) })) : (_jsx("div", { className: `${formStyles.settingsHint} tf-text-helper`, children: "No checklist items yet." }))] }))] }))] }), _jsxs("div", { children: [_jsx(React.Suspense, { fallback: null, children: _jsx(DeferredTaskContextUpload, { taskId: editingTaskId, taskReferenceLabel: currentTaskReferenceLabel, workspaceId: currentWorkspaceId, apiBaseUrl: apiBaseUrl, contextFiles: contextFiles, onAddContextFile: onAddContextFile, onRemoveContextFile: onRemoveContextFile, onUpdateContextCaption: onUpdateContextCaption }) }), _jsx("div", { className: `${formStyles.taskFormLifecycle} ${formStyles.taskFormMetaDivider}`, children: _jsx("div", { className: formStyles.taskFormMetaGrid, children: currentTask && (_jsxs(_Fragment, { children: [_jsxs("div", { className: formStyles.taskFormDateRow, children: [_jsx("span", { className: formStyles.taskFormDateLabel, children: t("taskForm.createdLabel") }), _jsxs("span", { className: formStyles.taskFormMetaStack, children: [_jsx("span", { className: formStyles.taskFormDateValue, children: createdLabel || t("taskForm.emptyValue") }), _jsx("span", { className: formStyles.taskFormMetaActor, children: createdByLabel
569
514
  ? `by ${createdByLabel}`
570
515
  : t("taskForm.emptyValue") })] })] }), _jsxs("div", { className: formStyles.taskFormDateRow, children: [_jsx("span", { className: formStyles.taskFormDateLabel, children: t("taskForm.updatedLabel") }), _jsxs("span", { className: formStyles.taskFormMetaStack, children: [_jsx("span", { className: formStyles.taskFormDateValue, children: updatedLabel || t("taskForm.emptyValue") }), _jsx("span", { className: formStyles.taskFormMetaActor, children: updatedByLabel
571
516
  ? `by ${updatedByLabel}`
@@ -455,7 +455,7 @@ describe("TaskForm Component", () => {
455
455
  ],
456
456
  },
457
457
  });
458
- expect(screen.getByText("ASSIGNED TO: Unassigned -> Planner Bot")).toBeInTheDocument();
458
+ expect(screen.getByText("Assigned to: Unassigned -> Planner Bot")).toBeInTheDocument();
459
459
  expect(screen.queryByText(/ai-profile-1/i)).not.toBeInTheDocument();
460
460
  });
461
461
  it("renders planning relationship audit activity with reference labels instead of raw ids", () => {
@@ -491,7 +491,7 @@ describe("TaskForm Component", () => {
491
491
  ],
492
492
  },
493
493
  });
494
- expect(screen.getByText("Workstream: none -> WS-12")).toBeInTheDocument();
494
+ expect(screen.getByText("Workstream changed: none -> WS-12")).toBeInTheDocument();
495
495
  expect(screen.queryByText(/workstream-1/i)).not.toBeInTheDocument();
496
496
  });
497
497
  it("3.13 Update title", async () => {
@@ -504,8 +504,8 @@ describe("TaskForm Component", () => {
504
504
  });
505
505
  it("keeps scheduled date editable in the task form", () => {
506
506
  renderForm({
507
- editingTaskId: "parent-1",
508
- currentTask: { id: "parent-1", title: "Parent Task" },
507
+ editingTaskId: "task-1",
508
+ currentTask: { id: "task-1", title: "Schedulable task" },
509
509
  });
510
510
  const scheduledLabel = screen.getByText("Scheduled:");
511
511
  const scheduledInput = scheduledLabel.nextElementSibling;
@@ -513,7 +513,6 @@ describe("TaskForm Component", () => {
513
513
  if (!scheduledInput)
514
514
  throw new Error("Scheduled date input missing");
515
515
  expect(scheduledInput.disabled).toBe(false);
516
- expect(screen.queryByText("Parent tasks cannot be scheduled. Schedule leaf tasks instead.")).not.toBeInTheDocument();
517
516
  });
518
517
  it("3.14 Context Documents section renders", async () => {
519
518
  const user = userEvent.setup();
@@ -682,9 +681,112 @@ describe("TaskForm Component", () => {
682
681
  ],
683
682
  },
684
683
  });
685
- expect(screen.getByText("Status: task -> in-progress")).toBeInTheDocument();
684
+ expect(screen.getByText("Status changed: Task -> In Progress")).toBeInTheDocument();
686
685
  expect(screen.queryByText("System")).not.toBeInTheDocument();
687
686
  });
687
+ it("captures comments alongside audit events and avoids duplicate comment event rows", () => {
688
+ renderForm({
689
+ editingTaskId: "123",
690
+ comments: [
691
+ {
692
+ id: "comment-activity-1",
693
+ author: "user",
694
+ text: "This comment should stay visible.",
695
+ timestamp: "2026-03-22T10:05:00.000Z",
696
+ },
697
+ ],
698
+ currentTask: {
699
+ id: "task-activity-with-comment",
700
+ title: "Activity with comment",
701
+ status: "task",
702
+ createdAt: "2026-03-22T09:00:00.000Z",
703
+ activity: [
704
+ {
705
+ id: "event:status-1",
706
+ type: "event",
707
+ timestamp: "2026-03-22T10:00:00.000Z",
708
+ event: {
709
+ id: "status-1",
710
+ taskId: "task-activity-with-comment",
711
+ workspaceId: "default",
712
+ action: "task-status-changed",
713
+ actor: "user",
714
+ actorType: "human",
715
+ createdAt: "2026-03-22T10:00:00.000Z",
716
+ details: {
717
+ changes: {
718
+ status: { from: "task", to: "in-progress" },
719
+ },
720
+ },
721
+ },
722
+ },
723
+ {
724
+ id: "event:comment-added-1",
725
+ type: "event",
726
+ timestamp: "2026-03-22T10:05:00.000Z",
727
+ event: {
728
+ id: "comment-added-1",
729
+ taskId: "task-activity-with-comment",
730
+ workspaceId: "default",
731
+ action: "task-comment-added",
732
+ actor: "user",
733
+ actorType: "human",
734
+ createdAt: "2026-03-22T10:05:00.000Z",
735
+ },
736
+ },
737
+ ],
738
+ },
739
+ });
740
+ expect(screen.getByText("This comment should stay visible.")).toBeInTheDocument();
741
+ expect(screen.getByText("Status changed: Task -> In Progress")).toBeInTheDocument();
742
+ expect(screen.queryByText("Comment added")).not.toBeInTheDocument();
743
+ });
744
+ it("does not repeat the primary activity change in multi-change event details", () => {
745
+ renderForm({
746
+ editingTaskId: "123",
747
+ assigneeOptions: [
748
+ ...defaultProps.assigneeOptions,
749
+ {
750
+ value: "member-2",
751
+ label: "Tiffany Case",
752
+ icon: "User",
753
+ color: "#22c55e",
754
+ kind: "member",
755
+ },
756
+ ],
757
+ currentTask: {
758
+ id: "task-multi-change",
759
+ title: "Multi change task",
760
+ status: "in-progress",
761
+ createdAt: "2026-03-22T09:00:00.000Z",
762
+ activity: [
763
+ {
764
+ id: "event:multi-change-1",
765
+ type: "event",
766
+ timestamp: "2026-03-22T10:00:00.000Z",
767
+ event: {
768
+ id: "multi-change-1",
769
+ taskId: "task-multi-change",
770
+ workspaceId: "default",
771
+ action: "task-status-changed",
772
+ actor: "user",
773
+ actorType: "human",
774
+ createdAt: "2026-03-22T10:00:00.000Z",
775
+ details: {
776
+ changes: {
777
+ status: { from: "task", to: "in-progress" },
778
+ assignee: { from: "unassigned", to: "member-2" },
779
+ },
780
+ },
781
+ },
782
+ },
783
+ ],
784
+ },
785
+ });
786
+ expect(screen.getByText("Status changed: Task -> In Progress")).toBeInTheDocument();
787
+ expect(screen.getByText("Assigned to: Unassigned -> Tiffany Case")).toBeInTheDocument();
788
+ expect(screen.queryByText("Status: Task -> In Progress")).not.toBeInTheDocument();
789
+ });
688
790
  it("summarizes description audit events without rendering the full description body", () => {
689
791
  renderForm({
690
792
  editingTaskId: "123",
@@ -720,7 +822,7 @@ describe("TaskForm Component", () => {
720
822
  ],
721
823
  },
722
824
  });
723
- expect(screen.getByText("DESCRIPTION: added")).toBeInTheDocument();
825
+ expect(screen.getByText("Description: added")).toBeInTheDocument();
724
826
  expect(screen.queryByText(/Line one/)).not.toBeInTheDocument();
725
827
  expect(screen.queryByText(/Line two/)).not.toBeInTheDocument();
726
828
  expect(screen.queryByText(/Line three/)).not.toBeInTheDocument();
@@ -760,7 +862,7 @@ describe("TaskForm Component", () => {
760
862
  ],
761
863
  },
762
864
  });
763
- expect(screen.getByText("TITLE: updated")).toBeInTheDocument();
865
+ expect(screen.getByText("Title: updated")).toBeInTheDocument();
764
866
  expect(screen.queryByText("Old title")).not.toBeInTheDocument();
765
867
  expect(screen.queryByText("New title")).not.toBeInTheDocument();
766
868
  });
@@ -53,6 +53,7 @@ interface TaskKanbanProps {
53
53
  filterPriorities?: number[];
54
54
  filterStatus?: string[];
55
55
  filterAssignees?: TaskAssignee[];
56
+ filtersReady?: boolean;
56
57
  scheduleFilteredTaskIds?: string[];
57
58
  categories?: CategoryConfig[];
58
59
  compressed?: boolean;
@@ -71,5 +72,5 @@ interface TaskKanbanProps {
71
72
  workstreams?: WorkstreamItem[];
72
73
  initiatives?: InitiativeItem[];
73
74
  }
74
- export declare function TaskKanban({ tasks, columns: kanbanColumns, groupBy, searchQuery, copiedId, taxonomies, types, priorities, approaches, assigneeOptions, onUpdateTask, onTaskClick, onOpenTaskById, onCopyId, onToggleInProgress, onToggleReview, onToggleComplete, onToggleCancel, onSetStatus, onArchiveTask, onUnarchive, onDelete, allTasks, onAddTaskToColumn, emptyColumnMode, filterCategories, filterTypes, filterPriorities, filterStatus, filterAssignees, scheduleFilteredTaskIds, categories, compressed, readOnlyMode, recentlyChangedTaskIds, scheduleDates, onScheduleDaySelected, persistedScrollLeft, onScrollLeftChange, sortBy, sortOrder, planningDropTargets, onAssignTaskToWorkstream, onAssignWorkstreamToInitiative, showTaskCardStatusLabel, workstreams, initiatives, }: TaskKanbanProps): import("react/jsx-runtime").JSX.Element;
75
+ export declare function TaskKanban({ tasks, columns: kanbanColumns, groupBy, searchQuery, copiedId, taxonomies, types, priorities, approaches, assigneeOptions, onUpdateTask, onTaskClick, onOpenTaskById, onCopyId, onToggleInProgress, onToggleReview, onToggleComplete, onToggleCancel, onSetStatus, onArchiveTask, onUnarchive, onDelete, allTasks, onAddTaskToColumn, emptyColumnMode, filterCategories, filterTypes, filterPriorities, filterStatus, filterAssignees, filtersReady, scheduleFilteredTaskIds, categories, compressed, readOnlyMode, recentlyChangedTaskIds, scheduleDates, onScheduleDaySelected, persistedScrollLeft, onScrollLeftChange, sortBy, sortOrder, planningDropTargets, onAssignTaskToWorkstream, onAssignWorkstreamToInitiative, showTaskCardStatusLabel, workstreams, initiatives, }: TaskKanbanProps): import("react/jsx-runtime").JSX.Element;
75
76
  export {};
@@ -11,7 +11,7 @@ import { buildScheduleDropResult, buildStatusTransitionUpdates, getGroupedTaskSt
11
11
  import * as Icons from 'lucide-react';
12
12
  import { IconMap, resolveColor } from '../../utils/constants';
13
13
  const EXPIRED_CARD_ID_PREFIX = 'expired::';
14
- export function TaskKanban({ tasks, columns: kanbanColumns, groupBy, searchQuery, copiedId, taxonomies, types, priorities, approaches, assigneeOptions = [], onUpdateTask, onTaskClick, onOpenTaskById, onCopyId, onToggleInProgress, onToggleReview, onToggleComplete, onToggleCancel, onSetStatus, onArchiveTask, onUnarchive, onDelete, allTasks = [], onAddTaskToColumn, emptyColumnMode = 'show', filterCategories = [], filterTypes = [], filterPriorities = [], filterStatus = [], filterAssignees = [], scheduleFilteredTaskIds, categories = [], compressed = false, readOnlyMode = null, recentlyChangedTaskIds = [], scheduleDates, onScheduleDaySelected, persistedScrollLeft, onScrollLeftChange, sortBy = 'created', sortOrder = 'desc', planningDropTargets = null, onAssignTaskToWorkstream, onAssignWorkstreamToInitiative, showTaskCardStatusLabel = true, workstreams = [], initiatives = [], }) {
14
+ export function TaskKanban({ tasks, columns: kanbanColumns, groupBy, searchQuery, copiedId, taxonomies, types, priorities, approaches, assigneeOptions = [], onUpdateTask, onTaskClick, onOpenTaskById, onCopyId, onToggleInProgress, onToggleReview, onToggleComplete, onToggleCancel, onSetStatus, onArchiveTask, onUnarchive, onDelete, allTasks = [], onAddTaskToColumn, emptyColumnMode = 'show', filterCategories = [], filterTypes = [], filterPriorities = [], filterStatus = [], filterAssignees = [], filtersReady = true, scheduleFilteredTaskIds, categories = [], compressed = false, readOnlyMode = null, recentlyChangedTaskIds = [], scheduleDates, onScheduleDaySelected, persistedScrollLeft, onScrollLeftChange, sortBy = 'created', sortOrder = 'desc', planningDropTargets = null, onAssignTaskToWorkstream, onAssignWorkstreamToInitiative, showTaskCardStatusLabel = true, workstreams = [], initiatives = [], }) {
15
15
  const [activeId, setActiveId] = useState(null);
16
16
  const [isHeaderPanning, setIsHeaderPanning] = useState(false);
17
17
  const [headerPanEnabled, setHeaderPanEnabled] = useState(false);
@@ -130,20 +130,99 @@ export function TaskKanban({ tasks, columns: kanbanColumns, groupBy, searchQuery
130
130
  ]);
131
131
  return dateToColumn.get(scheduledDate) || '__offweek';
132
132
  };
133
+ const inferredKanbanColumns = useMemo(() => {
134
+ if (groupBy === 'schedule')
135
+ return [];
136
+ const existingValues = new Set(kanbanColumns.map((column) => String(column.value)));
137
+ const existingLabels = new Set(kanbanColumns.map((column) => column.label));
138
+ const inferred = [];
139
+ const buildColumn = (task) => {
140
+ const rawValue = groupBy === 'status'
141
+ ? getTaskStatus(task)
142
+ : task[groupBy];
143
+ const value = String(rawValue ?? '');
144
+ if (!value || existingValues.has(value) || existingLabels.has(value))
145
+ return null;
146
+ if (groupBy === 'category') {
147
+ const category = categories.find((entry) => entry.value === value || entry.label === value);
148
+ return {
149
+ value,
150
+ label: category?.label || value,
151
+ icon: category?.icon || 'Folder',
152
+ color: category?.color,
153
+ };
154
+ }
155
+ if (groupBy === 'type') {
156
+ const type = types?.find((entry) => entry.value === value || entry.label === value);
157
+ return {
158
+ value,
159
+ label: type?.label || value,
160
+ icon: type?.icon || 'CheckSquare',
161
+ color: type?.color,
162
+ };
163
+ }
164
+ if (groupBy === 'priority') {
165
+ const priority = priorities?.find((entry) => Number(entry.value) === Number(value));
166
+ return {
167
+ value: Number.isFinite(Number(value)) ? Number(value) : value,
168
+ label: priority?.label || value,
169
+ icon: priority?.icon || 'Flag',
170
+ color: priority?.color,
171
+ };
172
+ }
173
+ if (groupBy === 'complexity') {
174
+ return {
175
+ value: Number.isFinite(Number(value)) ? Number(value) : value,
176
+ label: value,
177
+ icon: 'Gauge',
178
+ };
179
+ }
180
+ if (groupBy === 'status') {
181
+ return {
182
+ value,
183
+ label: value,
184
+ icon: 'Circle',
185
+ };
186
+ }
187
+ if (groupBy === 'assignee') {
188
+ const option = assigneeOptions.find((entry) => entry.value === value);
189
+ return {
190
+ value,
191
+ label: option?.label || value,
192
+ icon: option?.icon === 'HelpCircle' ? 'Circle' : option?.icon,
193
+ color: option?.color,
194
+ };
195
+ }
196
+ return {
197
+ value,
198
+ label: value,
199
+ };
200
+ };
201
+ for (const task of tasks) {
202
+ const column = buildColumn(task);
203
+ if (!column)
204
+ continue;
205
+ inferred.push(column);
206
+ existingValues.add(String(column.value));
207
+ existingLabels.add(column.label);
208
+ }
209
+ return inferred;
210
+ }, [assigneeOptions, categories, groupBy, kanbanColumns, priorities, tasks, types]);
211
+ const effectiveKanbanColumns = useMemo(() => [...kanbanColumns, ...inferredKanbanColumns], [inferredKanbanColumns, kanbanColumns]);
133
212
  const columnLookup = useMemo(() => {
134
213
  const map = new Map();
135
- for (const column of kanbanColumns) {
214
+ for (const column of effectiveKanbanColumns) {
136
215
  map.set(String(column.value), column);
137
216
  if (!map.has(column.label)) {
138
217
  map.set(column.label, column);
139
218
  }
140
219
  }
141
220
  return map;
142
- }, [kanbanColumns]);
221
+ }, [effectiveKanbanColumns]);
143
222
  // Totals for "X / Y" display
144
223
  const columnTotals = useMemo(() => {
145
224
  const counts = {};
146
- kanbanColumns.forEach(col => { counts[String(col.value)] = 0; });
225
+ effectiveKanbanColumns.forEach(col => { counts[String(col.value)] = 0; });
147
226
  const totalsSource = allTasks.length > 0 ? allTasks : tasks;
148
227
  totalsSource.forEach(task => {
149
228
  let stringValue = '';
@@ -170,12 +249,12 @@ export function TaskKanban({ tasks, columns: kanbanColumns, groupBy, searchQuery
170
249
  }
171
250
  });
172
251
  return counts;
173
- }, [allTasks, tasks, kanbanColumns, groupBy, columnLookup, todayDateOnly]);
252
+ }, [allTasks, tasks, effectiveKanbanColumns, groupBy, columnLookup, todayDateOnly]);
174
253
  // Group items by the groupBy field
175
254
  const groupedTasks = useMemo(() => {
176
255
  const groups = {};
177
256
  // Initialize all columns
178
- kanbanColumns.forEach(col => {
257
+ effectiveKanbanColumns.forEach(col => {
179
258
  groups[String(col.value)] = [];
180
259
  });
181
260
  // Distribute tasks
@@ -232,7 +311,7 @@ export function TaskKanban({ tasks, columns: kanbanColumns, groupBy, searchQuery
232
311
  });
233
312
  }
234
313
  return groups;
235
- }, [tasks, allTasks, kanbanColumns, groupBy, columnLookup, scheduleFilteredTaskIdSet, todayDateOnly, sortBy, sortOrder]);
314
+ }, [tasks, allTasks, effectiveKanbanColumns, groupBy, columnLookup, scheduleFilteredTaskIdSet, todayDateOnly, sortBy, sortOrder]);
236
315
  const activeTaskId = activeId ? getTaskIdFromCardId(activeId) : null;
237
316
  const activeTaskOverlay = activeTaskId ? tasks.find(t => t.id === activeTaskId) : null;
238
317
  // Scroll Syncing Refs and Logic
@@ -248,6 +327,8 @@ export function TaskKanban({ tasks, columns: kanbanColumns, groupBy, searchQuery
248
327
  const lastReportedScrollLeftRef = useRef(-1);
249
328
  // Calculate total width for scroll syncing
250
329
  const getIsColumnHidden = (columnValue, title) => {
330
+ if (!filtersReady)
331
+ return false;
251
332
  if (groupBy === 'category')
252
333
  return !filterCategories.includes(String(columnValue));
253
334
  if (groupBy === 'type')
@@ -269,7 +350,7 @@ export function TaskKanban({ tasks, columns: kanbanColumns, groupBy, searchQuery
269
350
  const COL_WIDTH = 320;
270
351
  const COL_COLLAPSED = 72;
271
352
  let width = 0;
272
- kanbanColumns.forEach((col, index) => {
353
+ effectiveKanbanColumns.forEach((col, index) => {
273
354
  const items = groupedTasks[String(col.value)] || [];
274
355
  const isExplicitlyHidden = getIsColumnHidden(col.value, col.label);
275
356
  const isAutoHidden = groupBy !== 'schedule' && emptyColumnMode === 'hide' && items.length === 0;
@@ -280,7 +361,7 @@ export function TaskKanban({ tasks, columns: kanbanColumns, groupBy, searchQuery
280
361
  width += GAP;
281
362
  });
282
363
  return width;
283
- }, [kanbanColumns, groupedTasks, emptyColumnMode, groupBy, filterCategories, filterTypes, filterPriorities, filterStatus]);
364
+ }, [effectiveKanbanColumns, groupedTasks, emptyColumnMode, groupBy, filterCategories, filterTypes, filterPriorities, filterStatus, filterAssignees, filtersReady]);
284
365
  const emitScrollLeft = useCallback((scrollLeft) => {
285
366
  if (!onScrollLeftChange)
286
367
  return;
@@ -353,7 +434,7 @@ export function TaskKanban({ tasks, columns: kanbanColumns, groupBy, searchQuery
353
434
  return () => {
354
435
  window.removeEventListener('resize', updatePanAvailability);
355
436
  };
356
- }, [totalWidth, kanbanColumns.length, groupedTasks]);
437
+ }, [totalWidth, effectiveKanbanColumns.length, groupedTasks]);
357
438
  useEffect(() => {
358
439
  const handlePointerMove = (event) => {
359
440
  const pan = panStateRef.current;
@@ -439,20 +520,12 @@ export function TaskKanban({ tasks, columns: kanbanColumns, groupBy, searchQuery
439
520
  void onAssignTaskToWorkstream?.(activeTaskDataId, overWorkstreamDataId);
440
521
  return;
441
522
  }
442
- if (overType === 'planning-task-unlink' && activeTaskDataId) {
443
- void onAssignTaskToWorkstream?.(activeTaskDataId, null);
444
- return;
445
- }
446
523
  }
447
524
  if (activeType === 'planning-workstream') {
448
525
  if (overType === 'planning-initiative-target' && activeWorkstreamDataId && overInitiativeDataId) {
449
526
  void onAssignWorkstreamToInitiative?.(activeWorkstreamDataId, overInitiativeDataId);
450
527
  return;
451
528
  }
452
- if (overType === 'planning-workstream-unlink' && activeWorkstreamDataId) {
453
- void onAssignWorkstreamToInitiative?.(activeWorkstreamDataId, null);
454
- return;
455
- }
456
529
  return;
457
530
  }
458
531
  const activeId = String(active.id);
@@ -474,7 +547,7 @@ export function TaskKanban({ tasks, columns: kanbanColumns, groupBy, searchQuery
474
547
  return;
475
548
  // Find the column definition
476
549
  const column = columnLookup.get(containerId)
477
- || kanbanColumns.find(c => String(c.value) === containerId || c.label === containerId);
550
+ || effectiveKanbanColumns.find(c => String(c.value) === containerId || c.label === containerId);
478
551
  if (column) {
479
552
  if (groupBy === 'schedule') {
480
553
  const targetColumn = String(column.value);
@@ -681,12 +754,12 @@ export function TaskKanban({ tasks, columns: kanbanColumns, groupBy, searchQuery
681
754
  return (_jsxs(DndContext, { sensors: sensors, collisionDetection: customCollisionDetection, onDragStart: handleDragStart, onDragOver: handleDragOver, onDragEnd: handleDragEnd, onDragCancel: (event) => {
682
755
  lastPlanningOverRef.current = null;
683
756
  setActiveId(null);
684
- }, children: [planningDropTargets, _jsxs("div", { className: styles.kanbanWrapper, children: [_jsx("div", { ref: topScrollRef, className: `${styles.kanbanTopScroll} tf-scrollbar`, children: _jsx("div", { className: styles.kanbanTopScrollSpacer, style: { width: `${totalWidth}px` } }) }), _jsx("div", { className: styles.kanbanContainer, ref: containerRef, children: kanbanColumns.map((column) => {
757
+ }, children: [planningDropTargets, _jsxs("div", { className: styles.kanbanWrapper, children: [_jsx("div", { ref: topScrollRef, className: `${styles.kanbanTopScroll} tf-scrollbar`, children: _jsx("div", { className: styles.kanbanTopScrollSpacer, style: { width: `${totalWidth}px` } }) }), _jsx("div", { className: styles.kanbanContainer, ref: containerRef, children: effectiveKanbanColumns.map((column) => {
685
758
  const columnTasks = groupedTasks[String(column.value)] || [];
686
759
  const isExplicitlyHidden = getIsColumnHidden(column.value, column.label);
687
760
  const isAutoHidden = groupBy !== 'schedule' && emptyColumnMode === 'hide' && columnTasks.length === 0;
688
761
  const isScheduleMode = groupBy === 'schedule';
689
- const hasBacklogColumn = isScheduleMode && kanbanColumns.some((entry) => String(entry.value) === 'backlog');
762
+ const hasBacklogColumn = isScheduleMode && effectiveKanbanColumns.some((entry) => String(entry.value) === 'backlog');
690
763
  const isBacklog = isScheduleMode && String(column.value) === 'backlog';
691
764
  const isExpired = isScheduleMode && String(column.value) === 'expired';
692
765
  const backlogTasks = groupedTasks.backlog || [];