@testchimp/cli 0.1.29 → 0.1.31
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.
- package/README.md +7 -0
- package/dist/cli/program.js +196 -3
- package/dist/core/agentTraceability.d.ts +15 -1
- package/dist/core/agentTraceability.js +29 -1
- package/dist/core/schemas.d.ts +124 -0
- package/dist/core/schemas.js +94 -2
- package/dist/core/tools.js +162 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -42,10 +42,17 @@ testchimp get-requirement-coverage --branch-name main --help
|
|
|
42
42
|
testchimp create-user-story --platform-file-path plans/stories/foo.md --title "Checkout"
|
|
43
43
|
testchimp list-screen-states --json-input '{}'
|
|
44
44
|
testchimp upsert-screen-states --json-input '{"screenStates":[{"screen":"Checkout","states":["empty","filled"]}]}'
|
|
45
|
+
testchimp list-perf-runs --testchimp-id TC-123 --kind JOURNEY --limit 20
|
|
46
|
+
testchimp get-perf-run --run-id 01ABC --include-raw
|
|
47
|
+
testchimp promote-perf-baseline --run-id 01ABC --env-class CI
|
|
48
|
+
testchimp compare-perf-to-baseline --run-id 01ABC --max-p95-regression-percent 10
|
|
49
|
+
testchimp list-related-perf-tests --scenario-titles "Checkout,Refund"
|
|
50
|
+
testchimp list-api-operation-interactions --operation-id 01XYZ --interaction-type REAL --limit 100
|
|
45
51
|
```
|
|
46
52
|
|
|
47
53
|
- **stdout:** API response JSON.
|
|
48
54
|
- **stderr:** progress for `provision-ephemeral-environment-and-wait` (“still waiting…” polls).
|
|
55
|
+
- **performance gate:** `compare-perf-to-baseline` still prints its JSON response but exits nonzero when `regressed` is `true` (top-level or under `comparison`).
|
|
49
56
|
- **Flags:** default for each subcommand; **`--json-input '<json>'`** or **`--json-input @file.json`** merges over flags (JSON wins on conflicts). Use JSON for nested bodies (e.g. TrueCoverage scopes).
|
|
50
57
|
|
|
51
58
|
## Migration from `testchimp-mcp-client`
|
package/dist/cli/program.js
CHANGED
|
@@ -8,6 +8,13 @@ import { TOOL_DEFINITIONS } from "../core/tools.js";
|
|
|
8
8
|
import { resolveGitHeadSha } from "../core/gitSha.js";
|
|
9
9
|
import { PACKAGE_VERSION } from "../core/version.js";
|
|
10
10
|
export { PACKAGE_VERSION };
|
|
11
|
+
/** True when ComparePerfToBaselineResponse (or a flat PerfComparison) reports a regression. */
|
|
12
|
+
function isPerfComparisonRegressed(parsed) {
|
|
13
|
+
if (!parsed || typeof parsed !== "object")
|
|
14
|
+
return false;
|
|
15
|
+
const body = parsed;
|
|
16
|
+
return body.regressed === true || body.comparison?.regressed === true;
|
|
17
|
+
}
|
|
11
18
|
function parseRecordTypesCsv(raw) {
|
|
12
19
|
return String(raw)
|
|
13
20
|
.split(",")
|
|
@@ -23,9 +30,11 @@ function parseRecordTypesCsv(raw) {
|
|
|
23
30
|
return "smart_test";
|
|
24
31
|
if (s === "manual")
|
|
25
32
|
return "manual";
|
|
33
|
+
if (s === "perf" || s === "perftest" || s === "perf_test")
|
|
34
|
+
return "perf_test";
|
|
26
35
|
return s;
|
|
27
36
|
})
|
|
28
|
-
.filter((v) => v === "smart_test" || v === "manual");
|
|
37
|
+
.filter((v) => v === "smart_test" || v === "manual" || v === "perf_test");
|
|
29
38
|
}
|
|
30
39
|
function parseJsonInput(raw) {
|
|
31
40
|
if (raw == null || raw.trim() === "")
|
|
@@ -55,7 +64,9 @@ function addAgentTraceabilityOptions(cmd) {
|
|
|
55
64
|
.option("--actor-type <type>", "LOCAL_AGENT | CLOUD_AGENT")
|
|
56
65
|
.option("--user-id <id>", "Optional user id")
|
|
57
66
|
.option("--branch-name <name>", "Git branch name")
|
|
58
|
-
.option("--agent-model <model>", "Optional agent model id (agent/CLI only)")
|
|
67
|
+
.option("--agent-model <model>", "Optional agent model id (agent/CLI only)")
|
|
68
|
+
.option("--skill-version <semver>", "TestChimp skill version from SKILL.md frontmatter")
|
|
69
|
+
.option("--cli-version <semver>", "CLI version (defaults to this package version)");
|
|
59
70
|
}
|
|
60
71
|
function collectAgentTraceabilityFlags(opts) {
|
|
61
72
|
const body = {};
|
|
@@ -77,6 +88,10 @@ function collectAgentTraceabilityFlags(opts) {
|
|
|
77
88
|
body.branchName = String(opts.branchName).trim();
|
|
78
89
|
if (opts.agentModel)
|
|
79
90
|
body.agentModel = String(opts.agentModel).trim();
|
|
91
|
+
if (opts.skillVersion)
|
|
92
|
+
body.skillVersion = String(opts.skillVersion).trim();
|
|
93
|
+
if (opts.cliVersion)
|
|
94
|
+
body.cliVersion = String(opts.cliVersion).trim();
|
|
80
95
|
return body;
|
|
81
96
|
}
|
|
82
97
|
function stderrProgress(msg) {
|
|
@@ -126,8 +141,9 @@ export function buildCliProgram() {
|
|
|
126
141
|
.option("--environment <s>")
|
|
127
142
|
.option("--branch-name <s>")
|
|
128
143
|
.option("--platform <web|ios|android>")
|
|
129
|
-
.option("--record-types <csv>", "coverage sources: smart_test,manual (aliases: automated,smarttest)")
|
|
144
|
+
.option("--record-types <csv>", "coverage sources: smart_test,manual,perf_test (aliases: automated,smarttest,perf)")
|
|
130
145
|
.option("--include-manual", "include manual session coverage in addition to automated SmartTests")
|
|
146
|
+
.option("--include-perf", "include PERF_TEST journey coverage in addition to automated SmartTests")
|
|
131
147
|
.option("--manual-only", "manual-only coverage (no automated)")
|
|
132
148
|
.option("--lifecycle-statuses <csv>", "scenario lifecycle allowlist (e.g. ready or draft,ready)")
|
|
133
149
|
.option("--limit <n>", "top N gaps after filter+rank into rankedScenarios (max 200)", (v) => parseInt(v, 10))
|
|
@@ -154,6 +170,9 @@ export function buildCliProgram() {
|
|
|
154
170
|
recordTypes = Array.from(new Set([...(recordTypes ?? ["smart_test"]), "manual"]));
|
|
155
171
|
if (opts.manualOnly)
|
|
156
172
|
recordTypes = ["manual"];
|
|
173
|
+
if (opts.includePerf) {
|
|
174
|
+
recordTypes = Array.from(new Set([...(recordTypes ?? ["smart_test"]), "perf_test"]));
|
|
175
|
+
}
|
|
157
176
|
if (recordTypes && recordTypes.length > 0)
|
|
158
177
|
body.recordTypes = recordTypes;
|
|
159
178
|
if (opts.lifecycleStatuses) {
|
|
@@ -1119,6 +1138,8 @@ export function buildCliProgram() {
|
|
|
1119
1138
|
.option("--user-id <id>", "Optional user id for traceability")
|
|
1120
1139
|
.option("--branch-name <name>", "Git branch")
|
|
1121
1140
|
.option("--agent-model <model>", "Optional agent model id (agent/CLI only)")
|
|
1141
|
+
.option("--skill-version <semver>", "TestChimp skill version from SKILL.md frontmatter")
|
|
1142
|
+
.option("--cli-version <semver>", "CLI version (defaults to this package version)")
|
|
1122
1143
|
.requiredOption("--entity-type <type>", "USER_STORY|SCENARIO|SMART_TEST|POLICY|ISSUE|TEST_EXECUTION|TEST_INVOCATION_BATCH|EXPLORATION|EVENT|WORKFLOW")
|
|
1123
1144
|
.option("--entity-identity <ordinal>", "Project-scoped ordinal id (mutually exclusive with --test-json)")
|
|
1124
1145
|
.option("--test-json <json>", "TestLocator JSON (folderPath/fileName/testSuite/testName)")
|
|
@@ -1144,6 +1165,10 @@ export function buildCliProgram() {
|
|
|
1144
1165
|
body.branchName = String(opts.branchName);
|
|
1145
1166
|
if (opts.agentModel)
|
|
1146
1167
|
body.agentModel = String(opts.agentModel).trim();
|
|
1168
|
+
if (opts.skillVersion)
|
|
1169
|
+
body.skillVersion = String(opts.skillVersion).trim();
|
|
1170
|
+
if (opts.cliVersion)
|
|
1171
|
+
body.cliVersion = String(opts.cliVersion).trim();
|
|
1147
1172
|
if (opts.entityIdentity)
|
|
1148
1173
|
body.entityIdentity = String(opts.entityIdentity);
|
|
1149
1174
|
if (opts.testJson)
|
|
@@ -1290,6 +1315,174 @@ export function buildCliProgram() {
|
|
|
1290
1315
|
const merged = mergeBodies(body, opts.jsonInput);
|
|
1291
1316
|
console.log(await runTool("get-api-operation-detail", merged, { postMcp }));
|
|
1292
1317
|
});
|
|
1318
|
+
program
|
|
1319
|
+
.command("list-perf-runs")
|
|
1320
|
+
.description(TOOL_DEFINITIONS.find((t) => t.kebab === "list-perf-runs").description)
|
|
1321
|
+
.addOption(jsonInputOption())
|
|
1322
|
+
.option("--testchimp-id <id>")
|
|
1323
|
+
.option("--kind <kind>", "JOURNEY | COMPOSITE")
|
|
1324
|
+
.option("--branch-name <name>")
|
|
1325
|
+
.option("--profile <name>")
|
|
1326
|
+
.option("--dataset <name>")
|
|
1327
|
+
.option("--llm-mode <mode>")
|
|
1328
|
+
.option("--environment <name>")
|
|
1329
|
+
.option("--limit <n>", "Maximum results", (v) => Number(v))
|
|
1330
|
+
.option("--offset <n>", "Pagination offset", (v) => Number(v))
|
|
1331
|
+
.action(async (opts) => {
|
|
1332
|
+
const body = {};
|
|
1333
|
+
if (opts.testchimpId)
|
|
1334
|
+
body.testchimpId = String(opts.testchimpId);
|
|
1335
|
+
if (opts.kind)
|
|
1336
|
+
body.kind = String(opts.kind);
|
|
1337
|
+
if (opts.branchName)
|
|
1338
|
+
body.branchName = String(opts.branchName);
|
|
1339
|
+
if (opts.profile)
|
|
1340
|
+
body.profile = String(opts.profile);
|
|
1341
|
+
if (opts.dataset)
|
|
1342
|
+
body.dataset = String(opts.dataset);
|
|
1343
|
+
if (opts.llmMode)
|
|
1344
|
+
body.llmMode = String(opts.llmMode);
|
|
1345
|
+
if (opts.environment)
|
|
1346
|
+
body.environment = String(opts.environment);
|
|
1347
|
+
if (opts.limit != null)
|
|
1348
|
+
body.limit = opts.limit;
|
|
1349
|
+
if (opts.offset != null)
|
|
1350
|
+
body.offset = opts.offset;
|
|
1351
|
+
console.log(await runTool("list-perf-runs", mergeBodies(body, opts.jsonInput), { postMcp }));
|
|
1352
|
+
});
|
|
1353
|
+
program
|
|
1354
|
+
.command("get-perf-run")
|
|
1355
|
+
.description(TOOL_DEFINITIONS.find((t) => t.kebab === "get-perf-run").description)
|
|
1356
|
+
.addOption(jsonInputOption())
|
|
1357
|
+
.option("--run-id <id>")
|
|
1358
|
+
.option("--include-raw", "Include the raw performance payload")
|
|
1359
|
+
.action(async (opts) => {
|
|
1360
|
+
const body = {};
|
|
1361
|
+
if (opts.runId)
|
|
1362
|
+
body.runId = String(opts.runId);
|
|
1363
|
+
if (opts.includeRaw)
|
|
1364
|
+
body.includeRaw = true;
|
|
1365
|
+
console.log(await runTool("get-perf-run", mergeBodies(body, opts.jsonInput), { postMcp }));
|
|
1366
|
+
});
|
|
1367
|
+
program
|
|
1368
|
+
.command("list-perf-baselines")
|
|
1369
|
+
.description(TOOL_DEFINITIONS.find((t) => t.kebab === "list-perf-baselines").description)
|
|
1370
|
+
.addOption(jsonInputOption())
|
|
1371
|
+
.option("--testchimp-id <id>")
|
|
1372
|
+
.option("--limit <n>", "Maximum results", (v) => Number(v))
|
|
1373
|
+
.option("--offset <n>", "Pagination offset", (v) => Number(v))
|
|
1374
|
+
.action(async (opts) => {
|
|
1375
|
+
const body = {};
|
|
1376
|
+
if (opts.testchimpId)
|
|
1377
|
+
body.testchimpId = String(opts.testchimpId);
|
|
1378
|
+
if (opts.limit != null)
|
|
1379
|
+
body.limit = opts.limit;
|
|
1380
|
+
if (opts.offset != null)
|
|
1381
|
+
body.offset = opts.offset;
|
|
1382
|
+
console.log(await runTool("list-perf-baselines", mergeBodies(body, opts.jsonInput), { postMcp }));
|
|
1383
|
+
});
|
|
1384
|
+
addAgentTraceabilityOptions(program
|
|
1385
|
+
.command("promote-perf-baseline")
|
|
1386
|
+
.description(TOOL_DEFINITIONS.find((t) => t.kebab === "promote-perf-baseline").description)
|
|
1387
|
+
.addOption(jsonInputOption())
|
|
1388
|
+
.option("--run-id <id>")
|
|
1389
|
+
.option("--env-class <name>")).action(async (opts) => {
|
|
1390
|
+
const body = {
|
|
1391
|
+
...collectAgentTraceabilityFlags(opts),
|
|
1392
|
+
};
|
|
1393
|
+
if (opts.runId)
|
|
1394
|
+
body.runId = String(opts.runId);
|
|
1395
|
+
if (opts.envClass)
|
|
1396
|
+
body.envClass = String(opts.envClass);
|
|
1397
|
+
console.log(await runTool("promote-perf-baseline", mergeBodies(body, opts.jsonInput), { postMcp }));
|
|
1398
|
+
});
|
|
1399
|
+
program
|
|
1400
|
+
.command("compare-perf-to-baseline")
|
|
1401
|
+
.description(TOOL_DEFINITIONS.find((t) => t.kebab === "compare-perf-to-baseline").description)
|
|
1402
|
+
.addOption(jsonInputOption())
|
|
1403
|
+
.option("--run-id <id>")
|
|
1404
|
+
.option("--testchimp-id <id>")
|
|
1405
|
+
.option("--profile <name>")
|
|
1406
|
+
.option("--dataset <name>")
|
|
1407
|
+
.option("--llm-mode <mode>")
|
|
1408
|
+
.option("--environment <name>")
|
|
1409
|
+
.option("--env-class <name>", "Baseline environment class (required)")
|
|
1410
|
+
.option("--max-p95-regression-percent <n>", "Allowed p95 regression percent", (v) => Number(v))
|
|
1411
|
+
.option("--max-fail-rate-increase <n>", "Allowed fail-rate increase", (v) => Number(v))
|
|
1412
|
+
.action(async (opts) => {
|
|
1413
|
+
const body = {};
|
|
1414
|
+
if (opts.runId)
|
|
1415
|
+
body.runId = String(opts.runId);
|
|
1416
|
+
if (opts.testchimpId)
|
|
1417
|
+
body.testchimpId = String(opts.testchimpId);
|
|
1418
|
+
if (opts.profile)
|
|
1419
|
+
body.profile = String(opts.profile);
|
|
1420
|
+
if (opts.dataset)
|
|
1421
|
+
body.dataset = String(opts.dataset);
|
|
1422
|
+
if (opts.llmMode)
|
|
1423
|
+
body.llmMode = String(opts.llmMode);
|
|
1424
|
+
if (opts.environment)
|
|
1425
|
+
body.environment = String(opts.environment);
|
|
1426
|
+
if (opts.envClass)
|
|
1427
|
+
body.envClass = String(opts.envClass);
|
|
1428
|
+
if (opts.maxP95RegressionPercent != null) {
|
|
1429
|
+
body.maxP95RegressionPercent = opts.maxP95RegressionPercent;
|
|
1430
|
+
}
|
|
1431
|
+
if (opts.maxFailRateIncrease != null)
|
|
1432
|
+
body.maxFailRateIncrease = opts.maxFailRateIncrease;
|
|
1433
|
+
const out = await runTool("compare-perf-to-baseline", mergeBodies(body, opts.jsonInput), { postMcp });
|
|
1434
|
+
// Always print response JSON; gate CI on regressed after stdout flush.
|
|
1435
|
+
console.log(out);
|
|
1436
|
+
try {
|
|
1437
|
+
if (isPerfComparisonRegressed(JSON.parse(out)))
|
|
1438
|
+
process.exitCode = 1;
|
|
1439
|
+
}
|
|
1440
|
+
catch {
|
|
1441
|
+
/* non-JSON responses still printed; leave exit 0 unless runTool threw */
|
|
1442
|
+
}
|
|
1443
|
+
});
|
|
1444
|
+
program
|
|
1445
|
+
.command("list-related-perf-tests")
|
|
1446
|
+
.description(TOOL_DEFINITIONS.find((t) => t.kebab === "list-related-perf-tests").description)
|
|
1447
|
+
.addOption(jsonInputOption())
|
|
1448
|
+
.option("--scenario-titles <csv>", "Comma-separated scenario titles")
|
|
1449
|
+
.option("--testchimp-ids <csv>", "Comma-separated TestChimp ids")
|
|
1450
|
+
.option("--no-include-composites", "Exclude COMPOSITE tests")
|
|
1451
|
+
.option("--limit <n>", "Maximum results (max 100)", (v) => Number(v))
|
|
1452
|
+
.action(async (opts) => {
|
|
1453
|
+
const body = {
|
|
1454
|
+
includeComposites: opts.includeComposites,
|
|
1455
|
+
};
|
|
1456
|
+
if (opts.scenarioTitles) {
|
|
1457
|
+
body.scenarioTitles = String(opts.scenarioTitles).split(",").map((s) => s.trim()).filter(Boolean);
|
|
1458
|
+
}
|
|
1459
|
+
if (opts.testchimpIds) {
|
|
1460
|
+
body.testchimpIds = String(opts.testchimpIds).split(",").map((s) => s.trim()).filter(Boolean);
|
|
1461
|
+
}
|
|
1462
|
+
if (opts.limit != null)
|
|
1463
|
+
body.limit = opts.limit;
|
|
1464
|
+
console.log(await runTool("list-related-perf-tests", mergeBodies(body, opts.jsonInput), { postMcp }));
|
|
1465
|
+
});
|
|
1466
|
+
program
|
|
1467
|
+
.command("list-api-operation-interactions")
|
|
1468
|
+
.description(TOOL_DEFINITIONS.find((t) => t.kebab === "list-api-operation-interactions").description)
|
|
1469
|
+
.addOption(jsonInputOption())
|
|
1470
|
+
.option("--test-id <id>")
|
|
1471
|
+
.option("--operation-id <id>")
|
|
1472
|
+
.option("--interaction-type <type>", "REAL | MOCKED", "REAL")
|
|
1473
|
+
.option("--limit <n>", "Maximum results (max 100)", (v) => Number(v))
|
|
1474
|
+
.action(async (opts) => {
|
|
1475
|
+
const body = {
|
|
1476
|
+
interactionType: opts.interactionType,
|
|
1477
|
+
};
|
|
1478
|
+
if (opts.testId)
|
|
1479
|
+
body.testId = String(opts.testId);
|
|
1480
|
+
if (opts.operationId)
|
|
1481
|
+
body.operationId = String(opts.operationId);
|
|
1482
|
+
if (opts.limit != null)
|
|
1483
|
+
body.limit = opts.limit;
|
|
1484
|
+
console.log(await runTool("list-api-operation-interactions", mergeBodies(body, opts.jsonInput), { postMcp }));
|
|
1485
|
+
});
|
|
1293
1486
|
program.on("--help", () => {
|
|
1294
1487
|
/* default */
|
|
1295
1488
|
});
|
|
@@ -9,9 +9,23 @@ export type AgentTraceabilityFields = {
|
|
|
9
9
|
userId?: string;
|
|
10
10
|
branchName?: string;
|
|
11
11
|
agentModel?: string;
|
|
12
|
+
skillVersion?: string;
|
|
13
|
+
cliVersion?: string;
|
|
12
14
|
/** Nested form (wins over flat when both present and non-empty). */
|
|
13
15
|
agentTraceability?: Record<string, unknown>;
|
|
14
16
|
};
|
|
17
|
+
/**
|
|
18
|
+
* Resolve skill / CLI versions for traceability payloads.
|
|
19
|
+
* CLI version defaults to this package's version; skill version from flag/env only.
|
|
20
|
+
*/
|
|
21
|
+
export declare function resolveToolchainVersions(a: {
|
|
22
|
+
skillVersion?: string;
|
|
23
|
+
cliVersion?: string;
|
|
24
|
+
nested?: Record<string, unknown> | null;
|
|
25
|
+
}): {
|
|
26
|
+
skillVersion?: string;
|
|
27
|
+
cliVersion?: string;
|
|
28
|
+
};
|
|
15
29
|
/**
|
|
16
30
|
* Build camelCase AgentActionTraceability for MCP JSON bodies.
|
|
17
31
|
* Returns undefined unless the caller supplied explicit traceability intent
|
|
@@ -19,7 +33,7 @@ export type AgentTraceabilityFields = {
|
|
|
19
33
|
* For Activity/timeline attachment the server also requires workflowExecutionId
|
|
20
34
|
* (stable Plan ULID for the whole run) — omit it and the mutation still succeeds
|
|
21
35
|
* but no workflow_executions / Activity row is recorded (server does not auto-mint).
|
|
22
|
-
* Auto-fills gitSha / agentModel / userId only after the workflowId bar is met.
|
|
36
|
+
* Auto-fills gitSha / agentModel / userId / cliVersion only after the workflowId bar is met.
|
|
23
37
|
* Non-empty nested `agentTraceability` wins over flat for overlapping keys.
|
|
24
38
|
*/
|
|
25
39
|
export declare function buildAgentTraceabilityPayload(a: AgentTraceabilityFields): Record<string, unknown> | undefined;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { resolveGitHeadSha } from "./gitSha.js";
|
|
2
|
+
import { PACKAGE_VERSION } from "./version.js";
|
|
2
3
|
function nonEmptyString(v) {
|
|
3
4
|
if (v == null)
|
|
4
5
|
return undefined;
|
|
@@ -24,6 +25,10 @@ function hasExplicitTraceabilityIntent(a) {
|
|
|
24
25
|
return true;
|
|
25
26
|
if (nonEmptyString(a.agentModel))
|
|
26
27
|
return true;
|
|
28
|
+
if (nonEmptyString(a.skillVersion))
|
|
29
|
+
return true;
|
|
30
|
+
if (nonEmptyString(a.cliVersion))
|
|
31
|
+
return true;
|
|
27
32
|
if (a.agentTraceability && typeof a.agentTraceability === "object") {
|
|
28
33
|
return Object.keys(a.agentTraceability).some((k) => nonEmptyString(a.agentTraceability[k]) != null);
|
|
29
34
|
}
|
|
@@ -39,6 +44,20 @@ function normalizeActorType(raw) {
|
|
|
39
44
|
return "LOCAL_AGENT";
|
|
40
45
|
return undefined;
|
|
41
46
|
}
|
|
47
|
+
/**
|
|
48
|
+
* Resolve skill / CLI versions for traceability payloads.
|
|
49
|
+
* CLI version defaults to this package's version; skill version from flag/env only.
|
|
50
|
+
*/
|
|
51
|
+
export function resolveToolchainVersions(a) {
|
|
52
|
+
const skillVersion = nonEmptyString(a.nested?.skillVersion) ??
|
|
53
|
+
nonEmptyString(a.skillVersion) ??
|
|
54
|
+
nonEmptyString(process.env.TESTCHIMP_SKILL_VERSION);
|
|
55
|
+
const cliVersion = nonEmptyString(a.nested?.cliVersion) ??
|
|
56
|
+
nonEmptyString(a.cliVersion) ??
|
|
57
|
+
nonEmptyString(process.env.TESTCHIMP_CLI_VERSION) ??
|
|
58
|
+
PACKAGE_VERSION;
|
|
59
|
+
return { skillVersion, cliVersion };
|
|
60
|
+
}
|
|
42
61
|
/**
|
|
43
62
|
* Build camelCase AgentActionTraceability for MCP JSON bodies.
|
|
44
63
|
* Returns undefined unless the caller supplied explicit traceability intent
|
|
@@ -46,7 +65,7 @@ function normalizeActorType(raw) {
|
|
|
46
65
|
* For Activity/timeline attachment the server also requires workflowExecutionId
|
|
47
66
|
* (stable Plan ULID for the whole run) — omit it and the mutation still succeeds
|
|
48
67
|
* but no workflow_executions / Activity row is recorded (server does not auto-mint).
|
|
49
|
-
* Auto-fills gitSha / agentModel / userId only after the workflowId bar is met.
|
|
68
|
+
* Auto-fills gitSha / agentModel / userId / cliVersion only after the workflowId bar is met.
|
|
50
69
|
* Non-empty nested `agentTraceability` wins over flat for overlapping keys.
|
|
51
70
|
*/
|
|
52
71
|
export function buildAgentTraceabilityPayload(a) {
|
|
@@ -72,6 +91,11 @@ export function buildAgentTraceabilityPayload(a) {
|
|
|
72
91
|
const agentModel = nonEmptyString(nested?.agentModel) ??
|
|
73
92
|
nonEmptyString(a.agentModel) ??
|
|
74
93
|
nonEmptyString(process.env.TESTCHIMP_AGENT_MODEL);
|
|
94
|
+
const { skillVersion, cliVersion } = resolveToolchainVersions({
|
|
95
|
+
skillVersion: a.skillVersion,
|
|
96
|
+
cliVersion: a.cliVersion,
|
|
97
|
+
nested,
|
|
98
|
+
});
|
|
75
99
|
// Server requires workflow_id for inline mutation Activity — do not send orphan payloads.
|
|
76
100
|
if (!workflowId) {
|
|
77
101
|
return undefined;
|
|
@@ -94,5 +118,9 @@ export function buildAgentTraceabilityPayload(a) {
|
|
|
94
118
|
out.branchName = branchName;
|
|
95
119
|
if (agentModel)
|
|
96
120
|
out.agentModel = agentModel;
|
|
121
|
+
if (skillVersion)
|
|
122
|
+
out.skillVersion = skillVersion;
|
|
123
|
+
if (cliVersion)
|
|
124
|
+
out.cliVersion = cliVersion;
|
|
97
125
|
return out;
|
|
98
126
|
}
|
package/dist/core/schemas.d.ts
CHANGED
|
@@ -25,8 +25,10 @@ export declare const listCoverageInput: z.ZodObject<{
|
|
|
25
25
|
recordTypes: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
26
26
|
smart_test: "smart_test";
|
|
27
27
|
manual: "manual";
|
|
28
|
+
perf_test: "perf_test";
|
|
28
29
|
SMART_TEST: "SMART_TEST";
|
|
29
30
|
MANUAL: "MANUAL";
|
|
31
|
+
PERF_TEST: "PERF_TEST";
|
|
30
32
|
}>>>;
|
|
31
33
|
scenarioLifecycleStatuses: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
32
34
|
limit: z.ZodOptional<z.ZodNumber>;
|
|
@@ -105,6 +107,8 @@ export declare const agentActionTraceabilitySchema: z.ZodObject<{
|
|
|
105
107
|
userId: z.ZodOptional<z.ZodString>;
|
|
106
108
|
branchName: z.ZodOptional<z.ZodString>;
|
|
107
109
|
agentModel: z.ZodOptional<z.ZodString>;
|
|
110
|
+
skillVersion: z.ZodOptional<z.ZodString>;
|
|
111
|
+
cliVersion: z.ZodOptional<z.ZodString>;
|
|
108
112
|
}, z.core.$strict>;
|
|
109
113
|
/** Flat + nested traceability fields shared by create/update MCP tools. */
|
|
110
114
|
export declare const agentTraceabilityFieldsSchema: z.ZodObject<{
|
|
@@ -122,6 +126,8 @@ export declare const agentTraceabilityFieldsSchema: z.ZodObject<{
|
|
|
122
126
|
userId: z.ZodOptional<z.ZodString>;
|
|
123
127
|
branchName: z.ZodOptional<z.ZodString>;
|
|
124
128
|
agentModel: z.ZodOptional<z.ZodString>;
|
|
129
|
+
skillVersion: z.ZodOptional<z.ZodString>;
|
|
130
|
+
cliVersion: z.ZodOptional<z.ZodString>;
|
|
125
131
|
agentTraceability: z.ZodOptional<z.ZodObject<{
|
|
126
132
|
workflowId: z.ZodOptional<z.ZodString>;
|
|
127
133
|
workflowExecutionId: z.ZodOptional<z.ZodString>;
|
|
@@ -137,6 +143,8 @@ export declare const agentTraceabilityFieldsSchema: z.ZodObject<{
|
|
|
137
143
|
userId: z.ZodOptional<z.ZodString>;
|
|
138
144
|
branchName: z.ZodOptional<z.ZodString>;
|
|
139
145
|
agentModel: z.ZodOptional<z.ZodString>;
|
|
146
|
+
skillVersion: z.ZodOptional<z.ZodString>;
|
|
147
|
+
cliVersion: z.ZodOptional<z.ZodString>;
|
|
140
148
|
}, z.core.$strict>>;
|
|
141
149
|
}, z.core.$strip>;
|
|
142
150
|
export declare const createUserStoryInput: z.ZodObject<{
|
|
@@ -156,6 +164,8 @@ export declare const createUserStoryInput: z.ZodObject<{
|
|
|
156
164
|
userId: z.ZodOptional<z.ZodString>;
|
|
157
165
|
branchName: z.ZodOptional<z.ZodString>;
|
|
158
166
|
agentModel: z.ZodOptional<z.ZodString>;
|
|
167
|
+
skillVersion: z.ZodOptional<z.ZodString>;
|
|
168
|
+
cliVersion: z.ZodOptional<z.ZodString>;
|
|
159
169
|
agentTraceability: z.ZodOptional<z.ZodObject<{
|
|
160
170
|
workflowId: z.ZodOptional<z.ZodString>;
|
|
161
171
|
workflowExecutionId: z.ZodOptional<z.ZodString>;
|
|
@@ -171,6 +181,8 @@ export declare const createUserStoryInput: z.ZodObject<{
|
|
|
171
181
|
userId: z.ZodOptional<z.ZodString>;
|
|
172
182
|
branchName: z.ZodOptional<z.ZodString>;
|
|
173
183
|
agentModel: z.ZodOptional<z.ZodString>;
|
|
184
|
+
skillVersion: z.ZodOptional<z.ZodString>;
|
|
185
|
+
cliVersion: z.ZodOptional<z.ZodString>;
|
|
174
186
|
}, z.core.$strict>>;
|
|
175
187
|
}, z.core.$strip>;
|
|
176
188
|
export declare const createTestScenarioInput: z.ZodObject<{
|
|
@@ -191,6 +203,8 @@ export declare const createTestScenarioInput: z.ZodObject<{
|
|
|
191
203
|
userId: z.ZodOptional<z.ZodString>;
|
|
192
204
|
branchName: z.ZodOptional<z.ZodString>;
|
|
193
205
|
agentModel: z.ZodOptional<z.ZodString>;
|
|
206
|
+
skillVersion: z.ZodOptional<z.ZodString>;
|
|
207
|
+
cliVersion: z.ZodOptional<z.ZodString>;
|
|
194
208
|
agentTraceability: z.ZodOptional<z.ZodObject<{
|
|
195
209
|
workflowId: z.ZodOptional<z.ZodString>;
|
|
196
210
|
workflowExecutionId: z.ZodOptional<z.ZodString>;
|
|
@@ -206,6 +220,8 @@ export declare const createTestScenarioInput: z.ZodObject<{
|
|
|
206
220
|
userId: z.ZodOptional<z.ZodString>;
|
|
207
221
|
branchName: z.ZodOptional<z.ZodString>;
|
|
208
222
|
agentModel: z.ZodOptional<z.ZodString>;
|
|
223
|
+
skillVersion: z.ZodOptional<z.ZodString>;
|
|
224
|
+
cliVersion: z.ZodOptional<z.ZodString>;
|
|
209
225
|
}, z.core.$strict>>;
|
|
210
226
|
}, z.core.$strip>;
|
|
211
227
|
export declare const updatePlanMarkdownInput: z.ZodObject<{
|
|
@@ -224,6 +240,8 @@ export declare const updatePlanMarkdownInput: z.ZodObject<{
|
|
|
224
240
|
userId: z.ZodOptional<z.ZodString>;
|
|
225
241
|
branchName: z.ZodOptional<z.ZodString>;
|
|
226
242
|
agentModel: z.ZodOptional<z.ZodString>;
|
|
243
|
+
skillVersion: z.ZodOptional<z.ZodString>;
|
|
244
|
+
cliVersion: z.ZodOptional<z.ZodString>;
|
|
227
245
|
agentTraceability: z.ZodOptional<z.ZodObject<{
|
|
228
246
|
workflowId: z.ZodOptional<z.ZodString>;
|
|
229
247
|
workflowExecutionId: z.ZodOptional<z.ZodString>;
|
|
@@ -239,6 +257,8 @@ export declare const updatePlanMarkdownInput: z.ZodObject<{
|
|
|
239
257
|
userId: z.ZodOptional<z.ZodString>;
|
|
240
258
|
branchName: z.ZodOptional<z.ZodString>;
|
|
241
259
|
agentModel: z.ZodOptional<z.ZodString>;
|
|
260
|
+
skillVersion: z.ZodOptional<z.ZodString>;
|
|
261
|
+
cliVersion: z.ZodOptional<z.ZodString>;
|
|
242
262
|
}, z.core.$strict>>;
|
|
243
263
|
}, z.core.$strip>;
|
|
244
264
|
export declare const markPlanItemsImplementationDoneInput: z.ZodObject<{
|
|
@@ -297,6 +317,8 @@ export declare const updateIssueStatusInput: z.ZodObject<{
|
|
|
297
317
|
userId: z.ZodOptional<z.ZodString>;
|
|
298
318
|
branchName: z.ZodOptional<z.ZodString>;
|
|
299
319
|
agentModel: z.ZodOptional<z.ZodString>;
|
|
320
|
+
skillVersion: z.ZodOptional<z.ZodString>;
|
|
321
|
+
cliVersion: z.ZodOptional<z.ZodString>;
|
|
300
322
|
agentTraceability: z.ZodOptional<z.ZodObject<{
|
|
301
323
|
workflowId: z.ZodOptional<z.ZodString>;
|
|
302
324
|
workflowExecutionId: z.ZodOptional<z.ZodString>;
|
|
@@ -312,6 +334,8 @@ export declare const updateIssueStatusInput: z.ZodObject<{
|
|
|
312
334
|
userId: z.ZodOptional<z.ZodString>;
|
|
313
335
|
branchName: z.ZodOptional<z.ZodString>;
|
|
314
336
|
agentModel: z.ZodOptional<z.ZodString>;
|
|
337
|
+
skillVersion: z.ZodOptional<z.ZodString>;
|
|
338
|
+
cliVersion: z.ZodOptional<z.ZodString>;
|
|
315
339
|
}, z.core.$strict>>;
|
|
316
340
|
}, z.core.$strip>;
|
|
317
341
|
export declare const createIssueInput: z.ZodObject<{
|
|
@@ -393,6 +417,8 @@ export declare const createIssueInput: z.ZodObject<{
|
|
|
393
417
|
userId: z.ZodOptional<z.ZodString>;
|
|
394
418
|
branchName: z.ZodOptional<z.ZodString>;
|
|
395
419
|
agentModel: z.ZodOptional<z.ZodString>;
|
|
420
|
+
skillVersion: z.ZodOptional<z.ZodString>;
|
|
421
|
+
cliVersion: z.ZodOptional<z.ZodString>;
|
|
396
422
|
agentTraceability: z.ZodOptional<z.ZodObject<{
|
|
397
423
|
workflowId: z.ZodOptional<z.ZodString>;
|
|
398
424
|
workflowExecutionId: z.ZodOptional<z.ZodString>;
|
|
@@ -408,6 +434,8 @@ export declare const createIssueInput: z.ZodObject<{
|
|
|
408
434
|
userId: z.ZodOptional<z.ZodString>;
|
|
409
435
|
branchName: z.ZodOptional<z.ZodString>;
|
|
410
436
|
agentModel: z.ZodOptional<z.ZodString>;
|
|
437
|
+
skillVersion: z.ZodOptional<z.ZodString>;
|
|
438
|
+
cliVersion: z.ZodOptional<z.ZodString>;
|
|
411
439
|
}, z.core.$strict>>;
|
|
412
440
|
}, z.core.$strip>;
|
|
413
441
|
export declare const emptyInput: z.ZodObject<{}, z.core.$strip>;
|
|
@@ -1364,6 +1392,8 @@ export declare const reportAgentActionInput: z.ZodObject<{
|
|
|
1364
1392
|
userId: z.ZodOptional<z.ZodString>;
|
|
1365
1393
|
branchName: z.ZodOptional<z.ZodString>;
|
|
1366
1394
|
agentModel: z.ZodOptional<z.ZodString>;
|
|
1395
|
+
skillVersion: z.ZodOptional<z.ZodString>;
|
|
1396
|
+
cliVersion: z.ZodOptional<z.ZodString>;
|
|
1367
1397
|
traceability: z.ZodOptional<z.ZodObject<{
|
|
1368
1398
|
workflowId: z.ZodOptional<z.ZodString>;
|
|
1369
1399
|
workflowExecutionId: z.ZodOptional<z.ZodString>;
|
|
@@ -1379,6 +1409,8 @@ export declare const reportAgentActionInput: z.ZodObject<{
|
|
|
1379
1409
|
userId: z.ZodOptional<z.ZodString>;
|
|
1380
1410
|
branchName: z.ZodOptional<z.ZodString>;
|
|
1381
1411
|
agentModel: z.ZodOptional<z.ZodString>;
|
|
1412
|
+
skillVersion: z.ZodOptional<z.ZodString>;
|
|
1413
|
+
cliVersion: z.ZodOptional<z.ZodString>;
|
|
1382
1414
|
}, z.core.$strict>>;
|
|
1383
1415
|
entityType: z.ZodEnum<{
|
|
1384
1416
|
SMART_TEST: "SMART_TEST";
|
|
@@ -1465,3 +1497,95 @@ export declare const getApiOperationDetailInput: z.ZodObject<{
|
|
|
1465
1497
|
includeManual: z.ZodOptional<z.ZodBoolean>;
|
|
1466
1498
|
includeRemoved: z.ZodOptional<z.ZodBoolean>;
|
|
1467
1499
|
}, z.core.$strip>;
|
|
1500
|
+
/** Performance run kind persisted by the Phase 2 performance API. */
|
|
1501
|
+
export declare const perfRunKindSchema: z.ZodEnum<{
|
|
1502
|
+
JOURNEY: "JOURNEY";
|
|
1503
|
+
COMPOSITE: "COMPOSITE";
|
|
1504
|
+
}>;
|
|
1505
|
+
export declare const listPerfRunsInput: z.ZodObject<{
|
|
1506
|
+
testchimpId: z.ZodOptional<z.ZodString>;
|
|
1507
|
+
kind: z.ZodOptional<z.ZodEnum<{
|
|
1508
|
+
JOURNEY: "JOURNEY";
|
|
1509
|
+
COMPOSITE: "COMPOSITE";
|
|
1510
|
+
}>>;
|
|
1511
|
+
branchName: z.ZodOptional<z.ZodString>;
|
|
1512
|
+
profile: z.ZodOptional<z.ZodString>;
|
|
1513
|
+
dataset: z.ZodOptional<z.ZodString>;
|
|
1514
|
+
llmMode: z.ZodOptional<z.ZodString>;
|
|
1515
|
+
environment: z.ZodOptional<z.ZodString>;
|
|
1516
|
+
limit: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
|
|
1517
|
+
offset: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
|
|
1518
|
+
}, z.core.$strip>;
|
|
1519
|
+
export declare const getPerfRunInput: z.ZodObject<{
|
|
1520
|
+
runId: z.ZodString;
|
|
1521
|
+
includeRaw: z.ZodOptional<z.ZodBoolean>;
|
|
1522
|
+
}, z.core.$strip>;
|
|
1523
|
+
export declare const listPerfBaselinesInput: z.ZodObject<{
|
|
1524
|
+
testchimpId: z.ZodOptional<z.ZodString>;
|
|
1525
|
+
limit: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
|
|
1526
|
+
offset: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
|
|
1527
|
+
}, z.core.$strip>;
|
|
1528
|
+
export declare const promotePerfBaselineInput: z.ZodObject<{
|
|
1529
|
+
runId: z.ZodString;
|
|
1530
|
+
envClass: z.ZodString;
|
|
1531
|
+
workflowId: z.ZodOptional<z.ZodString>;
|
|
1532
|
+
workflowExecutionId: z.ZodOptional<z.ZodString>;
|
|
1533
|
+
policyFile: z.ZodOptional<z.ZodString>;
|
|
1534
|
+
policyVersion: z.ZodOptional<z.ZodString>;
|
|
1535
|
+
gitSha: z.ZodOptional<z.ZodString>;
|
|
1536
|
+
actorType: z.ZodOptional<z.ZodEnum<{
|
|
1537
|
+
LOCAL_AGENT: "LOCAL_AGENT";
|
|
1538
|
+
CLOUD_AGENT: "CLOUD_AGENT";
|
|
1539
|
+
"local-agent": "local-agent";
|
|
1540
|
+
"cloud-agent": "cloud-agent";
|
|
1541
|
+
}>>;
|
|
1542
|
+
userId: z.ZodOptional<z.ZodString>;
|
|
1543
|
+
branchName: z.ZodOptional<z.ZodString>;
|
|
1544
|
+
agentModel: z.ZodOptional<z.ZodString>;
|
|
1545
|
+
skillVersion: z.ZodOptional<z.ZodString>;
|
|
1546
|
+
cliVersion: z.ZodOptional<z.ZodString>;
|
|
1547
|
+
agentTraceability: z.ZodOptional<z.ZodObject<{
|
|
1548
|
+
workflowId: z.ZodOptional<z.ZodString>;
|
|
1549
|
+
workflowExecutionId: z.ZodOptional<z.ZodString>;
|
|
1550
|
+
policyFile: z.ZodOptional<z.ZodString>;
|
|
1551
|
+
policyVersion: z.ZodOptional<z.ZodString>;
|
|
1552
|
+
gitSha: z.ZodOptional<z.ZodString>;
|
|
1553
|
+
actorType: z.ZodOptional<z.ZodEnum<{
|
|
1554
|
+
LOCAL_AGENT: "LOCAL_AGENT";
|
|
1555
|
+
CLOUD_AGENT: "CLOUD_AGENT";
|
|
1556
|
+
"local-agent": "local-agent";
|
|
1557
|
+
"cloud-agent": "cloud-agent";
|
|
1558
|
+
}>>;
|
|
1559
|
+
userId: z.ZodOptional<z.ZodString>;
|
|
1560
|
+
branchName: z.ZodOptional<z.ZodString>;
|
|
1561
|
+
agentModel: z.ZodOptional<z.ZodString>;
|
|
1562
|
+
skillVersion: z.ZodOptional<z.ZodString>;
|
|
1563
|
+
cliVersion: z.ZodOptional<z.ZodString>;
|
|
1564
|
+
}, z.core.$strict>>;
|
|
1565
|
+
}, z.core.$strip>;
|
|
1566
|
+
export declare const comparePerfToBaselineInput: z.ZodObject<{
|
|
1567
|
+
runId: z.ZodOptional<z.ZodString>;
|
|
1568
|
+
testchimpId: z.ZodOptional<z.ZodString>;
|
|
1569
|
+
profile: z.ZodOptional<z.ZodString>;
|
|
1570
|
+
dataset: z.ZodOptional<z.ZodString>;
|
|
1571
|
+
llmMode: z.ZodOptional<z.ZodString>;
|
|
1572
|
+
environment: z.ZodOptional<z.ZodString>;
|
|
1573
|
+
envClass: z.ZodString;
|
|
1574
|
+
maxP95RegressionPercent: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
|
|
1575
|
+
maxFailRateIncrease: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
|
|
1576
|
+
}, z.core.$strip>;
|
|
1577
|
+
export declare const listRelatedPerfTestsInput: z.ZodObject<{
|
|
1578
|
+
scenarioTitles: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
1579
|
+
testchimpIds: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
1580
|
+
includeComposites: z.ZodDefault<z.ZodBoolean>;
|
|
1581
|
+
limit: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
|
|
1582
|
+
}, z.core.$strip>;
|
|
1583
|
+
export declare const listApiOperationInteractionsInput: z.ZodObject<{
|
|
1584
|
+
testId: z.ZodOptional<z.ZodString>;
|
|
1585
|
+
operationId: z.ZodOptional<z.ZodString>;
|
|
1586
|
+
interactionType: z.ZodDefault<z.ZodEnum<{
|
|
1587
|
+
REAL: "REAL";
|
|
1588
|
+
MOCKED: "MOCKED";
|
|
1589
|
+
}>>;
|
|
1590
|
+
limit: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
|
|
1591
|
+
}, z.core.$strip>;
|
package/dist/core/schemas.js
CHANGED
|
@@ -6,7 +6,14 @@ export const scopeSchema = z
|
|
|
6
6
|
})
|
|
7
7
|
.optional();
|
|
8
8
|
const executionPlatformSchema = z.enum(["web", "ios", "android"]);
|
|
9
|
-
const requirementCoverageRecordTypeSchema = z.enum([
|
|
9
|
+
const requirementCoverageRecordTypeSchema = z.enum([
|
|
10
|
+
"smart_test",
|
|
11
|
+
"manual",
|
|
12
|
+
"perf_test",
|
|
13
|
+
"SMART_TEST",
|
|
14
|
+
"MANUAL",
|
|
15
|
+
"PERF_TEST",
|
|
16
|
+
]);
|
|
10
17
|
export const executionJobDimensionFilterSchema = z.object({
|
|
11
18
|
dimension: z.string().min(1),
|
|
12
19
|
values: z.array(z.string()).min(1),
|
|
@@ -23,7 +30,8 @@ export const listCoverageInput = z.object({
|
|
|
23
30
|
* Which coverage sources to include.
|
|
24
31
|
*
|
|
25
32
|
* Omit for legacy default: SMART_TEST only.
|
|
26
|
-
* When provided, send proto enum names ("SMART_TEST", "MANUAL"
|
|
33
|
+
* When provided, send proto enum names ("SMART_TEST", "MANUAL", "PERF_TEST")
|
|
34
|
+
* or CLI-friendly aliases ("smart_test", "manual", "perf_test").
|
|
27
35
|
*/
|
|
28
36
|
recordTypes: z.array(requirementCoverageRecordTypeSchema).optional(),
|
|
29
37
|
/** Allowlist of scenario lifecycle statuses (e.g. ["ready"] or ["draft","ready"]). Empty/omit = no status filter. */
|
|
@@ -82,6 +90,8 @@ export const agentActionTraceabilitySchema = z
|
|
|
82
90
|
userId: z.string().optional(),
|
|
83
91
|
branchName: z.string().optional(),
|
|
84
92
|
agentModel: z.string().optional(),
|
|
93
|
+
skillVersion: z.string().optional(),
|
|
94
|
+
cliVersion: z.string().optional(),
|
|
85
95
|
})
|
|
86
96
|
.strict();
|
|
87
97
|
/** Flat + nested traceability fields shared by create/update MCP tools. */
|
|
@@ -95,6 +105,8 @@ export const agentTraceabilityFieldsSchema = z.object({
|
|
|
95
105
|
userId: z.string().optional(),
|
|
96
106
|
branchName: z.string().optional(),
|
|
97
107
|
agentModel: z.string().optional(),
|
|
108
|
+
skillVersion: z.string().optional(),
|
|
109
|
+
cliVersion: z.string().optional(),
|
|
98
110
|
agentTraceability: agentActionTraceabilitySchema.optional(),
|
|
99
111
|
});
|
|
100
112
|
export const createUserStoryInput = z.object({
|
|
@@ -687,6 +699,8 @@ export const reportAgentActionInput = z
|
|
|
687
699
|
userId: z.string().optional(),
|
|
688
700
|
branchName: z.string().optional(),
|
|
689
701
|
agentModel: z.string().optional(),
|
|
702
|
+
skillVersion: z.string().optional(),
|
|
703
|
+
cliVersion: z.string().optional(),
|
|
690
704
|
traceability: agentActionTraceabilitySchema.optional(),
|
|
691
705
|
entityType: agentActionEntityTypeSchema,
|
|
692
706
|
/** Project-scoped ordinal id (or explicitly provided execution/batch id). Mutually exclusive with `test`. */
|
|
@@ -842,3 +856,81 @@ export const getApiOperationDetailInput = z
|
|
|
842
856
|
"or --root-file-path/--service-key with --http-method and --path-template",
|
|
843
857
|
});
|
|
844
858
|
});
|
|
859
|
+
/** Performance run kind persisted by the Phase 2 performance API. */
|
|
860
|
+
export const perfRunKindSchema = z.enum(["JOURNEY", "COMPOSITE"]);
|
|
861
|
+
export const listPerfRunsInput = z.object({
|
|
862
|
+
testchimpId: z.string().min(1).optional(),
|
|
863
|
+
kind: perfRunKindSchema.optional(),
|
|
864
|
+
branchName: z.string().min(1).optional(),
|
|
865
|
+
profile: z.string().min(1).optional(),
|
|
866
|
+
dataset: z.string().min(1).optional(),
|
|
867
|
+
llmMode: z.string().min(1).optional(),
|
|
868
|
+
environment: z.string().min(1).optional(),
|
|
869
|
+
limit: z.coerce.number().int().positive().max(100).optional(),
|
|
870
|
+
offset: z.coerce.number().int().nonnegative().optional(),
|
|
871
|
+
});
|
|
872
|
+
export const getPerfRunInput = z.object({
|
|
873
|
+
runId: z.string().min(1),
|
|
874
|
+
includeRaw: z.boolean().optional(),
|
|
875
|
+
});
|
|
876
|
+
export const listPerfBaselinesInput = z.object({
|
|
877
|
+
testchimpId: z.string().min(1).optional(),
|
|
878
|
+
limit: z.coerce.number().int().positive().max(100).optional(),
|
|
879
|
+
offset: z.coerce.number().int().nonnegative().optional(),
|
|
880
|
+
});
|
|
881
|
+
export const promotePerfBaselineInput = z
|
|
882
|
+
.object({
|
|
883
|
+
runId: z.string().min(1),
|
|
884
|
+
envClass: z.string().min(1),
|
|
885
|
+
})
|
|
886
|
+
.merge(agentTraceabilityFieldsSchema);
|
|
887
|
+
export const comparePerfToBaselineInput = z
|
|
888
|
+
.object({
|
|
889
|
+
runId: z.string().min(1).optional(),
|
|
890
|
+
testchimpId: z.string().min(1).optional(),
|
|
891
|
+
profile: z.string().min(1).optional(),
|
|
892
|
+
dataset: z.string().min(1).optional(),
|
|
893
|
+
llmMode: z.string().min(1).optional(),
|
|
894
|
+
environment: z.string().min(1).optional(),
|
|
895
|
+
envClass: z.string().min(1),
|
|
896
|
+
maxP95RegressionPercent: z.coerce.number().nonnegative().optional(),
|
|
897
|
+
maxFailRateIncrease: z.coerce.number().nonnegative().optional(),
|
|
898
|
+
})
|
|
899
|
+
.superRefine((v, ctx) => {
|
|
900
|
+
if (!(v.runId ?? "").trim() && !(v.testchimpId ?? "").trim()) {
|
|
901
|
+
ctx.addIssue({
|
|
902
|
+
code: z.ZodIssueCode.custom,
|
|
903
|
+
message: "Provide runId or testchimpId",
|
|
904
|
+
});
|
|
905
|
+
}
|
|
906
|
+
});
|
|
907
|
+
export const listRelatedPerfTestsInput = z
|
|
908
|
+
.object({
|
|
909
|
+
scenarioTitles: z.array(z.string().min(1)).min(1).optional(),
|
|
910
|
+
testchimpIds: z.array(z.string().min(1)).min(1).optional(),
|
|
911
|
+
includeComposites: z.boolean().default(true),
|
|
912
|
+
limit: z.coerce.number().int().positive().max(100).optional(),
|
|
913
|
+
})
|
|
914
|
+
.superRefine((v, ctx) => {
|
|
915
|
+
if (!v.scenarioTitles?.length && !v.testchimpIds?.length) {
|
|
916
|
+
ctx.addIssue({
|
|
917
|
+
code: z.ZodIssueCode.custom,
|
|
918
|
+
message: "Provide scenarioTitles and/or testchimpIds",
|
|
919
|
+
});
|
|
920
|
+
}
|
|
921
|
+
});
|
|
922
|
+
export const listApiOperationInteractionsInput = z
|
|
923
|
+
.object({
|
|
924
|
+
testId: z.string().min(1).optional(),
|
|
925
|
+
operationId: z.string().min(1).optional(),
|
|
926
|
+
interactionType: z.enum(["REAL", "MOCKED"]).default("REAL"),
|
|
927
|
+
limit: z.coerce.number().int().positive().max(100).optional(),
|
|
928
|
+
})
|
|
929
|
+
.superRefine((v, ctx) => {
|
|
930
|
+
if (!(v.testId ?? "").trim() && !(v.operationId ?? "").trim()) {
|
|
931
|
+
ctx.addIssue({
|
|
932
|
+
code: z.ZodIssueCode.custom,
|
|
933
|
+
message: "Provide testId and/or operationId",
|
|
934
|
+
});
|
|
935
|
+
}
|
|
936
|
+
});
|
package/dist/core/tools.js
CHANGED
|
@@ -2,7 +2,7 @@ import { normalizeScope } from "./normalize.js";
|
|
|
2
2
|
import { runProvisionEphemeralEnvironmentAndWait } from "./ephemeralWait.js";
|
|
3
3
|
import * as S from "./schemas.js";
|
|
4
4
|
import { resolveGitHeadSha } from "./gitSha.js";
|
|
5
|
-
import { buildAgentTraceabilityPayload } from "./agentTraceability.js";
|
|
5
|
+
import { buildAgentTraceabilityPayload, resolveToolchainVersions } from "./agentTraceability.js";
|
|
6
6
|
function platformToProtoEnum(platform) {
|
|
7
7
|
switch (platform) {
|
|
8
8
|
case "ios":
|
|
@@ -51,6 +51,8 @@ function listCoverageBody(args) {
|
|
|
51
51
|
return "MANUAL";
|
|
52
52
|
if (raw === "smart_test")
|
|
53
53
|
return "SMART_TEST";
|
|
54
|
+
if (raw === "perf_test")
|
|
55
|
+
return "PERF_TEST";
|
|
54
56
|
return raw;
|
|
55
57
|
});
|
|
56
58
|
body.recordTypes = normalized;
|
|
@@ -1040,7 +1042,15 @@ export const TOOL_DEFINITIONS = [
|
|
|
1040
1042
|
body.userId = process.env.TESTCHIMP_USER_ID;
|
|
1041
1043
|
if (a.branchName)
|
|
1042
1044
|
body.branchName = a.branchName;
|
|
1043
|
-
// Nested traceability wins for agentModel
|
|
1045
|
+
// Nested traceability wins for agentModel / skillVersion / cliVersion;
|
|
1046
|
+
// fill from flat/env/package when nested omits them.
|
|
1047
|
+
const { skillVersion, cliVersion } = resolveToolchainVersions({
|
|
1048
|
+
skillVersion: a.skillVersion,
|
|
1049
|
+
cliVersion: a.cliVersion,
|
|
1050
|
+
nested: a.traceability && typeof a.traceability === "object"
|
|
1051
|
+
? a.traceability
|
|
1052
|
+
: null,
|
|
1053
|
+
});
|
|
1044
1054
|
if (a.traceability && typeof a.traceability === "object") {
|
|
1045
1055
|
const nested = { ...a.traceability };
|
|
1046
1056
|
const nestedModel = nested.agentModel != null && String(nested.agentModel).trim() !== ""
|
|
@@ -1053,12 +1063,23 @@ export const TOOL_DEFINITIONS = [
|
|
|
1053
1063
|
else if (flatModel) {
|
|
1054
1064
|
nested.agentModel = flatModel;
|
|
1055
1065
|
}
|
|
1066
|
+
if (skillVersion)
|
|
1067
|
+
nested.skillVersion = skillVersion;
|
|
1068
|
+
if (cliVersion)
|
|
1069
|
+
nested.cliVersion = cliVersion;
|
|
1056
1070
|
body.traceability = nested;
|
|
1057
1071
|
}
|
|
1058
1072
|
else {
|
|
1059
1073
|
const model = a.agentModel?.trim() || process.env.TESTCHIMP_AGENT_MODEL?.trim();
|
|
1060
|
-
|
|
1061
|
-
|
|
1074
|
+
const nested = {};
|
|
1075
|
+
if (model)
|
|
1076
|
+
nested.agentModel = model;
|
|
1077
|
+
if (skillVersion)
|
|
1078
|
+
nested.skillVersion = skillVersion;
|
|
1079
|
+
if (cliVersion)
|
|
1080
|
+
nested.cliVersion = cliVersion;
|
|
1081
|
+
if (Object.keys(nested).length > 0) {
|
|
1082
|
+
body.traceability = nested;
|
|
1062
1083
|
}
|
|
1063
1084
|
}
|
|
1064
1085
|
if (a.test) {
|
|
@@ -1222,6 +1243,143 @@ export const TOOL_DEFINITIONS = [
|
|
|
1222
1243
|
return postMcp("/api/mcp/get_api_operation_detail", body);
|
|
1223
1244
|
},
|
|
1224
1245
|
},
|
|
1246
|
+
{
|
|
1247
|
+
kebab: "list-perf-runs",
|
|
1248
|
+
description: "List performance runs, optionally filtered by TestChimp id, JOURNEY/COMPOSITE kind, branch, profile, dataset, LLM mode, or environment.",
|
|
1249
|
+
inputSchema: S.listPerfRunsInput,
|
|
1250
|
+
execute: async (args, { postMcp }) => {
|
|
1251
|
+
const a = args;
|
|
1252
|
+
const body = {};
|
|
1253
|
+
if (a.testchimpId)
|
|
1254
|
+
body.testchimpId = a.testchimpId;
|
|
1255
|
+
if (a.kind)
|
|
1256
|
+
body.kind = a.kind;
|
|
1257
|
+
if (a.branchName)
|
|
1258
|
+
body.branchName = a.branchName;
|
|
1259
|
+
if (a.profile)
|
|
1260
|
+
body.profile = a.profile;
|
|
1261
|
+
if (a.dataset)
|
|
1262
|
+
body.dataset = a.dataset;
|
|
1263
|
+
if (a.llmMode)
|
|
1264
|
+
body.llmMode = a.llmMode;
|
|
1265
|
+
if (a.environment)
|
|
1266
|
+
body.environment = a.environment;
|
|
1267
|
+
if (a.limit != null)
|
|
1268
|
+
body.limit = a.limit;
|
|
1269
|
+
if (a.offset != null)
|
|
1270
|
+
body.offset = a.offset;
|
|
1271
|
+
return postMcp("/api/mcp/list_perf_runs", body);
|
|
1272
|
+
},
|
|
1273
|
+
},
|
|
1274
|
+
{
|
|
1275
|
+
kebab: "get-perf-run",
|
|
1276
|
+
description: "Fetch one performance run by runId; set includeRaw to include its raw payload.",
|
|
1277
|
+
inputSchema: S.getPerfRunInput,
|
|
1278
|
+
execute: async (args, { postMcp }) => {
|
|
1279
|
+
const a = args;
|
|
1280
|
+
return postMcp("/api/mcp/get_perf_run", {
|
|
1281
|
+
runId: a.runId,
|
|
1282
|
+
...(a.includeRaw != null ? { includeRaw: a.includeRaw } : {}),
|
|
1283
|
+
});
|
|
1284
|
+
},
|
|
1285
|
+
},
|
|
1286
|
+
{
|
|
1287
|
+
kebab: "list-perf-baselines",
|
|
1288
|
+
description: "List promoted performance baselines, optionally filtered by TestChimp id.",
|
|
1289
|
+
inputSchema: S.listPerfBaselinesInput,
|
|
1290
|
+
execute: async (args, { postMcp }) => {
|
|
1291
|
+
const a = args;
|
|
1292
|
+
const body = {};
|
|
1293
|
+
if (a.testchimpId)
|
|
1294
|
+
body.testchimpId = a.testchimpId;
|
|
1295
|
+
if (a.limit != null)
|
|
1296
|
+
body.limit = a.limit;
|
|
1297
|
+
if (a.offset != null)
|
|
1298
|
+
body.offset = a.offset;
|
|
1299
|
+
return postMcp("/api/mcp/list_perf_baselines", body);
|
|
1300
|
+
},
|
|
1301
|
+
},
|
|
1302
|
+
{
|
|
1303
|
+
kebab: "promote-perf-baseline",
|
|
1304
|
+
description: "Promote a performance run as the baseline for an environment class. Optional agent traceability records the mutation.",
|
|
1305
|
+
inputSchema: S.promotePerfBaselineInput,
|
|
1306
|
+
execute: async (args, { postMcp }) => {
|
|
1307
|
+
const a = args;
|
|
1308
|
+
const body = {
|
|
1309
|
+
runId: a.runId,
|
|
1310
|
+
envClass: a.envClass,
|
|
1311
|
+
};
|
|
1312
|
+
const trace = buildAgentTraceabilityPayload(a);
|
|
1313
|
+
if (trace)
|
|
1314
|
+
body.agentTraceability = trace;
|
|
1315
|
+
return postMcp("/api/mcp/promote_perf_baseline", body);
|
|
1316
|
+
},
|
|
1317
|
+
},
|
|
1318
|
+
{
|
|
1319
|
+
kebab: "compare-perf-to-baseline",
|
|
1320
|
+
description: "Compare a run (runId) or filtered target (testchimpId plus optional dimensions) to its promoted baseline. " +
|
|
1321
|
+
"envClass is required. Optional thresholds override max p95 regression percent and maximum fail-rate increase.",
|
|
1322
|
+
inputSchema: S.comparePerfToBaselineInput,
|
|
1323
|
+
execute: async (args, { postMcp }) => {
|
|
1324
|
+
const a = args;
|
|
1325
|
+
const body = {};
|
|
1326
|
+
if (a.runId)
|
|
1327
|
+
body.runId = a.runId;
|
|
1328
|
+
if (a.testchimpId)
|
|
1329
|
+
body.testchimpId = a.testchimpId;
|
|
1330
|
+
if (a.profile)
|
|
1331
|
+
body.profile = a.profile;
|
|
1332
|
+
if (a.dataset)
|
|
1333
|
+
body.dataset = a.dataset;
|
|
1334
|
+
if (a.llmMode)
|
|
1335
|
+
body.llmMode = a.llmMode;
|
|
1336
|
+
if (a.environment)
|
|
1337
|
+
body.environment = a.environment;
|
|
1338
|
+
body.envClass = a.envClass;
|
|
1339
|
+
if (a.maxP95RegressionPercent != null)
|
|
1340
|
+
body.maxP95RegressionPercent = a.maxP95RegressionPercent;
|
|
1341
|
+
if (a.maxFailRateIncrease != null)
|
|
1342
|
+
body.maxFailRateIncrease = a.maxFailRateIncrease;
|
|
1343
|
+
return postMcp("/api/mcp/compare_perf_to_baseline", body);
|
|
1344
|
+
},
|
|
1345
|
+
},
|
|
1346
|
+
{
|
|
1347
|
+
kebab: "list-related-perf-tests",
|
|
1348
|
+
description: "Find JOURNEY and, by default, COMPOSITE performance tests related to scenario titles and/or TestChimp ids.",
|
|
1349
|
+
inputSchema: S.listRelatedPerfTestsInput,
|
|
1350
|
+
execute: async (args, { postMcp }) => {
|
|
1351
|
+
const a = args;
|
|
1352
|
+
const body = {
|
|
1353
|
+
includeComposites: a.includeComposites,
|
|
1354
|
+
};
|
|
1355
|
+
if (a.scenarioTitles?.length)
|
|
1356
|
+
body.scenarioTitles = a.scenarioTitles;
|
|
1357
|
+
if (a.testchimpIds?.length)
|
|
1358
|
+
body.testchimpIds = a.testchimpIds;
|
|
1359
|
+
if (a.limit != null)
|
|
1360
|
+
body.limit = a.limit;
|
|
1361
|
+
return postMcp("/api/mcp/list_related_perf_tests", body);
|
|
1362
|
+
},
|
|
1363
|
+
},
|
|
1364
|
+
{
|
|
1365
|
+
kebab: "list-api-operation-interactions",
|
|
1366
|
+
description: "List recorded API operation interactions. Requires testId and/or operationId. " +
|
|
1367
|
+
"Defaults to REAL interactions; limit is capped at 100.",
|
|
1368
|
+
inputSchema: S.listApiOperationInteractionsInput,
|
|
1369
|
+
execute: async (args, { postMcp }) => {
|
|
1370
|
+
const a = args;
|
|
1371
|
+
const body = {
|
|
1372
|
+
interactionType: a.interactionType,
|
|
1373
|
+
};
|
|
1374
|
+
if (a.testId)
|
|
1375
|
+
body.testId = a.testId;
|
|
1376
|
+
if (a.operationId)
|
|
1377
|
+
body.operationId = a.operationId;
|
|
1378
|
+
if (a.limit != null)
|
|
1379
|
+
body.limit = a.limit;
|
|
1380
|
+
return postMcp("/api/mcp/list_api_operation_interactions", body);
|
|
1381
|
+
},
|
|
1382
|
+
},
|
|
1225
1383
|
];
|
|
1226
1384
|
const TOOL_BY_KEBAB = new Map(TOOL_DEFINITIONS.map((t) => [t.kebab, t]));
|
|
1227
1385
|
export function getToolDefinition(kebab) {
|
package/package.json
CHANGED