@taskforcehq/taskforce 0.3.305 → 0.3.307
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -2
- package/dist/Taskforce.module.css +603 -107
- package/dist/TaskforceCore.js +216 -43
- package/dist/TaskforceCore.test.js +611 -28
- package/dist/assets/fonts/CourierPrime-Bold.woff2 +0 -0
- package/dist/assets/fonts/CourierPrime-BoldItalic.woff2 +0 -0
- package/dist/assets/fonts/CourierPrime-Italic.woff2 +0 -0
- package/dist/assets/fonts/CourierPrime-Regular.woff2 +0 -0
- package/dist/assets/fonts/Noir_medium.woff2 +0 -0
- package/dist/assets/fonts/Noir_regular.woff2 +0 -0
- package/dist/assets/fonts/RussoOne-Regular.woff2 +0 -0
- package/dist/assets/fonts/SpecialElite-Regular.woff2 +0 -0
- package/dist/compat/workspaceSyncCompat.js +46 -2
- package/dist/compat/workspaceSyncCompat.test.js +38 -1
- package/dist/components/activity/EntityActivityTimeline.d.ts +34 -0
- package/dist/components/activity/EntityActivityTimeline.js +81 -0
- package/dist/components/context/ContextAttachmentManager.d.ts +14 -0
- package/dist/components/context/ContextAttachmentManager.js +561 -0
- package/dist/components/features/AgentsModule.d.ts +14 -1
- package/dist/components/features/AgentsModule.js +366 -18
- package/dist/components/features/AgentsModule.test.js +507 -8
- package/dist/components/features/AnnotatedAttachmentWorkspace.d.ts +3 -1
- package/dist/components/features/AnnotatedAttachmentWorkspace.js +118 -4
- package/dist/components/features/AnnotatedAttachmentWorkspace.test.js +52 -0
- package/dist/components/features/DocumentIndex.d.ts +2 -2
- package/dist/components/features/DocumentIndex.js +3 -4
- package/dist/components/features/DocumentViewer.d.ts +7 -1
- package/dist/components/features/DocumentViewer.js +62 -4
- package/dist/components/features/DocumentWorkspace.d.ts +10 -2
- package/dist/components/features/DocumentWorkspace.js +15 -4
- package/dist/components/features/DocumentWorkspace.test.js +51 -1
- package/dist/components/features/TaskSettings.d.ts +2 -0
- package/dist/components/features/TaskSettings.js +83 -78
- package/dist/components/features/TaskSettings.test.js +171 -82
- package/dist/components/features/documentWorkspaceModel.d.ts +1 -1
- package/dist/components/task/TaskActionHeader.js +11 -5
- package/dist/components/task/TaskActionHeader.test.js +10 -0
- package/dist/components/task/TaskCard.js +24 -29
- package/dist/components/task/TaskCard.test.js +38 -3
- package/dist/components/task/TaskContextUpload.js +4 -526
- package/dist/components/task/TaskContextUpload.test.js +3 -3
- package/dist/components/task/TaskForm.js +61 -116
- package/dist/components/task/TaskForm.test.js +110 -8
- package/dist/components/task/TaskKanban.d.ts +2 -1
- package/dist/components/task/TaskKanban.js +94 -21
- package/dist/components/task/TaskKanban.test.js +36 -0
- package/dist/components/task/TaskList.js +5 -1
- package/dist/components/task/TaskList.test.js +4 -0
- package/dist/components/ui/EditableAvatarButton.d.ts +18 -0
- package/dist/components/ui/EditableAvatarButton.js +18 -0
- package/dist/components/ui/HierarchyActionBadge.d.ts +10 -0
- package/dist/components/ui/HierarchyActionBadge.js +5 -0
- package/dist/components/views/AppShellHeader.d.ts +3 -1
- package/dist/components/views/AppShellHeader.js +27 -11
- package/dist/components/views/AppShellHeader.test.js +18 -1
- package/dist/components/views/PlanComparisonPage.d.ts +9 -1
- package/dist/components/views/PlanComparisonPage.js +78 -14
- package/dist/components/views/PlanComparisonPage.test.js +257 -0
- package/dist/components/views/PlansPage.js +127 -36
- package/dist/components/views/PlansPage.test.js +294 -12
- package/dist/components/views/StandaloneLayout.js +529 -592
- package/dist/components/views/WidgetView.js +10 -8
- package/dist/components/views/panels/PlanningDrawer.d.ts +25 -5
- package/dist/components/views/panels/PlanningDrawer.js +270 -55
- package/dist/components/views/panels/PlanningDrawer.test.d.ts +1 -0
- package/dist/components/views/panels/PlanningDrawer.test.js +529 -0
- package/dist/components/views/planningScope.d.ts +20 -0
- package/dist/components/views/planningScope.js +25 -0
- package/dist/components/views/planningScope.test.d.ts +1 -0
- package/dist/components/views/planningScope.test.js +60 -0
- package/dist/components/views/standalone/modals/AccountHubModal.d.ts +26 -1
- package/dist/components/views/standalone/modals/AccountHubModal.js +76 -2
- package/dist/components/views/standalone/modals/AccountHubModal.test.js +20 -3
- package/dist/components/views/standalone/modals/AvatarImageManagerModal.d.ts +20 -0
- package/dist/components/views/standalone/modals/AvatarImageManagerModal.js +127 -0
- package/dist/components/views/standalone/modals/EditProfileModal.d.ts +2 -9
- package/dist/components/views/standalone/modals/EditProfileModal.js +3 -2
- package/dist/components/views/standalone/modals/SyncEnableWarningModal.d.ts +9 -0
- package/dist/components/views/standalone/modals/SyncEnableWarningModal.js +6 -0
- package/dist/components/views/standalone/modals/SyncEnableWarningModal.test.d.ts +1 -0
- package/dist/components/views/standalone/modals/SyncEnableWarningModal.test.js +24 -0
- package/dist/components/views/standalone/modals/SyncStatusModal.d.ts +2 -1
- package/dist/components/views/standalone/modals/SyncStatusModal.js +2 -2
- package/dist/config/envSchema.js +1 -0
- package/dist/core/AiProfileService.d.ts +46 -2
- package/dist/core/AiProfileService.js +1073 -82
- package/dist/core/AiProfileService.test.js +19 -1
- package/dist/core/AiProfiles.test.js +1249 -44
- package/dist/core/AttachmentLinkService.d.ts +3 -0
- package/dist/core/AttachmentLinkService.js +110 -23
- package/dist/core/AuthIdentityService.d.ts +107 -0
- package/dist/core/AuthIdentityService.js +284 -0
- package/dist/core/AuthTokenService.d.ts +4 -0
- package/dist/core/AuthTokenService.js +34 -6
- package/dist/core/AuthTokenService.test.js +3 -3
- package/dist/core/EntitlementsPolicy.test.js +2 -2
- package/dist/core/GlobalSettingsService.js +127 -6
- package/dist/core/McpTokenService.d.ts +12 -0
- package/dist/core/McpTokenService.js +44 -1
- package/dist/core/PlanEntitlementService.d.ts +23 -2
- package/dist/core/PlanEntitlementService.js +343 -57
- package/dist/core/PlanFeatureCatalog.test.d.ts +1 -0
- package/dist/core/PlanFeatureCatalog.test.js +84 -0
- package/dist/core/PlanVersionPolicy.test.js +35 -2
- package/dist/core/PlanningEntities.test.js +418 -4
- package/dist/core/SignupMonetizationSettings.test.js +199 -27
- package/dist/core/SyncReconciliationService.js +2 -65
- package/dist/core/SystemAdmin.test.js +42 -42
- package/dist/core/TaskActivityService.d.ts +28 -1
- package/dist/core/TaskActivityService.js +227 -46
- package/dist/core/TaskActivitySync.test.d.ts +1 -0
- package/dist/core/TaskActivitySync.test.js +90 -0
- package/dist/core/TaskAttachmentsCanonical.test.js +51 -1
- package/dist/core/TaskAuditTimeline.test.js +96 -0
- package/dist/core/Taskforce.d.ts +415 -40
- package/dist/core/Taskforce.ids.test.js +58 -0
- package/dist/core/Taskforce.js +1543 -266
- package/dist/core/Taskforce.listTasksSlim.test.d.ts +1 -0
- package/dist/core/Taskforce.listTasksSlim.test.js +91 -0
- package/dist/core/Taskforce.mcpAuth.test.js +109 -0
- package/dist/core/UserProfileAvatarDrafts.test.js +30 -3
- package/dist/core/WorkspaceLifecycleService.js +0 -5
- package/dist/core/WorkspacePermissions.test.js +25 -1
- package/dist/core/WorkspacePlanMode.test.js +117 -16
- package/dist/core/shared.d.ts +1 -1
- package/dist/core/shared.js +5 -1
- package/dist/core/types.d.ts +75 -2
- package/dist/hooks/auth/useTaskforceAuthBootstrap.js +28 -2
- package/dist/hooks/bootstrapTimeouts.d.ts +4 -0
- package/dist/hooks/bootstrapTimeouts.js +8 -0
- package/dist/hooks/bootstrapTimeouts.test.d.ts +1 -0
- package/dist/hooks/bootstrapTimeouts.test.js +12 -0
- package/dist/hooks/sync/bootstrap.js +2 -0
- package/dist/hooks/sync/controlPlane.d.ts +37 -0
- package/dist/hooks/sync/controlPlane.js +78 -0
- package/dist/hooks/sync/controlPlane.test.d.ts +1 -0
- package/dist/hooks/sync/controlPlane.test.js +121 -0
- package/dist/hooks/sync/lifecyclePolicy.d.ts +45 -0
- package/dist/hooks/sync/lifecyclePolicy.js +93 -0
- package/dist/hooks/sync/lifecyclePolicy.test.d.ts +1 -0
- package/dist/hooks/sync/lifecyclePolicy.test.js +124 -0
- package/dist/hooks/sync/orchestratorShared.d.ts +13 -4
- package/dist/hooks/sync/orchestratorShared.js +129 -48
- package/dist/hooks/sync/orchestratorShared.test.js +50 -1
- package/dist/hooks/sync/pullLifecycle.d.ts +31 -0
- package/dist/hooks/sync/pullLifecycle.js +24 -0
- package/dist/hooks/sync/pullLifecycle.test.d.ts +1 -0
- package/dist/hooks/sync/pullLifecycle.test.js +80 -0
- package/dist/hooks/sync/recovery.d.ts +16 -2
- package/dist/hooks/sync/recovery.js +179 -53
- package/dist/hooks/sync/recovery.test.d.ts +1 -0
- package/dist/hooks/sync/recovery.test.js +292 -0
- package/dist/hooks/sync/transfers.d.ts +16 -3
- package/dist/hooks/sync/transfers.js +210 -66
- package/dist/hooks/sync/transfers.test.d.ts +1 -0
- package/dist/hooks/sync/transfers.test.js +928 -0
- package/dist/hooks/sync/useRecentSyncEvents.d.ts +21 -0
- package/dist/hooks/sync/useRecentSyncEvents.js +92 -0
- package/dist/hooks/sync/useRecentSyncEvents.test.d.ts +1 -0
- package/dist/hooks/sync/useRecentSyncEvents.test.js +124 -0
- package/dist/hooks/sync/useSyncStatusActions.d.ts +30 -0
- package/dist/hooks/sync/useSyncStatusActions.js +88 -0
- package/dist/hooks/sync/useSyncStatusActions.test.d.ts +1 -0
- package/dist/hooks/sync/useSyncStatusActions.test.js +133 -0
- package/dist/hooks/sync/useSyncStatusControls.d.ts +25 -0
- package/dist/hooks/sync/useSyncStatusControls.js +60 -0
- package/dist/hooks/sync/useSyncStatusControls.test.d.ts +1 -0
- package/dist/hooks/sync/useSyncStatusControls.test.js +88 -0
- package/dist/hooks/useFilterSort.js +13 -13
- package/dist/hooks/useFilterSort.test.js +87 -1
- package/dist/hooks/useSyncOrchestrator.aiProfiles.test.js +12 -0
- package/dist/hooks/useSyncOrchestrator.d.ts +9 -2
- package/dist/hooks/useSyncOrchestrator.js +409 -183
- package/dist/hooks/useSyncOrchestrator.retry-closure.test.js +407 -0
- package/dist/hooks/useTaskData.js +8 -3
- package/dist/hooks/useTaskData.test.js +45 -0
- package/dist/hooks/useTaskforce.d.ts +145 -52
- package/dist/hooks/useTaskforce.js +592 -253
- package/dist/hooks/useTaskforce.runtime-routing.test.d.ts +1 -0
- package/dist/hooks/useTaskforce.runtime-routing.test.js +246 -0
- package/dist/hooks/useTaskforce.sync-behavior.test.js +2468 -201
- package/dist/hooks/useWorkspaceSyncController.d.ts +1 -0
- package/dist/hooks/useWorkspaceSyncController.js +13 -2
- package/dist/hooks/useWorkspaceSyncController.test.js +48 -0
- package/dist/hooks/workspace/useTaskforceWorkspaceBootstrap.d.ts +16 -0
- package/dist/hooks/workspace/useTaskforceWorkspaceBootstrap.js +328 -40
- package/dist/localization/locales/en-US.d.ts +0 -1
- package/dist/localization/locales/en-US.js +0 -1
- package/dist/localization/locales/es-419.js +0 -1
- package/dist/localization/locales/pt-BR.js +0 -1
- package/dist/mcp/canonicalAssetHelpers.d.ts +16 -4
- package/dist/mcp/canonicalAssetHelpers.js +18 -10
- package/dist/mcp/canonicalAssetHelpers.test.d.ts +1 -0
- package/dist/mcp/canonicalAssetHelpers.test.js +67 -0
- package/dist/mcp/clientIntegrations.d.ts +1 -0
- package/dist/mcp/clientIntegrations.js +25 -0
- package/dist/mcp/clientIntegrations.test.js +14 -3
- package/dist/mcp/clientProfileDefaults.js +3 -3
- package/dist/mcp/collaborationRegistrar.js +7 -7
- package/dist/mcp/documentAssetRegistrar.js +116 -10
- package/dist/mcp/runtime.d.ts +3 -0
- package/dist/mcp/runtime.js +1099 -185
- package/dist/mcp/runtime.test.js +1491 -140
- package/dist/mcp/taskAttachmentTypes.d.ts +1 -1
- package/dist/mcp/taskPlanningRegistrar.js +48 -0
- package/dist/mcp/toolRegistry.d.ts +56 -0
- package/dist/mcp/toolRegistry.js +8 -0
- package/dist/mcp/toolRegistry.test.js +4 -0
- package/dist/migrations/taskSchemaMigrations.d.ts +1 -1
- package/dist/migrations/taskSchemaMigrations.js +192 -61
- package/dist/migrations/taskSchemaMigrations.test.js +15 -0
- package/dist/resources/templates/workflow-sources/workflowDocs.mjs +6 -6
- package/dist/resources/templates/workflows/collaborate.yaml +1 -1
- package/dist/resources/templates/workflows/evaluate.yaml +2 -2
- package/dist/resources/templates/workflows/plan.yaml +1 -1
- package/dist/resources/templates/workflows/review.yaml +2 -2
- package/dist/server/aiProfileAvatarAssets.d.ts +49 -0
- package/dist/server/aiProfileAvatarAssets.js +319 -0
- package/dist/server/aiProfileAvatarAssets.test.d.ts +1 -0
- package/dist/server/aiProfileAvatarAssets.test.js +213 -0
- package/dist/server/annotatedAttachmentsRoutes.test.js +69 -10
- package/dist/server/auth/providers/apple.d.ts +33 -0
- package/dist/server/auth/providers/apple.js +82 -0
- package/dist/server/auth/providers/appleClientSecret.d.ts +37 -0
- package/dist/server/auth/providers/appleClientSecret.js +65 -0
- package/dist/server/auth/providers/github.d.ts +26 -0
- package/dist/server/auth/providers/github.js +86 -0
- package/dist/server/auth/providers/google.d.ts +21 -0
- package/dist/server/auth/providers/google.js +56 -0
- package/dist/server/auth/providers/types.d.ts +21 -0
- package/dist/server/auth/providers/types.js +1 -0
- package/dist/server/auth.d.ts +2 -0
- package/dist/server/auth.js +6 -3
- package/dist/server/documentReviewRoutes.test.js +36 -3
- package/dist/server/index.cookieProxy.test.js +1 -0
- package/dist/server/index.d.ts +12 -0
- package/dist/server/index.js +124 -9
- package/dist/server/index.rateLimit.test.js +3 -0
- package/dist/server/index.test.js +111 -3
- package/dist/server/routes/admin.d.ts +3 -0
- package/dist/server/routes/admin.js +459 -28
- package/dist/server/routes/annotatedAttachments.js +51 -0
- package/dist/server/routes/auth.d.ts +26 -2
- package/dist/server/routes/auth.js +1170 -71
- package/dist/server/routes/authSupport.d.ts +5 -1
- package/dist/server/routes/authSupport.js +13 -2
- package/dist/server/routes/billing.js +372 -35
- package/dist/server/routes/billing.test.js +595 -12
- package/dist/server/routes/documents.d.ts +1 -0
- package/dist/server/routes/documents.js +182 -70
- package/dist/server/routes/shared.d.ts +28 -2
- package/dist/server/routes/shared.js +69 -14
- package/dist/server/routes/sync.integration.test.js +658 -39
- package/dist/server/routes/sync.js +74 -608
- package/dist/server/routes/syncAuxRoutes.d.ts +15 -0
- package/dist/server/routes/syncAuxRoutes.js +91 -0
- package/dist/server/routes/syncAuxRoutes.test.d.ts +1 -0
- package/dist/server/routes/syncAuxRoutes.test.js +158 -0
- package/dist/server/routes/syncPullApplyRoutes.d.ts +36 -0
- package/dist/server/routes/syncPullApplyRoutes.js +204 -0
- package/dist/server/routes/syncPushRoutes.d.ts +24 -0
- package/dist/server/routes/syncPushRoutes.js +212 -0
- package/dist/server/routes/syncRouteGuards.d.ts +36 -0
- package/dist/server/routes/syncRouteGuards.js +67 -0
- package/dist/server/routes/syncRouteGuards.test.d.ts +1 -0
- package/dist/server/routes/syncRouteGuards.test.js +94 -0
- package/dist/server/routes/syncRouteTypes.d.ts +13 -0
- package/dist/server/routes/syncRouteTypes.js +1 -0
- package/dist/server/routes/syncSnapshotRoutes.d.ts +66 -0
- package/dist/server/routes/syncSnapshotRoutes.js +182 -0
- package/dist/server/routes/tasks.js +55 -10
- package/dist/server/routes/workspaces.js +36 -5
- package/dist/server/routes.js +147 -11
- package/dist/server/routes.test.js +2704 -183
- package/dist/services/workflowExportSnapshots.test.js +2 -0
- package/dist/shared/aiProfileSeatScope.d.ts +5 -0
- package/dist/shared/aiProfileSeatScope.js +21 -0
- package/dist/shared/aiProfileSurfaceType.d.ts +1 -1
- package/dist/shared/aiProfileSurfaceType.js +10 -8
- package/dist/shared/passwordPolicy.d.ts +13 -0
- package/dist/shared/passwordPolicy.js +84 -0
- package/dist/shared/passwordPolicy.test.d.ts +1 -0
- package/dist/shared/passwordPolicy.test.js +34 -0
- package/dist/storage/objectStorage.d.ts +1 -0
- package/dist/storage/objectStorage.js +2 -1
- package/dist/storage/objectStorageClient.d.ts +1 -0
- package/dist/storage/objectStorageClient.js +41 -8
- package/dist/storage/objectStorageClient.test.js +26 -1
- package/dist/storage/objectStorageConfig.js +3 -1
- package/dist/storage/objectStorageConfig.test.js +13 -1
- package/dist/storage/workspaceAssetStore.d.ts +15 -3
- package/dist/storage/workspaceAssetStore.js +132 -44
- package/dist/storage/workspaceAssetStore.test.js +93 -6
- package/dist/styles/fonts.css +70 -0
- package/dist/sync/collaborationSyncPayload.d.ts +6 -1
- package/dist/sync/collaborationSyncPayload.js +19 -11
- package/dist/sync/collaborationSyncPayload.test.js +14 -1
- package/dist/sync/collaborationSyncState.d.ts +3 -3
- package/dist/sync/collaborationSyncState.js +19 -12
- package/dist/sync/contentSyncPayload.d.ts +5 -1
- package/dist/sync/contentSyncPayload.js +9 -0
- package/dist/sync/contentSyncPayload.test.js +39 -0
- package/dist/sync/contentSyncState.d.ts +9 -9
- package/dist/sync/contentSyncState.js +248 -107
- package/dist/sync/planningSyncPayload.js +5 -0
- package/dist/sync/planningSyncPayload.test.js +24 -0
- package/dist/sync/syncApplyHandlers.d.ts +11 -4
- package/dist/sync/syncApplyHandlers.js +115 -42
- package/dist/sync/syncApplyHandlers.test.js +251 -4
- package/dist/sync/syncFieldSemantics.d.ts +12 -0
- package/dist/sync/syncFieldSemantics.js +55 -0
- package/dist/sync/syncResourceAdapters.d.ts +46 -0
- package/dist/sync/syncResourceAdapters.js +79 -0
- package/dist/sync/syncService.d.ts +6 -0
- package/dist/sync/syncService.js +65 -1
- package/dist/sync/syncService.test.js +96 -3
- package/dist/sync/taskSyncChangeKey.d.ts +2 -0
- package/dist/sync/taskSyncChangeKey.js +143 -0
- package/dist/sync/taskSyncPayload.js +3 -8
- package/dist/sync/workspacePullFeed.d.ts +4 -0
- package/dist/sync/workspacePullFeed.js +132 -72
- package/dist/sync/workspacePullFeed.test.js +92 -0
- package/dist/sync/workspaceRepair.js +5 -2
- package/dist/sync/workspaceSyncModel.d.ts +73 -6
- package/dist/sync/workspaceSyncModel.js +342 -73
- package/dist/sync/workspaceSyncModel.test.js +559 -14
- package/dist/sync/workspaceSyncState.d.ts +17 -0
- package/dist/sync/workspaceSyncState.js +2 -1
- package/dist/sync/workspaceSyncSurface.js +3 -8
- package/dist/types.d.ts +50 -2
- package/dist/ui/assets/AgentsModule-2y82_3DO.js +1 -0
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-BTLZZCiQ.js +3 -0
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-BVKew-mH.css +1 -0
- package/dist/ui/assets/ContextAttachmentManager-D2epuNnG.js +3 -0
- package/dist/ui/assets/CourierPrime-Bold-BuLj_dpw.woff2 +0 -0
- package/dist/ui/assets/CourierPrime-BoldItalic-BrK2pUkZ.woff2 +0 -0
- package/dist/ui/assets/CourierPrime-Italic-DFUZK5Ey.woff2 +0 -0
- package/dist/ui/assets/CourierPrime-Regular-BsKphzVf.woff2 +0 -0
- package/dist/ui/assets/DocumentWorkspace-D4rJKXzd.css +1 -0
- package/dist/ui/assets/DocumentWorkspace-sVa-3Do6.js +252 -0
- package/dist/ui/assets/EntityActivityTimeline-DyqvvhuF.css +1 -0
- package/dist/ui/assets/EntityActivityTimeline-Zods27y_.js +1 -0
- package/dist/ui/assets/{InitiativesModule-Dhm7M8e7.js → InitiativesModule-D4XseTwW.js} +1 -1
- package/dist/ui/assets/Noir_medium-bxQwKGzB.woff2 +0 -0
- package/dist/ui/assets/Noir_regular-ojf2kxlG.woff2 +0 -0
- package/dist/ui/assets/PlansPage-D5AcbO0L.js +1 -0
- package/dist/ui/assets/PlansPage-Dvqsz5zc.css +1 -0
- package/dist/ui/assets/RussoOne-Regular-Cu_qq_qC.woff2 +0 -0
- package/dist/ui/assets/SpecialElite-Regular-Di6gSvAS.woff2 +0 -0
- package/dist/ui/assets/TaskContextUpload-uC5qx4Bv.js +1 -0
- package/dist/ui/assets/TaskSettings-CqvPAsTv.js +9 -0
- package/dist/ui/assets/{WorkflowsModule-BcS4afRn.js → WorkflowsModule-oOA9bcdK.js} +4 -4
- package/dist/ui/assets/documentReferences-DPZuTgHh.js +1 -0
- package/dist/ui/assets/index-607WPo_X.js +4 -0
- package/dist/ui/assets/index-CYyodXsg.css +1 -0
- package/dist/ui/assets/{vendor-icons-BSUaRwF8.js → vendor-icons-B32hGuF2.js} +1 -1
- package/dist/ui/fonts/CourierPrime-Bold.ttf +0 -0
- package/dist/ui/fonts/CourierPrime-Bold.woff2 +0 -0
- package/dist/ui/fonts/CourierPrime-BoldItalic.ttf +0 -0
- package/dist/ui/fonts/CourierPrime-BoldItalic.woff2 +0 -0
- package/dist/ui/fonts/CourierPrime-Italic.ttf +0 -0
- package/dist/ui/fonts/CourierPrime-Italic.woff2 +0 -0
- package/dist/ui/fonts/CourierPrime-Regular.ttf +0 -0
- package/dist/ui/fonts/CourierPrime-Regular.woff2 +0 -0
- package/dist/ui/fonts/Noir_medium.otf +0 -0
- package/dist/ui/fonts/Noir_medium.woff2 +0 -0
- package/dist/ui/fonts/Noir_regular.otf +0 -0
- package/dist/ui/fonts/Noir_regular.woff2 +0 -0
- package/dist/ui/fonts/RussoOne-Regular.woff2 +0 -0
- package/dist/ui/fonts/SpecialElite-Regular.ttf +0 -0
- package/dist/ui/fonts/SpecialElite-Regular.woff2 +0 -0
- package/dist/ui/index.html +3 -3
- package/dist/ui/product/agent manager.png +0 -0
- package/dist/ui/product/agent_manager_02.png +0 -0
- package/dist/utils/accountProfileSummaryCache.d.ts +5 -0
- package/dist/utils/aiProfileEvents.d.ts +7 -0
- package/dist/utils/aiProfileEvents.js +6 -0
- package/dist/utils/assignees.d.ts +8 -0
- package/dist/utils/assignees.js +10 -1
- package/dist/utils/assignees.test.d.ts +1 -0
- package/dist/utils/assignees.test.js +25 -0
- package/dist/utils/avatarDisplay.d.ts +1 -0
- package/dist/utils/avatarDisplay.js +15 -0
- package/dist/utils/avatarUpload.d.ts +27 -0
- package/dist/utils/avatarUpload.js +132 -0
- package/dist/utils/avatarUpload.test.d.ts +1 -0
- package/dist/utils/avatarUpload.test.js +40 -0
- package/dist/utils/bootstrapTrace.d.ts +7 -0
- package/dist/utils/bootstrapTrace.js +29 -0
- package/dist/utils/commercialLifecyclePresentation.js +3 -0
- package/dist/utils/contextAssetEvents.d.ts +2 -0
- package/dist/utils/contextFiles.d.ts +3 -1
- package/dist/utils/contextFiles.js +2 -1
- package/dist/utils/syncEventDetails.d.ts +3 -0
- package/dist/utils/syncEventDetails.js +64 -0
- package/dist/utils/syncEventDetails.test.d.ts +1 -0
- package/dist/utils/syncEventDetails.test.js +23 -0
- package/dist/utils/syncEventPresentation.d.ts +15 -0
- package/dist/utils/syncEventPresentation.js +129 -0
- package/dist/utils/syncEventPresentation.test.d.ts +1 -0
- package/dist/utils/syncEventPresentation.test.js +64 -0
- package/dist/utils/syncStatusPresentation.d.ts +72 -0
- package/dist/utils/syncStatusPresentation.js +217 -0
- package/dist/utils/syncStatusPresentation.test.d.ts +1 -0
- package/dist/utils/syncStatusPresentation.test.js +164 -0
- package/dist/utils/taskActivity.d.ts +9 -1
- package/dist/utils/taskActivity.js +290 -22
- package/dist/utils/taskActivity.test.js +141 -8
- package/dist/utils/taskSearch.d.ts +22 -0
- package/dist/utils/taskSearch.js +87 -0
- package/dist/utils/taskSearch.test.d.ts +1 -0
- package/dist/utils/taskSearch.test.js +69 -0
- package/dist/utils/taskUtils.js +10 -3
- package/dist/utils/taskUtils.test.d.ts +1 -0
- package/dist/utils/taskUtils.test.js +19 -0
- package/dist/utils/workspaceSyncPresentation.d.ts +4 -0
- package/dist/utils/workspaceSyncPresentation.js +68 -2
- package/dist/utils/workspaceSyncPresentation.test.js +36 -1
- package/package.json +3 -2
- package/scripts/export-sqlite-to-postgres.mjs +7 -9
- package/scripts/run-e2e-realtime.sh +17 -3
- package/scripts/run-smoke.sh +17 -5
- package/scripts/run-soak.sh +17 -5
- package/src/resources/templates/workflow-sources/workflowDocs.mjs +6 -6
- package/src/resources/templates/workflows/collaborate.yaml +1 -1
- package/src/resources/templates/workflows/evaluate.yaml +2 -2
- package/src/resources/templates/workflows/plan.yaml +1 -1
- package/src/resources/templates/workflows/review.yaml +2 -2
- package/dist/ui/assets/AgentsModule-N2MnQBZk.js +0 -1
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-BG6P_GVW.js +0 -3
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-BaS2VwIr.css +0 -1
- package/dist/ui/assets/DocumentWorkspace-B3nV_Gc5.css +0 -1
- package/dist/ui/assets/DocumentWorkspace-DRbDMwh8.js +0 -252
- package/dist/ui/assets/PlansPage-C2dd2n1X.css +0 -1
- package/dist/ui/assets/PlansPage-Cq0zXj3I.js +0 -1
- package/dist/ui/assets/RussoOne-Regular-C3BxZIj7.ttf +0 -0
- package/dist/ui/assets/TaskSettings-ln0aF7xc.js +0 -9
- package/dist/ui/assets/index-C2-OXZV7.css +0 -1
- package/dist/ui/assets/index-DcSI5F86.js +0 -6
- package/scripts/migrate-planning-model.ts +0 -233
|
@@ -26,57 +26,19 @@ import { useWorkspaceSyncController } from './useWorkspaceSyncController';
|
|
|
26
26
|
import { normalizeTaskforceTheme } from '../utils/theme';
|
|
27
27
|
import { useRealtimeSync } from './useRealtimeSync';
|
|
28
28
|
import { TASKFORCE_CONTEXT_ASSETS_MUTATED_EVENT } from '../utils/contextAssetEvents';
|
|
29
|
+
import { TASKFORCE_AI_PROFILES_MUTATED_EVENT } from '../utils/aiProfileEvents';
|
|
29
30
|
import { setLocale as setAppLocale } from '../localization';
|
|
30
31
|
import { normalizeTaskFromApi } from '../utils/taskNormalization.js';
|
|
32
|
+
import { normalizeSyncEventDetails } from '../utils/syncEventDetails';
|
|
31
33
|
import { createSyncAuthCoordinator } from './sync/auth';
|
|
32
34
|
import { createBootstrapTimeoutMonitor, syncBootstrapPhaseTracking } from './sync/bootstrap';
|
|
33
|
-
import {
|
|
35
|
+
import { resolvePullSyncReadiness, resolvePushSyncReadiness, resolveRetrySyncReadiness } from './sync/controlPlane';
|
|
36
|
+
import { resolveWorkspaceAutomaticPullPolicy, resolveWorkspaceSyncPresentation, shouldRunWorkspaceStartupRepair, shouldScheduleWorkspaceReactivePush, shouldStartWorkspacePeriodicFullReconcile, shouldStartWorkspacePushWatchdog, } from './sync/lifecyclePolicy';
|
|
37
|
+
import { buildPersistedSyncWatermarksSnapshot, buildTaxonomyStateFingerprint, flattenDocumentReviewComments, flattenTaskEvents, isValidWorkspaceKey, logSyncDebug, normalizeWorkspaceSyncAiProfileSnapshotEntry, parsePersistedSyncWatermarksSnapshot, readPersistedSyncWatermarks, readUserGlobalSyncMeta, savePersistedSyncWatermarks, WORKSPACE_CONCURRENT_WINDOW_MESSAGE, WORKSPACE_FULL_RECONCILE_INTERVAL_MS, writeUserGlobalSyncMeta } from './sync/orchestratorShared';
|
|
34
38
|
import { createRealtimeSyncBridge } from './sync/realtime';
|
|
35
39
|
import { createSyncRecoveryCoordinator } from './sync/recovery';
|
|
36
40
|
import { createWorkspaceTransferCoordinator } from './sync/transfers';
|
|
37
|
-
|
|
38
|
-
function summarizeSyncPhase(enabled, phase, busy, retryAt, lastErrorMessage) {
|
|
39
|
-
if (!enabled)
|
|
40
|
-
return 'Sync is turned off for this workspace.';
|
|
41
|
-
if (phase === 'provision-local') {
|
|
42
|
-
return busy
|
|
43
|
-
? 'Uploading this workspace to cloud for the first time.'
|
|
44
|
-
: 'Preparing the first upload to cloud.';
|
|
45
|
-
}
|
|
46
|
-
if (phase === 'attach-cloud') {
|
|
47
|
-
return busy
|
|
48
|
-
? 'Pulling the cloud workspace into this device.'
|
|
49
|
-
: 'Waiting for the first cloud pull into this device.';
|
|
50
|
-
}
|
|
51
|
-
if (retryAt) {
|
|
52
|
-
return 'Sync hit a temporary problem and will retry automatically.';
|
|
53
|
-
}
|
|
54
|
-
if (lastErrorMessage) {
|
|
55
|
-
return 'Sync needs attention before it can continue.';
|
|
56
|
-
}
|
|
57
|
-
if (busy) {
|
|
58
|
-
return 'Sync is currently running.';
|
|
59
|
-
}
|
|
60
|
-
return 'Sync is healthy.';
|
|
61
|
-
}
|
|
62
|
-
function recommendSyncAction(enabled, phase, retryAt, lastErrorMessage) {
|
|
63
|
-
if (!enabled) {
|
|
64
|
-
return 'Turn on sync when you are ready to back up this workspace.';
|
|
65
|
-
}
|
|
66
|
-
if (phase === 'provision-local') {
|
|
67
|
-
return 'Keep this window open while the first upload finishes. If it seems stalled, press Sync.';
|
|
68
|
-
}
|
|
69
|
-
if (phase === 'attach-cloud') {
|
|
70
|
-
return 'Keep this window open for the first cloud pull. If it does not move, press Repair.';
|
|
71
|
-
}
|
|
72
|
-
if (retryAt) {
|
|
73
|
-
return 'Wait for the automatic retry, or press Sync to retry now.';
|
|
74
|
-
}
|
|
75
|
-
if (lastErrorMessage) {
|
|
76
|
-
return 'Press Sync to retry. If the same error keeps returning, press Repair.';
|
|
77
|
-
}
|
|
78
|
-
return 'No action needed.';
|
|
79
|
-
}
|
|
41
|
+
import { aiProfileSyncResourceAdapter, taskSyncResourceAdapter } from '../sync/syncResourceAdapters.js';
|
|
80
42
|
const EMPTY_WORKSPACE_SYNC_REFERENCE_SNAPSHOT_STATUS = {
|
|
81
43
|
documents: false,
|
|
82
44
|
aiProfiles: false,
|
|
@@ -109,6 +71,7 @@ export function useSyncOrchestrator(input) {
|
|
|
109
71
|
const workspaceInitiativesRef = useRef(initiatives || []);
|
|
110
72
|
const workspaceWorkstreamsRef = useRef(workstreams || []);
|
|
111
73
|
const workspaceSyncMarkdownDocumentsRef = useRef([]);
|
|
74
|
+
const workspaceSyncKnownDocumentPathsRef = useRef(new Set());
|
|
112
75
|
const [workspaceSyncAiProfiles, setWorkspaceSyncAiProfiles] = useState([]);
|
|
113
76
|
const [workspaceSyncAiProfilesFingerprint, setWorkspaceSyncAiProfilesFingerprint] = useState('');
|
|
114
77
|
const [workspaceSyncAiProfilesLastFetchAt, setWorkspaceSyncAiProfilesLastFetchAt] = useState(null);
|
|
@@ -119,6 +82,7 @@ export function useSyncOrchestrator(input) {
|
|
|
119
82
|
const [workspaceSyncAssets, setWorkspaceSyncAssets] = useState([]);
|
|
120
83
|
const [workspaceSyncAssetsFingerprint, setWorkspaceSyncAssetsFingerprint] = useState('');
|
|
121
84
|
const workspaceSyncAssetsRef = useRef([]);
|
|
85
|
+
const workspaceSyncKnownAssetPathsRef = useRef(new Set());
|
|
122
86
|
const [workspaceSyncDocumentReviewSessions, setWorkspaceSyncDocumentReviewSessions] = useState([]);
|
|
123
87
|
const [workspaceSyncDocumentReviewSessionsFingerprint, setWorkspaceSyncDocumentReviewSessionsFingerprint] = useState('');
|
|
124
88
|
const workspaceSyncDocumentReviewSessionsRef = useRef([]);
|
|
@@ -137,6 +101,7 @@ export function useSyncOrchestrator(input) {
|
|
|
137
101
|
});
|
|
138
102
|
const userSettingsSyncInFlightRef = useRef(false);
|
|
139
103
|
const userSettingsRetryTimeoutRef = useRef(null);
|
|
104
|
+
const workspaceBaselineResetReasonRef = useRef('missing-baseline');
|
|
140
105
|
const userSettingsRetryAttemptRef = useRef(0);
|
|
141
106
|
const applyingRemoteUserSettingsRef = useRef(false);
|
|
142
107
|
const initialUserSettingsSyncCompletedRef = useRef(new Set());
|
|
@@ -150,6 +115,7 @@ export function useSyncOrchestrator(input) {
|
|
|
150
115
|
const realtimePullDebounceRef = useRef(null);
|
|
151
116
|
const realtimeSuppressedEventIdsRef = useRef(new Set());
|
|
152
117
|
const realtimeSuppressedEventQueueRef = useRef([]);
|
|
118
|
+
const workspacePendingPushReplayRef = useRef(null);
|
|
153
119
|
const retryWorkspaceSyncRef = useRef(() => Promise.resolve(false));
|
|
154
120
|
const syncUserGlobalSettingsRef = useRef(async () => { });
|
|
155
121
|
const bootstrapPhaseStartedAtRef = useRef(null);
|
|
@@ -178,73 +144,6 @@ export function useSyncOrchestrator(input) {
|
|
|
178
144
|
void syncUserGlobalSettingsRef.current({ preferCloudOnFirstSync: false });
|
|
179
145
|
}, delayMs);
|
|
180
146
|
}, [clearUserSettingsRetry]);
|
|
181
|
-
useEffect(() => {
|
|
182
|
-
workspaceSyncMarkdownDocumentsFingerprintRef.current = '';
|
|
183
|
-
workspaceSyncAiProfilesFingerprintRef.current = '';
|
|
184
|
-
workspaceSyncAssetsFingerprintRef.current = '';
|
|
185
|
-
workspaceSyncDocumentReviewSessionsFingerprintRef.current = '';
|
|
186
|
-
workspaceSyncAnnotatedAttachmentSessionsFingerprintRef.current = '';
|
|
187
|
-
workspaceAttachBootstrapBaselineSignatureRef.current = '';
|
|
188
|
-
workspaceCaptureAttachBootstrapBaselineRef.current = false;
|
|
189
|
-
setWorkspaceSyncMarkdownDocuments([]);
|
|
190
|
-
setWorkspaceSyncMarkdownDocumentsFingerprint('');
|
|
191
|
-
workspaceSyncAiProfilesRef.current = [];
|
|
192
|
-
setWorkspaceSyncAiProfiles([]);
|
|
193
|
-
setWorkspaceSyncAiProfilesFingerprint('');
|
|
194
|
-
setWorkspaceSyncAssets([]);
|
|
195
|
-
setWorkspaceSyncAssetsFingerprint('');
|
|
196
|
-
workspaceSyncDocumentReviewSessionsRef.current = [];
|
|
197
|
-
workspaceSyncDocumentReviewCommentsRef.current = [];
|
|
198
|
-
setWorkspaceSyncDocumentReviewSessions([]);
|
|
199
|
-
setWorkspaceSyncDocumentReviewSessionsFingerprint('');
|
|
200
|
-
workspaceSyncAnnotatedAttachmentSessionsRef.current = [];
|
|
201
|
-
setWorkspaceSyncAnnotatedAttachmentSessions([]);
|
|
202
|
-
setWorkspaceSyncAnnotatedAttachmentSessionsFingerprint('');
|
|
203
|
-
setWorkspaceSyncReferenceSnapshotStatus(EMPTY_WORKSPACE_SYNC_REFERENCE_SNAPSHOT_STATUS);
|
|
204
|
-
setWorkspaceLastErrorMessage(null);
|
|
205
|
-
setWorkspaceLastErrorAt(null);
|
|
206
|
-
setWorkspaceSyncPendingChanges(0);
|
|
207
|
-
realtimeSuppressedEventIdsRef.current = new Set();
|
|
208
|
-
realtimeSuppressedEventQueueRef.current = [];
|
|
209
|
-
// Reset watermarks for the new workspace, then restore from localStorage if recent
|
|
210
|
-
// enough. This prevents a full resync on every page reload while still catching any
|
|
211
|
-
// changes that happened while the app was closed.
|
|
212
|
-
workspaceLastPushedWatermarksRef.current = new Map();
|
|
213
|
-
workspaceLastPushedInitiativeIdsRef.current = new Set();
|
|
214
|
-
workspaceLastPushedInitiativeWatermarksRef.current = new Map();
|
|
215
|
-
workspaceLastPushedWorkstreamIdsRef.current = new Set();
|
|
216
|
-
workspaceLastPushedWorkstreamWatermarksRef.current = new Map();
|
|
217
|
-
workspaceLastPushedAiProfileIdsRef.current = new Set();
|
|
218
|
-
workspaceLastPushedAiProfileWatermarksRef.current = new Map();
|
|
219
|
-
workspaceLastPushedDocumentPathsRef.current = new Set();
|
|
220
|
-
workspaceLastPushedDocumentWatermarksRef.current = new Map();
|
|
221
|
-
workspaceLastPushedAssetPathsRef.current = new Set();
|
|
222
|
-
workspaceLastPushedAssetWatermarksRef.current = new Map();
|
|
223
|
-
workspaceLastPushedDocumentReviewSessionIdsRef.current = new Set();
|
|
224
|
-
workspaceLastPushedDocumentReviewSessionWatermarksRef.current = new Map();
|
|
225
|
-
workspaceLastPushedDocumentReviewCommentIdsRef.current = new Set();
|
|
226
|
-
workspaceLastPushedDocumentReviewCommentWatermarksRef.current = new Map();
|
|
227
|
-
workspaceLastPushedAnnotatedAttachmentSessionIdsRef.current = new Set();
|
|
228
|
-
workspaceLastPushedAnnotatedAttachmentSessionWatermarksRef.current = new Map();
|
|
229
|
-
workspaceLastPushedTaskEventWatermarksRef.current = new Map();
|
|
230
|
-
workspaceLastPushedAnnotatedAttachmentSessionIdsRef.current = new Set();
|
|
231
|
-
workspaceLastPushedAnnotatedAttachmentSessionWatermarksRef.current = new Map();
|
|
232
|
-
workspaceLastPushedTaskEventWatermarksRef.current = new Map();
|
|
233
|
-
workspaceStartupFullReconcileRanRef.current = false;
|
|
234
|
-
workspaceFullReconcileInFlightRef.current = false;
|
|
235
|
-
const persisted = readPersistedSyncWatermarks(currentWorkspaceId, taxonomyStateFingerprint);
|
|
236
|
-
if (persisted) {
|
|
237
|
-
workspaceLastPushedWatermarksRef.current = persisted.taskWatermarks;
|
|
238
|
-
workspaceLastPushedInitiativeWatermarksRef.current = persisted.initiativeWatermarks;
|
|
239
|
-
workspaceLastPushedWorkstreamWatermarksRef.current = persisted.workstreamWatermarks;
|
|
240
|
-
workspaceLastPushedDocumentWatermarksRef.current = persisted.documentWatermarks;
|
|
241
|
-
workspaceLastPushedAssetWatermarksRef.current = persisted.assetWatermarks;
|
|
242
|
-
workspaceLastPushedDocumentReviewSessionWatermarksRef.current = persisted.documentReviewSessionWatermarks;
|
|
243
|
-
workspaceLastPushedDocumentReviewCommentWatermarksRef.current = persisted.documentReviewCommentWatermarks;
|
|
244
|
-
workspaceLastPushedAnnotatedAttachmentSessionWatermarksRef.current = persisted.annotatedAttachmentSessionWatermarks;
|
|
245
|
-
workspaceLastPushedTaskEventWatermarksRef.current = persisted.taskEventWatermarks;
|
|
246
|
-
}
|
|
247
|
-
}, [currentWorkspaceId, taxonomyStateFingerprint]);
|
|
248
147
|
const markWorkspaceSyncReferenceSnapshotReady = useCallback((key) => {
|
|
249
148
|
setWorkspaceSyncReferenceSnapshotStatus((current) => (current[key]
|
|
250
149
|
? current
|
|
@@ -254,7 +153,7 @@ export function useSyncOrchestrator(input) {
|
|
|
254
153
|
}));
|
|
255
154
|
}, []);
|
|
256
155
|
const workspaceSyncReferenceSnapshotsReady = Object.values(workspaceSyncReferenceSnapshotStatus).every(Boolean);
|
|
257
|
-
const { workspaceRetryAt, isWorkspaceRetryPending, workspacePushInFlightRef, workspacePullInFlightRef, workspaceLastPushedSignatureRef, workspacePendingSignatureRef, workspaceLastPushedTaskIdsRef, workspaceDeletedTaskIdsRef, workspaceDeletedTaskWatermarksRef, workspacePullCursorRef, clearWorkspaceRetry, scheduleWorkspaceRetry, persistWorkspaceSyncPatch, applyWorkspaceSyncPatchLocally, loadWorkspaceSyncState, applyWorkspaceSyncStateSnapshot: applyWorkspaceSyncStateSnapshotBase, saveWorkspaceCloudSyncSettings: saveWorkspaceCloudSyncSettingsBase, acquireWorkspaceSyncLease, releaseWorkspaceSyncLease, forceClearWorkspaceSyncLease } = useWorkspaceSyncController({
|
|
156
|
+
const { workspaceRetryAt, isWorkspaceRetryPending, workspacePushInFlightRef, workspacePullInFlightRef, workspaceLastPushedSignatureRef, workspacePendingSignatureRef, workspaceLastPushedTaskIdsRef, workspaceDeletedTaskIdsRef, workspaceDeletedTaskWatermarksRef, workspacePullCursorRef, clearWorkspaceRetry, scheduleWorkspaceRetry, persistWorkspaceSyncPatch, applyWorkspaceSyncPatchLocally, readWorkspaceSyncStateSnapshot, loadWorkspaceSyncState, applyWorkspaceSyncStateSnapshot: applyWorkspaceSyncStateSnapshotBase, saveWorkspaceCloudSyncSettings: saveWorkspaceCloudSyncSettingsBase, acquireWorkspaceSyncLease, releaseWorkspaceSyncLease, forceClearWorkspaceSyncLease } = useWorkspaceSyncController({
|
|
258
157
|
currentWorkspaceId,
|
|
259
158
|
setWorkspaceCloudSyncEnabled,
|
|
260
159
|
setWorkspaceSyncPhase,
|
|
@@ -274,12 +173,14 @@ export function useSyncOrchestrator(input) {
|
|
|
274
173
|
applyWorkspaceSyncStateSnapshotBase(nextState);
|
|
275
174
|
}, [applyWorkspaceSyncStateSnapshotBase]);
|
|
276
175
|
const workspaceLastPushedWatermarksRef = useRef(new Map());
|
|
176
|
+
const workspaceLastPushedTaskChangeKeysRef = useRef(new Map());
|
|
277
177
|
const workspaceLastPushedInitiativeIdsRef = useRef(new Set());
|
|
278
178
|
const workspaceLastPushedInitiativeWatermarksRef = useRef(new Map());
|
|
279
179
|
const workspaceLastPushedWorkstreamIdsRef = useRef(new Set());
|
|
280
180
|
const workspaceLastPushedWorkstreamWatermarksRef = useRef(new Map());
|
|
281
181
|
const workspaceLastPushedAiProfileIdsRef = useRef(new Set());
|
|
282
182
|
const workspaceLastPushedAiProfileWatermarksRef = useRef(new Map());
|
|
183
|
+
const workspaceLastPushedAiProfileChangeKeysRef = useRef(new Map());
|
|
283
184
|
const workspaceLastPushedDocumentPathsRef = useRef(new Set());
|
|
284
185
|
const workspaceLastPushedDocumentWatermarksRef = useRef(new Map());
|
|
285
186
|
const workspaceLastPushedAssetPathsRef = useRef(new Set());
|
|
@@ -291,6 +192,48 @@ export function useSyncOrchestrator(input) {
|
|
|
291
192
|
const workspaceLastPushedAnnotatedAttachmentSessionIdsRef = useRef(new Set());
|
|
292
193
|
const workspaceLastPushedAnnotatedAttachmentSessionWatermarksRef = useRef(new Map());
|
|
293
194
|
const workspaceLastPushedTaskEventWatermarksRef = useRef(new Map());
|
|
195
|
+
const hydrateWorkspacePushBaselines = useCallback((persisted) => {
|
|
196
|
+
if (!persisted)
|
|
197
|
+
return false;
|
|
198
|
+
workspaceLastPushedTaskIdsRef.current = new Set(persisted.taskIds);
|
|
199
|
+
workspaceLastPushedWatermarksRef.current = persisted.taskWatermarks;
|
|
200
|
+
workspaceLastPushedTaskChangeKeysRef.current = persisted.taskChangeKeys || new Map();
|
|
201
|
+
workspaceLastPushedInitiativeIdsRef.current = new Set(Array.from(persisted.initiativeWatermarks.keys()));
|
|
202
|
+
workspaceLastPushedInitiativeWatermarksRef.current = persisted.initiativeWatermarks;
|
|
203
|
+
workspaceLastPushedWorkstreamIdsRef.current = new Set(Array.from(persisted.workstreamWatermarks.keys()));
|
|
204
|
+
workspaceLastPushedWorkstreamWatermarksRef.current = persisted.workstreamWatermarks;
|
|
205
|
+
workspaceLastPushedAiProfileIdsRef.current = new Set(Array.from(persisted.aiProfileWatermarks.keys()));
|
|
206
|
+
workspaceLastPushedAiProfileWatermarksRef.current = persisted.aiProfileWatermarks;
|
|
207
|
+
workspaceLastPushedAiProfileChangeKeysRef.current = persisted.aiProfileChangeKeys || new Map();
|
|
208
|
+
workspaceLastPushedDocumentPathsRef.current = new Set(Array.from(persisted.documentWatermarks.keys()));
|
|
209
|
+
workspaceLastPushedDocumentWatermarksRef.current = persisted.documentWatermarks;
|
|
210
|
+
workspaceLastPushedAssetPathsRef.current = new Set(Array.from(persisted.assetWatermarks.keys()));
|
|
211
|
+
workspaceLastPushedAssetWatermarksRef.current = persisted.assetWatermarks;
|
|
212
|
+
workspaceLastPushedDocumentReviewSessionIdsRef.current = new Set(Array.from(persisted.documentReviewSessionWatermarks.keys()));
|
|
213
|
+
workspaceLastPushedDocumentReviewSessionWatermarksRef.current = persisted.documentReviewSessionWatermarks;
|
|
214
|
+
workspaceLastPushedDocumentReviewCommentIdsRef.current = new Set(Array.from(persisted.documentReviewCommentWatermarks.keys()));
|
|
215
|
+
workspaceLastPushedDocumentReviewCommentWatermarksRef.current = persisted.documentReviewCommentWatermarks;
|
|
216
|
+
workspaceLastPushedAnnotatedAttachmentSessionIdsRef.current = new Set(Array.from(persisted.annotatedAttachmentSessionWatermarks.keys()));
|
|
217
|
+
workspaceLastPushedAnnotatedAttachmentSessionWatermarksRef.current = persisted.annotatedAttachmentSessionWatermarks;
|
|
218
|
+
workspaceLastPushedTaskEventWatermarksRef.current = persisted.taskEventWatermarks;
|
|
219
|
+
workspaceBaselineResetReasonRef.current = null;
|
|
220
|
+
return true;
|
|
221
|
+
}, [workspaceLastPushedTaskIdsRef]);
|
|
222
|
+
const buildCurrentPersistedWorkspaceSyncWatermarks = useCallback(() => ({
|
|
223
|
+
taskIds: workspaceLastPushedTaskIdsRef.current,
|
|
224
|
+
taskWatermarks: workspaceLastPushedWatermarksRef.current,
|
|
225
|
+
taskChangeKeys: workspaceLastPushedTaskChangeKeysRef.current,
|
|
226
|
+
initiativeWatermarks: workspaceLastPushedInitiativeWatermarksRef.current,
|
|
227
|
+
workstreamWatermarks: workspaceLastPushedWorkstreamWatermarksRef.current,
|
|
228
|
+
aiProfileWatermarks: workspaceLastPushedAiProfileWatermarksRef.current,
|
|
229
|
+
aiProfileChangeKeys: workspaceLastPushedAiProfileChangeKeysRef.current,
|
|
230
|
+
documentWatermarks: workspaceLastPushedDocumentWatermarksRef.current,
|
|
231
|
+
assetWatermarks: workspaceLastPushedAssetWatermarksRef.current,
|
|
232
|
+
documentReviewSessionWatermarks: workspaceLastPushedDocumentReviewSessionWatermarksRef.current,
|
|
233
|
+
documentReviewCommentWatermarks: workspaceLastPushedDocumentReviewCommentWatermarksRef.current,
|
|
234
|
+
annotatedAttachmentSessionWatermarks: workspaceLastPushedAnnotatedAttachmentSessionWatermarksRef.current,
|
|
235
|
+
taskEventWatermarks: workspaceLastPushedTaskEventWatermarksRef.current,
|
|
236
|
+
}), []);
|
|
294
237
|
const workspaceStartupRepairRanRef = useRef(false);
|
|
295
238
|
const workspaceStartupFullReconcileRanRef = useRef(false);
|
|
296
239
|
const workspaceRepairModeRef = useRef(false);
|
|
@@ -311,36 +254,22 @@ export function useSyncOrchestrator(input) {
|
|
|
311
254
|
return workspaceLastPushAt;
|
|
312
255
|
return null;
|
|
313
256
|
}, [workspaceLastPullAt, workspaceLastPushAt]);
|
|
314
|
-
const
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
return 'attention';
|
|
322
|
-
}
|
|
323
|
-
return 'healthy';
|
|
324
|
-
}, [
|
|
325
|
-
workspaceCloudSyncEnabled,
|
|
326
|
-
workspaceSyncBusy,
|
|
327
|
-
workspaceSyncPhase,
|
|
328
|
-
workspaceRetryAt,
|
|
329
|
-
workspaceLastErrorMessage
|
|
330
|
-
]);
|
|
331
|
-
const workspaceSyncSummary = useMemo(() => summarizeSyncPhase(workspaceCloudSyncEnabled, workspaceSyncPhase, workspaceSyncBusy, workspaceRetryAt, workspaceLastErrorMessage), [
|
|
257
|
+
const workspaceSyncPresentation = useMemo(() => resolveWorkspaceSyncPresentation({
|
|
258
|
+
enabled: workspaceCloudSyncEnabled,
|
|
259
|
+
phase: workspaceSyncPhase,
|
|
260
|
+
busy: workspaceSyncBusy,
|
|
261
|
+
retryAt: workspaceRetryAt,
|
|
262
|
+
lastErrorMessage: workspaceLastErrorMessage
|
|
263
|
+
}), [
|
|
332
264
|
workspaceCloudSyncEnabled,
|
|
333
265
|
workspaceSyncPhase,
|
|
334
266
|
workspaceSyncBusy,
|
|
335
267
|
workspaceRetryAt,
|
|
336
268
|
workspaceLastErrorMessage
|
|
337
269
|
]);
|
|
338
|
-
const
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
workspaceRetryAt,
|
|
342
|
-
workspaceLastErrorMessage
|
|
343
|
-
]);
|
|
270
|
+
const workspaceSyncStatus = workspaceSyncPresentation.status;
|
|
271
|
+
const workspaceSyncSummary = workspaceSyncPresentation.summary;
|
|
272
|
+
const workspaceSyncRecommendedAction = workspaceSyncPresentation.recommendedAction;
|
|
344
273
|
const getLocalUserSyncUpdatedAt = useCallback((userId) => {
|
|
345
274
|
const key = String(userId || '').trim();
|
|
346
275
|
if (!key)
|
|
@@ -531,6 +460,102 @@ export function useSyncOrchestrator(input) {
|
|
|
531
460
|
const persistWorkspaceSyncPatchSafely = useCallback((patch) => {
|
|
532
461
|
void persistWorkspaceSyncPatchBestEffort(patch).catch(() => { });
|
|
533
462
|
}, [persistWorkspaceSyncPatchBestEffort]);
|
|
463
|
+
const persistWorkspaceSyncWatermarksSnapshotBestEffort = useCallback(() => {
|
|
464
|
+
const snapshotData = {
|
|
465
|
+
...buildCurrentPersistedWorkspaceSyncWatermarks(),
|
|
466
|
+
taxonomyStateFingerprint
|
|
467
|
+
};
|
|
468
|
+
const persisted = savePersistedSyncWatermarks(currentWorkspaceId, snapshotData);
|
|
469
|
+
void persistWorkspaceSyncPatchBestEffort({
|
|
470
|
+
pushBaseline: buildPersistedSyncWatermarksSnapshot(snapshotData)
|
|
471
|
+
}).catch(() => { });
|
|
472
|
+
return persisted;
|
|
473
|
+
}, [
|
|
474
|
+
buildCurrentPersistedWorkspaceSyncWatermarks,
|
|
475
|
+
currentWorkspaceId,
|
|
476
|
+
persistWorkspaceSyncPatchBestEffort,
|
|
477
|
+
taxonomyStateFingerprint
|
|
478
|
+
]);
|
|
479
|
+
useEffect(() => {
|
|
480
|
+
workspaceSyncMarkdownDocumentsFingerprintRef.current = '';
|
|
481
|
+
workspaceSyncAiProfilesFingerprintRef.current = '';
|
|
482
|
+
workspaceSyncAssetsFingerprintRef.current = '';
|
|
483
|
+
workspaceSyncDocumentReviewSessionsFingerprintRef.current = '';
|
|
484
|
+
workspaceSyncAnnotatedAttachmentSessionsFingerprintRef.current = '';
|
|
485
|
+
workspaceAttachBootstrapBaselineSignatureRef.current = '';
|
|
486
|
+
workspaceCaptureAttachBootstrapBaselineRef.current = false;
|
|
487
|
+
setWorkspaceSyncMarkdownDocuments([]);
|
|
488
|
+
setWorkspaceSyncMarkdownDocumentsFingerprint('');
|
|
489
|
+
workspaceSyncAiProfilesRef.current = [];
|
|
490
|
+
setWorkspaceSyncAiProfiles([]);
|
|
491
|
+
setWorkspaceSyncAiProfilesFingerprint('');
|
|
492
|
+
setWorkspaceSyncAssets([]);
|
|
493
|
+
setWorkspaceSyncAssetsFingerprint('');
|
|
494
|
+
workspaceSyncDocumentReviewSessionsRef.current = [];
|
|
495
|
+
workspaceSyncDocumentReviewCommentsRef.current = [];
|
|
496
|
+
setWorkspaceSyncDocumentReviewSessions([]);
|
|
497
|
+
setWorkspaceSyncDocumentReviewSessionsFingerprint('');
|
|
498
|
+
workspaceSyncAnnotatedAttachmentSessionsRef.current = [];
|
|
499
|
+
setWorkspaceSyncAnnotatedAttachmentSessions([]);
|
|
500
|
+
setWorkspaceSyncAnnotatedAttachmentSessionsFingerprint('');
|
|
501
|
+
setWorkspaceSyncReferenceSnapshotStatus(EMPTY_WORKSPACE_SYNC_REFERENCE_SNAPSHOT_STATUS);
|
|
502
|
+
setWorkspaceLastErrorMessage(null);
|
|
503
|
+
setWorkspaceLastErrorAt(null);
|
|
504
|
+
setWorkspaceSyncPendingChanges(0);
|
|
505
|
+
realtimeSuppressedEventIdsRef.current = new Set();
|
|
506
|
+
realtimeSuppressedEventQueueRef.current = [];
|
|
507
|
+
// Reset watermarks for the new workspace, then restore from localStorage if recent
|
|
508
|
+
// enough. This prevents a full resync on every page reload while still catching any
|
|
509
|
+
// changes that happened while the app was closed.
|
|
510
|
+
workspaceLastPushedWatermarksRef.current = new Map();
|
|
511
|
+
workspaceLastPushedTaskChangeKeysRef.current = new Map();
|
|
512
|
+
workspaceLastPushedInitiativeIdsRef.current = new Set();
|
|
513
|
+
workspaceLastPushedInitiativeWatermarksRef.current = new Map();
|
|
514
|
+
workspaceLastPushedWorkstreamIdsRef.current = new Set();
|
|
515
|
+
workspaceLastPushedWorkstreamWatermarksRef.current = new Map();
|
|
516
|
+
workspaceLastPushedAiProfileIdsRef.current = new Set();
|
|
517
|
+
workspaceLastPushedAiProfileWatermarksRef.current = new Map();
|
|
518
|
+
workspaceLastPushedAiProfileChangeKeysRef.current = new Map();
|
|
519
|
+
workspaceLastPushedDocumentPathsRef.current = new Set();
|
|
520
|
+
workspaceLastPushedDocumentWatermarksRef.current = new Map();
|
|
521
|
+
workspaceLastPushedAssetPathsRef.current = new Set();
|
|
522
|
+
workspaceLastPushedAssetWatermarksRef.current = new Map();
|
|
523
|
+
workspaceLastPushedDocumentReviewSessionIdsRef.current = new Set();
|
|
524
|
+
workspaceLastPushedDocumentReviewSessionWatermarksRef.current = new Map();
|
|
525
|
+
workspaceLastPushedDocumentReviewCommentIdsRef.current = new Set();
|
|
526
|
+
workspaceLastPushedDocumentReviewCommentWatermarksRef.current = new Map();
|
|
527
|
+
workspaceLastPushedAnnotatedAttachmentSessionIdsRef.current = new Set();
|
|
528
|
+
workspaceLastPushedAnnotatedAttachmentSessionWatermarksRef.current = new Map();
|
|
529
|
+
workspaceLastPushedTaskEventWatermarksRef.current = new Map();
|
|
530
|
+
workspaceStartupFullReconcileRanRef.current = false;
|
|
531
|
+
workspaceFullReconcileInFlightRef.current = false;
|
|
532
|
+
const persisted = readPersistedSyncWatermarks(currentWorkspaceId, taxonomyStateFingerprint);
|
|
533
|
+
if (!hydrateWorkspacePushBaselines(persisted)) {
|
|
534
|
+
workspaceBaselineResetReasonRef.current = 'missing-baseline';
|
|
535
|
+
}
|
|
536
|
+
}, [currentWorkspaceId, hydrateWorkspacePushBaselines, taxonomyStateFingerprint]);
|
|
537
|
+
useEffect(() => {
|
|
538
|
+
if (workspaceBaselineResetReasonRef.current !== 'missing-baseline')
|
|
539
|
+
return;
|
|
540
|
+
const persistedLocal = readPersistedSyncWatermarks(currentWorkspaceId, taxonomyStateFingerprint);
|
|
541
|
+
if (hydrateWorkspacePushBaselines(persistedLocal))
|
|
542
|
+
return;
|
|
543
|
+
const persistedRemote = parsePersistedSyncWatermarksSnapshot(readWorkspaceSyncStateSnapshot().pushBaseline, taxonomyStateFingerprint);
|
|
544
|
+
if (!hydrateWorkspacePushBaselines(persistedRemote))
|
|
545
|
+
return;
|
|
546
|
+
savePersistedSyncWatermarks(currentWorkspaceId, {
|
|
547
|
+
...buildCurrentPersistedWorkspaceSyncWatermarks(),
|
|
548
|
+
taxonomyStateFingerprint
|
|
549
|
+
});
|
|
550
|
+
}, [
|
|
551
|
+
buildCurrentPersistedWorkspaceSyncWatermarks,
|
|
552
|
+
currentWorkspaceId,
|
|
553
|
+
hydrateWorkspacePushBaselines,
|
|
554
|
+
readWorkspaceSyncStateSnapshot,
|
|
555
|
+
taxonomyStateFingerprint,
|
|
556
|
+
workspaceCloudSyncEnabled,
|
|
557
|
+
workspaceSyncPhase
|
|
558
|
+
]);
|
|
534
559
|
const scheduleWorkspaceSyncRetry = useCallback((minDelayMs) => {
|
|
535
560
|
scheduleWorkspaceRetry(() => retryWorkspaceSyncRef.current(), { minDelayMs });
|
|
536
561
|
}, [scheduleWorkspaceRetry]);
|
|
@@ -592,13 +617,16 @@ export function useSyncOrchestrator(input) {
|
|
|
592
617
|
workspaceArchivedTasksRef.current = archivedTasks || [];
|
|
593
618
|
}, [archivedTasks]);
|
|
594
619
|
useEffect(() => {
|
|
620
|
+
workspaceDeletedTaskIdsRef.current = new Set((deletedTasks || [])
|
|
621
|
+
.map((entry) => String(entry?.taskId || '').trim())
|
|
622
|
+
.filter((taskId) => taskId.length > 0));
|
|
595
623
|
workspaceDeletedTaskWatermarksRef.current = new Map((deletedTasks || [])
|
|
596
624
|
.map((entry) => [
|
|
597
625
|
String(entry?.taskId || '').trim(),
|
|
598
626
|
String(entry?.deletedAt || '').trim()
|
|
599
627
|
])
|
|
600
628
|
.filter(([taskId, deletedAt]) => taskId.length > 0 && Number.isFinite(Date.parse(deletedAt))));
|
|
601
|
-
}, [deletedTasks, workspaceDeletedTaskWatermarksRef]);
|
|
629
|
+
}, [deletedTasks, workspaceDeletedTaskIdsRef, workspaceDeletedTaskWatermarksRef]);
|
|
602
630
|
useEffect(() => {
|
|
603
631
|
workspaceInitiativesRef.current = initiatives || [];
|
|
604
632
|
}, [initiatives]);
|
|
@@ -615,7 +643,7 @@ export function useSyncOrchestrator(input) {
|
|
|
615
643
|
return buildWorkspaceSyncPayloadModel({
|
|
616
644
|
tasks: workspaceTasksRef.current,
|
|
617
645
|
archivedTasks: workspaceArchivedTasksRef.current,
|
|
618
|
-
taskEvents: flattenTaskEvents(workspaceTasksRef.current, workspaceArchivedTasksRef.current),
|
|
646
|
+
taskEvents: flattenTaskEvents(workspaceTasksRef.current, workspaceArchivedTasksRef.current, workspaceInitiativesRef.current, workspaceWorkstreamsRef.current),
|
|
619
647
|
lastPushedTaskIds: workspaceLastPushedTaskIdsRef.current,
|
|
620
648
|
pendingDeletedTaskIds: workspaceDeletedTaskIdsRef.current,
|
|
621
649
|
pendingDeletedTaskWatermarks: workspaceDeletedTaskWatermarksRef.current,
|
|
@@ -630,8 +658,11 @@ export function useSyncOrchestrator(input) {
|
|
|
630
658
|
aiProfiles: workspaceSyncAiProfilesRef.current,
|
|
631
659
|
lastPushedAiProfileIds: forceAllAiProfiles ? new Set() : workspaceLastPushedAiProfileIdsRef.current,
|
|
632
660
|
lastPushedAiProfileWatermarks: forceAllAiProfiles ? new Map() : workspaceLastPushedAiProfileWatermarksRef.current,
|
|
661
|
+
lastPushedAiProfileChangeKeys: forceAllAiProfiles ? new Map() : workspaceLastPushedAiProfileChangeKeysRef.current,
|
|
633
662
|
documents: workspaceSyncMarkdownDocumentsRef.current,
|
|
634
663
|
assets: workspaceSyncAssetsRef.current,
|
|
664
|
+
currentDocumentPaths: workspaceSyncKnownDocumentPathsRef.current,
|
|
665
|
+
currentAssetPaths: workspaceSyncKnownAssetPathsRef.current,
|
|
635
666
|
documentReviewSessions: workspaceSyncDocumentReviewSessionsRef.current,
|
|
636
667
|
documentReviewComments: workspaceSyncDocumentReviewCommentsRef.current,
|
|
637
668
|
annotatedAttachmentSessions: workspaceSyncAnnotatedAttachmentSessionsRef.current,
|
|
@@ -646,25 +677,42 @@ export function useSyncOrchestrator(input) {
|
|
|
646
677
|
lastPushedAnnotatedAttachmentSessionIds: workspaceLastPushedAnnotatedAttachmentSessionIdsRef.current,
|
|
647
678
|
lastPushedAnnotatedAttachmentSessionWatermarks: workspaceLastPushedAnnotatedAttachmentSessionWatermarksRef.current,
|
|
648
679
|
lastPushedTaskEventWatermarks: workspaceLastPushedTaskEventWatermarksRef.current,
|
|
649
|
-
|
|
680
|
+
baselineResetReason: workspaceBaselineResetReasonRef.current,
|
|
681
|
+
lastPushedWatermarks: workspaceLastPushedWatermarksRef.current,
|
|
682
|
+
lastPushedTaskChangeKeys: workspaceLastPushedTaskChangeKeysRef.current
|
|
650
683
|
});
|
|
651
684
|
}, [taxonomies, taxonomyState]);
|
|
652
685
|
const reportSyncEvent = useCallback((workspaceId, event) => {
|
|
653
686
|
if (runtimeMode !== 'local')
|
|
654
687
|
return;
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
688
|
+
try {
|
|
689
|
+
const normalizedEvent = {
|
|
690
|
+
...event,
|
|
691
|
+
workspaceId,
|
|
692
|
+
details: normalizeSyncEventDetails(event.details)
|
|
693
|
+
};
|
|
694
|
+
void fetch('/api/taskforce/sync/events', {
|
|
695
|
+
method: 'POST',
|
|
696
|
+
credentials: 'include',
|
|
697
|
+
headers: { 'Content-Type': 'application/json' },
|
|
698
|
+
body: JSON.stringify(normalizedEvent)
|
|
699
|
+
}).catch((error) => {
|
|
700
|
+
logSyncDebug('sync_event_post_failed', {
|
|
701
|
+
workspaceId,
|
|
702
|
+
eventType: event.eventType,
|
|
703
|
+
status: event.status,
|
|
704
|
+
error: String(error?.message || error || '')
|
|
705
|
+
});
|
|
706
|
+
});
|
|
707
|
+
}
|
|
708
|
+
catch (error) {
|
|
661
709
|
logSyncDebug('sync_event_post_failed', {
|
|
662
710
|
workspaceId,
|
|
663
711
|
eventType: event.eventType,
|
|
664
712
|
status: event.status,
|
|
665
713
|
error: String(error?.message || error || '')
|
|
666
714
|
});
|
|
667
|
-
}
|
|
715
|
+
}
|
|
668
716
|
}, [runtimeMode]);
|
|
669
717
|
const buildWorkspaceSyncSignature = useCallback(() => {
|
|
670
718
|
// Read documents and assets from refs for the same stale-closure reason as
|
|
@@ -673,7 +721,7 @@ export function useSyncOrchestrator(input) {
|
|
|
673
721
|
workspaceId: currentWorkspaceId,
|
|
674
722
|
tasks: workspaceTasksRef.current,
|
|
675
723
|
archivedTasks: workspaceArchivedTasksRef.current,
|
|
676
|
-
taskEvents: flattenTaskEvents(workspaceTasksRef.current, workspaceArchivedTasksRef.current),
|
|
724
|
+
taskEvents: flattenTaskEvents(workspaceTasksRef.current, workspaceArchivedTasksRef.current, workspaceInitiativesRef.current, workspaceWorkstreamsRef.current),
|
|
677
725
|
pendingDeletedTaskIds: workspaceDeletedTaskIdsRef.current,
|
|
678
726
|
initiatives: workspaceInitiativesRef.current,
|
|
679
727
|
workstreams: workspaceWorkstreamsRef.current,
|
|
@@ -720,17 +768,25 @@ export function useSyncOrchestrator(input) {
|
|
|
720
768
|
isArchived: Boolean(workstream.isArchived)
|
|
721
769
|
}))
|
|
722
770
|
.sort((left, right) => left.id.localeCompare(right.id)),
|
|
723
|
-
taskEvents: flattenTaskEvents(tasks || [], archivedTasks || [])
|
|
771
|
+
taskEvents: flattenTaskEvents(tasks || [], archivedTasks || [], initiatives || [], workstreams || [])
|
|
724
772
|
.map((event) => ({
|
|
725
773
|
id: String(event.id || '').trim(),
|
|
726
|
-
|
|
774
|
+
entityType: String(event.entityType || 'task').trim(),
|
|
775
|
+
entityId: String(event.entityId || event.taskId || '').trim(),
|
|
727
776
|
createdAt: String(event.createdAt || '').trim(),
|
|
728
777
|
action: String(event.action || '').trim(),
|
|
729
778
|
}))
|
|
730
779
|
.sort((left, right) => left.id.localeCompare(right.id)),
|
|
780
|
+
deletedTasks: (deletedTasks || [])
|
|
781
|
+
.map((entry) => ({
|
|
782
|
+
taskId: String(entry?.taskId || '').trim(),
|
|
783
|
+
deletedAt: String(entry?.deletedAt || '').trim()
|
|
784
|
+
}))
|
|
785
|
+
.filter((entry) => entry.taskId.length > 0 && Number.isFinite(Date.parse(entry.deletedAt)))
|
|
786
|
+
.sort((left, right) => left.taskId.localeCompare(right.taskId)),
|
|
731
787
|
taxonomies: Array.isArray(taxonomies) ? taxonomies : [],
|
|
732
788
|
taxonomyState: taxonomyState && typeof taxonomyState === 'object' ? taxonomyState : null
|
|
733
|
-
}), [tasks, archivedTasks, initiatives, workstreams, taxonomies, taxonomyState]);
|
|
789
|
+
}), [tasks, archivedTasks, deletedTasks, initiatives, workstreams, taxonomies, taxonomyState]);
|
|
734
790
|
// Fingerprint of per-task attachment counts — changes when the MCP tool saves a new
|
|
735
791
|
// attachment and the React app polls the updated task. Used to trigger an immediate
|
|
736
792
|
// asset snapshot refresh without requiring a cross-process DOM event.
|
|
@@ -797,6 +853,11 @@ export function useSyncOrchestrator(input) {
|
|
|
797
853
|
}))
|
|
798
854
|
.filter((entry) => entry.path.length > 0)
|
|
799
855
|
: [];
|
|
856
|
+
const knownDocumentPaths = new Set(Array.isArray(data?.knownPaths)
|
|
857
|
+
? data.knownPaths
|
|
858
|
+
.map((entry) => String(entry || '').trim())
|
|
859
|
+
.filter((entry) => entry.length > 0)
|
|
860
|
+
: docs.map((entry) => entry.path));
|
|
800
861
|
const fingerprint = typeof data?.fingerprint === 'string'
|
|
801
862
|
? data.fingerprint
|
|
802
863
|
: JSON.stringify(docs.map((entry) => `${entry.path}:${entry.updatedAt}:${entry.content.length}`).sort());
|
|
@@ -804,6 +865,7 @@ export function useSyncOrchestrator(input) {
|
|
|
804
865
|
return;
|
|
805
866
|
workspaceSyncMarkdownDocumentsFingerprintRef.current = fingerprint;
|
|
806
867
|
workspaceSyncMarkdownDocumentsRef.current = docs;
|
|
868
|
+
workspaceSyncKnownDocumentPathsRef.current = knownDocumentPaths;
|
|
807
869
|
setWorkspaceSyncMarkdownDocuments(docs);
|
|
808
870
|
setWorkspaceSyncMarkdownDocumentsFingerprint(fingerprint);
|
|
809
871
|
}
|
|
@@ -853,7 +915,16 @@ export function useSyncOrchestrator(input) {
|
|
|
853
915
|
setWorkspaceSyncAiProfilesLastFetchAt(new Date().toISOString());
|
|
854
916
|
const fingerprint = typeof data?.fingerprint === 'string'
|
|
855
917
|
? data.fingerprint
|
|
856
|
-
: JSON.stringify(aiProfiles.map((entry) =>
|
|
918
|
+
: JSON.stringify(aiProfiles.map((entry) => [
|
|
919
|
+
entry.id,
|
|
920
|
+
entry.updatedAt,
|
|
921
|
+
entry.name,
|
|
922
|
+
entry.username,
|
|
923
|
+
entry.archivedAt ?? '',
|
|
924
|
+
entry.archivedReason ?? '',
|
|
925
|
+
entry.mergedIntoProfileId ?? '',
|
|
926
|
+
entry.rosterStateUpdatedAt ?? ''
|
|
927
|
+
].join(':')).sort());
|
|
857
928
|
if (fingerprint === workspaceSyncAiProfilesFingerprintRef.current)
|
|
858
929
|
return;
|
|
859
930
|
workspaceSyncAiProfilesFingerprintRef.current = fingerprint;
|
|
@@ -910,6 +981,11 @@ export function useSyncOrchestrator(input) {
|
|
|
910
981
|
}))
|
|
911
982
|
.filter((entry) => entry.path.length > 0 && entry.contentBase64.length > 0)
|
|
912
983
|
: [];
|
|
984
|
+
const knownAssetPaths = new Set(Array.isArray(data?.knownPaths)
|
|
985
|
+
? data.knownPaths
|
|
986
|
+
.map((entry) => String(entry || '').trim())
|
|
987
|
+
.filter((entry) => entry.length > 0)
|
|
988
|
+
: assets.map((entry) => entry.path));
|
|
913
989
|
const fingerprint = typeof data?.fingerprint === 'string'
|
|
914
990
|
? data.fingerprint
|
|
915
991
|
: JSON.stringify(assets.map((entry) => `${entry.path}:${entry.updatedAt}:${entry.contentBase64.length}`).sort());
|
|
@@ -917,6 +993,7 @@ export function useSyncOrchestrator(input) {
|
|
|
917
993
|
return;
|
|
918
994
|
workspaceSyncAssetsFingerprintRef.current = fingerprint;
|
|
919
995
|
workspaceSyncAssetsRef.current = assets;
|
|
996
|
+
workspaceSyncKnownAssetPathsRef.current = knownAssetPaths;
|
|
920
997
|
setWorkspaceSyncAssets(assets);
|
|
921
998
|
setWorkspaceSyncAssetsFingerprint(fingerprint);
|
|
922
999
|
}
|
|
@@ -930,6 +1007,37 @@ export function useSyncOrchestrator(input) {
|
|
|
930
1007
|
markWorkspaceSyncReferenceSnapshotReady('assets');
|
|
931
1008
|
}
|
|
932
1009
|
}, [runtimeMode, currentWorkspaceId, cloudAuthConfigured, authSessionResolved, isAuthenticated, markWorkspaceSyncReferenceSnapshotReady]);
|
|
1010
|
+
const refreshWorkspaceSyncPlanningEntitiesSnapshot = useCallback(async () => {
|
|
1011
|
+
if (runtimeMode !== 'local')
|
|
1012
|
+
return;
|
|
1013
|
+
if (!isValidWorkspaceKey(currentWorkspaceId))
|
|
1014
|
+
return;
|
|
1015
|
+
if (cloudAuthConfigured && (!authSessionResolved || !isAuthenticated))
|
|
1016
|
+
return;
|
|
1017
|
+
try {
|
|
1018
|
+
const res = await fetch(`/api/taskforce/planning/bootstrap?workspaceId=${encodeURIComponent(currentWorkspaceId)}`, {
|
|
1019
|
+
method: 'GET',
|
|
1020
|
+
credentials: 'include'
|
|
1021
|
+
});
|
|
1022
|
+
if (!res.ok)
|
|
1023
|
+
return;
|
|
1024
|
+
const data = await res.json().catch(() => ({}));
|
|
1025
|
+
const nextInitiatives = Array.isArray(data?.initiatives)
|
|
1026
|
+
? data.initiatives.filter((entry) => (Boolean(entry && typeof entry === 'object' && typeof entry.id === 'string')))
|
|
1027
|
+
: [];
|
|
1028
|
+
const nextWorkstreams = Array.isArray(data?.workstreams)
|
|
1029
|
+
? data.workstreams.filter((entry) => (Boolean(entry && typeof entry === 'object' && typeof entry.id === 'string')))
|
|
1030
|
+
: [];
|
|
1031
|
+
workspaceInitiativesRef.current = nextInitiatives;
|
|
1032
|
+
workspaceWorkstreamsRef.current = nextWorkstreams;
|
|
1033
|
+
}
|
|
1034
|
+
catch (error) {
|
|
1035
|
+
logSyncDebug('planning_snapshot_refresh_failed', {
|
|
1036
|
+
workspaceId: currentWorkspaceId,
|
|
1037
|
+
error: String(error?.message || error || '')
|
|
1038
|
+
});
|
|
1039
|
+
}
|
|
1040
|
+
}, [runtimeMode, currentWorkspaceId, cloudAuthConfigured, authSessionResolved, isAuthenticated]);
|
|
933
1041
|
const refreshWorkspaceSyncDocumentReviewSessionsSnapshot = useCallback(async () => {
|
|
934
1042
|
if (runtimeMode !== 'local')
|
|
935
1043
|
return;
|
|
@@ -1059,6 +1167,38 @@ export function useSyncOrchestrator(input) {
|
|
|
1059
1167
|
}
|
|
1060
1168
|
}, [runtimeMode, currentWorkspaceId, cloudAuthConfigured, authSessionResolved, isAuthenticated, markWorkspaceSyncReferenceSnapshotReady]);
|
|
1061
1169
|
const seedWorkspaceSnapshotPushBaseline = useCallback(() => {
|
|
1170
|
+
workspaceLastPushedTaskIdsRef.current = new Set([...workspaceTasksRef.current, ...workspaceArchivedTasksRef.current]
|
|
1171
|
+
.map((entry) => String(entry?.id || '').trim())
|
|
1172
|
+
.filter((id) => id.length > 0));
|
|
1173
|
+
workspaceLastPushedWatermarksRef.current = new Map([...workspaceTasksRef.current, ...workspaceArchivedTasksRef.current]
|
|
1174
|
+
.map((entry) => [String(entry?.id || '').trim(), taskSyncResourceAdapter.getWatermark(entry)])
|
|
1175
|
+
.filter(([id]) => id.length > 0));
|
|
1176
|
+
workspaceLastPushedTaskChangeKeysRef.current = new Map([
|
|
1177
|
+
...workspaceTasksRef.current.map((entry) => [String(entry?.id || '').trim(), taskSyncResourceAdapter.getChangeKey({ ...entry, isArchived: false })]),
|
|
1178
|
+
...workspaceArchivedTasksRef.current.map((entry) => [String(entry?.id || '').trim(), taskSyncResourceAdapter.getChangeKey({ ...entry, isArchived: true })])
|
|
1179
|
+
]
|
|
1180
|
+
.filter(([id]) => id.length > 0));
|
|
1181
|
+
workspaceLastPushedInitiativeIdsRef.current = new Set(workspaceInitiativesRef.current
|
|
1182
|
+
.map((entry) => String(entry?.id || '').trim())
|
|
1183
|
+
.filter((id) => id.length > 0));
|
|
1184
|
+
workspaceLastPushedInitiativeWatermarksRef.current = new Map(workspaceInitiativesRef.current
|
|
1185
|
+
.map((entry) => [String(entry?.id || '').trim(), String(entry?.updatedAt || entry?.createdAt || '').trim()])
|
|
1186
|
+
.filter(([id]) => id.length > 0));
|
|
1187
|
+
workspaceLastPushedWorkstreamIdsRef.current = new Set(workspaceWorkstreamsRef.current
|
|
1188
|
+
.map((entry) => String(entry?.id || '').trim())
|
|
1189
|
+
.filter((id) => id.length > 0));
|
|
1190
|
+
workspaceLastPushedWorkstreamWatermarksRef.current = new Map(workspaceWorkstreamsRef.current
|
|
1191
|
+
.map((entry) => [String(entry?.id || '').trim(), String(entry?.updatedAt || entry?.createdAt || '').trim()])
|
|
1192
|
+
.filter(([id]) => id.length > 0));
|
|
1193
|
+
workspaceLastPushedAiProfileIdsRef.current = new Set(workspaceSyncAiProfilesRef.current
|
|
1194
|
+
.map((entry) => String(entry?.id || '').trim())
|
|
1195
|
+
.filter((id) => id.length > 0));
|
|
1196
|
+
workspaceLastPushedAiProfileWatermarksRef.current = new Map(workspaceSyncAiProfilesRef.current
|
|
1197
|
+
.map((entry) => [String(entry?.id || '').trim(), aiProfileSyncResourceAdapter.getWatermark(entry)])
|
|
1198
|
+
.filter(([id]) => id.length > 0));
|
|
1199
|
+
workspaceLastPushedAiProfileChangeKeysRef.current = new Map(workspaceSyncAiProfilesRef.current
|
|
1200
|
+
.map((entry) => [String(entry?.id || '').trim(), aiProfileSyncResourceAdapter.getChangeKey(entry)])
|
|
1201
|
+
.filter(([id]) => id.length > 0));
|
|
1062
1202
|
workspaceLastPushedDocumentPathsRef.current = new Set(workspaceSyncMarkdownDocumentsRef.current
|
|
1063
1203
|
.map((entry) => String(entry?.path || '').trim())
|
|
1064
1204
|
.filter((path) => path.length > 0));
|
|
@@ -1089,10 +1229,12 @@ export function useSyncOrchestrator(input) {
|
|
|
1089
1229
|
workspaceLastPushedAnnotatedAttachmentSessionWatermarksRef.current = new Map(workspaceSyncAnnotatedAttachmentSessionsRef.current
|
|
1090
1230
|
.map((entry) => [String(entry?.id || '').trim(), String(entry?.updatedAt || entry?.createdAt || '').trim()])
|
|
1091
1231
|
.filter(([id]) => id.length > 0));
|
|
1092
|
-
workspaceLastPushedTaskEventWatermarksRef.current = new Map(flattenTaskEvents(workspaceTasksRef.current, workspaceArchivedTasksRef.current)
|
|
1232
|
+
workspaceLastPushedTaskEventWatermarksRef.current = new Map(flattenTaskEvents(workspaceTasksRef.current, workspaceArchivedTasksRef.current, workspaceInitiativesRef.current, workspaceWorkstreamsRef.current)
|
|
1093
1233
|
.map((entry) => [String(entry?.id || '').trim(), String(entry?.createdAt || '').trim()])
|
|
1094
1234
|
.filter(([id]) => id.length > 0));
|
|
1095
|
-
|
|
1235
|
+
const persisted = persistWorkspaceSyncWatermarksSnapshotBestEffort();
|
|
1236
|
+
workspaceBaselineResetReasonRef.current = persisted ? null : 'storage-write-failed';
|
|
1237
|
+
}, [persistWorkspaceSyncWatermarksSnapshotBestEffort]);
|
|
1096
1238
|
const refreshLocalWorkspaceTaskCollections = useCallback(async () => {
|
|
1097
1239
|
const [tasksRes, archiveRes] = await Promise.all([
|
|
1098
1240
|
fetch('/api/taskforce/tasks', {
|
|
@@ -1163,7 +1305,6 @@ export function useSyncOrchestrator(input) {
|
|
|
1163
1305
|
workspaceCloudSyncEnabled,
|
|
1164
1306
|
currentWorkspaceId,
|
|
1165
1307
|
workspaceSyncPhase,
|
|
1166
|
-
taxonomyStateFingerprint,
|
|
1167
1308
|
isAuthenticated,
|
|
1168
1309
|
checkAuthSession,
|
|
1169
1310
|
resolveCloudAuthUrl,
|
|
@@ -1176,6 +1317,7 @@ export function useSyncOrchestrator(input) {
|
|
|
1176
1317
|
scheduleWorkspaceSyncRetry,
|
|
1177
1318
|
persistWorkspaceSyncPatchSafely,
|
|
1178
1319
|
persistWorkspaceSyncPatchBestEffort,
|
|
1320
|
+
persistWorkspaceSyncWatermarksSnapshotBestEffort,
|
|
1179
1321
|
reportSyncEvent,
|
|
1180
1322
|
acquireWorkspaceSyncLease,
|
|
1181
1323
|
releaseWorkspaceSyncLease,
|
|
@@ -1183,6 +1325,7 @@ export function useSyncOrchestrator(input) {
|
|
|
1183
1325
|
refreshWorkspaceSyncMarkdownDocumentsSnapshot,
|
|
1184
1326
|
refreshWorkspaceSyncAiProfilesSnapshot,
|
|
1185
1327
|
refreshWorkspaceSyncAssetsSnapshot,
|
|
1328
|
+
refreshWorkspaceSyncPlanningEntitiesSnapshot,
|
|
1186
1329
|
refreshWorkspaceSyncDocumentReviewSessionsSnapshot,
|
|
1187
1330
|
refreshWorkspaceSyncAnnotatedAttachmentSessionsSnapshot,
|
|
1188
1331
|
refreshLocalWorkspaceTaskCollections,
|
|
@@ -1195,6 +1338,7 @@ export function useSyncOrchestrator(input) {
|
|
|
1195
1338
|
workspaceForceFullAiProfilePushRef,
|
|
1196
1339
|
workspacePushInFlightRef,
|
|
1197
1340
|
workspacePullInFlightRef,
|
|
1341
|
+
workspacePendingPushReplayRef,
|
|
1198
1342
|
workspaceLastPushedSignatureRef,
|
|
1199
1343
|
workspacePendingSignatureRef,
|
|
1200
1344
|
workspaceLastPushedTaskIdsRef,
|
|
@@ -1202,12 +1346,14 @@ export function useSyncOrchestrator(input) {
|
|
|
1202
1346
|
workspaceDeletedTaskWatermarksRef,
|
|
1203
1347
|
workspacePullCursorRef,
|
|
1204
1348
|
workspaceLastPushedWatermarksRef,
|
|
1349
|
+
workspaceLastPushedTaskChangeKeysRef,
|
|
1205
1350
|
workspaceLastPushedInitiativeIdsRef,
|
|
1206
1351
|
workspaceLastPushedInitiativeWatermarksRef,
|
|
1207
1352
|
workspaceLastPushedWorkstreamIdsRef,
|
|
1208
1353
|
workspaceLastPushedWorkstreamWatermarksRef,
|
|
1209
1354
|
workspaceLastPushedAiProfileIdsRef,
|
|
1210
1355
|
workspaceLastPushedAiProfileWatermarksRef,
|
|
1356
|
+
workspaceLastPushedAiProfileChangeKeysRef,
|
|
1211
1357
|
workspaceLastPushedDocumentPathsRef,
|
|
1212
1358
|
workspaceLastPushedDocumentWatermarksRef,
|
|
1213
1359
|
workspaceLastPushedAssetPathsRef,
|
|
@@ -1219,6 +1365,7 @@ export function useSyncOrchestrator(input) {
|
|
|
1219
1365
|
workspaceLastPushedAnnotatedAttachmentSessionIdsRef,
|
|
1220
1366
|
workspaceLastPushedAnnotatedAttachmentSessionWatermarksRef,
|
|
1221
1367
|
workspaceLastPushedTaskEventWatermarksRef,
|
|
1368
|
+
workspaceBaselineResetReasonRef,
|
|
1222
1369
|
workspaceCaptureAttachBootstrapBaselineRef,
|
|
1223
1370
|
workspaceStartupFullReconcileRanRef,
|
|
1224
1371
|
workspaceFullReconcileInFlightRef,
|
|
@@ -1252,6 +1399,7 @@ export function useSyncOrchestrator(input) {
|
|
|
1252
1399
|
scheduleWorkspaceSyncRetry,
|
|
1253
1400
|
persistWorkspaceSyncPatchSafely,
|
|
1254
1401
|
persistWorkspaceSyncPatchBestEffort,
|
|
1402
|
+
persistWorkspaceSyncWatermarksSnapshotBestEffort,
|
|
1255
1403
|
reportSyncEvent,
|
|
1256
1404
|
acquireWorkspaceSyncLease,
|
|
1257
1405
|
releaseWorkspaceSyncLease,
|
|
@@ -1259,6 +1407,7 @@ export function useSyncOrchestrator(input) {
|
|
|
1259
1407
|
refreshWorkspaceSyncMarkdownDocumentsSnapshot,
|
|
1260
1408
|
refreshWorkspaceSyncAiProfilesSnapshot,
|
|
1261
1409
|
refreshWorkspaceSyncAssetsSnapshot,
|
|
1410
|
+
refreshWorkspaceSyncPlanningEntitiesSnapshot,
|
|
1262
1411
|
refreshWorkspaceSyncDocumentReviewSessionsSnapshot,
|
|
1263
1412
|
refreshWorkspaceSyncAnnotatedAttachmentSessionsSnapshot,
|
|
1264
1413
|
refreshLocalWorkspaceTaskCollections,
|
|
@@ -1339,7 +1488,6 @@ export function useSyncOrchestrator(input) {
|
|
|
1339
1488
|
}, [syncUserGlobalSettings]);
|
|
1340
1489
|
const recoveryCoordinator = useMemo(() => createSyncRecoveryCoordinator({
|
|
1341
1490
|
currentWorkspaceId,
|
|
1342
|
-
taxonomyStateFingerprint,
|
|
1343
1491
|
workspaceCloudSyncEnabled,
|
|
1344
1492
|
workspaceSyncPhase,
|
|
1345
1493
|
workspaceLastPullAt,
|
|
@@ -1355,12 +1503,14 @@ export function useSyncOrchestrator(input) {
|
|
|
1355
1503
|
workspacePendingSignatureRef,
|
|
1356
1504
|
workspaceLastPushedSignatureRef,
|
|
1357
1505
|
workspaceLastPushedWatermarksRef,
|
|
1506
|
+
workspaceLastPushedTaskChangeKeysRef,
|
|
1358
1507
|
workspaceLastPushedInitiativeIdsRef,
|
|
1359
1508
|
workspaceLastPushedInitiativeWatermarksRef,
|
|
1360
1509
|
workspaceLastPushedWorkstreamIdsRef,
|
|
1361
1510
|
workspaceLastPushedWorkstreamWatermarksRef,
|
|
1362
1511
|
workspaceLastPushedAiProfileIdsRef,
|
|
1363
1512
|
workspaceLastPushedAiProfileWatermarksRef,
|
|
1513
|
+
workspaceLastPushedAiProfileChangeKeysRef,
|
|
1364
1514
|
workspaceLastPushedDocumentPathsRef,
|
|
1365
1515
|
workspaceLastPushedDocumentWatermarksRef,
|
|
1366
1516
|
workspaceLastPushedAssetPathsRef,
|
|
@@ -1372,6 +1522,7 @@ export function useSyncOrchestrator(input) {
|
|
|
1372
1522
|
workspaceLastPushedAnnotatedAttachmentSessionIdsRef,
|
|
1373
1523
|
workspaceLastPushedAnnotatedAttachmentSessionWatermarksRef,
|
|
1374
1524
|
workspaceLastPushedTaskEventWatermarksRef,
|
|
1525
|
+
workspaceBaselineResetReasonRef,
|
|
1375
1526
|
bootstrapPhaseStartedAtRef,
|
|
1376
1527
|
bootstrapLastProgressAtRef,
|
|
1377
1528
|
acquireWorkspaceSyncLease,
|
|
@@ -1380,7 +1531,9 @@ export function useSyncOrchestrator(input) {
|
|
|
1380
1531
|
clearWorkspaceRetry,
|
|
1381
1532
|
clearWorkspaceIssue,
|
|
1382
1533
|
reportWorkspaceWindowContention,
|
|
1534
|
+
reportSyncEvent,
|
|
1383
1535
|
persistWorkspaceSyncPatch,
|
|
1536
|
+
persistWorkspaceSyncWatermarksSnapshotBestEffort,
|
|
1384
1537
|
buildWorkspaceSyncSignature,
|
|
1385
1538
|
pullWorkspaceChangesFromCloud,
|
|
1386
1539
|
pushWorkspaceChangesToCloud,
|
|
@@ -1400,7 +1553,9 @@ export function useSyncOrchestrator(input) {
|
|
|
1400
1553
|
clearWorkspaceRetry,
|
|
1401
1554
|
clearWorkspaceIssue,
|
|
1402
1555
|
reportWorkspaceWindowContention,
|
|
1556
|
+
reportSyncEvent,
|
|
1403
1557
|
persistWorkspaceSyncPatch,
|
|
1558
|
+
persistWorkspaceSyncWatermarksSnapshotBestEffort,
|
|
1404
1559
|
buildWorkspaceSyncSignature,
|
|
1405
1560
|
pullWorkspaceChangesFromCloud,
|
|
1406
1561
|
pushWorkspaceChangesToCloud,
|
|
@@ -1412,6 +1567,39 @@ export function useSyncOrchestrator(input) {
|
|
|
1412
1567
|
const { retryWorkspaceCloudSync, resetWorkspaceSyncCursorAndPull } = recoveryCoordinator;
|
|
1413
1568
|
// === SECTION: Diagnostics & reactive effects ===
|
|
1414
1569
|
const getWorkspaceSyncDiagnostics = useCallback(() => {
|
|
1570
|
+
const pushReadiness = resolvePushSyncReadiness({
|
|
1571
|
+
cloudAuthConfigured,
|
|
1572
|
+
runtimeMode,
|
|
1573
|
+
workspaceCloudSyncEnabled,
|
|
1574
|
+
currentWorkspaceId,
|
|
1575
|
+
workspaceSyncPhase,
|
|
1576
|
+
isAuthenticated,
|
|
1577
|
+
repairModeActive: workspaceRepairModeRef.current === true,
|
|
1578
|
+
repairModeBypass: false,
|
|
1579
|
+
pushInFlight: workspacePushInFlightRef.current,
|
|
1580
|
+
pullInFlight: workspacePullInFlightRef.current
|
|
1581
|
+
});
|
|
1582
|
+
const retryPending = isWorkspaceRetryPending();
|
|
1583
|
+
const pullReadiness = resolvePullSyncReadiness({
|
|
1584
|
+
cloudAuthConfigured,
|
|
1585
|
+
runtimeMode,
|
|
1586
|
+
workspaceCloudSyncEnabled,
|
|
1587
|
+
currentWorkspaceId,
|
|
1588
|
+
workspaceSyncPhase,
|
|
1589
|
+
isAuthenticated,
|
|
1590
|
+
repairModeActive: workspaceRepairModeRef.current === true,
|
|
1591
|
+
repairModeBypass: false,
|
|
1592
|
+
retryPending,
|
|
1593
|
+
pushInFlight: workspacePushInFlightRef.current,
|
|
1594
|
+
pullInFlight: workspacePullInFlightRef.current
|
|
1595
|
+
});
|
|
1596
|
+
const retryReadiness = resolveRetrySyncReadiness({
|
|
1597
|
+
cloudAuthConfigured,
|
|
1598
|
+
runtimeMode,
|
|
1599
|
+
workspaceCloudSyncEnabled,
|
|
1600
|
+
currentWorkspaceId,
|
|
1601
|
+
isAuthenticated
|
|
1602
|
+
});
|
|
1415
1603
|
return {
|
|
1416
1604
|
workspaceId: currentWorkspaceId,
|
|
1417
1605
|
enabled: workspaceCloudSyncEnabled,
|
|
@@ -1425,6 +1613,13 @@ export function useSyncOrchestrator(input) {
|
|
|
1425
1613
|
pendingChanges: workspaceSyncPendingChanges,
|
|
1426
1614
|
lastErrorMessage: workspaceLastErrorMessage,
|
|
1427
1615
|
recommendedAction: workspaceSyncRecommendedAction,
|
|
1616
|
+
pushBlockedReason: pushReadiness.allowed ? null : pushReadiness.reason,
|
|
1617
|
+
pullBlockedReason: pullReadiness.allowed ? null : pullReadiness.reason,
|
|
1618
|
+
retryBlockedReason: retryReadiness.allowed ? null : retryReadiness.reason,
|
|
1619
|
+
repairActive: workspaceRepairModeRef.current === true,
|
|
1620
|
+
pushInFlight: workspacePushInFlightRef.current === true,
|
|
1621
|
+
pullInFlight: workspacePullInFlightRef.current === true,
|
|
1622
|
+
retryPending,
|
|
1428
1623
|
documentSnapshotCount: workspaceSyncMarkdownDocuments.length,
|
|
1429
1624
|
aiProfileSnapshotCount: workspaceSyncAiProfiles.length,
|
|
1430
1625
|
aiProfileSnapshotRawCount: workspaceSyncAiProfilesRawCount,
|
|
@@ -1441,9 +1636,12 @@ export function useSyncOrchestrator(input) {
|
|
|
1441
1636
|
forceFullAiProfilePushQueued: workspaceForceFullAiProfilePushRef.current === true
|
|
1442
1637
|
};
|
|
1443
1638
|
}, [
|
|
1639
|
+
cloudAuthConfigured,
|
|
1444
1640
|
currentWorkspaceId,
|
|
1641
|
+
runtimeMode,
|
|
1445
1642
|
workspaceCloudSyncEnabled,
|
|
1446
1643
|
workspaceSyncPhase,
|
|
1644
|
+
isAuthenticated,
|
|
1447
1645
|
workspaceSyncStatus,
|
|
1448
1646
|
workspaceSyncSummary,
|
|
1449
1647
|
workspaceLastSuccessfulSyncAt,
|
|
@@ -1463,7 +1661,8 @@ export function useSyncOrchestrator(input) {
|
|
|
1463
1661
|
workspaceSyncDocumentReviewSessions.length,
|
|
1464
1662
|
workspaceSyncDocumentReviewSessionsFingerprint,
|
|
1465
1663
|
workspaceSyncAnnotatedAttachmentSessions.length,
|
|
1466
|
-
workspaceSyncAnnotatedAttachmentSessionsFingerprint
|
|
1664
|
+
workspaceSyncAnnotatedAttachmentSessionsFingerprint,
|
|
1665
|
+
isWorkspaceRetryPending
|
|
1467
1666
|
]);
|
|
1468
1667
|
useEffect(() => {
|
|
1469
1668
|
retryWorkspaceSyncRef.current = retryWorkspaceCloudSync;
|
|
@@ -1492,7 +1691,16 @@ export function useSyncOrchestrator(input) {
|
|
|
1492
1691
|
return;
|
|
1493
1692
|
refreshWorkspaceSyncContextAssetSnapshots();
|
|
1494
1693
|
};
|
|
1694
|
+
const handleAiProfilesMutated = (event) => {
|
|
1695
|
+
const detail = event.detail;
|
|
1696
|
+
const eventWorkspaceId = String(detail?.workspaceId || '').trim() || 'default';
|
|
1697
|
+
if (eventWorkspaceId !== currentWorkspaceId)
|
|
1698
|
+
return;
|
|
1699
|
+
void refreshWorkspaceSyncAiProfilesSnapshot();
|
|
1700
|
+
void refreshWorkspaceSyncAssetsSnapshot();
|
|
1701
|
+
};
|
|
1495
1702
|
window.addEventListener(TASKFORCE_CONTEXT_ASSETS_MUTATED_EVENT, handleContextAssetsMutated);
|
|
1703
|
+
window.addEventListener(TASKFORCE_AI_PROFILES_MUTATED_EVENT, handleAiProfilesMutated);
|
|
1496
1704
|
const docsIntervalId = window.setInterval(() => {
|
|
1497
1705
|
void refreshWorkspaceSyncMarkdownDocumentsSnapshot();
|
|
1498
1706
|
}, workspaceDocumentsRefreshIntervalMs);
|
|
@@ -1510,6 +1718,7 @@ export function useSyncOrchestrator(input) {
|
|
|
1510
1718
|
}, workspaceDocumentsRefreshIntervalMs);
|
|
1511
1719
|
return () => {
|
|
1512
1720
|
window.removeEventListener(TASKFORCE_CONTEXT_ASSETS_MUTATED_EVENT, handleContextAssetsMutated);
|
|
1721
|
+
window.removeEventListener(TASKFORCE_AI_PROFILES_MUTATED_EVENT, handleAiProfilesMutated);
|
|
1513
1722
|
window.clearInterval(docsIntervalId);
|
|
1514
1723
|
window.clearInterval(aiProfilesIntervalId);
|
|
1515
1724
|
window.clearInterval(assetsIntervalId);
|
|
@@ -1545,11 +1754,14 @@ export function useSyncOrchestrator(input) {
|
|
|
1545
1754
|
refreshWorkspaceSyncContextAssetSnapshots();
|
|
1546
1755
|
}, [cloudAuthConfigured, runtimeMode, workspaceCloudSyncEnabled, authSessionResolved, isAuthenticated, taskAttachmentsFingerprint, refreshWorkspaceSyncContextAssetSnapshots]);
|
|
1547
1756
|
useEffect(() => {
|
|
1548
|
-
if (!
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1757
|
+
if (!shouldScheduleWorkspaceReactivePush({
|
|
1758
|
+
cloudAuthConfigured,
|
|
1759
|
+
runtimeMode,
|
|
1760
|
+
workspaceCloudSyncEnabled,
|
|
1761
|
+
authSessionResolved,
|
|
1762
|
+
workspaceSyncPhase,
|
|
1763
|
+
workspaceSyncReferenceSnapshotsReady
|
|
1764
|
+
}))
|
|
1553
1765
|
return;
|
|
1554
1766
|
const signature = buildWorkspaceSyncSignature();
|
|
1555
1767
|
if (shouldSuppressAttachBootstrapPush(signature))
|
|
@@ -1587,11 +1799,14 @@ export function useSyncOrchestrator(input) {
|
|
|
1587
1799
|
workspacePullInFlightRef
|
|
1588
1800
|
]);
|
|
1589
1801
|
useEffect(() => {
|
|
1590
|
-
if (!
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1802
|
+
if (!shouldStartWorkspacePushWatchdog({
|
|
1803
|
+
cloudAuthConfigured,
|
|
1804
|
+
runtimeMode,
|
|
1805
|
+
workspaceCloudSyncEnabled,
|
|
1806
|
+
authSessionResolved,
|
|
1807
|
+
workspaceSyncPhase,
|
|
1808
|
+
workspaceSyncReferenceSnapshotsReady
|
|
1809
|
+
}))
|
|
1595
1810
|
return;
|
|
1596
1811
|
const intervalId = window.setInterval(() => {
|
|
1597
1812
|
if (workspacePushInFlightRef.current || workspacePullInFlightRef.current)
|
|
@@ -1633,14 +1848,18 @@ export function useSyncOrchestrator(input) {
|
|
|
1633
1848
|
clearWorkspaceRetry
|
|
1634
1849
|
]);
|
|
1635
1850
|
useEffect(() => {
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1851
|
+
const pullPolicy = resolveWorkspaceAutomaticPullPolicy({
|
|
1852
|
+
cloudAuthConfigured,
|
|
1853
|
+
runtimeMode,
|
|
1854
|
+
workspaceCloudSyncEnabled,
|
|
1855
|
+
authSessionResolved,
|
|
1856
|
+
workspaceSyncPhase,
|
|
1857
|
+
lastPullAt: workspaceLastPullAt,
|
|
1858
|
+
retryPending: isWorkspaceRetryPending()
|
|
1859
|
+
});
|
|
1860
|
+
if (!pullPolicy.shouldStart)
|
|
1641
1861
|
return;
|
|
1642
|
-
|
|
1643
|
-
if (shouldKickOffPull) {
|
|
1862
|
+
if (pullPolicy.shouldKickOffImmediately) {
|
|
1644
1863
|
void pullWorkspaceChangesFromCloud();
|
|
1645
1864
|
}
|
|
1646
1865
|
const intervalId = window.setInterval(() => {
|
|
@@ -1661,9 +1880,14 @@ export function useSyncOrchestrator(input) {
|
|
|
1661
1880
|
workspacePullIntervalMs
|
|
1662
1881
|
]);
|
|
1663
1882
|
useEffect(() => {
|
|
1664
|
-
if (!
|
|
1665
|
-
|
|
1666
|
-
|
|
1883
|
+
if (!shouldStartWorkspacePeriodicFullReconcile({
|
|
1884
|
+
cloudAuthConfigured,
|
|
1885
|
+
runtimeMode,
|
|
1886
|
+
workspaceCloudSyncEnabled,
|
|
1887
|
+
authSessionResolved,
|
|
1888
|
+
isAuthenticated,
|
|
1889
|
+
workspaceSyncPhase
|
|
1890
|
+
}))
|
|
1667
1891
|
return;
|
|
1668
1892
|
const intervalId = window.setInterval(() => {
|
|
1669
1893
|
if (workspaceFullReconcileInFlightRef.current)
|
|
@@ -1726,13 +1950,15 @@ export function useSyncOrchestrator(input) {
|
|
|
1726
1950
|
// missing or stale-tombstoned metadata — a common result of a crash between file write
|
|
1727
1951
|
// and DB upsert. The repair only adds missing records; it never deletes files.
|
|
1728
1952
|
useEffect(() => {
|
|
1729
|
-
if (!
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1953
|
+
if (!shouldRunWorkspaceStartupRepair({
|
|
1954
|
+
cloudAuthConfigured,
|
|
1955
|
+
runtimeMode,
|
|
1956
|
+
workspaceCloudSyncEnabled,
|
|
1957
|
+
authSessionResolved,
|
|
1958
|
+
isAuthenticated,
|
|
1959
|
+
workspaceSyncPhase,
|
|
1960
|
+
alreadyRan: workspaceStartupRepairRanRef.current
|
|
1961
|
+
}))
|
|
1736
1962
|
return;
|
|
1737
1963
|
workspaceStartupRepairRanRef.current = true;
|
|
1738
1964
|
fetch('/api/taskforce/sync/workspace/repair-startup', {
|