@exodus/xqa 1.9.0 → 1.11.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 (3) hide show
  1. package/README.md +31 -0
  2. package/dist/xqa.cjs +1388 -694
  3. package/package.json +1 -1
package/dist/xqa.cjs CHANGED
@@ -1194,8 +1194,8 @@ var require_command = __commonJS({
1194
1194
  "../../node_modules/.pnpm/commander@14.0.3/node_modules/commander/lib/command.js"(exports2) {
1195
1195
  var EventEmitter = require("node:events").EventEmitter;
1196
1196
  var childProcess = require("node:child_process");
1197
- var path23 = require("node:path");
1198
- var fs3 = require("node:fs");
1197
+ var path24 = require("node:path");
1198
+ var fs4 = require("node:fs");
1199
1199
  var process6 = require("node:process");
1200
1200
  var { Argument: Argument2, humanReadableArgName } = require_argument();
1201
1201
  var { CommanderError: CommanderError2 } = require_error();
@@ -1621,9 +1621,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
1621
1621
  if (fn) {
1622
1622
  this._exitCallback = fn;
1623
1623
  } else {
1624
- this._exitCallback = (err18) => {
1625
- if (err18.code !== "commander.executeSubCommandAsync") {
1626
- throw err18;
1624
+ this._exitCallback = (err20) => {
1625
+ if (err20.code !== "commander.executeSubCommandAsync") {
1626
+ throw err20;
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 (err18) {
1703
- if (err18.code === "commander.invalidArgument") {
1704
- const message = `${invalidArgumentMessage} ${err18.message}`;
1705
- this.error(message, { exitCode: err18.exitCode, code: err18.code });
1702
+ } catch (err20) {
1703
+ if (err20.code === "commander.invalidArgument") {
1704
+ const message = `${invalidArgumentMessage} ${err20.message}`;
1705
+ this.error(message, { exitCode: err20.exitCode, code: err20.code });
1706
1706
  }
1707
- throw err18;
1707
+ throw err20;
1708
1708
  }
1709
1709
  }
1710
1710
  /**
@@ -2189,7 +2189,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
2189
2189
  * @param {string} subcommandName
2190
2190
  */
2191
2191
  _checkForMissingExecutable(executableFile, executableDir, subcommandName) {
2192
- if (fs3.existsSync(executableFile)) return;
2192
+ if (fs4.existsSync(executableFile)) return;
2193
2193
  const executableDirMessage = executableDir ? `searched for local subcommand relative to directory '${executableDir}'` : "no directory for search for local subcommand, use .executableDir() to supply a custom directory";
2194
2194
  const executableMissing = `'${executableFile}' does not exist
2195
2195
  - if '${subcommandName}' is not meant to be an executable command, remove description parameter from '.command()' and use '.description()' instead
@@ -2207,11 +2207,11 @@ Expecting one of '${allowedValues.join("', '")}'`);
2207
2207
  let launchWithNode = false;
2208
2208
  const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
2209
2209
  function findFile(baseDir, baseName) {
2210
- const localBin = path23.resolve(baseDir, baseName);
2211
- if (fs3.existsSync(localBin)) return localBin;
2212
- if (sourceExt.includes(path23.extname(baseName))) return void 0;
2210
+ const localBin = path24.resolve(baseDir, baseName);
2211
+ if (fs4.existsSync(localBin)) return localBin;
2212
+ if (sourceExt.includes(path24.extname(baseName))) return void 0;
2213
2213
  const foundExt = sourceExt.find(
2214
- (ext) => fs3.existsSync(`${localBin}${ext}`)
2214
+ (ext) => fs4.existsSync(`${localBin}${ext}`)
2215
2215
  );
2216
2216
  if (foundExt) return `${localBin}${foundExt}`;
2217
2217
  return void 0;
@@ -2223,21 +2223,21 @@ Expecting one of '${allowedValues.join("', '")}'`);
2223
2223
  if (this._scriptPath) {
2224
2224
  let resolvedScriptPath;
2225
2225
  try {
2226
- resolvedScriptPath = fs3.realpathSync(this._scriptPath);
2226
+ resolvedScriptPath = fs4.realpathSync(this._scriptPath);
2227
2227
  } catch {
2228
2228
  resolvedScriptPath = this._scriptPath;
2229
2229
  }
2230
- executableDir = path23.resolve(
2231
- path23.dirname(resolvedScriptPath),
2230
+ executableDir = path24.resolve(
2231
+ path24.dirname(resolvedScriptPath),
2232
2232
  executableDir
2233
2233
  );
2234
2234
  }
2235
2235
  if (executableDir) {
2236
2236
  let localFile = findFile(executableDir, executableFile);
2237
2237
  if (!localFile && !subcommand._executableFile && this._scriptPath) {
2238
- const legacyName = path23.basename(
2238
+ const legacyName = path24.basename(
2239
2239
  this._scriptPath,
2240
- path23.extname(this._scriptPath)
2240
+ path24.extname(this._scriptPath)
2241
2241
  );
2242
2242
  if (legacyName !== this._name) {
2243
2243
  localFile = findFile(
@@ -2248,7 +2248,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
2248
2248
  }
2249
2249
  executableFile = localFile || executableFile;
2250
2250
  }
2251
- launchWithNode = sourceExt.includes(path23.extname(executableFile));
2251
+ launchWithNode = sourceExt.includes(path24.extname(executableFile));
2252
2252
  let proc;
2253
2253
  if (process6.platform !== "win32") {
2254
2254
  if (launchWithNode) {
@@ -2293,14 +2293,14 @@ Expecting one of '${allowedValues.join("', '")}'`);
2293
2293
  );
2294
2294
  }
2295
2295
  });
2296
- proc.on("error", (err18) => {
2297
- if (err18.code === "ENOENT") {
2296
+ proc.on("error", (err20) => {
2297
+ if (err20.code === "ENOENT") {
2298
2298
  this._checkForMissingExecutable(
2299
2299
  executableFile,
2300
2300
  executableDir,
2301
2301
  subcommand._name
2302
2302
  );
2303
- } else if (err18.code === "EACCES") {
2303
+ } else if (err20.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 = err18;
2314
+ wrappedError.nestedError = err20;
2315
2315
  exitCallback(wrappedError);
2316
2316
  }
2317
2317
  });
@@ -3163,7 +3163,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
3163
3163
  * @return {Command}
3164
3164
  */
3165
3165
  nameFromFilename(filename) {
3166
- this._name = path23.basename(filename, path23.extname(filename));
3166
+ this._name = path24.basename(filename, path24.extname(filename));
3167
3167
  return this;
3168
3168
  }
3169
3169
  /**
@@ -3177,9 +3177,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
3177
3177
  * @param {string} [path]
3178
3178
  * @return {(string|null|Command)}
3179
3179
  */
3180
- executableDir(path24) {
3181
- if (path24 === void 0) return this._executableDir;
3182
- this._executableDir = path24;
3180
+ executableDir(path25) {
3181
+ if (path25 === void 0) return this._executableDir;
3182
+ this._executableDir = path25;
3183
3183
  return this;
3184
3184
  }
3185
3185
  /**
@@ -3539,11 +3539,11 @@ var require_index_cjs = __commonJS({
3539
3539
  try {
3540
3540
  step(g3[n3](v2));
3541
3541
  } catch (e3) {
3542
- settle(q4[0][3], e3);
3542
+ settle2(q4[0][3], e3);
3543
3543
  }
3544
3544
  }
3545
3545
  function step(r3) {
3546
- r3.value instanceof __await2 ? Promise.resolve(r3.value.v).then(fulfill, reject) : settle(q4[0][2], r3);
3546
+ r3.value instanceof __await2 ? Promise.resolve(r3.value.v).then(fulfill, reject) : settle2(q4[0][2], r3);
3547
3547
  }
3548
3548
  function fulfill(value) {
3549
3549
  resume("next", value);
@@ -3551,7 +3551,7 @@ var require_index_cjs = __commonJS({
3551
3551
  function reject(value) {
3552
3552
  resume("throw", value);
3553
3553
  }
3554
- function settle(f6, v2) {
3554
+ function settle2(f6, v2) {
3555
3555
  if (f6(v2), q4.shift(), q4.length) resume(q4[0][0], q4[0][1]);
3556
3556
  }
3557
3557
  }
@@ -3577,17 +3577,17 @@ var require_index_cjs = __commonJS({
3577
3577
  function verb(n3) {
3578
3578
  i3[n3] = o3[n3] && function(v2) {
3579
3579
  return new Promise(function(resolve, reject) {
3580
- v2 = o3[n3](v2), settle(resolve, reject, v2.done, v2.value);
3580
+ v2 = o3[n3](v2), settle2(resolve, reject, v2.done, v2.value);
3581
3581
  });
3582
3582
  };
3583
3583
  }
3584
- function settle(resolve, reject, d, v2) {
3584
+ function settle2(resolve, reject, d, v2) {
3585
3585
  Promise.resolve(v2).then(function(v3) {
3586
3586
  resolve({ value: v3, done: d });
3587
3587
  }, reject);
3588
3588
  }
3589
3589
  }
3590
- var ResultAsync12 = class _ResultAsync {
3590
+ var ResultAsync14 = class _ResultAsync {
3591
3591
  constructor(res) {
3592
3592
  this._promise = res;
3593
3593
  }
@@ -3688,8 +3688,8 @@ var require_index_cjs = __commonJS({
3688
3688
  return new Ok(res.value);
3689
3689
  })));
3690
3690
  }
3691
- match(ok20, _err) {
3692
- return this._promise.then((res) => res.match(ok20, _err));
3691
+ match(ok24, _err) {
3692
+ return this._promise.then((res) => res.match(ok24, _err));
3693
3693
  }
3694
3694
  unwrapOr(t) {
3695
3695
  return this._promise.then((res) => res.unwrapOr(t));
@@ -3726,19 +3726,19 @@ var require_index_cjs = __commonJS({
3726
3726
  }
3727
3727
  };
3728
3728
  function okAsync8(value) {
3729
- return new ResultAsync12(Promise.resolve(new Ok(value)));
3729
+ return new ResultAsync14(Promise.resolve(new Ok(value)));
3730
3730
  }
3731
- function errAsync8(err19) {
3732
- return new ResultAsync12(Promise.resolve(new Err(err19)));
3731
+ function errAsync8(err21) {
3732
+ return new ResultAsync14(Promise.resolve(new Err(err21)));
3733
3733
  }
3734
- var fromPromise = ResultAsync12.fromPromise;
3735
- var fromSafePromise2 = ResultAsync12.fromSafePromise;
3736
- var fromAsyncThrowable10 = ResultAsync12.fromThrowable;
3734
+ var fromPromise = ResultAsync14.fromPromise;
3735
+ var fromSafePromise2 = ResultAsync14.fromSafePromise;
3736
+ var fromAsyncThrowable10 = ResultAsync14.fromThrowable;
3737
3737
  var combineResultList = (resultList) => {
3738
- let acc = ok19([]);
3738
+ let acc = ok21([]);
3739
3739
  for (const result of resultList) {
3740
3740
  if (result.isErr()) {
3741
- acc = err18(result.error);
3741
+ acc = err20(result.error);
3742
3742
  break;
3743
3743
  } else {
3744
3744
  acc.map((list) => list.push(result.value));
@@ -3746,34 +3746,34 @@ var require_index_cjs = __commonJS({
3746
3746
  }
3747
3747
  return acc;
3748
3748
  };
3749
- var combineResultAsyncList = (asyncResultList) => ResultAsync12.fromSafePromise(Promise.all(asyncResultList)).andThen(combineResultList);
3749
+ var combineResultAsyncList = (asyncResultList) => ResultAsync14.fromSafePromise(Promise.all(asyncResultList)).andThen(combineResultList);
3750
3750
  var combineResultListWithAllErrors = (resultList) => {
3751
- let acc = ok19([]);
3751
+ let acc = ok21([]);
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 = err18([result.error]);
3756
+ acc = err20([result.error]);
3757
3757
  } else if (result.isOk() && acc.isOk()) {
3758
3758
  acc.value.push(result.value);
3759
3759
  }
3760
3760
  }
3761
3761
  return acc;
3762
3762
  };
3763
- var combineResultAsyncListWithAllErrors = (asyncResultList) => ResultAsync12.fromSafePromise(Promise.all(asyncResultList)).andThen(combineResultListWithAllErrors);
3763
+ var combineResultAsyncListWithAllErrors = (asyncResultList) => ResultAsync14.fromSafePromise(Promise.all(asyncResultList)).andThen(combineResultListWithAllErrors);
3764
3764
  exports2.Result = void 0;
3765
3765
  (function(Result3) {
3766
- function fromThrowable14(fn, errorFn) {
3766
+ function fromThrowable16(fn, errorFn) {
3767
3767
  return (...args) => {
3768
3768
  try {
3769
3769
  const result = fn(...args);
3770
- return ok19(result);
3770
+ return ok21(result);
3771
3771
  } catch (e3) {
3772
- return err18(errorFn ? errorFn(e3) : e3);
3772
+ return err20(errorFn ? errorFn(e3) : e3);
3773
3773
  }
3774
3774
  };
3775
3775
  }
3776
- Result3.fromThrowable = fromThrowable14;
3776
+ Result3.fromThrowable = fromThrowable16;
3777
3777
  function combine(resultList) {
3778
3778
  return combineResultList(resultList);
3779
3779
  }
@@ -3783,16 +3783,16 @@ var require_index_cjs = __commonJS({
3783
3783
  }
3784
3784
  Result3.combineWithAllErrors = combineWithAllErrors;
3785
3785
  })(exports2.Result || (exports2.Result = {}));
3786
- function ok19(value) {
3786
+ function ok21(value) {
3787
3787
  return new Ok(value);
3788
3788
  }
3789
- function err18(err19) {
3790
- return new Err(err19);
3789
+ function err20(err21) {
3790
+ return new Err(err21);
3791
3791
  }
3792
3792
  function safeTry(body) {
3793
3793
  const n3 = body().next();
3794
3794
  if (n3 instanceof Promise) {
3795
- return new ResultAsync12(n3.then((r3) => r3.value));
3795
+ return new ResultAsync14(n3.then((r3) => r3.value));
3796
3796
  }
3797
3797
  return n3.value;
3798
3798
  }
@@ -3807,11 +3807,11 @@ var require_index_cjs = __commonJS({
3807
3807
  return !this.isOk();
3808
3808
  }
3809
3809
  map(f6) {
3810
- return ok19(f6(this.value));
3810
+ return ok21(f6(this.value));
3811
3811
  }
3812
3812
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
3813
3813
  mapErr(_f) {
3814
- return ok19(this.value);
3814
+ return ok21(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 ok19(this.value);
3829
+ return ok21(this.value);
3830
3830
  }
3831
3831
  orTee(_f) {
3832
- return ok19(this.value);
3832
+ return ok21(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 ok19(this.value);
3836
+ return ok21(this.value);
3837
3837
  }
3838
3838
  asyncAndThen(f6) {
3839
3839
  return f6(this.value);
@@ -3843,15 +3843,15 @@ var require_index_cjs = __commonJS({
3843
3843
  return f6(this.value).map(() => this.value);
3844
3844
  }
3845
3845
  asyncMap(f6) {
3846
- return ResultAsync12.fromSafePromise(f6(this.value));
3846
+ return ResultAsync14.fromSafePromise(f6(this.value));
3847
3847
  }
3848
3848
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
3849
3849
  unwrapOr(_v) {
3850
3850
  return this.value;
3851
3851
  }
3852
3852
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
3853
- match(ok20, _err) {
3854
- return ok20(this.value);
3853
+ match(ok24, _err) {
3854
+ return ok24(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 err18(this.error);
3885
+ return err20(this.error);
3886
3886
  }
3887
3887
  mapErr(f6) {
3888
- return err18(f6(this.error));
3888
+ return err20(f6(this.error));
3889
3889
  }
3890
3890
  andThrough(_f) {
3891
- return err18(this.error);
3891
+ return err20(this.error);
3892
3892
  }
3893
3893
  andTee(_f) {
3894
- return err18(this.error);
3894
+ return err20(this.error);
3895
3895
  }
3896
3896
  orTee(f6) {
3897
3897
  try {
3898
3898
  f6(this.error);
3899
3899
  } catch (e3) {
3900
3900
  }
3901
- return err18(this.error);
3901
+ return err20(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 err18(this.error);
3905
+ return err20(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, err19) {
3926
- return err19(this.error);
3925
+ match(_ok, err21) {
3926
+ return err21(this.error);
3927
3927
  }
3928
3928
  safeUnwrap() {
3929
3929
  const error48 = this.error;
3930
3930
  return (function* () {
3931
- yield err18(error48);
3931
+ yield err20(error48);
3932
3932
  throw new Error("Do not use this generator out of `safeTry`");
3933
3933
  })();
3934
3934
  }
@@ -3944,17 +3944,17 @@ var require_index_cjs = __commonJS({
3944
3944
  return self2;
3945
3945
  }
3946
3946
  };
3947
- var fromThrowable13 = exports2.Result.fromThrowable;
3947
+ var fromThrowable15 = exports2.Result.fromThrowable;
3948
3948
  exports2.Err = Err;
3949
3949
  exports2.Ok = Ok;
3950
- exports2.ResultAsync = ResultAsync12;
3951
- exports2.err = err18;
3950
+ exports2.ResultAsync = ResultAsync14;
3951
+ exports2.err = err20;
3952
3952
  exports2.errAsync = errAsync8;
3953
3953
  exports2.fromAsyncThrowable = fromAsyncThrowable10;
3954
3954
  exports2.fromPromise = fromPromise;
3955
3955
  exports2.fromSafePromise = fromSafePromise2;
3956
- exports2.fromThrowable = fromThrowable13;
3957
- exports2.ok = ok19;
3956
+ exports2.fromThrowable = fromThrowable15;
3957
+ exports2.ok = ok21;
3958
3958
  exports2.okAsync = okAsync8;
3959
3959
  exports2.safeTry = safeTry;
3960
3960
  }
@@ -5052,15 +5052,15 @@ var require_route = __commonJS({
5052
5052
  };
5053
5053
  }
5054
5054
  function wrapConversion(toModel, graph) {
5055
- const path23 = [graph[toModel].parent, toModel];
5055
+ const path24 = [graph[toModel].parent, toModel];
5056
5056
  let fn = conversions[graph[toModel].parent][toModel];
5057
5057
  let cur = graph[toModel].parent;
5058
5058
  while (graph[cur].parent) {
5059
- path23.unshift(graph[cur].parent);
5059
+ path24.unshift(graph[cur].parent);
5060
5060
  fn = link(conversions[graph[cur].parent][cur], fn);
5061
5061
  cur = graph[cur].parent;
5062
5062
  }
5063
- fn.conversion = path23;
5063
+ fn.conversion = path24;
5064
5064
  return fn;
5065
5065
  }
5066
5066
  module2.exports = function(fromModel) {
@@ -11116,13 +11116,13 @@ var require_lib2 = __commonJS({
11116
11116
  exports2.analyse = analyse;
11117
11117
  var detectFile = (filepath, opts = {}) => new Promise((resolve, reject) => {
11118
11118
  let fd;
11119
- const fs3 = (0, node_1.default)();
11120
- const handler = (err18, buffer) => {
11119
+ const fs4 = (0, node_1.default)();
11120
+ const handler = (err20, buffer) => {
11121
11121
  if (fd) {
11122
- fs3.closeSync(fd);
11122
+ fs4.closeSync(fd);
11123
11123
  }
11124
- if (err18) {
11125
- reject(err18);
11124
+ if (err20) {
11125
+ reject(err20);
11126
11126
  } else if (buffer) {
11127
11127
  resolve((0, exports2.detect)(buffer));
11128
11128
  } else {
@@ -11131,11 +11131,11 @@ var require_lib2 = __commonJS({
11131
11131
  };
11132
11132
  const sampleSize = (opts === null || opts === void 0 ? void 0 : opts.sampleSize) || 0;
11133
11133
  if (sampleSize > 0) {
11134
- fd = fs3.openSync(filepath, "r");
11134
+ fd = fs4.openSync(filepath, "r");
11135
11135
  let sample = Buffer.allocUnsafe(sampleSize);
11136
- fs3.read(fd, sample, 0, sampleSize, opts.offset, (err18, bytesRead) => {
11137
- if (err18) {
11138
- handler(err18, null);
11136
+ fs4.read(fd, sample, 0, sampleSize, opts.offset, (err20, bytesRead) => {
11137
+ if (err20) {
11138
+ handler(err20, null);
11139
11139
  } else {
11140
11140
  if (bytesRead < sampleSize) {
11141
11141
  sample = sample.subarray(0, bytesRead);
@@ -11145,22 +11145,22 @@ var require_lib2 = __commonJS({
11145
11145
  });
11146
11146
  return;
11147
11147
  }
11148
- fs3.readFile(filepath, handler);
11148
+ fs4.readFile(filepath, handler);
11149
11149
  });
11150
11150
  exports2.detectFile = detectFile;
11151
11151
  var detectFileSync = (filepath, opts = {}) => {
11152
- const fs3 = (0, node_1.default)();
11152
+ const fs4 = (0, node_1.default)();
11153
11153
  if (opts && opts.sampleSize) {
11154
- const fd = fs3.openSync(filepath, "r");
11154
+ const fd = fs4.openSync(filepath, "r");
11155
11155
  let sample = Buffer.allocUnsafe(opts.sampleSize);
11156
- const bytesRead = fs3.readSync(fd, sample, 0, opts.sampleSize, opts.offset);
11156
+ const bytesRead = fs4.readSync(fd, sample, 0, opts.sampleSize, opts.offset);
11157
11157
  if (bytesRead < opts.sampleSize) {
11158
11158
  sample = sample.subarray(0, bytesRead);
11159
11159
  }
11160
- fs3.closeSync(fd);
11160
+ fs4.closeSync(fd);
11161
11161
  return (0, exports2.detect)(sample);
11162
11162
  }
11163
- return (0, exports2.detect)(fs3.readFileSync(filepath));
11163
+ return (0, exports2.detect)(fs4.readFileSync(filepath));
11164
11164
  };
11165
11165
  exports2.detectFileSync = detectFileSync;
11166
11166
  exports2.default = {
@@ -15025,8 +15025,8 @@ var require_package = __commonJS({
15025
15025
  // ../../node_modules/.pnpm/dotenv@16.6.1/node_modules/dotenv/lib/main.js
15026
15026
  var require_main = __commonJS({
15027
15027
  "../../node_modules/.pnpm/dotenv@16.6.1/node_modules/dotenv/lib/main.js"(exports2, module2) {
15028
- var fs3 = require("fs");
15029
- var path23 = require("path");
15028
+ var fs4 = require("fs");
15029
+ var path24 = require("path");
15030
15030
  var os4 = require("os");
15031
15031
  var crypto = require("crypto");
15032
15032
  var packageJson = require_package();
@@ -15057,9 +15057,9 @@ var require_main = __commonJS({
15057
15057
  options.path = vaultPath;
15058
15058
  const result = DotenvModule.configDotenv(options);
15059
15059
  if (!result.parsed) {
15060
- const err18 = new Error(`MISSING_DATA: Cannot parse ${vaultPath} for an unknown reason`);
15061
- err18.code = "MISSING_DATA";
15062
- throw err18;
15060
+ const err20 = new Error(`MISSING_DATA: Cannot parse ${vaultPath} for an unknown reason`);
15061
+ err20.code = "MISSING_DATA";
15062
+ throw err20;
15063
15063
  }
15064
15064
  const keys = _dotenvKey(options).split(",");
15065
15065
  const length = keys.length;
@@ -15102,30 +15102,30 @@ var require_main = __commonJS({
15102
15102
  uri = new URL(dotenvKey);
15103
15103
  } catch (error48) {
15104
15104
  if (error48.code === "ERR_INVALID_URL") {
15105
- const err18 = new Error("INVALID_DOTENV_KEY: Wrong format. Must be in valid uri format like dotenv://:key_1234@dotenvx.com/vault/.env.vault?environment=development");
15106
- err18.code = "INVALID_DOTENV_KEY";
15107
- throw err18;
15105
+ const err20 = new Error("INVALID_DOTENV_KEY: Wrong format. Must be in valid uri format like dotenv://:key_1234@dotenvx.com/vault/.env.vault?environment=development");
15106
+ err20.code = "INVALID_DOTENV_KEY";
15107
+ throw err20;
15108
15108
  }
15109
15109
  throw error48;
15110
15110
  }
15111
15111
  const key = uri.password;
15112
15112
  if (!key) {
15113
- const err18 = new Error("INVALID_DOTENV_KEY: Missing key part");
15114
- err18.code = "INVALID_DOTENV_KEY";
15115
- throw err18;
15113
+ const err20 = new Error("INVALID_DOTENV_KEY: Missing key part");
15114
+ err20.code = "INVALID_DOTENV_KEY";
15115
+ throw err20;
15116
15116
  }
15117
15117
  const environment = uri.searchParams.get("environment");
15118
15118
  if (!environment) {
15119
- const err18 = new Error("INVALID_DOTENV_KEY: Missing environment part");
15120
- err18.code = "INVALID_DOTENV_KEY";
15121
- throw err18;
15119
+ const err20 = new Error("INVALID_DOTENV_KEY: Missing environment part");
15120
+ err20.code = "INVALID_DOTENV_KEY";
15121
+ throw err20;
15122
15122
  }
15123
15123
  const environmentKey = `DOTENV_VAULT_${environment.toUpperCase()}`;
15124
15124
  const ciphertext = result.parsed[environmentKey];
15125
15125
  if (!ciphertext) {
15126
- const err18 = new Error(`NOT_FOUND_DOTENV_ENVIRONMENT: Cannot locate environment ${environmentKey} in your .env.vault file.`);
15127
- err18.code = "NOT_FOUND_DOTENV_ENVIRONMENT";
15128
- throw err18;
15126
+ const err20 = new Error(`NOT_FOUND_DOTENV_ENVIRONMENT: Cannot locate environment ${environmentKey} in your .env.vault file.`);
15127
+ err20.code = "NOT_FOUND_DOTENV_ENVIRONMENT";
15128
+ throw err20;
15129
15129
  }
15130
15130
  return { ciphertext, key };
15131
15131
  }
@@ -15134,7 +15134,7 @@ var require_main = __commonJS({
15134
15134
  if (options && options.path && options.path.length > 0) {
15135
15135
  if (Array.isArray(options.path)) {
15136
15136
  for (const filepath of options.path) {
15137
- if (fs3.existsSync(filepath)) {
15137
+ if (fs4.existsSync(filepath)) {
15138
15138
  possibleVaultPath = filepath.endsWith(".vault") ? filepath : `${filepath}.vault`;
15139
15139
  }
15140
15140
  }
@@ -15142,15 +15142,15 @@ var require_main = __commonJS({
15142
15142
  possibleVaultPath = options.path.endsWith(".vault") ? options.path : `${options.path}.vault`;
15143
15143
  }
15144
15144
  } else {
15145
- possibleVaultPath = path23.resolve(process.cwd(), ".env.vault");
15145
+ possibleVaultPath = path24.resolve(process.cwd(), ".env.vault");
15146
15146
  }
15147
- if (fs3.existsSync(possibleVaultPath)) {
15147
+ if (fs4.existsSync(possibleVaultPath)) {
15148
15148
  return possibleVaultPath;
15149
15149
  }
15150
15150
  return null;
15151
15151
  }
15152
15152
  function _resolveHome(envPath) {
15153
- return envPath[0] === "~" ? path23.join(os4.homedir(), envPath.slice(1)) : envPath;
15153
+ return envPath[0] === "~" ? path24.join(os4.homedir(), envPath.slice(1)) : envPath;
15154
15154
  }
15155
15155
  function _configVault(options) {
15156
15156
  const debug = Boolean(options && options.debug);
@@ -15167,7 +15167,7 @@ var require_main = __commonJS({
15167
15167
  return { parsed };
15168
15168
  }
15169
15169
  function configDotenv(options) {
15170
- const dotenvPath = path23.resolve(process.cwd(), ".env");
15170
+ const dotenvPath = path24.resolve(process.cwd(), ".env");
15171
15171
  let encoding = "utf8";
15172
15172
  const debug = Boolean(options && options.debug);
15173
15173
  const quiet = options && "quiet" in options ? options.quiet : true;
@@ -15191,13 +15191,13 @@ var require_main = __commonJS({
15191
15191
  }
15192
15192
  let lastError;
15193
15193
  const parsedAll = {};
15194
- for (const path24 of optionPaths) {
15194
+ for (const path25 of optionPaths) {
15195
15195
  try {
15196
- const parsed = DotenvModule.parse(fs3.readFileSync(path24, { encoding }));
15196
+ const parsed = DotenvModule.parse(fs4.readFileSync(path25, { encoding }));
15197
15197
  DotenvModule.populate(parsedAll, parsed, options);
15198
15198
  } catch (e3) {
15199
15199
  if (debug) {
15200
- _debug(`Failed to load ${path24} ${e3.message}`);
15200
+ _debug(`Failed to load ${path25} ${e3.message}`);
15201
15201
  }
15202
15202
  lastError = e3;
15203
15203
  }
@@ -15212,7 +15212,7 @@ var require_main = __commonJS({
15212
15212
  const shortPaths = [];
15213
15213
  for (const filePath of optionPaths) {
15214
15214
  try {
15215
- const relative = path23.relative(process.cwd(), filePath);
15215
+ const relative = path24.relative(process.cwd(), filePath);
15216
15216
  shortPaths.push(relative);
15217
15217
  } catch (e3) {
15218
15218
  if (debug) {
@@ -15255,13 +15255,13 @@ var require_main = __commonJS({
15255
15255
  const invalidKeyLength = error48.message === "Invalid key length";
15256
15256
  const decryptionFailed = error48.message === "Unsupported state or unable to authenticate data";
15257
15257
  if (isRange || invalidKeyLength) {
15258
- const err18 = new Error("INVALID_DOTENV_KEY: It must be 64 characters long (or more)");
15259
- err18.code = "INVALID_DOTENV_KEY";
15260
- throw err18;
15258
+ const err20 = new Error("INVALID_DOTENV_KEY: It must be 64 characters long (or more)");
15259
+ err20.code = "INVALID_DOTENV_KEY";
15260
+ throw err20;
15261
15261
  } else if (decryptionFailed) {
15262
- const err18 = new Error("DECRYPTION_FAILED: Please check your DOTENV_KEY");
15263
- err18.code = "DECRYPTION_FAILED";
15264
- throw err18;
15262
+ const err20 = new Error("DECRYPTION_FAILED: Please check your DOTENV_KEY");
15263
+ err20.code = "DECRYPTION_FAILED";
15264
+ throw err20;
15265
15265
  } else {
15266
15266
  throw error48;
15267
15267
  }
@@ -15271,9 +15271,9 @@ var require_main = __commonJS({
15271
15271
  const debug = Boolean(options && options.debug);
15272
15272
  const override = Boolean(options && options.override);
15273
15273
  if (typeof parsed !== "object") {
15274
- const err18 = new Error("OBJECT_REQUIRED: Please check the processEnv argument being passed to populate");
15275
- err18.code = "OBJECT_REQUIRED";
15276
- throw err18;
15274
+ const err20 = new Error("OBJECT_REQUIRED: Please check the processEnv argument being passed to populate");
15275
+ err20.code = "OBJECT_REQUIRED";
15276
+ throw err20;
15277
15277
  }
15278
15278
  for (const key of Object.keys(parsed)) {
15279
15279
  if (Object.prototype.hasOwnProperty.call(processEnv, key)) {
@@ -15384,7 +15384,7 @@ var require_path = __commonJS({
15384
15384
  Object.defineProperty(exports2, "__esModule", { value: true });
15385
15385
  exports2.convertPosixPathToPattern = exports2.convertWindowsPathToPattern = exports2.convertPathToPattern = exports2.escapePosixPath = exports2.escapeWindowsPath = exports2.escape = exports2.removeLeadingDotSegment = exports2.makeAbsolute = exports2.unixify = void 0;
15386
15386
  var os4 = require("os");
15387
- var path23 = require("path");
15387
+ var path24 = require("path");
15388
15388
  var IS_WINDOWS_PLATFORM = os4.platform() === "win32";
15389
15389
  var LEADING_DOT_SEGMENT_CHARACTERS_COUNT = 2;
15390
15390
  var POSIX_UNESCAPED_GLOB_SYMBOLS_RE = /(\\?)([()*?[\]{|}]|^!|[!+@](?=\()|\\(?![!()*+?@[\]{|}]))/g;
@@ -15396,7 +15396,7 @@ var require_path = __commonJS({
15396
15396
  }
15397
15397
  exports2.unixify = unixify;
15398
15398
  function makeAbsolute(cwd, filepath) {
15399
- return path23.resolve(cwd, filepath);
15399
+ return path24.resolve(cwd, filepath);
15400
15400
  }
15401
15401
  exports2.makeAbsolute = makeAbsolute;
15402
15402
  function removeLeadingDotSegment(entry) {
@@ -16693,7 +16693,7 @@ var require_braces = __commonJS({
16693
16693
  var require_constants2 = __commonJS({
16694
16694
  "../../node_modules/.pnpm/picomatch@2.3.2/node_modules/picomatch/lib/constants.js"(exports2, module2) {
16695
16695
  "use strict";
16696
- var path23 = require("path");
16696
+ var path24 = require("path");
16697
16697
  var WIN_SLASH = "\\\\/";
16698
16698
  var WIN_NO_SLASH = `[^${WIN_SLASH}]`;
16699
16699
  var DEFAULT_MAX_EXTGLOB_RECURSION = 0;
@@ -16867,7 +16867,7 @@ var require_constants2 = __commonJS({
16867
16867
  /* | */
16868
16868
  CHAR_ZERO_WIDTH_NOBREAK_SPACE: 65279,
16869
16869
  /* \uFEFF */
16870
- SEP: path23.sep,
16870
+ SEP: path24.sep,
16871
16871
  /**
16872
16872
  * Create EXTGLOB_CHARS
16873
16873
  */
@@ -16894,7 +16894,7 @@ var require_constants2 = __commonJS({
16894
16894
  var require_utils3 = __commonJS({
16895
16895
  "../../node_modules/.pnpm/picomatch@2.3.2/node_modules/picomatch/lib/utils.js"(exports2) {
16896
16896
  "use strict";
16897
- var path23 = require("path");
16897
+ var path24 = require("path");
16898
16898
  var win32 = process.platform === "win32";
16899
16899
  var {
16900
16900
  REGEX_BACKSLASH,
@@ -16923,7 +16923,7 @@ var require_utils3 = __commonJS({
16923
16923
  if (options && typeof options.windows === "boolean") {
16924
16924
  return options.windows;
16925
16925
  }
16926
- return win32 === true || path23.sep === "\\";
16926
+ return win32 === true || path24.sep === "\\";
16927
16927
  };
16928
16928
  exports2.escapeLast = (input, char, lastIdx) => {
16929
16929
  const idx = input.lastIndexOf(char, lastIdx);
@@ -18287,7 +18287,7 @@ var require_parse2 = __commonJS({
18287
18287
  var require_picomatch = __commonJS({
18288
18288
  "../../node_modules/.pnpm/picomatch@2.3.2/node_modules/picomatch/lib/picomatch.js"(exports2, module2) {
18289
18289
  "use strict";
18290
- var path23 = require("path");
18290
+ var path24 = require("path");
18291
18291
  var scan = require_scan();
18292
18292
  var parse3 = require_parse2();
18293
18293
  var utils = require_utils3();
@@ -18372,7 +18372,7 @@ var require_picomatch = __commonJS({
18372
18372
  };
18373
18373
  picomatch.matchBase = (input, glob, options, posix = utils.isWindows(options)) => {
18374
18374
  const regex = glob instanceof RegExp ? glob : picomatch.makeRe(glob, options);
18375
- return regex.test(path23.basename(input));
18375
+ return regex.test(path24.basename(input));
18376
18376
  };
18377
18377
  picomatch.isMatch = (str2, patterns, options) => picomatch(patterns, options)(str2);
18378
18378
  picomatch.parse = (pattern, options) => {
@@ -18414,8 +18414,8 @@ var require_picomatch = __commonJS({
18414
18414
  try {
18415
18415
  const opts = options || {};
18416
18416
  return new RegExp(source, opts.flags || (opts.nocase ? "i" : ""));
18417
- } catch (err18) {
18418
- if (options && options.debug === true) throw err18;
18417
+ } catch (err20) {
18418
+ if (options && options.debug === true) throw err20;
18419
18419
  return /$^/;
18420
18420
  }
18421
18421
  };
@@ -18599,7 +18599,7 @@ var require_pattern = __commonJS({
18599
18599
  "use strict";
18600
18600
  Object.defineProperty(exports2, "__esModule", { value: true });
18601
18601
  exports2.isAbsolute = exports2.partitionAbsoluteAndRelative = exports2.removeDuplicateSlashes = exports2.matchAny = exports2.convertPatternsToRe = exports2.makeRe = exports2.getPatternParts = exports2.expandBraceExpansion = exports2.expandPatternsWithBraceExpansion = exports2.isAffectDepthOfReadingPattern = exports2.endsWithSlashGlobStar = exports2.hasGlobStar = exports2.getBaseDirectory = exports2.isPatternRelatedToParentDirectory = exports2.getPatternsOutsideCurrentDirectory = exports2.getPatternsInsideCurrentDirectory = exports2.getPositivePatterns = exports2.getNegativePatterns = exports2.isPositivePattern = exports2.isNegativePattern = exports2.convertToNegativePattern = exports2.convertToPositivePattern = exports2.isDynamicPattern = exports2.isStaticPattern = void 0;
18602
- var path23 = require("path");
18602
+ var path24 = require("path");
18603
18603
  var globParent = require_glob_parent();
18604
18604
  var micromatch = require_micromatch();
18605
18605
  var GLOBSTAR = "**";
@@ -18694,7 +18694,7 @@ var require_pattern = __commonJS({
18694
18694
  }
18695
18695
  exports2.endsWithSlashGlobStar = endsWithSlashGlobStar;
18696
18696
  function isAffectDepthOfReadingPattern(pattern) {
18697
- const basename = path23.basename(pattern);
18697
+ const basename = path24.basename(pattern);
18698
18698
  return endsWithSlashGlobStar(pattern) || isStaticPattern(basename);
18699
18699
  }
18700
18700
  exports2.isAffectDepthOfReadingPattern = isAffectDepthOfReadingPattern;
@@ -18752,7 +18752,7 @@ var require_pattern = __commonJS({
18752
18752
  }
18753
18753
  exports2.partitionAbsoluteAndRelative = partitionAbsoluteAndRelative;
18754
18754
  function isAbsolute(pattern) {
18755
- return path23.isAbsolute(pattern);
18755
+ return path24.isAbsolute(pattern);
18756
18756
  }
18757
18757
  exports2.isAbsolute = isAbsolute;
18758
18758
  }
@@ -18822,8 +18822,8 @@ var require_merge2 = __commonJS({
18822
18822
  }
18823
18823
  next();
18824
18824
  }
18825
- function onerror(err18) {
18826
- mergedStream.emit("error", err18);
18825
+ function onerror(err20) {
18826
+ mergedStream.emit("error", err20);
18827
18827
  }
18828
18828
  if (stream._readableState.endEmitted) {
18829
18829
  return next();
@@ -18927,10 +18927,10 @@ var require_utils4 = __commonJS({
18927
18927
  exports2.array = array2;
18928
18928
  var errno = require_errno();
18929
18929
  exports2.errno = errno;
18930
- var fs3 = require_fs();
18931
- exports2.fs = fs3;
18932
- var path23 = require_path();
18933
- exports2.path = path23;
18930
+ var fs4 = require_fs();
18931
+ exports2.fs = fs4;
18932
+ var path24 = require_path();
18933
+ exports2.path = path24;
18934
18934
  var pattern = require_pattern();
18935
18935
  exports2.pattern = pattern;
18936
18936
  var stream = require_stream();
@@ -19042,8 +19042,8 @@ var require_async = __commonJS({
19042
19042
  "use strict";
19043
19043
  Object.defineProperty(exports2, "__esModule", { value: true });
19044
19044
  exports2.read = void 0;
19045
- function read(path23, settings, callback) {
19046
- settings.fs.lstat(path23, (lstatError, lstat) => {
19045
+ function read(path24, settings, callback) {
19046
+ settings.fs.lstat(path24, (lstatError, lstat) => {
19047
19047
  if (lstatError !== null) {
19048
19048
  callFailureCallback(callback, lstatError);
19049
19049
  return;
@@ -19052,7 +19052,7 @@ var require_async = __commonJS({
19052
19052
  callSuccessCallback(callback, lstat);
19053
19053
  return;
19054
19054
  }
19055
- settings.fs.stat(path23, (statError, stat2) => {
19055
+ settings.fs.stat(path24, (statError, stat2) => {
19056
19056
  if (statError !== null) {
19057
19057
  if (settings.throwErrorOnBrokenSymbolicLink) {
19058
19058
  callFailureCallback(callback, statError);
@@ -19084,13 +19084,13 @@ var require_sync = __commonJS({
19084
19084
  "use strict";
19085
19085
  Object.defineProperty(exports2, "__esModule", { value: true });
19086
19086
  exports2.read = void 0;
19087
- function read(path23, settings) {
19088
- const lstat = settings.fs.lstatSync(path23);
19087
+ function read(path24, settings) {
19088
+ const lstat = settings.fs.lstatSync(path24);
19089
19089
  if (!lstat.isSymbolicLink() || !settings.followSymbolicLink) {
19090
19090
  return lstat;
19091
19091
  }
19092
19092
  try {
19093
- const stat2 = settings.fs.statSync(path23);
19093
+ const stat2 = settings.fs.statSync(path24);
19094
19094
  if (settings.markSymbolicLink) {
19095
19095
  stat2.isSymbolicLink = () => true;
19096
19096
  }
@@ -19112,12 +19112,12 @@ var require_fs2 = __commonJS({
19112
19112
  "use strict";
19113
19113
  Object.defineProperty(exports2, "__esModule", { value: true });
19114
19114
  exports2.createFileSystemAdapter = exports2.FILE_SYSTEM_ADAPTER = void 0;
19115
- var fs3 = require("fs");
19115
+ var fs4 = require("fs");
19116
19116
  exports2.FILE_SYSTEM_ADAPTER = {
19117
- lstat: fs3.lstat,
19118
- stat: fs3.stat,
19119
- lstatSync: fs3.lstatSync,
19120
- statSync: fs3.statSync
19117
+ lstat: fs4.lstat,
19118
+ stat: fs4.stat,
19119
+ lstatSync: fs4.lstatSync,
19120
+ statSync: fs4.statSync
19121
19121
  };
19122
19122
  function createFileSystemAdapter(fsMethods) {
19123
19123
  if (fsMethods === void 0) {
@@ -19134,12 +19134,12 @@ var require_settings = __commonJS({
19134
19134
  "../../node_modules/.pnpm/@nodelib+fs.stat@2.0.5/node_modules/@nodelib/fs.stat/out/settings.js"(exports2) {
19135
19135
  "use strict";
19136
19136
  Object.defineProperty(exports2, "__esModule", { value: true });
19137
- var fs3 = require_fs2();
19137
+ var fs4 = require_fs2();
19138
19138
  var Settings = class {
19139
19139
  constructor(_options = {}) {
19140
19140
  this._options = _options;
19141
19141
  this.followSymbolicLink = this._getValue(this._options.followSymbolicLink, true);
19142
- this.fs = fs3.createFileSystemAdapter(this._options.fs);
19142
+ this.fs = fs4.createFileSystemAdapter(this._options.fs);
19143
19143
  this.markSymbolicLink = this._getValue(this._options.markSymbolicLink, false);
19144
19144
  this.throwErrorOnBrokenSymbolicLink = this._getValue(this._options.throwErrorOnBrokenSymbolicLink, true);
19145
19145
  }
@@ -19161,17 +19161,17 @@ var require_out = __commonJS({
19161
19161
  var sync = require_sync();
19162
19162
  var settings_1 = require_settings();
19163
19163
  exports2.Settings = settings_1.default;
19164
- function stat2(path23, optionsOrSettingsOrCallback, callback) {
19164
+ function stat2(path24, optionsOrSettingsOrCallback, callback) {
19165
19165
  if (typeof optionsOrSettingsOrCallback === "function") {
19166
- async.read(path23, getSettings(), optionsOrSettingsOrCallback);
19166
+ async.read(path24, getSettings(), optionsOrSettingsOrCallback);
19167
19167
  return;
19168
19168
  }
19169
- async.read(path23, getSettings(optionsOrSettingsOrCallback), callback);
19169
+ async.read(path24, getSettings(optionsOrSettingsOrCallback), callback);
19170
19170
  }
19171
19171
  exports2.stat = stat2;
19172
- function statSync2(path23, optionsOrSettings) {
19172
+ function statSync2(path24, optionsOrSettings) {
19173
19173
  const settings = getSettings(optionsOrSettings);
19174
- return sync.read(path23, settings);
19174
+ return sync.read(path24, settings);
19175
19175
  }
19176
19176
  exports2.statSync = statSync2;
19177
19177
  function getSettings(settingsOrOptions = {}) {
@@ -19187,8 +19187,8 @@ var require_out = __commonJS({
19187
19187
  var require_queue_microtask = __commonJS({
19188
19188
  "../../node_modules/.pnpm/queue-microtask@1.2.3/node_modules/queue-microtask/index.js"(exports2, module2) {
19189
19189
  var promise2;
19190
- module2.exports = typeof queueMicrotask === "function" ? queueMicrotask.bind(typeof window !== "undefined" ? window : global) : (cb2) => (promise2 || (promise2 = Promise.resolve())).then(cb2).catch((err18) => setTimeout(() => {
19191
- throw err18;
19190
+ module2.exports = typeof queueMicrotask === "function" ? queueMicrotask.bind(typeof window !== "undefined" ? window : global) : (cb2) => (promise2 || (promise2 = Promise.resolve())).then(cb2).catch((err20) => setTimeout(() => {
19191
+ throw err20;
19192
19192
  }, 0));
19193
19193
  }
19194
19194
  });
@@ -19209,32 +19209,32 @@ var require_run_parallel = __commonJS({
19209
19209
  results = {};
19210
19210
  pending = keys.length;
19211
19211
  }
19212
- function done(err18) {
19212
+ function done(err20) {
19213
19213
  function end() {
19214
- if (cb2) cb2(err18, results);
19214
+ if (cb2) cb2(err20, results);
19215
19215
  cb2 = null;
19216
19216
  }
19217
19217
  if (isSync) queueMicrotask2(end);
19218
19218
  else end();
19219
19219
  }
19220
- function each(i3, err18, result) {
19220
+ function each(i3, err20, result) {
19221
19221
  results[i3] = result;
19222
- if (--pending === 0 || err18) {
19223
- done(err18);
19222
+ if (--pending === 0 || err20) {
19223
+ done(err20);
19224
19224
  }
19225
19225
  }
19226
19226
  if (!pending) {
19227
19227
  done(null);
19228
19228
  } else if (keys) {
19229
19229
  keys.forEach(function(key) {
19230
- tasks[key](function(err18, result) {
19231
- each(key, err18, result);
19230
+ tasks[key](function(err20, result) {
19231
+ each(key, err20, result);
19232
19232
  });
19233
19233
  });
19234
19234
  } else {
19235
19235
  tasks.forEach(function(task, i3) {
19236
- task(function(err18, result) {
19237
- each(i3, err18, result);
19236
+ task(function(err20, result) {
19237
+ each(i3, err20, result);
19238
19238
  });
19239
19239
  });
19240
19240
  }
@@ -19294,8 +19294,8 @@ var require_utils5 = __commonJS({
19294
19294
  "use strict";
19295
19295
  Object.defineProperty(exports2, "__esModule", { value: true });
19296
19296
  exports2.fs = void 0;
19297
- var fs3 = require_fs3();
19298
- exports2.fs = fs3;
19297
+ var fs4 = require_fs3();
19298
+ exports2.fs = fs4;
19299
19299
  }
19300
19300
  });
19301
19301
 
@@ -19387,16 +19387,16 @@ var require_async2 = __commonJS({
19387
19387
  return;
19388
19388
  }
19389
19389
  const tasks = names.map((name) => {
19390
- const path23 = common3.joinPathSegments(directory, name, settings.pathSegmentSeparator);
19390
+ const path24 = common3.joinPathSegments(directory, name, settings.pathSegmentSeparator);
19391
19391
  return (done) => {
19392
- fsStat.stat(path23, settings.fsStatSettings, (error48, stats) => {
19392
+ fsStat.stat(path24, settings.fsStatSettings, (error48, stats) => {
19393
19393
  if (error48 !== null) {
19394
19394
  done(error48);
19395
19395
  return;
19396
19396
  }
19397
19397
  const entry = {
19398
19398
  name,
19399
- path: path23,
19399
+ path: path24,
19400
19400
  dirent: utils.fs.createDirentFromStats(name, stats)
19401
19401
  };
19402
19402
  if (settings.stats) {
@@ -19490,14 +19490,14 @@ var require_fs4 = __commonJS({
19490
19490
  "use strict";
19491
19491
  Object.defineProperty(exports2, "__esModule", { value: true });
19492
19492
  exports2.createFileSystemAdapter = exports2.FILE_SYSTEM_ADAPTER = void 0;
19493
- var fs3 = require("fs");
19493
+ var fs4 = require("fs");
19494
19494
  exports2.FILE_SYSTEM_ADAPTER = {
19495
- lstat: fs3.lstat,
19496
- stat: fs3.stat,
19497
- lstatSync: fs3.lstatSync,
19498
- statSync: fs3.statSync,
19499
- readdir: fs3.readdir,
19500
- readdirSync: fs3.readdirSync
19495
+ lstat: fs4.lstat,
19496
+ stat: fs4.stat,
19497
+ lstatSync: fs4.lstatSync,
19498
+ statSync: fs4.statSync,
19499
+ readdir: fs4.readdir,
19500
+ readdirSync: fs4.readdirSync
19501
19501
  };
19502
19502
  function createFileSystemAdapter(fsMethods) {
19503
19503
  if (fsMethods === void 0) {
@@ -19514,15 +19514,15 @@ var require_settings2 = __commonJS({
19514
19514
  "../../node_modules/.pnpm/@nodelib+fs.scandir@2.1.5/node_modules/@nodelib/fs.scandir/out/settings.js"(exports2) {
19515
19515
  "use strict";
19516
19516
  Object.defineProperty(exports2, "__esModule", { value: true });
19517
- var path23 = require("path");
19517
+ var path24 = require("path");
19518
19518
  var fsStat = require_out();
19519
- var fs3 = require_fs4();
19519
+ var fs4 = require_fs4();
19520
19520
  var Settings = class {
19521
19521
  constructor(_options = {}) {
19522
19522
  this._options = _options;
19523
19523
  this.followSymbolicLinks = this._getValue(this._options.followSymbolicLinks, false);
19524
- this.fs = fs3.createFileSystemAdapter(this._options.fs);
19525
- this.pathSegmentSeparator = this._getValue(this._options.pathSegmentSeparator, path23.sep);
19524
+ this.fs = fs4.createFileSystemAdapter(this._options.fs);
19525
+ this.pathSegmentSeparator = this._getValue(this._options.pathSegmentSeparator, path24.sep);
19526
19526
  this.stats = this._getValue(this._options.stats, false);
19527
19527
  this.throwErrorOnBrokenSymbolicLink = this._getValue(this._options.throwErrorOnBrokenSymbolicLink, true);
19528
19528
  this.fsStatSettings = new fsStat.Settings({
@@ -19549,17 +19549,17 @@ var require_out2 = __commonJS({
19549
19549
  var sync = require_sync2();
19550
19550
  var settings_1 = require_settings2();
19551
19551
  exports2.Settings = settings_1.default;
19552
- function scandir(path23, optionsOrSettingsOrCallback, callback) {
19552
+ function scandir(path24, optionsOrSettingsOrCallback, callback) {
19553
19553
  if (typeof optionsOrSettingsOrCallback === "function") {
19554
- async.read(path23, getSettings(), optionsOrSettingsOrCallback);
19554
+ async.read(path24, getSettings(), optionsOrSettingsOrCallback);
19555
19555
  return;
19556
19556
  }
19557
- async.read(path23, getSettings(optionsOrSettingsOrCallback), callback);
19557
+ async.read(path24, getSettings(optionsOrSettingsOrCallback), callback);
19558
19558
  }
19559
19559
  exports2.scandir = scandir;
19560
- function scandirSync(path23, optionsOrSettings) {
19560
+ function scandirSync(path24, optionsOrSettings) {
19561
19561
  const settings = getSettings(optionsOrSettings);
19562
- return sync.read(path23, settings);
19562
+ return sync.read(path24, settings);
19563
19563
  }
19564
19564
  exports2.scandirSync = scandirSync;
19565
19565
  function getSettings(settingsOrOptions = {}) {
@@ -19623,8 +19623,8 @@ var require_queue = __commonJS({
19623
19623
  var errorHandler = null;
19624
19624
  var self2 = {
19625
19625
  push,
19626
- drain: noop2,
19627
- saturated: noop2,
19626
+ drain: noop3,
19627
+ saturated: noop3,
19628
19628
  pause,
19629
19629
  paused: false,
19630
19630
  get concurrency() {
@@ -19647,7 +19647,7 @@ var require_queue = __commonJS({
19647
19647
  length,
19648
19648
  getQueue,
19649
19649
  unshift,
19650
- empty: noop2,
19650
+ empty: noop3,
19651
19651
  kill,
19652
19652
  killAndDrain,
19653
19653
  error: error48,
@@ -19699,7 +19699,7 @@ var require_queue = __commonJS({
19699
19699
  current.context = context;
19700
19700
  current.release = release;
19701
19701
  current.value = value;
19702
- current.callback = done || noop2;
19702
+ current.callback = done || noop3;
19703
19703
  current.errorHandler = errorHandler;
19704
19704
  if (_running >= _concurrency || self2.paused) {
19705
19705
  if (queueTail) {
@@ -19720,7 +19720,7 @@ var require_queue = __commonJS({
19720
19720
  current.context = context;
19721
19721
  current.release = release;
19722
19722
  current.value = value;
19723
- current.callback = done || noop2;
19723
+ current.callback = done || noop3;
19724
19724
  current.errorHandler = errorHandler;
19725
19725
  if (_running >= _concurrency || self2.paused) {
19726
19726
  if (queueHead) {
@@ -19762,13 +19762,13 @@ var require_queue = __commonJS({
19762
19762
  function kill() {
19763
19763
  queueHead = null;
19764
19764
  queueTail = null;
19765
- self2.drain = noop2;
19765
+ self2.drain = noop3;
19766
19766
  }
19767
19767
  function killAndDrain() {
19768
19768
  queueHead = null;
19769
19769
  queueTail = null;
19770
19770
  self2.drain();
19771
- self2.drain = noop2;
19771
+ self2.drain = noop3;
19772
19772
  }
19773
19773
  function abort() {
19774
19774
  var current = queueHead;
@@ -19781,7 +19781,7 @@ var require_queue = __commonJS({
19781
19781
  var val = current.value;
19782
19782
  var context2 = current.context;
19783
19783
  current.value = null;
19784
- current.callback = noop2;
19784
+ current.callback = noop3;
19785
19785
  current.errorHandler = null;
19786
19786
  if (errorHandler2) {
19787
19787
  errorHandler2(new Error("abort"), val);
@@ -19790,32 +19790,32 @@ var require_queue = __commonJS({
19790
19790
  current.release(current);
19791
19791
  current = next;
19792
19792
  }
19793
- self2.drain = noop2;
19793
+ self2.drain = noop3;
19794
19794
  }
19795
19795
  function error48(handler) {
19796
19796
  errorHandler = handler;
19797
19797
  }
19798
19798
  }
19799
- function noop2() {
19799
+ function noop3() {
19800
19800
  }
19801
19801
  function Task3() {
19802
19802
  this.value = null;
19803
- this.callback = noop2;
19803
+ this.callback = noop3;
19804
19804
  this.next = null;
19805
- this.release = noop2;
19805
+ this.release = noop3;
19806
19806
  this.context = null;
19807
19807
  this.errorHandler = null;
19808
19808
  var self2 = this;
19809
- this.worked = function worked(err18, result) {
19809
+ this.worked = function worked(err20, result) {
19810
19810
  var callback = self2.callback;
19811
19811
  var errorHandler = self2.errorHandler;
19812
19812
  var val = self2.value;
19813
19813
  self2.value = null;
19814
- self2.callback = noop2;
19814
+ self2.callback = noop3;
19815
19815
  if (self2.errorHandler) {
19816
- errorHandler(err18, val);
19816
+ errorHandler(err20, val);
19817
19817
  }
19818
- callback.call(self2.context, err18, result);
19818
+ callback.call(self2.context, err20, result);
19819
19819
  self2.release(self2);
19820
19820
  };
19821
19821
  }
@@ -19839,28 +19839,28 @@ var require_queue = __commonJS({
19839
19839
  return queue;
19840
19840
  function push(value) {
19841
19841
  var p = new Promise(function(resolve, reject) {
19842
- pushCb(value, function(err18, result) {
19843
- if (err18) {
19844
- reject(err18);
19842
+ pushCb(value, function(err20, result) {
19843
+ if (err20) {
19844
+ reject(err20);
19845
19845
  return;
19846
19846
  }
19847
19847
  resolve(result);
19848
19848
  });
19849
19849
  });
19850
- p.catch(noop2);
19850
+ p.catch(noop3);
19851
19851
  return p;
19852
19852
  }
19853
19853
  function unshift(value) {
19854
19854
  var p = new Promise(function(resolve, reject) {
19855
- unshiftCb(value, function(err18, result) {
19856
- if (err18) {
19857
- reject(err18);
19855
+ unshiftCb(value, function(err20, result) {
19856
+ if (err20) {
19857
+ reject(err20);
19858
19858
  return;
19859
19859
  }
19860
19860
  resolve(result);
19861
19861
  });
19862
19862
  });
19863
- p.catch(noop2);
19863
+ p.catch(noop3);
19864
19864
  return p;
19865
19865
  }
19866
19866
  function drained() {
@@ -20206,7 +20206,7 @@ var require_settings3 = __commonJS({
20206
20206
  "../../node_modules/.pnpm/@nodelib+fs.walk@1.2.8/node_modules/@nodelib/fs.walk/out/settings.js"(exports2) {
20207
20207
  "use strict";
20208
20208
  Object.defineProperty(exports2, "__esModule", { value: true });
20209
- var path23 = require("path");
20209
+ var path24 = require("path");
20210
20210
  var fsScandir = require_out2();
20211
20211
  var Settings = class {
20212
20212
  constructor(_options = {}) {
@@ -20216,7 +20216,7 @@ var require_settings3 = __commonJS({
20216
20216
  this.deepFilter = this._getValue(this._options.deepFilter, null);
20217
20217
  this.entryFilter = this._getValue(this._options.entryFilter, null);
20218
20218
  this.errorFilter = this._getValue(this._options.errorFilter, null);
20219
- this.pathSegmentSeparator = this._getValue(this._options.pathSegmentSeparator, path23.sep);
20219
+ this.pathSegmentSeparator = this._getValue(this._options.pathSegmentSeparator, path24.sep);
20220
20220
  this.fsScandirSettings = new fsScandir.Settings({
20221
20221
  followSymbolicLinks: this._options.followSymbolicLinks,
20222
20222
  fs: this._options.fs,
@@ -20278,7 +20278,7 @@ var require_reader2 = __commonJS({
20278
20278
  "../../node_modules/.pnpm/fast-glob@3.3.3/node_modules/fast-glob/out/readers/reader.js"(exports2) {
20279
20279
  "use strict";
20280
20280
  Object.defineProperty(exports2, "__esModule", { value: true });
20281
- var path23 = require("path");
20281
+ var path24 = require("path");
20282
20282
  var fsStat = require_out();
20283
20283
  var utils = require_utils4();
20284
20284
  var Reader = class {
@@ -20291,7 +20291,7 @@ var require_reader2 = __commonJS({
20291
20291
  });
20292
20292
  }
20293
20293
  _getFullEntryPath(filepath) {
20294
- return path23.resolve(this._settings.cwd, filepath);
20294
+ return path24.resolve(this._settings.cwd, filepath);
20295
20295
  }
20296
20296
  _makeEntry(stats, pattern) {
20297
20297
  const entry = {
@@ -20707,7 +20707,7 @@ var require_provider = __commonJS({
20707
20707
  "../../node_modules/.pnpm/fast-glob@3.3.3/node_modules/fast-glob/out/providers/provider.js"(exports2) {
20708
20708
  "use strict";
20709
20709
  Object.defineProperty(exports2, "__esModule", { value: true });
20710
- var path23 = require("path");
20710
+ var path24 = require("path");
20711
20711
  var deep_1 = require_deep();
20712
20712
  var entry_1 = require_entry();
20713
20713
  var error_1 = require_error2();
@@ -20721,7 +20721,7 @@ var require_provider = __commonJS({
20721
20721
  this.entryTransformer = new entry_2.default(this._settings);
20722
20722
  }
20723
20723
  _getRootDirectory(task) {
20724
- return path23.resolve(this._settings.cwd, task.base);
20724
+ return path24.resolve(this._settings.cwd, task.base);
20725
20725
  }
20726
20726
  _getReaderOptions(task) {
20727
20727
  const basePath = task.base === "." ? "" : task.base;
@@ -20902,16 +20902,16 @@ var require_settings4 = __commonJS({
20902
20902
  "use strict";
20903
20903
  Object.defineProperty(exports2, "__esModule", { value: true });
20904
20904
  exports2.DEFAULT_FILE_SYSTEM_ADAPTER = void 0;
20905
- var fs3 = require("fs");
20905
+ var fs4 = require("fs");
20906
20906
  var os4 = require("os");
20907
20907
  var CPU_COUNT = Math.max(os4.cpus().length, 1);
20908
20908
  exports2.DEFAULT_FILE_SYSTEM_ADAPTER = {
20909
- lstat: fs3.lstat,
20910
- lstatSync: fs3.lstatSync,
20911
- stat: fs3.stat,
20912
- statSync: fs3.statSync,
20913
- readdir: fs3.readdir,
20914
- readdirSync: fs3.readdirSync
20909
+ lstat: fs4.lstat,
20910
+ lstatSync: fs4.lstatSync,
20911
+ stat: fs4.stat,
20912
+ statSync: fs4.statSync,
20913
+ readdir: fs4.readdir,
20914
+ readdirSync: fs4.readdirSync
20915
20915
  };
20916
20916
  var Settings = class {
20917
20917
  constructor(_options = {}) {
@@ -21075,7 +21075,7 @@ var {
21075
21075
  } = import_index.default;
21076
21076
 
21077
21077
  // src/commands/analyse-command.ts
21078
- var import_promises16 = require("node:fs/promises");
21078
+ var import_promises17 = require("node:fs/promises");
21079
21079
 
21080
21080
  // ../../packages/pipeline/dist/index.js
21081
21081
  var import_node_fs2 = require("node:fs");
@@ -24368,9 +24368,9 @@ var tq = k((oq) => {
24368
24368
  });
24369
24369
  var sq = k((aq) => {
24370
24370
  Object.defineProperty(aq, "__esModule", { value: true });
24371
- var ok19 = Q$(), tk = { keyword: "not", schemaType: ["object", "boolean"], trackErrors: true, code($) {
24371
+ var ok21 = Q$(), tk = { keyword: "not", schemaType: ["object", "boolean"], trackErrors: true, code($) {
24372
24372
  let { gen: X, schema: J, it: Q } = $;
24373
- if ((0, ok19.alwaysValidSchema)(Q, J)) {
24373
+ if ((0, ok21.alwaysValidSchema)(Q, J)) {
24374
24374
  $.fail();
24375
24375
  return;
24376
24376
  }
@@ -38981,10 +38981,10 @@ function mergeDefs(...defs) {
38981
38981
  function cloneDef(schema2) {
38982
38982
  return mergeDefs(schema2._zod.def);
38983
38983
  }
38984
- function getElementAtPath(obj, path23) {
38985
- if (!path23)
38984
+ function getElementAtPath(obj, path24) {
38985
+ if (!path24)
38986
38986
  return obj;
38987
- return path23.reduce((acc, key) => acc?.[key], obj);
38987
+ return path24.reduce((acc, key) => acc?.[key], obj);
38988
38988
  }
38989
38989
  function promiseAllObject(promisesObj) {
38990
38990
  const keys = Object.keys(promisesObj);
@@ -39367,11 +39367,11 @@ function aborted(x, startIndex = 0) {
39367
39367
  }
39368
39368
  return false;
39369
39369
  }
39370
- function prefixIssues(path23, issues) {
39370
+ function prefixIssues(path24, issues) {
39371
39371
  return issues.map((iss) => {
39372
39372
  var _a3;
39373
39373
  (_a3 = iss).path ?? (_a3.path = []);
39374
- iss.path.unshift(path23);
39374
+ iss.path.unshift(path24);
39375
39375
  return iss;
39376
39376
  });
39377
39377
  }
@@ -39554,7 +39554,7 @@ function formatError(error48, mapper = (issue2) => issue2.message) {
39554
39554
  }
39555
39555
  function treeifyError(error48, mapper = (issue2) => issue2.message) {
39556
39556
  const result = { errors: [] };
39557
- const processError = (error49, path23 = []) => {
39557
+ const processError = (error49, path24 = []) => {
39558
39558
  var _a3, _b2;
39559
39559
  for (const issue2 of error49.issues) {
39560
39560
  if (issue2.code === "invalid_union" && issue2.errors.length) {
@@ -39564,7 +39564,7 @@ function treeifyError(error48, mapper = (issue2) => issue2.message) {
39564
39564
  } else if (issue2.code === "invalid_element") {
39565
39565
  processError({ issues: issue2.issues }, issue2.path);
39566
39566
  } else {
39567
- const fullpath = [...path23, ...issue2.path];
39567
+ const fullpath = [...path24, ...issue2.path];
39568
39568
  if (fullpath.length === 0) {
39569
39569
  result.errors.push(mapper(issue2));
39570
39570
  continue;
@@ -39596,8 +39596,8 @@ function treeifyError(error48, mapper = (issue2) => issue2.message) {
39596
39596
  }
39597
39597
  function toDotPath(_path) {
39598
39598
  const segs = [];
39599
- const path23 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
39600
- for (const seg of path23) {
39599
+ const path24 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
39600
+ for (const seg of path24) {
39601
39601
  if (typeof seg === "number")
39602
39602
  segs.push(`[${seg}]`);
39603
39603
  else if (typeof seg === "symbol")
@@ -51574,13 +51574,13 @@ function resolveRef(ref, ctx) {
51574
51574
  if (!ref.startsWith("#")) {
51575
51575
  throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
51576
51576
  }
51577
- const path23 = ref.slice(1).split("/").filter(Boolean);
51578
- if (path23.length === 0) {
51577
+ const path24 = ref.slice(1).split("/").filter(Boolean);
51578
+ if (path24.length === 0) {
51579
51579
  return ctx.rootSchema;
51580
51580
  }
51581
51581
  const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
51582
- if (path23[0] === defsKey) {
51583
- const key = path23[1];
51582
+ if (path24[0] === defsKey) {
51583
+ const key = path24[1];
51584
51584
  if (!key || !ctx.defs[key]) {
51585
51585
  throw new Error(`Reference not found: ${ref}`);
51586
51586
  }
@@ -51989,6 +51989,7 @@ var import_node_path = __toESM(require("node:path"), 1);
51989
51989
  var import_neverthrow5 = __toESM(require_index_cjs(), 1);
51990
51990
  var import_sharp = __toESM(require("sharp"), 1);
51991
51991
  var import_neverthrow6 = __toESM(require_index_cjs(), 1);
51992
+ var import_promises6 = require("node:timers/promises");
51992
51993
  var import_node_crypto = require("node:crypto");
51993
51994
  var import_node_child_process2 = require("node:child_process");
51994
51995
  var import_node_events = require("node:events");
@@ -52052,11 +52053,33 @@ function resolveUdid(udid) {
52052
52053
  return (0, import_neverthrow3.err)(result);
52053
52054
  });
52054
52055
  }
52056
+ var parseIdbTree = (0, import_neverthrow.fromThrowable)(
52057
+ (raw) => JSON.parse(raw),
52058
+ (cause) => ({ type: "SNAPSHOT_PARSE_FAILED", cause })
52059
+ );
52055
52060
  var FULLSCREEN_THRESHOLD = 0.9;
52056
52061
  var DEFAULT_SCREEN_WIDTH = 375;
52057
52062
  var DEFAULT_SCREEN_HEIGHT = 812;
52058
- var STABILITY_POLL_ATTEMPTS = 5;
52059
- var STABILITY_POLL_DELAY_MS = 300;
52063
+ var STABILITY_POLL_ATTEMPTS = 10;
52064
+ var STABILITY_POLL_DELAY_MS = 500;
52065
+ function structuralSignature(elements) {
52066
+ const lines = [];
52067
+ const walk = (nodes) => {
52068
+ for (const element of nodes) {
52069
+ const frame = element.frame ?? { x: 0, y: 0, width: 0, height: 0 };
52070
+ const type2 = element.type ?? "unknown";
52071
+ const childCount = (element.children ?? []).length;
52072
+ lines.push(
52073
+ `${type2}|${String(frame.x)},${String(frame.y)},${String(frame.width)},${String(frame.height)}|${String(childCount)}`
52074
+ );
52075
+ if (element.children) {
52076
+ walk(element.children);
52077
+ }
52078
+ }
52079
+ };
52080
+ walk(elements);
52081
+ return lines.join("\n");
52082
+ }
52060
52083
  function isInViewport(frame, screen) {
52061
52084
  return frame.width > 0 && frame.height > 0 && frame.x + frame.width > 0 && frame.x < screen.width && frame.y + frame.height > 0 && frame.y < screen.height;
52062
52085
  }
@@ -52168,36 +52191,39 @@ function formatAccessibilityElements(elements) {
52168
52191
 
52169
52192
  ${elementList}` : elementList;
52170
52193
  }
52194
+ function fetchSnapshot(udid) {
52195
+ return runCommand("idb", ["ui", "describe-all", "--udid", udid, "--json", "--nested"]);
52196
+ }
52171
52197
  async function pollUntilStable(udid) {
52172
- let previous;
52198
+ let previousSignature;
52199
+ let previousRaw = "";
52173
52200
  for (let index = 0; index < STABILITY_POLL_ATTEMPTS; index++) {
52174
- const result = await runCommand("idb", [
52175
- "ui",
52176
- "describe-all",
52177
- "--udid",
52178
- udid,
52179
- "--json",
52180
- "--nested"
52181
- ]);
52201
+ const result = await fetchSnapshot(udid);
52182
52202
  if (result.isErr()) {
52183
52203
  return result;
52184
52204
  }
52185
- const current = result.value;
52186
- if (current === previous) {
52187
- return (0, import_neverthrow.ok)(current);
52205
+ const raw = result.value;
52206
+ const parsed = parseIdbTree(raw);
52207
+ if (parsed.isErr()) {
52208
+ return (0, import_neverthrow.err)(parsed.error);
52188
52209
  }
52189
- previous = current;
52210
+ const signature = structuralSignature(parsed.value);
52211
+ if (signature === previousSignature) {
52212
+ return (0, import_neverthrow.ok)(raw);
52213
+ }
52214
+ previousSignature = signature;
52215
+ previousRaw = raw;
52190
52216
  if (index < STABILITY_POLL_ATTEMPTS - 1) {
52191
52217
  await (0, import_promises4.setTimeout)(STABILITY_POLL_DELAY_MS);
52192
52218
  }
52193
52219
  }
52194
- return (0, import_neverthrow.ok)(previous ?? "");
52220
+ return (0, import_neverthrow.ok)(previousRaw);
52195
52221
  }
52196
52222
  function waitForStableSnapshot(udid) {
52197
52223
  return new import_neverthrow.ResultAsync(pollUntilStable(udid));
52198
52224
  }
52199
52225
  function captureAccessibilityTree(udid = "booted") {
52200
- return resolveUdid(udid).andThen((resolvedUdid) => waitForStableSnapshot(resolvedUdid)).map((raw) => JSON.parse(raw));
52226
+ return resolveUdid(udid).andThen((resolvedUdid) => waitForStableSnapshot(resolvedUdid)).andThen((raw) => parseIdbTree(raw));
52201
52227
  }
52202
52228
  function captureAccessibilitySnapshot(udid = "booted") {
52203
52229
  return captureAccessibilityTree(udid).map((elements) => formatAccessibilityElements(elements));
@@ -52578,18 +52604,54 @@ function captureScreenshot(udid = "booted") {
52578
52604
  );
52579
52605
  }
52580
52606
  function createScreenshotTool(udid = "booted") {
52581
- return _x("screenshot", "Take a screenshot of the current screen.", {}, async () => {
52582
- const result = await captureScreenshot(udid);
52583
- if (result.isErr()) {
52584
- return {
52585
- content: [{ type: "text", text: String(result.error.cause) }],
52586
- isError: true
52587
- };
52607
+ return _x(
52608
+ "screenshot",
52609
+ "Capture a screenshot of the current screen. Use for passive visual verification \u2014 confirming a screen transition occurred, loading finished, or an expected visual outcome is present \u2014 when you do not need element labels, tap coordinates, or accessibility attributes. Does not return a <screen_id>; cannot be used for stuck-loop detection or element-targeted assertions. Do not call this immediately before or after `view_ui` for the same state.",
52610
+ {},
52611
+ async () => {
52612
+ const result = await captureScreenshot(udid);
52613
+ if (result.isErr()) {
52614
+ return {
52615
+ content: [{ type: "text", text: String(result.error.cause) }],
52616
+ isError: true
52617
+ };
52618
+ }
52619
+ return { content: [{ type: "image", data: result.value, mimeType: "image/png" }] };
52588
52620
  }
52589
- return { content: [{ type: "image", data: result.value, mimeType: "image/png" }] };
52590
- });
52621
+ );
52591
52622
  }
52592
52623
  var screenshotTool = createScreenshotTool();
52624
+ var MIN_WAIT_SECONDS = 1;
52625
+ var MAX_WAIT_SECONDS = 10;
52626
+ var MS_PER_SECOND2 = 1e3;
52627
+ var SECONDS_SCHEMA = external_exports.number().int().min(MIN_WAIT_SECONDS).max(MAX_WAIT_SECONDS);
52628
+ var WAIT_SCHEMA = {
52629
+ seconds: SECONDS_SCHEMA
52630
+ };
52631
+ function createWaitSecondsTool() {
52632
+ return _x(
52633
+ "wait_seconds",
52634
+ "Pause for N seconds (1-10) when expected UI content may still be loading silently. Call view_ui again after waiting.",
52635
+ WAIT_SCHEMA,
52636
+ async ({ seconds }) => {
52637
+ const parsed = SECONDS_SCHEMA.safeParse(seconds);
52638
+ if (!parsed.success) {
52639
+ return {
52640
+ content: [
52641
+ {
52642
+ type: "text",
52643
+ text: `wait_seconds expected an integer between ${String(MIN_WAIT_SECONDS)} and ${String(MAX_WAIT_SECONDS)}, got ${String(seconds)}`
52644
+ }
52645
+ ],
52646
+ isError: true
52647
+ };
52648
+ }
52649
+ await (0, import_promises6.setTimeout)(parsed.data * MS_PER_SECOND2);
52650
+ return { content: [{ type: "text", text: `Waited ${String(parsed.data)}s` }] };
52651
+ }
52652
+ );
52653
+ }
52654
+ var WAIT_SECONDS_TOOL_NAME = "mcp__mobile-ios__wait_seconds";
52593
52655
  var LABEL_SET_CAP = 50;
52594
52656
  var MID_DEPTH_THRESHOLD = 5;
52595
52657
  var DEFAULT_SCREEN_HEIGHT2 = 812;
@@ -52744,6 +52806,7 @@ function createMobileIosServer(udid = "booted", extraTools = []) {
52744
52806
  createLaunchAppTool(udid),
52745
52807
  createTerminateAppTool(udid),
52746
52808
  createListAppsTool(udid),
52809
+ createWaitSecondsTool(),
52747
52810
  ...extraTools
52748
52811
  ]
52749
52812
  });
@@ -52765,7 +52828,7 @@ var findingSchema = external_exports.object({
52765
52828
  "motion-regression",
52766
52829
  "interaction-regression",
52767
52830
  "continuity-regression",
52768
- "step-skipped"
52831
+ "missing-content"
52769
52832
  ]),
52770
52833
  flow: external_exports.string(),
52771
52834
  steps: external_exports.array(external_exports.string()),
@@ -52810,10 +52873,10 @@ function dismissalsPath(baseDirectory, override) {
52810
52873
 
52811
52874
  // ../../packages/pipeline/dist/index.js
52812
52875
  var import_neverthrow30 = __toESM(require_index_cjs(), 1);
52813
- var import_promises14 = require("node:timers/promises");
52876
+ var import_promises15 = require("node:timers/promises");
52814
52877
 
52815
52878
  // ../../agents/analyser/dist/index.js
52816
- var import_promises6 = require("node:fs/promises");
52879
+ var import_promises7 = require("node:fs/promises");
52817
52880
 
52818
52881
  // ../../node_modules/.pnpm/chalk@5.6.2/node_modules/chalk/source/vendor/ansi-styles/index.js
52819
52882
  var ANSI_BACKGROUND_OFFSET = 10;
@@ -53639,9 +53702,9 @@ function render(state, previous) {
53639
53702
  function dashboardEqual(left, right) {
53640
53703
  return JSON.stringify(left) === JSON.stringify(right);
53641
53704
  }
53642
- var MS_PER_SECOND2 = 1e3;
53705
+ var MS_PER_SECOND3 = 1e3;
53643
53706
  function formatDuration(ms) {
53644
- return `${String(Math.round(ms / MS_PER_SECOND2))}s`;
53707
+ return `${String(Math.round(ms / MS_PER_SECOND3))}s`;
53645
53708
  }
53646
53709
  function normalizeItemQueued(event) {
53647
53710
  return [{ kind: "text", style: "default", text: `[${event.item.name}] QUEUED` }];
@@ -54477,7 +54540,7 @@ function safeHandler(handler) {
54477
54540
 
54478
54541
  // ../../agents/analyser/dist/index.js
54479
54542
  var import_neverthrow10 = __toESM(require_index_cjs(), 1);
54480
- var import_promises7 = require("node:timers/promises");
54543
+ var import_promises8 = require("node:timers/promises");
54481
54544
 
54482
54545
  // ../../node_modules/.pnpm/@google+generative-ai@0.24.1/node_modules/@google/generative-ai/dist/index.mjs
54483
54546
  var SchemaType;
@@ -54680,15 +54743,15 @@ async function makeRequest(url2, fetchOptions, fetchFn = fetch) {
54680
54743
  return response;
54681
54744
  }
54682
54745
  function handleResponseError(e3, url2) {
54683
- let err18 = e3;
54684
- if (err18.name === "AbortError") {
54685
- err18 = new GoogleGenerativeAIAbortError(`Request aborted when fetching ${url2.toString()}: ${e3.message}`);
54686
- err18.stack = e3.stack;
54746
+ let err20 = e3;
54747
+ if (err20.name === "AbortError") {
54748
+ err20 = new GoogleGenerativeAIAbortError(`Request aborted when fetching ${url2.toString()}: ${e3.message}`);
54749
+ err20.stack = e3.stack;
54687
54750
  } else if (!(e3 instanceof GoogleGenerativeAIFetchError || e3 instanceof GoogleGenerativeAIRequestInputError)) {
54688
- err18 = new GoogleGenerativeAIError(`Error fetching from ${url2.toString()}: ${e3.message}`);
54689
- err18.stack = e3.stack;
54751
+ err20 = new GoogleGenerativeAIError(`Error fetching from ${url2.toString()}: ${e3.message}`);
54752
+ err20.stack = e3.stack;
54690
54753
  }
54691
- throw err18;
54754
+ throw err20;
54692
54755
  }
54693
54756
  async function handleResponseNotOk(response, url2) {
54694
54757
  let message = "";
@@ -54854,11 +54917,11 @@ function __asyncGenerator(thisArg, _arguments, generator) {
54854
54917
  try {
54855
54918
  step(g3[n3](v2));
54856
54919
  } catch (e3) {
54857
- settle(q4[0][3], e3);
54920
+ settle2(q4[0][3], e3);
54858
54921
  }
54859
54922
  }
54860
54923
  function step(r3) {
54861
- r3.value instanceof __await ? Promise.resolve(r3.value.v).then(fulfill, reject) : settle(q4[0][2], r3);
54924
+ r3.value instanceof __await ? Promise.resolve(r3.value.v).then(fulfill, reject) : settle2(q4[0][2], r3);
54862
54925
  }
54863
54926
  function fulfill(value) {
54864
54927
  resume("next", value);
@@ -54866,7 +54929,7 @@ function __asyncGenerator(thisArg, _arguments, generator) {
54866
54929
  function reject(value) {
54867
54930
  resume("throw", value);
54868
54931
  }
54869
- function settle(f6, v2) {
54932
+ function settle2(f6, v2) {
54870
54933
  if (f6(v2), q4.shift(), q4.length) resume(q4[0][0], q4[0][1]);
54871
54934
  }
54872
54935
  }
@@ -54935,14 +54998,14 @@ function getResponseStream(inputStream) {
54935
54998
  }
54936
54999
  return pump();
54937
55000
  }).catch((e3) => {
54938
- let err18 = e3;
54939
- err18.stack = e3.stack;
54940
- if (err18.name === "AbortError") {
54941
- err18 = new GoogleGenerativeAIAbortError("Request aborted when reading from the stream");
55001
+ let err20 = e3;
55002
+ err20.stack = e3.stack;
55003
+ if (err20.name === "AbortError") {
55004
+ err20 = new GoogleGenerativeAIAbortError("Request aborted when reading from the stream");
54942
55005
  } else {
54943
- err18 = new GoogleGenerativeAIError("Error reading from the stream");
55006
+ err20 = new GoogleGenerativeAIError("Error reading from the stream");
54944
55007
  }
54945
- throw err18;
55008
+ throw err20;
54946
55009
  });
54947
55010
  }
54948
55011
  }
@@ -55538,15 +55601,15 @@ async function makeRequest2(url2, fetchOptions, fetchFn = fetch) {
55538
55601
  return response;
55539
55602
  }
55540
55603
  function handleResponseError2(e3, url2) {
55541
- let err18 = e3;
55542
- if (err18.name === "AbortError") {
55543
- err18 = new GoogleGenerativeAIAbortError2(`Request aborted when fetching ${url2.toString()}: ${e3.message}`);
55544
- err18.stack = e3.stack;
55604
+ let err20 = e3;
55605
+ if (err20.name === "AbortError") {
55606
+ err20 = new GoogleGenerativeAIAbortError2(`Request aborted when fetching ${url2.toString()}: ${e3.message}`);
55607
+ err20.stack = e3.stack;
55545
55608
  } else if (!(e3 instanceof GoogleGenerativeAIFetchError2 || e3 instanceof GoogleGenerativeAIRequestInputError2)) {
55546
- err18 = new GoogleGenerativeAIError2(`Error fetching from ${url2.toString()}: ${e3.message}`);
55547
- err18.stack = e3.stack;
55609
+ err20 = new GoogleGenerativeAIError2(`Error fetching from ${url2.toString()}: ${e3.message}`);
55610
+ err20.stack = e3.stack;
55548
55611
  }
55549
- throw err18;
55612
+ throw err20;
55550
55613
  }
55551
55614
  async function handleResponseNotOk2(response, url2) {
55552
55615
  let message = "";
@@ -55585,8 +55648,8 @@ var ServerRequestUrl = class {
55585
55648
  this.apiKey = apiKey;
55586
55649
  this.requestOptions = requestOptions;
55587
55650
  }
55588
- appendPath(path23) {
55589
- this._url.pathname = this._url.pathname + `/${path23}`;
55651
+ appendPath(path24) {
55652
+ this._url.pathname = this._url.pathname + `/${path24}`;
55590
55653
  }
55591
55654
  appendParam(key, value) {
55592
55655
  this._url.searchParams.append(key, value);
@@ -55906,7 +55969,7 @@ async function runPollLoop(checkState, onTick) {
55906
55969
  if (state === FileState.FAILED) {
55907
55970
  return "failed";
55908
55971
  }
55909
- await (0, import_promises7.setTimeout)(POLL_INTERVAL_MS);
55972
+ await (0, import_promises8.setTimeout)(POLL_INTERVAL_MS);
55910
55973
  }
55911
55974
  return "timeout";
55912
55975
  }
@@ -56036,7 +56099,7 @@ var DEFAULT_MODEL = "gemini-2.5-pro";
56036
56099
  var BYTES_PER_MB = 1048576;
56037
56100
  var MAX_POLL_ATTEMPTS2 = 30;
56038
56101
  async function getFileSize(filePath) {
56039
- const fileStats = await (0, import_promises6.stat)(filePath);
56102
+ const fileStats = await (0, import_promises7.stat)(filePath);
56040
56103
  return fileStats.size;
56041
56104
  }
56042
56105
  function emitStageEnd(onEvent, start) {
@@ -56142,34 +56205,34 @@ var uuid42 = function() {
56142
56205
  };
56143
56206
 
56144
56207
  // ../../node_modules/.pnpm/@anthropic-ai+sdk@0.87.0_zod@4.3.6/node_modules/@anthropic-ai/sdk/internal/errors.mjs
56145
- function isAbortError(err18) {
56146
- return typeof err18 === "object" && err18 !== null && // Spec-compliant fetch implementations
56147
- ("name" in err18 && err18.name === "AbortError" || // Expo fetch
56148
- "message" in err18 && String(err18.message).includes("FetchRequestCanceledException"));
56149
- }
56150
- var castToError = (err18) => {
56151
- if (err18 instanceof Error)
56152
- return err18;
56153
- if (typeof err18 === "object" && err18 !== null) {
56208
+ function isAbortError(err20) {
56209
+ return typeof err20 === "object" && err20 !== null && // Spec-compliant fetch implementations
56210
+ ("name" in err20 && err20.name === "AbortError" || // Expo fetch
56211
+ "message" in err20 && String(err20.message).includes("FetchRequestCanceledException"));
56212
+ }
56213
+ var castToError = (err20) => {
56214
+ if (err20 instanceof Error)
56215
+ return err20;
56216
+ if (typeof err20 === "object" && err20 !== null) {
56154
56217
  try {
56155
- if (Object.prototype.toString.call(err18) === "[object Error]") {
56156
- const error48 = new Error(err18.message, err18.cause ? { cause: err18.cause } : {});
56157
- if (err18.stack)
56158
- error48.stack = err18.stack;
56159
- if (err18.cause && !error48.cause)
56160
- error48.cause = err18.cause;
56161
- if (err18.name)
56162
- error48.name = err18.name;
56218
+ if (Object.prototype.toString.call(err20) === "[object Error]") {
56219
+ const error48 = new Error(err20.message, err20.cause ? { cause: err20.cause } : {});
56220
+ if (err20.stack)
56221
+ error48.stack = err20.stack;
56222
+ if (err20.cause && !error48.cause)
56223
+ error48.cause = err20.cause;
56224
+ if (err20.name)
56225
+ error48.name = err20.name;
56163
56226
  return error48;
56164
56227
  }
56165
56228
  } catch {
56166
56229
  }
56167
56230
  try {
56168
- return new Error(JSON.stringify(err18));
56231
+ return new Error(JSON.stringify(err20));
56169
56232
  } catch {
56170
56233
  }
56171
56234
  }
56172
- return new Error(err18);
56235
+ return new Error(err20);
56173
56236
  };
56174
56237
 
56175
56238
  // ../../node_modules/.pnpm/@anthropic-ai+sdk@0.87.0_zod@4.3.6/node_modules/@anthropic-ai/sdk/core/error.mjs
@@ -56299,13 +56362,13 @@ var validatePositiveInteger = (name, n3) => {
56299
56362
  var safeJSON = (text) => {
56300
56363
  try {
56301
56364
  return JSON.parse(text);
56302
- } catch (err18) {
56365
+ } catch (err20) {
56303
56366
  return void 0;
56304
56367
  }
56305
56368
  };
56306
56369
 
56307
56370
  // ../../node_modules/.pnpm/@anthropic-ai+sdk@0.87.0_zod@4.3.6/node_modules/@anthropic-ai/sdk/internal/utils/sleep.mjs
56308
- var sleep3 = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
56371
+ var sleep4 = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
56309
56372
 
56310
56373
  // ../../node_modules/.pnpm/@anthropic-ai+sdk@0.87.0_zod@4.3.6/node_modules/@anthropic-ai/sdk/version.mjs
56311
56374
  var VERSION = "0.87.0";
@@ -56863,8 +56926,8 @@ var Stream = class _Stream {
56863
56926
  return ctrl.close();
56864
56927
  const bytes = encodeUTF8(JSON.stringify(value) + "\n");
56865
56928
  ctrl.enqueue(bytes);
56866
- } catch (err18) {
56867
- ctrl.error(err18);
56929
+ } catch (err20) {
56930
+ ctrl.error(err20);
56868
56931
  }
56869
56932
  },
56870
56933
  async cancel() {
@@ -57412,12 +57475,12 @@ function encodeURIPath(str2) {
57412
57475
  return str2.replace(/[^A-Za-z0-9\-._~!$&'()*+,;=:@]+/g, encodeURIComponent);
57413
57476
  }
57414
57477
  var EMPTY = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.create(null));
57415
- var createPathTagFunction = (pathEncoder = encodeURIPath) => function path23(statics, ...params) {
57478
+ var createPathTagFunction = (pathEncoder = encodeURIPath) => function path24(statics, ...params) {
57416
57479
  if (statics.length === 1)
57417
57480
  return statics[0];
57418
57481
  let postPath = false;
57419
57482
  const invalidSegments = [];
57420
- const path24 = statics.reduce((previousValue, currentValue, index) => {
57483
+ const path25 = statics.reduce((previousValue, currentValue, index) => {
57421
57484
  if (/[?#]/.test(currentValue)) {
57422
57485
  postPath = true;
57423
57486
  }
@@ -57434,7 +57497,7 @@ var createPathTagFunction = (pathEncoder = encodeURIPath) => function path23(sta
57434
57497
  }
57435
57498
  return previousValue + currentValue + (index === params.length ? "" : encoded);
57436
57499
  }, "");
57437
- const pathOnly = path24.split(/[?#]/, 1)[0];
57500
+ const pathOnly = path25.split(/[?#]/, 1)[0];
57438
57501
  const invalidSegmentPattern = /(?<=^|\/)(?:\.|%2e){1,2}(?=\/|$)/gi;
57439
57502
  let match;
57440
57503
  while ((match = invalidSegmentPattern.exec(pathOnly)) !== null) {
@@ -57455,10 +57518,10 @@ var createPathTagFunction = (pathEncoder = encodeURIPath) => function path23(sta
57455
57518
  }, "");
57456
57519
  throw new AnthropicError(`Path parameters result in path with invalid segments:
57457
57520
  ${invalidSegments.map((e3) => e3.error).join("\n")}
57458
- ${path24}
57521
+ ${path25}
57459
57522
  ${underline}`);
57460
57523
  }
57461
- return path24;
57524
+ return path25;
57462
57525
  };
57463
57526
  var path4 = /* @__PURE__ */ createPathTagFunction(encodeURIPath);
57464
57527
 
@@ -58771,8 +58834,8 @@ var BetaMessageStream = class _BetaMessageStream {
58771
58834
  if (jsonBuf) {
58772
58835
  try {
58773
58836
  newContent.input = partialParse(jsonBuf);
58774
- } catch (err18) {
58775
- const error48 = new AnthropicError(`Unable to parse tool parameter JSON from model. Please retry your request or adjust your prompt. Error: ${err18}. JSON: ${jsonBuf}`);
58837
+ } catch (err20) {
58838
+ const error48 = new AnthropicError(`Unable to parse tool parameter JSON from model. Please retry your request or adjust your prompt. Error: ${err20}. JSON: ${jsonBuf}`);
58776
58839
  __classPrivateFieldGet(this, _BetaMessageStream_handleError, "f").call(this, error48);
58777
58840
  }
58778
58841
  }
@@ -58834,17 +58897,17 @@ var BetaMessageStream = class _BetaMessageStream {
58834
58897
  }
58835
58898
  readQueue.length = 0;
58836
58899
  });
58837
- this.on("abort", (err18) => {
58900
+ this.on("abort", (err20) => {
58838
58901
  done = true;
58839
58902
  for (const reader of readQueue) {
58840
- reader.reject(err18);
58903
+ reader.reject(err20);
58841
58904
  }
58842
58905
  readQueue.length = 0;
58843
58906
  });
58844
- this.on("error", (err18) => {
58907
+ this.on("error", (err20) => {
58845
58908
  done = true;
58846
58909
  for (const reader of readQueue) {
58847
- reader.reject(err18);
58910
+ reader.reject(err20);
58848
58911
  }
58849
58912
  readQueue.length = 0;
58850
58913
  });
@@ -61087,17 +61150,17 @@ var MessageStream = class _MessageStream {
61087
61150
  }
61088
61151
  readQueue.length = 0;
61089
61152
  });
61090
- this.on("abort", (err18) => {
61153
+ this.on("abort", (err20) => {
61091
61154
  done = true;
61092
61155
  for (const reader of readQueue) {
61093
- reader.reject(err18);
61156
+ reader.reject(err20);
61094
61157
  }
61095
61158
  readQueue.length = 0;
61096
61159
  });
61097
- this.on("error", (err18) => {
61160
+ this.on("error", (err20) => {
61098
61161
  done = true;
61099
61162
  for (const reader of readQueue) {
61100
- reader.reject(err18);
61163
+ reader.reject(err20);
61101
61164
  }
61102
61165
  readQueue.length = 0;
61103
61166
  });
@@ -61546,9 +61609,9 @@ var BaseAnthropic = class {
61546
61609
  makeStatusError(status, error48, message, headers) {
61547
61610
  return APIError.generate(status, error48, message, headers);
61548
61611
  }
61549
- buildURL(path23, query, defaultBaseURL) {
61612
+ buildURL(path24, query, defaultBaseURL) {
61550
61613
  const baseURL = !__classPrivateFieldGet(this, _BaseAnthropic_instances, "m", _BaseAnthropic_baseURLOverridden).call(this) && defaultBaseURL || this.baseURL;
61551
- const url2 = isAbsoluteURL(path23) ? new URL(path23) : new URL(baseURL + (baseURL.endsWith("/") && path23.startsWith("/") ? path23.slice(1) : path23));
61614
+ const url2 = isAbsoluteURL(path24) ? new URL(path24) : new URL(baseURL + (baseURL.endsWith("/") && path24.startsWith("/") ? path24.slice(1) : path24));
61552
61615
  const defaultQuery = this.defaultQuery();
61553
61616
  const pathQuery = Object.fromEntries(url2.searchParams);
61554
61617
  if (!isEmptyObj(defaultQuery) || !isEmptyObj(pathQuery)) {
@@ -61580,24 +61643,24 @@ var BaseAnthropic = class {
61580
61643
  */
61581
61644
  async prepareRequest(request, { url: url2, options }) {
61582
61645
  }
61583
- get(path23, opts) {
61584
- return this.methodRequest("get", path23, opts);
61646
+ get(path24, opts) {
61647
+ return this.methodRequest("get", path24, opts);
61585
61648
  }
61586
- post(path23, opts) {
61587
- return this.methodRequest("post", path23, opts);
61649
+ post(path24, opts) {
61650
+ return this.methodRequest("post", path24, opts);
61588
61651
  }
61589
- patch(path23, opts) {
61590
- return this.methodRequest("patch", path23, opts);
61652
+ patch(path24, opts) {
61653
+ return this.methodRequest("patch", path24, opts);
61591
61654
  }
61592
- put(path23, opts) {
61593
- return this.methodRequest("put", path23, opts);
61655
+ put(path24, opts) {
61656
+ return this.methodRequest("put", path24, opts);
61594
61657
  }
61595
- delete(path23, opts) {
61596
- return this.methodRequest("delete", path23, opts);
61658
+ delete(path24, opts) {
61659
+ return this.methodRequest("delete", path24, opts);
61597
61660
  }
61598
- methodRequest(method, path23, opts) {
61661
+ methodRequest(method, path24, opts) {
61599
61662
  return this.request(Promise.resolve(opts).then((opts2) => {
61600
- return { method, path: path23, ...opts2 };
61663
+ return { method, path: path24, ...opts2 };
61601
61664
  }));
61602
61665
  }
61603
61666
  request(options, remainingRetries = null) {
@@ -61677,7 +61740,7 @@ var BaseAnthropic = class {
61677
61740
  }
61678
61741
  const retryMessage = shouldRetry ? `error; no more retries left` : `error; not retryable`;
61679
61742
  loggerFor(this).info(`${responseInfo} - ${retryMessage}`);
61680
- const errText = await response.text().catch((err19) => castToError(err19).message);
61743
+ const errText = await response.text().catch((err21) => castToError(err21).message);
61681
61744
  const errJSON = safeJSON(errText);
61682
61745
  const errMessage = errJSON ? void 0 : errText;
61683
61746
  loggerFor(this).debug(`[${requestLogID}] response error (${retryMessage})`, formatRequestDetails({
@@ -61688,8 +61751,8 @@ var BaseAnthropic = class {
61688
61751
  message: errMessage,
61689
61752
  durationMs: Date.now() - startTime
61690
61753
  }));
61691
- const err18 = this.makeStatusError(response.status, errJSON, errMessage, response.headers);
61692
- throw err18;
61754
+ const err20 = this.makeStatusError(response.status, errJSON, errMessage, response.headers);
61755
+ throw err20;
61693
61756
  }
61694
61757
  loggerFor(this).info(responseInfo);
61695
61758
  loggerFor(this).debug(`[${requestLogID}] response start`, formatRequestDetails({
@@ -61701,8 +61764,8 @@ var BaseAnthropic = class {
61701
61764
  }));
61702
61765
  return { response, options, controller: controller2, requestLogID, retryOfRequestLogID, startTime };
61703
61766
  }
61704
- getAPIList(path23, Page2, opts) {
61705
- return this.requestAPIList(Page2, opts && "then" in opts ? opts.then((opts2) => ({ method: "get", path: path23, ...opts2 })) : { method: "get", path: path23, ...opts });
61767
+ getAPIList(path24, Page2, opts) {
61768
+ return this.requestAPIList(Page2, opts && "then" in opts ? opts.then((opts2) => ({ method: "get", path: path24, ...opts2 })) : { method: "get", path: path24, ...opts });
61706
61769
  }
61707
61770
  requestAPIList(Page2, options) {
61708
61771
  const request = this.makeRequest(options, null, void 0);
@@ -61768,7 +61831,7 @@ var BaseAnthropic = class {
61768
61831
  const maxRetries = options.maxRetries ?? this.maxRetries;
61769
61832
  timeoutMillis = this.calculateDefaultRetryTimeoutMillis(retriesRemaining, maxRetries);
61770
61833
  }
61771
- await sleep3(timeoutMillis);
61834
+ await sleep4(timeoutMillis);
61772
61835
  return this.makeRequest(options, retriesRemaining - 1, requestLogID);
61773
61836
  }
61774
61837
  calculateDefaultRetryTimeoutMillis(retriesRemaining, maxRetries) {
@@ -61790,8 +61853,8 @@ var BaseAnthropic = class {
61790
61853
  }
61791
61854
  async buildRequest(inputOptions, { retryCount = 0 } = {}) {
61792
61855
  const options = { ...inputOptions };
61793
- const { method, path: path23, query, defaultBaseURL } = options;
61794
- const url2 = this.buildURL(path23, query, defaultBaseURL);
61856
+ const { method, path: path24, query, defaultBaseURL } = options;
61857
+ const url2 = this.buildURL(path24, query, defaultBaseURL);
61795
61858
  if ("timeout" in options)
61796
61859
  validatePositiveInteger("timeout", options.timeout);
61797
61860
  options.timeout = options.timeout ?? this.timeout;
@@ -62132,25 +62195,25 @@ var import_neverthrow31 = __toESM(require_index_cjs(), 1);
62132
62195
  var import_neverthrow32 = __toESM(require_index_cjs(), 1);
62133
62196
  var import_node_fs3 = require("node:fs");
62134
62197
  var import_neverthrow33 = __toESM(require_index_cjs(), 1);
62135
- var import_promises15 = require("node:timers/promises");
62198
+ var import_promises16 = require("node:timers/promises");
62136
62199
 
62137
62200
  // ../../agents/explorer/dist/index.js
62138
62201
  var import_node_child_process3 = require("node:child_process");
62139
62202
  var import_node_fs = require("node:fs");
62140
62203
  var import_node_path4 = __toESM(require("node:path"), 1);
62141
62204
  var import_neverthrow15 = __toESM(require_index_cjs(), 1);
62142
- var import_promises8 = require("node:timers/promises");
62205
+ var import_promises9 = require("node:timers/promises");
62143
62206
  var import_neverthrow16 = __toESM(require_index_cjs(), 1);
62144
62207
  var import_neverthrow17 = __toESM(require_index_cjs(), 1);
62145
- var import_promises9 = require("node:fs/promises");
62208
+ var import_promises10 = require("node:fs/promises");
62146
62209
  var import_node_path5 = __toESM(require("node:path"), 1);
62147
62210
  var import_neverthrow18 = __toESM(require_index_cjs(), 1);
62148
62211
  var import_node_child_process4 = require("node:child_process");
62149
- var import_promises10 = require("node:fs/promises");
62212
+ var import_promises11 = require("node:fs/promises");
62150
62213
  var import_neverthrow19 = __toESM(require_index_cjs(), 1);
62151
62214
  var import_neverthrow20 = __toESM(require_index_cjs(), 1);
62152
62215
  var import_neverthrow21 = __toESM(require_index_cjs(), 1);
62153
- var import_promises11 = require("node:fs/promises");
62216
+ var import_promises12 = require("node:fs/promises");
62154
62217
  var import_node_path6 = __toESM(require("node:path"), 1);
62155
62218
  var import_neverthrow22 = __toESM(require_index_cjs(), 1);
62156
62219
  async function runFfmpeg(arguments_) {
@@ -62166,7 +62229,7 @@ async function runFfmpeg(arguments_) {
62166
62229
  }
62167
62230
  function spawnRecorder(outputPath) {
62168
62231
  const safeMkdirSync = (0, import_neverthrow15.fromThrowable)(import_node_fs.mkdirSync, (cause) => cause);
62169
- const safeSpawn = (0, import_neverthrow15.fromThrowable)(
62232
+ const safeSpawn2 = (0, import_neverthrow15.fromThrowable)(
62170
62233
  (command, arguments_) => (0, import_node_child_process3.spawn)(command, arguments_),
62171
62234
  (cause) => cause
62172
62235
  );
@@ -62174,7 +62237,7 @@ function spawnRecorder(outputPath) {
62174
62237
  if (mkdirResult.isErr()) {
62175
62238
  return mkdirResult.error;
62176
62239
  }
62177
- const spawnResult = safeSpawn("xcrun", [
62240
+ const spawnResult = safeSpawn2("xcrun", [
62178
62241
  "simctl",
62179
62242
  "io",
62180
62243
  "booted",
@@ -62251,9 +62314,11 @@ function speedUpVideo({
62251
62314
  );
62252
62315
  }
62253
62316
  var VIEW_UI_TOOL_NAME = "mcp__mobile-ios__view_ui";
62254
- var VIEW_UI_DESCRIPTION = `Capture the current screen state: accessibility snapshot (element list with positions) and screenshot. Call this after every action to observe the result.
62317
+ 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>.
62318
+
62319
+ The result begins with a <screen_id> tag containing the current screen identifier. Use this to detect screen changes and track navigation history.
62255
62320
 
62256
- The result begins with a <screen_id> tag containing the current screen identifier. Use this to track which screen you are on.
62321
+ Do not call \`screenshot\` immediately before or after this tool for the same state \u2014 this tool already includes the screenshot.
62257
62322
 
62258
62323
  IMPORTANT: Snapshot coordinates and screenshot pixels are in the same logical point space. Do not apply any scaling factor (no 2x retina adjustment).`;
62259
62324
  function deriveScreenLabel(tree, stepIndex) {
@@ -62266,7 +62331,7 @@ function deriveScreenLabel(tree, stepIndex) {
62266
62331
  async function persistScreenshot(params) {
62267
62332
  const screenshotPath = import_node_path5.default.join(params.screenshotsDirectory, `${params.screenLabel}.png`);
62268
62333
  const safeWriteFile = (0, import_neverthrow18.fromAsyncThrowable)(
62269
- import_promises9.writeFile,
62334
+ import_promises10.writeFile,
62270
62335
  (cause) => ({ type: "WRITE_FAILED", cause })
62271
62336
  );
62272
62337
  const writeResult = safeWriteFile(screenshotPath, Buffer.from(params.data, "base64"));
@@ -62331,7 +62396,7 @@ function buildSnapshotRecord(rawElements, { stepIndex, context }) {
62331
62396
  async function handleScreenshotData(data, params) {
62332
62397
  if (params.context.screenshotsDir !== void 0) {
62333
62398
  const safeWrite2 = (0, import_neverthrow18.fromAsyncThrowable)(
62334
- import_promises9.writeFile,
62399
+ import_promises10.writeFile,
62335
62400
  (cause) => ({ type: "WRITE_FAILED", cause })
62336
62401
  );
62337
62402
  const snapshotPath = import_node_path5.default.join(params.context.screenshotsDir, `${params.screenLabel}.txt`);
@@ -62578,32 +62643,11 @@ function spawnDetached(options) {
62578
62643
  off: child.off.bind(child)
62579
62644
  };
62580
62645
  }
62581
- var cachedAllTools;
62582
- async function fetchAllTools() {
62583
- if (cachedAllTools !== void 0) {
62584
- return cachedAllTools;
62585
- }
62586
- const probe = Qs({ prompt: "", options: { settingSources: ["user"] } });
62587
- for await (const message of probe) {
62588
- if (message.type === "system" && message.subtype === "init") {
62589
- probe.close();
62590
- cachedAllTools = message.tools;
62591
- return cachedAllTools;
62592
- }
62593
- }
62594
- return [];
62595
- }
62596
- async function resolveDisallowedTools(allowedTools) {
62597
- const allTools = await fetchAllTools();
62598
- const allowedSet = new Set(allowedTools);
62599
- return allTools.filter((tool2) => !allowedSet.has(tool2));
62600
- }
62601
62646
  function buildQueryOptions({
62602
62647
  config: config3,
62603
62648
  outputTools,
62604
62649
  mobileIosServer,
62605
- allowedTools,
62606
- disallowedTools
62650
+ allowedTools
62607
62651
  }) {
62608
62652
  const base = {
62609
62653
  mcpServers: {
@@ -62612,8 +62656,9 @@ function buildQueryOptions({
62612
62656
  output: outputTools.server
62613
62657
  },
62614
62658
  allowedTools,
62615
- disallowedTools,
62616
- settingSources: ["user"],
62659
+ tools: [],
62660
+ permissionMode: "bypassPermissions",
62661
+ allowDangerouslySkipPermissions: true,
62617
62662
  spawnClaudeCodeProcess: spawnDetached,
62618
62663
  ...config3.cwd ? { cwd: config3.cwd } : {}
62619
62664
  };
@@ -62664,13 +62709,13 @@ function buildMobileIosServer(config3, state) {
62664
62709
  });
62665
62710
  return createMobileIosServer(config3.udid ?? "booted", [viewUiTool]);
62666
62711
  }
62667
- async function setupQuery(config3, outputTools) {
62712
+ function setupQuery(config3, outputTools) {
62668
62713
  const allowedTools = [
62669
62714
  ...config3.allowedTools ?? [],
62670
62715
  ...outputTools.allowedToolNames,
62671
- VIEW_UI_TOOL_NAME
62672
- ];
62673
- const disallowedTools = await resolveDisallowedTools(allowedTools);
62716
+ VIEW_UI_TOOL_NAME,
62717
+ WAIT_SECONDS_TOOL_NAME
62718
+ ].filter((tool2) => typeof tool2 === "string");
62674
62719
  const inputQueue = new MessageQueue();
62675
62720
  const state = buildAgentState({ config: config3, outputTools, inputQueue });
62676
62721
  const mobileIosServer = buildMobileIosServer(config3, state);
@@ -62678,8 +62723,7 @@ async function setupQuery(config3, outputTools) {
62678
62723
  config: config3,
62679
62724
  outputTools,
62680
62725
  mobileIosServer,
62681
- allowedTools,
62682
- disallowedTools
62726
+ allowedTools
62683
62727
  });
62684
62728
  return { inputQueue, state, options, linkedController };
62685
62729
  }
@@ -62744,7 +62788,7 @@ function startTimeout(timeoutMs, context) {
62744
62788
  var EXPLORER_FINDING_SCHEMA = findingSchema.omit({ agent: true });
62745
62789
  var INTERRUPT_DRAIN_TIMEOUT_MS = 1e4;
62746
62790
  async function interruptOrTimeout(queryRunner) {
62747
- await Promise.race([queryRunner.interrupt(), (0, import_promises8.setTimeout)(INTERRUPT_DRAIN_TIMEOUT_MS)]);
62791
+ await Promise.race([queryRunner.interrupt(), (0, import_promises9.setTimeout)(INTERRUPT_DRAIN_TIMEOUT_MS)]);
62748
62792
  }
62749
62793
  var safeInterruptOrTimeout = import_neverthrow16.ResultAsync.fromThrowable(
62750
62794
  interruptOrTimeout,
@@ -62795,16 +62839,16 @@ function startQueryTimers(config3, context) {
62795
62839
  inputQueue.close();
62796
62840
  };
62797
62841
  }
62798
- function awaitMessagesAndResolve({ queryRunner, state }, { cleanup: cleanup2, getOutput }) {
62842
+ function awaitMessagesAndResolve({ queryRunner, state }, { cleanup: cleanup3, getOutput }) {
62799
62843
  const messagesPromise = processMessages(queryRunner, state);
62800
62844
  return import_neverthrow16.ResultAsync.fromPromise(messagesPromise, String).andThen((innerResult) => {
62801
- cleanup2();
62845
+ cleanup3();
62802
62846
  if (innerResult.isErr()) {
62803
62847
  return (0, import_neverthrow16.err)(innerResult.error);
62804
62848
  }
62805
62849
  return (0, import_neverthrow16.ok)(getOutput());
62806
62850
  }).orElse((sdkError) => {
62807
- cleanup2();
62851
+ cleanup3();
62808
62852
  if (!state.timedOut.value && !state.aborted.value) {
62809
62853
  return (0, import_neverthrow16.err)(sdkError);
62810
62854
  }
@@ -62827,21 +62871,19 @@ function executeQuery({
62827
62871
  return (0, import_neverthrow16.errAsync)(queryRunnerResult.error);
62828
62872
  }
62829
62873
  const queryRunner = queryRunnerResult.value;
62830
- const cleanup2 = startQueryTimers(config3, { state, queryRunner, inputQueue, linkedController });
62874
+ const cleanup3 = startQueryTimers(config3, { state, queryRunner, inputQueue, linkedController });
62831
62875
  const getOutput = () => ({
62832
62876
  findings: (outputTools.getOutput()?.findings ?? []).map(
62833
62877
  (raw) => stampExplorerAgent(raw)
62834
62878
  ),
62835
62879
  snapshots: state.snapshots
62836
62880
  });
62837
- return awaitMessagesAndResolve({ queryRunner, state }, { cleanup: cleanup2, getOutput });
62881
+ return awaitMessagesAndResolve({ queryRunner, state }, { cleanup: cleanup3, getOutput });
62838
62882
  }
62839
62883
  function runQuery(prompt, config3) {
62840
62884
  const outputTools = createOutputTool({ findings: external_exports.array(EXPLORER_FINDING_SCHEMA) });
62841
- const setupPromise = setupQuery(config3, outputTools);
62842
- return import_neverthrow16.ResultAsync.fromPromise(setupPromise, String).andThen(
62843
- (setup) => executeQuery({ prompt, config: config3, outputTools, setup })
62844
- );
62885
+ const setup = setupQuery(config3, outputTools);
62886
+ return executeQuery({ prompt, config: config3, outputTools, setup });
62845
62887
  }
62846
62888
  function collectAgentOutput(prompt, config3) {
62847
62889
  return runQuery(prompt, config3).mapErr((cause) => ({ type: "QUERY_FAILED", cause }));
@@ -62893,6 +62935,12 @@ function startAndRun(params) {
62893
62935
  }).andThen((result) => applySpeedUpVariants({ result, params, toRecordingError }));
62894
62936
  });
62895
62937
  }
62938
+ var TOOL_SELECTION_SECTION = `## Tool Selection
62939
+
62940
+ - \`view_ui\` \u2014 returns accessibility tree (element labels, positions, attributes) AND screenshot; use when you need to tap, assert element presence, or read labels
62941
+ - \`screenshot\` \u2014 returns screenshot only; use for passive visual verification (confirm transition occurred, loading finished, outcome visible) when you do not need element data
62942
+ - Never call \`screenshot\` immediately before or after \`view_ui\` for the same state \u2014 \`view_ui\` already includes the screenshot
62943
+ - \`screenshot\` calls do not emit a \`<screen_id>\` and do not advance the stuck-loop counter; if screen identity tracking matters, use \`view_ui\``;
62896
62944
  var DEV_ENVIRONMENT_SECTION = `## Environment
62897
62945
 
62898
62946
  This is a development build. Debug overlays and internal messages are expected artifacts \u2014 do not report them as findings.`;
@@ -62904,9 +62952,11 @@ At every reasoning step, maintain a mental ledger:
62904
62952
  - PATH: your current navigation stack from root (e.g. Home > Settings > Privacy)
62905
62953
 
62906
62954
  Consult the ledger before every action. Always prefer navigating to a QUEUE screen over a VISITED one.`;
62907
- var BACK_NAV_RULE = `After navigating forward to any new screen: tap back, call \`view_ui\`, confirm you returned to the expected parent in PATH \u2014 if not, emit a \`back-nav-failure\` finding, then navigate forward again to continue`;
62908
- var STUCK_LOOP_RULE = `Stuck loop: emit a \`stuck-loop\` finding when any of these occur: (1) \`view_ui\` returns the same screen state 3 or more consecutive steps, (2) the same element has been tapped more than twice with no screen change, (3) PATH shows the same screen at two non-adjacent positions \u2014 before emitting, try one alternative action (scroll, long-press, swipe) to rule out a gesture mismatch`;
62909
- var LOADING_STATE_RULE = `Transient loading state: when \`view_ui\` reveals spinners, skeleton screens, progress bars, "Loading..." text, or placeholder content NOT described in spec or app context, wait and retry \`view_ui\` up to 3 times before treating screen as final \u2014 if loading persists after 3 retries, proceed with what is visible; if spec or app context explicitly describes a loading screen as a step, do not retry \u2014 inspect and assert normally`;
62955
+ var SESSION_START_RULE = `Before taking any other action \u2014 including initializing the Working State ledger or emitting findings \u2014 call \`view_ui\` once to observe the starting screen`;
62956
+ var BACK_NAV_RULE = `After navigating forward to any new screen: tap back, then confirm you returned to the expected parent in PATH \u2014 use \`screenshot\` if the parent screen is visually unambiguous, \`view_ui\` if you need element labels or coordinates to verify or to act next \u2014 if confirmation fails, emit a \`back-nav-failure\` finding, then navigate forward again to continue`;
62957
+ var STUCK_LOOP_RULE = `Stuck loop: emit a \`stuck-loop\` finding when any of these occur: (1) \`view_ui\` returns the same \`<screen_id>\` across 3 or more consecutive \`view_ui\` calls, (2) the same element has been tapped more than twice with no screen change confirmed by \`view_ui\`, (3) PATH shows the same screen at two non-adjacent positions \u2014 before emitting, try one alternative action (scroll, long-press, swipe) to rule out a gesture mismatch \u2014 note: \`screenshot\`-only calls do not update the stuck-loop counter; only \`view_ui\` calls count`;
62958
+ var LOADING_STATE_RULE = `Transient loading state: when the screen shows spinners, skeleton screens, progress bars, "Loading..." text, or placeholder content NOT described in spec or app context \u2014 use \`screenshot\` to poll for resolution (up to 3 retries); switch to \`view_ui\` only on the final check or when you need element data to act \u2014 if loading persists after 3 retries, proceed with what is visible; if spec or app context explicitly describes a loading screen as a step, do not retry \u2014 call \`view_ui\` and assert normally`;
62959
+ 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`;
62910
62960
  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`;
62911
62961
  var WHAT_TO_TEST_SECTION = `## What to Test
62912
62962
 
@@ -62948,7 +62998,7 @@ Each step has this shape:
62948
62998
  <intent> [\u2192 <outcome>] [hint: <advisory>]
62949
62999
 
62950
63000
  - The intent phrase is your goal. Achieve it by any reasonable UI path.
62951
- - If an outcome state is present, it is your verification target. After acting, call \`view_ui\` and confirm the outcome is met before marking the step complete. If no outcome is given, proceed when the action succeeds.
63001
+ - If an outcome state is present, it is your verification target. After acting, confirm the outcome is met before marking the step complete \u2014 use \`screenshot\` when the outcome is purely visual (screen transition visible, element gone, content appeared); use \`view_ui\` when the outcome requires asserting element labels, attributes, or coordinates. If no outcome is given, proceed when the action succeeds.
62952
63002
  - A hint is advisory only. Prefer an element matching the hint, but if no literal match exists, use intent and visual context to select the best candidate. Never fail a step solely because a hint label is absent.
62953
63003
  - Infer element role (primary action, secondary action, dismissal) from visual hierarchy, position, and hint text. Authors do not specify role.
62954
63004
  - If no element satisfies the intent after exhausting visible UI, emit a \`spec-deviation\` finding and halt that step.`;
@@ -62980,25 +63030,30 @@ ${initialState2}` : void 0,
62980
63030
  }
62981
63031
  var SPEC_RULES_SECTION = `## Rules
62982
63032
 
62983
- - ALWAYS call \`view_ui\` after every action before deciding what to do next \u2014 it is your only way to observe the screen
63033
+ - ${SESSION_START_RULE}
63034
+ - After any action, observe the screen before deciding next step \u2014 use \`screenshot\` when confirming a purely visual outcome (transition occurred, element disappeared, content appeared, loading finished); use \`view_ui\` when you need element labels, tap coordinates, or accessibility attributes
63035
+ - Never call both \`screenshot\` and \`view_ui\` back-to-back for the same observation \u2014 \`view_ui\` includes a screenshot; if you need both tree and image, one \`view_ui\` call suffices
62984
63036
  - ${BACK_NAV_RULE}
62985
63037
  - Before selecting any action, prefer navigating to a QUEUE screen over re-exploring a VISITED one
62986
63038
  - ${STUCK_LOOP_RULE}
62987
63039
  - ${LOADING_STATE_RULE}
63040
+ - ${EXPECTED_CONTENT_MISSING_RULE}
62988
63041
  - ${CLIPPED_ELEMENT_RULE}
62989
- - Each item in \`**Assertions**\` is a mandatory pass/fail check \u2014 verify using \`view_ui\`; if the accessibility tree cannot confirm, emit a \`spec-deviation\` finding based on what is observable
63042
+ - Each item in \`**Assertions**\` is a mandatory pass/fail check \u2014 verify using \`view_ui\` when the assertion targets an element attribute, label, or presence in the tree; use \`screenshot\` when the assertion is purely visual; if neither can confirm, emit a \`spec-deviation\` finding based on what is observable
62990
63043
  - Flag crash dialogs, unexpected system errors, or navigation failures that occur as a direct result of executing a spec step; if you observe a visibly broken element in passing while navigating, note it without interacting with it`;
62991
63044
  function buildSpecModeBody({
62992
63045
  specContent,
62993
63046
  contextBlock,
62994
63047
  environmentSection
62995
63048
  }) {
62996
- return `You are a spec execution agent. Your role is to follow the provided spec exactly \u2014 execute each step in sequence, verify each assertion, and report deviations. Observe and flag obvious breakage encountered in transit, but do not explore or interact with anything outside the spec.
63049
+ return `You are a spec execution agent. Your first action MUST be a \`view_ui\` call. Your role is to follow the provided spec exactly \u2014 execute each step in sequence, verify each assertion, and report deviations. Observe and flag obvious breakage encountered in transit, but do not explore or interact with anything outside the spec.
62997
63050
 
62998
63051
  Verify app against specs below.
62999
63052
 
63000
63053
  ${contextBlock}
63001
63054
 
63055
+ ${TOOL_SELECTION_SECTION}
63056
+
63002
63057
  ${SPEC_RULES_SECTION}
63003
63058
 
63004
63059
  ## Execution Strategy
@@ -63034,17 +63089,22 @@ var FREESTYLE_TEMPLATE = (options) => {
63034
63089
  const environmentSection = buildEnv === "dev" ? `
63035
63090
 
63036
63091
  ${DEV_ENVIRONMENT_SECTION}` : "";
63037
- return `You are a navigation and interaction testing agent. Your role is to find broken navigation flows and non-functional interactive elements. Do not report content bugs, copy errors, or visual style issues unless they directly prevent a navigation action from completing.
63092
+ return `You are a navigation and interaction testing agent. Your first action MUST be a \`view_ui\` call. Your role is to find broken navigation flows and non-functional interactive elements. Do not report content bugs, copy errors, or visual style issues unless they directly prevent a navigation action from completing.
63038
63093
 
63039
63094
  ${contextBlock}
63040
63095
 
63096
+ ${TOOL_SELECTION_SECTION}
63097
+
63041
63098
  ## Rules
63042
63099
 
63043
- - ALWAYS call \`view_ui\` after every action before deciding what to do next \u2014 it is your only way to observe the screen
63100
+ - ${SESSION_START_RULE}
63101
+ - After any action, observe the screen before deciding next step \u2014 use \`screenshot\` when confirming a purely visual outcome (transition occurred, element disappeared, content appeared, loading finished); use \`view_ui\` when you need element labels, tap coordinates, or accessibility attributes
63102
+ - Never call both \`screenshot\` and \`view_ui\` back-to-back for the same observation \u2014 \`view_ui\` includes a screenshot; if you need both tree and image, one \`view_ui\` call suffices
63044
63103
  - ${BACK_NAV_RULE}
63045
63104
  - Before selecting any action, prefer navigating to a QUEUE screen over re-exploring a VISITED one
63046
63105
  - ${STUCK_LOOP_RULE}
63047
63106
  - ${LOADING_STATE_RULE}
63107
+ - ${EXPECTED_CONTENT_MISSING_RULE}
63048
63108
  - ${CLIPPED_ELEMENT_RULE}
63049
63109
 
63050
63110
  ## Exploration Strategy
@@ -63259,7 +63319,7 @@ function direntToSpecEntry(directory, entry) {
63259
63319
  }
63260
63320
  function scanDirectory(directory) {
63261
63321
  const safeReaddir3 = (0, import_neverthrow22.fromAsyncThrowable)(
63262
- async () => (0, import_promises11.readdir)(directory, { withFileTypes: true }),
63322
+ async () => (0, import_promises12.readdir)(directory, { withFileTypes: true }),
63263
63323
  (cause) => ({ type: "DIR_READ_FAILED", dir: directory, cause })
63264
63324
  );
63265
63325
  return safeReaddir3().orElse((error48) => isNotFound(error48.cause) ? (0, import_neverthrow22.okAsync)([]) : (0, import_neverthrow22.errAsync)(error48)).map(
@@ -63273,7 +63333,7 @@ function readEntries(entries) {
63273
63333
  }
63274
63334
  function readEntry(entry) {
63275
63335
  const safeReadFile6 = (0, import_neverthrow22.fromAsyncThrowable)(
63276
- async () => (0, import_promises11.readFile)(entry.path, "utf8"),
63336
+ async () => (0, import_promises12.readFile)(entry.path, "utf8"),
63277
63337
  (cause) => ({ type: "FILE_READ_FAILED", path: entry.path, cause })
63278
63338
  );
63279
63339
  return safeReadFile6().map((content) => [{ name: entry.name, content }]).orElse((error48) => entry.required ? (0, import_neverthrow22.errAsync)(error48) : (0, import_neverthrow22.okAsync)([]));
@@ -63398,7 +63458,7 @@ function runExplorer(config3) {
63398
63458
  };
63399
63459
  safeConfig.onEvent?.({ type: "STAGE_START", agent: "explorer" });
63400
63460
  return import_neverthrow19.ResultAsync.fromSafePromise(
63401
- (0, import_promises10.mkdir)(runPaths.screenshotsDir, { recursive: true }).catch(() => null)
63461
+ (0, import_promises11.mkdir)(runPaths.screenshotsDir, { recursive: true }).catch(() => null)
63402
63462
  ).andThen(() => runPipeline({ safeConfig, runPaths, start }));
63403
63463
  }
63404
63464
 
@@ -63407,14 +63467,14 @@ var import_neverthrow34 = __toESM(require_index_cjs(), 1);
63407
63467
 
63408
63468
  // ../../agents/inspector/dist/index.js
63409
63469
  var import_neverthrow23 = __toESM(require_index_cjs(), 1);
63410
- var import_promises12 = require("node:fs/promises");
63470
+ var import_promises13 = require("node:fs/promises");
63411
63471
  var import_neverthrow24 = __toESM(require_index_cjs(), 1);
63412
63472
  var import_neverthrow25 = __toESM(require_index_cjs(), 1);
63413
63473
  var import_neverthrow26 = __toESM(require_index_cjs(), 1);
63414
63474
  var import_neverthrow27 = __toESM(require_index_cjs(), 1);
63415
63475
  var import_sharp2 = __toESM(require("sharp"), 1);
63416
63476
  var import_neverthrow28 = __toESM(require_index_cjs(), 1);
63417
- var import_promises13 = require("node:fs/promises");
63477
+ var import_promises14 = require("node:fs/promises");
63418
63478
  var import_node_path7 = __toESM(require("node:path"), 1);
63419
63479
 
63420
63480
  // ../../node_modules/.pnpm/js-yaml@4.1.1/node_modules/js-yaml/dist/js-yaml.mjs
@@ -64380,7 +64440,7 @@ var directiveHandlers = {
64380
64440
  }
64381
64441
  try {
64382
64442
  prefix = decodeURIComponent(prefix);
64383
- } catch (err18) {
64443
+ } catch (err20) {
64384
64444
  throwError(state, "tag prefix is malformed: " + prefix);
64385
64445
  }
64386
64446
  state.tagMap[handle] = prefix;
@@ -65061,7 +65121,7 @@ function readTagProperty(state) {
65061
65121
  }
65062
65122
  try {
65063
65123
  tagName = decodeURIComponent(tagName);
65064
- } catch (err18) {
65124
+ } catch (err20) {
65065
65125
  throwError(state, "tag name is malformed: " + tagName);
65066
65126
  }
65067
65127
  if (isVerbatim) {
@@ -66730,7 +66790,7 @@ async function initArtboardNames({ designStore, config: config3, state }) {
66730
66790
  }
66731
66791
  function readScreenshot(screenshotPath, stepIndex) {
66732
66792
  return import_neverthrow24.ResultAsync.fromThrowable(
66733
- import_promises12.readFile,
66793
+ import_promises13.readFile,
66734
66794
  (cause) => ({ type: "SCREENSHOT_READ_FAILED", stepIndex, cause })
66735
66795
  )(screenshotPath);
66736
66796
  }
@@ -66825,7 +66885,7 @@ function parseMeta(raw) {
66825
66885
  return {};
66826
66886
  }
66827
66887
  async function readAndParseSidecar(sidecarPath) {
66828
- const raw = await (0, import_promises13.readFile)(sidecarPath, "utf8");
66888
+ const raw = await (0, import_promises14.readFile)(sidecarPath, "utf8");
66829
66889
  return parseMeta(raw);
66830
66890
  }
66831
66891
  function readSidecarFile(sidecarPath) {
@@ -66856,7 +66916,7 @@ var FsDesignStore = class {
66856
66916
  }
66857
66917
  listArtboards() {
66858
66918
  return (0, import_neverthrow29.fromAsyncThrowable)(
66859
- import_promises13.readdir,
66919
+ import_promises14.readdir,
66860
66920
  wrapFsError
66861
66921
  )(this.designsDirectory).orElse((fsError) => {
66862
66922
  if (fsError.type === "FS_ERROR" && isEnoent(fsError.cause)) {
@@ -66871,7 +66931,7 @@ var FsDesignStore = class {
66871
66931
  const pngPath = import_node_path7.default.join(this.designsDirectory, `${filename}.png`);
66872
66932
  const sidecarPath = import_node_path7.default.join(this.designsDirectory, `${filename}.meta.yaml`);
66873
66933
  return (0, import_neverthrow29.fromAsyncThrowable)(
66874
- import_promises13.readFile,
66934
+ import_promises14.readFile,
66875
66935
  wrapFsError
66876
66936
  )(pngPath).orElse((fsError) => {
66877
66937
  if (fsError.type === "FS_ERROR" && isEnoent(fsError.cause)) {
@@ -66929,7 +66989,7 @@ function runAnalyserWithRetry(params) {
66929
66989
  ),
66930
66990
  {
66931
66991
  config: { maxAttempts: RETRY_MAX_ATTEMPTS, baseDelayMs: RETRY_BASE_DELAY_MS },
66932
- delayFunction: import_promises14.setTimeout,
66992
+ delayFunction: import_promises15.setTimeout,
66933
66993
  onRetry: ({ attempt, maxAttempts, delayMs, error: error48 }) => {
66934
66994
  onEvent?.({
66935
66995
  type: "AGENT_RETRY",
@@ -67118,7 +67178,7 @@ function runExplorerWithRetry(options) {
67118
67178
  const { explorerConfig, udid, onEvent } = options;
67119
67179
  return withRetry(() => runExplorerWithTeardown(explorerConfig, udid), {
67120
67180
  config: { maxAttempts: RETRY_MAX_ATTEMPTS, baseDelayMs: RETRY_BASE_DELAY_MS },
67121
- delayFunction: import_promises15.setTimeout,
67181
+ delayFunction: import_promises16.setTimeout,
67122
67182
  onRetry: ({ attempt, maxAttempts, delayMs, error: error48 }) => {
67123
67183
  onEvent?.({
67124
67184
  type: "AGENT_RETRY",
@@ -67278,7 +67338,7 @@ function runPipeline2(config3) {
67278
67338
  }
67279
67339
 
67280
67340
  // src/commands/analyse-command.ts
67281
- var import_neverthrow35 = __toESM(require_index_cjs(), 1);
67341
+ var import_neverthrow36 = __toESM(require_index_cjs(), 1);
67282
67342
 
67283
67343
  // src/commands/item-events.ts
67284
67344
  function emitItemStart(identity, at) {
@@ -67313,6 +67373,272 @@ function emitItemFailed(input) {
67313
67373
  });
67314
67374
  }
67315
67375
 
67376
+ // src/shell/debug-agent-events.ts
67377
+ var import_neverthrow35 = __toESM(require_index_cjs(), 1);
67378
+
67379
+ // src/constants.ts
67380
+ var MOBILE_IOS_TOOLS = [
67381
+ "mcp__mobile-ios__tap",
67382
+ "mcp__mobile-ios__double_tap",
67383
+ "mcp__mobile-ios__long_press",
67384
+ "mcp__mobile-ios__swipe",
67385
+ "mcp__mobile-ios__type_text",
67386
+ "mcp__mobile-ios__press_button",
67387
+ "mcp__mobile-ios__launch_app",
67388
+ "mcp__mobile-ios__terminate_app",
67389
+ "mcp__mobile-ios__list_apps",
67390
+ "mcp__mobile-ios__screenshot",
67391
+ "mcp__mobile-ios__accessibility_snapshot"
67392
+ ];
67393
+ var ALLOWED_TOOLS = [...MOBILE_IOS_TOOLS];
67394
+ var MS_PER_SECOND4 = 1e3;
67395
+ var DEFAULT_ABORT_EXIT_CODE = 130;
67396
+ var IDB_INSTALL_MESSAGE = "idb is not installed. Run:\n brew install idb-companion\n pipx install fb-idb\n";
67397
+ var FFMPEG_INSTALL_MESSAGE = "ffmpeg is not installed. Run:\n brew install ffmpeg\n";
67398
+
67399
+ // src/shell/debug-logger-core.ts
67400
+ var ELAPSED_PAD = 8;
67401
+ function formatElapsed(elapsedMs) {
67402
+ const seconds = (elapsedMs / MS_PER_SECOND4).toFixed(2);
67403
+ return `+${seconds}s`.padStart(ELAPSED_PAD, " ");
67404
+ }
67405
+ function createCallTracker() {
67406
+ const starts = /* @__PURE__ */ new Map();
67407
+ return {
67408
+ mark: (key, at) => {
67409
+ const queue = starts.get(key) ?? [];
67410
+ queue.push(at);
67411
+ starts.set(key, queue);
67412
+ },
67413
+ pop: (key) => {
67414
+ const queue = starts.get(key);
67415
+ const start = queue?.shift();
67416
+ if (queue?.length === 0) {
67417
+ starts.delete(key);
67418
+ }
67419
+ return start;
67420
+ }
67421
+ };
67422
+ }
67423
+ function buildLogger(options) {
67424
+ const now = options.now ?? Date.now;
67425
+ const write = options.write ?? ((line) => process.stderr.write(line));
67426
+ const startedAt = now();
67427
+ const tracker = createCallTracker();
67428
+ return {
67429
+ log: (tag, detail) => {
67430
+ const elapsed = now() - startedAt;
67431
+ write(`[debug] ${formatElapsed(elapsed)} ${tag} ${detail}
67432
+ `);
67433
+ },
67434
+ markCall: (key) => {
67435
+ tracker.mark(key, now());
67436
+ },
67437
+ elapsedSince: (key) => {
67438
+ const start = tracker.pop(key);
67439
+ return start === void 0 ? void 0 : now() - start;
67440
+ }
67441
+ };
67442
+ }
67443
+ function formatDurationSuffix(duration3) {
67444
+ if (duration3 === void 0) {
67445
+ return "";
67446
+ }
67447
+ return ` duration=${String(duration3)}ms`;
67448
+ }
67449
+ function formatOptionalNumber(value) {
67450
+ return value === void 0 ? "?" : String(value);
67451
+ }
67452
+
67453
+ // src/shell/debug-agent-events.ts
67454
+ var TOOL_INPUT_MAX = 120;
67455
+ var TOOL_ERROR_MAX = 120;
67456
+ var UNSERIALIZABLE = "[unserializable]";
67457
+ function tryStringify(value) {
67458
+ const result = JSON.stringify(value);
67459
+ return result ?? UNSERIALIZABLE;
67460
+ }
67461
+ var safeStringify = (0, import_neverthrow35.fromThrowable)(tryStringify, () => ({
67462
+ type: "STRINGIFY_FAILED"
67463
+ }));
67464
+ function toolKey(scope, event) {
67465
+ const prefix = scope === void 0 ? "" : `${scope}:`;
67466
+ return `${prefix}${event.agent}:${event.toolName}`;
67467
+ }
67468
+ function stringifyToolInput(input) {
67469
+ if (input === void 0 || input === null) {
67470
+ return "";
67471
+ }
67472
+ if (typeof input === "string") {
67473
+ return input;
67474
+ }
67475
+ return safeStringify(input).unwrapOr(UNSERIALIZABLE);
67476
+ }
67477
+ function truncate(value, max) {
67478
+ return value.length > max ? `${value.slice(0, max)}\u2026` : value;
67479
+ }
67480
+ function handleStageStart(context, event) {
67481
+ context.logger.log(
67482
+ "STAGE_START",
67483
+ `${event.agent} steps=${formatOptionalNumber(event.totalSteps)}`
67484
+ );
67485
+ }
67486
+ function handleStageEnd(context, event) {
67487
+ context.logger.log("STAGE_END", `${event.agent} duration=${String(event.durationMs)}ms`);
67488
+ }
67489
+ function handleToolCall(context, event) {
67490
+ context.logger.markCall(toolKey(context.scope, event));
67491
+ const input = truncate(stringifyToolInput(event.input), TOOL_INPUT_MAX);
67492
+ context.logger.log("TOOL_CALL", `${event.agent} ${event.toolName} ${input}`);
67493
+ }
67494
+ function handleToolResult(context, event) {
67495
+ const suffix = formatDurationSuffix(context.logger.elapsedSince(toolKey(context.scope, event)));
67496
+ context.logger.log("TOOL_RESULT", `${event.agent} ${event.toolName}${suffix}`);
67497
+ }
67498
+ function handleToolError(context, event) {
67499
+ const suffix = formatDurationSuffix(context.logger.elapsedSince(toolKey(context.scope, event)));
67500
+ const error48 = truncate(event.error, TOOL_ERROR_MAX);
67501
+ context.logger.log("TOOL_ERROR", `${event.agent} ${event.toolName}${suffix} ${error48}`);
67502
+ }
67503
+ function handleAgentRetry(context, event) {
67504
+ context.logger.log(
67505
+ "AGENT_RETRY",
67506
+ `${event.agent} attempt=${String(event.attempt)}/${String(event.maxAttempts)} delay=${String(event.delayMs)}ms`
67507
+ );
67508
+ }
67509
+ function handleAgentFailed(context, event) {
67510
+ context.logger.log(
67511
+ "AGENT_FAILED_NON_CRITICAL",
67512
+ `${event.agent} attempts=${String(event.attempts)}`
67513
+ );
67514
+ }
67515
+ function handleTimeoutGrace(context, event) {
67516
+ context.logger.log(
67517
+ "TIMEOUT_GRACE_ENTERED",
67518
+ `${event.agent} grace=${String(event.gracePeriodMs)}ms`
67519
+ );
67520
+ }
67521
+ function handleInspectorStepStart(context, event) {
67522
+ context.logger.log(
67523
+ "INSPECTOR_STEP_START",
67524
+ `step=${String(event.stepIndex)}/${formatOptionalNumber(event.totalSteps)} screen=${event.screenLabel}`
67525
+ );
67526
+ }
67527
+ function handleInspectorStep(context, event) {
67528
+ context.logger.log(
67529
+ "INSPECTOR_STEP",
67530
+ `step=${String(event.stepIndex)} screen=${event.screenLabel} outcome=${event.outcome}`
67531
+ );
67532
+ }
67533
+ function handleVisualStep(context, event) {
67534
+ context.logger.log("VISUAL_STEP", `step=${String(event.stepIndex)} screen=${event.screenLabel}`);
67535
+ }
67536
+ function handleError(context, event) {
67537
+ context.logger.log("ERROR", `${event.agent} ${event.message}`);
67538
+ }
67539
+ var AGENT_EVENT_HANDLERS = {
67540
+ STAGE_START: handleStageStart,
67541
+ STAGE_END: handleStageEnd,
67542
+ TOOL_CALL: handleToolCall,
67543
+ TOOL_RESULT: handleToolResult,
67544
+ TOOL_ERROR: handleToolError,
67545
+ AGENT_RETRY: handleAgentRetry,
67546
+ AGENT_FAILED_NON_CRITICAL: handleAgentFailed,
67547
+ TIMEOUT_GRACE_ENTERED: handleTimeoutGrace,
67548
+ INSPECTOR_STEP_START: handleInspectorStepStart,
67549
+ INSPECTOR_STEP: handleInspectorStep,
67550
+ VISUAL_STEP: handleVisualStep,
67551
+ ERROR: handleError
67552
+ };
67553
+ function handleAgentEvent(context, event) {
67554
+ const handler = AGENT_EVENT_HANDLERS[event.type];
67555
+ if (handler === void 0) {
67556
+ return;
67557
+ }
67558
+ handler(context, event);
67559
+ }
67560
+
67561
+ // src/shell/debug-suite-events.ts
67562
+ function handleItemQueued(logger, event) {
67563
+ logger.log("ITEM_QUEUED", `id=${event.item.id} name=${event.item.name}`);
67564
+ }
67565
+ function handleItemStarted(logger, event) {
67566
+ logger.log(
67567
+ "ITEM_STARTED",
67568
+ `id=${event.itemId} name=${event.itemName} sim=${event.simulatorUdid}`
67569
+ );
67570
+ }
67571
+ function handleItemCompleted(logger, event) {
67572
+ logger.log(
67573
+ "ITEM_COMPLETED",
67574
+ `id=${event.itemId} findings=${String(event.findingsCount)} duration=${String(event.durationMs)}ms`
67575
+ );
67576
+ }
67577
+ function handleItemFailed(logger, event) {
67578
+ logger.log(
67579
+ "ITEM_FAILED",
67580
+ `id=${event.itemId} error=${event.error} duration=${String(event.durationMs)}ms`
67581
+ );
67582
+ }
67583
+ function handleItemTimeout(logger, event) {
67584
+ logger.log("ITEM_TIMEOUT", `id=${event.itemId} duration=${String(event.durationMs)}ms`);
67585
+ }
67586
+ function handleSimulatorUnhealthy(logger, event) {
67587
+ logger.log(
67588
+ "SIMULATOR_UNHEALTHY",
67589
+ `sim=${event.simulatorUdid} failures=${String(event.consecutiveFailures)}`
67590
+ );
67591
+ }
67592
+ function handleSuiteCompleted(logger, event) {
67593
+ logger.log(
67594
+ "SUITE_COMPLETED",
67595
+ `items=${String(event.totalItems)} findings=${String(event.totalFindings)} duration=${String(event.durationMs)}ms aborted=${String(event.aborted)}`
67596
+ );
67597
+ }
67598
+ var SUITE_EVENT_HANDLERS = {
67599
+ ITEM_QUEUED: handleItemQueued,
67600
+ ITEM_STARTED: handleItemStarted,
67601
+ ITEM_COMPLETED: handleItemCompleted,
67602
+ ITEM_FAILED: handleItemFailed,
67603
+ ITEM_TIMEOUT: handleItemTimeout,
67604
+ SIMULATOR_UNHEALTHY: handleSimulatorUnhealthy,
67605
+ SUITE_COMPLETED: handleSuiteCompleted
67606
+ };
67607
+ function handleSuiteEvent(logger, event) {
67608
+ const handler = SUITE_EVENT_HANDLERS[event.type];
67609
+ if (handler === void 0) {
67610
+ return;
67611
+ }
67612
+ handler(logger, event);
67613
+ }
67614
+
67615
+ // src/shell/debug-logger.ts
67616
+ function passthroughAgent(handler) {
67617
+ return handler;
67618
+ }
67619
+ function passthroughSuite(handler) {
67620
+ return handler;
67621
+ }
67622
+ function createDebugLogger(options) {
67623
+ if (options.enabled !== true) {
67624
+ return {
67625
+ wrapAgentHandler: passthroughAgent,
67626
+ wrapSuiteHandler: passthroughSuite
67627
+ };
67628
+ }
67629
+ const logger = buildLogger(options);
67630
+ return {
67631
+ wrapAgentHandler: (handler, scope) => (event) => {
67632
+ handleAgentEvent({ logger, scope }, event);
67633
+ handler(event);
67634
+ },
67635
+ wrapSuiteHandler: (handler) => (event) => {
67636
+ handleSuiteEvent(logger, event);
67637
+ handler(event);
67638
+ }
67639
+ };
67640
+ }
67641
+
67316
67642
  // src/shell/trigger-abort.ts
67317
67643
  function triggerAbort() {
67318
67644
  process.kill(process.pid, "SIGINT");
@@ -67353,7 +67679,7 @@ function buildArtifacts(videoPath) {
67353
67679
  return { videoPath, videoPath2x: "", videoPath4x: videoPath, findings: [], snapshots: [] };
67354
67680
  }
67355
67681
  async function checkVideoPathExists(videoPath) {
67356
- const safeAccess = (0, import_neverthrow35.fromAsyncThrowable)(import_promises16.access, () => ({ type: "FILE_NOT_FOUND" }));
67682
+ const safeAccess = (0, import_neverthrow36.fromAsyncThrowable)(import_promises17.access, () => ({ type: "FILE_NOT_FOUND" }));
67357
67683
  const result = await safeAccess(videoPath);
67358
67684
  return result.isOk();
67359
67685
  }
@@ -67374,20 +67700,32 @@ function handleAnalyseError(state, errorType) {
67374
67700
  `);
67375
67701
  process.exit(1);
67376
67702
  }
67377
- async function runAnalysisAndExit(artifacts, apiKey) {
67378
- const identity = {
67703
+ function buildAnalyseIdentity() {
67704
+ return {
67379
67705
  display: createSoloDisplay(),
67380
67706
  itemId: ITEM_ID,
67381
67707
  itemName: ITEM_NAME,
67382
67708
  simulatorUdid: ""
67383
67709
  };
67384
- const startedAt = Date.now();
67385
- emitItemStart(identity, startedAt);
67386
- const onEvent = (event) => {
67710
+ }
67711
+ function buildAnalyseEventHandler(identity, debug) {
67712
+ const debugLogger = createDebugLogger({ enabled: debug });
67713
+ const baseHandler = (event) => {
67387
67714
  identity.display.onEvent({ ...event, itemId: ITEM_ID });
67388
67715
  };
67716
+ return debugLogger.wrapAgentHandler(baseHandler);
67717
+ }
67718
+ async function runAnalysisAndExit(input) {
67719
+ const identity = buildAnalyseIdentity();
67720
+ const startedAt = Date.now();
67721
+ emitItemStart(identity, startedAt);
67722
+ const onEvent = buildAnalyseEventHandler(identity, input.debug);
67389
67723
  const state = { identity, startedAt };
67390
- const result = await runAnalysis(artifacts, { apiKey, videoVariant: "1x", onEvent });
67724
+ const result = await runAnalysis(input.artifacts, {
67725
+ apiKey: input.apiKey,
67726
+ videoVariant: "1x",
67727
+ onEvent
67728
+ });
67391
67729
  result.match(
67392
67730
  (findings) => {
67393
67731
  handleAnalyseSuccess(state, findings);
@@ -67397,13 +67735,16 @@ async function runAnalysisAndExit(artifacts, apiKey) {
67397
67735
  }
67398
67736
  );
67399
67737
  }
67400
- async function runAnalyseCommand(videoPath, config3) {
67738
+ function ensureApiKey(config3) {
67401
67739
  const apiKey = config3.GOOGLE_GENERATIVE_AI_API_KEY ?? "";
67402
67740
  if (!apiKey) {
67403
67741
  process.stderr.write("GOOGLE_GENERATIVE_AI_API_KEY is not set\n");
67404
67742
  process.exit(1);
67405
67743
  return;
67406
67744
  }
67745
+ return apiKey;
67746
+ }
67747
+ async function resolveVideoPath2(videoPath) {
67407
67748
  if (videoPath === void 0) {
67408
67749
  process.stderr.write('A video path is required. Pass the path printed by "xqa explore".\n');
67409
67750
  process.exit(1);
@@ -67415,11 +67756,26 @@ async function runAnalyseCommand(videoPath, config3) {
67415
67756
  process.exit(1);
67416
67757
  return;
67417
67758
  }
67418
- await runAnalysisAndExit(buildArtifacts(videoPath), apiKey);
67759
+ return videoPath;
67760
+ }
67761
+ async function runAnalyseCommand(input) {
67762
+ const apiKey = ensureApiKey(input.config);
67763
+ if (apiKey === void 0) {
67764
+ return;
67765
+ }
67766
+ const videoPath = await resolveVideoPath2(input.videoPath);
67767
+ if (videoPath === void 0) {
67768
+ return;
67769
+ }
67770
+ await runAnalysisAndExit({
67771
+ artifacts: buildArtifacts(videoPath),
67772
+ apiKey,
67773
+ debug: input.debug
67774
+ });
67419
67775
  }
67420
67776
 
67421
67777
  // src/core/completion-generator.ts
67422
- var import_neverthrow36 = __toESM(require_index_cjs(), 1);
67778
+ var import_neverthrow37 = __toESM(require_index_cjs(), 1);
67423
67779
  function extractLongFlags(flags) {
67424
67780
  return flags.split(/[\s,]+/).filter((token) => token.startsWith("--"));
67425
67781
  }
@@ -67509,9 +67865,9 @@ complete -F _xqa_completion xqa`;
67509
67865
  }
67510
67866
  function generateCompletion(commands, shell) {
67511
67867
  if (shell !== "bash" && shell !== "zsh") {
67512
- return (0, import_neverthrow36.err)({ type: "UNSUPPORTED_SHELL", shell });
67868
+ return (0, import_neverthrow37.err)({ type: "UNSUPPORTED_SHELL", shell });
67513
67869
  }
67514
- return (0, import_neverthrow36.ok)(shell === "zsh" ? generateZshCompletion(commands) : generateBashCompletion(commands));
67870
+ return (0, import_neverthrow37.ok)(shell === "zsh" ? generateZshCompletion(commands) : generateBashCompletion(commands));
67515
67871
  }
67516
67872
 
67517
67873
  // src/commands/completion-command.ts
@@ -67546,39 +67902,19 @@ function runCompletionCommand(program3, shell) {
67546
67902
  // src/commands/explore-command.ts
67547
67903
  var import_node_path10 = __toESM(require("node:path"), 1);
67548
67904
 
67549
- // src/constants.ts
67550
- var MOBILE_IOS_TOOLS = [
67551
- "mcp__mobile-ios__tap",
67552
- "mcp__mobile-ios__double_tap",
67553
- "mcp__mobile-ios__long_press",
67554
- "mcp__mobile-ios__swipe",
67555
- "mcp__mobile-ios__type_text",
67556
- "mcp__mobile-ios__press_button",
67557
- "mcp__mobile-ios__launch_app",
67558
- "mcp__mobile-ios__terminate_app",
67559
- "mcp__mobile-ios__list_apps",
67560
- "mcp__mobile-ios__screenshot",
67561
- "mcp__mobile-ios__accessibility_snapshot"
67562
- ];
67563
- var ALLOWED_TOOLS = [...MOBILE_IOS_TOOLS];
67564
- var MS_PER_SECOND3 = 1e3;
67565
- var DEFAULT_ABORT_EXIT_CODE = 130;
67566
- var IDB_INSTALL_MESSAGE = "idb is not installed. Run:\n brew install idb-companion\n pipx install fb-idb\n";
67567
- var FFMPEG_INSTALL_MESSAGE = "ffmpeg is not installed. Run:\n brew install ffmpeg\n";
67568
-
67569
67905
  // src/core/last-path.ts
67570
67906
  var import_node_fs4 = require("node:fs");
67571
67907
  var import_node_path8 = __toESM(require("node:path"), 1);
67572
- var import_neverthrow37 = __toESM(require_index_cjs(), 1);
67908
+ var import_neverthrow38 = __toESM(require_index_cjs(), 1);
67573
67909
  function resolveLastPath(argument, stateContent) {
67574
67910
  if (argument !== void 0) {
67575
- return (0, import_neverthrow37.ok)(argument);
67911
+ return (0, import_neverthrow38.ok)(argument);
67576
67912
  }
67577
67913
  const trimmed = stateContent?.trim();
67578
67914
  if (trimmed) {
67579
- return (0, import_neverthrow37.ok)(trimmed);
67915
+ return (0, import_neverthrow38.ok)(trimmed);
67580
67916
  }
67581
- return (0, import_neverthrow37.err)({ type: "NO_ARG_AND_NO_STATE" });
67917
+ return (0, import_neverthrow38.err)({ type: "NO_ARG_AND_NO_STATE" });
67582
67918
  }
67583
67919
  function lastPathFilePath(xqaDirectoryectory) {
67584
67920
  return import_node_path8.default.join(xqaDirectoryectory, "last-findings-path");
@@ -67588,9 +67924,9 @@ function writeLastPath(xqaDirectory, findingsPath) {
67588
67924
  }
67589
67925
 
67590
67926
  // src/shell/app-context.ts
67591
- var import_promises17 = require("node:fs/promises");
67927
+ var import_promises18 = require("node:fs/promises");
67592
67928
  var import_node_path9 = __toESM(require("node:path"), 1);
67593
- var import_neverthrow38 = __toESM(require_index_cjs(), 1);
67929
+ var import_neverthrow39 = __toESM(require_index_cjs(), 1);
67594
67930
  var HTML_COMMENT_PATTERN = /<!--[\s\S]*?-->/g;
67595
67931
  function isEnoentError(value) {
67596
67932
  return value !== null && typeof value === "object" && "code" in value && value.code === "ENOENT";
@@ -67600,10 +67936,10 @@ function toAppContextError(cause) {
67600
67936
  }
67601
67937
  function absentContext() {
67602
67938
  const absent = void 0;
67603
- return (0, import_neverthrow38.ok)(absent);
67939
+ return (0, import_neverthrow39.ok)(absent);
67604
67940
  }
67605
- var safeReadFile2 = import_neverthrow38.ResultAsync.fromThrowable(
67606
- async (filePath) => (0, import_promises17.readFile)(filePath, "utf8"),
67941
+ var safeReadFile2 = import_neverthrow39.ResultAsync.fromThrowable(
67942
+ async (filePath) => (0, import_promises18.readFile)(filePath, "utf8"),
67607
67943
  toAppContextError
67608
67944
  );
67609
67945
  function stripAndNormalize(content) {
@@ -67616,7 +67952,7 @@ function readContextFile(xqaDirectory, filename) {
67616
67952
  if (isEnoentError(error48.cause)) {
67617
67953
  return absentContext();
67618
67954
  }
67619
- return (0, import_neverthrow38.err)(error48);
67955
+ return (0, import_neverthrow39.err)(error48);
67620
67956
  });
67621
67957
  }
67622
67958
  function readAppContext(xqaDirectory) {
@@ -67628,7 +67964,7 @@ function readExploreContext(xqaDirectory) {
67628
67964
 
67629
67965
  // src/shell/ffmpeg-check.ts
67630
67966
  var import_node_child_process5 = require("node:child_process");
67631
- var import_neverthrow39 = __toESM(require_index_cjs(), 1);
67967
+ var import_neverthrow40 = __toESM(require_index_cjs(), 1);
67632
67968
  async function whichFfmpeg() {
67633
67969
  const { promise: promise2, resolve, reject } = Promise.withResolvers();
67634
67970
  (0, import_node_child_process5.execFile)("which", ["ffmpeg"], (error48, stdout) => {
@@ -67640,7 +67976,7 @@ async function whichFfmpeg() {
67640
67976
  });
67641
67977
  return promise2;
67642
67978
  }
67643
- var safeWhichFfmpeg = (0, import_neverthrow39.fromAsyncThrowable)(
67979
+ var safeWhichFfmpeg = (0, import_neverthrow40.fromAsyncThrowable)(
67644
67980
  whichFfmpeg,
67645
67981
  () => ({ type: "FFMPEG_NOT_FOUND" })
67646
67982
  );
@@ -67677,7 +68013,7 @@ function buildExplorerConfig2({
67677
68013
  mode: "freestyle",
67678
68014
  mcpServers: createDefaultMcpServers(),
67679
68015
  allowedTools: ALLOWED_TOOLS,
67680
- timeoutMs: timeoutSeconds === void 0 ? void 0 : timeoutSeconds * MS_PER_SECOND3,
68016
+ timeoutMs: timeoutSeconds === void 0 ? void 0 : timeoutSeconds * MS_PER_SECOND4,
67681
68017
  appContext,
67682
68018
  initialState: resolvedStartingState,
67683
68019
  buildEnv: config3.QA_BUILD_ENV
@@ -67778,9 +68114,11 @@ function buildExploreRunState({
67778
68114
  simulatorUdid
67779
68115
  }) {
67780
68116
  const { config: config3, xqaDirectory } = options;
67781
- const onEvent = (event) => {
68117
+ const debugLogger = createDebugLogger({ enabled: input.debug ?? false });
68118
+ const baseHandler = (event) => {
67782
68119
  identity.display.onEvent({ ...event, itemId: ITEM_ID2 });
67783
68120
  };
68121
+ const onEvent = debugLogger.wrapAgentHandler(baseHandler);
67784
68122
  const onSuccess = buildSuccessHandler({ input, xqaDirectory, identity, startedAt });
67785
68123
  const onError = buildErrorHandler(identity, startedAt);
67786
68124
  return { input, config: config3, xqaDirectory, onEvent, onSuccess, onError, simulatorUdid };
@@ -67929,7 +68267,7 @@ function runInitCommand() {
67929
68267
  // src/commands/review-command.ts
67930
68268
  var import_node_fs7 = require("node:fs");
67931
68269
  var import_node_path14 = __toESM(require("node:path"), 1);
67932
- var import_neverthrow41 = __toESM(require_index_cjs(), 1);
68270
+ var import_neverthrow42 = __toESM(require_index_cjs(), 1);
67933
68271
 
67934
68272
  // ../../node_modules/.pnpm/@inquirer+core@10.3.2_@types+node@22.19.15/node_modules/@inquirer/core/dist/esm/lib/key.js
67935
68273
  var isUpKey = (key, keybindings = []) => (
@@ -69051,7 +69389,7 @@ function createPrompt(view) {
69051
69389
  effectScheduler.clearAll();
69052
69390
  throw error48;
69053
69391
  }).finally(() => {
69054
- cleanups.forEach((cleanup2) => cleanup2());
69392
+ cleanups.forEach((cleanup3) => cleanup3());
69055
69393
  screen.done({ clearContent: Boolean(context.clearPromptOnDone) });
69056
69394
  output.end();
69057
69395
  }).then(() => promise2), { cancel });
@@ -69311,9 +69649,9 @@ var RemoveFileError = class extends Error {
69311
69649
  // ../../node_modules/.pnpm/@inquirer+external-editor@1.0.3_@types+node@22.19.15/node_modules/@inquirer/external-editor/dist/esm/index.js
69312
69650
  function editAsync(text = "", callback, fileOptions) {
69313
69651
  const editor = new ExternalEditor(text, fileOptions);
69314
- editor.runAsync((err18, result) => {
69315
- if (err18) {
69316
- setImmediate(callback, err18, void 0);
69652
+ editor.runAsync((err20, result) => {
69653
+ if (err20) {
69654
+ setImmediate(callback, err20, void 0);
69317
69655
  } else {
69318
69656
  try {
69319
69657
  editor.cleanup();
@@ -70334,7 +70672,7 @@ var esm_default11 = createPrompt((config3, done) => {
70334
70672
  });
70335
70673
 
70336
70674
  // src/review-session.ts
70337
- var import_neverthrow40 = __toESM(require_index_cjs(), 1);
70675
+ var import_neverthrow41 = __toESM(require_index_cjs(), 1);
70338
70676
  var CONFIDENCE_PERCENT = 100;
70339
70677
  var FLOW_COL_WIDTH = 35;
70340
70678
  var TRIGGER_COL_WIDTH = 16;
@@ -70487,15 +70825,15 @@ async function runInteractiveLoop(findings, existing) {
70487
70825
  }
70488
70826
  return { staged: state.staged, undoneKeys: state.undoneKeys };
70489
70827
  }
70490
- var safeRunInteractiveLoop = (0, import_neverthrow40.fromAsyncThrowable)(
70828
+ var safeRunInteractiveLoop = (0, import_neverthrow41.fromAsyncThrowable)(
70491
70829
  runInteractiveLoop,
70492
70830
  (error48) => error48 instanceof Error && error48.name === "ExitPromptError" ? "exit-prompt" : "unexpected"
70493
70831
  );
70494
70832
 
70495
70833
  // src/commands/review-command.ts
70496
- var safeReadFile3 = (0, import_neverthrow41.fromThrowable)((filePath) => (0, import_node_fs7.readFileSync)(filePath, "utf8"));
70497
- var safeParseJson3 = (0, import_neverthrow41.fromThrowable)(JSON.parse);
70498
- var safeWrite = (0, import_neverthrow41.fromThrowable)((filePath, content) => {
70834
+ var safeReadFile3 = (0, import_neverthrow42.fromThrowable)((filePath) => (0, import_node_fs7.readFileSync)(filePath, "utf8"));
70835
+ var safeParseJson3 = (0, import_neverthrow42.fromThrowable)(JSON.parse);
70836
+ var safeWrite = (0, import_neverthrow42.fromThrowable)((filePath, content) => {
70499
70837
  (0, import_node_fs7.writeFileSync)(filePath, content);
70500
70838
  });
70501
70839
  function readLastPath(xqaDirectory) {
@@ -70512,13 +70850,13 @@ function isPipelineOutput(data) {
70512
70850
  function readFindings(filePath) {
70513
70851
  const readResult = safeReadFile3(filePath);
70514
70852
  if (readResult.isErr()) {
70515
- return (0, import_neverthrow41.err)("not-found");
70853
+ return (0, import_neverthrow42.err)("not-found");
70516
70854
  }
70517
70855
  return safeParseJson3(readResult.value).mapErr(() => "invalid").andThen((data) => {
70518
70856
  if (!isPipelineOutput(data)) {
70519
- return (0, import_neverthrow41.err)("invalid");
70857
+ return (0, import_neverthrow42.err)("invalid");
70520
70858
  }
70521
- return (0, import_neverthrow41.ok)(data);
70859
+ return (0, import_neverthrow42.ok)(data);
70522
70860
  });
70523
70861
  }
70524
70862
  function loadExistingDismissals(filePath) {
@@ -70591,7 +70929,7 @@ function resolveAndReadFindings(findingsPath, xqaDirectory) {
70591
70929
  "No findings path provided and no last path found. Run: xqa review <findings-path>\n"
70592
70930
  );
70593
70931
  process.exit(1);
70594
- return (0, import_neverthrow41.err)();
70932
+ return (0, import_neverthrow42.err)();
70595
70933
  }
70596
70934
  const resolvedPath = resolvedPathResult.value;
70597
70935
  const findingsResult = readFindings(resolvedPath);
@@ -70604,9 +70942,9 @@ function resolveAndReadFindings(findingsPath, xqaDirectory) {
70604
70942
  `);
70605
70943
  }
70606
70944
  process.exit(1);
70607
- return (0, import_neverthrow41.err)();
70945
+ return (0, import_neverthrow42.err)();
70608
70946
  }
70609
- return (0, import_neverthrow41.ok)({ resolvedPath, output: findingsResult.value });
70947
+ return (0, import_neverthrow42.ok)({ resolvedPath, output: findingsResult.value });
70610
70948
  }
70611
70949
  async function runReviewLoop({
70612
70950
  findings,
@@ -70680,40 +71018,40 @@ function stripExtensions(filename) {
70680
71018
  // src/commands/spec-resolver.ts
70681
71019
  var import_node_fs8 = require("node:fs");
70682
71020
  var import_node_path16 = __toESM(require("node:path"), 1);
70683
- var import_neverthrow43 = __toESM(require_index_cjs(), 1);
71021
+ var import_neverthrow44 = __toESM(require_index_cjs(), 1);
70684
71022
 
70685
71023
  // src/spec-frontmatter.ts
70686
- var import_neverthrow42 = __toESM(require_index_cjs(), 1);
71024
+ var import_neverthrow43 = __toESM(require_index_cjs(), 1);
70687
71025
  var FRONTMATTER_OPEN_LEN = 4;
70688
71026
  var FRONTMATTER_MARKER_LEN = 3;
70689
71027
  function extractFrontmatterBlock(content) {
70690
71028
  const normalized = content.replaceAll("\r\n", "\n");
70691
71029
  if (!normalized.startsWith("---")) {
70692
- return (0, import_neverthrow42.err)({ type: "MISSING_FRONTMATTER" });
71030
+ return (0, import_neverthrow43.err)({ type: "MISSING_FRONTMATTER" });
70693
71031
  }
70694
71032
  const end = normalized.indexOf("\n---", FRONTMATTER_MARKER_LEN);
70695
71033
  if (end === -1) {
70696
- return (0, import_neverthrow42.err)({ type: "MISSING_FRONTMATTER" });
71034
+ return (0, import_neverthrow43.err)({ type: "MISSING_FRONTMATTER" });
70697
71035
  }
70698
- return (0, import_neverthrow42.ok)(normalized.slice(FRONTMATTER_OPEN_LEN, end));
71036
+ return (0, import_neverthrow43.ok)(normalized.slice(FRONTMATTER_OPEN_LEN, end));
70699
71037
  }
70700
71038
  function parseTimeout(fields) {
70701
71039
  const raw = fields.get("timeout");
70702
71040
  if (raw === void 0) {
70703
- return (0, import_neverthrow42.ok)(raw);
71041
+ return (0, import_neverthrow43.ok)(raw);
70704
71042
  }
70705
71043
  const parsed = Number(raw);
70706
71044
  if (Number.isNaN(parsed) || parsed <= 0) {
70707
- return (0, import_neverthrow42.err)({ type: "PARSE_ERROR", cause: `invalid timeout: ${raw}` });
71045
+ return (0, import_neverthrow43.err)({ type: "PARSE_ERROR", cause: `invalid timeout: ${raw}` });
70708
71046
  }
70709
- return (0, import_neverthrow42.ok)(parsed);
71047
+ return (0, import_neverthrow43.ok)(parsed);
70710
71048
  }
70711
71049
  function parseSpecFrontmatter(content) {
70712
71050
  return extractFrontmatterBlock(content).andThen((block) => {
70713
71051
  const fields = parseYamlFields(block);
70714
71052
  const feature = fields.get("feature");
70715
71053
  if (feature === void 0) {
70716
- return (0, import_neverthrow42.err)({ type: "MISSING_FIELD", field: "feature" });
71054
+ return (0, import_neverthrow43.err)({ type: "MISSING_FIELD", field: "feature" });
70717
71055
  }
70718
71056
  return parseTimeout(fields).map((timeout) => ({ feature, timeout }));
70719
71057
  });
@@ -70735,12 +71073,12 @@ function parseYamlFields(block) {
70735
71073
  }
70736
71074
 
70737
71075
  // src/commands/spec-resolver.ts
70738
- var safeReadFile4 = (0, import_neverthrow43.fromThrowable)((filePath) => (0, import_node_fs8.readFileSync)(filePath, "utf8"));
70739
- var safeReaddir = (0, import_neverthrow43.fromThrowable)(
71076
+ var safeReadFile4 = (0, import_neverthrow44.fromThrowable)((filePath) => (0, import_node_fs8.readFileSync)(filePath, "utf8"));
71077
+ var safeReaddir = (0, import_neverthrow44.fromThrowable)(
70740
71078
  (directory) => (0, import_node_fs8.readdirSync)(directory, { recursive: true, encoding: "utf8" })
70741
71079
  );
70742
71080
  var CANCEL = "xqa:cancel";
70743
- var safeSelect = import_neverthrow43.ResultAsync.fromThrowable(
71081
+ var safeSelect = import_neverthrow44.ResultAsync.fromThrowable(
70744
71082
  esm_default11,
70745
71083
  (error48) => error48 instanceof Error && error48.name === "ExitPromptError" ? "cancelled" : "failed"
70746
71084
  );
@@ -70805,7 +71143,7 @@ function buildSpecExplorer(input, context) {
70805
71143
  specFiles: [context.absolutePath],
70806
71144
  mcpServers: createDefaultMcpServers(),
70807
71145
  allowedTools: ALLOWED_TOOLS,
70808
- timeoutMs: context.timeout === void 0 ? void 0 : context.timeout * MS_PER_SECOND3,
71146
+ timeoutMs: context.timeout === void 0 ? void 0 : context.timeout * MS_PER_SECOND4,
70809
71147
  appContext: context.appContext,
70810
71148
  buildEnv: context.config.QA_BUILD_ENV
70811
71149
  };
@@ -70864,9 +71202,11 @@ async function executeSpec(input, context) {
70864
71202
  };
70865
71203
  const startedAt = Date.now();
70866
71204
  emitItemStart(identity, startedAt);
70867
- const onEvent = (event) => {
71205
+ const debugLogger = createDebugLogger({ enabled: input.debug ?? false });
71206
+ const baseHandler = (event) => {
70868
71207
  identity.display.onEvent({ ...event, itemId: identity.itemId });
70869
71208
  };
71209
+ const onEvent = debugLogger.wrapAgentHandler(baseHandler);
70870
71210
  const { onSuccess, onError } = handleSpecResult({ identity, startedAt }, context);
70871
71211
  const result = await runPipeline2(buildPipelineConfig2({ input, context, onEvent }));
70872
71212
  result.match(onSuccess, onError);
@@ -70928,7 +71268,7 @@ function runUpdateCommand() {
70928
71268
  var import_node_path18 = __toESM(require("node:path"), 1);
70929
71269
  var import_node_url2 = require("node:url");
70930
71270
  var import_dotenv = __toESM(require_main(), 1);
70931
- var import_neverthrow44 = __toESM(require_index_cjs(), 1);
71271
+ var import_neverthrow45 = __toESM(require_index_cjs(), 1);
70932
71272
 
70933
71273
  // ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/external.js
70934
71274
  var external_exports2 = {};
@@ -71408,8 +71748,8 @@ function getErrorMap2() {
71408
71748
 
71409
71749
  // ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/parseUtil.js
71410
71750
  var makeIssue = (params) => {
71411
- const { data, path: path23, errorMaps, issueData } = params;
71412
- const fullPath = [...path23, ...issueData.path || []];
71751
+ const { data, path: path24, errorMaps, issueData } = params;
71752
+ const fullPath = [...path24, ...issueData.path || []];
71413
71753
  const fullIssue = {
71414
71754
  ...issueData,
71415
71755
  path: fullPath
@@ -71525,11 +71865,11 @@ var errorUtil;
71525
71865
 
71526
71866
  // ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/types.js
71527
71867
  var ParseInputLazyPath = class {
71528
- constructor(parent, value, path23, key) {
71868
+ constructor(parent, value, path24, key) {
71529
71869
  this._cachedPath = [];
71530
71870
  this.parent = parent;
71531
71871
  this.data = value;
71532
- this._path = path23;
71872
+ this._path = path24;
71533
71873
  this._key = key;
71534
71874
  }
71535
71875
  get path() {
@@ -71668,8 +72008,8 @@ var ZodType2 = class {
71668
72008
  } : {
71669
72009
  issues: ctx.common.issues
71670
72010
  };
71671
- } catch (err18) {
71672
- if (err18?.message?.toLowerCase()?.includes("encountered")) {
72011
+ } catch (err20) {
72012
+ if (err20?.message?.toLowerCase()?.includes("encountered")) {
71673
72013
  this["~standard"].async = true;
71674
72014
  }
71675
72015
  ctx.common = {
@@ -74989,10 +75329,10 @@ function loadConfig() {
74989
75329
  const messages = result.error.issues.map(
74990
75330
  (issue2) => ` - ${issue2.path.join(".")}: ${issue2.message}`
74991
75331
  );
74992
- return (0, import_neverthrow44.err)({ type: "INVALID_CONFIG", message: `Configuration error:
75332
+ return (0, import_neverthrow45.err)({ type: "INVALID_CONFIG", message: `Configuration error:
74993
75333
  ${messages.join("\n")}` });
74994
75334
  }
74995
- return (0, import_neverthrow44.ok)(result.data);
75335
+ return (0, import_neverthrow45.ok)(result.data);
74996
75336
  }
74997
75337
 
74998
75338
  // src/core/parse-timeout-seconds.ts
@@ -75025,7 +75365,7 @@ function parseVerboseOption(value) {
75025
75365
 
75026
75366
  // src/pid-lock.ts
75027
75367
  var import_node_fs9 = require("node:fs");
75028
- var import_neverthrow45 = __toESM(require_index_cjs(), 1);
75368
+ var import_neverthrow46 = __toESM(require_index_cjs(), 1);
75029
75369
  var PID_FILE = "/tmp/xqa.pid";
75030
75370
  var SIGINT_EXIT_CODE = 130;
75031
75371
  var SIGTERM_EXIT_CODE = 143;
@@ -75034,7 +75374,7 @@ var HARD_TIMEOUT_MS = 1e4;
75034
75374
  var cleanup = () => {
75035
75375
  (0, import_node_fs9.rmSync)(PID_FILE, { force: true });
75036
75376
  };
75037
- var checkProcessRunning = (0, import_neverthrow45.fromThrowable)(
75377
+ var checkProcessRunning = (0, import_neverthrow46.fromThrowable)(
75038
75378
  (pid) => {
75039
75379
  process.kill(pid, 0);
75040
75380
  return true;
@@ -75100,51 +75440,40 @@ function acquireLock() {
75100
75440
  // src/shell/xqa-directory.ts
75101
75441
  var import_node_fs10 = require("node:fs");
75102
75442
  var import_node_path19 = __toESM(require("node:path"), 1);
75103
- var import_neverthrow46 = __toESM(require_index_cjs(), 1);
75443
+ var import_neverthrow47 = __toESM(require_index_cjs(), 1);
75104
75444
  function findXqaDirectory(startDirectory) {
75105
75445
  let current = startDirectory;
75106
75446
  for (; ; ) {
75107
75447
  const candidate = import_node_path19.default.join(current, ".xqa");
75108
75448
  if ((0, import_node_fs10.existsSync)(candidate)) {
75109
- return (0, import_neverthrow46.ok)(candidate);
75449
+ return (0, import_neverthrow47.ok)(candidate);
75110
75450
  }
75111
75451
  const parent = import_node_path19.default.dirname(current);
75112
75452
  if (parent === current) {
75113
- return (0, import_neverthrow46.err)({ type: "XQA_NOT_INITIALIZED" });
75453
+ return (0, import_neverthrow47.err)({ type: "XQA_NOT_INITIALIZED" });
75114
75454
  }
75115
75455
  current = parent;
75116
75456
  }
75117
75457
  }
75118
75458
 
75119
75459
  // src/suite/commands/run-command.ts
75120
- var import_promises19 = __toESM(require("node:fs/promises"), 1);
75121
- var import_node_path22 = __toESM(require("node:path"), 1);
75460
+ var import_promises21 = __toESM(require("node:fs/promises"), 1);
75461
+ var import_node_path23 = __toESM(require("node:path"), 1);
75122
75462
  var import_fast_glob = __toESM(require_out4(), 1);
75123
- var import_neverthrow51 = __toESM(require_index_cjs(), 1);
75124
-
75125
- // src/suite/core/run-id.ts
75126
- var RUN_ID_PAD_LENGTH2 = 4;
75127
- function toNumeric(name) {
75128
- const parsed = Number(name);
75129
- return Number.isInteger(parsed) && parsed > 0 ? parsed : void 0;
75130
- }
75131
- function highestNumeric(directories) {
75132
- let highest = 0;
75133
- for (const name of directories) {
75134
- const numeric = toNumeric(name);
75135
- if (numeric !== void 0 && numeric > highest) {
75136
- highest = numeric;
75137
- }
75138
- }
75139
- return highest;
75140
- }
75141
- function computeNextRunId(existingDirectories) {
75142
- return String(highestNumeric(existingDirectories) + 1).padStart(RUN_ID_PAD_LENGTH2, "0");
75143
- }
75463
+ var import_neverthrow55 = __toESM(require_index_cjs(), 1);
75144
75464
 
75145
75465
  // src/suite/core/suite-config-parser.ts
75146
- var import_neverthrow47 = __toESM(require_index_cjs(), 1);
75147
75466
  var import_neverthrow48 = __toESM(require_index_cjs(), 1);
75467
+ var import_neverthrow49 = __toESM(require_index_cjs(), 1);
75468
+ var RESERVED_HOOK_ENV_KEYS = [
75469
+ "XQA_SIM_UDID",
75470
+ "XQA_ITEM_ID",
75471
+ "XQA_ITEM_TYPE",
75472
+ "XQA_ITEM_NAME",
75473
+ "XQA_SPEC_PATH",
75474
+ "XQA_SUITE"
75475
+ ];
75476
+ var reservedKeySet = new Set(RESERVED_HOOK_ENV_KEYS);
75148
75477
  var freestyleEntrySchema = external_exports2.object({
75149
75478
  prompt: external_exports2.string().optional(),
75150
75479
  timeoutSeconds: external_exports2.number().int().positive()
@@ -75159,24 +75488,80 @@ var freestyleSchema = external_exports2.union([external_exports2.number().int().
75159
75488
  }
75160
75489
  return value;
75161
75490
  });
75491
+ var hookConfigSchema = external_exports2.object({
75492
+ script: external_exports2.string().min(1),
75493
+ env: external_exports2.record(external_exports2.string(), external_exports2.string()).optional(),
75494
+ timeoutSeconds: external_exports2.number().int().positive().optional()
75495
+ }).superRefine((data, context) => {
75496
+ if (data.env === void 0) {
75497
+ return;
75498
+ }
75499
+ for (const key of Object.keys(data.env)) {
75500
+ if (reservedKeySet.has(key)) {
75501
+ context.addIssue({
75502
+ code: external_exports2.ZodIssueCode.custom,
75503
+ path: ["env", key],
75504
+ message: `Reserved xqa-owned key: ${key}`
75505
+ });
75506
+ }
75507
+ }
75508
+ });
75509
+ var suiteHooksSchema = external_exports2.object({
75510
+ beforeEach: hookConfigSchema.optional()
75511
+ });
75162
75512
  var suiteConfigSchema = external_exports2.object({
75163
75513
  specs: external_exports2.array(external_exports2.string()).nonempty(),
75164
- freestyle: freestyleSchema
75514
+ freestyle: freestyleSchema,
75515
+ hooks: suiteHooksSchema.optional()
75165
75516
  });
75166
- var safeJsonParse4 = (0, import_neverthrow47.fromThrowable)(
75517
+ var safeJsonParse4 = (0, import_neverthrow48.fromThrowable)(
75167
75518
  JSON.parse,
75168
75519
  (cause) => ({
75169
75520
  type: "INVALID_SUITE_CONFIG",
75170
75521
  cause
75171
75522
  })
75172
75523
  );
75524
+ function buildHookConfig(parsed) {
75525
+ const { script, env: env2, timeoutSeconds } = parsed;
75526
+ if (env2 !== void 0 && timeoutSeconds !== void 0) {
75527
+ return { script, env: env2, timeoutSeconds };
75528
+ }
75529
+ if (env2 !== void 0) {
75530
+ return { script, env: env2 };
75531
+ }
75532
+ if (timeoutSeconds !== void 0) {
75533
+ return { script, timeoutSeconds };
75534
+ }
75535
+ return { script };
75536
+ }
75537
+ function normalizeHooks(hooks) {
75538
+ if (hooks === void 0) {
75539
+ return void 0;
75540
+ }
75541
+ const { beforeEach } = hooks;
75542
+ if (beforeEach === void 0) {
75543
+ return {};
75544
+ }
75545
+ return { beforeEach: buildHookConfig(beforeEach) };
75546
+ }
75173
75547
  function parseSuiteConfig(raw) {
75174
75548
  return safeJsonParse4(raw).andThen((data) => {
75175
75549
  const parsed = suiteConfigSchema.safeParse(data);
75176
75550
  if (!parsed.success) {
75177
- return (0, import_neverthrow48.err)({ type: "INVALID_SUITE_CONFIG", cause: parsed.error });
75551
+ return (0, import_neverthrow49.err)({ type: "INVALID_SUITE_CONFIG", cause: parsed.error });
75178
75552
  }
75179
- return (0, import_neverthrow48.ok)({ specs: parsed.data.specs, freestyle: parsed.data.freestyle });
75553
+ const hooks = normalizeHooks(parsed.data.hooks);
75554
+ if (hooks === void 0) {
75555
+ return (0, import_neverthrow49.ok)({
75556
+ specs: parsed.data.specs,
75557
+ freestyle: parsed.data.freestyle
75558
+ });
75559
+ }
75560
+ return (0, import_neverthrow49.ok)({
75561
+ specs: parsed.data.specs,
75562
+ freestyle: parsed.data.freestyle,
75563
+ hooks
75564
+ });
75180
75565
  });
75181
75566
  }
75182
75567
 
@@ -75189,17 +75574,6 @@ function buildSuiteFindings(input) {
75189
75574
  return base;
75190
75575
  }
75191
75576
 
75192
- // src/suite/core/suite-id.ts
75193
- function slugify2(glob) {
75194
- return glob.replaceAll(/[^a-zA-Z0-9]+/g, "-").replaceAll(/-+/g, "-").replaceAll(/^-|-$/g, "");
75195
- }
75196
- function deriveSuiteId(input) {
75197
- if (input.mode === "suite") {
75198
- return input.name;
75199
- }
75200
- return input.globs.toSorted().map((glob) => slugify2(glob)).join("+");
75201
- }
75202
-
75203
75577
  // src/suite/core/work-item-builder.ts
75204
75578
  var DEFAULT_FREESTYLE_TIMEOUT_SECONDS = 300;
75205
75579
  function deriveSpecName(filePath) {
@@ -75240,9 +75614,9 @@ function buildFreestyleItems(entries) {
75240
75614
  }
75241
75615
 
75242
75616
  // src/suite/shell/suite-findings-writer.ts
75243
- var import_promises18 = __toESM(require("node:fs/promises"), 1);
75617
+ var import_promises19 = __toESM(require("node:fs/promises"), 1);
75244
75618
  var import_node_path20 = __toESM(require("node:path"), 1);
75245
- var import_neverthrow49 = __toESM(require_index_cjs(), 1);
75619
+ var import_neverthrow50 = __toESM(require_index_cjs(), 1);
75246
75620
  var INDENT_SPACES = 2;
75247
75621
  function writeSuiteFindings(findings, options) {
75248
75622
  const directory = import_node_path20.default.join(
@@ -75254,11 +75628,11 @@ function writeSuiteFindings(findings, options) {
75254
75628
  );
75255
75629
  const finalPath = import_node_path20.default.join(directory, "findings.json");
75256
75630
  const temporaryPath = `${finalPath}.tmp`;
75257
- const safeWriteAtomically = import_neverthrow49.ResultAsync.fromThrowable(
75631
+ const safeWriteAtomically = import_neverthrow50.ResultAsync.fromThrowable(
75258
75632
  async () => {
75259
- await import_promises18.default.mkdir(directory, { recursive: true });
75260
- await import_promises18.default.writeFile(temporaryPath, JSON.stringify(findings, void 0, INDENT_SPACES));
75261
- await import_promises18.default.rename(temporaryPath, finalPath);
75633
+ await import_promises19.default.mkdir(directory, { recursive: true });
75634
+ await import_promises19.default.writeFile(temporaryPath, JSON.stringify(findings, void 0, INDENT_SPACES));
75635
+ await import_promises19.default.rename(temporaryPath, finalPath);
75262
75636
  return finalPath;
75263
75637
  },
75264
75638
  (cause) => ({ type: "FINDINGS_WRITE_FAILED", cause })
@@ -75267,7 +75641,29 @@ function writeSuiteFindings(findings, options) {
75267
75641
  }
75268
75642
 
75269
75643
  // src/suite/shell/worker-pool.ts
75270
- var import_neverthrow50 = __toESM(require_index_cjs(), 1);
75644
+ var import_neverthrow53 = __toESM(require_index_cjs(), 1);
75645
+
75646
+ // src/suite/core/priority-queue.ts
75647
+ var PriorityQueue = class {
75648
+ entries = [];
75649
+ get size() {
75650
+ return this.entries.length;
75651
+ }
75652
+ get isEmpty() {
75653
+ return this.entries.length === 0;
75654
+ }
75655
+ enqueue(item, priority) {
75656
+ const insertIndex = this.entries.findIndex((entry) => entry.priority > priority);
75657
+ if (insertIndex === -1) {
75658
+ this.entries.push({ item, priority });
75659
+ } else {
75660
+ this.entries.splice(insertIndex, 0, { item, priority });
75661
+ }
75662
+ }
75663
+ dequeue() {
75664
+ return this.entries.shift()?.item;
75665
+ }
75666
+ };
75271
75667
 
75272
75668
  // src/suite/shell/item-result-builder.ts
75273
75669
  function getErrorMessage(cause) {
@@ -75341,33 +75737,7 @@ function buildAbortedItem(item, simulatorUdid) {
75341
75737
  };
75342
75738
  }
75343
75739
 
75344
- // src/suite/core/priority-queue.ts
75345
- var PriorityQueue = class {
75346
- entries = [];
75347
- get size() {
75348
- return this.entries.length;
75349
- }
75350
- get isEmpty() {
75351
- return this.entries.length === 0;
75352
- }
75353
- enqueue(item, priority) {
75354
- const insertIndex = this.entries.findIndex((entry) => entry.priority > priority);
75355
- if (insertIndex === -1) {
75356
- this.entries.push({ item, priority });
75357
- } else {
75358
- this.entries.splice(insertIndex, 0, { item, priority });
75359
- }
75360
- }
75361
- dequeue() {
75362
- return this.entries.shift()?.item;
75363
- }
75364
- };
75365
-
75366
- // src/suite/shell/worker-pool.ts
75367
- var CONSECUTIVE_FAILURES_THRESHOLD = 2;
75368
- function isTimeoutError(error48) {
75369
- return error48.type.toUpperCase().includes("TIMEOUT");
75370
- }
75740
+ // src/suite/shell/item-result-recorder.ts
75371
75741
  function buildNotifyBase(itemContext) {
75372
75742
  return {
75373
75743
  itemId: itemContext.item.id,
@@ -75376,6 +75746,9 @@ function buildNotifyBase(itemContext) {
75376
75746
  at: Date.now()
75377
75747
  };
75378
75748
  }
75749
+ function isTimeoutError(error48) {
75750
+ return error48.type.toUpperCase().includes("TIMEOUT");
75751
+ }
75379
75752
  function notifyItemResult(context, observer) {
75380
75753
  const base = buildNotifyBase(context.itemContext);
75381
75754
  if (context.result.isOk()) {
@@ -75396,12 +75769,12 @@ function notifyItemResult(context, observer) {
75396
75769
  error: getErrorMessage(context.result.error.cause)
75397
75770
  });
75398
75771
  }
75399
- function recordItemResult(context, workerContext) {
75772
+ function recordItemResult(input) {
75773
+ const { context, results, observer } = input;
75400
75774
  const { itemContext, result } = context;
75401
- const { results, config: config3 } = workerContext;
75402
75775
  if (result.isOk()) {
75403
75776
  results.push(buildCompletedItem(itemContext, result.value));
75404
- notifyItemResult(context, config3.observer);
75777
+ notifyItemResult(context, observer);
75405
75778
  return 0;
75406
75779
  }
75407
75780
  if (isTimeoutError(result.error)) {
@@ -75409,9 +75782,202 @@ function recordItemResult(context, workerContext) {
75409
75782
  } else {
75410
75783
  results.push(buildFailedItem(itemContext, getErrorMessage(result.error.cause)));
75411
75784
  }
75412
- notifyItemResult(context, config3.observer);
75785
+ notifyItemResult(context, observer);
75786
+ return 1;
75787
+ }
75788
+
75789
+ // src/suite/shell/hook-failure-recorder.ts
75790
+ function formatHookError(error48) {
75791
+ switch (error48.type) {
75792
+ case "HOOK_SPAWN_FAILED": {
75793
+ return `Hook spawn failed: ${getErrorMessage(error48.cause)}`;
75794
+ }
75795
+ case "HOOK_EXIT_NONZERO": {
75796
+ return `Hook exited with code ${String(error48.code)}: ${error48.stderr.trim()}`;
75797
+ }
75798
+ case "HOOK_TIMEOUT": {
75799
+ return `Hook timed out after ${String(error48.timeoutMs)}ms`;
75800
+ }
75801
+ case "HOOK_ABORTED": {
75802
+ return "Hook aborted";
75803
+ }
75804
+ }
75805
+ }
75806
+ function emitHookTimeout(input) {
75807
+ const base = buildNotifyBase(input.itemContext);
75808
+ input.results.push(buildTimedOutItem(input.itemContext));
75809
+ const event = { type: "ITEM_TIMEOUT", ...base };
75810
+ input.observer(event);
75811
+ }
75812
+ function emitHookFailed(input, message) {
75813
+ const base = buildNotifyBase(input.itemContext);
75814
+ input.results.push(buildFailedItem(input.itemContext, message));
75815
+ const event = { type: "ITEM_FAILED", ...base, error: message };
75816
+ input.observer(event);
75817
+ }
75818
+ function recordHookFailure(input) {
75819
+ if (input.error.type === "HOOK_TIMEOUT") {
75820
+ emitHookTimeout(input);
75821
+ return 1;
75822
+ }
75823
+ emitHookFailed(input, formatHookError(input.error));
75413
75824
  return 1;
75414
75825
  }
75826
+
75827
+ // src/suite/shell/hook-invoker.ts
75828
+ var import_neverthrow52 = __toESM(require_index_cjs(), 1);
75829
+
75830
+ // src/suite/core/hook-env-builder.ts
75831
+ function buildReservedKeys(input) {
75832
+ const { item, simulatorUdid, suiteName } = input;
75833
+ const base = {
75834
+ XQA_SIM_UDID: simulatorUdid,
75835
+ XQA_ITEM_ID: item.id,
75836
+ XQA_ITEM_TYPE: item.type,
75837
+ XQA_ITEM_NAME: item.name,
75838
+ XQA_SUITE: suiteName
75839
+ };
75840
+ if (item.type === "spec") {
75841
+ return { ...base, XQA_SPEC_PATH: item.specPath };
75842
+ }
75843
+ return base;
75844
+ }
75845
+ function buildHookEnv(input) {
75846
+ const reserved = buildReservedKeys(input);
75847
+ if (input.suiteEnv === void 0) {
75848
+ return reserved;
75849
+ }
75850
+ return { ...input.suiteEnv, ...reserved };
75851
+ }
75852
+
75853
+ // src/suite/shell/hook-runner.ts
75854
+ var import_node_child_process7 = require("node:child_process");
75855
+ var import_neverthrow51 = __toESM(require_index_cjs(), 1);
75856
+ var noop2 = () => void 0;
75857
+ function cleanup2(context) {
75858
+ clearTimeout(context.timeoutHandle);
75859
+ context.signal.removeEventListener("abort", context.onAbort);
75860
+ }
75861
+ function settle(context, outcome) {
75862
+ if (context.settled.value) {
75863
+ return;
75864
+ }
75865
+ context.settled.value = true;
75866
+ cleanup2(context);
75867
+ context.deferred.resolve(outcome);
75868
+ }
75869
+ function makeDeferred() {
75870
+ const raw = Promise.withResolvers();
75871
+ return { promise: raw.promise, resolve: raw.resolve };
75872
+ }
75873
+ function collectStderr(child, stderrReference) {
75874
+ if (child.stderr === null) {
75875
+ return;
75876
+ }
75877
+ child.stderr.on("data", (chunk) => {
75878
+ stderrReference.value += chunk.toString();
75879
+ });
75880
+ }
75881
+ function buildOnAbort(context) {
75882
+ return () => {
75883
+ context.child.kill("SIGTERM");
75884
+ settle(context, (0, import_neverthrow51.err)({ type: "HOOK_ABORTED" }));
75885
+ };
75886
+ }
75887
+ function attachChildListeners(context) {
75888
+ const { child, stderrReference } = context;
75889
+ child.on("error", (cause) => {
75890
+ settle(context, (0, import_neverthrow51.err)({ type: "HOOK_SPAWN_FAILED", cause }));
75891
+ });
75892
+ child.on("exit", (code) => {
75893
+ if (code === 0) {
75894
+ settle(context, (0, import_neverthrow51.ok)());
75895
+ return;
75896
+ }
75897
+ settle(
75898
+ context,
75899
+ (0, import_neverthrow51.err)({
75900
+ type: "HOOK_EXIT_NONZERO",
75901
+ code: code ?? -1,
75902
+ stderr: stderrReference.value
75903
+ })
75904
+ );
75905
+ });
75906
+ }
75907
+ function attachTimeout(context, timeoutMs) {
75908
+ clearTimeout(context.timeoutHandle);
75909
+ context.timeoutHandle = setTimeout(() => {
75910
+ context.child.kill("SIGTERM");
75911
+ settle(context, (0, import_neverthrow51.err)({ type: "HOOK_TIMEOUT", timeoutMs }));
75912
+ }, timeoutMs);
75913
+ }
75914
+ function buildContext2(options) {
75915
+ const { script, cwd, env: env2, baseEnv, nodeExecPath } = options;
75916
+ const deferred = makeDeferred();
75917
+ const stderrReference = { value: "" };
75918
+ const child = (0, import_node_child_process7.spawn)(nodeExecPath, [script], {
75919
+ cwd,
75920
+ env: { ...baseEnv, ...env2 },
75921
+ stdio: ["ignore", "inherit", "pipe"]
75922
+ });
75923
+ collectStderr(child, stderrReference);
75924
+ return {
75925
+ child,
75926
+ signal: options.signal,
75927
+ timeoutHandle: setTimeout(noop2, 0),
75928
+ onAbort: noop2,
75929
+ deferred,
75930
+ stderrReference,
75931
+ settled: { value: false }
75932
+ };
75933
+ }
75934
+ async function spawnHook(options) {
75935
+ const context = buildContext2(options);
75936
+ attachTimeout(context, options.timeoutMs);
75937
+ context.onAbort = buildOnAbort(context);
75938
+ if (options.signal.aborted) {
75939
+ context.onAbort();
75940
+ return context.deferred.promise;
75941
+ }
75942
+ options.signal.addEventListener("abort", context.onAbort, { once: true });
75943
+ attachChildListeners(context);
75944
+ return context.deferred.promise;
75945
+ }
75946
+ var safeSpawn = import_neverthrow51.ResultAsync.fromThrowable(
75947
+ spawnHook,
75948
+ (cause) => ({ type: "HOOK_SPAWN_FAILED", cause })
75949
+ );
75950
+ function runHook(options) {
75951
+ return safeSpawn(options).andThen((outcome) => outcome);
75952
+ }
75953
+
75954
+ // src/suite/shell/hook-invoker.ts
75955
+ var DEFAULT_HOOK_TIMEOUT_SECONDS = 120;
75956
+ var MS_PER_SECOND5 = 1e3;
75957
+ async function invokeHook(input) {
75958
+ const { hook, item, simulatorUdid, suiteName, hookCwd, hookBaseEnv, hookNodeExecPath, signal } = input;
75959
+ const env2 = buildHookEnv({ item, simulatorUdid, suiteName, suiteEnv: hook.env });
75960
+ const timeoutSeconds = hook.timeoutSeconds ?? DEFAULT_HOOK_TIMEOUT_SECONDS;
75961
+ return runHook({
75962
+ script: hook.script,
75963
+ cwd: hookCwd,
75964
+ env: env2,
75965
+ baseEnv: hookBaseEnv,
75966
+ nodeExecPath: hookNodeExecPath,
75967
+ timeoutMs: timeoutSeconds * MS_PER_SECOND5,
75968
+ signal
75969
+ });
75970
+ }
75971
+ async function maybeInvokeHook(input) {
75972
+ const { hook } = input;
75973
+ if (hook === void 0) {
75974
+ return (0, import_neverthrow52.ok)();
75975
+ }
75976
+ return invokeHook({ ...input, hook });
75977
+ }
75978
+
75979
+ // src/suite/shell/worker-pool.ts
75980
+ var CONSECUTIVE_FAILURES_THRESHOLD = 2;
75415
75981
  function buildExecuteOptions(workerContext, item) {
75416
75982
  const { simulatorUdid, config: config3 } = workerContext;
75417
75983
  const base = { item, simulatorUdid, signal: config3.signal };
@@ -75421,21 +75987,70 @@ function buildExecuteOptions(workerContext, item) {
75421
75987
  }
75422
75988
  return base;
75423
75989
  }
75424
- async function processItem(workerContext, item) {
75425
- const { simulatorUdid, config: config3 } = workerContext;
75426
- const startedAt = (/* @__PURE__ */ new Date()).toISOString();
75427
- const startMs = Date.now();
75428
- config3.observer({
75990
+ function buildHookInvokeInput(workerContext, item) {
75991
+ const { config: config3, simulatorUdid } = workerContext;
75992
+ return {
75993
+ hook: config3.hook,
75994
+ item,
75995
+ simulatorUdid,
75996
+ suiteName: config3.suiteName,
75997
+ hookCwd: config3.hookCwd,
75998
+ hookBaseEnv: config3.hookBaseEnv,
75999
+ hookNodeExecPath: config3.hookNodeExecPath,
76000
+ signal: config3.signal
76001
+ };
76002
+ }
76003
+ function emitItemStarted(state) {
76004
+ const { workerContext, item, startMs } = state;
76005
+ workerContext.config.observer({
75429
76006
  type: "ITEM_STARTED",
75430
76007
  itemId: item.id,
75431
76008
  itemName: item.name,
75432
- simulatorUdid,
76009
+ simulatorUdid: workerContext.simulatorUdid,
75433
76010
  at: startMs
75434
76011
  });
75435
- const result = await config3.executeItem(buildExecuteOptions(workerContext, item));
76012
+ }
76013
+ async function runAndRecordItem(state) {
76014
+ const { workerContext, item, startedAt, startMs } = state;
76015
+ const { simulatorUdid } = workerContext;
76016
+ const result = await workerContext.config.executeItem(buildExecuteOptions(workerContext, item));
75436
76017
  const durationMs = Date.now() - startMs;
75437
76018
  const itemContext = { item, simulatorUdid, startedAt, durationMs };
75438
- return recordItemResult({ itemContext, result }, workerContext);
76019
+ return recordItemResult({
76020
+ context: { itemContext, result },
76021
+ results: workerContext.results,
76022
+ observer: workerContext.config.observer
76023
+ });
76024
+ }
76025
+ function handleHookFailure(state, error48) {
76026
+ const { workerContext, item, startedAt, startMs } = state;
76027
+ const durationMs = Date.now() - startMs;
76028
+ const itemContext = {
76029
+ item,
76030
+ simulatorUdid: workerContext.simulatorUdid,
76031
+ startedAt,
76032
+ durationMs
76033
+ };
76034
+ return recordHookFailure({
76035
+ itemContext,
76036
+ error: error48,
76037
+ results: workerContext.results,
76038
+ observer: workerContext.config.observer
76039
+ });
76040
+ }
76041
+ async function processItem(workerContext, item) {
76042
+ const state = {
76043
+ workerContext,
76044
+ item,
76045
+ startedAt: (/* @__PURE__ */ new Date()).toISOString(),
76046
+ startMs: Date.now()
76047
+ };
76048
+ emitItemStarted(state);
76049
+ const hookOutcome = await maybeInvokeHook(buildHookInvokeInput(workerContext, item));
76050
+ if (hookOutcome.isErr()) {
76051
+ return handleHookFailure(state, hookOutcome.error);
76052
+ }
76053
+ return runAndRecordItem(state);
75439
76054
  }
75440
76055
  async function runWorker(workerContext) {
75441
76056
  const { simulatorUdid, queue, config: config3 } = workerContext;
@@ -75495,7 +76110,7 @@ function runWorkerPool(config3) {
75495
76110
  const queue = setupQueue(config3);
75496
76111
  const results = [];
75497
76112
  const suiteStartMs = Date.now();
75498
- const safeRun = import_neverthrow50.ResultAsync.fromThrowable(
76113
+ const safeRun = import_neverthrow53.ResultAsync.fromThrowable(
75499
76114
  async () => runAllWorkers({ config: config3, queue, results, suiteStartMs }),
75500
76115
  (cause) => ({ type: "WORKER_POOL_FAILED", cause })
75501
76116
  );
@@ -75535,7 +76150,7 @@ function buildFreestylePipelineConfig(input) {
75535
76150
  date: date5,
75536
76151
  mcpServers: createDefaultMcpServers(simulatorUdid),
75537
76152
  allowedTools: ALLOWED_TOOLS,
75538
- timeoutMs: resolveFreestyleTimeout(item, config3) * MS_PER_SECOND3,
76153
+ timeoutMs: resolveFreestyleTimeout(item, config3) * MS_PER_SECOND4,
75539
76154
  appContext: item.prompt ? `${buildDeviceInstruction(simulatorUdid)}
75540
76155
 
75541
76156
  ${item.prompt}` : buildDeviceInstruction(simulatorUdid),
@@ -75580,30 +76195,88 @@ function makeExecuteItem(context) {
75580
76195
  };
75581
76196
  }
75582
76197
 
75583
- // src/suite/commands/run-command.ts
76198
+ // src/suite/commands/suite-run-context.ts
76199
+ var import_promises20 = __toESM(require("node:fs/promises"), 1);
76200
+ var import_node_path22 = __toESM(require("node:path"), 1);
76201
+ var import_neverthrow54 = __toESM(require_index_cjs(), 1);
76202
+
76203
+ // src/suite/core/run-id.ts
76204
+ var RUN_ID_PAD_LENGTH2 = 4;
76205
+ function toNumeric(name) {
76206
+ const parsed = Number(name);
76207
+ return Number.isInteger(parsed) && parsed > 0 ? parsed : void 0;
76208
+ }
76209
+ function highestNumeric(directories) {
76210
+ let highest = 0;
76211
+ for (const name of directories) {
76212
+ const numeric = toNumeric(name);
76213
+ if (numeric !== void 0 && numeric > highest) {
76214
+ highest = numeric;
76215
+ }
76216
+ }
76217
+ return highest;
76218
+ }
76219
+ function computeNextRunId(existingDirectories) {
76220
+ return String(highestNumeric(existingDirectories) + 1).padStart(RUN_ID_PAD_LENGTH2, "0");
76221
+ }
76222
+
76223
+ // src/suite/core/suite-id.ts
76224
+ function slugify2(glob) {
76225
+ return glob.replaceAll(/[^a-zA-Z0-9]+/g, "-").replaceAll(/-+/g, "-").replaceAll(/^-|-$/g, "");
76226
+ }
76227
+ function deriveSuiteId(input) {
76228
+ if (input.mode === "suite") {
76229
+ return input.name;
76230
+ }
76231
+ return input.globs.toSorted().map((glob) => slugify2(glob)).join("+");
76232
+ }
76233
+
76234
+ // src/suite/commands/suite-run-context.ts
75584
76235
  var ISO_DATE_LENGTH3 = 10;
75585
- var safeReaddir2 = import_neverthrow51.ResultAsync.fromThrowable(
76236
+ var safeReaddir2 = import_neverthrow54.ResultAsync.fromThrowable(
75586
76237
  async (directoryPath) => {
75587
- const entries = await import_promises19.default.readdir(directoryPath, { withFileTypes: true });
76238
+ const entries = await import_promises20.default.readdir(directoryPath, { withFileTypes: true });
75588
76239
  return entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name);
75589
76240
  },
75590
76241
  () => "READDIR_FAILED"
75591
76242
  );
75592
- var safeReadFile5 = import_neverthrow51.ResultAsync.fromThrowable(
75593
- async (filePath) => import_promises19.default.readFile(filePath, "utf8"),
75594
- () => "READ_FAILED"
75595
- );
75596
76243
  async function listRunDirectories(input) {
75597
76244
  const { outputDirectory, suiteId, date: date5 } = input;
75598
76245
  const directoryPath = import_node_path22.default.join(outputDirectory, "suite", suiteId, date5);
75599
76246
  const result = await safeReaddir2(directoryPath);
75600
76247
  return result.unwrapOr([]);
75601
76248
  }
76249
+ function deriveSuiteIdFromMode(mode) {
76250
+ if (mode.type === "suite") {
76251
+ return deriveSuiteId({ mode: "suite", name: mode.name });
76252
+ }
76253
+ return deriveSuiteId({ mode: "spec", globs: mode.globs });
76254
+ }
76255
+ async function buildSuiteRunContext(input) {
76256
+ const suiteId = deriveSuiteIdFromMode(input.mode);
76257
+ const date5 = (/* @__PURE__ */ new Date()).toISOString().slice(0, ISO_DATE_LENGTH3);
76258
+ const outputDirectory = import_node_path22.default.join(input.xqaDirectory, "output");
76259
+ const existingDirectories = await listRunDirectories({ outputDirectory, suiteId, date: date5 });
76260
+ const runId = computeNextRunId(existingDirectories);
76261
+ const context = {
76262
+ config: input.config,
76263
+ xqaDirectory: input.xqaDirectory,
76264
+ runId,
76265
+ date: date5
76266
+ };
76267
+ return { suiteId, date: date5, outputDirectory, runId, context };
76268
+ }
76269
+
76270
+ // src/suite/commands/run-command.ts
76271
+ var safeReadFile5 = import_neverthrow55.ResultAsync.fromThrowable(
76272
+ async (filePath) => import_promises21.default.readFile(filePath, "utf8"),
76273
+ () => "READ_FAILED"
76274
+ );
75602
76275
  async function resolveGlobs(input) {
75603
76276
  return (0, import_fast_glob.default)(input.globs, { cwd: input.cwd, absolute: true });
75604
76277
  }
75605
76278
  async function loadSuiteConfig(xqaDirectory, name) {
75606
- const suitePath = import_node_path22.default.join(xqaDirectory, "suites", `${name}.suite.json`);
76279
+ const suitePath = import_node_path23.default.join(xqaDirectory, "suites", `${name}.suite.json`);
75607
76280
  const contentResult = await safeReadFile5(suitePath);
75608
76281
  if (contentResult.isErr()) {
75609
76282
  return;
@@ -75626,7 +76299,10 @@ async function resolveSuiteModeItems(input) {
75626
76299
  process.stderr.write("No spec files matched\n");
75627
76300
  return;
75628
76301
  }
75629
- return [...buildSpecItems(specPaths), ...buildFreestyleItems(suiteConfig.freestyle)];
76302
+ return {
76303
+ items: [...buildSpecItems(specPaths), ...buildFreestyleItems(suiteConfig.freestyle)],
76304
+ hook: suiteConfig.hooks?.beforeEach
76305
+ };
75630
76306
  }
75631
76307
  async function resolveSpecModeItems(input) {
75632
76308
  const specPaths = await resolveGlobs({ globs: input.mode.globs, cwd: input.xqaDirectory });
@@ -75634,7 +76310,7 @@ async function resolveSpecModeItems(input) {
75634
76310
  process.stderr.write("No spec files matched\n");
75635
76311
  return;
75636
76312
  }
75637
- return buildSpecItems(specPaths);
76313
+ return { items: buildSpecItems(specPaths), hook: void 0 };
75638
76314
  }
75639
76315
  async function resolveWorkItems(input) {
75640
76316
  if (input.mode.type === "suite") {
@@ -75642,12 +76318,6 @@ async function resolveWorkItems(input) {
75642
76318
  }
75643
76319
  return resolveSpecModeItems({ ...input, mode: input.mode });
75644
76320
  }
75645
- function deriveSuiteIdFromMode(mode) {
75646
- if (mode.type === "suite") {
75647
- return deriveSuiteId({ mode: "suite", name: mode.name });
75648
- }
75649
- return deriveSuiteId({ mode: "spec", globs: mode.globs });
75650
- }
75651
76321
  async function discoverSimulators() {
75652
76322
  const result = await discoverBootedSimulators();
75653
76323
  if (result.isErr()) {
@@ -75661,21 +76331,34 @@ async function discoverSimulators() {
75661
76331
  }
75662
76332
  return { simulators: result.value, exitCode: 0 };
75663
76333
  }
75664
- async function runPool(input) {
75665
- const { context, items, simulatorUdids, signal } = input;
75666
- const display = createSuiteDisplay();
75667
- const poolResult = await runWorkerPool({
76334
+ function buildPoolConfig(input, display) {
76335
+ const { context, items, simulatorUdids, debug, signal, suiteName, hookCwd } = input;
76336
+ const debugLogger = createDebugLogger({ enabled: debug });
76337
+ const baseObserver = (event) => {
76338
+ display.onEvent(event);
76339
+ };
76340
+ const observer = debugLogger.wrapSuiteHandler(baseObserver);
76341
+ const onEvent = (itemId) => debugLogger.wrapAgentHandler((event) => {
76342
+ display.onEvent({ ...event, itemId });
76343
+ }, itemId);
76344
+ return {
75668
76345
  items,
75669
76346
  simulatorUdids,
75670
- observer: (event) => {
75671
- display.onEvent(event);
75672
- },
75673
- onEvent: (itemId) => (event) => {
75674
- display.onEvent({ ...event, itemId });
75675
- },
76347
+ observer,
76348
+ onEvent,
75676
76349
  executeItem: makeExecuteItem(context),
75677
- signal
75678
- });
76350
+ signal,
76351
+ suiteName,
76352
+ hookCwd,
76353
+ hookBaseEnv: process.env,
76354
+ hookNodeExecPath: process.execPath
76355
+ };
76356
+ }
76357
+ async function runPool(input) {
76358
+ const { hook } = input;
76359
+ const display = createSuiteDisplay();
76360
+ const poolConfig = buildPoolConfig(input, display);
76361
+ const poolResult = hook === void 0 ? await runWorkerPool(poolConfig) : await runWorkerPool({ ...poolConfig, hook });
75679
76362
  display.cleanup();
75680
76363
  return poolResult;
75681
76364
  }
@@ -75696,36 +76379,37 @@ async function writeAndReport(input) {
75696
76379
  const hasFindings = items.some((item) => item.findings.length > 0);
75697
76380
  return hasFindings ? 1 : 0;
75698
76381
  }
75699
- async function buildSuiteRunContext(input) {
75700
- const suiteId = deriveSuiteIdFromMode(input.mode);
75701
- const date5 = (/* @__PURE__ */ new Date()).toISOString().slice(0, ISO_DATE_LENGTH3);
75702
- const outputDirectory = import_node_path22.default.join(input.xqaDirectory, "output");
75703
- const existingDirectories = await listRunDirectories({ outputDirectory, suiteId, date: date5 });
75704
- const runId = computeNextRunId(existingDirectories);
75705
- const context = {
75706
- config: input.config,
75707
- xqaDirectory: input.xqaDirectory,
75708
- runId,
75709
- date: date5
76382
+ function derivePoolInput(input, context) {
76383
+ const suiteName = input.mode.type === "suite" ? input.mode.name : "specs";
76384
+ return {
76385
+ context,
76386
+ items: input.items,
76387
+ simulatorUdids: input.simulatorUdids,
76388
+ debug: input.debug,
76389
+ signal: input.signal,
76390
+ suiteName,
76391
+ hook: input.hook,
76392
+ hookCwd: input.xqaDirectory
75710
76393
  };
75711
- return { suiteId, date: date5, outputDirectory, runId, context };
76394
+ }
76395
+ async function executePool(input, runContext) {
76396
+ return runPool(derivePoolInput(input, runContext.context));
75712
76397
  }
75713
76398
  async function runSuite(input) {
75714
- const { items, simulatorUdids, signal } = input;
75715
- const { suiteId, date: date5, outputDirectory, runId, context } = await buildSuiteRunContext(input);
75716
- const poolResult = await runPool({ context, items, simulatorUdids, signal });
76399
+ const runContext = await buildSuiteRunContext(input);
76400
+ const poolResult = await executePool(input, runContext);
75717
76401
  if (poolResult.isErr()) {
75718
76402
  process.stderr.write(`Suite runner failed: ${String(poolResult.error.cause)}
75719
76403
  `);
75720
76404
  return 1;
75721
76405
  }
75722
76406
  return writeAndReport({
75723
- suiteId,
75724
- runId,
75725
- outputDirectory,
75726
- date: date5,
76407
+ suiteId: runContext.suiteId,
76408
+ runId: runContext.runId,
76409
+ outputDirectory: runContext.outputDirectory,
76410
+ date: runContext.date,
75727
76411
  items: poolResult.value,
75728
- aborted: signal.aborted
76412
+ aborted: input.signal.aborted
75729
76413
  });
75730
76414
  }
75731
76415
  async function runSuiteCommand(input) {
@@ -75733,8 +76417,8 @@ async function runSuiteCommand(input) {
75733
76417
  if (preflightExit !== void 0) {
75734
76418
  return preflightExit;
75735
76419
  }
75736
- const items = await resolveWorkItems(input);
75737
- if (items === void 0) {
76420
+ const resolved = await resolveWorkItems(input);
76421
+ if (resolved === void 0) {
75738
76422
  return 1;
75739
76423
  }
75740
76424
  const simulatorResolution = await discoverSimulators();
@@ -75748,8 +76432,9 @@ async function runSuiteCommand(input) {
75748
76432
  }
75749
76433
  return runSuite({
75750
76434
  ...input,
75751
- items,
75752
- simulatorUdids: simulators.map((sim) => sim.udid)
76435
+ items: resolved.items,
76436
+ simulatorUdids: simulators.map((sim) => sim.udid),
76437
+ hook: resolved.hook
75753
76438
  });
75754
76439
  }
75755
76440
 
@@ -75771,7 +76456,7 @@ function resolveXqaDirectory() {
75771
76456
  return result.value;
75772
76457
  }
75773
76458
  var program2 = new Command();
75774
- program2.name("xqa").description("AI-powered QA agent CLI").version(`${"1.9.0"}${false ? ` (dev build +${"0938687"})` : ""}`);
76459
+ program2.name("xqa").description("AI-powered QA agent CLI").version(`${"1.11.0"}${false ? ` (dev build +${"1f9f698"})` : ""}`);
75775
76460
  program2.command("init").description("Initialize a new xqa project in the current directory").action(() => {
75776
76461
  runInitCommand();
75777
76462
  });
@@ -75786,20 +76471,23 @@ program2.command("explore").description("Run the explorer agent; omit prompt for
75786
76471
  "-t, --timeout <seconds>",
75787
76472
  "Explorer timeout in seconds (overrides QA_EXPLORE_TIMEOUT_SECONDS)",
75788
76473
  parseTimeoutSeconds
75789
- ).action((prompt, options) => {
75790
- const xqaDirectory = resolveXqaDirectory();
75791
- runExploreCommand(
75792
- {
75793
- prompt,
75794
- verbose: options.verbose,
75795
- timeoutSeconds: options.timeout,
75796
- signal: controller.signal
75797
- },
75798
- { config: config2, xqaDirectory }
75799
- );
75800
- });
75801
- program2.command("analyse").description("Analyse a session recording with Gemini").argument("[video-path]", "Path to video file").action((videoPath) => {
75802
- void runAnalyseCommand(videoPath, config2);
76474
+ ).option("--debug", "Log timing and event details to stderr").action(
76475
+ (prompt, options) => {
76476
+ const xqaDirectory = resolveXqaDirectory();
76477
+ runExploreCommand(
76478
+ {
76479
+ prompt,
76480
+ verbose: options.verbose,
76481
+ timeoutSeconds: options.timeout,
76482
+ debug: options.debug ?? false,
76483
+ signal: controller.signal
76484
+ },
76485
+ { config: config2, xqaDirectory }
76486
+ );
76487
+ }
76488
+ );
76489
+ program2.command("analyse").description("Analyse a session recording with Gemini").argument("[video-path]", "Path to video file").option("--debug", "Log timing and event details to stderr").action((videoPath, options) => {
76490
+ void runAnalyseCommand({ videoPath, config: config2, debug: options.debug ?? false });
75803
76491
  });
75804
76492
  program2.command("completion").description("Output shell completion script").argument("<shell>", "Shell to generate completion for (bash, zsh)").action((shell) => {
75805
76493
  runCompletionCommand(program2, shell);
@@ -75812,14 +76500,19 @@ program2.command("spec").description("Run the explorer agent against a spec file
75812
76500
  "-v, --verbose [categories]",
75813
76501
  "Verbose output [prompt,tools,screen,memory] (default: all)",
75814
76502
  parseVerboseOption
75815
- ).action((specFile, options) => {
76503
+ ).option("--debug", "Log timing and event details to stderr").action((specFile, options) => {
75816
76504
  const xqaDirectory = resolveXqaDirectory();
75817
76505
  void runSpecCommand(
75818
- { specFile, verbose: options.verbose, signal: controller.signal },
76506
+ {
76507
+ specFile,
76508
+ verbose: options.verbose,
76509
+ debug: options.debug ?? false,
76510
+ signal: controller.signal
76511
+ },
75819
76512
  { config: config2, xqaDirectory }
75820
76513
  );
75821
76514
  });
75822
- program2.command("run").description("Run a test suite or a set of spec files").option("--suite <name>", "Name of the suite to run").option("--spec <globs...>", "Glob patterns matching spec files to run").action(async (options) => {
76515
+ program2.command("run").description("Run a test suite or a set of spec files").option("--suite <name>", "Name of the suite to run").option("--spec <globs...>", "Glob patterns matching spec files to run").option("--debug", "Log timing and event details to stderr").action(async (options) => {
75823
76516
  if (options.suite === void 0 === (options.spec === void 0)) {
75824
76517
  process.stderr.write("Exactly one of --suite or --spec must be provided\n");
75825
76518
  process.exit(1);
@@ -75830,6 +76523,7 @@ program2.command("run").description("Run a test suite or a set of spec files").o
75830
76523
  mode,
75831
76524
  xqaDirectory,
75832
76525
  config: config2,
76526
+ debug: options.debug ?? false,
75833
76527
  signal: controller.signal
75834
76528
  });
75835
76529
  process.exit(exitCode);