@taskforcehq/taskforce 0.3.304 → 0.3.306

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 (383) hide show
  1. package/README.md +140 -247
  2. package/dist/Taskforce.module.css +295 -89
  3. package/dist/TaskforceCore.js +378 -111
  4. package/dist/TaskforceCore.test.js +1221 -107
  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 +52 -2
  14. package/dist/compat/workspaceSyncCompat.test.js +38 -1
  15. package/dist/components/context/ContextAttachmentManager.d.ts +14 -0
  16. package/dist/components/context/ContextAttachmentManager.js +549 -0
  17. package/dist/components/features/AgentsModule.d.ts +10 -1
  18. package/dist/components/features/AgentsModule.js +260 -15
  19. package/dist/components/features/AgentsModule.test.js +255 -5
  20. package/dist/components/features/DocumentIndex.d.ts +1 -1
  21. package/dist/components/features/DocumentIndex.js +1 -1
  22. package/dist/components/features/DocumentViewer.d.ts +6 -2
  23. package/dist/components/features/DocumentViewer.js +90 -10
  24. package/dist/components/features/DocumentWorkspace.d.ts +5 -22
  25. package/dist/components/features/DocumentWorkspace.js +12 -155
  26. package/dist/components/features/DocumentWorkspace.test.js +226 -6
  27. package/dist/components/features/TaskSettings.js +29 -3
  28. package/dist/components/features/TaskSettings.test.js +42 -1
  29. package/dist/components/features/documentWorkspaceModel.d.ts +24 -0
  30. package/dist/components/features/documentWorkspaceModel.js +57 -0
  31. package/dist/components/features/useDocumentWorkspaceController.d.ts +34 -0
  32. package/dist/components/features/useDocumentWorkspaceController.js +113 -0
  33. package/dist/components/task/TaskCard.js +19 -28
  34. package/dist/components/task/TaskCard.test.js +38 -3
  35. package/dist/components/task/TaskContextUpload.js +4 -526
  36. package/dist/components/task/TaskForm.d.ts +8 -8
  37. package/dist/components/task/TaskForm.js +362 -230
  38. package/dist/components/task/TaskForm.test.js +558 -381
  39. package/dist/components/task/TaskKanban.d.ts +2 -1
  40. package/dist/components/task/TaskKanban.js +96 -14
  41. package/dist/components/task/TaskKanban.test.js +36 -0
  42. package/dist/components/ui/EditableAvatarButton.d.ts +18 -0
  43. package/dist/components/ui/EditableAvatarButton.js +18 -0
  44. package/dist/components/views/PlanComparisonPage.d.ts +9 -1
  45. package/dist/components/views/PlanComparisonPage.js +70 -17
  46. package/dist/components/views/PlanComparisonPage.test.js +289 -41
  47. package/dist/components/views/PlansPage.js +239 -106
  48. package/dist/components/views/PlansPage.test.js +593 -42
  49. package/dist/components/views/StandaloneLayout.js +310 -554
  50. package/dist/components/views/panels/FilterToolbar.test.js +6 -4
  51. package/dist/components/views/panels/PlanningDrawer.d.ts +8 -1
  52. package/dist/components/views/panels/PlanningDrawer.js +18 -11
  53. package/dist/components/views/panels/PlanningDrawer.test.d.ts +1 -0
  54. package/dist/components/views/panels/PlanningDrawer.test.js +141 -0
  55. package/dist/components/views/planningScope.d.ts +20 -0
  56. package/dist/components/views/planningScope.js +25 -0
  57. package/dist/components/views/planningScope.test.d.ts +1 -0
  58. package/dist/components/views/planningScope.test.js +60 -0
  59. package/dist/components/views/standalone/modals/AccountHubModal.d.ts +27 -14
  60. package/dist/components/views/standalone/modals/AccountHubModal.js +87 -15
  61. package/dist/components/views/standalone/modals/AccountHubModal.test.js +42 -2
  62. package/dist/components/views/standalone/modals/AvatarImageManagerModal.d.ts +20 -0
  63. package/dist/components/views/standalone/modals/AvatarImageManagerModal.js +127 -0
  64. package/dist/components/views/standalone/modals/EditProfileModal.d.ts +2 -9
  65. package/dist/components/views/standalone/modals/EditProfileModal.js +3 -2
  66. package/dist/components/views/standalone/modals/SyncEnableWarningModal.d.ts +9 -0
  67. package/dist/components/views/standalone/modals/SyncEnableWarningModal.js +6 -0
  68. package/dist/components/views/standalone/modals/SyncEnableWarningModal.test.d.ts +1 -0
  69. package/dist/components/views/standalone/modals/SyncEnableWarningModal.test.js +24 -0
  70. package/dist/components/views/standalone/modals/SyncStatusModal.d.ts +2 -1
  71. package/dist/components/views/standalone/modals/SyncStatusModal.js +2 -2
  72. package/dist/config/envSchema.js +1 -1
  73. package/dist/core/AiProfileService.d.ts +45 -3
  74. package/dist/core/AiProfileService.js +774 -63
  75. package/dist/core/AiProfileService.test.js +22 -2
  76. package/dist/core/AiProfiles.test.js +761 -2
  77. package/dist/core/AttachmentLinkService.js +57 -15
  78. package/dist/core/AuthIdentityService.d.ts +107 -0
  79. package/dist/core/AuthIdentityService.js +284 -0
  80. package/dist/core/AuthTokenService.d.ts +4 -0
  81. package/dist/core/AuthTokenService.js +34 -6
  82. package/dist/core/AuthTokenService.test.d.ts +1 -0
  83. package/dist/core/AuthTokenService.test.js +78 -0
  84. package/dist/core/EntitlementsPolicy.test.js +77 -15
  85. package/dist/core/GlobalSettingsService.js +115 -6
  86. package/dist/core/PlanEntitlementService.d.ts +30 -3
  87. package/dist/core/PlanEntitlementService.js +454 -93
  88. package/dist/core/PlanFeatureCatalog.test.d.ts +1 -0
  89. package/dist/core/PlanFeatureCatalog.test.js +84 -0
  90. package/dist/core/PlanVersionPolicy.test.js +54 -28
  91. package/dist/core/PlanningEntities.test.js +52 -0
  92. package/dist/core/SignupMonetizationSettings.test.js +241 -44
  93. package/dist/core/SyncReconciliationService.js +2 -65
  94. package/dist/core/SystemAdmin.test.js +244 -88
  95. package/dist/core/TaskAttachmentsCanonical.test.js +51 -1
  96. package/dist/core/TaskTaxonomyValidation.test.js +53 -0
  97. package/dist/core/Taskforce.d.ts +228 -14
  98. package/dist/core/Taskforce.js +814 -201
  99. package/dist/core/Taskforce.listTasksSlim.test.d.ts +1 -0
  100. package/dist/core/Taskforce.listTasksSlim.test.js +91 -0
  101. package/dist/core/UserProfileAvatarDrafts.test.js +30 -3
  102. package/dist/core/WorkspaceLifecycleService.js +0 -5
  103. package/dist/core/WorkspacePermissions.test.js +25 -1
  104. package/dist/core/WorkspacePlanMode.test.js +128 -27
  105. package/dist/core/shared.d.ts +3 -1
  106. package/dist/core/shared.js +16 -1
  107. package/dist/core/types.d.ts +68 -2
  108. package/dist/hooks/auth/useTaskforceAuthBootstrap.js +26 -1
  109. package/dist/hooks/sync/auth.js +3 -1
  110. package/dist/hooks/sync/bootstrap.js +2 -0
  111. package/dist/hooks/sync/controlPlane.d.ts +37 -0
  112. package/dist/hooks/sync/controlPlane.js +78 -0
  113. package/dist/hooks/sync/controlPlane.test.d.ts +1 -0
  114. package/dist/hooks/sync/controlPlane.test.js +121 -0
  115. package/dist/hooks/sync/lifecyclePolicy.d.ts +45 -0
  116. package/dist/hooks/sync/lifecyclePolicy.js +93 -0
  117. package/dist/hooks/sync/lifecyclePolicy.test.d.ts +1 -0
  118. package/dist/hooks/sync/lifecyclePolicy.test.js +124 -0
  119. package/dist/hooks/sync/orchestratorShared.d.ts +10 -1
  120. package/dist/hooks/sync/orchestratorShared.js +68 -47
  121. package/dist/hooks/sync/orchestratorShared.test.js +50 -1
  122. package/dist/hooks/sync/pullLifecycle.d.ts +31 -0
  123. package/dist/hooks/sync/pullLifecycle.js +24 -0
  124. package/dist/hooks/sync/pullLifecycle.test.d.ts +1 -0
  125. package/dist/hooks/sync/pullLifecycle.test.js +80 -0
  126. package/dist/hooks/sync/recovery.d.ts +16 -2
  127. package/dist/hooks/sync/recovery.js +171 -53
  128. package/dist/hooks/sync/recovery.test.d.ts +1 -0
  129. package/dist/hooks/sync/recovery.test.js +292 -0
  130. package/dist/hooks/sync/transfers.d.ts +16 -3
  131. package/dist/hooks/sync/transfers.js +186 -65
  132. package/dist/hooks/sync/transfers.test.d.ts +1 -0
  133. package/dist/hooks/sync/transfers.test.js +396 -0
  134. package/dist/hooks/sync/useRecentSyncEvents.d.ts +21 -0
  135. package/dist/hooks/sync/useRecentSyncEvents.js +92 -0
  136. package/dist/hooks/sync/useRecentSyncEvents.test.d.ts +1 -0
  137. package/dist/hooks/sync/useRecentSyncEvents.test.js +124 -0
  138. package/dist/hooks/sync/useSyncStatusActions.d.ts +30 -0
  139. package/dist/hooks/sync/useSyncStatusActions.js +88 -0
  140. package/dist/hooks/sync/useSyncStatusActions.test.d.ts +1 -0
  141. package/dist/hooks/sync/useSyncStatusActions.test.js +133 -0
  142. package/dist/hooks/sync/useSyncStatusControls.d.ts +25 -0
  143. package/dist/hooks/sync/useSyncStatusControls.js +60 -0
  144. package/dist/hooks/sync/useSyncStatusControls.test.d.ts +1 -0
  145. package/dist/hooks/sync/useSyncStatusControls.test.js +88 -0
  146. package/dist/hooks/useSyncOrchestrator.aiProfiles.test.js +12 -0
  147. package/dist/hooks/useSyncOrchestrator.d.ts +16 -6
  148. package/dist/hooks/useSyncOrchestrator.js +424 -175
  149. package/dist/hooks/useSyncOrchestrator.retry-closure.test.js +487 -10
  150. package/dist/hooks/useTaskData.js +8 -3
  151. package/dist/hooks/useTaskData.test.js +45 -0
  152. package/dist/hooks/useTaskMutations.d.ts +2 -1
  153. package/dist/hooks/useTaskMutations.js +12 -1
  154. package/dist/hooks/useTaskMutations.test.js +30 -1
  155. package/dist/hooks/useTaskforce.d.ts +65 -4
  156. package/dist/hooks/useTaskforce.js +564 -243
  157. package/dist/hooks/useTaskforce.runtime-routing.test.d.ts +1 -0
  158. package/dist/hooks/useTaskforce.runtime-routing.test.js +152 -0
  159. package/dist/hooks/useTaskforce.sync-behavior.test.js +2454 -208
  160. package/dist/hooks/useWorkspaceSyncController.d.ts +4 -1
  161. package/dist/hooks/useWorkspaceSyncController.js +17 -2
  162. package/dist/hooks/useWorkspaceSyncController.test.js +1 -0
  163. package/dist/hooks/workspace/useTaskforceWorkspaceBootstrap.d.ts +16 -0
  164. package/dist/hooks/workspace/useTaskforceWorkspaceBootstrap.js +316 -35
  165. package/dist/localization/locales/en-US.d.ts +0 -1
  166. package/dist/localization/locales/en-US.js +0 -1
  167. package/dist/localization/locales/es-419.js +0 -1
  168. package/dist/localization/locales/pt-BR.js +0 -1
  169. package/dist/mcp/adminWorkspaceRegistrar.d.ts +2 -0
  170. package/dist/mcp/adminWorkspaceRegistrar.js +154 -0
  171. package/dist/mcp/collaborationRegistrar.d.ts +2 -0
  172. package/dist/mcp/collaborationRegistrar.js +71 -0
  173. package/dist/mcp/documentAssetRegistrar.d.ts +2 -0
  174. package/dist/mcp/documentAssetRegistrar.js +346 -0
  175. package/dist/mcp/runtime.d.ts +2 -0
  176. package/dist/mcp/runtime.js +2433 -3534
  177. package/dist/mcp/runtime.test.js +440 -2
  178. package/dist/mcp/taskPlanningRegistrar.d.ts +2 -0
  179. package/dist/mcp/taskPlanningRegistrar.js +418 -0
  180. package/dist/mcp/toolCatalog.d.ts +35 -0
  181. package/dist/mcp/toolCatalog.js +3 -0
  182. package/dist/migrations/taskSchemaMigrations.d.ts +1 -1
  183. package/dist/migrations/taskSchemaMigrations.js +171 -61
  184. package/dist/migrations/taskSchemaMigrations.test.js +15 -0
  185. package/dist/resources/templates/workflow-sources/workflowDocs.mjs +6 -6
  186. package/dist/resources/templates/workflows/collaborate.yaml +1 -1
  187. package/dist/resources/templates/workflows/evaluate.yaml +2 -2
  188. package/dist/resources/templates/workflows/plan.yaml +1 -1
  189. package/dist/resources/templates/workflows/review.yaml +2 -2
  190. package/dist/server/annotatedAttachmentsRoutes.test.js +3 -3
  191. package/dist/server/auth/providers/apple.d.ts +33 -0
  192. package/dist/server/auth/providers/apple.js +82 -0
  193. package/dist/server/auth/providers/appleClientSecret.d.ts +37 -0
  194. package/dist/server/auth/providers/appleClientSecret.js +65 -0
  195. package/dist/server/auth/providers/github.d.ts +26 -0
  196. package/dist/server/auth/providers/github.js +86 -0
  197. package/dist/server/auth/providers/google.d.ts +21 -0
  198. package/dist/server/auth/providers/google.js +56 -0
  199. package/dist/server/auth/providers/types.d.ts +21 -0
  200. package/dist/server/auth/providers/types.js +1 -0
  201. package/dist/server/auth.d.ts +2 -0
  202. package/dist/server/auth.js +6 -3
  203. package/dist/server/documentReviewRoutes.test.js +36 -3
  204. package/dist/server/index.cookieProxy.test.js +1 -0
  205. package/dist/server/index.d.ts +12 -0
  206. package/dist/server/index.js +120 -9
  207. package/dist/server/index.rateLimit.test.js +3 -0
  208. package/dist/server/index.test.js +106 -3
  209. package/dist/server/routes/admin.d.ts +4 -5
  210. package/dist/server/routes/admin.js +410 -80
  211. package/dist/server/routes/annotatedAttachments.d.ts +1 -1
  212. package/dist/server/routes/annotatedAttachments.js +1 -1
  213. package/dist/server/routes/auth.d.ts +16 -6
  214. package/dist/server/routes/auth.js +1015 -118
  215. package/dist/server/routes/authSupport.d.ts +30 -0
  216. package/dist/server/routes/authSupport.js +81 -0
  217. package/dist/server/routes/billing.d.ts +1 -1
  218. package/dist/server/routes/billing.js +276 -34
  219. package/dist/server/routes/billing.test.js +760 -52
  220. package/dist/server/routes/documentReviews.d.ts +1 -1
  221. package/dist/server/routes/documentReviews.js +1 -1
  222. package/dist/server/routes/documents.d.ts +5 -2
  223. package/dist/server/routes/documents.js +242 -74
  224. package/dist/server/routes/primitives.d.ts +11 -0
  225. package/dist/server/routes/primitives.js +73 -0
  226. package/dist/server/routes/resources.d.ts +1 -1
  227. package/dist/server/routes/resources.js +1 -1
  228. package/dist/server/routes/shared.d.ts +29 -3
  229. package/dist/server/routes/shared.js +69 -4
  230. package/dist/server/routes/sync.d.ts +1 -1
  231. package/dist/server/routes/sync.integration.test.js +437 -39
  232. package/dist/server/routes/sync.js +62 -606
  233. package/dist/server/routes/syncAuxRoutes.d.ts +15 -0
  234. package/dist/server/routes/syncAuxRoutes.js +91 -0
  235. package/dist/server/routes/syncAuxRoutes.test.d.ts +1 -0
  236. package/dist/server/routes/syncAuxRoutes.test.js +158 -0
  237. package/dist/server/routes/syncPullApplyRoutes.d.ts +36 -0
  238. package/dist/server/routes/syncPullApplyRoutes.js +204 -0
  239. package/dist/server/routes/syncPushRoutes.d.ts +24 -0
  240. package/dist/server/routes/syncPushRoutes.js +212 -0
  241. package/dist/server/routes/syncRouteGuards.d.ts +36 -0
  242. package/dist/server/routes/syncRouteGuards.js +67 -0
  243. package/dist/server/routes/syncRouteGuards.test.d.ts +1 -0
  244. package/dist/server/routes/syncRouteGuards.test.js +94 -0
  245. package/dist/server/routes/syncRouteTypes.d.ts +13 -0
  246. package/dist/server/routes/syncRouteTypes.js +1 -0
  247. package/dist/server/routes/syncSnapshotRoutes.d.ts +66 -0
  248. package/dist/server/routes/syncSnapshotRoutes.js +180 -0
  249. package/dist/server/routes/tasks.d.ts +1 -1
  250. package/dist/server/routes/tasks.js +44 -2
  251. package/dist/server/routes/workspaces.d.ts +1 -1
  252. package/dist/server/routes/workspaces.js +37 -6
  253. package/dist/server/routes.d.ts +2 -9
  254. package/dist/server/routes.js +136 -165
  255. package/dist/server/routes.test.js +2457 -162
  256. package/dist/services/workflowExportSnapshots.test.js +2 -0
  257. package/dist/shared/aiProfileSeatScope.d.ts +5 -0
  258. package/dist/shared/aiProfileSeatScope.js +21 -0
  259. package/dist/shared/passwordPolicy.d.ts +13 -0
  260. package/dist/shared/passwordPolicy.js +84 -0
  261. package/dist/shared/passwordPolicy.test.d.ts +1 -0
  262. package/dist/shared/passwordPolicy.test.js +34 -0
  263. package/dist/storage/workspaceAssetStore.d.ts +15 -3
  264. package/dist/storage/workspaceAssetStore.js +132 -44
  265. package/dist/storage/workspaceAssetStore.test.js +93 -6
  266. package/dist/styles/fonts.css +70 -0
  267. package/dist/sync/collaborationSyncPayload.d.ts +6 -1
  268. package/dist/sync/collaborationSyncPayload.js +17 -11
  269. package/dist/sync/collaborationSyncPayload.test.js +13 -1
  270. package/dist/sync/contentSyncState.d.ts +4 -8
  271. package/dist/sync/contentSyncState.js +33 -77
  272. package/dist/sync/syncApplyHandlers.d.ts +7 -0
  273. package/dist/sync/syncApplyHandlers.js +28 -13
  274. package/dist/sync/syncApplyHandlers.test.js +72 -3
  275. package/dist/sync/syncFieldSemantics.d.ts +12 -0
  276. package/dist/sync/syncFieldSemantics.js +55 -0
  277. package/dist/sync/syncResourceAdapters.d.ts +44 -0
  278. package/dist/sync/syncResourceAdapters.js +77 -0
  279. package/dist/sync/syncService.d.ts +6 -0
  280. package/dist/sync/syncService.js +60 -0
  281. package/dist/sync/syncService.test.js +71 -3
  282. package/dist/sync/taskSyncChangeKey.d.ts +2 -0
  283. package/dist/sync/taskSyncChangeKey.js +143 -0
  284. package/dist/sync/taskSyncPayload.js +3 -8
  285. package/dist/sync/workspacePullFeed.js +4 -3
  286. package/dist/sync/workspacePullFeed.test.js +43 -0
  287. package/dist/sync/workspaceRepair.js +5 -2
  288. package/dist/sync/workspaceSyncModel.d.ts +48 -0
  289. package/dist/sync/workspaceSyncModel.js +195 -31
  290. package/dist/sync/workspaceSyncModel.test.js +325 -12
  291. package/dist/sync/workspaceSyncState.d.ts +19 -0
  292. package/dist/sync/workspaceSyncState.js +3 -1
  293. package/dist/sync/workspaceSyncSurface.js +3 -8
  294. package/dist/types.d.ts +17 -0
  295. package/dist/ui/assets/AgentsModule-DrLawwNl.js +1 -0
  296. package/dist/ui/assets/{AnnotatedAttachmentWorkspace-BlS-cqnl.js → AnnotatedAttachmentWorkspace-Z9_whf7F.js} +1 -1
  297. package/dist/ui/assets/CourierPrime-Bold-BuLj_dpw.woff2 +0 -0
  298. package/dist/ui/assets/CourierPrime-BoldItalic-BrK2pUkZ.woff2 +0 -0
  299. package/dist/ui/assets/CourierPrime-Italic-DFUZK5Ey.woff2 +0 -0
  300. package/dist/ui/assets/CourierPrime-Regular-BsKphzVf.woff2 +0 -0
  301. package/dist/ui/assets/DocumentWorkspace-B03MaSkw.js +252 -0
  302. package/dist/ui/assets/DocumentWorkspace-Dhdso07p.css +1 -0
  303. package/dist/ui/assets/{InitiativesModule-BjR6iBf9.js → InitiativesModule-9E6ParrY.js} +1 -1
  304. package/dist/ui/assets/Noir_medium-bxQwKGzB.woff2 +0 -0
  305. package/dist/ui/assets/Noir_regular-ojf2kxlG.woff2 +0 -0
  306. package/dist/ui/assets/PlansPage-CvfnMiWq.css +1 -0
  307. package/dist/ui/assets/PlansPage-DRXscYxH.js +1 -0
  308. package/dist/ui/assets/RussoOne-Regular-Cu_qq_qC.woff2 +0 -0
  309. package/dist/ui/assets/SpecialElite-Regular-Di6gSvAS.woff2 +0 -0
  310. package/dist/ui/assets/TaskSettings-DZX4jk7e.js +9 -0
  311. package/dist/ui/assets/{WorkflowsModule-DnFqdUME.js → WorkflowsModule-BA7jcEpH.js} +1 -1
  312. package/dist/ui/assets/index-9eT8e0Lu.css +1 -0
  313. package/dist/ui/assets/index-C6k75jr8.js +6 -0
  314. package/dist/ui/assets/{vendor-icons-I7ZwG1z_.js → vendor-icons-DuEd_65c.js} +1 -1
  315. package/dist/ui/fonts/CourierPrime-Bold.ttf +0 -0
  316. package/dist/ui/fonts/CourierPrime-Bold.woff2 +0 -0
  317. package/dist/ui/fonts/CourierPrime-BoldItalic.ttf +0 -0
  318. package/dist/ui/fonts/CourierPrime-BoldItalic.woff2 +0 -0
  319. package/dist/ui/fonts/CourierPrime-Italic.ttf +0 -0
  320. package/dist/ui/fonts/CourierPrime-Italic.woff2 +0 -0
  321. package/dist/ui/fonts/CourierPrime-Regular.ttf +0 -0
  322. package/dist/ui/fonts/CourierPrime-Regular.woff2 +0 -0
  323. package/dist/ui/fonts/Noir_medium.otf +0 -0
  324. package/dist/ui/fonts/Noir_medium.woff2 +0 -0
  325. package/dist/ui/fonts/Noir_regular.otf +0 -0
  326. package/dist/ui/fonts/Noir_regular.woff2 +0 -0
  327. package/dist/ui/fonts/RussoOne-Regular.woff2 +0 -0
  328. package/dist/ui/fonts/SpecialElite-Regular.ttf +0 -0
  329. package/dist/ui/fonts/SpecialElite-Regular.woff2 +0 -0
  330. package/dist/ui/index.html +3 -3
  331. package/dist/utils/accountProfileSummaryCache.d.ts +5 -0
  332. package/dist/utils/assignees.d.ts +2 -0
  333. package/dist/utils/assignees.js +2 -0
  334. package/dist/utils/avatarUpload.d.ts +27 -0
  335. package/dist/utils/avatarUpload.js +132 -0
  336. package/dist/utils/avatarUpload.test.d.ts +1 -0
  337. package/dist/utils/avatarUpload.test.js +40 -0
  338. package/dist/utils/bootstrapTrace.d.ts +7 -0
  339. package/dist/utils/bootstrapTrace.js +29 -0
  340. package/dist/utils/commercialLifecyclePresentation.d.ts +19 -0
  341. package/dist/utils/commercialLifecyclePresentation.js +199 -0
  342. package/dist/utils/contextAssetEvents.d.ts +2 -0
  343. package/dist/utils/syncEventDetails.d.ts +3 -0
  344. package/dist/utils/syncEventDetails.js +64 -0
  345. package/dist/utils/syncEventDetails.test.d.ts +1 -0
  346. package/dist/utils/syncEventDetails.test.js +23 -0
  347. package/dist/utils/syncEventPresentation.d.ts +15 -0
  348. package/dist/utils/syncEventPresentation.js +129 -0
  349. package/dist/utils/syncEventPresentation.test.d.ts +1 -0
  350. package/dist/utils/syncEventPresentation.test.js +64 -0
  351. package/dist/utils/syncStatusPresentation.d.ts +72 -0
  352. package/dist/utils/syncStatusPresentation.js +217 -0
  353. package/dist/utils/syncStatusPresentation.test.d.ts +1 -0
  354. package/dist/utils/syncStatusPresentation.test.js +164 -0
  355. package/dist/utils/taskActivity.d.ts +2 -0
  356. package/dist/utils/taskActivity.js +228 -22
  357. package/dist/utils/taskActivity.test.js +119 -8
  358. package/dist/utils/workspaceSyncPresentation.d.ts +4 -0
  359. package/dist/utils/workspaceSyncPresentation.js +68 -2
  360. package/dist/utils/workspaceSyncPresentation.test.js +36 -1
  361. package/package.json +10 -2
  362. package/scripts/check-cloud-mcp.mjs +83 -0
  363. package/scripts/export-sqlite-to-postgres.mjs +7 -9
  364. package/scripts/playwright-auth.sh +5 -1
  365. package/scripts/run-billing-performance-smoke.sh +24 -0
  366. package/scripts/run-e2e-realtime.sh +17 -3
  367. package/scripts/run-smoke.sh +17 -5
  368. package/scripts/run-soak.sh +17 -5
  369. package/src/resources/templates/workflow-sources/workflowDocs.mjs +6 -6
  370. package/src/resources/templates/workflows/collaborate.yaml +1 -1
  371. package/src/resources/templates/workflows/evaluate.yaml +2 -2
  372. package/src/resources/templates/workflows/plan.yaml +1 -1
  373. package/src/resources/templates/workflows/review.yaml +2 -2
  374. package/dist/ui/assets/AgentsModule-BLWVbuKP.js +0 -1
  375. package/dist/ui/assets/DocumentWorkspace-BH_6DF6x.js +0 -250
  376. package/dist/ui/assets/DocumentWorkspace-C_8T8oz-.css +0 -1
  377. package/dist/ui/assets/PlansPage-C2dd2n1X.css +0 -1
  378. package/dist/ui/assets/PlansPage-CSDQ4sLa.js +0 -1
  379. package/dist/ui/assets/RussoOne-Regular-C3BxZIj7.ttf +0 -0
  380. package/dist/ui/assets/TaskSettings-CEDy34Jo.js +0 -9
  381. package/dist/ui/assets/index-DXUdtH1B.js +0 -6
  382. package/dist/ui/assets/index-Ii0B0rTO.css +0 -1
  383. package/scripts/migrate-planning-model.ts +0 -233
@@ -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,25 @@ 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
+ description: readSyncNullableStringField(profile, 'description') ?? null,
43
+ role: readSyncNullableStringField(profile, 'role') ?? null,
44
+ provider: readSyncNullableStringField(profile, 'provider') ?? null,
45
+ model: readSyncNullableStringField(profile, 'model') ?? null,
46
46
  surfaceType: normalizeSurfaceType(profile.surfaceType, { source, profileId, workspaceId: profileWorkspaceId }),
47
+ seatScope: normalizeSeatScope(profile.seatScope, { source, profileId, workspaceId: profileWorkspaceId }),
47
48
  providerMetadata: profile.providerMetadata && typeof profile.providerMetadata === 'object' && !Array.isArray(profile.providerMetadata)
48
49
  ? profile.providerMetadata
49
50
  : null,
51
+ archivedAt: readSyncNullableIsoStringField(profile, 'archivedAt') ?? null,
52
+ archivedBy: readSyncNullableIdField(profile, 'archivedBy') ?? null,
53
+ archivedReason: readSyncNullableStringField(profile, 'archivedReason') ?? null,
54
+ mergedIntoProfileId: readSyncNullableIdField(profile, 'mergedIntoProfileId') ?? null,
55
+ rosterStateUpdatedAt: readSyncNullableIsoStringField(profile, 'rosterStateUpdatedAt') ?? null,
50
56
  createdAt: String(profile.createdAt || '').trim(),
51
57
  updatedAt: String(profile.updatedAt || profile.createdAt || '').trim(),
52
- lastActiveAt: toNullableTrimmedString(profile.lastActiveAt),
58
+ lastActiveAt: readSyncNullableIsoStringField(profile, 'lastActiveAt') ?? toNullableTrimmedString(profile.lastActiveAt),
53
59
  };
54
60
  }
55
61
  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',
@@ -38,7 +44,13 @@ describe('collaborationSyncPayload', () => {
38
44
  provider: 'OpenAI',
39
45
  model: 'gpt-5.4',
40
46
  surfaceType: 'agent',
47
+ seatScope: 'cloud_metered',
41
48
  providerMetadata: { foo: 'bar' },
49
+ archivedAt: null,
50
+ archivedBy: null,
51
+ archivedReason: null,
52
+ mergedIntoProfileId: null,
53
+ rosterStateUpdatedAt: null,
42
54
  createdAt: '2026-04-10T10:00:00.000Z',
43
55
  updatedAt: '2026-04-10T11:00:00.000Z',
44
56
  lastActiveAt: '2026-04-10T12:00:00.000Z',
@@ -28,12 +28,8 @@ export declare function resolveCanonicalAssetSyncLinkState(deps: ContentSyncStat
28
28
  effectiveUpdatedAt: string;
29
29
  };
30
30
  export declare function getCanonicalSyncDocumentMetadata(deps: ContentSyncStateDeps, relativePath: string, workspaceId: string): Omit<DocumentSyncPayload, 'path' | 'updatedAt' | 'content'>;
31
- export declare function hasDocumentSyncMetadataDrift(deps: ContentSyncStateDeps, workspaceId: string, doc: DocumentSyncPayload, options?: {
32
- allowReferenceNumberReassignment?: boolean;
33
- }): boolean;
34
- export declare function hasBinaryAssetSyncMetadataDrift(deps: ContentSyncStateDeps, workspaceId: string, asset: BinaryAssetSyncPayload, options?: {
35
- allowReferenceNumberReassignment?: boolean;
36
- }): boolean;
31
+ export declare function hasDocumentSyncMetadataDrift(deps: ContentSyncStateDeps, workspaceId: string, doc: DocumentSyncPayload): boolean;
32
+ export declare function hasBinaryAssetSyncMetadataDrift(deps: ContentSyncStateDeps, workspaceId: string, asset: BinaryAssetSyncPayload): boolean;
37
33
  export declare function reconcileWorkspaceSyncLinks(deps: ContentSyncStateDeps, input: {
38
34
  workspaceId: string;
39
35
  assetId: string;
@@ -64,10 +60,10 @@ export declare function createContentSyncState(deps: ContentSyncStateDeps): {
64
60
  effectiveUpdatedAt: string;
65
61
  };
66
62
  getCanonicalSyncDocumentMetadata: (relativePath: string, workspaceId: string) => Omit<DocumentSyncPayload, "path" | "updatedAt" | "content">;
67
- hasDocumentSyncMetadataDrift: (workspaceId: string, doc: DocumentSyncPayload, options?: {
63
+ hasDocumentSyncMetadataDrift: (workspaceId: string, doc: DocumentSyncPayload, _options?: {
68
64
  allowReferenceNumberReassignment?: boolean;
69
65
  }) => boolean;
70
- hasBinaryAssetSyncMetadataDrift: (workspaceId: string, asset: BinaryAssetSyncPayload, options?: {
66
+ hasBinaryAssetSyncMetadataDrift: (workspaceId: string, asset: BinaryAssetSyncPayload, _options?: {
71
67
  allowReferenceNumberReassignment?: boolean;
72
68
  }) => boolean;
73
69
  reconcileWorkspaceSyncLinks: (input: {
@@ -38,7 +38,7 @@ export function getCanonicalSyncDocumentMetadata(deps, relativePath, workspaceId
38
38
  linkRole: primaryLink?.role === 'reference' ? 'reference' : 'attachment'
39
39
  };
40
40
  }
41
- export function hasDocumentSyncMetadataDrift(deps, workspaceId, doc, options) {
41
+ export function hasDocumentSyncMetadataDrift(deps, workspaceId, doc) {
42
42
  if (!deps.workspaceAssetStore)
43
43
  return false;
44
44
  const existingAsset = deps.workspaceAssetStore.getByStorageKey(doc.path, workspaceId);
@@ -67,20 +67,10 @@ export function hasDocumentSyncMetadataDrift(deps, workspaceId, doc, options) {
67
67
  ? doc.taskId.trim()
68
68
  : null;
69
69
  const normalizedIncomingLinkRole = doc.linkRole === 'reference' ? 'reference' : 'attachment';
70
- const allowReferenceNumberReassignment = options?.allowReferenceNumberReassignment === true;
71
70
  const referenceNumberMismatch = Boolean(existingAsset.referenceNumber
72
71
  && normalizedIncomingReference
73
72
  && 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)
73
+ return referenceNumberMismatch
84
74
  || existingAsset.version !== normalizedIncomingVersion
85
75
  || (existingAsset.documentId || null) !== normalizedIncomingDocumentId
86
76
  || (existingAsset.logicalName || null) !== normalizedIncomingLogicalName
@@ -89,7 +79,7 @@ export function hasDocumentSyncMetadataDrift(deps, workspaceId, doc, options) {
89
79
  || (primaryLink?.displayName || null) !== normalizedIncomingCaption
90
80
  || ((primaryLink?.role === 'reference' ? 'reference' : 'attachment')) !== normalizedIncomingLinkRole;
91
81
  }
92
- export function hasBinaryAssetSyncMetadataDrift(deps, workspaceId, asset, options) {
82
+ export function hasBinaryAssetSyncMetadataDrift(deps, workspaceId, asset) {
93
83
  if (!deps.workspaceAssetStore)
94
84
  return false;
95
85
  const existingAsset = deps.workspaceAssetStore.getByStorageKey(asset.path, workspaceId);
@@ -116,20 +106,10 @@ export function hasBinaryAssetSyncMetadataDrift(deps, workspaceId, asset, option
116
106
  : asset.kind === 'image'
117
107
  ? 'image'
118
108
  : 'attachment';
119
- const allowReferenceNumberReassignment = options?.allowReferenceNumberReassignment === true;
120
109
  const referenceNumberMismatch = Boolean(existingAsset.referenceNumber
121
110
  && normalizedIncomingReference
122
111
  && 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)
112
+ return referenceNumberMismatch
133
113
  || (existingAsset.logicalName || null) !== normalizedIncomingLogicalName
134
114
  || (existingAsset.originalFilename || null) !== normalizedIncomingFilename
135
115
  || (primaryLink?.taskId || null) !== normalizedIncomingTaskId
@@ -175,7 +155,8 @@ export function reconcileWorkspaceSyncLinks(deps, input) {
175
155
  deps.workspaceAssetStore.deleteLink({
176
156
  workspaceId,
177
157
  assetId,
178
- taskId: link.taskId,
158
+ targetType: link.targetType,
159
+ targetId: link.targetId,
179
160
  role: link.role
180
161
  });
181
162
  }
@@ -205,26 +186,9 @@ export async function listWorkspaceSyncDocumentsSnapshot(deps, basePath, workspa
205
186
  const root = path.resolve(basePath);
206
187
  const objectStorageClient = deps.getObjectStorageClient();
207
188
  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);
189
+ // Shared document sync is canonical-document-only. Raw .taskforce/docs files
190
+ // are intentionally excluded because they are not workspace-scoped and must
191
+ // not re-enter cross-runtime shared document sync.
228
192
  if (deps.workspaceAssetStore) {
229
193
  const canonicalAssets = deps.workspaceAssetStore.listAllByWorkspace(workspaceId, {
230
194
  includeDeleted: false,
@@ -345,28 +309,9 @@ export async function listWorkspaceSyncDocumentsSnapshot(deps, basePath, workspa
345
309
  return docs;
346
310
  }
347
311
  export async function listWorkspaceSyncDocumentIndex(deps, basePath, workspaceId = 'default') {
348
- const root = path.resolve(basePath);
349
312
  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);
313
+ // Keep the document index aligned with the snapshot invariant above: only
314
+ // canonical workspace document assets may participate in shared document sync.
370
315
  if (deps.workspaceAssetStore) {
371
316
  const canonicalAssets = deps.workspaceAssetStore.listAllByWorkspace(workspaceId, {
372
317
  includeDeleted: false,
@@ -533,15 +478,25 @@ export async function loadWorkspaceSyncDocumentPayload(deps, basePath, workspace
533
478
  const absolutePath = path.resolve(path.join(root, normalizedPath));
534
479
  if (absolutePath !== root && !absolutePath.startsWith(`${root}${path.sep}`))
535
480
  return null;
481
+ const objectStorageClient = deps.getObjectStorageClient();
482
+ const canonicalAsset = deps.workspaceAssetStore?.getByStorageKey(normalizedPath, workspaceId);
536
483
  let content = '';
537
484
  let stat = null;
538
485
  try {
539
- if (!fs.existsSync(absolutePath))
540
- return null;
541
- stat = fs.statSync(absolutePath);
542
- if (!stat.isFile())
543
- return null;
544
- content = fs.readFileSync(absolutePath, 'utf8');
486
+ if (canonicalAsset?.kind === 'document' && canonicalAsset.storageProvider === 'r2' && objectStorageClient) {
487
+ const object = await objectStorageClient.getObject(normalizedPath);
488
+ if (!object?.body)
489
+ return null;
490
+ content = object.body.toString('utf8');
491
+ }
492
+ else {
493
+ if (!fs.existsSync(absolutePath))
494
+ return null;
495
+ stat = fs.statSync(absolutePath);
496
+ if (!stat.isFile())
497
+ return null;
498
+ content = fs.readFileSync(absolutePath, 'utf8');
499
+ }
545
500
  }
546
501
  catch (error) {
547
502
  deps.recordSyncDiagnostic(workspaceId, 'pull', 'Failed to load targeted sync document payload.', {
@@ -558,7 +513,6 @@ export async function loadWorkspaceSyncDocumentPayload(deps, basePath, workspace
558
513
  return next;
559
514
  })();
560
515
  const cached = workspaceCache.get(normalizedPath);
561
- const canonicalAsset = deps.workspaceAssetStore?.getByStorageKey(normalizedPath, workspaceId);
562
516
  let updatedAt = '';
563
517
  if (canonicalAsset?.kind === 'document') {
564
518
  updatedAt = resolveCanonicalAssetSyncLinkState(deps, canonicalAsset, workspaceId).effectiveUpdatedAt;
@@ -917,7 +871,8 @@ export function deleteWorkspaceSyncBinaryAsset(deps, basePath, assetPath, worksp
917
871
  deps.workspaceAssetStore.deleteLink({
918
872
  workspaceId,
919
873
  assetId: existing.assetId,
920
- taskId: link.taskId,
874
+ targetType: link.targetType,
875
+ targetId: link.targetId,
921
876
  role: link.role
922
877
  });
923
878
  }
@@ -967,7 +922,8 @@ export function deleteWorkspaceSyncDocument(deps, basePath, docPath, workspaceId
967
922
  deps.workspaceAssetStore.deleteLink({
968
923
  workspaceId,
969
924
  assetId: existing.assetId,
970
- taskId: link.taskId,
925
+ targetType: link.targetType,
926
+ targetId: link.targetId,
971
927
  role: link.role
972
928
  });
973
929
  }
@@ -987,8 +943,8 @@ export function createContentSyncState(deps) {
987
943
  return {
988
944
  resolveCanonicalAssetSyncLinkState: (asset, workspaceId) => resolveCanonicalAssetSyncLinkState(deps, asset, workspaceId),
989
945
  getCanonicalSyncDocumentMetadata: (relativePath, workspaceId) => getCanonicalSyncDocumentMetadata(deps, relativePath, workspaceId),
990
- hasDocumentSyncMetadataDrift: (workspaceId, doc, options) => hasDocumentSyncMetadataDrift(deps, workspaceId, doc, options),
991
- hasBinaryAssetSyncMetadataDrift: (workspaceId, asset, options) => hasBinaryAssetSyncMetadataDrift(deps, workspaceId, asset, options),
946
+ hasDocumentSyncMetadataDrift: (workspaceId, doc, _options) => hasDocumentSyncMetadataDrift(deps, workspaceId, doc),
947
+ hasBinaryAssetSyncMetadataDrift: (workspaceId, asset, _options) => hasBinaryAssetSyncMetadataDrift(deps, workspaceId, asset),
992
948
  reconcileWorkspaceSyncLinks: (input) => reconcileWorkspaceSyncLinks(deps, input),
993
949
  listWorkspaceSyncDocumentDeletesSnapshot: (workspaceId = 'default') => listWorkspaceSyncDocumentDeletesSnapshot(deps, workspaceId),
994
950
  listWorkspaceSyncDocumentIndex: (basePath, workspaceId = 'default') => listWorkspaceSyncDocumentIndex(deps, basePath, workspaceId),
@@ -2,6 +2,7 @@ import type { TaskforceCore, TaskforceSyncCapable } from '../core/Taskforce.js';
2
2
  import type { WorkspaceSyncAiProfileSnapshot, WorkspaceSyncAnnotatedAttachmentSessionSnapshot, WorkspaceSyncChange, WorkspaceSyncDocumentReviewCommentSnapshot, WorkspaceSyncDocumentReviewSessionSnapshot, WorkspaceSyncInitiativeSnapshot, WorkspaceSyncTaskEventSnapshot, WorkspaceSyncTaskSnapshot, WorkspaceSyncWorkspaceMemberSnapshot, WorkspaceSyncWorkstreamSnapshot } from './workspaceSyncModel.js';
3
3
  import type { BinaryAssetSyncPayload, DocumentSyncPayload } from './contentSyncPayload.js';
4
4
  import type { AiProfileSurfaceType } from '../shared/aiProfileSurfaceType.js';
5
+ import type { AiProfileSeatScope } from '../shared/aiProfileSeatScope.js';
5
6
  type SyncCore = TaskforceCore & TaskforceSyncCapable;
6
7
  type SyncRouteError = Error & {
7
8
  code?: string;
@@ -18,6 +19,11 @@ type NormalizeIncomingAiProfileSurfaceType = (value: unknown, context: {
18
19
  profileId?: string;
19
20
  workspaceId?: string;
20
21
  }) => AiProfileSurfaceType | null;
22
+ type NormalizeIncomingAiProfileSeatScope = (value: unknown, context: {
23
+ source: string;
24
+ profileId?: string;
25
+ workspaceId?: string;
26
+ }) => AiProfileSeatScope | null;
21
27
  type NormalizeTaskEventSyncPayload = (raw: unknown, workspaceId: string, sourceWatermark?: string) => WorkspaceSyncTaskEventSnapshot | null;
22
28
  export interface WorkspaceSyncIncomingTaskMutation {
23
29
  archived: boolean;
@@ -68,6 +74,7 @@ export declare function classifyWorkspaceSyncChanges(input: {
68
74
  normalizeWorkspaceSyncDocumentPath: (rawPath: unknown) => string | null;
69
75
  normalizeTaskAssetPath: (rawPath: unknown) => string | null;
70
76
  normalizeIncomingAiProfileSurfaceType: NormalizeIncomingAiProfileSurfaceType;
77
+ normalizeIncomingAiProfileSeatScope: NormalizeIncomingAiProfileSeatScope;
71
78
  normalizeTaskEventSyncPayload: NormalizeTaskEventSyncPayload;
72
79
  recordSyncDiagnostic: RecordSyncDiagnostic;
73
80
  }): WorkspaceSyncIncomingApplyModel;
@@ -83,7 +83,7 @@ function recordTaskReferenceNumberMismatch(input) {
83
83
  return true;
84
84
  }
85
85
  export function classifyWorkspaceSyncChanges(input) {
86
- const { workspaceId, incomingChanges, normalizeWorkspaceSyncDocumentPath, normalizeTaskAssetPath, normalizeIncomingAiProfileSurfaceType, normalizeTaskEventSyncPayload, recordSyncDiagnostic, } = input;
86
+ const { workspaceId, incomingChanges, normalizeWorkspaceSyncDocumentPath, normalizeTaskAssetPath, normalizeIncomingAiProfileSurfaceType, normalizeIncomingAiProfileSeatScope, normalizeTaskEventSyncPayload, recordSyncDiagnostic, } = input;
87
87
  const model = createIncomingApplyModel();
88
88
  for (const change of incomingChanges) {
89
89
  const raw = change;
@@ -111,7 +111,7 @@ export function classifyWorkspaceSyncChanges(input) {
111
111
  continue;
112
112
  }
113
113
  if (op === 'ai-profile-upsert') {
114
- const profile = normalizeAiProfileSyncPayload(raw.profile, workspaceId, normalizeIncomingAiProfileSurfaceType, 'apply.aiProfileUpsert');
114
+ const profile = normalizeAiProfileSyncPayload(raw.profile, workspaceId, normalizeIncomingAiProfileSurfaceType, normalizeIncomingAiProfileSeatScope, 'apply.aiProfileUpsert');
115
115
  const profileId = String(profile?.id || '').trim();
116
116
  if (profileId && profile) {
117
117
  const profileWorkspaceId = String(profile.workspaceId || '').trim();
@@ -382,12 +382,20 @@ export function applyAiProfileAndMemberSyncChanges(input) {
382
382
  username: profile.username,
383
383
  icon: profile.icon,
384
384
  color: profile.color,
385
+ ...(Object.prototype.hasOwnProperty.call(profile, 'avatarUrl') ? { avatarUrl: profile.avatarUrl ?? null } : {}),
386
+ ...(Object.prototype.hasOwnProperty.call(profile, 'avatarSourceUrl') ? { avatarSourceUrl: profile.avatarSourceUrl ?? null } : {}),
385
387
  description: profile.description ?? null,
386
388
  role: profile.role ?? null,
387
389
  provider: profile.provider ?? null,
388
390
  model: profile.model ?? null,
389
391
  surfaceType: profile.surfaceType,
392
+ seatScope: profile.seatScope ?? null,
390
393
  providerMetadata: profile.providerMetadata,
394
+ archivedAt: profile.archivedAt ?? null,
395
+ archivedBy: profile.archivedBy ?? null,
396
+ archivedReason: profile.archivedReason ?? null,
397
+ mergedIntoProfileId: profile.mergedIntoProfileId ?? null,
398
+ rosterStateUpdatedAt: profile.rosterStateUpdatedAt ?? null,
391
399
  createdAt: profile.createdAt,
392
400
  updatedAt: profile.updatedAt,
393
401
  lastActiveAt: profile.lastActiveAt
@@ -434,14 +442,18 @@ export async function applyContentSyncChanges(input) {
434
442
  for (const doc of incomingDocuments) {
435
443
  try {
436
444
  const existingDoc = core.getDocumentWatermark(workspaceId, doc.path);
437
- const existingDocFallback = getExistingDocument ? getExistingDocument(doc.path, workspaceId) : null;
438
- const localDocumentPath = path.resolve(basePath, doc.path);
439
- const localDocumentHash = !hasObjectStorageClient() && fs.existsSync(localDocumentPath)
440
- ? createHash('sha256').update(fs.readFileSync(localDocumentPath, 'utf8')).digest('hex')
441
- : '';
445
+ const existingDocFallback = (!existingDoc && getExistingDocument)
446
+ ? getExistingDocument(doc.path, workspaceId)
447
+ : null;
442
448
  const incomingHash = createHash('sha256').update(String(doc.content || '')).digest('hex');
443
449
  const existingUpdatedAt = String(existingDoc?.updatedAt || existingDocFallback?.updatedAt || '').trim();
444
- const existingHash = String(existingDoc?.contentHash || localDocumentHash || existingDocFallback?.contentHash || '').trim();
450
+ let existingHash = String(existingDoc?.contentHash || existingDocFallback?.contentHash || '').trim();
451
+ if (!existingHash && !hasObjectStorageClient()) {
452
+ const localDocumentPath = path.resolve(basePath, doc.path);
453
+ if (fs.existsSync(localDocumentPath)) {
454
+ existingHash = createHash('sha256').update(fs.readFileSync(localDocumentPath, 'utf8')).digest('hex');
455
+ }
456
+ }
445
457
  const compare = resolveSyncConflictOrdering(doc.updatedAt, existingUpdatedAt, incomingHash, existingHash);
446
458
  const metadataDrift = hasDocumentSyncMetadataDrift(workspaceId, doc, options);
447
459
  if (compare < 0)
@@ -450,7 +462,9 @@ export async function applyContentSyncChanges(input) {
450
462
  continue;
451
463
  await writeWorkspaceSyncDocument(basePath, doc, workspaceId, {
452
464
  ...options,
453
- allowReferenceNumberReassignment: options?.allowReferenceNumberReassignment === true || existingHash !== incomingHash
465
+ allowReferenceNumberReassignment: options?.allowReferenceNumberReassignment === true
466
+ || existingHash !== incomingHash
467
+ || metadataDrift
454
468
  });
455
469
  }
456
470
  catch (error) {
@@ -481,11 +495,11 @@ export async function applyContentSyncChanges(input) {
481
495
  const existing = getExistingBinaryAsset(asset.path, workspaceId);
482
496
  const incomingHash = createHash('sha256').update(Buffer.from(String(asset.contentBase64 || ''), 'base64')).digest('hex');
483
497
  const localFileMissing = !hasObjectStorageClient() && !fs.existsSync(localAssetPath);
484
- const localAssetHash = !hasObjectStorageClient() && !localFileMissing
485
- ? createHash('sha256').update(fs.readFileSync(localAssetPath)).digest('hex')
486
- : '';
487
498
  const existingUpdatedAt = String(existing?.updatedAt || '').trim();
488
- const existingHash = String(localAssetHash || existing?.contentSha256 || '').trim();
499
+ let existingHash = String(existing?.contentSha256 || '').trim();
500
+ if (!existingHash && !hasObjectStorageClient() && !localFileMissing) {
501
+ existingHash = createHash('sha256').update(fs.readFileSync(localAssetPath)).digest('hex');
502
+ }
489
503
  const compare = resolveSyncConflictOrdering(asset.updatedAt, existingUpdatedAt, incomingHash, existingHash);
490
504
  const metadataDrift = hasBinaryAssetSyncMetadataDrift(workspaceId, asset, options);
491
505
  if (compare < 0)
@@ -497,6 +511,7 @@ export async function applyContentSyncChanges(input) {
497
511
  allowReferenceNumberReassignment: options?.allowReferenceNumberReassignment === true
498
512
  || existingHash !== incomingHash
499
513
  || localFileMissing
514
+ || metadataDrift
500
515
  });
501
516
  }
502
517
  catch (error) {