@exodus/xqa 1.17.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/xqa.cjs +1093 -811
  2. package/package.json +1 -1
package/dist/xqa.cjs CHANGED
@@ -1621,9 +1621,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
1621
1621
  if (fn) {
1622
1622
  this._exitCallback = fn;
1623
1623
  } else {
1624
- this._exitCallback = (err25) => {
1625
- if (err25.code !== "commander.executeSubCommandAsync") {
1626
- throw err25;
1624
+ this._exitCallback = (err26) => {
1625
+ if (err26.code !== "commander.executeSubCommandAsync") {
1626
+ throw err26;
1627
1627
  } else {
1628
1628
  }
1629
1629
  };
@@ -1699,12 +1699,12 @@ Expecting one of '${allowedValues.join("', '")}'`);
1699
1699
  _callParseArg(target, value, previous, invalidArgumentMessage) {
1700
1700
  try {
1701
1701
  return target.parseArg(value, previous);
1702
- } catch (err25) {
1703
- if (err25.code === "commander.invalidArgument") {
1704
- const message = `${invalidArgumentMessage} ${err25.message}`;
1705
- this.error(message, { exitCode: err25.exitCode, code: err25.code });
1702
+ } catch (err26) {
1703
+ if (err26.code === "commander.invalidArgument") {
1704
+ const message = `${invalidArgumentMessage} ${err26.message}`;
1705
+ this.error(message, { exitCode: err26.exitCode, code: err26.code });
1706
1706
  }
1707
- throw err25;
1707
+ throw err26;
1708
1708
  }
1709
1709
  }
1710
1710
  /**
@@ -2293,14 +2293,14 @@ Expecting one of '${allowedValues.join("', '")}'`);
2293
2293
  );
2294
2294
  }
2295
2295
  });
2296
- proc.on("error", (err25) => {
2297
- if (err25.code === "ENOENT") {
2296
+ proc.on("error", (err26) => {
2297
+ if (err26.code === "ENOENT") {
2298
2298
  this._checkForMissingExecutable(
2299
2299
  executableFile,
2300
2300
  executableDir,
2301
2301
  subcommand._name
2302
2302
  );
2303
- } else if (err25.code === "EACCES") {
2303
+ } else if (err26.code === "EACCES") {
2304
2304
  throw new Error(`'${executableFile}' not executable`);
2305
2305
  }
2306
2306
  if (!exitCallback) {
@@ -2311,7 +2311,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
2311
2311
  "commander.executeSubCommandAsync",
2312
2312
  "(error)"
2313
2313
  );
2314
- wrappedError.nestedError = err25;
2314
+ wrappedError.nestedError = err26;
2315
2315
  exitCallback(wrappedError);
2316
2316
  }
2317
2317
  });
@@ -3688,8 +3688,8 @@ var require_index_cjs = __commonJS({
3688
3688
  return new Ok(res.value);
3689
3689
  })));
3690
3690
  }
3691
- match(ok27, _err) {
3692
- return this._promise.then((res) => res.match(ok27, _err));
3691
+ match(ok28, _err) {
3692
+ return this._promise.then((res) => res.match(ok28, _err));
3693
3693
  }
3694
3694
  unwrapOr(t) {
3695
3695
  return this._promise.then((res) => res.unwrapOr(t));
@@ -3728,17 +3728,17 @@ var require_index_cjs = __commonJS({
3728
3728
  function okAsync10(value) {
3729
3729
  return new ResultAsync18(Promise.resolve(new Ok(value)));
3730
3730
  }
3731
- function errAsync10(err26) {
3732
- return new ResultAsync18(Promise.resolve(new Err(err26)));
3731
+ function errAsync10(err27) {
3732
+ return new ResultAsync18(Promise.resolve(new Err(err27)));
3733
3733
  }
3734
3734
  var fromPromise = ResultAsync18.fromPromise;
3735
3735
  var fromSafePromise2 = ResultAsync18.fromSafePromise;
3736
3736
  var fromAsyncThrowable10 = ResultAsync18.fromThrowable;
3737
3737
  var combineResultList = (resultList) => {
3738
- let acc = ok26([]);
3738
+ let acc = ok27([]);
3739
3739
  for (const result of resultList) {
3740
3740
  if (result.isErr()) {
3741
- acc = err25(result.error);
3741
+ acc = err26(result.error);
3742
3742
  break;
3743
3743
  } else {
3744
3744
  acc.map((list) => list.push(result.value));
@@ -3748,12 +3748,12 @@ var require_index_cjs = __commonJS({
3748
3748
  };
3749
3749
  var combineResultAsyncList = (asyncResultList) => ResultAsync18.fromSafePromise(Promise.all(asyncResultList)).andThen(combineResultList);
3750
3750
  var combineResultListWithAllErrors = (resultList) => {
3751
- let acc = ok26([]);
3751
+ let acc = ok27([]);
3752
3752
  for (const result of resultList) {
3753
3753
  if (result.isErr() && acc.isErr()) {
3754
3754
  acc.error.push(result.error);
3755
3755
  } else if (result.isErr() && acc.isOk()) {
3756
- acc = err25([result.error]);
3756
+ acc = err26([result.error]);
3757
3757
  } else if (result.isOk() && acc.isOk()) {
3758
3758
  acc.value.push(result.value);
3759
3759
  }
@@ -3767,9 +3767,9 @@ var require_index_cjs = __commonJS({
3767
3767
  return (...args) => {
3768
3768
  try {
3769
3769
  const result = fn(...args);
3770
- return ok26(result);
3770
+ return ok27(result);
3771
3771
  } catch (e3) {
3772
- return err25(errorFn ? errorFn(e3) : e3);
3772
+ return err26(errorFn ? errorFn(e3) : e3);
3773
3773
  }
3774
3774
  };
3775
3775
  }
@@ -3783,11 +3783,11 @@ var require_index_cjs = __commonJS({
3783
3783
  }
3784
3784
  Result3.combineWithAllErrors = combineWithAllErrors;
3785
3785
  })(exports2.Result || (exports2.Result = {}));
3786
- function ok26(value) {
3786
+ function ok27(value) {
3787
3787
  return new Ok(value);
3788
3788
  }
3789
- function err25(err26) {
3790
- return new Err(err26);
3789
+ function err26(err27) {
3790
+ return new Err(err27);
3791
3791
  }
3792
3792
  function safeTry(body) {
3793
3793
  const n3 = body().next();
@@ -3807,11 +3807,11 @@ var require_index_cjs = __commonJS({
3807
3807
  return !this.isOk();
3808
3808
  }
3809
3809
  map(f6) {
3810
- return ok26(f6(this.value));
3810
+ return ok27(f6(this.value));
3811
3811
  }
3812
3812
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
3813
3813
  mapErr(_f) {
3814
- return ok26(this.value);
3814
+ return ok27(this.value);
3815
3815
  }
3816
3816
  // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
3817
3817
  andThen(f6) {
@@ -3826,14 +3826,14 @@ var require_index_cjs = __commonJS({
3826
3826
  f6(this.value);
3827
3827
  } catch (e3) {
3828
3828
  }
3829
- return ok26(this.value);
3829
+ return ok27(this.value);
3830
3830
  }
3831
3831
  orTee(_f) {
3832
- return ok26(this.value);
3832
+ return ok27(this.value);
3833
3833
  }
3834
3834
  // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
3835
3835
  orElse(_f) {
3836
- return ok26(this.value);
3836
+ return ok27(this.value);
3837
3837
  }
3838
3838
  asyncAndThen(f6) {
3839
3839
  return f6(this.value);
@@ -3850,8 +3850,8 @@ var require_index_cjs = __commonJS({
3850
3850
  return this.value;
3851
3851
  }
3852
3852
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
3853
- match(ok27, _err) {
3854
- return ok27(this.value);
3853
+ match(ok28, _err) {
3854
+ return ok28(this.value);
3855
3855
  }
3856
3856
  safeUnwrap() {
3857
3857
  const value = this.value;
@@ -3882,27 +3882,27 @@ var require_index_cjs = __commonJS({
3882
3882
  }
3883
3883
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
3884
3884
  map(_f) {
3885
- return err25(this.error);
3885
+ return err26(this.error);
3886
3886
  }
3887
3887
  mapErr(f6) {
3888
- return err25(f6(this.error));
3888
+ return err26(f6(this.error));
3889
3889
  }
3890
3890
  andThrough(_f) {
3891
- return err25(this.error);
3891
+ return err26(this.error);
3892
3892
  }
3893
3893
  andTee(_f) {
3894
- return err25(this.error);
3894
+ return err26(this.error);
3895
3895
  }
3896
3896
  orTee(f6) {
3897
3897
  try {
3898
3898
  f6(this.error);
3899
3899
  } catch (e3) {
3900
3900
  }
3901
- return err25(this.error);
3901
+ return err26(this.error);
3902
3902
  }
3903
3903
  // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
3904
3904
  andThen(_f) {
3905
- return err25(this.error);
3905
+ return err26(this.error);
3906
3906
  }
3907
3907
  // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
3908
3908
  orElse(f6) {
@@ -3922,13 +3922,13 @@ var require_index_cjs = __commonJS({
3922
3922
  unwrapOr(v2) {
3923
3923
  return v2;
3924
3924
  }
3925
- match(_ok, err26) {
3926
- return err26(this.error);
3925
+ match(_ok, err27) {
3926
+ return err27(this.error);
3927
3927
  }
3928
3928
  safeUnwrap() {
3929
3929
  const error48 = this.error;
3930
3930
  return (function* () {
3931
- yield err25(error48);
3931
+ yield err26(error48);
3932
3932
  throw new Error("Do not use this generator out of `safeTry`");
3933
3933
  })();
3934
3934
  }
@@ -3948,13 +3948,13 @@ var require_index_cjs = __commonJS({
3948
3948
  exports2.Err = Err;
3949
3949
  exports2.Ok = Ok;
3950
3950
  exports2.ResultAsync = ResultAsync18;
3951
- exports2.err = err25;
3951
+ exports2.err = err26;
3952
3952
  exports2.errAsync = errAsync10;
3953
3953
  exports2.fromAsyncThrowable = fromAsyncThrowable10;
3954
3954
  exports2.fromPromise = fromPromise;
3955
3955
  exports2.fromSafePromise = fromSafePromise2;
3956
3956
  exports2.fromThrowable = fromThrowable17;
3957
- exports2.ok = ok26;
3957
+ exports2.ok = ok27;
3958
3958
  exports2.okAsync = okAsync10;
3959
3959
  exports2.safeTry = safeTry;
3960
3960
  }
@@ -11117,12 +11117,12 @@ var require_lib2 = __commonJS({
11117
11117
  var detectFile = (filepath, opts = {}) => new Promise((resolve, reject) => {
11118
11118
  let fd;
11119
11119
  const fs4 = (0, node_1.default)();
11120
- const handler2 = (err25, buffer) => {
11120
+ const handler2 = (err26, buffer) => {
11121
11121
  if (fd) {
11122
11122
  fs4.closeSync(fd);
11123
11123
  }
11124
- if (err25) {
11125
- reject(err25);
11124
+ if (err26) {
11125
+ reject(err26);
11126
11126
  } else if (buffer) {
11127
11127
  resolve((0, exports2.detect)(buffer));
11128
11128
  } else {
@@ -11133,9 +11133,9 @@ var require_lib2 = __commonJS({
11133
11133
  if (sampleSize > 0) {
11134
11134
  fd = fs4.openSync(filepath, "r");
11135
11135
  let sample = Buffer.allocUnsafe(sampleSize);
11136
- fs4.read(fd, sample, 0, sampleSize, opts.offset, (err25, bytesRead) => {
11137
- if (err25) {
11138
- handler2(err25, null);
11136
+ fs4.read(fd, sample, 0, sampleSize, opts.offset, (err26, bytesRead) => {
11137
+ if (err26) {
11138
+ handler2(err26, null);
11139
11139
  } else {
11140
11140
  if (bytesRead < sampleSize) {
11141
11141
  sample = sample.subarray(0, bytesRead);
@@ -15059,8 +15059,8 @@ var require_kind_of = __commonJS({
15059
15059
  if (typeof val.length === "number" && typeof val.callee === "function") {
15060
15060
  return true;
15061
15061
  }
15062
- } catch (err25) {
15063
- if (err25.message.indexOf("callee") !== -1) {
15062
+ } catch (err26) {
15063
+ if (err26.message.indexOf("callee") !== -1) {
15064
15064
  return true;
15065
15065
  }
15066
15066
  }
@@ -16283,7 +16283,7 @@ var require_function = __commonJS({
16283
16283
  return false;
16284
16284
  }
16285
16285
  return true;
16286
- } catch (err25) {
16286
+ } catch (err26) {
16287
16287
  return false;
16288
16288
  }
16289
16289
  }
@@ -18070,11 +18070,11 @@ var require_engines = __commonJS({
18070
18070
  str = "(function() {\nreturn " + str.trim() + ";\n}());";
18071
18071
  }
18072
18072
  return eval(str) || {};
18073
- } catch (err25) {
18074
- if (wrap !== false && /(unexpected|identifier)/i.test(err25.message)) {
18073
+ } catch (err26) {
18074
+ if (wrap !== false && /(unexpected|identifier)/i.test(err26.message)) {
18075
18075
  return parse(str, options, false);
18076
18076
  }
18077
- throw new SyntaxError(err25);
18077
+ throw new SyntaxError(err26);
18078
18078
  }
18079
18079
  },
18080
18080
  stringify: function() {
@@ -18636,9 +18636,9 @@ var require_main = __commonJS({
18636
18636
  options2.path = vaultPath;
18637
18637
  const result = DotenvModule.configDotenv(options2);
18638
18638
  if (!result.parsed) {
18639
- const err25 = new Error(`MISSING_DATA: Cannot parse ${vaultPath} for an unknown reason`);
18640
- err25.code = "MISSING_DATA";
18641
- throw err25;
18639
+ const err26 = new Error(`MISSING_DATA: Cannot parse ${vaultPath} for an unknown reason`);
18640
+ err26.code = "MISSING_DATA";
18641
+ throw err26;
18642
18642
  }
18643
18643
  const keys = _dotenvKey(options2).split(",");
18644
18644
  const length = keys.length;
@@ -18681,30 +18681,30 @@ var require_main = __commonJS({
18681
18681
  uri = new URL(dotenvKey);
18682
18682
  } catch (error48) {
18683
18683
  if (error48.code === "ERR_INVALID_URL") {
18684
- const err25 = new Error("INVALID_DOTENV_KEY: Wrong format. Must be in valid uri format like dotenv://:key_1234@dotenvx.com/vault/.env.vault?environment=development");
18685
- err25.code = "INVALID_DOTENV_KEY";
18686
- throw err25;
18684
+ const err26 = new Error("INVALID_DOTENV_KEY: Wrong format. Must be in valid uri format like dotenv://:key_1234@dotenvx.com/vault/.env.vault?environment=development");
18685
+ err26.code = "INVALID_DOTENV_KEY";
18686
+ throw err26;
18687
18687
  }
18688
18688
  throw error48;
18689
18689
  }
18690
18690
  const key = uri.password;
18691
18691
  if (!key) {
18692
- const err25 = new Error("INVALID_DOTENV_KEY: Missing key part");
18693
- err25.code = "INVALID_DOTENV_KEY";
18694
- throw err25;
18692
+ const err26 = new Error("INVALID_DOTENV_KEY: Missing key part");
18693
+ err26.code = "INVALID_DOTENV_KEY";
18694
+ throw err26;
18695
18695
  }
18696
18696
  const environment = uri.searchParams.get("environment");
18697
18697
  if (!environment) {
18698
- const err25 = new Error("INVALID_DOTENV_KEY: Missing environment part");
18699
- err25.code = "INVALID_DOTENV_KEY";
18700
- throw err25;
18698
+ const err26 = new Error("INVALID_DOTENV_KEY: Missing environment part");
18699
+ err26.code = "INVALID_DOTENV_KEY";
18700
+ throw err26;
18701
18701
  }
18702
18702
  const environmentKey = `DOTENV_VAULT_${environment.toUpperCase()}`;
18703
18703
  const ciphertext = result.parsed[environmentKey];
18704
18704
  if (!ciphertext) {
18705
- const err25 = new Error(`NOT_FOUND_DOTENV_ENVIRONMENT: Cannot locate environment ${environmentKey} in your .env.vault file.`);
18706
- err25.code = "NOT_FOUND_DOTENV_ENVIRONMENT";
18707
- throw err25;
18705
+ const err26 = new Error(`NOT_FOUND_DOTENV_ENVIRONMENT: Cannot locate environment ${environmentKey} in your .env.vault file.`);
18706
+ err26.code = "NOT_FOUND_DOTENV_ENVIRONMENT";
18707
+ throw err26;
18708
18708
  }
18709
18709
  return { ciphertext, key };
18710
18710
  }
@@ -18834,13 +18834,13 @@ var require_main = __commonJS({
18834
18834
  const invalidKeyLength = error48.message === "Invalid key length";
18835
18835
  const decryptionFailed = error48.message === "Unsupported state or unable to authenticate data";
18836
18836
  if (isRange || invalidKeyLength) {
18837
- const err25 = new Error("INVALID_DOTENV_KEY: It must be 64 characters long (or more)");
18838
- err25.code = "INVALID_DOTENV_KEY";
18839
- throw err25;
18837
+ const err26 = new Error("INVALID_DOTENV_KEY: It must be 64 characters long (or more)");
18838
+ err26.code = "INVALID_DOTENV_KEY";
18839
+ throw err26;
18840
18840
  } else if (decryptionFailed) {
18841
- const err25 = new Error("DECRYPTION_FAILED: Please check your DOTENV_KEY");
18842
- err25.code = "DECRYPTION_FAILED";
18843
- throw err25;
18841
+ const err26 = new Error("DECRYPTION_FAILED: Please check your DOTENV_KEY");
18842
+ err26.code = "DECRYPTION_FAILED";
18843
+ throw err26;
18844
18844
  } else {
18845
18845
  throw error48;
18846
18846
  }
@@ -18850,9 +18850,9 @@ var require_main = __commonJS({
18850
18850
  const debug = Boolean(options2 && options2.debug);
18851
18851
  const override = Boolean(options2 && options2.override);
18852
18852
  if (typeof parsed !== "object") {
18853
- const err25 = new Error("OBJECT_REQUIRED: Please check the processEnv argument being passed to populate");
18854
- err25.code = "OBJECT_REQUIRED";
18855
- throw err25;
18853
+ const err26 = new Error("OBJECT_REQUIRED: Please check the processEnv argument being passed to populate");
18854
+ err26.code = "OBJECT_REQUIRED";
18855
+ throw err26;
18856
18856
  }
18857
18857
  for (const key of Object.keys(parsed)) {
18858
18858
  if (Object.prototype.hasOwnProperty.call(processEnv, key)) {
@@ -21993,8 +21993,8 @@ var require_picomatch = __commonJS({
21993
21993
  try {
21994
21994
  const opts = options2 || {};
21995
21995
  return new RegExp(source, opts.flags || (opts.nocase ? "i" : ""));
21996
- } catch (err25) {
21997
- if (options2 && options2.debug === true) throw err25;
21996
+ } catch (err26) {
21997
+ if (options2 && options2.debug === true) throw err26;
21998
21998
  return /$^/;
21999
21999
  }
22000
22000
  };
@@ -22401,8 +22401,8 @@ var require_merge2 = __commonJS({
22401
22401
  }
22402
22402
  next();
22403
22403
  }
22404
- function onerror(err25) {
22405
- mergedStream.emit("error", err25);
22404
+ function onerror(err26) {
22405
+ mergedStream.emit("error", err26);
22406
22406
  }
22407
22407
  if (stream._readableState.endEmitted) {
22408
22408
  return next();
@@ -22766,8 +22766,8 @@ var require_out = __commonJS({
22766
22766
  var require_queue_microtask = __commonJS({
22767
22767
  "../../node_modules/.pnpm/queue-microtask@1.2.3/node_modules/queue-microtask/index.js"(exports2, module2) {
22768
22768
  var promise2;
22769
- module2.exports = typeof queueMicrotask === "function" ? queueMicrotask.bind(typeof window !== "undefined" ? window : global) : (cb2) => (promise2 || (promise2 = Promise.resolve())).then(cb2).catch((err25) => setTimeout(() => {
22770
- throw err25;
22769
+ module2.exports = typeof queueMicrotask === "function" ? queueMicrotask.bind(typeof window !== "undefined" ? window : global) : (cb2) => (promise2 || (promise2 = Promise.resolve())).then(cb2).catch((err26) => setTimeout(() => {
22770
+ throw err26;
22771
22771
  }, 0));
22772
22772
  }
22773
22773
  });
@@ -22788,32 +22788,32 @@ var require_run_parallel = __commonJS({
22788
22788
  results = {};
22789
22789
  pending = keys.length;
22790
22790
  }
22791
- function done(err25) {
22791
+ function done(err26) {
22792
22792
  function end() {
22793
- if (cb2) cb2(err25, results);
22793
+ if (cb2) cb2(err26, results);
22794
22794
  cb2 = null;
22795
22795
  }
22796
22796
  if (isSync) queueMicrotask2(end);
22797
22797
  else end();
22798
22798
  }
22799
- function each(i3, err25, result) {
22799
+ function each(i3, err26, result) {
22800
22800
  results[i3] = result;
22801
- if (--pending === 0 || err25) {
22802
- done(err25);
22801
+ if (--pending === 0 || err26) {
22802
+ done(err26);
22803
22803
  }
22804
22804
  }
22805
22805
  if (!pending) {
22806
22806
  done(null);
22807
22807
  } else if (keys) {
22808
22808
  keys.forEach(function(key) {
22809
- tasks[key](function(err25, result) {
22810
- each(key, err25, result);
22809
+ tasks[key](function(err26, result) {
22810
+ each(key, err26, result);
22811
22811
  });
22812
22812
  });
22813
22813
  } else {
22814
22814
  tasks.forEach(function(task, i3) {
22815
- task(function(err25, result) {
22816
- each(i3, err25, result);
22815
+ task(function(err26, result) {
22816
+ each(i3, err26, result);
22817
22817
  });
22818
22818
  });
22819
22819
  }
@@ -23385,16 +23385,16 @@ var require_queue = __commonJS({
23385
23385
  this.context = null;
23386
23386
  this.errorHandler = null;
23387
23387
  var self2 = this;
23388
- this.worked = function worked(err25, result) {
23388
+ this.worked = function worked(err26, result) {
23389
23389
  var callback = self2.callback;
23390
23390
  var errorHandler = self2.errorHandler;
23391
23391
  var val = self2.value;
23392
23392
  self2.value = null;
23393
23393
  self2.callback = noop4;
23394
23394
  if (self2.errorHandler) {
23395
- errorHandler(err25, val);
23395
+ errorHandler(err26, val);
23396
23396
  }
23397
- callback.call(self2.context, err25, result);
23397
+ callback.call(self2.context, err26, result);
23398
23398
  self2.release(self2);
23399
23399
  };
23400
23400
  }
@@ -23418,9 +23418,9 @@ var require_queue = __commonJS({
23418
23418
  return queue;
23419
23419
  function push(value) {
23420
23420
  var p = new Promise(function(resolve, reject) {
23421
- pushCb(value, function(err25, result) {
23422
- if (err25) {
23423
- reject(err25);
23421
+ pushCb(value, function(err26, result) {
23422
+ if (err26) {
23423
+ reject(err26);
23424
23424
  return;
23425
23425
  }
23426
23426
  resolve(result);
@@ -23431,9 +23431,9 @@ var require_queue = __commonJS({
23431
23431
  }
23432
23432
  function unshift(value) {
23433
23433
  var p = new Promise(function(resolve, reject) {
23434
- unshiftCb(value, function(err25, result) {
23435
- if (err25) {
23436
- reject(err25);
23434
+ unshiftCb(value, function(err26, result) {
23435
+ if (err26) {
23436
+ reject(err26);
23437
23437
  return;
23438
23438
  }
23439
23439
  resolve(result);
@@ -24654,7 +24654,7 @@ var {
24654
24654
  } = import_index.default;
24655
24655
 
24656
24656
  // src/commands/analyse-command.ts
24657
- var import_promises17 = require("node:fs/promises");
24657
+ var import_promises18 = require("node:fs/promises");
24658
24658
 
24659
24659
  // ../../packages/pipeline/dist/index.js
24660
24660
  var import_node_fs2 = require("node:fs");
@@ -27947,9 +27947,9 @@ var tq = k((oq) => {
27947
27947
  });
27948
27948
  var sq = k((aq) => {
27949
27949
  Object.defineProperty(aq, "__esModule", { value: true });
27950
- var ok26 = Q$(), tk = { keyword: "not", schemaType: ["object", "boolean"], trackErrors: true, code($) {
27950
+ var ok27 = Q$(), tk = { keyword: "not", schemaType: ["object", "boolean"], trackErrors: true, code($) {
27951
27951
  let { gen: X, schema: J, it: Q } = $;
27952
- if ((0, ok26.alwaysValidSchema)(Q, J)) {
27952
+ if ((0, ok27.alwaysValidSchema)(Q, J)) {
27953
27953
  $.fail();
27954
27954
  return;
27955
27955
  }
@@ -56400,6 +56400,24 @@ function createMobileIosServer(udid = "booted", extraTools = []) {
56400
56400
  });
56401
56401
  }
56402
56402
 
56403
+ // ../../packages/shared/dist/confidence.js
56404
+ var CONFIDENCE_LABELS = ["HIGH", "MEDIUM", "LOW"];
56405
+ var confidenceLabelSchema = external_exports.enum(CONFIDENCE_LABELS);
56406
+ var CONFIDENCE_ORDER = {
56407
+ LOW: 0,
56408
+ MEDIUM: 1,
56409
+ HIGH: 2
56410
+ };
56411
+ function compareConfidence(left, right) {
56412
+ return CONFIDENCE_ORDER[left] - CONFIDENCE_ORDER[right];
56413
+ }
56414
+ function maxConfidence(left, right) {
56415
+ return compareConfidence(left, right) >= 0 ? left : right;
56416
+ }
56417
+ function meetsConfidenceThreshold(label, threshold) {
56418
+ return compareConfidence(label, threshold) >= 0;
56419
+ }
56420
+
56403
56421
  // ../../packages/shared/dist/finding-schema.js
56404
56422
  var findingSchema = external_exports.object({
56405
56423
  triggerType: external_exports.enum([
@@ -56420,12 +56438,15 @@ var findingSchema = external_exports.object({
56420
56438
  ]),
56421
56439
  flow: external_exports.string(),
56422
56440
  steps: external_exports.array(external_exports.string()),
56423
- confidence: external_exports.number(),
56441
+ confidence: confidenceLabelSchema,
56424
56442
  description: external_exports.string(),
56425
56443
  screenshots: external_exports.array(external_exports.string()),
56426
56444
  agent: external_exports.string()
56427
56445
  });
56428
56446
 
56447
+ // ../../packages/shared/dist/finding-input-schema.js
56448
+ var findingInputSchema = findingSchema.omit({ agent: true, screenshots: true, confidence: true }).extend({ confidence: confidenceLabelSchema });
56449
+
56429
56450
  // ../../packages/shared/dist/run-paths.js
56430
56451
  var import_node_path2 = __toESM(require("node:path"), 1);
56431
56452
  var import_neverthrow8 = __toESM(require_index_cjs(), 1);
@@ -56458,8 +56479,8 @@ function dismissalsPath(baseDirectory, override) {
56458
56479
  }
56459
56480
 
56460
56481
  // ../../packages/pipeline/dist/index.js
56461
- var import_neverthrow30 = __toESM(require_index_cjs(), 1);
56462
- var import_promises15 = require("node:timers/promises");
56482
+ var import_neverthrow32 = __toESM(require_index_cjs(), 1);
56483
+ var import_promises16 = require("node:timers/promises");
56463
56484
 
56464
56485
  // ../../agents/analyser/dist/index.js
56465
56486
  var import_promises7 = require("node:fs/promises");
@@ -57424,6 +57445,47 @@ function formatMemoryElements(elements) {
57424
57445
  (element) => `${element.label} [${String(Math.round(element.confidence * PCT_MULTIPLIER))}%${element.phase === "after-scroll" ? "\u2193" : ""}]`
57425
57446
  ).join(", ");
57426
57447
  }
57448
+ function inspectorLabel(stepIndex, screenLabel) {
57449
+ return `inspector: step ${String(stepIndex + 1)} (${screenLabel})`;
57450
+ }
57451
+ function inspectorFailLines(label, event) {
57452
+ const desc = event.finding?.description ?? "unknown finding";
57453
+ return [
57454
+ { kind: "text", style: "error", text: `${label} \u2014 \u2716 ${desc}`, source: "inspector" },
57455
+ { kind: "annotation", level: "warning", message: `${label} \u2014 ${desc}` }
57456
+ ];
57457
+ }
57458
+ function normalizeInspectorStepStart(event) {
57459
+ return [
57460
+ {
57461
+ kind: "text",
57462
+ style: "default",
57463
+ text: `inspector: analysing step ${String(event.stepIndex + 1)} (${event.screenLabel})`,
57464
+ source: "inspector"
57465
+ }
57466
+ ];
57467
+ }
57468
+ function normalizeInspectorStep(event) {
57469
+ const label = inspectorLabel(event.stepIndex, event.screenLabel);
57470
+ switch (event.outcome) {
57471
+ case "pass": {
57472
+ return [
57473
+ { kind: "text", style: "success", text: `${label} \u2014 matches design`, source: "inspector" }
57474
+ ];
57475
+ }
57476
+ case "fail": {
57477
+ return inspectorFailLines(label, event);
57478
+ }
57479
+ case "stale": {
57480
+ return [
57481
+ { kind: "text", style: "default", text: `${label} \u2014 stale artboard`, source: "inspector" }
57482
+ ];
57483
+ }
57484
+ case "skip": {
57485
+ return [{ kind: "text", style: "default", text: `${label} \u2014 skipped`, source: "inspector" }];
57486
+ }
57487
+ }
57488
+ }
57427
57489
  var HIDDEN_TOOL_ARGS = /* @__PURE__ */ new Set(["device"]);
57428
57490
  var SCREEN_PREVIEW_LENGTH = 80;
57429
57491
  var MS_PER_SECOND22 = 1e3;
@@ -57442,7 +57504,20 @@ function normalizeTimeoutGraceEntered(event) {
57442
57504
  {
57443
57505
  kind: "annotation",
57444
57506
  level: "warning",
57445
- message: `${event.agent}: soft deadline reached \u2014 ${String(seconds)}s grace period to emit findings`
57507
+ message: `${event.agent}: soft deadline reached \u2014 ${String(seconds)}s grace period before interrupt`
57508
+ }
57509
+ ];
57510
+ }
57511
+ function normalizeFindingReported(event) {
57512
+ const marker = `#${String(event.findingIndex + 1)} [${event.finding.triggerType}]`;
57513
+ const header = `${event.agent}: finding ${marker} \u2014 ${event.finding.description}`;
57514
+ return [
57515
+ { kind: "text", style: "error", text: header },
57516
+ { kind: "text", style: "dim", text: ` screenshot: ${event.screenshotPath}` },
57517
+ {
57518
+ kind: "annotation",
57519
+ level: "warning",
57520
+ message: `${event.agent} finding ${marker}`
57446
57521
  }
57447
57522
  ];
57448
57523
  }
@@ -57556,47 +57631,6 @@ function normalizeError(event) {
57556
57631
  }
57557
57632
  return lines;
57558
57633
  }
57559
- function inspectorLabel(stepIndex, screenLabel) {
57560
- return `inspector: step ${String(stepIndex + 1)} (${screenLabel})`;
57561
- }
57562
- function normalizeInspectorStepStart(event) {
57563
- return [
57564
- {
57565
- kind: "text",
57566
- style: "default",
57567
- text: `inspector: analysing step ${String(event.stepIndex + 1)} (${event.screenLabel})`,
57568
- source: "inspector"
57569
- }
57570
- ];
57571
- }
57572
- function inspectorFailLines(label, event) {
57573
- const desc = event.finding?.description ?? "unknown finding";
57574
- return [
57575
- { kind: "text", style: "error", text: `${label} \u2014 \u2716 ${desc}`, source: "inspector" },
57576
- { kind: "annotation", level: "warning", message: `${label} \u2014 ${desc}` }
57577
- ];
57578
- }
57579
- function normalizeInspectorStep(event) {
57580
- const label = inspectorLabel(event.stepIndex, event.screenLabel);
57581
- switch (event.outcome) {
57582
- case "pass": {
57583
- return [
57584
- { kind: "text", style: "success", text: `${label} \u2014 matches design`, source: "inspector" }
57585
- ];
57586
- }
57587
- case "fail": {
57588
- return inspectorFailLines(label, event);
57589
- }
57590
- case "stale": {
57591
- return [
57592
- { kind: "text", style: "default", text: `${label} \u2014 stale artboard`, source: "inspector" }
57593
- ];
57594
- }
57595
- case "skip": {
57596
- return [{ kind: "text", style: "default", text: `${label} \u2014 skipped`, source: "inspector" }];
57597
- }
57598
- }
57599
- }
57600
57634
  var HANDLERS2 = {
57601
57635
  STAGE_START: (event) => normalizeStageStart(event),
57602
57636
  STAGE_END: (event) => normalizeStageEnd(event),
@@ -57615,7 +57649,8 @@ var HANDLERS2 = {
57615
57649
  INSPECTOR_STEP_START: (event) => normalizeInspectorStepStart(event),
57616
57650
  INSPECTOR_STEP: (event) => normalizeInspectorStep(event),
57617
57651
  TIMEOUT_GRACE_ENTERED: (event) => normalizeTimeoutGraceEntered(event),
57618
- VISUAL_STEP: () => []
57652
+ VISUAL_STEP: () => [],
57653
+ FINDING_REPORTED: (event) => normalizeFindingReported(event)
57619
57654
  };
57620
57655
  function normalizeAgentEvent(event, verbose) {
57621
57656
  return HANDLERS2[event.type](event, verbose);
@@ -58361,15 +58396,15 @@ async function makeRequest(url2, fetchOptions, fetchFn = fetch) {
58361
58396
  return response;
58362
58397
  }
58363
58398
  function handleResponseError(e3, url2) {
58364
- let err25 = e3;
58365
- if (err25.name === "AbortError") {
58366
- err25 = new GoogleGenerativeAIAbortError(`Request aborted when fetching ${url2.toString()}: ${e3.message}`);
58367
- err25.stack = e3.stack;
58399
+ let err26 = e3;
58400
+ if (err26.name === "AbortError") {
58401
+ err26 = new GoogleGenerativeAIAbortError(`Request aborted when fetching ${url2.toString()}: ${e3.message}`);
58402
+ err26.stack = e3.stack;
58368
58403
  } else if (!(e3 instanceof GoogleGenerativeAIFetchError || e3 instanceof GoogleGenerativeAIRequestInputError)) {
58369
- err25 = new GoogleGenerativeAIError(`Error fetching from ${url2.toString()}: ${e3.message}`);
58370
- err25.stack = e3.stack;
58404
+ err26 = new GoogleGenerativeAIError(`Error fetching from ${url2.toString()}: ${e3.message}`);
58405
+ err26.stack = e3.stack;
58371
58406
  }
58372
- throw err25;
58407
+ throw err26;
58373
58408
  }
58374
58409
  async function handleResponseNotOk(response, url2) {
58375
58410
  let message = "";
@@ -58616,14 +58651,14 @@ function getResponseStream(inputStream) {
58616
58651
  }
58617
58652
  return pump();
58618
58653
  }).catch((e3) => {
58619
- let err25 = e3;
58620
- err25.stack = e3.stack;
58621
- if (err25.name === "AbortError") {
58622
- err25 = new GoogleGenerativeAIAbortError("Request aborted when reading from the stream");
58654
+ let err26 = e3;
58655
+ err26.stack = e3.stack;
58656
+ if (err26.name === "AbortError") {
58657
+ err26 = new GoogleGenerativeAIAbortError("Request aborted when reading from the stream");
58623
58658
  } else {
58624
- err25 = new GoogleGenerativeAIError("Error reading from the stream");
58659
+ err26 = new GoogleGenerativeAIError("Error reading from the stream");
58625
58660
  }
58626
- throw err25;
58661
+ throw err26;
58627
58662
  });
58628
58663
  }
58629
58664
  }
@@ -59219,15 +59254,15 @@ async function makeRequest2(url2, fetchOptions, fetchFn = fetch) {
59219
59254
  return response;
59220
59255
  }
59221
59256
  function handleResponseError2(e3, url2) {
59222
- let err25 = e3;
59223
- if (err25.name === "AbortError") {
59224
- err25 = new GoogleGenerativeAIAbortError2(`Request aborted when fetching ${url2.toString()}: ${e3.message}`);
59225
- err25.stack = e3.stack;
59257
+ let err26 = e3;
59258
+ if (err26.name === "AbortError") {
59259
+ err26 = new GoogleGenerativeAIAbortError2(`Request aborted when fetching ${url2.toString()}: ${e3.message}`);
59260
+ err26.stack = e3.stack;
59226
59261
  } else if (!(e3 instanceof GoogleGenerativeAIFetchError2 || e3 instanceof GoogleGenerativeAIRequestInputError2)) {
59227
- err25 = new GoogleGenerativeAIError2(`Error fetching from ${url2.toString()}: ${e3.message}`);
59228
- err25.stack = e3.stack;
59262
+ err26 = new GoogleGenerativeAIError2(`Error fetching from ${url2.toString()}: ${e3.message}`);
59263
+ err26.stack = e3.stack;
59229
59264
  }
59230
- throw err25;
59265
+ throw err26;
59231
59266
  }
59232
59267
  async function handleResponseNotOk2(response, url2) {
59233
59268
  let message = "";
@@ -59542,7 +59577,16 @@ var DynamicRetrievalMode2;
59542
59577
  var import_neverthrow11 = __toESM(require_index_cjs(), 1);
59543
59578
  var MAX_POLL_ATTEMPTS = 30;
59544
59579
  var POLL_INTERVAL_MS = 2e3;
59545
- var findingsArraySchema = external_exports.array(findingSchema);
59580
+ var categoricalFindingSchema = external_exports.object({
59581
+ triggerType: external_exports.string(),
59582
+ flow: external_exports.string(),
59583
+ steps: external_exports.array(external_exports.string()),
59584
+ description: external_exports.string(),
59585
+ confidence: external_exports.enum(["HIGH", "MEDIUM"]),
59586
+ screenshots: external_exports.array(external_exports.string()),
59587
+ agent: external_exports.string()
59588
+ });
59589
+ var categoricalFindingsArraySchema = external_exports.array(categoricalFindingSchema);
59546
59590
  var safeJsonParse2 = (0, import_neverthrow11.fromThrowable)(JSON.parse);
59547
59591
  var FINDINGS_RESPONSE_SCHEMA = {
59548
59592
  type: "array",
@@ -59561,12 +59605,12 @@ var FINDINGS_RESPONSE_SCHEMA = {
59561
59605
  },
59562
59606
  flow: { type: "string" },
59563
59607
  steps: { type: "array", items: { type: "string" } },
59564
- confidence: { type: "number" },
59565
59608
  description: { type: "string" },
59609
+ confidence: { type: "string", format: "enum", enum: ["HIGH", "MEDIUM"] },
59566
59610
  screenshots: { type: "array", items: { type: "string" } },
59567
59611
  agent: { type: "string", format: "enum", enum: ["analyser"] }
59568
59612
  },
59569
- required: ["triggerType", "flow", "steps", "confidence", "description", "screenshots", "agent"]
59613
+ required: ["triggerType", "flow", "steps", "description", "confidence", "screenshots", "agent"]
59570
59614
  }
59571
59615
  };
59572
59616
  function extractFileName(fileUri) {
@@ -59615,17 +59659,21 @@ function parseAnalysisResponse(text) {
59615
59659
  return (0, import_neverthrow11.err)({ type: "REQUEST_FAILED", cause: parseResult.error });
59616
59660
  }
59617
59661
  const raw = parseResult.value;
59618
- const validated = findingsArraySchema.safeParse(raw);
59662
+ const validated = categoricalFindingsArraySchema.safeParse(raw);
59619
59663
  if (!validated.success) {
59620
59664
  return (0, import_neverthrow11.err)({ type: "SCHEMA_VALIDATION_FAILED", cause: validated.error });
59621
59665
  }
59622
- return (0, import_neverthrow11.ok)(validated.data);
59666
+ const findings = validated.data.map((finding) => ({ ...finding }));
59667
+ return (0, import_neverthrow11.ok)(findings);
59623
59668
  }
59669
+ var STEP_BY_STEP_DIRECTIVE = "Think step by step before calling set_output.";
59624
59670
  function buildGenerativeModel(apiKey, model) {
59625
59671
  const genAI = new GoogleGenerativeAI(apiKey);
59626
59672
  return genAI.getGenerativeModel({
59627
59673
  model,
59674
+ systemInstruction: STEP_BY_STEP_DIRECTIVE,
59628
59675
  generationConfig: {
59676
+ temperature: 0,
59629
59677
  responseMimeType: "application/json",
59630
59678
  responseSchema: FINDINGS_RESPONSE_SCHEMA
59631
59679
  }
@@ -59687,9 +59735,11 @@ var OUTPUT_FIELDS_SECTION = `For each finding:
59687
59735
  - \`triggerType\`: the category in parentheses from the section headings above
59688
59736
  - \`flow\`: name of the user flow from the snapshots (e.g. "send-funds", "onboarding")
59689
59737
  - \`steps\`: stepIndex values from the snapshots visible during or immediately before the issue
59690
- - \`confidence\`: 0.8\u20131.0 for unambiguous issues; 0.5\u20130.8 for visible but possibly intentional; omit anything below 0.5
59691
- - \`description\`: name the element, state what it was doing, and state how long or across how many steps the issue persisted
59692
- - \`screenshots\`: the \`screenshotPath\` values from the matching snapshots as reference identifiers \u2014 or the stepIndex as a string if no path is present`;
59738
+ - \`description\`: name the element, state what it was doing, and state how long or across how many steps the issue persisted \u2014 write this first, before committing to a confidence label
59739
+ - \`confidence\`: HIGH for unambiguous regressions visible repeatedly with no plausible intentional cause; MEDIUM for issues that are visible but ambiguous (could be a deliberate design choice); LOW \u2014 do not include the finding at all, omit it entirely
59740
+ - \`screenshots\`: the \`screenshotPath\` values from the matching snapshots as reference identifiers \u2014 or the stepIndex as a string if no path is present
59741
+
59742
+ Write the description first \u2014 justify what you saw and across how many steps \u2014 only then commit to a HIGH or MEDIUM label.`;
59693
59743
  function buildAnalyserPrompt(snapshots) {
59694
59744
  const snapshotHistory = JSON.stringify(snapshots, void 0, 2);
59695
59745
  return `You are a QA engineer watching a recorded mobile app session. Your task is to identify issues that can only be detected by watching the full video \u2014 things a static screenshot or accessibility tree cannot reveal.
@@ -59812,34 +59862,34 @@ var uuid42 = function() {
59812
59862
  };
59813
59863
 
59814
59864
  // ../../node_modules/.pnpm/@anthropic-ai+sdk@0.87.0_zod@4.3.6/node_modules/@anthropic-ai/sdk/internal/errors.mjs
59815
- function isAbortError(err25) {
59816
- return typeof err25 === "object" && err25 !== null && // Spec-compliant fetch implementations
59817
- ("name" in err25 && err25.name === "AbortError" || // Expo fetch
59818
- "message" in err25 && String(err25.message).includes("FetchRequestCanceledException"));
59819
- }
59820
- var castToError = (err25) => {
59821
- if (err25 instanceof Error)
59822
- return err25;
59823
- if (typeof err25 === "object" && err25 !== null) {
59865
+ function isAbortError(err26) {
59866
+ return typeof err26 === "object" && err26 !== null && // Spec-compliant fetch implementations
59867
+ ("name" in err26 && err26.name === "AbortError" || // Expo fetch
59868
+ "message" in err26 && String(err26.message).includes("FetchRequestCanceledException"));
59869
+ }
59870
+ var castToError = (err26) => {
59871
+ if (err26 instanceof Error)
59872
+ return err26;
59873
+ if (typeof err26 === "object" && err26 !== null) {
59824
59874
  try {
59825
- if (Object.prototype.toString.call(err25) === "[object Error]") {
59826
- const error48 = new Error(err25.message, err25.cause ? { cause: err25.cause } : {});
59827
- if (err25.stack)
59828
- error48.stack = err25.stack;
59829
- if (err25.cause && !error48.cause)
59830
- error48.cause = err25.cause;
59831
- if (err25.name)
59832
- error48.name = err25.name;
59875
+ if (Object.prototype.toString.call(err26) === "[object Error]") {
59876
+ const error48 = new Error(err26.message, err26.cause ? { cause: err26.cause } : {});
59877
+ if (err26.stack)
59878
+ error48.stack = err26.stack;
59879
+ if (err26.cause && !error48.cause)
59880
+ error48.cause = err26.cause;
59881
+ if (err26.name)
59882
+ error48.name = err26.name;
59833
59883
  return error48;
59834
59884
  }
59835
59885
  } catch {
59836
59886
  }
59837
59887
  try {
59838
- return new Error(JSON.stringify(err25));
59888
+ return new Error(JSON.stringify(err26));
59839
59889
  } catch {
59840
59890
  }
59841
59891
  }
59842
- return new Error(err25);
59892
+ return new Error(err26);
59843
59893
  };
59844
59894
 
59845
59895
  // ../../node_modules/.pnpm/@anthropic-ai+sdk@0.87.0_zod@4.3.6/node_modules/@anthropic-ai/sdk/core/error.mjs
@@ -59969,7 +60019,7 @@ var validatePositiveInteger = (name, n3) => {
59969
60019
  var safeJSON = (text) => {
59970
60020
  try {
59971
60021
  return JSON.parse(text);
59972
- } catch (err25) {
60022
+ } catch (err26) {
59973
60023
  return void 0;
59974
60024
  }
59975
60025
  };
@@ -60533,8 +60583,8 @@ var Stream = class _Stream {
60533
60583
  return ctrl.close();
60534
60584
  const bytes = encodeUTF8(JSON.stringify(value) + "\n");
60535
60585
  ctrl.enqueue(bytes);
60536
- } catch (err25) {
60537
- ctrl.error(err25);
60586
+ } catch (err26) {
60587
+ ctrl.error(err26);
60538
60588
  }
60539
60589
  },
60540
60590
  async cancel() {
@@ -62441,8 +62491,8 @@ var BetaMessageStream = class _BetaMessageStream {
62441
62491
  if (jsonBuf) {
62442
62492
  try {
62443
62493
  newContent.input = partialParse(jsonBuf);
62444
- } catch (err25) {
62445
- const error48 = new AnthropicError(`Unable to parse tool parameter JSON from model. Please retry your request or adjust your prompt. Error: ${err25}. JSON: ${jsonBuf}`);
62494
+ } catch (err26) {
62495
+ const error48 = new AnthropicError(`Unable to parse tool parameter JSON from model. Please retry your request or adjust your prompt. Error: ${err26}. JSON: ${jsonBuf}`);
62446
62496
  __classPrivateFieldGet(this, _BetaMessageStream_handleError, "f").call(this, error48);
62447
62497
  }
62448
62498
  }
@@ -62504,17 +62554,17 @@ var BetaMessageStream = class _BetaMessageStream {
62504
62554
  }
62505
62555
  readQueue.length = 0;
62506
62556
  });
62507
- this.on("abort", (err25) => {
62557
+ this.on("abort", (err26) => {
62508
62558
  done = true;
62509
62559
  for (const reader of readQueue) {
62510
- reader.reject(err25);
62560
+ reader.reject(err26);
62511
62561
  }
62512
62562
  readQueue.length = 0;
62513
62563
  });
62514
- this.on("error", (err25) => {
62564
+ this.on("error", (err26) => {
62515
62565
  done = true;
62516
62566
  for (const reader of readQueue) {
62517
- reader.reject(err25);
62567
+ reader.reject(err26);
62518
62568
  }
62519
62569
  readQueue.length = 0;
62520
62570
  });
@@ -64757,17 +64807,17 @@ var MessageStream = class _MessageStream {
64757
64807
  }
64758
64808
  readQueue.length = 0;
64759
64809
  });
64760
- this.on("abort", (err25) => {
64810
+ this.on("abort", (err26) => {
64761
64811
  done = true;
64762
64812
  for (const reader of readQueue) {
64763
- reader.reject(err25);
64813
+ reader.reject(err26);
64764
64814
  }
64765
64815
  readQueue.length = 0;
64766
64816
  });
64767
- this.on("error", (err25) => {
64817
+ this.on("error", (err26) => {
64768
64818
  done = true;
64769
64819
  for (const reader of readQueue) {
64770
- reader.reject(err25);
64820
+ reader.reject(err26);
64771
64821
  }
64772
64822
  readQueue.length = 0;
64773
64823
  });
@@ -65347,7 +65397,7 @@ var BaseAnthropic = class {
65347
65397
  }
65348
65398
  const retryMessage = shouldRetry ? `error; no more retries left` : `error; not retryable`;
65349
65399
  loggerFor(this).info(`${responseInfo} - ${retryMessage}`);
65350
- const errText = await response.text().catch((err26) => castToError(err26).message);
65400
+ const errText = await response.text().catch((err27) => castToError(err27).message);
65351
65401
  const errJSON = safeJSON(errText);
65352
65402
  const errMessage = errJSON ? void 0 : errText;
65353
65403
  loggerFor(this).debug(`[${requestLogID}] response error (${retryMessage})`, formatRequestDetails({
@@ -65358,8 +65408,8 @@ var BaseAnthropic = class {
65358
65408
  message: errMessage,
65359
65409
  durationMs: Date.now() - startTime
65360
65410
  }));
65361
- const err25 = this.makeStatusError(response.status, errJSON, errMessage, response.headers);
65362
- throw err25;
65411
+ const err26 = this.makeStatusError(response.status, errJSON, errMessage, response.headers);
65412
+ throw err26;
65363
65413
  }
65364
65414
  loggerFor(this).info(responseInfo);
65365
65415
  loggerFor(this).debug(`[${requestLogID}] response start`, formatRequestDetails({
@@ -65616,51 +65666,20 @@ function createOutputTools(schema2) {
65616
65666
  })
65617
65667
  };
65618
65668
  }
65619
- function buildOutputServer(options2) {
65620
- return xx({
65621
- name: options2.serverName,
65622
- tools: [
65623
- _x(
65624
- "set_output",
65625
- "Report the final output when the task is complete. Call once at the end of the session.",
65626
- options2.shape,
65627
- async (input) => {
65628
- options2.store(input);
65629
- return await Promise.resolve({ content: [{ type: "text", text: "ok" }] });
65630
- }
65631
- )
65632
- ]
65633
- });
65634
- }
65635
- function createOutputTool(shape, options2) {
65636
- const serverName = options2?.serverName ?? "output";
65637
- const schema2 = external_exports.object(shape);
65638
- let current;
65639
- function store(input) {
65640
- const parsed = schema2.safeParse(input);
65641
- if (parsed.success) {
65642
- current = parsed.data;
65643
- }
65644
- }
65645
- return {
65646
- server: buildOutputServer({ serverName, shape, store }),
65647
- getOutput: () => current,
65648
- captureInput: store,
65649
- allowedToolNames: [`mcp__${serverName}__set_output`]
65650
- };
65651
- }
65652
65669
 
65653
65670
  // ../../agents/consolidator/dist/index.js
65654
65671
  var import_neverthrow14 = __toESM(require_index_cjs(), 1);
65672
+ var import_neverthrow15 = __toESM(require_index_cjs(), 1);
65655
65673
  var MODEL = "claude-opus-4-6";
65656
65674
  var MAX_TOKENS = 4096;
65657
- var dismissedFindingSchema = external_exports.object({
65658
- finding: findingSchema,
65675
+ var findingWithoutConfidenceSchema = findingSchema.omit({ confidence: true });
65676
+ var dismissedRawFindingSchema = external_exports.object({
65677
+ finding: findingWithoutConfidenceSchema,
65659
65678
  reason: external_exports.string()
65660
65679
  });
65661
- var consolidationResultSchema = external_exports.object({
65662
- findings: external_exports.array(findingSchema),
65663
- dismissed: external_exports.array(dismissedFindingSchema)
65680
+ var rawConsolidationOutputSchema = external_exports.object({
65681
+ findings: external_exports.array(findingWithoutConfidenceSchema),
65682
+ dismissed: external_exports.array(dismissedRawFindingSchema)
65664
65683
  });
65665
65684
  async function fetchMessage({
65666
65685
  client,
@@ -65690,7 +65709,10 @@ function processToolUseBlock(toolUseBlock, context) {
65690
65709
  });
65691
65710
  const result = context.factory.handleToolCall(toolUseBlock.name, toolUseBlock.input);
65692
65711
  if (result.isErr()) {
65693
- return (0, import_neverthrow14.err)({ type: "REQUEST_FAILED", cause: result.error });
65712
+ return (0, import_neverthrow14.err)({
65713
+ type: "REQUEST_FAILED",
65714
+ cause: result.error
65715
+ });
65694
65716
  }
65695
65717
  const output = context.factory.getOutput();
65696
65718
  if (output === void 0) {
@@ -65698,7 +65720,7 @@ function processToolUseBlock(toolUseBlock, context) {
65698
65720
  }
65699
65721
  return (0, import_neverthrow14.ok)(output);
65700
65722
  }
65701
- function extractConsolidationResult(response, context) {
65723
+ function extractRawOutput(response, context) {
65702
65724
  emitThoughts(response, context.onEvent);
65703
65725
  const toolUseBlock = response.content.find(
65704
65726
  (block) => block.type === "tool_use" && block.name === "set_output"
@@ -65710,13 +65732,74 @@ function extractConsolidationResult(response, context) {
65710
65732
  }
65711
65733
  function consolidateFindings(prompt, onEvent) {
65712
65734
  const client = new Anthropic();
65713
- const factory = createOutputTools(consolidationResultSchema);
65735
+ const factory = createOutputTools(rawConsolidationOutputSchema);
65714
65736
  const tools = [factory.tools[1]];
65715
65737
  return (0, import_neverthrow14.fromAsyncThrowable)(
65716
65738
  fetchMessage,
65717
65739
  (cause) => ({ type: "REQUEST_FAILED", cause })
65718
65740
  )({ client, prompt, tools }).andThen(
65719
- (response) => extractConsolidationResult(response, { factory, onEvent })
65741
+ (response) => extractRawOutput(response, { factory, onEvent })
65742
+ );
65743
+ }
65744
+ function normalizeKey(value) {
65745
+ return value.toLowerCase().trim();
65746
+ }
65747
+ function findByKey(findings, key) {
65748
+ const normalizedFlow = normalizeKey(key.flow);
65749
+ const normalizedDescription = normalizeKey(key.description);
65750
+ return findings.find(
65751
+ (finding) => normalizeKey(finding.flow) === normalizedFlow && normalizeKey(finding.description) === normalizedDescription
65752
+ );
65753
+ }
65754
+ function resolveConfidence(output, pool) {
65755
+ const key = { flow: output.flow, description: output.description };
65756
+ const metadataMatch = findByKey(pool.metadataFindings, key);
65757
+ const visualMatch = findByKey(pool.visualFindings, key);
65758
+ if (metadataMatch !== void 0 && visualMatch !== void 0) {
65759
+ return (0, import_neverthrow15.ok)(maxConfidence(metadataMatch.confidence, visualMatch.confidence));
65760
+ }
65761
+ if (metadataMatch !== void 0) {
65762
+ return (0, import_neverthrow15.ok)(metadataMatch.confidence);
65763
+ }
65764
+ if (visualMatch !== void 0) {
65765
+ return (0, import_neverthrow15.ok)(visualMatch.confidence);
65766
+ }
65767
+ return (0, import_neverthrow15.err)({
65768
+ type: "UNMATCHED_OUTPUT_FINDING",
65769
+ flow: output.flow,
65770
+ description: output.description
65771
+ });
65772
+ }
65773
+ function attachConfidence(output, pool) {
65774
+ return resolveConfidence(output, pool).map((confidence) => ({ ...output, confidence }));
65775
+ }
65776
+ function mergeFindings(outputs, state) {
65777
+ if (outputs.length === 0) {
65778
+ return (0, import_neverthrow15.ok)(state.accumulated);
65779
+ }
65780
+ const [head, ...tail] = outputs;
65781
+ return attachConfidence(head, state.pool).andThen(
65782
+ (finding) => mergeFindings(tail, { pool: state.pool, accumulated: [...state.accumulated, finding] })
65783
+ );
65784
+ }
65785
+ function mergeDismissed(outputs, state) {
65786
+ if (outputs.length === 0) {
65787
+ return (0, import_neverthrow15.ok)(state.accumulated);
65788
+ }
65789
+ const [head, ...tail] = outputs;
65790
+ return attachConfidence(head.finding, state.pool).andThen(
65791
+ (finding) => mergeDismissed(tail, {
65792
+ pool: state.pool,
65793
+ accumulated: [...state.accumulated, { finding, reason: head.reason }]
65794
+ })
65795
+ );
65796
+ }
65797
+ function attachAllConfidences(raw, pool) {
65798
+ return mergeFindings(raw.findings, { pool, accumulated: [] }).andThen(
65799
+ (findings) => mergeDismissed(raw.dismissed, { pool, accumulated: [] }).map((dismissed) => ({
65800
+ findings,
65801
+ dismissed
65802
+ }))
65720
65803
  );
65721
65804
  }
65722
65805
  function buildDismissalSection(dismissals) {
@@ -65736,14 +65819,14 @@ function buildRulesSection() {
65736
65819
  return `## Rules
65737
65820
 
65738
65821
  1. Merge findings that share the same \`flow\` AND describe the same failure (overlapping \`steps\` or matching \`description\` intent). Do NOT merge findings from different flows.
65739
- 2. When merging: set \`confidence\` to the higher of the two scores; on a tie, keep the metadata channel's score. Combine \`steps\` and \`screenshots\` from both findings into the merged output.
65822
+ 2. When merging: combine \`steps\` and \`screenshots\` from both findings into the merged output. The system computes \`confidence\` after consolidation \u2014 do not emit it.
65740
65823
  3. Preserve unique findings unchanged.
65741
65824
  4. When uncertain if two findings are duplicates: keep both.
65742
65825
  5. Place a finding in \`dismissed\` only when it matches a dismissed entry on the same \`flow\` AND describes substantively the same failure (not just topically related). Copy the reason verbatim. When in doubt, keep it in \`findings\`.
65743
65826
  6. Every input finding MUST appear in exactly one of \`findings\` or \`dismissed\` \u2014 never both, never neither.
65744
65827
 
65745
65828
  CRITICAL: Call \`set_output\` exactly once when done. Do not reply in plain text.
65746
- - \`findings\`: array of Finding objects \u2014 preserve all original fields (\`triggerType\`, \`flow\`, \`steps\`, \`confidence\`, \`description\`, \`screenshots\`, \`agent\`)
65829
+ - \`findings\`: array of Finding objects \u2014 preserve all original fields (\`triggerType\`, \`flow\`, \`steps\`, \`description\`, \`screenshots\`, \`agent\`)
65747
65830
  - \`dismissed\`: array of objects with shape \`{ finding: Finding, reason: string }\` \u2014 populate \`finding\` with the full Finding object and copy \`reason\` verbatim from the dismissed context entry`;
65748
65831
  }
65749
65832
  function buildConsolidationPrompt({
@@ -65774,55 +65857,156 @@ function serializeDismissals(dismissals) {
65774
65857
  ({ finding, reason }) => `${finding.flow} \u2014 ${finding.description}${reason ? ` (reason: ${reason})` : ""}`
65775
65858
  );
65776
65859
  }
65777
- function emitStageEnd2(config3, start) {
65778
- config3?.onEvent?.({ type: "STAGE_END", agent: "consolidator", durationMs: Date.now() - start });
65860
+ function emitStageEnd2(context) {
65861
+ context.config?.onEvent?.({
65862
+ type: "STAGE_END",
65863
+ agent: "consolidator",
65864
+ durationMs: Date.now() - context.start
65865
+ });
65779
65866
  }
65780
- function runConsolidator(input, config3) {
65781
- if (input.metadataFindings.length === 0 && input.visualFindings.length === 0) {
65782
- return (0, import_neverthrow13.okAsync)({ findings: [], dismissed: [] });
65783
- }
65784
- const start = Date.now();
65785
- config3?.onEvent?.({ type: "STAGE_START", agent: "consolidator" });
65786
- const prompt = buildConsolidationPrompt({
65867
+ function buildPrompt(input) {
65868
+ return buildConsolidationPrompt({
65787
65869
  metadataFindings: input.metadataFindings,
65788
65870
  visualFindings: input.visualFindings,
65789
65871
  dismissals: serializeDismissals(input.dismissals)
65790
65872
  });
65791
- return consolidateFindings(prompt, config3?.onEvent).map((result) => {
65792
- emitStageEnd2(config3, start);
65873
+ }
65874
+ function runPipeline(input, context) {
65875
+ const pool = { metadataFindings: input.metadataFindings, visualFindings: input.visualFindings };
65876
+ return consolidateFindings(buildPrompt(input), context.config?.onEvent).andThen((raw) => attachAllConfidences(raw, pool)).map((result) => {
65877
+ emitStageEnd2(context);
65793
65878
  return result;
65794
65879
  }).mapErr((error48) => {
65795
- emitStageEnd2(config3, start);
65880
+ emitStageEnd2(context);
65796
65881
  return error48;
65797
65882
  });
65798
65883
  }
65884
+ function runConsolidator(input, config3) {
65885
+ if (input.metadataFindings.length === 0 && input.visualFindings.length === 0) {
65886
+ return (0, import_neverthrow13.okAsync)({ findings: [], dismissed: [] });
65887
+ }
65888
+ const start = Date.now();
65889
+ config3?.onEvent?.({ type: "STAGE_START", agent: "consolidator" });
65890
+ return runPipeline(input, { config: config3, start });
65891
+ }
65799
65892
 
65800
65893
  // ../../packages/pipeline/dist/index.js
65801
- var import_neverthrow31 = __toESM(require_index_cjs(), 1);
65802
- var import_neverthrow32 = __toESM(require_index_cjs(), 1);
65803
- var import_node_fs3 = require("node:fs");
65804
65894
  var import_neverthrow33 = __toESM(require_index_cjs(), 1);
65805
- var import_promises16 = require("node:timers/promises");
65895
+ var import_neverthrow34 = __toESM(require_index_cjs(), 1);
65896
+ var import_node_fs3 = require("node:fs");
65897
+ var import_neverthrow35 = __toESM(require_index_cjs(), 1);
65898
+ var import_promises17 = require("node:timers/promises");
65806
65899
 
65807
65900
  // ../../agents/explorer/dist/index.js
65808
65901
  var import_promises9 = require("node:timers/promises");
65809
- var import_neverthrow15 = __toESM(require_index_cjs(), 1);
65810
65902
  var import_neverthrow16 = __toESM(require_index_cjs(), 1);
65903
+ var import_neverthrow17 = __toESM(require_index_cjs(), 1);
65811
65904
  var import_promises10 = require("node:fs/promises");
65812
65905
  var import_node_path4 = __toESM(require("node:path"), 1);
65813
- var import_neverthrow17 = __toESM(require_index_cjs(), 1);
65814
- var import_node_child_process3 = require("node:child_process");
65815
- var import_promises11 = require("node:fs/promises");
65816
65906
  var import_neverthrow18 = __toESM(require_index_cjs(), 1);
65817
- var import_neverthrow19 = __toESM(require_index_cjs(), 1);
65818
- var import_node_child_process4 = require("node:child_process");
65819
- var import_node_fs = require("node:fs");
65907
+ var import_promises11 = require("node:fs/promises");
65820
65908
  var import_node_path5 = __toESM(require("node:path"), 1);
65909
+ var import_neverthrow19 = __toESM(require_index_cjs(), 1);
65910
+ var import_node_child_process3 = require("node:child_process");
65911
+ var import_promises12 = require("node:fs/promises");
65821
65912
  var import_neverthrow20 = __toESM(require_index_cjs(), 1);
65822
65913
  var import_neverthrow21 = __toESM(require_index_cjs(), 1);
65823
- var import_promises12 = require("node:fs/promises");
65914
+ var import_node_child_process4 = require("node:child_process");
65915
+ var import_node_fs = require("node:fs");
65824
65916
  var import_node_path6 = __toESM(require("node:path"), 1);
65825
65917
  var import_neverthrow22 = __toESM(require_index_cjs(), 1);
65918
+ var import_neverthrow23 = __toESM(require_index_cjs(), 1);
65919
+ var import_promises13 = require("node:fs/promises");
65920
+ var import_node_path7 = __toESM(require("node:path"), 1);
65921
+ var import_neverthrow24 = __toESM(require_index_cjs(), 1);
65922
+ function buildFinding(input, screenshotPath) {
65923
+ return {
65924
+ ...input,
65925
+ agent: "explorer",
65926
+ screenshots: [screenshotPath]
65927
+ };
65928
+ }
65929
+ var REPORT_FINDING_TOOL_NAME = "mcp__mobile-ios__report_finding";
65930
+ var REPORT_FINDING_DESCRIPTION = `Report a single finding the moment you observe it. Call this immediately when a finding condition is triggered \u2014 before taking any further actions. The current screen is captured automatically and attached to the finding. Do not pass screenshot paths. Do not batch findings for the end of the run.`;
65931
+ var safeWriteFile = (0, import_neverthrow18.fromAsyncThrowable)(
65932
+ import_promises10.writeFile,
65933
+ (cause) => ({ type: "WRITE_FAILED", cause })
65934
+ );
65935
+ async function persistScreenshot(params) {
65936
+ const filePath = import_node_path4.default.join(
65937
+ params.screenshotsDirectory,
65938
+ `finding-${String(params.findingIndex)}.png`
65939
+ );
65940
+ return safeWriteFile(filePath, Buffer.from(params.data, "base64")).match(
65941
+ () => filePath,
65942
+ () => ""
65943
+ );
65944
+ }
65945
+ function emitFindingEvent(params) {
65946
+ params.onEvent?.({
65947
+ type: "FINDING_REPORTED",
65948
+ agent: "explorer",
65949
+ finding: params.finding,
65950
+ findingIndex: params.findingIndex,
65951
+ screenshotPath: params.screenshotPath
65952
+ });
65953
+ }
65954
+ async function resolveScreenshotPath(params) {
65955
+ if (params.screenshotsDir === void 0) {
65956
+ return "";
65957
+ }
65958
+ return persistScreenshot({
65959
+ screenshotsDirectory: params.screenshotsDir,
65960
+ findingIndex: params.findingIndex,
65961
+ data: params.data
65962
+ });
65963
+ }
65964
+ async function recordFinding(params) {
65965
+ const screenshotPath = await resolveScreenshotPath({
65966
+ screenshotsDir: params.screenshotsDir,
65967
+ findingIndex: params.findingIndex,
65968
+ data: params.screenshotData
65969
+ });
65970
+ const finding = buildFinding(params.input, screenshotPath);
65971
+ params.findings.push(finding);
65972
+ emitFindingEvent({
65973
+ onEvent: params.onEvent,
65974
+ finding,
65975
+ findingIndex: params.findingIndex,
65976
+ screenshotPath
65977
+ });
65978
+ return { content: [{ type: "text", text: "ok" }] };
65979
+ }
65980
+ function screenshotErrorResult(cause) {
65981
+ return {
65982
+ content: [{ type: "text", text: `Screenshot failed: ${String(cause)}` }],
65983
+ isError: true
65984
+ };
65985
+ }
65986
+ function createHandler(context) {
65987
+ const counter = context.findingCounter;
65988
+ const { findings, onEvent, screenshotsDir, udid } = context;
65989
+ return async (input) => {
65990
+ const screenshotResult = await captureScreenshot(udid);
65991
+ if (screenshotResult.isErr()) {
65992
+ return screenshotErrorResult(screenshotResult.error.cause);
65993
+ }
65994
+ const findingIndex = counter.value;
65995
+ counter.value += 1;
65996
+ return recordFinding({
65997
+ findings,
65998
+ onEvent,
65999
+ screenshotsDir,
66000
+ input,
66001
+ screenshotData: screenshotResult.value,
66002
+ findingIndex
66003
+ });
66004
+ };
66005
+ }
66006
+ function createReportFindingTool(context) {
66007
+ const handler2 = createHandler(context);
66008
+ return _x("report_finding", REPORT_FINDING_DESCRIPTION, findingInputSchema.shape, handler2);
66009
+ }
65826
66010
  var VIEW_UI_DESCRIPTION = `Capture current screen state: accessibility tree (element labels, positions, attributes) and screenshot in one call. Use when you need to tap an element, assert element presence or labels, check attributes, or track screen identity via <screen_id>.
65827
66011
 
65828
66012
  The result begins with a <screen_id> tag containing the current screen identifier. Use this to detect screen changes and track navigation history.
@@ -65831,14 +66015,14 @@ Do not call \`screenshot\` immediately before or after this tool for the same st
65831
66015
 
65832
66016
  IMPORTANT: Snapshot coordinates and screenshot pixels are in the same logical point space. Do not apply any scaling factor (no 2x retina adjustment).`;
65833
66017
  var VIEW_UI_TOOL_NAME = "mcp__mobile-ios__view_ui";
65834
- async function persistScreenshot(params) {
66018
+ async function persistScreenshot2(params) {
65835
66019
  const targetSnapshot = params.snapshot;
65836
- const screenshotPath = import_node_path4.default.join(params.screenshotsDirectory, `${params.screenLabel}.png`);
65837
- const safeWriteFile = (0, import_neverthrow17.fromAsyncThrowable)(
65838
- import_promises10.writeFile,
66020
+ const screenshotPath = import_node_path5.default.join(params.screenshotsDirectory, `${params.screenLabel}.png`);
66021
+ const safeWriteFile2 = (0, import_neverthrow19.fromAsyncThrowable)(
66022
+ import_promises11.writeFile,
65839
66023
  (cause) => ({ type: "WRITE_FAILED", cause })
65840
66024
  );
65841
- const writeResult = safeWriteFile(screenshotPath, Buffer.from(params.data, "base64"));
66025
+ const writeResult = safeWriteFile2(screenshotPath, Buffer.from(params.data, "base64"));
65842
66026
  const succeeded = await writeResult.match(
65843
66027
  () => true,
65844
66028
  () => false
@@ -65899,16 +66083,16 @@ function buildSnapshotRecord(rawElements, { stepIndex, context }) {
65899
66083
  }
65900
66084
  async function handleScreenshotData(data, params) {
65901
66085
  if (params.context.screenshotsDir !== void 0) {
65902
- const safeWrite2 = (0, import_neverthrow17.fromAsyncThrowable)(
65903
- import_promises10.writeFile,
66086
+ const safeWrite2 = (0, import_neverthrow19.fromAsyncThrowable)(
66087
+ import_promises11.writeFile,
65904
66088
  (cause) => ({ type: "WRITE_FAILED", cause })
65905
66089
  );
65906
- const snapshotPath = import_node_path4.default.join(params.context.screenshotsDir, `${params.screenLabel}.txt`);
66090
+ const snapshotPath = import_node_path5.default.join(params.context.screenshotsDir, `${params.screenLabel}.txt`);
65907
66091
  await safeWrite2(snapshotPath, params.formatted).match(
65908
66092
  () => true,
65909
66093
  () => false
65910
66094
  );
65911
- await persistScreenshot({
66095
+ await persistScreenshot2({
65912
66096
  snapshot: params.snapshot,
65913
66097
  data,
65914
66098
  screenLabel: params.screenLabel,
@@ -66002,7 +66186,7 @@ function captureThinkingOrText(blk, state) {
66002
66186
  }
66003
66187
  }
66004
66188
  function captureToolUse(blk, state) {
66005
- if (typeof blk.name === "string") {
66189
+ if (typeof blk.name === "string" && blk.name !== REPORT_FINDING_TOOL_NAME) {
66006
66190
  state.onEvent?.({
66007
66191
  type: "TOOL_CALL",
66008
66192
  agent: "explorer",
@@ -66013,10 +66197,6 @@ function captureToolUse(blk, state) {
66013
66197
  if (typeof blk.id === "string" && typeof blk.name === "string") {
66014
66198
  state.pendingToolCallNames.set(blk.id, blk.name);
66015
66199
  }
66016
- if (typeof blk.name === "string" && blk.name.endsWith("set_output")) {
66017
- state.captureInput(blk.input);
66018
- state.closeQueue();
66019
- }
66020
66200
  }
66021
66201
  function extractResultText(block) {
66022
66202
  const typed = block;
@@ -66032,7 +66212,7 @@ function extractResultText(block) {
66032
66212
  }
66033
66213
  function emitToolResultEvent(emission) {
66034
66214
  const { block, toolName, blk, state } = emission;
66035
- if (toolName === VIEW_UI_TOOL_NAME) {
66215
+ if (toolName === VIEW_UI_TOOL_NAME || toolName === REPORT_FINDING_TOOL_NAME) {
66036
66216
  return;
66037
66217
  }
66038
66218
  const resultText = extractResultText(block);
@@ -66084,23 +66264,23 @@ function processMessage(message, state) {
66084
66264
  }
66085
66265
  if (message.type === "result") {
66086
66266
  if (message.subtype !== "success" && !state.timedOut.value && !state.aborted.value) {
66087
- return (0, import_neverthrow16.err)(message.errors.join("; "));
66267
+ return (0, import_neverthrow17.err)(message.errors.join("; "));
66088
66268
  }
66089
- return (0, import_neverthrow16.ok)(true);
66269
+ return (0, import_neverthrow17.ok)(true);
66090
66270
  }
66091
- return (0, import_neverthrow16.ok)(false);
66271
+ return (0, import_neverthrow17.ok)(false);
66092
66272
  }
66093
66273
  async function processMessages(queryRunner, state) {
66094
66274
  for await (const message of queryRunner) {
66095
66275
  const result = processMessage(message, state);
66096
66276
  if (result.isErr()) {
66097
- return (0, import_neverthrow16.err)(result.error);
66277
+ return (0, import_neverthrow17.err)(result.error);
66098
66278
  }
66099
66279
  if (result.value) {
66100
66280
  break;
66101
66281
  }
66102
66282
  }
66103
- return (0, import_neverthrow16.ok)(null);
66283
+ return (0, import_neverthrow17.ok)(null);
66104
66284
  }
66105
66285
  var MessageQueue = class {
66106
66286
  pending = [];
@@ -66165,26 +66345,25 @@ function spawnDetached(options2) {
66165
66345
  off: child.off.bind(child)
66166
66346
  };
66167
66347
  }
66168
- function buildQueryOptions({
66169
- config: config3,
66170
- outputTools,
66171
- mobileIosServer,
66172
- allowedTools
66173
- }) {
66174
- const base = {
66348
+ function buildBaseOptions(context) {
66349
+ const { config: config3, mobileIosServer, allowedTools } = context;
66350
+ return {
66175
66351
  mcpServers: {
66176
66352
  ...config3.mcpServers,
66177
- "mobile-ios": mobileIosServer,
66178
- output: outputTools.server
66353
+ "mobile-ios": mobileIosServer
66179
66354
  },
66180
66355
  allowedTools,
66181
66356
  tools: [],
66182
66357
  permissionMode: "bypassPermissions",
66183
66358
  allowDangerouslySkipPermissions: true,
66184
66359
  spawnClaudeCodeProcess: spawnDetached,
66360
+ thinking: { type: "adaptive" },
66185
66361
  ...config3.cwd ? { cwd: config3.cwd } : {}
66186
66362
  };
66187
- if (!config3.signal) {
66363
+ }
66364
+ function buildQueryOptions(context) {
66365
+ const base = buildBaseOptions(context);
66366
+ if (!context.config.signal) {
66188
66367
  return { options: base, linkedController: void 0 };
66189
66368
  }
66190
66369
  const linkedController = new AbortController();
@@ -66203,14 +66382,14 @@ function buildSendMessageFunction(inputQueue) {
66203
66382
  }
66204
66383
  function buildAgentState({
66205
66384
  config: config3,
66206
- outputTools,
66207
66385
  inputQueue
66208
66386
  }) {
66209
66387
  return {
66210
66388
  pendingToolCallNames: /* @__PURE__ */ new Map(),
66211
66389
  snapshots: [],
66212
66390
  stepCounter: { value: 0 },
66213
- captureInput: outputTools.captureInput,
66391
+ findings: [],
66392
+ findingCounter: { value: 0 },
66214
66393
  sendMessage: buildSendMessageFunction(inputQueue),
66215
66394
  closeQueue: () => {
66216
66395
  inputQueue.close();
@@ -66228,28 +66407,34 @@ function buildMobileIosServer(config3, state) {
66228
66407
  onEvent: config3.onEvent,
66229
66408
  screenshotsDir: config3.screenshotsDir
66230
66409
  });
66231
- return createMobileIosServer(config3.udid ?? "booted", [viewUiTool]);
66410
+ const reportFindingTool = createReportFindingTool({
66411
+ udid: config3.udid,
66412
+ findings: state.findings,
66413
+ findingCounter: state.findingCounter,
66414
+ onEvent: config3.onEvent,
66415
+ screenshotsDir: config3.screenshotsDir
66416
+ });
66417
+ return createMobileIosServer(config3.udid ?? "booted", [viewUiTool, reportFindingTool]);
66232
66418
  }
66233
- function setupQuery(config3, outputTools) {
66419
+ function setupQuery(config3) {
66234
66420
  const allowedTools = [
66235
66421
  ...config3.allowedTools ?? [],
66236
- ...outputTools.allowedToolNames,
66237
66422
  VIEW_UI_TOOL_NAME,
66423
+ REPORT_FINDING_TOOL_NAME,
66238
66424
  WAIT_SECONDS_TOOL_NAME
66239
- ].filter((tool2) => typeof tool2 === "string");
66425
+ ].filter((tool3) => typeof tool3 === "string");
66240
66426
  const inputQueue = new MessageQueue();
66241
- const state = buildAgentState({ config: config3, outputTools, inputQueue });
66427
+ const state = buildAgentState({ config: config3, inputQueue });
66242
66428
  const mobileIosServer = buildMobileIosServer(config3, state);
66243
66429
  const { options: options2, linkedController } = buildQueryOptions({
66244
66430
  config: config3,
66245
- outputTools,
66246
66431
  mobileIosServer,
66247
66432
  allowedTools
66248
66433
  });
66249
66434
  return { inputQueue, state, options: options2, linkedController };
66250
66435
  }
66251
- var DEFAULT_GRACE_PERIOD_MS = 6e4;
66252
- var SOFT_DEADLINE_MESSAGE = "Your time limit has been reached. Call set_output immediately with any findings you have collected so far. Do not take any further actions.";
66436
+ var DEFAULT_GRACE_PERIOD_MS = 1e4;
66437
+ var SOFT_DEADLINE_MESSAGE = "Your time limit has been reached. Do not take any further actions.";
66253
66438
  function buildInterruptErrorEvent(agent, error48) {
66254
66439
  const message = `interrupt failed: ${error48 instanceof Error ? error48.message : String(error48)}`;
66255
66440
  const stack = error48 instanceof Error ? error48.stack : void 0;
@@ -66308,18 +66493,14 @@ function startTimeout(timeoutMs, context) {
66308
66493
  const gracePeriodMs = context.gracePeriodMs ?? DEFAULT_GRACE_PERIOD_MS;
66309
66494
  return startActiveTimeout({ timeoutMs, gracePeriodMs, context });
66310
66495
  }
66311
- var EXPLORER_FINDING_SCHEMA = findingSchema.omit({ agent: true });
66312
66496
  var INTERRUPT_DRAIN_TIMEOUT_MS = 1e4;
66313
66497
  async function interruptOrTimeout(queryRunner) {
66314
66498
  await Promise.race([queryRunner.interrupt(), (0, import_promises9.setTimeout)(INTERRUPT_DRAIN_TIMEOUT_MS)]);
66315
66499
  }
66316
- var safeInterruptOrTimeout = import_neverthrow15.ResultAsync.fromThrowable(
66500
+ var safeInterruptOrTimeout = import_neverthrow16.ResultAsync.fromThrowable(
66317
66501
  interruptOrTimeout,
66318
66502
  (error48) => error48
66319
66503
  );
66320
- function stampExplorerAgent(raw) {
66321
- return { ...raw, agent: "explorer" };
66322
- }
66323
66504
  async function drainInterruptThenAbort(context) {
66324
66505
  const { queryRunner, state, linkedController, reason } = context;
66325
66506
  const result = await safeInterruptOrTimeout(queryRunner);
@@ -66365,24 +66546,23 @@ function startQueryTimers(config3, context) {
66365
66546
  }
66366
66547
  function awaitMessagesAndResolve({ queryRunner, state }, { cleanup: cleanup2, getOutput }) {
66367
66548
  const messagesPromise = processMessages(queryRunner, state);
66368
- return import_neverthrow15.ResultAsync.fromPromise(messagesPromise, String).andThen((innerResult) => {
66549
+ return import_neverthrow16.ResultAsync.fromPromise(messagesPromise, String).andThen((innerResult) => {
66369
66550
  cleanup2();
66370
66551
  if (innerResult.isErr()) {
66371
- return (0, import_neverthrow15.err)(innerResult.error);
66552
+ return (0, import_neverthrow16.err)(innerResult.error);
66372
66553
  }
66373
- return (0, import_neverthrow15.ok)(getOutput());
66554
+ return (0, import_neverthrow16.ok)(getOutput());
66374
66555
  }).orElse((sdkError) => {
66375
66556
  cleanup2();
66376
66557
  if (!state.timedOut.value && !state.aborted.value) {
66377
- return (0, import_neverthrow15.err)(sdkError);
66558
+ return (0, import_neverthrow16.err)(sdkError);
66378
66559
  }
66379
- return (0, import_neverthrow15.ok)(getOutput());
66560
+ return (0, import_neverthrow16.ok)(getOutput());
66380
66561
  });
66381
66562
  }
66382
66563
  function executeQuery({
66383
66564
  prompt,
66384
66565
  config: config3,
66385
- outputTools,
66386
66566
  setup: { inputQueue, state, options: options2, linkedController }
66387
66567
  }) {
66388
66568
  inputQueue.enqueue({
@@ -66390,35 +66570,32 @@ function executeQuery({
66390
66570
  message: { role: "user", content: prompt },
66391
66571
  parent_tool_use_id: null
66392
66572
  });
66393
- const queryRunnerResult = (0, import_neverthrow15.fromThrowable)(Qs, String)({ prompt: inputQueue, options: options2 });
66573
+ const queryRunnerResult = (0, import_neverthrow16.fromThrowable)(Qs, String)({ prompt: inputQueue, options: options2 });
66394
66574
  if (queryRunnerResult.isErr()) {
66395
- return (0, import_neverthrow15.errAsync)(queryRunnerResult.error);
66575
+ return (0, import_neverthrow16.errAsync)(queryRunnerResult.error);
66396
66576
  }
66397
66577
  const queryRunner = queryRunnerResult.value;
66398
66578
  const cleanup2 = startQueryTimers(config3, { state, queryRunner, inputQueue, linkedController });
66399
66579
  const getOutput = () => ({
66400
- findings: (outputTools.getOutput()?.findings ?? []).map(
66401
- (raw) => stampExplorerAgent(raw)
66402
- ),
66580
+ findings: state.findings,
66403
66581
  snapshots: state.snapshots
66404
66582
  });
66405
66583
  return awaitMessagesAndResolve({ queryRunner, state }, { cleanup: cleanup2, getOutput });
66406
66584
  }
66407
66585
  function runQuery(prompt, config3) {
66408
- const outputTools = createOutputTool({ findings: external_exports.array(EXPLORER_FINDING_SCHEMA) });
66409
- const setup = setupQuery(config3, outputTools);
66410
- return executeQuery({ prompt, config: config3, outputTools, setup });
66586
+ const setup = setupQuery(config3);
66587
+ return executeQuery({ prompt, config: config3, setup });
66411
66588
  }
66412
66589
  function collectAgentOutput(prompt, config3) {
66413
66590
  return runQuery(prompt, config3).mapErr((cause) => ({ type: "QUERY_FAILED", cause }));
66414
66591
  }
66415
66592
  function spawnRecorder(outputPath) {
66416
- const safeMkdirSync = (0, import_neverthrow20.fromThrowable)(import_node_fs.mkdirSync, (cause) => cause);
66417
- const safeSpawn2 = (0, import_neverthrow20.fromThrowable)(
66593
+ const safeMkdirSync = (0, import_neverthrow22.fromThrowable)(import_node_fs.mkdirSync, (cause) => cause);
66594
+ const safeSpawn2 = (0, import_neverthrow22.fromThrowable)(
66418
66595
  (command, arguments_) => (0, import_node_child_process4.spawn)(command, arguments_),
66419
66596
  (cause) => cause
66420
66597
  );
66421
- const mkdirResult = safeMkdirSync(import_node_path5.default.dirname(outputPath), { recursive: true });
66598
+ const mkdirResult = safeMkdirSync(import_node_path6.default.dirname(outputPath), { recursive: true });
66422
66599
  if (mkdirResult.isErr()) {
66423
66600
  return mkdirResult.error;
66424
66601
  }
@@ -66441,7 +66618,7 @@ function earlyExitError(code) {
66441
66618
  function waitForRecordingStart(proc) {
66442
66619
  const { stderr } = proc;
66443
66620
  if (!stderr) {
66444
- return (0, import_neverthrow20.errAsync)({ type: "SPAWN_FAILED", cause: new RangeError("proc has no stderr pipe") });
66621
+ return (0, import_neverthrow22.errAsync)({ type: "SPAWN_FAILED", cause: new RangeError("proc has no stderr pipe") });
66445
66622
  }
66446
66623
  const { promise: promise2, resolve, reject } = Promise.withResolvers();
66447
66624
  proc.once("error", reject);
@@ -66457,7 +66634,7 @@ function waitForRecordingStart(proc) {
66457
66634
  resolve({ process: proc, startedAt: Date.now() });
66458
66635
  }
66459
66636
  });
66460
- return import_neverthrow20.ResultAsync.fromPromise(
66637
+ return import_neverthrow22.ResultAsync.fromPromise(
66461
66638
  promise2,
66462
66639
  (cause) => ({ type: "SPAWN_FAILED", cause })
66463
66640
  );
@@ -66465,7 +66642,7 @@ function waitForRecordingStart(proc) {
66465
66642
  function startRecording(outputPath) {
66466
66643
  const procOrError = spawnRecorder(outputPath);
66467
66644
  if (procOrError instanceof Error) {
66468
- return (0, import_neverthrow20.errAsync)({ type: "SPAWN_FAILED", cause: procOrError });
66645
+ return (0, import_neverthrow22.errAsync)({ type: "SPAWN_FAILED", cause: procOrError });
66469
66646
  }
66470
66647
  return waitForRecordingStart(procOrError);
66471
66648
  }
@@ -66480,7 +66657,7 @@ function stopRecording(handle) {
66480
66657
  } else {
66481
66658
  resolve(true);
66482
66659
  }
66483
- return import_neverthrow20.ResultAsync.fromPromise(
66660
+ return import_neverthrow22.ResultAsync.fromPromise(
66484
66661
  promise2,
66485
66662
  (cause) => ({ type: "STOP_FAILED", cause })
66486
66663
  );
@@ -66493,7 +66670,7 @@ function runWithRecording(handle, collectOutput) {
66493
66670
  return collectOutput().andThen(
66494
66671
  ({ findings, snapshots }) => stopRecording(handle).mapErr(toRecordingError).map(() => ({ findings, snapshots }))
66495
66672
  ).orElse(
66496
- (error48) => stopRecording(handle).mapErr(toRecordingError).andThen(() => (0, import_neverthrow19.errAsync)(error48)).orElse(() => (0, import_neverthrow19.errAsync)(error48))
66673
+ (error48) => stopRecording(handle).mapErr(toRecordingError).andThen(() => (0, import_neverthrow21.errAsync)(error48)).orElse(() => (0, import_neverthrow21.errAsync)(error48))
66497
66674
  );
66498
66675
  }
66499
66676
  function startAndRun(params) {
@@ -66540,9 +66717,21 @@ var LOADING_STATE_RULE = `Transient loading state: when the screen shows spinner
66540
66717
  var EXPECTED_CONTENT_MISSING_RULE = `Expected content missing: when \`view_ui\` shows no loading indicator yet omits an element named or strongly implied by spec or app context \u2014 and its absence is not semantically consistent with the current screen \u2014 call \`wait_seconds\` with 2\u20135 seconds and retry \`view_ui\` up to 2 times; if element remains absent, emit a \`missing-content\` finding stating what was expected and what was observed`;
66541
66718
  var CLIPPED_ELEMENT_RULE = `Never tap an element tagged \`[clipped-top]\`, \`[clipped-bottom]\`, \`[clipped-left]\`, or \`[clipped-right]\` \u2014 scroll to fully reveal it first, then re-call \`view_ui\` before tapping`;
66542
66719
  var SCROLL_FOLD_RULE = `Scrollable lists: elements outside the visible viewport are absent from the a11y tree by design \u2014 this applies to elements below the fold in vertical lists AND elements clipped off-left or off-right in horizontal lists \u2014 scroll or swipe in the appropriate axis to reveal before asserting presence or absence; never emit a finding solely because list items, rows, or tabs are missing from the tree on a scrollable screen; if swipe attempts yield no position change across 2+ cycles, apply the scroll-stall path in STUCK_LOOP_RULE.`;
66720
+ var CONFIDENCE_RUBRIC_SECTION = `## Confidence
66721
+
66722
+ Write the description (what you saw vs. expected, where, when) before committing to a confidence label.
66723
+
66724
+ - HIGH \u2014 definite bug or deviation; the evidence is unambiguous
66725
+ - MEDIUM \u2014 probable bug, but could be intentional behavior you cannot verify
66726
+ - LOW \u2014 speculative; only include when freestyle/low-confidence triggers require it`;
66543
66727
  var FINDING_TAXONOMY_SECTION = `## Finding Types
66544
66728
 
66545
- You may emit only these trigger types: \`back-nav-failure\`, \`dead-end\`, \`stuck-modal\`, \`stuck-loop\`, \`missing-a11y-element\`, \`missing-content\`, \`spec-deviation\`, \`destructive-only-exit\`. Do NOT emit \`design-system-violation\`, \`motion-regression\`, \`continuity-regression\`, \`interaction-regression\`, or \`loading-regression\` \u2014 those belong to other agents.`;
66729
+ You may emit only these trigger types: \`back-nav-failure\`, \`dead-end\`, \`stuck-modal\`, \`stuck-loop\`, \`missing-a11y-element\`, \`missing-content\`, \`spec-deviation\`, \`destructive-only-exit\`. Do NOT emit \`design-system-violation\`, \`motion-regression\`, \`continuity-regression\`, \`interaction-regression\`, or \`loading-regression\` \u2014 those belong to other agents.
66730
+
66731
+ ${CONFIDENCE_RUBRIC_SECTION}`;
66732
+ var REPORTING_FINDINGS_SECTION = `## Reporting Findings
66733
+
66734
+ CRITICAL: When you observe a finding, call \`report_finding\` IMMEDIATELY \u2014 before taking any further actions. Do not batch findings. Do not wait until the end of the run. Each \`report_finding\` call atomically records one finding with the current screen attached; the server captures the screenshot. Do not pass screenshot paths or step indices. If you are uncertain whether something warrants a finding, do not report it \u2014 \`report_finding\` is for confirmed observations only.`;
66546
66735
  var A11Y_FALLBACK_RULE = `Missing a11y element: if you intend to tap or interact with a UI element and that element is absent from the most recent \`view_ui\` a11y tree \u2014 visible in the screenshot does NOT imply interactable; the a11y tree is authoritative \u2014 do NOT estimate its coordinates from the screenshot, do NOT attempt any pixel-based tap, do NOT retry at different coordinates, do NOT long-press or swipe in the element's visual region as a fallback; a failed pixel tap is never an \`interaction-regression\` \u2014 it is a \`missing-a11y-element\` \u2014 instead, emit a \`missing-a11y-element\` finding that states: (1) your intent (what you were trying to do), (2) the approximate visual region where the element appeared (coords/size from the screenshot), (3) nearby labeled elements from the a11y tree that serve as landmarks \u2014 then continue: in freestyle mode keep exploring other reachable screens; in spec mode advance to the next step`;
66547
66736
  var OUTCOME_LITERAL_RULE = `When verifying a step outcome or assertion, interpret all quantifiers literally and apply them exhaustively: any keyword that imposes a universal or count-bound constraint \u2014 including but not limited to \`only\`, \`all\`, \`every\`, \`each\`, \`both\`, \`no\`, \`none\`, \`neither\`, \`exactly N\`, \`at least N\`, \`fewer than N\`, \`more than N\` \u2014 a single counter-example observed in \`view_ui\` or \`screenshot\` constitutes a failed constraint; this rule applies only when the outcome text contains a universal or count-bound quantifier; positive-existence outcomes (\`X appears\`, \`Y becomes active\`, \`screen is visible\`) are not subject to counter-example scanning and are governed by SPEC_STEP_READING_SECTION; on a scrollable list, scroll through the full list before concluding pass or fail on a universal quantifier \u2014 apply SCROLL_FOLD_RULE to reveal all items, then evaluate across the complete visible set; if the screen shows any loading indicator at the time of observation, apply LOADING_STATE_RULE first and re-verify after resolution before emitting; do NOT soften (\`mostly\`, \`essentially\`, \`largely\`) and do NOT narrow the target class post-hoc to exclude the counter-example; when the counter-evidence is an element absent from the a11y tree, A11Y_FALLBACK_RULE takes precedence and determines the finding type (\`missing-a11y-element\`) \u2014 OUTCOME_LITERAL_RULE governs unwanted-presence violations only; if one item violates the constraint, emit \`spec-deviation\` immediately with: (a) the literal outcome text, (b) the specific element(s) that violate it, (c) the constraint keyword that is broken.`;
66548
66737
  var ANTI_RATIONALIZATION_RULE = `During outcome verification, monitor your own reasoning for reconciliation hypotheses: if you generate any reasoning that re-frames, redefines, or reinterprets the observed counter-example or target class in order to produce agreement with the spec outcome \u2014 regardless of phrasing \u2014 treat that reasoning as a deviation signal, not a resolution; stop, do NOT mark the step complete, and emit \`spec-deviation\` with: (a) the literal outcome text, (b) the specific observation that triggered the hypothesis, (c) the reconciliation reasoning itself verbatim; before marking any quantifier-bearing outcome complete, state explicitly in your reasoning: \`No reconciliation hypothesis generated. Counter-examples found: [list or none].\` If you cannot make that statement honestly, a hypothesis exists \u2014 emit \`spec-deviation\`; when outcome verification is ambiguous and no reconciliation hypothesis is generated, still default to emitting \`spec-deviation\`; silence is not a pass.`;
@@ -66677,9 +66866,7 @@ ${FINDING_TAXONOMY_SECTION}
66677
66866
 
66678
66867
  ${specContent}${environmentSection}
66679
66868
 
66680
- ## Output
66681
-
66682
- CRITICAL: Call \`set_output\` each time your findings change \u2014 when you discover something new, confirm a false positive, or revise a finding. Each call replaces the previous output entirely, so always pass the full current list. Do not reply in plain text.`;
66869
+ ${REPORTING_FINDINGS_SECTION}`;
66683
66870
  }
66684
66871
  var SPEC_MODE_TEMPLATE = (specContent, options2) => {
66685
66872
  const contextBlock = buildContextSections(options2.appContext, options2.initialState);
@@ -66723,9 +66910,7 @@ ${DEAD_END_SECTION}
66723
66910
 
66724
66911
  ${FINDING_TAXONOMY_SECTION}${environmentSection}
66725
66912
 
66726
- ## Output
66727
-
66728
- CRITICAL: Call \`set_output\` each time your findings change \u2014 when you discover something new, confirm a false positive, or revise a finding. Each call replaces the previous output entirely, so always pass the full current list. Do not reply in plain text.`;
66913
+ ${REPORTING_FINDINGS_SECTION}`;
66729
66914
  }
66730
66915
  var FREESTYLE_TEMPLATE = (options2) => {
66731
66916
  const { appContext, initialState: initialState2, buildEnv } = options2 ?? {};
@@ -66776,29 +66961,29 @@ var INLINE_ASSERTION_DELIMITER = " \u2192 ";
66776
66961
  var NUMBERED_STEP_PREFIX = /^\d+\.\s+/;
66777
66962
  function parseTagsValue(value) {
66778
66963
  if (!value.startsWith("[") || !value.endsWith("]")) {
66779
- return (0, import_neverthrow21.err)({ type: "MALFORMED_FRONTMATTER", cause: `Invalid tags format: ${value}` });
66964
+ return (0, import_neverthrow23.err)({ type: "MALFORMED_FRONTMATTER", cause: `Invalid tags format: ${value}` });
66780
66965
  }
66781
- return (0, import_neverthrow21.ok)(
66966
+ return (0, import_neverthrow23.ok)(
66782
66967
  value.slice(1, -1).split(",").map((tag) => tag.trim()).filter((tag) => tag.length > 0)
66783
66968
  );
66784
66969
  }
66785
66970
  function parseTimeoutValue(value) {
66786
66971
  const parsed = Number(value);
66787
66972
  if (Number.isNaN(parsed) || parsed <= 0) {
66788
- return (0, import_neverthrow21.err)({ type: "MALFORMED_FRONTMATTER", cause: `Invalid timeout: ${value}` });
66973
+ return (0, import_neverthrow23.err)({ type: "MALFORMED_FRONTMATTER", cause: `Invalid timeout: ${value}` });
66789
66974
  }
66790
- return (0, import_neverthrow21.ok)(parsed);
66975
+ return (0, import_neverthrow23.ok)(parsed);
66791
66976
  }
66792
66977
  function parseFrontmatterLine(line) {
66793
66978
  const colonIndex = line.indexOf(":");
66794
66979
  if (colonIndex === -1) {
66795
- return (0, import_neverthrow21.err)({ type: "MALFORMED_FRONTMATTER", cause: `Invalid line: ${line}` });
66980
+ return (0, import_neverthrow23.err)({ type: "MALFORMED_FRONTMATTER", cause: `Invalid line: ${line}` });
66796
66981
  }
66797
66982
  const key = line.slice(0, colonIndex).trim();
66798
66983
  const value = line.slice(colonIndex + 1).trim();
66799
66984
  switch (key) {
66800
66985
  case "description": {
66801
- return (0, import_neverthrow21.ok)({ description: value });
66986
+ return (0, import_neverthrow23.ok)({ description: value });
66802
66987
  }
66803
66988
  case "tags": {
66804
66989
  return parseTagsValue(value).map((tags) => ({ tags }));
@@ -66807,7 +66992,7 @@ function parseFrontmatterLine(line) {
66807
66992
  return parseTimeoutValue(value).map((timeout) => ({ timeout }));
66808
66993
  }
66809
66994
  default: {
66810
- return (0, import_neverthrow21.ok)({});
66995
+ return (0, import_neverthrow23.ok)({});
66811
66996
  }
66812
66997
  }
66813
66998
  }
@@ -66826,18 +67011,18 @@ function mergePartials(partials) {
66826
67011
  }
66827
67012
  function combineFrontmatterLines(lines) {
66828
67013
  const lineResults = lines.filter((line) => line.trim().length > 0).map((line) => parseFrontmatterLine(line));
66829
- return import_neverthrow21.Result.combine(lineResults).map((partials) => mergePartials(partials)).map((merged) => normalizeFrontmatter(merged));
67014
+ return import_neverthrow23.Result.combine(lineResults).map((partials) => mergePartials(partials)).map((merged) => normalizeFrontmatter(merged));
66830
67015
  }
66831
67016
  function extractFrontmatter(content) {
66832
67017
  const trimmed = content.trimStart();
66833
67018
  if (!trimmed.startsWith(FRONTMATTER_FENCE)) {
66834
- return (0, import_neverthrow21.ok)({ frontmatter: emptyFrontmatter(), body: content });
67019
+ return (0, import_neverthrow23.ok)({ frontmatter: emptyFrontmatter(), body: content });
66835
67020
  }
66836
67021
  const afterOpenFence = trimmed.slice(FRONTMATTER_FENCE.length);
66837
67022
  const closeIndex = afterOpenFence.indexOf(`
66838
67023
  ${FRONTMATTER_FENCE}`);
66839
67024
  if (closeIndex === -1) {
66840
- return (0, import_neverthrow21.err)({ type: "MALFORMED_FRONTMATTER", cause: "Unclosed frontmatter fence" });
67025
+ return (0, import_neverthrow23.err)({ type: "MALFORMED_FRONTMATTER", cause: "Unclosed frontmatter fence" });
66841
67026
  }
66842
67027
  const rawFrontmatter = afterOpenFence.slice(0, closeIndex);
66843
67028
  const body = afterOpenFence.slice(closeIndex + FRONTMATTER_FENCE.length + 1);
@@ -66879,13 +67064,13 @@ function parseTestSpec(name, content) {
66879
67064
  const sections = splitIntoSections(body);
66880
67065
  const setup = sections.Setup;
66881
67066
  if (setup === void 0) {
66882
- return (0, import_neverthrow21.err)({ type: "MISSING_SETUP_SECTION" });
67067
+ return (0, import_neverthrow23.err)({ type: "MISSING_SETUP_SECTION" });
66883
67068
  }
66884
67069
  const stepsSection = sections.Steps;
66885
67070
  if (stepsSection === void 0) {
66886
- return (0, import_neverthrow21.err)({ type: "MISSING_STEPS_SECTION" });
67071
+ return (0, import_neverthrow23.err)({ type: "MISSING_STEPS_SECTION" });
66887
67072
  }
66888
- return (0, import_neverthrow21.ok)({
67073
+ return (0, import_neverthrow23.ok)({
66889
67074
  name,
66890
67075
  frontmatter,
66891
67076
  setup,
@@ -66912,8 +67097,8 @@ function direntToSpecEntry(directory, entry) {
66912
67097
  if (entry.isFile() && entry.name.endsWith(".md")) {
66913
67098
  return [
66914
67099
  {
66915
- path: import_node_path6.default.join(directory, entry.name),
66916
- name: import_node_path6.default.basename(entry.name, import_node_path6.default.extname(entry.name)),
67100
+ path: import_node_path7.default.join(directory, entry.name),
67101
+ name: import_node_path7.default.basename(entry.name, import_node_path7.default.extname(entry.name)),
66917
67102
  required: true
66918
67103
  }
66919
67104
  ];
@@ -66921,7 +67106,7 @@ function direntToSpecEntry(directory, entry) {
66921
67106
  if (entry.isDirectory()) {
66922
67107
  return [
66923
67108
  {
66924
- path: import_node_path6.default.join(directory, entry.name, "spec.md"),
67109
+ path: import_node_path7.default.join(directory, entry.name, "spec.md"),
66925
67110
  name: entry.name,
66926
67111
  required: false
66927
67112
  }
@@ -66930,25 +67115,25 @@ function direntToSpecEntry(directory, entry) {
66930
67115
  return [];
66931
67116
  }
66932
67117
  function scanDirectory(directory) {
66933
- const safeReaddir3 = (0, import_neverthrow22.fromAsyncThrowable)(
66934
- async () => (0, import_promises12.readdir)(directory, { withFileTypes: true }),
67118
+ const safeReaddir3 = (0, import_neverthrow24.fromAsyncThrowable)(
67119
+ async () => (0, import_promises13.readdir)(directory, { withFileTypes: true }),
66935
67120
  (cause) => ({ type: "DIR_READ_FAILED", dir: directory, cause })
66936
67121
  );
66937
- return safeReaddir3().orElse((error48) => isNotFound(error48.cause) ? (0, import_neverthrow22.okAsync)([]) : (0, import_neverthrow22.errAsync)(error48)).map(
67122
+ return safeReaddir3().orElse((error48) => isNotFound(error48.cause) ? (0, import_neverthrow24.okAsync)([]) : (0, import_neverthrow24.errAsync)(error48)).map(
66938
67123
  (entries) => entries.flatMap((entry) => direntToSpecEntry(directory, entry))
66939
67124
  );
66940
67125
  }
66941
67126
  function readEntries(entries) {
66942
- return import_neverthrow22.ResultAsync.combine(entries.map((entry) => readEntry(entry))).map(
67127
+ return import_neverthrow24.ResultAsync.combine(entries.map((entry) => readEntry(entry))).map(
66943
67128
  (results) => results.flat()
66944
67129
  );
66945
67130
  }
66946
67131
  function readEntry(entry) {
66947
- const safeReadFile6 = (0, import_neverthrow22.fromAsyncThrowable)(
66948
- async () => (0, import_promises12.readFile)(entry.path, "utf8"),
67132
+ const safeReadFile6 = (0, import_neverthrow24.fromAsyncThrowable)(
67133
+ async () => (0, import_promises13.readFile)(entry.path, "utf8"),
66949
67134
  (cause) => ({ type: "FILE_READ_FAILED", path: entry.path, cause })
66950
67135
  );
66951
- return safeReadFile6().map((content) => [{ name: entry.name, content }]).orElse((error48) => entry.required ? (0, import_neverthrow22.errAsync)(error48) : (0, import_neverthrow22.okAsync)([]));
67136
+ return safeReadFile6().map((content) => [{ name: entry.name, content }]).orElse((error48) => entry.required ? (0, import_neverthrow24.errAsync)(error48) : (0, import_neverthrow24.okAsync)([]));
66952
67137
  }
66953
67138
  function specNameFromPath(filePath) {
66954
67139
  const parts = filePath.split("/");
@@ -66956,7 +67141,7 @@ function specNameFromPath(filePath) {
66956
67141
  if (fileName === "spec.md" && parts.length >= 2) {
66957
67142
  return parts.at(-2) ?? fileName;
66958
67143
  }
66959
- return import_node_path6.default.basename(fileName, import_node_path6.default.extname(fileName));
67144
+ return import_node_path7.default.basename(fileName, import_node_path7.default.extname(fileName));
66960
67145
  }
66961
67146
  function filterByNames(specs, specNames) {
66962
67147
  if (!specNames || specNames.length === 0) {
@@ -66965,11 +67150,11 @@ function filterByNames(specs, specNames) {
66965
67150
  return specs.filter((spec) => specNames.includes(spec.name));
66966
67151
  }
66967
67152
  function resolveSpecs(config3, repoRoot = process.cwd()) {
66968
- const source = config3.specFiles && config3.specFiles.length > 0 ? loadFromFiles(config3.specFiles) : loadFromDirectory(import_node_path6.default.join(repoRoot, "openspec", "specs"));
67153
+ const source = config3.specFiles && config3.specFiles.length > 0 ? loadFromFiles(config3.specFiles) : loadFromDirectory(import_node_path7.default.join(repoRoot, "openspec", "specs"));
66969
67154
  return source.map((specs) => filterByNames(specs, config3.specNames));
66970
67155
  }
66971
67156
  var ISO_DATE_LENGTH = 10;
66972
- function buildPrompt(safeConfig, specs) {
67157
+ function buildPrompt2(safeConfig, specs) {
66973
67158
  return generateExplorerPrompt({
66974
67159
  mode: safeConfig.mode,
66975
67160
  specs,
@@ -66979,7 +67164,7 @@ function buildPrompt(safeConfig, specs) {
66979
67164
  });
66980
67165
  }
66981
67166
  function parseSpecs(resolvedSpecs) {
66982
- return import_neverthrow18.Result.combine(
67167
+ return import_neverthrow20.Result.combine(
66983
67168
  resolvedSpecs.map(
66984
67169
  (spec) => parseTestSpec(spec.name, spec.content).mapErr(
66985
67170
  (cause) => ({ type: "SPEC_PARSE_FAILED", specName: spec.name, cause })
@@ -67034,16 +67219,16 @@ function collectAndFinalize({
67034
67219
  }
67035
67220
  function resolveAndParseSpecs(safeConfig) {
67036
67221
  if (safeConfig.mode === "freestyle") {
67037
- return (0, import_neverthrow18.okAsync)([]);
67222
+ return (0, import_neverthrow20.okAsync)([]);
67038
67223
  }
67039
67224
  return resolveSpecs(safeConfig).mapErr((cause) => ({ type: "SPEC_RESOLVE_FAILED", cause })).andThen((specs) => parseSpecs(specs));
67040
67225
  }
67041
- function runPipeline({
67226
+ function runPipeline2({
67042
67227
  safeConfig,
67043
67228
  runPaths,
67044
67229
  start
67045
67230
  }) {
67046
- return resolveAndParseSpecs(safeConfig).map((parsedSpecs) => buildPrompt(safeConfig, parsedSpecs)).map((prompt) => {
67231
+ return resolveAndParseSpecs(safeConfig).map((parsedSpecs) => buildPrompt2(safeConfig, parsedSpecs)).map((prompt) => {
67047
67232
  safeConfig.onEvent?.({ type: "SYSTEM_PROMPT", agent: "explorer", prompt });
67048
67233
  return prompt;
67049
67234
  }).andThen((prompt) => collectAndFinalize({ safeConfig, prompt, runPaths, start }));
@@ -67057,11 +67242,11 @@ function runExplorer(config3) {
67057
67242
  date: date5
67058
67243
  });
67059
67244
  if (runPathsResult.isErr()) {
67060
- return (0, import_neverthrow18.errAsync)({ type: "RUN_PATHS_FAILED", cause: runPathsResult.error });
67245
+ return (0, import_neverthrow20.errAsync)({ type: "RUN_PATHS_FAILED", cause: runPathsResult.error });
67061
67246
  }
67062
67247
  const runPaths = runPathsResult.value;
67063
67248
  if (config3.signal?.aborted) {
67064
- return (0, import_neverthrow18.okAsync)(toArtifacts({ findings: [], snapshots: [] }, runPaths));
67249
+ return (0, import_neverthrow20.okAsync)(toArtifacts({ findings: [], snapshots: [] }, runPaths));
67065
67250
  }
67066
67251
  const safeConfig = {
67067
67252
  ...config3,
@@ -67069,25 +67254,25 @@ function runExplorer(config3) {
67069
67254
  onEvent: config3.onEvent === void 0 ? void 0 : safeHandler(config3.onEvent)
67070
67255
  };
67071
67256
  safeConfig.onEvent?.({ type: "STAGE_START", agent: "explorer" });
67072
- return import_neverthrow18.ResultAsync.fromSafePromise(
67073
- (0, import_promises11.mkdir)(runPaths.screenshotsDir, { recursive: true }).catch(() => null)
67074
- ).andThen(() => runPipeline({ safeConfig, runPaths, start }));
67257
+ return import_neverthrow20.ResultAsync.fromSafePromise(
67258
+ (0, import_promises12.mkdir)(runPaths.screenshotsDir, { recursive: true }).catch(() => null)
67259
+ ).andThen(() => runPipeline2({ safeConfig, runPaths, start }));
67075
67260
  }
67076
67261
 
67077
67262
  // ../../packages/pipeline/dist/index.js
67078
- var import_neverthrow34 = __toESM(require_index_cjs(), 1);
67263
+ var import_neverthrow36 = __toESM(require_index_cjs(), 1);
67079
67264
 
67080
67265
  // ../../agents/inspector/dist/index.js
67081
- var import_neverthrow23 = __toESM(require_index_cjs(), 1);
67082
- var import_promises13 = require("node:fs/promises");
67083
- var import_neverthrow24 = __toESM(require_index_cjs(), 1);
67084
67266
  var import_neverthrow25 = __toESM(require_index_cjs(), 1);
67267
+ var import_promises14 = require("node:fs/promises");
67085
67268
  var import_neverthrow26 = __toESM(require_index_cjs(), 1);
67086
67269
  var import_neverthrow27 = __toESM(require_index_cjs(), 1);
67087
- var import_sharp2 = __toESM(require("sharp"), 1);
67088
67270
  var import_neverthrow28 = __toESM(require_index_cjs(), 1);
67089
- var import_promises14 = require("node:fs/promises");
67090
- var import_node_path7 = __toESM(require("node:path"), 1);
67271
+ var import_neverthrow29 = __toESM(require_index_cjs(), 1);
67272
+ var import_sharp2 = __toESM(require("sharp"), 1);
67273
+ var import_neverthrow30 = __toESM(require_index_cjs(), 1);
67274
+ var import_promises15 = require("node:fs/promises");
67275
+ var import_node_path8 = __toESM(require("node:path"), 1);
67091
67276
 
67092
67277
  // ../../node_modules/.pnpm/js-yaml@4.1.1/node_modules/js-yaml/dist/js-yaml.mjs
67093
67278
  function isNothing(subject) {
@@ -68052,7 +68237,7 @@ var directiveHandlers = {
68052
68237
  }
68053
68238
  try {
68054
68239
  prefix = decodeURIComponent(prefix);
68055
- } catch (err25) {
68240
+ } catch (err26) {
68056
68241
  throwError(state, "tag prefix is malformed: " + prefix);
68057
68242
  }
68058
68243
  state.tagMap[handle] = prefix;
@@ -68733,7 +68918,7 @@ function readTagProperty(state) {
68733
68918
  }
68734
68919
  try {
68735
68920
  tagName = decodeURIComponent(tagName);
68736
- } catch (err25) {
68921
+ } catch (err26) {
68737
68922
  throwError(state, "tag name is malformed: " + tagName);
68738
68923
  }
68739
68924
  if (isVerbatim) {
@@ -69714,7 +69899,7 @@ var jsYaml = {
69714
69899
  };
69715
69900
 
69716
69901
  // ../../agents/inspector/dist/index.js
69717
- var import_neverthrow29 = __toESM(require_index_cjs(), 1);
69902
+ var import_neverthrow31 = __toESM(require_index_cjs(), 1);
69718
69903
  var MS_PER_DAY = 864e5;
69719
69904
  function dequeue(context, current) {
69720
69905
  if (current.remainingQueue.length === 0 || context.activeCount + current.events.length >= context.maxConcurrency) {
@@ -69752,20 +69937,21 @@ function scheduleNext(state, maxConcurrency) {
69752
69937
  { events: [], remainingQueue: state.queue }
69753
69938
  );
69754
69939
  }
69755
- var CONFIDENCE_HIGH = 0.9;
69756
- var CONFIDENCE_MEDIUM = 0.6;
69757
- var CONFIDENCE_LOW = 0.3;
69758
69940
  function toTriggerType(type2) {
69759
69941
  return type2 === "localization-issue" ? "localization-issue" : "visual-regression";
69760
69942
  }
69761
- function toConfidence(severity) {
69762
- if (severity === "high") {
69763
- return CONFIDENCE_HIGH;
69764
- }
69765
- if (severity === "medium") {
69766
- return CONFIDENCE_MEDIUM;
69943
+ function severityToConfidence(severity) {
69944
+ switch (severity) {
69945
+ case "high": {
69946
+ return "HIGH";
69947
+ }
69948
+ case "medium": {
69949
+ return "MEDIUM";
69950
+ }
69951
+ case "low": {
69952
+ return "LOW";
69953
+ }
69767
69954
  }
69768
- return CONFIDENCE_LOW;
69769
69955
  }
69770
69956
  function parseJson(raw) {
69771
69957
  return JSON.parse(raw);
@@ -69785,13 +69971,13 @@ function mapRawFinding(item) {
69785
69971
  triggerType: toTriggerType(item.type),
69786
69972
  flow: "",
69787
69973
  steps: [],
69788
- confidence: toConfidence(item.severity),
69974
+ confidence: severityToConfidence(item.severity),
69789
69975
  description: `[${item.element}] ${item.description}`,
69790
69976
  screenshots: [],
69791
69977
  agent: "inspector"
69792
69978
  };
69793
69979
  }
69794
- var safeJsonParse3 = (0, import_neverthrow26.fromThrowable)(parseJson);
69980
+ var safeJsonParse3 = (0, import_neverthrow28.fromThrowable)(parseJson);
69795
69981
  function parseClaudeResponse(raw) {
69796
69982
  const parseResult = safeJsonParse3(raw);
69797
69983
  if (parseResult.isErr()) {
@@ -69818,7 +70004,7 @@ async function downscaleBuffer(buffer) {
69818
70004
  return (0, import_sharp2.default)(buffer).resize({ width: targetWidth }).toBuffer();
69819
70005
  }
69820
70006
  function downscale(buffer) {
69821
- return (0, import_neverthrow27.fromAsyncThrowable)(
70007
+ return (0, import_neverthrow29.fromAsyncThrowable)(
69822
70008
  downscaleBuffer,
69823
70009
  (cause) => ({ type: "CLAUDE_API_FAILED", cause })
69824
70010
  )(buffer);
@@ -69893,7 +70079,7 @@ async function fetchClaudeText({
69893
70079
  return block?.type === "text" ? block.text : "";
69894
70080
  }
69895
70081
  function callClaude(options2) {
69896
- return (0, import_neverthrow25.fromAsyncThrowable)(
70082
+ return (0, import_neverthrow27.fromAsyncThrowable)(
69897
70083
  fetchClaudeText,
69898
70084
  (cause) => ({ type: "CLAUDE_API_FAILED", cause })
69899
70085
  )(options2);
@@ -69905,9 +70091,9 @@ function toFindings(text) {
69905
70091
  const cleaned = stripCodeFences(text);
69906
70092
  const findings = parseClaudeResponse(cleaned);
69907
70093
  if (!findings) {
69908
- return (0, import_neverthrow25.errAsync)({ type: "CLAUDE_RESPONSE_INVALID", raw: cleaned });
70094
+ return (0, import_neverthrow27.errAsync)({ type: "CLAUDE_RESPONSE_INVALID", raw: cleaned });
69909
70095
  }
69910
- return (0, import_neverthrow25.okAsync)(findings);
70096
+ return (0, import_neverthrow27.okAsync)(findings);
69911
70097
  }
69912
70098
  function buildResolveMessages(screenshotBase64, artboardNames) {
69913
70099
  return [
@@ -69944,12 +70130,12 @@ async function fetchResolveName({
69944
70130
  }
69945
70131
  function resolveArtboard(screenshot, artboardNames) {
69946
70132
  if (artboardNames.length === 0) {
69947
- return (0, import_neverthrow25.okAsync)(void 0);
70133
+ return (0, import_neverthrow27.okAsync)(void 0);
69948
70134
  }
69949
70135
  const anthropic = new Anthropic();
69950
70136
  return downscale(screenshot).andThen((scaled) => {
69951
70137
  const screenshotBase64 = scaled.toString("base64");
69952
- return (0, import_neverthrow25.fromAsyncThrowable)(
70138
+ return (0, import_neverthrow27.fromAsyncThrowable)(
69953
70139
  fetchResolveName,
69954
70140
  (cause) => ({ type: "CLAUDE_API_FAILED", cause })
69955
70141
  )({ anthropic, screenshotBase64, artboardNames }).map((name) => {
@@ -69977,8 +70163,6 @@ var MAX_TOKENS22 = 2048;
69977
70163
  var CANDIDATES_MAX_TOKENS = 64;
69978
70164
  var MAX_CANDIDATES = 3;
69979
70165
  var TEMPERATURE2 = 0;
69980
- var CONFIDENCE_MEDIUM2 = 0.6;
69981
- var CONFIDENCE_LOW2 = 0.3;
69982
70166
  var DESIGN_CONTEXT_SYSTEM_PROMPT = `You are a visual QA engineer performing design-system inference. You will receive multiple candidate artboards followed by an actual screenshot.
69983
70167
 
69984
70168
  Infer the design system (color palette, typography scale, component patterns) from the candidate artboards. Then compare the screenshot against the inferred design system.
@@ -70008,11 +70192,17 @@ function isRawConservativeFinding(value) {
70008
70192
  const object2 = value;
70009
70193
  return typeof object2.type === "string" && typeof object2.element === "string" && typeof object2.description === "string" && typeof object2.severity === "string" && isValidConservativeSeverity(object2.severity);
70010
70194
  }
70011
- var SEVERITY_CONFIDENCE = {
70012
- medium: CONFIDENCE_MEDIUM2,
70013
- low: CONFIDENCE_LOW2
70014
- };
70015
- var safeJsonParse22 = (0, import_neverthrow28.fromThrowable)(JSON.parse);
70195
+ function conservativeSeverityToConfidence(severity) {
70196
+ switch (severity) {
70197
+ case "medium": {
70198
+ return "MEDIUM";
70199
+ }
70200
+ case "low": {
70201
+ return "LOW";
70202
+ }
70203
+ }
70204
+ }
70205
+ var safeJsonParse22 = (0, import_neverthrow30.fromThrowable)(JSON.parse);
70016
70206
  function resolveNamesFromParsed(parsed, artboardNames) {
70017
70207
  return parsed.filter((name) => typeof name === "string").map((name) => {
70018
70208
  const lower = name.toLowerCase();
@@ -70075,7 +70265,7 @@ function parseConservativeResponse(raw) {
70075
70265
  triggerType: "design-system-violation",
70076
70266
  flow: "",
70077
70267
  steps: [],
70078
- confidence: SEVERITY_CONFIDENCE[item.severity],
70268
+ confidence: conservativeSeverityToConfidence(item.severity),
70079
70269
  description: `[${item.element}] ${item.description}`,
70080
70270
  screenshots: [],
70081
70271
  agent: "inspector"
@@ -70101,9 +70291,9 @@ async function fetchDesignContextText({
70101
70291
  function toDesignContextFindings(text) {
70102
70292
  const findings = parseConservativeResponse(text);
70103
70293
  if (!findings) {
70104
- return (0, import_neverthrow28.errAsync)({ type: "CLAUDE_RESPONSE_INVALID", raw: text });
70294
+ return (0, import_neverthrow30.errAsync)({ type: "CLAUDE_RESPONSE_INVALID", raw: text });
70105
70295
  }
70106
- return (0, import_neverthrow28.okAsync)(findings);
70296
+ return (0, import_neverthrow30.okAsync)(findings);
70107
70297
  }
70108
70298
  async function downscaleAll(buffers) {
70109
70299
  return Promise.all(buffers.map(async (buf) => downscaleBuffer(buf)));
@@ -70129,12 +70319,12 @@ Artboards: ${artboardNames.join(", ")}`
70129
70319
  }
70130
70320
  function findCandidates(screenshot, artboardNames) {
70131
70321
  if (artboardNames.length === 0) {
70132
- return (0, import_neverthrow28.okAsync)([]);
70322
+ return (0, import_neverthrow30.okAsync)([]);
70133
70323
  }
70134
70324
  const anthropic = new Anthropic();
70135
70325
  return downscale(screenshot).andThen((scaled) => {
70136
70326
  const screenshotBase64 = scaled.toString("base64");
70137
- return (0, import_neverthrow28.fromAsyncThrowable)(
70327
+ return (0, import_neverthrow30.fromAsyncThrowable)(
70138
70328
  fetchCandidateNames,
70139
70329
  (cause) => ({ type: "CLAUDE_API_FAILED", cause })
70140
70330
  )({ anthropic, screenshotBase64, artboardNames });
@@ -70158,7 +70348,7 @@ function buildDesignContextMessages(screenshotBase64, artboardBase64s) {
70158
70348
  }
70159
70349
  ];
70160
70350
  }
70161
- var downscaleAllBuffers = (0, import_neverthrow28.fromAsyncThrowable)(
70351
+ var downscaleAllBuffers = (0, import_neverthrow30.fromAsyncThrowable)(
70162
70352
  downscaleAll,
70163
70353
  (cause) => ({ type: "CLAUDE_API_FAILED", cause })
70164
70354
  );
@@ -70168,7 +70358,7 @@ function compareWithDesignContext(screenshot, artboards) {
70168
70358
  const screenshotBase64 = scaledScreenshot.toString("base64");
70169
70359
  return downscaleAllBuffers(artboards).andThen((scaledArtboards) => {
70170
70360
  const artboardBase64s = scaledArtboards.map((buf) => buf.toString("base64"));
70171
- return (0, import_neverthrow28.fromAsyncThrowable)(
70361
+ return (0, import_neverthrow30.fromAsyncThrowable)(
70172
70362
  fetchDesignContextText,
70173
70363
  (cause) => ({ type: "CLAUDE_API_FAILED", cause })
70174
70364
  )({ anthropic, screenshotBase64, artboardBase64s }).andThen(toDesignContextFindings);
@@ -70402,8 +70592,8 @@ async function initArtboardNames({ designStore, config: config3, state }) {
70402
70592
  );
70403
70593
  }
70404
70594
  function readScreenshot(screenshotPath, stepIndex) {
70405
- return import_neverthrow24.ResultAsync.fromThrowable(
70406
- import_promises13.readFile,
70595
+ return import_neverthrow26.ResultAsync.fromThrowable(
70596
+ import_promises14.readFile,
70407
70597
  (cause) => ({ type: "SCREENSHOT_READ_FAILED", stepIndex, cause })
70408
70598
  )(screenshotPath);
70409
70599
  }
@@ -70475,7 +70665,7 @@ function buildInspector(state, context) {
70475
70665
  const { promise: promise2, resolve } = Promise.withResolvers();
70476
70666
  state.setResolve(resolve);
70477
70667
  applyTryResolve(state);
70478
- return (0, import_neverthrow23.fromSafePromise)(promise2);
70668
+ return (0, import_neverthrow25.fromSafePromise)(promise2);
70479
70669
  }
70480
70670
  };
70481
70671
  }
@@ -70524,14 +70714,14 @@ function parseMeta(raw) {
70524
70714
  return {};
70525
70715
  }
70526
70716
  async function readAndParseSidecar(sidecarPath) {
70527
- const raw = await (0, import_promises14.readFile)(sidecarPath, "utf8");
70717
+ const raw = await (0, import_promises15.readFile)(sidecarPath, "utf8");
70528
70718
  return parseMeta(raw);
70529
70719
  }
70530
70720
  function readSidecarFile(sidecarPath) {
70531
- return (0, import_neverthrow29.fromAsyncThrowable)(
70721
+ return (0, import_neverthrow31.fromAsyncThrowable)(
70532
70722
  readAndParseSidecar,
70533
70723
  () => ({})
70534
- )(sidecarPath).orElse(() => (0, import_neverthrow29.okAsync)({}));
70724
+ )(sidecarPath).orElse(() => (0, import_neverthrow31.okAsync)({}));
70535
70725
  }
70536
70726
  function isEnoent(error48) {
70537
70727
  return error48?.code === "ENOENT";
@@ -70540,13 +70730,13 @@ function wrapFsError(cause) {
70540
70730
  return { type: "FS_ERROR", cause };
70541
70731
  }
70542
70732
  function toFsError(fsError) {
70543
- return (0, import_neverthrow29.errAsync)(fsError);
70733
+ return (0, import_neverthrow31.errAsync)(fsError);
70544
70734
  }
70545
70735
  function missingBuffer() {
70546
- return (0, import_neverthrow29.okAsync)(void 0);
70736
+ return (0, import_neverthrow31.okAsync)(void 0);
70547
70737
  }
70548
70738
  function missingArtboard() {
70549
- return (0, import_neverthrow29.okAsync)(void 0);
70739
+ return (0, import_neverthrow31.okAsync)(void 0);
70550
70740
  }
70551
70741
  var FsDesignStore = class {
70552
70742
  designsDirectory;
@@ -70554,12 +70744,12 @@ var FsDesignStore = class {
70554
70744
  this.designsDirectory = designsDirectory;
70555
70745
  }
70556
70746
  listArtboards() {
70557
- return (0, import_neverthrow29.fromAsyncThrowable)(
70558
- import_promises14.readdir,
70747
+ return (0, import_neverthrow31.fromAsyncThrowable)(
70748
+ import_promises15.readdir,
70559
70749
  wrapFsError
70560
70750
  )(this.designsDirectory).orElse((fsError) => {
70561
70751
  if (fsError.type === "FS_ERROR" && isEnoent(fsError.cause)) {
70562
- return (0, import_neverthrow29.okAsync)([]);
70752
+ return (0, import_neverthrow31.okAsync)([]);
70563
70753
  }
70564
70754
  return toFsError(fsError);
70565
70755
  }).map(
@@ -70567,10 +70757,10 @@ var FsDesignStore = class {
70567
70757
  );
70568
70758
  }
70569
70759
  getArtboard(filename) {
70570
- const pngPath = import_node_path7.default.join(this.designsDirectory, `${filename}.png`);
70571
- const sidecarPath = import_node_path7.default.join(this.designsDirectory, `${filename}.meta.yaml`);
70572
- return (0, import_neverthrow29.fromAsyncThrowable)(
70573
- import_promises14.readFile,
70760
+ const pngPath = import_node_path8.default.join(this.designsDirectory, `${filename}.png`);
70761
+ const sidecarPath = import_node_path8.default.join(this.designsDirectory, `${filename}.meta.yaml`);
70762
+ return (0, import_neverthrow31.fromAsyncThrowable)(
70763
+ import_promises15.readFile,
70574
70764
  wrapFsError
70575
70765
  )(pngPath).orElse((fsError) => {
70576
70766
  if (fsError.type === "FS_ERROR" && isEnoent(fsError.cause)) {
@@ -70591,21 +70781,21 @@ var FsDesignStore = class {
70591
70781
  // ../../packages/pipeline/dist/index.js
70592
70782
  var RETRY_MAX_ATTEMPTS = 3;
70593
70783
  var RETRY_BASE_DELAY_MS = 1e3;
70594
- var CONFIDENCE_THRESHOLD = 0.7;
70784
+ var CONFIDENCE_THRESHOLD = "HIGH";
70595
70785
  function filterByConfidence(findings, threshold) {
70596
70786
  return {
70597
- kept: findings.filter((finding) => finding.confidence >= threshold),
70598
- dropped: findings.filter((finding) => finding.confidence < threshold).map((finding) => ({ finding, reason: "low-confidence" }))
70787
+ kept: findings.filter((finding) => meetsConfidenceThreshold(finding.confidence, threshold)),
70788
+ dropped: findings.filter((finding) => !meetsConfidenceThreshold(finding.confidence, threshold)).map((finding) => ({ finding, reason: "low-confidence" }))
70599
70789
  };
70600
70790
  }
70601
70791
  function attemptRetry(options2) {
70602
70792
  const { factory, config: config3, delayFunction, onRetry, attempt } = options2;
70603
70793
  return factory().orElse((error48) => {
70604
70794
  if (attempt >= config3.maxAttempts) {
70605
- return (0, import_neverthrow32.errAsync)(error48);
70795
+ return (0, import_neverthrow34.errAsync)(error48);
70606
70796
  }
70607
70797
  const delay = config3.baseDelayMs * Math.pow(2, attempt - 1);
70608
- return import_neverthrow32.ResultAsync.fromPromise(
70798
+ return import_neverthrow34.ResultAsync.fromPromise(
70609
70799
  (onRetry?.({ attempt, maxAttempts: config3.maxAttempts, delayMs: delay, error: error48 }), delayFunction(delay)),
70610
70800
  () => error48
70611
70801
  ).andThen(
@@ -70625,7 +70815,7 @@ function withRetry(factory, options2) {
70625
70815
  var CONSOLIDATOR_AGENT = "consolidator";
70626
70816
  function analyserFallback(artifacts, onEvent) {
70627
70817
  onEvent?.({ type: "AGENT_FAILED_NON_CRITICAL", agent: "analyser", attempts: RETRY_MAX_ATTEMPTS });
70628
- return (0, import_neverthrow31.okAsync)(artifacts.findings);
70818
+ return (0, import_neverthrow33.okAsync)(artifacts.findings);
70629
70819
  }
70630
70820
  function runAnalyserWithRetry(params) {
70631
70821
  const { artifacts, config: config3, onEvent } = params;
@@ -70635,7 +70825,7 @@ function runAnalyserWithRetry(params) {
70635
70825
  ),
70636
70826
  {
70637
70827
  config: { maxAttempts: RETRY_MAX_ATTEMPTS, baseDelayMs: RETRY_BASE_DELAY_MS },
70638
- delayFunction: import_promises15.setTimeout,
70828
+ delayFunction: import_promises16.setTimeout,
70639
70829
  onRetry: ({ attempt, maxAttempts, delayMs, error: error48 }) => {
70640
70830
  onEvent?.({
70641
70831
  type: "AGENT_RETRY",
@@ -70655,7 +70845,7 @@ function resolveVisualFindings({
70655
70845
  onEvent
70656
70846
  }) {
70657
70847
  if (config3.analyser === void 0 || config3.signal?.aborted) {
70658
- return (0, import_neverthrow31.okAsync)(artifacts.findings);
70848
+ return (0, import_neverthrow33.okAsync)(artifacts.findings);
70659
70849
  }
70660
70850
  return runAnalyserWithRetry({ artifacts, config: config3, onEvent });
70661
70851
  }
@@ -70665,7 +70855,7 @@ function unmergedFallback(allFindings, onEvent) {
70665
70855
  agent: CONSOLIDATOR_AGENT,
70666
70856
  message: "Consolidation failed, returning unmerged findings"
70667
70857
  });
70668
- return (0, import_neverthrow31.okAsync)({ findings: allFindings, dismissed: [] });
70858
+ return (0, import_neverthrow33.okAsync)({ findings: allFindings, dismissed: [] });
70669
70859
  }
70670
70860
  function mergeWithFallback(options2) {
70671
70861
  const {
@@ -70692,7 +70882,7 @@ function consolidate(options2) {
70692
70882
  const { artifacts, inspectorFindings, runId, dismissals, config: config3, consolidatorConfig, onEvent } = options2;
70693
70883
  return resolveVisualFindings({ artifacts, config: config3, onEvent }).andThen((visualFindings) => {
70694
70884
  if (config3.signal?.aborted) {
70695
- return (0, import_neverthrow31.okAsync)({ findings: artifacts.findings, dismissed: [] });
70885
+ return (0, import_neverthrow33.okAsync)({ findings: artifacts.findings, dismissed: [] });
70696
70886
  }
70697
70887
  return mergeWithFallback({
70698
70888
  artifacts,
@@ -70705,8 +70895,8 @@ function consolidate(options2) {
70705
70895
  });
70706
70896
  });
70707
70897
  }
70708
- var safeReadFile = (0, import_neverthrow33.fromThrowable)((filePath) => (0, import_node_fs3.readFileSync)(filePath, "utf8"));
70709
- var safeParseJson2 = (0, import_neverthrow33.fromThrowable)(JSON.parse);
70898
+ var safeReadFile = (0, import_neverthrow35.fromThrowable)((filePath) => (0, import_node_fs3.readFileSync)(filePath, "utf8"));
70899
+ var safeParseJson2 = (0, import_neverthrow35.fromThrowable)(JSON.parse);
70710
70900
  function isEnoent2(error48) {
70711
70901
  if (!(error48 instanceof Error)) {
70712
70902
  return false;
@@ -70718,19 +70908,19 @@ function loadDismissals(filePath) {
70718
70908
  const readResult = safeReadFile(filePath);
70719
70909
  if (readResult.isErr()) {
70720
70910
  if (isEnoent2(readResult.error)) {
70721
- return (0, import_neverthrow33.ok)([]);
70911
+ return (0, import_neverthrow35.ok)([]);
70722
70912
  }
70723
- return (0, import_neverthrow33.err)({ type: "DISMISSALS_LOAD_FAILED", cause: readResult.error });
70913
+ return (0, import_neverthrow35.err)({ type: "DISMISSALS_LOAD_FAILED", cause: readResult.error });
70724
70914
  }
70725
70915
  return safeParseJson2(readResult.value).mapErr((cause) => ({ type: "DISMISSALS_LOAD_FAILED", cause })).andThen((data) => {
70726
70916
  const store = data;
70727
70917
  if (!Array.isArray(store.dismissed)) {
70728
- return (0, import_neverthrow33.err)({
70918
+ return (0, import_neverthrow35.err)({
70729
70919
  type: "DISMISSALS_LOAD_FAILED",
70730
70920
  cause: "invalid shape: dismissed is not an array"
70731
70921
  });
70732
70922
  }
70733
- return (0, import_neverthrow33.ok)(store.dismissed);
70923
+ return (0, import_neverthrow35.ok)(store.dismissed);
70734
70924
  });
70735
70925
  }
70736
70926
  function toInspectorStepEvent(event) {
@@ -70817,14 +71007,14 @@ function runExplorerWithTeardown(explorerConfig, udid) {
70817
71007
  return runExplorer(explorerConfig).mapErr((cause) => ({ type: "EXPLORER_FAILED", cause })).andThen(
70818
71008
  (artifacts) => disableTouchIndicators(udid).mapErr(toSimulatorError).map(() => artifacts)
70819
71009
  ).orElse(
70820
- (error48) => disableTouchIndicators(udid).mapErr(toSimulatorError).andThen(() => (0, import_neverthrow34.errAsync)(error48)).orElse(() => (0, import_neverthrow34.errAsync)(error48))
71010
+ (error48) => disableTouchIndicators(udid).mapErr(toSimulatorError).andThen(() => (0, import_neverthrow36.errAsync)(error48)).orElse(() => (0, import_neverthrow36.errAsync)(error48))
70821
71011
  );
70822
71012
  }
70823
71013
  function runExplorerWithRetry(options2) {
70824
71014
  const { explorerConfig, udid, onEvent } = options2;
70825
71015
  return withRetry(() => runExplorerWithTeardown(explorerConfig, udid), {
70826
71016
  config: { maxAttempts: RETRY_MAX_ATTEMPTS, baseDelayMs: RETRY_BASE_DELAY_MS },
70827
- delayFunction: import_promises16.setTimeout,
71017
+ delayFunction: import_promises17.setTimeout,
70828
71018
  onRetry: ({ attempt, maxAttempts, delayMs, error: error48 }) => {
70829
71019
  onEvent?.({
70830
71020
  type: "AGENT_RETRY",
@@ -70843,12 +71033,12 @@ async function drainAfterExplorer(options2) {
70843
71033
  inspector?.close();
70844
71034
  const inspectorFindings = inspector ? await collectInspectorFindings({ inspector, onEvent, totalSteps: enqueuedCount.value }) : [];
70845
71035
  if (explorerResult.isErr()) {
70846
- return (0, import_neverthrow34.err)(explorerResult.error);
71036
+ return (0, import_neverthrow36.err)(explorerResult.error);
70847
71037
  }
70848
- return (0, import_neverthrow34.ok)({ artifacts: explorerResult.value, inspectorFindings });
71038
+ return (0, import_neverthrow36.ok)({ artifacts: explorerResult.value, inspectorFindings });
70849
71039
  }
70850
71040
  function runExplorerAndDrain(options2) {
70851
- return import_neverthrow34.ResultAsync.fromSafePromise(drainAfterExplorer(options2)).andThen((result) => result);
71041
+ return import_neverthrow36.ResultAsync.fromSafePromise(drainAfterExplorer(options2)).andThen((result) => result);
70852
71042
  }
70853
71043
  function createDefaultMcpServers(udid) {
70854
71044
  return {
@@ -70860,7 +71050,7 @@ function runAnalysis(artifacts, config3) {
70860
71050
  }
70861
71051
  var ISO_DATE_LENGTH2 = 10;
70862
71052
  var RUN_ID_PAD_LENGTH = 4;
70863
- var safeReaddirSync = (0, import_neverthrow30.fromThrowable)((directory) => (0, import_node_fs2.readdirSync)(directory));
71053
+ var safeReaddirSync = (0, import_neverthrow32.fromThrowable)((directory) => (0, import_node_fs2.readdirSync)(directory));
70864
71054
  function nextRunId(outputDirectory, date5) {
70865
71055
  const entries = safeReaddirSync(`${outputDirectory}/${date5}`).unwrapOr([]);
70866
71056
  let max = 0;
@@ -70872,7 +71062,7 @@ function nextRunId(outputDirectory, date5) {
70872
71062
  }
70873
71063
  return String(max + 1).padStart(RUN_ID_PAD_LENGTH, "0");
70874
71064
  }
70875
- var writeOutputFile = (0, import_neverthrow30.fromThrowable)(
71065
+ var writeOutputFile = (0, import_neverthrow32.fromThrowable)(
70876
71066
  (params) => {
70877
71067
  const { findingsPath, outputDirectory, json: json3 } = params;
70878
71068
  (0, import_node_fs2.mkdirSync)(outputDirectory, { recursive: true });
@@ -70885,15 +71075,15 @@ function validatePipelineConfig(config3) {
70885
71075
  const runId = config3.runId ?? nextRunId(config3.outputDir, date5);
70886
71076
  const runPathsResult = resolveRunPaths({ outputDirectory: config3.outputDir, runId, date: date5 });
70887
71077
  if (runPathsResult.isErr()) {
70888
- return (0, import_neverthrow30.err)({ type: "RUN_PATHS_FAILED", cause: runPathsResult.error });
71078
+ return (0, import_neverthrow32.err)({ type: "RUN_PATHS_FAILED", cause: runPathsResult.error });
70889
71079
  }
70890
71080
  const dismissalsResult = loadDismissals(
70891
71081
  dismissalsPath(config3.outputDir, process.env.QA_DISMISSALS_PATH)
70892
71082
  );
70893
71083
  if (dismissalsResult.isErr()) {
70894
- return (0, import_neverthrow30.err)(dismissalsResult.error);
71084
+ return (0, import_neverthrow32.err)(dismissalsResult.error);
70895
71085
  }
70896
- return (0, import_neverthrow30.ok)({ runId, date: date5, runPaths: runPathsResult.value, dismissals: dismissalsResult.value });
71086
+ return (0, import_neverthrow32.ok)({ runId, date: date5, runPaths: runPathsResult.value, dismissals: dismissalsResult.value });
70897
71087
  }
70898
71088
  function buildExplorerConfig({
70899
71089
  config: config3,
@@ -70931,11 +71121,11 @@ function buildOutput(consolidationResult, options2) {
70931
71121
  function buildPipelineSetup(config3) {
70932
71122
  const validatedResult = validatePipelineConfig(config3);
70933
71123
  if (validatedResult.isErr()) {
70934
- return (0, import_neverthrow30.err)(validatedResult.error);
71124
+ return (0, import_neverthrow32.err)(validatedResult.error);
70935
71125
  }
70936
71126
  const { runId, date: date5, runPaths, dismissals } = validatedResult.value;
70937
71127
  const { inspector, explorerOnEvent, enqueuedCount } = buildInspectorSetup(config3);
70938
- return (0, import_neverthrow30.ok)({
71128
+ return (0, import_neverthrow32.ok)({
70939
71129
  runId,
70940
71130
  udid: config3.simulatorUdid ?? "booted",
70941
71131
  runPaths,
@@ -70977,16 +71167,16 @@ function executePipeline(setup, config3) {
70977
71167
  })
70978
71168
  );
70979
71169
  }
70980
- function runPipeline2(config3) {
71170
+ function runPipeline3(config3) {
70981
71171
  const setupResult = buildPipelineSetup(config3);
70982
71172
  if (setupResult.isErr()) {
70983
- return (0, import_neverthrow30.errAsync)(setupResult.error);
71173
+ return (0, import_neverthrow32.errAsync)(setupResult.error);
70984
71174
  }
70985
71175
  return executePipeline(setupResult.value, config3);
70986
71176
  }
70987
71177
 
70988
71178
  // src/commands/analyse-command.ts
70989
- var import_neverthrow36 = __toESM(require_index_cjs(), 1);
71179
+ var import_neverthrow38 = __toESM(require_index_cjs(), 1);
70990
71180
 
70991
71181
  // src/commands/item-events.ts
70992
71182
  function emitItemStart(identity, at) {
@@ -71022,7 +71212,7 @@ function emitItemFailed(input) {
71022
71212
  }
71023
71213
 
71024
71214
  // src/shell/debug-agent-events.ts
71025
- var import_neverthrow35 = __toESM(require_index_cjs(), 1);
71215
+ var import_neverthrow37 = __toESM(require_index_cjs(), 1);
71026
71216
 
71027
71217
  // src/constants.ts
71028
71218
  var MOBILE_IOS_TOOLS = [
@@ -71105,7 +71295,7 @@ function tryStringify(value) {
71105
71295
  const result = JSON.stringify(value);
71106
71296
  return result ?? UNSERIALIZABLE;
71107
71297
  }
71108
- var safeStringify = (0, import_neverthrow35.fromThrowable)(tryStringify, () => ({
71298
+ var safeStringify = (0, import_neverthrow37.fromThrowable)(tryStringify, () => ({
71109
71299
  type: "STRINGIFY_FAILED"
71110
71300
  }));
71111
71301
  function toolKey(scope, event) {
@@ -71326,7 +71516,7 @@ function buildArtifacts(videoPath) {
71326
71516
  return { videoPath, findings: [], snapshots: [] };
71327
71517
  }
71328
71518
  async function checkVideoPathExists(videoPath) {
71329
- const safeAccess = (0, import_neverthrow36.fromAsyncThrowable)(import_promises17.access, () => ({ type: "FILE_NOT_FOUND" }));
71519
+ const safeAccess = (0, import_neverthrow38.fromAsyncThrowable)(import_promises18.access, () => ({ type: "FILE_NOT_FOUND" }));
71330
71520
  const result = await safeAccess(videoPath);
71331
71521
  return result.isOk();
71332
71522
  }
@@ -71421,7 +71611,7 @@ async function runAnalyseCommand(input) {
71421
71611
  }
71422
71612
 
71423
71613
  // src/core/completion-generator.ts
71424
- var import_neverthrow37 = __toESM(require_index_cjs(), 1);
71614
+ var import_neverthrow39 = __toESM(require_index_cjs(), 1);
71425
71615
  function extractLongFlags(flags) {
71426
71616
  return flags.split(/[\s,]+/).filter((token) => token.startsWith("--"));
71427
71617
  }
@@ -71511,9 +71701,9 @@ complete -F _xqa_completion xqa`;
71511
71701
  }
71512
71702
  function generateCompletion(commands, shell) {
71513
71703
  if (shell !== "bash" && shell !== "zsh") {
71514
- return (0, import_neverthrow37.err)({ type: "UNSUPPORTED_SHELL", shell });
71704
+ return (0, import_neverthrow39.err)({ type: "UNSUPPORTED_SHELL", shell });
71515
71705
  }
71516
- return (0, import_neverthrow37.ok)(shell === "zsh" ? generateZshCompletion(commands) : generateBashCompletion(commands));
71706
+ return (0, import_neverthrow39.ok)(shell === "zsh" ? generateZshCompletion(commands) : generateBashCompletion(commands));
71517
71707
  }
71518
71708
 
71519
71709
  // src/commands/completion-command.ts
@@ -71546,33 +71736,33 @@ function runCompletionCommand(program3, shell) {
71546
71736
  }
71547
71737
 
71548
71738
  // src/commands/explore-command.ts
71549
- var import_node_path10 = __toESM(require("node:path"), 1);
71739
+ var import_node_path11 = __toESM(require("node:path"), 1);
71550
71740
 
71551
71741
  // src/core/last-path.ts
71552
71742
  var import_node_fs4 = require("node:fs");
71553
- var import_node_path8 = __toESM(require("node:path"), 1);
71554
- var import_neverthrow38 = __toESM(require_index_cjs(), 1);
71743
+ var import_node_path9 = __toESM(require("node:path"), 1);
71744
+ var import_neverthrow40 = __toESM(require_index_cjs(), 1);
71555
71745
  function resolveLastPath(argument, stateContent) {
71556
71746
  if (argument !== void 0) {
71557
- return (0, import_neverthrow38.ok)(argument);
71747
+ return (0, import_neverthrow40.ok)(argument);
71558
71748
  }
71559
71749
  const trimmed = stateContent?.trim();
71560
71750
  if (trimmed) {
71561
- return (0, import_neverthrow38.ok)(trimmed);
71751
+ return (0, import_neverthrow40.ok)(trimmed);
71562
71752
  }
71563
- return (0, import_neverthrow38.err)({ type: "NO_ARG_AND_NO_STATE" });
71753
+ return (0, import_neverthrow40.err)({ type: "NO_ARG_AND_NO_STATE" });
71564
71754
  }
71565
71755
  function lastPathFilePath(xqaDirectoryectory) {
71566
- return import_node_path8.default.join(xqaDirectoryectory, "last-findings-path");
71756
+ return import_node_path9.default.join(xqaDirectoryectory, "last-findings-path");
71567
71757
  }
71568
71758
  function writeLastPath(xqaDirectory, findingsPath) {
71569
71759
  (0, import_node_fs4.writeFileSync)(lastPathFilePath(xqaDirectory), findingsPath);
71570
71760
  }
71571
71761
 
71572
71762
  // src/shell/app-context.ts
71573
- var import_promises18 = require("node:fs/promises");
71574
- var import_node_path9 = __toESM(require("node:path"), 1);
71575
- var import_neverthrow39 = __toESM(require_index_cjs(), 1);
71763
+ var import_promises19 = require("node:fs/promises");
71764
+ var import_node_path10 = __toESM(require("node:path"), 1);
71765
+ var import_neverthrow41 = __toESM(require_index_cjs(), 1);
71576
71766
  var HTML_COMMENT_PATTERN = /<!--[\s\S]*?-->/g;
71577
71767
  function isEnoentError(value) {
71578
71768
  return value !== null && typeof value === "object" && "code" in value && value.code === "ENOENT";
@@ -71582,10 +71772,10 @@ function toAppContextError(cause) {
71582
71772
  }
71583
71773
  function absentContext() {
71584
71774
  const absent = void 0;
71585
- return (0, import_neverthrow39.ok)(absent);
71775
+ return (0, import_neverthrow41.ok)(absent);
71586
71776
  }
71587
- var safeReadFile2 = import_neverthrow39.ResultAsync.fromThrowable(
71588
- async (filePath) => (0, import_promises18.readFile)(filePath, "utf8"),
71777
+ var safeReadFile2 = import_neverthrow41.ResultAsync.fromThrowable(
71778
+ async (filePath) => (0, import_promises19.readFile)(filePath, "utf8"),
71589
71779
  toAppContextError
71590
71780
  );
71591
71781
  function stripAndNormalize(content) {
@@ -71593,12 +71783,12 @@ function stripAndNormalize(content) {
71593
71783
  return stripped.length === 0 ? void 0 : stripped;
71594
71784
  }
71595
71785
  function readContextFile(xqaDirectory, filename) {
71596
- const filePath = import_node_path9.default.join(xqaDirectory, filename);
71786
+ const filePath = import_node_path10.default.join(xqaDirectory, filename);
71597
71787
  return safeReadFile2(filePath).map((content) => stripAndNormalize(content)).orElse((error48) => {
71598
71788
  if (isEnoentError(error48.cause)) {
71599
71789
  return absentContext();
71600
71790
  }
71601
- return (0, import_neverthrow39.err)(error48);
71791
+ return (0, import_neverthrow41.err)(error48);
71602
71792
  });
71603
71793
  }
71604
71794
  function readAppContext(xqaDirectory) {
@@ -71647,12 +71837,12 @@ function buildPipelineConfig({
71647
71837
  simulatorUdid
71648
71838
  }) {
71649
71839
  const base = {
71650
- outputDir: import_node_path10.default.join(xqaDirectory, "output"),
71840
+ outputDir: import_node_path11.default.join(xqaDirectory, "output"),
71651
71841
  runId: config3.QA_RUN_ID,
71652
71842
  simulatorUdid,
71653
71843
  onEvent,
71654
71844
  signal: input.signal,
71655
- inspector: { designsDirectory: import_node_path10.default.join(xqaDirectory, "designs") },
71845
+ inspector: { designsDirectory: import_node_path11.default.join(xqaDirectory, "designs") },
71656
71846
  explorer
71657
71847
  };
71658
71848
  if (!config3.GOOGLE_GENERATIVE_AI_API_KEY) {
@@ -71714,7 +71904,7 @@ function runExplorePipeline(state, contexts) {
71714
71904
  appContext: contexts.appContext,
71715
71905
  initialState: contexts.exploreContext
71716
71906
  });
71717
- void runPipeline2(
71907
+ void runPipeline3(
71718
71908
  buildPipelineConfig({
71719
71909
  input,
71720
71910
  config: config3,
@@ -71794,21 +71984,21 @@ function runExploreCommand(input, options2) {
71794
71984
 
71795
71985
  // src/commands/init-command.ts
71796
71986
  var import_node_fs6 = require("node:fs");
71797
- var import_node_path12 = __toESM(require("node:path"), 1);
71987
+ var import_node_path13 = __toESM(require("node:path"), 1);
71798
71988
 
71799
71989
  // src/commands/install-skills.ts
71800
71990
  var import_node_child_process5 = require("node:child_process");
71801
71991
  var import_node_fs5 = require("node:fs");
71802
- var import_node_path11 = __toESM(require("node:path"), 1);
71992
+ var import_node_path12 = __toESM(require("node:path"), 1);
71803
71993
  var import_node_url = require("node:url");
71804
71994
  function resolveSkillsRoot() {
71805
- const packageDistributionDirectory = import_node_path11.default.dirname((0, import_node_url.fileURLToPath)(__importMetaUrl));
71806
- return import_node_path11.default.join(packageDistributionDirectory, "skills");
71995
+ const packageDistributionDirectory = import_node_path12.default.dirname((0, import_node_url.fileURLToPath)(__importMetaUrl));
71996
+ return import_node_path12.default.join(packageDistributionDirectory, "skills");
71807
71997
  }
71808
71998
  function installSkills() {
71809
71999
  const skillsRoot = resolveSkillsRoot();
71810
72000
  for (const skill of (0, import_node_fs5.readdirSync)(skillsRoot)) {
71811
- (0, import_node_child_process5.spawnSync)("npx", ["skills", "add", import_node_path11.default.join(skillsRoot, skill), "-y"], {
72001
+ (0, import_node_child_process5.spawnSync)("npx", ["skills", "add", import_node_path12.default.join(skillsRoot, skill), "-y"], {
71812
72002
  stdio: "inherit"
71813
72003
  });
71814
72004
  }
@@ -71860,7 +72050,7 @@ Scope applies from the starting screen. If the focus area requires navigation, d
71860
72050
  -->
71861
72051
  `;
71862
72052
  function runInitCommand() {
71863
- const xqaDirectory = import_node_path12.default.join(process.cwd(), ".xqa");
72053
+ const xqaDirectory = import_node_path13.default.join(process.cwd(), ".xqa");
71864
72054
  installSkills();
71865
72055
  if ((0, import_node_fs6.existsSync)(xqaDirectory)) {
71866
72056
  process.stdout.write(`Skills updated. .xqa already exists, skipping project init.
@@ -71868,12 +72058,12 @@ function runInitCommand() {
71868
72058
  return;
71869
72059
  }
71870
72060
  (0, import_node_fs6.mkdirSync)(xqaDirectory);
71871
- (0, import_node_fs6.writeFileSync)(import_node_path12.default.join(xqaDirectory, ".gitignore"), GITIGNORE_CONTENT);
71872
- (0, import_node_fs6.writeFileSync)(import_node_path12.default.join(xqaDirectory, "app.md"), APP_TEMPLATE);
71873
- (0, import_node_fs6.writeFileSync)(import_node_path12.default.join(xqaDirectory, "explore.md"), EXPLORE_TEMPLATE);
72061
+ (0, import_node_fs6.writeFileSync)(import_node_path13.default.join(xqaDirectory, ".gitignore"), GITIGNORE_CONTENT);
72062
+ (0, import_node_fs6.writeFileSync)(import_node_path13.default.join(xqaDirectory, "app.md"), APP_TEMPLATE);
72063
+ (0, import_node_fs6.writeFileSync)(import_node_path13.default.join(xqaDirectory, "explore.md"), EXPLORE_TEMPLATE);
71874
72064
  for (const subdir of ["designs", "specs", "suites"]) {
71875
- (0, import_node_fs6.mkdirSync)(import_node_path12.default.join(xqaDirectory, subdir));
71876
- (0, import_node_fs6.writeFileSync)(import_node_path12.default.join(xqaDirectory, subdir, ".gitkeep"), "");
72065
+ (0, import_node_fs6.mkdirSync)(import_node_path13.default.join(xqaDirectory, subdir));
72066
+ (0, import_node_fs6.writeFileSync)(import_node_path13.default.join(xqaDirectory, subdir, ".gitkeep"), "");
71877
72067
  }
71878
72068
  process.stdout.write(`Initialized xqa project: ${xqaDirectory}
71879
72069
  `);
@@ -71885,8 +72075,8 @@ function runInitCommand() {
71885
72075
 
71886
72076
  // src/commands/review-command.ts
71887
72077
  var import_node_fs7 = require("node:fs");
71888
- var import_node_path14 = __toESM(require("node:path"), 1);
71889
- var import_neverthrow41 = __toESM(require_index_cjs(), 1);
72078
+ var import_node_path15 = __toESM(require("node:path"), 1);
72079
+ var import_neverthrow43 = __toESM(require_index_cjs(), 1);
71890
72080
 
71891
72081
  // ../../node_modules/.pnpm/@inquirer+core@10.3.2_@types+node@22.19.15/node_modules/@inquirer/core/dist/esm/lib/key.js
71892
72082
  var isUpKey = (key, keybindings = []) => (
@@ -73224,7 +73414,7 @@ var esm_default2 = createPrompt((config3, done) => {
73224
73414
  var import_chardet = __toESM(require_lib2(), 1);
73225
73415
  var import_child_process3 = require("child_process");
73226
73416
  var import_fs3 = require("fs");
73227
- var import_node_path13 = __toESM(require("node:path"), 1);
73417
+ var import_node_path14 = __toESM(require("node:path"), 1);
73228
73418
  var import_node_os3 = __toESM(require("node:os"), 1);
73229
73419
  var import_node_crypto2 = require("node:crypto");
73230
73420
  var import_iconv_lite = __toESM(require_lib3(), 1);
@@ -73268,9 +73458,9 @@ var RemoveFileError = class extends Error {
73268
73458
  // ../../node_modules/.pnpm/@inquirer+external-editor@1.0.3_@types+node@22.19.15/node_modules/@inquirer/external-editor/dist/esm/index.js
73269
73459
  function editAsync(text = "", callback, fileOptions) {
73270
73460
  const editor = new ExternalEditor(text, fileOptions);
73271
- editor.runAsync((err25, result) => {
73272
- if (err25) {
73273
- setImmediate(callback, err25, void 0);
73461
+ editor.runAsync((err26, result) => {
73462
+ if (err26) {
73463
+ setImmediate(callback, err26, void 0);
73274
73464
  } else {
73275
73465
  try {
73276
73466
  editor.cleanup();
@@ -73360,8 +73550,8 @@ var ExternalEditor = class {
73360
73550
  const prefix = sanitizeAffix(this.fileOptions.prefix);
73361
73551
  const postfix = sanitizeAffix(this.fileOptions.postfix);
73362
73552
  const filename = `${prefix}${id}${postfix}`;
73363
- const candidate = import_node_path13.default.resolve(baseDir, filename);
73364
- const baseResolved = import_node_path13.default.resolve(baseDir) + import_node_path13.default.sep;
73553
+ const candidate = import_node_path14.default.resolve(baseDir, filename);
73554
+ const baseResolved = import_node_path14.default.resolve(baseDir) + import_node_path14.default.sep;
73365
73555
  if (!candidate.startsWith(baseResolved)) {
73366
73556
  throw new Error("Resolved temporary file escaped the base directory");
73367
73557
  }
@@ -74291,11 +74481,10 @@ var esm_default11 = createPrompt((config3, done) => {
74291
74481
  });
74292
74482
 
74293
74483
  // src/review-session.ts
74294
- var import_neverthrow40 = __toESM(require_index_cjs(), 1);
74295
- var CONFIDENCE_PERCENT = 100;
74484
+ var import_neverthrow42 = __toESM(require_index_cjs(), 1);
74296
74485
  var FLOW_COL_WIDTH = 35;
74297
74486
  var TRIGGER_COL_WIDTH = 16;
74298
- var CONFIDENCE_COL_WIDTH = 5;
74487
+ var CONFIDENCE_COL_WIDTH = 6;
74299
74488
  var COL_SEPARATOR_WIDTH = 6;
74300
74489
  var FIXED_COLS_WIDTH = FLOW_COL_WIDTH + TRIGGER_COL_WIDTH + CONFIDENCE_COL_WIDTH + COL_SEPARATOR_WIDTH;
74301
74490
  var DEFAULT_TERMINAL_WIDTH = 80;
@@ -74362,7 +74551,7 @@ function applyDismissal(dismissal, state) {
74362
74551
  state.stagedKeys.add(key);
74363
74552
  }
74364
74553
  async function selectFinding(findings, state) {
74365
- const activeSorted = findings.filter((finding) => !state.dismissedKeys.has(dismissalKey(finding))).toSorted((fa, fb2) => fa.confidence - fb2.confidence);
74554
+ const activeSorted = findings.filter((finding) => !state.dismissedKeys.has(dismissalKey(finding))).toSorted((fa, fb2) => compareConfidence(fa.confidence, fb2.confidence));
74366
74555
  const reconsidered = activeSorted.filter(
74367
74556
  (finding) => state.undoneKeys.has(dismissalKey(finding))
74368
74557
  );
@@ -74401,9 +74590,7 @@ function buildChoiceName(finding, state) {
74401
74590
  const maxDescWidth = terminalWidth - CURSOR_MARGIN - FIXED_COLS_WIDTH - suffix.length;
74402
74591
  const flow = source_default.bold(finding.flow.padEnd(FLOW_COL_WIDTH));
74403
74592
  const triggerType = source_default.dim(finding.triggerType.padEnd(TRIGGER_COL_WIDTH));
74404
- const confidence = `${String(Math.round(finding.confidence * CONFIDENCE_PERCENT))}%`.padEnd(
74405
- CONFIDENCE_COL_WIDTH
74406
- );
74593
+ const confidence = finding.confidence.padEnd(CONFIDENCE_COL_WIDTH);
74407
74594
  const rawDescription = finding.description.split(".")[0] ?? finding.description;
74408
74595
  const description = rawDescription.length > maxDescWidth ? `${rawDescription.slice(0, maxDescWidth - ELLIPSIS_LENGTH)}...` : rawDescription;
74409
74596
  return `${flow} ${triggerType} ${confidence} ${description}${suffix ? source_default.dim(suffix) : ""}`;
@@ -74417,10 +74604,8 @@ function printDetail(finding) {
74417
74604
  process.stdout.write(` ${String(index + 1)}. ${step}
74418
74605
  `);
74419
74606
  }
74420
- process.stdout.write(
74421
- `${source_default.bold("\nConfidence: ")}${String(Math.round(finding.confidence * CONFIDENCE_PERCENT))}%
74422
- `
74423
- );
74607
+ process.stdout.write(`${source_default.bold("\nConfidence: ")}${finding.confidence}
74608
+ `);
74424
74609
  if (finding.screenshots.length > 0) {
74425
74610
  process.stdout.write(source_default.bold("\nScreenshots:\n"));
74426
74611
  for (const screenshot of finding.screenshots) {
@@ -74444,15 +74629,15 @@ async function runInteractiveLoop(findings, existing) {
74444
74629
  }
74445
74630
  return { staged: state.staged, undoneKeys: state.undoneKeys };
74446
74631
  }
74447
- var safeRunInteractiveLoop = (0, import_neverthrow40.fromAsyncThrowable)(
74632
+ var safeRunInteractiveLoop = (0, import_neverthrow42.fromAsyncThrowable)(
74448
74633
  runInteractiveLoop,
74449
74634
  (error48) => error48 instanceof Error && error48.name === "ExitPromptError" ? "exit-prompt" : "unexpected"
74450
74635
  );
74451
74636
 
74452
74637
  // src/commands/review-command.ts
74453
- var safeReadFile3 = (0, import_neverthrow41.fromThrowable)((filePath) => (0, import_node_fs7.readFileSync)(filePath, "utf8"));
74454
- var safeParseJson3 = (0, import_neverthrow41.fromThrowable)(JSON.parse);
74455
- var safeWrite = (0, import_neverthrow41.fromThrowable)((filePath, content) => {
74638
+ var safeReadFile3 = (0, import_neverthrow43.fromThrowable)((filePath) => (0, import_node_fs7.readFileSync)(filePath, "utf8"));
74639
+ var safeParseJson3 = (0, import_neverthrow43.fromThrowable)(JSON.parse);
74640
+ var safeWrite = (0, import_neverthrow43.fromThrowable)((filePath, content) => {
74456
74641
  (0, import_node_fs7.writeFileSync)(filePath, content);
74457
74642
  });
74458
74643
  function readLastPath(xqaDirectory) {
@@ -74469,13 +74654,13 @@ function isPipelineOutput(data) {
74469
74654
  function readFindings(filePath) {
74470
74655
  const readResult = safeReadFile3(filePath);
74471
74656
  if (readResult.isErr()) {
74472
- return (0, import_neverthrow41.err)("not-found");
74657
+ return (0, import_neverthrow43.err)("not-found");
74473
74658
  }
74474
74659
  return safeParseJson3(readResult.value).mapErr(() => "invalid").andThen((data) => {
74475
74660
  if (!isPipelineOutput(data)) {
74476
- return (0, import_neverthrow41.err)("invalid");
74661
+ return (0, import_neverthrow43.err)("invalid");
74477
74662
  }
74478
- return (0, import_neverthrow41.ok)(data);
74663
+ return (0, import_neverthrow43.ok)(data);
74479
74664
  });
74480
74665
  }
74481
74666
  function loadExistingDismissals(filePath) {
@@ -74548,7 +74733,7 @@ function resolveAndReadFindings(findingsPath, xqaDirectory) {
74548
74733
  "No findings path provided and no last path found. Run: xqa review <findings-path>\n"
74549
74734
  );
74550
74735
  process.exit(1);
74551
- return (0, import_neverthrow41.err)();
74736
+ return (0, import_neverthrow43.err)();
74552
74737
  }
74553
74738
  const resolvedPath = resolvedPathResult.value;
74554
74739
  const findingsResult = readFindings(resolvedPath);
@@ -74561,9 +74746,9 @@ function resolveAndReadFindings(findingsPath, xqaDirectory) {
74561
74746
  `);
74562
74747
  }
74563
74748
  process.exit(1);
74564
- return (0, import_neverthrow41.err)();
74749
+ return (0, import_neverthrow43.err)();
74565
74750
  }
74566
- return (0, import_neverthrow41.ok)({ resolvedPath, output: findingsResult.value });
74751
+ return (0, import_neverthrow43.ok)({ resolvedPath, output: findingsResult.value });
74567
74752
  }
74568
74753
  async function runReviewLoop({
74569
74754
  findings,
@@ -74591,7 +74776,7 @@ async function executeReview({
74591
74776
  return;
74592
74777
  }
74593
74778
  const dismissalsFilePath = dismissalsPath(
74594
- import_node_path14.default.dirname(xqaDirectory),
74779
+ import_node_path15.default.dirname(xqaDirectory),
74595
74780
  process.env.QA_DISMISSALS_PATH
74596
74781
  );
74597
74782
  await runReviewLoop({
@@ -74614,16 +74799,16 @@ async function runReviewCommand(findingsPath, xqaDirectory) {
74614
74799
  }
74615
74800
 
74616
74801
  // src/commands/spec-command.ts
74617
- var import_node_path17 = __toESM(require("node:path"), 1);
74802
+ var import_node_path18 = __toESM(require("node:path"), 1);
74618
74803
 
74619
74804
  // src/spec-slug.ts
74620
- var import_node_path15 = __toESM(require("node:path"), 1);
74805
+ var import_node_path16 = __toESM(require("node:path"), 1);
74621
74806
  var SPECS_DIR = "specs";
74622
74807
  function stripExtensions(filename) {
74623
74808
  return filename.replace(/\.test\.md$/, "").replace(/\.[^.]+$/, "");
74624
74809
  }
74625
74810
  function deriveSpecSlug(specFilePath) {
74626
- const parts = specFilePath.split(import_node_path15.default.sep);
74811
+ const parts = specFilePath.split(import_node_path16.default.sep);
74627
74812
  const specsIndex = parts.lastIndexOf(SPECS_DIR);
74628
74813
  if (specsIndex !== -1) {
74629
74814
  const relativeParts = parts.slice(specsIndex + 1);
@@ -74631,17 +74816,17 @@ function deriveSpecSlug(specFilePath) {
74631
74816
  relativeParts[relativeParts.length - 1] = stripExtensions(last);
74632
74817
  return relativeParts.join("__");
74633
74818
  }
74634
- return stripExtensions(import_node_path15.default.basename(specFilePath));
74819
+ return stripExtensions(import_node_path16.default.basename(specFilePath));
74635
74820
  }
74636
74821
 
74637
74822
  // src/commands/spec-resolver.ts
74638
74823
  var import_node_fs8 = require("node:fs");
74639
- var import_node_path16 = __toESM(require("node:path"), 1);
74640
- var import_neverthrow43 = __toESM(require_index_cjs(), 1);
74824
+ var import_node_path17 = __toESM(require("node:path"), 1);
74825
+ var import_neverthrow45 = __toESM(require_index_cjs(), 1);
74641
74826
 
74642
74827
  // src/spec-frontmatter.ts
74643
74828
  var import_gray_matter = __toESM(require_gray_matter(), 1);
74644
- var import_neverthrow42 = __toESM(require_index_cjs(), 1);
74829
+ var import_neverthrow44 = __toESM(require_index_cjs(), 1);
74645
74830
 
74646
74831
  // ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/external.js
74647
74832
  var external_exports2 = {};
@@ -75381,8 +75566,8 @@ var ZodType2 = class {
75381
75566
  } : {
75382
75567
  issues: ctx.common.issues
75383
75568
  };
75384
- } catch (err25) {
75385
- if (err25?.message?.toLowerCase()?.includes("encountered")) {
75569
+ } catch (err26) {
75570
+ if (err26?.message?.toLowerCase()?.includes("encountered")) {
75386
75571
  this["~standard"].async = true;
75387
75572
  }
75388
75573
  ctx.common = {
@@ -78689,45 +78874,45 @@ var frontmatterSchema = external_exports2.object({
78689
78874
  feature: external_exports2.string().min(1),
78690
78875
  timeout: external_exports2.number().int().positive().optional()
78691
78876
  });
78692
- var safeParseMatter = (0, import_neverthrow42.fromThrowable)(
78877
+ var safeParseMatter = (0, import_neverthrow44.fromThrowable)(
78693
78878
  import_gray_matter.default,
78694
78879
  (cause) => ({ type: "SPEC_FRONTMATTER_INVALID", cause })
78695
78880
  );
78696
78881
  function validate(data) {
78697
78882
  const parsed = frontmatterSchema.safeParse(data);
78698
78883
  if (!parsed.success) {
78699
- return (0, import_neverthrow42.err)({ type: "SPEC_FRONTMATTER_INVALID", cause: parsed.error });
78884
+ return (0, import_neverthrow44.err)({ type: "SPEC_FRONTMATTER_INVALID", cause: parsed.error });
78700
78885
  }
78701
78886
  const { feature, timeout } = parsed.data;
78702
78887
  if (timeout === void 0) {
78703
- return (0, import_neverthrow42.ok)({ feature });
78888
+ return (0, import_neverthrow44.ok)({ feature });
78704
78889
  }
78705
- return (0, import_neverthrow42.ok)({ feature, timeoutSeconds: timeout });
78890
+ return (0, import_neverthrow44.ok)({ feature, timeoutSeconds: timeout });
78706
78891
  }
78707
78892
  function parseSpecFrontmatter(raw) {
78708
78893
  return safeParseMatter(raw).andThen((parsed) => validate(parsed.data));
78709
78894
  }
78710
78895
 
78711
78896
  // src/commands/spec-resolver.ts
78712
- var safeReadFile4 = (0, import_neverthrow43.fromThrowable)((filePath) => (0, import_node_fs8.readFileSync)(filePath, "utf8"));
78713
- var safeReaddir = (0, import_neverthrow43.fromThrowable)(
78897
+ var safeReadFile4 = (0, import_neverthrow45.fromThrowable)((filePath) => (0, import_node_fs8.readFileSync)(filePath, "utf8"));
78898
+ var safeReaddir = (0, import_neverthrow45.fromThrowable)(
78714
78899
  (directory) => (0, import_node_fs8.readdirSync)(directory, { recursive: true, encoding: "utf8" })
78715
78900
  );
78716
78901
  var CANCEL = "xqa:cancel";
78717
- var safeSelect = import_neverthrow43.ResultAsync.fromThrowable(
78902
+ var safeSelect = import_neverthrow45.ResultAsync.fromThrowable(
78718
78903
  esm_default11,
78719
78904
  (error48) => error48 instanceof Error && error48.name === "ExitPromptError" ? "cancelled" : "failed"
78720
78905
  );
78721
78906
  function findSpecFiles(xqaDirectory) {
78722
- const specsDirectory = import_node_path16.default.join(xqaDirectory, "specs");
78723
- return safeReaddir(specsDirectory).unwrapOr([]).filter((file2) => file2.endsWith(".test.md")).map((file2) => import_node_path16.default.join(specsDirectory, file2));
78907
+ const specsDirectory = import_node_path17.default.join(xqaDirectory, "specs");
78908
+ return safeReaddir(specsDirectory).unwrapOr([]).filter((file2) => file2.endsWith(".test.md")).map((file2) => import_node_path17.default.join(specsDirectory, file2));
78724
78909
  }
78725
78910
  async function promptForSpec(specFiles, xqaDirectory) {
78726
78911
  const result = await safeSelect({
78727
78912
  message: "Select a spec",
78728
78913
  choices: [
78729
78914
  ...specFiles.map((specFile) => ({
78730
- name: import_node_path16.default.relative(xqaDirectory, specFile),
78915
+ name: import_node_path17.default.relative(xqaDirectory, specFile),
78731
78916
  value: specFile
78732
78917
  })),
78733
78918
  new Separator(),
@@ -78786,10 +78971,10 @@ function buildSpecExplorer(input, context) {
78786
78971
  }
78787
78972
  function buildPipelineConfig2({ input, context, onEvent }) {
78788
78973
  return {
78789
- outputDir: import_node_path17.default.join(context.xqaDirectory, "output", context.slug),
78974
+ outputDir: import_node_path18.default.join(context.xqaDirectory, "output", context.slug),
78790
78975
  signal: input.signal,
78791
78976
  onEvent,
78792
- inspector: { designsDirectory: import_node_path17.default.join(context.xqaDirectory, "designs") },
78977
+ inspector: { designsDirectory: import_node_path18.default.join(context.xqaDirectory, "designs") },
78793
78978
  explorer: buildSpecExplorer(input, context)
78794
78979
  };
78795
78980
  }
@@ -78833,7 +79018,7 @@ async function executeSpec(input, context) {
78833
79018
  const identity = {
78834
79019
  display: createSoloDisplay(input.verbose),
78835
79020
  itemId: "spec",
78836
- itemName: import_node_path17.default.basename(context.absolutePath, ".test.md"),
79021
+ itemName: import_node_path18.default.basename(context.absolutePath, ".test.md"),
78837
79022
  simulatorUdid: ""
78838
79023
  };
78839
79024
  const startedAt = Date.now();
@@ -78844,7 +79029,7 @@ async function executeSpec(input, context) {
78844
79029
  };
78845
79030
  const onEvent = debugLogger.wrapAgentHandler(baseHandler);
78846
79031
  const { onSuccess, onError } = handleSpecResult({ identity, startedAt }, context);
78847
- const result = await runPipeline2(buildPipelineConfig2({ input, context, onEvent }));
79032
+ const result = await runPipeline3(buildPipelineConfig2({ input, context, onEvent }));
78848
79033
  result.match(onSuccess, onError);
78849
79034
  }
78850
79035
  function handleAppContextError(error48) {
@@ -78874,7 +79059,7 @@ async function resolveSpecContext(input, options2) {
78874
79059
  if (resolvedSpecFile === void 0) {
78875
79060
  return;
78876
79061
  }
78877
- const absolutePath = import_node_path17.default.resolve(resolvedSpecFile);
79062
+ const absolutePath = import_node_path18.default.resolve(resolvedSpecFile);
78878
79063
  const frontmatter = readAndParseSpec(absolutePath);
78879
79064
  if (frontmatter === void 0) {
78880
79065
  return;
@@ -78895,7 +79080,7 @@ async function runSpecCommand(input, options2) {
78895
79080
  }
78896
79081
 
78897
79082
  // ../../agents/triager/dist/index.js
78898
- var import_neverthrow44 = __toESM(require_index_cjs(), 1);
79083
+ var import_neverthrow46 = __toESM(require_index_cjs(), 1);
78899
79084
 
78900
79085
  // ../../node_modules/.pnpm/@anthropic-ai+sdk@0.87.0_zod@3.25.76/node_modules/@anthropic-ai/sdk/internal/tslib.mjs
78901
79086
  function __classPrivateFieldSet2(receiver, state, value, kind, f6) {
@@ -78928,34 +79113,34 @@ var uuid43 = function() {
78928
79113
  };
78929
79114
 
78930
79115
  // ../../node_modules/.pnpm/@anthropic-ai+sdk@0.87.0_zod@3.25.76/node_modules/@anthropic-ai/sdk/internal/errors.mjs
78931
- function isAbortError2(err25) {
78932
- return typeof err25 === "object" && err25 !== null && // Spec-compliant fetch implementations
78933
- ("name" in err25 && err25.name === "AbortError" || // Expo fetch
78934
- "message" in err25 && String(err25.message).includes("FetchRequestCanceledException"));
78935
- }
78936
- var castToError2 = (err25) => {
78937
- if (err25 instanceof Error)
78938
- return err25;
78939
- if (typeof err25 === "object" && err25 !== null) {
79116
+ function isAbortError2(err26) {
79117
+ return typeof err26 === "object" && err26 !== null && // Spec-compliant fetch implementations
79118
+ ("name" in err26 && err26.name === "AbortError" || // Expo fetch
79119
+ "message" in err26 && String(err26.message).includes("FetchRequestCanceledException"));
79120
+ }
79121
+ var castToError2 = (err26) => {
79122
+ if (err26 instanceof Error)
79123
+ return err26;
79124
+ if (typeof err26 === "object" && err26 !== null) {
78940
79125
  try {
78941
- if (Object.prototype.toString.call(err25) === "[object Error]") {
78942
- const error48 = new Error(err25.message, err25.cause ? { cause: err25.cause } : {});
78943
- if (err25.stack)
78944
- error48.stack = err25.stack;
78945
- if (err25.cause && !error48.cause)
78946
- error48.cause = err25.cause;
78947
- if (err25.name)
78948
- error48.name = err25.name;
79126
+ if (Object.prototype.toString.call(err26) === "[object Error]") {
79127
+ const error48 = new Error(err26.message, err26.cause ? { cause: err26.cause } : {});
79128
+ if (err26.stack)
79129
+ error48.stack = err26.stack;
79130
+ if (err26.cause && !error48.cause)
79131
+ error48.cause = err26.cause;
79132
+ if (err26.name)
79133
+ error48.name = err26.name;
78949
79134
  return error48;
78950
79135
  }
78951
79136
  } catch {
78952
79137
  }
78953
79138
  try {
78954
- return new Error(JSON.stringify(err25));
79139
+ return new Error(JSON.stringify(err26));
78955
79140
  } catch {
78956
79141
  }
78957
79142
  }
78958
- return new Error(err25);
79143
+ return new Error(err26);
78959
79144
  };
78960
79145
 
78961
79146
  // ../../node_modules/.pnpm/@anthropic-ai+sdk@0.87.0_zod@3.25.76/node_modules/@anthropic-ai/sdk/core/error.mjs
@@ -79085,7 +79270,7 @@ var validatePositiveInteger2 = (name, n3) => {
79085
79270
  var safeJSON2 = (text) => {
79086
79271
  try {
79087
79272
  return JSON.parse(text);
79088
- } catch (err25) {
79273
+ } catch (err26) {
79089
79274
  return void 0;
79090
79275
  }
79091
79276
  };
@@ -79649,8 +79834,8 @@ var Stream2 = class _Stream {
79649
79834
  return ctrl.close();
79650
79835
  const bytes = encodeUTF82(JSON.stringify(value) + "\n");
79651
79836
  ctrl.enqueue(bytes);
79652
- } catch (err25) {
79653
- ctrl.error(err25);
79837
+ } catch (err26) {
79838
+ ctrl.error(err26);
79654
79839
  }
79655
79840
  },
79656
79841
  async cancel() {
@@ -81557,8 +81742,8 @@ var BetaMessageStream2 = class _BetaMessageStream {
81557
81742
  if (jsonBuf) {
81558
81743
  try {
81559
81744
  newContent.input = partialParse2(jsonBuf);
81560
- } catch (err25) {
81561
- const error48 = new AnthropicError2(`Unable to parse tool parameter JSON from model. Please retry your request or adjust your prompt. Error: ${err25}. JSON: ${jsonBuf}`);
81745
+ } catch (err26) {
81746
+ const error48 = new AnthropicError2(`Unable to parse tool parameter JSON from model. Please retry your request or adjust your prompt. Error: ${err26}. JSON: ${jsonBuf}`);
81562
81747
  __classPrivateFieldGet2(this, _BetaMessageStream_handleError2, "f").call(this, error48);
81563
81748
  }
81564
81749
  }
@@ -81620,17 +81805,17 @@ var BetaMessageStream2 = class _BetaMessageStream {
81620
81805
  }
81621
81806
  readQueue.length = 0;
81622
81807
  });
81623
- this.on("abort", (err25) => {
81808
+ this.on("abort", (err26) => {
81624
81809
  done = true;
81625
81810
  for (const reader of readQueue) {
81626
- reader.reject(err25);
81811
+ reader.reject(err26);
81627
81812
  }
81628
81813
  readQueue.length = 0;
81629
81814
  });
81630
- this.on("error", (err25) => {
81815
+ this.on("error", (err26) => {
81631
81816
  done = true;
81632
81817
  for (const reader of readQueue) {
81633
- reader.reject(err25);
81818
+ reader.reject(err26);
81634
81819
  }
81635
81820
  readQueue.length = 0;
81636
81821
  });
@@ -83873,17 +84058,17 @@ var MessageStream2 = class _MessageStream {
83873
84058
  }
83874
84059
  readQueue.length = 0;
83875
84060
  });
83876
- this.on("abort", (err25) => {
84061
+ this.on("abort", (err26) => {
83877
84062
  done = true;
83878
84063
  for (const reader of readQueue) {
83879
- reader.reject(err25);
84064
+ reader.reject(err26);
83880
84065
  }
83881
84066
  readQueue.length = 0;
83882
84067
  });
83883
- this.on("error", (err25) => {
84068
+ this.on("error", (err26) => {
83884
84069
  done = true;
83885
84070
  for (const reader of readQueue) {
83886
- reader.reject(err25);
84071
+ reader.reject(err26);
83887
84072
  }
83888
84073
  readQueue.length = 0;
83889
84074
  });
@@ -84463,7 +84648,7 @@ var BaseAnthropic2 = class {
84463
84648
  }
84464
84649
  const retryMessage = shouldRetry ? `error; no more retries left` : `error; not retryable`;
84465
84650
  loggerFor2(this).info(`${responseInfo} - ${retryMessage}`);
84466
- const errText = await response.text().catch((err26) => castToError2(err26).message);
84651
+ const errText = await response.text().catch((err27) => castToError2(err27).message);
84467
84652
  const errJSON = safeJSON2(errText);
84468
84653
  const errMessage = errJSON ? void 0 : errText;
84469
84654
  loggerFor2(this).debug(`[${requestLogID}] response error (${retryMessage})`, formatRequestDetails2({
@@ -84474,8 +84659,8 @@ var BaseAnthropic2 = class {
84474
84659
  message: errMessage,
84475
84660
  durationMs: Date.now() - startTime
84476
84661
  }));
84477
- const err25 = this.makeStatusError(response.status, errJSON, errMessage, response.headers);
84478
- throw err25;
84662
+ const err26 = this.makeStatusError(response.status, errJSON, errMessage, response.headers);
84663
+ throw err26;
84479
84664
  }
84480
84665
  loggerFor2(this).info(responseInfo);
84481
84666
  loggerFor2(this).debug(`[${requestLogID}] response start`, formatRequestDetails2({
@@ -84686,7 +84871,7 @@ Anthropic2.Models = Models4;
84686
84871
  Anthropic2.Beta = Beta2;
84687
84872
 
84688
84873
  // ../../agents/triager/dist/index.js
84689
- var import_neverthrow45 = __toESM(require_index_cjs(), 1);
84874
+ var import_neverthrow47 = __toESM(require_index_cjs(), 1);
84690
84875
 
84691
84876
  // ../../node_modules/.pnpm/balanced-match@4.0.4/node_modules/balanced-match/dist/esm/index.js
84692
84877
  var balanced = (a3, b, str3) => {
@@ -86492,16 +86677,16 @@ minimatch.unescape = unescape2;
86492
86677
 
86493
86678
  // ../../agents/triager/dist/index.js
86494
86679
  var MAX_TOKENS3 = 1024;
86680
+ var THINKING_BUDGET_TOKENS = 1024;
86495
86681
  var TEMPERATURE3 = 0;
86496
86682
  var TOOL_NAME = "select_test_groups";
86683
+ var pickSchema = external_exports2.object({
86684
+ groupId: external_exports2.string(),
86685
+ reason: external_exports2.string(),
86686
+ confidence: external_exports2.enum(["HIGH", "MEDIUM", "LOW"])
86687
+ });
86497
86688
  var toolInputSchema = external_exports2.object({
86498
- picks: external_exports2.array(
86499
- external_exports2.object({
86500
- groupId: external_exports2.string(),
86501
- score: external_exports2.number(),
86502
- reason: external_exports2.string()
86503
- })
86504
- )
86689
+ picks: external_exports2.array(pickSchema)
86505
86690
  });
86506
86691
  var TOOL_DEFINITION = {
86507
86692
  name: TOOL_NAME,
@@ -86515,16 +86700,17 @@ var TOOL_DEFINITION = {
86515
86700
  type: "object",
86516
86701
  properties: {
86517
86702
  groupId: { type: "string" },
86518
- score: { type: "number" },
86519
- reason: { type: "string" }
86703
+ reason: { type: "string" },
86704
+ confidence: { type: "string", enum: ["HIGH", "MEDIUM", "LOW"] }
86520
86705
  },
86521
- required: ["groupId", "score", "reason"]
86706
+ required: ["groupId", "reason", "confidence"]
86522
86707
  }
86523
86708
  }
86524
86709
  },
86525
86710
  required: ["picks"]
86526
86711
  }
86527
86712
  };
86713
+ var GRADER_SYSTEM_PROMPT = "Act as a senior QA auditor reviewing another engineer's test selection. For each pick below, confirm HIGH, confirm MEDIUM, or downgrade to LOW. Require citing the file path driving your verdict. Respond via the select_test_groups tool.";
86528
86714
  function findToolUseInput(response) {
86529
86715
  const block = response.content.find((entry) => entry.type === "tool_use");
86530
86716
  if (block?.type !== "tool_use") {
@@ -86538,63 +86724,79 @@ function serialiseResponse(response) {
86538
86724
  function parseToolResponse(response) {
86539
86725
  const input = findToolUseInput(response);
86540
86726
  if (input === void 0) {
86541
- return (0, import_neverthrow45.err)({ type: "AI_INVALID_RESPONSE", raw: serialiseResponse(response) });
86727
+ return (0, import_neverthrow47.err)({ type: "AI_INVALID_RESPONSE", raw: serialiseResponse(response) });
86542
86728
  }
86543
86729
  const parsed = toolInputSchema.safeParse(input);
86544
86730
  if (!parsed.success) {
86545
- return (0, import_neverthrow45.err)({ type: "AI_INVALID_RESPONSE", raw: JSON.stringify(input) });
86731
+ return (0, import_neverthrow47.err)({ type: "AI_INVALID_RESPONSE", raw: JSON.stringify(input) });
86546
86732
  }
86547
- return (0, import_neverthrow45.ok)(parsed.data.picks);
86733
+ return (0, import_neverthrow47.ok)(parsed.data.picks);
86734
+ }
86735
+ function filterKnownGroupIds(picks, validGroupIds) {
86736
+ const validIds = new Set(validGroupIds);
86737
+ return picks.filter((pick2) => validIds.has(pick2.groupId));
86548
86738
  }
86549
86739
  async function fetchSelection(options2) {
86550
- const { anthropic, prompt, model } = options2;
86551
- return anthropic.messages.create({
86740
+ const { anthropic, prompt, model, systemPrompt } = options2;
86741
+ const base = {
86552
86742
  model,
86553
86743
  max_tokens: MAX_TOKENS3,
86554
86744
  temperature: TEMPERATURE3,
86745
+ thinking: { type: "enabled", budget_tokens: THINKING_BUDGET_TOKENS },
86555
86746
  tools: [TOOL_DEFINITION],
86556
86747
  tool_choice: { type: "tool", name: TOOL_NAME },
86557
86748
  messages: [{ role: "user", content: prompt }]
86558
- });
86749
+ };
86750
+ if (systemPrompt !== void 0) {
86751
+ return anthropic.messages.create({ ...base, system: systemPrompt });
86752
+ }
86753
+ return anthropic.messages.create(base);
86754
+ }
86755
+ function buildGraderPrompt(originalPicks, basePrompt) {
86756
+ const picksText = originalPicks.map((pick2) => `- groupId: ${pick2.groupId}
86757
+ reason: ${pick2.reason}`).join("\n");
86758
+ return `${basePrompt}
86759
+
86760
+ ## Picks Under Review
86761
+
86762
+ ${picksText}`;
86559
86763
  }
86560
86764
  function selectGroups(options2) {
86561
86765
  const anthropic = new Anthropic2({ apiKey: options2.apiKey });
86562
- return (0, import_neverthrow45.fromAsyncThrowable)(
86766
+ return (0, import_neverthrow47.fromAsyncThrowable)(
86563
86767
  fetchSelection,
86564
86768
  (cause) => ({ type: "AI_CALL_FAILED", cause })
86565
- )({ anthropic, prompt: options2.prompt, model: options2.model }).andThen(parseToolResponse);
86769
+ )({ anthropic, prompt: options2.prompt, model: options2.model }).andThen(parseToolResponse).map((picks) => filterKnownGroupIds(picks, options2.validGroupIds));
86566
86770
  }
86567
- var HIGH_CONFIDENCE_THRESHOLD = 0.5;
86568
- function resolveConfidence(selected) {
86569
- if (selected.some((pick2) => pick2.score >= HIGH_CONFIDENCE_THRESHOLD)) {
86771
+ function graderSelectGroups(options2) {
86772
+ const anthropic = new Anthropic2({ apiKey: options2.apiKey });
86773
+ const graderPrompt = buildGraderPrompt(options2.originalPicks, options2.prompt);
86774
+ return (0, import_neverthrow47.fromAsyncThrowable)(
86775
+ fetchSelection,
86776
+ (cause) => ({ type: "AI_CALL_FAILED", cause })
86777
+ )({ anthropic, prompt: graderPrompt, model: options2.model, systemPrompt: GRADER_SYSTEM_PROMPT }).andThen(parseToolResponse).map((picks) => filterKnownGroupIds(picks, options2.validGroupIds));
86778
+ }
86779
+ function resolveConfidence2(selected) {
86780
+ if (selected.some((pick2) => pick2.confidence === "HIGH")) {
86570
86781
  return "high";
86571
86782
  }
86572
- if (selected.length > 0) {
86783
+ if (selected.some((pick2) => pick2.confidence === "MEDIUM")) {
86573
86784
  return "medium";
86574
86785
  }
86575
86786
  return "low";
86576
86787
  }
86577
- function buildDecision(picks, threshold) {
86578
- const selected = picks.filter((pick2) => pick2.score >= threshold);
86579
- const skipped = picks.filter((pick2) => pick2.score < threshold);
86788
+ function buildDecision(picks) {
86789
+ const selected = picks.filter((pick2) => pick2.confidence !== "LOW");
86790
+ const skipped = picks.filter((pick2) => pick2.confidence === "LOW");
86580
86791
  return {
86581
86792
  picks: selected,
86582
86793
  skipped,
86583
- confidence: resolveConfidence(selected)
86794
+ confidence: resolveConfidence2(selected)
86584
86795
  };
86585
86796
  }
86586
- var MIN_SCORE = 0;
86587
- var MAX_SCORE = 1;
86797
+ var HIGH_MATCH_RATIO = 0.7;
86798
+ var MEDIUM_MATCH_RATIO = 0.3;
86588
86799
  var REASON_SAMPLE_LIMIT = 3;
86589
- function clampScore(value) {
86590
- if (value < MIN_SCORE) {
86591
- return MIN_SCORE;
86592
- }
86593
- if (value > MAX_SCORE) {
86594
- return MAX_SCORE;
86595
- }
86596
- return value;
86597
- }
86598
86800
  function matchesAnyGlob(path27, patterns) {
86599
86801
  return patterns.some((pattern) => minimatch(path27, pattern));
86600
86802
  }
@@ -86605,6 +86807,19 @@ function formatReason(parts) {
86605
86807
  const sample = parts.paths.slice(0, REASON_SAMPLE_LIMIT).join(", ");
86606
86808
  return `matched ${String(parts.matches)}/${String(parts.total)} files: ${sample}`;
86607
86809
  }
86810
+ function resolvePickConfidence(matches, total) {
86811
+ if (total === 0 || matches === 0) {
86812
+ return void 0;
86813
+ }
86814
+ const ratio = matches / total;
86815
+ if (ratio >= HIGH_MATCH_RATIO) {
86816
+ return "HIGH";
86817
+ }
86818
+ if (ratio >= MEDIUM_MATCH_RATIO) {
86819
+ return "MEDIUM";
86820
+ }
86821
+ return "LOW";
86822
+ }
86608
86823
  function scoreGroup(diff, group) {
86609
86824
  if (!group.covers || group.covers.length === 0) {
86610
86825
  return void 0;
@@ -86612,28 +86827,62 @@ function scoreGroup(diff, group) {
86612
86827
  const total = diff.files.length;
86613
86828
  const matchingPaths = collectMatchingPaths(diff, group.covers);
86614
86829
  const matches = matchingPaths.length;
86615
- const score = total === 0 ? 0 : clampScore(matches / total);
86830
+ const confidence = resolvePickConfidence(matches, total);
86831
+ if (confidence === void 0) {
86832
+ return void 0;
86833
+ }
86616
86834
  return {
86617
86835
  groupId: group.id,
86618
- score,
86836
+ confidence,
86619
86837
  reason: formatReason({ matches, total, paths: matchingPaths })
86620
86838
  };
86621
86839
  }
86622
86840
  function scoreGroups(diff, groups) {
86623
86841
  return groups.map((group) => scoreGroup(diff, group)).filter((pick2) => pick2 !== void 0);
86624
86842
  }
86625
- var HEADER = `You are a QA engineer selecting which test groups to run against a pull request. Each group covers a surface of the product. Pick the groups whose coverage overlaps with the changed files. Skip groups unrelated to this change.`;
86843
+ var MAX_BODY_CHARS = 400;
86844
+ var HEADER = `You are a QA engineer selecting which test groups to run against a pull request. Each group covers a product surface. Err toward inclusion \u2014 a missed regression is far worse than wasted CI minutes.`;
86626
86845
  var INSTRUCTIONS = `Call the \`select_test_groups\` tool with an array of picks. For each selected group include:
86627
- - \`groupId\`: the exact id from the list below
86628
- - \`score\`: a number in [0, 1] indicating how strongly the change exercises this group
86629
- - \`reason\`: a short justification grounded in the changed files`;
86846
+ - \`groupId\`: an id that appears verbatim in the Test Groups list below \u2014 do not invent, paraphrase, or infer ids
86847
+ - \`reason\`: cite the specific file path(s) and which \`covers\` glob or heuristic matched; write the reason first; only then commit to HIGH/MEDIUM/LOW
86848
+ - \`confidence\`: label using the rubric below
86849
+
86850
+ If no group is relevant, call the tool with \`picks: []\`.
86851
+
86852
+ ### Confidence rubric
86853
+
86854
+ - HIGH: change clearly exercises this group \u2014 changed files are the primary implementation or directly call/are called by covered paths
86855
+ - MEDIUM: shared dependency or indirect but plausible \u2014 change modifies a shared dependency of covered paths or has a tangential but credible relationship
86856
+ - LOW: tangential \u2014 the heuristics would force inclusion but only as a safety net
86857
+
86858
+ ### Selection heuristics
86859
+
86860
+ - Config or infra changes (\`*.yaml\`, \`*.json\`, \`Dockerfile\`, \`*.tf\`) fan out broadly \u2014 include integration and e2e groups
86861
+ - Shared utility changes (\`**/core/**\`, \`**/utils/**\`, \`**/shared/**\`) fan out to consumers \u2014 include every group that depends on them
86862
+ - Doc-only changes (\`*.md\`, \`*.mdx\`, \`docs/**\`) \u2014 return empty picks
86863
+ - Test-only changes (\`*.test.*\`, \`__tests__/**\`) \u2014 skip execution groups unless production code in the same diff requires them
86864
+ - Breaking API changes (deleted exports, renamed public types) \u2014 include every group (full regression)
86865
+ - Deleted files \u2014 groups that covered the deleted path must still run to verify no breakage
86866
+
86867
+ ### Process
86868
+
86869
+ Before emitting picks, list the changed areas, then match each to candidate groups. If two groups overlap on the same file, include both and give the more specific one a higher confidence. When uncertain, include the group.`;
86630
86870
  function formatFile(file2) {
86631
- return `- [${file2.status}] ${file2.path}`;
86871
+ const hunkCount = file2.hunks?.length ?? 0;
86872
+ const hunkSuffix = hunkCount > 0 ? ` (${String(hunkCount)} hunk(s))` : "";
86873
+ return `- [${file2.status}] ${file2.path}${hunkSuffix}`;
86874
+ }
86875
+ function formatBody(body) {
86876
+ if (!body) {
86877
+ return "Body: (none)";
86878
+ }
86879
+ const trimmed = body.length > MAX_BODY_CHARS ? `${body.slice(0, MAX_BODY_CHARS)}\u2026` : body;
86880
+ return `Body:
86881
+ ${trimmed}`;
86632
86882
  }
86633
86883
  function formatDiffSection(diff) {
86634
86884
  const title = diff.title ? `Title: ${diff.title}` : "Title: (none)";
86635
- const body = diff.body ? `Body:
86636
- ${diff.body}` : "Body: (none)";
86885
+ const body = formatBody(diff.body);
86637
86886
  const files = diff.files.map((file2) => formatFile(file2)).join("\n");
86638
86887
  return `${title}
86639
86888
  ${body}
@@ -86659,20 +86908,40 @@ function formatGroupsSection(groups) {
86659
86908
  function buildTriagerPrompt(diff, groups) {
86660
86909
  return `${HEADER}
86661
86910
 
86911
+ ## Instructions
86912
+
86913
+ ${INSTRUCTIONS}
86914
+
86662
86915
  ## Change
86663
86916
 
86664
86917
  ${formatDiffSection(diff)}
86665
86918
 
86666
86919
  ## Test Groups
86667
86920
 
86668
- ${formatGroupsSection(groups)}
86669
-
86670
- ## Instructions
86671
-
86672
- ${INSTRUCTIONS}`;
86921
+ ${formatGroupsSection(groups)}`;
86673
86922
  }
86674
86923
  var DEFAULT_MODEL2 = "claude-opus-4-6";
86675
- var DEFAULT_SCORE_THRESHOLD = 0.3;
86924
+ var CONFIDENCE_RANK = {
86925
+ HIGH: 2,
86926
+ MEDIUM: 1,
86927
+ LOW: 0
86928
+ };
86929
+ function applyGraderResults(mediumPicks, graderPicks) {
86930
+ const graderById = /* @__PURE__ */ new Map();
86931
+ for (const pick2 of graderPicks) {
86932
+ graderById.set(pick2.groupId, pick2);
86933
+ }
86934
+ return mediumPicks.flatMap((pick2) => {
86935
+ const graderResult = graderById.get(pick2.groupId);
86936
+ if (graderResult === void 0) {
86937
+ return [pick2];
86938
+ }
86939
+ if (graderResult.confidence === "LOW") {
86940
+ return [];
86941
+ }
86942
+ return [graderResult];
86943
+ });
86944
+ }
86676
86945
  function buildContext2(options2) {
86677
86946
  const { diff, groups, config: config3 } = options2;
86678
86947
  return {
@@ -86680,10 +86949,27 @@ function buildContext2(options2) {
86680
86949
  groups,
86681
86950
  apiKey: config3?.apiKey ?? "",
86682
86951
  model: config3?.model ?? DEFAULT_MODEL2,
86683
- threshold: config3?.scoreThreshold ?? DEFAULT_SCORE_THRESHOLD,
86684
86952
  useAi: config3?.useAi ?? true
86685
86953
  };
86686
86954
  }
86955
+ function mapAiError(error48) {
86956
+ switch (error48.type) {
86957
+ case "AI_CALL_FAILED": {
86958
+ return { type: "AI_CALL_FAILED", cause: error48.cause };
86959
+ }
86960
+ case "AI_INVALID_RESPONSE": {
86961
+ return { type: "AI_INVALID_RESPONSE", raw: error48.raw };
86962
+ }
86963
+ }
86964
+ }
86965
+ function mergePickPair(existing, incoming) {
86966
+ const existingRank = CONFIDENCE_RANK[existing.confidence];
86967
+ const incomingRank = CONFIDENCE_RANK[incoming.confidence];
86968
+ if (incomingRank > existingRank) {
86969
+ return incoming;
86970
+ }
86971
+ return existing;
86972
+ }
86687
86973
  function mergePicks(staticPicks, aiPicks) {
86688
86974
  const byId = /* @__PURE__ */ new Map();
86689
86975
  for (const pick2 of staticPicks) {
@@ -86691,48 +86977,64 @@ function mergePicks(staticPicks, aiPicks) {
86691
86977
  }
86692
86978
  for (const pick2 of aiPicks) {
86693
86979
  const existing = byId.get(pick2.groupId);
86694
- if (!existing || pick2.score > existing.score) {
86980
+ if (existing === void 0) {
86695
86981
  byId.set(pick2.groupId, pick2);
86982
+ } else {
86983
+ byId.set(pick2.groupId, mergePickPair(existing, pick2));
86696
86984
  }
86697
86985
  }
86698
86986
  return [...byId.values()];
86699
86987
  }
86988
+ function runGraderPass(options2) {
86989
+ const { context, prompt, mediumPicks, highPicks, skippedPicks } = options2;
86990
+ const validGroupIds = context.groups.map((group) => group.id);
86991
+ return graderSelectGroups({
86992
+ prompt,
86993
+ apiKey: context.apiKey,
86994
+ model: context.model,
86995
+ validGroupIds,
86996
+ originalPicks: mediumPicks
86997
+ }).mapErr(mapAiError).map((graderPicks) => {
86998
+ const survivingMedium = applyGraderResults(mediumPicks, graderPicks);
86999
+ const downgraded = mediumPicks.filter((pick2) => !survivingMedium.some((kept) => kept.groupId === pick2.groupId)).map((pick2) => ({ ...pick2, confidence: "LOW" }));
87000
+ return buildDecision([...highPicks, ...survivingMedium, ...skippedPicks, ...downgraded]);
87001
+ });
87002
+ }
87003
+ function runAiTiebreaker(context, staticPicks) {
87004
+ const prompt = buildTriagerPrompt(context.diff, context.groups);
87005
+ const validGroupIds = context.groups.map((group) => group.id);
87006
+ return selectGroups({ prompt, apiKey: context.apiKey, model: context.model, validGroupIds }).mapErr(mapAiError).map((aiPicks) => mergePicks(staticPicks, aiPicks)).andThen((merged) => {
87007
+ const highPicks = merged.filter((pick2) => pick2.confidence === "HIGH");
87008
+ const mediumPicks = merged.filter((pick2) => pick2.confidence === "MEDIUM");
87009
+ const skippedPicks = merged.filter((pick2) => pick2.confidence === "LOW");
87010
+ if (mediumPicks.length === 0) {
87011
+ return (0, import_neverthrow46.okAsync)(buildDecision(merged));
87012
+ }
87013
+ return runGraderPass({ context, prompt, mediumPicks, highPicks, skippedPicks });
87014
+ });
87015
+ }
86700
87016
  function shouldSkipAi(context, decision) {
86701
87017
  if (!context.useAi) {
86702
87018
  return true;
86703
87019
  }
86704
87020
  return decision.confidence === "high";
86705
87021
  }
86706
- function mapAiError(error48) {
86707
- switch (error48.type) {
86708
- case "AI_CALL_FAILED": {
86709
- return { type: "AI_CALL_FAILED", cause: error48.cause };
86710
- }
86711
- case "AI_INVALID_RESPONSE": {
86712
- return { type: "AI_INVALID_RESPONSE", raw: error48.raw };
86713
- }
86714
- }
86715
- }
86716
- function runAiTiebreaker(context, staticPicks) {
86717
- const prompt = buildTriagerPrompt(context.diff, context.groups);
86718
- return selectGroups({ prompt, apiKey: context.apiKey, model: context.model }).mapErr(mapAiError).map((aiPicks) => mergePicks(staticPicks, aiPicks)).map((merged) => buildDecision(merged, context.threshold));
86719
- }
86720
87022
  function runTriager(options2) {
86721
87023
  const { diff, groups, config: config3 } = options2;
86722
87024
  if (groups.length === 0) {
86723
- return (0, import_neverthrow44.errAsync)({ type: "NO_GROUPS" });
87025
+ return (0, import_neverthrow46.errAsync)({ type: "NO_GROUPS" });
86724
87026
  }
86725
87027
  const context = buildContext2({ diff, groups, config: config3 });
86726
87028
  const staticPicks = scoreGroups(diff, groups);
86727
- const initial = buildDecision(staticPicks, context.threshold);
87029
+ const initial = buildDecision(staticPicks);
86728
87030
  if (shouldSkipAi(context, initial)) {
86729
- return (0, import_neverthrow44.okAsync)(initial);
87031
+ return (0, import_neverthrow46.okAsync)(initial);
86730
87032
  }
86731
87033
  return runAiTiebreaker(context, staticPicks);
86732
87034
  }
86733
87035
 
86734
87036
  // src/commands/triage-command.ts
86735
- var import_neverthrow49 = __toESM(require_index_cjs(), 1);
87037
+ var import_neverthrow51 = __toESM(require_index_cjs(), 1);
86736
87038
 
86737
87039
  // ../../node_modules/.pnpm/universal-user-agent@7.0.3/node_modules/universal-user-agent/index.js
86738
87040
  function getUserAgent() {
@@ -87330,7 +87632,7 @@ async function getResponseData(response) {
87330
87632
  try {
87331
87633
  text = await response.text();
87332
87634
  return JSON.parse(text);
87333
- } catch (err25) {
87635
+ } catch (err26) {
87334
87636
  return text;
87335
87637
  }
87336
87638
  } else if (mimetype.type.startsWith("text/") || mimetype.parameters.charset?.toLowerCase() === "utf-8") {
@@ -90282,7 +90584,7 @@ var Octokit2 = Octokit.plugin(requestLog, legacyRestEndpointMethods, paginateRes
90282
90584
  );
90283
90585
 
90284
90586
  // src/triage/github-pr-fetcher.ts
90285
- var import_neverthrow46 = __toESM(require_index_cjs(), 1);
90587
+ var import_neverthrow48 = __toESM(require_index_cjs(), 1);
90286
90588
  var STATUS_MAP = {
90287
90589
  added: "added",
90288
90590
  modified: "modified",
@@ -90318,11 +90620,11 @@ async function runListFiles(octokit, options2) {
90318
90620
  per_page: 100
90319
90621
  });
90320
90622
  }
90321
- var safeGet = import_neverthrow46.ResultAsync.fromThrowable(
90623
+ var safeGet = import_neverthrow48.ResultAsync.fromThrowable(
90322
90624
  runPullRequestGet,
90323
90625
  (cause) => ({ type: "PR_FETCH_FAILED", cause })
90324
90626
  );
90325
- var safeList = import_neverthrow46.ResultAsync.fromThrowable(
90627
+ var safeList = import_neverthrow48.ResultAsync.fromThrowable(
90326
90628
  runListFiles,
90327
90629
  (cause) => ({ type: "PR_FETCH_FAILED", cause })
90328
90630
  );
@@ -90336,13 +90638,13 @@ function toDiff(summary, files) {
90336
90638
  }
90337
90639
  function fetchPullRequestDiff(options2) {
90338
90640
  const octokit = new Octokit2({ auth: options2.token });
90339
- return import_neverthrow46.ResultAsync.combine([safeGet(octokit, options2), safeList(octokit, options2)]).map(
90641
+ return import_neverthrow48.ResultAsync.combine([safeGet(octokit, options2), safeList(octokit, options2)]).map(
90340
90642
  ([summary, files]) => toDiff(summary, files)
90341
90643
  );
90342
90644
  }
90343
90645
 
90344
90646
  // src/triage/github-pr-labeller.ts
90345
- var import_neverthrow47 = __toESM(require_index_cjs(), 1);
90647
+ var import_neverthrow49 = __toESM(require_index_cjs(), 1);
90346
90648
  async function runAddLabels(octokit, options2) {
90347
90649
  await octokit.issues.addLabels({
90348
90650
  owner: options2.owner,
@@ -90351,7 +90653,7 @@ async function runAddLabels(octokit, options2) {
90351
90653
  labels: [...options2.labels]
90352
90654
  });
90353
90655
  }
90354
- var safeAddLabels = import_neverthrow47.ResultAsync.fromThrowable(
90656
+ var safeAddLabels = import_neverthrow49.ResultAsync.fromThrowable(
90355
90657
  runAddLabels,
90356
90658
  (cause) => ({ type: "LABEL_APPLY_FAILED", cause })
90357
90659
  );
@@ -90382,9 +90684,9 @@ function formatXqaLabels(decision) {
90382
90684
  }
90383
90685
 
90384
90686
  // src/triage/suite-loader.ts
90385
- var import_promises19 = require("node:fs/promises");
90386
- var import_node_path18 = __toESM(require("node:path"), 1);
90387
- var import_neverthrow48 = __toESM(require_index_cjs(), 1);
90687
+ var import_promises20 = require("node:fs/promises");
90688
+ var import_node_path19 = __toESM(require("node:path"), 1);
90689
+ var import_neverthrow50 = __toESM(require_index_cjs(), 1);
90388
90690
  var SUITE_FILE_SUFFIX = ".suite.json";
90389
90691
  var freestyleEntrySchema = external_exports2.object({
90390
90692
  timeoutSeconds: external_exports2.number().int().positive()
@@ -90394,39 +90696,39 @@ var suiteFileSchema = external_exports2.object({
90394
90696
  freestyle: external_exports2.array(freestyleEntrySchema).optional(),
90395
90697
  hooks: external_exports2.record(external_exports2.unknown()).optional()
90396
90698
  });
90397
- var safeJsonParse4 = (0, import_neverthrow48.fromThrowable)(JSON.parse);
90699
+ var safeJsonParse4 = (0, import_neverthrow50.fromThrowable)(JSON.parse);
90398
90700
  async function runReadFile(filePath) {
90399
- return (0, import_promises19.readFile)(filePath, "utf8");
90701
+ return (0, import_promises20.readFile)(filePath, "utf8");
90400
90702
  }
90401
90703
  async function runStat(filePath) {
90402
- return (0, import_promises19.stat)(filePath);
90704
+ return (0, import_promises20.stat)(filePath);
90403
90705
  }
90404
90706
  async function runReadDirectory(filePath) {
90405
- return (0, import_promises19.readdir)(filePath);
90707
+ return (0, import_promises20.readdir)(filePath);
90406
90708
  }
90407
90709
  function readSuiteFile(filePath) {
90408
- const safeRead = import_neverthrow48.ResultAsync.fromThrowable(
90710
+ const safeRead = import_neverthrow50.ResultAsync.fromThrowable(
90409
90711
  runReadFile,
90410
90712
  (cause) => ({ type: "SUITE_READ_FAILED", path: filePath, cause })
90411
90713
  );
90412
90714
  return safeRead(filePath);
90413
90715
  }
90414
90716
  function readSpecFile(filePath) {
90415
- const safeRead = import_neverthrow48.ResultAsync.fromThrowable(
90717
+ const safeRead = import_neverthrow50.ResultAsync.fromThrowable(
90416
90718
  runReadFile,
90417
90719
  () => ({ type: "SPEC_NOT_FOUND", path: filePath })
90418
90720
  );
90419
90721
  return safeRead(filePath);
90420
90722
  }
90421
90723
  function statDirectory(directory) {
90422
- const safeStat = import_neverthrow48.ResultAsync.fromThrowable(
90724
+ const safeStat = import_neverthrow50.ResultAsync.fromThrowable(
90423
90725
  runStat,
90424
90726
  () => ({ type: "SUITE_DIR_MISSING", path: directory })
90425
90727
  );
90426
90728
  return safeStat(directory);
90427
90729
  }
90428
90730
  function readDirectoryEntries(directory) {
90429
- const safeReadDirectory = import_neverthrow48.ResultAsync.fromThrowable(
90731
+ const safeReadDirectory = import_neverthrow50.ResultAsync.fromThrowable(
90430
90732
  runReadDirectory,
90431
90733
  (cause) => ({ type: "SUITE_READ_FAILED", path: directory, cause })
90432
90734
  );
@@ -90435,34 +90737,34 @@ function readDirectoryEntries(directory) {
90435
90737
  function listSuiteFiles(directory) {
90436
90738
  return statDirectory(directory).andThen((stats) => {
90437
90739
  if (!stats.isDirectory()) {
90438
- return (0, import_neverthrow48.errAsync)({ type: "SUITE_DIR_MISSING", path: directory });
90740
+ return (0, import_neverthrow50.errAsync)({ type: "SUITE_DIR_MISSING", path: directory });
90439
90741
  }
90440
90742
  return readDirectoryEntries(directory);
90441
90743
  }).map(
90442
- (entries) => entries.filter((entry) => entry.endsWith(SUITE_FILE_SUFFIX)).map((entry) => import_node_path18.default.resolve(directory, entry)).toSorted()
90744
+ (entries) => entries.filter((entry) => entry.endsWith(SUITE_FILE_SUFFIX)).map((entry) => import_node_path19.default.resolve(directory, entry)).toSorted()
90443
90745
  );
90444
90746
  }
90445
90747
  function parseSuiteFile(filePath, raw) {
90446
90748
  const parsed = safeJsonParse4(raw);
90447
90749
  if (parsed.isErr()) {
90448
- return (0, import_neverthrow48.err)({ type: "SUITE_INVALID", path: filePath, cause: parsed.error });
90750
+ return (0, import_neverthrow50.err)({ type: "SUITE_INVALID", path: filePath, cause: parsed.error });
90449
90751
  }
90450
90752
  const validated = suiteFileSchema.safeParse(parsed.value);
90451
90753
  if (!validated.success) {
90452
- return (0, import_neverthrow48.err)({ type: "SUITE_INVALID", path: filePath, cause: validated.error });
90754
+ return (0, import_neverthrow50.err)({ type: "SUITE_INVALID", path: filePath, cause: validated.error });
90453
90755
  }
90454
- return (0, import_neverthrow48.ok)(validated.data);
90756
+ return (0, import_neverthrow50.ok)(validated.data);
90455
90757
  }
90456
90758
  function suiteIdFromPath(filePath) {
90457
- const name = import_node_path18.default.basename(filePath);
90759
+ const name = import_node_path19.default.basename(filePath);
90458
90760
  return name.slice(0, name.length - SUITE_FILE_SUFFIX.length);
90459
90761
  }
90460
90762
  function loadSpecReference(xqaDirectory, specPath) {
90461
- const absolute = import_node_path18.default.resolve(xqaDirectory, specPath);
90763
+ const absolute = import_node_path19.default.resolve(xqaDirectory, specPath);
90462
90764
  return readSpecFile(absolute).andThen((raw) => {
90463
90765
  const parsed = parseSpecFrontmatter(raw);
90464
90766
  if (parsed.isErr()) {
90465
- return (0, import_neverthrow48.err)({
90767
+ return (0, import_neverthrow50.err)({
90466
90768
  type: "SPEC_FRONTMATTER_INVALID",
90467
90769
  path: absolute,
90468
90770
  cause: parsed.error.cause
@@ -90470,19 +90772,19 @@ function loadSpecReference(xqaDirectory, specPath) {
90470
90772
  }
90471
90773
  const { feature, timeoutSeconds } = parsed.value;
90472
90774
  if (timeoutSeconds === void 0) {
90473
- return (0, import_neverthrow48.ok)({ path: specPath, feature });
90775
+ return (0, import_neverthrow50.ok)({ path: specPath, feature });
90474
90776
  }
90475
- return (0, import_neverthrow48.ok)({ path: specPath, feature, timeoutSeconds });
90777
+ return (0, import_neverthrow50.ok)({ path: specPath, feature, timeoutSeconds });
90476
90778
  });
90477
90779
  }
90478
90780
  function loadSpecReferences(xqaDirectory, specs) {
90479
90781
  if (specs.length === 0) {
90480
- return (0, import_neverthrow48.okAsync)([]);
90782
+ return (0, import_neverthrow50.okAsync)([]);
90481
90783
  }
90482
- return import_neverthrow48.ResultAsync.combine(specs.map((specPath) => loadSpecReference(xqaDirectory, specPath)));
90784
+ return import_neverthrow50.ResultAsync.combine(specs.map((specPath) => loadSpecReference(xqaDirectory, specPath)));
90483
90785
  }
90484
90786
  function addSpecTokens(tokens, spec) {
90485
- const stem = import_node_path18.default.basename(spec.path).replace(/\.test\.md$/u, "");
90787
+ const stem = import_node_path19.default.basename(spec.path).replace(/\.test\.md$/u, "");
90486
90788
  for (const part of stem.split(".")) {
90487
90789
  if (part.length > 0) {
90488
90790
  tokens.add(part);
@@ -90547,12 +90849,12 @@ function loadSuite(suiteFilePath, xqaDirectory) {
90547
90849
  );
90548
90850
  }
90549
90851
  function loadXqaSuites(directory) {
90550
- const xqaDirectory = import_node_path18.default.dirname(import_node_path18.default.resolve(directory));
90852
+ const xqaDirectory = import_node_path19.default.dirname(import_node_path19.default.resolve(directory));
90551
90853
  return listSuiteFiles(directory).andThen((files) => {
90552
90854
  if (files.length === 0) {
90553
- return (0, import_neverthrow48.okAsync)([]);
90855
+ return (0, import_neverthrow50.okAsync)([]);
90554
90856
  }
90555
- return import_neverthrow48.ResultAsync.combine(files.map((file2) => loadSuite(file2, xqaDirectory)));
90857
+ return import_neverthrow50.ResultAsync.combine(files.map((file2) => loadSuite(file2, xqaDirectory)));
90556
90858
  });
90557
90859
  }
90558
90860
 
@@ -90563,77 +90865,57 @@ function parseRepo(input) {
90563
90865
  const parts = input.split("/");
90564
90866
  const [owner, repo] = parts;
90565
90867
  if (parts.length !== 2 || owner === void 0 || owner === "" || repo === void 0 || repo === "") {
90566
- return (0, import_neverthrow49.err)({ type: "CLI_INVALID_ARG", message: `invalid --repo value: ${input}` });
90868
+ return (0, import_neverthrow51.err)({ type: "CLI_INVALID_ARG", message: `invalid --repo value: ${input}` });
90567
90869
  }
90568
- return (0, import_neverthrow49.ok)({ owner, repo });
90870
+ return (0, import_neverthrow51.ok)({ owner, repo });
90569
90871
  }
90570
90872
  function parsePrNumber(input) {
90571
90873
  const parsed = Number.parseInt(input, 10);
90572
90874
  if (!Number.isFinite(parsed) || parsed <= 0) {
90573
- return (0, import_neverthrow49.err)({ type: "CLI_INVALID_ARG", message: `invalid --pr value: ${input}` });
90875
+ return (0, import_neverthrow51.err)({ type: "CLI_INVALID_ARG", message: `invalid --pr value: ${input}` });
90574
90876
  }
90575
- return (0, import_neverthrow49.ok)(parsed);
90576
- }
90577
- function parseThresholdValue(input) {
90578
- const parsed = Number.parseFloat(input);
90579
- if (!Number.isFinite(parsed) || parsed < 0 || parsed > 1) {
90580
- return (0, import_neverthrow49.err)({ type: "CLI_INVALID_ARG", message: `invalid --threshold value: ${input}` });
90581
- }
90582
- return (0, import_neverthrow49.ok)(parsed);
90583
- }
90584
- function parseThreshold(input) {
90585
- if (input === void 0) {
90586
- return (0, import_neverthrow49.ok)(void 0);
90587
- }
90588
- return parseThresholdValue(input);
90877
+ return (0, import_neverthrow51.ok)(parsed);
90589
90878
  }
90590
90879
  function parseCliInputs(options2) {
90591
90880
  const repoResult = parseRepo(options2.repo);
90592
90881
  if (repoResult.isErr()) {
90593
- return (0, import_neverthrow49.err)(repoResult.error);
90882
+ return (0, import_neverthrow51.err)(repoResult.error);
90594
90883
  }
90595
90884
  const prResult = parsePrNumber(options2.pr);
90596
90885
  if (prResult.isErr()) {
90597
- return (0, import_neverthrow49.err)(prResult.error);
90598
- }
90599
- const thresholdResult = parseThreshold(options2.threshold);
90600
- if (thresholdResult.isErr()) {
90601
- return (0, import_neverthrow49.err)(thresholdResult.error);
90886
+ return (0, import_neverthrow51.err)(prResult.error);
90602
90887
  }
90603
- return (0, import_neverthrow49.ok)({
90888
+ return (0, import_neverthrow51.ok)({
90604
90889
  owner: repoResult.value.owner,
90605
90890
  repo: repoResult.value.repo,
90606
- prNumber: prResult.value,
90607
- threshold: thresholdResult.value
90891
+ prNumber: prResult.value
90608
90892
  });
90609
90893
  }
90610
90894
  function buildInputs(options2, config3) {
90611
90895
  if (config3.GITHUB_TOKEN === void 0) {
90612
- return (0, import_neverthrow49.err)({ type: "CONFIG_MISSING", key: "GITHUB_TOKEN" });
90896
+ return (0, import_neverthrow51.err)({ type: "CONFIG_MISSING", key: "GITHUB_TOKEN" });
90613
90897
  }
90614
90898
  const parsed = parseCliInputs(options2);
90615
90899
  if (parsed.isErr()) {
90616
- return (0, import_neverthrow49.err)(parsed.error);
90900
+ return (0, import_neverthrow51.err)(parsed.error);
90617
90901
  }
90618
- return (0, import_neverthrow49.ok)({
90902
+ return (0, import_neverthrow51.ok)({
90619
90903
  owner: parsed.value.owner,
90620
90904
  repo: parsed.value.repo,
90621
90905
  prNumber: parsed.value.prNumber,
90622
90906
  suitesDir: options2.suitesDir ?? config3.XQA_SUITES_DIR,
90623
90907
  applyLabels: options2.applyLabels === true,
90624
90908
  model: options2.model,
90625
- threshold: parsed.value.threshold,
90626
90909
  anthropicApiKey: config3.ANTHROPIC_API_KEY,
90627
90910
  githubToken: config3.GITHUB_TOKEN
90628
90911
  });
90629
90912
  }
90630
90913
  function buildTriagerConfig(inputs) {
90631
90914
  const base = { apiKey: inputs.anthropicApiKey };
90632
- const withModel = inputs.model === void 0 ? base : { ...base, model: inputs.model };
90633
- if (inputs.threshold === void 0) {
90634
- return withModel;
90915
+ if (inputs.model === void 0) {
90916
+ return base;
90635
90917
  }
90636
- return { ...withModel, scoreThreshold: inputs.threshold };
90918
+ return { ...base, model: inputs.model };
90637
90919
  }
90638
90920
  function callTriager(options2) {
90639
90921
  const { inputs, groups, diff } = options2;
@@ -90643,7 +90925,7 @@ function callTriager(options2) {
90643
90925
  }
90644
90926
  function maybeApplyLabels(inputs, labels) {
90645
90927
  if (!inputs.applyLabels || labels.length === 0) {
90646
- return import_neverthrow49.ResultAsync.fromSafePromise(Promise.resolve(labels));
90928
+ return import_neverthrow51.ResultAsync.fromSafePromise(Promise.resolve(labels));
90647
90929
  }
90648
90930
  return applyPullRequestLabels({
90649
90931
  owner: inputs.owner,
@@ -90653,8 +90935,8 @@ function maybeApplyLabels(inputs, labels) {
90653
90935
  token: inputs.githubToken
90654
90936
  }).map(() => labels);
90655
90937
  }
90656
- function runPipeline3(inputs) {
90657
- return import_neverthrow49.ResultAsync.combine([
90938
+ function runPipeline4(inputs) {
90939
+ return import_neverthrow51.ResultAsync.combine([
90658
90940
  loadXqaSuites(inputs.suitesDir),
90659
90941
  fetchPullRequestDiff({
90660
90942
  owner: inputs.owner,
@@ -90681,7 +90963,7 @@ async function runTriageCommand(options2, config3) {
90681
90963
  printError(inputs.error);
90682
90964
  return EXIT_FAILURE;
90683
90965
  }
90684
- const outcome = await runPipeline3(inputs.value);
90966
+ const outcome = await runPipeline4(inputs.value);
90685
90967
  return outcome.match(
90686
90968
  (payload) => {
90687
90969
  printSuccess(payload);
@@ -90701,10 +90983,10 @@ function runUpdateCommand() {
90701
90983
  }
90702
90984
 
90703
90985
  // src/config.ts
90704
- var import_node_path19 = __toESM(require("node:path"), 1);
90986
+ var import_node_path20 = __toESM(require("node:path"), 1);
90705
90987
  var import_node_url2 = require("node:url");
90706
90988
  var import_dotenv = __toESM(require_main(), 1);
90707
- var import_neverthrow50 = __toESM(require_index_cjs(), 1);
90989
+ var import_neverthrow52 = __toESM(require_index_cjs(), 1);
90708
90990
 
90709
90991
  // src/config-schema.ts
90710
90992
  var configSchema = external_exports2.object({
@@ -90718,18 +91000,18 @@ var configSchema = external_exports2.object({
90718
91000
  });
90719
91001
 
90720
91002
  // src/config.ts
90721
- var packageDirectory = import_node_path19.default.dirname((0, import_node_url2.fileURLToPath)(__importMetaUrl));
91003
+ var packageDirectory = import_node_path20.default.dirname((0, import_node_url2.fileURLToPath)(__importMetaUrl));
90722
91004
  function loadConfig() {
90723
- (0, import_dotenv.config)({ path: import_node_path19.default.resolve(packageDirectory, "..", ".env.local") });
91005
+ (0, import_dotenv.config)({ path: import_node_path20.default.resolve(packageDirectory, "..", ".env.local") });
90724
91006
  const result = configSchema.safeParse(process.env);
90725
91007
  if (!result.success) {
90726
91008
  const messages = result.error.issues.map(
90727
91009
  (issue2) => ` - ${issue2.path.join(".")}: ${issue2.message}`
90728
91010
  );
90729
- return (0, import_neverthrow50.err)({ type: "INVALID_CONFIG", message: `Configuration error:
91011
+ return (0, import_neverthrow52.err)({ type: "INVALID_CONFIG", message: `Configuration error:
90730
91012
  ${messages.join("\n")}` });
90731
91013
  }
90732
- return (0, import_neverthrow50.ok)(result.data);
91014
+ return (0, import_neverthrow52.ok)(result.data);
90733
91015
  }
90734
91016
 
90735
91017
  // src/core/parse-timeout-seconds.ts
@@ -90762,7 +91044,7 @@ function parseVerboseOption(value) {
90762
91044
 
90763
91045
  // src/pid-lock.ts
90764
91046
  var import_node_fs9 = require("node:fs");
90765
- var import_neverthrow51 = __toESM(require_index_cjs(), 1);
91047
+ var import_neverthrow53 = __toESM(require_index_cjs(), 1);
90766
91048
  var PID_FILE = "/tmp/xqa.pid";
90767
91049
  var SIGINT_EXIT_CODE = 130;
90768
91050
  var SIGTERM_EXIT_CODE = 143;
@@ -90771,7 +91053,7 @@ var HARD_TIMEOUT_MS = 1e4;
90771
91053
  var cleanup = () => {
90772
91054
  (0, import_node_fs9.rmSync)(PID_FILE, { force: true });
90773
91055
  };
90774
- var checkProcessRunning = (0, import_neverthrow51.fromThrowable)(
91056
+ var checkProcessRunning = (0, import_neverthrow53.fromThrowable)(
90775
91057
  (pid) => {
90776
91058
  process.kill(pid, 0);
90777
91059
  return true;
@@ -90836,32 +91118,32 @@ function acquireLock() {
90836
91118
 
90837
91119
  // src/shell/xqa-directory.ts
90838
91120
  var import_node_fs10 = require("node:fs");
90839
- var import_node_path20 = __toESM(require("node:path"), 1);
90840
- var import_neverthrow52 = __toESM(require_index_cjs(), 1);
91121
+ var import_node_path21 = __toESM(require("node:path"), 1);
91122
+ var import_neverthrow54 = __toESM(require_index_cjs(), 1);
90841
91123
  function findXqaDirectory(startDirectory) {
90842
91124
  let current = startDirectory;
90843
91125
  for (; ; ) {
90844
- const candidate = import_node_path20.default.join(current, ".xqa");
91126
+ const candidate = import_node_path21.default.join(current, ".xqa");
90845
91127
  if ((0, import_node_fs10.existsSync)(candidate)) {
90846
- return (0, import_neverthrow52.ok)(candidate);
91128
+ return (0, import_neverthrow54.ok)(candidate);
90847
91129
  }
90848
- const parent = import_node_path20.default.dirname(current);
91130
+ const parent = import_node_path21.default.dirname(current);
90849
91131
  if (parent === current) {
90850
- return (0, import_neverthrow52.err)({ type: "XQA_NOT_INITIALIZED" });
91132
+ return (0, import_neverthrow54.err)({ type: "XQA_NOT_INITIALIZED" });
90851
91133
  }
90852
91134
  current = parent;
90853
91135
  }
90854
91136
  }
90855
91137
 
90856
91138
  // src/suite/commands/run-command.ts
90857
- var import_promises22 = __toESM(require("node:fs/promises"), 1);
90858
- var import_node_path24 = __toESM(require("node:path"), 1);
91139
+ var import_promises23 = __toESM(require("node:fs/promises"), 1);
91140
+ var import_node_path25 = __toESM(require("node:path"), 1);
90859
91141
  var import_fast_glob = __toESM(require_out4(), 1);
90860
- var import_neverthrow60 = __toESM(require_index_cjs(), 1);
91142
+ var import_neverthrow62 = __toESM(require_index_cjs(), 1);
90861
91143
 
90862
91144
  // src/suite/core/suite-config-parser.ts
90863
- var import_neverthrow53 = __toESM(require_index_cjs(), 1);
90864
- var import_neverthrow54 = __toESM(require_index_cjs(), 1);
91145
+ var import_neverthrow55 = __toESM(require_index_cjs(), 1);
91146
+ var import_neverthrow56 = __toESM(require_index_cjs(), 1);
90865
91147
  var RESERVED_HOOK_ENV_KEYS = [
90866
91148
  "XQA_SIM_UDID",
90867
91149
  "XQA_ITEM_ID",
@@ -90913,7 +91195,7 @@ var suiteConfigSchema = external_exports2.object({
90913
91195
  }).refine((data) => data.specs.length > 0 || data.freestyle.length > 0, {
90914
91196
  message: "Suite must declare at least one spec or freestyle entry"
90915
91197
  });
90916
- var safeJsonParse5 = (0, import_neverthrow53.fromThrowable)(
91198
+ var safeJsonParse5 = (0, import_neverthrow55.fromThrowable)(
90917
91199
  JSON.parse,
90918
91200
  (cause) => ({
90919
91201
  type: "INVALID_SUITE_CONFIG",
@@ -90947,16 +91229,16 @@ function parseSuiteConfig(raw) {
90947
91229
  return safeJsonParse5(raw).andThen((data) => {
90948
91230
  const parsed = suiteConfigSchema.safeParse(data);
90949
91231
  if (!parsed.success) {
90950
- return (0, import_neverthrow54.err)({ type: "INVALID_SUITE_CONFIG", cause: parsed.error });
91232
+ return (0, import_neverthrow56.err)({ type: "INVALID_SUITE_CONFIG", cause: parsed.error });
90951
91233
  }
90952
91234
  const hooks = normalizeHooks(parsed.data.hooks);
90953
91235
  if (hooks === void 0) {
90954
- return (0, import_neverthrow54.ok)({
91236
+ return (0, import_neverthrow56.ok)({
90955
91237
  specs: parsed.data.specs,
90956
91238
  freestyle: parsed.data.freestyle
90957
91239
  });
90958
91240
  }
90959
- return (0, import_neverthrow54.ok)({
91241
+ return (0, import_neverthrow56.ok)({
90960
91242
  specs: parsed.data.specs,
90961
91243
  freestyle: parsed.data.freestyle,
90962
91244
  hooks
@@ -91013,25 +91295,25 @@ function buildFreestyleItems(entries) {
91013
91295
  }
91014
91296
 
91015
91297
  // src/suite/shell/suite-findings-writer.ts
91016
- var import_promises20 = __toESM(require("node:fs/promises"), 1);
91017
- var import_node_path21 = __toESM(require("node:path"), 1);
91018
- var import_neverthrow55 = __toESM(require_index_cjs(), 1);
91298
+ var import_promises21 = __toESM(require("node:fs/promises"), 1);
91299
+ var import_node_path22 = __toESM(require("node:path"), 1);
91300
+ var import_neverthrow57 = __toESM(require_index_cjs(), 1);
91019
91301
  var INDENT_SPACES = 2;
91020
91302
  function writeSuiteFindings(findings, options2) {
91021
- const directory = import_node_path21.default.join(
91303
+ const directory = import_node_path22.default.join(
91022
91304
  options2.outputDirectory,
91023
91305
  "suite",
91024
91306
  findings.suiteId,
91025
91307
  options2.date,
91026
91308
  findings.runId
91027
91309
  );
91028
- const finalPath = import_node_path21.default.join(directory, "findings.json");
91310
+ const finalPath = import_node_path22.default.join(directory, "findings.json");
91029
91311
  const temporaryPath = `${finalPath}.tmp`;
91030
- const safeWriteAtomically = import_neverthrow55.ResultAsync.fromThrowable(
91312
+ const safeWriteAtomically = import_neverthrow57.ResultAsync.fromThrowable(
91031
91313
  async () => {
91032
- await import_promises20.default.mkdir(directory, { recursive: true });
91033
- await import_promises20.default.writeFile(temporaryPath, JSON.stringify(findings, void 0, INDENT_SPACES));
91034
- await import_promises20.default.rename(temporaryPath, finalPath);
91314
+ await import_promises21.default.mkdir(directory, { recursive: true });
91315
+ await import_promises21.default.writeFile(temporaryPath, JSON.stringify(findings, void 0, INDENT_SPACES));
91316
+ await import_promises21.default.rename(temporaryPath, finalPath);
91035
91317
  return finalPath;
91036
91318
  },
91037
91319
  (cause) => ({ type: "FINDINGS_WRITE_FAILED", cause })
@@ -91040,7 +91322,7 @@ function writeSuiteFindings(findings, options2) {
91040
91322
  }
91041
91323
 
91042
91324
  // src/suite/shell/worker-pool.ts
91043
- var import_neverthrow58 = __toESM(require_index_cjs(), 1);
91325
+ var import_neverthrow60 = __toESM(require_index_cjs(), 1);
91044
91326
 
91045
91327
  // src/suite/core/priority-queue.ts
91046
91328
  var PriorityQueue = class {
@@ -91224,7 +91506,7 @@ function recordHookFailure(input) {
91224
91506
  }
91225
91507
 
91226
91508
  // src/suite/shell/hook-invoker.ts
91227
- var import_neverthrow57 = __toESM(require_index_cjs(), 1);
91509
+ var import_neverthrow59 = __toESM(require_index_cjs(), 1);
91228
91510
 
91229
91511
  // src/suite/core/hook-env-builder.ts
91230
91512
  function buildReservedKeys(input) {
@@ -91251,7 +91533,7 @@ function buildHookEnv(input) {
91251
91533
 
91252
91534
  // src/suite/shell/hook-runner.ts
91253
91535
  var import_node_child_process6 = require("node:child_process");
91254
- var import_neverthrow56 = __toESM(require_index_cjs(), 1);
91536
+ var import_neverthrow58 = __toESM(require_index_cjs(), 1);
91255
91537
  function makeDeferred() {
91256
91538
  const raw = Promise.withResolvers();
91257
91539
  return { promise: raw.promise, resolve: raw.resolve };
@@ -91281,7 +91563,7 @@ var HookRuntime = class {
91281
91563
  this.deferred = makeDeferred();
91282
91564
  this.onAbort = () => {
91283
91565
  this.child.kill("SIGTERM");
91284
- this.settle((0, import_neverthrow56.err)({ type: "HOOK_ABORTED" }));
91566
+ this.settle((0, import_neverthrow58.err)({ type: "HOOK_ABORTED" }));
91285
91567
  };
91286
91568
  }
91287
91569
  async start() {
@@ -91306,20 +91588,20 @@ var HookRuntime = class {
91306
91588
  attachTimeout() {
91307
91589
  this.timeoutHandle = setTimeout(() => {
91308
91590
  this.child.kill("SIGTERM");
91309
- this.settle((0, import_neverthrow56.err)({ type: "HOOK_TIMEOUT", timeoutMs: this.timeoutMs }));
91591
+ this.settle((0, import_neverthrow58.err)({ type: "HOOK_TIMEOUT", timeoutMs: this.timeoutMs }));
91310
91592
  }, this.timeoutMs);
91311
91593
  }
91312
91594
  attachChildListeners() {
91313
91595
  this.child.on("error", (cause) => {
91314
- this.settle((0, import_neverthrow56.err)({ type: "HOOK_SPAWN_FAILED", cause }));
91596
+ this.settle((0, import_neverthrow58.err)({ type: "HOOK_SPAWN_FAILED", cause }));
91315
91597
  });
91316
91598
  this.child.on("exit", (code) => {
91317
91599
  if (code === 0) {
91318
- this.settle((0, import_neverthrow56.ok)());
91600
+ this.settle((0, import_neverthrow58.ok)());
91319
91601
  return;
91320
91602
  }
91321
91603
  this.settle(
91322
- (0, import_neverthrow56.err)({
91604
+ (0, import_neverthrow58.err)({
91323
91605
  type: "HOOK_EXIT_NONZERO",
91324
91606
  code: code ?? -1,
91325
91607
  stderr: this.stderrBuffer
@@ -91342,7 +91624,7 @@ var HookRuntime = class {
91342
91624
  this.signal.removeEventListener("abort", this.onAbort);
91343
91625
  }
91344
91626
  };
91345
- var safeSpawn = import_neverthrow56.ResultAsync.fromThrowable(
91627
+ var safeSpawn = import_neverthrow58.ResultAsync.fromThrowable(
91346
91628
  spawnHook,
91347
91629
  (cause) => ({ type: "HOOK_SPAWN_FAILED", cause })
91348
91630
  );
@@ -91370,7 +91652,7 @@ async function invokeHook(input) {
91370
91652
  async function maybeInvokeHook(input) {
91371
91653
  const { hook: hook2 } = input;
91372
91654
  if (hook2 === void 0) {
91373
- return (0, import_neverthrow57.ok)();
91655
+ return (0, import_neverthrow59.ok)();
91374
91656
  }
91375
91657
  return invokeHook({ ...input, hook: hook2 });
91376
91658
  }
@@ -91509,7 +91791,7 @@ function runWorkerPool(config3) {
91509
91791
  const queue = setupQueue(config3);
91510
91792
  const results = [];
91511
91793
  const suiteStartMs = Date.now();
91512
- const safeRun = import_neverthrow58.ResultAsync.fromThrowable(
91794
+ const safeRun = import_neverthrow60.ResultAsync.fromThrowable(
91513
91795
  async () => runAllWorkers({ config: config3, queue, results, suiteStartMs }),
91514
91796
  (cause) => ({ type: "WORKER_POOL_FAILED", cause })
91515
91797
  );
@@ -91519,7 +91801,7 @@ function runWorkerPool(config3) {
91519
91801
  // src/suite/commands/execute-item.ts
91520
91802
  var import_node_fs11 = require("node:fs");
91521
91803
  var import_node_os4 = __toESM(require("node:os"), 1);
91522
- var import_node_path22 = __toESM(require("node:path"), 1);
91804
+ var import_node_path23 = __toESM(require("node:path"), 1);
91523
91805
  var DEFAULT_FREESTYLE_TIMEOUT_SECONDS2 = 300;
91524
91806
  function buildDeviceInstruction(simulatorUdid) {
91525
91807
  return `You MUST use device "${simulatorUdid}" for ALL mobile tool calls. The simulator UDID is already configured \u2014 use it directly.`;
@@ -91528,7 +91810,7 @@ function composeAppContext(parts) {
91528
91810
  return parts.filter((part) => part !== void 0 && part.length > 0).join("\n\n");
91529
91811
  }
91530
91812
  function ensureWorkerCwd(simulatorUdid) {
91531
- const workerDirectory = import_node_path22.default.join(import_node_os4.default.tmpdir(), "xqa-workers", simulatorUdid);
91813
+ const workerDirectory = import_node_path23.default.join(import_node_os4.default.tmpdir(), "xqa-workers", simulatorUdid);
91532
91814
  (0, import_node_fs11.mkdirSync)(workerDirectory, { recursive: true });
91533
91815
  return workerDirectory;
91534
91816
  }
@@ -91542,7 +91824,7 @@ function buildFreestylePipelineConfig(input) {
91542
91824
  const { item, context, signal, simulatorUdid, onEvent } = input;
91543
91825
  const { config: config3, xqaDirectory, runId, date: date5, appContext } = context;
91544
91826
  return {
91545
- outputDir: import_node_path22.default.join(xqaDirectory, "output", item.id),
91827
+ outputDir: import_node_path23.default.join(xqaDirectory, "output", item.id),
91546
91828
  runId,
91547
91829
  simulatorUdid,
91548
91830
  signal,
@@ -91564,13 +91846,13 @@ function buildFreestylePipelineConfig(input) {
91564
91846
  };
91565
91847
  }
91566
91848
  function executeFreestyleItem(input) {
91567
- return runPipeline2(buildFreestylePipelineConfig(input)).map((output) => ({ findings: output.findings, findingsPath: output.findingsPath })).mapErr((cause) => ({ type: "PIPELINE_FAILED", cause }));
91849
+ return runPipeline3(buildFreestylePipelineConfig(input)).map((output) => ({ findings: output.findings, findingsPath: output.findingsPath })).mapErr((cause) => ({ type: "PIPELINE_FAILED", cause }));
91568
91850
  }
91569
91851
  function buildSpecPipelineConfig(input) {
91570
91852
  const { item, context, signal, simulatorUdid, onEvent } = input;
91571
91853
  const { config: config3, xqaDirectory, runId, appContext } = context;
91572
91854
  return {
91573
- outputDir: import_node_path22.default.join(xqaDirectory, "output", item.id),
91855
+ outputDir: import_node_path23.default.join(xqaDirectory, "output", item.id),
91574
91856
  runId,
91575
91857
  simulatorUdid,
91576
91858
  signal,
@@ -91587,7 +91869,7 @@ function buildSpecPipelineConfig(input) {
91587
91869
  };
91588
91870
  }
91589
91871
  function executeSpecItem(input) {
91590
- return runPipeline2(buildSpecPipelineConfig(input)).map((output) => ({ findings: output.findings, findingsPath: output.findingsPath })).mapErr((cause) => ({ type: "PIPELINE_FAILED", cause }));
91872
+ return runPipeline3(buildSpecPipelineConfig(input)).map((output) => ({ findings: output.findings, findingsPath: output.findingsPath })).mapErr((cause) => ({ type: "PIPELINE_FAILED", cause }));
91591
91873
  }
91592
91874
  function makeExecuteItem(context) {
91593
91875
  return (options2) => {
@@ -91600,9 +91882,9 @@ function makeExecuteItem(context) {
91600
91882
  }
91601
91883
 
91602
91884
  // src/suite/commands/suite-run-context.ts
91603
- var import_promises21 = __toESM(require("node:fs/promises"), 1);
91604
- var import_node_path23 = __toESM(require("node:path"), 1);
91605
- var import_neverthrow59 = __toESM(require_index_cjs(), 1);
91885
+ var import_promises22 = __toESM(require("node:fs/promises"), 1);
91886
+ var import_node_path24 = __toESM(require("node:path"), 1);
91887
+ var import_neverthrow61 = __toESM(require_index_cjs(), 1);
91606
91888
 
91607
91889
  // src/suite/core/run-id.ts
91608
91890
  var RUN_ID_PAD_LENGTH2 = 4;
@@ -91637,16 +91919,16 @@ function deriveSuiteId(input) {
91637
91919
 
91638
91920
  // src/suite/commands/suite-run-context.ts
91639
91921
  var ISO_DATE_LENGTH3 = 10;
91640
- var safeReaddir2 = import_neverthrow59.ResultAsync.fromThrowable(
91922
+ var safeReaddir2 = import_neverthrow61.ResultAsync.fromThrowable(
91641
91923
  async (directoryPath) => {
91642
- const entries = await import_promises21.default.readdir(directoryPath, { withFileTypes: true });
91924
+ const entries = await import_promises22.default.readdir(directoryPath, { withFileTypes: true });
91643
91925
  return entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name);
91644
91926
  },
91645
91927
  () => "READDIR_FAILED"
91646
91928
  );
91647
91929
  async function listRunDirectories(input) {
91648
91930
  const { outputDirectory, suiteId, date: date5 } = input;
91649
- const directoryPath = import_node_path23.default.join(outputDirectory, "suite", suiteId, date5);
91931
+ const directoryPath = import_node_path24.default.join(outputDirectory, "suite", suiteId, date5);
91650
91932
  const result = await safeReaddir2(directoryPath);
91651
91933
  return result.unwrapOr([]);
91652
91934
  }
@@ -91670,7 +91952,7 @@ ${cause}
91670
91952
  async function buildSuiteRunContext(input) {
91671
91953
  const suiteId = deriveSuiteIdFromMode(input.mode);
91672
91954
  const date5 = (/* @__PURE__ */ new Date()).toISOString().slice(0, ISO_DATE_LENGTH3);
91673
- const outputDirectory = import_node_path23.default.join(input.xqaDirectory, "output");
91955
+ const outputDirectory = import_node_path24.default.join(input.xqaDirectory, "output");
91674
91956
  const existingDirectories = await listRunDirectories({ outputDirectory, suiteId, date: date5 });
91675
91957
  const runId = computeNextRunId(existingDirectories);
91676
91958
  const appContext = await loadAppContext(input.xqaDirectory);
@@ -91685,15 +91967,15 @@ async function buildSuiteRunContext(input) {
91685
91967
  }
91686
91968
 
91687
91969
  // src/suite/commands/run-command.ts
91688
- var safeReadFile5 = import_neverthrow60.ResultAsync.fromThrowable(
91689
- async (filePath) => import_promises22.default.readFile(filePath, "utf8"),
91970
+ var safeReadFile5 = import_neverthrow62.ResultAsync.fromThrowable(
91971
+ async (filePath) => import_promises23.default.readFile(filePath, "utf8"),
91690
91972
  () => "READ_FAILED"
91691
91973
  );
91692
91974
  async function resolveGlobs(input) {
91693
91975
  return (0, import_fast_glob.default)(input.globs, { cwd: input.cwd, absolute: true });
91694
91976
  }
91695
91977
  async function loadSuiteConfig(xqaDirectory, name) {
91696
- const suitePath = import_node_path24.default.join(xqaDirectory, "suites", `${name}.suite.json`);
91978
+ const suitePath = import_node_path25.default.join(xqaDirectory, "suites", `${name}.suite.json`);
91697
91979
  const contentResult = await safeReadFile5(suitePath);
91698
91980
  if (contentResult.isErr()) {
91699
91981
  return;
@@ -91889,7 +92171,7 @@ function resolveXqaDirectory() {
91889
92171
  return result.value;
91890
92172
  }
91891
92173
  var program2 = new Command();
91892
- program2.name("xqa").description("AI-powered QA agent CLI").version(`${"1.17.0"}${false ? ` (dev build +${"c37f65b"})` : ""}`);
92174
+ program2.name("xqa").description("AI-powered QA agent CLI").version(`${"2.0.0"}${false ? ` (dev build +${"e8d216b"})` : ""}`);
91893
92175
  program2.command("init").description("Initialize a new xqa project in the current directory").action(() => {
91894
92176
  runInitCommand();
91895
92177
  });