@taskforcehq/taskforce 0.3.328 → 0.3.330

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (485) hide show
  1. package/dist/Taskforce.module.css +523 -79
  2. package/dist/TaskforceCore.js +237 -230
  3. package/dist/annotatedAttachments/AnnotatedAttachmentSessionStore.js +1 -1
  4. package/dist/cli.js +34 -0
  5. package/dist/cliCloudTargetGuard.d.ts +5 -0
  6. package/dist/cliCloudTargetGuard.js +11 -0
  7. package/dist/components/features/AiProfilesModule.js +3 -5
  8. package/dist/components/features/AnnotatedAttachmentWorkspace.js +24 -8
  9. package/dist/components/features/TaskSettings.d.ts +12 -1
  10. package/dist/components/features/TaskSettings.js +217 -54
  11. package/dist/components/features/TaskforceAgentsModule.d.ts +1 -2
  12. package/dist/components/features/TaskforceAgentsModule.js +586 -116
  13. package/dist/components/features/agentCapabilities/AgentCapabilitiesPrototype.d.ts +1 -1
  14. package/dist/components/features/agentConnections/AgentConnectionControl.d.ts +15 -0
  15. package/dist/components/features/agentConnections/AgentConnectionControl.js +125 -0
  16. package/dist/components/features/agentConnections/ModelConnectionsPanel.d.ts +18 -0
  17. package/dist/components/features/agentConnections/ModelConnectionsPanel.js +393 -0
  18. package/dist/components/features/agentConnections/modelConnectionsApi.d.ts +65 -0
  19. package/dist/components/features/agentConnections/modelConnectionsApi.js +129 -0
  20. package/dist/components/features/planning/PlanningModule.js +2 -5
  21. package/dist/components/features/planning/PlanningTaskOrderList.d.ts +1 -1
  22. package/dist/components/features/planning/PlanningTaskOrderList.js +17 -6
  23. package/dist/components/features/planning/planningTaskArrangement.d.ts +1 -0
  24. package/dist/components/features/planning/planningTaskArrangement.js +5 -5
  25. package/dist/components/features/taskforceAgentAssignments/AgentBehaviorAssignments.js +15 -24
  26. package/dist/components/features/taskforceAgentEditorModel.d.ts +2 -1
  27. package/dist/components/features/taskforceAgentEditorModel.js +5 -1
  28. package/dist/components/features/workflowManager/workflowManagerApi.d.ts +1 -1
  29. package/dist/components/features/workflowManager/workflowManagerApi.js +3 -0
  30. package/dist/components/task/TaskCard.d.ts +5 -0
  31. package/dist/components/task/TaskCard.js +65 -10
  32. package/dist/components/task/TaskImageReviews.js +14 -5
  33. package/dist/components/task/TaskKanban.d.ts +6 -1
  34. package/dist/components/task/TaskKanban.js +152 -6
  35. package/dist/components/task/TaskList.d.ts +5 -0
  36. package/dist/components/task/TaskList.js +3 -3
  37. package/dist/components/task/TaskWorkflowAssignmentField.js +68 -10
  38. package/dist/components/ui/PasswordInput.d.ts +6 -0
  39. package/dist/components/ui/PasswordInput.js +11 -0
  40. package/dist/components/ui/TopNoticeLayer.js +1 -1
  41. package/dist/components/views/AppShellHeader.js +32 -11
  42. package/dist/components/views/PlanComparisonPage.js +12 -0
  43. package/dist/components/views/StandaloneLayout.js +32 -55
  44. package/dist/components/views/WidgetView.js +3 -3
  45. package/dist/components/views/panels/PlanningDrawer.js +5 -12
  46. package/dist/components/views/standalone/modals/AccountSettingsModal.js +26 -17
  47. package/dist/components/views/standalone/modals/SyncStatusModal.d.ts +4 -3
  48. package/dist/components/views/standalone/modals/SyncStatusModal.js +33 -38
  49. package/dist/config/envSchema.js +60 -1
  50. package/dist/config/localServiceRuntimeContract.d.ts +13 -0
  51. package/dist/config/localServiceRuntimeContract.js +135 -0
  52. package/dist/core/AiProfileService.js +46 -8
  53. package/dist/core/DeletedTaskLifecycleService.d.ts +1 -0
  54. package/dist/core/DeletedTaskLifecycleService.js +37 -6
  55. package/dist/core/McpTokenService.d.ts +23 -1
  56. package/dist/core/McpTokenService.js +93 -10
  57. package/dist/core/TaskAttachmentLinksDurableMutationService.d.ts +3 -2
  58. package/dist/core/TaskAttachmentLinksDurableMutationService.js +33 -9
  59. package/dist/core/TaskChecklistCommandService.d.ts +27 -0
  60. package/dist/core/TaskChecklistCommandService.js +83 -5
  61. package/dist/core/TaskLifecycleCommandService.d.ts +3 -1
  62. package/dist/core/TaskLifecycleCommandService.js +6 -2
  63. package/dist/core/Taskforce.d.ts +94 -2
  64. package/dist/core/Taskforce.js +760 -36
  65. package/dist/core/types.d.ts +14 -0
  66. package/dist/documentReviews/commandService.d.ts +2 -1
  67. package/dist/documentReviews/commandService.js +6 -3
  68. package/dist/hooks/sync/orchestratorShared.d.ts +1 -0
  69. package/dist/hooks/sync/orchestratorShared.js +2 -0
  70. package/dist/hooks/sync/useDurableLocalOutboxDrain.d.ts +1 -1
  71. package/dist/hooks/sync/useDurableTaskCreateMutation.js +1 -1
  72. package/dist/hooks/sync/useDurableTaskMetadataMutation.d.ts +1 -0
  73. package/dist/hooks/sync/useDurableTaskMetadataMutation.js +1 -0
  74. package/dist/hooks/sync/useDurableTaskStatusMutation.d.ts +1 -0
  75. package/dist/hooks/sync/useLocalSyncCoordinatorSnapshot.d.ts +3 -0
  76. package/dist/hooks/sync/useLocalSyncCoordinatorSnapshot.js +85 -9
  77. package/dist/hooks/sync/useSyncStatusControls.d.ts +4 -1
  78. package/dist/hooks/sync/useSyncStatusControls.js +47 -11
  79. package/dist/hooks/tasks/taskHttpMutation.js +1 -0
  80. package/dist/hooks/tasks/useCloudTaskSearch.d.ts +12 -0
  81. package/dist/hooks/tasks/useCloudTaskSearch.js +71 -0
  82. package/dist/hooks/tasks/useTaskDescriptionImageDraftRecovery.d.ts +16 -0
  83. package/dist/hooks/tasks/useTaskDescriptionImageDraftRecovery.js +197 -0
  84. package/dist/hooks/tasks/useTaskEditorNavigation.d.ts +16 -3
  85. package/dist/hooks/tasks/useTaskEditorNavigation.js +72 -13
  86. package/dist/hooks/tasks/useTaskFormActions.d.ts +6 -0
  87. package/dist/hooks/tasks/useTaskFormActions.js +65 -12
  88. package/dist/hooks/ui/useSettingsModel.d.ts +24 -2
  89. package/dist/hooks/ui/useSettingsModel.js +13 -2
  90. package/dist/hooks/ui/useSettingsPersistence.d.ts +12 -1
  91. package/dist/hooks/ui/useSettingsPersistence.js +74 -47
  92. package/dist/hooks/useFilterSort.d.ts +7 -3
  93. package/dist/hooks/useFilterSort.js +15 -5
  94. package/dist/hooks/useSyncOrchestrator.d.ts +3 -0
  95. package/dist/hooks/useSyncOrchestrator.js +111 -2
  96. package/dist/hooks/useTaskData.d.ts +40 -1
  97. package/dist/hooks/useTaskData.js +240 -9
  98. package/dist/hooks/useTaskMutations.d.ts +12 -2
  99. package/dist/hooks/useTaskMutations.js +266 -52
  100. package/dist/hooks/useTaskforce.d.ts +39 -9
  101. package/dist/hooks/useTaskforce.js +359 -40
  102. package/dist/hooks/useUiNotice.d.ts +4 -0
  103. package/dist/hooks/useUiNotice.js +4 -0
  104. package/dist/mcp/adminWorkspaceRegistrar.js +3 -3
  105. package/dist/mcp/clientRegistry.d.ts +2 -2
  106. package/dist/mcp/clientRegistry.js +1 -1
  107. package/dist/mcp/documentAssetRegistrar.js +53 -41
  108. package/dist/mcp/documentHelpers.d.ts +1 -0
  109. package/dist/mcp/documentHelpers.js +7 -3
  110. package/dist/mcp/durableTaskMutationRouter.d.ts +4 -1
  111. package/dist/mcp/durableTaskMutationRouter.js +10 -0
  112. package/dist/mcp/durableTaskRelationshipMutationRouter.js +4 -0
  113. package/dist/mcp/httpProtocolRouting.d.ts +10 -0
  114. package/dist/mcp/httpProtocolRouting.js +19 -0
  115. package/dist/mcp/localCliHealth.d.ts +2 -2
  116. package/dist/mcp/localCliHealth.js +2 -2
  117. package/dist/mcp/localServiceProxy.d.ts +1 -0
  118. package/dist/mcp/localServiceProxy.js +530 -68
  119. package/dist/mcp/planningAttachmentCommandAdapter.d.ts +3 -1
  120. package/dist/mcp/planningAttachmentCommandAdapter.js +20 -2
  121. package/dist/mcp/runtime.d.ts +54 -79
  122. package/dist/mcp/runtime.js +556 -139
  123. package/dist/mcp/taskPlanningRegistrar.js +64 -42
  124. package/dist/mcp/toolCallCompatibility.js +38 -1
  125. package/dist/mcp/toolCatalog.d.ts +1 -0
  126. package/dist/mcp/toolProfiles.d.ts +2 -0
  127. package/dist/mcp/toolProfiles.js +10 -0
  128. package/dist/mcp/toolRegistry.d.ts +1 -0
  129. package/dist/mcp/toolRegistry.js +1 -0
  130. package/dist/mcp/workflowExecutionRegistrar.js +4 -4
  131. package/dist/migrations/taskSchemaMigrations.d.ts +5 -0
  132. package/dist/migrations/taskSchemaMigrations.js +427 -0
  133. package/dist/runtime/appGateDefinitions.d.ts +30 -6
  134. package/dist/runtime/appGateDefinitions.js +6 -6
  135. package/dist/runtime/appGates.d.ts +13 -13
  136. package/dist/runtime/appGates.js +36 -13
  137. package/dist/runtime/nodeAppGates.d.ts +8 -0
  138. package/dist/runtime/nodeAppGates.js +27 -0
  139. package/dist/server/cloudCollectionRead.d.ts +1 -1
  140. package/dist/server/cloudCollectionRead.js +2 -2
  141. package/dist/server/index.d.ts +6 -0
  142. package/dist/server/index.js +123 -14
  143. package/dist/server/localDatabaseIdentity.js +4 -1
  144. package/dist/server/localServiceLease.d.ts +3 -0
  145. package/dist/server/localServiceLease.js +11 -2
  146. package/dist/server/localServiceSessions.d.ts +14 -17
  147. package/dist/server/localServiceSessions.js +308 -94
  148. package/dist/server/localWorkspaceSyncServerRuntime.js +12 -7
  149. package/dist/server/rateLimit.d.ts +1 -0
  150. package/dist/server/rateLimit.js +4 -0
  151. package/dist/server/realtimeSyncWs.js +36 -12
  152. package/dist/server/routes/admin.d.ts +4 -0
  153. package/dist/server/routes/admin.js +113 -3
  154. package/dist/server/routes/agentRoles.js +3 -2
  155. package/dist/server/routes/agentSkills.js +3 -2
  156. package/dist/server/routes/agents.d.ts +7 -0
  157. package/dist/server/routes/agents.js +394 -39
  158. package/dist/server/routes/annotatedAttachments.js +3 -2
  159. package/dist/server/routes/auth.js +3 -1
  160. package/dist/server/routes/billing.js +5 -1
  161. package/dist/server/routes/durableTaskHttpRouters.d.ts +11 -2
  162. package/dist/server/routes/executorPhaseAApprovals.d.ts +19 -0
  163. package/dist/server/routes/executorPhaseAApprovals.js +140 -0
  164. package/dist/server/routes/executorPhaseAIssuerRedemptions.d.ts +11 -0
  165. package/dist/server/routes/executorPhaseAIssuerRedemptions.js +24 -0
  166. package/dist/server/routes/githubReviewEvidence.d.ts +19 -0
  167. package/dist/server/routes/githubReviewEvidence.js +116 -0
  168. package/dist/server/routes/localService.d.ts +15 -4
  169. package/dist/server/routes/localService.js +138 -40
  170. package/dist/server/routes/modelConnections.d.ts +24 -0
  171. package/dist/server/routes/modelConnections.js +205 -0
  172. package/dist/server/routes/primitives.d.ts +2 -0
  173. package/dist/server/routes/shared.d.ts +19 -0
  174. package/dist/server/routes/shared.js +95 -19
  175. package/dist/server/routes/sync.js +1 -0
  176. package/dist/server/routes/syncAuxRoutes.js +9 -2
  177. package/dist/server/routes/syncPullApplyRoutes.js +23 -4
  178. package/dist/server/routes/syncPushRoutes.d.ts +1 -0
  179. package/dist/server/routes/syncPushRoutes.js +1 -0
  180. package/dist/server/routes/syncV3FeedRoutes.js +27 -16
  181. package/dist/server/routes/syncV3LocalCaptureRoutes.js +28 -2
  182. package/dist/server/routes/syncV3LocalFeedApplyRoutes.d.ts +1 -0
  183. package/dist/server/routes/syncV3LocalFeedApplyRoutes.js +26 -0
  184. package/dist/server/routes/syncV3OperationRoutes.js +45 -9
  185. package/dist/server/routes/tasks.js +124 -13
  186. package/dist/server/routes/workflows.js +9 -1
  187. package/dist/server/routes/workspaces.js +43 -1
  188. package/dist/server/routes.js +59 -0
  189. package/dist/server/workspaceDeletionAdmission.d.ts +23 -0
  190. package/dist/server/workspaceDeletionAdmission.js +50 -0
  191. package/dist/service/localServiceCli.js +16 -0
  192. package/dist/service/localServiceClientLifecycle.js +36 -10
  193. package/dist/services/codexAppServerModelGateway.d.ts +161 -0
  194. package/dist/services/codexAppServerModelGateway.js +663 -0
  195. package/dist/services/codexDeviceCodeLoginManager.d.ts +39 -0
  196. package/dist/services/codexDeviceCodeLoginManager.js +265 -0
  197. package/dist/services/codexModelProviderConnectionLifecycle.d.ts +8 -0
  198. package/dist/services/codexModelProviderConnectionLifecycle.js +73 -0
  199. package/dist/services/executorPhaseAApprovalRuntime.d.ts +14 -0
  200. package/dist/services/executorPhaseAApprovalRuntime.js +24 -0
  201. package/dist/services/executorPhaseAApprovalService.d.ts +40 -0
  202. package/dist/services/executorPhaseAApprovalService.js +609 -0
  203. package/dist/services/executorPhaseADriftEvaluator.d.ts +78 -0
  204. package/dist/services/executorPhaseADriftEvaluator.js +93 -0
  205. package/dist/services/executorPhaseAIssuerCore.d.ts +126 -0
  206. package/dist/services/executorPhaseAIssuerCore.js +295 -0
  207. package/dist/services/executorPhaseAIssuerRedemptionService.d.ts +34 -0
  208. package/dist/services/executorPhaseAIssuerRedemptionService.js +158 -0
  209. package/dist/services/githubReviewEvidenceRuntime.d.ts +14 -0
  210. package/dist/services/githubReviewEvidenceRuntime.js +30 -0
  211. package/dist/services/githubReviewEvidenceService.d.ts +93 -0
  212. package/dist/services/githubReviewEvidenceService.js +336 -0
  213. package/dist/services/modelGateway.d.ts +7 -0
  214. package/dist/services/modelProviderConnectionService.d.ts +71 -0
  215. package/dist/services/modelProviderConnectionService.js +279 -0
  216. package/dist/services/modelProviderCredentialHome.d.ts +32 -0
  217. package/dist/services/modelProviderCredentialHome.js +271 -0
  218. package/dist/services/ownerScopedModelConnectionGateway.d.ts +12 -0
  219. package/dist/services/ownerScopedModelConnectionGateway.js +30 -0
  220. package/dist/services/taskforceAgentConnectionBindingService.d.ts +66 -0
  221. package/dist/services/taskforceAgentConnectionBindingService.js +185 -0
  222. package/dist/services/taskforceAgentMcpBridge.d.ts +8 -2
  223. package/dist/services/taskforceAgentMcpBridge.js +30 -27
  224. package/dist/shared/adminEdgeProxy.d.ts +5 -0
  225. package/dist/shared/adminEdgeProxy.js +94 -0
  226. package/dist/shared/adminProxySessionCookies.d.ts +16 -0
  227. package/dist/shared/adminProxySessionCookies.js +86 -0
  228. package/dist/shared/aiProfileColors.d.ts +31 -1
  229. package/dist/shared/aiProfileColors.js +14 -6
  230. package/dist/shared/executorPhaseAApprovalGoldenVector.json +269 -0
  231. package/dist/shared/executorPhaseAApprovalReceipt.d.ts +112 -0
  232. package/dist/shared/executorPhaseAApprovalReceipt.js +58 -0
  233. package/dist/shared/executorPhaseAApprovalTrustPolicy.json +10 -0
  234. package/dist/shared/executorPhaseADriftContracts.d.ts +37 -0
  235. package/dist/shared/executorPhaseADriftContracts.js +63 -0
  236. package/dist/shared/executorPhaseAIssuerContracts.d.ts +75 -0
  237. package/dist/shared/executorPhaseAIssuerContracts.js +90 -0
  238. package/dist/shared/executorPhaseARunAuthorization.d.ts +120 -0
  239. package/dist/shared/executorPhaseARunAuthorization.js +232 -0
  240. package/dist/shared/executorPhaseASchemaValidation.d.ts +7 -0
  241. package/dist/shared/executorPhaseASchemaValidation.js +53 -0
  242. package/dist/shared/executorPhaseASchemas/approval-receipt.schema.json +106 -0
  243. package/dist/shared/executorPhaseASchemas/drift-attestation.schema.json +54 -0
  244. package/dist/shared/executorPhaseASchemas/drift-request.schema.json +47 -0
  245. package/dist/shared/executorPhaseASchemas/foundation-manifest.schema.json +29 -0
  246. package/dist/shared/executorPhaseASchemas/issuer-audit-record.schema.json +24 -0
  247. package/dist/shared/executorPhaseASchemas/issuer-proof.schema.json +43 -0
  248. package/dist/shared/executorPhaseASchemas/issuer-redemption-request.schema.json +18 -0
  249. package/dist/shared/executorPhaseASchemas/issuer-redemption-response.schema.json +39 -0
  250. package/dist/shared/executorPhaseASchemas/logical-envelope.schema.json +149 -0
  251. package/dist/shared/executorPhaseASchemas/preflight-report.schema.json +216 -0
  252. package/dist/shared/executorPhaseASchemas/run-capability.schema.json +111 -0
  253. package/dist/shared/executorPhaseASchemas/sender-proof.schema.json +37 -0
  254. package/dist/shared/executorPhaseASchemas/workload-grant.schema.json +68 -0
  255. package/dist/shared/executorPhaseASchemas/workload-jwt-claims.schema.json +67 -0
  256. package/dist/shared/executorPhaseATiming.d.ts +1 -0
  257. package/dist/shared/executorPhaseATiming.js +1 -0
  258. package/dist/shared/planningIdentity.js +1 -1
  259. package/dist/shared/productLogoKeys.d.ts +2 -0
  260. package/dist/shared/productLogoKeys.js +18 -0
  261. package/dist/shared/taskforceAgentDefinition.d.ts +0 -1
  262. package/dist/shared/taskforceAgentDefinition.js +6 -3
  263. package/dist/shared/taskforceAgentModels.d.ts +1 -0
  264. package/dist/shared/taskforceAgentModels.js +36 -3
  265. package/dist/shared/userFeatureGrants.d.ts +4 -0
  266. package/dist/shared/userFeatureGrants.js +7 -0
  267. package/dist/storage/executorPhaseAApprovalReceiptStore.d.ts +37 -0
  268. package/dist/storage/executorPhaseAApprovalReceiptStore.js +81 -0
  269. package/dist/storage/executorPhaseARunAuthorizationStore.d.ts +103 -0
  270. package/dist/storage/executorPhaseARunAuthorizationStore.js +492 -0
  271. package/dist/storage/githubReviewEvidenceInstallationStore.d.ts +26 -0
  272. package/dist/storage/githubReviewEvidenceInstallationStore.js +89 -0
  273. package/dist/storage/modelProviderConnectionStore.d.ts +99 -0
  274. package/dist/storage/modelProviderConnectionStore.js +446 -0
  275. package/dist/storage/postgresAdapter.d.ts +24 -3
  276. package/dist/storage/postgresAdapter.js +117 -14
  277. package/dist/storage/postgresWorker.js +22 -5
  278. package/dist/storage/postgresWorkerProtocol.d.ts +30 -0
  279. package/dist/storage/postgresWorkerProtocol.js +30 -0
  280. package/dist/storage/taskforceAgentConnectionBindingStore.d.ts +31 -0
  281. package/dist/storage/taskforceAgentConnectionBindingStore.js +84 -0
  282. package/dist/sync/cloudSyncApi.d.ts +4 -1
  283. package/dist/sync/cloudSyncApi.js +7 -2
  284. package/dist/sync/contentSyncState.d.ts +1 -1
  285. package/dist/sync/coordinator/localSyncExecutionPermitStore.d.ts +1 -0
  286. package/dist/sync/coordinator/localSyncExecutionPermitStore.js +67 -30
  287. package/dist/sync/coordinator/localWorkspaceSyncPendingV2PushProgress.d.ts +10 -0
  288. package/dist/sync/coordinator/localWorkspaceSyncPendingV2PushProgress.js +29 -0
  289. package/dist/sync/coordinator/localWorkspaceSyncRunner.js +6 -2
  290. package/dist/sync/coordinator/localWorkspaceSyncRunnerState.d.ts +15 -1
  291. package/dist/sync/coordinator/localWorkspaceSyncRunnerState.js +99 -2
  292. package/dist/sync/coordinator/workspaceSyncCredentialBroker.d.ts +1 -0
  293. package/dist/sync/coordinator/workspaceSyncCredentialBroker.js +33 -4
  294. package/dist/sync/engine/workspaceSyncContentLifecycleAdapter.d.ts +2 -1
  295. package/dist/sync/engine/workspaceSyncContentVersionStore.d.ts +38 -0
  296. package/dist/sync/engine/workspaceSyncContentVersionStore.js +50 -1
  297. package/dist/sync/engine/workspaceSyncEngineBrowserGatewayRemoteServices.js +20 -2
  298. package/dist/sync/engine/workspaceSyncEngineLifecyclePolicy.js +6 -6
  299. package/dist/sync/engine/workspaceSyncEngineLocalServices.d.ts +4 -0
  300. package/dist/sync/engine/workspaceSyncEngineLocalServices.js +11 -0
  301. package/dist/sync/engine/workspaceSyncEnginePushCompletion.d.ts +14 -0
  302. package/dist/sync/engine/workspaceSyncEnginePushCompletion.js +84 -0
  303. package/dist/sync/engine/workspaceSyncEngineRecovery.js +1 -0
  304. package/dist/sync/engine/workspaceSyncEngineRemoteServices.d.ts +11 -0
  305. package/dist/sync/engine/workspaceSyncEngineRemoteServices.js +2 -1
  306. package/dist/sync/engine/workspaceSyncEngineRuntime.d.ts +1 -0
  307. package/dist/sync/engine/workspaceSyncEngineRuntime.js +1 -0
  308. package/dist/sync/engine/workspaceSyncEngineServerRemoteServices.js +31 -4
  309. package/dist/sync/engine/workspaceSyncEngineServerRunnerOperations.d.ts +3 -1
  310. package/dist/sync/engine/workspaceSyncEngineServerRunnerOperations.js +134 -43
  311. package/dist/sync/engine/workspaceSyncEngineServerSnapshotReader.js +6 -0
  312. package/dist/sync/engine/workspaceSyncEngineTransfers.d.ts +1 -1
  313. package/dist/sync/engine/workspaceSyncEngineTransfers.js +11 -4
  314. package/dist/sync/engine/workspaceSyncV2ChangeDispatcher.d.ts +1 -0
  315. package/dist/sync/engine/workspaceSyncV2ChangeDispatcher.js +29 -0
  316. package/dist/sync/syncApplyHandlers.d.ts +2 -0
  317. package/dist/sync/syncApplyHandlers.js +10 -1
  318. package/dist/sync/syncService.d.ts +17 -0
  319. package/dist/sync/syncService.js +87 -19
  320. package/dist/sync/taskforceAgentSyncAuthorization.d.ts +16 -0
  321. package/dist/sync/taskforceAgentSyncAuthorization.js +20 -0
  322. package/dist/sync/v3/combinedFeedCapability.js +8 -0
  323. package/dist/sync/v3/durableInitiativeMutationRouter.js +18 -10
  324. package/dist/sync/v3/durableOperationReplay.d.ts +14 -0
  325. package/dist/sync/v3/durableOperationReplay.js +18 -0
  326. package/dist/sync/v3/durableTaskAttachmentLinksMutationRouter.d.ts +2 -0
  327. package/dist/sync/v3/durableTaskAttachmentLinksMutationRouter.js +14 -1
  328. package/dist/sync/v3/durableTaskChecklistMutationRouter.d.ts +4 -1
  329. package/dist/sync/v3/durableTaskChecklistMutationRouter.js +62 -15
  330. package/dist/sync/v3/durableTaskCommentMutationRouter.js +3 -0
  331. package/dist/sync/v3/durableTaskHttpBulkMutationRouter.d.ts +1 -0
  332. package/dist/sync/v3/durableTaskHttpBulkMutationRouter.js +30 -8
  333. package/dist/sync/v3/durableTaskHttpRootMutationRouter.d.ts +5 -3
  334. package/dist/sync/v3/durableTaskHttpRootMutationRouter.js +37 -2
  335. package/dist/sync/v3/durableTaxonomyMutationRouter.js +5 -0
  336. package/dist/sync/v3/durableWorkflowRuntimeMutationRouter.d.ts +11 -0
  337. package/dist/sync/v3/durableWorkflowRuntimeMutationRouter.js +39 -10
  338. package/dist/sync/v3/durableWorkstreamMutationRouter.js +18 -10
  339. package/dist/sync/v3/durableWorkstreamTaskOrderMutationRouter.js +16 -5
  340. package/dist/sync/v3/localOutboxDispatchRuntime.js +2 -2
  341. package/dist/sync/v3/localTaskAttachmentLinksOutboxService.d.ts +2 -0
  342. package/dist/sync/v3/localTaskAttachmentLinksOutboxService.js +47 -7
  343. package/dist/sync/v3/localTaskChecklistOutboxHandler.js +16 -2
  344. package/dist/sync/v3/localTaskChecklistOutboxService.d.ts +4 -0
  345. package/dist/sync/v3/localTaskChecklistOutboxService.js +14 -1
  346. package/dist/sync/v3/localTaskCreateOutboxService.js +15 -6
  347. package/dist/sync/v3/localTaskMetadataClient.d.ts +1 -0
  348. package/dist/sync/v3/localTaskMetadataClient.js +1 -0
  349. package/dist/sync/v3/localTaskMetadataOutboxHandler.js +5 -1
  350. package/dist/sync/v3/localTaskMetadataOutboxService.d.ts +2 -0
  351. package/dist/sync/v3/localTaskMetadataOutboxService.js +7 -0
  352. package/dist/sync/v3/localTaskRestoreOutboxService.js +14 -6
  353. package/dist/sync/v3/localTaskStatusClient.d.ts +1 -0
  354. package/dist/sync/v3/localTaskStatusClient.js +6 -1
  355. package/dist/sync/v3/localTaskStatusOutboxService.d.ts +10 -0
  356. package/dist/sync/v3/localTaskStatusOutboxService.js +272 -24
  357. package/dist/sync/v3/syncDurabilityStore.d.ts +41 -0
  358. package/dist/sync/v3/syncDurabilityStore.js +199 -13
  359. package/dist/sync/v3/taskAttachmentLinksMutationService.d.ts +6 -4
  360. package/dist/sync/v3/taskAttachmentLinksMutationService.js +19 -10
  361. package/dist/sync/v3/taskChecklistMutationService.d.ts +15 -2
  362. package/dist/sync/v3/taskChecklistMutationService.js +48 -1
  363. package/dist/sync/v3/taskCreateMutationService.d.ts +2 -2
  364. package/dist/sync/v3/taskCreateMutationService.js +7 -4
  365. package/dist/sync/v3/taskMetadataMutationService.d.ts +3 -0
  366. package/dist/sync/v3/taskMetadataMutationService.js +4 -0
  367. package/dist/sync/v3/taskRestoreMutationService.d.ts +2 -2
  368. package/dist/sync/v3/taskRestoreMutationService.js +7 -4
  369. package/dist/sync/v3/taskStatusMutationService.d.ts +31 -1
  370. package/dist/sync/v3/taskStatusMutationService.js +123 -3
  371. package/dist/sync/v3/workflowAssignmentSync.d.ts +6 -0
  372. package/dist/sync/v3/workflowAssignmentSync.js +30 -0
  373. package/dist/sync/v3/workspaceSyncJournalReader.js +1 -1
  374. package/dist/sync/v3/workspaceSyncOperationRetentionService.d.ts +16 -0
  375. package/dist/sync/v3/workspaceSyncOperationRetentionService.js +83 -0
  376. package/dist/sync/v3/workspaceSyncV2ProjectionExclusions.d.ts +1 -1
  377. package/dist/sync/v3/workspaceSyncV2ProjectionExclusions.js +13 -3
  378. package/dist/sync/v3/workspaceSyncV3AttachmentApplyObligationStore.d.ts +11 -0
  379. package/dist/sync/v3/workspaceSyncV3AttachmentApplyObligationStore.js +27 -10
  380. package/dist/sync/v3/workspaceSyncV3AttachmentAssetHydration.d.ts +2 -1
  381. package/dist/sync/v3/workspaceSyncV3AttachmentAssetHydration.js +52 -10
  382. package/dist/sync/v3/workspaceSyncV3CloudOperationHandler.d.ts +1 -0
  383. package/dist/sync/v3/workspaceSyncV3CloudOperationHandler.js +18 -3
  384. package/dist/sync/v3/workspaceSyncV3CombinedFeedOrchestrator.js +8 -3
  385. package/dist/sync/v3/workspaceSyncV3CombinedLocalApply.js +51 -10
  386. package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.d.ts +14 -0
  387. package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.js +49 -25
  388. package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.d.ts +13 -4
  389. package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.js +124 -57
  390. package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.d.ts +20 -0
  391. package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.js +106 -30
  392. package/dist/sync/v3/workspaceSyncV3CombinedWireContract.d.ts +4 -1
  393. package/dist/sync/v3/workspaceSyncV3CombinedWireContract.js +34 -0
  394. package/dist/sync/v3/workspaceSyncV3CoverageRegistry.js +12 -0
  395. package/dist/sync/v3/workspaceSyncV3FeedProfile.d.ts +1 -1
  396. package/dist/sync/v3/workspaceSyncV3LegacyBoundaryAttestation.d.ts +1 -0
  397. package/dist/sync/v3/workspaceSyncV3LegacyBoundaryAttestation.js +23 -10
  398. package/dist/sync/v3/workspaceSyncV3NestedTaskApply.d.ts +3 -0
  399. package/dist/sync/v3/workspaceSyncV3NestedTaskApply.js +64 -13
  400. package/dist/sync/v3/workspaceSyncV3NestedTaskCodecs.d.ts +9 -0
  401. package/dist/sync/v3/workspaceSyncV3NestedTaskCodecs.js +26 -0
  402. package/dist/sync/v3/workspaceSyncV3NestedTaskProjection.d.ts +15 -5
  403. package/dist/sync/v3/workspaceSyncV3NestedTaskProjection.js +50 -14
  404. package/dist/sync/v3/workspaceSyncV3NestedTaskRepairSnapshot.d.ts +2 -1
  405. package/dist/sync/v3/workspaceSyncV3NestedTaskRepairSnapshot.js +11 -3
  406. package/dist/sync/v3/workspaceSyncV3OperationProtocol.d.ts +5 -0
  407. package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.d.ts +7 -0
  408. package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.js +55 -9
  409. package/dist/sync/v3/workspaceSyncV3RepairSnapshotRetentionService.d.ts +17 -0
  410. package/dist/sync/v3/workspaceSyncV3RepairSnapshotRetentionService.js +64 -0
  411. package/dist/sync/v3/workspaceSyncV3TaskCommentAudit.js +9 -2
  412. package/dist/sync/v3/workspaceSyncV3TaskCoverCoverage.d.ts +7 -0
  413. package/dist/sync/v3/workspaceSyncV3TaskCoverCoverage.js +37 -0
  414. package/dist/sync/v3/workspaceSyncV3TaskCoverWireContract.d.ts +6 -0
  415. package/dist/sync/v3/workspaceSyncV3TaskCoverWireContract.js +9 -0
  416. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverCoverage.d.ts +7 -0
  417. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverCoverage.js +33 -0
  418. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverWireContract.d.ts +7 -0
  419. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverWireContract.js +8 -0
  420. package/dist/sync/workspacePullFeed.js +2 -1
  421. package/dist/sync/workspaceRepair.d.ts +8 -2
  422. package/dist/sync/workspaceRepair.js +222 -6
  423. package/dist/sync/workspaceSyncModel.d.ts +21 -0
  424. package/dist/sync/workspaceSyncModel.js +35 -7
  425. package/dist/sync/workspaceSyncState.d.ts +1 -0
  426. package/dist/sync/workspaceSyncV2SnapshotBuilder.d.ts +6 -0
  427. package/dist/sync/workspaceSyncV2SnapshotBuilder.js +5 -0
  428. package/dist/types.d.ts +47 -1
  429. package/dist/types.js +6 -0
  430. package/dist/ui/assets/AiIdentityRosterCard-OcSz1PkK.js +1 -0
  431. package/dist/ui/assets/AiProfilesModule-ByhYW5Xi.js +1 -0
  432. package/dist/ui/assets/AnnotatedAttachmentWorkspace-BTM6nIg_.js +3 -0
  433. package/dist/ui/assets/AnnotatedAttachmentWorkspace-TzYu7pkG.css +1 -0
  434. package/dist/ui/assets/{AssetTraySortControl-Kf1pelSy.js → AssetTraySortControl-DabEG8L4.js} +1 -1
  435. package/dist/ui/assets/{ContextAttachmentManager-B8boOs6Q.js → ContextAttachmentManager-Coa8yVGM.js} +2 -2
  436. package/dist/ui/assets/{DocumentWorkspace-DXH4XUsB.js → DocumentWorkspace-BB0qhdix.js} +1 -1
  437. package/dist/ui/assets/{EntityActivityTimeline-BtSTq0ON.js → EntityActivityTimeline-CZ8x4UJE.js} +1 -1
  438. package/dist/ui/assets/PlanningModule-pRPjR7v5.js +1 -0
  439. package/dist/ui/assets/PlansPage-D86pZSSl.js +1 -0
  440. package/dist/ui/assets/TaskContextUpload-BVIkU9yT.js +1 -0
  441. package/dist/ui/assets/TaskSettings-Cv1mNhv_.js +12 -0
  442. package/dist/ui/assets/TaskforceAgentsModule-b-8R25cJ.css +1 -0
  443. package/dist/ui/assets/TaskforceAgentsModule-gmH-PD2q.js +24 -0
  444. package/dist/ui/assets/{WorkflowManagerModule-DWFspC-o.js → WorkflowManagerModule-DbfnHJ-f.js} +1 -1
  445. package/dist/ui/assets/index-BZ-hdZSk.css +1 -0
  446. package/dist/ui/assets/index-CTsDBaef.js +7 -0
  447. package/dist/ui/assets/{vendor-icons-BkFLXavV.js → vendor-icons-Bsq-mcEn.js} +1 -1
  448. package/dist/ui/branding/logos/letterhead_dark.png +0 -0
  449. package/dist/ui/branding/logos/letterhead_light.png +0 -0
  450. package/dist/ui/branding/logos/signature_dark.png +0 -0
  451. package/dist/ui/branding/logos/signature_light.png +0 -0
  452. package/dist/ui/index.html +3 -3
  453. package/dist/utils/aiProfileDefaultLogo.js +16 -48
  454. package/dist/utils/httpSetCookie.d.ts +1 -0
  455. package/dist/utils/httpSetCookie.js +4 -1
  456. package/dist/utils/localRuntimeUrl.d.ts +1 -0
  457. package/dist/utils/localRuntimeUrl.js +14 -0
  458. package/dist/utils/productLogoRegistry.d.ts +2 -0
  459. package/dist/utils/productLogoRegistry.js +36 -0
  460. package/dist/utils/syncStatusPresentation.d.ts +4 -0
  461. package/dist/utils/syncStatusPresentation.js +17 -0
  462. package/dist/utils/taskActivity.d.ts +3 -2
  463. package/dist/utils/taskActivity.js +19 -2
  464. package/dist/utils/taskEditorReconciliation.d.ts +40 -0
  465. package/dist/utils/taskEditorReconciliation.js +217 -0
  466. package/dist/utils/taskEvents.d.ts +2 -0
  467. package/dist/utils/taskNormalization.d.ts +1 -0
  468. package/dist/utils/taskNormalization.js +39 -0
  469. package/dist/utils/taskSearch.js +2 -2
  470. package/dist/utils/uiNotice.d.ts +4 -0
  471. package/dist/utils/workspaceSyncPresentation.d.ts +1 -1
  472. package/dist/utils/workspaceSyncPresentation.js +23 -17
  473. package/package.json +36 -6
  474. package/dist/ui/assets/AiIdentityRosterCard-MZs7lVED.js +0 -1
  475. package/dist/ui/assets/AiProfilesModule-C3i0LOxe.js +0 -1
  476. package/dist/ui/assets/AnnotatedAttachmentWorkspace-CBRZ8rca.css +0 -1
  477. package/dist/ui/assets/AnnotatedAttachmentWorkspace-DVZk5Tln.js +0 -3
  478. package/dist/ui/assets/PlanningModule-BPVyEa-f.js +0 -1
  479. package/dist/ui/assets/PlansPage-ChqgxALc.js +0 -1
  480. package/dist/ui/assets/TaskContextUpload-CB3ol0sN.js +0 -1
  481. package/dist/ui/assets/TaskSettings-g4ECKNOz.js +0 -12
  482. package/dist/ui/assets/TaskforceAgentsModule-BazdUwxZ.js +0 -21
  483. package/dist/ui/assets/TaskforceAgentsModule-D6IC0S7Q.css +0 -1
  484. package/dist/ui/assets/index-BUplSsv_.js +0 -7
  485. package/dist/ui/assets/index-gz2EXuoK.css +0 -1
@@ -0,0 +1,129 @@
1
+ import { fetchTaskforceApi } from '../../../utils/taskforceApiClient.js';
2
+ export class ModelConnectionsApiError extends Error {
3
+ code;
4
+ status;
5
+ constructor(message, code, status) {
6
+ super(message);
7
+ this.code = code;
8
+ this.status = status;
9
+ this.name = 'ModelConnectionsApiError';
10
+ }
11
+ }
12
+ async function requestJson(path, init, context) {
13
+ const headers = new Headers(init?.headers || undefined);
14
+ if (init?.body)
15
+ headers.set('Content-Type', 'application/json');
16
+ const workspaceId = String(context.workspaceId || '').trim();
17
+ if (workspaceId && workspaceId !== 'default')
18
+ headers.set('x-taskforce-workspace-id', workspaceId);
19
+ const requestPath = context.resolveApiUrl?.(path) || path;
20
+ const response = await fetchTaskforceApi(requestPath, {
21
+ credentials: 'include',
22
+ ...init,
23
+ headers,
24
+ }, context.apiBaseUrl);
25
+ const payload = await response.json().catch(() => ({}));
26
+ if (!response.ok || payload.success === false) {
27
+ throw new ModelConnectionsApiError(String(payload.error || `Model connection request failed (${response.status}).`), payload.code, response.status);
28
+ }
29
+ return payload;
30
+ }
31
+ export async function listModelConnections(context) {
32
+ const payload = await requestJson('/api/taskforce/model-connections', undefined, context);
33
+ return Array.isArray(payload.connections) ? payload.connections : [];
34
+ }
35
+ export async function loadModelConnectionsSnapshot(context) {
36
+ const payload = await requestJson('/api/taskforce/model-connections', undefined, context);
37
+ return {
38
+ eligible: payload.eligible === true,
39
+ connections: Array.isArray(payload.connections) ? payload.connections : [],
40
+ };
41
+ }
42
+ export async function createOpenAiCodexConnection(context) {
43
+ const payload = await requestJson('/api/taskforce/model-connections', {
44
+ method: 'POST',
45
+ body: JSON.stringify({
46
+ providerKey: 'openai',
47
+ authenticationType: 'chatgpt_device_code',
48
+ }),
49
+ }, context);
50
+ if (!payload.connection)
51
+ throw new ModelConnectionsApiError('Model connection response was incomplete.');
52
+ return payload.connection;
53
+ }
54
+ export async function startDeviceCodeLogin(connectionId, context) {
55
+ const payload = await requestJson(`/api/taskforce/model-connections/${encodeURIComponent(connectionId)}/login`, { method: 'POST' }, context);
56
+ if (!payload.login)
57
+ throw new ModelConnectionsApiError('Device authorization response was incomplete.');
58
+ return payload.login;
59
+ }
60
+ export async function getDeviceCodeLogin(connectionId, sessionId, context) {
61
+ const payload = await requestJson(`/api/taskforce/model-connections/${encodeURIComponent(connectionId)}/login/${encodeURIComponent(sessionId)}`, undefined, context);
62
+ if (!payload.login)
63
+ throw new ModelConnectionsApiError('Device authorization response was incomplete.');
64
+ return payload.login;
65
+ }
66
+ export async function cancelDeviceCodeLogin(connectionId, sessionId, context) {
67
+ const payload = await requestJson(`/api/taskforce/model-connections/${encodeURIComponent(connectionId)}/login/${encodeURIComponent(sessionId)}/cancel`, { method: 'POST' }, context);
68
+ if (!payload.login)
69
+ throw new ModelConnectionsApiError('Device authorization response was incomplete.');
70
+ return payload.login;
71
+ }
72
+ async function runConnectionOperation(connectionId, operation, context) {
73
+ const payload = await requestJson(`/api/taskforce/model-connections/${encodeURIComponent(connectionId)}/${operation}`, { method: 'POST' }, context);
74
+ if (!payload.connection)
75
+ throw new ModelConnectionsApiError('Model connection response was incomplete.');
76
+ return payload.connection;
77
+ }
78
+ export const verifyModelConnection = (connectionId, context) => (runConnectionOperation(connectionId, 'verify', context));
79
+ export const refreshModelConnection = (connectionId, context) => (runConnectionOperation(connectionId, 'refresh', context));
80
+ export const disconnectModelConnection = (connectionId, context) => (runConnectionOperation(connectionId, 'disconnect', context));
81
+ export async function renameModelConnection(connectionId, displayName, context) {
82
+ const payload = await requestJson(`/api/taskforce/model-connections/${encodeURIComponent(connectionId)}`, {
83
+ method: 'PATCH',
84
+ body: JSON.stringify({ displayName }),
85
+ }, context);
86
+ if (!payload.connection)
87
+ throw new ModelConnectionsApiError('Model connection response was incomplete.');
88
+ return payload.connection;
89
+ }
90
+ export async function removeModelConnection(connectionId, context) {
91
+ await requestJson(`/api/taskforce/model-connections/${encodeURIComponent(connectionId)}`, { method: 'DELETE' }, context);
92
+ }
93
+ export async function inspectAgentConnectionBinding(agentId, context) {
94
+ const workspaceId = encodeURIComponent(String(context.workspaceId || '').trim());
95
+ const payload = await requestJson(`/api/taskforce/agents/${encodeURIComponent(agentId)}/connection-binding?workspaceId=${workspaceId}`, undefined, context);
96
+ return payload.binding || { bound: false, available: false, reasonCode: 'MODEL_CONNECTION_REQUIRED' };
97
+ }
98
+ export async function bindAgentConnection(agentId, connectionId, context) {
99
+ const payload = await requestJson(`/api/taskforce/agents/${encodeURIComponent(agentId)}/connection-binding`, {
100
+ method: 'PUT',
101
+ body: JSON.stringify({ workspaceId: context.workspaceId, connectionId }),
102
+ }, context);
103
+ if (!payload.binding)
104
+ throw new ModelConnectionsApiError('Agent connection response was incomplete.');
105
+ return payload.binding;
106
+ }
107
+ export async function clearAgentConnectionBinding(agentId, context) {
108
+ await requestJson(`/api/taskforce/agents/${encodeURIComponent(agentId)}/connection-binding`, {
109
+ method: 'DELETE',
110
+ body: JSON.stringify({ workspaceId: context.workspaceId }),
111
+ }, context);
112
+ }
113
+ export function modelConnectionFailureMessage(code, fallback = 'The connection needs to be authorized again.') {
114
+ switch (String(code || '').trim().toUpperCase()) {
115
+ case 'MODEL_CONNECTION_DEVICE_CODE_UNAVAILABLE':
116
+ return 'ChatGPT device authorization is unavailable for this account. Retry later or use another connection.';
117
+ case 'MODEL_CONNECTION_RATE_LIMITED':
118
+ return 'ChatGPT temporarily rate limited this connection. Wait a moment, then retry.';
119
+ case 'MODEL_CONNECTION_LOGIN_LIMIT_REACHED':
120
+ case 'MODEL_CONNECTION_LOGIN_CAPACITY_REACHED':
121
+ return 'Device authorization capacity is temporarily full. Wait a moment, then retry.';
122
+ case 'MODEL_CONNECTION_LOGIN_CANCELLED':
123
+ return 'Device authorization was cancelled.';
124
+ case 'MODEL_CONNECTION_LEASE_LOST':
125
+ return 'The connection changed while authorization was running. Start again.';
126
+ default:
127
+ return fallback;
128
+ }
129
+ }
@@ -1,6 +1,6 @@
1
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';
@@ -223,7 +223,6 @@ export function PlanningModule({ model }) {
223
223
  const [showArchivedPlanning, setShowArchivedPlanning] = React.useState(false);
224
224
  const taskArrangeMode = model.taskArrangeMode || 'execution';
225
225
  const [createState, setCreateState] = React.useState(null);
226
- const [showParentLinkPicker, setShowParentLinkPicker] = React.useState(false);
227
226
  const [pendingUnlink, setPendingUnlink] = React.useState(null);
228
227
  const [relationshipRecovery, setRelationshipRecovery] = React.useState(null);
229
228
  const [isChangingRelationship, setIsChangingRelationship] = React.useState(false);
@@ -349,7 +348,6 @@ export function PlanningModule({ model }) {
349
348
  void model.hydrateEntity(selectedEntityType, selectedEntityId);
350
349
  }, [model.hydrateEntity, selectedEntityId, selectedEntityType]);
351
350
  React.useEffect(() => {
352
- setShowParentLinkPicker(false);
353
351
  setPendingUnlink(null);
354
352
  setRelationshipRecovery(null);
355
353
  setIsChangingRelationship(false);
@@ -434,7 +432,6 @@ export function PlanningModule({ model }) {
434
432
  const result = await model.assignWorkstreamToInitiative(selectedWorkstream.id, option.referenceLabel);
435
433
  if (result !== false) {
436
434
  setSelectedInitiativeId(option.id);
437
- setShowParentLinkPicker(false);
438
435
  }
439
436
  }
440
437
  finally {
@@ -562,7 +559,7 @@ export function PlanningModule({ model }) {
562
559
  ? `${formatInitiativeReference(selectedInitiative)} ${selectedInitiative.title}`.trim()
563
560
  : 'its initiative',
564
561
  });
565
- }, 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
566
563
  ? (taskIds) => model.reorderWorkstreamTasks?.(selectedWorkstream.id, mergeVisiblePlanningTaskOrder(arrangePlanningTasks(selectedWorkstream.tasks ?? [], 'execution'), taskIds))
567
564
  : undefined, children: (task) => {
568
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
  }
@@ -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') {
@@ -6,8 +6,8 @@ import { TASKFORCE_AGENT_SKILLS_MUTATED_EVENT, } from '../../../utils/taskforceA
6
6
  import taskforceStyles from '../../../Taskforce.module.css';
7
7
  import { loadAgentBehaviorCatalogs, } from './agentBehaviorCatalogApi.js';
8
8
  import styles from './AgentBehaviorAssignments.module.css';
9
- function revisionValue(reference) {
10
- return reference.resolution === 'pinned' ? String(reference.revision ?? '') : '';
9
+ function versionValue(reference) {
10
+ return reference.resolution === 'pinned' ? `revision:${String(reference.revision ?? '')}` : 'current';
11
11
  }
12
12
  function pinReference(reference, revision) {
13
13
  return {
@@ -45,6 +45,11 @@ function selectedRevision(value) {
45
45
  const numeric = Number(value);
46
46
  return Number.isInteger(numeric) && String(numeric) === value ? numeric : value;
47
47
  }
48
+ function referenceForVersion(reference, value) {
49
+ if (value === 'current')
50
+ return currentReference(reference);
51
+ return pinReference(reference, selectedRevision(value.slice('revision:'.length)));
52
+ }
48
53
  export function AgentBehaviorAssignments({ workspaceId, roleRef, skillRefs, onRoleRefChange, onSkillRefsChange, onManageRoles, onManageSkills, }) {
49
54
  const [roles, setRoles] = useState([]);
50
55
  const [skills, setSkills] = useState([]);
@@ -113,26 +118,18 @@ export function AgentBehaviorAssignments({ workspaceId, roleRef, skillRefs, onRo
113
118
  ...(roleRef.resolution === 'pinned'
114
119
  && selectedRole
115
120
  && !selectedRole.revisions.some((revision) => String(revision.revision) === String(roleRef.revision))
116
- ? [`Pinned Role revision ${String(roleRef.revision)} is unavailable.`]
121
+ ? [`Role version ${String(roleRef.revision)} is unavailable.`]
117
122
  : []),
118
123
  ]
119
124
  : [];
120
125
  return (_jsxs("div", { className: styles.assignments, children: [_jsxs("section", { className: styles.section, "aria-labelledby": "agent-role-heading", children: [_jsxs("div", { className: styles.sectionHeader, children: [_jsxs("div", { className: styles.sectionHeading, children: [_jsx(BriefcaseBusiness, { size: 17 }), _jsxs("div", { children: [_jsx("strong", { id: "agent-role-heading", children: "Role" }), _jsx("small", { children: "Optional reusable professional profile. An Agent can have one Role." })] })] }), _jsx("button", { type: "button", className: taskforceStyles.secondaryHeaderBtn, onClick: onManageRoles, children: "Manage Roles" })] }), _jsxs("div", { className: styles.roleControls, children: [_jsxs("label", { className: taskforceStyles.field, children: [_jsx("span", { className: taskforceStyles.label, children: "Role" }), _jsxs("select", { className: taskforceStyles.select, "aria-label": "Role", value: roleRef?.id || '', disabled: loading, onChange: (event) => {
121
126
  const id = event.target.value;
122
127
  onRoleRefChange(id ? { id, resolution: 'current' } : null);
123
- }, children: [_jsx("option", { value: "", children: "No Role" }), roleRef && !selectedRole ? (_jsxs("option", { value: roleRef.id, children: ["Missing Role \u00B7 ", roleRef.id] })) : null, roles.map((role) => (_jsxs("option", { value: role.id, disabled: role.lifecycleStatus === 'retired', children: [role.definition.name, role.lifecycleStatus === 'retired' ? ' · Retired' : ''] }, role.id)))] })] }), _jsxs("label", { className: taskforceStyles.field, children: [_jsx("span", { className: taskforceStyles.label, children: "Version" }), _jsxs("select", { className: taskforceStyles.select, "aria-label": "Role version", value: roleRef?.resolution || 'current', disabled: !roleRef || !selectedRole, onChange: (event) => {
124
- if (!roleRef || !selectedRole)
125
- return;
126
- if (event.target.value === 'current') {
127
- onRoleRefChange(currentReference(roleRef));
128
- return;
129
- }
130
- onRoleRefChange(pinReference(roleRef, selectedRole.currentRevision));
131
- }, children: [_jsx("option", { value: "current", children: "Use latest" }), _jsx("option", { value: "pinned", children: "Pin revision" })] })] }), _jsxs("label", { className: taskforceStyles.field, children: [_jsx("span", { className: taskforceStyles.label, children: "Revision" }), _jsxs("select", { className: taskforceStyles.select, "aria-label": "Role pinned revision", value: roleRef ? revisionValue(roleRef) : '', disabled: !roleRef || roleRef.resolution !== 'pinned', onChange: (event) => {
128
+ }, children: [_jsx("option", { value: "", children: "No Role" }), roleRef && !selectedRole ? (_jsxs("option", { value: roleRef.id, children: ["Missing Role \u00B7 ", roleRef.id] })) : null, roles.map((role) => (_jsxs("option", { value: role.id, disabled: role.lifecycleStatus === 'retired', children: [role.definition.name, role.lifecycleStatus === 'retired' ? ' · Retired' : ''] }, role.id)))] })] }), _jsxs("label", { className: taskforceStyles.field, children: [_jsx("span", { className: taskforceStyles.label, children: "Version" }), _jsxs("select", { className: taskforceStyles.select, "aria-label": "Role version", value: roleRef ? versionValue(roleRef) : 'current', disabled: !roleRef || !selectedRole, onChange: (event) => {
132
129
  if (!roleRef)
133
130
  return;
134
- onRoleRefChange(pinReference(roleRef, selectedRevision(event.target.value)));
135
- }, children: [_jsx("option", { value: "", children: "Current" }), roleRef ? availableRevisions(selectedRole, roleRef).map((revision) => (_jsxs("option", { value: revision, children: ["Revision ", revision] }, revision))) : null] })] })] }), selectedRole?.definition.shortDescription ? (_jsx("small", { className: styles.empty, children: selectedRole.definition.shortDescription })) : null, roleIssues.map((message) => (_jsxs("div", { className: styles.issue, role: "alert", children: [_jsx(AlertTriangle, { size: 13 }), _jsxs("span", { children: [message, " Agent execution is blocked until this reference is repaired."] })] }, message)))] }), _jsxs("section", { className: styles.section, "aria-labelledby": "agent-skills-heading", children: [_jsxs("div", { className: styles.sectionHeader, children: [_jsxs("div", { className: styles.sectionHeading, children: [_jsx(Sparkles, { size: 17 }), _jsxs("div", { children: [_jsx("strong", { id: "agent-skills-heading", children: "Skills" }), _jsx("small", { children: "Composable behavior applied in this exact order. Later Skills take precedence when guidance conflicts." })] })] }), _jsx("button", { type: "button", className: taskforceStyles.secondaryHeaderBtn, onClick: onManageSkills, children: "Manage Skills" })] }), _jsxs("div", { className: styles.skillAdd, children: [_jsxs("label", { className: taskforceStyles.field, children: [_jsx("span", { className: taskforceStyles.label, children: "Add Skill" }), _jsxs("select", { className: taskforceStyles.select, "aria-label": "Skill to add", value: skillToAdd, disabled: loading || activeSkillsToAdd.length === 0, onChange: (event) => setSkillToAdd(event.target.value), children: [_jsx("option", { value: "", children: "Select a Skill" }), activeSkillsToAdd.map((skill) => (_jsx("option", { value: skill.id, children: skill.definition.name }, skill.id)))] })] }), _jsx("button", { type: "button", className: "tf-control-icon", disabled: !skillToAdd, "aria-label": "Add selected Skill", title: "Add selected Skill", onClick: () => {
131
+ onRoleRefChange(referenceForVersion(roleRef, event.target.value));
132
+ }, children: [_jsx("option", { value: "current", children: selectedRole ? `Use latest (Version ${selectedRole.currentRevision})` : 'Use latest' }), roleRef ? availableRevisions(selectedRole, roleRef).map((revision) => (_jsxs("option", { value: `revision:${String(revision)}`, children: ["Version ", revision] }, revision))) : null] })] })] }), selectedRole?.definition.shortDescription ? (_jsx("small", { className: styles.empty, children: selectedRole.definition.shortDescription })) : null, roleIssues.map((message) => (_jsxs("div", { className: styles.issue, role: "alert", children: [_jsx(AlertTriangle, { size: 13 }), _jsxs("span", { children: [message, " Agent execution is blocked until this reference is repaired."] })] }, message)))] }), _jsxs("section", { className: styles.section, "aria-labelledby": "agent-skills-heading", children: [_jsxs("div", { className: styles.sectionHeader, children: [_jsxs("div", { className: styles.sectionHeading, children: [_jsx(Sparkles, { size: 17 }), _jsxs("div", { children: [_jsx("strong", { id: "agent-skills-heading", children: "Skills" }), _jsx("small", { children: "Composable behavior applied in this exact order. Later Skills take precedence when guidance conflicts." })] })] }), _jsx("button", { type: "button", className: taskforceStyles.secondaryHeaderBtn, onClick: onManageSkills, children: "Manage Skills" })] }), _jsxs("div", { className: styles.skillAdd, children: [_jsxs("label", { className: taskforceStyles.field, children: [_jsx("span", { className: taskforceStyles.label, children: "Add Skill" }), _jsxs("select", { className: taskforceStyles.select, "aria-label": "Skill to add", value: skillToAdd, disabled: loading || activeSkillsToAdd.length === 0, onChange: (event) => setSkillToAdd(event.target.value), children: [_jsx("option", { value: "", children: "Select a Skill" }), activeSkillsToAdd.map((skill) => (_jsx("option", { value: skill.id, children: skill.definition.name }, skill.id)))] })] }), _jsx("button", { type: "button", className: "tf-control-icon", disabled: !skillToAdd, "aria-label": "Add selected Skill", title: "Add selected Skill", onClick: () => {
136
133
  if (!skillToAdd || selectedSkillIds.has(skillToAdd))
137
134
  return;
138
135
  onSkillRefsChange([...skillRefs, { id: skillToAdd, resolution: 'current' }]);
@@ -145,20 +142,14 @@ export function AgentBehaviorAssignments({ workspaceId, roleRef, skillRefs, onRo
145
142
  ...(reference.resolution === 'pinned'
146
143
  && skill
147
144
  && !skill.revisions.some((revision) => String(revision.revision) === String(reference.revision))
148
- ? [`Pinned Skill revision ${String(reference.revision)} is unavailable.`]
145
+ ? [`Skill version ${String(reference.revision)} is unavailable.`]
149
146
  : []),
150
147
  ];
151
- return (_jsxs("li", { children: [_jsxs("div", { className: styles.referenceRow, children: [_jsxs("div", { className: styles.referenceCopy, children: [_jsxs("strong", { children: [index + 1, ". ", skill?.definition.name || `Missing Skill · ${reference.id}`] }), _jsx("small", { children: skill?.definition.shortDescription || reference.id })] }), _jsxs("select", { className: taskforceStyles.select, "aria-label": `${skill?.definition.name || reference.id} version`, value: reference.resolution, disabled: !skill, onChange: (event) => {
152
- const next = [...skillRefs];
153
- next[index] = event.target.value === 'current'
154
- ? currentReference(reference)
155
- : pinReference(reference, skill?.revision || 1);
156
- onSkillRefsChange(next);
157
- }, children: [_jsx("option", { value: "current", children: "Use latest" }), _jsx("option", { value: "pinned", children: "Pin revision" })] }), _jsxs("select", { className: taskforceStyles.select, "aria-label": `${skill?.definition.name || reference.id} pinned revision`, value: revisionValue(reference), disabled: reference.resolution !== 'pinned', onChange: (event) => {
148
+ return (_jsxs("li", { children: [_jsxs("div", { className: styles.referenceRow, children: [_jsxs("div", { className: styles.referenceCopy, children: [_jsxs("strong", { children: [index + 1, ". ", skill?.definition.name || `Missing Skill · ${reference.id}`] }), _jsx("small", { children: skill?.definition.shortDescription || reference.id })] }), _jsxs("select", { className: taskforceStyles.select, "aria-label": `${skill?.definition.name || reference.id} version`, value: versionValue(reference), disabled: !skill, onChange: (event) => {
158
149
  const next = [...skillRefs];
159
- next[index] = pinReference(reference, selectedRevision(event.target.value));
150
+ next[index] = referenceForVersion(reference, event.target.value);
160
151
  onSkillRefsChange(next);
161
- }, children: [_jsx("option", { value: "", children: "Current" }), availableRevisions(skill, reference).map((revision) => (_jsxs("option", { value: revision, children: ["Revision ", revision] }, revision)))] }), _jsxs("div", { className: styles.rowActions, children: [_jsx("button", { type: "button", className: "tf-control-icon tf-control-icon-compact", "aria-label": `Move ${skill?.definition.name || reference.id} up`, disabled: index === 0, onClick: () => {
152
+ }, children: [_jsx("option", { value: "current", children: skill ? `Use latest (Version ${skill.revision})` : 'Use latest' }), availableRevisions(skill, reference).map((revision) => (_jsxs("option", { value: `revision:${String(revision)}`, children: ["Version ", revision] }, revision)))] }), _jsxs("div", { className: styles.rowActions, children: [_jsx("button", { type: "button", className: "tf-control-icon tf-control-icon-compact", "aria-label": `Move ${skill?.definition.name || reference.id} up`, disabled: index === 0, onClick: () => {
162
153
  if (index === 0)
163
154
  return;
164
155
  const next = [...skillRefs];
@@ -1,5 +1,5 @@
1
1
  import { type AgentDefinitionV1, type BehaviorReference } from '../../shared/taskforceAgentDefinition.js';
2
- import { type TaskforceAgentProviderKey } from '../../shared/taskforceAgentModels.js';
2
+ import { type TaskforceAgentProviderKey, type TaskforceAgentConnectionScope } from '../../shared/taskforceAgentModels.js';
3
3
  import type { ModelGatewayTier } from '../../services/modelGateway.js';
4
4
  export declare const PERSONALITY_PRESETS: readonly [{
5
5
  readonly key: "practical";
@@ -104,6 +104,7 @@ export declare function buildTaskforceAgentDefinitionFromDraft(input: {
104
104
  providerKey: TaskforceAgentProviderKey;
105
105
  modelKey: string;
106
106
  tier: ModelGatewayTier;
107
+ connectionScope?: TaskforceAgentConnectionScope;
107
108
  }): AgentDefinitionV1;
108
109
  export declare function hasUnsavedAvatarPresentation(definition: AgentDefinitionV1 | null | undefined, draft: TaskforceAgentEditorDraft): boolean;
109
110
  export {};
@@ -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,11 @@ 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'
111
+ ? { connectionScope: input.connectionScope || 'local_dev' }
112
+ : {}),
109
113
  },
110
114
  behavior: {
111
115
  ...(personality ? { personality } : {}),
@@ -14,7 +14,7 @@ export declare function getTaskWorkflowAssignment(taskId: string, context?: Work
14
14
  export type WorkflowCompletionProjection = {
15
15
  executionId: string;
16
16
  taskId: string;
17
- assignmentSnapshot: unknown;
17
+ assignmentSnapshot: WorkflowAssignmentDetails;
18
18
  taskSnapshot?: TaskItem | null;
19
19
  taskAuthoritative?: unknown;
20
20
  };
@@ -80,6 +80,9 @@ export async function completeCurrentWorkflowStep(executionId, idempotencyKey, c
80
80
  taskId: payload.result.taskSnapshot.id,
81
81
  reason: 'workflow-step',
82
82
  ...(installedTask ? { authoritativeTask: installedTask } : {}),
83
+ ...(payload.result.assignmentSnapshot
84
+ ? { authoritativeWorkflowAssignment: payload.result.assignmentSnapshot }
85
+ : {}),
83
86
  });
84
87
  }
85
88
  return payload.result;
@@ -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 {};
@@ -23,7 +23,55 @@ import { TaxonomyDropdown } from '../ui/TaxonomyDropdown';
23
23
  import { AssigneeAvatar, AssigneeIdentity } from '../ui/AssigneeIdentity';
24
24
  import { TaskWorkstreamPicker } from './TaskWorkstreamPicker';
25
25
  import { DocumentTypeIcon } from '../ui/DocumentTypeIcon';
26
- const TaskCardInner = ({ task, searchQuery = '', copiedId = null, taxonomies = [], types = [], priorities = [], categories = [], assigneeOptions = [], workstreams = [], taskWorkstream = null, taskInitiative = null, workspaceId = null, isOverlay = false, isArchived = false, readOnlyMode = null, isRecentlyChanged = false, selectable = false, selected = false, onSelectionChange, onClick, onCopyId, onToggleInProgress, onToggleReview, onToggleComplete, onToggleCancel, onSetStatus, onArchiveTask, onUnarchive, onDelete, deleteActionTitle, taskReferences, onAssigneeChange, onWorkstreamChange, compressed = false, showStatusLabel = false }) => {
26
+ function resolveLatestActivityActor(item, assigneeOptions) {
27
+ if (!item)
28
+ return null;
29
+ const actorRef = String(item.type === 'comment' ? item.comment.author : item.event.actor).trim();
30
+ const actorProfile = item.type === 'comment' ? item.comment.actor : item.event.actorProfile;
31
+ if (!actorRef && !actorProfile)
32
+ return null;
33
+ const normalizedActorRef = actorRef.toLowerCase();
34
+ const option = assigneeOptions.find((candidate) => (String(candidate.value || '').trim().toLowerCase() === normalizedActorRef));
35
+ const actorType = item.type === 'comment'
36
+ ? actorProfile?.kind === 'ai'
37
+ ? 'ai'
38
+ : actorProfile?.kind === 'human'
39
+ ? 'human'
40
+ : option?.kind === 'agent'
41
+ ? 'ai'
42
+ : option?.kind === 'member'
43
+ ? 'human'
44
+ : null
45
+ : item.event.actorType;
46
+ const kind = actorType === 'system' || normalizedActorRef === 'system'
47
+ ? 'system'
48
+ : actorType === 'ai' || actorProfile?.kind === 'ai' || option?.kind === 'agent'
49
+ ? 'agent'
50
+ : 'member';
51
+ if (kind === 'system')
52
+ return { label: 'System' };
53
+ const profileLabel = String(actorProfile?.label || '').trim();
54
+ const optionLabel = String(option?.label || '').trim();
55
+ const isGenericActor = !normalizedActorRef
56
+ || normalizedActorRef === 'user'
57
+ || normalizedActorRef === 'human'
58
+ || normalizedActorRef === 'ai';
59
+ const isOpaqueActor = /^(?:ai-profile|user|member)-[0-9a-f-]{8,}$/i.test(actorRef)
60
+ || /^[0-9a-f]{16,}$/i.test(actorRef);
61
+ const readableActorRef = actorRef
62
+ .replace(/[-_]+/g, ' ')
63
+ .replace(/\s+/g, ' ')
64
+ .trim()
65
+ .replace(/\b\w/g, (character) => character.toUpperCase());
66
+ const label = profileLabel
67
+ || optionLabel
68
+ || (kind === 'agent' && (isGenericActor || isOpaqueActor) ? 'AI Agent' : '')
69
+ || (isGenericActor || isOpaqueActor ? 'Workspace member' : readableActorRef)
70
+ || (kind === 'agent' ? 'AI Agent' : 'Workspace member');
71
+ const color = resolveColor(actorProfile?.color || option?.color);
72
+ return { label, color };
73
+ }
74
+ const TaskCardInner = ({ task, searchQuery = '', copiedId = null, taxonomies = [], types = [], priorities = [], categories = [], assigneeOptions = [], workstreams = [], taskWorkstream = null, taskInitiative = null, workspaceId = null, isOverlay = false, isArchived = false, readOnlyMode = null, isRecentlyChanged = false, selectable = false, selected = false, onSelectionChange, onClick, onCopyId, onToggleInProgress, onToggleReview, onToggleComplete, onToggleCancel, onSetStatus, onArchiveTask, onUnarchive, onDelete, deleteActionTitle, taskReferences, onAssigneeChange, onWorkstreamChange, compressed = false, showStatusLabel = false, showDescription = true, showAttachments = true, showChecklistProgress = true, showLatestActivity = true, tintActivityBackground = false }) => {
27
75
  const taskReference = getTaskReferenceDisplayState(task);
28
76
  const taskReferenceLabel = taskReference.label || (taskReference.isProvisional ? 'Pending' : '');
29
77
  const isProvisionalReference = taskReference.isProvisional;
@@ -71,7 +119,8 @@ const TaskCardInner = ({ task, searchQuery = '', copiedId = null, taxonomies = [
71
119
  kind,
72
120
  };
73
121
  }, [assigneeLabel, assigneeOptions, task.assignee]);
74
- const latestActivity = React.useMemo(() => getLatestTaskActivity(task), [task]);
122
+ const latestActivity = React.useMemo(() => task.latestActivity ?? getLatestTaskActivity(task), [task]);
123
+ const latestActivityActor = React.useMemo(() => resolveLatestActivityActor(latestActivity, assigneeOptions), [assigneeOptions, latestActivity]);
75
124
  const resolvedReadOnlyMode = readOnlyMode || (task.isDeleted ? 'deleted' : (isArchived ? 'archived' : null));
76
125
  const isReadOnly = resolvedReadOnlyMode !== null;
77
126
  const deletedExpiryLabel = React.useMemo(() => {
@@ -99,7 +148,7 @@ const TaskCardInner = ({ task, searchQuery = '', copiedId = null, taxonomies = [
99
148
  return undefined;
100
149
  }, [assigneeOptions, initiativeReferenceLabel, taskInitiative, taskWorkstream, workstreamReferenceLabel]);
101
150
  const latestActivityText = React.useMemo(() => summarizeTaskActivity(latestActivity, formatActivityFieldValue), [formatActivityFieldValue, latestActivity]);
102
- const commentCount = React.useMemo(() => getTaskActivityItems(task).filter((item) => item.type === 'comment').length, [task]);
151
+ const commentCount = React.useMemo(() => task.commentCount ?? getTaskActivityItems(task).filter((item) => item.type === 'comment').length, [task]);
103
152
  const cardClasses = [
104
153
  cardStyles.taskItem,
105
154
  task.status === 'on-hold' ? cardStyles.onHold : '',
@@ -196,10 +245,9 @@ const TaskCardInner = ({ task, searchQuery = '', copiedId = null, taxonomies = [
196
245
  const toTitleCase = (str) => str.replace(/\b\w/g, t => t.toUpperCase());
197
246
  const visibleTaxonomies = getVisibleTaxonomiesForTasks(taxonomies, [task]);
198
247
  const checklistItems = task.checklistItems || [];
199
- const checklistTotal = checklistItems.length;
200
- const checklistCompleted = checklistTotal > 0
201
- ? checklistItems.filter(item => item.isCompleted).length
202
- : 0;
248
+ const checklistTotal = task.checklistCount ?? checklistItems.length;
249
+ const checklistCompleted = task.completedChecklistCount
250
+ ?? (checklistTotal > 0 ? checklistItems.filter(item => item.isCompleted).length : 0);
203
251
  const handleReferenceCopy = (event, label) => {
204
252
  event.stopPropagation();
205
253
  onCopyId?.(event, label);
@@ -232,6 +280,11 @@ const TaskCardInner = ({ task, searchQuery = '', copiedId = null, taxonomies = [
232
280
  const cardCoverAttachment = (() => {
233
281
  if (compressed || isOverlay || !task.cardCoverAssetId)
234
282
  return null;
283
+ if (task.cardCoverAttachment
284
+ && typeof task.cardCoverAttachment !== 'string'
285
+ && task.cardCoverAttachment.assetId === task.cardCoverAssetId) {
286
+ return task.cardCoverAttachment;
287
+ }
235
288
  return (task.attachments || []).find((attachment) => (typeof attachment !== 'string'
236
289
  && String(attachment.assetId || '').trim() === task.cardCoverAssetId
237
290
  && attachment.linkRole === 'image'
@@ -288,7 +341,7 @@ const TaskCardInner = ({ task, searchQuery = '', copiedId = null, taxonomies = [
288
341
  }, children: _jsx("img", { src: cardCoverAttachment.path, alt: cardCoverAttachment.caption
289
342
  || cardCoverAttachment.displayName
290
343
  || cardCoverAttachment.originalFilename
291
- || task.title, loading: "lazy", decoding: "async", onError: () => setCardCoverLoadFailed(true) }) })), _jsxs("div", { className: cardStyles.taskContent, children: [/* Meta Badges moved to bottom */ isReadOnly && (_jsx("div", { className: `${cardStyles.taskMeta} ${cardStyles.taskMetaCompact}` })), _jsxs("div", { children: [_jsxs("div", { className: cardStyles.taskTitle, style: compressed ? { fontSize: '13px', lineHeight: '1.4' } : {}, children: [resolvedReadOnlyMode === 'archived' && '✓ ', resolvedReadOnlyMode === 'deleted' && 'Deleted: ', renderHighlighted(task.title, searchQuery)] }), deletedExpiryLabel && (_jsx("div", { className: cardStyles.deletedExpiry, title: "Trash items are permanently deleted 90 days after deletion.", children: deletedExpiryLabel })), task.description && !isReadOnly && !compressed && (_jsx("div", { className: cardStyles.taskDescription, children: _jsx(Markdown, { variant: "compact", taskReferences: taskReferences, children: task.description }) }))] }), cardAttachments.length > 0 && !isReadOnly && !compressed && (_jsxs("div", { className: cardStyles.attachmentThumbnails, children: [_jsx("div", { className: cardStyles.attachmentImageRow, children: cardAttachments.map((attachment, idx) => {
344
+ || task.title, loading: "lazy", decoding: "async", onError: () => setCardCoverLoadFailed(true) }) })), _jsxs("div", { className: cardStyles.taskContent, children: [/* Meta Badges moved to bottom */ isReadOnly && (_jsx("div", { className: `${cardStyles.taskMeta} ${cardStyles.taskMetaCompact}` })), _jsxs("div", { children: [_jsxs("div", { className: cardStyles.taskTitle, style: compressed ? { fontSize: '13px', lineHeight: '1.4' } : {}, children: [resolvedReadOnlyMode === 'archived' && '✓ ', resolvedReadOnlyMode === 'deleted' && 'Deleted: ', renderHighlighted(task.title, searchQuery)] }), deletedExpiryLabel && (_jsx("div", { className: cardStyles.deletedExpiry, title: "Trash items are permanently deleted 90 days after deletion.", children: deletedExpiryLabel })), showDescription && task.description && !isReadOnly && !compressed && (_jsx("div", { className: cardStyles.taskDescription, children: _jsx(Markdown, { variant: "compact", taskReferences: taskReferences, children: task.description }) }))] }), showAttachments && cardAttachments.length > 0 && !isReadOnly && !compressed && (_jsxs("div", { className: cardStyles.attachmentThumbnails, children: [_jsx("div", { className: cardStyles.attachmentImageRow, children: cardAttachments.map((attachment, idx) => {
292
345
  const path = typeof attachment === 'string' ? attachment : attachment.path;
293
346
  if (!isImageAttachment(attachment))
294
347
  return null;
@@ -319,7 +372,9 @@ const TaskCardInner = ({ task, searchQuery = '', copiedId = null, taxonomies = [
319
372
  return;
320
373
  window.open(path, '_blank');
321
374
  }, title: name, "aria-label": `${name} ${fileType}`, style: { '--context-doc-accent': fileAccentColor }, children: [_jsx(DocumentTypeIcon, { label: fileType, accentColor: fileAccentColor, compact: true }), _jsx("span", { className: cardStyles.contextDocMain, children: _jsx("span", { className: cardStyles.contextDocName, children: name }) })] }, idx));
322
- }) })] })), task.status === 'cancelled' && task.canceledReason && !compressed && (_jsxs("div", { className: cardStyles.taskCancellationReason, children: [_jsx("strong", { children: "Cancellation Reason:" }), " ", renderHighlighted(task.canceledReason, searchQuery)] })), (latestActivityText || commentCount > 0) && !isReadOnly && !compressed && (_jsxs("div", { className: cardStyles.taskLatestComment, "data-task-activity-summary": "true", children: [_jsxs("div", { className: cardStyles.taskLatestCommentHeader, children: [_jsx("strong", { children: latestActivityText ? 'Latest Activity:' : 'Activity:' }), commentCount > 0 && (_jsxs("span", { className: `${styles.metaBadge} ${cardStyles.taskCommentCount}`, title: `${commentCount} ${commentCount === 1 ? 'comment' : 'comments'}`, "aria-label": `${commentCount} ${commentCount === 1 ? 'comment' : 'comments'}`, children: [_jsx(MessageSquare, { size: 12, "aria-hidden": "true" }), _jsx("span", { children: commentCount })] }))] }), latestActivityText && (_jsx("div", { className: cardStyles.taskLatestCommentText, title: latestActivityText, children: renderHighlighted(latestActivityText, searchQuery) }))] })), !isReadOnly && visibleTaxonomies.length > 0 && !compressed && (_jsx("div", { className: `${cardStyles.taskSpecialists} ${cardStyles.taxonomiesList}`, children: visibleTaxonomies.map(tax => {
375
+ }) })] })), task.status === 'cancelled' && task.canceledReason && !compressed && (_jsxs("div", { className: cardStyles.taskCancellationReason, children: [_jsx("strong", { children: "Cancellation Reason:" }), " ", renderHighlighted(task.canceledReason, searchQuery)] })), showLatestActivity && (latestActivityText || commentCount > 0) && !isReadOnly && !compressed && (_jsxs("div", { className: `${cardStyles.taskLatestComment} ${tintActivityBackground && latestActivityActor?.color ? cardStyles.taskLatestCommentTinted : ''}`, "data-task-activity-summary": "true", style: latestActivityActor?.color
376
+ ? { '--task-activity-accent': latestActivityActor.color }
377
+ : undefined, children: [_jsxs("div", { className: cardStyles.taskLatestCommentHeader, children: [_jsxs("div", { className: cardStyles.taskLatestActivityHeading, children: [_jsx("strong", { children: latestActivityText ? 'Latest Activity:' : 'Activity:' }), latestActivityText && latestActivityActor ? (_jsx("span", { className: cardStyles.taskLatestActivityActor, title: latestActivityActor.label, children: latestActivityActor.label })) : null] }), commentCount > 0 && (_jsxs("span", { className: `${styles.metaBadge} ${cardStyles.taskCommentCount}`, title: `${commentCount} ${commentCount === 1 ? 'comment' : 'comments'}`, "aria-label": `${commentCount} ${commentCount === 1 ? 'comment' : 'comments'}`, children: [_jsx(MessageSquare, { size: 12, "aria-hidden": "true" }), _jsx("span", { children: commentCount })] }))] }), latestActivityText && (_jsx("div", { className: cardStyles.taskLatestCommentText, title: latestActivityText, children: renderHighlighted(latestActivityText, searchQuery) }))] })), !isReadOnly && visibleTaxonomies.length > 0 && !compressed && (_jsx("div", { className: `${cardStyles.taskSpecialists} ${cardStyles.taxonomiesList}`, children: visibleTaxonomies.map(tax => {
323
378
  const val = task.taxonomies?.[tax.id];
324
379
  if (!val)
325
380
  return null;
@@ -364,7 +419,7 @@ const TaskCardInner = ({ task, searchQuery = '', copiedId = null, taxonomies = [
364
419
  const iconName = priorityConfig.icon || 'AlertCircle';
365
420
  const IconComp = Icons[iconName] || Icons.AlertCircle;
366
421
  return _jsx(IconComp, { size: 14 });
367
- })() })), checklistTotal > 0 && (_jsxs("span", { className: styles.metaBadge, title: `${checklistCompleted}/${checklistTotal} checklist items complete`, style: {
422
+ })() })), showChecklistProgress && checklistTotal > 0 && (_jsxs("span", { className: styles.metaBadge, title: `${checklistCompleted}/${checklistTotal} checklist items complete`, style: {
368
423
  color: 'var(--text-muted)',
369
424
  backgroundColor: 'var(--bg-tertiary)',
370
425
  borderColor: 'var(--border-primary)',