@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.
Files changed (264) hide show
  1. package/dist/Taskforce.module.css +233 -34
  2. package/dist/TaskforceCore.js +237 -230
  3. package/dist/annotatedAttachments/AnnotatedAttachmentSessionStore.js +1 -1
  4. package/dist/cli.js +34 -0
  5. package/dist/cliCloudTargetGuard.d.ts +5 -0
  6. package/dist/cliCloudTargetGuard.js +11 -0
  7. package/dist/components/features/AnnotatedAttachmentWorkspace.js +24 -8
  8. package/dist/components/features/TaskSettings.d.ts +12 -1
  9. package/dist/components/features/TaskSettings.js +147 -40
  10. package/dist/components/features/agentCapabilities/AgentCapabilitiesPrototype.d.ts +1 -1
  11. package/dist/components/features/planning/PlanningModule.js +2 -5
  12. package/dist/components/features/planning/PlanningTaskOrderList.d.ts +1 -1
  13. package/dist/components/features/planning/PlanningTaskOrderList.js +17 -6
  14. package/dist/components/features/planning/planningTaskArrangement.d.ts +1 -0
  15. package/dist/components/features/planning/planningTaskArrangement.js +5 -5
  16. package/dist/components/features/taskforceAgentEditorModel.js +3 -1
  17. package/dist/components/task/TaskCard.d.ts +5 -0
  18. package/dist/components/task/TaskCard.js +65 -10
  19. package/dist/components/task/TaskImageReviews.js +14 -5
  20. package/dist/components/task/TaskKanban.d.ts +6 -1
  21. package/dist/components/task/TaskKanban.js +152 -6
  22. package/dist/components/task/TaskList.d.ts +5 -0
  23. package/dist/components/task/TaskList.js +3 -3
  24. package/dist/components/ui/PasswordInput.d.ts +6 -0
  25. package/dist/components/ui/PasswordInput.js +11 -0
  26. package/dist/components/ui/TopNoticeLayer.js +1 -1
  27. package/dist/components/views/AppShellHeader.js +32 -11
  28. package/dist/components/views/PlanComparisonPage.js +12 -0
  29. package/dist/components/views/StandaloneLayout.js +7 -31
  30. package/dist/components/views/WidgetView.js +3 -3
  31. package/dist/components/views/panels/PlanningDrawer.js +5 -12
  32. package/dist/components/views/standalone/modals/AccountSettingsModal.js +26 -17
  33. package/dist/config/envSchema.js +12 -0
  34. package/dist/config/localServiceRuntimeContract.d.ts +13 -0
  35. package/dist/config/localServiceRuntimeContract.js +135 -0
  36. package/dist/core/AiProfileService.js +46 -8
  37. package/dist/core/DeletedTaskLifecycleService.d.ts +1 -0
  38. package/dist/core/DeletedTaskLifecycleService.js +37 -6
  39. package/dist/core/TaskAttachmentLinksDurableMutationService.d.ts +3 -2
  40. package/dist/core/TaskAttachmentLinksDurableMutationService.js +33 -9
  41. package/dist/core/Taskforce.d.ts +62 -2
  42. package/dist/core/Taskforce.js +635 -32
  43. package/dist/core/types.d.ts +6 -0
  44. package/dist/hooks/sync/useDurableLocalOutboxDrain.d.ts +1 -1
  45. package/dist/hooks/sync/useDurableTaskCreateMutation.js +1 -1
  46. package/dist/hooks/sync/useDurableTaskMetadataMutation.d.ts +1 -0
  47. package/dist/hooks/sync/useDurableTaskMetadataMutation.js +1 -0
  48. package/dist/hooks/sync/useDurableTaskStatusMutation.d.ts +1 -0
  49. package/dist/hooks/tasks/taskHttpMutation.js +1 -0
  50. package/dist/hooks/tasks/useCloudTaskSearch.d.ts +12 -0
  51. package/dist/hooks/tasks/useCloudTaskSearch.js +71 -0
  52. package/dist/hooks/tasks/useTaskDescriptionImageDraftRecovery.d.ts +16 -0
  53. package/dist/hooks/tasks/useTaskDescriptionImageDraftRecovery.js +197 -0
  54. package/dist/hooks/tasks/useTaskEditorNavigation.d.ts +16 -3
  55. package/dist/hooks/tasks/useTaskEditorNavigation.js +72 -13
  56. package/dist/hooks/tasks/useTaskFormActions.d.ts +6 -0
  57. package/dist/hooks/tasks/useTaskFormActions.js +65 -12
  58. package/dist/hooks/ui/useSettingsModel.d.ts +24 -2
  59. package/dist/hooks/ui/useSettingsModel.js +13 -2
  60. package/dist/hooks/ui/useSettingsPersistence.d.ts +12 -1
  61. package/dist/hooks/ui/useSettingsPersistence.js +74 -47
  62. package/dist/hooks/useFilterSort.d.ts +7 -3
  63. package/dist/hooks/useFilterSort.js +15 -5
  64. package/dist/hooks/useTaskData.d.ts +10 -1
  65. package/dist/hooks/useTaskData.js +216 -7
  66. package/dist/hooks/useTaskMutations.d.ts +10 -2
  67. package/dist/hooks/useTaskMutations.js +223 -43
  68. package/dist/hooks/useTaskforce.d.ts +37 -9
  69. package/dist/hooks/useTaskforce.js +349 -39
  70. package/dist/hooks/useUiNotice.d.ts +4 -0
  71. package/dist/hooks/useUiNotice.js +4 -0
  72. package/dist/mcp/adminWorkspaceRegistrar.js +3 -3
  73. package/dist/mcp/documentAssetRegistrar.js +44 -35
  74. package/dist/mcp/documentHelpers.d.ts +1 -0
  75. package/dist/mcp/documentHelpers.js +7 -3
  76. package/dist/mcp/runtime.js +172 -42
  77. package/dist/mcp/taskPlanningRegistrar.js +41 -38
  78. package/dist/mcp/toolCallCompatibility.js +38 -1
  79. package/dist/mcp/toolCatalog.d.ts +1 -0
  80. package/dist/migrations/taskSchemaMigrations.js +12 -0
  81. package/dist/runtime/appGateDefinitions.d.ts +30 -6
  82. package/dist/runtime/appGateDefinitions.js +6 -6
  83. package/dist/runtime/appGates.d.ts +12 -13
  84. package/dist/runtime/appGates.js +29 -13
  85. package/dist/runtime/nodeAppGates.d.ts +8 -0
  86. package/dist/runtime/nodeAppGates.js +27 -0
  87. package/dist/server/cloudCollectionRead.d.ts +1 -1
  88. package/dist/server/cloudCollectionRead.js +2 -2
  89. package/dist/server/index.d.ts +3 -0
  90. package/dist/server/index.js +15 -3
  91. package/dist/server/localServiceLease.d.ts +3 -0
  92. package/dist/server/localServiceLease.js +9 -1
  93. package/dist/server/localWorkspaceSyncServerRuntime.js +10 -3
  94. package/dist/server/rateLimit.d.ts +1 -0
  95. package/dist/server/rateLimit.js +4 -0
  96. package/dist/server/realtimeSyncWs.js +36 -12
  97. package/dist/server/routes/admin.js +1 -0
  98. package/dist/server/routes/agentRoles.js +3 -2
  99. package/dist/server/routes/agentSkills.js +3 -2
  100. package/dist/server/routes/agents.js +118 -16
  101. package/dist/server/routes/annotatedAttachments.js +3 -2
  102. package/dist/server/routes/auth.js +3 -1
  103. package/dist/server/routes/durableTaskHttpRouters.d.ts +9 -2
  104. package/dist/server/routes/localService.js +2 -0
  105. package/dist/server/routes/primitives.d.ts +2 -0
  106. package/dist/server/routes/syncAuxRoutes.js +5 -2
  107. package/dist/server/routes/syncPullApplyRoutes.js +23 -4
  108. package/dist/server/routes/syncV3FeedRoutes.js +18 -16
  109. package/dist/server/routes/syncV3LocalCaptureRoutes.js +28 -2
  110. package/dist/server/routes/syncV3LocalFeedApplyRoutes.d.ts +1 -0
  111. package/dist/server/routes/syncV3LocalFeedApplyRoutes.js +26 -0
  112. package/dist/server/routes/syncV3OperationRoutes.js +10 -0
  113. package/dist/server/routes/tasks.js +103 -11
  114. package/dist/server/routes/workspaces.js +43 -1
  115. package/dist/server/workspaceDeletionAdmission.d.ts +23 -0
  116. package/dist/server/workspaceDeletionAdmission.js +50 -0
  117. package/dist/service/localServiceCli.js +16 -0
  118. package/dist/service/localServiceClientLifecycle.js +36 -10
  119. package/dist/services/codexAppServerModelGateway.d.ts +112 -0
  120. package/dist/services/codexAppServerModelGateway.js +438 -0
  121. package/dist/services/taskforceAgentMcpBridge.d.ts +7 -1
  122. package/dist/services/taskforceAgentMcpBridge.js +23 -3
  123. package/dist/shared/taskforceAgentDefinition.js +7 -1
  124. package/dist/shared/taskforceAgentModels.d.ts +1 -0
  125. package/dist/shared/taskforceAgentModels.js +30 -1
  126. package/dist/storage/postgresAdapter.d.ts +20 -3
  127. package/dist/storage/postgresAdapter.js +106 -14
  128. package/dist/storage/postgresWorker.js +13 -4
  129. package/dist/storage/postgresWorkerProtocol.d.ts +29 -0
  130. package/dist/storage/postgresWorkerProtocol.js +30 -0
  131. package/dist/sync/cloudSyncApi.d.ts +4 -1
  132. package/dist/sync/cloudSyncApi.js +7 -2
  133. package/dist/sync/contentSyncState.d.ts +1 -1
  134. package/dist/sync/coordinator/localSyncExecutionPermitStore.d.ts +1 -0
  135. package/dist/sync/coordinator/localSyncExecutionPermitStore.js +7 -1
  136. package/dist/sync/coordinator/localWorkspaceSyncRunner.js +6 -2
  137. package/dist/sync/engine/workspaceSyncEngineBrowserGatewayRemoteServices.js +20 -2
  138. package/dist/sync/engine/workspaceSyncEngineLocalServices.d.ts +4 -0
  139. package/dist/sync/engine/workspaceSyncEngineLocalServices.js +11 -0
  140. package/dist/sync/engine/workspaceSyncEngineRemoteServices.d.ts +11 -0
  141. package/dist/sync/engine/workspaceSyncEngineRemoteServices.js +2 -1
  142. package/dist/sync/engine/workspaceSyncEngineServerRemoteServices.js +31 -4
  143. package/dist/sync/engine/workspaceSyncEngineServerRunnerOperations.d.ts +3 -1
  144. package/dist/sync/engine/workspaceSyncEngineServerRunnerOperations.js +25 -8
  145. package/dist/sync/engine/workspaceSyncEngineTransfers.d.ts +1 -1
  146. package/dist/sync/engine/workspaceSyncEngineTransfers.js +8 -3
  147. package/dist/sync/syncService.d.ts +2 -0
  148. package/dist/sync/syncService.js +4 -1
  149. package/dist/sync/v3/combinedFeedCapability.js +4 -0
  150. package/dist/sync/v3/durableTaskAttachmentLinksMutationRouter.d.ts +2 -0
  151. package/dist/sync/v3/durableTaskAttachmentLinksMutationRouter.js +11 -1
  152. package/dist/sync/v3/durableTaskChecklistMutationRouter.d.ts +2 -0
  153. package/dist/sync/v3/durableTaskChecklistMutationRouter.js +4 -0
  154. package/dist/sync/v3/durableTaskHttpBulkMutationRouter.d.ts +1 -0
  155. package/dist/sync/v3/durableTaskHttpBulkMutationRouter.js +30 -8
  156. package/dist/sync/v3/durableTaskHttpRootMutationRouter.d.ts +5 -3
  157. package/dist/sync/v3/durableTaskHttpRootMutationRouter.js +27 -2
  158. package/dist/sync/v3/localTaskAttachmentLinksOutboxService.d.ts +2 -0
  159. package/dist/sync/v3/localTaskAttachmentLinksOutboxService.js +47 -7
  160. package/dist/sync/v3/localTaskCreateOutboxService.js +15 -6
  161. package/dist/sync/v3/localTaskMetadataClient.d.ts +1 -0
  162. package/dist/sync/v3/localTaskMetadataClient.js +1 -0
  163. package/dist/sync/v3/localTaskMetadataOutboxHandler.js +5 -1
  164. package/dist/sync/v3/localTaskMetadataOutboxService.d.ts +2 -0
  165. package/dist/sync/v3/localTaskMetadataOutboxService.js +7 -0
  166. package/dist/sync/v3/localTaskRestoreOutboxService.js +14 -6
  167. package/dist/sync/v3/localTaskStatusClient.d.ts +1 -0
  168. package/dist/sync/v3/localTaskStatusClient.js +6 -1
  169. package/dist/sync/v3/localTaskStatusOutboxService.d.ts +2 -0
  170. package/dist/sync/v3/localTaskStatusOutboxService.js +54 -13
  171. package/dist/sync/v3/syncDurabilityStore.d.ts +7 -0
  172. package/dist/sync/v3/syncDurabilityStore.js +31 -11
  173. package/dist/sync/v3/taskAttachmentLinksMutationService.d.ts +6 -4
  174. package/dist/sync/v3/taskAttachmentLinksMutationService.js +19 -10
  175. package/dist/sync/v3/taskChecklistMutationService.d.ts +4 -2
  176. package/dist/sync/v3/taskChecklistMutationService.js +4 -0
  177. package/dist/sync/v3/taskCreateMutationService.d.ts +2 -2
  178. package/dist/sync/v3/taskCreateMutationService.js +7 -4
  179. package/dist/sync/v3/taskMetadataMutationService.d.ts +3 -0
  180. package/dist/sync/v3/taskMetadataMutationService.js +4 -0
  181. package/dist/sync/v3/taskRestoreMutationService.d.ts +2 -2
  182. package/dist/sync/v3/taskRestoreMutationService.js +7 -4
  183. package/dist/sync/v3/taskStatusMutationService.d.ts +2 -0
  184. package/dist/sync/v3/taskStatusMutationService.js +4 -0
  185. package/dist/sync/v3/workflowAssignmentSync.d.ts +1 -0
  186. package/dist/sync/v3/workflowAssignmentSync.js +3 -0
  187. package/dist/sync/v3/workspaceSyncV2ProjectionExclusions.d.ts +1 -1
  188. package/dist/sync/v3/workspaceSyncV2ProjectionExclusions.js +13 -3
  189. package/dist/sync/v3/workspaceSyncV3AttachmentApplyObligationStore.d.ts +11 -0
  190. package/dist/sync/v3/workspaceSyncV3AttachmentApplyObligationStore.js +27 -10
  191. package/dist/sync/v3/workspaceSyncV3AttachmentAssetHydration.d.ts +2 -1
  192. package/dist/sync/v3/workspaceSyncV3AttachmentAssetHydration.js +52 -10
  193. package/dist/sync/v3/workspaceSyncV3CloudOperationHandler.js +9 -1
  194. package/dist/sync/v3/workspaceSyncV3CombinedFeedOrchestrator.js +8 -3
  195. package/dist/sync/v3/workspaceSyncV3CombinedLocalApply.js +51 -10
  196. package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.d.ts +7 -0
  197. package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.js +30 -18
  198. package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.d.ts +9 -4
  199. package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.js +98 -47
  200. package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.d.ts +10 -0
  201. package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.js +58 -21
  202. package/dist/sync/v3/workspaceSyncV3CombinedWireContract.d.ts +3 -1
  203. package/dist/sync/v3/workspaceSyncV3CombinedWireContract.js +18 -0
  204. package/dist/sync/v3/workspaceSyncV3CoverageRegistry.js +6 -0
  205. package/dist/sync/v3/workspaceSyncV3FeedProfile.d.ts +1 -1
  206. package/dist/sync/v3/workspaceSyncV3LegacyBoundaryAttestation.d.ts +1 -0
  207. package/dist/sync/v3/workspaceSyncV3LegacyBoundaryAttestation.js +23 -10
  208. package/dist/sync/v3/workspaceSyncV3NestedTaskApply.d.ts +3 -0
  209. package/dist/sync/v3/workspaceSyncV3NestedTaskApply.js +64 -13
  210. package/dist/sync/v3/workspaceSyncV3NestedTaskCodecs.d.ts +9 -0
  211. package/dist/sync/v3/workspaceSyncV3NestedTaskCodecs.js +26 -0
  212. package/dist/sync/v3/workspaceSyncV3NestedTaskProjection.d.ts +15 -5
  213. package/dist/sync/v3/workspaceSyncV3NestedTaskProjection.js +50 -14
  214. package/dist/sync/v3/workspaceSyncV3NestedTaskRepairSnapshot.d.ts +2 -1
  215. package/dist/sync/v3/workspaceSyncV3NestedTaskRepairSnapshot.js +11 -3
  216. package/dist/sync/v3/workspaceSyncV3OperationProtocol.d.ts +2 -0
  217. package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.d.ts +2 -0
  218. package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.js +19 -7
  219. package/dist/sync/v3/workspaceSyncV3TaskCommentAudit.js +9 -2
  220. package/dist/sync/v3/workspaceSyncV3TaskCoverCoverage.d.ts +7 -0
  221. package/dist/sync/v3/workspaceSyncV3TaskCoverCoverage.js +37 -0
  222. package/dist/sync/v3/workspaceSyncV3TaskCoverWireContract.d.ts +6 -0
  223. package/dist/sync/v3/workspaceSyncV3TaskCoverWireContract.js +9 -0
  224. package/dist/sync/workspacePullFeed.js +2 -1
  225. package/dist/sync/workspaceRepair.d.ts +3 -0
  226. package/dist/sync/workspaceRepair.js +67 -6
  227. package/dist/types.d.ts +47 -1
  228. package/dist/types.js +6 -0
  229. package/dist/ui/assets/{AiIdentityRosterCard-MZs7lVED.js → AiIdentityRosterCard-BZM4aQnM.js} +1 -1
  230. package/dist/ui/assets/AiProfilesModule-BbAEWtHH.js +1 -0
  231. package/dist/ui/assets/AnnotatedAttachmentWorkspace-B68Wg-RV.js +3 -0
  232. package/dist/ui/assets/AnnotatedAttachmentWorkspace-TzYu7pkG.css +1 -0
  233. package/dist/ui/assets/{AssetTraySortControl-Kf1pelSy.js → AssetTraySortControl-C8Rztyal.js} +1 -1
  234. package/dist/ui/assets/{ContextAttachmentManager-B8boOs6Q.js → ContextAttachmentManager-Cj3c7X9y.js} +2 -2
  235. package/dist/ui/assets/{DocumentWorkspace-DXH4XUsB.js → DocumentWorkspace-B5uvzems.js} +1 -1
  236. package/dist/ui/assets/{EntityActivityTimeline-BtSTq0ON.js → EntityActivityTimeline-BVFvCB5R.js} +1 -1
  237. package/dist/ui/assets/PlanningModule-B5DWQOGz.js +1 -0
  238. package/dist/ui/assets/PlansPage-AY4cGWco.js +1 -0
  239. package/dist/ui/assets/TaskContextUpload-DZxTVesW.js +1 -0
  240. package/dist/ui/assets/TaskSettings-BeWAuyZj.js +12 -0
  241. package/dist/ui/assets/{TaskforceAgentsModule-BazdUwxZ.js → TaskforceAgentsModule-BifCYtjR.js} +6 -6
  242. package/dist/ui/assets/{WorkflowManagerModule-DWFspC-o.js → WorkflowManagerModule-DEr5di_r.js} +1 -1
  243. package/dist/ui/assets/index-I5zhdtgt.js +7 -0
  244. package/dist/ui/assets/index-VRFsx3wz.css +1 -0
  245. package/dist/ui/assets/{vendor-icons-BkFLXavV.js → vendor-icons-D9Lpw-j4.js} +1 -1
  246. package/dist/ui/index.html +3 -3
  247. package/dist/utils/taskActivity.d.ts +3 -2
  248. package/dist/utils/taskActivity.js +19 -2
  249. package/dist/utils/taskEditorReconciliation.d.ts +40 -0
  250. package/dist/utils/taskEditorReconciliation.js +217 -0
  251. package/dist/utils/taskNormalization.d.ts +1 -0
  252. package/dist/utils/taskNormalization.js +39 -0
  253. package/dist/utils/taskSearch.js +2 -2
  254. package/dist/utils/uiNotice.d.ts +4 -0
  255. package/package.json +16 -4
  256. package/dist/ui/assets/AiProfilesModule-C3i0LOxe.js +0 -1
  257. package/dist/ui/assets/AnnotatedAttachmentWorkspace-CBRZ8rca.css +0 -1
  258. package/dist/ui/assets/AnnotatedAttachmentWorkspace-DVZk5Tln.js +0 -3
  259. package/dist/ui/assets/PlanningModule-BPVyEa-f.js +0 -1
  260. package/dist/ui/assets/PlansPage-ChqgxALc.js +0 -1
  261. package/dist/ui/assets/TaskContextUpload-CB3ol0sN.js +0 -1
  262. package/dist/ui/assets/TaskSettings-g4ECKNOz.js +0 -12
  263. package/dist/ui/assets/index-BUplSsv_.js +0 -7
  264. package/dist/ui/assets/index-gz2EXuoK.css +0 -1
@@ -11,8 +11,16 @@ function nullableStringProperty(description) {
11
11
  ],
12
12
  };
13
13
  }
14
- function numberProperty(description) {
15
- return { type: 'number', description };
14
+ function integerProperty(description, minimum, maximum) {
15
+ return {
16
+ type: 'integer',
17
+ description,
18
+ ...(minimum === undefined ? {} : { minimum }),
19
+ ...(maximum === undefined ? {} : { maximum }),
20
+ };
21
+ }
22
+ function integerEnumProperty(description, values) {
23
+ return { type: 'integer', description, enum: values };
16
24
  }
17
25
  function booleanProperty(description) {
18
26
  return { type: 'boolean', description };
@@ -57,7 +65,7 @@ export function registerTaskPlanningTools(registerTool, executeTool) {
57
65
  title: stringProperty('Initiative title.'),
58
66
  description: stringProperty('Optional initiative description.'),
59
67
  ownerId: stringProperty(`${context.assigneeHint} Call list_assignees to inspect eligible IDs.`),
60
- order: numberProperty('Optional initiative order.'),
68
+ order: integerProperty('Optional non-negative initiative order.', 0),
61
69
  },
62
70
  required: ['title'],
63
71
  },
@@ -71,7 +79,7 @@ export function registerTaskPlanningTools(registerTool, executeTool) {
71
79
  title: stringProperty('Workstream title.'),
72
80
  description: stringProperty('Optional workstream description.'),
73
81
  ownerId: stringProperty(`${context.assigneeHint} Call list_assignees to inspect eligible IDs.`),
74
- order: numberProperty('Optional workstream order.'),
82
+ order: integerProperty('Optional non-negative workstream order.', 0),
75
83
  tasks: {
76
84
  type: 'array', maxItems: 50,
77
85
  items: {
@@ -83,8 +91,8 @@ export function registerTaskPlanningTools(registerTool, executeTool) {
83
91
  assignee: stringProperty(`${context.assigneeHint} Call list_assignees to inspect eligible IDs.`),
84
92
  category: stringProperty('Task category.', context.categoryEnum),
85
93
  type: stringProperty('Task type.', context.typeEnum),
86
- priority: numberProperty(context.priorityDesc),
87
- complexity: numberProperty(context.complexityDesc),
94
+ priority: integerEnumProperty(context.priorityDesc, context.priorityEnum),
95
+ complexity: integerProperty(context.complexityDesc, 1, 5),
88
96
  scheduledDate: stringProperty('Optional schedule date (YYYY-MM-DD).'),
89
97
  dueDate: stringProperty('Optional due date (YYYY-MM-DD).'),
90
98
  },
@@ -120,22 +128,24 @@ export function registerTaskPlanningTools(registerTool, executeTool) {
120
128
  status: stringProperty('Filter by status.', ['task', 'on-hold', 'in-progress', 'review', 'done', 'cancelled']),
121
129
  openOnly: booleanProperty('When true, only include open tasks (task, on-hold, in-progress, review).'),
122
130
  assignee: stringProperty(context.assigneeHint),
123
- priority: numberProperty('Filter by priority level.'),
131
+ priority: integerEnumProperty(context.priorityDesc, context.priorityEnum),
124
132
  type: stringProperty('Filter by task type.', context.typeEnum),
125
133
  workstreamId: stringProperty('Filter by workstream ID or workstream reference such as WS-123.'),
126
134
  sort: stringProperty('Sort field (default: created).', ['priority', 'created', 'updated']),
127
135
  order: stringProperty('Sort order (default: desc).', ['asc', 'desc']),
128
- limit: numberProperty('Max tasks to return.'),
129
- offset: numberProperty('Non-negative result offset for pagination (default: 0).'),
136
+ limit: integerProperty('Max tasks to return (max 200).', 1, 200),
137
+ offset: integerProperty('Non-negative result offset for pagination (default: 0).', 0),
130
138
  },
131
139
  },
132
140
  }));
133
141
  register('search_tasks', (context) => ({
134
- description: context.describeTool('Search active and archived tasks by keyword, ID, T-* reference, or provisional LT-* reference. Use scope to narrow results. Prefer this over list_tasks when looking for a specific task by name. When results include links, preserve those links when presenting tasks.'),
142
+ description: context.describeTool('Search active and archived tasks by keyword, ID, T-* reference, or provisional LT-* reference. Use scope to narrow results and offset/limit to continue broad searches. Prefer this over list_tasks when looking for a specific task by name. When results include links, preserve those links when presenting tasks.'),
135
143
  inputSchema: {
136
144
  properties: {
137
145
  query: stringProperty('Search term or exact task reference such as T-123 or LT-123.'),
138
146
  scope: stringProperty('Search scope (default: all).', ['all', 'active', 'archive']),
147
+ limit: integerProperty('Page size (default 25; max 50).', 1, 50),
148
+ offset: integerProperty('Non-negative result offset (default 0).', 0),
139
149
  },
140
150
  required: ['query'],
141
151
  },
@@ -179,10 +189,12 @@ export function registerTaskPlanningTools(registerTool, executeTool) {
179
189
  },
180
190
  }));
181
191
  register('list_initiatives', (context) => ({
182
- description: context.describeTool('List or search initiatives for the active workspace. Pass query to search by initiative title, description, ID/reference, owner, or linked workstream title. Returns compact initiative summaries with workstream and task counts.'),
192
+ description: context.describeTool('List or search initiatives for the active workspace. Pass query to search by initiative title, description, ID/reference, owner, or linked workstream title. Use offset/limit to continue through compact summaries.'),
183
193
  inputSchema: {
184
194
  properties: {
185
195
  query: stringProperty('Optional search term for initiative title, description, ID/reference such as IN-123, owner, or linked workstream title.'),
196
+ limit: { type: 'integer', minimum: 1, maximum: 100, description: 'Page size (default 25; max 100).' },
197
+ offset: { type: 'integer', minimum: 0, description: 'Non-negative result offset (default 0).' },
186
198
  },
187
199
  },
188
200
  }));
@@ -205,7 +217,7 @@ export function registerTaskPlanningTools(registerTool, executeTool) {
205
217
  title: stringProperty('Initiative title.'),
206
218
  description: stringProperty('Optional initiative description.'),
207
219
  ownerId: stringProperty(context.assigneeHint),
208
- order: numberProperty('Optional sort order among initiatives.'),
220
+ order: integerProperty('Optional non-negative sort order among initiatives.', 0),
209
221
  attachments: arrayProperty('Optional attachment descriptors to store on the initiative. Prefer save_initiative_attachment for generated content or files.', {
210
222
  type: 'object',
211
223
  properties: {
@@ -231,7 +243,7 @@ export function registerTaskPlanningTools(registerTool, executeTool) {
231
243
  title: stringProperty('Updated initiative title.'),
232
244
  description: stringProperty('Updated initiative description.'),
233
245
  ownerId: stringProperty(context.assigneeHint),
234
- order: numberProperty('Optional sort order among initiatives.'),
246
+ order: integerProperty('Optional non-negative sort order among initiatives.', 0),
235
247
  attachments: arrayProperty('Replacement attachment descriptors for the initiative. Prefer save_initiative_attachment for generated content or files. Removing managed attachments requires delete_initiative_attachment in the extended profile.', {
236
248
  type: 'object',
237
249
  properties: {
@@ -278,10 +290,12 @@ export function registerTaskPlanningTools(registerTool, executeTool) {
278
290
  },
279
291
  }));
280
292
  register('list_workstreams', (context) => ({
281
- description: context.describeTool('List or search workstreams for the active workspace. Pass query to search by workstream title, description, ID/reference, owner, or linked initiative title/reference. Returns compact workstream summaries with task counts.'),
293
+ description: context.describeTool('List or search workstreams for the active workspace. Pass query to search by workstream title, description, ID/reference, owner, or linked initiative title/reference. Use offset/limit to continue through compact summaries.'),
282
294
  inputSchema: {
283
295
  properties: {
284
296
  query: stringProperty('Optional search term for workstream title, description, ID/reference such as WS-123, owner, or linked initiative title/reference.'),
297
+ limit: { type: 'integer', minimum: 1, maximum: 100, description: 'Page size (default 25; max 100).' },
298
+ offset: { type: 'integer', minimum: 0, description: 'Non-negative result offset (default 0).' },
285
299
  },
286
300
  },
287
301
  }));
@@ -305,7 +319,7 @@ export function registerTaskPlanningTools(registerTool, executeTool) {
305
319
  description: stringProperty('Optional workstream description.'),
306
320
  ownerId: stringProperty(context.assigneeHint),
307
321
  initiativeId: stringProperty('Optional initiative ID or initiative reference such as IN-123.'),
308
- order: numberProperty('Optional sort order among workstreams.'),
322
+ order: integerProperty('Optional non-negative sort order among workstreams.', 0),
309
323
  attachments: arrayProperty('Optional attachment descriptors to store on the workstream. Prefer save_workstream_attachment for generated content or files.', {
310
324
  type: 'object',
311
325
  properties: {
@@ -332,7 +346,7 @@ export function registerTaskPlanningTools(registerTool, executeTool) {
332
346
  description: stringProperty('Updated workstream description.'),
333
347
  ownerId: stringProperty(context.assigneeHint),
334
348
  initiativeId: stringProperty('Optional initiative ID or initiative reference such as IN-123. Pass an empty string to unlink.'),
335
- order: numberProperty('Optional sort order among workstreams.'),
349
+ order: integerProperty('Optional non-negative sort order among workstreams.', 0),
336
350
  attachments: arrayProperty('Replacement attachment descriptors for the workstream. Prefer save_workstream_attachment for generated content or files. Removing managed attachments requires delete_workstream_attachment in the extended profile.', {
337
351
  type: 'object',
338
352
  properties: {
@@ -384,9 +398,9 @@ export function registerTaskPlanningTools(registerTool, executeTool) {
384
398
  inputSchema: {
385
399
  properties: {
386
400
  taskId: stringProperty('Task ID or task reference such as T-123.'),
387
- id: stringProperty('Alias for taskId. Task ID or task reference such as T-123.'),
388
401
  workstreamId: nullableStringProperty('Workstream ID or workstream reference such as WS-123. Pass an empty string or null to unlink.'),
389
402
  },
403
+ required: ['taskId', 'workstreamId'],
390
404
  },
391
405
  }));
392
406
  register('update_workstream_initiative', (context) => ({
@@ -394,9 +408,9 @@ export function registerTaskPlanningTools(registerTool, executeTool) {
394
408
  inputSchema: {
395
409
  properties: {
396
410
  workstreamId: stringProperty('Workstream ID or workstream reference such as WS-123.'),
397
- id: stringProperty('Alias for workstreamId. Workstream ID or workstream reference such as WS-123.'),
398
411
  initiativeId: nullableStringProperty('Initiative ID or initiative reference such as IN-123. Pass an empty string or null to unlink.'),
399
412
  },
413
+ required: ['workstreamId', 'initiativeId'],
400
414
  },
401
415
  }));
402
416
  register('get_task_checklist', (context) => ({
@@ -430,7 +444,7 @@ export function registerTaskPlanningTools(registerTool, executeTool) {
430
444
  id: { type: 'string', description: 'Stable checklist item ID. Reuse it when reordering or updating an existing item.' },
431
445
  text: { type: 'string' },
432
446
  done: { type: 'boolean' },
433
- order: { type: 'number', description: 'Optional zero-based display order.' },
447
+ order: { type: 'integer', minimum: 0, description: 'Optional zero-based display order.' },
434
448
  createdAt: { type: 'string', description: 'Optional canonical ISO creation timestamp.' },
435
449
  updatedAt: { type: 'string', description: 'Optional canonical ISO last-change timestamp.' },
436
450
  },
@@ -454,28 +468,17 @@ export function registerTaskPlanningTools(registerTool, executeTool) {
454
468
  inputSchema: {
455
469
  properties: {
456
470
  taskId: stringProperty('Task ID or task reference such as T-123.'),
457
- id: stringProperty('Alias for taskId.'),
458
471
  date: nullableStringProperty('YYYY-MM-DD; null or empty with taskId unschedules.'),
459
- scheduledDate: nullableStringProperty('Alias for date.'),
460
- order: numberProperty('Optional position within that day.'),
461
- orderInDay: numberProperty('Alias for order.'),
472
+ order: integerProperty('Optional non-negative position within that day.', 0),
462
473
  taskIds: arrayProperty('Ordered task IDs or references replacing one day.', { type: 'string' }),
463
- moves: arrayProperty('Advanced reorder moves using task, date, and order aliases.', {
474
+ moves: arrayProperty('Advanced reorder moves using canonical taskId, date, and order fields.', {
464
475
  type: 'object',
465
476
  properties: {
466
- id: { type: 'string' },
467
477
  taskId: { type: 'string' },
468
478
  date: { type: 'string' },
469
- scheduledDate: { type: 'string' },
470
- order: { type: 'number' },
471
- orderInDay: { type: 'number' },
479
+ order: { type: 'integer', minimum: 0 },
472
480
  },
473
- anyOf: [
474
- { required: ['id', 'date'] },
475
- { required: ['id', 'scheduledDate'] },
476
- { required: ['taskId', 'date'] },
477
- { required: ['taskId', 'scheduledDate'] },
478
- ],
481
+ required: ['taskId', 'date'],
479
482
  }),
480
483
  },
481
484
  },
@@ -535,9 +538,9 @@ export function registerTaskPlanningTools(registerTool, executeTool) {
535
538
  workstreamId: stringProperty('Workstream ID or WS-123; use to create the task directly inside a workstream. Search list_workstreams if needed.'),
536
539
  category: stringProperty('Task category value.', context.categoryEnum),
537
540
  type: stringProperty('Task type value.', context.typeEnum),
538
- priority: numberProperty(context.priorityDesc),
541
+ priority: integerEnumProperty(context.priorityDesc, context.priorityEnum),
539
542
  status: stringProperty('Initial task status.', ['task', 'on-hold', 'in-progress', 'review', 'done', 'cancelled']),
540
- complexity: numberProperty(context.complexityDesc),
543
+ complexity: integerProperty(context.complexityDesc, 1, 5),
541
544
  scheduledDate: stringProperty('Optional scheduled date in YYYY-MM-DD format.'),
542
545
  dueDate: stringProperty('Optional due date in YYYY-MM-DD format.'),
543
546
  },
@@ -574,9 +577,9 @@ export function registerTaskPlanningTools(registerTool, executeTool) {
574
577
  workstreamId: stringProperty('Updated workstream ID or workstream reference such as WS-123. Pass an empty string to unlink the task. Call list_workstreams with query first if you only know the workstream name.'),
575
578
  category: stringProperty('Updated category value.', context.categoryEnum),
576
579
  type: stringProperty('Updated task type value.', context.typeEnum),
577
- priority: numberProperty(context.priorityDesc),
580
+ priority: integerEnumProperty(context.priorityDesc, context.priorityEnum),
578
581
  status: stringProperty('Updated task status.', ['task', 'on-hold', 'in-progress', 'review', 'done', 'cancelled']),
579
- complexity: numberProperty(context.complexityDesc),
582
+ complexity: integerProperty(context.complexityDesc, 1, 5),
580
583
  scheduledDate: stringProperty('Updated scheduled date in YYYY-MM-DD format. Pass an empty string to clear.'),
581
584
  dueDate: stringProperty('Updated due date in YYYY-MM-DD format. Pass an empty string to clear.'),
582
585
  },
@@ -10,7 +10,44 @@ export function resolveCanonicalMcpToolName(nameRaw) {
10
10
  export function resolveMcpToolCallCompatibility(nameRaw, argsRaw) {
11
11
  const name = resolveCanonicalMcpToolName(nameRaw);
12
12
  const args = argsRaw && typeof argsRaw === 'object' && !Array.isArray(argsRaw)
13
- ? argsRaw
13
+ ? { ...argsRaw }
14
14
  : {};
15
+ const moveAlias = (alias, canonical) => {
16
+ if (args[canonical] === undefined && args[alias] !== undefined)
17
+ args[canonical] = args[alias];
18
+ delete args[alias];
19
+ };
20
+ if (name === 'get_image')
21
+ moveAlias('id', 'imageId');
22
+ if (name === 'get_image_annotations')
23
+ moveAlias('imageAssetId', 'imageId');
24
+ if (name === 'get_task_attachments')
25
+ moveAlias('id', 'taskId');
26
+ if (name === 'update_task_workstream')
27
+ moveAlias('id', 'taskId');
28
+ if (name === 'update_workstream_initiative')
29
+ moveAlias('id', 'workstreamId');
30
+ if (name === 'update_schedule') {
31
+ moveAlias('id', 'taskId');
32
+ moveAlias('scheduledDate', 'date');
33
+ moveAlias('orderInDay', 'order');
34
+ if (Array.isArray(args.moves)) {
35
+ args.moves = args.moves.map((move) => {
36
+ if (!move || typeof move !== 'object' || Array.isArray(move))
37
+ return move;
38
+ const normalized = { ...move };
39
+ const normalizeMoveAlias = (alias, canonical) => {
40
+ if (normalized[canonical] === undefined && normalized[alias] !== undefined) {
41
+ normalized[canonical] = normalized[alias];
42
+ }
43
+ delete normalized[alias];
44
+ };
45
+ normalizeMoveAlias('id', 'taskId');
46
+ normalizeMoveAlias('scheduledDate', 'date');
47
+ normalizeMoveAlias('orderInDay', 'order');
48
+ return normalized;
49
+ });
50
+ }
51
+ }
15
52
  return { name, arguments: args };
16
53
  }
@@ -22,6 +22,7 @@ export type McpToolDescriptorContext = {
22
22
  describeTool: (text: string) => string;
23
23
  assigneeHint: string;
24
24
  categoryEnum: string[];
25
+ priorityEnum: number[];
25
26
  priorityDesc: string;
26
27
  typeEnum: string[];
27
28
  complexityDesc: string;
@@ -1423,6 +1423,7 @@ export function buildWorkspaceSyncDurabilitySchemaSql(provider) {
1423
1423
  base_lifecycle_revision ${revisionType} NOT NULL DEFAULT 0,
1424
1424
  payload_json TEXT NOT NULL,
1425
1425
  payload_fingerprint TEXT NOT NULL,
1426
+ canonical_intent_json TEXT,
1426
1427
  status TEXT NOT NULL DEFAULT 'pending',
1427
1428
  attempt_count INTEGER NOT NULL DEFAULT 0,
1428
1429
  initial_not_found_attempt_count INTEGER NOT NULL DEFAULT 0,
@@ -1827,6 +1828,9 @@ export function ensureWorkspaceSyncDurabilitySchema(db) {
1827
1828
  if (!outboxColumns.some((column) => column.name === 'initial_not_found_attempt_count')) {
1828
1829
  db.exec(`ALTER TABLE workspace_sync_outbox ADD COLUMN initial_not_found_attempt_count INTEGER NOT NULL DEFAULT 0`);
1829
1830
  }
1831
+ if (!outboxColumns.some((column) => column.name === 'canonical_intent_json')) {
1832
+ db.exec(`ALTER TABLE workspace_sync_outbox ADD COLUMN canonical_intent_json TEXT`);
1833
+ }
1830
1834
  if (!outboxColumns.some((column) => column.name === 'owns_task_metadata')) {
1831
1835
  db.exec(`ALTER TABLE workspace_sync_outbox ADD COLUMN owns_task_metadata INTEGER NOT NULL DEFAULT 0`);
1832
1836
  }
@@ -2129,6 +2133,8 @@ export function ensureLocalSyncCoordinatorSchema(db) {
2129
2133
  created_at TEXT NOT NULL,
2130
2134
  updated_at TEXT NOT NULL,
2131
2135
  next_attempt_at TEXT NOT NULL,
2136
+ terminal_at TEXT,
2137
+ terminal_reason TEXT,
2132
2138
  resolved_at TEXT,
2133
2139
  PRIMARY KEY (tenant_id, workspace_id, task_id)
2134
2140
  );
@@ -2172,6 +2178,12 @@ export function ensureLocalSyncCoordinatorSchema(db) {
2172
2178
  if (!attachmentApplyColumns.has('revision_fingerprint')) {
2173
2179
  db.exec(`ALTER TABLE workspace_sync_v3_attachment_apply_obligations ADD COLUMN revision_fingerprint TEXT`);
2174
2180
  }
2181
+ if (!attachmentApplyColumns.has('terminal_at')) {
2182
+ db.exec(`ALTER TABLE workspace_sync_v3_attachment_apply_obligations ADD COLUMN terminal_at TEXT`);
2183
+ }
2184
+ if (!attachmentApplyColumns.has('terminal_reason')) {
2185
+ db.exec(`ALTER TABLE workspace_sync_v3_attachment_apply_obligations ADD COLUMN terminal_reason TEXT`);
2186
+ }
2175
2187
  const coordinatorStateColumns = db.provider === 'postgres'
2176
2188
  ? new Set(db.prepare(`
2177
2189
  SELECT column_name AS name
@@ -1,36 +1,60 @@
1
1
  export declare const APP_GATE_DEFINITIONS: {
2
2
  readonly 'annotated_attachments.workspace_access': {
3
- readonly enabled: true;
3
+ readonly enabledByEnvironment: {
4
+ readonly performance: true;
5
+ readonly staging: true;
6
+ readonly production: true;
7
+ };
4
8
  readonly description: "Annotated Attachment workspace readiness gate.";
5
9
  readonly owner: "taskforce";
6
10
  readonly removalMilestone: "Annotated Attachment GA";
7
11
  };
8
12
  readonly 'documents.workspace_access': {
9
- readonly enabled: true;
13
+ readonly enabledByEnvironment: {
14
+ readonly performance: true;
15
+ readonly staging: true;
16
+ readonly production: true;
17
+ };
10
18
  readonly description: "Document Manager/editor workspace readiness gate.";
11
19
  readonly owner: "taskforce";
12
20
  readonly removalMilestone: "Document Manager GA";
13
21
  };
14
22
  readonly 'workflow_manager.workspace_access': {
15
- readonly enabled: false;
23
+ readonly enabledByEnvironment: {
24
+ readonly performance: true;
25
+ readonly staging: true;
26
+ readonly production: false;
27
+ };
16
28
  readonly description: "Workflow Manager workspace readiness gate.";
17
29
  readonly owner: "taskforce";
18
30
  readonly removalMilestone: "Workflow Manager GA";
19
31
  };
20
32
  readonly 'taskforce_agents.workspace_access': {
21
- readonly enabled: false;
33
+ readonly enabledByEnvironment: {
34
+ readonly performance: true;
35
+ readonly staging: true;
36
+ readonly production: false;
37
+ };
22
38
  readonly description: "Taskforce Agents workspace readiness gate.";
23
39
  readonly owner: "taskforce";
24
40
  readonly removalMilestone: "Taskforce Agents workspace GA";
25
41
  };
26
42
  readonly 'ai_profiles.workspace_access': {
27
- readonly enabled: true;
43
+ readonly enabledByEnvironment: {
44
+ readonly performance: true;
45
+ readonly staging: true;
46
+ readonly production: true;
47
+ };
28
48
  readonly description: "AI Profiles workspace readiness gate.";
29
49
  readonly owner: "taskforce";
30
50
  readonly removalMilestone: "AI Profiles workspace GA";
31
51
  };
32
52
  readonly 'planning.workspace_access': {
33
- readonly enabled: false;
53
+ readonly enabledByEnvironment: {
54
+ readonly performance: false;
55
+ readonly staging: false;
56
+ readonly production: false;
57
+ };
34
58
  readonly description: "Planning workspace readiness gate.";
35
59
  readonly owner: "taskforce";
36
60
  readonly removalMilestone: "Planning workspace GA";
@@ -1,36 +1,36 @@
1
1
  export const APP_GATE_DEFINITIONS = {
2
2
  'annotated_attachments.workspace_access': {
3
- enabled: true,
3
+ enabledByEnvironment: { performance: true, staging: true, production: true },
4
4
  description: 'Annotated Attachment workspace readiness gate.',
5
5
  owner: 'taskforce',
6
6
  removalMilestone: 'Annotated Attachment GA'
7
7
  },
8
8
  'documents.workspace_access': {
9
- enabled: true,
9
+ enabledByEnvironment: { performance: true, staging: true, production: true },
10
10
  description: 'Document Manager/editor workspace readiness gate.',
11
11
  owner: 'taskforce',
12
12
  removalMilestone: 'Document Manager GA'
13
13
  },
14
14
  'workflow_manager.workspace_access': {
15
- enabled: false,
15
+ enabledByEnvironment: { performance: true, staging: true, production: false },
16
16
  description: 'Workflow Manager workspace readiness gate.',
17
17
  owner: 'taskforce',
18
18
  removalMilestone: 'Workflow Manager GA'
19
19
  },
20
20
  'taskforce_agents.workspace_access': {
21
- enabled: false,
21
+ enabledByEnvironment: { performance: true, staging: true, production: false },
22
22
  description: 'Taskforce Agents workspace readiness gate.',
23
23
  owner: 'taskforce',
24
24
  removalMilestone: 'Taskforce Agents workspace GA'
25
25
  },
26
26
  'ai_profiles.workspace_access': {
27
- enabled: true,
27
+ enabledByEnvironment: { performance: true, staging: true, production: true },
28
28
  description: 'AI Profiles workspace readiness gate.',
29
29
  owner: 'taskforce',
30
30
  removalMilestone: 'AI Profiles workspace GA'
31
31
  },
32
32
  'planning.workspace_access': {
33
- enabled: false,
33
+ enabledByEnvironment: { performance: false, staging: false, production: false },
34
34
  description: 'Planning workspace readiness gate.',
35
35
  owner: 'taskforce',
36
36
  removalMilestone: 'Planning workspace GA'
@@ -1,17 +1,18 @@
1
- export type RuntimeMode = 'local' | 'cloud';
1
+ import type { TaskforceCloudEnvironment } from '../config/cloudEnvironment.js';
2
+ import { APP_GATE_DEFINITIONS as APP_GATE_CONFIG } from './appGateDefinitions.js';
2
3
  export declare const ANNOTATED_ATTACHMENTS_WORKSPACE_FEATURE_KEY: "annotated_attachments.workspace_access";
3
4
  export declare const DOCUMENT_WORKSPACE_FEATURE_KEY: "documents.workspace_access";
4
5
  export declare const WORKFLOW_MANAGER_WORKSPACE_FEATURE_KEY: "workflow_manager.workspace_access";
5
6
  export declare const TASKFORCE_AGENTS_WORKSPACE_FEATURE_KEY: "taskforce_agents.workspace_access";
6
7
  export declare const AI_PROFILES_WORKSPACE_FEATURE_KEY: "ai_profiles.workspace_access";
7
8
  export declare const PLANNING_WORKSPACE_FEATURE_KEY: "planning.workspace_access";
8
- export type AppGateKey = typeof ANNOTATED_ATTACHMENTS_WORKSPACE_FEATURE_KEY | typeof DOCUMENT_WORKSPACE_FEATURE_KEY | typeof WORKFLOW_MANAGER_WORKSPACE_FEATURE_KEY | typeof TASKFORCE_AGENTS_WORKSPACE_FEATURE_KEY | typeof AI_PROFILES_WORKSPACE_FEATURE_KEY | typeof PLANNING_WORKSPACE_FEATURE_KEY;
9
+ export type AppGateKey = keyof typeof APP_GATE_CONFIG;
9
10
  export interface AppGateDefinition {
10
- key: AppGateKey;
11
- enabled: boolean;
12
- description: string;
13
- owner: string;
14
- removalMilestone: string;
11
+ readonly key: AppGateKey;
12
+ readonly enabledByEnvironment: Readonly<Record<TaskforceCloudEnvironment, boolean>>;
13
+ readonly description: string;
14
+ readonly owner: string;
15
+ readonly removalMilestone: string;
15
16
  }
16
17
  export interface ResolvedFeatureAccess {
17
18
  featureKey: string;
@@ -20,11 +21,9 @@ export interface ResolvedFeatureAccess {
20
21
  code: string;
21
22
  }
22
23
  export type ResolvedFeatureAccessMap = Record<string, ResolvedFeatureAccess>;
23
- export declare const APP_GATE_DEFINITIONS: Record<AppGateKey, AppGateDefinition>;
24
+ export declare const APP_GATE_DEFINITIONS: Readonly<Record<AppGateKey, AppGateDefinition>>;
24
25
  export declare function listAppGateDefinitions(): AppGateDefinition[];
25
26
  export declare function getAppGateDefinition(featureKey: string): AppGateDefinition | null;
26
- export declare function resolveAppGateAccess(featureKey: string): ResolvedFeatureAccess;
27
- export declare function resolveFeatureAccess(input: {
28
- featureKey: string;
29
- runtimeMode: RuntimeMode;
30
- }): ResolvedFeatureAccess;
27
+ export declare function resolveAppGateAccess(featureKey: string, environment: TaskforceCloudEnvironment): ResolvedFeatureAccess;
28
+ export declare function resolveAppGateAccessMap(environment: TaskforceCloudEnvironment): ResolvedFeatureAccessMap;
29
+ export declare function isResolvedFeatureAccessMap(value: unknown): value is ResolvedFeatureAccessMap;
@@ -5,16 +5,17 @@ export const WORKFLOW_MANAGER_WORKSPACE_FEATURE_KEY = 'workflow_manager.workspac
5
5
  export const TASKFORCE_AGENTS_WORKSPACE_FEATURE_KEY = 'taskforce_agents.workspace_access';
6
6
  export const AI_PROFILES_WORKSPACE_FEATURE_KEY = 'ai_profiles.workspace_access';
7
7
  export const PLANNING_WORKSPACE_FEATURE_KEY = 'planning.workspace_access';
8
- export const APP_GATE_DEFINITIONS = Object.entries(APP_GATE_CONFIG).reduce((acc, [key, definition]) => {
9
- acc[key] = {
8
+ const appGateDefinitions = Object.fromEntries(Object.entries(APP_GATE_CONFIG).map(([key, definition]) => [
9
+ key,
10
+ Object.freeze({
10
11
  key: key,
11
- enabled: Boolean(definition.enabled),
12
- description: String(definition.description || ''),
13
- owner: String(definition.owner || ''),
14
- removalMilestone: String(definition.removalMilestone || '')
15
- };
16
- return acc;
17
- }, {});
12
+ enabledByEnvironment: Object.freeze({ ...definition.enabledByEnvironment }),
13
+ description: definition.description,
14
+ owner: definition.owner,
15
+ removalMilestone: definition.removalMilestone,
16
+ }),
17
+ ]));
18
+ export const APP_GATE_DEFINITIONS = Object.freeze(appGateDefinitions);
18
19
  export function listAppGateDefinitions() {
19
20
  return Object.values(APP_GATE_DEFINITIONS);
20
21
  }
@@ -24,7 +25,7 @@ export function getAppGateDefinition(featureKey) {
24
25
  return null;
25
26
  return APP_GATE_DEFINITIONS[normalizedKey] || null;
26
27
  }
27
- export function resolveAppGateAccess(featureKey) {
28
+ export function resolveAppGateAccess(featureKey, environment) {
28
29
  const gate = getAppGateDefinition(featureKey);
29
30
  if (!gate) {
30
31
  return {
@@ -34,7 +35,7 @@ export function resolveAppGateAccess(featureKey) {
34
35
  code: 'OK'
35
36
  };
36
37
  }
37
- if (!gate.enabled) {
38
+ if (!gate.enabledByEnvironment[environment]) {
38
39
  return {
39
40
  featureKey,
40
41
  allowed: false,
@@ -49,6 +50,21 @@ export function resolveAppGateAccess(featureKey) {
49
50
  code: 'OK'
50
51
  };
51
52
  }
52
- export function resolveFeatureAccess(input) {
53
- return resolveAppGateAccess(input.featureKey);
53
+ export function resolveAppGateAccessMap(environment) {
54
+ return Object.fromEntries(listAppGateDefinitions().map(({ key }) => [key, resolveAppGateAccess(key, environment)]));
55
+ }
56
+ export function isResolvedFeatureAccessMap(value) {
57
+ if (!value || typeof value !== 'object' || Array.isArray(value))
58
+ return false;
59
+ const candidate = value;
60
+ return listAppGateDefinitions().every(({ key }) => {
61
+ const access = candidate[key];
62
+ if (!access || typeof access !== 'object' || Array.isArray(access))
63
+ return false;
64
+ const resolved = access;
65
+ return resolved.featureKey === key
66
+ && typeof resolved.allowed === 'boolean'
67
+ && (resolved.source === 'app_gate' || resolved.source === 'cloud_entitlement' || resolved.source === 'none')
68
+ && typeof resolved.code === 'string';
69
+ });
54
70
  }
@@ -0,0 +1,8 @@
1
+ import type { TaskforceCloudEnvironment } from '../config/cloudEnvironment.js';
2
+ import { type ResolvedFeatureAccess, type ResolvedFeatureAccessMap } from './appGates.js';
3
+ export interface NodeAppGateResolutionOptions {
4
+ onWarning?: (message: string) => void;
5
+ }
6
+ export declare function resolveNodeAppGateEnvironment(env?: NodeJS.ProcessEnv, options?: NodeAppGateResolutionOptions): TaskforceCloudEnvironment;
7
+ export declare function resolveNodeAppGateAccess(featureKey: string, env?: NodeJS.ProcessEnv, options?: NodeAppGateResolutionOptions): ResolvedFeatureAccess;
8
+ export declare function resolveNodeAppGateAccessMap(env?: NodeJS.ProcessEnv, options?: NodeAppGateResolutionOptions): ResolvedFeatureAccessMap;
@@ -0,0 +1,27 @@
1
+ import { resolveDeploymentConfig } from '../config/deployment.js';
2
+ import { resolveAppGateAccess, resolveAppGateAccessMap, } from './appGates.js';
3
+ const warnedEnvironmentSignatures = new WeakMap();
4
+ export function resolveNodeAppGateEnvironment(env = process.env, options = {}) {
5
+ const deployment = resolveDeploymentConfig(env);
6
+ const warnings = [...deployment.warnings];
7
+ if (!deployment.cloudEnvironment) {
8
+ warnings.push('TASKFORCE_CLOUD_ENVIRONMENT could not be resolved; using the production App Gate profile.');
9
+ }
10
+ const warningSignature = warnings.join('\n');
11
+ if (warnings.length === 0) {
12
+ warnedEnvironmentSignatures.delete(env);
13
+ }
14
+ else if (warnedEnvironmentSignatures.get(env) !== warningSignature) {
15
+ const onWarning = options.onWarning || ((message) => console.warn(`[Taskforce App Gates] ${message}`));
16
+ for (const warning of warnings)
17
+ onWarning(warning);
18
+ warnedEnvironmentSignatures.set(env, warningSignature);
19
+ }
20
+ return deployment.cloudEnvironment || 'production';
21
+ }
22
+ export function resolveNodeAppGateAccess(featureKey, env = process.env, options = {}) {
23
+ return resolveAppGateAccess(featureKey, resolveNodeAppGateEnvironment(env, options));
24
+ }
25
+ export function resolveNodeAppGateAccessMap(env = process.env, options = {}) {
26
+ return resolveAppGateAccessMap(resolveNodeAppGateEnvironment(env, options));
27
+ }
@@ -18,7 +18,7 @@ export interface CloudCollectionReadResponse {
18
18
  details: Record<string, number>;
19
19
  };
20
20
  }
21
- type CloudCollectionReadCore = Pick<TaskforceCore, 'resolveUserAccess' | 'getSystemRole' | 'getAccountAccessStatus' | 'listTasks' | 'listArchive' | 'listDeletedTasksReadOnly' | 'listPlanningBootstrap'>;
21
+ type CloudCollectionReadCore = Pick<TaskforceCore, 'resolveUserAccess' | 'getSystemRole' | 'getAccountAccessStatus' | 'listActiveTaskSummaries' | 'listArchiveSummaries' | 'listDeletedTasksReadOnly' | 'listPlanningBootstrap'>;
22
22
  export declare function resolveCloudCollectionReadOperation(method: string | undefined, pathname: string): CloudCollectionReadOperation | null;
23
23
  export declare function executeCloudCollectionRead(core: CloudCollectionReadCore, request: CloudCollectionReadRequest): CloudCollectionReadResponse;
24
24
  export declare function cloudCollectionReadRoute(operation: CloudCollectionReadOperation): string;
@@ -63,9 +63,9 @@ export function executeCloudCollectionRead(core, request) {
63
63
  let data;
64
64
  const planningDiagnostics = {};
65
65
  if (request.operation === 'tasks')
66
- data = core.listTasks(workspaceId);
66
+ data = core.listActiveTaskSummaries(workspaceId);
67
67
  else if (request.operation === 'archive')
68
- data = core.listArchive(workspaceId);
68
+ data = core.listArchiveSummaries(workspaceId);
69
69
  else if (request.operation === 'deleted')
70
70
  data = core.listDeletedTasksReadOnly(workspaceId);
71
71
  else
@@ -8,6 +8,7 @@ import * as http from 'http';
8
8
  import { WebSocketServer } from 'ws';
9
9
  export { resolveAuthorizedWorkspaceAccess, resolveDisabledAccessError, isWorkspaceAccessRecoveryRoute, } from './authorizedWorkspaceAccess.js';
10
10
  import type { LocalServiceCloudTarget } from '../config/localServiceCloudTarget.js';
11
+ import type { LocalServiceRuntimeContract } from '../config/localServiceRuntimeContract.js';
11
12
  import type { LocalSyncCoordinatorHost } from '../sync/coordinator/localSyncCoordinatorHost.js';
12
13
  import type { LocalSyncProcessLock } from '../sync/coordinator/localSyncProcessLock.js';
13
14
  import type { LocalDataOwnerPermit } from './localDataOwnerPermit.js';
@@ -26,6 +27,7 @@ export interface StandaloneServerOptions {
26
27
  bootstrapCapability: string;
27
28
  ownershipKey: string;
28
29
  cloudTarget: LocalServiceCloudTarget;
30
+ runtimeContract: LocalServiceRuntimeContract;
29
31
  };
30
32
  }
31
33
  export interface TaskforceStandaloneServer extends http.Server {
@@ -46,6 +48,7 @@ export declare const TASKFORCE_PROXY_ORIGIN_PROTO_HEADER = "x-taskforce-origin-p
46
48
  export declare const TASKFORCE_PROXY_ORIGIN_BASE_URL_HEADER = "x-taskforce-origin-base-url";
47
49
  export declare const TASKFORCE_PROXY_ORIGIN_RUNTIME_HEADER = "x-taskforce-origin-runtime";
48
50
  export declare const TASKFORCE_PROXY_CLOUD_ENVIRONMENT_HEADER = "x-taskforce-cloud-environment";
51
+ export declare function sanitizeQaRunIdHeader(raw: unknown): string;
49
52
  export declare function shouldProxyCloudPath(pathname: string): boolean;
50
53
  export declare function shouldProxyCloudRequest(url: Pick<URL, 'pathname' | 'searchParams'>, env?: NodeJS.ProcessEnv): boolean;
51
54
  export declare function resolveCloudProxyUpstreamBaseUrl(req: http.IncomingMessage, fallbackBaseUrl: string): string;