@taskforcehq/taskforce 0.3.327 → 0.3.328
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 +24 -53
- package/dist/components/activity/EntityActivityTimeline.js +15 -5
- package/dist/components/context/AttachmentPreviewHost.js +1 -1
- package/dist/components/context/ContextAttachmentManager.d.ts +3 -0
- package/dist/components/context/ContextAttachmentManager.js +116 -20
- package/dist/components/features/planning/PlanningEntitySummary.d.ts +3 -1
- package/dist/components/features/planning/PlanningEntitySummary.js +3 -2
- package/dist/components/features/planning/PlanningLinkPicker.d.ts +3 -1
- package/dist/components/features/planning/PlanningLinkPicker.js +5 -3
- package/dist/components/features/planning/PlanningModule.js +26 -9
- package/dist/components/features/planning/PlanningVisualIdentity.d.ts +14 -0
- package/dist/components/features/planning/PlanningVisualIdentity.js +106 -0
- package/dist/components/features/planning/planningWorkspaceModel.d.ts +11 -0
- package/dist/components/task/TaskActionHeader.d.ts +2 -1
- package/dist/components/task/TaskActionHeader.js +2 -2
- package/dist/components/task/TaskCard.js +37 -4
- package/dist/components/task/TaskContextUpload.d.ts +3 -0
- package/dist/components/task/TaskContextUpload.js +2 -2
- package/dist/components/task/TaskForm.d.ts +4 -0
- package/dist/components/task/TaskForm.js +32 -7
- package/dist/components/task/TaskImageReviews.js +16 -16
- package/dist/components/task/TaskStatusActions.js +11 -2
- package/dist/components/task/TaskWorkstreamPicker.js +2 -1
- package/dist/components/ui/DocumentTypeIcon.d.ts +7 -0
- package/dist/components/ui/DocumentTypeIcon.js +8 -0
- package/dist/components/ui/TaxonomyDropdown.d.ts +9 -1
- package/dist/components/ui/TaxonomyDropdown.js +30 -3
- package/dist/components/views/StandaloneLayout.js +62 -9
- package/dist/components/views/WidgetView.js +8 -5
- package/dist/components/views/panels/PlanningDrawer.d.ts +7 -1
- package/dist/components/views/panels/PlanningDrawer.js +48 -44
- package/dist/config/envSchema.js +1 -0
- package/dist/config/localServiceCloudTarget.d.ts +10 -0
- package/dist/config/localServiceCloudTarget.js +76 -0
- package/dist/core/AiProfileService.d.ts +1 -0
- package/dist/core/AiProfileService.js +2 -1
- package/dist/core/AttachmentLinkService.js +7 -4
- package/dist/core/DeletedTaskLifecycleService.d.ts +4 -0
- package/dist/core/DeletedTaskLifecycleService.js +21 -0
- package/dist/core/McpTokenService.d.ts +4 -0
- package/dist/core/McpTokenService.js +52 -0
- package/dist/core/TaskAttachmentLinksDurableMutationService.d.ts +5 -0
- package/dist/core/TaskAttachmentLinksDurableMutationService.js +20 -11
- package/dist/core/Taskforce.d.ts +63 -1
- package/dist/core/Taskforce.js +558 -73
- package/dist/core/types.d.ts +2 -1
- package/dist/documentReviews/DocumentReviewCommentStore.d.ts +11 -0
- package/dist/documentReviews/DocumentReviewCommentStore.js +35 -2
- package/dist/documentReviews/service.d.ts +4 -0
- package/dist/documentReviews/service.js +141 -46
- package/dist/hooks/tasks/useTaskFormActions.d.ts +3 -0
- package/dist/hooks/tasks/useTaskFormActions.js +33 -7
- package/dist/hooks/useTaskforce.d.ts +59 -50
- package/dist/hooks/useTaskforce.js +103 -1
- package/dist/mcp/canonicalAssetHelpers.d.ts +13 -0
- package/dist/mcp/canonicalAssetHelpers.js +39 -5
- package/dist/mcp/collaborationRegistrar.js +15 -13
- package/dist/mcp/documentAssetRegistrar.js +16 -9
- package/dist/mcp/localServiceProxy.js +4 -1
- package/dist/mcp/runtime.d.ts +16 -0
- package/dist/mcp/runtime.js +566 -171
- package/dist/mcp/taskAttachmentCommandAdapter.d.ts +2 -0
- package/dist/mcp/taskAttachmentCommandAdapter.js +14 -8
- package/dist/mcp/taskPlanningRegistrar.js +42 -34
- package/dist/mcp/toolRegistry.js +2 -2
- package/dist/migrations/taskSchemaMigrations.js +35 -0
- package/dist/runtime/appGateDefinitions.d.ts +2 -2
- package/dist/runtime/appGateDefinitions.js +2 -2
- package/dist/server/appAccess.d.ts +12 -0
- package/dist/server/appAccess.js +21 -0
- package/dist/server/authorizedWorkspaceAccess.d.ts +12 -0
- package/dist/server/authorizedWorkspaceAccess.js +40 -0
- package/dist/server/cloudCollectionRead.d.ts +25 -0
- package/dist/server/cloudCollectionRead.js +120 -0
- package/dist/server/cloudCollectionReadPool.d.ts +52 -0
- package/dist/server/cloudCollectionReadPool.js +140 -0
- package/dist/server/cloudCollectionReadWorker.d.ts +1 -0
- package/dist/server/cloudCollectionReadWorker.js +36 -0
- package/dist/server/index.d.ts +3 -11
- package/dist/server/index.js +53 -40
- package/dist/server/localServiceLease.d.ts +3 -0
- package/dist/server/localServiceLease.js +9 -1
- package/dist/server/routes/documents.d.ts +5 -2
- package/dist/server/routes/documents.js +160 -13
- package/dist/server/routes/durableTaskHttpRouters.d.ts +2 -0
- package/dist/server/routes/durableTaskHttpRouters.js +2 -2
- package/dist/server/routes/localService.js +2 -0
- package/dist/server/routes/primitives.d.ts +2 -0
- package/dist/server/routes/shared.d.ts +24 -0
- package/dist/server/routes/shared.js +114 -18
- package/dist/server/routes/sync.js +22 -0
- package/dist/server/routes/syncV3FeedRoutes.js +4 -2
- package/dist/server/routes/syncV3LocalCaptureRoutes.js +20 -2
- package/dist/server/routes/syncV3OperationRoutes.js +17 -2
- package/dist/server/routes/tasks.js +199 -89
- package/dist/server/routes.js +35 -7
- package/dist/service/localServiceCli.js +36 -25
- package/dist/service/localServiceClientLifecycle.js +67 -6
- package/dist/shared/planningIdentity.d.ts +20 -0
- package/dist/shared/planningIdentity.js +79 -0
- package/dist/storage/postgresAdapter.js +4 -0
- package/dist/storage/postgresRequestDiagnostics.d.ts +8 -0
- package/dist/storage/postgresRequestDiagnostics.js +24 -0
- package/dist/storage/workspaceAssetStore.d.ts +32 -0
- package/dist/storage/workspaceAssetStore.js +70 -0
- package/dist/sync/coordinator/localSyncExecutionPermitStore.d.ts +16 -0
- package/dist/sync/coordinator/localSyncExecutionPermitStore.js +70 -22
- package/dist/sync/coordinator/workspaceSyncTransportGateway.js +4 -2
- package/dist/sync/engine/workspaceSyncEngineRemoteServices.d.ts +5 -0
- package/dist/sync/engine/workspaceSyncEngineServerRemoteServices.d.ts +1 -1
- package/dist/sync/engine/workspaceSyncEngineServerRemoteServices.js +15 -0
- package/dist/sync/engine/workspaceSyncEngineServerRunnerOperations.js +26 -3
- package/dist/sync/engine/workspaceSyncV2ChangeDispatcher.js +2 -0
- package/dist/sync/syncApplyHandlers.d.ts +3 -1
- package/dist/sync/syncApplyHandlers.js +29 -0
- package/dist/sync/syncService.js +9 -0
- package/dist/sync/taskSyncPayload.d.ts +1 -0
- package/dist/sync/taskSyncPayload.js +6 -0
- package/dist/sync/v3/durableTaskAttachmentLinksMutationRouter.d.ts +1 -0
- package/dist/sync/v3/durableTaskAttachmentLinksMutationRouter.js +21 -3
- package/dist/sync/v3/durableTaskHttpBulkMutationRouter.js +17 -4
- package/dist/sync/v3/localInitiativeOutboxService.js +4 -2
- package/dist/sync/v3/localOutboxDispatcher.js +5 -1
- package/dist/sync/v3/localTaskAttachmentLinksOutboxHandler.js +12 -2
- package/dist/sync/v3/localTaskAttachmentLinksOutboxService.d.ts +1 -0
- package/dist/sync/v3/localTaskAttachmentLinksOutboxService.js +15 -3
- package/dist/sync/v3/localWorkstreamOutboxService.js +4 -2
- package/dist/sync/v3/syncDurabilityStore.d.ts +8 -0
- package/dist/sync/v3/syncDurabilityStore.js +171 -33
- package/dist/sync/v3/taskAttachmentLinksMutationService.d.ts +1 -0
- package/dist/sync/v3/taskAttachmentLinksMutationService.js +18 -2
- package/dist/sync/v3/taskMetadataCoexistence.js +4 -0
- package/dist/sync/v3/workspaceSyncV2ProjectionExclusions.js +1 -9
- package/dist/sync/v3/workspaceSyncV3CloudOperationHandler.js +1 -0
- package/dist/sync/v3/workspaceSyncV3CombinedFeedOrchestrator.js +7 -1
- package/dist/sync/v3/workspaceSyncV3CombinedLocalApply.js +15 -3
- package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.d.ts +4 -0
- package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.js +29 -6
- package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.d.ts +1 -0
- package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.js +29 -7
- package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.js +62 -7
- package/dist/sync/v3/workspaceSyncV3OperationProtocol.d.ts +1 -0
- package/dist/sync/v3/workspaceSyncV3RepairSqlBatching.d.ts +2 -0
- package/dist/sync/v3/workspaceSyncV3RepairSqlBatching.js +10 -0
- package/dist/sync/v3/workspaceSyncV3TaskRootProjection.d.ts +1 -1
- package/dist/sync/v3/workspaceSyncV3TaskRootProjection.js +1 -1
- package/dist/sync/workspacePullFeed.d.ts +6 -1
- package/dist/sync/workspacePullFeed.js +172 -161
- package/dist/sync/workspaceSyncModel.d.ts +11 -0
- package/dist/sync/workspaceSyncModel.js +27 -2
- package/dist/types.d.ts +8 -0
- package/dist/ui/assets/{AiIdentityRosterCard-DB1BLO_j.js → AiIdentityRosterCard-MZs7lVED.js} +1 -1
- package/dist/ui/assets/{AiProfilesModule-DPxQeF9N.js → AiProfilesModule-C3i0LOxe.js} +1 -1
- package/dist/ui/assets/{AnnotatedAttachmentWorkspace-DHNYaNg6.js → AnnotatedAttachmentWorkspace-DVZk5Tln.js} +1 -1
- package/dist/ui/assets/AssetTraySortControl-Kf1pelSy.js +1 -0
- package/dist/ui/assets/ContextAttachmentManager-B8boOs6Q.js +3 -0
- package/dist/ui/assets/{DocumentWorkspace-BC7sy5TG.js → DocumentWorkspace-DXH4XUsB.js} +4 -4
- package/dist/ui/assets/EntityActivityTimeline-BtSTq0ON.js +1 -0
- package/dist/ui/assets/PlanningModule-BPVyEa-f.js +1 -0
- package/dist/ui/assets/PlanningModule-CoIR9hbV.css +1 -0
- package/dist/ui/assets/{PlansPage-BVH_NfgT.js → PlansPage-ChqgxALc.js} +1 -1
- package/dist/ui/assets/TaskContextUpload-CB3ol0sN.js +1 -0
- package/dist/ui/assets/TaskContextUpload-qmBeUw3u.css +1 -0
- package/dist/ui/assets/{TaskSettings-xVsxSa0g.js → TaskSettings-g4ECKNOz.js} +1 -1
- package/dist/ui/assets/{TaskforceAgentsModule-CkAxW19K.js → TaskforceAgentsModule-BazdUwxZ.js} +1 -1
- package/dist/ui/assets/WorkflowManagerModule-DWFspC-o.js +1 -0
- package/dist/ui/assets/index-BUplSsv_.js +7 -0
- package/dist/ui/assets/index-gz2EXuoK.css +1 -0
- package/dist/ui/assets/{vendor-icons-B8ZNsH1g.js → vendor-icons-BkFLXavV.js} +1 -1
- package/dist/ui/index.html +3 -3
- package/dist/utils/constants.d.ts +2 -2
- package/dist/utils/constants.js +1 -1
- package/dist/utils/contextAttachmentUpload.d.ts +2 -0
- package/dist/utils/contextAttachmentUpload.js +7 -0
- package/dist/utils/contextFiles.d.ts +1 -1
- package/dist/utils/contextFiles.js +4 -4
- package/package.json +6 -1
- package/dist/ui/assets/AssetTraySortControl-DphbyHVc.js +0 -1
- package/dist/ui/assets/ContextAttachmentManager-CMxSzHqc.js +0 -3
- package/dist/ui/assets/EntityActivityTimeline-pJ2ZjZ-k.js +0 -1
- package/dist/ui/assets/PlanningModule-CeTqXMMz.css +0 -1
- package/dist/ui/assets/PlanningModule-t5GbvVR9.js +0 -1
- package/dist/ui/assets/TaskContextUpload-Ds4LnDzV.css +0 -1
- package/dist/ui/assets/TaskContextUpload-bl4fOOUz.js +0 -1
- package/dist/ui/assets/WorkflowManagerModule-BKqIGVnF.js +0 -1
- package/dist/ui/assets/index-BzJlVnNS.css +0 -1
- package/dist/ui/assets/index-Cx7vZJHL.js +0 -7
|
@@ -7,6 +7,7 @@ export declare function prepareWorkspaceSyncV3CombinedRepairSnapshot(input: {
|
|
|
7
7
|
nestedCoverage?: boolean;
|
|
8
8
|
workflowCoverage?: boolean;
|
|
9
9
|
planningOrderCoverage?: boolean;
|
|
10
|
+
coveredLegacyWritesFenced?: boolean;
|
|
10
11
|
}): {
|
|
11
12
|
highWatermark: string;
|
|
12
13
|
insertedEntities: number;
|
|
@@ -20,16 +21,19 @@ export declare function prepareWorkspaceSyncV3NestedRepairSnapshot(input: {
|
|
|
20
21
|
core: TaskforceCore;
|
|
21
22
|
workspaceId: string;
|
|
22
23
|
now?: string;
|
|
24
|
+
coveredLegacyWritesFenced?: boolean;
|
|
23
25
|
}): ReturnType<typeof prepareWorkspaceSyncV3CombinedRepairSnapshot>;
|
|
24
26
|
export declare function prepareWorkspaceSyncV3WorkflowRepairSnapshot(input: {
|
|
25
27
|
core: TaskforceCore;
|
|
26
28
|
workspaceId: string;
|
|
27
29
|
now?: string;
|
|
30
|
+
coveredLegacyWritesFenced?: boolean;
|
|
28
31
|
}): ReturnType<typeof prepareWorkspaceSyncV3CombinedRepairSnapshot>;
|
|
29
32
|
export declare function prepareWorkspaceSyncV3PlanningOrderRepairSnapshot(input: {
|
|
30
33
|
core: TaskforceCore;
|
|
31
34
|
workspaceId: string;
|
|
32
35
|
now?: string;
|
|
36
|
+
coveredLegacyWritesFenced?: boolean;
|
|
33
37
|
}): ReturnType<typeof prepareWorkspaceSyncV3CombinedRepairSnapshot>;
|
|
34
38
|
export declare function ensureWorkspaceSyncV3CombinedRepairBaselines(input: {
|
|
35
39
|
core: TaskforceCore;
|
|
@@ -12,7 +12,7 @@ import { serializeWorkspaceSyncV3TaskAttachmentLinksPayload, serializeWorkspaceS
|
|
|
12
12
|
import { projectWorkspaceSyncV3NestedTaskJournalRow } from './workspaceSyncV3NestedTaskProjection.js';
|
|
13
13
|
import { serializeTaskRelationshipForSync } from './workspaceSyncV3TaskRelationshipProjection.js';
|
|
14
14
|
import { projectWorkspaceSyncV3TaskRootJournalRow, serializeTaskRootForSync, } from './workspaceSyncV3TaskRootProjection.js';
|
|
15
|
-
|
|
15
|
+
import { workspaceSyncV3RepairEntityReadBatchSize } from './workspaceSyncV3RepairSqlBatching.js';
|
|
16
16
|
const BASELINE_CLIENT_ID = 'sync-v3-repair';
|
|
17
17
|
const LEGACY_REPAIRABLE_NESTED_DOMAINS = new Set([
|
|
18
18
|
'task-comments', 'task-checklist', 'task-attachment-links',
|
|
@@ -84,10 +84,11 @@ function lifecycleState(candidate) {
|
|
|
84
84
|
function readRevisions(input) {
|
|
85
85
|
const result = new Map();
|
|
86
86
|
const db = input.core.getDatabaseAdapter();
|
|
87
|
+
const batchSize = workspaceSyncV3RepairEntityReadBatchSize(db);
|
|
87
88
|
for (const domain of [...new Set(input.candidates.map((candidate) => candidate.domain))]) {
|
|
88
89
|
const ids = input.candidates.filter((candidate) => candidate.domain === domain).map((candidate) => candidate.entityId);
|
|
89
|
-
for (let offset = 0; offset < ids.length; offset +=
|
|
90
|
-
const batch = ids.slice(offset, offset +
|
|
90
|
+
for (let offset = 0; offset < ids.length; offset += batchSize) {
|
|
91
|
+
const batch = ids.slice(offset, offset + batchSize);
|
|
91
92
|
const placeholders = batch.map(() => '?').join(', ');
|
|
92
93
|
const rows = db.prepare(`
|
|
93
94
|
SELECT entity_id, contract_version,
|
|
@@ -250,6 +251,7 @@ export function prepareWorkspaceSyncV3CombinedRepairSnapshot(input) {
|
|
|
250
251
|
const tenantId = input.core.getTenantId();
|
|
251
252
|
const db = input.core.getDatabaseAdapter();
|
|
252
253
|
return db.transaction(() => {
|
|
254
|
+
const startedAt = Date.now();
|
|
253
255
|
const lock = db.prepare(`
|
|
254
256
|
INSERT INTO workspace_sync_sequences (tenant_id, workspace_id, last_sequence, updated_at)
|
|
255
257
|
VALUES (?, ?, 0, ?)
|
|
@@ -257,6 +259,7 @@ export function prepareWorkspaceSyncV3CombinedRepairSnapshot(input) {
|
|
|
257
259
|
RETURNING CAST(last_sequence AS TEXT) AS last_sequence
|
|
258
260
|
`).get(tenantId, workspaceId, now);
|
|
259
261
|
sequence(lock?.last_sequence);
|
|
262
|
+
const lockCompletedAt = Date.now();
|
|
260
263
|
const candidates = input.workflowCoverage
|
|
261
264
|
? listWorkspaceSyncV3WorkflowRepairCandidates(input.core, workspaceId)
|
|
262
265
|
: input.planningOrderCoverage
|
|
@@ -264,10 +267,12 @@ export function prepareWorkspaceSyncV3CombinedRepairSnapshot(input) {
|
|
|
264
267
|
: input.nestedCoverage
|
|
265
268
|
? listWorkspaceSyncV3NestedRepairCandidates(input.core, workspaceId)
|
|
266
269
|
: listWorkspaceSyncV3CombinedRepairCandidates(input.core, workspaceId);
|
|
270
|
+
const inventoryCompletedAt = Date.now();
|
|
267
271
|
const keys = candidates.map((candidate) => `${candidate.domain}\0${candidate.entityId}`);
|
|
268
272
|
if (new Set(keys).size !== keys.length)
|
|
269
273
|
throw new Error('Combined repair baseline contains duplicate entities.');
|
|
270
274
|
const revisions = readRevisions({ core: input.core, tenantId, workspaceId, candidates });
|
|
275
|
+
const revisionsCompletedAt = Date.now();
|
|
271
276
|
const missing = [];
|
|
272
277
|
const legacyRelationshipSkews = [];
|
|
273
278
|
const legacyNestedDrifts = [];
|
|
@@ -383,6 +388,7 @@ export function prepareWorkspaceSyncV3CombinedRepairSnapshot(input) {
|
|
|
383
388
|
});
|
|
384
389
|
}
|
|
385
390
|
}
|
|
391
|
+
const validationCompletedAt = Date.now();
|
|
386
392
|
const rowCount = legacyRelationshipSkews.length + legacyNestedDrifts.length + missing.reduce((count, candidate) => {
|
|
387
393
|
if (candidate.domain === 'workflow-published-definition'
|
|
388
394
|
|| candidate.domain === 'workflow-execution'
|
|
@@ -541,6 +547,7 @@ export function prepareWorkspaceSyncV3CombinedRepairSnapshot(input) {
|
|
|
541
547
|
if (Number(updated.changes) !== 1)
|
|
542
548
|
throw repairConflict('legacy-nested-repair-raced', repair.candidate);
|
|
543
549
|
}
|
|
550
|
+
const baselineWritesCompletedAt = Date.now();
|
|
544
551
|
const profile = input.workflowCoverage
|
|
545
552
|
? WORKSPACE_SYNC_V3_WORKFLOW_COVERAGE_PROFILE
|
|
546
553
|
: input.planningOrderCoverage
|
|
@@ -557,9 +564,10 @@ export function prepareWorkspaceSyncV3CombinedRepairSnapshot(input) {
|
|
|
557
564
|
`).get(tenantId, workspaceId, WORKSPACE_SYNC_COMBINED_PROJECTION, WORKSPACE_SYNC_CONTRACT_VERSION, profile.coverageProfileId, profile.coverageVersion, profile.coverageDigest);
|
|
558
565
|
// Exact active v3 ownership closes every ordinary writer over the same
|
|
559
566
|
// sequence lock, so the inventory read above remains the authoritative
|
|
560
|
-
// cut.
|
|
561
|
-
//
|
|
562
|
-
|
|
567
|
+
// cut. The cloud activation route may attest the same invariant by
|
|
568
|
+
// fencing covered legacy/v2 writers. Unfenced rollback repair still
|
|
569
|
+
// re-inventories because those writers do not reserve this lock.
|
|
570
|
+
const snapshot = activeOwner?.active === 1 || input.coveredLegacyWritesFenced === true
|
|
563
571
|
? buildWorkspaceSyncV3CombinedRepairSnapshotFromLockedCandidates({
|
|
564
572
|
core: input.core,
|
|
565
573
|
workspaceId,
|
|
@@ -576,9 +584,24 @@ export function prepareWorkspaceSyncV3CombinedRepairSnapshot(input) {
|
|
|
576
584
|
: input.nestedCoverage
|
|
577
585
|
? buildWorkspaceSyncV3NestedRepairSnapshot({ core: input.core, workspaceId })
|
|
578
586
|
: buildWorkspaceSyncV3CombinedRepairSnapshot({ core: input.core, workspaceId });
|
|
587
|
+
const snapshotCompletedAt = Date.now();
|
|
579
588
|
if (snapshot.snapshotSequence !== highWatermark) {
|
|
580
589
|
throw new Error('Combined repair baseline snapshot sequence changed while locked.');
|
|
581
590
|
}
|
|
591
|
+
console.info('[Taskforce Sync Repair Baseline Timing]', JSON.stringify({
|
|
592
|
+
workspaceId,
|
|
593
|
+
coverage: input.workflowCoverage ? 'workflow'
|
|
594
|
+
: input.planningOrderCoverage ? 'planning-order'
|
|
595
|
+
: input.nestedCoverage ? 'nested' : 'combined',
|
|
596
|
+
candidates: candidates.length,
|
|
597
|
+
lock: lockCompletedAt - startedAt,
|
|
598
|
+
inventory: inventoryCompletedAt - lockCompletedAt,
|
|
599
|
+
revisions: revisionsCompletedAt - inventoryCompletedAt,
|
|
600
|
+
validation: validationCompletedAt - revisionsCompletedAt,
|
|
601
|
+
baselineWrites: baselineWritesCompletedAt - validationCompletedAt,
|
|
602
|
+
snapshot: snapshotCompletedAt - baselineWritesCompletedAt,
|
|
603
|
+
total: snapshotCompletedAt - startedAt,
|
|
604
|
+
}));
|
|
582
605
|
return { highWatermark, insertedEntities: missing.length + legacyRelationshipSkews.length + legacyNestedDrifts.length,
|
|
583
606
|
insertedJournalRows: rowCount, snapshot };
|
|
584
607
|
})();
|
|
@@ -59,6 +59,7 @@ export declare function buildWorkspaceSyncV3CombinedRepairPage(input: {
|
|
|
59
59
|
nestedCoverage?: boolean;
|
|
60
60
|
workflowCoverage?: boolean;
|
|
61
61
|
planningOrderCoverage?: boolean;
|
|
62
|
+
coveredLegacyWritesFenced?: boolean;
|
|
62
63
|
}): WorkspaceSyncV3CombinedRepairPage;
|
|
63
64
|
export declare function buildWorkspaceSyncV3NestedRepairPage(input: Omit<Parameters<typeof buildWorkspaceSyncV3CombinedRepairPage>[0], 'nestedCoverage' | 'workflowCoverage' | 'planningOrderCoverage'>): WorkspaceSyncV3CombinedRepairPage;
|
|
64
65
|
export declare function buildWorkspaceSyncV3WorkflowRepairPage(input: Omit<Parameters<typeof buildWorkspaceSyncV3CombinedRepairPage>[0], 'nestedCoverage' | 'workflowCoverage' | 'planningOrderCoverage'>): WorkspaceSyncV3CombinedRepairPage;
|
|
@@ -14,7 +14,11 @@ const MAX_PAGE_SIZE = 100;
|
|
|
14
14
|
const DEFAULT_MAX_RESPONSE_BYTES = 1024 * 1024;
|
|
15
15
|
const DEFAULT_SNAPSHOT_TTL_MS = 60 * 60_000;
|
|
16
16
|
const MAX_SNAPSHOT_TTL_MS = 24 * 60 * 60_000;
|
|
17
|
-
const
|
|
17
|
+
const SQLITE_INSERT_BATCH_SIZE = 50;
|
|
18
|
+
// Postgres permits 65,535 bind parameters. Each materialized entry uses 15,
|
|
19
|
+
// so 1,000 entries keeps a wide safety margin while avoiding hundreds of
|
|
20
|
+
// synchronous worker/database round trips for large repair snapshots.
|
|
21
|
+
const POSTGRES_INSERT_BATCH_SIZE = 1000;
|
|
18
22
|
export class WorkspaceSyncV3CombinedRepairSnapshotUnavailableError extends Error {
|
|
19
23
|
code = 'WORKSPACE_SYNC_V3_COMBINED_REPAIR_SNAPSHOT_UNAVAILABLE';
|
|
20
24
|
statusCode = 410;
|
|
@@ -170,8 +174,11 @@ function persistMaterialization(input) {
|
|
|
170
174
|
coverage_version, coverage_digest, snapshot_sequence, entry_count, created_at, expires_at
|
|
171
175
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
172
176
|
`).run(input.tenantId, input.workspaceId, snapshotId, WORKSPACE_SYNC_CONTRACT_VERSION, profile.coverageProfileId, profile.coverageVersion, profile.coverageDigest, snapshot.snapshotSequence, snapshot.entries.length, input.startedAt, provisionalExpiresAt);
|
|
173
|
-
|
|
174
|
-
|
|
177
|
+
const insertBatchSize = db.provider === 'postgres'
|
|
178
|
+
? POSTGRES_INSERT_BATCH_SIZE
|
|
179
|
+
: SQLITE_INSERT_BATCH_SIZE;
|
|
180
|
+
for (let offset = 0; offset < snapshot.entries.length; offset += insertBatchSize) {
|
|
181
|
+
const batch = snapshot.entries.slice(offset, offset + insertBatchSize);
|
|
175
182
|
const values = batch.map(() => '(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)').join(', ');
|
|
176
183
|
const args = [];
|
|
177
184
|
batch.forEach((entry, index) => args.push(input.tenantId, input.workspaceId, snapshotId, offset + index, entry.projection, entry.domain, entry.entityId, entry.sequence, entry.mutationKind, entry.entityRevision, entry.lifecycleRevision, entry.canonicalFingerprint ?? null, entry.payloadFingerprint, canonicalWorkspaceSyncJson(entry.payload), entry.occurredAt));
|
|
@@ -414,18 +421,24 @@ export function buildWorkspaceSyncV3CombinedRepairPage(input) {
|
|
|
414
421
|
if (reusable)
|
|
415
422
|
return { metadata: reusable, reused: true,
|
|
416
423
|
insertedBaselineEntities: 0, insertedBaselineJournalRows: 0 };
|
|
424
|
+
const repairStartedAt = Date.now();
|
|
417
425
|
const prepared = coverage === 'workflow'
|
|
418
|
-
? prepareWorkspaceSyncV3WorkflowRepairSnapshot({ core: input.core, workspaceId, now
|
|
426
|
+
? prepareWorkspaceSyncV3WorkflowRepairSnapshot({ core: input.core, workspaceId, now,
|
|
427
|
+
coveredLegacyWritesFenced: input.coveredLegacyWritesFenced })
|
|
419
428
|
: coverage === 'planning-order'
|
|
420
|
-
? prepareWorkspaceSyncV3PlanningOrderRepairSnapshot({ core: input.core, workspaceId, now
|
|
429
|
+
? prepareWorkspaceSyncV3PlanningOrderRepairSnapshot({ core: input.core, workspaceId, now,
|
|
430
|
+
coveredLegacyWritesFenced: input.coveredLegacyWritesFenced })
|
|
421
431
|
: coverage === 'nested'
|
|
422
|
-
? prepareWorkspaceSyncV3NestedRepairSnapshot({ core: input.core, workspaceId, now
|
|
423
|
-
|
|
432
|
+
? prepareWorkspaceSyncV3NestedRepairSnapshot({ core: input.core, workspaceId, now,
|
|
433
|
+
coveredLegacyWritesFenced: input.coveredLegacyWritesFenced })
|
|
434
|
+
: prepareWorkspaceSyncV3CombinedRepairSnapshot({ core: input.core, workspaceId, now,
|
|
435
|
+
coveredLegacyWritesFenced: input.coveredLegacyWritesFenced });
|
|
424
436
|
// Production expiry is sampled at the end of persistence, after
|
|
425
437
|
// every immutable payload row has committed in the same lock.
|
|
426
438
|
const materializationStartedAt = input.now
|
|
427
439
|
? now
|
|
428
440
|
: timestamp(new Date().toISOString(), 'Combined repair materialization start time');
|
|
441
|
+
const persistenceStartedAt = Date.now();
|
|
429
442
|
const persisted = persistMaterialization({
|
|
430
443
|
core: input.core, tenantId, workspaceId, startedAt: materializationStartedAt,
|
|
431
444
|
fixedCompletionTime: input.now ? now : undefined, ttlMs,
|
|
@@ -434,6 +447,15 @@ export function buildWorkspaceSyncV3CombinedRepairPage(input) {
|
|
|
434
447
|
insertedBaselineJournalRows: prepared.insertedJournalRows,
|
|
435
448
|
coverage,
|
|
436
449
|
});
|
|
450
|
+
console.info('[Taskforce Sync Repair Timing]', JSON.stringify({
|
|
451
|
+
workspaceId,
|
|
452
|
+
coverage,
|
|
453
|
+
entries: prepared.snapshot.entries.length,
|
|
454
|
+
insertedBaselineEntities: prepared.insertedEntities,
|
|
455
|
+
insertedBaselineJournalRows: prepared.insertedJournalRows,
|
|
456
|
+
persistence: Date.now() - persistenceStartedAt,
|
|
457
|
+
endToEnd: Date.now() - repairStartedAt,
|
|
458
|
+
}));
|
|
437
459
|
return { metadata: persisted, reused: false,
|
|
438
460
|
insertedBaselineEntities: prepared.insertedEntities,
|
|
439
461
|
insertedBaselineJournalRows: prepared.insertedJournalRows };
|
|
@@ -18,8 +18,8 @@ import { projectWorkspaceSyncV3WorkstreamTaskOrderJournalRow } from './workspace
|
|
|
18
18
|
import { serializeWorkstreamTaskOrderForSync } from './workstreamTaskOrderSync.js';
|
|
19
19
|
import { serializeTaxonomyStateForSync } from './taxonomySyncPayload.js';
|
|
20
20
|
import { fingerprintWorkspaceSyncPayload, WORKSPACE_SYNC_CONTRACT_VERSION } from './syncDurabilityStore.js';
|
|
21
|
+
import { workspaceSyncV3RepairEntityReadBatchSize } from './workspaceSyncV3RepairSqlBatching.js';
|
|
21
22
|
const READ_PAGE_SIZE = 1000;
|
|
22
|
-
const SQL_BATCH_SIZE = 400;
|
|
23
23
|
const COMBINED_PROJECTION_RANK = new Map(WORKSPACE_SYNC_V3_COMBINED_COVERAGE_PROFILE.projections
|
|
24
24
|
.map((projection, index) => [projection.projectionId, index]));
|
|
25
25
|
const NESTED_PROJECTION_RANK = new Map(WORKSPACE_SYNC_V3_NESTED_COVERAGE_PROFILE.projections
|
|
@@ -53,6 +53,9 @@ function projectionRank(entry, coverage) {
|
|
|
53
53
|
return rank;
|
|
54
54
|
}
|
|
55
55
|
function listTasks(core, workspaceId) {
|
|
56
|
+
if (typeof core.listTasksForAuthoritativeRepair === 'function') {
|
|
57
|
+
return core.listTasksForAuthoritativeRepair(workspaceId);
|
|
58
|
+
}
|
|
56
59
|
const result = [];
|
|
57
60
|
let cursor = null;
|
|
58
61
|
for (;;) {
|
|
@@ -150,18 +153,27 @@ function listLiveEvents(core, workspaceId, liveEntityIds) {
|
|
|
150
153
|
}
|
|
151
154
|
/** Candidate v4 inventory. The coverage-v3 inventory above intentionally remains unchanged. */
|
|
152
155
|
export function listWorkspaceSyncV3NestedRepairCandidates(core, workspaceId) {
|
|
156
|
+
const startedAt = Date.now();
|
|
153
157
|
const tasks = listTasks(core, workspaceId);
|
|
158
|
+
const tasksCompletedAt = Date.now();
|
|
154
159
|
const relationships = listRelationships(core, workspaceId);
|
|
160
|
+
const relationshipsCompletedAt = Date.now();
|
|
155
161
|
const initiatives = listInitiatives(core, workspaceId);
|
|
162
|
+
const initiativesCompletedAt = Date.now();
|
|
156
163
|
const workstreams = listWorkstreams(core, workspaceId);
|
|
164
|
+
const workstreamsCompletedAt = Date.now();
|
|
157
165
|
const taxonomy = serializeTaxonomyStateForSync(core.getTaxonomyState(workspaceId));
|
|
166
|
+
const taxonomyCompletedAt = Date.now();
|
|
158
167
|
const liveEntityIds = new Set([
|
|
159
168
|
...tasks.map((task) => `task\0${task.id}`),
|
|
160
169
|
...initiatives.map((candidate) => `initiative\0${candidate.entityId}`),
|
|
161
170
|
...workstreams.map((candidate) => `workstream\0${candidate.entityId}`),
|
|
162
171
|
]);
|
|
163
172
|
const attachmentLinksByTaskId = core.listWorkspaceTaskAttachmentLinksForDurableSync(new Set(tasks.map((task) => task.id)), workspaceId);
|
|
164
|
-
|
|
173
|
+
const attachmentLinksCompletedAt = Date.now();
|
|
174
|
+
const events = listLiveEvents(core, workspaceId, liveEntityIds);
|
|
175
|
+
const eventsCompletedAt = Date.now();
|
|
176
|
+
const candidates = [
|
|
165
177
|
...tasks.map((task) => ({
|
|
166
178
|
domain: 'task', entityId: task.id, payload: serializeTaskRootForSync(task),
|
|
167
179
|
})),
|
|
@@ -171,10 +183,32 @@ export function listWorkspaceSyncV3NestedRepairCandidates(core, workspaceId) {
|
|
|
171
183
|
...workstreams,
|
|
172
184
|
...buildWorkspaceSyncV3NestedTaskRepairCandidates({
|
|
173
185
|
tasks,
|
|
174
|
-
events
|
|
186
|
+
events,
|
|
175
187
|
attachmentLinksByTaskId,
|
|
176
188
|
}),
|
|
177
189
|
];
|
|
190
|
+
const completedAt = Date.now();
|
|
191
|
+
if (completedAt - startedAt >= 1_000) {
|
|
192
|
+
console.info('[Taskforce Sync Repair Inventory Timing]', JSON.stringify({
|
|
193
|
+
workspaceId,
|
|
194
|
+
tasks: tasks.length,
|
|
195
|
+
relationships: relationships.length,
|
|
196
|
+
initiatives: initiatives.length,
|
|
197
|
+
workstreams: workstreams.length,
|
|
198
|
+
events: events.length,
|
|
199
|
+
candidates: candidates.length,
|
|
200
|
+
listTasks: tasksCompletedAt - startedAt,
|
|
201
|
+
listRelationships: relationshipsCompletedAt - tasksCompletedAt,
|
|
202
|
+
listInitiatives: initiativesCompletedAt - relationshipsCompletedAt,
|
|
203
|
+
listWorkstreams: workstreamsCompletedAt - initiativesCompletedAt,
|
|
204
|
+
taxonomy: taxonomyCompletedAt - workstreamsCompletedAt,
|
|
205
|
+
attachmentLinks: attachmentLinksCompletedAt - taxonomyCompletedAt,
|
|
206
|
+
listEvents: eventsCompletedAt - attachmentLinksCompletedAt,
|
|
207
|
+
serializeCandidates: completedAt - eventsCompletedAt,
|
|
208
|
+
total: completedAt - startedAt,
|
|
209
|
+
}));
|
|
210
|
+
}
|
|
211
|
+
return candidates;
|
|
178
212
|
}
|
|
179
213
|
/** Candidate v5 inventory. Coverage-v3/v4 inventories intentionally remain unchanged. */
|
|
180
214
|
export function listWorkspaceSyncV3WorkflowRepairCandidates(core, workspaceId) {
|
|
@@ -258,10 +292,11 @@ function journalRow(row) {
|
|
|
258
292
|
}
|
|
259
293
|
function readLastRows(db, tenantId, workspaceId, inventory) {
|
|
260
294
|
const result = new Map();
|
|
295
|
+
const batchSize = workspaceSyncV3RepairEntityReadBatchSize(db);
|
|
261
296
|
for (const domain of [...new Set(inventory.map((candidate) => candidate.domain))]) {
|
|
262
297
|
const ids = inventory.filter((candidate) => candidate.domain === domain).map((candidate) => candidate.entityId);
|
|
263
|
-
for (let offset = 0; offset < ids.length; offset +=
|
|
264
|
-
const batch = ids.slice(offset, offset +
|
|
298
|
+
for (let offset = 0; offset < ids.length; offset += batchSize) {
|
|
299
|
+
const batch = ids.slice(offset, offset + batchSize);
|
|
265
300
|
const placeholders = batch.map(() => '?').join(', ');
|
|
266
301
|
const rows = db.prepare(`
|
|
267
302
|
SELECT journal.*
|
|
@@ -284,8 +319,9 @@ function readLastRows(db, tenantId, workspaceId, inventory) {
|
|
|
284
319
|
}
|
|
285
320
|
function readTaskFullProvenanceRows(input) {
|
|
286
321
|
const result = new Map();
|
|
287
|
-
|
|
288
|
-
|
|
322
|
+
const batchSize = workspaceSyncV3RepairEntityReadBatchSize(input.db);
|
|
323
|
+
for (let offset = 0; offset < input.taskIds.length; offset += batchSize) {
|
|
324
|
+
const batch = input.taskIds.slice(offset, offset + batchSize);
|
|
289
325
|
const placeholders = batch.map(() => '?').join(', ');
|
|
290
326
|
const rows = input.db.prepare(`
|
|
291
327
|
SELECT journal.*
|
|
@@ -427,7 +463,9 @@ export function buildWorkspaceSyncV3CombinedRepairSnapshotFromLockedCandidates(i
|
|
|
427
463
|
const tenantId = input.core.getTenantId();
|
|
428
464
|
const db = input.core.getDatabaseAdapter();
|
|
429
465
|
const inventory = input.inventory;
|
|
466
|
+
const startedAt = Date.now();
|
|
430
467
|
const rows = readLastRows(db, tenantId, workspaceId, inventory);
|
|
468
|
+
const rowsCompletedAt = Date.now();
|
|
431
469
|
const missing = inventory.filter((candidate) => !rows.has(`${candidate.domain}\0${candidate.entityId}`))
|
|
432
470
|
.map((candidate) => ({ domain: candidate.domain, entityId: candidate.entityId }));
|
|
433
471
|
if (missing.length > 0)
|
|
@@ -436,7 +474,9 @@ export function buildWorkspaceSyncV3CombinedRepairSnapshotFromLockedCandidates(i
|
|
|
436
474
|
.filter((candidate) => rows.get(`task\0${candidate.entityId}`)?.mutationKind === 'taxonomy-remap')
|
|
437
475
|
.map((candidate) => candidate.entityId);
|
|
438
476
|
const taskFullProvenance = readTaskFullProvenanceRows({ db, tenantId, workspaceId, taskIds: remappedTaskIds });
|
|
477
|
+
const provenanceCompletedAt = Date.now();
|
|
439
478
|
const entries = inventory.map((candidate) => entry(candidate, rows.get(`${candidate.domain}\0${candidate.entityId}`), taskFullProvenance));
|
|
479
|
+
const entriesCompletedAt = Date.now();
|
|
440
480
|
const coverage = input.workflowCoverage
|
|
441
481
|
? 'workflow'
|
|
442
482
|
: input.planningOrderCoverage
|
|
@@ -451,12 +491,27 @@ export function buildWorkspaceSyncV3CombinedRepairSnapshotFromLockedCandidates(i
|
|
|
451
491
|
: coverage === 'nested'
|
|
452
492
|
? validateWorkspaceSyncV3NestedCoverageFeedEntry
|
|
453
493
|
: validateWorkspaceSyncV3CombinedFeedEntry);
|
|
494
|
+
const validationCompletedAt = Date.now();
|
|
454
495
|
if (entries.some((candidate) => BigInt(candidate.sequence) > BigInt(snapshotSequence))) {
|
|
455
496
|
throw new Error('Combined repair entry exceeds the locked snapshot sequence.');
|
|
456
497
|
}
|
|
457
498
|
entries.sort((left, right) => (projectionRank(left, coverage)
|
|
458
499
|
- projectionRank(right, coverage))
|
|
459
500
|
|| compareCodeUnits(left.entityId, right.entityId));
|
|
501
|
+
const completedAt = Date.now();
|
|
502
|
+
if (completedAt - startedAt >= 1_000) {
|
|
503
|
+
console.info('[Taskforce Sync Repair Snapshot Timing]', JSON.stringify({
|
|
504
|
+
workspaceId,
|
|
505
|
+
coverage,
|
|
506
|
+
entries: entries.length,
|
|
507
|
+
readRows: rowsCompletedAt - startedAt,
|
|
508
|
+
readProvenance: provenanceCompletedAt - rowsCompletedAt,
|
|
509
|
+
projectEntries: entriesCompletedAt - provenanceCompletedAt,
|
|
510
|
+
validateEntries: validationCompletedAt - entriesCompletedAt,
|
|
511
|
+
sortEntries: completedAt - validationCompletedAt,
|
|
512
|
+
total: completedAt - startedAt,
|
|
513
|
+
}));
|
|
514
|
+
}
|
|
460
515
|
return { snapshotSequence: BigInt(snapshotSequence).toString(10), entries };
|
|
461
516
|
}
|
|
462
517
|
export function buildWorkspaceSyncV3NestedRepairSnapshot(input) {
|
|
@@ -134,6 +134,7 @@ export type WorkspaceSyncV3TaskAttachmentLinksEnvelope = WorkspaceSyncV3Operatio
|
|
|
134
134
|
baseLifecycleRevision: '0';
|
|
135
135
|
payload: {
|
|
136
136
|
links: WorkspaceSyncV3TaskAttachmentLink[];
|
|
137
|
+
cardCoverAssetId?: string | null;
|
|
137
138
|
originActor?: WorkspaceSyncV3OriginActor;
|
|
138
139
|
};
|
|
139
140
|
}>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
const SQLITE_ENTITY_READ_BATCH_SIZE = 400;
|
|
2
|
+
// These reads bind one parameter per entity plus a small fixed scope. Keeping
|
|
3
|
+
// the batch at 4,000 remains far below PostgreSQL's 65,535 parameter limit
|
|
4
|
+
// while avoiding dozens of synchronous database-worker round trips.
|
|
5
|
+
const POSTGRES_ENTITY_READ_BATCH_SIZE = 4000;
|
|
6
|
+
export function workspaceSyncV3RepairEntityReadBatchSize(db) {
|
|
7
|
+
return db.provider === 'postgres'
|
|
8
|
+
? POSTGRES_ENTITY_READ_BATCH_SIZE
|
|
9
|
+
: SQLITE_ENTITY_READ_BATCH_SIZE;
|
|
10
|
+
}
|
|
@@ -2,7 +2,7 @@ import { serializeTaskForSync, type TaskSyncPayload } from '../taskSyncPayload.j
|
|
|
2
2
|
import type { TaxonomyTaskRemapAuthoritativePayload } from './taxonomyCompositeMutationService.js';
|
|
3
3
|
import type { WorkspaceSyncJournalRow } from './workspaceSyncJournalReader.js';
|
|
4
4
|
export type WorkspaceSyncV3TaskRootMutationKind = 'create' | 'metadata-update' | 'archive' | 'unarchive' | 'complete' | 'reopen' | 'set-status' | 'taxonomy-remap' | 'delete';
|
|
5
|
-
export type WorkspaceSyncV3TaskRootPayload = Omit<TaskSyncPayload, 'attachments' | 'checklistItems' | 'comments'>;
|
|
5
|
+
export type WorkspaceSyncV3TaskRootPayload = Omit<TaskSyncPayload, 'attachments' | 'cardCoverAssetId' | 'checklistItems' | 'comments'>;
|
|
6
6
|
export type WorkspaceSyncV3TaskRootTombstone = {
|
|
7
7
|
taskId: string;
|
|
8
8
|
deletedAt: string;
|
|
@@ -20,7 +20,7 @@ const FULL_MUTATIONS = new Set([
|
|
|
20
20
|
]);
|
|
21
21
|
const TASK_STATUSES = new Set(['task', 'on-hold', 'in-progress', 'review', 'done', 'cancelled']);
|
|
22
22
|
function taskRootFromSerialized(task) {
|
|
23
|
-
const { attachments: _attachments, checklistItems: _checklistItems, comments: _comments, ...root } = task;
|
|
23
|
+
const { attachments: _attachments, cardCoverAssetId: _cardCoverAssetId, checklistItems: _checklistItems, comments: _comments, ...root } = task;
|
|
24
24
|
return root;
|
|
25
25
|
}
|
|
26
26
|
export function serializeTaskRootForSync(task) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { TaskforceCore, TaskforceSyncCapable, TaskRelationshipRecord } from '../core/Taskforce.js';
|
|
2
2
|
import type { WorkspaceTaxonomyState } from '../shared/taxonomyState.js';
|
|
3
|
-
import type { WorkspaceSyncAiProfileSnapshot, WorkspaceSyncAgentConversationSnapshot, WorkspaceSyncAgentRoleSnapshot, WorkspaceSyncAnnotatedAttachmentSessionSnapshot, WorkspaceSyncChange, WorkspaceSyncDocumentReviewCommentSnapshot, WorkspaceSyncDocumentReviewSessionSnapshot, WorkspaceSyncDurableTaskRevision, WorkspaceSyncDurablePlanningRevision, WorkspaceSyncDurableTaxonomyRevision, WorkspaceSyncEntityEventSnapshot, WorkspaceSyncInitiativeSnapshot, WorkspaceSyncTaskEventSnapshot, WorkspaceSyncTaskSnapshot, WorkspaceSyncTaskforceAgentSnapshot, WorkspaceSyncTaskforceAgentSkillSnapshot, WorkspaceSyncWorkspaceMemberSnapshot, WorkspaceSyncWorkstreamSnapshot } from './workspaceSyncModel.js';
|
|
3
|
+
import type { WorkspaceSyncAiProfileSnapshot, WorkspaceSyncAgentConversationSnapshot, WorkspaceSyncAgentRoleSnapshot, WorkspaceSyncAnnotatedAttachmentSessionSnapshot, WorkspaceSyncChange, WorkspaceSyncDocumentReviewCommentSnapshot, WorkspaceSyncDocumentReviewSessionSnapshot, WorkspaceSyncDurableTaskRevision, WorkspaceSyncDurablePlanningRevision, WorkspaceSyncDurableTaxonomyRevision, WorkspaceSyncEntityEventSnapshot, WorkspaceSyncInitiativeSnapshot, WorkspaceSyncPlanningIdentitySnapshot, WorkspaceSyncTaskEventSnapshot, WorkspaceSyncTaskSnapshot, WorkspaceSyncTaskforceAgentSnapshot, WorkspaceSyncTaskforceAgentSkillSnapshot, WorkspaceSyncWorkspaceMemberSnapshot, WorkspaceSyncWorkstreamSnapshot } from './workspaceSyncModel.js';
|
|
4
4
|
import { createCollaborationSyncState } from './collaborationSyncState.js';
|
|
5
5
|
import { createContentSyncState } from './contentSyncState.js';
|
|
6
6
|
import type { WorkspaceAssetSyncLinkPayload } from './contentSyncPayload.js';
|
|
@@ -52,6 +52,11 @@ type PullFeedEntry = {
|
|
|
52
52
|
watermark: string;
|
|
53
53
|
sortId: string;
|
|
54
54
|
workstream: WorkspaceSyncWorkstreamSnapshot;
|
|
55
|
+
} | {
|
|
56
|
+
kind: 'planning-identity';
|
|
57
|
+
watermark: string;
|
|
58
|
+
sortId: string;
|
|
59
|
+
identity: WorkspaceSyncPlanningIdentitySnapshot;
|
|
55
60
|
} | {
|
|
56
61
|
kind: 'ai-profile';
|
|
57
62
|
watermark: string;
|