@exodus/xqa 5.0.0 → 5.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/xqa.cjs CHANGED
@@ -31967,6 +31967,8 @@ agents:
31967
31967
  viewUiServer: true
31968
31968
  # Save per-finding screenshots to the run output directory.
31969
31969
  findingScreenshots: true
31970
+ # Allow the agent to read the simulator pasteboard via the read_pasteboard tool. Off by default \u2014 pasteboard contents (including any secrets copied during the run) are sent to the model provider verbatim.
31971
+ readPasteboard: false
31970
31972
 
31971
31973
  analyser:
31972
31974
  # Requires GOOGLE_GENERATIVE_AI_API_KEY in environment.
@@ -46039,7 +46041,7 @@ var {
46039
46041
  } = import_index.default;
46040
46042
 
46041
46043
  // src/bootstrap.ts
46042
- var import_neverthrow96 = __toESM(require_index_cjs(), 1);
46044
+ var import_neverthrow97 = __toESM(require_index_cjs(), 1);
46043
46045
 
46044
46046
  // src/config/error-formatter.ts
46045
46047
  function formatIssues(issues) {
@@ -63957,6 +63959,41 @@ function createPressButtonTool(udid = "booted") {
63957
63959
  async ({ button }) => handlePressButton(udid, button)
63958
63960
  );
63959
63961
  }
63962
+ var READ_PASTEBOARD_TOOL_NAME = "mcp__mobile-ios__read_pasteboard";
63963
+ var MAX_PASTEBOARD_LENGTH = 4096;
63964
+ var READ_PASTEBOARD_SCHEMA = {};
63965
+ var READ_PASTEBOARD_DESCRIPTION = [
63966
+ "Read current simulator pasteboard (clipboard) as text.",
63967
+ 'Use ONLY to verify a copy-to-clipboard action the user just performed (e.g. confirm a "Copy address" button wrote the expected value).',
63968
+ 'DO NOT call on screens showing secrets, seed phrases, recovery words, private keys, passwords, or 2FA codes, or after any "reveal/backup/export" flow \u2014 pasteboard contents are sent to the model provider verbatim.',
63969
+ `Output is truncated to ${String(MAX_PASTEBOARD_LENGTH)} characters; trailing newlines are stripped; returns empty string when the pasteboard is empty.`
63970
+ ].join(" ");
63971
+ function truncatePasteboard(raw) {
63972
+ const trimmed = raw.replace(/\r?\n+$/, "");
63973
+ if (trimmed.length <= MAX_PASTEBOARD_LENGTH) {
63974
+ return trimmed;
63975
+ }
63976
+ const overflow = trimmed.length - MAX_PASTEBOARD_LENGTH;
63977
+ return `${trimmed.slice(0, MAX_PASTEBOARD_LENGTH)}
63978
+ [truncated: ${String(overflow)} more chars]`;
63979
+ }
63980
+ async function handleReadPasteboard(udid) {
63981
+ return resolveUdid(udid).andThen((resolvedUdid) => runCommand("xcrun", ["simctl", "pbpaste", resolvedUdid])).match(
63982
+ (value) => ({ content: [{ type: "text", text: truncatePasteboard(value) }] }),
63983
+ (error48) => ({
63984
+ content: [{ type: "text", text: `Error: ${String(error48.cause)}` }],
63985
+ isError: true
63986
+ })
63987
+ );
63988
+ }
63989
+ function createReadPasteboardTool(udid = "booted") {
63990
+ return _x(
63991
+ "read_pasteboard",
63992
+ READ_PASTEBOARD_DESCRIPTION,
63993
+ READ_PASTEBOARD_SCHEMA,
63994
+ async () => handleReadPasteboard(udid)
63995
+ );
63996
+ }
63960
63997
  var cache2 = /* @__PURE__ */ new Map();
63961
63998
  function parseDeviceInfo(raw) {
63962
63999
  const parsed = JSON.parse(raw);
@@ -64196,25 +64233,29 @@ function discoverBootedSimulators() {
64196
64233
  function checkIdbAvailable() {
64197
64234
  return runCommand("which", ["idb"]).mapErr(() => ({ type: "IDB_NOT_FOUND" }));
64198
64235
  }
64199
- function createMobileIosServer(udid = "booted", extraTools = []) {
64236
+ function buildBaseTools(udid) {
64237
+ return [
64238
+ createScreenshotTool(udid),
64239
+ createAccessibilitySnapshotTool(udid),
64240
+ createTapTool(udid),
64241
+ createDoubleTapTool(udid),
64242
+ createLongPressTool(udid),
64243
+ createSwipeTool(udid),
64244
+ createTypeTextTool(udid),
64245
+ createPressButtonTool(udid),
64246
+ createLaunchAppTool(udid),
64247
+ createTerminateAppTool(udid),
64248
+ createListAppsTool(udid),
64249
+ createWaitSecondsTool()
64250
+ ];
64251
+ }
64252
+ function createMobileIosServer(udid = "booted", options2 = {}) {
64253
+ const { extraTools = [], enableReadPasteboard = false } = options2;
64254
+ const pasteboardTools = enableReadPasteboard ? [createReadPasteboardTool(udid)] : [];
64200
64255
  return xx({
64201
64256
  name: "mobile-ios",
64202
64257
  version: "0.0.0",
64203
- tools: [
64204
- createScreenshotTool(udid),
64205
- createAccessibilitySnapshotTool(udid),
64206
- createTapTool(udid),
64207
- createDoubleTapTool(udid),
64208
- createLongPressTool(udid),
64209
- createSwipeTool(udid),
64210
- createTypeTextTool(udid),
64211
- createPressButtonTool(udid),
64212
- createLaunchAppTool(udid),
64213
- createTerminateAppTool(udid),
64214
- createListAppsTool(udid),
64215
- createWaitSecondsTool(),
64216
- ...extraTools
64217
- ]
64258
+ tools: [...buildBaseTools(udid), ...pasteboardTools, ...extraTools]
64218
64259
  });
64219
64260
  }
64220
64261
 
@@ -74414,8 +74455,12 @@ function buildReportFindingTool(config2, state) {
74414
74455
  }
74415
74456
  function buildMobileIosServer(config2, state) {
74416
74457
  const reportFindingTool = buildReportFindingTool(config2, state);
74458
+ const enableReadPasteboard = config2.capabilities.readPasteboard;
74417
74459
  if (!config2.capabilities.viewUiServer) {
74418
- return createMobileIosServer(config2.udid ?? "booted", [reportFindingTool]);
74460
+ return createMobileIosServer(config2.udid ?? "booted", {
74461
+ extraTools: [reportFindingTool],
74462
+ enableReadPasteboard
74463
+ });
74419
74464
  }
74420
74465
  const viewUiTool = createViewUiTool({
74421
74466
  udid: config2.udid,
@@ -74424,15 +74469,23 @@ function buildMobileIosServer(config2, state) {
74424
74469
  onEvent: config2.onEvent,
74425
74470
  screenshotsDir: config2.screenshotsDir
74426
74471
  });
74427
- return createMobileIosServer(config2.udid ?? "booted", [viewUiTool, reportFindingTool]);
74472
+ return createMobileIosServer(config2.udid ?? "booted", {
74473
+ extraTools: [viewUiTool, reportFindingTool],
74474
+ enableReadPasteboard
74475
+ });
74428
74476
  }
74429
- function setupQuery(config2) {
74430
- const baseAllowedTools = [
74477
+ function buildAllowedTools(config2) {
74478
+ const tools = [
74431
74479
  ...config2.allowedTools ?? [],
74432
74480
  REPORT_FINDING_TOOL_NAME,
74433
- WAIT_SECONDS_TOOL_NAME
74481
+ WAIT_SECONDS_TOOL_NAME,
74482
+ config2.capabilities.viewUiServer ? VIEW_UI_TOOL_NAME : void 0,
74483
+ config2.capabilities.readPasteboard ? READ_PASTEBOARD_TOOL_NAME : void 0
74434
74484
  ];
74435
- const allowedTools = (config2.capabilities.viewUiServer ? [...baseAllowedTools, VIEW_UI_TOOL_NAME] : baseAllowedTools).filter((tool3) => typeof tool3 === "string");
74485
+ return tools.filter((tool3) => typeof tool3 === "string");
74486
+ }
74487
+ function setupQuery(config2) {
74488
+ const allowedTools = buildAllowedTools(config2);
74436
74489
  const inputQueue = new MessageQueue();
74437
74490
  const state = buildAgentState({ config: config2, inputQueue });
74438
74491
  const mobileIosServer = buildMobileIosServer(config2, state);
@@ -74717,8 +74770,8 @@ ${initialState2}` : void 0,
74717
74770
  WORKING_STATE_SECTION
74718
74771
  ].filter((section) => section !== void 0).join("\n\n");
74719
74772
  }
74720
- function buildEnvSection(buildEnv2) {
74721
- return buildEnv2 === "dev" ? `
74773
+ function buildEnvSection(buildEnv3) {
74774
+ return buildEnv3 === "dev" ? `
74722
74775
 
74723
74776
  ${DEV_ENVIRONMENT_SECTION}` : "";
74724
74777
  }
@@ -74785,9 +74838,9 @@ ${FINDING_TAXONOMY_SECTION}${environmentSection}
74785
74838
  ${reportingSection}`;
74786
74839
  }
74787
74840
  var FREESTYLE_TEMPLATE = (options2) => {
74788
- const { appContext, initialState: initialState2, buildEnv: buildEnv2, scenarioId } = options2 ?? {};
74841
+ const { appContext, initialState: initialState2, buildEnv: buildEnv3, scenarioId } = options2 ?? {};
74789
74842
  const contextBlock = buildContextSections(appContext, initialState2);
74790
- const environmentSection = buildEnvSection(buildEnv2);
74843
+ const environmentSection = buildEnvSection(buildEnv3);
74791
74844
  const reportingSection = buildReportFindingSection(scenarioId);
74792
74845
  return buildFreestyleBody({ contextBlock, environmentSection, reportingSection });
74793
74846
  };
@@ -74928,10 +74981,10 @@ function generateExplorerPrompt({
74928
74981
  specs,
74929
74982
  appContext,
74930
74983
  initialState: initialState2,
74931
- buildEnv: buildEnv2,
74984
+ buildEnv: buildEnv3,
74932
74985
  scenarioId
74933
74986
  }) {
74934
- return mode === "spec" ? buildSpecModePrompt(specs, { appContext, initialState: initialState2, buildEnv: buildEnv2, scenarioId }) : FREESTYLE_TEMPLATE({ appContext, initialState: initialState2, buildEnv: buildEnv2, scenarioId });
74987
+ return mode === "spec" ? buildSpecModePrompt(specs, { appContext, initialState: initialState2, buildEnv: buildEnv3, scenarioId }) : FREESTYLE_TEMPLATE({ appContext, initialState: initialState2, buildEnv: buildEnv3, scenarioId });
74935
74988
  }
74936
74989
  var FRONTMATTER_FENCE = "---";
74937
74990
  var INLINE_ASSERTION_DELIMITER = " \u2192 ";
@@ -75253,7 +75306,8 @@ function runExplorer(config2) {
75253
75306
  var explorerCapabilitiesSchema = external_exports.object({
75254
75307
  videoRecording: external_exports.boolean().default(false),
75255
75308
  viewUiServer: external_exports.boolean().default(true),
75256
- findingScreenshots: external_exports.boolean().default(true)
75309
+ findingScreenshots: external_exports.boolean().default(true),
75310
+ readPasteboard: external_exports.boolean().default(false)
75257
75311
  }).strict();
75258
75312
  var DEFAULT_EXPLORER_CAPABILITIES = explorerCapabilitiesSchema.parse({});
75259
75313
  var explorerConfigSchema = agentBaseConfigSchema.extend({
@@ -80303,16 +80357,19 @@ var import_node_child_process6 = require("node:child_process");
80303
80357
  var import_node_util = require("node:util");
80304
80358
  var import_neverthrow64 = __toESM(require_index_cjs(), 1);
80305
80359
  var import_node_process2 = require("node:process");
80360
+ var import_node_child_process7 = require("node:child_process");
80361
+ var import_node_util2 = require("node:util");
80306
80362
  var import_neverthrow65 = __toESM(require_index_cjs(), 1);
80307
80363
  var import_neverthrow66 = __toESM(require_index_cjs(), 1);
80364
+ var import_neverthrow67 = __toESM(require_index_cjs(), 1);
80308
80365
  var import_promises24 = require("node:fs/promises");
80309
80366
  var import_node_path20 = __toESM(require("node:path"), 1);
80310
- var import_neverthrow67 = __toESM(require_index_cjs(), 1);
80367
+ var import_neverthrow68 = __toESM(require_index_cjs(), 1);
80311
80368
  var import_promises25 = require("node:fs/promises");
80312
80369
  var import_node_path21 = __toESM(require("node:path"), 1);
80313
- var import_neverthrow68 = __toESM(require_index_cjs(), 1);
80314
- var import_promises26 = require("node:fs/promises");
80315
80370
  var import_neverthrow69 = __toESM(require_index_cjs(), 1);
80371
+ var import_promises26 = require("node:fs/promises");
80372
+ var import_neverthrow70 = __toESM(require_index_cjs(), 1);
80316
80373
  function isEmptySummary(summary) {
80317
80374
  return summary.touchedFiles.length === 0 && summary.uncommittedFiles.length === 0;
80318
80375
  }
@@ -80590,6 +80647,25 @@ function classifyActionability(summary, rawDiff) {
80590
80647
  }
80591
80648
  return { kind: "actionable" };
80592
80649
  }
80650
+ function summarizeChangeSummary(summary) {
80651
+ const hints = summary.hints.length > 0 ? summary.hints.join(",") : "none";
80652
+ return [
80653
+ `files=${String(summary.touchedFiles.length)}`,
80654
+ `uncommitted=${String(summary.uncommittedFiles.length)}`,
80655
+ `+${String(summary.addedLines)}/-${String(summary.deletedLines)}`,
80656
+ `hints=${hints}`
80657
+ ].join(" ");
80658
+ }
80659
+ function emitClassificationDebug(input) {
80660
+ if (input.emitDebug === void 0) {
80661
+ return;
80662
+ }
80663
+ if (input.kind === "empty") {
80664
+ input.emitDebug(`[plan] classification=empty reason=${input.reason ?? "unknown"}`);
80665
+ return;
80666
+ }
80667
+ input.emitDebug("[plan] classification=actionable");
80668
+ }
80593
80669
  var PORCELAIN_PATH_OFFSET = 3;
80594
80670
  var PORCELAIN_RENAME_SEPARATOR = " -> ";
80595
80671
  function extractPorcelainPath(line) {
@@ -80610,7 +80686,10 @@ function branchReferenceToString(reference) {
80610
80686
  return reference.sha;
80611
80687
  }
80612
80688
  function resolveBaseReference(context) {
80613
- return context.deps.gitSymbolicReferenceOriginHead(context.input.gitContext);
80689
+ if (context.input.baseOverride !== void 0) {
80690
+ return (0, import_neverthrow56.okAsync)(context.input.baseOverride);
80691
+ }
80692
+ return context.deps.resolveBaseBranch(context.input.gitContext);
80614
80693
  }
80615
80694
  function assertNonEmptyDiff(state) {
80616
80695
  if (isEmptySummary(state.summary)) {
@@ -80620,15 +80699,16 @@ function assertNonEmptyDiff(state) {
80620
80699
  }
80621
80700
  function emitDrafts(input) {
80622
80701
  const { context, summary } = input;
80623
- return recoverPlanMissing(context.deps.readPlan({ directory: context.input.outputDirectory })).map((entries) => toSpecSummaries(entries)).andThen(
80624
- (existingSpecs) => context.deps.emitScenarios({
80702
+ return recoverPlanMissing(context.deps.readPlan({ directory: context.input.outputDirectory })).map((entries) => toSpecSummaries(entries)).andThen((existingSpecs) => {
80703
+ context.deps.emitDebug?.(`[plan] existing-specs count=${String(existingSpecs.length)}`);
80704
+ return context.deps.emitScenarios({
80625
80705
  summary,
80626
80706
  intent: context.input.intent,
80627
80707
  appContext: context.input.appContext,
80628
80708
  existingSpecs,
80629
80709
  aiConfig: context.input.aiConfig
80630
- })
80631
- );
80710
+ });
80711
+ });
80632
80712
  }
80633
80713
  function persistScenarios(input) {
80634
80714
  return input.context.deps.writeScenarios({
@@ -80645,6 +80725,7 @@ function persistScenarios(input) {
80645
80725
  function runEmitAndPersist(input) {
80646
80726
  const { state, context } = input;
80647
80727
  return emitDrafts({ summary: state.summary, context }).andThen((drafts) => {
80728
+ context.deps.emitDebug?.(`[plan] drafts count=${String(drafts.length)}`);
80648
80729
  if (drafts.length === 0) {
80649
80730
  return (0, import_neverthrow56.okAsync)({
80650
80731
  specs: [],
@@ -80658,9 +80739,12 @@ function runEmitAndPersist(input) {
80658
80739
  }
80659
80740
  function dispatchClassification(input) {
80660
80741
  const classification = classifyActionability(input.state.summary, input.state.rawDiff);
80742
+ const emitDebug = input.context.deps.emitDebug;
80661
80743
  if (classification.kind === "empty") {
80744
+ emitClassificationDebug({ emitDebug, kind: "empty", reason: classification.reason });
80662
80745
  return (0, import_neverthrow56.okAsync)({ specs: [], emptyReason: classification.reason });
80663
80746
  }
80747
+ emitClassificationDebug({ emitDebug, kind: "actionable" });
80664
80748
  return runEmitAndPersist(input);
80665
80749
  }
80666
80750
  function combineReferences(context) {
@@ -80668,7 +80752,10 @@ function combineReferences(context) {
80668
80752
  (baseReference) => resolveHead({
80669
80753
  gitContext: context.input.gitContext,
80670
80754
  gitBranchReference: context.deps.gitBranchReference
80671
- }).map((head) => ({ baseRef: baseReference, head }))
80755
+ }).map((head) => {
80756
+ context.deps.emitDebug?.(`[plan] base=${baseReference} head=${head}`);
80757
+ return { baseRef: baseReference, head };
80758
+ })
80672
80759
  );
80673
80760
  }
80674
80761
  function buildSummaryState(context, references) {
@@ -80677,11 +80764,16 @@ function buildSummaryState(context, references) {
80677
80764
  gitContext: context.input.gitContext,
80678
80765
  gitDiff: context.deps.gitDiff,
80679
80766
  gitStatusPorcelain: context.deps.gitStatusPorcelain
80680
- }).map((collected) => ({
80681
- ...references,
80682
- rawDiff: collected.rawDiff,
80683
- summary: collected.summary
80684
- }));
80767
+ }).map((collected) => {
80768
+ context.deps.emitDebug?.(
80769
+ `[plan] diff-bytes=${String(collected.rawDiff.length)} ${summarizeChangeSummary(collected.summary)}`
80770
+ );
80771
+ return {
80772
+ ...references,
80773
+ rawDiff: collected.rawDiff,
80774
+ summary: collected.summary
80775
+ };
80776
+ });
80685
80777
  }
80686
80778
  function resolveHead(input) {
80687
80779
  return input.gitBranchReference(input.gitContext).map((reference) => branchReferenceToString(reference));
@@ -81498,6 +81590,48 @@ function gitStatusPorcelain(context) {
81498
81590
  function gitSymbolicReferenceOriginHead(context) {
81499
81591
  return execGit(["symbolic-ref", "--short", "refs/remotes/origin/HEAD"], context).map((result) => stripOriginPrefix(result.stdout)).mapErr(() => ({ type: "GIT_NO_BASE_BRANCH" }));
81500
81592
  }
81593
+ var NON_INTERACTIVE_ENV = {
81594
+ PAGER: "",
81595
+ GH_PAGER: "",
81596
+ GH_FORCE_TTY: "",
81597
+ GH_PROMPT_DISABLED: "1"
81598
+ };
81599
+ var execFileAsync2 = (0, import_node_util2.promisify)(
81600
+ import_node_child_process7.execFile
81601
+ );
81602
+ function buildEnv2(context) {
81603
+ return {
81604
+ ...readProcessEnv(),
81605
+ ...NON_INTERACTIVE_ENV,
81606
+ ...context.env
81607
+ };
81608
+ }
81609
+ async function runGh(input) {
81610
+ const { stdout, stderr } = await execFileAsync2("gh", [...input.commandArguments], {
81611
+ cwd: input.context.cwd,
81612
+ env: buildEnv2(input.context)
81613
+ });
81614
+ return { stdout, stderr };
81615
+ }
81616
+ var safeRunGh = (0, import_neverthrow65.fromAsyncThrowable)(
81617
+ runGh,
81618
+ (cause) => ({ type: "GH_PR_LOOKUP_FAILED", cause })
81619
+ );
81620
+ function ghDetectPrBaseBranch(context) {
81621
+ return safeRunGh({
81622
+ commandArguments: ["pr", "view", "--json", "baseRefName", "-q", ".baseRefName"],
81623
+ context
81624
+ }).andThen((result) => {
81625
+ const value = result.stdout.trim();
81626
+ if (value.length === 0) {
81627
+ return (0, import_neverthrow65.errAsync)({ type: "GH_PR_LOOKUP_FAILED", cause: "empty-output" });
81628
+ }
81629
+ return (0, import_neverthrow65.okAsync)(value);
81630
+ });
81631
+ }
81632
+ function resolveBaseBranch(gitContext, deps) {
81633
+ return deps.ghDetectPrBaseBranch(gitContext).orElse(() => deps.gitSymbolicReferenceOriginHead(gitContext));
81634
+ }
81501
81635
  var MAX_EXISTING_SPECS = 30;
81502
81636
  function renderList(items, emptyLabel) {
81503
81637
  if (items.length === 0) {
@@ -81615,20 +81749,20 @@ var scenarioDraftSchema = external_exports.object({
81615
81749
  coverageNote: external_exports.string().optional()
81616
81750
  });
81617
81751
  var payloadSchema = external_exports.object({ scenarios: external_exports.array(scenarioDraftSchema) });
81618
- var safeParseJson3 = (0, import_neverthrow65.fromThrowable)(
81752
+ var safeParseJson3 = (0, import_neverthrow66.fromThrowable)(
81619
81753
  (raw) => JSON.parse(raw),
81620
81754
  () => ({ type: "AI_RESPONSE_JSON_PARSE" })
81621
81755
  );
81622
81756
  function validatePayload(raw) {
81623
81757
  const parsed = safeParseJson3(raw);
81624
81758
  if (parsed.isErr()) {
81625
- return (0, import_neverthrow65.err)({ type: "AI_RESPONSE_INVALID", operation: "scenario-emit", raw });
81759
+ return (0, import_neverthrow66.err)({ type: "AI_RESPONSE_INVALID", operation: "scenario-emit", raw });
81626
81760
  }
81627
81761
  const validated = payloadSchema.safeParse(parsed.value);
81628
81762
  if (!validated.success) {
81629
- return (0, import_neverthrow65.err)({ type: "AI_RESPONSE_INVALID", operation: "scenario-emit", raw });
81763
+ return (0, import_neverthrow66.err)({ type: "AI_RESPONSE_INVALID", operation: "scenario-emit", raw });
81630
81764
  }
81631
- return (0, import_neverthrow65.ok)(validated.data.scenarios);
81765
+ return (0, import_neverthrow66.ok)(validated.data.scenarios);
81632
81766
  }
81633
81767
  function emitScenarios(input, deps) {
81634
81768
  const prompt = buildScenarioEmitterPrompt({
@@ -81637,7 +81771,13 @@ function emitScenarios(input, deps) {
81637
81771
  appContext: input.appContext,
81638
81772
  existingSpecs: input.existingSpecs
81639
81773
  });
81640
- return deps.callAi({ prompt, config: input.aiConfig }).andThen((raw) => validatePayload(raw));
81774
+ deps.emitDebug?.(`[plan] prompt chars=${String(prompt.length)}
81775
+ ${prompt}`);
81776
+ return deps.callAi({ prompt, config: input.aiConfig }).andThen((raw) => {
81777
+ deps.emitDebug?.(`[plan] ai-response chars=${String(raw.length)}
81778
+ ${raw}`);
81779
+ return validatePayload(raw);
81780
+ });
81641
81781
  }
81642
81782
  function renderExistingSpecSection(existingSpec) {
81643
81783
  const feature = existingSpec.feature;
@@ -81704,14 +81844,14 @@ function validateCandidate(validateInput) {
81704
81844
  const { raw, existingSpec, specPath } = validateInput;
81705
81845
  const parsed = parseSpec(raw, specPath);
81706
81846
  if (parsed.isErr()) {
81707
- return (0, import_neverthrow66.err)({ type: "AI_RESPONSE_INVALID", operation: "edit-apply", raw });
81847
+ return (0, import_neverthrow67.err)({ type: "AI_RESPONSE_INVALID", operation: "edit-apply", raw });
81708
81848
  }
81709
81849
  const candidate = parsed.value;
81710
81850
  const violated = findMissingOrChangedKey(candidate, existingSpec);
81711
81851
  if (violated !== void 0) {
81712
- return (0, import_neverthrow66.err)({ type: "SCENARIO_ID_LOST_IN_EDIT", path: specPath });
81852
+ return (0, import_neverthrow67.err)({ type: "SCENARIO_ID_LOST_IN_EDIT", path: specPath });
81713
81853
  }
81714
- return (0, import_neverthrow66.ok)(candidate);
81854
+ return (0, import_neverthrow67.ok)(candidate);
81715
81855
  }
81716
81856
  function applyEdit(input, deps) {
81717
81857
  const prompt = buildEditApplierPrompt(input.existingSpec, input.userFeedback);
@@ -81729,14 +81869,14 @@ function mapReaddirError(input) {
81729
81869
  }
81730
81870
  return { type: "SPEC_READ_FAILED", path: input.directory, cause: input.cause };
81731
81871
  }
81732
- var rawReaddir = import_neverthrow67.ResultAsync.fromThrowable(
81872
+ var rawReaddir = import_neverthrow68.ResultAsync.fromThrowable(
81733
81873
  async (directory) => (0, import_promises24.readdir)(directory),
81734
81874
  (cause) => ({ cause })
81735
81875
  );
81736
81876
  function safeReaddir(directory) {
81737
81877
  return rawReaddir(directory).mapErr(({ cause }) => mapReaddirError({ directory, cause }));
81738
81878
  }
81739
- var rawReadFile = import_neverthrow67.ResultAsync.fromThrowable(
81879
+ var rawReadFile = import_neverthrow68.ResultAsync.fromThrowable(
81740
81880
  async (input) => (0, import_promises24.readFile)(input.path, "utf8"),
81741
81881
  (cause) => ({ cause })
81742
81882
  );
@@ -81756,17 +81896,17 @@ function readEntry2(input) {
81756
81896
  }
81757
81897
  function readEntries2(directory, filenames) {
81758
81898
  const tasks = filenames.map((filename) => readEntry2({ directory, filename }));
81759
- return import_neverthrow67.ResultAsync.combine([...tasks]);
81899
+ return import_neverthrow68.ResultAsync.combine([...tasks]);
81760
81900
  }
81761
81901
  function readPlan(input) {
81762
81902
  return safeReaddir(input.directory).map((filenames) => filterAndSortSpecs(filenames)).andThen((filenames) => readEntries2(input.directory, filenames));
81763
81903
  }
81764
81904
  var SCENARIO_FILENAME_PATTERN = /^scenario-(\d+)\.test\.md$/;
81765
- var safeMkdir = import_neverthrow68.ResultAsync.fromThrowable(
81905
+ var safeMkdir = import_neverthrow69.ResultAsync.fromThrowable(
81766
81906
  async (path43) => (0, import_promises25.mkdir)(path43, { recursive: true }),
81767
81907
  (cause) => ({ type: "SPEC_WRITE_FAILED", path: "", cause })
81768
81908
  );
81769
- var safeReaddir2 = import_neverthrow68.ResultAsync.fromThrowable(
81909
+ var safeReaddir2 = import_neverthrow69.ResultAsync.fromThrowable(
81770
81910
  async (path43) => (0, import_promises25.readdir)(path43),
81771
81911
  (cause) => ({ type: "SPEC_WRITE_FAILED", path: "", cause })
81772
81912
  );
@@ -81817,12 +81957,12 @@ function writeAllScenarios(input, startIndex) {
81817
81957
  context: input.context
81818
81958
  })
81819
81959
  );
81820
- return import_neverthrow68.ResultAsync.combine([...tasks]);
81960
+ return import_neverthrow69.ResultAsync.combine([...tasks]);
81821
81961
  }
81822
81962
  function writeScenarios(input) {
81823
81963
  return ensureDirectory(input.directory).andThen(() => listScenarioIndices(input.directory)).map((indices) => computeNextIndex(indices)).andThen((startIndex) => writeAllScenarios(input, startIndex));
81824
81964
  }
81825
- var readFileByPath = import_neverthrow69.ResultAsync.fromThrowable(
81965
+ var readFileByPath = import_neverthrow70.ResultAsync.fromThrowable(
81826
81966
  async (path43) => (0, import_promises26.readFile)(path43, "utf8"),
81827
81967
  (cause) => ({ cause })
81828
81968
  );
@@ -81858,10 +81998,10 @@ var EXIT_PLAN_EMPTY = 45;
81858
81998
  var EXIT_SCENARIO_ID_LOST_IN_EDIT = 51;
81859
81999
 
81860
82000
  // src/commands/plan/format-diagnostic.ts
81861
- var import_neverthrow70 = __toESM(require_index_cjs(), 1);
82001
+ var import_neverthrow71 = __toESM(require_index_cjs(), 1);
81862
82002
  var RAW_TRUNCATION_LIMIT = 200;
81863
82003
  var UNSERIALIZABLE2 = "[unserializable]";
81864
- var safeStringify2 = (0, import_neverthrow70.fromThrowable)(
82004
+ var safeStringify2 = (0, import_neverthrow71.fromThrowable)(
81865
82005
  (value) => JSON.stringify(value),
81866
82006
  () => UNSERIALIZABLE2
81867
82007
  );
@@ -82106,15 +82246,23 @@ function runPlanExtend(input, options2) {
82106
82246
  }
82107
82247
 
82108
82248
  // src/commands/plan/generate-command.ts
82109
- var DEPS3 = {
82110
- gitBranchReference,
82111
- gitSymbolicReferenceOriginHead,
82112
- gitDiff,
82113
- gitStatusPorcelain,
82114
- emitScenarios: (input) => emitScenarios(input, { callAi: callScenarioEmitter }),
82115
- writeScenarios,
82116
- readPlan
82117
- };
82249
+ function stderrDebug(message) {
82250
+ process.stderr.write(`${message}
82251
+ `);
82252
+ }
82253
+ function buildDeps(input) {
82254
+ const emitDebug = input.debug === true ? stderrDebug : void 0;
82255
+ return {
82256
+ gitBranchReference,
82257
+ resolveBaseBranch: (gitContext) => resolveBaseBranch(gitContext, { ghDetectPrBaseBranch, gitSymbolicReferenceOriginHead }),
82258
+ gitDiff,
82259
+ gitStatusPorcelain,
82260
+ emitScenarios: (emitInput) => emitScenarios(emitInput, { callAi: callScenarioEmitter, emitDebug }),
82261
+ writeScenarios,
82262
+ readPlan,
82263
+ emitDebug
82264
+ };
82265
+ }
82118
82266
  function buildPlannerInput3(arguments_, appContext) {
82119
82267
  return {
82120
82268
  gitContext: { cwd: process.cwd() },
@@ -82129,12 +82277,13 @@ function buildPlannerInput3(arguments_, appContext) {
82129
82277
  model: PLANNER_MODEL
82130
82278
  },
82131
82279
  idGenerator: () => ulid3(),
82132
- now: () => (/* @__PURE__ */ new Date()).toISOString()
82280
+ now: () => (/* @__PURE__ */ new Date()).toISOString(),
82281
+ baseOverride: arguments_.input.baseOverride
82133
82282
  };
82134
82283
  }
82135
82284
  function executePipeline4(arguments_) {
82136
82285
  return readAppContextOrDiagnose(arguments_.input.xqaDirectory).andThen(
82137
- (appContext) => generatePlan(buildPlannerInput3(arguments_, appContext ?? ""), DEPS3)
82286
+ (appContext) => generatePlan(buildPlannerInput3(arguments_, appContext ?? ""), buildDeps(arguments_.input))
82138
82287
  );
82139
82288
  }
82140
82289
  function runPlanGenerate(input, options2) {
@@ -82143,7 +82292,7 @@ function runPlanGenerate(input, options2) {
82143
82292
 
82144
82293
  // src/commands/plan/report-command.ts
82145
82294
  var import_node_path24 = __toESM(require("node:path"), 1);
82146
- var DEPS4 = {
82295
+ var DEPS3 = {
82147
82296
  readPlan,
82148
82297
  readFindingsFile,
82149
82298
  writeReportFile
@@ -82155,20 +82304,26 @@ function buildReportInput(input) {
82155
82304
  };
82156
82305
  }
82157
82306
  function executePipeline5(input) {
82158
- return reportRun(buildReportInput(input), DEPS4);
82307
+ return reportRun(buildReportInput(input), DEPS3);
82159
82308
  }
82160
82309
  function runPlanReport(input) {
82161
82310
  void executePipeline5(input).match(emitSuccess, emitFailure);
82162
82311
  }
82163
82312
 
82164
82313
  // src/commands/register/plan.ts
82314
+ function normalizeBaseOverride(value) {
82315
+ const trimmed = value?.trim();
82316
+ return trimmed !== void 0 && trimmed.length > 0 ? trimmed : void 0;
82317
+ }
82165
82318
  function invokePlanGenerate(context, options2) {
82166
82319
  const xqaDirectory = resolveXqaDirectory();
82167
82320
  runPlanGenerate(
82168
82321
  {
82169
82322
  intent: options2.intent ?? "",
82170
82323
  outputDirectory: options2.out,
82171
- xqaDirectory
82324
+ xqaDirectory,
82325
+ baseOverride: normalizeBaseOverride(options2.base),
82326
+ debug: options2.debug
82172
82327
  },
82173
82328
  { config: context.config }
82174
82329
  );
@@ -82202,7 +82357,7 @@ function registerReportSubcommand(plan) {
82202
82357
  });
82203
82358
  }
82204
82359
  function registerPlanCommand(program3, loader2) {
82205
- const plan = program3.command("plan").description("Generate or evolve the manual test plan for the current branch").option("--intent <text>", "Optional focus hint for the planner", "").option("--out <dir>", "Output directory for the generated scenarios").action((options2) => {
82360
+ const plan = program3.command("plan").description("Generate or evolve the manual test plan for the current branch").option("--intent <text>", "Optional focus hint for the planner", "").option("--out <dir>", "Output directory for the generated scenarios").option("--base <ref>", "Base git ref to diff against (defaults to origin/HEAD)").option("--debug", "Log base ref, diff summary, prompt, and AI response to stderr").action((options2) => {
82206
82361
  const context = resolveContextOrExit(loader2);
82207
82362
  invokePlanGenerate(context, options2);
82208
82363
  });
@@ -82214,7 +82369,7 @@ function registerPlanCommand(program3, loader2) {
82214
82369
  // src/commands/review-command.ts
82215
82370
  var import_node_fs10 = require("node:fs");
82216
82371
  var import_node_path26 = __toESM(require("node:path"), 1);
82217
- var import_neverthrow72 = __toESM(require_index_cjs(), 1);
82372
+ var import_neverthrow73 = __toESM(require_index_cjs(), 1);
82218
82373
 
82219
82374
  // ../../node_modules/.pnpm/@inquirer+core@10.3.2_@types+node@22.19.15/node_modules/@inquirer/core/dist/esm/lib/key.js
82220
82375
  var isUpKey = (key, keybindings = []) => (
@@ -83165,7 +83320,7 @@ var {
83165
83320
  } = signalExitWrap(processOk(process5) ? new SignalExit(process5) : new SignalExitFallback());
83166
83321
 
83167
83322
  // ../../node_modules/.pnpm/@inquirer+core@10.3.2_@types+node@22.19.15/node_modules/@inquirer/core/dist/esm/lib/screen-manager.js
83168
- var import_node_util2 = require("node:util");
83323
+ var import_node_util3 = require("node:util");
83169
83324
 
83170
83325
  // ../../node_modules/.pnpm/@inquirer+ansi@1.0.2/node_modules/@inquirer/ansi/dist/esm/index.js
83171
83326
  var ESC2 = "\x1B[";
@@ -83203,7 +83358,7 @@ var ScreenManager = class {
83203
83358
  }
83204
83359
  render(content, bottomContent = "") {
83205
83360
  const promptLine = lastLine(content);
83206
- const rawPromptLine = (0, import_node_util2.stripVTControlCharacters)(promptLine);
83361
+ const rawPromptLine = (0, import_node_util3.stripVTControlCharacters)(promptLine);
83207
83362
  let prompt = rawPromptLine;
83208
83363
  if (this.rl.line.length > 0) {
83209
83364
  prompt = prompt.slice(0, -this.rl.line.length);
@@ -84619,7 +84774,7 @@ var esm_default11 = createPrompt((config2, done) => {
84619
84774
  });
84620
84775
 
84621
84776
  // src/review-session.ts
84622
- var import_neverthrow71 = __toESM(require_index_cjs(), 1);
84777
+ var import_neverthrow72 = __toESM(require_index_cjs(), 1);
84623
84778
  var FLOW_COL_WIDTH = 35;
84624
84779
  var TRIGGER_COL_WIDTH = 16;
84625
84780
  var CONFIDENCE_COL_WIDTH = 6;
@@ -84767,15 +84922,15 @@ async function runInteractiveLoop(findings, existing) {
84767
84922
  }
84768
84923
  return { staged: state.staged, undoneKeys: state.undoneKeys };
84769
84924
  }
84770
- var safeRunInteractiveLoop = (0, import_neverthrow71.fromAsyncThrowable)(
84925
+ var safeRunInteractiveLoop = (0, import_neverthrow72.fromAsyncThrowable)(
84771
84926
  runInteractiveLoop,
84772
84927
  (error48) => error48 instanceof Error && error48.name === "ExitPromptError" ? "exit-prompt" : "unexpected"
84773
84928
  );
84774
84929
 
84775
84930
  // src/commands/review-command.ts
84776
- var safeReadFile4 = (0, import_neverthrow72.fromThrowable)((filePath) => (0, import_node_fs10.readFileSync)(filePath, "utf8"));
84777
- var safeParseJson4 = (0, import_neverthrow72.fromThrowable)(JSON.parse);
84778
- var safeWrite = (0, import_neverthrow72.fromThrowable)((filePath, content) => {
84931
+ var safeReadFile4 = (0, import_neverthrow73.fromThrowable)((filePath) => (0, import_node_fs10.readFileSync)(filePath, "utf8"));
84932
+ var safeParseJson4 = (0, import_neverthrow73.fromThrowable)(JSON.parse);
84933
+ var safeWrite = (0, import_neverthrow73.fromThrowable)((filePath, content) => {
84779
84934
  (0, import_node_fs10.writeFileSync)(filePath, content);
84780
84935
  });
84781
84936
  function readLastPath(xqaDirectory) {
@@ -84792,13 +84947,13 @@ function isPipelineOutput(data) {
84792
84947
  function readFindings(filePath) {
84793
84948
  const readResult = safeReadFile4(filePath);
84794
84949
  if (readResult.isErr()) {
84795
- return (0, import_neverthrow72.err)("not-found");
84950
+ return (0, import_neverthrow73.err)("not-found");
84796
84951
  }
84797
84952
  return safeParseJson4(readResult.value).mapErr(() => "invalid").andThen((data) => {
84798
84953
  if (!isPipelineOutput(data)) {
84799
- return (0, import_neverthrow72.err)("invalid");
84954
+ return (0, import_neverthrow73.err)("invalid");
84800
84955
  }
84801
- return (0, import_neverthrow72.ok)(data);
84956
+ return (0, import_neverthrow73.ok)(data);
84802
84957
  });
84803
84958
  }
84804
84959
  function loadExistingDismissals(filePath) {
@@ -84871,7 +85026,7 @@ function resolveAndReadFindings(findingsPath, xqaDirectory) {
84871
85026
  "No findings path provided and no last path found. Run: xqa review <findings-path>\n"
84872
85027
  );
84873
85028
  process.exit(1);
84874
- return (0, import_neverthrow72.err)();
85029
+ return (0, import_neverthrow73.err)();
84875
85030
  }
84876
85031
  const resolvedPath = resolvedPathResult.value;
84877
85032
  const findingsResult = readFindings(resolvedPath);
@@ -84884,9 +85039,9 @@ function resolveAndReadFindings(findingsPath, xqaDirectory) {
84884
85039
  `);
84885
85040
  }
84886
85041
  process.exit(1);
84887
- return (0, import_neverthrow72.err)();
85042
+ return (0, import_neverthrow73.err)();
84888
85043
  }
84889
- return (0, import_neverthrow72.ok)({ resolvedPath, output: findingsResult.value });
85044
+ return (0, import_neverthrow73.ok)({ resolvedPath, output: findingsResult.value });
84890
85045
  }
84891
85046
  async function runReviewLoop({
84892
85047
  findings,
@@ -84959,11 +85114,11 @@ function discoverSimulators(udidOverride) {
84959
85114
  var import_promises27 = __toESM(require("node:fs/promises"), 1);
84960
85115
  var import_node_path27 = __toESM(require("node:path"), 1);
84961
85116
  var import_fast_glob = __toESM(require_out4(), 1);
84962
- var import_neverthrow75 = __toESM(require_index_cjs(), 1);
85117
+ var import_neverthrow76 = __toESM(require_index_cjs(), 1);
84963
85118
 
84964
85119
  // src/suite/core/suite-config-parser.ts
84965
- var import_neverthrow73 = __toESM(require_index_cjs(), 1);
84966
85120
  var import_neverthrow74 = __toESM(require_index_cjs(), 1);
85121
+ var import_neverthrow75 = __toESM(require_index_cjs(), 1);
84967
85122
  var RESERVED_HOOK_ENV_KEYS = [
84968
85123
  "XQA_SIM_UDID",
84969
85124
  "XQA_ITEM_ID",
@@ -85015,7 +85170,7 @@ var suiteConfigSchema = external_exports.object({
85015
85170
  }).refine((data) => data.specs.length > 0 || data.freestyle.length > 0, {
85016
85171
  message: "Suite must declare at least one spec or freestyle entry"
85017
85172
  });
85018
- var safeJsonParse5 = (0, import_neverthrow73.fromThrowable)(
85173
+ var safeJsonParse5 = (0, import_neverthrow74.fromThrowable)(
85019
85174
  JSON.parse,
85020
85175
  (cause) => ({
85021
85176
  type: "INVALID_SUITE_CONFIG",
@@ -85049,16 +85204,16 @@ function parseSuiteConfig(raw) {
85049
85204
  return safeJsonParse5(raw).andThen((data) => {
85050
85205
  const parsed = suiteConfigSchema.safeParse(data);
85051
85206
  if (!parsed.success) {
85052
- return (0, import_neverthrow74.err)({ type: "INVALID_SUITE_CONFIG", cause: parsed.error });
85207
+ return (0, import_neverthrow75.err)({ type: "INVALID_SUITE_CONFIG", cause: parsed.error });
85053
85208
  }
85054
85209
  const hooks = normalizeHooks(parsed.data.hooks);
85055
85210
  if (hooks === void 0) {
85056
- return (0, import_neverthrow74.ok)({
85211
+ return (0, import_neverthrow75.ok)({
85057
85212
  specs: parsed.data.specs,
85058
85213
  freestyle: parsed.data.freestyle
85059
85214
  });
85060
85215
  }
85061
- return (0, import_neverthrow74.ok)({
85216
+ return (0, import_neverthrow75.ok)({
85062
85217
  specs: parsed.data.specs,
85063
85218
  freestyle: parsed.data.freestyle,
85064
85219
  hooks
@@ -85106,7 +85261,7 @@ function buildFreestyleItems(entries) {
85106
85261
  }
85107
85262
 
85108
85263
  // src/suite/commands/run/resolve-work-items.ts
85109
- var safeReadFile5 = import_neverthrow75.ResultAsync.fromThrowable(
85264
+ var safeReadFile5 = import_neverthrow76.ResultAsync.fromThrowable(
85110
85265
  async (filePath) => import_promises27.default.readFile(filePath, "utf8"),
85111
85266
  () => "READ_FAILED"
85112
85267
  );
@@ -85174,7 +85329,7 @@ async function resolveAndFilterItems(input) {
85174
85329
  }
85175
85330
 
85176
85331
  // src/suite/shell/worker-pool.ts
85177
- var import_neverthrow78 = __toESM(require_index_cjs(), 1);
85332
+ var import_neverthrow79 = __toESM(require_index_cjs(), 1);
85178
85333
 
85179
85334
  // src/suite/core/priority-queue.ts
85180
85335
  var PriorityQueue = class {
@@ -85421,7 +85576,7 @@ function recordHookFailure(input) {
85421
85576
  }
85422
85577
 
85423
85578
  // src/suite/shell/hook-invoker.ts
85424
- var import_neverthrow77 = __toESM(require_index_cjs(), 1);
85579
+ var import_neverthrow78 = __toESM(require_index_cjs(), 1);
85425
85580
 
85426
85581
  // src/suite/core/hook-env-builder.ts
85427
85582
  function buildReservedKeys(input) {
@@ -85447,8 +85602,8 @@ function buildHookEnv(input) {
85447
85602
  }
85448
85603
 
85449
85604
  // src/suite/shell/hook-runner.ts
85450
- var import_node_child_process7 = require("node:child_process");
85451
- var import_neverthrow76 = __toESM(require_index_cjs(), 1);
85605
+ var import_node_child_process8 = require("node:child_process");
85606
+ var import_neverthrow77 = __toESM(require_index_cjs(), 1);
85452
85607
  function makeDeferred() {
85453
85608
  const raw = Promise.withResolvers();
85454
85609
  return { promise: raw.promise, resolve: raw.resolve };
@@ -85468,7 +85623,7 @@ var HookRuntime = class {
85468
85623
  onAbort;
85469
85624
  constructor(options2) {
85470
85625
  const { script, cwd, env: env3, baseEnv, nodeExecPath, timeoutMs, signal } = options2;
85471
- this.child = (0, import_node_child_process7.spawn)(nodeExecPath, [script], {
85626
+ this.child = (0, import_node_child_process8.spawn)(nodeExecPath, [script], {
85472
85627
  cwd,
85473
85628
  env: { ...baseEnv, ...env3 },
85474
85629
  stdio: ["ignore", "inherit", "pipe"]
@@ -85478,7 +85633,7 @@ var HookRuntime = class {
85478
85633
  this.deferred = makeDeferred();
85479
85634
  this.onAbort = () => {
85480
85635
  this.child.kill("SIGTERM");
85481
- this.settle((0, import_neverthrow76.err)({ type: "HOOK_ABORTED" }));
85636
+ this.settle((0, import_neverthrow77.err)({ type: "HOOK_ABORTED" }));
85482
85637
  };
85483
85638
  }
85484
85639
  async start() {
@@ -85503,20 +85658,20 @@ var HookRuntime = class {
85503
85658
  attachTimeout() {
85504
85659
  this.timeoutHandle = setTimeout(() => {
85505
85660
  this.child.kill("SIGTERM");
85506
- this.settle((0, import_neverthrow76.err)({ type: "HOOK_TIMEOUT", timeoutMs: this.timeoutMs }));
85661
+ this.settle((0, import_neverthrow77.err)({ type: "HOOK_TIMEOUT", timeoutMs: this.timeoutMs }));
85507
85662
  }, this.timeoutMs);
85508
85663
  }
85509
85664
  attachChildListeners() {
85510
85665
  this.child.on("error", (cause) => {
85511
- this.settle((0, import_neverthrow76.err)({ type: "HOOK_SPAWN_FAILED", cause }));
85666
+ this.settle((0, import_neverthrow77.err)({ type: "HOOK_SPAWN_FAILED", cause }));
85512
85667
  });
85513
85668
  this.child.on("exit", (code) => {
85514
85669
  if (code === 0) {
85515
- this.settle((0, import_neverthrow76.ok)());
85670
+ this.settle((0, import_neverthrow77.ok)());
85516
85671
  return;
85517
85672
  }
85518
85673
  this.settle(
85519
- (0, import_neverthrow76.err)({
85674
+ (0, import_neverthrow77.err)({
85520
85675
  type: "HOOK_EXIT_NONZERO",
85521
85676
  code: code ?? -1,
85522
85677
  stderr: this.stderrBuffer
@@ -85539,7 +85694,7 @@ var HookRuntime = class {
85539
85694
  this.signal.removeEventListener("abort", this.onAbort);
85540
85695
  }
85541
85696
  };
85542
- var safeSpawn = import_neverthrow76.ResultAsync.fromThrowable(
85697
+ var safeSpawn = import_neverthrow77.ResultAsync.fromThrowable(
85543
85698
  spawnHook,
85544
85699
  (cause) => ({ type: "HOOK_SPAWN_FAILED", cause })
85545
85700
  );
@@ -85567,7 +85722,7 @@ async function invokeHook(input) {
85567
85722
  async function maybeInvokeHook(input) {
85568
85723
  const { hook: hook2 } = input;
85569
85724
  if (hook2 === void 0) {
85570
- return (0, import_neverthrow77.ok)();
85725
+ return (0, import_neverthrow78.ok)();
85571
85726
  }
85572
85727
  return invokeHook({ ...input, hook: hook2 });
85573
85728
  }
@@ -85661,7 +85816,7 @@ async function processItem(workerContext, item) {
85661
85816
  workerContext.inFlight.delete(item.id);
85662
85817
  return failCount;
85663
85818
  }
85664
- var safeProcessItem = import_neverthrow78.ResultAsync.fromThrowable(
85819
+ var safeProcessItem = import_neverthrow79.ResultAsync.fromThrowable(
85665
85820
  processItem,
85666
85821
  (cause) => ({
85667
85822
  type: "PROCESS_ITEM_FAILED",
@@ -85726,7 +85881,7 @@ function runWorkerPool(config2) {
85726
85881
  const results = [];
85727
85882
  const inFlight = /* @__PURE__ */ new Map();
85728
85883
  const suiteStartMs = Date.now();
85729
- const safeRun = import_neverthrow78.ResultAsync.fromThrowable(
85884
+ const safeRun = import_neverthrow79.ResultAsync.fromThrowable(
85730
85885
  async () => runAllWorkers({ config: config2, queue, results, suiteStartMs, inFlight }),
85731
85886
  (cause) => ({ type: "WORKER_POOL_FAILED", cause })
85732
85887
  );
@@ -85882,7 +86037,7 @@ function buildSuiteFindings(input) {
85882
86037
  // src/suite/shell/suite-findings-writer.ts
85883
86038
  var import_promises28 = __toESM(require("node:fs/promises"), 1);
85884
86039
  var import_node_path29 = __toESM(require("node:path"), 1);
85885
- var import_neverthrow79 = __toESM(require_index_cjs(), 1);
86040
+ var import_neverthrow80 = __toESM(require_index_cjs(), 1);
85886
86041
  var INDENT_SPACES = 2;
85887
86042
  function writeSuiteFindings(findings, options2) {
85888
86043
  const directory = import_node_path29.default.join(
@@ -85894,7 +86049,7 @@ function writeSuiteFindings(findings, options2) {
85894
86049
  );
85895
86050
  const finalPath = import_node_path29.default.join(directory, "findings.json");
85896
86051
  const temporaryPath = `${finalPath}.tmp`;
85897
- const safeWriteAtomically = import_neverthrow79.ResultAsync.fromThrowable(
86052
+ const safeWriteAtomically = import_neverthrow80.ResultAsync.fromThrowable(
85898
86053
  async () => {
85899
86054
  await import_promises28.default.mkdir(directory, { recursive: true });
85900
86055
  await import_promises28.default.writeFile(temporaryPath, JSON.stringify(findings, void 0, INDENT_SPACES));
@@ -85928,7 +86083,7 @@ async function writeAndReport(input) {
85928
86083
  // src/suite/commands/suite-run-context.ts
85929
86084
  var import_promises29 = __toESM(require("node:fs/promises"), 1);
85930
86085
  var import_node_path30 = __toESM(require("node:path"), 1);
85931
- var import_neverthrow80 = __toESM(require_index_cjs(), 1);
86086
+ var import_neverthrow81 = __toESM(require_index_cjs(), 1);
85932
86087
 
85933
86088
  // src/suite/core/run-id.ts
85934
86089
  var RUN_ID_PAD_LENGTH2 = 4;
@@ -85963,7 +86118,7 @@ function deriveSuiteId(input) {
85963
86118
 
85964
86119
  // src/suite/commands/suite-run-context.ts
85965
86120
  var ISO_DATE_LENGTH3 = 10;
85966
- var safeReaddir3 = import_neverthrow80.ResultAsync.fromThrowable(
86121
+ var safeReaddir3 = import_neverthrow81.ResultAsync.fromThrowable(
85967
86122
  async (directoryPath) => {
85968
86123
  const entries = await import_promises29.default.readdir(directoryPath, { withFileTypes: true });
85969
86124
  return entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name);
@@ -86098,18 +86253,18 @@ async function runSuiteCommand(input) {
86098
86253
  }
86099
86254
 
86100
86255
  // src/suite/commands/validate-run-arguments.ts
86101
- var import_neverthrow81 = __toESM(require_index_cjs(), 1);
86256
+ var import_neverthrow82 = __toESM(require_index_cjs(), 1);
86102
86257
  function validateRunArguments(options2) {
86103
86258
  if (options2.suite === void 0 && options2.spec === void 0) {
86104
- return (0, import_neverthrow81.err)({ type: "MISSING_SUITE_OR_SPEC" });
86259
+ return (0, import_neverthrow82.err)({ type: "MISSING_SUITE_OR_SPEC" });
86105
86260
  }
86106
86261
  if (options2.suite !== void 0 && options2.spec !== void 0) {
86107
- return (0, import_neverthrow81.err)({ type: "BOTH_SUITE_AND_SPEC" });
86262
+ return (0, import_neverthrow82.err)({ type: "BOTH_SUITE_AND_SPEC" });
86108
86263
  }
86109
86264
  if (options2.only !== void 0 && options2.suite === void 0) {
86110
- return (0, import_neverthrow81.err)({ type: "ONLY_REQUIRES_SUITE" });
86265
+ return (0, import_neverthrow82.err)({ type: "ONLY_REQUIRES_SUITE" });
86111
86266
  }
86112
- return (0, import_neverthrow81.ok)(
86267
+ return (0, import_neverthrow82.ok)(
86113
86268
  options2.suite === void 0 ? { type: "spec", globs: options2.spec ?? [] } : { type: "suite", name: options2.suite }
86114
86269
  );
86115
86270
  }
@@ -86264,41 +86419,41 @@ function deriveSpecSlug(specFilePath) {
86264
86419
  // src/commands/spec-resolver.ts
86265
86420
  var import_node_fs12 = require("node:fs");
86266
86421
  var import_node_path33 = __toESM(require("node:path"), 1);
86267
- var import_neverthrow83 = __toESM(require_index_cjs(), 1);
86422
+ var import_neverthrow84 = __toESM(require_index_cjs(), 1);
86268
86423
 
86269
86424
  // src/spec-frontmatter.ts
86270
86425
  var import_gray_matter = __toESM(require_gray_matter(), 1);
86271
- var import_neverthrow82 = __toESM(require_index_cjs(), 1);
86426
+ var import_neverthrow83 = __toESM(require_index_cjs(), 1);
86272
86427
  var frontmatterSchema = external_exports.object({
86273
86428
  feature: external_exports.string().min(1),
86274
86429
  timeout: external_exports.number().int().positive().optional()
86275
86430
  });
86276
- var safeParseMatter = (0, import_neverthrow82.fromThrowable)(
86431
+ var safeParseMatter = (0, import_neverthrow83.fromThrowable)(
86277
86432
  import_gray_matter.default,
86278
86433
  (cause) => ({ type: "SPEC_FRONTMATTER_INVALID", cause })
86279
86434
  );
86280
86435
  function validate(data) {
86281
86436
  const parsed = frontmatterSchema.safeParse(data);
86282
86437
  if (!parsed.success) {
86283
- return (0, import_neverthrow82.err)({ type: "SPEC_FRONTMATTER_INVALID", cause: parsed.error });
86438
+ return (0, import_neverthrow83.err)({ type: "SPEC_FRONTMATTER_INVALID", cause: parsed.error });
86284
86439
  }
86285
86440
  const { feature, timeout } = parsed.data;
86286
86441
  if (timeout === void 0) {
86287
- return (0, import_neverthrow82.ok)({ feature });
86442
+ return (0, import_neverthrow83.ok)({ feature });
86288
86443
  }
86289
- return (0, import_neverthrow82.ok)({ feature, timeoutSeconds: timeout });
86444
+ return (0, import_neverthrow83.ok)({ feature, timeoutSeconds: timeout });
86290
86445
  }
86291
86446
  function parseSpecFrontmatter(raw) {
86292
86447
  return safeParseMatter(raw).andThen((parsed) => validate(parsed.data));
86293
86448
  }
86294
86449
 
86295
86450
  // src/commands/spec-resolver.ts
86296
- var safeReadFile6 = (0, import_neverthrow83.fromThrowable)((filePath) => (0, import_node_fs12.readFileSync)(filePath, "utf8"));
86297
- var safeReaddir4 = (0, import_neverthrow83.fromThrowable)(
86451
+ var safeReadFile6 = (0, import_neverthrow84.fromThrowable)((filePath) => (0, import_node_fs12.readFileSync)(filePath, "utf8"));
86452
+ var safeReaddir4 = (0, import_neverthrow84.fromThrowable)(
86298
86453
  (directory) => (0, import_node_fs12.readdirSync)(directory, { recursive: true, encoding: "utf8" })
86299
86454
  );
86300
86455
  var CANCEL = "xqa:cancel";
86301
- var safeSelect = import_neverthrow83.ResultAsync.fromThrowable(
86456
+ var safeSelect = import_neverthrow84.ResultAsync.fromThrowable(
86302
86457
  esm_default11,
86303
86458
  (error48) => error48 instanceof Error && error48.name === "ExitPromptError" ? "cancelled" : "failed"
86304
86459
  );
@@ -86441,7 +86596,7 @@ function registerSpecCommand(program3, loader2) {
86441
86596
  }
86442
86597
 
86443
86598
  // ../../agents/triager/dist/index.js
86444
- var import_neverthrow84 = __toESM(require_index_cjs(), 1);
86599
+ var import_neverthrow85 = __toESM(require_index_cjs(), 1);
86445
86600
 
86446
86601
  // ../../node_modules/.pnpm/balanced-match@4.0.4/node_modules/balanced-match/dist/esm/index.js
86447
86602
  var balanced = (a3, b, str3) => {
@@ -88246,14 +88401,14 @@ minimatch.escape = escape2;
88246
88401
  minimatch.unescape = unescape2;
88247
88402
 
88248
88403
  // ../../agents/triager/dist/index.js
88249
- var import_neverthrow85 = __toESM(require_index_cjs(), 1);
88250
- var import_promises30 = require("node:fs/promises");
88251
88404
  var import_neverthrow86 = __toESM(require_index_cjs(), 1);
88252
- var import_node_child_process8 = require("node:child_process");
88405
+ var import_promises30 = require("node:fs/promises");
88406
+ var import_neverthrow87 = __toESM(require_index_cjs(), 1);
88407
+ var import_node_child_process9 = require("node:child_process");
88253
88408
  var import_promises31 = require("node:fs/promises");
88254
88409
  var import_node_path35 = __toESM(require("node:path"), 1);
88255
- var import_neverthrow87 = __toESM(require_index_cjs(), 1);
88256
88410
  var import_neverthrow88 = __toESM(require_index_cjs(), 1);
88411
+ var import_neverthrow89 = __toESM(require_index_cjs(), 1);
88257
88412
  function resolveConfidence2(selected) {
88258
88413
  if (selected.some((pick2) => pick2.confidence === "HIGH")) {
88259
88414
  return "high";
@@ -88872,7 +89027,7 @@ function buildMcpServer(state, options2) {
88872
89027
  });
88873
89028
  return xx({ name: TRIAGER_MCP_SERVER_NAME, version: "0.0.0", tools });
88874
89029
  }
88875
- function buildAllowedTools() {
89030
+ function buildAllowedTools2() {
88876
89031
  return [
88877
89032
  `${TOOL_PREFIX}read_spec`,
88878
89033
  `${TOOL_PREFIX}read_app_section`,
@@ -88883,7 +89038,7 @@ function buildAllowedTools() {
88883
89038
  function buildQueryOptions2(input) {
88884
89039
  return {
88885
89040
  mcpServers: { [TRIAGER_MCP_SERVER_NAME]: input.server },
88886
- allowedTools: buildAllowedTools(),
89041
+ allowedTools: buildAllowedTools2(),
88887
89042
  tools: [],
88888
89043
  permissionMode: "bypassPermissions",
88889
89044
  allowDangerouslySkipPermissions: true,
@@ -88918,7 +89073,7 @@ async function drainMessages(runner, state) {
88918
89073
  }
88919
89074
  }
88920
89075
  }
88921
- var safeDrainMessages = import_neverthrow85.ResultAsync.fromThrowable(
89076
+ var safeDrainMessages = import_neverthrow86.ResultAsync.fromThrowable(
88922
89077
  drainMessages,
88923
89078
  (cause) => ({ type: "AI_CALL_FAILED", cause })
88924
89079
  );
@@ -88944,25 +89099,25 @@ function finalizeRun(bootstrap) {
88944
89099
  const telemetry = buildTelemetry(bootstrap.telemetryInput, bootstrap.state);
88945
89100
  const error48 = resolveError(bootstrap.state);
88946
89101
  if (error48 !== void 0) {
88947
- return (0, import_neverthrow85.errAsync)(error48);
89102
+ return (0, import_neverthrow86.errAsync)(error48);
88948
89103
  }
88949
89104
  const output = bootstrap.state.output;
88950
89105
  if (output === void 0) {
88951
- return (0, import_neverthrow85.errAsync)({ type: "AI_NO_FINAL_TOOL_CALL" });
89106
+ return (0, import_neverthrow86.errAsync)({ type: "AI_NO_FINAL_TOOL_CALL" });
88952
89107
  }
88953
89108
  bootstrap.reportTelemetry(telemetry);
88954
- return (0, import_neverthrow85.okAsync)({ picks: output.picks, metaPr: output.metaPr, telemetry });
89109
+ return (0, import_neverthrow86.okAsync)({ picks: output.picks, metaPr: output.metaPr, telemetry });
88955
89110
  }
88956
89111
  function launchQuery(input) {
88957
- const safeLaunch = (0, import_neverthrow85.fromThrowable)(
89112
+ const safeLaunch = (0, import_neverthrow86.fromThrowable)(
88958
89113
  input.queryRunner,
88959
89114
  (cause) => ({ type: "AI_CALL_FAILED", cause })
88960
89115
  );
88961
89116
  const result = safeLaunch({ prompt: input.inputQueue, options: input.queryOptions });
88962
89117
  if (result.isErr()) {
88963
- return (0, import_neverthrow85.errAsync)(result.error);
89118
+ return (0, import_neverthrow86.errAsync)(result.error);
88964
89119
  }
88965
- return (0, import_neverthrow85.okAsync)(result.value);
89120
+ return (0, import_neverthrow86.okAsync)(result.value);
88966
89121
  }
88967
89122
  function runPipeline4(bootstrap) {
88968
89123
  return launchQuery({
@@ -89016,9 +89171,9 @@ var STATIC_ONLY_FIELDS = {
89016
89171
  freestyleByGroup: /* @__PURE__ */ new Map(),
89017
89172
  appIndex: [],
89018
89173
  handlers: {
89019
- readSpec: () => (0, import_neverthrow84.errAsync)({ type: "FILE_NOT_FOUND", path: "" }),
89020
- readAppSection: () => (0, import_neverthrow84.errAsync)({ type: "FILE_NOT_FOUND", path: "" }),
89021
- grepCodebase: () => (0, import_neverthrow84.errAsync)({ type: "FILE_NOT_FOUND", path: "" })
89174
+ readSpec: () => (0, import_neverthrow85.errAsync)({ type: "FILE_NOT_FOUND", path: "" }),
89175
+ readAppSection: () => (0, import_neverthrow85.errAsync)({ type: "FILE_NOT_FOUND", path: "" }),
89176
+ grepCodebase: () => (0, import_neverthrow85.errAsync)({ type: "FILE_NOT_FOUND", path: "" })
89022
89177
  }
89023
89178
  };
89024
89179
  function resolveAiFields(config2) {
@@ -89139,15 +89294,15 @@ function runAiTiebreaker(context, staticPicks) {
89139
89294
  function runTriager(options2) {
89140
89295
  const { groups, config: config2 } = options2;
89141
89296
  if (groups.length === 0) {
89142
- return (0, import_neverthrow84.errAsync)({ type: "NO_GROUPS" });
89297
+ return (0, import_neverthrow85.errAsync)({ type: "NO_GROUPS" });
89143
89298
  }
89144
89299
  if (config2?.useAi === true && config2.ai === void 0) {
89145
- return (0, import_neverthrow84.errAsync)({ type: "AI_CONFIG_MISSING" });
89300
+ return (0, import_neverthrow85.errAsync)({ type: "AI_CONFIG_MISSING" });
89146
89301
  }
89147
89302
  const context = buildContext2(options2);
89148
89303
  const staticPicks = scoreGroups(context.diff, context.groups);
89149
89304
  if (!context.useAi) {
89150
- return (0, import_neverthrow84.okAsync)(buildDecision({ picks: staticPicks, metaPr: false }));
89305
+ return (0, import_neverthrow85.okAsync)(buildDecision({ picks: staticPicks, metaPr: false }));
89151
89306
  }
89152
89307
  return runAiTiebreaker(context, staticPicks);
89153
89308
  }
@@ -89208,9 +89363,9 @@ function parseSections(text) {
89208
89363
  function lookupSection(sections, screenName) {
89209
89364
  const section = sections.get(screenName);
89210
89365
  if (section === void 0) {
89211
- return (0, import_neverthrow86.errAsync)({ type: "SECTION_NOT_FOUND", screenName });
89366
+ return (0, import_neverthrow87.errAsync)({ type: "SECTION_NOT_FOUND", screenName });
89212
89367
  }
89213
- return (0, import_neverthrow86.okAsync)(section);
89368
+ return (0, import_neverthrow87.okAsync)(section);
89214
89369
  }
89215
89370
  async function readUtf8File(filePath) {
89216
89371
  return (0, import_promises30.readFile)(filePath, UTF8);
@@ -89218,7 +89373,7 @@ async function readUtf8File(filePath) {
89218
89373
  function createAppMdReader(options2) {
89219
89374
  const filePath = options2.path;
89220
89375
  let sectionCache;
89221
- const safeReadFile7 = import_neverthrow86.ResultAsync.fromThrowable(
89376
+ const safeReadFile7 = import_neverthrow87.ResultAsync.fromThrowable(
89222
89377
  readUtf8File,
89223
89378
  (cause) => classifyReadError(cause, filePath)
89224
89379
  );
@@ -89255,7 +89410,7 @@ function buildSpawnExitError(code, stderr) {
89255
89410
  }
89256
89411
  async function runExecFile(request2) {
89257
89412
  const { promise: promise2, resolve, reject } = Promise.withResolvers();
89258
- const child = (0, import_node_child_process8.spawn)(request2.binary, [...request2.arguments_], { cwd: request2.cwd });
89413
+ const child = (0, import_node_child_process9.spawn)(request2.binary, [...request2.arguments_], { cwd: request2.cwd });
89259
89414
  const stdoutChunks = [];
89260
89415
  const stderrChunks = [];
89261
89416
  child.stdout.on("data", (chunk) => {
@@ -89336,15 +89491,15 @@ async function invokeRipgrep(options2) {
89336
89491
  return runExecFile({ binary: binary2, arguments_, cwd });
89337
89492
  }
89338
89493
  function execRipgrepRaw(options2) {
89339
- const safeExec = import_neverthrow87.ResultAsync.fromThrowable(invokeRipgrep, classifyRawExecError);
89494
+ const safeExec = import_neverthrow88.ResultAsync.fromThrowable(invokeRipgrep, classifyRawExecError);
89340
89495
  return safeExec(options2);
89341
89496
  }
89342
89497
  function handleExecResult(options2) {
89343
89498
  return execRipgrepRaw(options2).orElse((error48) => {
89344
89499
  if (error48.type === "GREP_FAILED" && error48.cause.code === RIPGREP_NO_MATCH_CODE) {
89345
- return (0, import_neverthrow87.ok)({ stdout: "", stderr: "" });
89500
+ return (0, import_neverthrow88.ok)({ stdout: "", stderr: "" });
89346
89501
  }
89347
- return (0, import_neverthrow87.err)(error48);
89502
+ return (0, import_neverthrow88.err)(error48);
89348
89503
  });
89349
89504
  }
89350
89505
  async function readUtf8File2(filePath) {
@@ -89353,7 +89508,7 @@ async function readUtf8File2(filePath) {
89353
89508
  function makeReadFile(cwd) {
89354
89509
  return (filePath) => {
89355
89510
  const resolvedPath = resolveFilePath(filePath, cwd);
89356
- const safeRead = import_neverthrow87.ResultAsync.fromThrowable(
89511
+ const safeRead = import_neverthrow88.ResultAsync.fromThrowable(
89357
89512
  readUtf8File2,
89358
89513
  (cause) => classifyReadError2(cause, resolvedPath)
89359
89514
  );
@@ -89420,9 +89575,9 @@ function applyHeading(state, screenName) {
89420
89575
  function handleHeading(state, indexed) {
89421
89576
  const screenName = indexed.text.slice(LEVEL_2_HEADING_MARKER.length).trim();
89422
89577
  if (screenName.length === 0) {
89423
- return (0, import_neverthrow88.err)({ type: "APP_MD_MALFORMED", line: indexed.number });
89578
+ return (0, import_neverthrow89.err)({ type: "APP_MD_MALFORMED", line: indexed.number });
89424
89579
  }
89425
- return (0, import_neverthrow88.ok)(applyHeading(state, screenName));
89580
+ return (0, import_neverthrow89.ok)(applyHeading(state, screenName));
89426
89581
  }
89427
89582
  function handleFenceLine(state, lineNumber) {
89428
89583
  if (state.insideFence) {
@@ -89456,23 +89611,23 @@ function isLevel2Heading(line) {
89456
89611
  }
89457
89612
  function processLine2(state, indexed) {
89458
89613
  if (indexed.text.startsWith(FENCE_MARKER)) {
89459
- return (0, import_neverthrow88.ok)(handleFenceLine(state, indexed.number));
89614
+ return (0, import_neverthrow89.ok)(handleFenceLine(state, indexed.number));
89460
89615
  }
89461
89616
  if (state.insideFence) {
89462
- return (0, import_neverthrow88.ok)(state);
89617
+ return (0, import_neverthrow89.ok)(state);
89463
89618
  }
89464
89619
  if (isLevel2Heading(indexed.text)) {
89465
89620
  return handleHeading(state, indexed);
89466
89621
  }
89467
89622
  if (indexed.text.trim().length === 0) {
89468
- return (0, import_neverthrow88.ok)(handleBlankLine(state));
89623
+ return (0, import_neverthrow89.ok)(handleBlankLine(state));
89469
89624
  }
89470
- return (0, import_neverthrow88.ok)(handleContentLine(state, indexed.text));
89625
+ return (0, import_neverthrow89.ok)(handleContentLine(state, indexed.text));
89471
89626
  }
89472
89627
  function processIndexedLines(indexedLines, state) {
89473
89628
  const [head, ...tail] = indexedLines;
89474
89629
  if (head === void 0) {
89475
- return (0, import_neverthrow88.ok)(state);
89630
+ return (0, import_neverthrow89.ok)(state);
89476
89631
  }
89477
89632
  return processLine2(state, head).andThen((next) => processIndexedLines(tail, next));
89478
89633
  }
@@ -89484,9 +89639,9 @@ function buildFinalEntries(state) {
89484
89639
  }
89485
89640
  function finaliseState(state) {
89486
89641
  if (state.insideFence) {
89487
- return (0, import_neverthrow88.err)({ type: "APP_MD_MALFORMED", line: state.fenceOpenLine });
89642
+ return (0, import_neverthrow89.err)({ type: "APP_MD_MALFORMED", line: state.fenceOpenLine });
89488
89643
  }
89489
- return (0, import_neverthrow88.ok)([...buildFinalEntries(state)]);
89644
+ return (0, import_neverthrow89.ok)([...buildFinalEntries(state)]);
89490
89645
  }
89491
89646
  function buildAppIndex(appMd) {
89492
89647
  const indexedLines = toIndexedLines(appMd.split("\n"));
@@ -89517,11 +89672,11 @@ function summariseSpec(input) {
89517
89672
  var triagerConfigSchema = agentBaseConfigSchema.extend({ enabled: external_exports.boolean().default(false) }).strict();
89518
89673
 
89519
89674
  // src/commands/triage-command.ts
89520
- var import_neverthrow93 = __toESM(require_index_cjs(), 1);
89675
+ var import_neverthrow94 = __toESM(require_index_cjs(), 1);
89521
89676
 
89522
89677
  // src/triage/ai-context-builder.ts
89523
89678
  var import_node_path36 = __toESM(require("node:path"), 1);
89524
- var import_neverthrow89 = __toESM(require_index_cjs(), 1);
89679
+ var import_neverthrow90 = __toESM(require_index_cjs(), 1);
89525
89680
  var PROMPT_VERSION = "v1";
89526
89681
  var MAX_GREP_PATTERN_LENGTH = 200;
89527
89682
  var DENIED_SAMPLE_PATHS = [
@@ -89600,7 +89755,7 @@ function isDeniedGlob(pathGlob) {
89600
89755
  return normalized !== pathGlob && matchesDeniedSample(normalized);
89601
89756
  }
89602
89757
  function pathDenied(reason) {
89603
- return (0, import_neverthrow89.errAsync)({ type: "PATH_DENIED", reason });
89758
+ return (0, import_neverthrow90.errAsync)({ type: "PATH_DENIED", reason });
89604
89759
  }
89605
89760
  function buildHandlers(cwd, validSpecIds) {
89606
89761
  const reader = createCodebaseReader({ cwd });
@@ -89633,13 +89788,13 @@ function loadAppIndex(appMdPath) {
89633
89788
  return appMdReader.readFile(appMdPath).mapErr(() => ({ type: "SPEC_NOT_FOUND", path: appMdPath })).andThen((content) => {
89634
89789
  const indexResult = buildAppIndex(content);
89635
89790
  if (indexResult.isErr()) {
89636
- return (0, import_neverthrow89.errAsync)({
89791
+ return (0, import_neverthrow90.errAsync)({
89637
89792
  type: "SUITE_INVALID",
89638
89793
  path: appMdPath,
89639
89794
  cause: indexResult.error
89640
89795
  });
89641
89796
  }
89642
- return (0, import_neverthrow89.okAsync)(indexResult.value);
89797
+ return (0, import_neverthrow90.okAsync)(indexResult.value);
89643
89798
  });
89644
89799
  }
89645
89800
  function collectSpecIds(specSummariesByGroup) {
@@ -93214,7 +93369,7 @@ var Octokit2 = Octokit.plugin(requestLog, legacyRestEndpointMethods, paginateRes
93214
93369
  );
93215
93370
 
93216
93371
  // src/triage/github-pr-fetcher.ts
93217
- var import_neverthrow90 = __toESM(require_index_cjs(), 1);
93372
+ var import_neverthrow91 = __toESM(require_index_cjs(), 1);
93218
93373
  var STATUS_MAP = {
93219
93374
  added: "added",
93220
93375
  modified: "modified",
@@ -93250,11 +93405,11 @@ async function runListFiles(octokit, options2) {
93250
93405
  per_page: 100
93251
93406
  });
93252
93407
  }
93253
- var safeGet = import_neverthrow90.ResultAsync.fromThrowable(
93408
+ var safeGet = import_neverthrow91.ResultAsync.fromThrowable(
93254
93409
  runPullRequestGet,
93255
93410
  (cause) => ({ type: "PR_FETCH_FAILED", cause })
93256
93411
  );
93257
- var safeList = import_neverthrow90.ResultAsync.fromThrowable(
93412
+ var safeList = import_neverthrow91.ResultAsync.fromThrowable(
93258
93413
  runListFiles,
93259
93414
  (cause) => ({ type: "PR_FETCH_FAILED", cause })
93260
93415
  );
@@ -93268,13 +93423,13 @@ function toDiff(summary, files) {
93268
93423
  }
93269
93424
  function fetchPullRequestDiff(options2) {
93270
93425
  const octokit = new Octokit2({ auth: options2.token });
93271
- return import_neverthrow90.ResultAsync.combine([safeGet(octokit, options2), safeList(octokit, options2)]).map(
93426
+ return import_neverthrow91.ResultAsync.combine([safeGet(octokit, options2), safeList(octokit, options2)]).map(
93272
93427
  ([summary, files]) => toDiff(summary, files)
93273
93428
  );
93274
93429
  }
93275
93430
 
93276
93431
  // src/triage/github-pr-labeller.ts
93277
- var import_neverthrow91 = __toESM(require_index_cjs(), 1);
93432
+ var import_neverthrow92 = __toESM(require_index_cjs(), 1);
93278
93433
  async function runAddLabels(octokit, options2) {
93279
93434
  await octokit.issues.addLabels({
93280
93435
  owner: options2.owner,
@@ -93283,7 +93438,7 @@ async function runAddLabels(octokit, options2) {
93283
93438
  labels: [...options2.labels]
93284
93439
  });
93285
93440
  }
93286
- var safeAddLabels = import_neverthrow91.ResultAsync.fromThrowable(
93441
+ var safeAddLabels = import_neverthrow92.ResultAsync.fromThrowable(
93287
93442
  runAddLabels,
93288
93443
  (cause) => ({ type: "LABEL_APPLY_FAILED", cause })
93289
93444
  );
@@ -93323,7 +93478,7 @@ function formatXqaLabels(decision) {
93323
93478
  // src/triage/suite-loader.ts
93324
93479
  var import_promises32 = require("node:fs/promises");
93325
93480
  var import_node_path37 = __toESM(require("node:path"), 1);
93326
- var import_neverthrow92 = __toESM(require_index_cjs(), 1);
93481
+ var import_neverthrow93 = __toESM(require_index_cjs(), 1);
93327
93482
  var SUITE_FILE_SUFFIX = ".suite.json";
93328
93483
  var freestyleEntrySchema2 = external_exports.object({
93329
93484
  timeoutSeconds: external_exports.number().int().positive(),
@@ -93334,7 +93489,7 @@ var suiteFileSchema = external_exports.object({
93334
93489
  freestyle: external_exports.array(freestyleEntrySchema2).optional(),
93335
93490
  hooks: external_exports.record(external_exports.string(), external_exports.unknown()).optional()
93336
93491
  });
93337
- var safeJsonParse6 = (0, import_neverthrow92.fromThrowable)(JSON.parse);
93492
+ var safeJsonParse6 = (0, import_neverthrow93.fromThrowable)(JSON.parse);
93338
93493
  async function runReadFile(filePath) {
93339
93494
  return (0, import_promises32.readFile)(filePath, "utf8");
93340
93495
  }
@@ -93345,28 +93500,28 @@ async function runReadDirectory(filePath) {
93345
93500
  return (0, import_promises32.readdir)(filePath);
93346
93501
  }
93347
93502
  function readSuiteFile(filePath) {
93348
- const safeRead = import_neverthrow92.ResultAsync.fromThrowable(
93503
+ const safeRead = import_neverthrow93.ResultAsync.fromThrowable(
93349
93504
  runReadFile,
93350
93505
  (cause) => ({ type: "SUITE_READ_FAILED", path: filePath, cause })
93351
93506
  );
93352
93507
  return safeRead(filePath);
93353
93508
  }
93354
93509
  function readSpecFile2(filePath) {
93355
- const safeRead = import_neverthrow92.ResultAsync.fromThrowable(
93510
+ const safeRead = import_neverthrow93.ResultAsync.fromThrowable(
93356
93511
  runReadFile,
93357
93512
  () => ({ type: "SPEC_NOT_FOUND", path: filePath })
93358
93513
  );
93359
93514
  return safeRead(filePath);
93360
93515
  }
93361
93516
  function statDirectory(directory) {
93362
- const safeStat = import_neverthrow92.ResultAsync.fromThrowable(
93517
+ const safeStat = import_neverthrow93.ResultAsync.fromThrowable(
93363
93518
  runStat,
93364
93519
  () => ({ type: "SUITE_DIR_MISSING", path: directory })
93365
93520
  );
93366
93521
  return safeStat(directory);
93367
93522
  }
93368
93523
  function readDirectoryEntries(directory) {
93369
- const safeReadDirectory = import_neverthrow92.ResultAsync.fromThrowable(
93524
+ const safeReadDirectory = import_neverthrow93.ResultAsync.fromThrowable(
93370
93525
  runReadDirectory,
93371
93526
  (cause) => ({ type: "SUITE_READ_FAILED", path: directory, cause })
93372
93527
  );
@@ -93375,7 +93530,7 @@ function readDirectoryEntries(directory) {
93375
93530
  function listSuiteFiles(directory) {
93376
93531
  return statDirectory(directory).andThen((stats) => {
93377
93532
  if (!stats.isDirectory()) {
93378
- return (0, import_neverthrow92.errAsync)({ type: "SUITE_DIR_MISSING", path: directory });
93533
+ return (0, import_neverthrow93.errAsync)({ type: "SUITE_DIR_MISSING", path: directory });
93379
93534
  }
93380
93535
  return readDirectoryEntries(directory);
93381
93536
  }).map(
@@ -93385,13 +93540,13 @@ function listSuiteFiles(directory) {
93385
93540
  function parseSuiteFile(filePath, raw) {
93386
93541
  const parsed = safeJsonParse6(raw);
93387
93542
  if (parsed.isErr()) {
93388
- return (0, import_neverthrow92.err)({ type: "SUITE_INVALID", path: filePath, cause: parsed.error });
93543
+ return (0, import_neverthrow93.err)({ type: "SUITE_INVALID", path: filePath, cause: parsed.error });
93389
93544
  }
93390
93545
  const validated = suiteFileSchema.safeParse(parsed.value);
93391
93546
  if (!validated.success) {
93392
- return (0, import_neverthrow92.err)({ type: "SUITE_INVALID", path: filePath, cause: validated.error });
93547
+ return (0, import_neverthrow93.err)({ type: "SUITE_INVALID", path: filePath, cause: validated.error });
93393
93548
  }
93394
- return (0, import_neverthrow92.ok)(validated.data);
93549
+ return (0, import_neverthrow93.ok)(validated.data);
93395
93550
  }
93396
93551
  function suiteIdFromPath(filePath) {
93397
93552
  const name = import_node_path37.default.basename(filePath);
@@ -93402,7 +93557,7 @@ function loadSpecReference(xqaDirectory, specPath) {
93402
93557
  return readSpecFile2(absolute).andThen((raw) => {
93403
93558
  const parsed = parseSpecFrontmatter(raw);
93404
93559
  if (parsed.isErr()) {
93405
- return (0, import_neverthrow92.err)({
93560
+ return (0, import_neverthrow93.err)({
93406
93561
  type: "SPEC_FRONTMATTER_INVALID",
93407
93562
  path: absolute,
93408
93563
  cause: parsed.error.cause
@@ -93410,16 +93565,16 @@ function loadSpecReference(xqaDirectory, specPath) {
93410
93565
  }
93411
93566
  const { feature, timeoutSeconds } = parsed.value;
93412
93567
  if (timeoutSeconds === void 0) {
93413
- return (0, import_neverthrow92.ok)({ path: specPath, feature });
93568
+ return (0, import_neverthrow93.ok)({ path: specPath, feature });
93414
93569
  }
93415
- return (0, import_neverthrow92.ok)({ path: specPath, feature, timeoutSeconds });
93570
+ return (0, import_neverthrow93.ok)({ path: specPath, feature, timeoutSeconds });
93416
93571
  });
93417
93572
  }
93418
93573
  function loadSpecReferences(xqaDirectory, specs) {
93419
93574
  if (specs.length === 0) {
93420
- return (0, import_neverthrow92.okAsync)([]);
93575
+ return (0, import_neverthrow93.okAsync)([]);
93421
93576
  }
93422
- return import_neverthrow92.ResultAsync.combine(specs.map((specPath) => loadSpecReference(xqaDirectory, specPath)));
93577
+ return import_neverthrow93.ResultAsync.combine(specs.map((specPath) => loadSpecReference(xqaDirectory, specPath)));
93423
93578
  }
93424
93579
  function addSpecTokens(tokens, spec) {
93425
93580
  const stem = import_node_path37.default.basename(spec.path).replace(/\.test\.md$/u, "");
@@ -93498,9 +93653,9 @@ function loadXqaSuites(directory) {
93498
93653
  const xqaDirectory = import_node_path37.default.dirname(import_node_path37.default.resolve(directory));
93499
93654
  return listSuiteFiles(directory).andThen((files) => {
93500
93655
  if (files.length === 0) {
93501
- return (0, import_neverthrow92.okAsync)([]);
93656
+ return (0, import_neverthrow93.okAsync)([]);
93502
93657
  }
93503
- return import_neverthrow92.ResultAsync.combine(files.map((file2) => loadSuite(file2, xqaDirectory)));
93658
+ return import_neverthrow93.ResultAsync.combine(files.map((file2) => loadSuite(file2, xqaDirectory)));
93504
93659
  });
93505
93660
  }
93506
93661
 
@@ -93511,27 +93666,27 @@ function parseRepo(input) {
93511
93666
  const parts = input.split("/");
93512
93667
  const [owner, repo] = parts;
93513
93668
  if (parts.length !== 2 || owner === void 0 || owner === "" || repo === void 0 || repo === "") {
93514
- return (0, import_neverthrow93.err)({ type: "CLI_INVALID_ARG", message: `invalid --repo value: ${input}` });
93669
+ return (0, import_neverthrow94.err)({ type: "CLI_INVALID_ARG", message: `invalid --repo value: ${input}` });
93515
93670
  }
93516
- return (0, import_neverthrow93.ok)({ owner, repo });
93671
+ return (0, import_neverthrow94.ok)({ owner, repo });
93517
93672
  }
93518
93673
  function parsePrNumber(input) {
93519
93674
  const parsed = Number.parseInt(input, 10);
93520
93675
  if (!Number.isFinite(parsed) || parsed <= 0) {
93521
- return (0, import_neverthrow93.err)({ type: "CLI_INVALID_ARG", message: `invalid --pr value: ${input}` });
93676
+ return (0, import_neverthrow94.err)({ type: "CLI_INVALID_ARG", message: `invalid --pr value: ${input}` });
93522
93677
  }
93523
- return (0, import_neverthrow93.ok)(parsed);
93678
+ return (0, import_neverthrow94.ok)(parsed);
93524
93679
  }
93525
93680
  function parseCliInputs(options2) {
93526
93681
  const repoResult = parseRepo(options2.repo);
93527
93682
  if (repoResult.isErr()) {
93528
- return (0, import_neverthrow93.err)(repoResult.error);
93683
+ return (0, import_neverthrow94.err)(repoResult.error);
93529
93684
  }
93530
93685
  const prResult = parsePrNumber(options2.pr);
93531
93686
  if (prResult.isErr()) {
93532
- return (0, import_neverthrow93.err)(prResult.error);
93687
+ return (0, import_neverthrow94.err)(prResult.error);
93533
93688
  }
93534
- return (0, import_neverthrow93.ok)({
93689
+ return (0, import_neverthrow94.ok)({
93535
93690
  owner: repoResult.value.owner,
93536
93691
  repo: repoResult.value.repo,
93537
93692
  prNumber: prResult.value
@@ -93539,23 +93694,23 @@ function parseCliInputs(options2) {
93539
93694
  }
93540
93695
  function resolveGithubToken(context) {
93541
93696
  if (!context.rootConfig.agents.triager.enabled) {
93542
- return (0, import_neverthrow93.err)({ type: "TRIAGER_DISABLED" });
93697
+ return (0, import_neverthrow94.err)({ type: "TRIAGER_DISABLED" });
93543
93698
  }
93544
93699
  if (context.config.GITHUB_TOKEN === void 0) {
93545
- return (0, import_neverthrow93.err)({ type: "CONFIG_MISSING", key: "GITHUB_TOKEN" });
93700
+ return (0, import_neverthrow94.err)({ type: "CONFIG_MISSING", key: "GITHUB_TOKEN" });
93546
93701
  }
93547
- return (0, import_neverthrow93.ok)(context.config.GITHUB_TOKEN);
93702
+ return (0, import_neverthrow94.ok)(context.config.GITHUB_TOKEN);
93548
93703
  }
93549
93704
  function buildInputs(options2, context) {
93550
93705
  const tokenResult = resolveGithubToken(context);
93551
93706
  if (tokenResult.isErr()) {
93552
- return (0, import_neverthrow93.err)(tokenResult.error);
93707
+ return (0, import_neverthrow94.err)(tokenResult.error);
93553
93708
  }
93554
93709
  const parsed = parseCliInputs(options2);
93555
93710
  if (parsed.isErr()) {
93556
- return (0, import_neverthrow93.err)(parsed.error);
93711
+ return (0, import_neverthrow94.err)(parsed.error);
93557
93712
  }
93558
- return (0, import_neverthrow93.ok)({
93713
+ return (0, import_neverthrow94.ok)({
93559
93714
  owner: parsed.value.owner,
93560
93715
  repo: parsed.value.repo,
93561
93716
  prNumber: parsed.value.prNumber,
@@ -93583,7 +93738,7 @@ function callTriager(options2) {
93583
93738
  }
93584
93739
  function maybeApplyLabels(inputs, labels) {
93585
93740
  if (!inputs.applyLabels || labels.length === 0) {
93586
- return import_neverthrow93.ResultAsync.fromSafePromise(Promise.resolve(labels));
93741
+ return import_neverthrow94.ResultAsync.fromSafePromise(Promise.resolve(labels));
93587
93742
  }
93588
93743
  return applyPullRequestLabels({
93589
93744
  owner: inputs.owner,
@@ -93594,7 +93749,7 @@ function maybeApplyLabels(inputs, labels) {
93594
93749
  }).map(() => labels);
93595
93750
  }
93596
93751
  function runPipeline5(inputs) {
93597
- return import_neverthrow93.ResultAsync.combine([
93752
+ return import_neverthrow94.ResultAsync.combine([
93598
93753
  loadXqaSuites(inputs.suitesDir),
93599
93754
  fetchPullRequestDiff({
93600
93755
  owner: inputs.owner,
@@ -93691,7 +93846,7 @@ var rootConfigSchema = external_exports.object({
93691
93846
  var import_node_path38 = __toESM(require("node:path"), 1);
93692
93847
  var import_node_url2 = require("node:url");
93693
93848
  var import_dotenv = __toESM(require_main(), 1);
93694
- var import_neverthrow94 = __toESM(require_index_cjs(), 1);
93849
+ var import_neverthrow95 = __toESM(require_index_cjs(), 1);
93695
93850
 
93696
93851
  // src/config-schema.ts
93697
93852
  var configSchema = external_exports.object({
@@ -93709,15 +93864,15 @@ function loadConfig2() {
93709
93864
  const messages = result.error.issues.map(
93710
93865
  (issue2) => ` - ${issue2.path.join(".")}: ${issue2.message}`
93711
93866
  );
93712
- return (0, import_neverthrow94.err)({ type: "INVALID_CONFIG", message: `Configuration error:
93867
+ return (0, import_neverthrow95.err)({ type: "INVALID_CONFIG", message: `Configuration error:
93713
93868
  ${messages.join("\n")}` });
93714
93869
  }
93715
- return (0, import_neverthrow94.ok)(result.data);
93870
+ return (0, import_neverthrow95.ok)(result.data);
93716
93871
  }
93717
93872
 
93718
93873
  // src/pid-lock.ts
93719
93874
  var import_node_fs13 = require("node:fs");
93720
- var import_neverthrow95 = __toESM(require_index_cjs(), 1);
93875
+ var import_neverthrow96 = __toESM(require_index_cjs(), 1);
93721
93876
  var PID_FILE = "/tmp/xqa.pid";
93722
93877
  var SIGINT_EXIT_CODE = 130;
93723
93878
  var SIGTERM_EXIT_CODE = 143;
@@ -93726,7 +93881,7 @@ var HARD_TIMEOUT_MS = 1e4;
93726
93881
  var cleanup = () => {
93727
93882
  (0, import_node_fs13.rmSync)(PID_FILE, { force: true });
93728
93883
  };
93729
- var checkProcessRunning = (0, import_neverthrow95.fromThrowable)(
93884
+ var checkProcessRunning = (0, import_neverthrow96.fromThrowable)(
93730
93885
  (pid) => {
93731
93886
  process.kill(pid, 0);
93732
93887
  return true;
@@ -93793,16 +93948,16 @@ function acquireLock() {
93793
93948
  function loadCliContext(signal) {
93794
93949
  const configResult = loadConfig2();
93795
93950
  if (configResult.isErr()) {
93796
- return (0, import_neverthrow96.err)(configResult.error);
93951
+ return (0, import_neverthrow97.err)(configResult.error);
93797
93952
  }
93798
93953
  const rootConfigResult = loadConfigSync({
93799
93954
  cwd: process.cwd(),
93800
93955
  schema: rootConfigSchema
93801
93956
  });
93802
93957
  if (rootConfigResult.isErr()) {
93803
- return (0, import_neverthrow96.err)(rootConfigResult.error);
93958
+ return (0, import_neverthrow97.err)(rootConfigResult.error);
93804
93959
  }
93805
- return (0, import_neverthrow96.ok)({
93960
+ return (0, import_neverthrow97.ok)({
93806
93961
  config: configResult.value,
93807
93962
  rootConfig: rootConfigResult.value,
93808
93963
  signal
@@ -93834,7 +93989,7 @@ function buildProgram(options2) {
93834
93989
 
93835
93990
  // src/index.ts
93836
93991
  process.title = "xqa";
93837
- var version2 = `${"5.0.0"}${false ? ` (dev build +${"1701986"})` : ""}`;
93992
+ var version2 = `${"5.1.0"}${false ? ` (dev build +${"7bb7ba0"})` : ""}`;
93838
93993
  var program2 = buildProgram({ version: version2 });
93839
93994
  void program2.parseAsync(process.argv);
93840
93995
  /*! Bundled license information: