@exodus/xqa 4.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/README.md +3 -0
- package/dist/skills/xqa-test-plan/SKILL.md +20 -3
- package/dist/xqa.cjs +508 -441
- package/package.json +4 -4
package/dist/xqa.cjs
CHANGED
|
@@ -31961,12 +31961,14 @@ agents:
|
|
|
31961
31961
|
# App under test build environment. 'dev' disables reporting debug overlays as bugs.
|
|
31962
31962
|
buildEnv: dev
|
|
31963
31963
|
capabilities:
|
|
31964
|
-
# Record the simulator screen as MP4
|
|
31964
|
+
# Record the simulator screen as HEVC MP4 via simctl (no inline ffmpeg pass). Off by default \u2014 CI-heavy.
|
|
31965
31965
|
videoRecording: false
|
|
31966
31966
|
# Register the view_ui MCP tool so the explorer can inspect the accessibility tree. On by default; disable to reduce tool surface.
|
|
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.
|
|
@@ -45971,19 +45973,6 @@ function initConfig(options2) {
|
|
|
45971
45973
|
});
|
|
45972
45974
|
}
|
|
45973
45975
|
|
|
45974
|
-
// ../../packages/config/dist/shell/legacy-env-detector.js
|
|
45975
|
-
var LEGACY_ENV_VARS = [
|
|
45976
|
-
"QA_RUN_ID",
|
|
45977
|
-
"QA_EXPLORE_TIMEOUT_SECONDS",
|
|
45978
|
-
"QA_BUILD_ENV",
|
|
45979
|
-
"QA_DISMISSALS_PATH",
|
|
45980
|
-
"XQA_SUITES_DIR",
|
|
45981
|
-
"XQA_CWD"
|
|
45982
|
-
];
|
|
45983
|
-
function detectLegacyEnv(env3) {
|
|
45984
|
-
return LEGACY_ENV_VARS.filter((name) => env3[name] !== void 0);
|
|
45985
|
-
}
|
|
45986
|
-
|
|
45987
45976
|
// ../../packages/config/dist/shell/loader.js
|
|
45988
45977
|
var import_node_fs = require("node:fs");
|
|
45989
45978
|
var import_node_path3 = __toESM(require("node:path"), 1);
|
|
@@ -46027,19 +46016,11 @@ function loadConfigSync(options2) {
|
|
|
46027
46016
|
if (readResult.isErr()) {
|
|
46028
46017
|
return (0, import_neverthrow4.err)(readResult.error);
|
|
46029
46018
|
}
|
|
46030
|
-
|
|
46019
|
+
return parseAndValidateSync({
|
|
46031
46020
|
schema: options2.schema,
|
|
46032
46021
|
text: readResult.value,
|
|
46033
46022
|
filePath
|
|
46034
46023
|
});
|
|
46035
|
-
if (validated.isErr()) {
|
|
46036
|
-
return (0, import_neverthrow4.err)(validated.error);
|
|
46037
|
-
}
|
|
46038
|
-
const legacy = detectLegacyEnv(options2.env);
|
|
46039
|
-
if (legacy.length > 0) {
|
|
46040
|
-
return (0, import_neverthrow4.err)({ type: "LEGACY_ENV_DETECTED", vars: [...legacy] });
|
|
46041
|
-
}
|
|
46042
|
-
return (0, import_neverthrow4.ok)(validated.value);
|
|
46043
46024
|
}
|
|
46044
46025
|
|
|
46045
46026
|
// ../../node_modules/.pnpm/commander@14.0.3/node_modules/commander/esm.mjs
|
|
@@ -46060,15 +46041,9 @@ var {
|
|
|
46060
46041
|
} = import_index.default;
|
|
46061
46042
|
|
|
46062
46043
|
// src/bootstrap.ts
|
|
46063
|
-
var
|
|
46044
|
+
var import_neverthrow97 = __toESM(require_index_cjs(), 1);
|
|
46064
46045
|
|
|
46065
46046
|
// src/config/error-formatter.ts
|
|
46066
|
-
function formatLegacyVariables(variables) {
|
|
46067
|
-
const lines = variables.map((name) => ` ${name}`).join("\n");
|
|
46068
|
-
return `Legacy environment variables detected:
|
|
46069
|
-
${lines}
|
|
46070
|
-
Move these values into .xqa/config.yaml.`;
|
|
46071
|
-
}
|
|
46072
46047
|
function formatIssues(issues) {
|
|
46073
46048
|
const lines = issues.map((issue2) => ` ${issue2.path.join(".")}: ${issue2.message}`).join("\n");
|
|
46074
46049
|
return `Config validation failed:
|
|
@@ -46095,9 +46070,6 @@ function formatConfigError(error48) {
|
|
|
46095
46070
|
return `Config file not found: ${error48.path}
|
|
46096
46071
|
Run \`xqa init\` to generate it.`;
|
|
46097
46072
|
}
|
|
46098
|
-
case "LEGACY_ENV_DETECTED": {
|
|
46099
|
-
return formatLegacyVariables(error48.vars);
|
|
46100
|
-
}
|
|
46101
46073
|
case "CONFIG_SCHEMA_INVALID": {
|
|
46102
46074
|
return formatIssues(error48.issues);
|
|
46103
46075
|
}
|
|
@@ -63987,6 +63959,41 @@ function createPressButtonTool(udid = "booted") {
|
|
|
63987
63959
|
async ({ button }) => handlePressButton(udid, button)
|
|
63988
63960
|
);
|
|
63989
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
|
+
}
|
|
63990
63997
|
var cache2 = /* @__PURE__ */ new Map();
|
|
63991
63998
|
function parseDeviceInfo(raw) {
|
|
63992
63999
|
const parsed = JSON.parse(raw);
|
|
@@ -64226,25 +64233,29 @@ function discoverBootedSimulators() {
|
|
|
64226
64233
|
function checkIdbAvailable() {
|
|
64227
64234
|
return runCommand("which", ["idb"]).mapErr(() => ({ type: "IDB_NOT_FOUND" }));
|
|
64228
64235
|
}
|
|
64229
|
-
function
|
|
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)] : [];
|
|
64230
64255
|
return xx({
|
|
64231
64256
|
name: "mobile-ios",
|
|
64232
64257
|
version: "0.0.0",
|
|
64233
|
-
tools: [
|
|
64234
|
-
createScreenshotTool(udid),
|
|
64235
|
-
createAccessibilitySnapshotTool(udid),
|
|
64236
|
-
createTapTool(udid),
|
|
64237
|
-
createDoubleTapTool(udid),
|
|
64238
|
-
createLongPressTool(udid),
|
|
64239
|
-
createSwipeTool(udid),
|
|
64240
|
-
createTypeTextTool(udid),
|
|
64241
|
-
createPressButtonTool(udid),
|
|
64242
|
-
createLaunchAppTool(udid),
|
|
64243
|
-
createTerminateAppTool(udid),
|
|
64244
|
-
createListAppsTool(udid),
|
|
64245
|
-
createWaitSecondsTool(),
|
|
64246
|
-
...extraTools
|
|
64247
|
-
]
|
|
64258
|
+
tools: [...buildBaseTools(udid), ...pasteboardTools, ...extraTools]
|
|
64248
64259
|
});
|
|
64249
64260
|
}
|
|
64250
64261
|
|
|
@@ -67636,7 +67647,7 @@ var analyserConfigSchema = agentBaseConfigSchema.extend({ enabled: external_expo
|
|
|
67636
67647
|
|
|
67637
67648
|
// ../../packages/pipeline/dist/index.js
|
|
67638
67649
|
var import_neverthrow40 = __toESM(require_index_cjs(), 1);
|
|
67639
|
-
var
|
|
67650
|
+
var import_promises19 = require("node:timers/promises");
|
|
67640
67651
|
|
|
67641
67652
|
// ../../agents/consolidator/dist/index.js
|
|
67642
67653
|
var import_neverthrow19 = __toESM(require_index_cjs(), 1);
|
|
@@ -73783,7 +73794,7 @@ var consolidatorConfigSchema = agentBaseConfigSchema.extend({ enabled: external_
|
|
|
73783
73794
|
// ../../packages/pipeline/dist/index.js
|
|
73784
73795
|
var import_neverthrow41 = __toESM(require_index_cjs(), 1);
|
|
73785
73796
|
var import_neverthrow42 = __toESM(require_index_cjs(), 1);
|
|
73786
|
-
var
|
|
73797
|
+
var import_promises20 = require("node:timers/promises");
|
|
73787
73798
|
|
|
73788
73799
|
// ../../agents/explorer/dist/index.js
|
|
73789
73800
|
var import_neverthrow22 = __toESM(require_index_cjs(), 1);
|
|
@@ -73800,16 +73811,14 @@ var import_neverthrow26 = __toESM(require_index_cjs(), 1);
|
|
|
73800
73811
|
var import_node_child_process3 = require("node:child_process");
|
|
73801
73812
|
var import_promises15 = require("node:fs/promises");
|
|
73802
73813
|
var import_neverthrow27 = __toESM(require_index_cjs(), 1);
|
|
73803
|
-
var import_promises16 = require("node:fs/promises");
|
|
73804
|
-
var import_node_path10 = __toESM(require("node:path"), 1);
|
|
73805
73814
|
var import_neverthrow28 = __toESM(require_index_cjs(), 1);
|
|
73806
73815
|
var import_node_child_process4 = require("node:child_process");
|
|
73807
73816
|
var import_node_fs2 = require("node:fs");
|
|
73808
|
-
var
|
|
73817
|
+
var import_node_path10 = __toESM(require("node:path"), 1);
|
|
73809
73818
|
var import_neverthrow29 = __toESM(require_index_cjs(), 1);
|
|
73810
73819
|
var import_neverthrow30 = __toESM(require_index_cjs(), 1);
|
|
73811
|
-
var
|
|
73812
|
-
var
|
|
73820
|
+
var import_promises16 = require("node:fs/promises");
|
|
73821
|
+
var import_node_path11 = __toESM(require("node:path"), 1);
|
|
73813
73822
|
var import_neverthrow31 = __toESM(require_index_cjs(), 1);
|
|
73814
73823
|
var INTERRUPT_DRAIN_TIMEOUT_MS = 1e4;
|
|
73815
73824
|
async function interruptOrTimeout(queryRunner) {
|
|
@@ -74446,8 +74455,12 @@ function buildReportFindingTool(config2, state) {
|
|
|
74446
74455
|
}
|
|
74447
74456
|
function buildMobileIosServer(config2, state) {
|
|
74448
74457
|
const reportFindingTool = buildReportFindingTool(config2, state);
|
|
74458
|
+
const enableReadPasteboard = config2.capabilities.readPasteboard;
|
|
74449
74459
|
if (!config2.capabilities.viewUiServer) {
|
|
74450
|
-
return createMobileIosServer(config2.udid ?? "booted",
|
|
74460
|
+
return createMobileIosServer(config2.udid ?? "booted", {
|
|
74461
|
+
extraTools: [reportFindingTool],
|
|
74462
|
+
enableReadPasteboard
|
|
74463
|
+
});
|
|
74451
74464
|
}
|
|
74452
74465
|
const viewUiTool = createViewUiTool({
|
|
74453
74466
|
udid: config2.udid,
|
|
@@ -74456,15 +74469,23 @@ function buildMobileIosServer(config2, state) {
|
|
|
74456
74469
|
onEvent: config2.onEvent,
|
|
74457
74470
|
screenshotsDir: config2.screenshotsDir
|
|
74458
74471
|
});
|
|
74459
|
-
return createMobileIosServer(config2.udid ?? "booted",
|
|
74472
|
+
return createMobileIosServer(config2.udid ?? "booted", {
|
|
74473
|
+
extraTools: [viewUiTool, reportFindingTool],
|
|
74474
|
+
enableReadPasteboard
|
|
74475
|
+
});
|
|
74460
74476
|
}
|
|
74461
|
-
function
|
|
74462
|
-
const
|
|
74477
|
+
function buildAllowedTools(config2) {
|
|
74478
|
+
const tools = [
|
|
74463
74479
|
...config2.allowedTools ?? [],
|
|
74464
74480
|
REPORT_FINDING_TOOL_NAME,
|
|
74465
|
-
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
|
|
74466
74484
|
];
|
|
74467
|
-
|
|
74485
|
+
return tools.filter((tool3) => typeof tool3 === "string");
|
|
74486
|
+
}
|
|
74487
|
+
function setupQuery(config2) {
|
|
74488
|
+
const allowedTools = buildAllowedTools(config2);
|
|
74468
74489
|
const inputQueue = new MessageQueue();
|
|
74469
74490
|
const state = buildAgentState({ config: config2, inputQueue });
|
|
74470
74491
|
const mobileIosServer = buildMobileIosServer(config2, state);
|
|
@@ -74529,14 +74550,13 @@ function runQuery(prompt, config2) {
|
|
|
74529
74550
|
function collectAgentOutput(prompt, config2) {
|
|
74530
74551
|
return runQuery(prompt, config2).mapErr((cause) => ({ type: "QUERY_FAILED", cause }));
|
|
74531
74552
|
}
|
|
74532
|
-
var VIDEO_OUTPUT_FPS = 10;
|
|
74533
74553
|
function spawnRecorder(outputPath) {
|
|
74534
74554
|
const safeMkdirSync = (0, import_neverthrow29.fromThrowable)(import_node_fs2.mkdirSync, (cause) => cause);
|
|
74535
74555
|
const safeSpawn2 = (0, import_neverthrow29.fromThrowable)(
|
|
74536
74556
|
(command, arguments_) => (0, import_node_child_process4.spawn)(command, arguments_),
|
|
74537
74557
|
(cause) => cause
|
|
74538
74558
|
);
|
|
74539
|
-
const mkdirResult = safeMkdirSync(
|
|
74559
|
+
const mkdirResult = safeMkdirSync(import_node_path10.default.dirname(outputPath), { recursive: true });
|
|
74540
74560
|
if (mkdirResult.isErr()) {
|
|
74541
74561
|
return mkdirResult.error;
|
|
74542
74562
|
}
|
|
@@ -74545,7 +74565,7 @@ function spawnRecorder(outputPath) {
|
|
|
74545
74565
|
"io",
|
|
74546
74566
|
"booted",
|
|
74547
74567
|
"recordVideo",
|
|
74548
|
-
"--codec=
|
|
74568
|
+
"--codec=hevc",
|
|
74549
74569
|
"--mask=ignored",
|
|
74550
74570
|
"--force",
|
|
74551
74571
|
outputPath
|
|
@@ -74582,17 +74602,6 @@ function waitForRecordingStart(proc) {
|
|
|
74582
74602
|
(cause) => ({ type: "SPAWN_FAILED", cause })
|
|
74583
74603
|
);
|
|
74584
74604
|
}
|
|
74585
|
-
async function runFfmpeg(arguments_) {
|
|
74586
|
-
const { promise: promise2, resolve, reject } = Promise.withResolvers();
|
|
74587
|
-
(0, import_node_child_process4.execFile)("ffmpeg", [...arguments_], (error48) => {
|
|
74588
|
-
if (error48) {
|
|
74589
|
-
reject(error48);
|
|
74590
|
-
} else {
|
|
74591
|
-
resolve(true);
|
|
74592
|
-
}
|
|
74593
|
-
});
|
|
74594
|
-
await promise2;
|
|
74595
|
-
}
|
|
74596
74605
|
function startRecording(outputPath) {
|
|
74597
74606
|
const procOrError = spawnRecorder(outputPath);
|
|
74598
74607
|
if (procOrError instanceof Error) {
|
|
@@ -74616,72 +74625,29 @@ function stopRecording(handle) {
|
|
|
74616
74625
|
(cause) => ({ type: "STOP_FAILED", cause })
|
|
74617
74626
|
);
|
|
74618
74627
|
}
|
|
74619
|
-
function reencodeVideo({
|
|
74620
|
-
inputPath,
|
|
74621
|
-
outputPath,
|
|
74622
|
-
fps
|
|
74623
|
-
}) {
|
|
74624
|
-
const safeRunFfmpeg = (0, import_neverthrow29.fromAsyncThrowable)(
|
|
74625
|
-
runFfmpeg,
|
|
74626
|
-
(cause) => ({ type: "REENCODE_FAILED", cause })
|
|
74627
|
-
);
|
|
74628
|
-
return safeRunFfmpeg([
|
|
74629
|
-
"-y",
|
|
74630
|
-
"-fflags",
|
|
74631
|
-
"+genpts",
|
|
74632
|
-
"-i",
|
|
74633
|
-
inputPath,
|
|
74634
|
-
"-vf",
|
|
74635
|
-
`fps=${String(fps)}`,
|
|
74636
|
-
"-fps_mode",
|
|
74637
|
-
"cfr",
|
|
74638
|
-
"-c:v",
|
|
74639
|
-
"h264_videotoolbox",
|
|
74640
|
-
"-an",
|
|
74641
|
-
outputPath
|
|
74642
|
-
]).map(() => outputPath);
|
|
74643
|
-
}
|
|
74644
74628
|
var toRecordingError = (cause) => ({
|
|
74645
74629
|
type: "RECORDING_FAILED",
|
|
74646
74630
|
cause
|
|
74647
74631
|
});
|
|
74648
|
-
function rawPathFor(videoPath) {
|
|
74649
|
-
const extension = import_node_path10.default.extname(videoPath);
|
|
74650
|
-
const base = extension.length > 0 ? videoPath.slice(0, -extension.length) : videoPath;
|
|
74651
|
-
return `${base}.raw.mov`;
|
|
74652
|
-
}
|
|
74653
|
-
var safeUnlink = (0, import_neverthrow28.fromAsyncThrowable)(
|
|
74654
|
-
import_promises16.unlink,
|
|
74655
|
-
(cause) => ({ type: "REENCODE_FAILED", cause })
|
|
74656
|
-
);
|
|
74657
|
-
function tryUnlink(target) {
|
|
74658
|
-
return safeUnlink(target).map(() => true).orElse(() => (0, import_neverthrow28.okAsync)(true));
|
|
74659
|
-
}
|
|
74660
|
-
function finalizeVideo(rawPath, videoPath) {
|
|
74661
|
-
return reencodeVideo({ inputPath: rawPath, outputPath: videoPath, fps: VIDEO_OUTPUT_FPS }).mapErr(toRecordingError).andThen(() => tryUnlink(rawPath)).map(() => true);
|
|
74662
|
-
}
|
|
74663
74632
|
function stopAndPropagate(handle, originalError) {
|
|
74664
74633
|
return stopRecording(handle).mapErr(toRecordingError).andThen(() => (0, import_neverthrow28.errAsync)(originalError)).orElse(() => (0, import_neverthrow28.errAsync)(originalError));
|
|
74665
74634
|
}
|
|
74666
74635
|
function runWithRecording({
|
|
74667
74636
|
handle,
|
|
74668
|
-
rawPath,
|
|
74669
|
-
videoPath,
|
|
74670
74637
|
collectOutput
|
|
74671
74638
|
}) {
|
|
74672
74639
|
return collectOutput().orElse((error48) => stopAndPropagate(handle, error48)).andThen(
|
|
74673
74640
|
(result) => stopRecording(handle).mapErr(toRecordingError).map(() => result)
|
|
74674
|
-
)
|
|
74641
|
+
);
|
|
74675
74642
|
}
|
|
74676
74643
|
function startAndRun(params) {
|
|
74677
74644
|
const { videoPath, signal, collectOutput } = params;
|
|
74678
|
-
|
|
74679
|
-
return startRecording(rawPath).mapErr(toRecordingError).andThen((handle) => {
|
|
74645
|
+
return startRecording(videoPath).mapErr(toRecordingError).andThen((handle) => {
|
|
74680
74646
|
const onAbort = () => {
|
|
74681
74647
|
void stopRecording(handle).unwrapOr(null);
|
|
74682
74648
|
};
|
|
74683
74649
|
signal?.addEventListener("abort", onAbort, { once: true });
|
|
74684
|
-
return runWithRecording({ handle,
|
|
74650
|
+
return runWithRecording({ handle, collectOutput }).map((result) => {
|
|
74685
74651
|
signal?.removeEventListener("abort", onAbort);
|
|
74686
74652
|
return result;
|
|
74687
74653
|
}).mapErr((error48) => {
|
|
@@ -74804,8 +74770,8 @@ ${initialState2}` : void 0,
|
|
|
74804
74770
|
WORKING_STATE_SECTION
|
|
74805
74771
|
].filter((section) => section !== void 0).join("\n\n");
|
|
74806
74772
|
}
|
|
74807
|
-
function buildEnvSection(
|
|
74808
|
-
return
|
|
74773
|
+
function buildEnvSection(buildEnv3) {
|
|
74774
|
+
return buildEnv3 === "dev" ? `
|
|
74809
74775
|
|
|
74810
74776
|
${DEV_ENVIRONMENT_SECTION}` : "";
|
|
74811
74777
|
}
|
|
@@ -74872,9 +74838,9 @@ ${FINDING_TAXONOMY_SECTION}${environmentSection}
|
|
|
74872
74838
|
${reportingSection}`;
|
|
74873
74839
|
}
|
|
74874
74840
|
var FREESTYLE_TEMPLATE = (options2) => {
|
|
74875
|
-
const { appContext, initialState: initialState2, buildEnv:
|
|
74841
|
+
const { appContext, initialState: initialState2, buildEnv: buildEnv3, scenarioId } = options2 ?? {};
|
|
74876
74842
|
const contextBlock = buildContextSections(appContext, initialState2);
|
|
74877
|
-
const environmentSection = buildEnvSection(
|
|
74843
|
+
const environmentSection = buildEnvSection(buildEnv3);
|
|
74878
74844
|
const reportingSection = buildReportFindingSection(scenarioId);
|
|
74879
74845
|
return buildFreestyleBody({ contextBlock, environmentSection, reportingSection });
|
|
74880
74846
|
};
|
|
@@ -75015,10 +74981,10 @@ function generateExplorerPrompt({
|
|
|
75015
74981
|
specs,
|
|
75016
74982
|
appContext,
|
|
75017
74983
|
initialState: initialState2,
|
|
75018
|
-
buildEnv:
|
|
74984
|
+
buildEnv: buildEnv3,
|
|
75019
74985
|
scenarioId
|
|
75020
74986
|
}) {
|
|
75021
|
-
return mode === "spec" ? buildSpecModePrompt(specs, { appContext, initialState: initialState2, buildEnv:
|
|
74987
|
+
return mode === "spec" ? buildSpecModePrompt(specs, { appContext, initialState: initialState2, buildEnv: buildEnv3, scenarioId }) : FREESTYLE_TEMPLATE({ appContext, initialState: initialState2, buildEnv: buildEnv3, scenarioId });
|
|
75022
74988
|
}
|
|
75023
74989
|
var FRONTMATTER_FENCE = "---";
|
|
75024
74990
|
var INLINE_ASSERTION_DELIMITER = " \u2192 ";
|
|
@@ -75168,8 +75134,8 @@ function direntToSpecEntry(directory, entry) {
|
|
|
75168
75134
|
if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
75169
75135
|
return [
|
|
75170
75136
|
{
|
|
75171
|
-
path:
|
|
75172
|
-
name:
|
|
75137
|
+
path: import_node_path11.default.join(directory, entry.name),
|
|
75138
|
+
name: import_node_path11.default.basename(entry.name, import_node_path11.default.extname(entry.name)),
|
|
75173
75139
|
required: true
|
|
75174
75140
|
}
|
|
75175
75141
|
];
|
|
@@ -75177,7 +75143,7 @@ function direntToSpecEntry(directory, entry) {
|
|
|
75177
75143
|
if (entry.isDirectory()) {
|
|
75178
75144
|
return [
|
|
75179
75145
|
{
|
|
75180
|
-
path:
|
|
75146
|
+
path: import_node_path11.default.join(directory, entry.name, "spec.md"),
|
|
75181
75147
|
name: entry.name,
|
|
75182
75148
|
required: false
|
|
75183
75149
|
}
|
|
@@ -75187,7 +75153,7 @@ function direntToSpecEntry(directory, entry) {
|
|
|
75187
75153
|
}
|
|
75188
75154
|
function scanDirectory(directory) {
|
|
75189
75155
|
const safeReaddir5 = (0, import_neverthrow31.fromAsyncThrowable)(
|
|
75190
|
-
async () => (0,
|
|
75156
|
+
async () => (0, import_promises16.readdir)(directory, { withFileTypes: true }),
|
|
75191
75157
|
(cause) => ({ type: "DIR_READ_FAILED", dir: directory, cause })
|
|
75192
75158
|
);
|
|
75193
75159
|
return safeReaddir5().orElse((error48) => isNotFound(error48.cause) ? (0, import_neverthrow31.okAsync)([]) : (0, import_neverthrow31.errAsync)(error48)).map(
|
|
@@ -75201,7 +75167,7 @@ function readEntries(entries) {
|
|
|
75201
75167
|
}
|
|
75202
75168
|
function readEntry(entry) {
|
|
75203
75169
|
const safeReadFile7 = (0, import_neverthrow31.fromAsyncThrowable)(
|
|
75204
|
-
async () => (0,
|
|
75170
|
+
async () => (0, import_promises16.readFile)(entry.path, "utf8"),
|
|
75205
75171
|
(cause) => ({ type: "FILE_READ_FAILED", path: entry.path, cause })
|
|
75206
75172
|
);
|
|
75207
75173
|
return safeReadFile7().map((content) => [{ name: entry.name, content }]).orElse((error48) => entry.required ? (0, import_neverthrow31.errAsync)(error48) : (0, import_neverthrow31.okAsync)([]));
|
|
@@ -75212,7 +75178,7 @@ function specNameFromPath(filePath) {
|
|
|
75212
75178
|
if (fileName2 === "spec.md" && parts.length >= 2) {
|
|
75213
75179
|
return parts.at(-2) ?? fileName2;
|
|
75214
75180
|
}
|
|
75215
|
-
return
|
|
75181
|
+
return import_node_path11.default.basename(fileName2, import_node_path11.default.extname(fileName2));
|
|
75216
75182
|
}
|
|
75217
75183
|
function filterByNames(specs, specNames) {
|
|
75218
75184
|
if (!specNames || specNames.length === 0) {
|
|
@@ -75221,7 +75187,7 @@ function filterByNames(specs, specNames) {
|
|
|
75221
75187
|
return specs.filter((spec) => specNames.includes(spec.name));
|
|
75222
75188
|
}
|
|
75223
75189
|
function resolveSpecs(config2, repoRoot = process.cwd()) {
|
|
75224
|
-
const source = config2.specFiles && config2.specFiles.length > 0 ? loadFromFiles(config2.specFiles) : loadFromDirectory(
|
|
75190
|
+
const source = config2.specFiles && config2.specFiles.length > 0 ? loadFromFiles(config2.specFiles) : loadFromDirectory(import_node_path11.default.join(repoRoot, "openspec", "specs"));
|
|
75225
75191
|
return source.map((specs) => filterByNames(specs, config2.specNames));
|
|
75226
75192
|
}
|
|
75227
75193
|
var ISO_DATE_LENGTH = 10;
|
|
@@ -75340,7 +75306,8 @@ function runExplorer(config2) {
|
|
|
75340
75306
|
var explorerCapabilitiesSchema = external_exports.object({
|
|
75341
75307
|
videoRecording: external_exports.boolean().default(false),
|
|
75342
75308
|
viewUiServer: external_exports.boolean().default(true),
|
|
75343
|
-
findingScreenshots: external_exports.boolean().default(true)
|
|
75309
|
+
findingScreenshots: external_exports.boolean().default(true),
|
|
75310
|
+
readPasteboard: external_exports.boolean().default(false)
|
|
75344
75311
|
}).strict();
|
|
75345
75312
|
var DEFAULT_EXPLORER_CAPABILITIES = explorerCapabilitiesSchema.parse({});
|
|
75346
75313
|
var explorerConfigSchema = agentBaseConfigSchema.extend({
|
|
@@ -75356,7 +75323,7 @@ var import_neverthrow43 = __toESM(require_index_cjs(), 1);
|
|
|
75356
75323
|
|
|
75357
75324
|
// ../../agents/inspector/dist/index.js
|
|
75358
75325
|
var import_neverthrow32 = __toESM(require_index_cjs(), 1);
|
|
75359
|
-
var
|
|
75326
|
+
var import_promises17 = require("node:fs/promises");
|
|
75360
75327
|
var import_neverthrow33 = __toESM(require_index_cjs(), 1);
|
|
75361
75328
|
var import_neverthrow34 = __toESM(require_index_cjs(), 1);
|
|
75362
75329
|
var import_neverthrow35 = __toESM(require_index_cjs(), 1);
|
|
@@ -75364,8 +75331,8 @@ var import_neverthrow36 = __toESM(require_index_cjs(), 1);
|
|
|
75364
75331
|
var import_sharp2 = __toESM(require("sharp"), 1);
|
|
75365
75332
|
var import_neverthrow37 = __toESM(require_index_cjs(), 1);
|
|
75366
75333
|
var import_neverthrow38 = __toESM(require_index_cjs(), 1);
|
|
75367
|
-
var
|
|
75368
|
-
var
|
|
75334
|
+
var import_promises18 = require("node:fs/promises");
|
|
75335
|
+
var import_node_path12 = __toESM(require("node:path"), 1);
|
|
75369
75336
|
|
|
75370
75337
|
// ../../node_modules/.pnpm/js-yaml@4.1.1/node_modules/js-yaml/dist/js-yaml.mjs
|
|
75371
75338
|
function isNothing(subject) {
|
|
@@ -78676,7 +78643,7 @@ async function initArtboardNames({ designStore, config: config2, state }) {
|
|
|
78676
78643
|
}
|
|
78677
78644
|
function readScreenshot(screenshotPath, stepIndex) {
|
|
78678
78645
|
return import_neverthrow33.ResultAsync.fromThrowable(
|
|
78679
|
-
|
|
78646
|
+
import_promises17.readFile,
|
|
78680
78647
|
(cause) => ({ type: "SCREENSHOT_READ_FAILED", stepIndex, cause })
|
|
78681
78648
|
)(screenshotPath);
|
|
78682
78649
|
}
|
|
@@ -78797,7 +78764,7 @@ function parseMeta(raw) {
|
|
|
78797
78764
|
return {};
|
|
78798
78765
|
}
|
|
78799
78766
|
async function readAndParseSidecar(sidecarPath) {
|
|
78800
|
-
const raw = await (0,
|
|
78767
|
+
const raw = await (0, import_promises18.readFile)(sidecarPath, "utf8");
|
|
78801
78768
|
return parseMeta(raw);
|
|
78802
78769
|
}
|
|
78803
78770
|
function readSidecarFile(sidecarPath) {
|
|
@@ -78828,7 +78795,7 @@ var FsDesignStore = class {
|
|
|
78828
78795
|
}
|
|
78829
78796
|
listArtboards() {
|
|
78830
78797
|
return (0, import_neverthrow39.fromAsyncThrowable)(
|
|
78831
|
-
|
|
78798
|
+
import_promises18.readdir,
|
|
78832
78799
|
wrapFsError
|
|
78833
78800
|
)(this.designsDirectory).orElse((fsError) => {
|
|
78834
78801
|
if (fsError.type === "FS_ERROR" && isEnoent(fsError.cause)) {
|
|
@@ -78840,10 +78807,10 @@ var FsDesignStore = class {
|
|
|
78840
78807
|
);
|
|
78841
78808
|
}
|
|
78842
78809
|
getArtboard(filename) {
|
|
78843
|
-
const pngPath =
|
|
78844
|
-
const sidecarPath =
|
|
78810
|
+
const pngPath = import_node_path12.default.join(this.designsDirectory, `${filename}.png`);
|
|
78811
|
+
const sidecarPath = import_node_path12.default.join(this.designsDirectory, `${filename}.meta.yaml`);
|
|
78845
78812
|
return (0, import_neverthrow39.fromAsyncThrowable)(
|
|
78846
|
-
|
|
78813
|
+
import_promises18.readFile,
|
|
78847
78814
|
wrapFsError
|
|
78848
78815
|
)(pngPath).orElse((fsError) => {
|
|
78849
78816
|
if (fsError.type === "FS_ERROR" && isEnoent(fsError.cause)) {
|
|
@@ -78922,7 +78889,7 @@ function runAnalyserWithRetry(params) {
|
|
|
78922
78889
|
),
|
|
78923
78890
|
{
|
|
78924
78891
|
config: { maxAttempts: RETRY_MAX_ATTEMPTS, baseDelayMs: RETRY_BASE_DELAY_MS },
|
|
78925
|
-
delayFunction:
|
|
78892
|
+
delayFunction: import_promises19.setTimeout,
|
|
78926
78893
|
onRetry: ({ attempt, maxAttempts, delayMs, error: error48 }) => {
|
|
78927
78894
|
onEvent?.({
|
|
78928
78895
|
type: "AGENT_RETRY",
|
|
@@ -79083,7 +79050,7 @@ function runExplorerWithRetry(options2) {
|
|
|
79083
79050
|
const { explorerConfig, udid, onEvent } = options2;
|
|
79084
79051
|
return withRetry(() => runExplorerWithTeardown(explorerConfig, udid), {
|
|
79085
79052
|
config: { maxAttempts: RETRY_MAX_ATTEMPTS, baseDelayMs: RETRY_BASE_DELAY_MS },
|
|
79086
|
-
delayFunction:
|
|
79053
|
+
delayFunction: import_promises20.setTimeout,
|
|
79087
79054
|
onRetry: ({ attempt, maxAttempts, delayMs, error: error48 }) => {
|
|
79088
79055
|
onEvent?.({
|
|
79089
79056
|
type: "AGENT_RETRY",
|
|
@@ -79836,16 +79803,16 @@ function parseVerboseOption(value) {
|
|
|
79836
79803
|
|
|
79837
79804
|
// src/shell/xqa-directory.ts
|
|
79838
79805
|
var import_node_fs6 = require("node:fs");
|
|
79839
|
-
var
|
|
79806
|
+
var import_node_path13 = __toESM(require("node:path"), 1);
|
|
79840
79807
|
var import_neverthrow51 = __toESM(require_index_cjs(), 1);
|
|
79841
79808
|
function findXqaDirectory(startDirectory) {
|
|
79842
79809
|
let current = startDirectory;
|
|
79843
79810
|
for (; ; ) {
|
|
79844
|
-
const candidate =
|
|
79811
|
+
const candidate = import_node_path13.default.join(current, ".xqa");
|
|
79845
79812
|
if ((0, import_node_fs6.existsSync)(candidate)) {
|
|
79846
79813
|
return (0, import_neverthrow51.ok)(candidate);
|
|
79847
79814
|
}
|
|
79848
|
-
const parent =
|
|
79815
|
+
const parent = import_node_path13.default.dirname(current);
|
|
79849
79816
|
if (parent === current) {
|
|
79850
79817
|
return (0, import_neverthrow51.err)({ type: "XQA_NOT_INITIALIZED" });
|
|
79851
79818
|
}
|
|
@@ -79864,7 +79831,7 @@ function resolveXqaDirectory() {
|
|
|
79864
79831
|
}
|
|
79865
79832
|
|
|
79866
79833
|
// src/commands/explore/pipeline-config.ts
|
|
79867
|
-
var
|
|
79834
|
+
var import_node_path14 = __toESM(require("node:path"), 1);
|
|
79868
79835
|
function resolveTimeoutMs({
|
|
79869
79836
|
input,
|
|
79870
79837
|
rootConfig
|
|
@@ -79919,7 +79886,7 @@ function buildPipelineConfig({
|
|
|
79919
79886
|
simulatorUdid
|
|
79920
79887
|
}) {
|
|
79921
79888
|
const base = {
|
|
79922
|
-
outputDir:
|
|
79889
|
+
outputDir: import_node_path14.default.join(xqaDirectory, "output"),
|
|
79923
79890
|
runId: rootConfig.run.id,
|
|
79924
79891
|
simulatorUdid,
|
|
79925
79892
|
onEvent,
|
|
@@ -79932,7 +79899,7 @@ function buildPipelineConfig({
|
|
|
79932
79899
|
|
|
79933
79900
|
// src/core/last-path.ts
|
|
79934
79901
|
var import_node_fs7 = require("node:fs");
|
|
79935
|
-
var
|
|
79902
|
+
var import_node_path15 = __toESM(require("node:path"), 1);
|
|
79936
79903
|
var import_neverthrow52 = __toESM(require_index_cjs(), 1);
|
|
79937
79904
|
function resolveLastPath(argument, stateContent) {
|
|
79938
79905
|
if (argument !== void 0) {
|
|
@@ -79945,7 +79912,7 @@ function resolveLastPath(argument, stateContent) {
|
|
|
79945
79912
|
return (0, import_neverthrow52.err)({ type: "NO_ARG_AND_NO_STATE" });
|
|
79946
79913
|
}
|
|
79947
79914
|
function lastPathFilePath(xqaDirectoryectory) {
|
|
79948
|
-
return
|
|
79915
|
+
return import_node_path15.default.join(xqaDirectoryectory, "last-findings-path");
|
|
79949
79916
|
}
|
|
79950
79917
|
function writeLastPath(xqaDirectory, findingsPath) {
|
|
79951
79918
|
(0, import_node_fs7.writeFileSync)(lastPathFilePath(xqaDirectory), findingsPath);
|
|
@@ -80065,8 +80032,8 @@ function buildExploreRunState({
|
|
|
80065
80032
|
}
|
|
80066
80033
|
|
|
80067
80034
|
// src/shell/app-context.ts
|
|
80068
|
-
var
|
|
80069
|
-
var
|
|
80035
|
+
var import_promises21 = require("node:fs/promises");
|
|
80036
|
+
var import_node_path16 = __toESM(require("node:path"), 1);
|
|
80070
80037
|
var import_neverthrow55 = __toESM(require_index_cjs(), 1);
|
|
80071
80038
|
var HTML_COMMENT_PATTERN = /<!--[\s\S]*?-->/g;
|
|
80072
80039
|
function isEnoentError(value) {
|
|
@@ -80080,7 +80047,7 @@ function absentContext() {
|
|
|
80080
80047
|
return (0, import_neverthrow55.ok)(absent);
|
|
80081
80048
|
}
|
|
80082
80049
|
var safeReadFile2 = import_neverthrow55.ResultAsync.fromThrowable(
|
|
80083
|
-
async (filePath) => (0,
|
|
80050
|
+
async (filePath) => (0, import_promises21.readFile)(filePath, "utf8"),
|
|
80084
80051
|
toAppContextError
|
|
80085
80052
|
);
|
|
80086
80053
|
function stripAndNormalize(content) {
|
|
@@ -80088,7 +80055,7 @@ function stripAndNormalize(content) {
|
|
|
80088
80055
|
return stripped.length === 0 ? void 0 : stripped;
|
|
80089
80056
|
}
|
|
80090
80057
|
function readContextFile(xqaDirectory, filename) {
|
|
80091
|
-
const filePath =
|
|
80058
|
+
const filePath = import_node_path16.default.join(xqaDirectory, filename);
|
|
80092
80059
|
return safeReadFile2(filePath).map((content) => stripAndNormalize(content)).orElse((error48) => {
|
|
80093
80060
|
if (isEnoentError(error48.cause)) {
|
|
80094
80061
|
return absentContext();
|
|
@@ -80233,21 +80200,21 @@ function registerExploreCommand(program3, loader2) {
|
|
|
80233
80200
|
|
|
80234
80201
|
// src/commands/init-command.ts
|
|
80235
80202
|
var import_node_fs9 = require("node:fs");
|
|
80236
|
-
var
|
|
80203
|
+
var import_node_path18 = __toESM(require("node:path"), 1);
|
|
80237
80204
|
|
|
80238
80205
|
// src/commands/install-skills.ts
|
|
80239
80206
|
var import_node_child_process5 = require("node:child_process");
|
|
80240
80207
|
var import_node_fs8 = require("node:fs");
|
|
80241
|
-
var
|
|
80208
|
+
var import_node_path17 = __toESM(require("node:path"), 1);
|
|
80242
80209
|
var import_node_url = require("node:url");
|
|
80243
80210
|
function resolveSkillsRoot() {
|
|
80244
|
-
const packageDistributionDirectory =
|
|
80245
|
-
return
|
|
80211
|
+
const packageDistributionDirectory = import_node_path17.default.dirname((0, import_node_url.fileURLToPath)(__importMetaUrl));
|
|
80212
|
+
return import_node_path17.default.join(packageDistributionDirectory, "skills");
|
|
80246
80213
|
}
|
|
80247
80214
|
function installSkills() {
|
|
80248
80215
|
const skillsRoot = resolveSkillsRoot();
|
|
80249
80216
|
for (const skill of (0, import_node_fs8.readdirSync)(skillsRoot)) {
|
|
80250
|
-
(0, import_node_child_process5.spawnSync)("npx", ["skills", "add",
|
|
80217
|
+
(0, import_node_child_process5.spawnSync)("npx", ["skills", "add", import_node_path17.default.join(skillsRoot, skill), "-y"], {
|
|
80251
80218
|
stdio: "inherit"
|
|
80252
80219
|
});
|
|
80253
80220
|
}
|
|
@@ -80259,7 +80226,7 @@ var GITIGNORE_CONTENT = `/output
|
|
|
80259
80226
|
`;
|
|
80260
80227
|
var TEST_PLAN_IGNORE_LINE = ".xqa/test-plan/";
|
|
80261
80228
|
function ensureTestPlanIgnored(repoRoot) {
|
|
80262
|
-
const gitignorePath =
|
|
80229
|
+
const gitignorePath = import_node_path18.default.join(repoRoot, ".gitignore");
|
|
80263
80230
|
if (!(0, import_node_fs9.existsSync)(gitignorePath)) {
|
|
80264
80231
|
(0, import_node_fs9.writeFileSync)(gitignorePath, `${TEST_PLAN_IGNORE_LINE}
|
|
80265
80232
|
`);
|
|
@@ -80316,12 +80283,12 @@ Scope applies from the starting screen. If the focus area requires navigation, d
|
|
|
80316
80283
|
`;
|
|
80317
80284
|
function scaffoldProject(xqaDirectory) {
|
|
80318
80285
|
(0, import_node_fs9.mkdirSync)(xqaDirectory);
|
|
80319
|
-
(0, import_node_fs9.writeFileSync)(
|
|
80320
|
-
(0, import_node_fs9.writeFileSync)(
|
|
80321
|
-
(0, import_node_fs9.writeFileSync)(
|
|
80286
|
+
(0, import_node_fs9.writeFileSync)(import_node_path18.default.join(xqaDirectory, ".gitignore"), GITIGNORE_CONTENT);
|
|
80287
|
+
(0, import_node_fs9.writeFileSync)(import_node_path18.default.join(xqaDirectory, "app.md"), APP_TEMPLATE);
|
|
80288
|
+
(0, import_node_fs9.writeFileSync)(import_node_path18.default.join(xqaDirectory, "explore.md"), EXPLORE_TEMPLATE);
|
|
80322
80289
|
for (const subdir of ["designs", "specs", "suites"]) {
|
|
80323
|
-
(0, import_node_fs9.mkdirSync)(
|
|
80324
|
-
(0, import_node_fs9.writeFileSync)(
|
|
80290
|
+
(0, import_node_fs9.mkdirSync)(import_node_path18.default.join(xqaDirectory, subdir));
|
|
80291
|
+
(0, import_node_fs9.writeFileSync)(import_node_path18.default.join(xqaDirectory, subdir, ".gitkeep"), "");
|
|
80325
80292
|
}
|
|
80326
80293
|
}
|
|
80327
80294
|
function printInitReport(report) {
|
|
@@ -80343,7 +80310,7 @@ ${addedLines}
|
|
|
80343
80310
|
}
|
|
80344
80311
|
async function runInitCommand() {
|
|
80345
80312
|
const cwd = process.cwd();
|
|
80346
|
-
const xqaDirectory =
|
|
80313
|
+
const xqaDirectory = import_node_path18.default.join(cwd, ".xqa");
|
|
80347
80314
|
installSkills();
|
|
80348
80315
|
ensureTestPlanIgnored(cwd);
|
|
80349
80316
|
if ((0, import_node_fs9.existsSync)(xqaDirectory)) {
|
|
@@ -80370,7 +80337,7 @@ function registerInitCommand(program3) {
|
|
|
80370
80337
|
}
|
|
80371
80338
|
|
|
80372
80339
|
// src/commands/plan/edit-command.ts
|
|
80373
|
-
var
|
|
80340
|
+
var import_node_path23 = __toESM(require("node:path"), 1);
|
|
80374
80341
|
|
|
80375
80342
|
// ../../agents/planner/dist/index.js
|
|
80376
80343
|
var import_neverthrow56 = __toESM(require_index_cjs(), 1);
|
|
@@ -80380,26 +80347,29 @@ var yaml2 = __toESM(require_dist(), 1);
|
|
|
80380
80347
|
var import_neverthrow59 = __toESM(require_index_cjs(), 1);
|
|
80381
80348
|
var yaml22 = __toESM(require_dist(), 1);
|
|
80382
80349
|
var import_neverthrow60 = __toESM(require_index_cjs(), 1);
|
|
80383
|
-
var
|
|
80384
|
-
var
|
|
80350
|
+
var import_promises22 = require("node:fs/promises");
|
|
80351
|
+
var import_node_path19 = __toESM(require("node:path"), 1);
|
|
80385
80352
|
var import_neverthrow61 = __toESM(require_index_cjs(), 1);
|
|
80386
|
-
var
|
|
80353
|
+
var import_promises23 = require("node:fs/promises");
|
|
80387
80354
|
var import_neverthrow62 = __toESM(require_index_cjs(), 1);
|
|
80388
80355
|
var import_neverthrow63 = __toESM(require_index_cjs(), 1);
|
|
80389
80356
|
var import_node_child_process6 = require("node:child_process");
|
|
80390
80357
|
var import_node_util = require("node:util");
|
|
80391
80358
|
var import_neverthrow64 = __toESM(require_index_cjs(), 1);
|
|
80392
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");
|
|
80393
80362
|
var import_neverthrow65 = __toESM(require_index_cjs(), 1);
|
|
80394
80363
|
var import_neverthrow66 = __toESM(require_index_cjs(), 1);
|
|
80395
|
-
var import_promises25 = require("node:fs/promises");
|
|
80396
|
-
var import_node_path21 = __toESM(require("node:path"), 1);
|
|
80397
80364
|
var import_neverthrow67 = __toESM(require_index_cjs(), 1);
|
|
80398
|
-
var
|
|
80399
|
-
var
|
|
80365
|
+
var import_promises24 = require("node:fs/promises");
|
|
80366
|
+
var import_node_path20 = __toESM(require("node:path"), 1);
|
|
80400
80367
|
var import_neverthrow68 = __toESM(require_index_cjs(), 1);
|
|
80401
|
-
var
|
|
80368
|
+
var import_promises25 = require("node:fs/promises");
|
|
80369
|
+
var import_node_path21 = __toESM(require("node:path"), 1);
|
|
80402
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);
|
|
80403
80373
|
function isEmptySummary(summary) {
|
|
80404
80374
|
return summary.touchedFiles.length === 0 && summary.uncommittedFiles.length === 0;
|
|
80405
80375
|
}
|
|
@@ -80677,6 +80647,25 @@ function classifyActionability(summary, rawDiff) {
|
|
|
80677
80647
|
}
|
|
80678
80648
|
return { kind: "actionable" };
|
|
80679
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
|
+
}
|
|
80680
80669
|
var PORCELAIN_PATH_OFFSET = 3;
|
|
80681
80670
|
var PORCELAIN_RENAME_SEPARATOR = " -> ";
|
|
80682
80671
|
function extractPorcelainPath(line) {
|
|
@@ -80697,7 +80686,10 @@ function branchReferenceToString(reference) {
|
|
|
80697
80686
|
return reference.sha;
|
|
80698
80687
|
}
|
|
80699
80688
|
function resolveBaseReference(context) {
|
|
80700
|
-
|
|
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);
|
|
80701
80693
|
}
|
|
80702
80694
|
function assertNonEmptyDiff(state) {
|
|
80703
80695
|
if (isEmptySummary(state.summary)) {
|
|
@@ -80707,15 +80699,16 @@ function assertNonEmptyDiff(state) {
|
|
|
80707
80699
|
}
|
|
80708
80700
|
function emitDrafts(input) {
|
|
80709
80701
|
const { context, summary } = input;
|
|
80710
|
-
return recoverPlanMissing(context.deps.readPlan({ directory: context.input.outputDirectory })).map((entries) => toSpecSummaries(entries)).andThen(
|
|
80711
|
-
|
|
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({
|
|
80712
80705
|
summary,
|
|
80713
80706
|
intent: context.input.intent,
|
|
80714
80707
|
appContext: context.input.appContext,
|
|
80715
80708
|
existingSpecs,
|
|
80716
80709
|
aiConfig: context.input.aiConfig
|
|
80717
|
-
})
|
|
80718
|
-
);
|
|
80710
|
+
});
|
|
80711
|
+
});
|
|
80719
80712
|
}
|
|
80720
80713
|
function persistScenarios(input) {
|
|
80721
80714
|
return input.context.deps.writeScenarios({
|
|
@@ -80732,6 +80725,7 @@ function persistScenarios(input) {
|
|
|
80732
80725
|
function runEmitAndPersist(input) {
|
|
80733
80726
|
const { state, context } = input;
|
|
80734
80727
|
return emitDrafts({ summary: state.summary, context }).andThen((drafts) => {
|
|
80728
|
+
context.deps.emitDebug?.(`[plan] drafts count=${String(drafts.length)}`);
|
|
80735
80729
|
if (drafts.length === 0) {
|
|
80736
80730
|
return (0, import_neverthrow56.okAsync)({
|
|
80737
80731
|
specs: [],
|
|
@@ -80745,9 +80739,12 @@ function runEmitAndPersist(input) {
|
|
|
80745
80739
|
}
|
|
80746
80740
|
function dispatchClassification(input) {
|
|
80747
80741
|
const classification = classifyActionability(input.state.summary, input.state.rawDiff);
|
|
80742
|
+
const emitDebug = input.context.deps.emitDebug;
|
|
80748
80743
|
if (classification.kind === "empty") {
|
|
80744
|
+
emitClassificationDebug({ emitDebug, kind: "empty", reason: classification.reason });
|
|
80749
80745
|
return (0, import_neverthrow56.okAsync)({ specs: [], emptyReason: classification.reason });
|
|
80750
80746
|
}
|
|
80747
|
+
emitClassificationDebug({ emitDebug, kind: "actionable" });
|
|
80751
80748
|
return runEmitAndPersist(input);
|
|
80752
80749
|
}
|
|
80753
80750
|
function combineReferences(context) {
|
|
@@ -80755,7 +80752,10 @@ function combineReferences(context) {
|
|
|
80755
80752
|
(baseReference) => resolveHead({
|
|
80756
80753
|
gitContext: context.input.gitContext,
|
|
80757
80754
|
gitBranchReference: context.deps.gitBranchReference
|
|
80758
|
-
}).map((head) =>
|
|
80755
|
+
}).map((head) => {
|
|
80756
|
+
context.deps.emitDebug?.(`[plan] base=${baseReference} head=${head}`);
|
|
80757
|
+
return { baseRef: baseReference, head };
|
|
80758
|
+
})
|
|
80759
80759
|
);
|
|
80760
80760
|
}
|
|
80761
80761
|
function buildSummaryState(context, references) {
|
|
@@ -80764,11 +80764,16 @@ function buildSummaryState(context, references) {
|
|
|
80764
80764
|
gitContext: context.input.gitContext,
|
|
80765
80765
|
gitDiff: context.deps.gitDiff,
|
|
80766
80766
|
gitStatusPorcelain: context.deps.gitStatusPorcelain
|
|
80767
|
-
}).map((collected) =>
|
|
80768
|
-
|
|
80769
|
-
|
|
80770
|
-
|
|
80771
|
-
|
|
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
|
+
});
|
|
80772
80777
|
}
|
|
80773
80778
|
function resolveHead(input) {
|
|
80774
80779
|
return input.gitBranchReference(input.gitContext).map((reference) => branchReferenceToString(reference));
|
|
@@ -81252,8 +81257,8 @@ function extendPlan(input, deps) {
|
|
|
81252
81257
|
}
|
|
81253
81258
|
async function writeAndRename(input) {
|
|
81254
81259
|
const temporaryPath = `${input.path}.tmp`;
|
|
81255
|
-
await (0,
|
|
81256
|
-
await (0,
|
|
81260
|
+
await (0, import_promises23.writeFile)(temporaryPath, input.content, "utf8");
|
|
81261
|
+
await (0, import_promises23.rename)(temporaryPath, input.path);
|
|
81257
81262
|
}
|
|
81258
81263
|
var rawAtomicWrite = import_neverthrow62.ResultAsync.fromThrowable(
|
|
81259
81264
|
writeAndRename,
|
|
@@ -81415,7 +81420,7 @@ function validateFindings(input) {
|
|
|
81415
81420
|
return parseFindingsJson(input).andThen((data) => validateFindingsSchema(data, input.path));
|
|
81416
81421
|
}
|
|
81417
81422
|
function reportPathFor(findingsPath) {
|
|
81418
|
-
return
|
|
81423
|
+
return import_node_path19.default.join(import_node_path19.default.dirname(findingsPath), REPORT_FILENAME);
|
|
81419
81424
|
}
|
|
81420
81425
|
function buildReport(input) {
|
|
81421
81426
|
return correlate({
|
|
@@ -81437,7 +81442,7 @@ function correlateAndPersist(input) {
|
|
|
81437
81442
|
});
|
|
81438
81443
|
}
|
|
81439
81444
|
var rawReadFindings = import_neverthrow61.ResultAsync.fromThrowable(
|
|
81440
|
-
async (filePath) => (0,
|
|
81445
|
+
async (filePath) => (0, import_promises22.readFile)(filePath, "utf8"),
|
|
81441
81446
|
(cause) => ({ cause })
|
|
81442
81447
|
);
|
|
81443
81448
|
function readFindingsFile(filePath) {
|
|
@@ -81585,6 +81590,48 @@ function gitStatusPorcelain(context) {
|
|
|
81585
81590
|
function gitSymbolicReferenceOriginHead(context) {
|
|
81586
81591
|
return execGit(["symbolic-ref", "--short", "refs/remotes/origin/HEAD"], context).map((result) => stripOriginPrefix(result.stdout)).mapErr(() => ({ type: "GIT_NO_BASE_BRANCH" }));
|
|
81587
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
|
+
}
|
|
81588
81635
|
var MAX_EXISTING_SPECS = 30;
|
|
81589
81636
|
function renderList(items, emptyLabel) {
|
|
81590
81637
|
if (items.length === 0) {
|
|
@@ -81702,20 +81749,20 @@ var scenarioDraftSchema = external_exports.object({
|
|
|
81702
81749
|
coverageNote: external_exports.string().optional()
|
|
81703
81750
|
});
|
|
81704
81751
|
var payloadSchema = external_exports.object({ scenarios: external_exports.array(scenarioDraftSchema) });
|
|
81705
|
-
var safeParseJson3 = (0,
|
|
81752
|
+
var safeParseJson3 = (0, import_neverthrow66.fromThrowable)(
|
|
81706
81753
|
(raw) => JSON.parse(raw),
|
|
81707
81754
|
() => ({ type: "AI_RESPONSE_JSON_PARSE" })
|
|
81708
81755
|
);
|
|
81709
81756
|
function validatePayload(raw) {
|
|
81710
81757
|
const parsed = safeParseJson3(raw);
|
|
81711
81758
|
if (parsed.isErr()) {
|
|
81712
|
-
return (0,
|
|
81759
|
+
return (0, import_neverthrow66.err)({ type: "AI_RESPONSE_INVALID", operation: "scenario-emit", raw });
|
|
81713
81760
|
}
|
|
81714
81761
|
const validated = payloadSchema.safeParse(parsed.value);
|
|
81715
81762
|
if (!validated.success) {
|
|
81716
|
-
return (0,
|
|
81763
|
+
return (0, import_neverthrow66.err)({ type: "AI_RESPONSE_INVALID", operation: "scenario-emit", raw });
|
|
81717
81764
|
}
|
|
81718
|
-
return (0,
|
|
81765
|
+
return (0, import_neverthrow66.ok)(validated.data.scenarios);
|
|
81719
81766
|
}
|
|
81720
81767
|
function emitScenarios(input, deps) {
|
|
81721
81768
|
const prompt = buildScenarioEmitterPrompt({
|
|
@@ -81724,7 +81771,13 @@ function emitScenarios(input, deps) {
|
|
|
81724
81771
|
appContext: input.appContext,
|
|
81725
81772
|
existingSpecs: input.existingSpecs
|
|
81726
81773
|
});
|
|
81727
|
-
|
|
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
|
+
});
|
|
81728
81781
|
}
|
|
81729
81782
|
function renderExistingSpecSection(existingSpec) {
|
|
81730
81783
|
const feature = existingSpec.feature;
|
|
@@ -81791,14 +81844,14 @@ function validateCandidate(validateInput) {
|
|
|
81791
81844
|
const { raw, existingSpec, specPath } = validateInput;
|
|
81792
81845
|
const parsed = parseSpec(raw, specPath);
|
|
81793
81846
|
if (parsed.isErr()) {
|
|
81794
|
-
return (0,
|
|
81847
|
+
return (0, import_neverthrow67.err)({ type: "AI_RESPONSE_INVALID", operation: "edit-apply", raw });
|
|
81795
81848
|
}
|
|
81796
81849
|
const candidate = parsed.value;
|
|
81797
81850
|
const violated = findMissingOrChangedKey(candidate, existingSpec);
|
|
81798
81851
|
if (violated !== void 0) {
|
|
81799
|
-
return (0,
|
|
81852
|
+
return (0, import_neverthrow67.err)({ type: "SCENARIO_ID_LOST_IN_EDIT", path: specPath });
|
|
81800
81853
|
}
|
|
81801
|
-
return (0,
|
|
81854
|
+
return (0, import_neverthrow67.ok)(candidate);
|
|
81802
81855
|
}
|
|
81803
81856
|
function applyEdit(input, deps) {
|
|
81804
81857
|
const prompt = buildEditApplierPrompt(input.existingSpec, input.userFeedback);
|
|
@@ -81816,15 +81869,15 @@ function mapReaddirError(input) {
|
|
|
81816
81869
|
}
|
|
81817
81870
|
return { type: "SPEC_READ_FAILED", path: input.directory, cause: input.cause };
|
|
81818
81871
|
}
|
|
81819
|
-
var rawReaddir =
|
|
81820
|
-
async (directory) => (0,
|
|
81872
|
+
var rawReaddir = import_neverthrow68.ResultAsync.fromThrowable(
|
|
81873
|
+
async (directory) => (0, import_promises24.readdir)(directory),
|
|
81821
81874
|
(cause) => ({ cause })
|
|
81822
81875
|
);
|
|
81823
81876
|
function safeReaddir(directory) {
|
|
81824
81877
|
return rawReaddir(directory).mapErr(({ cause }) => mapReaddirError({ directory, cause }));
|
|
81825
81878
|
}
|
|
81826
|
-
var rawReadFile =
|
|
81827
|
-
async (input) => (0,
|
|
81879
|
+
var rawReadFile = import_neverthrow68.ResultAsync.fromThrowable(
|
|
81880
|
+
async (input) => (0, import_promises24.readFile)(input.path, "utf8"),
|
|
81828
81881
|
(cause) => ({ cause })
|
|
81829
81882
|
);
|
|
81830
81883
|
function safeReadFile3(input) {
|
|
@@ -81836,25 +81889,25 @@ function filterAndSortSpecs(filenames) {
|
|
|
81836
81889
|
return filenames.filter((name) => name.endsWith(SPEC_SUFFIX)).toSorted();
|
|
81837
81890
|
}
|
|
81838
81891
|
function readEntry2(input) {
|
|
81839
|
-
const entryPath =
|
|
81892
|
+
const entryPath = import_node_path20.default.join(input.directory, input.filename);
|
|
81840
81893
|
return safeReadFile3({ path: entryPath }).andThen(
|
|
81841
81894
|
(raw) => parseSpec(raw, entryPath).map((spec) => ({ path: entryPath, spec }))
|
|
81842
81895
|
);
|
|
81843
81896
|
}
|
|
81844
81897
|
function readEntries2(directory, filenames) {
|
|
81845
81898
|
const tasks = filenames.map((filename) => readEntry2({ directory, filename }));
|
|
81846
|
-
return
|
|
81899
|
+
return import_neverthrow68.ResultAsync.combine([...tasks]);
|
|
81847
81900
|
}
|
|
81848
81901
|
function readPlan(input) {
|
|
81849
81902
|
return safeReaddir(input.directory).map((filenames) => filterAndSortSpecs(filenames)).andThen((filenames) => readEntries2(input.directory, filenames));
|
|
81850
81903
|
}
|
|
81851
81904
|
var SCENARIO_FILENAME_PATTERN = /^scenario-(\d+)\.test\.md$/;
|
|
81852
|
-
var safeMkdir =
|
|
81853
|
-
async (path43) => (0,
|
|
81905
|
+
var safeMkdir = import_neverthrow69.ResultAsync.fromThrowable(
|
|
81906
|
+
async (path43) => (0, import_promises25.mkdir)(path43, { recursive: true }),
|
|
81854
81907
|
(cause) => ({ type: "SPEC_WRITE_FAILED", path: "", cause })
|
|
81855
81908
|
);
|
|
81856
|
-
var safeReaddir2 =
|
|
81857
|
-
async (path43) => (0,
|
|
81909
|
+
var safeReaddir2 = import_neverthrow69.ResultAsync.fromThrowable(
|
|
81910
|
+
async (path43) => (0, import_promises25.readdir)(path43),
|
|
81858
81911
|
(cause) => ({ type: "SPEC_WRITE_FAILED", path: "", cause })
|
|
81859
81912
|
);
|
|
81860
81913
|
function ensureDirectory(directory) {
|
|
@@ -81890,7 +81943,7 @@ function buildMeta(context) {
|
|
|
81890
81943
|
}
|
|
81891
81944
|
function writeSingleScenario(input) {
|
|
81892
81945
|
const filename = `scenario-${String(input.index)}.test.md`;
|
|
81893
|
-
const targetPath =
|
|
81946
|
+
const targetPath = import_node_path21.default.join(input.directory, filename);
|
|
81894
81947
|
const meta3 = buildMeta(input.context);
|
|
81895
81948
|
const content = renderSpec2(input.draft, meta3);
|
|
81896
81949
|
return atomicWrite({ path: targetPath, content }).map(() => targetPath);
|
|
@@ -81904,13 +81957,13 @@ function writeAllScenarios(input, startIndex) {
|
|
|
81904
81957
|
context: input.context
|
|
81905
81958
|
})
|
|
81906
81959
|
);
|
|
81907
|
-
return
|
|
81960
|
+
return import_neverthrow69.ResultAsync.combine([...tasks]);
|
|
81908
81961
|
}
|
|
81909
81962
|
function writeScenarios(input) {
|
|
81910
81963
|
return ensureDirectory(input.directory).andThen(() => listScenarioIndices(input.directory)).map((indices) => computeNextIndex(indices)).andThen((startIndex) => writeAllScenarios(input, startIndex));
|
|
81911
81964
|
}
|
|
81912
|
-
var readFileByPath =
|
|
81913
|
-
async (path43) => (0,
|
|
81965
|
+
var readFileByPath = import_neverthrow70.ResultAsync.fromThrowable(
|
|
81966
|
+
async (path43) => (0, import_promises26.readFile)(path43, "utf8"),
|
|
81914
81967
|
(cause) => ({ cause })
|
|
81915
81968
|
);
|
|
81916
81969
|
function readSpecFile(path43) {
|
|
@@ -81923,7 +81976,7 @@ function writeSpecFile(input) {
|
|
|
81923
81976
|
}
|
|
81924
81977
|
|
|
81925
81978
|
// src/commands/plan/shared-runner.ts
|
|
81926
|
-
var
|
|
81979
|
+
var import_node_path22 = __toESM(require("node:path"), 1);
|
|
81927
81980
|
|
|
81928
81981
|
// src/commands/plan/exit-codes.ts
|
|
81929
81982
|
var EXIT_OK = 0;
|
|
@@ -81945,10 +81998,10 @@ var EXIT_PLAN_EMPTY = 45;
|
|
|
81945
81998
|
var EXIT_SCENARIO_ID_LOST_IN_EDIT = 51;
|
|
81946
81999
|
|
|
81947
82000
|
// src/commands/plan/format-diagnostic.ts
|
|
81948
|
-
var
|
|
82001
|
+
var import_neverthrow71 = __toESM(require_index_cjs(), 1);
|
|
81949
82002
|
var RAW_TRUNCATION_LIMIT = 200;
|
|
81950
82003
|
var UNSERIALIZABLE2 = "[unserializable]";
|
|
81951
|
-
var safeStringify2 = (0,
|
|
82004
|
+
var safeStringify2 = (0, import_neverthrow71.fromThrowable)(
|
|
81952
82005
|
(value) => JSON.stringify(value),
|
|
81953
82006
|
() => UNSERIALIZABLE2
|
|
81954
82007
|
);
|
|
@@ -82018,9 +82071,9 @@ var PLANNER_MODEL = "claude-opus-4-5";
|
|
|
82018
82071
|
var DEFAULT_PLAN_SUBDIR = "test-plan/default";
|
|
82019
82072
|
function resolveOutputDirectory(xqaDirectory, override) {
|
|
82020
82073
|
if (override !== void 0) {
|
|
82021
|
-
return
|
|
82074
|
+
return import_node_path22.default.resolve(process.cwd(), override);
|
|
82022
82075
|
}
|
|
82023
|
-
return
|
|
82076
|
+
return import_node_path22.default.join(xqaDirectory, DEFAULT_PLAN_SUBDIR);
|
|
82024
82077
|
}
|
|
82025
82078
|
function readAppContextOrDiagnose(xqaDirectory) {
|
|
82026
82079
|
return readAppContext(xqaDirectory).mapErr(
|
|
@@ -82046,7 +82099,7 @@ var DEPS = {
|
|
|
82046
82099
|
};
|
|
82047
82100
|
function buildPlannerInput(input, options2) {
|
|
82048
82101
|
return {
|
|
82049
|
-
file:
|
|
82102
|
+
file: import_node_path23.default.resolve(process.cwd(), input.file),
|
|
82050
82103
|
userFeedback: input.feedback,
|
|
82051
82104
|
aiConfig: {
|
|
82052
82105
|
apiKey: options2.config.ANTHROPIC_API_KEY,
|
|
@@ -82193,15 +82246,23 @@ function runPlanExtend(input, options2) {
|
|
|
82193
82246
|
}
|
|
82194
82247
|
|
|
82195
82248
|
// src/commands/plan/generate-command.ts
|
|
82196
|
-
|
|
82197
|
-
|
|
82198
|
-
|
|
82199
|
-
|
|
82200
|
-
|
|
82201
|
-
|
|
82202
|
-
|
|
82203
|
-
|
|
82204
|
-
}
|
|
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
|
+
}
|
|
82205
82266
|
function buildPlannerInput3(arguments_, appContext) {
|
|
82206
82267
|
return {
|
|
82207
82268
|
gitContext: { cwd: process.cwd() },
|
|
@@ -82216,12 +82277,13 @@ function buildPlannerInput3(arguments_, appContext) {
|
|
|
82216
82277
|
model: PLANNER_MODEL
|
|
82217
82278
|
},
|
|
82218
82279
|
idGenerator: () => ulid3(),
|
|
82219
|
-
now: () => (/* @__PURE__ */ new Date()).toISOString()
|
|
82280
|
+
now: () => (/* @__PURE__ */ new Date()).toISOString(),
|
|
82281
|
+
baseOverride: arguments_.input.baseOverride
|
|
82220
82282
|
};
|
|
82221
82283
|
}
|
|
82222
82284
|
function executePipeline4(arguments_) {
|
|
82223
82285
|
return readAppContextOrDiagnose(arguments_.input.xqaDirectory).andThen(
|
|
82224
|
-
(appContext) => generatePlan(buildPlannerInput3(arguments_, appContext ?? ""),
|
|
82286
|
+
(appContext) => generatePlan(buildPlannerInput3(arguments_, appContext ?? ""), buildDeps(arguments_.input))
|
|
82225
82287
|
);
|
|
82226
82288
|
}
|
|
82227
82289
|
function runPlanGenerate(input, options2) {
|
|
@@ -82229,33 +82291,39 @@ function runPlanGenerate(input, options2) {
|
|
|
82229
82291
|
}
|
|
82230
82292
|
|
|
82231
82293
|
// src/commands/plan/report-command.ts
|
|
82232
|
-
var
|
|
82233
|
-
var
|
|
82294
|
+
var import_node_path24 = __toESM(require("node:path"), 1);
|
|
82295
|
+
var DEPS3 = {
|
|
82234
82296
|
readPlan,
|
|
82235
82297
|
readFindingsFile,
|
|
82236
82298
|
writeReportFile
|
|
82237
82299
|
};
|
|
82238
82300
|
function buildReportInput(input) {
|
|
82239
82301
|
return {
|
|
82240
|
-
findingsPath:
|
|
82302
|
+
findingsPath: import_node_path24.default.resolve(process.cwd(), input.findingsPath),
|
|
82241
82303
|
specsDirectory: resolveOutputDirectory(input.xqaDirectory, input.specsDirectory)
|
|
82242
82304
|
};
|
|
82243
82305
|
}
|
|
82244
82306
|
function executePipeline5(input) {
|
|
82245
|
-
return reportRun(buildReportInput(input),
|
|
82307
|
+
return reportRun(buildReportInput(input), DEPS3);
|
|
82246
82308
|
}
|
|
82247
82309
|
function runPlanReport(input) {
|
|
82248
82310
|
void executePipeline5(input).match(emitSuccess, emitFailure);
|
|
82249
82311
|
}
|
|
82250
82312
|
|
|
82251
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
|
+
}
|
|
82252
82318
|
function invokePlanGenerate(context, options2) {
|
|
82253
82319
|
const xqaDirectory = resolveXqaDirectory();
|
|
82254
82320
|
runPlanGenerate(
|
|
82255
82321
|
{
|
|
82256
82322
|
intent: options2.intent ?? "",
|
|
82257
82323
|
outputDirectory: options2.out,
|
|
82258
|
-
xqaDirectory
|
|
82324
|
+
xqaDirectory,
|
|
82325
|
+
baseOverride: normalizeBaseOverride(options2.base),
|
|
82326
|
+
debug: options2.debug
|
|
82259
82327
|
},
|
|
82260
82328
|
{ config: context.config }
|
|
82261
82329
|
);
|
|
@@ -82289,7 +82357,7 @@ function registerReportSubcommand(plan) {
|
|
|
82289
82357
|
});
|
|
82290
82358
|
}
|
|
82291
82359
|
function registerPlanCommand(program3, loader2) {
|
|
82292
|
-
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) => {
|
|
82293
82361
|
const context = resolveContextOrExit(loader2);
|
|
82294
82362
|
invokePlanGenerate(context, options2);
|
|
82295
82363
|
});
|
|
@@ -82300,8 +82368,8 @@ function registerPlanCommand(program3, loader2) {
|
|
|
82300
82368
|
|
|
82301
82369
|
// src/commands/review-command.ts
|
|
82302
82370
|
var import_node_fs10 = require("node:fs");
|
|
82303
|
-
var
|
|
82304
|
-
var
|
|
82371
|
+
var import_node_path26 = __toESM(require("node:path"), 1);
|
|
82372
|
+
var import_neverthrow73 = __toESM(require_index_cjs(), 1);
|
|
82305
82373
|
|
|
82306
82374
|
// ../../node_modules/.pnpm/@inquirer+core@10.3.2_@types+node@22.19.15/node_modules/@inquirer/core/dist/esm/lib/key.js
|
|
82307
82375
|
var isUpKey = (key, keybindings = []) => (
|
|
@@ -83252,7 +83320,7 @@ var {
|
|
|
83252
83320
|
} = signalExitWrap(processOk(process5) ? new SignalExit(process5) : new SignalExitFallback());
|
|
83253
83321
|
|
|
83254
83322
|
// ../../node_modules/.pnpm/@inquirer+core@10.3.2_@types+node@22.19.15/node_modules/@inquirer/core/dist/esm/lib/screen-manager.js
|
|
83255
|
-
var
|
|
83323
|
+
var import_node_util3 = require("node:util");
|
|
83256
83324
|
|
|
83257
83325
|
// ../../node_modules/.pnpm/@inquirer+ansi@1.0.2/node_modules/@inquirer/ansi/dist/esm/index.js
|
|
83258
83326
|
var ESC2 = "\x1B[";
|
|
@@ -83290,7 +83358,7 @@ var ScreenManager = class {
|
|
|
83290
83358
|
}
|
|
83291
83359
|
render(content, bottomContent = "") {
|
|
83292
83360
|
const promptLine = lastLine(content);
|
|
83293
|
-
const rawPromptLine = (0,
|
|
83361
|
+
const rawPromptLine = (0, import_node_util3.stripVTControlCharacters)(promptLine);
|
|
83294
83362
|
let prompt = rawPromptLine;
|
|
83295
83363
|
if (this.rl.line.length > 0) {
|
|
83296
83364
|
prompt = prompt.slice(0, -this.rl.line.length);
|
|
@@ -83639,7 +83707,7 @@ var esm_default2 = createPrompt((config2, done) => {
|
|
|
83639
83707
|
var import_chardet = __toESM(require_lib2(), 1);
|
|
83640
83708
|
var import_child_process3 = require("child_process");
|
|
83641
83709
|
var import_fs3 = require("fs");
|
|
83642
|
-
var
|
|
83710
|
+
var import_node_path25 = __toESM(require("node:path"), 1);
|
|
83643
83711
|
var import_node_os3 = __toESM(require("node:os"), 1);
|
|
83644
83712
|
var import_node_crypto3 = require("node:crypto");
|
|
83645
83713
|
var import_iconv_lite = __toESM(require_lib3(), 1);
|
|
@@ -83775,8 +83843,8 @@ var ExternalEditor = class {
|
|
|
83775
83843
|
const prefix = sanitizeAffix(this.fileOptions.prefix);
|
|
83776
83844
|
const postfix = sanitizeAffix(this.fileOptions.postfix);
|
|
83777
83845
|
const filename = `${prefix}${id}${postfix}`;
|
|
83778
|
-
const candidate =
|
|
83779
|
-
const baseResolved =
|
|
83846
|
+
const candidate = import_node_path25.default.resolve(baseDir, filename);
|
|
83847
|
+
const baseResolved = import_node_path25.default.resolve(baseDir) + import_node_path25.default.sep;
|
|
83780
83848
|
if (!candidate.startsWith(baseResolved)) {
|
|
83781
83849
|
throw new Error("Resolved temporary file escaped the base directory");
|
|
83782
83850
|
}
|
|
@@ -84706,7 +84774,7 @@ var esm_default11 = createPrompt((config2, done) => {
|
|
|
84706
84774
|
});
|
|
84707
84775
|
|
|
84708
84776
|
// src/review-session.ts
|
|
84709
|
-
var
|
|
84777
|
+
var import_neverthrow72 = __toESM(require_index_cjs(), 1);
|
|
84710
84778
|
var FLOW_COL_WIDTH = 35;
|
|
84711
84779
|
var TRIGGER_COL_WIDTH = 16;
|
|
84712
84780
|
var CONFIDENCE_COL_WIDTH = 6;
|
|
@@ -84854,15 +84922,15 @@ async function runInteractiveLoop(findings, existing) {
|
|
|
84854
84922
|
}
|
|
84855
84923
|
return { staged: state.staged, undoneKeys: state.undoneKeys };
|
|
84856
84924
|
}
|
|
84857
|
-
var safeRunInteractiveLoop = (0,
|
|
84925
|
+
var safeRunInteractiveLoop = (0, import_neverthrow72.fromAsyncThrowable)(
|
|
84858
84926
|
runInteractiveLoop,
|
|
84859
84927
|
(error48) => error48 instanceof Error && error48.name === "ExitPromptError" ? "exit-prompt" : "unexpected"
|
|
84860
84928
|
);
|
|
84861
84929
|
|
|
84862
84930
|
// src/commands/review-command.ts
|
|
84863
|
-
var safeReadFile4 = (0,
|
|
84864
|
-
var safeParseJson4 = (0,
|
|
84865
|
-
var safeWrite = (0,
|
|
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) => {
|
|
84866
84934
|
(0, import_node_fs10.writeFileSync)(filePath, content);
|
|
84867
84935
|
});
|
|
84868
84936
|
function readLastPath(xqaDirectory) {
|
|
@@ -84879,13 +84947,13 @@ function isPipelineOutput(data) {
|
|
|
84879
84947
|
function readFindings(filePath) {
|
|
84880
84948
|
const readResult = safeReadFile4(filePath);
|
|
84881
84949
|
if (readResult.isErr()) {
|
|
84882
|
-
return (0,
|
|
84950
|
+
return (0, import_neverthrow73.err)("not-found");
|
|
84883
84951
|
}
|
|
84884
84952
|
return safeParseJson4(readResult.value).mapErr(() => "invalid").andThen((data) => {
|
|
84885
84953
|
if (!isPipelineOutput(data)) {
|
|
84886
|
-
return (0,
|
|
84954
|
+
return (0, import_neverthrow73.err)("invalid");
|
|
84887
84955
|
}
|
|
84888
|
-
return (0,
|
|
84956
|
+
return (0, import_neverthrow73.ok)(data);
|
|
84889
84957
|
});
|
|
84890
84958
|
}
|
|
84891
84959
|
function loadExistingDismissals(filePath) {
|
|
@@ -84958,7 +85026,7 @@ function resolveAndReadFindings(findingsPath, xqaDirectory) {
|
|
|
84958
85026
|
"No findings path provided and no last path found. Run: xqa review <findings-path>\n"
|
|
84959
85027
|
);
|
|
84960
85028
|
process.exit(1);
|
|
84961
|
-
return (0,
|
|
85029
|
+
return (0, import_neverthrow73.err)();
|
|
84962
85030
|
}
|
|
84963
85031
|
const resolvedPath = resolvedPathResult.value;
|
|
84964
85032
|
const findingsResult = readFindings(resolvedPath);
|
|
@@ -84971,9 +85039,9 @@ function resolveAndReadFindings(findingsPath, xqaDirectory) {
|
|
|
84971
85039
|
`);
|
|
84972
85040
|
}
|
|
84973
85041
|
process.exit(1);
|
|
84974
|
-
return (0,
|
|
85042
|
+
return (0, import_neverthrow73.err)();
|
|
84975
85043
|
}
|
|
84976
|
-
return (0,
|
|
85044
|
+
return (0, import_neverthrow73.ok)({ resolvedPath, output: findingsResult.value });
|
|
84977
85045
|
}
|
|
84978
85046
|
async function runReviewLoop({
|
|
84979
85047
|
findings,
|
|
@@ -85001,7 +85069,7 @@ async function executeReview({
|
|
|
85001
85069
|
process.exit(0);
|
|
85002
85070
|
return;
|
|
85003
85071
|
}
|
|
85004
|
-
const dismissalsFilePath = dismissalsPath(
|
|
85072
|
+
const dismissalsFilePath = dismissalsPath(import_node_path26.default.dirname(xqaDirectory), dismissalsPathOverride);
|
|
85005
85073
|
await runReviewLoop({
|
|
85006
85074
|
findings,
|
|
85007
85075
|
dismissalsFilePath,
|
|
@@ -85043,14 +85111,14 @@ function discoverSimulators(udidOverride) {
|
|
|
85043
85111
|
}
|
|
85044
85112
|
|
|
85045
85113
|
// src/suite/commands/run/resolve-work-items.ts
|
|
85046
|
-
var
|
|
85047
|
-
var
|
|
85114
|
+
var import_promises27 = __toESM(require("node:fs/promises"), 1);
|
|
85115
|
+
var import_node_path27 = __toESM(require("node:path"), 1);
|
|
85048
85116
|
var import_fast_glob = __toESM(require_out4(), 1);
|
|
85049
|
-
var
|
|
85117
|
+
var import_neverthrow76 = __toESM(require_index_cjs(), 1);
|
|
85050
85118
|
|
|
85051
85119
|
// src/suite/core/suite-config-parser.ts
|
|
85052
|
-
var import_neverthrow73 = __toESM(require_index_cjs(), 1);
|
|
85053
85120
|
var import_neverthrow74 = __toESM(require_index_cjs(), 1);
|
|
85121
|
+
var import_neverthrow75 = __toESM(require_index_cjs(), 1);
|
|
85054
85122
|
var RESERVED_HOOK_ENV_KEYS = [
|
|
85055
85123
|
"XQA_SIM_UDID",
|
|
85056
85124
|
"XQA_ITEM_ID",
|
|
@@ -85102,7 +85170,7 @@ var suiteConfigSchema = external_exports.object({
|
|
|
85102
85170
|
}).refine((data) => data.specs.length > 0 || data.freestyle.length > 0, {
|
|
85103
85171
|
message: "Suite must declare at least one spec or freestyle entry"
|
|
85104
85172
|
});
|
|
85105
|
-
var safeJsonParse5 = (0,
|
|
85173
|
+
var safeJsonParse5 = (0, import_neverthrow74.fromThrowable)(
|
|
85106
85174
|
JSON.parse,
|
|
85107
85175
|
(cause) => ({
|
|
85108
85176
|
type: "INVALID_SUITE_CONFIG",
|
|
@@ -85136,16 +85204,16 @@ function parseSuiteConfig(raw) {
|
|
|
85136
85204
|
return safeJsonParse5(raw).andThen((data) => {
|
|
85137
85205
|
const parsed = suiteConfigSchema.safeParse(data);
|
|
85138
85206
|
if (!parsed.success) {
|
|
85139
|
-
return (0,
|
|
85207
|
+
return (0, import_neverthrow75.err)({ type: "INVALID_SUITE_CONFIG", cause: parsed.error });
|
|
85140
85208
|
}
|
|
85141
85209
|
const hooks = normalizeHooks(parsed.data.hooks);
|
|
85142
85210
|
if (hooks === void 0) {
|
|
85143
|
-
return (0,
|
|
85211
|
+
return (0, import_neverthrow75.ok)({
|
|
85144
85212
|
specs: parsed.data.specs,
|
|
85145
85213
|
freestyle: parsed.data.freestyle
|
|
85146
85214
|
});
|
|
85147
85215
|
}
|
|
85148
|
-
return (0,
|
|
85216
|
+
return (0, import_neverthrow75.ok)({
|
|
85149
85217
|
specs: parsed.data.specs,
|
|
85150
85218
|
freestyle: parsed.data.freestyle,
|
|
85151
85219
|
hooks
|
|
@@ -85193,15 +85261,15 @@ function buildFreestyleItems(entries) {
|
|
|
85193
85261
|
}
|
|
85194
85262
|
|
|
85195
85263
|
// src/suite/commands/run/resolve-work-items.ts
|
|
85196
|
-
var safeReadFile5 =
|
|
85197
|
-
async (filePath) =>
|
|
85264
|
+
var safeReadFile5 = import_neverthrow76.ResultAsync.fromThrowable(
|
|
85265
|
+
async (filePath) => import_promises27.default.readFile(filePath, "utf8"),
|
|
85198
85266
|
() => "READ_FAILED"
|
|
85199
85267
|
);
|
|
85200
85268
|
async function resolveGlobs(input) {
|
|
85201
85269
|
return (0, import_fast_glob.default)(input.globs, { cwd: input.cwd, absolute: true });
|
|
85202
85270
|
}
|
|
85203
85271
|
async function loadSuiteConfig(suitesDirectory, name) {
|
|
85204
|
-
const suitePath =
|
|
85272
|
+
const suitePath = import_node_path27.default.join(suitesDirectory, `${name}.suite.json`);
|
|
85205
85273
|
const contentResult = await safeReadFile5(suitePath);
|
|
85206
85274
|
if (contentResult.isErr()) {
|
|
85207
85275
|
return;
|
|
@@ -85261,7 +85329,7 @@ async function resolveAndFilterItems(input) {
|
|
|
85261
85329
|
}
|
|
85262
85330
|
|
|
85263
85331
|
// src/suite/shell/worker-pool.ts
|
|
85264
|
-
var
|
|
85332
|
+
var import_neverthrow79 = __toESM(require_index_cjs(), 1);
|
|
85265
85333
|
|
|
85266
85334
|
// src/suite/core/priority-queue.ts
|
|
85267
85335
|
var PriorityQueue = class {
|
|
@@ -85508,7 +85576,7 @@ function recordHookFailure(input) {
|
|
|
85508
85576
|
}
|
|
85509
85577
|
|
|
85510
85578
|
// src/suite/shell/hook-invoker.ts
|
|
85511
|
-
var
|
|
85579
|
+
var import_neverthrow78 = __toESM(require_index_cjs(), 1);
|
|
85512
85580
|
|
|
85513
85581
|
// src/suite/core/hook-env-builder.ts
|
|
85514
85582
|
function buildReservedKeys(input) {
|
|
@@ -85534,8 +85602,8 @@ function buildHookEnv(input) {
|
|
|
85534
85602
|
}
|
|
85535
85603
|
|
|
85536
85604
|
// src/suite/shell/hook-runner.ts
|
|
85537
|
-
var
|
|
85538
|
-
var
|
|
85605
|
+
var import_node_child_process8 = require("node:child_process");
|
|
85606
|
+
var import_neverthrow77 = __toESM(require_index_cjs(), 1);
|
|
85539
85607
|
function makeDeferred() {
|
|
85540
85608
|
const raw = Promise.withResolvers();
|
|
85541
85609
|
return { promise: raw.promise, resolve: raw.resolve };
|
|
@@ -85555,7 +85623,7 @@ var HookRuntime = class {
|
|
|
85555
85623
|
onAbort;
|
|
85556
85624
|
constructor(options2) {
|
|
85557
85625
|
const { script, cwd, env: env3, baseEnv, nodeExecPath, timeoutMs, signal } = options2;
|
|
85558
|
-
this.child = (0,
|
|
85626
|
+
this.child = (0, import_node_child_process8.spawn)(nodeExecPath, [script], {
|
|
85559
85627
|
cwd,
|
|
85560
85628
|
env: { ...baseEnv, ...env3 },
|
|
85561
85629
|
stdio: ["ignore", "inherit", "pipe"]
|
|
@@ -85565,7 +85633,7 @@ var HookRuntime = class {
|
|
|
85565
85633
|
this.deferred = makeDeferred();
|
|
85566
85634
|
this.onAbort = () => {
|
|
85567
85635
|
this.child.kill("SIGTERM");
|
|
85568
|
-
this.settle((0,
|
|
85636
|
+
this.settle((0, import_neverthrow77.err)({ type: "HOOK_ABORTED" }));
|
|
85569
85637
|
};
|
|
85570
85638
|
}
|
|
85571
85639
|
async start() {
|
|
@@ -85590,20 +85658,20 @@ var HookRuntime = class {
|
|
|
85590
85658
|
attachTimeout() {
|
|
85591
85659
|
this.timeoutHandle = setTimeout(() => {
|
|
85592
85660
|
this.child.kill("SIGTERM");
|
|
85593
|
-
this.settle((0,
|
|
85661
|
+
this.settle((0, import_neverthrow77.err)({ type: "HOOK_TIMEOUT", timeoutMs: this.timeoutMs }));
|
|
85594
85662
|
}, this.timeoutMs);
|
|
85595
85663
|
}
|
|
85596
85664
|
attachChildListeners() {
|
|
85597
85665
|
this.child.on("error", (cause) => {
|
|
85598
|
-
this.settle((0,
|
|
85666
|
+
this.settle((0, import_neverthrow77.err)({ type: "HOOK_SPAWN_FAILED", cause }));
|
|
85599
85667
|
});
|
|
85600
85668
|
this.child.on("exit", (code) => {
|
|
85601
85669
|
if (code === 0) {
|
|
85602
|
-
this.settle((0,
|
|
85670
|
+
this.settle((0, import_neverthrow77.ok)());
|
|
85603
85671
|
return;
|
|
85604
85672
|
}
|
|
85605
85673
|
this.settle(
|
|
85606
|
-
(0,
|
|
85674
|
+
(0, import_neverthrow77.err)({
|
|
85607
85675
|
type: "HOOK_EXIT_NONZERO",
|
|
85608
85676
|
code: code ?? -1,
|
|
85609
85677
|
stderr: this.stderrBuffer
|
|
@@ -85626,7 +85694,7 @@ var HookRuntime = class {
|
|
|
85626
85694
|
this.signal.removeEventListener("abort", this.onAbort);
|
|
85627
85695
|
}
|
|
85628
85696
|
};
|
|
85629
|
-
var safeSpawn =
|
|
85697
|
+
var safeSpawn = import_neverthrow77.ResultAsync.fromThrowable(
|
|
85630
85698
|
spawnHook,
|
|
85631
85699
|
(cause) => ({ type: "HOOK_SPAWN_FAILED", cause })
|
|
85632
85700
|
);
|
|
@@ -85654,7 +85722,7 @@ async function invokeHook(input) {
|
|
|
85654
85722
|
async function maybeInvokeHook(input) {
|
|
85655
85723
|
const { hook: hook2 } = input;
|
|
85656
85724
|
if (hook2 === void 0) {
|
|
85657
|
-
return (0,
|
|
85725
|
+
return (0, import_neverthrow78.ok)();
|
|
85658
85726
|
}
|
|
85659
85727
|
return invokeHook({ ...input, hook: hook2 });
|
|
85660
85728
|
}
|
|
@@ -85748,7 +85816,7 @@ async function processItem(workerContext, item) {
|
|
|
85748
85816
|
workerContext.inFlight.delete(item.id);
|
|
85749
85817
|
return failCount;
|
|
85750
85818
|
}
|
|
85751
|
-
var safeProcessItem =
|
|
85819
|
+
var safeProcessItem = import_neverthrow79.ResultAsync.fromThrowable(
|
|
85752
85820
|
processItem,
|
|
85753
85821
|
(cause) => ({
|
|
85754
85822
|
type: "PROCESS_ITEM_FAILED",
|
|
@@ -85813,7 +85881,7 @@ function runWorkerPool(config2) {
|
|
|
85813
85881
|
const results = [];
|
|
85814
85882
|
const inFlight = /* @__PURE__ */ new Map();
|
|
85815
85883
|
const suiteStartMs = Date.now();
|
|
85816
|
-
const safeRun =
|
|
85884
|
+
const safeRun = import_neverthrow79.ResultAsync.fromThrowable(
|
|
85817
85885
|
async () => runAllWorkers({ config: config2, queue, results, suiteStartMs, inFlight }),
|
|
85818
85886
|
(cause) => ({ type: "WORKER_POOL_FAILED", cause })
|
|
85819
85887
|
);
|
|
@@ -85823,7 +85891,7 @@ function runWorkerPool(config2) {
|
|
|
85823
85891
|
// src/suite/commands/pipeline-config-builder.ts
|
|
85824
85892
|
var import_node_fs11 = require("node:fs");
|
|
85825
85893
|
var import_node_os4 = __toESM(require("node:os"), 1);
|
|
85826
|
-
var
|
|
85894
|
+
var import_node_path28 = __toESM(require("node:path"), 1);
|
|
85827
85895
|
var DEFAULT_FREESTYLE_TIMEOUT_SECONDS2 = 300;
|
|
85828
85896
|
function buildDeviceInstruction(simulatorUdid) {
|
|
85829
85897
|
return `You MUST use device "${simulatorUdid}" for ALL mobile tool calls. The simulator UDID is already configured \u2014 use it directly.`;
|
|
@@ -85832,7 +85900,7 @@ function composeAppContext(parts) {
|
|
|
85832
85900
|
return parts.filter((part) => part !== void 0 && part.length > 0).join("\n\n");
|
|
85833
85901
|
}
|
|
85834
85902
|
function ensureWorkerCwd(simulatorUdid) {
|
|
85835
|
-
const workerDirectory =
|
|
85903
|
+
const workerDirectory = import_node_path28.default.join(import_node_os4.default.tmpdir(), "xqa-workers", simulatorUdid);
|
|
85836
85904
|
(0, import_node_fs11.mkdirSync)(workerDirectory, { recursive: true });
|
|
85837
85905
|
return workerDirectory;
|
|
85838
85906
|
}
|
|
@@ -85898,7 +85966,7 @@ function buildPipelineConfig2(input) {
|
|
|
85898
85966
|
const { item, context, signal, simulatorUdid, onEvent } = input;
|
|
85899
85967
|
const { xqaDirectory, runId, config: config2, rootConfig } = context;
|
|
85900
85968
|
const base = {
|
|
85901
|
-
outputDir:
|
|
85969
|
+
outputDir: import_node_path28.default.join(xqaDirectory, "output", item.id),
|
|
85902
85970
|
runId,
|
|
85903
85971
|
simulatorUdid,
|
|
85904
85972
|
signal,
|
|
@@ -85967,25 +86035,25 @@ function buildSuiteFindings(input) {
|
|
|
85967
86035
|
}
|
|
85968
86036
|
|
|
85969
86037
|
// src/suite/shell/suite-findings-writer.ts
|
|
85970
|
-
var
|
|
85971
|
-
var
|
|
85972
|
-
var
|
|
86038
|
+
var import_promises28 = __toESM(require("node:fs/promises"), 1);
|
|
86039
|
+
var import_node_path29 = __toESM(require("node:path"), 1);
|
|
86040
|
+
var import_neverthrow80 = __toESM(require_index_cjs(), 1);
|
|
85973
86041
|
var INDENT_SPACES = 2;
|
|
85974
86042
|
function writeSuiteFindings(findings, options2) {
|
|
85975
|
-
const directory =
|
|
86043
|
+
const directory = import_node_path29.default.join(
|
|
85976
86044
|
options2.outputDirectory,
|
|
85977
86045
|
"suite",
|
|
85978
86046
|
findings.suiteId,
|
|
85979
86047
|
options2.date,
|
|
85980
86048
|
findings.runId
|
|
85981
86049
|
);
|
|
85982
|
-
const finalPath =
|
|
86050
|
+
const finalPath = import_node_path29.default.join(directory, "findings.json");
|
|
85983
86051
|
const temporaryPath = `${finalPath}.tmp`;
|
|
85984
|
-
const safeWriteAtomically =
|
|
86052
|
+
const safeWriteAtomically = import_neverthrow80.ResultAsync.fromThrowable(
|
|
85985
86053
|
async () => {
|
|
85986
|
-
await
|
|
85987
|
-
await
|
|
85988
|
-
await
|
|
86054
|
+
await import_promises28.default.mkdir(directory, { recursive: true });
|
|
86055
|
+
await import_promises28.default.writeFile(temporaryPath, JSON.stringify(findings, void 0, INDENT_SPACES));
|
|
86056
|
+
await import_promises28.default.rename(temporaryPath, finalPath);
|
|
85989
86057
|
return finalPath;
|
|
85990
86058
|
},
|
|
85991
86059
|
(cause) => ({ type: "FINDINGS_WRITE_FAILED", cause })
|
|
@@ -86013,9 +86081,9 @@ async function writeAndReport(input) {
|
|
|
86013
86081
|
}
|
|
86014
86082
|
|
|
86015
86083
|
// src/suite/commands/suite-run-context.ts
|
|
86016
|
-
var
|
|
86017
|
-
var
|
|
86018
|
-
var
|
|
86084
|
+
var import_promises29 = __toESM(require("node:fs/promises"), 1);
|
|
86085
|
+
var import_node_path30 = __toESM(require("node:path"), 1);
|
|
86086
|
+
var import_neverthrow81 = __toESM(require_index_cjs(), 1);
|
|
86019
86087
|
|
|
86020
86088
|
// src/suite/core/run-id.ts
|
|
86021
86089
|
var RUN_ID_PAD_LENGTH2 = 4;
|
|
@@ -86050,16 +86118,16 @@ function deriveSuiteId(input) {
|
|
|
86050
86118
|
|
|
86051
86119
|
// src/suite/commands/suite-run-context.ts
|
|
86052
86120
|
var ISO_DATE_LENGTH3 = 10;
|
|
86053
|
-
var safeReaddir3 =
|
|
86121
|
+
var safeReaddir3 = import_neverthrow81.ResultAsync.fromThrowable(
|
|
86054
86122
|
async (directoryPath) => {
|
|
86055
|
-
const entries = await
|
|
86123
|
+
const entries = await import_promises29.default.readdir(directoryPath, { withFileTypes: true });
|
|
86056
86124
|
return entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name);
|
|
86057
86125
|
},
|
|
86058
86126
|
() => "READDIR_FAILED"
|
|
86059
86127
|
);
|
|
86060
86128
|
async function listRunDirectories(input) {
|
|
86061
86129
|
const { outputDirectory, suiteId, date: date5 } = input;
|
|
86062
|
-
const directoryPath =
|
|
86130
|
+
const directoryPath = import_node_path30.default.join(outputDirectory, "suite", suiteId, date5);
|
|
86063
86131
|
const result = await safeReaddir3(directoryPath);
|
|
86064
86132
|
return result.unwrapOr([]);
|
|
86065
86133
|
}
|
|
@@ -86083,7 +86151,7 @@ ${cause}
|
|
|
86083
86151
|
async function buildSuiteRunContext(input) {
|
|
86084
86152
|
const suiteId = deriveSuiteIdFromMode(input.mode);
|
|
86085
86153
|
const date5 = (/* @__PURE__ */ new Date()).toISOString().slice(0, ISO_DATE_LENGTH3);
|
|
86086
|
-
const outputDirectory =
|
|
86154
|
+
const outputDirectory = import_node_path30.default.join(input.xqaDirectory, "output");
|
|
86087
86155
|
const existingDirectories = await listRunDirectories({ outputDirectory, suiteId, date: date5 });
|
|
86088
86156
|
const runId = computeNextRunId2(existingDirectories);
|
|
86089
86157
|
const appContext = await loadAppContext(input.xqaDirectory);
|
|
@@ -86185,18 +86253,18 @@ async function runSuiteCommand(input) {
|
|
|
86185
86253
|
}
|
|
86186
86254
|
|
|
86187
86255
|
// src/suite/commands/validate-run-arguments.ts
|
|
86188
|
-
var
|
|
86256
|
+
var import_neverthrow82 = __toESM(require_index_cjs(), 1);
|
|
86189
86257
|
function validateRunArguments(options2) {
|
|
86190
86258
|
if (options2.suite === void 0 && options2.spec === void 0) {
|
|
86191
|
-
return (0,
|
|
86259
|
+
return (0, import_neverthrow82.err)({ type: "MISSING_SUITE_OR_SPEC" });
|
|
86192
86260
|
}
|
|
86193
86261
|
if (options2.suite !== void 0 && options2.spec !== void 0) {
|
|
86194
|
-
return (0,
|
|
86262
|
+
return (0, import_neverthrow82.err)({ type: "BOTH_SUITE_AND_SPEC" });
|
|
86195
86263
|
}
|
|
86196
86264
|
if (options2.only !== void 0 && options2.suite === void 0) {
|
|
86197
|
-
return (0,
|
|
86265
|
+
return (0, import_neverthrow82.err)({ type: "ONLY_REQUIRES_SUITE" });
|
|
86198
86266
|
}
|
|
86199
|
-
return (0,
|
|
86267
|
+
return (0, import_neverthrow82.ok)(
|
|
86200
86268
|
options2.suite === void 0 ? { type: "spec", globs: options2.spec ?? [] } : { type: "suite", name: options2.suite }
|
|
86201
86269
|
);
|
|
86202
86270
|
}
|
|
@@ -86244,10 +86312,10 @@ function registerRunCommand(program3, loader2) {
|
|
|
86244
86312
|
}
|
|
86245
86313
|
|
|
86246
86314
|
// src/commands/spec/runner.ts
|
|
86247
|
-
var
|
|
86315
|
+
var import_node_path34 = __toESM(require("node:path"), 1);
|
|
86248
86316
|
|
|
86249
86317
|
// src/commands/spec/pipeline-config.ts
|
|
86250
|
-
var
|
|
86318
|
+
var import_node_path31 = __toESM(require("node:path"), 1);
|
|
86251
86319
|
function buildInspector3(context) {
|
|
86252
86320
|
const { inspector } = context.rootConfig.agents;
|
|
86253
86321
|
if (!inspector.enabled) {
|
|
@@ -86272,7 +86340,7 @@ function buildSpecExplorer2(context) {
|
|
|
86272
86340
|
}
|
|
86273
86341
|
function buildPipelineConfig3({ input, context, onEvent }) {
|
|
86274
86342
|
return {
|
|
86275
|
-
outputDir:
|
|
86343
|
+
outputDir: import_node_path31.default.join(context.xqaDirectory, "output", context.slug),
|
|
86276
86344
|
signal: input.signal,
|
|
86277
86345
|
onEvent,
|
|
86278
86346
|
inspector: buildInspector3(context),
|
|
@@ -86331,13 +86399,13 @@ function handleSpecResult(state, context) {
|
|
|
86331
86399
|
}
|
|
86332
86400
|
|
|
86333
86401
|
// src/spec-slug.ts
|
|
86334
|
-
var
|
|
86402
|
+
var import_node_path32 = __toESM(require("node:path"), 1);
|
|
86335
86403
|
var SPECS_DIR = "specs";
|
|
86336
86404
|
function stripExtensions(filename) {
|
|
86337
86405
|
return filename.replace(/\.test\.md$/, "").replace(/\.[^.]+$/, "");
|
|
86338
86406
|
}
|
|
86339
86407
|
function deriveSpecSlug(specFilePath) {
|
|
86340
|
-
const parts = specFilePath.split(
|
|
86408
|
+
const parts = specFilePath.split(import_node_path32.default.sep);
|
|
86341
86409
|
const specsIndex = parts.lastIndexOf(SPECS_DIR);
|
|
86342
86410
|
if (specsIndex !== -1) {
|
|
86343
86411
|
const relativeParts = parts.slice(specsIndex + 1);
|
|
@@ -86345,60 +86413,60 @@ function deriveSpecSlug(specFilePath) {
|
|
|
86345
86413
|
relativeParts[relativeParts.length - 1] = stripExtensions(last);
|
|
86346
86414
|
return relativeParts.join("__");
|
|
86347
86415
|
}
|
|
86348
|
-
return stripExtensions(
|
|
86416
|
+
return stripExtensions(import_node_path32.default.basename(specFilePath));
|
|
86349
86417
|
}
|
|
86350
86418
|
|
|
86351
86419
|
// src/commands/spec-resolver.ts
|
|
86352
86420
|
var import_node_fs12 = require("node:fs");
|
|
86353
|
-
var
|
|
86354
|
-
var
|
|
86421
|
+
var import_node_path33 = __toESM(require("node:path"), 1);
|
|
86422
|
+
var import_neverthrow84 = __toESM(require_index_cjs(), 1);
|
|
86355
86423
|
|
|
86356
86424
|
// src/spec-frontmatter.ts
|
|
86357
86425
|
var import_gray_matter = __toESM(require_gray_matter(), 1);
|
|
86358
|
-
var
|
|
86426
|
+
var import_neverthrow83 = __toESM(require_index_cjs(), 1);
|
|
86359
86427
|
var frontmatterSchema = external_exports.object({
|
|
86360
86428
|
feature: external_exports.string().min(1),
|
|
86361
86429
|
timeout: external_exports.number().int().positive().optional()
|
|
86362
86430
|
});
|
|
86363
|
-
var safeParseMatter = (0,
|
|
86431
|
+
var safeParseMatter = (0, import_neverthrow83.fromThrowable)(
|
|
86364
86432
|
import_gray_matter.default,
|
|
86365
86433
|
(cause) => ({ type: "SPEC_FRONTMATTER_INVALID", cause })
|
|
86366
86434
|
);
|
|
86367
86435
|
function validate(data) {
|
|
86368
86436
|
const parsed = frontmatterSchema.safeParse(data);
|
|
86369
86437
|
if (!parsed.success) {
|
|
86370
|
-
return (0,
|
|
86438
|
+
return (0, import_neverthrow83.err)({ type: "SPEC_FRONTMATTER_INVALID", cause: parsed.error });
|
|
86371
86439
|
}
|
|
86372
86440
|
const { feature, timeout } = parsed.data;
|
|
86373
86441
|
if (timeout === void 0) {
|
|
86374
|
-
return (0,
|
|
86442
|
+
return (0, import_neverthrow83.ok)({ feature });
|
|
86375
86443
|
}
|
|
86376
|
-
return (0,
|
|
86444
|
+
return (0, import_neverthrow83.ok)({ feature, timeoutSeconds: timeout });
|
|
86377
86445
|
}
|
|
86378
86446
|
function parseSpecFrontmatter(raw) {
|
|
86379
86447
|
return safeParseMatter(raw).andThen((parsed) => validate(parsed.data));
|
|
86380
86448
|
}
|
|
86381
86449
|
|
|
86382
86450
|
// src/commands/spec-resolver.ts
|
|
86383
|
-
var safeReadFile6 = (0,
|
|
86384
|
-
var safeReaddir4 = (0,
|
|
86451
|
+
var safeReadFile6 = (0, import_neverthrow84.fromThrowable)((filePath) => (0, import_node_fs12.readFileSync)(filePath, "utf8"));
|
|
86452
|
+
var safeReaddir4 = (0, import_neverthrow84.fromThrowable)(
|
|
86385
86453
|
(directory) => (0, import_node_fs12.readdirSync)(directory, { recursive: true, encoding: "utf8" })
|
|
86386
86454
|
);
|
|
86387
86455
|
var CANCEL = "xqa:cancel";
|
|
86388
|
-
var safeSelect =
|
|
86456
|
+
var safeSelect = import_neverthrow84.ResultAsync.fromThrowable(
|
|
86389
86457
|
esm_default11,
|
|
86390
86458
|
(error48) => error48 instanceof Error && error48.name === "ExitPromptError" ? "cancelled" : "failed"
|
|
86391
86459
|
);
|
|
86392
86460
|
function findSpecFiles(xqaDirectory) {
|
|
86393
|
-
const specsDirectory =
|
|
86394
|
-
return safeReaddir4(specsDirectory).unwrapOr([]).filter((file2) => file2.endsWith(".test.md")).map((file2) =>
|
|
86461
|
+
const specsDirectory = import_node_path33.default.join(xqaDirectory, "specs");
|
|
86462
|
+
return safeReaddir4(specsDirectory).unwrapOr([]).filter((file2) => file2.endsWith(".test.md")).map((file2) => import_node_path33.default.join(specsDirectory, file2));
|
|
86395
86463
|
}
|
|
86396
86464
|
async function promptForSpec(specFiles, xqaDirectory) {
|
|
86397
86465
|
const result = await safeSelect({
|
|
86398
86466
|
message: "Select a spec",
|
|
86399
86467
|
choices: [
|
|
86400
86468
|
...specFiles.map((specFile) => ({
|
|
86401
|
-
name:
|
|
86469
|
+
name: import_node_path33.default.relative(xqaDirectory, specFile),
|
|
86402
86470
|
value: specFile
|
|
86403
86471
|
})),
|
|
86404
86472
|
new Separator(),
|
|
@@ -86448,7 +86516,7 @@ async function executeSpec(input, context) {
|
|
|
86448
86516
|
const identity = {
|
|
86449
86517
|
display: createSoloDisplay(input.verbose),
|
|
86450
86518
|
itemId: "spec",
|
|
86451
|
-
itemName:
|
|
86519
|
+
itemName: import_node_path34.default.basename(context.absolutePath, ".test.md"),
|
|
86452
86520
|
simulatorUdid: ""
|
|
86453
86521
|
};
|
|
86454
86522
|
const startedAt = Date.now();
|
|
@@ -86483,7 +86551,7 @@ async function resolveSpecContext(input, options2) {
|
|
|
86483
86551
|
if (resolvedSpecFile === void 0) {
|
|
86484
86552
|
return;
|
|
86485
86553
|
}
|
|
86486
|
-
const absolutePath =
|
|
86554
|
+
const absolutePath = import_node_path34.default.resolve(resolvedSpecFile);
|
|
86487
86555
|
const frontmatter = readAndParseSpec(absolutePath);
|
|
86488
86556
|
if (frontmatter === void 0) {
|
|
86489
86557
|
return;
|
|
@@ -86528,7 +86596,7 @@ function registerSpecCommand(program3, loader2) {
|
|
|
86528
86596
|
}
|
|
86529
86597
|
|
|
86530
86598
|
// ../../agents/triager/dist/index.js
|
|
86531
|
-
var
|
|
86599
|
+
var import_neverthrow85 = __toESM(require_index_cjs(), 1);
|
|
86532
86600
|
|
|
86533
86601
|
// ../../node_modules/.pnpm/balanced-match@4.0.4/node_modules/balanced-match/dist/esm/index.js
|
|
86534
86602
|
var balanced = (a3, b, str3) => {
|
|
@@ -88333,14 +88401,14 @@ minimatch.escape = escape2;
|
|
|
88333
88401
|
minimatch.unescape = unescape2;
|
|
88334
88402
|
|
|
88335
88403
|
// ../../agents/triager/dist/index.js
|
|
88336
|
-
var import_neverthrow85 = __toESM(require_index_cjs(), 1);
|
|
88337
|
-
var import_promises31 = require("node:fs/promises");
|
|
88338
88404
|
var import_neverthrow86 = __toESM(require_index_cjs(), 1);
|
|
88339
|
-
var
|
|
88340
|
-
var import_promises32 = require("node:fs/promises");
|
|
88341
|
-
var import_node_path36 = __toESM(require("node:path"), 1);
|
|
88405
|
+
var import_promises30 = require("node:fs/promises");
|
|
88342
88406
|
var import_neverthrow87 = __toESM(require_index_cjs(), 1);
|
|
88407
|
+
var import_node_child_process9 = require("node:child_process");
|
|
88408
|
+
var import_promises31 = require("node:fs/promises");
|
|
88409
|
+
var import_node_path35 = __toESM(require("node:path"), 1);
|
|
88343
88410
|
var import_neverthrow88 = __toESM(require_index_cjs(), 1);
|
|
88411
|
+
var import_neverthrow89 = __toESM(require_index_cjs(), 1);
|
|
88344
88412
|
function resolveConfidence2(selected) {
|
|
88345
88413
|
if (selected.some((pick2) => pick2.confidence === "HIGH")) {
|
|
88346
88414
|
return "high";
|
|
@@ -88959,7 +89027,7 @@ function buildMcpServer(state, options2) {
|
|
|
88959
89027
|
});
|
|
88960
89028
|
return xx({ name: TRIAGER_MCP_SERVER_NAME, version: "0.0.0", tools });
|
|
88961
89029
|
}
|
|
88962
|
-
function
|
|
89030
|
+
function buildAllowedTools2() {
|
|
88963
89031
|
return [
|
|
88964
89032
|
`${TOOL_PREFIX}read_spec`,
|
|
88965
89033
|
`${TOOL_PREFIX}read_app_section`,
|
|
@@ -88970,7 +89038,7 @@ function buildAllowedTools() {
|
|
|
88970
89038
|
function buildQueryOptions2(input) {
|
|
88971
89039
|
return {
|
|
88972
89040
|
mcpServers: { [TRIAGER_MCP_SERVER_NAME]: input.server },
|
|
88973
|
-
allowedTools:
|
|
89041
|
+
allowedTools: buildAllowedTools2(),
|
|
88974
89042
|
tools: [],
|
|
88975
89043
|
permissionMode: "bypassPermissions",
|
|
88976
89044
|
allowDangerouslySkipPermissions: true,
|
|
@@ -89005,7 +89073,7 @@ async function drainMessages(runner, state) {
|
|
|
89005
89073
|
}
|
|
89006
89074
|
}
|
|
89007
89075
|
}
|
|
89008
|
-
var safeDrainMessages =
|
|
89076
|
+
var safeDrainMessages = import_neverthrow86.ResultAsync.fromThrowable(
|
|
89009
89077
|
drainMessages,
|
|
89010
89078
|
(cause) => ({ type: "AI_CALL_FAILED", cause })
|
|
89011
89079
|
);
|
|
@@ -89031,25 +89099,25 @@ function finalizeRun(bootstrap) {
|
|
|
89031
89099
|
const telemetry = buildTelemetry(bootstrap.telemetryInput, bootstrap.state);
|
|
89032
89100
|
const error48 = resolveError(bootstrap.state);
|
|
89033
89101
|
if (error48 !== void 0) {
|
|
89034
|
-
return (0,
|
|
89102
|
+
return (0, import_neverthrow86.errAsync)(error48);
|
|
89035
89103
|
}
|
|
89036
89104
|
const output = bootstrap.state.output;
|
|
89037
89105
|
if (output === void 0) {
|
|
89038
|
-
return (0,
|
|
89106
|
+
return (0, import_neverthrow86.errAsync)({ type: "AI_NO_FINAL_TOOL_CALL" });
|
|
89039
89107
|
}
|
|
89040
89108
|
bootstrap.reportTelemetry(telemetry);
|
|
89041
|
-
return (0,
|
|
89109
|
+
return (0, import_neverthrow86.okAsync)({ picks: output.picks, metaPr: output.metaPr, telemetry });
|
|
89042
89110
|
}
|
|
89043
89111
|
function launchQuery(input) {
|
|
89044
|
-
const safeLaunch = (0,
|
|
89112
|
+
const safeLaunch = (0, import_neverthrow86.fromThrowable)(
|
|
89045
89113
|
input.queryRunner,
|
|
89046
89114
|
(cause) => ({ type: "AI_CALL_FAILED", cause })
|
|
89047
89115
|
);
|
|
89048
89116
|
const result = safeLaunch({ prompt: input.inputQueue, options: input.queryOptions });
|
|
89049
89117
|
if (result.isErr()) {
|
|
89050
|
-
return (0,
|
|
89118
|
+
return (0, import_neverthrow86.errAsync)(result.error);
|
|
89051
89119
|
}
|
|
89052
|
-
return (0,
|
|
89120
|
+
return (0, import_neverthrow86.okAsync)(result.value);
|
|
89053
89121
|
}
|
|
89054
89122
|
function runPipeline4(bootstrap) {
|
|
89055
89123
|
return launchQuery({
|
|
@@ -89103,9 +89171,9 @@ var STATIC_ONLY_FIELDS = {
|
|
|
89103
89171
|
freestyleByGroup: /* @__PURE__ */ new Map(),
|
|
89104
89172
|
appIndex: [],
|
|
89105
89173
|
handlers: {
|
|
89106
|
-
readSpec: () => (0,
|
|
89107
|
-
readAppSection: () => (0,
|
|
89108
|
-
grepCodebase: () => (0,
|
|
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: "" })
|
|
89109
89177
|
}
|
|
89110
89178
|
};
|
|
89111
89179
|
function resolveAiFields(config2) {
|
|
@@ -89226,15 +89294,15 @@ function runAiTiebreaker(context, staticPicks) {
|
|
|
89226
89294
|
function runTriager(options2) {
|
|
89227
89295
|
const { groups, config: config2 } = options2;
|
|
89228
89296
|
if (groups.length === 0) {
|
|
89229
|
-
return (0,
|
|
89297
|
+
return (0, import_neverthrow85.errAsync)({ type: "NO_GROUPS" });
|
|
89230
89298
|
}
|
|
89231
89299
|
if (config2?.useAi === true && config2.ai === void 0) {
|
|
89232
|
-
return (0,
|
|
89300
|
+
return (0, import_neverthrow85.errAsync)({ type: "AI_CONFIG_MISSING" });
|
|
89233
89301
|
}
|
|
89234
89302
|
const context = buildContext2(options2);
|
|
89235
89303
|
const staticPicks = scoreGroups(context.diff, context.groups);
|
|
89236
89304
|
if (!context.useAi) {
|
|
89237
|
-
return (0,
|
|
89305
|
+
return (0, import_neverthrow85.okAsync)(buildDecision({ picks: staticPicks, metaPr: false }));
|
|
89238
89306
|
}
|
|
89239
89307
|
return runAiTiebreaker(context, staticPicks);
|
|
89240
89308
|
}
|
|
@@ -89295,17 +89363,17 @@ function parseSections(text) {
|
|
|
89295
89363
|
function lookupSection(sections, screenName) {
|
|
89296
89364
|
const section = sections.get(screenName);
|
|
89297
89365
|
if (section === void 0) {
|
|
89298
|
-
return (0,
|
|
89366
|
+
return (0, import_neverthrow87.errAsync)({ type: "SECTION_NOT_FOUND", screenName });
|
|
89299
89367
|
}
|
|
89300
|
-
return (0,
|
|
89368
|
+
return (0, import_neverthrow87.okAsync)(section);
|
|
89301
89369
|
}
|
|
89302
89370
|
async function readUtf8File(filePath) {
|
|
89303
|
-
return (0,
|
|
89371
|
+
return (0, import_promises30.readFile)(filePath, UTF8);
|
|
89304
89372
|
}
|
|
89305
89373
|
function createAppMdReader(options2) {
|
|
89306
89374
|
const filePath = options2.path;
|
|
89307
89375
|
let sectionCache;
|
|
89308
|
-
const safeReadFile7 =
|
|
89376
|
+
const safeReadFile7 = import_neverthrow87.ResultAsync.fromThrowable(
|
|
89309
89377
|
readUtf8File,
|
|
89310
89378
|
(cause) => classifyReadError(cause, filePath)
|
|
89311
89379
|
);
|
|
@@ -89342,7 +89410,7 @@ function buildSpawnExitError(code, stderr) {
|
|
|
89342
89410
|
}
|
|
89343
89411
|
async function runExecFile(request2) {
|
|
89344
89412
|
const { promise: promise2, resolve, reject } = Promise.withResolvers();
|
|
89345
|
-
const child = (0,
|
|
89413
|
+
const child = (0, import_node_child_process9.spawn)(request2.binary, [...request2.arguments_], { cwd: request2.cwd });
|
|
89346
89414
|
const stdoutChunks = [];
|
|
89347
89415
|
const stderrChunks = [];
|
|
89348
89416
|
child.stdout.on("data", (chunk) => {
|
|
@@ -89366,10 +89434,10 @@ async function runExecFile(request2) {
|
|
|
89366
89434
|
return promise2;
|
|
89367
89435
|
}
|
|
89368
89436
|
function resolveFilePath(filePath, cwd) {
|
|
89369
|
-
if (
|
|
89437
|
+
if (import_node_path35.default.isAbsolute(filePath)) {
|
|
89370
89438
|
return filePath;
|
|
89371
89439
|
}
|
|
89372
|
-
return
|
|
89440
|
+
return import_node_path35.default.resolve(cwd, filePath);
|
|
89373
89441
|
}
|
|
89374
89442
|
function classifyReadError2(cause, resolvedPath) {
|
|
89375
89443
|
const nodeError = cause;
|
|
@@ -89423,24 +89491,24 @@ async function invokeRipgrep(options2) {
|
|
|
89423
89491
|
return runExecFile({ binary: binary2, arguments_, cwd });
|
|
89424
89492
|
}
|
|
89425
89493
|
function execRipgrepRaw(options2) {
|
|
89426
|
-
const safeExec =
|
|
89494
|
+
const safeExec = import_neverthrow88.ResultAsync.fromThrowable(invokeRipgrep, classifyRawExecError);
|
|
89427
89495
|
return safeExec(options2);
|
|
89428
89496
|
}
|
|
89429
89497
|
function handleExecResult(options2) {
|
|
89430
89498
|
return execRipgrepRaw(options2).orElse((error48) => {
|
|
89431
89499
|
if (error48.type === "GREP_FAILED" && error48.cause.code === RIPGREP_NO_MATCH_CODE) {
|
|
89432
|
-
return (0,
|
|
89500
|
+
return (0, import_neverthrow88.ok)({ stdout: "", stderr: "" });
|
|
89433
89501
|
}
|
|
89434
|
-
return (0,
|
|
89502
|
+
return (0, import_neverthrow88.err)(error48);
|
|
89435
89503
|
});
|
|
89436
89504
|
}
|
|
89437
89505
|
async function readUtf8File2(filePath) {
|
|
89438
|
-
return (0,
|
|
89506
|
+
return (0, import_promises31.readFile)(filePath, "utf8");
|
|
89439
89507
|
}
|
|
89440
89508
|
function makeReadFile(cwd) {
|
|
89441
89509
|
return (filePath) => {
|
|
89442
89510
|
const resolvedPath = resolveFilePath(filePath, cwd);
|
|
89443
|
-
const safeRead =
|
|
89511
|
+
const safeRead = import_neverthrow88.ResultAsync.fromThrowable(
|
|
89444
89512
|
readUtf8File2,
|
|
89445
89513
|
(cause) => classifyReadError2(cause, resolvedPath)
|
|
89446
89514
|
);
|
|
@@ -89507,9 +89575,9 @@ function applyHeading(state, screenName) {
|
|
|
89507
89575
|
function handleHeading(state, indexed) {
|
|
89508
89576
|
const screenName = indexed.text.slice(LEVEL_2_HEADING_MARKER.length).trim();
|
|
89509
89577
|
if (screenName.length === 0) {
|
|
89510
|
-
return (0,
|
|
89578
|
+
return (0, import_neverthrow89.err)({ type: "APP_MD_MALFORMED", line: indexed.number });
|
|
89511
89579
|
}
|
|
89512
|
-
return (0,
|
|
89580
|
+
return (0, import_neverthrow89.ok)(applyHeading(state, screenName));
|
|
89513
89581
|
}
|
|
89514
89582
|
function handleFenceLine(state, lineNumber) {
|
|
89515
89583
|
if (state.insideFence) {
|
|
@@ -89543,23 +89611,23 @@ function isLevel2Heading(line) {
|
|
|
89543
89611
|
}
|
|
89544
89612
|
function processLine2(state, indexed) {
|
|
89545
89613
|
if (indexed.text.startsWith(FENCE_MARKER)) {
|
|
89546
|
-
return (0,
|
|
89614
|
+
return (0, import_neverthrow89.ok)(handleFenceLine(state, indexed.number));
|
|
89547
89615
|
}
|
|
89548
89616
|
if (state.insideFence) {
|
|
89549
|
-
return (0,
|
|
89617
|
+
return (0, import_neverthrow89.ok)(state);
|
|
89550
89618
|
}
|
|
89551
89619
|
if (isLevel2Heading(indexed.text)) {
|
|
89552
89620
|
return handleHeading(state, indexed);
|
|
89553
89621
|
}
|
|
89554
89622
|
if (indexed.text.trim().length === 0) {
|
|
89555
|
-
return (0,
|
|
89623
|
+
return (0, import_neverthrow89.ok)(handleBlankLine(state));
|
|
89556
89624
|
}
|
|
89557
|
-
return (0,
|
|
89625
|
+
return (0, import_neverthrow89.ok)(handleContentLine(state, indexed.text));
|
|
89558
89626
|
}
|
|
89559
89627
|
function processIndexedLines(indexedLines, state) {
|
|
89560
89628
|
const [head, ...tail] = indexedLines;
|
|
89561
89629
|
if (head === void 0) {
|
|
89562
|
-
return (0,
|
|
89630
|
+
return (0, import_neverthrow89.ok)(state);
|
|
89563
89631
|
}
|
|
89564
89632
|
return processLine2(state, head).andThen((next) => processIndexedLines(tail, next));
|
|
89565
89633
|
}
|
|
@@ -89571,9 +89639,9 @@ function buildFinalEntries(state) {
|
|
|
89571
89639
|
}
|
|
89572
89640
|
function finaliseState(state) {
|
|
89573
89641
|
if (state.insideFence) {
|
|
89574
|
-
return (0,
|
|
89642
|
+
return (0, import_neverthrow89.err)({ type: "APP_MD_MALFORMED", line: state.fenceOpenLine });
|
|
89575
89643
|
}
|
|
89576
|
-
return (0,
|
|
89644
|
+
return (0, import_neverthrow89.ok)([...buildFinalEntries(state)]);
|
|
89577
89645
|
}
|
|
89578
89646
|
function buildAppIndex(appMd) {
|
|
89579
89647
|
const indexedLines = toIndexedLines(appMd.split("\n"));
|
|
@@ -89604,11 +89672,11 @@ function summariseSpec(input) {
|
|
|
89604
89672
|
var triagerConfigSchema = agentBaseConfigSchema.extend({ enabled: external_exports.boolean().default(false) }).strict();
|
|
89605
89673
|
|
|
89606
89674
|
// src/commands/triage-command.ts
|
|
89607
|
-
var
|
|
89675
|
+
var import_neverthrow94 = __toESM(require_index_cjs(), 1);
|
|
89608
89676
|
|
|
89609
89677
|
// src/triage/ai-context-builder.ts
|
|
89610
|
-
var
|
|
89611
|
-
var
|
|
89678
|
+
var import_node_path36 = __toESM(require("node:path"), 1);
|
|
89679
|
+
var import_neverthrow90 = __toESM(require_index_cjs(), 1);
|
|
89612
89680
|
var PROMPT_VERSION = "v1";
|
|
89613
89681
|
var MAX_GREP_PATTERN_LENGTH = 200;
|
|
89614
89682
|
var DENIED_SAMPLE_PATHS = [
|
|
@@ -89687,11 +89755,11 @@ function isDeniedGlob(pathGlob) {
|
|
|
89687
89755
|
return normalized !== pathGlob && matchesDeniedSample(normalized);
|
|
89688
89756
|
}
|
|
89689
89757
|
function pathDenied(reason) {
|
|
89690
|
-
return (0,
|
|
89758
|
+
return (0, import_neverthrow90.errAsync)({ type: "PATH_DENIED", reason });
|
|
89691
89759
|
}
|
|
89692
89760
|
function buildHandlers(cwd, validSpecIds) {
|
|
89693
89761
|
const reader = createCodebaseReader({ cwd });
|
|
89694
|
-
const appMdPath =
|
|
89762
|
+
const appMdPath = import_node_path36.default.join(cwd, "app.md");
|
|
89695
89763
|
const appMdReader = createAppMdReader({ path: appMdPath });
|
|
89696
89764
|
return {
|
|
89697
89765
|
readSpec: (id) => {
|
|
@@ -89713,20 +89781,20 @@ function buildHandlers(cwd, validSpecIds) {
|
|
|
89713
89781
|
};
|
|
89714
89782
|
}
|
|
89715
89783
|
function resolveAppMdPath(suitesDirectory) {
|
|
89716
|
-
return
|
|
89784
|
+
return import_node_path36.default.join(import_node_path36.default.dirname(import_node_path36.default.resolve(suitesDirectory)), "app.md");
|
|
89717
89785
|
}
|
|
89718
89786
|
function loadAppIndex(appMdPath) {
|
|
89719
|
-
const appMdReader = createCodebaseReader({ cwd:
|
|
89787
|
+
const appMdReader = createCodebaseReader({ cwd: import_node_path36.default.dirname(appMdPath) });
|
|
89720
89788
|
return appMdReader.readFile(appMdPath).mapErr(() => ({ type: "SPEC_NOT_FOUND", path: appMdPath })).andThen((content) => {
|
|
89721
89789
|
const indexResult = buildAppIndex(content);
|
|
89722
89790
|
if (indexResult.isErr()) {
|
|
89723
|
-
return (0,
|
|
89791
|
+
return (0, import_neverthrow90.errAsync)({
|
|
89724
89792
|
type: "SUITE_INVALID",
|
|
89725
89793
|
path: appMdPath,
|
|
89726
89794
|
cause: indexResult.error
|
|
89727
89795
|
});
|
|
89728
89796
|
}
|
|
89729
|
-
return (0,
|
|
89797
|
+
return (0, import_neverthrow90.okAsync)(indexResult.value);
|
|
89730
89798
|
});
|
|
89731
89799
|
}
|
|
89732
89800
|
function collectSpecIds(specSummariesByGroup) {
|
|
@@ -93301,7 +93369,7 @@ var Octokit2 = Octokit.plugin(requestLog, legacyRestEndpointMethods, paginateRes
|
|
|
93301
93369
|
);
|
|
93302
93370
|
|
|
93303
93371
|
// src/triage/github-pr-fetcher.ts
|
|
93304
|
-
var
|
|
93372
|
+
var import_neverthrow91 = __toESM(require_index_cjs(), 1);
|
|
93305
93373
|
var STATUS_MAP = {
|
|
93306
93374
|
added: "added",
|
|
93307
93375
|
modified: "modified",
|
|
@@ -93337,11 +93405,11 @@ async function runListFiles(octokit, options2) {
|
|
|
93337
93405
|
per_page: 100
|
|
93338
93406
|
});
|
|
93339
93407
|
}
|
|
93340
|
-
var safeGet =
|
|
93408
|
+
var safeGet = import_neverthrow91.ResultAsync.fromThrowable(
|
|
93341
93409
|
runPullRequestGet,
|
|
93342
93410
|
(cause) => ({ type: "PR_FETCH_FAILED", cause })
|
|
93343
93411
|
);
|
|
93344
|
-
var safeList =
|
|
93412
|
+
var safeList = import_neverthrow91.ResultAsync.fromThrowable(
|
|
93345
93413
|
runListFiles,
|
|
93346
93414
|
(cause) => ({ type: "PR_FETCH_FAILED", cause })
|
|
93347
93415
|
);
|
|
@@ -93355,13 +93423,13 @@ function toDiff(summary, files) {
|
|
|
93355
93423
|
}
|
|
93356
93424
|
function fetchPullRequestDiff(options2) {
|
|
93357
93425
|
const octokit = new Octokit2({ auth: options2.token });
|
|
93358
|
-
return
|
|
93426
|
+
return import_neverthrow91.ResultAsync.combine([safeGet(octokit, options2), safeList(octokit, options2)]).map(
|
|
93359
93427
|
([summary, files]) => toDiff(summary, files)
|
|
93360
93428
|
);
|
|
93361
93429
|
}
|
|
93362
93430
|
|
|
93363
93431
|
// src/triage/github-pr-labeller.ts
|
|
93364
|
-
var
|
|
93432
|
+
var import_neverthrow92 = __toESM(require_index_cjs(), 1);
|
|
93365
93433
|
async function runAddLabels(octokit, options2) {
|
|
93366
93434
|
await octokit.issues.addLabels({
|
|
93367
93435
|
owner: options2.owner,
|
|
@@ -93370,7 +93438,7 @@ async function runAddLabels(octokit, options2) {
|
|
|
93370
93438
|
labels: [...options2.labels]
|
|
93371
93439
|
});
|
|
93372
93440
|
}
|
|
93373
|
-
var safeAddLabels =
|
|
93441
|
+
var safeAddLabels = import_neverthrow92.ResultAsync.fromThrowable(
|
|
93374
93442
|
runAddLabels,
|
|
93375
93443
|
(cause) => ({ type: "LABEL_APPLY_FAILED", cause })
|
|
93376
93444
|
);
|
|
@@ -93408,9 +93476,9 @@ function formatXqaLabels(decision) {
|
|
|
93408
93476
|
}
|
|
93409
93477
|
|
|
93410
93478
|
// src/triage/suite-loader.ts
|
|
93411
|
-
var
|
|
93412
|
-
var
|
|
93413
|
-
var
|
|
93479
|
+
var import_promises32 = require("node:fs/promises");
|
|
93480
|
+
var import_node_path37 = __toESM(require("node:path"), 1);
|
|
93481
|
+
var import_neverthrow93 = __toESM(require_index_cjs(), 1);
|
|
93414
93482
|
var SUITE_FILE_SUFFIX = ".suite.json";
|
|
93415
93483
|
var freestyleEntrySchema2 = external_exports.object({
|
|
93416
93484
|
timeoutSeconds: external_exports.number().int().positive(),
|
|
@@ -93421,39 +93489,39 @@ var suiteFileSchema = external_exports.object({
|
|
|
93421
93489
|
freestyle: external_exports.array(freestyleEntrySchema2).optional(),
|
|
93422
93490
|
hooks: external_exports.record(external_exports.string(), external_exports.unknown()).optional()
|
|
93423
93491
|
});
|
|
93424
|
-
var safeJsonParse6 = (0,
|
|
93492
|
+
var safeJsonParse6 = (0, import_neverthrow93.fromThrowable)(JSON.parse);
|
|
93425
93493
|
async function runReadFile(filePath) {
|
|
93426
|
-
return (0,
|
|
93494
|
+
return (0, import_promises32.readFile)(filePath, "utf8");
|
|
93427
93495
|
}
|
|
93428
93496
|
async function runStat(filePath) {
|
|
93429
|
-
return (0,
|
|
93497
|
+
return (0, import_promises32.stat)(filePath);
|
|
93430
93498
|
}
|
|
93431
93499
|
async function runReadDirectory(filePath) {
|
|
93432
|
-
return (0,
|
|
93500
|
+
return (0, import_promises32.readdir)(filePath);
|
|
93433
93501
|
}
|
|
93434
93502
|
function readSuiteFile(filePath) {
|
|
93435
|
-
const safeRead =
|
|
93503
|
+
const safeRead = import_neverthrow93.ResultAsync.fromThrowable(
|
|
93436
93504
|
runReadFile,
|
|
93437
93505
|
(cause) => ({ type: "SUITE_READ_FAILED", path: filePath, cause })
|
|
93438
93506
|
);
|
|
93439
93507
|
return safeRead(filePath);
|
|
93440
93508
|
}
|
|
93441
93509
|
function readSpecFile2(filePath) {
|
|
93442
|
-
const safeRead =
|
|
93510
|
+
const safeRead = import_neverthrow93.ResultAsync.fromThrowable(
|
|
93443
93511
|
runReadFile,
|
|
93444
93512
|
() => ({ type: "SPEC_NOT_FOUND", path: filePath })
|
|
93445
93513
|
);
|
|
93446
93514
|
return safeRead(filePath);
|
|
93447
93515
|
}
|
|
93448
93516
|
function statDirectory(directory) {
|
|
93449
|
-
const safeStat =
|
|
93517
|
+
const safeStat = import_neverthrow93.ResultAsync.fromThrowable(
|
|
93450
93518
|
runStat,
|
|
93451
93519
|
() => ({ type: "SUITE_DIR_MISSING", path: directory })
|
|
93452
93520
|
);
|
|
93453
93521
|
return safeStat(directory);
|
|
93454
93522
|
}
|
|
93455
93523
|
function readDirectoryEntries(directory) {
|
|
93456
|
-
const safeReadDirectory =
|
|
93524
|
+
const safeReadDirectory = import_neverthrow93.ResultAsync.fromThrowable(
|
|
93457
93525
|
runReadDirectory,
|
|
93458
93526
|
(cause) => ({ type: "SUITE_READ_FAILED", path: directory, cause })
|
|
93459
93527
|
);
|
|
@@ -93462,34 +93530,34 @@ function readDirectoryEntries(directory) {
|
|
|
93462
93530
|
function listSuiteFiles(directory) {
|
|
93463
93531
|
return statDirectory(directory).andThen((stats) => {
|
|
93464
93532
|
if (!stats.isDirectory()) {
|
|
93465
|
-
return (0,
|
|
93533
|
+
return (0, import_neverthrow93.errAsync)({ type: "SUITE_DIR_MISSING", path: directory });
|
|
93466
93534
|
}
|
|
93467
93535
|
return readDirectoryEntries(directory);
|
|
93468
93536
|
}).map(
|
|
93469
|
-
(entries) => entries.filter((entry) => entry.endsWith(SUITE_FILE_SUFFIX)).map((entry) =>
|
|
93537
|
+
(entries) => entries.filter((entry) => entry.endsWith(SUITE_FILE_SUFFIX)).map((entry) => import_node_path37.default.resolve(directory, entry)).toSorted()
|
|
93470
93538
|
);
|
|
93471
93539
|
}
|
|
93472
93540
|
function parseSuiteFile(filePath, raw) {
|
|
93473
93541
|
const parsed = safeJsonParse6(raw);
|
|
93474
93542
|
if (parsed.isErr()) {
|
|
93475
|
-
return (0,
|
|
93543
|
+
return (0, import_neverthrow93.err)({ type: "SUITE_INVALID", path: filePath, cause: parsed.error });
|
|
93476
93544
|
}
|
|
93477
93545
|
const validated = suiteFileSchema.safeParse(parsed.value);
|
|
93478
93546
|
if (!validated.success) {
|
|
93479
|
-
return (0,
|
|
93547
|
+
return (0, import_neverthrow93.err)({ type: "SUITE_INVALID", path: filePath, cause: validated.error });
|
|
93480
93548
|
}
|
|
93481
|
-
return (0,
|
|
93549
|
+
return (0, import_neverthrow93.ok)(validated.data);
|
|
93482
93550
|
}
|
|
93483
93551
|
function suiteIdFromPath(filePath) {
|
|
93484
|
-
const name =
|
|
93552
|
+
const name = import_node_path37.default.basename(filePath);
|
|
93485
93553
|
return name.slice(0, name.length - SUITE_FILE_SUFFIX.length);
|
|
93486
93554
|
}
|
|
93487
93555
|
function loadSpecReference(xqaDirectory, specPath) {
|
|
93488
|
-
const absolute =
|
|
93556
|
+
const absolute = import_node_path37.default.resolve(xqaDirectory, specPath);
|
|
93489
93557
|
return readSpecFile2(absolute).andThen((raw) => {
|
|
93490
93558
|
const parsed = parseSpecFrontmatter(raw);
|
|
93491
93559
|
if (parsed.isErr()) {
|
|
93492
|
-
return (0,
|
|
93560
|
+
return (0, import_neverthrow93.err)({
|
|
93493
93561
|
type: "SPEC_FRONTMATTER_INVALID",
|
|
93494
93562
|
path: absolute,
|
|
93495
93563
|
cause: parsed.error.cause
|
|
@@ -93497,19 +93565,19 @@ function loadSpecReference(xqaDirectory, specPath) {
|
|
|
93497
93565
|
}
|
|
93498
93566
|
const { feature, timeoutSeconds } = parsed.value;
|
|
93499
93567
|
if (timeoutSeconds === void 0) {
|
|
93500
|
-
return (0,
|
|
93568
|
+
return (0, import_neverthrow93.ok)({ path: specPath, feature });
|
|
93501
93569
|
}
|
|
93502
|
-
return (0,
|
|
93570
|
+
return (0, import_neverthrow93.ok)({ path: specPath, feature, timeoutSeconds });
|
|
93503
93571
|
});
|
|
93504
93572
|
}
|
|
93505
93573
|
function loadSpecReferences(xqaDirectory, specs) {
|
|
93506
93574
|
if (specs.length === 0) {
|
|
93507
|
-
return (0,
|
|
93575
|
+
return (0, import_neverthrow93.okAsync)([]);
|
|
93508
93576
|
}
|
|
93509
|
-
return
|
|
93577
|
+
return import_neverthrow93.ResultAsync.combine(specs.map((specPath) => loadSpecReference(xqaDirectory, specPath)));
|
|
93510
93578
|
}
|
|
93511
93579
|
function addSpecTokens(tokens, spec) {
|
|
93512
|
-
const stem =
|
|
93580
|
+
const stem = import_node_path37.default.basename(spec.path).replace(/\.test\.md$/u, "");
|
|
93513
93581
|
for (const part of stem.split(".")) {
|
|
93514
93582
|
if (part.length > 0) {
|
|
93515
93583
|
tokens.add(part);
|
|
@@ -93582,12 +93650,12 @@ function loadSuite(suiteFilePath, xqaDirectory) {
|
|
|
93582
93650
|
);
|
|
93583
93651
|
}
|
|
93584
93652
|
function loadXqaSuites(directory) {
|
|
93585
|
-
const xqaDirectory =
|
|
93653
|
+
const xqaDirectory = import_node_path37.default.dirname(import_node_path37.default.resolve(directory));
|
|
93586
93654
|
return listSuiteFiles(directory).andThen((files) => {
|
|
93587
93655
|
if (files.length === 0) {
|
|
93588
|
-
return (0,
|
|
93656
|
+
return (0, import_neverthrow93.okAsync)([]);
|
|
93589
93657
|
}
|
|
93590
|
-
return
|
|
93658
|
+
return import_neverthrow93.ResultAsync.combine(files.map((file2) => loadSuite(file2, xqaDirectory)));
|
|
93591
93659
|
});
|
|
93592
93660
|
}
|
|
93593
93661
|
|
|
@@ -93598,27 +93666,27 @@ function parseRepo(input) {
|
|
|
93598
93666
|
const parts = input.split("/");
|
|
93599
93667
|
const [owner, repo] = parts;
|
|
93600
93668
|
if (parts.length !== 2 || owner === void 0 || owner === "" || repo === void 0 || repo === "") {
|
|
93601
|
-
return (0,
|
|
93669
|
+
return (0, import_neverthrow94.err)({ type: "CLI_INVALID_ARG", message: `invalid --repo value: ${input}` });
|
|
93602
93670
|
}
|
|
93603
|
-
return (0,
|
|
93671
|
+
return (0, import_neverthrow94.ok)({ owner, repo });
|
|
93604
93672
|
}
|
|
93605
93673
|
function parsePrNumber(input) {
|
|
93606
93674
|
const parsed = Number.parseInt(input, 10);
|
|
93607
93675
|
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
93608
|
-
return (0,
|
|
93676
|
+
return (0, import_neverthrow94.err)({ type: "CLI_INVALID_ARG", message: `invalid --pr value: ${input}` });
|
|
93609
93677
|
}
|
|
93610
|
-
return (0,
|
|
93678
|
+
return (0, import_neverthrow94.ok)(parsed);
|
|
93611
93679
|
}
|
|
93612
93680
|
function parseCliInputs(options2) {
|
|
93613
93681
|
const repoResult = parseRepo(options2.repo);
|
|
93614
93682
|
if (repoResult.isErr()) {
|
|
93615
|
-
return (0,
|
|
93683
|
+
return (0, import_neverthrow94.err)(repoResult.error);
|
|
93616
93684
|
}
|
|
93617
93685
|
const prResult = parsePrNumber(options2.pr);
|
|
93618
93686
|
if (prResult.isErr()) {
|
|
93619
|
-
return (0,
|
|
93687
|
+
return (0, import_neverthrow94.err)(prResult.error);
|
|
93620
93688
|
}
|
|
93621
|
-
return (0,
|
|
93689
|
+
return (0, import_neverthrow94.ok)({
|
|
93622
93690
|
owner: repoResult.value.owner,
|
|
93623
93691
|
repo: repoResult.value.repo,
|
|
93624
93692
|
prNumber: prResult.value
|
|
@@ -93626,23 +93694,23 @@ function parseCliInputs(options2) {
|
|
|
93626
93694
|
}
|
|
93627
93695
|
function resolveGithubToken(context) {
|
|
93628
93696
|
if (!context.rootConfig.agents.triager.enabled) {
|
|
93629
|
-
return (0,
|
|
93697
|
+
return (0, import_neverthrow94.err)({ type: "TRIAGER_DISABLED" });
|
|
93630
93698
|
}
|
|
93631
93699
|
if (context.config.GITHUB_TOKEN === void 0) {
|
|
93632
|
-
return (0,
|
|
93700
|
+
return (0, import_neverthrow94.err)({ type: "CONFIG_MISSING", key: "GITHUB_TOKEN" });
|
|
93633
93701
|
}
|
|
93634
|
-
return (0,
|
|
93702
|
+
return (0, import_neverthrow94.ok)(context.config.GITHUB_TOKEN);
|
|
93635
93703
|
}
|
|
93636
93704
|
function buildInputs(options2, context) {
|
|
93637
93705
|
const tokenResult = resolveGithubToken(context);
|
|
93638
93706
|
if (tokenResult.isErr()) {
|
|
93639
|
-
return (0,
|
|
93707
|
+
return (0, import_neverthrow94.err)(tokenResult.error);
|
|
93640
93708
|
}
|
|
93641
93709
|
const parsed = parseCliInputs(options2);
|
|
93642
93710
|
if (parsed.isErr()) {
|
|
93643
|
-
return (0,
|
|
93711
|
+
return (0, import_neverthrow94.err)(parsed.error);
|
|
93644
93712
|
}
|
|
93645
|
-
return (0,
|
|
93713
|
+
return (0, import_neverthrow94.ok)({
|
|
93646
93714
|
owner: parsed.value.owner,
|
|
93647
93715
|
repo: parsed.value.repo,
|
|
93648
93716
|
prNumber: parsed.value.prNumber,
|
|
@@ -93670,7 +93738,7 @@ function callTriager(options2) {
|
|
|
93670
93738
|
}
|
|
93671
93739
|
function maybeApplyLabels(inputs, labels) {
|
|
93672
93740
|
if (!inputs.applyLabels || labels.length === 0) {
|
|
93673
|
-
return
|
|
93741
|
+
return import_neverthrow94.ResultAsync.fromSafePromise(Promise.resolve(labels));
|
|
93674
93742
|
}
|
|
93675
93743
|
return applyPullRequestLabels({
|
|
93676
93744
|
owner: inputs.owner,
|
|
@@ -93681,7 +93749,7 @@ function maybeApplyLabels(inputs, labels) {
|
|
|
93681
93749
|
}).map(() => labels);
|
|
93682
93750
|
}
|
|
93683
93751
|
function runPipeline5(inputs) {
|
|
93684
|
-
return
|
|
93752
|
+
return import_neverthrow94.ResultAsync.combine([
|
|
93685
93753
|
loadXqaSuites(inputs.suitesDir),
|
|
93686
93754
|
fetchPullRequestDiff({
|
|
93687
93755
|
owner: inputs.owner,
|
|
@@ -93775,10 +93843,10 @@ var rootConfigSchema = external_exports.object({
|
|
|
93775
93843
|
}).strict();
|
|
93776
93844
|
|
|
93777
93845
|
// src/config.ts
|
|
93778
|
-
var
|
|
93846
|
+
var import_node_path38 = __toESM(require("node:path"), 1);
|
|
93779
93847
|
var import_node_url2 = require("node:url");
|
|
93780
93848
|
var import_dotenv = __toESM(require_main(), 1);
|
|
93781
|
-
var
|
|
93849
|
+
var import_neverthrow95 = __toESM(require_index_cjs(), 1);
|
|
93782
93850
|
|
|
93783
93851
|
// src/config-schema.ts
|
|
93784
93852
|
var configSchema = external_exports.object({
|
|
@@ -93788,23 +93856,23 @@ var configSchema = external_exports.object({
|
|
|
93788
93856
|
});
|
|
93789
93857
|
|
|
93790
93858
|
// src/config.ts
|
|
93791
|
-
var packageDirectory =
|
|
93859
|
+
var packageDirectory = import_node_path38.default.dirname((0, import_node_url2.fileURLToPath)(__importMetaUrl));
|
|
93792
93860
|
function loadConfig2() {
|
|
93793
|
-
(0, import_dotenv.config)({ path:
|
|
93861
|
+
(0, import_dotenv.config)({ path: import_node_path38.default.resolve(packageDirectory, "..", ".env.local") });
|
|
93794
93862
|
const result = configSchema.safeParse(process.env);
|
|
93795
93863
|
if (!result.success) {
|
|
93796
93864
|
const messages = result.error.issues.map(
|
|
93797
93865
|
(issue2) => ` - ${issue2.path.join(".")}: ${issue2.message}`
|
|
93798
93866
|
);
|
|
93799
|
-
return (0,
|
|
93867
|
+
return (0, import_neverthrow95.err)({ type: "INVALID_CONFIG", message: `Configuration error:
|
|
93800
93868
|
${messages.join("\n")}` });
|
|
93801
93869
|
}
|
|
93802
|
-
return (0,
|
|
93870
|
+
return (0, import_neverthrow95.ok)(result.data);
|
|
93803
93871
|
}
|
|
93804
93872
|
|
|
93805
93873
|
// src/pid-lock.ts
|
|
93806
93874
|
var import_node_fs13 = require("node:fs");
|
|
93807
|
-
var
|
|
93875
|
+
var import_neverthrow96 = __toESM(require_index_cjs(), 1);
|
|
93808
93876
|
var PID_FILE = "/tmp/xqa.pid";
|
|
93809
93877
|
var SIGINT_EXIT_CODE = 130;
|
|
93810
93878
|
var SIGTERM_EXIT_CODE = 143;
|
|
@@ -93813,7 +93881,7 @@ var HARD_TIMEOUT_MS = 1e4;
|
|
|
93813
93881
|
var cleanup = () => {
|
|
93814
93882
|
(0, import_node_fs13.rmSync)(PID_FILE, { force: true });
|
|
93815
93883
|
};
|
|
93816
|
-
var checkProcessRunning = (0,
|
|
93884
|
+
var checkProcessRunning = (0, import_neverthrow96.fromThrowable)(
|
|
93817
93885
|
(pid) => {
|
|
93818
93886
|
process.kill(pid, 0);
|
|
93819
93887
|
return true;
|
|
@@ -93880,17 +93948,16 @@ function acquireLock() {
|
|
|
93880
93948
|
function loadCliContext(signal) {
|
|
93881
93949
|
const configResult = loadConfig2();
|
|
93882
93950
|
if (configResult.isErr()) {
|
|
93883
|
-
return (0,
|
|
93951
|
+
return (0, import_neverthrow97.err)(configResult.error);
|
|
93884
93952
|
}
|
|
93885
93953
|
const rootConfigResult = loadConfigSync({
|
|
93886
93954
|
cwd: process.cwd(),
|
|
93887
|
-
schema: rootConfigSchema
|
|
93888
|
-
env: process.env
|
|
93955
|
+
schema: rootConfigSchema
|
|
93889
93956
|
});
|
|
93890
93957
|
if (rootConfigResult.isErr()) {
|
|
93891
|
-
return (0,
|
|
93958
|
+
return (0, import_neverthrow97.err)(rootConfigResult.error);
|
|
93892
93959
|
}
|
|
93893
|
-
return (0,
|
|
93960
|
+
return (0, import_neverthrow97.ok)({
|
|
93894
93961
|
config: configResult.value,
|
|
93895
93962
|
rootConfig: rootConfigResult.value,
|
|
93896
93963
|
signal
|
|
@@ -93922,7 +93989,7 @@ function buildProgram(options2) {
|
|
|
93922
93989
|
|
|
93923
93990
|
// src/index.ts
|
|
93924
93991
|
process.title = "xqa";
|
|
93925
|
-
var version2 = `${"
|
|
93992
|
+
var version2 = `${"5.1.0"}${false ? ` (dev build +${"7bb7ba0"})` : ""}`;
|
|
93926
93993
|
var program2 = buildProgram({ version: version2 });
|
|
93927
93994
|
void program2.parseAsync(process.argv);
|
|
93928
93995
|
/*! Bundled license information:
|