@qawolf/cli 1.36.0 → 1.37.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -16617,6 +16617,10 @@ var publicRunStatusValues = [
16617
16617
  "failed",
16618
16618
  "canceled"
16619
16619
  ];
16620
+ var publicRunSummaryStatusValues = [
16621
+ ...publicRunStatusValues,
16622
+ "superseded"
16623
+ ];
16620
16624
  var makeRunSummaryFields = (ids) => ({
16621
16625
  completedAt: exports_iso.datetime().optional().describe("When the run finished executing. Absent while queued or running, and also absent for a terminal run that never completed execution (e.g. every flow was canceled or skipped)."),
16622
16626
  createdAt: exports_iso.datetime(),
@@ -16628,7 +16632,11 @@ var makeRunSummaryFields = (ids) => ({
16628
16632
  }).describe("The branch and commit under test. The fields are present when a deploy notification started the run, and absent for runs started another way, for example manually or with run.create."),
16629
16633
  needsReview: boolean2().optional().describe("True once every flow has finished its attempts and at least one failed flow still has no diagnosis, including one whose investigation carried over to a later run. `status` stays `running` until that failure is diagnosed, so a caller that is not waiting for a diagnosis can stop polling here and read the run's failed flows."),
16630
16634
  runId: ids.run,
16631
- status: _enum(publicRunStatusValues).describe("Whole-run status, and the value to gate a pipeline on. Terminal statuses are passed, failed, and canceled; poll until one is reached. `failed` means the run found a bug that is still open and serious enough to block — a lower-priority bug, or one since resolved, reads `passed`, and the per-flow diagnoses are still in `flows`. The run stays `running` while any investigation is unresolved, including one that carried over to a later run, so a terminal status always means a settled answer. `needsReview` tells such a run apart from one that is still executing.")
16635
+ status: _enum(publicRunSummaryStatusValues).describe("Whole-run status, and the value to gate a pipeline on. Terminal statuses are passed, failed, canceled, and superseded; poll until one is reached. `failed` means the run found a bug that is still open and serious enough to block — a lower-priority bug, or one since resolved, reads `passed`, and the per-flow diagnoses are still in `flows`. The run stays `running` while any investigation is unresolved, including one that carried over to a later run, so a terminal status always means a settled answer, and `needsReview` tells such a run apart from one that is still executing. `superseded` means a newer run replaced this one before it finished: it is not a pass, this run will never change again, and the verdict belongs to the run in `supersededBy`."),
16636
+ supersededBy: object({
16637
+ runId: ids.run,
16638
+ url: url().describe("Absolute URL of the replacement run's page.")
16639
+ }).optional().describe("The run that replaced this one, present only when `status` is `superseded`. A newer deployment to the same branch and environment (and service, when the deployment named one) cancels the older run's unfinished flows and takes over. Deduplication ignores the commit, so the replacement may be testing a later commit than this run did. Only the direct replacement is named; that run can itself be superseded.")
16632
16640
  });
16633
16641
 
16634
16642
  // node_modules/@qawolf/api-contracts/dist/v1/deployment/didNotRunReason.js
@@ -16843,6 +16851,7 @@ var defaultIdSchemas = {
16843
16851
  issue: string2().min(1).describe("The id of the issue."),
16844
16852
  legacyTrigger: string2().min(1).describe("The id of the legacy trigger, from legacyTrigger.find."),
16845
16853
  run: string2().min(1).describe("The id of the run."),
16854
+ runAttempt: string2().min(1).describe("The id of the run attempt."),
16846
16855
  trigger: string2().min(1).describe("The id of the trigger."),
16847
16856
  workspace: string2().min(1).describe("The id of the workspace.")
16848
16857
  };
@@ -19045,7 +19054,7 @@ var makeAddFlowsToIssueContract = (ids) => {
19045
19054
  // node_modules/@qawolf/api-contracts/dist/v1/issue/create.js
19046
19055
  var makeCreateIssueContract = (ids) => {
19047
19056
  const commonFields = {
19048
- description: string2().optional().describe("The issue description as plain text; each line becomes a paragraph. Markdown is not parsed."),
19057
+ description: string2().optional().describe("The issue description in Markdown, which is stored as rich text. Text without Markdown is stored as written, one paragraph per line."),
19049
19058
  name: string2().trim().min(1).max(255),
19050
19059
  priority: issuePrioritySchema.optional().describe('Defaults to "unprioritized" for bug reports and coverage requests.'),
19051
19060
  workspaceId: ids.workspace.optional().describe("The workspace to create the issue in. Required when authenticating with an organization or user API key.")
@@ -19110,7 +19119,7 @@ var makeRemoveFlowsFromIssueContract = (ids) => {
19110
19119
 
19111
19120
  // node_modules/@qawolf/api-contracts/dist/v1/issue/update.js
19112
19121
  var makeUpdateIssueContract = (ids) => {
19113
- const descriptionSchema = string2().describe("The issue description as plain text; each line becomes a paragraph. Markdown is not parsed.");
19122
+ const descriptionSchema = string2().describe("The issue description in Markdown, which is stored as rich text. Text without Markdown is stored as written, one paragraph per line.");
19114
19123
  const nameSchema = string2().trim().min(1).max(255);
19115
19124
  const input = object({
19116
19125
  description: descriptionSchema.optional(),
@@ -19294,9 +19303,11 @@ var makeFindRunsContract = (ids) => {
19294
19303
  });
19295
19304
  const output = object({
19296
19305
  nextCursor: nextCursorSchema,
19297
- runs: array(resource(makeRunSummaryFields(ids), {
19298
- urlFieldDescription: "Absolute URL of the run page."
19299
- })).describe("The environment's runs, newest first. Per-flow results are available via run.get.")
19306
+ runs: array(resource({
19307
+ ...makeRunSummaryFields(ids),
19308
+ failedAttemptCount: number2().int().nonnegative().optional(),
19309
+ hasFailedAttempts: boolean2().optional()
19310
+ }, { urlFieldDescription: "Absolute URL of the run page." })).describe("The environment's runs, newest first. Per-flow results are available via run.get.")
19300
19311
  });
19301
19312
  return {
19302
19313
  annotations: {
@@ -19304,7 +19315,7 @@ var makeFindRunsContract = (ids) => {
19304
19315
  openWorldHint: false,
19305
19316
  readOnlyHint: true
19306
19317
  },
19307
- description: "List an environment's recent runs, newest first.",
19318
+ description: "List an environment's recent runs, newest first, including failed-attempt discovery metadata.",
19308
19319
  input,
19309
19320
  kind: "read",
19310
19321
  name: "run.find",
@@ -19328,6 +19339,7 @@ var makeGetRunContract = (ids) => {
19328
19339
  const automatedAttempt = discriminatedUnion("status", [
19329
19340
  object({
19330
19341
  ...artifactUrls,
19342
+ attemptId: ids.runAttempt.optional(),
19331
19343
  completedAt: exports_iso.datetime(),
19332
19344
  kind: automatedKind,
19333
19345
  startedAt: exports_iso.datetime(),
@@ -19335,12 +19347,14 @@ var makeGetRunContract = (ids) => {
19335
19347
  }),
19336
19348
  object({
19337
19349
  ...artifactUrls,
19350
+ attemptId: ids.runAttempt.optional(),
19338
19351
  completedAt: exports_iso.datetime(),
19339
19352
  kind: automatedKind,
19340
19353
  startedAt: exports_iso.datetime().optional().describe("Absent when the attempt failed before it could start."),
19341
19354
  status: literal("failed")
19342
19355
  }),
19343
19356
  object({
19357
+ attemptId: ids.runAttempt.optional(),
19344
19358
  completedAt: exports_iso.datetime().optional(),
19345
19359
  kind: automatedKind,
19346
19360
  startedAt: exports_iso.datetime().optional(),
@@ -19348,6 +19362,7 @@ var makeGetRunContract = (ids) => {
19348
19362
  })
19349
19363
  ]);
19350
19364
  const manualAttempt = object({
19365
+ attemptId: ids.runAttempt.optional(),
19351
19366
  completedAt: exports_iso.datetime(),
19352
19367
  kind: literal("manual").describe("The attempt ran by hand in the Wolf Browser."),
19353
19368
  startedAt: exports_iso.datetime(),
@@ -19396,6 +19411,83 @@ var makeGetRunContract = (ids) => {
19396
19411
  };
19397
19412
  };
19398
19413
 
19414
+ // node_modules/@qawolf/api-contracts/dist/v1/run/getAttemptArtifacts.js
19415
+ var makeGetRunAttemptArtifactsContract = (ids) => {
19416
+ const input = object({ attemptId: ids.runAttempt });
19417
+ const attemptStatus = _enum([
19418
+ "passed",
19419
+ "failed",
19420
+ "canceled",
19421
+ "aborted",
19422
+ "skipped"
19423
+ ]);
19424
+ const attemptNeighbor = object({
19425
+ attemptId: ids.runAttempt,
19426
+ status: attemptStatus
19427
+ });
19428
+ const response = object({
19429
+ flowId: ids.flow,
19430
+ flowStatus: _enum(publicRunStatusValues),
19431
+ retryContext: object({
19432
+ currentOrdinal: number2().int().min(1),
19433
+ next: attemptNeighbor.optional(),
19434
+ previous: attemptNeighbor.optional(),
19435
+ total: number2().int().min(1)
19436
+ }),
19437
+ runId: ids.run,
19438
+ runStatus: _enum(publicRunSummaryStatusValues)
19439
+ });
19440
+ const attempt = object({
19441
+ attemptId: ids.runAttempt,
19442
+ completedAt: exports_iso.datetime().optional(),
19443
+ createdAt: exports_iso.datetime(),
19444
+ error: string2().optional(),
19445
+ startedAt: exports_iso.datetime().optional()
19446
+ });
19447
+ const output = discriminatedUnion("artifactStatus", [
19448
+ response.extend({
19449
+ artifacts: object({
19450
+ logsUrl: url().optional(),
19451
+ traceUrl: url().optional(),
19452
+ videoUrl: url().optional()
19453
+ }),
19454
+ artifactStatus: literal("signed"),
19455
+ attempt: attempt.extend({
19456
+ kind: literal("automated"),
19457
+ status: attemptStatus
19458
+ })
19459
+ }),
19460
+ response.extend({
19461
+ artifacts: object({}).strict(),
19462
+ artifactStatus: literal("signing-failed"),
19463
+ attempt: attempt.extend({
19464
+ kind: literal("automated"),
19465
+ status: attemptStatus
19466
+ })
19467
+ }),
19468
+ response.extend({
19469
+ artifacts: object({}).strict(),
19470
+ artifactStatus: literal("not-captured"),
19471
+ attempt: attempt.extend({
19472
+ kind: literal("manual"),
19473
+ status: literal("passed")
19474
+ })
19475
+ })
19476
+ ]);
19477
+ return {
19478
+ annotations: {
19479
+ destructiveHint: false,
19480
+ openWorldHint: false,
19481
+ readOnlyHint: true
19482
+ },
19483
+ description: "Get metadata and signed artifact URLs for one finished run attempt.",
19484
+ input,
19485
+ kind: "read",
19486
+ name: "run.getAttemptArtifacts",
19487
+ output
19488
+ };
19489
+ };
19490
+
19399
19491
  // node_modules/@qawolf/api-contracts/dist/v1/run/reattempt.js
19400
19492
  var makeReattemptRunContract = (ids) => {
19401
19493
  const input = object({
@@ -19956,7 +20048,11 @@ var makeListTagsContract = (ids) => {
19956
20048
 
19957
20049
  // node_modules/@qawolf/api-contracts/dist/v1/index.js
19958
20050
  var makeContractsV1 = (ids) => {
19959
- const resolvedIds = { ...defaultIdSchemas, ...ids };
20051
+ const resolvedIds = {
20052
+ ...defaultIdSchemas,
20053
+ ...ids,
20054
+ runAttempt: ids.runAttempt ?? defaultIdSchemas.runAttempt
20055
+ };
19960
20056
  return {
19961
20057
  agent: {
19962
20058
  get: makeAgentGetContract(resolvedIds),
@@ -20007,6 +20103,7 @@ var makeContractsV1 = (ids) => {
20007
20103
  diagnose: makeDiagnoseRunContract(resolvedIds),
20008
20104
  find: makeFindRunsContract(resolvedIds),
20009
20105
  get: makeGetRunContract(resolvedIds),
20106
+ getAttemptArtifacts: makeGetRunAttemptArtifactsContract(resolvedIds),
20010
20107
  reattempt: makeReattemptRunContract(resolvedIds),
20011
20108
  stop: makeStopRunContract(resolvedIds)
20012
20109
  },
@@ -22524,7 +22621,7 @@ function startUpdateCheck(deps) {
22524
22621
  // package.json
22525
22622
  var package_default = {
22526
22623
  name: "@qawolf/cli",
22527
- version: "1.36.0",
22624
+ version: "1.37.0",
22528
22625
  description: "Run and manage QA Wolf flows from the terminal, CI, or an AI agent",
22529
22626
  keywords: [
22530
22627
  "automation",
@@ -22595,7 +22692,7 @@ var package_default = {
22595
22692
  "@clack/prompts": "1.5.1",
22596
22693
  "@napi-rs/keyring": "1.3.0",
22597
22694
  "@oxc-node/core": "0.1.0",
22598
- "@qawolf/api-contracts": "0.73.0",
22695
+ "@qawolf/api-contracts": "0.74.0",
22599
22696
  "@qawolf/emails": "1.1.1",
22600
22697
  "@qawolf/flow-targets": "1.0.0",
22601
22698
  "@qawolf/flows": "0.1.4",
@@ -38846,4 +38943,4 @@ createProgram({ signals }).parseAsync().catch(() => {
38846
38943
  process.exitCode = 1;
38847
38944
  }).finally(() => exitWhenIdle(typeof process.exitCode === "number" ? process.exitCode : 0));
38848
38945
 
38849
- //# debugId=9A39ADF2531708B264756E2164756E21
38946
+ //# debugId=0EBF9D8CD8CB2E9E64756E2164756E21
@@ -6979,6 +6979,10 @@ var publicRunStatusValues = [
6979
6979
  "failed",
6980
6980
  "canceled"
6981
6981
  ];
6982
+ var publicRunSummaryStatusValues = [
6983
+ ...publicRunStatusValues,
6984
+ "superseded"
6985
+ ];
6982
6986
  var makeRunSummaryFields = (ids) => ({
6983
6987
  completedAt: exports_iso.datetime().optional().describe("When the run finished executing. Absent while queued or running, and also absent for a terminal run that never completed execution (e.g. every flow was canceled or skipped)."),
6984
6988
  createdAt: exports_iso.datetime(),
@@ -6990,7 +6994,11 @@ var makeRunSummaryFields = (ids) => ({
6990
6994
  }).describe("The branch and commit under test. The fields are present when a deploy notification started the run, and absent for runs started another way, for example manually or with run.create."),
6991
6995
  needsReview: boolean2().optional().describe("True once every flow has finished its attempts and at least one failed flow still has no diagnosis, including one whose investigation carried over to a later run. `status` stays `running` until that failure is diagnosed, so a caller that is not waiting for a diagnosis can stop polling here and read the run's failed flows."),
6992
6996
  runId: ids.run,
6993
- status: _enum(publicRunStatusValues).describe("Whole-run status, and the value to gate a pipeline on. Terminal statuses are passed, failed, and canceled; poll until one is reached. `failed` means the run found a bug that is still open and serious enough to block — a lower-priority bug, or one since resolved, reads `passed`, and the per-flow diagnoses are still in `flows`. The run stays `running` while any investigation is unresolved, including one that carried over to a later run, so a terminal status always means a settled answer. `needsReview` tells such a run apart from one that is still executing.")
6997
+ status: _enum(publicRunSummaryStatusValues).describe("Whole-run status, and the value to gate a pipeline on. Terminal statuses are passed, failed, canceled, and superseded; poll until one is reached. `failed` means the run found a bug that is still open and serious enough to block — a lower-priority bug, or one since resolved, reads `passed`, and the per-flow diagnoses are still in `flows`. The run stays `running` while any investigation is unresolved, including one that carried over to a later run, so a terminal status always means a settled answer, and `needsReview` tells such a run apart from one that is still executing. `superseded` means a newer run replaced this one before it finished: it is not a pass, this run will never change again, and the verdict belongs to the run in `supersededBy`."),
6998
+ supersededBy: object({
6999
+ runId: ids.run,
7000
+ url: url().describe("Absolute URL of the replacement run's page.")
7001
+ }).optional().describe("The run that replaced this one, present only when `status` is `superseded`. A newer deployment to the same branch and environment (and service, when the deployment named one) cancels the older run's unfinished flows and takes over. Deduplication ignores the commit, so the replacement may be testing a later commit than this run did. Only the direct replacement is named; that run can itself be superseded.")
6994
7002
  });
6995
7003
 
6996
7004
  // node_modules/@qawolf/api-contracts/dist/v1/deployment/didNotRunReason.js
@@ -7205,6 +7213,7 @@ var defaultIdSchemas = {
7205
7213
  issue: string2().min(1).describe("The id of the issue."),
7206
7214
  legacyTrigger: string2().min(1).describe("The id of the legacy trigger, from legacyTrigger.find."),
7207
7215
  run: string2().min(1).describe("The id of the run."),
7216
+ runAttempt: string2().min(1).describe("The id of the run attempt."),
7208
7217
  trigger: string2().min(1).describe("The id of the trigger."),
7209
7218
  workspace: string2().min(1).describe("The id of the workspace.")
7210
7219
  };
@@ -9414,7 +9423,7 @@ var makeAddFlowsToIssueContract = (ids) => {
9414
9423
  // node_modules/@qawolf/api-contracts/dist/v1/issue/create.js
9415
9424
  var makeCreateIssueContract = (ids) => {
9416
9425
  const commonFields = {
9417
- description: string2().optional().describe("The issue description as plain text; each line becomes a paragraph. Markdown is not parsed."),
9426
+ description: string2().optional().describe("The issue description in Markdown, which is stored as rich text. Text without Markdown is stored as written, one paragraph per line."),
9418
9427
  name: string2().trim().min(1).max(255),
9419
9428
  priority: issuePrioritySchema.optional().describe('Defaults to "unprioritized" for bug reports and coverage requests.'),
9420
9429
  workspaceId: ids.workspace.optional().describe("The workspace to create the issue in. Required when authenticating with an organization or user API key.")
@@ -9479,7 +9488,7 @@ var makeRemoveFlowsFromIssueContract = (ids) => {
9479
9488
 
9480
9489
  // node_modules/@qawolf/api-contracts/dist/v1/issue/update.js
9481
9490
  var makeUpdateIssueContract = (ids) => {
9482
- const descriptionSchema = string2().describe("The issue description as plain text; each line becomes a paragraph. Markdown is not parsed.");
9491
+ const descriptionSchema = string2().describe("The issue description in Markdown, which is stored as rich text. Text without Markdown is stored as written, one paragraph per line.");
9483
9492
  const nameSchema = string2().trim().min(1).max(255);
9484
9493
  const input = object({
9485
9494
  description: descriptionSchema.optional(),
@@ -9663,9 +9672,11 @@ var makeFindRunsContract = (ids) => {
9663
9672
  });
9664
9673
  const output = object({
9665
9674
  nextCursor: nextCursorSchema,
9666
- runs: array(resource(makeRunSummaryFields(ids), {
9667
- urlFieldDescription: "Absolute URL of the run page."
9668
- })).describe("The environment's runs, newest first. Per-flow results are available via run.get.")
9675
+ runs: array(resource({
9676
+ ...makeRunSummaryFields(ids),
9677
+ failedAttemptCount: number2().int().nonnegative().optional(),
9678
+ hasFailedAttempts: boolean2().optional()
9679
+ }, { urlFieldDescription: "Absolute URL of the run page." })).describe("The environment's runs, newest first. Per-flow results are available via run.get.")
9669
9680
  });
9670
9681
  return {
9671
9682
  annotations: {
@@ -9673,7 +9684,7 @@ var makeFindRunsContract = (ids) => {
9673
9684
  openWorldHint: false,
9674
9685
  readOnlyHint: true
9675
9686
  },
9676
- description: "List an environment's recent runs, newest first.",
9687
+ description: "List an environment's recent runs, newest first, including failed-attempt discovery metadata.",
9677
9688
  input,
9678
9689
  kind: "read",
9679
9690
  name: "run.find",
@@ -9697,6 +9708,7 @@ var makeGetRunContract = (ids) => {
9697
9708
  const automatedAttempt = discriminatedUnion("status", [
9698
9709
  object({
9699
9710
  ...artifactUrls,
9711
+ attemptId: ids.runAttempt.optional(),
9700
9712
  completedAt: exports_iso.datetime(),
9701
9713
  kind: automatedKind,
9702
9714
  startedAt: exports_iso.datetime(),
@@ -9704,12 +9716,14 @@ var makeGetRunContract = (ids) => {
9704
9716
  }),
9705
9717
  object({
9706
9718
  ...artifactUrls,
9719
+ attemptId: ids.runAttempt.optional(),
9707
9720
  completedAt: exports_iso.datetime(),
9708
9721
  kind: automatedKind,
9709
9722
  startedAt: exports_iso.datetime().optional().describe("Absent when the attempt failed before it could start."),
9710
9723
  status: literal("failed")
9711
9724
  }),
9712
9725
  object({
9726
+ attemptId: ids.runAttempt.optional(),
9713
9727
  completedAt: exports_iso.datetime().optional(),
9714
9728
  kind: automatedKind,
9715
9729
  startedAt: exports_iso.datetime().optional(),
@@ -9717,6 +9731,7 @@ var makeGetRunContract = (ids) => {
9717
9731
  })
9718
9732
  ]);
9719
9733
  const manualAttempt = object({
9734
+ attemptId: ids.runAttempt.optional(),
9720
9735
  completedAt: exports_iso.datetime(),
9721
9736
  kind: literal("manual").describe("The attempt ran by hand in the Wolf Browser."),
9722
9737
  startedAt: exports_iso.datetime(),
@@ -9765,6 +9780,83 @@ var makeGetRunContract = (ids) => {
9765
9780
  };
9766
9781
  };
9767
9782
 
9783
+ // node_modules/@qawolf/api-contracts/dist/v1/run/getAttemptArtifacts.js
9784
+ var makeGetRunAttemptArtifactsContract = (ids) => {
9785
+ const input = object({ attemptId: ids.runAttempt });
9786
+ const attemptStatus = _enum([
9787
+ "passed",
9788
+ "failed",
9789
+ "canceled",
9790
+ "aborted",
9791
+ "skipped"
9792
+ ]);
9793
+ const attemptNeighbor = object({
9794
+ attemptId: ids.runAttempt,
9795
+ status: attemptStatus
9796
+ });
9797
+ const response = object({
9798
+ flowId: ids.flow,
9799
+ flowStatus: _enum(publicRunStatusValues),
9800
+ retryContext: object({
9801
+ currentOrdinal: number2().int().min(1),
9802
+ next: attemptNeighbor.optional(),
9803
+ previous: attemptNeighbor.optional(),
9804
+ total: number2().int().min(1)
9805
+ }),
9806
+ runId: ids.run,
9807
+ runStatus: _enum(publicRunSummaryStatusValues)
9808
+ });
9809
+ const attempt = object({
9810
+ attemptId: ids.runAttempt,
9811
+ completedAt: exports_iso.datetime().optional(),
9812
+ createdAt: exports_iso.datetime(),
9813
+ error: string2().optional(),
9814
+ startedAt: exports_iso.datetime().optional()
9815
+ });
9816
+ const output = discriminatedUnion("artifactStatus", [
9817
+ response.extend({
9818
+ artifacts: object({
9819
+ logsUrl: url().optional(),
9820
+ traceUrl: url().optional(),
9821
+ videoUrl: url().optional()
9822
+ }),
9823
+ artifactStatus: literal("signed"),
9824
+ attempt: attempt.extend({
9825
+ kind: literal("automated"),
9826
+ status: attemptStatus
9827
+ })
9828
+ }),
9829
+ response.extend({
9830
+ artifacts: object({}).strict(),
9831
+ artifactStatus: literal("signing-failed"),
9832
+ attempt: attempt.extend({
9833
+ kind: literal("automated"),
9834
+ status: attemptStatus
9835
+ })
9836
+ }),
9837
+ response.extend({
9838
+ artifacts: object({}).strict(),
9839
+ artifactStatus: literal("not-captured"),
9840
+ attempt: attempt.extend({
9841
+ kind: literal("manual"),
9842
+ status: literal("passed")
9843
+ })
9844
+ })
9845
+ ]);
9846
+ return {
9847
+ annotations: {
9848
+ destructiveHint: false,
9849
+ openWorldHint: false,
9850
+ readOnlyHint: true
9851
+ },
9852
+ description: "Get metadata and signed artifact URLs for one finished run attempt.",
9853
+ input,
9854
+ kind: "read",
9855
+ name: "run.getAttemptArtifacts",
9856
+ output
9857
+ };
9858
+ };
9859
+
9768
9860
  // node_modules/@qawolf/api-contracts/dist/v1/run/reattempt.js
9769
9861
  var makeReattemptRunContract = (ids) => {
9770
9862
  const input = object({
@@ -10325,7 +10417,11 @@ var makeListTagsContract = (ids) => {
10325
10417
 
10326
10418
  // node_modules/@qawolf/api-contracts/dist/v1/index.js
10327
10419
  var makeContractsV1 = (ids) => {
10328
- const resolvedIds = { ...defaultIdSchemas, ...ids };
10420
+ const resolvedIds = {
10421
+ ...defaultIdSchemas,
10422
+ ...ids,
10423
+ runAttempt: ids.runAttempt ?? defaultIdSchemas.runAttempt
10424
+ };
10329
10425
  return {
10330
10426
  agent: {
10331
10427
  get: makeAgentGetContract(resolvedIds),
@@ -10376,6 +10472,7 @@ var makeContractsV1 = (ids) => {
10376
10472
  diagnose: makeDiagnoseRunContract(resolvedIds),
10377
10473
  find: makeFindRunsContract(resolvedIds),
10378
10474
  get: makeGetRunContract(resolvedIds),
10475
+ getAttemptArtifacts: makeGetRunAttemptArtifactsContract(resolvedIds),
10379
10476
  reattempt: makeReattemptRunContract(resolvedIds),
10380
10477
  stop: makeStopRunContract(resolvedIds)
10381
10478
  },
@@ -15011,4 +15108,4 @@ export {
15011
15108
  createRunnerSdk
15012
15109
  };
15013
15110
 
15014
- //# debugId=CBFC365D381BD6E864756E2164756E21
15111
+ //# debugId=3EFB50CF5F60CF8264756E2164756E21
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qawolf/cli",
3
- "version": "1.36.0",
3
+ "version": "1.37.0",
4
4
  "description": "Run and manage QA Wolf flows from the terminal, CI, or an AI agent",
5
5
  "keywords": [
6
6
  "automation",
@@ -71,7 +71,7 @@
71
71
  "@clack/prompts": "1.5.1",
72
72
  "@napi-rs/keyring": "1.3.0",
73
73
  "@oxc-node/core": "0.1.0",
74
- "@qawolf/api-contracts": "0.73.0",
74
+ "@qawolf/api-contracts": "0.74.0",
75
75
  "@qawolf/emails": "1.1.1",
76
76
  "@qawolf/flow-targets": "1.0.0",
77
77
  "@qawolf/flows": "0.1.4",
@@ -178,8 +178,9 @@ that `url`; never guess a route and never send a repository link in its place.
178
178
  | `qawolf legacyTrigger resume` | write | Resume one legacy trigger, the older per-environment kind; use trigger.resume for a current one. Its copies in pull request environments resume too, and a scheduled one jumps to the next upcoming slot even if it was not paused. For migration only; it goes when legacy triggers go. |
179
179
  | `qawolf run create` | write | Create a run for the selected flows and/or tags in an environment. |
180
180
  | `qawolf run diagnose` | write | Diagnose failed flows in a run as reproductions of a bug or maintenance report owned by the caller's team. The issue's type selects the diagnosis. Each flow must have failed in the run. A flow that is already diagnosed moves to this issue. The diagnosis appears on the run, and the reproduction appears under the issue's reproductions. Coverage requests cannot be diagnosed; use issue.addFlows to cover flows instead. |
181
- | `qawolf run find` | read | List an environment's recent runs, newest first. |
181
+ | `qawolf run find` | read | List an environment's recent runs, newest first, including failed-attempt discovery metadata. |
182
182
  | `qawolf run get` | read | Get a run's status, per-flow results, links, and how many of its bugs are blocking. |
183
+ | `qawolf run getAttemptArtifacts` | read | Get metadata and signed artifact URLs for one finished run attempt. |
183
184
  | `qawolf run reattempt` | write | Request new attempts for a run's flows, in the same run. A flow is eligible once its result is failed or canceled and QA Wolf's automatic retries have finished. A fully investigated run no longer accepts reattempts. Attempts run with the latest flow code. Poll run.get for results. |
184
185
  | `qawolf run stop` | write | Stop a run, including its queued flows and automatic retries. Stopping is asynchronous and can update run-status messages and commit statuses in connected integrations. Repeated requests are safe, and finished runs keep their results. A run that is still being created returns not found; retry once run.get returns the run. If run.get returns a different runId, use that ID. Poll run.get for results. |
185
186
  | `qawolf runner act` | write | Perform one raw action on a runner's screen. A browser runner takes click, double_click, scroll, move, drag, keypress, navigate and type; a mobile runner takes tap, swipe, fill and type. A browser runner answers mobile actions with action-not-supported-on-browser; a mobile runner answers the other browser actions with action-not-supported-on-mobile. Use - to read a whole action as JSON from stdin |
@@ -59,8 +59,10 @@ A run that has been requested but not yet created answers exit `8` too, and
59
59
  says it is still being created. That one clears on its own, so read the message
60
60
  rather than the code before deciding whether to poll.
61
61
 
62
- Poll `status` until it reaches `passed`, `failed` or `canceled`. The other
63
- values mean the run is still going.
62
+ Poll `status` until it reaches `passed`, `failed`, `canceled` or `superseded`.
63
+ When it is `superseded`, this run will never change again. Read the replacement
64
+ run in `supersededBy.runId` for the verdict. `queued` and `running` mean the run
65
+ is still going.
64
66
 
65
67
  ## Fields a passing run does not show you
66
68
 
@@ -185,13 +187,17 @@ Every documented field of the `run.get` response. `[]` marks an array, so
185
187
  - `git.commitUrl` — Link to the commit on the code host.
186
188
  - `needsReview` — True once every flow has finished its attempts and at least one failed flow still has no diagnosis, including one whose investigation carried over to a later run. `status` stays `running` until that failure is diagnosed, so a caller that is not waiting for a diagnosis can stop polling here and read the run's failed flows.
187
189
  - `runId` — The run this response describes. Treat it as canonical: it can differ from the id you asked for. A deploy notification returns a run id before the run exists, and if a second notification for the same commit is folded into an earlier run, that id resolves to the earlier run instead.
188
- - `status` — One of: queued, running, passed, failed, canceled
190
+ - `status` — One of: queued, running, passed, failed, canceled, superseded
191
+ - `supersededBy` — The run that replaced this one, present only when `status` is `superseded`. A newer deployment to the same branch and environment (and service, when the deployment named one) cancels the older run's unfinished flows and takes over. Deduplication ignores the commit, so the replacement may be testing a later commit than this run did. Only the direct replacement is named; that run can itself be superseded.
192
+ - `supersededBy.runId` — The id of the run.
193
+ - `supersededBy.url` — Absolute URL of the replacement run's page.
189
194
  - `blockingBugCount` — How many bugs this run found are blocking: still open, and priority urgent, high, or unprioritized — unprioritized counts because nobody has ruled it out yet. This is what `failed` is derived from, so it explains a failure rather than adding a second verdict: gate on `status`, then read this to say how many bugs are holding the build. It counts a bug filed against a later run by an investigation that carried over from this one, and it drops a bug once that bug is resolved.
190
195
  - `flows` — The run's flows, ordered alphabetically by name. Only the flows matching flowStatuses when the request set it.
191
196
  - `flows[].attempts` — The flow's finished execution attempts, oldest first, including manual Wolf Browser attempts. Present once at least one attempt has finished, so a flow that passed after retries also lists its failed attempts. Artifact URLs appear only on automated attempts that reached a verdict, stay valid for at least a day (call run.get again for fresh ones), and can return 404 when the attempt did not produce that artifact.
192
197
  - `flows[].attempts[].logsUrl` — Signed URL for the attempt's execution logs.
193
198
  - `flows[].attempts[].traceUrl` — Signed URL for the attempt's Playwright trace (a trace.zip; open it with `npx playwright show-trace`).
194
199
  - `flows[].attempts[].videoUrl` — Signed URL for the attempt's screen recording.
200
+ - `flows[].attempts[].attemptId` — The id of the run attempt.
195
201
  - `flows[].attempts[].kind` — One of: automated, manual
196
202
  - `flows[].attempts[].startedAt` — Absent when the attempt failed before it could start.
197
203
  - `flows[].attempts[].status` — One of: passed, failed, canceled