zelari-code 2.2.0 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/gauntlet/blind.js +38 -0
- package/dist/cli/gauntlet/blind.js.map +1 -0
- package/dist/cli/gauntlet/complete.js +90 -0
- package/dist/cli/gauntlet/complete.js.map +1 -0
- package/dist/cli/gauntlet/decompose.js +163 -0
- package/dist/cli/gauntlet/decompose.js.map +1 -0
- package/dist/cli/gauntlet/events.js +30 -0
- package/dist/cli/gauntlet/events.js.map +1 -0
- package/dist/cli/gauntlet/loop.js +142 -0
- package/dist/cli/gauntlet/loop.js.map +1 -0
- package/dist/cli/gauntlet/policy.js +61 -0
- package/dist/cli/gauntlet/policy.js.map +1 -0
- package/dist/cli/gauntlet/prompts.js +70 -0
- package/dist/cli/gauntlet/prompts.js.map +1 -0
- package/dist/cli/gauntlet/run.js +213 -0
- package/dist/cli/gauntlet/run.js.map +1 -0
- package/dist/cli/gauntlet/schedule.js +34 -0
- package/dist/cli/gauntlet/schedule.js.map +1 -0
- package/dist/cli/gauntlet/verdict.js +58 -0
- package/dist/cli/gauntlet/verdict.js.map +1 -0
- package/dist/cli/headless.js +11 -0
- package/dist/cli/headless.js.map +1 -1
- package/dist/cli/kraken/executor.js +9 -8
- package/dist/cli/kraken/executor.js.map +1 -1
- package/dist/cli/kraken/tentacle.js +1 -1
- package/dist/cli/kraken/tentacle.js.map +1 -1
- package/dist/cli/main.bundled.js +1469 -238
- package/dist/cli/main.bundled.js.map +4 -4
- package/dist/cli/runHeadless.js +18 -0
- package/dist/cli/runHeadless.js.map +1 -1
- package/dist/cli/toolRegistry.js +13 -6
- package/dist/cli/toolRegistry.js.map +1 -1
- package/dist/cli/tools/taskTool.js +88 -72
- package/dist/cli/tools/taskTool.js.map +1 -1
- package/package.json +2 -2
package/dist/cli/main.bundled.js
CHANGED
|
@@ -595,8 +595,8 @@ async function runGrokOAuthFlow(options = {}) {
|
|
|
595
595
|
);
|
|
596
596
|
} catch {
|
|
597
597
|
}
|
|
598
|
-
const
|
|
599
|
-
const effectiveTimeout = Math.min(
|
|
598
|
+
const timeoutMs2 = options.timeoutMs ?? DEFAULT_OAUTH_TIMEOUT_MS;
|
|
599
|
+
const effectiveTimeout = Math.min(timeoutMs2, deviceAuth.expiresIn * 1e3);
|
|
600
600
|
return pollForDeviceToken({
|
|
601
601
|
clientId: clientId2,
|
|
602
602
|
deviceCode: deviceAuth.deviceCode,
|
|
@@ -739,7 +739,7 @@ function generateOAuthState() {
|
|
|
739
739
|
}
|
|
740
740
|
async function waitForLoopbackCallback(options) {
|
|
741
741
|
const host = options.host ?? "127.0.0.1";
|
|
742
|
-
const
|
|
742
|
+
const timeoutMs2 = options.timeoutMs ?? 3e5;
|
|
743
743
|
const expectedPath = options.path.startsWith("/") ? options.path : `/${options.path}`;
|
|
744
744
|
return new Promise((resolve3, reject) => {
|
|
745
745
|
let settled = false;
|
|
@@ -759,12 +759,12 @@ async function waitForLoopbackCallback(options) {
|
|
|
759
759
|
const ok = Boolean(result.code) && !result.error;
|
|
760
760
|
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
|
|
761
761
|
res.end(oauthResultHtml(ok, result.errorDescription ?? result.error));
|
|
762
|
-
|
|
762
|
+
finish2(result);
|
|
763
763
|
});
|
|
764
764
|
const timer = setTimeout(() => {
|
|
765
|
-
|
|
766
|
-
},
|
|
767
|
-
const
|
|
765
|
+
finish2(void 0, new Error(`Timed out waiting for OAuth callback on http://${host}:${options.port}`));
|
|
766
|
+
}, timeoutMs2);
|
|
767
|
+
const finish2 = (value, err) => {
|
|
768
768
|
if (settled) return;
|
|
769
769
|
settled = true;
|
|
770
770
|
clearTimeout(timer);
|
|
@@ -773,7 +773,7 @@ async function waitForLoopbackCallback(options) {
|
|
|
773
773
|
else resolve3(value ?? {});
|
|
774
774
|
});
|
|
775
775
|
};
|
|
776
|
-
server.on("error", (err) =>
|
|
776
|
+
server.on("error", (err) => finish2(void 0, err));
|
|
777
777
|
server.listen(options.port, host);
|
|
778
778
|
});
|
|
779
779
|
}
|
|
@@ -971,8 +971,8 @@ async function pollChatgptDeviceAuth(options) {
|
|
|
971
971
|
const clientId2 = options.clientId || process.env.CHATGPT_OAUTH_CLIENT_ID || DEFAULT_CHATGPT_CLIENT_ID;
|
|
972
972
|
const fetchImpl = options.fetchImpl ?? fetch;
|
|
973
973
|
const sleep = options.sleepImpl ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
|
|
974
|
-
const
|
|
975
|
-
const deadline = Date.now() +
|
|
974
|
+
const timeoutMs2 = options.timeoutMs ?? 3e5;
|
|
975
|
+
const deadline = Date.now() + timeoutMs2;
|
|
976
976
|
let interval = options.interval ?? 5;
|
|
977
977
|
let authorizationCode;
|
|
978
978
|
let codeVerifier;
|
|
@@ -18246,14 +18246,15 @@ var init_filesystem = __esm({
|
|
|
18246
18246
|
init_toolTypes();
|
|
18247
18247
|
ReadFileArgsSchema = external_exports.object({
|
|
18248
18248
|
path: external_exports.string().min(1),
|
|
18249
|
-
startLine: external_exports.number().int().nonnegative().optional(),
|
|
18250
|
-
endLine: external_exports.number().int().positive().optional(),
|
|
18249
|
+
startLine: external_exports.number().int().nonnegative().optional().describe("0-based first line to include. Range is applied to the full file before maxBytes."),
|
|
18250
|
+
endLine: external_exports.number().int().positive().optional().describe("Exclusive 0-based end line. Omit to read through EOF (still capped by maxBytes)."),
|
|
18251
18251
|
maxBytes: external_exports.number().int().positive().max(1e7).default(1e6)
|
|
18252
18252
|
});
|
|
18253
18253
|
readFileTool = {
|
|
18254
18254
|
name: "read_file",
|
|
18255
|
-
description: "Read a file with optional line range. Returns content + metadata. Use before edit_file.",
|
|
18255
|
+
description: "Read a file with optional 0-based line range (endLine exclusive). maxBytes caps the selected range, not a prefix of the file. Returns content + metadata. Use before edit_file.",
|
|
18256
18256
|
permissions: ["read"],
|
|
18257
|
+
sideEffect: "none",
|
|
18257
18258
|
timeoutMs: 5e3,
|
|
18258
18259
|
inputSchema: ReadFileArgsSchema,
|
|
18259
18260
|
execute: async (args, ctx) => {
|
|
@@ -18262,24 +18263,31 @@ var init_filesystem = __esm({
|
|
|
18262
18263
|
const buf = await fs4.readFile(absPath, { encoding: "utf-8", signal: ctx.signal });
|
|
18263
18264
|
const content = typeof buf === "string" ? buf : buf.toString("utf-8");
|
|
18264
18265
|
const allLines = content.split("\n");
|
|
18265
|
-
const truncated = content.length > args.maxBytes ? content.slice(0, args.maxBytes) : content;
|
|
18266
|
-
const lines = truncated === content ? allLines : truncated.split("\n");
|
|
18267
18266
|
const totalLines = allLines.length;
|
|
18268
18267
|
const start = args.startLine ?? 0;
|
|
18269
|
-
const
|
|
18270
|
-
const wasTruncated = truncated !== content;
|
|
18268
|
+
const endExclusive = Math.min(args.endLine ?? totalLines, totalLines);
|
|
18271
18269
|
const empty = content.length === 0;
|
|
18272
|
-
const
|
|
18270
|
+
const rangeEmpty = !empty && (start >= totalLines || endExclusive <= start);
|
|
18271
|
+
const selected = rangeEmpty ? [] : allLines.slice(start, endExclusive);
|
|
18272
|
+
let text = selected.join("\n");
|
|
18273
|
+
const wasTruncated = text.length > args.maxBytes;
|
|
18274
|
+
if (wasTruncated)
|
|
18275
|
+
text = text.slice(0, args.maxBytes);
|
|
18276
|
+
const returnedLines = text.length === 0 ? 0 : text.split("\n").length;
|
|
18277
|
+
const readEnd = returnedLines === 0 ? Math.max(0, start - 1) : start + returnedLines - 1;
|
|
18278
|
+
const status = empty || rangeEmpty ? "empty" : wasTruncated ? "partial" : "complete";
|
|
18273
18279
|
const warnings = [];
|
|
18274
18280
|
if (empty)
|
|
18275
18281
|
warnings.push("EMPTY_FILE");
|
|
18282
|
+
if (rangeEmpty)
|
|
18283
|
+
warnings.push("LINE_RANGE_EMPTY");
|
|
18276
18284
|
if (wasTruncated)
|
|
18277
18285
|
warnings.push("MAX_BYTES_TRUNCATED");
|
|
18278
18286
|
return typedOk({
|
|
18279
18287
|
path: absPath,
|
|
18280
|
-
content:
|
|
18288
|
+
content: text,
|
|
18281
18289
|
totalLines,
|
|
18282
|
-
readLines: { start, end:
|
|
18290
|
+
readLines: { start, end: readEnd },
|
|
18283
18291
|
sizeBytes: content.length
|
|
18284
18292
|
}, {
|
|
18285
18293
|
status,
|
|
@@ -18305,6 +18313,7 @@ var init_filesystem = __esm({
|
|
|
18305
18313
|
name: "write_file",
|
|
18306
18314
|
description: "Write or create a file. Use createDirs=true to auto-create parent directories.",
|
|
18307
18315
|
permissions: ["write"],
|
|
18316
|
+
sideEffect: "local",
|
|
18308
18317
|
timeoutMs: 1e4,
|
|
18309
18318
|
inputSchema: WriteFileArgsSchema,
|
|
18310
18319
|
execute: async (args, ctx) => {
|
|
@@ -18330,6 +18339,7 @@ var init_filesystem = __esm({
|
|
|
18330
18339
|
name: "edit_file",
|
|
18331
18340
|
description: "Replace exact string match in a file. Idempotent: returns 0 occurrences if no match.",
|
|
18332
18341
|
permissions: ["write"],
|
|
18342
|
+
sideEffect: "local",
|
|
18333
18343
|
timeoutMs: 1e4,
|
|
18334
18344
|
inputSchema: EditFileArgsSchema,
|
|
18335
18345
|
execute: async (args, ctx) => {
|
|
@@ -18561,6 +18571,7 @@ var init_shell = __esm({
|
|
|
18561
18571
|
name: "bash",
|
|
18562
18572
|
description: "Run a shell command. On Windows uses Git Bash when available (POSIX semantics: ls, $VAR, && work); falls back to cmd.exe otherwise. Streams stdout/stderr. Respects timeout and cancellation. Returns exit code. stdin is CLOSED (non-interactive): any command that prompts for input will fail or be cancelled \u2014 always pass non-interactive flags (--yes, -y, --template), and if a scaffolder insists on prompting (e.g. create-vite in a non-empty directory), create the files manually with write_file instead.",
|
|
18563
18573
|
permissions: ["execute"],
|
|
18574
|
+
sideEffect: "local",
|
|
18564
18575
|
timeoutMs: 6e4,
|
|
18565
18576
|
inputSchema: BashArgsSchema,
|
|
18566
18577
|
execute: async (args, ctx) => {
|
|
@@ -18870,6 +18881,7 @@ var init_search = __esm({
|
|
|
18870
18881
|
name: "grep_content",
|
|
18871
18882
|
description: 'Regex search for content in a file OR recursively in a directory. When path is a directory, include/exclude globs filter which files are searched (default: all files, excluding node_modules/dist/.git/etc.). Glob semantics: "*" matches ONE path segment only ("*.ts" does NOT match "sub/file.ts"); use "**" for recursive matching ("**/*.ts" matches at any depth). include/exclude accept a single glob string (e.g. "*.ts") OR an array of globs. Returns matches with line numbers and context, plus filesWalked/filesInTree counts and a warning when the include globs matched suspiciously few files.',
|
|
18872
18883
|
permissions: ["read"],
|
|
18884
|
+
sideEffect: "none",
|
|
18873
18885
|
timeoutMs: 3e4,
|
|
18874
18886
|
inputSchema: GrepContentArgsSchema,
|
|
18875
18887
|
execute: async (args, ctx) => {
|
|
@@ -18987,6 +18999,7 @@ var init_listFiles = __esm({
|
|
|
18987
18999
|
name: "list_files",
|
|
18988
19000
|
description: "List files and directories in the given path (defaults to the working directory). Returns names with types (file/directory). Use this to discover the project structure before reading specific files. Supports a maxDepth for recursive listing and excludes common dependency/build directories by default.",
|
|
18989
19001
|
permissions: ["read"],
|
|
19002
|
+
sideEffect: "none",
|
|
18990
19003
|
timeoutMs: 15e3,
|
|
18991
19004
|
inputSchema: ListFilesArgsSchema,
|
|
18992
19005
|
execute: async (args, ctx) => {
|
|
@@ -19241,6 +19254,7 @@ var init_diff = __esm({
|
|
|
19241
19254
|
name: "show_diff",
|
|
19242
19255
|
description: "Show unified diff between current file content and proposed content. Read-only \u2014 does NOT modify the file. Use this to preview edits before applying with edit_file or apply_diff.",
|
|
19243
19256
|
permissions: ["read"],
|
|
19257
|
+
sideEffect: "none",
|
|
19244
19258
|
timeoutMs: 15e3,
|
|
19245
19259
|
inputSchema: ShowDiffArgsSchema,
|
|
19246
19260
|
execute: async (args, ctx) => {
|
|
@@ -19343,6 +19357,7 @@ var init_diff = __esm({
|
|
|
19343
19357
|
name: "apply_diff",
|
|
19344
19358
|
description: "Apply a unified diff patch to a file. Parses ---/+++/@@ headers and applies each hunk sequentially. With fuzzyMatch=true, tolerates whitespace differences. With dryRun=true, returns the final content without writing. Atomic: if any hunk fails, no partial write occurs.",
|
|
19345
19359
|
permissions: ["write"],
|
|
19360
|
+
sideEffect: "local",
|
|
19346
19361
|
timeoutMs: 15e3,
|
|
19347
19362
|
inputSchema: ApplyDiffArgsSchema,
|
|
19348
19363
|
execute: async (args, ctx) => {
|
|
@@ -19404,9 +19419,9 @@ function assertHttpUrl(raw) {
|
|
|
19404
19419
|
}
|
|
19405
19420
|
return url2;
|
|
19406
19421
|
}
|
|
19407
|
-
async function fetchWithTimeout(url2, init, outerSignal,
|
|
19422
|
+
async function fetchWithTimeout(url2, init, outerSignal, timeoutMs2) {
|
|
19408
19423
|
const ctrl = new AbortController();
|
|
19409
|
-
const timer = setTimeout(() => ctrl.abort(new Error(`timeout after ${
|
|
19424
|
+
const timer = setTimeout(() => ctrl.abort(new Error(`timeout after ${timeoutMs2}ms`)), timeoutMs2);
|
|
19410
19425
|
const onOuterAbort = () => ctrl.abort(outerSignal?.reason);
|
|
19411
19426
|
outerSignal?.addEventListener("abort", onOuterAbort, { once: true });
|
|
19412
19427
|
try {
|
|
@@ -21471,6 +21486,42 @@ var init_types = __esm({
|
|
|
21471
21486
|
}
|
|
21472
21487
|
});
|
|
21473
21488
|
|
|
21489
|
+
// packages/core/dist/core/tools/concurrency.js
|
|
21490
|
+
function taskAgent(args) {
|
|
21491
|
+
if (!args || typeof args !== "object")
|
|
21492
|
+
return "explore";
|
|
21493
|
+
const agent = args.agent;
|
|
21494
|
+
return typeof agent === "string" && agent.trim() ? agent : "explore";
|
|
21495
|
+
}
|
|
21496
|
+
function classifyToolConcurrency(input) {
|
|
21497
|
+
const env = input.env ?? process.env;
|
|
21498
|
+
if (env.ZELARI_PARALLEL_TOOLS === "0")
|
|
21499
|
+
return "exclusive";
|
|
21500
|
+
const name = input.toolName;
|
|
21501
|
+
if (name === "task") {
|
|
21502
|
+
return taskAgent(input.args) === "general" ? "exclusive" : "parallel-safe";
|
|
21503
|
+
}
|
|
21504
|
+
if (input.registered === false) {
|
|
21505
|
+
if (name.startsWith("mcp_")) {
|
|
21506
|
+
const lower = name.toLowerCase();
|
|
21507
|
+
if (lower.includes("write") || lower.includes("edit") || lower.includes("delete")) {
|
|
21508
|
+
return "exclusive";
|
|
21509
|
+
}
|
|
21510
|
+
return "parallel-safe";
|
|
21511
|
+
}
|
|
21512
|
+
return "exclusive";
|
|
21513
|
+
}
|
|
21514
|
+
const perms = input.permissions ?? [];
|
|
21515
|
+
if (perms.includes("write") || perms.includes("execute"))
|
|
21516
|
+
return "exclusive";
|
|
21517
|
+
return "parallel-safe";
|
|
21518
|
+
}
|
|
21519
|
+
var init_concurrency = __esm({
|
|
21520
|
+
"packages/core/dist/core/tools/concurrency.js"() {
|
|
21521
|
+
"use strict";
|
|
21522
|
+
}
|
|
21523
|
+
});
|
|
21524
|
+
|
|
21474
21525
|
// packages/core/dist/core/contextGrowth.js
|
|
21475
21526
|
function emptyContextGrowthStats() {
|
|
21476
21527
|
return {
|
|
@@ -22022,6 +22073,7 @@ var init_AgentHarness = __esm({
|
|
|
22022
22073
|
"packages/core/dist/core/AgentHarness.js"() {
|
|
22023
22074
|
"use strict";
|
|
22024
22075
|
init_events();
|
|
22076
|
+
init_concurrency();
|
|
22025
22077
|
init_toolTypes();
|
|
22026
22078
|
init_contextGrowth();
|
|
22027
22079
|
init_requestSnapshot();
|
|
@@ -22106,30 +22158,19 @@ var init_AgentHarness = __esm({
|
|
|
22106
22158
|
};
|
|
22107
22159
|
}
|
|
22108
22160
|
/**
|
|
22109
|
-
* v1.8.0: true when a tool may run concurrently with other
|
|
22110
|
-
* tools. Write/execute
|
|
22111
|
-
*
|
|
22161
|
+
* v1.8.0 / 2.x F: true when a tool may run concurrently with other
|
|
22162
|
+
* parallel-safe tools. Write/execute stay serial. `task agent=general`
|
|
22163
|
+
* is exclusive (it writes); explore/verify tentacles stay parallel-safe.
|
|
22164
|
+
* Opt out: ZELARI_PARALLEL_TOOLS=0.
|
|
22112
22165
|
*/
|
|
22113
|
-
isParallelSafeTool(toolName) {
|
|
22114
|
-
if (process.env.ZELARI_PARALLEL_TOOLS === "0")
|
|
22115
|
-
return false;
|
|
22116
|
-
if (toolName === "task")
|
|
22117
|
-
return true;
|
|
22166
|
+
isParallelSafeTool(toolName, args) {
|
|
22118
22167
|
const def = this.config.toolRegistry?.get(toolName);
|
|
22119
|
-
|
|
22120
|
-
|
|
22121
|
-
|
|
22122
|
-
|
|
22123
|
-
|
|
22124
|
-
|
|
22125
|
-
return true;
|
|
22126
|
-
}
|
|
22127
|
-
return false;
|
|
22128
|
-
}
|
|
22129
|
-
const perms = def.permissions ?? [];
|
|
22130
|
-
if (perms.includes("write") || perms.includes("execute"))
|
|
22131
|
-
return false;
|
|
22132
|
-
return true;
|
|
22168
|
+
return classifyToolConcurrency({
|
|
22169
|
+
toolName,
|
|
22170
|
+
args,
|
|
22171
|
+
permissions: def?.permissions,
|
|
22172
|
+
registered: Boolean(def) || toolName === "task"
|
|
22173
|
+
}) === "parallel-safe";
|
|
22133
22174
|
}
|
|
22134
22175
|
/**
|
|
22135
22176
|
* Execute buffered native tool calls: consecutive parallel-safe tools run
|
|
@@ -22234,13 +22275,13 @@ ${shared2.content}`,
|
|
|
22234
22275
|
let i = 0;
|
|
22235
22276
|
while (i < pending.length) {
|
|
22236
22277
|
const p3 = pending[i];
|
|
22237
|
-
if (p3.skipped || p3.cached !== void 0 || !this.isParallelSafeTool(p3.toolName)) {
|
|
22278
|
+
if (p3.skipped || p3.cached !== void 0 || !this.isParallelSafeTool(p3.toolName, p3.args)) {
|
|
22238
22279
|
out[i] = toOut(p3, await invokeOne(p3));
|
|
22239
22280
|
i += 1;
|
|
22240
22281
|
continue;
|
|
22241
22282
|
}
|
|
22242
22283
|
let j = i;
|
|
22243
|
-
while (j < pending.length && !pending[j].skipped && pending[j].cached === void 0 && this.isParallelSafeTool(pending[j].toolName)) {
|
|
22284
|
+
while (j < pending.length && !pending[j].skipped && pending[j].cached === void 0 && this.isParallelSafeTool(pending[j].toolName, pending[j].args)) {
|
|
22244
22285
|
j += 1;
|
|
22245
22286
|
}
|
|
22246
22287
|
for (let off = i; off < j; off += maxParallel) {
|
|
@@ -23286,8 +23327,8 @@ var init_lifecycleHookRunner = __esm({
|
|
|
23286
23327
|
/** Execute a single hook, swallowing every failure into an allow. */
|
|
23287
23328
|
async runHookSafely(hook, payload) {
|
|
23288
23329
|
try {
|
|
23289
|
-
const
|
|
23290
|
-
const raw = hook.url ? await this.postHttp(hook.url, payload,
|
|
23330
|
+
const timeoutMs2 = hook.timeoutMs ?? this.defaultTimeoutMs;
|
|
23331
|
+
const raw = hook.url ? await this.postHttp(hook.url, payload, timeoutMs2) : await this.execCommand(hook.command ?? "", payload, timeoutMs2, hook.cwd);
|
|
23291
23332
|
const decision = parseJson(raw);
|
|
23292
23333
|
if (!decision) {
|
|
23293
23334
|
this.logger(`hook "${hook.name}" returned invalid JSON (fail-open): ${raw.slice(0, 200)}`);
|
|
@@ -23304,7 +23345,7 @@ var init_lifecycleHookRunner = __esm({
|
|
|
23304
23345
|
}
|
|
23305
23346
|
}
|
|
23306
23347
|
/** Spawn `command`, write JSON payload to stdin, read stdout until close. */
|
|
23307
|
-
execCommand(command, payload,
|
|
23348
|
+
execCommand(command, payload, timeoutMs2, cwd) {
|
|
23308
23349
|
return new Promise((resolve3, reject) => {
|
|
23309
23350
|
const child = spawn2(command, {
|
|
23310
23351
|
shell: true,
|
|
@@ -23316,8 +23357,8 @@ var init_lifecycleHookRunner = __esm({
|
|
|
23316
23357
|
let stderr = "";
|
|
23317
23358
|
const timer = setTimeout(() => {
|
|
23318
23359
|
child.kill("SIGKILL");
|
|
23319
|
-
reject(new Error(`timed out after ${
|
|
23320
|
-
},
|
|
23360
|
+
reject(new Error(`timed out after ${timeoutMs2}ms`));
|
|
23361
|
+
}, timeoutMs2);
|
|
23321
23362
|
child.stdout?.on("data", (d) => {
|
|
23322
23363
|
stdout += d.toString();
|
|
23323
23364
|
});
|
|
@@ -23343,9 +23384,9 @@ var init_lifecycleHookRunner = __esm({
|
|
|
23343
23384
|
});
|
|
23344
23385
|
}
|
|
23345
23386
|
/** POST JSON payload; resolve with the response body text. */
|
|
23346
|
-
async postHttp(url2, payload,
|
|
23387
|
+
async postHttp(url2, payload, timeoutMs2) {
|
|
23347
23388
|
const ctrl = new AbortController();
|
|
23348
|
-
const timer = setTimeout(() => ctrl.abort(),
|
|
23389
|
+
const timer = setTimeout(() => ctrl.abort(), timeoutMs2);
|
|
23349
23390
|
try {
|
|
23350
23391
|
const res = await fetch(url2, {
|
|
23351
23392
|
method: "POST",
|
|
@@ -27921,7 +27962,7 @@ function deepFreeze(value) {
|
|
|
27921
27962
|
return Object.freeze(value);
|
|
27922
27963
|
}
|
|
27923
27964
|
async function runInSandbox(opts) {
|
|
27924
|
-
const { bundleCode, sdk, timeoutMs } = opts;
|
|
27965
|
+
const { bundleCode, sdk, timeoutMs: timeoutMs2 } = opts;
|
|
27925
27966
|
if (!opts.skipFootgunScan) {
|
|
27926
27967
|
const footguns = scanForFootguns(bundleCode);
|
|
27927
27968
|
if (footguns.length > 0) {
|
|
@@ -27941,7 +27982,7 @@ async function runInSandbox(opts) {
|
|
|
27941
27982
|
});
|
|
27942
27983
|
const start = Date.now();
|
|
27943
27984
|
const vmOpts = {
|
|
27944
|
-
timeout: Math.max(1,
|
|
27985
|
+
timeout: Math.max(1, timeoutMs2),
|
|
27945
27986
|
displayErrors: true,
|
|
27946
27987
|
breakOnSigint: true
|
|
27947
27988
|
};
|
|
@@ -27951,7 +27992,7 @@ async function runInSandbox(opts) {
|
|
|
27951
27992
|
} catch (err) {
|
|
27952
27993
|
const msg = err && typeof err === "object" && "message" in err ? String(err.message ?? "") : String(err);
|
|
27953
27994
|
if (/timed out/i.test(msg)) {
|
|
27954
|
-
throw new PlanError("budget_exceeded", `script exceeded ${
|
|
27995
|
+
throw new PlanError("budget_exceeded", `script exceeded ${timeoutMs2}ms budget`);
|
|
27955
27996
|
}
|
|
27956
27997
|
if (opts.signal?.aborted) {
|
|
27957
27998
|
throw new PlanError("cancelled", "script aborted by host");
|
|
@@ -28263,6 +28304,8 @@ var init_types8 = __esm({
|
|
|
28263
28304
|
"assistant.message",
|
|
28264
28305
|
"tool.call",
|
|
28265
28306
|
"tool.result",
|
|
28307
|
+
// 2.x B (crash-safe recovery): dangling call classified. State-only.
|
|
28308
|
+
"tool.interrupted",
|
|
28266
28309
|
"context.injected",
|
|
28267
28310
|
"session.compacted",
|
|
28268
28311
|
"task.created",
|
|
@@ -28515,6 +28558,82 @@ var init_writer = __esm({
|
|
|
28515
28558
|
}
|
|
28516
28559
|
});
|
|
28517
28560
|
|
|
28561
|
+
// packages/core/dist/session/recovery.js
|
|
28562
|
+
function sideEffectForTool(tool, declared) {
|
|
28563
|
+
if (declared)
|
|
28564
|
+
return declared;
|
|
28565
|
+
if (EXTERNAL.has(tool))
|
|
28566
|
+
return "external";
|
|
28567
|
+
if (READ_ONLY.has(tool))
|
|
28568
|
+
return "none";
|
|
28569
|
+
return "local";
|
|
28570
|
+
}
|
|
28571
|
+
function retrySafetyForSideEffect(sideEffect) {
|
|
28572
|
+
return sideEffect === "none" ? "safe" : "inspect-first";
|
|
28573
|
+
}
|
|
28574
|
+
function toolNameOf(call) {
|
|
28575
|
+
return typeof call.data.tool === "string" && call.data.tool.trim() ? call.data.tool : "unknown";
|
|
28576
|
+
}
|
|
28577
|
+
function callIdOf(call) {
|
|
28578
|
+
return typeof call.data.callId === "string" ? call.data.callId : `seq:${call.seq}`;
|
|
28579
|
+
}
|
|
28580
|
+
function classifyInterruptedTools(events, sideEffects = /* @__PURE__ */ new Map()) {
|
|
28581
|
+
const alreadyClassified = new Set(events.filter((e) => e.kind === "tool.interrupted").map((e) => typeof e.data.callId === "string" ? e.data.callId : void 0).filter((id) => Boolean(id)));
|
|
28582
|
+
const out = [];
|
|
28583
|
+
for (const pair of pairToolCalls(events)) {
|
|
28584
|
+
if (pair.result)
|
|
28585
|
+
continue;
|
|
28586
|
+
const callId = callIdOf(pair.call);
|
|
28587
|
+
if (alreadyClassified.has(callId))
|
|
28588
|
+
continue;
|
|
28589
|
+
const tool = toolNameOf(pair.call);
|
|
28590
|
+
const sideEffect = sideEffectForTool(tool, sideEffects.get(tool));
|
|
28591
|
+
const retrySafety = retrySafetyForSideEffect(sideEffect);
|
|
28592
|
+
out.push({
|
|
28593
|
+
toolCallSeq: pair.call.seq,
|
|
28594
|
+
callId,
|
|
28595
|
+
tool,
|
|
28596
|
+
state: retrySafety === "safe" ? "not-started" : "started-outcome-unknown",
|
|
28597
|
+
retrySafety,
|
|
28598
|
+
sideEffect
|
|
28599
|
+
});
|
|
28600
|
+
}
|
|
28601
|
+
return out;
|
|
28602
|
+
}
|
|
28603
|
+
function interruptedEventData(item) {
|
|
28604
|
+
return {
|
|
28605
|
+
toolCallSeq: item.toolCallSeq,
|
|
28606
|
+
callId: item.callId,
|
|
28607
|
+
tool: item.tool,
|
|
28608
|
+
state: item.state,
|
|
28609
|
+
retrySafety: item.retrySafety,
|
|
28610
|
+
sideEffect: item.sideEffect
|
|
28611
|
+
};
|
|
28612
|
+
}
|
|
28613
|
+
var READ_ONLY, EXTERNAL;
|
|
28614
|
+
var init_recovery = __esm({
|
|
28615
|
+
"packages/core/dist/session/recovery.js"() {
|
|
28616
|
+
"use strict";
|
|
28617
|
+
init_modelSurface();
|
|
28618
|
+
READ_ONLY = /* @__PURE__ */ new Set([
|
|
28619
|
+
"read_file",
|
|
28620
|
+
"list_files",
|
|
28621
|
+
"grep_content",
|
|
28622
|
+
"show_diff",
|
|
28623
|
+
"web_search",
|
|
28624
|
+
"fetch_url",
|
|
28625
|
+
"lsp_definition",
|
|
28626
|
+
"lsp_references",
|
|
28627
|
+
"lsp_hover",
|
|
28628
|
+
"lsp_symbols",
|
|
28629
|
+
"ast_outline",
|
|
28630
|
+
"ast_find_symbol",
|
|
28631
|
+
"semantic_search"
|
|
28632
|
+
]);
|
|
28633
|
+
EXTERNAL = /* @__PURE__ */ new Set(["fetch_url", "web_search"]);
|
|
28634
|
+
}
|
|
28635
|
+
});
|
|
28636
|
+
|
|
28518
28637
|
// packages/core/dist/session/replay.js
|
|
28519
28638
|
import { promises as fs10 } from "node:fs";
|
|
28520
28639
|
async function readSessionLog(filePath) {
|
|
@@ -28599,7 +28718,8 @@ function buildProjection(events, issues = []) {
|
|
|
28599
28718
|
missionPhases: [],
|
|
28600
28719
|
missionAdvice: [],
|
|
28601
28720
|
replans: 0,
|
|
28602
|
-
issues
|
|
28721
|
+
issues,
|
|
28722
|
+
interruptedTools: classifyInterruptedTools(events)
|
|
28603
28723
|
};
|
|
28604
28724
|
for (const e of events) {
|
|
28605
28725
|
switch (e.kind) {
|
|
@@ -28650,6 +28770,7 @@ var init_replay = __esm({
|
|
|
28650
28770
|
"use strict";
|
|
28651
28771
|
init_types8();
|
|
28652
28772
|
init_modelSurface();
|
|
28773
|
+
init_recovery();
|
|
28653
28774
|
}
|
|
28654
28775
|
});
|
|
28655
28776
|
|
|
@@ -28789,12 +28910,20 @@ async function forkSession(store6, parentSessionId, options = {}) {
|
|
|
28789
28910
|
}
|
|
28790
28911
|
async function resumeSession(store6, sessionId2) {
|
|
28791
28912
|
const opened = await store6.open(sessionId2);
|
|
28913
|
+
const classified = [];
|
|
28914
|
+
for (const item of classifyInterruptedTools(opened.report.events)) {
|
|
28915
|
+
classified.push(await opened.writer.append({
|
|
28916
|
+
kind: "tool.interrupted",
|
|
28917
|
+
actor: ACTOR_SYSTEM,
|
|
28918
|
+
data: interruptedEventData(item)
|
|
28919
|
+
}));
|
|
28920
|
+
}
|
|
28792
28921
|
const resumed = await opened.writer.append({
|
|
28793
28922
|
kind: "session.resumed",
|
|
28794
28923
|
actor: ACTOR_SYSTEM,
|
|
28795
28924
|
data: { fromSeq: opened.projection.lastSeq }
|
|
28796
28925
|
});
|
|
28797
|
-
const projection = buildProjection([...opened.report.events, resumed]);
|
|
28926
|
+
const projection = buildProjection([...opened.report.events, ...classified, resumed]);
|
|
28798
28927
|
return { writer: opened.writer, projection };
|
|
28799
28928
|
}
|
|
28800
28929
|
async function lineageOf(store6, sessionId2) {
|
|
@@ -28822,6 +28951,7 @@ var init_lineage = __esm({
|
|
|
28822
28951
|
"use strict";
|
|
28823
28952
|
init_types8();
|
|
28824
28953
|
init_replay();
|
|
28954
|
+
init_recovery();
|
|
28825
28955
|
}
|
|
28826
28956
|
});
|
|
28827
28957
|
|
|
@@ -28862,6 +28992,104 @@ var init_exportSession = __esm({
|
|
|
28862
28992
|
}
|
|
28863
28993
|
});
|
|
28864
28994
|
|
|
28995
|
+
// packages/core/dist/session/invariants.js
|
|
28996
|
+
function asSeq(value) {
|
|
28997
|
+
return typeof value === "number" && Number.isInteger(value) && value > 0 ? value : void 0;
|
|
28998
|
+
}
|
|
28999
|
+
function collectEvidenceSeqs(events) {
|
|
29000
|
+
const out = [];
|
|
29001
|
+
const walk2 = (ownerSeq, value) => {
|
|
29002
|
+
if (Array.isArray(value)) {
|
|
29003
|
+
for (const item of value)
|
|
29004
|
+
walk2(ownerSeq, item);
|
|
29005
|
+
return;
|
|
29006
|
+
}
|
|
29007
|
+
if (!value || typeof value !== "object")
|
|
29008
|
+
return;
|
|
29009
|
+
const rec = value;
|
|
29010
|
+
const seq = asSeq(rec.seq);
|
|
29011
|
+
if (seq !== void 0 && ("digest" in rec || "tier" in rec || "ref" in rec)) {
|
|
29012
|
+
out.push({ ownerSeq, refSeq: seq });
|
|
29013
|
+
}
|
|
29014
|
+
for (const v of Object.values(rec))
|
|
29015
|
+
walk2(ownerSeq, v);
|
|
29016
|
+
};
|
|
29017
|
+
for (const e of events)
|
|
29018
|
+
walk2(e.seq, e.data);
|
|
29019
|
+
return out;
|
|
29020
|
+
}
|
|
29021
|
+
function validateSessionTrace(events, mode = "minimal") {
|
|
29022
|
+
const violations = [];
|
|
29023
|
+
let expected = 1;
|
|
29024
|
+
for (const e of events) {
|
|
29025
|
+
if (e.seq !== expected) {
|
|
29026
|
+
violations.push({
|
|
29027
|
+
code: "SEQ_NOT_MONOTONIC",
|
|
29028
|
+
seq: e.seq,
|
|
29029
|
+
message: `expected seq ${expected}, got ${e.seq}`
|
|
29030
|
+
});
|
|
29031
|
+
}
|
|
29032
|
+
expected = e.seq + 1;
|
|
29033
|
+
}
|
|
29034
|
+
const pairs = pairToolCalls(events);
|
|
29035
|
+
const resultCounts = /* @__PURE__ */ new Map();
|
|
29036
|
+
for (const e of events) {
|
|
29037
|
+
if (e.kind !== "tool.result")
|
|
29038
|
+
continue;
|
|
29039
|
+
const callId = typeof e.data.callId === "string" ? e.data.callId : `seq:${e.seq}`;
|
|
29040
|
+
resultCounts.set(callId, (resultCounts.get(callId) ?? 0) + 1);
|
|
29041
|
+
}
|
|
29042
|
+
for (const [callId, n] of resultCounts) {
|
|
29043
|
+
if (n > 1) {
|
|
29044
|
+
violations.push({
|
|
29045
|
+
code: "DUPLICATE_TOOL_RESULT",
|
|
29046
|
+
message: `callId ${callId} has ${n} tool.result events`
|
|
29047
|
+
});
|
|
29048
|
+
}
|
|
29049
|
+
}
|
|
29050
|
+
const interruptedCallIds = new Set(events.filter((e) => e.kind === "tool.interrupted").map((e) => typeof e.data.callId === "string" ? e.data.callId : void 0).filter((id) => Boolean(id)));
|
|
29051
|
+
for (const pair of pairs) {
|
|
29052
|
+
if (pair.result)
|
|
29053
|
+
continue;
|
|
29054
|
+
const callId = typeof pair.call.data.callId === "string" ? pair.call.data.callId : `seq:${pair.call.seq}`;
|
|
29055
|
+
if (interruptedCallIds.has(callId))
|
|
29056
|
+
continue;
|
|
29057
|
+
if (mode === "strict") {
|
|
29058
|
+
violations.push({
|
|
29059
|
+
code: "DANGLING_TOOL_CALL",
|
|
29060
|
+
seq: pair.call.seq,
|
|
29061
|
+
message: `tool.call ${callId} has no tool.result and no tool.interrupted`
|
|
29062
|
+
});
|
|
29063
|
+
}
|
|
29064
|
+
}
|
|
29065
|
+
const knownSeq = new Set(events.map((e) => e.seq));
|
|
29066
|
+
for (const ref of collectEvidenceSeqs(events)) {
|
|
29067
|
+
if (!knownSeq.has(ref.refSeq)) {
|
|
29068
|
+
violations.push({
|
|
29069
|
+
code: "EVIDENCE_SEQ_MISSING",
|
|
29070
|
+
seq: ref.ownerSeq,
|
|
29071
|
+
message: `EvidenceRef.seq ${ref.refSeq} is not an event in this trace`
|
|
29072
|
+
});
|
|
29073
|
+
}
|
|
29074
|
+
}
|
|
29075
|
+
const firstVerification = events.find((e) => e.kind === "verification.run");
|
|
29076
|
+
const firstEnded = events.find((e) => e.kind === "session.ended");
|
|
29077
|
+
if (firstVerification && firstEnded && firstEnded.seq < firstVerification.seq) {
|
|
29078
|
+
violations.push({
|
|
29079
|
+
code: "COMPLETION_BEFORE_VERIFICATION",
|
|
29080
|
+
seq: firstEnded.seq,
|
|
29081
|
+
message: `session.ended seq ${firstEnded.seq} precedes verification.run seq ${firstVerification.seq}`
|
|
29082
|
+
});
|
|
29083
|
+
}
|
|
29084
|
+
return violations;
|
|
29085
|
+
}
|
|
29086
|
+
var init_invariants = __esm({
|
|
29087
|
+
"packages/core/dist/session/invariants.js"() {
|
|
29088
|
+
"use strict";
|
|
29089
|
+
init_modelSurface();
|
|
29090
|
+
}
|
|
29091
|
+
});
|
|
29092
|
+
|
|
28865
29093
|
// packages/core/dist/session/index.js
|
|
28866
29094
|
var init_session = __esm({
|
|
28867
29095
|
"packages/core/dist/session/index.js"() {
|
|
@@ -28874,6 +29102,8 @@ var init_session = __esm({
|
|
|
28874
29102
|
init_store();
|
|
28875
29103
|
init_lineage();
|
|
28876
29104
|
init_exportSession();
|
|
29105
|
+
init_invariants();
|
|
29106
|
+
init_recovery();
|
|
28877
29107
|
}
|
|
28878
29108
|
});
|
|
28879
29109
|
|
|
@@ -29007,7 +29237,7 @@ var init_nodeProviders = __esm({
|
|
|
29007
29237
|
async exec(command, options = {}) {
|
|
29008
29238
|
const started = Date.now();
|
|
29009
29239
|
const cwd = this.workspace.resolve(options.cwd ?? ".");
|
|
29010
|
-
const
|
|
29240
|
+
const timeoutMs2 = options.timeoutMs ?? this.defaults.timeoutMs ?? DEFAULT_TIMEOUT_MS2;
|
|
29011
29241
|
const maxChars = options.maxOutputChars ?? DEFAULT_MAX_OUTPUT_CHARS;
|
|
29012
29242
|
const isWindows = process.platform === "win32";
|
|
29013
29243
|
const file2 = isWindows ? "cmd.exe" : "/bin/sh";
|
|
@@ -29030,7 +29260,7 @@ var init_nodeProviders = __esm({
|
|
|
29030
29260
|
const timer = setTimeout(() => {
|
|
29031
29261
|
timedOut = true;
|
|
29032
29262
|
killTree(child);
|
|
29033
|
-
},
|
|
29263
|
+
}, timeoutMs2);
|
|
29034
29264
|
child.stdout?.on("data", (d) => {
|
|
29035
29265
|
stdout = append(stdout, d.toString("utf-8"));
|
|
29036
29266
|
});
|
|
@@ -29486,6 +29716,72 @@ var init_types9 = __esm({
|
|
|
29486
29716
|
}
|
|
29487
29717
|
});
|
|
29488
29718
|
|
|
29719
|
+
// packages/core/dist/verification/scopeDiscipline.js
|
|
29720
|
+
function normalize(p3) {
|
|
29721
|
+
return p3.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
29722
|
+
}
|
|
29723
|
+
function isGeneratedPath(file2) {
|
|
29724
|
+
const n = normalize(file2);
|
|
29725
|
+
return GENERATED_NAME.test(n) || GENERATED_DIR.test(n);
|
|
29726
|
+
}
|
|
29727
|
+
function parseNameOnlyDiff(stdout) {
|
|
29728
|
+
return stdout.split(/\r?\n/).map((l) => l.trim()).filter(Boolean).map(normalize);
|
|
29729
|
+
}
|
|
29730
|
+
function analyzeScope(input) {
|
|
29731
|
+
const changed = input.changedFiles.map(normalize);
|
|
29732
|
+
if (changed.length === 0) {
|
|
29733
|
+
return {
|
|
29734
|
+
status: "unknown",
|
|
29735
|
+
expected: [],
|
|
29736
|
+
unexpected: [],
|
|
29737
|
+
generated: [],
|
|
29738
|
+
reasons: ["no changed files observed"]
|
|
29739
|
+
};
|
|
29740
|
+
}
|
|
29741
|
+
const expectedSet = new Set((input.expectedFiles ?? []).map(normalize));
|
|
29742
|
+
const generatedExtra = new Set((input.generatedFiles ?? []).map(normalize));
|
|
29743
|
+
const generated = [];
|
|
29744
|
+
const unexpected = [];
|
|
29745
|
+
const expectedHit = [];
|
|
29746
|
+
for (const file2 of changed) {
|
|
29747
|
+
if (generatedExtra.has(file2) || isGeneratedPath(file2)) {
|
|
29748
|
+
generated.push(file2);
|
|
29749
|
+
continue;
|
|
29750
|
+
}
|
|
29751
|
+
if (expectedSet.size === 0) {
|
|
29752
|
+
expectedHit.push(file2);
|
|
29753
|
+
continue;
|
|
29754
|
+
}
|
|
29755
|
+
if (expectedSet.has(file2))
|
|
29756
|
+
expectedHit.push(file2);
|
|
29757
|
+
else
|
|
29758
|
+
unexpected.push(file2);
|
|
29759
|
+
}
|
|
29760
|
+
const reasons = [];
|
|
29761
|
+
if (unexpected.length > 0) {
|
|
29762
|
+
reasons.push(`${unexpected.length} file(s) outside expected scope: ${unexpected.join(", ")}`);
|
|
29763
|
+
}
|
|
29764
|
+
if (generated.length > 0) {
|
|
29765
|
+
reasons.push(`${generated.length} generated/lockfile path(s) ignored for the concern`);
|
|
29766
|
+
}
|
|
29767
|
+
let status = "pass";
|
|
29768
|
+
if (expectedSet.size === 0) {
|
|
29769
|
+
status = "unknown";
|
|
29770
|
+
reasons.push("no expected-files allowlist \u2014 cannot judge scope");
|
|
29771
|
+
} else if (unexpected.length > 0) {
|
|
29772
|
+
status = "concern";
|
|
29773
|
+
}
|
|
29774
|
+
return { status, expected: expectedHit, unexpected, generated, reasons };
|
|
29775
|
+
}
|
|
29776
|
+
var GENERATED_NAME, GENERATED_DIR;
|
|
29777
|
+
var init_scopeDiscipline = __esm({
|
|
29778
|
+
"packages/core/dist/verification/scopeDiscipline.js"() {
|
|
29779
|
+
"use strict";
|
|
29780
|
+
GENERATED_NAME = /(?:^|\/)(?:package-lock\.json|pnpm-lock\.yaml|yarn\.lock|bun\.lockb|Cargo\.lock|go\.sum|poetry\.lock|composer\.lock)$/i;
|
|
29781
|
+
GENERATED_DIR = /(?:^|\/)(?:dist|build|out|coverage|\.next|node_modules)\//;
|
|
29782
|
+
}
|
|
29783
|
+
});
|
|
29784
|
+
|
|
29489
29785
|
// packages/core/dist/verification/engine.js
|
|
29490
29786
|
import { createHash as createHash4 } from "node:crypto";
|
|
29491
29787
|
function defaultSha256(input) {
|
|
@@ -29498,6 +29794,7 @@ var VerificationEngine;
|
|
|
29498
29794
|
var init_engine = __esm({
|
|
29499
29795
|
"packages/core/dist/verification/engine.js"() {
|
|
29500
29796
|
"use strict";
|
|
29797
|
+
init_scopeDiscipline();
|
|
29501
29798
|
VerificationEngine = class {
|
|
29502
29799
|
services;
|
|
29503
29800
|
options;
|
|
@@ -29509,7 +29806,7 @@ var init_engine = __esm({
|
|
|
29509
29806
|
async evaluate(criteria, context = {}) {
|
|
29510
29807
|
const results = [];
|
|
29511
29808
|
for (const criterion of criteria) {
|
|
29512
|
-
results.push(await this.evaluateOne(criterion));
|
|
29809
|
+
results.push(await this.evaluateOne(criterion, context.scope));
|
|
29513
29810
|
}
|
|
29514
29811
|
if (this.options.emit) {
|
|
29515
29812
|
try {
|
|
@@ -29559,7 +29856,7 @@ var init_engine = __esm({
|
|
|
29559
29856
|
return void 0;
|
|
29560
29857
|
}
|
|
29561
29858
|
}
|
|
29562
|
-
async evaluateOne(criterion) {
|
|
29859
|
+
async evaluateOne(criterion, scope) {
|
|
29563
29860
|
const started = this.options.now?.() ?? Date.now();
|
|
29564
29861
|
const base = {
|
|
29565
29862
|
criterionId: criterion.id,
|
|
@@ -29571,6 +29868,15 @@ var init_engine = __esm({
|
|
|
29571
29868
|
...patch,
|
|
29572
29869
|
durationMs: Math.max(0, (this.options.now?.() ?? Date.now()) - started)
|
|
29573
29870
|
});
|
|
29871
|
+
if (criterion.id === "quality.scope-discipline" && scope) {
|
|
29872
|
+
const analysis = analyzeScope(scope);
|
|
29873
|
+
const status = analysis.status === "pass" ? "pass" : "unknown";
|
|
29874
|
+
return done({
|
|
29875
|
+
status,
|
|
29876
|
+
evidence: [],
|
|
29877
|
+
detail: analysis.reasons.join("; ") || analysis.status
|
|
29878
|
+
});
|
|
29879
|
+
}
|
|
29574
29880
|
const check2 = criterion.check;
|
|
29575
29881
|
if (!check2 || check2.kind === "none") {
|
|
29576
29882
|
return done({
|
|
@@ -29892,9 +30198,9 @@ var init_sessionEvidence = __esm({
|
|
|
29892
30198
|
|
|
29893
30199
|
// packages/core/dist/verification/criteriaPack.v1.js
|
|
29894
30200
|
function codingCriteriaPack(options = {}) {
|
|
29895
|
-
const
|
|
30201
|
+
const timeoutMs2 = options.commandTimeoutMs ?? 6e5;
|
|
29896
30202
|
const withDefault = (o, d) => o === void 0 ? d : o;
|
|
29897
|
-
const command = (command2) => command2 ? { kind: "command", command: command2, timeoutMs } : void 0;
|
|
30203
|
+
const command = (command2) => command2 ? { kind: "command", command: command2, timeoutMs: timeoutMs2 } : void 0;
|
|
29898
30204
|
const criteria = [
|
|
29899
30205
|
{
|
|
29900
30206
|
id: "correctness.error-signals",
|
|
@@ -30184,6 +30490,7 @@ var init_verification2 = __esm({
|
|
|
30184
30490
|
init_criteriaPack_v1();
|
|
30185
30491
|
init_metrics();
|
|
30186
30492
|
init_verifier();
|
|
30493
|
+
init_scopeDiscipline();
|
|
30187
30494
|
}
|
|
30188
30495
|
});
|
|
30189
30496
|
|
|
@@ -30448,6 +30755,7 @@ __export(dist_exports, {
|
|
|
30448
30755
|
WorkspacePathEscapeError: () => WorkspacePathEscapeError,
|
|
30449
30756
|
WorktreeWorkspace: () => WorktreeWorkspace,
|
|
30450
30757
|
ZELARI_CODING_PACK_ID: () => ZELARI_CODING_PACK_ID,
|
|
30758
|
+
analyzeScope: () => analyzeScope,
|
|
30451
30759
|
applyCompletionRetry: () => applyCompletionRetry,
|
|
30452
30760
|
applyDeterministicAutofix: () => applyDeterministicAutofix,
|
|
30453
30761
|
applyImplementationWriteRetry: () => applyImplementationWriteRetry,
|
|
@@ -30478,6 +30786,7 @@ __export(dist_exports, {
|
|
|
30478
30786
|
checkImplementationDelivery: () => checkImplementationDelivery,
|
|
30479
30787
|
checkMemberToolEmissionSets: () => checkMemberToolEmissionSets,
|
|
30480
30788
|
checkMemberToolEmissions: () => checkMemberToolEmissions,
|
|
30789
|
+
classifyInterruptedTools: () => classifyInterruptedTools,
|
|
30481
30790
|
classifyMission: () => classifyMission,
|
|
30482
30791
|
classifyTaskScope: () => classifyTaskScope,
|
|
30483
30792
|
cleanAgentContent: () => cleanAgentContent,
|
|
@@ -30545,6 +30854,7 @@ __export(dist_exports, {
|
|
|
30545
30854
|
hasInteractiveClarification: () => hasInteractiveClarification,
|
|
30546
30855
|
hashToolCall: () => hashToolCall,
|
|
30547
30856
|
hookMatches: () => hookMatches,
|
|
30857
|
+
interruptedEventData: () => interruptedEventData,
|
|
30548
30858
|
isAnswerLeak: () => isAnswerLeak,
|
|
30549
30859
|
isBrainAgentEndEvent: () => isBrainAgentEndEvent,
|
|
30550
30860
|
isBrainAgentStartEvent: () => isBrainAgentStartEvent,
|
|
@@ -30568,6 +30878,7 @@ __export(dist_exports, {
|
|
|
30568
30878
|
isConverged: () => isConverged,
|
|
30569
30879
|
isEventBackedEvidence: () => isEventBackedEvidence,
|
|
30570
30880
|
isExperimentalEnabled: () => isExperimentalEnabled,
|
|
30881
|
+
isGeneratedPath: () => isGeneratedPath,
|
|
30571
30882
|
isModelSurfaceEvent: () => isModelSurfaceEvent,
|
|
30572
30883
|
isReviewerKind: () => isReviewerKind,
|
|
30573
30884
|
isSettled: () => isSettled,
|
|
@@ -30594,6 +30905,7 @@ __export(dist_exports, {
|
|
|
30594
30905
|
parseClarificationRequest: () => parseClarificationRequest,
|
|
30595
30906
|
parseEvidenceTier: () => parseEvidenceTier,
|
|
30596
30907
|
parseMinimaxStyleToolCalls: () => parseMinimaxStyleToolCalls,
|
|
30908
|
+
parseNameOnlyDiff: () => parseNameOnlyDiff,
|
|
30597
30909
|
parsePersonaVerdict: () => parsePersonaVerdict,
|
|
30598
30910
|
parseProjectRootFromWorkspaceContext: () => parseProjectRootFromWorkspaceContext,
|
|
30599
30911
|
parseTextToolCalls: () => parseTextToolCalls,
|
|
@@ -30631,6 +30943,7 @@ __export(dist_exports, {
|
|
|
30631
30943
|
resolveVerifyRetryTool: () => resolveVerifyRetryTool,
|
|
30632
30944
|
restrictImplementationWrites: () => restrictImplementationWrites,
|
|
30633
30945
|
resumeSession: () => resumeSession,
|
|
30946
|
+
retrySafetyForSideEffect: () => retrySafetyForSideEffect,
|
|
30634
30947
|
runChairmanDeliveryLoop: () => runChairmanDeliveryLoop,
|
|
30635
30948
|
runChairmanFixLoop: () => runChairmanFixLoop,
|
|
30636
30949
|
runChairmanMicroGate: () => runChairmanMicroGate,
|
|
@@ -30647,6 +30960,7 @@ __export(dist_exports, {
|
|
|
30647
30960
|
setWorkspaceStubs: () => setWorkspaceStubs,
|
|
30648
30961
|
sha256Hex: () => sha256Hex,
|
|
30649
30962
|
shouldRetryMember: () => shouldRetryMember,
|
|
30963
|
+
sideEffectForTool: () => sideEffectForTool,
|
|
30650
30964
|
slugify: () => slugify2,
|
|
30651
30965
|
snapshotToCompletionEvaluation: () => snapshotToCompletionEvaluation,
|
|
30652
30966
|
specificityFromAssumptions: () => specificityFromAssumptions,
|
|
@@ -30666,6 +30980,7 @@ __export(dist_exports, {
|
|
|
30666
30980
|
utf8Bytes: () => utf8Bytes,
|
|
30667
30981
|
validateCodingSkillRequires: () => validateCodingSkillRequires,
|
|
30668
30982
|
validateGraph: () => validateGraph,
|
|
30983
|
+
validateSessionTrace: () => validateSessionTrace,
|
|
30669
30984
|
verificationCostRatio: () => verificationCostRatio,
|
|
30670
30985
|
verifiedSolveRate: () => verifiedSolveRate,
|
|
30671
30986
|
verifyCitations: () => verifyCitations,
|
|
@@ -32966,10 +33281,26 @@ var init_registry2 = __esm({
|
|
|
32966
33281
|
if (!parsed.success) {
|
|
32967
33282
|
return typedErr(`Invalid input: ${parsed.error.message}`);
|
|
32968
33283
|
}
|
|
32969
|
-
const
|
|
32970
|
-
const
|
|
33284
|
+
const timeoutMs2 = options.timeoutMs ?? tool.timeoutMs ?? 3e4;
|
|
33285
|
+
const parentSignal = options.signal;
|
|
33286
|
+
const controller = new AbortController();
|
|
33287
|
+
let timer;
|
|
33288
|
+
let rejectRace;
|
|
33289
|
+
const onParentAbort = () => {
|
|
33290
|
+
if (timer !== void 0)
|
|
33291
|
+
clearTimeout(timer);
|
|
33292
|
+
if (!controller.signal.aborted)
|
|
33293
|
+
controller.abort();
|
|
33294
|
+
rejectRace?.(new Error(`Tool "${name}" aborted`));
|
|
33295
|
+
};
|
|
33296
|
+
if (parentSignal) {
|
|
33297
|
+
if (parentSignal.aborted)
|
|
33298
|
+
onParentAbort();
|
|
33299
|
+
else
|
|
33300
|
+
parentSignal.addEventListener("abort", onParentAbort);
|
|
33301
|
+
}
|
|
32971
33302
|
const ctx = {
|
|
32972
|
-
signal:
|
|
33303
|
+
signal: controller.signal,
|
|
32973
33304
|
cwd: options.cwd ?? process.cwd(),
|
|
32974
33305
|
audit: () => {
|
|
32975
33306
|
},
|
|
@@ -32982,6 +33313,7 @@ var init_registry2 = __esm({
|
|
|
32982
33313
|
cwd: ctx.cwd
|
|
32983
33314
|
});
|
|
32984
33315
|
if (!pre.ok) {
|
|
33316
|
+
parentSignal?.removeEventListener("abort", onParentAbort);
|
|
32985
33317
|
return typedErr(`[hook:${pre.hookName ?? "unknown"}] ${pre.reason ?? "denied"}`);
|
|
32986
33318
|
}
|
|
32987
33319
|
} catch (hookErr) {
|
|
@@ -32991,11 +33323,16 @@ var init_registry2 = __esm({
|
|
|
32991
33323
|
const result = await Promise.race([
|
|
32992
33324
|
tool.execute(parsed.data, ctx),
|
|
32993
33325
|
new Promise((_, reject) => {
|
|
32994
|
-
|
|
32995
|
-
|
|
32996
|
-
|
|
32997
|
-
|
|
32998
|
-
}
|
|
33326
|
+
rejectRace = reject;
|
|
33327
|
+
if (parentSignal?.aborted) {
|
|
33328
|
+
onParentAbort();
|
|
33329
|
+
return;
|
|
33330
|
+
}
|
|
33331
|
+
timer = setTimeout(() => {
|
|
33332
|
+
if (!controller.signal.aborted)
|
|
33333
|
+
controller.abort();
|
|
33334
|
+
reject(new Error(`Tool "${name}" timed out after ${timeoutMs2}ms`));
|
|
33335
|
+
}, timeoutMs2);
|
|
32999
33336
|
})
|
|
33000
33337
|
]);
|
|
33001
33338
|
if (result.ok) {
|
|
@@ -33030,6 +33367,11 @@ var init_registry2 = __esm({
|
|
|
33030
33367
|
} catch (err) {
|
|
33031
33368
|
const error51 = err instanceof Error ? err.message : String(err);
|
|
33032
33369
|
return typedErr(error51);
|
|
33370
|
+
} finally {
|
|
33371
|
+
rejectRace = void 0;
|
|
33372
|
+
if (timer !== void 0)
|
|
33373
|
+
clearTimeout(timer);
|
|
33374
|
+
parentSignal?.removeEventListener("abort", onParentAbort);
|
|
33033
33375
|
}
|
|
33034
33376
|
}
|
|
33035
33377
|
/** Return all tool definitions in OpenAI function-calling format (memoized). */
|
|
@@ -33336,11 +33678,11 @@ async function runDiagnosticsForFile(file2, options = {}) {
|
|
|
33336
33678
|
const provider = providerForFile(file2, options.providers);
|
|
33337
33679
|
if (!provider) return [];
|
|
33338
33680
|
const cwd = options.cwd ?? process.cwd();
|
|
33339
|
-
const
|
|
33681
|
+
const timeoutMs2 = options.timeoutMs ?? 5e3;
|
|
33340
33682
|
const runner = options.runner ?? defaultRunner;
|
|
33341
33683
|
try {
|
|
33342
33684
|
const bin = options.runner ? provider.bin : resolveBin(provider.bin, cwd);
|
|
33343
|
-
const result = await runner(bin, provider.args(file2), { cwd, timeoutMs });
|
|
33685
|
+
const result = await runner(bin, provider.args(file2), { cwd, timeoutMs: timeoutMs2 });
|
|
33344
33686
|
return provider.parse(result.stdout, file2);
|
|
33345
33687
|
} catch {
|
|
33346
33688
|
return [];
|
|
@@ -33829,7 +34171,7 @@ var init_candidateRegistry = __esm({
|
|
|
33829
34171
|
});
|
|
33830
34172
|
|
|
33831
34173
|
// src/cli/kraken/verifyReport.ts
|
|
33832
|
-
function
|
|
34174
|
+
function normalize2(text) {
|
|
33833
34175
|
return text.toLowerCase().replace(/\s+/g, " ").trim();
|
|
33834
34176
|
}
|
|
33835
34177
|
function extractVerifyReportBlocks(raw) {
|
|
@@ -33858,11 +34200,11 @@ function extractVerifyReportBlocks(raw) {
|
|
|
33858
34200
|
function parseVerifyReport(raw, requiredChecks) {
|
|
33859
34201
|
const byCriterion = /* @__PURE__ */ new Map();
|
|
33860
34202
|
for (const block of extractVerifyReportBlocks(raw)) {
|
|
33861
|
-
byCriterion.set(
|
|
34203
|
+
byCriterion.set(normalize2(block.check), block);
|
|
33862
34204
|
}
|
|
33863
34205
|
const keys = [...byCriterion.keys()];
|
|
33864
34206
|
return requiredChecks.map((check2) => {
|
|
33865
|
-
const norm =
|
|
34207
|
+
const norm = normalize2(check2);
|
|
33866
34208
|
let block = byCriterion.get(norm) ?? null;
|
|
33867
34209
|
if (!block) {
|
|
33868
34210
|
for (const key of keys) {
|
|
@@ -33901,18 +34243,18 @@ var init_verifyReport = __esm({
|
|
|
33901
34243
|
});
|
|
33902
34244
|
|
|
33903
34245
|
// src/cli/kraken/completionGate.ts
|
|
33904
|
-
function
|
|
34246
|
+
function normalize3(text) {
|
|
33905
34247
|
return text.toLowerCase().replace(/\s+/g, " ").trim();
|
|
33906
34248
|
}
|
|
33907
34249
|
function classifyKrakenChecks(requiredChecks, results) {
|
|
33908
34250
|
const byCriterion = /* @__PURE__ */ new Map();
|
|
33909
34251
|
for (const result of results ?? []) {
|
|
33910
|
-
byCriterion.set(
|
|
34252
|
+
byCriterion.set(normalize3(result.check), result);
|
|
33911
34253
|
}
|
|
33912
34254
|
const keys = [...byCriterion.keys()];
|
|
33913
34255
|
const out = { passed: [], failed: [], unknown: [] };
|
|
33914
34256
|
for (const check2 of requiredChecks) {
|
|
33915
|
-
const norm =
|
|
34257
|
+
const norm = normalize3(check2);
|
|
33916
34258
|
let result = byCriterion.get(norm) ?? null;
|
|
33917
34259
|
if (!result) {
|
|
33918
34260
|
for (const key of keys) {
|
|
@@ -34137,69 +34479,79 @@ async function runSubAgent(harness, opts = {}) {
|
|
|
34137
34479
|
let usage;
|
|
34138
34480
|
const pendingTools = /* @__PURE__ */ new Map();
|
|
34139
34481
|
const toolTrace = [];
|
|
34140
|
-
|
|
34141
|
-
|
|
34142
|
-
|
|
34143
|
-
|
|
34144
|
-
|
|
34145
|
-
|
|
34146
|
-
|
|
34147
|
-
|
|
34148
|
-
|
|
34149
|
-
|
|
34150
|
-
|
|
34151
|
-
|
|
34152
|
-
|
|
34153
|
-
|
|
34154
|
-
|
|
34155
|
-
|
|
34156
|
-
tool: started?.tool ?? "unknown",
|
|
34157
|
-
callId: ev.toolCallId,
|
|
34158
|
-
ok: !ev.isError,
|
|
34159
|
-
...started?.command ? { command: started.command } : {},
|
|
34160
|
-
output: String(ev.result ?? "").slice(0, TOOL_TRACE_OUTPUT_MAX),
|
|
34161
|
-
durationMs: ev.durationMs,
|
|
34162
|
-
endedAt: Date.now()
|
|
34163
|
-
});
|
|
34164
|
-
if (toolTrace.length > TOOL_TRACE_RING) {
|
|
34165
|
-
toolTrace.splice(0, toolTrace.length - TOOL_TRACE_RING);
|
|
34482
|
+
const onAbort = () => harness.cancel?.();
|
|
34483
|
+
if (signal?.aborted) {
|
|
34484
|
+
onAbort();
|
|
34485
|
+
return { result: "", aborted: true };
|
|
34486
|
+
}
|
|
34487
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
34488
|
+
try {
|
|
34489
|
+
for await (const ev of harness.run()) {
|
|
34490
|
+
if (signal?.aborted) {
|
|
34491
|
+
onAbort();
|
|
34492
|
+
return {
|
|
34493
|
+
result: (lastCompleted || current).trim(),
|
|
34494
|
+
...error51 ? { error: error51 } : {},
|
|
34495
|
+
aborted: true,
|
|
34496
|
+
...toolTrace.length > 0 ? { toolTrace } : {}
|
|
34497
|
+
};
|
|
34166
34498
|
}
|
|
34167
|
-
|
|
34168
|
-
|
|
34169
|
-
|
|
34170
|
-
|
|
34171
|
-
|
|
34172
|
-
|
|
34173
|
-
|
|
34174
|
-
|
|
34175
|
-
|
|
34176
|
-
|
|
34177
|
-
|
|
34178
|
-
|
|
34179
|
-
|
|
34180
|
-
|
|
34181
|
-
|
|
34182
|
-
|
|
34183
|
-
cachedPromptTokens: (usage.cachedPromptTokens ?? 0) + (ev.usage.cachedPromptTokens ?? 0)
|
|
34184
|
-
} : {}
|
|
34185
|
-
} : ev.usage;
|
|
34499
|
+
if (ev.type === "tool_execution_start") {
|
|
34500
|
+
pendingTools.set(ev.toolCallId, { tool: ev.toolName, command: toolCommandHint(ev.args) });
|
|
34501
|
+
} else if (ev.type === "tool_execution_end") {
|
|
34502
|
+
const started = pendingTools.get(ev.toolCallId);
|
|
34503
|
+
pendingTools.delete(ev.toolCallId);
|
|
34504
|
+
toolTrace.push({
|
|
34505
|
+
tool: started?.tool ?? "unknown",
|
|
34506
|
+
callId: ev.toolCallId,
|
|
34507
|
+
ok: !ev.isError,
|
|
34508
|
+
...started?.command ? { command: started.command } : {},
|
|
34509
|
+
output: String(ev.result ?? "").slice(0, TOOL_TRACE_OUTPUT_MAX),
|
|
34510
|
+
durationMs: ev.durationMs,
|
|
34511
|
+
endedAt: Date.now()
|
|
34512
|
+
});
|
|
34513
|
+
if (toolTrace.length > TOOL_TRACE_RING) {
|
|
34514
|
+
toolTrace.splice(0, toolTrace.length - TOOL_TRACE_RING);
|
|
34186
34515
|
}
|
|
34187
|
-
|
|
34188
|
-
|
|
34189
|
-
|
|
34190
|
-
|
|
34191
|
-
|
|
34192
|
-
|
|
34193
|
-
|
|
34516
|
+
}
|
|
34517
|
+
switch (ev.type) {
|
|
34518
|
+
case "message_start":
|
|
34519
|
+
current = "";
|
|
34520
|
+
break;
|
|
34521
|
+
case "message_delta":
|
|
34522
|
+
current += ev.delta;
|
|
34523
|
+
break;
|
|
34524
|
+
case "message_end":
|
|
34525
|
+
if (current.trim()) lastCompleted = current;
|
|
34526
|
+
if (ev.usage) {
|
|
34527
|
+
usage = usage ? {
|
|
34528
|
+
promptTokens: usage.promptTokens + ev.usage.promptTokens,
|
|
34529
|
+
completionTokens: usage.completionTokens + ev.usage.completionTokens,
|
|
34530
|
+
totalTokens: usage.totalTokens + ev.usage.totalTokens,
|
|
34531
|
+
...(usage.cachedPromptTokens ?? 0) + (ev.usage.cachedPromptTokens ?? 0) > 0 ? {
|
|
34532
|
+
cachedPromptTokens: (usage.cachedPromptTokens ?? 0) + (ev.usage.cachedPromptTokens ?? 0)
|
|
34533
|
+
} : {}
|
|
34534
|
+
} : ev.usage;
|
|
34535
|
+
}
|
|
34536
|
+
current = "";
|
|
34537
|
+
break;
|
|
34538
|
+
case "error":
|
|
34539
|
+
error51 = ev.message;
|
|
34540
|
+
break;
|
|
34541
|
+
default:
|
|
34542
|
+
break;
|
|
34543
|
+
}
|
|
34194
34544
|
}
|
|
34545
|
+
const result = (lastCompleted || current).trim();
|
|
34546
|
+
return {
|
|
34547
|
+
result,
|
|
34548
|
+
...error51 ? { error: error51 } : {},
|
|
34549
|
+
...usage ? { usage } : {},
|
|
34550
|
+
...toolTrace.length > 0 ? { toolTrace } : {}
|
|
34551
|
+
};
|
|
34552
|
+
} finally {
|
|
34553
|
+
signal?.removeEventListener("abort", onAbort);
|
|
34195
34554
|
}
|
|
34196
|
-
const result = (lastCompleted || current).trim();
|
|
34197
|
-
return {
|
|
34198
|
-
result,
|
|
34199
|
-
...error51 ? { error: error51 } : {},
|
|
34200
|
-
...usage ? { usage } : {},
|
|
34201
|
-
...toolTrace.length > 0 ? { toolTrace } : {}
|
|
34202
|
-
};
|
|
34203
34555
|
}
|
|
34204
34556
|
async function runTentacle(opts) {
|
|
34205
34557
|
const { deps, args, agent, thoroughness, parentCwd, sessionId: sessionId2 } = opts;
|
|
@@ -34429,7 +34781,7 @@ function createTaskTool(deps, policy = {}) {
|
|
|
34429
34781
|
description: "Delegate a focused sub-task to an isolated sub-agent with its own context; returns only a concise conclusion (keeps parent context lean).\n- agent=explore (default): read-only research/search\n- agent=general: can edit files for one bounded unit of work\n- agent=verify: read + bash to run tests/checks\nProvide a fully self-contained `prompt` (sub-agent cannot see this conversation). Optional scope[] + acceptance[] contracts. After general, follow up with verify." + (restricted ? `
|
|
34430
34782
|
RESTRICTED in this mode: only agent=${allowedAgents.join("|")} is allowed.` : ""),
|
|
34431
34783
|
permissions: ["read", "network", "write", "execute"],
|
|
34432
|
-
timeoutMs:
|
|
34784
|
+
timeoutMs: TASK_TOOL_TIMEOUT_MS,
|
|
34433
34785
|
inputSchema: inputSchema2,
|
|
34434
34786
|
execute: async (args, ctx) => {
|
|
34435
34787
|
const agent = args.agent ?? "explore";
|
|
@@ -34532,7 +34884,7 @@ ${res.result}${res.footer}`,
|
|
|
34532
34884
|
}
|
|
34533
34885
|
};
|
|
34534
34886
|
}
|
|
34535
|
-
var EXPLORE_PROMPT, GENERAL_PROMPT, VERIFY_PROMPT, TaskArgsSchema, TaskPurposeSchema, TaskArgsWithPurposeSchema, TOOL_TRACE_RING, TOOL_TRACE_OUTPUT_MAX;
|
|
34887
|
+
var TASK_TOOL_TIMEOUT_MS, EXPLORE_PROMPT, GENERAL_PROMPT, VERIFY_PROMPT, TaskArgsSchema, TaskPurposeSchema, TaskArgsWithPurposeSchema, TOOL_TRACE_RING, TOOL_TRACE_OUTPUT_MAX;
|
|
34536
34888
|
var init_taskTool = __esm({
|
|
34537
34889
|
"src/cli/tools/taskTool.ts"() {
|
|
34538
34890
|
"use strict";
|
|
@@ -34544,6 +34896,7 @@ var init_taskTool = __esm({
|
|
|
34544
34896
|
init_candidateRegistry();
|
|
34545
34897
|
init_verifyReport();
|
|
34546
34898
|
init_metrics3();
|
|
34899
|
+
TASK_TOOL_TIMEOUT_MS = 9e5;
|
|
34547
34900
|
EXPLORE_PROMPT = [
|
|
34548
34901
|
"You are a focused EXPLORE tentacle of Kraken (parent super-agent).",
|
|
34549
34902
|
"READ-ONLY tools only (read, list, grep, fetch). No edits, no shell.",
|
|
@@ -34831,7 +35184,7 @@ function renderVerdict(verdict, candidateCount) {
|
|
|
34831
35184
|
return lines.join("\n");
|
|
34832
35185
|
}
|
|
34833
35186
|
function createKrakenSelectTool(deps) {
|
|
34834
|
-
const
|
|
35187
|
+
const timeoutMs2 = deps.timeoutMs ?? 12e4;
|
|
34835
35188
|
return {
|
|
34836
35189
|
name: "kraken_select",
|
|
34837
35190
|
description: "Compare the candidate research reports spawned this turn (task purpose=candidate) and select the hypothesis best supported by OBSERVED EVIDENCE. A dedicated verifier call (default: the current model) judges grounded vs unsupported claims; degraded observations are never treated as proof of absence. Returns the selected candidate, a rationale, and requiredChecks the implementation must pass. Call it ONCE per turn, after candidate tentacles finished and BEFORE implementing. If it reports needs_more_evidence, either spawn ONE more differentiated candidate or proceed with your own judgment.",
|
|
@@ -34888,7 +35241,7 @@ function createKrakenSelectTool(deps) {
|
|
|
34888
35241
|
model: id.model,
|
|
34889
35242
|
provider: id.provider,
|
|
34890
35243
|
tools: [],
|
|
34891
|
-
signal: AbortSignal.timeout(
|
|
35244
|
+
signal: AbortSignal.timeout(timeoutMs2)
|
|
34892
35245
|
});
|
|
34893
35246
|
judgingUsage = usage;
|
|
34894
35247
|
if (raw.trim().length === 0) throw new Error("empty verifier response");
|
|
@@ -38439,7 +38792,7 @@ exec node "$(dirname "$0")/askpass.cjs"
|
|
|
38439
38792
|
}
|
|
38440
38793
|
return sh;
|
|
38441
38794
|
}
|
|
38442
|
-
function runSsh(target, remoteCommand,
|
|
38795
|
+
function runSsh(target, remoteCommand, timeoutMs2 = 6e4) {
|
|
38443
38796
|
return new Promise((resolve3) => {
|
|
38444
38797
|
if (target.auth === "password" && !getSshPassword(target.id)) {
|
|
38445
38798
|
resolve3({
|
|
@@ -38479,7 +38832,7 @@ function runSsh(target, remoteCommand, timeoutMs = 6e4) {
|
|
|
38479
38832
|
stdout,
|
|
38480
38833
|
stderr: stderr + "\n[ssh] timeout"
|
|
38481
38834
|
});
|
|
38482
|
-
},
|
|
38835
|
+
}, timeoutMs2);
|
|
38483
38836
|
child.on("error", (err) => {
|
|
38484
38837
|
clearTimeout(timer);
|
|
38485
38838
|
resolve3({
|
|
@@ -38708,7 +39061,7 @@ async function readChecks(cwd) {
|
|
|
38708
39061
|
return [];
|
|
38709
39062
|
}
|
|
38710
39063
|
}
|
|
38711
|
-
function runShell(command, cwd,
|
|
39064
|
+
function runShell(command, cwd, timeoutMs2, signal) {
|
|
38712
39065
|
return new Promise((resolve3) => {
|
|
38713
39066
|
const isWin = process.platform === "win32";
|
|
38714
39067
|
const child = spawn10(isWin ? "cmd.exe" : "/bin/sh", isWin ? ["/c", command] : ["-c", command], {
|
|
@@ -38720,7 +39073,7 @@ function runShell(command, cwd, timeoutMs, signal) {
|
|
|
38720
39073
|
let stdout = "";
|
|
38721
39074
|
let stderr = "";
|
|
38722
39075
|
let settled = false;
|
|
38723
|
-
const
|
|
39076
|
+
const finish2 = (exitCode) => {
|
|
38724
39077
|
if (settled) return;
|
|
38725
39078
|
settled = true;
|
|
38726
39079
|
resolve3({ exitCode, stdout, stderr });
|
|
@@ -38730,8 +39083,8 @@ function runShell(command, cwd, timeoutMs, signal) {
|
|
|
38730
39083
|
child.kill("SIGTERM");
|
|
38731
39084
|
} catch {
|
|
38732
39085
|
}
|
|
38733
|
-
|
|
38734
|
-
},
|
|
39086
|
+
finish2(124);
|
|
39087
|
+
}, timeoutMs2);
|
|
38735
39088
|
if (signal) {
|
|
38736
39089
|
if (signal.aborted) {
|
|
38737
39090
|
try {
|
|
@@ -38739,7 +39092,7 @@ function runShell(command, cwd, timeoutMs, signal) {
|
|
|
38739
39092
|
} catch {
|
|
38740
39093
|
}
|
|
38741
39094
|
clearTimeout(timer);
|
|
38742
|
-
|
|
39095
|
+
finish2(130);
|
|
38743
39096
|
return;
|
|
38744
39097
|
}
|
|
38745
39098
|
signal.addEventListener(
|
|
@@ -38750,7 +39103,7 @@ function runShell(command, cwd, timeoutMs, signal) {
|
|
|
38750
39103
|
} catch {
|
|
38751
39104
|
}
|
|
38752
39105
|
clearTimeout(timer);
|
|
38753
|
-
|
|
39106
|
+
finish2(130);
|
|
38754
39107
|
},
|
|
38755
39108
|
{ once: true }
|
|
38756
39109
|
);
|
|
@@ -38765,11 +39118,11 @@ function runShell(command, cwd, timeoutMs, signal) {
|
|
|
38765
39118
|
});
|
|
38766
39119
|
child.on("error", () => {
|
|
38767
39120
|
clearTimeout(timer);
|
|
38768
|
-
|
|
39121
|
+
finish2(1);
|
|
38769
39122
|
});
|
|
38770
39123
|
child.on("close", (code) => {
|
|
38771
39124
|
clearTimeout(timer);
|
|
38772
|
-
|
|
39125
|
+
finish2(code ?? 1);
|
|
38773
39126
|
});
|
|
38774
39127
|
});
|
|
38775
39128
|
}
|
|
@@ -38791,9 +39144,9 @@ async function runBacktest(cwd, signal) {
|
|
|
38791
39144
|
const results = [];
|
|
38792
39145
|
for (const c of checks) {
|
|
38793
39146
|
const expectExit = c.expectExit ?? 0;
|
|
38794
|
-
const
|
|
39147
|
+
const timeoutMs2 = c.timeoutMs ?? 12e4;
|
|
38795
39148
|
const start = Date.now();
|
|
38796
|
-
const { exitCode, stdout, stderr } = await runShell(c.command, cwd,
|
|
39149
|
+
const { exitCode, stdout, stderr } = await runShell(c.command, cwd, timeoutMs2, signal);
|
|
38797
39150
|
const combined = `${stdout}${stderr}`;
|
|
38798
39151
|
const preview = combined.slice(0, 400);
|
|
38799
39152
|
let ok = exitCode === expectExit;
|
|
@@ -39077,7 +39430,7 @@ import path38 from "node:path";
|
|
|
39077
39430
|
function trustStorePath() {
|
|
39078
39431
|
return _overrideStorePath ?? path38.join(homedir8(), ".zelari-code", "trust.json");
|
|
39079
39432
|
}
|
|
39080
|
-
function
|
|
39433
|
+
function normalize4(p3) {
|
|
39081
39434
|
const resolved = path38.resolve(p3);
|
|
39082
39435
|
return process.platform === "win32" ? resolved.toLowerCase() : resolved;
|
|
39083
39436
|
}
|
|
@@ -39114,14 +39467,14 @@ function isFolderTrusted(folderPath) {
|
|
|
39114
39467
|
const env = envTrustedFolder();
|
|
39115
39468
|
if (env === "all") return true;
|
|
39116
39469
|
if (env === "none") return false;
|
|
39117
|
-
if (env) return
|
|
39118
|
-
const target =
|
|
39119
|
-
return readStore3().folders.some((f) =>
|
|
39470
|
+
if (env) return normalize4(env) === normalize4(folderPath);
|
|
39471
|
+
const target = normalize4(folderPath);
|
|
39472
|
+
return readStore3().folders.some((f) => normalize4(f.path) === target);
|
|
39120
39473
|
}
|
|
39121
39474
|
function trustFolder(folderPath) {
|
|
39122
39475
|
const store6 = readStore3();
|
|
39123
39476
|
const normalized = path38.resolve(folderPath);
|
|
39124
|
-
if (!store6.folders.some((f) =>
|
|
39477
|
+
if (!store6.folders.some((f) => normalize4(f.path) === normalize4(normalized))) {
|
|
39125
39478
|
store6.folders.push({ path: normalized, trustedAt: (/* @__PURE__ */ new Date()).toISOString() });
|
|
39126
39479
|
writeStore3(store6);
|
|
39127
39480
|
}
|
|
@@ -39129,9 +39482,9 @@ function trustFolder(folderPath) {
|
|
|
39129
39482
|
}
|
|
39130
39483
|
function untrustFolder(folderPath) {
|
|
39131
39484
|
const store6 = readStore3();
|
|
39132
|
-
const target =
|
|
39485
|
+
const target = normalize4(folderPath);
|
|
39133
39486
|
const before = store6.folders.length;
|
|
39134
|
-
store6.folders = store6.folders.filter((f) =>
|
|
39487
|
+
store6.folders = store6.folders.filter((f) => normalize4(f.path) !== target);
|
|
39135
39488
|
if (store6.folders.length === before) return { ok: true, removed: false };
|
|
39136
39489
|
writeStore3(store6);
|
|
39137
39490
|
return { ok: true, removed: true };
|
|
@@ -39505,8 +39858,9 @@ function createBuiltinToolRegistry(options = {}) {
|
|
|
39505
39858
|
if (hooks) registry4.setLifecycleHooks(hooks);
|
|
39506
39859
|
const readOnly = options.readOnly === true || options.planMode === true || profile === "explore";
|
|
39507
39860
|
const verifyMode = profile === "verify";
|
|
39508
|
-
const
|
|
39509
|
-
const
|
|
39861
|
+
const gauntletParent = options.gauntletParent === true;
|
|
39862
|
+
const allowMutators = !readOnly && !verifyMode && !gauntletParent;
|
|
39863
|
+
const allowBash = (allowMutators || verifyMode) && !gauntletParent;
|
|
39510
39864
|
const permPolicy = options.permissionPolicy ?? defaultPermissionPolicy();
|
|
39511
39865
|
const withPerm = (t) => wrapWithPermissions(t, permPolicy, options.onPermissionAsk);
|
|
39512
39866
|
registry4.register(withPerm(safeReadFile));
|
|
@@ -39539,21 +39893,21 @@ function createBuiltinToolRegistry(options = {}) {
|
|
|
39539
39893
|
if (allowBash) {
|
|
39540
39894
|
registry4.register(withPerm(safeBash));
|
|
39541
39895
|
}
|
|
39542
|
-
const askUserTool = options.readOnly === true || profile === "explore" || profile === "verify" ? null : createAskUserTool(options.onAskUser);
|
|
39896
|
+
const askUserTool = options.readOnly === true || profile === "explore" || profile === "verify" || gauntletParent ? null : createAskUserTool(options.onAskUser);
|
|
39543
39897
|
if (askUserTool) {
|
|
39544
39898
|
registry4.register(withPerm(askUserTool));
|
|
39545
39899
|
}
|
|
39546
|
-
const enableSkill = options.enableSkill !== false && options.readOnly !== true && profile !== "explore" && profile !== "verify";
|
|
39900
|
+
const enableSkill = options.enableSkill !== false && options.readOnly !== true && !gauntletParent && profile !== "explore" && profile !== "verify";
|
|
39547
39901
|
const skillTool = enableSkill ? withPerm(createSkillTool({ cwd: root })) : null;
|
|
39548
39902
|
if (skillTool) {
|
|
39549
39903
|
registry4.register(skillTool);
|
|
39550
39904
|
}
|
|
39551
|
-
const enableTodos = options.enableTodos !== false && options.readOnly !== true && profile === "full";
|
|
39905
|
+
const enableTodos = options.enableTodos !== false && options.readOnly !== true && !gauntletParent && profile === "full";
|
|
39552
39906
|
const todoWrite = enableTodos ? withPerm(createTodoWriteTool()) : null;
|
|
39553
39907
|
const todoRead = enableTodos ? withPerm(createTodoReadTool()) : null;
|
|
39554
39908
|
if (todoWrite) registry4.register(todoWrite);
|
|
39555
39909
|
if (todoRead) registry4.register(todoRead);
|
|
39556
|
-
const enablePlanTasks = options.enablePlanTasks !== false && options.readOnly !== true && (profile === "full" || options.planMode === true) && profile !== "explore" && profile !== "verify" && profile !== "general";
|
|
39910
|
+
const enablePlanTasks = options.enablePlanTasks !== false && options.readOnly !== true && !gauntletParent && (profile === "full" || options.planMode === true) && profile !== "explore" && profile !== "verify" && profile !== "general";
|
|
39557
39911
|
const planTaskToolsWrapped = (enablePlanTasks ? createPlanTaskTools({ projectRoot: root, onTaskEvent: options.onTaskEvent }) : []).map((t) => withPerm(t));
|
|
39558
39912
|
for (const t of planTaskToolsWrapped) {
|
|
39559
39913
|
registry4.register(t);
|
|
@@ -39604,7 +39958,7 @@ function createBuiltinToolRegistry(options = {}) {
|
|
|
39604
39958
|
permissions: semanticTool.permissions ?? []
|
|
39605
39959
|
});
|
|
39606
39960
|
}
|
|
39607
|
-
if (!readOnly && process.env.ZELARI_BROWSER !== "0") {
|
|
39961
|
+
if (!readOnly && !gauntletParent && process.env.ZELARI_BROWSER !== "0") {
|
|
39608
39962
|
const browserTool = createBrowserTool();
|
|
39609
39963
|
registry4.register(browserTool);
|
|
39610
39964
|
tools.push({
|
|
@@ -39613,7 +39967,7 @@ function createBuiltinToolRegistry(options = {}) {
|
|
|
39613
39967
|
permissions: browserTool.permissions ?? []
|
|
39614
39968
|
});
|
|
39615
39969
|
}
|
|
39616
|
-
if (!readOnly && process.env.ZELARI_SSH !== "0") {
|
|
39970
|
+
if (!readOnly && !gauntletParent && process.env.ZELARI_SSH !== "0") {
|
|
39617
39971
|
for (const t of createSshTools()) {
|
|
39618
39972
|
registry4.register(t);
|
|
39619
39973
|
tools.push({
|
|
@@ -39623,7 +39977,7 @@ function createBuiltinToolRegistry(options = {}) {
|
|
|
39623
39977
|
});
|
|
39624
39978
|
}
|
|
39625
39979
|
}
|
|
39626
|
-
if (!readOnly) {
|
|
39980
|
+
if (!readOnly && !gauntletParent) {
|
|
39627
39981
|
for (const t of createWorldModelTools()) {
|
|
39628
39982
|
const safe = wrapWithAudit(t, audit, sessionId2);
|
|
39629
39983
|
registry4.register(safe);
|
|
@@ -39849,10 +40203,10 @@ function wrapWithDiagnostics(original, root, runner) {
|
|
|
39849
40203
|
const filePath = value && typeof value === "object" && typeof value.path === "string" ? value.path : void 0;
|
|
39850
40204
|
if (!filePath) return result;
|
|
39851
40205
|
try {
|
|
39852
|
-
const
|
|
40206
|
+
const timeoutMs2 = Number(process.env.ZELARI_DIAGNOSTICS_TIMEOUT_MS) || 5e3;
|
|
39853
40207
|
const diags = await runDiagnosticsForFile(filePath, {
|
|
39854
40208
|
cwd: root,
|
|
39855
|
-
timeoutMs,
|
|
40209
|
+
timeoutMs: timeoutMs2,
|
|
39856
40210
|
...runner ? { runner } : {}
|
|
39857
40211
|
});
|
|
39858
40212
|
const formatted = formatDiagnostics(diags, { relativeTo: root });
|
|
@@ -40117,6 +40471,7 @@ function parseHeadlessFlags(argv) {
|
|
|
40117
40471
|
let krakenGraph;
|
|
40118
40472
|
let planOnly = process.env.ZELARI_KRAKEN_PLAN_ONLY === "1" || process.env.ZELARI_KRAKEN_PLAN_ONLY === "true";
|
|
40119
40473
|
let runPlan = process.env.ZELARI_KRAKEN_RUN_PLAN;
|
|
40474
|
+
let gauntlet = process.env.ZELARI_GAUNTLET === "1" || process.env.ZELARI_GAUNTLET === "true";
|
|
40120
40475
|
for (let i = 0; i < argv.length; i++) {
|
|
40121
40476
|
const arg = argv[i];
|
|
40122
40477
|
if (arg === "--headless") continue;
|
|
@@ -40287,6 +40642,10 @@ function parseHeadlessFlags(argv) {
|
|
|
40287
40642
|
} else if (arg === "--run-plan") {
|
|
40288
40643
|
runPlan = argv[i + 1];
|
|
40289
40644
|
i++;
|
|
40645
|
+
} else if (arg === "--gauntlet") {
|
|
40646
|
+
gauntlet = true;
|
|
40647
|
+
} else if (arg === "--no-gauntlet") {
|
|
40648
|
+
gauntlet = false;
|
|
40290
40649
|
}
|
|
40291
40650
|
}
|
|
40292
40651
|
if (councilFlag && !modeExplicit) {
|
|
@@ -40321,7 +40680,8 @@ function parseHeadlessFlags(argv) {
|
|
|
40321
40680
|
...strictDone ? { strictDone: true } : {},
|
|
40322
40681
|
...krakenGraph ? { krakenGraph } : {},
|
|
40323
40682
|
...planOnly ? { planOnly: true } : {},
|
|
40324
|
-
...runPlan ? { runPlan } : {}
|
|
40683
|
+
...runPlan ? { runPlan } : {},
|
|
40684
|
+
...gauntlet ? { gauntlet: true } : {}
|
|
40325
40685
|
}
|
|
40326
40686
|
};
|
|
40327
40687
|
}
|
|
@@ -41632,10 +41992,10 @@ __export(claudeProvider_exports, {
|
|
|
41632
41992
|
createLocalCliProvider: () => createLocalCliProvider
|
|
41633
41993
|
});
|
|
41634
41994
|
import { spawn as spawn11 } from "node:child_process";
|
|
41635
|
-
function waitForExit(child,
|
|
41995
|
+
function waitForExit(child, timeoutMs2 = 2e3) {
|
|
41636
41996
|
return new Promise((resolve3) => {
|
|
41637
41997
|
if (child.exitCode != null) return resolve3(child.exitCode);
|
|
41638
|
-
const timer = setTimeout(() => resolve3(child.exitCode ?? null),
|
|
41998
|
+
const timer = setTimeout(() => resolve3(child.exitCode ?? null), timeoutMs2);
|
|
41639
41999
|
timer.unref?.();
|
|
41640
42000
|
child.once("exit", (code) => {
|
|
41641
42001
|
clearTimeout(timer);
|
|
@@ -43206,10 +43566,10 @@ function distTagForVersion(version2) {
|
|
|
43206
43566
|
function registryUrlForTag(tag = distTagForVersion(getCurrentVersion())) {
|
|
43207
43567
|
return `https://registry.npmjs.org/zelari-code/${tag}`;
|
|
43208
43568
|
}
|
|
43209
|
-
async function fetchLatestVersion(fetcher = fetch, registryUrl = REGISTRY_URL,
|
|
43569
|
+
async function fetchLatestVersion(fetcher = fetch, registryUrl = REGISTRY_URL, timeoutMs2 = 5e3) {
|
|
43210
43570
|
try {
|
|
43211
43571
|
const controller = new AbortController();
|
|
43212
|
-
const timer = setTimeout(() => controller.abort(),
|
|
43572
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs2);
|
|
43213
43573
|
const response = await fetcher(registryUrl, { signal: controller.signal });
|
|
43214
43574
|
clearTimeout(timer);
|
|
43215
43575
|
if (!response.ok) {
|
|
@@ -43379,11 +43739,11 @@ var init_mcpClient = __esm({
|
|
|
43379
43739
|
* Call a tool. Returns the concatenated text content; non-text content
|
|
43380
43740
|
* items are summarized by type. Throws when the server flags isError.
|
|
43381
43741
|
*/
|
|
43382
|
-
async callTool(name, args,
|
|
43742
|
+
async callTool(name, args, timeoutMs2 = DEFAULT_REQUEST_TIMEOUT_MS) {
|
|
43383
43743
|
const res = await this.request(
|
|
43384
43744
|
"tools/call",
|
|
43385
43745
|
{ name, arguments: args },
|
|
43386
|
-
|
|
43746
|
+
timeoutMs2
|
|
43387
43747
|
);
|
|
43388
43748
|
const text = (res.content ?? []).map(
|
|
43389
43749
|
(c) => c.type === "text" && typeof c.text === "string" ? c.text : `[${c.type ?? "unknown"} content]`
|
|
@@ -43400,7 +43760,7 @@ var init_mcpClient = __esm({
|
|
|
43400
43760
|
this.child = null;
|
|
43401
43761
|
}
|
|
43402
43762
|
// ── JSON-RPC plumbing ────────────────────────────────────────────────
|
|
43403
|
-
request(method, params,
|
|
43763
|
+
request(method, params, timeoutMs2 = DEFAULT_REQUEST_TIMEOUT_MS) {
|
|
43404
43764
|
const child = this.child;
|
|
43405
43765
|
if (!child)
|
|
43406
43766
|
return Promise.reject(new Error(`[mcp:${this.serverName}] not started`));
|
|
@@ -43411,10 +43771,10 @@ var init_mcpClient = __esm({
|
|
|
43411
43771
|
this.pending.delete(id);
|
|
43412
43772
|
reject(
|
|
43413
43773
|
new Error(
|
|
43414
|
-
`[mcp:${this.serverName}] ${method} timed out after ${
|
|
43774
|
+
`[mcp:${this.serverName}] ${method} timed out after ${timeoutMs2}ms`
|
|
43415
43775
|
)
|
|
43416
43776
|
);
|
|
43417
|
-
},
|
|
43777
|
+
}, timeoutMs2);
|
|
43418
43778
|
this.pending.set(id, { resolve: resolve3, reject, timer });
|
|
43419
43779
|
child.stdin.write(payload + "\n", (err) => {
|
|
43420
43780
|
if (err) {
|
|
@@ -44488,7 +44848,7 @@ function pickSmokeScript(scripts) {
|
|
|
44488
44848
|
}
|
|
44489
44849
|
return null;
|
|
44490
44850
|
}
|
|
44491
|
-
async function runProjectSmoke(projectRoot,
|
|
44851
|
+
async function runProjectSmoke(projectRoot, timeoutMs2 = DEFAULT_TIMEOUT_MS3) {
|
|
44492
44852
|
if (process.env["ZELARI_SMOKE"] === "0") {
|
|
44493
44853
|
return { ran: false, reason: "ZELARI_SMOKE=0 (disabled)" };
|
|
44494
44854
|
}
|
|
@@ -44521,7 +44881,7 @@ async function runProjectSmoke(projectRoot, timeoutMs = DEFAULT_TIMEOUT_MS3) {
|
|
|
44521
44881
|
let stdout = "";
|
|
44522
44882
|
let stderr = "";
|
|
44523
44883
|
let settled = false;
|
|
44524
|
-
const
|
|
44884
|
+
const finish2 = (result) => {
|
|
44525
44885
|
if (settled) return;
|
|
44526
44886
|
settled = true;
|
|
44527
44887
|
clearTimeout(timer);
|
|
@@ -44529,15 +44889,15 @@ async function runProjectSmoke(projectRoot, timeoutMs = DEFAULT_TIMEOUT_MS3) {
|
|
|
44529
44889
|
};
|
|
44530
44890
|
const timer = setTimeout(() => {
|
|
44531
44891
|
child.kill("SIGTERM");
|
|
44532
|
-
|
|
44892
|
+
finish2({
|
|
44533
44893
|
ran: true,
|
|
44534
44894
|
ok: false,
|
|
44535
44895
|
script,
|
|
44536
44896
|
exitCode: -1,
|
|
44537
44897
|
output: stdout + stderr,
|
|
44538
|
-
reason: `smoke timeout after ${
|
|
44898
|
+
reason: `smoke timeout after ${timeoutMs2}ms`
|
|
44539
44899
|
});
|
|
44540
|
-
},
|
|
44900
|
+
}, timeoutMs2);
|
|
44541
44901
|
child.stdout?.on("data", (chunk) => {
|
|
44542
44902
|
stdout += chunk.toString("utf8");
|
|
44543
44903
|
});
|
|
@@ -44545,7 +44905,7 @@ async function runProjectSmoke(projectRoot, timeoutMs = DEFAULT_TIMEOUT_MS3) {
|
|
|
44545
44905
|
stderr += chunk.toString("utf8");
|
|
44546
44906
|
});
|
|
44547
44907
|
child.on("error", (err) => {
|
|
44548
|
-
|
|
44908
|
+
finish2({
|
|
44549
44909
|
ran: true,
|
|
44550
44910
|
ok: false,
|
|
44551
44911
|
script,
|
|
@@ -44557,7 +44917,7 @@ async function runProjectSmoke(projectRoot, timeoutMs = DEFAULT_TIMEOUT_MS3) {
|
|
|
44557
44917
|
child.on("close", (code) => {
|
|
44558
44918
|
const exitCode = code ?? -1;
|
|
44559
44919
|
const ok = exitCode === 0;
|
|
44560
|
-
|
|
44920
|
+
finish2({
|
|
44561
44921
|
ran: true,
|
|
44562
44922
|
ok,
|
|
44563
44923
|
script,
|
|
@@ -46166,7 +46526,7 @@ function startPermissionBroker(socketPath, handlers, opts) {
|
|
|
46166
46526
|
const closeAll = server.closeAllConnections;
|
|
46167
46527
|
if (typeof closeAll === "function") closeAll.call(server);
|
|
46168
46528
|
let done = false;
|
|
46169
|
-
const
|
|
46529
|
+
const finish2 = () => {
|
|
46170
46530
|
if (done) return;
|
|
46171
46531
|
done = true;
|
|
46172
46532
|
if (process.platform !== "win32") {
|
|
@@ -46175,8 +46535,8 @@ function startPermissionBroker(socketPath, handlers, opts) {
|
|
|
46175
46535
|
res();
|
|
46176
46536
|
}
|
|
46177
46537
|
};
|
|
46178
|
-
server.close(() =>
|
|
46179
|
-
setTimeout(
|
|
46538
|
+
server.close(() => finish2());
|
|
46539
|
+
setTimeout(finish2, 1e3).unref?.();
|
|
46180
46540
|
})
|
|
46181
46541
|
});
|
|
46182
46542
|
});
|
|
@@ -46613,13 +46973,13 @@ async function createDefaultLlmClient(opts) {
|
|
|
46613
46973
|
const llm = await resolveLlm(opts);
|
|
46614
46974
|
return {
|
|
46615
46975
|
async complete({ system, user }) {
|
|
46616
|
-
const
|
|
46976
|
+
const timeoutMs2 = resolvePlannerTimeoutMs();
|
|
46617
46977
|
const controller = new AbortController();
|
|
46618
46978
|
let timedOut = false;
|
|
46619
|
-
const t =
|
|
46979
|
+
const t = timeoutMs2 > 0 ? setTimeout(() => {
|
|
46620
46980
|
timedOut = true;
|
|
46621
46981
|
controller.abort();
|
|
46622
|
-
},
|
|
46982
|
+
}, timeoutMs2) : void 0;
|
|
46623
46983
|
try {
|
|
46624
46984
|
const url2 = `${llm.baseUrl.replace(/\/$/, "")}/chat/completions`;
|
|
46625
46985
|
let res;
|
|
@@ -46645,7 +47005,7 @@ async function createDefaultLlmClient(opts) {
|
|
|
46645
47005
|
} catch (err) {
|
|
46646
47006
|
if (timedOut) {
|
|
46647
47007
|
throw new PlannerTransportError(
|
|
46648
|
-
`Planner request timed out after ${Math.round(
|
|
47008
|
+
`Planner request timed out after ${Math.round(timeoutMs2 / 1e3)}s (no response). Raise ZELARI_KRAKEN_PLANNER_TIMEOUT_MS, or set ZELARI_KRAKEN_PLANNER_MODEL to a faster non-reasoning model.`
|
|
46649
47009
|
);
|
|
46650
47010
|
}
|
|
46651
47011
|
throw new PlannerTransportError(
|
|
@@ -47538,7 +47898,7 @@ var init_executor = __esm({
|
|
|
47538
47898
|
DEFAULT_MAX_REVIEW_ROUNDS = 1;
|
|
47539
47899
|
DEFAULT_GRAPH_TIMEOUT_MS = 0;
|
|
47540
47900
|
DEFAULT_NODE_TIMEOUT_MS = 3e5;
|
|
47541
|
-
DEFAULT_WRITER_NODE_TIMEOUT_MS =
|
|
47901
|
+
DEFAULT_WRITER_NODE_TIMEOUT_MS = TASK_TOOL_TIMEOUT_MS;
|
|
47542
47902
|
DEFAULT_CANCEL_GRACE_MS = 3e4;
|
|
47543
47903
|
MAX_UPSTREAM_CHARS_PER_DEP = 2800;
|
|
47544
47904
|
MAX_UPSTREAM_CHARS_TOTAL = 8e3;
|
|
@@ -49028,10 +49388,10 @@ async function validateApiKey(providerId, apiKey, options = {}) {
|
|
|
49028
49388
|
return { ok: true, skipped: true, reason: "no_base_url" };
|
|
49029
49389
|
}
|
|
49030
49390
|
const probeUrl = options.probeUrl ?? `${spec.baseUrl.replace(/\/+$/, "")}/models`;
|
|
49031
|
-
const
|
|
49391
|
+
const timeoutMs2 = options.timeoutMs ?? 5e3;
|
|
49032
49392
|
const fetchImpl = options.fetchImpl ?? fetch;
|
|
49033
49393
|
const controller = new AbortController();
|
|
49034
|
-
const timer = setTimeout(() => controller.abort(),
|
|
49394
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs2);
|
|
49035
49395
|
try {
|
|
49036
49396
|
const response = await fetchImpl(probeUrl, {
|
|
49037
49397
|
method: "GET",
|
|
@@ -49060,7 +49420,7 @@ async function validateApiKey(providerId, apiKey, options = {}) {
|
|
|
49060
49420
|
return {
|
|
49061
49421
|
ok: false,
|
|
49062
49422
|
reason: isAbort ? "network" : "network",
|
|
49063
|
-
detail: isAbort ? `timeout after ${
|
|
49423
|
+
detail: isAbort ? `timeout after ${timeoutMs2}ms` : msg,
|
|
49064
49424
|
durationMs
|
|
49065
49425
|
};
|
|
49066
49426
|
} finally {
|
|
@@ -49829,6 +50189,864 @@ var init_atMentions = __esm({
|
|
|
49829
50189
|
}
|
|
49830
50190
|
});
|
|
49831
50191
|
|
|
50192
|
+
// src/cli/gauntlet/policy.ts
|
|
50193
|
+
var policy_exports = {};
|
|
50194
|
+
__export(policy_exports, {
|
|
50195
|
+
DEFAULT_MAX_PARALLEL: () => DEFAULT_MAX_PARALLEL2,
|
|
50196
|
+
DEFAULT_MAX_PIECES: () => DEFAULT_MAX_PIECES,
|
|
50197
|
+
DEFAULT_MAX_ROUNDS: () => DEFAULT_MAX_ROUNDS,
|
|
50198
|
+
DEFAULT_WALL_MS: () => DEFAULT_WALL_MS,
|
|
50199
|
+
GAUNTLET_PARENT_BLOCKED_TOOLS: () => GAUNTLET_PARENT_BLOCKED_TOOLS,
|
|
50200
|
+
isGauntletFlagOn: () => isGauntletFlagOn,
|
|
50201
|
+
resolveGauntletCaps: () => resolveGauntletCaps,
|
|
50202
|
+
shouldRunGauntletHostLoop: () => shouldRunGauntletHostLoop
|
|
50203
|
+
});
|
|
50204
|
+
function envInt(raw, fallback, min, max) {
|
|
50205
|
+
if (raw === void 0 || raw === "") return fallback;
|
|
50206
|
+
const n = Number.parseInt(raw, 10);
|
|
50207
|
+
if (!Number.isFinite(n)) return fallback;
|
|
50208
|
+
return Math.min(max, Math.max(min, n));
|
|
50209
|
+
}
|
|
50210
|
+
function isGauntletFlagOn(explicit, env = process.env) {
|
|
50211
|
+
if (explicit === true) return true;
|
|
50212
|
+
if (explicit === false) return false;
|
|
50213
|
+
const raw = env.ZELARI_GAUNTLET;
|
|
50214
|
+
if (!raw) return false;
|
|
50215
|
+
return raw === "1" || raw.toLowerCase() === "true";
|
|
50216
|
+
}
|
|
50217
|
+
function resolveGauntletCaps(env = process.env) {
|
|
50218
|
+
const wallRaw = env.ZELARI_GAUNTLET_WALL_MS;
|
|
50219
|
+
let wallClockMs = DEFAULT_WALL_MS;
|
|
50220
|
+
if (wallRaw !== void 0 && wallRaw !== "") {
|
|
50221
|
+
const n = Number.parseInt(wallRaw, 10);
|
|
50222
|
+
if (Number.isFinite(n) && n >= 0) wallClockMs = n;
|
|
50223
|
+
}
|
|
50224
|
+
return {
|
|
50225
|
+
maxPieces: envInt(env.ZELARI_GAUNTLET_MAX_PIECES, DEFAULT_MAX_PIECES, 1, 16),
|
|
50226
|
+
maxRounds: envInt(env.ZELARI_GAUNTLET_MAX_ROUNDS, DEFAULT_MAX_ROUNDS, 1, 8),
|
|
50227
|
+
maxParallel: envInt(env.ZELARI_GAUNTLET_MAX_PARALLEL, DEFAULT_MAX_PARALLEL2, 1, 4),
|
|
50228
|
+
wallClockMs
|
|
50229
|
+
};
|
|
50230
|
+
}
|
|
50231
|
+
function shouldRunGauntletHostLoop(opts) {
|
|
50232
|
+
if (!isGauntletFlagOn(opts.gauntlet)) return false;
|
|
50233
|
+
if (opts.krakenGraph) return false;
|
|
50234
|
+
if (opts.useCouncil || opts.mode === "council" || opts.mode === "zelari") return false;
|
|
50235
|
+
const phase2 = opts.phase ?? "build";
|
|
50236
|
+
return phase2 !== "plan";
|
|
50237
|
+
}
|
|
50238
|
+
var DEFAULT_MAX_PIECES, DEFAULT_MAX_ROUNDS, DEFAULT_MAX_PARALLEL2, DEFAULT_WALL_MS, GAUNTLET_PARENT_BLOCKED_TOOLS;
|
|
50239
|
+
var init_policy = __esm({
|
|
50240
|
+
"src/cli/gauntlet/policy.ts"() {
|
|
50241
|
+
"use strict";
|
|
50242
|
+
DEFAULT_MAX_PIECES = 6;
|
|
50243
|
+
DEFAULT_MAX_ROUNDS = 3;
|
|
50244
|
+
DEFAULT_MAX_PARALLEL2 = 2;
|
|
50245
|
+
DEFAULT_WALL_MS = 45 * 60 * 1e3;
|
|
50246
|
+
GAUNTLET_PARENT_BLOCKED_TOOLS = [
|
|
50247
|
+
"write_file",
|
|
50248
|
+
"edit_file",
|
|
50249
|
+
"apply_diff",
|
|
50250
|
+
"bash"
|
|
50251
|
+
];
|
|
50252
|
+
}
|
|
50253
|
+
});
|
|
50254
|
+
|
|
50255
|
+
// src/cli/gauntlet/complete.ts
|
|
50256
|
+
function timeoutMs(env = process.env) {
|
|
50257
|
+
const raw = env.ZELARI_GAUNTLET_DECOMPOSE_TIMEOUT_MS;
|
|
50258
|
+
if (raw === void 0 || raw === "") return DEFAULT_TIMEOUT_MS4;
|
|
50259
|
+
const n = Number.parseInt(raw, 10);
|
|
50260
|
+
return Number.isFinite(n) && n >= 0 ? n : DEFAULT_TIMEOUT_MS4;
|
|
50261
|
+
}
|
|
50262
|
+
async function gauntletComplete(args, opts) {
|
|
50263
|
+
const provider = opts.provider;
|
|
50264
|
+
const meta3 = await resolveApiKeyWithMeta(provider);
|
|
50265
|
+
if (!meta3?.apiKey) {
|
|
50266
|
+
throw new Error(`No API key for provider '${provider}'`);
|
|
50267
|
+
}
|
|
50268
|
+
const baseUrl = resolveBaseUrl(provider);
|
|
50269
|
+
if (!baseUrl) {
|
|
50270
|
+
throw new Error(`No base URL for provider '${provider}'`);
|
|
50271
|
+
}
|
|
50272
|
+
const model = process.env.ZELARI_KRAKEN_PLANNER_MODEL?.trim() || opts.model || getModelForProvider(provider) || getProviderConfig().modelByProvider[provider] || "";
|
|
50273
|
+
if (!model) throw new Error(`No model for provider '${provider}'`);
|
|
50274
|
+
const ms = timeoutMs();
|
|
50275
|
+
const controller = new AbortController();
|
|
50276
|
+
const onParentAbort = () => controller.abort();
|
|
50277
|
+
opts.signal?.addEventListener("abort", onParentAbort, { once: true });
|
|
50278
|
+
let timedOut = false;
|
|
50279
|
+
const timer = ms > 0 ? setTimeout(() => {
|
|
50280
|
+
timedOut = true;
|
|
50281
|
+
controller.abort();
|
|
50282
|
+
}, ms) : void 0;
|
|
50283
|
+
try {
|
|
50284
|
+
const url2 = `${baseUrl.replace(/\/$/, "")}/chat/completions`;
|
|
50285
|
+
const res = await fetch(url2, {
|
|
50286
|
+
method: "POST",
|
|
50287
|
+
signal: controller.signal,
|
|
50288
|
+
headers: {
|
|
50289
|
+
"content-type": "application/json",
|
|
50290
|
+
authorization: `Bearer ${meta3.apiKey}`
|
|
50291
|
+
},
|
|
50292
|
+
body: JSON.stringify({
|
|
50293
|
+
model,
|
|
50294
|
+
temperature: 0.2,
|
|
50295
|
+
max_tokens: DEFAULT_MAX_TOKENS,
|
|
50296
|
+
stream: false,
|
|
50297
|
+
messages: [
|
|
50298
|
+
{ role: "system", content: args.system },
|
|
50299
|
+
{ role: "user", content: args.user }
|
|
50300
|
+
]
|
|
50301
|
+
})
|
|
50302
|
+
});
|
|
50303
|
+
if (!res.ok) {
|
|
50304
|
+
const errBody = await res.text().catch(() => "");
|
|
50305
|
+
throw new Error(`decompose HTTP ${res.status}${errBody ? `: ${errBody.slice(0, 160)}` : ""}`);
|
|
50306
|
+
}
|
|
50307
|
+
const json2 = await res.json();
|
|
50308
|
+
const msg = json2.choices?.[0]?.message;
|
|
50309
|
+
const text = msg?.content?.trim() || msg?.reasoning_content?.trim() || "";
|
|
50310
|
+
if (!text) throw new Error("decompose: empty model response");
|
|
50311
|
+
return text;
|
|
50312
|
+
} catch (err) {
|
|
50313
|
+
if (timedOut) {
|
|
50314
|
+
throw new Error(
|
|
50315
|
+
`decompose timed out after ${Math.round(ms / 1e3)}s \u2014 using a single piece. Raise ZELARI_GAUNTLET_DECOMPOSE_TIMEOUT_MS or set ZELARI_KRAKEN_PLANNER_MODEL to a fast model.`
|
|
50316
|
+
);
|
|
50317
|
+
}
|
|
50318
|
+
throw err instanceof Error ? err : new Error(String(err));
|
|
50319
|
+
} finally {
|
|
50320
|
+
if (timer) clearTimeout(timer);
|
|
50321
|
+
opts.signal?.removeEventListener("abort", onParentAbort);
|
|
50322
|
+
}
|
|
50323
|
+
}
|
|
50324
|
+
var DEFAULT_TIMEOUT_MS4, DEFAULT_MAX_TOKENS;
|
|
50325
|
+
var init_complete = __esm({
|
|
50326
|
+
"src/cli/gauntlet/complete.ts"() {
|
|
50327
|
+
"use strict";
|
|
50328
|
+
init_providerConfig();
|
|
50329
|
+
init_keyStore();
|
|
50330
|
+
init_openai_compatible();
|
|
50331
|
+
DEFAULT_TIMEOUT_MS4 = 6e4;
|
|
50332
|
+
DEFAULT_MAX_TOKENS = 2048;
|
|
50333
|
+
}
|
|
50334
|
+
});
|
|
50335
|
+
|
|
50336
|
+
// src/cli/gauntlet/decompose.ts
|
|
50337
|
+
function fallbackPieces(goal) {
|
|
50338
|
+
const prompt = goal.trim() || "Complete the user Goal.";
|
|
50339
|
+
return [
|
|
50340
|
+
{
|
|
50341
|
+
id: "g1",
|
|
50342
|
+
label: labelFromGoal(prompt),
|
|
50343
|
+
prompt,
|
|
50344
|
+
acceptance: []
|
|
50345
|
+
}
|
|
50346
|
+
];
|
|
50347
|
+
}
|
|
50348
|
+
function labelFromGoal(goal) {
|
|
50349
|
+
const line = goal.trim().split(/\r?\n/, 1)[0] ?? "Goal";
|
|
50350
|
+
return line.slice(0, MAX_LABEL) || "Goal";
|
|
50351
|
+
}
|
|
50352
|
+
function parsePiecesJson(raw, maxPieces) {
|
|
50353
|
+
if (!raw || typeof raw !== "object") return null;
|
|
50354
|
+
const rec = raw;
|
|
50355
|
+
const list = rec.pieces ?? rec.nodes;
|
|
50356
|
+
if (!Array.isArray(list) || list.length === 0) return null;
|
|
50357
|
+
const out = [];
|
|
50358
|
+
for (let i = 0; i < list.length && out.length < maxPieces; i++) {
|
|
50359
|
+
const item = list[i];
|
|
50360
|
+
if (!item || typeof item !== "object") continue;
|
|
50361
|
+
const row = item;
|
|
50362
|
+
const prompt = typeof row.prompt === "string" ? row.prompt.trim() : typeof row.goal === "string" ? row.goal.trim() : "";
|
|
50363
|
+
if (!prompt) continue;
|
|
50364
|
+
const id = typeof row.id === "string" && row.id.trim() ? row.id.trim().slice(0, 32) : `g${out.length + 1}`;
|
|
50365
|
+
const label = typeof row.label === "string" && row.label.trim() ? row.label.trim().slice(0, MAX_LABEL) : labelFromGoal(prompt);
|
|
50366
|
+
const acceptance = Array.isArray(row.acceptance) ? row.acceptance.filter((a) => typeof a === "string" && a.trim().length > 0).map((a) => a.trim()).slice(0, MAX_ACCEPTANCE) : [];
|
|
50367
|
+
const scope = Array.isArray(row.scope) ? row.scope.filter((s) => typeof s === "string" && s.trim().length > 0).map((s) => s.trim()).slice(0, 16) : void 0;
|
|
50368
|
+
const bar = Array.isArray(row.bar) ? row.bar.filter((s) => typeof s === "string" && s.trim().length > 0).map((s) => s.trim()).slice(0, 4) : void 0;
|
|
50369
|
+
out.push({
|
|
50370
|
+
id: uniqueId2(id, out),
|
|
50371
|
+
label,
|
|
50372
|
+
prompt: prompt.slice(0, MAX_PROMPT),
|
|
50373
|
+
acceptance,
|
|
50374
|
+
...scope && scope.length > 0 ? { scope } : {},
|
|
50375
|
+
...bar && bar.length > 0 ? { bar } : {}
|
|
50376
|
+
});
|
|
50377
|
+
}
|
|
50378
|
+
return out.length > 0 ? out : null;
|
|
50379
|
+
}
|
|
50380
|
+
function formatHistoryNote(messages, maxMessages = 4, each = 400) {
|
|
50381
|
+
const slice = messages.filter((m) => m.role === "user" || m.role === "assistant").slice(-maxMessages);
|
|
50382
|
+
if (slice.length === 0) return "";
|
|
50383
|
+
return slice.map((m) => {
|
|
50384
|
+
const body = m.content.replace(/\s+/g, " ").trim().slice(0, each);
|
|
50385
|
+
return `${m.role}: ${body}`;
|
|
50386
|
+
}).join("\n");
|
|
50387
|
+
}
|
|
50388
|
+
function buildDecomposeUser(opts) {
|
|
50389
|
+
const parts = [
|
|
50390
|
+
`Max pieces: ${opts.maxPieces}`,
|
|
50391
|
+
"",
|
|
50392
|
+
"## Goal",
|
|
50393
|
+
opts.goal.trim() || "(empty)"
|
|
50394
|
+
];
|
|
50395
|
+
if (opts.historyNote?.trim()) {
|
|
50396
|
+
parts.push("", "## Prior turns (context only \u2014 the Goal above is authoritative)", opts.historyNote.trim());
|
|
50397
|
+
}
|
|
50398
|
+
if (opts.workspace?.trim()) {
|
|
50399
|
+
parts.push("", "## Workspace", opts.workspace.trim());
|
|
50400
|
+
}
|
|
50401
|
+
return parts.join("\n");
|
|
50402
|
+
}
|
|
50403
|
+
function piecesFromModelText(text, maxPieces) {
|
|
50404
|
+
try {
|
|
50405
|
+
const json2 = extractJsonObject(text, { requireKey: "pieces" });
|
|
50406
|
+
return parsePiecesJson(json2, maxPieces);
|
|
50407
|
+
} catch {
|
|
50408
|
+
return null;
|
|
50409
|
+
}
|
|
50410
|
+
}
|
|
50411
|
+
async function decomposeGoal(opts) {
|
|
50412
|
+
const fallback = fallbackPieces(opts.goal);
|
|
50413
|
+
if (!opts.complete) return { pieces: fallback, source: "fallback" };
|
|
50414
|
+
try {
|
|
50415
|
+
const text = await opts.complete({
|
|
50416
|
+
system: GAUNTLET_DECOMPOSE_SYSTEM,
|
|
50417
|
+
user: buildDecomposeUser(opts)
|
|
50418
|
+
});
|
|
50419
|
+
const parsed = piecesFromModelText(text, opts.maxPieces);
|
|
50420
|
+
if (parsed && parsed.length > 0) return { pieces: parsed, source: "llm" };
|
|
50421
|
+
return { pieces: fallback, source: "fallback", error: "decompose JSON unusable" };
|
|
50422
|
+
} catch (err) {
|
|
50423
|
+
return {
|
|
50424
|
+
pieces: fallback,
|
|
50425
|
+
source: "fallback",
|
|
50426
|
+
error: err instanceof Error ? err.message : String(err)
|
|
50427
|
+
};
|
|
50428
|
+
}
|
|
50429
|
+
}
|
|
50430
|
+
function uniqueId2(id, existing) {
|
|
50431
|
+
if (!existing.some((p3) => p3.id === id)) return id;
|
|
50432
|
+
let n = 2;
|
|
50433
|
+
while (existing.some((p3) => p3.id === `${id}-${n}`)) n += 1;
|
|
50434
|
+
return `${id}-${n}`;
|
|
50435
|
+
}
|
|
50436
|
+
var MAX_LABEL, MAX_PROMPT, MAX_ACCEPTANCE, GAUNTLET_DECOMPOSE_SYSTEM;
|
|
50437
|
+
var init_decompose = __esm({
|
|
50438
|
+
"src/cli/gauntlet/decompose.ts"() {
|
|
50439
|
+
"use strict";
|
|
50440
|
+
init_planner();
|
|
50441
|
+
MAX_LABEL = 80;
|
|
50442
|
+
MAX_PROMPT = 8e3;
|
|
50443
|
+
MAX_ACCEPTANCE = 8;
|
|
50444
|
+
GAUNTLET_DECOMPOSE_SYSTEM = [
|
|
50445
|
+
"Decompose the user Goal into independently shippable Gauntlet pieces.",
|
|
50446
|
+
"Return ONLY JSON (no markdown, no prose):",
|
|
50447
|
+
'{ "pieces": [ { "id": string, "label": string, "prompt": string, "scope"?: string[], "acceptance"?: string[], "bar"?: string[] } ] }',
|
|
50448
|
+
"Rules:",
|
|
50449
|
+
"- 1 to N pieces (N is given in the user message). Prefer fewer. One piece is valid when the goal is atomic.",
|
|
50450
|
+
'- "prompt" is self-contained: the builder will not see this conversation.',
|
|
50451
|
+
'- "scope" is a path allowlist so disjoint pieces can run in parallel. Omit if unsure (forces sequential).',
|
|
50452
|
+
'- "acceptance" is checkable (file, command, observable). Never subjective ("elegant").',
|
|
50453
|
+
'- "bar" (optional) is on-disk reference path(s) the critic compares against blindly (gold file, screenshot, test).',
|
|
50454
|
+
"- Use paths from the workspace listing. Do not invent a tree.",
|
|
50455
|
+
"- Decompose the USER GOAL literally. Do not enlarge it into a different project."
|
|
50456
|
+
].join("\n");
|
|
50457
|
+
}
|
|
50458
|
+
});
|
|
50459
|
+
|
|
50460
|
+
// src/cli/gauntlet/events.ts
|
|
50461
|
+
function gauntletProgressEvent(sessionId2, progress) {
|
|
50462
|
+
return {
|
|
50463
|
+
type: "gauntlet_progress",
|
|
50464
|
+
sessionId: sessionId2,
|
|
50465
|
+
ts: Date.now(),
|
|
50466
|
+
progress
|
|
50467
|
+
};
|
|
50468
|
+
}
|
|
50469
|
+
function formatGauntletSummary(results, opts) {
|
|
50470
|
+
if (results.length === 0) {
|
|
50471
|
+
if (opts?.timedOut) return "Gauntlet stopped: wall clock. No pieces finished.";
|
|
50472
|
+
if (opts?.cancelled) return "Gauntlet cancelled. No pieces finished.";
|
|
50473
|
+
return "Gauntlet: no pieces ran.";
|
|
50474
|
+
}
|
|
50475
|
+
const head = opts?.timedOut ? "Gauntlet stopped: wall clock." : opts?.cancelled ? "Gauntlet cancelled." : "Gauntlet finished.";
|
|
50476
|
+
const lines = [head, ""];
|
|
50477
|
+
for (const r of results) {
|
|
50478
|
+
const gap = r.gap ? ` \u2014 ${r.gap}` : "";
|
|
50479
|
+
const win = r.winner ? ` [A/B ${r.winner}]` : "";
|
|
50480
|
+
lines.push(`- ${r.label} (${r.id}): ${r.verdict} after ${r.rounds} round(s)${win}${gap}`);
|
|
50481
|
+
}
|
|
50482
|
+
return lines.join("\n");
|
|
50483
|
+
}
|
|
50484
|
+
var init_events3 = __esm({
|
|
50485
|
+
"src/cli/gauntlet/events.ts"() {
|
|
50486
|
+
"use strict";
|
|
50487
|
+
}
|
|
50488
|
+
});
|
|
50489
|
+
|
|
50490
|
+
// src/cli/gauntlet/blind.ts
|
|
50491
|
+
function assignBlindLabels(items, rand = Math.random) {
|
|
50492
|
+
if (rand() < 0.5) {
|
|
50493
|
+
return { A: items[0], B: items[1], firstLabel: "A" };
|
|
50494
|
+
}
|
|
50495
|
+
return { A: items[1], B: items[0], firstLabel: "B" };
|
|
50496
|
+
}
|
|
50497
|
+
function qualityBarSection(bars, rand = Math.random) {
|
|
50498
|
+
if (!bars || bars.length === 0) return "";
|
|
50499
|
+
if (bars.length === 1) {
|
|
50500
|
+
return [
|
|
50501
|
+
"## Quality bar (blind)",
|
|
50502
|
+
"Inspect this reference on disk. PASS only if the work in Scope meets or beats it.",
|
|
50503
|
+
"Do not assume the new files are better \u2014 compare concretely.",
|
|
50504
|
+
`- ${bars[0]}`
|
|
50505
|
+
].join("\n");
|
|
50506
|
+
}
|
|
50507
|
+
const pair = assignBlindLabels([bars[0], bars[1]], rand);
|
|
50508
|
+
return [
|
|
50509
|
+
"## Blind A/B",
|
|
50510
|
+
"Two unlabeled artifacts on disk. Compare them against the piece acceptance.",
|
|
50511
|
+
'Do not assume which is newer or which you are "supposed" to prefer.',
|
|
50512
|
+
`A: ${pair.A}`,
|
|
50513
|
+
`B: ${pair.B}`,
|
|
50514
|
+
"Also emit: WINNER: A | B | TIE"
|
|
50515
|
+
].join("\n");
|
|
50516
|
+
}
|
|
50517
|
+
function parseBlindWinner(text) {
|
|
50518
|
+
const m = WINNER_RE.exec(text);
|
|
50519
|
+
if (!m) return void 0;
|
|
50520
|
+
const v = m[1].toUpperCase();
|
|
50521
|
+
if (v === "A" || v === "B" || v === "TIE") return v;
|
|
50522
|
+
return void 0;
|
|
50523
|
+
}
|
|
50524
|
+
var WINNER_RE;
|
|
50525
|
+
var init_blind = __esm({
|
|
50526
|
+
"src/cli/gauntlet/blind.ts"() {
|
|
50527
|
+
"use strict";
|
|
50528
|
+
WINNER_RE = /\bWINNER:\s*(A|B|TIE)\b/i;
|
|
50529
|
+
}
|
|
50530
|
+
});
|
|
50531
|
+
|
|
50532
|
+
// src/cli/gauntlet/verdict.ts
|
|
50533
|
+
function parseGauntletVerdict(text, opts = {}) {
|
|
50534
|
+
const evidence = (opts.toolTraceCount ?? 0) > 0;
|
|
50535
|
+
if (opts.builderFailed) {
|
|
50536
|
+
return {
|
|
50537
|
+
kind: "GAP",
|
|
50538
|
+
gap: (opts.builderError ?? "builder failed").trim() || "builder failed",
|
|
50539
|
+
evidence
|
|
50540
|
+
};
|
|
50541
|
+
}
|
|
50542
|
+
const raw = (text ?? "").trim();
|
|
50543
|
+
if (!raw) {
|
|
50544
|
+
return { kind: "BLOCKED", gap: "critic produced no output", evidence };
|
|
50545
|
+
}
|
|
50546
|
+
const explicit = VERDICT_RE.exec(raw);
|
|
50547
|
+
let kind = explicit ? explicit[1].toUpperCase() : void 0;
|
|
50548
|
+
const reports = [...raw.matchAll(REPORT_STATUS_RE)].map((m) => m[1].toLowerCase());
|
|
50549
|
+
const anyFail = reports.includes("fail");
|
|
50550
|
+
const anyUnknown = reports.includes("unknown");
|
|
50551
|
+
const anyPass = reports.includes("pass");
|
|
50552
|
+
if (!kind) {
|
|
50553
|
+
if (anyFail) kind = "GAP";
|
|
50554
|
+
else if (anyPass && !anyUnknown) kind = "PASS";
|
|
50555
|
+
else if (anyUnknown && !anyPass) kind = "BLOCKED";
|
|
50556
|
+
else kind = "BLOCKED";
|
|
50557
|
+
}
|
|
50558
|
+
const gapMatch = GAP_RE.exec(raw);
|
|
50559
|
+
let gap = gapMatch ? gapMatch[1].trim() : void 0;
|
|
50560
|
+
if (kind === "GAP" && !gap) {
|
|
50561
|
+
gap = anyFail ? "a verify-report check failed" : "critic named a gap without a GAP: line";
|
|
50562
|
+
}
|
|
50563
|
+
if (kind === "PASS" && !evidence) {
|
|
50564
|
+
return {
|
|
50565
|
+
kind: "GAP",
|
|
50566
|
+
gap: "unknown \u2260 pass: critic declared PASS without tool evidence",
|
|
50567
|
+
evidence: false
|
|
50568
|
+
};
|
|
50569
|
+
}
|
|
50570
|
+
if (kind === "PASS" && anyFail) {
|
|
50571
|
+
return {
|
|
50572
|
+
kind: "GAP",
|
|
50573
|
+
gap: gap ?? "verify-report contains a fail",
|
|
50574
|
+
evidence
|
|
50575
|
+
};
|
|
50576
|
+
}
|
|
50577
|
+
return { kind, ...gap ? { gap } : {}, evidence };
|
|
50578
|
+
}
|
|
50579
|
+
var VERDICT_RE, GAP_RE, REPORT_STATUS_RE;
|
|
50580
|
+
var init_verdict2 = __esm({
|
|
50581
|
+
"src/cli/gauntlet/verdict.ts"() {
|
|
50582
|
+
"use strict";
|
|
50583
|
+
VERDICT_RE = /\bVERDICT:\s*(PASS|GAP|BLOCKED)\b/i;
|
|
50584
|
+
GAP_RE = /\bGAP:\s*(.+)/i;
|
|
50585
|
+
REPORT_STATUS_RE = /^status:\s*(pass|fail|unknown)\b/gim;
|
|
50586
|
+
}
|
|
50587
|
+
});
|
|
50588
|
+
|
|
50589
|
+
// src/cli/gauntlet/prompts.ts
|
|
50590
|
+
function builderUserPrompt(piece, gap, briefing) {
|
|
50591
|
+
const parts = [
|
|
50592
|
+
`You are the BUILDER for one Gauntlet piece. Implement it on disk.`,
|
|
50593
|
+
`Do not spawn sub-agents. Stay inside Scope if provided.`
|
|
50594
|
+
];
|
|
50595
|
+
if (briefing?.trim()) {
|
|
50596
|
+
parts.push("", "## Workspace briefing (do not treat as already-done work)", briefing.trim());
|
|
50597
|
+
}
|
|
50598
|
+
parts.push("", `## Piece: ${piece.label}`, piece.prompt.trim());
|
|
50599
|
+
if (piece.scope && piece.scope.length > 0) {
|
|
50600
|
+
parts.push("", "## Scope", ...piece.scope.map((s) => `- ${s}`));
|
|
50601
|
+
}
|
|
50602
|
+
if (piece.acceptance.length > 0) {
|
|
50603
|
+
parts.push("", "## Acceptance", ...piece.acceptance.map((a) => `- ${a}`));
|
|
50604
|
+
}
|
|
50605
|
+
if (gap && gap.trim()) {
|
|
50606
|
+
parts.push(
|
|
50607
|
+
"",
|
|
50608
|
+
"## Previous critic GAP (fix ONLY this)",
|
|
50609
|
+
gap.trim(),
|
|
50610
|
+
"Do not widen scope. Re-check the acceptance after the fix."
|
|
50611
|
+
);
|
|
50612
|
+
}
|
|
50613
|
+
parts.push("", "Return: files touched, what changed, residual risks.");
|
|
50614
|
+
return parts.join("\n");
|
|
50615
|
+
}
|
|
50616
|
+
function criticUserPrompt(piece, round, rand) {
|
|
50617
|
+
const parts = [
|
|
50618
|
+
`Round ${round}. Inspect the current tree against this piece.`,
|
|
50619
|
+
"Do not edit files. Do not take the builder's word \u2014 open files / run checks.",
|
|
50620
|
+
"",
|
|
50621
|
+
`## Piece: ${piece.label}`,
|
|
50622
|
+
piece.prompt.trim()
|
|
50623
|
+
];
|
|
50624
|
+
if (piece.scope && piece.scope.length > 0) {
|
|
50625
|
+
parts.push("", "## Scope", ...piece.scope.map((s) => `- ${s}`));
|
|
50626
|
+
}
|
|
50627
|
+
if (piece.acceptance.length > 0) {
|
|
50628
|
+
parts.push("", "## Acceptance (check each)", ...piece.acceptance.map((a) => `- ${a}`));
|
|
50629
|
+
} else {
|
|
50630
|
+
parts.push(
|
|
50631
|
+
"",
|
|
50632
|
+
"## Acceptance",
|
|
50633
|
+
"- The piece prompt is satisfied by files on disk.",
|
|
50634
|
+
"- Relevant typecheck/tests pass when the project has them."
|
|
50635
|
+
);
|
|
50636
|
+
}
|
|
50637
|
+
const bar = qualityBarSection(piece.bar, rand);
|
|
50638
|
+
if (bar) parts.push("", bar);
|
|
50639
|
+
return parts.join("\n");
|
|
50640
|
+
}
|
|
50641
|
+
var GAUNTLET_CRITIC_SYSTEM;
|
|
50642
|
+
var init_prompts = __esm({
|
|
50643
|
+
"src/cli/gauntlet/prompts.ts"() {
|
|
50644
|
+
"use strict";
|
|
50645
|
+
init_blind();
|
|
50646
|
+
GAUNTLET_CRITIC_SYSTEM = [
|
|
50647
|
+
"You are a ruthless VERIFY critic in a Gauntlet Loop.",
|
|
50648
|
+
"Inspect the REAL files and commands on disk. Do not trust a builder self-report.",
|
|
50649
|
+
"You have no builder transcript \u2014 only the Goal, Scope, Acceptance, and the tree.",
|
|
50650
|
+
"OBSERVATION INTEGRITY: unknown \u2260 pass. EMPTY/degraded tools are not evidence.",
|
|
50651
|
+
"Name at most ONE biggest remaining gap. Do not write a laundry list.",
|
|
50652
|
+
"You may read files and run test/build commands via bash. Prefer targeted checks.",
|
|
50653
|
+
"",
|
|
50654
|
+
"End with BOTH:",
|
|
50655
|
+
"1. One <verify-report> block per acceptance criterion:",
|
|
50656
|
+
"<verify-report>",
|
|
50657
|
+
"check: <criterion text as given>",
|
|
50658
|
+
"status: pass | fail | unknown",
|
|
50659
|
+
"note: <one line of evidence (command or file + outcome)>",
|
|
50660
|
+
"</verify-report>",
|
|
50661
|
+
"2. A trailer on its own lines:",
|
|
50662
|
+
"VERDICT: PASS | GAP | BLOCKED",
|
|
50663
|
+
"GAP: <single biggest remaining gap; omit on PASS>",
|
|
50664
|
+
"3. If a Blind A/B section is present, also emit WINNER: A | B | TIE"
|
|
50665
|
+
].join("\n");
|
|
50666
|
+
}
|
|
50667
|
+
});
|
|
50668
|
+
|
|
50669
|
+
// src/cli/gauntlet/schedule.ts
|
|
50670
|
+
function piecesCanRunInParallel(a, b) {
|
|
50671
|
+
return disjointScopeSets(a.scope, b.scope);
|
|
50672
|
+
}
|
|
50673
|
+
function scheduleWaves(pieces, maxParallel) {
|
|
50674
|
+
const cap3 = Math.max(1, maxParallel);
|
|
50675
|
+
const remaining = [...pieces];
|
|
50676
|
+
const waves = [];
|
|
50677
|
+
while (remaining.length > 0) {
|
|
50678
|
+
const wave = [];
|
|
50679
|
+
const leftover = [];
|
|
50680
|
+
for (const p3 of remaining) {
|
|
50681
|
+
if (wave.length >= cap3) {
|
|
50682
|
+
leftover.push(p3);
|
|
50683
|
+
continue;
|
|
50684
|
+
}
|
|
50685
|
+
if (wave.length === 0 || wave.every((w) => piecesCanRunInParallel(w, p3))) {
|
|
50686
|
+
wave.push(p3);
|
|
50687
|
+
} else {
|
|
50688
|
+
leftover.push(p3);
|
|
50689
|
+
}
|
|
50690
|
+
}
|
|
50691
|
+
waves.push(wave);
|
|
50692
|
+
remaining.splice(0, remaining.length, ...leftover);
|
|
50693
|
+
}
|
|
50694
|
+
return waves;
|
|
50695
|
+
}
|
|
50696
|
+
var init_schedule = __esm({
|
|
50697
|
+
"src/cli/gauntlet/schedule.ts"() {
|
|
50698
|
+
"use strict";
|
|
50699
|
+
init_dist();
|
|
50700
|
+
}
|
|
50701
|
+
});
|
|
50702
|
+
|
|
50703
|
+
// src/cli/gauntlet/loop.ts
|
|
50704
|
+
async function runGauntletLoop(args) {
|
|
50705
|
+
const { caps, deps } = args;
|
|
50706
|
+
const pieces = args.pieces.slice(0, caps.maxPieces);
|
|
50707
|
+
const started = (deps.now ?? Date.now)();
|
|
50708
|
+
const results = [];
|
|
50709
|
+
const emitProgress = (partial2) => {
|
|
50710
|
+
const progress = {
|
|
50711
|
+
...partial2,
|
|
50712
|
+
elapsedMs: (deps.now ?? Date.now)() - started
|
|
50713
|
+
};
|
|
50714
|
+
deps.emit(gauntletProgressEvent(deps.sessionId, progress));
|
|
50715
|
+
deps.note?.("gauntlet.progress", progress);
|
|
50716
|
+
};
|
|
50717
|
+
const wall = caps.wallClockMs === void 0 ? DEFAULT_WALL_MS : caps.wallClockMs;
|
|
50718
|
+
const expired = () => wall > 0 && (deps.now ?? Date.now)() - started >= wall;
|
|
50719
|
+
const aborted2 = () => Boolean(deps.signal?.aborted);
|
|
50720
|
+
const stop = () => aborted2() || expired();
|
|
50721
|
+
const indexOf = (piece) => pieces.findIndex((p3) => p3.id === piece.id);
|
|
50722
|
+
const runOnePiece = async (piece) => {
|
|
50723
|
+
let last = {
|
|
50724
|
+
kind: "BLOCKED",
|
|
50725
|
+
gap: "no round ran",
|
|
50726
|
+
evidence: false
|
|
50727
|
+
};
|
|
50728
|
+
let gap;
|
|
50729
|
+
let winner;
|
|
50730
|
+
let rounds = 0;
|
|
50731
|
+
const i = Math.max(0, indexOf(piece));
|
|
50732
|
+
for (let round = 1; round <= caps.maxRounds; round++) {
|
|
50733
|
+
if (stop()) break;
|
|
50734
|
+
rounds = round;
|
|
50735
|
+
const phase2 = gap ? "repairing" : "building";
|
|
50736
|
+
emitProgress({
|
|
50737
|
+
phase: phase2,
|
|
50738
|
+
pieceId: piece.id,
|
|
50739
|
+
pieceLabel: piece.label,
|
|
50740
|
+
pieceIndex: i,
|
|
50741
|
+
pieceCount: pieces.length,
|
|
50742
|
+
round,
|
|
50743
|
+
maxRounds: caps.maxRounds
|
|
50744
|
+
});
|
|
50745
|
+
const built = await deps.runBuilder({
|
|
50746
|
+
piece,
|
|
50747
|
+
prompt: builderUserPrompt(piece, gap, deps.briefing),
|
|
50748
|
+
round
|
|
50749
|
+
});
|
|
50750
|
+
if (stop()) break;
|
|
50751
|
+
emitProgress({
|
|
50752
|
+
phase: "critiquing",
|
|
50753
|
+
pieceId: piece.id,
|
|
50754
|
+
pieceLabel: piece.label,
|
|
50755
|
+
pieceIndex: i,
|
|
50756
|
+
pieceCount: pieces.length,
|
|
50757
|
+
round,
|
|
50758
|
+
maxRounds: caps.maxRounds
|
|
50759
|
+
});
|
|
50760
|
+
const criticized = await deps.runCritic({
|
|
50761
|
+
piece,
|
|
50762
|
+
prompt: criticUserPrompt(piece, round),
|
|
50763
|
+
systemPrompt: GAUNTLET_CRITIC_SYSTEM,
|
|
50764
|
+
round
|
|
50765
|
+
});
|
|
50766
|
+
last = parseGauntletVerdict(criticized.result, {
|
|
50767
|
+
toolTraceCount: criticized.toolTraceCount ?? 0,
|
|
50768
|
+
builderFailed: !built.ok,
|
|
50769
|
+
builderError: built.error
|
|
50770
|
+
});
|
|
50771
|
+
winner = parseBlindWinner(criticized.result) ?? winner;
|
|
50772
|
+
emitProgress({
|
|
50773
|
+
phase: last.kind === "PASS" ? "settled" : last.kind === "BLOCKED" ? "blocked" : "repairing",
|
|
50774
|
+
pieceId: piece.id,
|
|
50775
|
+
pieceLabel: piece.label,
|
|
50776
|
+
pieceIndex: i,
|
|
50777
|
+
pieceCount: pieces.length,
|
|
50778
|
+
round,
|
|
50779
|
+
maxRounds: caps.maxRounds,
|
|
50780
|
+
verdict: last.kind,
|
|
50781
|
+
gap: last.gap,
|
|
50782
|
+
winner
|
|
50783
|
+
});
|
|
50784
|
+
if (last.kind === "PASS" || last.kind === "BLOCKED") break;
|
|
50785
|
+
gap = last.gap;
|
|
50786
|
+
}
|
|
50787
|
+
return {
|
|
50788
|
+
id: piece.id,
|
|
50789
|
+
label: piece.label,
|
|
50790
|
+
verdict: last,
|
|
50791
|
+
rounds,
|
|
50792
|
+
...winner ? { winner } : {}
|
|
50793
|
+
};
|
|
50794
|
+
};
|
|
50795
|
+
for (const wave of scheduleWaves(pieces, caps.maxParallel)) {
|
|
50796
|
+
if (stop()) return finish(results, { cancelled: aborted2(), timedOut: expired() });
|
|
50797
|
+
if (wave.length === 1) {
|
|
50798
|
+
results.push(await runOnePiece(wave[0]));
|
|
50799
|
+
} else {
|
|
50800
|
+
const waveResults = await Promise.all(wave.map((p3) => runOnePiece(p3)));
|
|
50801
|
+
results.push(...waveResults);
|
|
50802
|
+
}
|
|
50803
|
+
if (stop()) return finish(results, { cancelled: aborted2(), timedOut: expired() });
|
|
50804
|
+
}
|
|
50805
|
+
return finish(results, { cancelled: aborted2(), timedOut: expired() });
|
|
50806
|
+
}
|
|
50807
|
+
function finish(results, flags) {
|
|
50808
|
+
const cancelled = flags.timedOut ? false : flags.cancelled;
|
|
50809
|
+
const timedOut = flags.timedOut;
|
|
50810
|
+
const settled = !cancelled && !timedOut && results.length > 0 && results.every((r) => r.verdict.kind === "PASS");
|
|
50811
|
+
return {
|
|
50812
|
+
settled,
|
|
50813
|
+
cancelled,
|
|
50814
|
+
timedOut,
|
|
50815
|
+
pieces: results,
|
|
50816
|
+
summary: formatGauntletSummary(
|
|
50817
|
+
results.map((r) => ({
|
|
50818
|
+
id: r.id,
|
|
50819
|
+
label: r.label,
|
|
50820
|
+
verdict: r.verdict.kind,
|
|
50821
|
+
rounds: r.rounds,
|
|
50822
|
+
gap: r.verdict.gap,
|
|
50823
|
+
winner: r.winner
|
|
50824
|
+
})),
|
|
50825
|
+
{ timedOut, cancelled }
|
|
50826
|
+
)
|
|
50827
|
+
};
|
|
50828
|
+
}
|
|
50829
|
+
var init_loop = __esm({
|
|
50830
|
+
"src/cli/gauntlet/loop.ts"() {
|
|
50831
|
+
"use strict";
|
|
50832
|
+
init_blind();
|
|
50833
|
+
init_policy();
|
|
50834
|
+
init_verdict2();
|
|
50835
|
+
init_prompts();
|
|
50836
|
+
init_schedule();
|
|
50837
|
+
init_events3();
|
|
50838
|
+
}
|
|
50839
|
+
});
|
|
50840
|
+
|
|
50841
|
+
// src/cli/gauntlet/run.ts
|
|
50842
|
+
var run_exports = {};
|
|
50843
|
+
__export(run_exports, {
|
|
50844
|
+
runHeadlessGauntlet: () => runHeadlessGauntlet
|
|
50845
|
+
});
|
|
50846
|
+
async function runHeadlessGauntlet(opts, provider, model) {
|
|
50847
|
+
const sessionId2 = opts.resumeSessionId ?? crypto.randomUUID();
|
|
50848
|
+
const spine = await openHeadlessSpine({
|
|
50849
|
+
sessionId: sessionId2,
|
|
50850
|
+
mode: opts.mode,
|
|
50851
|
+
profile: opts.profile,
|
|
50852
|
+
workspace: process.cwd()
|
|
50853
|
+
});
|
|
50854
|
+
emitEvent(sessionStartedEvent(spine));
|
|
50855
|
+
const seeded = await seedHeadlessModelHistory(spine, opts.history);
|
|
50856
|
+
if (opts.task) spine.userMessage(opts.task);
|
|
50857
|
+
spine.note("gauntlet.start", { goal: opts.task.slice(0, 200) });
|
|
50858
|
+
const abort = new AbortController();
|
|
50859
|
+
const onSigint = () => {
|
|
50860
|
+
emitEvent({ type: "log", message: "[gauntlet] SIGINT \u2014 cancelling" });
|
|
50861
|
+
abort.abort();
|
|
50862
|
+
};
|
|
50863
|
+
process.once("SIGINT", onSigint);
|
|
50864
|
+
const wallMs = resolveGauntletCaps().wallClockMs ?? 0;
|
|
50865
|
+
const wallTimer = wallMs > 0 ? setTimeout(() => {
|
|
50866
|
+
emitEvent({ type: "log", message: "[gauntlet] wall clock \u2014 aborting tentacles" });
|
|
50867
|
+
abort.abort();
|
|
50868
|
+
}, wallMs) : void 0;
|
|
50869
|
+
const cwd = process.cwd();
|
|
50870
|
+
const audit = new AuditLogger();
|
|
50871
|
+
const createSubAgentContext = createKrakenSubAgentContextFactory({
|
|
50872
|
+
root: cwd,
|
|
50873
|
+
audit,
|
|
50874
|
+
sessionId: sessionId2,
|
|
50875
|
+
provider,
|
|
50876
|
+
model
|
|
50877
|
+
});
|
|
50878
|
+
const deps = {
|
|
50879
|
+
createSubAgentContext,
|
|
50880
|
+
allowWorktree: false,
|
|
50881
|
+
harnessFactory: (config2) => {
|
|
50882
|
+
const harness = new AgentHarness(config2);
|
|
50883
|
+
return {
|
|
50884
|
+
async *run() {
|
|
50885
|
+
for await (const ev of harness.run()) {
|
|
50886
|
+
if (ev.type === "thinking_delta" || ev.type === "tool_execution_start" || ev.type === "tool_execution_end") {
|
|
50887
|
+
emitEvent(ev);
|
|
50888
|
+
spine.observe(ev);
|
|
50889
|
+
}
|
|
50890
|
+
yield ev;
|
|
50891
|
+
}
|
|
50892
|
+
},
|
|
50893
|
+
cancel: () => harness.cancel()
|
|
50894
|
+
};
|
|
50895
|
+
}
|
|
50896
|
+
};
|
|
50897
|
+
const emit = (event) => {
|
|
50898
|
+
if (opts.output === "json") emitEvent(event);
|
|
50899
|
+
else if (typeof event.message === "string") {
|
|
50900
|
+
process.stderr.write(`${event.message}
|
|
50901
|
+
`);
|
|
50902
|
+
}
|
|
50903
|
+
};
|
|
50904
|
+
emitEvent({ type: "agent_start", model, provider, role: "gauntlet" });
|
|
50905
|
+
emit({ type: "log", message: "[gauntlet] host loop \u2014 builder/critic rounds, parent cannot write" });
|
|
50906
|
+
const caps = resolveGauntletCaps();
|
|
50907
|
+
const workspace = buildWorkspaceSummary(cwd, { maxChars: 2500 });
|
|
50908
|
+
const historyNote = formatHistoryNote(seeded.history);
|
|
50909
|
+
emitEvent(
|
|
50910
|
+
gauntletProgressEvent(sessionId2, {
|
|
50911
|
+
phase: "decomposing",
|
|
50912
|
+
pieceId: "",
|
|
50913
|
+
pieceLabel: "Goal",
|
|
50914
|
+
pieceIndex: 0,
|
|
50915
|
+
pieceCount: 1,
|
|
50916
|
+
round: 0,
|
|
50917
|
+
maxRounds: caps.maxRounds,
|
|
50918
|
+
elapsedMs: 0
|
|
50919
|
+
})
|
|
50920
|
+
);
|
|
50921
|
+
try {
|
|
50922
|
+
const decomposed = await decomposeGoal({
|
|
50923
|
+
goal: opts.task,
|
|
50924
|
+
maxPieces: caps.maxPieces,
|
|
50925
|
+
workspace,
|
|
50926
|
+
historyNote,
|
|
50927
|
+
complete: (req) => gauntletComplete(req, { provider, model, signal: abort.signal })
|
|
50928
|
+
});
|
|
50929
|
+
spine.note("gauntlet.decompose", {
|
|
50930
|
+
source: decomposed.source,
|
|
50931
|
+
count: decomposed.pieces.length,
|
|
50932
|
+
...decomposed.error ? { error: decomposed.error.slice(0, 240) } : {}
|
|
50933
|
+
});
|
|
50934
|
+
emit({
|
|
50935
|
+
type: "log",
|
|
50936
|
+
message: `[gauntlet] ${decomposed.pieces.length} piece(s) from ${decomposed.source}${decomposed.error ? ` (${decomposed.error.slice(0, 80)})` : ""}`
|
|
50937
|
+
});
|
|
50938
|
+
const result = await runGauntletLoop({
|
|
50939
|
+
pieces: decomposed.pieces,
|
|
50940
|
+
caps,
|
|
50941
|
+
deps: {
|
|
50942
|
+
sessionId: sessionId2,
|
|
50943
|
+
signal: abort.signal,
|
|
50944
|
+
emit,
|
|
50945
|
+
briefing: workspace.slice(0, 1200),
|
|
50946
|
+
note: (text, data) => spine.note(text, data),
|
|
50947
|
+
runBuilder: async ({ piece, prompt, round }) => {
|
|
50948
|
+
emit({
|
|
50949
|
+
type: "log",
|
|
50950
|
+
message: `[gauntlet] ${piece.id} round ${round}/${caps.maxRounds} builder`
|
|
50951
|
+
});
|
|
50952
|
+
const tent = await runTentacle({
|
|
50953
|
+
deps,
|
|
50954
|
+
agent: "general",
|
|
50955
|
+
thoroughness: "medium",
|
|
50956
|
+
parentCwd: cwd,
|
|
50957
|
+
sessionId: sessionId2,
|
|
50958
|
+
signal: abort.signal,
|
|
50959
|
+
args: {
|
|
50960
|
+
description: `gauntlet-builder ${piece.id} r${round}`,
|
|
50961
|
+
prompt,
|
|
50962
|
+
...piece.scope ? { scope: piece.scope } : {},
|
|
50963
|
+
...piece.acceptance.length > 0 ? { acceptance: piece.acceptance } : {}
|
|
50964
|
+
}
|
|
50965
|
+
});
|
|
50966
|
+
if (!tent.ok) return { ok: false, result: "", error: tent.error };
|
|
50967
|
+
return {
|
|
50968
|
+
ok: true,
|
|
50969
|
+
result: tent.result,
|
|
50970
|
+
toolTraceCount: tent.toolTrace?.length ?? 0
|
|
50971
|
+
};
|
|
50972
|
+
},
|
|
50973
|
+
runCritic: async ({ piece, prompt, systemPrompt, round }) => {
|
|
50974
|
+
emit({
|
|
50975
|
+
type: "log",
|
|
50976
|
+
message: `[gauntlet] ${piece.id} round ${round}/${caps.maxRounds} critic`
|
|
50977
|
+
});
|
|
50978
|
+
const tent = await runTentacle({
|
|
50979
|
+
deps,
|
|
50980
|
+
agent: "verify",
|
|
50981
|
+
thoroughness: "medium",
|
|
50982
|
+
parentCwd: cwd,
|
|
50983
|
+
sessionId: sessionId2,
|
|
50984
|
+
signal: abort.signal,
|
|
50985
|
+
systemPromptOverride: systemPrompt,
|
|
50986
|
+
args: {
|
|
50987
|
+
description: `gauntlet-critic ${piece.id} r${round}`,
|
|
50988
|
+
prompt,
|
|
50989
|
+
...piece.scope ? { scope: piece.scope } : {},
|
|
50990
|
+
...piece.acceptance.length > 0 ? { acceptance: piece.acceptance } : {}
|
|
50991
|
+
}
|
|
50992
|
+
});
|
|
50993
|
+
if (!tent.ok) {
|
|
50994
|
+
return { ok: false, result: tent.error, error: tent.error, toolTraceCount: 0 };
|
|
50995
|
+
}
|
|
50996
|
+
return {
|
|
50997
|
+
ok: true,
|
|
50998
|
+
result: tent.result,
|
|
50999
|
+
toolTraceCount: tent.toolTrace?.length ?? 0
|
|
51000
|
+
};
|
|
51001
|
+
}
|
|
51002
|
+
}
|
|
51003
|
+
});
|
|
51004
|
+
emitEvent({ type: "message_start", role: "assistant" });
|
|
51005
|
+
emitEvent({ type: "message_delta", delta: result.summary });
|
|
51006
|
+
emitEvent({ type: "message_end", totalLength: result.summary.length });
|
|
51007
|
+
emitEvent({
|
|
51008
|
+
type: "agent_end",
|
|
51009
|
+
reason: result.cancelled || result.timedOut ? "cancelled" : result.settled ? "completed" : "error"
|
|
51010
|
+
});
|
|
51011
|
+
if (result.timedOut) {
|
|
51012
|
+
emit({ type: "log", message: `[gauntlet] wall clock (${Math.round(wallMs / 6e4)}m)` });
|
|
51013
|
+
await spine.interrupt("gauntlet-wall-clock");
|
|
51014
|
+
return 1;
|
|
51015
|
+
}
|
|
51016
|
+
if (result.cancelled) {
|
|
51017
|
+
await spine.interrupt("gauntlet-cancelled");
|
|
51018
|
+
return 1;
|
|
51019
|
+
}
|
|
51020
|
+
await spine.close(result.settled ? "gauntlet-pass" : "gauntlet-incomplete");
|
|
51021
|
+
return result.settled ? 0 : 3;
|
|
51022
|
+
} catch (err) {
|
|
51023
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
51024
|
+
emitEvent({ type: "error", severity: "fatal", message: msg, code: "gauntlet" });
|
|
51025
|
+
await spine.interrupt(`gauntlet-error: ${msg}`).catch(() => void 0);
|
|
51026
|
+
return 2;
|
|
51027
|
+
} finally {
|
|
51028
|
+
if (wallTimer) clearTimeout(wallTimer);
|
|
51029
|
+
process.removeListener("SIGINT", onSigint);
|
|
51030
|
+
}
|
|
51031
|
+
}
|
|
51032
|
+
var init_run = __esm({
|
|
51033
|
+
"src/cli/gauntlet/run.ts"() {
|
|
51034
|
+
"use strict";
|
|
51035
|
+
init_harness();
|
|
51036
|
+
init_headless();
|
|
51037
|
+
init_headlessSpine();
|
|
51038
|
+
init_auditLogger();
|
|
51039
|
+
init_toolRegistry();
|
|
51040
|
+
init_taskTool();
|
|
51041
|
+
init_complete();
|
|
51042
|
+
init_decompose();
|
|
51043
|
+
init_events3();
|
|
51044
|
+
init_loop();
|
|
51045
|
+
init_policy();
|
|
51046
|
+
init_workspaceSummary();
|
|
51047
|
+
}
|
|
51048
|
+
});
|
|
51049
|
+
|
|
49832
51050
|
// src/cli/triggerLock.ts
|
|
49833
51051
|
var triggerLock_exports = {};
|
|
49834
51052
|
__export(triggerLock_exports, {
|
|
@@ -50603,7 +51821,7 @@ function startPermissionMcpServer(opts) {
|
|
|
50603
51821
|
}
|
|
50604
51822
|
return { error: { code: -32601, message: `method not found: ${method}` } };
|
|
50605
51823
|
}
|
|
50606
|
-
async function callApprove(args,
|
|
51824
|
+
async function callApprove(args, timeoutMs2) {
|
|
50607
51825
|
const toolName = typeof args.tool_name === "string" ? args.tool_name : "";
|
|
50608
51826
|
if (!toolName) {
|
|
50609
51827
|
return { error: { code: -32602, message: "approve requires a string tool_name" } };
|
|
@@ -50622,7 +51840,7 @@ function startPermissionMcpServer(opts) {
|
|
|
50622
51840
|
toolUseId: typeof args.tool_use_id === "string" ? args.tool_use_id : void 0,
|
|
50623
51841
|
suggestions
|
|
50624
51842
|
},
|
|
50625
|
-
{ requestTimeoutMs:
|
|
51843
|
+
{ requestTimeoutMs: timeoutMs2 }
|
|
50626
51844
|
);
|
|
50627
51845
|
const result = res.behavior === "allow" ? {
|
|
50628
51846
|
behavior: "allow",
|
|
@@ -50642,7 +51860,7 @@ function startPermissionMcpServer(opts) {
|
|
|
50642
51860
|
);
|
|
50643
51861
|
}
|
|
50644
51862
|
}
|
|
50645
|
-
async function callAskUser(args,
|
|
51863
|
+
async function callAskUser(args, timeoutMs2) {
|
|
50646
51864
|
const question = typeof args.question === "string" ? args.question : "";
|
|
50647
51865
|
if (!question) {
|
|
50648
51866
|
return { error: { code: -32602, message: "ask_user requires a string question" } };
|
|
@@ -50660,7 +51878,7 @@ function startPermissionMcpServer(opts) {
|
|
|
50660
51878
|
choices,
|
|
50661
51879
|
context
|
|
50662
51880
|
},
|
|
50663
|
-
{ requestTimeoutMs:
|
|
51881
|
+
{ requestTimeoutMs: timeoutMs2 }
|
|
50664
51882
|
);
|
|
50665
51883
|
const text = res.behavior === "allow" && typeof res.answer === "string" ? res.answer : res.message ?? "No answer was given \u2014 use your best judgment.";
|
|
50666
51884
|
return textResult(text);
|
|
@@ -55508,8 +56726,8 @@ async function readPackageScripts(cwd = process.cwd()) {
|
|
|
55508
56726
|
return {};
|
|
55509
56727
|
}
|
|
55510
56728
|
}
|
|
55511
|
-
function buildNativeCriteria(commands,
|
|
55512
|
-
const pack = codingCriteriaPack({ ...commands, commandTimeoutMs:
|
|
56729
|
+
function buildNativeCriteria(commands, timeoutMs2) {
|
|
56730
|
+
const pack = codingCriteriaPack({ ...commands, commandTimeoutMs: timeoutMs2 });
|
|
55513
56731
|
return pack.criteria.filter(
|
|
55514
56732
|
(c) => !(c.required && (!c.check || c.check.kind === "none"))
|
|
55515
56733
|
);
|
|
@@ -55543,11 +56761,11 @@ function criterionId(check2, index) {
|
|
|
55543
56761
|
const slug = check2.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 48);
|
|
55544
56762
|
return `check-${index + 1}-${slug || "criterion"}`;
|
|
55545
56763
|
}
|
|
55546
|
-
function
|
|
56764
|
+
function normalize5(text) {
|
|
55547
56765
|
return text.toLowerCase().replace(/\s+/g, " ").trim();
|
|
55548
56766
|
}
|
|
55549
56767
|
function matchResult(check2, byNormalized) {
|
|
55550
|
-
const norm =
|
|
56768
|
+
const norm = normalize5(check2);
|
|
55551
56769
|
const direct = byNormalized.get(norm);
|
|
55552
56770
|
if (direct) return direct;
|
|
55553
56771
|
for (const key of byNormalized.keys()) {
|
|
@@ -55559,7 +56777,7 @@ function matchResult(check2, byNormalized) {
|
|
|
55559
56777
|
}
|
|
55560
56778
|
function krakenResultsToContract(requiredChecks, results, now = Date.now()) {
|
|
55561
56779
|
const byNormalized = /* @__PURE__ */ new Map();
|
|
55562
|
-
for (const r of results ?? []) byNormalized.set(
|
|
56780
|
+
for (const r of results ?? []) byNormalized.set(normalize5(r.check), r);
|
|
55563
56781
|
const criteria = [];
|
|
55564
56782
|
const verifications = [];
|
|
55565
56783
|
requiredChecks.forEach((check2, i) => {
|
|
@@ -55595,16 +56813,16 @@ function sha256Hex2(input) {
|
|
|
55595
56813
|
return createHash10("sha256").update(input).digest("hex");
|
|
55596
56814
|
}
|
|
55597
56815
|
function matchNoteToToolTrace(note, trace) {
|
|
55598
|
-
const n =
|
|
56816
|
+
const n = normalize5(note);
|
|
55599
56817
|
if (!n) return null;
|
|
55600
56818
|
for (let i = trace.length - 1; i >= 0; i--) {
|
|
55601
56819
|
const t = trace[i];
|
|
55602
|
-
const cmd = t.command ?
|
|
56820
|
+
const cmd = t.command ? normalize5(t.command) : "";
|
|
55603
56821
|
if (cmd.length >= 4 && (n.includes(cmd) || cmd.includes(n))) return t;
|
|
55604
56822
|
}
|
|
55605
56823
|
for (let i = trace.length - 1; i >= 0; i--) {
|
|
55606
56824
|
const t = trace[i];
|
|
55607
|
-
const out =
|
|
56825
|
+
const out = normalize5(t.output);
|
|
55608
56826
|
if (!out) continue;
|
|
55609
56827
|
if (n.length >= 8 && out.includes(n)) return t;
|
|
55610
56828
|
const fragments = n.match(/\S*\d[\d.,/%]*\S*/g) ?? [];
|
|
@@ -55811,7 +57029,7 @@ ${detail}
|
|
|
55811
57029
|
let settled = false;
|
|
55812
57030
|
const askTimeoutMs = askUserTimeoutMs();
|
|
55813
57031
|
let cancelAskTimeout = () => void 0;
|
|
55814
|
-
const
|
|
57032
|
+
const finish2 = (ok, note) => {
|
|
55815
57033
|
if (settled) return;
|
|
55816
57034
|
settled = true;
|
|
55817
57035
|
cancelAskTimeout();
|
|
@@ -55820,7 +57038,7 @@ ${detail}
|
|
|
55820
57038
|
resolve3(ok);
|
|
55821
57039
|
};
|
|
55822
57040
|
cancelAskTimeout = armPickerTimeout(
|
|
55823
|
-
() =>
|
|
57041
|
+
() => finish2(
|
|
55824
57042
|
false,
|
|
55825
57043
|
`[permission] ask for "${req.toolName}" timed out after ${Math.round(
|
|
55826
57044
|
askTimeoutMs / 1e3
|
|
@@ -55849,12 +57067,12 @@ ${detail}
|
|
|
55849
57067
|
onAnswer: (value) => {
|
|
55850
57068
|
const v = value.trim().toLowerCase();
|
|
55851
57069
|
if (v === "deny" || v.startsWith("deny")) {
|
|
55852
|
-
|
|
57070
|
+
finish2(false);
|
|
55853
57071
|
return;
|
|
55854
57072
|
}
|
|
55855
57073
|
if (v === "always-tool" || v.includes("always") && v.includes("tool")) {
|
|
55856
57074
|
grantSessionTool(req.toolName);
|
|
55857
|
-
|
|
57075
|
+
finish2(
|
|
55858
57076
|
true,
|
|
55859
57077
|
`[permission] Granted "${req.toolName}" for this session (tool).`
|
|
55860
57078
|
);
|
|
@@ -55863,19 +57081,19 @@ ${detail}
|
|
|
55863
57081
|
if (v === "always-cat" || v.includes("always") && !v.includes("tool")) {
|
|
55864
57082
|
for (const c of cats) grantSessionCategory(c);
|
|
55865
57083
|
grantSessionTool(req.toolName);
|
|
55866
|
-
|
|
57084
|
+
finish2(
|
|
55867
57085
|
true,
|
|
55868
57086
|
`[permission] Granted ${catLabel} (+ ${req.toolName}) for this session.`
|
|
55869
57087
|
);
|
|
55870
57088
|
return;
|
|
55871
57089
|
}
|
|
55872
57090
|
if (v === "allow" || v.startsWith("allow") || v === "yes" || v === "y" || v === "1") {
|
|
55873
|
-
|
|
57091
|
+
finish2(true);
|
|
55874
57092
|
return;
|
|
55875
57093
|
}
|
|
55876
|
-
|
|
57094
|
+
finish2(false);
|
|
55877
57095
|
},
|
|
55878
|
-
onCancel: () =>
|
|
57096
|
+
onCancel: () => finish2(false)
|
|
55879
57097
|
});
|
|
55880
57098
|
});
|
|
55881
57099
|
}
|
|
@@ -56194,7 +57412,7 @@ _(${req.context})_` : "") + "\n\u2192 scegli dalla lista (il turno continua dopo
|
|
|
56194
57412
|
let settled = false;
|
|
56195
57413
|
const askTimeoutMs = askUserTimeoutMs();
|
|
56196
57414
|
let cancelAskTimeout = () => void 0;
|
|
56197
|
-
const
|
|
57415
|
+
const finish2 = (value) => {
|
|
56198
57416
|
if (settled) return;
|
|
56199
57417
|
settled = true;
|
|
56200
57418
|
cancelAskTimeout();
|
|
@@ -56210,7 +57428,7 @@ _(${req.context})_` : "") + "\n\u2192 scegli dalla lista (il turno continua dopo
|
|
|
56210
57428
|
)}s \u2014 proseguo con assunzione documentata (ZELARI_ASK_USER_TIMEOUT_MS).`,
|
|
56211
57429
|
Date.now()
|
|
56212
57430
|
);
|
|
56213
|
-
|
|
57431
|
+
finish2(null);
|
|
56214
57432
|
},
|
|
56215
57433
|
askTimeoutMs
|
|
56216
57434
|
);
|
|
@@ -56218,8 +57436,8 @@ _(${req.context})_` : "") + "\n\u2192 scegli dalla lista (il turno continua dopo
|
|
|
56218
57436
|
kind: "clarification",
|
|
56219
57437
|
title: req.question,
|
|
56220
57438
|
items: choices.map((c) => ({ value: c, label: c })),
|
|
56221
|
-
onAnswer: (value) =>
|
|
56222
|
-
onCancel: () =>
|
|
57439
|
+
onAnswer: (value) => finish2(value),
|
|
57440
|
+
onCancel: () => finish2(null)
|
|
56223
57441
|
});
|
|
56224
57442
|
}) : void 0;
|
|
56225
57443
|
const onPermissionAsk = setPicker2 ? createPermissionAskHandler({
|
|
@@ -57008,7 +58226,7 @@ _(${req.context})_` : "") + "\n\u2192 scegli dalla lista (il membro riprende dop
|
|
|
57008
58226
|
let settled = false;
|
|
57009
58227
|
const askTimeoutMs = askUserTimeoutMs();
|
|
57010
58228
|
let cancelAskTimeout = () => void 0;
|
|
57011
|
-
const
|
|
58229
|
+
const finish2 = (value) => {
|
|
57012
58230
|
if (settled) return;
|
|
57013
58231
|
settled = true;
|
|
57014
58232
|
cancelAskTimeout();
|
|
@@ -57024,7 +58242,7 @@ _(${req.context})_` : "") + "\n\u2192 scegli dalla lista (il membro riprende dop
|
|
|
57024
58242
|
)}s \u2014 il membro prosegue con assunzione documentata (ZELARI_ASK_USER_TIMEOUT_MS).`,
|
|
57025
58243
|
Date.now()
|
|
57026
58244
|
);
|
|
57027
|
-
|
|
58245
|
+
finish2(null);
|
|
57028
58246
|
},
|
|
57029
58247
|
askTimeoutMs
|
|
57030
58248
|
);
|
|
@@ -57032,8 +58250,8 @@ _(${req.context})_` : "") + "\n\u2192 scegli dalla lista (il membro riprende dop
|
|
|
57032
58250
|
kind: "clarification",
|
|
57033
58251
|
title: req.question,
|
|
57034
58252
|
items: choices.map((c) => ({ value: c, label: c })),
|
|
57035
|
-
onAnswer: (value) =>
|
|
57036
|
-
onCancel: () =>
|
|
58253
|
+
onAnswer: (value) => finish2(value),
|
|
58254
|
+
onCancel: () => finish2(null)
|
|
57037
58255
|
});
|
|
57038
58256
|
}) : void 0;
|
|
57039
58257
|
let phaseRunMode = overrides.runMode ?? (workPhase === "plan" ? "design-phase" : "implementation");
|
|
@@ -57177,7 +58395,7 @@ _(${req.context})_` : "") + "\n\u2192 scegli dalla lista (il membro riprende dop
|
|
|
57177
58395
|
Date.now()
|
|
57178
58396
|
);
|
|
57179
58397
|
let settled = false;
|
|
57180
|
-
const
|
|
58398
|
+
const finish2 = (value) => {
|
|
57181
58399
|
if (settled) return;
|
|
57182
58400
|
settled = true;
|
|
57183
58401
|
setPicker2(null);
|
|
@@ -57187,8 +58405,8 @@ _(${req.context})_` : "") + "\n\u2192 scegli dalla lista (il membro riprende dop
|
|
|
57187
58405
|
kind: "clarification",
|
|
57188
58406
|
title: req.question,
|
|
57189
58407
|
items: choices.map((c) => ({ value: c, label: c })),
|
|
57190
|
-
onAnswer: (value) =>
|
|
57191
|
-
onCancel: () =>
|
|
58408
|
+
onAnswer: (value) => finish2(value),
|
|
58409
|
+
onCancel: () => finish2(null)
|
|
57192
58410
|
});
|
|
57193
58411
|
}) : void 0
|
|
57194
58412
|
})) {
|
|
@@ -57793,7 +59011,7 @@ function usePermissionBroker(opts) {
|
|
|
57793
59011
|
}
|
|
57794
59012
|
let settled = false;
|
|
57795
59013
|
let cancelWaitTimeout;
|
|
57796
|
-
const
|
|
59014
|
+
const finish2 = (value) => {
|
|
57797
59015
|
if (settled) return;
|
|
57798
59016
|
settled = true;
|
|
57799
59017
|
cancelWaitTimeout?.();
|
|
@@ -57809,7 +59027,7 @@ function usePermissionBroker(opts) {
|
|
|
57809
59027
|
)}s \u2014 richiesta annullata.`,
|
|
57810
59028
|
Date.now()
|
|
57811
59029
|
);
|
|
57812
|
-
|
|
59030
|
+
finish2(null);
|
|
57813
59031
|
}, waitTimeoutMs);
|
|
57814
59032
|
appendSystem(
|
|
57815
59033
|
setMessages,
|
|
@@ -57821,8 +59039,8 @@ function usePermissionBroker(opts) {
|
|
|
57821
59039
|
kind: "clarification",
|
|
57822
59040
|
title: req.question,
|
|
57823
59041
|
items: choices.map((c) => ({ value: c, label: c })),
|
|
57824
|
-
onAnswer: (value) =>
|
|
57825
|
-
onCancel: () =>
|
|
59042
|
+
onAnswer: (value) => finish2(value),
|
|
59043
|
+
onCancel: () => finish2(null)
|
|
57826
59044
|
});
|
|
57827
59045
|
});
|
|
57828
59046
|
void startPermissionBroker(socketPath, {
|
|
@@ -61927,7 +63145,7 @@ function verifierReviewEnabled(selection = loadVerifierModelSelection(), env = p
|
|
|
61927
63145
|
if (v === "1" || v === "true" || v === "on") return true;
|
|
61928
63146
|
return selection.mode === "fixed";
|
|
61929
63147
|
}
|
|
61930
|
-
function makeVerifierCallModel(loadStream, identity,
|
|
63148
|
+
function makeVerifierCallModel(loadStream, identity, timeoutMs2 = 12e4) {
|
|
61931
63149
|
return async ({ system, user }) => {
|
|
61932
63150
|
const stream = await loadStream(identity.provider, identity.model);
|
|
61933
63151
|
if (!stream) {
|
|
@@ -61941,7 +63159,7 @@ function makeVerifierCallModel(loadStream, identity, timeoutMs = 12e4) {
|
|
|
61941
63159
|
model: identity.model,
|
|
61942
63160
|
provider: identity.provider,
|
|
61943
63161
|
tools: [],
|
|
61944
|
-
signal: AbortSignal.timeout(
|
|
63162
|
+
signal: AbortSignal.timeout(timeoutMs2)
|
|
61945
63163
|
});
|
|
61946
63164
|
return { text, provider: identity.provider, model: identity.model };
|
|
61947
63165
|
};
|
|
@@ -62098,6 +63316,18 @@ ${err.stack}` : "";
|
|
|
62098
63316
|
if (opts.krakenGraph) {
|
|
62099
63317
|
return runHeadlessKrakenGraph(opts, provider, model);
|
|
62100
63318
|
}
|
|
63319
|
+
const { shouldRunGauntletHostLoop: shouldRunGauntletHostLoop2 } = await Promise.resolve().then(() => (init_policy(), policy_exports));
|
|
63320
|
+
if (shouldRunGauntletHostLoop2(opts)) {
|
|
63321
|
+
const { runHeadlessGauntlet: runHeadlessGauntlet2 } = await Promise.resolve().then(() => (init_run(), run_exports));
|
|
63322
|
+
return runHeadlessGauntlet2(opts, provider, model);
|
|
63323
|
+
}
|
|
63324
|
+
if (opts.gauntlet) {
|
|
63325
|
+
const why = opts.krakenGraph ? "kraken-graph owns dispatch" : (opts.phase ?? "build") === "plan" ? "PLAN is already write-stripped; host loop is BUILD-only" : "mode is not kraken-build";
|
|
63326
|
+
const line = `[gauntlet] flag set but host loop skipped (${why})`;
|
|
63327
|
+
if (opts.output === "json") emitEvent({ type: "log", message: line });
|
|
63328
|
+
else process.stderr.write(`[zelari-code --headless] ${line}
|
|
63329
|
+
`);
|
|
63330
|
+
}
|
|
62101
63331
|
if (mode === "zelari") {
|
|
62102
63332
|
return runHeadlessZelari(opts, provider, model, providerStream);
|
|
62103
63333
|
}
|
|
@@ -62314,6 +63544,7 @@ async function runHeadlessSingle(opts, provider, model, providerStream) {
|
|
|
62314
63544
|
resetKrakenTurnMetrics();
|
|
62315
63545
|
const { registry: toolRegistry } = createBuiltinToolRegistry({
|
|
62316
63546
|
planMode: planModeFromOpts(opts),
|
|
63547
|
+
gauntletParent: Boolean(opts.gauntlet) && !planModeFromOpts(opts),
|
|
62317
63548
|
// Fase 1 (ADR-0020): anchor tentacles to the provider/model THIS run
|
|
62318
63549
|
// resolved (--provider/--model opts or Desktop's selector), mirroring
|
|
62319
63550
|
// what the kraken-graph path already does for its executor.
|