@taskforcehq/taskforce 0.3.328 → 0.3.329
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/dist/Taskforce.module.css +233 -34
- package/dist/TaskforceCore.js +237 -230
- package/dist/annotatedAttachments/AnnotatedAttachmentSessionStore.js +1 -1
- package/dist/cli.js +34 -0
- package/dist/cliCloudTargetGuard.d.ts +5 -0
- package/dist/cliCloudTargetGuard.js +11 -0
- package/dist/components/features/AnnotatedAttachmentWorkspace.js +24 -8
- package/dist/components/features/TaskSettings.d.ts +12 -1
- package/dist/components/features/TaskSettings.js +147 -40
- package/dist/components/features/agentCapabilities/AgentCapabilitiesPrototype.d.ts +1 -1
- package/dist/components/features/planning/PlanningModule.js +2 -5
- package/dist/components/features/planning/PlanningTaskOrderList.d.ts +1 -1
- package/dist/components/features/planning/PlanningTaskOrderList.js +17 -6
- package/dist/components/features/planning/planningTaskArrangement.d.ts +1 -0
- package/dist/components/features/planning/planningTaskArrangement.js +5 -5
- package/dist/components/features/taskforceAgentEditorModel.js +3 -1
- package/dist/components/task/TaskCard.d.ts +5 -0
- package/dist/components/task/TaskCard.js +65 -10
- package/dist/components/task/TaskImageReviews.js +14 -5
- package/dist/components/task/TaskKanban.d.ts +6 -1
- package/dist/components/task/TaskKanban.js +152 -6
- package/dist/components/task/TaskList.d.ts +5 -0
- package/dist/components/task/TaskList.js +3 -3
- package/dist/components/ui/PasswordInput.d.ts +6 -0
- package/dist/components/ui/PasswordInput.js +11 -0
- package/dist/components/ui/TopNoticeLayer.js +1 -1
- package/dist/components/views/AppShellHeader.js +32 -11
- package/dist/components/views/PlanComparisonPage.js +12 -0
- package/dist/components/views/StandaloneLayout.js +7 -31
- package/dist/components/views/WidgetView.js +3 -3
- package/dist/components/views/panels/PlanningDrawer.js +5 -12
- package/dist/components/views/standalone/modals/AccountSettingsModal.js +26 -17
- package/dist/config/envSchema.js +12 -0
- package/dist/config/localServiceRuntimeContract.d.ts +13 -0
- package/dist/config/localServiceRuntimeContract.js +135 -0
- package/dist/core/AiProfileService.js +46 -8
- package/dist/core/DeletedTaskLifecycleService.d.ts +1 -0
- package/dist/core/DeletedTaskLifecycleService.js +37 -6
- package/dist/core/TaskAttachmentLinksDurableMutationService.d.ts +3 -2
- package/dist/core/TaskAttachmentLinksDurableMutationService.js +33 -9
- package/dist/core/Taskforce.d.ts +62 -2
- package/dist/core/Taskforce.js +635 -32
- package/dist/core/types.d.ts +6 -0
- package/dist/hooks/sync/useDurableLocalOutboxDrain.d.ts +1 -1
- package/dist/hooks/sync/useDurableTaskCreateMutation.js +1 -1
- package/dist/hooks/sync/useDurableTaskMetadataMutation.d.ts +1 -0
- package/dist/hooks/sync/useDurableTaskMetadataMutation.js +1 -0
- package/dist/hooks/sync/useDurableTaskStatusMutation.d.ts +1 -0
- package/dist/hooks/tasks/taskHttpMutation.js +1 -0
- package/dist/hooks/tasks/useCloudTaskSearch.d.ts +12 -0
- package/dist/hooks/tasks/useCloudTaskSearch.js +71 -0
- package/dist/hooks/tasks/useTaskDescriptionImageDraftRecovery.d.ts +16 -0
- package/dist/hooks/tasks/useTaskDescriptionImageDraftRecovery.js +197 -0
- package/dist/hooks/tasks/useTaskEditorNavigation.d.ts +16 -3
- package/dist/hooks/tasks/useTaskEditorNavigation.js +72 -13
- package/dist/hooks/tasks/useTaskFormActions.d.ts +6 -0
- package/dist/hooks/tasks/useTaskFormActions.js +65 -12
- package/dist/hooks/ui/useSettingsModel.d.ts +24 -2
- package/dist/hooks/ui/useSettingsModel.js +13 -2
- package/dist/hooks/ui/useSettingsPersistence.d.ts +12 -1
- package/dist/hooks/ui/useSettingsPersistence.js +74 -47
- package/dist/hooks/useFilterSort.d.ts +7 -3
- package/dist/hooks/useFilterSort.js +15 -5
- package/dist/hooks/useTaskData.d.ts +10 -1
- package/dist/hooks/useTaskData.js +216 -7
- package/dist/hooks/useTaskMutations.d.ts +10 -2
- package/dist/hooks/useTaskMutations.js +223 -43
- package/dist/hooks/useTaskforce.d.ts +37 -9
- package/dist/hooks/useTaskforce.js +349 -39
- package/dist/hooks/useUiNotice.d.ts +4 -0
- package/dist/hooks/useUiNotice.js +4 -0
- package/dist/mcp/adminWorkspaceRegistrar.js +3 -3
- package/dist/mcp/documentAssetRegistrar.js +44 -35
- package/dist/mcp/documentHelpers.d.ts +1 -0
- package/dist/mcp/documentHelpers.js +7 -3
- package/dist/mcp/runtime.js +172 -42
- package/dist/mcp/taskPlanningRegistrar.js +41 -38
- package/dist/mcp/toolCallCompatibility.js +38 -1
- package/dist/mcp/toolCatalog.d.ts +1 -0
- package/dist/migrations/taskSchemaMigrations.js +12 -0
- package/dist/runtime/appGateDefinitions.d.ts +30 -6
- package/dist/runtime/appGateDefinitions.js +6 -6
- package/dist/runtime/appGates.d.ts +12 -13
- package/dist/runtime/appGates.js +29 -13
- package/dist/runtime/nodeAppGates.d.ts +8 -0
- package/dist/runtime/nodeAppGates.js +27 -0
- package/dist/server/cloudCollectionRead.d.ts +1 -1
- package/dist/server/cloudCollectionRead.js +2 -2
- package/dist/server/index.d.ts +3 -0
- package/dist/server/index.js +15 -3
- package/dist/server/localServiceLease.d.ts +3 -0
- package/dist/server/localServiceLease.js +9 -1
- package/dist/server/localWorkspaceSyncServerRuntime.js +10 -3
- package/dist/server/rateLimit.d.ts +1 -0
- package/dist/server/rateLimit.js +4 -0
- package/dist/server/realtimeSyncWs.js +36 -12
- package/dist/server/routes/admin.js +1 -0
- package/dist/server/routes/agentRoles.js +3 -2
- package/dist/server/routes/agentSkills.js +3 -2
- package/dist/server/routes/agents.js +118 -16
- package/dist/server/routes/annotatedAttachments.js +3 -2
- package/dist/server/routes/auth.js +3 -1
- package/dist/server/routes/durableTaskHttpRouters.d.ts +9 -2
- package/dist/server/routes/localService.js +2 -0
- package/dist/server/routes/primitives.d.ts +2 -0
- package/dist/server/routes/syncAuxRoutes.js +5 -2
- package/dist/server/routes/syncPullApplyRoutes.js +23 -4
- package/dist/server/routes/syncV3FeedRoutes.js +18 -16
- package/dist/server/routes/syncV3LocalCaptureRoutes.js +28 -2
- package/dist/server/routes/syncV3LocalFeedApplyRoutes.d.ts +1 -0
- package/dist/server/routes/syncV3LocalFeedApplyRoutes.js +26 -0
- package/dist/server/routes/syncV3OperationRoutes.js +10 -0
- package/dist/server/routes/tasks.js +103 -11
- package/dist/server/routes/workspaces.js +43 -1
- package/dist/server/workspaceDeletionAdmission.d.ts +23 -0
- package/dist/server/workspaceDeletionAdmission.js +50 -0
- package/dist/service/localServiceCli.js +16 -0
- package/dist/service/localServiceClientLifecycle.js +36 -10
- package/dist/services/codexAppServerModelGateway.d.ts +112 -0
- package/dist/services/codexAppServerModelGateway.js +438 -0
- package/dist/services/taskforceAgentMcpBridge.d.ts +7 -1
- package/dist/services/taskforceAgentMcpBridge.js +23 -3
- package/dist/shared/taskforceAgentDefinition.js +7 -1
- package/dist/shared/taskforceAgentModels.d.ts +1 -0
- package/dist/shared/taskforceAgentModels.js +30 -1
- package/dist/storage/postgresAdapter.d.ts +20 -3
- package/dist/storage/postgresAdapter.js +106 -14
- package/dist/storage/postgresWorker.js +13 -4
- package/dist/storage/postgresWorkerProtocol.d.ts +29 -0
- package/dist/storage/postgresWorkerProtocol.js +30 -0
- package/dist/sync/cloudSyncApi.d.ts +4 -1
- package/dist/sync/cloudSyncApi.js +7 -2
- package/dist/sync/contentSyncState.d.ts +1 -1
- package/dist/sync/coordinator/localSyncExecutionPermitStore.d.ts +1 -0
- package/dist/sync/coordinator/localSyncExecutionPermitStore.js +7 -1
- package/dist/sync/coordinator/localWorkspaceSyncRunner.js +6 -2
- package/dist/sync/engine/workspaceSyncEngineBrowserGatewayRemoteServices.js +20 -2
- package/dist/sync/engine/workspaceSyncEngineLocalServices.d.ts +4 -0
- package/dist/sync/engine/workspaceSyncEngineLocalServices.js +11 -0
- package/dist/sync/engine/workspaceSyncEngineRemoteServices.d.ts +11 -0
- package/dist/sync/engine/workspaceSyncEngineRemoteServices.js +2 -1
- package/dist/sync/engine/workspaceSyncEngineServerRemoteServices.js +31 -4
- package/dist/sync/engine/workspaceSyncEngineServerRunnerOperations.d.ts +3 -1
- package/dist/sync/engine/workspaceSyncEngineServerRunnerOperations.js +25 -8
- package/dist/sync/engine/workspaceSyncEngineTransfers.d.ts +1 -1
- package/dist/sync/engine/workspaceSyncEngineTransfers.js +8 -3
- package/dist/sync/syncService.d.ts +2 -0
- package/dist/sync/syncService.js +4 -1
- package/dist/sync/v3/combinedFeedCapability.js +4 -0
- package/dist/sync/v3/durableTaskAttachmentLinksMutationRouter.d.ts +2 -0
- package/dist/sync/v3/durableTaskAttachmentLinksMutationRouter.js +11 -1
- package/dist/sync/v3/durableTaskChecklistMutationRouter.d.ts +2 -0
- package/dist/sync/v3/durableTaskChecklistMutationRouter.js +4 -0
- package/dist/sync/v3/durableTaskHttpBulkMutationRouter.d.ts +1 -0
- package/dist/sync/v3/durableTaskHttpBulkMutationRouter.js +30 -8
- package/dist/sync/v3/durableTaskHttpRootMutationRouter.d.ts +5 -3
- package/dist/sync/v3/durableTaskHttpRootMutationRouter.js +27 -2
- package/dist/sync/v3/localTaskAttachmentLinksOutboxService.d.ts +2 -0
- package/dist/sync/v3/localTaskAttachmentLinksOutboxService.js +47 -7
- package/dist/sync/v3/localTaskCreateOutboxService.js +15 -6
- package/dist/sync/v3/localTaskMetadataClient.d.ts +1 -0
- package/dist/sync/v3/localTaskMetadataClient.js +1 -0
- package/dist/sync/v3/localTaskMetadataOutboxHandler.js +5 -1
- package/dist/sync/v3/localTaskMetadataOutboxService.d.ts +2 -0
- package/dist/sync/v3/localTaskMetadataOutboxService.js +7 -0
- package/dist/sync/v3/localTaskRestoreOutboxService.js +14 -6
- package/dist/sync/v3/localTaskStatusClient.d.ts +1 -0
- package/dist/sync/v3/localTaskStatusClient.js +6 -1
- package/dist/sync/v3/localTaskStatusOutboxService.d.ts +2 -0
- package/dist/sync/v3/localTaskStatusOutboxService.js +54 -13
- package/dist/sync/v3/syncDurabilityStore.d.ts +7 -0
- package/dist/sync/v3/syncDurabilityStore.js +31 -11
- package/dist/sync/v3/taskAttachmentLinksMutationService.d.ts +6 -4
- package/dist/sync/v3/taskAttachmentLinksMutationService.js +19 -10
- package/dist/sync/v3/taskChecklistMutationService.d.ts +4 -2
- package/dist/sync/v3/taskChecklistMutationService.js +4 -0
- package/dist/sync/v3/taskCreateMutationService.d.ts +2 -2
- package/dist/sync/v3/taskCreateMutationService.js +7 -4
- package/dist/sync/v3/taskMetadataMutationService.d.ts +3 -0
- package/dist/sync/v3/taskMetadataMutationService.js +4 -0
- package/dist/sync/v3/taskRestoreMutationService.d.ts +2 -2
- package/dist/sync/v3/taskRestoreMutationService.js +7 -4
- package/dist/sync/v3/taskStatusMutationService.d.ts +2 -0
- package/dist/sync/v3/taskStatusMutationService.js +4 -0
- package/dist/sync/v3/workflowAssignmentSync.d.ts +1 -0
- package/dist/sync/v3/workflowAssignmentSync.js +3 -0
- package/dist/sync/v3/workspaceSyncV2ProjectionExclusions.d.ts +1 -1
- package/dist/sync/v3/workspaceSyncV2ProjectionExclusions.js +13 -3
- package/dist/sync/v3/workspaceSyncV3AttachmentApplyObligationStore.d.ts +11 -0
- package/dist/sync/v3/workspaceSyncV3AttachmentApplyObligationStore.js +27 -10
- package/dist/sync/v3/workspaceSyncV3AttachmentAssetHydration.d.ts +2 -1
- package/dist/sync/v3/workspaceSyncV3AttachmentAssetHydration.js +52 -10
- package/dist/sync/v3/workspaceSyncV3CloudOperationHandler.js +9 -1
- package/dist/sync/v3/workspaceSyncV3CombinedFeedOrchestrator.js +8 -3
- package/dist/sync/v3/workspaceSyncV3CombinedLocalApply.js +51 -10
- package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.d.ts +7 -0
- package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.js +30 -18
- package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.d.ts +9 -4
- package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.js +98 -47
- package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.d.ts +10 -0
- package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.js +58 -21
- package/dist/sync/v3/workspaceSyncV3CombinedWireContract.d.ts +3 -1
- package/dist/sync/v3/workspaceSyncV3CombinedWireContract.js +18 -0
- package/dist/sync/v3/workspaceSyncV3CoverageRegistry.js +6 -0
- package/dist/sync/v3/workspaceSyncV3FeedProfile.d.ts +1 -1
- package/dist/sync/v3/workspaceSyncV3LegacyBoundaryAttestation.d.ts +1 -0
- package/dist/sync/v3/workspaceSyncV3LegacyBoundaryAttestation.js +23 -10
- package/dist/sync/v3/workspaceSyncV3NestedTaskApply.d.ts +3 -0
- package/dist/sync/v3/workspaceSyncV3NestedTaskApply.js +64 -13
- package/dist/sync/v3/workspaceSyncV3NestedTaskCodecs.d.ts +9 -0
- package/dist/sync/v3/workspaceSyncV3NestedTaskCodecs.js +26 -0
- package/dist/sync/v3/workspaceSyncV3NestedTaskProjection.d.ts +15 -5
- package/dist/sync/v3/workspaceSyncV3NestedTaskProjection.js +50 -14
- package/dist/sync/v3/workspaceSyncV3NestedTaskRepairSnapshot.d.ts +2 -1
- package/dist/sync/v3/workspaceSyncV3NestedTaskRepairSnapshot.js +11 -3
- package/dist/sync/v3/workspaceSyncV3OperationProtocol.d.ts +2 -0
- package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.d.ts +2 -0
- package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.js +19 -7
- package/dist/sync/v3/workspaceSyncV3TaskCommentAudit.js +9 -2
- package/dist/sync/v3/workspaceSyncV3TaskCoverCoverage.d.ts +7 -0
- package/dist/sync/v3/workspaceSyncV3TaskCoverCoverage.js +37 -0
- package/dist/sync/v3/workspaceSyncV3TaskCoverWireContract.d.ts +6 -0
- package/dist/sync/v3/workspaceSyncV3TaskCoverWireContract.js +9 -0
- package/dist/sync/workspacePullFeed.js +2 -1
- package/dist/sync/workspaceRepair.d.ts +3 -0
- package/dist/sync/workspaceRepair.js +67 -6
- package/dist/types.d.ts +47 -1
- package/dist/types.js +6 -0
- package/dist/ui/assets/{AiIdentityRosterCard-MZs7lVED.js → AiIdentityRosterCard-BZM4aQnM.js} +1 -1
- package/dist/ui/assets/AiProfilesModule-BbAEWtHH.js +1 -0
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-B68Wg-RV.js +3 -0
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-TzYu7pkG.css +1 -0
- package/dist/ui/assets/{AssetTraySortControl-Kf1pelSy.js → AssetTraySortControl-C8Rztyal.js} +1 -1
- package/dist/ui/assets/{ContextAttachmentManager-B8boOs6Q.js → ContextAttachmentManager-Cj3c7X9y.js} +2 -2
- package/dist/ui/assets/{DocumentWorkspace-DXH4XUsB.js → DocumentWorkspace-B5uvzems.js} +1 -1
- package/dist/ui/assets/{EntityActivityTimeline-BtSTq0ON.js → EntityActivityTimeline-BVFvCB5R.js} +1 -1
- package/dist/ui/assets/PlanningModule-B5DWQOGz.js +1 -0
- package/dist/ui/assets/PlansPage-AY4cGWco.js +1 -0
- package/dist/ui/assets/TaskContextUpload-DZxTVesW.js +1 -0
- package/dist/ui/assets/TaskSettings-BeWAuyZj.js +12 -0
- package/dist/ui/assets/{TaskforceAgentsModule-BazdUwxZ.js → TaskforceAgentsModule-BifCYtjR.js} +6 -6
- package/dist/ui/assets/{WorkflowManagerModule-DWFspC-o.js → WorkflowManagerModule-DEr5di_r.js} +1 -1
- package/dist/ui/assets/index-I5zhdtgt.js +7 -0
- package/dist/ui/assets/index-VRFsx3wz.css +1 -0
- package/dist/ui/assets/{vendor-icons-BkFLXavV.js → vendor-icons-D9Lpw-j4.js} +1 -1
- package/dist/ui/index.html +3 -3
- package/dist/utils/taskActivity.d.ts +3 -2
- package/dist/utils/taskActivity.js +19 -2
- package/dist/utils/taskEditorReconciliation.d.ts +40 -0
- package/dist/utils/taskEditorReconciliation.js +217 -0
- package/dist/utils/taskNormalization.d.ts +1 -0
- package/dist/utils/taskNormalization.js +39 -0
- package/dist/utils/taskSearch.js +2 -2
- package/dist/utils/uiNotice.d.ts +4 -0
- package/package.json +16 -4
- package/dist/ui/assets/AiProfilesModule-C3i0LOxe.js +0 -1
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-CBRZ8rca.css +0 -1
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-DVZk5Tln.js +0 -3
- package/dist/ui/assets/PlanningModule-BPVyEa-f.js +0 -1
- package/dist/ui/assets/PlansPage-ChqgxALc.js +0 -1
- package/dist/ui/assets/TaskContextUpload-CB3ol0sN.js +0 -1
- package/dist/ui/assets/TaskSettings-g4ECKNOz.js +0 -12
- package/dist/ui/assets/index-BUplSsv_.js +0 -7
- package/dist/ui/assets/index-gz2EXuoK.css +0 -1
|
@@ -6,7 +6,7 @@ import { validateWorkspaceSyncV3CombinedRepairPage, WorkspaceSyncV3CombinedProje
|
|
|
6
6
|
import { fingerprintWorkspaceSyncPayload, WorkspaceSyncDurabilityStore } from './syncDurabilityStore.js';
|
|
7
7
|
import { WorkflowStore } from '../../storage/workflowStore.js';
|
|
8
8
|
import { serializeTaskRelationshipForSync } from './workspaceSyncV3TaskRelationshipProjection.js';
|
|
9
|
-
import { serializeWorkspaceSyncV3EntityEventPayload, serializeWorkspaceSyncV3TaskAttachmentLinksPayload, serializeWorkspaceSyncV3TaskChecklistPayload, serializeWorkspaceSyncV3TaskCommentsPayload, validateWorkspaceSyncV3EntityEventPayload, } from './workspaceSyncV3NestedTaskCodecs.js';
|
|
9
|
+
import { serializeWorkspaceSyncV3EntityEventPayload, serializeWorkspaceSyncV3TaskAttachmentLinksPayload, serializeWorkspaceSyncV3TaskAttachmentLinksV2Payload, serializeWorkspaceSyncV3TaskChecklistPayload, serializeWorkspaceSyncV3TaskCommentsPayload, validateWorkspaceSyncV3EntityEventPayload, } from './workspaceSyncV3NestedTaskCodecs.js';
|
|
10
10
|
import { applyWorkspaceSyncV3NestedTaskEntries, WorkspaceSyncV3TaskCommentAggregateDivergenceError, } from './workspaceSyncV3NestedTaskApply.js';
|
|
11
11
|
import { LocalSyncIdentityStore } from './localSyncIdentityStore.js';
|
|
12
12
|
import { enqueueLocalTaskCommentReconciliation } from './localTaskCommentOutboxService.js';
|
|
@@ -25,7 +25,8 @@ function combinedRepairBaselineMarker(page) {
|
|
|
25
25
|
})}`;
|
|
26
26
|
}
|
|
27
27
|
const NESTED_TASK_PROJECTIONS = new Set([
|
|
28
|
-
'task-comments/full-v1', 'task-checklist/full-v1', 'task-attachment-links/full-v1',
|
|
28
|
+
'task-comments/full-v1', 'task-checklist/full-v1', 'task-attachment-links/full-v1',
|
|
29
|
+
'task-attachment-links/full-v2', 'entity-event/full-v1',
|
|
29
30
|
]);
|
|
30
31
|
const WORKFLOW_RUNTIME_PROJECTIONS = new Set([
|
|
31
32
|
'workflow-published-definition/full-v2',
|
|
@@ -59,7 +60,8 @@ function coveredDomains(projections) {
|
|
|
59
60
|
domains.push('task-comments');
|
|
60
61
|
if (projections.has('task-checklist/full-v1'))
|
|
61
62
|
domains.push('task-checklist');
|
|
62
|
-
if (projections.has('task-attachment-links/full-v1')
|
|
63
|
+
if (projections.has('task-attachment-links/full-v1')
|
|
64
|
+
|| projections.has('task-attachment-links/full-v2'))
|
|
63
65
|
domains.push('task-attachment-links');
|
|
64
66
|
if (projections.has('entity-event/full-v1'))
|
|
65
67
|
domains.push('entity-event');
|
|
@@ -181,6 +183,15 @@ function isExactPlanningRootProjectionReplay(input) {
|
|
|
181
183
|
&& input.current.lastSequence === input.entry.sequence
|
|
182
184
|
&& input.current.canonicalFingerprint === (input.entry.canonicalFingerprint || input.entry.payloadFingerprint);
|
|
183
185
|
}
|
|
186
|
+
function parentOwnedNestedTaskId(entry) {
|
|
187
|
+
if (entry.projection === 'task-comments/full-v1'
|
|
188
|
+
|| entry.projection === 'task-checklist/full-v1'
|
|
189
|
+
|| entry.projection === 'task-attachment-links/full-v1'
|
|
190
|
+
|| entry.projection === 'task-attachment-links/full-v2') {
|
|
191
|
+
return entry.entityId;
|
|
192
|
+
}
|
|
193
|
+
return null;
|
|
194
|
+
}
|
|
184
195
|
function applyEntries(input) {
|
|
185
196
|
const store = new WorkspaceSyncDurabilityStore(input.core.getDatabaseAdapter());
|
|
186
197
|
const workflowApply = prepareWorkspaceSyncV3WorkflowRuntimeApply({
|
|
@@ -200,9 +211,13 @@ function applyEntries(input) {
|
|
|
200
211
|
throw coveredLocalOperationsError('Combined feed apply is blocked by covered local operations.');
|
|
201
212
|
}
|
|
202
213
|
const notices = notifications();
|
|
214
|
+
const deletedTaskRoots = new Set();
|
|
203
215
|
for (const entry of input.entries) {
|
|
204
216
|
let taskChange = null;
|
|
205
217
|
let nestedTaskChangeId = null;
|
|
218
|
+
const nestedTaskId = parentOwnedNestedTaskId(entry);
|
|
219
|
+
if (nestedTaskId && deletedTaskRoots.has(nestedTaskId))
|
|
220
|
+
continue;
|
|
206
221
|
const current = store.readWorkspaceDomainOwnership({ tenantId: input.tenantId,
|
|
207
222
|
workspaceId: input.workspaceId, domain: entry.domain, entityId: entry.entityId });
|
|
208
223
|
const exactTaskRootReplay = isExactTaskRootProjectionReplay({ entry, current });
|
|
@@ -288,6 +303,16 @@ function applyEntries(input) {
|
|
|
288
303
|
shouldRecordRevision: (result) => result?.state !== 'deferred',
|
|
289
304
|
});
|
|
290
305
|
}
|
|
306
|
+
if (entry.projection === 'task/root-v1') {
|
|
307
|
+
if (taskChange === 'upsert') {
|
|
308
|
+
deletedTaskRoots.delete(entry.entityId);
|
|
309
|
+
}
|
|
310
|
+
else if (taskChange === 'delete'
|
|
311
|
+
|| (!input.core.getTask(entry.entityId, input.workspaceId)
|
|
312
|
+
&& input.core.hasTaskDeletionMarkerForSync(entry.entityId, input.workspaceId))) {
|
|
313
|
+
deletedTaskRoots.add(entry.entityId);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
291
316
|
if (applied.state !== 'applied')
|
|
292
317
|
continue;
|
|
293
318
|
if (entry.projection === 'task/root-v1' && entry.mutationKind !== 'delete') {
|
|
@@ -366,12 +391,19 @@ function listLocalTaskNestedProjection(core, workspaceId, projection) {
|
|
|
366
391
|
taskId: task.id, items: task.checklistItems || [],
|
|
367
392
|
}));
|
|
368
393
|
}
|
|
369
|
-
else {
|
|
394
|
+
else if (projection === 'task-attachment-links/full-v1') {
|
|
370
395
|
values.set(task.id, serializeWorkspaceSyncV3TaskAttachmentLinksPayload({
|
|
371
396
|
taskId: task.id,
|
|
372
397
|
links: core.listTaskAttachmentLinksForDurableSync(task.id, workspaceId),
|
|
373
398
|
}));
|
|
374
399
|
}
|
|
400
|
+
else {
|
|
401
|
+
values.set(task.id, serializeWorkspaceSyncV3TaskAttachmentLinksV2Payload({
|
|
402
|
+
taskId: task.id,
|
|
403
|
+
links: core.listTaskAttachmentLinksForDurableSync(task.id, workspaceId),
|
|
404
|
+
cardCoverAssetId: task.cardCoverAssetId ?? null,
|
|
405
|
+
}));
|
|
406
|
+
}
|
|
375
407
|
}
|
|
376
408
|
const last = page.at(-1);
|
|
377
409
|
cursor = page.length === 1000 && last
|
|
@@ -416,6 +448,9 @@ function nestedLocalDomains(core, workspaceId, projections, liveEntityIds) {
|
|
|
416
448
|
if (projections.has('task-attachment-links/full-v1')) {
|
|
417
449
|
domains.push(['task-attachment-links', listLocalTaskNestedProjection(core, workspaceId, 'task-attachment-links/full-v1')]);
|
|
418
450
|
}
|
|
451
|
+
else if (projections.has('task-attachment-links/full-v2')) {
|
|
452
|
+
domains.push(['task-attachment-links', listLocalTaskNestedProjection(core, workspaceId, 'task-attachment-links/full-v2')]);
|
|
453
|
+
}
|
|
419
454
|
if (projections.has('entity-event/full-v1')) {
|
|
420
455
|
domains.push(['entity-event', listLocalEntityEvents(core, workspaceId, liveEntityIds)]);
|
|
421
456
|
}
|
|
@@ -560,13 +595,18 @@ function isCompatibleLegacyAttachmentLinks(core, workspaceId, local, incoming) {
|
|
|
560
595
|
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
561
596
|
return false;
|
|
562
597
|
const incomingLink = value;
|
|
563
|
-
if (localLink.role !== incomingLink.role)
|
|
564
|
-
return false;
|
|
565
598
|
const localAsset = store.get(String(localLink.assetId || ''), workspaceId);
|
|
566
599
|
const incomingAsset = store.get(String(incomingLink.assetId || ''), workspaceId);
|
|
567
600
|
if (!localAsset || !incomingAsset || localAsset.deletedAt || incomingAsset.deletedAt
|
|
568
601
|
|| localAsset.storageKey !== incomingAsset.storageKey)
|
|
569
602
|
return false;
|
|
603
|
+
const compatibleRole = localLink.role === incomingLink.role
|
|
604
|
+
|| (localAsset.storageProvider === 'external'
|
|
605
|
+
&& localLink.role === 'reference'
|
|
606
|
+
&& incomingAsset.storageProvider !== 'external'
|
|
607
|
+
&& incomingLink.role === (incomingAsset.kind === 'image' ? 'image' : 'attachment'));
|
|
608
|
+
if (!compatibleRole)
|
|
609
|
+
return false;
|
|
570
610
|
const sameContent = localAsset.contentSha256 === incomingAsset.contentSha256
|
|
571
611
|
&& localAsset.sizeBytes === incomingAsset.sizeBytes;
|
|
572
612
|
const authoritativeMaterialization = localAsset.storageProvider === 'external'
|
|
@@ -584,15 +624,15 @@ function isCompatibleLegacyAttachmentLinks(core, workspaceId, local, incoming) {
|
|
|
584
624
|
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
585
625
|
return false;
|
|
586
626
|
const incomingLink = value;
|
|
587
|
-
if (localLink.role !== incomingLink.role)
|
|
588
|
-
return false;
|
|
589
627
|
const incomingAsset = store.get(String(incomingLink.assetId || ''), workspaceId);
|
|
590
628
|
return Boolean(incomingAsset && !incomingAsset.deletedAt
|
|
591
629
|
&& incomingAsset.storageProvider !== 'external'
|
|
630
|
+
&& localLink.role === 'reference'
|
|
631
|
+
&& incomingLink.role === (incomingAsset.kind === 'image' ? 'image' : 'attachment')
|
|
592
632
|
&& incomingAsset.storageKey === localAsset.storageKey
|
|
593
633
|
&& incomingAsset.sizeBytes >= localAsset.sizeBytes);
|
|
594
634
|
}));
|
|
595
|
-
})
|
|
635
|
+
});
|
|
596
636
|
return compatible;
|
|
597
637
|
}
|
|
598
638
|
function assertLocalInventoryReady(input) {
|
|
@@ -981,7 +1021,8 @@ export function applyWorkspaceSyncV3CombinedRepairPage(input) {
|
|
|
981
1021
|
const supportedTarget = ((target.domain === 'task' && entry.projection === 'task/root-v1')
|
|
982
1022
|
|| (target.domain === 'task-comments' && entry.projection === 'task-comments/full-v1')
|
|
983
1023
|
|| (target.domain === 'task-attachment-links'
|
|
984
|
-
&& entry.projection === 'task-attachment-links/full-v1'
|
|
1024
|
+
&& (entry.projection === 'task-attachment-links/full-v1'
|
|
1025
|
+
|| entry.projection === 'task-attachment-links/full-v2'))
|
|
985
1026
|
|| (target.domain === 'entity-event' && entry.projection === 'entity-event/full-v1'));
|
|
986
1027
|
if (!supportedTarget) {
|
|
987
1028
|
throw new Error('Targeted workspace sync recovery does not support this projection.');
|
|
@@ -7,6 +7,7 @@ export declare function prepareWorkspaceSyncV3CombinedRepairSnapshot(input: {
|
|
|
7
7
|
nestedCoverage?: boolean;
|
|
8
8
|
workflowCoverage?: boolean;
|
|
9
9
|
planningOrderCoverage?: boolean;
|
|
10
|
+
taskCoverCoverage?: boolean;
|
|
10
11
|
coveredLegacyWritesFenced?: boolean;
|
|
11
12
|
}): {
|
|
12
13
|
highWatermark: string;
|
|
@@ -35,6 +36,12 @@ export declare function prepareWorkspaceSyncV3PlanningOrderRepairSnapshot(input:
|
|
|
35
36
|
now?: string;
|
|
36
37
|
coveredLegacyWritesFenced?: boolean;
|
|
37
38
|
}): ReturnType<typeof prepareWorkspaceSyncV3CombinedRepairSnapshot>;
|
|
39
|
+
export declare function prepareWorkspaceSyncV3TaskCoverRepairSnapshot(input: {
|
|
40
|
+
core: TaskforceCore;
|
|
41
|
+
workspaceId: string;
|
|
42
|
+
now?: string;
|
|
43
|
+
coveredLegacyWritesFenced?: boolean;
|
|
44
|
+
}): ReturnType<typeof prepareWorkspaceSyncV3CombinedRepairSnapshot>;
|
|
38
45
|
export declare function ensureWorkspaceSyncV3CombinedRepairBaselines(input: {
|
|
39
46
|
core: TaskforceCore;
|
|
40
47
|
workspaceId: string;
|
|
@@ -3,11 +3,12 @@ import { serializeInitiativeForSync, serializeWorkstreamForSync } from '../plann
|
|
|
3
3
|
import { serializeTaskForSync } from '../taskSyncPayload.js';
|
|
4
4
|
import { canonicalWorkspaceSyncJson } from './canonicalWorkspaceSyncJson.js';
|
|
5
5
|
import { WORKSPACE_SYNC_COMBINED_PROJECTION, fingerprintWorkspaceSyncPayload, WORKSPACE_SYNC_CONTRACT_VERSION, WorkspaceSyncRevisionConflictError, } from './syncDurabilityStore.js';
|
|
6
|
-
import { buildWorkspaceSyncV3CombinedRepairSnapshot, buildWorkspaceSyncV3CombinedRepairSnapshotFromLockedCandidates, buildWorkspaceSyncV3NestedRepairSnapshot, buildWorkspaceSyncV3PlanningOrderRepairSnapshot, buildWorkspaceSyncV3WorkflowRepairSnapshot, listWorkspaceSyncV3CombinedRepairCandidates, listWorkspaceSyncV3NestedRepairCandidates, listWorkspaceSyncV3PlanningOrderRepairCandidates, listWorkspaceSyncV3WorkflowRepairCandidates, } from './workspaceSyncV3CombinedRepairSnapshot.js';
|
|
6
|
+
import { buildWorkspaceSyncV3CombinedRepairSnapshot, buildWorkspaceSyncV3CombinedRepairSnapshotFromLockedCandidates, buildWorkspaceSyncV3NestedRepairSnapshot, buildWorkspaceSyncV3PlanningOrderRepairSnapshot, buildWorkspaceSyncV3TaskCoverRepairSnapshot, buildWorkspaceSyncV3WorkflowRepairSnapshot, listWorkspaceSyncV3CombinedRepairCandidates, listWorkspaceSyncV3NestedRepairCandidates, listWorkspaceSyncV3PlanningOrderRepairCandidates, listWorkspaceSyncV3TaskCoverRepairCandidates, listWorkspaceSyncV3WorkflowRepairCandidates, } from './workspaceSyncV3CombinedRepairSnapshot.js';
|
|
7
7
|
import { WORKSPACE_SYNC_V3_COMBINED_COVERAGE_PROFILE } from './workspaceSyncV3CombinedCoverage.js';
|
|
8
8
|
import { WORKSPACE_SYNC_V3_NESTED_COVERAGE_PROFILE } from './workspaceSyncV3NestedCoverage.js';
|
|
9
9
|
import { WORKSPACE_SYNC_V3_WORKFLOW_COVERAGE_PROFILE } from './workspaceSyncV3WorkflowCoverage.js';
|
|
10
10
|
import { WORKSPACE_SYNC_V3_PLANNING_ORDER_COVERAGE_PROFILE } from './workspaceSyncV3PlanningOrderCoverage.js';
|
|
11
|
+
import { WORKSPACE_SYNC_V3_TASK_COVER_COVERAGE_PROFILE } from './workspaceSyncV3TaskCoverCoverage.js';
|
|
11
12
|
import { serializeWorkspaceSyncV3TaskAttachmentLinksPayload, serializeWorkspaceSyncV3TaskCommentsPayload, } from './workspaceSyncV3NestedTaskCodecs.js';
|
|
12
13
|
import { projectWorkspaceSyncV3NestedTaskJournalRow } from './workspaceSyncV3NestedTaskProjection.js';
|
|
13
14
|
import { serializeTaskRelationshipForSync } from './workspaceSyncV3TaskRelationshipProjection.js';
|
|
@@ -262,11 +263,13 @@ export function prepareWorkspaceSyncV3CombinedRepairSnapshot(input) {
|
|
|
262
263
|
const lockCompletedAt = Date.now();
|
|
263
264
|
const candidates = input.workflowCoverage
|
|
264
265
|
? listWorkspaceSyncV3WorkflowRepairCandidates(input.core, workspaceId)
|
|
265
|
-
: input.
|
|
266
|
-
?
|
|
267
|
-
: input.
|
|
268
|
-
?
|
|
269
|
-
:
|
|
266
|
+
: input.taskCoverCoverage
|
|
267
|
+
? listWorkspaceSyncV3TaskCoverRepairCandidates(input.core, workspaceId)
|
|
268
|
+
: input.planningOrderCoverage
|
|
269
|
+
? listWorkspaceSyncV3PlanningOrderRepairCandidates(input.core, workspaceId)
|
|
270
|
+
: input.nestedCoverage
|
|
271
|
+
? listWorkspaceSyncV3NestedRepairCandidates(input.core, workspaceId)
|
|
272
|
+
: listWorkspaceSyncV3CombinedRepairCandidates(input.core, workspaceId);
|
|
270
273
|
const inventoryCompletedAt = Date.now();
|
|
271
274
|
const keys = candidates.map((candidate) => `${candidate.domain}\0${candidate.entityId}`);
|
|
272
275
|
if (new Set(keys).size !== keys.length)
|
|
@@ -550,11 +553,13 @@ export function prepareWorkspaceSyncV3CombinedRepairSnapshot(input) {
|
|
|
550
553
|
const baselineWritesCompletedAt = Date.now();
|
|
551
554
|
const profile = input.workflowCoverage
|
|
552
555
|
? WORKSPACE_SYNC_V3_WORKFLOW_COVERAGE_PROFILE
|
|
553
|
-
: input.
|
|
554
|
-
?
|
|
555
|
-
: input.
|
|
556
|
-
?
|
|
557
|
-
:
|
|
556
|
+
: input.taskCoverCoverage
|
|
557
|
+
? WORKSPACE_SYNC_V3_TASK_COVER_COVERAGE_PROFILE
|
|
558
|
+
: input.planningOrderCoverage
|
|
559
|
+
? WORKSPACE_SYNC_V3_PLANNING_ORDER_COVERAGE_PROFILE
|
|
560
|
+
: input.nestedCoverage
|
|
561
|
+
? WORKSPACE_SYNC_V3_NESTED_COVERAGE_PROFILE
|
|
562
|
+
: WORKSPACE_SYNC_V3_COMBINED_COVERAGE_PROFILE;
|
|
558
563
|
const activeOwner = db.prepare(`
|
|
559
564
|
SELECT 1 AS active
|
|
560
565
|
FROM workspace_sync_projection_state
|
|
@@ -576,14 +581,17 @@ export function prepareWorkspaceSyncV3CombinedRepairSnapshot(input) {
|
|
|
576
581
|
nestedCoverage: input.nestedCoverage === true,
|
|
577
582
|
workflowCoverage: input.workflowCoverage === true,
|
|
578
583
|
planningOrderCoverage: input.planningOrderCoverage === true,
|
|
584
|
+
taskCoverCoverage: input.taskCoverCoverage === true,
|
|
579
585
|
})
|
|
580
586
|
: input.workflowCoverage
|
|
581
587
|
? buildWorkspaceSyncV3WorkflowRepairSnapshot({ core: input.core, workspaceId })
|
|
582
|
-
: input.
|
|
583
|
-
?
|
|
584
|
-
: input.
|
|
585
|
-
?
|
|
586
|
-
:
|
|
588
|
+
: input.taskCoverCoverage
|
|
589
|
+
? buildWorkspaceSyncV3TaskCoverRepairSnapshot({ core: input.core, workspaceId })
|
|
590
|
+
: input.planningOrderCoverage
|
|
591
|
+
? buildWorkspaceSyncV3PlanningOrderRepairSnapshot({ core: input.core, workspaceId })
|
|
592
|
+
: input.nestedCoverage
|
|
593
|
+
? buildWorkspaceSyncV3NestedRepairSnapshot({ core: input.core, workspaceId })
|
|
594
|
+
: buildWorkspaceSyncV3CombinedRepairSnapshot({ core: input.core, workspaceId });
|
|
587
595
|
const snapshotCompletedAt = Date.now();
|
|
588
596
|
if (snapshot.snapshotSequence !== highWatermark) {
|
|
589
597
|
throw new Error('Combined repair baseline snapshot sequence changed while locked.');
|
|
@@ -591,8 +599,9 @@ export function prepareWorkspaceSyncV3CombinedRepairSnapshot(input) {
|
|
|
591
599
|
console.info('[Taskforce Sync Repair Baseline Timing]', JSON.stringify({
|
|
592
600
|
workspaceId,
|
|
593
601
|
coverage: input.workflowCoverage ? 'workflow'
|
|
594
|
-
: input.
|
|
595
|
-
: input.
|
|
602
|
+
: input.taskCoverCoverage ? 'task-cover'
|
|
603
|
+
: input.planningOrderCoverage ? 'planning-order'
|
|
604
|
+
: input.nestedCoverage ? 'nested' : 'combined',
|
|
596
605
|
candidates: candidates.length,
|
|
597
606
|
lock: lockCompletedAt - startedAt,
|
|
598
607
|
inventory: inventoryCompletedAt - lockCompletedAt,
|
|
@@ -615,6 +624,9 @@ export function prepareWorkspaceSyncV3WorkflowRepairSnapshot(input) {
|
|
|
615
624
|
export function prepareWorkspaceSyncV3PlanningOrderRepairSnapshot(input) {
|
|
616
625
|
return prepareWorkspaceSyncV3CombinedRepairSnapshot({ ...input, planningOrderCoverage: true });
|
|
617
626
|
}
|
|
627
|
+
export function prepareWorkspaceSyncV3TaskCoverRepairSnapshot(input) {
|
|
628
|
+
return prepareWorkspaceSyncV3CombinedRepairSnapshot({ ...input, taskCoverCoverage: true });
|
|
629
|
+
}
|
|
618
630
|
export function ensureWorkspaceSyncV3CombinedRepairBaselines(input) {
|
|
619
631
|
const { snapshot: _snapshot, ...result } = prepareWorkspaceSyncV3CombinedRepairSnapshot(input);
|
|
620
632
|
return result;
|
|
@@ -3,6 +3,7 @@ import { WORKSPACE_SYNC_V3_COMBINED_COVERAGE_PROFILE } from './workspaceSyncV3Co
|
|
|
3
3
|
import { WORKSPACE_SYNC_V3_NESTED_COVERAGE_PROFILE } from './workspaceSyncV3NestedCoverage.js';
|
|
4
4
|
import { WORKSPACE_SYNC_V3_WORKFLOW_COVERAGE_PROFILE } from './workspaceSyncV3WorkflowCoverage.js';
|
|
5
5
|
import { WORKSPACE_SYNC_V3_PLANNING_ORDER_COVERAGE_PROFILE } from './workspaceSyncV3PlanningOrderCoverage.js';
|
|
6
|
+
import { WORKSPACE_SYNC_V3_TASK_COVER_COVERAGE_PROFILE } from './workspaceSyncV3TaskCoverCoverage.js';
|
|
6
7
|
import { type WorkspaceSyncV3FeedEntry } from './workspaceSyncV3Feed.js';
|
|
7
8
|
import { type WorkspaceSyncV3FeedCursorKeyring } from './workspaceSyncV3FeedCursorKeys.js';
|
|
8
9
|
export interface WorkspaceSyncV3CombinedRepairCursor {
|
|
@@ -21,7 +22,7 @@ export interface WorkspaceSyncV3CombinedRepairPage {
|
|
|
21
22
|
success: true;
|
|
22
23
|
protocolVersion: 3;
|
|
23
24
|
workspaceId: string;
|
|
24
|
-
coverage: typeof WORKSPACE_SYNC_V3_COMBINED_COVERAGE_PROFILE | typeof WORKSPACE_SYNC_V3_NESTED_COVERAGE_PROFILE | typeof WORKSPACE_SYNC_V3_WORKFLOW_COVERAGE_PROFILE | typeof WORKSPACE_SYNC_V3_PLANNING_ORDER_COVERAGE_PROFILE;
|
|
25
|
+
coverage: typeof WORKSPACE_SYNC_V3_COMBINED_COVERAGE_PROFILE | typeof WORKSPACE_SYNC_V3_NESTED_COVERAGE_PROFILE | typeof WORKSPACE_SYNC_V3_WORKFLOW_COVERAGE_PROFILE | typeof WORKSPACE_SYNC_V3_PLANNING_ORDER_COVERAGE_PROFILE | typeof WORKSPACE_SYNC_V3_TASK_COVER_COVERAGE_PROFILE;
|
|
25
26
|
snapshotId: string;
|
|
26
27
|
snapshotSequence: string;
|
|
27
28
|
expiresAt: string;
|
|
@@ -47,6 +48,8 @@ export declare function decodeWorkspaceSyncV3CombinedRepairCursor(raw: string |
|
|
|
47
48
|
export declare function decodeWorkspaceSyncV3NestedRepairCursor(raw: string | null | undefined, keyring: WorkspaceSyncV3FeedCursorKeyring): WorkspaceSyncV3CombinedRepairCursor | null;
|
|
48
49
|
export declare function decodeWorkspaceSyncV3WorkflowRepairCursor(raw: string | null | undefined, keyring: WorkspaceSyncV3FeedCursorKeyring): WorkspaceSyncV3CombinedRepairCursor | null;
|
|
49
50
|
export declare function decodeWorkspaceSyncV3PlanningOrderRepairCursor(raw: string | null | undefined, keyring: WorkspaceSyncV3FeedCursorKeyring): WorkspaceSyncV3CombinedRepairCursor | null;
|
|
51
|
+
export declare function decodeWorkspaceSyncV3TaskCoverRepairCursor(raw: string | null | undefined, keyring: WorkspaceSyncV3FeedCursorKeyring): WorkspaceSyncV3CombinedRepairCursor | null;
|
|
52
|
+
export declare const WORKSPACE_SYNC_REPAIR_SNAPSHOT_CLEANUP_BATCH_SIZE = 500;
|
|
50
53
|
export declare function buildWorkspaceSyncV3CombinedRepairPage(input: {
|
|
51
54
|
core: TaskforceCore;
|
|
52
55
|
workspaceId: string;
|
|
@@ -59,8 +62,10 @@ export declare function buildWorkspaceSyncV3CombinedRepairPage(input: {
|
|
|
59
62
|
nestedCoverage?: boolean;
|
|
60
63
|
workflowCoverage?: boolean;
|
|
61
64
|
planningOrderCoverage?: boolean;
|
|
65
|
+
taskCoverCoverage?: boolean;
|
|
62
66
|
coveredLegacyWritesFenced?: boolean;
|
|
63
67
|
}): WorkspaceSyncV3CombinedRepairPage;
|
|
64
|
-
export declare function buildWorkspaceSyncV3NestedRepairPage(input: Omit<Parameters<typeof buildWorkspaceSyncV3CombinedRepairPage>[0], 'nestedCoverage' | 'workflowCoverage' | 'planningOrderCoverage'>): WorkspaceSyncV3CombinedRepairPage;
|
|
65
|
-
export declare function buildWorkspaceSyncV3WorkflowRepairPage(input: Omit<Parameters<typeof buildWorkspaceSyncV3CombinedRepairPage>[0], 'nestedCoverage' | 'workflowCoverage' | 'planningOrderCoverage'>): WorkspaceSyncV3CombinedRepairPage;
|
|
66
|
-
export declare function buildWorkspaceSyncV3PlanningOrderRepairPage(input: Omit<Parameters<typeof buildWorkspaceSyncV3CombinedRepairPage>[0], 'nestedCoverage' | 'workflowCoverage' | 'planningOrderCoverage'>): WorkspaceSyncV3CombinedRepairPage;
|
|
68
|
+
export declare function buildWorkspaceSyncV3NestedRepairPage(input: Omit<Parameters<typeof buildWorkspaceSyncV3CombinedRepairPage>[0], 'nestedCoverage' | 'workflowCoverage' | 'planningOrderCoverage' | 'taskCoverCoverage'>): WorkspaceSyncV3CombinedRepairPage;
|
|
69
|
+
export declare function buildWorkspaceSyncV3WorkflowRepairPage(input: Omit<Parameters<typeof buildWorkspaceSyncV3CombinedRepairPage>[0], 'nestedCoverage' | 'workflowCoverage' | 'planningOrderCoverage' | 'taskCoverCoverage'>): WorkspaceSyncV3CombinedRepairPage;
|
|
70
|
+
export declare function buildWorkspaceSyncV3PlanningOrderRepairPage(input: Omit<Parameters<typeof buildWorkspaceSyncV3CombinedRepairPage>[0], 'nestedCoverage' | 'workflowCoverage' | 'planningOrderCoverage' | 'taskCoverCoverage'>): WorkspaceSyncV3CombinedRepairPage;
|
|
71
|
+
export declare function buildWorkspaceSyncV3TaskCoverRepairPage(input: Omit<Parameters<typeof buildWorkspaceSyncV3CombinedRepairPage>[0], 'nestedCoverage' | 'workflowCoverage' | 'planningOrderCoverage' | 'taskCoverCoverage'>): WorkspaceSyncV3CombinedRepairPage;
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { createHmac, randomUUID, timingSafeEqual } from 'crypto';
|
|
2
2
|
import { canonicalWorkspaceSyncJson } from './canonicalWorkspaceSyncJson.js';
|
|
3
3
|
import { decodeCanonicalWorkspaceSyncBase64Url } from './workspaceSyncV3CursorEncoding.js';
|
|
4
|
-
import { prepareWorkspaceSyncV3CombinedRepairSnapshot, prepareWorkspaceSyncV3NestedRepairSnapshot, prepareWorkspaceSyncV3PlanningOrderRepairSnapshot, prepareWorkspaceSyncV3WorkflowRepairSnapshot, } from './workspaceSyncV3CombinedRepairBaseline.js';
|
|
4
|
+
import { prepareWorkspaceSyncV3CombinedRepairSnapshot, prepareWorkspaceSyncV3NestedRepairSnapshot, prepareWorkspaceSyncV3PlanningOrderRepairSnapshot, prepareWorkspaceSyncV3TaskCoverRepairSnapshot, prepareWorkspaceSyncV3WorkflowRepairSnapshot, } from './workspaceSyncV3CombinedRepairBaseline.js';
|
|
5
5
|
import { validateWorkspaceSyncV3CombinedFeedEntry, WORKSPACE_SYNC_V3_COMBINED_COVERAGE_PROFILE, } from './workspaceSyncV3CombinedCoverage.js';
|
|
6
6
|
import { validateWorkspaceSyncV3NestedCoverageFeedEntry, WORKSPACE_SYNC_V3_NESTED_COVERAGE_PROFILE, } from './workspaceSyncV3NestedCoverage.js';
|
|
7
7
|
import { validateWorkspaceSyncV3WorkflowCoverageFeedEntry, WORKSPACE_SYNC_V3_WORKFLOW_COVERAGE_PROFILE, } from './workspaceSyncV3WorkflowCoverage.js';
|
|
8
8
|
import { validateWorkspaceSyncV3PlanningOrderCoverageFeedEntry, WORKSPACE_SYNC_V3_PLANNING_ORDER_COVERAGE_PROFILE, } from './workspaceSyncV3PlanningOrderCoverage.js';
|
|
9
|
+
import { validateWorkspaceSyncV3TaskCoverCoverageFeedEntry, WORKSPACE_SYNC_V3_TASK_COVER_COVERAGE_PROFILE, } from './workspaceSyncV3TaskCoverCoverage.js';
|
|
9
10
|
import { createWorkspaceSyncV3FeedResumeCursor, WorkspaceSyncV3FeedOperationTooLargeError, } from './workspaceSyncV3Feed.js';
|
|
10
11
|
import { findWorkspaceSyncV3FeedCursorVerificationKey, } from './workspaceSyncV3FeedCursorKeys.js';
|
|
11
12
|
import { WORKSPACE_SYNC_COMBINED_PROJECTION, WORKSPACE_SYNC_CONTRACT_VERSION, } from './syncDurabilityStore.js';
|
|
@@ -95,14 +96,19 @@ export function decodeWorkspaceSyncV3WorkflowRepairCursor(raw, keyring) {
|
|
|
95
96
|
export function decodeWorkspaceSyncV3PlanningOrderRepairCursor(raw, keyring) {
|
|
96
97
|
return decodeRepairCursor(raw, keyring, WORKSPACE_SYNC_V3_PLANNING_ORDER_COVERAGE_PROFILE);
|
|
97
98
|
}
|
|
99
|
+
export function decodeWorkspaceSyncV3TaskCoverRepairCursor(raw, keyring) {
|
|
100
|
+
return decodeRepairCursor(raw, keyring, WORKSPACE_SYNC_V3_TASK_COVER_COVERAGE_PROFILE);
|
|
101
|
+
}
|
|
98
102
|
function repairProfile(coverage) {
|
|
99
103
|
return coverage === 'workflow'
|
|
100
104
|
? WORKSPACE_SYNC_V3_WORKFLOW_COVERAGE_PROFILE
|
|
101
|
-
: coverage === '
|
|
102
|
-
?
|
|
103
|
-
: coverage === '
|
|
104
|
-
?
|
|
105
|
-
:
|
|
105
|
+
: coverage === 'task-cover'
|
|
106
|
+
? WORKSPACE_SYNC_V3_TASK_COVER_COVERAGE_PROFILE
|
|
107
|
+
: coverage === 'planning-order'
|
|
108
|
+
? WORKSPACE_SYNC_V3_PLANNING_ORDER_COVERAGE_PROFILE
|
|
109
|
+
: coverage === 'nested'
|
|
110
|
+
? WORKSPACE_SYNC_V3_NESTED_COVERAGE_PROFILE
|
|
111
|
+
: WORKSPACE_SYNC_V3_COMBINED_COVERAGE_PROFILE;
|
|
106
112
|
}
|
|
107
113
|
function containsCurrentEntityEventInventory(input) {
|
|
108
114
|
if (input.coverage === 'combined')
|
|
@@ -140,27 +146,70 @@ function containsCurrentEntityEventInventory(input) {
|
|
|
140
146
|
AND entry.domain = 'entity-event'
|
|
141
147
|
AND entry.entity_id = event.id
|
|
142
148
|
)
|
|
149
|
+
AND NOT EXISTS (
|
|
150
|
+
SELECT 1
|
|
151
|
+
FROM workspace_sync_journal journal
|
|
152
|
+
WHERE journal.tenant_id = event.tenant_id
|
|
153
|
+
AND journal.workspace_id = event.workspace_id
|
|
154
|
+
AND journal.domain = 'entity-event'
|
|
155
|
+
AND journal.entity_id = event.id
|
|
156
|
+
-- Later sequenced events are delivered after the immutable
|
|
157
|
+
-- repair boundary; only unsequenced legacy adoption makes the
|
|
158
|
+
-- snapshot incomplete and requires rematerialization.
|
|
159
|
+
AND journal.sequence > ?
|
|
160
|
+
)
|
|
143
161
|
LIMIT 1
|
|
144
|
-
`).get(input.tenantId, input.workspaceId, input.snapshotId);
|
|
162
|
+
`).get(input.tenantId, input.workspaceId, input.snapshotId, input.snapshotSequence);
|
|
145
163
|
return !missing;
|
|
146
164
|
}
|
|
147
|
-
|
|
165
|
+
export const WORKSPACE_SYNC_REPAIR_SNAPSHOT_CLEANUP_BATCH_SIZE = 500;
|
|
166
|
+
function cleanupExpiredBestEffort(core, tenantId, workspaceId, now, excludingSnapshotId) {
|
|
148
167
|
const db = core.getDatabaseAdapter();
|
|
149
168
|
const exclusion = excludingSnapshotId ? ' AND snapshot_id <> ?' : '';
|
|
150
169
|
const args = excludingSnapshotId
|
|
151
170
|
? [tenantId, workspaceId, now, excludingSnapshotId]
|
|
152
171
|
: [tenantId, workspaceId, now];
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
172
|
+
try {
|
|
173
|
+
db.transaction(() => {
|
|
174
|
+
const expired = db.prepare(`
|
|
175
|
+
SELECT snapshot_id
|
|
176
|
+
FROM workspace_sync_repair_snapshots
|
|
177
|
+
WHERE tenant_id = ? AND workspace_id = ? AND expires_at <= ?${exclusion}
|
|
178
|
+
ORDER BY expires_at ASC, snapshot_id ASC
|
|
179
|
+
LIMIT 1
|
|
180
|
+
`).get(...args);
|
|
181
|
+
const snapshotId = String(expired?.snapshot_id || '').trim();
|
|
182
|
+
if (!snapshotId)
|
|
183
|
+
return;
|
|
184
|
+
db.prepare(`
|
|
185
|
+
DELETE FROM workspace_sync_repair_snapshot_entries
|
|
186
|
+
WHERE tenant_id = ? AND workspace_id = ? AND snapshot_id = ?
|
|
187
|
+
AND entry_index IN (
|
|
188
|
+
SELECT entry_index
|
|
189
|
+
FROM workspace_sync_repair_snapshot_entries
|
|
190
|
+
WHERE tenant_id = ? AND workspace_id = ? AND snapshot_id = ?
|
|
191
|
+
ORDER BY entry_index ASC
|
|
192
|
+
LIMIT ?
|
|
193
|
+
)
|
|
194
|
+
`).run(tenantId, workspaceId, snapshotId, tenantId, workspaceId, snapshotId, WORKSPACE_SYNC_REPAIR_SNAPSHOT_CLEANUP_BATCH_SIZE);
|
|
195
|
+
db.prepare(`
|
|
196
|
+
DELETE FROM workspace_sync_repair_snapshots
|
|
197
|
+
WHERE tenant_id = ? AND workspace_id = ? AND snapshot_id = ? AND expires_at <= ?
|
|
198
|
+
AND NOT EXISTS (
|
|
199
|
+
SELECT 1 FROM workspace_sync_repair_snapshot_entries
|
|
200
|
+
WHERE tenant_id = ? AND workspace_id = ? AND snapshot_id = ?
|
|
201
|
+
)
|
|
202
|
+
`).run(tenantId, workspaceId, snapshotId, now, tenantId, workspaceId, snapshotId);
|
|
203
|
+
})();
|
|
204
|
+
}
|
|
205
|
+
catch (error) {
|
|
206
|
+
// Expired snapshot removal is opportunistic maintenance. A cleanup
|
|
207
|
+
// timeout must not invalidate an otherwise valid repair response.
|
|
208
|
+
console.warn('[Taskforce Sync Repair Cleanup Deferred]', JSON.stringify({
|
|
209
|
+
workspaceId,
|
|
210
|
+
error: String(error?.message || error),
|
|
211
|
+
}));
|
|
212
|
+
}
|
|
164
213
|
}
|
|
165
214
|
function persistMaterialization(input) {
|
|
166
215
|
const db = input.core.getDatabaseAdapter();
|
|
@@ -225,6 +274,7 @@ function readMetadata(input) {
|
|
|
225
274
|
tenantId: input.tenantId,
|
|
226
275
|
workspaceId: input.workspaceId,
|
|
227
276
|
snapshotId: input.cursor.snapshotId,
|
|
277
|
+
snapshotSequence: input.cursor.snapshotSequence,
|
|
228
278
|
coverage: input.coverage,
|
|
229
279
|
})) {
|
|
230
280
|
throw new WorkspaceSyncV3CombinedRepairSnapshotUnavailableError();
|
|
@@ -275,6 +325,7 @@ function readReusableMetadata(input) {
|
|
|
275
325
|
tenantId: input.tenantId,
|
|
276
326
|
workspaceId: input.workspaceId,
|
|
277
327
|
snapshotId: String(row.snapshot_id),
|
|
328
|
+
snapshotSequence: sequence(row.snapshot_sequence, 'Combined repair snapshot sequence'),
|
|
278
329
|
coverage: input.coverage,
|
|
279
330
|
}))
|
|
280
331
|
return null;
|
|
@@ -306,11 +357,13 @@ function mapEntry(row, coverage) {
|
|
|
306
357
|
};
|
|
307
358
|
(coverage === 'workflow'
|
|
308
359
|
? validateWorkspaceSyncV3WorkflowCoverageFeedEntry
|
|
309
|
-
: coverage === '
|
|
310
|
-
?
|
|
311
|
-
: coverage === '
|
|
312
|
-
?
|
|
313
|
-
:
|
|
360
|
+
: coverage === 'task-cover'
|
|
361
|
+
? validateWorkspaceSyncV3TaskCoverCoverageFeedEntry
|
|
362
|
+
: coverage === 'planning-order'
|
|
363
|
+
? validateWorkspaceSyncV3PlanningOrderCoverageFeedEntry
|
|
364
|
+
: coverage === 'nested'
|
|
365
|
+
? validateWorkspaceSyncV3NestedCoverageFeedEntry
|
|
366
|
+
: validateWorkspaceSyncV3CombinedFeedEntry)(entry);
|
|
314
367
|
return entry;
|
|
315
368
|
}
|
|
316
369
|
function finalizePage(input) {
|
|
@@ -369,22 +422,15 @@ export function buildWorkspaceSyncV3CombinedRepairPage(input) {
|
|
|
369
422
|
const db = input.core.getDatabaseAdapter();
|
|
370
423
|
const coverage = input.workflowCoverage
|
|
371
424
|
? 'workflow'
|
|
372
|
-
: input.
|
|
373
|
-
? '
|
|
374
|
-
: input.
|
|
375
|
-
? '
|
|
376
|
-
:
|
|
425
|
+
: input.taskCoverCoverage
|
|
426
|
+
? 'task-cover'
|
|
427
|
+
: input.planningOrderCoverage
|
|
428
|
+
? 'planning-order'
|
|
429
|
+
: input.nestedCoverage
|
|
430
|
+
? 'nested'
|
|
431
|
+
: 'combined';
|
|
377
432
|
if (input.cursor && Date.parse(input.cursor.expiresAt) <= Date.parse(now)) {
|
|
378
|
-
|
|
379
|
-
db.prepare(`DELETE FROM workspace_sync_repair_snapshot_entries
|
|
380
|
-
WHERE tenant_id = ? AND workspace_id = ? AND snapshot_id = ? AND EXISTS (
|
|
381
|
-
SELECT 1 FROM workspace_sync_repair_snapshots
|
|
382
|
-
WHERE tenant_id = ? AND workspace_id = ? AND snapshot_id = ? AND expires_at <= ?
|
|
383
|
-
)`).run(tenantId, workspaceId, input.cursor.snapshotId, tenantId, workspaceId, input.cursor.snapshotId, now);
|
|
384
|
-
db.prepare(`DELETE FROM workspace_sync_repair_snapshots
|
|
385
|
-
WHERE tenant_id = ? AND workspace_id = ? AND snapshot_id = ? AND expires_at <= ?`)
|
|
386
|
-
.run(tenantId, workspaceId, input.cursor.snapshotId, now);
|
|
387
|
-
})();
|
|
433
|
+
cleanupExpiredBestEffort(input.core, tenantId, workspaceId, now);
|
|
388
434
|
throw new WorkspaceSyncV3CombinedRepairSnapshotUnavailableError();
|
|
389
435
|
}
|
|
390
436
|
let insertedBaselineEntities = 0;
|
|
@@ -393,17 +439,17 @@ export function buildWorkspaceSyncV3CombinedRepairPage(input) {
|
|
|
393
439
|
let metadata;
|
|
394
440
|
let nextIndex;
|
|
395
441
|
if (input.cursor) {
|
|
442
|
+
cleanupExpiredBestEffort(input.core, tenantId, workspaceId, now, input.cursor.snapshotId);
|
|
396
443
|
metadata = db.transaction(() => {
|
|
397
|
-
|
|
444
|
+
return readMetadata({
|
|
398
445
|
core: input.core, tenantId, workspaceId, cursor: input.cursor, now,
|
|
399
446
|
coverage,
|
|
400
447
|
});
|
|
401
|
-
cleanupExpired(input.core, tenantId, workspaceId, now, current.snapshotId);
|
|
402
|
-
return current;
|
|
403
448
|
})();
|
|
404
449
|
nextIndex = input.cursor.nextIndex;
|
|
405
450
|
}
|
|
406
451
|
else {
|
|
452
|
+
cleanupExpiredBestEffort(input.core, tenantId, workspaceId, now);
|
|
407
453
|
const materialized = db.transaction(() => {
|
|
408
454
|
// Serialize cursorless materialization and reuse decisions with
|
|
409
455
|
// durable writers and competing repair requests.
|
|
@@ -413,7 +459,6 @@ export function buildWorkspaceSyncV3CombinedRepairPage(input) {
|
|
|
413
459
|
ON CONFLICT (tenant_id, workspace_id) DO UPDATE SET updated_at = excluded.updated_at
|
|
414
460
|
RETURNING CAST(last_sequence AS TEXT) AS last_sequence
|
|
415
461
|
`).get(tenantId, workspaceId, now);
|
|
416
|
-
cleanupExpired(input.core, tenantId, workspaceId, now);
|
|
417
462
|
const reusable = readReusableMetadata({
|
|
418
463
|
core: input.core, tenantId, workspaceId, now,
|
|
419
464
|
coverage,
|
|
@@ -428,11 +473,14 @@ export function buildWorkspaceSyncV3CombinedRepairPage(input) {
|
|
|
428
473
|
: coverage === 'planning-order'
|
|
429
474
|
? prepareWorkspaceSyncV3PlanningOrderRepairSnapshot({ core: input.core, workspaceId, now,
|
|
430
475
|
coveredLegacyWritesFenced: input.coveredLegacyWritesFenced })
|
|
431
|
-
: coverage === '
|
|
432
|
-
?
|
|
476
|
+
: coverage === 'task-cover'
|
|
477
|
+
? prepareWorkspaceSyncV3TaskCoverRepairSnapshot({ core: input.core, workspaceId, now,
|
|
433
478
|
coveredLegacyWritesFenced: input.coveredLegacyWritesFenced })
|
|
434
|
-
:
|
|
435
|
-
|
|
479
|
+
: coverage === 'nested'
|
|
480
|
+
? prepareWorkspaceSyncV3NestedRepairSnapshot({ core: input.core, workspaceId, now,
|
|
481
|
+
coveredLegacyWritesFenced: input.coveredLegacyWritesFenced })
|
|
482
|
+
: prepareWorkspaceSyncV3CombinedRepairSnapshot({ core: input.core, workspaceId, now,
|
|
483
|
+
coveredLegacyWritesFenced: input.coveredLegacyWritesFenced });
|
|
436
484
|
// Production expiry is sampled at the end of persistence, after
|
|
437
485
|
// every immutable payload row has committed in the same lock.
|
|
438
486
|
const materializationStartedAt = input.now
|
|
@@ -525,3 +573,6 @@ export function buildWorkspaceSyncV3WorkflowRepairPage(input) {
|
|
|
525
573
|
export function buildWorkspaceSyncV3PlanningOrderRepairPage(input) {
|
|
526
574
|
return buildWorkspaceSyncV3CombinedRepairPage({ ...input, planningOrderCoverage: true });
|
|
527
575
|
}
|
|
576
|
+
export function buildWorkspaceSyncV3TaskCoverRepairPage(input) {
|
|
577
|
+
return buildWorkspaceSyncV3CombinedRepairPage({ ...input, taskCoverCoverage: true });
|
|
578
|
+
}
|
|
@@ -31,6 +31,8 @@ export declare class WorkspaceSyncV3CombinedRepairBaselineRequiredError extends
|
|
|
31
31
|
export declare function listWorkspaceSyncV3CombinedRepairCandidates(core: TaskforceCore, workspaceId: string): WorkspaceSyncV3CombinedRepairCandidate[];
|
|
32
32
|
/** Candidate v4 inventory. The coverage-v3 inventory above intentionally remains unchanged. */
|
|
33
33
|
export declare function listWorkspaceSyncV3NestedRepairCandidates(core: TaskforceCore, workspaceId: string): WorkspaceSyncV3CombinedRepairCandidate[];
|
|
34
|
+
/** Candidate v7 inventory. It is the v4 family with attachment-link schema v2. */
|
|
35
|
+
export declare function listWorkspaceSyncV3TaskCoverRepairCandidates(core: TaskforceCore, workspaceId: string): WorkspaceSyncV3CombinedRepairCandidate[];
|
|
34
36
|
/** Candidate v5 inventory. Coverage-v3/v4 inventories intentionally remain unchanged. */
|
|
35
37
|
export declare function listWorkspaceSyncV3WorkflowRepairCandidates(core: TaskforceCore, workspaceId: string): WorkspaceSyncV3CombinedRepairCandidate[];
|
|
36
38
|
/** Candidate v6 inventory. Workflow v5 remains an independent dark contract. */
|
|
@@ -50,6 +52,7 @@ export declare function buildWorkspaceSyncV3CombinedRepairSnapshotFromLockedCand
|
|
|
50
52
|
nestedCoverage?: boolean;
|
|
51
53
|
workflowCoverage?: boolean;
|
|
52
54
|
planningOrderCoverage?: boolean;
|
|
55
|
+
taskCoverCoverage?: boolean;
|
|
53
56
|
}): {
|
|
54
57
|
snapshotSequence: string;
|
|
55
58
|
entries: WorkspaceSyncV3FeedEntry[];
|
|
@@ -75,4 +78,11 @@ export declare function buildWorkspaceSyncV3PlanningOrderRepairSnapshot(input: {
|
|
|
75
78
|
snapshotSequence: string;
|
|
76
79
|
entries: WorkspaceSyncV3FeedEntry[];
|
|
77
80
|
};
|
|
81
|
+
export declare function buildWorkspaceSyncV3TaskCoverRepairSnapshot(input: {
|
|
82
|
+
core: TaskforceCore;
|
|
83
|
+
workspaceId: string;
|
|
84
|
+
}): {
|
|
85
|
+
snapshotSequence: string;
|
|
86
|
+
entries: WorkspaceSyncV3FeedEntry[];
|
|
87
|
+
};
|
|
78
88
|
export {};
|