@testchimp/cli 0.1.21 → 0.1.23

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.
@@ -5,6 +5,7 @@ import { DEFAULT_BACKEND, postMcp } from "../core/client.js";
5
5
  import { deepMerge } from "../core/merge.js";
6
6
  import { runTool } from "../core/tools.js";
7
7
  import { TOOL_DEFINITIONS } from "../core/tools.js";
8
+ import { resolveGitHeadSha } from "../core/gitSha.js";
8
9
  import { PACKAGE_VERSION } from "../core/version.js";
9
10
  export { PACKAGE_VERSION };
10
11
  function parseRecordTypesCsv(raw) {
@@ -43,6 +44,41 @@ function mergeBodies(flagBody, jsonInputRaw) {
43
44
  return flagBody;
44
45
  return deepMerge(flagBody, extra);
45
46
  }
47
+ /** Shared agent policy/traceability flags for mutating CRUD commands. */
48
+ function addAgentTraceabilityOptions(cmd) {
49
+ return cmd
50
+ .option("--workflow-id <id>", "Catalog workflow id for agent Activity")
51
+ .option("--workflow-execution-id <ulid>", "Stable ULID for the whole agent run")
52
+ .option("--policy-file <name>", "Policy filename (e.g. run-qa.policy.md)")
53
+ .option("--policy-version <semver>", "Policy version from frontmatter")
54
+ .option("--git-sha <sha>", "Git SHA (defaults to HEAD)")
55
+ .option("--actor-type <type>", "LOCAL_AGENT | CLOUD_AGENT")
56
+ .option("--user-id <id>", "Optional user id")
57
+ .option("--branch-name <name>", "Git branch name")
58
+ .option("--agent-model <model>", "Optional agent model id (agent/CLI only)");
59
+ }
60
+ function collectAgentTraceabilityFlags(opts) {
61
+ const body = {};
62
+ if (opts.workflowId)
63
+ body.workflowId = String(opts.workflowId).trim();
64
+ if (opts.workflowExecutionId)
65
+ body.workflowExecutionId = String(opts.workflowExecutionId).trim();
66
+ if (opts.policyFile)
67
+ body.policyFile = String(opts.policyFile).trim();
68
+ if (opts.policyVersion)
69
+ body.policyVersion = String(opts.policyVersion).trim();
70
+ if (opts.gitSha)
71
+ body.gitSha = String(opts.gitSha).trim();
72
+ if (opts.actorType)
73
+ body.actorType = String(opts.actorType).trim();
74
+ if (opts.userId)
75
+ body.userId = String(opts.userId).trim();
76
+ if (opts.branchName)
77
+ body.branchName = String(opts.branchName).trim();
78
+ if (opts.agentModel)
79
+ body.agentModel = String(opts.agentModel).trim();
80
+ return body;
81
+ }
46
82
  function stderrProgress(msg) {
47
83
  console.error(`[testchimp] ${msg}`);
48
84
  }
@@ -175,48 +211,50 @@ export function buildCliProgram() {
175
211
  const out = await runTool("fetch-execution-report", merged, { postMcp });
176
212
  console.log(out);
177
213
  });
178
- program
214
+ addAgentTraceabilityOptions(program
179
215
  .command("create-user-story")
180
216
  .description(TOOL_DEFINITIONS.find((t) => t.kebab === "create-user-story").description)
181
217
  .addOption(jsonInputOption())
182
218
  .requiredOption("--platform-file-path <path>")
183
- .requiredOption("--title <title>")
184
- .action(async (opts) => {
185
- const body = { platformFilePath: opts.platformFilePath, title: opts.title };
219
+ .requiredOption("--title <title>")).action(async (opts) => {
220
+ const body = {
221
+ platformFilePath: opts.platformFilePath,
222
+ title: opts.title,
223
+ ...collectAgentTraceabilityFlags(opts),
224
+ };
186
225
  const merged = mergeBodies(body, opts.jsonInput);
187
226
  const out = await runTool("create-user-story", merged, { postMcp });
188
227
  console.log(out);
189
228
  });
190
- program
229
+ addAgentTraceabilityOptions(program
191
230
  .command("create-test-scenario")
192
231
  .description(TOOL_DEFINITIONS.find((t) => t.kebab === "create-test-scenario").description)
193
232
  .addOption(jsonInputOption())
194
233
  .requiredOption("--platform-file-path <path>")
195
234
  .requiredOption("--title <title>")
196
- .requiredOption("--user-story-ordinal-id <n>")
197
- .action(async (opts) => {
235
+ .requiredOption("--user-story-ordinal-id <n>")).action(async (opts) => {
198
236
  const body = {
199
237
  platformFilePath: opts.platformFilePath,
200
238
  title: opts.title,
201
239
  userStoryOrdinalId: Number(opts.userStoryOrdinalId),
240
+ ...collectAgentTraceabilityFlags(opts),
202
241
  };
203
242
  const merged = mergeBodies(body, opts.jsonInput);
204
243
  const out = await runTool("create-test-scenario", merged, { postMcp });
205
244
  console.log(out);
206
245
  });
207
- program
246
+ addAgentTraceabilityOptions(program
208
247
  .command("update-user-story")
209
248
  .description(TOOL_DEFINITIONS.find((t) => t.kebab === "update-user-story").description)
210
249
  .addOption(jsonInputOption())
211
250
  .option("--content <markdown>", "full markdown including frontmatter")
212
- .option("--content-file <path>", "read markdown from file")
213
- .action(async (opts) => {
251
+ .option("--content-file <path>", "read markdown from file")).action(async (opts) => {
214
252
  let content = opts.content;
215
253
  if (opts.contentFile)
216
254
  content = await readFile(String(opts.contentFile), "utf8");
217
255
  if (!content)
218
256
  throw new Error("Provide --content or --content-file (or full body via --json-input)");
219
- const body = { content };
257
+ const body = { content, ...collectAgentTraceabilityFlags(opts) };
220
258
  const merged = mergeBodies(body, opts.jsonInput);
221
259
  const out = await runTool("update-user-story", merged, { postMcp });
222
260
  console.log(out);
@@ -285,15 +323,16 @@ export function buildCliProgram() {
285
323
  const out = await runTool("get-issue-details", { issueId: String(merged.issueId).trim() }, { postMcp });
286
324
  console.log(out);
287
325
  });
288
- program
326
+ addAgentTraceabilityOptions(program
289
327
  .command("update-issue-status")
290
328
  .description(TOOL_DEFINITIONS.find((t) => t.kebab === "update-issue-status").description)
291
329
  .addOption(jsonInputOption())
292
330
  .option("--issue-id <id>", "Issue ordinal id (#B-123, B-123, B123, or 123)")
293
331
  .option("--status <status>", "ACTIVE | IGNORED | FIXED | DUPLICATE | IN_PROGRESS_BUG | ARCHIVED_BUG | BLOCKED")
294
- .option("--ignore-reason <reason>", "When status=IGNORED: INTENDED_BEHAVIOUR | INACCURATE_ASSESSMENT | NOT_IMPORTANT")
295
- .action(async (opts) => {
296
- const body = {};
332
+ .option("--ignore-reason <reason>", "When status=IGNORED: INTENDED_BEHAVIOUR | INACCURATE_ASSESSMENT | NOT_IMPORTANT")).action(async (opts) => {
333
+ const body = {
334
+ ...collectAgentTraceabilityFlags(opts),
335
+ };
297
336
  if (opts.issueId)
298
337
  body.issueId = String(opts.issueId).trim();
299
338
  if (opts.status)
@@ -307,16 +346,10 @@ export function buildCliProgram() {
307
346
  if (!merged.status || String(merged.status).trim() === "") {
308
347
  throw new Error("status is required (ACTIVE | IGNORED | FIXED | DUPLICATE | IN_PROGRESS_BUG | ARCHIVED_BUG | BLOCKED)");
309
348
  }
310
- const out = await runTool("update-issue-status", {
311
- issueId: String(merged.issueId).trim(),
312
- status: String(merged.status).trim(),
313
- ...(merged.ignoreReason
314
- ? { ignoreReason: String(merged.ignoreReason).trim() }
315
- : {}),
316
- }, { postMcp });
349
+ const out = await runTool("update-issue-status", merged, { postMcp });
317
350
  console.log(out);
318
351
  });
319
- program
352
+ addAgentTraceabilityOptions(program
320
353
  .command("create-issue")
321
354
  .description(TOOL_DEFINITIONS.find((t) => t.kebab === "create-issue").description)
322
355
  .addOption(jsonInputOption())
@@ -331,9 +364,10 @@ export function buildCliProgram() {
331
364
  .option("--assignee <userId>", "Assignee user id")
332
365
  .option("--labels <csv>", "Comma-separated labels")
333
366
  .option("--source <name>", "External ingest source identifier (stored as label source:<name>)")
334
- .option("--environment <name>", "Environment tag (defaults to QA when omitted)")
335
- .action(async (opts) => {
336
- const body = {};
367
+ .option("--environment <name>", "Environment tag (defaults to QA when omitted)")).action(async (opts) => {
368
+ const body = {
369
+ ...collectAgentTraceabilityFlags(opts),
370
+ };
337
371
  if (opts.title)
338
372
  body.title = String(opts.title).trim();
339
373
  if (opts.description)
@@ -394,18 +428,50 @@ export function buildCliProgram() {
394
428
  console.log(out);
395
429
  });
396
430
  program
431
+ .command("update-plan-items-lifecycle-status")
432
+ .description(TOOL_DEFINITIONS.find((t) => t.kebab === "update-plan-items-lifecycle-status").description)
433
+ .addOption(jsonInputOption())
434
+ .option("--entity-type <type>", "story | scenario")
435
+ .option("--ordinal-id <n>", "numeric US-/TS- ordinal")
436
+ .option("--status <status>", "draft | ready | in progress | blocked | done | archived")
437
+ .action(async (opts) => {
438
+ const body = {};
439
+ if (opts.entityType)
440
+ body.entityType = String(opts.entityType).trim();
441
+ if (opts.ordinalId != null && String(opts.ordinalId).trim() !== "") {
442
+ body.ordinalId = Number(String(opts.ordinalId).trim());
443
+ }
444
+ if (opts.status)
445
+ body.status = String(opts.status).trim();
446
+ const merged = mergeBodies(body, opts.jsonInput);
447
+ if (!merged.entityType || String(merged.entityType).trim() === "") {
448
+ throw new Error("entity-type is required (story | scenario)");
449
+ }
450
+ if (merged.ordinalId == null || !Number.isFinite(merged.ordinalId) || merged.ordinalId <= 0) {
451
+ throw new Error("ordinal-id is required (positive integer)");
452
+ }
453
+ if (!merged.status || String(merged.status).trim() === "") {
454
+ throw new Error("status is required (draft | ready | in progress | blocked | done | archived)");
455
+ }
456
+ const out = await runTool("update-plan-items-lifecycle-status", {
457
+ entityType: String(merged.entityType).trim(),
458
+ ordinalId: merged.ordinalId,
459
+ status: String(merged.status).trim(),
460
+ }, { postMcp });
461
+ console.log(out);
462
+ });
463
+ addAgentTraceabilityOptions(program
397
464
  .command("update-test-scenario")
398
465
  .description(TOOL_DEFINITIONS.find((t) => t.kebab === "update-test-scenario").description)
399
466
  .addOption(jsonInputOption())
400
467
  .option("--content <markdown>")
401
- .option("--content-file <path>")
402
- .action(async (opts) => {
468
+ .option("--content-file <path>")).action(async (opts) => {
403
469
  let content = opts.content;
404
470
  if (opts.contentFile)
405
471
  content = await readFile(String(opts.contentFile), "utf8");
406
472
  if (!content)
407
473
  throw new Error("Provide --content or --content-file (or full body via --json-input)");
408
- const body = { content };
474
+ const body = { content, ...collectAgentTraceabilityFlags(opts) };
409
475
  const merged = mergeBodies(body, opts.jsonInput);
410
476
  const out = await runTool("update-test-scenario", merged, { postMcp });
411
477
  console.log(out);
@@ -904,43 +970,43 @@ export function buildCliProgram() {
904
970
  .addOption(jsonInputOption())
905
971
  .requiredOption("--workflow-id <id>", "Catalog workflow id")
906
972
  .requiredOption("--workflow-execution-id <ulid>", "Stable ULID for the whole run")
907
- .requiredOption("--action-type <type>", "CREATED|UPDATED|DELETED|ANALYZED|ACTION_COMPLETED|ACTION_FAILED")
973
+ .requiredOption("--action-type <type>", "CREATED|UPDATED|DELETED|ANALYZED|IMPLEMENTED|ACTION_COMPLETED|ACTION_FAILED")
908
974
  .option("--policy-file <name>", "Policy filename")
909
975
  .option("--policy-version <semver>", "Policy version from frontmatter")
910
976
  .option("--git-sha <sha>", "Current HEAD sha")
911
977
  .option("--actor-type <type>", "LOCAL_AGENT|CLOUD_AGENT (or local-agent|cloud-agent)")
912
978
  .option("--user-id <id>", "Optional user id for traceability")
913
979
  .option("--branch-name <name>", "Git branch")
914
- .option("--entity-type <type>", "test|story|scenario|issue|workflow|…")
980
+ .option("--agent-model <model>", "Optional agent model id (agent/CLI only)")
981
+ .requiredOption("--entity-type <type>", "USER_STORY|SCENARIO|SMART_TEST|POLICY|ISSUE|TEST_EXECUTION|TEST_INVOCATION_BATCH|EXPLORATION|EVENT|WORKFLOW")
915
982
  .option("--entity-identity <ordinal>", "Project-scoped ordinal id (mutually exclusive with --test-json)")
916
983
  .option("--test-json <json>", "TestLocator JSON (folderPath/fileName/testSuite/testName)")
917
- .option("--detail-json <json>", "Optional detail payload")
918
984
  .action(async (opts) => {
919
985
  const body = {
920
986
  workflowId: String(opts.workflowId),
921
987
  workflowExecutionId: String(opts.workflowExecutionId),
922
988
  actionType: String(opts.actionType),
989
+ entityType: String(opts.entityType),
923
990
  };
924
991
  if (opts.policyFile)
925
992
  body.policyFile = String(opts.policyFile);
926
993
  if (opts.policyVersion)
927
994
  body.policyVersion = String(opts.policyVersion);
928
- if (opts.gitSha)
929
- body.gitSha = String(opts.gitSha);
995
+ const gitSha = resolveGitHeadSha(opts.gitSha ? String(opts.gitSha) : undefined);
996
+ if (gitSha)
997
+ body.gitSha = gitSha;
930
998
  if (opts.actorType)
931
999
  body.actorType = String(opts.actorType);
932
1000
  if (opts.userId)
933
1001
  body.userId = String(opts.userId);
934
1002
  if (opts.branchName)
935
1003
  body.branchName = String(opts.branchName);
936
- if (opts.entityType)
937
- body.entityType = String(opts.entityType);
1004
+ if (opts.agentModel)
1005
+ body.agentModel = String(opts.agentModel).trim();
938
1006
  if (opts.entityIdentity)
939
1007
  body.entityIdentity = String(opts.entityIdentity);
940
1008
  if (opts.testJson)
941
1009
  body.test = JSON.parse(String(opts.testJson));
942
- if (opts.detailJson)
943
- body.detailJson = String(opts.detailJson);
944
1010
  const merged = mergeBodies(body, opts.jsonInput);
945
1011
  console.log(await runTool("report-agent-action", merged, { postMcp }));
946
1012
  });
@@ -0,0 +1,22 @@
1
+ /** Flat CLI/MCP fields that map to AgentActionTraceability. */
2
+ export type AgentTraceabilityFields = {
3
+ workflowId?: string;
4
+ workflowExecutionId?: string;
5
+ policyFile?: string;
6
+ policyVersion?: string;
7
+ gitSha?: string;
8
+ actorType?: string;
9
+ userId?: string;
10
+ branchName?: string;
11
+ agentModel?: string;
12
+ /** Nested form (wins over flat when both present and non-empty). */
13
+ agentTraceability?: Record<string, unknown>;
14
+ };
15
+ /**
16
+ * Build camelCase AgentActionTraceability for MCP JSON bodies.
17
+ * Returns undefined unless the caller supplied explicit traceability intent
18
+ * **and** a non-empty workflowId (server requires workflow_id for inline Activity).
19
+ * Auto-fills gitSha / agentModel / userId only after that bar is met.
20
+ * Non-empty nested `agentTraceability` wins over flat for overlapping keys.
21
+ */
22
+ export declare function buildAgentTraceabilityPayload(a: AgentTraceabilityFields): Record<string, unknown> | undefined;
@@ -0,0 +1,95 @@
1
+ import { resolveGitHeadSha } from "./gitSha.js";
2
+ function nonEmptyString(v) {
3
+ if (v == null)
4
+ return undefined;
5
+ const s = String(v).trim();
6
+ return s === "" ? undefined : s;
7
+ }
8
+ function hasExplicitTraceabilityIntent(a) {
9
+ if (nonEmptyString(a.workflowId))
10
+ return true;
11
+ if (nonEmptyString(a.workflowExecutionId))
12
+ return true;
13
+ if (nonEmptyString(a.policyFile))
14
+ return true;
15
+ if (nonEmptyString(a.policyVersion))
16
+ return true;
17
+ if (nonEmptyString(a.gitSha))
18
+ return true;
19
+ if (nonEmptyString(a.actorType))
20
+ return true;
21
+ if (nonEmptyString(a.userId))
22
+ return true;
23
+ if (nonEmptyString(a.branchName))
24
+ return true;
25
+ if (nonEmptyString(a.agentModel))
26
+ return true;
27
+ if (a.agentTraceability && typeof a.agentTraceability === "object") {
28
+ return Object.keys(a.agentTraceability).some((k) => nonEmptyString(a.agentTraceability[k]) != null);
29
+ }
30
+ return false;
31
+ }
32
+ function normalizeActorType(raw) {
33
+ if (raw == null)
34
+ return undefined;
35
+ const s = String(raw).toUpperCase().replace(/-/g, "_");
36
+ if (s === "CLOUD_AGENT")
37
+ return "CLOUD_AGENT";
38
+ if (s === "LOCAL_AGENT")
39
+ return "LOCAL_AGENT";
40
+ return undefined;
41
+ }
42
+ /**
43
+ * Build camelCase AgentActionTraceability for MCP JSON bodies.
44
+ * Returns undefined unless the caller supplied explicit traceability intent
45
+ * **and** a non-empty workflowId (server requires workflow_id for inline Activity).
46
+ * Auto-fills gitSha / agentModel / userId only after that bar is met.
47
+ * Non-empty nested `agentTraceability` wins over flat for overlapping keys.
48
+ */
49
+ export function buildAgentTraceabilityPayload(a) {
50
+ if (!hasExplicitTraceabilityIntent(a)) {
51
+ return undefined;
52
+ }
53
+ const nested = a.agentTraceability &&
54
+ typeof a.agentTraceability === "object" &&
55
+ Object.keys(a.agentTraceability).some((k) => nonEmptyString(a.agentTraceability[k]) != null)
56
+ ? { ...a.agentTraceability }
57
+ : null;
58
+ const out = {};
59
+ const workflowId = nonEmptyString(nested?.workflowId) ?? nonEmptyString(a.workflowId);
60
+ const workflowExecutionId = nonEmptyString(nested?.workflowExecutionId) ?? nonEmptyString(a.workflowExecutionId);
61
+ const policyFile = nonEmptyString(nested?.policyFile) ?? nonEmptyString(a.policyFile);
62
+ const policyVersion = nonEmptyString(nested?.policyVersion) ?? nonEmptyString(a.policyVersion);
63
+ const gitShaExplicit = nonEmptyString(nested?.gitSha) ?? nonEmptyString(a.gitSha);
64
+ const actorType = normalizeActorType(nested?.actorType) ?? normalizeActorType(a.actorType);
65
+ const userId = nonEmptyString(nested?.userId) ??
66
+ nonEmptyString(a.userId) ??
67
+ nonEmptyString(process.env.TESTCHIMP_USER_ID);
68
+ const branchName = nonEmptyString(nested?.branchName) ?? nonEmptyString(a.branchName);
69
+ const agentModel = nonEmptyString(nested?.agentModel) ??
70
+ nonEmptyString(a.agentModel) ??
71
+ nonEmptyString(process.env.TESTCHIMP_AGENT_MODEL);
72
+ // Server requires workflow_id for inline mutation Activity — do not send orphan payloads.
73
+ if (!workflowId) {
74
+ return undefined;
75
+ }
76
+ out.workflowId = workflowId;
77
+ if (workflowExecutionId)
78
+ out.workflowExecutionId = workflowExecutionId;
79
+ if (policyFile)
80
+ out.policyFile = policyFile;
81
+ if (policyVersion)
82
+ out.policyVersion = policyVersion;
83
+ const gitSha = resolveGitHeadSha(gitShaExplicit);
84
+ if (gitSha)
85
+ out.gitSha = gitSha;
86
+ if (actorType)
87
+ out.actorType = actorType;
88
+ if (userId)
89
+ out.userId = userId;
90
+ if (branchName)
91
+ out.branchName = branchName;
92
+ if (agentModel)
93
+ out.agentModel = agentModel;
94
+ return out;
95
+ }
@@ -0,0 +1,2 @@
1
+ /** Current git HEAD when running in a repo; used when agents omit git_sha on report-agent-action. */
2
+ export declare function resolveGitHeadSha(provided?: string): string | undefined;
@@ -0,0 +1,14 @@
1
+ import { execSync } from "node:child_process";
2
+ /** Current git HEAD when running in a repo; used when agents omit git_sha on report-agent-action. */
3
+ export function resolveGitHeadSha(provided) {
4
+ const trimmed = provided?.trim();
5
+ if (trimmed) {
6
+ return trimmed;
7
+ }
8
+ try {
9
+ return execSync("git rev-parse HEAD", { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }).trim();
10
+ }
11
+ catch {
12
+ return undefined;
13
+ }
14
+ }
@@ -54,22 +54,173 @@ export declare const fetchExecutionReportInput: z.ZodObject<{
54
54
  batchInvocationId: z.ZodOptional<z.ZodString>;
55
55
  jobId: z.ZodOptional<z.ZodString>;
56
56
  }, z.core.$strip>;
57
+ export declare const agentActorTypeSchema: z.ZodEnum<{
58
+ LOCAL_AGENT: "LOCAL_AGENT";
59
+ CLOUD_AGENT: "CLOUD_AGENT";
60
+ "local-agent": "local-agent";
61
+ "cloud-agent": "cloud-agent";
62
+ }>;
63
+ /** Nested AgentActionTraceability (agent_traceability.proto) for mutating MCP CRUDs. */
64
+ export declare const agentActionTraceabilitySchema: z.ZodObject<{
65
+ workflowId: z.ZodOptional<z.ZodString>;
66
+ workflowExecutionId: z.ZodOptional<z.ZodString>;
67
+ policyFile: z.ZodOptional<z.ZodString>;
68
+ policyVersion: z.ZodOptional<z.ZodString>;
69
+ gitSha: z.ZodOptional<z.ZodString>;
70
+ actorType: z.ZodOptional<z.ZodEnum<{
71
+ LOCAL_AGENT: "LOCAL_AGENT";
72
+ CLOUD_AGENT: "CLOUD_AGENT";
73
+ "local-agent": "local-agent";
74
+ "cloud-agent": "cloud-agent";
75
+ }>>;
76
+ userId: z.ZodOptional<z.ZodString>;
77
+ branchName: z.ZodOptional<z.ZodString>;
78
+ agentModel: z.ZodOptional<z.ZodString>;
79
+ }, z.core.$strict>;
80
+ /** Flat + nested traceability fields shared by create/update MCP tools. */
81
+ export declare const agentTraceabilityFieldsSchema: z.ZodObject<{
82
+ workflowId: z.ZodOptional<z.ZodString>;
83
+ workflowExecutionId: z.ZodOptional<z.ZodString>;
84
+ policyFile: z.ZodOptional<z.ZodString>;
85
+ policyVersion: z.ZodOptional<z.ZodString>;
86
+ gitSha: z.ZodOptional<z.ZodString>;
87
+ actorType: z.ZodOptional<z.ZodEnum<{
88
+ LOCAL_AGENT: "LOCAL_AGENT";
89
+ CLOUD_AGENT: "CLOUD_AGENT";
90
+ "local-agent": "local-agent";
91
+ "cloud-agent": "cloud-agent";
92
+ }>>;
93
+ userId: z.ZodOptional<z.ZodString>;
94
+ branchName: z.ZodOptional<z.ZodString>;
95
+ agentModel: z.ZodOptional<z.ZodString>;
96
+ agentTraceability: z.ZodOptional<z.ZodObject<{
97
+ workflowId: z.ZodOptional<z.ZodString>;
98
+ workflowExecutionId: z.ZodOptional<z.ZodString>;
99
+ policyFile: z.ZodOptional<z.ZodString>;
100
+ policyVersion: z.ZodOptional<z.ZodString>;
101
+ gitSha: z.ZodOptional<z.ZodString>;
102
+ actorType: z.ZodOptional<z.ZodEnum<{
103
+ LOCAL_AGENT: "LOCAL_AGENT";
104
+ CLOUD_AGENT: "CLOUD_AGENT";
105
+ "local-agent": "local-agent";
106
+ "cloud-agent": "cloud-agent";
107
+ }>>;
108
+ userId: z.ZodOptional<z.ZodString>;
109
+ branchName: z.ZodOptional<z.ZodString>;
110
+ agentModel: z.ZodOptional<z.ZodString>;
111
+ }, z.core.$strict>>;
112
+ }, z.core.$strip>;
57
113
  export declare const createUserStoryInput: z.ZodObject<{
58
114
  platformFilePath: z.ZodString;
59
115
  title: z.ZodString;
116
+ workflowId: z.ZodOptional<z.ZodString>;
117
+ workflowExecutionId: z.ZodOptional<z.ZodString>;
118
+ policyFile: z.ZodOptional<z.ZodString>;
119
+ policyVersion: z.ZodOptional<z.ZodString>;
120
+ gitSha: z.ZodOptional<z.ZodString>;
121
+ actorType: z.ZodOptional<z.ZodEnum<{
122
+ LOCAL_AGENT: "LOCAL_AGENT";
123
+ CLOUD_AGENT: "CLOUD_AGENT";
124
+ "local-agent": "local-agent";
125
+ "cloud-agent": "cloud-agent";
126
+ }>>;
127
+ userId: z.ZodOptional<z.ZodString>;
128
+ branchName: z.ZodOptional<z.ZodString>;
129
+ agentModel: z.ZodOptional<z.ZodString>;
130
+ agentTraceability: z.ZodOptional<z.ZodObject<{
131
+ workflowId: z.ZodOptional<z.ZodString>;
132
+ workflowExecutionId: z.ZodOptional<z.ZodString>;
133
+ policyFile: z.ZodOptional<z.ZodString>;
134
+ policyVersion: z.ZodOptional<z.ZodString>;
135
+ gitSha: z.ZodOptional<z.ZodString>;
136
+ actorType: z.ZodOptional<z.ZodEnum<{
137
+ LOCAL_AGENT: "LOCAL_AGENT";
138
+ CLOUD_AGENT: "CLOUD_AGENT";
139
+ "local-agent": "local-agent";
140
+ "cloud-agent": "cloud-agent";
141
+ }>>;
142
+ userId: z.ZodOptional<z.ZodString>;
143
+ branchName: z.ZodOptional<z.ZodString>;
144
+ agentModel: z.ZodOptional<z.ZodString>;
145
+ }, z.core.$strict>>;
60
146
  }, z.core.$strip>;
61
147
  export declare const createTestScenarioInput: z.ZodObject<{
62
148
  platformFilePath: z.ZodString;
63
149
  title: z.ZodString;
64
150
  userStoryOrdinalId: z.ZodCoercedNumber<unknown>;
151
+ workflowId: z.ZodOptional<z.ZodString>;
152
+ workflowExecutionId: z.ZodOptional<z.ZodString>;
153
+ policyFile: z.ZodOptional<z.ZodString>;
154
+ policyVersion: z.ZodOptional<z.ZodString>;
155
+ gitSha: z.ZodOptional<z.ZodString>;
156
+ actorType: z.ZodOptional<z.ZodEnum<{
157
+ LOCAL_AGENT: "LOCAL_AGENT";
158
+ CLOUD_AGENT: "CLOUD_AGENT";
159
+ "local-agent": "local-agent";
160
+ "cloud-agent": "cloud-agent";
161
+ }>>;
162
+ userId: z.ZodOptional<z.ZodString>;
163
+ branchName: z.ZodOptional<z.ZodString>;
164
+ agentModel: z.ZodOptional<z.ZodString>;
165
+ agentTraceability: z.ZodOptional<z.ZodObject<{
166
+ workflowId: z.ZodOptional<z.ZodString>;
167
+ workflowExecutionId: z.ZodOptional<z.ZodString>;
168
+ policyFile: z.ZodOptional<z.ZodString>;
169
+ policyVersion: z.ZodOptional<z.ZodString>;
170
+ gitSha: z.ZodOptional<z.ZodString>;
171
+ actorType: z.ZodOptional<z.ZodEnum<{
172
+ LOCAL_AGENT: "LOCAL_AGENT";
173
+ CLOUD_AGENT: "CLOUD_AGENT";
174
+ "local-agent": "local-agent";
175
+ "cloud-agent": "cloud-agent";
176
+ }>>;
177
+ userId: z.ZodOptional<z.ZodString>;
178
+ branchName: z.ZodOptional<z.ZodString>;
179
+ agentModel: z.ZodOptional<z.ZodString>;
180
+ }, z.core.$strict>>;
65
181
  }, z.core.$strip>;
66
182
  export declare const updatePlanMarkdownInput: z.ZodObject<{
67
183
  content: z.ZodString;
184
+ workflowId: z.ZodOptional<z.ZodString>;
185
+ workflowExecutionId: z.ZodOptional<z.ZodString>;
186
+ policyFile: z.ZodOptional<z.ZodString>;
187
+ policyVersion: z.ZodOptional<z.ZodString>;
188
+ gitSha: z.ZodOptional<z.ZodString>;
189
+ actorType: z.ZodOptional<z.ZodEnum<{
190
+ LOCAL_AGENT: "LOCAL_AGENT";
191
+ CLOUD_AGENT: "CLOUD_AGENT";
192
+ "local-agent": "local-agent";
193
+ "cloud-agent": "cloud-agent";
194
+ }>>;
195
+ userId: z.ZodOptional<z.ZodString>;
196
+ branchName: z.ZodOptional<z.ZodString>;
197
+ agentModel: z.ZodOptional<z.ZodString>;
198
+ agentTraceability: z.ZodOptional<z.ZodObject<{
199
+ workflowId: z.ZodOptional<z.ZodString>;
200
+ workflowExecutionId: z.ZodOptional<z.ZodString>;
201
+ policyFile: z.ZodOptional<z.ZodString>;
202
+ policyVersion: z.ZodOptional<z.ZodString>;
203
+ gitSha: z.ZodOptional<z.ZodString>;
204
+ actorType: z.ZodOptional<z.ZodEnum<{
205
+ LOCAL_AGENT: "LOCAL_AGENT";
206
+ CLOUD_AGENT: "CLOUD_AGENT";
207
+ "local-agent": "local-agent";
208
+ "cloud-agent": "cloud-agent";
209
+ }>>;
210
+ userId: z.ZodOptional<z.ZodString>;
211
+ branchName: z.ZodOptional<z.ZodString>;
212
+ agentModel: z.ZodOptional<z.ZodString>;
213
+ }, z.core.$strict>>;
68
214
  }, z.core.$strip>;
69
215
  export declare const markPlanItemsImplementationDoneInput: z.ZodObject<{
70
216
  scenarioOrdinalIds: z.ZodOptional<z.ZodArray<z.ZodCoercedNumber<unknown>>>;
71
217
  userStoryOrdinalIds: z.ZodOptional<z.ZodArray<z.ZodCoercedNumber<unknown>>>;
72
218
  }, z.core.$strip>;
219
+ export declare const updatePlanItemsLifecycleStatusInput: z.ZodObject<{
220
+ entityType: z.ZodString;
221
+ ordinalId: z.ZodCoercedNumber<unknown>;
222
+ status: z.ZodString;
223
+ }, z.core.$strip>;
73
224
  export declare const getUserStoriesInput: z.ZodObject<{
74
225
  userStoryOrdinalIds: z.ZodArray<z.ZodCoercedNumber<unknown>>;
75
226
  }, z.core.$strip>;
@@ -98,6 +249,36 @@ export declare const updateIssueStatusInput: z.ZodObject<{
98
249
  INACCURATE_ASSESSMENT: "INACCURATE_ASSESSMENT";
99
250
  NOT_IMPORTANT: "NOT_IMPORTANT";
100
251
  }>>;
252
+ workflowId: z.ZodOptional<z.ZodString>;
253
+ workflowExecutionId: z.ZodOptional<z.ZodString>;
254
+ policyFile: z.ZodOptional<z.ZodString>;
255
+ policyVersion: z.ZodOptional<z.ZodString>;
256
+ gitSha: z.ZodOptional<z.ZodString>;
257
+ actorType: z.ZodOptional<z.ZodEnum<{
258
+ LOCAL_AGENT: "LOCAL_AGENT";
259
+ CLOUD_AGENT: "CLOUD_AGENT";
260
+ "local-agent": "local-agent";
261
+ "cloud-agent": "cloud-agent";
262
+ }>>;
263
+ userId: z.ZodOptional<z.ZodString>;
264
+ branchName: z.ZodOptional<z.ZodString>;
265
+ agentModel: z.ZodOptional<z.ZodString>;
266
+ agentTraceability: z.ZodOptional<z.ZodObject<{
267
+ workflowId: z.ZodOptional<z.ZodString>;
268
+ workflowExecutionId: z.ZodOptional<z.ZodString>;
269
+ policyFile: z.ZodOptional<z.ZodString>;
270
+ policyVersion: z.ZodOptional<z.ZodString>;
271
+ gitSha: z.ZodOptional<z.ZodString>;
272
+ actorType: z.ZodOptional<z.ZodEnum<{
273
+ LOCAL_AGENT: "LOCAL_AGENT";
274
+ CLOUD_AGENT: "CLOUD_AGENT";
275
+ "local-agent": "local-agent";
276
+ "cloud-agent": "cloud-agent";
277
+ }>>;
278
+ userId: z.ZodOptional<z.ZodString>;
279
+ branchName: z.ZodOptional<z.ZodString>;
280
+ agentModel: z.ZodOptional<z.ZodString>;
281
+ }, z.core.$strict>>;
101
282
  }, z.core.$strip>;
102
283
  export declare const createIssueInput: z.ZodObject<{
103
284
  title: z.ZodString;
@@ -164,6 +345,36 @@ export declare const createIssueInput: z.ZodObject<{
164
345
  environment: z.ZodOptional<z.ZodString>;
165
346
  attachments: z.ZodOptional<z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
166
347
  artifactReference: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
348
+ workflowId: z.ZodOptional<z.ZodString>;
349
+ workflowExecutionId: z.ZodOptional<z.ZodString>;
350
+ policyFile: z.ZodOptional<z.ZodString>;
351
+ policyVersion: z.ZodOptional<z.ZodString>;
352
+ gitSha: z.ZodOptional<z.ZodString>;
353
+ actorType: z.ZodOptional<z.ZodEnum<{
354
+ LOCAL_AGENT: "LOCAL_AGENT";
355
+ CLOUD_AGENT: "CLOUD_AGENT";
356
+ "local-agent": "local-agent";
357
+ "cloud-agent": "cloud-agent";
358
+ }>>;
359
+ userId: z.ZodOptional<z.ZodString>;
360
+ branchName: z.ZodOptional<z.ZodString>;
361
+ agentModel: z.ZodOptional<z.ZodString>;
362
+ agentTraceability: z.ZodOptional<z.ZodObject<{
363
+ workflowId: z.ZodOptional<z.ZodString>;
364
+ workflowExecutionId: z.ZodOptional<z.ZodString>;
365
+ policyFile: z.ZodOptional<z.ZodString>;
366
+ policyVersion: z.ZodOptional<z.ZodString>;
367
+ gitSha: z.ZodOptional<z.ZodString>;
368
+ actorType: z.ZodOptional<z.ZodEnum<{
369
+ LOCAL_AGENT: "LOCAL_AGENT";
370
+ CLOUD_AGENT: "CLOUD_AGENT";
371
+ "local-agent": "local-agent";
372
+ "cloud-agent": "cloud-agent";
373
+ }>>;
374
+ userId: z.ZodOptional<z.ZodString>;
375
+ branchName: z.ZodOptional<z.ZodString>;
376
+ agentModel: z.ZodOptional<z.ZodString>;
377
+ }, z.core.$strict>>;
167
378
  }, z.core.$strip>;
168
379
  export declare const emptyInput: z.ZodObject<{}, z.core.$strip>;
169
380
  export declare const getBranchSpecificEndpointConfigInput: z.ZodObject<{
@@ -730,8 +941,8 @@ export declare const requirementFindingUserStateSchema: z.ZodEnum<{
730
941
  }>;
731
942
  /** RequirementQualityReportSource — proto enum names. */
732
943
  export declare const requirementQualityReportSourceSchema: z.ZodEnum<{
733
- CLOUD: "CLOUD";
734
944
  LOCAL_AGENT: "LOCAL_AGENT";
945
+ CLOUD: "CLOUD";
735
946
  }>;
736
947
  /** SuggestedFixKind — proto enum names. */
737
948
  export declare const suggestedFixKindSchema: z.ZodEnum<{
@@ -859,8 +1070,8 @@ export declare const requirementQualityReportSchema: z.ZodObject<{
859
1070
  title: z.ZodOptional<z.ZodString>;
860
1071
  }, z.core.$strip>>;
861
1072
  source: z.ZodOptional<z.ZodEnum<{
862
- CLOUD: "CLOUD";
863
1073
  LOCAL_AGENT: "LOCAL_AGENT";
1074
+ CLOUD: "CLOUD";
864
1075
  }>>;
865
1076
  metrics: z.ZodOptional<z.ZodObject<{
866
1077
  overall: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
@@ -944,8 +1155,8 @@ export declare const reportRequirementQualityFindingsInput: z.ZodObject<{
944
1155
  title: z.ZodOptional<z.ZodString>;
945
1156
  }, z.core.$strip>>;
946
1157
  source: z.ZodOptional<z.ZodEnum<{
947
- CLOUD: "CLOUD";
948
1158
  LOCAL_AGENT: "LOCAL_AGENT";
1159
+ CLOUD: "CLOUD";
949
1160
  }>>;
950
1161
  metrics: z.ZodOptional<z.ZodObject<{
951
1162
  overall: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
@@ -1015,11 +1226,18 @@ export declare const reportRequirementQualityFindingsInput: z.ZodObject<{
1015
1226
  subjectEntityId: z.ZodOptional<z.ZodString>;
1016
1227
  ordinalId: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
1017
1228
  }, z.core.$strip>;
1018
- export declare const agentActorTypeSchema: z.ZodEnum<{
1019
- LOCAL_AGENT: "LOCAL_AGENT";
1020
- CLOUD_AGENT: "CLOUD_AGENT";
1021
- "local-agent": "local-agent";
1022
- "cloud-agent": "cloud-agent";
1229
+ /** Closed vocabulary for report-agent-action entity_type (agent_workflow.proto AgentActionEntityType). */
1230
+ export declare const agentActionEntityTypeSchema: z.ZodEnum<{
1231
+ SMART_TEST: "SMART_TEST";
1232
+ SCENARIO: "SCENARIO";
1233
+ ISSUE: "ISSUE";
1234
+ TEST_EXECUTION: "TEST_EXECUTION";
1235
+ USER_STORY: "USER_STORY";
1236
+ POLICY: "POLICY";
1237
+ TEST_INVOCATION_BATCH: "TEST_INVOCATION_BATCH";
1238
+ EXPLORATION: "EXPLORATION";
1239
+ EVENT: "EVENT";
1240
+ WORKFLOW: "WORKFLOW";
1023
1241
  }>;
1024
1242
  export declare const agentActionTypeSchema: z.ZodEnum<{
1025
1243
  failed: "failed";
@@ -1029,6 +1247,7 @@ export declare const agentActionTypeSchema: z.ZodEnum<{
1029
1247
  ANALYZED: "ANALYZED";
1030
1248
  ACTION_COMPLETED: "ACTION_COMPLETED";
1031
1249
  ACTION_FAILED: "ACTION_FAILED";
1250
+ IMPLEMENTED: "IMPLEMENTED";
1032
1251
  created: "created";
1033
1252
  updated: "updated";
1034
1253
  deleted: "deleted";
@@ -1036,6 +1255,7 @@ export declare const agentActionTypeSchema: z.ZodEnum<{
1036
1255
  completed: "completed";
1037
1256
  action_completed: "action_completed";
1038
1257
  action_failed: "action_failed";
1258
+ implemented: "implemented";
1039
1259
  }>;
1040
1260
  export declare const reportAgentActionInput: z.ZodObject<{
1041
1261
  workflowId: z.ZodString;
@@ -1051,7 +1271,35 @@ export declare const reportAgentActionInput: z.ZodObject<{
1051
1271
  }>>;
1052
1272
  userId: z.ZodOptional<z.ZodString>;
1053
1273
  branchName: z.ZodOptional<z.ZodString>;
1054
- entityType: z.ZodOptional<z.ZodString>;
1274
+ agentModel: z.ZodOptional<z.ZodString>;
1275
+ traceability: z.ZodOptional<z.ZodObject<{
1276
+ workflowId: z.ZodOptional<z.ZodString>;
1277
+ workflowExecutionId: z.ZodOptional<z.ZodString>;
1278
+ policyFile: z.ZodOptional<z.ZodString>;
1279
+ policyVersion: z.ZodOptional<z.ZodString>;
1280
+ gitSha: z.ZodOptional<z.ZodString>;
1281
+ actorType: z.ZodOptional<z.ZodEnum<{
1282
+ LOCAL_AGENT: "LOCAL_AGENT";
1283
+ CLOUD_AGENT: "CLOUD_AGENT";
1284
+ "local-agent": "local-agent";
1285
+ "cloud-agent": "cloud-agent";
1286
+ }>>;
1287
+ userId: z.ZodOptional<z.ZodString>;
1288
+ branchName: z.ZodOptional<z.ZodString>;
1289
+ agentModel: z.ZodOptional<z.ZodString>;
1290
+ }, z.core.$strict>>;
1291
+ entityType: z.ZodEnum<{
1292
+ SMART_TEST: "SMART_TEST";
1293
+ SCENARIO: "SCENARIO";
1294
+ ISSUE: "ISSUE";
1295
+ TEST_EXECUTION: "TEST_EXECUTION";
1296
+ USER_STORY: "USER_STORY";
1297
+ POLICY: "POLICY";
1298
+ TEST_INVOCATION_BATCH: "TEST_INVOCATION_BATCH";
1299
+ EXPLORATION: "EXPLORATION";
1300
+ EVENT: "EVENT";
1301
+ WORKFLOW: "WORKFLOW";
1302
+ }>;
1055
1303
  entityIdentity: z.ZodOptional<z.ZodString>;
1056
1304
  test: z.ZodOptional<z.ZodObject<{
1057
1305
  folderPath: z.ZodOptional<z.ZodArray<z.ZodString>>;
@@ -1067,6 +1315,7 @@ export declare const reportAgentActionInput: z.ZodObject<{
1067
1315
  ANALYZED: "ANALYZED";
1068
1316
  ACTION_COMPLETED: "ACTION_COMPLETED";
1069
1317
  ACTION_FAILED: "ACTION_FAILED";
1318
+ IMPLEMENTED: "IMPLEMENTED";
1070
1319
  created: "created";
1071
1320
  updated: "updated";
1072
1321
  deleted: "deleted";
@@ -1074,8 +1323,8 @@ export declare const reportAgentActionInput: z.ZodObject<{
1074
1323
  completed: "completed";
1075
1324
  action_completed: "action_completed";
1076
1325
  action_failed: "action_failed";
1326
+ implemented: "implemented";
1077
1327
  }>;
1078
- detailJson: z.ZodOptional<z.ZodString>;
1079
1328
  }, z.core.$strip>;
1080
1329
  export declare const getLastRunWorkflowDetailInput: z.ZodObject<{
1081
1330
  workflowId: z.ZodString;
@@ -53,22 +53,57 @@ export const fetchExecutionReportInput = z
53
53
  });
54
54
  }
55
55
  });
56
+ export const agentActorTypeSchema = z.enum(["LOCAL_AGENT", "CLOUD_AGENT", "local-agent", "cloud-agent"]);
57
+ /** Nested AgentActionTraceability (agent_traceability.proto) for mutating MCP CRUDs. */
58
+ export const agentActionTraceabilitySchema = z
59
+ .object({
60
+ workflowId: z.string().optional(),
61
+ workflowExecutionId: z.string().optional(),
62
+ policyFile: z.string().optional(),
63
+ policyVersion: z.string().optional(),
64
+ gitSha: z.string().optional(),
65
+ actorType: agentActorTypeSchema.optional(),
66
+ userId: z.string().optional(),
67
+ branchName: z.string().optional(),
68
+ agentModel: z.string().optional(),
69
+ })
70
+ .strict();
71
+ /** Flat + nested traceability fields shared by create/update MCP tools. */
72
+ export const agentTraceabilityFieldsSchema = z.object({
73
+ workflowId: z.string().optional(),
74
+ workflowExecutionId: z.string().optional(),
75
+ policyFile: z.string().optional(),
76
+ policyVersion: z.string().optional(),
77
+ gitSha: z.string().optional(),
78
+ actorType: agentActorTypeSchema.optional(),
79
+ userId: z.string().optional(),
80
+ branchName: z.string().optional(),
81
+ agentModel: z.string().optional(),
82
+ agentTraceability: agentActionTraceabilitySchema.optional(),
83
+ });
56
84
  export const createUserStoryInput = z.object({
57
85
  platformFilePath: z.string().min(1),
58
86
  title: z.string().min(1),
59
- });
87
+ }).merge(agentTraceabilityFieldsSchema);
60
88
  export const createTestScenarioInput = z.object({
61
89
  platformFilePath: z.string().min(1),
62
90
  title: z.string().min(1),
63
91
  userStoryOrdinalId: z.coerce.number().int().positive(),
64
- });
92
+ }).merge(agentTraceabilityFieldsSchema);
65
93
  export const updatePlanMarkdownInput = z.object({
66
94
  content: z.string().min(1),
67
- });
95
+ }).merge(agentTraceabilityFieldsSchema);
68
96
  export const markPlanItemsImplementationDoneInput = z.object({
69
97
  scenarioOrdinalIds: z.array(z.coerce.number().int().positive()).optional(),
70
98
  userStoryOrdinalIds: z.array(z.coerce.number().int().positive()).optional(),
71
99
  });
100
+ export const updatePlanItemsLifecycleStatusInput = z.object({
101
+ /** story | scenario (also accepts user_story / USER_STORY / SCENARIO) */
102
+ entityType: z.string().min(1),
103
+ ordinalId: z.coerce.number().int().positive(),
104
+ /** draft | ready | in progress | blocked | done | archived */
105
+ status: z.string().min(1),
106
+ });
72
107
  export const getUserStoriesInput = z
73
108
  .object({
74
109
  userStoryOrdinalIds: z.array(z.coerce.number().int().positive()).min(1),
@@ -98,7 +133,7 @@ export const updateIssueStatusInput = z.object({
98
133
  ignoreReason: z
99
134
  .enum(["INTENDED_BEHAVIOUR", "INACCURATE_ASSESSMENT", "NOT_IMPORTANT"])
100
135
  .optional(),
101
- });
136
+ }).merge(agentTraceabilityFieldsSchema);
102
137
  const linkedEntityTypeSchema = z.enum([
103
138
  "STORY",
104
139
  "SCENARIO",
@@ -164,7 +199,7 @@ export const createIssueInput = z.object({
164
199
  environment: z.string().optional(),
165
200
  attachments: z.array(z.record(z.string(), z.unknown())).optional(),
166
201
  artifactReference: z.record(z.string(), z.unknown()).optional(),
167
- });
202
+ }).merge(agentTraceabilityFieldsSchema);
168
203
  export const emptyInput = z.object({});
169
204
  export const getBranchSpecificEndpointConfigInput = z.object({
170
205
  branchName: z.string().optional(),
@@ -500,7 +535,19 @@ export const reportRequirementQualityFindingsInput = z
500
535
  });
501
536
  }
502
537
  });
503
- export const agentActorTypeSchema = z.enum(["LOCAL_AGENT", "CLOUD_AGENT", "local-agent", "cloud-agent"]);
538
+ /** Closed vocabulary for report-agent-action entity_type (agent_workflow.proto AgentActionEntityType). */
539
+ export const agentActionEntityTypeSchema = z.enum([
540
+ "USER_STORY",
541
+ "SCENARIO",
542
+ "SMART_TEST",
543
+ "POLICY",
544
+ "ISSUE",
545
+ "TEST_EXECUTION",
546
+ "TEST_INVOCATION_BATCH",
547
+ "EXPLORATION",
548
+ "EVENT",
549
+ "WORKFLOW",
550
+ ]);
504
551
  export const agentActionTypeSchema = z.enum([
505
552
  "CREATED",
506
553
  "UPDATED",
@@ -508,6 +555,7 @@ export const agentActionTypeSchema = z.enum([
508
555
  "ANALYZED",
509
556
  "ACTION_COMPLETED",
510
557
  "ACTION_FAILED",
558
+ "IMPLEMENTED",
511
559
  "created",
512
560
  "updated",
513
561
  "deleted",
@@ -516,6 +564,7 @@ export const agentActionTypeSchema = z.enum([
516
564
  "failed",
517
565
  "action_completed",
518
566
  "action_failed",
567
+ "implemented",
519
568
  ]);
520
569
  export const reportAgentActionInput = z
521
570
  .object({
@@ -527,20 +576,85 @@ export const reportAgentActionInput = z
527
576
  actorType: agentActorTypeSchema.optional(),
528
577
  userId: z.string().optional(),
529
578
  branchName: z.string().optional(),
530
- entityType: z.string().optional(),
579
+ agentModel: z.string().optional(),
580
+ traceability: agentActionTraceabilitySchema.optional(),
581
+ entityType: agentActionEntityTypeSchema,
531
582
  /** Project-scoped ordinal id (or explicitly provided execution/batch id). Mutually exclusive with `test`. */
532
583
  entityIdentity: z.string().optional(),
533
584
  /** SmartTest TestLocator. Mutually exclusive with `entityIdentity`. */
534
585
  test: testLocatorSchema.optional(),
535
586
  actionType: agentActionTypeSchema,
536
- detailJson: z.string().optional(),
537
587
  })
538
588
  .superRefine((val, ctx) => {
539
- if (val.test && val.entityIdentity) {
589
+ const actionNorm = val.actionType.toString().toUpperCase().replace(/-/g, "_");
590
+ const isCompletion = actionNorm === "ACTION_COMPLETED" ||
591
+ actionNorm === "ACTION_FAILED" ||
592
+ actionNorm === "COMPLETED" ||
593
+ actionNorm === "FAILED";
594
+ if (isCompletion) {
595
+ if (val.entityType !== "WORKFLOW") {
596
+ ctx.addIssue({
597
+ code: z.ZodIssueCode.custom,
598
+ message: "ACTION_COMPLETED / ACTION_FAILED require entityType WORKFLOW",
599
+ path: ["entityType"],
600
+ });
601
+ }
602
+ const identity = (val.entityIdentity ?? "").trim();
603
+ if (identity === "" || identity !== val.workflowId.trim()) {
604
+ ctx.addIssue({
605
+ code: z.ZodIssueCode.custom,
606
+ message: "entityIdentity must equal workflowId for WORKFLOW completion",
607
+ path: ["entityIdentity"],
608
+ });
609
+ }
610
+ if (val.test) {
611
+ ctx.addIssue({
612
+ code: z.ZodIssueCode.custom,
613
+ message: "test must not be set for WORKFLOW completion",
614
+ path: ["test"],
615
+ });
616
+ }
617
+ return;
618
+ }
619
+ if (val.entityType === "WORKFLOW") {
620
+ ctx.addIssue({
621
+ code: z.ZodIssueCode.custom,
622
+ message: "WORKFLOW entityType is only valid with ACTION_COMPLETED / ACTION_FAILED",
623
+ path: ["entityType"],
624
+ });
625
+ return;
626
+ }
627
+ if (actionNorm === "IMPLEMENTED" &&
628
+ val.entityType !== "USER_STORY" &&
629
+ val.entityType !== "SCENARIO") {
630
+ ctx.addIssue({
631
+ code: z.ZodIssueCode.custom,
632
+ message: "IMPLEMENTED is only valid for USER_STORY or SCENARIO",
633
+ path: ["entityType"],
634
+ });
635
+ }
636
+ if (val.entityType === "SMART_TEST") {
637
+ if (!val.test) {
638
+ ctx.addIssue({
639
+ code: z.ZodIssueCode.custom,
640
+ message: "SMART_TEST requires test (TestLocator)",
641
+ path: ["test"],
642
+ });
643
+ }
644
+ if (val.entityIdentity != null && val.entityIdentity.trim() !== "") {
645
+ ctx.addIssue({
646
+ code: z.ZodIssueCode.custom,
647
+ message: "SMART_TEST forbids entityIdentity; use test (TestLocator)",
648
+ path: ["entityIdentity"],
649
+ });
650
+ }
651
+ return;
652
+ }
653
+ if (!(val.entityIdentity ?? "").trim()) {
540
654
  ctx.addIssue({
541
655
  code: z.ZodIssueCode.custom,
542
- message: "Provide either test (TestLocator) or entityIdentity (ordinal), not both",
543
- path: ["test"],
656
+ message: `entityIdentity is required for ${val.entityType}`,
657
+ path: ["entityIdentity"],
544
658
  });
545
659
  }
546
660
  });
@@ -1,6 +1,8 @@
1
1
  import { normalizeScope } from "./normalize.js";
2
2
  import { runProvisionEphemeralEnvironmentAndWait } from "./ephemeralWait.js";
3
3
  import * as S from "./schemas.js";
4
+ import { resolveGitHeadSha } from "./gitSha.js";
5
+ import { buildAgentTraceabilityPayload } from "./agentTraceability.js";
4
6
  function platformToProtoEnum(platform) {
5
7
  switch (platform) {
6
8
  case "ios":
@@ -166,14 +168,20 @@ export const TOOL_DEFINITIONS = [
166
168
  "Response includes content: canonical stub markdown already containing id: US-<ordinalId>. " +
167
169
  "BLOCKING workflow: call this FIRST → Write the returned content to the repo plans/stories path " +
168
170
  "(edit body as needed but keep id:) → call update-user-story with the full markdown. " +
169
- "Never write story markdown that omits id. platformFilePath must be under plans/stories/ and end with .md.",
171
+ "Never write story markdown that omits id. platformFilePath must be under plans/stories/ and end with .md. " +
172
+ "Optional agentTraceability (or flat workflowId/workflowExecutionId/policyFile/policyVersion/gitSha/…) " +
173
+ "records AGENT_WORKFLOW_ACTIVITY inline — no separate report-agent-action needed for this create.",
170
174
  inputSchema: S.createUserStoryInput,
171
175
  execute: async (args, { postMcp }) => {
172
176
  const a = args;
173
- return postMcp("/api/mcp/create_user_story", {
177
+ const body = {
174
178
  platformFilePath: a.platformFilePath,
175
179
  title: a.title,
176
- });
180
+ };
181
+ const trace = buildAgentTraceabilityPayload(a);
182
+ if (trace)
183
+ body.agentTraceability = trace;
184
+ return postMcp("/api/mcp/create_user_story", body);
177
185
  },
178
186
  },
179
187
  {
@@ -184,37 +192,52 @@ export const TOOL_DEFINITIONS = [
184
192
  "(edit body as needed but keep id: and story:) → call update-test-scenario with the full markdown. " +
185
193
  "Never write scenario markdown that omits id. update-test-scenario rejects missing id/story with a clear error. " +
186
194
  "platformFilePath must be under plans/scenarios/ and end with .md. " +
187
- "userStoryOrdinalId is the numeric part of the parent US-<n> id.",
195
+ "userStoryOrdinalId is the numeric part of the parent US-<n> id. " +
196
+ "Optional agentTraceability records Activity inline (no separate report-agent-action for this create).",
188
197
  inputSchema: S.createTestScenarioInput,
189
198
  execute: async (args, { postMcp }) => {
190
199
  const a = args;
191
- return postMcp("/api/mcp/create_test_scenario", {
200
+ const body = {
192
201
  platformFilePath: a.platformFilePath,
193
202
  title: a.title,
194
203
  userStoryOrdinalId: a.userStoryOrdinalId,
195
- });
204
+ };
205
+ const trace = buildAgentTraceabilityPayload(a);
206
+ if (trace)
207
+ body.agentTraceability = trace;
208
+ return postMcp("/api/mcp/create_test_scenario", body);
196
209
  },
197
210
  },
198
211
  {
199
212
  kebab: "update-user-story",
200
213
  description: "Sync a user story markdown file to the platform after local edits. " +
201
214
  "Requires frontmatter id: US-<n> (platform-issued). Missing id returns an error telling you to call create-user-story first. " +
202
- "Parses frontmatter (id, title, priority) and updates the linked support file and entity.",
215
+ "Parses frontmatter (id, title, priority) and updates the linked support file and entity. " +
216
+ "Optional agentTraceability records UPDATED Activity inline.",
203
217
  inputSchema: S.updatePlanMarkdownInput,
204
218
  execute: async (args, { postMcp }) => {
205
219
  const a = args;
206
- return postMcp("/api/mcp/update_user_story", { content: a.content });
220
+ const body = { content: a.content };
221
+ const trace = buildAgentTraceabilityPayload(a);
222
+ if (trace)
223
+ body.agentTraceability = trace;
224
+ return postMcp("/api/mcp/update_user_story", body);
207
225
  },
208
226
  },
209
227
  {
210
228
  kebab: "update-test-scenario",
211
229
  description: "Sync a test scenario markdown file to the platform after local edits. " +
212
230
  "Requires frontmatter id: TS-<n> and story: US-<n>. Missing either returns an error telling you to call create-test-scenario first. " +
213
- "Parses frontmatter and updates linking if story changes.",
231
+ "Parses frontmatter and updates linking if story changes. " +
232
+ "Optional agentTraceability records UPDATED Activity inline.",
214
233
  inputSchema: S.updatePlanMarkdownInput,
215
234
  execute: async (args, { postMcp }) => {
216
235
  const a = args;
217
- return postMcp("/api/mcp/update_test_scenario", { content: a.content });
236
+ const body = { content: a.content };
237
+ const trace = buildAgentTraceabilityPayload(a);
238
+ if (trace)
239
+ body.agentTraceability = trace;
240
+ return postMcp("/api/mcp/update_test_scenario", body);
218
241
  },
219
242
  },
220
243
  {
@@ -274,7 +297,8 @@ export const TOOL_DEFINITIONS = [
274
297
  description: "Update a TestChimp issue status by ordinal id (same flexible issueId formats as get-issue-details). " +
275
298
  "status must be one of: ACTIVE, IGNORED, FIXED, DUPLICATE, IN_PROGRESS_BUG, ARCHIVED_BUG, BLOCKED. " +
276
299
  "For /testchimp fix issue: set IN_PROGRESS_BUG after applying a code fix; set FIXED only after user confirmation / commits pushed. " +
277
- "Optional ignoreReason when status is IGNORED: INTENDED_BEHAVIOUR | INACCURATE_ASSESSMENT | NOT_IMPORTANT.",
300
+ "Optional ignoreReason when status is IGNORED: INTENDED_BEHAVIOUR | INACCURATE_ASSESSMENT | NOT_IMPORTANT. " +
301
+ "Optional agentTraceability records UPDATED Activity inline.",
278
302
  inputSchema: S.updateIssueStatusInput,
279
303
  execute: async (args, { postMcp }) => {
280
304
  const a = args;
@@ -284,6 +308,9 @@ export const TOOL_DEFINITIONS = [
284
308
  };
285
309
  if (a.ignoreReason)
286
310
  body.ignoreReason = a.ignoreReason;
311
+ const trace = buildAgentTraceabilityPayload(a);
312
+ if (trace)
313
+ body.agentTraceability = trace;
287
314
  return postMcp("/api/mcp/update_issue_status", body);
288
315
  },
289
316
  },
@@ -293,6 +320,8 @@ export const TOOL_DEFINITIONS = [
293
320
  "Use simple fields for common creates, or pass the full curated contract via --json-input " +
294
321
  "(description, issueType, category, severity, status, reportedReleaseId, dueDateMillis, assignee, " +
295
322
  "linkTargets, labels, source, environment, attachments, artifactReference). " +
323
+ "Optional agentTraceability (or flat workflowId/policyFile/…) records CREATED Activity inline — " +
324
+ "prefer this over a separate report-agent-action for issue creates. " +
296
325
  "Authenticated via project API key; project is resolved from the key.",
297
326
  inputSchema: S.createIssueInput,
298
327
  execute: async (args, { postMcp }) => {
@@ -326,6 +355,9 @@ export const TOOL_DEFINITIONS = [
326
355
  body.attachments = a.attachments;
327
356
  if (a.artifactReference != null)
328
357
  body.artifactReference = a.artifactReference;
358
+ const trace = buildAgentTraceabilityPayload(a);
359
+ if (trace)
360
+ body.agentTraceability = trace;
329
361
  return postMcp("/api/mcp/create_issue", body);
330
362
  },
331
363
  },
@@ -344,6 +376,21 @@ export const TOOL_DEFINITIONS = [
344
376
  return postMcp("/api/mcp/mark_plan_items_implementation_done", body);
345
377
  },
346
378
  },
379
+ {
380
+ kebab: "update-plan-items-lifecycle-status",
381
+ description: "Update lifecycle_fields.status for one user story or test scenario (DB only; does not rewrite plan markdown). " +
382
+ "entityType: story | scenario; ordinalId: numeric US-/TS- ordinal; status: draft | ready | in progress | blocked | done | archived. " +
383
+ "Used after /testchimp implement to set status to ready (unless policy overrides).",
384
+ inputSchema: S.updatePlanItemsLifecycleStatusInput,
385
+ execute: async (args, { postMcp }) => {
386
+ const a = args;
387
+ return postMcp("/api/mcp/update_plan_items_lifecycle_status", {
388
+ entityType: a.entityType,
389
+ ordinalId: a.ordinalId,
390
+ status: a.status,
391
+ });
392
+ },
393
+ },
347
394
  {
348
395
  kebab: "get-eaas-config",
349
396
  description: "Return the project's BunnyShell (Environment-as-a-Service) settings. Secrets are never returned.",
@@ -779,10 +826,15 @@ export const TOOL_DEFINITIONS = [
779
826
  {
780
827
  kebab: "report-agent-action",
781
828
  description: "Report a mutating agent action under a stable workflow-execution-id (ULID). " +
782
- "First call for an id creates the workflow_executions row; later calls append agent_actions. " +
783
- "Identity: pass `test` (TestLocator: folderPath/fileName/testSuite/testName) for SmartTests, " +
784
- "or `entityIdentity` as a project-scoped ordinal id for stories/scenarios/issues " +
785
- "(or an execution/batch id only when the prompt explicitly provided it). Do not use platform UUIDs.",
829
+ "First call for an id creates the workflow_executions row; later calls append Activity " +
830
+ "timeline rows (AGENT_WORKFLOW_ACTIVITY). " +
831
+ "Actions land on the entity's Activity timeline (plans, issues, SmartTest file). " +
832
+ "entityType: USER_STORY | SCENARIO | SMART_TEST | POLICY | ISSUE | TEST_EXECUTION | " +
833
+ "TEST_INVOCATION_BATCH | EXPLORATION | EVENT | WORKFLOW. " +
834
+ "actionType: CREATED | UPDATED | DELETED | ANALYZED | IMPLEMENTED | ACTION_COMPLETED | ACTION_FAILED. " +
835
+ "Identity: SMART_TEST uses `test` (TestLocator: folderPath/fileName/testSuite/testName); " +
836
+ "other artifact types use `entityIdentity` (ordinal / filename / opaque id). Do not use platform UUIDs. " +
837
+ "Completion (ACTION_COMPLETED / ACTION_FAILED): entityType WORKFLOW and entityIdentity = catalog workflow_id.",
786
838
  inputSchema: S.reportAgentActionInput,
787
839
  execute: async (args, { postMcp }) => {
788
840
  const a = args;
@@ -801,29 +853,48 @@ export const TOOL_DEFINITIONS = [
801
853
  workflowExecutionId: a.workflowExecutionId,
802
854
  actionType,
803
855
  actorType,
856
+ entityType: a.entityType,
804
857
  };
805
858
  if (a.policyFile)
806
859
  body.policyFile = a.policyFile;
807
860
  if (a.policyVersion)
808
861
  body.policyVersion = a.policyVersion;
809
- if (a.gitSha)
810
- body.gitSha = a.gitSha;
862
+ const gitSha = resolveGitHeadSha(a.gitSha);
863
+ if (gitSha)
864
+ body.gitSha = gitSha;
811
865
  if (a.userId)
812
866
  body.userId = a.userId;
813
867
  else if (process.env.TESTCHIMP_USER_ID)
814
868
  body.userId = process.env.TESTCHIMP_USER_ID;
815
869
  if (a.branchName)
816
870
  body.branchName = a.branchName;
817
- if (a.entityType)
818
- body.entityType = a.entityType;
871
+ // Nested traceability wins for agentModel; only fill from flat/env when nested omits it.
872
+ if (a.traceability && typeof a.traceability === "object") {
873
+ const nested = { ...a.traceability };
874
+ const nestedModel = nested.agentModel != null && String(nested.agentModel).trim() !== ""
875
+ ? String(nested.agentModel).trim()
876
+ : undefined;
877
+ const flatModel = a.agentModel?.trim() || process.env.TESTCHIMP_AGENT_MODEL?.trim();
878
+ if (nestedModel) {
879
+ nested.agentModel = nestedModel;
880
+ }
881
+ else if (flatModel) {
882
+ nested.agentModel = flatModel;
883
+ }
884
+ body.traceability = nested;
885
+ }
886
+ else {
887
+ const model = a.agentModel?.trim() || process.env.TESTCHIMP_AGENT_MODEL?.trim();
888
+ if (model) {
889
+ body.traceability = { agentModel: model };
890
+ }
891
+ }
819
892
  if (a.test) {
820
893
  body.test = a.test;
821
894
  }
822
895
  else if (a.entityIdentity) {
823
896
  body.entityIdentity = a.entityIdentity;
824
897
  }
825
- if (a.detailJson)
826
- body.detailJson = a.detailJson;
827
898
  return postMcp("/api/mcp/report_agent_action", body);
828
899
  },
829
900
  },
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@testchimp/cli",
3
- "version": "0.1.21",
4
- "description": "TestChimp CLI and MCP server coverage, plans, EaaS, TrueCoverage (calls /api/mcp/*)",
3
+ "version": "0.1.23",
4
+ "description": "TestChimp CLI and MCP server \u2014 coverage, plans, EaaS, TrueCoverage (calls /api/mcp/*)",
5
5
  "type": "module",
6
6
  "main": "dist/bin/testchimp.js",
7
7
  "types": "dist/bin/testchimp.d.ts",