common-qa-mcp 0.2.0 → 0.4.0

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 (110) hide show
  1. package/README.md +6 -0
  2. package/dist/adapters/factory.d.ts +17 -7
  3. package/dist/adapters/factory.d.ts.map +1 -1
  4. package/dist/adapters/factory.js +44 -7
  5. package/dist/adapters/factory.js.map +1 -1
  6. package/dist/adapters/http.d.ts +50 -0
  7. package/dist/adapters/http.d.ts.map +1 -0
  8. package/dist/adapters/http.js +108 -0
  9. package/dist/adapters/http.js.map +1 -0
  10. package/dist/adapters/remoteMcp/adapter.d.ts +16 -2
  11. package/dist/adapters/remoteMcp/adapter.d.ts.map +1 -1
  12. package/dist/adapters/remoteMcp/adapter.js +34 -5
  13. package/dist/adapters/remoteMcp/adapter.js.map +1 -1
  14. package/dist/adapters/simplifyqa/adapter.d.ts +437 -0
  15. package/dist/adapters/simplifyqa/adapter.d.ts.map +1 -0
  16. package/dist/adapters/simplifyqa/adapter.js +3097 -0
  17. package/dist/adapters/simplifyqa/adapter.js.map +1 -0
  18. package/dist/adapters/simplifyqa/mapper.d.ts +95 -0
  19. package/dist/adapters/simplifyqa/mapper.d.ts.map +1 -0
  20. package/dist/adapters/simplifyqa/mapper.js +858 -0
  21. package/dist/adapters/simplifyqa/mapper.js.map +1 -0
  22. package/dist/adapters/types.d.ts +168 -5
  23. package/dist/adapters/types.d.ts.map +1 -1
  24. package/dist/adapters/walnut/adapter.d.ts +235 -0
  25. package/dist/adapters/walnut/adapter.d.ts.map +1 -0
  26. package/dist/adapters/walnut/adapter.js +1114 -0
  27. package/dist/adapters/walnut/adapter.js.map +1 -0
  28. package/dist/adapters/walnut/mapper.d.ts +30 -9
  29. package/dist/adapters/walnut/mapper.d.ts.map +1 -1
  30. package/dist/adapters/walnut/mapper.js +149 -24
  31. package/dist/adapters/walnut/mapper.js.map +1 -1
  32. package/dist/config.d.ts +38 -14
  33. package/dist/config.d.ts.map +1 -1
  34. package/dist/config.js +73 -19
  35. package/dist/config.js.map +1 -1
  36. package/dist/connection.d.ts +3 -2
  37. package/dist/connection.d.ts.map +1 -1
  38. package/dist/connection.js +44 -15
  39. package/dist/connection.js.map +1 -1
  40. package/dist/domain/types.d.ts +680 -5
  41. package/dist/domain/types.d.ts.map +1 -1
  42. package/dist/drafts/store.d.ts +4 -1
  43. package/dist/drafts/store.d.ts.map +1 -1
  44. package/dist/drafts/store.js +7 -2
  45. package/dist/drafts/store.js.map +1 -1
  46. package/dist/initAgents.d.ts.map +1 -1
  47. package/dist/initAgents.js +48 -18
  48. package/dist/initAgents.js.map +1 -1
  49. package/dist/requestConnection.d.ts +5 -3
  50. package/dist/requestConnection.d.ts.map +1 -1
  51. package/dist/requestConnection.js +11 -5
  52. package/dist/requestConnection.js.map +1 -1
  53. package/dist/server.d.ts.map +1 -1
  54. package/dist/server.js +47 -1
  55. package/dist/server.js.map +1 -1
  56. package/dist/tools/backlog.tools.d.ts +13 -0
  57. package/dist/tools/backlog.tools.d.ts.map +1 -0
  58. package/dist/tools/backlog.tools.js +399 -0
  59. package/dist/tools/backlog.tools.js.map +1 -0
  60. package/dist/tools/connection.tools.js +5 -5
  61. package/dist/tools/connection.tools.js.map +1 -1
  62. package/dist/tools/defects.tools.d.ts +7 -0
  63. package/dist/tools/defects.tools.d.ts.map +1 -0
  64. package/dist/tools/defects.tools.js +82 -0
  65. package/dist/tools/defects.tools.js.map +1 -0
  66. package/dist/tools/discovery.tools.d.ts.map +1 -1
  67. package/dist/tools/discovery.tools.js +951 -43
  68. package/dist/tools/discovery.tools.js.map +1 -1
  69. package/dist/tools/formulas.tools.d.ts +7 -0
  70. package/dist/tools/formulas.tools.d.ts.map +1 -0
  71. package/dist/tools/formulas.tools.js +56 -0
  72. package/dist/tools/formulas.tools.js.map +1 -0
  73. package/dist/tools/heal.tools.d.ts +17 -0
  74. package/dist/tools/heal.tools.d.ts.map +1 -0
  75. package/dist/tools/heal.tools.js +76 -0
  76. package/dist/tools/heal.tools.js.map +1 -0
  77. package/dist/tools/markdown.d.ts +3 -3
  78. package/dist/tools/markdown.d.ts.map +1 -1
  79. package/dist/tools/markdown.js +89 -18
  80. package/dist/tools/markdown.js.map +1 -1
  81. package/dist/tools/objects.tools.d.ts +7 -0
  82. package/dist/tools/objects.tools.d.ts.map +1 -0
  83. package/dist/tools/objects.tools.js +201 -0
  84. package/dist/tools/objects.tools.js.map +1 -0
  85. package/dist/tools/recording.tools.d.ts.map +1 -1
  86. package/dist/tools/recording.tools.js +92 -12
  87. package/dist/tools/recording.tools.js.map +1 -1
  88. package/dist/tools/run.tools.d.ts.map +1 -1
  89. package/dist/tools/run.tools.js +464 -39
  90. package/dist/tools/run.tools.js.map +1 -1
  91. package/dist/tools/schemas.d.ts +21 -4
  92. package/dist/tools/schemas.d.ts.map +1 -1
  93. package/dist/tools/schemas.js +14 -1
  94. package/dist/tools/schemas.js.map +1 -1
  95. package/dist/tools/storySync.tools.d.ts +66 -0
  96. package/dist/tools/storySync.tools.d.ts.map +1 -0
  97. package/dist/tools/storySync.tools.js +213 -0
  98. package/dist/tools/storySync.tools.js.map +1 -0
  99. package/dist/tools/tasks.tools.d.ts +7 -0
  100. package/dist/tools/tasks.tools.d.ts.map +1 -0
  101. package/dist/tools/tasks.tools.js +75 -0
  102. package/dist/tools/tasks.tools.js.map +1 -0
  103. package/dist/tools/testcase.tools.d.ts.map +1 -1
  104. package/dist/tools/testcase.tools.js +162 -101
  105. package/dist/tools/testcase.tools.js.map +1 -1
  106. package/dist/tools/testdata.tools.d.ts +7 -0
  107. package/dist/tools/testdata.tools.d.ts.map +1 -0
  108. package/dist/tools/testdata.tools.js +249 -0
  109. package/dist/tools/testdata.tools.js.map +1 -0
  110. package/package.json +3 -3
@@ -19,7 +19,7 @@ export type Step = {
19
19
  * steps by identity (update in place) and correctly deletes the ones dropped — not fragile
20
20
  * slot-by-number matching. Absent on freshly-inserted steps (the backend then creates them). */
21
21
  sourceId?: string | undefined;
22
- stepType: 'web' | 'api' | 'control_flow' | 'function' | 'database' | 'android' | 'mainframe';
22
+ stepType: 'manual' | 'web' | 'api' | 'control_flow' | 'function' | 'function_end' | 'database' | 'android' | 'mainframe' | 'switch' | 'compare';
23
23
  objectRef?: {
24
24
  id?: string | undefined;
25
25
  name?: string | undefined;
@@ -27,9 +27,15 @@ export type Step = {
27
27
  } | undefined;
28
28
  value?: string | undefined;
29
29
  expectedResult?: string | undefined;
30
+ /** Control-flow marker. `kind` mirrors SQA's raw `stepType` for control rows (IF/ELSE/ELSE_IF/IF_END,
31
+ * WHILE_START/WHILE/WHILE_END, DO/DO_WHILE, FOR_START/FOR_END, LOOP, ITERATOR_START/END,
32
+ * LOOP_ITERATION_START/END, SWITCH_TO_*). Kept as a wide string so a future backend adds don't need
33
+ * a schema change here — the markdown renderer defaults unknown kinds to their raw uppercase name. */
30
34
  controlFlow?: {
31
- kind: 'if' | 'else' | 'if_end' | 'while' | 'while_end';
35
+ kind: string;
32
36
  condition?: Condition | undefined;
37
+ /** Raw ifstring from SQA's `conditions.ifstring` — the human-readable expression as shown in the UI. */
38
+ conditionText?: string | undefined;
33
39
  blockId?: string | undefined;
34
40
  maxIterations?: number | undefined;
35
41
  } | undefined;
@@ -41,6 +47,13 @@ export type Step = {
41
47
  functionCall?: {
42
48
  testCaseId: string;
43
49
  testCaseName?: string | undefined;
50
+ /** SQA function code (e.g. FN_12). Populated by the adapter's FN-name lookup so the
51
+ * markdown renderer can show a human ref instead of a bare numeric id. */
52
+ testCaseCode?: string | undefined;
53
+ /** SQA `fnVersionId` — the specific version of the referenced function pinned by this call. */
54
+ versionId?: string | undefined;
55
+ /** SQA `sharedFnProjectId` — non-null when the FN lives in a different project (shared functions). */
56
+ sharedProjectId?: string | undefined;
44
57
  inputParams?: Record<string, unknown> | undefined;
45
58
  continueOnFailure?: boolean | undefined;
46
59
  } | undefined;
@@ -50,6 +63,14 @@ export type Step = {
50
63
  continueOnFailure?: boolean | undefined;
51
64
  optional?: boolean | undefined;
52
65
  } | undefined;
66
+ /** WEB automation: browser to target for this step. Defaults to CHROME when absent. */
67
+ browserType?: string | undefined;
68
+ /** SQA automation: recorded values for this step, keyed by ACTION PARAMETER NAME (not id).
69
+ * Example: for a launch action, `{ packageName: 'us.zoom.videomeetings', activity: '...' }`.
70
+ * The mapper resolves each name → paramId via get-or-create, then emits SQA's
71
+ * `parameterIds: [<id>...]` + `recordedParam: { <id>: value }` on the step. Populates the
72
+ * default iteration on save. Manual TCs ignore this field. */
73
+ recordedParam?: Record<string, string> | undefined;
53
74
  };
54
75
  export type TestCase = {
55
76
  id?: string | undefined;
@@ -66,29 +87,82 @@ export type TestCase = {
66
87
  tags?: string[] | undefined;
67
88
  steps: Step[];
68
89
  version?: number | undefined;
90
+ /** All non-deleted versions of this TC — populated by adapters that support versioning (SQA).
91
+ * `id` is the version's opaque id (SQA `tcfn_version.id`, a uuid); `name` is the human label
92
+ * ("v1.0"). Walnut/manual-only adapters leave this undefined. */
93
+ versions?: TcVersion[] | undefined;
94
+ /** The version whose steps are surfaced on `steps[]`. Adapters resolve this: caller-provided
95
+ * `versionId` argument > TC's currently-selected version > first entry in `versions[]`. */
96
+ currentVersionId?: string | undefined;
69
97
  /** Default-row test data: param name -> value. Forwarded to the product on save to populate the
70
98
  * datarow of the dataset it auto-creates from the `${param}` tokens in step descriptions, so the
71
99
  * saved test case is executable with data. Optional -- the product also derives it from each
72
100
  * step's single `${param}` + its value. */
73
101
  data?: Record<string, string> | undefined;
102
+ /** SQA automation: execution target (device / browser) for the test case.
103
+ * - WEB: OPTIONAL — omit to let the SQA backend default to Chrome.
104
+ * - ANDROID / IOS: REQUIRED — the mapper refuses the save without one.
105
+ * Wire shape mirrors the SQA `executionPlatform` field on the tcfnObj:
106
+ * `{ id: <deviceSerial|'CHROME'>, name, technologyType: 'ANDROID'|'IOS'|'WEB', type:
107
+ * 'REAL_DEVICE'|'CLOUD_DEVICE'|'NONE', cloudDeviceType? }`. */
108
+ executionPlatform?: {
109
+ id: string;
110
+ name: string;
111
+ technologyType: string;
112
+ type: string;
113
+ cloudDeviceType?: string | undefined;
114
+ } | undefined;
115
+ };
116
+ /** One entry in `TestCase.versions[]`. Fields mirror what SQA's `/tm/testcase/getById` projects onto
117
+ * `versions[]` (tcfn.service.js:1489). `updateVersion` is the optimistic-lock counter, useful when
118
+ * the caller wants to display which version is newest. */
119
+ export type TcVersion = {
120
+ id: string;
121
+ name: string;
122
+ updateVersion?: number | undefined;
123
+ reviewApproveStatus?: string | undefined;
124
+ executionType?: string | undefined;
125
+ /** True when this is the TC's currently-selected version (the one the UI opens by default). */
126
+ isCurrent?: boolean | undefined;
74
127
  };
75
128
  export type TcSummary = {
76
129
  id: string;
130
+ code?: string;
77
131
  title: string;
78
132
  priority: string;
79
133
  status?: string;
80
134
  stepCount?: number;
135
+ technologyType?: string;
136
+ executionType?: string;
137
+ obsolete?: boolean;
81
138
  };
82
139
  export type ProjectSummary = {
83
140
  id: string;
141
+ code?: string;
84
142
  name: string;
85
143
  counts?: Record<string, number> | undefined;
86
144
  };
145
+ /** One raw backend column filter (searchFields protocol) — see `zRawFilter` in tools/schemas.ts. */
146
+ export type RawSearchFilter = {
147
+ column: string;
148
+ value: string | number | boolean | string[] | number[];
149
+ regEx?: boolean | undefined;
150
+ };
87
151
  export type TcQuery = {
88
152
  search?: string;
89
153
  status?: string;
90
154
  limit?: number;
91
155
  offset?: number;
156
+ /** Filter by numeric userId of the creator. Pass "me" and the adapter substitutes cfg.userId. */
157
+ createdBy?: string;
158
+ /** Filter by numeric userId of the last updater. Pass "me" and the adapter substitutes cfg.userId. */
159
+ updatedBy?: string;
160
+ storyId?: string;
161
+ /** Filter to test cases filed under this module (id or business key). SimplifyQA only; ignored on providers without a module tree. */
162
+ moduleId?: string;
163
+ /** True → only obsolete TCs; false → only non-obsolete. Omit to include both. SimplifyQA only. */
164
+ obsolete?: boolean;
165
+ filters?: RawSearchFilter[];
92
166
  };
93
167
  /** A USER STORY (Walnut `user_stories` doc, type 'story'). `key` = the human business key (walnut_key
94
168
  * like US_001, or an external Jira/ADO key). `id` = the Mongo _id (what test cases link to via story_id). */
@@ -113,6 +187,420 @@ export type StoryQuery = {
113
187
  status?: string;
114
188
  limit?: number;
115
189
  offset?: number;
190
+ /** Filter stories that belong to this sprint. Neutral name; SimplifyQA maps it to `userstory.iterationId` server-side. */
191
+ sprintId?: string;
192
+ /** Filter stories that belong to this release (SimplifyQA `userstory.releaseId`). */
193
+ releaseId?: string;
194
+ /** Filter by numeric userId of the creator. Pass "me" and the adapter substitutes cfg.userId. */
195
+ createdBy?: string;
196
+ /** Filter by numeric userId of the last updater. Pass "me" and the adapter substitutes cfg.userId. */
197
+ updatedBy?: string;
198
+ /** Filter by numeric userId of the story owner (`userstory.ownerId`). Pass "me" and the adapter
199
+ * substitutes cfg.userId. Testcases have no owner field — this is story-only. */
200
+ ownerId?: string;
201
+ filters?: RawSearchFilter[];
202
+ };
203
+ export type DefectSummary = {
204
+ id: string;
205
+ code?: string | undefined;
206
+ title: string;
207
+ state?: string | undefined;
208
+ severity?: string | undefined;
209
+ priority?: string | undefined;
210
+ assignedTo?: string[] | undefined;
211
+ tcIds?: string[] | undefined;
212
+ };
213
+ export type DefectQuery = {
214
+ search?: string;
215
+ limit?: number;
216
+ offset?: number;
217
+ tcId?: string;
218
+ storyId?: string;
219
+ /** Exact workflow-state key (e.g. "new"), not the capitalized UI label. */
220
+ state?: string;
221
+ /** Numeric userId of the assignee (array field on the defect). Pass "me" for the caller. */
222
+ assignedTo?: string;
223
+ createdBy?: string;
224
+ filters?: RawSearchFilter[];
225
+ };
226
+ /** A TASK (SimplifyQA `pm.task`) — project-management work item, distinct from a test case or defect. */
227
+ export type TaskSummary = {
228
+ id: string;
229
+ code?: string | undefined;
230
+ title: string;
231
+ state?: string | undefined;
232
+ priority?: string | undefined;
233
+ assignedTo?: string[] | undefined;
234
+ /** Linked defect id, when raised against one. */
235
+ defectId?: string | undefined;
236
+ };
237
+ export type TaskQuery = {
238
+ search?: string;
239
+ limit?: number;
240
+ offset?: number;
241
+ /** Filter to tasks linked to this user story (`userstoryId`). */
242
+ storyId?: string;
243
+ state?: string;
244
+ assignedTo?: string;
245
+ createdBy?: string;
246
+ filters?: RawSearchFilter[];
247
+ };
248
+ /** Fields accepted when CREATING a user story (`POST /pm/userstory`). Neutral shape — the SQA adapter
249
+ * maps `moduleId`/`iterationId`/etc to the SQA payload as-is. `projectId` is filled from the connected
250
+ * project when omitted; `state` and `estimatedEffort` are backend-required. */
251
+ export type StoryInput = {
252
+ name: string;
253
+ state: string;
254
+ estimatedEffort: number;
255
+ projectId?: number | undefined;
256
+ epicId?: number | undefined;
257
+ featureId?: number | undefined;
258
+ moduleId?: number | undefined;
259
+ releaseId?: number | undefined;
260
+ /** SQA `iterationId` — the sprint. */
261
+ iterationId?: number | undefined;
262
+ acceptanceCriteria?: string | undefined;
263
+ description?: string | undefined;
264
+ priority?: string | undefined;
265
+ /** SQA accepts an array of userIds. */
266
+ ownerId?: number[] | undefined;
267
+ tags?: number[] | undefined;
268
+ teamId?: number[] | undefined;
269
+ type?: string | undefined;
270
+ plannedStartDate?: string | undefined;
271
+ plannedEndDate?: string | undefined;
272
+ customFields?: Record<string, unknown> | undefined;
273
+ };
274
+ /** Partial update body for `PUT /pm/userstory/:id`. `updateVersion` is optimistic-concurrency: the
275
+ * server bumps it on every write and rejects stale writes. Pass it back from the last `getStory`. */
276
+ export type StoryUpdate = {
277
+ name?: string | undefined;
278
+ state?: string | undefined;
279
+ estimatedEffort?: number | undefined;
280
+ projectId?: number | undefined;
281
+ epicId?: number | undefined;
282
+ featureId?: number | undefined;
283
+ moduleId?: number | undefined;
284
+ releaseId?: number | undefined;
285
+ iterationId?: number | undefined;
286
+ acceptanceCriteria?: string | undefined;
287
+ description?: string | undefined;
288
+ priority?: string | undefined;
289
+ ownerId?: number[] | undefined;
290
+ tags?: number[] | undefined;
291
+ teamId?: number[] | undefined;
292
+ type?: string | undefined;
293
+ plannedStartDate?: string | undefined;
294
+ plannedEndDate?: string | undefined;
295
+ customFields?: Record<string, unknown> | undefined;
296
+ updateVersion?: number | undefined;
297
+ };
298
+ /** An EPIC (SimplifyQA `pm.epic`). Top of the backlog hierarchy: epic → feature → story. `key` is the
299
+ * human business key (EP_XXX); `id` is the numeric doc id. */
300
+ export type EpicSummary = {
301
+ id: string;
302
+ key?: string | undefined;
303
+ name: string;
304
+ state?: string | undefined;
305
+ };
306
+ export type Epic = EpicSummary & {
307
+ description?: string | undefined;
308
+ estimatedEffort?: number | undefined;
309
+ ownerId?: number | undefined;
310
+ plannedStartDate?: string | undefined;
311
+ plannedEndDate?: string | undefined;
312
+ };
313
+ export type EpicQuery = {
314
+ search?: string;
315
+ state?: string;
316
+ limit?: number;
317
+ offset?: number;
318
+ /** Numeric userId of the creator. Pass "me" and the adapter substitutes cfg.userId. */
319
+ createdBy?: string;
320
+ /** Numeric userId of the last updater. Pass "me" and the adapter substitutes cfg.userId. */
321
+ updatedBy?: string;
322
+ /** Numeric userId of the epic owner. Pass "me" and the adapter substitutes cfg.userId. */
323
+ ownerId?: string;
324
+ };
325
+ /** Fields accepted when CREATING an epic (`POST /pm/epic`). `projectIds` is filled to `[currentProject]`
326
+ * when omitted; all six required fields (name/state/estimatedEffort/plannedStartDate/plannedEndDate/projectIds)
327
+ * must be present before hitting the backend. */
328
+ export type EpicInput = {
329
+ name: string;
330
+ state: string;
331
+ estimatedEffort: number;
332
+ plannedStartDate: string;
333
+ plannedEndDate: string;
334
+ projectIds?: number[] | undefined;
335
+ ownerId?: number | undefined;
336
+ description?: string | undefined;
337
+ tags?: string[] | undefined;
338
+ teamId?: number[] | undefined;
339
+ actualStartDate?: string | undefined;
340
+ actualEndDate?: string | undefined;
341
+ actualEffort?: number | undefined;
342
+ remainingEffort?: number | undefined;
343
+ plannedBudget?: number | undefined;
344
+ customFields?: Record<string, unknown> | undefined;
345
+ };
346
+ export type EpicUpdate = {
347
+ name?: string | undefined;
348
+ state?: string | undefined;
349
+ estimatedEffort?: number | undefined;
350
+ plannedStartDate?: string | undefined;
351
+ plannedEndDate?: string | undefined;
352
+ projectIds?: number[] | undefined;
353
+ ownerId?: number | undefined;
354
+ description?: string | undefined;
355
+ tags?: string[] | undefined;
356
+ teamId?: number[] | undefined;
357
+ actualStartDate?: string | undefined;
358
+ actualEndDate?: string | undefined;
359
+ actualEffort?: number | undefined;
360
+ remainingEffort?: number | undefined;
361
+ plannedBudget?: number | undefined;
362
+ customFields?: Record<string, unknown> | undefined;
363
+ updateVersion?: number | undefined;
364
+ };
365
+ /** A FEATURE (SimplifyQA `pm.feature`). Middle of the backlog hierarchy: epic → feature → story.
366
+ * `key` = business key (FT_XXX). `epicId` links to the parent epic. */
367
+ export type FeatureSummary = {
368
+ id: string;
369
+ key?: string | undefined;
370
+ name: string;
371
+ state?: string | undefined;
372
+ priority?: string | undefined;
373
+ epicId?: string | undefined;
374
+ };
375
+ export type Feature = FeatureSummary & {
376
+ description?: string | undefined;
377
+ estimatedEffort?: number | undefined;
378
+ ownerId?: number | undefined;
379
+ plannedStartDate?: string | undefined;
380
+ plannedEndDate?: string | undefined;
381
+ };
382
+ export type FeatureQuery = {
383
+ search?: string;
384
+ state?: string;
385
+ limit?: number;
386
+ offset?: number;
387
+ /** Filter features under a specific parent epic id. */
388
+ epicId?: string;
389
+ /** Numeric userId of the creator. Pass "me" and the adapter substitutes cfg.userId. */
390
+ createdBy?: string;
391
+ /** Numeric userId of the last updater. Pass "me" and the adapter substitutes cfg.userId. */
392
+ updatedBy?: string;
393
+ /** Numeric userId of the feature owner. Pass "me" and the adapter substitutes cfg.userId. */
394
+ ownerId?: string;
395
+ };
396
+ /** Fields accepted when CREATING a feature (`POST /pm/feature`). Same rules as EpicInput plus optional
397
+ * `epicId` (parent). `state` is optional on the backend for features (unlike epic/story). */
398
+ export type FeatureInput = {
399
+ name: string;
400
+ estimatedEffort: number;
401
+ plannedStartDate: string;
402
+ plannedEndDate: string;
403
+ projectIds?: number[] | undefined;
404
+ epicId?: number | undefined;
405
+ state?: string | undefined;
406
+ priority?: string | undefined;
407
+ ownerId?: number | undefined;
408
+ description?: string | undefined;
409
+ tags?: number[] | undefined;
410
+ teamId?: number[] | undefined;
411
+ actualStartDate?: string | undefined;
412
+ actualEndDate?: string | undefined;
413
+ actualEffort?: number | undefined;
414
+ remainingEffort?: number | undefined;
415
+ customFields?: Record<string, unknown> | undefined;
416
+ };
417
+ export type FeatureUpdate = {
418
+ name?: string | undefined;
419
+ estimatedEffort?: number | undefined;
420
+ plannedStartDate?: string | undefined;
421
+ plannedEndDate?: string | undefined;
422
+ projectIds?: number[] | undefined;
423
+ epicId?: number | undefined;
424
+ state?: string | undefined;
425
+ priority?: string | undefined;
426
+ ownerId?: number | undefined;
427
+ description?: string | undefined;
428
+ tags?: number[] | undefined;
429
+ teamId?: number[] | undefined;
430
+ actualStartDate?: string | undefined;
431
+ actualEndDate?: string | undefined;
432
+ actualEffort?: number | undefined;
433
+ remainingEffort?: number | undefined;
434
+ customFields?: Record<string, unknown> | undefined;
435
+ updateVersion?: number | undefined;
436
+ };
437
+ /** A RELEASE (SimplifyQA `pm.release`). `state` is the release state ("planned", "in-progress", ...). */
438
+ export type ReleaseSummary = {
439
+ id: string;
440
+ name: string;
441
+ state?: string | undefined;
442
+ plannedStartDate?: string | undefined;
443
+ plannedEndDate?: string | undefined;
444
+ };
445
+ export type ReleaseQuery = {
446
+ scope: 'project' | 'all';
447
+ };
448
+ /** A SPRINT (SimplifyQA `pm.sprint`). `releaseId` links to the parent Release. */
449
+ export type SprintSummary = {
450
+ id: string;
451
+ name: string;
452
+ releaseId?: string | undefined;
453
+ state?: string | undefined;
454
+ plannedStartDate?: string | undefined;
455
+ plannedEndDate?: string | undefined;
456
+ };
457
+ export type SprintQuery = {
458
+ releaseId?: string;
459
+ };
460
+ /** A MODULE / folder in the SimplifyQA test-case tree. `parentId` is absent on root nodes. */
461
+ export type ModuleSummary = {
462
+ id: string;
463
+ name: string;
464
+ parentId?: string | undefined;
465
+ };
466
+ /** Full MODULE detail — `list_modules` returns only summary rows; `get_module` returns everything the
467
+ * server persists (description, human-readable code, immediate children, project). */
468
+ export type ModuleDetail = ModuleSummary & {
469
+ code?: string | undefined;
470
+ description?: string | undefined;
471
+ childIds?: number[] | undefined;
472
+ projectId?: string | undefined;
473
+ isRoot?: boolean | undefined;
474
+ };
475
+ /** Input to `createModule`. `isRoot:true` files under the project root (server strips `parentId`);
476
+ * otherwise `parentId` must resolve to an existing module in the same project. */
477
+ export type ModuleCreateInput = {
478
+ name: string;
479
+ projectId: string;
480
+ isRoot: boolean;
481
+ parentId?: string | undefined;
482
+ description?: string | undefined;
483
+ };
484
+ /** Per-id dependency footprint the PATCH /pm/module dry-run returns. Non-empty arrays block delete
485
+ * until the referring rows are moved or removed. */
486
+ export type ModuleDependency = {
487
+ id: number;
488
+ tcArr: number[];
489
+ fnArr: number[];
490
+ parameterArr: number[];
491
+ objArr: number[];
492
+ defectArr: number[];
493
+ usArr: number[];
494
+ };
495
+ /** Result of `deleteModule`. `dryRun:true` → nothing was deleted; `dependencies` names what still
496
+ * references each id. `dryRun:false` → server actually deleted the ids with empty dependencies and
497
+ * silently skipped the rest; `dependencies` still surfaces the skipped-with-refs list for the caller
498
+ * to act on. */
499
+ export type ModuleDeleteResult = {
500
+ dryRun: boolean;
501
+ dependencies: ModuleDependency[];
502
+ };
503
+ /** Input to `deleteVersion`. `kind` toggles the backend `parentType` ('TC'|'FN'); `versionId` is
504
+ * the tcfn_version uuid (from `TestCase.versions[]` / `QaFunction.versions[]`); `versionName` is
505
+ * required by the backend validator even though the delete match doesn't strictly need it. */
506
+ export type VersionDeleteInput = {
507
+ kind: 'tc' | 'fn';
508
+ parentId: string;
509
+ versionId: string;
510
+ versionName: string;
511
+ confirm?: boolean;
512
+ };
513
+ /** TC-version dependency row — matches the payload SQA's dry-run returns for `parentType==='TC'`
514
+ * (tcfnversion.service.js:219). Each `*Arr` maps projectId (as a string key) → array of referring
515
+ * entity ids in that project. Empty maps mean "no refs of this kind". */
516
+ export type TcVersionDep = {
517
+ id: number;
518
+ versionName?: string | undefined;
519
+ defectArr: Record<string, number[]>;
520
+ suiteArr: Record<string, number[]>;
521
+ epArr: Record<string, number[]>;
522
+ scenarioArr: Record<string, number[]>;
523
+ schedulerArr: Record<string, number[]>;
524
+ pipelineArr: Record<string, number[]>;
525
+ workflowArr: Record<string, number[]>;
526
+ };
527
+ /** FN-version dependency row — matches the payload SQA returns for `parentType==='FN'`
528
+ * (tcfnversion.service.js:267). Same {projectId → ids} shape, narrower key set. */
529
+ export type FnVersionDep = {
530
+ id: number;
531
+ tcArr: Record<string, number[]>;
532
+ fnArr: Record<string, number[]>;
533
+ wfArr: Record<string, number[]>;
534
+ };
535
+ /** Result of `deleteVersion`. Two-phase mirrors the backend contract (tcfnversion.service.js:30):
536
+ * - `confirm:false` → `dryRun:true`, `dependencies` non-empty either way (each ref-array in the
537
+ * dep row may be empty maps — a truly-safe delete is when EVERY *Arr is `{}`).
538
+ * - `confirm:true` with empty deps → `dryRun:false`, `deleted:true`, `dependencies` empty.
539
+ * - `confirm:true` with non-empty deps → SERVER REFUSED: `dryRun:false`, `deleted:false`,
540
+ * `dependencies` populated. Caller must inspect the shape, not assume success from confirm:true. */
541
+ export type VersionDeleteResult = {
542
+ dryRun: boolean;
543
+ deleted: boolean;
544
+ dependencies: Array<TcVersionDep | FnVersionDep>;
545
+ /** True when any dependency row still has a non-empty ref map. When `dryRun:true` this means
546
+ * "delete would be refused"; when `dryRun:false` this means "server refused the delete". */
547
+ hasBlockers: boolean;
548
+ };
549
+ /** A reusable FUNCTION (SimplifyQA `tcfnObj` with type='FN'). Distinct from a TC: intended to be
550
+ * called as a nested step from many test cases. `fnType` is the technology (WEB/API/ANDROID/IOS);
551
+ * `executionType` is MANUAL/AUTOMATION; `status` is the review/approve status. */
552
+ export type FunctionSummary = {
553
+ id: string;
554
+ code?: string;
555
+ name: string;
556
+ description?: string | undefined;
557
+ fnType?: string | undefined;
558
+ executionType?: string | undefined;
559
+ stepCount?: number | undefined;
560
+ status?: string | undefined;
561
+ };
562
+ export type QaFunction = {
563
+ id: string;
564
+ code?: string | undefined;
565
+ name: string;
566
+ description?: string | undefined;
567
+ fnType?: string | undefined;
568
+ executionType?: string | undefined;
569
+ status?: string | undefined;
570
+ stepCount?: number | undefined;
571
+ steps: Step[];
572
+ /** Present when the FN has versions (SQA always does). Newest first — same shape as `TestCase.versions`. */
573
+ versions?: TcVersion[] | undefined;
574
+ };
575
+ export type FunctionQuery = {
576
+ search?: string;
577
+ fnType?: string;
578
+ executionType?: string;
579
+ /** Filter to functions filed under this module (id or business key). */
580
+ moduleId?: string;
581
+ /** Numeric userId of the creator. Pass "me" and the adapter substitutes cfg.userId. */
582
+ createdBy?: string;
583
+ /** Numeric userId of the last updater. Pass "me" and the adapter substitutes cfg.userId. */
584
+ updatedBy?: string;
585
+ limit?: number;
586
+ offset?: number;
587
+ };
588
+ /** A USER row from `/pm/user/search` — the identity behind `createdBy` / `updatedBy` on stories &
589
+ * testcases. Use `list_users` to resolve a name → id, then pass that id to `tc_list({createdBy})`. */
590
+ export type UserSummary = {
591
+ id: string;
592
+ name?: string;
593
+ email?: string;
594
+ username?: string;
595
+ status?: string;
596
+ };
597
+ export type UserQuery = {
598
+ search?: string;
599
+ limit?: number;
600
+ offset?: number;
601
+ /** Restrict to users assigned to this project (via projectuserrole). Non-admin callers are
602
+ * already scoped server-side to their accessible projects. */
603
+ projectId?: string;
116
604
  };
117
605
  export type QaObject = {
118
606
  id?: string;
@@ -122,8 +610,10 @@ export type QaObject = {
122
610
  locators: Locator[];
123
611
  };
124
612
  export type ObjectQuery = {
125
- query: string;
613
+ query?: string;
126
614
  pageName?: string;
615
+ limit?: number;
616
+ offset?: number;
127
617
  };
128
618
  export type Suite = {
129
619
  id?: string;
@@ -134,10 +624,12 @@ export type Suite = {
134
624
  order: number;
135
625
  }[];
136
626
  };
627
+ /** `suiteType` is SimplifyQA-only ("MANUAL" | "AUTOMATION"); absent on Walnut. */
137
628
  export type SuiteSummary = {
138
629
  id: string;
139
630
  name: string;
140
631
  memberCount?: number;
632
+ suiteType?: string | undefined;
141
633
  };
142
634
  export type MemberOp = {
143
635
  op: 'add' | 'remove' | 'reorder';
@@ -155,8 +647,15 @@ export type RunOptions = {
155
647
  /** Where to run: 'local' = the connected agent's own browser; 'cloud' = a cloud runner VM.
156
648
  * The client MUST decide this (asking the user when unstated) — there is no safe default. */
157
649
  mode?: 'local' | 'cloud';
650
+ /** For mode:'local' — a specific local agent credential_id to dispatch to (resolved from
651
+ * listLocalAgents). When omitted the adapter auto-picks the acting user's online agent. */
652
+ agentId?: string;
158
653
  /** For mode:'cloud' — the specific online cloud runner to dispatch to (resolved from listCloudRunners). */
159
654
  cloudRunnerId?: string;
655
+ /** REQUIRED for ANDROID/IOS test cases — the target device id (adb serial / emulator name for
656
+ * LOCAL; cloud device name for CLOUD). Enumerate with `android_list_devices`. Ignored for
657
+ * non-mobile tcTypes (WEB / API / MAINFRAME / etc.). */
658
+ deviceId?: string;
160
659
  /** SUITE runs only. Cloud dispatch order across the suite's test cases: 'serial' one-at-a-time,
161
660
  * 'batch'/'dynamic' concurrent (with maxConcurrent). Local is always serial. Default 'serial'. */
162
661
  strategy?: 'serial' | 'batch' | 'dynamic';
@@ -164,18 +663,121 @@ export type RunOptions = {
164
663
  maxConcurrent?: number;
165
664
  /** SUITE runs only — stop dispatching remaining test cases after the first failure. */
166
665
  terminateOnFailure?: boolean;
666
+ /** SimplifyQA project-management tag on the run. Optional — the UI's "Release" picker
667
+ * (from `list_releases`). Sent as numeric `releaseId` on the exec payload; default 0. */
668
+ releaseId?: string;
669
+ /** SimplifyQA project-management tag on the run. Optional — the UI's "Sprint" picker
670
+ * (from `list_sprints`). Sent as numeric `iterationId` on the exec payload; default 0. */
671
+ sprintId?: string;
672
+ /** Override the TC's currently-selected version for this run. Optional — the UI's
673
+ * "Version" chip defaults to the TC's current; pass an id from the TC's `versions[]` to run
674
+ * a different one. Omit to run the current version. */
675
+ versionId?: string;
167
676
  };
168
677
  export type RunRef = {
169
678
  runId: string;
170
679
  };
171
- /** A cloud runner VM registered to the project. `online` is the single flag the run flow gates on. */
680
+ /** A cloud runner VM registered to the project. `online` is the single flag the run flow gates on.
681
+ * `id` (compute_configs._id) drives an IMMEDIATE cloud reserve; `credentialId` (the linked
682
+ * test_runner_vm agent credential) is what a SCHEDULE pins as assigned_agent_credential_id —
683
+ * a different id-space from `id`. */
172
684
  export type CloudRunner = {
173
685
  id: string;
174
686
  name: string;
175
687
  online: boolean;
176
688
  status?: string;
177
689
  os?: string;
690
+ credentialId?: string;
691
+ };
692
+ /** A LOCAL Walnut agent registered to the project. `id` is the agent credential_id (what a LOCAL
693
+ * run/schedule dispatches to). `online` gates whether it can take a run now. `owner` is the person
694
+ * and `host` the machine hostname — shown together (like the product UI) so a user can tell apart
695
+ * several agents owned by the same person (the credential_id alone means nothing to them). */
696
+ export type LocalAgent = {
697
+ id: string;
698
+ name?: string;
699
+ online: boolean;
700
+ status?: string;
701
+ owner?: string;
702
+ host?: string;
178
703
  };
704
+ /** Inputs to createSchedule (POST /api/schedules) — mirrors RunOptions' runner-pick fields plus the
705
+ * schedule cadence. `mode` and `scheduledFor` are required (the backend rejects a schedule with no
706
+ * start time). Manual test cases are not schedulable — the backend surfaces that error. */
707
+ export type ScheduleOptions = {
708
+ /** Where the scheduled run executes: 'local' (a local agent) or 'cloud' (a cloud runner VM). */
709
+ mode: 'local' | 'cloud';
710
+ /** mode:'local' — REQUIRED: the specific local agent credential_id (from listLocalAgents) the
711
+ * schedule fires on. A schedule runs detached from any live session (no "caller's own agent" at
712
+ * fire time), so a local schedule must pin an agent — createSchedule sets execution_mode:'manual'
713
+ * so the backend honors it. */
714
+ agentId?: string;
715
+ /** mode:'cloud' — the specific cloud runner id (compute_configs._id, from listCloudRunners), used
716
+ * only to identify the runner. The actual SCHEDULE pin travels in cloudRunnerCredentialId. */
717
+ cloudRunnerId?: string;
718
+ /** mode:'cloud' — pin a SPECIFIC cloud runner by its agent CREDENTIAL id (CloudRunner.credentialId,
719
+ * NOT cloudRunnerId). The backend validates it as an active test_runner_vm credential and rejects a
720
+ * VM that is offline at create time; omit to let the backend auto-pick a live VM at fire time. */
721
+ cloudRunnerCredentialId?: string;
722
+ browser?: string;
723
+ /** Environment id (Mongo id); only forwarded when it is a 24-hex id, mirroring startRun. */
724
+ environmentId?: string;
725
+ /** Tag the scheduled run with a RELEASE (from list_releases). REQUIRED for suite schedules on
726
+ * SimplifyQA — the UI marks Release with `*` when _parentComponent==='SU'. Sent as numeric
727
+ * releaseId on the schedule payload. */
728
+ releaseId?: string;
729
+ /** Tag the scheduled run with a SPRINT (from list_sprints). REQUIRED for suite schedules on
730
+ * SimplifyQA — mirrors the UI. SQA's underlying column is `iterationId`. */
731
+ sprintId?: string;
732
+ /** REQUIRED — ISO datetime of the first (or only) run. */
733
+ scheduledFor: string;
734
+ /** Recurrence cadence. Default 'once'. */
735
+ scheduleType?: 'once' | 'hourly' | 'daily' | 'weekdays' | 'weekly' | 'monthly';
736
+ /** ISO end date for recurring schedules. */
737
+ endDate?: string;
738
+ /** IANA timezone, default 'UTC'. */
739
+ timezone?: string;
740
+ };
741
+ /** Neutral reference to a created schedule (from POST /api/schedules `data`). */
742
+ export type ScheduleRef = {
743
+ id: string;
744
+ status?: string;
745
+ nextRunAt?: string;
746
+ productUrl?: string;
747
+ };
748
+ /** A schedule as listed for management (GET /api/schedules). `target` names WHAT it runs (a test case
749
+ * or a suite), `agent` is the pinned agent/runner's human name, and `updateVersion` is the optimistic-
750
+ * concurrency token an edit must echo back. */
751
+ export type ScheduleInfo = {
752
+ id: string;
753
+ target: string;
754
+ scheduleType: string;
755
+ status: string;
756
+ active?: boolean;
757
+ executionTarget?: 'local' | 'cloud_runner';
758
+ agent?: string;
759
+ browser?: string;
760
+ nextRunAt?: string;
761
+ scheduledFor?: string;
762
+ timezone?: string;
763
+ updateVersion?: number;
764
+ };
765
+ /** Fields an edit may change (schedule_update). Omitted = leave as-is. Mirrors updateScheduleSchema;
766
+ * `mode:'local'` re-pins via agentId, `mode:'cloud'` via cloudRunnerCredentialId. */
767
+ export type ScheduleUpdate = {
768
+ scheduledFor?: string;
769
+ scheduleType?: 'once' | 'hourly' | 'daily' | 'weekdays' | 'weekly' | 'monthly';
770
+ endDate?: string;
771
+ timezone?: string;
772
+ browser?: string;
773
+ environmentId?: string;
774
+ mode?: 'local' | 'cloud';
775
+ agentId?: string;
776
+ cloudRunnerCredentialId?: string;
777
+ };
778
+ /** State transitions for schedule_control. pause↔resume are reversible; cancel stops the pending/live
779
+ * run; delete (a separate tool) removes the row entirely. */
780
+ export type ScheduleAction = 'pause' | 'resume' | 'cancel';
179
781
  export type RunStatus = {
180
782
  runId: string;
181
783
  state: 'queued' | 'running' | 'passed' | 'failed' | 'stopped' | 'error';
@@ -213,14 +815,87 @@ export type ActionDef = {
213
815
  export type EnvInfo = {
214
816
  id: string;
215
817
  name: string;
818
+ key?: string;
819
+ isDefault?: boolean;
216
820
  };
217
821
  export type DatasetInfo = {
218
822
  id: string;
219
823
  name: string;
220
824
  rowCount?: number;
221
825
  };
826
+ /** Template row for testdata generation. `parameters[i].paramId` is the backend id used when
827
+ * posting new rows; `name` is the human-facing token (e.g. `${username}`); `seed` is the current
828
+ * default value (empty string if unset) — used for regex-based type inference when no override is
829
+ * supplied. `versionId`/`environmentType` are echoed back from the product so a follow-up
830
+ * saveGeneratedIterations call targets the same TC context without a second lookup. */
831
+ export type DefaultIteration = {
832
+ tcId: string;
833
+ versionId: string;
834
+ environmentType: string;
835
+ /** `seed` is already masked for a protected parameter ("*****" / "(empty)") — the real value
836
+ * never leaves the adapter. */
837
+ parameters: Array<{
838
+ paramId: number;
839
+ name: string;
840
+ seed: string;
841
+ protected?: boolean | undefined;
842
+ }>;
843
+ };
844
+ /** Request body for `saveGeneratedIterations`. `rows[i]` is a flat `{paramName: value}` map; the
845
+ * adapter re-keys it to `{paramId: value}` server-side using the template.
846
+ * `formulas` — optional per-column formula assignments applied to EVERY row: the adapter evaluates
847
+ * the formula fresh per row via the product's compute endpoint and stamps both `value` (evaluated)
848
+ * and `formulaValue` (source `=NAME(...)` expression) on the payload cell. A formula wins over an
849
+ * explicit `rows[i]` value for the same param name. */
850
+ export type SaveGeneratedIterations = {
851
+ tcId: string;
852
+ versionId: string;
853
+ environmentType: string;
854
+ rows: Array<Record<string, string>>;
855
+ formulas?: Record<string, FormulaCall> | undefined;
856
+ /** Optional pre-fetched template parameters (from a getDefaultIteration the caller already made).
857
+ * When present the adapter skips its own re-fetch — avoids paying the template + N parameter-name
858
+ * lookups twice per save. Safe to omit; adapter falls back to fetching. */
859
+ parameters?: Array<{
860
+ paramId: number;
861
+ name: string;
862
+ seed: string;
863
+ }> | undefined;
864
+ };
865
+ /** A formula available in the project for testdata generation. `scope` is derived from the formula
866
+ * document: 'default' = customer-wide prefab (FIRST_NAME, RANDOM_EMAIL, …); 'customer' = user-defined
867
+ * formula visible across every project in the customer; 'project' = only in the current project.
868
+ * `signature`/`example` come straight from the formula's stored description. `parameters` names the
869
+ * argument keys (order matters: the adapter serialises calls positionally as `=NAME("a","b")`). */
870
+ export type Formula = {
871
+ name: string;
872
+ uniqueId: string;
873
+ type: 'DEFAULT' | 'CUSTOM';
874
+ scope: 'default' | 'customer' | 'project';
875
+ signature: string;
876
+ details?: string | undefined;
877
+ example?: string | undefined;
878
+ parameters: Array<{
879
+ keyName: string;
880
+ description?: string | undefined;
881
+ dataType?: string | undefined;
882
+ }>;
883
+ };
884
+ /** A model-supplied call to a formula for one testdata column. `args` is name→value keyed by
885
+ * `Formula.parameters[].keyName`; the adapter orders them positionally when building the stored
886
+ * `formulaValue` expression, and passes them as query params to the compute endpoint. */
887
+ export type FormulaCall = {
888
+ name: string;
889
+ args?: Record<string, string> | undefined;
890
+ };
891
+ export type SaveGeneratedIterationsResult = {
892
+ tcId: string;
893
+ inserted: number;
894
+ iterationIds?: string[];
895
+ datasetUrl?: string;
896
+ };
222
897
  export type EntityRef = {
223
- kind: 'testcase' | 'suite' | 'run';
898
+ kind: 'testcase' | 'suite' | 'run' | 'function';
224
899
  id: string;
225
900
  };
226
901
  /** The recording-JOURNAL view of a test case, for journal-first editing. `source:'journal'` = steps