@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
@@ -1,6 +1,64 @@
1
1
  import * as fs from 'fs';
2
2
  import * as path from 'path';
3
3
  import { createHash, randomUUID } from 'crypto';
4
+ function decodeTaskforceContextPath(value, normalizePath) {
5
+ const normalized = String(value || '').trim();
6
+ if (!normalized.startsWith('/api/taskforce/context/'))
7
+ return null;
8
+ const encoded = normalized.slice('/api/taskforce/context/'.length).split(/[?#]/, 1)[0] || '';
9
+ if (!encoded)
10
+ return null;
11
+ try {
12
+ return normalizePath(decodeURIComponent(encoded));
13
+ }
14
+ catch {
15
+ return null;
16
+ }
17
+ }
18
+ function isAiProfileAvatarAssetPath(value, workspaceId) {
19
+ const normalized = String(value || '').replace(/\\/g, '/');
20
+ return normalized.startsWith(`workspaces/${workspaceId}/assets/images/ai-profiles/`)
21
+ && normalized.includes('/avatar/');
22
+ }
23
+ function inferBinaryAssetMimeType(assetPath) {
24
+ const ext = path.extname(assetPath).toLowerCase();
25
+ if (ext === '.png')
26
+ return 'image/png';
27
+ if (ext === '.jpg' || ext === '.jpeg')
28
+ return 'image/jpeg';
29
+ if (ext === '.webp')
30
+ return 'image/webp';
31
+ if (ext === '.gif')
32
+ return 'image/gif';
33
+ return 'application/octet-stream';
34
+ }
35
+ function inferAssetIdFromPath(assetPath) {
36
+ const match = String(assetPath || '').match(/(^|\/)(asset-[a-f0-9]{32})(?=[^/]*$)/i);
37
+ return match?.[2];
38
+ }
39
+ function listReferencedAiProfileAvatarAssetPaths(deps, workspaceId) {
40
+ const profiles = typeof deps.core.listAiProfiles === 'function'
41
+ ? deps.core.listAiProfiles(workspaceId, { includeArchived: true })
42
+ : [];
43
+ const referenced = new Map();
44
+ for (const profile of Array.isArray(profiles) ? profiles : []) {
45
+ const updatedAt = String(profile?.updatedAt || profile?.createdAt || '').trim();
46
+ for (const url of [profile?.avatarUrl, profile?.avatarSourceUrl]) {
47
+ const assetPath = decodeTaskforceContextPath(url, deps.normalizeTaskDataRelativePath);
48
+ if (!assetPath || !isAiProfileAvatarAssetPath(assetPath, workspaceId))
49
+ continue;
50
+ if (referenced.has(assetPath))
51
+ continue;
52
+ referenced.set(assetPath, {
53
+ updatedAt,
54
+ assetId: inferAssetIdFromPath(assetPath),
55
+ originalFilename: path.basename(assetPath),
56
+ mimeType: inferBinaryAssetMimeType(assetPath)
57
+ });
58
+ }
59
+ }
60
+ return referenced;
61
+ }
4
62
  export function resolveCanonicalAssetSyncLinkState(deps, asset, workspaceId) {
5
63
  if (!deps.workspaceAssetStore) {
6
64
  return {
@@ -19,6 +77,28 @@ export function resolveCanonicalAssetSyncLinkState(deps, asset, workspaceId) {
19
77
  }
20
78
  return { primaryLink, effectiveUpdatedAt };
21
79
  }
80
+ function resolveSyncLinkTarget(primaryLink) {
81
+ if (!primaryLink)
82
+ return null;
83
+ const targetId = String(primaryLink.targetId || primaryLink.taskId || '').trim();
84
+ if (!targetId)
85
+ return null;
86
+ const targetType = primaryLink.targetType === 'initiative' || primaryLink.targetType === 'workstream'
87
+ ? primaryLink.targetType
88
+ : 'task';
89
+ return { targetType, targetId };
90
+ }
91
+ function resolveIncomingSyncLinkTarget(input) {
92
+ const linkTargetType = input.linkTargetType === 'initiative' || input.linkTargetType === 'workstream' || input.linkTargetType === 'task'
93
+ ? input.linkTargetType
94
+ : null;
95
+ const linkTargetId = String(input.linkTargetId || '').trim();
96
+ if (linkTargetType && linkTargetId) {
97
+ return { targetType: linkTargetType, targetId: linkTargetId };
98
+ }
99
+ const taskId = String(input.taskId || '').trim();
100
+ return taskId ? { targetType: 'task', targetId: taskId } : null;
101
+ }
22
102
  export function getCanonicalSyncDocumentMetadata(deps, relativePath, workspaceId) {
23
103
  if (!deps.workspaceAssetStore)
24
104
  return {};
@@ -26,19 +106,22 @@ export function getCanonicalSyncDocumentMetadata(deps, relativePath, workspaceId
26
106
  if (!asset || asset.kind !== 'document')
27
107
  return {};
28
108
  const { primaryLink } = resolveCanonicalAssetSyncLinkState(deps, asset, workspaceId);
109
+ const linkTarget = resolveSyncLinkTarget(primaryLink);
29
110
  return {
30
111
  assetId: asset.assetId,
31
112
  documentId: asset.documentId,
32
113
  referenceNumber: asset.referenceNumber,
33
114
  version: asset.version,
34
- taskId: primaryLink?.taskId || null,
115
+ taskId: linkTarget?.targetType === 'task' ? linkTarget.targetId : null,
116
+ linkTargetType: linkTarget?.targetType || null,
117
+ linkTargetId: linkTarget?.targetId || null,
35
118
  logicalName: asset.logicalName || null,
36
119
  caption: primaryLink?.displayName || null,
37
120
  originalFilename: asset.originalFilename || path.basename(relativePath),
38
121
  linkRole: primaryLink?.role === 'reference' ? 'reference' : 'attachment'
39
122
  };
40
123
  }
41
- export function hasDocumentSyncMetadataDrift(deps, workspaceId, doc, options) {
124
+ export function hasDocumentSyncMetadataDrift(deps, workspaceId, doc) {
42
125
  if (!deps.workspaceAssetStore)
43
126
  return false;
44
127
  const existingAsset = deps.workspaceAssetStore.getByStorageKey(doc.path, workspaceId);
@@ -63,33 +146,23 @@ export function hasDocumentSyncMetadataDrift(deps, workspaceId, doc, options) {
63
146
  const normalizedIncomingFilename = typeof doc.originalFilename === 'string' && doc.originalFilename.trim().length > 0
64
147
  ? doc.originalFilename.trim()
65
148
  : null;
66
- const normalizedIncomingTaskId = typeof doc.taskId === 'string' && doc.taskId.trim().length > 0
67
- ? doc.taskId.trim()
68
- : null;
149
+ const incomingLinkTarget = resolveIncomingSyncLinkTarget(doc);
150
+ const primaryLinkTarget = resolveSyncLinkTarget(primaryLink);
69
151
  const normalizedIncomingLinkRole = doc.linkRole === 'reference' ? 'reference' : 'attachment';
70
- const allowReferenceNumberReassignment = options?.allowReferenceNumberReassignment === true;
71
152
  const referenceNumberMismatch = Boolean(existingAsset.referenceNumber
72
153
  && normalizedIncomingReference
73
154
  && existingAsset.referenceNumber !== normalizedIncomingReference);
74
- if (referenceNumberMismatch) {
75
- deps.recordSyncDiagnostic(workspaceId, 'apply', 'Detected document reference number mismatch during normal sync.', {
76
- source: 'documents.referenceNumber.mismatch',
77
- path: doc.path,
78
- assetId: existingAsset.assetId,
79
- existingReferenceNumber: existingAsset.referenceNumber,
80
- incomingReferenceNumber: normalizedIncomingReference
81
- });
82
- }
83
- return (allowReferenceNumberReassignment && existingAsset.referenceNumber !== normalizedIncomingReference)
155
+ return referenceNumberMismatch
84
156
  || existingAsset.version !== normalizedIncomingVersion
85
157
  || (existingAsset.documentId || null) !== normalizedIncomingDocumentId
86
158
  || (existingAsset.logicalName || null) !== normalizedIncomingLogicalName
87
159
  || (existingAsset.originalFilename || null) !== normalizedIncomingFilename
88
- || (primaryLink?.taskId || null) !== normalizedIncomingTaskId
160
+ || (primaryLinkTarget?.targetType || null) !== (incomingLinkTarget?.targetType || null)
161
+ || (primaryLinkTarget?.targetId || null) !== (incomingLinkTarget?.targetId || null)
89
162
  || (primaryLink?.displayName || null) !== normalizedIncomingCaption
90
163
  || ((primaryLink?.role === 'reference' ? 'reference' : 'attachment')) !== normalizedIncomingLinkRole;
91
164
  }
92
- export function hasBinaryAssetSyncMetadataDrift(deps, workspaceId, asset, options) {
165
+ export function hasBinaryAssetSyncMetadataDrift(deps, workspaceId, asset) {
93
166
  if (!deps.workspaceAssetStore)
94
167
  return false;
95
168
  const existingAsset = deps.workspaceAssetStore.getByStorageKey(asset.path, workspaceId);
@@ -108,31 +181,21 @@ export function hasBinaryAssetSyncMetadataDrift(deps, workspaceId, asset, option
108
181
  const normalizedIncomingFilename = typeof asset.originalFilename === 'string' && asset.originalFilename.trim().length > 0
109
182
  ? asset.originalFilename.trim()
110
183
  : null;
111
- const normalizedIncomingTaskId = typeof asset.taskId === 'string' && asset.taskId.trim().length > 0
112
- ? asset.taskId.trim()
113
- : null;
184
+ const incomingLinkTarget = resolveIncomingSyncLinkTarget(asset);
185
+ const primaryLinkTarget = resolveSyncLinkTarget(primaryLink);
114
186
  const normalizedIncomingLinkRole = asset.linkRole === 'reference'
115
187
  ? 'reference'
116
188
  : asset.kind === 'image'
117
189
  ? 'image'
118
190
  : 'attachment';
119
- const allowReferenceNumberReassignment = options?.allowReferenceNumberReassignment === true;
120
191
  const referenceNumberMismatch = Boolean(existingAsset.referenceNumber
121
192
  && normalizedIncomingReference
122
193
  && existingAsset.referenceNumber !== normalizedIncomingReference);
123
- if (referenceNumberMismatch) {
124
- deps.recordSyncDiagnostic(workspaceId, 'apply', 'Detected asset reference number mismatch during normal sync.', {
125
- source: 'assets.referenceNumber.mismatch',
126
- path: asset.path,
127
- assetId: existingAsset.assetId,
128
- existingReferenceNumber: existingAsset.referenceNumber,
129
- incomingReferenceNumber: normalizedIncomingReference
130
- });
131
- }
132
- return (allowReferenceNumberReassignment && existingAsset.referenceNumber !== normalizedIncomingReference)
194
+ return referenceNumberMismatch
133
195
  || (existingAsset.logicalName || null) !== normalizedIncomingLogicalName
134
196
  || (existingAsset.originalFilename || null) !== normalizedIncomingFilename
135
- || (primaryLink?.taskId || null) !== normalizedIncomingTaskId
197
+ || (primaryLinkTarget?.targetType || null) !== (incomingLinkTarget?.targetType || null)
198
+ || (primaryLinkTarget?.targetId || null) !== (incomingLinkTarget?.targetId || null)
136
199
  || (primaryLink?.displayName || null) !== normalizedIncomingCaption
137
200
  || ((primaryLink?.role === 'reference'
138
201
  ? 'reference'
@@ -147,7 +210,7 @@ export function reconcileWorkspaceSyncLinks(deps, input) {
147
210
  const assetId = String(input.assetId || '').trim();
148
211
  if (!assetId)
149
212
  return;
150
- const desiredTaskId = String(input.taskId || '').trim();
213
+ const desiredLinkTarget = resolveIncomingSyncLinkTarget(input);
151
214
  const desiredRole = input.role === 'reference'
152
215
  ? 'reference'
153
216
  : input.role === 'image'
@@ -155,27 +218,32 @@ export function reconcileWorkspaceSyncLinks(deps, input) {
155
218
  : 'attachment';
156
219
  const linkUpdatedAt = String(input.updatedAt || '').trim() || new Date().toISOString();
157
220
  const existingLinks = deps.workspaceAssetStore.listLinksForAsset(assetId, workspaceId, { includeDeleted: true });
158
- if (desiredTaskId) {
221
+ if (desiredLinkTarget) {
159
222
  deps.workspaceAssetStore.upsertLink({
160
223
  workspaceId,
161
224
  assetId,
162
- taskId: desiredTaskId,
225
+ targetType: desiredLinkTarget.targetType,
226
+ targetId: desiredLinkTarget.targetId,
163
227
  role: desiredRole,
164
228
  displayName: typeof input.displayName === 'string' && input.displayName.trim().length > 0 ? input.displayName.trim() : null,
165
229
  updatedAt: linkUpdatedAt,
166
230
  deletedAt: null
167
231
  });
168
232
  }
169
- if (desiredTaskId) {
233
+ if (desiredLinkTarget) {
170
234
  for (const link of existingLinks) {
171
- if (link.taskId === desiredTaskId && link.role === desiredRole)
235
+ if (link.targetType === desiredLinkTarget.targetType
236
+ && link.targetId === desiredLinkTarget.targetId
237
+ && link.role === desiredRole) {
172
238
  continue;
239
+ }
173
240
  if (link.deletedAt)
174
241
  continue;
175
242
  deps.workspaceAssetStore.deleteLink({
176
243
  workspaceId,
177
244
  assetId,
178
- taskId: link.taskId,
245
+ targetType: link.targetType,
246
+ targetId: link.targetId,
179
247
  role: link.role
180
248
  });
181
249
  }
@@ -205,26 +273,9 @@ export async function listWorkspaceSyncDocumentsSnapshot(deps, basePath, workspa
205
273
  const root = path.resolve(basePath);
206
274
  const objectStorageClient = deps.getObjectStorageClient();
207
275
  const candidatePaths = new Set();
208
- const docsRoot = path.join(root, 'docs');
209
- const collectMarkdownPaths = (directory) => {
210
- if (!fs.existsSync(directory))
211
- return;
212
- const entries = fs.readdirSync(directory, { withFileTypes: true });
213
- for (const entry of entries) {
214
- const absolutePath = path.join(directory, entry.name);
215
- if (entry.isDirectory()) {
216
- collectMarkdownPaths(absolutePath);
217
- continue;
218
- }
219
- if (!entry.isFile())
220
- continue;
221
- const relativeFromRoot = path.relative(root, absolutePath).replace(/\\/g, '/');
222
- const normalized = deps.normalizeWorkspaceSyncDocumentPath(relativeFromRoot);
223
- if (normalized)
224
- candidatePaths.add(normalized);
225
- }
226
- };
227
- collectMarkdownPaths(docsRoot);
276
+ // Shared document sync is canonical-document-only. Raw .taskforce/docs files
277
+ // are intentionally excluded because they are not workspace-scoped and must
278
+ // not re-enter cross-runtime shared document sync.
228
279
  if (deps.workspaceAssetStore) {
229
280
  const canonicalAssets = deps.workspaceAssetStore.listAllByWorkspace(workspaceId, {
230
281
  includeDeleted: false,
@@ -345,28 +396,9 @@ export async function listWorkspaceSyncDocumentsSnapshot(deps, basePath, workspa
345
396
  return docs;
346
397
  }
347
398
  export async function listWorkspaceSyncDocumentIndex(deps, basePath, workspaceId = 'default') {
348
- const root = path.resolve(basePath);
349
399
  const candidatePaths = new Set();
350
- const docsRoot = path.join(root, 'docs');
351
- const collectMarkdownPaths = (directory) => {
352
- if (!fs.existsSync(directory))
353
- return;
354
- const entries = fs.readdirSync(directory, { withFileTypes: true });
355
- for (const entry of entries) {
356
- const absolutePath = path.join(directory, entry.name);
357
- if (entry.isDirectory()) {
358
- collectMarkdownPaths(absolutePath);
359
- continue;
360
- }
361
- if (!entry.isFile())
362
- continue;
363
- const relativeFromRoot = path.relative(root, absolutePath).replace(/\\/g, '/');
364
- const normalized = deps.normalizeWorkspaceSyncDocumentPath(relativeFromRoot);
365
- if (normalized)
366
- candidatePaths.add(normalized);
367
- }
368
- };
369
- collectMarkdownPaths(docsRoot);
400
+ // Keep the document index aligned with the snapshot invariant above: only
401
+ // canonical workspace document assets may participate in shared document sync.
370
402
  if (deps.workspaceAssetStore) {
371
403
  const canonicalAssets = deps.workspaceAssetStore.listAllByWorkspace(workspaceId, {
372
404
  includeDeleted: false,
@@ -419,14 +451,13 @@ export async function listWorkspaceSyncDocumentIndex(deps, basePath, workspaceId
419
451
  return docs;
420
452
  }
421
453
  export async function listWorkspaceSyncBinaryAssetsSnapshot(deps, basePath, workspaceId = 'default') {
422
- if (!deps.workspaceAssetStore)
423
- return [];
424
454
  const root = path.resolve(basePath);
425
455
  const objectStorageClient = deps.getObjectStorageClient();
426
- const assets = deps.workspaceAssetStore.listAllByWorkspace(workspaceId, {
456
+ const assets = deps.workspaceAssetStore?.listAllByWorkspace(workspaceId, {
427
457
  includeDeleted: false
428
- });
458
+ }) || [];
429
459
  const snapshots = [];
460
+ const emittedPaths = new Set();
430
461
  for (const asset of assets) {
431
462
  if (asset.kind !== 'image' && asset.kind !== 'file')
432
463
  continue;
@@ -437,6 +468,7 @@ export async function listWorkspaceSyncBinaryAssetsSnapshot(deps, basePath, work
437
468
  continue;
438
469
  if (!deps.normalizeTaskDataRelativePath(storageKey))
439
470
  continue;
471
+ emittedPaths.add(storageKey);
440
472
  try {
441
473
  let buffer = null;
442
474
  if (asset.storageProvider === 'r2' && objectStorageClient) {
@@ -467,6 +499,7 @@ export async function listWorkspaceSyncBinaryAssetsSnapshot(deps, basePath, work
467
499
  continue;
468
500
  }
469
501
  const { primaryLink, effectiveUpdatedAt } = resolveCanonicalAssetSyncLinkState(deps, asset, workspaceId);
502
+ const linkTarget = resolveSyncLinkTarget(primaryLink);
470
503
  snapshots.push({
471
504
  path: storageKey,
472
505
  updatedAt: effectiveUpdatedAt,
@@ -475,7 +508,9 @@ export async function listWorkspaceSyncBinaryAssetsSnapshot(deps, basePath, work
475
508
  kind: asset.kind,
476
509
  mimeType: asset.mimeType || 'application/octet-stream',
477
510
  referenceNumber: asset.referenceNumber,
478
- taskId: primaryLink?.taskId || null,
511
+ taskId: linkTarget?.targetType === 'task' ? linkTarget.targetId : null,
512
+ linkTargetType: linkTarget?.targetType || null,
513
+ linkTargetId: linkTarget?.targetId || null,
479
514
  logicalName: asset.logicalName || null,
480
515
  caption: primaryLink?.displayName || null,
481
516
  originalFilename: asset.originalFilename || path.basename(storageKey),
@@ -490,15 +525,56 @@ export async function listWorkspaceSyncBinaryAssetsSnapshot(deps, basePath, work
490
525
  });
491
526
  }
492
527
  }
528
+ const referencedAiAvatarAssets = listReferencedAiProfileAvatarAssetPaths(deps, workspaceId);
529
+ for (const [assetPath, metadata] of referencedAiAvatarAssets.entries()) {
530
+ if (emittedPaths.has(assetPath))
531
+ continue;
532
+ const absolutePath = path.resolve(root, assetPath);
533
+ if (absolutePath === root || !absolutePath.startsWith(`${root}${path.sep}`))
534
+ continue;
535
+ try {
536
+ let buffer = null;
537
+ if (objectStorageClient) {
538
+ const object = await objectStorageClient.getObject(assetPath);
539
+ buffer = object?.body || null;
540
+ }
541
+ else if (fs.existsSync(absolutePath)) {
542
+ buffer = fs.readFileSync(absolutePath);
543
+ }
544
+ if (!buffer)
545
+ continue;
546
+ snapshots.push({
547
+ path: assetPath,
548
+ updatedAt: metadata.updatedAt || new Date().toISOString(),
549
+ contentBase64: buffer.toString('base64'),
550
+ ...(metadata.assetId ? { assetId: metadata.assetId } : {}),
551
+ kind: 'image',
552
+ mimeType: metadata.mimeType,
553
+ referenceNumber: null,
554
+ taskId: null,
555
+ linkTargetType: null,
556
+ linkTargetId: null,
557
+ logicalName: null,
558
+ caption: null,
559
+ originalFilename: metadata.originalFilename,
560
+ linkRole: 'image'
561
+ });
562
+ }
563
+ catch (error) {
564
+ deps.recordSyncDiagnostic(workspaceId, 'pull', 'Failed to read referenced AI profile avatar asset.', {
565
+ source: 'assets.snapshot.aiProfileAvatar',
566
+ path: assetPath,
567
+ error: String(error?.message || error || '')
568
+ });
569
+ }
570
+ }
493
571
  return snapshots;
494
572
  }
495
573
  export async function listWorkspaceSyncBinaryAssetIndex(deps, workspaceId = 'default') {
496
- if (!deps.workspaceAssetStore)
497
- return [];
498
- const assets = deps.workspaceAssetStore.listAllByWorkspace(workspaceId, {
574
+ const assets = deps.workspaceAssetStore?.listAllByWorkspace(workspaceId, {
499
575
  includeDeleted: false
500
- });
501
- return assets
576
+ }) || [];
577
+ const indexed = assets
502
578
  .filter((asset) => asset.kind === 'image' || asset.kind === 'file')
503
579
  .filter((asset) => asset.storageProvider !== 'external')
504
580
  .filter((asset) => {
@@ -508,6 +584,7 @@ export async function listWorkspaceSyncBinaryAssetIndex(deps, workspaceId = 'def
508
584
  .map((asset) => {
509
585
  const storageKey = String(asset.storageKey || '').trim();
510
586
  const { primaryLink, effectiveUpdatedAt } = resolveCanonicalAssetSyncLinkState(deps, asset, workspaceId);
587
+ const linkTarget = resolveSyncLinkTarget(primaryLink);
511
588
  const assetKind = asset.kind === 'image' ? 'image' : 'file';
512
589
  return {
513
590
  path: storageKey,
@@ -516,7 +593,9 @@ export async function listWorkspaceSyncBinaryAssetIndex(deps, workspaceId = 'def
516
593
  kind: assetKind,
517
594
  mimeType: asset.mimeType || 'application/octet-stream',
518
595
  referenceNumber: asset.referenceNumber,
519
- taskId: primaryLink?.taskId || null,
596
+ taskId: linkTarget?.targetType === 'task' ? linkTarget.targetId : null,
597
+ linkTargetType: linkTarget?.targetType || null,
598
+ linkTargetId: linkTarget?.targetId || null,
520
599
  logicalName: asset.logicalName || null,
521
600
  caption: primaryLink?.displayName || null,
522
601
  originalFilename: asset.originalFilename || path.basename(storageKey),
@@ -524,6 +603,29 @@ export async function listWorkspaceSyncBinaryAssetIndex(deps, workspaceId = 'def
524
603
  };
525
604
  })
526
605
  .filter((entry) => Number.isFinite(Date.parse(entry.updatedAt)) && entry.path.length > 0);
606
+ const indexedPaths = new Set(indexed.map((entry) => entry.path));
607
+ for (const [assetPath, metadata] of listReferencedAiProfileAvatarAssetPaths(deps, workspaceId).entries()) {
608
+ if (indexedPaths.has(assetPath))
609
+ continue;
610
+ if (!Number.isFinite(Date.parse(metadata.updatedAt)))
611
+ continue;
612
+ indexed.push({
613
+ path: assetPath,
614
+ updatedAt: metadata.updatedAt,
615
+ ...(metadata.assetId ? { assetId: metadata.assetId } : {}),
616
+ kind: 'image',
617
+ mimeType: metadata.mimeType,
618
+ referenceNumber: null,
619
+ taskId: null,
620
+ linkTargetType: null,
621
+ linkTargetId: null,
622
+ logicalName: null,
623
+ caption: null,
624
+ originalFilename: metadata.originalFilename,
625
+ linkRole: 'image'
626
+ });
627
+ }
628
+ return indexed;
527
629
  }
528
630
  export async function loadWorkspaceSyncDocumentPayload(deps, basePath, workspaceId, relativePath) {
529
631
  const normalizedPath = deps.normalizeWorkspaceSyncDocumentPath(relativePath);
@@ -626,16 +728,18 @@ export async function loadWorkspaceSyncBinaryAssetPayload(deps, basePath, worksp
626
728
  const normalizedPath = deps.normalizeTaskDataRelativePath(assetPath);
627
729
  if (!normalizedPath)
628
730
  return null;
629
- if (!deps.workspaceAssetStore)
630
- return null;
631
- const asset = deps.workspaceAssetStore.getByStorageKey(normalizedPath, workspaceId);
632
- if (!asset || (asset.kind !== 'image' && asset.kind !== 'file') || asset.storageProvider === 'external') {
731
+ const asset = deps.workspaceAssetStore?.getByStorageKey(normalizedPath, workspaceId) || null;
732
+ const referencedAiAvatar = !asset
733
+ ? listReferencedAiProfileAvatarAssetPaths(deps, workspaceId).get(normalizedPath) || null
734
+ : null;
735
+ if (!referencedAiAvatar
736
+ && (!asset || (asset.kind !== 'image' && asset.kind !== 'file') || asset.storageProvider === 'external')) {
633
737
  return null;
634
738
  }
635
739
  const objectStorageClient = deps.getObjectStorageClient();
636
740
  let buffer = null;
637
741
  try {
638
- if (asset.storageProvider === 'r2' && objectStorageClient) {
742
+ if ((asset?.storageProvider === 'r2' || referencedAiAvatar) && objectStorageClient) {
639
743
  const object = await objectStorageClient.getObject(normalizedPath);
640
744
  buffer = object?.body || null;
641
745
  }
@@ -648,28 +752,59 @@ export async function loadWorkspaceSyncBinaryAssetPayload(deps, basePath, worksp
648
752
  return null;
649
753
  buffer = fs.readFileSync(absolutePath);
650
754
  }
755
+ if (!buffer && referencedAiAvatar && objectStorageClient) {
756
+ const root = path.resolve(basePath);
757
+ const absolutePath = path.resolve(root, normalizedPath);
758
+ if (absolutePath !== root && absolutePath.startsWith(`${root}${path.sep}`) && fs.existsSync(absolutePath)) {
759
+ buffer = fs.readFileSync(absolutePath);
760
+ }
761
+ }
651
762
  }
652
763
  catch (error) {
653
764
  deps.recordSyncDiagnostic(workspaceId, 'pull', 'Failed to load targeted binary asset payload.', {
654
765
  source: 'assets.snapshot.loadPayload',
655
766
  path: normalizedPath,
656
- assetId: asset.assetId,
767
+ assetId: asset?.assetId || referencedAiAvatar?.assetId,
657
768
  error: String(error?.message || error || '')
658
769
  });
659
770
  return null;
660
771
  }
661
772
  if (!buffer)
662
773
  return null;
774
+ if (!asset && referencedAiAvatar) {
775
+ return {
776
+ path: normalizedPath,
777
+ updatedAt: referencedAiAvatar.updatedAt || new Date().toISOString(),
778
+ contentBase64: buffer.toString('base64'),
779
+ ...(referencedAiAvatar.assetId ? { assetId: referencedAiAvatar.assetId } : {}),
780
+ kind: 'image',
781
+ mimeType: referencedAiAvatar.mimeType,
782
+ referenceNumber: null,
783
+ taskId: null,
784
+ linkTargetType: null,
785
+ linkTargetId: null,
786
+ logicalName: null,
787
+ caption: null,
788
+ originalFilename: referencedAiAvatar.originalFilename,
789
+ linkRole: 'image'
790
+ };
791
+ }
792
+ if (!asset)
793
+ return null;
663
794
  const { primaryLink, effectiveUpdatedAt } = resolveCanonicalAssetSyncLinkState(deps, asset, workspaceId);
795
+ const linkTarget = resolveSyncLinkTarget(primaryLink);
796
+ const assetKind = asset.kind === 'image' ? 'image' : 'file';
664
797
  return {
665
798
  path: normalizedPath,
666
799
  updatedAt: effectiveUpdatedAt,
667
800
  contentBase64: buffer.toString('base64'),
668
801
  assetId: asset.assetId,
669
- kind: asset.kind,
802
+ kind: assetKind,
670
803
  mimeType: asset.mimeType || 'application/octet-stream',
671
804
  referenceNumber: asset.referenceNumber,
672
- taskId: primaryLink?.taskId || null,
805
+ taskId: linkTarget?.targetType === 'task' ? linkTarget.targetId : null,
806
+ linkTargetType: linkTarget?.targetType || null,
807
+ linkTargetId: linkTarget?.targetId || null,
673
808
  logicalName: asset.logicalName || null,
674
809
  caption: primaryLink?.displayName || null,
675
810
  originalFilename: asset.originalFilename || path.basename(normalizedPath),
@@ -774,11 +909,13 @@ export async function writeWorkspaceSyncDocument(deps, basePath, doc, workspaceI
774
909
  purgeAfter: null,
775
910
  allowReferenceNumberReassignment
776
911
  });
777
- const taskId = String(doc.taskId || '').trim();
912
+ const linkTarget = resolveIncomingSyncLinkTarget(doc);
778
913
  reconcileWorkspaceSyncLinks(deps, {
779
914
  workspaceId,
780
915
  assetId: asset.assetId,
781
- taskId,
916
+ taskId: linkTarget?.targetType === 'task' ? linkTarget.targetId : null,
917
+ linkTargetType: linkTarget?.targetType || null,
918
+ linkTargetId: linkTarget?.targetId || null,
782
919
  displayName: typeof doc.caption === 'string' && doc.caption.trim().length > 0 ? doc.caption.trim() : null,
783
920
  role: doc.linkRole === 'reference' ? 'reference' : 'attachment',
784
921
  updatedAt: effectiveUpdatedAt
@@ -866,11 +1003,13 @@ export async function writeWorkspaceSyncBinaryAsset(deps, basePath, asset, works
866
1003
  purgeAfter: null,
867
1004
  allowReferenceNumberReassignment
868
1005
  });
869
- const taskId = String(asset.taskId || '').trim();
1006
+ const linkTarget = resolveIncomingSyncLinkTarget(asset);
870
1007
  reconcileWorkspaceSyncLinks(deps, {
871
1008
  workspaceId,
872
1009
  assetId: assetRecord.assetId,
873
- taskId,
1010
+ taskId: linkTarget?.targetType === 'task' ? linkTarget.targetId : null,
1011
+ linkTargetType: linkTarget?.targetType || null,
1012
+ linkTargetId: linkTarget?.targetId || null,
874
1013
  displayName: typeof asset.caption === 'string' && asset.caption.trim().length > 0 ? asset.caption.trim() : null,
875
1014
  role: asset.linkRole === 'reference' ? 'reference' : asset.kind === 'image' ? 'image' : 'attachment',
876
1015
  updatedAt: effectiveUpdatedAt
@@ -926,7 +1065,8 @@ export function deleteWorkspaceSyncBinaryAsset(deps, basePath, assetPath, worksp
926
1065
  deps.workspaceAssetStore.deleteLink({
927
1066
  workspaceId,
928
1067
  assetId: existing.assetId,
929
- taskId: link.taskId,
1068
+ targetType: link.targetType,
1069
+ targetId: link.targetId,
930
1070
  role: link.role
931
1071
  });
932
1072
  }
@@ -976,7 +1116,8 @@ export function deleteWorkspaceSyncDocument(deps, basePath, docPath, workspaceId
976
1116
  deps.workspaceAssetStore.deleteLink({
977
1117
  workspaceId,
978
1118
  assetId: existing.assetId,
979
- taskId: link.taskId,
1119
+ targetType: link.targetType,
1120
+ targetId: link.targetId,
980
1121
  role: link.role
981
1122
  });
982
1123
  }
@@ -996,8 +1137,8 @@ export function createContentSyncState(deps) {
996
1137
  return {
997
1138
  resolveCanonicalAssetSyncLinkState: (asset, workspaceId) => resolveCanonicalAssetSyncLinkState(deps, asset, workspaceId),
998
1139
  getCanonicalSyncDocumentMetadata: (relativePath, workspaceId) => getCanonicalSyncDocumentMetadata(deps, relativePath, workspaceId),
999
- hasDocumentSyncMetadataDrift: (workspaceId, doc, options) => hasDocumentSyncMetadataDrift(deps, workspaceId, doc, options),
1000
- hasBinaryAssetSyncMetadataDrift: (workspaceId, asset, options) => hasBinaryAssetSyncMetadataDrift(deps, workspaceId, asset, options),
1140
+ hasDocumentSyncMetadataDrift: (workspaceId, doc, _options) => hasDocumentSyncMetadataDrift(deps, workspaceId, doc),
1141
+ hasBinaryAssetSyncMetadataDrift: (workspaceId, asset, _options) => hasBinaryAssetSyncMetadataDrift(deps, workspaceId, asset),
1001
1142
  reconcileWorkspaceSyncLinks: (input) => reconcileWorkspaceSyncLinks(deps, input),
1002
1143
  listWorkspaceSyncDocumentDeletesSnapshot: (workspaceId = 'default') => listWorkspaceSyncDocumentDeletesSnapshot(deps, workspaceId),
1003
1144
  listWorkspaceSyncDocumentIndex: (basePath, workspaceId = 'default') => listWorkspaceSyncDocumentIndex(deps, basePath, workspaceId),
@@ -23,6 +23,9 @@ function toOptionalInteger(value) {
23
23
  return null;
24
24
  return Math.floor(normalized);
25
25
  }
26
+ function clonePlanningAttachments(value) {
27
+ return Array.isArray(value) ? value : undefined;
28
+ }
26
29
  export function normalizeTaxonomySyncPayload(raw) {
27
30
  if (!raw || typeof raw !== 'object' || Array.isArray(raw))
28
31
  return null;
@@ -56,6 +59,7 @@ export function normalizeInitiativeSyncPayload(raw, sourceWatermark) {
56
59
  createdAt: String(source.createdAt || sourceWatermark || '').trim(),
57
60
  updatedAt: String(source.updatedAt || sourceWatermark || source.createdAt || '').trim(),
58
61
  order: toOptionalInteger(source.order),
62
+ attachments: clonePlanningAttachments(source.attachments),
59
63
  isArchived: Boolean(source.isArchived),
60
64
  };
61
65
  }
@@ -77,6 +81,7 @@ export function normalizeWorkstreamSyncPayload(raw, sourceWatermark) {
77
81
  createdAt: String(source.createdAt || sourceWatermark || '').trim(),
78
82
  updatedAt: String(source.updatedAt || sourceWatermark || source.createdAt || '').trim(),
79
83
  order: toOptionalInteger(source.order),
84
+ attachments: clonePlanningAttachments(source.attachments),
80
85
  isArchived: Boolean(source.isArchived),
81
86
  };
82
87
  }