@taskforcehq/taskforce 0.3.302 → 0.3.304

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 (192) hide show
  1. package/dist/Taskforce.module.css +113 -5
  2. package/dist/TaskforceCore.js +560 -208
  3. package/dist/TaskforceCore.test.js +1833 -91
  4. package/dist/annotatedAttachments/service.d.ts +1 -1
  5. package/dist/annotatedAttachments/types.d.ts +1 -1
  6. package/dist/components/features/AgentsModule.js +1 -1
  7. package/dist/components/features/AgentsModule.test.js +1 -1
  8. package/dist/components/features/TaskSettings.js +58 -38
  9. package/dist/components/features/TaskSettings.test.js +139 -40
  10. package/dist/components/task/TaskActionHeader.d.ts +2 -1
  11. package/dist/components/task/TaskActionHeader.js +3 -3
  12. package/dist/components/task/TaskActionHeader.test.js +8 -0
  13. package/dist/components/task/TaskCard.js +16 -1
  14. package/dist/components/task/TaskCard.test.js +31 -0
  15. package/dist/components/task/TaskForm.d.ts +2 -1
  16. package/dist/components/task/TaskForm.js +22 -4
  17. package/dist/components/task/TaskForm.test.js +46 -0
  18. package/dist/components/task/TaskKanban.d.ts +1 -1
  19. package/dist/components/task/TaskKanban.js +31 -160
  20. package/dist/components/task/TaskKanban.test.js +17 -0
  21. package/dist/components/task/TaskStatusActions.d.ts +6 -1
  22. package/dist/components/task/TaskStatusActions.js +8 -3
  23. package/dist/components/task/TaskStatusActions.test.js +9 -0
  24. package/dist/components/task/taskKanbanDropRules.d.ts +58 -0
  25. package/dist/components/task/taskKanbanDropRules.js +187 -0
  26. package/dist/components/task/taskKanbanDropRules.test.d.ts +1 -0
  27. package/dist/components/task/taskKanbanDropRules.test.js +114 -0
  28. package/dist/components/ui/Modal.d.ts +1 -1
  29. package/dist/components/ui/Modal.js +1 -0
  30. package/dist/components/views/AppShellHeader.js +5 -1
  31. package/dist/components/views/AppShellHeader.test.js +4 -0
  32. package/dist/components/views/PlanComparisonPage.d.ts +3 -2
  33. package/dist/components/views/PlanComparisonPage.js +4 -2
  34. package/dist/components/views/PlanComparisonPage.test.js +4 -0
  35. package/dist/components/views/PlansPage.d.ts +7 -1
  36. package/dist/components/views/PlansPage.js +139 -53
  37. package/dist/components/views/PlansPage.test.d.ts +1 -0
  38. package/dist/components/views/PlansPage.test.js +157 -0
  39. package/dist/components/views/StandaloneLayout.d.ts +1 -0
  40. package/dist/components/views/StandaloneLayout.js +216 -186
  41. package/dist/components/views/WidgetView.js +11 -2
  42. package/dist/components/views/standalone/modals/AccountHubModal.d.ts +8 -3
  43. package/dist/components/views/standalone/modals/AccountHubModal.js +16 -2
  44. package/dist/components/views/standalone/modals/AccountHubModal.test.d.ts +1 -0
  45. package/dist/components/views/standalone/modals/AccountHubModal.test.js +26 -0
  46. package/dist/components/views/standalone/modals/SyncStatusModal.js +1 -1
  47. package/dist/core/DeletedTaskLifecycleService.d.ts +2 -1
  48. package/dist/core/EntitlementsPolicy.test.js +2 -2
  49. package/dist/core/GlobalSettingsService.js +78 -18
  50. package/dist/core/PlanEntitlementService.d.ts +31 -5
  51. package/dist/core/PlanEntitlementService.js +350 -222
  52. package/dist/core/SignupMonetizationSettings.test.js +208 -49
  53. package/dist/core/SystemAdmin.test.js +186 -96
  54. package/dist/core/TaskActivityService.d.ts +4 -1
  55. package/dist/core/TaskActivityService.js +45 -0
  56. package/dist/core/TaskAuditTimeline.test.js +52 -1
  57. package/dist/core/Taskforce.d.ts +65 -20
  58. package/dist/core/Taskforce.js +261 -51
  59. package/dist/core/Taskforce.mcpAuth.test.js +0 -2
  60. package/dist/core/UserProfileAvatarDrafts.test.js +12 -3
  61. package/dist/core/WorkspacePlanMode.test.js +65 -0
  62. package/dist/core/types.d.ts +11 -12
  63. package/dist/documentReviews/service.d.ts +1 -1
  64. package/dist/documentReviews/types.d.ts +1 -1
  65. package/dist/hooks/auth/useTaskforceAuthBootstrap.d.ts +48 -0
  66. package/dist/hooks/auth/useTaskforceAuthBootstrap.js +219 -0
  67. package/dist/hooks/sync/auth.d.ts +37 -0
  68. package/dist/hooks/sync/auth.js +61 -0
  69. package/dist/hooks/sync/bootstrap.d.ts +34 -0
  70. package/dist/hooks/sync/bootstrap.js +52 -0
  71. package/dist/hooks/sync/orchestratorShared.d.ts +36 -0
  72. package/dist/hooks/sync/orchestratorShared.js +209 -0
  73. package/dist/hooks/sync/orchestratorShared.test.d.ts +1 -0
  74. package/dist/hooks/sync/orchestratorShared.test.js +49 -0
  75. package/dist/hooks/sync/realtime.d.ts +25 -0
  76. package/dist/hooks/sync/realtime.js +60 -0
  77. package/dist/hooks/sync/recovery.d.ts +69 -0
  78. package/dist/hooks/sync/recovery.js +118 -0
  79. package/dist/hooks/sync/transfers.d.ts +122 -0
  80. package/dist/hooks/sync/transfers.js +431 -0
  81. package/dist/hooks/sync/useDataVersionRefresh.d.ts +16 -0
  82. package/dist/hooks/sync/useDataVersionRefresh.js +73 -0
  83. package/dist/hooks/ui/useResourceExport.d.ts +3 -1
  84. package/dist/hooks/ui/useResourceExport.js +5 -2
  85. package/dist/hooks/ui/useWorkflowTemplates.js +11 -6
  86. package/dist/hooks/useRealtimeSync.js +2 -1
  87. package/dist/hooks/useSyncOrchestrator.aiProfiles.test.js +8 -0
  88. package/dist/hooks/useSyncOrchestrator.context-assets.test.d.ts +1 -0
  89. package/dist/hooks/useSyncOrchestrator.context-assets.test.js +228 -0
  90. package/dist/hooks/useSyncOrchestrator.d.ts +5 -4
  91. package/dist/hooks/useSyncOrchestrator.js +315 -860
  92. package/dist/hooks/useSyncOrchestrator.retry-closure.test.js +665 -8
  93. package/dist/hooks/useTaskMutations.js +45 -6
  94. package/dist/hooks/useTaskMutations.test.js +147 -0
  95. package/dist/hooks/useTaskforce.d.ts +11 -2
  96. package/dist/hooks/useTaskforce.js +290 -812
  97. package/dist/hooks/useWorkspaceSyncController.d.ts +1 -0
  98. package/dist/hooks/useWorkspaceSyncController.js +22 -10
  99. package/dist/hooks/workspace/useTaskforceApiRouting.test.js +17 -0
  100. package/dist/hooks/workspace/useTaskforceWorkspaceBootstrap.d.ts +166 -0
  101. package/dist/hooks/workspace/useTaskforceWorkspaceBootstrap.js +434 -0
  102. package/dist/hooks/workspace/workspaceLocalState.d.ts +19 -0
  103. package/dist/hooks/workspace/workspaceLocalState.js +100 -0
  104. package/dist/hooks/workspace/workspaceLocalState.test.d.ts +1 -0
  105. package/dist/hooks/workspace/workspaceLocalState.test.js +59 -0
  106. package/dist/localization/locales/en-US.js +2 -2
  107. package/dist/mcp/canonicalAssetHelpers.d.ts +70 -0
  108. package/dist/mcp/canonicalAssetHelpers.js +259 -0
  109. package/dist/mcp/clientIntegrations.d.ts +12 -1
  110. package/dist/mcp/clientIntegrations.js +161 -6
  111. package/dist/mcp/clientIntegrations.test.js +76 -4
  112. package/dist/mcp/documentHelpers.d.ts +100 -0
  113. package/dist/mcp/documentHelpers.js +161 -0
  114. package/dist/mcp/runtime.js +264 -505
  115. package/dist/mcp/runtime.test.js +353 -89
  116. package/dist/mcp/taskAttachmentHelpers.d.ts +41 -0
  117. package/dist/mcp/taskAttachmentHelpers.js +60 -0
  118. package/dist/mcp/taskAttachmentTypes.d.ts +37 -0
  119. package/dist/mcp/taskAttachmentTypes.js +1 -0
  120. package/dist/migrations/billingSchemaParity.test.js +3 -0
  121. package/dist/migrations/taskSchemaMigrations.js +15 -0
  122. package/dist/plugins/vite.js +1 -1
  123. package/dist/runtime/appGateDefinitions.d.ts +1 -1
  124. package/dist/runtime/appGateDefinitions.js +1 -1
  125. package/dist/server/index.cookieProxy.test.js +1 -0
  126. package/dist/server/index.d.ts +1 -0
  127. package/dist/server/index.js +48 -3
  128. package/dist/server/index.test.js +14 -2
  129. package/dist/server/mockStripe.d.ts +1 -0
  130. package/dist/server/mockStripe.js +2 -0
  131. package/dist/server/routes/admin.js +91 -40
  132. package/dist/server/routes/auth.d.ts +1 -0
  133. package/dist/server/routes/auth.js +231 -55
  134. package/dist/server/routes/billing.js +473 -39
  135. package/dist/server/routes/billing.test.js +972 -37
  136. package/dist/server/routes/shared.d.ts +30 -0
  137. package/dist/server/routes/shared.js +31 -3
  138. package/dist/server/routes/sync.integration.test.js +180 -0
  139. package/dist/server/routes/sync.js +125 -242
  140. package/dist/server/routes/tasks.js +49 -7
  141. package/dist/server/routes.js +11 -22
  142. package/dist/server/routes.test.js +530 -81
  143. package/dist/shared/taskActor.d.ts +10 -0
  144. package/dist/shared/taskActor.js +1 -0
  145. package/dist/sync/cloudSyncApi.d.ts +1 -0
  146. package/dist/sync/collaborationSyncPayload.js +4 -0
  147. package/dist/sync/collaborationSyncPayload.test.js +8 -0
  148. package/dist/sync/collaborationSyncState.d.ts +3 -1
  149. package/dist/sync/collaborationSyncState.js +19 -0
  150. package/dist/sync/contentSyncState.d.ts +10 -0
  151. package/dist/sync/contentSyncState.js +277 -14
  152. package/dist/sync/syncApplyHandlers.d.ts +87 -1
  153. package/dist/sync/syncApplyHandlers.js +370 -8
  154. package/dist/sync/syncApplyHandlers.test.d.ts +1 -0
  155. package/dist/sync/syncApplyHandlers.test.js +377 -0
  156. package/dist/sync/syncService.d.ts +9 -1
  157. package/dist/sync/syncService.js +57 -10
  158. package/dist/sync/syncService.test.js +48 -0
  159. package/dist/sync/workspacePullFeed.d.ts +11 -0
  160. package/dist/sync/workspacePullFeed.js +123 -68
  161. package/dist/sync/workspacePullFeed.test.js +180 -0
  162. package/dist/sync/workspaceSyncModel.d.ts +22 -1
  163. package/dist/sync/workspaceSyncModel.js +65 -0
  164. package/dist/sync/workspaceSyncModel.test.js +119 -0
  165. package/dist/types.d.ts +2 -10
  166. package/dist/ui/assets/AgentsModule-BLWVbuKP.js +1 -0
  167. package/dist/ui/assets/{AnnotatedAttachmentWorkspace-Dvi02Y7q.js → AnnotatedAttachmentWorkspace-BlS-cqnl.js} +1 -1
  168. package/dist/ui/assets/{DocumentWorkspace-iys3zfca.js → DocumentWorkspace-BH_6DF6x.js} +1 -1
  169. package/dist/ui/assets/{InitiativesModule-DJvLJI3A.js → InitiativesModule-BjR6iBf9.js} +1 -1
  170. package/dist/ui/assets/{PlansPage-BlVC_lRq.css → PlansPage-C2dd2n1X.css} +1 -1
  171. package/dist/ui/assets/PlansPage-CSDQ4sLa.js +1 -0
  172. package/dist/ui/assets/TaskSettings-CEDy34Jo.js +9 -0
  173. package/dist/ui/assets/{WorkflowsModule-BguHeQaV.js → WorkflowsModule-DnFqdUME.js} +1 -1
  174. package/dist/ui/assets/index-DXUdtH1B.js +6 -0
  175. package/dist/ui/assets/index-Ii0B0rTO.css +1 -0
  176. package/dist/ui/assets/{vendor-icons-C8EED3Oh.js → vendor-icons-I7ZwG1z_.js} +1 -1
  177. package/dist/ui/index.html +4 -4
  178. package/dist/utils/accountProfileSummaryCache.d.ts +31 -0
  179. package/dist/utils/accountProfileSummaryCache.js +97 -0
  180. package/dist/utils/accountProfileSummaryCache.test.d.ts +1 -0
  181. package/dist/utils/accountProfileSummaryCache.test.js +63 -0
  182. package/dist/utils/taskActivity.js +4 -0
  183. package/dist/utils/taskActivity.test.js +25 -1
  184. package/package.json +5 -3
  185. package/scripts/playwright-auth.sh +4 -0
  186. package/dist/ui/assets/AgentsModule-JG5jc3he.js +0 -1
  187. package/dist/ui/assets/PlansPage-BMPlpFpw.js +0 -1
  188. package/dist/ui/assets/TaskSettings-Bqd4cCzW.js +0 -8
  189. package/dist/ui/assets/index-MXeWoebC.css +0 -1
  190. package/dist/ui/assets/index-YJ4k5QNa.js +0 -6
  191. package/dist/utils/billingStatusCache.d.ts +0 -21
  192. package/dist/utils/billingStatusCache.js +0 -70
@@ -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 {};
@@ -25,6 +25,7 @@ export declare function pullWorkspaceChanges(resolveCloudAuthUrl: (path: string)
25
25
  nextCursor?: string | null;
26
26
  hasMore?: boolean;
27
27
  workspaceMembers?: WorkspaceSyncWorkspaceMemberSnapshot[];
28
+ diagnostics?: Record<string, unknown>;
28
29
  }>>;
29
30
  export declare function pushWorkspaceChanges(resolveCloudAuthUrl: (path: string) => string, input: {
30
31
  workspaceId: string;
@@ -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
  }
@@ -21,6 +21,8 @@ interface ContentSyncStateDeps {
21
21
  recordSyncDiagnostic: RecordSyncDiagnostic;
22
22
  workspaceDocumentSnapshotCache: Map<string, Map<string, CachedWorkspaceSyncDocument>>;
23
23
  }
24
+ export type DocumentSyncIndexEntry = Omit<DocumentSyncPayload, 'content'>;
25
+ export type BinaryAssetSyncIndexEntry = Omit<BinaryAssetSyncPayload, 'contentBase64'>;
24
26
  export declare function resolveCanonicalAssetSyncLinkState(deps: ContentSyncStateDeps, asset: WorkspaceAssetEntry, workspaceId: string): {
25
27
  primaryLink: WorkspaceAssetLinkEntry | null;
26
28
  effectiveUpdatedAt: string;
@@ -42,7 +44,11 @@ export declare function reconcileWorkspaceSyncLinks(deps: ContentSyncStateDeps,
42
44
  }): void;
43
45
  export declare function listWorkspaceSyncDocumentDeletesSnapshot(deps: ContentSyncStateDeps, workspaceId?: string): DocumentDeleteSyncPayload[];
44
46
  export declare function listWorkspaceSyncDocumentsSnapshot(deps: ContentSyncStateDeps, basePath: string, workspaceId?: string): Promise<DocumentSyncPayload[]>;
47
+ export declare function listWorkspaceSyncDocumentIndex(deps: ContentSyncStateDeps, basePath: string, workspaceId?: string): Promise<DocumentSyncIndexEntry[]>;
45
48
  export declare function listWorkspaceSyncBinaryAssetsSnapshot(deps: ContentSyncStateDeps, basePath: string, workspaceId?: string): Promise<BinaryAssetSyncPayload[]>;
49
+ export declare function listWorkspaceSyncBinaryAssetIndex(deps: ContentSyncStateDeps, workspaceId?: string): Promise<BinaryAssetSyncIndexEntry[]>;
50
+ export declare function loadWorkspaceSyncDocumentPayload(deps: ContentSyncStateDeps, basePath: string, workspaceId: string, relativePath: string): Promise<DocumentSyncPayload | null>;
51
+ export declare function loadWorkspaceSyncBinaryAssetPayload(deps: ContentSyncStateDeps, basePath: string, workspaceId: string, assetPath: string): Promise<BinaryAssetSyncPayload | null>;
46
52
  export declare function listWorkspaceSyncBinaryAssetDeletesSnapshot(deps: ContentSyncStateDeps, workspaceId?: string): BinaryAssetDeleteSyncPayload[];
47
53
  export declare function writeWorkspaceSyncDocument(deps: ContentSyncStateDeps, basePath: string, doc: DocumentSyncPayload, workspaceId?: string, options?: {
48
54
  allowReferenceNumberReassignment?: boolean;
@@ -73,8 +79,12 @@ export declare function createContentSyncState(deps: ContentSyncStateDeps): {
73
79
  updatedAt?: string | null;
74
80
  }) => void;
75
81
  listWorkspaceSyncDocumentDeletesSnapshot: (workspaceId?: string) => DocumentDeleteSyncPayload[];
82
+ listWorkspaceSyncDocumentIndex: (basePath: string, workspaceId?: string) => Promise<DocumentSyncIndexEntry[]>;
76
83
  listWorkspaceSyncDocumentsSnapshot: (basePath: string, workspaceId?: string) => Promise<DocumentSyncPayload[]>;
84
+ loadWorkspaceSyncDocumentPayload: (basePath: string, workspaceId: string, relativePath: string) => Promise<DocumentSyncPayload | null>;
85
+ listWorkspaceSyncBinaryAssetIndex: (workspaceId?: string) => Promise<BinaryAssetSyncIndexEntry[]>;
77
86
  listWorkspaceSyncBinaryAssetsSnapshot: (basePath: string, workspaceId?: string) => Promise<BinaryAssetSyncPayload[]>;
87
+ loadWorkspaceSyncBinaryAssetPayload: (basePath: string, workspaceId: string, assetPath: string) => Promise<BinaryAssetSyncPayload | null>;
78
88
  listWorkspaceSyncBinaryAssetDeletesSnapshot: (workspaceId?: string) => BinaryAssetDeleteSyncPayload[];
79
89
  writeWorkspaceSyncDocument: (basePath: string, doc: DocumentSyncPayload, workspaceId?: string, options?: {
80
90
  allowReferenceNumberReassignment?: boolean;
@@ -68,10 +68,10 @@ export function hasDocumentSyncMetadataDrift(deps, workspaceId, doc, options) {
68
68
  : null;
69
69
  const normalizedIncomingLinkRole = doc.linkRole === 'reference' ? 'reference' : 'attachment';
70
70
  const allowReferenceNumberReassignment = options?.allowReferenceNumberReassignment === true;
71
- if (!allowReferenceNumberReassignment
72
- && existingAsset.referenceNumber
71
+ const referenceNumberMismatch = Boolean(existingAsset.referenceNumber
73
72
  && normalizedIncomingReference
74
- && existingAsset.referenceNumber !== normalizedIncomingReference) {
73
+ && existingAsset.referenceNumber !== normalizedIncomingReference);
74
+ if (referenceNumberMismatch) {
75
75
  deps.recordSyncDiagnostic(workspaceId, 'apply', 'Detected document reference number mismatch during normal sync.', {
76
76
  source: 'documents.referenceNumber.mismatch',
77
77
  path: doc.path,
@@ -117,10 +117,10 @@ export function hasBinaryAssetSyncMetadataDrift(deps, workspaceId, asset, option
117
117
  ? 'image'
118
118
  : 'attachment';
119
119
  const allowReferenceNumberReassignment = options?.allowReferenceNumberReassignment === true;
120
- if (!allowReferenceNumberReassignment
121
- && existingAsset.referenceNumber
120
+ const referenceNumberMismatch = Boolean(existingAsset.referenceNumber
122
121
  && normalizedIncomingReference
123
- && existingAsset.referenceNumber !== normalizedIncomingReference) {
122
+ && existingAsset.referenceNumber !== normalizedIncomingReference);
123
+ if (referenceNumberMismatch) {
124
124
  deps.recordSyncDiagnostic(workspaceId, 'apply', 'Detected asset reference number mismatch during normal sync.', {
125
125
  source: 'assets.referenceNumber.mismatch',
126
126
  path: asset.path,
@@ -344,6 +344,80 @@ export async function listWorkspaceSyncDocumentsSnapshot(deps, basePath, workspa
344
344
  }
345
345
  return docs;
346
346
  }
347
+ export async function listWorkspaceSyncDocumentIndex(deps, basePath, workspaceId = 'default') {
348
+ const root = path.resolve(basePath);
349
+ 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);
370
+ if (deps.workspaceAssetStore) {
371
+ const canonicalAssets = deps.workspaceAssetStore.listAllByWorkspace(workspaceId, {
372
+ includeDeleted: false,
373
+ kind: 'document'
374
+ });
375
+ for (const asset of canonicalAssets) {
376
+ const normalized = deps.normalizeWorkspaceSyncDocumentPath(asset.storageKey);
377
+ if (normalized)
378
+ candidatePaths.add(normalized);
379
+ }
380
+ }
381
+ const docs = [];
382
+ for (const relativePath of Array.from(candidatePaths).sort((a, b) => a.localeCompare(b))) {
383
+ try {
384
+ const canonicalAsset = deps.workspaceAssetStore?.getByStorageKey(relativePath, workspaceId);
385
+ let updatedAt = '';
386
+ if (canonicalAsset?.kind === 'document') {
387
+ updatedAt = resolveCanonicalAssetSyncLinkState(deps, canonicalAsset, workspaceId).effectiveUpdatedAt;
388
+ }
389
+ else {
390
+ const absPath = path.resolve(path.join(basePath, relativePath));
391
+ const safeRoot = path.resolve(basePath);
392
+ if (absPath !== safeRoot && !absPath.startsWith(`${safeRoot}${path.sep}`))
393
+ continue;
394
+ if (!fs.existsSync(absPath))
395
+ continue;
396
+ const stat = fs.statSync(absPath);
397
+ if (!stat.isFile())
398
+ continue;
399
+ const existing = deps.core.getDocumentWatermark(workspaceId, relativePath);
400
+ updatedAt = existing?.updatedAt
401
+ || (Number.isFinite(stat.mtimeMs) ? new Date(stat.mtimeMs).toISOString() : new Date().toISOString());
402
+ }
403
+ if (!Number.isFinite(Date.parse(String(updatedAt || '').trim())))
404
+ continue;
405
+ docs.push({
406
+ path: relativePath,
407
+ updatedAt: String(updatedAt || '').trim(),
408
+ ...getCanonicalSyncDocumentMetadata(deps, relativePath, workspaceId)
409
+ });
410
+ }
411
+ catch (error) {
412
+ deps.recordSyncDiagnostic(workspaceId, 'pull', 'Failed to index sync document snapshot entry.', {
413
+ source: 'documents.snapshot.indexEntry',
414
+ path: relativePath,
415
+ error: String(error?.message || error || '')
416
+ });
417
+ }
418
+ }
419
+ return docs;
420
+ }
347
421
  export async function listWorkspaceSyncBinaryAssetsSnapshot(deps, basePath, workspaceId = 'default') {
348
422
  if (!deps.workspaceAssetStore)
349
423
  return [];
@@ -418,6 +492,181 @@ export async function listWorkspaceSyncBinaryAssetsSnapshot(deps, basePath, work
418
492
  }
419
493
  return snapshots;
420
494
  }
495
+ export async function listWorkspaceSyncBinaryAssetIndex(deps, workspaceId = 'default') {
496
+ if (!deps.workspaceAssetStore)
497
+ return [];
498
+ const assets = deps.workspaceAssetStore.listAllByWorkspace(workspaceId, {
499
+ includeDeleted: false
500
+ });
501
+ return assets
502
+ .filter((asset) => asset.kind === 'image' || asset.kind === 'file')
503
+ .filter((asset) => asset.storageProvider !== 'external')
504
+ .filter((asset) => {
505
+ const storageKey = String(asset.storageKey || '').trim();
506
+ return Boolean(storageKey && deps.normalizeTaskDataRelativePath(storageKey));
507
+ })
508
+ .map((asset) => {
509
+ const storageKey = String(asset.storageKey || '').trim();
510
+ const { primaryLink, effectiveUpdatedAt } = resolveCanonicalAssetSyncLinkState(deps, asset, workspaceId);
511
+ const assetKind = asset.kind === 'image' ? 'image' : 'file';
512
+ return {
513
+ path: storageKey,
514
+ updatedAt: effectiveUpdatedAt,
515
+ assetId: asset.assetId,
516
+ kind: assetKind,
517
+ mimeType: asset.mimeType || 'application/octet-stream',
518
+ referenceNumber: asset.referenceNumber,
519
+ taskId: primaryLink?.taskId || null,
520
+ logicalName: asset.logicalName || null,
521
+ caption: primaryLink?.displayName || null,
522
+ originalFilename: asset.originalFilename || path.basename(storageKey),
523
+ linkRole: primaryLink?.role || (asset.kind === 'image' ? 'image' : 'attachment')
524
+ };
525
+ })
526
+ .filter((entry) => Number.isFinite(Date.parse(entry.updatedAt)) && entry.path.length > 0);
527
+ }
528
+ export async function loadWorkspaceSyncDocumentPayload(deps, basePath, workspaceId, relativePath) {
529
+ const normalizedPath = deps.normalizeWorkspaceSyncDocumentPath(relativePath);
530
+ if (!normalizedPath)
531
+ return null;
532
+ const root = path.resolve(basePath);
533
+ const absolutePath = path.resolve(path.join(root, normalizedPath));
534
+ if (absolutePath !== root && !absolutePath.startsWith(`${root}${path.sep}`))
535
+ return null;
536
+ let content = '';
537
+ let stat = null;
538
+ 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');
545
+ }
546
+ catch (error) {
547
+ deps.recordSyncDiagnostic(workspaceId, 'pull', 'Failed to load targeted sync document payload.', {
548
+ source: 'documents.snapshot.loadPayload',
549
+ path: normalizedPath,
550
+ error: String(error?.message || error || '')
551
+ });
552
+ return null;
553
+ }
554
+ const workspaceCache = deps.workspaceDocumentSnapshotCache.get(workspaceId)
555
+ ?? (() => {
556
+ const next = new Map();
557
+ deps.workspaceDocumentSnapshotCache.set(workspaceId, next);
558
+ return next;
559
+ })();
560
+ const cached = workspaceCache.get(normalizedPath);
561
+ const canonicalAsset = deps.workspaceAssetStore?.getByStorageKey(normalizedPath, workspaceId);
562
+ let updatedAt = '';
563
+ if (canonicalAsset?.kind === 'document') {
564
+ updatedAt = resolveCanonicalAssetSyncLinkState(deps, canonicalAsset, workspaceId).effectiveUpdatedAt;
565
+ }
566
+ else {
567
+ const contentHash = createHash('sha256').update(content).digest('hex');
568
+ const existing = deps.core.getDocumentWatermark(workspaceId, normalizedPath);
569
+ if (existing && existing.contentHash === contentHash) {
570
+ updatedAt = existing.updatedAt;
571
+ }
572
+ else {
573
+ updatedAt = stat && Number.isFinite(stat.mtimeMs)
574
+ ? new Date(stat.mtimeMs).toISOString()
575
+ : new Date().toISOString();
576
+ try {
577
+ deps.core.upsertDocumentWatermark(workspaceId, normalizedPath, contentHash, updatedAt);
578
+ }
579
+ catch (error) {
580
+ deps.recordSyncDiagnostic(workspaceId, 'pull', 'Failed to persist document watermark during targeted payload load.', {
581
+ source: 'documents.snapshot.loadPayload.upsertWatermark',
582
+ path: normalizedPath,
583
+ error: String(error?.message || error || '')
584
+ });
585
+ }
586
+ }
587
+ }
588
+ if (cached
589
+ && stat
590
+ && cached.size === Buffer.byteLength(content, 'utf8')
591
+ && (canonicalAsset
592
+ ? cached.updatedAt === updatedAt
593
+ : cached.mtimeMs === stat.mtimeMs && cached.ctimeMs === stat.ctimeMs)) {
594
+ return {
595
+ path: normalizedPath,
596
+ updatedAt: cached.updatedAt,
597
+ content: cached.content,
598
+ ...getCanonicalSyncDocumentMetadata(deps, normalizedPath, workspaceId)
599
+ };
600
+ }
601
+ workspaceCache.set(normalizedPath, {
602
+ path: normalizedPath,
603
+ mtimeMs: stat?.mtimeMs ?? 0,
604
+ ctimeMs: stat?.ctimeMs ?? 0,
605
+ size: Buffer.byteLength(content, 'utf8'),
606
+ updatedAt,
607
+ content
608
+ });
609
+ return {
610
+ path: normalizedPath,
611
+ updatedAt,
612
+ content,
613
+ ...getCanonicalSyncDocumentMetadata(deps, normalizedPath, workspaceId)
614
+ };
615
+ }
616
+ export async function loadWorkspaceSyncBinaryAssetPayload(deps, basePath, workspaceId, assetPath) {
617
+ const normalizedPath = deps.normalizeTaskDataRelativePath(assetPath);
618
+ if (!normalizedPath)
619
+ return null;
620
+ if (!deps.workspaceAssetStore)
621
+ return null;
622
+ const asset = deps.workspaceAssetStore.getByStorageKey(normalizedPath, workspaceId);
623
+ if (!asset || (asset.kind !== 'image' && asset.kind !== 'file') || asset.storageProvider === 'external') {
624
+ return null;
625
+ }
626
+ const objectStorageClient = deps.getObjectStorageClient();
627
+ let buffer = null;
628
+ try {
629
+ if (asset.storageProvider === 'r2' && objectStorageClient) {
630
+ const object = await objectStorageClient.getObject(normalizedPath);
631
+ buffer = object?.body || null;
632
+ }
633
+ else {
634
+ const root = path.resolve(basePath);
635
+ const absolutePath = path.resolve(root, normalizedPath);
636
+ if (absolutePath !== root && !absolutePath.startsWith(`${root}${path.sep}`))
637
+ return null;
638
+ if (!fs.existsSync(absolutePath))
639
+ return null;
640
+ buffer = fs.readFileSync(absolutePath);
641
+ }
642
+ }
643
+ catch (error) {
644
+ deps.recordSyncDiagnostic(workspaceId, 'pull', 'Failed to load targeted binary asset payload.', {
645
+ source: 'assets.snapshot.loadPayload',
646
+ path: normalizedPath,
647
+ assetId: asset.assetId,
648
+ error: String(error?.message || error || '')
649
+ });
650
+ return null;
651
+ }
652
+ if (!buffer)
653
+ return null;
654
+ const { primaryLink, effectiveUpdatedAt } = resolveCanonicalAssetSyncLinkState(deps, asset, workspaceId);
655
+ return {
656
+ path: normalizedPath,
657
+ updatedAt: effectiveUpdatedAt,
658
+ contentBase64: buffer.toString('base64'),
659
+ assetId: asset.assetId,
660
+ kind: asset.kind,
661
+ mimeType: asset.mimeType || 'application/octet-stream',
662
+ referenceNumber: asset.referenceNumber,
663
+ taskId: primaryLink?.taskId || null,
664
+ logicalName: asset.logicalName || null,
665
+ caption: primaryLink?.displayName || null,
666
+ originalFilename: asset.originalFilename || path.basename(normalizedPath),
667
+ linkRole: primaryLink?.role || (asset.kind === 'image' ? 'image' : 'attachment')
668
+ };
669
+ }
421
670
  export function listWorkspaceSyncBinaryAssetDeletesSnapshot(deps, workspaceId = 'default') {
422
671
  if (!deps.workspaceAssetStore)
423
672
  return [];
@@ -479,6 +728,13 @@ export async function writeWorkspaceSyncDocument(deps, basePath, doc, workspaceI
479
728
  if (deps.workspaceAssetStore) {
480
729
  const existing = deps.workspaceAssetStore.getByStorageKey(normalizedPath, workspaceId);
481
730
  const effectiveUpdatedAt = updatedAt || new Date().toISOString();
731
+ const incomingReferenceNumber = Number.isFinite(Number(doc.referenceNumber))
732
+ ? Math.max(1, Math.floor(Number(doc.referenceNumber)))
733
+ : null;
734
+ const allowReferenceNumberReassignment = options?.allowReferenceNumberReassignment === true;
735
+ const nextReferenceNumber = allowReferenceNumberReassignment
736
+ ? (incomingReferenceNumber ?? existing?.referenceNumber ?? null)
737
+ : (existing?.referenceNumber ?? incomingReferenceNumber ?? null);
482
738
  const originalFilename = String(doc.originalFilename || existing?.originalFilename || path.basename(normalizedPath) || 'document.md').trim() || 'document.md';
483
739
  const asset = deps.workspaceAssetStore.upsertAsset({
484
740
  assetId: String(doc.assetId || existing?.assetId || `asset-${randomUUID().replace(/-/g, '')}`),
@@ -494,9 +750,7 @@ export async function writeWorkspaceSyncDocument(deps, basePath, doc, workspaceI
494
750
  contentSha256: contentHash,
495
751
  sizeBytes: Buffer.byteLength(content, 'utf8'),
496
752
  documentId: String(doc.documentId || existing?.documentId || `doc-${randomUUID().replace(/-/g, '')}`),
497
- referenceNumber: Number.isFinite(Number(doc.referenceNumber))
498
- ? Math.max(1, Math.floor(Number(doc.referenceNumber)))
499
- : existing?.referenceNumber || null,
753
+ referenceNumber: nextReferenceNumber,
500
754
  version: Number.isFinite(Number(doc.version))
501
755
  ? Math.max(1, Math.floor(Number(doc.version)))
502
756
  : Math.max(1, Number(existing?.version || 0) + 1),
@@ -509,7 +763,7 @@ export async function writeWorkspaceSyncDocument(deps, basePath, doc, workspaceI
509
763
  updatedAt: effectiveUpdatedAt,
510
764
  deletedAt: null,
511
765
  purgeAfter: null,
512
- allowReferenceNumberReassignment: options?.allowReferenceNumberReassignment === true
766
+ allowReferenceNumberReassignment
513
767
  });
514
768
  const taskId = String(doc.taskId || '').trim();
515
769
  reconcileWorkspaceSyncLinks(deps, {
@@ -569,6 +823,13 @@ export async function writeWorkspaceSyncBinaryAsset(deps, basePath, asset, works
569
823
  try {
570
824
  const existing = deps.workspaceAssetStore.getByStorageKey(normalizedPath, workspaceId);
571
825
  const effectiveUpdatedAt = updatedAt || new Date().toISOString();
826
+ const incomingReferenceNumber = Number.isFinite(Number(asset.referenceNumber))
827
+ ? Math.max(1, Math.floor(Number(asset.referenceNumber)))
828
+ : null;
829
+ const allowReferenceNumberReassignment = options?.allowReferenceNumberReassignment === true;
830
+ const nextReferenceNumber = allowReferenceNumberReassignment
831
+ ? (incomingReferenceNumber ?? existing?.referenceNumber ?? null)
832
+ : (existing?.referenceNumber ?? incomingReferenceNumber ?? null);
572
833
  const assetRecord = deps.workspaceAssetStore.upsertAsset({
573
834
  assetId: String(asset.assetId || existing?.assetId || `asset-${randomUUID().replace(/-/g, '')}`),
574
835
  workspaceId,
@@ -583,9 +844,7 @@ export async function writeWorkspaceSyncBinaryAsset(deps, basePath, asset, works
583
844
  contentSha256: createHash('sha256').update(buffer).digest('hex'),
584
845
  sizeBytes: buffer.length,
585
846
  documentId: null,
586
- referenceNumber: Number.isFinite(Number(asset.referenceNumber))
587
- ? Math.max(1, Math.floor(Number(asset.referenceNumber)))
588
- : existing?.referenceNumber || null,
847
+ referenceNumber: nextReferenceNumber,
589
848
  version: null,
590
849
  isLatest: true,
591
850
  scanStatus: existing?.scanStatus || 'clean',
@@ -596,7 +855,7 @@ export async function writeWorkspaceSyncBinaryAsset(deps, basePath, asset, works
596
855
  updatedAt: effectiveUpdatedAt,
597
856
  deletedAt: null,
598
857
  purgeAfter: null,
599
- allowReferenceNumberReassignment: options?.allowReferenceNumberReassignment === true
858
+ allowReferenceNumberReassignment
600
859
  });
601
860
  const taskId = String(asset.taskId || '').trim();
602
861
  reconcileWorkspaceSyncLinks(deps, {
@@ -732,8 +991,12 @@ export function createContentSyncState(deps) {
732
991
  hasBinaryAssetSyncMetadataDrift: (workspaceId, asset, options) => hasBinaryAssetSyncMetadataDrift(deps, workspaceId, asset, options),
733
992
  reconcileWorkspaceSyncLinks: (input) => reconcileWorkspaceSyncLinks(deps, input),
734
993
  listWorkspaceSyncDocumentDeletesSnapshot: (workspaceId = 'default') => listWorkspaceSyncDocumentDeletesSnapshot(deps, workspaceId),
994
+ listWorkspaceSyncDocumentIndex: (basePath, workspaceId = 'default') => listWorkspaceSyncDocumentIndex(deps, basePath, workspaceId),
735
995
  listWorkspaceSyncDocumentsSnapshot: (basePath, workspaceId = 'default') => listWorkspaceSyncDocumentsSnapshot(deps, basePath, workspaceId),
996
+ loadWorkspaceSyncDocumentPayload: (basePath, workspaceId, relativePath) => loadWorkspaceSyncDocumentPayload(deps, basePath, workspaceId, relativePath),
997
+ listWorkspaceSyncBinaryAssetIndex: (workspaceId = 'default') => listWorkspaceSyncBinaryAssetIndex(deps, workspaceId),
736
998
  listWorkspaceSyncBinaryAssetsSnapshot: (basePath, workspaceId = 'default') => listWorkspaceSyncBinaryAssetsSnapshot(deps, basePath, workspaceId),
999
+ loadWorkspaceSyncBinaryAssetPayload: (basePath, workspaceId, assetPath) => loadWorkspaceSyncBinaryAssetPayload(deps, basePath, workspaceId, assetPath),
737
1000
  listWorkspaceSyncBinaryAssetDeletesSnapshot: (workspaceId = 'default') => listWorkspaceSyncBinaryAssetDeletesSnapshot(deps, workspaceId),
738
1001
  writeWorkspaceSyncDocument: (basePath, doc, workspaceId = 'default', options) => writeWorkspaceSyncDocument(deps, basePath, doc, workspaceId, options),
739
1002
  writeWorkspaceSyncBinaryAsset: (basePath, asset, workspaceId = 'default', options) => writeWorkspaceSyncBinaryAsset(deps, basePath, asset, workspaceId, options),
@@ -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 {};