zelari-code 2.56.0 → 2.57.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/budget/modelContextBuilder.js +4 -1
- package/dist/cli/budget/modelContextBuilder.js.map +1 -1
- package/dist/cli/evolution/ledger.js +85 -0
- package/dist/cli/evolution/ledger.js.map +1 -1
- package/dist/cli/evolution/patternLedger.js +165 -0
- package/dist/cli/evolution/patternLedger.js.map +1 -0
- package/dist/cli/headless/runOneTurn.js +13 -1
- package/dist/cli/headless/runOneTurn.js.map +1 -1
- package/dist/cli/hooks/useChatTurn.js +21 -1
- package/dist/cli/hooks/useChatTurn.js.map +1 -1
- package/dist/cli/main.bundled.js +1246 -662
- package/dist/cli/main.bundled.js.map +4 -4
- package/dist/cli/memory/mcpAdapter.js +3 -1
- package/dist/cli/memory/mcpAdapter.js.map +1 -1
- package/dist/cli/memory/onePager.js +93 -0
- package/dist/cli/memory/onePager.js.map +1 -0
- package/dist/cli/memory/serviceFactory.js +5 -0
- package/dist/cli/memory/serviceFactory.js.map +1 -1
- package/dist/cli/memory/sqliteBackend.js +40 -3
- package/dist/cli/memory/sqliteBackend.js.map +1 -1
- package/dist/cli/memory/sqliteCodec.js +2 -0
- package/dist/cli/memory/sqliteCodec.js.map +1 -1
- package/dist/cli/memory/sqliteSchema.js +11 -1
- package/dist/cli/memory/sqliteSchema.js.map +1 -1
- package/dist/cli/runHeadless.js +62 -12
- package/dist/cli/runHeadless.js.map +1 -1
- package/dist/cli/slashCommands.js +1 -1
- package/dist/cli/slashHandlers/memory.js +21 -0
- package/dist/cli/slashHandlers/memory.js.map +1 -1
- package/dist/cli/toolResultCache.js +4 -22
- package/dist/cli/toolResultCache.js.map +1 -1
- package/package.json +3 -2
package/dist/cli/main.bundled.js
CHANGED
|
@@ -3876,10 +3876,10 @@ function mergeDefs(...defs) {
|
|
|
3876
3876
|
function cloneDef(schema) {
|
|
3877
3877
|
return mergeDefs(schema._zod.def);
|
|
3878
3878
|
}
|
|
3879
|
-
function getElementAtPath(obj,
|
|
3880
|
-
if (!
|
|
3879
|
+
function getElementAtPath(obj, path128) {
|
|
3880
|
+
if (!path128)
|
|
3881
3881
|
return obj;
|
|
3882
|
-
return
|
|
3882
|
+
return path128.reduce((acc, key) => acc?.[key], obj);
|
|
3883
3883
|
}
|
|
3884
3884
|
function promiseAllObject(promisesObj) {
|
|
3885
3885
|
const keys = Object.keys(promisesObj);
|
|
@@ -4207,11 +4207,11 @@ function explicitlyAborted(x, startIndex = 0) {
|
|
|
4207
4207
|
}
|
|
4208
4208
|
return false;
|
|
4209
4209
|
}
|
|
4210
|
-
function prefixIssues(
|
|
4210
|
+
function prefixIssues(path128, issues) {
|
|
4211
4211
|
return issues.map((iss) => {
|
|
4212
4212
|
var _a3;
|
|
4213
4213
|
(_a3 = iss).path ?? (_a3.path = []);
|
|
4214
|
-
iss.path.unshift(
|
|
4214
|
+
iss.path.unshift(path128);
|
|
4215
4215
|
return iss;
|
|
4216
4216
|
});
|
|
4217
4217
|
}
|
|
@@ -4429,16 +4429,16 @@ function flattenError(error51, mapper = (issue2) => issue2.message) {
|
|
|
4429
4429
|
}
|
|
4430
4430
|
function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
4431
4431
|
const fieldErrors = { _errors: [] };
|
|
4432
|
-
const processError = (error52,
|
|
4432
|
+
const processError = (error52, path128 = []) => {
|
|
4433
4433
|
for (const issue2 of error52.issues) {
|
|
4434
4434
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
4435
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
4435
|
+
issue2.errors.map((issues) => processError({ issues }, [...path128, ...issue2.path]));
|
|
4436
4436
|
} else if (issue2.code === "invalid_key") {
|
|
4437
|
-
processError({ issues: issue2.issues }, [...
|
|
4437
|
+
processError({ issues: issue2.issues }, [...path128, ...issue2.path]);
|
|
4438
4438
|
} else if (issue2.code === "invalid_element") {
|
|
4439
|
-
processError({ issues: issue2.issues }, [...
|
|
4439
|
+
processError({ issues: issue2.issues }, [...path128, ...issue2.path]);
|
|
4440
4440
|
} else {
|
|
4441
|
-
const fullpath = [...
|
|
4441
|
+
const fullpath = [...path128, ...issue2.path];
|
|
4442
4442
|
if (fullpath.length === 0) {
|
|
4443
4443
|
fieldErrors._errors.push(mapper(issue2));
|
|
4444
4444
|
} else {
|
|
@@ -4465,17 +4465,17 @@ function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
|
4465
4465
|
}
|
|
4466
4466
|
function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
4467
4467
|
const result = { errors: [] };
|
|
4468
|
-
const processError = (error52,
|
|
4468
|
+
const processError = (error52, path128 = []) => {
|
|
4469
4469
|
var _a3, _b;
|
|
4470
4470
|
for (const issue2 of error52.issues) {
|
|
4471
4471
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
4472
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
4472
|
+
issue2.errors.map((issues) => processError({ issues }, [...path128, ...issue2.path]));
|
|
4473
4473
|
} else if (issue2.code === "invalid_key") {
|
|
4474
|
-
processError({ issues: issue2.issues }, [...
|
|
4474
|
+
processError({ issues: issue2.issues }, [...path128, ...issue2.path]);
|
|
4475
4475
|
} else if (issue2.code === "invalid_element") {
|
|
4476
|
-
processError({ issues: issue2.issues }, [...
|
|
4476
|
+
processError({ issues: issue2.issues }, [...path128, ...issue2.path]);
|
|
4477
4477
|
} else {
|
|
4478
|
-
const fullpath = [...
|
|
4478
|
+
const fullpath = [...path128, ...issue2.path];
|
|
4479
4479
|
if (fullpath.length === 0) {
|
|
4480
4480
|
result.errors.push(mapper(issue2));
|
|
4481
4481
|
continue;
|
|
@@ -4507,8 +4507,8 @@ function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
|
4507
4507
|
}
|
|
4508
4508
|
function toDotPath(_path) {
|
|
4509
4509
|
const segs = [];
|
|
4510
|
-
const
|
|
4511
|
-
for (const seg of
|
|
4510
|
+
const path128 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
4511
|
+
for (const seg of path128) {
|
|
4512
4512
|
if (typeof seg === "number")
|
|
4513
4513
|
segs.push(`[${seg}]`);
|
|
4514
4514
|
else if (typeof seg === "symbol")
|
|
@@ -18011,13 +18011,13 @@ function resolveRef(ref, ctx) {
|
|
|
18011
18011
|
if (!ref.startsWith("#")) {
|
|
18012
18012
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
18013
18013
|
}
|
|
18014
|
-
const
|
|
18015
|
-
if (
|
|
18014
|
+
const path128 = ref.slice(1).split("/").filter(Boolean);
|
|
18015
|
+
if (path128.length === 0) {
|
|
18016
18016
|
return ctx.rootSchema;
|
|
18017
18017
|
}
|
|
18018
18018
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
18019
|
-
if (
|
|
18020
|
-
const key =
|
|
18019
|
+
if (path128[0] === defsKey) {
|
|
18020
|
+
const key = path128[1];
|
|
18021
18021
|
if (!key || !ctx.defs[key]) {
|
|
18022
18022
|
throw new Error(`Reference not found: ${ref}`);
|
|
18023
18023
|
}
|
|
@@ -18851,17 +18851,17 @@ var init_newlines = __esm({
|
|
|
18851
18851
|
});
|
|
18852
18852
|
|
|
18853
18853
|
// packages/core/dist/core/tools/builtin/fileEvents.js
|
|
18854
|
-
function fileReadEvent(
|
|
18855
|
-
return { kind: "file.read", actor: { type: "tool" }, data: { path:
|
|
18854
|
+
function fileReadEvent(path128, snapshotId) {
|
|
18855
|
+
return { kind: "file.read", actor: { type: "tool" }, data: { path: path128, snapshotId } };
|
|
18856
18856
|
}
|
|
18857
|
-
function fileAppliedEvent(
|
|
18858
|
-
return { kind: "file.applied", actor: { type: "tool" }, data: { path:
|
|
18857
|
+
function fileAppliedEvent(path128, snapshotId, bytes) {
|
|
18858
|
+
return { kind: "file.applied", actor: { type: "tool" }, data: { path: path128, snapshotId, bytes } };
|
|
18859
18859
|
}
|
|
18860
|
-
function fileRejectedEvent(
|
|
18860
|
+
function fileRejectedEvent(path128, reason, hint) {
|
|
18861
18861
|
return {
|
|
18862
18862
|
kind: "file.rejected",
|
|
18863
18863
|
actor: { type: "tool" },
|
|
18864
|
-
data: hint === void 0 ? { path:
|
|
18864
|
+
data: hint === void 0 ? { path: path128, reason } : { path: path128, reason, hint }
|
|
18865
18865
|
};
|
|
18866
18866
|
}
|
|
18867
18867
|
function reReadHint(reject) {
|
|
@@ -20817,11 +20817,11 @@ var init_tools = __esm({
|
|
|
20817
20817
|
if (!ctx.addDocument)
|
|
20818
20818
|
return "Knowledge vault tool not available.";
|
|
20819
20819
|
const title = args["title"] || "New Document";
|
|
20820
|
-
const
|
|
20820
|
+
const path128 = args["path"] || `notes/${title.toLowerCase().replace(/[^a-z0-9]+/g, "-")}`;
|
|
20821
20821
|
const content = args["content"] || "";
|
|
20822
20822
|
const tags = args["tags"] || [];
|
|
20823
20823
|
ctx.addDocument({
|
|
20824
|
-
path:
|
|
20824
|
+
path: path128,
|
|
20825
20825
|
title,
|
|
20826
20826
|
content,
|
|
20827
20827
|
format: "markdown",
|
|
@@ -20830,7 +20830,7 @@ var init_tools = __esm({
|
|
|
20830
20830
|
workspaceId: ctx.workspaceId
|
|
20831
20831
|
});
|
|
20832
20832
|
ctx.addActivity("vault", "created document", title);
|
|
20833
|
-
return `Document "${title}" created at "${
|
|
20833
|
+
return `Document "${title}" created at "${path128}".`;
|
|
20834
20834
|
}
|
|
20835
20835
|
}
|
|
20836
20836
|
];
|
|
@@ -24666,7 +24666,7 @@ async function createExecutionContext(options = {}) {
|
|
|
24666
24666
|
workspaceKind: workspace.kind
|
|
24667
24667
|
}
|
|
24668
24668
|
});
|
|
24669
|
-
const
|
|
24669
|
+
const fs52 = options.fs ?? new NodeFsProvider(workspace);
|
|
24670
24670
|
const shell = options.shell ?? new NodeShellProvider(workspace);
|
|
24671
24671
|
const subagent = options.subagent ?? NOOP_SUBAGENT_PROVIDER;
|
|
24672
24672
|
const env = options.env ?? process.env;
|
|
@@ -24674,7 +24674,7 @@ async function createExecutionContext(options = {}) {
|
|
|
24674
24674
|
sessionId: sessionId2,
|
|
24675
24675
|
profile,
|
|
24676
24676
|
workspace,
|
|
24677
|
-
fs:
|
|
24677
|
+
fs: fs52,
|
|
24678
24678
|
shell,
|
|
24679
24679
|
subagent,
|
|
24680
24680
|
appendSessionEvent: (input) => writer.append(input),
|
|
@@ -26075,16 +26075,16 @@ function runRetentionFromEnv() {
|
|
|
26075
26075
|
maxTotalBytes: Number.isFinite(parseMb) && parseMb > 0 ? Math.round(parseMb * 1024 * 1024) : DEFAULT_RUN_RETENTION_MAX_MB * 1024 * 1024
|
|
26076
26076
|
};
|
|
26077
26077
|
}
|
|
26078
|
-
async function dirSize(
|
|
26078
|
+
async function dirSize(path128) {
|
|
26079
26079
|
let total = 0;
|
|
26080
26080
|
let entries;
|
|
26081
26081
|
try {
|
|
26082
|
-
entries = await readdir(
|
|
26082
|
+
entries = await readdir(path128, { withFileTypes: true });
|
|
26083
26083
|
} catch {
|
|
26084
26084
|
return 0;
|
|
26085
26085
|
}
|
|
26086
26086
|
for (const entry of entries) {
|
|
26087
|
-
const child = join3(
|
|
26087
|
+
const child = join3(path128, entry.name);
|
|
26088
26088
|
if (entry.isDirectory())
|
|
26089
26089
|
total += await dirSize(child);
|
|
26090
26090
|
else {
|
|
@@ -26111,19 +26111,19 @@ async function enforceRunRetention(runsDir, options = {}) {
|
|
|
26111
26111
|
for (const entry of entries) {
|
|
26112
26112
|
if (!entry.isDirectory())
|
|
26113
26113
|
continue;
|
|
26114
|
-
const
|
|
26114
|
+
const path128 = join3(runsDir, entry.name);
|
|
26115
26115
|
let startedAt = 0;
|
|
26116
26116
|
let endedAt;
|
|
26117
26117
|
let completed = false;
|
|
26118
26118
|
try {
|
|
26119
|
-
const manifest = JSON.parse(await readFile(join3(
|
|
26119
|
+
const manifest = JSON.parse(await readFile(join3(path128, "manifest.json"), "utf8"));
|
|
26120
26120
|
startedAt = manifest.startedAt ?? 0;
|
|
26121
26121
|
endedAt = manifest.endedAt;
|
|
26122
26122
|
completed = Boolean(endedAt) && manifest.status !== "running";
|
|
26123
26123
|
} catch {
|
|
26124
26124
|
completed = false;
|
|
26125
26125
|
}
|
|
26126
|
-
infos.push({ name: entry.name, path:
|
|
26126
|
+
infos.push({ name: entry.name, path: path128, startedAt, endedAt, completed, bytes: await dirSize(path128) });
|
|
26127
26127
|
}
|
|
26128
26128
|
const remove = async (info) => {
|
|
26129
26129
|
await rm(info.path, { recursive: true, force: true });
|
|
@@ -26681,12 +26681,12 @@ var init_engine = __esm({
|
|
|
26681
26681
|
* content digest) and the returned ref carries the event seq when the
|
|
26682
26682
|
* emitter resolved one.
|
|
26683
26683
|
*/
|
|
26684
|
-
async fsEvidence(observation,
|
|
26684
|
+
async fsEvidence(observation, path128, sha2562, content, extra = {}) {
|
|
26685
26685
|
const digest = sha2562 && content !== void 0 ? sha2562(content) : void 0;
|
|
26686
|
-
const seq = await this.emitEvidence({ observation, path:
|
|
26686
|
+
const seq = await this.emitEvidence({ observation, path: path128, ...extra, ...digest ? { digest } : {} });
|
|
26687
26687
|
return {
|
|
26688
26688
|
tier: "fs-observation",
|
|
26689
|
-
ref:
|
|
26689
|
+
ref: path128,
|
|
26690
26690
|
capturedAt: Date.now(),
|
|
26691
26691
|
...digest ? { digest } : {},
|
|
26692
26692
|
...seq !== void 0 ? { seq } : {}
|
|
@@ -26694,25 +26694,25 @@ var init_engine = __esm({
|
|
|
26694
26694
|
}
|
|
26695
26695
|
async evalFileExists(check2, done) {
|
|
26696
26696
|
const sha2562 = this.options.sha256 ?? defaultSha256;
|
|
26697
|
-
const
|
|
26698
|
-
if (!
|
|
26697
|
+
const fs52 = this.services.fs;
|
|
26698
|
+
if (!fs52)
|
|
26699
26699
|
return done({ status: "unknown", evidence: [], detail: "fs provider unavailable" });
|
|
26700
|
-
const exists = await
|
|
26700
|
+
const exists = await fs52.exists(check2.path);
|
|
26701
26701
|
if (!exists) {
|
|
26702
26702
|
await this.emitEvidence({ observation: "file-exists", path: check2.path, exists: false });
|
|
26703
26703
|
return done({ status: "fail", evidence: [], detail: `file not found: ${check2.path}` });
|
|
26704
26704
|
}
|
|
26705
|
-
const content = await
|
|
26705
|
+
const content = await fs52.readFile(check2.path).catch(() => "");
|
|
26706
26706
|
return done({
|
|
26707
26707
|
status: "pass",
|
|
26708
26708
|
evidence: [await this.fsEvidence("file-exists", check2.path, sha2562, content, { exists: true })]
|
|
26709
26709
|
});
|
|
26710
26710
|
}
|
|
26711
26711
|
async evalFileAbsent(check2, done) {
|
|
26712
|
-
const
|
|
26713
|
-
if (!
|
|
26712
|
+
const fs52 = this.services.fs;
|
|
26713
|
+
if (!fs52)
|
|
26714
26714
|
return done({ status: "unknown", evidence: [], detail: "fs provider unavailable" });
|
|
26715
|
-
const exists = await
|
|
26715
|
+
const exists = await fs52.exists(check2.path);
|
|
26716
26716
|
if (exists) {
|
|
26717
26717
|
await this.emitEvidence({ observation: "file-absent", path: check2.path, exists: true });
|
|
26718
26718
|
return done({ status: "fail", evidence: [], detail: `file still present: ${check2.path}` });
|
|
@@ -26724,12 +26724,12 @@ var init_engine = __esm({
|
|
|
26724
26724
|
}
|
|
26725
26725
|
async evalFileContains(check2, done) {
|
|
26726
26726
|
const sha2562 = this.options.sha256 ?? defaultSha256;
|
|
26727
|
-
const
|
|
26728
|
-
if (!
|
|
26727
|
+
const fs52 = this.services.fs;
|
|
26728
|
+
if (!fs52)
|
|
26729
26729
|
return done({ status: "unknown", evidence: [], detail: "fs provider unavailable" });
|
|
26730
26730
|
let content;
|
|
26731
26731
|
try {
|
|
26732
|
-
content = await
|
|
26732
|
+
content = await fs52.readFile(check2.path);
|
|
26733
26733
|
} catch {
|
|
26734
26734
|
await this.emitEvidence({ observation: "file-contains", path: check2.path, readable: false });
|
|
26735
26735
|
return done({ status: "fail", evidence: [], detail: `file not readable: ${check2.path}` });
|
|
@@ -28463,8 +28463,8 @@ function strictEnvOverlay(knobs, base2 = process.env) {
|
|
|
28463
28463
|
return overlay;
|
|
28464
28464
|
}
|
|
28465
28465
|
function criterionId(check2, index) {
|
|
28466
|
-
const
|
|
28467
|
-
return `check-${index + 1}-${
|
|
28466
|
+
const slug2 = check2.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 48);
|
|
28467
|
+
return `check-${index + 1}-${slug2 || "criterion"}`;
|
|
28468
28468
|
}
|
|
28469
28469
|
function normalize3(text) {
|
|
28470
28470
|
return text.toLowerCase().replace(/\s+/g, " ").trim();
|
|
@@ -34430,11 +34430,11 @@ var init_synthesisAudit = __esm({
|
|
|
34430
34430
|
import { existsSync as existsSync16, readFileSync as readFileSync15, writeFileSync as writeFileSync8 } from "node:fs";
|
|
34431
34431
|
import { join as join5 } from "node:path";
|
|
34432
34432
|
function loadNfrSpec(zelariRoot) {
|
|
34433
|
-
const
|
|
34434
|
-
if (!existsSync16(
|
|
34433
|
+
const path128 = join5(zelariRoot, "nfr-spec.json");
|
|
34434
|
+
if (!existsSync16(path128))
|
|
34435
34435
|
return null;
|
|
34436
34436
|
try {
|
|
34437
|
-
const raw = JSON.parse(readFileSync15(
|
|
34437
|
+
const raw = JSON.parse(readFileSync15(path128, "utf8"));
|
|
34438
34438
|
if (raw.version !== 1 || !Array.isArray(raw.targets))
|
|
34439
34439
|
return null;
|
|
34440
34440
|
return raw;
|
|
@@ -36835,9 +36835,9 @@ var init_types9 = __esm({
|
|
|
36835
36835
|
import { readFileSync as readFileSync20 } from "node:fs";
|
|
36836
36836
|
import { join as join11 } from "node:path";
|
|
36837
36837
|
function readLessonsDeduped(zelariRoot) {
|
|
36838
|
-
const
|
|
36838
|
+
const path128 = join11(zelariRoot, LESSONS_FILE);
|
|
36839
36839
|
try {
|
|
36840
|
-
const raw = readFileSync20(
|
|
36840
|
+
const raw = readFileSync20(path128, "utf8");
|
|
36841
36841
|
const byId = /* @__PURE__ */ new Map();
|
|
36842
36842
|
for (const line of raw.split(/\r?\n/)) {
|
|
36843
36843
|
if (!line.trim())
|
|
@@ -36938,8 +36938,8 @@ function keywordsFrom(check2, signature) {
|
|
|
36938
36938
|
return [.../* @__PURE__ */ new Set([...fromId, ...words])].slice(0, 12);
|
|
36939
36939
|
}
|
|
36940
36940
|
function writeLesson(zelariRoot, lesson) {
|
|
36941
|
-
const
|
|
36942
|
-
appendFileSync(
|
|
36941
|
+
const path128 = join12(zelariRoot, LESSONS_FILE);
|
|
36942
|
+
appendFileSync(path128, `${JSON.stringify(lesson)}
|
|
36943
36943
|
`, "utf8");
|
|
36944
36944
|
}
|
|
36945
36945
|
function findSimilar(lessons, signature) {
|
|
@@ -37550,7 +37550,7 @@ var init_types11 = __esm({
|
|
|
37550
37550
|
});
|
|
37551
37551
|
|
|
37552
37552
|
// packages/core/dist/memory/schemas.js
|
|
37553
|
-
var isoDate, unit, metadata, MemoryKindSchema, MemoryStatusSchema, MemoryRelationSchema, MemoryVisibilitySchema, MemorySourceSchema, MemoryNodeInputSchema, MemoryNodeSchema, MemoryEdgeInputSchema, MemoryEdgeSchema;
|
|
37553
|
+
var isoDate, unit, metadata, relevantWhen, MemoryKindSchema, MemoryStatusSchema, MemoryRelationSchema, MemoryVisibilitySchema, MemorySourceSchema, MemoryNodeInputSchema, MemoryNodeSchema, MemoryEdgeInputSchema, MemoryEdgeSchema;
|
|
37554
37554
|
var init_schemas3 = __esm({
|
|
37555
37555
|
"packages/core/dist/memory/schemas.js"() {
|
|
37556
37556
|
"use strict";
|
|
@@ -37565,6 +37565,7 @@ var init_schemas3 = __esm({
|
|
|
37565
37565
|
return false;
|
|
37566
37566
|
}
|
|
37567
37567
|
}, "Memory metadata must be JSON-serializable and no larger than 128 KB.");
|
|
37568
|
+
relevantWhen = external_exports.array(external_exports.string().min(1).max(120)).max(8).optional();
|
|
37568
37569
|
MemoryKindSchema = external_exports.enum(MEMORY_KINDS);
|
|
37569
37570
|
MemoryStatusSchema = external_exports.enum(MEMORY_STATUSES);
|
|
37570
37571
|
MemoryRelationSchema = external_exports.enum(MEMORY_RELATIONS);
|
|
@@ -37596,6 +37597,7 @@ var init_schemas3 = __esm({
|
|
|
37596
37597
|
status: MemoryStatusSchema.optional(),
|
|
37597
37598
|
visibility: MemoryVisibilitySchema.optional(),
|
|
37598
37599
|
tags: external_exports.array(external_exports.string().min(1).max(120)).max(64).optional(),
|
|
37600
|
+
relevantWhen,
|
|
37599
37601
|
source: MemorySourceSchema.optional(),
|
|
37600
37602
|
createdAt: isoDate.optional(),
|
|
37601
37603
|
recordedAt: isoDate.optional(),
|
|
@@ -37678,11 +37680,13 @@ function scoreMemoryCandidate(candidate, query, options = {}) {
|
|
|
37678
37680
|
confidence: node.confidence,
|
|
37679
37681
|
recency: recencyScore(node.updatedAt, options.now, options.recencyHalfLifeDays),
|
|
37680
37682
|
graphProximity: Math.max(0, Math.min(1, candidate.graphProximity ?? 0)),
|
|
37681
|
-
verificationBonus: verified(node)
|
|
37683
|
+
verificationBonus: verified(node),
|
|
37684
|
+
triggerMatch: Math.max(0, Math.min(1, candidate.triggerMatch ?? 0))
|
|
37682
37685
|
};
|
|
37683
37686
|
const weights = { ...DEFAULT_MEMORY_SCORING_WEIGHTS, ...options.weights };
|
|
37684
37687
|
const semanticAvailable = candidate.semanticRelevance !== void 0;
|
|
37685
|
-
const
|
|
37688
|
+
const triggerAvailable = candidate.triggerMatch !== void 0;
|
|
37689
|
+
const activeEntries = Object.entries(weights).filter(([key]) => (semanticAvailable || key !== "semanticRelevance") && (triggerAvailable || key !== "triggerMatch"));
|
|
37686
37690
|
const totalWeight = activeEntries.reduce((sum, [, weight]) => sum + Math.max(0, weight), 0);
|
|
37687
37691
|
const weighted = activeEntries.reduce((sum, [key, weight]) => sum + signals[key] * Math.max(0, weight), 0);
|
|
37688
37692
|
const score = totalWeight > 0 ? weighted / totalWeight : 0;
|
|
@@ -37702,11 +37706,117 @@ var init_scoring = __esm({
|
|
|
37702
37706
|
confidence: 0.1,
|
|
37703
37707
|
recency: 0.1,
|
|
37704
37708
|
graphProximity: 0.1,
|
|
37705
|
-
verificationBonus: 0.05
|
|
37709
|
+
verificationBonus: 0.05,
|
|
37710
|
+
// A trigger hit is a strong "this memory is useful now" signal; weight it
|
|
37711
|
+
// above lexical overlap so an associative match beats a loose keyword match.
|
|
37712
|
+
triggerMatch: 0.4
|
|
37706
37713
|
};
|
|
37707
37714
|
}
|
|
37708
37715
|
});
|
|
37709
37716
|
|
|
37717
|
+
// packages/core/dist/memory/relevantWhen.js
|
|
37718
|
+
function keyTokens(value) {
|
|
37719
|
+
const seen = /* @__PURE__ */ new Set();
|
|
37720
|
+
const out = [];
|
|
37721
|
+
for (const token of memoryTokens(value)) {
|
|
37722
|
+
if (token.length < 3 || token.length > MAX_TOKEN_LENGTH)
|
|
37723
|
+
continue;
|
|
37724
|
+
if (STOPWORDS.has(token) || seen.has(token))
|
|
37725
|
+
continue;
|
|
37726
|
+
seen.add(token);
|
|
37727
|
+
out.push(token);
|
|
37728
|
+
}
|
|
37729
|
+
return out;
|
|
37730
|
+
}
|
|
37731
|
+
function clip(phrase) {
|
|
37732
|
+
const trimmed = phrase.replace(/\s+/g, " ").trim();
|
|
37733
|
+
return trimmed.length <= MAX_PHRASE_LENGTH ? trimmed : `${trimmed.slice(0, MAX_PHRASE_LENGTH - 1).trimEnd()}\u2026`;
|
|
37734
|
+
}
|
|
37735
|
+
function deriveRelevantWhen(content, kind2, tags = []) {
|
|
37736
|
+
const tokens = keyTokens(content);
|
|
37737
|
+
for (const tag of tags) {
|
|
37738
|
+
for (const token of keyTokens(tag)) {
|
|
37739
|
+
if (!tokens.includes(token))
|
|
37740
|
+
tokens.push(token);
|
|
37741
|
+
}
|
|
37742
|
+
}
|
|
37743
|
+
if (tokens.length === 0)
|
|
37744
|
+
return [];
|
|
37745
|
+
if (kind2 === "failure") {
|
|
37746
|
+
const errorClass = tokens.find((token) => ERRORISH.test(token));
|
|
37747
|
+
const tool = tokens.find((token) => TOOLISH.test(token) && token !== errorClass) ?? tokens[0];
|
|
37748
|
+
return [clip(errorClass ? `when ${tool} fails with ${errorClass}` : `when ${tool} fails`)];
|
|
37749
|
+
}
|
|
37750
|
+
if (kind2 === "procedure") {
|
|
37751
|
+
const command = tokens.find((token) => TOOLISH.test(token)) ?? tokens[0];
|
|
37752
|
+
return [clip(`when running ${command}`)];
|
|
37753
|
+
}
|
|
37754
|
+
const phrases = [];
|
|
37755
|
+
for (const token of tokens) {
|
|
37756
|
+
if (phrases.length >= RELEVANT_WHEN_CAP)
|
|
37757
|
+
break;
|
|
37758
|
+
phrases.push(clip(`when ${token}`));
|
|
37759
|
+
}
|
|
37760
|
+
return [...new Set(phrases)];
|
|
37761
|
+
}
|
|
37762
|
+
var RELEVANT_WHEN_CAP, MAX_PHRASE_LENGTH, MAX_TOKEN_LENGTH, STOPWORDS, TOOLISH, ERRORISH;
|
|
37763
|
+
var init_relevantWhen = __esm({
|
|
37764
|
+
"packages/core/dist/memory/relevantWhen.js"() {
|
|
37765
|
+
"use strict";
|
|
37766
|
+
init_scoring();
|
|
37767
|
+
RELEVANT_WHEN_CAP = 3;
|
|
37768
|
+
MAX_PHRASE_LENGTH = 120;
|
|
37769
|
+
MAX_TOKEN_LENGTH = 24;
|
|
37770
|
+
STOPWORDS = /* @__PURE__ */ new Set([
|
|
37771
|
+
"the",
|
|
37772
|
+
"and",
|
|
37773
|
+
"for",
|
|
37774
|
+
"with",
|
|
37775
|
+
"that",
|
|
37776
|
+
"this",
|
|
37777
|
+
"from",
|
|
37778
|
+
"when",
|
|
37779
|
+
"into",
|
|
37780
|
+
"your",
|
|
37781
|
+
"you",
|
|
37782
|
+
"are",
|
|
37783
|
+
"was",
|
|
37784
|
+
"were",
|
|
37785
|
+
"has",
|
|
37786
|
+
"have",
|
|
37787
|
+
"had",
|
|
37788
|
+
"not",
|
|
37789
|
+
"but",
|
|
37790
|
+
"its",
|
|
37791
|
+
"also",
|
|
37792
|
+
"will",
|
|
37793
|
+
"can",
|
|
37794
|
+
"should",
|
|
37795
|
+
"must",
|
|
37796
|
+
"them",
|
|
37797
|
+
"they",
|
|
37798
|
+
"our",
|
|
37799
|
+
"out",
|
|
37800
|
+
"any",
|
|
37801
|
+
"all",
|
|
37802
|
+
"each",
|
|
37803
|
+
"per",
|
|
37804
|
+
"via",
|
|
37805
|
+
"use",
|
|
37806
|
+
"using",
|
|
37807
|
+
"get",
|
|
37808
|
+
"set",
|
|
37809
|
+
"new",
|
|
37810
|
+
"old",
|
|
37811
|
+
"one",
|
|
37812
|
+
"two",
|
|
37813
|
+
"may"
|
|
37814
|
+
]);
|
|
37815
|
+
TOOLISH = /(?:npm|pnpm|yarn|node|tsc|vitest|jest|eslint|prettier|docker|git|cargo|rustc|python|pip|go|mvn|gradle|make|curl|http|fetch|sqlite|postgres|redis|deploy|build|test|lint|install|migrate|migration)/i;
|
|
37816
|
+
ERRORISH = /(?:timeout|timedout|etimedout|econn|eaddrinuse|enoent|eacces|enospc|eexist|lock|locked|denied|refused|crash|signal|exhaust|oom|heap|exception|error|traceback|segfault|panic)/i;
|
|
37817
|
+
}
|
|
37818
|
+
});
|
|
37819
|
+
|
|
37710
37820
|
// packages/core/dist/memory/policies.js
|
|
37711
37821
|
function shannonEntropy(value) {
|
|
37712
37822
|
const counts = /* @__PURE__ */ new Map();
|
|
@@ -38148,6 +38258,7 @@ var init_service = __esm({
|
|
|
38148
38258
|
init_context2();
|
|
38149
38259
|
init_policies();
|
|
38150
38260
|
init_scoring();
|
|
38261
|
+
init_relevantWhen();
|
|
38151
38262
|
init_semantic();
|
|
38152
38263
|
MemoryPolicyError = class extends Error {
|
|
38153
38264
|
constructor(message) {
|
|
@@ -38162,6 +38273,7 @@ var init_service = __esm({
|
|
|
38162
38273
|
onEvent;
|
|
38163
38274
|
now;
|
|
38164
38275
|
defaultContextChars;
|
|
38276
|
+
relevantWhenEnabled;
|
|
38165
38277
|
semantic;
|
|
38166
38278
|
constructor(projectId2, backend, options = {}) {
|
|
38167
38279
|
this.backend = backend;
|
|
@@ -38172,6 +38284,7 @@ var init_service = __esm({
|
|
|
38172
38284
|
this.onEvent = options.onEvent;
|
|
38173
38285
|
this.now = options.now ?? (() => /* @__PURE__ */ new Date());
|
|
38174
38286
|
this.defaultContextChars = options.defaultContextChars ?? 2e3;
|
|
38287
|
+
this.relevantWhenEnabled = options.relevantWhen ?? true;
|
|
38175
38288
|
if (options.embeddingProvider) {
|
|
38176
38289
|
this.semantic = new SemanticMemoryController(projectId2, backend, options.embeddingProvider, {
|
|
38177
38290
|
now: this.now,
|
|
@@ -38181,6 +38294,31 @@ var init_service = __esm({
|
|
|
38181
38294
|
});
|
|
38182
38295
|
}
|
|
38183
38296
|
}
|
|
38297
|
+
/** Sanitize, dedupe, and cap associative triggers before persistence. */
|
|
38298
|
+
cleanRelevantWhen(proposed) {
|
|
38299
|
+
const out = [];
|
|
38300
|
+
for (const phrase of proposed) {
|
|
38301
|
+
if (typeof phrase !== "string")
|
|
38302
|
+
continue;
|
|
38303
|
+
const cleaned = this.sanitizer.sanitize(phrase);
|
|
38304
|
+
if (cleaned.rejected)
|
|
38305
|
+
continue;
|
|
38306
|
+
const value = cleaned.content.trim().slice(0, 120).trim();
|
|
38307
|
+
if (!value || out.includes(value))
|
|
38308
|
+
continue;
|
|
38309
|
+
out.push(value);
|
|
38310
|
+
if (out.length >= RELEVANT_WHEN_CAP)
|
|
38311
|
+
break;
|
|
38312
|
+
}
|
|
38313
|
+
return out;
|
|
38314
|
+
}
|
|
38315
|
+
/** Use host-supplied triggers, else derive them purely from the content. */
|
|
38316
|
+
buildRelevantWhen(input, content, kind2, tags) {
|
|
38317
|
+
if (!this.relevantWhenEnabled)
|
|
38318
|
+
return [];
|
|
38319
|
+
const proposed = input && input.length > 0 ? input : deriveRelevantWhen(content, kind2, tags);
|
|
38320
|
+
return this.cleanRelevantWhen(proposed);
|
|
38321
|
+
}
|
|
38184
38322
|
emit(event) {
|
|
38185
38323
|
if (!this.onEvent)
|
|
38186
38324
|
return;
|
|
@@ -38213,6 +38351,7 @@ var init_service = __esm({
|
|
|
38213
38351
|
...sanitized.redactions.length > 0 ? { secretRedactions: sanitized.redactions } : {}
|
|
38214
38352
|
};
|
|
38215
38353
|
const tags = normalizeTags(parsed.tags);
|
|
38354
|
+
const relevantWhen2 = this.buildRelevantWhen(parsed.relevantWhen, sanitized.content, parsed.kind, tags);
|
|
38216
38355
|
const exactKey = normalizedMemoryKey(sanitized.content);
|
|
38217
38356
|
const possible = await this.backend.search({
|
|
38218
38357
|
text: sanitized.content,
|
|
@@ -38225,13 +38364,18 @@ var init_service = __esm({
|
|
|
38225
38364
|
const duplicate = possible.find(({ node: node2 }) => normalizedMemoryKey(node2.content) === exactKey && (visibility === "project" || node2.source.client === source2.client))?.node;
|
|
38226
38365
|
if (duplicate) {
|
|
38227
38366
|
const mergedTags = normalizeTags([...duplicate.tags, ...tags]);
|
|
38228
|
-
const
|
|
38367
|
+
const mergedRelevantWhen = this.cleanRelevantWhen([
|
|
38368
|
+
...duplicate.relevantWhen ?? [],
|
|
38369
|
+
...relevantWhen2
|
|
38370
|
+
]);
|
|
38371
|
+
const shouldUpdate = confidence > duplicate.confidence || clampUnit(parsed.importance, 0.5) > duplicate.importance || mergedTags.length !== duplicate.tags.length || mergedRelevantWhen.length !== (duplicate.relevantWhen?.length ?? 0) || sanitized.redactions.length > 0;
|
|
38229
38372
|
if (!shouldUpdate)
|
|
38230
38373
|
return duplicate;
|
|
38231
38374
|
const updated = await this.backend.update(duplicate.id, {
|
|
38232
38375
|
confidence: Math.max(duplicate.confidence, confidence),
|
|
38233
38376
|
importance: Math.max(duplicate.importance, clampUnit(parsed.importance, 0.5)),
|
|
38234
38377
|
tags: mergedTags,
|
|
38378
|
+
...mergedRelevantWhen.length ? { relevantWhen: mergedRelevantWhen } : {},
|
|
38235
38379
|
source: source2,
|
|
38236
38380
|
metadata: { ...duplicate.metadata, ...metadata2 },
|
|
38237
38381
|
actor: source2.agent,
|
|
@@ -38250,6 +38394,7 @@ var init_service = __esm({
|
|
|
38250
38394
|
status: parsed.status ?? "active",
|
|
38251
38395
|
visibility,
|
|
38252
38396
|
tags,
|
|
38397
|
+
...relevantWhen2.length ? { relevantWhen: relevantWhen2 } : {},
|
|
38253
38398
|
source: source2,
|
|
38254
38399
|
...parsed.createdAt ? { createdAt: parsed.createdAt } : {},
|
|
38255
38400
|
...parsed.recordedAt ? { recordedAt: parsed.recordedAt } : {},
|
|
@@ -38283,6 +38428,21 @@ var init_service = __esm({
|
|
|
38283
38428
|
if (candidate.node.projectId === this.projectId && (!raw.externalClient || candidate.node.visibility === "project" || candidate.node.source.client === raw.externalClient))
|
|
38284
38429
|
byId.set(candidate.node.id, candidate);
|
|
38285
38430
|
}
|
|
38431
|
+
if (this.relevantWhenEnabled && !raw.asOf && text && this.backend.searchRelevantWhen) {
|
|
38432
|
+
const triggers = await this.backend.searchRelevantWhen({
|
|
38433
|
+
...recallQuery,
|
|
38434
|
+
text,
|
|
38435
|
+
projectId: this.projectId,
|
|
38436
|
+
statuses: raw.statuses ?? (raw.includeHistorical ? void 0 : ["active"]),
|
|
38437
|
+
limit: Math.max(limit, Math.min(200, limit * 5))
|
|
38438
|
+
});
|
|
38439
|
+
for (const hit of triggers) {
|
|
38440
|
+
if (hit.node.projectId !== this.projectId || raw.externalClient && hit.node.visibility === "private" && hit.node.source.client !== raw.externalClient)
|
|
38441
|
+
continue;
|
|
38442
|
+
const prior = byId.get(hit.node.id);
|
|
38443
|
+
byId.set(hit.node.id, prior ? { ...prior, triggerMatch: 1 } : { ...hit, lexicalRelevance: 1, triggerMatch: 1 });
|
|
38444
|
+
}
|
|
38445
|
+
}
|
|
38286
38446
|
if (this.semantic) {
|
|
38287
38447
|
const semantic = await this.semantic.search({
|
|
38288
38448
|
...raw,
|
|
@@ -38850,6 +39010,7 @@ var init_memory = __esm({
|
|
|
38850
39010
|
init_types11();
|
|
38851
39011
|
init_schemas3();
|
|
38852
39012
|
init_scoring();
|
|
39013
|
+
init_relevantWhen();
|
|
38853
39014
|
init_policies();
|
|
38854
39015
|
init_context2();
|
|
38855
39016
|
init_service();
|
|
@@ -38917,9 +39078,9 @@ function findCycle(nodes) {
|
|
|
38917
39078
|
if (color.get(start) !== WHITE)
|
|
38918
39079
|
continue;
|
|
38919
39080
|
const stack = [[start, 0]];
|
|
38920
|
-
const
|
|
39081
|
+
const path128 = [];
|
|
38921
39082
|
color.set(start, GRAY);
|
|
38922
|
-
|
|
39083
|
+
path128.push(start);
|
|
38923
39084
|
while (stack.length > 0) {
|
|
38924
39085
|
const top = stack[stack.length - 1];
|
|
38925
39086
|
const [id3, idx] = top;
|
|
@@ -38932,17 +39093,17 @@ function findCycle(nodes) {
|
|
|
38932
39093
|
continue;
|
|
38933
39094
|
const c = color.get(dep);
|
|
38934
39095
|
if (c === GRAY) {
|
|
38935
|
-
const at =
|
|
38936
|
-
return [...
|
|
39096
|
+
const at = path128.indexOf(dep);
|
|
39097
|
+
return [...path128.slice(at), dep];
|
|
38937
39098
|
}
|
|
38938
39099
|
if (c === WHITE) {
|
|
38939
39100
|
color.set(dep, GRAY);
|
|
38940
|
-
|
|
39101
|
+
path128.push(dep);
|
|
38941
39102
|
stack.push([dep, 0]);
|
|
38942
39103
|
}
|
|
38943
39104
|
} else {
|
|
38944
39105
|
color.set(id3, BLACK);
|
|
38945
|
-
|
|
39106
|
+
path128.pop();
|
|
38946
39107
|
stack.pop();
|
|
38947
39108
|
}
|
|
38948
39109
|
}
|
|
@@ -39862,8 +40023,8 @@ var init_runner = __esm({
|
|
|
39862
40023
|
failed: [...this.tentaclesById.values()].filter((r) => r.status === "error"),
|
|
39863
40024
|
pending: []
|
|
39864
40025
|
};
|
|
39865
|
-
const
|
|
39866
|
-
this.host.log(`checkpoint: ${label ?? "auto"} \u2192 ${
|
|
40026
|
+
const path128 = await this.host.saveSnapshot(snapshot, ".zelari/kraken/snapshots");
|
|
40027
|
+
this.host.log(`checkpoint: ${label ?? "auto"} \u2192 ${path128}`);
|
|
39867
40028
|
return snapshot;
|
|
39868
40029
|
}
|
|
39869
40030
|
callLog(msg, data) {
|
|
@@ -40421,7 +40582,7 @@ var CORE_VERSION;
|
|
|
40421
40582
|
var init_version = __esm({
|
|
40422
40583
|
"packages/core/dist/version.js"() {
|
|
40423
40584
|
"use strict";
|
|
40424
|
-
CORE_VERSION = "2.
|
|
40585
|
+
CORE_VERSION = "2.57.0";
|
|
40425
40586
|
}
|
|
40426
40587
|
});
|
|
40427
40588
|
|
|
@@ -40596,6 +40757,7 @@ __export(dist_exports, {
|
|
|
40596
40757
|
PressureThresholdsSchema: () => PressureThresholdsSchema,
|
|
40597
40758
|
ProfileSchema: () => ProfileSchema,
|
|
40598
40759
|
REDACTED: () => REDACTED,
|
|
40760
|
+
RELEVANT_WHEN_CAP: () => RELEVANT_WHEN_CAP,
|
|
40599
40761
|
ReasoningWatchdog: () => ReasoningWatchdog,
|
|
40600
40762
|
RepetitionGuard: () => RepetitionGuard,
|
|
40601
40763
|
ResourcePolicySchema: () => ResourcePolicySchema,
|
|
@@ -40737,6 +40899,7 @@ __export(dist_exports, {
|
|
|
40737
40899
|
deriveInitialContract: () => deriveInitialContract,
|
|
40738
40900
|
deriveMessages: () => deriveMessages,
|
|
40739
40901
|
deriveMissionState: () => deriveMissionState,
|
|
40902
|
+
deriveRelevantWhen: () => deriveRelevantWhen,
|
|
40740
40903
|
derivedToAgentMessages: () => derivedToAgentMessages,
|
|
40741
40904
|
detectAssistantTextLoop: () => detectAssistantTextLoop,
|
|
40742
40905
|
detectAssistantTextLoopWindow: () => detectAssistantTextLoopWindow,
|
|
@@ -43145,9 +43308,9 @@ function spillToolOutput(fullText, meta3) {
|
|
|
43145
43308
|
const rnd = randomBytes3(3).toString("hex");
|
|
43146
43309
|
const safeTool = (meta3?.toolName ?? "tool").replace(/[^a-zA-Z0-9._-]+/g, "_").slice(0, 32);
|
|
43147
43310
|
const file2 = `${stamp}-${safeTool}-${hash3}-${rnd}.txt`;
|
|
43148
|
-
const
|
|
43149
|
-
writeFileSync13(
|
|
43150
|
-
return
|
|
43311
|
+
const path128 = join14(dir, file2);
|
|
43312
|
+
writeFileSync13(path128, fullText, "utf8");
|
|
43313
|
+
return path128;
|
|
43151
43314
|
} catch {
|
|
43152
43315
|
return null;
|
|
43153
43316
|
}
|
|
@@ -43158,7 +43321,7 @@ var init_toolOutputSpill = __esm({
|
|
|
43158
43321
|
}
|
|
43159
43322
|
});
|
|
43160
43323
|
|
|
43161
|
-
// packages/core/dist/core/tools/
|
|
43324
|
+
// packages/core/dist/core/tools/observationCompactor.js
|
|
43162
43325
|
function truncateToolResult(text, capOrOpts = TOOL_RESULT_LINE_CAP) {
|
|
43163
43326
|
if (text.length === 0)
|
|
43164
43327
|
return text;
|
|
@@ -43193,10 +43356,10 @@ function truncateToolResult(text, capOrOpts = TOOL_RESULT_LINE_CAP) {
|
|
|
43193
43356
|
${tail2}`;
|
|
43194
43357
|
}
|
|
43195
43358
|
if (doSpill) {
|
|
43196
|
-
const
|
|
43197
|
-
if (
|
|
43359
|
+
const path128 = spillToolOutput(text, { toolName: opts.toolName });
|
|
43360
|
+
if (path128) {
|
|
43198
43361
|
const spillNote = `
|
|
43199
|
-
\u2026 [full output spilled to: ${
|
|
43362
|
+
\u2026 [full output spilled to: ${path128} \u2014 re-read with read_file if you need the complete text] \u2026`;
|
|
43200
43363
|
if (preview.includes("] \u2026\n")) {
|
|
43201
43364
|
preview = preview.replace("] \u2026\n", `] \u2026${spillNote}
|
|
43202
43365
|
`);
|
|
@@ -43207,14 +43370,47 @@ ${tail2}`;
|
|
|
43207
43370
|
}
|
|
43208
43371
|
return preview;
|
|
43209
43372
|
}
|
|
43210
|
-
|
|
43373
|
+
function compactToolResult(result, opts = {}) {
|
|
43374
|
+
if (!result.ok)
|
|
43375
|
+
return result;
|
|
43376
|
+
const truncOpts = { toolName: opts.toolName };
|
|
43377
|
+
if (opts.cap !== void 0)
|
|
43378
|
+
truncOpts.cap = opts.cap;
|
|
43379
|
+
if (opts.spill !== void 0)
|
|
43380
|
+
truncOpts.spill = opts.spill;
|
|
43381
|
+
if (typeof result.value === "string") {
|
|
43382
|
+
result.value = truncateToolResult(result.value, truncOpts);
|
|
43383
|
+
} else if (result.value && typeof result.value === "object") {
|
|
43384
|
+
const v = result.value;
|
|
43385
|
+
if (typeof v.content === "string") {
|
|
43386
|
+
v.content = truncateToolResult(v.content, truncOpts);
|
|
43387
|
+
}
|
|
43388
|
+
}
|
|
43389
|
+
return result;
|
|
43390
|
+
}
|
|
43391
|
+
var TOOL_RESULT_LINE_CAP;
|
|
43392
|
+
var init_observationCompactor = __esm({
|
|
43393
|
+
"packages/core/dist/core/tools/observationCompactor.js"() {
|
|
43394
|
+
"use strict";
|
|
43395
|
+
init_toolOutputSpill();
|
|
43396
|
+
TOOL_RESULT_LINE_CAP = (() => {
|
|
43397
|
+
const raw = process.env.ZELARI_TOOL_RESULT_LINES;
|
|
43398
|
+
const n = raw ? Number.parseInt(raw, 10) : 200;
|
|
43399
|
+
return Number.isFinite(n) && n >= 10 ? n : 200;
|
|
43400
|
+
})();
|
|
43401
|
+
}
|
|
43402
|
+
});
|
|
43403
|
+
|
|
43404
|
+
// packages/core/dist/core/tools/registry.js
|
|
43405
|
+
var TOOL_NAME_ALIASES, ToolRegistry;
|
|
43211
43406
|
var init_registry2 = __esm({
|
|
43212
43407
|
"packages/core/dist/core/tools/registry.js"() {
|
|
43213
43408
|
"use strict";
|
|
43214
43409
|
init_zodBridge();
|
|
43215
|
-
|
|
43410
|
+
init_observationCompactor();
|
|
43216
43411
|
init_toolTypes();
|
|
43217
43412
|
init_toolOutputSpill();
|
|
43413
|
+
init_observationCompactor();
|
|
43218
43414
|
TOOL_NAME_ALIASES = {
|
|
43219
43415
|
read: "read_file",
|
|
43220
43416
|
readfile: "read_file",
|
|
@@ -43239,11 +43435,6 @@ var init_registry2 = __esm({
|
|
|
43239
43435
|
run: "bash",
|
|
43240
43436
|
exec: "bash"
|
|
43241
43437
|
};
|
|
43242
|
-
TOOL_RESULT_LINE_CAP = (() => {
|
|
43243
|
-
const raw = process.env.ZELARI_TOOL_RESULT_LINES;
|
|
43244
|
-
const n = raw ? Number.parseInt(raw, 10) : 200;
|
|
43245
|
-
return Number.isFinite(n) && n >= 10 ? n : 200;
|
|
43246
|
-
})();
|
|
43247
43438
|
ToolRegistry = class {
|
|
43248
43439
|
tools = /* @__PURE__ */ new Map();
|
|
43249
43440
|
/** v0.10.0: lifecycle hooks (PreToolUse/PostToolUse). Null = no hooks. */
|
|
@@ -43373,17 +43564,7 @@ var init_registry2 = __esm({
|
|
|
43373
43564
|
})
|
|
43374
43565
|
]);
|
|
43375
43566
|
if (result.ok) {
|
|
43376
|
-
|
|
43377
|
-
if (typeof result.value === "string") {
|
|
43378
|
-
result.value = truncateToolResult(result.value, {
|
|
43379
|
-
toolName: tName
|
|
43380
|
-
});
|
|
43381
|
-
} else if (result.value && typeof result.value === "object") {
|
|
43382
|
-
const v = result.value;
|
|
43383
|
-
if (typeof v.content === "string") {
|
|
43384
|
-
v.content = truncateToolResult(v.content, { toolName: tName });
|
|
43385
|
-
}
|
|
43386
|
-
}
|
|
43567
|
+
compactToolResult(result, { toolName: options.toolName ?? name });
|
|
43387
43568
|
}
|
|
43388
43569
|
if (this.lifecycleHooks) {
|
|
43389
43570
|
try {
|
|
@@ -43756,8 +43937,8 @@ function workspaceFile(rootDir, kind2) {
|
|
|
43756
43937
|
return join15(rootDir, "workspace.json");
|
|
43757
43938
|
}
|
|
43758
43939
|
}
|
|
43759
|
-
function workspaceArtifact(rootDir, subdir,
|
|
43760
|
-
return join15(rootDir, subdir, `${
|
|
43940
|
+
function workspaceArtifact(rootDir, subdir, slug2) {
|
|
43941
|
+
return join15(rootDir, subdir, `${slug2}.md`);
|
|
43761
43942
|
}
|
|
43762
43943
|
function projectName(projectRoot = process.cwd()) {
|
|
43763
43944
|
return basename(realpathSync(projectRoot));
|
|
@@ -44041,28 +44222,28 @@ var init_storage = __esm({
|
|
|
44041
44222
|
VALID_SCALARS = /^(true|false|null|~)$/i;
|
|
44042
44223
|
Storage = class {
|
|
44043
44224
|
/** Read a Markdown file with frontmatter. Throws if not found. */
|
|
44044
|
-
read(
|
|
44045
|
-
if (!existsSync25(
|
|
44046
|
-
throw new Error(`File not found: ${
|
|
44225
|
+
read(path128) {
|
|
44226
|
+
if (!existsSync25(path128)) {
|
|
44227
|
+
throw new Error(`File not found: ${path128}`);
|
|
44047
44228
|
}
|
|
44048
|
-
const md = readFileSync24(
|
|
44229
|
+
const md = readFileSync24(path128, "utf8");
|
|
44049
44230
|
return parseFrontmatter(md);
|
|
44050
44231
|
}
|
|
44051
44232
|
/** Read a Markdown file; returns null if not found. */
|
|
44052
|
-
readIfExists(
|
|
44053
|
-
if (!existsSync25(
|
|
44054
|
-
return this.read(
|
|
44233
|
+
readIfExists(path128) {
|
|
44234
|
+
if (!existsSync25(path128)) return null;
|
|
44235
|
+
return this.read(path128);
|
|
44055
44236
|
}
|
|
44056
44237
|
/**
|
|
44057
44238
|
* Write a Markdown file atomically (tmp + rename). Creates parent dirs.
|
|
44058
44239
|
* The meta object is serialized as YAML frontmatter; body as Markdown.
|
|
44059
44240
|
*/
|
|
44060
|
-
write(
|
|
44061
|
-
mkdirSync11(dirname2(
|
|
44062
|
-
const tmp =
|
|
44241
|
+
write(path128, meta3, body) {
|
|
44242
|
+
mkdirSync11(dirname2(path128), { recursive: true });
|
|
44243
|
+
const tmp = path128 + ".tmp-" + process.pid;
|
|
44063
44244
|
const md = serializeFrontmatter(meta3, body);
|
|
44064
44245
|
writeFileSync15(tmp, md, "utf8");
|
|
44065
|
-
renameSync2(tmp,
|
|
44246
|
+
renameSync2(tmp, path128);
|
|
44066
44247
|
}
|
|
44067
44248
|
/** List all .md files in a directory (non-recursive). */
|
|
44068
44249
|
listMarkdown(dir) {
|
|
@@ -44173,8 +44354,8 @@ function nextPlanTaskId(store6) {
|
|
|
44173
44354
|
return `t${store6.counter}`;
|
|
44174
44355
|
}
|
|
44175
44356
|
function writePlanTaskArtifact(rootDir, task) {
|
|
44176
|
-
const
|
|
44177
|
-
mkdirSync12(dirname3(
|
|
44357
|
+
const path128 = join17(rootDir, "plan-tasks", `${task.id}.md`);
|
|
44358
|
+
mkdirSync12(dirname3(path128), { recursive: true });
|
|
44178
44359
|
const meta3 = {
|
|
44179
44360
|
kind: "task",
|
|
44180
44361
|
id: task.id,
|
|
@@ -44195,7 +44376,7 @@ function writePlanTaskArtifact(rootDir, task) {
|
|
|
44195
44376
|
task.notes?.trim() ? task.notes.trim() : "_(no notes)_",
|
|
44196
44377
|
""
|
|
44197
44378
|
].filter((l) => l !== null).join("\n");
|
|
44198
|
-
new Storage().write(
|
|
44379
|
+
new Storage().write(path128, meta3, body);
|
|
44199
44380
|
}
|
|
44200
44381
|
function loadHandle(rootDir) {
|
|
44201
44382
|
const jsonPath = join17(rootDir, "plan.json");
|
|
@@ -45352,8 +45533,8 @@ async function createKrakenWorktreeDetailed(cwd, label) {
|
|
|
45352
45533
|
const head = await git3(repoRoot, ["rev-parse", "HEAD"]);
|
|
45353
45534
|
const baseSha = head.ok ? head.stdout.trim() : void 0;
|
|
45354
45535
|
const id3 = `${Date.now().toString(36)}-${randomBytes4(3).toString("hex")}`;
|
|
45355
|
-
const
|
|
45356
|
-
const branch = `kraken/${
|
|
45536
|
+
const slug2 = (label ?? "task").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 24) || "task";
|
|
45537
|
+
const branch = `kraken/${slug2}-${id3}`;
|
|
45357
45538
|
const wtRoot = path50.join(repoRoot, ".zelari", "worktrees");
|
|
45358
45539
|
const wtPath = path50.join(wtRoot, `kraken-${id3}`);
|
|
45359
45540
|
const longPaths = isLongPath(repoRoot, wtPath);
|
|
@@ -53056,7 +53237,7 @@ function upsertSkill(opts) {
|
|
|
53056
53237
|
}
|
|
53057
53238
|
dir = getProjectSkillsDir(root);
|
|
53058
53239
|
}
|
|
53059
|
-
const
|
|
53240
|
+
const path128 = skillFilePath(dir, name);
|
|
53060
53241
|
const content = serializeSkillMd({
|
|
53061
53242
|
name,
|
|
53062
53243
|
description,
|
|
@@ -53065,13 +53246,13 @@ function upsertSkill(opts) {
|
|
|
53065
53246
|
tools: opts.tools,
|
|
53066
53247
|
cost: opts.cost
|
|
53067
53248
|
});
|
|
53068
|
-
const parsed = parseSkillMd(content,
|
|
53249
|
+
const parsed = parseSkillMd(content, path128);
|
|
53069
53250
|
if (!parsed) {
|
|
53070
53251
|
return { ok: false, error: "Generated SKILL.md failed validation" };
|
|
53071
53252
|
}
|
|
53072
|
-
mkdirSync15(dirname4(
|
|
53073
|
-
writeFileSync18(
|
|
53074
|
-
return { ok: true, path:
|
|
53253
|
+
mkdirSync15(dirname4(path128), { recursive: true });
|
|
53254
|
+
writeFileSync18(path128, content, "utf8");
|
|
53255
|
+
return { ok: true, path: path128 };
|
|
53075
53256
|
}
|
|
53076
53257
|
function removeSkill(opts) {
|
|
53077
53258
|
const name = opts.name.trim().toLowerCase();
|
|
@@ -53089,8 +53270,8 @@ function removeSkill(opts) {
|
|
|
53089
53270
|
dir = getProjectSkillsDir(root);
|
|
53090
53271
|
}
|
|
53091
53272
|
const skillDir = join20(dir, name);
|
|
53092
|
-
const
|
|
53093
|
-
if (!existsSync35(
|
|
53273
|
+
const path128 = skillFilePath(dir, name);
|
|
53274
|
+
if (!existsSync35(path128) && !existsSync35(skillDir)) {
|
|
53094
53275
|
return { ok: false, error: `Skill "${name}" not found in ${dir}` };
|
|
53095
53276
|
}
|
|
53096
53277
|
try {
|
|
@@ -53101,7 +53282,7 @@ function removeSkill(opts) {
|
|
|
53101
53282
|
error: err instanceof Error ? err.message : String(err)
|
|
53102
53283
|
};
|
|
53103
53284
|
}
|
|
53104
|
-
return { ok: true, path:
|
|
53285
|
+
return { ok: true, path: path128 };
|
|
53105
53286
|
}
|
|
53106
53287
|
var NAME_RE, BUILTIN_SKILL_MODULES, builtinsLoaded;
|
|
53107
53288
|
var init_skillConfigIo = __esm({
|
|
@@ -53161,16 +53342,16 @@ function createCreateSkillTool(opts) {
|
|
|
53161
53342
|
const overwrite = args?.overwrite === true;
|
|
53162
53343
|
const dir = scope === "user" ? getUserSkillsDir() : getProjectSkillsDir(root);
|
|
53163
53344
|
const skillDir = resolve3(dir, name);
|
|
53164
|
-
const
|
|
53165
|
-
if (!
|
|
53345
|
+
const path128 = resolve3(skillDir, "SKILL.md");
|
|
53346
|
+
if (!path128.startsWith(resolve3(dir) + sep)) {
|
|
53166
53347
|
return typedErr(
|
|
53167
53348
|
`Refused: "${name}" would resolve outside the ${scope} skills directory (${resolve3(dir)}).`
|
|
53168
53349
|
);
|
|
53169
53350
|
}
|
|
53170
|
-
const existed = existsSync36(
|
|
53351
|
+
const existed = existsSync36(path128);
|
|
53171
53352
|
if (existed && !overwrite) {
|
|
53172
53353
|
return typedErr(
|
|
53173
|
-
`Skill "${name}" already exists at ${
|
|
53354
|
+
`Skill "${name}" already exists at ${path128} \u2014 nothing was written. Call create_skill again with overwrite: true to replace it, or pick another name.`
|
|
53174
53355
|
);
|
|
53175
53356
|
}
|
|
53176
53357
|
const written = upsertSkill({
|
|
@@ -56785,21 +56966,21 @@ function normalizeAuth(auth) {
|
|
|
56785
56966
|
return "agent";
|
|
56786
56967
|
}
|
|
56787
56968
|
function readSecrets() {
|
|
56788
|
-
const
|
|
56789
|
-
if (!existsSync39(
|
|
56969
|
+
const path128 = getSshSecretsPath();
|
|
56970
|
+
if (!existsSync39(path128)) return {};
|
|
56790
56971
|
try {
|
|
56791
|
-
return JSON.parse(readFileSync31(
|
|
56972
|
+
return JSON.parse(readFileSync31(path128, "utf8"));
|
|
56792
56973
|
} catch {
|
|
56793
56974
|
return {};
|
|
56794
56975
|
}
|
|
56795
56976
|
}
|
|
56796
56977
|
function writeSecrets(data) {
|
|
56797
|
-
const
|
|
56798
|
-
mkdirSync16(dirname5(
|
|
56799
|
-
writeFileSync19(
|
|
56978
|
+
const path128 = getSshSecretsPath();
|
|
56979
|
+
mkdirSync16(dirname5(path128), { recursive: true });
|
|
56980
|
+
writeFileSync19(path128, `${JSON.stringify(data, null, 2)}
|
|
56800
56981
|
`, "utf8");
|
|
56801
56982
|
try {
|
|
56802
|
-
chmodSync(
|
|
56983
|
+
chmodSync(path128, 384);
|
|
56803
56984
|
} catch {
|
|
56804
56985
|
}
|
|
56805
56986
|
}
|
|
@@ -56828,10 +57009,10 @@ function deleteSshPassword(id3) {
|
|
|
56828
57009
|
writeSecrets({ passwords });
|
|
56829
57010
|
}
|
|
56830
57011
|
function readStore2() {
|
|
56831
|
-
const
|
|
56832
|
-
if (!existsSync39(
|
|
57012
|
+
const path128 = getSshTargetsPath();
|
|
57013
|
+
if (!existsSync39(path128)) return [];
|
|
56833
57014
|
try {
|
|
56834
|
-
const parsed = JSON.parse(readFileSync31(
|
|
57015
|
+
const parsed = JSON.parse(readFileSync31(path128, "utf8"));
|
|
56835
57016
|
const list = Array.isArray(parsed.targets) ? parsed.targets : [];
|
|
56836
57017
|
return list.filter(
|
|
56837
57018
|
(t) => t && typeof t.id === "string" && typeof t.host === "string" && typeof t.user === "string"
|
|
@@ -56846,11 +57027,11 @@ function readStore2() {
|
|
|
56846
57027
|
}
|
|
56847
57028
|
}
|
|
56848
57029
|
function writeStore2(targets) {
|
|
56849
|
-
const
|
|
56850
|
-
mkdirSync16(dirname5(
|
|
57030
|
+
const path128 = getSshTargetsPath();
|
|
57031
|
+
mkdirSync16(dirname5(path128), { recursive: true });
|
|
56851
57032
|
const clean = targets.map(({ hasPassword: _hp, ...t }) => t);
|
|
56852
57033
|
writeFileSync19(
|
|
56853
|
-
|
|
57034
|
+
path128,
|
|
56854
57035
|
`${JSON.stringify({ targets: clean }, null, 2)}
|
|
56855
57036
|
`,
|
|
56856
57037
|
"utf8"
|
|
@@ -57096,11 +57277,11 @@ function formatSshTargetsForPrompt() {
|
|
|
57096
57277
|
];
|
|
57097
57278
|
for (const t of targets) {
|
|
57098
57279
|
const tags = t.tags?.length ? ` tags=[${t.tags.join(",")}]` : "";
|
|
57099
|
-
const
|
|
57280
|
+
const path128 = t.defaultRemotePath ? ` remotePath=${t.defaultRemotePath}` : "";
|
|
57100
57281
|
const allow = t.allowedCommands?.length ? ` allowed=${t.allowedCommands.join("|")}` : " allowed=status-only";
|
|
57101
57282
|
const auth = t.auth === "password" ? " auth=password" : t.auth === "keyPath" ? " auth=key" : " auth=agent";
|
|
57102
57283
|
lines.push(
|
|
57103
|
-
`- id=${t.id} name=${t.name} ${t.user}@${t.host}:${t.port ?? 22}${auth}${
|
|
57284
|
+
`- id=${t.id} name=${t.name} ${t.user}@${t.host}:${t.port ?? 22}${auth}${path128}${tags}${allow}`
|
|
57104
57285
|
);
|
|
57105
57286
|
}
|
|
57106
57287
|
return lines.join("\n");
|
|
@@ -59888,26 +60069,7 @@ function cloneResult(result) {
|
|
|
59888
60069
|
}
|
|
59889
60070
|
}
|
|
59890
60071
|
function applyTruncation(result, toolName2) {
|
|
59891
|
-
|
|
59892
|
-
if (typeof result.value === "string") {
|
|
59893
|
-
return {
|
|
59894
|
-
ok: true,
|
|
59895
|
-
value: truncateToolResult(result.value, { toolName: toolName2, spill: false })
|
|
59896
|
-
};
|
|
59897
|
-
}
|
|
59898
|
-
if (result.value && typeof result.value === "object") {
|
|
59899
|
-
const v = result.value;
|
|
59900
|
-
if (typeof v.content === "string") {
|
|
59901
|
-
return {
|
|
59902
|
-
ok: true,
|
|
59903
|
-
value: {
|
|
59904
|
-
...v,
|
|
59905
|
-
content: truncateToolResult(v.content, { toolName: toolName2, spill: false })
|
|
59906
|
-
}
|
|
59907
|
-
};
|
|
59908
|
-
}
|
|
59909
|
-
}
|
|
59910
|
-
return result;
|
|
60072
|
+
return compactToolResult(result, { toolName: toolName2, spill: false });
|
|
59911
60073
|
}
|
|
59912
60074
|
function evictOldest() {
|
|
59913
60075
|
let oldestKey = null;
|
|
@@ -62479,6 +62641,7 @@ function decodeNode(row) {
|
|
|
62479
62641
|
status: row.status,
|
|
62480
62642
|
visibility: row.visibility ?? "project",
|
|
62481
62643
|
tags: json2(row.tags_json, []),
|
|
62644
|
+
relevantWhen: json2(row.relevant_when_json, []),
|
|
62482
62645
|
source: json2(row.source_json, {}),
|
|
62483
62646
|
createdAt: row.created_at,
|
|
62484
62647
|
updatedAt: row.updated_at,
|
|
@@ -62503,6 +62666,7 @@ function nodeSqlValues(node) {
|
|
|
62503
62666
|
node.status,
|
|
62504
62667
|
node.visibility ?? "project",
|
|
62505
62668
|
JSON.stringify(node.tags),
|
|
62669
|
+
JSON.stringify(node.relevantWhen ?? []),
|
|
62506
62670
|
JSON.stringify(node.source),
|
|
62507
62671
|
node.createdAt,
|
|
62508
62672
|
node.updatedAt,
|
|
@@ -62687,7 +62851,7 @@ var SQLITE_MEMORY_SCHEMA_VERSION, SQLITE_MEMORY_BASE_SCHEMA, SQLITE_MEMORY_MIGRA
|
|
|
62687
62851
|
var init_sqliteSchema = __esm({
|
|
62688
62852
|
"src/cli/memory/sqliteSchema.ts"() {
|
|
62689
62853
|
"use strict";
|
|
62690
|
-
SQLITE_MEMORY_SCHEMA_VERSION =
|
|
62854
|
+
SQLITE_MEMORY_SCHEMA_VERSION = 3;
|
|
62691
62855
|
SQLITE_MEMORY_BASE_SCHEMA = `
|
|
62692
62856
|
PRAGMA foreign_keys = ON;
|
|
62693
62857
|
PRAGMA journal_mode = WAL;
|
|
@@ -62705,6 +62869,7 @@ CREATE TABLE IF NOT EXISTS memory_nodes (
|
|
|
62705
62869
|
status TEXT NOT NULL CHECK (status IN ('active','superseded','retracted','archived')),
|
|
62706
62870
|
visibility TEXT NOT NULL DEFAULT 'project' CHECK (visibility IN ('project','private')),
|
|
62707
62871
|
tags_json TEXT NOT NULL DEFAULT '[]',
|
|
62872
|
+
relevant_when_json TEXT NOT NULL DEFAULT '[]',
|
|
62708
62873
|
source_json TEXT NOT NULL DEFAULT '{}',
|
|
62709
62874
|
created_at TEXT NOT NULL,
|
|
62710
62875
|
updated_at TEXT NOT NULL,
|
|
@@ -62834,6 +62999,15 @@ SELECT id, visibility, json_extract(source_json, '$.client'), updated_at FROM me
|
|
|
62834
62999
|
END;
|
|
62835
63000
|
INSERT INTO memory_access(memory_id, visibility, owner_client, updated_at)
|
|
62836
63001
|
SELECT id, visibility, json_extract(source_json, '$.client'), updated_at FROM memory_nodes;
|
|
63002
|
+
`
|
|
63003
|
+
},
|
|
63004
|
+
{
|
|
63005
|
+
// S3 (T-Mem lite): additive associative-trigger column. Legacy rows default
|
|
63006
|
+
// to '[]'; the FTS triggers are untouched (triggers are matched via
|
|
63007
|
+
// json_each, and json_each('[]') yields zero rows, so '[]' never explodes).
|
|
63008
|
+
version: 3,
|
|
63009
|
+
sql: `
|
|
63010
|
+
ALTER TABLE memory_nodes ADD COLUMN relevant_when_json TEXT NOT NULL DEFAULT '[]';
|
|
62837
63011
|
`
|
|
62838
63012
|
}
|
|
62839
63013
|
];
|
|
@@ -62897,10 +63071,10 @@ var init_sqliteBackend = __esm({
|
|
|
62897
63071
|
init_sqliteSchema();
|
|
62898
63072
|
NODE_COLUMNS = `
|
|
62899
63073
|
id, schema_version, project_id, kind, content, importance, confidence,
|
|
62900
|
-
status, visibility, tags_json, source_json, created_at, updated_at, valid_from,
|
|
63074
|
+
status, visibility, tags_json, relevant_when_json, source_json, created_at, updated_at, valid_from,
|
|
62901
63075
|
valid_until, recorded_at, retracted_at, embedding_ref, metadata_json`;
|
|
62902
63076
|
INSERT_NODE_SQL = `INSERT INTO memory_nodes (${NODE_COLUMNS})
|
|
62903
|
-
VALUES (${Array.from({ length:
|
|
63077
|
+
VALUES (${Array.from({ length: 20 }, () => "?").join(",")})`;
|
|
62904
63078
|
IMPORT_ID_CHUNK = 500;
|
|
62905
63079
|
SOURCE_COLUMNS = {
|
|
62906
63080
|
agent: "agent",
|
|
@@ -63004,6 +63178,7 @@ VALUES (${Array.from({ length: 19 }, () => "?").join(",")})`;
|
|
|
63004
63178
|
status: input.status ?? "active",
|
|
63005
63179
|
visibility: input.visibility ?? "project",
|
|
63006
63180
|
tags: input.tags ?? [],
|
|
63181
|
+
relevantWhen: input.relevantWhen ?? [],
|
|
63007
63182
|
source: input.source ?? {},
|
|
63008
63183
|
createdAt,
|
|
63009
63184
|
updatedAt: now,
|
|
@@ -63053,6 +63228,7 @@ VALUES (${Array.from({ length: 19 }, () => "?").join(",")})`;
|
|
|
63053
63228
|
...patch.status ? { status: patch.status } : {},
|
|
63054
63229
|
...patch.visibility ? { visibility: patch.visibility } : {},
|
|
63055
63230
|
...patch.tags ? { tags: patch.tags } : {},
|
|
63231
|
+
...patch.relevantWhen ? { relevantWhen: patch.relevantWhen } : {},
|
|
63056
63232
|
...patch.source ? { source: patch.source } : {},
|
|
63057
63233
|
...patch.metadata ? { metadata: patch.metadata } : {},
|
|
63058
63234
|
updatedAt: now,
|
|
@@ -63071,7 +63247,7 @@ VALUES (${Array.from({ length: 19 }, () => "?").join(",")})`;
|
|
|
63071
63247
|
{
|
|
63072
63248
|
sql: `UPDATE memory_nodes SET
|
|
63073
63249
|
schema_version=?, project_id=?, kind=?, content=?, importance=?, confidence=?,
|
|
63074
|
-
status=?, visibility=?, tags_json=?, source_json=?, created_at=?, updated_at=?, valid_from=?,
|
|
63250
|
+
status=?, visibility=?, tags_json=?, relevant_when_json=?, source_json=?, created_at=?, updated_at=?, valid_from=?,
|
|
63075
63251
|
valid_until=?, recorded_at=?, retracted_at=?, embedding_ref=?, metadata_json=?
|
|
63076
63252
|
WHERE id=?`,
|
|
63077
63253
|
params: [...nodeSqlValues(updated).slice(1), updated.id]
|
|
@@ -63107,6 +63283,36 @@ VALUES (${Array.from({ length: 19 }, () => "?").join(",")})`;
|
|
|
63107
63283
|
return this.searchCurrent(query, text, expression, false);
|
|
63108
63284
|
}
|
|
63109
63285
|
}
|
|
63286
|
+
/**
|
|
63287
|
+
* T-Mem lite: retrieve nodes whose `relevantWhen` triggers overlap the query
|
|
63288
|
+
* tokens. Runs as a separate query so the lexical similarity prefilter in
|
|
63289
|
+
* `search` can never drop an associative hit. `json_each('[]')` yields zero
|
|
63290
|
+
* rows, so empty/legacy triggers are harmless.
|
|
63291
|
+
*/
|
|
63292
|
+
async searchRelevantWhen(query) {
|
|
63293
|
+
this.assertReady();
|
|
63294
|
+
const text = query.text?.trim() ?? "";
|
|
63295
|
+
if (!text) return [];
|
|
63296
|
+
const tokens = [
|
|
63297
|
+
...new Set(text.toLocaleLowerCase().match(/[\p{L}\p{N}_-]{3,}/gu) ?? [])
|
|
63298
|
+
].slice(0, 24);
|
|
63299
|
+
if (tokens.length === 0) return [];
|
|
63300
|
+
const params = [];
|
|
63301
|
+
const where = [];
|
|
63302
|
+
const clauses = tokens.map(
|
|
63303
|
+
() => `EXISTS (SELECT 1 FROM json_each(n.relevant_when_json) je WHERE instr(' ' || lower(je.value) || ' ', ' ' || ? || ' ') > 0)`
|
|
63304
|
+
);
|
|
63305
|
+
where.push(`(${clauses.join(" OR ")})`);
|
|
63306
|
+
params.push(...tokens);
|
|
63307
|
+
this.addFilters(query, where, params, "n");
|
|
63308
|
+
params.push(boundedLimit(query.limit));
|
|
63309
|
+
const rows = await this.rpc.statement({
|
|
63310
|
+
sql: `SELECT n.* FROM memory_nodes n WHERE ${where.join(" AND ")} ORDER BY n.importance DESC, n.updated_at DESC LIMIT ?`,
|
|
63311
|
+
params,
|
|
63312
|
+
mode: "all"
|
|
63313
|
+
});
|
|
63314
|
+
return rows.map(decodeNode).filter((node) => Boolean(node)).map((node) => ({ node, lexicalRelevance: 1, triggerMatch: 1 }));
|
|
63315
|
+
}
|
|
63110
63316
|
async searchCurrent(query, text, expression, useFts) {
|
|
63111
63317
|
const params = [];
|
|
63112
63318
|
const where = [];
|
|
@@ -63507,6 +63713,7 @@ __export(serviceFactory_exports, {
|
|
|
63507
63713
|
getMemoryService: () => getMemoryService,
|
|
63508
63714
|
isMemoryAutoWriteEnabled: () => isMemoryAutoWriteEnabled,
|
|
63509
63715
|
isMemorySemanticEnabled: () => isMemorySemanticEnabled,
|
|
63716
|
+
isMemoryTriggersEnabled: () => isMemoryTriggersEnabled,
|
|
63510
63717
|
isMemoryV2Enabled: () => isMemoryV2Enabled
|
|
63511
63718
|
});
|
|
63512
63719
|
import { createHash as createHash22 } from "node:crypto";
|
|
@@ -63523,6 +63730,9 @@ function isMemoryAutoWriteEnabled(env = process.env) {
|
|
|
63523
63730
|
function isMemorySemanticEnabled(env = process.env) {
|
|
63524
63731
|
return isMemoryV2Enabled(env) && env.ZELARI_MEMORY_SEMANTIC === "1";
|
|
63525
63732
|
}
|
|
63733
|
+
function isMemoryTriggersEnabled(env = process.env) {
|
|
63734
|
+
return isMemoryV2Enabled(env) && env.ZELARI_MEMORY_TRIGGERS !== "0";
|
|
63735
|
+
}
|
|
63526
63736
|
function semanticMinScore(env) {
|
|
63527
63737
|
const value = Number(env.ZELARI_MEMORY_SEMANTIC_MIN_SCORE);
|
|
63528
63738
|
return Number.isFinite(value) ? Math.max(0, Math.min(value, 1)) : void 0;
|
|
@@ -63560,7 +63770,8 @@ async function getMemoryService(projectRoot, env = process.env, options = {}) {
|
|
|
63560
63770
|
const service = new DefaultMemoryService(projectId2, backend, {
|
|
63561
63771
|
...options.onEvent ? { onEvent: options.onEvent } : {},
|
|
63562
63772
|
...embeddingProvider ? { embeddingProvider } : {},
|
|
63563
|
-
...semanticMinScore(env) !== void 0 ? { minSemanticRelevance: semanticMinScore(env) } : {}
|
|
63773
|
+
...semanticMinScore(env) !== void 0 ? { minSemanticRelevance: semanticMinScore(env) } : {},
|
|
63774
|
+
relevantWhen: isMemoryTriggersEnabled(env)
|
|
63564
63775
|
});
|
|
63565
63776
|
if (backend.lastMigration) {
|
|
63566
63777
|
const migration = backend.lastMigration;
|
|
@@ -63842,6 +64053,75 @@ var init_opsKnowledge = __esm({
|
|
|
63842
64053
|
}
|
|
63843
64054
|
});
|
|
63844
64055
|
|
|
64056
|
+
// src/cli/memory/onePager.ts
|
|
64057
|
+
import { promises as fs33 } from "node:fs";
|
|
64058
|
+
import * as path84 from "node:path";
|
|
64059
|
+
function isOnePagerEnabled(env = process.env) {
|
|
64060
|
+
return env.ZELARI_ONE_PAGER !== "0";
|
|
64061
|
+
}
|
|
64062
|
+
function slug(text, max = 48) {
|
|
64063
|
+
const line = text.split(/\r?\n/, 1)[0].trim();
|
|
64064
|
+
return line.length <= max ? line : `${line.slice(0, max - 1)}\u2026`;
|
|
64065
|
+
}
|
|
64066
|
+
async function howWeTestIndex(cwd) {
|
|
64067
|
+
try {
|
|
64068
|
+
const stat9 = await fs33.stat(path84.join(cwd, HOW_WE_TEST_RELATIVE));
|
|
64069
|
+
return `${HOW_WE_TEST_RELATIVE} \xB7 ${new Date(stat9.mtimeMs).toISOString()}`;
|
|
64070
|
+
} catch {
|
|
64071
|
+
return null;
|
|
64072
|
+
}
|
|
64073
|
+
}
|
|
64074
|
+
async function procedureAliases(memory) {
|
|
64075
|
+
if (!memory) return null;
|
|
64076
|
+
const nodes = await listVerifiedProcedureNodes(memory);
|
|
64077
|
+
if (!nodes || nodes.length === 0) return null;
|
|
64078
|
+
return nodes.slice(0, MAX_PROCEDURES).map((node) => `- ${slug(node.tags[0] ?? node.content)}`).join("\n");
|
|
64079
|
+
}
|
|
64080
|
+
function truncate(text, cap3) {
|
|
64081
|
+
if (text.length <= cap3) return text;
|
|
64082
|
+
return `${text.slice(0, cap3 - TRUNCATION_MARKER2.length).trimEnd()}${TRUNCATION_MARKER2}`;
|
|
64083
|
+
}
|
|
64084
|
+
async function buildOnePager(opts = {}) {
|
|
64085
|
+
if (!isOnePagerEnabled(opts.env)) return [];
|
|
64086
|
+
try {
|
|
64087
|
+
const cwd = opts.cwd ?? process.cwd();
|
|
64088
|
+
const sections = [];
|
|
64089
|
+
const todos2 = formatTodosForModel(listSessionTodos());
|
|
64090
|
+
if (todos2 && todos2 !== "(no todos)") sections.push(`## Open loops
|
|
64091
|
+
${todos2}`);
|
|
64092
|
+
const index = await howWeTestIndex(cwd);
|
|
64093
|
+
if (index) sections.push(`## How we test
|
|
64094
|
+
${index}`);
|
|
64095
|
+
const procedures = await procedureAliases(opts.memory);
|
|
64096
|
+
if (procedures) sections.push(`## Procedures
|
|
64097
|
+
${procedures}`);
|
|
64098
|
+
if (!opts.skipCompactRecap) {
|
|
64099
|
+
const recap = opts.compactSummary?.trim();
|
|
64100
|
+
if (recap) sections.push(`## Compact recap
|
|
64101
|
+
${recap.slice(0, SECTION_RECAP_CAP)}`);
|
|
64102
|
+
}
|
|
64103
|
+
if (sections.length === 0) return [];
|
|
64104
|
+
const body = `${ONE_PAGER_PREFIX}
|
|
64105
|
+
${sections.join("\n\n")}`;
|
|
64106
|
+
return [{ role: "system", content: truncate(body, ONE_PAGER_CHAR_CAP) }];
|
|
64107
|
+
} catch {
|
|
64108
|
+
return [];
|
|
64109
|
+
}
|
|
64110
|
+
}
|
|
64111
|
+
var ONE_PAGER_CHAR_CAP, ONE_PAGER_PREFIX, SECTION_RECAP_CAP, MAX_PROCEDURES, TRUNCATION_MARKER2;
|
|
64112
|
+
var init_onePager = __esm({
|
|
64113
|
+
"src/cli/memory/onePager.ts"() {
|
|
64114
|
+
"use strict";
|
|
64115
|
+
init_sessionTodos();
|
|
64116
|
+
init_howWeTest();
|
|
64117
|
+
ONE_PAGER_CHAR_CAP = 1500;
|
|
64118
|
+
ONE_PAGER_PREFIX = "WORKING SET";
|
|
64119
|
+
SECTION_RECAP_CAP = 400;
|
|
64120
|
+
MAX_PROCEDURES = 8;
|
|
64121
|
+
TRUNCATION_MARKER2 = "\n\u2026(working set truncated)";
|
|
64122
|
+
}
|
|
64123
|
+
});
|
|
64124
|
+
|
|
63845
64125
|
// src/cli/memory/spineTelemetry.ts
|
|
63846
64126
|
function spineMemoryEventNote(handle, event) {
|
|
63847
64127
|
try {
|
|
@@ -63925,20 +64205,20 @@ var init_askUserTimeout = __esm({
|
|
|
63925
64205
|
|
|
63926
64206
|
// src/cli/state/fileStateStore.ts
|
|
63927
64207
|
import { createHash as createHash24, randomUUID as randomUUID6 } from "node:crypto";
|
|
63928
|
-
import { promises as
|
|
63929
|
-
import * as
|
|
64208
|
+
import { promises as fs34 } from "node:fs";
|
|
64209
|
+
import * as path85 from "node:path";
|
|
63930
64210
|
function shortId() {
|
|
63931
64211
|
return randomUUID6().replace(/-/g, "").slice(0, 12);
|
|
63932
64212
|
}
|
|
63933
64213
|
async function writeJsonAtomic(filePath, data) {
|
|
63934
|
-
await
|
|
64214
|
+
await fs34.mkdir(path85.dirname(filePath), { recursive: true });
|
|
63935
64215
|
const tmp = `${filePath}.${process.pid}.${Date.now()}.tmp`;
|
|
63936
|
-
await
|
|
63937
|
-
await
|
|
64216
|
+
await fs34.writeFile(tmp, JSON.stringify(data, null, 2) + "\n", "utf8");
|
|
64217
|
+
await fs34.rename(tmp, filePath);
|
|
63938
64218
|
}
|
|
63939
64219
|
async function readJsonFile(filePath) {
|
|
63940
64220
|
try {
|
|
63941
|
-
const raw = await
|
|
64221
|
+
const raw = await fs34.readFile(filePath, "utf8");
|
|
63942
64222
|
return JSON.parse(raw);
|
|
63943
64223
|
} catch {
|
|
63944
64224
|
return null;
|
|
@@ -63992,13 +64272,13 @@ var init_fileStateStore = __esm({
|
|
|
63992
64272
|
indexPath = "";
|
|
63993
64273
|
async init(projectRoot) {
|
|
63994
64274
|
this.root = projectRoot;
|
|
63995
|
-
this.stateDir =
|
|
63996
|
-
this.commitsDir =
|
|
63997
|
-
this.artifactsDir =
|
|
63998
|
-
this.headPath =
|
|
63999
|
-
this.indexPath =
|
|
64000
|
-
await
|
|
64001
|
-
await
|
|
64275
|
+
this.stateDir = path85.join(projectRoot, ".zelari", "state");
|
|
64276
|
+
this.commitsDir = path85.join(this.stateDir, "commits");
|
|
64277
|
+
this.artifactsDir = path85.join(this.stateDir, "artifacts");
|
|
64278
|
+
this.headPath = path85.join(this.stateDir, "HEAD.json");
|
|
64279
|
+
this.indexPath = path85.join(this.stateDir, "index.jsonl");
|
|
64280
|
+
await fs34.mkdir(this.commitsDir, { recursive: true });
|
|
64281
|
+
await fs34.mkdir(this.artifactsDir, { recursive: true });
|
|
64002
64282
|
}
|
|
64003
64283
|
async commit(input) {
|
|
64004
64284
|
if (!input.force && input.verification.ran && !input.verification.ok) {
|
|
@@ -64009,13 +64289,13 @@ var init_fileStateStore = __esm({
|
|
|
64009
64289
|
const discoveries = input.discoveries ?? [];
|
|
64010
64290
|
const parent = await this.head();
|
|
64011
64291
|
const id3 = shortId();
|
|
64012
|
-
const artifactRel =
|
|
64013
|
-
const artifactAbs =
|
|
64014
|
-
await
|
|
64292
|
+
const artifactRel = path85.join("artifacts", id3);
|
|
64293
|
+
const artifactAbs = path85.join(this.artifactsDir, id3);
|
|
64294
|
+
await fs34.mkdir(artifactAbs, { recursive: true });
|
|
64015
64295
|
const summary = defaultSummary(input, discoveries);
|
|
64016
|
-
await
|
|
64017
|
-
await writeJsonAtomic(
|
|
64018
|
-
await writeJsonAtomic(
|
|
64296
|
+
await fs34.writeFile(path85.join(artifactAbs, "summary.md"), summary + "\n", "utf8");
|
|
64297
|
+
await writeJsonAtomic(path85.join(artifactAbs, "discoveries.json"), discoveries);
|
|
64298
|
+
await writeJsonAtomic(path85.join(artifactAbs, "verification.json"), input.verification);
|
|
64019
64299
|
const meta3 = {
|
|
64020
64300
|
id: id3,
|
|
64021
64301
|
parentId: parent?.id ?? null,
|
|
@@ -64027,16 +64307,16 @@ var init_fileStateStore = __esm({
|
|
|
64027
64307
|
workspaceCheckpointId: input.workspaceCheckpointId,
|
|
64028
64308
|
verification: {
|
|
64029
64309
|
...input.verification,
|
|
64030
|
-
reportPath: input.verification.reportPath ??
|
|
64310
|
+
reportPath: input.verification.reportPath ?? path85.join(".zelari", "state", artifactRel, "verification.json").replace(/\\/g, "/")
|
|
64031
64311
|
},
|
|
64032
64312
|
changedPaths: input.changedPaths ?? [],
|
|
64033
64313
|
stablePromptHash: input.stablePromptHash,
|
|
64034
64314
|
discoveryCount: discoveries.length,
|
|
64035
64315
|
artifactDir: artifactRel.replace(/\\/g, "/")
|
|
64036
64316
|
};
|
|
64037
|
-
await writeJsonAtomic(
|
|
64317
|
+
await writeJsonAtomic(path85.join(this.commitsDir, `${id3}.json`), meta3);
|
|
64038
64318
|
await writeJsonAtomic(this.headPath, { id: id3, updatedAt: meta3.createdAt });
|
|
64039
|
-
await
|
|
64319
|
+
await fs34.appendFile(this.indexPath, JSON.stringify({ id: id3, createdAt: meta3.createdAt, label: meta3.label }) + "\n", "utf8");
|
|
64040
64320
|
return stripStored(meta3);
|
|
64041
64321
|
}
|
|
64042
64322
|
async head() {
|
|
@@ -64045,13 +64325,13 @@ var init_fileStateStore = __esm({
|
|
|
64045
64325
|
return this.get(head.id);
|
|
64046
64326
|
}
|
|
64047
64327
|
async get(id3) {
|
|
64048
|
-
const stored = await readJsonFile(
|
|
64328
|
+
const stored = await readJsonFile(path85.join(this.commitsDir, `${id3}.json`));
|
|
64049
64329
|
return stored ? stripStored(stored) : null;
|
|
64050
64330
|
}
|
|
64051
64331
|
async list(limit = 20) {
|
|
64052
64332
|
let raw;
|
|
64053
64333
|
try {
|
|
64054
|
-
raw = await
|
|
64334
|
+
raw = await fs34.readFile(this.indexPath, "utf8");
|
|
64055
64335
|
} catch {
|
|
64056
64336
|
return [];
|
|
64057
64337
|
}
|
|
@@ -64084,9 +64364,9 @@ var init_fileStateStore = __esm({
|
|
|
64084
64364
|
async loadDiscoveries(id3) {
|
|
64085
64365
|
const meta3 = id3 ? await this.get(id3) : await this.head();
|
|
64086
64366
|
if (!meta3) return [];
|
|
64087
|
-
const stored = await readJsonFile(
|
|
64367
|
+
const stored = await readJsonFile(path85.join(this.commitsDir, `${meta3.id}.json`));
|
|
64088
64368
|
if (!stored?.artifactDir) return [];
|
|
64089
|
-
const discPath =
|
|
64369
|
+
const discPath = path85.join(this.stateDir, stored.artifactDir, "discoveries.json");
|
|
64090
64370
|
return await readJsonFile(discPath) ?? [];
|
|
64091
64371
|
}
|
|
64092
64372
|
async materializeContext(id3, maxChars = DEFAULT_MATERIALIZE_CHARS) {
|
|
@@ -64297,7 +64577,7 @@ __export(conversationContext_exports, {
|
|
|
64297
64577
|
setLastClarification: () => setLastClarification
|
|
64298
64578
|
});
|
|
64299
64579
|
import { existsSync as existsSync44 } from "node:fs";
|
|
64300
|
-
import { join as
|
|
64580
|
+
import { join as join29 } from "node:path";
|
|
64301
64581
|
function getHistory() {
|
|
64302
64582
|
return history;
|
|
64303
64583
|
}
|
|
@@ -64306,7 +64586,7 @@ function setHistory(messages) {
|
|
|
64306
64586
|
history = projected === messages ? [...messages] : projected;
|
|
64307
64587
|
}
|
|
64308
64588
|
function compactInPlace(cwd = process.cwd()) {
|
|
64309
|
-
const durableStatePresent = existsSync44(
|
|
64589
|
+
const durableStatePresent = existsSync44(join29(cwd, ".zelari", "state", "HEAD.json"));
|
|
64310
64590
|
history = applySessionSurface(compactHistory(history, { durableStatePresent }));
|
|
64311
64591
|
}
|
|
64312
64592
|
function appendMessages(msgs) {
|
|
@@ -64365,10 +64645,10 @@ function formatHistoryMessages(messages, maxTurns = 6, maxTotalChars = 12e3) {
|
|
|
64365
64645
|
for (let i = messages.length - 1; i >= 0 && turns < maxTurns; i--) {
|
|
64366
64646
|
const m = messages[i];
|
|
64367
64647
|
if (m.role === "user") {
|
|
64368
|
-
chunk.push(`User: ${
|
|
64648
|
+
chunk.push(`User: ${truncate2(m.content, 800)}`);
|
|
64369
64649
|
turns += 1;
|
|
64370
64650
|
} else if (m.role === "assistant" && m.content.trim()) {
|
|
64371
|
-
chunk.push(`Assistant: ${
|
|
64651
|
+
chunk.push(`Assistant: ${truncate2(m.content, 2e3)}`);
|
|
64372
64652
|
}
|
|
64373
64653
|
}
|
|
64374
64654
|
if (chunk.length === 0) return "";
|
|
@@ -64407,7 +64687,7 @@ The user CONFIRMED the plan and wants you to IMPLEMENT it ON DISK NOW.
|
|
|
64407
64687
|
- Do NOT restart from zero or re-ask for the overall goal.
|
|
64408
64688
|
|
|
64409
64689
|
## Prior assistant output (plan to implement \u2014 authoritative)
|
|
64410
|
-
${
|
|
64690
|
+
${truncate2(lastAsst.content, max)}
|
|
64411
64691
|
|
|
64412
64692
|
## Instruction
|
|
64413
64693
|
Implement the plan on disk now with mutating tools, then briefly list the files you wrote/edited.`;
|
|
@@ -64458,7 +64738,7 @@ function buildAgentUserWithHistory(task, prior) {
|
|
|
64458
64738
|
if (anchored) return anchored;
|
|
64459
64739
|
return buildContinueUserMessage(task, messages, { maxPriorChars: 8e3 }) ?? task;
|
|
64460
64740
|
}
|
|
64461
|
-
function
|
|
64741
|
+
function truncate2(s, max) {
|
|
64462
64742
|
const t = s.replace(/\s+/g, " ").trim();
|
|
64463
64743
|
if (t.length <= max) return t;
|
|
64464
64744
|
return `${t.slice(0, max - 1)}\u2026`;
|
|
@@ -64700,10 +64980,10 @@ __export(headless_exports, {
|
|
|
64700
64980
|
resolveHeadlessProvider: () => resolveHeadlessProvider
|
|
64701
64981
|
});
|
|
64702
64982
|
import { readFileSync as readFileSync34 } from "node:fs";
|
|
64703
|
-
import
|
|
64983
|
+
import path86 from "node:path";
|
|
64704
64984
|
function resolveHeadlessCwd(opts) {
|
|
64705
64985
|
const raw = typeof opts.cwd === "string" ? opts.cwd.trim() : "";
|
|
64706
|
-
return
|
|
64986
|
+
return path86.resolve(raw.length > 0 ? raw : process.cwd());
|
|
64707
64987
|
}
|
|
64708
64988
|
function defaultProfileForMode(mode) {
|
|
64709
64989
|
switch (mode) {
|
|
@@ -65069,7 +65349,7 @@ __export(headlessSpine_exports, {
|
|
|
65069
65349
|
seedHeadlessModelHistory: () => seedHeadlessModelHistory,
|
|
65070
65350
|
sessionStartedEvent: () => sessionStartedEvent
|
|
65071
65351
|
});
|
|
65072
|
-
import
|
|
65352
|
+
import path87 from "node:path";
|
|
65073
65353
|
function sessionStartedEvent(handle) {
|
|
65074
65354
|
return {
|
|
65075
65355
|
type: "session_started",
|
|
@@ -65086,7 +65366,7 @@ async function countVerificationEvidenceInLog(mirror, sessionId2) {
|
|
|
65086
65366
|
try {
|
|
65087
65367
|
await mirror.flush().catch(() => void 0);
|
|
65088
65368
|
const report = await readSessionLogCached(
|
|
65089
|
-
|
|
65369
|
+
path87.join(mirror.sessionsDir, sessionId2, "events.jsonl"),
|
|
65090
65370
|
mirror.replayCache
|
|
65091
65371
|
);
|
|
65092
65372
|
return report.events.filter((e) => e.kind === "verification.evidence").length;
|
|
@@ -65396,7 +65676,10 @@ async function buildModelContext(input) {
|
|
|
65396
65676
|
const sourceHistory = (derived ?? [...input.fallbackHistory]).filter(
|
|
65397
65677
|
(message) => !isLegacyResourceStatus(message)
|
|
65398
65678
|
);
|
|
65399
|
-
const requestTail =
|
|
65679
|
+
const requestTail = [
|
|
65680
|
+
...resourceStatusTail(input.resourceSnapshot),
|
|
65681
|
+
...input.volatileOnePager ?? []
|
|
65682
|
+
];
|
|
65400
65683
|
const inputTokens = estimateHistoryTokens(sourceHistory);
|
|
65401
65684
|
const requestSurface = input.systemMessages || input.tools ? {
|
|
65402
65685
|
provider: input.provider ?? "local",
|
|
@@ -65862,9 +66145,9 @@ __export(planDetect_exports, {
|
|
|
65862
66145
|
hasWorkspacePlan: () => hasWorkspacePlan
|
|
65863
66146
|
});
|
|
65864
66147
|
import { existsSync as existsSync45, readFileSync as readFileSync35 } from "node:fs";
|
|
65865
|
-
import { join as
|
|
66148
|
+
import { join as join30 } from "node:path";
|
|
65866
66149
|
function hasWorkspacePlan(projectRoot = process.cwd()) {
|
|
65867
|
-
const planPath =
|
|
66150
|
+
const planPath = join30(resolveWorkspaceRoot(projectRoot), "plan.json");
|
|
65868
66151
|
if (!existsSync45(planPath)) return false;
|
|
65869
66152
|
try {
|
|
65870
66153
|
const parsed = JSON.parse(readFileSync35(planPath, "utf8"));
|
|
@@ -65882,10 +66165,10 @@ var init_planDetect = __esm({
|
|
|
65882
66165
|
|
|
65883
66166
|
// src/cli/workspace/projectInstructions.ts
|
|
65884
66167
|
import { existsSync as existsSync46, readFileSync as readFileSync36 } from "node:fs";
|
|
65885
|
-
import { join as
|
|
66168
|
+
import { join as join31 } from "node:path";
|
|
65886
66169
|
function loadProjectInstructions(projectRoot = process.cwd(), maxChars = MAX_CHARS) {
|
|
65887
66170
|
for (const name of CANDIDATES) {
|
|
65888
|
-
const full =
|
|
66171
|
+
const full = join31(projectRoot, name);
|
|
65889
66172
|
if (!existsSync46(full)) continue;
|
|
65890
66173
|
try {
|
|
65891
66174
|
let raw = readFileSync36(full, "utf8");
|
|
@@ -65933,7 +66216,7 @@ __export(workspaceSummary_exports, {
|
|
|
65933
66216
|
buildZelariReadHint: () => buildZelariReadHint
|
|
65934
66217
|
});
|
|
65935
66218
|
import { existsSync as existsSync47, readFileSync as readFileSync37, readdirSync as readdirSync9, statSync as statSync8 } from "node:fs";
|
|
65936
|
-
import { join as
|
|
66219
|
+
import { join as join32, relative as relative2 } from "node:path";
|
|
65937
66220
|
function buildWorkspaceSummary(projectRoot = process.cwd(), options = {}) {
|
|
65938
66221
|
const { maxEntries = 30, maxChars = 3500, maxDeps = 24, maxScripts = 16 } = options;
|
|
65939
66222
|
const name = safeProjectName(projectRoot);
|
|
@@ -65966,7 +66249,7 @@ function formatTaskLine(t) {
|
|
|
65966
66249
|
}
|
|
65967
66250
|
function buildPlanSummary(projectRoot = process.cwd(), options) {
|
|
65968
66251
|
const zelariRoot = resolveWorkspaceRoot(projectRoot);
|
|
65969
|
-
const planPath =
|
|
66252
|
+
const planPath = join32(zelariRoot, "plan.json");
|
|
65970
66253
|
if (!existsSync47(planPath)) return null;
|
|
65971
66254
|
let plan;
|
|
65972
66255
|
try {
|
|
@@ -66109,7 +66392,7 @@ function pickNextTask(open2) {
|
|
|
66109
66392
|
)[0];
|
|
66110
66393
|
}
|
|
66111
66394
|
function buildZelariReadHint(projectRoot = process.cwd()) {
|
|
66112
|
-
const planPath =
|
|
66395
|
+
const planPath = join32(resolveWorkspaceRoot(projectRoot), "plan.json");
|
|
66113
66396
|
if (!existsSync47(planPath)) return "";
|
|
66114
66397
|
return [
|
|
66115
66398
|
"# Council workspace detected (.zelari/) \u2014 DRAFT vault",
|
|
@@ -66125,7 +66408,7 @@ function safeProjectName(root) {
|
|
|
66125
66408
|
}
|
|
66126
66409
|
}
|
|
66127
66410
|
function readPackageJson2(projectRoot) {
|
|
66128
|
-
const p3 =
|
|
66411
|
+
const p3 = join32(projectRoot, "package.json");
|
|
66129
66412
|
if (!existsSync47(p3)) return null;
|
|
66130
66413
|
try {
|
|
66131
66414
|
return JSON.parse(readFileSync37(p3, "utf8"));
|
|
@@ -66178,11 +66461,11 @@ function listShallow(projectRoot, maxEntries) {
|
|
|
66178
66461
|
out.push(`\u2026 (+${top.length - count} more)`);
|
|
66179
66462
|
break;
|
|
66180
66463
|
}
|
|
66181
|
-
const rel2 = relative2(projectRoot,
|
|
66464
|
+
const rel2 = relative2(projectRoot, join32(projectRoot, entry.name));
|
|
66182
66465
|
if (entry.isDirectory()) {
|
|
66183
66466
|
let inner = "";
|
|
66184
66467
|
try {
|
|
66185
|
-
const sub = readdirSync9(
|
|
66468
|
+
const sub = readdirSync9(join32(projectRoot, entry.name), {
|
|
66186
66469
|
withFileTypes: true
|
|
66187
66470
|
}).filter((e) => !e.name.startsWith(".")).slice(0, 4).map((e) => e.name);
|
|
66188
66471
|
if (sub.length > 0)
|
|
@@ -66231,11 +66514,11 @@ var init_workspaceSummary = __esm({
|
|
|
66231
66514
|
|
|
66232
66515
|
// src/cli/workspace/buildLessonsSummary.ts
|
|
66233
66516
|
import { existsSync as existsSync48 } from "node:fs";
|
|
66234
|
-
import { join as
|
|
66517
|
+
import { join as join33 } from "node:path";
|
|
66235
66518
|
function buildLessonsSummary(projectRoot = process.cwd(), taskText) {
|
|
66236
66519
|
if (process.env["ZELARI_LESSONS"] === "0") return null;
|
|
66237
66520
|
const zelariRoot = resolveWorkspaceRoot(projectRoot);
|
|
66238
|
-
if (!existsSync48(
|
|
66521
|
+
if (!existsSync48(join33(zelariRoot, "lessons.jsonl"))) return null;
|
|
66239
66522
|
const lessons = recallLessons(zelariRoot, {
|
|
66240
66523
|
maxLessons: 5,
|
|
66241
66524
|
maxBytes: 2048,
|
|
@@ -66257,7 +66540,7 @@ __export(composeContext_exports, {
|
|
|
66257
66540
|
composeProjectContext: () => composeProjectContext
|
|
66258
66541
|
});
|
|
66259
66542
|
import { existsSync as existsSync49, readdirSync as readdirSync10, readFileSync as readFileSync38 } from "node:fs";
|
|
66260
|
-
import { join as
|
|
66543
|
+
import { join as join34 } from "node:path";
|
|
66261
66544
|
function cap2(text, max, label) {
|
|
66262
66545
|
if (!text || text.length <= max) return { text: text || "", truncated: false };
|
|
66263
66546
|
return {
|
|
@@ -66274,7 +66557,7 @@ function buildDesignIndex(projectRoot, maxChars) {
|
|
|
66274
66557
|
"# Design vault index (.zelari/) \u2014 HYPOTHESES only",
|
|
66275
66558
|
"Full design docs are NOT product source of truth. Open with list_files / read_file / searchDocuments if needed."
|
|
66276
66559
|
];
|
|
66277
|
-
const docsDir =
|
|
66560
|
+
const docsDir = join34(root, "docs");
|
|
66278
66561
|
if (existsSync49(docsDir)) {
|
|
66279
66562
|
try {
|
|
66280
66563
|
const docs = readdirSync10(docsDir).filter((n) => n.endsWith(".md")).slice(0, 12);
|
|
@@ -66289,11 +66572,11 @@ function buildDesignIndex(projectRoot, maxChars) {
|
|
|
66289
66572
|
}
|
|
66290
66573
|
}
|
|
66291
66574
|
for (const name of ["risks.md", "plan.json", "nfr-spec.json"]) {
|
|
66292
|
-
if (existsSync49(
|
|
66575
|
+
if (existsSync49(join34(root, name))) {
|
|
66293
66576
|
lines.push(`- .zelari/${name} present`);
|
|
66294
66577
|
}
|
|
66295
66578
|
}
|
|
66296
|
-
const decisionsDir =
|
|
66579
|
+
const decisionsDir = join34(root, "decisions");
|
|
66297
66580
|
if (existsSync49(decisionsDir)) {
|
|
66298
66581
|
try {
|
|
66299
66582
|
const n = readdirSync10(decisionsDir).filter((f) => f.endsWith(".md")).length;
|
|
@@ -66395,14 +66678,14 @@ function composeProjectContext(input) {
|
|
|
66395
66678
|
}
|
|
66396
66679
|
function readDurableHeadSync(projectRoot) {
|
|
66397
66680
|
try {
|
|
66398
|
-
const headPath =
|
|
66681
|
+
const headPath = join34(projectRoot, ".zelari", "state", "HEAD.json");
|
|
66399
66682
|
if (!existsSync49(headPath)) return "";
|
|
66400
66683
|
const head = JSON.parse(readFileSync38(headPath, "utf8"));
|
|
66401
66684
|
if (!head?.id) return "";
|
|
66402
|
-
const metaPath =
|
|
66685
|
+
const metaPath = join34(projectRoot, ".zelari", "state", "commits", `${head.id}.json`);
|
|
66403
66686
|
if (!existsSync49(metaPath)) return "";
|
|
66404
66687
|
const meta3 = JSON.parse(readFileSync38(metaPath, "utf8"));
|
|
66405
|
-
const discPath = meta3.artifactDir ?
|
|
66688
|
+
const discPath = meta3.artifactDir ? join34(projectRoot, ".zelari", "state", meta3.artifactDir, "discoveries.json") : join34(projectRoot, ".zelari", "state", "artifacts", head.id, "discoveries.json");
|
|
66406
66689
|
let discoveries = [];
|
|
66407
66690
|
if (existsSync49(discPath)) {
|
|
66408
66691
|
discoveries = JSON.parse(readFileSync38(discPath, "utf8"));
|
|
@@ -66486,7 +66769,7 @@ import {
|
|
|
66486
66769
|
mkdirSync as mkdirSync19,
|
|
66487
66770
|
renameSync as renameSync5
|
|
66488
66771
|
} from "node:fs";
|
|
66489
|
-
import { join as
|
|
66772
|
+
import { join as join35, basename as basename4, dirname as dirname10, relative as relative3 } from "node:path";
|
|
66490
66773
|
function createWorkspaceContext(projectRoot = process.cwd()) {
|
|
66491
66774
|
const rootDir = resolveWorkspaceRoot(projectRoot);
|
|
66492
66775
|
return {
|
|
@@ -66496,7 +66779,7 @@ function createWorkspaceContext(projectRoot = process.cwd()) {
|
|
|
66496
66779
|
};
|
|
66497
66780
|
}
|
|
66498
66781
|
function planJsonPath(ctx) {
|
|
66499
|
-
return
|
|
66782
|
+
return join35(ctx.rootDir, "plan.json");
|
|
66500
66783
|
}
|
|
66501
66784
|
function readPlan(ctx) {
|
|
66502
66785
|
const jsonPath = planJsonPath(ctx);
|
|
@@ -66515,8 +66798,8 @@ function readPlan(ctx) {
|
|
|
66515
66798
|
} catch {
|
|
66516
66799
|
}
|
|
66517
66800
|
}
|
|
66518
|
-
const
|
|
66519
|
-
const doc = ctx.storage.readIfExists(
|
|
66801
|
+
const path128 = workspaceFile(ctx.rootDir, "plan");
|
|
66802
|
+
const doc = ctx.storage.readIfExists(path128);
|
|
66520
66803
|
if (!doc) return { phases: [], tasks: [], milestones: [] };
|
|
66521
66804
|
const meta3 = doc.meta;
|
|
66522
66805
|
return {
|
|
@@ -66609,7 +66892,7 @@ function renderPlanBody(summary) {
|
|
|
66609
66892
|
return lines.join("\n");
|
|
66610
66893
|
}
|
|
66611
66894
|
function nextAdrId(ctx) {
|
|
66612
|
-
const decisionsDir =
|
|
66895
|
+
const decisionsDir = join35(ctx.rootDir, "decisions");
|
|
66613
66896
|
if (!existsSync50(decisionsDir)) return "001";
|
|
66614
66897
|
const existing = readdirSync11(decisionsDir).filter((f) => f.endsWith(".md")).map((f) => f.match(/^(\d+)-/)).filter((m) => !!m).map((m) => parseInt(m[1], 10));
|
|
66615
66898
|
const max = existing.length === 0 ? 0 : Math.max(...existing);
|
|
@@ -66634,14 +66917,14 @@ function addPhaseRecord(summary, input) {
|
|
|
66634
66917
|
return { id: id3, created: true };
|
|
66635
66918
|
}
|
|
66636
66919
|
function addTaskRecord(ctx, summary, phaseId, t, options) {
|
|
66637
|
-
const
|
|
66920
|
+
const slug2 = slugify3(t.title);
|
|
66638
66921
|
if (options.dedupe) {
|
|
66639
66922
|
const existing = summary.tasks.find(
|
|
66640
|
-
(k) => k.phaseId === phaseId && k.id.replace(/-\d+$/, "") === `${phaseId}-${
|
|
66923
|
+
(k) => k.phaseId === phaseId && k.id.replace(/-\d+$/, "") === `${phaseId}-${slug2}`
|
|
66641
66924
|
);
|
|
66642
66925
|
if (existing) return { id: existing.id, created: false };
|
|
66643
66926
|
}
|
|
66644
|
-
const id3 = `${phaseId}-${
|
|
66927
|
+
const id3 = `${phaseId}-${slug2}-${summary.tasks.filter((k) => k.phaseId === phaseId).length + 1}`;
|
|
66645
66928
|
summary.tasks.push({
|
|
66646
66929
|
kind: "task",
|
|
66647
66930
|
id: id3,
|
|
@@ -66655,7 +66938,7 @@ function addTaskRecord(ctx, summary, phaseId, t, options) {
|
|
|
66655
66938
|
// plan.json record (they already live in tags + the artifact body md).
|
|
66656
66939
|
files: t.fileRefs
|
|
66657
66940
|
});
|
|
66658
|
-
const taskPath =
|
|
66941
|
+
const taskPath = join35(ctx.rootDir, "plan-tasks", `${id3}.md`);
|
|
66659
66942
|
const meta3 = {
|
|
66660
66943
|
kind: "task",
|
|
66661
66944
|
id: id3,
|
|
@@ -66697,7 +66980,7 @@ function addMilestoneRecord(ctx, summary, input) {
|
|
|
66697
66980
|
dueDate: input.dueDate,
|
|
66698
66981
|
targetVersion: version2
|
|
66699
66982
|
});
|
|
66700
|
-
const
|
|
66983
|
+
const path128 = join35(ctx.rootDir, "milestones", `${id3}.md`);
|
|
66701
66984
|
const meta3 = {
|
|
66702
66985
|
kind: "milestone",
|
|
66703
66986
|
id: id3,
|
|
@@ -66714,7 +66997,7 @@ function addMilestoneRecord(ctx, summary, input) {
|
|
|
66714
66997
|
`Target version: ${version2}`,
|
|
66715
66998
|
""
|
|
66716
66999
|
].join("\n");
|
|
66717
|
-
ctx.storage.write(
|
|
67000
|
+
ctx.storage.write(path128, meta3, body);
|
|
66718
67001
|
return { id: id3, created: true };
|
|
66719
67002
|
}
|
|
66720
67003
|
function readPlanSummary(ctx) {
|
|
@@ -66918,7 +67201,7 @@ function addIdeaStub(ctx) {
|
|
|
66918
67201
|
const tags = args["tags"] ?? [];
|
|
66919
67202
|
const category = args["category"] ?? "General";
|
|
66920
67203
|
const id3 = `${nextAdrId(ctx)}-${slugify3(title)}`;
|
|
66921
|
-
const
|
|
67204
|
+
const path128 = workspaceArtifact(ctx.rootDir, "decisions", id3);
|
|
66922
67205
|
const meta3 = {
|
|
66923
67206
|
kind: "adr",
|
|
66924
67207
|
status: "proposed",
|
|
@@ -66944,7 +67227,7 @@ function addIdeaStub(ctx) {
|
|
|
66944
67227
|
...consequences.map((c) => `- ${c}`),
|
|
66945
67228
|
""
|
|
66946
67229
|
].join("\n");
|
|
66947
|
-
ctx.storage.write(
|
|
67230
|
+
ctx.storage.write(path128, meta3, body);
|
|
66948
67231
|
return `ADR ${id3} created: "${title}". Status: proposed. Promote to accepted via /update ADR or manual edit.`;
|
|
66949
67232
|
});
|
|
66950
67233
|
}
|
|
@@ -66995,7 +67278,7 @@ function createNfrSpecStub(ctx) {
|
|
|
66995
67278
|
},
|
|
66996
67279
|
planFeatureKeywords: Array.isArray(args["planFeatureKeywords"]) ? args["planFeatureKeywords"] : void 0
|
|
66997
67280
|
};
|
|
66998
|
-
const outPath =
|
|
67281
|
+
const outPath = join35(ctx.rootDir, "nfr-spec.json");
|
|
66999
67282
|
writeFileSync21(outPath, JSON.stringify(spec, null, 2), "utf8");
|
|
67000
67283
|
return `NFR spec written to nfr-spec.json (${targets.length} target(s)).`;
|
|
67001
67284
|
});
|
|
@@ -67014,8 +67297,8 @@ function createDocumentStub(ctx) {
|
|
|
67014
67297
|
const content = args["content"] ?? "";
|
|
67015
67298
|
const tags = args["tags"] ?? [];
|
|
67016
67299
|
const normalizedTitle = title.replace(/\.(md|markdown)\s*$/i, "");
|
|
67017
|
-
const
|
|
67018
|
-
if (
|
|
67300
|
+
const slug2 = slugify3(normalizedTitle) || `doc-${Date.now()}`;
|
|
67301
|
+
if (slug2 === "risks") {
|
|
67019
67302
|
const risksPath = workspaceFile(ctx.rootDir, "risks");
|
|
67020
67303
|
const riskMeta = {
|
|
67021
67304
|
kind: "risk",
|
|
@@ -67026,15 +67309,15 @@ function createDocumentStub(ctx) {
|
|
|
67026
67309
|
ctx.storage.write(risksPath, riskMeta, content);
|
|
67027
67310
|
return `Document "${title}" created at risks.md (workspace root).`;
|
|
67028
67311
|
}
|
|
67029
|
-
const
|
|
67312
|
+
const path128 = workspaceArtifact(ctx.rootDir, "docs", slug2);
|
|
67030
67313
|
const meta3 = {
|
|
67031
67314
|
kind: "doc",
|
|
67032
|
-
id:
|
|
67315
|
+
id: slug2,
|
|
67033
67316
|
date: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10),
|
|
67034
67317
|
tags
|
|
67035
67318
|
};
|
|
67036
|
-
ctx.storage.write(
|
|
67037
|
-
return `Document "${title}" created at docs/${
|
|
67319
|
+
ctx.storage.write(path128, meta3, content);
|
|
67320
|
+
return `Document "${title}" created at docs/${slug2}.md.`;
|
|
67038
67321
|
});
|
|
67039
67322
|
}
|
|
67040
67323
|
};
|
|
@@ -67059,11 +67342,11 @@ function searchDocumentsStub(ctx) {
|
|
|
67059
67342
|
(w) => w.length >= 3 && w !== "or" && w !== "and" && w !== "the"
|
|
67060
67343
|
);
|
|
67061
67344
|
const files = [
|
|
67062
|
-
...ctx.storage.listMarkdown(
|
|
67063
|
-
...ctx.storage.listMarkdown(
|
|
67064
|
-
...ctx.storage.listMarkdown(
|
|
67065
|
-
...ctx.storage.listMarkdown(
|
|
67066
|
-
...ctx.storage.listMarkdown(
|
|
67345
|
+
...ctx.storage.listMarkdown(join35(ctx.rootDir, "decisions")),
|
|
67346
|
+
...ctx.storage.listMarkdown(join35(ctx.rootDir, "docs")),
|
|
67347
|
+
...ctx.storage.listMarkdown(join35(ctx.rootDir, "reviews")),
|
|
67348
|
+
...ctx.storage.listMarkdown(join35(ctx.rootDir, "plan-tasks")),
|
|
67349
|
+
...ctx.storage.listMarkdown(join35(ctx.rootDir, "milestones")),
|
|
67067
67350
|
workspaceFile(ctx.rootDir, "plan"),
|
|
67068
67351
|
workspaceFile(ctx.rootDir, "risks")
|
|
67069
67352
|
];
|
|
@@ -67121,9 +67404,9 @@ function linkDocumentsStub(ctx) {
|
|
|
67121
67404
|
const toId = args["toId"] ?? args["targetId"] ?? args["targetPathOrTitle"];
|
|
67122
67405
|
if (!fromId || !toId) return "linkDocuments requires fromId and toId.";
|
|
67123
67406
|
const allFiles = [
|
|
67124
|
-
...ctx.storage.listMarkdown(
|
|
67125
|
-
...ctx.storage.listMarkdown(
|
|
67126
|
-
...ctx.storage.listMarkdown(
|
|
67407
|
+
...ctx.storage.listMarkdown(join35(ctx.rootDir, "decisions")),
|
|
67408
|
+
...ctx.storage.listMarkdown(join35(ctx.rootDir, "docs")),
|
|
67409
|
+
...ctx.storage.listMarkdown(join35(ctx.rootDir, "reviews"))
|
|
67127
67410
|
];
|
|
67128
67411
|
const source2 = allFiles.find((f) => {
|
|
67129
67412
|
try {
|
|
@@ -67154,9 +67437,9 @@ function getDocumentBacklinksStub(ctx) {
|
|
|
67154
67437
|
const targetId = args["targetId"] ?? args["id"];
|
|
67155
67438
|
if (!targetId) return "getDocumentBacklinks requires targetId.";
|
|
67156
67439
|
const allFiles = [
|
|
67157
|
-
...ctx.storage.listMarkdown(
|
|
67158
|
-
...ctx.storage.listMarkdown(
|
|
67159
|
-
...ctx.storage.listMarkdown(
|
|
67440
|
+
...ctx.storage.listMarkdown(join35(ctx.rootDir, "decisions")),
|
|
67441
|
+
...ctx.storage.listMarkdown(join35(ctx.rootDir, "docs")),
|
|
67442
|
+
...ctx.storage.listMarkdown(join35(ctx.rootDir, "reviews"))
|
|
67160
67443
|
];
|
|
67161
67444
|
const backlinks = [];
|
|
67162
67445
|
for (const file2 of allFiles) {
|
|
@@ -67656,17 +67939,17 @@ import {
|
|
|
67656
67939
|
readFileSync as readFileSync40,
|
|
67657
67940
|
writeFileSync as writeFileSync22
|
|
67658
67941
|
} from "node:fs";
|
|
67659
|
-
import { dirname as dirname11, join as
|
|
67942
|
+
import { dirname as dirname11, join as join36 } from "node:path";
|
|
67660
67943
|
function getUserMcpPath() {
|
|
67661
|
-
return
|
|
67944
|
+
return join36(zelariHome(), "mcp.json");
|
|
67662
67945
|
}
|
|
67663
67946
|
function getProjectMcpPath(projectRoot) {
|
|
67664
|
-
return
|
|
67947
|
+
return join36(projectRoot, ".zelari", "mcp.json");
|
|
67665
67948
|
}
|
|
67666
|
-
function readFile10(
|
|
67667
|
-
if (!existsSync51(
|
|
67949
|
+
function readFile10(path128) {
|
|
67950
|
+
if (!existsSync51(path128)) return {};
|
|
67668
67951
|
try {
|
|
67669
|
-
const parsed = JSON.parse(readFileSync40(
|
|
67952
|
+
const parsed = JSON.parse(readFileSync40(path128, "utf8"));
|
|
67670
67953
|
const out = {};
|
|
67671
67954
|
for (const [name, cfg] of Object.entries(parsed.mcpServers ?? {})) {
|
|
67672
67955
|
const hasCommand = !!cfg && typeof cfg.command === "string" && !!cfg.command.trim();
|
|
@@ -67688,10 +67971,10 @@ function readFile10(path126) {
|
|
|
67688
67971
|
return {};
|
|
67689
67972
|
}
|
|
67690
67973
|
}
|
|
67691
|
-
function writeFile4(
|
|
67692
|
-
mkdirSync20(dirname11(
|
|
67974
|
+
function writeFile4(path128, servers) {
|
|
67975
|
+
mkdirSync20(dirname11(path128), { recursive: true });
|
|
67693
67976
|
const body = { mcpServers: servers };
|
|
67694
|
-
writeFileSync22(
|
|
67977
|
+
writeFileSync22(path128, `${JSON.stringify(body, null, 2)}
|
|
67695
67978
|
`, "utf8");
|
|
67696
67979
|
}
|
|
67697
67980
|
function listMcpServers(projectRoot) {
|
|
@@ -67769,9 +68052,9 @@ function upsertMcpServer(opts) {
|
|
|
67769
68052
|
error: "either command (stdio) or url (http) is required"
|
|
67770
68053
|
};
|
|
67771
68054
|
}
|
|
67772
|
-
let
|
|
68055
|
+
let path128;
|
|
67773
68056
|
if (opts.scope === "user") {
|
|
67774
|
-
|
|
68057
|
+
path128 = getUserMcpPath();
|
|
67775
68058
|
} else {
|
|
67776
68059
|
const root = opts.projectRoot?.trim();
|
|
67777
68060
|
if (!root) {
|
|
@@ -67780,9 +68063,9 @@ function upsertMcpServer(opts) {
|
|
|
67780
68063
|
error: "projectRoot required for project scope (Open Folder first)"
|
|
67781
68064
|
};
|
|
67782
68065
|
}
|
|
67783
|
-
|
|
68066
|
+
path128 = getProjectMcpPath(root);
|
|
67784
68067
|
}
|
|
67785
|
-
const current = readFile10(
|
|
68068
|
+
const current = readFile10(path128);
|
|
67786
68069
|
const previous = current[name];
|
|
67787
68070
|
current[name] = {
|
|
67788
68071
|
command: hasCommand ? opts.config.command.trim() : void 0,
|
|
@@ -67798,21 +68081,21 @@ function upsertMcpServer(opts) {
|
|
|
67798
68081
|
serial: opts.config.serial,
|
|
67799
68082
|
enabled: opts.config.enabled !== false
|
|
67800
68083
|
};
|
|
67801
|
-
writeFile4(
|
|
67802
|
-
return { ok: true, path:
|
|
68084
|
+
writeFile4(path128, current);
|
|
68085
|
+
return { ok: true, path: path128 };
|
|
67803
68086
|
}
|
|
67804
68087
|
function removeMcpServer(opts) {
|
|
67805
|
-
const
|
|
67806
|
-
if (!
|
|
68088
|
+
const path128 = opts.scope === "user" ? getUserMcpPath() : opts.projectRoot ? getProjectMcpPath(opts.projectRoot) : null;
|
|
68089
|
+
if (!path128) {
|
|
67807
68090
|
return { ok: false, error: "projectRoot required for project scope" };
|
|
67808
68091
|
}
|
|
67809
|
-
const current = readFile10(
|
|
68092
|
+
const current = readFile10(path128);
|
|
67810
68093
|
if (!(opts.name in current)) {
|
|
67811
|
-
return { ok: false, error: `Server "${opts.name}" not found in ${
|
|
68094
|
+
return { ok: false, error: `Server "${opts.name}" not found in ${path128}` };
|
|
67812
68095
|
}
|
|
67813
68096
|
delete current[opts.name];
|
|
67814
|
-
writeFile4(
|
|
67815
|
-
return { ok: true, path:
|
|
68097
|
+
writeFile4(path128, current);
|
|
68098
|
+
return { ok: true, path: path128 };
|
|
67816
68099
|
}
|
|
67817
68100
|
var ENV_KEY_RE;
|
|
67818
68101
|
var init_mcpConfigIo = __esm({
|
|
@@ -67987,15 +68270,15 @@ __export(mcpManager_exports, {
|
|
|
67987
68270
|
registerMcpTools: () => registerMcpTools
|
|
67988
68271
|
});
|
|
67989
68272
|
import { existsSync as existsSync52, readFileSync as readFileSync41 } from "node:fs";
|
|
67990
|
-
import { join as
|
|
68273
|
+
import { join as join37 } from "node:path";
|
|
67991
68274
|
function readMcpConfig(projectRoot = process.cwd(), opts) {
|
|
67992
68275
|
const merged = {};
|
|
67993
68276
|
const paths = [];
|
|
67994
68277
|
if (process.env["ZELARI_MCP_USER"] !== "0") {
|
|
67995
|
-
paths.push(
|
|
68278
|
+
paths.push(join37(zelariHome(), "mcp.json"));
|
|
67996
68279
|
}
|
|
67997
68280
|
if (!opts?.skipProjectMcp) {
|
|
67998
|
-
paths.push(
|
|
68281
|
+
paths.push(join37(projectRoot, ".zelari", "mcp.json"));
|
|
67999
68282
|
}
|
|
68000
68283
|
for (const p3 of paths) {
|
|
68001
68284
|
if (!existsSync52(p3)) continue;
|
|
@@ -68016,7 +68299,7 @@ async function ensureLoaded(projectRoot) {
|
|
|
68016
68299
|
if (state2.loaded) return;
|
|
68017
68300
|
state2.loaded = true;
|
|
68018
68301
|
const trusted = isFolderTrusted(projectRoot);
|
|
68019
|
-
if (!trusted && existsSync52(
|
|
68302
|
+
if (!trusted && existsSync52(join37(projectRoot, ".zelari", "mcp.json"))) {
|
|
68020
68303
|
state2.warnings.push(
|
|
68021
68304
|
"[mcp] project .zelari/mcp.json ignored \u2014 folder not trusted (run /trust or `zelari-code --trust` to enable project MCP)"
|
|
68022
68305
|
);
|
|
@@ -68286,13 +68569,13 @@ __export(agentsMd_exports, {
|
|
|
68286
68569
|
});
|
|
68287
68570
|
import { existsSync as existsSync53, readFileSync as readFileSync42, writeFileSync as writeFileSync23 } from "node:fs";
|
|
68288
68571
|
import { createHash as createHash25 } from "node:crypto";
|
|
68289
|
-
import { join as
|
|
68572
|
+
import { join as join38 } from "node:path";
|
|
68290
68573
|
import { readFile as readFile11 } from "node:fs/promises";
|
|
68291
68574
|
async function readPackageJson3(projectRoot) {
|
|
68292
|
-
const
|
|
68293
|
-
if (!existsSync53(
|
|
68575
|
+
const path128 = join38(projectRoot, "package.json");
|
|
68576
|
+
if (!existsSync53(path128)) return null;
|
|
68294
68577
|
try {
|
|
68295
|
-
return JSON.parse(await readFile11(
|
|
68578
|
+
return JSON.parse(await readFile11(path128, "utf8"));
|
|
68296
68579
|
} catch {
|
|
68297
68580
|
return null;
|
|
68298
68581
|
}
|
|
@@ -68314,7 +68597,7 @@ async function genTechStack(ctx) {
|
|
|
68314
68597
|
].join("\n");
|
|
68315
68598
|
}
|
|
68316
68599
|
async function genDecisions(ctx) {
|
|
68317
|
-
const decisionsDir =
|
|
68600
|
+
const decisionsDir = join38(ctx.rootDir, "decisions");
|
|
68318
68601
|
if (!existsSync53(decisionsDir)) return "_No ADRs yet._";
|
|
68319
68602
|
const files = ctx.storage.listMarkdown(decisionsDir).sort();
|
|
68320
68603
|
const accepted = [];
|
|
@@ -68340,7 +68623,7 @@ async function genDecisions(ctx) {
|
|
|
68340
68623
|
}
|
|
68341
68624
|
async function genConventions(ctx) {
|
|
68342
68625
|
const lines = [];
|
|
68343
|
-
const claudeMd =
|
|
68626
|
+
const claudeMd = join38(ctx.projectRoot, "CLAUDE.MD");
|
|
68344
68627
|
if (existsSync53(claudeMd)) {
|
|
68345
68628
|
const content = readFileSync42(claudeMd, "utf8");
|
|
68346
68629
|
const match = content.match(/## Architecture rules[\s\S]+?(?=\n## |\n*$)/);
|
|
@@ -68374,9 +68657,9 @@ async function genBuild(ctx) {
|
|
|
68374
68657
|
].join("\n");
|
|
68375
68658
|
}
|
|
68376
68659
|
async function genOpenQuestions(ctx) {
|
|
68377
|
-
const
|
|
68378
|
-
if (!existsSync53(
|
|
68379
|
-
const content = readFileSync42(
|
|
68660
|
+
const path128 = join38(ctx.rootDir, "risks.md");
|
|
68661
|
+
if (!existsSync53(path128)) return "_No open questions._";
|
|
68662
|
+
const content = readFileSync42(path128, "utf8");
|
|
68380
68663
|
const lines = content.split("\n");
|
|
68381
68664
|
const questions = [];
|
|
68382
68665
|
let currentTitle = "";
|
|
@@ -68450,7 +68733,7 @@ function titleCase(id3) {
|
|
|
68450
68733
|
return id3.split("-").map((w) => w[0].toUpperCase() + w.slice(1)).join(" ");
|
|
68451
68734
|
}
|
|
68452
68735
|
async function updateAgentsMd(ctx, projectRoot) {
|
|
68453
|
-
const agentsPath =
|
|
68736
|
+
const agentsPath = join38(projectRoot, "AGENTS.MD");
|
|
68454
68737
|
if (existsSync53(agentsPath)) {
|
|
68455
68738
|
const content = readFileSync42(agentsPath, "utf8");
|
|
68456
68739
|
const hasAnyMarker = AUTO_SECTIONS.some((id3) => content.includes(MARKER_OPEN(id3)));
|
|
@@ -68622,11 +68905,11 @@ var init_completeDesign = __esm({
|
|
|
68622
68905
|
|
|
68623
68906
|
// src/cli/workspace/planDriftCheck.ts
|
|
68624
68907
|
import { existsSync as existsSync54, readFileSync as readFileSync43, readdirSync as readdirSync12, statSync as statSync9, writeFileSync as writeFileSync24 } from "node:fs";
|
|
68625
|
-
import { join as
|
|
68908
|
+
import { join as join39 } from "node:path";
|
|
68626
68909
|
function findCanonicalDoc(rootDir) {
|
|
68627
|
-
const docsDir =
|
|
68910
|
+
const docsDir = join39(rootDir, "docs");
|
|
68628
68911
|
if (!existsSync54(docsDir)) return null;
|
|
68629
|
-
const candidates = readdirSync12(docsDir).filter((f) => /^plan-canonical.*\.md$/i.test(f)).map((f) => ({ f, mtime: statSync9(
|
|
68912
|
+
const candidates = readdirSync12(docsDir).filter((f) => /^plan-canonical.*\.md$/i.test(f)).map((f) => ({ f, mtime: statSync9(join39(docsDir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
|
|
68630
68913
|
return candidates.length > 0 ? candidates[0].f : null;
|
|
68631
68914
|
}
|
|
68632
68915
|
function parseCanonicalDoc(text) {
|
|
@@ -68650,9 +68933,9 @@ function versionKey(value) {
|
|
|
68650
68933
|
function firstString2(v) {
|
|
68651
68934
|
return typeof v === "string" && v.trim().length > 0 ? v : null;
|
|
68652
68935
|
}
|
|
68653
|
-
function readFileSyncSafe(
|
|
68936
|
+
function readFileSyncSafe(path128) {
|
|
68654
68937
|
try {
|
|
68655
|
-
return readFileSync43(
|
|
68938
|
+
return readFileSync43(path128, "utf8");
|
|
68656
68939
|
} catch {
|
|
68657
68940
|
return null;
|
|
68658
68941
|
}
|
|
@@ -68661,7 +68944,7 @@ async function runPlanDriftCheck(rootDir) {
|
|
|
68661
68944
|
if (process.env["ZELARI_DRIFT_CHECK"] === "0") {
|
|
68662
68945
|
return { ran: false, reason: "ZELARI_DRIFT_CHECK=0 (disabled)" };
|
|
68663
68946
|
}
|
|
68664
|
-
const planPath =
|
|
68947
|
+
const planPath = join39(rootDir, "plan.json");
|
|
68665
68948
|
if (!existsSync54(planPath)) {
|
|
68666
68949
|
return { ran: false, reason: ".zelari/plan.json missing (not design-phase)" };
|
|
68667
68950
|
}
|
|
@@ -68677,7 +68960,7 @@ async function runPlanDriftCheck(rootDir) {
|
|
|
68677
68960
|
const milestones = Array.isArray(plan.milestones) ? plan.milestones : [];
|
|
68678
68961
|
const phaseIds = new Set(phases.map((p3) => typeof p3.id === "string" ? p3.id : "").filter(Boolean));
|
|
68679
68962
|
const canonicalName = findCanonicalDoc(rootDir);
|
|
68680
|
-
const canonicalText = canonicalName ? readFileSyncSafe(
|
|
68963
|
+
const canonicalText = canonicalName ? readFileSyncSafe(join39(rootDir, "docs", canonicalName)) : null;
|
|
68681
68964
|
if (canonicalText !== null) {
|
|
68682
68965
|
const { activePhases, blockedPrefixes } = parseCanonicalDoc(canonicalText);
|
|
68683
68966
|
for (const id3 of activePhases) {
|
|
@@ -68756,7 +69039,7 @@ async function runPlanDriftCheck(rootDir) {
|
|
|
68756
69039
|
const canonicalParsed = canonicalName !== null && canonicalText !== null;
|
|
68757
69040
|
let reportPath;
|
|
68758
69041
|
try {
|
|
68759
|
-
reportPath =
|
|
69042
|
+
reportPath = join39(rootDir, "drift-report.json");
|
|
68760
69043
|
writeFileSync24(
|
|
68761
69044
|
reportPath,
|
|
68762
69045
|
JSON.stringify(
|
|
@@ -68794,7 +69077,7 @@ var init_planDriftCheck = __esm({
|
|
|
68794
69077
|
// src/cli/workspace/projectSmoke.ts
|
|
68795
69078
|
import { spawn as spawn15 } from "node:child_process";
|
|
68796
69079
|
import { existsSync as existsSync55, readFileSync as readFileSync44 } from "node:fs";
|
|
68797
|
-
import { join as
|
|
69080
|
+
import { join as join40 } from "node:path";
|
|
68798
69081
|
function pickSmokeScript(scripts) {
|
|
68799
69082
|
if (!scripts) return null;
|
|
68800
69083
|
for (const name of SMOKE_SCRIPT_PRIORITY) {
|
|
@@ -68806,7 +69089,7 @@ async function runProjectSmoke(projectRoot, timeoutMs2 = DEFAULT_TIMEOUT_MS3) {
|
|
|
68806
69089
|
if (process.env["ZELARI_SMOKE"] === "0") {
|
|
68807
69090
|
return { ran: false, reason: "ZELARI_SMOKE=0 (disabled)" };
|
|
68808
69091
|
}
|
|
68809
|
-
const pkgPath =
|
|
69092
|
+
const pkgPath = join40(projectRoot, "package.json");
|
|
68810
69093
|
if (!existsSync55(pkgPath)) {
|
|
68811
69094
|
return { ran: false, reason: "no package.json (skipped)" };
|
|
68812
69095
|
}
|
|
@@ -68900,7 +69183,7 @@ __export(evidenceFromSpine_exports, {
|
|
|
68900
69183
|
evidenceRefsFromEventLines: () => evidenceRefsFromEventLines
|
|
68901
69184
|
});
|
|
68902
69185
|
import { existsSync as existsSync56, readFileSync as readFileSync45 } from "node:fs";
|
|
68903
|
-
import
|
|
69186
|
+
import path88 from "node:path";
|
|
68904
69187
|
function asRecord5(v) {
|
|
68905
69188
|
return v && typeof v === "object" && !Array.isArray(v) ? v : void 0;
|
|
68906
69189
|
}
|
|
@@ -68938,7 +69221,7 @@ function evidenceRefsFromEventLines(lines) {
|
|
|
68938
69221
|
}
|
|
68939
69222
|
function collectSessionEvidenceRefs(sessionId2) {
|
|
68940
69223
|
try {
|
|
68941
|
-
const file2 =
|
|
69224
|
+
const file2 = path88.join(sessionsDir(), sessionId2, "events.jsonl");
|
|
68942
69225
|
if (!existsSync56(file2)) return [];
|
|
68943
69226
|
return evidenceRefsFromEventLines(readFileSync45(file2, "utf8").split("\n"));
|
|
68944
69227
|
} catch {
|
|
@@ -68964,7 +69247,7 @@ __export(postCouncilHook_exports, {
|
|
|
68964
69247
|
});
|
|
68965
69248
|
import { spawn as spawn16 } from "node:child_process";
|
|
68966
69249
|
import { existsSync as existsSync57, readFileSync as readFileSync46 } from "node:fs";
|
|
68967
|
-
import { join as
|
|
69250
|
+
import { join as join41 } from "node:path";
|
|
68968
69251
|
async function runCompleteDesignPostProcessor(ctx, options) {
|
|
68969
69252
|
if (options?.runMode === "implementation") {
|
|
68970
69253
|
return {
|
|
@@ -68975,8 +69258,8 @@ async function runCompleteDesignPostProcessor(ctx, options) {
|
|
|
68975
69258
|
if (process.env["ZELARI_COMPLETE_DESIGN"] === "0") {
|
|
68976
69259
|
return { ran: false, reason: "ZELARI_COMPLETE_DESIGN=0 (disabled)" };
|
|
68977
69260
|
}
|
|
68978
|
-
const planJsonPath2 =
|
|
68979
|
-
const scriptPath =
|
|
69261
|
+
const planJsonPath2 = join41(ctx.rootDir, "plan.json");
|
|
69262
|
+
const scriptPath = join41(ctx.projectRoot, "complete-design.mjs");
|
|
68980
69263
|
if (!existsSync57(planJsonPath2)) {
|
|
68981
69264
|
return {
|
|
68982
69265
|
ran: false,
|
|
@@ -69188,8 +69471,8 @@ async function runPostCouncilHook(ctx, options) {
|
|
|
69188
69471
|
sources: scope.sources
|
|
69189
69472
|
} : void 0
|
|
69190
69473
|
});
|
|
69191
|
-
const
|
|
69192
|
-
completionHook = { ran: true, path:
|
|
69474
|
+
const path128 = writeCouncilCompletion(ctx.rootDir, completion);
|
|
69475
|
+
completionHook = { ran: true, path: path128, completion };
|
|
69193
69476
|
} catch (err) {
|
|
69194
69477
|
completionHook = {
|
|
69195
69478
|
ran: true,
|
|
@@ -69228,13 +69511,13 @@ __export(councilFeedback_exports, {
|
|
|
69228
69511
|
FeedbackStore: () => FeedbackStore
|
|
69229
69512
|
});
|
|
69230
69513
|
import {
|
|
69231
|
-
promises as
|
|
69514
|
+
promises as fs35,
|
|
69232
69515
|
existsSync as existsSync58,
|
|
69233
69516
|
readFileSync as readFileSync47,
|
|
69234
69517
|
writeFileSync as writeFileSync25,
|
|
69235
69518
|
mkdirSync as mkdirSync21
|
|
69236
69519
|
} from "node:fs";
|
|
69237
|
-
import
|
|
69520
|
+
import path89 from "node:path";
|
|
69238
69521
|
var FeedbackStore;
|
|
69239
69522
|
var init_councilFeedback = __esm({
|
|
69240
69523
|
"src/cli/councilFeedback.ts"() {
|
|
@@ -69351,7 +69634,7 @@ var init_councilFeedback = __esm({
|
|
|
69351
69634
|
}
|
|
69352
69635
|
}
|
|
69353
69636
|
save() {
|
|
69354
|
-
mkdirSync21(
|
|
69637
|
+
mkdirSync21(path89.dirname(this.file), { recursive: true });
|
|
69355
69638
|
writeFileSync25(
|
|
69356
69639
|
this.file,
|
|
69357
69640
|
JSON.stringify({ entries: this.entries }, null, 2),
|
|
@@ -69361,7 +69644,7 @@ var init_councilFeedback = __esm({
|
|
|
69361
69644
|
/** Async variant of load for callers that prefer async IO. */
|
|
69362
69645
|
async loadAsync() {
|
|
69363
69646
|
try {
|
|
69364
|
-
const raw = await
|
|
69647
|
+
const raw = await fs35.readFile(this.file, "utf-8");
|
|
69365
69648
|
const parsed = JSON.parse(raw);
|
|
69366
69649
|
if (parsed && Array.isArray(parsed.entries)) {
|
|
69367
69650
|
this.entries = parsed.entries.filter(
|
|
@@ -69418,22 +69701,77 @@ var init_buildPolicy = __esm({
|
|
|
69418
69701
|
var ledger_exports = {};
|
|
69419
69702
|
__export(ledger_exports, {
|
|
69420
69703
|
EVOLUTION_ENV: () => EVOLUTION_ENV,
|
|
69704
|
+
EVOLUTION_PATHS: () => EVOLUTION_PATHS,
|
|
69705
|
+
FINDINGS_REL: () => FINDINGS_REL,
|
|
69421
69706
|
HONESTY_CHECK_PREFIX: () => HONESTY_CHECK_PREFIX,
|
|
69422
69707
|
LEDGER_REL: () => LEDGER_REL,
|
|
69708
|
+
appendFindings: () => appendFindings,
|
|
69423
69709
|
appendLedgerEntry: () => appendLedgerEntry,
|
|
69424
69710
|
evolutionMode: () => evolutionMode,
|
|
69711
|
+
findingFingerprint: () => findingFingerprint,
|
|
69712
|
+
findingsPath: () => findingsPath,
|
|
69425
69713
|
honestyFromVerificationResults: () => honestyFromVerificationResults,
|
|
69426
69714
|
ledgerPath: () => ledgerPath,
|
|
69427
69715
|
ledgerStats: () => ledgerStats,
|
|
69716
|
+
readFindings: () => readFindings,
|
|
69428
69717
|
readLedger: () => readLedger
|
|
69429
69718
|
});
|
|
69430
69719
|
import { appendFileSync as appendFileSync4, existsSync as existsSync59, mkdirSync as mkdirSync22, readFileSync as readFileSync48 } from "node:fs";
|
|
69431
|
-
import
|
|
69720
|
+
import path90 from "node:path";
|
|
69721
|
+
function findingFingerprint(f) {
|
|
69722
|
+
return [f.kind || "unknown", f.operator || "-", f.surface || "-", f.signal || "-"].join("|");
|
|
69723
|
+
}
|
|
69724
|
+
function findingsPath(cwd) {
|
|
69725
|
+
return path90.join(cwd, FINDINGS_REL);
|
|
69726
|
+
}
|
|
69727
|
+
function appendFindings(cwd, findings) {
|
|
69728
|
+
if (evolutionMode() === "0") {
|
|
69729
|
+
return { written: false, reason: `${EVOLUTION_ENV} != shadow \u2014 findings write skipped` };
|
|
69730
|
+
}
|
|
69731
|
+
if (findings.length === 0) {
|
|
69732
|
+
return { written: false, reason: "no findings" };
|
|
69733
|
+
}
|
|
69734
|
+
try {
|
|
69735
|
+
const file2 = findingsPath(cwd);
|
|
69736
|
+
mkdirSync22(path90.dirname(file2), { recursive: true });
|
|
69737
|
+
appendFileSync4(file2, `${findings.map((f) => JSON.stringify(f)).join("\n")}
|
|
69738
|
+
`, "utf8");
|
|
69739
|
+
return { written: true, path: file2 };
|
|
69740
|
+
} catch (err) {
|
|
69741
|
+
return {
|
|
69742
|
+
written: false,
|
|
69743
|
+
reason: `findings append failed (fail-open): ${err instanceof Error ? err.message : String(err)}`
|
|
69744
|
+
};
|
|
69745
|
+
}
|
|
69746
|
+
}
|
|
69747
|
+
function readFindings(cwd) {
|
|
69748
|
+
const file2 = findingsPath(cwd);
|
|
69749
|
+
if (!existsSync59(file2)) return [];
|
|
69750
|
+
let raw;
|
|
69751
|
+
try {
|
|
69752
|
+
raw = readFileSync48(file2, "utf8");
|
|
69753
|
+
} catch {
|
|
69754
|
+
return [];
|
|
69755
|
+
}
|
|
69756
|
+
const out = [];
|
|
69757
|
+
for (const line of raw.split("\n")) {
|
|
69758
|
+
const trimmed = line.trim();
|
|
69759
|
+
if (!trimmed) continue;
|
|
69760
|
+
try {
|
|
69761
|
+
const parsed = JSON.parse(trimmed);
|
|
69762
|
+
if (parsed && typeof parsed === "object" && typeof parsed.kind === "string") {
|
|
69763
|
+
out.push(parsed);
|
|
69764
|
+
}
|
|
69765
|
+
} catch {
|
|
69766
|
+
}
|
|
69767
|
+
}
|
|
69768
|
+
return out;
|
|
69769
|
+
}
|
|
69432
69770
|
function evolutionMode(env = process.env) {
|
|
69433
69771
|
return env[EVOLUTION_ENV] === "shadow" ? "shadow" : "0";
|
|
69434
69772
|
}
|
|
69435
69773
|
function ledgerPath(cwd) {
|
|
69436
|
-
return
|
|
69774
|
+
return path90.join(cwd, LEDGER_REL);
|
|
69437
69775
|
}
|
|
69438
69776
|
function honestyFromVerificationResults(results) {
|
|
69439
69777
|
if (!results) return void 0;
|
|
@@ -69448,7 +69786,7 @@ function appendLedgerEntry(cwd, entry) {
|
|
|
69448
69786
|
}
|
|
69449
69787
|
try {
|
|
69450
69788
|
const file2 = ledgerPath(cwd);
|
|
69451
|
-
mkdirSync22(
|
|
69789
|
+
mkdirSync22(path90.dirname(file2), { recursive: true });
|
|
69452
69790
|
appendFileSync4(file2, `${JSON.stringify(entry)}
|
|
69453
69791
|
`, "utf8");
|
|
69454
69792
|
return { written: true, path: file2 };
|
|
@@ -69559,12 +69897,23 @@ function ledgerStats(entries) {
|
|
|
69559
69897
|
byClassFitness
|
|
69560
69898
|
};
|
|
69561
69899
|
}
|
|
69562
|
-
var EVOLUTION_ENV, LEDGER_REL, HONESTY_CHECK_PREFIX, TIER_WEIGHTS, UNTIERED_WEIGHT;
|
|
69900
|
+
var EVOLUTION_ENV, LEDGER_REL, FINDINGS_REL, EVOLUTION_PATHS, HONESTY_CHECK_PREFIX, TIER_WEIGHTS, UNTIERED_WEIGHT;
|
|
69563
69901
|
var init_ledger = __esm({
|
|
69564
69902
|
"src/cli/evolution/ledger.ts"() {
|
|
69565
69903
|
"use strict";
|
|
69566
69904
|
EVOLUTION_ENV = "ZELARI_EVOLUTION";
|
|
69567
|
-
LEDGER_REL =
|
|
69905
|
+
LEDGER_REL = path90.join(".zelari", "evolution", "ledger.jsonl");
|
|
69906
|
+
FINDINGS_REL = path90.join(".zelari", "evolution", "findings.jsonl");
|
|
69907
|
+
EVOLUTION_PATHS = {
|
|
69908
|
+
/** Outcome ledger (ADR-0036) — one JSON object per run. */
|
|
69909
|
+
ledger: LEDGER_REL,
|
|
69910
|
+
/** Instance-level findings ledger — the input to the pattern ledger (S1). */
|
|
69911
|
+
findings: FINDINGS_REL,
|
|
69912
|
+
/** Proposals store — owned by tools/eval evolvePropose (read-only here). */
|
|
69913
|
+
proposals: path90.join(".zelari", "evolution", "proposals.jsonl"),
|
|
69914
|
+
/** Failure-pattern clusters — derived, append-only (S1). */
|
|
69915
|
+
patternLedger: path90.join(".zelari", "evolution", "pattern-ledger.jsonl")
|
|
69916
|
+
};
|
|
69568
69917
|
HONESTY_CHECK_PREFIX = "synthesis.";
|
|
69569
69918
|
TIER_WEIGHTS = {
|
|
69570
69919
|
build: 1,
|
|
@@ -69706,8 +70055,8 @@ __export(fileBackend_exports, {
|
|
|
69706
70055
|
isMemoryEnabled: () => isMemoryEnabled
|
|
69707
70056
|
});
|
|
69708
70057
|
import { randomUUID as randomUUID7 } from "node:crypto";
|
|
69709
|
-
import { promises as
|
|
69710
|
-
import * as
|
|
70058
|
+
import { promises as fs36 } from "node:fs";
|
|
70059
|
+
import * as path91 from "node:path";
|
|
69711
70060
|
function tokenize2(text) {
|
|
69712
70061
|
return text.toLowerCase().split(/[^\p{L}\p{N}]+/u).filter((t) => t.length >= 3);
|
|
69713
70062
|
}
|
|
@@ -69760,9 +70109,9 @@ var init_fileBackend = __esm({
|
|
|
69760
70109
|
logPath = "";
|
|
69761
70110
|
memoryDir = "";
|
|
69762
70111
|
async init(projectRoot) {
|
|
69763
|
-
this.memoryDir =
|
|
69764
|
-
this.logPath =
|
|
69765
|
-
await
|
|
70112
|
+
this.memoryDir = path91.join(projectRoot, ".zelari", "memory");
|
|
70113
|
+
this.logPath = path91.join(this.memoryDir, "log.jsonl");
|
|
70114
|
+
await fs36.mkdir(this.memoryDir, { recursive: true });
|
|
69766
70115
|
}
|
|
69767
70116
|
async add(content, metadata2 = {}, graph) {
|
|
69768
70117
|
const fact = {
|
|
@@ -69772,7 +70121,7 @@ var init_fileBackend = __esm({
|
|
|
69772
70121
|
...graph ? { graph } : {},
|
|
69773
70122
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
69774
70123
|
};
|
|
69775
|
-
await
|
|
70124
|
+
await fs36.appendFile(this.logPath, JSON.stringify(fact) + "\n", "utf8");
|
|
69776
70125
|
return fact.id;
|
|
69777
70126
|
}
|
|
69778
70127
|
async search(query, options = {}) {
|
|
@@ -69800,7 +70149,7 @@ var init_fileBackend = __esm({
|
|
|
69800
70149
|
async readAll() {
|
|
69801
70150
|
let raw;
|
|
69802
70151
|
try {
|
|
69803
|
-
raw = await
|
|
70152
|
+
raw = await fs36.readFile(this.logPath, "utf8");
|
|
69804
70153
|
} catch {
|
|
69805
70154
|
return [];
|
|
69806
70155
|
}
|
|
@@ -69833,23 +70182,23 @@ var init_fileBackend = __esm({
|
|
|
69833
70182
|
});
|
|
69834
70183
|
|
|
69835
70184
|
// src/cli/traceStore.ts
|
|
69836
|
-
import { promises as
|
|
69837
|
-
import * as
|
|
70185
|
+
import { promises as fs37 } from "node:fs";
|
|
70186
|
+
import * as path92 from "node:path";
|
|
69838
70187
|
function traceDir(projectRoot) {
|
|
69839
|
-
return
|
|
70188
|
+
return path92.join(projectRoot, ".zelari", "trace");
|
|
69840
70189
|
}
|
|
69841
70190
|
function tracePath(projectRoot, missionId) {
|
|
69842
|
-
return
|
|
70191
|
+
return path92.join(traceDir(projectRoot), `${missionId}.json`);
|
|
69843
70192
|
}
|
|
69844
70193
|
async function saveTrace(projectRoot, missionId, entries) {
|
|
69845
70194
|
const dir = traceDir(projectRoot);
|
|
69846
|
-
await
|
|
70195
|
+
await fs37.mkdir(dir, { recursive: true });
|
|
69847
70196
|
const payload = {
|
|
69848
70197
|
missionId,
|
|
69849
70198
|
ts: Date.now(),
|
|
69850
70199
|
entries
|
|
69851
70200
|
};
|
|
69852
|
-
await
|
|
70201
|
+
await fs37.writeFile(
|
|
69853
70202
|
tracePath(projectRoot, missionId),
|
|
69854
70203
|
JSON.stringify(payload, null, 2) + "\n",
|
|
69855
70204
|
"utf8"
|
|
@@ -69880,8 +70229,8 @@ __export(zelariMission_exports, {
|
|
|
69880
70229
|
runZelariMission: () => runZelariMission
|
|
69881
70230
|
});
|
|
69882
70231
|
import { randomUUID as randomUUID8 } from "node:crypto";
|
|
69883
|
-
import { promises as
|
|
69884
|
-
import * as
|
|
70232
|
+
import { promises as fs38 } from "node:fs";
|
|
70233
|
+
import * as path93 from "node:path";
|
|
69885
70234
|
function resolveMaxIterations(env = process.env) {
|
|
69886
70235
|
const raw = env.ZELARI_MISSION_MAX_ITER;
|
|
69887
70236
|
const n = raw ? Number.parseInt(raw, 10) : DEFAULT_MAX_ITER;
|
|
@@ -69924,10 +70273,10 @@ function isMissionAutoStart(env = process.env) {
|
|
|
69924
70273
|
return env.ZELARI_MISSION_AUTO === "1";
|
|
69925
70274
|
}
|
|
69926
70275
|
async function writeMissionState(projectRoot, state3) {
|
|
69927
|
-
const dir =
|
|
69928
|
-
await
|
|
69929
|
-
await
|
|
69930
|
-
|
|
70276
|
+
const dir = path93.join(projectRoot, ".zelari");
|
|
70277
|
+
await fs38.mkdir(dir, { recursive: true });
|
|
70278
|
+
await fs38.writeFile(
|
|
70279
|
+
path93.join(dir, "mission-state.json"),
|
|
69931
70280
|
JSON.stringify(state3, null, 2) + "\n",
|
|
69932
70281
|
"utf8"
|
|
69933
70282
|
);
|
|
@@ -69940,8 +70289,8 @@ async function writeMissionState(projectRoot, state3) {
|
|
|
69940
70289
|
}
|
|
69941
70290
|
async function loadMissionState(projectRoot) {
|
|
69942
70291
|
try {
|
|
69943
|
-
const raw = await
|
|
69944
|
-
|
|
70292
|
+
const raw = await fs38.readFile(
|
|
70293
|
+
path93.join(projectRoot, ".zelari", "mission-state.json"),
|
|
69945
70294
|
"utf8"
|
|
69946
70295
|
);
|
|
69947
70296
|
const parsed = JSON.parse(raw);
|
|
@@ -70700,7 +71049,7 @@ function safeSocketPath(socketPath) {
|
|
|
70700
71049
|
return socketPath.trim();
|
|
70701
71050
|
}
|
|
70702
71051
|
function startPermissionBroker(socketPath, handlers, opts) {
|
|
70703
|
-
const
|
|
71052
|
+
const path128 = safeSocketPath(socketPath);
|
|
70704
71053
|
const requestTimeoutMs = opts?.requestTimeoutMs ?? PERMISSION_BROKER_DEFAULT_TIMEOUT_MS;
|
|
70705
71054
|
const sockets = /* @__PURE__ */ new Set();
|
|
70706
71055
|
const server = createServer2((socket) => {
|
|
@@ -70800,10 +71149,10 @@ function startPermissionBroker(socketPath, handlers, opts) {
|
|
|
70800
71149
|
return new Promise((resolve11, reject) => {
|
|
70801
71150
|
const onError = (err) => reject(err);
|
|
70802
71151
|
server.once("error", onError);
|
|
70803
|
-
server.listen(
|
|
71152
|
+
server.listen(path128, () => {
|
|
70804
71153
|
server.removeListener("error", onError);
|
|
70805
71154
|
resolve11({
|
|
70806
|
-
socketPath:
|
|
71155
|
+
socketPath: path128,
|
|
70807
71156
|
stop: () => new Promise((res) => {
|
|
70808
71157
|
for (const s of sockets) s.destroy();
|
|
70809
71158
|
sockets.clear();
|
|
@@ -70814,7 +71163,7 @@ function startPermissionBroker(socketPath, handlers, opts) {
|
|
|
70814
71163
|
if (done) return;
|
|
70815
71164
|
done = true;
|
|
70816
71165
|
if (process.platform !== "win32") {
|
|
70817
|
-
unlink(
|
|
71166
|
+
unlink(path128, () => res());
|
|
70818
71167
|
} else {
|
|
70819
71168
|
res();
|
|
70820
71169
|
}
|
|
@@ -70827,11 +71176,11 @@ function startPermissionBroker(socketPath, handlers, opts) {
|
|
|
70827
71176
|
});
|
|
70828
71177
|
}
|
|
70829
71178
|
function requestBrokerAsk(socketPath, ask, opts) {
|
|
70830
|
-
const
|
|
71179
|
+
const path128 = safeSocketPath(socketPath);
|
|
70831
71180
|
const requestTimeoutMs = opts?.requestTimeoutMs ?? PERMISSION_BROKER_DEFAULT_TIMEOUT_MS;
|
|
70832
71181
|
const connectTimeoutMs = opts?.connectTimeoutMs ?? PERMISSION_BROKER_DEFAULT_CONNECT_TIMEOUT_MS;
|
|
70833
71182
|
return new Promise((resolve11, reject) => {
|
|
70834
|
-
const socket = connect(
|
|
71183
|
+
const socket = connect(path128);
|
|
70835
71184
|
let buffer = "";
|
|
70836
71185
|
let settled = false;
|
|
70837
71186
|
const settle = (fn) => {
|
|
@@ -70846,7 +71195,7 @@ function requestBrokerAsk(socketPath, ask, opts) {
|
|
|
70846
71195
|
settle(
|
|
70847
71196
|
() => reject(
|
|
70848
71197
|
new Error(
|
|
70849
|
-
`permission broker unavailable at "${
|
|
71198
|
+
`permission broker unavailable at "${path128}" (connect timed out after ${connectTimeoutMs}ms)`
|
|
70850
71199
|
)
|
|
70851
71200
|
)
|
|
70852
71201
|
);
|
|
@@ -72087,7 +72436,7 @@ var init_prereqChecks = __esm({
|
|
|
72087
72436
|
|
|
72088
72437
|
// src/cli/plugins/prefs.ts
|
|
72089
72438
|
import { existsSync as existsSync63, readFileSync as readFileSync51, writeFileSync as writeFileSync26, mkdirSync as mkdirSync23 } from "node:fs";
|
|
72090
|
-
import
|
|
72439
|
+
import path100 from "node:path";
|
|
72091
72440
|
function getPluginPrefsPath() {
|
|
72092
72441
|
return pluginsPrefsPath();
|
|
72093
72442
|
}
|
|
@@ -72110,7 +72459,7 @@ function getPluginPrefs() {
|
|
|
72110
72459
|
}
|
|
72111
72460
|
function writePluginPrefs(prefs) {
|
|
72112
72461
|
const file2 = getPluginPrefsPath();
|
|
72113
|
-
mkdirSync23(
|
|
72462
|
+
mkdirSync23(path100.dirname(file2), { recursive: true });
|
|
72114
72463
|
writeFileSync26(file2, JSON.stringify(prefs, null, 2), {
|
|
72115
72464
|
encoding: "utf-8",
|
|
72116
72465
|
mode: 384
|
|
@@ -72148,7 +72497,7 @@ __export(registry_exports, {
|
|
|
72148
72497
|
isBinaryOnPath: () => isBinaryOnPath
|
|
72149
72498
|
});
|
|
72150
72499
|
import { existsSync as existsSync64 } from "node:fs";
|
|
72151
|
-
import
|
|
72500
|
+
import path101 from "node:path";
|
|
72152
72501
|
function detectLocalBin(bin) {
|
|
72153
72502
|
return (cwd) => {
|
|
72154
72503
|
try {
|
|
@@ -72166,7 +72515,7 @@ function isBinaryOnPath(bin, opts = {}) {
|
|
|
72166
72515
|
const platform = opts.platform ?? process.platform;
|
|
72167
72516
|
const exists = opts.exists ?? existsSync64;
|
|
72168
72517
|
const pathEnv = opts.pathEnv ?? process.env.PATH ?? "";
|
|
72169
|
-
const pathMod = platform === "win32" ?
|
|
72518
|
+
const pathMod = platform === "win32" ? path101.win32 : path101.posix;
|
|
72170
72519
|
const sep5 = platform === "win32" ? ";" : ":";
|
|
72171
72520
|
const dirs = pathEnv.split(sep5).filter((d) => d.length > 0);
|
|
72172
72521
|
const candidates = [bin];
|
|
@@ -73305,11 +73654,11 @@ var init_policy = __esm({
|
|
|
73305
73654
|
});
|
|
73306
73655
|
|
|
73307
73656
|
// src/cli/orchestration/facts.ts
|
|
73308
|
-
import { promises as
|
|
73309
|
-
import
|
|
73657
|
+
import { promises as fs47 } from "node:fs";
|
|
73658
|
+
import path105 from "node:path";
|
|
73310
73659
|
async function collectRepoFileCount(root = process.cwd()) {
|
|
73311
73660
|
try {
|
|
73312
|
-
await
|
|
73661
|
+
await fs47.readdir(root);
|
|
73313
73662
|
} catch {
|
|
73314
73663
|
return void 0;
|
|
73315
73664
|
}
|
|
@@ -73320,13 +73669,13 @@ async function collectRepoFileCount(root = process.cwd()) {
|
|
|
73320
73669
|
const dir = queue.pop();
|
|
73321
73670
|
let entries;
|
|
73322
73671
|
try {
|
|
73323
|
-
entries = await
|
|
73672
|
+
entries = await fs47.readdir(dir, { withFileTypes: true });
|
|
73324
73673
|
} catch {
|
|
73325
73674
|
continue;
|
|
73326
73675
|
}
|
|
73327
73676
|
for (const e of entries) {
|
|
73328
73677
|
if (e.isDirectory()) {
|
|
73329
|
-
if (!SKIP_DIRS2.has(e.name)) queue.push(
|
|
73678
|
+
if (!SKIP_DIRS2.has(e.name)) queue.push(path105.join(dir, e.name));
|
|
73330
73679
|
} else if (e.isFile()) {
|
|
73331
73680
|
count++;
|
|
73332
73681
|
if (count > MAX_WALK_FILES) return count;
|
|
@@ -73424,7 +73773,7 @@ var init_streamScrub = __esm({
|
|
|
73424
73773
|
});
|
|
73425
73774
|
|
|
73426
73775
|
// src/cli/harnessState.ts
|
|
73427
|
-
import
|
|
73776
|
+
import path106 from "node:path";
|
|
73428
73777
|
function asString4(v) {
|
|
73429
73778
|
return typeof v === "string" ? v : "";
|
|
73430
73779
|
}
|
|
@@ -73599,7 +73948,7 @@ function contractFor(t) {
|
|
|
73599
73948
|
};
|
|
73600
73949
|
}
|
|
73601
73950
|
async function readHarnessState(sessionDir, cache5) {
|
|
73602
|
-
const report = await readSessionLogCached(
|
|
73951
|
+
const report = await readSessionLogCached(path106.join(sessionDir, "events.jsonl"), cache5);
|
|
73603
73952
|
return deriveHarnessState(report.events);
|
|
73604
73953
|
}
|
|
73605
73954
|
var init_harnessState = __esm({
|
|
@@ -73610,12 +73959,12 @@ var init_harnessState = __esm({
|
|
|
73610
73959
|
});
|
|
73611
73960
|
|
|
73612
73961
|
// src/cli/headless/harnessStateEmit.ts
|
|
73613
|
-
import
|
|
73962
|
+
import path107 from "node:path";
|
|
73614
73963
|
async function emitHarnessStateEvent(opts) {
|
|
73615
73964
|
if (opts.output !== "json") return;
|
|
73616
73965
|
try {
|
|
73617
73966
|
const sessionsDir2 = resolveSessionsDir({ workspaceRoot: opts.workspaceRoot });
|
|
73618
|
-
const state3 = await readHarnessState(
|
|
73967
|
+
const state3 = await readHarnessState(path107.join(sessionsDir2, opts.spine.sessionId));
|
|
73619
73968
|
opts.emitEvent({ type: "harness_state", ...state3 });
|
|
73620
73969
|
} catch (err) {
|
|
73621
73970
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -74154,13 +74503,13 @@ var init_verifierLifecycle = __esm({
|
|
|
74154
74503
|
|
|
74155
74504
|
// src/cli/extensions/sandboxedFs.ts
|
|
74156
74505
|
import { promises as fsp } from "node:fs";
|
|
74157
|
-
import
|
|
74506
|
+
import path108 from "node:path";
|
|
74158
74507
|
function errText(prefix, p3, err) {
|
|
74159
74508
|
const msg = err instanceof Error ? err.message : String(err);
|
|
74160
74509
|
return `[extension-fs] ${prefix} "${p3}": ${msg}`;
|
|
74161
74510
|
}
|
|
74162
74511
|
function bindSandboxedFs(root) {
|
|
74163
|
-
const resolvedRoot =
|
|
74512
|
+
const resolvedRoot = path108.resolve(root);
|
|
74164
74513
|
return {
|
|
74165
74514
|
root: resolvedRoot,
|
|
74166
74515
|
async readFile(relativePath) {
|
|
@@ -74176,7 +74525,7 @@ function bindSandboxedFs(root) {
|
|
|
74176
74525
|
try {
|
|
74177
74526
|
const target = resolveSandboxedPath(relativePath, { root: resolvedRoot });
|
|
74178
74527
|
verifyContainment(target, { root: resolvedRoot });
|
|
74179
|
-
await fsp.mkdir(
|
|
74528
|
+
await fsp.mkdir(path108.dirname(target), { recursive: true });
|
|
74180
74529
|
await fsp.writeFile(target, data, "utf8");
|
|
74181
74530
|
return typedOk({ path: target });
|
|
74182
74531
|
} catch (err) {
|
|
@@ -74203,15 +74552,15 @@ var init_sandboxedFs = __esm({
|
|
|
74203
74552
|
});
|
|
74204
74553
|
|
|
74205
74554
|
// src/cli/extensions/loader.ts
|
|
74206
|
-
import { join as
|
|
74555
|
+
import { join as join47 } from "node:path";
|
|
74207
74556
|
import { readdirSync as readdirSync14, readFileSync as readFileSync54 } from "node:fs";
|
|
74208
74557
|
import { createHash as createHash26 } from "node:crypto";
|
|
74209
74558
|
import { pathToFileURL as pathToFileURL3 } from "node:url";
|
|
74210
74559
|
function globalExtensionsDir() {
|
|
74211
|
-
return
|
|
74560
|
+
return join47(zelariHome(), "extensions");
|
|
74212
74561
|
}
|
|
74213
74562
|
function projectExtensionsDir(projectRoot) {
|
|
74214
|
-
return
|
|
74563
|
+
return join47(projectRoot, ".zelari", "extensions");
|
|
74215
74564
|
}
|
|
74216
74565
|
function sha256File(file2) {
|
|
74217
74566
|
return createHash26("sha256").update(readFileSync54(file2)).digest("hex");
|
|
@@ -74223,7 +74572,7 @@ function candidateFiles(dir) {
|
|
|
74223
74572
|
} catch {
|
|
74224
74573
|
return [];
|
|
74225
74574
|
}
|
|
74226
|
-
return names.filter((n) => EXTENSION_FILE_EXTS.has(n.slice(n.lastIndexOf(".")).toLowerCase())).sort().map((n) =>
|
|
74575
|
+
return names.filter((n) => EXTENSION_FILE_EXTS.has(n.slice(n.lastIndexOf(".")).toLowerCase())).sort().map((n) => join47(dir, n));
|
|
74227
74576
|
}
|
|
74228
74577
|
function extractExtension(mod) {
|
|
74229
74578
|
const m = mod;
|
|
@@ -74245,14 +74594,14 @@ async function loadExtensionsFromDirs(dirs, options = {}) {
|
|
|
74245
74594
|
skipped
|
|
74246
74595
|
};
|
|
74247
74596
|
const fsRoot = options.fsRoot ?? process.cwd();
|
|
74248
|
-
let
|
|
74597
|
+
let fs52 = null;
|
|
74249
74598
|
const pending = [];
|
|
74250
74599
|
for (const dir of dirs) {
|
|
74251
74600
|
const files = candidateFiles(dir.path);
|
|
74252
74601
|
if (files.length === 0) continue;
|
|
74253
74602
|
let lock = null;
|
|
74254
74603
|
try {
|
|
74255
|
-
lock = JSON.parse(readFileSync54(
|
|
74604
|
+
lock = JSON.parse(readFileSync54(join47(dir.path, EXTENSIONS_LOCK_FILE), "utf8"));
|
|
74256
74605
|
} catch {
|
|
74257
74606
|
lock = null;
|
|
74258
74607
|
if (dirHasLockFile(dir.path)) {
|
|
@@ -74300,9 +74649,9 @@ async function loadExtensionsFromDirs(dirs, options = {}) {
|
|
|
74300
74649
|
skipped.push(`${file2}: missing ZelariExtension export`);
|
|
74301
74650
|
continue;
|
|
74302
74651
|
}
|
|
74303
|
-
if (!
|
|
74652
|
+
if (!fs52) fs52 = bindSandboxedFs(fsRoot);
|
|
74304
74653
|
try {
|
|
74305
|
-
await runtime.registry.registerExtension(ext, { fs:
|
|
74654
|
+
await runtime.registry.registerExtension(ext, { fs: fs52 });
|
|
74306
74655
|
runtime.loaded.push({ id: ext.id, file: file2, scope });
|
|
74307
74656
|
} catch (err) {
|
|
74308
74657
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -74319,7 +74668,7 @@ function basenameOf(file2) {
|
|
|
74319
74668
|
}
|
|
74320
74669
|
function dirHasLockFile(dir) {
|
|
74321
74670
|
try {
|
|
74322
|
-
readFileSync54(
|
|
74671
|
+
readFileSync54(join47(dir, EXTENSIONS_LOCK_FILE));
|
|
74323
74672
|
return true;
|
|
74324
74673
|
} catch {
|
|
74325
74674
|
return false;
|
|
@@ -74360,8 +74709,8 @@ var init_loader = __esm({
|
|
|
74360
74709
|
});
|
|
74361
74710
|
|
|
74362
74711
|
// src/cli/headless/runOneTurn.ts
|
|
74363
|
-
import { promises as
|
|
74364
|
-
import
|
|
74712
|
+
import { promises as fs48 } from "node:fs";
|
|
74713
|
+
import path109 from "node:path";
|
|
74365
74714
|
function planModeFromOpts(opts) {
|
|
74366
74715
|
return (opts.phase ?? "build") === "plan";
|
|
74367
74716
|
}
|
|
@@ -74683,10 +75032,16 @@ async function runOneTurn(opts, provider, model, providerStream, extras) {
|
|
|
74683
75032
|
wireSplit = { stable: systemMessages[0].content, volatile: "" };
|
|
74684
75033
|
}
|
|
74685
75034
|
await spine.beginResourceTurn();
|
|
75035
|
+
const onePager = await buildOnePager({
|
|
75036
|
+
cwd,
|
|
75037
|
+
memory: nativeMemory ?? null,
|
|
75038
|
+
skipCompactRecap: true
|
|
75039
|
+
});
|
|
74686
75040
|
const modelContext = await buildModelContext({
|
|
74687
75041
|
fallbackHistory: seededHistory.history,
|
|
74688
75042
|
session: spine.spine,
|
|
74689
75043
|
resourceSnapshot: spine.spine.latestResourceSnapshot(),
|
|
75044
|
+
volatileOnePager: onePager,
|
|
74690
75045
|
phase: opts.phase ?? "build",
|
|
74691
75046
|
model,
|
|
74692
75047
|
provider,
|
|
@@ -74735,7 +75090,10 @@ async function runOneTurn(opts, provider, model, providerStream, extras) {
|
|
|
74735
75090
|
cwd,
|
|
74736
75091
|
providerStream,
|
|
74737
75092
|
buildLiveness: { mutationRequired: wantWrites, maxRecoveries: 2 },
|
|
74738
|
-
requestTail: () =>
|
|
75093
|
+
requestTail: () => [
|
|
75094
|
+
...resourceStatusTail(spine.spine.latestResourceSnapshot()),
|
|
75095
|
+
...onePager
|
|
75096
|
+
],
|
|
74739
75097
|
// 2.6 Phase 3: host-owned pre-dispatch resource gate (doc section 11.3).
|
|
74740
75098
|
// Advisory by default; ZELARI_RESOURCE_ENFORCEMENT=protected enables the
|
|
74741
75099
|
// protected verification reserve. Degrade-and-stop (null gate = allow).
|
|
@@ -74991,8 +75349,8 @@ async function runOneTurn(opts, provider, model, providerStream, extras) {
|
|
|
74991
75349
|
if (json3) {
|
|
74992
75350
|
if (opts.exportSessionPath === "-") process.stdout.write(json3 + "\n");
|
|
74993
75351
|
else {
|
|
74994
|
-
await
|
|
74995
|
-
await
|
|
75352
|
+
await fs48.mkdir(path109.dirname(opts.exportSessionPath), { recursive: true }).catch(() => void 0);
|
|
75353
|
+
await fs48.writeFile(opts.exportSessionPath, json3, "utf8");
|
|
74996
75354
|
}
|
|
74997
75355
|
}
|
|
74998
75356
|
} catch {
|
|
@@ -75065,6 +75423,7 @@ var init_runOneTurn = __esm({
|
|
|
75065
75423
|
init_nativeVerification();
|
|
75066
75424
|
init_verifierLifecycle();
|
|
75067
75425
|
init_modelContextBuilder();
|
|
75426
|
+
init_onePager();
|
|
75068
75427
|
init_metrics3();
|
|
75069
75428
|
init_messageUsage();
|
|
75070
75429
|
init_headlessSpine();
|
|
@@ -75968,6 +76327,150 @@ var init_run = __esm({
|
|
|
75968
76327
|
}
|
|
75969
76328
|
});
|
|
75970
76329
|
|
|
76330
|
+
// src/cli/evolution/patternLedger.ts
|
|
76331
|
+
var patternLedger_exports = {};
|
|
76332
|
+
__export(patternLedger_exports, {
|
|
76333
|
+
DEFAULT_MIN_DISTINCT_TASKS: () => DEFAULT_MIN_DISTINCT_TASKS,
|
|
76334
|
+
PATTERN_LEDGER_REL: () => PATTERN_LEDGER_REL,
|
|
76335
|
+
appendClusters: () => appendClusters,
|
|
76336
|
+
categorizeCluster: () => categorizeCluster,
|
|
76337
|
+
clusterFailures: () => clusterFailures,
|
|
76338
|
+
clusterKeyFor: () => clusterKeyFor,
|
|
76339
|
+
makeTaskKey: () => makeTaskKey,
|
|
76340
|
+
patternLedgerPath: () => patternLedgerPath,
|
|
76341
|
+
readClusters: () => readClusters
|
|
76342
|
+
});
|
|
76343
|
+
import { createHash as createHash27 } from "node:crypto";
|
|
76344
|
+
import { appendFileSync as appendFileSync6, existsSync as existsSync69, mkdirSync as mkdirSync26, readFileSync as readFileSync55 } from "node:fs";
|
|
76345
|
+
import path110 from "node:path";
|
|
76346
|
+
function nonEmpty2(v) {
|
|
76347
|
+
return typeof v === "string" && v.trim() !== "" ? v : void 0;
|
|
76348
|
+
}
|
|
76349
|
+
function makeTaskKey(input) {
|
|
76350
|
+
const mission = input.missionTaskId?.trim();
|
|
76351
|
+
if (mission) return mission;
|
|
76352
|
+
const normalized = (input.taskText ?? "").trim().replace(/\s+/g, " ").toLowerCase();
|
|
76353
|
+
if (normalized) return createHash27("sha256").update(normalized).digest("hex").slice(0, 12);
|
|
76354
|
+
return input.sessionId;
|
|
76355
|
+
}
|
|
76356
|
+
function clusterKeyFor(input) {
|
|
76357
|
+
const tool = nonEmpty2(input.tool) ?? "unknown";
|
|
76358
|
+
const errorClass = nonEmpty2(input.errorClass) ?? "unknown";
|
|
76359
|
+
const termination = nonEmpty2(input.termination) ?? nonEmpty2(input.kind) ?? "unknown";
|
|
76360
|
+
return `${tool}|${errorClass}|${termination}`;
|
|
76361
|
+
}
|
|
76362
|
+
function categorizeCluster(input) {
|
|
76363
|
+
const operator = nonEmpty2(input.operator) ?? "";
|
|
76364
|
+
const haystack = `${input.kind ?? ""} ${operator} ${input.patchHint ?? ""}`.toLowerCase();
|
|
76365
|
+
const touchesHarness = /tool|verif|observ|compact|resource|budget|boundary|interrupt|loop|context/.test(haystack);
|
|
76366
|
+
if (operator === "revise_skill" && !touchesHarness) return "model-accommodation";
|
|
76367
|
+
return "harness-repair";
|
|
76368
|
+
}
|
|
76369
|
+
function deriveTool(f) {
|
|
76370
|
+
const ev = f.evidence ?? {};
|
|
76371
|
+
const explicit = nonEmpty2(ev.toolName) ?? nonEmpty2(ev.tool);
|
|
76372
|
+
if (explicit) return explicit;
|
|
76373
|
+
const signal = nonEmpty2(f.signal);
|
|
76374
|
+
return signal && signal.includes(":") ? signal.slice(0, signal.indexOf(":")) : "unknown";
|
|
76375
|
+
}
|
|
76376
|
+
function clusterFailures(findings, opts) {
|
|
76377
|
+
const minDistinct = Math.max(1, Math.floor(opts?.minDistinctTasks ?? DEFAULT_MIN_DISTINCT_TASKS));
|
|
76378
|
+
const buckets = /* @__PURE__ */ new Map();
|
|
76379
|
+
let unmapped = 0;
|
|
76380
|
+
for (const f of findings) {
|
|
76381
|
+
const sessions = f.sessions ?? [];
|
|
76382
|
+
const taskKey = nonEmpty2(f.taskKey) ?? nonEmpty2(sessions[0]);
|
|
76383
|
+
if (!taskKey) {
|
|
76384
|
+
unmapped += 1;
|
|
76385
|
+
continue;
|
|
76386
|
+
}
|
|
76387
|
+
const tool = deriveTool(f);
|
|
76388
|
+
const errorClass = nonEmpty2(f.evidence?.errorClass) ?? "unknown";
|
|
76389
|
+
const termination = nonEmpty2(f.evidence?.termination) ?? nonEmpty2(f.kind) ?? "unknown";
|
|
76390
|
+
const key = clusterKeyFor({ tool, errorClass, termination, kind: f.kind });
|
|
76391
|
+
let b = buckets.get(key);
|
|
76392
|
+
if (!b) {
|
|
76393
|
+
b = { tool, errorClass, termination, count: 0, findings: 0, sessions: /* @__PURE__ */ new Set(), taskKeys: /* @__PURE__ */ new Set(), taskClasses: /* @__PURE__ */ new Set() };
|
|
76394
|
+
buckets.set(key, b);
|
|
76395
|
+
}
|
|
76396
|
+
b.findings += 1;
|
|
76397
|
+
b.count += typeof f.count === "number" ? f.count : 1;
|
|
76398
|
+
for (const s of sessions) b.sessions.add(s);
|
|
76399
|
+
b.taskKeys.add(taskKey);
|
|
76400
|
+
if (!b.operator) b.operator = nonEmpty2(f.operator);
|
|
76401
|
+
if (!b.patchHint) b.patchHint = nonEmpty2(f.surface);
|
|
76402
|
+
const taskClass = nonEmpty2(f.taskClass);
|
|
76403
|
+
if (taskClass) b.taskClasses.add(taskClass);
|
|
76404
|
+
if (f.firstAt && (!b.firstAt || f.firstAt < b.firstAt)) b.firstAt = f.firstAt;
|
|
76405
|
+
if (f.lastAt && (!b.lastAt || f.lastAt > b.lastAt)) b.lastAt = f.lastAt;
|
|
76406
|
+
}
|
|
76407
|
+
const clusters = [];
|
|
76408
|
+
for (const [key, b] of [...buckets.entries()].sort(([a], [c]) => a < c ? -1 : a > c ? 1 : 0)) {
|
|
76409
|
+
if (b.taskKeys.size < minDistinct) {
|
|
76410
|
+
unmapped += b.findings;
|
|
76411
|
+
continue;
|
|
76412
|
+
}
|
|
76413
|
+
clusters.push({
|
|
76414
|
+
id: `c-${String(clusters.length + 1).padStart(4, "0")}`,
|
|
76415
|
+
key,
|
|
76416
|
+
category: categorizeCluster({ kind: b.termination, operator: b.operator, patchHint: b.patchHint ?? key }),
|
|
76417
|
+
tool: b.tool,
|
|
76418
|
+
errorClass: b.errorClass,
|
|
76419
|
+
termination: b.termination,
|
|
76420
|
+
count: b.count,
|
|
76421
|
+
sessions: [...b.sessions].sort(),
|
|
76422
|
+
taskKeys: [...b.taskKeys].sort(),
|
|
76423
|
+
distinctTasks: b.taskKeys.size,
|
|
76424
|
+
taskClasses: [...b.taskClasses].sort(),
|
|
76425
|
+
firstAt: b.firstAt ?? "",
|
|
76426
|
+
lastAt: b.lastAt ?? ""
|
|
76427
|
+
});
|
|
76428
|
+
}
|
|
76429
|
+
return { clusters, unmapped };
|
|
76430
|
+
}
|
|
76431
|
+
function patternLedgerPath(cwd = process.cwd()) {
|
|
76432
|
+
return path110.join(cwd, PATTERN_LEDGER_REL);
|
|
76433
|
+
}
|
|
76434
|
+
async function appendClusters(clusters, cwd = process.cwd()) {
|
|
76435
|
+
if (clusters.length === 0) return;
|
|
76436
|
+
try {
|
|
76437
|
+
const file2 = patternLedgerPath(cwd);
|
|
76438
|
+
mkdirSync26(path110.dirname(file2), { recursive: true });
|
|
76439
|
+
appendFileSync6(file2, `${clusters.map((c) => JSON.stringify(c)).join("\n")}
|
|
76440
|
+
`, "utf8");
|
|
76441
|
+
} catch {
|
|
76442
|
+
}
|
|
76443
|
+
}
|
|
76444
|
+
async function readClusters(cwd = process.cwd()) {
|
|
76445
|
+
const file2 = patternLedgerPath(cwd);
|
|
76446
|
+
if (!existsSync69(file2)) return [];
|
|
76447
|
+
let raw;
|
|
76448
|
+
try {
|
|
76449
|
+
raw = readFileSync55(file2, "utf8");
|
|
76450
|
+
} catch {
|
|
76451
|
+
return [];
|
|
76452
|
+
}
|
|
76453
|
+
const out = [];
|
|
76454
|
+
for (const line of raw.split("\n")) {
|
|
76455
|
+
const trimmed = line.trim();
|
|
76456
|
+
if (!trimmed) continue;
|
|
76457
|
+
try {
|
|
76458
|
+
const parsed = JSON.parse(trimmed);
|
|
76459
|
+
if (parsed && typeof parsed === "object" && typeof parsed.key === "string") out.push(parsed);
|
|
76460
|
+
} catch {
|
|
76461
|
+
}
|
|
76462
|
+
}
|
|
76463
|
+
return out;
|
|
76464
|
+
}
|
|
76465
|
+
var PATTERN_LEDGER_REL, DEFAULT_MIN_DISTINCT_TASKS;
|
|
76466
|
+
var init_patternLedger = __esm({
|
|
76467
|
+
"src/cli/evolution/patternLedger.ts"() {
|
|
76468
|
+
"use strict";
|
|
76469
|
+
PATTERN_LEDGER_REL = path110.join(".zelari", "evolution", "pattern-ledger.jsonl");
|
|
76470
|
+
DEFAULT_MIN_DISTINCT_TASKS = 2;
|
|
76471
|
+
}
|
|
76472
|
+
});
|
|
76473
|
+
|
|
75971
76474
|
// src/cli/evolution/runTelemetry.ts
|
|
75972
76475
|
var runTelemetry_exports = {};
|
|
75973
76476
|
__export(runTelemetry_exports, {
|
|
@@ -76045,10 +76548,10 @@ __export(triggerLock_exports, {
|
|
|
76045
76548
|
lockPath: () => lockPath,
|
|
76046
76549
|
releaseLock: () => releaseLock
|
|
76047
76550
|
});
|
|
76048
|
-
import { promises as
|
|
76049
|
-
import * as
|
|
76551
|
+
import { promises as fs49 } from "node:fs";
|
|
76552
|
+
import * as path111 from "node:path";
|
|
76050
76553
|
function lockPath(projectRoot) {
|
|
76051
|
-
return
|
|
76554
|
+
return path111.join(projectRoot, ".zelari", "trigger.lock");
|
|
76052
76555
|
}
|
|
76053
76556
|
function isPidAlive(pid) {
|
|
76054
76557
|
try {
|
|
@@ -76061,10 +76564,10 @@ function isPidAlive(pid) {
|
|
|
76061
76564
|
}
|
|
76062
76565
|
async function acquireLock(projectRoot, now = () => /* @__PURE__ */ new Date()) {
|
|
76063
76566
|
const lp = lockPath(projectRoot);
|
|
76064
|
-
const dir =
|
|
76065
|
-
await
|
|
76567
|
+
const dir = path111.dirname(lp);
|
|
76568
|
+
await fs49.mkdir(dir, { recursive: true });
|
|
76066
76569
|
try {
|
|
76067
|
-
const raw = await
|
|
76570
|
+
const raw = await fs49.readFile(lp, "utf8");
|
|
76068
76571
|
const existing = JSON.parse(raw);
|
|
76069
76572
|
if (existing.pid && isPidAlive(existing.pid)) {
|
|
76070
76573
|
return { acquired: false, heldBy: existing.pid, lockPath: lp };
|
|
@@ -76075,13 +76578,13 @@ async function acquireLock(projectRoot, now = () => /* @__PURE__ */ new Date())
|
|
|
76075
76578
|
pid: process.pid,
|
|
76076
76579
|
acquiredAt: now().toISOString()
|
|
76077
76580
|
};
|
|
76078
|
-
await
|
|
76581
|
+
await fs49.writeFile(lp, JSON.stringify(payload, null, 2) + "\n", "utf8");
|
|
76079
76582
|
return { acquired: true, lockPath: lp };
|
|
76080
76583
|
}
|
|
76081
76584
|
async function releaseLock(projectRoot) {
|
|
76082
76585
|
const lp = lockPath(projectRoot);
|
|
76083
76586
|
try {
|
|
76084
|
-
await
|
|
76587
|
+
await fs49.unlink(lp);
|
|
76085
76588
|
} catch {
|
|
76086
76589
|
}
|
|
76087
76590
|
}
|
|
@@ -76098,8 +76601,8 @@ __export(runHeadless_exports, {
|
|
|
76098
76601
|
dispatchHeadlessTurn: () => dispatchHeadlessTurn,
|
|
76099
76602
|
runHeadless: () => runHeadless
|
|
76100
76603
|
});
|
|
76101
|
-
import { promises as
|
|
76102
|
-
import
|
|
76604
|
+
import { promises as fs50 } from "node:fs";
|
|
76605
|
+
import path112 from "node:path";
|
|
76103
76606
|
import { randomUUID as randomUUID10 } from "node:crypto";
|
|
76104
76607
|
async function runHeadless(opts) {
|
|
76105
76608
|
resetTaskSpawnCount();
|
|
@@ -76386,11 +76889,11 @@ async function runHeadlessKrakenGraph(opts, provider, model, providerStream, ext
|
|
|
76386
76889
|
try {
|
|
76387
76890
|
let preflightGraph;
|
|
76388
76891
|
if (opts.runPlan && opts.runPlan.trim() !== "") {
|
|
76389
|
-
const planPath =
|
|
76892
|
+
const planPath = path112.join(cwd, ".zelari", "radio", `plan-${opts.runPlan}.json`);
|
|
76390
76893
|
log(`loading pre-flight plan: ${planPath}`);
|
|
76391
76894
|
let raw;
|
|
76392
76895
|
try {
|
|
76393
|
-
raw = await
|
|
76896
|
+
raw = await fs50.readFile(planPath, "utf8");
|
|
76394
76897
|
} catch (e) {
|
|
76395
76898
|
log(`plan file not found: ${planPath} (${e.message})`);
|
|
76396
76899
|
exitCode = 1;
|
|
@@ -76444,10 +76947,10 @@ async function runHeadlessKrakenGraph(opts, provider, model, providerStream, ext
|
|
|
76444
76947
|
log(formatKrakenGraphAscii2(graph));
|
|
76445
76948
|
if (opts.planOnly) {
|
|
76446
76949
|
const planId = randomUUID10();
|
|
76447
|
-
const planDir =
|
|
76448
|
-
const planPath =
|
|
76449
|
-
await
|
|
76450
|
-
await
|
|
76950
|
+
const planDir = path112.join(cwd, ".zelari", "radio");
|
|
76951
|
+
const planPath = path112.join(planDir, `plan-${planId}.json`);
|
|
76952
|
+
await fs50.mkdir(planDir, { recursive: true });
|
|
76953
|
+
await fs50.writeFile(
|
|
76451
76954
|
planPath,
|
|
76452
76955
|
JSON.stringify(
|
|
76453
76956
|
{ id: graph.id, nodes: [...graph.nodes.values()] },
|
|
@@ -76549,16 +77052,32 @@ ${formatKrakenGraphDigest2(
|
|
|
76549
77052
|
} catch {
|
|
76550
77053
|
}
|
|
76551
77054
|
try {
|
|
76552
|
-
const { appendLedgerEntry: appendLedgerEntry2, evolutionMode: evolutionMode2 } = await Promise.resolve().then(() => (init_ledger(), ledger_exports));
|
|
77055
|
+
const { appendLedgerEntry: appendLedgerEntry2, appendFindings: appendFindings2, evolutionMode: evolutionMode2 } = await Promise.resolve().then(() => (init_ledger(), ledger_exports));
|
|
76553
77056
|
const { classifyTask: classifyTask2 } = await Promise.resolve().then(() => (init_classifyTask(), classifyTask_exports));
|
|
77057
|
+
const { makeTaskKey: makeTaskKey2 } = await Promise.resolve().then(() => (init_patternLedger(), patternLedger_exports));
|
|
76554
77058
|
if (evolutionMode2() === "shadow") {
|
|
77059
|
+
const taskText = opts.task ?? "";
|
|
77060
|
+
const at = (/* @__PURE__ */ new Date()).toISOString();
|
|
77061
|
+
const taskClass = classifyTask2({ prompt: taskText }).taskClass;
|
|
76555
77062
|
appendLedgerEntry2(cwd, {
|
|
76556
77063
|
runId: spine.sessionId,
|
|
76557
|
-
at
|
|
77064
|
+
at,
|
|
76558
77065
|
mode: "shadow",
|
|
76559
|
-
taskClass
|
|
77066
|
+
taskClass,
|
|
76560
77067
|
verdict: exitCode === 0 ? "PASS" : exitCode === 3 ? "FAIL" : "UNKNOWN"
|
|
76561
77068
|
});
|
|
77069
|
+
appendFindings2(cwd, [{
|
|
77070
|
+
kind: "run-termination",
|
|
77071
|
+
operator: "needs_human_review",
|
|
77072
|
+
surface: "run:outcome",
|
|
77073
|
+
signal: exitCode === 0 ? "completed" : "failed",
|
|
77074
|
+
count: 1,
|
|
77075
|
+
sessions: [spine.sessionId],
|
|
77076
|
+
taskKey: makeTaskKey2({ taskText, sessionId: spine.sessionId }),
|
|
77077
|
+
taskClass,
|
|
77078
|
+
firstAt: at,
|
|
77079
|
+
evidence: { termination: exitCode === 0 ? "completed" : exitCode === 3 ? "not-converged" : "error" }
|
|
77080
|
+
}]);
|
|
76562
77081
|
}
|
|
76563
77082
|
} catch {
|
|
76564
77083
|
}
|
|
@@ -76692,9 +77211,15 @@ async function runHeadlessCouncilBody(opts, provider, model, providerStream, ext
|
|
|
76692
77211
|
parameters: tool.function.parameters
|
|
76693
77212
|
}));
|
|
76694
77213
|
await spine.beginResourceTurn();
|
|
77214
|
+
const onePager = await buildOnePager({
|
|
77215
|
+
cwd,
|
|
77216
|
+
memory: nativeMemory ?? null,
|
|
77217
|
+
skipCompactRecap: true
|
|
77218
|
+
});
|
|
76695
77219
|
const councilContext = await buildModelContext({
|
|
76696
77220
|
fallbackHistory: seededHistory.history,
|
|
76697
77221
|
session: spine.spine,
|
|
77222
|
+
volatileOnePager: onePager,
|
|
76698
77223
|
phase: councilRunMode === "design-phase" ? "plan" : "build",
|
|
76699
77224
|
model,
|
|
76700
77225
|
provider,
|
|
@@ -76829,14 +77354,17 @@ async function runHeadlessCouncilBody(opts, provider, model, providerStream, ext
|
|
|
76829
77354
|
} catch {
|
|
76830
77355
|
}
|
|
76831
77356
|
try {
|
|
76832
|
-
const { appendLedgerEntry: appendLedgerEntry2, evolutionMode: evolutionMode2 } = await Promise.resolve().then(() => (init_ledger(), ledger_exports));
|
|
77357
|
+
const { appendLedgerEntry: appendLedgerEntry2, appendFindings: appendFindings2, evolutionMode: evolutionMode2 } = await Promise.resolve().then(() => (init_ledger(), ledger_exports));
|
|
76833
77358
|
const { classifyTask: classifyTask2 } = await Promise.resolve().then(() => (init_classifyTask(), classifyTask_exports));
|
|
77359
|
+
const { makeTaskKey: makeTaskKey2 } = await Promise.resolve().then(() => (init_patternLedger(), patternLedger_exports));
|
|
76834
77360
|
if (evolutionMode2() === "shadow") {
|
|
77361
|
+
const taskClass = classifyTask2({ prompt: effectiveTask }).taskClass;
|
|
77362
|
+
const verdict = signal.aborted ? "UNKNOWN" : exitCode === 0 ? "PASS" : exitCode === 3 ? "FAIL" : "UNKNOWN";
|
|
76835
77363
|
appendLedgerEntry2(cwd, {
|
|
76836
77364
|
runId: spine.sessionId,
|
|
76837
77365
|
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
76838
77366
|
mode: "shadow",
|
|
76839
|
-
taskClass
|
|
77367
|
+
taskClass,
|
|
76840
77368
|
// Steal #1/#2 wiring: real efficiency + attribution fields — the
|
|
76841
77369
|
// ledger schema carried them since ADR-0036, this site never wrote them.
|
|
76842
77370
|
latencyMs: Date.now() - councilStartedAt,
|
|
@@ -76851,8 +77379,20 @@ async function runHeadlessCouncilBody(opts, provider, model, providerStream, ext
|
|
|
76851
77379
|
// post-council hook (no verification report in scope, see
|
|
76852
77380
|
// runHeadlessZelariBody for that path), so the key is omitted.
|
|
76853
77381
|
...telemetry.usage().usageReports > 0 ? { cacheHitTokens: telemetry.usage().cacheHitTokens } : {},
|
|
76854
|
-
verdict
|
|
77382
|
+
verdict
|
|
76855
77383
|
});
|
|
77384
|
+
appendFindings2(cwd, [{
|
|
77385
|
+
kind: "run-termination",
|
|
77386
|
+
operator: "needs_human_review",
|
|
77387
|
+
surface: "run:outcome",
|
|
77388
|
+
signal: verdict === "PASS" ? "completed" : "failed",
|
|
77389
|
+
count: 1,
|
|
77390
|
+
sessions: [spine.sessionId],
|
|
77391
|
+
taskKey: makeTaskKey2({ taskText: effectiveTask, sessionId: spine.sessionId }),
|
|
77392
|
+
taskClass,
|
|
77393
|
+
firstAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
77394
|
+
evidence: { termination: verdict === "PASS" ? "completed" : verdict === "FAIL" ? "not-converged" : "error" }
|
|
77395
|
+
}]);
|
|
76856
77396
|
}
|
|
76857
77397
|
} catch {
|
|
76858
77398
|
}
|
|
@@ -76863,8 +77403,8 @@ async function runHeadlessCouncilBody(opts, provider, model, providerStream, ext
|
|
|
76863
77403
|
if (json3) {
|
|
76864
77404
|
if (opts.exportSessionPath === "-") process.stdout.write(json3 + "\n");
|
|
76865
77405
|
else {
|
|
76866
|
-
await
|
|
76867
|
-
await
|
|
77406
|
+
await fs50.mkdir(path112.dirname(opts.exportSessionPath), { recursive: true }).catch(() => void 0);
|
|
77407
|
+
await fs50.writeFile(opts.exportSessionPath, json3, "utf8");
|
|
76868
77408
|
}
|
|
76869
77409
|
}
|
|
76870
77410
|
} catch {
|
|
@@ -76964,9 +77504,15 @@ async function runHeadlessZelariBody(opts, provider, model, providerStream, extr
|
|
|
76964
77504
|
parameters: tool.function.parameters
|
|
76965
77505
|
}));
|
|
76966
77506
|
await spine.beginResourceTurn();
|
|
77507
|
+
const onePager = await buildOnePager({
|
|
77508
|
+
cwd: projectRoot,
|
|
77509
|
+
memory: nativeMissionMemory ?? null,
|
|
77510
|
+
skipCompactRecap: true
|
|
77511
|
+
});
|
|
76967
77512
|
const missionContext = await buildModelContext({
|
|
76968
77513
|
fallbackHistory: seededHistory.history,
|
|
76969
77514
|
session: spine.spine,
|
|
77515
|
+
volatileOnePager: onePager,
|
|
76970
77516
|
phase: opts.phase ?? "build",
|
|
76971
77517
|
model,
|
|
76972
77518
|
provider,
|
|
@@ -77341,8 +77887,8 @@ ${ragContext}` : slicePrompt;
|
|
|
77341
77887
|
if (json3) {
|
|
77342
77888
|
if (opts.exportSessionPath === "-") process.stdout.write(json3 + "\n");
|
|
77343
77889
|
else {
|
|
77344
|
-
await
|
|
77345
|
-
await
|
|
77890
|
+
await fs50.mkdir(path112.dirname(opts.exportSessionPath), { recursive: true }).catch(() => void 0);
|
|
77891
|
+
await fs50.writeFile(opts.exportSessionPath, json3, "utf8");
|
|
77346
77892
|
}
|
|
77347
77893
|
}
|
|
77348
77894
|
} catch {
|
|
@@ -77374,6 +77920,7 @@ var init_runHeadless = __esm({
|
|
|
77374
77920
|
init_verificationBridge();
|
|
77375
77921
|
init_completionProofPersist();
|
|
77376
77922
|
init_modelContextBuilder();
|
|
77923
|
+
init_onePager();
|
|
77377
77924
|
init_metrics3();
|
|
77378
77925
|
init_headlessSpine();
|
|
77379
77926
|
init_harnessStateEmit();
|
|
@@ -77874,7 +78421,7 @@ var init_jsonApi = __esm({
|
|
|
77874
78421
|
});
|
|
77875
78422
|
|
|
77876
78423
|
// src/cli/memory/mcpAdapter.ts
|
|
77877
|
-
import * as
|
|
78424
|
+
import * as path113 from "node:path";
|
|
77878
78425
|
var id2, projectId, source, SearchSchema, AddSchema, LinkSchema, RetractSchema, MEMORY_MCP_TOOLS, MemoryMcpAdapter;
|
|
77879
78426
|
var init_mcpAdapter = __esm({
|
|
77880
78427
|
"src/cli/memory/mcpAdapter.ts"() {
|
|
@@ -77910,6 +78457,7 @@ var init_mcpAdapter = __esm({
|
|
|
77910
78457
|
confidence: external_exports.number().finite().min(0).max(1).optional(),
|
|
77911
78458
|
visibility: MemoryVisibilitySchema.default("private"),
|
|
77912
78459
|
tags: external_exports.array(external_exports.string().min(1).max(120)).max(64).optional(),
|
|
78460
|
+
relevant_when: external_exports.array(external_exports.string().min(1).max(120)).max(8).optional(),
|
|
77913
78461
|
source,
|
|
77914
78462
|
metadata: external_exports.record(external_exports.string(), external_exports.unknown()).optional()
|
|
77915
78463
|
}).strict();
|
|
@@ -77940,7 +78488,7 @@ var init_mcpAdapter = __esm({
|
|
|
77940
78488
|
{
|
|
77941
78489
|
name: "zelari_memory_add",
|
|
77942
78490
|
description: "Add a scoped memory. Secrets are scanned and source.client is enforced by the server.",
|
|
77943
|
-
inputSchema: { type: "object", properties: { project_id: { type: "string" }, kind: { type: "string" }, content: { type: "string", maxLength: 64e3 }, importance: { type: "number", minimum: 0, maximum: 1 }, confidence: { type: "number", minimum: 0, maximum: 1 }, visibility: { type: "string", enum: ["project", "private"], default: "private" }, tags: { type: "array", items: { type: "string" } }, source: { type: "object" }, metadata: { type: "object" } }, required: ["project_id", "kind", "content"] }
|
|
78491
|
+
inputSchema: { type: "object", properties: { project_id: { type: "string" }, kind: { type: "string" }, content: { type: "string", maxLength: 64e3 }, importance: { type: "number", minimum: 0, maximum: 1 }, confidence: { type: "number", minimum: 0, maximum: 1 }, visibility: { type: "string", enum: ["project", "private"], default: "private" }, tags: { type: "array", items: { type: "string" } }, relevant_when: { type: "array", items: { type: "string", maxLength: 120 }, maxItems: 8 }, source: { type: "object" }, metadata: { type: "object" } }, required: ["project_id", "kind", "content"] }
|
|
77944
78492
|
},
|
|
77945
78493
|
{
|
|
77946
78494
|
name: "zelari_memory_link",
|
|
@@ -78044,8 +78592,8 @@ var init_mcpAdapter = __esm({
|
|
|
78044
78592
|
this.takeWrite();
|
|
78045
78593
|
const externalFile = args.source?.file;
|
|
78046
78594
|
if (externalFile) {
|
|
78047
|
-
const normalized =
|
|
78048
|
-
if (
|
|
78595
|
+
const normalized = path113.normalize(externalFile);
|
|
78596
|
+
if (path113.isAbsolute(normalized) || normalized === ".." || normalized.startsWith(`..${path113.sep}`)) {
|
|
78049
78597
|
throw new Error("source.file must be project-relative and cannot escape the project");
|
|
78050
78598
|
}
|
|
78051
78599
|
}
|
|
@@ -78056,6 +78604,7 @@ var init_mcpAdapter = __esm({
|
|
|
78056
78604
|
confidence: args.confidence,
|
|
78057
78605
|
visibility: args.visibility,
|
|
78058
78606
|
tags: args.tags,
|
|
78607
|
+
relevantWhen: args.relevant_when,
|
|
78059
78608
|
source: {
|
|
78060
78609
|
...args.source ?? {},
|
|
78061
78610
|
...externalFile ? { file: externalFile.replace(/\\/g, "/") } : {},
|
|
@@ -78549,36 +79098,36 @@ var init_permissionCli = __esm({
|
|
|
78549
79098
|
|
|
78550
79099
|
// src/cli/companion/config.ts
|
|
78551
79100
|
import {
|
|
78552
|
-
existsSync as
|
|
78553
|
-
mkdirSync as
|
|
78554
|
-
readFileSync as
|
|
79101
|
+
existsSync as existsSync70,
|
|
79102
|
+
mkdirSync as mkdirSync27,
|
|
79103
|
+
readFileSync as readFileSync56,
|
|
78555
79104
|
statSync as statSync13,
|
|
78556
79105
|
writeFileSync as writeFileSync28
|
|
78557
79106
|
} from "node:fs";
|
|
78558
|
-
import { join as
|
|
78559
|
-
import { createHash as
|
|
79107
|
+
import { join as join49, resolve as resolve9 } from "node:path";
|
|
79108
|
+
import { createHash as createHash28, randomBytes as randomBytes7, timingSafeEqual } from "node:crypto";
|
|
78560
79109
|
function getZelariHome() {
|
|
78561
79110
|
return zelariHome();
|
|
78562
79111
|
}
|
|
78563
79112
|
function getCompanionConfigPath() {
|
|
78564
|
-
return
|
|
79113
|
+
return join49(getZelariHome(), "companion.json");
|
|
78565
79114
|
}
|
|
78566
79115
|
function getCompanionTokenPath() {
|
|
78567
|
-
return
|
|
79116
|
+
return join49(getZelariHome(), "companion.token");
|
|
78568
79117
|
}
|
|
78569
79118
|
function ensureHome() {
|
|
78570
79119
|
const home = getZelariHome();
|
|
78571
|
-
if (!
|
|
78572
|
-
|
|
79120
|
+
if (!existsSync70(home)) {
|
|
79121
|
+
mkdirSync27(home, { recursive: true });
|
|
78573
79122
|
}
|
|
78574
79123
|
}
|
|
78575
79124
|
function loadCompanionConfig() {
|
|
78576
|
-
const
|
|
78577
|
-
if (!
|
|
79125
|
+
const path128 = getCompanionConfigPath();
|
|
79126
|
+
if (!existsSync70(path128)) {
|
|
78578
79127
|
return { projects: [] };
|
|
78579
79128
|
}
|
|
78580
79129
|
try {
|
|
78581
|
-
const raw = JSON.parse(
|
|
79130
|
+
const raw = JSON.parse(readFileSync56(path128, "utf8"));
|
|
78582
79131
|
const projects = Array.isArray(raw.projects) ? raw.projects.filter(
|
|
78583
79132
|
(p3) => p3 && typeof p3.path === "string" && p3.path.trim() && typeof (p3.id ?? p3.name) === "string"
|
|
78584
79133
|
).map((p3) => ({
|
|
@@ -78616,24 +79165,24 @@ function loadOrCreateToken(explicit) {
|
|
|
78616
79165
|
return { token: explicit.trim(), created: false };
|
|
78617
79166
|
}
|
|
78618
79167
|
ensureHome();
|
|
78619
|
-
const
|
|
78620
|
-
if (
|
|
78621
|
-
const t =
|
|
79168
|
+
const path128 = getCompanionTokenPath();
|
|
79169
|
+
if (existsSync70(path128)) {
|
|
79170
|
+
const t = readFileSync56(path128, "utf8").trim();
|
|
78622
79171
|
if (t) return { token: t, created: false };
|
|
78623
79172
|
}
|
|
78624
79173
|
const token = randomBytes7(24).toString("base64url");
|
|
78625
|
-
writeFileSync28(
|
|
79174
|
+
writeFileSync28(path128, token + "\n", "utf8");
|
|
78626
79175
|
try {
|
|
78627
|
-
const
|
|
78628
|
-
|
|
79176
|
+
const fs52 = __require("node:fs");
|
|
79177
|
+
fs52.chmodSync?.(path128, 384);
|
|
78629
79178
|
} catch {
|
|
78630
79179
|
}
|
|
78631
79180
|
return { token, created: true };
|
|
78632
79181
|
}
|
|
78633
79182
|
function tokenMatches(expected, provided) {
|
|
78634
79183
|
if (!provided) return false;
|
|
78635
|
-
const a =
|
|
78636
|
-
const b =
|
|
79184
|
+
const a = createHash28("sha256").update(expected).digest();
|
|
79185
|
+
const b = createHash28("sha256").update(provided).digest();
|
|
78637
79186
|
try {
|
|
78638
79187
|
return timingSafeEqual(a, b);
|
|
78639
79188
|
} catch {
|
|
@@ -78665,8 +79214,8 @@ function resolveFsDirectory(rawPath) {
|
|
|
78665
79214
|
return { ok: false, error: `not a directory: ${trimmed}` };
|
|
78666
79215
|
}
|
|
78667
79216
|
const abs = resolve9(trimmed);
|
|
78668
|
-
const
|
|
78669
|
-
return { ok: true, project: { id:
|
|
79217
|
+
const slug2 = slugFromPath(abs);
|
|
79218
|
+
return { ok: true, project: { id: slug2, name: slug2, path: abs } };
|
|
78670
79219
|
}
|
|
78671
79220
|
function mergeProjects(cfg, extraPaths) {
|
|
78672
79221
|
const byId = /* @__PURE__ */ new Map();
|
|
@@ -78674,17 +79223,17 @@ function mergeProjects(cfg, extraPaths) {
|
|
|
78674
79223
|
byId.set(p3.id, p3);
|
|
78675
79224
|
}
|
|
78676
79225
|
for (const raw of extraPaths) {
|
|
78677
|
-
const
|
|
78678
|
-
if (!
|
|
78679
|
-
let id3 = slugFromPath(
|
|
79226
|
+
const path128 = raw.trim();
|
|
79227
|
+
if (!path128) continue;
|
|
79228
|
+
let id3 = slugFromPath(path128);
|
|
78680
79229
|
let n = 2;
|
|
78681
|
-
while (byId.has(id3) && byId.get(id3).path !==
|
|
78682
|
-
id3 = `${slugFromPath(
|
|
79230
|
+
while (byId.has(id3) && byId.get(id3).path !== path128) {
|
|
79231
|
+
id3 = `${slugFromPath(path128)}-${n++}`;
|
|
78683
79232
|
}
|
|
78684
79233
|
byId.set(id3, {
|
|
78685
79234
|
id: id3,
|
|
78686
|
-
name: slugFromPath(
|
|
78687
|
-
path:
|
|
79235
|
+
name: slugFromPath(path128),
|
|
79236
|
+
path: path128
|
|
78688
79237
|
});
|
|
78689
79238
|
}
|
|
78690
79239
|
return [...byId.values()];
|
|
@@ -78974,8 +79523,8 @@ var init_askUserBridge = __esm({
|
|
|
78974
79523
|
});
|
|
78975
79524
|
|
|
78976
79525
|
// src/cli/serve/spineLockSweep.ts
|
|
78977
|
-
import { promises as
|
|
78978
|
-
import
|
|
79526
|
+
import { promises as fs51 } from "node:fs";
|
|
79527
|
+
import path114 from "node:path";
|
|
78979
79528
|
async function sweepOrphanSpineLocks(sessionsDir2, options = {}) {
|
|
78980
79529
|
const dir = sessionsDir2 ?? resolveSessionsDir();
|
|
78981
79530
|
const onSwept = options.onSwept ?? ((sessionId2, reason) => {
|
|
@@ -78988,14 +79537,14 @@ async function sweepOrphanSpineLocks(sessionsDir2, options = {}) {
|
|
|
78988
79537
|
const result = { swept: 0, kept: 0, errors: 0 };
|
|
78989
79538
|
let entries;
|
|
78990
79539
|
try {
|
|
78991
|
-
entries = await
|
|
79540
|
+
entries = await fs51.readdir(dir);
|
|
78992
79541
|
} catch {
|
|
78993
79542
|
return result;
|
|
78994
79543
|
}
|
|
78995
79544
|
for (const sessionId2 of entries) {
|
|
78996
|
-
const lockPath2 =
|
|
79545
|
+
const lockPath2 = path114.join(dir, sessionId2, "writer.lock");
|
|
78997
79546
|
try {
|
|
78998
|
-
const raw = await
|
|
79547
|
+
const raw = await fs51.readFile(lockPath2, "utf-8");
|
|
78999
79548
|
let lockInfo = {};
|
|
79000
79549
|
try {
|
|
79001
79550
|
lockInfo = JSON.parse(raw);
|
|
@@ -79012,7 +79561,7 @@ async function sweepOrphanSpineLocks(sessionsDir2, options = {}) {
|
|
|
79012
79561
|
result.kept += 1;
|
|
79013
79562
|
continue;
|
|
79014
79563
|
}
|
|
79015
|
-
await
|
|
79564
|
+
await fs51.rm(lockPath2, { force: true });
|
|
79016
79565
|
result.swept += 1;
|
|
79017
79566
|
onSwept(sessionId2, verdict.reason);
|
|
79018
79567
|
} catch (err) {
|
|
@@ -79110,7 +79659,7 @@ __export(harnessServer_exports, {
|
|
|
79110
79659
|
startHarnessServer: () => startHarnessServer
|
|
79111
79660
|
});
|
|
79112
79661
|
import { createInterface as createInterface3 } from "node:readline";
|
|
79113
|
-
import
|
|
79662
|
+
import path115 from "node:path";
|
|
79114
79663
|
import { randomUUID as randomUUID12 } from "node:crypto";
|
|
79115
79664
|
function createCliWorkspaceServices(workspaceRoot) {
|
|
79116
79665
|
const mode = activePolicyLoadMode();
|
|
@@ -79145,7 +79694,7 @@ function resolveSessionCreateRoot(params, cwd = process.cwd()) {
|
|
|
79145
79694
|
};
|
|
79146
79695
|
}
|
|
79147
79696
|
const root = raw.trim();
|
|
79148
|
-
if (!
|
|
79697
|
+
if (!path115.isAbsolute(root)) {
|
|
79149
79698
|
return {
|
|
79150
79699
|
ok: false,
|
|
79151
79700
|
message: `session.create workspaceRoot must be an absolute path (got '${root}') \u2014 a relative root would resolve against the sidecar cwd (${cwd}) and mix conversations (ADR-0016)`
|
|
@@ -79560,7 +80109,7 @@ import { spawn as spawn19 } from "node:child_process";
|
|
|
79560
80109
|
import { createInterface as createInterface4 } from "node:readline";
|
|
79561
80110
|
import { randomUUID as randomUUID13 } from "node:crypto";
|
|
79562
80111
|
import { writeFileSync as writeFileSync29, unlinkSync as unlinkSync3 } from "node:fs";
|
|
79563
|
-
import { join as
|
|
80112
|
+
import { join as join50 } from "node:path";
|
|
79564
80113
|
import { tmpdir as tmpdir4 } from "node:os";
|
|
79565
80114
|
function harnessServerMode() {
|
|
79566
80115
|
return process.env[HARNESS_SERVER_ENV] === "1";
|
|
@@ -79767,7 +80316,7 @@ var init_runManager = __esm({
|
|
|
79767
80316
|
}
|
|
79768
80317
|
let historyFile;
|
|
79769
80318
|
if (args.history && Array.isArray(args.history) && args.history.length > 0) {
|
|
79770
|
-
historyFile =
|
|
80319
|
+
historyFile = join50(tmpdir4(), `zelari-companion-hist-${run.id}.json`);
|
|
79771
80320
|
try {
|
|
79772
80321
|
writeFileSync29(historyFile, JSON.stringify(args.history), "utf8");
|
|
79773
80322
|
argv.push("--history-file", historyFile);
|
|
@@ -80154,8 +80703,8 @@ __export(serve_exports, {
|
|
|
80154
80703
|
runCompanionServe: () => runCompanionServe
|
|
80155
80704
|
});
|
|
80156
80705
|
import { createServer as createServer3 } from "node:http";
|
|
80157
|
-
import { existsSync as
|
|
80158
|
-
import { join as
|
|
80706
|
+
import { existsSync as existsSync71, readdirSync as readdirSync15 } from "node:fs";
|
|
80707
|
+
import { join as join51, resolve as resolve10 } from "node:path";
|
|
80159
80708
|
function readBody(req, max = 2e6) {
|
|
80160
80709
|
return new Promise((resolveBody, reject) => {
|
|
80161
80710
|
const chunks = [];
|
|
@@ -80203,7 +80752,7 @@ async function runCompanionServe(opts = {}) {
|
|
|
80203
80752
|
let projects = mergeProjects(fileCfg, opts.projects ?? []);
|
|
80204
80753
|
projects = projects.filter((p3) => {
|
|
80205
80754
|
const abs = resolve10(p3.path);
|
|
80206
|
-
if (!
|
|
80755
|
+
if (!existsSync71(abs)) {
|
|
80207
80756
|
process.stderr.write(
|
|
80208
80757
|
`[zelari-code serve] skip missing project path: ${p3.path}
|
|
80209
80758
|
`
|
|
@@ -80255,9 +80804,9 @@ async function runCompanionServe(opts = {}) {
|
|
|
80255
80804
|
return;
|
|
80256
80805
|
}
|
|
80257
80806
|
const url2 = parseUrl(req);
|
|
80258
|
-
const
|
|
80807
|
+
const path128 = url2.pathname.replace(/\/+$/, "") || "/";
|
|
80259
80808
|
try {
|
|
80260
|
-
if (req.method === "GET" && (
|
|
80809
|
+
if (req.method === "GET" && (path128 === "/health" || path128 === "/v1/health")) {
|
|
80261
80810
|
sendJson2(res, 200, {
|
|
80262
80811
|
ok: true,
|
|
80263
80812
|
service: "zelari-companion",
|
|
@@ -80269,25 +80818,25 @@ async function runCompanionServe(opts = {}) {
|
|
|
80269
80818
|
});
|
|
80270
80819
|
return;
|
|
80271
80820
|
}
|
|
80272
|
-
if (
|
|
80821
|
+
if (path128.startsWith("/v1")) {
|
|
80273
80822
|
if (!tokenMatches(token, getBearer(req))) {
|
|
80274
80823
|
sendJson2(res, 401, { ok: false, error: "unauthorized" });
|
|
80275
80824
|
return;
|
|
80276
80825
|
}
|
|
80277
80826
|
}
|
|
80278
|
-
if (req.method === "GET" &&
|
|
80827
|
+
if (req.method === "GET" && path128 === "/v1/config") {
|
|
80279
80828
|
const snap = buildDesktopConfigSnapshot();
|
|
80280
80829
|
sendJson2(res, 200, { ok: true, ...snap });
|
|
80281
80830
|
return;
|
|
80282
80831
|
}
|
|
80283
|
-
if (req.method === "GET" &&
|
|
80832
|
+
if (req.method === "GET" && path128 === "/v1/fs") {
|
|
80284
80833
|
const listFsRootsInline = () => {
|
|
80285
80834
|
if (process.platform === "win32") {
|
|
80286
80835
|
const roots = [];
|
|
80287
80836
|
for (let code = 65; code <= 90; code++) {
|
|
80288
80837
|
const letter = String.fromCharCode(code);
|
|
80289
80838
|
const drive = `${letter}:\\`;
|
|
80290
|
-
if (
|
|
80839
|
+
if (existsSync71(drive)) {
|
|
80291
80840
|
roots.push({
|
|
80292
80841
|
id: `fs-${letter.toLowerCase()}`,
|
|
80293
80842
|
name: drive,
|
|
@@ -80315,7 +80864,7 @@ async function runCompanionServe(opts = {}) {
|
|
|
80315
80864
|
sendJson2(res, 403, { ok: false, error: "path outside allowed roots" });
|
|
80316
80865
|
return;
|
|
80317
80866
|
}
|
|
80318
|
-
if (!
|
|
80867
|
+
if (!existsSync71(rawParam)) {
|
|
80319
80868
|
sendJson2(res, 404, { ok: false, error: "path not found" });
|
|
80320
80869
|
return;
|
|
80321
80870
|
}
|
|
@@ -80333,13 +80882,13 @@ async function runCompanionServe(opts = {}) {
|
|
|
80333
80882
|
parent,
|
|
80334
80883
|
entries: dirs.map((d) => ({
|
|
80335
80884
|
name: d.name,
|
|
80336
|
-
path:
|
|
80885
|
+
path: join51(rawParam, d.name),
|
|
80337
80886
|
dir: true
|
|
80338
80887
|
}))
|
|
80339
80888
|
});
|
|
80340
80889
|
return;
|
|
80341
80890
|
}
|
|
80342
|
-
if (req.method === "GET" &&
|
|
80891
|
+
if (req.method === "GET" && path128 === "/v1/projects") {
|
|
80343
80892
|
sendJson2(res, 200, {
|
|
80344
80893
|
ok: true,
|
|
80345
80894
|
projects: projects.map((p3) => ({
|
|
@@ -80350,7 +80899,7 @@ async function runCompanionServe(opts = {}) {
|
|
|
80350
80899
|
});
|
|
80351
80900
|
return;
|
|
80352
80901
|
}
|
|
80353
|
-
if (req.method === "GET" &&
|
|
80902
|
+
if (req.method === "GET" && path128 === "/v1/runs") {
|
|
80354
80903
|
sendJson2(res, 200, {
|
|
80355
80904
|
ok: true,
|
|
80356
80905
|
active: runs.getActive(),
|
|
@@ -80368,7 +80917,7 @@ async function runCompanionServe(opts = {}) {
|
|
|
80368
80917
|
});
|
|
80369
80918
|
return;
|
|
80370
80919
|
}
|
|
80371
|
-
if (req.method === "POST" &&
|
|
80920
|
+
if (req.method === "POST" && path128 === "/v1/runs") {
|
|
80372
80921
|
const raw = await readBody(req);
|
|
80373
80922
|
let body = {};
|
|
80374
80923
|
try {
|
|
@@ -80428,7 +80977,7 @@ async function runCompanionServe(opts = {}) {
|
|
|
80428
80977
|
});
|
|
80429
80978
|
return;
|
|
80430
80979
|
}
|
|
80431
|
-
if (req.method === "POST" &&
|
|
80980
|
+
if (req.method === "POST" && path128 === "/v1/trust") {
|
|
80432
80981
|
const raw = await readBody(req);
|
|
80433
80982
|
let body = {};
|
|
80434
80983
|
try {
|
|
@@ -80469,11 +81018,11 @@ async function runCompanionServe(opts = {}) {
|
|
|
80469
81018
|
sendJson2(res, 200, { ok: true, denied: runId });
|
|
80470
81019
|
return;
|
|
80471
81020
|
}
|
|
80472
|
-
if (req.method === "GET" &&
|
|
81021
|
+
if (req.method === "GET" && path128 === "/v1/trust/pending") {
|
|
80473
81022
|
sendJson2(res, 200, { ok: true, pending: runs.pendingTrust() });
|
|
80474
81023
|
return;
|
|
80475
81024
|
}
|
|
80476
|
-
const eventsMatch = /^\/v1\/runs\/([^/]+)\/events$/.exec(
|
|
81025
|
+
const eventsMatch = /^\/v1\/runs\/([^/]+)\/events$/.exec(path128);
|
|
80477
81026
|
if (req.method === "GET" && eventsMatch) {
|
|
80478
81027
|
const runId = eventsMatch[1];
|
|
80479
81028
|
const run = runs.getRun(runId);
|
|
@@ -80538,7 +81087,7 @@ async function runCompanionServe(opts = {}) {
|
|
|
80538
81087
|
}, 500);
|
|
80539
81088
|
return;
|
|
80540
81089
|
}
|
|
80541
|
-
const cancelMatch = /^\/v1\/runs\/([^/]+)\/cancel$/.exec(
|
|
81090
|
+
const cancelMatch = /^\/v1\/runs\/([^/]+)\/cancel$/.exec(path128);
|
|
80542
81091
|
if (req.method === "POST" && cancelMatch) {
|
|
80543
81092
|
const runId = cancelMatch[1];
|
|
80544
81093
|
const result = runs.cancel(runId);
|
|
@@ -80549,7 +81098,7 @@ async function runCompanionServe(opts = {}) {
|
|
|
80549
81098
|
sendJson2(res, 200, { ok: true, cancelled: runId });
|
|
80550
81099
|
return;
|
|
80551
81100
|
}
|
|
80552
|
-
const steerMatch = /^\/v1\/runs\/([^/]+)\/steer$/.exec(
|
|
81101
|
+
const steerMatch = /^\/v1\/runs\/([^/]+)\/steer$/.exec(path128);
|
|
80553
81102
|
if (req.method === "POST" && steerMatch) {
|
|
80554
81103
|
const runId = steerMatch[1];
|
|
80555
81104
|
const raw = await readBody(req);
|
|
@@ -80573,7 +81122,7 @@ async function runCompanionServe(opts = {}) {
|
|
|
80573
81122
|
sendJson2(res, 200, { ok: true, steered: runId, result: result.result });
|
|
80574
81123
|
return;
|
|
80575
81124
|
}
|
|
80576
|
-
const askMatch = /^\/v1\/runs\/([^/]+)\/(permission|ask)$/.exec(
|
|
81125
|
+
const askMatch = /^\/v1\/runs\/([^/]+)\/(permission|ask)$/.exec(path128);
|
|
80577
81126
|
if (req.method === "POST" && askMatch) {
|
|
80578
81127
|
const runId = askMatch[1];
|
|
80579
81128
|
const kind2 = askMatch[2];
|
|
@@ -80834,26 +81383,26 @@ __export(doctor_exports, {
|
|
|
80834
81383
|
runDoctor: () => runDoctor
|
|
80835
81384
|
});
|
|
80836
81385
|
import { execSync as execSync3 } from "node:child_process";
|
|
80837
|
-
import { existsSync as
|
|
81386
|
+
import { existsSync as existsSync72, readFileSync as readFileSync57, readlinkSync, statSync as statSync14 } from "node:fs";
|
|
80838
81387
|
import { createRequire as createRequire3 } from "node:module";
|
|
80839
81388
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
80840
|
-
import
|
|
81389
|
+
import path116 from "node:path";
|
|
80841
81390
|
function findPackageRoot(start) {
|
|
80842
81391
|
let dir = start;
|
|
80843
81392
|
for (let i = 0; i < 6; i += 1) {
|
|
80844
|
-
const candidate =
|
|
80845
|
-
if (
|
|
81393
|
+
const candidate = path116.join(dir, "package.json");
|
|
81394
|
+
if (existsSync72(candidate)) {
|
|
80846
81395
|
try {
|
|
80847
|
-
const pkg = JSON.parse(
|
|
81396
|
+
const pkg = JSON.parse(readFileSync57(candidate, "utf8"));
|
|
80848
81397
|
if (pkg.name === "zelari-code") return dir;
|
|
80849
81398
|
} catch {
|
|
80850
81399
|
}
|
|
80851
81400
|
}
|
|
80852
|
-
const parent =
|
|
81401
|
+
const parent = path116.dirname(dir);
|
|
80853
81402
|
if (parent === dir) break;
|
|
80854
81403
|
dir = parent;
|
|
80855
81404
|
}
|
|
80856
|
-
return
|
|
81405
|
+
return path116.resolve(__dirname3, "..", "..", "..");
|
|
80857
81406
|
}
|
|
80858
81407
|
function tryExec(cmd) {
|
|
80859
81408
|
try {
|
|
@@ -80867,8 +81416,8 @@ function tryExec(cmd) {
|
|
|
80867
81416
|
}
|
|
80868
81417
|
function readPackageJson4() {
|
|
80869
81418
|
try {
|
|
80870
|
-
const pkgPath =
|
|
80871
|
-
return JSON.parse(
|
|
81419
|
+
const pkgPath = path116.join(packageRoot, "package.json");
|
|
81420
|
+
return JSON.parse(readFileSync57(pkgPath, "utf8"));
|
|
80872
81421
|
} catch {
|
|
80873
81422
|
return null;
|
|
80874
81423
|
}
|
|
@@ -80879,7 +81428,7 @@ function getGlobalPrefix2() {
|
|
|
80879
81428
|
return (process.env.npm_config_prefix || process.env.NPM_CONFIG_PREFIX || "").trim();
|
|
80880
81429
|
}
|
|
80881
81430
|
function isSourceCheckout() {
|
|
80882
|
-
return
|
|
81431
|
+
return existsSync72(path116.join(packageRoot, "src", "cli", "main.ts")) && existsSync72(path116.join(packageRoot, "apps", "desktop", "package.json"));
|
|
80883
81432
|
}
|
|
80884
81433
|
function checkShim(pkgName) {
|
|
80885
81434
|
const prefix = getGlobalPrefix2();
|
|
@@ -80888,10 +81437,10 @@ function checkShim(pkgName) {
|
|
|
80888
81437
|
}
|
|
80889
81438
|
const isWin = process.platform === "win32";
|
|
80890
81439
|
const shimName = isWin ? "zelari-code.cmd" : "zelari-code";
|
|
80891
|
-
const shimPath =
|
|
80892
|
-
if (!
|
|
80893
|
-
const localBin =
|
|
80894
|
-
if (isSourceCheckout() &&
|
|
81440
|
+
const shimPath = path116.join(prefix, shimName);
|
|
81441
|
+
if (!existsSync72(shimPath)) {
|
|
81442
|
+
const localBin = path116.join(packageRoot, "bin", "zelari-code.js");
|
|
81443
|
+
if (isSourceCheckout() && existsSync72(localBin)) {
|
|
80895
81444
|
return WARN(
|
|
80896
81445
|
`global shim not found at ${shimPath}
|
|
80897
81446
|
source checkout \u2014 using ${localBin}
|
|
@@ -80914,7 +81463,7 @@ function checkShim(pkgName) {
|
|
|
80914
81463
|
try {
|
|
80915
81464
|
const st = statSync14(shimPath);
|
|
80916
81465
|
if (isWin) {
|
|
80917
|
-
const content =
|
|
81466
|
+
const content = readFileSync57(shimPath, "utf8");
|
|
80918
81467
|
if (content.includes(`${pkgName}\\bin\\`) || content.includes(`${pkgName}/bin/`)) {
|
|
80919
81468
|
return OK(`shim OK at ${shimPath} (${st.size} bytes)`);
|
|
80920
81469
|
}
|
|
@@ -80932,8 +81481,8 @@ function checkShim(pkgName) {
|
|
|
80932
81481
|
fix: npm install -g ${pkgName}@latest --force`
|
|
80933
81482
|
);
|
|
80934
81483
|
}
|
|
80935
|
-
const resolved =
|
|
80936
|
-
const expected =
|
|
81484
|
+
const resolved = path116.resolve(path116.dirname(shimPath), target);
|
|
81485
|
+
const expected = path116.join(
|
|
80937
81486
|
prefix,
|
|
80938
81487
|
"node_modules",
|
|
80939
81488
|
pkgName,
|
|
@@ -80975,8 +81524,8 @@ function checkNode(pkg) {
|
|
|
80975
81524
|
return OK(`node ${raw} (engines.node ${enginesNode ?? ">= 20.0.0"})`);
|
|
80976
81525
|
}
|
|
80977
81526
|
function checkBundle() {
|
|
80978
|
-
const bundle =
|
|
80979
|
-
if (!
|
|
81527
|
+
const bundle = path116.join(packageRoot, "dist", "cli", "main.bundled.js");
|
|
81528
|
+
if (!existsSync72(bundle)) {
|
|
80980
81529
|
return FAIL(
|
|
80981
81530
|
`dist/cli/main.bundled.js missing at ${bundle}
|
|
80982
81531
|
fix: npm run build:cli (then reinstall or run via tsx)`
|
|
@@ -80996,7 +81545,7 @@ function checkRuntimeDeps() {
|
|
|
80996
81545
|
const missing = [];
|
|
80997
81546
|
for (const dep of required2) {
|
|
80998
81547
|
try {
|
|
80999
|
-
const localReq = createRequire3(
|
|
81548
|
+
const localReq = createRequire3(path116.join(packageRoot, "package.json"));
|
|
81000
81549
|
localReq.resolve(dep);
|
|
81001
81550
|
} catch {
|
|
81002
81551
|
missing.push(dep);
|
|
@@ -81297,7 +81846,7 @@ var init_doctor = __esm({
|
|
|
81297
81846
|
init_cacheHitReport();
|
|
81298
81847
|
init_updater();
|
|
81299
81848
|
require3 = createRequire3(import.meta.url);
|
|
81300
|
-
__dirname3 =
|
|
81849
|
+
__dirname3 = path116.dirname(fileURLToPath3(import.meta.url));
|
|
81301
81850
|
packageRoot = findPackageRoot(__dirname3);
|
|
81302
81851
|
OK = (message) => ({
|
|
81303
81852
|
ok: true,
|
|
@@ -81480,8 +82029,8 @@ __export(inspectSession_exports, {
|
|
|
81480
82029
|
renderInspectReport: () => renderInspectReport,
|
|
81481
82030
|
runInspectSession: () => runInspectSession
|
|
81482
82031
|
});
|
|
81483
|
-
import
|
|
81484
|
-
import { existsSync as
|
|
82032
|
+
import path117 from "node:path";
|
|
82033
|
+
import { existsSync as existsSync73 } from "node:fs";
|
|
81485
82034
|
function formatLimit(limit) {
|
|
81486
82035
|
return `${Math.round(limit / 1e3)}k`;
|
|
81487
82036
|
}
|
|
@@ -81514,13 +82063,13 @@ function renderInspectReport(state3) {
|
|
|
81514
82063
|
}
|
|
81515
82064
|
async function runInspectSession(opts) {
|
|
81516
82065
|
const sessionsDir2 = resolveSessionsDir({ workspaceRoot: opts.cwd ?? process.cwd() });
|
|
81517
|
-
const sessionDir =
|
|
81518
|
-
const eventsPath =
|
|
81519
|
-
if (!
|
|
82066
|
+
const sessionDir = path117.join(sessionsDir2, opts.sessionId);
|
|
82067
|
+
const eventsPath = path117.join(sessionDir, "events.jsonl");
|
|
82068
|
+
if (!existsSync73(sessionDir)) {
|
|
81520
82069
|
console.error(`zelari-code inspect: no session directory at ${sessionDir}`);
|
|
81521
82070
|
return 1;
|
|
81522
82071
|
}
|
|
81523
|
-
if (!
|
|
82072
|
+
if (!existsSync73(eventsPath)) {
|
|
81524
82073
|
console.error(`zelari-code inspect: session directory has no events.jsonl at ${eventsPath}`);
|
|
81525
82074
|
return 1;
|
|
81526
82075
|
}
|
|
@@ -81549,14 +82098,14 @@ __export(inspect_exports, {
|
|
|
81549
82098
|
collectInspectReport: () => collectInspectReport,
|
|
81550
82099
|
runInspect: () => runInspect
|
|
81551
82100
|
});
|
|
81552
|
-
import
|
|
81553
|
-
import { existsSync as
|
|
82101
|
+
import path118 from "node:path";
|
|
82102
|
+
import { existsSync as existsSync74, readFileSync as readFileSync58, readdirSync as readdirSync16 } from "node:fs";
|
|
81554
82103
|
async function collectInspectReport(cwd = process.cwd()) {
|
|
81555
82104
|
ensureBuiltinSkillsLoadedSync();
|
|
81556
82105
|
const snap = listSkillsSnapshot(cwd);
|
|
81557
82106
|
const mcp = listMcpServers(cwd);
|
|
81558
|
-
const userMcpPath =
|
|
81559
|
-
const projectMcpPath =
|
|
82107
|
+
const userMcpPath = path118.join(zelariHome(), "mcp.json");
|
|
82108
|
+
const projectMcpPath = path118.join(cwd, ".zelari", "mcp.json");
|
|
81560
82109
|
const globalHooks = globalHooksDir();
|
|
81561
82110
|
const projectHooks = projectHooksDir(cwd);
|
|
81562
82111
|
const projectTrusted = isFolderTrusted(cwd);
|
|
@@ -81582,11 +82131,11 @@ async function collectInspectReport(cwd = process.cwd()) {
|
|
|
81582
82131
|
folders: listTrustedFolders()
|
|
81583
82132
|
},
|
|
81584
82133
|
configSources: [
|
|
81585
|
-
{ path: userMcpPath, exists:
|
|
81586
|
-
{ path: projectMcpPath, exists:
|
|
81587
|
-
{ path:
|
|
81588
|
-
{ path:
|
|
81589
|
-
{ path:
|
|
82134
|
+
{ path: userMcpPath, exists: existsSync74(userMcpPath) },
|
|
82135
|
+
{ path: projectMcpPath, exists: existsSync74(projectMcpPath) },
|
|
82136
|
+
{ path: path118.join(zelariHome(), "provider.json"), exists: existsSync74(path118.join(zelariHome(), "provider.json")) },
|
|
82137
|
+
{ path: path118.join(cwd, ".zelari", "AGENTS.md"), exists: existsSync74(path118.join(cwd, ".zelari", "AGENTS.md")) },
|
|
82138
|
+
{ path: path118.join(cwd, "AGENTS.md"), exists: existsSync74(path118.join(cwd, "AGENTS.md")) }
|
|
81590
82139
|
],
|
|
81591
82140
|
skills: {
|
|
81592
82141
|
total: snap.skills.length,
|
|
@@ -81599,7 +82148,7 @@ async function collectInspectReport(cwd = process.cwd()) {
|
|
|
81599
82148
|
user: mcp.servers.filter((s) => s.scope === "user").map((s) => ({ name: s.name, enabled: s.enabled !== false })),
|
|
81600
82149
|
project: mcp.servers.filter((s) => s.scope === "project").map((s) => ({ name: s.name, enabled: s.enabled !== false })),
|
|
81601
82150
|
projectTrusted,
|
|
81602
|
-
projectConfigExists:
|
|
82151
|
+
projectConfigExists: existsSync74(projectMcpPath)
|
|
81603
82152
|
},
|
|
81604
82153
|
hooks: {
|
|
81605
82154
|
global: {
|
|
@@ -81626,14 +82175,14 @@ function listJsonFiles(dir) {
|
|
|
81626
82175
|
}
|
|
81627
82176
|
function findAgentsMd(cwd) {
|
|
81628
82177
|
const candidates = [
|
|
81629
|
-
|
|
81630
|
-
|
|
82178
|
+
path118.join(cwd, "AGENTS.md"),
|
|
82179
|
+
path118.join(cwd, ".zelari", "AGENTS.md")
|
|
81631
82180
|
];
|
|
81632
82181
|
const found = [];
|
|
81633
82182
|
for (const c of candidates) {
|
|
81634
|
-
if (
|
|
82183
|
+
if (existsSync74(c)) {
|
|
81635
82184
|
try {
|
|
81636
|
-
const text =
|
|
82185
|
+
const text = readFileSync58(c, "utf8");
|
|
81637
82186
|
found.push(`${c} (${text.length} bytes)`);
|
|
81638
82187
|
} catch {
|
|
81639
82188
|
found.push(`${c} (unreadable)`);
|
|
@@ -81701,8 +82250,8 @@ __export(skillsCheck_exports, {
|
|
|
81701
82250
|
formatSkillsCheckReport: () => formatSkillsCheckReport,
|
|
81702
82251
|
parseFrontmatter: () => parseFrontmatter2
|
|
81703
82252
|
});
|
|
81704
|
-
import { existsSync as
|
|
81705
|
-
import { join as
|
|
82253
|
+
import { existsSync as existsSync75, readdirSync as readdirSync17, readFileSync as readFileSync59 } from "node:fs";
|
|
82254
|
+
import { join as join52 } from "node:path";
|
|
81706
82255
|
function parseFrontmatter2(content) {
|
|
81707
82256
|
const fm = FRONTMATTER_RE2.exec(content);
|
|
81708
82257
|
if (!fm) return null;
|
|
@@ -81723,10 +82272,10 @@ function parseFrontmatter2(content) {
|
|
|
81723
82272
|
function messageOf(err) {
|
|
81724
82273
|
return err instanceof Error ? err.message : String(err);
|
|
81725
82274
|
}
|
|
81726
|
-
function checkSkillMd(
|
|
82275
|
+
function checkSkillMd(path128, content) {
|
|
81727
82276
|
const lines = [];
|
|
81728
82277
|
const push = (level, detail) => {
|
|
81729
|
-
lines.push({ level, what: `${
|
|
82278
|
+
lines.push({ level, what: `${path128}: ${detail}` });
|
|
81730
82279
|
};
|
|
81731
82280
|
if (content.length === 0) {
|
|
81732
82281
|
push("error", "file is empty (the loader requires frontmatter AND a body)");
|
|
@@ -81784,7 +82333,7 @@ function checkSkillFiles(options = {}) {
|
|
|
81784
82333
|
let existingRoots = 0;
|
|
81785
82334
|
let skillsChecked = 0;
|
|
81786
82335
|
for (const root of roots) {
|
|
81787
|
-
if (!
|
|
82336
|
+
if (!existsSync75(root)) continue;
|
|
81788
82337
|
existingRoots += 1;
|
|
81789
82338
|
let entries;
|
|
81790
82339
|
try {
|
|
@@ -81794,31 +82343,31 @@ function checkSkillFiles(options = {}) {
|
|
|
81794
82343
|
continue;
|
|
81795
82344
|
}
|
|
81796
82345
|
for (const entry of entries) {
|
|
81797
|
-
const dir =
|
|
81798
|
-
const
|
|
81799
|
-
if (!
|
|
82346
|
+
const dir = join52(root, entry);
|
|
82347
|
+
const path128 = join52(dir, "SKILL.md");
|
|
82348
|
+
if (!existsSync75(path128)) {
|
|
81800
82349
|
lines.push({ level: "warn", what: `${dir}: no SKILL.md inside this skills directory (ignored by the loader)` });
|
|
81801
82350
|
continue;
|
|
81802
82351
|
}
|
|
81803
82352
|
let content;
|
|
81804
82353
|
try {
|
|
81805
|
-
content =
|
|
82354
|
+
content = readFileSync59(path128, "utf8");
|
|
81806
82355
|
} catch (err) {
|
|
81807
|
-
lines.push({ level: "error", what: `${
|
|
82356
|
+
lines.push({ level: "error", what: `${path128}: unreadable \u2014 ${messageOf(err)}` });
|
|
81808
82357
|
continue;
|
|
81809
82358
|
}
|
|
81810
82359
|
skillsChecked += 1;
|
|
81811
|
-
lines.push(...checkSkillMd(
|
|
82360
|
+
lines.push(...checkSkillMd(path128, content));
|
|
81812
82361
|
const name = (parseFrontmatter2(content)?.fields["name"] ?? "").trim().toLowerCase();
|
|
81813
82362
|
if (!name) continue;
|
|
81814
82363
|
const owner = ownerByName.get(name);
|
|
81815
82364
|
if (owner) {
|
|
81816
82365
|
lines.push({
|
|
81817
82366
|
level: "warn",
|
|
81818
|
-
what: `${
|
|
82367
|
+
what: `${path128}: name "${name}" is already provided by ${owner} (earlier directory wins; this file is skipped)`
|
|
81819
82368
|
});
|
|
81820
82369
|
} else {
|
|
81821
|
-
ownerByName.set(name,
|
|
82370
|
+
ownerByName.set(name, path128);
|
|
81822
82371
|
}
|
|
81823
82372
|
}
|
|
81824
82373
|
}
|
|
@@ -82868,13 +83417,13 @@ var init_command = __esm({
|
|
|
82868
83417
|
});
|
|
82869
83418
|
|
|
82870
83419
|
// src/cli/plugins/bundleManifest.ts
|
|
82871
|
-
import
|
|
83420
|
+
import path119 from "node:path";
|
|
82872
83421
|
function stripComment2(value) {
|
|
82873
83422
|
const { $comment: _comment, ...rest } = value;
|
|
82874
83423
|
return rest;
|
|
82875
83424
|
}
|
|
82876
83425
|
function escapesBundleRoot(p3) {
|
|
82877
|
-
if (
|
|
83426
|
+
if (path119.isAbsolute(p3) || path119.win32.isAbsolute(p3)) return true;
|
|
82878
83427
|
return p3.split(/[\\/]+/).includes("..");
|
|
82879
83428
|
}
|
|
82880
83429
|
function formatIssues(error51, filePath) {
|
|
@@ -82987,7 +83536,7 @@ var init_bundleManifest = __esm({
|
|
|
82987
83536
|
|
|
82988
83537
|
// src/cli/plugins/bundleFs.ts
|
|
82989
83538
|
import { stat as stat8 } from "node:fs/promises";
|
|
82990
|
-
import
|
|
83539
|
+
import path120 from "node:path";
|
|
82991
83540
|
async function isFile(p3) {
|
|
82992
83541
|
try {
|
|
82993
83542
|
return (await stat8(p3)).isFile();
|
|
@@ -83006,9 +83555,9 @@ function isRecord(value) {
|
|
|
83006
83555
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
83007
83556
|
}
|
|
83008
83557
|
async function resolveInsideBundle(root, relPath, at, manifestPath, errors) {
|
|
83009
|
-
const abs =
|
|
83010
|
-
const rel2 =
|
|
83011
|
-
if (rel2 === "" || rel2.startsWith("..") ||
|
|
83558
|
+
const abs = path120.resolve(root, relPath);
|
|
83559
|
+
const rel2 = path120.relative(root, abs);
|
|
83560
|
+
if (rel2 === "" || rel2.startsWith("..") || path120.isAbsolute(rel2)) {
|
|
83012
83561
|
errors.push(
|
|
83013
83562
|
`${manifestPath}: invalid bundle manifest at '${at}': path escapes the bundle directory ('${relPath}')`
|
|
83014
83563
|
);
|
|
@@ -83137,7 +83686,7 @@ var init_bundleMcp = __esm({
|
|
|
83137
83686
|
|
|
83138
83687
|
// src/cli/plugins/bundleLoad.ts
|
|
83139
83688
|
import { readFile as readFile12 } from "node:fs/promises";
|
|
83140
|
-
import
|
|
83689
|
+
import path121 from "node:path";
|
|
83141
83690
|
async function readSkills(manifestSkills, root, manifestPath, errors) {
|
|
83142
83691
|
const skills = [];
|
|
83143
83692
|
for (let i = 0; i < manifestSkills.length; i += 1) {
|
|
@@ -83186,8 +83735,8 @@ async function readHooks(manifestHooks, root, manifestPath, errors, warnings) {
|
|
|
83186
83735
|
async function readBundle(dir, manifestFileName = BUNDLE_MANIFEST_FILE) {
|
|
83187
83736
|
const errors = [];
|
|
83188
83737
|
const warnings = [];
|
|
83189
|
-
const root =
|
|
83190
|
-
const manifestPath =
|
|
83738
|
+
const root = path121.resolve(dir);
|
|
83739
|
+
const manifestPath = path121.join(root, manifestFileName);
|
|
83191
83740
|
if (!await isDir(root)) {
|
|
83192
83741
|
return { errors: [`${root}: not a bundle directory`], warnings };
|
|
83193
83742
|
}
|
|
@@ -83250,12 +83799,12 @@ var init_bundleLoad = __esm({
|
|
|
83250
83799
|
|
|
83251
83800
|
// src/cli/plugins/bundleDiscover.ts
|
|
83252
83801
|
import { readdir as readdir4 } from "node:fs/promises";
|
|
83253
|
-
import
|
|
83802
|
+
import path122 from "node:path";
|
|
83254
83803
|
function defaultBundleRoots(projectRoot, state3) {
|
|
83255
|
-
const roots = [
|
|
83256
|
-
for (const p3 of state3.paths) roots.push(
|
|
83804
|
+
const roots = [path122.join(projectRoot, "examples", "extensions")];
|
|
83805
|
+
for (const p3 of state3.paths) roots.push(path122.resolve(projectRoot, p3));
|
|
83257
83806
|
const unique = /* @__PURE__ */ new Map();
|
|
83258
|
-
for (const root of roots) unique.set(
|
|
83807
|
+
for (const root of roots) unique.set(path122.resolve(root).toLowerCase(), root);
|
|
83259
83808
|
return [...unique.values()];
|
|
83260
83809
|
}
|
|
83261
83810
|
async function discoverBundles(roots) {
|
|
@@ -83270,9 +83819,9 @@ async function discoverBundles(roots) {
|
|
|
83270
83819
|
continue;
|
|
83271
83820
|
}
|
|
83272
83821
|
for (const entry of entries) {
|
|
83273
|
-
const dir =
|
|
83274
|
-
if (!await isFile(
|
|
83275
|
-
const key =
|
|
83822
|
+
const dir = path122.join(root, entry);
|
|
83823
|
+
if (!await isFile(path122.join(dir, BUNDLE_MANIFEST_FILE))) continue;
|
|
83824
|
+
const key = path122.resolve(dir);
|
|
83276
83825
|
if (seen.has(key)) continue;
|
|
83277
83826
|
seen.add(key);
|
|
83278
83827
|
const result = await readBundle(dir);
|
|
@@ -83299,12 +83848,12 @@ var init_bundleDiscover = __esm({
|
|
|
83299
83848
|
|
|
83300
83849
|
// src/cli/plugins/bundleState.ts
|
|
83301
83850
|
import { mkdir as mkdir6, readFile as readFile13, writeFile as writeFile5 } from "node:fs/promises";
|
|
83302
|
-
import
|
|
83851
|
+
import path123 from "node:path";
|
|
83303
83852
|
function emptyBundleState() {
|
|
83304
83853
|
return { enabled: {}, paths: [] };
|
|
83305
83854
|
}
|
|
83306
83855
|
function bundleStatePath(projectRoot) {
|
|
83307
|
-
return
|
|
83856
|
+
return path123.join(projectRoot, BUNDLE_STATE_FILE);
|
|
83308
83857
|
}
|
|
83309
83858
|
function isBundleEnabled(state3, name) {
|
|
83310
83859
|
return state3.enabled[name] === true;
|
|
@@ -83344,11 +83893,11 @@ async function readBundleState(projectRoot) {
|
|
|
83344
83893
|
return { state: state3, path: file2, errors: [] };
|
|
83345
83894
|
}
|
|
83346
83895
|
function withRegisteredScanRoot(state3, projectRoot, bundleDir) {
|
|
83347
|
-
const abs =
|
|
83348
|
-
const rel2 =
|
|
83349
|
-
const value = rel2 === "" || rel2.startsWith("..") ||
|
|
83350
|
-
const paths = state3.paths.map((p3) =>
|
|
83351
|
-
if (paths.includes(
|
|
83896
|
+
const abs = path123.dirname(path123.resolve(bundleDir));
|
|
83897
|
+
const rel2 = path123.relative(path123.resolve(projectRoot), abs);
|
|
83898
|
+
const value = rel2 === "" || rel2.startsWith("..") || path123.isAbsolute(rel2) ? abs : rel2;
|
|
83899
|
+
const paths = state3.paths.map((p3) => path123.normalize(p3));
|
|
83900
|
+
if (paths.includes(path123.normalize(value))) return state3;
|
|
83352
83901
|
return { ...state3, paths: [...state3.paths, value] };
|
|
83353
83902
|
}
|
|
83354
83903
|
async function setBundleEnabled(opts) {
|
|
@@ -83365,7 +83914,7 @@ async function setBundleEnabled(opts) {
|
|
|
83365
83914
|
};
|
|
83366
83915
|
const next = opts.dir ? withRegisteredScanRoot(named, opts.projectRoot, opts.dir) : named;
|
|
83367
83916
|
try {
|
|
83368
|
-
await mkdir6(
|
|
83917
|
+
await mkdir6(path123.dirname(read.path), { recursive: true });
|
|
83369
83918
|
await writeFile5(read.path, `${JSON.stringify(next, null, 2)}
|
|
83370
83919
|
`, "utf8");
|
|
83371
83920
|
} catch (err) {
|
|
@@ -83400,7 +83949,7 @@ __export(bundleCommand_exports, {
|
|
|
83400
83949
|
runPluginValidate: () => runPluginValidate
|
|
83401
83950
|
});
|
|
83402
83951
|
import { readFile as readFile14 } from "node:fs/promises";
|
|
83403
|
-
import
|
|
83952
|
+
import path124 from "node:path";
|
|
83404
83953
|
function parsePluginFlags(argv) {
|
|
83405
83954
|
const out = {};
|
|
83406
83955
|
if (argv.includes("--help") || argv.includes("-h")) out.help = true;
|
|
@@ -83413,9 +83962,9 @@ function pluginHelpText() {
|
|
|
83413
83962
|
return 'zelari-code plugin \u2014 plugin bundles (format v1)\n\nA bundle is a directory with a zelari-plugin.json manifest declaring\nskills, hooks, MCP servers and agents. Validation is static: nothing is\ninstalled, executed or fetched. Bundles are DISABLED until enabled, and\nenablement lives in the project file .zelari/plugins.json.\n\nUsage:\n zelari-code plugin validate <dir> Validate one bundle (exit 0/1)\n zelari-code plugin list [dir...] List discovered bundles + state\n zelari-code plugin enable <dir|name> Enable a bundle (validates first)\n zelari-code plugin disable <dir|name> Disable a bundle (always allowed)\n\nOptions:\n --cwd <path> Project root holding .zelari/plugins.json\n (default: current directory)\n --help, -h This text\n\n`list` scans <projectRoot>/examples/extensions plus every directory\nrecorded in "paths" of .zelari/plugins.json, then any extra dirs given.\n';
|
|
83414
83963
|
}
|
|
83415
83964
|
async function resolveBundleName(target, projectRoot, roots) {
|
|
83416
|
-
const asDir =
|
|
83965
|
+
const asDir = path124.resolve(projectRoot, target);
|
|
83417
83966
|
if (await isDir(asDir)) {
|
|
83418
|
-
const manifestPath =
|
|
83967
|
+
const manifestPath = path124.join(asDir, BUNDLE_MANIFEST_FILE);
|
|
83419
83968
|
let raw;
|
|
83420
83969
|
try {
|
|
83421
83970
|
raw = await readFile14(manifestPath, "utf8");
|
|
@@ -83473,7 +84022,7 @@ async function runPluginList(extraDirs, projectRoot) {
|
|
|
83473
84022
|
`);
|
|
83474
84023
|
const roots = [
|
|
83475
84024
|
...defaultBundleRoots(projectRoot, read.state),
|
|
83476
|
-
...extraDirs.map((d) =>
|
|
84025
|
+
...extraDirs.map((d) => path124.resolve(projectRoot, d))
|
|
83477
84026
|
];
|
|
83478
84027
|
const found = await discoverBundles(roots);
|
|
83479
84028
|
process.stdout.write(`zelari-code plugin list \u2014 project ${projectRoot}
|
|
@@ -83538,7 +84087,7 @@ async function runPluginCommand(argv) {
|
|
|
83538
84087
|
try {
|
|
83539
84088
|
const args = argv[0] === "plugin" ? argv.slice(1) : [...argv];
|
|
83540
84089
|
const opts = parsePluginFlags(args);
|
|
83541
|
-
const projectRoot =
|
|
84090
|
+
const projectRoot = path124.resolve(opts.cwd ?? process.cwd());
|
|
83542
84091
|
const positional = args.filter((a, i) => !a.startsWith("-") && args[i - 1] !== "--cwd");
|
|
83543
84092
|
const [subcommand, ...rest] = positional;
|
|
83544
84093
|
if (opts.help === true || subcommand === void 0) {
|
|
@@ -83591,19 +84140,19 @@ var init_bundleCommand = __esm({
|
|
|
83591
84140
|
});
|
|
83592
84141
|
|
|
83593
84142
|
// src/cli/commands/spineSession.ts
|
|
83594
|
-
import { existsSync as
|
|
83595
|
-
import
|
|
84143
|
+
import { existsSync as existsSync76, readFileSync as readFileSync60, readdirSync as readdirSync18 } from "node:fs";
|
|
84144
|
+
import path125 from "node:path";
|
|
83596
84145
|
function newestSpineSessionId(sessionsDir2) {
|
|
83597
84146
|
let names;
|
|
83598
84147
|
try {
|
|
83599
|
-
names = readdirSync18(sessionsDir2).filter((n) =>
|
|
84148
|
+
names = readdirSync18(sessionsDir2).filter((n) => existsSync76(path125.join(sessionsDir2, n, "events.jsonl")));
|
|
83600
84149
|
} catch {
|
|
83601
84150
|
return null;
|
|
83602
84151
|
}
|
|
83603
84152
|
if (names.length === 0) return null;
|
|
83604
84153
|
const scored = names.map((n) => {
|
|
83605
84154
|
try {
|
|
83606
|
-
const text =
|
|
84155
|
+
const text = readFileSync60(path125.join(sessionsDir2, n, "events.jsonl"), "utf-8");
|
|
83607
84156
|
const events = parseSessionLogText("events.jsonl", text).events;
|
|
83608
84157
|
return { n, ts: events[events.length - 1]?.ts ?? 0 };
|
|
83609
84158
|
} catch {
|
|
@@ -83619,16 +84168,16 @@ function resolveSpineSession(query = {}) {
|
|
|
83619
84168
|
const at = (sessionId2) => ({
|
|
83620
84169
|
sessionId: sessionId2,
|
|
83621
84170
|
sessionsDir: sessionsDir2,
|
|
83622
|
-
eventsPath:
|
|
84171
|
+
eventsPath: path125.join(sessionsDir2, sessionId2, "events.jsonl")
|
|
83623
84172
|
});
|
|
83624
84173
|
if (query.sessionId !== void 0 && query.sessionId !== "") {
|
|
83625
84174
|
const candidate = at(query.sessionId);
|
|
83626
|
-
return
|
|
84175
|
+
return existsSync76(candidate.eventsPath) ? candidate : { error: `no session spine at ${candidate.eventsPath}` };
|
|
83627
84176
|
}
|
|
83628
84177
|
const marker = getCurrentSessionId();
|
|
83629
84178
|
if (marker !== null) {
|
|
83630
84179
|
const candidate = at(marker);
|
|
83631
|
-
if (
|
|
84180
|
+
if (existsSync76(candidate.eventsPath)) return candidate;
|
|
83632
84181
|
}
|
|
83633
84182
|
const newest = newestSpineSessionId(sessionsDir2);
|
|
83634
84183
|
if (newest === null) {
|
|
@@ -83652,8 +84201,8 @@ __export(replay_exports, {
|
|
|
83652
84201
|
replayHelpText: () => replayHelpText,
|
|
83653
84202
|
runReplayCommand: () => runReplayCommand
|
|
83654
84203
|
});
|
|
83655
|
-
import { readFileSync as
|
|
83656
|
-
import
|
|
84204
|
+
import { readFileSync as readFileSync61 } from "node:fs";
|
|
84205
|
+
import path126 from "node:path";
|
|
83657
84206
|
function parseReplayFlags(argv) {
|
|
83658
84207
|
const args = argv[0] === "replay" ? argv.slice(1) : [...argv];
|
|
83659
84208
|
const out = {};
|
|
@@ -83670,7 +84219,7 @@ function replayHelpText() {
|
|
|
83670
84219
|
return "zelari-code replay \u2014 replay a session spine (read-only, no LLM, no network)\n\nRe-reads one session log with the core tolerant reader and prints what it\ncontains: tool calls, verify debt, verify runs and decision events\n(permission asks/denials, auto-approvals, jail blocks, ask_user, verify\nrequests). Nothing is written: the log it reads is never modified.\n\nUsage:\n zelari-code replay [<sessionId>] [--json]\n\nWith no <sessionId>: the current-session marker, else the newest spine.\n\nOptions:\n --json Print the full projection as JSON\n --cwd <path> Workspace root for the sessions dir\n (default: current directory;\n ZELARI_SESSIONS_DIR overrides both)\n --help, -h This text\n\nExit code: 0 on a successful replay (spine issues are reported, not\nfatal \u2014 see `zelari-code session validate` to fail on them), 1 when there\nwas nothing to replay.\n";
|
|
83671
84220
|
}
|
|
83672
84221
|
function shortPath2(p3, cwd) {
|
|
83673
|
-
const rel2 =
|
|
84222
|
+
const rel2 = path126.relative(cwd, p3);
|
|
83674
84223
|
return rel2 && !rel2.startsWith("..") ? rel2 : p3;
|
|
83675
84224
|
}
|
|
83676
84225
|
function renderReplayReport(input) {
|
|
@@ -83745,7 +84294,7 @@ async function runReplayCommand(argv) {
|
|
|
83745
84294
|
process.stdout.write(replayHelpText());
|
|
83746
84295
|
return 0;
|
|
83747
84296
|
}
|
|
83748
|
-
const cwd =
|
|
84297
|
+
const cwd = path126.resolve(opts.cwd ?? process.cwd());
|
|
83749
84298
|
const resolved = resolveSpineSession({
|
|
83750
84299
|
...opts.sessionId !== void 0 ? { sessionId: opts.sessionId } : {},
|
|
83751
84300
|
cwd
|
|
@@ -83755,7 +84304,7 @@ async function runReplayCommand(argv) {
|
|
|
83755
84304
|
`);
|
|
83756
84305
|
return 1;
|
|
83757
84306
|
}
|
|
83758
|
-
const text =
|
|
84307
|
+
const text = readFileSync61(resolved.eventsPath, "utf-8");
|
|
83759
84308
|
const report = parseSessionLogText(resolved.eventsPath, text);
|
|
83760
84309
|
const projection = buildProjection(report.events, report.issues);
|
|
83761
84310
|
if (opts.json === true) {
|
|
@@ -83808,8 +84357,8 @@ __export(session_exports, {
|
|
|
83808
84357
|
runSessionCommand: () => runSessionCommand,
|
|
83809
84358
|
sessionHelpText: () => sessionHelpText
|
|
83810
84359
|
});
|
|
83811
|
-
import { readFileSync as
|
|
83812
|
-
import
|
|
84360
|
+
import { readFileSync as readFileSync62 } from "node:fs";
|
|
84361
|
+
import path127 from "node:path";
|
|
83813
84362
|
function parseSessionFlags(argv) {
|
|
83814
84363
|
const args = argv[0] === "session" ? argv.slice(1) : [...argv];
|
|
83815
84364
|
const out = {};
|
|
@@ -83830,7 +84379,7 @@ function sessionHelpText() {
|
|
|
83830
84379
|
return "zelari-code session \u2014 inspect and curate one session spine\n\nUsage:\n zelari-code session validate [<sessionId>] [--json]\n zelari-code session waive-debt <sessionId> <taskId> [--note <text>]\n\nvalidate re-reads the log with the core tolerant reader and reports the\nReplayIssues it collected (corrupt lines, schema mismatches, seq gaps /\nduplicates / non-monotonic seq) with line, seq and reason. With no\n<sessionId>: the current-session marker, else the newest spine.\n\nwaive-debt closes ONE open verify-debt slot (a verify.debt_open with no\nmatching verify.debt_cleared) by appending the cleared event through the\nsame locked writer the runtime uses. A waiver is an OPERATOR assertion,\nnot a verification (ADR-0023) \u2014 the event carries source=waiver plus the\noptional --note, so replay can always tell the two apart.\n\nOptions:\n --json (validate) Print the report as JSON\n --note <text> (waive-debt) Why the slot is being waived\n --cwd <path> Workspace root for the sessions dir\n (default: current directory;\n ZELARI_SESSIONS_DIR overrides both)\n --help, -h This text\n\nExit codes: validate \u2014 0 clean / 1 issues (or no spine). waive-debt \u2014\n0 cleared / 1 bad invocation or unknown taskId / 2 spine locked by a\nlive writer / 3 read or write error.\n";
|
|
83831
84380
|
}
|
|
83832
84381
|
function shortPath3(p3, cwd) {
|
|
83833
|
-
const rel2 =
|
|
84382
|
+
const rel2 = path127.relative(cwd, p3);
|
|
83834
84383
|
return rel2 && !rel2.startsWith("..") ? rel2 : p3;
|
|
83835
84384
|
}
|
|
83836
84385
|
function formatIssue(issue2) {
|
|
@@ -83870,7 +84419,7 @@ async function runWaiveDebt(opts, cwd) {
|
|
|
83870
84419
|
}
|
|
83871
84420
|
let report;
|
|
83872
84421
|
try {
|
|
83873
|
-
report = parseSessionLogText(resolved.eventsPath,
|
|
84422
|
+
report = parseSessionLogText(resolved.eventsPath, readFileSync62(resolved.eventsPath, "utf-8"));
|
|
83874
84423
|
} catch (err) {
|
|
83875
84424
|
process.stderr.write(`[session] ${err instanceof Error ? err.message : String(err)}
|
|
83876
84425
|
`);
|
|
@@ -83893,7 +84442,7 @@ async function runWaiveDebt(opts, cwd) {
|
|
|
83893
84442
|
return 1;
|
|
83894
84443
|
}
|
|
83895
84444
|
const last = report.events[report.events.length - 1];
|
|
83896
|
-
const sessionDir =
|
|
84445
|
+
const sessionDir = path127.dirname(resolved.eventsPath);
|
|
83897
84446
|
let writer;
|
|
83898
84447
|
try {
|
|
83899
84448
|
writer = await SessionLogWriter.open(sessionDir, resolved.sessionId, (last?.seq ?? 0) + 1);
|
|
@@ -83950,7 +84499,7 @@ async function runSessionCommand(argv) {
|
|
|
83950
84499
|
return 1;
|
|
83951
84500
|
}
|
|
83952
84501
|
if (subcommand === "waive-debt") {
|
|
83953
|
-
return await runWaiveDebt(opts,
|
|
84502
|
+
return await runWaiveDebt(opts, path127.resolve(opts.cwd ?? process.cwd()));
|
|
83954
84503
|
}
|
|
83955
84504
|
if (subcommand !== "validate") {
|
|
83956
84505
|
process.stderr.write(`[session] unknown subcommand '${subcommand}'
|
|
@@ -83959,7 +84508,7 @@ async function runSessionCommand(argv) {
|
|
|
83959
84508
|
process.stdout.write(sessionHelpText());
|
|
83960
84509
|
return 1;
|
|
83961
84510
|
}
|
|
83962
|
-
const cwd =
|
|
84511
|
+
const cwd = path127.resolve(opts.cwd ?? process.cwd());
|
|
83963
84512
|
const resolved = resolveSpineSession({
|
|
83964
84513
|
...opts.sessionId !== void 0 ? { sessionId: opts.sessionId } : {},
|
|
83965
84514
|
cwd
|
|
@@ -83969,7 +84518,7 @@ async function runSessionCommand(argv) {
|
|
|
83969
84518
|
`);
|
|
83970
84519
|
return 1;
|
|
83971
84520
|
}
|
|
83972
|
-
const text =
|
|
84521
|
+
const text = readFileSync62(resolved.eventsPath, "utf-8");
|
|
83973
84522
|
const report = parseSessionLogText(resolved.eventsPath, text);
|
|
83974
84523
|
const last = report.events[report.events.length - 1];
|
|
83975
84524
|
if (opts.json === true) {
|
|
@@ -84103,7 +84652,7 @@ __export(evolve_exports2, {
|
|
|
84103
84652
|
parseEvolveFlags: () => parseEvolveFlags,
|
|
84104
84653
|
runEvolveCommand: () => runEvolveCommand
|
|
84105
84654
|
});
|
|
84106
|
-
import { readFileSync as
|
|
84655
|
+
import { readFileSync as readFileSync63 } from "node:fs";
|
|
84107
84656
|
function asString5(value) {
|
|
84108
84657
|
return typeof value === "string" ? value : "";
|
|
84109
84658
|
}
|
|
@@ -84195,9 +84744,9 @@ function verdictLine(v) {
|
|
|
84195
84744
|
return ` [hold ] ${v.reason}`;
|
|
84196
84745
|
}
|
|
84197
84746
|
const at = `@seq ${v.proposal.decisiveSeq}`;
|
|
84198
|
-
const
|
|
84747
|
+
const path128 = v.proposal.path !== void 0 ? ` \xB7 ${v.proposal.path}` : "";
|
|
84199
84748
|
const saved = v.action === "shadow" ? ` \xB7 saves ~${v.proposal.estSavedCalls} call` : "";
|
|
84200
|
-
return ` [${v.action === "shadow" ? "shadow" : "hold "}] ${v.proposal.kind} ${at}${
|
|
84749
|
+
return ` [${v.action === "shadow" ? "shadow" : "hold "}] ${v.proposal.kind} ${at}${path128}${saved}${v.action === "shadow" ? "" : ` \u2014 ${v.reason}`}`;
|
|
84201
84750
|
}
|
|
84202
84751
|
async function runEvolveCommand(argv) {
|
|
84203
84752
|
const flags = parseEvolveFlags(argv);
|
|
@@ -84221,7 +84770,7 @@ ${evolveHelpText()}`);
|
|
|
84221
84770
|
}
|
|
84222
84771
|
let parsed;
|
|
84223
84772
|
try {
|
|
84224
|
-
parsed = parseSessionLogText("events.jsonl",
|
|
84773
|
+
parsed = parseSessionLogText("events.jsonl", readFileSync63(target.eventsPath, "utf-8"));
|
|
84225
84774
|
} catch (err) {
|
|
84226
84775
|
process.stderr.write(
|
|
84227
84776
|
`[zelari-code evolve] cannot read ${target.eventsPath}: ${err instanceof Error ? err.message : String(err)}
|
|
@@ -88255,6 +88804,7 @@ init_verificationBridge();
|
|
|
88255
88804
|
init_completionProof();
|
|
88256
88805
|
init_opsKnowledge();
|
|
88257
88806
|
init_repeatCheck();
|
|
88807
|
+
init_onePager();
|
|
88258
88808
|
init_verifyStatus();
|
|
88259
88809
|
init_nativeVerification();
|
|
88260
88810
|
init_spineTelemetry();
|
|
@@ -88625,10 +89175,16 @@ _(${req.context})_` : "") + "\n\u2192 scegli dalla lista (il turno continua dopo
|
|
|
88625
89175
|
const cwd = process.cwd();
|
|
88626
89176
|
const requestSnapshot = getRequestSnapshotWithUsage(sessionId2);
|
|
88627
89177
|
await writerRef.current?.spine?.beginResourceTurn();
|
|
89178
|
+
const onePager = await buildOnePager({
|
|
89179
|
+
cwd,
|
|
89180
|
+
memory: memoryService ?? null,
|
|
89181
|
+
skipCompactRecap: true
|
|
89182
|
+
});
|
|
88628
89183
|
const modelContext = await buildModelContext({
|
|
88629
89184
|
fallbackHistory: historyForModel,
|
|
88630
89185
|
session: writerRef.current?.spine ?? null,
|
|
88631
89186
|
resourceSnapshot: writerRef.current?.spine?.latestResourceSnapshot() ?? null,
|
|
89187
|
+
volatileOnePager: onePager,
|
|
88632
89188
|
phase: workPhase,
|
|
88633
89189
|
model: getActiveModel(),
|
|
88634
89190
|
provider: envConfig?.providerId ?? (localCli || "local"),
|
|
@@ -88881,9 +89437,12 @@ _(${req.context})_` : "") + "\n\u2192 scegli dalla lista (il turno continua dopo
|
|
|
88881
89437
|
),
|
|
88882
89438
|
maxRecoveries: 2
|
|
88883
89439
|
},
|
|
88884
|
-
requestTail: () =>
|
|
88885
|
-
|
|
88886
|
-
|
|
89440
|
+
requestTail: () => [
|
|
89441
|
+
...resourceStatusTail(
|
|
89442
|
+
writerRef.current?.spine?.latestResourceSnapshot() ?? null
|
|
89443
|
+
),
|
|
89444
|
+
...onePager
|
|
89445
|
+
],
|
|
88887
89446
|
// 2.6 Phase 3: host-owned pre-dispatch resource gate via the spine
|
|
88888
89447
|
// mirror (doc section 11.3). Degrade-and-stop (null gate = allow).
|
|
88889
89448
|
// 2.6.1 (plan §13): argument-aware — bash is essential only when
|
|
@@ -89470,9 +90029,15 @@ async function dispatchCouncilPromptImpl(text, deps, overrides = {}) {
|
|
|
89470
90029
|
const anchored = maybeAnchorShortAnswer(text);
|
|
89471
90030
|
const effectiveText = anchored ?? text;
|
|
89472
90031
|
await writerRef.current?.spine?.beginResourceTurn();
|
|
90032
|
+
const onePager = await buildOnePager({
|
|
90033
|
+
cwd: process.cwd(),
|
|
90034
|
+
memory: null,
|
|
90035
|
+
skipCompactRecap: true
|
|
90036
|
+
});
|
|
89473
90037
|
const councilContext = await buildModelContext({
|
|
89474
90038
|
fallbackHistory: getHistory(),
|
|
89475
90039
|
session: writerRef.current?.spine ?? null,
|
|
90040
|
+
volatileOnePager: onePager,
|
|
89476
90041
|
phase: getPhase(),
|
|
89477
90042
|
model: envConfig.model,
|
|
89478
90043
|
provider: envConfig.providerId,
|
|
@@ -90490,10 +91055,10 @@ init_ledger();
|
|
|
90490
91055
|
|
|
90491
91056
|
// src/cli/evolution/proposals.ts
|
|
90492
91057
|
import { existsSync as existsSync60, readFileSync as readFileSync49 } from "node:fs";
|
|
90493
|
-
import
|
|
90494
|
-
var PROPOSALS_REL =
|
|
91058
|
+
import path94 from "node:path";
|
|
91059
|
+
var PROPOSALS_REL = path94.join(".zelari", "evolution", "proposals.jsonl");
|
|
90495
91060
|
function proposalsPath(cwd) {
|
|
90496
|
-
return
|
|
91061
|
+
return path94.join(cwd, PROPOSALS_REL);
|
|
90497
91062
|
}
|
|
90498
91063
|
function readProposalStore(cwd) {
|
|
90499
91064
|
const file2 = proposalsPath(cwd);
|
|
@@ -90680,15 +91245,15 @@ function handleStatusLine(args, opts = {}) {
|
|
|
90680
91245
|
init_session();
|
|
90681
91246
|
init_sessionManager();
|
|
90682
91247
|
import { existsSync as existsSync61, readFileSync as readFileSync50, readdirSync as readdirSync13 } from "node:fs";
|
|
90683
|
-
import
|
|
91248
|
+
import path95 from "node:path";
|
|
90684
91249
|
var FILE_TOOLS2 = /* @__PURE__ */ new Set(["read_file", "write_file", "edit"]);
|
|
90685
91250
|
function newestSessionId(sessionsDir2) {
|
|
90686
91251
|
try {
|
|
90687
|
-
const names = readdirSync13(sessionsDir2).filter((n) => existsSync61(
|
|
91252
|
+
const names = readdirSync13(sessionsDir2).filter((n) => existsSync61(path95.join(sessionsDir2, n, "events.jsonl")));
|
|
90688
91253
|
if (names.length === 0) return null;
|
|
90689
91254
|
const scored = names.map((n) => {
|
|
90690
91255
|
try {
|
|
90691
|
-
const text = readFileSync50(
|
|
91256
|
+
const text = readFileSync50(path95.join(sessionsDir2, n, "events.jsonl"), "utf-8");
|
|
90692
91257
|
const last = parseSessionLogText("events.jsonl", text).events;
|
|
90693
91258
|
return { n, ts: last[last.length - 1]?.ts ?? 0 };
|
|
90694
91259
|
} catch {
|
|
@@ -90702,7 +91267,7 @@ function newestSessionId(sessionsDir2) {
|
|
|
90702
91267
|
}
|
|
90703
91268
|
}
|
|
90704
91269
|
function shortPath(p3, cwd) {
|
|
90705
|
-
const rel2 =
|
|
91270
|
+
const rel2 = path95.relative(cwd, p3);
|
|
90706
91271
|
return rel2 && !rel2.startsWith("..") ? rel2 : p3;
|
|
90707
91272
|
}
|
|
90708
91273
|
function render(report, cwd, sessionId2) {
|
|
@@ -90861,7 +91426,7 @@ function buildSessionReport(opts = {}) {
|
|
|
90861
91426
|
const cwd = opts.cwd ?? process.cwd();
|
|
90862
91427
|
const sessionsDir2 = resolveSessionsDir({ workspaceRoot: cwd, env: opts.env });
|
|
90863
91428
|
const marker = opts.sessionId ?? getCurrentSessionId() ?? void 0;
|
|
90864
|
-
const marked = marker ?
|
|
91429
|
+
const marked = marker ? path95.join(sessionsDir2, marker, "events.jsonl") : null;
|
|
90865
91430
|
const sessionId2 = marker && marked && existsSync61(marked) ? marker : newestSessionId(sessionsDir2);
|
|
90866
91431
|
if (!sessionId2) {
|
|
90867
91432
|
return {
|
|
@@ -90870,7 +91435,7 @@ function buildSessionReport(opts = {}) {
|
|
|
90870
91435
|
markdown: `no session spine found under ${sessionsDir2} \u2014 nothing to report (this is not an error).`
|
|
90871
91436
|
};
|
|
90872
91437
|
}
|
|
90873
|
-
const eventsPath =
|
|
91438
|
+
const eventsPath = path95.join(sessionsDir2, sessionId2, "events.jsonl");
|
|
90874
91439
|
let text;
|
|
90875
91440
|
try {
|
|
90876
91441
|
text = readFileSync50(eventsPath, "utf-8");
|
|
@@ -90964,7 +91529,7 @@ function handleSlashCommand(text, availableSkills) {
|
|
|
90964
91529
|
/resume-mission \u2014 resume the persisted mission (.zelari/mission-state.json; TUI twin of --resume-mission)
|
|
90965
91530
|
/council-feedback <memberId> <1-5> [note] \u2014 rate a council member for future ranking (Task I.2)
|
|
90966
91531
|
/promote-member <memberId> \u2014 promote a council member to a standalone skill (v3-K)
|
|
90967
|
-
/memory [stats|search|show|related|history|retract|forget|consolidate|index|promote|doctor|export|audit] \u2014 inspect native project memory
|
|
91532
|
+
/memory [stats|search|show|related|history|retract|forget|consolidate|dream|index|promote|doctor|export|audit] \u2014 inspect native project memory
|
|
90968
91533
|
/update [--yes|-y] \u2014 check for zelari-code updates; --yes performs the update (v3-N)
|
|
90969
91534
|
/plugins \u2014 list optional tool plugins (Playwright, eslint, ruff, LSP servers)
|
|
90970
91535
|
/plugins install <id> \u2014 install a plugin now (e.g. /plugins install eslint)
|
|
@@ -91780,7 +92345,7 @@ async function handleUndo(ctx, warningMessage, doConfirm) {
|
|
|
91780
92345
|
init_session();
|
|
91781
92346
|
init_sessionManager();
|
|
91782
92347
|
init_messageHelpers();
|
|
91783
|
-
import
|
|
92348
|
+
import path96 from "node:path";
|
|
91784
92349
|
var EMPTY_FIELDS = { name: "", engine: "", cwd: "" };
|
|
91785
92350
|
function sessionSearchText(fields) {
|
|
91786
92351
|
return [fields.name, fields.engine, fields.cwd].map((s) => s.trim()).filter((s) => s.length > 0).join(" ");
|
|
@@ -91796,7 +92361,7 @@ function shortenPath(p3, max = 28) {
|
|
|
91796
92361
|
}
|
|
91797
92362
|
async function readSessionSearchFields(id3, sessionsDir2 = resolveSessionsDir()) {
|
|
91798
92363
|
try {
|
|
91799
|
-
const report = await readSessionLog(
|
|
92364
|
+
const report = await readSessionLog(path96.join(sessionsDir2, id3, "events.jsonl"));
|
|
91800
92365
|
const started = report.events.find((e) => e.kind === "session.started");
|
|
91801
92366
|
const firstUser = report.events.find((e) => e.kind === "user.message");
|
|
91802
92367
|
const data = started?.data ?? {};
|
|
@@ -92105,8 +92670,8 @@ init_howWeTest();
|
|
|
92105
92670
|
init_promotion();
|
|
92106
92671
|
init_repeatCheck();
|
|
92107
92672
|
init_worldModel();
|
|
92108
|
-
import { promises as
|
|
92109
|
-
import * as
|
|
92673
|
+
import { promises as fs39 } from "node:fs";
|
|
92674
|
+
import * as path97 from "node:path";
|
|
92110
92675
|
var USAGE = [
|
|
92111
92676
|
"/memory \u2014 backend summary",
|
|
92112
92677
|
"/memory search <query>",
|
|
@@ -92116,6 +92681,7 @@ var USAGE = [
|
|
|
92116
92681
|
"/memory retract <id> [reason]",
|
|
92117
92682
|
"/memory forget <id> --yes",
|
|
92118
92683
|
"/memory consolidate [query]",
|
|
92684
|
+
"/memory dream [--min-candidates N] \u2014 consolidate pending candidates into durable nodes",
|
|
92119
92685
|
"/memory index [--force]",
|
|
92120
92686
|
"/memory promote <id> \u2014 append durable knowledge to managed AGENTS.md section",
|
|
92121
92687
|
'/memory promote con-<fp> --as-check --command "<cmd>" [--expect-exit N] \u2014 append a WorldCheck',
|
|
@@ -92131,25 +92697,34 @@ function sourceLine(source2) {
|
|
|
92131
92697
|
const entries = Object.entries(source2).filter(([, value]) => value !== void 0 && value !== "");
|
|
92132
92698
|
return entries.length ? entries.map(([key, value]) => `${key}=${value}`).join(" \xB7 ") : "unknown";
|
|
92133
92699
|
}
|
|
92700
|
+
function parseMinCandidates(args) {
|
|
92701
|
+
const flagIndex = args.findIndex(
|
|
92702
|
+
(arg) => arg === "--min-candidates" || arg === "--min-occurrences"
|
|
92703
|
+
);
|
|
92704
|
+
const raw = flagIndex >= 0 ? args[flagIndex + 1] : args.find((arg) => /^\d+$/.test(arg));
|
|
92705
|
+
if (raw === void 0) return void 0;
|
|
92706
|
+
const value = Number.parseInt(raw, 10);
|
|
92707
|
+
return Number.isFinite(value) && value > 0 ? value : void 0;
|
|
92708
|
+
}
|
|
92134
92709
|
function isInside(root, target) {
|
|
92135
|
-
const relative6 =
|
|
92136
|
-
return relative6 === "" || !relative6.startsWith("..") && !
|
|
92710
|
+
const relative6 = path97.relative(root, target);
|
|
92711
|
+
return relative6 === "" || !relative6.startsWith("..") && !path97.isAbsolute(relative6);
|
|
92137
92712
|
}
|
|
92138
92713
|
async function safeExportPath(cwd, requested) {
|
|
92139
|
-
const lexicalRoot =
|
|
92140
|
-
const root = await
|
|
92141
|
-
const fallback =
|
|
92142
|
-
const target = requested?.trim() ?
|
|
92714
|
+
const lexicalRoot = path97.resolve(cwd);
|
|
92715
|
+
const root = await fs39.realpath(lexicalRoot).catch(() => lexicalRoot);
|
|
92716
|
+
const fallback = path97.join(root, ".zelari", "memory", `export-${Date.now()}.json`);
|
|
92717
|
+
const target = requested?.trim() ? path97.resolve(root, requested.trim()) : fallback;
|
|
92143
92718
|
if (!isInside(root, target)) {
|
|
92144
92719
|
throw new Error("Export path must stay inside the active project.");
|
|
92145
92720
|
}
|
|
92146
|
-
const parent =
|
|
92147
|
-
const relativeParent =
|
|
92721
|
+
const parent = path97.dirname(target);
|
|
92722
|
+
const relativeParent = path97.relative(root, parent);
|
|
92148
92723
|
let cursor = root;
|
|
92149
|
-
for (const segment of relativeParent.split(
|
|
92150
|
-
cursor =
|
|
92724
|
+
for (const segment of relativeParent.split(path97.sep).filter(Boolean)) {
|
|
92725
|
+
cursor = path97.join(cursor, segment);
|
|
92151
92726
|
try {
|
|
92152
|
-
const stat9 = await
|
|
92727
|
+
const stat9 = await fs39.lstat(cursor);
|
|
92153
92728
|
if (stat9.isSymbolicLink()) {
|
|
92154
92729
|
throw new Error("Export path must not traverse a symbolic link.");
|
|
92155
92730
|
}
|
|
@@ -92159,7 +92734,7 @@ async function safeExportPath(cwd, requested) {
|
|
|
92159
92734
|
}
|
|
92160
92735
|
}
|
|
92161
92736
|
try {
|
|
92162
|
-
if ((await
|
|
92737
|
+
if ((await fs39.lstat(target)).isSymbolicLink()) {
|
|
92163
92738
|
throw new Error("Export target must not be a symbolic link.");
|
|
92164
92739
|
}
|
|
92165
92740
|
} catch (error51) {
|
|
@@ -92288,6 +92863,15 @@ ${message}` : message
|
|
|
92288
92863
|
emit(`[memory] consolidation scanned ${result.scanned} candidate(s), created ${result.created.length} durable node(s), archived ${result.archivedSourceIds.length} source duplicate(s).`);
|
|
92289
92864
|
return;
|
|
92290
92865
|
}
|
|
92866
|
+
case "dream": {
|
|
92867
|
+
const minOccurrences = parseMinCandidates(args);
|
|
92868
|
+
const result = await memory.consolidate({
|
|
92869
|
+
source: { agent: "user-cli-dream" },
|
|
92870
|
+
...minOccurrences === void 0 ? {} : { minOccurrences }
|
|
92871
|
+
});
|
|
92872
|
+
emit(`[memory dream] consolidated ${result.scanned} candidate(s), created ${result.created.length} durable node(s), archived ${result.archivedSourceIds.length} source duplicate(s).`);
|
|
92873
|
+
return;
|
|
92874
|
+
}
|
|
92291
92875
|
case "index": {
|
|
92292
92876
|
const result = memory.index ? await memory.index({ force: args.includes("--force") || args.includes("-f") }) : { status: "disabled", scanned: 0, indexed: 0, skipped: 0, failed: 0, interrupted: false };
|
|
92293
92877
|
emit(
|
|
@@ -92350,13 +92934,13 @@ ${message}` : message
|
|
|
92350
92934
|
}
|
|
92351
92935
|
case "export": {
|
|
92352
92936
|
const target = await safeExportPath(ctx.cwd, args.join(" ").trim() || void 0);
|
|
92353
|
-
await
|
|
92354
|
-
const root = await
|
|
92355
|
-
const realParent = await
|
|
92937
|
+
await fs39.mkdir(path97.dirname(target), { recursive: true });
|
|
92938
|
+
const root = await fs39.realpath(ctx.cwd).catch(() => path97.resolve(ctx.cwd));
|
|
92939
|
+
const realParent = await fs39.realpath(path97.dirname(target));
|
|
92356
92940
|
if (!isInside(root, realParent)) {
|
|
92357
92941
|
throw new Error("Export path resolves outside the active project.");
|
|
92358
92942
|
}
|
|
92359
|
-
await
|
|
92943
|
+
await fs39.writeFile(target, JSON.stringify(await memory.export(), null, 2) + "\n", "utf8");
|
|
92360
92944
|
emit(`[memory] export written to ${target}`);
|
|
92361
92945
|
return;
|
|
92362
92946
|
}
|
|
@@ -92761,13 +93345,13 @@ ${digest}
|
|
|
92761
93345
|
init_auditLogger();
|
|
92762
93346
|
init_toolRegistry();
|
|
92763
93347
|
init_messageHelpers();
|
|
92764
|
-
import { promises as
|
|
93348
|
+
import { promises as fs41 } from "node:fs";
|
|
92765
93349
|
|
|
92766
93350
|
// src/cli/tools/krakenCsvFanout.ts
|
|
92767
93351
|
init_zod();
|
|
92768
93352
|
init_taskTool();
|
|
92769
|
-
import { promises as
|
|
92770
|
-
import
|
|
93353
|
+
import { promises as fs40 } from "node:fs";
|
|
93354
|
+
import path98 from "node:path";
|
|
92771
93355
|
import { randomBytes as randomBytes6 } from "node:crypto";
|
|
92772
93356
|
var CsvFanoutArgsSchema = external_exports.object({
|
|
92773
93357
|
csv_path: external_exports.string().min(1),
|
|
@@ -92788,7 +93372,7 @@ var CsvFanoutArgsSchema = external_exports.object({
|
|
|
92788
93372
|
max_runtime_seconds: external_exports.number().int().positive().optional()
|
|
92789
93373
|
});
|
|
92790
93374
|
async function readCsv(filePath) {
|
|
92791
|
-
const text = await
|
|
93375
|
+
const text = await fs40.readFile(filePath, "utf8");
|
|
92792
93376
|
return parseCsv(text);
|
|
92793
93377
|
}
|
|
92794
93378
|
function parseCsv(text) {
|
|
@@ -92861,8 +93445,8 @@ function resolveMaxConcurrency(env = process.env) {
|
|
|
92861
93445
|
}
|
|
92862
93446
|
async function runCsvFanout(args, deps, opts) {
|
|
92863
93447
|
const start = Date.now();
|
|
92864
|
-
const absCsv =
|
|
92865
|
-
const absOut =
|
|
93448
|
+
const absCsv = path98.isAbsolute(args.csv_path) ? args.csv_path : path98.join(opts.parentCwd, args.csv_path);
|
|
93449
|
+
const absOut = path98.isAbsolute(args.output_csv_path) ? args.output_csv_path : path98.join(opts.parentCwd, args.output_csv_path);
|
|
92866
93450
|
const { headers: headers3, rows } = await readCsv(absCsv);
|
|
92867
93451
|
if (headers3.length === 0) {
|
|
92868
93452
|
throw new Error(`kraken_csv_fanout: ${absCsv} is empty`);
|
|
@@ -92918,7 +93502,7 @@ async function runCsvFanout(args, deps, opts) {
|
|
|
92918
93502
|
errored += 1;
|
|
92919
93503
|
errors.push(`${row[args.id_column] ?? i}: ${res.error}`);
|
|
92920
93504
|
}
|
|
92921
|
-
await
|
|
93505
|
+
await fs40.mkdir(path98.dirname(absOut), { recursive: true });
|
|
92922
93506
|
await queueWrite(serializeCsv(outHeaders, outputRecords));
|
|
92923
93507
|
}
|
|
92924
93508
|
}
|
|
@@ -92940,8 +93524,8 @@ async function runCsvFanout(args, deps, opts) {
|
|
|
92940
93524
|
}
|
|
92941
93525
|
async function atomicWrite(file2, contents) {
|
|
92942
93526
|
const tmp = `${file2}.${process.pid}.${Date.now()}.${randomBytes6(6).toString("hex")}.tmp`;
|
|
92943
|
-
await
|
|
92944
|
-
await
|
|
93527
|
+
await fs40.writeFile(tmp, contents, "utf8");
|
|
93528
|
+
await fs40.rename(tmp, file2);
|
|
92945
93529
|
}
|
|
92946
93530
|
|
|
92947
93531
|
// src/cli/slashHandlers/krakenFanout.ts
|
|
@@ -93039,7 +93623,7 @@ async function handleKrakenFanout(ctx, raw) {
|
|
|
93039
93623
|
}
|
|
93040
93624
|
const absCsv = isAbsolute4(parsed.args.csv_path) ? parsed.args.csv_path : joinPath(ctx.cwd, parsed.args.csv_path);
|
|
93041
93625
|
try {
|
|
93042
|
-
await
|
|
93626
|
+
await fs41.access(absCsv);
|
|
93043
93627
|
} catch {
|
|
93044
93628
|
appendSystem(ctx.setMessages, `[kraken fanout] source CSV not found: ${absCsv}`);
|
|
93045
93629
|
return;
|
|
@@ -93112,8 +93696,8 @@ function splitArgs(s) {
|
|
|
93112
93696
|
|
|
93113
93697
|
// src/cli/slashHandlers/krakenWorkbench.ts
|
|
93114
93698
|
init_messageHelpers();
|
|
93115
|
-
import { promises as
|
|
93116
|
-
import
|
|
93699
|
+
import { promises as fs42 } from "node:fs";
|
|
93700
|
+
import path99 from "node:path";
|
|
93117
93701
|
|
|
93118
93702
|
// src/cli/kraken/workbenchView.ts
|
|
93119
93703
|
var EMPTY = {
|
|
@@ -93230,15 +93814,15 @@ function formatWorkbenchForTerminal(p3) {
|
|
|
93230
93814
|
|
|
93231
93815
|
// src/cli/slashHandlers/krakenWorkbench.ts
|
|
93232
93816
|
async function handleKrakenWorkbench(ctx) {
|
|
93233
|
-
const dir =
|
|
93817
|
+
const dir = path99.join(ctx.cwd, ".zelari", "radio");
|
|
93234
93818
|
let latest = null;
|
|
93235
93819
|
let latestMtime = 0;
|
|
93236
93820
|
try {
|
|
93237
|
-
const files = await
|
|
93821
|
+
const files = await fs42.readdir(dir);
|
|
93238
93822
|
for (const f of files) {
|
|
93239
93823
|
if (!f.startsWith("workbench-") || !f.endsWith(".md")) continue;
|
|
93240
|
-
const full =
|
|
93241
|
-
const stat9 = await
|
|
93824
|
+
const full = path99.join(dir, f);
|
|
93825
|
+
const stat9 = await fs42.stat(full);
|
|
93242
93826
|
if (stat9.mtimeMs > latestMtime) {
|
|
93243
93827
|
latestMtime = stat9.mtimeMs;
|
|
93244
93828
|
latest = full;
|
|
@@ -93250,14 +93834,14 @@ async function handleKrakenWorkbench(ctx) {
|
|
|
93250
93834
|
appendSystem(ctx.setMessages, "[kraken workbench] no workbench file found (.zelari/radio/workbench-*.md)");
|
|
93251
93835
|
return;
|
|
93252
93836
|
}
|
|
93253
|
-
const content = await
|
|
93837
|
+
const content = await fs42.readFile(latest, "utf8");
|
|
93254
93838
|
const parsed = parseWorkbench(content);
|
|
93255
93839
|
const rendered = formatWorkbenchForTerminal(parsed);
|
|
93256
93840
|
if (!rendered.trim()) {
|
|
93257
|
-
appendSystem(ctx.setMessages, `[kraken workbench] ${
|
|
93841
|
+
appendSystem(ctx.setMessages, `[kraken workbench] ${path99.basename(latest)}: (no nodes / no events yet)`);
|
|
93258
93842
|
return;
|
|
93259
93843
|
}
|
|
93260
|
-
appendSystem(ctx.setMessages, `[kraken workbench] ${
|
|
93844
|
+
appendSystem(ctx.setMessages, `[kraken workbench] ${path99.basename(latest)}:
|
|
93261
93845
|
${rendered}`);
|
|
93262
93846
|
}
|
|
93263
93847
|
|
|
@@ -93576,20 +94160,20 @@ ${result.output.split("\n").slice(-8).join("\n")}` : "";
|
|
|
93576
94160
|
// src/cli/slashHandlers/promoteMember.ts
|
|
93577
94161
|
init_messageHelpers();
|
|
93578
94162
|
init_paths();
|
|
93579
|
-
import { promises as
|
|
93580
|
-
import
|
|
94163
|
+
import { promises as fs43 } from "node:fs";
|
|
94164
|
+
import path102 from "node:path";
|
|
93581
94165
|
async function handlePromoteMember(ctx, memberId) {
|
|
93582
94166
|
try {
|
|
93583
94167
|
const { promoteMember: promoteMember2 } = await Promise.resolve().then(() => (init_council(), council_exports));
|
|
93584
94168
|
const { skill, markdown } = promoteMember2(memberId);
|
|
93585
94169
|
const skillDir = skillsDir();
|
|
93586
|
-
await
|
|
93587
|
-
const filePath =
|
|
93588
|
-
const previous = await
|
|
93589
|
-
const { createHash:
|
|
93590
|
-
const sha = (s) =>
|
|
94170
|
+
await fs43.mkdir(skillDir, { recursive: true });
|
|
94171
|
+
const filePath = path102.join(skillDir, `${skill.id}.md`);
|
|
94172
|
+
const previous = await fs43.readFile(filePath, "utf8").catch(() => null);
|
|
94173
|
+
const { createHash: createHash29 } = await import("node:crypto");
|
|
94174
|
+
const sha = (s) => createHash29("sha256").update(s, "utf8").digest("hex");
|
|
93591
94175
|
const lineage = `<!-- lineage: genome=sha256:${sha(markdown)} parent=${previous ? `sha256:${sha(previous)}` : "none"} promotedBy=user promotedAt=${(/* @__PURE__ */ new Date()).toISOString()} -->`;
|
|
93592
|
-
await
|
|
94176
|
+
await fs43.writeFile(filePath, `${markdown}
|
|
93593
94177
|
${lineage}
|
|
93594
94178
|
`, "utf8");
|
|
93595
94179
|
appendSystem(
|
|
@@ -93609,8 +94193,8 @@ ${lineage}
|
|
|
93609
94193
|
|
|
93610
94194
|
// src/cli/branchManager.ts
|
|
93611
94195
|
init_paths();
|
|
93612
|
-
import { promises as
|
|
93613
|
-
import
|
|
94196
|
+
import { promises as fs44, existsSync as existsSync65, readFileSync as readFileSync52, writeFileSync as writeFileSync27, mkdirSync as mkdirSync24, statSync as statSync10, rmSync as rmSync5 } from "node:fs";
|
|
94197
|
+
import path103 from "node:path";
|
|
93614
94198
|
var META_FILENAME = "meta.json";
|
|
93615
94199
|
var SESSIONS_SUBDIR = "sessions";
|
|
93616
94200
|
function getBranchesBaseDir() {
|
|
@@ -93620,13 +94204,13 @@ function getSessionsBaseDir() {
|
|
|
93620
94204
|
return sessionsDir();
|
|
93621
94205
|
}
|
|
93622
94206
|
function branchPathFor(name, baseDir) {
|
|
93623
|
-
return
|
|
94207
|
+
return path103.join(baseDir, name);
|
|
93624
94208
|
}
|
|
93625
94209
|
function metaPathFor(name, baseDir) {
|
|
93626
|
-
return
|
|
94210
|
+
return path103.join(baseDir, name, META_FILENAME);
|
|
93627
94211
|
}
|
|
93628
94212
|
function sessionsPathFor(name, baseDir) {
|
|
93629
|
-
return
|
|
94213
|
+
return path103.join(baseDir, name, SESSIONS_SUBDIR);
|
|
93630
94214
|
}
|
|
93631
94215
|
function readBranchMeta(name, baseDir) {
|
|
93632
94216
|
const metaPath = metaPathFor(name, baseDir);
|
|
@@ -93651,13 +94235,13 @@ function readBranchMeta(name, baseDir) {
|
|
|
93651
94235
|
}
|
|
93652
94236
|
function writeBranchMeta(name, baseDir, meta3) {
|
|
93653
94237
|
const metaPath = metaPathFor(name, baseDir);
|
|
93654
|
-
mkdirSync24(
|
|
94238
|
+
mkdirSync24(path103.dirname(metaPath), { recursive: true });
|
|
93655
94239
|
writeFileSync27(metaPath, JSON.stringify(meta3, null, 2), "utf-8");
|
|
93656
94240
|
}
|
|
93657
94241
|
async function countSessions(name, baseDir) {
|
|
93658
94242
|
const sessionsPath = sessionsPathFor(name, baseDir);
|
|
93659
94243
|
try {
|
|
93660
|
-
const entries = await
|
|
94244
|
+
const entries = await fs44.readdir(sessionsPath);
|
|
93661
94245
|
return entries.filter((e) => e.endsWith(".jsonl")).length;
|
|
93662
94246
|
} catch (err) {
|
|
93663
94247
|
if (err.code === "ENOENT") return 0;
|
|
@@ -93702,15 +94286,15 @@ async function createBranch(name, fromSessionId, baseDir = getBranchesBaseDir(),
|
|
|
93702
94286
|
if (branchExists(name, baseDir)) {
|
|
93703
94287
|
throw new BranchAlreadyExistsError(name);
|
|
93704
94288
|
}
|
|
93705
|
-
const sourcePath =
|
|
94289
|
+
const sourcePath = path103.join(sessionsBaseDir, `${fromSessionId}.jsonl`);
|
|
93706
94290
|
if (!existsSync65(sourcePath)) {
|
|
93707
94291
|
throw new SessionNotFoundError(`Source session "${fromSessionId}" not found at ${sourcePath}`);
|
|
93708
94292
|
}
|
|
93709
94293
|
const branchPath = branchPathFor(name, baseDir);
|
|
93710
94294
|
const branchSessionsPath = sessionsPathFor(name, baseDir);
|
|
93711
94295
|
mkdirSync24(branchSessionsPath, { recursive: true });
|
|
93712
|
-
const destPath =
|
|
93713
|
-
await
|
|
94296
|
+
const destPath = path103.join(branchSessionsPath, `${fromSessionId}.jsonl`);
|
|
94297
|
+
await fs44.copyFile(sourcePath, destPath);
|
|
93714
94298
|
const meta3 = {
|
|
93715
94299
|
name,
|
|
93716
94300
|
createdAt: Date.now(),
|
|
@@ -93728,7 +94312,7 @@ async function createBranch(name, fromSessionId, baseDir = getBranchesBaseDir(),
|
|
|
93728
94312
|
async function listBranches(baseDir = getBranchesBaseDir()) {
|
|
93729
94313
|
let entries;
|
|
93730
94314
|
try {
|
|
93731
|
-
entries = await
|
|
94315
|
+
entries = await fs44.readdir(baseDir);
|
|
93732
94316
|
} catch (err) {
|
|
93733
94317
|
if (err.code === "ENOENT") return [];
|
|
93734
94318
|
throw err;
|
|
@@ -93812,26 +94396,26 @@ async function handleBranchCheckout(ctx, branchName) {
|
|
|
93812
94396
|
|
|
93813
94397
|
// src/cli/slashHandlers/workspace.ts
|
|
93814
94398
|
init_messageHelpers();
|
|
93815
|
-
import { promises as
|
|
93816
|
-
import
|
|
94399
|
+
import { promises as fs45 } from "node:fs";
|
|
94400
|
+
import path104 from "node:path";
|
|
93817
94401
|
async function handleWorkspaceShow(ctx, what) {
|
|
93818
94402
|
try {
|
|
93819
|
-
const zelari =
|
|
94403
|
+
const zelari = path104.join(process.cwd(), ".zelari");
|
|
93820
94404
|
let content;
|
|
93821
94405
|
switch (what) {
|
|
93822
94406
|
case "plan": {
|
|
93823
|
-
const planPath =
|
|
94407
|
+
const planPath = path104.join(zelari, "plan.md");
|
|
93824
94408
|
try {
|
|
93825
|
-
content = await
|
|
94409
|
+
content = await fs45.readFile(planPath, "utf-8");
|
|
93826
94410
|
} catch {
|
|
93827
94411
|
content = "(no plan.md yet \u2014 run a council session first)";
|
|
93828
94412
|
}
|
|
93829
94413
|
break;
|
|
93830
94414
|
}
|
|
93831
94415
|
case "decisions": {
|
|
93832
|
-
const decisionsDir =
|
|
94416
|
+
const decisionsDir = path104.join(zelari, "decisions");
|
|
93833
94417
|
try {
|
|
93834
|
-
const files = (await
|
|
94418
|
+
const files = (await fs45.readdir(decisionsDir)).filter((f) => f.endsWith(".md")).sort();
|
|
93835
94419
|
if (files.length === 0) {
|
|
93836
94420
|
content = "(no ADRs yet \u2014 invoke /council to generate some)";
|
|
93837
94421
|
} else {
|
|
@@ -93839,7 +94423,7 @@ async function handleWorkspaceShow(ctx, what) {
|
|
|
93839
94423
|
`];
|
|
93840
94424
|
const { parseFrontmatter: parseFrontmatter3 } = await Promise.resolve().then(() => (init_storage(), storage_exports));
|
|
93841
94425
|
for (const f of files) {
|
|
93842
|
-
const raw = await
|
|
94426
|
+
const raw = await fs45.readFile(path104.join(decisionsDir, f), "utf-8");
|
|
93843
94427
|
const { meta: meta3, body } = parseFrontmatter3(raw);
|
|
93844
94428
|
const title = meta3.title ?? body.split("\n")[0]?.replace(/^#\s*/, "").trim() ?? f;
|
|
93845
94429
|
lines.push(`- **${f.replace(/\.md$/, "")}** [${meta3.status ?? "unknown"}] ${title}`);
|
|
@@ -93852,27 +94436,27 @@ async function handleWorkspaceShow(ctx, what) {
|
|
|
93852
94436
|
break;
|
|
93853
94437
|
}
|
|
93854
94438
|
case "risks": {
|
|
93855
|
-
const risksPath =
|
|
94439
|
+
const risksPath = path104.join(zelari, "risks.md");
|
|
93856
94440
|
try {
|
|
93857
|
-
content = await
|
|
94441
|
+
content = await fs45.readFile(risksPath, "utf-8");
|
|
93858
94442
|
} catch {
|
|
93859
94443
|
content = "(no risks.md yet)";
|
|
93860
94444
|
}
|
|
93861
94445
|
break;
|
|
93862
94446
|
}
|
|
93863
94447
|
case "agents": {
|
|
93864
|
-
const agentsPath =
|
|
94448
|
+
const agentsPath = path104.join(process.cwd(), "AGENTS.MD");
|
|
93865
94449
|
try {
|
|
93866
|
-
content = await
|
|
94450
|
+
content = await fs45.readFile(agentsPath, "utf-8");
|
|
93867
94451
|
} catch {
|
|
93868
94452
|
content = "(no AGENTS.MD yet at project root \u2014 run `/workspace sync` after a council session)";
|
|
93869
94453
|
}
|
|
93870
94454
|
break;
|
|
93871
94455
|
}
|
|
93872
94456
|
case "docs": {
|
|
93873
|
-
const docsDir =
|
|
94457
|
+
const docsDir = path104.join(zelari, "docs");
|
|
93874
94458
|
try {
|
|
93875
|
-
const files = (await
|
|
94459
|
+
const files = (await fs45.readdir(docsDir)).filter((f) => f.endsWith(".md")).sort();
|
|
93876
94460
|
content = files.length ? `# Docs (${files.length})
|
|
93877
94461
|
|
|
93878
94462
|
` + files.map((f) => `- ${f}`).join("\n") : "(no docs drafts yet)";
|
|
@@ -93912,8 +94496,8 @@ async function handleWorkspaceReset(ctx, force) {
|
|
|
93912
94496
|
return;
|
|
93913
94497
|
}
|
|
93914
94498
|
try {
|
|
93915
|
-
const target =
|
|
93916
|
-
await
|
|
94499
|
+
const target = path104.join(process.cwd(), ".zelari");
|
|
94500
|
+
await fs45.rm(target, { recursive: true, force: true });
|
|
93917
94501
|
appendSystem(ctx.setMessages, "[workspace] .zelari/ removed");
|
|
93918
94502
|
} catch (err) {
|
|
93919
94503
|
appendSystem(ctx.setMessages, `[workspace reset error] ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -93924,13 +94508,13 @@ async function handleWorkspaceReset(ctx, force) {
|
|
|
93924
94508
|
init_provider2();
|
|
93925
94509
|
|
|
93926
94510
|
// src/cli/skillHistory.ts
|
|
93927
|
-
import { promises as
|
|
94511
|
+
import { promises as fs46, existsSync as existsSync66, statSync as statSync11, renameSync as renameSync6, appendFileSync as appendFileSync5, mkdirSync as mkdirSync25 } from "node:fs";
|
|
93928
94512
|
init_paths();
|
|
93929
94513
|
var SKILL_HISTORY_ROTATE_BYTES = 10 * 1024 * 1024;
|
|
93930
94514
|
async function readSkillHistory(file2) {
|
|
93931
94515
|
let raw = "";
|
|
93932
94516
|
try {
|
|
93933
|
-
raw = await
|
|
94517
|
+
raw = await fs46.readFile(file2, "utf-8");
|
|
93934
94518
|
} catch {
|
|
93935
94519
|
return [];
|
|
93936
94520
|
}
|
|
@@ -95822,8 +96406,8 @@ function normalizeDraft(raw, sourceUrl, provider, model) {
|
|
|
95822
96406
|
let name = String(o.name ?? "").trim().toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 64);
|
|
95823
96407
|
if (!name || !/^[a-z0-9][a-z0-9-]{0,63}$/.test(name)) {
|
|
95824
96408
|
try {
|
|
95825
|
-
const
|
|
95826
|
-
name =
|
|
96409
|
+
const path128 = new URL(sourceUrl).pathname.split("/").filter(Boolean).pop()?.replace(/\.[a-z0-9]+$/i, "").toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 48);
|
|
96410
|
+
name = path128 && /^[a-z0-9]/.test(path128) ? path128 : "imported-skill";
|
|
95827
96411
|
} catch {
|
|
95828
96412
|
name = "imported-skill";
|
|
95829
96413
|
}
|