@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.
Files changed (187) hide show
  1. package/dist/Taskforce.module.css +24 -53
  2. package/dist/components/activity/EntityActivityTimeline.js +15 -5
  3. package/dist/components/context/AttachmentPreviewHost.js +1 -1
  4. package/dist/components/context/ContextAttachmentManager.d.ts +3 -0
  5. package/dist/components/context/ContextAttachmentManager.js +116 -20
  6. package/dist/components/features/planning/PlanningEntitySummary.d.ts +3 -1
  7. package/dist/components/features/planning/PlanningEntitySummary.js +3 -2
  8. package/dist/components/features/planning/PlanningLinkPicker.d.ts +3 -1
  9. package/dist/components/features/planning/PlanningLinkPicker.js +5 -3
  10. package/dist/components/features/planning/PlanningModule.js +26 -9
  11. package/dist/components/features/planning/PlanningVisualIdentity.d.ts +14 -0
  12. package/dist/components/features/planning/PlanningVisualIdentity.js +106 -0
  13. package/dist/components/features/planning/planningWorkspaceModel.d.ts +11 -0
  14. package/dist/components/task/TaskActionHeader.d.ts +2 -1
  15. package/dist/components/task/TaskActionHeader.js +2 -2
  16. package/dist/components/task/TaskCard.js +37 -4
  17. package/dist/components/task/TaskContextUpload.d.ts +3 -0
  18. package/dist/components/task/TaskContextUpload.js +2 -2
  19. package/dist/components/task/TaskForm.d.ts +4 -0
  20. package/dist/components/task/TaskForm.js +32 -7
  21. package/dist/components/task/TaskImageReviews.js +16 -16
  22. package/dist/components/task/TaskStatusActions.js +11 -2
  23. package/dist/components/task/TaskWorkstreamPicker.js +2 -1
  24. package/dist/components/ui/DocumentTypeIcon.d.ts +7 -0
  25. package/dist/components/ui/DocumentTypeIcon.js +8 -0
  26. package/dist/components/ui/TaxonomyDropdown.d.ts +9 -1
  27. package/dist/components/ui/TaxonomyDropdown.js +30 -3
  28. package/dist/components/views/StandaloneLayout.js +62 -9
  29. package/dist/components/views/WidgetView.js +8 -5
  30. package/dist/components/views/panels/PlanningDrawer.d.ts +7 -1
  31. package/dist/components/views/panels/PlanningDrawer.js +48 -44
  32. package/dist/config/envSchema.js +1 -0
  33. package/dist/config/localServiceCloudTarget.d.ts +10 -0
  34. package/dist/config/localServiceCloudTarget.js +76 -0
  35. package/dist/core/AiProfileService.d.ts +1 -0
  36. package/dist/core/AiProfileService.js +2 -1
  37. package/dist/core/AttachmentLinkService.js +7 -4
  38. package/dist/core/DeletedTaskLifecycleService.d.ts +4 -0
  39. package/dist/core/DeletedTaskLifecycleService.js +21 -0
  40. package/dist/core/McpTokenService.d.ts +4 -0
  41. package/dist/core/McpTokenService.js +52 -0
  42. package/dist/core/TaskAttachmentLinksDurableMutationService.d.ts +5 -0
  43. package/dist/core/TaskAttachmentLinksDurableMutationService.js +20 -11
  44. package/dist/core/Taskforce.d.ts +63 -1
  45. package/dist/core/Taskforce.js +558 -73
  46. package/dist/core/types.d.ts +2 -1
  47. package/dist/documentReviews/DocumentReviewCommentStore.d.ts +11 -0
  48. package/dist/documentReviews/DocumentReviewCommentStore.js +35 -2
  49. package/dist/documentReviews/service.d.ts +4 -0
  50. package/dist/documentReviews/service.js +141 -46
  51. package/dist/hooks/tasks/useTaskFormActions.d.ts +3 -0
  52. package/dist/hooks/tasks/useTaskFormActions.js +33 -7
  53. package/dist/hooks/useTaskforce.d.ts +59 -50
  54. package/dist/hooks/useTaskforce.js +103 -1
  55. package/dist/mcp/canonicalAssetHelpers.d.ts +13 -0
  56. package/dist/mcp/canonicalAssetHelpers.js +39 -5
  57. package/dist/mcp/collaborationRegistrar.js +15 -13
  58. package/dist/mcp/documentAssetRegistrar.js +16 -9
  59. package/dist/mcp/localServiceProxy.js +4 -1
  60. package/dist/mcp/runtime.d.ts +16 -0
  61. package/dist/mcp/runtime.js +566 -171
  62. package/dist/mcp/taskAttachmentCommandAdapter.d.ts +2 -0
  63. package/dist/mcp/taskAttachmentCommandAdapter.js +14 -8
  64. package/dist/mcp/taskPlanningRegistrar.js +42 -34
  65. package/dist/mcp/toolRegistry.js +2 -2
  66. package/dist/migrations/taskSchemaMigrations.js +35 -0
  67. package/dist/runtime/appGateDefinitions.d.ts +2 -2
  68. package/dist/runtime/appGateDefinitions.js +2 -2
  69. package/dist/server/appAccess.d.ts +12 -0
  70. package/dist/server/appAccess.js +21 -0
  71. package/dist/server/authorizedWorkspaceAccess.d.ts +12 -0
  72. package/dist/server/authorizedWorkspaceAccess.js +40 -0
  73. package/dist/server/cloudCollectionRead.d.ts +25 -0
  74. package/dist/server/cloudCollectionRead.js +120 -0
  75. package/dist/server/cloudCollectionReadPool.d.ts +52 -0
  76. package/dist/server/cloudCollectionReadPool.js +140 -0
  77. package/dist/server/cloudCollectionReadWorker.d.ts +1 -0
  78. package/dist/server/cloudCollectionReadWorker.js +36 -0
  79. package/dist/server/index.d.ts +3 -11
  80. package/dist/server/index.js +53 -40
  81. package/dist/server/localServiceLease.d.ts +3 -0
  82. package/dist/server/localServiceLease.js +9 -1
  83. package/dist/server/routes/documents.d.ts +5 -2
  84. package/dist/server/routes/documents.js +160 -13
  85. package/dist/server/routes/durableTaskHttpRouters.d.ts +2 -0
  86. package/dist/server/routes/durableTaskHttpRouters.js +2 -2
  87. package/dist/server/routes/localService.js +2 -0
  88. package/dist/server/routes/primitives.d.ts +2 -0
  89. package/dist/server/routes/shared.d.ts +24 -0
  90. package/dist/server/routes/shared.js +114 -18
  91. package/dist/server/routes/sync.js +22 -0
  92. package/dist/server/routes/syncV3FeedRoutes.js +4 -2
  93. package/dist/server/routes/syncV3LocalCaptureRoutes.js +20 -2
  94. package/dist/server/routes/syncV3OperationRoutes.js +17 -2
  95. package/dist/server/routes/tasks.js +199 -89
  96. package/dist/server/routes.js +35 -7
  97. package/dist/service/localServiceCli.js +36 -25
  98. package/dist/service/localServiceClientLifecycle.js +67 -6
  99. package/dist/shared/planningIdentity.d.ts +20 -0
  100. package/dist/shared/planningIdentity.js +79 -0
  101. package/dist/storage/postgresAdapter.js +4 -0
  102. package/dist/storage/postgresRequestDiagnostics.d.ts +8 -0
  103. package/dist/storage/postgresRequestDiagnostics.js +24 -0
  104. package/dist/storage/workspaceAssetStore.d.ts +32 -0
  105. package/dist/storage/workspaceAssetStore.js +70 -0
  106. package/dist/sync/coordinator/localSyncExecutionPermitStore.d.ts +16 -0
  107. package/dist/sync/coordinator/localSyncExecutionPermitStore.js +70 -22
  108. package/dist/sync/coordinator/workspaceSyncTransportGateway.js +4 -2
  109. package/dist/sync/engine/workspaceSyncEngineRemoteServices.d.ts +5 -0
  110. package/dist/sync/engine/workspaceSyncEngineServerRemoteServices.d.ts +1 -1
  111. package/dist/sync/engine/workspaceSyncEngineServerRemoteServices.js +15 -0
  112. package/dist/sync/engine/workspaceSyncEngineServerRunnerOperations.js +26 -3
  113. package/dist/sync/engine/workspaceSyncV2ChangeDispatcher.js +2 -0
  114. package/dist/sync/syncApplyHandlers.d.ts +3 -1
  115. package/dist/sync/syncApplyHandlers.js +29 -0
  116. package/dist/sync/syncService.js +9 -0
  117. package/dist/sync/taskSyncPayload.d.ts +1 -0
  118. package/dist/sync/taskSyncPayload.js +6 -0
  119. package/dist/sync/v3/durableTaskAttachmentLinksMutationRouter.d.ts +1 -0
  120. package/dist/sync/v3/durableTaskAttachmentLinksMutationRouter.js +21 -3
  121. package/dist/sync/v3/durableTaskHttpBulkMutationRouter.js +17 -4
  122. package/dist/sync/v3/localInitiativeOutboxService.js +4 -2
  123. package/dist/sync/v3/localOutboxDispatcher.js +5 -1
  124. package/dist/sync/v3/localTaskAttachmentLinksOutboxHandler.js +12 -2
  125. package/dist/sync/v3/localTaskAttachmentLinksOutboxService.d.ts +1 -0
  126. package/dist/sync/v3/localTaskAttachmentLinksOutboxService.js +15 -3
  127. package/dist/sync/v3/localWorkstreamOutboxService.js +4 -2
  128. package/dist/sync/v3/syncDurabilityStore.d.ts +8 -0
  129. package/dist/sync/v3/syncDurabilityStore.js +171 -33
  130. package/dist/sync/v3/taskAttachmentLinksMutationService.d.ts +1 -0
  131. package/dist/sync/v3/taskAttachmentLinksMutationService.js +18 -2
  132. package/dist/sync/v3/taskMetadataCoexistence.js +4 -0
  133. package/dist/sync/v3/workspaceSyncV2ProjectionExclusions.js +1 -9
  134. package/dist/sync/v3/workspaceSyncV3CloudOperationHandler.js +1 -0
  135. package/dist/sync/v3/workspaceSyncV3CombinedFeedOrchestrator.js +7 -1
  136. package/dist/sync/v3/workspaceSyncV3CombinedLocalApply.js +15 -3
  137. package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.d.ts +4 -0
  138. package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.js +29 -6
  139. package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.d.ts +1 -0
  140. package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.js +29 -7
  141. package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.js +62 -7
  142. package/dist/sync/v3/workspaceSyncV3OperationProtocol.d.ts +1 -0
  143. package/dist/sync/v3/workspaceSyncV3RepairSqlBatching.d.ts +2 -0
  144. package/dist/sync/v3/workspaceSyncV3RepairSqlBatching.js +10 -0
  145. package/dist/sync/v3/workspaceSyncV3TaskRootProjection.d.ts +1 -1
  146. package/dist/sync/v3/workspaceSyncV3TaskRootProjection.js +1 -1
  147. package/dist/sync/workspacePullFeed.d.ts +6 -1
  148. package/dist/sync/workspacePullFeed.js +172 -161
  149. package/dist/sync/workspaceSyncModel.d.ts +11 -0
  150. package/dist/sync/workspaceSyncModel.js +27 -2
  151. package/dist/types.d.ts +8 -0
  152. package/dist/ui/assets/{AiIdentityRosterCard-DB1BLO_j.js → AiIdentityRosterCard-MZs7lVED.js} +1 -1
  153. package/dist/ui/assets/{AiProfilesModule-DPxQeF9N.js → AiProfilesModule-C3i0LOxe.js} +1 -1
  154. package/dist/ui/assets/{AnnotatedAttachmentWorkspace-DHNYaNg6.js → AnnotatedAttachmentWorkspace-DVZk5Tln.js} +1 -1
  155. package/dist/ui/assets/AssetTraySortControl-Kf1pelSy.js +1 -0
  156. package/dist/ui/assets/ContextAttachmentManager-B8boOs6Q.js +3 -0
  157. package/dist/ui/assets/{DocumentWorkspace-BC7sy5TG.js → DocumentWorkspace-DXH4XUsB.js} +4 -4
  158. package/dist/ui/assets/EntityActivityTimeline-BtSTq0ON.js +1 -0
  159. package/dist/ui/assets/PlanningModule-BPVyEa-f.js +1 -0
  160. package/dist/ui/assets/PlanningModule-CoIR9hbV.css +1 -0
  161. package/dist/ui/assets/{PlansPage-BVH_NfgT.js → PlansPage-ChqgxALc.js} +1 -1
  162. package/dist/ui/assets/TaskContextUpload-CB3ol0sN.js +1 -0
  163. package/dist/ui/assets/TaskContextUpload-qmBeUw3u.css +1 -0
  164. package/dist/ui/assets/{TaskSettings-xVsxSa0g.js → TaskSettings-g4ECKNOz.js} +1 -1
  165. package/dist/ui/assets/{TaskforceAgentsModule-CkAxW19K.js → TaskforceAgentsModule-BazdUwxZ.js} +1 -1
  166. package/dist/ui/assets/WorkflowManagerModule-DWFspC-o.js +1 -0
  167. package/dist/ui/assets/index-BUplSsv_.js +7 -0
  168. package/dist/ui/assets/index-gz2EXuoK.css +1 -0
  169. package/dist/ui/assets/{vendor-icons-B8ZNsH1g.js → vendor-icons-BkFLXavV.js} +1 -1
  170. package/dist/ui/index.html +3 -3
  171. package/dist/utils/constants.d.ts +2 -2
  172. package/dist/utils/constants.js +1 -1
  173. package/dist/utils/contextAttachmentUpload.d.ts +2 -0
  174. package/dist/utils/contextAttachmentUpload.js +7 -0
  175. package/dist/utils/contextFiles.d.ts +1 -1
  176. package/dist/utils/contextFiles.js +4 -4
  177. package/package.json +6 -1
  178. package/dist/ui/assets/AssetTraySortControl-DphbyHVc.js +0 -1
  179. package/dist/ui/assets/ContextAttachmentManager-CMxSzHqc.js +0 -3
  180. package/dist/ui/assets/EntityActivityTimeline-pJ2ZjZ-k.js +0 -1
  181. package/dist/ui/assets/PlanningModule-CeTqXMMz.css +0 -1
  182. package/dist/ui/assets/PlanningModule-t5GbvVR9.js +0 -1
  183. package/dist/ui/assets/TaskContextUpload-Ds4LnDzV.css +0 -1
  184. package/dist/ui/assets/TaskContextUpload-bl4fOOUz.js +0 -1
  185. package/dist/ui/assets/WorkflowManagerModule-BKqIGVnF.js +0 -1
  186. package/dist/ui/assets/index-BzJlVnNS.css +0 -1
  187. package/dist/ui/assets/index-Cx7vZJHL.js +0 -7
@@ -85,6 +85,7 @@ export function registerDocumentAssetTools(registerTool, executeTool) {
85
85
  properties: descriptor.inputSchema.properties,
86
86
  ...(descriptor.inputSchema.required ? { required: descriptor.inputSchema.required } : {}),
87
87
  },
88
+ ...(descriptor.annotations ? { annotations: descriptor.annotations } : {}),
88
89
  };
89
90
  },
90
91
  handler: bindDomainTool(executeTool, name),
@@ -116,6 +117,7 @@ export function registerDocumentAssetTools(registerTool, executeTool) {
116
117
  }));
117
118
  register('link_document', (context) => ({
118
119
  description: context.describeTool('Link an existing canonical document to a task, initiative, or workstream without copying it. The operation is idempotent. Use search_documents first when you do not know the exact D-123 reference or asset id.'),
120
+ annotations: { idempotentHint: true },
119
121
  inputSchema: {
120
122
  properties: {
121
123
  documentId: stringProperty('Canonical document reference such as D-123, document id, or asset id.'),
@@ -139,6 +141,7 @@ export function registerDocumentAssetTools(registerTool, executeTool) {
139
141
  }));
140
142
  register('rehome_document', (context) => ({
141
143
  description: context.describeTool('Atomically move an existing canonical document reference between a task, initiative, or workstream without copying or deleting the document. Use this instead of separate link_document and unlink_document calls when correcting planning scope.'),
144
+ annotations: { idempotentHint: true },
142
145
  inputSchema: {
143
146
  properties: {
144
147
  documentId: stringProperty('Canonical document reference such as D-123, document id, or asset id.'),
@@ -159,18 +162,18 @@ export function registerDocumentAssetTools(registerTool, executeTool) {
159
162
  }));
160
163
  register('save_workstream_attachment', (context) => ({
161
164
  description: context.describeTool(context.runtimeMode === 'cloud'
162
- ? 'Save generated content and attach it to a workstream. Provide inline content. Set overwrite=true to replace an existing canonical attachment with the same filename.'
163
- : 'Save a file and attach it to a workstream. Provide inline content or an approved local sourcePath. Set overwrite=true to replace an existing canonical attachment with the same filename.'),
165
+ ? 'Save inline content as a workstream-owned attachment. Use overwrite=true to replace the same filename.'
166
+ : 'Save inline content or an approved local file as a workstream-owned attachment. Use overwrite=true to replace the same filename.'),
164
167
  inputSchema: {
165
168
  properties: {
166
169
  id: stringProperty('Workstream ID or workstream reference such as WS-123.'),
167
170
  filename: stringProperty('Destination filename for the attachment.'),
168
- content: stringProperty('Inline file content; use this for AI-authored markdown/text attachments.'),
171
+ content: stringProperty('Inline text content.'),
169
172
  ...(context.runtimeMode === 'local' ? {
170
173
  sourcePath: stringProperty("Existing local file. Allowed roots: project, registered Git worktrees, Taskforce-managed sources, approved agent workspaces, or the bound profile's ~/.taskforce/qa/<username>/artifacts."),
171
174
  } : {}),
172
175
  caption: stringProperty('Optional attachment caption.'),
173
- overwrite: booleanProperty('When true, overwrite an existing canonical workstream attachment with the same filename instead of creating a new one.'),
176
+ overwrite: booleanProperty('Replace the existing attachment with the same filename.'),
174
177
  },
175
178
  required: ['id', 'filename'],
176
179
  },
@@ -199,18 +202,18 @@ export function registerDocumentAssetTools(registerTool, executeTool) {
199
202
  }));
200
203
  register('save_initiative_attachment', (context) => ({
201
204
  description: context.describeTool(context.runtimeMode === 'cloud'
202
- ? 'Save generated content and attach it to an initiative. Provide inline content. Set overwrite=true to replace an existing canonical attachment with the same filename.'
203
- : 'Save a file and attach it to an initiative. Provide inline content or an approved local sourcePath. Set overwrite=true to replace an existing canonical attachment with the same filename.'),
205
+ ? 'Save inline content as an initiative-owned attachment. Use overwrite=true to replace the same filename.'
206
+ : 'Save inline content or an approved local file as an initiative-owned attachment. Use overwrite=true to replace the same filename.'),
204
207
  inputSchema: {
205
208
  properties: {
206
209
  id: stringProperty('Initiative ID or initiative reference such as IN-123.'),
207
210
  filename: stringProperty('Destination filename for the attachment.'),
208
- content: stringProperty('Inline file content; use this for AI-authored markdown/text attachments.'),
211
+ content: stringProperty('Inline text content.'),
209
212
  ...(context.runtimeMode === 'local' ? {
210
213
  sourcePath: stringProperty("Existing local file. Allowed roots: project, registered Git worktrees, Taskforce-managed sources, approved agent workspaces, or the bound profile's ~/.taskforce/qa/<username>/artifacts."),
211
214
  } : {}),
212
215
  caption: stringProperty('Optional attachment caption.'),
213
- overwrite: booleanProperty('When true, overwrite an existing canonical initiative attachment with the same filename instead of creating a new one.'),
216
+ overwrite: booleanProperty('Replace the existing attachment with the same filename.'),
214
217
  },
215
218
  required: ['id', 'filename'],
216
219
  },
@@ -263,6 +266,7 @@ export function registerDocumentAssetTools(registerTool, executeTool) {
263
266
  format: stringProperty('Optional read mode when including content.', ['metadata', 'text', 'content', 'full', 'download']),
264
267
  maxChars: numberProperty('Optional max inline character count for readable documents. Longer content is truncated with size metadata and a download hint.'),
265
268
  },
269
+ required: ['documentId'],
266
270
  },
267
271
  }));
268
272
  register('update_document', (context) => ({
@@ -466,13 +470,14 @@ export function registerDocumentAssetTools(registerTool, executeTool) {
466
470
  },
467
471
  }));
468
472
  register('add_document_review_comment', (context) => ({
469
- description: context.describeTool('Add one follow-up comment to an existing review session. Prefer review_document for multi-comment first-pass reviews.'),
473
+ description: context.describeTool('Add one follow-up comment to an existing review session. Prefer review_document for a complete review. Pass idempotencyKey only for exact retries after an ambiguous timeout.'),
470
474
  inputSchema: {
471
475
  properties: {
472
476
  sessionId: stringProperty('Document review session id.'),
473
477
  body: stringProperty('Comment text.'),
474
478
  anchor: documentReviewAnchorProperty(),
475
479
  parentCommentId: stringProperty('Optional root comment id. When supplied, adds a reply to that one-level thread; replies cannot target other replies.'),
480
+ idempotencyKey: { type: 'string', minLength: 1, maxLength: 128, description: 'Optional opaque retry key scoped to the active workspace, actor, and tool.' },
476
481
  },
477
482
  required: ['sessionId', 'body'],
478
483
  },
@@ -540,6 +545,7 @@ export function registerDocumentAssetTools(registerTool, executeTool) {
540
545
  }),
541
546
  expectedSizeBytes: numberProperty('Optional exact byte count for integrity verification. The save is rejected before attachment when the persisted bytes would differ.'),
542
547
  expectedSha256: stringProperty('Optional lowercase or uppercase SHA-256 hex digest for integrity verification. The save is rejected before attachment when the persisted bytes would differ.'),
548
+ displayName: stringProperty('Optional attachment display name. Defaults to filename and is independent from caption.'),
543
549
  caption: stringProperty('Optional attachment caption.'),
544
550
  overwrite: booleanProperty('When true, overwrite an existing canonical task attachment with the same filename instead of creating a new one.'),
545
551
  },
@@ -548,6 +554,7 @@ export function registerDocumentAssetTools(registerTool, executeTool) {
548
554
  }));
549
555
  register('set_task_plan', (context) => ({
550
556
  description: context.describeTool('Create or replace the canonical Markdown implementation plan for a task. Identical retries are no-ops. Optionally replace the task description with a concise summary after the plan is verified; a description failure preserves the valid plan and returns partial-success recovery guidance.'),
557
+ annotations: { idempotentHint: true },
551
558
  inputSchema: {
552
559
  properties: {
553
560
  taskId: stringProperty('Task ID or task reference such as T-123.'),
@@ -3,6 +3,7 @@ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
3
3
  import { JSONRPCMessageSchema, } from '@modelcontextprotocol/sdk/types.js';
4
4
  import { normalizeMcpConnectionId, parseMcpClientId } from './clientRegistry.js';
5
5
  import { normalizeMcpToolProfile } from './toolProfiles.js';
6
+ import { localServiceCloudTargetsEqual, parseLocalServiceCloudTarget, } from '../config/localServiceCloudTarget.js';
6
7
  import { discoverOrStartLocalService, LOCAL_SERVICE_API_BASE_PATH, LOCAL_SERVICE_PROTOCOL_VERSION, } from '../service/localServiceClientLifecycle.js';
7
8
  const REQUEST_TIMEOUT_MS = 120_000;
8
9
  const MAX_IN_FLIGHT = 32;
@@ -24,6 +25,7 @@ async function readJson(response, label) {
24
25
  }
25
26
  }
26
27
  function validateReadiness(readiness, descriptor) {
28
+ const readinessCloudTarget = parseLocalServiceCloudTarget(readiness.cloudTarget);
27
29
  if (!readiness.ready)
28
30
  throw new Error('Taskforce shared local service is not accepting new work.');
29
31
  if (readiness.protocolVersion !== LOCAL_SERVICE_PROTOCOL_VERSION
@@ -31,7 +33,8 @@ function validateReadiness(readiness, descriptor) {
31
33
  || readiness.generation !== descriptor.generation
32
34
  || readiness.pid !== descriptor.pid
33
35
  || readiness.endpoint !== descriptor.endpoint
34
- || readiness.dataIdentity !== descriptor.ownershipKey) {
36
+ || readiness.dataIdentity !== descriptor.ownershipKey
37
+ || !localServiceCloudTargetsEqual(readinessCloudTarget, descriptor.cloudTarget)) {
35
38
  throw new Error('Taskforce shared local service readiness does not match its descriptor.');
36
39
  }
37
40
  }
@@ -16,6 +16,18 @@ import { createDurableTaskCommentMutationRouter } from '../sync/v3/durableTaskCo
16
16
  import { createDurableTaskChecklistMutationRouter } from '../sync/v3/durableTaskChecklistMutationRouter.js';
17
17
  import { createDurableTaskAttachmentLinksMutationRouter } from '../sync/v3/durableTaskAttachmentLinksMutationRouter.js';
18
18
  import type { LocalDataOwnerPermit } from '../server/localDataOwnerPermit.js';
19
+ export type McpToolCallTiming = {
20
+ requestId: string | null;
21
+ toolName: string;
22
+ isWrite: boolean;
23
+ outcome: 'success' | 'failure';
24
+ totalMs: number;
25
+ preparationMs: number;
26
+ validationMs: number;
27
+ handlerMs: number;
28
+ responseBytes: number;
29
+ subphases: Record<string, number>;
30
+ };
19
31
  export interface TaskforceMcpServerOptions {
20
32
  projectRoot?: string;
21
33
  tenantId?: string;
@@ -34,6 +46,7 @@ export interface TaskforceMcpServerOptions {
34
46
  mutationKind: string;
35
47
  payloadFingerprint: string;
36
48
  }) => void;
49
+ onToolCallTiming?: (timing: McpToolCallTiming) => void;
37
50
  operationIdentityScope?: {
38
51
  generation: string;
39
52
  sessionId: string;
@@ -45,10 +58,12 @@ export interface TaskforceMcpServerOptions {
45
58
  durableTaxonomyMutationRouter?: ReturnType<typeof createDurableTaxonomyMutationRouter>;
46
59
  durableInitiativeMutationRouterFactory?: (actorRef: string, options?: {
47
60
  operationId?: string;
61
+ commentId?: string;
48
62
  deferPostCommitNotification?: (notify: () => void) => void;
49
63
  }) => ReturnType<typeof createDurableInitiativeMutationRouter>;
50
64
  durableWorkstreamMutationRouterFactory?: (actorRef: string, options?: {
51
65
  operationId?: string;
66
+ commentId?: string;
52
67
  deferPostCommitNotification?: (notify: () => void) => void;
53
68
  }) => ReturnType<typeof createDurableWorkstreamMutationRouter>;
54
69
  durableTaskRelationshipMutationRouter?: ReturnType<typeof createDurableTaskRelationshipMutationRouter>;
@@ -62,6 +77,7 @@ export interface TaskforceMcpServerOptions {
62
77
  userId?: string | null;
63
78
  tokenId?: string | null;
64
79
  aiProfileId?: string | null;
80
+ aiProfileIdentityAsserted?: boolean;
65
81
  aiProfileToken?: AiProfileBootstrapConfig['aiProfileToken'];
66
82
  aiProfileName?: AiProfileBootstrapConfig['aiProfileName'];
67
83
  aiProfileIcon?: AiProfileBootstrapConfig['aiProfileIcon'];