zelari-code 2.36.0 → 2.37.1
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/evolution/ledger.js.map +1 -1
- package/dist/cli/evolution/runTelemetry.js +68 -0
- package/dist/cli/evolution/runTelemetry.js.map +1 -0
- package/dist/cli/headless/runOneTurn.js +15 -5
- package/dist/cli/headless/runOneTurn.js.map +1 -1
- package/dist/cli/headless.js +21 -0
- package/dist/cli/headless.js.map +1 -1
- package/dist/cli/headlessSpine.js +26 -0
- package/dist/cli/headlessSpine.js.map +1 -1
- package/dist/cli/hooks/useChatTurn.js +18 -3
- package/dist/cli/hooks/useChatTurn.js.map +1 -1
- package/dist/cli/kraken/completionGate.js +78 -1
- package/dist/cli/kraken/completionGate.js.map +1 -1
- package/dist/cli/kraken/verificationBridge.js +153 -32
- package/dist/cli/kraken/verificationBridge.js.map +1 -1
- package/dist/cli/kraken/verifyReport.js.map +1 -1
- package/dist/cli/main.bundled.js +776 -373
- package/dist/cli/main.bundled.js.map +4 -4
- package/dist/cli/main.js +3 -0
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/runHeadless.js +48 -2
- package/dist/cli/runHeadless.js.map +1 -1
- package/dist/cli/workspace/planStore.js +29 -0
- package/dist/cli/workspace/planStore.js.map +1 -1
- package/dist/cli/zelariMission.js +130 -30
- package/dist/cli/zelariMission.js.map +1 -1
- package/package.json +2 -2
package/dist/cli/main.bundled.js
CHANGED
|
@@ -3482,10 +3482,10 @@ function mergeDefs(...defs) {
|
|
|
3482
3482
|
function cloneDef(schema) {
|
|
3483
3483
|
return mergeDefs(schema._zod.def);
|
|
3484
3484
|
}
|
|
3485
|
-
function getElementAtPath(obj,
|
|
3486
|
-
if (!
|
|
3485
|
+
function getElementAtPath(obj, path101) {
|
|
3486
|
+
if (!path101)
|
|
3487
3487
|
return obj;
|
|
3488
|
-
return
|
|
3488
|
+
return path101.reduce((acc, key) => acc?.[key], obj);
|
|
3489
3489
|
}
|
|
3490
3490
|
function promiseAllObject(promisesObj) {
|
|
3491
3491
|
const keys = Object.keys(promisesObj);
|
|
@@ -3813,11 +3813,11 @@ function explicitlyAborted(x, startIndex = 0) {
|
|
|
3813
3813
|
}
|
|
3814
3814
|
return false;
|
|
3815
3815
|
}
|
|
3816
|
-
function prefixIssues(
|
|
3816
|
+
function prefixIssues(path101, issues) {
|
|
3817
3817
|
return issues.map((iss) => {
|
|
3818
3818
|
var _a3;
|
|
3819
3819
|
(_a3 = iss).path ?? (_a3.path = []);
|
|
3820
|
-
iss.path.unshift(
|
|
3820
|
+
iss.path.unshift(path101);
|
|
3821
3821
|
return iss;
|
|
3822
3822
|
});
|
|
3823
3823
|
}
|
|
@@ -4035,16 +4035,16 @@ function flattenError(error51, mapper = (issue2) => issue2.message) {
|
|
|
4035
4035
|
}
|
|
4036
4036
|
function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
4037
4037
|
const fieldErrors = { _errors: [] };
|
|
4038
|
-
const processError = (error52,
|
|
4038
|
+
const processError = (error52, path101 = []) => {
|
|
4039
4039
|
for (const issue2 of error52.issues) {
|
|
4040
4040
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
4041
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
4041
|
+
issue2.errors.map((issues) => processError({ issues }, [...path101, ...issue2.path]));
|
|
4042
4042
|
} else if (issue2.code === "invalid_key") {
|
|
4043
|
-
processError({ issues: issue2.issues }, [...
|
|
4043
|
+
processError({ issues: issue2.issues }, [...path101, ...issue2.path]);
|
|
4044
4044
|
} else if (issue2.code === "invalid_element") {
|
|
4045
|
-
processError({ issues: issue2.issues }, [...
|
|
4045
|
+
processError({ issues: issue2.issues }, [...path101, ...issue2.path]);
|
|
4046
4046
|
} else {
|
|
4047
|
-
const fullpath = [...
|
|
4047
|
+
const fullpath = [...path101, ...issue2.path];
|
|
4048
4048
|
if (fullpath.length === 0) {
|
|
4049
4049
|
fieldErrors._errors.push(mapper(issue2));
|
|
4050
4050
|
} else {
|
|
@@ -4071,17 +4071,17 @@ function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
|
4071
4071
|
}
|
|
4072
4072
|
function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
4073
4073
|
const result = { errors: [] };
|
|
4074
|
-
const processError = (error52,
|
|
4074
|
+
const processError = (error52, path101 = []) => {
|
|
4075
4075
|
var _a3, _b;
|
|
4076
4076
|
for (const issue2 of error52.issues) {
|
|
4077
4077
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
4078
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
4078
|
+
issue2.errors.map((issues) => processError({ issues }, [...path101, ...issue2.path]));
|
|
4079
4079
|
} else if (issue2.code === "invalid_key") {
|
|
4080
|
-
processError({ issues: issue2.issues }, [...
|
|
4080
|
+
processError({ issues: issue2.issues }, [...path101, ...issue2.path]);
|
|
4081
4081
|
} else if (issue2.code === "invalid_element") {
|
|
4082
|
-
processError({ issues: issue2.issues }, [...
|
|
4082
|
+
processError({ issues: issue2.issues }, [...path101, ...issue2.path]);
|
|
4083
4083
|
} else {
|
|
4084
|
-
const fullpath = [...
|
|
4084
|
+
const fullpath = [...path101, ...issue2.path];
|
|
4085
4085
|
if (fullpath.length === 0) {
|
|
4086
4086
|
result.errors.push(mapper(issue2));
|
|
4087
4087
|
continue;
|
|
@@ -4113,8 +4113,8 @@ function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
|
4113
4113
|
}
|
|
4114
4114
|
function toDotPath(_path) {
|
|
4115
4115
|
const segs = [];
|
|
4116
|
-
const
|
|
4117
|
-
for (const seg of
|
|
4116
|
+
const path101 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
4117
|
+
for (const seg of path101) {
|
|
4118
4118
|
if (typeof seg === "number")
|
|
4119
4119
|
segs.push(`[${seg}]`);
|
|
4120
4120
|
else if (typeof seg === "symbol")
|
|
@@ -17617,13 +17617,13 @@ function resolveRef(ref, ctx) {
|
|
|
17617
17617
|
if (!ref.startsWith("#")) {
|
|
17618
17618
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
17619
17619
|
}
|
|
17620
|
-
const
|
|
17621
|
-
if (
|
|
17620
|
+
const path101 = ref.slice(1).split("/").filter(Boolean);
|
|
17621
|
+
if (path101.length === 0) {
|
|
17622
17622
|
return ctx.rootSchema;
|
|
17623
17623
|
}
|
|
17624
17624
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
17625
|
-
if (
|
|
17626
|
-
const key =
|
|
17625
|
+
if (path101[0] === defsKey) {
|
|
17626
|
+
const key = path101[1];
|
|
17627
17627
|
if (!key || !ctx.defs[key]) {
|
|
17628
17628
|
throw new Error(`Reference not found: ${ref}`);
|
|
17629
17629
|
}
|
|
@@ -18457,17 +18457,17 @@ var init_newlines = __esm({
|
|
|
18457
18457
|
});
|
|
18458
18458
|
|
|
18459
18459
|
// packages/core/dist/core/tools/builtin/fileEvents.js
|
|
18460
|
-
function fileReadEvent(
|
|
18461
|
-
return { kind: "file.read", actor: { type: "tool" }, data: { path:
|
|
18460
|
+
function fileReadEvent(path101, snapshotId) {
|
|
18461
|
+
return { kind: "file.read", actor: { type: "tool" }, data: { path: path101, snapshotId } };
|
|
18462
18462
|
}
|
|
18463
|
-
function fileAppliedEvent(
|
|
18464
|
-
return { kind: "file.applied", actor: { type: "tool" }, data: { path:
|
|
18463
|
+
function fileAppliedEvent(path101, snapshotId, bytes) {
|
|
18464
|
+
return { kind: "file.applied", actor: { type: "tool" }, data: { path: path101, snapshotId, bytes } };
|
|
18465
18465
|
}
|
|
18466
|
-
function fileRejectedEvent(
|
|
18466
|
+
function fileRejectedEvent(path101, reason, hint) {
|
|
18467
18467
|
return {
|
|
18468
18468
|
kind: "file.rejected",
|
|
18469
18469
|
actor: { type: "tool" },
|
|
18470
|
-
data: hint === void 0 ? { path:
|
|
18470
|
+
data: hint === void 0 ? { path: path101, reason } : { path: path101, reason, hint }
|
|
18471
18471
|
};
|
|
18472
18472
|
}
|
|
18473
18473
|
function reReadHint(reject) {
|
|
@@ -20336,11 +20336,11 @@ var init_tools = __esm({
|
|
|
20336
20336
|
if (!ctx.addDocument)
|
|
20337
20337
|
return "Knowledge vault tool not available.";
|
|
20338
20338
|
const title = args["title"] || "New Document";
|
|
20339
|
-
const
|
|
20339
|
+
const path101 = args["path"] || `notes/${title.toLowerCase().replace(/[^a-z0-9]+/g, "-")}`;
|
|
20340
20340
|
const content = args["content"] || "";
|
|
20341
20341
|
const tags = args["tags"] || [];
|
|
20342
20342
|
ctx.addDocument({
|
|
20343
|
-
path:
|
|
20343
|
+
path: path101,
|
|
20344
20344
|
title,
|
|
20345
20345
|
content,
|
|
20346
20346
|
format: "markdown",
|
|
@@ -20349,7 +20349,7 @@ var init_tools = __esm({
|
|
|
20349
20349
|
workspaceId: ctx.workspaceId
|
|
20350
20350
|
});
|
|
20351
20351
|
ctx.addActivity("vault", "created document", title);
|
|
20352
|
-
return `Document "${title}" created at "${
|
|
20352
|
+
return `Document "${title}" created at "${path101}".`;
|
|
20353
20353
|
}
|
|
20354
20354
|
}
|
|
20355
20355
|
];
|
|
@@ -22036,7 +22036,20 @@ function evaluateKrakenCompletionGate(mode) {
|
|
|
22036
22036
|
};
|
|
22037
22037
|
}
|
|
22038
22038
|
}
|
|
22039
|
-
function
|
|
22039
|
+
function excerptEntries(excerpts) {
|
|
22040
|
+
if (!excerpts) return [];
|
|
22041
|
+
return excerpts instanceof Map ? [...excerpts.entries()] : Object.entries(excerpts);
|
|
22042
|
+
}
|
|
22043
|
+
function excerptBlock(name, raw) {
|
|
22044
|
+
const trimmed = raw.trim();
|
|
22045
|
+
const truncated = trimmed.length > REPAIR_FAIL_EXCERPT_CAP;
|
|
22046
|
+
const tail2 = truncated ? trimmed.slice(trimmed.length - REPAIR_FAIL_EXCERPT_CAP) : trimmed;
|
|
22047
|
+
const lines = [`Failure excerpt (tail, capped ${REPAIR_FAIL_EXCERPT_CAP} chars) \u2014 ${name}:`];
|
|
22048
|
+
if (truncated) lines.push(`\u2026[truncated ${trimmed.length - REPAIR_FAIL_EXCERPT_CAP} chars]`);
|
|
22049
|
+
lines.push(tail2, "");
|
|
22050
|
+
return lines;
|
|
22051
|
+
}
|
|
22052
|
+
function buildKrakenRepairPrompt(gate, excerpts) {
|
|
22040
22053
|
const lines = [
|
|
22041
22054
|
`The BUILD turn is ending, but the required checks from kraken_select are not all satisfied (passed ${gate.passed}/${gate.total}).`,
|
|
22042
22055
|
""
|
|
@@ -22053,6 +22066,36 @@ function buildKrakenRepairPrompt(gate) {
|
|
|
22053
22066
|
for (const check2 of gate.unknownChecks) lines.push(`- ${check2}`);
|
|
22054
22067
|
lines.push("");
|
|
22055
22068
|
}
|
|
22069
|
+
const entries = excerptEntries(excerpts);
|
|
22070
|
+
if (entries.length > 0) {
|
|
22071
|
+
const byName = new Map(entries);
|
|
22072
|
+
const used = /* @__PURE__ */ new Set();
|
|
22073
|
+
const blocks = [];
|
|
22074
|
+
let emitted = 0;
|
|
22075
|
+
for (const check2 of [...gate.failedChecks, ...gate.unknownChecks]) {
|
|
22076
|
+
if (emitted >= MAX_REPAIR_EXCERPTS) break;
|
|
22077
|
+
const raw = byName.get(check2);
|
|
22078
|
+
if (raw === void 0 || used.has(check2)) continue;
|
|
22079
|
+
used.add(check2);
|
|
22080
|
+
blocks.push(excerptBlock(check2, raw));
|
|
22081
|
+
emitted += 1;
|
|
22082
|
+
}
|
|
22083
|
+
let leadInPushed = false;
|
|
22084
|
+
for (const [name, raw] of entries) {
|
|
22085
|
+
if (emitted >= MAX_REPAIR_EXCERPTS) break;
|
|
22086
|
+
if (used.has(name)) continue;
|
|
22087
|
+
if (!leadInPushed) {
|
|
22088
|
+
blocks.push([
|
|
22089
|
+
"DETERMINISTIC check failures with captured output (criteria pack / task contract):",
|
|
22090
|
+
""
|
|
22091
|
+
]);
|
|
22092
|
+
leadInPushed = true;
|
|
22093
|
+
}
|
|
22094
|
+
blocks.push(excerptBlock(name, raw));
|
|
22095
|
+
emitted += 1;
|
|
22096
|
+
}
|
|
22097
|
+
for (const block of blocks) lines.push(...block);
|
|
22098
|
+
}
|
|
22056
22099
|
lines.push(
|
|
22057
22100
|
"Recover this turn:",
|
|
22058
22101
|
"1. The approach selection is settled \u2014 do NOT call kraken_select again.",
|
|
@@ -22063,7 +22106,7 @@ function buildKrakenRepairPrompt(gate) {
|
|
|
22063
22106
|
);
|
|
22064
22107
|
return lines.join("\n");
|
|
22065
22108
|
}
|
|
22066
|
-
var OPEN_GATE;
|
|
22109
|
+
var OPEN_GATE, REPAIR_FAIL_EXCERPT_CAP, MAX_REPAIR_EXCERPTS;
|
|
22067
22110
|
var init_completionGate = __esm({
|
|
22068
22111
|
"src/cli/kraken/completionGate.ts"() {
|
|
22069
22112
|
"use strict";
|
|
@@ -22076,6 +22119,8 @@ var init_completionGate = __esm({
|
|
|
22076
22119
|
failedChecks: [],
|
|
22077
22120
|
unknownChecks: []
|
|
22078
22121
|
};
|
|
22122
|
+
REPAIR_FAIL_EXCERPT_CAP = 2e3;
|
|
22123
|
+
MAX_REPAIR_EXCERPTS = 5;
|
|
22079
22124
|
}
|
|
22080
22125
|
});
|
|
22081
22126
|
|
|
@@ -25174,16 +25219,16 @@ function runRetentionFromEnv() {
|
|
|
25174
25219
|
maxTotalBytes: Number.isFinite(parseMb) && parseMb > 0 ? Math.round(parseMb * 1024 * 1024) : DEFAULT_RUN_RETENTION_MAX_MB * 1024 * 1024
|
|
25175
25220
|
};
|
|
25176
25221
|
}
|
|
25177
|
-
async function dirSize(
|
|
25222
|
+
async function dirSize(path101) {
|
|
25178
25223
|
let total = 0;
|
|
25179
25224
|
let entries;
|
|
25180
25225
|
try {
|
|
25181
|
-
entries = await readdir(
|
|
25226
|
+
entries = await readdir(path101, { withFileTypes: true });
|
|
25182
25227
|
} catch {
|
|
25183
25228
|
return 0;
|
|
25184
25229
|
}
|
|
25185
25230
|
for (const entry of entries) {
|
|
25186
|
-
const child = join3(
|
|
25231
|
+
const child = join3(path101, entry.name);
|
|
25187
25232
|
if (entry.isDirectory())
|
|
25188
25233
|
total += await dirSize(child);
|
|
25189
25234
|
else {
|
|
@@ -25210,19 +25255,19 @@ async function enforceRunRetention(runsDir, options = {}) {
|
|
|
25210
25255
|
for (const entry of entries) {
|
|
25211
25256
|
if (!entry.isDirectory())
|
|
25212
25257
|
continue;
|
|
25213
|
-
const
|
|
25258
|
+
const path101 = join3(runsDir, entry.name);
|
|
25214
25259
|
let startedAt = 0;
|
|
25215
25260
|
let endedAt;
|
|
25216
25261
|
let completed = false;
|
|
25217
25262
|
try {
|
|
25218
|
-
const manifest = JSON.parse(await readFile(join3(
|
|
25263
|
+
const manifest = JSON.parse(await readFile(join3(path101, "manifest.json"), "utf8"));
|
|
25219
25264
|
startedAt = manifest.startedAt ?? 0;
|
|
25220
25265
|
endedAt = manifest.endedAt;
|
|
25221
25266
|
completed = Boolean(endedAt) && manifest.status !== "running";
|
|
25222
25267
|
} catch {
|
|
25223
25268
|
completed = false;
|
|
25224
25269
|
}
|
|
25225
|
-
infos.push({ name: entry.name, path:
|
|
25270
|
+
infos.push({ name: entry.name, path: path101, startedAt, endedAt, completed, bytes: await dirSize(path101) });
|
|
25226
25271
|
}
|
|
25227
25272
|
const remove = async (info) => {
|
|
25228
25273
|
await rm(info.path, { recursive: true, force: true });
|
|
@@ -25709,12 +25754,12 @@ var init_engine = __esm({
|
|
|
25709
25754
|
* content digest) and the returned ref carries the event seq when the
|
|
25710
25755
|
* emitter resolved one.
|
|
25711
25756
|
*/
|
|
25712
|
-
async fsEvidence(observation,
|
|
25757
|
+
async fsEvidence(observation, path101, sha256, content, extra = {}) {
|
|
25713
25758
|
const digest = sha256 && content !== void 0 ? sha256(content) : void 0;
|
|
25714
|
-
const seq = await this.emitEvidence({ observation, path:
|
|
25759
|
+
const seq = await this.emitEvidence({ observation, path: path101, ...extra, ...digest ? { digest } : {} });
|
|
25715
25760
|
return {
|
|
25716
25761
|
tier: "fs-observation",
|
|
25717
|
-
ref:
|
|
25762
|
+
ref: path101,
|
|
25718
25763
|
capturedAt: Date.now(),
|
|
25719
25764
|
...digest ? { digest } : {},
|
|
25720
25765
|
...seq !== void 0 ? { seq } : {}
|
|
@@ -27184,11 +27229,14 @@ var init_contractCompiler = __esm({
|
|
|
27184
27229
|
var verificationBridge_exports = {};
|
|
27185
27230
|
__export(verificationBridge_exports, {
|
|
27186
27231
|
STRICT_DONE_EXIT_CODE: () => STRICT_DONE_EXIT_CODE,
|
|
27232
|
+
allowUnverified: () => allowUnverified,
|
|
27187
27233
|
anchorSelectionEvidence: () => anchorSelectionEvidence,
|
|
27188
27234
|
evaluateStrictBuildGate: () => evaluateStrictBuildGate,
|
|
27189
27235
|
evaluateStrictBuildGateFromSession: () => evaluateStrictBuildGateFromSession,
|
|
27190
27236
|
krakenResultsToContract: () => krakenResultsToContract,
|
|
27191
27237
|
matchNoteToToolTrace: () => matchNoteToToolTrace,
|
|
27238
|
+
missionClaimExitCode: () => missionClaimExitCode,
|
|
27239
|
+
repairExcerptsFromEvaluation: () => repairExcerptsFromEvaluation,
|
|
27192
27240
|
strictDoneEnabled: () => strictDoneEnabled,
|
|
27193
27241
|
strictEnvOverlay: () => strictEnvOverlay,
|
|
27194
27242
|
strictGateEventPayload: () => strictGateEventPayload,
|
|
@@ -27224,20 +27272,20 @@ function criterionId(check2, index) {
|
|
|
27224
27272
|
function normalize3(text) {
|
|
27225
27273
|
return text.toLowerCase().replace(/\s+/g, " ").trim();
|
|
27226
27274
|
}
|
|
27227
|
-
function matchResult(check2, byNormalized) {
|
|
27228
|
-
|
|
27229
|
-
|
|
27230
|
-
|
|
27231
|
-
for (const key of byNormalized.keys()) {
|
|
27232
|
-
if (key.length >= 8 && (key.includes(norm) || norm.includes(key))) {
|
|
27233
|
-
return byNormalized.get(key);
|
|
27234
|
-
}
|
|
27275
|
+
function matchResult(check2, byNormalized, byId, id3) {
|
|
27276
|
+
if (byId && id3) {
|
|
27277
|
+
const byCriterion = byId.get(id3);
|
|
27278
|
+
if (byCriterion) return byCriterion;
|
|
27235
27279
|
}
|
|
27236
|
-
return
|
|
27280
|
+
return byNormalized.get(normalize3(check2));
|
|
27237
27281
|
}
|
|
27238
27282
|
function krakenResultsToContract(requiredChecks, results, now = Date.now()) {
|
|
27239
27283
|
const byNormalized = /* @__PURE__ */ new Map();
|
|
27240
|
-
|
|
27284
|
+
const byId = /* @__PURE__ */ new Map();
|
|
27285
|
+
for (const r of results ?? []) {
|
|
27286
|
+
byNormalized.set(normalize3(r.check), r);
|
|
27287
|
+
if (r.criterionId) byId.set(r.criterionId, r);
|
|
27288
|
+
}
|
|
27241
27289
|
const criteria = [];
|
|
27242
27290
|
const verifications = [];
|
|
27243
27291
|
requiredChecks.forEach((check2, i) => {
|
|
@@ -27247,12 +27295,12 @@ function krakenResultsToContract(requiredChecks, results, now = Date.now()) {
|
|
|
27247
27295
|
text: check2,
|
|
27248
27296
|
source: "kraken-selection",
|
|
27249
27297
|
required: true,
|
|
27250
|
-
check: { kind: "none", reason: "
|
|
27298
|
+
check: { kind: "none", reason: "verify tentacle proposal \u2014 runtime evidence required" }
|
|
27251
27299
|
});
|
|
27252
|
-
const reported = matchResult(check2, byNormalized);
|
|
27300
|
+
const reported = matchResult(check2, byNormalized, byId, id3);
|
|
27253
27301
|
const evidence = reported?.note && reported.note.trim().length > 0 ? [
|
|
27254
27302
|
{
|
|
27255
|
-
tier: "
|
|
27303
|
+
tier: "verifier-llm",
|
|
27256
27304
|
ref: reported.note.trim().slice(0, 500),
|
|
27257
27305
|
capturedAt: now
|
|
27258
27306
|
}
|
|
@@ -27299,12 +27347,12 @@ async function anchorSelectionEvidence(results, emit, toolTrace) {
|
|
|
27299
27347
|
for (const r of results) {
|
|
27300
27348
|
for (const ev of r.evidence) {
|
|
27301
27349
|
if (ev.seq !== void 0) continue;
|
|
27302
|
-
if (ev.tier === "
|
|
27350
|
+
if (ev.tier === "human") continue;
|
|
27303
27351
|
try {
|
|
27304
27352
|
const match = toolTrace && toolTrace.length > 0 ? matchNoteToToolTrace(ev.ref, toolTrace) : null;
|
|
27305
27353
|
if (match) {
|
|
27306
27354
|
const digest = sha256Hex2(match.output);
|
|
27307
|
-
const
|
|
27355
|
+
const appended = await emit({
|
|
27308
27356
|
kind: "verification.evidence",
|
|
27309
27357
|
actor: { type: "system", role: "verification" },
|
|
27310
27358
|
data: {
|
|
@@ -27320,16 +27368,17 @@ async function anchorSelectionEvidence(results, emit, toolTrace) {
|
|
|
27320
27368
|
...match.command ? { command: match.command } : {}
|
|
27321
27369
|
}
|
|
27322
27370
|
});
|
|
27323
|
-
const toolSeq =
|
|
27371
|
+
const toolSeq = appended && typeof appended === "object" && "seq" in appended ? Number(appended.seq) : NaN;
|
|
27324
27372
|
if (Number.isFinite(toolSeq) && toolSeq > 0) {
|
|
27325
27373
|
ev.seq = toolSeq;
|
|
27326
27374
|
ev.digest = digest;
|
|
27375
|
+
ev.tier = "tool-output";
|
|
27327
27376
|
ev.ref = `${match.tool}${match.command ? ` ${match.command}` : ""} \u2192 ${match.ok ? "ok" : "error"} @seq`;
|
|
27328
27377
|
counts.toolResultAnchored += 1;
|
|
27329
27378
|
}
|
|
27330
27379
|
continue;
|
|
27331
27380
|
}
|
|
27332
|
-
|
|
27381
|
+
await emit({
|
|
27333
27382
|
kind: "verification.evidence",
|
|
27334
27383
|
actor: { type: "system", role: "verification" },
|
|
27335
27384
|
data: {
|
|
@@ -27337,14 +27386,11 @@ async function anchorSelectionEvidence(results, emit, toolTrace) {
|
|
|
27337
27386
|
provenance: "note-fallback",
|
|
27338
27387
|
criterionId: r.criterionId,
|
|
27339
27388
|
ref: ev.ref,
|
|
27340
|
-
tier: ev.tier
|
|
27389
|
+
tier: ev.tier,
|
|
27390
|
+
anchored: false
|
|
27341
27391
|
}
|
|
27342
27392
|
});
|
|
27343
|
-
|
|
27344
|
-
if (Number.isFinite(seq) && seq > 0) {
|
|
27345
|
-
ev.seq = seq;
|
|
27346
|
-
counts.noteFallback += 1;
|
|
27347
|
-
}
|
|
27393
|
+
counts.noteFallback += 1;
|
|
27348
27394
|
} catch {
|
|
27349
27395
|
}
|
|
27350
27396
|
}
|
|
@@ -27358,7 +27404,8 @@ async function evaluateStrictBuildGate(mode, options = {}) {
|
|
|
27358
27404
|
const selectionAvailable = gate.selectionUsed && gate.total > 0;
|
|
27359
27405
|
const scopeContract = options.taskContract ?? activeContractScope()?.contract;
|
|
27360
27406
|
const contractPlan = scopeContract ? compileVerificationCriteria(scopeContract) : [];
|
|
27361
|
-
|
|
27407
|
+
const nothingBindable = !selectionAvailable && !nativeOn && contractPlan.length === 0;
|
|
27408
|
+
if (!strictOn && !nativeOn) {
|
|
27362
27409
|
return {
|
|
27363
27410
|
gate,
|
|
27364
27411
|
strict: false,
|
|
@@ -27368,6 +27415,17 @@ async function evaluateStrictBuildGate(mode, options = {}) {
|
|
|
27368
27415
|
summary: gate.blocked ? `blocked: ${gate.failedChecks.length} failed, ${gate.unknownChecks.length} unknown` : "open"
|
|
27369
27416
|
};
|
|
27370
27417
|
}
|
|
27418
|
+
if (nothingBindable) {
|
|
27419
|
+
return {
|
|
27420
|
+
gate,
|
|
27421
|
+
strict: true,
|
|
27422
|
+
unverified: true,
|
|
27423
|
+
evaluation: null,
|
|
27424
|
+
native: null,
|
|
27425
|
+
blocked: true,
|
|
27426
|
+
summary: "unverified (strict on: no criteria \u2014 pack off/unbound, no selection contract, no task contract)"
|
|
27427
|
+
};
|
|
27428
|
+
}
|
|
27371
27429
|
const checks = selectionAvailable ? krakenRequiredChecks() : [];
|
|
27372
27430
|
const contract = selectionAvailable ? krakenResultsToContract(checks, getKrakenCheckResults()) : { criteria: [], results: [] };
|
|
27373
27431
|
const anchoring = await anchorSelectionEvidence(
|
|
@@ -27389,6 +27447,19 @@ async function evaluateStrictBuildGate(mode, options = {}) {
|
|
|
27389
27447
|
const allCriteria = [...contract.criteria, ...native?.criteria ?? [], ...compiled?.criteria ?? []];
|
|
27390
27448
|
const allResults = [...contract.results, ...native?.results ?? [], ...compiled?.results ?? []];
|
|
27391
27449
|
if (allCriteria.length === 0) {
|
|
27450
|
+
if (strictOn) {
|
|
27451
|
+
return {
|
|
27452
|
+
gate,
|
|
27453
|
+
strict: true,
|
|
27454
|
+
unverified: true,
|
|
27455
|
+
evaluation: null,
|
|
27456
|
+
native,
|
|
27457
|
+
compiled,
|
|
27458
|
+
results: allResults,
|
|
27459
|
+
blocked: true,
|
|
27460
|
+
summary: "unverified (strict on: native pack bound no command, no selection contract)"
|
|
27461
|
+
};
|
|
27462
|
+
}
|
|
27392
27463
|
return {
|
|
27393
27464
|
gate,
|
|
27394
27465
|
strict: false,
|
|
@@ -27414,14 +27485,51 @@ async function evaluateStrictBuildGate(mode, options = {}) {
|
|
|
27414
27485
|
summary: blocked ? `blocked (strict ${evaluation?.verdict ?? "n/a"}): ${legacyPart}evidence ${evaluation?.evidenceComplete ? "complete" : "incomplete"}` : `open (strict PASS): ${evaluation?.satisfied.length ?? 0}/${allCriteria.length} criteria pass with evidence`
|
|
27415
27486
|
};
|
|
27416
27487
|
}
|
|
27417
|
-
function
|
|
27418
|
-
|
|
27488
|
+
function repairExcerptsFromEvaluation(evaluation) {
|
|
27489
|
+
const excerpts = /* @__PURE__ */ new Map();
|
|
27490
|
+
const nameById = /* @__PURE__ */ new Map();
|
|
27491
|
+
for (const c of [...evaluation.native?.criteria ?? [], ...evaluation.compiled?.criteria ?? []]) {
|
|
27492
|
+
nameById.set(c.id, c.text);
|
|
27493
|
+
}
|
|
27494
|
+
try {
|
|
27495
|
+
krakenRequiredChecks().forEach((text, i) => {
|
|
27496
|
+
if (!nameById.has(criterionId(text, i))) nameById.set(criterionId(text, i), text);
|
|
27497
|
+
});
|
|
27498
|
+
} catch {
|
|
27499
|
+
}
|
|
27500
|
+
for (const r of evaluation.results ?? []) {
|
|
27501
|
+
if (r.status === "pass") continue;
|
|
27502
|
+
const detail = r.detail?.trim();
|
|
27503
|
+
if (!detail) continue;
|
|
27504
|
+
excerpts.set(nameById.get(r.criterionId) ?? r.criterionId, detail);
|
|
27505
|
+
}
|
|
27506
|
+
return excerpts;
|
|
27507
|
+
}
|
|
27508
|
+
function allowUnverified(env = process.env) {
|
|
27509
|
+
const v = env.ZELARI_ALLOW_UNVERIFIED?.toLowerCase();
|
|
27510
|
+
return v === "1" || v === "true" || v === "yes" || v === "on";
|
|
27511
|
+
}
|
|
27512
|
+
function strictGateExitCode(evaluation, env = process.env) {
|
|
27513
|
+
if (evaluation.strict && evaluation.blocked) {
|
|
27514
|
+
if (evaluation.unverified && allowUnverified(env)) return 0;
|
|
27515
|
+
return STRICT_DONE_EXIT_CODE;
|
|
27516
|
+
}
|
|
27517
|
+
return 0;
|
|
27518
|
+
}
|
|
27519
|
+
function missionClaimExitCode(evidenceCount, env = process.env) {
|
|
27520
|
+
if (evidenceCount < 0) return 0;
|
|
27521
|
+
if (evidenceCount > 0) return 0;
|
|
27522
|
+
if (allowUnverified(env)) return 0;
|
|
27523
|
+
return STRICT_DONE_EXIT_CODE;
|
|
27419
27524
|
}
|
|
27420
27525
|
function strictGateEventPayload(evaluation) {
|
|
27421
27526
|
return {
|
|
27422
27527
|
engine: evaluation.native ? "kraken-legacy+completion-policy+criteria-pack" : "kraken-legacy+completion-policy",
|
|
27423
27528
|
strict: evaluation.strict,
|
|
27424
27529
|
verdict: evaluation.evaluation?.verdict ?? (evaluation.blocked ? "BLOCKED" : "PASS"),
|
|
27530
|
+
// M1.2: UNVERIFIED marker — strict on, nothing evaluable. Present only
|
|
27531
|
+
// when true so historical payloads stay byte-identical.
|
|
27532
|
+
...evaluation.unverified ? { unverified: true } : {},
|
|
27425
27533
|
legacy: {
|
|
27426
27534
|
total: evaluation.gate.total,
|
|
27427
27535
|
passed: evaluation.gate.passed,
|
|
@@ -31734,11 +31842,11 @@ var init_synthesisAudit = __esm({
|
|
|
31734
31842
|
import { existsSync as existsSync10, readFileSync as readFileSync9, writeFileSync as writeFileSync6 } from "node:fs";
|
|
31735
31843
|
import { join as join5 } from "node:path";
|
|
31736
31844
|
function loadNfrSpec(zelariRoot) {
|
|
31737
|
-
const
|
|
31738
|
-
if (!existsSync10(
|
|
31845
|
+
const path101 = join5(zelariRoot, "nfr-spec.json");
|
|
31846
|
+
if (!existsSync10(path101))
|
|
31739
31847
|
return null;
|
|
31740
31848
|
try {
|
|
31741
|
-
const raw = JSON.parse(readFileSync9(
|
|
31849
|
+
const raw = JSON.parse(readFileSync9(path101, "utf8"));
|
|
31742
31850
|
if (raw.version !== 1 || !Array.isArray(raw.targets))
|
|
31743
31851
|
return null;
|
|
31744
31852
|
return raw;
|
|
@@ -33854,10 +33962,28 @@ function buildMissionBrief(input) {
|
|
|
33854
33962
|
],
|
|
33855
33963
|
phases,
|
|
33856
33964
|
sliceMvp,
|
|
33857
|
-
slices:
|
|
33965
|
+
slices: buildSlicePlan(sliceMvp, input.planTaskIds, maxTasks),
|
|
33858
33966
|
userPromptOriginal: userMessage
|
|
33859
33967
|
};
|
|
33860
33968
|
}
|
|
33969
|
+
function buildSlicePlan(sliceMvp, planTaskIds, maxTasks) {
|
|
33970
|
+
const ids = Array.isArray(planTaskIds) ? planTaskIds.filter((t) => typeof t === "string" && t) : [];
|
|
33971
|
+
if (ids.length === 0)
|
|
33972
|
+
return [{ ...sliceMvp }];
|
|
33973
|
+
const size = Number.isFinite(maxTasks) && maxTasks > 0 ? Math.floor(maxTasks) : 8;
|
|
33974
|
+
const slices = [];
|
|
33975
|
+
for (let i = 0; i < ids.length; i += size) {
|
|
33976
|
+
const chunk = ids.slice(i, i + size);
|
|
33977
|
+
const index = i / size;
|
|
33978
|
+
slices.push(index === 0 ? { ...sliceMvp, taskIds: chunk, maxTasks: size } : {
|
|
33979
|
+
id: `slice-${index + 1}`,
|
|
33980
|
+
title: `Increment ${index + 1} \u2014 ${chunk.length} plan task(s)`,
|
|
33981
|
+
taskIds: chunk,
|
|
33982
|
+
maxTasks: size
|
|
33983
|
+
});
|
|
33984
|
+
}
|
|
33985
|
+
return slices;
|
|
33986
|
+
}
|
|
33861
33987
|
var STACK_SIGNALS;
|
|
33862
33988
|
var init_missionBrief = __esm({
|
|
33863
33989
|
"packages/core/dist/council/missionBrief.js"() {
|
|
@@ -34121,9 +34247,9 @@ var init_types9 = __esm({
|
|
|
34121
34247
|
import { readFileSync as readFileSync14 } from "node:fs";
|
|
34122
34248
|
import { join as join11 } from "node:path";
|
|
34123
34249
|
function readLessonsDeduped(zelariRoot) {
|
|
34124
|
-
const
|
|
34250
|
+
const path101 = join11(zelariRoot, LESSONS_FILE);
|
|
34125
34251
|
try {
|
|
34126
|
-
const raw = readFileSync14(
|
|
34252
|
+
const raw = readFileSync14(path101, "utf8");
|
|
34127
34253
|
const byId = /* @__PURE__ */ new Map();
|
|
34128
34254
|
for (const line of raw.split(/\r?\n/)) {
|
|
34129
34255
|
if (!line.trim())
|
|
@@ -34224,8 +34350,8 @@ function keywordsFrom(check2, signature) {
|
|
|
34224
34350
|
return [.../* @__PURE__ */ new Set([...fromId, ...words])].slice(0, 12);
|
|
34225
34351
|
}
|
|
34226
34352
|
function writeLesson(zelariRoot, lesson) {
|
|
34227
|
-
const
|
|
34228
|
-
appendFileSync(
|
|
34353
|
+
const path101 = join12(zelariRoot, LESSONS_FILE);
|
|
34354
|
+
appendFileSync(path101, `${JSON.stringify(lesson)}
|
|
34229
34355
|
`, "utf8");
|
|
34230
34356
|
}
|
|
34231
34357
|
function findSimilar(lessons, signature) {
|
|
@@ -34682,6 +34808,7 @@ __export(council_exports, {
|
|
|
34682
34808
|
buildMotionFixPrompt: () => buildMotionFixPrompt,
|
|
34683
34809
|
buildRetryPrompt: () => buildRetryPrompt,
|
|
34684
34810
|
buildSkillDefinition: () => buildSkillDefinition,
|
|
34811
|
+
buildSlicePlan: () => buildSlicePlan,
|
|
34685
34812
|
buildSystemPrompt: () => buildSystemPrompt,
|
|
34686
34813
|
buildSystemPromptSplit: () => buildSystemPromptSplit,
|
|
34687
34814
|
captureFailure: () => captureFailure,
|
|
@@ -36192,9 +36319,9 @@ function findCycle(nodes) {
|
|
|
36192
36319
|
if (color.get(start) !== WHITE)
|
|
36193
36320
|
continue;
|
|
36194
36321
|
const stack = [[start, 0]];
|
|
36195
|
-
const
|
|
36322
|
+
const path101 = [];
|
|
36196
36323
|
color.set(start, GRAY);
|
|
36197
|
-
|
|
36324
|
+
path101.push(start);
|
|
36198
36325
|
while (stack.length > 0) {
|
|
36199
36326
|
const top = stack[stack.length - 1];
|
|
36200
36327
|
const [id3, idx] = top;
|
|
@@ -36207,17 +36334,17 @@ function findCycle(nodes) {
|
|
|
36207
36334
|
continue;
|
|
36208
36335
|
const c = color.get(dep);
|
|
36209
36336
|
if (c === GRAY) {
|
|
36210
|
-
const at =
|
|
36211
|
-
return [...
|
|
36337
|
+
const at = path101.indexOf(dep);
|
|
36338
|
+
return [...path101.slice(at), dep];
|
|
36212
36339
|
}
|
|
36213
36340
|
if (c === WHITE) {
|
|
36214
36341
|
color.set(dep, GRAY);
|
|
36215
|
-
|
|
36342
|
+
path101.push(dep);
|
|
36216
36343
|
stack.push([dep, 0]);
|
|
36217
36344
|
}
|
|
36218
36345
|
} else {
|
|
36219
36346
|
color.set(id3, BLACK);
|
|
36220
|
-
|
|
36347
|
+
path101.pop();
|
|
36221
36348
|
stack.pop();
|
|
36222
36349
|
}
|
|
36223
36350
|
}
|
|
@@ -37137,8 +37264,8 @@ var init_runner = __esm({
|
|
|
37137
37264
|
failed: [...this.tentaclesById.values()].filter((r) => r.status === "error"),
|
|
37138
37265
|
pending: []
|
|
37139
37266
|
};
|
|
37140
|
-
const
|
|
37141
|
-
this.host.log(`checkpoint: ${label ?? "auto"} \u2192 ${
|
|
37267
|
+
const path101 = await this.host.saveSnapshot(snapshot, ".zelari/kraken/snapshots");
|
|
37268
|
+
this.host.log(`checkpoint: ${label ?? "auto"} \u2192 ${path101}`);
|
|
37142
37269
|
return snapshot;
|
|
37143
37270
|
}
|
|
37144
37271
|
callLog(msg, data) {
|
|
@@ -38289,7 +38416,7 @@ var CORE_VERSION;
|
|
|
38289
38416
|
var init_version = __esm({
|
|
38290
38417
|
"packages/core/dist/version.js"() {
|
|
38291
38418
|
"use strict";
|
|
38292
|
-
CORE_VERSION = "2.
|
|
38419
|
+
CORE_VERSION = "2.37.1";
|
|
38293
38420
|
}
|
|
38294
38421
|
});
|
|
38295
38422
|
|
|
@@ -38539,6 +38666,7 @@ __export(dist_exports, {
|
|
|
38539
38666
|
buildRetryPrompt: () => buildRetryPrompt,
|
|
38540
38667
|
buildRuntimeObserverBus: () => buildRuntimeObserverBus,
|
|
38541
38668
|
buildSkillDefinition: () => buildSkillDefinition,
|
|
38669
|
+
buildSlicePlan: () => buildSlicePlan,
|
|
38542
38670
|
buildSystemPrompt: () => buildSystemPrompt,
|
|
38543
38671
|
buildSystemPromptSplit: () => buildSystemPromptSplit,
|
|
38544
38672
|
canExternalClientMutate: () => canExternalClientMutate,
|
|
@@ -40747,9 +40875,9 @@ function spillToolOutput(fullText, meta3) {
|
|
|
40747
40875
|
const rnd = randomBytes3(3).toString("hex");
|
|
40748
40876
|
const safeTool = (meta3?.toolName ?? "tool").replace(/[^a-zA-Z0-9._-]+/g, "_").slice(0, 32);
|
|
40749
40877
|
const file2 = `${stamp}-${safeTool}-${hash3}-${rnd}.txt`;
|
|
40750
|
-
const
|
|
40751
|
-
writeFileSync12(
|
|
40752
|
-
return
|
|
40878
|
+
const path101 = join14(dir, file2);
|
|
40879
|
+
writeFileSync12(path101, fullText, "utf8");
|
|
40880
|
+
return path101;
|
|
40753
40881
|
} catch {
|
|
40754
40882
|
return null;
|
|
40755
40883
|
}
|
|
@@ -40795,10 +40923,10 @@ function truncateToolResult(text, capOrOpts = TOOL_RESULT_LINE_CAP) {
|
|
|
40795
40923
|
${tail2}`;
|
|
40796
40924
|
}
|
|
40797
40925
|
if (doSpill) {
|
|
40798
|
-
const
|
|
40799
|
-
if (
|
|
40926
|
+
const path101 = spillToolOutput(text, { toolName: opts.toolName });
|
|
40927
|
+
if (path101) {
|
|
40800
40928
|
const spillNote = `
|
|
40801
|
-
\u2026 [full output spilled to: ${
|
|
40929
|
+
\u2026 [full output spilled to: ${path101} \u2014 re-read with read_file if you need the complete text] \u2026`;
|
|
40802
40930
|
if (preview.includes("] \u2026\n")) {
|
|
40803
40931
|
preview = preview.replace("] \u2026\n", `] \u2026${spillNote}
|
|
40804
40932
|
`);
|
|
@@ -41569,28 +41697,28 @@ var init_storage = __esm({
|
|
|
41569
41697
|
VALID_SCALARS = /^(true|false|null|~)$/i;
|
|
41570
41698
|
Storage = class {
|
|
41571
41699
|
/** Read a Markdown file with frontmatter. Throws if not found. */
|
|
41572
|
-
read(
|
|
41573
|
-
if (!existsSync19(
|
|
41574
|
-
throw new Error(`File not found: ${
|
|
41700
|
+
read(path101) {
|
|
41701
|
+
if (!existsSync19(path101)) {
|
|
41702
|
+
throw new Error(`File not found: ${path101}`);
|
|
41575
41703
|
}
|
|
41576
|
-
const md = readFileSync17(
|
|
41704
|
+
const md = readFileSync17(path101, "utf8");
|
|
41577
41705
|
return parseFrontmatter(md);
|
|
41578
41706
|
}
|
|
41579
41707
|
/** Read a Markdown file; returns null if not found. */
|
|
41580
|
-
readIfExists(
|
|
41581
|
-
if (!existsSync19(
|
|
41582
|
-
return this.read(
|
|
41708
|
+
readIfExists(path101) {
|
|
41709
|
+
if (!existsSync19(path101)) return null;
|
|
41710
|
+
return this.read(path101);
|
|
41583
41711
|
}
|
|
41584
41712
|
/**
|
|
41585
41713
|
* Write a Markdown file atomically (tmp + rename). Creates parent dirs.
|
|
41586
41714
|
* The meta object is serialized as YAML frontmatter; body as Markdown.
|
|
41587
41715
|
*/
|
|
41588
|
-
write(
|
|
41589
|
-
mkdirSync10(dirname2(
|
|
41590
|
-
const tmp =
|
|
41716
|
+
write(path101, meta3, body) {
|
|
41717
|
+
mkdirSync10(dirname2(path101), { recursive: true });
|
|
41718
|
+
const tmp = path101 + ".tmp-" + process.pid;
|
|
41591
41719
|
const md = serializeFrontmatter(meta3, body);
|
|
41592
41720
|
writeFileSync14(tmp, md, "utf8");
|
|
41593
|
-
renameSync2(tmp,
|
|
41721
|
+
renameSync2(tmp, path101);
|
|
41594
41722
|
}
|
|
41595
41723
|
/** List all .md files in a directory (non-recursive). */
|
|
41596
41724
|
listMarkdown(dir) {
|
|
@@ -41625,6 +41753,24 @@ var init_storage = __esm({
|
|
|
41625
41753
|
});
|
|
41626
41754
|
|
|
41627
41755
|
// src/cli/workspace/planStore.ts
|
|
41756
|
+
var planStore_exports = {};
|
|
41757
|
+
__export(planStore_exports, {
|
|
41758
|
+
PLAN_FILES_MAX: () => PLAN_FILES_MAX,
|
|
41759
|
+
PLAN_FILE_GLOB_MAX: () => PLAN_FILE_GLOB_MAX,
|
|
41760
|
+
PLAN_MAX_TASKS: () => PLAN_MAX_TASKS,
|
|
41761
|
+
PLAN_NOTES_MAX: () => PLAN_NOTES_MAX,
|
|
41762
|
+
PLAN_SCHEMA_VERSION: () => PLAN_SCHEMA_VERSION,
|
|
41763
|
+
PLAN_TAG_MAX: () => PLAN_TAG_MAX,
|
|
41764
|
+
PLAN_TASK_STATUSES: () => PLAN_TASK_STATUSES,
|
|
41765
|
+
PLAN_TITLE_MAX: () => PLAN_TITLE_MAX,
|
|
41766
|
+
PlanStoreError: () => PlanStoreError,
|
|
41767
|
+
listOpenPlanTaskIds: () => listOpenPlanTaskIds,
|
|
41768
|
+
nextPlanTaskId: () => nextPlanTaskId,
|
|
41769
|
+
normalizePlanTaskFiles: () => normalizePlanTaskFiles,
|
|
41770
|
+
planJsonPathFor: () => planJsonPathFor,
|
|
41771
|
+
withPlanStore: () => withPlanStore,
|
|
41772
|
+
writePlanTaskArtifact: () => writePlanTaskArtifact
|
|
41773
|
+
});
|
|
41628
41774
|
import {
|
|
41629
41775
|
copyFileSync,
|
|
41630
41776
|
existsSync as existsSync20,
|
|
@@ -41647,6 +41793,24 @@ function normalizePlanTaskFiles(values) {
|
|
|
41647
41793
|
function planJsonPathFor(projectRoot = process.cwd()) {
|
|
41648
41794
|
return join17(resolveWorkspaceRoot(projectRoot), "plan.json");
|
|
41649
41795
|
}
|
|
41796
|
+
async function listOpenPlanTaskIds(projectRoot) {
|
|
41797
|
+
try {
|
|
41798
|
+
const jsonPath = planJsonPathFor(projectRoot);
|
|
41799
|
+
if (!existsSync20(jsonPath)) return [];
|
|
41800
|
+
const parsed = JSON.parse(readFileSync18(jsonPath, "utf8"));
|
|
41801
|
+
if (!Array.isArray(parsed.tasks)) return [];
|
|
41802
|
+
const ids = [];
|
|
41803
|
+
for (const raw of parsed.tasks) {
|
|
41804
|
+
if (raw === null || typeof raw !== "object") continue;
|
|
41805
|
+
const t = raw;
|
|
41806
|
+
if (typeof t.id !== "string" || t.id.length === 0) continue;
|
|
41807
|
+
if (t.status === "pending" || t.status === "in_progress") ids.push(t.id);
|
|
41808
|
+
}
|
|
41809
|
+
return ids;
|
|
41810
|
+
} catch {
|
|
41811
|
+
return [];
|
|
41812
|
+
}
|
|
41813
|
+
}
|
|
41650
41814
|
async function withPlanStore(projectRoot, fn) {
|
|
41651
41815
|
const rootDir = resolveWorkspaceRoot(projectRoot);
|
|
41652
41816
|
return workspaceMutex.run(`${rootDir}:plan`, () => {
|
|
@@ -41665,8 +41829,8 @@ function nextPlanTaskId(store6) {
|
|
|
41665
41829
|
return `t${store6.counter}`;
|
|
41666
41830
|
}
|
|
41667
41831
|
function writePlanTaskArtifact(rootDir, task) {
|
|
41668
|
-
const
|
|
41669
|
-
mkdirSync11(dirname3(
|
|
41832
|
+
const path101 = join17(rootDir, "plan-tasks", `${task.id}.md`);
|
|
41833
|
+
mkdirSync11(dirname3(path101), { recursive: true });
|
|
41670
41834
|
const meta3 = {
|
|
41671
41835
|
kind: "task",
|
|
41672
41836
|
id: task.id,
|
|
@@ -41687,7 +41851,7 @@ function writePlanTaskArtifact(rootDir, task) {
|
|
|
41687
41851
|
task.notes?.trim() ? task.notes.trim() : "_(no notes)_",
|
|
41688
41852
|
""
|
|
41689
41853
|
].filter((l) => l !== null).join("\n");
|
|
41690
|
-
new Storage().write(
|
|
41854
|
+
new Storage().write(path101, meta3, body);
|
|
41691
41855
|
}
|
|
41692
41856
|
function loadHandle(rootDir) {
|
|
41693
41857
|
const jsonPath = join17(rootDir, "plan.json");
|
|
@@ -41790,7 +41954,7 @@ function normalizeStatus(raw) {
|
|
|
41790
41954
|
function firstString(v) {
|
|
41791
41955
|
return typeof v === "string" && v.trim().length > 0 ? v : null;
|
|
41792
41956
|
}
|
|
41793
|
-
var PLAN_SCHEMA_VERSION, PLAN_MAX_TASKS, PLAN_TITLE_MAX, PLAN_NOTES_MAX, PLAN_TAG_MAX, PLAN_FILES_MAX, PLAN_FILE_GLOB_MAX, PlanStoreError;
|
|
41957
|
+
var PLAN_SCHEMA_VERSION, PLAN_MAX_TASKS, PLAN_TITLE_MAX, PLAN_NOTES_MAX, PLAN_TAG_MAX, PLAN_TASK_STATUSES, PLAN_FILES_MAX, PLAN_FILE_GLOB_MAX, PlanStoreError;
|
|
41794
41958
|
var init_planStore = __esm({
|
|
41795
41959
|
"src/cli/workspace/planStore.ts"() {
|
|
41796
41960
|
"use strict";
|
|
@@ -41801,6 +41965,13 @@ var init_planStore = __esm({
|
|
|
41801
41965
|
PLAN_TITLE_MAX = 200;
|
|
41802
41966
|
PLAN_NOTES_MAX = 2e3;
|
|
41803
41967
|
PLAN_TAG_MAX = 64;
|
|
41968
|
+
PLAN_TASK_STATUSES = [
|
|
41969
|
+
"pending",
|
|
41970
|
+
"in_progress",
|
|
41971
|
+
"completed",
|
|
41972
|
+
"cancelled",
|
|
41973
|
+
"blocked"
|
|
41974
|
+
];
|
|
41804
41975
|
PLAN_FILES_MAX = 32;
|
|
41805
41976
|
PLAN_FILE_GLOB_MAX = 260;
|
|
41806
41977
|
PlanStoreError = class extends Error {
|
|
@@ -52011,21 +52182,21 @@ function normalizeAuth(auth) {
|
|
|
52011
52182
|
return "agent";
|
|
52012
52183
|
}
|
|
52013
52184
|
function readSecrets() {
|
|
52014
|
-
const
|
|
52015
|
-
if (!existsSync30(
|
|
52185
|
+
const path101 = getSshSecretsPath();
|
|
52186
|
+
if (!existsSync30(path101)) return {};
|
|
52016
52187
|
try {
|
|
52017
|
-
return JSON.parse(readFileSync22(
|
|
52188
|
+
return JSON.parse(readFileSync22(path101, "utf8"));
|
|
52018
52189
|
} catch {
|
|
52019
52190
|
return {};
|
|
52020
52191
|
}
|
|
52021
52192
|
}
|
|
52022
52193
|
function writeSecrets(data) {
|
|
52023
|
-
const
|
|
52024
|
-
mkdirSync13(dirname4(
|
|
52025
|
-
writeFileSync16(
|
|
52194
|
+
const path101 = getSshSecretsPath();
|
|
52195
|
+
mkdirSync13(dirname4(path101), { recursive: true });
|
|
52196
|
+
writeFileSync16(path101, `${JSON.stringify(data, null, 2)}
|
|
52026
52197
|
`, "utf8");
|
|
52027
52198
|
try {
|
|
52028
|
-
chmodSync(
|
|
52199
|
+
chmodSync(path101, 384);
|
|
52029
52200
|
} catch {
|
|
52030
52201
|
}
|
|
52031
52202
|
}
|
|
@@ -52054,10 +52225,10 @@ function deleteSshPassword(id3) {
|
|
|
52054
52225
|
writeSecrets({ passwords });
|
|
52055
52226
|
}
|
|
52056
52227
|
function readStore2() {
|
|
52057
|
-
const
|
|
52058
|
-
if (!existsSync30(
|
|
52228
|
+
const path101 = getSshTargetsPath();
|
|
52229
|
+
if (!existsSync30(path101)) return [];
|
|
52059
52230
|
try {
|
|
52060
|
-
const parsed = JSON.parse(readFileSync22(
|
|
52231
|
+
const parsed = JSON.parse(readFileSync22(path101, "utf8"));
|
|
52061
52232
|
const list = Array.isArray(parsed.targets) ? parsed.targets : [];
|
|
52062
52233
|
return list.filter(
|
|
52063
52234
|
(t) => t && typeof t.id === "string" && typeof t.host === "string" && typeof t.user === "string"
|
|
@@ -52072,11 +52243,11 @@ function readStore2() {
|
|
|
52072
52243
|
}
|
|
52073
52244
|
}
|
|
52074
52245
|
function writeStore2(targets) {
|
|
52075
|
-
const
|
|
52076
|
-
mkdirSync13(dirname4(
|
|
52246
|
+
const path101 = getSshTargetsPath();
|
|
52247
|
+
mkdirSync13(dirname4(path101), { recursive: true });
|
|
52077
52248
|
const clean = targets.map(({ hasPassword: _hp, ...t }) => t);
|
|
52078
52249
|
writeFileSync16(
|
|
52079
|
-
|
|
52250
|
+
path101,
|
|
52080
52251
|
`${JSON.stringify({ targets: clean }, null, 2)}
|
|
52081
52252
|
`,
|
|
52082
52253
|
"utf8"
|
|
@@ -52322,11 +52493,11 @@ function formatSshTargetsForPrompt() {
|
|
|
52322
52493
|
];
|
|
52323
52494
|
for (const t of targets) {
|
|
52324
52495
|
const tags = t.tags?.length ? ` tags=[${t.tags.join(",")}]` : "";
|
|
52325
|
-
const
|
|
52496
|
+
const path101 = t.defaultRemotePath ? ` remotePath=${t.defaultRemotePath}` : "";
|
|
52326
52497
|
const allow = t.allowedCommands?.length ? ` allowed=${t.allowedCommands.join("|")}` : " allowed=status-only";
|
|
52327
52498
|
const auth = t.auth === "password" ? " auth=password" : t.auth === "keyPath" ? " auth=key" : " auth=agent";
|
|
52328
52499
|
lines.push(
|
|
52329
|
-
`- id=${t.id} name=${t.name} ${t.user}@${t.host}:${t.port ?? 22}${auth}${
|
|
52500
|
+
`- id=${t.id} name=${t.name} ${t.user}@${t.host}:${t.port ?? 22}${auth}${path101}${tags}${allow}`
|
|
52330
52501
|
);
|
|
52331
52502
|
}
|
|
52332
52503
|
return lines.join("\n");
|
|
@@ -57055,6 +57226,7 @@ function parseHeadlessFlags(argv) {
|
|
|
57055
57226
|
let once = false;
|
|
57056
57227
|
let profile;
|
|
57057
57228
|
let resumeSessionId;
|
|
57229
|
+
let resumeMission = false;
|
|
57058
57230
|
let exportSessionPath;
|
|
57059
57231
|
let strictDone;
|
|
57060
57232
|
let missionStrict;
|
|
@@ -57201,6 +57373,8 @@ function parseHeadlessFlags(argv) {
|
|
|
57201
57373
|
}
|
|
57202
57374
|
profile = next;
|
|
57203
57375
|
i++;
|
|
57376
|
+
} else if (arg === "--resume-mission") {
|
|
57377
|
+
resumeMission = true;
|
|
57204
57378
|
} else if (arg === "--resume") {
|
|
57205
57379
|
const next = argv[i + 1];
|
|
57206
57380
|
if (!next || next.startsWith("--")) {
|
|
@@ -57223,6 +57397,8 @@ function parseHeadlessFlags(argv) {
|
|
|
57223
57397
|
missionStrict = true;
|
|
57224
57398
|
} else if (arg === "--no-mission-strict") {
|
|
57225
57399
|
missionStrict = false;
|
|
57400
|
+
} else if (arg === "--allow-unverified") {
|
|
57401
|
+
process.env.ZELARI_ALLOW_UNVERIFIED = "1";
|
|
57226
57402
|
} else if (arg === "--kraken-graph") {
|
|
57227
57403
|
krakenGraph = argv[i + 1];
|
|
57228
57404
|
i++;
|
|
@@ -57274,6 +57450,7 @@ function parseHeadlessFlags(argv) {
|
|
|
57274
57450
|
...history2 && history2.length > 0 ? { history: history2 } : {},
|
|
57275
57451
|
...todos2 && todos2.length > 0 ? { todos: todos2 } : {},
|
|
57276
57452
|
...once ? { once: true } : {},
|
|
57453
|
+
...resumeMission ? { resumeMission: true } : {},
|
|
57277
57454
|
...profile ? { profile } : {},
|
|
57278
57455
|
...resumeSessionId ? { resumeSessionId } : {},
|
|
57279
57456
|
...exportSessionPath ? { exportSessionPath } : {},
|
|
@@ -57335,6 +57512,7 @@ __export(headlessSpine_exports, {
|
|
|
57335
57512
|
seedHeadlessModelHistory: () => seedHeadlessModelHistory,
|
|
57336
57513
|
sessionStartedEvent: () => sessionStartedEvent
|
|
57337
57514
|
});
|
|
57515
|
+
import path67 from "node:path";
|
|
57338
57516
|
function sessionStartedEvent(handle) {
|
|
57339
57517
|
return {
|
|
57340
57518
|
type: "session_started",
|
|
@@ -57346,6 +57524,20 @@ function resolveHeadlessProfileId(mode, explicit) {
|
|
|
57346
57524
|
if (explicit) return resolveProfile(explicit).id;
|
|
57347
57525
|
return defaultProfileForMode(mode ?? "kraken");
|
|
57348
57526
|
}
|
|
57527
|
+
async function countVerificationEvidenceInLog(mirror, sessionId2) {
|
|
57528
|
+
if (mirror.status !== "active" && mirror.status !== "closed") return -1;
|
|
57529
|
+
try {
|
|
57530
|
+
await mirror.flush().catch(() => void 0);
|
|
57531
|
+
const report = await readSessionLog(path67.join(mirror.sessionsDir, sessionId2, "events.jsonl"));
|
|
57532
|
+
return report.events.filter((e) => e.kind === "verification.evidence").length;
|
|
57533
|
+
} catch (err) {
|
|
57534
|
+
process.stderr.write(
|
|
57535
|
+
`[zelari-code] verification-evidence count unavailable (${err instanceof Error ? err.message : String(err)}) \u2014 event-back gate skipped
|
|
57536
|
+
`
|
|
57537
|
+
);
|
|
57538
|
+
return -1;
|
|
57539
|
+
}
|
|
57540
|
+
}
|
|
57349
57541
|
async function openHeadlessSpine(opts) {
|
|
57350
57542
|
const profileId = resolveHeadlessProfileId(opts.mode, opts.profile);
|
|
57351
57543
|
let profileTools = [];
|
|
@@ -57417,6 +57609,9 @@ async function openHeadlessSpine(opts) {
|
|
|
57417
57609
|
lastVerificationRun() {
|
|
57418
57610
|
return spine.lastVerificationRun();
|
|
57419
57611
|
},
|
|
57612
|
+
countVerificationEvidence() {
|
|
57613
|
+
return countVerificationEvidenceInLog(spine, opts.sessionId);
|
|
57614
|
+
},
|
|
57420
57615
|
missionPhase(phase2, note) {
|
|
57421
57616
|
spine.missionPhase(phase2, note);
|
|
57422
57617
|
},
|
|
@@ -57524,6 +57719,7 @@ var init_headlessSpine = __esm({
|
|
|
57524
57719
|
init_dist();
|
|
57525
57720
|
init_session();
|
|
57526
57721
|
init_mission2();
|
|
57722
|
+
init_session();
|
|
57527
57723
|
init_runtime();
|
|
57528
57724
|
init_sessionSpine();
|
|
57529
57725
|
init_budgetRuntime();
|
|
@@ -58127,7 +58323,7 @@ var init_planDetect = __esm({
|
|
|
58127
58323
|
// src/cli/memory/legacyImport.ts
|
|
58128
58324
|
import { createHash as createHash18 } from "node:crypto";
|
|
58129
58325
|
import { promises as fs27 } from "node:fs";
|
|
58130
|
-
import * as
|
|
58326
|
+
import * as path68 from "node:path";
|
|
58131
58327
|
function sourceId(fact, line) {
|
|
58132
58328
|
return `jsonl:${fact.id ?? createHash18("sha256").update(line).digest("hex")}`;
|
|
58133
58329
|
}
|
|
@@ -58145,7 +58341,7 @@ function timestamp(value) {
|
|
|
58145
58341
|
}
|
|
58146
58342
|
async function importLegacyMemoryLog(backend, service) {
|
|
58147
58343
|
const result = { found: 0, imported: 0, skipped: 0, corrupt: 0 };
|
|
58148
|
-
const logPath =
|
|
58344
|
+
const logPath = path68.join(path68.dirname(backend.databasePath), "log.jsonl");
|
|
58149
58345
|
let raw;
|
|
58150
58346
|
try {
|
|
58151
58347
|
raw = await fs27.readFile(logPath, "utf8");
|
|
@@ -58328,7 +58524,7 @@ var init_sqliteCodec = __esm({
|
|
|
58328
58524
|
// src/cli/memory/sqliteRpc.ts
|
|
58329
58525
|
import { existsSync as existsSync36 } from "node:fs";
|
|
58330
58526
|
import { fileURLToPath as fileURLToPath2, pathToFileURL as pathToFileURL2 } from "node:url";
|
|
58331
|
-
import * as
|
|
58527
|
+
import * as path69 from "node:path";
|
|
58332
58528
|
import { Worker } from "node:worker_threads";
|
|
58333
58529
|
function isBusy(error51) {
|
|
58334
58530
|
const candidate = error51;
|
|
@@ -58337,10 +58533,10 @@ function isBusy(error51) {
|
|
|
58337
58533
|
);
|
|
58338
58534
|
}
|
|
58339
58535
|
function resolveWorkerUrl() {
|
|
58340
|
-
const here =
|
|
58341
|
-
const direct =
|
|
58536
|
+
const here = path69.dirname(fileURLToPath2(import.meta.url));
|
|
58537
|
+
const direct = path69.join(here, "sqliteWorker.mjs");
|
|
58342
58538
|
if (existsSync36(direct)) return pathToFileURL2(direct);
|
|
58343
|
-
return pathToFileURL2(
|
|
58539
|
+
return pathToFileURL2(path69.join(here, "memory", "sqliteWorker.mjs"));
|
|
58344
58540
|
}
|
|
58345
58541
|
var SqliteWorkerRpc;
|
|
58346
58542
|
var init_sqliteRpc = __esm({
|
|
@@ -58629,7 +58825,7 @@ WHERE NOT EXISTS (SELECT 1 FROM memory_fts f WHERE f.node_id = n.id);
|
|
|
58629
58825
|
// src/cli/memory/sqliteBackend.ts
|
|
58630
58826
|
import { createHash as createHash19, randomUUID as randomUUID6 } from "node:crypto";
|
|
58631
58827
|
import { promises as fs28 } from "node:fs";
|
|
58632
|
-
import * as
|
|
58828
|
+
import * as path70 from "node:path";
|
|
58633
58829
|
function boundedLimit(value, fallback = 50) {
|
|
58634
58830
|
return Math.max(1, Math.min(Math.floor(value ?? fallback), 1e5));
|
|
58635
58831
|
}
|
|
@@ -58691,16 +58887,16 @@ VALUES (${Array.from({ length: 19 }, () => "?").join(",")})`;
|
|
|
58691
58887
|
try {
|
|
58692
58888
|
resolved = await fs28.realpath(projectRoot);
|
|
58693
58889
|
} catch {
|
|
58694
|
-
resolved =
|
|
58890
|
+
resolved = path70.resolve(projectRoot);
|
|
58695
58891
|
}
|
|
58696
58892
|
if (this.initialized && resolved === this.projectRoot) return;
|
|
58697
58893
|
if (this.initialized) await this.close();
|
|
58698
58894
|
const filename = this.options.filename ?? "memory.db";
|
|
58699
|
-
if (
|
|
58895
|
+
if (path70.basename(filename) !== filename || filename === "." || filename === "..") {
|
|
58700
58896
|
throw new Error("SQLite memory filename must not contain a path.");
|
|
58701
58897
|
}
|
|
58702
|
-
const zelariDirectory =
|
|
58703
|
-
const directory =
|
|
58898
|
+
const zelariDirectory = path70.join(resolved, ".zelari");
|
|
58899
|
+
const directory = path70.join(zelariDirectory, "memory");
|
|
58704
58900
|
for (const candidate of [zelariDirectory, directory]) {
|
|
58705
58901
|
let stat8;
|
|
58706
58902
|
try {
|
|
@@ -58719,12 +58915,12 @@ VALUES (${Array.from({ length: 19 }, () => "?").join(",")})`;
|
|
|
58719
58915
|
}
|
|
58720
58916
|
}
|
|
58721
58917
|
const canonicalDirectory = await fs28.realpath(directory);
|
|
58722
|
-
const relativeDirectory =
|
|
58723
|
-
if (relativeDirectory.startsWith("..") ||
|
|
58918
|
+
const relativeDirectory = path70.relative(resolved, canonicalDirectory);
|
|
58919
|
+
if (relativeDirectory.startsWith("..") || path70.isAbsolute(relativeDirectory)) {
|
|
58724
58920
|
throw new Error("SQLite memory directory resolves outside the active project.");
|
|
58725
58921
|
}
|
|
58726
58922
|
this.projectRoot = resolved;
|
|
58727
|
-
this.databasePath =
|
|
58923
|
+
this.databasePath = path70.join(canonicalDirectory, filename);
|
|
58728
58924
|
const opened = await this.rpc.open({
|
|
58729
58925
|
dbPath: this.databasePath,
|
|
58730
58926
|
schemaSql: SQLITE_MEMORY_BASE_SCHEMA,
|
|
@@ -59257,7 +59453,7 @@ __export(serviceFactory_exports, {
|
|
|
59257
59453
|
});
|
|
59258
59454
|
import { createHash as createHash20 } from "node:crypto";
|
|
59259
59455
|
import { promises as fs29 } from "node:fs";
|
|
59260
|
-
import * as
|
|
59456
|
+
import * as path71 from "node:path";
|
|
59261
59457
|
function isMemoryV2Enabled(env = process.env) {
|
|
59262
59458
|
if (env.ZELARI_MEMORY === "0") return false;
|
|
59263
59459
|
if (env.ZELARI_MEMORY_BACKEND === "file" || env.ZELARI_MEMORY_BACKEND === "jsonl") return false;
|
|
@@ -59278,7 +59474,7 @@ async function canonicalProjectId(projectRoot) {
|
|
|
59278
59474
|
try {
|
|
59279
59475
|
canonical = await fs29.realpath(projectRoot);
|
|
59280
59476
|
} catch {
|
|
59281
|
-
canonical =
|
|
59477
|
+
canonical = path71.resolve(projectRoot);
|
|
59282
59478
|
}
|
|
59283
59479
|
canonical = canonical.replace(/\\/g, "/").replace(/\/$/, "");
|
|
59284
59480
|
if (process.platform === "win32") canonical = canonical.toLocaleLowerCase("en-US");
|
|
@@ -59980,8 +60176,8 @@ function readPlan(ctx) {
|
|
|
59980
60176
|
} catch {
|
|
59981
60177
|
}
|
|
59982
60178
|
}
|
|
59983
|
-
const
|
|
59984
|
-
const doc = ctx.storage.readIfExists(
|
|
60179
|
+
const path101 = workspaceFile(ctx.rootDir, "plan");
|
|
60180
|
+
const doc = ctx.storage.readIfExists(path101);
|
|
59985
60181
|
if (!doc) return { phases: [], tasks: [], milestones: [] };
|
|
59986
60182
|
const meta3 = doc.meta;
|
|
59987
60183
|
return {
|
|
@@ -60162,7 +60358,7 @@ function addMilestoneRecord(ctx, summary, input) {
|
|
|
60162
60358
|
dueDate: input.dueDate,
|
|
60163
60359
|
targetVersion: version2
|
|
60164
60360
|
});
|
|
60165
|
-
const
|
|
60361
|
+
const path101 = join31(ctx.rootDir, "milestones", `${id3}.md`);
|
|
60166
60362
|
const meta3 = {
|
|
60167
60363
|
kind: "milestone",
|
|
60168
60364
|
id: id3,
|
|
@@ -60179,7 +60375,7 @@ function addMilestoneRecord(ctx, summary, input) {
|
|
|
60179
60375
|
`Target version: ${version2}`,
|
|
60180
60376
|
""
|
|
60181
60377
|
].join("\n");
|
|
60182
|
-
ctx.storage.write(
|
|
60378
|
+
ctx.storage.write(path101, meta3, body);
|
|
60183
60379
|
return { id: id3, created: true };
|
|
60184
60380
|
}
|
|
60185
60381
|
function readPlanSummary(ctx) {
|
|
@@ -60383,7 +60579,7 @@ function addIdeaStub(ctx) {
|
|
|
60383
60579
|
const tags = args["tags"] ?? [];
|
|
60384
60580
|
const category = args["category"] ?? "General";
|
|
60385
60581
|
const id3 = `${nextAdrId(ctx)}-${slugify3(title)}`;
|
|
60386
|
-
const
|
|
60582
|
+
const path101 = workspaceArtifact(ctx.rootDir, "decisions", id3);
|
|
60387
60583
|
const meta3 = {
|
|
60388
60584
|
kind: "adr",
|
|
60389
60585
|
status: "proposed",
|
|
@@ -60409,7 +60605,7 @@ function addIdeaStub(ctx) {
|
|
|
60409
60605
|
...consequences.map((c) => `- ${c}`),
|
|
60410
60606
|
""
|
|
60411
60607
|
].join("\n");
|
|
60412
|
-
ctx.storage.write(
|
|
60608
|
+
ctx.storage.write(path101, meta3, body);
|
|
60413
60609
|
return `ADR ${id3} created: "${title}". Status: proposed. Promote to accepted via /update ADR or manual edit.`;
|
|
60414
60610
|
});
|
|
60415
60611
|
}
|
|
@@ -60491,14 +60687,14 @@ function createDocumentStub(ctx) {
|
|
|
60491
60687
|
ctx.storage.write(risksPath, riskMeta, content);
|
|
60492
60688
|
return `Document "${title}" created at risks.md (workspace root).`;
|
|
60493
60689
|
}
|
|
60494
|
-
const
|
|
60690
|
+
const path101 = workspaceArtifact(ctx.rootDir, "docs", slug);
|
|
60495
60691
|
const meta3 = {
|
|
60496
60692
|
kind: "doc",
|
|
60497
60693
|
id: slug,
|
|
60498
60694
|
date: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10),
|
|
60499
60695
|
tags
|
|
60500
60696
|
};
|
|
60501
|
-
ctx.storage.write(
|
|
60697
|
+
ctx.storage.write(path101, meta3, content);
|
|
60502
60698
|
return `Document "${title}" created at docs/${slug}.md.`;
|
|
60503
60699
|
});
|
|
60504
60700
|
}
|
|
@@ -61123,10 +61319,10 @@ function getUserMcpPath() {
|
|
|
61123
61319
|
function getProjectMcpPath(projectRoot) {
|
|
61124
61320
|
return join32(projectRoot, ".zelari", "mcp.json");
|
|
61125
61321
|
}
|
|
61126
|
-
function readFile9(
|
|
61127
|
-
if (!existsSync42(
|
|
61322
|
+
function readFile9(path101) {
|
|
61323
|
+
if (!existsSync42(path101)) return {};
|
|
61128
61324
|
try {
|
|
61129
|
-
const parsed = JSON.parse(readFileSync30(
|
|
61325
|
+
const parsed = JSON.parse(readFileSync30(path101, "utf8"));
|
|
61130
61326
|
const out = {};
|
|
61131
61327
|
for (const [name, cfg] of Object.entries(parsed.mcpServers ?? {})) {
|
|
61132
61328
|
const hasCommand = !!cfg && typeof cfg.command === "string" && !!cfg.command.trim();
|
|
@@ -61148,10 +61344,10 @@ function readFile9(path100) {
|
|
|
61148
61344
|
return {};
|
|
61149
61345
|
}
|
|
61150
61346
|
}
|
|
61151
|
-
function writeFile3(
|
|
61152
|
-
mkdirSync17(dirname9(
|
|
61347
|
+
function writeFile3(path101, servers) {
|
|
61348
|
+
mkdirSync17(dirname9(path101), { recursive: true });
|
|
61153
61349
|
const body = { mcpServers: servers };
|
|
61154
|
-
writeFileSync19(
|
|
61350
|
+
writeFileSync19(path101, `${JSON.stringify(body, null, 2)}
|
|
61155
61351
|
`, "utf8");
|
|
61156
61352
|
}
|
|
61157
61353
|
function listMcpServers(projectRoot) {
|
|
@@ -61189,9 +61385,9 @@ function upsertMcpServer(opts) {
|
|
|
61189
61385
|
error: "either command (stdio) or url (http) is required"
|
|
61190
61386
|
};
|
|
61191
61387
|
}
|
|
61192
|
-
let
|
|
61388
|
+
let path101;
|
|
61193
61389
|
if (opts.scope === "user") {
|
|
61194
|
-
|
|
61390
|
+
path101 = getUserMcpPath();
|
|
61195
61391
|
} else {
|
|
61196
61392
|
const root = opts.projectRoot?.trim();
|
|
61197
61393
|
if (!root) {
|
|
@@ -61200,9 +61396,9 @@ function upsertMcpServer(opts) {
|
|
|
61200
61396
|
error: "projectRoot required for project scope (Open Folder first)"
|
|
61201
61397
|
};
|
|
61202
61398
|
}
|
|
61203
|
-
|
|
61399
|
+
path101 = getProjectMcpPath(root);
|
|
61204
61400
|
}
|
|
61205
|
-
const current = readFile9(
|
|
61401
|
+
const current = readFile9(path101);
|
|
61206
61402
|
current[name] = {
|
|
61207
61403
|
command: hasCommand ? opts.config.command.trim() : void 0,
|
|
61208
61404
|
args: opts.config.args,
|
|
@@ -61213,21 +61409,21 @@ function upsertMcpServer(opts) {
|
|
|
61213
61409
|
serial: opts.config.serial,
|
|
61214
61410
|
enabled: opts.config.enabled !== false
|
|
61215
61411
|
};
|
|
61216
|
-
writeFile3(
|
|
61217
|
-
return { ok: true, path:
|
|
61412
|
+
writeFile3(path101, current);
|
|
61413
|
+
return { ok: true, path: path101 };
|
|
61218
61414
|
}
|
|
61219
61415
|
function removeMcpServer(opts) {
|
|
61220
|
-
const
|
|
61221
|
-
if (!
|
|
61416
|
+
const path101 = opts.scope === "user" ? getUserMcpPath() : opts.projectRoot ? getProjectMcpPath(opts.projectRoot) : null;
|
|
61417
|
+
if (!path101) {
|
|
61222
61418
|
return { ok: false, error: "projectRoot required for project scope" };
|
|
61223
61419
|
}
|
|
61224
|
-
const current = readFile9(
|
|
61420
|
+
const current = readFile9(path101);
|
|
61225
61421
|
if (!(opts.name in current)) {
|
|
61226
|
-
return { ok: false, error: `Server "${opts.name}" not found in ${
|
|
61422
|
+
return { ok: false, error: `Server "${opts.name}" not found in ${path101}` };
|
|
61227
61423
|
}
|
|
61228
61424
|
delete current[opts.name];
|
|
61229
|
-
writeFile3(
|
|
61230
|
-
return { ok: true, path:
|
|
61425
|
+
writeFile3(path101, current);
|
|
61426
|
+
return { ok: true, path: path101 };
|
|
61231
61427
|
}
|
|
61232
61428
|
var init_mcpConfigIo = __esm({
|
|
61233
61429
|
"src/cli/mcp/mcpConfigIo.ts"() {
|
|
@@ -61698,10 +61894,10 @@ import { createHash as createHash21 } from "node:crypto";
|
|
|
61698
61894
|
import { join as join34 } from "node:path";
|
|
61699
61895
|
import { readFile as readFile10 } from "node:fs/promises";
|
|
61700
61896
|
async function readPackageJson3(projectRoot) {
|
|
61701
|
-
const
|
|
61702
|
-
if (!existsSync44(
|
|
61897
|
+
const path101 = join34(projectRoot, "package.json");
|
|
61898
|
+
if (!existsSync44(path101)) return null;
|
|
61703
61899
|
try {
|
|
61704
|
-
return JSON.parse(await readFile10(
|
|
61900
|
+
return JSON.parse(await readFile10(path101, "utf8"));
|
|
61705
61901
|
} catch {
|
|
61706
61902
|
return null;
|
|
61707
61903
|
}
|
|
@@ -61783,9 +61979,9 @@ async function genBuild(ctx) {
|
|
|
61783
61979
|
].join("\n");
|
|
61784
61980
|
}
|
|
61785
61981
|
async function genOpenQuestions(ctx) {
|
|
61786
|
-
const
|
|
61787
|
-
if (!existsSync44(
|
|
61788
|
-
const content = readFileSync32(
|
|
61982
|
+
const path101 = join34(ctx.rootDir, "risks.md");
|
|
61983
|
+
if (!existsSync44(path101)) return "_No open questions._";
|
|
61984
|
+
const content = readFileSync32(path101, "utf8");
|
|
61789
61985
|
const lines = content.split("\n");
|
|
61790
61986
|
const questions = [];
|
|
61791
61987
|
let currentTitle = "";
|
|
@@ -62059,9 +62255,9 @@ function versionKey(value) {
|
|
|
62059
62255
|
function firstString2(v) {
|
|
62060
62256
|
return typeof v === "string" && v.trim().length > 0 ? v : null;
|
|
62061
62257
|
}
|
|
62062
|
-
function readFileSyncSafe(
|
|
62258
|
+
function readFileSyncSafe(path101) {
|
|
62063
62259
|
try {
|
|
62064
|
-
return readFileSync33(
|
|
62260
|
+
return readFileSync33(path101, "utf8");
|
|
62065
62261
|
} catch {
|
|
62066
62262
|
return null;
|
|
62067
62263
|
}
|
|
@@ -62309,7 +62505,7 @@ __export(evidenceFromSpine_exports, {
|
|
|
62309
62505
|
evidenceRefsFromEventLines: () => evidenceRefsFromEventLines
|
|
62310
62506
|
});
|
|
62311
62507
|
import { existsSync as existsSync47, readFileSync as readFileSync35 } from "node:fs";
|
|
62312
|
-
import
|
|
62508
|
+
import path72 from "node:path";
|
|
62313
62509
|
function asRecord2(v) {
|
|
62314
62510
|
return v && typeof v === "object" && !Array.isArray(v) ? v : void 0;
|
|
62315
62511
|
}
|
|
@@ -62347,7 +62543,7 @@ function evidenceRefsFromEventLines(lines) {
|
|
|
62347
62543
|
}
|
|
62348
62544
|
function collectSessionEvidenceRefs(sessionId2) {
|
|
62349
62545
|
try {
|
|
62350
|
-
const file2 =
|
|
62546
|
+
const file2 = path72.join(sessionsDir(), sessionId2, "events.jsonl");
|
|
62351
62547
|
if (!existsSync47(file2)) return [];
|
|
62352
62548
|
return evidenceRefsFromEventLines(readFileSync35(file2, "utf8").split("\n"));
|
|
62353
62549
|
} catch {
|
|
@@ -62597,8 +62793,8 @@ async function runPostCouncilHook(ctx, options) {
|
|
|
62597
62793
|
sources: scope.sources
|
|
62598
62794
|
} : void 0
|
|
62599
62795
|
});
|
|
62600
|
-
const
|
|
62601
|
-
completionHook = { ran: true, path:
|
|
62796
|
+
const path101 = writeCouncilCompletion(ctx.rootDir, completion);
|
|
62797
|
+
completionHook = { ran: true, path: path101, completion };
|
|
62602
62798
|
} catch (err) {
|
|
62603
62799
|
completionHook = {
|
|
62604
62800
|
ran: true,
|
|
@@ -62643,7 +62839,7 @@ import {
|
|
|
62643
62839
|
writeFileSync as writeFileSync22,
|
|
62644
62840
|
mkdirSync as mkdirSync18
|
|
62645
62841
|
} from "node:fs";
|
|
62646
|
-
import
|
|
62842
|
+
import path73 from "node:path";
|
|
62647
62843
|
var FeedbackStore;
|
|
62648
62844
|
var init_councilFeedback = __esm({
|
|
62649
62845
|
"src/cli/councilFeedback.ts"() {
|
|
@@ -62760,7 +62956,7 @@ var init_councilFeedback = __esm({
|
|
|
62760
62956
|
}
|
|
62761
62957
|
}
|
|
62762
62958
|
save() {
|
|
62763
|
-
mkdirSync18(
|
|
62959
|
+
mkdirSync18(path73.dirname(this.file), { recursive: true });
|
|
62764
62960
|
writeFileSync22(
|
|
62765
62961
|
this.file,
|
|
62766
62962
|
JSON.stringify({ entries: this.entries }, null, 2),
|
|
@@ -62835,12 +63031,12 @@ __export(ledger_exports, {
|
|
|
62835
63031
|
readLedger: () => readLedger
|
|
62836
63032
|
});
|
|
62837
63033
|
import { appendFileSync as appendFileSync4, existsSync as existsSync50, mkdirSync as mkdirSync19, readFileSync as readFileSync38 } from "node:fs";
|
|
62838
|
-
import
|
|
63034
|
+
import path74 from "node:path";
|
|
62839
63035
|
function evolutionMode(env = process.env) {
|
|
62840
63036
|
return env[EVOLUTION_ENV] === "shadow" ? "shadow" : "0";
|
|
62841
63037
|
}
|
|
62842
63038
|
function ledgerPath(cwd) {
|
|
62843
|
-
return
|
|
63039
|
+
return path74.join(cwd, LEDGER_REL);
|
|
62844
63040
|
}
|
|
62845
63041
|
function appendLedgerEntry(cwd, entry) {
|
|
62846
63042
|
if (evolutionMode() === "0") {
|
|
@@ -62848,7 +63044,7 @@ function appendLedgerEntry(cwd, entry) {
|
|
|
62848
63044
|
}
|
|
62849
63045
|
try {
|
|
62850
63046
|
const file2 = ledgerPath(cwd);
|
|
62851
|
-
mkdirSync19(
|
|
63047
|
+
mkdirSync19(path74.dirname(file2), { recursive: true });
|
|
62852
63048
|
appendFileSync4(file2, `${JSON.stringify(entry)}
|
|
62853
63049
|
`, "utf8");
|
|
62854
63050
|
return { written: true, path: file2 };
|
|
@@ -62949,7 +63145,7 @@ var init_ledger = __esm({
|
|
|
62949
63145
|
"src/cli/evolution/ledger.ts"() {
|
|
62950
63146
|
"use strict";
|
|
62951
63147
|
EVOLUTION_ENV = "ZELARI_EVOLUTION";
|
|
62952
|
-
LEDGER_REL =
|
|
63148
|
+
LEDGER_REL = path74.join(".zelari", "evolution", "ledger.jsonl");
|
|
62953
63149
|
TIER_WEIGHTS = {
|
|
62954
63150
|
build: 1,
|
|
62955
63151
|
"tool-output": 1,
|
|
@@ -63091,7 +63287,7 @@ __export(fileBackend_exports, {
|
|
|
63091
63287
|
});
|
|
63092
63288
|
import { randomUUID as randomUUID7 } from "node:crypto";
|
|
63093
63289
|
import { promises as fs31 } from "node:fs";
|
|
63094
|
-
import * as
|
|
63290
|
+
import * as path75 from "node:path";
|
|
63095
63291
|
function tokenize2(text) {
|
|
63096
63292
|
return text.toLowerCase().split(/[^\p{L}\p{N}]+/u).filter((t) => t.length >= 3);
|
|
63097
63293
|
}
|
|
@@ -63144,8 +63340,8 @@ var init_fileBackend = __esm({
|
|
|
63144
63340
|
logPath = "";
|
|
63145
63341
|
memoryDir = "";
|
|
63146
63342
|
async init(projectRoot) {
|
|
63147
|
-
this.memoryDir =
|
|
63148
|
-
this.logPath =
|
|
63343
|
+
this.memoryDir = path75.join(projectRoot, ".zelari", "memory");
|
|
63344
|
+
this.logPath = path75.join(this.memoryDir, "log.jsonl");
|
|
63149
63345
|
await fs31.mkdir(this.memoryDir, { recursive: true });
|
|
63150
63346
|
}
|
|
63151
63347
|
async add(content, metadata2 = {}, graph) {
|
|
@@ -63218,12 +63414,12 @@ var init_fileBackend = __esm({
|
|
|
63218
63414
|
|
|
63219
63415
|
// src/cli/traceStore.ts
|
|
63220
63416
|
import { promises as fs32 } from "node:fs";
|
|
63221
|
-
import * as
|
|
63417
|
+
import * as path76 from "node:path";
|
|
63222
63418
|
function traceDir(projectRoot) {
|
|
63223
|
-
return
|
|
63419
|
+
return path76.join(projectRoot, ".zelari", "trace");
|
|
63224
63420
|
}
|
|
63225
63421
|
function tracePath(projectRoot, missionId) {
|
|
63226
|
-
return
|
|
63422
|
+
return path76.join(traceDir(projectRoot), `${missionId}.json`);
|
|
63227
63423
|
}
|
|
63228
63424
|
async function saveTrace(projectRoot, missionId, entries) {
|
|
63229
63425
|
const dir = traceDir(projectRoot);
|
|
@@ -63248,19 +63444,24 @@ var init_traceStore = __esm({
|
|
|
63248
63444
|
// src/cli/zelariMission.ts
|
|
63249
63445
|
var zelariMission_exports = {};
|
|
63250
63446
|
__export(zelariMission_exports, {
|
|
63447
|
+
MissionResumeError: () => MissionResumeError,
|
|
63251
63448
|
formatBriefForChat: () => formatBriefForChat,
|
|
63252
63449
|
isMissionAutoStart: () => isMissionAutoStart,
|
|
63450
|
+
isResumableMission: () => isResumableMission,
|
|
63451
|
+
loadMissionState: () => loadMissionState,
|
|
63253
63452
|
missionGapKey: () => missionGapKey,
|
|
63254
63453
|
missionPressure: () => missionPressure,
|
|
63255
63454
|
resolveMaxCost: () => resolveMaxCost,
|
|
63256
63455
|
resolveMaxIterations: () => resolveMaxIterations,
|
|
63257
63456
|
resolveMaxStall: () => resolveMaxStall,
|
|
63258
63457
|
resolveMaxTokens: () => resolveMaxTokens,
|
|
63458
|
+
resolveMissionSlices: () => resolveMissionSlices,
|
|
63459
|
+
resumeZelariMission: () => resumeZelariMission,
|
|
63259
63460
|
runZelariMission: () => runZelariMission
|
|
63260
63461
|
});
|
|
63261
63462
|
import { randomUUID as randomUUID8 } from "node:crypto";
|
|
63262
63463
|
import { promises as fs33 } from "node:fs";
|
|
63263
|
-
import * as
|
|
63464
|
+
import * as path77 from "node:path";
|
|
63264
63465
|
function resolveMaxIterations(env = process.env) {
|
|
63265
63466
|
const raw = env.ZELARI_MISSION_MAX_ITER;
|
|
63266
63467
|
const n = raw ? Number.parseInt(raw, 10) : DEFAULT_MAX_ITER;
|
|
@@ -63303,10 +63504,10 @@ function isMissionAutoStart(env = process.env) {
|
|
|
63303
63504
|
return env.ZELARI_MISSION_AUTO === "1";
|
|
63304
63505
|
}
|
|
63305
63506
|
async function writeMissionState(projectRoot, state3) {
|
|
63306
|
-
const dir =
|
|
63507
|
+
const dir = path77.join(projectRoot, ".zelari");
|
|
63307
63508
|
await fs33.mkdir(dir, { recursive: true });
|
|
63308
63509
|
await fs33.writeFile(
|
|
63309
|
-
|
|
63510
|
+
path77.join(dir, "mission-state.json"),
|
|
63310
63511
|
JSON.stringify(state3, null, 2) + "\n",
|
|
63311
63512
|
"utf8"
|
|
63312
63513
|
);
|
|
@@ -63317,16 +63518,42 @@ async function writeMissionState(projectRoot, state3) {
|
|
|
63317
63518
|
}
|
|
63318
63519
|
}
|
|
63319
63520
|
}
|
|
63320
|
-
function
|
|
63521
|
+
async function loadMissionState(projectRoot) {
|
|
63522
|
+
try {
|
|
63523
|
+
const raw = await fs33.readFile(
|
|
63524
|
+
path77.join(projectRoot, ".zelari", "mission-state.json"),
|
|
63525
|
+
"utf8"
|
|
63526
|
+
);
|
|
63527
|
+
const parsed = JSON.parse(raw);
|
|
63528
|
+
if (!parsed || typeof parsed.missionId !== "string" || !parsed.brief) return void 0;
|
|
63529
|
+
return parsed;
|
|
63530
|
+
} catch {
|
|
63531
|
+
return void 0;
|
|
63532
|
+
}
|
|
63533
|
+
}
|
|
63534
|
+
function isResumableMission(state3) {
|
|
63535
|
+
return !!state3 && state3.status !== "success";
|
|
63536
|
+
}
|
|
63537
|
+
function resolveMissionSlices(brief) {
|
|
63538
|
+
const slices = Array.isArray(brief.slices) ? brief.slices.filter((s) => s && !!s.id) : [];
|
|
63539
|
+
return slices.length ? slices : [brief.sliceMvp];
|
|
63540
|
+
}
|
|
63541
|
+
function countImplementationSlices(state3) {
|
|
63542
|
+
return Array.isArray(state3.trace) ? state3.trace.filter((t) => t?.runMode === "implementation").length : 0;
|
|
63543
|
+
}
|
|
63544
|
+
function buildSlicePrompt(brief, userMessage, runMode, iteration, slice) {
|
|
63321
63545
|
if (runMode === "design-phase") {
|
|
63322
63546
|
return `${userMessage}
|
|
63323
63547
|
|
|
63324
|
-
[Zelari mission] Produce the design-phase plan for the MVP: ${brief.deliverableThisMission}. Keep the first slice to at most ${
|
|
63548
|
+
[Zelari mission] Produce the design-phase plan for the MVP: ${brief.deliverableThisMission}. Keep the first slice to at most ${slice.maxTasks ?? 8} tasks.`;
|
|
63325
63549
|
}
|
|
63326
63550
|
const fix = iteration > 1 ? " Address any remaining verification failures recorded in .zelari/completion.json." : "";
|
|
63551
|
+
const isMvpSlice = slice.id === resolveMissionSlices(brief)[0].id;
|
|
63552
|
+
const target = isMvpSlice ? "the MVP slice" : `increment "${slice.title}"`;
|
|
63553
|
+
const scope = slice.taskIds?.length ? ` Scope: plan tasks ${slice.taskIds.join(", ")}.` : "";
|
|
63327
63554
|
return `${userMessage}
|
|
63328
63555
|
|
|
63329
|
-
[Zelari mission] Implement
|
|
63556
|
+
[Zelari mission] Implement ${target}: ${brief.deliverableThisMission}.${scope}${fix} You MUST create or modify the real project files with write_file / edit \u2014 not just describe them in prose. A run that claims completion without writing any file is a failed run and will not be accepted.`;
|
|
63330
63557
|
}
|
|
63331
63558
|
function formatBriefForChat(brief) {
|
|
63332
63559
|
const lines = [
|
|
@@ -63346,34 +63573,74 @@ function formatBriefForChat(brief) {
|
|
|
63346
63573
|
lines.push(" out of scope:");
|
|
63347
63574
|
for (const o of brief.outOfScope) lines.push(` - ${o}`);
|
|
63348
63575
|
}
|
|
63576
|
+
const slices = resolveMissionSlices(brief);
|
|
63349
63577
|
lines.push(` MVP slice: ${brief.sliceMvp.title} (\u2264 ${brief.sliceMvp.maxTasks} tasks)`);
|
|
63578
|
+
if (slices.length > 1) {
|
|
63579
|
+
lines.push(` increments: ${slices.length} (gated: slice N+1 starts only when N is green)`);
|
|
63580
|
+
for (const s of slices.slice(1)) lines.push(` - ${s.id}: ${s.title}`);
|
|
63581
|
+
}
|
|
63350
63582
|
return lines.join("\n");
|
|
63351
63583
|
}
|
|
63352
63584
|
async function runZelariMission(userMessage, brief, deps) {
|
|
63353
63585
|
const now = deps.now ?? (() => /* @__PURE__ */ new Date());
|
|
63354
|
-
const maxIter = deps.maxIterations ?? resolveMaxIterations(deps.env);
|
|
63355
|
-
const maxStall = resolveMaxStall(deps.env);
|
|
63356
|
-
const maxCost = resolveMaxCost(deps.env);
|
|
63357
|
-
const maxTokens = resolveMaxTokens(deps.env);
|
|
63358
|
-
const missionId = deps.missionId ?? `m_${randomUUID8().slice(0, 8)}`;
|
|
63359
63586
|
const startedAt = now().toISOString();
|
|
63360
63587
|
const state3 = {
|
|
63361
|
-
missionId,
|
|
63588
|
+
missionId: deps.missionId ?? `m_${randomUUID8().slice(0, 8)}`,
|
|
63362
63589
|
userPrompt: userMessage,
|
|
63363
63590
|
brief,
|
|
63364
63591
|
iteration: 0,
|
|
63365
|
-
currentSliceId: brief.
|
|
63592
|
+
currentSliceId: resolveMissionSlices(brief)[0].id,
|
|
63366
63593
|
status: "running",
|
|
63367
63594
|
lastCompletionOk: false,
|
|
63368
63595
|
startedAt,
|
|
63369
63596
|
updatedAt: startedAt
|
|
63370
63597
|
};
|
|
63598
|
+
return driveMission(userMessage, brief, deps, state3, false);
|
|
63599
|
+
}
|
|
63600
|
+
async function resumeZelariMission(deps) {
|
|
63601
|
+
const loaded = await loadMissionState(deps.projectRoot);
|
|
63602
|
+
if (!loaded) {
|
|
63603
|
+
throw new MissionResumeError(
|
|
63604
|
+
"nessuna missione da riprendere: .zelari/mission-state.json assente o illeggibile."
|
|
63605
|
+
);
|
|
63606
|
+
}
|
|
63607
|
+
if (!isResumableMission(loaded)) {
|
|
63608
|
+
throw new MissionResumeError(
|
|
63609
|
+
`la missione ${loaded.missionId} \xE8 gi\xE0 completata (status=success).`
|
|
63610
|
+
);
|
|
63611
|
+
}
|
|
63612
|
+
const brief = loaded.brief;
|
|
63613
|
+
const userMessage = loaded.userPrompt ?? brief.userPromptOriginal;
|
|
63614
|
+
deps.emit(
|
|
63615
|
+
`[zelari] resume missione ${loaded.missionId} \u2014 step ${loaded.iteration}, slice ${loaded.currentSliceId}, status precedente ${loaded.status}`
|
|
63616
|
+
);
|
|
63617
|
+
return driveMission(userMessage, brief, deps, loaded, true);
|
|
63618
|
+
}
|
|
63619
|
+
async function driveMission(userMessage, brief, deps, state3, resumed) {
|
|
63620
|
+
const now = deps.now ?? (() => /* @__PURE__ */ new Date());
|
|
63621
|
+
const maxIter = deps.maxIterations ?? resolveMaxIterations(deps.env);
|
|
63622
|
+
const maxStall = resolveMaxStall(deps.env);
|
|
63623
|
+
const maxCost = resolveMaxCost(deps.env);
|
|
63624
|
+
const maxTokens = resolveMaxTokens(deps.env);
|
|
63625
|
+
const missionId = state3.missionId;
|
|
63626
|
+
const slices = resolveMissionSlices(brief);
|
|
63627
|
+
let sliceIndex = resumed ? Math.max(
|
|
63628
|
+
0,
|
|
63629
|
+
slices.findIndex((s) => s.id === state3.currentSliceId)
|
|
63630
|
+
) : 0;
|
|
63631
|
+
const currentSlice = () => slices[sliceIndex] ?? slices[0];
|
|
63632
|
+
state3.currentSliceId = currentSlice().id;
|
|
63633
|
+
state3.status = "running";
|
|
63634
|
+
state3.updatedAt = now().toISOString();
|
|
63371
63635
|
await deps.memory.init(deps.projectRoot);
|
|
63372
63636
|
const persist = async () => {
|
|
63373
63637
|
await writeMissionState(deps.projectRoot, state3);
|
|
63374
63638
|
await deps.onStatePersisted?.(state3);
|
|
63375
63639
|
};
|
|
63376
|
-
deps.onMissionPhase?.(
|
|
63640
|
+
deps.onMissionPhase?.(
|
|
63641
|
+
resumed ? "build" : "design",
|
|
63642
|
+
resumed ? "mission-resume" : "mission-start"
|
|
63643
|
+
);
|
|
63377
63644
|
await persist();
|
|
63378
63645
|
const stateStore = deps.stateStore ?? await getStateStore(deps.projectRoot, deps.env ?? process.env);
|
|
63379
63646
|
try {
|
|
@@ -63381,7 +63648,7 @@ async function runZelariMission(userMessage, brief, deps) {
|
|
|
63381
63648
|
} catch {
|
|
63382
63649
|
}
|
|
63383
63650
|
let missionCheckpointId;
|
|
63384
|
-
if ((deps.env ?? process.env).ZELARI_CHECKPOINT !== "0") {
|
|
63651
|
+
if (!resumed && (deps.env ?? process.env).ZELARI_CHECKPOINT !== "0") {
|
|
63385
63652
|
const cp = await createCheckpoint(deps.projectRoot, `zelari mission ${missionId}`);
|
|
63386
63653
|
if (cp.ok) {
|
|
63387
63654
|
missionCheckpointId = cp.value.id;
|
|
@@ -63392,11 +63659,11 @@ async function runZelariMission(userMessage, brief, deps) {
|
|
|
63392
63659
|
}
|
|
63393
63660
|
const designFirst = brief.phases[0]?.mode === "design-phase";
|
|
63394
63661
|
let noWriteStreak = 0;
|
|
63395
|
-
let step = 0;
|
|
63396
|
-
let implStep = 0;
|
|
63397
|
-
let pendingDesign = designFirst;
|
|
63398
|
-
let cumulativeCostUsd = 0;
|
|
63399
|
-
let cumulativeTokens = 0;
|
|
63662
|
+
let step = resumed ? state3.iteration : 0;
|
|
63663
|
+
let implStep = resumed ? countImplementationSlices(state3) : 0;
|
|
63664
|
+
let pendingDesign = designFirst && !resumed;
|
|
63665
|
+
let cumulativeCostUsd = resumed ? state3.cumulativeCostUsd ?? 0 : 0;
|
|
63666
|
+
let cumulativeTokens = resumed ? state3.cumulativeTokens ?? 0 : 0;
|
|
63400
63667
|
const repairHistory = Array.isArray(state3.repairHistory) ? [...state3.repairHistory] : [];
|
|
63401
63668
|
let forcePivot = false;
|
|
63402
63669
|
const missionStartMs = now().getTime();
|
|
@@ -63424,25 +63691,25 @@ async function runZelariMission(userMessage, brief, deps) {
|
|
|
63424
63691
|
});
|
|
63425
63692
|
const ragContext = formatMemoryHits(hits);
|
|
63426
63693
|
const promptIter = runMode === "implementation" ? implStep : 1;
|
|
63427
|
-
const slicePrompt = buildSlicePrompt(brief, userMessage, runMode, promptIter);
|
|
63694
|
+
const slicePrompt = buildSlicePrompt(brief, userMessage, runMode, promptIter, currentSlice());
|
|
63428
63695
|
const implementerRetry = runMode === "implementation" && (implStep > 1 || forcePivot);
|
|
63429
63696
|
const sliceStartedAt = now().toISOString();
|
|
63430
63697
|
const sliceStartMs = now().getTime();
|
|
63431
63698
|
if (runMode === "design-phase") {
|
|
63432
63699
|
deps.emit(
|
|
63433
|
-
`[zelari] design-phase (fuori budget) \xB7 step ${step} \xB7 slice ${
|
|
63700
|
+
`[zelari] design-phase (fuori budget) \xB7 step ${step} \xB7 slice ${currentSlice().id}`
|
|
63434
63701
|
);
|
|
63435
63702
|
} else if (deps.buildViaAgent) {
|
|
63436
63703
|
deps.emit(
|
|
63437
|
-
`[zelari] implementazione ${implStep}/${maxIter} \xB7 step ${step} \xB7 build@agent \xB7 slice ${
|
|
63704
|
+
`[zelari] implementazione ${implStep}/${maxIter} \xB7 step ${step} \xB7 build@agent \xB7 slice ${currentSlice().id}`
|
|
63438
63705
|
);
|
|
63439
63706
|
} else if (implementerRetry) {
|
|
63440
63707
|
deps.emit(
|
|
63441
|
-
`[zelari] implementazione ${implStep}/${maxIter} \xB7 step ${step} \xB7 roster ridotto (Minosse+Lucifero) \xB7 slice ${
|
|
63708
|
+
`[zelari] implementazione ${implStep}/${maxIter} \xB7 step ${step} \xB7 roster ridotto (Minosse+Lucifero) \xB7 slice ${currentSlice().id}`
|
|
63442
63709
|
);
|
|
63443
63710
|
} else {
|
|
63444
63711
|
deps.emit(
|
|
63445
|
-
`[zelari] implementazione ${implStep}/${maxIter} \xB7 step ${step} \xB7 council completo \xB7 slice ${
|
|
63712
|
+
`[zelari] implementazione ${implStep}/${maxIter} \xB7 step ${step} \xB7 council completo \xB7 slice ${currentSlice().id}`
|
|
63446
63713
|
);
|
|
63447
63714
|
}
|
|
63448
63715
|
let result;
|
|
@@ -63484,7 +63751,7 @@ async function runZelariMission(userMessage, brief, deps) {
|
|
|
63484
63751
|
{
|
|
63485
63752
|
projectRoot: deps.projectRoot,
|
|
63486
63753
|
missionId,
|
|
63487
|
-
sliceId:
|
|
63754
|
+
sliceId: currentSlice().id,
|
|
63488
63755
|
source: "council",
|
|
63489
63756
|
iteration: step,
|
|
63490
63757
|
memoryKind: result.completionOk ? "outcome" : runMode === "design-phase" ? "decision" : "episode",
|
|
@@ -63508,7 +63775,7 @@ async function runZelariMission(userMessage, brief, deps) {
|
|
|
63508
63775
|
state3.cumulativeTokens = cumulativeTokens;
|
|
63509
63776
|
if (!state3.trace) state3.trace = [];
|
|
63510
63777
|
state3.trace.push({
|
|
63511
|
-
sliceId:
|
|
63778
|
+
sliceId: currentSlice().id,
|
|
63512
63779
|
iteration: step,
|
|
63513
63780
|
runMode,
|
|
63514
63781
|
completionOk,
|
|
@@ -63533,7 +63800,7 @@ async function runZelariMission(userMessage, brief, deps) {
|
|
|
63533
63800
|
env: deps.env,
|
|
63534
63801
|
mode: "zelari",
|
|
63535
63802
|
layer: hard ? `mission:impl-${implStep}` : `mission:progress-${implStep}`,
|
|
63536
|
-
label: hard ? `zelari ${
|
|
63803
|
+
label: hard ? `zelari ${currentSlice().id} impl ${implStep} verified` : `zelari ${currentSlice().id} progress impl ${implStep}`,
|
|
63537
63804
|
sessionId: missionId,
|
|
63538
63805
|
verification: { ok: hard, ran: result.ran },
|
|
63539
63806
|
force: !hard,
|
|
@@ -63572,12 +63839,24 @@ async function runZelariMission(userMessage, brief, deps) {
|
|
|
63572
63839
|
budget: { iterationsUsed: implStep, iterationsMax: maxIter }
|
|
63573
63840
|
});
|
|
63574
63841
|
deps.onMissionProgress?.(advice, step);
|
|
63842
|
+
if (completionOk && sliceIndex < slices.length - 1) {
|
|
63843
|
+
const doneSlice = currentSlice();
|
|
63844
|
+
sliceIndex += 1;
|
|
63845
|
+
state3.currentSliceId = currentSlice().id;
|
|
63846
|
+
state3.updatedAt = now().toISOString();
|
|
63847
|
+
await persist();
|
|
63848
|
+
deps.emit(
|
|
63849
|
+
`[zelari] \u2713 incremento ${sliceIndex}/${slices.length} verde (${doneSlice.id}) \u2014 avvio ${currentSlice().id}`
|
|
63850
|
+
);
|
|
63851
|
+
continue;
|
|
63852
|
+
}
|
|
63575
63853
|
if (completionOk) {
|
|
63576
63854
|
state3.status = "success";
|
|
63577
63855
|
deps.onMissionPhase?.("done", "mvp-green");
|
|
63578
63856
|
await persist();
|
|
63857
|
+
const sliceLabel = slices.length === 1 ? "slice MVP" : `ultimo incremento (${currentSlice().id})`;
|
|
63579
63858
|
deps.emit(
|
|
63580
|
-
`[zelari] \u2713 missione completata \u2014
|
|
63859
|
+
`[zelari] \u2713 missione completata \u2014 ${sliceLabel} verde all'implementazione ${implStep}/${maxIter} (step ${step}).`
|
|
63581
63860
|
);
|
|
63582
63861
|
return state3;
|
|
63583
63862
|
}
|
|
@@ -63655,7 +63934,7 @@ async function runZelariMission(userMessage, brief, deps) {
|
|
|
63655
63934
|
);
|
|
63656
63935
|
return state3;
|
|
63657
63936
|
}
|
|
63658
|
-
var DEFAULT_MAX_ITER, DEFAULT_MAX_STALL;
|
|
63937
|
+
var DEFAULT_MAX_ITER, DEFAULT_MAX_STALL, MissionResumeError;
|
|
63659
63938
|
var init_zelariMission = __esm({
|
|
63660
63939
|
"src/cli/zelariMission.ts"() {
|
|
63661
63940
|
"use strict";
|
|
@@ -63668,6 +63947,12 @@ var init_zelariMission = __esm({
|
|
|
63668
63947
|
init_traceStore();
|
|
63669
63948
|
DEFAULT_MAX_ITER = 6;
|
|
63670
63949
|
DEFAULT_MAX_STALL = 2;
|
|
63950
|
+
MissionResumeError = class extends Error {
|
|
63951
|
+
constructor(message) {
|
|
63952
|
+
super(message);
|
|
63953
|
+
this.name = "MissionResumeError";
|
|
63954
|
+
}
|
|
63955
|
+
};
|
|
63671
63956
|
}
|
|
63672
63957
|
});
|
|
63673
63958
|
|
|
@@ -63995,7 +64280,7 @@ function safeSocketPath(socketPath) {
|
|
|
63995
64280
|
return socketPath.trim();
|
|
63996
64281
|
}
|
|
63997
64282
|
function startPermissionBroker(socketPath, handlers, opts) {
|
|
63998
|
-
const
|
|
64283
|
+
const path101 = safeSocketPath(socketPath);
|
|
63999
64284
|
const requestTimeoutMs = opts?.requestTimeoutMs ?? PERMISSION_BROKER_DEFAULT_TIMEOUT_MS;
|
|
64000
64285
|
const sockets = /* @__PURE__ */ new Set();
|
|
64001
64286
|
const server = createServer2((socket) => {
|
|
@@ -64095,10 +64380,10 @@ function startPermissionBroker(socketPath, handlers, opts) {
|
|
|
64095
64380
|
return new Promise((resolve9, reject) => {
|
|
64096
64381
|
const onError = (err) => reject(err);
|
|
64097
64382
|
server.once("error", onError);
|
|
64098
|
-
server.listen(
|
|
64383
|
+
server.listen(path101, () => {
|
|
64099
64384
|
server.removeListener("error", onError);
|
|
64100
64385
|
resolve9({
|
|
64101
|
-
socketPath:
|
|
64386
|
+
socketPath: path101,
|
|
64102
64387
|
stop: () => new Promise((res) => {
|
|
64103
64388
|
for (const s of sockets) s.destroy();
|
|
64104
64389
|
sockets.clear();
|
|
@@ -64109,7 +64394,7 @@ function startPermissionBroker(socketPath, handlers, opts) {
|
|
|
64109
64394
|
if (done) return;
|
|
64110
64395
|
done = true;
|
|
64111
64396
|
if (process.platform !== "win32") {
|
|
64112
|
-
unlink(
|
|
64397
|
+
unlink(path101, () => res());
|
|
64113
64398
|
} else {
|
|
64114
64399
|
res();
|
|
64115
64400
|
}
|
|
@@ -64122,11 +64407,11 @@ function startPermissionBroker(socketPath, handlers, opts) {
|
|
|
64122
64407
|
});
|
|
64123
64408
|
}
|
|
64124
64409
|
function requestBrokerAsk(socketPath, ask, opts) {
|
|
64125
|
-
const
|
|
64410
|
+
const path101 = safeSocketPath(socketPath);
|
|
64126
64411
|
const requestTimeoutMs = opts?.requestTimeoutMs ?? PERMISSION_BROKER_DEFAULT_TIMEOUT_MS;
|
|
64127
64412
|
const connectTimeoutMs = opts?.connectTimeoutMs ?? PERMISSION_BROKER_DEFAULT_CONNECT_TIMEOUT_MS;
|
|
64128
64413
|
return new Promise((resolve9, reject) => {
|
|
64129
|
-
const socket = connect(
|
|
64414
|
+
const socket = connect(path101);
|
|
64130
64415
|
let buffer = "";
|
|
64131
64416
|
let settled = false;
|
|
64132
64417
|
const settle = (fn) => {
|
|
@@ -64141,7 +64426,7 @@ function requestBrokerAsk(socketPath, ask, opts) {
|
|
|
64141
64426
|
settle(
|
|
64142
64427
|
() => reject(
|
|
64143
64428
|
new Error(
|
|
64144
|
-
`permission broker unavailable at "${
|
|
64429
|
+
`permission broker unavailable at "${path101}" (connect timed out after ${connectTimeoutMs}ms)`
|
|
64145
64430
|
)
|
|
64146
64431
|
)
|
|
64147
64432
|
);
|
|
@@ -65330,7 +65615,7 @@ var init_prereqChecks = __esm({
|
|
|
65330
65615
|
|
|
65331
65616
|
// src/cli/plugins/prefs.ts
|
|
65332
65617
|
import { existsSync as existsSync53, readFileSync as readFileSync40, writeFileSync as writeFileSync23, mkdirSync as mkdirSync20 } from "node:fs";
|
|
65333
|
-
import
|
|
65618
|
+
import path83 from "node:path";
|
|
65334
65619
|
function getPluginPrefsPath() {
|
|
65335
65620
|
return pluginsPrefsPath();
|
|
65336
65621
|
}
|
|
@@ -65353,7 +65638,7 @@ function getPluginPrefs() {
|
|
|
65353
65638
|
}
|
|
65354
65639
|
function writePluginPrefs(prefs) {
|
|
65355
65640
|
const file2 = getPluginPrefsPath();
|
|
65356
|
-
mkdirSync20(
|
|
65641
|
+
mkdirSync20(path83.dirname(file2), { recursive: true });
|
|
65357
65642
|
writeFileSync23(file2, JSON.stringify(prefs, null, 2), {
|
|
65358
65643
|
encoding: "utf-8",
|
|
65359
65644
|
mode: 384
|
|
@@ -65391,7 +65676,7 @@ __export(registry_exports, {
|
|
|
65391
65676
|
isBinaryOnPath: () => isBinaryOnPath
|
|
65392
65677
|
});
|
|
65393
65678
|
import { existsSync as existsSync54 } from "node:fs";
|
|
65394
|
-
import
|
|
65679
|
+
import path84 from "node:path";
|
|
65395
65680
|
function detectLocalBin(bin) {
|
|
65396
65681
|
return (cwd) => {
|
|
65397
65682
|
try {
|
|
@@ -65409,7 +65694,7 @@ function isBinaryOnPath(bin, opts = {}) {
|
|
|
65409
65694
|
const platform = opts.platform ?? process.platform;
|
|
65410
65695
|
const exists = opts.exists ?? existsSync54;
|
|
65411
65696
|
const pathEnv = opts.pathEnv ?? process.env.PATH ?? "";
|
|
65412
|
-
const pathMod = platform === "win32" ?
|
|
65697
|
+
const pathMod = platform === "win32" ? path84.win32 : path84.posix;
|
|
65413
65698
|
const sep4 = platform === "win32" ? ";" : ":";
|
|
65414
65699
|
const dirs = pathEnv.split(sep4).filter((d) => d.length > 0);
|
|
65415
65700
|
const candidates = [bin];
|
|
@@ -66514,7 +66799,7 @@ var init_policy = __esm({
|
|
|
66514
66799
|
|
|
66515
66800
|
// src/cli/orchestration/facts.ts
|
|
66516
66801
|
import { promises as fs43 } from "node:fs";
|
|
66517
|
-
import
|
|
66802
|
+
import path88 from "node:path";
|
|
66518
66803
|
async function collectRepoFileCount(root = process.cwd()) {
|
|
66519
66804
|
try {
|
|
66520
66805
|
await fs43.readdir(root);
|
|
@@ -66534,7 +66819,7 @@ async function collectRepoFileCount(root = process.cwd()) {
|
|
|
66534
66819
|
}
|
|
66535
66820
|
for (const e of entries) {
|
|
66536
66821
|
if (e.isDirectory()) {
|
|
66537
|
-
if (!SKIP_DIRS.has(e.name)) queue.push(
|
|
66822
|
+
if (!SKIP_DIRS.has(e.name)) queue.push(path88.join(dir, e.name));
|
|
66538
66823
|
} else if (e.isFile()) {
|
|
66539
66824
|
count++;
|
|
66540
66825
|
if (count > MAX_WALK_FILES) return count;
|
|
@@ -66632,7 +66917,7 @@ var init_streamScrub = __esm({
|
|
|
66632
66917
|
});
|
|
66633
66918
|
|
|
66634
66919
|
// src/cli/harnessState.ts
|
|
66635
|
-
import
|
|
66920
|
+
import path89 from "node:path";
|
|
66636
66921
|
function asString4(v) {
|
|
66637
66922
|
return typeof v === "string" ? v : "";
|
|
66638
66923
|
}
|
|
@@ -66807,7 +67092,7 @@ function contractFor(t) {
|
|
|
66807
67092
|
};
|
|
66808
67093
|
}
|
|
66809
67094
|
async function readHarnessState(sessionDir) {
|
|
66810
|
-
const report = await readSessionLog(
|
|
67095
|
+
const report = await readSessionLog(path89.join(sessionDir, "events.jsonl"));
|
|
66811
67096
|
return deriveHarnessState(report.events);
|
|
66812
67097
|
}
|
|
66813
67098
|
var init_harnessState = __esm({
|
|
@@ -66818,12 +67103,12 @@ var init_harnessState = __esm({
|
|
|
66818
67103
|
});
|
|
66819
67104
|
|
|
66820
67105
|
// src/cli/headless/harnessStateEmit.ts
|
|
66821
|
-
import
|
|
67106
|
+
import path90 from "node:path";
|
|
66822
67107
|
async function emitHarnessStateEvent(opts) {
|
|
66823
67108
|
if (opts.output !== "json") return;
|
|
66824
67109
|
try {
|
|
66825
67110
|
const sessionsDir2 = resolveSessionsDir({ workspaceRoot: opts.workspaceRoot });
|
|
66826
|
-
const state3 = await readHarnessState(
|
|
67111
|
+
const state3 = await readHarnessState(path90.join(sessionsDir2, opts.spine.sessionId));
|
|
66827
67112
|
opts.emitEvent({ type: "harness_state", ...state3 });
|
|
66828
67113
|
} catch (err) {
|
|
66829
67114
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -67380,13 +67665,13 @@ var init_verifierLifecycle = __esm({
|
|
|
67380
67665
|
|
|
67381
67666
|
// src/cli/extensions/sandboxedFs.ts
|
|
67382
67667
|
import { promises as fsp } from "node:fs";
|
|
67383
|
-
import
|
|
67668
|
+
import path91 from "node:path";
|
|
67384
67669
|
function errText(prefix, p3, err) {
|
|
67385
67670
|
const msg = err instanceof Error ? err.message : String(err);
|
|
67386
67671
|
return `[extension-fs] ${prefix} "${p3}": ${msg}`;
|
|
67387
67672
|
}
|
|
67388
67673
|
function bindSandboxedFs(root) {
|
|
67389
|
-
const resolvedRoot =
|
|
67674
|
+
const resolvedRoot = path91.resolve(root);
|
|
67390
67675
|
return {
|
|
67391
67676
|
root: resolvedRoot,
|
|
67392
67677
|
async readFile(relativePath) {
|
|
@@ -67402,7 +67687,7 @@ function bindSandboxedFs(root) {
|
|
|
67402
67687
|
try {
|
|
67403
67688
|
const target = resolveSandboxedPath(relativePath, { root: resolvedRoot });
|
|
67404
67689
|
verifyContainment(target, { root: resolvedRoot });
|
|
67405
|
-
await fsp.mkdir(
|
|
67690
|
+
await fsp.mkdir(path91.dirname(target), { recursive: true });
|
|
67406
67691
|
await fsp.writeFile(target, data, "utf8");
|
|
67407
67692
|
return typedOk({ path: target });
|
|
67408
67693
|
} catch (err) {
|
|
@@ -67587,7 +67872,7 @@ var init_loader = __esm({
|
|
|
67587
67872
|
|
|
67588
67873
|
// src/cli/headless/runOneTurn.ts
|
|
67589
67874
|
import { promises as fs44 } from "node:fs";
|
|
67590
|
-
import
|
|
67875
|
+
import path92 from "node:path";
|
|
67591
67876
|
function planModeFromOpts(opts) {
|
|
67592
67877
|
return (opts.phase ?? "build") === "plan";
|
|
67593
67878
|
}
|
|
@@ -68065,11 +68350,14 @@ async function runOneTurn(opts, provider, model, providerStream, extras) {
|
|
|
68065
68350
|
return null;
|
|
68066
68351
|
}
|
|
68067
68352
|
},
|
|
68068
|
-
|
|
68353
|
+
// F3 seam adapter (same as the gate sites below): the core engine reads
|
|
68354
|
+
// the anchor as `out.seq`, while the spine resolves the seq NUMBER. A bare
|
|
68355
|
+
// number here leaves the review evidence unanchored on the spine.
|
|
68356
|
+
emit: async (input) => ({ seq: await spine.appendEvent(input) })
|
|
68069
68357
|
};
|
|
68070
68358
|
const strictEnv = strictEnvOverlay(opts);
|
|
68071
68359
|
if (pass.finalReason === "completed" && pass.exitCode === 0 && isKrakenMode(opts.mode) && (isKrakenSelectionEnabled() || nativePackEnabled()) && !planModeFromOpts(opts)) {
|
|
68072
|
-
const strictGate = await evaluateStrictBuildGate("build", { emit: (input) => spine.appendEvent(input), cwd, env: strictEnv });
|
|
68360
|
+
const strictGate = await evaluateStrictBuildGate("build", { emit: async (input) => ({ seq: await spine.appendEvent(input) }), cwd, env: strictEnv });
|
|
68073
68361
|
await runAdvisoryVerifierReview(strictGate, verifierReviewDeps).catch(() => void 0);
|
|
68074
68362
|
const gate = strictGate.gate;
|
|
68075
68363
|
const verificationPayload = strictGateEventPayload(strictGate);
|
|
@@ -68079,7 +68367,7 @@ async function runOneTurn(opts, provider, model, providerStream, extras) {
|
|
|
68079
68367
|
}
|
|
68080
68368
|
await writeProofSafe(strictGate, { surface: "kraken", sessionId: spine.sessionId }, cwd);
|
|
68081
68369
|
if (strictGate.blocked) {
|
|
68082
|
-
const repairPrompt = buildKrakenRepairPrompt(gate);
|
|
68370
|
+
const repairPrompt = buildKrakenRepairPrompt(gate, repairExcerptsFromEvaluation(strictGate));
|
|
68083
68371
|
if (opts.output === "json") {
|
|
68084
68372
|
emitEvent({
|
|
68085
68373
|
type: "log",
|
|
@@ -68104,7 +68392,7 @@ async function runOneTurn(opts, provider, model, providerStream, extras) {
|
|
|
68104
68392
|
successfulWrites: pass.successfulWrites + repair.successfulWrites,
|
|
68105
68393
|
emittedWrites: pass.emittedWrites + repair.emittedWrites
|
|
68106
68394
|
};
|
|
68107
|
-
const after = await evaluateStrictBuildGate("build", { emit: (input) => spine.appendEvent(input), cwd, env: strictEnv });
|
|
68395
|
+
const after = await evaluateStrictBuildGate("build", { emit: async (input) => ({ seq: await spine.appendEvent(input) }), cwd, env: strictEnv });
|
|
68108
68396
|
await runAdvisoryVerifierReview(after, verifierReviewDeps).catch(() => void 0);
|
|
68109
68397
|
const afterPayload = strictGateEventPayload(after);
|
|
68110
68398
|
spine.verificationRun(afterPayload);
|
|
@@ -68154,7 +68442,7 @@ async function runOneTurn(opts, provider, model, providerStream, extras) {
|
|
|
68154
68442
|
if (json3) {
|
|
68155
68443
|
if (opts.exportSessionPath === "-") process.stdout.write(json3 + "\n");
|
|
68156
68444
|
else {
|
|
68157
|
-
await fs44.mkdir(
|
|
68445
|
+
await fs44.mkdir(path92.dirname(opts.exportSessionPath), { recursive: true }).catch(() => void 0);
|
|
68158
68446
|
await fs44.writeFile(opts.exportSessionPath, json3, "utf8");
|
|
68159
68447
|
}
|
|
68160
68448
|
}
|
|
@@ -69125,6 +69413,76 @@ var init_run = __esm({
|
|
|
69125
69413
|
}
|
|
69126
69414
|
});
|
|
69127
69415
|
|
|
69416
|
+
// src/cli/evolution/runTelemetry.ts
|
|
69417
|
+
var runTelemetry_exports = {};
|
|
69418
|
+
__export(runTelemetry_exports, {
|
|
69419
|
+
RunTelemetryAccumulator: () => RunTelemetryAccumulator
|
|
69420
|
+
});
|
|
69421
|
+
var RunTelemetryAccumulator;
|
|
69422
|
+
var init_runTelemetry = __esm({
|
|
69423
|
+
"src/cli/evolution/runTelemetry.ts"() {
|
|
69424
|
+
"use strict";
|
|
69425
|
+
RunTelemetryAccumulator = class {
|
|
69426
|
+
constructor(meta3 = {}) {
|
|
69427
|
+
this.meta = meta3;
|
|
69428
|
+
}
|
|
69429
|
+
totals = {
|
|
69430
|
+
inputTokens: 0,
|
|
69431
|
+
outputTokens: 0,
|
|
69432
|
+
cacheHitTokens: 0,
|
|
69433
|
+
toolCalls: 0,
|
|
69434
|
+
usageReports: 0
|
|
69435
|
+
};
|
|
69436
|
+
/** Mirror one dispatch/spine event. Never throws on unknown shapes. */
|
|
69437
|
+
observe(ev) {
|
|
69438
|
+
if (!ev || typeof ev !== "object" || !("type" in ev)) return;
|
|
69439
|
+
const e = ev;
|
|
69440
|
+
if (e["type"] === "tool_execution_end") {
|
|
69441
|
+
this.totals.toolCalls += 1;
|
|
69442
|
+
return;
|
|
69443
|
+
}
|
|
69444
|
+
if (e["type"] !== "message_end") return;
|
|
69445
|
+
const usage = e["usage"];
|
|
69446
|
+
if (!usage || typeof usage !== "object") return;
|
|
69447
|
+
const u = usage;
|
|
69448
|
+
if (typeof u["promptTokens"] === "number") this.totals.inputTokens += u["promptTokens"];
|
|
69449
|
+
if (typeof u["completionTokens"] === "number") this.totals.outputTokens += u["completionTokens"];
|
|
69450
|
+
if (typeof u["cachedPromptTokens"] === "number") this.totals.cacheHitTokens += u["cachedPromptTokens"];
|
|
69451
|
+
this.totals.usageReports += 1;
|
|
69452
|
+
}
|
|
69453
|
+
/** Cumulative totals (defensive copy). */
|
|
69454
|
+
usage() {
|
|
69455
|
+
return { ...this.totals };
|
|
69456
|
+
}
|
|
69457
|
+
/**
|
|
69458
|
+
* Final NDJSON `usage` event for JSON hosts (Desktop, competitive bench,
|
|
69459
|
+
* anchor runner). Emitted once per run, after the dispatch stream ends —
|
|
69460
|
+
* `tools/eval/competitive/adapters.ts#parseZelariUsage` reads exactly this
|
|
69461
|
+
* flat `{ inputTokens, outputTokens, cacheHitTokens, model?, provider? }`
|
|
69462
|
+
* shape, so the bench stops recording `tokens: null` with no bench change.
|
|
69463
|
+
*/
|
|
69464
|
+
usageEvent() {
|
|
69465
|
+
return {
|
|
69466
|
+
type: "usage",
|
|
69467
|
+
...this.usage(),
|
|
69468
|
+
...this.meta.model ? { model: this.meta.model } : {},
|
|
69469
|
+
...this.meta.provider ? { provider: this.meta.provider } : {}
|
|
69470
|
+
};
|
|
69471
|
+
}
|
|
69472
|
+
/**
|
|
69473
|
+
* Ledger projection: toolCalls always (event-countable), token fields ONLY
|
|
69474
|
+
* when backed by ≥1 provider usage report (unknown ≠ estimated ≠ zero).
|
|
69475
|
+
*/
|
|
69476
|
+
ledgerFields() {
|
|
69477
|
+
return {
|
|
69478
|
+
toolCalls: this.totals.toolCalls,
|
|
69479
|
+
...this.totals.usageReports > 0 ? { inputTokens: this.totals.inputTokens, outputTokens: this.totals.outputTokens } : {}
|
|
69480
|
+
};
|
|
69481
|
+
}
|
|
69482
|
+
};
|
|
69483
|
+
}
|
|
69484
|
+
});
|
|
69485
|
+
|
|
69128
69486
|
// src/cli/triggerLock.ts
|
|
69129
69487
|
var triggerLock_exports = {};
|
|
69130
69488
|
__export(triggerLock_exports, {
|
|
@@ -69133,9 +69491,9 @@ __export(triggerLock_exports, {
|
|
|
69133
69491
|
releaseLock: () => releaseLock
|
|
69134
69492
|
});
|
|
69135
69493
|
import { promises as fs45 } from "node:fs";
|
|
69136
|
-
import * as
|
|
69494
|
+
import * as path93 from "node:path";
|
|
69137
69495
|
function lockPath(projectRoot) {
|
|
69138
|
-
return
|
|
69496
|
+
return path93.join(projectRoot, ".zelari", "trigger.lock");
|
|
69139
69497
|
}
|
|
69140
69498
|
function isPidAlive(pid) {
|
|
69141
69499
|
try {
|
|
@@ -69148,7 +69506,7 @@ function isPidAlive(pid) {
|
|
|
69148
69506
|
}
|
|
69149
69507
|
async function acquireLock(projectRoot, now = () => /* @__PURE__ */ new Date()) {
|
|
69150
69508
|
const lp = lockPath(projectRoot);
|
|
69151
|
-
const dir =
|
|
69509
|
+
const dir = path93.dirname(lp);
|
|
69152
69510
|
await fs45.mkdir(dir, { recursive: true });
|
|
69153
69511
|
try {
|
|
69154
69512
|
const raw = await fs45.readFile(lp, "utf8");
|
|
@@ -69180,7 +69538,7 @@ var init_triggerLock = __esm({
|
|
|
69180
69538
|
|
|
69181
69539
|
// src/cli/runHeadless.ts
|
|
69182
69540
|
import { promises as fs46 } from "node:fs";
|
|
69183
|
-
import
|
|
69541
|
+
import path94 from "node:path";
|
|
69184
69542
|
import { randomUUID as randomUUID10 } from "node:crypto";
|
|
69185
69543
|
async function runHeadless(opts) {
|
|
69186
69544
|
resetTaskSpawnCount();
|
|
@@ -69424,7 +69782,7 @@ async function runHeadlessKrakenGraph(opts, provider, model) {
|
|
|
69424
69782
|
try {
|
|
69425
69783
|
let preflightGraph;
|
|
69426
69784
|
if (opts.runPlan && opts.runPlan.trim() !== "") {
|
|
69427
|
-
const planPath =
|
|
69785
|
+
const planPath = path94.join(cwd, ".zelari", "radio", `plan-${opts.runPlan}.json`);
|
|
69428
69786
|
log(`loading pre-flight plan: ${planPath}`);
|
|
69429
69787
|
let raw;
|
|
69430
69788
|
try {
|
|
@@ -69467,8 +69825,8 @@ async function runHeadlessKrakenGraph(opts, provider, model) {
|
|
|
69467
69825
|
log(formatKrakenGraphAscii2(graph));
|
|
69468
69826
|
if (opts.planOnly) {
|
|
69469
69827
|
const planId = randomUUID10();
|
|
69470
|
-
const planDir =
|
|
69471
|
-
const planPath =
|
|
69828
|
+
const planDir = path94.join(cwd, ".zelari", "radio");
|
|
69829
|
+
const planPath = path94.join(planDir, `plan-${planId}.json`);
|
|
69472
69830
|
await fs46.mkdir(planDir, { recursive: true });
|
|
69473
69831
|
await fs46.writeFile(
|
|
69474
69832
|
planPath,
|
|
@@ -69729,6 +70087,9 @@ async function runHeadlessCouncilBody(opts, provider, model, providerStream, ext
|
|
|
69729
70087
|
const scrub = createStreamScrubber2({ stripQuestion: opts.output !== "json" });
|
|
69730
70088
|
let lastAssistantText = "";
|
|
69731
70089
|
let currentAssistantText = "";
|
|
70090
|
+
const { RunTelemetryAccumulator: RunTelemetryAccumulator2 } = await Promise.resolve().then(() => (init_runTelemetry(), runTelemetry_exports));
|
|
70091
|
+
const telemetry = new RunTelemetryAccumulator2({ model, provider });
|
|
70092
|
+
const councilStartedAt = Date.now();
|
|
69732
70093
|
try {
|
|
69733
70094
|
const { composeProjectContext: composeProjectContext2 } = await Promise.resolve().then(() => (init_composeContext(), composeContext_exports));
|
|
69734
70095
|
const { loadDurableContext: loadDurableContext2 } = await Promise.resolve().then(() => (init_loadDurableContext(), loadDurableContext_exports));
|
|
@@ -69784,6 +70145,7 @@ async function runHeadlessCouncilBody(opts, provider, model, providerStream, ext
|
|
|
69784
70145
|
currentAssistantText = "";
|
|
69785
70146
|
}
|
|
69786
70147
|
spine.observe(event);
|
|
70148
|
+
telemetry.observe(event);
|
|
69787
70149
|
if (event.type === "message_delta" && typeof event.delta === "string") {
|
|
69788
70150
|
const cleanDelta = scrub.push(event.delta);
|
|
69789
70151
|
if (cleanDelta.length > 0) currentAssistantText += cleanDelta;
|
|
@@ -69811,6 +70173,9 @@ async function runHeadlessCouncilBody(opts, provider, model, providerStream, ext
|
|
|
69811
70173
|
}
|
|
69812
70174
|
}
|
|
69813
70175
|
}
|
|
70176
|
+
if (opts.output === "json") {
|
|
70177
|
+
emitEvent(telemetry.usageEvent());
|
|
70178
|
+
}
|
|
69814
70179
|
} catch (err) {
|
|
69815
70180
|
process.stderr.write(
|
|
69816
70181
|
`[zelari-code --headless] council error: ${err instanceof Error ? err.message : String(err)}
|
|
@@ -69834,6 +70199,12 @@ async function runHeadlessCouncilBody(opts, provider, model, providerStream, ext
|
|
|
69834
70199
|
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
69835
70200
|
mode: "shadow",
|
|
69836
70201
|
taskClass: classifyTask2({ prompt: effectiveTask }).taskClass,
|
|
70202
|
+
// Steal #1/#2 wiring: real efficiency + attribution fields — the
|
|
70203
|
+
// ledger schema carried them since ADR-0036, this site never wrote them.
|
|
70204
|
+
latencyMs: Date.now() - councilStartedAt,
|
|
70205
|
+
model,
|
|
70206
|
+
provider,
|
|
70207
|
+
...telemetry.ledgerFields(),
|
|
69837
70208
|
verdict: signal.aborted ? "UNKNOWN" : exitCode === 0 ? "PASS" : exitCode === 3 ? "FAIL" : "UNKNOWN"
|
|
69838
70209
|
});
|
|
69839
70210
|
}
|
|
@@ -69846,7 +70217,7 @@ async function runHeadlessCouncilBody(opts, provider, model, providerStream, ext
|
|
|
69846
70217
|
if (json3) {
|
|
69847
70218
|
if (opts.exportSessionPath === "-") process.stdout.write(json3 + "\n");
|
|
69848
70219
|
else {
|
|
69849
|
-
await fs46.mkdir(
|
|
70220
|
+
await fs46.mkdir(path94.dirname(opts.exportSessionPath), { recursive: true }).catch(() => void 0);
|
|
69850
70221
|
await fs46.writeFile(opts.exportSessionPath, json3, "utf8");
|
|
69851
70222
|
}
|
|
69852
70223
|
}
|
|
@@ -69901,14 +70272,17 @@ async function runHeadlessZelariBody(opts, provider, model, providerStream, extr
|
|
|
69901
70272
|
spine.missionPhase("design", "mission-start");
|
|
69902
70273
|
const { buildMissionBrief: buildMissionBrief2 } = await Promise.resolve().then(() => (init_council(), council_exports));
|
|
69903
70274
|
const { hasWorkspacePlan: hasWorkspacePlan2 } = await Promise.resolve().then(() => (init_planDetect(), planDetect_exports));
|
|
70275
|
+
const { listOpenPlanTaskIds: listOpenPlanTaskIds2 } = await Promise.resolve().then(() => (init_planStore(), planStore_exports));
|
|
69904
70276
|
const { getMemoryBackend: getMemoryBackend2 } = await Promise.resolve().then(() => (init_fileBackend(), fileBackend_exports));
|
|
69905
70277
|
const { runZelariMission: runZelariMission2 } = await Promise.resolve().then(() => (init_zelariMission(), zelariMission_exports));
|
|
69906
70278
|
const { dispatchCouncil: dispatchCouncil2 } = await Promise.resolve().then(() => (init_councilDispatcher(), councilDispatcher_exports));
|
|
69907
70279
|
const { FeedbackStore: FeedbackStore2 } = await Promise.resolve().then(() => (init_councilFeedback(), councilFeedback_exports));
|
|
69908
70280
|
const { runPostCouncilHook: runPostCouncilHook2 } = await Promise.resolve().then(() => (init_postCouncilHook(), postCouncilHook_exports));
|
|
70281
|
+
const planTaskIds = await listOpenPlanTaskIds2(projectRoot);
|
|
69909
70282
|
const brief = buildMissionBrief2({
|
|
69910
70283
|
userMessage: opts.task,
|
|
69911
|
-
hasPlan: hasWorkspacePlan2(projectRoot)
|
|
70284
|
+
hasPlan: hasWorkspacePlan2(projectRoot),
|
|
70285
|
+
planTaskIds
|
|
69912
70286
|
});
|
|
69913
70287
|
const memory = await getMemoryBackend2(
|
|
69914
70288
|
projectRoot,
|
|
@@ -69993,7 +70367,9 @@ ${JSON.stringify({ deliverable: brief.deliverableThisMission, mvp: brief.sliceMv
|
|
|
69993
70367
|
}
|
|
69994
70368
|
}
|
|
69995
70369
|
try {
|
|
69996
|
-
const
|
|
70370
|
+
const { resumeZelariMission: resumeZelariMission2 } = await Promise.resolve().then(() => (init_zelariMission(), zelariMission_exports));
|
|
70371
|
+
const runMission = (missionDeps) => opts.resumeMission ? resumeZelariMission2(missionDeps) : runZelariMission2(missionTask, brief, missionDeps);
|
|
70372
|
+
const state3 = await runMission({
|
|
69997
70373
|
projectRoot,
|
|
69998
70374
|
memory,
|
|
69999
70375
|
emit,
|
|
@@ -70264,6 +70640,22 @@ ${ragContext}` : slicePrompt;
|
|
|
70264
70640
|
if (missionGate.blocked) {
|
|
70265
70641
|
exitCode = strictGateExitCode(missionGate);
|
|
70266
70642
|
spine.missionPhase("verification", "mission-strict-blocked");
|
|
70643
|
+
} else if (
|
|
70644
|
+
// M2.1/R4b: an open strict gate is not enough — the success claim must
|
|
70645
|
+
// be event-backed: zero `verification.evidence` events in the spine
|
|
70646
|
+
// means narration-only done → strict exit code. Same overlay seam as
|
|
70647
|
+
// the gate above (H10-fix1) so --allow-unverified /
|
|
70648
|
+
// ZELARI_ALLOW_UNVERIFIED=1 waives mission-side too. `opts.phase` is
|
|
70649
|
+
// the only phase/mode discriminant on this site: `--phase plan`
|
|
70650
|
+
// missions are design-only (no verification expected), so the gate
|
|
70651
|
+
// applies unconditionally to build-phase claims.
|
|
70652
|
+
opts.phase !== "plan" && missionClaimExitCode(await spine.countVerificationEvidence(), strictEnvOverlay(opts)) !== 0
|
|
70653
|
+
) {
|
|
70654
|
+
exitCode = STRICT_DONE_EXIT_CODE;
|
|
70655
|
+
spine.missionPhase("verification", "mission-event-back-missing");
|
|
70656
|
+
process.stderr.write(
|
|
70657
|
+
"[zelari-code --headless] mission success claim has zero verification.evidence events (narration-only done) \u2014 exit 4 (waive with --allow-unverified / ZELARI_ALLOW_UNVERIFIED=1)\n"
|
|
70658
|
+
);
|
|
70267
70659
|
} else {
|
|
70268
70660
|
exitCode = 0;
|
|
70269
70661
|
spine.missionPhase("done", "mission-success");
|
|
@@ -70297,7 +70689,7 @@ ${ragContext}` : slicePrompt;
|
|
|
70297
70689
|
if (json3) {
|
|
70298
70690
|
if (opts.exportSessionPath === "-") process.stdout.write(json3 + "\n");
|
|
70299
70691
|
else {
|
|
70300
|
-
await fs46.mkdir(
|
|
70692
|
+
await fs46.mkdir(path94.dirname(opts.exportSessionPath), { recursive: true }).catch(() => void 0);
|
|
70301
70693
|
await fs46.writeFile(opts.exportSessionPath, json3, "utf8");
|
|
70302
70694
|
}
|
|
70303
70695
|
}
|
|
@@ -70922,7 +71314,7 @@ function upsertSkill(opts) {
|
|
|
70922
71314
|
}
|
|
70923
71315
|
dir = getProjectSkillsDir(root);
|
|
70924
71316
|
}
|
|
70925
|
-
const
|
|
71317
|
+
const path101 = skillFilePath(dir, name);
|
|
70926
71318
|
const content = serializeSkillMd({
|
|
70927
71319
|
name,
|
|
70928
71320
|
description,
|
|
@@ -70931,13 +71323,13 @@ function upsertSkill(opts) {
|
|
|
70931
71323
|
tools: opts.tools,
|
|
70932
71324
|
cost: opts.cost
|
|
70933
71325
|
});
|
|
70934
|
-
const parsed = parseSkillMd(content,
|
|
71326
|
+
const parsed = parseSkillMd(content, path101);
|
|
70935
71327
|
if (!parsed) {
|
|
70936
71328
|
return { ok: false, error: "Generated SKILL.md failed validation" };
|
|
70937
71329
|
}
|
|
70938
|
-
mkdirSync23(dirname13(
|
|
70939
|
-
writeFileSync25(
|
|
70940
|
-
return { ok: true, path:
|
|
71330
|
+
mkdirSync23(dirname13(path101), { recursive: true });
|
|
71331
|
+
writeFileSync25(path101, content, "utf8");
|
|
71332
|
+
return { ok: true, path: path101 };
|
|
70941
71333
|
}
|
|
70942
71334
|
function removeSkill(opts) {
|
|
70943
71335
|
const name = opts.name.trim().toLowerCase();
|
|
@@ -70955,8 +71347,8 @@ function removeSkill(opts) {
|
|
|
70955
71347
|
dir = getProjectSkillsDir(root);
|
|
70956
71348
|
}
|
|
70957
71349
|
const skillDir = join46(dir, name);
|
|
70958
|
-
const
|
|
70959
|
-
if (!existsSync59(
|
|
71350
|
+
const path101 = skillFilePath(dir, name);
|
|
71351
|
+
if (!existsSync59(path101) && !existsSync59(skillDir)) {
|
|
70960
71352
|
return { ok: false, error: `Skill "${name}" not found in ${dir}` };
|
|
70961
71353
|
}
|
|
70962
71354
|
try {
|
|
@@ -70967,7 +71359,7 @@ function removeSkill(opts) {
|
|
|
70967
71359
|
error: err instanceof Error ? err.message : String(err)
|
|
70968
71360
|
};
|
|
70969
71361
|
}
|
|
70970
|
-
return { ok: true, path:
|
|
71362
|
+
return { ok: true, path: path101 };
|
|
70971
71363
|
}
|
|
70972
71364
|
var NAME_RE, BUILTIN_SKILL_MODULES, builtinsLoaded;
|
|
70973
71365
|
var init_skillConfigIo = __esm({
|
|
@@ -71088,7 +71480,7 @@ var init_jsonApi = __esm({
|
|
|
71088
71480
|
});
|
|
71089
71481
|
|
|
71090
71482
|
// src/cli/memory/mcpAdapter.ts
|
|
71091
|
-
import * as
|
|
71483
|
+
import * as path95 from "node:path";
|
|
71092
71484
|
var id2, projectId, source, SearchSchema, AddSchema, LinkSchema, RetractSchema, MEMORY_MCP_TOOLS, MemoryMcpAdapter;
|
|
71093
71485
|
var init_mcpAdapter = __esm({
|
|
71094
71486
|
"src/cli/memory/mcpAdapter.ts"() {
|
|
@@ -71258,8 +71650,8 @@ var init_mcpAdapter = __esm({
|
|
|
71258
71650
|
this.takeWrite();
|
|
71259
71651
|
const externalFile = args.source?.file;
|
|
71260
71652
|
if (externalFile) {
|
|
71261
|
-
const normalized =
|
|
71262
|
-
if (
|
|
71653
|
+
const normalized = path95.normalize(externalFile);
|
|
71654
|
+
if (path95.isAbsolute(normalized) || normalized === ".." || normalized.startsWith(`..${path95.sep}`)) {
|
|
71263
71655
|
throw new Error("source.file must be project-relative and cannot escape the project");
|
|
71264
71656
|
}
|
|
71265
71657
|
}
|
|
@@ -71786,12 +72178,12 @@ function ensureHome() {
|
|
|
71786
72178
|
}
|
|
71787
72179
|
}
|
|
71788
72180
|
function loadCompanionConfig() {
|
|
71789
|
-
const
|
|
71790
|
-
if (!existsSync60(
|
|
72181
|
+
const path101 = getCompanionConfigPath();
|
|
72182
|
+
if (!existsSync60(path101)) {
|
|
71791
72183
|
return { projects: [] };
|
|
71792
72184
|
}
|
|
71793
72185
|
try {
|
|
71794
|
-
const raw = JSON.parse(readFileSync45(
|
|
72186
|
+
const raw = JSON.parse(readFileSync45(path101, "utf8"));
|
|
71795
72187
|
const projects = Array.isArray(raw.projects) ? raw.projects.filter(
|
|
71796
72188
|
(p3) => p3 && typeof p3.path === "string" && p3.path.trim() && typeof (p3.id ?? p3.name) === "string"
|
|
71797
72189
|
).map((p3) => ({
|
|
@@ -71829,16 +72221,16 @@ function loadOrCreateToken(explicit) {
|
|
|
71829
72221
|
return { token: explicit.trim(), created: false };
|
|
71830
72222
|
}
|
|
71831
72223
|
ensureHome();
|
|
71832
|
-
const
|
|
71833
|
-
if (existsSync60(
|
|
71834
|
-
const t = readFileSync45(
|
|
72224
|
+
const path101 = getCompanionTokenPath();
|
|
72225
|
+
if (existsSync60(path101)) {
|
|
72226
|
+
const t = readFileSync45(path101, "utf8").trim();
|
|
71835
72227
|
if (t) return { token: t, created: false };
|
|
71836
72228
|
}
|
|
71837
72229
|
const token = randomBytes7(24).toString("base64url");
|
|
71838
|
-
writeFileSync26(
|
|
72230
|
+
writeFileSync26(path101, token + "\n", "utf8");
|
|
71839
72231
|
try {
|
|
71840
72232
|
const fs48 = __require("node:fs");
|
|
71841
|
-
fs48.chmodSync?.(
|
|
72233
|
+
fs48.chmodSync?.(path101, 384);
|
|
71842
72234
|
} catch {
|
|
71843
72235
|
}
|
|
71844
72236
|
return { token, created: true };
|
|
@@ -71863,17 +72255,17 @@ function mergeProjects(cfg, extraPaths) {
|
|
|
71863
72255
|
byId.set(p3.id, p3);
|
|
71864
72256
|
}
|
|
71865
72257
|
for (const raw of extraPaths) {
|
|
71866
|
-
const
|
|
71867
|
-
if (!
|
|
71868
|
-
let id3 = slugFromPath(
|
|
72258
|
+
const path101 = raw.trim();
|
|
72259
|
+
if (!path101) continue;
|
|
72260
|
+
let id3 = slugFromPath(path101);
|
|
71869
72261
|
let n = 2;
|
|
71870
|
-
while (byId.has(id3) && byId.get(id3).path !==
|
|
71871
|
-
id3 = `${slugFromPath(
|
|
72262
|
+
while (byId.has(id3) && byId.get(id3).path !== path101) {
|
|
72263
|
+
id3 = `${slugFromPath(path101)}-${n++}`;
|
|
71872
72264
|
}
|
|
71873
72265
|
byId.set(id3, {
|
|
71874
72266
|
id: id3,
|
|
71875
|
-
name: slugFromPath(
|
|
71876
|
-
path:
|
|
72267
|
+
name: slugFromPath(path101),
|
|
72268
|
+
path: path101
|
|
71877
72269
|
});
|
|
71878
72270
|
}
|
|
71879
72271
|
return [...byId.values()];
|
|
@@ -72116,7 +72508,7 @@ var init_askUserBridge = __esm({
|
|
|
72116
72508
|
|
|
72117
72509
|
// src/cli/serve/spineLockSweep.ts
|
|
72118
72510
|
import { promises as fs47 } from "node:fs";
|
|
72119
|
-
import
|
|
72511
|
+
import path96 from "node:path";
|
|
72120
72512
|
async function sweepOrphanSpineLocks(sessionsDir2, options = {}) {
|
|
72121
72513
|
const dir = sessionsDir2 ?? resolveSessionsDir();
|
|
72122
72514
|
const onSwept = options.onSwept ?? ((sessionId2, reason) => {
|
|
@@ -72134,7 +72526,7 @@ async function sweepOrphanSpineLocks(sessionsDir2, options = {}) {
|
|
|
72134
72526
|
return result;
|
|
72135
72527
|
}
|
|
72136
72528
|
for (const sessionId2 of entries) {
|
|
72137
|
-
const lockPath2 =
|
|
72529
|
+
const lockPath2 = path96.join(dir, sessionId2, "writer.lock");
|
|
72138
72530
|
try {
|
|
72139
72531
|
const raw = await fs47.readFile(lockPath2, "utf-8");
|
|
72140
72532
|
let lockInfo = {};
|
|
@@ -73131,9 +73523,9 @@ async function runCompanionServe(opts = {}) {
|
|
|
73131
73523
|
return;
|
|
73132
73524
|
}
|
|
73133
73525
|
const url2 = parseUrl(req);
|
|
73134
|
-
const
|
|
73526
|
+
const path101 = url2.pathname.replace(/\/+$/, "") || "/";
|
|
73135
73527
|
try {
|
|
73136
|
-
if (req.method === "GET" && (
|
|
73528
|
+
if (req.method === "GET" && (path101 === "/health" || path101 === "/v1/health")) {
|
|
73137
73529
|
sendJson2(res, 200, {
|
|
73138
73530
|
ok: true,
|
|
73139
73531
|
service: "zelari-companion",
|
|
@@ -73145,18 +73537,18 @@ async function runCompanionServe(opts = {}) {
|
|
|
73145
73537
|
});
|
|
73146
73538
|
return;
|
|
73147
73539
|
}
|
|
73148
|
-
if (
|
|
73540
|
+
if (path101.startsWith("/v1")) {
|
|
73149
73541
|
if (!tokenMatches(token, getBearer(req))) {
|
|
73150
73542
|
sendJson2(res, 401, { ok: false, error: "unauthorized" });
|
|
73151
73543
|
return;
|
|
73152
73544
|
}
|
|
73153
73545
|
}
|
|
73154
|
-
if (req.method === "GET" &&
|
|
73546
|
+
if (req.method === "GET" && path101 === "/v1/config") {
|
|
73155
73547
|
const snap = buildDesktopConfigSnapshot();
|
|
73156
73548
|
sendJson2(res, 200, { ok: true, ...snap });
|
|
73157
73549
|
return;
|
|
73158
73550
|
}
|
|
73159
|
-
if (req.method === "GET" &&
|
|
73551
|
+
if (req.method === "GET" && path101 === "/v1/projects") {
|
|
73160
73552
|
sendJson2(res, 200, {
|
|
73161
73553
|
ok: true,
|
|
73162
73554
|
projects: projects.map((p3) => ({
|
|
@@ -73167,7 +73559,7 @@ async function runCompanionServe(opts = {}) {
|
|
|
73167
73559
|
});
|
|
73168
73560
|
return;
|
|
73169
73561
|
}
|
|
73170
|
-
if (req.method === "GET" &&
|
|
73562
|
+
if (req.method === "GET" && path101 === "/v1/runs") {
|
|
73171
73563
|
sendJson2(res, 200, {
|
|
73172
73564
|
ok: true,
|
|
73173
73565
|
active: runs.getActive(),
|
|
@@ -73185,7 +73577,7 @@ async function runCompanionServe(opts = {}) {
|
|
|
73185
73577
|
});
|
|
73186
73578
|
return;
|
|
73187
73579
|
}
|
|
73188
|
-
if (req.method === "POST" &&
|
|
73580
|
+
if (req.method === "POST" && path101 === "/v1/runs") {
|
|
73189
73581
|
const raw = await readBody(req);
|
|
73190
73582
|
let body = {};
|
|
73191
73583
|
try {
|
|
@@ -73233,7 +73625,7 @@ async function runCompanionServe(opts = {}) {
|
|
|
73233
73625
|
});
|
|
73234
73626
|
return;
|
|
73235
73627
|
}
|
|
73236
|
-
const eventsMatch = /^\/v1\/runs\/([^/]+)\/events$/.exec(
|
|
73628
|
+
const eventsMatch = /^\/v1\/runs\/([^/]+)\/events$/.exec(path101);
|
|
73237
73629
|
if (req.method === "GET" && eventsMatch) {
|
|
73238
73630
|
const runId = eventsMatch[1];
|
|
73239
73631
|
const run = runs.getRun(runId);
|
|
@@ -73298,7 +73690,7 @@ async function runCompanionServe(opts = {}) {
|
|
|
73298
73690
|
}, 500);
|
|
73299
73691
|
return;
|
|
73300
73692
|
}
|
|
73301
|
-
const cancelMatch = /^\/v1\/runs\/([^/]+)\/cancel$/.exec(
|
|
73693
|
+
const cancelMatch = /^\/v1\/runs\/([^/]+)\/cancel$/.exec(path101);
|
|
73302
73694
|
if (req.method === "POST" && cancelMatch) {
|
|
73303
73695
|
const runId = cancelMatch[1];
|
|
73304
73696
|
const result = runs.cancel(runId);
|
|
@@ -73309,7 +73701,7 @@ async function runCompanionServe(opts = {}) {
|
|
|
73309
73701
|
sendJson2(res, 200, { ok: true, cancelled: runId });
|
|
73310
73702
|
return;
|
|
73311
73703
|
}
|
|
73312
|
-
const steerMatch = /^\/v1\/runs\/([^/]+)\/steer$/.exec(
|
|
73704
|
+
const steerMatch = /^\/v1\/runs\/([^/]+)\/steer$/.exec(path101);
|
|
73313
73705
|
if (req.method === "POST" && steerMatch) {
|
|
73314
73706
|
const runId = steerMatch[1];
|
|
73315
73707
|
const raw = await readBody(req);
|
|
@@ -73478,11 +73870,11 @@ import { execSync as execSync2 } from "node:child_process";
|
|
|
73478
73870
|
import { existsSync as existsSync62, readFileSync as readFileSync46, readlinkSync, statSync as statSync10 } from "node:fs";
|
|
73479
73871
|
import { createRequire as createRequire3 } from "node:module";
|
|
73480
73872
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
73481
|
-
import
|
|
73873
|
+
import path97 from "node:path";
|
|
73482
73874
|
function findPackageRoot(start) {
|
|
73483
73875
|
let dir = start;
|
|
73484
73876
|
for (let i = 0; i < 6; i += 1) {
|
|
73485
|
-
const candidate =
|
|
73877
|
+
const candidate = path97.join(dir, "package.json");
|
|
73486
73878
|
if (existsSync62(candidate)) {
|
|
73487
73879
|
try {
|
|
73488
73880
|
const pkg = JSON.parse(readFileSync46(candidate, "utf8"));
|
|
@@ -73490,11 +73882,11 @@ function findPackageRoot(start) {
|
|
|
73490
73882
|
} catch {
|
|
73491
73883
|
}
|
|
73492
73884
|
}
|
|
73493
|
-
const parent =
|
|
73885
|
+
const parent = path97.dirname(dir);
|
|
73494
73886
|
if (parent === dir) break;
|
|
73495
73887
|
dir = parent;
|
|
73496
73888
|
}
|
|
73497
|
-
return
|
|
73889
|
+
return path97.resolve(__dirname3, "..", "..", "..");
|
|
73498
73890
|
}
|
|
73499
73891
|
function tryExec(cmd) {
|
|
73500
73892
|
try {
|
|
@@ -73508,7 +73900,7 @@ function tryExec(cmd) {
|
|
|
73508
73900
|
}
|
|
73509
73901
|
function readPackageJson4() {
|
|
73510
73902
|
try {
|
|
73511
|
-
const pkgPath =
|
|
73903
|
+
const pkgPath = path97.join(packageRoot, "package.json");
|
|
73512
73904
|
return JSON.parse(readFileSync46(pkgPath, "utf8"));
|
|
73513
73905
|
} catch {
|
|
73514
73906
|
return null;
|
|
@@ -73520,7 +73912,7 @@ function getGlobalPrefix() {
|
|
|
73520
73912
|
return (process.env.npm_config_prefix || process.env.NPM_CONFIG_PREFIX || "").trim();
|
|
73521
73913
|
}
|
|
73522
73914
|
function isSourceCheckout() {
|
|
73523
|
-
return existsSync62(
|
|
73915
|
+
return existsSync62(path97.join(packageRoot, "src", "cli", "main.ts")) && existsSync62(path97.join(packageRoot, "apps", "desktop", "package.json"));
|
|
73524
73916
|
}
|
|
73525
73917
|
function checkShim(pkgName) {
|
|
73526
73918
|
const prefix = getGlobalPrefix();
|
|
@@ -73529,9 +73921,9 @@ function checkShim(pkgName) {
|
|
|
73529
73921
|
}
|
|
73530
73922
|
const isWin = process.platform === "win32";
|
|
73531
73923
|
const shimName = isWin ? "zelari-code.cmd" : "zelari-code";
|
|
73532
|
-
const shimPath =
|
|
73924
|
+
const shimPath = path97.join(prefix, shimName);
|
|
73533
73925
|
if (!existsSync62(shimPath)) {
|
|
73534
|
-
const localBin =
|
|
73926
|
+
const localBin = path97.join(packageRoot, "bin", "zelari-code.js");
|
|
73535
73927
|
if (isSourceCheckout() && existsSync62(localBin)) {
|
|
73536
73928
|
return WARN(
|
|
73537
73929
|
`global shim not found at ${shimPath}
|
|
@@ -73565,8 +73957,8 @@ function checkShim(pkgName) {
|
|
|
73565
73957
|
fix: npm install -g ${pkgName}@latest --force`
|
|
73566
73958
|
);
|
|
73567
73959
|
}
|
|
73568
|
-
const resolved =
|
|
73569
|
-
const expected =
|
|
73960
|
+
const resolved = path97.resolve(path97.dirname(shimPath), target);
|
|
73961
|
+
const expected = path97.join(
|
|
73570
73962
|
prefix,
|
|
73571
73963
|
"node_modules",
|
|
73572
73964
|
pkgName,
|
|
@@ -73608,7 +74000,7 @@ function checkNode(pkg) {
|
|
|
73608
74000
|
return OK(`node ${raw} (engines.node ${enginesNode ?? ">= 20.0.0"})`);
|
|
73609
74001
|
}
|
|
73610
74002
|
function checkBundle() {
|
|
73611
|
-
const bundle =
|
|
74003
|
+
const bundle = path97.join(packageRoot, "dist", "cli", "main.bundled.js");
|
|
73612
74004
|
if (!existsSync62(bundle)) {
|
|
73613
74005
|
return FAIL(
|
|
73614
74006
|
`dist/cli/main.bundled.js missing at ${bundle}
|
|
@@ -73629,7 +74021,7 @@ function checkRuntimeDeps() {
|
|
|
73629
74021
|
const missing = [];
|
|
73630
74022
|
for (const dep of required2) {
|
|
73631
74023
|
try {
|
|
73632
|
-
const localReq = createRequire3(
|
|
74024
|
+
const localReq = createRequire3(path97.join(packageRoot, "package.json"));
|
|
73633
74025
|
localReq.resolve(dep);
|
|
73634
74026
|
} catch {
|
|
73635
74027
|
missing.push(dep);
|
|
@@ -73906,7 +74298,7 @@ var init_doctor = __esm({
|
|
|
73906
74298
|
init_metrics3();
|
|
73907
74299
|
init_contextGrowthSummary();
|
|
73908
74300
|
require3 = createRequire3(import.meta.url);
|
|
73909
|
-
__dirname3 =
|
|
74301
|
+
__dirname3 = path97.dirname(fileURLToPath3(import.meta.url));
|
|
73910
74302
|
packageRoot = findPackageRoot(__dirname3);
|
|
73911
74303
|
OK = (message) => ({
|
|
73912
74304
|
ok: true,
|
|
@@ -74015,7 +74407,7 @@ __export(userSettings_exports, {
|
|
|
74015
74407
|
settingsOverrides: () => settingsOverrides
|
|
74016
74408
|
});
|
|
74017
74409
|
import { existsSync as existsSync63, readFileSync as readFileSync47 } from "node:fs";
|
|
74018
|
-
import
|
|
74410
|
+
import path98 from "node:path";
|
|
74019
74411
|
function parseBool(raw) {
|
|
74020
74412
|
const v = raw.trim().toLowerCase();
|
|
74021
74413
|
if (["1", "true", "yes", "on"].includes(v)) return true;
|
|
@@ -74082,8 +74474,8 @@ function envValueFor(key, env) {
|
|
|
74082
74474
|
function resolveUserSettings(opts = {}) {
|
|
74083
74475
|
const cwd = opts.cwd ?? process.cwd();
|
|
74084
74476
|
const env = opts.env ?? process.env;
|
|
74085
|
-
const userPath =
|
|
74086
|
-
const projectPath =
|
|
74477
|
+
const userPath = path98.join(zelariHome(), SETTINGS_FILE_NAME);
|
|
74478
|
+
const projectPath = path98.join(cwd, ".zelari", SETTINGS_FILE_NAME);
|
|
74087
74479
|
const warnings = [];
|
|
74088
74480
|
const userLayer = loadFileLayer(userPath, "user", warnings);
|
|
74089
74481
|
const projectLayer = loadFileLayer(projectPath, "project", warnings);
|
|
@@ -74297,7 +74689,7 @@ __export(inspectSession_exports, {
|
|
|
74297
74689
|
renderInspectReport: () => renderInspectReport,
|
|
74298
74690
|
runInspectSession: () => runInspectSession
|
|
74299
74691
|
});
|
|
74300
|
-
import
|
|
74692
|
+
import path99 from "node:path";
|
|
74301
74693
|
import { existsSync as existsSync64 } from "node:fs";
|
|
74302
74694
|
function formatLimit(limit) {
|
|
74303
74695
|
return `${Math.round(limit / 1e3)}k`;
|
|
@@ -74331,8 +74723,8 @@ function renderInspectReport(state3) {
|
|
|
74331
74723
|
}
|
|
74332
74724
|
async function runInspectSession(opts) {
|
|
74333
74725
|
const sessionsDir2 = resolveSessionsDir({ workspaceRoot: opts.cwd ?? process.cwd() });
|
|
74334
|
-
const sessionDir =
|
|
74335
|
-
const eventsPath =
|
|
74726
|
+
const sessionDir = path99.join(sessionsDir2, opts.sessionId);
|
|
74727
|
+
const eventsPath = path99.join(sessionDir, "events.jsonl");
|
|
74336
74728
|
if (!existsSync64(sessionDir)) {
|
|
74337
74729
|
console.error(`zelari-code inspect: no session directory at ${sessionDir}`);
|
|
74338
74730
|
return 1;
|
|
@@ -74366,14 +74758,14 @@ __export(inspect_exports, {
|
|
|
74366
74758
|
collectInspectReport: () => collectInspectReport,
|
|
74367
74759
|
runInspect: () => runInspect
|
|
74368
74760
|
});
|
|
74369
|
-
import
|
|
74761
|
+
import path100 from "node:path";
|
|
74370
74762
|
import { existsSync as existsSync65, readFileSync as readFileSync48, readdirSync as readdirSync13 } from "node:fs";
|
|
74371
74763
|
async function collectInspectReport(cwd = process.cwd()) {
|
|
74372
74764
|
ensureBuiltinSkillsLoadedSync();
|
|
74373
74765
|
const snap = listSkillsSnapshot(cwd);
|
|
74374
74766
|
const mcp = listMcpServers(cwd);
|
|
74375
|
-
const userMcpPath =
|
|
74376
|
-
const projectMcpPath =
|
|
74767
|
+
const userMcpPath = path100.join(zelariHome(), "mcp.json");
|
|
74768
|
+
const projectMcpPath = path100.join(cwd, ".zelari", "mcp.json");
|
|
74377
74769
|
const globalHooks = globalHooksDir();
|
|
74378
74770
|
const projectHooks = projectHooksDir(cwd);
|
|
74379
74771
|
const projectTrusted = isFolderTrusted(cwd);
|
|
@@ -74401,9 +74793,9 @@ async function collectInspectReport(cwd = process.cwd()) {
|
|
|
74401
74793
|
configSources: [
|
|
74402
74794
|
{ path: userMcpPath, exists: existsSync65(userMcpPath) },
|
|
74403
74795
|
{ path: projectMcpPath, exists: existsSync65(projectMcpPath) },
|
|
74404
|
-
{ path:
|
|
74405
|
-
{ path:
|
|
74406
|
-
{ path:
|
|
74796
|
+
{ path: path100.join(zelariHome(), "provider.json"), exists: existsSync65(path100.join(zelariHome(), "provider.json")) },
|
|
74797
|
+
{ path: path100.join(cwd, ".zelari", "AGENTS.md"), exists: existsSync65(path100.join(cwd, ".zelari", "AGENTS.md")) },
|
|
74798
|
+
{ path: path100.join(cwd, "AGENTS.md"), exists: existsSync65(path100.join(cwd, "AGENTS.md")) }
|
|
74407
74799
|
],
|
|
74408
74800
|
skills: {
|
|
74409
74801
|
total: snap.skills.length,
|
|
@@ -74443,8 +74835,8 @@ function listJsonFiles(dir) {
|
|
|
74443
74835
|
}
|
|
74444
74836
|
function findAgentsMd(cwd) {
|
|
74445
74837
|
const candidates = [
|
|
74446
|
-
|
|
74447
|
-
|
|
74838
|
+
path100.join(cwd, "AGENTS.md"),
|
|
74839
|
+
path100.join(cwd, ".zelari", "AGENTS.md")
|
|
74448
74840
|
];
|
|
74449
74841
|
const found = [];
|
|
74450
74842
|
for (const c of candidates) {
|
|
@@ -78197,7 +78589,10 @@ _(${req.context})_` : "") + "\n\u2192 scegli dalla lista (il turno continua dopo
|
|
|
78197
78589
|
progressRuntime.observe(event);
|
|
78198
78590
|
if (event.type === "agent_end") {
|
|
78199
78591
|
let krakenSuppressFinish = false;
|
|
78200
|
-
const krakenSpineEmit = (input) =>
|
|
78592
|
+
const krakenSpineEmit = async (input) => {
|
|
78593
|
+
const seq = await (writerRef.current?.spine?.appendEvent(input) ?? Promise.resolve(null));
|
|
78594
|
+
return { seq };
|
|
78595
|
+
};
|
|
78201
78596
|
const writeProofSafe2 = (gate) => writeCompletionProof(gate, { meta: { surface: "kraken", sessionId: sessionId2 } }).then(
|
|
78202
78597
|
() => void 0,
|
|
78203
78598
|
() => void 0
|
|
@@ -78211,7 +78606,9 @@ _(${req.context})_` : "") + "\n\u2192 scegli dalla lista (il turno continua dopo
|
|
|
78211
78606
|
if (krakenGate.blocked) {
|
|
78212
78607
|
krakenRepairEnqueued = true;
|
|
78213
78608
|
markRepairTriggered();
|
|
78214
|
-
harness2.enqueue(
|
|
78609
|
+
harness2.enqueue(
|
|
78610
|
+
buildKrakenRepairPrompt(krakenGate, repairExcerptsFromEvaluation(strictGate))
|
|
78611
|
+
);
|
|
78215
78612
|
appendSystem(
|
|
78216
78613
|
setMessages,
|
|
78217
78614
|
formatStrictBlockExplanation(strictGate),
|
|
@@ -79407,11 +79804,14 @@ async function dispatchZelariPromptImpl(text, deps, pendingRef) {
|
|
|
79407
79804
|
}
|
|
79408
79805
|
const { buildMissionBrief: buildMissionBrief2 } = await Promise.resolve().then(() => (init_council(), council_exports));
|
|
79409
79806
|
const { hasWorkspacePlan: hasWorkspacePlan2 } = await Promise.resolve().then(() => (init_planDetect(), planDetect_exports));
|
|
79807
|
+
const { listOpenPlanTaskIds: listOpenPlanTaskIds2 } = await Promise.resolve().then(() => (init_planStore(), planStore_exports));
|
|
79410
79808
|
const { formatBriefForChat: formatBriefForChat2, isMissionAutoStart: isMissionAutoStart2 } = await Promise.resolve().then(() => (init_zelariMission(), zelariMission_exports));
|
|
79411
79809
|
const projectRoot = process.cwd();
|
|
79810
|
+
const planTaskIds = await listOpenPlanTaskIds2(projectRoot);
|
|
79412
79811
|
const brief = buildMissionBrief2({
|
|
79413
79812
|
userMessage: text,
|
|
79414
|
-
hasPlan: hasWorkspacePlan2(projectRoot)
|
|
79813
|
+
hasPlan: hasWorkspacePlan2(projectRoot),
|
|
79814
|
+
planTaskIds
|
|
79415
79815
|
});
|
|
79416
79816
|
emit(formatBriefForChat2(brief));
|
|
79417
79817
|
if (isMissionAutoStart2()) {
|
|
@@ -79437,11 +79837,14 @@ async function runZelariMissionInTui(userMessage, deps, emit) {
|
|
|
79437
79837
|
const projectRoot = process.cwd();
|
|
79438
79838
|
const { buildMissionBrief: buildMissionBrief2 } = await Promise.resolve().then(() => (init_council(), council_exports));
|
|
79439
79839
|
const { hasWorkspacePlan: hasWorkspacePlan2 } = await Promise.resolve().then(() => (init_planDetect(), planDetect_exports));
|
|
79840
|
+
const { listOpenPlanTaskIds: listOpenPlanTaskIds2 } = await Promise.resolve().then(() => (init_planStore(), planStore_exports));
|
|
79440
79841
|
const { getMemoryBackend: getMemoryBackend2 } = await Promise.resolve().then(() => (init_fileBackend(), fileBackend_exports));
|
|
79441
79842
|
const { runZelariMission: runZelariMission2 } = await Promise.resolve().then(() => (init_zelariMission(), zelariMission_exports));
|
|
79843
|
+
const planTaskIds = await listOpenPlanTaskIds2(projectRoot);
|
|
79442
79844
|
const brief = buildMissionBrief2({
|
|
79443
79845
|
userMessage,
|
|
79444
|
-
hasPlan: hasWorkspacePlan2(projectRoot)
|
|
79846
|
+
hasPlan: hasWorkspacePlan2(projectRoot),
|
|
79847
|
+
planTaskIds
|
|
79445
79848
|
});
|
|
79446
79849
|
const missionSpineHolder = {
|
|
79447
79850
|
get current() {
|
|
@@ -79699,10 +80102,10 @@ init_ledger();
|
|
|
79699
80102
|
|
|
79700
80103
|
// src/cli/evolution/proposals.ts
|
|
79701
80104
|
import { existsSync as existsSync51, readFileSync as readFileSync39 } from "node:fs";
|
|
79702
|
-
import
|
|
79703
|
-
var PROPOSALS_REL =
|
|
80105
|
+
import path78 from "node:path";
|
|
80106
|
+
var PROPOSALS_REL = path78.join(".zelari", "evolution", "proposals.jsonl");
|
|
79704
80107
|
function proposalsPath(cwd) {
|
|
79705
|
-
return
|
|
80108
|
+
return path78.join(cwd, PROPOSALS_REL);
|
|
79706
80109
|
}
|
|
79707
80110
|
function readProposalStore(cwd) {
|
|
79708
80111
|
const file2 = proposalsPath(cwd);
|
|
@@ -80812,11 +81215,11 @@ function handleCacheStats(ctx) {
|
|
|
80812
81215
|
init_messageHelpers();
|
|
80813
81216
|
init_serviceFactory();
|
|
80814
81217
|
import { promises as fs35 } from "node:fs";
|
|
80815
|
-
import * as
|
|
81218
|
+
import * as path80 from "node:path";
|
|
80816
81219
|
|
|
80817
81220
|
// src/cli/memory/promotion.ts
|
|
80818
81221
|
import { promises as fs34 } from "node:fs";
|
|
80819
|
-
import * as
|
|
81222
|
+
import * as path79 from "node:path";
|
|
80820
81223
|
var START = "<!-- zelari:memory-promotions:start -->";
|
|
80821
81224
|
var END = "<!-- zelari:memory-promotions:end -->";
|
|
80822
81225
|
var DURABLE_KINDS = /* @__PURE__ */ new Set(["fact", "decision", "constraint", "preference", "procedure"]);
|
|
@@ -80827,13 +81230,13 @@ function lineFor(node) {
|
|
|
80827
81230
|
}
|
|
80828
81231
|
async function promoteMemoryToAgentsMd(projectRoot, node) {
|
|
80829
81232
|
if (node.status !== "active") {
|
|
80830
|
-
return { added: false, path:
|
|
81233
|
+
return { added: false, path: path79.join(projectRoot, "AGENTS.md"), reason: `memory is ${node.status}` };
|
|
80831
81234
|
}
|
|
80832
81235
|
if (!DURABLE_KINDS.has(node.kind)) {
|
|
80833
|
-
return { added: false, path:
|
|
81236
|
+
return { added: false, path: path79.join(projectRoot, "AGENTS.md"), reason: `${node.kind} is not a durable instruction kind` };
|
|
80834
81237
|
}
|
|
80835
|
-
const root = await fs34.realpath(projectRoot).catch(() =>
|
|
80836
|
-
const target =
|
|
81238
|
+
const root = await fs34.realpath(projectRoot).catch(() => path79.resolve(projectRoot));
|
|
81239
|
+
const target = path79.join(root, "AGENTS.md");
|
|
80837
81240
|
try {
|
|
80838
81241
|
const stat8 = await fs34.lstat(target);
|
|
80839
81242
|
if (stat8.isSymbolicLink() || !stat8.isFile()) throw new Error("AGENTS.md must be a regular project file.");
|
|
@@ -80898,22 +81301,22 @@ function sourceLine(source2) {
|
|
|
80898
81301
|
return entries.length ? entries.map(([key, value]) => `${key}=${value}`).join(" \xB7 ") : "unknown";
|
|
80899
81302
|
}
|
|
80900
81303
|
function isInside(root, target) {
|
|
80901
|
-
const relative6 =
|
|
80902
|
-
return relative6 === "" || !relative6.startsWith("..") && !
|
|
81304
|
+
const relative6 = path80.relative(root, target);
|
|
81305
|
+
return relative6 === "" || !relative6.startsWith("..") && !path80.isAbsolute(relative6);
|
|
80903
81306
|
}
|
|
80904
81307
|
async function safeExportPath(cwd, requested) {
|
|
80905
|
-
const lexicalRoot =
|
|
81308
|
+
const lexicalRoot = path80.resolve(cwd);
|
|
80906
81309
|
const root = await fs35.realpath(lexicalRoot).catch(() => lexicalRoot);
|
|
80907
|
-
const fallback =
|
|
80908
|
-
const target = requested?.trim() ?
|
|
81310
|
+
const fallback = path80.join(root, ".zelari", "memory", `export-${Date.now()}.json`);
|
|
81311
|
+
const target = requested?.trim() ? path80.resolve(root, requested.trim()) : fallback;
|
|
80909
81312
|
if (!isInside(root, target)) {
|
|
80910
81313
|
throw new Error("Export path must stay inside the active project.");
|
|
80911
81314
|
}
|
|
80912
|
-
const parent =
|
|
80913
|
-
const relativeParent =
|
|
81315
|
+
const parent = path80.dirname(target);
|
|
81316
|
+
const relativeParent = path80.relative(root, parent);
|
|
80914
81317
|
let cursor = root;
|
|
80915
|
-
for (const segment of relativeParent.split(
|
|
80916
|
-
cursor =
|
|
81318
|
+
for (const segment of relativeParent.split(path80.sep).filter(Boolean)) {
|
|
81319
|
+
cursor = path80.join(cursor, segment);
|
|
80917
81320
|
try {
|
|
80918
81321
|
const stat8 = await fs35.lstat(cursor);
|
|
80919
81322
|
if (stat8.isSymbolicLink()) {
|
|
@@ -81085,9 +81488,9 @@ ${message}` : message
|
|
|
81085
81488
|
}
|
|
81086
81489
|
case "export": {
|
|
81087
81490
|
const target = await safeExportPath(ctx.cwd, args.join(" ").trim() || void 0);
|
|
81088
|
-
await fs35.mkdir(
|
|
81089
|
-
const root = await fs35.realpath(ctx.cwd).catch(() =>
|
|
81090
|
-
const realParent = await fs35.realpath(
|
|
81491
|
+
await fs35.mkdir(path80.dirname(target), { recursive: true });
|
|
81492
|
+
const root = await fs35.realpath(ctx.cwd).catch(() => path80.resolve(ctx.cwd));
|
|
81493
|
+
const realParent = await fs35.realpath(path80.dirname(target));
|
|
81091
81494
|
if (!isInside(root, realParent)) {
|
|
81092
81495
|
throw new Error("Export path resolves outside the active project.");
|
|
81093
81496
|
}
|
|
@@ -81302,7 +81705,7 @@ import { promises as fs37 } from "node:fs";
|
|
|
81302
81705
|
init_zod();
|
|
81303
81706
|
init_taskTool();
|
|
81304
81707
|
import { promises as fs36 } from "node:fs";
|
|
81305
|
-
import
|
|
81708
|
+
import path81 from "node:path";
|
|
81306
81709
|
import { randomBytes as randomBytes6 } from "node:crypto";
|
|
81307
81710
|
var CsvFanoutArgsSchema = external_exports.object({
|
|
81308
81711
|
csv_path: external_exports.string().min(1),
|
|
@@ -81396,8 +81799,8 @@ function resolveMaxConcurrency(env = process.env) {
|
|
|
81396
81799
|
}
|
|
81397
81800
|
async function runCsvFanout(args, deps, opts) {
|
|
81398
81801
|
const start = Date.now();
|
|
81399
|
-
const absCsv =
|
|
81400
|
-
const absOut =
|
|
81802
|
+
const absCsv = path81.isAbsolute(args.csv_path) ? args.csv_path : path81.join(opts.parentCwd, args.csv_path);
|
|
81803
|
+
const absOut = path81.isAbsolute(args.output_csv_path) ? args.output_csv_path : path81.join(opts.parentCwd, args.output_csv_path);
|
|
81401
81804
|
const { headers: headers3, rows } = await readCsv(absCsv);
|
|
81402
81805
|
if (headers3.length === 0) {
|
|
81403
81806
|
throw new Error(`kraken_csv_fanout: ${absCsv} is empty`);
|
|
@@ -81453,7 +81856,7 @@ async function runCsvFanout(args, deps, opts) {
|
|
|
81453
81856
|
errored += 1;
|
|
81454
81857
|
errors.push(`${row[args.id_column] ?? i}: ${res.error}`);
|
|
81455
81858
|
}
|
|
81456
|
-
await fs36.mkdir(
|
|
81859
|
+
await fs36.mkdir(path81.dirname(absOut), { recursive: true });
|
|
81457
81860
|
await queueWrite(serializeCsv(outHeaders, outputRecords));
|
|
81458
81861
|
}
|
|
81459
81862
|
}
|
|
@@ -81648,7 +82051,7 @@ function splitArgs(s) {
|
|
|
81648
82051
|
// src/cli/slashHandlers/krakenWorkbench.ts
|
|
81649
82052
|
init_messageHelpers();
|
|
81650
82053
|
import { promises as fs38 } from "node:fs";
|
|
81651
|
-
import
|
|
82054
|
+
import path82 from "node:path";
|
|
81652
82055
|
|
|
81653
82056
|
// src/cli/kraken/workbenchView.ts
|
|
81654
82057
|
var EMPTY = {
|
|
@@ -81765,14 +82168,14 @@ function formatWorkbenchForTerminal(p3) {
|
|
|
81765
82168
|
|
|
81766
82169
|
// src/cli/slashHandlers/krakenWorkbench.ts
|
|
81767
82170
|
async function handleKrakenWorkbench(ctx) {
|
|
81768
|
-
const dir =
|
|
82171
|
+
const dir = path82.join(ctx.cwd, ".zelari", "radio");
|
|
81769
82172
|
let latest = null;
|
|
81770
82173
|
let latestMtime = 0;
|
|
81771
82174
|
try {
|
|
81772
82175
|
const files = await fs38.readdir(dir);
|
|
81773
82176
|
for (const f of files) {
|
|
81774
82177
|
if (!f.startsWith("workbench-") || !f.endsWith(".md")) continue;
|
|
81775
|
-
const full =
|
|
82178
|
+
const full = path82.join(dir, f);
|
|
81776
82179
|
const stat8 = await fs38.stat(full);
|
|
81777
82180
|
if (stat8.mtimeMs > latestMtime) {
|
|
81778
82181
|
latestMtime = stat8.mtimeMs;
|
|
@@ -81789,10 +82192,10 @@ async function handleKrakenWorkbench(ctx) {
|
|
|
81789
82192
|
const parsed = parseWorkbench(content);
|
|
81790
82193
|
const rendered = formatWorkbenchForTerminal(parsed);
|
|
81791
82194
|
if (!rendered.trim()) {
|
|
81792
|
-
appendSystem(ctx.setMessages, `[kraken workbench] ${
|
|
82195
|
+
appendSystem(ctx.setMessages, `[kraken workbench] ${path82.basename(latest)}: (no nodes / no events yet)`);
|
|
81793
82196
|
return;
|
|
81794
82197
|
}
|
|
81795
|
-
appendSystem(ctx.setMessages, `[kraken workbench] ${
|
|
82198
|
+
appendSystem(ctx.setMessages, `[kraken workbench] ${path82.basename(latest)}:
|
|
81796
82199
|
${rendered}`);
|
|
81797
82200
|
}
|
|
81798
82201
|
|
|
@@ -82100,14 +82503,14 @@ ${result.output.split("\n").slice(-8).join("\n")}` : "";
|
|
|
82100
82503
|
init_messageHelpers();
|
|
82101
82504
|
init_paths();
|
|
82102
82505
|
import { promises as fs39 } from "node:fs";
|
|
82103
|
-
import
|
|
82506
|
+
import path85 from "node:path";
|
|
82104
82507
|
async function handlePromoteMember(ctx, memberId) {
|
|
82105
82508
|
try {
|
|
82106
82509
|
const { promoteMember: promoteMember2 } = await Promise.resolve().then(() => (init_council(), council_exports));
|
|
82107
82510
|
const { skill, markdown } = promoteMember2(memberId);
|
|
82108
82511
|
const skillDir = skillsDir();
|
|
82109
82512
|
await fs39.mkdir(skillDir, { recursive: true });
|
|
82110
|
-
const filePath =
|
|
82513
|
+
const filePath = path85.join(skillDir, `${skill.id}.md`);
|
|
82111
82514
|
const previous = await fs39.readFile(filePath, "utf8").catch(() => null);
|
|
82112
82515
|
const { createHash: createHash24 } = await import("node:crypto");
|
|
82113
82516
|
const sha = (s) => createHash24("sha256").update(s, "utf8").digest("hex");
|
|
@@ -82133,7 +82536,7 @@ ${lineage}
|
|
|
82133
82536
|
// src/cli/branchManager.ts
|
|
82134
82537
|
init_paths();
|
|
82135
82538
|
import { promises as fs40, existsSync as existsSync55, readFileSync as readFileSync41, writeFileSync as writeFileSync24, mkdirSync as mkdirSync21, statSync as statSync7, rmSync as rmSync3 } from "node:fs";
|
|
82136
|
-
import
|
|
82539
|
+
import path86 from "node:path";
|
|
82137
82540
|
var META_FILENAME = "meta.json";
|
|
82138
82541
|
var SESSIONS_SUBDIR = "sessions";
|
|
82139
82542
|
function getBranchesBaseDir() {
|
|
@@ -82143,13 +82546,13 @@ function getSessionsBaseDir() {
|
|
|
82143
82546
|
return sessionsDir();
|
|
82144
82547
|
}
|
|
82145
82548
|
function branchPathFor(name, baseDir) {
|
|
82146
|
-
return
|
|
82549
|
+
return path86.join(baseDir, name);
|
|
82147
82550
|
}
|
|
82148
82551
|
function metaPathFor(name, baseDir) {
|
|
82149
|
-
return
|
|
82552
|
+
return path86.join(baseDir, name, META_FILENAME);
|
|
82150
82553
|
}
|
|
82151
82554
|
function sessionsPathFor(name, baseDir) {
|
|
82152
|
-
return
|
|
82555
|
+
return path86.join(baseDir, name, SESSIONS_SUBDIR);
|
|
82153
82556
|
}
|
|
82154
82557
|
function readBranchMeta(name, baseDir) {
|
|
82155
82558
|
const metaPath = metaPathFor(name, baseDir);
|
|
@@ -82174,7 +82577,7 @@ function readBranchMeta(name, baseDir) {
|
|
|
82174
82577
|
}
|
|
82175
82578
|
function writeBranchMeta(name, baseDir, meta3) {
|
|
82176
82579
|
const metaPath = metaPathFor(name, baseDir);
|
|
82177
|
-
mkdirSync21(
|
|
82580
|
+
mkdirSync21(path86.dirname(metaPath), { recursive: true });
|
|
82178
82581
|
writeFileSync24(metaPath, JSON.stringify(meta3, null, 2), "utf-8");
|
|
82179
82582
|
}
|
|
82180
82583
|
async function countSessions(name, baseDir) {
|
|
@@ -82225,14 +82628,14 @@ async function createBranch(name, fromSessionId, baseDir = getBranchesBaseDir(),
|
|
|
82225
82628
|
if (branchExists(name, baseDir)) {
|
|
82226
82629
|
throw new BranchAlreadyExistsError(name);
|
|
82227
82630
|
}
|
|
82228
|
-
const sourcePath =
|
|
82631
|
+
const sourcePath = path86.join(sessionsBaseDir, `${fromSessionId}.jsonl`);
|
|
82229
82632
|
if (!existsSync55(sourcePath)) {
|
|
82230
82633
|
throw new SessionNotFoundError(`Source session "${fromSessionId}" not found at ${sourcePath}`);
|
|
82231
82634
|
}
|
|
82232
82635
|
const branchPath = branchPathFor(name, baseDir);
|
|
82233
82636
|
const branchSessionsPath = sessionsPathFor(name, baseDir);
|
|
82234
82637
|
mkdirSync21(branchSessionsPath, { recursive: true });
|
|
82235
|
-
const destPath =
|
|
82638
|
+
const destPath = path86.join(branchSessionsPath, `${fromSessionId}.jsonl`);
|
|
82236
82639
|
await fs40.copyFile(sourcePath, destPath);
|
|
82237
82640
|
const meta3 = {
|
|
82238
82641
|
name,
|
|
@@ -82336,14 +82739,14 @@ async function handleBranchCheckout(ctx, branchName) {
|
|
|
82336
82739
|
// src/cli/slashHandlers/workspace.ts
|
|
82337
82740
|
init_messageHelpers();
|
|
82338
82741
|
import { promises as fs41 } from "node:fs";
|
|
82339
|
-
import
|
|
82742
|
+
import path87 from "node:path";
|
|
82340
82743
|
async function handleWorkspaceShow(ctx, what) {
|
|
82341
82744
|
try {
|
|
82342
|
-
const zelari =
|
|
82745
|
+
const zelari = path87.join(process.cwd(), ".zelari");
|
|
82343
82746
|
let content;
|
|
82344
82747
|
switch (what) {
|
|
82345
82748
|
case "plan": {
|
|
82346
|
-
const planPath =
|
|
82749
|
+
const planPath = path87.join(zelari, "plan.md");
|
|
82347
82750
|
try {
|
|
82348
82751
|
content = await fs41.readFile(planPath, "utf-8");
|
|
82349
82752
|
} catch {
|
|
@@ -82352,7 +82755,7 @@ async function handleWorkspaceShow(ctx, what) {
|
|
|
82352
82755
|
break;
|
|
82353
82756
|
}
|
|
82354
82757
|
case "decisions": {
|
|
82355
|
-
const decisionsDir =
|
|
82758
|
+
const decisionsDir = path87.join(zelari, "decisions");
|
|
82356
82759
|
try {
|
|
82357
82760
|
const files = (await fs41.readdir(decisionsDir)).filter((f) => f.endsWith(".md")).sort();
|
|
82358
82761
|
if (files.length === 0) {
|
|
@@ -82362,7 +82765,7 @@ async function handleWorkspaceShow(ctx, what) {
|
|
|
82362
82765
|
`];
|
|
82363
82766
|
const { parseFrontmatter: parseFrontmatter2 } = await Promise.resolve().then(() => (init_storage(), storage_exports));
|
|
82364
82767
|
for (const f of files) {
|
|
82365
|
-
const raw = await fs41.readFile(
|
|
82768
|
+
const raw = await fs41.readFile(path87.join(decisionsDir, f), "utf-8");
|
|
82366
82769
|
const { meta: meta3, body } = parseFrontmatter2(raw);
|
|
82367
82770
|
const title = meta3.title ?? body.split("\n")[0]?.replace(/^#\s*/, "").trim() ?? f;
|
|
82368
82771
|
lines.push(`- **${f.replace(/\.md$/, "")}** [${meta3.status ?? "unknown"}] ${title}`);
|
|
@@ -82375,7 +82778,7 @@ async function handleWorkspaceShow(ctx, what) {
|
|
|
82375
82778
|
break;
|
|
82376
82779
|
}
|
|
82377
82780
|
case "risks": {
|
|
82378
|
-
const risksPath =
|
|
82781
|
+
const risksPath = path87.join(zelari, "risks.md");
|
|
82379
82782
|
try {
|
|
82380
82783
|
content = await fs41.readFile(risksPath, "utf-8");
|
|
82381
82784
|
} catch {
|
|
@@ -82384,7 +82787,7 @@ async function handleWorkspaceShow(ctx, what) {
|
|
|
82384
82787
|
break;
|
|
82385
82788
|
}
|
|
82386
82789
|
case "agents": {
|
|
82387
|
-
const agentsPath =
|
|
82790
|
+
const agentsPath = path87.join(process.cwd(), "AGENTS.MD");
|
|
82388
82791
|
try {
|
|
82389
82792
|
content = await fs41.readFile(agentsPath, "utf-8");
|
|
82390
82793
|
} catch {
|
|
@@ -82393,7 +82796,7 @@ async function handleWorkspaceShow(ctx, what) {
|
|
|
82393
82796
|
break;
|
|
82394
82797
|
}
|
|
82395
82798
|
case "docs": {
|
|
82396
|
-
const docsDir =
|
|
82799
|
+
const docsDir = path87.join(zelari, "docs");
|
|
82397
82800
|
try {
|
|
82398
82801
|
const files = (await fs41.readdir(docsDir)).filter((f) => f.endsWith(".md")).sort();
|
|
82399
82802
|
content = files.length ? `# Docs (${files.length})
|
|
@@ -82435,7 +82838,7 @@ async function handleWorkspaceReset(ctx, force) {
|
|
|
82435
82838
|
return;
|
|
82436
82839
|
}
|
|
82437
82840
|
try {
|
|
82438
|
-
const target =
|
|
82841
|
+
const target = path87.join(process.cwd(), ".zelari");
|
|
82439
82842
|
await fs41.rm(target, { recursive: true, force: true });
|
|
82440
82843
|
appendSystem(ctx.setMessages, "[workspace] .zelari/ removed");
|
|
82441
82844
|
} catch (err) {
|
|
@@ -84319,8 +84722,8 @@ function normalizeDraft(raw, sourceUrl, provider, model) {
|
|
|
84319
84722
|
let name = String(o.name ?? "").trim().toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 64);
|
|
84320
84723
|
if (!name || !/^[a-z0-9][a-z0-9-]{0,63}$/.test(name)) {
|
|
84321
84724
|
try {
|
|
84322
|
-
const
|
|
84323
|
-
name =
|
|
84725
|
+
const path101 = new URL(sourceUrl).pathname.split("/").filter(Boolean).pop()?.replace(/\.[a-z0-9]+$/i, "").toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 48);
|
|
84726
|
+
name = path101 && /^[a-z0-9]/.test(path101) ? path101 : "imported-skill";
|
|
84324
84727
|
} catch {
|
|
84325
84728
|
name = "imported-skill";
|
|
84326
84729
|
}
|
|
@@ -84733,7 +85136,7 @@ proposals: npm run evolve:propose \u2014 decisions in npm run evolve:decide (P1:
|
|
|
84733
85136
|
}
|
|
84734
85137
|
if (argv.includes("--help") || argv.includes("-h")) {
|
|
84735
85138
|
console.log(
|
|
84736
|
-
"zelari-code \u2014 AI Council coding agent CLI.\n\nUsage: zelari-code [options]\n\nOptions:\n --version, -v Print version and exit\n --help, -h Print this help and exit\n --doctor [--json] Diagnose install health (shim, bundle, PATH, deps,\n node/git/bash in the agent shell)\n --inspect [--json] Unified project inspection (config, skills, MCP,\n hooks, plugins, AGENTS.md, trust status)\n --trust [path] Trust the cwd (or path) so project MCP + hooks load\n --fix-path Add the npm global prefix to the user PATH\n (Windows only; fixes 'command not found' after install)\n --fix-budget Set recommended ZELARI_MAX_TOOL_LOOP_HARD=180,\n ZELARI_MAX_TOOL_LOOP_ITERATIONS=60, ZELARI_CONTEXT_LIMIT=400000\n at User scope (prevents the agent stopping mid-task)\n --permission-mcp <socket> MCP stdio server for external agent permission prompts\n (spawned by claude --permission-prompt-tool)\n --memory-mcp Optional MCP stdio server for project memory\n --cwd <path> Trusted project root (requires ZELARI_MEMORY_MCP=1)\n --client-id <id> Stable local owner identity for private memories\n --memory-json <json> Read-only project-memory bridge for Zelari Desktop\n --skip-checks Skip the boot-time prerequisite check\n (alias for ZELARI_SKIP_PREFLIGHT=1)\n --no-wizard Skip the first-run wizard\n --reset-config Re-run the wizard (clears provider.json on commit)\n --headless Run a single task without mounting the TUI\n --task <text> Task prompt (required in headless mode)\n --output json|plain Output format (default: json)\n --mode kraken|council|zelari Dispatch mode (default: kraken; agent=alias)\n --council Alias for --mode council\n --phase plan|build Work phase (default: build)\n --provider <id> Provider override (default: active)\n --model <id> Model override (default: provider default)\n --profile <id> Capability profile (minimal/v1|kraken/v1|council/v1|mission/v1)\n --resume <id> Continue a 2.0 spine session\n --export-session <path> Write zelari-session-export/1 after the run\n --strict-done Evidence-based BUILD completion gate\n --task-file <path> Read the task prompt from a file (Windows argv cap)\n --once Single-cycle run (cron/git-hook triggers, ADR-0014)\n --kraken-graph <goal> Plan + execute a Kraken task graph\n (variant: --kraken-graph-file <path>; kill-switch\n ZELARI_KRAKEN_GRAPH=0)\n --plan-only Serialize the graph plan to .zelari/radio/ and exit 0\n --run-plan <id> Execute a pre-built .zelari/radio/plan-<id>.json\n --gauntlet Host-driven gauntlet loop (builder/critic tentacles)\n --session-export <id> Print a portable 2.0 session export (no LLM)\n serve Companion host for Android/remote clients (Tailscale)\n --bind <ip> Listen address (default: 127.0.0.1; use Tailscale IP)\n --port <n> Port (default: 7421)\n --token <secret> Bearer token (default: ~/.zelari-code/companion.token)\n --project <path> Allowlisted project root (repeatable)\n --save-projects Persist --project list to companion.json\n --serve-harness Long-lived harness kernel for hosts (NDJSON JSON-RPC\n on stdin/stdout; Desktop/companion transport)\n --print-config Print provider/model config as JSON (no secrets)\n --print-settings Print zelari.config.json values + the origin of\n each (default < user < project < env)\n --permissions <p> Permission preset: strict | standard | yolo \u2014 changes\n category DEFAULTS only (env vars and policy files win)\n --evolve-status Evolution ledger stats (read-only; ADR-0036; the\n ledger is written only when ZELARI_EVOLUTION=shadow)\n --plugins-status JSON status of optional plugins (Playwright, eslint, \u2026)\n --plugins-install <id> Install plugin (playwright also fetches Chromium)\n --cwd <path> Workspace for -D installs (default: process.cwd())\n --set-config Persist provider/model/endpoint\n --provider <id> Set active provider\n --model <id> Set model for that provider\n --endpoint <url> Custom OpenAI-compatible base URL\n --endpoint-clear Remove custom endpoint override\n --thinking <spec> Thinking effort (auto|off|low|medium|high|budget:N)\n --set-key Store an API key (never printed back)\n --provider <id> Provider id (required)\n --key <secret> API key (required)\n --login-oauth Start subscription OAuth (grok, chatgpt, anthropic)\n --provider <id> grok | chatgpt | anthropic\n --code <paste> Anthropic magic-link code (CODE#STATE)\n --no-browser Do not open the system browser\n --refresh-oauth Force-refresh an OAuth access token\n --provider <id> grok | chatgpt | anthropic\n --logout-oauth Clear stored OAuth credentials\n --provider <id> grok | chatgpt | anthropic\n --discover-models Refresh model list for a provider\n --provider <id> Provider (default: active)\n --print-mcp Print MCP server config (user + project)\n --cwd <path> Project root for .zelari/mcp.json\n --set-mcp Add/update an MCP server entry\n --name <id> Server name (required)\n --command <bin> Executable for stdio servers\n --url <endpoint> Streamable HTTP endpoint (e.g. UE 5.8 editor)\n --args <json> JSON array of args (stdio, optional)\n --timeout <ms> Per-server request timeout (http, optional)\n --scope user|project Default: user\n --enabled true|false Default: true\n --cwd <path> Required when scope=project\n --set-mcp-preset Install a named MCP preset (e.g. cua)\n --preset cua Cua Driver desktop computer-use (MCP)\n --preset unreal-mcp Unreal Engine 5.8+ editor (MCP over HTTP)\n --scope user|project Default: user\n --cwd <path> Required when scope=project\n --remove-mcp Remove an MCP server entry\n --name <id> --scope user|project [--cwd <path>]\n --print-skills Print skills (builtin + user + project)\n --cwd <path> Project root for .zelari/skills\n --set-skill Add/update a SKILL.md skill\n --name <id> Skill id (required)\n --description <t> One-line description (required)\n --body <text> Markdown instructions (required)\n --category <c> plan|refactor|debug|review|test|docs|ops|git|db|maint\n --tools <csv> Comma-separated required tools (optional)\n --cost <l> low|medium|high (default: medium)\n --scope user|project Default: user\n --cwd <path> Required when scope=project\n --remove-skill Remove a user/project SKILL.md\n --name <id> --scope user|project [--cwd <path>]\n --generate-skill-from-url Fetch URL + draft skill via model (JSON)\n --url <https://...> Required\n --provider <id> Override active provider\n --model <name> Override model for the selected provider\n --print-ssh-targets Print SSH deploy/monitor targets\n --set-ssh-target Upsert target (--json '{...}' or flags)\n --remove-ssh-target --id <id>\n --test-ssh-target --id <id> (BatchMode ssh true)\n --print-ssh-pubkey --path <private-or-.pub> (display public key)\n\nEnvironment:\n ZELARI_NO_WIZARD=1 Skip the first-run wizard\n ZELARI_SKIP_PREFLIGHT=1 Skip the boot prerequisite check\n ZELARI_NO_PLUGIN_PROMPT=1 Skip the boot plugin-install prompt\n ZELARI_MEMORY_MCP=1 Enable the optional external memory MCP server\n ANATHEMA_DEV=1 Disable background update check + preflight\n"
|
|
85139
|
+
"zelari-code \u2014 AI Council coding agent CLI.\n\nUsage: zelari-code [options]\n\nOptions:\n --version, -v Print version and exit\n --help, -h Print this help and exit\n --doctor [--json] Diagnose install health (shim, bundle, PATH, deps,\n node/git/bash in the agent shell)\n --inspect [--json] Unified project inspection (config, skills, MCP,\n hooks, plugins, AGENTS.md, trust status)\n --trust [path] Trust the cwd (or path) so project MCP + hooks load\n --fix-path Add the npm global prefix to the user PATH\n (Windows only; fixes 'command not found' after install)\n --fix-budget Set recommended ZELARI_MAX_TOOL_LOOP_HARD=180,\n ZELARI_MAX_TOOL_LOOP_ITERATIONS=60, ZELARI_CONTEXT_LIMIT=400000\n at User scope (prevents the agent stopping mid-task)\n --permission-mcp <socket> MCP stdio server for external agent permission prompts\n (spawned by claude --permission-prompt-tool)\n --memory-mcp Optional MCP stdio server for project memory\n --cwd <path> Trusted project root (requires ZELARI_MEMORY_MCP=1)\n --client-id <id> Stable local owner identity for private memories\n --memory-json <json> Read-only project-memory bridge for Zelari Desktop\n --skip-checks Skip the boot-time prerequisite check\n (alias for ZELARI_SKIP_PREFLIGHT=1)\n --no-wizard Skip the first-run wizard\n --reset-config Re-run the wizard (clears provider.json on commit)\n --headless Run a single task without mounting the TUI\n --task <text> Task prompt (required in headless mode)\n --output json|plain Output format (default: json)\n --mode kraken|council|zelari Dispatch mode (default: kraken; agent=alias)\n zelari/mission mode auto-scopes slices from open tasks in .zelari/plan.json\n --council Alias for --mode council\n --phase plan|build Work phase (default: build)\n --provider <id> Provider override (default: active)\n --model <id> Model override (default: provider default)\n --profile <id> Capability profile (minimal/v1|kraken/v1|council/v1|mission/v1)\n --resume <id> Continue a 2.0 spine session\n --resume-mission Resume .zelari/mission-state.json (not the spine)\n --export-session <path> Write zelari-session-export/1 after the run\n --strict-done Evidence-based BUILD completion gate\n --allow-unverified Exit 0 when strict is ON but nothing could be verified (M1.2)\n --task-file <path> Read the task prompt from a file (Windows argv cap)\n --once Single-cycle run (cron/git-hook triggers, ADR-0014)\n --kraken-graph <goal> Plan + execute a Kraken task graph\n (variant: --kraken-graph-file <path>; kill-switch\n ZELARI_KRAKEN_GRAPH=0)\n --plan-only Serialize the graph plan to .zelari/radio/ and exit 0\n --run-plan <id> Execute a pre-built .zelari/radio/plan-<id>.json\n --gauntlet Host-driven gauntlet loop (builder/critic tentacles)\n --session-export <id> Print a portable 2.0 session export (no LLM)\n serve Companion host for Android/remote clients (Tailscale)\n --bind <ip> Listen address (default: 127.0.0.1; use Tailscale IP)\n --port <n> Port (default: 7421)\n --token <secret> Bearer token (default: ~/.zelari-code/companion.token)\n --project <path> Allowlisted project root (repeatable)\n --save-projects Persist --project list to companion.json\n --serve-harness Long-lived harness kernel for hosts (NDJSON JSON-RPC\n on stdin/stdout; Desktop/companion transport)\n --print-config Print provider/model config as JSON (no secrets)\n --print-settings Print zelari.config.json values + the origin of\n each (default < user < project < env)\n --permissions <p> Permission preset: strict | standard | yolo \u2014 changes\n category DEFAULTS only (env vars and policy files win)\n --evolve-status Evolution ledger stats (read-only; ADR-0036; the\n ledger is written only when ZELARI_EVOLUTION=shadow)\n --plugins-status JSON status of optional plugins (Playwright, eslint, \u2026)\n --plugins-install <id> Install plugin (playwright also fetches Chromium)\n --cwd <path> Workspace for -D installs (default: process.cwd())\n --set-config Persist provider/model/endpoint\n --provider <id> Set active provider\n --model <id> Set model for that provider\n --endpoint <url> Custom OpenAI-compatible base URL\n --endpoint-clear Remove custom endpoint override\n --thinking <spec> Thinking effort (auto|off|low|medium|high|budget:N)\n --set-key Store an API key (never printed back)\n --provider <id> Provider id (required)\n --key <secret> API key (required)\n --login-oauth Start subscription OAuth (grok, chatgpt, anthropic)\n --provider <id> grok | chatgpt | anthropic\n --code <paste> Anthropic magic-link code (CODE#STATE)\n --no-browser Do not open the system browser\n --refresh-oauth Force-refresh an OAuth access token\n --provider <id> grok | chatgpt | anthropic\n --logout-oauth Clear stored OAuth credentials\n --provider <id> grok | chatgpt | anthropic\n --discover-models Refresh model list for a provider\n --provider <id> Provider (default: active)\n --print-mcp Print MCP server config (user + project)\n --cwd <path> Project root for .zelari/mcp.json\n --set-mcp Add/update an MCP server entry\n --name <id> Server name (required)\n --command <bin> Executable for stdio servers\n --url <endpoint> Streamable HTTP endpoint (e.g. UE 5.8 editor)\n --args <json> JSON array of args (stdio, optional)\n --timeout <ms> Per-server request timeout (http, optional)\n --scope user|project Default: user\n --enabled true|false Default: true\n --cwd <path> Required when scope=project\n --set-mcp-preset Install a named MCP preset (e.g. cua)\n --preset cua Cua Driver desktop computer-use (MCP)\n --preset unreal-mcp Unreal Engine 5.8+ editor (MCP over HTTP)\n --scope user|project Default: user\n --cwd <path> Required when scope=project\n --remove-mcp Remove an MCP server entry\n --name <id> --scope user|project [--cwd <path>]\n --print-skills Print skills (builtin + user + project)\n --cwd <path> Project root for .zelari/skills\n --set-skill Add/update a SKILL.md skill\n --name <id> Skill id (required)\n --description <t> One-line description (required)\n --body <text> Markdown instructions (required)\n --category <c> plan|refactor|debug|review|test|docs|ops|git|db|maint\n --tools <csv> Comma-separated required tools (optional)\n --cost <l> low|medium|high (default: medium)\n --scope user|project Default: user\n --cwd <path> Required when scope=project\n --remove-skill Remove a user/project SKILL.md\n --name <id> --scope user|project [--cwd <path>]\n --generate-skill-from-url Fetch URL + draft skill via model (JSON)\n --url <https://...> Required\n --provider <id> Override active provider\n --model <name> Override model for the selected provider\n --print-ssh-targets Print SSH deploy/monitor targets\n --set-ssh-target Upsert target (--json '{...}' or flags)\n --remove-ssh-target --id <id>\n --test-ssh-target --id <id> (BatchMode ssh true)\n --print-ssh-pubkey --path <private-or-.pub> (display public key)\n\nEnvironment:\n ZELARI_NO_WIZARD=1 Skip the first-run wizard\n ZELARI_SKIP_PREFLIGHT=1 Skip the boot prerequisite check\n ZELARI_NO_PLUGIN_PROMPT=1 Skip the boot plugin-install prompt\n ZELARI_MEMORY_MCP=1 Enable the optional external memory MCP server\n ANATHEMA_DEV=1 Disable background update check + preflight\n"
|
|
84737
85140
|
);
|
|
84738
85141
|
process.exit(0);
|
|
84739
85142
|
}
|