@taskforcehq/taskforce 0.3.303 → 0.3.305

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 (237) hide show
  1. package/README.md +140 -247
  2. package/dist/Taskforce.module.css +102 -5
  3. package/dist/TaskforceCore.js +635 -238
  4. package/dist/TaskforceCore.test.js +2243 -495
  5. package/dist/annotatedAttachments/service.d.ts +1 -1
  6. package/dist/annotatedAttachments/types.d.ts +1 -1
  7. package/dist/compat/workspaceSyncCompat.js +6 -0
  8. package/dist/components/features/AgentsModule.js +1 -1
  9. package/dist/components/features/AgentsModule.test.js +1 -1
  10. package/dist/components/features/DocumentIndex.d.ts +1 -1
  11. package/dist/components/features/DocumentIndex.js +1 -1
  12. package/dist/components/features/DocumentViewer.d.ts +1 -1
  13. package/dist/components/features/DocumentViewer.js +32 -9
  14. package/dist/components/features/DocumentWorkspace.d.ts +5 -22
  15. package/dist/components/features/DocumentWorkspace.js +12 -155
  16. package/dist/components/features/DocumentWorkspace.test.js +193 -6
  17. package/dist/components/features/TaskSettings.js +87 -41
  18. package/dist/components/features/TaskSettings.test.js +180 -40
  19. package/dist/components/features/documentWorkspaceModel.d.ts +24 -0
  20. package/dist/components/features/documentWorkspaceModel.js +57 -0
  21. package/dist/components/features/useDocumentWorkspaceController.d.ts +34 -0
  22. package/dist/components/features/useDocumentWorkspaceController.js +113 -0
  23. package/dist/components/task/TaskActionHeader.d.ts +2 -1
  24. package/dist/components/task/TaskActionHeader.js +3 -3
  25. package/dist/components/task/TaskActionHeader.test.js +8 -0
  26. package/dist/components/task/TaskCard.js +16 -1
  27. package/dist/components/task/TaskCard.test.js +31 -0
  28. package/dist/components/task/TaskForm.d.ts +9 -8
  29. package/dist/components/task/TaskForm.js +374 -219
  30. package/dist/components/task/TaskForm.test.js +482 -361
  31. package/dist/components/task/TaskKanban.d.ts +1 -1
  32. package/dist/components/task/TaskKanban.js +33 -161
  33. package/dist/components/task/TaskStatusActions.d.ts +6 -1
  34. package/dist/components/task/TaskStatusActions.js +8 -3
  35. package/dist/components/task/TaskStatusActions.test.js +9 -0
  36. package/dist/components/task/taskKanbanDropRules.d.ts +58 -0
  37. package/dist/components/task/taskKanbanDropRules.js +187 -0
  38. package/dist/components/task/taskKanbanDropRules.test.d.ts +1 -0
  39. package/dist/components/task/taskKanbanDropRules.test.js +114 -0
  40. package/dist/components/ui/Modal.d.ts +1 -1
  41. package/dist/components/ui/Modal.js +1 -0
  42. package/dist/components/views/AppShellHeader.js +5 -1
  43. package/dist/components/views/AppShellHeader.test.js +4 -0
  44. package/dist/components/views/PlanComparisonPage.d.ts +3 -2
  45. package/dist/components/views/PlanComparisonPage.js +9 -10
  46. package/dist/components/views/PlanComparisonPage.test.js +55 -41
  47. package/dist/components/views/PlansPage.d.ts +5 -1
  48. package/dist/components/views/PlansPage.js +150 -81
  49. package/dist/components/views/PlansPage.test.js +367 -41
  50. package/dist/components/views/StandaloneLayout.js +135 -54
  51. package/dist/components/views/WidgetView.js +11 -2
  52. package/dist/components/views/panels/FilterToolbar.test.js +6 -4
  53. package/dist/components/views/standalone/modals/AccountHubModal.d.ts +2 -14
  54. package/dist/components/views/standalone/modals/AccountHubModal.js +12 -14
  55. package/dist/components/views/standalone/modals/AccountHubModal.test.js +24 -1
  56. package/dist/components/views/standalone/modals/SyncStatusModal.js +1 -1
  57. package/dist/config/envSchema.js +1 -1
  58. package/dist/core/AiProfileService.d.ts +6 -1
  59. package/dist/core/AiProfileService.js +161 -16
  60. package/dist/core/AiProfileService.test.js +3 -1
  61. package/dist/core/AiProfiles.test.js +200 -0
  62. package/dist/core/AuthTokenService.test.d.ts +1 -0
  63. package/dist/core/AuthTokenService.test.js +78 -0
  64. package/dist/core/DeletedTaskLifecycleService.d.ts +2 -1
  65. package/dist/core/EntitlementsPolicy.test.js +75 -13
  66. package/dist/core/PlanEntitlementService.d.ts +9 -1
  67. package/dist/core/PlanEntitlementService.js +144 -19
  68. package/dist/core/PlanVersionPolicy.test.js +19 -26
  69. package/dist/core/SignupMonetizationSettings.test.js +75 -15
  70. package/dist/core/SystemAdmin.test.js +212 -56
  71. package/dist/core/TaskActivityService.d.ts +4 -1
  72. package/dist/core/TaskActivityService.js +45 -0
  73. package/dist/core/TaskAuditTimeline.test.js +52 -1
  74. package/dist/core/TaskTaxonomyValidation.test.js +53 -0
  75. package/dist/core/Taskforce.d.ts +18 -11
  76. package/dist/core/Taskforce.js +93 -12
  77. package/dist/core/WorkspacePlanMode.test.js +73 -8
  78. package/dist/core/shared.d.ts +2 -0
  79. package/dist/core/shared.js +11 -0
  80. package/dist/documentReviews/service.d.ts +1 -1
  81. package/dist/documentReviews/types.d.ts +1 -1
  82. package/dist/hooks/auth/useTaskforceAuthBootstrap.d.ts +48 -0
  83. package/dist/hooks/auth/useTaskforceAuthBootstrap.js +219 -0
  84. package/dist/hooks/sync/auth.d.ts +37 -0
  85. package/dist/hooks/sync/auth.js +63 -0
  86. package/dist/hooks/sync/bootstrap.d.ts +34 -0
  87. package/dist/hooks/sync/bootstrap.js +52 -0
  88. package/dist/hooks/sync/orchestratorShared.d.ts +36 -0
  89. package/dist/hooks/sync/orchestratorShared.js +209 -0
  90. package/dist/hooks/sync/orchestratorShared.test.d.ts +1 -0
  91. package/dist/hooks/sync/orchestratorShared.test.js +49 -0
  92. package/dist/hooks/sync/realtime.d.ts +25 -0
  93. package/dist/hooks/sync/realtime.js +60 -0
  94. package/dist/hooks/sync/recovery.d.ts +69 -0
  95. package/dist/hooks/sync/recovery.js +118 -0
  96. package/dist/hooks/sync/transfers.d.ts +123 -0
  97. package/dist/hooks/sync/transfers.js +435 -0
  98. package/dist/hooks/sync/useDataVersionRefresh.d.ts +16 -0
  99. package/dist/hooks/sync/useDataVersionRefresh.js +73 -0
  100. package/dist/hooks/ui/useResourceExport.d.ts +3 -1
  101. package/dist/hooks/ui/useResourceExport.js +5 -2
  102. package/dist/hooks/ui/useWorkflowTemplates.js +11 -6
  103. package/dist/hooks/useRealtimeSync.js +2 -1
  104. package/dist/hooks/useSyncOrchestrator.aiProfiles.test.js +8 -0
  105. package/dist/hooks/useSyncOrchestrator.context-assets.test.d.ts +1 -0
  106. package/dist/hooks/useSyncOrchestrator.context-assets.test.js +228 -0
  107. package/dist/hooks/useSyncOrchestrator.d.ts +12 -8
  108. package/dist/hooks/useSyncOrchestrator.js +388 -879
  109. package/dist/hooks/useSyncOrchestrator.retry-closure.test.js +641 -6
  110. package/dist/hooks/useTaskMutations.d.ts +2 -1
  111. package/dist/hooks/useTaskMutations.js +57 -7
  112. package/dist/hooks/useTaskMutations.test.js +176 -0
  113. package/dist/hooks/useTaskforce.d.ts +13 -4
  114. package/dist/hooks/useTaskforce.js +302 -817
  115. package/dist/hooks/useTaskforce.sync-behavior.test.js +78 -0
  116. package/dist/hooks/useWorkspaceSyncController.d.ts +4 -1
  117. package/dist/hooks/useWorkspaceSyncController.js +33 -11
  118. package/dist/hooks/useWorkspaceSyncController.test.js +1 -0
  119. package/dist/hooks/workspace/useTaskforceApiRouting.test.js +17 -0
  120. package/dist/hooks/workspace/useTaskforceWorkspaceBootstrap.d.ts +166 -0
  121. package/dist/hooks/workspace/useTaskforceWorkspaceBootstrap.js +434 -0
  122. package/dist/hooks/workspace/workspaceLocalState.d.ts +19 -0
  123. package/dist/hooks/workspace/workspaceLocalState.js +100 -0
  124. package/dist/hooks/workspace/workspaceLocalState.test.d.ts +1 -0
  125. package/dist/hooks/workspace/workspaceLocalState.test.js +59 -0
  126. package/dist/localization/locales/en-US.js +2 -2
  127. package/dist/mcp/adminWorkspaceRegistrar.d.ts +2 -0
  128. package/dist/mcp/adminWorkspaceRegistrar.js +154 -0
  129. package/dist/mcp/canonicalAssetHelpers.d.ts +70 -0
  130. package/dist/mcp/canonicalAssetHelpers.js +259 -0
  131. package/dist/mcp/clientIntegrations.d.ts +12 -1
  132. package/dist/mcp/clientIntegrations.js +161 -6
  133. package/dist/mcp/clientIntegrations.test.js +76 -4
  134. package/dist/mcp/collaborationRegistrar.d.ts +2 -0
  135. package/dist/mcp/collaborationRegistrar.js +71 -0
  136. package/dist/mcp/documentAssetRegistrar.d.ts +2 -0
  137. package/dist/mcp/documentAssetRegistrar.js +346 -0
  138. package/dist/mcp/documentHelpers.d.ts +100 -0
  139. package/dist/mcp/documentHelpers.js +161 -0
  140. package/dist/mcp/runtime.js +2455 -3925
  141. package/dist/mcp/runtime.test.js +240 -8
  142. package/dist/mcp/taskAttachmentHelpers.d.ts +41 -0
  143. package/dist/mcp/taskAttachmentHelpers.js +60 -0
  144. package/dist/mcp/taskAttachmentTypes.d.ts +37 -0
  145. package/dist/mcp/taskAttachmentTypes.js +1 -0
  146. package/dist/mcp/taskPlanningRegistrar.d.ts +2 -0
  147. package/dist/mcp/taskPlanningRegistrar.js +418 -0
  148. package/dist/mcp/toolCatalog.d.ts +35 -0
  149. package/dist/mcp/toolCatalog.js +3 -0
  150. package/dist/plugins/vite.js +1 -1
  151. package/dist/runtime/appGateDefinitions.d.ts +1 -1
  152. package/dist/runtime/appGateDefinitions.js +1 -1
  153. package/dist/server/index.d.ts +1 -0
  154. package/dist/server/index.js +46 -3
  155. package/dist/server/index.test.js +12 -1
  156. package/dist/server/routes/admin.d.ts +1 -5
  157. package/dist/server/routes/admin.js +151 -80
  158. package/dist/server/routes/annotatedAttachments.d.ts +1 -1
  159. package/dist/server/routes/annotatedAttachments.js +1 -1
  160. package/dist/server/routes/auth.d.ts +1 -4
  161. package/dist/server/routes/auth.js +59 -64
  162. package/dist/server/routes/authSupport.d.ts +30 -0
  163. package/dist/server/routes/authSupport.js +81 -0
  164. package/dist/server/routes/billing.d.ts +1 -1
  165. package/dist/server/routes/billing.js +122 -255
  166. package/dist/server/routes/billing.test.js +257 -86
  167. package/dist/server/routes/documentReviews.d.ts +1 -1
  168. package/dist/server/routes/documentReviews.js +1 -1
  169. package/dist/server/routes/documents.d.ts +4 -2
  170. package/dist/server/routes/documents.js +73 -7
  171. package/dist/server/routes/primitives.d.ts +11 -0
  172. package/dist/server/routes/primitives.js +73 -0
  173. package/dist/server/routes/resources.d.ts +1 -1
  174. package/dist/server/routes/resources.js +1 -1
  175. package/dist/server/routes/shared.d.ts +31 -1
  176. package/dist/server/routes/shared.js +26 -0
  177. package/dist/server/routes/sync.d.ts +1 -1
  178. package/dist/server/routes/sync.integration.test.js +20 -0
  179. package/dist/server/routes/sync.js +111 -238
  180. package/dist/server/routes/tasks.d.ts +1 -1
  181. package/dist/server/routes/tasks.js +50 -8
  182. package/dist/server/routes/workspaces.d.ts +1 -1
  183. package/dist/server/routes/workspaces.js +1 -1
  184. package/dist/server/routes.d.ts +2 -9
  185. package/dist/server/routes.js +84 -181
  186. package/dist/server/routes.test.js +912 -32
  187. package/dist/shared/taskActor.d.ts +10 -0
  188. package/dist/shared/taskActor.js +1 -0
  189. package/dist/sync/collaborationSyncPayload.js +4 -0
  190. package/dist/sync/collaborationSyncPayload.test.js +8 -0
  191. package/dist/sync/collaborationSyncState.d.ts +3 -1
  192. package/dist/sync/collaborationSyncState.js +19 -0
  193. package/dist/sync/contentSyncState.js +28 -17
  194. package/dist/sync/syncApplyHandlers.d.ts +87 -1
  195. package/dist/sync/syncApplyHandlers.js +370 -8
  196. package/dist/sync/syncApplyHandlers.test.d.ts +1 -0
  197. package/dist/sync/syncApplyHandlers.test.js +379 -0
  198. package/dist/sync/syncService.d.ts +9 -1
  199. package/dist/sync/syncService.js +44 -2
  200. package/dist/sync/syncService.test.js +62 -0
  201. package/dist/sync/workspacePullFeed.d.ts +1 -0
  202. package/dist/sync/workspacePullFeed.js +66 -59
  203. package/dist/sync/workspacePullFeed.test.js +72 -4
  204. package/dist/sync/workspaceSyncModel.d.ts +25 -1
  205. package/dist/sync/workspaceSyncModel.js +77 -3
  206. package/dist/sync/workspaceSyncModel.test.js +153 -0
  207. package/dist/sync/workspaceSyncState.d.ts +2 -0
  208. package/dist/sync/workspaceSyncState.js +1 -0
  209. package/dist/types.d.ts +2 -10
  210. package/dist/ui/assets/AgentsModule-N2MnQBZk.js +1 -0
  211. package/dist/ui/assets/{AnnotatedAttachmentWorkspace-C_TmXZwA.js → AnnotatedAttachmentWorkspace-BG6P_GVW.js} +1 -1
  212. package/dist/ui/assets/DocumentWorkspace-B3nV_Gc5.css +1 -0
  213. package/dist/ui/assets/DocumentWorkspace-DRbDMwh8.js +252 -0
  214. package/dist/ui/assets/{InitiativesModule-4-Rh2K2n.js → InitiativesModule-Dhm7M8e7.js} +1 -1
  215. package/dist/ui/assets/{PlansPage-BlVC_lRq.css → PlansPage-C2dd2n1X.css} +1 -1
  216. package/dist/ui/assets/PlansPage-Cq0zXj3I.js +1 -0
  217. package/dist/ui/assets/TaskSettings-ln0aF7xc.js +9 -0
  218. package/dist/ui/assets/{WorkflowsModule-CGk9s3NJ.js → WorkflowsModule-BcS4afRn.js} +1 -1
  219. package/dist/ui/assets/index-C2-OXZV7.css +1 -0
  220. package/dist/ui/assets/index-DcSI5F86.js +6 -0
  221. package/dist/ui/assets/{vendor-icons-pWocEipT.js → vendor-icons-BSUaRwF8.js} +1 -1
  222. package/dist/ui/index.html +4 -4
  223. package/dist/utils/commercialLifecyclePresentation.d.ts +19 -0
  224. package/dist/utils/commercialLifecyclePresentation.js +196 -0
  225. package/dist/utils/taskActivity.js +4 -0
  226. package/dist/utils/taskActivity.test.js +25 -1
  227. package/package.json +10 -1
  228. package/scripts/check-cloud-mcp.mjs +83 -0
  229. package/scripts/playwright-auth.sh +9 -1
  230. package/scripts/run-billing-performance-smoke.sh +24 -0
  231. package/dist/ui/assets/AgentsModule-CpsTmrIW.js +0 -1
  232. package/dist/ui/assets/DocumentWorkspace-C3GyzrWm.js +0 -250
  233. package/dist/ui/assets/DocumentWorkspace-C_8T8oz-.css +0 -1
  234. package/dist/ui/assets/PlansPage-BP7AYOqr.js +0 -1
  235. package/dist/ui/assets/TaskSettings-BOC5F6Ag.js +0 -8
  236. package/dist/ui/assets/index-CLIMgR6g.js +0 -6
  237. package/dist/ui/assets/index-DneETxcu.css +0 -1
@@ -0,0 +1,10 @@
1
+ export interface TaskActor {
2
+ id: string;
3
+ kind: 'human' | 'ai';
4
+ label: string;
5
+ username: string;
6
+ icon: string;
7
+ color: string;
8
+ isNamed: boolean;
9
+ meta?: Record<string, unknown>;
10
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -39,6 +39,10 @@ export function normalizeAiProfileSyncPayload(raw, workspaceId, normalizeSurface
39
39
  username: String(profile.username || '').trim(),
40
40
  icon: String(profile.icon || 'Bot').trim() || 'Bot',
41
41
  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),
42
46
  surfaceType: normalizeSurfaceType(profile.surfaceType, { source, profileId, workspaceId: profileWorkspaceId }),
43
47
  providerMetadata: profile.providerMetadata && typeof profile.providerMetadata === 'object' && !Array.isArray(profile.providerMetadata)
44
48
  ? profile.providerMetadata
@@ -15,6 +15,10 @@ describe('collaborationSyncPayload', () => {
15
15
  username: ' agent ',
16
16
  icon: ' Bot ',
17
17
  color: ' #111111 ',
18
+ description: ' Product coding agent ',
19
+ role: ' Implementer ',
20
+ provider: ' OpenAI ',
21
+ model: ' gpt-5.4 ',
18
22
  surfaceType: 'agent',
19
23
  providerMetadata: { foo: 'bar' },
20
24
  createdAt: '2026-04-10T10:00:00.000Z',
@@ -29,6 +33,10 @@ describe('collaborationSyncPayload', () => {
29
33
  username: 'agent',
30
34
  icon: 'Bot',
31
35
  color: '#111111',
36
+ description: 'Product coding agent',
37
+ role: 'Implementer',
38
+ provider: 'OpenAI',
39
+ model: 'gpt-5.4',
32
40
  surfaceType: 'agent',
33
41
  providerMetadata: { foo: 'bar' },
34
42
  createdAt: '2026-04-10T10:00:00.000Z',
@@ -1,5 +1,5 @@
1
1
  import type { TaskforceCore, TaskforceSyncCapable } from '../core/Taskforce.js';
2
- import type { WorkspaceSyncAnnotatedAttachmentSessionSnapshot, WorkspaceSyncDocumentReviewCommentSnapshot, WorkspaceSyncDocumentReviewSessionSnapshot } from './workspaceSyncModel.js';
2
+ import type { WorkspaceSyncAnnotatedAttachmentSessionSnapshot, WorkspaceSyncDocumentReviewCommentSnapshot, WorkspaceSyncDocumentReviewSessionSnapshot, WorkspaceSyncTaskEventSnapshot } from './workspaceSyncModel.js';
3
3
  type SyncCore = TaskforceCore & TaskforceSyncCapable;
4
4
  interface CollaborationSyncStateDeps {
5
5
  core: SyncCore;
@@ -7,9 +7,11 @@ interface CollaborationSyncStateDeps {
7
7
  export declare function listWorkspaceSyncDocumentReviewSessionsSnapshot(deps: CollaborationSyncStateDeps, workspaceId?: string): WorkspaceSyncDocumentReviewSessionSnapshot[];
8
8
  export declare function listWorkspaceSyncDocumentReviewCommentsSnapshot(deps: CollaborationSyncStateDeps, workspaceId?: string): WorkspaceSyncDocumentReviewCommentSnapshot[];
9
9
  export declare function listWorkspaceSyncAnnotatedAttachmentSessionsSnapshot(deps: CollaborationSyncStateDeps, workspaceId?: string): WorkspaceSyncAnnotatedAttachmentSessionSnapshot[];
10
+ export declare function listWorkspaceSyncTaskEventsSnapshot(deps: CollaborationSyncStateDeps, workspaceId?: string): WorkspaceSyncTaskEventSnapshot[];
10
11
  export declare function createCollaborationSyncState(deps: CollaborationSyncStateDeps): {
11
12
  listWorkspaceSyncDocumentReviewSessionsSnapshot: (workspaceId?: string) => WorkspaceSyncDocumentReviewSessionSnapshot[];
12
13
  listWorkspaceSyncDocumentReviewCommentsSnapshot: (workspaceId?: string) => WorkspaceSyncDocumentReviewCommentSnapshot[];
13
14
  listWorkspaceSyncAnnotatedAttachmentSessionsSnapshot: (workspaceId?: string) => WorkspaceSyncAnnotatedAttachmentSessionSnapshot[];
15
+ listWorkspaceSyncTaskEventsSnapshot: (workspaceId?: string) => WorkspaceSyncTaskEventSnapshot[];
14
16
  };
15
17
  export {};
@@ -51,10 +51,29 @@ export function listWorkspaceSyncAnnotatedAttachmentSessionsSnapshot(deps, works
51
51
  && session.workspaceId.length > 0
52
52
  && session.baseImageAssetId.length > 0));
53
53
  }
54
+ export function listWorkspaceSyncTaskEventsSnapshot(deps, workspaceId = 'default') {
55
+ return deps.core.listTaskEventsForSync({ workspaceId })
56
+ .map((event) => ({
57
+ id: event.id,
58
+ taskId: event.taskId,
59
+ workspaceId: event.workspaceId,
60
+ action: event.action,
61
+ actor: event.actor,
62
+ actorType: event.actorType,
63
+ details: event.details,
64
+ createdAt: event.createdAt,
65
+ }))
66
+ .filter((event) => (event.id.length > 0
67
+ && event.taskId.length > 0
68
+ && event.workspaceId.length > 0
69
+ && event.action.length > 0
70
+ && event.createdAt.length > 0));
71
+ }
54
72
  export function createCollaborationSyncState(deps) {
55
73
  return {
56
74
  listWorkspaceSyncDocumentReviewSessionsSnapshot: (workspaceId = 'default') => listWorkspaceSyncDocumentReviewSessionsSnapshot(deps, workspaceId),
57
75
  listWorkspaceSyncDocumentReviewCommentsSnapshot: (workspaceId = 'default') => listWorkspaceSyncDocumentReviewCommentsSnapshot(deps, workspaceId),
58
76
  listWorkspaceSyncAnnotatedAttachmentSessionsSnapshot: (workspaceId = 'default') => listWorkspaceSyncAnnotatedAttachmentSessionsSnapshot(deps, workspaceId),
77
+ listWorkspaceSyncTaskEventsSnapshot: (workspaceId = 'default') => listWorkspaceSyncTaskEventsSnapshot(deps, workspaceId),
59
78
  };
60
79
  }
@@ -80,8 +80,7 @@ export function hasDocumentSyncMetadataDrift(deps, workspaceId, doc, options) {
80
80
  incomingReferenceNumber: normalizedIncomingReference
81
81
  });
82
82
  }
83
- return referenceNumberMismatch
84
- || (allowReferenceNumberReassignment && existingAsset.referenceNumber !== normalizedIncomingReference)
83
+ return (allowReferenceNumberReassignment && existingAsset.referenceNumber !== normalizedIncomingReference)
85
84
  || existingAsset.version !== normalizedIncomingVersion
86
85
  || (existingAsset.documentId || null) !== normalizedIncomingDocumentId
87
86
  || (existingAsset.logicalName || null) !== normalizedIncomingLogicalName
@@ -130,8 +129,7 @@ export function hasBinaryAssetSyncMetadataDrift(deps, workspaceId, asset, option
130
129
  incomingReferenceNumber: normalizedIncomingReference
131
130
  });
132
131
  }
133
- return referenceNumberMismatch
134
- || (allowReferenceNumberReassignment && existingAsset.referenceNumber !== normalizedIncomingReference)
132
+ return (allowReferenceNumberReassignment && existingAsset.referenceNumber !== normalizedIncomingReference)
135
133
  || (existingAsset.logicalName || null) !== normalizedIncomingLogicalName
136
134
  || (existingAsset.originalFilename || null) !== normalizedIncomingFilename
137
135
  || (primaryLink?.taskId || null) !== normalizedIncomingTaskId
@@ -535,15 +533,25 @@ export async function loadWorkspaceSyncDocumentPayload(deps, basePath, workspace
535
533
  const absolutePath = path.resolve(path.join(root, normalizedPath));
536
534
  if (absolutePath !== root && !absolutePath.startsWith(`${root}${path.sep}`))
537
535
  return null;
536
+ const objectStorageClient = deps.getObjectStorageClient();
537
+ const canonicalAsset = deps.workspaceAssetStore?.getByStorageKey(normalizedPath, workspaceId);
538
538
  let content = '';
539
539
  let stat = null;
540
540
  try {
541
- if (!fs.existsSync(absolutePath))
542
- return null;
543
- stat = fs.statSync(absolutePath);
544
- if (!stat.isFile())
545
- return null;
546
- content = fs.readFileSync(absolutePath, 'utf8');
541
+ if (canonicalAsset?.kind === 'document' && canonicalAsset.storageProvider === 'r2' && objectStorageClient) {
542
+ const object = await objectStorageClient.getObject(normalizedPath);
543
+ if (!object?.body)
544
+ return null;
545
+ content = object.body.toString('utf8');
546
+ }
547
+ else {
548
+ if (!fs.existsSync(absolutePath))
549
+ return null;
550
+ stat = fs.statSync(absolutePath);
551
+ if (!stat.isFile())
552
+ return null;
553
+ content = fs.readFileSync(absolutePath, 'utf8');
554
+ }
547
555
  }
548
556
  catch (error) {
549
557
  deps.recordSyncDiagnostic(workspaceId, 'pull', 'Failed to load targeted sync document payload.', {
@@ -560,7 +568,6 @@ export async function loadWorkspaceSyncDocumentPayload(deps, basePath, workspace
560
568
  return next;
561
569
  })();
562
570
  const cached = workspaceCache.get(normalizedPath);
563
- const canonicalAsset = deps.workspaceAssetStore?.getByStorageKey(normalizedPath, workspaceId);
564
571
  let updatedAt = '';
565
572
  if (canonicalAsset?.kind === 'document') {
566
573
  updatedAt = resolveCanonicalAssetSyncLinkState(deps, canonicalAsset, workspaceId).effectiveUpdatedAt;
@@ -733,8 +740,10 @@ export async function writeWorkspaceSyncDocument(deps, basePath, doc, workspaceI
733
740
  const incomingReferenceNumber = Number.isFinite(Number(doc.referenceNumber))
734
741
  ? Math.max(1, Math.floor(Number(doc.referenceNumber)))
735
742
  : null;
736
- const allowReferenceNumberReassignment = options?.allowReferenceNumberReassignment === true
737
- || Boolean(existing?.referenceNumber && incomingReferenceNumber && existing.referenceNumber !== incomingReferenceNumber);
743
+ const allowReferenceNumberReassignment = options?.allowReferenceNumberReassignment === true;
744
+ const nextReferenceNumber = allowReferenceNumberReassignment
745
+ ? (incomingReferenceNumber ?? existing?.referenceNumber ?? null)
746
+ : (existing?.referenceNumber ?? incomingReferenceNumber ?? null);
738
747
  const originalFilename = String(doc.originalFilename || existing?.originalFilename || path.basename(normalizedPath) || 'document.md').trim() || 'document.md';
739
748
  const asset = deps.workspaceAssetStore.upsertAsset({
740
749
  assetId: String(doc.assetId || existing?.assetId || `asset-${randomUUID().replace(/-/g, '')}`),
@@ -750,7 +759,7 @@ export async function writeWorkspaceSyncDocument(deps, basePath, doc, workspaceI
750
759
  contentSha256: contentHash,
751
760
  sizeBytes: Buffer.byteLength(content, 'utf8'),
752
761
  documentId: String(doc.documentId || existing?.documentId || `doc-${randomUUID().replace(/-/g, '')}`),
753
- referenceNumber: incomingReferenceNumber ?? existing?.referenceNumber ?? null,
762
+ referenceNumber: nextReferenceNumber,
754
763
  version: Number.isFinite(Number(doc.version))
755
764
  ? Math.max(1, Math.floor(Number(doc.version)))
756
765
  : Math.max(1, Number(existing?.version || 0) + 1),
@@ -826,8 +835,10 @@ export async function writeWorkspaceSyncBinaryAsset(deps, basePath, asset, works
826
835
  const incomingReferenceNumber = Number.isFinite(Number(asset.referenceNumber))
827
836
  ? Math.max(1, Math.floor(Number(asset.referenceNumber)))
828
837
  : null;
829
- const allowReferenceNumberReassignment = options?.allowReferenceNumberReassignment === true
830
- || Boolean(existing?.referenceNumber && incomingReferenceNumber && existing.referenceNumber !== incomingReferenceNumber);
838
+ const allowReferenceNumberReassignment = options?.allowReferenceNumberReassignment === true;
839
+ const nextReferenceNumber = allowReferenceNumberReassignment
840
+ ? (incomingReferenceNumber ?? existing?.referenceNumber ?? null)
841
+ : (existing?.referenceNumber ?? incomingReferenceNumber ?? null);
831
842
  const assetRecord = deps.workspaceAssetStore.upsertAsset({
832
843
  assetId: String(asset.assetId || existing?.assetId || `asset-${randomUUID().replace(/-/g, '')}`),
833
844
  workspaceId,
@@ -842,7 +853,7 @@ export async function writeWorkspaceSyncBinaryAsset(deps, basePath, asset, works
842
853
  contentSha256: createHash('sha256').update(buffer).digest('hex'),
843
854
  sizeBytes: buffer.length,
844
855
  documentId: null,
845
- referenceNumber: incomingReferenceNumber ?? existing?.referenceNumber ?? null,
856
+ referenceNumber: nextReferenceNumber,
846
857
  version: null,
847
858
  isLatest: true,
848
859
  scanStatus: existing?.scanStatus || 'clean',
@@ -1,6 +1,7 @@
1
1
  import type { TaskforceCore, TaskforceSyncCapable } from '../core/Taskforce.js';
2
- import type { WorkspaceSyncAiProfileSnapshot, WorkspaceSyncAnnotatedAttachmentSessionSnapshot, WorkspaceSyncDocumentReviewCommentSnapshot, WorkspaceSyncDocumentReviewSessionSnapshot, WorkspaceSyncInitiativeSnapshot, WorkspaceSyncWorkspaceMemberSnapshot, WorkspaceSyncWorkstreamSnapshot } from './workspaceSyncModel.js';
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
+ import type { AiProfileSurfaceType } from '../shared/aiProfileSurfaceType.js';
4
5
  type SyncCore = TaskforceCore & TaskforceSyncCapable;
5
6
  type SyncRouteError = Error & {
6
7
  code?: string;
@@ -12,7 +13,81 @@ type CreateSyncRouteError = (message: string, details: Record<string, unknown>,
12
13
  code?: string;
13
14
  statusCode?: number;
14
15
  }) => SyncRouteError;
16
+ type NormalizeIncomingAiProfileSurfaceType = (value: unknown, context: {
17
+ source: string;
18
+ profileId?: string;
19
+ workspaceId?: string;
20
+ }) => AiProfileSurfaceType | null;
21
+ type NormalizeTaskEventSyncPayload = (raw: unknown, workspaceId: string, sourceWatermark?: string) => WorkspaceSyncTaskEventSnapshot | null;
22
+ export interface WorkspaceSyncIncomingTaskMutation {
23
+ archived: boolean;
24
+ task: WorkspaceSyncTaskSnapshot;
25
+ }
26
+ export interface WorkspaceSyncIncomingTaskApplyModel {
27
+ upserts: WorkspaceSyncIncomingTaskMutation[];
28
+ deletes: Map<string, string>;
29
+ }
30
+ export interface WorkspaceSyncIncomingApplyModel {
31
+ taskMutations: WorkspaceSyncIncomingTaskApplyModel;
32
+ planning: {
33
+ incomingTaxonomies: unknown[] | null;
34
+ incomingTaxonomyState: Record<string, unknown> | null;
35
+ incomingTaxonomiesUpdatedAt: string;
36
+ incomingInitiatives: Map<string, WorkspaceSyncInitiativeSnapshot>;
37
+ incomingWorkstreams: Map<string, WorkspaceSyncWorkstreamSnapshot>;
38
+ };
39
+ profiles: {
40
+ incomingAiProfiles: Map<string, WorkspaceSyncAiProfileSnapshot>;
41
+ };
42
+ content: {
43
+ incomingDocuments: DocumentSyncPayload[];
44
+ incomingDocumentDeletes: Map<string, string>;
45
+ incomingAssets: BinaryAssetSyncPayload[];
46
+ incomingAssetDeletes: Map<string, string>;
47
+ };
48
+ collaboration: {
49
+ incomingDocumentReviewSessions: Map<string, WorkspaceSyncDocumentReviewSessionSnapshot>;
50
+ incomingDocumentReviewSessionDeletes: Map<string, string>;
51
+ incomingDocumentReviewComments: Map<string, WorkspaceSyncDocumentReviewCommentSnapshot>;
52
+ incomingDocumentReviewCommentDeletes: Map<string, string>;
53
+ incomingAnnotatedAttachmentSessions: Map<string, WorkspaceSyncAnnotatedAttachmentSessionSnapshot>;
54
+ incomingAnnotatedAttachmentSessionDeletes: Map<string, string>;
55
+ };
56
+ taskActivity: {
57
+ incomingTaskEvents: Map<string, WorkspaceSyncTaskEventSnapshot>;
58
+ };
59
+ }
60
+ export interface PreparedWorkspaceTaskSyncSnapshot {
61
+ tasks: WorkspaceSyncTaskSnapshot[];
62
+ archived: WorkspaceSyncTaskSnapshot[];
63
+ }
15
64
  export declare function resolveSyncConflictOrdering(incomingWatermark: string, existingWatermark: string, incomingTieBreak: string, existingTieBreak: string): number;
65
+ export declare function classifyWorkspaceSyncChanges(input: {
66
+ workspaceId: string;
67
+ incomingChanges: WorkspaceSyncChange[];
68
+ normalizeWorkspaceSyncDocumentPath: (rawPath: unknown) => string | null;
69
+ normalizeTaskAssetPath: (rawPath: unknown) => string | null;
70
+ normalizeIncomingAiProfileSurfaceType: NormalizeIncomingAiProfileSurfaceType;
71
+ normalizeTaskEventSyncPayload: NormalizeTaskEventSyncPayload;
72
+ recordSyncDiagnostic: RecordSyncDiagnostic;
73
+ }): WorkspaceSyncIncomingApplyModel;
74
+ export declare function prepareTaskSyncSnapshotApply(input: {
75
+ core: SyncCore;
76
+ workspaceId: string;
77
+ taskMutations: WorkspaceSyncIncomingTaskApplyModel;
78
+ recordSyncDiagnostic: RecordSyncDiagnostic;
79
+ }): PreparedWorkspaceTaskSyncSnapshot;
80
+ export declare function applyTaskSyncDeletes(input: {
81
+ core: SyncCore;
82
+ workspaceId: string;
83
+ taskMutations: WorkspaceSyncIncomingTaskApplyModel;
84
+ recordSyncDiagnostic: RecordSyncDiagnostic;
85
+ }): number;
86
+ export declare function applyPreparedTaskSyncSnapshot(input: {
87
+ core: SyncCore;
88
+ workspaceId: string;
89
+ prepared: PreparedWorkspaceTaskSyncSnapshot;
90
+ }): ReturnType<SyncCore['applyWorkspaceSyncSnapshot']>;
16
91
  export declare function applyPlanningSyncChanges(input: {
17
92
  core: SyncCore;
18
93
  workspaceId: string;
@@ -51,6 +126,10 @@ export declare function applyContentSyncChanges(input: {
51
126
  hasBinaryAssetSyncMetadataDrift: (workspaceId: string, asset: BinaryAssetSyncPayload, options?: {
52
127
  allowReferenceNumberReassignment?: boolean;
53
128
  }) => boolean;
129
+ getExistingDocument?: (docPath: string, workspaceId: string) => {
130
+ updatedAt?: string | null;
131
+ contentHash?: string | null;
132
+ } | null;
54
133
  writeWorkspaceSyncDocument: (basePath: string, doc: DocumentSyncPayload, workspaceId?: string, options?: {
55
134
  allowReferenceNumberReassignment?: boolean;
56
135
  }) => Promise<void>;
@@ -80,4 +159,11 @@ export declare function applyCollaborationSyncChanges(input: {
80
159
  recordSyncDiagnostic: RecordSyncDiagnostic;
81
160
  createSyncRouteError: CreateSyncRouteError;
82
161
  }): void;
162
+ export declare function applyTaskActivitySyncChanges(input: {
163
+ core: SyncCore;
164
+ workspaceId: string;
165
+ incomingTaskEvents: Map<string, WorkspaceSyncTaskEventSnapshot>;
166
+ recordSyncDiagnostic: RecordSyncDiagnostic;
167
+ createSyncRouteError: CreateSyncRouteError;
168
+ }): void;
83
169
  export {};