@qawolf/cli 1.35.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.
@@ -2462,7 +2462,6 @@ var bigint = /^-?\d+n?$/;
2462
2462
  var integer = /^-?\d+$/;
2463
2463
  var number = /^-?\d+(?:\.\d+)?$/;
2464
2464
  var boolean = /^(?:true|false)$/i;
2465
- var _null = /^null$/i;
2466
2465
  var lowercase = /^[^A-Z]*$/;
2467
2466
  var uppercase = /^[^a-z]*$/;
2468
2467
 
@@ -3383,23 +3382,6 @@ var $ZodBigInt = /* @__PURE__ */ $constructor("$ZodBigInt", (inst, def) => {
3383
3382
  return payload;
3384
3383
  };
3385
3384
  });
3386
- var $ZodNull = /* @__PURE__ */ $constructor("$ZodNull", (inst, def) => {
3387
- $ZodType.init(inst, def);
3388
- inst._zod.pattern = _null;
3389
- inst._zod.values = new Set([null]);
3390
- inst._zod.parse = (payload, _ctx) => {
3391
- const input = payload.value;
3392
- if (input === null)
3393
- return payload;
3394
- payload.issues.push({
3395
- expected: "null",
3396
- code: "invalid_type",
3397
- input,
3398
- inst
3399
- });
3400
- return payload;
3401
- };
3402
- });
3403
3385
  var $ZodUnknown = /* @__PURE__ */ $constructor("$ZodUnknown", (inst, def) => {
3404
3386
  $ZodType.init(inst, def);
3405
3387
  inst._zod.parse = (payload) => payload;
@@ -4884,12 +4866,6 @@ function _coercedBigint(Class, params) {
4884
4866
  ...normalizeParams(params)
4885
4867
  });
4886
4868
  }
4887
- function _null2(Class, params) {
4888
- return new Class({
4889
- type: "null",
4890
- ...normalizeParams(params)
4891
- });
4892
- }
4893
4869
  function _unknown(Class) {
4894
4870
  return new Class({
4895
4871
  type: "unknown"
@@ -6519,14 +6495,6 @@ var ZodBigInt = /* @__PURE__ */ $constructor("ZodBigInt", (inst, def) => {
6519
6495
  inst.maxValue = bag.maximum ?? null;
6520
6496
  inst.format = bag.format ?? null;
6521
6497
  });
6522
- var ZodNull = /* @__PURE__ */ $constructor("ZodNull", (inst, def) => {
6523
- $ZodNull.init(inst, def);
6524
- ZodType.init(inst, def);
6525
- inst._zod.processJSONSchema = (ctx, json, params) => nullProcessor(inst, ctx, json, params);
6526
- });
6527
- function _null3(params) {
6528
- return _null2(ZodNull, params);
6529
- }
6530
6498
  var ZodUnknown = /* @__PURE__ */ $constructor("ZodUnknown", (inst, def) => {
6531
6499
  $ZodUnknown.init(inst, def);
6532
6500
  ZodType.init(inst, def);
@@ -6957,12 +6925,6 @@ function refine(fn, _params = {}) {
6957
6925
  function superRefine(fn, params) {
6958
6926
  return _superRefine(fn, params);
6959
6927
  }
6960
- function json(params) {
6961
- const jsonSchema = lazy(() => {
6962
- return union([string2(params), number2(), boolean2(), _null3(), array(jsonSchema), record(string2(), jsonSchema)]);
6963
- });
6964
- return jsonSchema;
6965
- }
6966
6928
  // node_modules/zod/v4/classic/coerce.js
6967
6929
  var exports_coerce = {};
6968
6930
  __export(exports_coerce, {
@@ -7009,6 +6971,83 @@ var agentReplySchema = object({
7009
6971
  var maxAgentWaitSeconds = 45;
7010
6972
  var agentWakeReasonSchema = _enum(["reply", "status", "timeout"]).describe('Why a held check answered. "reply" means the AI said something new, "status" means the session settled or needs you, "timeout" means the hold ran out with nothing new.');
7011
6973
 
6974
+ // node_modules/@qawolf/api-contracts/dist/v1/run/summary.js
6975
+ var publicRunStatusValues = [
6976
+ "queued",
6977
+ "running",
6978
+ "passed",
6979
+ "failed",
6980
+ "canceled"
6981
+ ];
6982
+ var publicRunSummaryStatusValues = [
6983
+ ...publicRunStatusValues,
6984
+ "superseded"
6985
+ ];
6986
+ var makeRunSummaryFields = (ids) => ({
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)."),
6988
+ createdAt: exports_iso.datetime(),
6989
+ git: object({
6990
+ branch: string2().optional(),
6991
+ commitMessage: string2().optional(),
6992
+ commitSha: string2().optional(),
6993
+ commitUrl: string2().optional().describe("Link to the commit on the code host.")
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."),
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."),
6996
+ runId: ids.run,
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.")
7002
+ });
7003
+
7004
+ // node_modules/@qawolf/api-contracts/dist/v1/deployment/didNotRunReason.js
7005
+ var didNotRunReasonSchema = _enum([
7006
+ "billing-prevented",
7007
+ "branch-still-syncing",
7008
+ "deployment-no-longer-live",
7009
+ "duplicate-run",
7010
+ "environment-not-linked-to-branch",
7011
+ "environment-not-ready",
7012
+ "environment-terminated",
7013
+ "internal-error",
7014
+ "low-risk-change",
7015
+ "no-flows-to-run",
7016
+ "no-matching-trigger",
7017
+ "no-pull-request",
7018
+ "no-relevant-flows",
7019
+ "rate-limited",
7020
+ "run-not-created",
7021
+ "skipped",
7022
+ "test-configuration-error",
7023
+ "trigger-not-found",
7024
+ "workspace-inactive",
7025
+ "workspace-not-ready"
7026
+ ]).describe([
7027
+ "Why the matched trigger created no run, as a stable value safe to branch on in a CI pipeline. The accompanying `message` is the wording for a person to read and may be reworded at any time; this value will not be.",
7028
+ "billing-prevented: a billing restriction on the workspace stopped the run.",
7029
+ "branch-still-syncing: the environment was still syncing its flows.",
7030
+ "deployment-no-longer-live: the deployment was torn down or replaced by a newer one before the run started.",
7031
+ "duplicate-run: another run already covered this same deployment.",
7032
+ "environment-not-linked-to-branch: the environment has no branch to take flows from yet.",
7033
+ "environment-not-ready: the environment was still being prepared; retrying later can succeed.",
7034
+ "environment-terminated: the environment for the run is terminated.",
7035
+ "internal-error: QA Wolf could not start the run and the cause is on our side.",
7036
+ "low-risk-change: adaptive flow selection assessed the change as low risk, so nothing needed to run.",
7037
+ "no-flows-to-run: no flow was eligible, because the trigger's flows are in maintenance, still drafts, or missing on this branch.",
7038
+ "no-matching-trigger: no deployment trigger matched.",
7039
+ "no-pull-request: the trigger uses adaptive flow selection, which needs an open pull request, and this deployment had none.",
7040
+ "no-relevant-flows: adaptive flow selection found no existing flow covering this change.",
7041
+ "rate-limited: too many runs were requested at once; retrying later can succeed.",
7042
+ "run-not-created: the run never reached a decision.",
7043
+ "skipped: the run was skipped for a reason with no more specific value.",
7044
+ "test-configuration-error: the workspace's flows or dependency rules need fixing before this can run.",
7045
+ "trigger-not-found: the trigger no longer exists.",
7046
+ "workspace-inactive: the workspace is not active.",
7047
+ "workspace-not-ready: the workspace has not finished setting up."
7048
+ ].join(`
7049
+ `));
7050
+
7012
7051
  // node_modules/@qawolf/api-contracts/dist/v1/resource.js
7013
7052
  function resource(fields, { urlFieldDescription = "Absolute URL." } = {}) {
7014
7053
  return object({
@@ -7174,6 +7213,7 @@ var defaultIdSchemas = {
7174
7213
  issue: string2().min(1).describe("The id of the issue."),
7175
7214
  legacyTrigger: string2().min(1).describe("The id of the legacy trigger, from legacyTrigger.find."),
7176
7215
  run: string2().min(1).describe("The id of the run."),
7216
+ runAttempt: string2().min(1).describe("The id of the run attempt."),
7177
7217
  trigger: string2().min(1).describe("The id of the trigger."),
7178
7218
  workspace: string2().min(1).describe("The id of the workspace.")
7179
7219
  };
@@ -7351,7 +7391,8 @@ var runnerNameSchema = _enum([
7351
7391
  "basic",
7352
7392
  "playwright",
7353
7393
  "android",
7354
- "ios"
7394
+ "ios",
7395
+ "windows"
7355
7396
  ]);
7356
7397
  var runnerWorkspaceRequirement = "Read it from whoami.";
7357
7398
  var runnerWorkspaceIdDescription = `The workspace the runner belongs to. ${runnerWorkspaceRequirement}`;
@@ -7473,7 +7514,11 @@ function makeRunnerFailureSchema(reasons) {
7473
7514
 
7474
7515
  // node_modules/@qawolf/api-contracts/dist/v1/runner/inspectMobile.js
7475
7516
  var maxElementTextLength = 500;
7476
- var selectorStrategySchema = _enum(["ios-predicate", "shadow", "xpath"]);
7517
+ var selectorStrategySchema = _enum([
7518
+ "ios-predicate",
7519
+ "shadow",
7520
+ "xpath"
7521
+ ]);
7477
7522
  var elementsRequestSchema = discriminatedUnion("by", [
7478
7523
  object({
7479
7524
  by: literal("point"),
@@ -7638,6 +7683,65 @@ var runFilesSchema = record(string2(), string2()).superRefine((files, refinement
7638
7683
  }).refine((files) => runFilesByteLength(files) <= maxRunFilesByteLength, {
7639
7684
  error: `The files in one request may carry at most ${maxRunFilesByteLength} bytes in total.`
7640
7685
  });
7686
+ // node_modules/@qawolf/api-contracts/dist/v1/runner/runnerAction.js
7687
+ var maxSwipeDurationMs = 1e4;
7688
+ var selectorSchema2 = string2().min(1).max(maxSelectorLength).describe("The element to act on, resolved the way a screen object's own selector is.");
7689
+ var strategySchema = selectorStrategySchema.optional().describe("How `selector` is resolved. Defaults to `xpath`.");
7690
+ function refuseStrategyWithoutSelector(action, context) {
7691
+ if (action.strategy !== undefined && action.selector === undefined) {
7692
+ context.addIssue({
7693
+ code: "custom",
7694
+ message: "`strategy` says how to resolve a `selector`, so it needs one.",
7695
+ path: ["strategy"]
7696
+ });
7697
+ }
7698
+ }
7699
+ var tapActionSchema = strictObject({
7700
+ selector: selectorSchema2.optional(),
7701
+ strategy: strategySchema,
7702
+ type: literal("tap"),
7703
+ x: screenCoordinateSchema.optional(),
7704
+ y: screenCoordinateSchema.optional()
7705
+ }).superRefine((tap, context) => {
7706
+ refuseStrategyWithoutSelector(tap, context);
7707
+ const hasPoint = tap.x !== undefined || tap.y !== undefined;
7708
+ if (tap.selector !== undefined && hasPoint) {
7709
+ context.addIssue({
7710
+ code: "custom",
7711
+ message: "A tap aims at `x` and `y` or at a `selector`, not both.",
7712
+ path: ["selector"]
7713
+ });
7714
+ }
7715
+ if (tap.selector === undefined && (tap.x === undefined || tap.y === undefined)) {
7716
+ context.addIssue({
7717
+ code: "custom",
7718
+ message: "A tap needs both `x` and `y`, or a `selector`.",
7719
+ path: [tap.x === undefined ? "x" : "y"]
7720
+ });
7721
+ }
7722
+ });
7723
+ var swipeActionSchema = strictObject({
7724
+ duration_ms: int().positive().max(maxSwipeDurationMs).optional().describe("How long the swipe takes, in milliseconds. A slow one scrolls, a fast one flings. The device's default is 300."),
7725
+ from: screenPointSchema,
7726
+ to: screenPointSchema,
7727
+ type: literal("swipe")
7728
+ }).refine(({ from, to }) => from.x !== to.x || from.y !== to.y, {
7729
+ message: "A swipe whose `from` and `to` are the same travels nowhere.",
7730
+ path: ["to"]
7731
+ });
7732
+ var fillActionSchema = strictObject({
7733
+ selector: selectorSchema2,
7734
+ strategy: strategySchema,
7735
+ text: string2().max(maxTypedTextLength).describe("What the field holds afterwards, in place of its old value. Empty clears it."),
7736
+ type: literal("fill")
7737
+ });
7738
+ var runnerActionSchema = discriminatedUnion("type", [
7739
+ ...browserActionSchema.options,
7740
+ tapActionSchema,
7741
+ swipeActionSchema,
7742
+ fillActionSchema
7743
+ ]);
7744
+
7641
7745
  // node_modules/@qawolf/api-contracts/dist/v1/runner/screen.js
7642
7746
  var screenFailureReasons = [
7643
7747
  "runner-has-no-screen",
@@ -7646,17 +7750,18 @@ var screenFailureReasons = [
7646
7750
  ];
7647
7751
  var screenNotReadyDescription = "`screen-not-ready` if the runner has a screen that cannot serve this instant. Retry in a second or two: the desktop restarts when a run changes the display size, and it serves one see-or-act request at a time, so a screenshot or action already in flight is the usual reason. Do not submit a run to clear this — a run may restart the display and discard what is on it.";
7648
7752
  var screenNeedsARunDescription = "`screen-needs-a-run` if the runner's virtual desktop has never started. Waiting will not change this and retrying is pointless — call `runner.runFlow` with a flow that opens a browser, then ask for the screen again. On a runner image with a browser that has never run anything, any `runner.performAction` also starts the browser itself. Evaluating a snippet does not start the desktop.";
7649
- var runnerHasNoScreenDescription = "`runner-has-no-screen` if this runner is not one that runs a browser on a virtual desktop. Nothing about it can be seen or driven, and retrying will never help — launch a `playwright` runner instead.";
7753
+ var runnerHasNoScreenDescription = "`runner-has-no-screen` if this runner has no browser desktop to see or drive, and retrying will never help. Launch a `playwright` runner, or on `windows` use `runner.runFlow`.";
7650
7754
  var screenshotImageSchema = string2().min(1).describe("The screenshot, as a base64-encoded JPEG. Decode it and write the bytes to a `.jpg` file — writing this string to the file leaves you with base64 text rather than an image.");
7651
7755
 
7652
7756
  // node_modules/@qawolf/api-contracts/dist/v1/runner/performAction.js
7653
7757
  var unreachableDescription = "`runner-unreachable` if the runner could not be reached: it may still be starting, it may have terminated after inactivity, or it may have stopped answering mid-action. This does not mean the action was not performed — take a screenshot before repeating it.";
7654
- var notSupportedOnMobileDescription = "`action-not-supported-on-mobile` if the runner is a mobile device and this action has no touchscreen equivalent: `double_click`, `scroll`, `move`, `keypress` and `navigate`, and a `click` whose `button` is not `left`, are all pointer-device concepts a touchscreen has nothing to offer for. `click` taps, `drag` swipes between its path's first and last point, and `type` types into whatever the last tap focused.";
7758
+ var notSupportedOnMobileDescription = "`action-not-supported-on-mobile` if the runner is a mobile device and this action has no touchscreen equivalent: `double_click`, `scroll`, `move`, `keypress` and `navigate`, and a `click` whose `button` is not `left`, are all pointer-device concepts a touchscreen has nothing to offer for. `type` types into whatever the last tap focused. Deprecated on mobile and to be removed: `click` taps and `drag` swipes between its path's first and last point; send `tap` and `swipe` instead.";
7759
+ var mobileActionsDescription = "Only a mobile runner performs `tap`, `swipe` and `fill`: `tap` touches a point or the element a `selector` names, `swipe` moves from one point to another over `duration_ms`, and `fill` replaces the value of the field a `selector` names. A browser runner answers them with `action-not-supported-on-browser`.";
7655
7760
  var withScreenshotDescription = "With `withScreenshot: true`, the answer also carries `imageJpegBase64`: a screenshot taken after the action. One call instead of `runner.performAction` followed by `runner.takeScreenshot`. The action itself is performed exactly as without the option; if the screen could serve no frame after it — a display restart, or a `navigate` on a desktop that is still starting — the action's result comes back without `imageJpegBase64`, so take a screenshot separately rather than repeating the action. On a mobile runner the screenshot is the device's own, taken right after a performed action.";
7656
7761
  var maxActionErrorMessageLength = 1000;
7657
7762
  var makePerformActionOnRunnerContract = (ids) => {
7658
7763
  const input = object({
7659
- action: browserActionSchema.describe(`The action to perform. Coordinates are whole pixels on the runner's virtual desktop, in the same space as \`runner.takeScreenshot\`. The action shapes follow the computer-use vocabulary, minus \`screenshot\` (use \`runner.takeScreenshot\`) and \`wait\` (delay on the caller's side). A \`navigate\` does not go through the screen, so a screen that is not ready does not stop it. ${notSupportedOnMobileDescription}`),
7764
+ action: runnerActionSchema.describe(`The action to perform. Coordinates are whole pixels on the runner's virtual desktop, in the same space as \`runner.takeScreenshot\`. The browser action shapes follow the computer-use vocabulary, minus \`screenshot\` (use \`runner.takeScreenshot\`) and \`wait\` (delay on the caller's side). A \`navigate\` does not go through the screen, so a screen that is not ready does not stop it. ${notSupportedOnMobileDescription} ${mobileActionsDescription}`),
7660
7765
  id: runnerIdSchema.describe("Id of the runner to act on."),
7661
7766
  withScreenshot: boolean2().optional().describe(withScreenshotDescription),
7662
7767
  workspaceId: ids.workspace.optional().describe(runnerWorkspaceIdDescription)
@@ -7672,6 +7777,7 @@ var makePerformActionOnRunnerContract = (ids) => {
7672
7777
  makeRunnerFailureSchema([
7673
7778
  ...screenFailureReasons,
7674
7779
  "action-not-supported-on-mobile",
7780
+ "action-not-supported-on-browser",
7675
7781
  runnerUnreachableFailureReason
7676
7782
  ])
7677
7783
  ]);
@@ -7688,7 +7794,7 @@ var makePerformActionOnRunnerContract = (ids) => {
7688
7794
  openWorldHint: true,
7689
7795
  readOnlyHint: false
7690
7796
  },
7691
- description: `Perform one raw browser action on an interactive runner: click, double_click, move, drag, scroll, keypress, type, or navigate. One action per request, and the runner serves one at a time. A success means the action took effect. \`action-failed\`, with a reason, if it reached the runner and did not take effect. On a runner image with a browser, the first action on a runner that has never run anything starts its browser and waits for it, so it can take up to a minute to answer — no \`runner.runFlow\` is needed before acting; if the browser is still starting when the wait runs out, the answer is \`screen-not-ready\` and retrying converges. On a mobile runner, the same \`screen-needs-a-run\` and \`screen-not-ready\` outcomes mean no Appium session has started yet, or it did not answer this instant; \`runner.runFlow\` is what starts one, same as a browser. \`screen-needs-a-run\` if the browser could not be started that way — usually a runner whose runs all finished without starting its desktop; call \`runner.runFlow\` with a flow that opens a browser. ${screenNotReadyDescription} ${runnerHasNoScreenDescription} ${unreachableDescription}`,
7797
+ description: `Perform one raw action on an interactive runner: click, double_click, move, drag, scroll, keypress, type, or navigate; on mobile, tap, swipe, fill, or type. One action per request, and the runner serves one at a time. A success means the action took effect. \`action-failed\`, with a reason, if it reached the runner and did not take effect. On a runner image with a browser, the first action on a runner that has never run anything starts its browser and waits for it, so it can take up to a minute to answer — no \`runner.runFlow\` is needed before acting; if the browser is still starting when the wait runs out, the answer is \`screen-not-ready\` and retrying converges. On a mobile runner, the same \`screen-needs-a-run\` and \`screen-not-ready\` outcomes mean no Appium session has started yet, or it did not answer this instant; \`runner.runFlow\` is what starts one, same as a browser. \`screen-needs-a-run\` if the browser could not be started that way — usually a runner whose runs all finished without starting its desktop; call \`runner.runFlow\` with a flow that opens a browser. ${screenNotReadyDescription} ${runnerHasNoScreenDescription} ${unreachableDescription}`,
7692
7798
  input,
7693
7799
  kind: "write",
7694
7800
  name: "runner.performAction",
@@ -7951,7 +8057,7 @@ var makeTriggerScheduleFields = (ids) => ({
7951
8057
  environmentId: ids.environmentId.describe("The environment the scheduled runs happen in."),
7952
8058
  minuteOfHour: number2().int().min(0).max(59).optional().describe("Minutes past the hour an hourly schedule fires. Defaults to 0."),
7953
8059
  timeOfDay: string2().regex(/^([01]\d|2[0-3]):[0-5]\d$/).optional().describe('The wall clock time a daily or weekly schedule fires, as "HH:mm". Required when cadence is daily or weekly.'),
7954
- timezoneId: string2().min(1).refine(isTimezone, "Expected an IANA timezone, such as America/New_York.").optional().describe("The IANA timezone the schedule is read in, such as America/New_York. Required when cadence is daily or weekly, and when an hourly schedule names daysOfWeek, whose day boundaries it sets. An hourly schedule firing on every day needs none, and is read in America/Los_Angeles.")
8060
+ timezoneId: string2().min(1).refine(isTimezone, "Expected an IANA timezone, such as America/New_York.").optional().describe("The IANA timezone the schedule is read in, such as America/New_York. Required for every cadence: it sets the day boundaries daysOfWeek is read against, and the wall clock timeOfDay is read against.")
7955
8061
  });
7956
8062
  var makeTriggerDeploymentFields = (ids) => ({
7957
8063
  action: makeTriggerActionSchema(ids),
@@ -7992,12 +8098,12 @@ var checkAction = (action, ctx) => {
7992
8098
  };
7993
8099
  var requiredScheduleFields = {
7994
8100
  daily: ["timeOfDay", "timezoneId"],
7995
- hourly: [],
8101
+ hourly: ["timezoneId"],
7996
8102
  weekly: ["dayOfWeek", "timeOfDay", "timezoneId"]
7997
8103
  };
7998
8104
  var optionalScheduleFields = {
7999
8105
  daily: ["daysOfWeek"],
8000
- hourly: ["daysOfWeek", "minuteOfHour", "timezoneId"],
8106
+ hourly: ["daysOfWeek", "minuteOfHour"],
8001
8107
  weekly: []
8002
8108
  };
8003
8109
  var cadencesUsingField = {
@@ -8038,18 +8144,8 @@ var checkScheduleFields = (value, ctx) => {
8038
8144
  }
8039
8145
  }
8040
8146
  };
8041
- var checkHourlyZone = (value, ctx) => {
8042
- if (value.cadence !== "hourly" || value.daysOfWeek === undefined || value.timezoneId !== undefined)
8043
- return;
8044
- ctx.addIssue({
8045
- code: "custom",
8046
- message: "timezoneId is required when an hourly cadence names daysOfWeek.",
8047
- path: ["timezoneId"]
8048
- });
8049
- };
8050
8147
  var checkSchedule = (value, ctx) => {
8051
8148
  checkScheduleFields(value, ctx);
8052
- checkHourlyZone(value, ctx);
8053
8149
  if (value.action.kind === "generativeSuite") {
8054
8150
  ctx.addIssue({
8055
8151
  code: "custom",
@@ -8452,53 +8548,6 @@ var makeFindDeploymentsContract = (ids) => {
8452
8548
  };
8453
8549
  };
8454
8550
 
8455
- // node_modules/@qawolf/api-contracts/dist/v1/deployment/didNotRunReason.js
8456
- var didNotRunReasonSchema = _enum([
8457
- "billing-prevented",
8458
- "branch-still-syncing",
8459
- "deployment-no-longer-live",
8460
- "duplicate-run",
8461
- "environment-not-linked-to-branch",
8462
- "environment-not-ready",
8463
- "environment-terminated",
8464
- "internal-error",
8465
- "low-risk-change",
8466
- "no-flows-to-run",
8467
- "no-matching-trigger",
8468
- "no-pull-request",
8469
- "no-relevant-flows",
8470
- "rate-limited",
8471
- "run-not-created",
8472
- "skipped",
8473
- "test-configuration-error",
8474
- "trigger-not-found",
8475
- "workspace-inactive",
8476
- "workspace-not-ready"
8477
- ]).describe([
8478
- "Why the matched trigger created no run, as a stable value safe to branch on in a CI pipeline. The accompanying `message` is the wording for a person to read and may be reworded at any time; this value will not be.",
8479
- "billing-prevented: a billing restriction on the workspace stopped the run.",
8480
- "branch-still-syncing: the environment was still syncing its flows.",
8481
- "deployment-no-longer-live: the deployment was torn down or replaced by a newer one before the run started.",
8482
- "duplicate-run: another run already covered this same deployment.",
8483
- "environment-not-linked-to-branch: the environment has no branch to take flows from yet.",
8484
- "environment-not-ready: the environment was still being prepared; retrying later can succeed.",
8485
- "environment-terminated: the environment for the run is terminated.",
8486
- "internal-error: QA Wolf could not start the run and the cause is on our side.",
8487
- "low-risk-change: adaptive flow selection assessed the change as low risk, so nothing needed to run.",
8488
- "no-flows-to-run: no flow was eligible, because the trigger's flows are in maintenance, still drafts, or missing on this branch.",
8489
- "no-matching-trigger: no deployment trigger matched.",
8490
- "no-pull-request: the trigger uses adaptive flow selection, which needs an open pull request, and this deployment had none.",
8491
- "no-relevant-flows: adaptive flow selection found no existing flow covering this change.",
8492
- "rate-limited: too many runs were requested at once; retrying later can succeed.",
8493
- "run-not-created: the run never reached a decision.",
8494
- "skipped: the run was skipped for a reason with no more specific value.",
8495
- "test-configuration-error: the workspace's flows or dependency rules need fixing before this can run.",
8496
- "trigger-not-found: the trigger no longer exists.",
8497
- "workspace-inactive: the workspace is not active.",
8498
- "workspace-not-ready: the workspace has not finished setting up."
8499
- ].join(`
8500
- `));
8501
-
8502
8551
  // node_modules/@qawolf/api-contracts/dist/v1/deployment/listTriggerEvaluations.js
8503
8552
  var conditionKindSchema = _enum(["environment", "deployTarget", "branch", "service"]).describe("What the condition checks on the deployment: the environment it reported into, the deploy target it serves, the git branch of the deployed commit, or the service it deployed.");
8504
8553
  var conditionVerdictSchema = discriminatedUnion("outcome", [
@@ -9374,9 +9423,9 @@ var makeAddFlowsToIssueContract = (ids) => {
9374
9423
  // node_modules/@qawolf/api-contracts/dist/v1/issue/create.js
9375
9424
  var makeCreateIssueContract = (ids) => {
9376
9425
  const commonFields = {
9377
- 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."),
9378
9427
  name: string2().trim().min(1).max(255),
9379
- priority: issuePrioritySchema.optional().describe('Defaults to "unprioritized".'),
9428
+ priority: issuePrioritySchema.optional().describe('Defaults to "unprioritized" for bug reports and coverage requests.'),
9380
9429
  workspaceId: ids.workspace.optional().describe("The workspace to create the issue in. Required when authenticating with an organization or user API key.")
9381
9430
  };
9382
9431
  const input = discriminatedUnion("type", [
@@ -9388,6 +9437,13 @@ var makeCreateIssueContract = (ids) => {
9388
9437
  ...commonFields,
9389
9438
  estimatedDueDate: exports_iso.date().optional().describe("The calendar date the coverage is estimated to be complete, as YYYY-MM-DD."),
9390
9439
  type: literal("coverageRequest")
9440
+ }),
9441
+ object({
9442
+ ...commonFields,
9443
+ effort: _enum(["extraSmall", "small", "medium", "large", "extraLarge"]).describe("The effort to repair the flows."),
9444
+ priority: _enum(["low", "medium", "high", "urgent"]),
9445
+ reason: _enum(["dataChanged", "flowNeedsWork", "other", "uiChanged"]).describe("Why the flows need maintenance."),
9446
+ type: literal("maintenance")
9391
9447
  })
9392
9448
  ]);
9393
9449
  const output = object({
@@ -9399,7 +9455,7 @@ var makeCreateIssueContract = (ids) => {
9399
9455
  openWorldHint: true,
9400
9456
  readOnlyHint: false
9401
9457
  },
9402
- description: "Create a bug or coverage request issue for the caller's team. " + "Maintenance issues cannot be created through the public API.",
9458
+ description: "Create a bug report, maintenance report, or coverage request issue for the caller's team. " + "A user can create a maintenance report only when they can see the workspace's maintenance reports; " + "a team or organization API key credits it to the workspace's automation user. " + "Link its failed flows afterwards with run.diagnose.",
9403
9459
  input,
9404
9460
  kind: "write",
9405
9461
  name: "issue.create",
@@ -9432,7 +9488,7 @@ var makeRemoveFlowsFromIssueContract = (ids) => {
9432
9488
 
9433
9489
  // node_modules/@qawolf/api-contracts/dist/v1/issue/update.js
9434
9490
  var makeUpdateIssueContract = (ids) => {
9435
- 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.");
9436
9492
  const nameSchema = string2().trim().min(1).max(255);
9437
9493
  const input = object({
9438
9494
  description: descriptionSchema.optional(),
@@ -9488,6 +9544,8 @@ var makeLegacyTriggerSchema = (ids) => {
9488
9544
  isPaused: boolean2(),
9489
9545
  name: string2(),
9490
9546
  pausedAt: exports_iso.datetime().optional(),
9547
+ runConcurrencyLimit: string2().describe(`How many of the trigger's runs may execute at once: a whole number, "unlimited", or a concurrency expression. A trigger that stores no limit reads as "unlimited", which leaves the environment's limit in charge. Copy a number or an expression onto the current trigger action's runConcurrencyLimit, and omit that field when this reads "unlimited".`),
9548
+ shouldTriage: boolean2().describe("Whether QA Wolf investigates the failures of the runs this trigger creates. It becomes the current trigger action's investigateFailures, which is on unless the trigger says otherwise."),
9491
9549
  tags: array(namedIdentity)
9492
9550
  };
9493
9551
  return union([
@@ -9604,27 +9662,6 @@ var makeDiagnoseRunContract = (ids) => {
9604
9662
  };
9605
9663
  };
9606
9664
 
9607
- // node_modules/@qawolf/api-contracts/dist/v1/run/summary.js
9608
- var publicRunStatusValues = [
9609
- "queued",
9610
- "running",
9611
- "passed",
9612
- "failed",
9613
- "canceled"
9614
- ];
9615
- var makeRunSummaryFields = (ids) => ({
9616
- 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)."),
9617
- createdAt: exports_iso.datetime(),
9618
- git: object({
9619
- branch: string2().optional(),
9620
- commitMessage: string2().optional(),
9621
- commitSha: string2().optional(),
9622
- commitUrl: string2().optional().describe("Link to the commit on the code host.")
9623
- }).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."),
9624
- runId: ids.run,
9625
- 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.")
9626
- });
9627
-
9628
9665
  // node_modules/@qawolf/api-contracts/dist/v1/run/find.js
9629
9666
  var makeFindRunsContract = (ids) => {
9630
9667
  const input = object({
@@ -9635,9 +9672,11 @@ var makeFindRunsContract = (ids) => {
9635
9672
  });
9636
9673
  const output = object({
9637
9674
  nextCursor: nextCursorSchema,
9638
- runs: array(resource(makeRunSummaryFields(ids), {
9639
- urlFieldDescription: "Absolute URL of the run page."
9640
- })).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.")
9641
9680
  });
9642
9681
  return {
9643
9682
  annotations: {
@@ -9645,7 +9684,7 @@ var makeFindRunsContract = (ids) => {
9645
9684
  openWorldHint: false,
9646
9685
  readOnlyHint: true
9647
9686
  },
9648
- description: "List an environment's recent runs, newest first.",
9687
+ description: "List an environment's recent runs, newest first, including failed-attempt discovery metadata.",
9649
9688
  input,
9650
9689
  kind: "read",
9651
9690
  name: "run.find",
@@ -9669,6 +9708,7 @@ var makeGetRunContract = (ids) => {
9669
9708
  const automatedAttempt = discriminatedUnion("status", [
9670
9709
  object({
9671
9710
  ...artifactUrls,
9711
+ attemptId: ids.runAttempt.optional(),
9672
9712
  completedAt: exports_iso.datetime(),
9673
9713
  kind: automatedKind,
9674
9714
  startedAt: exports_iso.datetime(),
@@ -9676,12 +9716,14 @@ var makeGetRunContract = (ids) => {
9676
9716
  }),
9677
9717
  object({
9678
9718
  ...artifactUrls,
9719
+ attemptId: ids.runAttempt.optional(),
9679
9720
  completedAt: exports_iso.datetime(),
9680
9721
  kind: automatedKind,
9681
9722
  startedAt: exports_iso.datetime().optional().describe("Absent when the attempt failed before it could start."),
9682
9723
  status: literal("failed")
9683
9724
  }),
9684
9725
  object({
9726
+ attemptId: ids.runAttempt.optional(),
9685
9727
  completedAt: exports_iso.datetime().optional(),
9686
9728
  kind: automatedKind,
9687
9729
  startedAt: exports_iso.datetime().optional(),
@@ -9689,6 +9731,7 @@ var makeGetRunContract = (ids) => {
9689
9731
  })
9690
9732
  ]);
9691
9733
  const manualAttempt = object({
9734
+ attemptId: ids.runAttempt.optional(),
9692
9735
  completedAt: exports_iso.datetime(),
9693
9736
  kind: literal("manual").describe("The attempt ran by hand in the Wolf Browser."),
9694
9737
  startedAt: exports_iso.datetime(),
@@ -9737,6 +9780,83 @@ var makeGetRunContract = (ids) => {
9737
9780
  };
9738
9781
  };
9739
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
+
9740
9860
  // node_modules/@qawolf/api-contracts/dist/v1/run/reattempt.js
9741
9861
  var makeReattemptRunContract = (ids) => {
9742
9862
  const input = object({
@@ -9782,54 +9902,6 @@ var makeStopRunContract = (ids) => {
9782
9902
  };
9783
9903
  };
9784
9904
 
9785
- // node_modules/@qawolf/api-contracts/dist/v1/run/triage.js
9786
- var probability = number2().min(0).max(1);
9787
- var verdictAnswer = object({
9788
- choice: _enum(["bug", "maintenance"]),
9789
- confidence: probability,
9790
- probabilities: record(string2(), probability),
9791
- type: literal("choice")
9792
- });
9793
- var makeTriageRunContract = (ids) => {
9794
- const input = object({
9795
- flowId: ids.flow.describe("The flow that failed in the run."),
9796
- runId: ids.run
9797
- });
9798
- const decision = discriminatedUnion("type", [
9799
- object({
9800
- diagnosis: _enum(["bug", "maintenance"]),
9801
- type: literal("diagnose")
9802
- }),
9803
- object({
9804
- diagnosis: _enum(["bug", "maintenance"]),
9805
- type: literal("suggest")
9806
- }),
9807
- object({
9808
- type: literal("needsHuman")
9809
- })
9810
- ]);
9811
- const output = object({
9812
- answers: object({
9813
- verdict: verdictAnswer
9814
- }),
9815
- decision: decision.describe("What the triage would do with the verdict. The prototype records nothing; it only reports."),
9816
- model: string2(),
9817
- state: json().describe("The context that was sent to the model, for inspection.")
9818
- });
9819
- return {
9820
- annotations: {
9821
- destructiveHint: false,
9822
- openWorldHint: false,
9823
- readOnlyHint: true
9824
- },
9825
- description: "Prototype. Ask Jev, a TypeSafe System One model, whether a flow failure in a run is a bug in the product " + "or a test that needs maintenance. Compares the failing attempt with the flow's last passing run in the " + "same environment. Records nothing.",
9826
- input,
9827
- kind: "read",
9828
- name: "run.triage",
9829
- output
9830
- };
9831
- };
9832
-
9833
9905
  // node_modules/@qawolf/api-contracts/dist/v1/runner/evaluateSnippet.js
9834
9906
  var maxSnippetCodeLength = 64 * 1024;
9835
9907
  var makeEvaluateSnippetOnRunnerContract = (ids) => {
@@ -10345,7 +10417,11 @@ var makeListTagsContract = (ids) => {
10345
10417
 
10346
10418
  // node_modules/@qawolf/api-contracts/dist/v1/index.js
10347
10419
  var makeContractsV1 = (ids) => {
10348
- const resolvedIds = { ...defaultIdSchemas, ...ids };
10420
+ const resolvedIds = {
10421
+ ...defaultIdSchemas,
10422
+ ...ids,
10423
+ runAttempt: ids.runAttempt ?? defaultIdSchemas.runAttempt
10424
+ };
10349
10425
  return {
10350
10426
  agent: {
10351
10427
  get: makeAgentGetContract(resolvedIds),
@@ -10396,9 +10472,9 @@ var makeContractsV1 = (ids) => {
10396
10472
  diagnose: makeDiagnoseRunContract(resolvedIds),
10397
10473
  find: makeFindRunsContract(resolvedIds),
10398
10474
  get: makeGetRunContract(resolvedIds),
10475
+ getAttemptArtifacts: makeGetRunAttemptArtifactsContract(resolvedIds),
10399
10476
  reattempt: makeReattemptRunContract(resolvedIds),
10400
- stop: makeStopRunContract(resolvedIds),
10401
- triage: makeTriageRunContract(resolvedIds)
10477
+ stop: makeStopRunContract(resolvedIds)
10402
10478
  },
10403
10479
  runner: makeRunnerContracts(resolvedIds),
10404
10480
  skill: makeSkillContracts(),
@@ -10711,7 +10787,8 @@ var interactMessages = {
10711
10787
  actionFlagsWithStdin: '"-" reads the whole action from stdin, so an action flag passed alongside it would be ignored. Pipe the action in on its own, or name the action type and use flags.',
10712
10788
  actionMayHaveHappened: "The runner could not be reached, which does not mean the action was not performed: it may have stopped answering mid-action. Take a screenshot before repeating it.",
10713
10789
  actionNotJson: `Stdin did not hold a JSON action. Pipe one object, for example '{"type":"click","button":"left","x":480,"y":260}'.`,
10714
- actionNotSupportedOnMobile: (type) => `A mobile runner has a touchscreen, so it cannot perform ${type} as asked. It taps with a left-button click, swipes with drag, and types into whatever the last tap focused.`,
10790
+ actionNotSupportedOnBrowser: (type) => `Only a mobile runner performs ${type}. On a browser runner, click at --x and --y, drag along a --path, and type into whatever has focus.`,
10791
+ actionNotSupportedOnMobile: (type) => `A mobile runner has a touchscreen, so it cannot perform ${type} as asked. Use tap, swipe, fill, or type into whatever the last tap focused.`,
10715
10792
  actionFailedScreenshotToStdout: "Its screen was written to stdout as a JPEG, so look at that rather than sending the action again.",
10716
10793
  actionFailedScreenshotUnwritten: (detail) => `Its screen could not be written, because ${detail}, so take one with qawolf runner screenshot rather than sending the action again.`,
10717
10794
  actionFailedScreenshotWritten: (path) => `Its screen was written to ${path}, so look at that rather than sending the action again.`,
@@ -15031,4 +15108,4 @@ export {
15031
15108
  createRunnerSdk
15032
15109
  };
15033
15110
 
15034
- //# debugId=CF6139275CB5B8DC64756E2164756E21
15111
+ //# debugId=3EFB50CF5F60CF8264756E2164756E21