zelari-code 2.11.2 → 2.13.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/headless.js +16 -5
- package/dist/cli/headless.js.map +1 -1
- package/dist/cli/hooks/useChatTurn.js +17 -4
- package/dist/cli/hooks/useChatTurn.js.map +1 -1
- package/dist/cli/kraken/completionProof.js +176 -0
- package/dist/cli/kraken/completionProof.js.map +1 -0
- package/dist/cli/kraken/nativeVerification.js +12 -5
- package/dist/cli/kraken/nativeVerification.js.map +1 -1
- package/dist/cli/kraken/verificationBridge.js +5 -1
- package/dist/cli/kraken/verificationBridge.js.map +1 -1
- package/dist/cli/kraken/verifierLifecycle.js +72 -8
- package/dist/cli/kraken/verifierLifecycle.js.map +1 -1
- package/dist/cli/main.bundled.js +1141 -433
- package/dist/cli/main.bundled.js.map +4 -4
- package/dist/cli/orchestration/policy.js +88 -0
- package/dist/cli/orchestration/policy.js.map +1 -0
- package/dist/cli/runHeadless.js +49 -0
- package/dist/cli/runHeadless.js.map +1 -1
- package/dist/cli/safety/policyEngine.js +315 -0
- package/dist/cli/safety/policyEngine.js.map +1 -0
- package/dist/cli/safety/policyLayers.js +55 -0
- package/dist/cli/safety/policyLayers.js.map +1 -0
- package/dist/cli/safety/toolPermissions.js +38 -0
- package/dist/cli/safety/toolPermissions.js.map +1 -1
- package/dist/cli/toolRegistry.js +49 -9
- package/dist/cli/toolRegistry.js.map +1 -1
- package/dist/cli/tools/krakenCsvFanout.js +4 -4
- package/dist/cli/tools/krakenCsvFanout.js.map +1 -1
- package/dist/cli/tools/krakenModel.js +75 -0
- package/dist/cli/tools/krakenModel.js.map +1 -1
- package/dist/cli/tools/taskTool.js +4 -3
- package/dist/cli/tools/taskTool.js.map +1 -1
- package/package.json +2 -2
package/dist/cli/main.bundled.js
CHANGED
|
@@ -3288,10 +3288,10 @@ function mergeDefs(...defs) {
|
|
|
3288
3288
|
function cloneDef(schema) {
|
|
3289
3289
|
return mergeDefs(schema._zod.def);
|
|
3290
3290
|
}
|
|
3291
|
-
function getElementAtPath(obj,
|
|
3292
|
-
if (!
|
|
3291
|
+
function getElementAtPath(obj, path74) {
|
|
3292
|
+
if (!path74)
|
|
3293
3293
|
return obj;
|
|
3294
|
-
return
|
|
3294
|
+
return path74.reduce((acc, key) => acc?.[key], obj);
|
|
3295
3295
|
}
|
|
3296
3296
|
function promiseAllObject(promisesObj) {
|
|
3297
3297
|
const keys = Object.keys(promisesObj);
|
|
@@ -3619,11 +3619,11 @@ function explicitlyAborted(x, startIndex = 0) {
|
|
|
3619
3619
|
}
|
|
3620
3620
|
return false;
|
|
3621
3621
|
}
|
|
3622
|
-
function prefixIssues(
|
|
3622
|
+
function prefixIssues(path74, issues) {
|
|
3623
3623
|
return issues.map((iss) => {
|
|
3624
3624
|
var _a3;
|
|
3625
3625
|
(_a3 = iss).path ?? (_a3.path = []);
|
|
3626
|
-
iss.path.unshift(
|
|
3626
|
+
iss.path.unshift(path74);
|
|
3627
3627
|
return iss;
|
|
3628
3628
|
});
|
|
3629
3629
|
}
|
|
@@ -3841,16 +3841,16 @@ function flattenError(error51, mapper = (issue2) => issue2.message) {
|
|
|
3841
3841
|
}
|
|
3842
3842
|
function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
3843
3843
|
const fieldErrors = { _errors: [] };
|
|
3844
|
-
const processError = (error52,
|
|
3844
|
+
const processError = (error52, path74 = []) => {
|
|
3845
3845
|
for (const issue2 of error52.issues) {
|
|
3846
3846
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
3847
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
3847
|
+
issue2.errors.map((issues) => processError({ issues }, [...path74, ...issue2.path]));
|
|
3848
3848
|
} else if (issue2.code === "invalid_key") {
|
|
3849
|
-
processError({ issues: issue2.issues }, [...
|
|
3849
|
+
processError({ issues: issue2.issues }, [...path74, ...issue2.path]);
|
|
3850
3850
|
} else if (issue2.code === "invalid_element") {
|
|
3851
|
-
processError({ issues: issue2.issues }, [...
|
|
3851
|
+
processError({ issues: issue2.issues }, [...path74, ...issue2.path]);
|
|
3852
3852
|
} else {
|
|
3853
|
-
const fullpath = [...
|
|
3853
|
+
const fullpath = [...path74, ...issue2.path];
|
|
3854
3854
|
if (fullpath.length === 0) {
|
|
3855
3855
|
fieldErrors._errors.push(mapper(issue2));
|
|
3856
3856
|
} else {
|
|
@@ -3877,17 +3877,17 @@ function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
|
3877
3877
|
}
|
|
3878
3878
|
function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
3879
3879
|
const result = { errors: [] };
|
|
3880
|
-
const processError = (error52,
|
|
3880
|
+
const processError = (error52, path74 = []) => {
|
|
3881
3881
|
var _a3, _b;
|
|
3882
3882
|
for (const issue2 of error52.issues) {
|
|
3883
3883
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
3884
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
3884
|
+
issue2.errors.map((issues) => processError({ issues }, [...path74, ...issue2.path]));
|
|
3885
3885
|
} else if (issue2.code === "invalid_key") {
|
|
3886
|
-
processError({ issues: issue2.issues }, [...
|
|
3886
|
+
processError({ issues: issue2.issues }, [...path74, ...issue2.path]);
|
|
3887
3887
|
} else if (issue2.code === "invalid_element") {
|
|
3888
|
-
processError({ issues: issue2.issues }, [...
|
|
3888
|
+
processError({ issues: issue2.issues }, [...path74, ...issue2.path]);
|
|
3889
3889
|
} else {
|
|
3890
|
-
const fullpath = [...
|
|
3890
|
+
const fullpath = [...path74, ...issue2.path];
|
|
3891
3891
|
if (fullpath.length === 0) {
|
|
3892
3892
|
result.errors.push(mapper(issue2));
|
|
3893
3893
|
continue;
|
|
@@ -3919,8 +3919,8 @@ function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
|
3919
3919
|
}
|
|
3920
3920
|
function toDotPath(_path) {
|
|
3921
3921
|
const segs = [];
|
|
3922
|
-
const
|
|
3923
|
-
for (const seg of
|
|
3922
|
+
const path74 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
3923
|
+
for (const seg of path74) {
|
|
3924
3924
|
if (typeof seg === "number")
|
|
3925
3925
|
segs.push(`[${seg}]`);
|
|
3926
3926
|
else if (typeof seg === "symbol")
|
|
@@ -17423,13 +17423,13 @@ function resolveRef(ref, ctx) {
|
|
|
17423
17423
|
if (!ref.startsWith("#")) {
|
|
17424
17424
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
17425
17425
|
}
|
|
17426
|
-
const
|
|
17427
|
-
if (
|
|
17426
|
+
const path74 = ref.slice(1).split("/").filter(Boolean);
|
|
17427
|
+
if (path74.length === 0) {
|
|
17428
17428
|
return ctx.rootSchema;
|
|
17429
17429
|
}
|
|
17430
17430
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
17431
|
-
if (
|
|
17432
|
-
const key =
|
|
17431
|
+
if (path74[0] === defsKey) {
|
|
17432
|
+
const key = path74[1];
|
|
17433
17433
|
if (!key || !ctx.defs[key]) {
|
|
17434
17434
|
throw new Error(`Reference not found: ${ref}`);
|
|
17435
17435
|
}
|
|
@@ -18235,15 +18235,66 @@ var init_toolTypes = __esm({
|
|
|
18235
18235
|
}
|
|
18236
18236
|
});
|
|
18237
18237
|
|
|
18238
|
+
// packages/core/dist/core/tools/builtin/newlines.js
|
|
18239
|
+
function detectNewline(text) {
|
|
18240
|
+
if (text.includes("\r\n"))
|
|
18241
|
+
return "\r\n";
|
|
18242
|
+
if (text.includes("\r"))
|
|
18243
|
+
return "\r";
|
|
18244
|
+
return "\n";
|
|
18245
|
+
}
|
|
18246
|
+
function toLF(text) {
|
|
18247
|
+
return text.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
18248
|
+
}
|
|
18249
|
+
function fromLF(text, nl) {
|
|
18250
|
+
if (nl === "\n")
|
|
18251
|
+
return text;
|
|
18252
|
+
return text.replace(/\n/g, nl);
|
|
18253
|
+
}
|
|
18254
|
+
function splitLinesLF(text) {
|
|
18255
|
+
return toLF(text).split("\n");
|
|
18256
|
+
}
|
|
18257
|
+
var init_newlines = __esm({
|
|
18258
|
+
"packages/core/dist/core/tools/builtin/newlines.js"() {
|
|
18259
|
+
"use strict";
|
|
18260
|
+
}
|
|
18261
|
+
});
|
|
18262
|
+
|
|
18238
18263
|
// packages/core/dist/core/tools/builtin/filesystem.js
|
|
18239
18264
|
import { promises as fs4 } from "node:fs";
|
|
18240
18265
|
import path6 from "node:path";
|
|
18266
|
+
function replaceFileString(text, oldString, newString, replaceAll) {
|
|
18267
|
+
const exact = replaceOnceOrAll(text, oldString, newString, replaceAll);
|
|
18268
|
+
if (exact.occurrences > 0)
|
|
18269
|
+
return exact;
|
|
18270
|
+
const nl = detectNewline(text);
|
|
18271
|
+
const normalized = replaceOnceOrAll(toLF(text), toLF(oldString), toLF(newString), replaceAll);
|
|
18272
|
+
if (normalized.occurrences === 0)
|
|
18273
|
+
return normalized;
|
|
18274
|
+
return { occurrences: normalized.occurrences, newContent: fromLF(normalized.newContent, nl) };
|
|
18275
|
+
}
|
|
18276
|
+
function replaceOnceOrAll(text, oldString, newString, replaceAll) {
|
|
18277
|
+
if (replaceAll) {
|
|
18278
|
+
if (!text.includes(oldString))
|
|
18279
|
+
return { occurrences: 0, newContent: text };
|
|
18280
|
+
const parts = text.split(oldString);
|
|
18281
|
+
return { occurrences: parts.length - 1, newContent: parts.join(newString) };
|
|
18282
|
+
}
|
|
18283
|
+
const idx = text.indexOf(oldString);
|
|
18284
|
+
if (idx === -1)
|
|
18285
|
+
return { occurrences: 0, newContent: text };
|
|
18286
|
+
return {
|
|
18287
|
+
occurrences: 1,
|
|
18288
|
+
newContent: text.slice(0, idx) + newString + text.slice(idx + oldString.length)
|
|
18289
|
+
};
|
|
18290
|
+
}
|
|
18241
18291
|
var ReadFileArgsSchema, readFileTool, WriteFileArgsSchema, writeFileTool, EditFileArgsSchema, editFileTool;
|
|
18242
18292
|
var init_filesystem = __esm({
|
|
18243
18293
|
"packages/core/dist/core/tools/builtin/filesystem.js"() {
|
|
18244
18294
|
"use strict";
|
|
18245
18295
|
init_zod();
|
|
18246
18296
|
init_toolTypes();
|
|
18297
|
+
init_newlines();
|
|
18247
18298
|
ReadFileArgsSchema = external_exports.object({
|
|
18248
18299
|
path: external_exports.string().min(1),
|
|
18249
18300
|
startLine: external_exports.number().int().nonnegative().optional().describe("0-based first line to include. Range is applied to the full file before maxBytes."),
|
|
@@ -18337,7 +18388,7 @@ var init_filesystem = __esm({
|
|
|
18337
18388
|
});
|
|
18338
18389
|
editFileTool = {
|
|
18339
18390
|
name: "edit_file",
|
|
18340
|
-
description: "Replace
|
|
18391
|
+
description: "Replace a string in a file. Matching ignores CRLF vs LF; the file keeps its original line endings. Returns an error if oldString is not found.",
|
|
18341
18392
|
permissions: ["write"],
|
|
18342
18393
|
sideEffect: "local",
|
|
18343
18394
|
timeoutMs: 1e4,
|
|
@@ -18347,22 +18398,7 @@ var init_filesystem = __esm({
|
|
|
18347
18398
|
const absPath = path6.isAbsolute(args.path) ? args.path : path6.join(ctx.cwd, args.path);
|
|
18348
18399
|
const content = await fs4.readFile(absPath, { encoding: "utf-8", signal: ctx.signal });
|
|
18349
18400
|
const text = typeof content === "string" ? content : content.toString("utf-8");
|
|
18350
|
-
|
|
18351
|
-
let newContent;
|
|
18352
|
-
if (args.replaceAll) {
|
|
18353
|
-
const parts = text.split(args.oldString);
|
|
18354
|
-
occurrences = parts.length - 1;
|
|
18355
|
-
newContent = parts.join(args.newString);
|
|
18356
|
-
} else {
|
|
18357
|
-
const idx = text.indexOf(args.oldString);
|
|
18358
|
-
if (idx === -1) {
|
|
18359
|
-
occurrences = 0;
|
|
18360
|
-
newContent = text;
|
|
18361
|
-
} else {
|
|
18362
|
-
occurrences = 1;
|
|
18363
|
-
newContent = text.slice(0, idx) + args.newString + text.slice(idx + args.oldString.length);
|
|
18364
|
-
}
|
|
18365
|
-
}
|
|
18401
|
+
const { occurrences, newContent } = replaceFileString(text, args.oldString, args.newString, args.replaceAll);
|
|
18366
18402
|
if (occurrences === 0) {
|
|
18367
18403
|
return typedErr(`edit_file: no match for oldString in ${args.path}. Use read_file to copy the exact text (whitespace included) and retry.`);
|
|
18368
18404
|
}
|
|
@@ -19114,7 +19150,7 @@ function formatUnified(hunks, oldLabel, newLabel) {
|
|
|
19114
19150
|
return lines.join("\n");
|
|
19115
19151
|
}
|
|
19116
19152
|
function parseUnified(raw) {
|
|
19117
|
-
const lines = raw
|
|
19153
|
+
const lines = splitLinesLF(raw);
|
|
19118
19154
|
if (lines.length < 2 || !lines[0].startsWith("--- ") || !lines[1].startsWith("+++ ")) {
|
|
19119
19155
|
throw new Error("Invalid unified diff: missing --- / +++ headers");
|
|
19120
19156
|
}
|
|
@@ -19170,6 +19206,72 @@ function parseUnified(raw) {
|
|
|
19170
19206
|
function normalizeWhitespace(s) {
|
|
19171
19207
|
return s.replace(/\s+/g, " ").trim();
|
|
19172
19208
|
}
|
|
19209
|
+
function linesEqual(fileLine, opText, fuzzy) {
|
|
19210
|
+
if (fileLine === opText)
|
|
19211
|
+
return true;
|
|
19212
|
+
if (fuzzy && normalizeWhitespace(fileLine) === normalizeWhitespace(opText))
|
|
19213
|
+
return true;
|
|
19214
|
+
return false;
|
|
19215
|
+
}
|
|
19216
|
+
function hunkOldNeedle(hunk) {
|
|
19217
|
+
return hunk.ops.filter((op) => op.kind !== "+").map((op) => op.text);
|
|
19218
|
+
}
|
|
19219
|
+
function matchAt(lines, at, needle, fuzzy) {
|
|
19220
|
+
if (needle.length === 0)
|
|
19221
|
+
return at >= 0 && at <= lines.length;
|
|
19222
|
+
if (at < 0 || at + needle.length > lines.length)
|
|
19223
|
+
return false;
|
|
19224
|
+
for (let i = 0; i < needle.length; i++) {
|
|
19225
|
+
if (!linesEqual(lines[at + i] ?? "", needle[i], fuzzy))
|
|
19226
|
+
return false;
|
|
19227
|
+
}
|
|
19228
|
+
return true;
|
|
19229
|
+
}
|
|
19230
|
+
function locateHunk(lines, hunk, fileIdx, fuzzy) {
|
|
19231
|
+
const needle = hunkOldNeedle(hunk);
|
|
19232
|
+
const preferred = hunk.oldStart - 1;
|
|
19233
|
+
if (needle.length === 0) {
|
|
19234
|
+
const start = Math.max(fileIdx, preferred >= 0 ? preferred : fileIdx);
|
|
19235
|
+
return { start };
|
|
19236
|
+
}
|
|
19237
|
+
if (preferred >= fileIdx && matchAt(lines, preferred, needle, fuzzy)) {
|
|
19238
|
+
return { start: preferred };
|
|
19239
|
+
}
|
|
19240
|
+
const hits = [];
|
|
19241
|
+
for (let i = fileIdx; i <= lines.length - needle.length; i++) {
|
|
19242
|
+
if (matchAt(lines, i, needle, fuzzy))
|
|
19243
|
+
hits.push(i);
|
|
19244
|
+
}
|
|
19245
|
+
if (hits.length === 0) {
|
|
19246
|
+
if (preferred >= fileIdx) {
|
|
19247
|
+
let fileAt = preferred;
|
|
19248
|
+
for (const op of hunk.ops) {
|
|
19249
|
+
if (op.kind === "+")
|
|
19250
|
+
continue;
|
|
19251
|
+
const fileLine = lines[fileAt] ?? "";
|
|
19252
|
+
if (!linesEqual(fileLine, op.text, fuzzy)) {
|
|
19253
|
+
const label = op.kind === "-" ? "Delete mismatch" : "Context mismatch";
|
|
19254
|
+
return {
|
|
19255
|
+
error: `${label} at line ${fileAt + 1}: expected "${op.text.slice(0, 60)}", got "${fileLine.slice(0, 60)}"`
|
|
19256
|
+
};
|
|
19257
|
+
}
|
|
19258
|
+
fileAt++;
|
|
19259
|
+
}
|
|
19260
|
+
}
|
|
19261
|
+
return { error: `Hunk context not found (oldStart ${hunk.oldStart})` };
|
|
19262
|
+
}
|
|
19263
|
+
if (hits.length === 1)
|
|
19264
|
+
return { start: hits[0] };
|
|
19265
|
+
hits.sort((a, b) => Math.abs(a - preferred) - Math.abs(b - preferred) || a - b);
|
|
19266
|
+
const bestDist = Math.abs(hits[0] - preferred);
|
|
19267
|
+
const tied = hits.filter((h) => Math.abs(h - preferred) === bestDist);
|
|
19268
|
+
if (tied.length > 1) {
|
|
19269
|
+
return {
|
|
19270
|
+
error: `Ambiguous hunk at oldStart ${hunk.oldStart}: ${tied.length} equally close matches (refusing to guess)`
|
|
19271
|
+
};
|
|
19272
|
+
}
|
|
19273
|
+
return { start: hits[0] };
|
|
19274
|
+
}
|
|
19173
19275
|
function applyAllHunks(originalLines, hunks, fuzzy) {
|
|
19174
19276
|
const out = [];
|
|
19175
19277
|
let fileIdx = 0;
|
|
@@ -19177,17 +19279,13 @@ function applyAllHunks(originalLines, hunks, fuzzy) {
|
|
|
19177
19279
|
let hunksSkipped = 0;
|
|
19178
19280
|
let lastReason;
|
|
19179
19281
|
for (const hunk of hunks) {
|
|
19180
|
-
const
|
|
19181
|
-
if (
|
|
19182
|
-
hunksSkipped++;
|
|
19183
|
-
lastReason = `oldStart ${hunk.oldStart} out of range (must be >= 1)`;
|
|
19184
|
-
continue;
|
|
19185
|
-
}
|
|
19186
|
-
if (startIdx > originalLines.length) {
|
|
19282
|
+
const located = locateHunk(originalLines, hunk, fileIdx, fuzzy);
|
|
19283
|
+
if ("error" in located) {
|
|
19187
19284
|
hunksSkipped++;
|
|
19188
|
-
lastReason =
|
|
19189
|
-
|
|
19285
|
+
lastReason = located.error;
|
|
19286
|
+
break;
|
|
19190
19287
|
}
|
|
19288
|
+
const startIdx = located.start;
|
|
19191
19289
|
while (fileIdx < startIdx) {
|
|
19192
19290
|
out.push(originalLines[fileIdx]);
|
|
19193
19291
|
fileIdx++;
|
|
@@ -19200,7 +19298,7 @@ function applyAllHunks(originalLines, hunks, fuzzy) {
|
|
|
19200
19298
|
const op = hunk.ops[hunkIdx];
|
|
19201
19299
|
if (op.kind === " ") {
|
|
19202
19300
|
const fileLine = originalLines[hunkFileIdx] ?? "";
|
|
19203
|
-
if (fileLine
|
|
19301
|
+
if (linesEqual(fileLine, op.text, fuzzy)) {
|
|
19204
19302
|
hunkOut.push(fileLine);
|
|
19205
19303
|
hunkFileIdx++;
|
|
19206
19304
|
hunkIdx++;
|
|
@@ -19211,7 +19309,7 @@ function applyAllHunks(originalLines, hunks, fuzzy) {
|
|
|
19211
19309
|
}
|
|
19212
19310
|
} else if (op.kind === "-") {
|
|
19213
19311
|
const fileLine = originalLines[hunkFileIdx] ?? "";
|
|
19214
|
-
if (fileLine
|
|
19312
|
+
if (linesEqual(fileLine, op.text, fuzzy)) {
|
|
19215
19313
|
hunkFileIdx++;
|
|
19216
19314
|
hunkIdx++;
|
|
19217
19315
|
} else {
|
|
@@ -19244,6 +19342,7 @@ var init_diff = __esm({
|
|
|
19244
19342
|
"use strict";
|
|
19245
19343
|
init_zod();
|
|
19246
19344
|
init_toolTypes();
|
|
19345
|
+
init_newlines();
|
|
19247
19346
|
LCS_MAX_CELLS = 4e6;
|
|
19248
19347
|
ShowDiffArgsSchema = external_exports.object({
|
|
19249
19348
|
path: external_exports.string().min(1),
|
|
@@ -19268,8 +19367,8 @@ var init_diff = __esm({
|
|
|
19268
19367
|
return typedErr(err instanceof Error ? err.message : String(err));
|
|
19269
19368
|
}
|
|
19270
19369
|
}
|
|
19271
|
-
const a = current
|
|
19272
|
-
const b = args.proposedContent
|
|
19370
|
+
const a = splitLinesLF(current);
|
|
19371
|
+
const b = splitLinesLF(args.proposedContent);
|
|
19273
19372
|
const CONTEXT = args.contextLines;
|
|
19274
19373
|
const rawOps = diffOps(a, b);
|
|
19275
19374
|
if (rawOps === null) {
|
|
@@ -19355,7 +19454,7 @@ var init_diff = __esm({
|
|
|
19355
19454
|
});
|
|
19356
19455
|
applyDiffTool = {
|
|
19357
19456
|
name: "apply_diff",
|
|
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.",
|
|
19457
|
+
description: "Apply a unified diff patch to a file. Parses ---/+++/@@ headers and applies each hunk sequentially. CRLF vs LF is ignored; the file keeps its original line endings. Hunks whose @@ line numbers drifted (common after an earlier insert) are relocated by matching context. With fuzzyMatch=true, also tolerates whitespace differences. With dryRun=true, returns the final content without writing. Atomic: if any hunk fails, no partial write occurs.",
|
|
19359
19458
|
permissions: ["write"],
|
|
19360
19459
|
sideEffect: "local",
|
|
19361
19460
|
timeoutMs: 15e3,
|
|
@@ -19380,9 +19479,10 @@ var init_diff = __esm({
|
|
|
19380
19479
|
if (parsed.hunks.length === 0) {
|
|
19381
19480
|
return typedErr("No hunks found in diff");
|
|
19382
19481
|
}
|
|
19383
|
-
const
|
|
19482
|
+
const nl = detectNewline(current);
|
|
19483
|
+
const originalLines = splitLinesLF(current);
|
|
19384
19484
|
const result = applyAllHunks(originalLines, parsed.hunks, args.fuzzyMatch);
|
|
19385
|
-
const finalContent = result.lines.join("\n");
|
|
19485
|
+
const finalContent = fromLF(result.lines.join("\n"), nl);
|
|
19386
19486
|
const ok = result.hunksSkipped === 0;
|
|
19387
19487
|
if (ok && !args.dryRun) {
|
|
19388
19488
|
await fs7.mkdir(path10.dirname(absPath), { recursive: true });
|
|
@@ -19765,11 +19865,11 @@ var init_tools = __esm({
|
|
|
19765
19865
|
if (!ctx.addDocument)
|
|
19766
19866
|
return "Knowledge vault tool not available.";
|
|
19767
19867
|
const title = args["title"] || "New Document";
|
|
19768
|
-
const
|
|
19868
|
+
const path74 = args["path"] || `notes/${title.toLowerCase().replace(/[^a-z0-9]+/g, "-")}`;
|
|
19769
19869
|
const content = args["content"] || "";
|
|
19770
19870
|
const tags = args["tags"] || [];
|
|
19771
19871
|
ctx.addDocument({
|
|
19772
|
-
path:
|
|
19872
|
+
path: path74,
|
|
19773
19873
|
title,
|
|
19774
19874
|
content,
|
|
19775
19875
|
format: "markdown",
|
|
@@ -19778,7 +19878,7 @@ var init_tools = __esm({
|
|
|
19778
19878
|
workspaceId: ctx.workspaceId
|
|
19779
19879
|
});
|
|
19780
19880
|
ctx.addActivity("vault", "created document", title);
|
|
19781
|
-
return `Document "${title}" created at "${
|
|
19881
|
+
return `Document "${title}" created at "${path74}".`;
|
|
19782
19882
|
}
|
|
19783
19883
|
}
|
|
19784
19884
|
];
|
|
@@ -25734,11 +25834,11 @@ var init_synthesisAudit = __esm({
|
|
|
25734
25834
|
import { existsSync as existsSync7, readFileSync as readFileSync7, writeFileSync as writeFileSync5 } from "node:fs";
|
|
25735
25835
|
import { join as join4 } from "node:path";
|
|
25736
25836
|
function loadNfrSpec(zelariRoot) {
|
|
25737
|
-
const
|
|
25738
|
-
if (!existsSync7(
|
|
25837
|
+
const path74 = join4(zelariRoot, "nfr-spec.json");
|
|
25838
|
+
if (!existsSync7(path74))
|
|
25739
25839
|
return null;
|
|
25740
25840
|
try {
|
|
25741
|
-
const raw = JSON.parse(readFileSync7(
|
|
25841
|
+
const raw = JSON.parse(readFileSync7(path74, "utf8"));
|
|
25742
25842
|
if (raw.version !== 1 || !Array.isArray(raw.targets))
|
|
25743
25843
|
return null;
|
|
25744
25844
|
return raw;
|
|
@@ -28044,9 +28144,9 @@ var init_types5 = __esm({
|
|
|
28044
28144
|
import { readFileSync as readFileSync12 } from "node:fs";
|
|
28045
28145
|
import { join as join10 } from "node:path";
|
|
28046
28146
|
function readLessonsDeduped(zelariRoot) {
|
|
28047
|
-
const
|
|
28147
|
+
const path74 = join10(zelariRoot, LESSONS_FILE);
|
|
28048
28148
|
try {
|
|
28049
|
-
const raw = readFileSync12(
|
|
28149
|
+
const raw = readFileSync12(path74, "utf8");
|
|
28050
28150
|
const byId = /* @__PURE__ */ new Map();
|
|
28051
28151
|
for (const line of raw.split(/\r?\n/)) {
|
|
28052
28152
|
if (!line.trim())
|
|
@@ -28147,8 +28247,8 @@ function keywordsFrom(check2, signature) {
|
|
|
28147
28247
|
return [.../* @__PURE__ */ new Set([...fromId, ...words])].slice(0, 12);
|
|
28148
28248
|
}
|
|
28149
28249
|
function writeLesson(zelariRoot, lesson) {
|
|
28150
|
-
const
|
|
28151
|
-
appendFileSync(
|
|
28250
|
+
const path74 = join11(zelariRoot, LESSONS_FILE);
|
|
28251
|
+
appendFileSync(path74, `${JSON.stringify(lesson)}
|
|
28152
28252
|
`, "utf8");
|
|
28153
28253
|
}
|
|
28154
28254
|
function findSimilar(lessons, signature) {
|
|
@@ -30111,9 +30211,9 @@ function findCycle(nodes) {
|
|
|
30111
30211
|
if (color.get(start) !== WHITE)
|
|
30112
30212
|
continue;
|
|
30113
30213
|
const stack = [[start, 0]];
|
|
30114
|
-
const
|
|
30214
|
+
const path74 = [];
|
|
30115
30215
|
color.set(start, GRAY);
|
|
30116
|
-
|
|
30216
|
+
path74.push(start);
|
|
30117
30217
|
while (stack.length > 0) {
|
|
30118
30218
|
const top = stack[stack.length - 1];
|
|
30119
30219
|
const [id3, idx] = top;
|
|
@@ -30126,17 +30226,17 @@ function findCycle(nodes) {
|
|
|
30126
30226
|
continue;
|
|
30127
30227
|
const c = color.get(dep);
|
|
30128
30228
|
if (c === GRAY) {
|
|
30129
|
-
const at =
|
|
30130
|
-
return [...
|
|
30229
|
+
const at = path74.indexOf(dep);
|
|
30230
|
+
return [...path74.slice(at), dep];
|
|
30131
30231
|
}
|
|
30132
30232
|
if (c === WHITE) {
|
|
30133
30233
|
color.set(dep, GRAY);
|
|
30134
|
-
|
|
30234
|
+
path74.push(dep);
|
|
30135
30235
|
stack.push([dep, 0]);
|
|
30136
30236
|
}
|
|
30137
30237
|
} else {
|
|
30138
30238
|
color.set(id3, BLACK);
|
|
30139
|
-
|
|
30239
|
+
path74.pop();
|
|
30140
30240
|
stack.pop();
|
|
30141
30241
|
}
|
|
30142
30242
|
}
|
|
@@ -31056,8 +31156,8 @@ var init_runner = __esm({
|
|
|
31056
31156
|
failed: [...this.tentaclesById.values()].filter((r) => r.status === "error"),
|
|
31057
31157
|
pending: []
|
|
31058
31158
|
};
|
|
31059
|
-
const
|
|
31060
|
-
this.host.log(`checkpoint: ${label ?? "auto"} \u2192 ${
|
|
31159
|
+
const path74 = await this.host.saveSnapshot(snapshot, ".zelari/kraken/snapshots");
|
|
31160
|
+
this.host.log(`checkpoint: ${label ?? "auto"} \u2192 ${path74}`);
|
|
31061
31161
|
return snapshot;
|
|
31062
31162
|
}
|
|
31063
31163
|
callLog(msg, data) {
|
|
@@ -33499,16 +33599,16 @@ function runRetentionFromEnv() {
|
|
|
33499
33599
|
maxTotalBytes: Number.isFinite(parseMb) && parseMb > 0 ? Math.round(parseMb * 1024 * 1024) : DEFAULT_RUN_RETENTION_MAX_MB * 1024 * 1024
|
|
33500
33600
|
};
|
|
33501
33601
|
}
|
|
33502
|
-
async function dirSize(
|
|
33602
|
+
async function dirSize(path74) {
|
|
33503
33603
|
let total = 0;
|
|
33504
33604
|
let entries;
|
|
33505
33605
|
try {
|
|
33506
|
-
entries = await readdir(
|
|
33606
|
+
entries = await readdir(path74, { withFileTypes: true });
|
|
33507
33607
|
} catch {
|
|
33508
33608
|
return 0;
|
|
33509
33609
|
}
|
|
33510
33610
|
for (const entry of entries) {
|
|
33511
|
-
const child = join13(
|
|
33611
|
+
const child = join13(path74, entry.name);
|
|
33512
33612
|
if (entry.isDirectory())
|
|
33513
33613
|
total += await dirSize(child);
|
|
33514
33614
|
else {
|
|
@@ -33535,19 +33635,19 @@ async function enforceRunRetention(runsDir, options = {}) {
|
|
|
33535
33635
|
for (const entry of entries) {
|
|
33536
33636
|
if (!entry.isDirectory())
|
|
33537
33637
|
continue;
|
|
33538
|
-
const
|
|
33638
|
+
const path74 = join13(runsDir, entry.name);
|
|
33539
33639
|
let startedAt = 0;
|
|
33540
33640
|
let endedAt;
|
|
33541
33641
|
let completed = false;
|
|
33542
33642
|
try {
|
|
33543
|
-
const manifest = JSON.parse(await readFile(join13(
|
|
33643
|
+
const manifest = JSON.parse(await readFile(join13(path74, "manifest.json"), "utf8"));
|
|
33544
33644
|
startedAt = manifest.startedAt ?? 0;
|
|
33545
33645
|
endedAt = manifest.endedAt;
|
|
33546
33646
|
completed = Boolean(endedAt) && manifest.status !== "running";
|
|
33547
33647
|
} catch {
|
|
33548
33648
|
completed = false;
|
|
33549
33649
|
}
|
|
33550
|
-
infos.push({ name: entry.name, path:
|
|
33650
|
+
infos.push({ name: entry.name, path: path74, startedAt, endedAt, completed, bytes: await dirSize(path74) });
|
|
33551
33651
|
}
|
|
33552
33652
|
const remove = async (info) => {
|
|
33553
33653
|
await rm(info.path, { recursive: true, force: true });
|
|
@@ -34319,12 +34419,12 @@ var init_engine = __esm({
|
|
|
34319
34419
|
* content digest) and the returned ref carries the event seq when the
|
|
34320
34420
|
* emitter resolved one.
|
|
34321
34421
|
*/
|
|
34322
|
-
async fsEvidence(observation,
|
|
34422
|
+
async fsEvidence(observation, path74, sha256, content, extra = {}) {
|
|
34323
34423
|
const digest = sha256 && content !== void 0 ? sha256(content) : void 0;
|
|
34324
|
-
const seq = await this.emitEvidence({ observation, path:
|
|
34424
|
+
const seq = await this.emitEvidence({ observation, path: path74, ...extra, ...digest ? { digest } : {} });
|
|
34325
34425
|
return {
|
|
34326
34426
|
tier: "fs-observation",
|
|
34327
|
-
ref:
|
|
34427
|
+
ref: path74,
|
|
34328
34428
|
capturedAt: Date.now(),
|
|
34329
34429
|
...digest ? { digest } : {},
|
|
34330
34430
|
...seq !== void 0 ? { seq } : {}
|
|
@@ -34706,7 +34806,8 @@ var init_verifier = __esm({
|
|
|
34706
34806
|
});
|
|
34707
34807
|
VERIFIER_SYSTEM_PROMPT = [
|
|
34708
34808
|
"You are an independent completion verifier.",
|
|
34709
|
-
"You receive a
|
|
34809
|
+
"You receive the original task, a git diff summary, a test output excerpt,",
|
|
34810
|
+
"and deterministic verification results \u2014 never the builder narration.",
|
|
34710
34811
|
"Answer with a single JSON object and nothing else:",
|
|
34711
34812
|
'{"verdict":"confirmed|rejected|unknown","score":0..1,"rationale":"..."}',
|
|
34712
34813
|
"Rules: never confirm when a required deterministic check failed or is unknown;",
|
|
@@ -34741,8 +34842,14 @@ var init_verifier = __esm({
|
|
|
34741
34842
|
try {
|
|
34742
34843
|
response = await this.deps.callModel({
|
|
34743
34844
|
system: VERIFIER_SYSTEM_PROMPT,
|
|
34845
|
+
// Blind review payload: evidence only (task, diff summary, test output
|
|
34846
|
+
// excerpt, deterministic results). Builder narration/reasoning is
|
|
34847
|
+
// structurally excluded — undefined keys are omitted.
|
|
34744
34848
|
user: JSON.stringify({
|
|
34849
|
+
...request.task === void 0 ? {} : { task: request.task },
|
|
34745
34850
|
summary: request.summary,
|
|
34851
|
+
...request.diffSummary === void 0 ? {} : { diffSummary: request.diffSummary },
|
|
34852
|
+
...request.testOutputExcerpt === void 0 ? {} : { testOutputExcerpt: request.testOutputExcerpt },
|
|
34746
34853
|
deterministicResults: request.results.map((r) => ({
|
|
34747
34854
|
criterionId: r.criterionId,
|
|
34748
34855
|
status: r.status,
|
|
@@ -37457,9 +37564,9 @@ function spillToolOutput(fullText, meta3) {
|
|
|
37457
37564
|
const rnd = randomBytes3(3).toString("hex");
|
|
37458
37565
|
const safeTool = (meta3?.toolName ?? "tool").replace(/[^a-zA-Z0-9._-]+/g, "_").slice(0, 32);
|
|
37459
37566
|
const file2 = `${stamp}-${safeTool}-${hash3}-${rnd}.txt`;
|
|
37460
|
-
const
|
|
37461
|
-
writeFileSync11(
|
|
37462
|
-
return
|
|
37567
|
+
const path74 = join14(dir, file2);
|
|
37568
|
+
writeFileSync11(path74, fullText, "utf8");
|
|
37569
|
+
return path74;
|
|
37463
37570
|
} catch {
|
|
37464
37571
|
return null;
|
|
37465
37572
|
}
|
|
@@ -37505,10 +37612,10 @@ function truncateToolResult(text, capOrOpts = TOOL_RESULT_LINE_CAP) {
|
|
|
37505
37612
|
${tail2}`;
|
|
37506
37613
|
}
|
|
37507
37614
|
if (doSpill) {
|
|
37508
|
-
const
|
|
37509
|
-
if (
|
|
37615
|
+
const path74 = spillToolOutput(text, { toolName: opts.toolName });
|
|
37616
|
+
if (path74) {
|
|
37510
37617
|
const spillNote = `
|
|
37511
|
-
\u2026 [full output spilled to: ${
|
|
37618
|
+
\u2026 [full output spilled to: ${path74} \u2014 re-read with read_file if you need the complete text] \u2026`;
|
|
37512
37619
|
if (preview.includes("] \u2026\n")) {
|
|
37513
37620
|
preview = preview.replace("] \u2026\n", `] \u2026${spillNote}
|
|
37514
37621
|
`);
|
|
@@ -39305,7 +39412,7 @@ var init_taskTool = __esm({
|
|
|
39305
39412
|
init_candidateRegistry();
|
|
39306
39413
|
init_verifyReport();
|
|
39307
39414
|
init_metrics2();
|
|
39308
|
-
TASK_TOOL_TIMEOUT_MS =
|
|
39415
|
+
TASK_TOOL_TIMEOUT_MS = 27e5;
|
|
39309
39416
|
EXPLORE_PROMPT = [
|
|
39310
39417
|
"You are a focused EXPLORE tentacle of Kraken (parent super-agent).",
|
|
39311
39418
|
"READ-ONLY tools only (read, list, grep, fetch). No edits, no shell.",
|
|
@@ -40340,28 +40447,28 @@ var init_storage = __esm({
|
|
|
40340
40447
|
VALID_SCALARS = /^(true|false|null|~)$/i;
|
|
40341
40448
|
Storage = class {
|
|
40342
40449
|
/** Read a Markdown file with frontmatter. Throws if not found. */
|
|
40343
|
-
read(
|
|
40344
|
-
if (!existsSync19(
|
|
40345
|
-
throw new Error(`File not found: ${
|
|
40450
|
+
read(path74) {
|
|
40451
|
+
if (!existsSync19(path74)) {
|
|
40452
|
+
throw new Error(`File not found: ${path74}`);
|
|
40346
40453
|
}
|
|
40347
|
-
const md = readFileSync16(
|
|
40454
|
+
const md = readFileSync16(path74, "utf8");
|
|
40348
40455
|
return parseFrontmatter(md);
|
|
40349
40456
|
}
|
|
40350
40457
|
/** Read a Markdown file; returns null if not found. */
|
|
40351
|
-
readIfExists(
|
|
40352
|
-
if (!existsSync19(
|
|
40353
|
-
return this.read(
|
|
40458
|
+
readIfExists(path74) {
|
|
40459
|
+
if (!existsSync19(path74)) return null;
|
|
40460
|
+
return this.read(path74);
|
|
40354
40461
|
}
|
|
40355
40462
|
/**
|
|
40356
40463
|
* Write a Markdown file atomically (tmp + rename). Creates parent dirs.
|
|
40357
40464
|
* The meta object is serialized as YAML frontmatter; body as Markdown.
|
|
40358
40465
|
*/
|
|
40359
|
-
write(
|
|
40360
|
-
mkdirSync10(dirname2(
|
|
40361
|
-
const tmp =
|
|
40466
|
+
write(path74, meta3, body) {
|
|
40467
|
+
mkdirSync10(dirname2(path74), { recursive: true });
|
|
40468
|
+
const tmp = path74 + ".tmp-" + process.pid;
|
|
40362
40469
|
const md = serializeFrontmatter(meta3, body);
|
|
40363
40470
|
writeFileSync13(tmp, md, "utf8");
|
|
40364
|
-
renameSync(tmp,
|
|
40471
|
+
renameSync(tmp, path74);
|
|
40365
40472
|
}
|
|
40366
40473
|
/** List all .md files in a directory (non-recursive). */
|
|
40367
40474
|
listMarkdown(dir) {
|
|
@@ -40423,8 +40530,8 @@ function nextPlanTaskId(store6) {
|
|
|
40423
40530
|
return `t${store6.counter}`;
|
|
40424
40531
|
}
|
|
40425
40532
|
function writePlanTaskArtifact(rootDir, task) {
|
|
40426
|
-
const
|
|
40427
|
-
mkdirSync11(dirname3(
|
|
40533
|
+
const path74 = join18(rootDir, "plan-tasks", `${task.id}.md`);
|
|
40534
|
+
mkdirSync11(dirname3(path74), { recursive: true });
|
|
40428
40535
|
const meta3 = {
|
|
40429
40536
|
kind: "task",
|
|
40430
40537
|
id: task.id,
|
|
@@ -40445,7 +40552,7 @@ function writePlanTaskArtifact(rootDir, task) {
|
|
|
40445
40552
|
task.notes?.trim() ? task.notes.trim() : "_(no notes)_",
|
|
40446
40553
|
""
|
|
40447
40554
|
].filter((l) => l !== null).join("\n");
|
|
40448
|
-
new Storage().write(
|
|
40555
|
+
new Storage().write(path74, meta3, body);
|
|
40449
40556
|
}
|
|
40450
40557
|
function loadHandle(rootDir) {
|
|
40451
40558
|
const jsonPath = join18(rootDir, "plan.json");
|
|
@@ -43733,21 +43840,21 @@ function normalizeAuth(auth) {
|
|
|
43733
43840
|
return "agent";
|
|
43734
43841
|
}
|
|
43735
43842
|
function readSecrets() {
|
|
43736
|
-
const
|
|
43737
|
-
if (!existsSync23(
|
|
43843
|
+
const path74 = getSshSecretsPath();
|
|
43844
|
+
if (!existsSync23(path74)) return {};
|
|
43738
43845
|
try {
|
|
43739
|
-
return JSON.parse(readFileSync20(
|
|
43846
|
+
return JSON.parse(readFileSync20(path74, "utf8"));
|
|
43740
43847
|
} catch {
|
|
43741
43848
|
return {};
|
|
43742
43849
|
}
|
|
43743
43850
|
}
|
|
43744
43851
|
function writeSecrets(data) {
|
|
43745
|
-
const
|
|
43746
|
-
mkdirSync12(dirname4(
|
|
43747
|
-
writeFileSync15(
|
|
43852
|
+
const path74 = getSshSecretsPath();
|
|
43853
|
+
mkdirSync12(dirname4(path74), { recursive: true });
|
|
43854
|
+
writeFileSync15(path74, `${JSON.stringify(data, null, 2)}
|
|
43748
43855
|
`, "utf8");
|
|
43749
43856
|
try {
|
|
43750
|
-
chmodSync(
|
|
43857
|
+
chmodSync(path74, 384);
|
|
43751
43858
|
} catch {
|
|
43752
43859
|
}
|
|
43753
43860
|
}
|
|
@@ -43776,10 +43883,10 @@ function deleteSshPassword(id3) {
|
|
|
43776
43883
|
writeSecrets({ passwords });
|
|
43777
43884
|
}
|
|
43778
43885
|
function readStore2() {
|
|
43779
|
-
const
|
|
43780
|
-
if (!existsSync23(
|
|
43886
|
+
const path74 = getSshTargetsPath();
|
|
43887
|
+
if (!existsSync23(path74)) return [];
|
|
43781
43888
|
try {
|
|
43782
|
-
const parsed = JSON.parse(readFileSync20(
|
|
43889
|
+
const parsed = JSON.parse(readFileSync20(path74, "utf8"));
|
|
43783
43890
|
const list = Array.isArray(parsed.targets) ? parsed.targets : [];
|
|
43784
43891
|
return list.filter(
|
|
43785
43892
|
(t) => t && typeof t.id === "string" && typeof t.host === "string" && typeof t.user === "string"
|
|
@@ -43794,11 +43901,11 @@ function readStore2() {
|
|
|
43794
43901
|
}
|
|
43795
43902
|
}
|
|
43796
43903
|
function writeStore2(targets) {
|
|
43797
|
-
const
|
|
43798
|
-
mkdirSync12(dirname4(
|
|
43904
|
+
const path74 = getSshTargetsPath();
|
|
43905
|
+
mkdirSync12(dirname4(path74), { recursive: true });
|
|
43799
43906
|
const clean = targets.map(({ hasPassword: _hp, ...t }) => t);
|
|
43800
43907
|
writeFileSync15(
|
|
43801
|
-
|
|
43908
|
+
path74,
|
|
43802
43909
|
`${JSON.stringify({ targets: clean }, null, 2)}
|
|
43803
43910
|
`,
|
|
43804
43911
|
"utf8"
|
|
@@ -44044,11 +44151,11 @@ function formatSshTargetsForPrompt() {
|
|
|
44044
44151
|
];
|
|
44045
44152
|
for (const t of targets) {
|
|
44046
44153
|
const tags = t.tags?.length ? ` tags=[${t.tags.join(",")}]` : "";
|
|
44047
|
-
const
|
|
44154
|
+
const path74 = t.defaultRemotePath ? ` remotePath=${t.defaultRemotePath}` : "";
|
|
44048
44155
|
const allow = t.allowedCommands?.length ? ` allowed=${t.allowedCommands.join("|")}` : " allowed=status-only";
|
|
44049
44156
|
const auth = t.auth === "password" ? " auth=password" : t.auth === "keyPath" ? " auth=key" : " auth=agent";
|
|
44050
44157
|
lines.push(
|
|
44051
|
-
`- id=${t.id} name=${t.name} ${t.user}@${t.host}:${t.port ?? 22}${auth}${
|
|
44158
|
+
`- id=${t.id} name=${t.name} ${t.user}@${t.host}:${t.port ?? 22}${auth}${path74}${tags}${allow}`
|
|
44052
44159
|
);
|
|
44053
44160
|
}
|
|
44054
44161
|
return lines.join("\n");
|
|
@@ -45048,6 +45155,19 @@ function defaultPermissionPolicy(overrides) {
|
|
|
45048
45155
|
...overrides
|
|
45049
45156
|
};
|
|
45050
45157
|
}
|
|
45158
|
+
function moreRestrictive(a, b) {
|
|
45159
|
+
return ACTION_RANK2[a] >= ACTION_RANK2[b] ? a : b;
|
|
45160
|
+
}
|
|
45161
|
+
function intersectPermissionPolicy(parent, child) {
|
|
45162
|
+
return {
|
|
45163
|
+
read: moreRestrictive(parent.read, child.read),
|
|
45164
|
+
write: moreRestrictive(parent.write, child.write),
|
|
45165
|
+
execute: moreRestrictive(parent.execute, child.execute),
|
|
45166
|
+
network: moreRestrictive(parent.network, child.network),
|
|
45167
|
+
ui: moreRestrictive(parent.ui, child.ui),
|
|
45168
|
+
auto: parent.auto && child.auto
|
|
45169
|
+
};
|
|
45170
|
+
}
|
|
45051
45171
|
function resolveToolPermission(toolName, required2, policy) {
|
|
45052
45172
|
if (!required2.length) {
|
|
45053
45173
|
return { action: "allow", reason: "", categories: [] };
|
|
@@ -45083,12 +45203,13 @@ function resolveToolPermission(toolName, required2, policy) {
|
|
|
45083
45203
|
categories: hit
|
|
45084
45204
|
};
|
|
45085
45205
|
}
|
|
45086
|
-
var sessionToolGrants, sessionCategoryGrants;
|
|
45206
|
+
var sessionToolGrants, sessionCategoryGrants, ACTION_RANK2;
|
|
45087
45207
|
var init_toolPermissions = __esm({
|
|
45088
45208
|
"src/cli/safety/toolPermissions.ts"() {
|
|
45089
45209
|
"use strict";
|
|
45090
45210
|
sessionToolGrants = /* @__PURE__ */ new Set();
|
|
45091
45211
|
sessionCategoryGrants = /* @__PURE__ */ new Set();
|
|
45212
|
+
ACTION_RANK2 = { allow: 0, ask: 1, deny: 2 };
|
|
45092
45213
|
}
|
|
45093
45214
|
});
|
|
45094
45215
|
|
|
@@ -45265,10 +45386,239 @@ var init_lifecycleHooks = __esm({
|
|
|
45265
45386
|
}
|
|
45266
45387
|
});
|
|
45267
45388
|
|
|
45389
|
+
// src/cli/safety/policyEngine.ts
|
|
45390
|
+
import { readFileSync as readFileSync22 } from "node:fs";
|
|
45391
|
+
import { homedir as homedir10 } from "node:os";
|
|
45392
|
+
import path40 from "node:path";
|
|
45393
|
+
function emptyPolicySet() {
|
|
45394
|
+
return { agents: /* @__PURE__ */ new Map(), warnings: [], precedence: policyPrecedenceFromEnv() };
|
|
45395
|
+
}
|
|
45396
|
+
function agentLayersFor(set2, agent) {
|
|
45397
|
+
return set2.agents.get(agent) ?? EMPTY_POLICY_LAYERS;
|
|
45398
|
+
}
|
|
45399
|
+
function globToRegExp(pattern) {
|
|
45400
|
+
let src = "^";
|
|
45401
|
+
for (let i = 0; i < pattern.length; i++) {
|
|
45402
|
+
const ch = pattern[i];
|
|
45403
|
+
if (ch === "*") {
|
|
45404
|
+
while (pattern[i + 1] === "*") i++;
|
|
45405
|
+
src += ".*";
|
|
45406
|
+
} else if ("\\^$.|?+()[]{}".includes(ch)) {
|
|
45407
|
+
src += "\\" + ch;
|
|
45408
|
+
} else {
|
|
45409
|
+
src += ch;
|
|
45410
|
+
}
|
|
45411
|
+
}
|
|
45412
|
+
return new RegExp(src + "$");
|
|
45413
|
+
}
|
|
45414
|
+
function normalizeForMatch(value) {
|
|
45415
|
+
return value.replace(/\\/g, "/");
|
|
45416
|
+
}
|
|
45417
|
+
function resolvePolicyRule(rules, value) {
|
|
45418
|
+
const v = normalizeForMatch(value);
|
|
45419
|
+
for (const rule of rules) {
|
|
45420
|
+
if (globToRegExp(normalizeForMatch(rule.match)).test(v)) return rule;
|
|
45421
|
+
}
|
|
45422
|
+
return null;
|
|
45423
|
+
}
|
|
45424
|
+
function mergeRuleEffect(base2, rule) {
|
|
45425
|
+
if (!rule) return base2;
|
|
45426
|
+
return EFFECT_RANK[rule.effect] > EFFECT_RANK[base2] ? rule.effect : base2;
|
|
45427
|
+
}
|
|
45428
|
+
function pathCandidates(value, root) {
|
|
45429
|
+
const norm = normalizeForMatch(value);
|
|
45430
|
+
if (!root) return [norm];
|
|
45431
|
+
const prefix = normalizeForMatch(root).replace(/\/+$/, "") + "/";
|
|
45432
|
+
const stripped = norm.toLowerCase().startsWith(prefix.toLowerCase()) ? norm.slice(prefix.length) : null;
|
|
45433
|
+
return stripped !== null ? [stripped, norm] : [norm];
|
|
45434
|
+
}
|
|
45435
|
+
function matchAgentPolicyRule(rules, required2, args, root) {
|
|
45436
|
+
if (!rules) return null;
|
|
45437
|
+
const a = args !== null && typeof args === "object" ? args : {};
|
|
45438
|
+
if (required2.includes("execute")) {
|
|
45439
|
+
const cmd = a["command"];
|
|
45440
|
+
if (typeof cmd === "string" && cmd !== "") {
|
|
45441
|
+
const hit = resolvePolicyRule(rules.shell, cmd);
|
|
45442
|
+
if (hit) return hit;
|
|
45443
|
+
}
|
|
45444
|
+
}
|
|
45445
|
+
if (required2.includes("write")) {
|
|
45446
|
+
const p3 = typeof a["path"] === "string" ? a["path"] : typeof a["file_path"] === "string" ? a["file_path"] : "";
|
|
45447
|
+
if (p3 !== "") {
|
|
45448
|
+
for (const candidate of pathCandidates(p3, root)) {
|
|
45449
|
+
const hit = resolvePolicyRule(rules.edit, candidate);
|
|
45450
|
+
if (hit) return hit;
|
|
45451
|
+
}
|
|
45452
|
+
}
|
|
45453
|
+
}
|
|
45454
|
+
return null;
|
|
45455
|
+
}
|
|
45456
|
+
function isPolicyEngineDisabled() {
|
|
45457
|
+
const v = process.env.ZELARI_POLICY?.trim().toLowerCase();
|
|
45458
|
+
return v === "0" || v === "false" || v === "no" || v === "off";
|
|
45459
|
+
}
|
|
45460
|
+
function policyPrecedenceFromEnv() {
|
|
45461
|
+
const v = process.env.ZELARI_POLICY_PRECEDENCE?.trim().toLowerCase();
|
|
45462
|
+
return v === "legacy" ? "legacy" : "restrict-only";
|
|
45463
|
+
}
|
|
45464
|
+
function isPlainObject2(v) {
|
|
45465
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
45466
|
+
}
|
|
45467
|
+
function parseRuleList(raw, origin, warnings) {
|
|
45468
|
+
if (raw === void 0) return [];
|
|
45469
|
+
if (!Array.isArray(raw)) {
|
|
45470
|
+
warnings.push(`${origin}: expected an array of rules, got ${typeof raw} \u2014 section ignored.`);
|
|
45471
|
+
return [];
|
|
45472
|
+
}
|
|
45473
|
+
const out = [];
|
|
45474
|
+
raw.forEach((item, i) => {
|
|
45475
|
+
const where = `${origin}[${i}]`;
|
|
45476
|
+
if (!isPlainObject2(item)) {
|
|
45477
|
+
warnings.push(`${where}: rule is not an object \u2014 skipped.`);
|
|
45478
|
+
return;
|
|
45479
|
+
}
|
|
45480
|
+
const match = item["match"];
|
|
45481
|
+
const effect = item["effect"];
|
|
45482
|
+
const reason = item["reason"];
|
|
45483
|
+
if (typeof match !== "string" || match.trim() === "") {
|
|
45484
|
+
warnings.push(`${where}: missing or empty "match" \u2014 skipped.`);
|
|
45485
|
+
return;
|
|
45486
|
+
}
|
|
45487
|
+
if (effect !== "allow" && effect !== "ask" && effect !== "deny") {
|
|
45488
|
+
warnings.push(`${where} ("${match}"): "effect" must be allow|ask|deny \u2014 skipped.`);
|
|
45489
|
+
return;
|
|
45490
|
+
}
|
|
45491
|
+
out.push(
|
|
45492
|
+
typeof reason === "string" && reason.trim() !== "" ? { match, effect, reason } : { match, effect }
|
|
45493
|
+
);
|
|
45494
|
+
});
|
|
45495
|
+
return out;
|
|
45496
|
+
}
|
|
45497
|
+
function parsePolicyFile(raw, origin, warnings) {
|
|
45498
|
+
if (!isPlainObject2(raw)) {
|
|
45499
|
+
warnings.push(`${origin}: policy file is not a JSON object \u2014 file ignored.`);
|
|
45500
|
+
return null;
|
|
45501
|
+
}
|
|
45502
|
+
const version2 = raw["version"];
|
|
45503
|
+
if (version2 !== void 0 && version2 !== 1) {
|
|
45504
|
+
warnings.push(`${origin}: unsupported "version" ${JSON.stringify(version2)} (expected 1) \u2014 file ignored.`);
|
|
45505
|
+
return null;
|
|
45506
|
+
}
|
|
45507
|
+
const agentsRaw = raw["agents"];
|
|
45508
|
+
if (agentsRaw === void 0) {
|
|
45509
|
+
warnings.push(`${origin}: no "agents" key \u2014 file ignored.`);
|
|
45510
|
+
return null;
|
|
45511
|
+
}
|
|
45512
|
+
if (!isPlainObject2(agentsRaw)) {
|
|
45513
|
+
warnings.push(`${origin}: "agents" is not an object \u2014 file ignored.`);
|
|
45514
|
+
return null;
|
|
45515
|
+
}
|
|
45516
|
+
const out = /* @__PURE__ */ new Map();
|
|
45517
|
+
for (const [key, val] of Object.entries(agentsRaw)) {
|
|
45518
|
+
const agent = key.trim().toLowerCase();
|
|
45519
|
+
if (!KNOWN_AGENTS.has(agent)) {
|
|
45520
|
+
warnings.push(`${origin}: unknown agent "${key}" (known: ${POLICY_AGENTS.join(" | ")}) \u2014 ignored.`);
|
|
45521
|
+
continue;
|
|
45522
|
+
}
|
|
45523
|
+
if (!isPlainObject2(val)) {
|
|
45524
|
+
warnings.push(`${origin}: agents.${key} is not an object \u2014 ignored.`);
|
|
45525
|
+
continue;
|
|
45526
|
+
}
|
|
45527
|
+
const shell = parseRuleList(val["shell"], `${origin} agents.${key}.shell`, warnings);
|
|
45528
|
+
const edit = parseRuleList(val["edit"], `${origin} agents.${key}.edit`, warnings);
|
|
45529
|
+
out.set(agent, { shell, edit });
|
|
45530
|
+
}
|
|
45531
|
+
return out;
|
|
45532
|
+
}
|
|
45533
|
+
function readPolicyFile(file2, warnings) {
|
|
45534
|
+
let text;
|
|
45535
|
+
try {
|
|
45536
|
+
text = readFileSync22(file2, "utf8");
|
|
45537
|
+
} catch {
|
|
45538
|
+
return /* @__PURE__ */ new Map();
|
|
45539
|
+
}
|
|
45540
|
+
let parsed;
|
|
45541
|
+
try {
|
|
45542
|
+
parsed = JSON.parse(text);
|
|
45543
|
+
} catch (err) {
|
|
45544
|
+
warnings.push(
|
|
45545
|
+
`${file2}: invalid JSON (${err instanceof Error ? err.message : String(err)}) \u2014 file ignored.`
|
|
45546
|
+
);
|
|
45547
|
+
return /* @__PURE__ */ new Map();
|
|
45548
|
+
}
|
|
45549
|
+
return parsePolicyFile(parsed, file2, warnings) ?? /* @__PURE__ */ new Map();
|
|
45550
|
+
}
|
|
45551
|
+
function loadPolicySet(root, opts = {}) {
|
|
45552
|
+
if (isPolicyEngineDisabled()) return emptyPolicySet();
|
|
45553
|
+
const warnings = [];
|
|
45554
|
+
const precedence = policyPrecedenceFromEnv();
|
|
45555
|
+
const project = readPolicyFile(path40.join(root, ".zelari", "policy.json"), warnings);
|
|
45556
|
+
const global = readPolicyFile(path40.join(opts.homeDir ?? homedir10(), ".zelari", "policy.json"), warnings);
|
|
45557
|
+
const agents = /* @__PURE__ */ new Map();
|
|
45558
|
+
for (const [agent, p3] of project) {
|
|
45559
|
+
agents.set(agent, { project: p3, global: EMPTY_POLICY_RULE_SET });
|
|
45560
|
+
}
|
|
45561
|
+
for (const [agent, g] of global) {
|
|
45562
|
+
const l = agents.get(agent);
|
|
45563
|
+
agents.set(agent, l ? { ...l, global: g } : { project: EMPTY_POLICY_RULE_SET, global: g });
|
|
45564
|
+
}
|
|
45565
|
+
return { agents, warnings, precedence };
|
|
45566
|
+
}
|
|
45567
|
+
var POLICY_AGENTS, KNOWN_AGENTS, EMPTY_POLICY_RULE_SET, EMPTY_POLICY_LAYERS, EFFECT_RANK;
|
|
45568
|
+
var init_policyEngine = __esm({
|
|
45569
|
+
"src/cli/safety/policyEngine.ts"() {
|
|
45570
|
+
"use strict";
|
|
45571
|
+
POLICY_AGENTS = ["lead", "explore", "general", "verify"];
|
|
45572
|
+
KNOWN_AGENTS = new Set(POLICY_AGENTS);
|
|
45573
|
+
EMPTY_POLICY_RULE_SET = { shell: [], edit: [] };
|
|
45574
|
+
EMPTY_POLICY_LAYERS = {
|
|
45575
|
+
global: EMPTY_POLICY_RULE_SET,
|
|
45576
|
+
project: EMPTY_POLICY_RULE_SET
|
|
45577
|
+
};
|
|
45578
|
+
EFFECT_RANK = { allow: 0, ask: 1, deny: 2 };
|
|
45579
|
+
}
|
|
45580
|
+
});
|
|
45581
|
+
|
|
45582
|
+
// src/cli/safety/policyLayers.ts
|
|
45583
|
+
function intersectEffects(...effects) {
|
|
45584
|
+
let best;
|
|
45585
|
+
for (const effect of effects) {
|
|
45586
|
+
if (effect === void 0) continue;
|
|
45587
|
+
if (best === void 0 || EFFECT_RANK[effect] > EFFECT_RANK[best]) best = effect;
|
|
45588
|
+
}
|
|
45589
|
+
return best ?? "allow";
|
|
45590
|
+
}
|
|
45591
|
+
function matchAgentPolicyRuleLayered(layers, precedence, required2, args, root) {
|
|
45592
|
+
if (!layers) return null;
|
|
45593
|
+
if (precedence === "legacy") {
|
|
45594
|
+
return matchAgentPolicyRule(
|
|
45595
|
+
{
|
|
45596
|
+
shell: [...layers.project.shell, ...layers.global.shell],
|
|
45597
|
+
edit: [...layers.project.edit, ...layers.global.edit]
|
|
45598
|
+
},
|
|
45599
|
+
required2,
|
|
45600
|
+
args,
|
|
45601
|
+
root
|
|
45602
|
+
);
|
|
45603
|
+
}
|
|
45604
|
+
const g = matchAgentPolicyRule(layers.global, required2, args, root);
|
|
45605
|
+
const p3 = matchAgentPolicyRule(layers.project, required2, args, root);
|
|
45606
|
+
if (!g) return p3;
|
|
45607
|
+
if (!p3) return g;
|
|
45608
|
+
const win = intersectEffects(p3.effect, g.effect);
|
|
45609
|
+
return p3.effect === win ? p3 : g;
|
|
45610
|
+
}
|
|
45611
|
+
var init_policyLayers = __esm({
|
|
45612
|
+
"src/cli/safety/policyLayers.ts"() {
|
|
45613
|
+
"use strict";
|
|
45614
|
+
init_policyEngine();
|
|
45615
|
+
}
|
|
45616
|
+
});
|
|
45617
|
+
|
|
45268
45618
|
// src/cli/toolResultCache.ts
|
|
45269
45619
|
import { createHash as createHash13 } from "node:crypto";
|
|
45270
45620
|
import { promises as fs19 } from "node:fs";
|
|
45271
|
-
import
|
|
45621
|
+
import path41 from "node:path";
|
|
45272
45622
|
function isToolCacheEnabled() {
|
|
45273
45623
|
const raw = process.env.ZELARI_TOOL_CACHE;
|
|
45274
45624
|
return raw !== "0" && raw !== "false" && raw !== "off";
|
|
@@ -45353,7 +45703,7 @@ async function statKey(toolName, input, ctx) {
|
|
|
45353
45703
|
if (!input || typeof input !== "object") return null;
|
|
45354
45704
|
const rawPath = input.path;
|
|
45355
45705
|
if (typeof rawPath !== "string" || rawPath.length === 0) return null;
|
|
45356
|
-
const abs =
|
|
45706
|
+
const abs = path41.isAbsolute(rawPath) ? rawPath : path41.join(ctx.cwd, rawPath);
|
|
45357
45707
|
try {
|
|
45358
45708
|
const st = await fs19.stat(abs);
|
|
45359
45709
|
return hashKey({
|
|
@@ -45402,10 +45752,13 @@ var init_toolResultCache = __esm({
|
|
|
45402
45752
|
// src/cli/tools/krakenModel.ts
|
|
45403
45753
|
var krakenModel_exports = {};
|
|
45404
45754
|
__export(krakenModel_exports, {
|
|
45755
|
+
inferModelFamily: () => inferModelFamily,
|
|
45405
45756
|
isCheapModelId: () => isCheapModelId,
|
|
45406
45757
|
isKrakenAutoModelEnabled: () => isKrakenAutoModelEnabled,
|
|
45407
45758
|
parseQualifiedModelRef: () => parseQualifiedModelRef,
|
|
45408
45759
|
pickCheapModel: () => pickCheapModel,
|
|
45760
|
+
pickDifferentFamily: () => pickDifferentFamily,
|
|
45761
|
+
resolveCrossModelVerifier: () => resolveCrossModelVerifier,
|
|
45409
45762
|
resolveKrakenPlannerModel: () => resolveKrakenPlannerModel,
|
|
45410
45763
|
resolveKrakenSubModel: () => resolveKrakenSubModel,
|
|
45411
45764
|
resolveKrakenSubModelAsync: () => resolveKrakenSubModelAsync,
|
|
@@ -45450,6 +45803,44 @@ function parseQualifiedModelRef(ref) {
|
|
|
45450
45803
|
if (!provider || !model) return null;
|
|
45451
45804
|
return { provider, model };
|
|
45452
45805
|
}
|
|
45806
|
+
function inferModelFamily(provider, model) {
|
|
45807
|
+
const p3 = (provider ?? "").trim().toLowerCase();
|
|
45808
|
+
const m = (model ?? "").trim().toLowerCase();
|
|
45809
|
+
const hay = `${p3} ${m}`.trim();
|
|
45810
|
+
if (!hay) return "other";
|
|
45811
|
+
if (/\b(zhipu|glm)\b/.test(hay)) return "zhipu";
|
|
45812
|
+
if (/\b(google|gemini)\b/.test(hay)) return "google";
|
|
45813
|
+
if (/\b(xai|grok)\b/.test(hay)) return "xai";
|
|
45814
|
+
if (/\b(anthropic|claude)\b/.test(hay)) return "anthropic";
|
|
45815
|
+
if (/\b(openai|chatgpt|codex)\b/.test(hay) || /\bgpt\b/.test(hay) || /(^|\s)o[134]($|[-_.])/.test(hay)) {
|
|
45816
|
+
return "openai";
|
|
45817
|
+
}
|
|
45818
|
+
return p3 || "other";
|
|
45819
|
+
}
|
|
45820
|
+
function pickDifferentFamily(builder, candidates) {
|
|
45821
|
+
const builderFamily = inferModelFamily(builder.provider, builder.model);
|
|
45822
|
+
for (const c of candidates) {
|
|
45823
|
+
const provider = c.provider?.trim() ?? "";
|
|
45824
|
+
const model = c.model?.trim() ?? "";
|
|
45825
|
+
if (!provider || !model) continue;
|
|
45826
|
+
if (inferModelFamily(provider, model) !== builderFamily) {
|
|
45827
|
+
return { provider, model };
|
|
45828
|
+
}
|
|
45829
|
+
}
|
|
45830
|
+
return null;
|
|
45831
|
+
}
|
|
45832
|
+
function resolveCrossModelVerifier(builder, candidates, env = process.env) {
|
|
45833
|
+
const cross = (env.ZELARI_KRAKEN_CROSS_MODEL ?? "").trim().toLowerCase();
|
|
45834
|
+
if (cross === "0" || cross === "false" || cross === "off") return null;
|
|
45835
|
+
const specific = env.ZELARI_KRAKEN_VERIFY_MODEL?.trim();
|
|
45836
|
+
if (specific) {
|
|
45837
|
+
const qualified = parseQualifiedModelRef(specific);
|
|
45838
|
+
if (qualified) return qualified;
|
|
45839
|
+
const provider = builder.provider?.trim();
|
|
45840
|
+
return provider ? { provider, model: specific } : null;
|
|
45841
|
+
}
|
|
45842
|
+
return pickDifferentFamily(builder, candidates);
|
|
45843
|
+
}
|
|
45453
45844
|
function resolveKrakenSubModel(agent, parentModel, env = process.env, opts = {}) {
|
|
45454
45845
|
const kindKey = agent === "explore" ? "ZELARI_KRAKEN_EXPLORE_MODEL" : agent === "verify" ? "ZELARI_KRAKEN_VERIFY_MODEL" : "ZELARI_KRAKEN_GENERAL_MODEL";
|
|
45455
45846
|
const specific = env[kindKey]?.trim();
|
|
@@ -45462,6 +45853,13 @@ function resolveKrakenSubModel(agent, parentModel, env = process.env, opts = {})
|
|
|
45462
45853
|
}
|
|
45463
45854
|
return shared2;
|
|
45464
45855
|
}
|
|
45856
|
+
if (agent === "verify" && opts.familyCandidates && opts.familyCandidates.length > 0) {
|
|
45857
|
+
const picked = pickDifferentFamily(
|
|
45858
|
+
{ provider: opts.provider ?? "", model: parentModel },
|
|
45859
|
+
opts.familyCandidates
|
|
45860
|
+
);
|
|
45861
|
+
if (picked) return `${picked.provider}/${picked.model}`;
|
|
45862
|
+
}
|
|
45465
45863
|
if ((agent === "explore" || agent === "verify") && isKrakenAutoModelEnabled(env) && opts.candidates && opts.candidates.length > 0) {
|
|
45466
45864
|
const picked = pickCheapModel(parentModel, opts.candidates);
|
|
45467
45865
|
if (picked) return picked;
|
|
@@ -45557,7 +45955,19 @@ function createBuiltinToolRegistry(options = {}) {
|
|
|
45557
45955
|
const allowMutators = !readOnly && !verifyMode && !gauntletParent;
|
|
45558
45956
|
const allowBash = (allowMutators || verifyMode) && !gauntletParent;
|
|
45559
45957
|
const permPolicy = options.permissionPolicy ?? defaultPermissionPolicy();
|
|
45560
|
-
const
|
|
45958
|
+
const agentPolicySet = loadPolicySet(root);
|
|
45959
|
+
const agentPolicyLayers = agentLayersFor(
|
|
45960
|
+
agentPolicySet,
|
|
45961
|
+
options.policyAgent ?? "lead"
|
|
45962
|
+
);
|
|
45963
|
+
const withPerm = (t) => wrapWithPermissions(
|
|
45964
|
+
t,
|
|
45965
|
+
permPolicy,
|
|
45966
|
+
options.onPermissionAsk,
|
|
45967
|
+
agentPolicyLayers,
|
|
45968
|
+
agentPolicySet.precedence,
|
|
45969
|
+
root
|
|
45970
|
+
);
|
|
45561
45971
|
registry4.register(withPerm(safeReadFile));
|
|
45562
45972
|
registry4.register(withPerm(safeGrepContent));
|
|
45563
45973
|
registry4.register(withPerm(safeListFiles));
|
|
@@ -45691,6 +46101,10 @@ function createBuiltinToolRegistry(options = {}) {
|
|
|
45691
46101
|
root,
|
|
45692
46102
|
audit,
|
|
45693
46103
|
sessionId: sessionId2,
|
|
46104
|
+
// P0.4 capability inheritance: tentacles intersect THIS
|
|
46105
|
+
// registry's own policy (permPolicy above) — they can never
|
|
46106
|
+
// exceed it.
|
|
46107
|
+
parentPolicy: permPolicy,
|
|
45694
46108
|
...options.subAgentProvider ? { provider: options.subAgentProvider } : {},
|
|
45695
46109
|
...options.subAgentModel ? { model: options.subAgentModel } : {}
|
|
45696
46110
|
}),
|
|
@@ -45768,7 +46182,7 @@ function taskAgentToProfile(agent) {
|
|
|
45768
46182
|
return "explore";
|
|
45769
46183
|
}
|
|
45770
46184
|
function createKrakenSubAgentContextFactory(opts) {
|
|
45771
|
-
const { root, audit, sessionId: sessionId2, provider: providerOverride, model: modelOverride } = opts;
|
|
46185
|
+
const { root, audit, sessionId: sessionId2, provider: providerOverride, model: modelOverride, parentPolicy } = opts;
|
|
45772
46186
|
return async ({ agent, cwd: subCwd }) => {
|
|
45773
46187
|
const cfg = providerOverride ? await providerConfigFor(providerOverride) : await providerFromEnv();
|
|
45774
46188
|
if (!cfg) return null;
|
|
@@ -45787,6 +46201,11 @@ function createKrakenSubAgentContextFactory(opts) {
|
|
|
45787
46201
|
const subCfg = { ...effCfg, model };
|
|
45788
46202
|
const subProfile = taskAgentToProfile(agent);
|
|
45789
46203
|
const subRoot = subCwd || root;
|
|
46204
|
+
const agentPolicyForSubProfile = defaultPermissionPolicy({ auto: true });
|
|
46205
|
+
const effectiveSubPolicy = intersectPermissionPolicy(
|
|
46206
|
+
parentPolicy ?? agentPolicyForSubProfile,
|
|
46207
|
+
agentPolicyForSubProfile
|
|
46208
|
+
);
|
|
45790
46209
|
const { registry: subRegistry } = createBuiltinToolRegistry({
|
|
45791
46210
|
root: subRoot,
|
|
45792
46211
|
audit,
|
|
@@ -45796,7 +46215,9 @@ function createKrakenSubAgentContextFactory(opts) {
|
|
|
45796
46215
|
enableSkill: agent === "general",
|
|
45797
46216
|
diagnostics: false,
|
|
45798
46217
|
lspProvider: null,
|
|
45799
|
-
permissionPolicy:
|
|
46218
|
+
permissionPolicy: effectiveSubPolicy,
|
|
46219
|
+
// P0.5: the tentacle's agent identity drives per-agent policy rules.
|
|
46220
|
+
policyAgent: agent
|
|
45800
46221
|
});
|
|
45801
46222
|
return {
|
|
45802
46223
|
providerStream: buildProviderStream(subCfg),
|
|
@@ -45813,7 +46234,7 @@ function createKrakenSubAgentContextFactory(opts) {
|
|
|
45813
46234
|
};
|
|
45814
46235
|
};
|
|
45815
46236
|
}
|
|
45816
|
-
function wrapWithPermissions(original, policy, onAsk) {
|
|
46237
|
+
function wrapWithPermissions(original, policy, onAsk, agentLayers, precedence = "restrict-only", root) {
|
|
45817
46238
|
const required2 = original.permissions ?? [];
|
|
45818
46239
|
const decisionProbe = resolveToolPermission(original.name, required2, policy);
|
|
45819
46240
|
if (decisionProbe.action === "allow" && !required2.includes("write") && !required2.includes("execute")) {
|
|
@@ -45822,13 +46243,22 @@ function wrapWithPermissions(original, policy, onAsk) {
|
|
|
45822
46243
|
...original,
|
|
45823
46244
|
execute: async (input, ctx) => {
|
|
45824
46245
|
const decision = resolveToolPermission(original.name, required2, policy);
|
|
45825
|
-
|
|
45826
|
-
|
|
45827
|
-
|
|
45828
|
-
|
|
46246
|
+
const rule = agentLayers ? matchAgentPolicyRuleLayered(
|
|
46247
|
+
agentLayers,
|
|
46248
|
+
precedence,
|
|
46249
|
+
required2,
|
|
46250
|
+
input ?? {},
|
|
46251
|
+
root ?? process.cwd()
|
|
46252
|
+
) : null;
|
|
46253
|
+
const action = mergeRuleEffect(decision.action, rule);
|
|
46254
|
+
const rulePrefix = rule ? `[policy] rule '${rule.match}'${rule.reason ? ` \u2014 ${rule.reason}` : ""}` : "";
|
|
46255
|
+
if (action === "deny") {
|
|
46256
|
+
return typedErr(`[permission] ${rulePrefix || decision.reason}`);
|
|
46257
|
+
}
|
|
46258
|
+
if (action === "ask") {
|
|
45829
46259
|
if (!onAsk) {
|
|
45830
46260
|
return typedErr(
|
|
45831
|
-
`[permission] ${decision.reason} No interactive approval available (set ZELARI_AUTO=1 to auto-allow, or configure onPermissionAsk).`
|
|
46261
|
+
`[permission] ${rulePrefix ? `${rulePrefix} ` : ""}${decision.reason} No interactive approval available (set ZELARI_AUTO=1 to auto-allow, or configure onPermissionAsk).`
|
|
45832
46262
|
);
|
|
45833
46263
|
}
|
|
45834
46264
|
try {
|
|
@@ -46044,6 +46474,8 @@ var init_toolRegistry = __esm({
|
|
|
46044
46474
|
init_providerConfig();
|
|
46045
46475
|
init_toolPermissions();
|
|
46046
46476
|
init_lifecycleHooks();
|
|
46477
|
+
init_policyEngine();
|
|
46478
|
+
init_policyLayers();
|
|
46047
46479
|
init_toolResultCache();
|
|
46048
46480
|
init_toolTypes();
|
|
46049
46481
|
init_skills2();
|
|
@@ -46064,7 +46496,7 @@ var init_toolRegistry = __esm({
|
|
|
46064
46496
|
|
|
46065
46497
|
// src/cli/metrics.ts
|
|
46066
46498
|
import { promises as fs20, existsSync as existsSync25, statSync as statSync4, renameSync as renameSync3, appendFileSync as appendFileSync3, mkdirSync as mkdirSync14 } from "node:fs";
|
|
46067
|
-
import
|
|
46499
|
+
import path42 from "node:path";
|
|
46068
46500
|
import os9 from "node:os";
|
|
46069
46501
|
async function readMetrics(file2) {
|
|
46070
46502
|
let raw = "";
|
|
@@ -46113,8 +46545,8 @@ var init_metrics3 = __esm({
|
|
|
46113
46545
|
file;
|
|
46114
46546
|
writeQueue = Promise.resolve();
|
|
46115
46547
|
constructor(file2) {
|
|
46116
|
-
this.file = file2 ?? process.env.ANATHEMA_METRICS_FILE ??
|
|
46117
|
-
mkdirSync14(
|
|
46548
|
+
this.file = file2 ?? process.env.ANATHEMA_METRICS_FILE ?? path42.join(os9.homedir(), ".tmp", "zelari-code", "metrics.jsonl");
|
|
46549
|
+
mkdirSync14(path42.dirname(this.file), { recursive: true });
|
|
46118
46550
|
}
|
|
46119
46551
|
/** Metrics file path — doctor/summary readers use this. */
|
|
46120
46552
|
get filePath() {
|
|
@@ -46246,12 +46678,12 @@ Current policy: **lead only**.
|
|
|
46246
46678
|
// src/cli/state/fileStateStore.ts
|
|
46247
46679
|
import { createHash as createHash15, randomUUID as randomUUID3 } from "node:crypto";
|
|
46248
46680
|
import { promises as fs21 } from "node:fs";
|
|
46249
|
-
import * as
|
|
46681
|
+
import * as path45 from "node:path";
|
|
46250
46682
|
function shortId() {
|
|
46251
46683
|
return randomUUID3().replace(/-/g, "").slice(0, 12);
|
|
46252
46684
|
}
|
|
46253
46685
|
async function writeJsonAtomic(filePath, data) {
|
|
46254
|
-
await fs21.mkdir(
|
|
46686
|
+
await fs21.mkdir(path45.dirname(filePath), { recursive: true });
|
|
46255
46687
|
const tmp = `${filePath}.${process.pid}.${Date.now()}.tmp`;
|
|
46256
46688
|
await fs21.writeFile(tmp, JSON.stringify(data, null, 2) + "\n", "utf8");
|
|
46257
46689
|
await fs21.rename(tmp, filePath);
|
|
@@ -46312,11 +46744,11 @@ var init_fileStateStore = __esm({
|
|
|
46312
46744
|
indexPath = "";
|
|
46313
46745
|
async init(projectRoot) {
|
|
46314
46746
|
this.root = projectRoot;
|
|
46315
|
-
this.stateDir =
|
|
46316
|
-
this.commitsDir =
|
|
46317
|
-
this.artifactsDir =
|
|
46318
|
-
this.headPath =
|
|
46319
|
-
this.indexPath =
|
|
46747
|
+
this.stateDir = path45.join(projectRoot, ".zelari", "state");
|
|
46748
|
+
this.commitsDir = path45.join(this.stateDir, "commits");
|
|
46749
|
+
this.artifactsDir = path45.join(this.stateDir, "artifacts");
|
|
46750
|
+
this.headPath = path45.join(this.stateDir, "HEAD.json");
|
|
46751
|
+
this.indexPath = path45.join(this.stateDir, "index.jsonl");
|
|
46320
46752
|
await fs21.mkdir(this.commitsDir, { recursive: true });
|
|
46321
46753
|
await fs21.mkdir(this.artifactsDir, { recursive: true });
|
|
46322
46754
|
}
|
|
@@ -46329,13 +46761,13 @@ var init_fileStateStore = __esm({
|
|
|
46329
46761
|
const discoveries = input.discoveries ?? [];
|
|
46330
46762
|
const parent = await this.head();
|
|
46331
46763
|
const id3 = shortId();
|
|
46332
|
-
const artifactRel =
|
|
46333
|
-
const artifactAbs =
|
|
46764
|
+
const artifactRel = path45.join("artifacts", id3);
|
|
46765
|
+
const artifactAbs = path45.join(this.artifactsDir, id3);
|
|
46334
46766
|
await fs21.mkdir(artifactAbs, { recursive: true });
|
|
46335
46767
|
const summary = defaultSummary(input, discoveries);
|
|
46336
|
-
await fs21.writeFile(
|
|
46337
|
-
await writeJsonAtomic(
|
|
46338
|
-
await writeJsonAtomic(
|
|
46768
|
+
await fs21.writeFile(path45.join(artifactAbs, "summary.md"), summary + "\n", "utf8");
|
|
46769
|
+
await writeJsonAtomic(path45.join(artifactAbs, "discoveries.json"), discoveries);
|
|
46770
|
+
await writeJsonAtomic(path45.join(artifactAbs, "verification.json"), input.verification);
|
|
46339
46771
|
const meta3 = {
|
|
46340
46772
|
id: id3,
|
|
46341
46773
|
parentId: parent?.id ?? null,
|
|
@@ -46347,14 +46779,14 @@ var init_fileStateStore = __esm({
|
|
|
46347
46779
|
workspaceCheckpointId: input.workspaceCheckpointId,
|
|
46348
46780
|
verification: {
|
|
46349
46781
|
...input.verification,
|
|
46350
|
-
reportPath: input.verification.reportPath ??
|
|
46782
|
+
reportPath: input.verification.reportPath ?? path45.join(".zelari", "state", artifactRel, "verification.json").replace(/\\/g, "/")
|
|
46351
46783
|
},
|
|
46352
46784
|
changedPaths: input.changedPaths ?? [],
|
|
46353
46785
|
stablePromptHash: input.stablePromptHash,
|
|
46354
46786
|
discoveryCount: discoveries.length,
|
|
46355
46787
|
artifactDir: artifactRel.replace(/\\/g, "/")
|
|
46356
46788
|
};
|
|
46357
|
-
await writeJsonAtomic(
|
|
46789
|
+
await writeJsonAtomic(path45.join(this.commitsDir, `${id3}.json`), meta3);
|
|
46358
46790
|
await writeJsonAtomic(this.headPath, { id: id3, updatedAt: meta3.createdAt });
|
|
46359
46791
|
await fs21.appendFile(this.indexPath, JSON.stringify({ id: id3, createdAt: meta3.createdAt, label: meta3.label }) + "\n", "utf8");
|
|
46360
46792
|
return stripStored(meta3);
|
|
@@ -46365,7 +46797,7 @@ var init_fileStateStore = __esm({
|
|
|
46365
46797
|
return this.get(head.id);
|
|
46366
46798
|
}
|
|
46367
46799
|
async get(id3) {
|
|
46368
|
-
const stored = await readJsonFile(
|
|
46800
|
+
const stored = await readJsonFile(path45.join(this.commitsDir, `${id3}.json`));
|
|
46369
46801
|
return stored ? stripStored(stored) : null;
|
|
46370
46802
|
}
|
|
46371
46803
|
async list(limit = 20) {
|
|
@@ -46404,9 +46836,9 @@ var init_fileStateStore = __esm({
|
|
|
46404
46836
|
async loadDiscoveries(id3) {
|
|
46405
46837
|
const meta3 = id3 ? await this.get(id3) : await this.head();
|
|
46406
46838
|
if (!meta3) return [];
|
|
46407
|
-
const stored = await readJsonFile(
|
|
46839
|
+
const stored = await readJsonFile(path45.join(this.commitsDir, `${meta3.id}.json`));
|
|
46408
46840
|
if (!stored?.artifactDir) return [];
|
|
46409
|
-
const discPath =
|
|
46841
|
+
const discPath = path45.join(this.stateDir, stored.artifactDir, "discoveries.json");
|
|
46410
46842
|
return await readJsonFile(discPath) ?? [];
|
|
46411
46843
|
}
|
|
46412
46844
|
async materializeContext(id3, maxChars = DEFAULT_MATERIALIZE_CHARS) {
|
|
@@ -47357,7 +47789,7 @@ var init_mode = __esm({
|
|
|
47357
47789
|
});
|
|
47358
47790
|
|
|
47359
47791
|
// src/cli/headless.ts
|
|
47360
|
-
import { readFileSync as
|
|
47792
|
+
import { readFileSync as readFileSync23 } from "node:fs";
|
|
47361
47793
|
function defaultProfileForMode(mode) {
|
|
47362
47794
|
switch (mode) {
|
|
47363
47795
|
case "council":
|
|
@@ -47378,6 +47810,7 @@ function parseHeadlessFlags(argv) {
|
|
|
47378
47810
|
let phase2 = "build";
|
|
47379
47811
|
let modeExplicit = false;
|
|
47380
47812
|
let councilFlag = false;
|
|
47813
|
+
let sawModeAuto = false;
|
|
47381
47814
|
let provider;
|
|
47382
47815
|
let model;
|
|
47383
47816
|
let history2;
|
|
@@ -47412,7 +47845,7 @@ function parseHeadlessFlags(argv) {
|
|
|
47412
47845
|
const next = argv[i + 1];
|
|
47413
47846
|
if (next) {
|
|
47414
47847
|
try {
|
|
47415
|
-
const fromFile =
|
|
47848
|
+
const fromFile = readFileSync23(next, "utf-8");
|
|
47416
47849
|
if (fromFile.trim()) task = fromFile;
|
|
47417
47850
|
} catch {
|
|
47418
47851
|
}
|
|
@@ -47422,11 +47855,17 @@ function parseHeadlessFlags(argv) {
|
|
|
47422
47855
|
councilFlag = true;
|
|
47423
47856
|
} else if (arg === "--mode") {
|
|
47424
47857
|
const next = argv[i + 1];
|
|
47858
|
+
if (next !== void 0 && next.trim().toLowerCase() === "auto") {
|
|
47859
|
+
sawModeAuto = true;
|
|
47860
|
+
modeExplicit = true;
|
|
47861
|
+
i++;
|
|
47862
|
+
continue;
|
|
47863
|
+
}
|
|
47425
47864
|
const parsed = next ? parseMode(next) : null;
|
|
47426
47865
|
if (!parsed) {
|
|
47427
47866
|
return {
|
|
47428
47867
|
options: null,
|
|
47429
|
-
error: `--mode requires 'kraken', 'council', or '
|
|
47868
|
+
error: `--mode requires 'kraken', 'council', 'zelari', or 'auto' (agent=alias), got '${next ?? "(missing)"}'`
|
|
47430
47869
|
};
|
|
47431
47870
|
}
|
|
47432
47871
|
mode = parsed;
|
|
@@ -47455,7 +47894,7 @@ function parseHeadlessFlags(argv) {
|
|
|
47455
47894
|
let raw = null;
|
|
47456
47895
|
if (arg === "--history-file") {
|
|
47457
47896
|
try {
|
|
47458
|
-
raw =
|
|
47897
|
+
raw = readFileSync23(next, "utf-8");
|
|
47459
47898
|
} catch {
|
|
47460
47899
|
raw = null;
|
|
47461
47900
|
}
|
|
@@ -47550,7 +47989,7 @@ function parseHeadlessFlags(argv) {
|
|
|
47550
47989
|
const next = argv[i + 1];
|
|
47551
47990
|
if (next) {
|
|
47552
47991
|
try {
|
|
47553
|
-
const fromFile =
|
|
47992
|
+
const fromFile = readFileSync23(next, "utf-8");
|
|
47554
47993
|
if (fromFile.trim()) krakenGraph = fromFile;
|
|
47555
47994
|
} catch {
|
|
47556
47995
|
}
|
|
@@ -47588,6 +48027,7 @@ function parseHeadlessFlags(argv) {
|
|
|
47588
48027
|
mode,
|
|
47589
48028
|
phase: phase2,
|
|
47590
48029
|
useCouncil: mode === "council",
|
|
48030
|
+
...sawModeAuto ? { orchestrationAuto: true } : {},
|
|
47591
48031
|
provider,
|
|
47592
48032
|
model,
|
|
47593
48033
|
...history2 && history2.length > 0 ? { history: history2 } : {},
|
|
@@ -48115,7 +48555,7 @@ var init_claudeProvider = __esm({
|
|
|
48115
48555
|
// src/cli/memory/legacyImport.ts
|
|
48116
48556
|
import { createHash as createHash16 } from "node:crypto";
|
|
48117
48557
|
import { promises as fs22 } from "node:fs";
|
|
48118
|
-
import * as
|
|
48558
|
+
import * as path46 from "node:path";
|
|
48119
48559
|
function sourceId(fact, line) {
|
|
48120
48560
|
return `jsonl:${fact.id ?? createHash16("sha256").update(line).digest("hex")}`;
|
|
48121
48561
|
}
|
|
@@ -48133,7 +48573,7 @@ function timestamp(value) {
|
|
|
48133
48573
|
}
|
|
48134
48574
|
async function importLegacyMemoryLog(backend, service) {
|
|
48135
48575
|
const result = { found: 0, imported: 0, skipped: 0, corrupt: 0 };
|
|
48136
|
-
const logPath =
|
|
48576
|
+
const logPath = path46.join(path46.dirname(backend.databasePath), "log.jsonl");
|
|
48137
48577
|
let raw;
|
|
48138
48578
|
try {
|
|
48139
48579
|
raw = await fs22.readFile(logPath, "utf8");
|
|
@@ -48316,7 +48756,7 @@ var init_sqliteCodec = __esm({
|
|
|
48316
48756
|
// src/cli/memory/sqliteRpc.ts
|
|
48317
48757
|
import { existsSync as existsSync27 } from "node:fs";
|
|
48318
48758
|
import { fileURLToPath as fileURLToPath2, pathToFileURL as pathToFileURL2 } from "node:url";
|
|
48319
|
-
import * as
|
|
48759
|
+
import * as path47 from "node:path";
|
|
48320
48760
|
import { Worker } from "node:worker_threads";
|
|
48321
48761
|
function isBusy(error51) {
|
|
48322
48762
|
const candidate = error51;
|
|
@@ -48325,10 +48765,10 @@ function isBusy(error51) {
|
|
|
48325
48765
|
);
|
|
48326
48766
|
}
|
|
48327
48767
|
function resolveWorkerUrl() {
|
|
48328
|
-
const here =
|
|
48329
|
-
const direct =
|
|
48768
|
+
const here = path47.dirname(fileURLToPath2(import.meta.url));
|
|
48769
|
+
const direct = path47.join(here, "sqliteWorker.mjs");
|
|
48330
48770
|
if (existsSync27(direct)) return pathToFileURL2(direct);
|
|
48331
|
-
return pathToFileURL2(
|
|
48771
|
+
return pathToFileURL2(path47.join(here, "memory", "sqliteWorker.mjs"));
|
|
48332
48772
|
}
|
|
48333
48773
|
var SqliteWorkerRpc;
|
|
48334
48774
|
var init_sqliteRpc = __esm({
|
|
@@ -48617,7 +49057,7 @@ WHERE NOT EXISTS (SELECT 1 FROM memory_fts f WHERE f.node_id = n.id);
|
|
|
48617
49057
|
// src/cli/memory/sqliteBackend.ts
|
|
48618
49058
|
import { createHash as createHash17, randomUUID as randomUUID4 } from "node:crypto";
|
|
48619
49059
|
import { promises as fs23 } from "node:fs";
|
|
48620
|
-
import * as
|
|
49060
|
+
import * as path48 from "node:path";
|
|
48621
49061
|
function boundedLimit(value, fallback = 50) {
|
|
48622
49062
|
return Math.max(1, Math.min(Math.floor(value ?? fallback), 1e5));
|
|
48623
49063
|
}
|
|
@@ -48679,16 +49119,16 @@ VALUES (${Array.from({ length: 19 }, () => "?").join(",")})`;
|
|
|
48679
49119
|
try {
|
|
48680
49120
|
resolved = await fs23.realpath(projectRoot);
|
|
48681
49121
|
} catch {
|
|
48682
|
-
resolved =
|
|
49122
|
+
resolved = path48.resolve(projectRoot);
|
|
48683
49123
|
}
|
|
48684
49124
|
if (this.initialized && resolved === this.projectRoot) return;
|
|
48685
49125
|
if (this.initialized) await this.close();
|
|
48686
49126
|
const filename = this.options.filename ?? "memory.db";
|
|
48687
|
-
if (
|
|
49127
|
+
if (path48.basename(filename) !== filename || filename === "." || filename === "..") {
|
|
48688
49128
|
throw new Error("SQLite memory filename must not contain a path.");
|
|
48689
49129
|
}
|
|
48690
|
-
const zelariDirectory =
|
|
48691
|
-
const directory =
|
|
49130
|
+
const zelariDirectory = path48.join(resolved, ".zelari");
|
|
49131
|
+
const directory = path48.join(zelariDirectory, "memory");
|
|
48692
49132
|
for (const candidate of [zelariDirectory, directory]) {
|
|
48693
49133
|
let stat2;
|
|
48694
49134
|
try {
|
|
@@ -48707,12 +49147,12 @@ VALUES (${Array.from({ length: 19 }, () => "?").join(",")})`;
|
|
|
48707
49147
|
}
|
|
48708
49148
|
}
|
|
48709
49149
|
const canonicalDirectory = await fs23.realpath(directory);
|
|
48710
|
-
const relativeDirectory =
|
|
48711
|
-
if (relativeDirectory.startsWith("..") ||
|
|
49150
|
+
const relativeDirectory = path48.relative(resolved, canonicalDirectory);
|
|
49151
|
+
if (relativeDirectory.startsWith("..") || path48.isAbsolute(relativeDirectory)) {
|
|
48712
49152
|
throw new Error("SQLite memory directory resolves outside the active project.");
|
|
48713
49153
|
}
|
|
48714
49154
|
this.projectRoot = resolved;
|
|
48715
|
-
this.databasePath =
|
|
49155
|
+
this.databasePath = path48.join(canonicalDirectory, filename);
|
|
48716
49156
|
const opened = await this.rpc.open({
|
|
48717
49157
|
dbPath: this.databasePath,
|
|
48718
49158
|
schemaSql: SQLITE_MEMORY_BASE_SCHEMA,
|
|
@@ -49245,7 +49685,7 @@ __export(serviceFactory_exports, {
|
|
|
49245
49685
|
});
|
|
49246
49686
|
import { createHash as createHash18 } from "node:crypto";
|
|
49247
49687
|
import { promises as fs24 } from "node:fs";
|
|
49248
|
-
import * as
|
|
49688
|
+
import * as path49 from "node:path";
|
|
49249
49689
|
function isMemoryV2Enabled(env = process.env) {
|
|
49250
49690
|
if (env.ZELARI_MEMORY === "0") return false;
|
|
49251
49691
|
if (env.ZELARI_MEMORY_BACKEND === "file" || env.ZELARI_MEMORY_BACKEND === "jsonl") return false;
|
|
@@ -49266,7 +49706,7 @@ async function canonicalProjectId(projectRoot) {
|
|
|
49266
49706
|
try {
|
|
49267
49707
|
canonical = await fs24.realpath(projectRoot);
|
|
49268
49708
|
} catch {
|
|
49269
|
-
canonical =
|
|
49709
|
+
canonical = path49.resolve(projectRoot);
|
|
49270
49710
|
}
|
|
49271
49711
|
canonical = canonical.replace(/\\/g, "/").replace(/\/$/, "");
|
|
49272
49712
|
if (process.platform === "win32") canonical = canonical.toLocaleLowerCase("en-US");
|
|
@@ -49334,14 +49774,14 @@ var init_serviceFactory = __esm({
|
|
|
49334
49774
|
});
|
|
49335
49775
|
|
|
49336
49776
|
// src/cli/workspace/projectInstructions.ts
|
|
49337
|
-
import { existsSync as existsSync28, readFileSync as
|
|
49777
|
+
import { existsSync as existsSync28, readFileSync as readFileSync24 } from "node:fs";
|
|
49338
49778
|
import { join as join26 } from "node:path";
|
|
49339
49779
|
function loadProjectInstructions(projectRoot = process.cwd(), maxChars = MAX_CHARS) {
|
|
49340
49780
|
for (const name of CANDIDATES) {
|
|
49341
49781
|
const full = join26(projectRoot, name);
|
|
49342
49782
|
if (!existsSync28(full)) continue;
|
|
49343
49783
|
try {
|
|
49344
|
-
let raw =
|
|
49784
|
+
let raw = readFileSync24(full, "utf8");
|
|
49345
49785
|
raw = raw.replace(/\r\n/g, "\n").trim();
|
|
49346
49786
|
if (!raw) continue;
|
|
49347
49787
|
if (raw.length <= maxChars) {
|
|
@@ -49385,7 +49825,7 @@ __export(workspaceSummary_exports, {
|
|
|
49385
49825
|
buildWorkspaceSummary: () => buildWorkspaceSummary,
|
|
49386
49826
|
buildZelariReadHint: () => buildZelariReadHint
|
|
49387
49827
|
});
|
|
49388
|
-
import { existsSync as existsSync29, readFileSync as
|
|
49828
|
+
import { existsSync as existsSync29, readFileSync as readFileSync25, readdirSync as readdirSync6, statSync as statSync5 } from "node:fs";
|
|
49389
49829
|
import { join as join27, relative as relative2 } from "node:path";
|
|
49390
49830
|
function buildWorkspaceSummary(projectRoot = process.cwd(), options = {}) {
|
|
49391
49831
|
const { maxEntries = 30, maxChars = 3500, maxDeps = 24, maxScripts = 16 } = options;
|
|
@@ -49423,7 +49863,7 @@ function buildPlanSummary(projectRoot = process.cwd(), options) {
|
|
|
49423
49863
|
if (!existsSync29(planPath)) return null;
|
|
49424
49864
|
let plan;
|
|
49425
49865
|
try {
|
|
49426
|
-
plan = JSON.parse(
|
|
49866
|
+
plan = JSON.parse(readFileSync25(planPath, "utf8"));
|
|
49427
49867
|
} catch {
|
|
49428
49868
|
return null;
|
|
49429
49869
|
}
|
|
@@ -49581,7 +50021,7 @@ function readPackageJson(projectRoot) {
|
|
|
49581
50021
|
const p3 = join27(projectRoot, "package.json");
|
|
49582
50022
|
if (!existsSync29(p3)) return null;
|
|
49583
50023
|
try {
|
|
49584
|
-
return JSON.parse(
|
|
50024
|
+
return JSON.parse(readFileSync25(p3, "utf8"));
|
|
49585
50025
|
} catch {
|
|
49586
50026
|
return null;
|
|
49587
50027
|
}
|
|
@@ -49709,7 +50149,7 @@ var composeContext_exports = {};
|
|
|
49709
50149
|
__export(composeContext_exports, {
|
|
49710
50150
|
composeProjectContext: () => composeProjectContext
|
|
49711
50151
|
});
|
|
49712
|
-
import { existsSync as existsSync31, readdirSync as readdirSync7, readFileSync as
|
|
50152
|
+
import { existsSync as existsSync31, readdirSync as readdirSync7, readFileSync as readFileSync26 } from "node:fs";
|
|
49713
50153
|
import { join as join29 } from "node:path";
|
|
49714
50154
|
function cap2(text, max, label) {
|
|
49715
50155
|
if (!text || text.length <= max) return { text: text || "", truncated: false };
|
|
@@ -49850,15 +50290,15 @@ function readDurableHeadSync(projectRoot) {
|
|
|
49850
50290
|
try {
|
|
49851
50291
|
const headPath = join29(projectRoot, ".zelari", "state", "HEAD.json");
|
|
49852
50292
|
if (!existsSync31(headPath)) return "";
|
|
49853
|
-
const head = JSON.parse(
|
|
50293
|
+
const head = JSON.parse(readFileSync26(headPath, "utf8"));
|
|
49854
50294
|
if (!head?.id) return "";
|
|
49855
50295
|
const metaPath = join29(projectRoot, ".zelari", "state", "commits", `${head.id}.json`);
|
|
49856
50296
|
if (!existsSync31(metaPath)) return "";
|
|
49857
|
-
const meta3 = JSON.parse(
|
|
50297
|
+
const meta3 = JSON.parse(readFileSync26(metaPath, "utf8"));
|
|
49858
50298
|
const discPath = meta3.artifactDir ? join29(projectRoot, ".zelari", "state", meta3.artifactDir, "discoveries.json") : join29(projectRoot, ".zelari", "state", "artifacts", head.id, "discoveries.json");
|
|
49859
50299
|
let discoveries = [];
|
|
49860
50300
|
if (existsSync31(discPath)) {
|
|
49861
|
-
discoveries = JSON.parse(
|
|
50301
|
+
discoveries = JSON.parse(readFileSync26(discPath, "utf8"));
|
|
49862
50302
|
}
|
|
49863
50303
|
const reusable = discoveries.filter((d) => d.reusable !== false);
|
|
49864
50304
|
const lines = [
|
|
@@ -49891,13 +50331,13 @@ var planDetect_exports = {};
|
|
|
49891
50331
|
__export(planDetect_exports, {
|
|
49892
50332
|
hasWorkspacePlan: () => hasWorkspacePlan
|
|
49893
50333
|
});
|
|
49894
|
-
import { existsSync as existsSync32, readFileSync as
|
|
50334
|
+
import { existsSync as existsSync32, readFileSync as readFileSync27 } from "node:fs";
|
|
49895
50335
|
import { join as join30 } from "node:path";
|
|
49896
50336
|
function hasWorkspacePlan(projectRoot = process.cwd()) {
|
|
49897
50337
|
const planPath = join30(resolveWorkspaceRoot(projectRoot), "plan.json");
|
|
49898
50338
|
if (!existsSync32(planPath)) return false;
|
|
49899
50339
|
try {
|
|
49900
|
-
const parsed = JSON.parse(
|
|
50340
|
+
const parsed = JSON.parse(readFileSync27(planPath, "utf8"));
|
|
49901
50341
|
return Array.isArray(parsed.phases) && parsed.phases.length > 0;
|
|
49902
50342
|
} catch {
|
|
49903
50343
|
return false;
|
|
@@ -49959,7 +50399,7 @@ import {
|
|
|
49959
50399
|
existsSync as existsSync33,
|
|
49960
50400
|
readdirSync as readdirSync8,
|
|
49961
50401
|
writeFileSync as writeFileSync17,
|
|
49962
|
-
readFileSync as
|
|
50402
|
+
readFileSync as readFileSync28,
|
|
49963
50403
|
mkdirSync as mkdirSync15,
|
|
49964
50404
|
renameSync as renameSync4
|
|
49965
50405
|
} from "node:fs";
|
|
@@ -49980,7 +50420,7 @@ function readPlan(ctx) {
|
|
|
49980
50420
|
if (existsSync33(jsonPath)) {
|
|
49981
50421
|
try {
|
|
49982
50422
|
const parsed = JSON.parse(
|
|
49983
|
-
|
|
50423
|
+
readFileSync28(jsonPath, "utf8")
|
|
49984
50424
|
);
|
|
49985
50425
|
const { phases, tasks, milestones, ...root } = parsed;
|
|
49986
50426
|
return {
|
|
@@ -49992,8 +50432,8 @@ function readPlan(ctx) {
|
|
|
49992
50432
|
} catch {
|
|
49993
50433
|
}
|
|
49994
50434
|
}
|
|
49995
|
-
const
|
|
49996
|
-
const doc = ctx.storage.readIfExists(
|
|
50435
|
+
const path74 = workspaceFile(ctx.rootDir, "plan");
|
|
50436
|
+
const doc = ctx.storage.readIfExists(path74);
|
|
49997
50437
|
if (!doc) return { phases: [], tasks: [], milestones: [] };
|
|
49998
50438
|
const meta3 = doc.meta;
|
|
49999
50439
|
return {
|
|
@@ -50171,7 +50611,7 @@ function addMilestoneRecord(ctx, summary, input) {
|
|
|
50171
50611
|
dueDate: input.dueDate,
|
|
50172
50612
|
targetVersion: version2
|
|
50173
50613
|
});
|
|
50174
|
-
const
|
|
50614
|
+
const path74 = join31(ctx.rootDir, "milestones", `${id3}.md`);
|
|
50175
50615
|
const meta3 = {
|
|
50176
50616
|
kind: "milestone",
|
|
50177
50617
|
id: id3,
|
|
@@ -50188,7 +50628,7 @@ function addMilestoneRecord(ctx, summary, input) {
|
|
|
50188
50628
|
`Target version: ${version2}`,
|
|
50189
50629
|
""
|
|
50190
50630
|
].join("\n");
|
|
50191
|
-
ctx.storage.write(
|
|
50631
|
+
ctx.storage.write(path74, meta3, body);
|
|
50192
50632
|
return { id: id3, created: true };
|
|
50193
50633
|
}
|
|
50194
50634
|
function readPlanSummary(ctx) {
|
|
@@ -50392,7 +50832,7 @@ function addIdeaStub(ctx) {
|
|
|
50392
50832
|
const tags = args["tags"] ?? [];
|
|
50393
50833
|
const category = args["category"] ?? "General";
|
|
50394
50834
|
const id3 = `${nextAdrId(ctx)}-${slugify3(title)}`;
|
|
50395
|
-
const
|
|
50835
|
+
const path74 = workspaceArtifact(ctx.rootDir, "decisions", id3);
|
|
50396
50836
|
const meta3 = {
|
|
50397
50837
|
kind: "adr",
|
|
50398
50838
|
status: "proposed",
|
|
@@ -50418,7 +50858,7 @@ function addIdeaStub(ctx) {
|
|
|
50418
50858
|
...consequences.map((c) => `- ${c}`),
|
|
50419
50859
|
""
|
|
50420
50860
|
].join("\n");
|
|
50421
|
-
ctx.storage.write(
|
|
50861
|
+
ctx.storage.write(path74, meta3, body);
|
|
50422
50862
|
return `ADR ${id3} created: "${title}". Status: proposed. Promote to accepted via /update ADR or manual edit.`;
|
|
50423
50863
|
});
|
|
50424
50864
|
}
|
|
@@ -50500,14 +50940,14 @@ function createDocumentStub(ctx) {
|
|
|
50500
50940
|
ctx.storage.write(risksPath, riskMeta, content);
|
|
50501
50941
|
return `Document "${title}" created at risks.md (workspace root).`;
|
|
50502
50942
|
}
|
|
50503
|
-
const
|
|
50943
|
+
const path74 = workspaceArtifact(ctx.rootDir, "docs", slug);
|
|
50504
50944
|
const meta3 = {
|
|
50505
50945
|
kind: "doc",
|
|
50506
50946
|
id: slug,
|
|
50507
50947
|
date: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10),
|
|
50508
50948
|
tags
|
|
50509
50949
|
};
|
|
50510
|
-
ctx.storage.write(
|
|
50950
|
+
ctx.storage.write(path74, meta3, content);
|
|
50511
50951
|
return `Document "${title}" created at docs/${slug}.md.`;
|
|
50512
50952
|
});
|
|
50513
50953
|
}
|
|
@@ -50544,7 +50984,7 @@ function searchDocumentsStub(ctx) {
|
|
|
50544
50984
|
const results = [];
|
|
50545
50985
|
for (const file2 of files) {
|
|
50546
50986
|
if (!existsSync33(file2)) continue;
|
|
50547
|
-
const raw =
|
|
50987
|
+
const raw = readFileSync28(file2, "utf8");
|
|
50548
50988
|
const content = raw.toLowerCase();
|
|
50549
50989
|
let idx = -1;
|
|
50550
50990
|
let matchLen = 0;
|
|
@@ -50883,21 +51323,21 @@ var init_mcpClient = __esm({
|
|
|
50883
51323
|
import {
|
|
50884
51324
|
existsSync as existsSync34,
|
|
50885
51325
|
mkdirSync as mkdirSync16,
|
|
50886
|
-
readFileSync as
|
|
51326
|
+
readFileSync as readFileSync29,
|
|
50887
51327
|
writeFileSync as writeFileSync18
|
|
50888
51328
|
} from "node:fs";
|
|
50889
51329
|
import { dirname as dirname9, join as join32 } from "node:path";
|
|
50890
|
-
import { homedir as
|
|
51330
|
+
import { homedir as homedir11 } from "node:os";
|
|
50891
51331
|
function getUserMcpPath() {
|
|
50892
|
-
return join32(
|
|
51332
|
+
return join32(homedir11(), ".zelari-code", "mcp.json");
|
|
50893
51333
|
}
|
|
50894
51334
|
function getProjectMcpPath(projectRoot) {
|
|
50895
51335
|
return join32(projectRoot, ".zelari", "mcp.json");
|
|
50896
51336
|
}
|
|
50897
|
-
function readFile4(
|
|
50898
|
-
if (!existsSync34(
|
|
51337
|
+
function readFile4(path74) {
|
|
51338
|
+
if (!existsSync34(path74)) return {};
|
|
50899
51339
|
try {
|
|
50900
|
-
const parsed = JSON.parse(
|
|
51340
|
+
const parsed = JSON.parse(readFileSync29(path74, "utf8"));
|
|
50901
51341
|
const out = {};
|
|
50902
51342
|
for (const [name, cfg] of Object.entries(parsed.mcpServers ?? {})) {
|
|
50903
51343
|
if (!cfg || typeof cfg.command !== "string" || !cfg.command.trim()) continue;
|
|
@@ -50913,10 +51353,10 @@ function readFile4(path72) {
|
|
|
50913
51353
|
return {};
|
|
50914
51354
|
}
|
|
50915
51355
|
}
|
|
50916
|
-
function
|
|
50917
|
-
mkdirSync16(dirname9(
|
|
51356
|
+
function writeFile3(path74, servers) {
|
|
51357
|
+
mkdirSync16(dirname9(path74), { recursive: true });
|
|
50918
51358
|
const body = { mcpServers: servers };
|
|
50919
|
-
writeFileSync18(
|
|
51359
|
+
writeFileSync18(path74, `${JSON.stringify(body, null, 2)}
|
|
50920
51360
|
`, "utf8");
|
|
50921
51361
|
}
|
|
50922
51362
|
function listMcpServers(projectRoot) {
|
|
@@ -50949,9 +51389,9 @@ function upsertMcpServer(opts) {
|
|
|
50949
51389
|
if (!opts.config.command?.trim()) {
|
|
50950
51390
|
return { ok: false, error: "command is required" };
|
|
50951
51391
|
}
|
|
50952
|
-
let
|
|
51392
|
+
let path74;
|
|
50953
51393
|
if (opts.scope === "user") {
|
|
50954
|
-
|
|
51394
|
+
path74 = getUserMcpPath();
|
|
50955
51395
|
} else {
|
|
50956
51396
|
const root = opts.projectRoot?.trim();
|
|
50957
51397
|
if (!root) {
|
|
@@ -50960,30 +51400,30 @@ function upsertMcpServer(opts) {
|
|
|
50960
51400
|
error: "projectRoot required for project scope (Open Folder first)"
|
|
50961
51401
|
};
|
|
50962
51402
|
}
|
|
50963
|
-
|
|
51403
|
+
path74 = getProjectMcpPath(root);
|
|
50964
51404
|
}
|
|
50965
|
-
const current = readFile4(
|
|
51405
|
+
const current = readFile4(path74);
|
|
50966
51406
|
current[name] = {
|
|
50967
51407
|
command: opts.config.command.trim(),
|
|
50968
51408
|
args: opts.config.args,
|
|
50969
51409
|
env: opts.config.env,
|
|
50970
51410
|
enabled: opts.config.enabled !== false
|
|
50971
51411
|
};
|
|
50972
|
-
|
|
50973
|
-
return { ok: true, path:
|
|
51412
|
+
writeFile3(path74, current);
|
|
51413
|
+
return { ok: true, path: path74 };
|
|
50974
51414
|
}
|
|
50975
51415
|
function removeMcpServer(opts) {
|
|
50976
|
-
const
|
|
50977
|
-
if (!
|
|
51416
|
+
const path74 = opts.scope === "user" ? getUserMcpPath() : opts.projectRoot ? getProjectMcpPath(opts.projectRoot) : null;
|
|
51417
|
+
if (!path74) {
|
|
50978
51418
|
return { ok: false, error: "projectRoot required for project scope" };
|
|
50979
51419
|
}
|
|
50980
|
-
const current = readFile4(
|
|
51420
|
+
const current = readFile4(path74);
|
|
50981
51421
|
if (!(opts.name in current)) {
|
|
50982
|
-
return { ok: false, error: `Server "${opts.name}" not found in ${
|
|
51422
|
+
return { ok: false, error: `Server "${opts.name}" not found in ${path74}` };
|
|
50983
51423
|
}
|
|
50984
51424
|
delete current[opts.name];
|
|
50985
|
-
|
|
50986
|
-
return { ok: true, path:
|
|
51425
|
+
writeFile3(path74, current);
|
|
51426
|
+
return { ok: true, path: path74 };
|
|
50987
51427
|
}
|
|
50988
51428
|
var init_mcpConfigIo = __esm({
|
|
50989
51429
|
"src/cli/mcp/mcpConfigIo.ts"() {
|
|
@@ -51125,14 +51565,14 @@ __export(mcpManager_exports, {
|
|
|
51125
51565
|
readMcpConfig: () => readMcpConfig,
|
|
51126
51566
|
registerMcpTools: () => registerMcpTools
|
|
51127
51567
|
});
|
|
51128
|
-
import { existsSync as existsSync35, readFileSync as
|
|
51568
|
+
import { existsSync as existsSync35, readFileSync as readFileSync30 } from "node:fs";
|
|
51129
51569
|
import { join as join33 } from "node:path";
|
|
51130
|
-
import { homedir as
|
|
51570
|
+
import { homedir as homedir12 } from "node:os";
|
|
51131
51571
|
function readMcpConfig(projectRoot = process.cwd(), opts) {
|
|
51132
51572
|
const merged = {};
|
|
51133
51573
|
const paths = [];
|
|
51134
51574
|
if (process.env["ZELARI_MCP_USER"] !== "0") {
|
|
51135
|
-
paths.push(join33(
|
|
51575
|
+
paths.push(join33(homedir12(), ".zelari-code", "mcp.json"));
|
|
51136
51576
|
}
|
|
51137
51577
|
if (!opts?.skipProjectMcp) {
|
|
51138
51578
|
paths.push(join33(projectRoot, ".zelari", "mcp.json"));
|
|
@@ -51140,7 +51580,7 @@ function readMcpConfig(projectRoot = process.cwd(), opts) {
|
|
|
51140
51580
|
for (const p3 of paths) {
|
|
51141
51581
|
if (!existsSync35(p3)) continue;
|
|
51142
51582
|
try {
|
|
51143
|
-
const parsed = JSON.parse(
|
|
51583
|
+
const parsed = JSON.parse(readFileSync30(p3, "utf8"));
|
|
51144
51584
|
for (const [name, cfg] of Object.entries(parsed.mcpServers ?? {})) {
|
|
51145
51585
|
if (!cfg || typeof cfg.command !== "string" || cfg.command.length === 0) continue;
|
|
51146
51586
|
merged[name] = cfg;
|
|
@@ -51379,15 +51819,15 @@ __export(agentsMd_exports, {
|
|
|
51379
51819
|
serializeAgentsMd: () => serializeAgentsMd,
|
|
51380
51820
|
updateAgentsMd: () => updateAgentsMd
|
|
51381
51821
|
});
|
|
51382
|
-
import { existsSync as existsSync36, readFileSync as
|
|
51822
|
+
import { existsSync as existsSync36, readFileSync as readFileSync31, writeFileSync as writeFileSync19 } from "node:fs";
|
|
51383
51823
|
import { createHash as createHash19 } from "node:crypto";
|
|
51384
51824
|
import { join as join34 } from "node:path";
|
|
51385
51825
|
import { readFile as readFile5 } from "node:fs/promises";
|
|
51386
51826
|
async function readPackageJson2(projectRoot) {
|
|
51387
|
-
const
|
|
51388
|
-
if (!existsSync36(
|
|
51827
|
+
const path74 = join34(projectRoot, "package.json");
|
|
51828
|
+
if (!existsSync36(path74)) return null;
|
|
51389
51829
|
try {
|
|
51390
|
-
return JSON.parse(await readFile5(
|
|
51830
|
+
return JSON.parse(await readFile5(path74, "utf8"));
|
|
51391
51831
|
} catch {
|
|
51392
51832
|
return null;
|
|
51393
51833
|
}
|
|
@@ -51437,7 +51877,7 @@ async function genConventions(ctx) {
|
|
|
51437
51877
|
const lines = [];
|
|
51438
51878
|
const claudeMd = join34(ctx.projectRoot, "CLAUDE.MD");
|
|
51439
51879
|
if (existsSync36(claudeMd)) {
|
|
51440
|
-
const content =
|
|
51880
|
+
const content = readFileSync31(claudeMd, "utf8");
|
|
51441
51881
|
const match = content.match(/## Architecture rules[\s\S]+?(?=\n## |\n*$)/);
|
|
51442
51882
|
if (match) {
|
|
51443
51883
|
lines.push('<!-- Extracted from CLAUDE.MD "Architecture rules" -->');
|
|
@@ -51469,9 +51909,9 @@ async function genBuild(ctx) {
|
|
|
51469
51909
|
].join("\n");
|
|
51470
51910
|
}
|
|
51471
51911
|
async function genOpenQuestions(ctx) {
|
|
51472
|
-
const
|
|
51473
|
-
if (!existsSync36(
|
|
51474
|
-
const content =
|
|
51912
|
+
const path74 = join34(ctx.rootDir, "risks.md");
|
|
51913
|
+
if (!existsSync36(path74)) return "_No open questions._";
|
|
51914
|
+
const content = readFileSync31(path74, "utf8");
|
|
51475
51915
|
const lines = content.split("\n");
|
|
51476
51916
|
const questions = [];
|
|
51477
51917
|
let currentTitle = "";
|
|
@@ -51547,7 +51987,7 @@ function titleCase(id3) {
|
|
|
51547
51987
|
async function updateAgentsMd(ctx, projectRoot) {
|
|
51548
51988
|
const agentsPath = join34(projectRoot, "AGENTS.MD");
|
|
51549
51989
|
if (existsSync36(agentsPath)) {
|
|
51550
|
-
const content =
|
|
51990
|
+
const content = readFileSync31(agentsPath, "utf8");
|
|
51551
51991
|
const hasAnyMarker = AUTO_SECTIONS.some((id3) => content.includes(MARKER_OPEN(id3)));
|
|
51552
51992
|
if (!hasAnyMarker) {
|
|
51553
51993
|
return {
|
|
@@ -51563,7 +52003,7 @@ async function updateAgentsMd(ctx, projectRoot) {
|
|
|
51563
52003
|
}
|
|
51564
52004
|
let manualContent = "";
|
|
51565
52005
|
if (existsSync36(agentsPath)) {
|
|
51566
|
-
const { manualBlocks } = parseAgentsMd(
|
|
52006
|
+
const { manualBlocks } = parseAgentsMd(readFileSync31(agentsPath, "utf8"));
|
|
51567
52007
|
manualContent = manualBlocks.after;
|
|
51568
52008
|
} else {
|
|
51569
52009
|
const projectName2 = projectName(projectRoot);
|
|
@@ -51579,7 +52019,7 @@ async function updateAgentsMd(ctx, projectRoot) {
|
|
|
51579
52019
|
""
|
|
51580
52020
|
].join("\n");
|
|
51581
52021
|
}
|
|
51582
|
-
const oldContent = existsSync36(agentsPath) ?
|
|
52022
|
+
const oldContent = existsSync36(agentsPath) ? readFileSync31(agentsPath, "utf8") : "";
|
|
51583
52023
|
const { sections: oldSections } = parseAgentsMd(oldContent);
|
|
51584
52024
|
const changedSections = [];
|
|
51585
52025
|
for (const id3 of AUTO_SECTIONS) {
|
|
@@ -51716,7 +52156,7 @@ var init_completeDesign = __esm({
|
|
|
51716
52156
|
});
|
|
51717
52157
|
|
|
51718
52158
|
// src/cli/workspace/planDriftCheck.ts
|
|
51719
|
-
import { existsSync as existsSync37, readFileSync as
|
|
52159
|
+
import { existsSync as existsSync37, readFileSync as readFileSync32, readdirSync as readdirSync9, statSync as statSync6, writeFileSync as writeFileSync20 } from "node:fs";
|
|
51720
52160
|
import { join as join35 } from "node:path";
|
|
51721
52161
|
function findCanonicalDoc(rootDir) {
|
|
51722
52162
|
const docsDir = join35(rootDir, "docs");
|
|
@@ -51745,9 +52185,9 @@ function versionKey(value) {
|
|
|
51745
52185
|
function firstString2(v) {
|
|
51746
52186
|
return typeof v === "string" && v.trim().length > 0 ? v : null;
|
|
51747
52187
|
}
|
|
51748
|
-
function readFileSyncSafe(
|
|
52188
|
+
function readFileSyncSafe(path74) {
|
|
51749
52189
|
try {
|
|
51750
|
-
return
|
|
52190
|
+
return readFileSync32(path74, "utf8");
|
|
51751
52191
|
} catch {
|
|
51752
52192
|
return null;
|
|
51753
52193
|
}
|
|
@@ -51762,7 +52202,7 @@ async function runPlanDriftCheck(rootDir) {
|
|
|
51762
52202
|
}
|
|
51763
52203
|
let plan;
|
|
51764
52204
|
try {
|
|
51765
|
-
plan = JSON.parse(
|
|
52205
|
+
plan = JSON.parse(readFileSync32(planPath, "utf8"));
|
|
51766
52206
|
} catch {
|
|
51767
52207
|
return { ran: false, reason: ".zelari/plan.json corrupt" };
|
|
51768
52208
|
}
|
|
@@ -51888,7 +52328,7 @@ var init_planDriftCheck = __esm({
|
|
|
51888
52328
|
|
|
51889
52329
|
// src/cli/workspace/projectSmoke.ts
|
|
51890
52330
|
import { spawn as spawn14 } from "node:child_process";
|
|
51891
|
-
import { existsSync as existsSync38, readFileSync as
|
|
52331
|
+
import { existsSync as existsSync38, readFileSync as readFileSync33 } from "node:fs";
|
|
51892
52332
|
import { join as join36 } from "node:path";
|
|
51893
52333
|
function pickSmokeScript(scripts) {
|
|
51894
52334
|
if (!scripts) return null;
|
|
@@ -51907,7 +52347,7 @@ async function runProjectSmoke(projectRoot, timeoutMs2 = DEFAULT_TIMEOUT_MS3) {
|
|
|
51907
52347
|
}
|
|
51908
52348
|
let scripts = {};
|
|
51909
52349
|
try {
|
|
51910
|
-
const pkg = JSON.parse(
|
|
52350
|
+
const pkg = JSON.parse(readFileSync33(pkgPath, "utf8"));
|
|
51911
52351
|
scripts = pkg.scripts ?? {};
|
|
51912
52352
|
} catch {
|
|
51913
52353
|
return { ran: false, reason: "package.json unreadable (skipped)" };
|
|
@@ -51995,7 +52435,7 @@ __export(postCouncilHook_exports, {
|
|
|
51995
52435
|
runPostCouncilHook: () => runPostCouncilHook
|
|
51996
52436
|
});
|
|
51997
52437
|
import { spawn as spawn15 } from "node:child_process";
|
|
51998
|
-
import { existsSync as existsSync39, readFileSync as
|
|
52438
|
+
import { existsSync as existsSync39, readFileSync as readFileSync34 } from "node:fs";
|
|
51999
52439
|
import { join as join37 } from "node:path";
|
|
52000
52440
|
async function runCompleteDesignPostProcessor(ctx, options) {
|
|
52001
52441
|
if (options?.runMode === "implementation") {
|
|
@@ -52017,7 +52457,7 @@ async function runCompleteDesignPostProcessor(ctx, options) {
|
|
|
52017
52457
|
}
|
|
52018
52458
|
let phaseCount = 0;
|
|
52019
52459
|
try {
|
|
52020
|
-
const parsed = JSON.parse(
|
|
52460
|
+
const parsed = JSON.parse(readFileSync34(planJsonPath2, "utf8"));
|
|
52021
52461
|
phaseCount = Array.isArray(parsed.phases) ? parsed.phases.length : 0;
|
|
52022
52462
|
} catch {
|
|
52023
52463
|
return { ran: false, reason: ".zelari/plan.json corrupt" };
|
|
@@ -52210,8 +52650,8 @@ async function runPostCouncilHook(ctx, options) {
|
|
|
52210
52650
|
sources: scope.sources
|
|
52211
52651
|
} : void 0
|
|
52212
52652
|
});
|
|
52213
|
-
const
|
|
52214
|
-
completionHook = { ran: true, path:
|
|
52653
|
+
const path74 = writeCouncilCompletion(ctx.rootDir, completion);
|
|
52654
|
+
completionHook = { ran: true, path: path74, completion };
|
|
52215
52655
|
} catch (err) {
|
|
52216
52656
|
completionHook = {
|
|
52217
52657
|
ran: true,
|
|
@@ -52252,11 +52692,11 @@ __export(councilFeedback_exports, {
|
|
|
52252
52692
|
import {
|
|
52253
52693
|
promises as fs25,
|
|
52254
52694
|
existsSync as existsSync40,
|
|
52255
|
-
readFileSync as
|
|
52695
|
+
readFileSync as readFileSync35,
|
|
52256
52696
|
writeFileSync as writeFileSync21,
|
|
52257
52697
|
mkdirSync as mkdirSync17
|
|
52258
52698
|
} from "node:fs";
|
|
52259
|
-
import
|
|
52699
|
+
import path50 from "node:path";
|
|
52260
52700
|
import os10 from "node:os";
|
|
52261
52701
|
var FeedbackStore;
|
|
52262
52702
|
var init_councilFeedback = __esm({
|
|
@@ -52267,7 +52707,7 @@ var init_councilFeedback = __esm({
|
|
|
52267
52707
|
now;
|
|
52268
52708
|
entries = [];
|
|
52269
52709
|
constructor(options = {}) {
|
|
52270
|
-
this.file = options.file ?? (process.env.ANATHEMA_COUNCIL_FEEDBACK_FILE ??
|
|
52710
|
+
this.file = options.file ?? (process.env.ANATHEMA_COUNCIL_FEEDBACK_FILE ?? path50.join(os10.homedir(), ".tmp", "zelari-code", "council-feedback.json"));
|
|
52271
52711
|
this.now = options.now ?? Date.now;
|
|
52272
52712
|
this.load();
|
|
52273
52713
|
}
|
|
@@ -52362,7 +52802,7 @@ var init_councilFeedback = __esm({
|
|
|
52362
52802
|
load() {
|
|
52363
52803
|
if (!existsSync40(this.file)) return;
|
|
52364
52804
|
try {
|
|
52365
|
-
const raw =
|
|
52805
|
+
const raw = readFileSync35(this.file, "utf-8");
|
|
52366
52806
|
const parsed = JSON.parse(raw);
|
|
52367
52807
|
if (parsed && Array.isArray(parsed.entries)) {
|
|
52368
52808
|
this.entries = parsed.entries.filter(
|
|
@@ -52373,7 +52813,7 @@ var init_councilFeedback = __esm({
|
|
|
52373
52813
|
}
|
|
52374
52814
|
}
|
|
52375
52815
|
save() {
|
|
52376
|
-
mkdirSync17(
|
|
52816
|
+
mkdirSync17(path50.dirname(this.file), { recursive: true });
|
|
52377
52817
|
writeFileSync21(
|
|
52378
52818
|
this.file,
|
|
52379
52819
|
JSON.stringify({ entries: this.entries }, null, 2),
|
|
@@ -52441,7 +52881,7 @@ import { execFile as execFile3 } from "node:child_process";
|
|
|
52441
52881
|
import { promisify as promisify2 } from "node:util";
|
|
52442
52882
|
import { mkdtempSync, rmSync as rmSync2 } from "node:fs";
|
|
52443
52883
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
52444
|
-
import
|
|
52884
|
+
import path51 from "node:path";
|
|
52445
52885
|
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
52446
52886
|
async function git3(cwd, args, env) {
|
|
52447
52887
|
const { stdout } = await execFileAsync2("git", ["-C", cwd, ...args], {
|
|
@@ -52461,8 +52901,8 @@ async function isGitRepo(cwd) {
|
|
|
52461
52901
|
return await gitSafe(cwd, ["rev-parse", "--is-inside-work-tree"]) === "true";
|
|
52462
52902
|
}
|
|
52463
52903
|
async function withTempIndex(fn) {
|
|
52464
|
-
const dir = mkdtempSync(
|
|
52465
|
-
const indexFile =
|
|
52904
|
+
const dir = mkdtempSync(path51.join(tmpdir2(), "zelari-ckpt-"));
|
|
52905
|
+
const indexFile = path51.join(dir, "index");
|
|
52466
52906
|
try {
|
|
52467
52907
|
return await fn(indexFile);
|
|
52468
52908
|
} finally {
|
|
@@ -52553,7 +52993,7 @@ async function restoreCheckpoint(cwd, id3) {
|
|
|
52553
52993
|
const deleted = [];
|
|
52554
52994
|
for (const rel2 of added) {
|
|
52555
52995
|
try {
|
|
52556
|
-
rmSync2(
|
|
52996
|
+
rmSync2(path51.join(cwd, rel2), { force: true });
|
|
52557
52997
|
deleted.push(rel2);
|
|
52558
52998
|
} catch {
|
|
52559
52999
|
}
|
|
@@ -52654,7 +53094,7 @@ __export(fileBackend_exports, {
|
|
|
52654
53094
|
});
|
|
52655
53095
|
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
52656
53096
|
import { promises as fs26 } from "node:fs";
|
|
52657
|
-
import * as
|
|
53097
|
+
import * as path52 from "node:path";
|
|
52658
53098
|
function tokenize(text) {
|
|
52659
53099
|
return text.toLowerCase().split(/[^\p{L}\p{N}]+/u).filter((t) => t.length >= 3);
|
|
52660
53100
|
}
|
|
@@ -52705,8 +53145,8 @@ var init_fileBackend = __esm({
|
|
|
52705
53145
|
logPath = "";
|
|
52706
53146
|
memoryDir = "";
|
|
52707
53147
|
async init(projectRoot) {
|
|
52708
|
-
this.memoryDir =
|
|
52709
|
-
this.logPath =
|
|
53148
|
+
this.memoryDir = path52.join(projectRoot, ".zelari", "memory");
|
|
53149
|
+
this.logPath = path52.join(this.memoryDir, "log.jsonl");
|
|
52710
53150
|
await fs26.mkdir(this.memoryDir, { recursive: true });
|
|
52711
53151
|
}
|
|
52712
53152
|
async add(content, metadata2 = {}, graph) {
|
|
@@ -52779,12 +53219,12 @@ var init_fileBackend = __esm({
|
|
|
52779
53219
|
|
|
52780
53220
|
// src/cli/traceStore.ts
|
|
52781
53221
|
import { promises as fs27 } from "node:fs";
|
|
52782
|
-
import * as
|
|
53222
|
+
import * as path53 from "node:path";
|
|
52783
53223
|
function traceDir(projectRoot) {
|
|
52784
|
-
return
|
|
53224
|
+
return path53.join(projectRoot, ".zelari", "trace");
|
|
52785
53225
|
}
|
|
52786
53226
|
function tracePath(projectRoot, missionId) {
|
|
52787
|
-
return
|
|
53227
|
+
return path53.join(traceDir(projectRoot), `${missionId}.json`);
|
|
52788
53228
|
}
|
|
52789
53229
|
async function saveTrace(projectRoot, missionId, entries) {
|
|
52790
53230
|
const dir = traceDir(projectRoot);
|
|
@@ -52821,7 +53261,7 @@ __export(zelariMission_exports, {
|
|
|
52821
53261
|
});
|
|
52822
53262
|
import { randomUUID as randomUUID7 } from "node:crypto";
|
|
52823
53263
|
import { promises as fs28 } from "node:fs";
|
|
52824
|
-
import * as
|
|
53264
|
+
import * as path54 from "node:path";
|
|
52825
53265
|
function resolveMaxIterations(env = process.env) {
|
|
52826
53266
|
const raw = env.ZELARI_MISSION_MAX_ITER;
|
|
52827
53267
|
const n = raw ? Number.parseInt(raw, 10) : DEFAULT_MAX_ITER;
|
|
@@ -52864,10 +53304,10 @@ function isMissionAutoStart(env = process.env) {
|
|
|
52864
53304
|
return env.ZELARI_MISSION_AUTO === "1";
|
|
52865
53305
|
}
|
|
52866
53306
|
async function writeMissionState(projectRoot, state3) {
|
|
52867
|
-
const dir =
|
|
53307
|
+
const dir = path54.join(projectRoot, ".zelari");
|
|
52868
53308
|
await fs28.mkdir(dir, { recursive: true });
|
|
52869
53309
|
await fs28.writeFile(
|
|
52870
|
-
|
|
53310
|
+
path54.join(dir, "mission-state.json"),
|
|
52871
53311
|
JSON.stringify(state3, null, 2) + "\n",
|
|
52872
53312
|
"utf8"
|
|
52873
53313
|
);
|
|
@@ -53542,7 +53982,7 @@ function safeSocketPath(socketPath) {
|
|
|
53542
53982
|
return socketPath.trim();
|
|
53543
53983
|
}
|
|
53544
53984
|
function startPermissionBroker(socketPath, handlers, opts) {
|
|
53545
|
-
const
|
|
53985
|
+
const path74 = safeSocketPath(socketPath);
|
|
53546
53986
|
const requestTimeoutMs = opts?.requestTimeoutMs ?? PERMISSION_BROKER_DEFAULT_TIMEOUT_MS;
|
|
53547
53987
|
const sockets = /* @__PURE__ */ new Set();
|
|
53548
53988
|
const server = createServer2((socket) => {
|
|
@@ -53642,10 +54082,10 @@ function startPermissionBroker(socketPath, handlers, opts) {
|
|
|
53642
54082
|
return new Promise((resolve7, reject) => {
|
|
53643
54083
|
const onError = (err) => reject(err);
|
|
53644
54084
|
server.once("error", onError);
|
|
53645
|
-
server.listen(
|
|
54085
|
+
server.listen(path74, () => {
|
|
53646
54086
|
server.removeListener("error", onError);
|
|
53647
54087
|
resolve7({
|
|
53648
|
-
socketPath:
|
|
54088
|
+
socketPath: path74,
|
|
53649
54089
|
stop: () => new Promise((res) => {
|
|
53650
54090
|
for (const s of sockets) s.destroy();
|
|
53651
54091
|
sockets.clear();
|
|
@@ -53656,7 +54096,7 @@ function startPermissionBroker(socketPath, handlers, opts) {
|
|
|
53656
54096
|
if (done) return;
|
|
53657
54097
|
done = true;
|
|
53658
54098
|
if (process.platform !== "win32") {
|
|
53659
|
-
unlink(
|
|
54099
|
+
unlink(path74, () => res());
|
|
53660
54100
|
} else {
|
|
53661
54101
|
res();
|
|
53662
54102
|
}
|
|
@@ -53669,11 +54109,11 @@ function startPermissionBroker(socketPath, handlers, opts) {
|
|
|
53669
54109
|
});
|
|
53670
54110
|
}
|
|
53671
54111
|
function requestBrokerAsk(socketPath, ask, opts) {
|
|
53672
|
-
const
|
|
54112
|
+
const path74 = safeSocketPath(socketPath);
|
|
53673
54113
|
const requestTimeoutMs = opts?.requestTimeoutMs ?? PERMISSION_BROKER_DEFAULT_TIMEOUT_MS;
|
|
53674
54114
|
const connectTimeoutMs = opts?.connectTimeoutMs ?? PERMISSION_BROKER_DEFAULT_CONNECT_TIMEOUT_MS;
|
|
53675
54115
|
return new Promise((resolve7, reject) => {
|
|
53676
|
-
const socket = connect(
|
|
54116
|
+
const socket = connect(path74);
|
|
53677
54117
|
let buffer = "";
|
|
53678
54118
|
let settled = false;
|
|
53679
54119
|
const settle = (fn) => {
|
|
@@ -53688,7 +54128,7 @@ function requestBrokerAsk(socketPath, ask, opts) {
|
|
|
53688
54128
|
settle(
|
|
53689
54129
|
() => reject(
|
|
53690
54130
|
new Error(
|
|
53691
|
-
`permission broker unavailable at "${
|
|
54131
|
+
`permission broker unavailable at "${path74}" (connect timed out after ${connectTimeoutMs}ms)`
|
|
53692
54132
|
)
|
|
53693
54133
|
)
|
|
53694
54134
|
);
|
|
@@ -54431,9 +54871,9 @@ __export(graphMemory_exports, {
|
|
|
54431
54871
|
toGraphSnapshot: () => toGraphSnapshot
|
|
54432
54872
|
});
|
|
54433
54873
|
import { promises as fs31 } from "node:fs";
|
|
54434
|
-
import
|
|
54874
|
+
import path58 from "node:path";
|
|
54435
54875
|
function snapshotPath(cwd) {
|
|
54436
|
-
return
|
|
54876
|
+
return path58.join(cwd, SNAPSHOT_DIR, SNAPSHOT_FILE);
|
|
54437
54877
|
}
|
|
54438
54878
|
function toGraphSnapshot(graph, opts) {
|
|
54439
54879
|
const unresolved = (opts.unresolvedFindings ?? []).map((u) => ({
|
|
@@ -54460,7 +54900,7 @@ async function saveGraphSnapshot(cwd, snapshot) {
|
|
|
54460
54900
|
try {
|
|
54461
54901
|
await fs31.access(cwd);
|
|
54462
54902
|
const file2 = snapshotPath(cwd);
|
|
54463
|
-
await fs31.mkdir(
|
|
54903
|
+
await fs31.mkdir(path58.dirname(file2), { recursive: true });
|
|
54464
54904
|
await fs31.writeFile(file2, JSON.stringify(snapshot, null, 2) + "\n", "utf8");
|
|
54465
54905
|
} catch {
|
|
54466
54906
|
}
|
|
@@ -54527,7 +54967,7 @@ var SNAPSHOT_DIR, SNAPSHOT_FILE, MAX_SNAPSHOT_FINDINGS_CHARS;
|
|
|
54527
54967
|
var init_graphMemory = __esm({
|
|
54528
54968
|
"src/cli/kraken/graphMemory.ts"() {
|
|
54529
54969
|
"use strict";
|
|
54530
|
-
SNAPSHOT_DIR =
|
|
54970
|
+
SNAPSHOT_DIR = path58.join(".zelari", "kraken");
|
|
54531
54971
|
SNAPSHOT_FILE = "last-graph.json";
|
|
54532
54972
|
MAX_SNAPSHOT_FINDINGS_CHARS = 400;
|
|
54533
54973
|
}
|
|
@@ -54543,14 +54983,14 @@ var init_tentacle = __esm({
|
|
|
54543
54983
|
|
|
54544
54984
|
// src/cli/kraken/workbench.ts
|
|
54545
54985
|
import { promises as fs32 } from "node:fs";
|
|
54546
|
-
import
|
|
54986
|
+
import path59 from "node:path";
|
|
54547
54987
|
function isWorkbenchEnabled(env = process.env) {
|
|
54548
54988
|
const v = (env.ZELARI_KRAKEN_WORKBENCH ?? "1").trim().toLowerCase();
|
|
54549
54989
|
if (v === "0" || v === "false" || v === "no" || v === "off") return false;
|
|
54550
54990
|
return true;
|
|
54551
54991
|
}
|
|
54552
54992
|
function workbenchPath(cwd, graphId) {
|
|
54553
|
-
return
|
|
54993
|
+
return path59.join(cwd, ".zelari", "radio", `workbench-${graphId}.md`);
|
|
54554
54994
|
}
|
|
54555
54995
|
function countByStatus2(nodes) {
|
|
54556
54996
|
const out = { pending: 0, running: 0, done: 0, error: 0, skipped: 0 };
|
|
@@ -54713,7 +55153,7 @@ var init_workbench = __esm({
|
|
|
54713
55153
|
if (!this.enabled) return null;
|
|
54714
55154
|
if (!this.dirty && this.lastWrite) return this.lastWrite;
|
|
54715
55155
|
const out = workbenchPath(this.cwd, this.graphId);
|
|
54716
|
-
await fs32.mkdir(
|
|
55156
|
+
await fs32.mkdir(path59.dirname(out), { recursive: true });
|
|
54717
55157
|
const body = this.render();
|
|
54718
55158
|
const tmp = `${out}.${process.pid}.${Date.now()}.tmp`;
|
|
54719
55159
|
await fs32.writeFile(tmp, body, "utf8");
|
|
@@ -54910,7 +55350,7 @@ __export(executor_exports, {
|
|
|
54910
55350
|
thoroughnessForKind: () => thoroughnessForKind
|
|
54911
55351
|
});
|
|
54912
55352
|
import { existsSync as existsSync41 } from "node:fs";
|
|
54913
|
-
import
|
|
55353
|
+
import path60 from "node:path";
|
|
54914
55354
|
function resolveMaxParallel(env = process.env) {
|
|
54915
55355
|
const raw = env.ZELARI_KRAKEN_MAX_PARALLEL;
|
|
54916
55356
|
if (raw === void 0 || raw === "") return DEFAULT_MAX_PARALLEL;
|
|
@@ -54968,7 +55408,7 @@ function isWorldModelGateEnabled(cwd, env = process.env, checksExists = defaultC
|
|
|
54968
55408
|
}
|
|
54969
55409
|
function defaultChecksExists(cwd) {
|
|
54970
55410
|
try {
|
|
54971
|
-
return existsSync41(
|
|
55411
|
+
return existsSync41(path60.join(cwd, ".zelari", "world", "checks.json"));
|
|
54972
55412
|
} catch {
|
|
54973
55413
|
return false;
|
|
54974
55414
|
}
|
|
@@ -56364,17 +56804,17 @@ var init_prereqChecks = __esm({
|
|
|
56364
56804
|
});
|
|
56365
56805
|
|
|
56366
56806
|
// src/cli/plugins/prefs.ts
|
|
56367
|
-
import { existsSync as existsSync43, readFileSync as
|
|
56368
|
-
import
|
|
56807
|
+
import { existsSync as existsSync43, readFileSync as readFileSync36, writeFileSync as writeFileSync22, mkdirSync as mkdirSync18 } from "node:fs";
|
|
56808
|
+
import path63 from "node:path";
|
|
56369
56809
|
import os11 from "node:os";
|
|
56370
56810
|
function getPluginPrefsPath() {
|
|
56371
|
-
return process.env.ZELARI_PLUGINS_PREFS_FILE ??
|
|
56811
|
+
return process.env.ZELARI_PLUGINS_PREFS_FILE ?? path63.join(os11.homedir(), ".tmp", "zelari-code", "plugins.json");
|
|
56372
56812
|
}
|
|
56373
56813
|
function getPluginPrefs() {
|
|
56374
56814
|
const file2 = getPluginPrefsPath();
|
|
56375
56815
|
try {
|
|
56376
56816
|
if (!existsSync43(file2)) return { ...DEFAULTS2, dontAskAgain: {} };
|
|
56377
|
-
const raw =
|
|
56817
|
+
const raw = readFileSync36(file2, "utf-8");
|
|
56378
56818
|
const parsed = JSON.parse(raw);
|
|
56379
56819
|
if (parsed && typeof parsed === "object" && parsed.dontAskAgain && typeof parsed.dontAskAgain === "object") {
|
|
56380
56820
|
const clean = {};
|
|
@@ -56389,7 +56829,7 @@ function getPluginPrefs() {
|
|
|
56389
56829
|
}
|
|
56390
56830
|
function writePluginPrefs(prefs) {
|
|
56391
56831
|
const file2 = getPluginPrefsPath();
|
|
56392
|
-
mkdirSync18(
|
|
56832
|
+
mkdirSync18(path63.dirname(file2), { recursive: true });
|
|
56393
56833
|
writeFileSync22(file2, JSON.stringify(prefs, null, 2), {
|
|
56394
56834
|
encoding: "utf-8",
|
|
56395
56835
|
mode: 384
|
|
@@ -56426,7 +56866,7 @@ __export(registry_exports, {
|
|
|
56426
56866
|
isBinaryOnPath: () => isBinaryOnPath
|
|
56427
56867
|
});
|
|
56428
56868
|
import { existsSync as existsSync44 } from "node:fs";
|
|
56429
|
-
import
|
|
56869
|
+
import path64 from "node:path";
|
|
56430
56870
|
function detectLocalBin(bin) {
|
|
56431
56871
|
return (cwd) => {
|
|
56432
56872
|
try {
|
|
@@ -56444,7 +56884,7 @@ function isBinaryOnPath(bin, opts = {}) {
|
|
|
56444
56884
|
const platform = opts.platform ?? process.platform;
|
|
56445
56885
|
const exists = opts.exists ?? existsSync44;
|
|
56446
56886
|
const pathEnv = opts.pathEnv ?? process.env.PATH ?? "";
|
|
56447
|
-
const pathMod = platform === "win32" ?
|
|
56887
|
+
const pathMod = platform === "win32" ? path64.win32 : path64.posix;
|
|
56448
56888
|
const sep4 = platform === "win32" ? ";" : ":";
|
|
56449
56889
|
const dirs = pathEnv.split(sep4).filter((d) => d.length > 0);
|
|
56450
56890
|
const candidates = [bin];
|
|
@@ -57176,7 +57616,7 @@ __export(atMentions_exports, {
|
|
|
57176
57616
|
extractAtMentions: () => extractAtMentions,
|
|
57177
57617
|
hasAtMentions: () => hasAtMentions
|
|
57178
57618
|
});
|
|
57179
|
-
import { existsSync as existsSync47, readFileSync as
|
|
57619
|
+
import { existsSync as existsSync47, readFileSync as readFileSync38, statSync as statSync9 } from "node:fs";
|
|
57180
57620
|
import { basename as basename4, isAbsolute as isAbsolute4, relative as relative5, resolve as resolve5, sep as sep2 } from "node:path";
|
|
57181
57621
|
function isImagePath(abs) {
|
|
57182
57622
|
const ext = abs.split(".").pop()?.toLowerCase() ?? "";
|
|
@@ -57282,7 +57722,7 @@ function resolveMention(token, cwd) {
|
|
|
57282
57722
|
note: `image too large (${Math.round(st.size / 1024)} KB) \u2014 path only`
|
|
57283
57723
|
};
|
|
57284
57724
|
}
|
|
57285
|
-
const dataBase64 =
|
|
57725
|
+
const dataBase64 = readFileSync38(abs).toString("base64");
|
|
57286
57726
|
return {
|
|
57287
57727
|
raw: token,
|
|
57288
57728
|
path: rel2,
|
|
@@ -57293,7 +57733,7 @@ function resolveMention(token, cwd) {
|
|
|
57293
57733
|
};
|
|
57294
57734
|
}
|
|
57295
57735
|
try {
|
|
57296
|
-
const buf =
|
|
57736
|
+
const buf = readFileSync38(abs);
|
|
57297
57737
|
const head = buf.subarray(0, 800).toString("utf8");
|
|
57298
57738
|
if (!isProbablyText(abs, head)) {
|
|
57299
57739
|
return {
|
|
@@ -58278,9 +58718,9 @@ __export(triggerLock_exports, {
|
|
|
58278
58718
|
releaseLock: () => releaseLock
|
|
58279
58719
|
});
|
|
58280
58720
|
import { promises as fs40 } from "node:fs";
|
|
58281
|
-
import * as
|
|
58721
|
+
import * as path69 from "node:path";
|
|
58282
58722
|
function lockPath(projectRoot) {
|
|
58283
|
-
return
|
|
58723
|
+
return path69.join(projectRoot, ".zelari", "trigger.lock");
|
|
58284
58724
|
}
|
|
58285
58725
|
function isPidAlive(pid) {
|
|
58286
58726
|
try {
|
|
@@ -58293,7 +58733,7 @@ function isPidAlive(pid) {
|
|
|
58293
58733
|
}
|
|
58294
58734
|
async function acquireLock(projectRoot, now = () => /* @__PURE__ */ new Date()) {
|
|
58295
58735
|
const lp = lockPath(projectRoot);
|
|
58296
|
-
const dir =
|
|
58736
|
+
const dir = path69.dirname(lp);
|
|
58297
58737
|
await fs40.mkdir(dir, { recursive: true });
|
|
58298
58738
|
try {
|
|
58299
58739
|
const raw = await fs40.readFile(lp, "utf8");
|
|
@@ -58721,12 +59161,12 @@ import {
|
|
|
58721
59161
|
existsSync as existsSync49,
|
|
58722
59162
|
mkdirSync as mkdirSync21,
|
|
58723
59163
|
readdirSync as readdirSync10,
|
|
58724
|
-
readFileSync as
|
|
59164
|
+
readFileSync as readFileSync39,
|
|
58725
59165
|
rmSync as rmSync4,
|
|
58726
59166
|
writeFileSync as writeFileSync24
|
|
58727
59167
|
} from "node:fs";
|
|
58728
59168
|
import { dirname as dirname13, join as join45 } from "node:path";
|
|
58729
|
-
import { homedir as
|
|
59169
|
+
import { homedir as homedir13 } from "node:os";
|
|
58730
59170
|
function ensureBuiltinSkillsLoadedSync() {
|
|
58731
59171
|
if (builtinsLoaded) return;
|
|
58732
59172
|
for (const spec of BUILTIN_SKILL_MODULES) {
|
|
@@ -58737,7 +59177,7 @@ function ensureBuiltinSkillsLoadedSync() {
|
|
|
58737
59177
|
}
|
|
58738
59178
|
}
|
|
58739
59179
|
function getUserSkillsDir() {
|
|
58740
|
-
return join45(
|
|
59180
|
+
return join45(homedir13(), ".zelari-code", "skills");
|
|
58741
59181
|
}
|
|
58742
59182
|
function getProjectSkillsDir(projectRoot) {
|
|
58743
59183
|
return join45(projectRoot, ".zelari", "skills");
|
|
@@ -58803,7 +59243,7 @@ function scanSkillsDir(dir, projectRoot, seen, out) {
|
|
|
58803
59243
|
const skillPath = skillFilePath(dir, entry);
|
|
58804
59244
|
if (!existsSync49(skillPath)) continue;
|
|
58805
59245
|
try {
|
|
58806
|
-
const parsed = parseSkillMd(
|
|
59246
|
+
const parsed = parseSkillMd(readFileSync39(skillPath, "utf8"), skillPath);
|
|
58807
59247
|
if (!parsed) continue;
|
|
58808
59248
|
if (seen.has(parsed.name)) continue;
|
|
58809
59249
|
seen.add(parsed.name);
|
|
@@ -58887,7 +59327,7 @@ function upsertSkill(opts) {
|
|
|
58887
59327
|
}
|
|
58888
59328
|
dir = getProjectSkillsDir(root);
|
|
58889
59329
|
}
|
|
58890
|
-
const
|
|
59330
|
+
const path74 = skillFilePath(dir, name);
|
|
58891
59331
|
const content = serializeSkillMd({
|
|
58892
59332
|
name,
|
|
58893
59333
|
description,
|
|
@@ -58896,13 +59336,13 @@ function upsertSkill(opts) {
|
|
|
58896
59336
|
tools: opts.tools,
|
|
58897
59337
|
cost: opts.cost
|
|
58898
59338
|
});
|
|
58899
|
-
const parsed = parseSkillMd(content,
|
|
59339
|
+
const parsed = parseSkillMd(content, path74);
|
|
58900
59340
|
if (!parsed) {
|
|
58901
59341
|
return { ok: false, error: "Generated SKILL.md failed validation" };
|
|
58902
59342
|
}
|
|
58903
|
-
mkdirSync21(dirname13(
|
|
58904
|
-
writeFileSync24(
|
|
58905
|
-
return { ok: true, path:
|
|
59343
|
+
mkdirSync21(dirname13(path74), { recursive: true });
|
|
59344
|
+
writeFileSync24(path74, content, "utf8");
|
|
59345
|
+
return { ok: true, path: path74 };
|
|
58906
59346
|
}
|
|
58907
59347
|
function removeSkill(opts) {
|
|
58908
59348
|
const name = opts.name.trim().toLowerCase();
|
|
@@ -58920,8 +59360,8 @@ function removeSkill(opts) {
|
|
|
58920
59360
|
dir = getProjectSkillsDir(root);
|
|
58921
59361
|
}
|
|
58922
59362
|
const skillDir = join45(dir, name);
|
|
58923
|
-
const
|
|
58924
|
-
if (!existsSync49(
|
|
59363
|
+
const path74 = skillFilePath(dir, name);
|
|
59364
|
+
if (!existsSync49(path74) && !existsSync49(skillDir)) {
|
|
58925
59365
|
return { ok: false, error: `Skill "${name}" not found in ${dir}` };
|
|
58926
59366
|
}
|
|
58927
59367
|
try {
|
|
@@ -58932,7 +59372,7 @@ function removeSkill(opts) {
|
|
|
58932
59372
|
error: err instanceof Error ? err.message : String(err)
|
|
58933
59373
|
};
|
|
58934
59374
|
}
|
|
58935
|
-
return { ok: true, path:
|
|
59375
|
+
return { ok: true, path: path74 };
|
|
58936
59376
|
}
|
|
58937
59377
|
var NAME_RE, BUILTIN_SKILL_MODULES, builtinsLoaded;
|
|
58938
59378
|
var init_skillConfigIo = __esm({
|
|
@@ -59051,7 +59491,7 @@ var init_jsonApi = __esm({
|
|
|
59051
59491
|
});
|
|
59052
59492
|
|
|
59053
59493
|
// src/cli/memory/mcpAdapter.ts
|
|
59054
|
-
import * as
|
|
59494
|
+
import * as path71 from "node:path";
|
|
59055
59495
|
var id2, projectId, source, SearchSchema, AddSchema, LinkSchema, RetractSchema, MEMORY_MCP_TOOLS, MemoryMcpAdapter;
|
|
59056
59496
|
var init_mcpAdapter = __esm({
|
|
59057
59497
|
"src/cli/memory/mcpAdapter.ts"() {
|
|
@@ -59221,8 +59661,8 @@ var init_mcpAdapter = __esm({
|
|
|
59221
59661
|
this.takeWrite();
|
|
59222
59662
|
const externalFile = args.source?.file;
|
|
59223
59663
|
if (externalFile) {
|
|
59224
|
-
const normalized =
|
|
59225
|
-
if (
|
|
59664
|
+
const normalized = path71.normalize(externalFile);
|
|
59665
|
+
if (path71.isAbsolute(normalized) || normalized === ".." || normalized.startsWith(`..${path71.sep}`)) {
|
|
59226
59666
|
throw new Error("source.file must be project-relative and cannot escape the project");
|
|
59227
59667
|
}
|
|
59228
59668
|
}
|
|
@@ -59728,14 +60168,14 @@ var init_permissionCli = __esm({
|
|
|
59728
60168
|
import {
|
|
59729
60169
|
existsSync as existsSync50,
|
|
59730
60170
|
mkdirSync as mkdirSync22,
|
|
59731
|
-
readFileSync as
|
|
60171
|
+
readFileSync as readFileSync40,
|
|
59732
60172
|
writeFileSync as writeFileSync25
|
|
59733
60173
|
} from "node:fs";
|
|
59734
60174
|
import { join as join46 } from "node:path";
|
|
59735
|
-
import { homedir as
|
|
60175
|
+
import { homedir as homedir14 } from "node:os";
|
|
59736
60176
|
import { createHash as createHash20, randomBytes as randomBytes6, timingSafeEqual } from "node:crypto";
|
|
59737
60177
|
function getZelariHome() {
|
|
59738
|
-
return join46(
|
|
60178
|
+
return join46(homedir14(), ".zelari-code");
|
|
59739
60179
|
}
|
|
59740
60180
|
function getCompanionConfigPath() {
|
|
59741
60181
|
return join46(getZelariHome(), "companion.json");
|
|
@@ -59750,12 +60190,12 @@ function ensureHome() {
|
|
|
59750
60190
|
}
|
|
59751
60191
|
}
|
|
59752
60192
|
function loadCompanionConfig() {
|
|
59753
|
-
const
|
|
59754
|
-
if (!existsSync50(
|
|
60193
|
+
const path74 = getCompanionConfigPath();
|
|
60194
|
+
if (!existsSync50(path74)) {
|
|
59755
60195
|
return { projects: [] };
|
|
59756
60196
|
}
|
|
59757
60197
|
try {
|
|
59758
|
-
const raw = JSON.parse(
|
|
60198
|
+
const raw = JSON.parse(readFileSync40(path74, "utf8"));
|
|
59759
60199
|
const projects = Array.isArray(raw.projects) ? raw.projects.filter(
|
|
59760
60200
|
(p3) => p3 && typeof p3.path === "string" && p3.path.trim() && typeof (p3.id ?? p3.name) === "string"
|
|
59761
60201
|
).map((p3) => ({
|
|
@@ -59793,16 +60233,16 @@ function loadOrCreateToken(explicit) {
|
|
|
59793
60233
|
return { token: explicit.trim(), created: false };
|
|
59794
60234
|
}
|
|
59795
60235
|
ensureHome();
|
|
59796
|
-
const
|
|
59797
|
-
if (existsSync50(
|
|
59798
|
-
const t =
|
|
60236
|
+
const path74 = getCompanionTokenPath();
|
|
60237
|
+
if (existsSync50(path74)) {
|
|
60238
|
+
const t = readFileSync40(path74, "utf8").trim();
|
|
59799
60239
|
if (t) return { token: t, created: false };
|
|
59800
60240
|
}
|
|
59801
60241
|
const token = randomBytes6(24).toString("base64url");
|
|
59802
|
-
writeFileSync25(
|
|
60242
|
+
writeFileSync25(path74, token + "\n", "utf8");
|
|
59803
60243
|
try {
|
|
59804
60244
|
const fs42 = __require("node:fs");
|
|
59805
|
-
fs42.chmodSync?.(
|
|
60245
|
+
fs42.chmodSync?.(path74, 384);
|
|
59806
60246
|
} catch {
|
|
59807
60247
|
}
|
|
59808
60248
|
return { token, created: true };
|
|
@@ -59827,17 +60267,17 @@ function mergeProjects(cfg, extraPaths) {
|
|
|
59827
60267
|
byId.set(p3.id, p3);
|
|
59828
60268
|
}
|
|
59829
60269
|
for (const raw of extraPaths) {
|
|
59830
|
-
const
|
|
59831
|
-
if (!
|
|
59832
|
-
let id3 = slugFromPath(
|
|
60270
|
+
const path74 = raw.trim();
|
|
60271
|
+
if (!path74) continue;
|
|
60272
|
+
let id3 = slugFromPath(path74);
|
|
59833
60273
|
let n = 2;
|
|
59834
|
-
while (byId.has(id3) && byId.get(id3).path !==
|
|
59835
|
-
id3 = `${slugFromPath(
|
|
60274
|
+
while (byId.has(id3) && byId.get(id3).path !== path74) {
|
|
60275
|
+
id3 = `${slugFromPath(path74)}-${n++}`;
|
|
59836
60276
|
}
|
|
59837
60277
|
byId.set(id3, {
|
|
59838
60278
|
id: id3,
|
|
59839
|
-
name: slugFromPath(
|
|
59840
|
-
path:
|
|
60279
|
+
name: slugFromPath(path74),
|
|
60280
|
+
path: path74
|
|
59841
60281
|
});
|
|
59842
60282
|
}
|
|
59843
60283
|
return [...byId.values()];
|
|
@@ -60214,9 +60654,9 @@ async function runCompanionServe(opts = {}) {
|
|
|
60214
60654
|
return;
|
|
60215
60655
|
}
|
|
60216
60656
|
const url2 = parseUrl(req);
|
|
60217
|
-
const
|
|
60657
|
+
const path74 = url2.pathname.replace(/\/+$/, "") || "/";
|
|
60218
60658
|
try {
|
|
60219
|
-
if (req.method === "GET" && (
|
|
60659
|
+
if (req.method === "GET" && (path74 === "/health" || path74 === "/v1/health")) {
|
|
60220
60660
|
sendJson2(res, 200, {
|
|
60221
60661
|
ok: true,
|
|
60222
60662
|
service: "zelari-companion",
|
|
@@ -60228,18 +60668,18 @@ async function runCompanionServe(opts = {}) {
|
|
|
60228
60668
|
});
|
|
60229
60669
|
return;
|
|
60230
60670
|
}
|
|
60231
|
-
if (
|
|
60671
|
+
if (path74.startsWith("/v1")) {
|
|
60232
60672
|
if (!tokenMatches(token, getBearer(req))) {
|
|
60233
60673
|
sendJson2(res, 401, { ok: false, error: "unauthorized" });
|
|
60234
60674
|
return;
|
|
60235
60675
|
}
|
|
60236
60676
|
}
|
|
60237
|
-
if (req.method === "GET" &&
|
|
60677
|
+
if (req.method === "GET" && path74 === "/v1/config") {
|
|
60238
60678
|
const snap = buildDesktopConfigSnapshot();
|
|
60239
60679
|
sendJson2(res, 200, { ok: true, ...snap });
|
|
60240
60680
|
return;
|
|
60241
60681
|
}
|
|
60242
|
-
if (req.method === "GET" &&
|
|
60682
|
+
if (req.method === "GET" && path74 === "/v1/projects") {
|
|
60243
60683
|
sendJson2(res, 200, {
|
|
60244
60684
|
ok: true,
|
|
60245
60685
|
projects: projects.map((p3) => ({
|
|
@@ -60250,7 +60690,7 @@ async function runCompanionServe(opts = {}) {
|
|
|
60250
60690
|
});
|
|
60251
60691
|
return;
|
|
60252
60692
|
}
|
|
60253
|
-
if (req.method === "GET" &&
|
|
60693
|
+
if (req.method === "GET" && path74 === "/v1/runs") {
|
|
60254
60694
|
sendJson2(res, 200, {
|
|
60255
60695
|
ok: true,
|
|
60256
60696
|
active: runs.getActive(),
|
|
@@ -60268,7 +60708,7 @@ async function runCompanionServe(opts = {}) {
|
|
|
60268
60708
|
});
|
|
60269
60709
|
return;
|
|
60270
60710
|
}
|
|
60271
|
-
if (req.method === "POST" &&
|
|
60711
|
+
if (req.method === "POST" && path74 === "/v1/runs") {
|
|
60272
60712
|
const raw = await readBody(req);
|
|
60273
60713
|
let body = {};
|
|
60274
60714
|
try {
|
|
@@ -60315,7 +60755,7 @@ async function runCompanionServe(opts = {}) {
|
|
|
60315
60755
|
});
|
|
60316
60756
|
return;
|
|
60317
60757
|
}
|
|
60318
|
-
const eventsMatch = /^\/v1\/runs\/([^/]+)\/events$/.exec(
|
|
60758
|
+
const eventsMatch = /^\/v1\/runs\/([^/]+)\/events$/.exec(path74);
|
|
60319
60759
|
if (req.method === "GET" && eventsMatch) {
|
|
60320
60760
|
const runId = eventsMatch[1];
|
|
60321
60761
|
const run = runs.getRun(runId);
|
|
@@ -60380,7 +60820,7 @@ async function runCompanionServe(opts = {}) {
|
|
|
60380
60820
|
}, 500);
|
|
60381
60821
|
return;
|
|
60382
60822
|
}
|
|
60383
|
-
const cancelMatch = /^\/v1\/runs\/([^/]+)\/cancel$/.exec(
|
|
60823
|
+
const cancelMatch = /^\/v1\/runs\/([^/]+)\/cancel$/.exec(path74);
|
|
60384
60824
|
if (req.method === "POST" && cancelMatch) {
|
|
60385
60825
|
const runId = cancelMatch[1];
|
|
60386
60826
|
const result = runs.cancel(runId);
|
|
@@ -60530,26 +60970,26 @@ __export(doctor_exports, {
|
|
|
60530
60970
|
runDoctor: () => runDoctor
|
|
60531
60971
|
});
|
|
60532
60972
|
import { execSync as execSync2 } from "node:child_process";
|
|
60533
|
-
import { existsSync as existsSync52, readFileSync as
|
|
60973
|
+
import { existsSync as existsSync52, readFileSync as readFileSync41, readlinkSync, statSync as statSync10 } from "node:fs";
|
|
60534
60974
|
import { createRequire as createRequire3 } from "node:module";
|
|
60535
60975
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
60536
|
-
import
|
|
60976
|
+
import path72 from "node:path";
|
|
60537
60977
|
function findPackageRoot(start) {
|
|
60538
60978
|
let dir = start;
|
|
60539
60979
|
for (let i = 0; i < 6; i += 1) {
|
|
60540
|
-
const candidate =
|
|
60980
|
+
const candidate = path72.join(dir, "package.json");
|
|
60541
60981
|
if (existsSync52(candidate)) {
|
|
60542
60982
|
try {
|
|
60543
|
-
const pkg = JSON.parse(
|
|
60983
|
+
const pkg = JSON.parse(readFileSync41(candidate, "utf8"));
|
|
60544
60984
|
if (pkg.name === "zelari-code") return dir;
|
|
60545
60985
|
} catch {
|
|
60546
60986
|
}
|
|
60547
60987
|
}
|
|
60548
|
-
const parent =
|
|
60988
|
+
const parent = path72.dirname(dir);
|
|
60549
60989
|
if (parent === dir) break;
|
|
60550
60990
|
dir = parent;
|
|
60551
60991
|
}
|
|
60552
|
-
return
|
|
60992
|
+
return path72.resolve(__dirname3, "..", "..", "..");
|
|
60553
60993
|
}
|
|
60554
60994
|
function tryExec(cmd) {
|
|
60555
60995
|
try {
|
|
@@ -60563,8 +61003,8 @@ function tryExec(cmd) {
|
|
|
60563
61003
|
}
|
|
60564
61004
|
function readPackageJson3() {
|
|
60565
61005
|
try {
|
|
60566
|
-
const pkgPath =
|
|
60567
|
-
return JSON.parse(
|
|
61006
|
+
const pkgPath = path72.join(packageRoot, "package.json");
|
|
61007
|
+
return JSON.parse(readFileSync41(pkgPath, "utf8"));
|
|
60568
61008
|
} catch {
|
|
60569
61009
|
return null;
|
|
60570
61010
|
}
|
|
@@ -60579,7 +61019,7 @@ function checkShim(pkgName) {
|
|
|
60579
61019
|
}
|
|
60580
61020
|
const isWin = process.platform === "win32";
|
|
60581
61021
|
const shimName = isWin ? "zelari-code.cmd" : "zelari-code";
|
|
60582
|
-
const shimPath =
|
|
61022
|
+
const shimPath = path72.join(prefix, shimName);
|
|
60583
61023
|
if (!existsSync52(shimPath)) {
|
|
60584
61024
|
return FAIL(
|
|
60585
61025
|
`shim not found at ${shimPath}
|
|
@@ -60589,7 +61029,7 @@ function checkShim(pkgName) {
|
|
|
60589
61029
|
try {
|
|
60590
61030
|
const st = statSync10(shimPath);
|
|
60591
61031
|
if (isWin) {
|
|
60592
|
-
const content =
|
|
61032
|
+
const content = readFileSync41(shimPath, "utf8");
|
|
60593
61033
|
if (content.includes(`${pkgName}\\bin\\`) || content.includes(`${pkgName}/bin/`)) {
|
|
60594
61034
|
return OK(`shim OK at ${shimPath} (${st.size} bytes)`);
|
|
60595
61035
|
}
|
|
@@ -60607,8 +61047,8 @@ function checkShim(pkgName) {
|
|
|
60607
61047
|
fix: npm install -g ${pkgName}@latest --force`
|
|
60608
61048
|
);
|
|
60609
61049
|
}
|
|
60610
|
-
const resolved =
|
|
60611
|
-
const expected =
|
|
61050
|
+
const resolved = path72.resolve(path72.dirname(shimPath), target);
|
|
61051
|
+
const expected = path72.join(
|
|
60612
61052
|
prefix,
|
|
60613
61053
|
"node_modules",
|
|
60614
61054
|
pkgName,
|
|
@@ -60647,7 +61087,7 @@ function checkNode(pkg) {
|
|
|
60647
61087
|
return OK(`node ${raw}`);
|
|
60648
61088
|
}
|
|
60649
61089
|
function checkBundle() {
|
|
60650
|
-
const bundle =
|
|
61090
|
+
const bundle = path72.join(packageRoot, "dist", "cli", "main.bundled.js");
|
|
60651
61091
|
if (!existsSync52(bundle)) {
|
|
60652
61092
|
return FAIL(
|
|
60653
61093
|
`dist/cli/main.bundled.js missing at ${bundle}
|
|
@@ -60668,7 +61108,7 @@ function checkRuntimeDeps() {
|
|
|
60668
61108
|
const missing = [];
|
|
60669
61109
|
for (const dep of required2) {
|
|
60670
61110
|
try {
|
|
60671
|
-
const localReq = createRequire3(
|
|
61111
|
+
const localReq = createRequire3(path72.join(packageRoot, "package.json"));
|
|
60672
61112
|
localReq.resolve(dep);
|
|
60673
61113
|
} catch {
|
|
60674
61114
|
missing.push(dep);
|
|
@@ -60868,7 +61308,7 @@ var init_doctor = __esm({
|
|
|
60868
61308
|
init_metrics3();
|
|
60869
61309
|
init_contextGrowthSummary();
|
|
60870
61310
|
require3 = createRequire3(import.meta.url);
|
|
60871
|
-
__dirname3 =
|
|
61311
|
+
__dirname3 = path72.dirname(fileURLToPath3(import.meta.url));
|
|
60872
61312
|
packageRoot = findPackageRoot(__dirname3);
|
|
60873
61313
|
OK = (message) => ({
|
|
60874
61314
|
ok: true,
|
|
@@ -61052,15 +61492,15 @@ __export(inspect_exports, {
|
|
|
61052
61492
|
collectInspectReport: () => collectInspectReport,
|
|
61053
61493
|
runInspect: () => runInspect
|
|
61054
61494
|
});
|
|
61055
|
-
import
|
|
61056
|
-
import { existsSync as existsSync53, readFileSync as
|
|
61057
|
-
import { homedir as
|
|
61495
|
+
import path73 from "node:path";
|
|
61496
|
+
import { existsSync as existsSync53, readFileSync as readFileSync42, readdirSync as readdirSync11 } from "node:fs";
|
|
61497
|
+
import { homedir as homedir15 } from "node:os";
|
|
61058
61498
|
async function collectInspectReport(cwd = process.cwd()) {
|
|
61059
61499
|
ensureBuiltinSkillsLoadedSync();
|
|
61060
61500
|
const snap = listSkillsSnapshot(cwd);
|
|
61061
61501
|
const mcp = listMcpServers(cwd);
|
|
61062
|
-
const userMcpPath =
|
|
61063
|
-
const projectMcpPath =
|
|
61502
|
+
const userMcpPath = path73.join(homedir15(), ".zelari-code", "mcp.json");
|
|
61503
|
+
const projectMcpPath = path73.join(cwd, ".zelari", "mcp.json");
|
|
61064
61504
|
const globalHooks = globalHooksDir();
|
|
61065
61505
|
const projectHooks = projectHooksDir(cwd);
|
|
61066
61506
|
const projectTrusted = isFolderTrusted(cwd);
|
|
@@ -61088,9 +61528,9 @@ async function collectInspectReport(cwd = process.cwd()) {
|
|
|
61088
61528
|
configSources: [
|
|
61089
61529
|
{ path: userMcpPath, exists: existsSync53(userMcpPath) },
|
|
61090
61530
|
{ path: projectMcpPath, exists: existsSync53(projectMcpPath) },
|
|
61091
|
-
{ path:
|
|
61092
|
-
{ path:
|
|
61093
|
-
{ path:
|
|
61531
|
+
{ path: path73.join(homedir15(), ".zelari-code", "provider.json"), exists: existsSync53(path73.join(homedir15(), ".zelari-code", "provider.json")) },
|
|
61532
|
+
{ path: path73.join(cwd, ".zelari", "AGENTS.md"), exists: existsSync53(path73.join(cwd, ".zelari", "AGENTS.md")) },
|
|
61533
|
+
{ path: path73.join(cwd, "AGENTS.md"), exists: existsSync53(path73.join(cwd, "AGENTS.md")) }
|
|
61094
61534
|
],
|
|
61095
61535
|
skills: {
|
|
61096
61536
|
total: snap.skills.length,
|
|
@@ -61130,14 +61570,14 @@ function listJsonFiles(dir) {
|
|
|
61130
61570
|
}
|
|
61131
61571
|
function findAgentsMd(cwd) {
|
|
61132
61572
|
const candidates = [
|
|
61133
|
-
|
|
61134
|
-
|
|
61573
|
+
path73.join(cwd, "AGENTS.md"),
|
|
61574
|
+
path73.join(cwd, ".zelari", "AGENTS.md")
|
|
61135
61575
|
];
|
|
61136
61576
|
const found = [];
|
|
61137
61577
|
for (const c of candidates) {
|
|
61138
61578
|
if (existsSync53(c)) {
|
|
61139
61579
|
try {
|
|
61140
|
-
const text =
|
|
61580
|
+
const text = readFileSync42(c, "utf8");
|
|
61141
61581
|
found.push(`${c} (${text.length} bytes)`);
|
|
61142
61582
|
} catch {
|
|
61143
61583
|
found.push(`${c} (unreadable)`);
|
|
@@ -64431,10 +64871,11 @@ import { createHash as createHash14 } from "node:crypto";
|
|
|
64431
64871
|
init_runtime2();
|
|
64432
64872
|
init_verification2();
|
|
64433
64873
|
import { readFile as readFile3 } from "node:fs/promises";
|
|
64434
|
-
import
|
|
64874
|
+
import path43 from "node:path";
|
|
64435
64875
|
function nativePackEnabled(env = process.env) {
|
|
64436
64876
|
const v = env.ZELARI_VERIFY_PACK?.toLowerCase();
|
|
64437
|
-
|
|
64877
|
+
if (v === "0" || v === "off" || v === "false") return false;
|
|
64878
|
+
return true;
|
|
64438
64879
|
}
|
|
64439
64880
|
function resolvePackCommands(env, scripts) {
|
|
64440
64881
|
const pick2 = (override, scriptName) => {
|
|
@@ -64458,7 +64899,7 @@ function packTimeoutMs(env = process.env) {
|
|
|
64458
64899
|
}
|
|
64459
64900
|
async function readPackageScripts(cwd = process.cwd()) {
|
|
64460
64901
|
try {
|
|
64461
|
-
const raw = await readFile3(
|
|
64902
|
+
const raw = await readFile3(path43.join(cwd, "package.json"), "utf-8");
|
|
64462
64903
|
const parsed = JSON.parse(raw);
|
|
64463
64904
|
if (parsed && typeof parsed === "object" && typeof parsed.scripts === "object") {
|
|
64464
64905
|
return parsed.scripts;
|
|
@@ -64497,7 +64938,8 @@ function strictDoneEnabled(surface = "kraken") {
|
|
|
64497
64938
|
return true;
|
|
64498
64939
|
}
|
|
64499
64940
|
const v = process.env.ZELARI_STRICT_DONE;
|
|
64500
|
-
|
|
64941
|
+
if (v === "0" || v === "false") return false;
|
|
64942
|
+
return true;
|
|
64501
64943
|
}
|
|
64502
64944
|
function criterionId(check2, index) {
|
|
64503
64945
|
const slug = check2.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 48);
|
|
@@ -64734,6 +65176,145 @@ function strictGateEventPayload(evaluation) {
|
|
|
64734
65176
|
};
|
|
64735
65177
|
}
|
|
64736
65178
|
|
|
65179
|
+
// src/cli/kraken/completionProof.ts
|
|
65180
|
+
import { mkdir as mkdir2, writeFile as writeFile2 } from "node:fs/promises";
|
|
65181
|
+
import path44 from "node:path";
|
|
65182
|
+
function verdictOf(evaluation) {
|
|
65183
|
+
return evaluation.evaluation?.verdict ?? (evaluation.blocked ? "BLOCKED" : "PASS");
|
|
65184
|
+
}
|
|
65185
|
+
function cell(text, max = 200) {
|
|
65186
|
+
const flat = text.replace(/\r?\n/g, " ").replace(/\|/g, "\\|").trim();
|
|
65187
|
+
return flat.length > max ? `${flat.slice(0, max - 1)}\u2026` : flat;
|
|
65188
|
+
}
|
|
65189
|
+
function evidenceCell(result) {
|
|
65190
|
+
if (!result || result.evidence.length === 0) return "\u2014";
|
|
65191
|
+
return result.evidence.map((e) => {
|
|
65192
|
+
const parts = [e.tier];
|
|
65193
|
+
if (e.seq !== void 0) parts.push(`seq ${e.seq}`);
|
|
65194
|
+
if (e.digest) parts.push(`digest ${e.digest.slice(0, 8)}\u2026`);
|
|
65195
|
+
return parts.join(" \xB7 ");
|
|
65196
|
+
}).join("; ");
|
|
65197
|
+
}
|
|
65198
|
+
function proofRows(evaluation) {
|
|
65199
|
+
const nativeById = new Map(
|
|
65200
|
+
(evaluation.native?.criteria ?? []).map((c) => [c.id, c])
|
|
65201
|
+
);
|
|
65202
|
+
const rows = /* @__PURE__ */ new Map();
|
|
65203
|
+
for (const result of evaluation.results ?? []) {
|
|
65204
|
+
const criterion = nativeById.get(result.criterionId);
|
|
65205
|
+
rows.set(result.criterionId, {
|
|
65206
|
+
id: result.criterionId,
|
|
65207
|
+
text: criterion?.text ?? null,
|
|
65208
|
+
required: criterion ? criterion.required : true,
|
|
65209
|
+
status: result.status,
|
|
65210
|
+
result
|
|
65211
|
+
});
|
|
65212
|
+
}
|
|
65213
|
+
for (const unsatisfied of evaluation.evaluation?.unsatisfied ?? []) {
|
|
65214
|
+
if (rows.has(unsatisfied.id)) continue;
|
|
65215
|
+
const criterion = nativeById.get(unsatisfied.id);
|
|
65216
|
+
rows.set(unsatisfied.id, {
|
|
65217
|
+
id: unsatisfied.id,
|
|
65218
|
+
text: criterion?.text ?? null,
|
|
65219
|
+
required: true,
|
|
65220
|
+
// satisfied/unsatisfied lists cover required criteria only
|
|
65221
|
+
status: unsatisfied.status,
|
|
65222
|
+
result: null
|
|
65223
|
+
});
|
|
65224
|
+
}
|
|
65225
|
+
return [...rows.values()];
|
|
65226
|
+
}
|
|
65227
|
+
function renderMarkdown(evaluation, meta3) {
|
|
65228
|
+
const lines = [
|
|
65229
|
+
"# Completion Proof",
|
|
65230
|
+
"",
|
|
65231
|
+
"Strict build-gate proof-of-work (ADR-0023). The machine-readable twin of",
|
|
65232
|
+
"this document \u2014 `completion-proof.json` \u2014 is the exact `verification.run`",
|
|
65233
|
+
"payload sent to the session spine.",
|
|
65234
|
+
"",
|
|
65235
|
+
`- **Verdict**: **${verdictOf(evaluation)}**`,
|
|
65236
|
+
`- **Strict gate**: ${evaluation.strict ? "on" : "off"}`,
|
|
65237
|
+
`- **Turn blocked**: ${evaluation.blocked ? "yes" : "no"}`,
|
|
65238
|
+
`- **Summary**: ${cell(evaluation.summary, 400)}`,
|
|
65239
|
+
`- **Legacy selection gate**: ${evaluation.gate.passed}/${evaluation.gate.total} passed` + (evaluation.gate.failedChecks.length > 0 ? `; failed: ${evaluation.gate.failedChecks.length}` : "") + (evaluation.gate.unknownChecks.length > 0 ? `; unknown: ${evaluation.gate.unknownChecks.length}` : "")
|
|
65240
|
+
];
|
|
65241
|
+
if (meta3.surface) lines.push(`- **Surface**: ${meta3.surface}`);
|
|
65242
|
+
if (meta3.sessionId) lines.push(`- **Session**: ${meta3.sessionId} (session spine)`);
|
|
65243
|
+
if (meta3.generatedAt !== void 0) {
|
|
65244
|
+
lines.push(`- **Generated**: ${new Date(meta3.generatedAt).toISOString()}`);
|
|
65245
|
+
}
|
|
65246
|
+
const rows = proofRows(evaluation);
|
|
65247
|
+
lines.push("", "## Criteria", "", "| Criterion | Required | Status | Evidence |", "| --- | --- | --- | --- |");
|
|
65248
|
+
if (rows.length === 0) {
|
|
65249
|
+
lines.push("| _none \u2014 no criteria joined this evaluation_ | \u2014 | \u2014 | \u2014 |");
|
|
65250
|
+
}
|
|
65251
|
+
for (const row of rows) {
|
|
65252
|
+
const label = row.text ? `\`${row.id}\` \u2014 ${cell(row.text)}` : `\`${row.id}\``;
|
|
65253
|
+
lines.push(`| ${label} | ${row.required ? "yes" : "no"} | ${row.status} | ${evidenceCell(row.result)} |`);
|
|
65254
|
+
}
|
|
65255
|
+
const unsatisfied = evaluation.evaluation?.unsatisfied ?? [];
|
|
65256
|
+
if (unsatisfied.length > 0) {
|
|
65257
|
+
lines.push("", "### Unsatisfied", "");
|
|
65258
|
+
for (const u of unsatisfied) lines.push(`- \`${u.id}\`: **${u.status}** \u2014 ${cell(u.reason, 300)}`);
|
|
65259
|
+
}
|
|
65260
|
+
const native = evaluation.native;
|
|
65261
|
+
if (native) {
|
|
65262
|
+
lines.push(
|
|
65263
|
+
"",
|
|
65264
|
+
`## Native criteria pack \u2014 ${native.packId}`,
|
|
65265
|
+
"",
|
|
65266
|
+
"| Criterion | Command | Status | Detail |",
|
|
65267
|
+
"| --- | --- | --- | --- |"
|
|
65268
|
+
);
|
|
65269
|
+
for (const result of native.results) {
|
|
65270
|
+
const criterion = native.criteria.find((c) => c.id === result.criterionId);
|
|
65271
|
+
const check2 = criterion?.check;
|
|
65272
|
+
const command = check2?.kind === "command" ? check2.command : "\u2014";
|
|
65273
|
+
const label = criterion?.text ? `\`${result.criterionId}\` \u2014 ${cell(criterion.text, 120)}` : `\`${result.criterionId}\``;
|
|
65274
|
+
lines.push(`| ${label} | \`${cell(command, 120)}\` | ${result.status} | ${cell(result.detail ?? "\u2014")} |`);
|
|
65275
|
+
}
|
|
65276
|
+
}
|
|
65277
|
+
const review = evaluation.review;
|
|
65278
|
+
if (review) {
|
|
65279
|
+
lines.push(
|
|
65280
|
+
"",
|
|
65281
|
+
"## Advisory verifier review",
|
|
65282
|
+
"",
|
|
65283
|
+
"_Advisory only \u2014 this review cannot change the gate verdict above._",
|
|
65284
|
+
"",
|
|
65285
|
+
`- **Verdict**: ${review.verdict}`
|
|
65286
|
+
);
|
|
65287
|
+
if (review.score !== void 0) lines.push(`- **Score**: ${review.score}`);
|
|
65288
|
+
const model = review.effectiveModel.model ?? review.effectiveModel.provider ?? review.effectiveModel.mode;
|
|
65289
|
+
lines.push(`- **Model**: ${model}${review.usedLogprobs ? " (logprobs)" : ""}`);
|
|
65290
|
+
if (review.fallback) lines.push(`- **Fallback**: ${review.fallback}`);
|
|
65291
|
+
if (review.rationale) lines.push(`- **Rationale**: ${cell(review.rationale, 400)}`);
|
|
65292
|
+
}
|
|
65293
|
+
lines.push("", "---", "", "Machine record: `completion-proof.json` (same directory).");
|
|
65294
|
+
return `${lines.join("\n")}
|
|
65295
|
+
`;
|
|
65296
|
+
}
|
|
65297
|
+
function renderCompletionProof(evaluation, meta3 = {}) {
|
|
65298
|
+
return {
|
|
65299
|
+
markdown: renderMarkdown(evaluation, meta3),
|
|
65300
|
+
json: JSON.stringify(strictGateEventPayload(evaluation), null, 2)
|
|
65301
|
+
};
|
|
65302
|
+
}
|
|
65303
|
+
async function writeCompletionProof(evaluation, options = {}) {
|
|
65304
|
+
try {
|
|
65305
|
+
const dir = path44.join(options.baseDir ?? process.cwd(), ".zelari");
|
|
65306
|
+
await mkdir2(dir, { recursive: true });
|
|
65307
|
+
const { markdown, json: json3 } = renderCompletionProof(evaluation, options.meta);
|
|
65308
|
+
const markdownPath = path44.join(dir, "completion-proof.md");
|
|
65309
|
+
const jsonPath = path44.join(dir, "completion-proof.json");
|
|
65310
|
+
await writeFile2(markdownPath, markdown, "utf8");
|
|
65311
|
+
await writeFile2(jsonPath, json3, "utf8");
|
|
65312
|
+
return { markdownPath, jsonPath };
|
|
65313
|
+
} catch {
|
|
65314
|
+
return null;
|
|
65315
|
+
}
|
|
65316
|
+
}
|
|
65317
|
+
|
|
64737
65318
|
// src/cli/hooks/permissionPicker.ts
|
|
64738
65319
|
init_toolPermissions();
|
|
64739
65320
|
|
|
@@ -65774,10 +66355,15 @@ _(${req.context})_` : "") + "\n\u2192 scegli dalla lista (il turno continua dopo
|
|
|
65774
66355
|
if (event.type === "agent_end") {
|
|
65775
66356
|
let krakenSuppressFinish = false;
|
|
65776
66357
|
const krakenSpineEmit = (input) => writerRef.current?.spine?.appendEvent(input) ?? Promise.resolve(null);
|
|
66358
|
+
const writeProofSafe2 = (gate) => writeCompletionProof(gate, { meta: { surface: "kraken", sessionId: sessionId2 } }).then(
|
|
66359
|
+
() => void 0,
|
|
66360
|
+
() => void 0
|
|
66361
|
+
);
|
|
65777
66362
|
if (event.reason === "completed" && !krakenRepairEnqueued && (isKrakenSelectionEnabled() || nativePackEnabled()) && workPhase === "build") {
|
|
65778
66363
|
const strictGate = await evaluateStrictBuildGate("build", { emit: krakenSpineEmit });
|
|
65779
66364
|
const krakenGate = strictGate.gate;
|
|
65780
66365
|
writerRef.current?.spine?.verificationRun(strictGateEventPayload(strictGate));
|
|
66366
|
+
await writeProofSafe2(strictGate);
|
|
65781
66367
|
if (krakenGate.blocked) {
|
|
65782
66368
|
krakenRepairEnqueued = true;
|
|
65783
66369
|
markRepairTriggered();
|
|
@@ -65791,10 +66377,13 @@ _(${req.context})_` : "") + "\n\u2192 scegli dalla lista (il turno continua dopo
|
|
|
65791
66377
|
krakenSuppressFinish = true;
|
|
65792
66378
|
}
|
|
65793
66379
|
}
|
|
65794
|
-
|
|
66380
|
+
const repairCheck = event.reason === "completed" && krakenRepairEnqueued ? await evaluateStrictBuildGate("build", { emit: krakenSpineEmit }) : null;
|
|
66381
|
+
if (repairCheck) await writeProofSafe2(repairCheck);
|
|
66382
|
+
if (repairCheck && !repairCheck.blocked) {
|
|
65795
66383
|
markRepairSucceeded();
|
|
65796
66384
|
} else if (event.reason === "completed" && krakenRepairEnqueued) {
|
|
65797
66385
|
const still = await evaluateStrictBuildGate("build", { emit: krakenSpineEmit });
|
|
66386
|
+
await writeProofSafe2(still);
|
|
65798
66387
|
if (still.blocked) {
|
|
65799
66388
|
appendSystem(
|
|
65800
66389
|
setMessages,
|
|
@@ -67910,7 +68499,7 @@ init_sessionManager();
|
|
|
67910
68499
|
// src/cli/gitOps.ts
|
|
67911
68500
|
import { execFile as execFile4 } from "node:child_process";
|
|
67912
68501
|
import { promisify as promisify3 } from "node:util";
|
|
67913
|
-
import
|
|
68502
|
+
import path55 from "node:path";
|
|
67914
68503
|
var execFileAsync3 = promisify3(execFile4);
|
|
67915
68504
|
async function git4(cwd, args) {
|
|
67916
68505
|
try {
|
|
@@ -67956,7 +68545,7 @@ async function undoWorkingChanges(opts = {}) {
|
|
|
67956
68545
|
};
|
|
67957
68546
|
}
|
|
67958
68547
|
function defaultProjectRoot() {
|
|
67959
|
-
return
|
|
68548
|
+
return path55.resolve(__dirname, "..", "..", "..");
|
|
67960
68549
|
}
|
|
67961
68550
|
|
|
67962
68551
|
// src/cli/slashHandlers/git.ts
|
|
@@ -68243,11 +68832,11 @@ function handleCacheStats(ctx) {
|
|
|
68243
68832
|
init_messageHelpers();
|
|
68244
68833
|
init_serviceFactory();
|
|
68245
68834
|
import { promises as fs30 } from "node:fs";
|
|
68246
|
-
import * as
|
|
68835
|
+
import * as path57 from "node:path";
|
|
68247
68836
|
|
|
68248
68837
|
// src/cli/memory/promotion.ts
|
|
68249
68838
|
import { promises as fs29 } from "node:fs";
|
|
68250
|
-
import * as
|
|
68839
|
+
import * as path56 from "node:path";
|
|
68251
68840
|
var START = "<!-- zelari:memory-promotions:start -->";
|
|
68252
68841
|
var END = "<!-- zelari:memory-promotions:end -->";
|
|
68253
68842
|
var DURABLE_KINDS = /* @__PURE__ */ new Set(["fact", "decision", "constraint", "preference", "procedure"]);
|
|
@@ -68258,13 +68847,13 @@ function lineFor(node) {
|
|
|
68258
68847
|
}
|
|
68259
68848
|
async function promoteMemoryToAgentsMd(projectRoot, node) {
|
|
68260
68849
|
if (node.status !== "active") {
|
|
68261
|
-
return { added: false, path:
|
|
68850
|
+
return { added: false, path: path56.join(projectRoot, "AGENTS.md"), reason: `memory is ${node.status}` };
|
|
68262
68851
|
}
|
|
68263
68852
|
if (!DURABLE_KINDS.has(node.kind)) {
|
|
68264
|
-
return { added: false, path:
|
|
68853
|
+
return { added: false, path: path56.join(projectRoot, "AGENTS.md"), reason: `${node.kind} is not a durable instruction kind` };
|
|
68265
68854
|
}
|
|
68266
|
-
const root = await fs29.realpath(projectRoot).catch(() =>
|
|
68267
|
-
const target =
|
|
68855
|
+
const root = await fs29.realpath(projectRoot).catch(() => path56.resolve(projectRoot));
|
|
68856
|
+
const target = path56.join(root, "AGENTS.md");
|
|
68268
68857
|
try {
|
|
68269
68858
|
const stat2 = await fs29.lstat(target);
|
|
68270
68859
|
if (stat2.isSymbolicLink() || !stat2.isFile()) throw new Error("AGENTS.md must be a regular project file.");
|
|
@@ -68329,22 +68918,22 @@ function sourceLine(source2) {
|
|
|
68329
68918
|
return entries.length ? entries.map(([key, value]) => `${key}=${value}`).join(" \xB7 ") : "unknown";
|
|
68330
68919
|
}
|
|
68331
68920
|
function isInside(root, target) {
|
|
68332
|
-
const relative6 =
|
|
68333
|
-
return relative6 === "" || !relative6.startsWith("..") && !
|
|
68921
|
+
const relative6 = path57.relative(root, target);
|
|
68922
|
+
return relative6 === "" || !relative6.startsWith("..") && !path57.isAbsolute(relative6);
|
|
68334
68923
|
}
|
|
68335
68924
|
async function safeExportPath(cwd, requested) {
|
|
68336
|
-
const lexicalRoot =
|
|
68925
|
+
const lexicalRoot = path57.resolve(cwd);
|
|
68337
68926
|
const root = await fs30.realpath(lexicalRoot).catch(() => lexicalRoot);
|
|
68338
|
-
const fallback =
|
|
68339
|
-
const target = requested?.trim() ?
|
|
68927
|
+
const fallback = path57.join(root, ".zelari", "memory", `export-${Date.now()}.json`);
|
|
68928
|
+
const target = requested?.trim() ? path57.resolve(root, requested.trim()) : fallback;
|
|
68340
68929
|
if (!isInside(root, target)) {
|
|
68341
68930
|
throw new Error("Export path must stay inside the active project.");
|
|
68342
68931
|
}
|
|
68343
|
-
const parent =
|
|
68344
|
-
const relativeParent =
|
|
68932
|
+
const parent = path57.dirname(target);
|
|
68933
|
+
const relativeParent = path57.relative(root, parent);
|
|
68345
68934
|
let cursor = root;
|
|
68346
|
-
for (const segment of relativeParent.split(
|
|
68347
|
-
cursor =
|
|
68935
|
+
for (const segment of relativeParent.split(path57.sep).filter(Boolean)) {
|
|
68936
|
+
cursor = path57.join(cursor, segment);
|
|
68348
68937
|
try {
|
|
68349
68938
|
const stat2 = await fs30.lstat(cursor);
|
|
68350
68939
|
if (stat2.isSymbolicLink()) {
|
|
@@ -68516,9 +69105,9 @@ ${message}` : message
|
|
|
68516
69105
|
}
|
|
68517
69106
|
case "export": {
|
|
68518
69107
|
const target = await safeExportPath(ctx.cwd, args.join(" ").trim() || void 0);
|
|
68519
|
-
await fs30.mkdir(
|
|
68520
|
-
const root = await fs30.realpath(ctx.cwd).catch(() =>
|
|
68521
|
-
const realParent = await fs30.realpath(
|
|
69108
|
+
await fs30.mkdir(path57.dirname(target), { recursive: true });
|
|
69109
|
+
const root = await fs30.realpath(ctx.cwd).catch(() => path57.resolve(ctx.cwd));
|
|
69110
|
+
const realParent = await fs30.realpath(path57.dirname(target));
|
|
68522
69111
|
if (!isInside(root, realParent)) {
|
|
68523
69112
|
throw new Error("Export path resolves outside the active project.");
|
|
68524
69113
|
}
|
|
@@ -68714,7 +69303,7 @@ import { promises as fs34 } from "node:fs";
|
|
|
68714
69303
|
init_zod();
|
|
68715
69304
|
init_taskTool();
|
|
68716
69305
|
import { promises as fs33 } from "node:fs";
|
|
68717
|
-
import
|
|
69306
|
+
import path61 from "node:path";
|
|
68718
69307
|
import { randomBytes as randomBytes5 } from "node:crypto";
|
|
68719
69308
|
var CsvFanoutArgsSchema = external_exports.object({
|
|
68720
69309
|
csv_path: external_exports.string().min(1),
|
|
@@ -68731,7 +69320,7 @@ var CsvFanoutArgsSchema = external_exports.object({
|
|
|
68731
69320
|
scope_template: external_exports.array(external_exports.string()).optional(),
|
|
68732
69321
|
/** Default: ZELARI_KRAKEN_MAX_PARALLEL. */
|
|
68733
69322
|
max_concurrency: external_exports.number().int().positive().optional(),
|
|
68734
|
-
/** Per-row timeout (ms). Default: 5 min for verify,
|
|
69323
|
+
/** Per-row timeout (ms). Default: 5 min for verify, 45 min for general. */
|
|
68735
69324
|
max_runtime_seconds: external_exports.number().int().positive().optional()
|
|
68736
69325
|
});
|
|
68737
69326
|
async function readCsv(filePath) {
|
|
@@ -68808,8 +69397,8 @@ function resolveMaxConcurrency(env = process.env) {
|
|
|
68808
69397
|
}
|
|
68809
69398
|
async function runCsvFanout(args, deps, opts) {
|
|
68810
69399
|
const start = Date.now();
|
|
68811
|
-
const absCsv =
|
|
68812
|
-
const absOut =
|
|
69400
|
+
const absCsv = path61.isAbsolute(args.csv_path) ? args.csv_path : path61.join(opts.parentCwd, args.csv_path);
|
|
69401
|
+
const absOut = path61.isAbsolute(args.output_csv_path) ? args.output_csv_path : path61.join(opts.parentCwd, args.output_csv_path);
|
|
68813
69402
|
const { headers: headers2, rows } = await readCsv(absCsv);
|
|
68814
69403
|
if (headers2.length === 0) {
|
|
68815
69404
|
throw new Error(`kraken_csv_fanout: ${absCsv} is empty`);
|
|
@@ -68822,7 +69411,7 @@ async function runCsvFanout(args, deps, opts) {
|
|
|
68822
69411
|
}
|
|
68823
69412
|
const concurrency = args.max_concurrency ?? resolveMaxConcurrency();
|
|
68824
69413
|
opts.onLog?.(`csv fanout: ${rows.length} rows \xD7 ${args.agent_kind} @ concurrency=${concurrency}`);
|
|
68825
|
-
const perRowMs = args.max_runtime_seconds !== void 0 ? args.max_runtime_seconds * 1e3 : args.agent_kind === "general" ?
|
|
69414
|
+
const perRowMs = args.max_runtime_seconds !== void 0 ? args.max_runtime_seconds * 1e3 : args.agent_kind === "general" ? TASK_TOOL_TIMEOUT_MS : 3e5;
|
|
68826
69415
|
const outputRecords = rows.map((r) => ({ ...r, status: "pending", result: "", error: "" }));
|
|
68827
69416
|
const outHeaders = [...headers2, "status", "result", "error"];
|
|
68828
69417
|
let writeChain2 = Promise.resolve();
|
|
@@ -68865,7 +69454,7 @@ async function runCsvFanout(args, deps, opts) {
|
|
|
68865
69454
|
errored += 1;
|
|
68866
69455
|
errors.push(`${row[args.id_column] ?? i}: ${res.error}`);
|
|
68867
69456
|
}
|
|
68868
|
-
await fs33.mkdir(
|
|
69457
|
+
await fs33.mkdir(path61.dirname(absOut), { recursive: true });
|
|
68869
69458
|
await queueWrite(serializeCsv(outHeaders, outputRecords));
|
|
68870
69459
|
}
|
|
68871
69460
|
}
|
|
@@ -69060,7 +69649,7 @@ function splitArgs(s) {
|
|
|
69060
69649
|
// src/cli/slashHandlers/krakenWorkbench.ts
|
|
69061
69650
|
init_messageHelpers();
|
|
69062
69651
|
import { promises as fs35 } from "node:fs";
|
|
69063
|
-
import
|
|
69652
|
+
import path62 from "node:path";
|
|
69064
69653
|
|
|
69065
69654
|
// src/cli/kraken/workbenchView.ts
|
|
69066
69655
|
var EMPTY = {
|
|
@@ -69177,14 +69766,14 @@ function formatWorkbenchForTerminal(p3) {
|
|
|
69177
69766
|
|
|
69178
69767
|
// src/cli/slashHandlers/krakenWorkbench.ts
|
|
69179
69768
|
async function handleKrakenWorkbench(ctx) {
|
|
69180
|
-
const dir =
|
|
69769
|
+
const dir = path62.join(ctx.cwd, ".zelari", "radio");
|
|
69181
69770
|
let latest = null;
|
|
69182
69771
|
let latestMtime = 0;
|
|
69183
69772
|
try {
|
|
69184
69773
|
const files = await fs35.readdir(dir);
|
|
69185
69774
|
for (const f of files) {
|
|
69186
69775
|
if (!f.startsWith("workbench-") || !f.endsWith(".md")) continue;
|
|
69187
|
-
const full =
|
|
69776
|
+
const full = path62.join(dir, f);
|
|
69188
69777
|
const stat2 = await fs35.stat(full);
|
|
69189
69778
|
if (stat2.mtimeMs > latestMtime) {
|
|
69190
69779
|
latestMtime = stat2.mtimeMs;
|
|
@@ -69201,10 +69790,10 @@ async function handleKrakenWorkbench(ctx) {
|
|
|
69201
69790
|
const parsed = parseWorkbench(content);
|
|
69202
69791
|
const rendered = formatWorkbenchForTerminal(parsed);
|
|
69203
69792
|
if (!rendered.trim()) {
|
|
69204
|
-
appendSystem(ctx.setMessages, `[kraken workbench] ${
|
|
69793
|
+
appendSystem(ctx.setMessages, `[kraken workbench] ${path62.basename(latest)}: (no nodes / no events yet)`);
|
|
69205
69794
|
return;
|
|
69206
69795
|
}
|
|
69207
|
-
appendSystem(ctx.setMessages, `[kraken workbench] ${
|
|
69796
|
+
appendSystem(ctx.setMessages, `[kraken workbench] ${path62.basename(latest)}:
|
|
69208
69797
|
${rendered}`);
|
|
69209
69798
|
}
|
|
69210
69799
|
|
|
@@ -69511,15 +70100,15 @@ ${result.output.split("\n").slice(-8).join("\n")}` : "";
|
|
|
69511
70100
|
// src/cli/slashHandlers/promoteMember.ts
|
|
69512
70101
|
init_messageHelpers();
|
|
69513
70102
|
import { promises as fs36 } from "node:fs";
|
|
69514
|
-
import
|
|
70103
|
+
import path65 from "node:path";
|
|
69515
70104
|
import os12 from "node:os";
|
|
69516
70105
|
async function handlePromoteMember(ctx, memberId) {
|
|
69517
70106
|
try {
|
|
69518
70107
|
const { promoteMember: promoteMember2 } = await Promise.resolve().then(() => (init_council(), council_exports));
|
|
69519
70108
|
const { skill, markdown } = promoteMember2(memberId);
|
|
69520
|
-
const skillDir = process.env.ANATHEMA_SKILL_DIR ??
|
|
70109
|
+
const skillDir = process.env.ANATHEMA_SKILL_DIR ?? path65.join(os12.homedir(), ".tmp", "zelari-code", "skills");
|
|
69521
70110
|
await fs36.mkdir(skillDir, { recursive: true });
|
|
69522
|
-
const filePath =
|
|
70111
|
+
const filePath = path65.join(skillDir, `${skill.id}.md`);
|
|
69523
70112
|
await fs36.writeFile(filePath, markdown, "utf8");
|
|
69524
70113
|
appendSystem(
|
|
69525
70114
|
ctx.setMessages,
|
|
@@ -69536,25 +70125,25 @@ async function handlePromoteMember(ctx, memberId) {
|
|
|
69536
70125
|
}
|
|
69537
70126
|
|
|
69538
70127
|
// src/cli/branchManager.ts
|
|
69539
|
-
import { promises as fs37, existsSync as existsSync45, readFileSync as
|
|
69540
|
-
import
|
|
70128
|
+
import { promises as fs37, existsSync as existsSync45, readFileSync as readFileSync37, writeFileSync as writeFileSync23, mkdirSync as mkdirSync19, statSync as statSync7, rmSync as rmSync3 } from "node:fs";
|
|
70129
|
+
import path66 from "node:path";
|
|
69541
70130
|
import os13 from "node:os";
|
|
69542
70131
|
var META_FILENAME = "meta.json";
|
|
69543
70132
|
var SESSIONS_SUBDIR = "sessions";
|
|
69544
70133
|
function getBranchesBaseDir() {
|
|
69545
|
-
return process.env.ANATHEMA_BRANCHES_DIR ??
|
|
70134
|
+
return process.env.ANATHEMA_BRANCHES_DIR ?? path66.join(os13.homedir(), ".tmp", "zelari-code", "branches");
|
|
69546
70135
|
}
|
|
69547
70136
|
function getSessionsBaseDir() {
|
|
69548
|
-
return process.env.ANATHEMA_SESSIONS_DIR ??
|
|
70137
|
+
return process.env.ANATHEMA_SESSIONS_DIR ?? path66.join(os13.homedir(), ".tmp", "zelari-code", "sessions");
|
|
69549
70138
|
}
|
|
69550
70139
|
function branchPathFor(name, baseDir) {
|
|
69551
|
-
return
|
|
70140
|
+
return path66.join(baseDir, name);
|
|
69552
70141
|
}
|
|
69553
70142
|
function metaPathFor(name, baseDir) {
|
|
69554
|
-
return
|
|
70143
|
+
return path66.join(baseDir, name, META_FILENAME);
|
|
69555
70144
|
}
|
|
69556
70145
|
function sessionsPathFor(name, baseDir) {
|
|
69557
|
-
return
|
|
70146
|
+
return path66.join(baseDir, name, SESSIONS_SUBDIR);
|
|
69558
70147
|
}
|
|
69559
70148
|
function readBranchMeta(name, baseDir) {
|
|
69560
70149
|
const metaPath = metaPathFor(name, baseDir);
|
|
@@ -69562,7 +70151,7 @@ function readBranchMeta(name, baseDir) {
|
|
|
69562
70151
|
throw new BranchNotFoundError(`Branch "${name}" not found`);
|
|
69563
70152
|
}
|
|
69564
70153
|
try {
|
|
69565
|
-
const raw =
|
|
70154
|
+
const raw = readFileSync37(metaPath, "utf-8");
|
|
69566
70155
|
const parsed = JSON.parse(raw);
|
|
69567
70156
|
if (!parsed || typeof parsed !== "object" || typeof parsed.name !== "string" || typeof parsed.createdAt !== "number" || typeof parsed.fromSessionId !== "string") {
|
|
69568
70157
|
throw new BranchCorruptError(`Branch "${name}" meta.json is malformed`);
|
|
@@ -69579,7 +70168,7 @@ function readBranchMeta(name, baseDir) {
|
|
|
69579
70168
|
}
|
|
69580
70169
|
function writeBranchMeta(name, baseDir, meta3) {
|
|
69581
70170
|
const metaPath = metaPathFor(name, baseDir);
|
|
69582
|
-
mkdirSync19(
|
|
70171
|
+
mkdirSync19(path66.dirname(metaPath), { recursive: true });
|
|
69583
70172
|
writeFileSync23(metaPath, JSON.stringify(meta3, null, 2), "utf-8");
|
|
69584
70173
|
}
|
|
69585
70174
|
async function countSessions(name, baseDir) {
|
|
@@ -69630,14 +70219,14 @@ async function createBranch(name, fromSessionId, baseDir = getBranchesBaseDir(),
|
|
|
69630
70219
|
if (branchExists(name, baseDir)) {
|
|
69631
70220
|
throw new BranchAlreadyExistsError(name);
|
|
69632
70221
|
}
|
|
69633
|
-
const sourcePath =
|
|
70222
|
+
const sourcePath = path66.join(sessionsBaseDir, `${fromSessionId}.jsonl`);
|
|
69634
70223
|
if (!existsSync45(sourcePath)) {
|
|
69635
70224
|
throw new SessionNotFoundError(`Source session "${fromSessionId}" not found at ${sourcePath}`);
|
|
69636
70225
|
}
|
|
69637
70226
|
const branchPath = branchPathFor(name, baseDir);
|
|
69638
70227
|
const branchSessionsPath = sessionsPathFor(name, baseDir);
|
|
69639
70228
|
mkdirSync19(branchSessionsPath, { recursive: true });
|
|
69640
|
-
const destPath =
|
|
70229
|
+
const destPath = path66.join(branchSessionsPath, `${fromSessionId}.jsonl`);
|
|
69641
70230
|
await fs37.copyFile(sourcePath, destPath);
|
|
69642
70231
|
const meta3 = {
|
|
69643
70232
|
name,
|
|
@@ -69741,14 +70330,14 @@ async function handleBranchCheckout(ctx, branchName) {
|
|
|
69741
70330
|
// src/cli/slashHandlers/workspace.ts
|
|
69742
70331
|
init_messageHelpers();
|
|
69743
70332
|
import { promises as fs38 } from "node:fs";
|
|
69744
|
-
import
|
|
70333
|
+
import path67 from "node:path";
|
|
69745
70334
|
async function handleWorkspaceShow(ctx, what) {
|
|
69746
70335
|
try {
|
|
69747
|
-
const zelari =
|
|
70336
|
+
const zelari = path67.join(process.cwd(), ".zelari");
|
|
69748
70337
|
let content;
|
|
69749
70338
|
switch (what) {
|
|
69750
70339
|
case "plan": {
|
|
69751
|
-
const planPath =
|
|
70340
|
+
const planPath = path67.join(zelari, "plan.md");
|
|
69752
70341
|
try {
|
|
69753
70342
|
content = await fs38.readFile(planPath, "utf-8");
|
|
69754
70343
|
} catch {
|
|
@@ -69757,7 +70346,7 @@ async function handleWorkspaceShow(ctx, what) {
|
|
|
69757
70346
|
break;
|
|
69758
70347
|
}
|
|
69759
70348
|
case "decisions": {
|
|
69760
|
-
const decisionsDir =
|
|
70349
|
+
const decisionsDir = path67.join(zelari, "decisions");
|
|
69761
70350
|
try {
|
|
69762
70351
|
const files = (await fs38.readdir(decisionsDir)).filter((f) => f.endsWith(".md")).sort();
|
|
69763
70352
|
if (files.length === 0) {
|
|
@@ -69767,7 +70356,7 @@ async function handleWorkspaceShow(ctx, what) {
|
|
|
69767
70356
|
`];
|
|
69768
70357
|
const { parseFrontmatter: parseFrontmatter2 } = await Promise.resolve().then(() => (init_storage(), storage_exports));
|
|
69769
70358
|
for (const f of files) {
|
|
69770
|
-
const raw = await fs38.readFile(
|
|
70359
|
+
const raw = await fs38.readFile(path67.join(decisionsDir, f), "utf-8");
|
|
69771
70360
|
const { meta: meta3, body } = parseFrontmatter2(raw);
|
|
69772
70361
|
const title = meta3.title ?? body.split("\n")[0]?.replace(/^#\s*/, "").trim() ?? f;
|
|
69773
70362
|
lines.push(`- **${f.replace(/\.md$/, "")}** [${meta3.status ?? "unknown"}] ${title}`);
|
|
@@ -69780,7 +70369,7 @@ async function handleWorkspaceShow(ctx, what) {
|
|
|
69780
70369
|
break;
|
|
69781
70370
|
}
|
|
69782
70371
|
case "risks": {
|
|
69783
|
-
const risksPath =
|
|
70372
|
+
const risksPath = path67.join(zelari, "risks.md");
|
|
69784
70373
|
try {
|
|
69785
70374
|
content = await fs38.readFile(risksPath, "utf-8");
|
|
69786
70375
|
} catch {
|
|
@@ -69789,7 +70378,7 @@ async function handleWorkspaceShow(ctx, what) {
|
|
|
69789
70378
|
break;
|
|
69790
70379
|
}
|
|
69791
70380
|
case "agents": {
|
|
69792
|
-
const agentsPath =
|
|
70381
|
+
const agentsPath = path67.join(process.cwd(), "AGENTS.MD");
|
|
69793
70382
|
try {
|
|
69794
70383
|
content = await fs38.readFile(agentsPath, "utf-8");
|
|
69795
70384
|
} catch {
|
|
@@ -69798,7 +70387,7 @@ async function handleWorkspaceShow(ctx, what) {
|
|
|
69798
70387
|
break;
|
|
69799
70388
|
}
|
|
69800
70389
|
case "docs": {
|
|
69801
|
-
const docsDir =
|
|
70390
|
+
const docsDir = path67.join(zelari, "docs");
|
|
69802
70391
|
try {
|
|
69803
70392
|
const files = (await fs38.readdir(docsDir)).filter((f) => f.endsWith(".md")).sort();
|
|
69804
70393
|
content = files.length ? `# Docs (${files.length})
|
|
@@ -69840,7 +70429,7 @@ async function handleWorkspaceReset(ctx, force) {
|
|
|
69840
70429
|
return;
|
|
69841
70430
|
}
|
|
69842
70431
|
try {
|
|
69843
|
-
const target =
|
|
70432
|
+
const target = path67.join(process.cwd(), ".zelari");
|
|
69844
70433
|
await fs38.rm(target, { recursive: true, force: true });
|
|
69845
70434
|
appendSystem(ctx.setMessages, "[workspace] .zelari/ removed");
|
|
69846
70435
|
} catch (err) {
|
|
@@ -69852,7 +70441,7 @@ async function handleWorkspaceReset(ctx, force) {
|
|
|
69852
70441
|
init_provider2();
|
|
69853
70442
|
|
|
69854
70443
|
// src/cli/slashHandlers/skills.ts
|
|
69855
|
-
import
|
|
70444
|
+
import path68 from "node:path";
|
|
69856
70445
|
import os14 from "node:os";
|
|
69857
70446
|
|
|
69858
70447
|
// src/cli/skillHistory.ts
|
|
@@ -69981,7 +70570,7 @@ function handleSkillPicker(ctx, skills, openPicker, fallbackMessage) {
|
|
|
69981
70570
|
});
|
|
69982
70571
|
}
|
|
69983
70572
|
async function handleSkillStats(ctx, skillId) {
|
|
69984
|
-
const historyFile = process.env.ANATHEMA_SKILL_HISTORY_FILE ??
|
|
70573
|
+
const historyFile = process.env.ANATHEMA_SKILL_HISTORY_FILE ?? path68.join(os14.homedir(), ".tmp", "zelari-code", "skill-history.jsonl");
|
|
69985
70574
|
try {
|
|
69986
70575
|
const records = await readSkillHistory(historyFile);
|
|
69987
70576
|
const stats = getSkillStats(records, skillId);
|
|
@@ -69997,7 +70586,7 @@ async function handleSkillCompare(ctx, ids, fallbackMessage) {
|
|
|
69997
70586
|
appendSystem(ctx.setMessages, fallbackMessage ?? "[skill-compare] missing args");
|
|
69998
70587
|
return;
|
|
69999
70588
|
}
|
|
70000
|
-
const historyFile = process.env.ANATHEMA_SKILL_HISTORY_FILE ??
|
|
70589
|
+
const historyFile = process.env.ANATHEMA_SKILL_HISTORY_FILE ?? path68.join(os14.homedir(), ".tmp", "zelari-code", "skill-history.jsonl");
|
|
70001
70590
|
try {
|
|
70002
70591
|
const formatted = await compareSkillsFromFile(ids[0], ids[1], historyFile);
|
|
70003
70592
|
appendSystem(ctx.setMessages, formatted);
|
|
@@ -71512,6 +72101,54 @@ init_candidateRegistry();
|
|
|
71512
72101
|
init_metrics2();
|
|
71513
72102
|
init_completionGate();
|
|
71514
72103
|
init_delegationPolicy();
|
|
72104
|
+
|
|
72105
|
+
// src/cli/orchestration/policy.ts
|
|
72106
|
+
var DEFAULT_MAX_SOLO_CHARS = 300;
|
|
72107
|
+
var KRAKEN_SIGNALS = [
|
|
72108
|
+
{ re: /\bimplement(?:s|ed|ing)?\b/i, reason: "implementation signal" },
|
|
72109
|
+
{ re: /\brefactor(?:ing|ed)?\b/i, reason: "refactor signal" },
|
|
72110
|
+
{ re: /\bmigrat(?:e|es|ed|ion|ing)\b/i, reason: "migration signal" },
|
|
72111
|
+
{
|
|
72112
|
+
re: /\b(?:add|build|create|introduce)\b[^.?!]{0,48}\b(?:feature|endpoint|module|service|command|api|registry|runtime)\b/i,
|
|
72113
|
+
reason: "new-capability signal"
|
|
72114
|
+
},
|
|
72115
|
+
{
|
|
72116
|
+
re: /\b(?:unit|integration|e2e|end-to-end)\s+(?:tests?|testing|specs?)\b|\bwrite\s+(?:the\s+|some\s+)?tests?\b/i,
|
|
72117
|
+
reason: "test-writing signal"
|
|
72118
|
+
},
|
|
72119
|
+
{
|
|
72120
|
+
re: /\b\d+\s*-?\s*(?:files?|modules?|packages?|components?|services?|endpoints?|worktrees?)\b/i,
|
|
72121
|
+
reason: "multi-artifact count"
|
|
72122
|
+
},
|
|
72123
|
+
{
|
|
72124
|
+
re: /\b(?:across|spanning|between|touching)\s+(?:all\s+|the\s+)?(?:\w+\s+){0,2}(?:files|modules|packages|layers|surfaces)\b/i,
|
|
72125
|
+
reason: "cross-cutting scope"
|
|
72126
|
+
}
|
|
72127
|
+
];
|
|
72128
|
+
var QUESTION_RE = /\?\s*$|^(?:who|what|why|when|where|which|how|is|are|was|were|does|do|did|can|could|should|would|will)\b/i;
|
|
72129
|
+
var EXPLAIN_RE = /\b(?:explain|describe|summarize|summarise|clarify|walk\W*me\W*through)\b/i;
|
|
72130
|
+
var READONLY_RE = /\b(?:find|show|list|grep|search|locate|inspect|read|check|review|where\W+is)\b/i;
|
|
72131
|
+
function chooseOrchestration(task, opts = {}) {
|
|
72132
|
+
const text = String(task ?? "").trim();
|
|
72133
|
+
const failClosed = () => ({
|
|
72134
|
+
surface: "solo",
|
|
72135
|
+
reason: "fail-closed default"
|
|
72136
|
+
});
|
|
72137
|
+
if (!text) return failClosed();
|
|
72138
|
+
for (const { re, reason } of KRAKEN_SIGNALS) {
|
|
72139
|
+
if (re.test(text)) return { surface: "kraken", reason };
|
|
72140
|
+
}
|
|
72141
|
+
if (QUESTION_RE.test(text)) return { surface: "solo", reason: "question-shaped task" };
|
|
72142
|
+
if (EXPLAIN_RE.test(text)) return { surface: "solo", reason: "explanation request" };
|
|
72143
|
+
if (READONLY_RE.test(text)) return { surface: "solo", reason: "read-only request" };
|
|
72144
|
+
const budget = opts.maxSoloChars ?? DEFAULT_MAX_SOLO_CHARS;
|
|
72145
|
+
if (text.length <= budget) {
|
|
72146
|
+
return { surface: "solo", reason: "small task, no heavy signals" };
|
|
72147
|
+
}
|
|
72148
|
+
return failClosed();
|
|
72149
|
+
}
|
|
72150
|
+
|
|
72151
|
+
// src/cli/runHeadless.ts
|
|
71515
72152
|
init_headless();
|
|
71516
72153
|
init_claudeProvider();
|
|
71517
72154
|
init_skills2();
|
|
@@ -71550,12 +72187,13 @@ function createStreamScrubber2() {
|
|
|
71550
72187
|
init_taskTool();
|
|
71551
72188
|
init_sessionTodos();
|
|
71552
72189
|
import { promises as fs41 } from "node:fs";
|
|
71553
|
-
import
|
|
72190
|
+
import path70 from "node:path";
|
|
71554
72191
|
import { randomUUID as randomUUID8 } from "node:crypto";
|
|
71555
72192
|
|
|
71556
72193
|
// src/cli/kraken/verifierLifecycle.ts
|
|
71557
72194
|
init_verification2();
|
|
71558
72195
|
init_krakenSelectTool();
|
|
72196
|
+
init_krakenModel();
|
|
71559
72197
|
|
|
71560
72198
|
// src/cli/kraken/verifierResolution.ts
|
|
71561
72199
|
init_providerConfig();
|
|
@@ -71599,18 +72237,61 @@ function makeVerifierCallModel(loadStream, identity, timeoutMs2 = 12e4) {
|
|
|
71599
72237
|
return { text, provider: identity.provider, model: identity.model };
|
|
71600
72238
|
};
|
|
71601
72239
|
}
|
|
71602
|
-
function resolveIdentity(selection, session) {
|
|
72240
|
+
function resolveIdentity(selection, session, familyCandidates, env = process.env) {
|
|
71603
72241
|
if (selection.mode === "fixed") {
|
|
71604
72242
|
return { provider: selection.provider, model: selection.model };
|
|
71605
72243
|
}
|
|
71606
|
-
|
|
72244
|
+
if (!session || !session.provider || !session.model) return null;
|
|
72245
|
+
if (familyCandidates && familyCandidates.length > 0) {
|
|
72246
|
+
const cross = resolveCrossModelVerifier(session, familyCandidates, env);
|
|
72247
|
+
if (cross) return { provider: cross.provider, model: cross.model };
|
|
72248
|
+
}
|
|
72249
|
+
return session;
|
|
72250
|
+
}
|
|
72251
|
+
function isTestEvidenceCriterion(criterionId2) {
|
|
72252
|
+
const id3 = criterionId2.toLowerCase();
|
|
72253
|
+
return ["test", "typecheck", "build", "lint"].some((k) => id3.includes(k));
|
|
72254
|
+
}
|
|
72255
|
+
function extractTestOutputExcerpt(results, maxChars = 4e3) {
|
|
72256
|
+
const lines = [];
|
|
72257
|
+
for (const r of results) {
|
|
72258
|
+
if (!isTestEvidenceCriterion(r.criterionId)) continue;
|
|
72259
|
+
lines.push([r.criterionId, r.status, r.detail].filter(Boolean).join(" \u2014 "));
|
|
72260
|
+
}
|
|
72261
|
+
if (lines.length === 0) return "";
|
|
72262
|
+
return lines.join("\n").slice(0, maxChars);
|
|
72263
|
+
}
|
|
72264
|
+
async function buildBlindReviewInput(evaluation, deps) {
|
|
72265
|
+
const results = evaluation.results ?? [];
|
|
72266
|
+
const passed = results.filter((r) => r.status === "pass").length;
|
|
72267
|
+
const verdict = evaluation.evaluation?.verdict ?? "UNKNOWN";
|
|
72268
|
+
const summary = `Kraken BUILD turn \u2014 deterministic evidence: ${passed}/${results.length} criteria pass, completion verdict ${verdict}.`;
|
|
72269
|
+
const task = deps.task?.trim();
|
|
72270
|
+
const testOutputExcerpt = extractTestOutputExcerpt(results);
|
|
72271
|
+
let diffSummary;
|
|
72272
|
+
try {
|
|
72273
|
+
const res = await (deps.getDiff ?? getWorkingDiff)({
|
|
72274
|
+
cwd: deps.cwd ?? process.cwd(),
|
|
72275
|
+
maxChars: 8e3,
|
|
72276
|
+
staged: true
|
|
72277
|
+
});
|
|
72278
|
+
if (res && !res.empty && res.diff) diffSummary = res.diff;
|
|
72279
|
+
} catch {
|
|
72280
|
+
}
|
|
72281
|
+
return {
|
|
72282
|
+
...task ? { task } : {},
|
|
72283
|
+
summary,
|
|
72284
|
+
...diffSummary !== void 0 ? { diffSummary } : {},
|
|
72285
|
+
...testOutputExcerpt ? { testOutputExcerpt } : {},
|
|
72286
|
+
results
|
|
72287
|
+
};
|
|
71607
72288
|
}
|
|
71608
72289
|
async function runAdvisoryVerifierReview(evaluation, deps = {}) {
|
|
71609
72290
|
if (!evaluation.evaluation || !evaluation.results) return null;
|
|
71610
72291
|
const env = deps.env ?? process.env;
|
|
71611
72292
|
const selection = deps.selection ?? loadVerifierModelSelection();
|
|
71612
72293
|
if (!verifierReviewEnabled(selection, env)) return null;
|
|
71613
|
-
const identity = resolveIdentity(selection, deps.session);
|
|
72294
|
+
const identity = resolveIdentity(selection, deps.session, deps.familyCandidates, env);
|
|
71614
72295
|
let callModel = deps.callModel;
|
|
71615
72296
|
if (!callModel) {
|
|
71616
72297
|
if (!identity || !deps.loadStream) return null;
|
|
@@ -71627,11 +72308,9 @@ async function runAdvisoryVerifierReview(evaluation, deps = {}) {
|
|
|
71627
72308
|
emit: deps.emit,
|
|
71628
72309
|
env
|
|
71629
72310
|
});
|
|
71630
|
-
const
|
|
71631
|
-
const summary = `Kraken BUILD turn \u2014 deterministic evidence: ${passed}/${evaluation.results.length} criteria pass, completion verdict ${evaluation.evaluation.verdict}.`;
|
|
72311
|
+
const blind = await buildBlindReviewInput(evaluation, deps);
|
|
71632
72312
|
const review = await service.reviewCompletion({
|
|
71633
|
-
|
|
71634
|
-
results: evaluation.results,
|
|
72313
|
+
...blind,
|
|
71635
72314
|
session: deps.session
|
|
71636
72315
|
});
|
|
71637
72316
|
evaluation.review = review;
|
|
@@ -71945,6 +72624,13 @@ ${err.stack}` : "";
|
|
|
71945
72624
|
model
|
|
71946
72625
|
});
|
|
71947
72626
|
}
|
|
72627
|
+
if (opts.orchestrationAuto) {
|
|
72628
|
+
const verdict = chooseOrchestration(opts.task ?? "");
|
|
72629
|
+
const line = `[orchestration] --mode auto -> surface=${verdict.surface} (${verdict.reason})`;
|
|
72630
|
+
if (opts.output === "json") emitEvent({ type: "log", message: line });
|
|
72631
|
+
else process.stderr.write(`[zelari-code --headless] ${line}
|
|
72632
|
+
`);
|
|
72633
|
+
}
|
|
71948
72634
|
const mode = opts.mode ?? (opts.useCouncil ? "council" : "kraken");
|
|
71949
72635
|
const profileId = resolveHeadlessProfileId(mode, opts.profile);
|
|
71950
72636
|
if (opts.output === "json") {
|
|
@@ -72018,7 +72704,7 @@ async function runHeadlessKrakenGraph(opts, provider, model) {
|
|
|
72018
72704
|
try {
|
|
72019
72705
|
let preflightGraph;
|
|
72020
72706
|
if (opts.runPlan && opts.runPlan.trim() !== "") {
|
|
72021
|
-
const planPath =
|
|
72707
|
+
const planPath = path70.join(cwd, ".zelari", "radio", `plan-${opts.runPlan}.json`);
|
|
72022
72708
|
log(`loading pre-flight plan: ${planPath}`);
|
|
72023
72709
|
let raw;
|
|
72024
72710
|
try {
|
|
@@ -72058,8 +72744,8 @@ async function runHeadlessKrakenGraph(opts, provider, model) {
|
|
|
72058
72744
|
log(formatKrakenGraphAscii2(graph));
|
|
72059
72745
|
if (opts.planOnly) {
|
|
72060
72746
|
const planId = randomUUID8();
|
|
72061
|
-
const planDir =
|
|
72062
|
-
const planPath =
|
|
72747
|
+
const planDir = path70.join(cwd, ".zelari", "radio");
|
|
72748
|
+
const planPath = path70.join(planDir, `plan-${planId}.json`);
|
|
72063
72749
|
await fs41.mkdir(planDir, { recursive: true });
|
|
72064
72750
|
await fs41.writeFile(
|
|
72065
72751
|
planPath,
|
|
@@ -72087,6 +72773,18 @@ async function runHeadlessKrakenGraph(opts, provider, model) {
|
|
|
72087
72773
|
root: cwd,
|
|
72088
72774
|
audit,
|
|
72089
72775
|
sessionId: sessionId2,
|
|
72776
|
+
// P0.4 capability inheritance: tentacles intersect the headless
|
|
72777
|
+
// parent policy. Headless runs are auto-allow (the same literal
|
|
72778
|
+
// the main headless registry below uses), so this is a no-op
|
|
72779
|
+
// today — wired for correctness if that default ever tightens.
|
|
72780
|
+
parentPolicy: {
|
|
72781
|
+
read: "allow",
|
|
72782
|
+
write: "allow",
|
|
72783
|
+
execute: "allow",
|
|
72784
|
+
network: "allow",
|
|
72785
|
+
ui: "allow",
|
|
72786
|
+
auto: true
|
|
72787
|
+
},
|
|
72090
72788
|
// Anchor every tentacle to the SAME provider/model this run
|
|
72091
72789
|
// resolved (Desktop's selector, or --provider/--model), instead
|
|
72092
72790
|
// of the persisted provider.json default the factory falls back
|
|
@@ -72179,6 +72877,12 @@ async function registerHeadlessMcp(toolRegistry, opts) {
|
|
|
72179
72877
|
}
|
|
72180
72878
|
}
|
|
72181
72879
|
}
|
|
72880
|
+
function writeProofSafe(gate, meta3, baseDir = process.cwd()) {
|
|
72881
|
+
return writeCompletionProof(gate, { baseDir, meta: meta3 }).then(
|
|
72882
|
+
() => void 0,
|
|
72883
|
+
() => void 0
|
|
72884
|
+
);
|
|
72885
|
+
}
|
|
72182
72886
|
async function runHeadlessSingle(opts, provider, model, providerStream) {
|
|
72183
72887
|
const sessionId2 = crypto.randomUUID();
|
|
72184
72888
|
const memoryFactory = await Promise.resolve().then(() => (init_serviceFactory(), serviceFactory_exports));
|
|
@@ -72517,6 +73221,7 @@ async function runHeadlessSingle(opts, provider, model, providerStream) {
|
|
|
72517
73221
|
let strictExit = 0;
|
|
72518
73222
|
const verifierReviewDeps = {
|
|
72519
73223
|
session: { provider, model },
|
|
73224
|
+
task: effectiveTask,
|
|
72520
73225
|
loadStream: async (providerId, modelId) => {
|
|
72521
73226
|
if (providerId === provider) return providerStream;
|
|
72522
73227
|
try {
|
|
@@ -72544,6 +73249,7 @@ async function runHeadlessSingle(opts, provider, model, providerStream) {
|
|
|
72544
73249
|
if (opts.output === "json") {
|
|
72545
73250
|
emitEvent({ type: "verification_run", ...verificationPayload });
|
|
72546
73251
|
}
|
|
73252
|
+
await writeProofSafe(strictGate, { surface: "kraken", sessionId: spine.sessionId });
|
|
72547
73253
|
if (strictGate.blocked) {
|
|
72548
73254
|
const repairPrompt = buildKrakenRepairPrompt(gate);
|
|
72549
73255
|
if (opts.output === "json") {
|
|
@@ -72577,6 +73283,7 @@ async function runHeadlessSingle(opts, provider, model, providerStream) {
|
|
|
72577
73283
|
if (opts.output === "json") {
|
|
72578
73284
|
emitEvent({ type: "verification_run", ...afterPayload });
|
|
72579
73285
|
}
|
|
73286
|
+
await writeProofSafe(after, { surface: "kraken", sessionId: spine.sessionId });
|
|
72580
73287
|
if (!after.blocked) markRepairSucceeded();
|
|
72581
73288
|
else {
|
|
72582
73289
|
strictExit = strictGateExitCode(after);
|
|
@@ -72610,7 +73317,7 @@ async function runHeadlessSingle(opts, provider, model, providerStream) {
|
|
|
72610
73317
|
if (json3) {
|
|
72611
73318
|
if (opts.exportSessionPath === "-") process.stdout.write(json3 + "\n");
|
|
72612
73319
|
else {
|
|
72613
|
-
await fs41.mkdir(
|
|
73320
|
+
await fs41.mkdir(path70.dirname(opts.exportSessionPath), { recursive: true }).catch(() => void 0);
|
|
72614
73321
|
await fs41.writeFile(opts.exportSessionPath, json3, "utf8");
|
|
72615
73322
|
}
|
|
72616
73323
|
}
|
|
@@ -72839,7 +73546,7 @@ async function runHeadlessCouncil(opts, provider, model, providerStream) {
|
|
|
72839
73546
|
if (json3) {
|
|
72840
73547
|
if (opts.exportSessionPath === "-") process.stdout.write(json3 + "\n");
|
|
72841
73548
|
else {
|
|
72842
|
-
await fs41.mkdir(
|
|
73549
|
+
await fs41.mkdir(path70.dirname(opts.exportSessionPath), { recursive: true }).catch(() => void 0);
|
|
72843
73550
|
await fs41.writeFile(opts.exportSessionPath, json3, "utf8");
|
|
72844
73551
|
}
|
|
72845
73552
|
}
|
|
@@ -73219,6 +73926,7 @@ ${ragContext}` : slicePrompt;
|
|
|
73219
73926
|
if (opts.output === "json") {
|
|
73220
73927
|
emitEvent({ type: "verification_run", ...missionVerificationPayload });
|
|
73221
73928
|
}
|
|
73929
|
+
await writeProofSafe(missionGate, { surface: "mission", sessionId: spine.sessionId }, projectRoot);
|
|
73222
73930
|
if (missionGate.blocked) {
|
|
73223
73931
|
exitCode = strictGateExitCode(missionGate);
|
|
73224
73932
|
spine.missionPhase("verification", "mission-strict-blocked");
|
|
@@ -73253,7 +73961,7 @@ ${ragContext}` : slicePrompt;
|
|
|
73253
73961
|
if (json3) {
|
|
73254
73962
|
if (opts.exportSessionPath === "-") process.stdout.write(json3 + "\n");
|
|
73255
73963
|
else {
|
|
73256
|
-
await fs41.mkdir(
|
|
73964
|
+
await fs41.mkdir(path70.dirname(opts.exportSessionPath), { recursive: true }).catch(() => void 0);
|
|
73257
73965
|
await fs41.writeFile(opts.exportSessionPath, json3, "utf8");
|
|
73258
73966
|
}
|
|
73259
73967
|
}
|
|
@@ -73455,8 +74163,8 @@ function normalizeDraft(raw, sourceUrl, provider, model) {
|
|
|
73455
74163
|
let name = String(o.name ?? "").trim().toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 64);
|
|
73456
74164
|
if (!name || !/^[a-z0-9][a-z0-9-]{0,63}$/.test(name)) {
|
|
73457
74165
|
try {
|
|
73458
|
-
const
|
|
73459
|
-
name =
|
|
74166
|
+
const path74 = new URL(sourceUrl).pathname.split("/").filter(Boolean).pop()?.replace(/\.[a-z0-9]+$/i, "").toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 48);
|
|
74167
|
+
name = path74 && /^[a-z0-9]/.test(path74) ? path74 : "imported-skill";
|
|
73460
74168
|
} catch {
|
|
73461
74169
|
name = "imported-skill";
|
|
73462
74170
|
}
|