@copado/agentia-cli 1.0.0-beta.1 → 1.0.0-beta.2

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 (39) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/README.md +499 -323
  3. package/dist/commands/cicd/cloud/commit.js +252 -0
  4. package/dist/commands/cicd/cloud/promote.js +139 -0
  5. package/dist/commands/cicd/health-check.js +77 -0
  6. package/dist/commands/cicd/work/commit.js +10 -324
  7. package/dist/commands/cicd/work/environment-sync.js +120 -0
  8. package/dist/commands/cicd/work/get.js +25 -4
  9. package/dist/commands/cicd/work/promote.js +93 -97
  10. package/dist/commands/cicd/work/set.js +4 -2
  11. package/dist/commands/cicd/work/submit.js +7 -0
  12. package/dist/lib/defaults-store.js +2 -1
  13. package/dist/lib/git-sizer.js +5 -0
  14. package/dist/lib/git-worktree.js +16 -1
  15. package/dist/lib/health-check.js +3 -0
  16. package/dist/lib/mcp/command-id.js +1 -0
  17. package/dist/lib/mcp/health-check-tools.js +16 -0
  18. package/dist/lib/mcp/server.js +2 -1
  19. package/dist/lib/mcp/tool-annotations.js +265 -0
  20. package/dist/lib/mcp/tools.js +3 -0
  21. package/dist/lib/mcp/work-tools.js +96 -78
  22. package/dist/lib/metadata-pathspecs.js +4 -0
  23. package/dist/lib/metadataRegistry.json +5427 -0
  24. package/dist/lib/promotion-types.js +4 -1
  25. package/dist/lib/runtime.js +1 -1
  26. package/dist/lib/work-environment-sync-errors.js +4 -0
  27. package/dist/lib/work-environment-sync-ready.js +18 -0
  28. package/dist/lib/work-environment-sync.js +42 -0
  29. package/dist/lib/work-promote-deploy.js +13 -0
  30. package/dist/lib/work-promote-errors.js +5 -0
  31. package/dist/lib/work-promote.js +12 -0
  32. package/dist/lib/work-set-selection.js +2 -1
  33. package/dist/lib/work-submit-ahead-behind.js +8 -0
  34. package/dist/lib/work-types.js +2 -1
  35. package/oclif.manifest.json +1118 -675
  36. package/package.json +5 -2
  37. package/templates/skills/agentia-cicd/SKILL.md +2 -2
  38. package/templates/skills/agentia-cicd/references/promotions.md +8 -8
  39. package/templates/skills/agentia-cicd/references/work.md +16 -14
@@ -0,0 +1,265 @@
1
+ /**
2
+ * Standard MCP tool annotations for every Agentia MCP tool.
3
+ *
4
+ * Annotations are hints for MCP clients (auto-approve, confirmation prompts); they are not
5
+ * enforcement. Gateway authorization still applies. Only a few tools enforce their own `confirm` flag.
6
+ *
7
+ * Every tool is classified here explicitly. `test/lib/mcp/tool-annotations.test.ts` fails when a
8
+ * registered tool is missing from the table, so new tools must be classified when they are added.
9
+ */
10
+ /** MCP spec: destructive means the tool may overwrite or remove existing state, not only add. */
11
+ const CLASS_ANNOTATIONS = {
12
+ // Runs or triggers something with side effects; repeating it repeats the effect.
13
+ action: { destructiveHint: true, idempotentHint: false, readOnlyHint: false },
14
+ // Read-only but not repeatable (model output varies).
15
+ ask: { destructiveHint: false, idempotentHint: false, readOnlyHint: true },
16
+ // Purely additive; repeating it creates another record.
17
+ create: { destructiveHint: false, idempotentHint: false, readOnlyHint: false },
18
+ // Removes or resets state; repeating it has no further effect.
19
+ delete: { destructiveHint: true, idempotentHint: true, readOnlyHint: false },
20
+ read: { destructiveHint: false, idempotentHint: true, readOnlyHint: true },
21
+ // Overwrites existing state with the same result when repeated.
22
+ update: { destructiveHint: true, idempotentHint: true, readOnlyHint: false },
23
+ };
24
+ /** Triggers side effects (commit, promote, run, kill, ...). */
25
+ const ACTION_TOOLS = [
26
+ 'agentia_cloud_commit',
27
+ 'agentia_cloud_promote',
28
+ 'agentia_data_sync_apply',
29
+ 'agentia_function_run',
30
+ 'agentia_function_run_local',
31
+ 'agentia_job_kill',
32
+ 'agentia_job_pause',
33
+ 'agentia_job_resume',
34
+ 'agentia_job_run',
35
+ 'agentia_metadata_refresh_deleted',
36
+ 'agentia_metadata_refresh_run',
37
+ 'agentia_promotion_run',
38
+ 'agentia_testing_build_abort',
39
+ 'agentia_testing_build_run',
40
+ 'agentia_testing_job_run',
41
+ 'agentia_testing_live_continue',
42
+ 'agentia_testing_live_execute',
43
+ 'agentia_testing_live_interrupt',
44
+ 'agentia_testing_live_stop',
45
+ 'agentia_testing_run',
46
+ 'agentia_work_commit',
47
+ 'agentia_work_done',
48
+ 'agentia_work_publish',
49
+ 'agentia_work_push',
50
+ 'agentia_work_submit',
51
+ 'agentia_work_test',
52
+ 'agentia_work_test_apex',
53
+ ];
54
+ /** Read-only, non-repeatable model calls. */
55
+ const ASK_TOOLS = [
56
+ 'agentia_ai_ask',
57
+ ];
58
+ /** Additive writes. */
59
+ const CREATE_TOOLS = [
60
+ 'agentia_credential_create',
61
+ 'agentia_data_commit_create',
62
+ 'agentia_data_filter_add',
63
+ 'agentia_data_formula_create',
64
+ 'agentia_data_template_convert_old',
65
+ 'agentia_data_template_create',
66
+ 'agentia_environment_create',
67
+ 'agentia_pipeline_connection_create',
68
+ 'agentia_pipeline_create',
69
+ 'agentia_pipeline_stage_connection_create',
70
+ 'agentia_project_create',
71
+ 'agentia_repository_create',
72
+ 'agentia_stage_create',
73
+ 'agentia_testing_create',
74
+ 'agentia_testing_data_table_create',
75
+ 'agentia_testing_job_create',
76
+ 'agentia_testing_job_download',
77
+ 'agentia_testing_live_start',
78
+ 'agentia_testing_project_create',
79
+ 'agentia_testing_robot_create',
80
+ 'agentia_testing_user_parameter_create',
81
+ 'agentia_testing_variable_create',
82
+ 'agentia_work_create',
83
+ 'agentia_work_deployment_step_create',
84
+ ];
85
+ /** Removes or resets state. */
86
+ const DELETE_TOOLS = [
87
+ 'agentia_data_filter_delete',
88
+ 'agentia_data_template_delete',
89
+ 'agentia_function_delete',
90
+ 'agentia_pipeline_connection_delete',
91
+ 'agentia_pipeline_stage_connection_delete',
92
+ 'agentia_project_delete',
93
+ 'agentia_repository_delete',
94
+ 'agentia_repository_reset',
95
+ 'agentia_stage_delete',
96
+ 'agentia_testing_data_table_delete',
97
+ 'agentia_testing_job_delete',
98
+ 'agentia_testing_job_schedule_remove',
99
+ 'agentia_testing_project_delete',
100
+ 'agentia_testing_robot_delete',
101
+ 'agentia_testing_user_parameter_delete',
102
+ 'agentia_testing_variable_delete',
103
+ 'agentia_work_delete',
104
+ 'agentia_work_deployment_step_delete',
105
+ ];
106
+ /** Read-only lookups. */
107
+ const READ_TOOLS = [
108
+ 'agentia_auth_get',
109
+ 'agentia_credential_list',
110
+ 'agentia_data_commit_list',
111
+ 'agentia_data_dataset_file_content',
112
+ 'agentia_data_dataset_file_list',
113
+ 'agentia_data_filter_list',
114
+ 'agentia_data_formula_list',
115
+ 'agentia_data_records_match',
116
+ 'agentia_data_records_search',
117
+ 'agentia_data_sobject_fields',
118
+ 'agentia_data_sobject_relationships',
119
+ 'agentia_data_sync_preview_updates',
120
+ 'agentia_data_template_get',
121
+ 'agentia_data_template_get_detail',
122
+ 'agentia_data_template_list',
123
+ 'agentia_environment_auth_status',
124
+ 'agentia_environment_get',
125
+ 'agentia_environment_list',
126
+ 'agentia_function_defaults',
127
+ 'agentia_function_get',
128
+ 'agentia_function_list',
129
+ 'agentia_function_result_get',
130
+ 'agentia_function_result_log_get',
131
+ 'agentia_job_get',
132
+ 'agentia_job_list',
133
+ 'agentia_job_log_get',
134
+ 'agentia_job_result_file_get',
135
+ 'agentia_job_result_file_list',
136
+ 'agentia_metadata_content_compare',
137
+ 'agentia_metadata_content_get',
138
+ 'agentia_metadata_dependency_list',
139
+ 'agentia_metadata_index_compare',
140
+ 'agentia_metadata_list',
141
+ 'agentia_metadata_refresh_status',
142
+ 'agentia_navigation_resolve',
143
+ 'agentia_pipeline_connection_list',
144
+ 'agentia_pipeline_get',
145
+ 'agentia_pipeline_list',
146
+ 'agentia_pipeline_stage_connection_list',
147
+ 'agentia_project_default_get',
148
+ 'agentia_project_get',
149
+ 'agentia_project_list',
150
+ 'agentia_promotion_conflict_get',
151
+ 'agentia_promotion_conflict_list',
152
+ 'agentia_promotion_get',
153
+ 'agentia_promotion_list',
154
+ 'agentia_repository_get',
155
+ 'agentia_repository_list',
156
+ 'agentia_repository_validate',
157
+ 'agentia_stage_get',
158
+ 'agentia_stage_list',
159
+ 'agentia_testing_build_get',
160
+ 'agentia_testing_build_latest',
161
+ 'agentia_testing_build_list',
162
+ 'agentia_testing_build_logs',
163
+ 'agentia_testing_build_search',
164
+ 'agentia_testing_data_table_get',
165
+ 'agentia_testing_data_table_list',
166
+ 'agentia_testing_job_files',
167
+ 'agentia_testing_job_get',
168
+ 'agentia_testing_job_list',
169
+ 'agentia_testing_job_refs',
170
+ 'agentia_testing_job_schedule_get',
171
+ 'agentia_testing_live_history',
172
+ 'agentia_testing_live_inspect',
173
+ 'agentia_testing_live_reports',
174
+ 'agentia_testing_live_screenshot',
175
+ 'agentia_testing_live_status',
176
+ 'agentia_testing_logs',
177
+ 'agentia_testing_project_get',
178
+ 'agentia_testing_project_list',
179
+ 'agentia_testing_project_permission_get',
180
+ 'agentia_testing_project_permission_list',
181
+ 'agentia_testing_robot_get',
182
+ 'agentia_testing_robot_list',
183
+ 'agentia_testing_status',
184
+ 'agentia_testing_user_parameter_get',
185
+ 'agentia_testing_user_parameter_list',
186
+ 'agentia_testing_variable_get',
187
+ 'agentia_testing_variable_list',
188
+ 'agentia_user_get',
189
+ 'agentia_work_deployment_step_list',
190
+ 'agentia_work_deployment_step_salesforce_flows',
191
+ 'agentia_work_deployment_step_types',
192
+ 'agentia_work_get',
193
+ 'agentia_work_list',
194
+ 'agentia_work_status',
195
+ ];
196
+ /** Overwrites existing state. */
197
+ const UPDATE_TOOLS = [
198
+ 'agentia_auth_set',
199
+ 'agentia_credential_update',
200
+ 'agentia_data_filter_update',
201
+ 'agentia_data_formula_update',
202
+ 'agentia_data_template_save_detail',
203
+ 'agentia_environment_update',
204
+ 'agentia_function_upsert',
205
+ 'agentia_pipeline_connection_update',
206
+ 'agentia_pipeline_stage_connection_update',
207
+ 'agentia_pipeline_update',
208
+ 'agentia_project_default_set',
209
+ 'agentia_project_default_unset',
210
+ 'agentia_project_update',
211
+ 'agentia_promotion_conflict_resolve',
212
+ 'agentia_promotion_conflict_unresolve',
213
+ 'agentia_promotion_job_step_update',
214
+ 'agentia_repository_update',
215
+ 'agentia_stage_update',
216
+ 'agentia_testing_data_table_update',
217
+ 'agentia_testing_job_schedule_set',
218
+ 'agentia_testing_job_update',
219
+ 'agentia_testing_job_upload',
220
+ 'agentia_testing_live_set_options',
221
+ 'agentia_testing_project_permission_set',
222
+ 'agentia_testing_project_permission_update',
223
+ 'agentia_testing_project_update',
224
+ 'agentia_testing_robot_update',
225
+ 'agentia_testing_update',
226
+ 'agentia_testing_user_parameter_update',
227
+ 'agentia_testing_variable_update',
228
+ 'agentia_work_deployment_step_reorder',
229
+ 'agentia_work_deployment_step_update',
230
+ 'agentia_work_set',
231
+ 'agentia_work_update',
232
+ ];
233
+ /** Tools that only touch local state (keychain/config), not the gateway or Salesforce. */
234
+ const LOCAL_ONLY_TOOLS = new Set([
235
+ 'agentia_auth_get',
236
+ 'agentia_project_default_get',
237
+ 'agentia_project_default_set',
238
+ 'agentia_project_default_unset',
239
+ ]);
240
+ const TOOL_CLASSES = new Map([
241
+ ...ACTION_TOOLS.map((name) => [name, 'action']),
242
+ ...ASK_TOOLS.map((name) => [name, 'ask']),
243
+ ...CREATE_TOOLS.map((name) => [name, 'create']),
244
+ ...DELETE_TOOLS.map((name) => [name, 'delete']),
245
+ ...READ_TOOLS.map((name) => [name, 'read']),
246
+ ...UPDATE_TOOLS.map((name) => [name, 'update']),
247
+ ]);
248
+ export function listClassifiedToolNames() {
249
+ return [...TOOL_CLASSES.keys()];
250
+ }
251
+ export function getToolAnnotations(toolName) {
252
+ const toolClass = TOOL_CLASSES.get(toolName);
253
+ if (toolClass === undefined)
254
+ return undefined;
255
+ return { ...CLASS_ANNOTATIONS[toolClass], openWorldHint: !LOCAL_ONLY_TOOLS.has(toolName) };
256
+ }
257
+ /** Returns the tool config with default annotations; annotations already set on the tool win. */
258
+ export function withToolAnnotations(toolName, config) {
259
+ const defaults = getToolAnnotations(toolName);
260
+ if (defaults === undefined || typeof config !== 'object' || config === null)
261
+ return config;
262
+ const existing = config.annotations;
263
+ return { ...config, annotations: { ...defaults, ...existing } };
264
+ }
265
+ //# sourceMappingURL=tool-annotations.js.map
@@ -47,6 +47,7 @@ import { workStatusEndpoint } from '../work-types.js';
47
47
  import { agentiaMcpAiToolHandlers, registerAgentiaMcpAiTools } from './ai-tools.js';
48
48
  import { agentiaMcpDataToolHandlers, registerAgentiaMcpDataTools } from './data-tools.js';
49
49
  import { agentiaMcpDeploymentStepToolHandlers, registerAgentiaMcpDeploymentStepTools } from './deployment-step-tools.js';
50
+ import { agentiaMcpHealthCheckToolHandlers, registerAgentiaMcpHealthCheckTools } from './health-check-tools.js';
50
51
  import { safelyHandleTool, wrapMcpToolHandlers } from './result.js';
51
52
  import { agentiaMcpTestingToolHandlers, registerAgentiaMcpTestingTools } from './testing-tools.js';
52
53
  import { agentiaMcpWorkToolHandlers, registerAgentiaMcpWorkTools } from './work-tools.js';
@@ -1206,6 +1207,7 @@ export const agentiaMcpToolHandlers = wrapMcpToolHandlers({
1206
1207
  ...agentiaMcpAiToolHandlers,
1207
1208
  ...agentiaMcpDataToolHandlers,
1208
1209
  ...agentiaMcpDeploymentStepToolHandlers,
1210
+ ...agentiaMcpHealthCheckToolHandlers,
1209
1211
  authGet,
1210
1212
  authSet,
1211
1213
  credentialCreate,
@@ -1366,6 +1368,7 @@ export function registerAgentiaMcpTools(server) {
1366
1368
  registerAgentiaMcpAiTools(server);
1367
1369
  registerAgentiaMcpDataTools(server);
1368
1370
  registerAgentiaMcpDeploymentStepTools(server);
1371
+ registerAgentiaMcpHealthCheckTools(server);
1369
1372
  registerAgentiaMcpTestingTools(server);
1370
1373
  server.registerTool('agentia_environment_list', {
1371
1374
  description: 'List Copado environments via the CICD gateway.',
@@ -21,7 +21,8 @@ import { performWorkLocalCommit } from '../work-local-commit.js';
21
21
  import { reportLocalQualityGatesFailure, reportLocalQualityGatesOutcome, } from '../work-local-run-tests.js';
22
22
  import { capturingWorkPushHooks, performWorkPush, resolveActiveFeatureWorkItem, resolveWorkPushContext, resolveWorkPushNeed, } from '../work-push.js';
23
23
  import { performWorkSetNone } from '../work-set-none.js';
24
- import { isWorkSetWarning, parseWorkSetSelection, toWorkSetWarningResult } from '../work-set-selection.js';
24
+ import { isWorkSetWarning, parseWorkSetSelection, toWorkSetWarningResult, writeWorkSetWarningSelection, } from '../work-set-selection.js';
25
+ import { reportSubmitUserStoriesAheadBehind } from '../work-submit-ahead-behind.js';
25
26
  import { waitForPendingCommitJobIfNeeded } from '../work-submit-wait.js';
26
27
  import { applySourceCredentialEnvironmentRule, featureBranchName, normalizeUserStoriesListPage, workCreateEndpoint, workDoneEndpoint, workEndpoint, workListEndpoint, workSetEndpoint, workSubmitEndpoint, } from '../work-types.js';
27
28
  import { safelyHandleTool } from './result.js';
@@ -213,6 +214,7 @@ async function workSet(args) {
213
214
  method: 'POST',
214
215
  });
215
216
  if (isWorkSetWarning(setResponse)) {
217
+ await writeWorkSetWarningSelection(setResponse);
216
218
  return toWorkSetWarningResult(setResponse);
217
219
  }
218
220
  const selection = parseWorkSetSelection(setResponse, args.baseBranch);
@@ -262,6 +264,12 @@ async function workPublish(args = {}) {
262
264
  async function workPush(args = {}) {
263
265
  return workPublish(args);
264
266
  }
267
+ async function reportSubmitAheadBehindForMcp(workItem) {
268
+ return reportSubmitUserStoriesAheadBehind(workItem, {
269
+ log: (message) => capturingWorkPushHooks.log(message),
270
+ warn: (message) => capturingWorkPushHooks.log(`Warning: ${message}`),
271
+ });
272
+ }
265
273
  async function promoteWorkItemDone(args = {}) {
266
274
  return withCapturedCommandOutput(async () => {
267
275
  const { branch, workItem } = await requireFeatureBranchWorkItem();
@@ -276,6 +284,7 @@ async function promoteWorkItemDone(args = {}) {
276
284
  skipNestedMetadataDetection: args.skipNestedMetadataDetection,
277
285
  });
278
286
  }
287
+ const userStoriesAheadBehind = await reportSubmitAheadBehindForMcp(workItem);
279
288
  await waitForPendingCommitJobIfNeeded({
280
289
  hooks: capturingWorkPushHooks,
281
290
  workItem,
@@ -294,6 +303,7 @@ async function promoteWorkItemDone(args = {}) {
294
303
  done,
295
304
  push: pushResult,
296
305
  pushed: needsPush,
306
+ ...(userStoriesAheadBehind === undefined ? {} : { userStoriesAheadBehind }),
297
307
  workItem,
298
308
  };
299
309
  }, MCP_STDIO_CAPTURE_OPTIONS);
@@ -341,6 +351,7 @@ async function workSubmit(args = {}) {
341
351
  skipNestedMetadataDetection: args.skipNestedMetadataDetection,
342
352
  });
343
353
  }
354
+ const userStoriesAheadBehind = await reportSubmitAheadBehindForMcp(workItem);
344
355
  await waitForPendingCommitJobIfNeeded({
345
356
  hooks: capturingWorkPushHooks,
346
357
  workItem,
@@ -359,6 +370,7 @@ async function workSubmit(args = {}) {
359
370
  pushed: needsPush,
360
371
  qualityGates,
361
372
  submit,
373
+ ...(userStoriesAheadBehind === undefined ? {} : { userStoriesAheadBehind }),
362
374
  workItem,
363
375
  };
364
376
  }, MCP_STDIO_CAPTURE_OPTIONS);
@@ -428,7 +440,7 @@ function providedCommitArgs(names, args) {
428
440
  async function workLocalCommit(args) {
429
441
  const cloudOnly = providedCommitArgs(CLOUD_ONLY_COMMIT_ARGS, args);
430
442
  if (cloudOnly.length > 0) {
431
- throw new Error(`Local commit does not support ${cloudOnly.join(', ')}. Pass cloud: true to use POST /release/commit.`);
443
+ throw new Error(`Local commit does not support ${cloudOnly.join(', ')}. Use agentia_cloud_commit for POST /release/commit.`);
432
444
  }
433
445
  return performWorkLocalCommit({
434
446
  all: args.all === true,
@@ -469,17 +481,13 @@ function buildMcpWorkCommitInput(args) {
469
481
  recreateFeatureBranch: args.recreateFeatureBranch,
470
482
  };
471
483
  }
472
- async function workCommit(args = {}) {
473
- // Local git commit is not exposed. Implementation remains in workLocalCommit.
474
- if (args.cloud !== true) {
475
- throw new Error('This tool creates Copado cloud metadata commits. For local Git work, use git commit then agentia_work_publish. Pass cloud: true for a Copado cloud commit. Permission and full-metadata selections belong on agentia_work_publish.');
476
- }
484
+ async function cloudCommit(args = {}) {
477
485
  if (args.local === true) {
478
- throw new Error('local and cloud are mutually exclusive.');
486
+ throw new Error('This tool creates Copado cloud metadata commits. For local Git work, use git commit then agentia_work_publish.');
479
487
  }
480
488
  const localOnly = providedCommitArgs(LOCAL_ONLY_COMMIT_ARGS, args);
481
489
  if (localOnly.length > 0) {
482
- throw new Error(`Cloud commit does not support ${localOnly.join(', ')}.`);
490
+ throw new Error(`Cloud commit does not support ${localOnly.join(', ')}. Use agentia_work_publish for ${localOnly.join(', ')}.`);
483
491
  }
484
492
  if (args.changes !== undefined && hasMcpSimpleCommitArgs(args)) {
485
493
  throw new Error('Use changes or simple metadata fields, not both.');
@@ -511,10 +519,11 @@ async function workCommit(args = {}) {
511
519
  });
512
520
  }
513
521
  export { workLocalCommit as retainedWorkLocalCommit };
514
- async function workPromote(args = {}) {
515
- if (args.cloud !== true) {
516
- throw new Error('Only cloud=true is supported for work promotion.');
517
- }
522
+ /** Compatibility alias of agentia_cloud_commit. Prefer agentia_cloud_commit. */
523
+ async function workCommit(args = {}) {
524
+ return cloudCommit(args);
525
+ }
526
+ async function cloudPromote(args = {}) {
518
527
  if (args.recreatePromotionBranch === true && args.confirmRecreate !== true) {
519
528
  throw new Error('recreatePromotionBranch requires confirmRecreate=true.');
520
529
  }
@@ -550,13 +559,14 @@ async function workDone(args = {}) {
550
559
  });
551
560
  }
552
561
  export const agentiaMcpWorkToolHandlers = {
562
+ cloudCommit,
563
+ cloudPromote,
553
564
  workCommit,
554
565
  workCreate,
555
566
  workDelete,
556
567
  workDone,
557
568
  workGet,
558
569
  workList,
559
- workPromote,
560
570
  workPublish,
561
571
  workPush,
562
572
  workSet,
@@ -645,7 +655,7 @@ export function registerAgentiaMcpWorkTools(server) {
645
655
  title: 'Agentia Work Delete',
646
656
  }, (args) => safelyHandleTool(() => workDelete(args)));
647
657
  server.registerTool('agentia_work_set', {
648
- description: 'Set the active Copado work item and prepare a local feature/<user-story-name> branch. Requires a clean tracked working tree. Fetches the base branch from origin, fetches the feature branch when it exists on origin, then creates or checks out the feature branch from the remote feature when present, otherwise from the base. A gateway warning prints the message, skips git, and leaves local work context unchanged. After work/set returns, compares the Story source credential with the CICD project default: warns when the default or Story credential is missing, and warns without changing the Story when they differ (shows the current credential and environment; use work update to change it). With none=true, clears every last* key from config.user.json and checks out the previous lastBaseBranch when present, else main, else master, else stays put.',
658
+ description: 'Set the active Copado work item and prepare a local feature/<user-story-name> branch. Requires a clean tracked working tree. Fetches the base branch from origin, fetches the feature branch when it exists on origin, then creates or checks out the feature branch from the remote feature when present, otherwise from the base. A gateway warning prints the message, skips git, clears lastBaseBranch/lastDevOrgBranch/lastPullRequestBaseUrl, and records lastWorkItemId/lastWorkItem/lastWorkItemTitle from the returned work item. After work/set returns, compares the Story source credential with the CICD project default: warns when the default or Story credential is missing, and warns without changing the Story when they differ (shows the current credential and environment; use work update to change it). With none=true, clears every last* key from config.user.json and checks out the previous lastBaseBranch when present, else main, else master, else stays put.',
649
659
  inputSchema: {
650
660
  baseBranch: z
651
661
  .string()
@@ -680,79 +690,87 @@ export function registerAgentiaMcpWorkTools(server) {
680
690
  inputSchema: workPublishInputSchema,
681
691
  title: 'Agentia Work Push',
682
692
  }, (args) => safelyHandleTool(() => workPush(args || {})));
693
+ const cloudCommitInputSchema = {
694
+ action: z.enum(WORK_COMMIT_ACTIONS).optional().describe('Metadata action for simple input. Defaults to Add.'),
695
+ baseBranch: z.string().nullable().optional().describe('Optional base branch included in the commit request.'),
696
+ changes: z
697
+ .array(z.record(z.string(), z.unknown()))
698
+ .optional()
699
+ .describe(WORK_COMMIT_CHANGES_HELP),
700
+ commitId: z
701
+ .string()
702
+ .optional()
703
+ .describe('Existing local Git commit identifier to register when executeCommit is false.'),
704
+ dataTemplateSyncConfig: z
705
+ .array(z.unknown())
706
+ .optional()
707
+ .describe('Optional data-template synchronization configuration.'),
708
+ executeCommit: z.boolean().optional().describe('Execute the Copado commit job. Defaults to true.'),
709
+ id: z.string().optional().describe('User story Id. Defaults to the active work item from work set.'),
710
+ message: z
711
+ .string()
712
+ .optional()
713
+ .describe('Commit message. Required unless supplied in the request body.'),
714
+ metadataCategory: z.string().optional().describe(WORK_COMMIT_METADATA_CATEGORY_HELP),
715
+ metadataMessage: z.string().optional().describe('Optional per-change message for simple input.'),
716
+ metadataName: z.string().optional().describe('Metadata full name for simple input.'),
717
+ metadataRawJson: z.unknown().optional().describe('Optional raw metadata JSON value for simple input.'),
718
+ metadataType: z.string().optional().describe('Metadata type for simple input, for example ApexClass.'),
719
+ recreateFeatureBranch: z.boolean().optional().describe('Ask Copado to recreate the feature branch.'),
720
+ selection: z
721
+ .array(z.string())
722
+ .optional()
723
+ .describe('Selected files inside a bundle for SelectiveCommit simple input.'),
724
+ wait: z.boolean().optional().describe('Poll the commit job to a terminal status. Defaults to true.'),
725
+ waitTimeout: z.number().int().optional().describe('Maximum seconds to wait for the commit job. Defaults to 300.'),
726
+ };
727
+ const cloudPromoteInputSchema = {
728
+ confirmRecreate: z
729
+ .boolean()
730
+ .optional()
731
+ .describe('Required true when recreatePromotionBranch is true because MCP cannot prompt.'),
732
+ deploy: z.boolean().optional().describe('Use merge_and_deploy instead of promote-only merge.'),
733
+ deploymentStepIds: z
734
+ .array(z.string())
735
+ .optional()
736
+ .describe('Ordered deployment-step Salesforce IDs. Requires deploy=true.'),
737
+ id: z.string().optional().describe('User Story ID. Defaults to the active work item from work set.'),
738
+ ignoredMetadata: z.array(z.unknown()).optional().describe('Ignored metadata persisted before starting the run.'),
739
+ promotionId: z
740
+ .string()
741
+ .optional()
742
+ .describe('Explicit 18-character Promotion ID when the User Story belongs to multiple promotions.'),
743
+ recreatePromotionBranch: z.boolean().optional().describe('Recreate the promotion branch before execution.'),
744
+ wait: z.boolean().optional().describe('Poll all created executions to terminal status. Defaults to true.'),
745
+ waitTimeout: z
746
+ .number()
747
+ .int()
748
+ .optional()
749
+ .describe(`Maximum total wait in seconds. Defaults to ${PROMOTION_RUN_DEFAULT_TIMEOUT_SECONDS}.`),
750
+ };
751
+ server.registerTool('agentia_cloud_commit', {
752
+ description: 'Create a Copado cloud metadata commit. Preflights the user story, submits POST /release/commit, and optionally waits for the job. Use simple metadata fields for one change or changes for multi-change requests. For Salesforce metadata, set metadataCategory to SFDX (or c: "SFDX" on each changes entry); Copado SFDX deploy skips entries that omit that field. For local Git work, use git commit then agentia_work_publish; pass permissions and fullMetadata on agentia_work_publish.',
753
+ inputSchema: cloudCommitInputSchema,
754
+ title: 'Agentia Cloud Commit',
755
+ }, (args) => safelyHandleTool(() => cloudCommit(args || {})));
683
756
  server.registerTool('agentia_work_commit', {
684
- description: 'Create a Copado cloud metadata commit. Requires cloud: true. Preflights the user story, submits POST /release/commit, and optionally waits for the job. Use simple metadata fields for one change or changes for multi-change requests. For Salesforce metadata, set metadataCategory to SFDX (or c: "SFDX" on each changes entry); Copado SFDX deploy skips entries that omit that field. For local Git work, use git commit then agentia_work_publish; pass permissions and fullMetadata on agentia_work_publish.',
757
+ description: 'Compatibility alias of agentia_cloud_commit. Prefer agentia_cloud_commit. Create a Copado cloud metadata commit. cloud is ignored when present.',
685
758
  inputSchema: {
686
- action: z.enum(WORK_COMMIT_ACTIONS).optional().describe('Metadata action for simple input. Defaults to Add.'),
687
- baseBranch: z.string().nullable().optional().describe('Optional base branch included in the commit request.'),
688
- changes: z
689
- .array(z.record(z.string(), z.unknown()))
690
- .optional()
691
- .describe(WORK_COMMIT_CHANGES_HELP),
759
+ ...cloudCommitInputSchema,
692
760
  cloud: z
693
761
  .boolean()
694
762
  .optional()
695
- .describe('Required. Create a Copado cloud metadata commit (POST /release/commit). Local Git commits use git commit then agentia_work_publish.'),
696
- commitId: z
697
- .string()
698
- .optional()
699
- .describe('Existing local Git commit identifier to register when executeCommit is false.'),
700
- dataTemplateSyncConfig: z
701
- .array(z.unknown())
702
- .optional()
703
- .describe('Optional data-template synchronization configuration.'),
704
- executeCommit: z.boolean().optional().describe('Execute the Copado commit job. Defaults to true.'),
705
- id: z.string().optional().describe('User story Id. Defaults to the active work item from work set.'),
706
- message: z
707
- .string()
708
- .optional()
709
- .describe('Commit message. Required unless supplied in the request body.'),
710
- metadataCategory: z.string().optional().describe(WORK_COMMIT_METADATA_CATEGORY_HELP),
711
- metadataMessage: z.string().optional().describe('Optional per-change message for simple input.'),
712
- metadataName: z.string().optional().describe('Metadata full name for simple input.'),
713
- metadataRawJson: z.unknown().optional().describe('Optional raw metadata JSON value for simple input.'),
714
- metadataType: z.string().optional().describe('Metadata type for simple input, for example ApexClass.'),
715
- recreateFeatureBranch: z.boolean().optional().describe('Ask Copado to recreate the feature branch.'),
716
- selection: z
717
- .array(z.string())
718
- .optional()
719
- .describe('Selected files inside a bundle for SelectiveCommit simple input.'),
720
- wait: z.boolean().optional().describe('Poll the commit job to a terminal status. Defaults to true.'),
721
- waitTimeout: z.number().int().optional().describe('Maximum seconds to wait for the commit job. Defaults to 300.'),
763
+ .describe('Ignored. This tool is a compatibility alias of agentia_cloud_commit.'),
722
764
  },
723
765
  title: 'Agentia Work Commit',
724
766
  }, (args) => safelyHandleTool(() => workCommit(args || {})));
725
- server.registerTool('agentia_work_promote', {
767
+ server.registerTool('agentia_cloud_promote', {
726
768
  description: 'Resolve a Promotion from an explicit or active User Story, then preflight, start, and optionally wait for the cloud promotion.',
727
- inputSchema: {
728
- cloud: z.boolean().optional().describe('Must be true. Uses the cloud promotion run endpoint.'),
729
- confirmRecreate: z
730
- .boolean()
731
- .optional()
732
- .describe('Required true when recreatePromotionBranch is true because MCP cannot prompt.'),
733
- deploy: z.boolean().optional().describe('Use merge_and_deploy instead of promote-only merge.'),
734
- deploymentStepIds: z
735
- .array(z.string())
736
- .optional()
737
- .describe('Ordered deployment-step Salesforce IDs. Requires deploy=true.'),
738
- id: z.string().optional().describe('User Story ID. Defaults to the active work item from work set.'),
739
- ignoredMetadata: z.array(z.unknown()).optional().describe('Ignored metadata persisted before starting the run.'),
740
- promotionId: z
741
- .string()
742
- .optional()
743
- .describe('Explicit 18-character Promotion ID when the User Story belongs to multiple promotions.'),
744
- recreatePromotionBranch: z.boolean().optional().describe('Recreate the promotion branch before execution.'),
745
- wait: z.boolean().optional().describe('Poll all created executions to terminal status. Defaults to true.'),
746
- waitTimeout: z
747
- .number()
748
- .int()
749
- .optional()
750
- .describe(`Maximum total wait in seconds. Defaults to ${PROMOTION_RUN_DEFAULT_TIMEOUT_SECONDS}.`),
751
- },
752
- title: 'Agentia Work Promote',
753
- }, (args) => safelyHandleTool(() => workPromote(args || {})));
769
+ inputSchema: cloudPromoteInputSchema,
770
+ title: 'Agentia Cloud Promote',
771
+ }, (args) => safelyHandleTool(() => cloudPromote(args || {})));
754
772
  server.registerTool('agentia_work_submit', {
755
- description: 'Submit the current feature/US-XXXX work item for pipeline quality gates and validation. Runs project-root .agentia_quality_gates.sh (macOS/Linux) or .agentia_quality_gates.cmd (Windows) when present, then fetches origin/<lastBaseBranch> and counts origin/<lastBaseBranch>..HEAD before checking origin. Pushes and registers commits when that feature-only range is non-empty and the branch is ahead of origin. When the last pending related job template name contains Commit, waits up to 5 minutes for that job before calling headless work/submit. With done=true or deploy=true, matches Copado UI Submit when promoting (headless work/done) and uses the same commit wait. Prefer this over agentia_work_done.',
773
+ description: 'Submit the current feature/US-XXXX work item for pipeline quality gates and validation. Runs project-root .agentia_quality_gates.sh (macOS/Linux) or .agentia_quality_gates.cmd (Windows) when present, then fetches origin/<lastBaseBranch> and counts origin/<lastBaseBranch>..HEAD before checking origin. Pushes and registers commits when that feature-only range is non-empty and the branch is ahead of origin. When the last pending related job template name contains Commit, waits up to 5 minutes for that job before calling headless work/submit. Before submit or promote, counts user stories ahead and behind between the source environment and the next pipeline environment, and warns when stories behind might cause promotion conflicts. With done=true or deploy=true, matches Copado UI Submit when promoting (headless work/done) and uses the same commit wait. Prefer this over agentia_work_done.',
756
774
  inputSchema: {
757
775
  apexTestClasses: z
758
776
  .string()
@@ -0,0 +1,4 @@
1
+ import {modules} from './runtime.js';
2
+ const DEFAULT_SFDX_METADATA_ROOT = modules["metadata-pathspecs.js"]["DEFAULT_SFDX_METADATA_ROOT"]
3
+ const guessMetadataPathspecs = modules["metadata-pathspecs.js"]["guessMetadataPathspecs"]
4
+ export {DEFAULT_SFDX_METADATA_ROOT, guessMetadataPathspecs};