@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
@@ -47,11 +47,15 @@ function mapAssetRow(row) {
47
47
  };
48
48
  }
49
49
  function mapLinkRow(row) {
50
+ const targetType = String(row.target_type || 'task').trim();
51
+ const targetId = String(row.task_id || '').trim();
50
52
  return {
51
53
  tenantId: String(row.tenant_id || 'default'),
52
54
  workspaceId: String(row.workspace_id || 'default'),
53
55
  assetId: String(row.asset_id || ''),
54
- taskId: String(row.task_id || ''),
56
+ targetType,
57
+ targetId,
58
+ taskId: targetType === 'task' ? targetId : null,
55
59
  role: String(row.role || 'attachment'),
56
60
  displayName: row.display_name == null ? null : String(row.display_name),
57
61
  sortOrder: row.sort_order == null ? null : Number(row.sort_order),
@@ -73,10 +77,36 @@ function usesReadableAssetReference(kind) {
73
77
  export class WorkspaceAssetStore {
74
78
  db;
75
79
  tenantId;
80
+ supportsTargetTypeCache = null;
76
81
  constructor(db, tenantId) {
77
82
  this.db = db;
78
83
  this.tenantId = tenantId;
79
84
  }
85
+ supportsTargetType() {
86
+ if (this.supportsTargetTypeCache !== null)
87
+ return this.supportsTargetTypeCache;
88
+ try {
89
+ if (this.db.provider === 'postgres') {
90
+ const row = this.db.prepare(`
91
+ SELECT 1
92
+ FROM information_schema.columns
93
+ WHERE table_schema = current_schema()
94
+ AND table_name = 'workspace_asset_links'
95
+ AND column_name = 'target_type'
96
+ LIMIT 1
97
+ `).get();
98
+ this.supportsTargetTypeCache = Boolean(row);
99
+ return this.supportsTargetTypeCache;
100
+ }
101
+ const columns = this.db.prepare(`PRAGMA table_info(workspace_asset_links)`).all();
102
+ this.supportsTargetTypeCache = columns.some((column) => String(column.name || '').trim() === 'target_type');
103
+ return this.supportsTargetTypeCache;
104
+ }
105
+ catch {
106
+ this.supportsTargetTypeCache = false;
107
+ return false;
108
+ }
109
+ }
80
110
  normalizePersistedAsset(entry) {
81
111
  const normalizedKind = normalizeCanonicalAssetKind({
82
112
  kind: entry.kind,
@@ -411,47 +441,93 @@ export class WorkspaceAssetStore {
411
441
  upsertLink(input) {
412
442
  const workspaceId = normalizeWorkspaceId(input.workspaceId);
413
443
  const assetId = normalizeId(input.assetId);
414
- const taskId = normalizeId(input.taskId);
444
+ const targetType = normalizeId(input.targetType, input.taskId ? 'task' : 'task');
445
+ const targetId = normalizeId(input.targetId, input.taskId || '');
415
446
  const role = normalizeId(input.role, 'attachment');
416
447
  const createdAt = normalizeId(input.createdAt, new Date().toISOString());
417
448
  const updatedAt = normalizeId(input.updatedAt, createdAt);
418
- this.db.prepare(`
419
- INSERT INTO workspace_asset_links (
420
- tenant_id,
421
- workspace_id,
422
- asset_id,
423
- task_id,
424
- role,
425
- display_name,
426
- sort_order,
427
- created_at,
428
- updated_at,
429
- deleted_at
430
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
431
- ON CONFLICT(tenant_id, workspace_id, asset_id, task_id, role) DO UPDATE SET
432
- display_name = excluded.display_name,
433
- sort_order = excluded.sort_order,
434
- updated_at = excluded.updated_at,
435
- deleted_at = excluded.deleted_at
436
- `).run(this.tenantId, workspaceId, assetId, taskId, role, normalizeNullable(input.displayName), input.sortOrder == null ? null : Math.floor(Number(input.sortOrder)), createdAt, updatedAt, normalizeNullable(input.deletedAt));
449
+ if (!targetId) {
450
+ throw new Error('Workspace asset links require a targetId.');
451
+ }
452
+ if (this.supportsTargetType()) {
453
+ this.db.prepare(`
454
+ INSERT INTO workspace_asset_links (
455
+ tenant_id,
456
+ workspace_id,
457
+ asset_id,
458
+ target_type,
459
+ task_id,
460
+ role,
461
+ display_name,
462
+ sort_order,
463
+ created_at,
464
+ updated_at,
465
+ deleted_at
466
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
467
+ ON CONFLICT(tenant_id, workspace_id, asset_id, task_id, role) DO UPDATE SET
468
+ target_type = excluded.target_type,
469
+ display_name = excluded.display_name,
470
+ sort_order = excluded.sort_order,
471
+ updated_at = excluded.updated_at,
472
+ deleted_at = excluded.deleted_at
473
+ `).run(this.tenantId, workspaceId, assetId, targetType, targetId, role, normalizeNullable(input.displayName), input.sortOrder == null ? null : Math.floor(Number(input.sortOrder)), createdAt, updatedAt, normalizeNullable(input.deletedAt));
474
+ }
475
+ else {
476
+ this.db.prepare(`
477
+ INSERT INTO workspace_asset_links (
478
+ tenant_id,
479
+ workspace_id,
480
+ asset_id,
481
+ task_id,
482
+ role,
483
+ display_name,
484
+ sort_order,
485
+ created_at,
486
+ updated_at,
487
+ deleted_at
488
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
489
+ ON CONFLICT(tenant_id, workspace_id, asset_id, task_id, role) DO UPDATE SET
490
+ display_name = excluded.display_name,
491
+ sort_order = excluded.sort_order,
492
+ updated_at = excluded.updated_at,
493
+ deleted_at = excluded.deleted_at
494
+ `).run(this.tenantId, workspaceId, assetId, targetId, role, normalizeNullable(input.displayName), input.sortOrder == null ? null : Math.floor(Number(input.sortOrder)), createdAt, updatedAt, normalizeNullable(input.deletedAt));
495
+ }
437
496
  return this.listLinksForAsset(assetId, workspaceId, { includeDeleted: true })
438
- .find((entry) => entry.taskId === taskId && entry.role === role);
497
+ .find((entry) => entry.targetType === targetType && entry.targetId === targetId && entry.role === role);
439
498
  }
440
499
  listLinksForTask(taskIdRaw, workspaceIdRaw, options) {
500
+ return this.listLinksForTarget('task', taskIdRaw, workspaceIdRaw, options);
501
+ }
502
+ listLinksForTarget(targetTypeRaw, targetIdRaw, workspaceIdRaw, options) {
441
503
  const workspaceId = normalizeWorkspaceId(workspaceIdRaw);
442
- const taskId = normalizeId(taskIdRaw);
443
- if (!taskId)
504
+ const targetType = normalizeId(targetTypeRaw, 'task');
505
+ const targetId = normalizeId(targetIdRaw);
506
+ if (!targetId)
444
507
  return [];
445
508
  const includeDeleted = options?.includeDeleted === true;
446
- const rows = this.db.prepare(`
447
- SELECT *
448
- FROM workspace_asset_links
449
- WHERE tenant_id = ?
450
- AND workspace_id = ?
451
- AND task_id = ?
452
- ${includeDeleted ? '' : 'AND deleted_at IS NULL'}
453
- ORDER BY COALESCE(sort_order, 2147483647) ASC, created_at ASC, asset_id ASC
454
- `).all(this.tenantId, workspaceId, taskId);
509
+ const rows = this.supportsTargetType()
510
+ ? this.db.prepare(`
511
+ SELECT *
512
+ FROM workspace_asset_links
513
+ WHERE tenant_id = ?
514
+ AND workspace_id = ?
515
+ AND target_type = ?
516
+ AND task_id = ?
517
+ ${includeDeleted ? '' : 'AND deleted_at IS NULL'}
518
+ ORDER BY COALESCE(sort_order, 2147483647) ASC, created_at ASC, asset_id ASC
519
+ `).all(this.tenantId, workspaceId, targetType, targetId)
520
+ : (targetType === 'task'
521
+ ? this.db.prepare(`
522
+ SELECT *
523
+ FROM workspace_asset_links
524
+ WHERE tenant_id = ?
525
+ AND workspace_id = ?
526
+ AND task_id = ?
527
+ ${includeDeleted ? '' : 'AND deleted_at IS NULL'}
528
+ ORDER BY COALESCE(sort_order, 2147483647) ASC, created_at ASC, asset_id ASC
529
+ `).all(this.tenantId, workspaceId, targetId)
530
+ : []);
455
531
  return rows.map(mapLinkRow);
456
532
  }
457
533
  listLinksForAsset(assetIdRaw, workspaceIdRaw, options) {
@@ -474,23 +550,35 @@ export class WorkspaceAssetStore {
474
550
  deleteLink(input) {
475
551
  const workspaceId = normalizeWorkspaceId(input.workspaceId);
476
552
  const assetId = normalizeId(input.assetId);
477
- const taskId = normalizeId(input.taskId);
553
+ const targetType = normalizeId(input.targetType, input.taskId ? 'task' : 'task');
554
+ const targetId = normalizeId(input.targetId, input.taskId || '');
478
555
  const role = normalizeId(input.role);
479
- if (!assetId || !taskId || !role)
556
+ if (!assetId || !targetId || !role)
480
557
  return false;
481
558
  if (input.hardDelete) {
482
- const result = this.db.prepare(`
483
- DELETE FROM workspace_asset_links
484
- WHERE tenant_id = ? AND workspace_id = ? AND asset_id = ? AND task_id = ? AND role = ?
485
- `).run(this.tenantId, workspaceId, assetId, taskId, role);
559
+ const result = this.supportsTargetType()
560
+ ? this.db.prepare(`
561
+ DELETE FROM workspace_asset_links
562
+ WHERE tenant_id = ? AND workspace_id = ? AND asset_id = ? AND target_type = ? AND task_id = ? AND role = ?
563
+ `).run(this.tenantId, workspaceId, assetId, targetType, targetId, role)
564
+ : this.db.prepare(`
565
+ DELETE FROM workspace_asset_links
566
+ WHERE tenant_id = ? AND workspace_id = ? AND asset_id = ? AND task_id = ? AND role = ?
567
+ `).run(this.tenantId, workspaceId, assetId, targetId, role);
486
568
  return Number(result?.changes || 0) > 0;
487
569
  }
488
570
  const nowIso = new Date().toISOString();
489
- const result = this.db.prepare(`
490
- UPDATE workspace_asset_links
491
- SET deleted_at = ?, updated_at = ?
492
- WHERE tenant_id = ? AND workspace_id = ? AND asset_id = ? AND task_id = ? AND role = ?
493
- `).run(nowIso, nowIso, this.tenantId, workspaceId, assetId, taskId, role);
571
+ const result = this.supportsTargetType()
572
+ ? this.db.prepare(`
573
+ UPDATE workspace_asset_links
574
+ SET deleted_at = ?, updated_at = ?
575
+ WHERE tenant_id = ? AND workspace_id = ? AND asset_id = ? AND target_type = ? AND task_id = ? AND role = ?
576
+ `).run(nowIso, nowIso, this.tenantId, workspaceId, assetId, targetType, targetId, role)
577
+ : this.db.prepare(`
578
+ UPDATE workspace_asset_links
579
+ SET deleted_at = ?, updated_at = ?
580
+ WHERE tenant_id = ? AND workspace_id = ? AND asset_id = ? AND task_id = ? AND role = ?
581
+ `).run(nowIso, nowIso, this.tenantId, workspaceId, assetId, targetId, role);
494
582
  return Number(result?.changes || 0) > 0;
495
583
  }
496
584
  }
@@ -23,6 +23,40 @@ function makeStore() {
23
23
  }
24
24
  };
25
25
  }
26
+ function makeLegacyLinkStore() {
27
+ const root = fs.mkdtempSync(path.join(os.tmpdir(), 'taskforce-workspace-assets-legacy-'));
28
+ const dbPath = path.join(root, 'taskforce.db');
29
+ const db = createDatabaseAdapter({ sqliteDbPath: dbPath });
30
+ ensureTaskAssetsSchema(db);
31
+ ensureWorkspaceAssetsSchema(db);
32
+ ensureDocumentReferenceSchema(db);
33
+ db.exec(`DROP TABLE IF EXISTS workspace_asset_links`);
34
+ db.exec(`
35
+ CREATE TABLE IF NOT EXISTS workspace_asset_links (
36
+ tenant_id TEXT NOT NULL DEFAULT 'default',
37
+ workspace_id TEXT NOT NULL,
38
+ asset_id TEXT NOT NULL,
39
+ task_id TEXT NOT NULL,
40
+ role TEXT NOT NULL,
41
+ display_name TEXT,
42
+ sort_order INTEGER,
43
+ created_at TEXT NOT NULL,
44
+ updated_at TEXT NOT NULL,
45
+ deleted_at TEXT,
46
+ PRIMARY KEY (tenant_id, workspace_id, asset_id, task_id, role)
47
+ );
48
+ `);
49
+ const store = new WorkspaceAssetStore(db, 'default');
50
+ return {
51
+ root,
52
+ db,
53
+ store,
54
+ cleanup() {
55
+ db.close();
56
+ fs.rmSync(root, { recursive: true, force: true });
57
+ }
58
+ };
59
+ }
26
60
  describe('WorkspaceAssetStore', () => {
27
61
  const cleanups = [];
28
62
  afterEach(() => {
@@ -64,6 +98,50 @@ describe('WorkspaceAssetStore', () => {
64
98
  referenceNumber: 1
65
99
  });
66
100
  });
101
+ it('supports legacy workspace asset links without target_type', () => {
102
+ const ctx = makeLegacyLinkStore();
103
+ cleanups.push(() => ctx.cleanup());
104
+ const now = new Date().toISOString();
105
+ ctx.store.upsertAsset({
106
+ assetId: 'asset-legacy-1',
107
+ workspaceId: 'workspace-1',
108
+ kind: 'file',
109
+ originalFilename: 'legacy.pdf',
110
+ mimeType: 'application/pdf',
111
+ storageProvider: 'local',
112
+ storageKey: 'workspaces/workspace-1/assets/files/asset-legacy-1-legacy.pdf',
113
+ contentSha256: 'sha-legacy',
114
+ sizeBytes: 42,
115
+ createdAt: now,
116
+ updatedAt: now
117
+ });
118
+ const created = ctx.store.upsertLink({
119
+ workspaceId: 'workspace-1',
120
+ assetId: 'asset-legacy-1',
121
+ taskId: 'task-1',
122
+ role: 'attachment',
123
+ displayName: 'Legacy attachment',
124
+ createdAt: now,
125
+ updatedAt: now
126
+ });
127
+ expect(created.targetType).toBe('task');
128
+ expect(created.targetId).toBe('task-1');
129
+ expect(ctx.store.listLinksForTask('task-1', 'workspace-1')).toEqual([
130
+ expect.objectContaining({
131
+ assetId: 'asset-legacy-1',
132
+ targetType: 'task',
133
+ targetId: 'task-1',
134
+ role: 'attachment'
135
+ })
136
+ ]);
137
+ expect(ctx.store.deleteLink({
138
+ workspaceId: 'workspace-1',
139
+ assetId: 'asset-legacy-1',
140
+ taskId: 'task-1',
141
+ role: 'attachment'
142
+ })).toBe(true);
143
+ expect(ctx.store.listLinksForTask('task-1', 'workspace-1')).toEqual([]);
144
+ });
67
145
  it('assigns sequential document reference numbers per workspace', () => {
68
146
  const ctx = makeStore();
69
147
  cleanups.push(() => ctx.cleanup());
@@ -382,7 +460,7 @@ describe('WorkspaceAssetStore', () => {
382
460
  const all = ctx.store.listByWorkspace('workspace-1', { includeDeleted: true });
383
461
  expect(all.map((entry) => entry.assetId).sort()).toEqual(['asset-a', 'asset-b']);
384
462
  });
385
- it('creates, lists, and soft-deletes task links separately from asset identity', () => {
463
+ it('creates, lists, and soft-deletes generic target links while preserving task compatibility helpers', () => {
386
464
  const ctx = makeStore();
387
465
  cleanups.push(() => ctx.cleanup());
388
466
  ctx.store.upsertAsset({
@@ -399,27 +477,36 @@ describe('WorkspaceAssetStore', () => {
399
477
  ctx.store.upsertLink({
400
478
  workspaceId: 'workspace-1',
401
479
  assetId: 'asset-link-1',
402
- taskId: 'task-1',
480
+ targetType: 'task',
481
+ targetId: 'task-1',
403
482
  role: 'attachment',
404
483
  sortOrder: 2
405
484
  });
406
485
  ctx.store.upsertLink({
407
486
  workspaceId: 'workspace-1',
408
487
  assetId: 'asset-link-1',
409
- taskId: 'task-2',
488
+ targetType: 'initiative',
489
+ targetId: 'initiative-2',
410
490
  role: 'reference',
411
491
  sortOrder: 1
412
492
  });
413
493
  const taskLinks = ctx.store.listLinksForTask('task-1', 'workspace-1');
414
494
  expect(taskLinks).toHaveLength(1);
415
- expect(taskLinks[0]).toMatchObject({ assetId: 'asset-link-1', role: 'attachment' });
495
+ expect(taskLinks[0]).toMatchObject({ assetId: 'asset-link-1', role: 'attachment', targetType: 'task', targetId: 'task-1', taskId: 'task-1' });
496
+ const initiativeLinks = ctx.store.listLinksForTarget('initiative', 'initiative-2', 'workspace-1');
497
+ expect(initiativeLinks).toHaveLength(1);
498
+ expect(initiativeLinks[0]).toMatchObject({ assetId: 'asset-link-1', role: 'reference', targetType: 'initiative', targetId: 'initiative-2', taskId: null });
416
499
  const assetLinks = ctx.store.listLinksForAsset('asset-link-1', 'workspace-1');
417
500
  expect(assetLinks).toHaveLength(2);
418
- expect(assetLinks.map((entry) => entry.taskId)).toEqual(['task-2', 'task-1']);
501
+ expect(assetLinks.map((entry) => [entry.targetType, entry.targetId])).toEqual([
502
+ ['initiative', 'initiative-2'],
503
+ ['task', 'task-1'],
504
+ ]);
419
505
  expect(ctx.store.deleteLink({
420
506
  workspaceId: 'workspace-1',
421
507
  assetId: 'asset-link-1',
422
- taskId: 'task-1',
508
+ targetType: 'task',
509
+ targetId: 'task-1',
423
510
  role: 'attachment'
424
511
  })).toBe(true);
425
512
  expect(ctx.store.listLinksForTask('task-1', 'workspace-1')).toHaveLength(0);
@@ -0,0 +1,70 @@
1
+ @font-face {
2
+ font-family: "Russo One";
3
+ src: url("../assets/fonts/RussoOne-Regular.woff2") format("woff2");
4
+ font-weight: 400;
5
+ font-style: normal;
6
+ font-display: swap;
7
+ }
8
+
9
+ @font-face {
10
+ font-family: "Courier Prime";
11
+ src: url("../assets/fonts/CourierPrime-Regular.woff2") format("woff2");
12
+ font-weight: 400;
13
+ font-style: normal;
14
+ font-display: swap;
15
+ }
16
+
17
+ @font-face {
18
+ font-family: "Courier Prime";
19
+ src: url("../assets/fonts/CourierPrime-Italic.woff2") format("woff2");
20
+ font-weight: 400;
21
+ font-style: italic;
22
+ font-display: swap;
23
+ }
24
+
25
+ @font-face {
26
+ font-family: "Courier Prime";
27
+ src: url("../assets/fonts/CourierPrime-Bold.woff2") format("woff2");
28
+ font-weight: 700;
29
+ font-style: normal;
30
+ font-display: swap;
31
+ }
32
+
33
+ @font-face {
34
+ font-family: "Courier Prime";
35
+ src: url("../assets/fonts/CourierPrime-BoldItalic.woff2") format("woff2");
36
+ font-weight: 700;
37
+ font-style: italic;
38
+ font-display: swap;
39
+ }
40
+
41
+ @font-face {
42
+ font-family: "Special Elite";
43
+ src: url("../assets/fonts/SpecialElite-Regular.woff2") format("woff2");
44
+ font-weight: 400;
45
+ font-style: normal;
46
+ font-display: swap;
47
+ }
48
+
49
+ @font-face {
50
+ font-family: "Noir";
51
+ src: url("../assets/fonts/Noir_regular.woff2") format("woff2");
52
+ font-weight: 400;
53
+ font-style: normal;
54
+ font-display: swap;
55
+ }
56
+
57
+ @font-face {
58
+ font-family: "Noir";
59
+ src: url("../assets/fonts/Noir_medium.woff2") format("woff2");
60
+ font-weight: 500;
61
+ font-style: normal;
62
+ font-display: swap;
63
+ }
64
+
65
+ :root {
66
+ --font-brand: "Russo One", sans-serif;
67
+ --font-typewriter: "Courier Prime", "Courier New", Courier, monospace;
68
+ --font-stamped: "Special Elite", "Courier Prime", "Courier New", Courier, monospace;
69
+ --font-noir: "Noir", var(--font-sans, ui-sans-serif, system-ui, sans-serif);
70
+ }
@@ -1,10 +1,15 @@
1
1
  import type { WorkspaceSyncAiProfileSnapshot, WorkspaceSyncAnnotatedAttachmentSessionSnapshot, WorkspaceSyncDocumentReviewCommentSnapshot, WorkspaceSyncDocumentReviewSessionSnapshot } from './workspaceSyncModel.js';
2
2
  import type { AiProfileSurfaceType } from '../shared/aiProfileSurfaceType.js';
3
+ import type { AiProfileSeatScope } from '../shared/aiProfileSeatScope.js';
3
4
  export declare function normalizeAiProfileSyncPayload(raw: unknown, workspaceId: string, normalizeSurfaceType: (value: unknown, context: {
4
5
  source: string;
5
6
  profileId?: string;
6
7
  workspaceId?: string;
7
- }) => AiProfileSurfaceType | null, source: string): WorkspaceSyncAiProfileSnapshot | null;
8
+ }) => AiProfileSurfaceType | null, normalizeSeatScope: (value: unknown, context: {
9
+ source: string;
10
+ profileId?: string;
11
+ workspaceId?: string;
12
+ }) => AiProfileSeatScope | null, source: string): WorkspaceSyncAiProfileSnapshot | null;
8
13
  export declare function normalizeDocumentReviewSessionSyncPayload(raw: unknown, sourceWatermark?: string): WorkspaceSyncDocumentReviewSessionSnapshot | null;
9
14
  export declare function normalizeDocumentReviewCommentSyncPayload(raw: unknown, options?: {
10
15
  sessionId?: string;
@@ -1,11 +1,9 @@
1
+ import { hasOwnSyncField, normalizeSyncNullableString, normalizeSyncOptionalString, readSyncNullableIdField, readSyncNullableIsoStringField, readSyncNullableStringField, readSyncSameOriginAssetUrlField, } from './syncFieldSemantics.js';
1
2
  function toOptionalTrimmedString(value) {
2
- if (typeof value !== 'string')
3
- return undefined;
4
- const normalized = value.trim();
5
- return normalized.length > 0 ? normalized : undefined;
3
+ return normalizeSyncOptionalString(value);
6
4
  }
7
5
  function toNullableTrimmedString(value) {
8
- return toOptionalTrimmedString(value) ?? null;
6
+ return normalizeSyncNullableString(value);
9
7
  }
10
8
  function toOptionalPositiveInteger(value) {
11
9
  if (value === undefined || value === null || value === '')
@@ -23,7 +21,7 @@ function toOptionalNonNegativeInteger(value) {
23
21
  return 0;
24
22
  return Math.max(0, Math.floor(normalized));
25
23
  }
26
- export function normalizeAiProfileSyncPayload(raw, workspaceId, normalizeSurfaceType, source) {
24
+ export function normalizeAiProfileSyncPayload(raw, workspaceId, normalizeSurfaceType, normalizeSeatScope, source) {
27
25
  if (!raw || typeof raw !== 'object' || Array.isArray(raw))
28
26
  return null;
29
27
  const profile = raw;
@@ -39,17 +37,27 @@ export function normalizeAiProfileSyncPayload(raw, workspaceId, normalizeSurface
39
37
  username: String(profile.username || '').trim(),
40
38
  icon: String(profile.icon || 'Bot').trim() || 'Bot',
41
39
  color: String(profile.color || '#8b5cf6').trim() || '#8b5cf6',
42
- description: toNullableTrimmedString(profile.description),
43
- role: toNullableTrimmedString(profile.role),
44
- provider: toNullableTrimmedString(profile.provider),
45
- model: toNullableTrimmedString(profile.model),
40
+ ...(hasOwnSyncField(profile, 'avatarUrl') ? { avatarUrl: readSyncSameOriginAssetUrlField(profile, 'avatarUrl') ?? null } : {}),
41
+ ...(hasOwnSyncField(profile, 'avatarSourceUrl') ? { avatarSourceUrl: readSyncSameOriginAssetUrlField(profile, 'avatarSourceUrl') ?? null } : {}),
42
+ ...(hasOwnSyncField(profile, 'avatarRevision') ? { avatarRevision: toOptionalNonNegativeInteger(profile.avatarRevision) } : {}),
43
+ avatarUpdatedAt: readSyncNullableIsoStringField(profile, 'avatarUpdatedAt') ?? null,
44
+ description: readSyncNullableStringField(profile, 'description') ?? null,
45
+ role: readSyncNullableStringField(profile, 'role') ?? null,
46
+ provider: readSyncNullableStringField(profile, 'provider') ?? null,
47
+ model: readSyncNullableStringField(profile, 'model') ?? null,
46
48
  surfaceType: normalizeSurfaceType(profile.surfaceType, { source, profileId, workspaceId: profileWorkspaceId }),
49
+ seatScope: normalizeSeatScope(profile.seatScope, { source, profileId, workspaceId: profileWorkspaceId }),
47
50
  providerMetadata: profile.providerMetadata && typeof profile.providerMetadata === 'object' && !Array.isArray(profile.providerMetadata)
48
51
  ? profile.providerMetadata
49
52
  : null,
53
+ archivedAt: readSyncNullableIsoStringField(profile, 'archivedAt') ?? null,
54
+ archivedBy: readSyncNullableIdField(profile, 'archivedBy') ?? null,
55
+ archivedReason: readSyncNullableStringField(profile, 'archivedReason') ?? null,
56
+ mergedIntoProfileId: readSyncNullableIdField(profile, 'mergedIntoProfileId') ?? null,
57
+ rosterStateUpdatedAt: readSyncNullableIsoStringField(profile, 'rosterStateUpdatedAt') ?? null,
50
58
  createdAt: String(profile.createdAt || '').trim(),
51
59
  updatedAt: String(profile.updatedAt || profile.createdAt || '').trim(),
52
- lastActiveAt: toNullableTrimmedString(profile.lastActiveAt),
60
+ lastActiveAt: readSyncNullableIsoStringField(profile, 'lastActiveAt') ?? toNullableTrimmedString(profile.lastActiveAt),
53
61
  };
54
62
  }
55
63
  export function normalizeDocumentReviewSessionSyncPayload(raw, sourceWatermark) {
@@ -6,6 +6,11 @@ describe('collaborationSyncPayload', () => {
6
6
  return null;
7
7
  return String(value).trim();
8
8
  };
9
+ const normalizeSeatScope = (value) => {
10
+ if (value === undefined || value === null || value === '')
11
+ return null;
12
+ return String(value).trim();
13
+ };
9
14
  it('normalizes ai profile sync payloads with workspace and surface type', () => {
10
15
  const profile = normalizeAiProfileSyncPayload({
11
16
  id: 'profile-1',
@@ -20,11 +25,12 @@ describe('collaborationSyncPayload', () => {
20
25
  provider: ' OpenAI ',
21
26
  model: ' gpt-5.4 ',
22
27
  surfaceType: 'agent',
28
+ seatScope: 'cloud_metered',
23
29
  providerMetadata: { foo: 'bar' },
24
30
  createdAt: '2026-04-10T10:00:00.000Z',
25
31
  updatedAt: '2026-04-10T11:00:00.000Z',
26
32
  lastActiveAt: '2026-04-10T12:00:00.000Z',
27
- }, 'workspace-a', normalizeSurfaceType, 'test.ai');
33
+ }, 'workspace-a', normalizeSurfaceType, normalizeSeatScope, 'test.ai');
28
34
  expect(profile).toEqual({
29
35
  id: 'profile-1',
30
36
  workspaceId: 'workspace-a',
@@ -33,12 +39,19 @@ describe('collaborationSyncPayload', () => {
33
39
  username: 'agent',
34
40
  icon: 'Bot',
35
41
  color: '#111111',
42
+ avatarUpdatedAt: null,
36
43
  description: 'Product coding agent',
37
44
  role: 'Implementer',
38
45
  provider: 'OpenAI',
39
46
  model: 'gpt-5.4',
40
47
  surfaceType: 'agent',
48
+ seatScope: 'cloud_metered',
41
49
  providerMetadata: { foo: 'bar' },
50
+ archivedAt: null,
51
+ archivedBy: null,
52
+ archivedReason: null,
53
+ mergedIntoProfileId: null,
54
+ rosterStateUpdatedAt: null,
42
55
  createdAt: '2026-04-10T10:00:00.000Z',
43
56
  updatedAt: '2026-04-10T11:00:00.000Z',
44
57
  lastActiveAt: '2026-04-10T12:00:00.000Z',
@@ -1,5 +1,5 @@
1
1
  import type { TaskforceCore, TaskforceSyncCapable } from '../core/Taskforce.js';
2
- import type { WorkspaceSyncAnnotatedAttachmentSessionSnapshot, WorkspaceSyncDocumentReviewCommentSnapshot, WorkspaceSyncDocumentReviewSessionSnapshot, WorkspaceSyncTaskEventSnapshot } from './workspaceSyncModel.js';
2
+ import type { WorkspaceSyncAnnotatedAttachmentSessionSnapshot, WorkspaceSyncDocumentReviewCommentSnapshot, WorkspaceSyncDocumentReviewSessionSnapshot, WorkspaceSyncEntityEventSnapshot } from './workspaceSyncModel.js';
3
3
  type SyncCore = TaskforceCore & TaskforceSyncCapable;
4
4
  interface CollaborationSyncStateDeps {
5
5
  core: SyncCore;
@@ -7,11 +7,11 @@ interface CollaborationSyncStateDeps {
7
7
  export declare function listWorkspaceSyncDocumentReviewSessionsSnapshot(deps: CollaborationSyncStateDeps, workspaceId?: string): WorkspaceSyncDocumentReviewSessionSnapshot[];
8
8
  export declare function listWorkspaceSyncDocumentReviewCommentsSnapshot(deps: CollaborationSyncStateDeps, workspaceId?: string): WorkspaceSyncDocumentReviewCommentSnapshot[];
9
9
  export declare function listWorkspaceSyncAnnotatedAttachmentSessionsSnapshot(deps: CollaborationSyncStateDeps, workspaceId?: string): WorkspaceSyncAnnotatedAttachmentSessionSnapshot[];
10
- export declare function listWorkspaceSyncTaskEventsSnapshot(deps: CollaborationSyncStateDeps, workspaceId?: string): WorkspaceSyncTaskEventSnapshot[];
10
+ export declare function listWorkspaceSyncTaskEventsSnapshot(deps: CollaborationSyncStateDeps, workspaceId?: string): WorkspaceSyncEntityEventSnapshot[];
11
11
  export declare function createCollaborationSyncState(deps: CollaborationSyncStateDeps): {
12
12
  listWorkspaceSyncDocumentReviewSessionsSnapshot: (workspaceId?: string) => WorkspaceSyncDocumentReviewSessionSnapshot[];
13
13
  listWorkspaceSyncDocumentReviewCommentsSnapshot: (workspaceId?: string) => WorkspaceSyncDocumentReviewCommentSnapshot[];
14
14
  listWorkspaceSyncAnnotatedAttachmentSessionsSnapshot: (workspaceId?: string) => WorkspaceSyncAnnotatedAttachmentSessionSnapshot[];
15
- listWorkspaceSyncTaskEventsSnapshot: (workspaceId?: string) => WorkspaceSyncTaskEventSnapshot[];
15
+ listWorkspaceSyncTaskEventsSnapshot: (workspaceId?: string) => WorkspaceSyncEntityEventSnapshot[];
16
16
  };
17
17
  export {};
@@ -52,19 +52,26 @@ export function listWorkspaceSyncAnnotatedAttachmentSessionsSnapshot(deps, works
52
52
  && session.baseImageAssetId.length > 0));
53
53
  }
54
54
  export function listWorkspaceSyncTaskEventsSnapshot(deps, workspaceId = 'default') {
55
- return deps.core.listTaskEventsForSync({ workspaceId })
56
- .map((event) => ({
57
- id: event.id,
58
- taskId: event.taskId,
59
- workspaceId: event.workspaceId,
60
- action: event.action,
61
- actor: event.actor,
62
- actorType: event.actorType,
63
- details: event.details,
64
- createdAt: event.createdAt,
65
- }))
55
+ return deps.core.listEntityEventsForSync({ workspaceId })
56
+ .map((event) => {
57
+ const entityType = event.entityType === 'initiative' || event.entityType === 'workstream'
58
+ ? event.entityType
59
+ : 'task';
60
+ return {
61
+ id: event.id,
62
+ workspaceId: event.workspaceId,
63
+ entityType,
64
+ entityId: String(event.entityId || ('taskId' in event ? event.taskId : '') || '').trim(),
65
+ taskId: entityType === 'task' && 'taskId' in event ? event.taskId : undefined,
66
+ action: event.action,
67
+ actor: event.actor,
68
+ actorType: event.actorType,
69
+ details: event.details,
70
+ createdAt: event.createdAt,
71
+ };
72
+ })
66
73
  .filter((event) => (event.id.length > 0
67
- && event.taskId.length > 0
74
+ && event.entityId.length > 0
68
75
  && event.workspaceId.length > 0
69
76
  && event.action.length > 0
70
77
  && event.createdAt.length > 0));
@@ -1,4 +1,4 @@
1
- import type { WorkspaceAssetLinkRole } from '../storage/workspaceAssetStore.js';
1
+ import type { WorkspaceAssetLinkRole, WorkspaceAssetLinkTargetType } from '../storage/workspaceAssetStore.js';
2
2
  export interface DocumentSyncPayload {
3
3
  path: string;
4
4
  updatedAt: string;
@@ -8,6 +8,8 @@ export interface DocumentSyncPayload {
8
8
  referenceNumber?: number | null;
9
9
  version?: number | null;
10
10
  taskId?: string | null;
11
+ linkTargetType?: WorkspaceAssetLinkTargetType | null;
12
+ linkTargetId?: string | null;
11
13
  logicalName?: string | null;
12
14
  caption?: string | null;
13
15
  originalFilename?: string | null;
@@ -27,6 +29,8 @@ export interface BinaryAssetSyncPayload {
27
29
  mimeType: string;
28
30
  referenceNumber?: number | null;
29
31
  taskId?: string | null;
32
+ linkTargetType?: WorkspaceAssetLinkTargetType | null;
33
+ linkTargetId?: string | null;
30
34
  logicalName?: string | null;
31
35
  caption?: string | null;
32
36
  originalFilename?: string | null;