@exodus/xqa 1.6.1 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/xqa.cjs +255 -211
  2. package/package.json +2 -2
package/dist/xqa.cjs CHANGED
@@ -3719,7 +3719,7 @@ var require_index_cjs = __commonJS({
3719
3719
  return __asyncGenerator2(this, arguments, function* _a3() {
3720
3720
  const result = yield __await2(this._promise);
3721
3721
  if (result.isErr()) {
3722
- yield yield __await2(errAsync7(result.error));
3722
+ yield yield __await2(errAsync8(result.error));
3723
3723
  }
3724
3724
  return yield __await2(result.value);
3725
3725
  });
@@ -3728,7 +3728,7 @@ var require_index_cjs = __commonJS({
3728
3728
  function okAsync8(value) {
3729
3729
  return new ResultAsync12(Promise.resolve(new Ok(value)));
3730
3730
  }
3731
- function errAsync7(err19) {
3731
+ function errAsync8(err19) {
3732
3732
  return new ResultAsync12(Promise.resolve(new Err(err19)));
3733
3733
  }
3734
3734
  var fromPromise = ResultAsync12.fromPromise;
@@ -3910,14 +3910,14 @@ var require_index_cjs = __commonJS({
3910
3910
  }
3911
3911
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
3912
3912
  asyncAndThen(_f) {
3913
- return errAsync7(this.error);
3913
+ return errAsync8(this.error);
3914
3914
  }
3915
3915
  asyncAndThrough(_f) {
3916
- return errAsync7(this.error);
3916
+ return errAsync8(this.error);
3917
3917
  }
3918
3918
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
3919
3919
  asyncMap(_f) {
3920
- return errAsync7(this.error);
3920
+ return errAsync8(this.error);
3921
3921
  }
3922
3922
  unwrapOr(v2) {
3923
3923
  return v2;
@@ -3949,7 +3949,7 @@ var require_index_cjs = __commonJS({
3949
3949
  exports2.Ok = Ok;
3950
3950
  exports2.ResultAsync = ResultAsync12;
3951
3951
  exports2.err = err18;
3952
- exports2.errAsync = errAsync7;
3952
+ exports2.errAsync = errAsync8;
3953
3953
  exports2.fromAsyncThrowable = fromAsyncThrowable10;
3954
3954
  exports2.fromPromise = fromPromise;
3955
3955
  exports2.fromSafePromise = fromSafePromise2;
@@ -52810,7 +52810,7 @@ function dismissalsPath(baseDirectory, override) {
52810
52810
  }
52811
52811
 
52812
52812
  // ../../packages/pipeline/dist/index.js
52813
- var import_neverthrow29 = __toESM(require_index_cjs(), 1);
52813
+ var import_neverthrow30 = __toESM(require_index_cjs(), 1);
52814
52814
  var import_promises14 = require("node:timers/promises");
52815
52815
 
52816
52816
  // ../../agents/analyser/dist/index.js
@@ -62129,10 +62129,10 @@ function runConsolidator(input, config3) {
62129
62129
  }
62130
62130
 
62131
62131
  // ../../packages/pipeline/dist/index.js
62132
- var import_neverthrow30 = __toESM(require_index_cjs(), 1);
62133
62132
  var import_neverthrow31 = __toESM(require_index_cjs(), 1);
62134
- var import_node_fs3 = require("node:fs");
62135
62133
  var import_neverthrow32 = __toESM(require_index_cjs(), 1);
62134
+ var import_node_fs3 = require("node:fs");
62135
+ var import_neverthrow33 = __toESM(require_index_cjs(), 1);
62136
62136
  var import_promises15 = require("node:timers/promises");
62137
62137
 
62138
62138
  // ../../agents/explorer/dist/index.js
@@ -62150,9 +62150,10 @@ var import_node_child_process4 = require("node:child_process");
62150
62150
  var import_promises10 = require("node:fs/promises");
62151
62151
  var import_neverthrow19 = __toESM(require_index_cjs(), 1);
62152
62152
  var import_neverthrow20 = __toESM(require_index_cjs(), 1);
62153
+ var import_neverthrow21 = __toESM(require_index_cjs(), 1);
62153
62154
  var import_promises11 = require("node:fs/promises");
62154
62155
  var import_node_path6 = __toESM(require("node:path"), 1);
62155
- var import_neverthrow21 = __toESM(require_index_cjs(), 1);
62156
+ var import_neverthrow22 = __toESM(require_index_cjs(), 1);
62156
62157
  async function runFfmpeg(arguments_) {
62157
62158
  const { promise: promise2, resolve, reject } = Promise.withResolvers();
62158
62159
  (0, import_node_child_process3.execFile)("ffmpeg", arguments_, (error48) => {
@@ -62846,6 +62847,53 @@ function runQuery(prompt, config3) {
62846
62847
  function collectAgentOutput(prompt, config3) {
62847
62848
  return runQuery(prompt, config3).mapErr((cause) => ({ type: "QUERY_FAILED", cause }));
62848
62849
  }
62850
+ var SPEED_2X = 2;
62851
+ var SPEED_4X = 4;
62852
+ function applySpeedUpVariants({
62853
+ result,
62854
+ params,
62855
+ toRecordingError
62856
+ }) {
62857
+ const { findings, snapshots } = result;
62858
+ const { videoPath, videoPath2x, videoPath4x, signal } = params;
62859
+ if (signal?.aborted) {
62860
+ return (0, import_neverthrow20.okAsync)({ findings, snapshots });
62861
+ }
62862
+ return speedUpVideo({ inputPath: videoPath, factor: SPEED_2X, outputPath: videoPath2x }).mapErr(toRecordingError).andThen(
62863
+ () => speedUpVideo({ inputPath: videoPath, factor: SPEED_4X, outputPath: videoPath4x }).mapErr(toRecordingError).map(() => ({ findings, snapshots }))
62864
+ );
62865
+ }
62866
+ function runWithRecording(handle, collectOutput) {
62867
+ const toRecordingError = (cause) => ({
62868
+ type: "RECORDING_FAILED",
62869
+ cause
62870
+ });
62871
+ return collectOutput().andThen(
62872
+ ({ findings, snapshots }) => stopRecording(handle).mapErr(toRecordingError).map(() => ({ findings, snapshots }))
62873
+ ).orElse(
62874
+ (error48) => stopRecording(handle).mapErr(toRecordingError).andThen(() => (0, import_neverthrow20.errAsync)(error48)).orElse(() => (0, import_neverthrow20.errAsync)(error48))
62875
+ );
62876
+ }
62877
+ function startAndRun(params) {
62878
+ const { videoPath, signal, collectOutput } = params;
62879
+ const toRecordingError = (cause) => ({
62880
+ type: "RECORDING_FAILED",
62881
+ cause
62882
+ });
62883
+ return startRecording(videoPath).mapErr(toRecordingError).andThen((handle) => {
62884
+ const onAbort = () => {
62885
+ void stopRecording(handle).unwrapOr(null);
62886
+ };
62887
+ signal?.addEventListener("abort", onAbort, { once: true });
62888
+ return runWithRecording(handle, collectOutput).map((result) => {
62889
+ signal?.removeEventListener("abort", onAbort);
62890
+ return result;
62891
+ }).mapErr((error48) => {
62892
+ signal?.removeEventListener("abort", onAbort);
62893
+ return error48;
62894
+ }).andThen((result) => applySpeedUpVariants({ result, params, toRecordingError }));
62895
+ });
62896
+ }
62849
62897
  var DEV_ENVIRONMENT_SECTION = `## Environment
62850
62898
 
62851
62899
  This is a development build. Debug overlays and internal messages are expected artifacts \u2014 do not report them as findings.`;
@@ -62915,8 +62963,6 @@ A step MAY be skipped if and only if:
62915
62963
  - The action's direct target (element, modal, screen) is not present, AND
62916
62964
  - The current screen state already satisfies the expected postcondition of this step (i.e. the step's effect has already occurred or was never needed).
62917
62965
 
62918
- When skipping, emit a \`step-skipped\` finding with a one-sentence reason explaining what was absent and what already-satisfied condition justified the skip.
62919
-
62920
62966
  Do NOT skip if:
62921
62967
  - The target is absent but the screen is in an unexpected or intermediate state.
62922
62968
  - You are uncertain whether the postcondition is satisfied.
@@ -63057,29 +63103,29 @@ var INLINE_ASSERTION_DELIMITER = " \u2192 ";
63057
63103
  var NUMBERED_STEP_PREFIX = /^\d+\.\s+/;
63058
63104
  function parseTagsValue(value) {
63059
63105
  if (!value.startsWith("[") || !value.endsWith("]")) {
63060
- return (0, import_neverthrow20.err)({ type: "MALFORMED_FRONTMATTER", cause: `Invalid tags format: ${value}` });
63106
+ return (0, import_neverthrow21.err)({ type: "MALFORMED_FRONTMATTER", cause: `Invalid tags format: ${value}` });
63061
63107
  }
63062
- return (0, import_neverthrow20.ok)(
63108
+ return (0, import_neverthrow21.ok)(
63063
63109
  value.slice(1, -1).split(",").map((tag) => tag.trim()).filter((tag) => tag.length > 0)
63064
63110
  );
63065
63111
  }
63066
63112
  function parseTimeoutValue(value) {
63067
63113
  const parsed = Number(value);
63068
63114
  if (Number.isNaN(parsed) || parsed <= 0) {
63069
- return (0, import_neverthrow20.err)({ type: "MALFORMED_FRONTMATTER", cause: `Invalid timeout: ${value}` });
63115
+ return (0, import_neverthrow21.err)({ type: "MALFORMED_FRONTMATTER", cause: `Invalid timeout: ${value}` });
63070
63116
  }
63071
- return (0, import_neverthrow20.ok)(parsed);
63117
+ return (0, import_neverthrow21.ok)(parsed);
63072
63118
  }
63073
63119
  function parseFrontmatterLine(line) {
63074
63120
  const colonIndex = line.indexOf(":");
63075
63121
  if (colonIndex === -1) {
63076
- return (0, import_neverthrow20.err)({ type: "MALFORMED_FRONTMATTER", cause: `Invalid line: ${line}` });
63122
+ return (0, import_neverthrow21.err)({ type: "MALFORMED_FRONTMATTER", cause: `Invalid line: ${line}` });
63077
63123
  }
63078
63124
  const key = line.slice(0, colonIndex).trim();
63079
63125
  const value = line.slice(colonIndex + 1).trim();
63080
63126
  switch (key) {
63081
63127
  case "description": {
63082
- return (0, import_neverthrow20.ok)({ description: value });
63128
+ return (0, import_neverthrow21.ok)({ description: value });
63083
63129
  }
63084
63130
  case "tags": {
63085
63131
  return parseTagsValue(value).map((tags) => ({ tags }));
@@ -63088,7 +63134,7 @@ function parseFrontmatterLine(line) {
63088
63134
  return parseTimeoutValue(value).map((timeout) => ({ timeout }));
63089
63135
  }
63090
63136
  default: {
63091
- return (0, import_neverthrow20.ok)({});
63137
+ return (0, import_neverthrow21.ok)({});
63092
63138
  }
63093
63139
  }
63094
63140
  }
@@ -63107,18 +63153,18 @@ function mergePartials(partials) {
63107
63153
  }
63108
63154
  function combineFrontmatterLines(lines) {
63109
63155
  const lineResults = lines.filter((line) => line.trim().length > 0).map((line) => parseFrontmatterLine(line));
63110
- return import_neverthrow20.Result.combine(lineResults).map((partials) => mergePartials(partials)).map((merged) => normalizeFrontmatter(merged));
63156
+ return import_neverthrow21.Result.combine(lineResults).map((partials) => mergePartials(partials)).map((merged) => normalizeFrontmatter(merged));
63111
63157
  }
63112
63158
  function extractFrontmatter(content) {
63113
63159
  const trimmed = content.trimStart();
63114
63160
  if (!trimmed.startsWith(FRONTMATTER_FENCE)) {
63115
- return (0, import_neverthrow20.ok)({ frontmatter: emptyFrontmatter(), body: content });
63161
+ return (0, import_neverthrow21.ok)({ frontmatter: emptyFrontmatter(), body: content });
63116
63162
  }
63117
63163
  const afterOpenFence = trimmed.slice(FRONTMATTER_FENCE.length);
63118
63164
  const closeIndex = afterOpenFence.indexOf(`
63119
63165
  ${FRONTMATTER_FENCE}`);
63120
63166
  if (closeIndex === -1) {
63121
- return (0, import_neverthrow20.err)({ type: "MALFORMED_FRONTMATTER", cause: "Unclosed frontmatter fence" });
63167
+ return (0, import_neverthrow21.err)({ type: "MALFORMED_FRONTMATTER", cause: "Unclosed frontmatter fence" });
63122
63168
  }
63123
63169
  const rawFrontmatter = afterOpenFence.slice(0, closeIndex);
63124
63170
  const body = afterOpenFence.slice(closeIndex + FRONTMATTER_FENCE.length + 1);
@@ -63160,13 +63206,13 @@ function parseTestSpec(name, content) {
63160
63206
  const sections = splitIntoSections(body);
63161
63207
  const setup = sections.Setup;
63162
63208
  if (setup === void 0) {
63163
- return (0, import_neverthrow20.err)({ type: "MISSING_SETUP_SECTION" });
63209
+ return (0, import_neverthrow21.err)({ type: "MISSING_SETUP_SECTION" });
63164
63210
  }
63165
63211
  const stepsSection = sections.Steps;
63166
63212
  if (stepsSection === void 0) {
63167
- return (0, import_neverthrow20.err)({ type: "MISSING_STEPS_SECTION" });
63213
+ return (0, import_neverthrow21.err)({ type: "MISSING_STEPS_SECTION" });
63168
63214
  }
63169
- return (0, import_neverthrow20.ok)({
63215
+ return (0, import_neverthrow21.ok)({
63170
63216
  name,
63171
63217
  frontmatter,
63172
63218
  setup,
@@ -63215,25 +63261,25 @@ function direntToSpecEntry(directory, entry) {
63215
63261
  return [];
63216
63262
  }
63217
63263
  function scanDirectory(directory) {
63218
- const safeReaddir3 = (0, import_neverthrow21.fromAsyncThrowable)(
63264
+ const safeReaddir3 = (0, import_neverthrow22.fromAsyncThrowable)(
63219
63265
  async () => (0, import_promises11.readdir)(directory, { withFileTypes: true }),
63220
63266
  (cause) => ({ type: "DIR_READ_FAILED", dir: directory, cause })
63221
63267
  );
63222
- return safeReaddir3().orElse((error48) => isNotFound(error48.cause) ? (0, import_neverthrow21.okAsync)([]) : (0, import_neverthrow21.errAsync)(error48)).map(
63268
+ return safeReaddir3().orElse((error48) => isNotFound(error48.cause) ? (0, import_neverthrow22.okAsync)([]) : (0, import_neverthrow22.errAsync)(error48)).map(
63223
63269
  (entries) => entries.flatMap((entry) => direntToSpecEntry(directory, entry))
63224
63270
  );
63225
63271
  }
63226
63272
  function readEntries(entries) {
63227
- return import_neverthrow21.ResultAsync.combine(entries.map((entry) => readEntry(entry))).map(
63273
+ return import_neverthrow22.ResultAsync.combine(entries.map((entry) => readEntry(entry))).map(
63228
63274
  (results) => results.flat()
63229
63275
  );
63230
63276
  }
63231
63277
  function readEntry(entry) {
63232
- const safeReadFile6 = (0, import_neverthrow21.fromAsyncThrowable)(
63278
+ const safeReadFile6 = (0, import_neverthrow22.fromAsyncThrowable)(
63233
63279
  async () => (0, import_promises11.readFile)(entry.path, "utf8"),
63234
63280
  (cause) => ({ type: "FILE_READ_FAILED", path: entry.path, cause })
63235
63281
  );
63236
- return safeReadFile6().map((content) => [{ name: entry.name, content }]).orElse((error48) => entry.required ? (0, import_neverthrow21.errAsync)(error48) : (0, import_neverthrow21.okAsync)([]));
63282
+ return safeReadFile6().map((content) => [{ name: entry.name, content }]).orElse((error48) => entry.required ? (0, import_neverthrow22.errAsync)(error48) : (0, import_neverthrow22.okAsync)([]));
63237
63283
  }
63238
63284
  function specNameFromPath(filePath) {
63239
63285
  const parts = filePath.split("/");
@@ -63249,8 +63295,6 @@ function filterByNames(specs, specNames) {
63249
63295
  }
63250
63296
  return specs.filter((spec) => specNames.includes(spec.name));
63251
63297
  }
63252
- var SPEED_2X = 2;
63253
- var SPEED_4X = 4;
63254
63298
  var ISO_DATE_LENGTH = 10;
63255
63299
  function buildPrompt(safeConfig, specs) {
63256
63300
  return generateExplorerPrompt({
@@ -63282,12 +63326,29 @@ function toArtifacts(result, runPaths) {
63282
63326
  function emitStageEnd3(safeConfig, start) {
63283
63327
  safeConfig.onEvent?.({ type: "STAGE_END", agent: "explorer", durationMs: Date.now() - start });
63284
63328
  }
63329
+ var EMPTY_RUN_PATHS = { videoPath: "", videoPath2x: "", videoPath4x: "" };
63330
+ function collectWithoutRecording({
63331
+ safeConfig,
63332
+ prompt,
63333
+ start
63334
+ }) {
63335
+ return collectAgentOutput(prompt, safeConfig).map((result) => {
63336
+ emitStageEnd3(safeConfig, start);
63337
+ return toArtifacts(result, EMPTY_RUN_PATHS);
63338
+ }).mapErr((error48) => {
63339
+ emitStageEnd3(safeConfig, start);
63340
+ return error48;
63341
+ });
63342
+ }
63285
63343
  function collectAndFinalize({
63286
63344
  safeConfig,
63287
63345
  prompt,
63288
63346
  runPaths,
63289
63347
  start
63290
63348
  }) {
63349
+ if (safeConfig.record === false) {
63350
+ return collectWithoutRecording({ safeConfig, prompt, start });
63351
+ }
63291
63352
  return startAndRun({
63292
63353
  videoPath: runPaths.videoPath,
63293
63354
  videoPath2x: runPaths.videoPath2x,
@@ -63343,71 +63404,19 @@ function runExplorer(config3) {
63343
63404
  (0, import_promises10.mkdir)(runPaths.screenshotsDir, { recursive: true }).catch(() => null)
63344
63405
  ).andThen(() => runPipeline({ safeConfig, runPaths, start }));
63345
63406
  }
63346
- function applySpeedUpVariants({
63347
- result,
63348
- params,
63349
- toRecordingError
63350
- }) {
63351
- const { findings, snapshots } = result;
63352
- const { videoPath, videoPath2x, videoPath4x, signal } = params;
63353
- if (signal?.aborted) {
63354
- return (0, import_neverthrow19.okAsync)({ findings, snapshots });
63355
- }
63356
- return speedUpVideo({ inputPath: videoPath, factor: SPEED_2X, outputPath: videoPath2x }).mapErr(toRecordingError).andThen(
63357
- () => speedUpVideo({ inputPath: videoPath, factor: SPEED_4X, outputPath: videoPath4x }).mapErr(toRecordingError).map(() => ({ findings, snapshots }))
63358
- );
63359
- }
63360
- function applyPostProcessing({
63361
- result,
63362
- params,
63363
- toRecordingError
63364
- }) {
63365
- return applySpeedUpVariants({ result, params, toRecordingError });
63366
- }
63367
- function startAndRun(params) {
63368
- const { videoPath, signal, collectOutput } = params;
63369
- const toRecordingError = (cause) => ({
63370
- type: "RECORDING_FAILED",
63371
- cause
63372
- });
63373
- return startRecording(videoPath).mapErr(toRecordingError).andThen((handle) => {
63374
- const onAbort = () => {
63375
- void stopRecording(handle).unwrapOr(null);
63376
- };
63377
- signal?.addEventListener("abort", onAbort, { once: true });
63378
- return runWithRecording(handle, collectOutput).map((result) => {
63379
- signal?.removeEventListener("abort", onAbort);
63380
- return result;
63381
- }).mapErr((error48) => {
63382
- signal?.removeEventListener("abort", onAbort);
63383
- return error48;
63384
- }).andThen((result) => applyPostProcessing({ result, params, toRecordingError }));
63385
- });
63386
- }
63387
- function runWithRecording(handle, collectOutput) {
63388
- const toRecordingError = (cause) => ({
63389
- type: "RECORDING_FAILED",
63390
- cause
63391
- });
63392
- return collectOutput().andThen(
63393
- ({ findings, snapshots }) => stopRecording(handle).mapErr(toRecordingError).map(() => ({ findings, snapshots }))
63394
- ).orElse(
63395
- (error48) => stopRecording(handle).mapErr(toRecordingError).andThen(() => (0, import_neverthrow19.errAsync)(error48)).orElse(() => (0, import_neverthrow19.errAsync)(error48))
63396
- );
63397
- }
63398
63407
 
63399
63408
  // ../../packages/pipeline/dist/index.js
63400
- var import_neverthrow33 = __toESM(require_index_cjs(), 1);
63409
+ var import_neverthrow34 = __toESM(require_index_cjs(), 1);
63401
63410
 
63402
63411
  // ../../agents/inspector/dist/index.js
63403
- var import_neverthrow22 = __toESM(require_index_cjs(), 1);
63404
- var import_promises12 = require("node:fs/promises");
63405
63412
  var import_neverthrow23 = __toESM(require_index_cjs(), 1);
63413
+ var import_promises12 = require("node:fs/promises");
63406
63414
  var import_neverthrow24 = __toESM(require_index_cjs(), 1);
63407
63415
  var import_neverthrow25 = __toESM(require_index_cjs(), 1);
63408
63416
  var import_neverthrow26 = __toESM(require_index_cjs(), 1);
63409
- var import_sharp2 = __toESM(require("sharp"), 1);
63410
63417
  var import_neverthrow27 = __toESM(require_index_cjs(), 1);
63418
+ var import_sharp2 = __toESM(require("sharp"), 1);
63419
+ var import_neverthrow28 = __toESM(require_index_cjs(), 1);
63411
63420
  var import_promises13 = require("node:fs/promises");
63412
63421
  var import_node_path7 = __toESM(require("node:path"), 1);
63413
63422
 
@@ -66036,7 +66045,7 @@ var jsYaml = {
66036
66045
  };
66037
66046
 
66038
66047
  // ../../agents/inspector/dist/index.js
66039
- var import_neverthrow28 = __toESM(require_index_cjs(), 1);
66048
+ var import_neverthrow29 = __toESM(require_index_cjs(), 1);
66040
66049
  var MS_PER_DAY = 864e5;
66041
66050
  function checkStaleness({ lastUpdated, thresholdDays, now }) {
66042
66051
  if (!lastUpdated) {
@@ -66113,7 +66122,7 @@ function mapRawFinding(item) {
66113
66122
  function parseJson(raw) {
66114
66123
  return JSON.parse(raw);
66115
66124
  }
66116
- var safeJsonParse3 = (0, import_neverthrow25.fromThrowable)(parseJson);
66125
+ var safeJsonParse3 = (0, import_neverthrow26.fromThrowable)(parseJson);
66117
66126
  function parseClaudeResponse(raw) {
66118
66127
  const parseResult = safeJsonParse3(raw);
66119
66128
  if (parseResult.isErr()) {
@@ -66140,7 +66149,7 @@ async function downscaleBuffer(buffer) {
66140
66149
  return (0, import_sharp2.default)(buffer).resize({ width: targetWidth }).toBuffer();
66141
66150
  }
66142
66151
  function downscale(buffer) {
66143
- return (0, import_neverthrow26.fromAsyncThrowable)(
66152
+ return (0, import_neverthrow27.fromAsyncThrowable)(
66144
66153
  downscaleBuffer,
66145
66154
  (cause) => ({ type: "CLAUDE_API_FAILED", cause })
66146
66155
  )(buffer);
@@ -66215,7 +66224,7 @@ async function fetchClaudeText({
66215
66224
  return block?.type === "text" ? block.text : "";
66216
66225
  }
66217
66226
  function callClaude(options) {
66218
- return (0, import_neverthrow24.fromAsyncThrowable)(
66227
+ return (0, import_neverthrow25.fromAsyncThrowable)(
66219
66228
  fetchClaudeText,
66220
66229
  (cause) => ({ type: "CLAUDE_API_FAILED", cause })
66221
66230
  )(options);
@@ -66227,9 +66236,9 @@ function toFindings(text) {
66227
66236
  const cleaned = stripCodeFences(text);
66228
66237
  const findings = parseClaudeResponse(cleaned);
66229
66238
  if (!findings) {
66230
- return (0, import_neverthrow24.errAsync)({ type: "CLAUDE_RESPONSE_INVALID", raw: cleaned });
66239
+ return (0, import_neverthrow25.errAsync)({ type: "CLAUDE_RESPONSE_INVALID", raw: cleaned });
66231
66240
  }
66232
- return (0, import_neverthrow24.okAsync)(findings);
66241
+ return (0, import_neverthrow25.okAsync)(findings);
66233
66242
  }
66234
66243
  function buildResolveMessages(screenshotBase64, artboardNames) {
66235
66244
  return [
@@ -66266,12 +66275,12 @@ async function fetchResolveName({
66266
66275
  }
66267
66276
  function resolveArtboard(screenshot, artboardNames) {
66268
66277
  if (artboardNames.length === 0) {
66269
- return (0, import_neverthrow24.okAsync)(void 0);
66278
+ return (0, import_neverthrow25.okAsync)(void 0);
66270
66279
  }
66271
66280
  const anthropic = new Anthropic();
66272
66281
  return downscale(screenshot).andThen((scaled) => {
66273
66282
  const screenshotBase64 = scaled.toString("base64");
66274
- return (0, import_neverthrow24.fromAsyncThrowable)(
66283
+ return (0, import_neverthrow25.fromAsyncThrowable)(
66275
66284
  fetchResolveName,
66276
66285
  (cause) => ({ type: "CLAUDE_API_FAILED", cause })
66277
66286
  )({ anthropic, screenshotBase64, artboardNames }).map((name) => {
@@ -66334,7 +66343,7 @@ var SEVERITY_CONFIDENCE = {
66334
66343
  medium: CONFIDENCE_MEDIUM2,
66335
66344
  low: CONFIDENCE_LOW2
66336
66345
  };
66337
- var safeJsonParse22 = (0, import_neverthrow27.fromThrowable)(JSON.parse);
66346
+ var safeJsonParse22 = (0, import_neverthrow28.fromThrowable)(JSON.parse);
66338
66347
  function buildFindCandidatesMessages(screenshotBase64, artboardNames) {
66339
66348
  return [
66340
66349
  {
@@ -66381,12 +66390,12 @@ async function fetchCandidateNames({
66381
66390
  }
66382
66391
  function findCandidates(screenshot, artboardNames) {
66383
66392
  if (artboardNames.length === 0) {
66384
- return (0, import_neverthrow27.okAsync)([]);
66393
+ return (0, import_neverthrow28.okAsync)([]);
66385
66394
  }
66386
66395
  const anthropic = new Anthropic();
66387
66396
  return downscale(screenshot).andThen((scaled) => {
66388
66397
  const screenshotBase64 = scaled.toString("base64");
66389
- return (0, import_neverthrow27.fromAsyncThrowable)(
66398
+ return (0, import_neverthrow28.fromAsyncThrowable)(
66390
66399
  fetchCandidateNames,
66391
66400
  (cause) => ({ type: "CLAUDE_API_FAILED", cause })
66392
66401
  )({ anthropic, screenshotBase64, artboardNames });
@@ -66473,14 +66482,14 @@ async function fetchDesignContextText({
66473
66482
  function toDesignContextFindings(text) {
66474
66483
  const findings = parseConservativeResponse(text);
66475
66484
  if (!findings) {
66476
- return (0, import_neverthrow27.errAsync)({ type: "CLAUDE_RESPONSE_INVALID", raw: text });
66485
+ return (0, import_neverthrow28.errAsync)({ type: "CLAUDE_RESPONSE_INVALID", raw: text });
66477
66486
  }
66478
- return (0, import_neverthrow27.okAsync)(findings);
66487
+ return (0, import_neverthrow28.okAsync)(findings);
66479
66488
  }
66480
66489
  async function downscaleAll(buffers) {
66481
66490
  return Promise.all(buffers.map(async (buf) => downscaleBuffer(buf)));
66482
66491
  }
66483
- var downscaleAllBuffers = (0, import_neverthrow27.fromAsyncThrowable)(
66492
+ var downscaleAllBuffers = (0, import_neverthrow28.fromAsyncThrowable)(
66484
66493
  downscaleAll,
66485
66494
  (cause) => ({ type: "CLAUDE_API_FAILED", cause })
66486
66495
  );
@@ -66490,7 +66499,7 @@ function compareWithDesignContext(screenshot, artboards) {
66490
66499
  const screenshotBase64 = scaledScreenshot.toString("base64");
66491
66500
  return downscaleAllBuffers(artboards).andThen((scaledArtboards) => {
66492
66501
  const artboardBase64s = scaledArtboards.map((buf) => buf.toString("base64"));
66493
- return (0, import_neverthrow27.fromAsyncThrowable)(
66502
+ return (0, import_neverthrow28.fromAsyncThrowable)(
66494
66503
  fetchDesignContextText,
66495
66504
  (cause) => ({ type: "CLAUDE_API_FAILED", cause })
66496
66505
  )({ anthropic, screenshotBase64, artboardBase64s }).andThen(toDesignContextFindings);
@@ -66723,7 +66732,7 @@ async function initArtboardNames({ designStore, config: config3, state }) {
66723
66732
  return state.artboardNamesPromise;
66724
66733
  }
66725
66734
  function readScreenshot(screenshotPath, stepIndex) {
66726
- return import_neverthrow23.ResultAsync.fromThrowable(
66735
+ return import_neverthrow24.ResultAsync.fromThrowable(
66727
66736
  import_promises12.readFile,
66728
66737
  (cause) => ({ type: "SCREENSHOT_READ_FAILED", stepIndex, cause })
66729
66738
  )(screenshotPath);
@@ -66799,7 +66808,7 @@ function buildInspector(state, context) {
66799
66808
  const { promise: promise2, resolve } = Promise.withResolvers();
66800
66809
  state.resolve = resolve;
66801
66810
  applyTryResolve(state);
66802
- return (0, import_neverthrow22.fromSafePromise)(promise2);
66811
+ return (0, import_neverthrow23.fromSafePromise)(promise2);
66803
66812
  }
66804
66813
  };
66805
66814
  }
@@ -66823,10 +66832,10 @@ async function readAndParseSidecar(sidecarPath) {
66823
66832
  return parseMeta(raw);
66824
66833
  }
66825
66834
  function readSidecarFile(sidecarPath) {
66826
- return (0, import_neverthrow28.fromAsyncThrowable)(
66835
+ return (0, import_neverthrow29.fromAsyncThrowable)(
66827
66836
  readAndParseSidecar,
66828
66837
  () => ({})
66829
- )(sidecarPath).orElse(() => (0, import_neverthrow28.okAsync)({}));
66838
+ )(sidecarPath).orElse(() => (0, import_neverthrow29.okAsync)({}));
66830
66839
  }
66831
66840
  function isEnoent(error48) {
66832
66841
  return error48?.code === "ENOENT";
@@ -66835,13 +66844,13 @@ function wrapFsError(cause) {
66835
66844
  return { type: "FS_ERROR", cause };
66836
66845
  }
66837
66846
  function toFsError(fsError) {
66838
- return (0, import_neverthrow28.errAsync)(fsError);
66847
+ return (0, import_neverthrow29.errAsync)(fsError);
66839
66848
  }
66840
66849
  function missingBuffer() {
66841
- return (0, import_neverthrow28.okAsync)(void 0);
66850
+ return (0, import_neverthrow29.okAsync)(void 0);
66842
66851
  }
66843
66852
  function missingArtboard() {
66844
- return (0, import_neverthrow28.okAsync)(void 0);
66853
+ return (0, import_neverthrow29.okAsync)(void 0);
66845
66854
  }
66846
66855
  var FsDesignStore = class {
66847
66856
  designsDirectory;
@@ -66849,12 +66858,12 @@ var FsDesignStore = class {
66849
66858
  this.designsDirectory = designsDirectory;
66850
66859
  }
66851
66860
  listArtboards() {
66852
- return (0, import_neverthrow28.fromAsyncThrowable)(
66861
+ return (0, import_neverthrow29.fromAsyncThrowable)(
66853
66862
  import_promises13.readdir,
66854
66863
  wrapFsError
66855
66864
  )(this.designsDirectory).orElse((fsError) => {
66856
66865
  if (fsError.type === "FS_ERROR" && isEnoent(fsError.cause)) {
66857
- return (0, import_neverthrow28.okAsync)([]);
66866
+ return (0, import_neverthrow29.okAsync)([]);
66858
66867
  }
66859
66868
  return toFsError(fsError);
66860
66869
  }).map(
@@ -66864,7 +66873,7 @@ var FsDesignStore = class {
66864
66873
  getArtboard(filename) {
66865
66874
  const pngPath = import_node_path7.default.join(this.designsDirectory, `${filename}.png`);
66866
66875
  const sidecarPath = import_node_path7.default.join(this.designsDirectory, `${filename}.meta.yaml`);
66867
- return (0, import_neverthrow28.fromAsyncThrowable)(
66876
+ return (0, import_neverthrow29.fromAsyncThrowable)(
66868
66877
  import_promises13.readFile,
66869
66878
  wrapFsError
66870
66879
  )(pngPath).orElse((fsError) => {
@@ -66890,10 +66899,10 @@ function attemptRetry(options) {
66890
66899
  const { factory, config: config3, delayFunction, onRetry, attempt } = options;
66891
66900
  return factory().orElse((error48) => {
66892
66901
  if (attempt >= config3.maxAttempts) {
66893
- return (0, import_neverthrow31.errAsync)(error48);
66902
+ return (0, import_neverthrow32.errAsync)(error48);
66894
66903
  }
66895
66904
  const delay = config3.baseDelayMs * Math.pow(2, attempt - 1);
66896
- return import_neverthrow31.ResultAsync.fromPromise(
66905
+ return import_neverthrow32.ResultAsync.fromPromise(
66897
66906
  (onRetry?.({ attempt, maxAttempts: config3.maxAttempts, delayMs: delay, error: error48 }), delayFunction(delay)),
66898
66907
  () => error48
66899
66908
  ).andThen(
@@ -66913,7 +66922,7 @@ function withRetry(factory, options) {
66913
66922
  var CONSOLIDATOR_AGENT = "consolidator";
66914
66923
  function analyserFallback(artifacts, onEvent) {
66915
66924
  onEvent?.({ type: "AGENT_FAILED_NON_CRITICAL", agent: "analyser", attempts: RETRY_MAX_ATTEMPTS });
66916
- return (0, import_neverthrow30.okAsync)(artifacts.findings);
66925
+ return (0, import_neverthrow31.okAsync)(artifacts.findings);
66917
66926
  }
66918
66927
  function runAnalyserWithRetry(params) {
66919
66928
  const { artifacts, config: config3, onEvent } = params;
@@ -66943,7 +66952,7 @@ function resolveVisualFindings({
66943
66952
  onEvent
66944
66953
  }) {
66945
66954
  if (config3.analyser === void 0 || config3.signal?.aborted) {
66946
- return (0, import_neverthrow30.okAsync)(artifacts.findings);
66955
+ return (0, import_neverthrow31.okAsync)(artifacts.findings);
66947
66956
  }
66948
66957
  return runAnalyserWithRetry({ artifacts, config: config3, onEvent });
66949
66958
  }
@@ -66953,7 +66962,7 @@ function unmergedFallback(allFindings, onEvent) {
66953
66962
  agent: CONSOLIDATOR_AGENT,
66954
66963
  message: "Consolidation failed, returning unmerged findings"
66955
66964
  });
66956
- return (0, import_neverthrow30.okAsync)({ findings: allFindings, dismissed: [] });
66965
+ return (0, import_neverthrow31.okAsync)({ findings: allFindings, dismissed: [] });
66957
66966
  }
66958
66967
  function mergeWithFallback(options) {
66959
66968
  const {
@@ -66980,7 +66989,7 @@ function consolidate(options) {
66980
66989
  const { artifacts, inspectorFindings, runId, dismissals, config: config3, consolidatorConfig, onEvent } = options;
66981
66990
  return resolveVisualFindings({ artifacts, config: config3, onEvent }).andThen((visualFindings) => {
66982
66991
  if (config3.signal?.aborted) {
66983
- return (0, import_neverthrow30.okAsync)({ findings: artifacts.findings, dismissed: [] });
66992
+ return (0, import_neverthrow31.okAsync)({ findings: artifacts.findings, dismissed: [] });
66984
66993
  }
66985
66994
  return mergeWithFallback({
66986
66995
  artifacts,
@@ -66993,8 +67002,8 @@ function consolidate(options) {
66993
67002
  });
66994
67003
  });
66995
67004
  }
66996
- var safeReadFile = (0, import_neverthrow32.fromThrowable)((filePath) => (0, import_node_fs3.readFileSync)(filePath, "utf8"));
66997
- var safeParseJson2 = (0, import_neverthrow32.fromThrowable)(JSON.parse);
67005
+ var safeReadFile = (0, import_neverthrow33.fromThrowable)((filePath) => (0, import_node_fs3.readFileSync)(filePath, "utf8"));
67006
+ var safeParseJson2 = (0, import_neverthrow33.fromThrowable)(JSON.parse);
66998
67007
  function isEnoent2(error48) {
66999
67008
  if (!(error48 instanceof Error)) {
67000
67009
  return false;
@@ -67006,19 +67015,19 @@ function loadDismissals(filePath) {
67006
67015
  const readResult = safeReadFile(filePath);
67007
67016
  if (readResult.isErr()) {
67008
67017
  if (isEnoent2(readResult.error)) {
67009
- return (0, import_neverthrow32.ok)([]);
67018
+ return (0, import_neverthrow33.ok)([]);
67010
67019
  }
67011
- return (0, import_neverthrow32.err)({ type: "DISMISSALS_LOAD_FAILED", cause: readResult.error });
67020
+ return (0, import_neverthrow33.err)({ type: "DISMISSALS_LOAD_FAILED", cause: readResult.error });
67012
67021
  }
67013
67022
  return safeParseJson2(readResult.value).mapErr((cause) => ({ type: "DISMISSALS_LOAD_FAILED", cause })).andThen((data) => {
67014
67023
  const store = data;
67015
67024
  if (!Array.isArray(store.dismissed)) {
67016
- return (0, import_neverthrow32.err)({
67025
+ return (0, import_neverthrow33.err)({
67017
67026
  type: "DISMISSALS_LOAD_FAILED",
67018
67027
  cause: "invalid shape: dismissed is not an array"
67019
67028
  });
67020
67029
  }
67021
- return (0, import_neverthrow32.ok)(store.dismissed);
67030
+ return (0, import_neverthrow33.ok)(store.dismissed);
67022
67031
  });
67023
67032
  }
67024
67033
  function toInspectorStepEvent(event) {
@@ -67105,7 +67114,7 @@ function runExplorerWithTeardown(explorerConfig, udid) {
67105
67114
  return runExplorer(explorerConfig).mapErr((cause) => ({ type: "EXPLORER_FAILED", cause })).andThen(
67106
67115
  (artifacts) => disableTouchIndicators(udid).mapErr(toSimulatorError).map(() => artifacts)
67107
67116
  ).orElse(
67108
- (error48) => disableTouchIndicators(udid).mapErr(toSimulatorError).andThen(() => (0, import_neverthrow33.errAsync)(error48)).orElse(() => (0, import_neverthrow33.errAsync)(error48))
67117
+ (error48) => disableTouchIndicators(udid).mapErr(toSimulatorError).andThen(() => (0, import_neverthrow34.errAsync)(error48)).orElse(() => (0, import_neverthrow34.errAsync)(error48))
67109
67118
  );
67110
67119
  }
67111
67120
  function runExplorerWithRetry(options) {
@@ -67131,12 +67140,12 @@ async function drainAfterExplorer(options) {
67131
67140
  inspector?.close();
67132
67141
  const inspectorFindings = inspector ? await collectInspectorFindings({ inspector, onEvent, totalSteps: enqueuedCount.value }) : [];
67133
67142
  if (explorerResult.isErr()) {
67134
- return (0, import_neverthrow33.err)(explorerResult.error);
67143
+ return (0, import_neverthrow34.err)(explorerResult.error);
67135
67144
  }
67136
- return (0, import_neverthrow33.ok)({ artifacts: explorerResult.value, inspectorFindings });
67145
+ return (0, import_neverthrow34.ok)({ artifacts: explorerResult.value, inspectorFindings });
67137
67146
  }
67138
67147
  function runExplorerAndDrain(options) {
67139
- return new import_neverthrow33.ResultAsync(drainAfterExplorer(options));
67148
+ return new import_neverthrow34.ResultAsync(drainAfterExplorer(options));
67140
67149
  }
67141
67150
  function createDefaultMcpServers(udid) {
67142
67151
  return {
@@ -67148,7 +67157,7 @@ function runAnalysis(artifacts, config3) {
67148
67157
  }
67149
67158
  var ISO_DATE_LENGTH2 = 10;
67150
67159
  var RUN_ID_PAD_LENGTH = 4;
67151
- var safeReaddirSync = (0, import_neverthrow29.fromThrowable)((directory) => (0, import_node_fs2.readdirSync)(directory));
67160
+ var safeReaddirSync = (0, import_neverthrow30.fromThrowable)((directory) => (0, import_node_fs2.readdirSync)(directory));
67152
67161
  function nextRunId(outputDirectory, date5) {
67153
67162
  const entries = safeReaddirSync(`${outputDirectory}/${date5}`).unwrapOr([]);
67154
67163
  let max = 0;
@@ -67160,7 +67169,7 @@ function nextRunId(outputDirectory, date5) {
67160
67169
  }
67161
67170
  return String(max + 1).padStart(RUN_ID_PAD_LENGTH, "0");
67162
67171
  }
67163
- var writeOutputFile = (0, import_neverthrow29.fromThrowable)(
67172
+ var writeOutputFile = (0, import_neverthrow30.fromThrowable)(
67164
67173
  (params) => {
67165
67174
  const { findingsPath, outputDirectory, json: json3 } = params;
67166
67175
  (0, import_node_fs2.mkdirSync)(outputDirectory, { recursive: true });
@@ -67173,15 +67182,15 @@ function validatePipelineConfig(config3) {
67173
67182
  const runId = config3.runId ?? nextRunId(config3.outputDir, date5);
67174
67183
  const runPathsResult = resolveRunPaths({ outputDirectory: config3.outputDir, runId, date: date5 });
67175
67184
  if (runPathsResult.isErr()) {
67176
- return (0, import_neverthrow29.err)({ type: "RUN_PATHS_FAILED", cause: runPathsResult.error });
67185
+ return (0, import_neverthrow30.err)({ type: "RUN_PATHS_FAILED", cause: runPathsResult.error });
67177
67186
  }
67178
67187
  const dismissalsResult = loadDismissals(
67179
67188
  dismissalsPath(config3.outputDir, process.env.QA_DISMISSALS_PATH)
67180
67189
  );
67181
67190
  if (dismissalsResult.isErr()) {
67182
- return (0, import_neverthrow29.err)(dismissalsResult.error);
67191
+ return (0, import_neverthrow30.err)(dismissalsResult.error);
67183
67192
  }
67184
- return (0, import_neverthrow29.ok)({ runId, date: date5, runPaths: runPathsResult.value, dismissals: dismissalsResult.value });
67193
+ return (0, import_neverthrow30.ok)({ runId, date: date5, runPaths: runPathsResult.value, dismissals: dismissalsResult.value });
67185
67194
  }
67186
67195
  function buildExplorerConfig({
67187
67196
  config: config3,
@@ -67196,7 +67205,8 @@ function buildExplorerConfig({
67196
67205
  date: date5,
67197
67206
  onEvent,
67198
67207
  signal: config3.signal,
67199
- udid: config3.simulatorUdid ?? "booted"
67208
+ udid: config3.simulatorUdid ?? "booted",
67209
+ record: config3.explorer.record ?? config3.analyser !== void 0
67200
67210
  };
67201
67211
  }
67202
67212
  function buildOutput(consolidationResult, options) {
@@ -67217,11 +67227,11 @@ function buildOutput(consolidationResult, options) {
67217
67227
  function buildPipelineSetup(config3) {
67218
67228
  const validatedResult = validatePipelineConfig(config3);
67219
67229
  if (validatedResult.isErr()) {
67220
- return (0, import_neverthrow29.err)(validatedResult.error);
67230
+ return (0, import_neverthrow30.err)(validatedResult.error);
67221
67231
  }
67222
67232
  const { runId, date: date5, runPaths, dismissals } = validatedResult.value;
67223
67233
  const { inspector, explorerOnEvent, enqueuedCount } = buildInspectorSetup(config3);
67224
- return (0, import_neverthrow29.ok)({
67234
+ return (0, import_neverthrow30.ok)({
67225
67235
  runId,
67226
67236
  udid: config3.simulatorUdid ?? "booted",
67227
67237
  runPaths,
@@ -67265,19 +67275,19 @@ function executePipeline(setup, config3) {
67265
67275
  function runPipeline2(config3) {
67266
67276
  const setupResult = buildPipelineSetup(config3);
67267
67277
  if (setupResult.isErr()) {
67268
- return (0, import_neverthrow29.errAsync)(setupResult.error);
67278
+ return (0, import_neverthrow30.errAsync)(setupResult.error);
67269
67279
  }
67270
67280
  return executePipeline(setupResult.value, config3);
67271
67281
  }
67272
67282
 
67273
67283
  // src/commands/analyse-command.ts
67274
- var import_neverthrow34 = __toESM(require_index_cjs(), 1);
67284
+ var import_neverthrow35 = __toESM(require_index_cjs(), 1);
67275
67285
 
67276
67286
  // src/commands/item-events.ts
67277
67287
  function emitItemStart(identity, at) {
67278
- const { display, itemId, itemName } = identity;
67288
+ const { display, itemId, itemName, simulatorUdid } = identity;
67279
67289
  display.onEvent({ type: "ITEM_QUEUED", item: { id: itemId, name: itemName } });
67280
- display.onEvent({ type: "ITEM_STARTED", itemId, itemName, simulatorUdid: "", at });
67290
+ display.onEvent({ type: "ITEM_STARTED", itemId, itemName, simulatorUdid, at });
67281
67291
  }
67282
67292
  function emitItemCompleted(input) {
67283
67293
  const { identity, startedAt, findingsCount } = input;
@@ -67346,7 +67356,7 @@ function buildArtifacts(videoPath) {
67346
67356
  return { videoPath, videoPath2x: "", videoPath4x: videoPath, findings: [], snapshots: [] };
67347
67357
  }
67348
67358
  async function checkVideoPathExists(videoPath) {
67349
- const safeAccess = (0, import_neverthrow34.fromAsyncThrowable)(import_promises16.access, () => ({ type: "FILE_NOT_FOUND" }));
67359
+ const safeAccess = (0, import_neverthrow35.fromAsyncThrowable)(import_promises16.access, () => ({ type: "FILE_NOT_FOUND" }));
67350
67360
  const result = await safeAccess(videoPath);
67351
67361
  return result.isOk();
67352
67362
  }
@@ -67371,7 +67381,8 @@ async function runAnalysisAndExit(artifacts, apiKey) {
67371
67381
  const identity = {
67372
67382
  display: createSoloDisplay(),
67373
67383
  itemId: ITEM_ID,
67374
- itemName: ITEM_NAME
67384
+ itemName: ITEM_NAME,
67385
+ simulatorUdid: ""
67375
67386
  };
67376
67387
  const startedAt = Date.now();
67377
67388
  emitItemStart(identity, startedAt);
@@ -67411,7 +67422,7 @@ async function runAnalyseCommand(videoPath, config3) {
67411
67422
  }
67412
67423
 
67413
67424
  // src/core/completion-generator.ts
67414
- var import_neverthrow35 = __toESM(require_index_cjs(), 1);
67425
+ var import_neverthrow36 = __toESM(require_index_cjs(), 1);
67415
67426
  function extractLongFlags(flags) {
67416
67427
  return flags.split(/[\s,]+/).filter((token) => token.startsWith("--"));
67417
67428
  }
@@ -67501,9 +67512,9 @@ complete -F _xqa_completion xqa`;
67501
67512
  }
67502
67513
  function generateCompletion(commands, shell) {
67503
67514
  if (shell !== "bash" && shell !== "zsh") {
67504
- return (0, import_neverthrow35.err)({ type: "UNSUPPORTED_SHELL", shell });
67515
+ return (0, import_neverthrow36.err)({ type: "UNSUPPORTED_SHELL", shell });
67505
67516
  }
67506
- return (0, import_neverthrow35.ok)(shell === "zsh" ? generateZshCompletion(commands) : generateBashCompletion(commands));
67517
+ return (0, import_neverthrow36.ok)(shell === "zsh" ? generateZshCompletion(commands) : generateBashCompletion(commands));
67507
67518
  }
67508
67519
 
67509
67520
  // src/commands/completion-command.ts
@@ -67561,16 +67572,16 @@ var FFMPEG_INSTALL_MESSAGE = "ffmpeg is not installed. Run:\n brew install ffmp
67561
67572
  // src/core/last-path.ts
67562
67573
  var import_node_fs4 = require("node:fs");
67563
67574
  var import_node_path8 = __toESM(require("node:path"), 1);
67564
- var import_neverthrow36 = __toESM(require_index_cjs(), 1);
67575
+ var import_neverthrow37 = __toESM(require_index_cjs(), 1);
67565
67576
  function resolveLastPath(argument, stateContent) {
67566
67577
  if (argument !== void 0) {
67567
- return (0, import_neverthrow36.ok)(argument);
67578
+ return (0, import_neverthrow37.ok)(argument);
67568
67579
  }
67569
67580
  const trimmed = stateContent?.trim();
67570
67581
  if (trimmed) {
67571
- return (0, import_neverthrow36.ok)(trimmed);
67582
+ return (0, import_neverthrow37.ok)(trimmed);
67572
67583
  }
67573
- return (0, import_neverthrow36.err)({ type: "NO_ARG_AND_NO_STATE" });
67584
+ return (0, import_neverthrow37.err)({ type: "NO_ARG_AND_NO_STATE" });
67574
67585
  }
67575
67586
  function lastPathFilePath(xqaDirectoryectory) {
67576
67587
  return import_node_path8.default.join(xqaDirectoryectory, "last-findings-path");
@@ -67582,7 +67593,7 @@ function writeLastPath(xqaDirectory, findingsPath) {
67582
67593
  // src/shell/app-context.ts
67583
67594
  var import_promises17 = require("node:fs/promises");
67584
67595
  var import_node_path9 = __toESM(require("node:path"), 1);
67585
- var import_neverthrow37 = __toESM(require_index_cjs(), 1);
67596
+ var import_neverthrow38 = __toESM(require_index_cjs(), 1);
67586
67597
  var HTML_COMMENT_PATTERN = /<!--[\s\S]*?-->/g;
67587
67598
  function isEnoentError(value) {
67588
67599
  return value !== null && typeof value === "object" && "code" in value && value.code === "ENOENT";
@@ -67592,9 +67603,9 @@ function toAppContextError(cause) {
67592
67603
  }
67593
67604
  function absentContext() {
67594
67605
  const absent = void 0;
67595
- return (0, import_neverthrow37.ok)(absent);
67606
+ return (0, import_neverthrow38.ok)(absent);
67596
67607
  }
67597
- var safeReadFile2 = import_neverthrow37.ResultAsync.fromThrowable(
67608
+ var safeReadFile2 = import_neverthrow38.ResultAsync.fromThrowable(
67598
67609
  async (filePath) => (0, import_promises17.readFile)(filePath, "utf8"),
67599
67610
  toAppContextError
67600
67611
  );
@@ -67608,7 +67619,7 @@ function readContextFile(xqaDirectory, filename) {
67608
67619
  if (isEnoentError(error48.cause)) {
67609
67620
  return absentContext();
67610
67621
  }
67611
- return (0, import_neverthrow37.err)(error48);
67622
+ return (0, import_neverthrow38.err)(error48);
67612
67623
  });
67613
67624
  }
67614
67625
  function readAppContext(xqaDirectory) {
@@ -67620,7 +67631,7 @@ function readExploreContext(xqaDirectory) {
67620
67631
 
67621
67632
  // src/shell/ffmpeg-check.ts
67622
67633
  var import_node_child_process5 = require("node:child_process");
67623
- var import_neverthrow38 = __toESM(require_index_cjs(), 1);
67634
+ var import_neverthrow39 = __toESM(require_index_cjs(), 1);
67624
67635
  async function whichFfmpeg() {
67625
67636
  const { promise: promise2, resolve, reject } = Promise.withResolvers();
67626
67637
  (0, import_node_child_process5.execFile)("which", ["ffmpeg"], (error48, stdout) => {
@@ -67632,7 +67643,7 @@ async function whichFfmpeg() {
67632
67643
  });
67633
67644
  return promise2;
67634
67645
  }
67635
- var safeWhichFfmpeg = (0, import_neverthrow38.fromAsyncThrowable)(
67646
+ var safeWhichFfmpeg = (0, import_neverthrow39.fromAsyncThrowable)(
67636
67647
  whichFfmpeg,
67637
67648
  () => ({ type: "FFMPEG_NOT_FOUND" })
67638
67649
  );
@@ -67680,11 +67691,13 @@ function buildPipelineConfig({
67680
67691
  config: config3,
67681
67692
  xqaDirectory,
67682
67693
  explorer,
67683
- onEvent
67694
+ onEvent,
67695
+ simulatorUdid
67684
67696
  }) {
67685
67697
  const base = {
67686
67698
  outputDir: import_node_path10.default.join(xqaDirectory, "output"),
67687
67699
  runId: config3.QA_RUN_ID,
67700
+ simulatorUdid,
67688
67701
  onEvent,
67689
67702
  signal: input.signal,
67690
67703
  inspector: { designsDirectory: import_node_path10.default.join(xqaDirectory, "designs") },
@@ -67705,7 +67718,9 @@ function buildSuccessMessage(output) {
67705
67718
  `;
67706
67719
  }
67707
67720
  var ITEM_ID2 = "explore";
67708
- var ITEM_NAME2 = "explore";
67721
+ function buildItemName(simulatorUdid) {
67722
+ return `${simulatorUdid} - explorer`;
67723
+ }
67709
67724
  function buildSuccessHandler({ input, xqaDirectory, identity, startedAt }) {
67710
67725
  return (output) => {
67711
67726
  emitItemCompleted({ identity, startedAt, findingsCount: output.findings.length });
@@ -67740,7 +67755,7 @@ ${cause}
67740
67755
  };
67741
67756
  }
67742
67757
  function runExplorePipeline(state, contexts) {
67743
- const { input, config: config3, xqaDirectory, onEvent, onSuccess, onError } = state;
67758
+ const { input, config: config3, xqaDirectory, onEvent, onSuccess, onError, simulatorUdid } = state;
67744
67759
  const explorerConfig = buildExplorerConfig2({
67745
67760
  input,
67746
67761
  config: config3,
@@ -67748,14 +67763,22 @@ function runExplorePipeline(state, contexts) {
67748
67763
  initialState: contexts.exploreContext
67749
67764
  });
67750
67765
  void runPipeline2(
67751
- buildPipelineConfig({ input, config: config3, xqaDirectory, explorer: explorerConfig, onEvent })
67766
+ buildPipelineConfig({
67767
+ input,
67768
+ config: config3,
67769
+ xqaDirectory,
67770
+ explorer: explorerConfig,
67771
+ onEvent,
67772
+ simulatorUdid
67773
+ })
67752
67774
  ).match(onSuccess, onError);
67753
67775
  }
67754
67776
  function buildExploreRunState({
67755
67777
  input,
67756
67778
  options,
67757
67779
  identity,
67758
- startedAt
67780
+ startedAt,
67781
+ simulatorUdid
67759
67782
  }) {
67760
67783
  const { config: config3, xqaDirectory } = options;
67761
67784
  const onEvent = (event) => {
@@ -67763,17 +67786,32 @@ function buildExploreRunState({
67763
67786
  };
67764
67787
  const onSuccess = buildSuccessHandler({ input, xqaDirectory, identity, startedAt });
67765
67788
  const onError = buildErrorHandler(identity, startedAt);
67766
- return { input, config: config3, xqaDirectory, onEvent, onSuccess, onError };
67789
+ return { input, config: config3, xqaDirectory, onEvent, onSuccess, onError, simulatorUdid };
67767
67790
  }
67768
- function runPipelineAfterPreflight({ input, options }) {
67791
+ async function resolveSimulatorUdid() {
67792
+ const result = await discoverBootedSimulators();
67793
+ if (result.isErr()) {
67794
+ process.stderr.write(`Failed to discover simulators: ${String(result.error.cause)}
67795
+ `);
67796
+ return;
67797
+ }
67798
+ const first = result.value[0];
67799
+ if (!first) {
67800
+ process.stderr.write("No booted simulators found\n");
67801
+ return;
67802
+ }
67803
+ return first.udid;
67804
+ }
67805
+ function runPipelineAfterPreflight({ input, options }, simulatorUdid) {
67769
67806
  const identity = {
67770
67807
  display: createSoloDisplay(input.verbose),
67771
67808
  itemId: ITEM_ID2,
67772
- itemName: ITEM_NAME2
67809
+ itemName: buildItemName(simulatorUdid),
67810
+ simulatorUdid
67773
67811
  };
67774
67812
  const startedAt = Date.now();
67775
67813
  emitItemStart(identity, startedAt);
67776
- const state = buildExploreRunState({ input, options, identity, startedAt });
67814
+ const state = buildExploreRunState({ input, options, identity, startedAt, simulatorUdid });
67777
67815
  void readAppContext(options.xqaDirectory).andThen(
67778
67816
  (appContext) => readExploreContext(options.xqaDirectory).map((exploreContext) => ({
67779
67817
  appContext,
@@ -67789,7 +67827,12 @@ async function runExploreAfterPreflight(context) {
67789
67827
  process.exit(preflightExit);
67790
67828
  return;
67791
67829
  }
67792
- runPipelineAfterPreflight(context);
67830
+ const simulatorUdid = await resolveSimulatorUdid();
67831
+ if (simulatorUdid === void 0) {
67832
+ process.exit(2);
67833
+ return;
67834
+ }
67835
+ runPipelineAfterPreflight(context, simulatorUdid);
67793
67836
  }
67794
67837
  function runExploreCommand(input, options) {
67795
67838
  void runExploreAfterPreflight({ input, options });
@@ -67889,7 +67932,7 @@ function runInitCommand() {
67889
67932
  // src/commands/review-command.ts
67890
67933
  var import_node_fs7 = require("node:fs");
67891
67934
  var import_node_path14 = __toESM(require("node:path"), 1);
67892
- var import_neverthrow40 = __toESM(require_index_cjs(), 1);
67935
+ var import_neverthrow41 = __toESM(require_index_cjs(), 1);
67893
67936
 
67894
67937
  // ../../node_modules/.pnpm/@inquirer+core@10.3.2_@types+node@22.19.15/node_modules/@inquirer/core/dist/esm/lib/key.js
67895
67938
  var isUpKey = (key, keybindings = []) => (
@@ -70294,7 +70337,7 @@ var esm_default11 = createPrompt((config3, done) => {
70294
70337
  });
70295
70338
 
70296
70339
  // src/review-session.ts
70297
- var import_neverthrow39 = __toESM(require_index_cjs(), 1);
70340
+ var import_neverthrow40 = __toESM(require_index_cjs(), 1);
70298
70341
  var CONFIDENCE_PERCENT = 100;
70299
70342
  var FLOW_COL_WIDTH = 35;
70300
70343
  var TRIGGER_COL_WIDTH = 16;
@@ -70447,15 +70490,15 @@ async function runInteractiveLoop(findings, existing) {
70447
70490
  }
70448
70491
  return { staged: state.staged, undoneKeys: state.undoneKeys };
70449
70492
  }
70450
- var safeRunInteractiveLoop = (0, import_neverthrow39.fromAsyncThrowable)(
70493
+ var safeRunInteractiveLoop = (0, import_neverthrow40.fromAsyncThrowable)(
70451
70494
  runInteractiveLoop,
70452
70495
  (error48) => error48 instanceof Error && error48.name === "ExitPromptError" ? "exit-prompt" : "unexpected"
70453
70496
  );
70454
70497
 
70455
70498
  // src/commands/review-command.ts
70456
- var safeReadFile3 = (0, import_neverthrow40.fromThrowable)((filePath) => (0, import_node_fs7.readFileSync)(filePath, "utf8"));
70457
- var safeParseJson3 = (0, import_neverthrow40.fromThrowable)(JSON.parse);
70458
- var safeWrite = (0, import_neverthrow40.fromThrowable)((filePath, content) => {
70499
+ var safeReadFile3 = (0, import_neverthrow41.fromThrowable)((filePath) => (0, import_node_fs7.readFileSync)(filePath, "utf8"));
70500
+ var safeParseJson3 = (0, import_neverthrow41.fromThrowable)(JSON.parse);
70501
+ var safeWrite = (0, import_neverthrow41.fromThrowable)((filePath, content) => {
70459
70502
  (0, import_node_fs7.writeFileSync)(filePath, content);
70460
70503
  });
70461
70504
  function readLastPath(xqaDirectory) {
@@ -70472,13 +70515,13 @@ function isPipelineOutput(data) {
70472
70515
  function readFindings(filePath) {
70473
70516
  const readResult = safeReadFile3(filePath);
70474
70517
  if (readResult.isErr()) {
70475
- return (0, import_neverthrow40.err)("not-found");
70518
+ return (0, import_neverthrow41.err)("not-found");
70476
70519
  }
70477
70520
  return safeParseJson3(readResult.value).mapErr(() => "invalid").andThen((data) => {
70478
70521
  if (!isPipelineOutput(data)) {
70479
- return (0, import_neverthrow40.err)("invalid");
70522
+ return (0, import_neverthrow41.err)("invalid");
70480
70523
  }
70481
- return (0, import_neverthrow40.ok)(data);
70524
+ return (0, import_neverthrow41.ok)(data);
70482
70525
  });
70483
70526
  }
70484
70527
  function loadExistingDismissals(filePath) {
@@ -70551,7 +70594,7 @@ function resolveAndReadFindings(findingsPath, xqaDirectory) {
70551
70594
  "No findings path provided and no last path found. Run: xqa review <findings-path>\n"
70552
70595
  );
70553
70596
  process.exit(1);
70554
- return (0, import_neverthrow40.err)();
70597
+ return (0, import_neverthrow41.err)();
70555
70598
  }
70556
70599
  const resolvedPath = resolvedPathResult.value;
70557
70600
  const findingsResult = readFindings(resolvedPath);
@@ -70564,9 +70607,9 @@ function resolveAndReadFindings(findingsPath, xqaDirectory) {
70564
70607
  `);
70565
70608
  }
70566
70609
  process.exit(1);
70567
- return (0, import_neverthrow40.err)();
70610
+ return (0, import_neverthrow41.err)();
70568
70611
  }
70569
- return (0, import_neverthrow40.ok)({ resolvedPath, output: findingsResult.value });
70612
+ return (0, import_neverthrow41.ok)({ resolvedPath, output: findingsResult.value });
70570
70613
  }
70571
70614
  async function runReviewLoop({
70572
70615
  findings,
@@ -70640,40 +70683,40 @@ function stripExtensions(filename) {
70640
70683
  // src/commands/spec-resolver.ts
70641
70684
  var import_node_fs8 = require("node:fs");
70642
70685
  var import_node_path16 = __toESM(require("node:path"), 1);
70643
- var import_neverthrow42 = __toESM(require_index_cjs(), 1);
70686
+ var import_neverthrow43 = __toESM(require_index_cjs(), 1);
70644
70687
 
70645
70688
  // src/spec-frontmatter.ts
70646
- var import_neverthrow41 = __toESM(require_index_cjs(), 1);
70689
+ var import_neverthrow42 = __toESM(require_index_cjs(), 1);
70647
70690
  var FRONTMATTER_OPEN_LEN = 4;
70648
70691
  var FRONTMATTER_MARKER_LEN = 3;
70649
70692
  function extractFrontmatterBlock(content) {
70650
70693
  const normalized = content.replaceAll("\r\n", "\n");
70651
70694
  if (!normalized.startsWith("---")) {
70652
- return (0, import_neverthrow41.err)({ type: "MISSING_FRONTMATTER" });
70695
+ return (0, import_neverthrow42.err)({ type: "MISSING_FRONTMATTER" });
70653
70696
  }
70654
70697
  const end = normalized.indexOf("\n---", FRONTMATTER_MARKER_LEN);
70655
70698
  if (end === -1) {
70656
- return (0, import_neverthrow41.err)({ type: "MISSING_FRONTMATTER" });
70699
+ return (0, import_neverthrow42.err)({ type: "MISSING_FRONTMATTER" });
70657
70700
  }
70658
- return (0, import_neverthrow41.ok)(normalized.slice(FRONTMATTER_OPEN_LEN, end));
70701
+ return (0, import_neverthrow42.ok)(normalized.slice(FRONTMATTER_OPEN_LEN, end));
70659
70702
  }
70660
70703
  function parseTimeout(fields) {
70661
70704
  const raw = fields.get("timeout");
70662
70705
  if (raw === void 0) {
70663
- return (0, import_neverthrow41.ok)(raw);
70706
+ return (0, import_neverthrow42.ok)(raw);
70664
70707
  }
70665
70708
  const parsed = Number(raw);
70666
70709
  if (Number.isNaN(parsed) || parsed <= 0) {
70667
- return (0, import_neverthrow41.err)({ type: "PARSE_ERROR", cause: `invalid timeout: ${raw}` });
70710
+ return (0, import_neverthrow42.err)({ type: "PARSE_ERROR", cause: `invalid timeout: ${raw}` });
70668
70711
  }
70669
- return (0, import_neverthrow41.ok)(parsed);
70712
+ return (0, import_neverthrow42.ok)(parsed);
70670
70713
  }
70671
70714
  function parseSpecFrontmatter(content) {
70672
70715
  return extractFrontmatterBlock(content).andThen((block) => {
70673
70716
  const fields = parseYamlFields(block);
70674
70717
  const feature = fields.get("feature");
70675
70718
  if (feature === void 0) {
70676
- return (0, import_neverthrow41.err)({ type: "MISSING_FIELD", field: "feature" });
70719
+ return (0, import_neverthrow42.err)({ type: "MISSING_FIELD", field: "feature" });
70677
70720
  }
70678
70721
  return parseTimeout(fields).map((timeout) => ({ feature, timeout }));
70679
70722
  });
@@ -70695,12 +70738,12 @@ function parseYamlFields(block) {
70695
70738
  }
70696
70739
 
70697
70740
  // src/commands/spec-resolver.ts
70698
- var safeReadFile4 = (0, import_neverthrow42.fromThrowable)((filePath) => (0, import_node_fs8.readFileSync)(filePath, "utf8"));
70699
- var safeReaddir = (0, import_neverthrow42.fromThrowable)(
70741
+ var safeReadFile4 = (0, import_neverthrow43.fromThrowable)((filePath) => (0, import_node_fs8.readFileSync)(filePath, "utf8"));
70742
+ var safeReaddir = (0, import_neverthrow43.fromThrowable)(
70700
70743
  (directory) => (0, import_node_fs8.readdirSync)(directory, { recursive: true, encoding: "utf8" })
70701
70744
  );
70702
70745
  var CANCEL = "xqa:cancel";
70703
- var safeSelect = import_neverthrow42.ResultAsync.fromThrowable(
70746
+ var safeSelect = import_neverthrow43.ResultAsync.fromThrowable(
70704
70747
  esm_default11,
70705
70748
  (error48) => error48 instanceof Error && error48.name === "ExitPromptError" ? "cancelled" : "failed"
70706
70749
  );
@@ -70819,7 +70862,8 @@ async function executeSpec(input, context) {
70819
70862
  const identity = {
70820
70863
  display: createSoloDisplay(input.verbose),
70821
70864
  itemId: "spec",
70822
- itemName: import_node_path17.default.basename(context.absolutePath, ".test.md")
70865
+ itemName: import_node_path17.default.basename(context.absolutePath, ".test.md"),
70866
+ simulatorUdid: ""
70823
70867
  };
70824
70868
  const startedAt = Date.now();
70825
70869
  emitItemStart(identity, startedAt);
@@ -70887,7 +70931,7 @@ function runUpdateCommand() {
70887
70931
  var import_node_path18 = __toESM(require("node:path"), 1);
70888
70932
  var import_node_url2 = require("node:url");
70889
70933
  var import_dotenv = __toESM(require_main(), 1);
70890
- var import_neverthrow43 = __toESM(require_index_cjs(), 1);
70934
+ var import_neverthrow44 = __toESM(require_index_cjs(), 1);
70891
70935
 
70892
70936
  // ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/external.js
70893
70937
  var external_exports2 = {};
@@ -74948,10 +74992,10 @@ function loadConfig() {
74948
74992
  const messages = result.error.issues.map(
74949
74993
  (issue2) => ` - ${issue2.path.join(".")}: ${issue2.message}`
74950
74994
  );
74951
- return (0, import_neverthrow43.err)({ type: "INVALID_CONFIG", message: `Configuration error:
74995
+ return (0, import_neverthrow44.err)({ type: "INVALID_CONFIG", message: `Configuration error:
74952
74996
  ${messages.join("\n")}` });
74953
74997
  }
74954
- return (0, import_neverthrow43.ok)(result.data);
74998
+ return (0, import_neverthrow44.ok)(result.data);
74955
74999
  }
74956
75000
 
74957
75001
  // src/core/parse-timeout-seconds.ts
@@ -74984,7 +75028,7 @@ function parseVerboseOption(value) {
74984
75028
 
74985
75029
  // src/pid-lock.ts
74986
75030
  var import_node_fs9 = require("node:fs");
74987
- var import_neverthrow44 = __toESM(require_index_cjs(), 1);
75031
+ var import_neverthrow45 = __toESM(require_index_cjs(), 1);
74988
75032
  var PID_FILE = "/tmp/xqa.pid";
74989
75033
  var SIGINT_EXIT_CODE = 130;
74990
75034
  var SIGTERM_EXIT_CODE = 143;
@@ -74993,7 +75037,7 @@ var HARD_TIMEOUT_MS = 1e4;
74993
75037
  var cleanup = () => {
74994
75038
  (0, import_node_fs9.rmSync)(PID_FILE, { force: true });
74995
75039
  };
74996
- var checkProcessRunning = (0, import_neverthrow44.fromThrowable)(
75040
+ var checkProcessRunning = (0, import_neverthrow45.fromThrowable)(
74997
75041
  (pid) => {
74998
75042
  process.kill(pid, 0);
74999
75043
  return true;
@@ -75059,17 +75103,17 @@ function acquireLock() {
75059
75103
  // src/shell/xqa-directory.ts
75060
75104
  var import_node_fs10 = require("node:fs");
75061
75105
  var import_node_path19 = __toESM(require("node:path"), 1);
75062
- var import_neverthrow45 = __toESM(require_index_cjs(), 1);
75106
+ var import_neverthrow46 = __toESM(require_index_cjs(), 1);
75063
75107
  function findXqaDirectory(startDirectory) {
75064
75108
  let current = startDirectory;
75065
75109
  for (; ; ) {
75066
75110
  const candidate = import_node_path19.default.join(current, ".xqa");
75067
75111
  if ((0, import_node_fs10.existsSync)(candidate)) {
75068
- return (0, import_neverthrow45.ok)(candidate);
75112
+ return (0, import_neverthrow46.ok)(candidate);
75069
75113
  }
75070
75114
  const parent = import_node_path19.default.dirname(current);
75071
75115
  if (parent === current) {
75072
- return (0, import_neverthrow45.err)({ type: "XQA_NOT_INITIALIZED" });
75116
+ return (0, import_neverthrow46.err)({ type: "XQA_NOT_INITIALIZED" });
75073
75117
  }
75074
75118
  current = parent;
75075
75119
  }
@@ -75079,7 +75123,7 @@ function findXqaDirectory(startDirectory) {
75079
75123
  var import_promises19 = __toESM(require("node:fs/promises"), 1);
75080
75124
  var import_node_path22 = __toESM(require("node:path"), 1);
75081
75125
  var import_fast_glob = __toESM(require_out4(), 1);
75082
- var import_neverthrow50 = __toESM(require_index_cjs(), 1);
75126
+ var import_neverthrow51 = __toESM(require_index_cjs(), 1);
75083
75127
 
75084
75128
  // src/suite/core/run-id.ts
75085
75129
  var RUN_ID_PAD_LENGTH2 = 4;
@@ -75102,8 +75146,8 @@ function computeNextRunId(existingDirectories) {
75102
75146
  }
75103
75147
 
75104
75148
  // src/suite/core/suite-config-parser.ts
75105
- var import_neverthrow46 = __toESM(require_index_cjs(), 1);
75106
75149
  var import_neverthrow47 = __toESM(require_index_cjs(), 1);
75150
+ var import_neverthrow48 = __toESM(require_index_cjs(), 1);
75107
75151
  var freestyleEntrySchema = external_exports2.object({
75108
75152
  prompt: external_exports2.string().optional(),
75109
75153
  timeoutSeconds: external_exports2.number().int().positive()
@@ -75122,7 +75166,7 @@ var suiteConfigSchema = external_exports2.object({
75122
75166
  specs: external_exports2.array(external_exports2.string()).nonempty(),
75123
75167
  freestyle: freestyleSchema
75124
75168
  });
75125
- var safeJsonParse4 = (0, import_neverthrow46.fromThrowable)(
75169
+ var safeJsonParse4 = (0, import_neverthrow47.fromThrowable)(
75126
75170
  JSON.parse,
75127
75171
  (cause) => ({
75128
75172
  type: "INVALID_SUITE_CONFIG",
@@ -75133,9 +75177,9 @@ function parseSuiteConfig(raw) {
75133
75177
  return safeJsonParse4(raw).andThen((data) => {
75134
75178
  const parsed = suiteConfigSchema.safeParse(data);
75135
75179
  if (!parsed.success) {
75136
- return (0, import_neverthrow47.err)({ type: "INVALID_SUITE_CONFIG", cause: parsed.error });
75180
+ return (0, import_neverthrow48.err)({ type: "INVALID_SUITE_CONFIG", cause: parsed.error });
75137
75181
  }
75138
- return (0, import_neverthrow47.ok)({ specs: parsed.data.specs, freestyle: parsed.data.freestyle });
75182
+ return (0, import_neverthrow48.ok)({ specs: parsed.data.specs, freestyle: parsed.data.freestyle });
75139
75183
  });
75140
75184
  }
75141
75185
 
@@ -75201,7 +75245,7 @@ function buildFreestyleItems(entries) {
75201
75245
  // src/suite/shell/suite-findings-writer.ts
75202
75246
  var import_promises18 = __toESM(require("node:fs/promises"), 1);
75203
75247
  var import_node_path20 = __toESM(require("node:path"), 1);
75204
- var import_neverthrow48 = __toESM(require_index_cjs(), 1);
75248
+ var import_neverthrow49 = __toESM(require_index_cjs(), 1);
75205
75249
  var INDENT_SPACES = 2;
75206
75250
  function writeSuiteFindings(findings, options) {
75207
75251
  const directory = import_node_path20.default.join(
@@ -75213,7 +75257,7 @@ function writeSuiteFindings(findings, options) {
75213
75257
  );
75214
75258
  const finalPath = import_node_path20.default.join(directory, "findings.json");
75215
75259
  const temporaryPath = `${finalPath}.tmp`;
75216
- const safeWriteAtomically = import_neverthrow48.ResultAsync.fromThrowable(
75260
+ const safeWriteAtomically = import_neverthrow49.ResultAsync.fromThrowable(
75217
75261
  async () => {
75218
75262
  await import_promises18.default.mkdir(directory, { recursive: true });
75219
75263
  await import_promises18.default.writeFile(temporaryPath, JSON.stringify(findings, void 0, INDENT_SPACES));
@@ -75226,7 +75270,7 @@ function writeSuiteFindings(findings, options) {
75226
75270
  }
75227
75271
 
75228
75272
  // src/suite/shell/worker-pool.ts
75229
- var import_neverthrow49 = __toESM(require_index_cjs(), 1);
75273
+ var import_neverthrow50 = __toESM(require_index_cjs(), 1);
75230
75274
 
75231
75275
  // src/suite/shell/item-result-builder.ts
75232
75276
  function getErrorMessage(cause) {
@@ -75454,7 +75498,7 @@ function runWorkerPool(config3) {
75454
75498
  const queue = setupQueue(config3);
75455
75499
  const results = [];
75456
75500
  const suiteStartMs = Date.now();
75457
- const safeRun = import_neverthrow49.ResultAsync.fromThrowable(
75501
+ const safeRun = import_neverthrow50.ResultAsync.fromThrowable(
75458
75502
  async () => runAllWorkers({ config: config3, queue, results, suiteStartMs }),
75459
75503
  (cause) => ({ type: "WORKER_POOL_FAILED", cause })
75460
75504
  );
@@ -75541,14 +75585,14 @@ function makeExecuteItem(context) {
75541
75585
 
75542
75586
  // src/suite/commands/run-command.ts
75543
75587
  var ISO_DATE_LENGTH3 = 10;
75544
- var safeReaddir2 = import_neverthrow50.ResultAsync.fromThrowable(
75588
+ var safeReaddir2 = import_neverthrow51.ResultAsync.fromThrowable(
75545
75589
  async (directoryPath) => {
75546
75590
  const entries = await import_promises19.default.readdir(directoryPath, { withFileTypes: true });
75547
75591
  return entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name);
75548
75592
  },
75549
75593
  () => "READDIR_FAILED"
75550
75594
  );
75551
- var safeReadFile5 = import_neverthrow50.ResultAsync.fromThrowable(
75595
+ var safeReadFile5 = import_neverthrow51.ResultAsync.fromThrowable(
75552
75596
  async (filePath) => import_promises19.default.readFile(filePath, "utf8"),
75553
75597
  () => "READ_FAILED"
75554
75598
  );
@@ -75730,7 +75774,7 @@ function resolveXqaDirectory() {
75730
75774
  return result.value;
75731
75775
  }
75732
75776
  var program2 = new Command();
75733
- program2.name("xqa").description("AI-powered QA agent CLI").version(`${"1.6.1"}${false ? ` (dev build +${"6b23ee9"})` : ""}`);
75777
+ program2.name("xqa").description("AI-powered QA agent CLI").version(`${"1.8.0"}${false ? ` (dev build +${"d16dbac"})` : ""}`);
75734
75778
  program2.command("init").description("Initialize a new xqa project in the current directory").action(() => {
75735
75779
  runInitCommand();
75736
75780
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exodus/xqa",
3
- "version": "1.6.1",
3
+ "version": "1.8.0",
4
4
  "type": "module",
5
5
  "engines": {
6
6
  "node": ">=22"
@@ -27,11 +27,11 @@
27
27
  "vitest": "^3.2.1",
28
28
  "zod": "^3.0.0",
29
29
  "@qa-agents/display": "0.0.0",
30
+ "@qa-agents/eslint-config": "0.0.0",
30
31
  "@qa-agents/explorer": "0.0.0",
31
32
  "@qa-agents/mobile-ios": "0.0.0",
32
33
  "@qa-agents/pipeline": "0.0.0",
33
34
  "@qa-agents/shared": "0.0.0",
34
- "@qa-agents/eslint-config": "0.0.0",
35
35
  "@qa-agents/typescript-config": "0.0.0"
36
36
  },
37
37
  "dependencies": {