@testchimp/cli 0.1.10 → 0.1.12

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.
@@ -1,3 +1,4 @@
1
1
  import { Command } from "commander";
2
- export declare const PACKAGE_VERSION = "0.1.7";
2
+ import { PACKAGE_VERSION } from "../core/version.js";
3
+ export { PACKAGE_VERSION };
3
4
  export declare function buildCliProgram(): Command;
@@ -5,7 +5,8 @@ import { DEFAULT_BACKEND, postMcp } from "../core/client.js";
5
5
  import { deepMerge } from "../core/merge.js";
6
6
  import { runTool } from "../core/tools.js";
7
7
  import { TOOL_DEFINITIONS } from "../core/tools.js";
8
- export const PACKAGE_VERSION = "0.1.7";
8
+ import { PACKAGE_VERSION } from "../core/version.js";
9
+ export { PACKAGE_VERSION };
9
10
  function parseRecordTypesCsv(raw) {
10
11
  return String(raw)
11
12
  .split(",")
@@ -58,6 +59,29 @@ export function buildCliProgram() {
58
59
  function jsonInputOption() {
59
60
  return new Option("--json-input <json>", "Advanced: JSON object or @path; merged over flags (JSON wins on conflicts)");
60
61
  }
62
+ /** Seed a minimal ExecutionScope from common flags (JSON can override / extend). */
63
+ function scopeFromFlags(opts) {
64
+ const scope = {};
65
+ if (opts.environment)
66
+ scope.environment = String(opts.environment);
67
+ if (opts.relativeWindow)
68
+ scope.timeWindow = { relativeWindow: String(opts.relativeWindow) };
69
+ if (opts.platform)
70
+ scope.platform = String(opts.platform);
71
+ if (opts.release)
72
+ scope.release = String(opts.release);
73
+ if (opts.branchName)
74
+ scope.branchName = String(opts.branchName);
75
+ return Object.keys(scope).length > 0 ? scope : undefined;
76
+ }
77
+ function addTruecoverageScopeFlags(cmd) {
78
+ return cmd
79
+ .option("--environment <s>", "RUM environment tag (seeds base scope)")
80
+ .option("--relative-window <duration>", 'Duration string ending in s, e.g. 604800s (seeds base scope timeWindow)')
81
+ .option("--platform <web|ios|android>", "Platform filter on base scope (aliases or WEB_/IOS_/ANDROID_EXECUTION_PLATFORM)")
82
+ .option("--release <s>", "Optional release filter on base scope")
83
+ .option("--branch-name <s>", "Optional branchName on base scope");
84
+ }
61
85
  program
62
86
  .command("get-requirement-coverage")
63
87
  .description(TOOL_DEFINITIONS.find((t) => t.kebab === "get-requirement-coverage").description)
@@ -420,49 +444,81 @@ export function buildCliProgram() {
420
444
  const out = await runTool("list-rum-environments", merged, { postMcp });
421
445
  console.log(out);
422
446
  });
423
- const truecoverageHelp = "Use --json-input with full request JSON (proto-shaped; set platform inside each ExecutionScope).";
424
- program
447
+ addTruecoverageScopeFlags(program
425
448
  .command("get-truecoverage-events")
426
- .description(TOOL_DEFINITIONS.find((t) => t.kebab === "get-truecoverage-events").description + " " + truecoverageHelp)
427
- .addOption(jsonInputOption())
428
- .action(async (opts) => {
429
- const merged = mergeBodies({}, opts.jsonInput);
449
+ .description(TOOL_DEFINITIONS.find((t) => t.kebab === "get-truecoverage-events").description)
450
+ .addOption(jsonInputOption())).action(async (opts) => {
451
+ const body = {};
452
+ const base = scopeFromFlags(opts);
453
+ if (base)
454
+ body.baseExecutionScope = base;
455
+ const merged = mergeBodies(body, opts.jsonInput);
430
456
  const out = await runTool("get-truecoverage-events", merged, { postMcp });
431
457
  console.log(out);
432
458
  });
433
- program
459
+ addTruecoverageScopeFlags(program
434
460
  .command("get-truecoverage-event-details")
435
- .description(TOOL_DEFINITIONS.find((t) => t.kebab === "get-truecoverage-event-details").description + " " + truecoverageHelp)
461
+ .description(TOOL_DEFINITIONS.find((t) => t.kebab === "get-truecoverage-event-details").description)
436
462
  .addOption(jsonInputOption())
437
- .action(async (opts) => {
438
- const merged = mergeBodies({}, opts.jsonInput);
463
+ .option("--event-title <title>", "Event title (or set eventTitle in --json-input)")).action(async (opts) => {
464
+ const body = {};
465
+ if (opts.eventTitle)
466
+ body.eventTitle = String(opts.eventTitle);
467
+ const base = scopeFromFlags(opts);
468
+ if (base)
469
+ body.baseExecutionScope = base;
470
+ const merged = mergeBodies(body, opts.jsonInput);
439
471
  const out = await runTool("get-truecoverage-event-details", merged, { postMcp });
440
472
  console.log(out);
441
473
  });
442
- program
474
+ addTruecoverageScopeFlags(program
443
475
  .command("get-truecoverage-child-event-tree")
444
- .description(TOOL_DEFINITIONS.find((t) => t.kebab === "get-truecoverage-child-event-tree").description + " " + truecoverageHelp)
476
+ .description(TOOL_DEFINITIONS.find((t) => t.kebab === "get-truecoverage-child-event-tree").description)
445
477
  .addOption(jsonInputOption())
446
- .action(async (opts) => {
447
- const merged = mergeBodies({}, opts.jsonInput);
478
+ .option("--event-title <title>", "Parent event title (or set eventTitle in --json-input)")).action(async (opts) => {
479
+ const body = {};
480
+ if (opts.eventTitle)
481
+ body.eventTitle = String(opts.eventTitle);
482
+ const base = scopeFromFlags(opts);
483
+ if (base)
484
+ body.baseScope = base;
485
+ const merged = mergeBodies(body, opts.jsonInput);
448
486
  const out = await runTool("get-truecoverage-child-event-tree", merged, { postMcp });
449
487
  console.log(out);
450
488
  });
451
- program
489
+ addTruecoverageScopeFlags(program
452
490
  .command("get-truecoverage-event-transition")
453
- .description(TOOL_DEFINITIONS.find((t) => t.kebab === "get-truecoverage-event-transition").description + " " + truecoverageHelp)
491
+ .description(TOOL_DEFINITIONS.find((t) => t.kebab === "get-truecoverage-event-transition").description)
454
492
  .addOption(jsonInputOption())
455
- .action(async (opts) => {
456
- const merged = mergeBodies({}, opts.jsonInput);
493
+ .option("--event-title <title>", "From event (or eventTitle in --json-input)")
494
+ .option("--next-event-title <title>", "To event (or nextEventTitle in --json-input)")).action(async (opts) => {
495
+ const body = {};
496
+ if (opts.eventTitle)
497
+ body.eventTitle = String(opts.eventTitle);
498
+ if (opts.nextEventTitle)
499
+ body.nextEventTitle = String(opts.nextEventTitle);
500
+ const base = scopeFromFlags(opts);
501
+ if (base)
502
+ body.baseScope = base;
503
+ const merged = mergeBodies(body, opts.jsonInput);
457
504
  const out = await runTool("get-truecoverage-event-transition", merged, { postMcp });
458
505
  console.log(out);
459
506
  });
460
- program
507
+ addTruecoverageScopeFlags(program
461
508
  .command("get-truecoverage-event-time-series")
462
- .description(TOOL_DEFINITIONS.find((t) => t.kebab === "get-truecoverage-event-time-series").description + " " + truecoverageHelp)
509
+ .description(TOOL_DEFINITIONS.find((t) => t.kebab === "get-truecoverage-event-time-series").description)
463
510
  .addOption(jsonInputOption())
464
- .action(async (opts) => {
465
- const merged = mergeBodies({}, opts.jsonInput);
511
+ .option("--event-title <title>", "Optional event title")
512
+ .option("--metric-type <name>", "SESSION_COUNT | RELATIVE_FREQUENCY | PERCENTAGE_TERMINAL_EVENT | SESSION_POSITION | …")).action(async (opts) => {
513
+ const body = {};
514
+ if (opts.eventTitle)
515
+ body.eventTitle = String(opts.eventTitle);
516
+ if (opts.metricType)
517
+ body.metricType = String(opts.metricType);
518
+ const base = scopeFromFlags(opts);
519
+ if (base)
520
+ body.baseExecutionScope = base;
521
+ const merged = mergeBodies(body, opts.jsonInput);
466
522
  const out = await runTool("get-truecoverage-event-time-series", merged, { postMcp });
467
523
  console.log(out);
468
524
  });
@@ -479,9 +535,11 @@ export function buildCliProgram() {
479
535
  .command("get-truecoverage-event-metadata-keys")
480
536
  .description(TOOL_DEFINITIONS.find((t) => t.kebab === "get-truecoverage-event-metadata-keys").description)
481
537
  .addOption(jsonInputOption())
482
- .requiredOption("--event-title <title>")
538
+ .option("--event-title <title>", "Event title (or set eventTitle in --json-input)")
483
539
  .action(async (opts) => {
484
- const body = { eventTitle: opts.eventTitle };
540
+ const body = {};
541
+ if (opts.eventTitle)
542
+ body.eventTitle = String(opts.eventTitle);
485
543
  const merged = mergeBodies(body, opts.jsonInput);
486
544
  const out = await runTool("get-truecoverage-event-metadata-keys", merged, { postMcp });
487
545
  console.log(out);
@@ -83,7 +83,449 @@ export declare const emptyInput: z.ZodObject<{}, z.core.$strip>;
83
83
  export declare const getBranchSpecificEndpointConfigInput: z.ZodObject<{
84
84
  branchName: z.ZodOptional<z.ZodString>;
85
85
  }, z.core.$strip>;
86
- export declare const truecoverageJsonInput: z.ZodRecord<z.ZodString, z.ZodUnknown>;
86
+ /** TimeWindow oneof exactly one branch (union exposes clearly to MCP agents). */
87
+ export declare const timeWindowSchema: z.ZodUnion<readonly [z.ZodObject<{
88
+ relativeWindow: z.ZodString;
89
+ }, z.core.$strict>, z.ZodObject<{
90
+ fixedWindow: z.ZodObject<{
91
+ startTime: z.ZodString;
92
+ endTime: z.ZodString;
93
+ }, z.core.$strip>;
94
+ }, z.core.$strict>]>;
95
+ /**
96
+ * ExecutionScope (rum_service.proto) — wire shape for Protobuf JsonFormat.
97
+ * Window must be nested under timeWindow (canonical). Flat relativeWindow on the scope is not accepted here.
98
+ */
99
+ export declare const executionScopeSchema: z.ZodObject<{
100
+ environment: z.ZodString;
101
+ timeWindow: z.ZodUnion<readonly [z.ZodObject<{
102
+ relativeWindow: z.ZodString;
103
+ }, z.core.$strict>, z.ZodObject<{
104
+ fixedWindow: z.ZodObject<{
105
+ startTime: z.ZodString;
106
+ endTime: z.ZodString;
107
+ }, z.core.$strip>;
108
+ }, z.core.$strict>]>;
109
+ release: z.ZodOptional<z.ZodString>;
110
+ branchName: z.ZodOptional<z.ZodString>;
111
+ platform: z.ZodOptional<z.ZodPipe<z.ZodEnum<{
112
+ web: "web";
113
+ ios: "ios";
114
+ android: "android";
115
+ UNKNOWN_EXECUTION_PLATFORM: "UNKNOWN_EXECUTION_PLATFORM";
116
+ WEB_EXECUTION_PLATFORM: "WEB_EXECUTION_PLATFORM";
117
+ IOS_EXECUTION_PLATFORM: "IOS_EXECUTION_PLATFORM";
118
+ ANDROID_EXECUTION_PLATFORM: "ANDROID_EXECUTION_PLATFORM";
119
+ }>, z.ZodTransform<"UNKNOWN_EXECUTION_PLATFORM" | "WEB_EXECUTION_PLATFORM" | "IOS_EXECUTION_PLATFORM" | "ANDROID_EXECUTION_PLATFORM", "web" | "ios" | "android" | "UNKNOWN_EXECUTION_PLATFORM" | "WEB_EXECUTION_PLATFORM" | "IOS_EXECUTION_PLATFORM" | "ANDROID_EXECUTION_PLATFORM">>>;
120
+ automationEmitsOnly: z.ZodOptional<z.ZodBoolean>;
121
+ metadataFilters: z.ZodOptional<z.ZodArray<z.ZodObject<{
122
+ key: z.ZodString;
123
+ value: z.ZodObject<{
124
+ stringValue: z.ZodOptional<z.ZodString>;
125
+ intValue: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
126
+ floatValue: z.ZodOptional<z.ZodNumber>;
127
+ boolValue: z.ZodOptional<z.ZodBoolean>;
128
+ }, z.core.$strip>;
129
+ operator: z.ZodOptional<z.ZodEnum<{
130
+ UNKNOWN_OPERATOR: "UNKNOWN_OPERATOR";
131
+ EQUALS: "EQUALS";
132
+ NOT_EQUALS: "NOT_EQUALS";
133
+ GREATER_THAN: "GREATER_THAN";
134
+ LESS_THAN: "LESS_THAN";
135
+ }>>;
136
+ }, z.core.$strip>>>;
137
+ }, z.core.$strip>;
138
+ export declare const listTruecoverageEventsInput: z.ZodObject<{
139
+ baseExecutionScope: z.ZodObject<{
140
+ environment: z.ZodString;
141
+ timeWindow: z.ZodUnion<readonly [z.ZodObject<{
142
+ relativeWindow: z.ZodString;
143
+ }, z.core.$strict>, z.ZodObject<{
144
+ fixedWindow: z.ZodObject<{
145
+ startTime: z.ZodString;
146
+ endTime: z.ZodString;
147
+ }, z.core.$strip>;
148
+ }, z.core.$strict>]>;
149
+ release: z.ZodOptional<z.ZodString>;
150
+ branchName: z.ZodOptional<z.ZodString>;
151
+ platform: z.ZodOptional<z.ZodPipe<z.ZodEnum<{
152
+ web: "web";
153
+ ios: "ios";
154
+ android: "android";
155
+ UNKNOWN_EXECUTION_PLATFORM: "UNKNOWN_EXECUTION_PLATFORM";
156
+ WEB_EXECUTION_PLATFORM: "WEB_EXECUTION_PLATFORM";
157
+ IOS_EXECUTION_PLATFORM: "IOS_EXECUTION_PLATFORM";
158
+ ANDROID_EXECUTION_PLATFORM: "ANDROID_EXECUTION_PLATFORM";
159
+ }>, z.ZodTransform<"UNKNOWN_EXECUTION_PLATFORM" | "WEB_EXECUTION_PLATFORM" | "IOS_EXECUTION_PLATFORM" | "ANDROID_EXECUTION_PLATFORM", "web" | "ios" | "android" | "UNKNOWN_EXECUTION_PLATFORM" | "WEB_EXECUTION_PLATFORM" | "IOS_EXECUTION_PLATFORM" | "ANDROID_EXECUTION_PLATFORM">>>;
160
+ automationEmitsOnly: z.ZodOptional<z.ZodBoolean>;
161
+ metadataFilters: z.ZodOptional<z.ZodArray<z.ZodObject<{
162
+ key: z.ZodString;
163
+ value: z.ZodObject<{
164
+ stringValue: z.ZodOptional<z.ZodString>;
165
+ intValue: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
166
+ floatValue: z.ZodOptional<z.ZodNumber>;
167
+ boolValue: z.ZodOptional<z.ZodBoolean>;
168
+ }, z.core.$strip>;
169
+ operator: z.ZodOptional<z.ZodEnum<{
170
+ UNKNOWN_OPERATOR: "UNKNOWN_OPERATOR";
171
+ EQUALS: "EQUALS";
172
+ NOT_EQUALS: "NOT_EQUALS";
173
+ GREATER_THAN: "GREATER_THAN";
174
+ LESS_THAN: "LESS_THAN";
175
+ }>>;
176
+ }, z.core.$strip>>>;
177
+ }, z.core.$strip>;
178
+ comparisonExecutionScope: z.ZodOptional<z.ZodObject<{
179
+ environment: z.ZodString;
180
+ timeWindow: z.ZodUnion<readonly [z.ZodObject<{
181
+ relativeWindow: z.ZodString;
182
+ }, z.core.$strict>, z.ZodObject<{
183
+ fixedWindow: z.ZodObject<{
184
+ startTime: z.ZodString;
185
+ endTime: z.ZodString;
186
+ }, z.core.$strip>;
187
+ }, z.core.$strict>]>;
188
+ release: z.ZodOptional<z.ZodString>;
189
+ branchName: z.ZodOptional<z.ZodString>;
190
+ platform: z.ZodOptional<z.ZodPipe<z.ZodEnum<{
191
+ web: "web";
192
+ ios: "ios";
193
+ android: "android";
194
+ UNKNOWN_EXECUTION_PLATFORM: "UNKNOWN_EXECUTION_PLATFORM";
195
+ WEB_EXECUTION_PLATFORM: "WEB_EXECUTION_PLATFORM";
196
+ IOS_EXECUTION_PLATFORM: "IOS_EXECUTION_PLATFORM";
197
+ ANDROID_EXECUTION_PLATFORM: "ANDROID_EXECUTION_PLATFORM";
198
+ }>, z.ZodTransform<"UNKNOWN_EXECUTION_PLATFORM" | "WEB_EXECUTION_PLATFORM" | "IOS_EXECUTION_PLATFORM" | "ANDROID_EXECUTION_PLATFORM", "web" | "ios" | "android" | "UNKNOWN_EXECUTION_PLATFORM" | "WEB_EXECUTION_PLATFORM" | "IOS_EXECUTION_PLATFORM" | "ANDROID_EXECUTION_PLATFORM">>>;
199
+ automationEmitsOnly: z.ZodOptional<z.ZodBoolean>;
200
+ metadataFilters: z.ZodOptional<z.ZodArray<z.ZodObject<{
201
+ key: z.ZodString;
202
+ value: z.ZodObject<{
203
+ stringValue: z.ZodOptional<z.ZodString>;
204
+ intValue: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
205
+ floatValue: z.ZodOptional<z.ZodNumber>;
206
+ boolValue: z.ZodOptional<z.ZodBoolean>;
207
+ }, z.core.$strip>;
208
+ operator: z.ZodOptional<z.ZodEnum<{
209
+ UNKNOWN_OPERATOR: "UNKNOWN_OPERATOR";
210
+ EQUALS: "EQUALS";
211
+ NOT_EQUALS: "NOT_EQUALS";
212
+ GREATER_THAN: "GREATER_THAN";
213
+ LESS_THAN: "LESS_THAN";
214
+ }>>;
215
+ }, z.core.$strip>>>;
216
+ }, z.core.$strip>>;
217
+ }, z.core.$strip>;
218
+ export declare const getTruecoverageEventDetailsInput: z.ZodObject<{
219
+ eventTitle: z.ZodString;
220
+ baseExecutionScope: z.ZodObject<{
221
+ environment: z.ZodString;
222
+ timeWindow: z.ZodUnion<readonly [z.ZodObject<{
223
+ relativeWindow: z.ZodString;
224
+ }, z.core.$strict>, z.ZodObject<{
225
+ fixedWindow: z.ZodObject<{
226
+ startTime: z.ZodString;
227
+ endTime: z.ZodString;
228
+ }, z.core.$strip>;
229
+ }, z.core.$strict>]>;
230
+ release: z.ZodOptional<z.ZodString>;
231
+ branchName: z.ZodOptional<z.ZodString>;
232
+ platform: z.ZodOptional<z.ZodPipe<z.ZodEnum<{
233
+ web: "web";
234
+ ios: "ios";
235
+ android: "android";
236
+ UNKNOWN_EXECUTION_PLATFORM: "UNKNOWN_EXECUTION_PLATFORM";
237
+ WEB_EXECUTION_PLATFORM: "WEB_EXECUTION_PLATFORM";
238
+ IOS_EXECUTION_PLATFORM: "IOS_EXECUTION_PLATFORM";
239
+ ANDROID_EXECUTION_PLATFORM: "ANDROID_EXECUTION_PLATFORM";
240
+ }>, z.ZodTransform<"UNKNOWN_EXECUTION_PLATFORM" | "WEB_EXECUTION_PLATFORM" | "IOS_EXECUTION_PLATFORM" | "ANDROID_EXECUTION_PLATFORM", "web" | "ios" | "android" | "UNKNOWN_EXECUTION_PLATFORM" | "WEB_EXECUTION_PLATFORM" | "IOS_EXECUTION_PLATFORM" | "ANDROID_EXECUTION_PLATFORM">>>;
241
+ automationEmitsOnly: z.ZodOptional<z.ZodBoolean>;
242
+ metadataFilters: z.ZodOptional<z.ZodArray<z.ZodObject<{
243
+ key: z.ZodString;
244
+ value: z.ZodObject<{
245
+ stringValue: z.ZodOptional<z.ZodString>;
246
+ intValue: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
247
+ floatValue: z.ZodOptional<z.ZodNumber>;
248
+ boolValue: z.ZodOptional<z.ZodBoolean>;
249
+ }, z.core.$strip>;
250
+ operator: z.ZodOptional<z.ZodEnum<{
251
+ UNKNOWN_OPERATOR: "UNKNOWN_OPERATOR";
252
+ EQUALS: "EQUALS";
253
+ NOT_EQUALS: "NOT_EQUALS";
254
+ GREATER_THAN: "GREATER_THAN";
255
+ LESS_THAN: "LESS_THAN";
256
+ }>>;
257
+ }, z.core.$strip>>>;
258
+ }, z.core.$strip>;
259
+ comparisonExecutionScope: z.ZodOptional<z.ZodObject<{
260
+ environment: z.ZodString;
261
+ timeWindow: z.ZodUnion<readonly [z.ZodObject<{
262
+ relativeWindow: z.ZodString;
263
+ }, z.core.$strict>, z.ZodObject<{
264
+ fixedWindow: z.ZodObject<{
265
+ startTime: z.ZodString;
266
+ endTime: z.ZodString;
267
+ }, z.core.$strip>;
268
+ }, z.core.$strict>]>;
269
+ release: z.ZodOptional<z.ZodString>;
270
+ branchName: z.ZodOptional<z.ZodString>;
271
+ platform: z.ZodOptional<z.ZodPipe<z.ZodEnum<{
272
+ web: "web";
273
+ ios: "ios";
274
+ android: "android";
275
+ UNKNOWN_EXECUTION_PLATFORM: "UNKNOWN_EXECUTION_PLATFORM";
276
+ WEB_EXECUTION_PLATFORM: "WEB_EXECUTION_PLATFORM";
277
+ IOS_EXECUTION_PLATFORM: "IOS_EXECUTION_PLATFORM";
278
+ ANDROID_EXECUTION_PLATFORM: "ANDROID_EXECUTION_PLATFORM";
279
+ }>, z.ZodTransform<"UNKNOWN_EXECUTION_PLATFORM" | "WEB_EXECUTION_PLATFORM" | "IOS_EXECUTION_PLATFORM" | "ANDROID_EXECUTION_PLATFORM", "web" | "ios" | "android" | "UNKNOWN_EXECUTION_PLATFORM" | "WEB_EXECUTION_PLATFORM" | "IOS_EXECUTION_PLATFORM" | "ANDROID_EXECUTION_PLATFORM">>>;
280
+ automationEmitsOnly: z.ZodOptional<z.ZodBoolean>;
281
+ metadataFilters: z.ZodOptional<z.ZodArray<z.ZodObject<{
282
+ key: z.ZodString;
283
+ value: z.ZodObject<{
284
+ stringValue: z.ZodOptional<z.ZodString>;
285
+ intValue: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
286
+ floatValue: z.ZodOptional<z.ZodNumber>;
287
+ boolValue: z.ZodOptional<z.ZodBoolean>;
288
+ }, z.core.$strip>;
289
+ operator: z.ZodOptional<z.ZodEnum<{
290
+ UNKNOWN_OPERATOR: "UNKNOWN_OPERATOR";
291
+ EQUALS: "EQUALS";
292
+ NOT_EQUALS: "NOT_EQUALS";
293
+ GREATER_THAN: "GREATER_THAN";
294
+ LESS_THAN: "LESS_THAN";
295
+ }>>;
296
+ }, z.core.$strip>>>;
297
+ }, z.core.$strip>>;
298
+ }, z.core.$strip>;
299
+ export declare const listTruecoverageChildEventTreeInput: z.ZodObject<{
300
+ eventTitle: z.ZodString;
301
+ baseScope: z.ZodObject<{
302
+ environment: z.ZodString;
303
+ timeWindow: z.ZodUnion<readonly [z.ZodObject<{
304
+ relativeWindow: z.ZodString;
305
+ }, z.core.$strict>, z.ZodObject<{
306
+ fixedWindow: z.ZodObject<{
307
+ startTime: z.ZodString;
308
+ endTime: z.ZodString;
309
+ }, z.core.$strip>;
310
+ }, z.core.$strict>]>;
311
+ release: z.ZodOptional<z.ZodString>;
312
+ branchName: z.ZodOptional<z.ZodString>;
313
+ platform: z.ZodOptional<z.ZodPipe<z.ZodEnum<{
314
+ web: "web";
315
+ ios: "ios";
316
+ android: "android";
317
+ UNKNOWN_EXECUTION_PLATFORM: "UNKNOWN_EXECUTION_PLATFORM";
318
+ WEB_EXECUTION_PLATFORM: "WEB_EXECUTION_PLATFORM";
319
+ IOS_EXECUTION_PLATFORM: "IOS_EXECUTION_PLATFORM";
320
+ ANDROID_EXECUTION_PLATFORM: "ANDROID_EXECUTION_PLATFORM";
321
+ }>, z.ZodTransform<"UNKNOWN_EXECUTION_PLATFORM" | "WEB_EXECUTION_PLATFORM" | "IOS_EXECUTION_PLATFORM" | "ANDROID_EXECUTION_PLATFORM", "web" | "ios" | "android" | "UNKNOWN_EXECUTION_PLATFORM" | "WEB_EXECUTION_PLATFORM" | "IOS_EXECUTION_PLATFORM" | "ANDROID_EXECUTION_PLATFORM">>>;
322
+ automationEmitsOnly: z.ZodOptional<z.ZodBoolean>;
323
+ metadataFilters: z.ZodOptional<z.ZodArray<z.ZodObject<{
324
+ key: z.ZodString;
325
+ value: z.ZodObject<{
326
+ stringValue: z.ZodOptional<z.ZodString>;
327
+ intValue: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
328
+ floatValue: z.ZodOptional<z.ZodNumber>;
329
+ boolValue: z.ZodOptional<z.ZodBoolean>;
330
+ }, z.core.$strip>;
331
+ operator: z.ZodOptional<z.ZodEnum<{
332
+ UNKNOWN_OPERATOR: "UNKNOWN_OPERATOR";
333
+ EQUALS: "EQUALS";
334
+ NOT_EQUALS: "NOT_EQUALS";
335
+ GREATER_THAN: "GREATER_THAN";
336
+ LESS_THAN: "LESS_THAN";
337
+ }>>;
338
+ }, z.core.$strip>>>;
339
+ }, z.core.$strip>;
340
+ coverageScope: z.ZodOptional<z.ZodObject<{
341
+ environment: z.ZodString;
342
+ timeWindow: z.ZodUnion<readonly [z.ZodObject<{
343
+ relativeWindow: z.ZodString;
344
+ }, z.core.$strict>, z.ZodObject<{
345
+ fixedWindow: z.ZodObject<{
346
+ startTime: z.ZodString;
347
+ endTime: z.ZodString;
348
+ }, z.core.$strip>;
349
+ }, z.core.$strict>]>;
350
+ release: z.ZodOptional<z.ZodString>;
351
+ branchName: z.ZodOptional<z.ZodString>;
352
+ platform: z.ZodOptional<z.ZodPipe<z.ZodEnum<{
353
+ web: "web";
354
+ ios: "ios";
355
+ android: "android";
356
+ UNKNOWN_EXECUTION_PLATFORM: "UNKNOWN_EXECUTION_PLATFORM";
357
+ WEB_EXECUTION_PLATFORM: "WEB_EXECUTION_PLATFORM";
358
+ IOS_EXECUTION_PLATFORM: "IOS_EXECUTION_PLATFORM";
359
+ ANDROID_EXECUTION_PLATFORM: "ANDROID_EXECUTION_PLATFORM";
360
+ }>, z.ZodTransform<"UNKNOWN_EXECUTION_PLATFORM" | "WEB_EXECUTION_PLATFORM" | "IOS_EXECUTION_PLATFORM" | "ANDROID_EXECUTION_PLATFORM", "web" | "ios" | "android" | "UNKNOWN_EXECUTION_PLATFORM" | "WEB_EXECUTION_PLATFORM" | "IOS_EXECUTION_PLATFORM" | "ANDROID_EXECUTION_PLATFORM">>>;
361
+ automationEmitsOnly: z.ZodOptional<z.ZodBoolean>;
362
+ metadataFilters: z.ZodOptional<z.ZodArray<z.ZodObject<{
363
+ key: z.ZodString;
364
+ value: z.ZodObject<{
365
+ stringValue: z.ZodOptional<z.ZodString>;
366
+ intValue: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
367
+ floatValue: z.ZodOptional<z.ZodNumber>;
368
+ boolValue: z.ZodOptional<z.ZodBoolean>;
369
+ }, z.core.$strip>;
370
+ operator: z.ZodOptional<z.ZodEnum<{
371
+ UNKNOWN_OPERATOR: "UNKNOWN_OPERATOR";
372
+ EQUALS: "EQUALS";
373
+ NOT_EQUALS: "NOT_EQUALS";
374
+ GREATER_THAN: "GREATER_THAN";
375
+ LESS_THAN: "LESS_THAN";
376
+ }>>;
377
+ }, z.core.$strip>>>;
378
+ }, z.core.$strip>>;
379
+ }, z.core.$strip>;
380
+ export declare const getTruecoverageEventTransitionInput: z.ZodObject<{
381
+ eventTitle: z.ZodString;
382
+ nextEventTitle: z.ZodString;
383
+ baseScope: z.ZodObject<{
384
+ environment: z.ZodString;
385
+ timeWindow: z.ZodUnion<readonly [z.ZodObject<{
386
+ relativeWindow: z.ZodString;
387
+ }, z.core.$strict>, z.ZodObject<{
388
+ fixedWindow: z.ZodObject<{
389
+ startTime: z.ZodString;
390
+ endTime: z.ZodString;
391
+ }, z.core.$strip>;
392
+ }, z.core.$strict>]>;
393
+ release: z.ZodOptional<z.ZodString>;
394
+ branchName: z.ZodOptional<z.ZodString>;
395
+ platform: z.ZodOptional<z.ZodPipe<z.ZodEnum<{
396
+ web: "web";
397
+ ios: "ios";
398
+ android: "android";
399
+ UNKNOWN_EXECUTION_PLATFORM: "UNKNOWN_EXECUTION_PLATFORM";
400
+ WEB_EXECUTION_PLATFORM: "WEB_EXECUTION_PLATFORM";
401
+ IOS_EXECUTION_PLATFORM: "IOS_EXECUTION_PLATFORM";
402
+ ANDROID_EXECUTION_PLATFORM: "ANDROID_EXECUTION_PLATFORM";
403
+ }>, z.ZodTransform<"UNKNOWN_EXECUTION_PLATFORM" | "WEB_EXECUTION_PLATFORM" | "IOS_EXECUTION_PLATFORM" | "ANDROID_EXECUTION_PLATFORM", "web" | "ios" | "android" | "UNKNOWN_EXECUTION_PLATFORM" | "WEB_EXECUTION_PLATFORM" | "IOS_EXECUTION_PLATFORM" | "ANDROID_EXECUTION_PLATFORM">>>;
404
+ automationEmitsOnly: z.ZodOptional<z.ZodBoolean>;
405
+ metadataFilters: z.ZodOptional<z.ZodArray<z.ZodObject<{
406
+ key: z.ZodString;
407
+ value: z.ZodObject<{
408
+ stringValue: z.ZodOptional<z.ZodString>;
409
+ intValue: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
410
+ floatValue: z.ZodOptional<z.ZodNumber>;
411
+ boolValue: z.ZodOptional<z.ZodBoolean>;
412
+ }, z.core.$strip>;
413
+ operator: z.ZodOptional<z.ZodEnum<{
414
+ UNKNOWN_OPERATOR: "UNKNOWN_OPERATOR";
415
+ EQUALS: "EQUALS";
416
+ NOT_EQUALS: "NOT_EQUALS";
417
+ GREATER_THAN: "GREATER_THAN";
418
+ LESS_THAN: "LESS_THAN";
419
+ }>>;
420
+ }, z.core.$strip>>>;
421
+ }, z.core.$strip>;
422
+ coverageScope: z.ZodOptional<z.ZodObject<{
423
+ environment: z.ZodString;
424
+ timeWindow: z.ZodUnion<readonly [z.ZodObject<{
425
+ relativeWindow: z.ZodString;
426
+ }, z.core.$strict>, z.ZodObject<{
427
+ fixedWindow: z.ZodObject<{
428
+ startTime: z.ZodString;
429
+ endTime: z.ZodString;
430
+ }, z.core.$strip>;
431
+ }, z.core.$strict>]>;
432
+ release: z.ZodOptional<z.ZodString>;
433
+ branchName: z.ZodOptional<z.ZodString>;
434
+ platform: z.ZodOptional<z.ZodPipe<z.ZodEnum<{
435
+ web: "web";
436
+ ios: "ios";
437
+ android: "android";
438
+ UNKNOWN_EXECUTION_PLATFORM: "UNKNOWN_EXECUTION_PLATFORM";
439
+ WEB_EXECUTION_PLATFORM: "WEB_EXECUTION_PLATFORM";
440
+ IOS_EXECUTION_PLATFORM: "IOS_EXECUTION_PLATFORM";
441
+ ANDROID_EXECUTION_PLATFORM: "ANDROID_EXECUTION_PLATFORM";
442
+ }>, z.ZodTransform<"UNKNOWN_EXECUTION_PLATFORM" | "WEB_EXECUTION_PLATFORM" | "IOS_EXECUTION_PLATFORM" | "ANDROID_EXECUTION_PLATFORM", "web" | "ios" | "android" | "UNKNOWN_EXECUTION_PLATFORM" | "WEB_EXECUTION_PLATFORM" | "IOS_EXECUTION_PLATFORM" | "ANDROID_EXECUTION_PLATFORM">>>;
443
+ automationEmitsOnly: z.ZodOptional<z.ZodBoolean>;
444
+ metadataFilters: z.ZodOptional<z.ZodArray<z.ZodObject<{
445
+ key: z.ZodString;
446
+ value: z.ZodObject<{
447
+ stringValue: z.ZodOptional<z.ZodString>;
448
+ intValue: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
449
+ floatValue: z.ZodOptional<z.ZodNumber>;
450
+ boolValue: z.ZodOptional<z.ZodBoolean>;
451
+ }, z.core.$strip>;
452
+ operator: z.ZodOptional<z.ZodEnum<{
453
+ UNKNOWN_OPERATOR: "UNKNOWN_OPERATOR";
454
+ EQUALS: "EQUALS";
455
+ NOT_EQUALS: "NOT_EQUALS";
456
+ GREATER_THAN: "GREATER_THAN";
457
+ LESS_THAN: "LESS_THAN";
458
+ }>>;
459
+ }, z.core.$strip>>>;
460
+ }, z.core.$strip>>;
461
+ }, z.core.$strip>;
462
+ /** EventTimeSeriesMetricType — must match rum_service.proto enum names. */
463
+ export declare const eventTimeSeriesMetricSchema: z.ZodEnum<{
464
+ EVENT_TIME_SERIES_METRIC_UNSPECIFIED: "EVENT_TIME_SERIES_METRIC_UNSPECIFIED";
465
+ SESSION_COUNT: "SESSION_COUNT";
466
+ RELATIVE_FREQUENCY: "RELATIVE_FREQUENCY";
467
+ PERCENTAGE_TERMINAL_EVENT: "PERCENTAGE_TERMINAL_EVENT";
468
+ SESSION_POSITION: "SESSION_POSITION";
469
+ TIME_TO_NEXT_EVENT: "TIME_TO_NEXT_EVENT";
470
+ REVERSE_INDEX: "REVERSE_INDEX";
471
+ TIME_FROM_START: "TIME_FROM_START";
472
+ TIME_TO_END: "TIME_TO_END";
473
+ TIME_SINCE_PREVIOUS_EVENT: "TIME_SINCE_PREVIOUS_EVENT";
474
+ }>;
475
+ export declare const getTruecoverageEventTimeSeriesInput: z.ZodObject<{
476
+ baseExecutionScope: z.ZodObject<{
477
+ environment: z.ZodString;
478
+ timeWindow: z.ZodUnion<readonly [z.ZodObject<{
479
+ relativeWindow: z.ZodString;
480
+ }, z.core.$strict>, z.ZodObject<{
481
+ fixedWindow: z.ZodObject<{
482
+ startTime: z.ZodString;
483
+ endTime: z.ZodString;
484
+ }, z.core.$strip>;
485
+ }, z.core.$strict>]>;
486
+ release: z.ZodOptional<z.ZodString>;
487
+ branchName: z.ZodOptional<z.ZodString>;
488
+ platform: z.ZodOptional<z.ZodPipe<z.ZodEnum<{
489
+ web: "web";
490
+ ios: "ios";
491
+ android: "android";
492
+ UNKNOWN_EXECUTION_PLATFORM: "UNKNOWN_EXECUTION_PLATFORM";
493
+ WEB_EXECUTION_PLATFORM: "WEB_EXECUTION_PLATFORM";
494
+ IOS_EXECUTION_PLATFORM: "IOS_EXECUTION_PLATFORM";
495
+ ANDROID_EXECUTION_PLATFORM: "ANDROID_EXECUTION_PLATFORM";
496
+ }>, z.ZodTransform<"UNKNOWN_EXECUTION_PLATFORM" | "WEB_EXECUTION_PLATFORM" | "IOS_EXECUTION_PLATFORM" | "ANDROID_EXECUTION_PLATFORM", "web" | "ios" | "android" | "UNKNOWN_EXECUTION_PLATFORM" | "WEB_EXECUTION_PLATFORM" | "IOS_EXECUTION_PLATFORM" | "ANDROID_EXECUTION_PLATFORM">>>;
497
+ automationEmitsOnly: z.ZodOptional<z.ZodBoolean>;
498
+ metadataFilters: z.ZodOptional<z.ZodArray<z.ZodObject<{
499
+ key: z.ZodString;
500
+ value: z.ZodObject<{
501
+ stringValue: z.ZodOptional<z.ZodString>;
502
+ intValue: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
503
+ floatValue: z.ZodOptional<z.ZodNumber>;
504
+ boolValue: z.ZodOptional<z.ZodBoolean>;
505
+ }, z.core.$strip>;
506
+ operator: z.ZodOptional<z.ZodEnum<{
507
+ UNKNOWN_OPERATOR: "UNKNOWN_OPERATOR";
508
+ EQUALS: "EQUALS";
509
+ NOT_EQUALS: "NOT_EQUALS";
510
+ GREATER_THAN: "GREATER_THAN";
511
+ LESS_THAN: "LESS_THAN";
512
+ }>>;
513
+ }, z.core.$strip>>>;
514
+ }, z.core.$strip>;
515
+ eventTitle: z.ZodOptional<z.ZodString>;
516
+ metricType: z.ZodOptional<z.ZodEnum<{
517
+ EVENT_TIME_SERIES_METRIC_UNSPECIFIED: "EVENT_TIME_SERIES_METRIC_UNSPECIFIED";
518
+ SESSION_COUNT: "SESSION_COUNT";
519
+ RELATIVE_FREQUENCY: "RELATIVE_FREQUENCY";
520
+ PERCENTAGE_TERMINAL_EVENT: "PERCENTAGE_TERMINAL_EVENT";
521
+ SESSION_POSITION: "SESSION_POSITION";
522
+ TIME_TO_NEXT_EVENT: "TIME_TO_NEXT_EVENT";
523
+ REVERSE_INDEX: "REVERSE_INDEX";
524
+ TIME_FROM_START: "TIME_FROM_START";
525
+ TIME_TO_END: "TIME_TO_END";
526
+ TIME_SINCE_PREVIOUS_EVENT: "TIME_SINCE_PREVIOUS_EVENT";
527
+ }>>;
528
+ }, z.core.$strip>;
87
529
  export declare const eventMetadataKeysInput: z.ZodObject<{
88
530
  eventTitle: z.ZodString;
89
531
  }, z.core.$strip>;
@@ -84,7 +84,125 @@ export const emptyInput = z.object({});
84
84
  export const getBranchSpecificEndpointConfigInput = z.object({
85
85
  branchName: z.string().optional(),
86
86
  });
87
- export const truecoverageJsonInput = z.record(z.string(), z.unknown());
87
+ /** Protobuf JSON Duration — must end in `s`, e.g. "604800s", "1.5s". */
88
+ const protobufDurationSchema = z
89
+ .string()
90
+ .regex(/^-?\d+(\.\d+)?s$/, 'Duration must be protobuf JSON ending in "s", e.g. "604800s"');
91
+ const fixedWindowSchema = z
92
+ .object({
93
+ startTime: z.string().min(1).describe("RFC 3339 timestamp"),
94
+ endTime: z.string().min(1).describe("RFC 3339 timestamp"),
95
+ })
96
+ .describe("Fixed calendar window (both bounds required)");
97
+ /** TimeWindow oneof — exactly one branch (union exposes clearly to MCP agents). */
98
+ export const timeWindowSchema = z.union([
99
+ z.object({ relativeWindow: protobufDurationSchema }).strict(),
100
+ z.object({ fixedWindow: fixedWindowSchema }).strict(),
101
+ ]);
102
+ /** Accept CLI aliases (web|ios|android) or proto enum names; normalize to proto. */
103
+ const executionScopePlatformSchema = z
104
+ .enum([
105
+ "web",
106
+ "ios",
107
+ "android",
108
+ "UNKNOWN_EXECUTION_PLATFORM",
109
+ "WEB_EXECUTION_PLATFORM",
110
+ "IOS_EXECUTION_PLATFORM",
111
+ "ANDROID_EXECUTION_PLATFORM",
112
+ ])
113
+ .transform((p) => {
114
+ switch (p) {
115
+ case "web":
116
+ return "WEB_EXECUTION_PLATFORM";
117
+ case "ios":
118
+ return "IOS_EXECUTION_PLATFORM";
119
+ case "android":
120
+ return "ANDROID_EXECUTION_PLATFORM";
121
+ default:
122
+ return p;
123
+ }
124
+ });
125
+ const typedValueSchema = z
126
+ .object({
127
+ stringValue: z.string().optional(),
128
+ /** Protobuf JSON often encodes int64 as string. */
129
+ intValue: z.union([z.string(), z.number()]).optional(),
130
+ floatValue: z.number().optional(),
131
+ boolValue: z.boolean().optional(),
132
+ })
133
+ .superRefine((v, ctx) => {
134
+ const set = [v.stringValue, v.intValue, v.floatValue, v.boolValue].filter((x) => x !== undefined);
135
+ if (set.length !== 1) {
136
+ ctx.addIssue({
137
+ code: z.ZodIssueCode.custom,
138
+ message: "TypedValue requires exactly one of stringValue, intValue, floatValue, boolValue",
139
+ });
140
+ }
141
+ });
142
+ const metadataFilterSchema = z.object({
143
+ key: z.string().min(1),
144
+ value: typedValueSchema,
145
+ operator: z
146
+ .enum(["UNKNOWN_OPERATOR", "EQUALS", "NOT_EQUALS", "GREATER_THAN", "LESS_THAN"])
147
+ .optional(),
148
+ });
149
+ /**
150
+ * ExecutionScope (rum_service.proto) — wire shape for Protobuf JsonFormat.
151
+ * Window must be nested under timeWindow (canonical). Flat relativeWindow on the scope is not accepted here.
152
+ */
153
+ export const executionScopeSchema = z.object({
154
+ environment: z
155
+ .string()
156
+ .min(1)
157
+ .describe("RUM environment tag from list-rum-environments (e.g. QA, production)"),
158
+ timeWindow: timeWindowSchema,
159
+ release: z.string().optional(),
160
+ branchName: z.string().optional(),
161
+ platform: executionScopePlatformSchema.optional(),
162
+ automationEmitsOnly: z
163
+ .boolean()
164
+ .optional()
165
+ .describe("On comparison/coverage scopes only: restrict to emits with test_id"),
166
+ metadataFilters: z.array(metadataFilterSchema).optional(),
167
+ });
168
+ export const listTruecoverageEventsInput = z.object({
169
+ baseExecutionScope: executionScopeSchema,
170
+ comparisonExecutionScope: executionScopeSchema.optional(),
171
+ });
172
+ export const getTruecoverageEventDetailsInput = z.object({
173
+ eventTitle: z.string().min(1),
174
+ baseExecutionScope: executionScopeSchema,
175
+ comparisonExecutionScope: executionScopeSchema.optional(),
176
+ });
177
+ export const listTruecoverageChildEventTreeInput = z.object({
178
+ eventTitle: z.string().min(1),
179
+ baseScope: executionScopeSchema,
180
+ coverageScope: executionScopeSchema.optional(),
181
+ });
182
+ export const getTruecoverageEventTransitionInput = z.object({
183
+ eventTitle: z.string().min(1),
184
+ nextEventTitle: z.string().min(1),
185
+ baseScope: executionScopeSchema,
186
+ coverageScope: executionScopeSchema.optional(),
187
+ });
188
+ /** EventTimeSeriesMetricType — must match rum_service.proto enum names. */
189
+ export const eventTimeSeriesMetricSchema = z.enum([
190
+ "EVENT_TIME_SERIES_METRIC_UNSPECIFIED",
191
+ "SESSION_COUNT",
192
+ "RELATIVE_FREQUENCY",
193
+ "PERCENTAGE_TERMINAL_EVENT",
194
+ "SESSION_POSITION",
195
+ "TIME_TO_NEXT_EVENT",
196
+ "REVERSE_INDEX",
197
+ "TIME_FROM_START",
198
+ "TIME_TO_END",
199
+ "TIME_SINCE_PREVIOUS_EVENT",
200
+ ]);
201
+ export const getTruecoverageEventTimeSeriesInput = z.object({
202
+ baseExecutionScope: executionScopeSchema,
203
+ eventTitle: z.string().optional(),
204
+ metricType: eventTimeSeriesMetricSchema.optional(),
205
+ });
88
206
  export const eventMetadataKeysInput = z.object({
89
207
  eventTitle: z.string().min(1),
90
208
  });
@@ -11,6 +11,20 @@ function platformToProtoEnum(platform) {
11
11
  return "WEB_EXECUTION_PLATFORM";
12
12
  }
13
13
  }
14
+ /** Build ExecutionScope JSON after Zod parse (platform aliases already normalized). */
15
+ function executionScopeBody(scope) {
16
+ return {
17
+ environment: scope.environment,
18
+ timeWindow: scope.timeWindow,
19
+ ...(scope.release != null ? { release: scope.release } : {}),
20
+ ...(scope.branchName != null ? { branchName: scope.branchName } : {}),
21
+ ...(scope.platform != null ? { platform: scope.platform } : {}),
22
+ ...(scope.automationEmitsOnly != null ? { automationEmitsOnly: scope.automationEmitsOnly } : {}),
23
+ ...(scope.metadataFilters != null && scope.metadataFilters.length > 0
24
+ ? { metadataFilters: scope.metadataFilters }
25
+ : {}),
26
+ };
27
+ }
14
28
  function listCoverageBody(args) {
15
29
  const body = {};
16
30
  if (args.release != null)
@@ -111,9 +125,11 @@ export const TOOL_DEFINITIONS = [
111
125
  },
112
126
  {
113
127
  kebab: "create-user-story",
114
- description: "Create a user story on the TestChimp project and its plan file stub. " +
115
- "Always call this before writing a new story markdown file; use the returned ordinalId as US-<ordinalId> in frontmatter. " +
116
- "platformFilePath must be under plans/stories/ and end with .md.",
128
+ description: "Create a user story on the TestChimp project and allocate a real US-<ordinalId>. " +
129
+ "Response includes content: canonical stub markdown already containing id: US-<ordinalId>. " +
130
+ "BLOCKING workflow: call this FIRST → Write the returned content to the repo plans/stories path " +
131
+ "(edit body as needed but keep id:) → call update-user-story with the full markdown. " +
132
+ "Never write story markdown that omits id. platformFilePath must be under plans/stories/ and end with .md.",
117
133
  inputSchema: S.createUserStoryInput,
118
134
  execute: async (args, { postMcp }) => {
119
135
  const a = args;
@@ -125,7 +141,12 @@ export const TOOL_DEFINITIONS = [
125
141
  },
126
142
  {
127
143
  kebab: "create-test-scenario",
128
- description: "Create a test scenario linked to a user story. platformFilePath must be under plans/scenarios/ and end with .md. " +
144
+ description: "Create a test scenario linked to a user story and allocate a real TS-<ordinalId>. " +
145
+ "Response includes content: canonical stub markdown already containing id: TS-<ordinalId> and story: US-<n>. " +
146
+ "BLOCKING workflow: call this FIRST → Write the returned content to the repo plans/scenarios path " +
147
+ "(edit body as needed but keep id: and story:) → call update-test-scenario with the full markdown. " +
148
+ "Never write scenario markdown that omits id. update-test-scenario rejects missing id/story with a clear error. " +
149
+ "platformFilePath must be under plans/scenarios/ and end with .md. " +
129
150
  "userStoryOrdinalId is the numeric part of the parent US-<n> id.",
130
151
  inputSchema: S.createTestScenarioInput,
131
152
  execute: async (args, { postMcp }) => {
@@ -140,8 +161,8 @@ export const TOOL_DEFINITIONS = [
140
161
  {
141
162
  kebab: "update-user-story",
142
163
  description: "Sync a user story markdown file to the platform after local edits. " +
143
- "Parses frontmatter (id: US-..., title, priority) and updates the linked support file and entity. " +
144
- "Implementation status is not stored in markdown; use mark-plan-items-implementation-done.",
164
+ "Requires frontmatter id: US-<n> (platform-issued). Missing id returns an error telling you to call create-user-story first. " +
165
+ "Parses frontmatter (id, title, priority) and updates the linked support file and entity.",
145
166
  inputSchema: S.updatePlanMarkdownInput,
146
167
  execute: async (args, { postMcp }) => {
147
168
  const a = args;
@@ -151,8 +172,8 @@ export const TOOL_DEFINITIONS = [
151
172
  {
152
173
  kebab: "update-test-scenario",
153
174
  description: "Sync a test scenario markdown file to the platform after local edits. " +
154
- "Parses frontmatter (id: TS-..., story: US-..., title, priority) and updates linking if story changes. " +
155
- "Implementation status is not stored in markdown; use mark-plan-items-implementation-done.",
175
+ "Requires frontmatter id: TS-<n> and story: US-<n>. Missing either returns an error telling you to call create-test-scenario first. " +
176
+ "Parses frontmatter and updates linking if story changes.",
156
177
  inputSchema: S.updatePlanMarkdownInput,
157
178
  execute: async (args, { postMcp }) => {
158
179
  const a = args;
@@ -317,56 +338,115 @@ export const TOOL_DEFINITIONS = [
317
338
  },
318
339
  {
319
340
  kebab: "list-rum-environments",
320
- description: "List distinct RUM environment tags for TrueCoverage scoping.",
341
+ description: "List distinct RUM environment tags for this project. Call this first to choose environment values " +
342
+ "for TrueCoverage ExecutionScope.environment (e.g. QA, production).",
321
343
  inputSchema: S.emptyInput,
322
344
  execute: async (_args, { postMcp }) => postMcp("/api/mcp/list_rum_environments", {}),
323
345
  },
324
346
  {
325
347
  kebab: "get-truecoverage-events",
326
- description: "TrueCoverage event funnel summaries (ListEventsRequest JSON: baseExecutionScope, comparisonExecutionScope). " +
327
- "Optional ExecutionScope.platform: WEB_EXECUTION_PLATFORM | IOS_EXECUTION_PLATFORM | ANDROID_EXECUTION_PLATFORM " +
328
- "(filters RUM rows stamped via testchimp-rum-platform header: web=1, ios=2, android=3). " +
329
- "Use automationEmitsOnly on comparisonExecutionScope for test-tagged emits only.",
330
- inputSchema: S.truecoverageJsonInput,
331
- execute: async (args, { postMcp }) => postMcp("/api/mcp/truecoverage_list_events", args ?? {}),
348
+ description: "TrueCoverage event funnel summaries (ListEventsRequest). " +
349
+ "baseExecutionScope is the real-user / primary environment; optional comparisonExecutionScope for coverage " +
350
+ "(set automationEmitsOnly:true on comparison for test-tagged emits only). " +
351
+ "Each scope needs environment + timeWindow: { relativeWindow: \"604800s\" } or { fixedWindow: { startTime, endTime } } (RFC 3339). " +
352
+ "Optional platform: web|ios|android or WEB_/IOS_/ANDROID_EXECUTION_PLATFORM. " +
353
+ "Prefer list-rum-environments first.",
354
+ inputSchema: S.listTruecoverageEventsInput,
355
+ execute: async (args, { postMcp }) => {
356
+ const a = args;
357
+ const body = {
358
+ baseExecutionScope: executionScopeBody(a.baseExecutionScope),
359
+ };
360
+ if (a.comparisonExecutionScope != null) {
361
+ body.comparisonExecutionScope = executionScopeBody(a.comparisonExecutionScope);
362
+ }
363
+ return postMcp("/api/mcp/truecoverage_list_events", body);
364
+ },
332
365
  },
333
366
  {
334
367
  kebab: "get-truecoverage-event-details",
335
- description: "TrueCoverage drill-down for one event title (GetEventDetailsRequest JSON). " +
336
- "Optional platform on baseExecutionScope / comparisonExecutionScope (WEB_EXECUTION_PLATFORM, IOS_EXECUTION_PLATFORM, ANDROID_EXECUTION_PLATFORM).",
337
- inputSchema: S.truecoverageJsonInput,
338
- execute: async (args, { postMcp }) => postMcp("/api/mcp/truecoverage_event_details", args ?? {}),
368
+ description: "TrueCoverage drill-down for one event (GetEventDetailsRequest). " +
369
+ "Requires eventTitle plus baseExecutionScope (environment + timeWindow). " +
370
+ "Optional comparisonExecutionScope for coverage columns (automationEmitsOnly on comparison). " +
371
+ "Same timeWindow / platform rules as get-truecoverage-events.",
372
+ inputSchema: S.getTruecoverageEventDetailsInput,
373
+ execute: async (args, { postMcp }) => {
374
+ const a = args;
375
+ const body = {
376
+ eventTitle: a.eventTitle,
377
+ baseExecutionScope: executionScopeBody(a.baseExecutionScope),
378
+ };
379
+ if (a.comparisonExecutionScope != null) {
380
+ body.comparisonExecutionScope = executionScopeBody(a.comparisonExecutionScope);
381
+ }
382
+ return postMcp("/api/mcp/truecoverage_event_details", body);
383
+ },
339
384
  },
340
385
  {
341
386
  kebab: "get-truecoverage-child-event-tree",
342
- description: "TrueCoverage next-event tree for an event (ListChildEventTreeRequest JSON). " +
343
- "Optional platform on baseScope / coverageScope (inside each ExecutionScope).",
344
- inputSchema: S.truecoverageJsonInput,
345
- execute: async (args, { postMcp }) => postMcp("/api/mcp/truecoverage_list_child_event_tree", args ?? {}),
387
+ description: "TrueCoverage next-event tree after an event (ListChildEventTreeRequest). " +
388
+ "Requires eventTitle, baseScope (environment + timeWindow); optional coverageScope for PRESENT/ABSENT. " +
389
+ "Note: metadataFilters on scopes are ignored for transition stats. Field names are baseScope/coverageScope " +
390
+ "(not baseExecutionScope).",
391
+ inputSchema: S.listTruecoverageChildEventTreeInput,
392
+ execute: async (args, { postMcp }) => {
393
+ const a = args;
394
+ const body = {
395
+ eventTitle: a.eventTitle,
396
+ baseScope: executionScopeBody(a.baseScope),
397
+ };
398
+ if (a.coverageScope != null)
399
+ body.coverageScope = executionScopeBody(a.coverageScope);
400
+ return postMcp("/api/mcp/truecoverage_list_child_event_tree", body);
401
+ },
346
402
  },
347
403
  {
348
404
  kebab: "get-truecoverage-event-transition",
349
- description: "TrueCoverage detailed transition summary between events (GetDetailedEventTransitionSummaryRequest JSON). " +
350
- "Optional platform on baseScope / coverageScope (inside each ExecutionScope).",
351
- inputSchema: S.truecoverageJsonInput,
352
- execute: async (args, { postMcp }) => postMcp("/api/mcp/truecoverage_detailed_event_transition", args ?? {}),
405
+ description: "TrueCoverage detailed transition stats between two events (GetDetailedEventTransitionSummaryRequest). " +
406
+ "Requires eventTitle, nextEventTitle, baseScope (environment + timeWindow); optional coverageScope. " +
407
+ "metadataFilters on scopes are ignored. Uses baseScope/coverageScope field names.",
408
+ inputSchema: S.getTruecoverageEventTransitionInput,
409
+ execute: async (args, { postMcp }) => {
410
+ const a = args;
411
+ const body = {
412
+ eventTitle: a.eventTitle,
413
+ nextEventTitle: a.nextEventTitle,
414
+ baseScope: executionScopeBody(a.baseScope),
415
+ };
416
+ if (a.coverageScope != null)
417
+ body.coverageScope = executionScopeBody(a.coverageScope);
418
+ return postMcp("/api/mcp/truecoverage_detailed_event_transition", body);
419
+ },
353
420
  },
354
421
  {
355
422
  kebab: "get-truecoverage-event-time-series",
356
- description: "TrueCoverage time series for sessions or metrics (EventTimeSeriesRequest JSON). " +
357
- "Optional platform on baseExecutionScope.",
358
- inputSchema: S.truecoverageJsonInput,
359
- execute: async (args, { postMcp }) => postMcp("/api/mcp/truecoverage_event_time_series", args ?? {}),
423
+ description: "TrueCoverage daily time series for one metric (EventTimeSeriesRequest). " +
424
+ "Requires baseExecutionScope (environment + timeWindow). Optional eventTitle and metricType: " +
425
+ "SESSION_COUNT | RELATIVE_FREQUENCY | PERCENTAGE_TERMINAL_EVENT | SESSION_POSITION | " +
426
+ "TIME_TO_NEXT_EVENT | REVERSE_INDEX | TIME_FROM_START | TIME_TO_END | TIME_SINCE_PREVIOUS_EVENT.",
427
+ inputSchema: S.getTruecoverageEventTimeSeriesInput,
428
+ execute: async (args, { postMcp }) => {
429
+ const a = args;
430
+ const body = {
431
+ baseExecutionScope: executionScopeBody(a.baseExecutionScope),
432
+ };
433
+ if (a.eventTitle != null)
434
+ body.eventTitle = a.eventTitle;
435
+ if (a.metricType != null)
436
+ body.metricType = a.metricType;
437
+ return postMcp("/api/mcp/truecoverage_event_time_series", body);
438
+ },
360
439
  },
361
440
  {
362
441
  kebab: "get-truecoverage-session-metadata-keys",
363
- description: "List session-level metadata keys observed for TrueCoverage.",
442
+ description: "List session-level metadata keys observed in RUM for TrueCoverage filters.",
364
443
  inputSchema: S.emptyInput,
365
444
  execute: async (_args, { postMcp }) => postMcp("/api/mcp/truecoverage_session_metadata_keys", {}),
366
445
  },
367
446
  {
368
447
  kebab: "get-truecoverage-event-metadata-keys",
369
- description: "List metadata keys for a given event title.",
448
+ description: "List metadata keys for a given event title (ListEventMetadataKeysRequest). " +
449
+ "Pass eventTitle (CLI: --event-title or json-input).",
370
450
  inputSchema: S.eventMetadataKeysInput,
371
451
  execute: async (args, { postMcp }) => {
372
452
  const a = args;
@@ -0,0 +1 @@
1
+ export declare const PACKAGE_VERSION: string;
@@ -0,0 +1,4 @@
1
+ import { createRequire } from "node:module";
2
+ const require = createRequire(import.meta.url);
3
+ const pkg = require("../../package.json");
4
+ export const PACKAGE_VERSION = pkg.version;
@@ -2,7 +2,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
2
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
3
  import { postMcp } from "../core/client.js";
4
4
  import { TOOL_DEFINITIONS, runTool } from "../core/tools.js";
5
- const PACKAGE_VERSION = "0.1.7";
5
+ import { PACKAGE_VERSION } from "../core/version.js";
6
6
  function textResult(json) {
7
7
  return {
8
8
  content: [{ type: "text", text: json }],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@testchimp/cli",
3
- "version": "0.1.10",
3
+ "version": "0.1.12",
4
4
  "description": "TestChimp CLI and MCP server — coverage, plans, EaaS, TrueCoverage (calls /api/mcp/*)",
5
5
  "type": "module",
6
6
  "main": "dist/bin/testchimp.js",