zelari-code 2.40.0 → 2.41.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/headless/runOneTurn.js +28 -4
- package/dist/cli/headless/runOneTurn.js.map +1 -1
- package/dist/cli/hooks/useChatTurn.js +12 -1
- package/dist/cli/hooks/useChatTurn.js.map +1 -1
- package/dist/cli/main.bundled.js +919 -516
- package/dist/cli/main.bundled.js.map +4 -4
- package/dist/cli/memory/howWeTest.js +196 -0
- package/dist/cli/memory/howWeTest.js.map +1 -0
- package/dist/cli/memory/opsKnowledge.js +18 -1
- package/dist/cli/memory/opsKnowledge.js.map +1 -1
- package/dist/cli/memory/promotion.js +57 -0
- package/dist/cli/memory/promotion.js.map +1 -1
- package/dist/cli/memory/repeatCheck.js +129 -0
- package/dist/cli/memory/repeatCheck.js.map +1 -0
- package/dist/cli/slashHandlers/memory.js +47 -3
- package/dist/cli/slashHandlers/memory.js.map +1 -1
- package/dist/cli/workspace/worldModel.js +61 -0
- package/dist/cli/workspace/worldModel.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, path103) {
|
|
3486
|
+
if (!path103)
|
|
3487
3487
|
return obj;
|
|
3488
|
-
return
|
|
3488
|
+
return path103.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(path103, 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(path103);
|
|
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, path103 = []) => {
|
|
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 }, [...path103, ...issue2.path]));
|
|
4042
4042
|
} else if (issue2.code === "invalid_key") {
|
|
4043
|
-
processError({ issues: issue2.issues }, [...
|
|
4043
|
+
processError({ issues: issue2.issues }, [...path103, ...issue2.path]);
|
|
4044
4044
|
} else if (issue2.code === "invalid_element") {
|
|
4045
|
-
processError({ issues: issue2.issues }, [...
|
|
4045
|
+
processError({ issues: issue2.issues }, [...path103, ...issue2.path]);
|
|
4046
4046
|
} else {
|
|
4047
|
-
const fullpath = [...
|
|
4047
|
+
const fullpath = [...path103, ...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, path103 = []) => {
|
|
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 }, [...path103, ...issue2.path]));
|
|
4079
4079
|
} else if (issue2.code === "invalid_key") {
|
|
4080
|
-
processError({ issues: issue2.issues }, [...
|
|
4080
|
+
processError({ issues: issue2.issues }, [...path103, ...issue2.path]);
|
|
4081
4081
|
} else if (issue2.code === "invalid_element") {
|
|
4082
|
-
processError({ issues: issue2.issues }, [...
|
|
4082
|
+
processError({ issues: issue2.issues }, [...path103, ...issue2.path]);
|
|
4083
4083
|
} else {
|
|
4084
|
-
const fullpath = [...
|
|
4084
|
+
const fullpath = [...path103, ...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 path103 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
4117
|
+
for (const seg of path103) {
|
|
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 path103 = ref.slice(1).split("/").filter(Boolean);
|
|
17621
|
+
if (path103.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 (path103[0] === defsKey) {
|
|
17626
|
+
const key = path103[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(path103, snapshotId) {
|
|
18461
|
+
return { kind: "file.read", actor: { type: "tool" }, data: { path: path103, snapshotId } };
|
|
18462
18462
|
}
|
|
18463
|
-
function fileAppliedEvent(
|
|
18464
|
-
return { kind: "file.applied", actor: { type: "tool" }, data: { path:
|
|
18463
|
+
function fileAppliedEvent(path103, snapshotId, bytes) {
|
|
18464
|
+
return { kind: "file.applied", actor: { type: "tool" }, data: { path: path103, snapshotId, bytes } };
|
|
18465
18465
|
}
|
|
18466
|
-
function fileRejectedEvent(
|
|
18466
|
+
function fileRejectedEvent(path103, 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: path103, reason } : { path: path103, 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 path103 = 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: path103,
|
|
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 "${path103}".`;
|
|
20353
20353
|
}
|
|
20354
20354
|
}
|
|
20355
20355
|
];
|
|
@@ -23878,7 +23878,7 @@ async function createExecutionContext(options = {}) {
|
|
|
23878
23878
|
workspaceKind: workspace.kind
|
|
23879
23879
|
}
|
|
23880
23880
|
});
|
|
23881
|
-
const
|
|
23881
|
+
const fs50 = options.fs ?? new NodeFsProvider(workspace);
|
|
23882
23882
|
const shell = options.shell ?? new NodeShellProvider(workspace);
|
|
23883
23883
|
const subagent = options.subagent ?? NOOP_SUBAGENT_PROVIDER;
|
|
23884
23884
|
const env = options.env ?? process.env;
|
|
@@ -23886,7 +23886,7 @@ async function createExecutionContext(options = {}) {
|
|
|
23886
23886
|
sessionId: sessionId2,
|
|
23887
23887
|
profile,
|
|
23888
23888
|
workspace,
|
|
23889
|
-
fs:
|
|
23889
|
+
fs: fs50,
|
|
23890
23890
|
shell,
|
|
23891
23891
|
subagent,
|
|
23892
23892
|
appendSessionEvent: (input) => writer.append(input),
|
|
@@ -25287,16 +25287,16 @@ function runRetentionFromEnv() {
|
|
|
25287
25287
|
maxTotalBytes: Number.isFinite(parseMb) && parseMb > 0 ? Math.round(parseMb * 1024 * 1024) : DEFAULT_RUN_RETENTION_MAX_MB * 1024 * 1024
|
|
25288
25288
|
};
|
|
25289
25289
|
}
|
|
25290
|
-
async function dirSize(
|
|
25290
|
+
async function dirSize(path103) {
|
|
25291
25291
|
let total = 0;
|
|
25292
25292
|
let entries;
|
|
25293
25293
|
try {
|
|
25294
|
-
entries = await readdir(
|
|
25294
|
+
entries = await readdir(path103, { withFileTypes: true });
|
|
25295
25295
|
} catch {
|
|
25296
25296
|
return 0;
|
|
25297
25297
|
}
|
|
25298
25298
|
for (const entry of entries) {
|
|
25299
|
-
const child = join3(
|
|
25299
|
+
const child = join3(path103, entry.name);
|
|
25300
25300
|
if (entry.isDirectory())
|
|
25301
25301
|
total += await dirSize(child);
|
|
25302
25302
|
else {
|
|
@@ -25323,19 +25323,19 @@ async function enforceRunRetention(runsDir, options = {}) {
|
|
|
25323
25323
|
for (const entry of entries) {
|
|
25324
25324
|
if (!entry.isDirectory())
|
|
25325
25325
|
continue;
|
|
25326
|
-
const
|
|
25326
|
+
const path103 = join3(runsDir, entry.name);
|
|
25327
25327
|
let startedAt = 0;
|
|
25328
25328
|
let endedAt;
|
|
25329
25329
|
let completed = false;
|
|
25330
25330
|
try {
|
|
25331
|
-
const manifest = JSON.parse(await readFile(join3(
|
|
25331
|
+
const manifest = JSON.parse(await readFile(join3(path103, "manifest.json"), "utf8"));
|
|
25332
25332
|
startedAt = manifest.startedAt ?? 0;
|
|
25333
25333
|
endedAt = manifest.endedAt;
|
|
25334
25334
|
completed = Boolean(endedAt) && manifest.status !== "running";
|
|
25335
25335
|
} catch {
|
|
25336
25336
|
completed = false;
|
|
25337
25337
|
}
|
|
25338
|
-
infos.push({ name: entry.name, path:
|
|
25338
|
+
infos.push({ name: entry.name, path: path103, startedAt, endedAt, completed, bytes: await dirSize(path103) });
|
|
25339
25339
|
}
|
|
25340
25340
|
const remove = async (info) => {
|
|
25341
25341
|
await rm(info.path, { recursive: true, force: true });
|
|
@@ -25893,12 +25893,12 @@ var init_engine = __esm({
|
|
|
25893
25893
|
* content digest) and the returned ref carries the event seq when the
|
|
25894
25894
|
* emitter resolved one.
|
|
25895
25895
|
*/
|
|
25896
|
-
async fsEvidence(observation,
|
|
25896
|
+
async fsEvidence(observation, path103, sha2562, content, extra = {}) {
|
|
25897
25897
|
const digest = sha2562 && content !== void 0 ? sha2562(content) : void 0;
|
|
25898
|
-
const seq = await this.emitEvidence({ observation, path:
|
|
25898
|
+
const seq = await this.emitEvidence({ observation, path: path103, ...extra, ...digest ? { digest } : {} });
|
|
25899
25899
|
return {
|
|
25900
25900
|
tier: "fs-observation",
|
|
25901
|
-
ref:
|
|
25901
|
+
ref: path103,
|
|
25902
25902
|
capturedAt: Date.now(),
|
|
25903
25903
|
...digest ? { digest } : {},
|
|
25904
25904
|
...seq !== void 0 ? { seq } : {}
|
|
@@ -25906,25 +25906,25 @@ var init_engine = __esm({
|
|
|
25906
25906
|
}
|
|
25907
25907
|
async evalFileExists(check2, done) {
|
|
25908
25908
|
const sha2562 = this.options.sha256 ?? defaultSha256;
|
|
25909
|
-
const
|
|
25910
|
-
if (!
|
|
25909
|
+
const fs50 = this.services.fs;
|
|
25910
|
+
if (!fs50)
|
|
25911
25911
|
return done({ status: "unknown", evidence: [], detail: "fs provider unavailable" });
|
|
25912
|
-
const exists = await
|
|
25912
|
+
const exists = await fs50.exists(check2.path);
|
|
25913
25913
|
if (!exists) {
|
|
25914
25914
|
await this.emitEvidence({ observation: "file-exists", path: check2.path, exists: false });
|
|
25915
25915
|
return done({ status: "fail", evidence: [], detail: `file not found: ${check2.path}` });
|
|
25916
25916
|
}
|
|
25917
|
-
const content = await
|
|
25917
|
+
const content = await fs50.readFile(check2.path).catch(() => "");
|
|
25918
25918
|
return done({
|
|
25919
25919
|
status: "pass",
|
|
25920
25920
|
evidence: [await this.fsEvidence("file-exists", check2.path, sha2562, content, { exists: true })]
|
|
25921
25921
|
});
|
|
25922
25922
|
}
|
|
25923
25923
|
async evalFileAbsent(check2, done) {
|
|
25924
|
-
const
|
|
25925
|
-
if (!
|
|
25924
|
+
const fs50 = this.services.fs;
|
|
25925
|
+
if (!fs50)
|
|
25926
25926
|
return done({ status: "unknown", evidence: [], detail: "fs provider unavailable" });
|
|
25927
|
-
const exists = await
|
|
25927
|
+
const exists = await fs50.exists(check2.path);
|
|
25928
25928
|
if (exists) {
|
|
25929
25929
|
await this.emitEvidence({ observation: "file-absent", path: check2.path, exists: true });
|
|
25930
25930
|
return done({ status: "fail", evidence: [], detail: `file still present: ${check2.path}` });
|
|
@@ -25936,12 +25936,12 @@ var init_engine = __esm({
|
|
|
25936
25936
|
}
|
|
25937
25937
|
async evalFileContains(check2, done) {
|
|
25938
25938
|
const sha2562 = this.options.sha256 ?? defaultSha256;
|
|
25939
|
-
const
|
|
25940
|
-
if (!
|
|
25939
|
+
const fs50 = this.services.fs;
|
|
25940
|
+
if (!fs50)
|
|
25941
25941
|
return done({ status: "unknown", evidence: [], detail: "fs provider unavailable" });
|
|
25942
25942
|
let content;
|
|
25943
25943
|
try {
|
|
25944
|
-
content = await
|
|
25944
|
+
content = await fs50.readFile(check2.path);
|
|
25945
25945
|
} catch {
|
|
25946
25946
|
await this.emitEvidence({ observation: "file-contains", path: check2.path, readable: false });
|
|
25947
25947
|
return done({ status: "fail", evidence: [], detail: `file not readable: ${check2.path}` });
|
|
@@ -32107,11 +32107,11 @@ var init_synthesisAudit = __esm({
|
|
|
32107
32107
|
import { existsSync as existsSync10, readFileSync as readFileSync9, writeFileSync as writeFileSync6 } from "node:fs";
|
|
32108
32108
|
import { join as join5 } from "node:path";
|
|
32109
32109
|
function loadNfrSpec(zelariRoot) {
|
|
32110
|
-
const
|
|
32111
|
-
if (!existsSync10(
|
|
32110
|
+
const path103 = join5(zelariRoot, "nfr-spec.json");
|
|
32111
|
+
if (!existsSync10(path103))
|
|
32112
32112
|
return null;
|
|
32113
32113
|
try {
|
|
32114
|
-
const raw = JSON.parse(readFileSync9(
|
|
32114
|
+
const raw = JSON.parse(readFileSync9(path103, "utf8"));
|
|
32115
32115
|
if (raw.version !== 1 || !Array.isArray(raw.targets))
|
|
32116
32116
|
return null;
|
|
32117
32117
|
return raw;
|
|
@@ -34512,9 +34512,9 @@ var init_types9 = __esm({
|
|
|
34512
34512
|
import { readFileSync as readFileSync14 } from "node:fs";
|
|
34513
34513
|
import { join as join11 } from "node:path";
|
|
34514
34514
|
function readLessonsDeduped(zelariRoot) {
|
|
34515
|
-
const
|
|
34515
|
+
const path103 = join11(zelariRoot, LESSONS_FILE);
|
|
34516
34516
|
try {
|
|
34517
|
-
const raw = readFileSync14(
|
|
34517
|
+
const raw = readFileSync14(path103, "utf8");
|
|
34518
34518
|
const byId = /* @__PURE__ */ new Map();
|
|
34519
34519
|
for (const line of raw.split(/\r?\n/)) {
|
|
34520
34520
|
if (!line.trim())
|
|
@@ -34615,8 +34615,8 @@ function keywordsFrom(check2, signature) {
|
|
|
34615
34615
|
return [.../* @__PURE__ */ new Set([...fromId, ...words])].slice(0, 12);
|
|
34616
34616
|
}
|
|
34617
34617
|
function writeLesson(zelariRoot, lesson) {
|
|
34618
|
-
const
|
|
34619
|
-
appendFileSync(
|
|
34618
|
+
const path103 = join12(zelariRoot, LESSONS_FILE);
|
|
34619
|
+
appendFileSync(path103, `${JSON.stringify(lesson)}
|
|
34620
34620
|
`, "utf8");
|
|
34621
34621
|
}
|
|
34622
34622
|
function findSimilar(lessons, signature) {
|
|
@@ -36584,9 +36584,9 @@ function findCycle(nodes) {
|
|
|
36584
36584
|
if (color.get(start) !== WHITE)
|
|
36585
36585
|
continue;
|
|
36586
36586
|
const stack = [[start, 0]];
|
|
36587
|
-
const
|
|
36587
|
+
const path103 = [];
|
|
36588
36588
|
color.set(start, GRAY);
|
|
36589
|
-
|
|
36589
|
+
path103.push(start);
|
|
36590
36590
|
while (stack.length > 0) {
|
|
36591
36591
|
const top = stack[stack.length - 1];
|
|
36592
36592
|
const [id3, idx] = top;
|
|
@@ -36599,17 +36599,17 @@ function findCycle(nodes) {
|
|
|
36599
36599
|
continue;
|
|
36600
36600
|
const c = color.get(dep);
|
|
36601
36601
|
if (c === GRAY) {
|
|
36602
|
-
const at =
|
|
36603
|
-
return [...
|
|
36602
|
+
const at = path103.indexOf(dep);
|
|
36603
|
+
return [...path103.slice(at), dep];
|
|
36604
36604
|
}
|
|
36605
36605
|
if (c === WHITE) {
|
|
36606
36606
|
color.set(dep, GRAY);
|
|
36607
|
-
|
|
36607
|
+
path103.push(dep);
|
|
36608
36608
|
stack.push([dep, 0]);
|
|
36609
36609
|
}
|
|
36610
36610
|
} else {
|
|
36611
36611
|
color.set(id3, BLACK);
|
|
36612
|
-
|
|
36612
|
+
path103.pop();
|
|
36613
36613
|
stack.pop();
|
|
36614
36614
|
}
|
|
36615
36615
|
}
|
|
@@ -37529,8 +37529,8 @@ var init_runner = __esm({
|
|
|
37529
37529
|
failed: [...this.tentaclesById.values()].filter((r) => r.status === "error"),
|
|
37530
37530
|
pending: []
|
|
37531
37531
|
};
|
|
37532
|
-
const
|
|
37533
|
-
this.host.log(`checkpoint: ${label ?? "auto"} \u2192 ${
|
|
37532
|
+
const path103 = await this.host.saveSnapshot(snapshot, ".zelari/kraken/snapshots");
|
|
37533
|
+
this.host.log(`checkpoint: ${label ?? "auto"} \u2192 ${path103}`);
|
|
37534
37534
|
return snapshot;
|
|
37535
37535
|
}
|
|
37536
37536
|
callLog(msg, data) {
|
|
@@ -38826,7 +38826,7 @@ var CORE_VERSION;
|
|
|
38826
38826
|
var init_version = __esm({
|
|
38827
38827
|
"packages/core/dist/version.js"() {
|
|
38828
38828
|
"use strict";
|
|
38829
|
-
CORE_VERSION = "2.
|
|
38829
|
+
CORE_VERSION = "2.41.0";
|
|
38830
38830
|
}
|
|
38831
38831
|
});
|
|
38832
38832
|
|
|
@@ -41308,9 +41308,9 @@ function spillToolOutput(fullText, meta3) {
|
|
|
41308
41308
|
const rnd = randomBytes3(3).toString("hex");
|
|
41309
41309
|
const safeTool = (meta3?.toolName ?? "tool").replace(/[^a-zA-Z0-9._-]+/g, "_").slice(0, 32);
|
|
41310
41310
|
const file2 = `${stamp}-${safeTool}-${hash3}-${rnd}.txt`;
|
|
41311
|
-
const
|
|
41312
|
-
writeFileSync12(
|
|
41313
|
-
return
|
|
41311
|
+
const path103 = join14(dir, file2);
|
|
41312
|
+
writeFileSync12(path103, fullText, "utf8");
|
|
41313
|
+
return path103;
|
|
41314
41314
|
} catch {
|
|
41315
41315
|
return null;
|
|
41316
41316
|
}
|
|
@@ -41356,10 +41356,10 @@ function truncateToolResult(text, capOrOpts = TOOL_RESULT_LINE_CAP) {
|
|
|
41356
41356
|
${tail2}`;
|
|
41357
41357
|
}
|
|
41358
41358
|
if (doSpill) {
|
|
41359
|
-
const
|
|
41360
|
-
if (
|
|
41359
|
+
const path103 = spillToolOutput(text, { toolName: opts.toolName });
|
|
41360
|
+
if (path103) {
|
|
41361
41361
|
const spillNote = `
|
|
41362
|
-
\u2026 [full output spilled to: ${
|
|
41362
|
+
\u2026 [full output spilled to: ${path103} \u2014 re-read with read_file if you need the complete text] \u2026`;
|
|
41363
41363
|
if (preview.includes("] \u2026\n")) {
|
|
41364
41364
|
preview = preview.replace("] \u2026\n", `] \u2026${spillNote}
|
|
41365
41365
|
`);
|
|
@@ -42162,28 +42162,28 @@ var init_storage = __esm({
|
|
|
42162
42162
|
VALID_SCALARS = /^(true|false|null|~)$/i;
|
|
42163
42163
|
Storage = class {
|
|
42164
42164
|
/** Read a Markdown file with frontmatter. Throws if not found. */
|
|
42165
|
-
read(
|
|
42166
|
-
if (!existsSync19(
|
|
42167
|
-
throw new Error(`File not found: ${
|
|
42165
|
+
read(path103) {
|
|
42166
|
+
if (!existsSync19(path103)) {
|
|
42167
|
+
throw new Error(`File not found: ${path103}`);
|
|
42168
42168
|
}
|
|
42169
|
-
const md = readFileSync17(
|
|
42169
|
+
const md = readFileSync17(path103, "utf8");
|
|
42170
42170
|
return parseFrontmatter(md);
|
|
42171
42171
|
}
|
|
42172
42172
|
/** Read a Markdown file; returns null if not found. */
|
|
42173
|
-
readIfExists(
|
|
42174
|
-
if (!existsSync19(
|
|
42175
|
-
return this.read(
|
|
42173
|
+
readIfExists(path103) {
|
|
42174
|
+
if (!existsSync19(path103)) return null;
|
|
42175
|
+
return this.read(path103);
|
|
42176
42176
|
}
|
|
42177
42177
|
/**
|
|
42178
42178
|
* Write a Markdown file atomically (tmp + rename). Creates parent dirs.
|
|
42179
42179
|
* The meta object is serialized as YAML frontmatter; body as Markdown.
|
|
42180
42180
|
*/
|
|
42181
|
-
write(
|
|
42182
|
-
mkdirSync10(dirname2(
|
|
42183
|
-
const tmp =
|
|
42181
|
+
write(path103, meta3, body) {
|
|
42182
|
+
mkdirSync10(dirname2(path103), { recursive: true });
|
|
42183
|
+
const tmp = path103 + ".tmp-" + process.pid;
|
|
42184
42184
|
const md = serializeFrontmatter(meta3, body);
|
|
42185
42185
|
writeFileSync14(tmp, md, "utf8");
|
|
42186
|
-
renameSync2(tmp,
|
|
42186
|
+
renameSync2(tmp, path103);
|
|
42187
42187
|
}
|
|
42188
42188
|
/** List all .md files in a directory (non-recursive). */
|
|
42189
42189
|
listMarkdown(dir) {
|
|
@@ -42294,8 +42294,8 @@ function nextPlanTaskId(store6) {
|
|
|
42294
42294
|
return `t${store6.counter}`;
|
|
42295
42295
|
}
|
|
42296
42296
|
function writePlanTaskArtifact(rootDir, task) {
|
|
42297
|
-
const
|
|
42298
|
-
mkdirSync11(dirname3(
|
|
42297
|
+
const path103 = join17(rootDir, "plan-tasks", `${task.id}.md`);
|
|
42298
|
+
mkdirSync11(dirname3(path103), { recursive: true });
|
|
42299
42299
|
const meta3 = {
|
|
42300
42300
|
kind: "task",
|
|
42301
42301
|
id: task.id,
|
|
@@ -42316,7 +42316,7 @@ function writePlanTaskArtifact(rootDir, task) {
|
|
|
42316
42316
|
task.notes?.trim() ? task.notes.trim() : "_(no notes)_",
|
|
42317
42317
|
""
|
|
42318
42318
|
].filter((l) => l !== null).join("\n");
|
|
42319
|
-
new Storage().write(
|
|
42319
|
+
new Storage().write(path103, meta3, body);
|
|
42320
42320
|
}
|
|
42321
42321
|
function loadHandle(rootDir) {
|
|
42322
42322
|
const jsonPath = join17(rootDir, "plan.json");
|
|
@@ -43721,6 +43721,46 @@ function formatPromoteNotice(node) {
|
|
|
43721
43721
|
const preview = node.content.replace(/\s+/g, " ").trim().slice(0, 120);
|
|
43722
43722
|
return `[memory] candidato AGENTS.MD: ${node.kind} \u201C${preview}\u201D \u2014 /memory promote ${node.id}`;
|
|
43723
43723
|
}
|
|
43724
|
+
function parsePromoteArgs(args = []) {
|
|
43725
|
+
const result = { asCheck: false };
|
|
43726
|
+
const tokens = [...args];
|
|
43727
|
+
for (let i = 0; i < tokens.length; i += 1) {
|
|
43728
|
+
const token = tokens[i] ?? "";
|
|
43729
|
+
const inline = token.startsWith("--") && token.includes("=") ? token.split("=") : null;
|
|
43730
|
+
const flag = inline ? inline[0] ?? "" : token;
|
|
43731
|
+
const inlineValue = inline ? inline.slice(1).join("=") : void 0;
|
|
43732
|
+
if (flag === "--as-check") {
|
|
43733
|
+
result.asCheck = true;
|
|
43734
|
+
continue;
|
|
43735
|
+
}
|
|
43736
|
+
if (COMMAND_FLAGS.has(flag) || EXIT_FLAGS.has(flag)) {
|
|
43737
|
+
const parts = [];
|
|
43738
|
+
if (inlineValue !== void 0 && inlineValue !== "") parts.push(inlineValue);
|
|
43739
|
+
else {
|
|
43740
|
+
while (i + 1 < tokens.length && !(tokens[i + 1] ?? "").startsWith("-")) {
|
|
43741
|
+
parts.push(tokens[i + 1] ?? "");
|
|
43742
|
+
i += 1;
|
|
43743
|
+
}
|
|
43744
|
+
}
|
|
43745
|
+
const value = parts.join(" ").replace(/^\s*["']|["']\s*$/g, "").trim();
|
|
43746
|
+
if (EXIT_FLAGS.has(flag)) {
|
|
43747
|
+
const exit = Number(value);
|
|
43748
|
+
if (!value || !Number.isInteger(exit)) {
|
|
43749
|
+
return { ...result, error: `expect-exit must be an integer, got \u201C${value}\u201D.` };
|
|
43750
|
+
}
|
|
43751
|
+
result.expectExit = exit;
|
|
43752
|
+
continue;
|
|
43753
|
+
}
|
|
43754
|
+
if (!value) return { ...result, error: "missing value for --command." };
|
|
43755
|
+
result.command = value;
|
|
43756
|
+
continue;
|
|
43757
|
+
}
|
|
43758
|
+
if (token.startsWith("-")) return { ...result, error: `unknown flag \u201C${token}\u201D.` };
|
|
43759
|
+
if (!result.id) result.id = token;
|
|
43760
|
+
else if (!result.command) return { ...result, error: `unexpected argument \u201C${token}\u201D.` };
|
|
43761
|
+
}
|
|
43762
|
+
return result;
|
|
43763
|
+
}
|
|
43724
43764
|
function lineFor(node) {
|
|
43725
43765
|
const content = node.content.replace(/\s+/g, " ").replace(/-->/g, "\u2014>").trim().slice(0, 2e3);
|
|
43726
43766
|
const provenance = node.source.agent ? `; source=${node.source.agent}` : "";
|
|
@@ -43778,7 +43818,7 @@ ${END}
|
|
|
43778
43818
|
}
|
|
43779
43819
|
return { added: true, path: target };
|
|
43780
43820
|
}
|
|
43781
|
-
var START, END, DURABLE_KINDS, PROMOTE_MIN_IMPORTANCE, PROMOTE_MIN_CONFIDENCE;
|
|
43821
|
+
var START, END, DURABLE_KINDS, PROMOTE_MIN_IMPORTANCE, PROMOTE_MIN_CONFIDENCE, PROMOTE_USAGE, COMMAND_FLAGS, EXIT_FLAGS;
|
|
43782
43822
|
var init_promotion = __esm({
|
|
43783
43823
|
"src/cli/memory/promotion.ts"() {
|
|
43784
43824
|
"use strict";
|
|
@@ -43787,6 +43827,9 @@ var init_promotion = __esm({
|
|
|
43787
43827
|
DURABLE_KINDS = /* @__PURE__ */ new Set(["fact", "decision", "constraint", "preference", "procedure"]);
|
|
43788
43828
|
PROMOTE_MIN_IMPORTANCE = 0.7;
|
|
43789
43829
|
PROMOTE_MIN_CONFIDENCE = 0.8;
|
|
43830
|
+
PROMOTE_USAGE = 'Usage: /memory promote <id> [--as-check --command "<comando>" [--expect-exit N]]';
|
|
43831
|
+
COMMAND_FLAGS = /* @__PURE__ */ new Set(["--command", "-c"]);
|
|
43832
|
+
EXIT_FLAGS = /* @__PURE__ */ new Set(["--expect-exit", "-e", "--expectExit"]);
|
|
43790
43833
|
}
|
|
43791
43834
|
});
|
|
43792
43835
|
|
|
@@ -44133,6 +44176,48 @@ async function runBacktest(cwd, signal) {
|
|
|
44133
44176
|
await appendTimeline(cwd, { kind: "backtest", ok: summary.ok, passed, failed, total: results.length });
|
|
44134
44177
|
return summary;
|
|
44135
44178
|
}
|
|
44179
|
+
async function readChecksStrict(cwd) {
|
|
44180
|
+
const p3 = path44.join(worldDir(cwd), CHECKS_FILE);
|
|
44181
|
+
let raw;
|
|
44182
|
+
try {
|
|
44183
|
+
raw = await fs19.readFile(p3, "utf8");
|
|
44184
|
+
} catch (error51) {
|
|
44185
|
+
if (error51.code === "ENOENT") return [];
|
|
44186
|
+
throw error51;
|
|
44187
|
+
}
|
|
44188
|
+
let parsed;
|
|
44189
|
+
try {
|
|
44190
|
+
parsed = JSON.parse(raw);
|
|
44191
|
+
} catch {
|
|
44192
|
+
throw new Error(`${p3} is not valid JSON \u2014 refusing to overwrite it.`);
|
|
44193
|
+
}
|
|
44194
|
+
if (!parsed || !Array.isArray(parsed.checks)) {
|
|
44195
|
+
throw new Error(`${p3} has no "checks" array \u2014 refusing to overwrite it.`);
|
|
44196
|
+
}
|
|
44197
|
+
return parsed.checks;
|
|
44198
|
+
}
|
|
44199
|
+
async function appendWorldCheck(cwd, check2) {
|
|
44200
|
+
const dir = await ensureWorldDir(cwd);
|
|
44201
|
+
const file2 = path44.join(dir, CHECKS_FILE);
|
|
44202
|
+
const checks = await readChecksStrict(cwd);
|
|
44203
|
+
if (checks.some((entry) => entry?.id === check2.id)) {
|
|
44204
|
+
return { added: false, count: checks.length, path: file2, reason: "duplicate" };
|
|
44205
|
+
}
|
|
44206
|
+
const next = { checks: [...checks, check2] };
|
|
44207
|
+
const temporary = `${file2}.tmp-${process.pid}-${Date.now()}`;
|
|
44208
|
+
await fs19.writeFile(temporary, JSON.stringify(next, null, 2) + "\n", {
|
|
44209
|
+
encoding: "utf8",
|
|
44210
|
+
flag: "wx"
|
|
44211
|
+
});
|
|
44212
|
+
try {
|
|
44213
|
+
await fs19.rename(temporary, file2);
|
|
44214
|
+
} catch (error51) {
|
|
44215
|
+
await fs19.unlink(temporary).catch(() => void 0);
|
|
44216
|
+
throw error51;
|
|
44217
|
+
}
|
|
44218
|
+
await appendTimeline(cwd, { kind: "world_check_appended", id: check2.id, count: next.checks.length });
|
|
44219
|
+
return { added: true, count: next.checks.length, path: file2 };
|
|
44220
|
+
}
|
|
44136
44221
|
function createWorldModelTools() {
|
|
44137
44222
|
if (process.env["ZELARI_SCHEMA_LOOP"] === "0") return [];
|
|
44138
44223
|
return [
|
|
@@ -53356,21 +53441,21 @@ function normalizeAuth(auth) {
|
|
|
53356
53441
|
return "agent";
|
|
53357
53442
|
}
|
|
53358
53443
|
function readSecrets() {
|
|
53359
|
-
const
|
|
53360
|
-
if (!existsSync30(
|
|
53444
|
+
const path103 = getSshSecretsPath();
|
|
53445
|
+
if (!existsSync30(path103)) return {};
|
|
53361
53446
|
try {
|
|
53362
|
-
return JSON.parse(readFileSync22(
|
|
53447
|
+
return JSON.parse(readFileSync22(path103, "utf8"));
|
|
53363
53448
|
} catch {
|
|
53364
53449
|
return {};
|
|
53365
53450
|
}
|
|
53366
53451
|
}
|
|
53367
53452
|
function writeSecrets(data) {
|
|
53368
|
-
const
|
|
53369
|
-
mkdirSync13(dirname4(
|
|
53370
|
-
writeFileSync16(
|
|
53453
|
+
const path103 = getSshSecretsPath();
|
|
53454
|
+
mkdirSync13(dirname4(path103), { recursive: true });
|
|
53455
|
+
writeFileSync16(path103, `${JSON.stringify(data, null, 2)}
|
|
53371
53456
|
`, "utf8");
|
|
53372
53457
|
try {
|
|
53373
|
-
chmodSync(
|
|
53458
|
+
chmodSync(path103, 384);
|
|
53374
53459
|
} catch {
|
|
53375
53460
|
}
|
|
53376
53461
|
}
|
|
@@ -53399,10 +53484,10 @@ function deleteSshPassword(id3) {
|
|
|
53399
53484
|
writeSecrets({ passwords });
|
|
53400
53485
|
}
|
|
53401
53486
|
function readStore2() {
|
|
53402
|
-
const
|
|
53403
|
-
if (!existsSync30(
|
|
53487
|
+
const path103 = getSshTargetsPath();
|
|
53488
|
+
if (!existsSync30(path103)) return [];
|
|
53404
53489
|
try {
|
|
53405
|
-
const parsed = JSON.parse(readFileSync22(
|
|
53490
|
+
const parsed = JSON.parse(readFileSync22(path103, "utf8"));
|
|
53406
53491
|
const list = Array.isArray(parsed.targets) ? parsed.targets : [];
|
|
53407
53492
|
return list.filter(
|
|
53408
53493
|
(t) => t && typeof t.id === "string" && typeof t.host === "string" && typeof t.user === "string"
|
|
@@ -53417,11 +53502,11 @@ function readStore2() {
|
|
|
53417
53502
|
}
|
|
53418
53503
|
}
|
|
53419
53504
|
function writeStore2(targets) {
|
|
53420
|
-
const
|
|
53421
|
-
mkdirSync13(dirname4(
|
|
53505
|
+
const path103 = getSshTargetsPath();
|
|
53506
|
+
mkdirSync13(dirname4(path103), { recursive: true });
|
|
53422
53507
|
const clean = targets.map(({ hasPassword: _hp, ...t }) => t);
|
|
53423
53508
|
writeFileSync16(
|
|
53424
|
-
|
|
53509
|
+
path103,
|
|
53425
53510
|
`${JSON.stringify({ targets: clean }, null, 2)}
|
|
53426
53511
|
`,
|
|
53427
53512
|
"utf8"
|
|
@@ -53667,11 +53752,11 @@ function formatSshTargetsForPrompt() {
|
|
|
53667
53752
|
];
|
|
53668
53753
|
for (const t of targets) {
|
|
53669
53754
|
const tags = t.tags?.length ? ` tags=[${t.tags.join(",")}]` : "";
|
|
53670
|
-
const
|
|
53755
|
+
const path103 = t.defaultRemotePath ? ` remotePath=${t.defaultRemotePath}` : "";
|
|
53671
53756
|
const allow = t.allowedCommands?.length ? ` allowed=${t.allowedCommands.join("|")}` : " allowed=status-only";
|
|
53672
53757
|
const auth = t.auth === "password" ? " auth=password" : t.auth === "keyPath" ? " auth=key" : " auth=agent";
|
|
53673
53758
|
lines.push(
|
|
53674
|
-
`- id=${t.id} name=${t.name} ${t.user}@${t.host}:${t.port ?? 22}${auth}${
|
|
53759
|
+
`- id=${t.id} name=${t.name} ${t.user}@${t.host}:${t.port ?? 22}${auth}${path103}${tags}${allow}`
|
|
53675
53760
|
);
|
|
53676
53761
|
}
|
|
53677
53762
|
return lines.join("\n");
|
|
@@ -57697,6 +57782,162 @@ var init_completionProof = __esm({
|
|
|
57697
57782
|
}
|
|
57698
57783
|
});
|
|
57699
57784
|
|
|
57785
|
+
// src/cli/memory/howWeTest.ts
|
|
57786
|
+
import { promises as fs28 } from "node:fs";
|
|
57787
|
+
import * as path67 from "node:path";
|
|
57788
|
+
function metaString(node, key) {
|
|
57789
|
+
const value = node.metadata?.[key];
|
|
57790
|
+
return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
|
|
57791
|
+
}
|
|
57792
|
+
function metaNumber(node, key) {
|
|
57793
|
+
const value = node.metadata?.[key];
|
|
57794
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
57795
|
+
}
|
|
57796
|
+
function rowFromNode(node) {
|
|
57797
|
+
if (node.kind !== "procedure" || node.status !== "active") return null;
|
|
57798
|
+
if (node.metadata?.verified !== true) return null;
|
|
57799
|
+
const key = metaString(node, "opsKnowledgeKey");
|
|
57800
|
+
const command = metaString(node, "command");
|
|
57801
|
+
const digest = metaString(node, "digest");
|
|
57802
|
+
if (!key || !command || !digest) return null;
|
|
57803
|
+
const seq = metaNumber(node, "seq");
|
|
57804
|
+
return {
|
|
57805
|
+
key,
|
|
57806
|
+
criterionId: metaString(node, "criterionId") ?? "unknown",
|
|
57807
|
+
command,
|
|
57808
|
+
digest,
|
|
57809
|
+
...seq === void 0 ? {} : { seq }
|
|
57810
|
+
};
|
|
57811
|
+
}
|
|
57812
|
+
function collectHowWeTestRows(nodes) {
|
|
57813
|
+
const rows = nodes.map(rowFromNode).filter((row) => row !== null);
|
|
57814
|
+
rows.sort((a, b) => a.key.localeCompare(b.key) || (a.seq ?? -1) - (b.seq ?? -1));
|
|
57815
|
+
const byKey = /* @__PURE__ */ new Map();
|
|
57816
|
+
for (const row of rows) byKey.set(row.key, row);
|
|
57817
|
+
return [...byKey.values()].sort(
|
|
57818
|
+
(a, b) => a.criterionId.localeCompare(b.criterionId) || a.command.localeCompare(b.command)
|
|
57819
|
+
);
|
|
57820
|
+
}
|
|
57821
|
+
function shortDigest(digest) {
|
|
57822
|
+
return digest.length <= 8 ? digest : digest.slice(0, 8);
|
|
57823
|
+
}
|
|
57824
|
+
function escapeCell(value) {
|
|
57825
|
+
return value.replace(/\r?\n/g, " ").replace(/`/g, "'").trim();
|
|
57826
|
+
}
|
|
57827
|
+
function projectHowWeTest(rows) {
|
|
57828
|
+
const lines = [
|
|
57829
|
+
"# How we test",
|
|
57830
|
+
"",
|
|
57831
|
+
HOW_WE_TEST_HEADER,
|
|
57832
|
+
"",
|
|
57833
|
+
"Procedure verificate (deterministiche, evidence-backed): quello che una run",
|
|
57834
|
+
"ha dimostrato resta qui per gli agenti e per gli umani che vengono dopo.",
|
|
57835
|
+
"Generato da zelari \u2014 rigenera con `/memory how-we-test`.",
|
|
57836
|
+
""
|
|
57837
|
+
];
|
|
57838
|
+
if (rows.length === 0) {
|
|
57839
|
+
lines.push("_Nessuna procedura verificata ancora: niente da proiettare._", "");
|
|
57840
|
+
return lines.join("\n");
|
|
57841
|
+
}
|
|
57842
|
+
let current = null;
|
|
57843
|
+
for (const row of rows) {
|
|
57844
|
+
if (row.criterionId !== current) {
|
|
57845
|
+
current = row.criterionId;
|
|
57846
|
+
lines.push(`## ${current}`, "");
|
|
57847
|
+
}
|
|
57848
|
+
const seq = row.seq === void 0 ? "\u2014" : `seq ${row.seq}`;
|
|
57849
|
+
lines.push(`- \`${escapeCell(row.command)}\` \u2014 exit 0 \u2014 digest \`${shortDigest(row.digest)}\` \u2014 ultima osservazione ${seq}`);
|
|
57850
|
+
}
|
|
57851
|
+
lines.push("");
|
|
57852
|
+
return lines.join("\n");
|
|
57853
|
+
}
|
|
57854
|
+
function isMissing(error51) {
|
|
57855
|
+
return error51?.code === "ENOENT";
|
|
57856
|
+
}
|
|
57857
|
+
async function writeHowWeTest(projectRoot, rows) {
|
|
57858
|
+
const target = path67.join(projectRoot, HOW_WE_TEST_RELATIVE);
|
|
57859
|
+
try {
|
|
57860
|
+
if ((await fs28.lstat(target)).isSymbolicLink()) {
|
|
57861
|
+
return { written: false, path: target, rows: rows.length, reason: "target is a symbolic link" };
|
|
57862
|
+
}
|
|
57863
|
+
} catch (error51) {
|
|
57864
|
+
if (!isMissing(error51)) {
|
|
57865
|
+
return {
|
|
57866
|
+
written: false,
|
|
57867
|
+
path: target,
|
|
57868
|
+
rows: rows.length,
|
|
57869
|
+
reason: error51 instanceof Error ? error51.message : String(error51)
|
|
57870
|
+
};
|
|
57871
|
+
}
|
|
57872
|
+
}
|
|
57873
|
+
await fs28.mkdir(path67.dirname(target), { recursive: true });
|
|
57874
|
+
const temporary = `${target}.tmp-${process.pid}-${Date.now()}`;
|
|
57875
|
+
await fs28.writeFile(temporary, projectHowWeTest(rows), { encoding: "utf8", flag: "wx" });
|
|
57876
|
+
try {
|
|
57877
|
+
await fs28.rename(temporary, target);
|
|
57878
|
+
} catch (error51) {
|
|
57879
|
+
await fs28.unlink(temporary).catch(() => void 0);
|
|
57880
|
+
throw error51;
|
|
57881
|
+
}
|
|
57882
|
+
return { written: true, path: target, rows: rows.length };
|
|
57883
|
+
}
|
|
57884
|
+
function nodesFromDump(dump) {
|
|
57885
|
+
if (Array.isArray(dump)) return dump;
|
|
57886
|
+
const nodes = dump?.nodes;
|
|
57887
|
+
return Array.isArray(nodes) ? nodes : [];
|
|
57888
|
+
}
|
|
57889
|
+
async function listNodes(source2) {
|
|
57890
|
+
if (typeof source2.export !== "function") return null;
|
|
57891
|
+
try {
|
|
57892
|
+
return nodesFromDump(await source2.export());
|
|
57893
|
+
} catch {
|
|
57894
|
+
return null;
|
|
57895
|
+
}
|
|
57896
|
+
}
|
|
57897
|
+
async function listVerifiedProcedureNodes(source2) {
|
|
57898
|
+
const nodes = await listNodes(source2);
|
|
57899
|
+
if (!nodes) return null;
|
|
57900
|
+
return nodes.filter((node) => node.kind === "procedure" && node.metadata?.verified === true);
|
|
57901
|
+
}
|
|
57902
|
+
async function regenerateHowWeTest(source2, projectRoot) {
|
|
57903
|
+
const nodes = await listVerifiedProcedureNodes(source2);
|
|
57904
|
+
if (!nodes) {
|
|
57905
|
+
return {
|
|
57906
|
+
written: false,
|
|
57907
|
+
path: path67.join(projectRoot, HOW_WE_TEST_RELATIVE),
|
|
57908
|
+
rows: 0,
|
|
57909
|
+
reason: "memory backend cannot enumerate procedures"
|
|
57910
|
+
};
|
|
57911
|
+
}
|
|
57912
|
+
try {
|
|
57913
|
+
return await writeHowWeTest(projectRoot, collectHowWeTestRows(nodes));
|
|
57914
|
+
} catch (error51) {
|
|
57915
|
+
return {
|
|
57916
|
+
written: false,
|
|
57917
|
+
path: path67.join(projectRoot, HOW_WE_TEST_RELATIVE),
|
|
57918
|
+
rows: 0,
|
|
57919
|
+
reason: error51 instanceof Error ? error51.message : String(error51)
|
|
57920
|
+
};
|
|
57921
|
+
}
|
|
57922
|
+
}
|
|
57923
|
+
async function regenerateHowWeTestSafe(source2, projectRoot) {
|
|
57924
|
+
const nodes = await listVerifiedProcedureNodes(source2);
|
|
57925
|
+
if (!nodes) return null;
|
|
57926
|
+
try {
|
|
57927
|
+
return await writeHowWeTest(projectRoot, collectHowWeTestRows(nodes));
|
|
57928
|
+
} catch {
|
|
57929
|
+
return null;
|
|
57930
|
+
}
|
|
57931
|
+
}
|
|
57932
|
+
var HOW_WE_TEST_RELATIVE, HOW_WE_TEST_HEADER;
|
|
57933
|
+
var init_howWeTest = __esm({
|
|
57934
|
+
"src/cli/memory/howWeTest.ts"() {
|
|
57935
|
+
"use strict";
|
|
57936
|
+
HOW_WE_TEST_RELATIVE = path67.join(".zelari", "how-we-test.md");
|
|
57937
|
+
HOW_WE_TEST_HEADER = "<!-- generato \u2014 non editare (rigenera con /memory how-we-test) -->";
|
|
57938
|
+
}
|
|
57939
|
+
});
|
|
57940
|
+
|
|
57700
57941
|
// src/cli/memory/repeatFailure.ts
|
|
57701
57942
|
import { createHash as createHash18 } from "node:crypto";
|
|
57702
57943
|
function failureFingerprint(command, exitCode, digest) {
|
|
@@ -57731,10 +57972,102 @@ var init_repeatFailure = __esm({
|
|
|
57731
57972
|
}
|
|
57732
57973
|
});
|
|
57733
57974
|
|
|
57975
|
+
// src/cli/memory/repeatCheck.ts
|
|
57976
|
+
function metaString2(node, key) {
|
|
57977
|
+
const value = node.metadata?.[key];
|
|
57978
|
+
return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
|
|
57979
|
+
}
|
|
57980
|
+
function metaNumber2(node, key) {
|
|
57981
|
+
const value = node.metadata?.[key];
|
|
57982
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
57983
|
+
}
|
|
57984
|
+
function checkIdForFingerprint(fingerprint) {
|
|
57985
|
+
return `con-${fingerprint}`;
|
|
57986
|
+
}
|
|
57987
|
+
function constraintFromNode(node) {
|
|
57988
|
+
if (!node) return null;
|
|
57989
|
+
const fingerprint = metaString2(node, "fingerprint");
|
|
57990
|
+
const command = metaString2(node, "command");
|
|
57991
|
+
const digest = metaString2(node, "digest");
|
|
57992
|
+
if (!fingerprint || !command || !digest) return null;
|
|
57993
|
+
const criterionId2 = metaString2(node, "criterionId");
|
|
57994
|
+
return {
|
|
57995
|
+
fingerprint,
|
|
57996
|
+
command,
|
|
57997
|
+
digest,
|
|
57998
|
+
exitCode: metaNumber2(node, "exitCode") ?? guessExitCode(command),
|
|
57999
|
+
...criterionId2 ? { criterionId: criterionId2 } : {}
|
|
58000
|
+
};
|
|
58001
|
+
}
|
|
58002
|
+
function sameCommand(a, b) {
|
|
58003
|
+
return failureCommandLabel(a).toLowerCase() === failureCommandLabel(b).toLowerCase();
|
|
58004
|
+
}
|
|
58005
|
+
function pickFixProcedure(constraint, procedures = []) {
|
|
58006
|
+
return procedures.find((node) => {
|
|
58007
|
+
if (node.kind !== "procedure" || node.status !== "active") return false;
|
|
58008
|
+
if (node.metadata?.verified !== true) return false;
|
|
58009
|
+
const digest = metaString2(node, "digest");
|
|
58010
|
+
const command = metaString2(node, "command");
|
|
58011
|
+
if (!digest || digest !== constraint.digest || !command) return false;
|
|
58012
|
+
return !sameCommand(command, constraint.command);
|
|
58013
|
+
});
|
|
58014
|
+
}
|
|
58015
|
+
function commandFromProcedure(procedure) {
|
|
58016
|
+
return metaString2(procedure, "command") ?? PLACEHOLDER_COMMAND;
|
|
58017
|
+
}
|
|
58018
|
+
function proposalFromConstraint(constraint, procedures = []) {
|
|
58019
|
+
const fix = pickFixProcedure(constraint, procedures);
|
|
58020
|
+
const command = fix ? commandFromProcedure(fix) : PLACEHOLDER_COMMAND;
|
|
58021
|
+
return {
|
|
58022
|
+
fp: constraint.fingerprint,
|
|
58023
|
+
command: constraint.command,
|
|
58024
|
+
exit: constraint.exitCode,
|
|
58025
|
+
digest: constraint.digest,
|
|
58026
|
+
checkId: checkIdForFingerprint(constraint.fingerprint),
|
|
58027
|
+
derivedFromProcedure: fix !== void 0,
|
|
58028
|
+
suggestedCheck: {
|
|
58029
|
+
id: checkIdForFingerprint(constraint.fingerprint),
|
|
58030
|
+
command,
|
|
58031
|
+
expectExit: 0
|
|
58032
|
+
}
|
|
58033
|
+
};
|
|
58034
|
+
}
|
|
58035
|
+
function confirmCheck(proposal, confirmed = {}) {
|
|
58036
|
+
const command = (confirmed.command ?? "").replace(/^\s*["']|["']\s*$/g, "").trim();
|
|
58037
|
+
if (!command || command === PLACEHOLDER_COMMAND) return null;
|
|
58038
|
+
const expectExit = typeof confirmed.expectExit === "number" && Number.isInteger(confirmed.expectExit) ? confirmed.expectExit : proposal.suggestedCheck.expectExit ?? 0;
|
|
58039
|
+
return { id: proposal.checkId, command, expectExit };
|
|
58040
|
+
}
|
|
58041
|
+
function formatCheckProposalNotice(proposal) {
|
|
58042
|
+
const preview = failureCommandLabel(proposal.command).replace(/\s+/g, " ").slice(0, 120);
|
|
58043
|
+
const suffix = proposal.derivedFromProcedure ? `--as-check --command "${proposal.suggestedCheck.command}"` : '--as-check --command "<comando>"';
|
|
58044
|
+
return `[memory] candidato WorldCheck: \u201C${preview}\u201D (exit ${proposal.exit}) \u2014 /memory promote ${proposal.checkId} ${suffix}`;
|
|
58045
|
+
}
|
|
58046
|
+
function checkConfirmationHint(proposal) {
|
|
58047
|
+
return proposal.derivedFromProcedure ? `[memory] proposta di check (applicazione sempre manuale):
|
|
58048
|
+
id: ${proposal.checkId}
|
|
58049
|
+
comando suggerito (da procedura verificata): ${proposal.suggestedCheck.command}
|
|
58050
|
+
exit atteso: ${proposal.suggestedCheck.expectExit}
|
|
58051
|
+
conferma con: /memory promote ${proposal.checkId} --as-check --command "${proposal.suggestedCheck.command}"` : `[memory] proposta di check (applicazione sempre manuale):
|
|
58052
|
+
id: ${proposal.checkId}
|
|
58053
|
+
comando fallito (NON ri-eseguito automaticamente): ${failureCommandLabel(proposal.command)}
|
|
58054
|
+
digest: ${proposal.digest} \xB7 exit ${proposal.exit}
|
|
58055
|
+
nessuna procedura verificata per lo stesso digest: scrivi il comando di regressione,
|
|
58056
|
+
conferma con: /memory promote ${proposal.checkId} --as-check --command "<comando>"`;
|
|
58057
|
+
}
|
|
58058
|
+
var PLACEHOLDER_COMMAND;
|
|
58059
|
+
var init_repeatCheck = __esm({
|
|
58060
|
+
"src/cli/memory/repeatCheck.ts"() {
|
|
58061
|
+
"use strict";
|
|
58062
|
+
init_repeatFailure();
|
|
58063
|
+
PLACEHOLDER_COMMAND = "<confirm-command>";
|
|
58064
|
+
}
|
|
58065
|
+
});
|
|
58066
|
+
|
|
57734
58067
|
// src/cli/memory/legacyImport.ts
|
|
57735
58068
|
import { createHash as createHash19 } from "node:crypto";
|
|
57736
|
-
import { promises as
|
|
57737
|
-
import * as
|
|
58069
|
+
import { promises as fs29 } from "node:fs";
|
|
58070
|
+
import * as path68 from "node:path";
|
|
57738
58071
|
function sourceId(fact, line) {
|
|
57739
58072
|
return `jsonl:${fact.id ?? createHash19("sha256").update(line).digest("hex")}`;
|
|
57740
58073
|
}
|
|
@@ -57755,7 +58088,7 @@ function isPermanentSkip(error51) {
|
|
|
57755
58088
|
}
|
|
57756
58089
|
async function isImportComplete(markerPath) {
|
|
57757
58090
|
try {
|
|
57758
|
-
const marker = JSON.parse(await
|
|
58091
|
+
const marker = JSON.parse(await fs29.readFile(markerPath, "utf8"));
|
|
57759
58092
|
return typeof marker?.found === "number" && typeof marker?.at === "string";
|
|
57760
58093
|
} catch {
|
|
57761
58094
|
return false;
|
|
@@ -57764,20 +58097,20 @@ async function isImportComplete(markerPath) {
|
|
|
57764
58097
|
async function markImportComplete(markerPath, found) {
|
|
57765
58098
|
const temporary = `${markerPath}.tmp`;
|
|
57766
58099
|
try {
|
|
57767
|
-
await
|
|
58100
|
+
await fs29.writeFile(temporary, `${JSON.stringify({ found, at: (/* @__PURE__ */ new Date()).toISOString() })}
|
|
57768
58101
|
`, "utf8");
|
|
57769
|
-
await
|
|
58102
|
+
await fs29.rename(temporary, markerPath);
|
|
57770
58103
|
} catch {
|
|
57771
58104
|
}
|
|
57772
58105
|
}
|
|
57773
58106
|
async function importLegacyMemoryLog(backend, service) {
|
|
57774
58107
|
const result = { found: 0, imported: 0, skipped: 0, corrupt: 0 };
|
|
57775
|
-
const memoryDir =
|
|
57776
|
-
const markerPath =
|
|
58108
|
+
const memoryDir = path68.dirname(backend.databasePath);
|
|
58109
|
+
const markerPath = path68.join(memoryDir, LEGACY_IMPORT_MARKER);
|
|
57777
58110
|
if (await isImportComplete(markerPath)) return result;
|
|
57778
58111
|
let raw;
|
|
57779
58112
|
try {
|
|
57780
|
-
raw = await
|
|
58113
|
+
raw = await fs29.readFile(path68.join(memoryDir, "log.jsonl"), "utf8");
|
|
57781
58114
|
} catch {
|
|
57782
58115
|
return result;
|
|
57783
58116
|
}
|
|
@@ -57969,7 +58302,7 @@ var init_sqliteCodec = __esm({
|
|
|
57969
58302
|
// src/cli/memory/sqliteRpc.ts
|
|
57970
58303
|
import { existsSync as existsSync34 } from "node:fs";
|
|
57971
58304
|
import { fileURLToPath as fileURLToPath2, pathToFileURL as pathToFileURL2 } from "node:url";
|
|
57972
|
-
import * as
|
|
58305
|
+
import * as path69 from "node:path";
|
|
57973
58306
|
import { Worker } from "node:worker_threads";
|
|
57974
58307
|
function isBusy(error51) {
|
|
57975
58308
|
const candidate = error51;
|
|
@@ -57978,10 +58311,10 @@ function isBusy(error51) {
|
|
|
57978
58311
|
);
|
|
57979
58312
|
}
|
|
57980
58313
|
function resolveWorkerUrl() {
|
|
57981
|
-
const here =
|
|
57982
|
-
const direct =
|
|
58314
|
+
const here = path69.dirname(fileURLToPath2(import.meta.url));
|
|
58315
|
+
const direct = path69.join(here, "sqliteWorker.mjs");
|
|
57983
58316
|
if (existsSync34(direct)) return pathToFileURL2(direct);
|
|
57984
|
-
return pathToFileURL2(
|
|
58317
|
+
return pathToFileURL2(path69.join(here, "memory", "sqliteWorker.mjs"));
|
|
57985
58318
|
}
|
|
57986
58319
|
var SqliteWorkerRpc;
|
|
57987
58320
|
var init_sqliteRpc = __esm({
|
|
@@ -58269,8 +58602,8 @@ WHERE NOT EXISTS (SELECT 1 FROM memory_fts f WHERE f.node_id = n.id);
|
|
|
58269
58602
|
|
|
58270
58603
|
// src/cli/memory/sqliteBackend.ts
|
|
58271
58604
|
import { createHash as createHash20, randomUUID as randomUUID5 } from "node:crypto";
|
|
58272
|
-
import { promises as
|
|
58273
|
-
import * as
|
|
58605
|
+
import { promises as fs30 } from "node:fs";
|
|
58606
|
+
import * as path70 from "node:path";
|
|
58274
58607
|
function boundedLimit(value, fallback = 50) {
|
|
58275
58608
|
return Math.max(1, Math.min(Math.floor(value ?? fallback), 1e5));
|
|
58276
58609
|
}
|
|
@@ -58331,42 +58664,42 @@ VALUES (${Array.from({ length: 19 }, () => "?").join(",")})`;
|
|
|
58331
58664
|
async init(projectRoot) {
|
|
58332
58665
|
let resolved;
|
|
58333
58666
|
try {
|
|
58334
|
-
resolved = await
|
|
58667
|
+
resolved = await fs30.realpath(projectRoot);
|
|
58335
58668
|
} catch {
|
|
58336
|
-
resolved =
|
|
58669
|
+
resolved = path70.resolve(projectRoot);
|
|
58337
58670
|
}
|
|
58338
58671
|
if (this.initialized && resolved === this.projectRoot) return;
|
|
58339
58672
|
if (this.initialized) await this.close();
|
|
58340
58673
|
const filename = this.options.filename ?? "memory.db";
|
|
58341
|
-
if (
|
|
58674
|
+
if (path70.basename(filename) !== filename || filename === "." || filename === "..") {
|
|
58342
58675
|
throw new Error("SQLite memory filename must not contain a path.");
|
|
58343
58676
|
}
|
|
58344
|
-
const zelariDirectory =
|
|
58345
|
-
const directory =
|
|
58677
|
+
const zelariDirectory = path70.join(resolved, ".zelari");
|
|
58678
|
+
const directory = path70.join(zelariDirectory, "memory");
|
|
58346
58679
|
for (const candidate of [zelariDirectory, directory]) {
|
|
58347
58680
|
let stat8;
|
|
58348
58681
|
try {
|
|
58349
|
-
stat8 = await
|
|
58682
|
+
stat8 = await fs30.lstat(candidate);
|
|
58350
58683
|
} catch (error51) {
|
|
58351
58684
|
if (error51.code !== "ENOENT") throw error51;
|
|
58352
58685
|
try {
|
|
58353
|
-
await
|
|
58686
|
+
await fs30.mkdir(candidate);
|
|
58354
58687
|
} catch (mkdirError) {
|
|
58355
58688
|
if (mkdirError.code !== "EEXIST") throw mkdirError;
|
|
58356
58689
|
}
|
|
58357
|
-
stat8 = await
|
|
58690
|
+
stat8 = await fs30.lstat(candidate);
|
|
58358
58691
|
}
|
|
58359
58692
|
if (stat8.isSymbolicLink() || !stat8.isDirectory()) {
|
|
58360
58693
|
throw new Error(`Memory directory is not a real directory: ${candidate}`);
|
|
58361
58694
|
}
|
|
58362
58695
|
}
|
|
58363
|
-
const canonicalDirectory = await
|
|
58364
|
-
const relativeDirectory =
|
|
58365
|
-
if (relativeDirectory.startsWith("..") ||
|
|
58696
|
+
const canonicalDirectory = await fs30.realpath(directory);
|
|
58697
|
+
const relativeDirectory = path70.relative(resolved, canonicalDirectory);
|
|
58698
|
+
if (relativeDirectory.startsWith("..") || path70.isAbsolute(relativeDirectory)) {
|
|
58366
58699
|
throw new Error("SQLite memory directory resolves outside the active project.");
|
|
58367
58700
|
}
|
|
58368
58701
|
this.projectRoot = resolved;
|
|
58369
|
-
this.databasePath =
|
|
58702
|
+
this.databasePath = path70.join(canonicalDirectory, filename);
|
|
58370
58703
|
const opened = await this.rpc.open({
|
|
58371
58704
|
dbPath: this.databasePath,
|
|
58372
58705
|
schemaSql: SQLITE_MEMORY_BASE_SCHEMA,
|
|
@@ -58908,8 +59241,8 @@ __export(serviceFactory_exports, {
|
|
|
58908
59241
|
isMemoryV2Enabled: () => isMemoryV2Enabled
|
|
58909
59242
|
});
|
|
58910
59243
|
import { createHash as createHash21 } from "node:crypto";
|
|
58911
|
-
import { promises as
|
|
58912
|
-
import * as
|
|
59244
|
+
import { promises as fs31 } from "node:fs";
|
|
59245
|
+
import * as path71 from "node:path";
|
|
58913
59246
|
function isMemoryV2Enabled(env = process.env) {
|
|
58914
59247
|
if (env.ZELARI_MEMORY === "0") return false;
|
|
58915
59248
|
if (env.ZELARI_MEMORY_BACKEND === "file" || env.ZELARI_MEMORY_BACKEND === "jsonl") return false;
|
|
@@ -58928,9 +59261,9 @@ function semanticMinScore(env) {
|
|
|
58928
59261
|
async function canonicalProjectId(projectRoot) {
|
|
58929
59262
|
let canonical;
|
|
58930
59263
|
try {
|
|
58931
|
-
canonical = await
|
|
59264
|
+
canonical = await fs31.realpath(projectRoot);
|
|
58932
59265
|
} catch {
|
|
58933
|
-
canonical =
|
|
59266
|
+
canonical = path71.resolve(projectRoot);
|
|
58934
59267
|
}
|
|
58935
59268
|
canonical = canonical.replace(/\\/g, "/").replace(/\/$/, "");
|
|
58936
59269
|
if (process.platform === "win32") canonical = canonical.toLocaleLowerCase("en-US");
|
|
@@ -59167,6 +59500,8 @@ async function promoteOpsKnowledge(gate, deps) {
|
|
|
59167
59500
|
let skippedDuplicate = 0;
|
|
59168
59501
|
let constraintsCreated = 0;
|
|
59169
59502
|
const proposals = [];
|
|
59503
|
+
const checkProposals = [];
|
|
59504
|
+
const procedureNodes = fails.length > 0 ? await listVerifiedProcedureNodes(memory) ?? [] : [];
|
|
59170
59505
|
for (const candidate of pass) {
|
|
59171
59506
|
const outcome = await rememberProcedure(memory, candidate, { sessionId: deps.sessionId });
|
|
59172
59507
|
if (outcome === "created") {
|
|
@@ -59186,11 +59521,14 @@ async function promoteOpsKnowledge(gate, deps) {
|
|
|
59186
59521
|
constraintsCreated += 1;
|
|
59187
59522
|
const node = await memory.get(outcome.constraintId);
|
|
59188
59523
|
if (node && meetsPromoteThreshold(node)) proposals.push(formatPromoteNotice(node));
|
|
59524
|
+
const constraint = constraintFromNode(node);
|
|
59525
|
+
if (constraint) checkProposals.push(proposalFromConstraint(constraint, procedureNodes));
|
|
59189
59526
|
} else if (outcome.constraint === "duplicate") {
|
|
59190
59527
|
skippedDuplicate += 1;
|
|
59191
59528
|
}
|
|
59192
59529
|
}
|
|
59193
|
-
|
|
59530
|
+
if (created > 0) await regenerateHowWeTestSafe(memory, deps.projectRoot);
|
|
59531
|
+
return { enabled: true, created, skippedDuplicate, constraintsCreated, proposals, checkProposals };
|
|
59194
59532
|
}
|
|
59195
59533
|
async function promoteOpsKnowledgeSafe(gate, deps) {
|
|
59196
59534
|
try {
|
|
@@ -59206,7 +59544,8 @@ function emptyResult(enabled, skippedReason) {
|
|
|
59206
59544
|
created: 0,
|
|
59207
59545
|
skippedDuplicate: 0,
|
|
59208
59546
|
constraintsCreated: 0,
|
|
59209
|
-
proposals: []
|
|
59547
|
+
proposals: [],
|
|
59548
|
+
checkProposals: []
|
|
59210
59549
|
};
|
|
59211
59550
|
}
|
|
59212
59551
|
async function openMemory(projectRoot, env) {
|
|
@@ -59222,7 +59561,9 @@ var ALLOWED_TIERS;
|
|
|
59222
59561
|
var init_opsKnowledge = __esm({
|
|
59223
59562
|
"src/cli/memory/opsKnowledge.ts"() {
|
|
59224
59563
|
"use strict";
|
|
59564
|
+
init_howWeTest();
|
|
59225
59565
|
init_promotion();
|
|
59566
|
+
init_repeatCheck();
|
|
59226
59567
|
init_repeatFailure();
|
|
59227
59568
|
init_repeatFailure();
|
|
59228
59569
|
ALLOWED_TIERS = /* @__PURE__ */ new Set(["command-output", "fs-observation"]);
|
|
@@ -59312,20 +59653,20 @@ var init_askUserTimeout = __esm({
|
|
|
59312
59653
|
|
|
59313
59654
|
// src/cli/state/fileStateStore.ts
|
|
59314
59655
|
import { createHash as createHash23, randomUUID as randomUUID6 } from "node:crypto";
|
|
59315
|
-
import { promises as
|
|
59316
|
-
import * as
|
|
59656
|
+
import { promises as fs32 } from "node:fs";
|
|
59657
|
+
import * as path72 from "node:path";
|
|
59317
59658
|
function shortId() {
|
|
59318
59659
|
return randomUUID6().replace(/-/g, "").slice(0, 12);
|
|
59319
59660
|
}
|
|
59320
59661
|
async function writeJsonAtomic(filePath, data) {
|
|
59321
|
-
await
|
|
59662
|
+
await fs32.mkdir(path72.dirname(filePath), { recursive: true });
|
|
59322
59663
|
const tmp = `${filePath}.${process.pid}.${Date.now()}.tmp`;
|
|
59323
|
-
await
|
|
59324
|
-
await
|
|
59664
|
+
await fs32.writeFile(tmp, JSON.stringify(data, null, 2) + "\n", "utf8");
|
|
59665
|
+
await fs32.rename(tmp, filePath);
|
|
59325
59666
|
}
|
|
59326
59667
|
async function readJsonFile(filePath) {
|
|
59327
59668
|
try {
|
|
59328
|
-
const raw = await
|
|
59669
|
+
const raw = await fs32.readFile(filePath, "utf8");
|
|
59329
59670
|
return JSON.parse(raw);
|
|
59330
59671
|
} catch {
|
|
59331
59672
|
return null;
|
|
@@ -59379,13 +59720,13 @@ var init_fileStateStore = __esm({
|
|
|
59379
59720
|
indexPath = "";
|
|
59380
59721
|
async init(projectRoot) {
|
|
59381
59722
|
this.root = projectRoot;
|
|
59382
|
-
this.stateDir =
|
|
59383
|
-
this.commitsDir =
|
|
59384
|
-
this.artifactsDir =
|
|
59385
|
-
this.headPath =
|
|
59386
|
-
this.indexPath =
|
|
59387
|
-
await
|
|
59388
|
-
await
|
|
59723
|
+
this.stateDir = path72.join(projectRoot, ".zelari", "state");
|
|
59724
|
+
this.commitsDir = path72.join(this.stateDir, "commits");
|
|
59725
|
+
this.artifactsDir = path72.join(this.stateDir, "artifacts");
|
|
59726
|
+
this.headPath = path72.join(this.stateDir, "HEAD.json");
|
|
59727
|
+
this.indexPath = path72.join(this.stateDir, "index.jsonl");
|
|
59728
|
+
await fs32.mkdir(this.commitsDir, { recursive: true });
|
|
59729
|
+
await fs32.mkdir(this.artifactsDir, { recursive: true });
|
|
59389
59730
|
}
|
|
59390
59731
|
async commit(input) {
|
|
59391
59732
|
if (!input.force && input.verification.ran && !input.verification.ok) {
|
|
@@ -59396,13 +59737,13 @@ var init_fileStateStore = __esm({
|
|
|
59396
59737
|
const discoveries = input.discoveries ?? [];
|
|
59397
59738
|
const parent = await this.head();
|
|
59398
59739
|
const id3 = shortId();
|
|
59399
|
-
const artifactRel =
|
|
59400
|
-
const artifactAbs =
|
|
59401
|
-
await
|
|
59740
|
+
const artifactRel = path72.join("artifacts", id3);
|
|
59741
|
+
const artifactAbs = path72.join(this.artifactsDir, id3);
|
|
59742
|
+
await fs32.mkdir(artifactAbs, { recursive: true });
|
|
59402
59743
|
const summary = defaultSummary(input, discoveries);
|
|
59403
|
-
await
|
|
59404
|
-
await writeJsonAtomic(
|
|
59405
|
-
await writeJsonAtomic(
|
|
59744
|
+
await fs32.writeFile(path72.join(artifactAbs, "summary.md"), summary + "\n", "utf8");
|
|
59745
|
+
await writeJsonAtomic(path72.join(artifactAbs, "discoveries.json"), discoveries);
|
|
59746
|
+
await writeJsonAtomic(path72.join(artifactAbs, "verification.json"), input.verification);
|
|
59406
59747
|
const meta3 = {
|
|
59407
59748
|
id: id3,
|
|
59408
59749
|
parentId: parent?.id ?? null,
|
|
@@ -59414,16 +59755,16 @@ var init_fileStateStore = __esm({
|
|
|
59414
59755
|
workspaceCheckpointId: input.workspaceCheckpointId,
|
|
59415
59756
|
verification: {
|
|
59416
59757
|
...input.verification,
|
|
59417
|
-
reportPath: input.verification.reportPath ??
|
|
59758
|
+
reportPath: input.verification.reportPath ?? path72.join(".zelari", "state", artifactRel, "verification.json").replace(/\\/g, "/")
|
|
59418
59759
|
},
|
|
59419
59760
|
changedPaths: input.changedPaths ?? [],
|
|
59420
59761
|
stablePromptHash: input.stablePromptHash,
|
|
59421
59762
|
discoveryCount: discoveries.length,
|
|
59422
59763
|
artifactDir: artifactRel.replace(/\\/g, "/")
|
|
59423
59764
|
};
|
|
59424
|
-
await writeJsonAtomic(
|
|
59765
|
+
await writeJsonAtomic(path72.join(this.commitsDir, `${id3}.json`), meta3);
|
|
59425
59766
|
await writeJsonAtomic(this.headPath, { id: id3, updatedAt: meta3.createdAt });
|
|
59426
|
-
await
|
|
59767
|
+
await fs32.appendFile(this.indexPath, JSON.stringify({ id: id3, createdAt: meta3.createdAt, label: meta3.label }) + "\n", "utf8");
|
|
59427
59768
|
return stripStored(meta3);
|
|
59428
59769
|
}
|
|
59429
59770
|
async head() {
|
|
@@ -59432,13 +59773,13 @@ var init_fileStateStore = __esm({
|
|
|
59432
59773
|
return this.get(head.id);
|
|
59433
59774
|
}
|
|
59434
59775
|
async get(id3) {
|
|
59435
|
-
const stored = await readJsonFile(
|
|
59776
|
+
const stored = await readJsonFile(path72.join(this.commitsDir, `${id3}.json`));
|
|
59436
59777
|
return stored ? stripStored(stored) : null;
|
|
59437
59778
|
}
|
|
59438
59779
|
async list(limit = 20) {
|
|
59439
59780
|
let raw;
|
|
59440
59781
|
try {
|
|
59441
|
-
raw = await
|
|
59782
|
+
raw = await fs32.readFile(this.indexPath, "utf8");
|
|
59442
59783
|
} catch {
|
|
59443
59784
|
return [];
|
|
59444
59785
|
}
|
|
@@ -59471,9 +59812,9 @@ var init_fileStateStore = __esm({
|
|
|
59471
59812
|
async loadDiscoveries(id3) {
|
|
59472
59813
|
const meta3 = id3 ? await this.get(id3) : await this.head();
|
|
59473
59814
|
if (!meta3) return [];
|
|
59474
|
-
const stored = await readJsonFile(
|
|
59815
|
+
const stored = await readJsonFile(path72.join(this.commitsDir, `${meta3.id}.json`));
|
|
59475
59816
|
if (!stored?.artifactDir) return [];
|
|
59476
|
-
const discPath =
|
|
59817
|
+
const discPath = path72.join(this.stateDir, stored.artifactDir, "discoveries.json");
|
|
59477
59818
|
return await readJsonFile(discPath) ?? [];
|
|
59478
59819
|
}
|
|
59479
59820
|
async materializeContext(id3, maxChars = DEFAULT_MATERIALIZE_CHARS) {
|
|
@@ -59684,7 +60025,7 @@ __export(conversationContext_exports, {
|
|
|
59684
60025
|
setLastClarification: () => setLastClarification
|
|
59685
60026
|
});
|
|
59686
60027
|
import { existsSync as existsSync35 } from "node:fs";
|
|
59687
|
-
import { join as
|
|
60028
|
+
import { join as join27 } from "node:path";
|
|
59688
60029
|
function getHistory() {
|
|
59689
60030
|
return history;
|
|
59690
60031
|
}
|
|
@@ -59693,7 +60034,7 @@ function setHistory(messages) {
|
|
|
59693
60034
|
history = projected === messages ? [...messages] : projected;
|
|
59694
60035
|
}
|
|
59695
60036
|
function compactInPlace(cwd = process.cwd()) {
|
|
59696
|
-
const durableStatePresent = existsSync35(
|
|
60037
|
+
const durableStatePresent = existsSync35(join27(cwd, ".zelari", "state", "HEAD.json"));
|
|
59697
60038
|
history = applySessionSurface(compactHistory(history, { durableStatePresent }));
|
|
59698
60039
|
}
|
|
59699
60040
|
function appendMessages(msgs) {
|
|
@@ -60076,10 +60417,10 @@ var init_mode = __esm({
|
|
|
60076
60417
|
|
|
60077
60418
|
// src/cli/headless.ts
|
|
60078
60419
|
import { readFileSync as readFileSync24 } from "node:fs";
|
|
60079
|
-
import
|
|
60420
|
+
import path73 from "node:path";
|
|
60080
60421
|
function resolveHeadlessCwd(opts) {
|
|
60081
60422
|
const raw = typeof opts.cwd === "string" ? opts.cwd.trim() : "";
|
|
60082
|
-
return
|
|
60423
|
+
return path73.resolve(raw.length > 0 ? raw : process.cwd());
|
|
60083
60424
|
}
|
|
60084
60425
|
function defaultProfileForMode(mode) {
|
|
60085
60426
|
switch (mode) {
|
|
@@ -60395,7 +60736,7 @@ __export(headlessSpine_exports, {
|
|
|
60395
60736
|
seedHeadlessModelHistory: () => seedHeadlessModelHistory,
|
|
60396
60737
|
sessionStartedEvent: () => sessionStartedEvent
|
|
60397
60738
|
});
|
|
60398
|
-
import
|
|
60739
|
+
import path74 from "node:path";
|
|
60399
60740
|
function sessionStartedEvent(handle) {
|
|
60400
60741
|
return {
|
|
60401
60742
|
type: "session_started",
|
|
@@ -60412,7 +60753,7 @@ async function countVerificationEvidenceInLog(mirror, sessionId2) {
|
|
|
60412
60753
|
try {
|
|
60413
60754
|
await mirror.flush().catch(() => void 0);
|
|
60414
60755
|
const report = await readSessionLogCached(
|
|
60415
|
-
|
|
60756
|
+
path74.join(mirror.sessionsDir, sessionId2, "events.jsonl"),
|
|
60416
60757
|
mirror.replayCache
|
|
60417
60758
|
);
|
|
60418
60759
|
return report.events.filter((e) => e.kind === "verification.evidence").length;
|
|
@@ -61188,9 +61529,9 @@ __export(planDetect_exports, {
|
|
|
61188
61529
|
hasWorkspacePlan: () => hasWorkspacePlan
|
|
61189
61530
|
});
|
|
61190
61531
|
import { existsSync as existsSync36, readFileSync as readFileSync25 } from "node:fs";
|
|
61191
|
-
import { join as
|
|
61532
|
+
import { join as join28 } from "node:path";
|
|
61192
61533
|
function hasWorkspacePlan(projectRoot = process.cwd()) {
|
|
61193
|
-
const planPath =
|
|
61534
|
+
const planPath = join28(resolveWorkspaceRoot(projectRoot), "plan.json");
|
|
61194
61535
|
if (!existsSync36(planPath)) return false;
|
|
61195
61536
|
try {
|
|
61196
61537
|
const parsed = JSON.parse(readFileSync25(planPath, "utf8"));
|
|
@@ -61208,10 +61549,10 @@ var init_planDetect = __esm({
|
|
|
61208
61549
|
|
|
61209
61550
|
// src/cli/workspace/projectInstructions.ts
|
|
61210
61551
|
import { existsSync as existsSync37, readFileSync as readFileSync26 } from "node:fs";
|
|
61211
|
-
import { join as
|
|
61552
|
+
import { join as join29 } from "node:path";
|
|
61212
61553
|
function loadProjectInstructions(projectRoot = process.cwd(), maxChars = MAX_CHARS) {
|
|
61213
61554
|
for (const name of CANDIDATES) {
|
|
61214
|
-
const full =
|
|
61555
|
+
const full = join29(projectRoot, name);
|
|
61215
61556
|
if (!existsSync37(full)) continue;
|
|
61216
61557
|
try {
|
|
61217
61558
|
let raw = readFileSync26(full, "utf8");
|
|
@@ -61259,7 +61600,7 @@ __export(workspaceSummary_exports, {
|
|
|
61259
61600
|
buildZelariReadHint: () => buildZelariReadHint
|
|
61260
61601
|
});
|
|
61261
61602
|
import { existsSync as existsSync38, readFileSync as readFileSync27, readdirSync as readdirSync7, statSync as statSync5 } from "node:fs";
|
|
61262
|
-
import { join as
|
|
61603
|
+
import { join as join30, relative as relative2 } from "node:path";
|
|
61263
61604
|
function buildWorkspaceSummary(projectRoot = process.cwd(), options = {}) {
|
|
61264
61605
|
const { maxEntries = 30, maxChars = 3500, maxDeps = 24, maxScripts = 16 } = options;
|
|
61265
61606
|
const name = safeProjectName(projectRoot);
|
|
@@ -61292,7 +61633,7 @@ function formatTaskLine(t) {
|
|
|
61292
61633
|
}
|
|
61293
61634
|
function buildPlanSummary(projectRoot = process.cwd(), options) {
|
|
61294
61635
|
const zelariRoot = resolveWorkspaceRoot(projectRoot);
|
|
61295
|
-
const planPath =
|
|
61636
|
+
const planPath = join30(zelariRoot, "plan.json");
|
|
61296
61637
|
if (!existsSync38(planPath)) return null;
|
|
61297
61638
|
let plan;
|
|
61298
61639
|
try {
|
|
@@ -61435,7 +61776,7 @@ function pickNextTask(open2) {
|
|
|
61435
61776
|
)[0];
|
|
61436
61777
|
}
|
|
61437
61778
|
function buildZelariReadHint(projectRoot = process.cwd()) {
|
|
61438
|
-
const planPath =
|
|
61779
|
+
const planPath = join30(resolveWorkspaceRoot(projectRoot), "plan.json");
|
|
61439
61780
|
if (!existsSync38(planPath)) return "";
|
|
61440
61781
|
return [
|
|
61441
61782
|
"# Council workspace detected (.zelari/) \u2014 DRAFT vault",
|
|
@@ -61451,7 +61792,7 @@ function safeProjectName(root) {
|
|
|
61451
61792
|
}
|
|
61452
61793
|
}
|
|
61453
61794
|
function readPackageJson2(projectRoot) {
|
|
61454
|
-
const p3 =
|
|
61795
|
+
const p3 = join30(projectRoot, "package.json");
|
|
61455
61796
|
if (!existsSync38(p3)) return null;
|
|
61456
61797
|
try {
|
|
61457
61798
|
return JSON.parse(readFileSync27(p3, "utf8"));
|
|
@@ -61504,11 +61845,11 @@ function listShallow(projectRoot, maxEntries) {
|
|
|
61504
61845
|
out.push(`\u2026 (+${top.length - count} more)`);
|
|
61505
61846
|
break;
|
|
61506
61847
|
}
|
|
61507
|
-
const rel2 = relative2(projectRoot,
|
|
61848
|
+
const rel2 = relative2(projectRoot, join30(projectRoot, entry.name));
|
|
61508
61849
|
if (entry.isDirectory()) {
|
|
61509
61850
|
let inner = "";
|
|
61510
61851
|
try {
|
|
61511
|
-
const sub = readdirSync7(
|
|
61852
|
+
const sub = readdirSync7(join30(projectRoot, entry.name), {
|
|
61512
61853
|
withFileTypes: true
|
|
61513
61854
|
}).filter((e) => !e.name.startsWith(".")).slice(0, 4).map((e) => e.name);
|
|
61514
61855
|
if (sub.length > 0)
|
|
@@ -61557,11 +61898,11 @@ var init_workspaceSummary = __esm({
|
|
|
61557
61898
|
|
|
61558
61899
|
// src/cli/workspace/buildLessonsSummary.ts
|
|
61559
61900
|
import { existsSync as existsSync39 } from "node:fs";
|
|
61560
|
-
import { join as
|
|
61901
|
+
import { join as join31 } from "node:path";
|
|
61561
61902
|
function buildLessonsSummary(projectRoot = process.cwd(), taskText) {
|
|
61562
61903
|
if (process.env["ZELARI_LESSONS"] === "0") return null;
|
|
61563
61904
|
const zelariRoot = resolveWorkspaceRoot(projectRoot);
|
|
61564
|
-
if (!existsSync39(
|
|
61905
|
+
if (!existsSync39(join31(zelariRoot, "lessons.jsonl"))) return null;
|
|
61565
61906
|
const lessons = recallLessons(zelariRoot, {
|
|
61566
61907
|
maxLessons: 5,
|
|
61567
61908
|
maxBytes: 2048,
|
|
@@ -61583,7 +61924,7 @@ __export(composeContext_exports, {
|
|
|
61583
61924
|
composeProjectContext: () => composeProjectContext
|
|
61584
61925
|
});
|
|
61585
61926
|
import { existsSync as existsSync40, readdirSync as readdirSync8, readFileSync as readFileSync28 } from "node:fs";
|
|
61586
|
-
import { join as
|
|
61927
|
+
import { join as join32 } from "node:path";
|
|
61587
61928
|
function cap2(text, max, label) {
|
|
61588
61929
|
if (!text || text.length <= max) return { text: text || "", truncated: false };
|
|
61589
61930
|
return {
|
|
@@ -61600,7 +61941,7 @@ function buildDesignIndex(projectRoot, maxChars) {
|
|
|
61600
61941
|
"# Design vault index (.zelari/) \u2014 HYPOTHESES only",
|
|
61601
61942
|
"Full design docs are NOT product source of truth. Open with list_files / read_file / searchDocuments if needed."
|
|
61602
61943
|
];
|
|
61603
|
-
const docsDir =
|
|
61944
|
+
const docsDir = join32(root, "docs");
|
|
61604
61945
|
if (existsSync40(docsDir)) {
|
|
61605
61946
|
try {
|
|
61606
61947
|
const docs = readdirSync8(docsDir).filter((n) => n.endsWith(".md")).slice(0, 12);
|
|
@@ -61615,11 +61956,11 @@ function buildDesignIndex(projectRoot, maxChars) {
|
|
|
61615
61956
|
}
|
|
61616
61957
|
}
|
|
61617
61958
|
for (const name of ["risks.md", "plan.json", "nfr-spec.json"]) {
|
|
61618
|
-
if (existsSync40(
|
|
61959
|
+
if (existsSync40(join32(root, name))) {
|
|
61619
61960
|
lines.push(`- .zelari/${name} present`);
|
|
61620
61961
|
}
|
|
61621
61962
|
}
|
|
61622
|
-
const decisionsDir =
|
|
61963
|
+
const decisionsDir = join32(root, "decisions");
|
|
61623
61964
|
if (existsSync40(decisionsDir)) {
|
|
61624
61965
|
try {
|
|
61625
61966
|
const n = readdirSync8(decisionsDir).filter((f) => f.endsWith(".md")).length;
|
|
@@ -61721,14 +62062,14 @@ function composeProjectContext(input) {
|
|
|
61721
62062
|
}
|
|
61722
62063
|
function readDurableHeadSync(projectRoot) {
|
|
61723
62064
|
try {
|
|
61724
|
-
const headPath =
|
|
62065
|
+
const headPath = join32(projectRoot, ".zelari", "state", "HEAD.json");
|
|
61725
62066
|
if (!existsSync40(headPath)) return "";
|
|
61726
62067
|
const head = JSON.parse(readFileSync28(headPath, "utf8"));
|
|
61727
62068
|
if (!head?.id) return "";
|
|
61728
|
-
const metaPath =
|
|
62069
|
+
const metaPath = join32(projectRoot, ".zelari", "state", "commits", `${head.id}.json`);
|
|
61729
62070
|
if (!existsSync40(metaPath)) return "";
|
|
61730
62071
|
const meta3 = JSON.parse(readFileSync28(metaPath, "utf8"));
|
|
61731
|
-
const discPath = meta3.artifactDir ?
|
|
62072
|
+
const discPath = meta3.artifactDir ? join32(projectRoot, ".zelari", "state", meta3.artifactDir, "discoveries.json") : join32(projectRoot, ".zelari", "state", "artifacts", head.id, "discoveries.json");
|
|
61732
62073
|
let discoveries = [];
|
|
61733
62074
|
if (existsSync40(discPath)) {
|
|
61734
62075
|
discoveries = JSON.parse(readFileSync28(discPath, "utf8"));
|
|
@@ -61812,7 +62153,7 @@ import {
|
|
|
61812
62153
|
mkdirSync as mkdirSync16,
|
|
61813
62154
|
renameSync as renameSync5
|
|
61814
62155
|
} from "node:fs";
|
|
61815
|
-
import { join as
|
|
62156
|
+
import { join as join33, basename as basename4, dirname as dirname9, relative as relative3 } from "node:path";
|
|
61816
62157
|
function createWorkspaceContext(projectRoot = process.cwd()) {
|
|
61817
62158
|
const rootDir = resolveWorkspaceRoot(projectRoot);
|
|
61818
62159
|
return {
|
|
@@ -61822,7 +62163,7 @@ function createWorkspaceContext(projectRoot = process.cwd()) {
|
|
|
61822
62163
|
};
|
|
61823
62164
|
}
|
|
61824
62165
|
function planJsonPath(ctx) {
|
|
61825
|
-
return
|
|
62166
|
+
return join33(ctx.rootDir, "plan.json");
|
|
61826
62167
|
}
|
|
61827
62168
|
function readPlan(ctx) {
|
|
61828
62169
|
const jsonPath = planJsonPath(ctx);
|
|
@@ -61841,8 +62182,8 @@ function readPlan(ctx) {
|
|
|
61841
62182
|
} catch {
|
|
61842
62183
|
}
|
|
61843
62184
|
}
|
|
61844
|
-
const
|
|
61845
|
-
const doc = ctx.storage.readIfExists(
|
|
62185
|
+
const path103 = workspaceFile(ctx.rootDir, "plan");
|
|
62186
|
+
const doc = ctx.storage.readIfExists(path103);
|
|
61846
62187
|
if (!doc) return { phases: [], tasks: [], milestones: [] };
|
|
61847
62188
|
const meta3 = doc.meta;
|
|
61848
62189
|
return {
|
|
@@ -61853,7 +62194,7 @@ function readPlan(ctx) {
|
|
|
61853
62194
|
}
|
|
61854
62195
|
function writePlan(ctx, summary) {
|
|
61855
62196
|
const jsonPath = planJsonPath(ctx);
|
|
61856
|
-
mkdirSync16(
|
|
62197
|
+
mkdirSync16(dirname9(jsonPath), { recursive: true });
|
|
61857
62198
|
const tmp = jsonPath + ".tmp-" + process.pid;
|
|
61858
62199
|
writeFileSync18(
|
|
61859
62200
|
tmp,
|
|
@@ -61935,7 +62276,7 @@ function renderPlanBody(summary) {
|
|
|
61935
62276
|
return lines.join("\n");
|
|
61936
62277
|
}
|
|
61937
62278
|
function nextAdrId(ctx) {
|
|
61938
|
-
const decisionsDir =
|
|
62279
|
+
const decisionsDir = join33(ctx.rootDir, "decisions");
|
|
61939
62280
|
if (!existsSync41(decisionsDir)) return "001";
|
|
61940
62281
|
const existing = readdirSync9(decisionsDir).filter((f) => f.endsWith(".md")).map((f) => f.match(/^(\d+)-/)).filter((m) => !!m).map((m) => parseInt(m[1], 10));
|
|
61941
62282
|
const max = existing.length === 0 ? 0 : Math.max(...existing);
|
|
@@ -61981,7 +62322,7 @@ function addTaskRecord(ctx, summary, phaseId, t, options) {
|
|
|
61981
62322
|
// plan.json record (they already live in tags + the artifact body md).
|
|
61982
62323
|
files: t.fileRefs
|
|
61983
62324
|
});
|
|
61984
|
-
const taskPath =
|
|
62325
|
+
const taskPath = join33(ctx.rootDir, "plan-tasks", `${id3}.md`);
|
|
61985
62326
|
const meta3 = {
|
|
61986
62327
|
kind: "task",
|
|
61987
62328
|
id: id3,
|
|
@@ -62023,7 +62364,7 @@ function addMilestoneRecord(ctx, summary, input) {
|
|
|
62023
62364
|
dueDate: input.dueDate,
|
|
62024
62365
|
targetVersion: version2
|
|
62025
62366
|
});
|
|
62026
|
-
const
|
|
62367
|
+
const path103 = join33(ctx.rootDir, "milestones", `${id3}.md`);
|
|
62027
62368
|
const meta3 = {
|
|
62028
62369
|
kind: "milestone",
|
|
62029
62370
|
id: id3,
|
|
@@ -62040,7 +62381,7 @@ function addMilestoneRecord(ctx, summary, input) {
|
|
|
62040
62381
|
`Target version: ${version2}`,
|
|
62041
62382
|
""
|
|
62042
62383
|
].join("\n");
|
|
62043
|
-
ctx.storage.write(
|
|
62384
|
+
ctx.storage.write(path103, meta3, body);
|
|
62044
62385
|
return { id: id3, created: true };
|
|
62045
62386
|
}
|
|
62046
62387
|
function readPlanSummary(ctx) {
|
|
@@ -62244,7 +62585,7 @@ function addIdeaStub(ctx) {
|
|
|
62244
62585
|
const tags = args["tags"] ?? [];
|
|
62245
62586
|
const category = args["category"] ?? "General";
|
|
62246
62587
|
const id3 = `${nextAdrId(ctx)}-${slugify3(title)}`;
|
|
62247
|
-
const
|
|
62588
|
+
const path103 = workspaceArtifact(ctx.rootDir, "decisions", id3);
|
|
62248
62589
|
const meta3 = {
|
|
62249
62590
|
kind: "adr",
|
|
62250
62591
|
status: "proposed",
|
|
@@ -62270,7 +62611,7 @@ function addIdeaStub(ctx) {
|
|
|
62270
62611
|
...consequences.map((c) => `- ${c}`),
|
|
62271
62612
|
""
|
|
62272
62613
|
].join("\n");
|
|
62273
|
-
ctx.storage.write(
|
|
62614
|
+
ctx.storage.write(path103, meta3, body);
|
|
62274
62615
|
return `ADR ${id3} created: "${title}". Status: proposed. Promote to accepted via /update ADR or manual edit.`;
|
|
62275
62616
|
});
|
|
62276
62617
|
}
|
|
@@ -62321,7 +62662,7 @@ function createNfrSpecStub(ctx) {
|
|
|
62321
62662
|
},
|
|
62322
62663
|
planFeatureKeywords: Array.isArray(args["planFeatureKeywords"]) ? args["planFeatureKeywords"] : void 0
|
|
62323
62664
|
};
|
|
62324
|
-
const outPath =
|
|
62665
|
+
const outPath = join33(ctx.rootDir, "nfr-spec.json");
|
|
62325
62666
|
writeFileSync18(outPath, JSON.stringify(spec, null, 2), "utf8");
|
|
62326
62667
|
return `NFR spec written to nfr-spec.json (${targets.length} target(s)).`;
|
|
62327
62668
|
});
|
|
@@ -62352,14 +62693,14 @@ function createDocumentStub(ctx) {
|
|
|
62352
62693
|
ctx.storage.write(risksPath, riskMeta, content);
|
|
62353
62694
|
return `Document "${title}" created at risks.md (workspace root).`;
|
|
62354
62695
|
}
|
|
62355
|
-
const
|
|
62696
|
+
const path103 = workspaceArtifact(ctx.rootDir, "docs", slug);
|
|
62356
62697
|
const meta3 = {
|
|
62357
62698
|
kind: "doc",
|
|
62358
62699
|
id: slug,
|
|
62359
62700
|
date: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10),
|
|
62360
62701
|
tags
|
|
62361
62702
|
};
|
|
62362
|
-
ctx.storage.write(
|
|
62703
|
+
ctx.storage.write(path103, meta3, content);
|
|
62363
62704
|
return `Document "${title}" created at docs/${slug}.md.`;
|
|
62364
62705
|
});
|
|
62365
62706
|
}
|
|
@@ -62385,11 +62726,11 @@ function searchDocumentsStub(ctx) {
|
|
|
62385
62726
|
(w) => w.length >= 3 && w !== "or" && w !== "and" && w !== "the"
|
|
62386
62727
|
);
|
|
62387
62728
|
const files = [
|
|
62388
|
-
...ctx.storage.listMarkdown(
|
|
62389
|
-
...ctx.storage.listMarkdown(
|
|
62390
|
-
...ctx.storage.listMarkdown(
|
|
62391
|
-
...ctx.storage.listMarkdown(
|
|
62392
|
-
...ctx.storage.listMarkdown(
|
|
62729
|
+
...ctx.storage.listMarkdown(join33(ctx.rootDir, "decisions")),
|
|
62730
|
+
...ctx.storage.listMarkdown(join33(ctx.rootDir, "docs")),
|
|
62731
|
+
...ctx.storage.listMarkdown(join33(ctx.rootDir, "reviews")),
|
|
62732
|
+
...ctx.storage.listMarkdown(join33(ctx.rootDir, "plan-tasks")),
|
|
62733
|
+
...ctx.storage.listMarkdown(join33(ctx.rootDir, "milestones")),
|
|
62393
62734
|
workspaceFile(ctx.rootDir, "plan"),
|
|
62394
62735
|
workspaceFile(ctx.rootDir, "risks")
|
|
62395
62736
|
];
|
|
@@ -62447,9 +62788,9 @@ function linkDocumentsStub(ctx) {
|
|
|
62447
62788
|
const toId = args["toId"] ?? args["targetId"] ?? args["targetPathOrTitle"];
|
|
62448
62789
|
if (!fromId || !toId) return "linkDocuments requires fromId and toId.";
|
|
62449
62790
|
const allFiles = [
|
|
62450
|
-
...ctx.storage.listMarkdown(
|
|
62451
|
-
...ctx.storage.listMarkdown(
|
|
62452
|
-
...ctx.storage.listMarkdown(
|
|
62791
|
+
...ctx.storage.listMarkdown(join33(ctx.rootDir, "decisions")),
|
|
62792
|
+
...ctx.storage.listMarkdown(join33(ctx.rootDir, "docs")),
|
|
62793
|
+
...ctx.storage.listMarkdown(join33(ctx.rootDir, "reviews"))
|
|
62453
62794
|
];
|
|
62454
62795
|
const source2 = allFiles.find((f) => {
|
|
62455
62796
|
try {
|
|
@@ -62480,9 +62821,9 @@ function getDocumentBacklinksStub(ctx) {
|
|
|
62480
62821
|
const targetId = args["targetId"] ?? args["id"];
|
|
62481
62822
|
if (!targetId) return "getDocumentBacklinks requires targetId.";
|
|
62482
62823
|
const allFiles = [
|
|
62483
|
-
...ctx.storage.listMarkdown(
|
|
62484
|
-
...ctx.storage.listMarkdown(
|
|
62485
|
-
...ctx.storage.listMarkdown(
|
|
62824
|
+
...ctx.storage.listMarkdown(join33(ctx.rootDir, "decisions")),
|
|
62825
|
+
...ctx.storage.listMarkdown(join33(ctx.rootDir, "docs")),
|
|
62826
|
+
...ctx.storage.listMarkdown(join33(ctx.rootDir, "reviews"))
|
|
62486
62827
|
];
|
|
62487
62828
|
const backlinks = [];
|
|
62488
62829
|
for (const file2 of allFiles) {
|
|
@@ -62977,17 +63318,17 @@ import {
|
|
|
62977
63318
|
readFileSync as readFileSync30,
|
|
62978
63319
|
writeFileSync as writeFileSync19
|
|
62979
63320
|
} from "node:fs";
|
|
62980
|
-
import { dirname as
|
|
63321
|
+
import { dirname as dirname10, join as join34 } from "node:path";
|
|
62981
63322
|
function getUserMcpPath() {
|
|
62982
|
-
return
|
|
63323
|
+
return join34(zelariHome(), "mcp.json");
|
|
62983
63324
|
}
|
|
62984
63325
|
function getProjectMcpPath(projectRoot) {
|
|
62985
|
-
return
|
|
63326
|
+
return join34(projectRoot, ".zelari", "mcp.json");
|
|
62986
63327
|
}
|
|
62987
|
-
function readFile10(
|
|
62988
|
-
if (!existsSync42(
|
|
63328
|
+
function readFile10(path103) {
|
|
63329
|
+
if (!existsSync42(path103)) return {};
|
|
62989
63330
|
try {
|
|
62990
|
-
const parsed = JSON.parse(readFileSync30(
|
|
63331
|
+
const parsed = JSON.parse(readFileSync30(path103, "utf8"));
|
|
62991
63332
|
const out = {};
|
|
62992
63333
|
for (const [name, cfg] of Object.entries(parsed.mcpServers ?? {})) {
|
|
62993
63334
|
const hasCommand = !!cfg && typeof cfg.command === "string" && !!cfg.command.trim();
|
|
@@ -63009,10 +63350,10 @@ function readFile10(path102) {
|
|
|
63009
63350
|
return {};
|
|
63010
63351
|
}
|
|
63011
63352
|
}
|
|
63012
|
-
function writeFile4(
|
|
63013
|
-
mkdirSync17(
|
|
63353
|
+
function writeFile4(path103, servers) {
|
|
63354
|
+
mkdirSync17(dirname10(path103), { recursive: true });
|
|
63014
63355
|
const body = { mcpServers: servers };
|
|
63015
|
-
writeFileSync19(
|
|
63356
|
+
writeFileSync19(path103, `${JSON.stringify(body, null, 2)}
|
|
63016
63357
|
`, "utf8");
|
|
63017
63358
|
}
|
|
63018
63359
|
function listMcpServers(projectRoot) {
|
|
@@ -63050,9 +63391,9 @@ function upsertMcpServer(opts) {
|
|
|
63050
63391
|
error: "either command (stdio) or url (http) is required"
|
|
63051
63392
|
};
|
|
63052
63393
|
}
|
|
63053
|
-
let
|
|
63394
|
+
let path103;
|
|
63054
63395
|
if (opts.scope === "user") {
|
|
63055
|
-
|
|
63396
|
+
path103 = getUserMcpPath();
|
|
63056
63397
|
} else {
|
|
63057
63398
|
const root = opts.projectRoot?.trim();
|
|
63058
63399
|
if (!root) {
|
|
@@ -63061,9 +63402,9 @@ function upsertMcpServer(opts) {
|
|
|
63061
63402
|
error: "projectRoot required for project scope (Open Folder first)"
|
|
63062
63403
|
};
|
|
63063
63404
|
}
|
|
63064
|
-
|
|
63405
|
+
path103 = getProjectMcpPath(root);
|
|
63065
63406
|
}
|
|
63066
|
-
const current = readFile10(
|
|
63407
|
+
const current = readFile10(path103);
|
|
63067
63408
|
current[name] = {
|
|
63068
63409
|
command: hasCommand ? opts.config.command.trim() : void 0,
|
|
63069
63410
|
args: opts.config.args,
|
|
@@ -63074,21 +63415,21 @@ function upsertMcpServer(opts) {
|
|
|
63074
63415
|
serial: opts.config.serial,
|
|
63075
63416
|
enabled: opts.config.enabled !== false
|
|
63076
63417
|
};
|
|
63077
|
-
writeFile4(
|
|
63078
|
-
return { ok: true, path:
|
|
63418
|
+
writeFile4(path103, current);
|
|
63419
|
+
return { ok: true, path: path103 };
|
|
63079
63420
|
}
|
|
63080
63421
|
function removeMcpServer(opts) {
|
|
63081
|
-
const
|
|
63082
|
-
if (!
|
|
63422
|
+
const path103 = opts.scope === "user" ? getUserMcpPath() : opts.projectRoot ? getProjectMcpPath(opts.projectRoot) : null;
|
|
63423
|
+
if (!path103) {
|
|
63083
63424
|
return { ok: false, error: "projectRoot required for project scope" };
|
|
63084
63425
|
}
|
|
63085
|
-
const current = readFile10(
|
|
63426
|
+
const current = readFile10(path103);
|
|
63086
63427
|
if (!(opts.name in current)) {
|
|
63087
|
-
return { ok: false, error: `Server "${opts.name}" not found in ${
|
|
63428
|
+
return { ok: false, error: `Server "${opts.name}" not found in ${path103}` };
|
|
63088
63429
|
}
|
|
63089
63430
|
delete current[opts.name];
|
|
63090
|
-
writeFile4(
|
|
63091
|
-
return { ok: true, path:
|
|
63431
|
+
writeFile4(path103, current);
|
|
63432
|
+
return { ok: true, path: path103 };
|
|
63092
63433
|
}
|
|
63093
63434
|
var init_mcpConfigIo = __esm({
|
|
63094
63435
|
"src/cli/mcp/mcpConfigIo.ts"() {
|
|
@@ -63261,15 +63602,15 @@ __export(mcpManager_exports, {
|
|
|
63261
63602
|
registerMcpTools: () => registerMcpTools
|
|
63262
63603
|
});
|
|
63263
63604
|
import { existsSync as existsSync43, readFileSync as readFileSync31 } from "node:fs";
|
|
63264
|
-
import { join as
|
|
63605
|
+
import { join as join35 } from "node:path";
|
|
63265
63606
|
function readMcpConfig(projectRoot = process.cwd(), opts) {
|
|
63266
63607
|
const merged = {};
|
|
63267
63608
|
const paths = [];
|
|
63268
63609
|
if (process.env["ZELARI_MCP_USER"] !== "0") {
|
|
63269
|
-
paths.push(
|
|
63610
|
+
paths.push(join35(zelariHome(), "mcp.json"));
|
|
63270
63611
|
}
|
|
63271
63612
|
if (!opts?.skipProjectMcp) {
|
|
63272
|
-
paths.push(
|
|
63613
|
+
paths.push(join35(projectRoot, ".zelari", "mcp.json"));
|
|
63273
63614
|
}
|
|
63274
63615
|
for (const p3 of paths) {
|
|
63275
63616
|
if (!existsSync43(p3)) continue;
|
|
@@ -63290,7 +63631,7 @@ async function ensureLoaded(projectRoot) {
|
|
|
63290
63631
|
if (state2.loaded) return;
|
|
63291
63632
|
state2.loaded = true;
|
|
63292
63633
|
const trusted = isFolderTrusted(projectRoot);
|
|
63293
|
-
if (!trusted && existsSync43(
|
|
63634
|
+
if (!trusted && existsSync43(join35(projectRoot, ".zelari", "mcp.json"))) {
|
|
63294
63635
|
state2.warnings.push(
|
|
63295
63636
|
"[mcp] project .zelari/mcp.json ignored \u2014 folder not trusted (run /trust or `zelari-code --trust` to enable project MCP)"
|
|
63296
63637
|
);
|
|
@@ -63556,13 +63897,13 @@ __export(agentsMd_exports, {
|
|
|
63556
63897
|
});
|
|
63557
63898
|
import { existsSync as existsSync44, readFileSync as readFileSync32, writeFileSync as writeFileSync20 } from "node:fs";
|
|
63558
63899
|
import { createHash as createHash24 } from "node:crypto";
|
|
63559
|
-
import { join as
|
|
63900
|
+
import { join as join36 } from "node:path";
|
|
63560
63901
|
import { readFile as readFile11 } from "node:fs/promises";
|
|
63561
63902
|
async function readPackageJson3(projectRoot) {
|
|
63562
|
-
const
|
|
63563
|
-
if (!existsSync44(
|
|
63903
|
+
const path103 = join36(projectRoot, "package.json");
|
|
63904
|
+
if (!existsSync44(path103)) return null;
|
|
63564
63905
|
try {
|
|
63565
|
-
return JSON.parse(await readFile11(
|
|
63906
|
+
return JSON.parse(await readFile11(path103, "utf8"));
|
|
63566
63907
|
} catch {
|
|
63567
63908
|
return null;
|
|
63568
63909
|
}
|
|
@@ -63584,7 +63925,7 @@ async function genTechStack(ctx) {
|
|
|
63584
63925
|
].join("\n");
|
|
63585
63926
|
}
|
|
63586
63927
|
async function genDecisions(ctx) {
|
|
63587
|
-
const decisionsDir =
|
|
63928
|
+
const decisionsDir = join36(ctx.rootDir, "decisions");
|
|
63588
63929
|
if (!existsSync44(decisionsDir)) return "_No ADRs yet._";
|
|
63589
63930
|
const files = ctx.storage.listMarkdown(decisionsDir).sort();
|
|
63590
63931
|
const accepted = [];
|
|
@@ -63610,7 +63951,7 @@ async function genDecisions(ctx) {
|
|
|
63610
63951
|
}
|
|
63611
63952
|
async function genConventions(ctx) {
|
|
63612
63953
|
const lines = [];
|
|
63613
|
-
const claudeMd =
|
|
63954
|
+
const claudeMd = join36(ctx.projectRoot, "CLAUDE.MD");
|
|
63614
63955
|
if (existsSync44(claudeMd)) {
|
|
63615
63956
|
const content = readFileSync32(claudeMd, "utf8");
|
|
63616
63957
|
const match = content.match(/## Architecture rules[\s\S]+?(?=\n## |\n*$)/);
|
|
@@ -63644,9 +63985,9 @@ async function genBuild(ctx) {
|
|
|
63644
63985
|
].join("\n");
|
|
63645
63986
|
}
|
|
63646
63987
|
async function genOpenQuestions(ctx) {
|
|
63647
|
-
const
|
|
63648
|
-
if (!existsSync44(
|
|
63649
|
-
const content = readFileSync32(
|
|
63988
|
+
const path103 = join36(ctx.rootDir, "risks.md");
|
|
63989
|
+
if (!existsSync44(path103)) return "_No open questions._";
|
|
63990
|
+
const content = readFileSync32(path103, "utf8");
|
|
63650
63991
|
const lines = content.split("\n");
|
|
63651
63992
|
const questions = [];
|
|
63652
63993
|
let currentTitle = "";
|
|
@@ -63720,7 +64061,7 @@ function titleCase(id3) {
|
|
|
63720
64061
|
return id3.split("-").map((w) => w[0].toUpperCase() + w.slice(1)).join(" ");
|
|
63721
64062
|
}
|
|
63722
64063
|
async function updateAgentsMd(ctx, projectRoot) {
|
|
63723
|
-
const agentsPath =
|
|
64064
|
+
const agentsPath = join36(projectRoot, "AGENTS.MD");
|
|
63724
64065
|
if (existsSync44(agentsPath)) {
|
|
63725
64066
|
const content = readFileSync32(agentsPath, "utf8");
|
|
63726
64067
|
const hasAnyMarker = AUTO_SECTIONS.some((id3) => content.includes(MARKER_OPEN(id3)));
|
|
@@ -63892,11 +64233,11 @@ var init_completeDesign = __esm({
|
|
|
63892
64233
|
|
|
63893
64234
|
// src/cli/workspace/planDriftCheck.ts
|
|
63894
64235
|
import { existsSync as existsSync45, readFileSync as readFileSync33, readdirSync as readdirSync10, statSync as statSync6, writeFileSync as writeFileSync21 } from "node:fs";
|
|
63895
|
-
import { join as
|
|
64236
|
+
import { join as join37 } from "node:path";
|
|
63896
64237
|
function findCanonicalDoc(rootDir) {
|
|
63897
|
-
const docsDir =
|
|
64238
|
+
const docsDir = join37(rootDir, "docs");
|
|
63898
64239
|
if (!existsSync45(docsDir)) return null;
|
|
63899
|
-
const candidates = readdirSync10(docsDir).filter((f) => /^plan-canonical.*\.md$/i.test(f)).map((f) => ({ f, mtime: statSync6(
|
|
64240
|
+
const candidates = readdirSync10(docsDir).filter((f) => /^plan-canonical.*\.md$/i.test(f)).map((f) => ({ f, mtime: statSync6(join37(docsDir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
|
|
63900
64241
|
return candidates.length > 0 ? candidates[0].f : null;
|
|
63901
64242
|
}
|
|
63902
64243
|
function parseCanonicalDoc(text) {
|
|
@@ -63920,9 +64261,9 @@ function versionKey(value) {
|
|
|
63920
64261
|
function firstString2(v) {
|
|
63921
64262
|
return typeof v === "string" && v.trim().length > 0 ? v : null;
|
|
63922
64263
|
}
|
|
63923
|
-
function readFileSyncSafe(
|
|
64264
|
+
function readFileSyncSafe(path103) {
|
|
63924
64265
|
try {
|
|
63925
|
-
return readFileSync33(
|
|
64266
|
+
return readFileSync33(path103, "utf8");
|
|
63926
64267
|
} catch {
|
|
63927
64268
|
return null;
|
|
63928
64269
|
}
|
|
@@ -63931,7 +64272,7 @@ async function runPlanDriftCheck(rootDir) {
|
|
|
63931
64272
|
if (process.env["ZELARI_DRIFT_CHECK"] === "0") {
|
|
63932
64273
|
return { ran: false, reason: "ZELARI_DRIFT_CHECK=0 (disabled)" };
|
|
63933
64274
|
}
|
|
63934
|
-
const planPath =
|
|
64275
|
+
const planPath = join37(rootDir, "plan.json");
|
|
63935
64276
|
if (!existsSync45(planPath)) {
|
|
63936
64277
|
return { ran: false, reason: ".zelari/plan.json missing (not design-phase)" };
|
|
63937
64278
|
}
|
|
@@ -63947,7 +64288,7 @@ async function runPlanDriftCheck(rootDir) {
|
|
|
63947
64288
|
const milestones = Array.isArray(plan.milestones) ? plan.milestones : [];
|
|
63948
64289
|
const phaseIds = new Set(phases.map((p3) => typeof p3.id === "string" ? p3.id : "").filter(Boolean));
|
|
63949
64290
|
const canonicalName = findCanonicalDoc(rootDir);
|
|
63950
|
-
const canonicalText = canonicalName ? readFileSyncSafe(
|
|
64291
|
+
const canonicalText = canonicalName ? readFileSyncSafe(join37(rootDir, "docs", canonicalName)) : null;
|
|
63951
64292
|
if (canonicalText !== null) {
|
|
63952
64293
|
const { activePhases, blockedPrefixes } = parseCanonicalDoc(canonicalText);
|
|
63953
64294
|
for (const id3 of activePhases) {
|
|
@@ -64026,7 +64367,7 @@ async function runPlanDriftCheck(rootDir) {
|
|
|
64026
64367
|
const canonicalParsed = canonicalName !== null && canonicalText !== null;
|
|
64027
64368
|
let reportPath;
|
|
64028
64369
|
try {
|
|
64029
|
-
reportPath =
|
|
64370
|
+
reportPath = join37(rootDir, "drift-report.json");
|
|
64030
64371
|
writeFileSync21(
|
|
64031
64372
|
reportPath,
|
|
64032
64373
|
JSON.stringify(
|
|
@@ -64064,7 +64405,7 @@ var init_planDriftCheck = __esm({
|
|
|
64064
64405
|
// src/cli/workspace/projectSmoke.ts
|
|
64065
64406
|
import { spawn as spawn15 } from "node:child_process";
|
|
64066
64407
|
import { existsSync as existsSync46, readFileSync as readFileSync34 } from "node:fs";
|
|
64067
|
-
import { join as
|
|
64408
|
+
import { join as join38 } from "node:path";
|
|
64068
64409
|
function pickSmokeScript(scripts) {
|
|
64069
64410
|
if (!scripts) return null;
|
|
64070
64411
|
for (const name of SMOKE_SCRIPT_PRIORITY) {
|
|
@@ -64076,7 +64417,7 @@ async function runProjectSmoke(projectRoot, timeoutMs2 = DEFAULT_TIMEOUT_MS3) {
|
|
|
64076
64417
|
if (process.env["ZELARI_SMOKE"] === "0") {
|
|
64077
64418
|
return { ran: false, reason: "ZELARI_SMOKE=0 (disabled)" };
|
|
64078
64419
|
}
|
|
64079
|
-
const pkgPath =
|
|
64420
|
+
const pkgPath = join38(projectRoot, "package.json");
|
|
64080
64421
|
if (!existsSync46(pkgPath)) {
|
|
64081
64422
|
return { ran: false, reason: "no package.json (skipped)" };
|
|
64082
64423
|
}
|
|
@@ -64170,7 +64511,7 @@ __export(evidenceFromSpine_exports, {
|
|
|
64170
64511
|
evidenceRefsFromEventLines: () => evidenceRefsFromEventLines
|
|
64171
64512
|
});
|
|
64172
64513
|
import { existsSync as existsSync47, readFileSync as readFileSync35 } from "node:fs";
|
|
64173
|
-
import
|
|
64514
|
+
import path75 from "node:path";
|
|
64174
64515
|
function asRecord2(v) {
|
|
64175
64516
|
return v && typeof v === "object" && !Array.isArray(v) ? v : void 0;
|
|
64176
64517
|
}
|
|
@@ -64208,7 +64549,7 @@ function evidenceRefsFromEventLines(lines) {
|
|
|
64208
64549
|
}
|
|
64209
64550
|
function collectSessionEvidenceRefs(sessionId2) {
|
|
64210
64551
|
try {
|
|
64211
|
-
const file2 =
|
|
64552
|
+
const file2 = path75.join(sessionsDir(), sessionId2, "events.jsonl");
|
|
64212
64553
|
if (!existsSync47(file2)) return [];
|
|
64213
64554
|
return evidenceRefsFromEventLines(readFileSync35(file2, "utf8").split("\n"));
|
|
64214
64555
|
} catch {
|
|
@@ -64234,7 +64575,7 @@ __export(postCouncilHook_exports, {
|
|
|
64234
64575
|
});
|
|
64235
64576
|
import { spawn as spawn16 } from "node:child_process";
|
|
64236
64577
|
import { existsSync as existsSync48, readFileSync as readFileSync36 } from "node:fs";
|
|
64237
|
-
import { join as
|
|
64578
|
+
import { join as join39 } from "node:path";
|
|
64238
64579
|
async function runCompleteDesignPostProcessor(ctx, options) {
|
|
64239
64580
|
if (options?.runMode === "implementation") {
|
|
64240
64581
|
return {
|
|
@@ -64245,8 +64586,8 @@ async function runCompleteDesignPostProcessor(ctx, options) {
|
|
|
64245
64586
|
if (process.env["ZELARI_COMPLETE_DESIGN"] === "0") {
|
|
64246
64587
|
return { ran: false, reason: "ZELARI_COMPLETE_DESIGN=0 (disabled)" };
|
|
64247
64588
|
}
|
|
64248
|
-
const planJsonPath2 =
|
|
64249
|
-
const scriptPath =
|
|
64589
|
+
const planJsonPath2 = join39(ctx.rootDir, "plan.json");
|
|
64590
|
+
const scriptPath = join39(ctx.projectRoot, "complete-design.mjs");
|
|
64250
64591
|
if (!existsSync48(planJsonPath2)) {
|
|
64251
64592
|
return {
|
|
64252
64593
|
ran: false,
|
|
@@ -64458,8 +64799,8 @@ async function runPostCouncilHook(ctx, options) {
|
|
|
64458
64799
|
sources: scope.sources
|
|
64459
64800
|
} : void 0
|
|
64460
64801
|
});
|
|
64461
|
-
const
|
|
64462
|
-
completionHook = { ran: true, path:
|
|
64802
|
+
const path103 = writeCouncilCompletion(ctx.rootDir, completion);
|
|
64803
|
+
completionHook = { ran: true, path: path103, completion };
|
|
64463
64804
|
} catch (err) {
|
|
64464
64805
|
completionHook = {
|
|
64465
64806
|
ran: true,
|
|
@@ -64498,13 +64839,13 @@ __export(councilFeedback_exports, {
|
|
|
64498
64839
|
FeedbackStore: () => FeedbackStore
|
|
64499
64840
|
});
|
|
64500
64841
|
import {
|
|
64501
|
-
promises as
|
|
64842
|
+
promises as fs33,
|
|
64502
64843
|
existsSync as existsSync49,
|
|
64503
64844
|
readFileSync as readFileSync37,
|
|
64504
64845
|
writeFileSync as writeFileSync22,
|
|
64505
64846
|
mkdirSync as mkdirSync18
|
|
64506
64847
|
} from "node:fs";
|
|
64507
|
-
import
|
|
64848
|
+
import path76 from "node:path";
|
|
64508
64849
|
var FeedbackStore;
|
|
64509
64850
|
var init_councilFeedback = __esm({
|
|
64510
64851
|
"src/cli/councilFeedback.ts"() {
|
|
@@ -64621,7 +64962,7 @@ var init_councilFeedback = __esm({
|
|
|
64621
64962
|
}
|
|
64622
64963
|
}
|
|
64623
64964
|
save() {
|
|
64624
|
-
mkdirSync18(
|
|
64965
|
+
mkdirSync18(path76.dirname(this.file), { recursive: true });
|
|
64625
64966
|
writeFileSync22(
|
|
64626
64967
|
this.file,
|
|
64627
64968
|
JSON.stringify({ entries: this.entries }, null, 2),
|
|
@@ -64631,7 +64972,7 @@ var init_councilFeedback = __esm({
|
|
|
64631
64972
|
/** Async variant of load for callers that prefer async IO. */
|
|
64632
64973
|
async loadAsync() {
|
|
64633
64974
|
try {
|
|
64634
|
-
const raw = await
|
|
64975
|
+
const raw = await fs33.readFile(this.file, "utf-8");
|
|
64635
64976
|
const parsed = JSON.parse(raw);
|
|
64636
64977
|
if (parsed && Array.isArray(parsed.entries)) {
|
|
64637
64978
|
this.entries = parsed.entries.filter(
|
|
@@ -64696,12 +65037,12 @@ __export(ledger_exports, {
|
|
|
64696
65037
|
readLedger: () => readLedger
|
|
64697
65038
|
});
|
|
64698
65039
|
import { appendFileSync as appendFileSync4, existsSync as existsSync50, mkdirSync as mkdirSync19, readFileSync as readFileSync38 } from "node:fs";
|
|
64699
|
-
import
|
|
65040
|
+
import path77 from "node:path";
|
|
64700
65041
|
function evolutionMode(env = process.env) {
|
|
64701
65042
|
return env[EVOLUTION_ENV] === "shadow" ? "shadow" : "0";
|
|
64702
65043
|
}
|
|
64703
65044
|
function ledgerPath(cwd) {
|
|
64704
|
-
return
|
|
65045
|
+
return path77.join(cwd, LEDGER_REL);
|
|
64705
65046
|
}
|
|
64706
65047
|
function appendLedgerEntry(cwd, entry) {
|
|
64707
65048
|
if (evolutionMode() === "0") {
|
|
@@ -64709,7 +65050,7 @@ function appendLedgerEntry(cwd, entry) {
|
|
|
64709
65050
|
}
|
|
64710
65051
|
try {
|
|
64711
65052
|
const file2 = ledgerPath(cwd);
|
|
64712
|
-
mkdirSync19(
|
|
65053
|
+
mkdirSync19(path77.dirname(file2), { recursive: true });
|
|
64713
65054
|
appendFileSync4(file2, `${JSON.stringify(entry)}
|
|
64714
65055
|
`, "utf8");
|
|
64715
65056
|
return { written: true, path: file2 };
|
|
@@ -64810,7 +65151,7 @@ var init_ledger = __esm({
|
|
|
64810
65151
|
"src/cli/evolution/ledger.ts"() {
|
|
64811
65152
|
"use strict";
|
|
64812
65153
|
EVOLUTION_ENV = "ZELARI_EVOLUTION";
|
|
64813
|
-
LEDGER_REL =
|
|
65154
|
+
LEDGER_REL = path77.join(".zelari", "evolution", "ledger.jsonl");
|
|
64814
65155
|
TIER_WEIGHTS = {
|
|
64815
65156
|
build: 1,
|
|
64816
65157
|
"tool-output": 1,
|
|
@@ -64951,8 +65292,8 @@ __export(fileBackend_exports, {
|
|
|
64951
65292
|
isMemoryEnabled: () => isMemoryEnabled
|
|
64952
65293
|
});
|
|
64953
65294
|
import { randomUUID as randomUUID7 } from "node:crypto";
|
|
64954
|
-
import { promises as
|
|
64955
|
-
import * as
|
|
65295
|
+
import { promises as fs34 } from "node:fs";
|
|
65296
|
+
import * as path78 from "node:path";
|
|
64956
65297
|
function tokenize2(text) {
|
|
64957
65298
|
return text.toLowerCase().split(/[^\p{L}\p{N}]+/u).filter((t) => t.length >= 3);
|
|
64958
65299
|
}
|
|
@@ -65005,9 +65346,9 @@ var init_fileBackend = __esm({
|
|
|
65005
65346
|
logPath = "";
|
|
65006
65347
|
memoryDir = "";
|
|
65007
65348
|
async init(projectRoot) {
|
|
65008
|
-
this.memoryDir =
|
|
65009
|
-
this.logPath =
|
|
65010
|
-
await
|
|
65349
|
+
this.memoryDir = path78.join(projectRoot, ".zelari", "memory");
|
|
65350
|
+
this.logPath = path78.join(this.memoryDir, "log.jsonl");
|
|
65351
|
+
await fs34.mkdir(this.memoryDir, { recursive: true });
|
|
65011
65352
|
}
|
|
65012
65353
|
async add(content, metadata2 = {}, graph) {
|
|
65013
65354
|
const fact = {
|
|
@@ -65017,7 +65358,7 @@ var init_fileBackend = __esm({
|
|
|
65017
65358
|
...graph ? { graph } : {},
|
|
65018
65359
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
65019
65360
|
};
|
|
65020
|
-
await
|
|
65361
|
+
await fs34.appendFile(this.logPath, JSON.stringify(fact) + "\n", "utf8");
|
|
65021
65362
|
return fact.id;
|
|
65022
65363
|
}
|
|
65023
65364
|
async search(query, options = {}) {
|
|
@@ -65045,7 +65386,7 @@ var init_fileBackend = __esm({
|
|
|
65045
65386
|
async readAll() {
|
|
65046
65387
|
let raw;
|
|
65047
65388
|
try {
|
|
65048
|
-
raw = await
|
|
65389
|
+
raw = await fs34.readFile(this.logPath, "utf8");
|
|
65049
65390
|
} catch {
|
|
65050
65391
|
return [];
|
|
65051
65392
|
}
|
|
@@ -65078,23 +65419,23 @@ var init_fileBackend = __esm({
|
|
|
65078
65419
|
});
|
|
65079
65420
|
|
|
65080
65421
|
// src/cli/traceStore.ts
|
|
65081
|
-
import { promises as
|
|
65082
|
-
import * as
|
|
65422
|
+
import { promises as fs35 } from "node:fs";
|
|
65423
|
+
import * as path79 from "node:path";
|
|
65083
65424
|
function traceDir(projectRoot) {
|
|
65084
|
-
return
|
|
65425
|
+
return path79.join(projectRoot, ".zelari", "trace");
|
|
65085
65426
|
}
|
|
65086
65427
|
function tracePath(projectRoot, missionId) {
|
|
65087
|
-
return
|
|
65428
|
+
return path79.join(traceDir(projectRoot), `${missionId}.json`);
|
|
65088
65429
|
}
|
|
65089
65430
|
async function saveTrace(projectRoot, missionId, entries) {
|
|
65090
65431
|
const dir = traceDir(projectRoot);
|
|
65091
|
-
await
|
|
65432
|
+
await fs35.mkdir(dir, { recursive: true });
|
|
65092
65433
|
const payload = {
|
|
65093
65434
|
missionId,
|
|
65094
65435
|
ts: Date.now(),
|
|
65095
65436
|
entries
|
|
65096
65437
|
};
|
|
65097
|
-
await
|
|
65438
|
+
await fs35.writeFile(
|
|
65098
65439
|
tracePath(projectRoot, missionId),
|
|
65099
65440
|
JSON.stringify(payload, null, 2) + "\n",
|
|
65100
65441
|
"utf8"
|
|
@@ -65125,8 +65466,8 @@ __export(zelariMission_exports, {
|
|
|
65125
65466
|
runZelariMission: () => runZelariMission
|
|
65126
65467
|
});
|
|
65127
65468
|
import { randomUUID as randomUUID8 } from "node:crypto";
|
|
65128
|
-
import { promises as
|
|
65129
|
-
import * as
|
|
65469
|
+
import { promises as fs36 } from "node:fs";
|
|
65470
|
+
import * as path80 from "node:path";
|
|
65130
65471
|
function resolveMaxIterations(env = process.env) {
|
|
65131
65472
|
const raw = env.ZELARI_MISSION_MAX_ITER;
|
|
65132
65473
|
const n = raw ? Number.parseInt(raw, 10) : DEFAULT_MAX_ITER;
|
|
@@ -65169,10 +65510,10 @@ function isMissionAutoStart(env = process.env) {
|
|
|
65169
65510
|
return env.ZELARI_MISSION_AUTO === "1";
|
|
65170
65511
|
}
|
|
65171
65512
|
async function writeMissionState(projectRoot, state3) {
|
|
65172
|
-
const dir =
|
|
65173
|
-
await
|
|
65174
|
-
await
|
|
65175
|
-
|
|
65513
|
+
const dir = path80.join(projectRoot, ".zelari");
|
|
65514
|
+
await fs36.mkdir(dir, { recursive: true });
|
|
65515
|
+
await fs36.writeFile(
|
|
65516
|
+
path80.join(dir, "mission-state.json"),
|
|
65176
65517
|
JSON.stringify(state3, null, 2) + "\n",
|
|
65177
65518
|
"utf8"
|
|
65178
65519
|
);
|
|
@@ -65185,8 +65526,8 @@ async function writeMissionState(projectRoot, state3) {
|
|
|
65185
65526
|
}
|
|
65186
65527
|
async function loadMissionState(projectRoot) {
|
|
65187
65528
|
try {
|
|
65188
|
-
const raw = await
|
|
65189
|
-
|
|
65529
|
+
const raw = await fs36.readFile(
|
|
65530
|
+
path80.join(projectRoot, ".zelari", "mission-state.json"),
|
|
65190
65531
|
"utf8"
|
|
65191
65532
|
);
|
|
65192
65533
|
const parsed = JSON.parse(raw);
|
|
@@ -65945,7 +66286,7 @@ function safeSocketPath(socketPath) {
|
|
|
65945
66286
|
return socketPath.trim();
|
|
65946
66287
|
}
|
|
65947
66288
|
function startPermissionBroker(socketPath, handlers, opts) {
|
|
65948
|
-
const
|
|
66289
|
+
const path103 = safeSocketPath(socketPath);
|
|
65949
66290
|
const requestTimeoutMs = opts?.requestTimeoutMs ?? PERMISSION_BROKER_DEFAULT_TIMEOUT_MS;
|
|
65950
66291
|
const sockets = /* @__PURE__ */ new Set();
|
|
65951
66292
|
const server = createServer2((socket) => {
|
|
@@ -66045,10 +66386,10 @@ function startPermissionBroker(socketPath, handlers, opts) {
|
|
|
66045
66386
|
return new Promise((resolve9, reject) => {
|
|
66046
66387
|
const onError = (err) => reject(err);
|
|
66047
66388
|
server.once("error", onError);
|
|
66048
|
-
server.listen(
|
|
66389
|
+
server.listen(path103, () => {
|
|
66049
66390
|
server.removeListener("error", onError);
|
|
66050
66391
|
resolve9({
|
|
66051
|
-
socketPath:
|
|
66392
|
+
socketPath: path103,
|
|
66052
66393
|
stop: () => new Promise((res) => {
|
|
66053
66394
|
for (const s of sockets) s.destroy();
|
|
66054
66395
|
sockets.clear();
|
|
@@ -66059,7 +66400,7 @@ function startPermissionBroker(socketPath, handlers, opts) {
|
|
|
66059
66400
|
if (done) return;
|
|
66060
66401
|
done = true;
|
|
66061
66402
|
if (process.platform !== "win32") {
|
|
66062
|
-
unlink(
|
|
66403
|
+
unlink(path103, () => res());
|
|
66063
66404
|
} else {
|
|
66064
66405
|
res();
|
|
66065
66406
|
}
|
|
@@ -66072,11 +66413,11 @@ function startPermissionBroker(socketPath, handlers, opts) {
|
|
|
66072
66413
|
});
|
|
66073
66414
|
}
|
|
66074
66415
|
function requestBrokerAsk(socketPath, ask, opts) {
|
|
66075
|
-
const
|
|
66416
|
+
const path103 = safeSocketPath(socketPath);
|
|
66076
66417
|
const requestTimeoutMs = opts?.requestTimeoutMs ?? PERMISSION_BROKER_DEFAULT_TIMEOUT_MS;
|
|
66077
66418
|
const connectTimeoutMs = opts?.connectTimeoutMs ?? PERMISSION_BROKER_DEFAULT_CONNECT_TIMEOUT_MS;
|
|
66078
66419
|
return new Promise((resolve9, reject) => {
|
|
66079
|
-
const socket = connect(
|
|
66420
|
+
const socket = connect(path103);
|
|
66080
66421
|
let buffer = "";
|
|
66081
66422
|
let settled = false;
|
|
66082
66423
|
const settle = (fn) => {
|
|
@@ -66091,7 +66432,7 @@ function requestBrokerAsk(socketPath, ask, opts) {
|
|
|
66091
66432
|
settle(
|
|
66092
66433
|
() => reject(
|
|
66093
66434
|
new Error(
|
|
66094
|
-
`permission broker unavailable at "${
|
|
66435
|
+
`permission broker unavailable at "${path103}" (connect timed out after ${connectTimeoutMs}ms)`
|
|
66095
66436
|
)
|
|
66096
66437
|
)
|
|
66097
66438
|
);
|
|
@@ -66909,7 +67250,7 @@ __export(prereqChecks_exports, {
|
|
|
66909
67250
|
});
|
|
66910
67251
|
import { execSync, spawnSync as spawnSync2 } from "node:child_process";
|
|
66911
67252
|
import { existsSync as existsSync52 } from "node:fs";
|
|
66912
|
-
import { dirname as
|
|
67253
|
+
import { dirname as dirname12 } from "node:path";
|
|
66913
67254
|
function isWslBashPath2(p3) {
|
|
66914
67255
|
if (!p3 || typeof p3 !== "string") return false;
|
|
66915
67256
|
const n = p3.replace(/\//g, "\\").toLowerCase();
|
|
@@ -67015,7 +67356,7 @@ function resolveAgentShellSync() {
|
|
|
67015
67356
|
function agentProbeEnv() {
|
|
67016
67357
|
const env = { ...process.env };
|
|
67017
67358
|
try {
|
|
67018
|
-
const nodeDir =
|
|
67359
|
+
const nodeDir = dirname12(process.execPath);
|
|
67019
67360
|
if (!nodeDir) return env;
|
|
67020
67361
|
const sep4 = process.platform === "win32" ? ";" : ":";
|
|
67021
67362
|
const current = env.PATH ?? env.Path ?? "";
|
|
@@ -67280,7 +67621,7 @@ var init_prereqChecks = __esm({
|
|
|
67280
67621
|
|
|
67281
67622
|
// src/cli/plugins/prefs.ts
|
|
67282
67623
|
import { existsSync as existsSync53, readFileSync as readFileSync40, writeFileSync as writeFileSync23, mkdirSync as mkdirSync20 } from "node:fs";
|
|
67283
|
-
import
|
|
67624
|
+
import path85 from "node:path";
|
|
67284
67625
|
function getPluginPrefsPath() {
|
|
67285
67626
|
return pluginsPrefsPath();
|
|
67286
67627
|
}
|
|
@@ -67303,7 +67644,7 @@ function getPluginPrefs() {
|
|
|
67303
67644
|
}
|
|
67304
67645
|
function writePluginPrefs(prefs) {
|
|
67305
67646
|
const file2 = getPluginPrefsPath();
|
|
67306
|
-
mkdirSync20(
|
|
67647
|
+
mkdirSync20(path85.dirname(file2), { recursive: true });
|
|
67307
67648
|
writeFileSync23(file2, JSON.stringify(prefs, null, 2), {
|
|
67308
67649
|
encoding: "utf-8",
|
|
67309
67650
|
mode: 384
|
|
@@ -67341,7 +67682,7 @@ __export(registry_exports, {
|
|
|
67341
67682
|
isBinaryOnPath: () => isBinaryOnPath
|
|
67342
67683
|
});
|
|
67343
67684
|
import { existsSync as existsSync54 } from "node:fs";
|
|
67344
|
-
import
|
|
67685
|
+
import path86 from "node:path";
|
|
67345
67686
|
function detectLocalBin(bin) {
|
|
67346
67687
|
return (cwd) => {
|
|
67347
67688
|
try {
|
|
@@ -67359,7 +67700,7 @@ function isBinaryOnPath(bin, opts = {}) {
|
|
|
67359
67700
|
const platform = opts.platform ?? process.platform;
|
|
67360
67701
|
const exists = opts.exists ?? existsSync54;
|
|
67361
67702
|
const pathEnv = opts.pathEnv ?? process.env.PATH ?? "";
|
|
67362
|
-
const pathMod = platform === "win32" ?
|
|
67703
|
+
const pathMod = platform === "win32" ? path86.win32 : path86.posix;
|
|
67363
67704
|
const sep4 = platform === "win32" ? ";" : ":";
|
|
67364
67705
|
const dirs = pathEnv.split(sep4).filter((d) => d.length > 0);
|
|
67365
67706
|
const candidates = [bin];
|
|
@@ -68463,11 +68804,11 @@ var init_policy = __esm({
|
|
|
68463
68804
|
});
|
|
68464
68805
|
|
|
68465
68806
|
// src/cli/orchestration/facts.ts
|
|
68466
|
-
import { promises as
|
|
68467
|
-
import
|
|
68807
|
+
import { promises as fs45 } from "node:fs";
|
|
68808
|
+
import path90 from "node:path";
|
|
68468
68809
|
async function collectRepoFileCount(root = process.cwd()) {
|
|
68469
68810
|
try {
|
|
68470
|
-
await
|
|
68811
|
+
await fs45.readdir(root);
|
|
68471
68812
|
} catch {
|
|
68472
68813
|
return void 0;
|
|
68473
68814
|
}
|
|
@@ -68478,13 +68819,13 @@ async function collectRepoFileCount(root = process.cwd()) {
|
|
|
68478
68819
|
const dir = queue.pop();
|
|
68479
68820
|
let entries;
|
|
68480
68821
|
try {
|
|
68481
|
-
entries = await
|
|
68822
|
+
entries = await fs45.readdir(dir, { withFileTypes: true });
|
|
68482
68823
|
} catch {
|
|
68483
68824
|
continue;
|
|
68484
68825
|
}
|
|
68485
68826
|
for (const e of entries) {
|
|
68486
68827
|
if (e.isDirectory()) {
|
|
68487
|
-
if (!SKIP_DIRS.has(e.name)) queue.push(
|
|
68828
|
+
if (!SKIP_DIRS.has(e.name)) queue.push(path90.join(dir, e.name));
|
|
68488
68829
|
} else if (e.isFile()) {
|
|
68489
68830
|
count++;
|
|
68490
68831
|
if (count > MAX_WALK_FILES) return count;
|
|
@@ -68582,7 +68923,7 @@ var init_streamScrub = __esm({
|
|
|
68582
68923
|
});
|
|
68583
68924
|
|
|
68584
68925
|
// src/cli/harnessState.ts
|
|
68585
|
-
import
|
|
68926
|
+
import path91 from "node:path";
|
|
68586
68927
|
function asString4(v) {
|
|
68587
68928
|
return typeof v === "string" ? v : "";
|
|
68588
68929
|
}
|
|
@@ -68757,7 +69098,7 @@ function contractFor(t) {
|
|
|
68757
69098
|
};
|
|
68758
69099
|
}
|
|
68759
69100
|
async function readHarnessState(sessionDir, cache4) {
|
|
68760
|
-
const report = await readSessionLogCached(
|
|
69101
|
+
const report = await readSessionLogCached(path91.join(sessionDir, "events.jsonl"), cache4);
|
|
68761
69102
|
return deriveHarnessState(report.events);
|
|
68762
69103
|
}
|
|
68763
69104
|
var init_harnessState = __esm({
|
|
@@ -68768,12 +69109,12 @@ var init_harnessState = __esm({
|
|
|
68768
69109
|
});
|
|
68769
69110
|
|
|
68770
69111
|
// src/cli/headless/harnessStateEmit.ts
|
|
68771
|
-
import
|
|
69112
|
+
import path92 from "node:path";
|
|
68772
69113
|
async function emitHarnessStateEvent(opts) {
|
|
68773
69114
|
if (opts.output !== "json") return;
|
|
68774
69115
|
try {
|
|
68775
69116
|
const sessionsDir2 = resolveSessionsDir({ workspaceRoot: opts.workspaceRoot });
|
|
68776
|
-
const state3 = await readHarnessState(
|
|
69117
|
+
const state3 = await readHarnessState(path92.join(sessionsDir2, opts.spine.sessionId));
|
|
68777
69118
|
opts.emitEvent({ type: "harness_state", ...state3 });
|
|
68778
69119
|
} catch (err) {
|
|
68779
69120
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -69330,13 +69671,13 @@ var init_verifierLifecycle = __esm({
|
|
|
69330
69671
|
|
|
69331
69672
|
// src/cli/extensions/sandboxedFs.ts
|
|
69332
69673
|
import { promises as fsp } from "node:fs";
|
|
69333
|
-
import
|
|
69674
|
+
import path93 from "node:path";
|
|
69334
69675
|
function errText(prefix, p3, err) {
|
|
69335
69676
|
const msg = err instanceof Error ? err.message : String(err);
|
|
69336
69677
|
return `[extension-fs] ${prefix} "${p3}": ${msg}`;
|
|
69337
69678
|
}
|
|
69338
69679
|
function bindSandboxedFs(root) {
|
|
69339
|
-
const resolvedRoot =
|
|
69680
|
+
const resolvedRoot = path93.resolve(root);
|
|
69340
69681
|
return {
|
|
69341
69682
|
root: resolvedRoot,
|
|
69342
69683
|
async readFile(relativePath) {
|
|
@@ -69352,7 +69693,7 @@ function bindSandboxedFs(root) {
|
|
|
69352
69693
|
try {
|
|
69353
69694
|
const target = resolveSandboxedPath(relativePath, { root: resolvedRoot });
|
|
69354
69695
|
verifyContainment(target, { root: resolvedRoot });
|
|
69355
|
-
await fsp.mkdir(
|
|
69696
|
+
await fsp.mkdir(path93.dirname(target), { recursive: true });
|
|
69356
69697
|
await fsp.writeFile(target, data, "utf8");
|
|
69357
69698
|
return typedOk({ path: target });
|
|
69358
69699
|
} catch (err) {
|
|
@@ -69379,15 +69720,15 @@ var init_sandboxedFs = __esm({
|
|
|
69379
69720
|
});
|
|
69380
69721
|
|
|
69381
69722
|
// src/cli/extensions/loader.ts
|
|
69382
|
-
import { join as
|
|
69723
|
+
import { join as join45 } from "node:path";
|
|
69383
69724
|
import { readdirSync as readdirSync11, readFileSync as readFileSync43 } from "node:fs";
|
|
69384
69725
|
import { createHash as createHash25 } from "node:crypto";
|
|
69385
69726
|
import { pathToFileURL as pathToFileURL3 } from "node:url";
|
|
69386
69727
|
function globalExtensionsDir() {
|
|
69387
|
-
return
|
|
69728
|
+
return join45(zelariHome(), "extensions");
|
|
69388
69729
|
}
|
|
69389
69730
|
function projectExtensionsDir(projectRoot) {
|
|
69390
|
-
return
|
|
69731
|
+
return join45(projectRoot, ".zelari", "extensions");
|
|
69391
69732
|
}
|
|
69392
69733
|
function sha256File(file2) {
|
|
69393
69734
|
return createHash25("sha256").update(readFileSync43(file2)).digest("hex");
|
|
@@ -69399,7 +69740,7 @@ function candidateFiles(dir) {
|
|
|
69399
69740
|
} catch {
|
|
69400
69741
|
return [];
|
|
69401
69742
|
}
|
|
69402
|
-
return names.filter((n) => EXTENSION_FILE_EXTS.has(n.slice(n.lastIndexOf(".")).toLowerCase())).sort().map((n) =>
|
|
69743
|
+
return names.filter((n) => EXTENSION_FILE_EXTS.has(n.slice(n.lastIndexOf(".")).toLowerCase())).sort().map((n) => join45(dir, n));
|
|
69403
69744
|
}
|
|
69404
69745
|
function extractExtension(mod) {
|
|
69405
69746
|
const m = mod;
|
|
@@ -69421,14 +69762,14 @@ async function loadExtensionsFromDirs(dirs, options = {}) {
|
|
|
69421
69762
|
skipped
|
|
69422
69763
|
};
|
|
69423
69764
|
const fsRoot = options.fsRoot ?? process.cwd();
|
|
69424
|
-
let
|
|
69765
|
+
let fs50 = null;
|
|
69425
69766
|
const pending = [];
|
|
69426
69767
|
for (const dir of dirs) {
|
|
69427
69768
|
const files = candidateFiles(dir.path);
|
|
69428
69769
|
if (files.length === 0) continue;
|
|
69429
69770
|
let lock = null;
|
|
69430
69771
|
try {
|
|
69431
|
-
lock = JSON.parse(readFileSync43(
|
|
69772
|
+
lock = JSON.parse(readFileSync43(join45(dir.path, EXTENSIONS_LOCK_FILE), "utf8"));
|
|
69432
69773
|
} catch {
|
|
69433
69774
|
lock = null;
|
|
69434
69775
|
if (dirHasLockFile(dir.path)) {
|
|
@@ -69476,9 +69817,9 @@ async function loadExtensionsFromDirs(dirs, options = {}) {
|
|
|
69476
69817
|
skipped.push(`${file2}: missing ZelariExtension export`);
|
|
69477
69818
|
continue;
|
|
69478
69819
|
}
|
|
69479
|
-
if (!
|
|
69820
|
+
if (!fs50) fs50 = bindSandboxedFs(fsRoot);
|
|
69480
69821
|
try {
|
|
69481
|
-
await runtime.registry.registerExtension(ext, { fs:
|
|
69822
|
+
await runtime.registry.registerExtension(ext, { fs: fs50 });
|
|
69482
69823
|
runtime.loaded.push({ id: ext.id, file: file2, scope });
|
|
69483
69824
|
} catch (err) {
|
|
69484
69825
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -69495,7 +69836,7 @@ function basenameOf(file2) {
|
|
|
69495
69836
|
}
|
|
69496
69837
|
function dirHasLockFile(dir) {
|
|
69497
69838
|
try {
|
|
69498
|
-
readFileSync43(
|
|
69839
|
+
readFileSync43(join45(dir, EXTENSIONS_LOCK_FILE));
|
|
69499
69840
|
return true;
|
|
69500
69841
|
} catch {
|
|
69501
69842
|
return false;
|
|
@@ -69536,8 +69877,8 @@ var init_loader = __esm({
|
|
|
69536
69877
|
});
|
|
69537
69878
|
|
|
69538
69879
|
// src/cli/headless/runOneTurn.ts
|
|
69539
|
-
import { promises as
|
|
69540
|
-
import
|
|
69880
|
+
import { promises as fs46 } from "node:fs";
|
|
69881
|
+
import path94 from "node:path";
|
|
69541
69882
|
function planModeFromOpts(opts) {
|
|
69542
69883
|
return (opts.phase ?? "build") === "plan";
|
|
69543
69884
|
}
|
|
@@ -69590,7 +69931,18 @@ async function writeProofSafe(gate, meta3, baseDir = process.cwd()) {
|
|
|
69590
69931
|
`
|
|
69591
69932
|
);
|
|
69592
69933
|
}
|
|
69593
|
-
|
|
69934
|
+
return promoteOpsKnowledgeSafe(gate, { projectRoot: baseDir, sessionId: meta3.sessionId });
|
|
69935
|
+
}
|
|
69936
|
+
function surfaceOpsKnowledgeNotices(result, opts) {
|
|
69937
|
+
const notices = [
|
|
69938
|
+
...result.proposals,
|
|
69939
|
+
...result.checkProposals.map(formatCheckProposalNotice)
|
|
69940
|
+
];
|
|
69941
|
+
for (const notice of notices) {
|
|
69942
|
+
if (opts.output === "json") emitEvent({ type: "log", message: notice });
|
|
69943
|
+
else process.stderr.write(`[zelari-code --headless] ${notice}
|
|
69944
|
+
`);
|
|
69945
|
+
}
|
|
69594
69946
|
}
|
|
69595
69947
|
async function runOneTurn(opts, provider, model, providerStream, extras) {
|
|
69596
69948
|
const sessionId2 = crypto.randomUUID();
|
|
@@ -70031,7 +70383,10 @@ async function runOneTurn(opts, provider, model, providerStream, extras) {
|
|
|
70031
70383
|
if (opts.output === "json") {
|
|
70032
70384
|
emitEvent({ type: "verification_run", ...verificationPayload });
|
|
70033
70385
|
}
|
|
70034
|
-
|
|
70386
|
+
surfaceOpsKnowledgeNotices(
|
|
70387
|
+
await writeProofSafe(strictGate, { surface: "kraken", sessionId: spine.sessionId }, cwd),
|
|
70388
|
+
opts
|
|
70389
|
+
);
|
|
70035
70390
|
if (strictGate.blocked) {
|
|
70036
70391
|
const repairPrompt = buildKrakenRepairPrompt(gate, repairExcerptsFromEvaluation(strictGate));
|
|
70037
70392
|
if (opts.output === "json") {
|
|
@@ -70065,7 +70420,10 @@ async function runOneTurn(opts, provider, model, providerStream, extras) {
|
|
|
70065
70420
|
if (opts.output === "json") {
|
|
70066
70421
|
emitEvent({ type: "verification_run", ...afterPayload });
|
|
70067
70422
|
}
|
|
70068
|
-
|
|
70423
|
+
surfaceOpsKnowledgeNotices(
|
|
70424
|
+
await writeProofSafe(after, { surface: "kraken", sessionId: spine.sessionId }, cwd),
|
|
70425
|
+
opts
|
|
70426
|
+
);
|
|
70069
70427
|
if (!after.blocked) markRepairSucceeded();
|
|
70070
70428
|
else {
|
|
70071
70429
|
strictExit = strictGateExitCode(after);
|
|
@@ -70108,8 +70466,8 @@ async function runOneTurn(opts, provider, model, providerStream, extras) {
|
|
|
70108
70466
|
if (json3) {
|
|
70109
70467
|
if (opts.exportSessionPath === "-") process.stdout.write(json3 + "\n");
|
|
70110
70468
|
else {
|
|
70111
|
-
await
|
|
70112
|
-
await
|
|
70469
|
+
await fs46.mkdir(path94.dirname(opts.exportSessionPath), { recursive: true }).catch(() => void 0);
|
|
70470
|
+
await fs46.writeFile(opts.exportSessionPath, json3, "utf8");
|
|
70113
70471
|
}
|
|
70114
70472
|
}
|
|
70115
70473
|
} catch {
|
|
@@ -70175,6 +70533,7 @@ var init_runOneTurn = __esm({
|
|
|
70175
70533
|
init_completionProof();
|
|
70176
70534
|
init_completionProofPersist();
|
|
70177
70535
|
init_opsKnowledge();
|
|
70536
|
+
init_repeatCheck();
|
|
70178
70537
|
init_nativeVerification();
|
|
70179
70538
|
init_verifierLifecycle();
|
|
70180
70539
|
init_modelContextBuilder();
|
|
@@ -71157,10 +71516,10 @@ __export(triggerLock_exports, {
|
|
|
71157
71516
|
lockPath: () => lockPath,
|
|
71158
71517
|
releaseLock: () => releaseLock
|
|
71159
71518
|
});
|
|
71160
|
-
import { promises as
|
|
71161
|
-
import * as
|
|
71519
|
+
import { promises as fs47 } from "node:fs";
|
|
71520
|
+
import * as path95 from "node:path";
|
|
71162
71521
|
function lockPath(projectRoot) {
|
|
71163
|
-
return
|
|
71522
|
+
return path95.join(projectRoot, ".zelari", "trigger.lock");
|
|
71164
71523
|
}
|
|
71165
71524
|
function isPidAlive(pid) {
|
|
71166
71525
|
try {
|
|
@@ -71173,10 +71532,10 @@ function isPidAlive(pid) {
|
|
|
71173
71532
|
}
|
|
71174
71533
|
async function acquireLock(projectRoot, now = () => /* @__PURE__ */ new Date()) {
|
|
71175
71534
|
const lp = lockPath(projectRoot);
|
|
71176
|
-
const dir =
|
|
71177
|
-
await
|
|
71535
|
+
const dir = path95.dirname(lp);
|
|
71536
|
+
await fs47.mkdir(dir, { recursive: true });
|
|
71178
71537
|
try {
|
|
71179
|
-
const raw = await
|
|
71538
|
+
const raw = await fs47.readFile(lp, "utf8");
|
|
71180
71539
|
const existing = JSON.parse(raw);
|
|
71181
71540
|
if (existing.pid && isPidAlive(existing.pid)) {
|
|
71182
71541
|
return { acquired: false, heldBy: existing.pid, lockPath: lp };
|
|
@@ -71187,13 +71546,13 @@ async function acquireLock(projectRoot, now = () => /* @__PURE__ */ new Date())
|
|
|
71187
71546
|
pid: process.pid,
|
|
71188
71547
|
acquiredAt: now().toISOString()
|
|
71189
71548
|
};
|
|
71190
|
-
await
|
|
71549
|
+
await fs47.writeFile(lp, JSON.stringify(payload, null, 2) + "\n", "utf8");
|
|
71191
71550
|
return { acquired: true, lockPath: lp };
|
|
71192
71551
|
}
|
|
71193
71552
|
async function releaseLock(projectRoot) {
|
|
71194
71553
|
const lp = lockPath(projectRoot);
|
|
71195
71554
|
try {
|
|
71196
|
-
await
|
|
71555
|
+
await fs47.unlink(lp);
|
|
71197
71556
|
} catch {
|
|
71198
71557
|
}
|
|
71199
71558
|
}
|
|
@@ -71204,8 +71563,8 @@ var init_triggerLock = __esm({
|
|
|
71204
71563
|
});
|
|
71205
71564
|
|
|
71206
71565
|
// src/cli/runHeadless.ts
|
|
71207
|
-
import { promises as
|
|
71208
|
-
import
|
|
71566
|
+
import { promises as fs48 } from "node:fs";
|
|
71567
|
+
import path96 from "node:path";
|
|
71209
71568
|
import { randomUUID as randomUUID10 } from "node:crypto";
|
|
71210
71569
|
async function runHeadless(opts) {
|
|
71211
71570
|
resetTaskSpawnCount();
|
|
@@ -71479,11 +71838,11 @@ async function runHeadlessKrakenGraph(opts, provider, model) {
|
|
|
71479
71838
|
try {
|
|
71480
71839
|
let preflightGraph;
|
|
71481
71840
|
if (opts.runPlan && opts.runPlan.trim() !== "") {
|
|
71482
|
-
const planPath =
|
|
71841
|
+
const planPath = path96.join(cwd, ".zelari", "radio", `plan-${opts.runPlan}.json`);
|
|
71483
71842
|
log(`loading pre-flight plan: ${planPath}`);
|
|
71484
71843
|
let raw;
|
|
71485
71844
|
try {
|
|
71486
|
-
raw = await
|
|
71845
|
+
raw = await fs48.readFile(planPath, "utf8");
|
|
71487
71846
|
} catch (e) {
|
|
71488
71847
|
log(`plan file not found: ${planPath} (${e.message})`);
|
|
71489
71848
|
exitCode = 1;
|
|
@@ -71522,10 +71881,10 @@ async function runHeadlessKrakenGraph(opts, provider, model) {
|
|
|
71522
71881
|
log(formatKrakenGraphAscii2(graph));
|
|
71523
71882
|
if (opts.planOnly) {
|
|
71524
71883
|
const planId = randomUUID10();
|
|
71525
|
-
const planDir =
|
|
71526
|
-
const planPath =
|
|
71527
|
-
await
|
|
71528
|
-
await
|
|
71884
|
+
const planDir = path96.join(cwd, ".zelari", "radio");
|
|
71885
|
+
const planPath = path96.join(planDir, `plan-${planId}.json`);
|
|
71886
|
+
await fs48.mkdir(planDir, { recursive: true });
|
|
71887
|
+
await fs48.writeFile(
|
|
71529
71888
|
planPath,
|
|
71530
71889
|
JSON.stringify(
|
|
71531
71890
|
{ id: graph.id, nodes: [...graph.nodes.values()] },
|
|
@@ -71914,8 +72273,8 @@ async function runHeadlessCouncilBody(opts, provider, model, providerStream, ext
|
|
|
71914
72273
|
if (json3) {
|
|
71915
72274
|
if (opts.exportSessionPath === "-") process.stdout.write(json3 + "\n");
|
|
71916
72275
|
else {
|
|
71917
|
-
await
|
|
71918
|
-
await
|
|
72276
|
+
await fs48.mkdir(path96.dirname(opts.exportSessionPath), { recursive: true }).catch(() => void 0);
|
|
72277
|
+
await fs48.writeFile(opts.exportSessionPath, json3, "utf8");
|
|
71919
72278
|
}
|
|
71920
72279
|
}
|
|
71921
72280
|
} catch {
|
|
@@ -72386,8 +72745,8 @@ ${ragContext}` : slicePrompt;
|
|
|
72386
72745
|
if (json3) {
|
|
72387
72746
|
if (opts.exportSessionPath === "-") process.stdout.write(json3 + "\n");
|
|
72388
72747
|
else {
|
|
72389
|
-
await
|
|
72390
|
-
await
|
|
72748
|
+
await fs48.mkdir(path96.dirname(opts.exportSessionPath), { recursive: true }).catch(() => void 0);
|
|
72749
|
+
await fs48.writeFile(opts.exportSessionPath, json3, "utf8");
|
|
72391
72750
|
}
|
|
72392
72751
|
}
|
|
72393
72752
|
} catch {
|
|
@@ -72850,7 +73209,7 @@ import {
|
|
|
72850
73209
|
rmSync as rmSync4,
|
|
72851
73210
|
writeFileSync as writeFileSync25
|
|
72852
73211
|
} from "node:fs";
|
|
72853
|
-
import { dirname as
|
|
73212
|
+
import { dirname as dirname14, join as join47 } from "node:path";
|
|
72854
73213
|
function ensureBuiltinSkillsLoadedSync() {
|
|
72855
73214
|
if (builtinsLoaded) return;
|
|
72856
73215
|
for (const spec of BUILTIN_SKILL_MODULES) {
|
|
@@ -72861,13 +73220,13 @@ function ensureBuiltinSkillsLoadedSync() {
|
|
|
72861
73220
|
}
|
|
72862
73221
|
}
|
|
72863
73222
|
function getUserSkillsDir() {
|
|
72864
|
-
return
|
|
73223
|
+
return join47(zelariHome(), "skills");
|
|
72865
73224
|
}
|
|
72866
73225
|
function getProjectSkillsDir(projectRoot) {
|
|
72867
|
-
return
|
|
73226
|
+
return join47(projectRoot, ".zelari", "skills");
|
|
72868
73227
|
}
|
|
72869
73228
|
function skillFilePath(dir, name) {
|
|
72870
|
-
return
|
|
73229
|
+
return join47(dir, name, "SKILL.md");
|
|
72871
73230
|
}
|
|
72872
73231
|
function classifyScope(skillPath, projectRoot) {
|
|
72873
73232
|
const userDir = getUserSkillsDir().replace(/\\/g, "/");
|
|
@@ -72943,9 +73302,9 @@ function listSkillsSnapshot(projectRoot) {
|
|
|
72943
73302
|
const skills = [];
|
|
72944
73303
|
const seen = /* @__PURE__ */ new Set();
|
|
72945
73304
|
if (root) {
|
|
72946
|
-
scanSkillsDir(
|
|
72947
|
-
scanSkillsDir(
|
|
72948
|
-
scanSkillsDir(
|
|
73305
|
+
scanSkillsDir(join47(root, ".zelari", "skills"), root, seen, skills);
|
|
73306
|
+
scanSkillsDir(join47(root, ".claude", "skills"), root, seen, skills);
|
|
73307
|
+
scanSkillsDir(join47(root, ".opencode", "skills"), root, seen, skills);
|
|
72949
73308
|
}
|
|
72950
73309
|
scanSkillsDir(userSkillsDir, root, seen, skills);
|
|
72951
73310
|
for (const s of listCodingSkills()) {
|
|
@@ -73011,7 +73370,7 @@ function upsertSkill(opts) {
|
|
|
73011
73370
|
}
|
|
73012
73371
|
dir = getProjectSkillsDir(root);
|
|
73013
73372
|
}
|
|
73014
|
-
const
|
|
73373
|
+
const path103 = skillFilePath(dir, name);
|
|
73015
73374
|
const content = serializeSkillMd({
|
|
73016
73375
|
name,
|
|
73017
73376
|
description,
|
|
@@ -73020,13 +73379,13 @@ function upsertSkill(opts) {
|
|
|
73020
73379
|
tools: opts.tools,
|
|
73021
73380
|
cost: opts.cost
|
|
73022
73381
|
});
|
|
73023
|
-
const parsed = parseSkillMd(content,
|
|
73382
|
+
const parsed = parseSkillMd(content, path103);
|
|
73024
73383
|
if (!parsed) {
|
|
73025
73384
|
return { ok: false, error: "Generated SKILL.md failed validation" };
|
|
73026
73385
|
}
|
|
73027
|
-
mkdirSync23(
|
|
73028
|
-
writeFileSync25(
|
|
73029
|
-
return { ok: true, path:
|
|
73386
|
+
mkdirSync23(dirname14(path103), { recursive: true });
|
|
73387
|
+
writeFileSync25(path103, content, "utf8");
|
|
73388
|
+
return { ok: true, path: path103 };
|
|
73030
73389
|
}
|
|
73031
73390
|
function removeSkill(opts) {
|
|
73032
73391
|
const name = opts.name.trim().toLowerCase();
|
|
@@ -73043,9 +73402,9 @@ function removeSkill(opts) {
|
|
|
73043
73402
|
}
|
|
73044
73403
|
dir = getProjectSkillsDir(root);
|
|
73045
73404
|
}
|
|
73046
|
-
const skillDir =
|
|
73047
|
-
const
|
|
73048
|
-
if (!existsSync59(
|
|
73405
|
+
const skillDir = join47(dir, name);
|
|
73406
|
+
const path103 = skillFilePath(dir, name);
|
|
73407
|
+
if (!existsSync59(path103) && !existsSync59(skillDir)) {
|
|
73049
73408
|
return { ok: false, error: `Skill "${name}" not found in ${dir}` };
|
|
73050
73409
|
}
|
|
73051
73410
|
try {
|
|
@@ -73056,7 +73415,7 @@ function removeSkill(opts) {
|
|
|
73056
73415
|
error: err instanceof Error ? err.message : String(err)
|
|
73057
73416
|
};
|
|
73058
73417
|
}
|
|
73059
|
-
return { ok: true, path:
|
|
73418
|
+
return { ok: true, path: path103 };
|
|
73060
73419
|
}
|
|
73061
73420
|
var NAME_RE, BUILTIN_SKILL_MODULES, builtinsLoaded;
|
|
73062
73421
|
var init_skillConfigIo = __esm({
|
|
@@ -73177,7 +73536,7 @@ var init_jsonApi = __esm({
|
|
|
73177
73536
|
});
|
|
73178
73537
|
|
|
73179
73538
|
// src/cli/memory/mcpAdapter.ts
|
|
73180
|
-
import * as
|
|
73539
|
+
import * as path97 from "node:path";
|
|
73181
73540
|
var id2, projectId, source, SearchSchema, AddSchema, LinkSchema, RetractSchema, MEMORY_MCP_TOOLS, MemoryMcpAdapter;
|
|
73182
73541
|
var init_mcpAdapter = __esm({
|
|
73183
73542
|
"src/cli/memory/mcpAdapter.ts"() {
|
|
@@ -73347,8 +73706,8 @@ var init_mcpAdapter = __esm({
|
|
|
73347
73706
|
this.takeWrite();
|
|
73348
73707
|
const externalFile = args.source?.file;
|
|
73349
73708
|
if (externalFile) {
|
|
73350
|
-
const normalized =
|
|
73351
|
-
if (
|
|
73709
|
+
const normalized = path97.normalize(externalFile);
|
|
73710
|
+
if (path97.isAbsolute(normalized) || normalized === ".." || normalized.startsWith(`..${path97.sep}`)) {
|
|
73352
73711
|
throw new Error("source.file must be project-relative and cannot escape the project");
|
|
73353
73712
|
}
|
|
73354
73713
|
}
|
|
@@ -73857,16 +74216,16 @@ import {
|
|
|
73857
74216
|
readFileSync as readFileSync45,
|
|
73858
74217
|
writeFileSync as writeFileSync26
|
|
73859
74218
|
} from "node:fs";
|
|
73860
|
-
import { join as
|
|
74219
|
+
import { join as join48 } from "node:path";
|
|
73861
74220
|
import { createHash as createHash26, randomBytes as randomBytes7, timingSafeEqual } from "node:crypto";
|
|
73862
74221
|
function getZelariHome() {
|
|
73863
74222
|
return zelariHome();
|
|
73864
74223
|
}
|
|
73865
74224
|
function getCompanionConfigPath() {
|
|
73866
|
-
return
|
|
74225
|
+
return join48(getZelariHome(), "companion.json");
|
|
73867
74226
|
}
|
|
73868
74227
|
function getCompanionTokenPath() {
|
|
73869
|
-
return
|
|
74228
|
+
return join48(getZelariHome(), "companion.token");
|
|
73870
74229
|
}
|
|
73871
74230
|
function ensureHome() {
|
|
73872
74231
|
const home = getZelariHome();
|
|
@@ -73875,12 +74234,12 @@ function ensureHome() {
|
|
|
73875
74234
|
}
|
|
73876
74235
|
}
|
|
73877
74236
|
function loadCompanionConfig() {
|
|
73878
|
-
const
|
|
73879
|
-
if (!existsSync60(
|
|
74237
|
+
const path103 = getCompanionConfigPath();
|
|
74238
|
+
if (!existsSync60(path103)) {
|
|
73880
74239
|
return { projects: [] };
|
|
73881
74240
|
}
|
|
73882
74241
|
try {
|
|
73883
|
-
const raw = JSON.parse(readFileSync45(
|
|
74242
|
+
const raw = JSON.parse(readFileSync45(path103, "utf8"));
|
|
73884
74243
|
const projects = Array.isArray(raw.projects) ? raw.projects.filter(
|
|
73885
74244
|
(p3) => p3 && typeof p3.path === "string" && p3.path.trim() && typeof (p3.id ?? p3.name) === "string"
|
|
73886
74245
|
).map((p3) => ({
|
|
@@ -73918,16 +74277,16 @@ function loadOrCreateToken(explicit) {
|
|
|
73918
74277
|
return { token: explicit.trim(), created: false };
|
|
73919
74278
|
}
|
|
73920
74279
|
ensureHome();
|
|
73921
|
-
const
|
|
73922
|
-
if (existsSync60(
|
|
73923
|
-
const t = readFileSync45(
|
|
74280
|
+
const path103 = getCompanionTokenPath();
|
|
74281
|
+
if (existsSync60(path103)) {
|
|
74282
|
+
const t = readFileSync45(path103, "utf8").trim();
|
|
73924
74283
|
if (t) return { token: t, created: false };
|
|
73925
74284
|
}
|
|
73926
74285
|
const token = randomBytes7(24).toString("base64url");
|
|
73927
|
-
writeFileSync26(
|
|
74286
|
+
writeFileSync26(path103, token + "\n", "utf8");
|
|
73928
74287
|
try {
|
|
73929
|
-
const
|
|
73930
|
-
|
|
74288
|
+
const fs50 = __require("node:fs");
|
|
74289
|
+
fs50.chmodSync?.(path103, 384);
|
|
73931
74290
|
} catch {
|
|
73932
74291
|
}
|
|
73933
74292
|
return { token, created: true };
|
|
@@ -73952,17 +74311,17 @@ function mergeProjects(cfg, extraPaths) {
|
|
|
73952
74311
|
byId.set(p3.id, p3);
|
|
73953
74312
|
}
|
|
73954
74313
|
for (const raw of extraPaths) {
|
|
73955
|
-
const
|
|
73956
|
-
if (!
|
|
73957
|
-
let id3 = slugFromPath(
|
|
74314
|
+
const path103 = raw.trim();
|
|
74315
|
+
if (!path103) continue;
|
|
74316
|
+
let id3 = slugFromPath(path103);
|
|
73958
74317
|
let n = 2;
|
|
73959
|
-
while (byId.has(id3) && byId.get(id3).path !==
|
|
73960
|
-
id3 = `${slugFromPath(
|
|
74318
|
+
while (byId.has(id3) && byId.get(id3).path !== path103) {
|
|
74319
|
+
id3 = `${slugFromPath(path103)}-${n++}`;
|
|
73961
74320
|
}
|
|
73962
74321
|
byId.set(id3, {
|
|
73963
74322
|
id: id3,
|
|
73964
|
-
name: slugFromPath(
|
|
73965
|
-
path:
|
|
74323
|
+
name: slugFromPath(path103),
|
|
74324
|
+
path: path103
|
|
73966
74325
|
});
|
|
73967
74326
|
}
|
|
73968
74327
|
return [...byId.values()];
|
|
@@ -74204,8 +74563,8 @@ var init_askUserBridge = __esm({
|
|
|
74204
74563
|
});
|
|
74205
74564
|
|
|
74206
74565
|
// src/cli/serve/spineLockSweep.ts
|
|
74207
|
-
import { promises as
|
|
74208
|
-
import
|
|
74566
|
+
import { promises as fs49 } from "node:fs";
|
|
74567
|
+
import path98 from "node:path";
|
|
74209
74568
|
async function sweepOrphanSpineLocks(sessionsDir2, options = {}) {
|
|
74210
74569
|
const dir = sessionsDir2 ?? resolveSessionsDir();
|
|
74211
74570
|
const onSwept = options.onSwept ?? ((sessionId2, reason) => {
|
|
@@ -74218,14 +74577,14 @@ async function sweepOrphanSpineLocks(sessionsDir2, options = {}) {
|
|
|
74218
74577
|
const result = { swept: 0, kept: 0, errors: 0 };
|
|
74219
74578
|
let entries;
|
|
74220
74579
|
try {
|
|
74221
|
-
entries = await
|
|
74580
|
+
entries = await fs49.readdir(dir);
|
|
74222
74581
|
} catch {
|
|
74223
74582
|
return result;
|
|
74224
74583
|
}
|
|
74225
74584
|
for (const sessionId2 of entries) {
|
|
74226
|
-
const lockPath2 =
|
|
74585
|
+
const lockPath2 = path98.join(dir, sessionId2, "writer.lock");
|
|
74227
74586
|
try {
|
|
74228
|
-
const raw = await
|
|
74587
|
+
const raw = await fs49.readFile(lockPath2, "utf-8");
|
|
74229
74588
|
let lockInfo = {};
|
|
74230
74589
|
try {
|
|
74231
74590
|
lockInfo = JSON.parse(raw);
|
|
@@ -74242,7 +74601,7 @@ async function sweepOrphanSpineLocks(sessionsDir2, options = {}) {
|
|
|
74242
74601
|
result.kept += 1;
|
|
74243
74602
|
continue;
|
|
74244
74603
|
}
|
|
74245
|
-
await
|
|
74604
|
+
await fs49.rm(lockPath2, { force: true });
|
|
74246
74605
|
result.swept += 1;
|
|
74247
74606
|
onSwept(sessionId2, verdict.reason);
|
|
74248
74607
|
} catch (err) {
|
|
@@ -74676,7 +75035,7 @@ import { spawn as spawn18 } from "node:child_process";
|
|
|
74676
75035
|
import { createInterface as createInterface4 } from "node:readline";
|
|
74677
75036
|
import { randomUUID as randomUUID13 } from "node:crypto";
|
|
74678
75037
|
import { writeFileSync as writeFileSync27, unlinkSync as unlinkSync3 } from "node:fs";
|
|
74679
|
-
import { join as
|
|
75038
|
+
import { join as join49 } from "node:path";
|
|
74680
75039
|
import { tmpdir as tmpdir4 } from "node:os";
|
|
74681
75040
|
function harnessServerMode() {
|
|
74682
75041
|
return process.env[HARNESS_SERVER_ENV] === "1";
|
|
@@ -74798,7 +75157,7 @@ var init_runManager = __esm({
|
|
|
74798
75157
|
}
|
|
74799
75158
|
let historyFile;
|
|
74800
75159
|
if (args.history && Array.isArray(args.history) && args.history.length > 0) {
|
|
74801
|
-
historyFile =
|
|
75160
|
+
historyFile = join49(tmpdir4(), `zelari-companion-hist-${id3}.json`);
|
|
74802
75161
|
try {
|
|
74803
75162
|
writeFileSync27(historyFile, JSON.stringify(args.history), "utf8");
|
|
74804
75163
|
argv.push("--history-file", historyFile);
|
|
@@ -75221,9 +75580,9 @@ async function runCompanionServe(opts = {}) {
|
|
|
75221
75580
|
return;
|
|
75222
75581
|
}
|
|
75223
75582
|
const url2 = parseUrl(req);
|
|
75224
|
-
const
|
|
75583
|
+
const path103 = url2.pathname.replace(/\/+$/, "") || "/";
|
|
75225
75584
|
try {
|
|
75226
|
-
if (req.method === "GET" && (
|
|
75585
|
+
if (req.method === "GET" && (path103 === "/health" || path103 === "/v1/health")) {
|
|
75227
75586
|
sendJson2(res, 200, {
|
|
75228
75587
|
ok: true,
|
|
75229
75588
|
service: "zelari-companion",
|
|
@@ -75235,18 +75594,18 @@ async function runCompanionServe(opts = {}) {
|
|
|
75235
75594
|
});
|
|
75236
75595
|
return;
|
|
75237
75596
|
}
|
|
75238
|
-
if (
|
|
75597
|
+
if (path103.startsWith("/v1")) {
|
|
75239
75598
|
if (!tokenMatches(token, getBearer(req))) {
|
|
75240
75599
|
sendJson2(res, 401, { ok: false, error: "unauthorized" });
|
|
75241
75600
|
return;
|
|
75242
75601
|
}
|
|
75243
75602
|
}
|
|
75244
|
-
if (req.method === "GET" &&
|
|
75603
|
+
if (req.method === "GET" && path103 === "/v1/config") {
|
|
75245
75604
|
const snap = buildDesktopConfigSnapshot();
|
|
75246
75605
|
sendJson2(res, 200, { ok: true, ...snap });
|
|
75247
75606
|
return;
|
|
75248
75607
|
}
|
|
75249
|
-
if (req.method === "GET" &&
|
|
75608
|
+
if (req.method === "GET" && path103 === "/v1/projects") {
|
|
75250
75609
|
sendJson2(res, 200, {
|
|
75251
75610
|
ok: true,
|
|
75252
75611
|
projects: projects.map((p3) => ({
|
|
@@ -75257,7 +75616,7 @@ async function runCompanionServe(opts = {}) {
|
|
|
75257
75616
|
});
|
|
75258
75617
|
return;
|
|
75259
75618
|
}
|
|
75260
|
-
if (req.method === "GET" &&
|
|
75619
|
+
if (req.method === "GET" && path103 === "/v1/runs") {
|
|
75261
75620
|
sendJson2(res, 200, {
|
|
75262
75621
|
ok: true,
|
|
75263
75622
|
active: runs.getActive(),
|
|
@@ -75275,7 +75634,7 @@ async function runCompanionServe(opts = {}) {
|
|
|
75275
75634
|
});
|
|
75276
75635
|
return;
|
|
75277
75636
|
}
|
|
75278
|
-
if (req.method === "POST" &&
|
|
75637
|
+
if (req.method === "POST" && path103 === "/v1/runs") {
|
|
75279
75638
|
const raw = await readBody(req);
|
|
75280
75639
|
let body = {};
|
|
75281
75640
|
try {
|
|
@@ -75323,7 +75682,7 @@ async function runCompanionServe(opts = {}) {
|
|
|
75323
75682
|
});
|
|
75324
75683
|
return;
|
|
75325
75684
|
}
|
|
75326
|
-
const eventsMatch = /^\/v1\/runs\/([^/]+)\/events$/.exec(
|
|
75685
|
+
const eventsMatch = /^\/v1\/runs\/([^/]+)\/events$/.exec(path103);
|
|
75327
75686
|
if (req.method === "GET" && eventsMatch) {
|
|
75328
75687
|
const runId = eventsMatch[1];
|
|
75329
75688
|
const run = runs.getRun(runId);
|
|
@@ -75388,7 +75747,7 @@ async function runCompanionServe(opts = {}) {
|
|
|
75388
75747
|
}, 500);
|
|
75389
75748
|
return;
|
|
75390
75749
|
}
|
|
75391
|
-
const cancelMatch = /^\/v1\/runs\/([^/]+)\/cancel$/.exec(
|
|
75750
|
+
const cancelMatch = /^\/v1\/runs\/([^/]+)\/cancel$/.exec(path103);
|
|
75392
75751
|
if (req.method === "POST" && cancelMatch) {
|
|
75393
75752
|
const runId = cancelMatch[1];
|
|
75394
75753
|
const result = runs.cancel(runId);
|
|
@@ -75399,7 +75758,7 @@ async function runCompanionServe(opts = {}) {
|
|
|
75399
75758
|
sendJson2(res, 200, { ok: true, cancelled: runId });
|
|
75400
75759
|
return;
|
|
75401
75760
|
}
|
|
75402
|
-
const steerMatch = /^\/v1\/runs\/([^/]+)\/steer$/.exec(
|
|
75761
|
+
const steerMatch = /^\/v1\/runs\/([^/]+)\/steer$/.exec(path103);
|
|
75403
75762
|
if (req.method === "POST" && steerMatch) {
|
|
75404
75763
|
const runId = steerMatch[1];
|
|
75405
75764
|
const raw = await readBody(req);
|
|
@@ -75568,11 +75927,11 @@ import { execSync as execSync2 } from "node:child_process";
|
|
|
75568
75927
|
import { existsSync as existsSync62, readFileSync as readFileSync46, readlinkSync, statSync as statSync10 } from "node:fs";
|
|
75569
75928
|
import { createRequire as createRequire3 } from "node:module";
|
|
75570
75929
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
75571
|
-
import
|
|
75930
|
+
import path99 from "node:path";
|
|
75572
75931
|
function findPackageRoot(start) {
|
|
75573
75932
|
let dir = start;
|
|
75574
75933
|
for (let i = 0; i < 6; i += 1) {
|
|
75575
|
-
const candidate =
|
|
75934
|
+
const candidate = path99.join(dir, "package.json");
|
|
75576
75935
|
if (existsSync62(candidate)) {
|
|
75577
75936
|
try {
|
|
75578
75937
|
const pkg = JSON.parse(readFileSync46(candidate, "utf8"));
|
|
@@ -75580,11 +75939,11 @@ function findPackageRoot(start) {
|
|
|
75580
75939
|
} catch {
|
|
75581
75940
|
}
|
|
75582
75941
|
}
|
|
75583
|
-
const parent =
|
|
75942
|
+
const parent = path99.dirname(dir);
|
|
75584
75943
|
if (parent === dir) break;
|
|
75585
75944
|
dir = parent;
|
|
75586
75945
|
}
|
|
75587
|
-
return
|
|
75946
|
+
return path99.resolve(__dirname3, "..", "..", "..");
|
|
75588
75947
|
}
|
|
75589
75948
|
function tryExec(cmd) {
|
|
75590
75949
|
try {
|
|
@@ -75598,7 +75957,7 @@ function tryExec(cmd) {
|
|
|
75598
75957
|
}
|
|
75599
75958
|
function readPackageJson4() {
|
|
75600
75959
|
try {
|
|
75601
|
-
const pkgPath =
|
|
75960
|
+
const pkgPath = path99.join(packageRoot, "package.json");
|
|
75602
75961
|
return JSON.parse(readFileSync46(pkgPath, "utf8"));
|
|
75603
75962
|
} catch {
|
|
75604
75963
|
return null;
|
|
@@ -75610,7 +75969,7 @@ function getGlobalPrefix() {
|
|
|
75610
75969
|
return (process.env.npm_config_prefix || process.env.NPM_CONFIG_PREFIX || "").trim();
|
|
75611
75970
|
}
|
|
75612
75971
|
function isSourceCheckout() {
|
|
75613
|
-
return existsSync62(
|
|
75972
|
+
return existsSync62(path99.join(packageRoot, "src", "cli", "main.ts")) && existsSync62(path99.join(packageRoot, "apps", "desktop", "package.json"));
|
|
75614
75973
|
}
|
|
75615
75974
|
function checkShim(pkgName) {
|
|
75616
75975
|
const prefix = getGlobalPrefix();
|
|
@@ -75619,9 +75978,9 @@ function checkShim(pkgName) {
|
|
|
75619
75978
|
}
|
|
75620
75979
|
const isWin = process.platform === "win32";
|
|
75621
75980
|
const shimName = isWin ? "zelari-code.cmd" : "zelari-code";
|
|
75622
|
-
const shimPath =
|
|
75981
|
+
const shimPath = path99.join(prefix, shimName);
|
|
75623
75982
|
if (!existsSync62(shimPath)) {
|
|
75624
|
-
const localBin =
|
|
75983
|
+
const localBin = path99.join(packageRoot, "bin", "zelari-code.js");
|
|
75625
75984
|
if (isSourceCheckout() && existsSync62(localBin)) {
|
|
75626
75985
|
return WARN(
|
|
75627
75986
|
`global shim not found at ${shimPath}
|
|
@@ -75655,8 +76014,8 @@ function checkShim(pkgName) {
|
|
|
75655
76014
|
fix: npm install -g ${pkgName}@latest --force`
|
|
75656
76015
|
);
|
|
75657
76016
|
}
|
|
75658
|
-
const resolved =
|
|
75659
|
-
const expected =
|
|
76017
|
+
const resolved = path99.resolve(path99.dirname(shimPath), target);
|
|
76018
|
+
const expected = path99.join(
|
|
75660
76019
|
prefix,
|
|
75661
76020
|
"node_modules",
|
|
75662
76021
|
pkgName,
|
|
@@ -75698,7 +76057,7 @@ function checkNode(pkg) {
|
|
|
75698
76057
|
return OK(`node ${raw} (engines.node ${enginesNode ?? ">= 20.0.0"})`);
|
|
75699
76058
|
}
|
|
75700
76059
|
function checkBundle() {
|
|
75701
|
-
const bundle =
|
|
76060
|
+
const bundle = path99.join(packageRoot, "dist", "cli", "main.bundled.js");
|
|
75702
76061
|
if (!existsSync62(bundle)) {
|
|
75703
76062
|
return FAIL(
|
|
75704
76063
|
`dist/cli/main.bundled.js missing at ${bundle}
|
|
@@ -75719,7 +76078,7 @@ function checkRuntimeDeps() {
|
|
|
75719
76078
|
const missing = [];
|
|
75720
76079
|
for (const dep of required2) {
|
|
75721
76080
|
try {
|
|
75722
|
-
const localReq = createRequire3(
|
|
76081
|
+
const localReq = createRequire3(path99.join(packageRoot, "package.json"));
|
|
75723
76082
|
localReq.resolve(dep);
|
|
75724
76083
|
} catch {
|
|
75725
76084
|
missing.push(dep);
|
|
@@ -75996,7 +76355,7 @@ var init_doctor = __esm({
|
|
|
75996
76355
|
init_metrics3();
|
|
75997
76356
|
init_contextGrowthSummary();
|
|
75998
76357
|
require3 = createRequire3(import.meta.url);
|
|
75999
|
-
__dirname3 =
|
|
76358
|
+
__dirname3 = path99.dirname(fileURLToPath3(import.meta.url));
|
|
76000
76359
|
packageRoot = findPackageRoot(__dirname3);
|
|
76001
76360
|
OK = (message) => ({
|
|
76002
76361
|
ok: true,
|
|
@@ -76105,7 +76464,7 @@ __export(userSettings_exports, {
|
|
|
76105
76464
|
settingsOverrides: () => settingsOverrides
|
|
76106
76465
|
});
|
|
76107
76466
|
import { existsSync as existsSync63, readFileSync as readFileSync47 } from "node:fs";
|
|
76108
|
-
import
|
|
76467
|
+
import path100 from "node:path";
|
|
76109
76468
|
function parseBool(raw) {
|
|
76110
76469
|
const v = raw.trim().toLowerCase();
|
|
76111
76470
|
if (["1", "true", "yes", "on"].includes(v)) return true;
|
|
@@ -76172,8 +76531,8 @@ function envValueFor(key, env) {
|
|
|
76172
76531
|
function resolveUserSettings(opts = {}) {
|
|
76173
76532
|
const cwd = opts.cwd ?? process.cwd();
|
|
76174
76533
|
const env = opts.env ?? process.env;
|
|
76175
|
-
const userPath =
|
|
76176
|
-
const projectPath =
|
|
76534
|
+
const userPath = path100.join(zelariHome(), SETTINGS_FILE_NAME);
|
|
76535
|
+
const projectPath = path100.join(cwd, ".zelari", SETTINGS_FILE_NAME);
|
|
76177
76536
|
const warnings = [];
|
|
76178
76537
|
const userLayer = loadFileLayer(userPath, "user", warnings);
|
|
76179
76538
|
const projectLayer = loadFileLayer(projectPath, "project", warnings);
|
|
@@ -76387,7 +76746,7 @@ __export(inspectSession_exports, {
|
|
|
76387
76746
|
renderInspectReport: () => renderInspectReport,
|
|
76388
76747
|
runInspectSession: () => runInspectSession
|
|
76389
76748
|
});
|
|
76390
|
-
import
|
|
76749
|
+
import path101 from "node:path";
|
|
76391
76750
|
import { existsSync as existsSync64 } from "node:fs";
|
|
76392
76751
|
function formatLimit(limit) {
|
|
76393
76752
|
return `${Math.round(limit / 1e3)}k`;
|
|
@@ -76421,8 +76780,8 @@ function renderInspectReport(state3) {
|
|
|
76421
76780
|
}
|
|
76422
76781
|
async function runInspectSession(opts) {
|
|
76423
76782
|
const sessionsDir2 = resolveSessionsDir({ workspaceRoot: opts.cwd ?? process.cwd() });
|
|
76424
|
-
const sessionDir =
|
|
76425
|
-
const eventsPath =
|
|
76783
|
+
const sessionDir = path101.join(sessionsDir2, opts.sessionId);
|
|
76784
|
+
const eventsPath = path101.join(sessionDir, "events.jsonl");
|
|
76426
76785
|
if (!existsSync64(sessionDir)) {
|
|
76427
76786
|
console.error(`zelari-code inspect: no session directory at ${sessionDir}`);
|
|
76428
76787
|
return 1;
|
|
@@ -76456,14 +76815,14 @@ __export(inspect_exports, {
|
|
|
76456
76815
|
collectInspectReport: () => collectInspectReport,
|
|
76457
76816
|
runInspect: () => runInspect
|
|
76458
76817
|
});
|
|
76459
|
-
import
|
|
76818
|
+
import path102 from "node:path";
|
|
76460
76819
|
import { existsSync as existsSync65, readFileSync as readFileSync48, readdirSync as readdirSync13 } from "node:fs";
|
|
76461
76820
|
async function collectInspectReport(cwd = process.cwd()) {
|
|
76462
76821
|
ensureBuiltinSkillsLoadedSync();
|
|
76463
76822
|
const snap = listSkillsSnapshot(cwd);
|
|
76464
76823
|
const mcp = listMcpServers(cwd);
|
|
76465
|
-
const userMcpPath =
|
|
76466
|
-
const projectMcpPath =
|
|
76824
|
+
const userMcpPath = path102.join(zelariHome(), "mcp.json");
|
|
76825
|
+
const projectMcpPath = path102.join(cwd, ".zelari", "mcp.json");
|
|
76467
76826
|
const globalHooks = globalHooksDir();
|
|
76468
76827
|
const projectHooks = projectHooksDir(cwd);
|
|
76469
76828
|
const projectTrusted = isFolderTrusted(cwd);
|
|
@@ -76491,9 +76850,9 @@ async function collectInspectReport(cwd = process.cwd()) {
|
|
|
76491
76850
|
configSources: [
|
|
76492
76851
|
{ path: userMcpPath, exists: existsSync65(userMcpPath) },
|
|
76493
76852
|
{ path: projectMcpPath, exists: existsSync65(projectMcpPath) },
|
|
76494
|
-
{ path:
|
|
76495
|
-
{ path:
|
|
76496
|
-
{ path:
|
|
76853
|
+
{ path: path102.join(zelariHome(), "provider.json"), exists: existsSync65(path102.join(zelariHome(), "provider.json")) },
|
|
76854
|
+
{ path: path102.join(cwd, ".zelari", "AGENTS.md"), exists: existsSync65(path102.join(cwd, ".zelari", "AGENTS.md")) },
|
|
76855
|
+
{ path: path102.join(cwd, "AGENTS.md"), exists: existsSync65(path102.join(cwd, "AGENTS.md")) }
|
|
76497
76856
|
],
|
|
76498
76857
|
skills: {
|
|
76499
76858
|
total: snap.skills.length,
|
|
@@ -76533,8 +76892,8 @@ function listJsonFiles(dir) {
|
|
|
76533
76892
|
}
|
|
76534
76893
|
function findAgentsMd(cwd) {
|
|
76535
76894
|
const candidates = [
|
|
76536
|
-
|
|
76537
|
-
|
|
76895
|
+
path102.join(cwd, "AGENTS.md"),
|
|
76896
|
+
path102.join(cwd, ".zelari", "AGENTS.md")
|
|
76538
76897
|
];
|
|
76539
76898
|
const found = [];
|
|
76540
76899
|
for (const c of candidates) {
|
|
@@ -79566,6 +79925,7 @@ init_completionGate();
|
|
|
79566
79925
|
init_verificationBridge();
|
|
79567
79926
|
init_completionProof();
|
|
79568
79927
|
init_opsKnowledge();
|
|
79928
|
+
init_repeatCheck();
|
|
79569
79929
|
init_verifyStatus();
|
|
79570
79930
|
init_nativeVerification();
|
|
79571
79931
|
init_spineTelemetry();
|
|
@@ -80199,10 +80559,17 @@ _(${req.context})_` : "") + "\n\u2192 scegli dalla lista (il turno continua dopo
|
|
|
80199
80559
|
() => void 0,
|
|
80200
80560
|
() => void 0
|
|
80201
80561
|
);
|
|
80202
|
-
await promoteOpsKnowledgeSafe(gate, {
|
|
80562
|
+
const opsKnowledge = await promoteOpsKnowledgeSafe(gate, {
|
|
80203
80563
|
projectRoot: process.cwd(),
|
|
80204
80564
|
sessionId: sessionId2
|
|
80205
80565
|
});
|
|
80566
|
+
const notices = [
|
|
80567
|
+
...opsKnowledge.proposals,
|
|
80568
|
+
...opsKnowledge.checkProposals.map(formatCheckProposalNotice)
|
|
80569
|
+
];
|
|
80570
|
+
if (notices.length > 0) {
|
|
80571
|
+
appendSystem(setMessages, notices.join("\n"), Date.now());
|
|
80572
|
+
}
|
|
80206
80573
|
};
|
|
80207
80574
|
if (event.reason === "completed" && !krakenRepairEnqueued && (isKrakenSelectionEnabled() || nativePackEnabled()) && workPhase === "build") {
|
|
80208
80575
|
const strictGate = await evaluateStrictBuildGate("build", { emit: krakenSpineEmit });
|
|
@@ -81741,10 +82108,10 @@ init_ledger();
|
|
|
81741
82108
|
|
|
81742
82109
|
// src/cli/evolution/proposals.ts
|
|
81743
82110
|
import { existsSync as existsSync51, readFileSync as readFileSync39 } from "node:fs";
|
|
81744
|
-
import
|
|
81745
|
-
var PROPOSALS_REL =
|
|
82111
|
+
import path81 from "node:path";
|
|
82112
|
+
var PROPOSALS_REL = path81.join(".zelari", "evolution", "proposals.jsonl");
|
|
81746
82113
|
function proposalsPath(cwd) {
|
|
81747
|
-
return
|
|
82114
|
+
return path81.join(cwd, PROPOSALS_REL);
|
|
81748
82115
|
}
|
|
81749
82116
|
function readProposalStore(cwd) {
|
|
81750
82117
|
const file2 = proposalsPath(cwd);
|
|
@@ -82868,9 +83235,12 @@ function handleCacheStats(ctx) {
|
|
|
82868
83235
|
// src/cli/slashHandlers/memory.ts
|
|
82869
83236
|
init_messageHelpers();
|
|
82870
83237
|
init_serviceFactory();
|
|
83238
|
+
init_howWeTest();
|
|
82871
83239
|
init_promotion();
|
|
82872
|
-
|
|
82873
|
-
|
|
83240
|
+
init_repeatCheck();
|
|
83241
|
+
init_worldModel();
|
|
83242
|
+
import { promises as fs37 } from "node:fs";
|
|
83243
|
+
import * as path82 from "node:path";
|
|
82874
83244
|
var USAGE = [
|
|
82875
83245
|
"/memory \u2014 backend summary",
|
|
82876
83246
|
"/memory search <query>",
|
|
@@ -82882,6 +83252,8 @@ var USAGE = [
|
|
|
82882
83252
|
"/memory consolidate [query]",
|
|
82883
83253
|
"/memory index [--force]",
|
|
82884
83254
|
"/memory promote <id> \u2014 append durable knowledge to managed AGENTS.md section",
|
|
83255
|
+
'/memory promote con-<fp> --as-check --command "<cmd>" [--expect-exit N] \u2014 append a WorldCheck',
|
|
83256
|
+
"/memory how-we-test \u2014 regenerate .zelari/how-we-test.md from verified procedures",
|
|
82885
83257
|
"/memory stats | doctor | export [project-relative-path]",
|
|
82886
83258
|
"/memory audit \u2014 read-only decay + contradiction report (nothing is mutated)"
|
|
82887
83259
|
].join("\n ");
|
|
@@ -82894,24 +83266,24 @@ function sourceLine(source2) {
|
|
|
82894
83266
|
return entries.length ? entries.map(([key, value]) => `${key}=${value}`).join(" \xB7 ") : "unknown";
|
|
82895
83267
|
}
|
|
82896
83268
|
function isInside(root, target) {
|
|
82897
|
-
const relative6 =
|
|
82898
|
-
return relative6 === "" || !relative6.startsWith("..") && !
|
|
83269
|
+
const relative6 = path82.relative(root, target);
|
|
83270
|
+
return relative6 === "" || !relative6.startsWith("..") && !path82.isAbsolute(relative6);
|
|
82899
83271
|
}
|
|
82900
83272
|
async function safeExportPath(cwd, requested) {
|
|
82901
|
-
const lexicalRoot =
|
|
82902
|
-
const root = await
|
|
82903
|
-
const fallback =
|
|
82904
|
-
const target = requested?.trim() ?
|
|
83273
|
+
const lexicalRoot = path82.resolve(cwd);
|
|
83274
|
+
const root = await fs37.realpath(lexicalRoot).catch(() => lexicalRoot);
|
|
83275
|
+
const fallback = path82.join(root, ".zelari", "memory", `export-${Date.now()}.json`);
|
|
83276
|
+
const target = requested?.trim() ? path82.resolve(root, requested.trim()) : fallback;
|
|
82905
83277
|
if (!isInside(root, target)) {
|
|
82906
83278
|
throw new Error("Export path must stay inside the active project.");
|
|
82907
83279
|
}
|
|
82908
|
-
const parent =
|
|
82909
|
-
const relativeParent =
|
|
83280
|
+
const parent = path82.dirname(target);
|
|
83281
|
+
const relativeParent = path82.relative(root, parent);
|
|
82910
83282
|
let cursor = root;
|
|
82911
|
-
for (const segment of relativeParent.split(
|
|
82912
|
-
cursor =
|
|
83283
|
+
for (const segment of relativeParent.split(path82.sep).filter(Boolean)) {
|
|
83284
|
+
cursor = path82.join(cursor, segment);
|
|
82913
83285
|
try {
|
|
82914
|
-
const stat8 = await
|
|
83286
|
+
const stat8 = await fs37.lstat(cursor);
|
|
82915
83287
|
if (stat8.isSymbolicLink()) {
|
|
82916
83288
|
throw new Error("Export path must not traverse a symbolic link.");
|
|
82917
83289
|
}
|
|
@@ -82921,7 +83293,7 @@ async function safeExportPath(cwd, requested) {
|
|
|
82921
83293
|
}
|
|
82922
83294
|
}
|
|
82923
83295
|
try {
|
|
82924
|
-
if ((await
|
|
83296
|
+
if ((await fs37.lstat(target)).isSymbolicLink()) {
|
|
82925
83297
|
throw new Error("Export target must not be a symbolic link.");
|
|
82926
83298
|
}
|
|
82927
83299
|
} catch (error51) {
|
|
@@ -83058,10 +83430,21 @@ ${message}` : message
|
|
|
83058
83430
|
);
|
|
83059
83431
|
return;
|
|
83060
83432
|
}
|
|
83433
|
+
case "how-we-test": {
|
|
83434
|
+
const result = await regenerateHowWeTest(memory, ctx.cwd);
|
|
83435
|
+
emit(result.written ? `[memory] how-we-test written to ${result.path} (${result.rows} procedure(s))` : `[memory] how-we-test not written: ${result.reason ?? "nothing to project"}.`);
|
|
83436
|
+
return;
|
|
83437
|
+
}
|
|
83061
83438
|
case "promote": {
|
|
83062
|
-
const
|
|
83439
|
+
const parsed = parsePromoteArgs(args);
|
|
83440
|
+
if (parsed.error) {
|
|
83441
|
+
emit(`[memory] ${parsed.error}
|
|
83442
|
+
${PROMOTE_USAGE}`);
|
|
83443
|
+
return;
|
|
83444
|
+
}
|
|
83445
|
+
const memoryId = parsed.id;
|
|
83063
83446
|
if (!memoryId) {
|
|
83064
|
-
emit(
|
|
83447
|
+
emit(PROMOTE_USAGE);
|
|
83065
83448
|
return;
|
|
83066
83449
|
}
|
|
83067
83450
|
const node = await memory.get(memoryId);
|
|
@@ -83069,6 +83452,26 @@ ${message}` : message
|
|
|
83069
83452
|
emit(`[memory] ${memoryId} not found in this project.`);
|
|
83070
83453
|
return;
|
|
83071
83454
|
}
|
|
83455
|
+
if (parsed.asCheck) {
|
|
83456
|
+
const constraint = constraintFromNode(node);
|
|
83457
|
+
if (!constraint) {
|
|
83458
|
+
emit(`[memory] ${memoryId} is not a repeat-failure constraint (no fingerprint/command/digest) \u2014 nothing to turn into a check.`);
|
|
83459
|
+
return;
|
|
83460
|
+
}
|
|
83461
|
+
const nodes = await listVerifiedProcedureNodes(memory);
|
|
83462
|
+
const proposal = proposalFromConstraint(constraint, nodes ?? []);
|
|
83463
|
+
const check2 = confirmCheck(proposal, {
|
|
83464
|
+
command: parsed.command,
|
|
83465
|
+
...parsed.expectExit === void 0 ? {} : { expectExit: parsed.expectExit }
|
|
83466
|
+
});
|
|
83467
|
+
if (!check2) {
|
|
83468
|
+
emit(checkConfirmationHint(proposal));
|
|
83469
|
+
return;
|
|
83470
|
+
}
|
|
83471
|
+
const appended = await appendWorldCheck(ctx.cwd, check2);
|
|
83472
|
+
emit(appended.added ? `[memory] check \u201C${check2.id}\u201D appended to ${appended.path} (${appended.count} check(s))` : `[memory] check \u201C${check2.id}\u201D already present in ${appended.path} \u2014 file untouched.`);
|
|
83473
|
+
return;
|
|
83474
|
+
}
|
|
83072
83475
|
const promoted = await promoteMemoryToAgentsMd(ctx.cwd, node);
|
|
83073
83476
|
emit(promoted.added ? `[memory] promoted ${memoryId} to ${promoted.path}` : `[memory] ${memoryId} not promoted: ${promoted.reason ?? "policy rejected it"}.`);
|
|
83074
83477
|
return;
|
|
@@ -83081,13 +83484,13 @@ ${message}` : message
|
|
|
83081
83484
|
}
|
|
83082
83485
|
case "export": {
|
|
83083
83486
|
const target = await safeExportPath(ctx.cwd, args.join(" ").trim() || void 0);
|
|
83084
|
-
await
|
|
83085
|
-
const root = await
|
|
83086
|
-
const realParent = await
|
|
83487
|
+
await fs37.mkdir(path82.dirname(target), { recursive: true });
|
|
83488
|
+
const root = await fs37.realpath(ctx.cwd).catch(() => path82.resolve(ctx.cwd));
|
|
83489
|
+
const realParent = await fs37.realpath(path82.dirname(target));
|
|
83087
83490
|
if (!isInside(root, realParent)) {
|
|
83088
83491
|
throw new Error("Export path resolves outside the active project.");
|
|
83089
83492
|
}
|
|
83090
|
-
await
|
|
83493
|
+
await fs37.writeFile(target, JSON.stringify(await memory.export(), null, 2) + "\n", "utf8");
|
|
83091
83494
|
emit(`[memory] export written to ${target}`);
|
|
83092
83495
|
return;
|
|
83093
83496
|
}
|
|
@@ -83329,13 +83732,13 @@ ${digest}
|
|
|
83329
83732
|
init_auditLogger();
|
|
83330
83733
|
init_toolRegistry();
|
|
83331
83734
|
init_messageHelpers();
|
|
83332
|
-
import { promises as
|
|
83735
|
+
import { promises as fs39 } from "node:fs";
|
|
83333
83736
|
|
|
83334
83737
|
// src/cli/tools/krakenCsvFanout.ts
|
|
83335
83738
|
init_zod();
|
|
83336
83739
|
init_taskTool();
|
|
83337
|
-
import { promises as
|
|
83338
|
-
import
|
|
83740
|
+
import { promises as fs38 } from "node:fs";
|
|
83741
|
+
import path83 from "node:path";
|
|
83339
83742
|
import { randomBytes as randomBytes6 } from "node:crypto";
|
|
83340
83743
|
var CsvFanoutArgsSchema = external_exports.object({
|
|
83341
83744
|
csv_path: external_exports.string().min(1),
|
|
@@ -83356,7 +83759,7 @@ var CsvFanoutArgsSchema = external_exports.object({
|
|
|
83356
83759
|
max_runtime_seconds: external_exports.number().int().positive().optional()
|
|
83357
83760
|
});
|
|
83358
83761
|
async function readCsv(filePath) {
|
|
83359
|
-
const text = await
|
|
83762
|
+
const text = await fs38.readFile(filePath, "utf8");
|
|
83360
83763
|
return parseCsv(text);
|
|
83361
83764
|
}
|
|
83362
83765
|
function parseCsv(text) {
|
|
@@ -83429,8 +83832,8 @@ function resolveMaxConcurrency(env = process.env) {
|
|
|
83429
83832
|
}
|
|
83430
83833
|
async function runCsvFanout(args, deps, opts) {
|
|
83431
83834
|
const start = Date.now();
|
|
83432
|
-
const absCsv =
|
|
83433
|
-
const absOut =
|
|
83835
|
+
const absCsv = path83.isAbsolute(args.csv_path) ? args.csv_path : path83.join(opts.parentCwd, args.csv_path);
|
|
83836
|
+
const absOut = path83.isAbsolute(args.output_csv_path) ? args.output_csv_path : path83.join(opts.parentCwd, args.output_csv_path);
|
|
83434
83837
|
const { headers: headers3, rows } = await readCsv(absCsv);
|
|
83435
83838
|
if (headers3.length === 0) {
|
|
83436
83839
|
throw new Error(`kraken_csv_fanout: ${absCsv} is empty`);
|
|
@@ -83486,7 +83889,7 @@ async function runCsvFanout(args, deps, opts) {
|
|
|
83486
83889
|
errored += 1;
|
|
83487
83890
|
errors.push(`${row[args.id_column] ?? i}: ${res.error}`);
|
|
83488
83891
|
}
|
|
83489
|
-
await
|
|
83892
|
+
await fs38.mkdir(path83.dirname(absOut), { recursive: true });
|
|
83490
83893
|
await queueWrite(serializeCsv(outHeaders, outputRecords));
|
|
83491
83894
|
}
|
|
83492
83895
|
}
|
|
@@ -83508,8 +83911,8 @@ async function runCsvFanout(args, deps, opts) {
|
|
|
83508
83911
|
}
|
|
83509
83912
|
async function atomicWrite(file2, contents) {
|
|
83510
83913
|
const tmp = `${file2}.${process.pid}.${Date.now()}.${randomBytes6(6).toString("hex")}.tmp`;
|
|
83511
|
-
await
|
|
83512
|
-
await
|
|
83914
|
+
await fs38.writeFile(tmp, contents, "utf8");
|
|
83915
|
+
await fs38.rename(tmp, file2);
|
|
83513
83916
|
}
|
|
83514
83917
|
|
|
83515
83918
|
// src/cli/slashHandlers/krakenFanout.ts
|
|
@@ -83607,7 +84010,7 @@ async function handleKrakenFanout(ctx, raw) {
|
|
|
83607
84010
|
}
|
|
83608
84011
|
const absCsv = isAbsolute3(parsed.args.csv_path) ? parsed.args.csv_path : joinPath(ctx.cwd, parsed.args.csv_path);
|
|
83609
84012
|
try {
|
|
83610
|
-
await
|
|
84013
|
+
await fs39.access(absCsv);
|
|
83611
84014
|
} catch {
|
|
83612
84015
|
appendSystem(ctx.setMessages, `[kraken fanout] source CSV not found: ${absCsv}`);
|
|
83613
84016
|
return;
|
|
@@ -83680,8 +84083,8 @@ function splitArgs(s) {
|
|
|
83680
84083
|
|
|
83681
84084
|
// src/cli/slashHandlers/krakenWorkbench.ts
|
|
83682
84085
|
init_messageHelpers();
|
|
83683
|
-
import { promises as
|
|
83684
|
-
import
|
|
84086
|
+
import { promises as fs40 } from "node:fs";
|
|
84087
|
+
import path84 from "node:path";
|
|
83685
84088
|
|
|
83686
84089
|
// src/cli/kraken/workbenchView.ts
|
|
83687
84090
|
var EMPTY = {
|
|
@@ -83798,15 +84201,15 @@ function formatWorkbenchForTerminal(p3) {
|
|
|
83798
84201
|
|
|
83799
84202
|
// src/cli/slashHandlers/krakenWorkbench.ts
|
|
83800
84203
|
async function handleKrakenWorkbench(ctx) {
|
|
83801
|
-
const dir =
|
|
84204
|
+
const dir = path84.join(ctx.cwd, ".zelari", "radio");
|
|
83802
84205
|
let latest = null;
|
|
83803
84206
|
let latestMtime = 0;
|
|
83804
84207
|
try {
|
|
83805
|
-
const files = await
|
|
84208
|
+
const files = await fs40.readdir(dir);
|
|
83806
84209
|
for (const f of files) {
|
|
83807
84210
|
if (!f.startsWith("workbench-") || !f.endsWith(".md")) continue;
|
|
83808
|
-
const full =
|
|
83809
|
-
const stat8 = await
|
|
84211
|
+
const full = path84.join(dir, f);
|
|
84212
|
+
const stat8 = await fs40.stat(full);
|
|
83810
84213
|
if (stat8.mtimeMs > latestMtime) {
|
|
83811
84214
|
latestMtime = stat8.mtimeMs;
|
|
83812
84215
|
latest = full;
|
|
@@ -83818,14 +84221,14 @@ async function handleKrakenWorkbench(ctx) {
|
|
|
83818
84221
|
appendSystem(ctx.setMessages, "[kraken workbench] no workbench file found (.zelari/radio/workbench-*.md)");
|
|
83819
84222
|
return;
|
|
83820
84223
|
}
|
|
83821
|
-
const content = await
|
|
84224
|
+
const content = await fs40.readFile(latest, "utf8");
|
|
83822
84225
|
const parsed = parseWorkbench(content);
|
|
83823
84226
|
const rendered = formatWorkbenchForTerminal(parsed);
|
|
83824
84227
|
if (!rendered.trim()) {
|
|
83825
|
-
appendSystem(ctx.setMessages, `[kraken workbench] ${
|
|
84228
|
+
appendSystem(ctx.setMessages, `[kraken workbench] ${path84.basename(latest)}: (no nodes / no events yet)`);
|
|
83826
84229
|
return;
|
|
83827
84230
|
}
|
|
83828
|
-
appendSystem(ctx.setMessages, `[kraken workbench] ${
|
|
84231
|
+
appendSystem(ctx.setMessages, `[kraken workbench] ${path84.basename(latest)}:
|
|
83829
84232
|
${rendered}`);
|
|
83830
84233
|
}
|
|
83831
84234
|
|
|
@@ -84132,20 +84535,20 @@ ${result.output.split("\n").slice(-8).join("\n")}` : "";
|
|
|
84132
84535
|
// src/cli/slashHandlers/promoteMember.ts
|
|
84133
84536
|
init_messageHelpers();
|
|
84134
84537
|
init_paths();
|
|
84135
|
-
import { promises as
|
|
84136
|
-
import
|
|
84538
|
+
import { promises as fs41 } from "node:fs";
|
|
84539
|
+
import path87 from "node:path";
|
|
84137
84540
|
async function handlePromoteMember(ctx, memberId) {
|
|
84138
84541
|
try {
|
|
84139
84542
|
const { promoteMember: promoteMember2 } = await Promise.resolve().then(() => (init_council(), council_exports));
|
|
84140
84543
|
const { skill, markdown } = promoteMember2(memberId);
|
|
84141
84544
|
const skillDir = skillsDir();
|
|
84142
|
-
await
|
|
84143
|
-
const filePath =
|
|
84144
|
-
const previous = await
|
|
84545
|
+
await fs41.mkdir(skillDir, { recursive: true });
|
|
84546
|
+
const filePath = path87.join(skillDir, `${skill.id}.md`);
|
|
84547
|
+
const previous = await fs41.readFile(filePath, "utf8").catch(() => null);
|
|
84145
84548
|
const { createHash: createHash27 } = await import("node:crypto");
|
|
84146
84549
|
const sha = (s) => createHash27("sha256").update(s, "utf8").digest("hex");
|
|
84147
84550
|
const lineage = `<!-- lineage: genome=sha256:${sha(markdown)} parent=${previous ? `sha256:${sha(previous)}` : "none"} promotedBy=user promotedAt=${(/* @__PURE__ */ new Date()).toISOString()} -->`;
|
|
84148
|
-
await
|
|
84551
|
+
await fs41.writeFile(filePath, `${markdown}
|
|
84149
84552
|
${lineage}
|
|
84150
84553
|
`, "utf8");
|
|
84151
84554
|
appendSystem(
|
|
@@ -84165,8 +84568,8 @@ ${lineage}
|
|
|
84165
84568
|
|
|
84166
84569
|
// src/cli/branchManager.ts
|
|
84167
84570
|
init_paths();
|
|
84168
|
-
import { promises as
|
|
84169
|
-
import
|
|
84571
|
+
import { promises as fs42, existsSync as existsSync55, readFileSync as readFileSync41, writeFileSync as writeFileSync24, mkdirSync as mkdirSync21, statSync as statSync7, rmSync as rmSync3 } from "node:fs";
|
|
84572
|
+
import path88 from "node:path";
|
|
84170
84573
|
var META_FILENAME = "meta.json";
|
|
84171
84574
|
var SESSIONS_SUBDIR = "sessions";
|
|
84172
84575
|
function getBranchesBaseDir() {
|
|
@@ -84176,13 +84579,13 @@ function getSessionsBaseDir() {
|
|
|
84176
84579
|
return sessionsDir();
|
|
84177
84580
|
}
|
|
84178
84581
|
function branchPathFor(name, baseDir) {
|
|
84179
|
-
return
|
|
84582
|
+
return path88.join(baseDir, name);
|
|
84180
84583
|
}
|
|
84181
84584
|
function metaPathFor(name, baseDir) {
|
|
84182
|
-
return
|
|
84585
|
+
return path88.join(baseDir, name, META_FILENAME);
|
|
84183
84586
|
}
|
|
84184
84587
|
function sessionsPathFor(name, baseDir) {
|
|
84185
|
-
return
|
|
84588
|
+
return path88.join(baseDir, name, SESSIONS_SUBDIR);
|
|
84186
84589
|
}
|
|
84187
84590
|
function readBranchMeta(name, baseDir) {
|
|
84188
84591
|
const metaPath = metaPathFor(name, baseDir);
|
|
@@ -84207,13 +84610,13 @@ function readBranchMeta(name, baseDir) {
|
|
|
84207
84610
|
}
|
|
84208
84611
|
function writeBranchMeta(name, baseDir, meta3) {
|
|
84209
84612
|
const metaPath = metaPathFor(name, baseDir);
|
|
84210
|
-
mkdirSync21(
|
|
84613
|
+
mkdirSync21(path88.dirname(metaPath), { recursive: true });
|
|
84211
84614
|
writeFileSync24(metaPath, JSON.stringify(meta3, null, 2), "utf-8");
|
|
84212
84615
|
}
|
|
84213
84616
|
async function countSessions(name, baseDir) {
|
|
84214
84617
|
const sessionsPath = sessionsPathFor(name, baseDir);
|
|
84215
84618
|
try {
|
|
84216
|
-
const entries = await
|
|
84619
|
+
const entries = await fs42.readdir(sessionsPath);
|
|
84217
84620
|
return entries.filter((e) => e.endsWith(".jsonl")).length;
|
|
84218
84621
|
} catch (err) {
|
|
84219
84622
|
if (err.code === "ENOENT") return 0;
|
|
@@ -84258,15 +84661,15 @@ async function createBranch(name, fromSessionId, baseDir = getBranchesBaseDir(),
|
|
|
84258
84661
|
if (branchExists(name, baseDir)) {
|
|
84259
84662
|
throw new BranchAlreadyExistsError(name);
|
|
84260
84663
|
}
|
|
84261
|
-
const sourcePath =
|
|
84664
|
+
const sourcePath = path88.join(sessionsBaseDir, `${fromSessionId}.jsonl`);
|
|
84262
84665
|
if (!existsSync55(sourcePath)) {
|
|
84263
84666
|
throw new SessionNotFoundError(`Source session "${fromSessionId}" not found at ${sourcePath}`);
|
|
84264
84667
|
}
|
|
84265
84668
|
const branchPath = branchPathFor(name, baseDir);
|
|
84266
84669
|
const branchSessionsPath = sessionsPathFor(name, baseDir);
|
|
84267
84670
|
mkdirSync21(branchSessionsPath, { recursive: true });
|
|
84268
|
-
const destPath =
|
|
84269
|
-
await
|
|
84671
|
+
const destPath = path88.join(branchSessionsPath, `${fromSessionId}.jsonl`);
|
|
84672
|
+
await fs42.copyFile(sourcePath, destPath);
|
|
84270
84673
|
const meta3 = {
|
|
84271
84674
|
name,
|
|
84272
84675
|
createdAt: Date.now(),
|
|
@@ -84284,7 +84687,7 @@ async function createBranch(name, fromSessionId, baseDir = getBranchesBaseDir(),
|
|
|
84284
84687
|
async function listBranches(baseDir = getBranchesBaseDir()) {
|
|
84285
84688
|
let entries;
|
|
84286
84689
|
try {
|
|
84287
|
-
entries = await
|
|
84690
|
+
entries = await fs42.readdir(baseDir);
|
|
84288
84691
|
} catch (err) {
|
|
84289
84692
|
if (err.code === "ENOENT") return [];
|
|
84290
84693
|
throw err;
|
|
@@ -84368,26 +84771,26 @@ async function handleBranchCheckout(ctx, branchName) {
|
|
|
84368
84771
|
|
|
84369
84772
|
// src/cli/slashHandlers/workspace.ts
|
|
84370
84773
|
init_messageHelpers();
|
|
84371
|
-
import { promises as
|
|
84372
|
-
import
|
|
84774
|
+
import { promises as fs43 } from "node:fs";
|
|
84775
|
+
import path89 from "node:path";
|
|
84373
84776
|
async function handleWorkspaceShow(ctx, what) {
|
|
84374
84777
|
try {
|
|
84375
|
-
const zelari =
|
|
84778
|
+
const zelari = path89.join(process.cwd(), ".zelari");
|
|
84376
84779
|
let content;
|
|
84377
84780
|
switch (what) {
|
|
84378
84781
|
case "plan": {
|
|
84379
|
-
const planPath =
|
|
84782
|
+
const planPath = path89.join(zelari, "plan.md");
|
|
84380
84783
|
try {
|
|
84381
|
-
content = await
|
|
84784
|
+
content = await fs43.readFile(planPath, "utf-8");
|
|
84382
84785
|
} catch {
|
|
84383
84786
|
content = "(no plan.md yet \u2014 run a council session first)";
|
|
84384
84787
|
}
|
|
84385
84788
|
break;
|
|
84386
84789
|
}
|
|
84387
84790
|
case "decisions": {
|
|
84388
|
-
const decisionsDir =
|
|
84791
|
+
const decisionsDir = path89.join(zelari, "decisions");
|
|
84389
84792
|
try {
|
|
84390
|
-
const files = (await
|
|
84793
|
+
const files = (await fs43.readdir(decisionsDir)).filter((f) => f.endsWith(".md")).sort();
|
|
84391
84794
|
if (files.length === 0) {
|
|
84392
84795
|
content = "(no ADRs yet \u2014 invoke /council to generate some)";
|
|
84393
84796
|
} else {
|
|
@@ -84395,7 +84798,7 @@ async function handleWorkspaceShow(ctx, what) {
|
|
|
84395
84798
|
`];
|
|
84396
84799
|
const { parseFrontmatter: parseFrontmatter2 } = await Promise.resolve().then(() => (init_storage(), storage_exports));
|
|
84397
84800
|
for (const f of files) {
|
|
84398
|
-
const raw = await
|
|
84801
|
+
const raw = await fs43.readFile(path89.join(decisionsDir, f), "utf-8");
|
|
84399
84802
|
const { meta: meta3, body } = parseFrontmatter2(raw);
|
|
84400
84803
|
const title = meta3.title ?? body.split("\n")[0]?.replace(/^#\s*/, "").trim() ?? f;
|
|
84401
84804
|
lines.push(`- **${f.replace(/\.md$/, "")}** [${meta3.status ?? "unknown"}] ${title}`);
|
|
@@ -84408,27 +84811,27 @@ async function handleWorkspaceShow(ctx, what) {
|
|
|
84408
84811
|
break;
|
|
84409
84812
|
}
|
|
84410
84813
|
case "risks": {
|
|
84411
|
-
const risksPath =
|
|
84814
|
+
const risksPath = path89.join(zelari, "risks.md");
|
|
84412
84815
|
try {
|
|
84413
|
-
content = await
|
|
84816
|
+
content = await fs43.readFile(risksPath, "utf-8");
|
|
84414
84817
|
} catch {
|
|
84415
84818
|
content = "(no risks.md yet)";
|
|
84416
84819
|
}
|
|
84417
84820
|
break;
|
|
84418
84821
|
}
|
|
84419
84822
|
case "agents": {
|
|
84420
|
-
const agentsPath =
|
|
84823
|
+
const agentsPath = path89.join(process.cwd(), "AGENTS.MD");
|
|
84421
84824
|
try {
|
|
84422
|
-
content = await
|
|
84825
|
+
content = await fs43.readFile(agentsPath, "utf-8");
|
|
84423
84826
|
} catch {
|
|
84424
84827
|
content = "(no AGENTS.MD yet at project root \u2014 run `/workspace sync` after a council session)";
|
|
84425
84828
|
}
|
|
84426
84829
|
break;
|
|
84427
84830
|
}
|
|
84428
84831
|
case "docs": {
|
|
84429
|
-
const docsDir =
|
|
84832
|
+
const docsDir = path89.join(zelari, "docs");
|
|
84430
84833
|
try {
|
|
84431
|
-
const files = (await
|
|
84834
|
+
const files = (await fs43.readdir(docsDir)).filter((f) => f.endsWith(".md")).sort();
|
|
84432
84835
|
content = files.length ? `# Docs (${files.length})
|
|
84433
84836
|
|
|
84434
84837
|
` + files.map((f) => `- ${f}`).join("\n") : "(no docs drafts yet)";
|
|
@@ -84468,8 +84871,8 @@ async function handleWorkspaceReset(ctx, force) {
|
|
|
84468
84871
|
return;
|
|
84469
84872
|
}
|
|
84470
84873
|
try {
|
|
84471
|
-
const target =
|
|
84472
|
-
await
|
|
84874
|
+
const target = path89.join(process.cwd(), ".zelari");
|
|
84875
|
+
await fs43.rm(target, { recursive: true, force: true });
|
|
84473
84876
|
appendSystem(ctx.setMessages, "[workspace] .zelari/ removed");
|
|
84474
84877
|
} catch (err) {
|
|
84475
84878
|
appendSystem(ctx.setMessages, `[workspace reset error] ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -84480,13 +84883,13 @@ async function handleWorkspaceReset(ctx, force) {
|
|
|
84480
84883
|
init_provider2();
|
|
84481
84884
|
|
|
84482
84885
|
// src/cli/skillHistory.ts
|
|
84483
|
-
import { promises as
|
|
84886
|
+
import { promises as fs44, existsSync as existsSync56, statSync as statSync8, renameSync as renameSync6, appendFileSync as appendFileSync5, mkdirSync as mkdirSync22 } from "node:fs";
|
|
84484
84887
|
init_paths();
|
|
84485
84888
|
var SKILL_HISTORY_ROTATE_BYTES = 10 * 1024 * 1024;
|
|
84486
84889
|
async function readSkillHistory(file2) {
|
|
84487
84890
|
let raw = "";
|
|
84488
84891
|
try {
|
|
84489
|
-
raw = await
|
|
84892
|
+
raw = await fs44.readFile(file2, "utf-8");
|
|
84490
84893
|
} catch {
|
|
84491
84894
|
return [];
|
|
84492
84895
|
}
|
|
@@ -86366,8 +86769,8 @@ function normalizeDraft(raw, sourceUrl, provider, model) {
|
|
|
86366
86769
|
let name = String(o.name ?? "").trim().toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 64);
|
|
86367
86770
|
if (!name || !/^[a-z0-9][a-z0-9-]{0,63}$/.test(name)) {
|
|
86368
86771
|
try {
|
|
86369
|
-
const
|
|
86370
|
-
name =
|
|
86772
|
+
const path103 = new URL(sourceUrl).pathname.split("/").filter(Boolean).pop()?.replace(/\.[a-z0-9]+$/i, "").toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 48);
|
|
86773
|
+
name = path103 && /^[a-z0-9]/.test(path103) ? path103 : "imported-skill";
|
|
86371
86774
|
} catch {
|
|
86372
86775
|
name = "imported-skill";
|
|
86373
86776
|
}
|