zelari-code 2.34.1 → 2.35.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.
@@ -3414,10 +3414,10 @@ function mergeDefs(...defs) {
3414
3414
  function cloneDef(schema) {
3415
3415
  return mergeDefs(schema._zod.def);
3416
3416
  }
3417
- function getElementAtPath(obj, path99) {
3418
- if (!path99)
3417
+ function getElementAtPath(obj, path100) {
3418
+ if (!path100)
3419
3419
  return obj;
3420
- return path99.reduce((acc, key) => acc?.[key], obj);
3420
+ return path100.reduce((acc, key) => acc?.[key], obj);
3421
3421
  }
3422
3422
  function promiseAllObject(promisesObj) {
3423
3423
  const keys = Object.keys(promisesObj);
@@ -3745,11 +3745,11 @@ function explicitlyAborted(x, startIndex = 0) {
3745
3745
  }
3746
3746
  return false;
3747
3747
  }
3748
- function prefixIssues(path99, issues) {
3748
+ function prefixIssues(path100, issues) {
3749
3749
  return issues.map((iss) => {
3750
3750
  var _a3;
3751
3751
  (_a3 = iss).path ?? (_a3.path = []);
3752
- iss.path.unshift(path99);
3752
+ iss.path.unshift(path100);
3753
3753
  return iss;
3754
3754
  });
3755
3755
  }
@@ -3967,16 +3967,16 @@ function flattenError(error51, mapper = (issue2) => issue2.message) {
3967
3967
  }
3968
3968
  function formatError(error51, mapper = (issue2) => issue2.message) {
3969
3969
  const fieldErrors = { _errors: [] };
3970
- const processError = (error52, path99 = []) => {
3970
+ const processError = (error52, path100 = []) => {
3971
3971
  for (const issue2 of error52.issues) {
3972
3972
  if (issue2.code === "invalid_union" && issue2.errors.length) {
3973
- issue2.errors.map((issues) => processError({ issues }, [...path99, ...issue2.path]));
3973
+ issue2.errors.map((issues) => processError({ issues }, [...path100, ...issue2.path]));
3974
3974
  } else if (issue2.code === "invalid_key") {
3975
- processError({ issues: issue2.issues }, [...path99, ...issue2.path]);
3975
+ processError({ issues: issue2.issues }, [...path100, ...issue2.path]);
3976
3976
  } else if (issue2.code === "invalid_element") {
3977
- processError({ issues: issue2.issues }, [...path99, ...issue2.path]);
3977
+ processError({ issues: issue2.issues }, [...path100, ...issue2.path]);
3978
3978
  } else {
3979
- const fullpath = [...path99, ...issue2.path];
3979
+ const fullpath = [...path100, ...issue2.path];
3980
3980
  if (fullpath.length === 0) {
3981
3981
  fieldErrors._errors.push(mapper(issue2));
3982
3982
  } else {
@@ -4003,17 +4003,17 @@ function formatError(error51, mapper = (issue2) => issue2.message) {
4003
4003
  }
4004
4004
  function treeifyError(error51, mapper = (issue2) => issue2.message) {
4005
4005
  const result = { errors: [] };
4006
- const processError = (error52, path99 = []) => {
4006
+ const processError = (error52, path100 = []) => {
4007
4007
  var _a3, _b;
4008
4008
  for (const issue2 of error52.issues) {
4009
4009
  if (issue2.code === "invalid_union" && issue2.errors.length) {
4010
- issue2.errors.map((issues) => processError({ issues }, [...path99, ...issue2.path]));
4010
+ issue2.errors.map((issues) => processError({ issues }, [...path100, ...issue2.path]));
4011
4011
  } else if (issue2.code === "invalid_key") {
4012
- processError({ issues: issue2.issues }, [...path99, ...issue2.path]);
4012
+ processError({ issues: issue2.issues }, [...path100, ...issue2.path]);
4013
4013
  } else if (issue2.code === "invalid_element") {
4014
- processError({ issues: issue2.issues }, [...path99, ...issue2.path]);
4014
+ processError({ issues: issue2.issues }, [...path100, ...issue2.path]);
4015
4015
  } else {
4016
- const fullpath = [...path99, ...issue2.path];
4016
+ const fullpath = [...path100, ...issue2.path];
4017
4017
  if (fullpath.length === 0) {
4018
4018
  result.errors.push(mapper(issue2));
4019
4019
  continue;
@@ -4045,8 +4045,8 @@ function treeifyError(error51, mapper = (issue2) => issue2.message) {
4045
4045
  }
4046
4046
  function toDotPath(_path) {
4047
4047
  const segs = [];
4048
- const path99 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
4049
- for (const seg of path99) {
4048
+ const path100 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
4049
+ for (const seg of path100) {
4050
4050
  if (typeof seg === "number")
4051
4051
  segs.push(`[${seg}]`);
4052
4052
  else if (typeof seg === "symbol")
@@ -17549,13 +17549,13 @@ function resolveRef(ref, ctx) {
17549
17549
  if (!ref.startsWith("#")) {
17550
17550
  throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
17551
17551
  }
17552
- const path99 = ref.slice(1).split("/").filter(Boolean);
17553
- if (path99.length === 0) {
17552
+ const path100 = ref.slice(1).split("/").filter(Boolean);
17553
+ if (path100.length === 0) {
17554
17554
  return ctx.rootSchema;
17555
17555
  }
17556
17556
  const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
17557
- if (path99[0] === defsKey) {
17558
- const key = path99[1];
17557
+ if (path100[0] === defsKey) {
17558
+ const key = path100[1];
17559
17559
  if (!key || !ctx.defs[key]) {
17560
17560
  throw new Error(`Reference not found: ${ref}`);
17561
17561
  }
@@ -18327,7 +18327,9 @@ var init_zod = __esm({
18327
18327
  });
18328
18328
 
18329
18329
  // packages/core/dist/core/tools/toolTypes.js
18330
- function typedOk(value, meta3) {
18330
+ function typedOk(value, meta3, images) {
18331
+ if (images && images.length > 0)
18332
+ return { ok: true, value, meta: meta3, images };
18331
18333
  return meta3 ? { ok: true, value, meta: meta3 } : { ok: true, value };
18332
18334
  }
18333
18335
  function typedErr(error51, meta3) {
@@ -18387,17 +18389,17 @@ var init_newlines = __esm({
18387
18389
  });
18388
18390
 
18389
18391
  // packages/core/dist/core/tools/builtin/fileEvents.js
18390
- function fileReadEvent(path99, snapshotId) {
18391
- return { kind: "file.read", actor: { type: "tool" }, data: { path: path99, snapshotId } };
18392
+ function fileReadEvent(path100, snapshotId) {
18393
+ return { kind: "file.read", actor: { type: "tool" }, data: { path: path100, snapshotId } };
18392
18394
  }
18393
- function fileAppliedEvent(path99, snapshotId, bytes) {
18394
- return { kind: "file.applied", actor: { type: "tool" }, data: { path: path99, snapshotId, bytes } };
18395
+ function fileAppliedEvent(path100, snapshotId, bytes) {
18396
+ return { kind: "file.applied", actor: { type: "tool" }, data: { path: path100, snapshotId, bytes } };
18395
18397
  }
18396
- function fileRejectedEvent(path99, reason, hint) {
18398
+ function fileRejectedEvent(path100, reason, hint) {
18397
18399
  return {
18398
18400
  kind: "file.rejected",
18399
18401
  actor: { type: "tool" },
18400
- data: hint === void 0 ? { path: path99, reason } : { path: path99, reason, hint }
18402
+ data: hint === void 0 ? { path: path100, reason } : { path: path100, reason, hint }
18401
18403
  };
18402
18404
  }
18403
18405
  function reReadHint(reject) {
@@ -19313,8 +19315,8 @@ async function searchFile(absPath, relPath, regex, contextLines, remainingSlots)
19313
19315
  }
19314
19316
  async function isDirectory(p3) {
19315
19317
  try {
19316
- const stat7 = await fs7.stat(p3);
19317
- return stat7.isDirectory();
19318
+ const stat8 = await fs7.stat(p3);
19319
+ return stat8.isDirectory();
19318
19320
  } catch {
19319
19321
  return false;
19320
19322
  }
@@ -20266,11 +20268,11 @@ var init_tools = __esm({
20266
20268
  if (!ctx.addDocument)
20267
20269
  return "Knowledge vault tool not available.";
20268
20270
  const title = args["title"] || "New Document";
20269
- const path99 = args["path"] || `notes/${title.toLowerCase().replace(/[^a-z0-9]+/g, "-")}`;
20271
+ const path100 = args["path"] || `notes/${title.toLowerCase().replace(/[^a-z0-9]+/g, "-")}`;
20270
20272
  const content = args["content"] || "";
20271
20273
  const tags = args["tags"] || [];
20272
20274
  ctx.addDocument({
20273
- path: path99,
20275
+ path: path100,
20274
20276
  title,
20275
20277
  content,
20276
20278
  format: "markdown",
@@ -20279,7 +20281,7 @@ var init_tools = __esm({
20279
20281
  workspaceId: ctx.workspaceId
20280
20282
  });
20281
20283
  ctx.addActivity("vault", "created document", title);
20282
- return `Document "${title}" created at "${path99}".`;
20284
+ return `Document "${title}" created at "${path100}".`;
20283
20285
  }
20284
20286
  }
20285
20287
  ];
@@ -25104,16 +25106,16 @@ function runRetentionFromEnv() {
25104
25106
  maxTotalBytes: Number.isFinite(parseMb) && parseMb > 0 ? Math.round(parseMb * 1024 * 1024) : DEFAULT_RUN_RETENTION_MAX_MB * 1024 * 1024
25105
25107
  };
25106
25108
  }
25107
- async function dirSize(path99) {
25109
+ async function dirSize(path100) {
25108
25110
  let total = 0;
25109
25111
  let entries;
25110
25112
  try {
25111
- entries = await readdir(path99, { withFileTypes: true });
25113
+ entries = await readdir(path100, { withFileTypes: true });
25112
25114
  } catch {
25113
25115
  return 0;
25114
25116
  }
25115
25117
  for (const entry of entries) {
25116
- const child = join3(path99, entry.name);
25118
+ const child = join3(path100, entry.name);
25117
25119
  if (entry.isDirectory())
25118
25120
  total += await dirSize(child);
25119
25121
  else {
@@ -25140,19 +25142,19 @@ async function enforceRunRetention(runsDir, options = {}) {
25140
25142
  for (const entry of entries) {
25141
25143
  if (!entry.isDirectory())
25142
25144
  continue;
25143
- const path99 = join3(runsDir, entry.name);
25145
+ const path100 = join3(runsDir, entry.name);
25144
25146
  let startedAt = 0;
25145
25147
  let endedAt;
25146
25148
  let completed = false;
25147
25149
  try {
25148
- const manifest = JSON.parse(await readFile(join3(path99, "manifest.json"), "utf8"));
25150
+ const manifest = JSON.parse(await readFile(join3(path100, "manifest.json"), "utf8"));
25149
25151
  startedAt = manifest.startedAt ?? 0;
25150
25152
  endedAt = manifest.endedAt;
25151
25153
  completed = Boolean(endedAt) && manifest.status !== "running";
25152
25154
  } catch {
25153
25155
  completed = false;
25154
25156
  }
25155
- infos.push({ name: entry.name, path: path99, startedAt, endedAt, completed, bytes: await dirSize(path99) });
25157
+ infos.push({ name: entry.name, path: path100, startedAt, endedAt, completed, bytes: await dirSize(path100) });
25156
25158
  }
25157
25159
  const remove = async (info) => {
25158
25160
  await rm(info.path, { recursive: true, force: true });
@@ -25639,12 +25641,12 @@ var init_engine = __esm({
25639
25641
  * content digest) and the returned ref carries the event seq when the
25640
25642
  * emitter resolved one.
25641
25643
  */
25642
- async fsEvidence(observation, path99, sha256, content, extra = {}) {
25644
+ async fsEvidence(observation, path100, sha256, content, extra = {}) {
25643
25645
  const digest = sha256 && content !== void 0 ? sha256(content) : void 0;
25644
- const seq = await this.emitEvidence({ observation, path: path99, ...extra, ...digest ? { digest } : {} });
25646
+ const seq = await this.emitEvidence({ observation, path: path100, ...extra, ...digest ? { digest } : {} });
25645
25647
  return {
25646
25648
  tier: "fs-observation",
25647
- ref: path99,
25649
+ ref: path100,
25648
25650
  capturedAt: Date.now(),
25649
25651
  ...digest ? { digest } : {},
25650
25652
  ...seq !== void 0 ? { seq } : {}
@@ -29106,7 +29108,8 @@ ${shared.content}`,
29106
29108
  return {
29107
29109
  content: resultStr,
29108
29110
  isError: !result.ok,
29109
- durationMs: Date.now() - startMs
29111
+ durationMs: Date.now() - startMs,
29112
+ ...result.ok && result.images && result.images.length > 0 ? { images: result.images } : {}
29110
29113
  };
29111
29114
  })();
29112
29115
  inflight.set(callKey, prom);
@@ -29127,7 +29130,8 @@ ${shared.content}`,
29127
29130
  toolCallId: p3.toolCallId,
29128
29131
  content: r.content,
29129
29132
  isError: r.isError,
29130
- endEvent
29133
+ endEvent,
29134
+ ...r.images ? { images: r.images } : {}
29131
29135
  // Cache already written in invokeOne; no need to re-set.
29132
29136
  };
29133
29137
  };
@@ -29679,7 +29683,8 @@ ${cached2}`
29679
29683
  yield item.endEvent;
29680
29684
  turnToolResults.push({
29681
29685
  toolCallId: item.toolCallId,
29682
- content: item.content
29686
+ content: item.content,
29687
+ ...item.images ? { images: item.images } : {}
29683
29688
  });
29684
29689
  if (item.cacheKey && item.content && !item.isError) {
29685
29690
  this.toolCallCache.set(item.cacheKey, item.content);
@@ -29859,7 +29864,8 @@ ${cached2}`
29859
29864
  this.config.messages.push({
29860
29865
  role: "tool",
29861
29866
  toolCallId: tr.toolCallId,
29862
- content: tr.content
29867
+ content: tr.content,
29868
+ ...tr.images ? { images: tr.images } : {}
29863
29869
  });
29864
29870
  }
29865
29871
  if (truncatedToolCall) {
@@ -31660,11 +31666,11 @@ var init_synthesisAudit = __esm({
31660
31666
  import { existsSync as existsSync10, readFileSync as readFileSync9, writeFileSync as writeFileSync6 } from "node:fs";
31661
31667
  import { join as join5 } from "node:path";
31662
31668
  function loadNfrSpec(zelariRoot) {
31663
- const path99 = join5(zelariRoot, "nfr-spec.json");
31664
- if (!existsSync10(path99))
31669
+ const path100 = join5(zelariRoot, "nfr-spec.json");
31670
+ if (!existsSync10(path100))
31665
31671
  return null;
31666
31672
  try {
31667
- const raw = JSON.parse(readFileSync9(path99, "utf8"));
31673
+ const raw = JSON.parse(readFileSync9(path100, "utf8"));
31668
31674
  if (raw.version !== 1 || !Array.isArray(raw.targets))
31669
31675
  return null;
31670
31676
  return raw;
@@ -34047,9 +34053,9 @@ var init_types9 = __esm({
34047
34053
  import { readFileSync as readFileSync14 } from "node:fs";
34048
34054
  import { join as join11 } from "node:path";
34049
34055
  function readLessonsDeduped(zelariRoot) {
34050
- const path99 = join11(zelariRoot, LESSONS_FILE);
34056
+ const path100 = join11(zelariRoot, LESSONS_FILE);
34051
34057
  try {
34052
- const raw = readFileSync14(path99, "utf8");
34058
+ const raw = readFileSync14(path100, "utf8");
34053
34059
  const byId = /* @__PURE__ */ new Map();
34054
34060
  for (const line of raw.split(/\r?\n/)) {
34055
34061
  if (!line.trim())
@@ -34150,8 +34156,8 @@ function keywordsFrom(check2, signature) {
34150
34156
  return [.../* @__PURE__ */ new Set([...fromId, ...words])].slice(0, 12);
34151
34157
  }
34152
34158
  function writeLesson(zelariRoot, lesson) {
34153
- const path99 = join12(zelariRoot, LESSONS_FILE);
34154
- appendFileSync(path99, `${JSON.stringify(lesson)}
34159
+ const path100 = join12(zelariRoot, LESSONS_FILE);
34160
+ appendFileSync(path100, `${JSON.stringify(lesson)}
34155
34161
  `, "utf8");
34156
34162
  }
34157
34163
  function findSimilar(lessons, signature) {
@@ -36118,9 +36124,9 @@ function findCycle(nodes) {
36118
36124
  if (color.get(start) !== WHITE)
36119
36125
  continue;
36120
36126
  const stack = [[start, 0]];
36121
- const path99 = [];
36127
+ const path100 = [];
36122
36128
  color.set(start, GRAY);
36123
- path99.push(start);
36129
+ path100.push(start);
36124
36130
  while (stack.length > 0) {
36125
36131
  const top = stack[stack.length - 1];
36126
36132
  const [id3, idx] = top;
@@ -36133,17 +36139,17 @@ function findCycle(nodes) {
36133
36139
  continue;
36134
36140
  const c = color.get(dep);
36135
36141
  if (c === GRAY) {
36136
- const at = path99.indexOf(dep);
36137
- return [...path99.slice(at), dep];
36142
+ const at = path100.indexOf(dep);
36143
+ return [...path100.slice(at), dep];
36138
36144
  }
36139
36145
  if (c === WHITE) {
36140
36146
  color.set(dep, GRAY);
36141
- path99.push(dep);
36147
+ path100.push(dep);
36142
36148
  stack.push([dep, 0]);
36143
36149
  }
36144
36150
  } else {
36145
36151
  color.set(id3, BLACK);
36146
- path99.pop();
36152
+ path100.pop();
36147
36153
  stack.pop();
36148
36154
  }
36149
36155
  }
@@ -37063,8 +37069,8 @@ var init_runner = __esm({
37063
37069
  failed: [...this.tentaclesById.values()].filter((r) => r.status === "error"),
37064
37070
  pending: []
37065
37071
  };
37066
- const path99 = await this.host.saveSnapshot(snapshot, ".zelari/kraken/snapshots");
37067
- this.host.log(`checkpoint: ${label ?? "auto"} \u2192 ${path99}`);
37072
+ const path100 = await this.host.saveSnapshot(snapshot, ".zelari/kraken/snapshots");
37073
+ this.host.log(`checkpoint: ${label ?? "auto"} \u2192 ${path100}`);
37068
37074
  return snapshot;
37069
37075
  }
37070
37076
  callLog(msg, data) {
@@ -38215,7 +38221,7 @@ var CORE_VERSION;
38215
38221
  var init_version = __esm({
38216
38222
  "packages/core/dist/version.js"() {
38217
38223
  "use strict";
38218
- CORE_VERSION = "2.34.1";
38224
+ CORE_VERSION = "2.35.0";
38219
38225
  }
38220
38226
  });
38221
38227
 
@@ -40673,9 +40679,9 @@ function spillToolOutput(fullText, meta3) {
40673
40679
  const rnd = randomBytes3(3).toString("hex");
40674
40680
  const safeTool = (meta3?.toolName ?? "tool").replace(/[^a-zA-Z0-9._-]+/g, "_").slice(0, 32);
40675
40681
  const file2 = `${stamp}-${safeTool}-${hash3}-${rnd}.txt`;
40676
- const path99 = join14(dir, file2);
40677
- writeFileSync12(path99, fullText, "utf8");
40678
- return path99;
40682
+ const path100 = join14(dir, file2);
40683
+ writeFileSync12(path100, fullText, "utf8");
40684
+ return path100;
40679
40685
  } catch {
40680
40686
  return null;
40681
40687
  }
@@ -40721,10 +40727,10 @@ function truncateToolResult(text, capOrOpts = TOOL_RESULT_LINE_CAP) {
40721
40727
  ${tail2}`;
40722
40728
  }
40723
40729
  if (doSpill) {
40724
- const path99 = spillToolOutput(text, { toolName: opts.toolName });
40725
- if (path99) {
40730
+ const path100 = spillToolOutput(text, { toolName: opts.toolName });
40731
+ if (path100) {
40726
40732
  const spillNote = `
40727
- \u2026 [full output spilled to: ${path99} \u2014 re-read with read_file if you need the complete text] \u2026`;
40733
+ \u2026 [full output spilled to: ${path100} \u2014 re-read with read_file if you need the complete text] \u2026`;
40728
40734
  if (preview.includes("] \u2026\n")) {
40729
40735
  preview = preview.replace("] \u2026\n", `] \u2026${spillNote}
40730
40736
  `);
@@ -41495,28 +41501,28 @@ var init_storage = __esm({
41495
41501
  VALID_SCALARS = /^(true|false|null|~)$/i;
41496
41502
  Storage = class {
41497
41503
  /** Read a Markdown file with frontmatter. Throws if not found. */
41498
- read(path99) {
41499
- if (!existsSync19(path99)) {
41500
- throw new Error(`File not found: ${path99}`);
41504
+ read(path100) {
41505
+ if (!existsSync19(path100)) {
41506
+ throw new Error(`File not found: ${path100}`);
41501
41507
  }
41502
- const md = readFileSync17(path99, "utf8");
41508
+ const md = readFileSync17(path100, "utf8");
41503
41509
  return parseFrontmatter(md);
41504
41510
  }
41505
41511
  /** Read a Markdown file; returns null if not found. */
41506
- readIfExists(path99) {
41507
- if (!existsSync19(path99)) return null;
41508
- return this.read(path99);
41512
+ readIfExists(path100) {
41513
+ if (!existsSync19(path100)) return null;
41514
+ return this.read(path100);
41509
41515
  }
41510
41516
  /**
41511
41517
  * Write a Markdown file atomically (tmp + rename). Creates parent dirs.
41512
41518
  * The meta object is serialized as YAML frontmatter; body as Markdown.
41513
41519
  */
41514
- write(path99, meta3, body) {
41515
- mkdirSync10(dirname2(path99), { recursive: true });
41516
- const tmp = path99 + ".tmp-" + process.pid;
41520
+ write(path100, meta3, body) {
41521
+ mkdirSync10(dirname2(path100), { recursive: true });
41522
+ const tmp = path100 + ".tmp-" + process.pid;
41517
41523
  const md = serializeFrontmatter(meta3, body);
41518
41524
  writeFileSync14(tmp, md, "utf8");
41519
- renameSync2(tmp, path99);
41525
+ renameSync2(tmp, path100);
41520
41526
  }
41521
41527
  /** List all .md files in a directory (non-recursive). */
41522
41528
  listMarkdown(dir) {
@@ -41591,8 +41597,8 @@ function nextPlanTaskId(store6) {
41591
41597
  return `t${store6.counter}`;
41592
41598
  }
41593
41599
  function writePlanTaskArtifact(rootDir, task) {
41594
- const path99 = join17(rootDir, "plan-tasks", `${task.id}.md`);
41595
- mkdirSync11(dirname3(path99), { recursive: true });
41600
+ const path100 = join17(rootDir, "plan-tasks", `${task.id}.md`);
41601
+ mkdirSync11(dirname3(path100), { recursive: true });
41596
41602
  const meta3 = {
41597
41603
  kind: "task",
41598
41604
  id: task.id,
@@ -41613,7 +41619,7 @@ function writePlanTaskArtifact(rootDir, task) {
41613
41619
  task.notes?.trim() ? task.notes.trim() : "_(no notes)_",
41614
41620
  ""
41615
41621
  ].filter((l) => l !== null).join("\n");
41616
- new Storage().write(path99, meta3, body);
41622
+ new Storage().write(path100, meta3, body);
41617
41623
  }
41618
41624
  function loadHandle(rootDir) {
41619
41625
  const jsonPath = join17(rootDir, "plan.json");
@@ -50815,12 +50821,9 @@ function backoffDelay(attempt, retryAfterHeader) {
50815
50821
  }
50816
50822
  return Math.min(BACKOFF_BASE_MS * 2 ** attempt, BACKOFF_CAP_MS);
50817
50823
  }
50818
- function modelSupportsVision(model) {
50824
+ function modelSupportsVision(_model) {
50819
50825
  const force = process.env.ZELARI_VISION;
50820
- if (force === "1" || force === "true" || force === "on") return true;
50821
- if (force === "0" || force === "false" || force === "off") return false;
50822
- const m = model.toLowerCase();
50823
- return VISION_MODEL_HINTS.some((hint) => m.includes(hint));
50826
+ return !(force === "0" || force === "false" || force === "off");
50824
50827
  }
50825
50828
  function dataUriFromImage(img) {
50826
50829
  return `data:${img.mime};base64,${img.dataBase64}`;
@@ -50915,6 +50918,22 @@ ${notes}
50915
50918
  }
50916
50919
  return { role: m.role, content: m.content };
50917
50920
  }
50921
+ function imagesFollowUpMessage(images) {
50922
+ const labels = images.map((img) => img.alt ?? img.mime).join(", ");
50923
+ return {
50924
+ role: "user",
50925
+ content: [
50926
+ {
50927
+ type: "text",
50928
+ text: `[Immagine(i) dal tool: ${labels} \u2014 usa questi pixel per l'analisi visiva.]`
50929
+ },
50930
+ ...images.map((img) => ({
50931
+ type: "image_url",
50932
+ image_url: { url: dataUriFromImage(img) }
50933
+ }))
50934
+ ]
50935
+ };
50936
+ }
50918
50937
  function positiveEnvInt(name) {
50919
50938
  const raw = process.env[name];
50920
50939
  if (!raw) return void 0;
@@ -50925,15 +50944,27 @@ function openaiCompatibleProvider(config2) {
50925
50944
  return async function* (params) {
50926
50945
  const capabilities = capabilitiesFor(params.model, config2.providerId);
50927
50946
  const vision = modelSupportsVision(params.model);
50928
- const messages = params.messages.map((m) => {
50947
+ const msgsIn = params.messages;
50948
+ let toolRunImages = [];
50949
+ const messages = msgsIn.flatMap((m, i) => {
50929
50950
  const cacheable = !(m.role === "user" && m.images && m.images.length > 0);
50930
50951
  if (cacheable) {
50931
50952
  const cached2 = messageMappingCache.get(m);
50932
- if (cached2) return cached2;
50953
+ if (cached2) return [cached2];
50933
50954
  }
50934
50955
  const mapped = mapAgentMessage(m, vision);
50935
50956
  if (cacheable) messageMappingCache.set(m, mapped);
50936
- return mapped;
50957
+ if (m.role === "tool") {
50958
+ if (m.images && m.images.length > 0) toolRunImages.push(...m.images);
50959
+ const next = msgsIn[i + 1];
50960
+ const runEnds = !next || next.role !== "tool";
50961
+ if (runEnds && vision && toolRunImages.length > 0) {
50962
+ const followUp = imagesFollowUpMessage(toolRunImages);
50963
+ toolRunImages = [];
50964
+ return [mapped, followUp];
50965
+ }
50966
+ }
50967
+ return [mapped];
50937
50968
  });
50938
50969
  const generation = params.generation;
50939
50970
  const body = {
@@ -51257,7 +51288,7 @@ async function providerConfigFor(providerId) {
51257
51288
  ...extraFromStored(providerId)
51258
51289
  };
51259
51290
  }
51260
- var RETRYABLE_STATUSES, MAX_RETRIES, BACKOFF_BASE_MS, BACKOFF_CAP_MS, PROVIDER_CONNECT_TIMEOUT_MS, PROVIDER_STREAM_IDLE_MS, PROVIDER_STREAM_MAX_MS, VISION_MODEL_HINTS, PROVIDER_ENDPOINTS, messageMappingCache;
51291
+ var RETRYABLE_STATUSES, MAX_RETRIES, BACKOFF_BASE_MS, BACKOFF_CAP_MS, PROVIDER_CONNECT_TIMEOUT_MS, PROVIDER_STREAM_IDLE_MS, PROVIDER_STREAM_MAX_MS, PROVIDER_ENDPOINTS, messageMappingCache;
51261
51292
  var init_openai_compatible = __esm({
51262
51293
  "src/cli/provider/openai-compatible.ts"() {
51263
51294
  "use strict";
@@ -51288,33 +51319,6 @@ var init_openai_compatible = __esm({
51288
51319
  const n = raw ? Number.parseInt(raw, 10) : 18e5;
51289
51320
  return Number.isFinite(n) && n >= 6e4 ? n : 18e5;
51290
51321
  })();
51291
- VISION_MODEL_HINTS = [
51292
- "grok-4",
51293
- "grok-3",
51294
- "grok-2-vision",
51295
- "grok-vision",
51296
- "glm-4v",
51297
- "glm-4.5v",
51298
- "glm-4.1v",
51299
- "glm-5v",
51300
- "qwen-vl",
51301
- "qwen2-vl",
51302
- "qwen2.5-vl",
51303
- "qwen3-vl",
51304
- "gpt-4o",
51305
- "gpt-4.1",
51306
- "gpt-4.5",
51307
- "gpt-4-vision",
51308
- "gpt-5",
51309
- "claude-3",
51310
- "claude-4",
51311
- "gemini-",
51312
- "gemini/",
51313
- "minimax-m1",
51314
- "minimax-m2",
51315
- "minimax-m3",
51316
- "deepseek-vl"
51317
- ];
51318
51322
  PROVIDER_ENDPOINTS = {
51319
51323
  "openai-compatible": "https://api.x.ai/v1",
51320
51324
  "minimax": "https://api.minimax.io/v1",
@@ -51709,6 +51713,16 @@ var init_driver = __esm({
51709
51713
  // src/cli/browser/tools.ts
51710
51714
  import path56 from "node:path";
51711
51715
  import os3 from "node:os";
51716
+ import { readFile as readFile7 } from "node:fs/promises";
51717
+ async function loadImageBlock(filePath) {
51718
+ try {
51719
+ const buf = await readFile7(filePath);
51720
+ if (buf.byteLength > SCREENSHOT_MAX_BYTES) return void 0;
51721
+ return { mime: "image/png", dataBase64: buf.toString("base64"), alt: path56.basename(filePath) };
51722
+ } catch {
51723
+ return void 0;
51724
+ }
51725
+ }
51712
51726
  function createBrowserTool(deps = {}) {
51713
51727
  return {
51714
51728
  name: "browser_check",
@@ -51761,17 +51775,23 @@ function createBrowserTool(deps = {}) {
51761
51775
  note: "Weak smoke only: no selector/text/evaluate assertions. No console/page errors is necessary but not sufficient to claim a logic fix. Add waitForSelector, waitForText, or evaluate (DOM/read hooks) for stronger evidence.",
51762
51776
  smokeStrength: "weak"
51763
51777
  } : { smokeStrength: "asserted" }
51764
- });
51778
+ }, void 0, await toolImages(result.screenshotPath));
51765
51779
  }
51766
51780
  };
51767
51781
  }
51768
- var ActionSchema;
51782
+ async function toolImages(screenshotPath) {
51783
+ if (!screenshotPath) return void 0;
51784
+ const image = await loadImageBlock(screenshotPath);
51785
+ return image ? [image] : void 0;
51786
+ }
51787
+ var SCREENSHOT_MAX_BYTES, ActionSchema;
51769
51788
  var init_tools5 = __esm({
51770
51789
  "src/cli/browser/tools.ts"() {
51771
51790
  "use strict";
51772
51791
  init_zod();
51773
51792
  init_toolTypes();
51774
51793
  init_driver();
51794
+ SCREENSHOT_MAX_BYTES = 8 * 1024 * 1024;
51775
51795
  ActionSchema = external_exports.discriminatedUnion("type", [
51776
51796
  external_exports.object({ type: external_exports.literal("click"), selector: external_exports.string().min(1) }),
51777
51797
  external_exports.object({ type: external_exports.literal("fill"), selector: external_exports.string().min(1), value: external_exports.string() }),
@@ -51796,6 +51816,92 @@ var init_tools5 = __esm({
51796
51816
  }
51797
51817
  });
51798
51818
 
51819
+ // src/cli/tools/screenshotTool.ts
51820
+ import { execFile as execFile5 } from "node:child_process";
51821
+ import { mkdir as mkdir3, readFile as readFile8, stat as stat7 } from "node:fs/promises";
51822
+ import path57 from "node:path";
51823
+ import { promisify as promisify4 } from "node:util";
51824
+ async function captureWindows(target) {
51825
+ const script = `Add-Type -AssemblyName System.Windows.Forms,System.Drawing;$b=[System.Windows.Forms.SystemInformation]::VirtualScreen;$bmp=New-Object System.Drawing.Bitmap $b.Width,$b.Height;$g=[System.Drawing.Graphics]::FromImage($bmp);$g.CopyFromScreen($b.Left,$b.Top,0,0,$bmp.Size);$g.Dispose(); $bmp.Save('${target.replace(/'/g, "''")}'); $bmp.Dispose();`;
51826
+ await execFileAsync4("powershell.exe", ["-NoProfile", "-NonInteractive", "-Command", script], {
51827
+ timeout: 12e3,
51828
+ windowsHide: true
51829
+ });
51830
+ }
51831
+ async function captureUnixLike(target) {
51832
+ const attempts = process.platform === "darwin" ? [["screencapture", ["-x", target]]] : [
51833
+ ["gnome-screenshot", ["-f", target]],
51834
+ ["scrot", [target]],
51835
+ ["import", ["-window", "root", target]]
51836
+ ];
51837
+ let lastErr = null;
51838
+ for (const [bin, args] of attempts) {
51839
+ try {
51840
+ await execFileAsync4(bin, args, { timeout: 12e3 });
51841
+ return;
51842
+ } catch (e) {
51843
+ lastErr = e;
51844
+ }
51845
+ }
51846
+ throw lastErr ?? new Error("no screen-capture utility available");
51847
+ }
51848
+ function createScreenshotTool(deps = {}) {
51849
+ return {
51850
+ name: "screenshot",
51851
+ description: "Capture a screenshot of the user screen(s) as PNG. Use it when the user asks to see/check something on screen (running app, game, dialog, error window) or when you need to LOOK at the current UI state to debug it. The image is returned to you as pixels (vision) and saved to disk; give the path back to the user so they can open it.",
51852
+ permissions: ["ui"],
51853
+ timeoutMs: 2e4,
51854
+ inputSchema: external_exports.object({
51855
+ note: external_exports.string().max(200).optional().describe("Why you are capturing (shown to the user with the permission prompt).")
51856
+ }),
51857
+ execute: async (args, ctx) => {
51858
+ const a = args;
51859
+ const dir = deps.outDir ?? path57.join(ctx.cwd ?? process.cwd(), ".zelari", "screenshots");
51860
+ const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
51861
+ const target = path57.join(dir, `screenshot-${stamp}.png`);
51862
+ const capture = deps.capture ?? (process.platform === "win32" ? captureWindows : captureUnixLike);
51863
+ try {
51864
+ await mkdir3(dir, { recursive: true });
51865
+ await capture(target);
51866
+ const meta3 = await stat7(target);
51867
+ if (meta3.size === 0) return typedErr(`capture produced an empty file: ${target}`);
51868
+ const buf = await readFile8(target);
51869
+ const image = {
51870
+ mime: "image/png",
51871
+ dataBase64: buf.toString("base64"),
51872
+ alt: path57.basename(target)
51873
+ };
51874
+ const attachable = meta3.size <= SCREENSHOT_MAX_BYTES2;
51875
+ return typedOk(
51876
+ {
51877
+ ok: true,
51878
+ path: target,
51879
+ bytes: meta3.size,
51880
+ ...a.note ? { note: a.note } : {},
51881
+ ...attachable ? {} : { warning: "PNG over 8MB: pixels not attached to the model context; open the path instead." }
51882
+ },
51883
+ void 0,
51884
+ attachable ? [image] : void 0
51885
+ );
51886
+ } catch (e) {
51887
+ return typedErr(
51888
+ `screen capture failed on ${process.platform}: ${e instanceof Error ? e.message : String(e)}`
51889
+ );
51890
+ }
51891
+ }
51892
+ };
51893
+ }
51894
+ var execFileAsync4, SCREENSHOT_MAX_BYTES2;
51895
+ var init_screenshotTool = __esm({
51896
+ "src/cli/tools/screenshotTool.ts"() {
51897
+ "use strict";
51898
+ init_zod();
51899
+ init_toolTypes();
51900
+ execFileAsync4 = promisify4(execFile5);
51901
+ SCREENSHOT_MAX_BYTES2 = 8 * 1024 * 1024;
51902
+ }
51903
+ });
51904
+
51799
51905
  // src/cli/ssh/targets.ts
51800
51906
  var targets_exports = {};
51801
51907
  __export(targets_exports, {
@@ -51837,21 +51943,21 @@ function normalizeAuth(auth) {
51837
51943
  return "agent";
51838
51944
  }
51839
51945
  function readSecrets() {
51840
- const path99 = getSshSecretsPath();
51841
- if (!existsSync30(path99)) return {};
51946
+ const path100 = getSshSecretsPath();
51947
+ if (!existsSync30(path100)) return {};
51842
51948
  try {
51843
- return JSON.parse(readFileSync22(path99, "utf8"));
51949
+ return JSON.parse(readFileSync22(path100, "utf8"));
51844
51950
  } catch {
51845
51951
  return {};
51846
51952
  }
51847
51953
  }
51848
51954
  function writeSecrets(data) {
51849
- const path99 = getSshSecretsPath();
51850
- mkdirSync13(dirname4(path99), { recursive: true });
51851
- writeFileSync16(path99, `${JSON.stringify(data, null, 2)}
51955
+ const path100 = getSshSecretsPath();
51956
+ mkdirSync13(dirname4(path100), { recursive: true });
51957
+ writeFileSync16(path100, `${JSON.stringify(data, null, 2)}
51852
51958
  `, "utf8");
51853
51959
  try {
51854
- chmodSync(path99, 384);
51960
+ chmodSync(path100, 384);
51855
51961
  } catch {
51856
51962
  }
51857
51963
  }
@@ -51880,10 +51986,10 @@ function deleteSshPassword(id3) {
51880
51986
  writeSecrets({ passwords });
51881
51987
  }
51882
51988
  function readStore2() {
51883
- const path99 = getSshTargetsPath();
51884
- if (!existsSync30(path99)) return [];
51989
+ const path100 = getSshTargetsPath();
51990
+ if (!existsSync30(path100)) return [];
51885
51991
  try {
51886
- const parsed = JSON.parse(readFileSync22(path99, "utf8"));
51992
+ const parsed = JSON.parse(readFileSync22(path100, "utf8"));
51887
51993
  const list = Array.isArray(parsed.targets) ? parsed.targets : [];
51888
51994
  return list.filter(
51889
51995
  (t) => t && typeof t.id === "string" && typeof t.host === "string" && typeof t.user === "string"
@@ -51898,11 +52004,11 @@ function readStore2() {
51898
52004
  }
51899
52005
  }
51900
52006
  function writeStore2(targets) {
51901
- const path99 = getSshTargetsPath();
51902
- mkdirSync13(dirname4(path99), { recursive: true });
52007
+ const path100 = getSshTargetsPath();
52008
+ mkdirSync13(dirname4(path100), { recursive: true });
51903
52009
  const clean = targets.map(({ hasPassword: _hp, ...t }) => t);
51904
52010
  writeFileSync16(
51905
- path99,
52011
+ path100,
51906
52012
  `${JSON.stringify({ targets: clean }, null, 2)}
51907
52013
  `,
51908
52014
  "utf8"
@@ -52148,11 +52254,11 @@ function formatSshTargetsForPrompt() {
52148
52254
  ];
52149
52255
  for (const t of targets) {
52150
52256
  const tags = t.tags?.length ? ` tags=[${t.tags.join(",")}]` : "";
52151
- const path99 = t.defaultRemotePath ? ` remotePath=${t.defaultRemotePath}` : "";
52257
+ const path100 = t.defaultRemotePath ? ` remotePath=${t.defaultRemotePath}` : "";
52152
52258
  const allow = t.allowedCommands?.length ? ` allowed=${t.allowedCommands.join("|")}` : " allowed=status-only";
52153
52259
  const auth = t.auth === "password" ? " auth=password" : t.auth === "keyPath" ? " auth=key" : " auth=agent";
52154
52260
  lines.push(
52155
- `- id=${t.id} name=${t.name} ${t.user}@${t.host}:${t.port ?? 22}${auth}${path99}${tags}${allow}`
52261
+ `- id=${t.id} name=${t.name} ${t.user}@${t.host}:${t.port ?? 22}${auth}${path100}${tags}${allow}`
52156
52262
  );
52157
52263
  }
52158
52264
  return lines.join("\n");
@@ -53138,12 +53244,12 @@ __export(folderTrust_exports, {
53138
53244
  untrustFolder: () => untrustFolder
53139
53245
  });
53140
53246
  import { existsSync as existsSync31, mkdirSync as mkdirSync14, readFileSync as readFileSync23, writeFileSync as writeFileSync17 } from "node:fs";
53141
- import path57 from "node:path";
53247
+ import path58 from "node:path";
53142
53248
  function trustStorePath() {
53143
53249
  return _overrideStorePath ?? trustConfigPath();
53144
53250
  }
53145
53251
  function normalize6(p3) {
53146
- const resolved = path57.resolve(p3);
53252
+ const resolved = path58.resolve(p3);
53147
53253
  return process.platform === "win32" ? resolved.toLowerCase() : resolved;
53148
53254
  }
53149
53255
  function readStore3() {
@@ -53159,7 +53265,7 @@ function readStore3() {
53159
53265
  function writeStore3(store6) {
53160
53266
  const p3 = trustStorePath();
53161
53267
  try {
53162
- mkdirSync14(path57.dirname(p3), { recursive: true });
53268
+ mkdirSync14(path58.dirname(p3), { recursive: true });
53163
53269
  writeFileSync17(p3, JSON.stringify(store6, null, 2), "utf8");
53164
53270
  } catch (err) {
53165
53271
  throw new Error(
@@ -53185,7 +53291,7 @@ function isFolderTrusted(folderPath) {
53185
53291
  }
53186
53292
  function trustFolder(folderPath) {
53187
53293
  const store6 = readStore3();
53188
- const normalized = path57.resolve(folderPath);
53294
+ const normalized = path58.resolve(folderPath);
53189
53295
  if (!store6.folders.some((f) => normalize6(f.path) === normalize6(normalized))) {
53190
53296
  store6.folders.push({ path: normalized, trustedAt: (/* @__PURE__ */ new Date()).toISOString() });
53191
53297
  writeStore3(store6);
@@ -53311,7 +53417,7 @@ var init_lifecycleHooks = __esm({
53311
53417
 
53312
53418
  // src/cli/safety/astGate.ts
53313
53419
  import { promises as fs23 } from "node:fs";
53314
- import path58 from "node:path";
53420
+ import path59 from "node:path";
53315
53421
  function astGateEnabled() {
53316
53422
  return process.env.ZELARI_AST_GATE !== "0";
53317
53423
  }
@@ -53346,9 +53452,9 @@ function wrapWithAstGate(original, opts) {
53346
53452
  const containedPathOf = (args) => {
53347
53453
  const raw = args["path"];
53348
53454
  if (typeof raw !== "string" || raw.length === 0) return null;
53349
- const absPath = path58.isAbsolute(raw) ? raw : path58.join(opts.root, raw);
53350
- const rel2 = path58.relative(opts.root, absPath);
53351
- if (rel2.startsWith("..") || path58.isAbsolute(rel2)) return null;
53455
+ const absPath = path59.isAbsolute(raw) ? raw : path59.join(opts.root, raw);
53456
+ const rel2 = path59.relative(opts.root, absPath);
53457
+ if (rel2.startsWith("..") || path59.isAbsolute(rel2)) return null;
53352
53458
  return absPath;
53353
53459
  };
53354
53460
  return {
@@ -53373,7 +53479,7 @@ function wrapWithAstGate(original, opts) {
53373
53479
  if (!result.ok) return result;
53374
53480
  if (gateTarget !== null && !isAstSupported(gateTarget)) {
53375
53481
  process.stderr.write(
53376
- `[ast_gate] LOUD SKIP (unsupported-extension): ${original.name} ${gateTarget} \u2014 ${path58.extname(gateTarget) || "(no extension)"} is outside the AST surface; write KEPT, NOT syntax-gated.
53482
+ `[ast_gate] LOUD SKIP (unsupported-extension): ${original.name} ${gateTarget} \u2014 ${path59.extname(gateTarget) || "(no extension)"} is outside the AST surface; write KEPT, NOT syntax-gated.
53377
53483
  `
53378
53484
  );
53379
53485
  return result;
@@ -53390,7 +53496,7 @@ function wrapWithAstGate(original, opts) {
53390
53496
  return result;
53391
53497
  }
53392
53498
  const post = await fs23.readFile(absPath, "utf8");
53393
- const syntaxError = firstSyntaxError(ts, path58.basename(absPath), post);
53499
+ const syntaxError = firstSyntaxError(ts, path59.basename(absPath), post);
53394
53500
  if (!syntaxError) return result;
53395
53501
  const parseError = `${syntaxError.message} (line ${syntaxError.line}, col ${syntaxError.character})`;
53396
53502
  let revertedTo;
@@ -53401,7 +53507,7 @@ function wrapWithAstGate(original, opts) {
53401
53507
  await fs23.writeFile(absPath, preContent, "utf8");
53402
53508
  revertedTo = snapshotIdOf(preContent);
53403
53509
  }
53404
- const relLabel = path58.relative(opts.root, absPath) || path58.basename(absPath);
53510
+ const relLabel = path59.relative(opts.root, absPath) || path59.basename(absPath);
53405
53511
  return typedErr(
53406
53512
  `[ast_gate_reverted] ${original.name}: ${absPath} written but the file no longer parses \u2014 write REVERTED (revertedTo=${revertedTo}). ${parseError}. Fix the syntax and re-apply (read_file first for a fresh snapshotId).`,
53407
53513
  {
@@ -53826,7 +53932,7 @@ var init_resourceClaims = __esm({
53826
53932
  // src/cli/toolResultCache.ts
53827
53933
  import { createHash as createHash15 } from "node:crypto";
53828
53934
  import { promises as fs24 } from "node:fs";
53829
- import path59 from "node:path";
53935
+ import path60 from "node:path";
53830
53936
  function isToolCacheEnabled() {
53831
53937
  const raw = process.env.ZELARI_TOOL_CACHE;
53832
53938
  return raw !== "0" && raw !== "false" && raw !== "off";
@@ -53911,7 +54017,7 @@ async function statKey(toolName, input, ctx) {
53911
54017
  if (!input || typeof input !== "object") return null;
53912
54018
  const rawPath = input.path;
53913
54019
  if (typeof rawPath !== "string" || rawPath.length === 0) return null;
53914
- const abs = path59.isAbsolute(rawPath) ? rawPath : path59.join(ctx.cwd, rawPath);
54020
+ const abs = path60.isAbsolute(rawPath) ? rawPath : path60.join(ctx.cwd, rawPath);
53915
54021
  try {
53916
54022
  const st = await fs24.stat(abs);
53917
54023
  return hashKey({
@@ -53967,7 +54073,7 @@ __export(toolRegistry_exports, {
53967
54073
  wrapWithSandbox: () => wrapWithSandbox
53968
54074
  });
53969
54075
  import { existsSync as existsSync32 } from "node:fs";
53970
- import path60 from "node:path";
54076
+ import path61 from "node:path";
53971
54077
  function createBuiltinToolRegistry(options = {}) {
53972
54078
  const root = options.root ?? process.cwd();
53973
54079
  const audit = options.audit ?? new AuditLogger();
@@ -54192,6 +54298,15 @@ function createBuiltinToolRegistry(options = {}) {
54192
54298
  permissions: browserTool.permissions ?? []
54193
54299
  });
54194
54300
  }
54301
+ if (!readOnly && !gauntletParent && process.env.ZELARI_SCREENSHOT !== "0") {
54302
+ const screenshotTool = createScreenshotTool();
54303
+ registry4.register(screenshotTool);
54304
+ tools.push({
54305
+ name: screenshotTool.name,
54306
+ description: screenshotTool.description,
54307
+ permissions: screenshotTool.permissions ?? []
54308
+ });
54309
+ }
54195
54310
  if (!readOnly && !gauntletParent && process.env.ZELARI_SSH !== "0") {
54196
54311
  for (const t of createSshTools()) {
54197
54312
  registry4.register(t);
@@ -54576,14 +54691,14 @@ function wrapWithDiagnostics(original, root, runner) {
54576
54691
  function claimedSourcePath(token, args, root) {
54577
54692
  const cleaned = token.replace(/^["']|["']$/g, "");
54578
54693
  if (!cleaned || cleaned.startsWith("-")) return null;
54579
- if (!DIAG_SOURCE_EXTENSIONS.has(path60.extname(cleaned).toLowerCase())) return null;
54694
+ if (!DIAG_SOURCE_EXTENSIONS.has(path61.extname(cleaned).toLowerCase())) return null;
54580
54695
  const bases = [root];
54581
54696
  const cwd = args["cwd"];
54582
54697
  if (typeof cwd === "string" && cwd.length > 0) {
54583
- bases.unshift(path60.isAbsolute(cwd) ? cwd : path60.resolve(root, cwd));
54698
+ bases.unshift(path61.isAbsolute(cwd) ? cwd : path61.resolve(root, cwd));
54584
54699
  }
54585
54700
  for (const base2 of bases) {
54586
- const candidate = path60.isAbsolute(cleaned) ? path60.normalize(cleaned) : path60.resolve(base2, cleaned);
54701
+ const candidate = path61.isAbsolute(cleaned) ? path61.normalize(cleaned) : path61.resolve(base2, cleaned);
54587
54702
  try {
54588
54703
  const contained = resolveSandboxedPath(candidate, { root });
54589
54704
  if (existsSync32(contained)) return contained;
@@ -54853,6 +54968,7 @@ var init_toolRegistry = __esm({
54853
54968
  init_tools3();
54854
54969
  init_tools4();
54855
54970
  init_tools5();
54971
+ init_screenshotTool();
54856
54972
  init_tools6();
54857
54973
  init_worldModel();
54858
54974
  init_openai_compatible();
@@ -54899,7 +55015,7 @@ var init_toolRegistry = __esm({
54899
55015
 
54900
55016
  // src/cli/metrics.ts
54901
55017
  import { promises as fs25, existsSync as existsSync33, statSync as statSync4, renameSync as renameSync4, appendFileSync as appendFileSync3, mkdirSync as mkdirSync15 } from "node:fs";
54902
- import path61 from "node:path";
55018
+ import path62 from "node:path";
54903
55019
  async function readMetrics(file2) {
54904
55020
  let raw = "";
54905
55021
  try {
@@ -54949,7 +55065,7 @@ var init_metrics3 = __esm({
54949
55065
  writeQueue = Promise.resolve();
54950
55066
  constructor(file2) {
54951
55067
  this.file = file2 ?? metricsPath();
54952
- mkdirSync15(path61.dirname(this.file), { recursive: true });
55068
+ mkdirSync15(path62.dirname(this.file), { recursive: true });
54953
55069
  }
54954
55070
  /** Metrics file path — doctor/summary readers use this. */
54955
55071
  get filePath() {
@@ -54986,8 +55102,8 @@ var init_metrics3 = __esm({
54986
55102
  maybeRotate() {
54987
55103
  if (!existsSync33(this.file)) return;
54988
55104
  try {
54989
- const stat7 = statSync4(this.file);
54990
- if (stat7.size >= METRICS_ROTATE_BYTES) {
55105
+ const stat8 = statSync4(this.file);
55106
+ if (stat8.size >= METRICS_ROTATE_BYTES) {
54991
55107
  const rotated = this.file.replace(/\.jsonl$/, ".1.jsonl");
54992
55108
  renameSync4(this.file, rotated);
54993
55109
  }
@@ -55281,15 +55397,15 @@ __export(completionProofProbe_exports, {
55281
55397
  gatherGitAttestation: () => gatherGitAttestation,
55282
55398
  harnessManifest: () => harnessManifest
55283
55399
  });
55284
- import { execFile as execFile5 } from "node:child_process";
55285
- import { promisify as promisify4 } from "node:util";
55400
+ import { execFile as execFile6 } from "node:child_process";
55401
+ import { promisify as promisify5 } from "node:util";
55286
55402
  async function readHarnessVersion() {
55287
55403
  if (cachedHarnessVersion !== null) return cachedHarnessVersion;
55288
55404
  try {
55289
- const { readFile: readFile9 } = await import("node:fs/promises");
55405
+ const { readFile: readFile11 } = await import("node:fs/promises");
55290
55406
  const { fileURLToPath: fileURLToPath4 } = await import("node:url");
55291
55407
  const pkgPath = fileURLToPath4(new URL("../../../package.json", import.meta.url));
55292
- const parsed = JSON.parse(await readFile9(pkgPath, "utf8"));
55408
+ const parsed = JSON.parse(await readFile11(pkgPath, "utf8"));
55293
55409
  if (typeof parsed.version === "string" && parsed.version.length > 0) {
55294
55410
  return cachedHarnessVersion = parsed.version;
55295
55411
  }
@@ -55313,7 +55429,7 @@ async function harnessManifest(env = process.env) {
55313
55429
  }
55314
55430
  async function git5(cwd, args) {
55315
55431
  try {
55316
- const { stdout } = await execFileAsync4("git", ["-C", cwd, ...args], {
55432
+ const { stdout } = await execFileAsync5("git", ["-C", cwd, ...args], {
55317
55433
  maxBuffer: 32 * 1024 * 1024,
55318
55434
  windowsHide: true
55319
55435
  });
@@ -55355,7 +55471,7 @@ function activeTaskContractSnapshot() {
55355
55471
  return void 0;
55356
55472
  }
55357
55473
  }
55358
- var HARNESS_VERSION_FALLBACK, ADAPTER_IDS, cachedHarnessVersion, execFileAsync4;
55474
+ var HARNESS_VERSION_FALLBACK, ADAPTER_IDS, cachedHarnessVersion, execFileAsync5;
55359
55475
  var init_completionProofProbe = __esm({
55360
55476
  "src/cli/kraken/completionProofProbe.ts"() {
55361
55477
  "use strict";
@@ -55363,7 +55479,7 @@ var init_completionProofProbe = __esm({
55363
55479
  HARNESS_VERSION_FALLBACK = "2.13.0";
55364
55480
  ADAPTER_IDS = ["node", "python", "rust", "go", "java", "dotnet"];
55365
55481
  cachedHarnessVersion = null;
55366
- execFileAsync4 = promisify4(execFile5);
55482
+ execFileAsync5 = promisify5(execFile6);
55367
55483
  }
55368
55484
  });
55369
55485
 
@@ -55467,7 +55583,7 @@ var init_completionProofAttestation = __esm({
55467
55583
  // src/cli/kraken/completionProofPersist.ts
55468
55584
  import { open, rename as rename2, rm as rm2 } from "node:fs/promises";
55469
55585
  import { randomBytes as randomBytes5 } from "node:crypto";
55470
- import path62 from "node:path";
55586
+ import path63 from "node:path";
55471
55587
  function isTruthyFlag2(v) {
55472
55588
  const n = v?.trim().toLowerCase();
55473
55589
  return n === "1" || n === "true" || n === "yes" || n === "on";
@@ -55509,8 +55625,8 @@ function isWindowsRenameBlock(err) {
55509
55625
  return code === "EPERM" || code === "ENOTEMPTY" || code === "EEXIST";
55510
55626
  }
55511
55627
  async function writeFileAtomic(target, data) {
55512
- const dir = path62.dirname(target);
55513
- const tmp = path62.join(dir, `.${path62.basename(target)}.${randomBytes5(6).toString("hex")}.tmp`);
55628
+ const dir = path63.dirname(target);
55629
+ const tmp = path63.join(dir, `.${path63.basename(target)}.${randomBytes5(6).toString("hex")}.tmp`);
55514
55630
  let fh = null;
55515
55631
  try {
55516
55632
  fh = await open(tmp, "w");
@@ -55555,8 +55671,8 @@ var init_completionProofPersist = __esm({
55555
55671
  });
55556
55672
 
55557
55673
  // src/cli/kraken/completionProof.ts
55558
- import { mkdir as mkdir3 } from "node:fs/promises";
55559
- import path63 from "node:path";
55674
+ import { mkdir as mkdir4 } from "node:fs/promises";
55675
+ import path64 from "node:path";
55560
55676
  function verdictOf(evaluation) {
55561
55677
  return evaluation.evaluation?.verdict ?? (evaluation.blocked ? "BLOCKED" : "PASS");
55562
55678
  }
@@ -55701,8 +55817,8 @@ async function writeCompletionProofDetailed(evaluation, options = {}) {
55701
55817
  const mode = options.persistenceMode ?? activeProofPersistenceMode();
55702
55818
  try {
55703
55819
  const baseDir = options.baseDir ?? process.cwd();
55704
- const dir = path63.join(baseDir, ".zelari");
55705
- await mkdir3(dir, { recursive: true });
55820
+ const dir = path64.join(baseDir, ".zelari");
55821
+ await mkdir4(dir, { recursive: true });
55706
55822
  const requested = options.attestation ?? {};
55707
55823
  const plan = requested.skipProbes || requested.verificationPlan !== void 0 ? void 0 : await defaultVerificationPlanSnapshot(baseDir);
55708
55824
  const wrapper = await buildAttestedWrapper(
@@ -55721,8 +55837,8 @@ async function writeCompletionProofDetailed(evaluation, options = {}) {
55721
55837
  baseDir
55722
55838
  );
55723
55839
  const rendered = renderCompletionProof(evaluation, options.meta ?? {}, wrapper.attestation);
55724
- const markdownPath = path63.join(dir, "completion-proof.md");
55725
- const jsonPath = path63.join(dir, "completion-proof.json");
55840
+ const markdownPath = path64.join(dir, "completion-proof.md");
55841
+ const jsonPath = path64.join(dir, "completion-proof.json");
55726
55842
  await writeFileAtomic(markdownPath, rendered.markdown);
55727
55843
  await writeFileAtomic(jsonPath, rendered.json);
55728
55844
  return { paths: { markdownPath, jsonPath }, mode, requiredBlockReason: null };
@@ -55832,12 +55948,12 @@ var init_askUserTimeout = __esm({
55832
55948
  // src/cli/state/fileStateStore.ts
55833
55949
  import { createHash as createHash17, randomUUID as randomUUID5 } from "node:crypto";
55834
55950
  import { promises as fs26 } from "node:fs";
55835
- import * as path64 from "node:path";
55951
+ import * as path65 from "node:path";
55836
55952
  function shortId() {
55837
55953
  return randomUUID5().replace(/-/g, "").slice(0, 12);
55838
55954
  }
55839
55955
  async function writeJsonAtomic(filePath, data) {
55840
- await fs26.mkdir(path64.dirname(filePath), { recursive: true });
55956
+ await fs26.mkdir(path65.dirname(filePath), { recursive: true });
55841
55957
  const tmp = `${filePath}.${process.pid}.${Date.now()}.tmp`;
55842
55958
  await fs26.writeFile(tmp, JSON.stringify(data, null, 2) + "\n", "utf8");
55843
55959
  await fs26.rename(tmp, filePath);
@@ -55898,11 +56014,11 @@ var init_fileStateStore = __esm({
55898
56014
  indexPath = "";
55899
56015
  async init(projectRoot) {
55900
56016
  this.root = projectRoot;
55901
- this.stateDir = path64.join(projectRoot, ".zelari", "state");
55902
- this.commitsDir = path64.join(this.stateDir, "commits");
55903
- this.artifactsDir = path64.join(this.stateDir, "artifacts");
55904
- this.headPath = path64.join(this.stateDir, "HEAD.json");
55905
- this.indexPath = path64.join(this.stateDir, "index.jsonl");
56017
+ this.stateDir = path65.join(projectRoot, ".zelari", "state");
56018
+ this.commitsDir = path65.join(this.stateDir, "commits");
56019
+ this.artifactsDir = path65.join(this.stateDir, "artifacts");
56020
+ this.headPath = path65.join(this.stateDir, "HEAD.json");
56021
+ this.indexPath = path65.join(this.stateDir, "index.jsonl");
55906
56022
  await fs26.mkdir(this.commitsDir, { recursive: true });
55907
56023
  await fs26.mkdir(this.artifactsDir, { recursive: true });
55908
56024
  }
@@ -55915,13 +56031,13 @@ var init_fileStateStore = __esm({
55915
56031
  const discoveries = input.discoveries ?? [];
55916
56032
  const parent = await this.head();
55917
56033
  const id3 = shortId();
55918
- const artifactRel = path64.join("artifacts", id3);
55919
- const artifactAbs = path64.join(this.artifactsDir, id3);
56034
+ const artifactRel = path65.join("artifacts", id3);
56035
+ const artifactAbs = path65.join(this.artifactsDir, id3);
55920
56036
  await fs26.mkdir(artifactAbs, { recursive: true });
55921
56037
  const summary = defaultSummary(input, discoveries);
55922
- await fs26.writeFile(path64.join(artifactAbs, "summary.md"), summary + "\n", "utf8");
55923
- await writeJsonAtomic(path64.join(artifactAbs, "discoveries.json"), discoveries);
55924
- await writeJsonAtomic(path64.join(artifactAbs, "verification.json"), input.verification);
56038
+ await fs26.writeFile(path65.join(artifactAbs, "summary.md"), summary + "\n", "utf8");
56039
+ await writeJsonAtomic(path65.join(artifactAbs, "discoveries.json"), discoveries);
56040
+ await writeJsonAtomic(path65.join(artifactAbs, "verification.json"), input.verification);
55925
56041
  const meta3 = {
55926
56042
  id: id3,
55927
56043
  parentId: parent?.id ?? null,
@@ -55933,14 +56049,14 @@ var init_fileStateStore = __esm({
55933
56049
  workspaceCheckpointId: input.workspaceCheckpointId,
55934
56050
  verification: {
55935
56051
  ...input.verification,
55936
- reportPath: input.verification.reportPath ?? path64.join(".zelari", "state", artifactRel, "verification.json").replace(/\\/g, "/")
56052
+ reportPath: input.verification.reportPath ?? path65.join(".zelari", "state", artifactRel, "verification.json").replace(/\\/g, "/")
55937
56053
  },
55938
56054
  changedPaths: input.changedPaths ?? [],
55939
56055
  stablePromptHash: input.stablePromptHash,
55940
56056
  discoveryCount: discoveries.length,
55941
56057
  artifactDir: artifactRel.replace(/\\/g, "/")
55942
56058
  };
55943
- await writeJsonAtomic(path64.join(this.commitsDir, `${id3}.json`), meta3);
56059
+ await writeJsonAtomic(path65.join(this.commitsDir, `${id3}.json`), meta3);
55944
56060
  await writeJsonAtomic(this.headPath, { id: id3, updatedAt: meta3.createdAt });
55945
56061
  await fs26.appendFile(this.indexPath, JSON.stringify({ id: id3, createdAt: meta3.createdAt, label: meta3.label }) + "\n", "utf8");
55946
56062
  return stripStored(meta3);
@@ -55951,7 +56067,7 @@ var init_fileStateStore = __esm({
55951
56067
  return this.get(head.id);
55952
56068
  }
55953
56069
  async get(id3) {
55954
- const stored = await readJsonFile(path64.join(this.commitsDir, `${id3}.json`));
56070
+ const stored = await readJsonFile(path65.join(this.commitsDir, `${id3}.json`));
55955
56071
  return stored ? stripStored(stored) : null;
55956
56072
  }
55957
56073
  async list(limit = 20) {
@@ -55990,9 +56106,9 @@ var init_fileStateStore = __esm({
55990
56106
  async loadDiscoveries(id3) {
55991
56107
  const meta3 = id3 ? await this.get(id3) : await this.head();
55992
56108
  if (!meta3) return [];
55993
- const stored = await readJsonFile(path64.join(this.commitsDir, `${meta3.id}.json`));
56109
+ const stored = await readJsonFile(path65.join(this.commitsDir, `${meta3.id}.json`));
55994
56110
  if (!stored?.artifactDir) return [];
55995
- const discPath = path64.join(this.stateDir, stored.artifactDir, "discoveries.json");
56111
+ const discPath = path65.join(this.stateDir, stored.artifactDir, "discoveries.json");
55996
56112
  return await readJsonFile(discPath) ?? [];
55997
56113
  }
55998
56114
  async materializeContext(id3, maxChars = DEFAULT_MATERIALIZE_CHARS) {
@@ -56595,10 +56711,10 @@ var init_mode = __esm({
56595
56711
 
56596
56712
  // src/cli/headless.ts
56597
56713
  import { readFileSync as readFileSync24 } from "node:fs";
56598
- import path65 from "node:path";
56714
+ import path66 from "node:path";
56599
56715
  function resolveHeadlessCwd(opts) {
56600
56716
  const raw = typeof opts.cwd === "string" ? opts.cwd.trim() : "";
56601
- return path65.resolve(raw.length > 0 ? raw : process.cwd());
56717
+ return path66.resolve(raw.length > 0 ? raw : process.cwd());
56602
56718
  }
56603
56719
  function defaultProfileForMode(mode) {
56604
56720
  switch (mode) {
@@ -57700,7 +57816,7 @@ var init_planDetect = __esm({
57700
57816
  // src/cli/memory/legacyImport.ts
57701
57817
  import { createHash as createHash18 } from "node:crypto";
57702
57818
  import { promises as fs27 } from "node:fs";
57703
- import * as path66 from "node:path";
57819
+ import * as path67 from "node:path";
57704
57820
  function sourceId(fact, line) {
57705
57821
  return `jsonl:${fact.id ?? createHash18("sha256").update(line).digest("hex")}`;
57706
57822
  }
@@ -57718,7 +57834,7 @@ function timestamp(value) {
57718
57834
  }
57719
57835
  async function importLegacyMemoryLog(backend, service) {
57720
57836
  const result = { found: 0, imported: 0, skipped: 0, corrupt: 0 };
57721
- const logPath = path66.join(path66.dirname(backend.databasePath), "log.jsonl");
57837
+ const logPath = path67.join(path67.dirname(backend.databasePath), "log.jsonl");
57722
57838
  let raw;
57723
57839
  try {
57724
57840
  raw = await fs27.readFile(logPath, "utf8");
@@ -57901,7 +58017,7 @@ var init_sqliteCodec = __esm({
57901
58017
  // src/cli/memory/sqliteRpc.ts
57902
58018
  import { existsSync as existsSync36 } from "node:fs";
57903
58019
  import { fileURLToPath as fileURLToPath2, pathToFileURL as pathToFileURL2 } from "node:url";
57904
- import * as path67 from "node:path";
58020
+ import * as path68 from "node:path";
57905
58021
  import { Worker } from "node:worker_threads";
57906
58022
  function isBusy(error51) {
57907
58023
  const candidate = error51;
@@ -57910,10 +58026,10 @@ function isBusy(error51) {
57910
58026
  );
57911
58027
  }
57912
58028
  function resolveWorkerUrl() {
57913
- const here = path67.dirname(fileURLToPath2(import.meta.url));
57914
- const direct = path67.join(here, "sqliteWorker.mjs");
58029
+ const here = path68.dirname(fileURLToPath2(import.meta.url));
58030
+ const direct = path68.join(here, "sqliteWorker.mjs");
57915
58031
  if (existsSync36(direct)) return pathToFileURL2(direct);
57916
- return pathToFileURL2(path67.join(here, "memory", "sqliteWorker.mjs"));
58032
+ return pathToFileURL2(path68.join(here, "memory", "sqliteWorker.mjs"));
57917
58033
  }
57918
58034
  var SqliteWorkerRpc;
57919
58035
  var init_sqliteRpc = __esm({
@@ -58202,7 +58318,7 @@ WHERE NOT EXISTS (SELECT 1 FROM memory_fts f WHERE f.node_id = n.id);
58202
58318
  // src/cli/memory/sqliteBackend.ts
58203
58319
  import { createHash as createHash19, randomUUID as randomUUID6 } from "node:crypto";
58204
58320
  import { promises as fs28 } from "node:fs";
58205
- import * as path68 from "node:path";
58321
+ import * as path69 from "node:path";
58206
58322
  function boundedLimit(value, fallback = 50) {
58207
58323
  return Math.max(1, Math.min(Math.floor(value ?? fallback), 1e5));
58208
58324
  }
@@ -58264,20 +58380,20 @@ VALUES (${Array.from({ length: 19 }, () => "?").join(",")})`;
58264
58380
  try {
58265
58381
  resolved = await fs28.realpath(projectRoot);
58266
58382
  } catch {
58267
- resolved = path68.resolve(projectRoot);
58383
+ resolved = path69.resolve(projectRoot);
58268
58384
  }
58269
58385
  if (this.initialized && resolved === this.projectRoot) return;
58270
58386
  if (this.initialized) await this.close();
58271
58387
  const filename = this.options.filename ?? "memory.db";
58272
- if (path68.basename(filename) !== filename || filename === "." || filename === "..") {
58388
+ if (path69.basename(filename) !== filename || filename === "." || filename === "..") {
58273
58389
  throw new Error("SQLite memory filename must not contain a path.");
58274
58390
  }
58275
- const zelariDirectory = path68.join(resolved, ".zelari");
58276
- const directory = path68.join(zelariDirectory, "memory");
58391
+ const zelariDirectory = path69.join(resolved, ".zelari");
58392
+ const directory = path69.join(zelariDirectory, "memory");
58277
58393
  for (const candidate of [zelariDirectory, directory]) {
58278
- let stat7;
58394
+ let stat8;
58279
58395
  try {
58280
- stat7 = await fs28.lstat(candidate);
58396
+ stat8 = await fs28.lstat(candidate);
58281
58397
  } catch (error51) {
58282
58398
  if (error51.code !== "ENOENT") throw error51;
58283
58399
  try {
@@ -58285,19 +58401,19 @@ VALUES (${Array.from({ length: 19 }, () => "?").join(",")})`;
58285
58401
  } catch (mkdirError) {
58286
58402
  if (mkdirError.code !== "EEXIST") throw mkdirError;
58287
58403
  }
58288
- stat7 = await fs28.lstat(candidate);
58404
+ stat8 = await fs28.lstat(candidate);
58289
58405
  }
58290
- if (stat7.isSymbolicLink() || !stat7.isDirectory()) {
58406
+ if (stat8.isSymbolicLink() || !stat8.isDirectory()) {
58291
58407
  throw new Error(`Memory directory is not a real directory: ${candidate}`);
58292
58408
  }
58293
58409
  }
58294
58410
  const canonicalDirectory = await fs28.realpath(directory);
58295
- const relativeDirectory = path68.relative(resolved, canonicalDirectory);
58296
- if (relativeDirectory.startsWith("..") || path68.isAbsolute(relativeDirectory)) {
58411
+ const relativeDirectory = path69.relative(resolved, canonicalDirectory);
58412
+ if (relativeDirectory.startsWith("..") || path69.isAbsolute(relativeDirectory)) {
58297
58413
  throw new Error("SQLite memory directory resolves outside the active project.");
58298
58414
  }
58299
58415
  this.projectRoot = resolved;
58300
- this.databasePath = path68.join(canonicalDirectory, filename);
58416
+ this.databasePath = path69.join(canonicalDirectory, filename);
58301
58417
  const opened = await this.rpc.open({
58302
58418
  dbPath: this.databasePath,
58303
58419
  schemaSql: SQLITE_MEMORY_BASE_SCHEMA,
@@ -58830,7 +58946,7 @@ __export(serviceFactory_exports, {
58830
58946
  });
58831
58947
  import { createHash as createHash20 } from "node:crypto";
58832
58948
  import { promises as fs29 } from "node:fs";
58833
- import * as path69 from "node:path";
58949
+ import * as path70 from "node:path";
58834
58950
  function isMemoryV2Enabled(env = process.env) {
58835
58951
  if (env.ZELARI_MEMORY === "0") return false;
58836
58952
  if (env.ZELARI_MEMORY_BACKEND === "file" || env.ZELARI_MEMORY_BACKEND === "jsonl") return false;
@@ -58851,7 +58967,7 @@ async function canonicalProjectId(projectRoot) {
58851
58967
  try {
58852
58968
  canonical = await fs29.realpath(projectRoot);
58853
58969
  } catch {
58854
- canonical = path69.resolve(projectRoot);
58970
+ canonical = path70.resolve(projectRoot);
58855
58971
  }
58856
58972
  canonical = canonical.replace(/\\/g, "/").replace(/\/$/, "");
58857
58973
  if (process.platform === "win32") canonical = canonical.toLocaleLowerCase("en-US");
@@ -59553,8 +59669,8 @@ function readPlan(ctx) {
59553
59669
  } catch {
59554
59670
  }
59555
59671
  }
59556
- const path99 = workspaceFile(ctx.rootDir, "plan");
59557
- const doc = ctx.storage.readIfExists(path99);
59672
+ const path100 = workspaceFile(ctx.rootDir, "plan");
59673
+ const doc = ctx.storage.readIfExists(path100);
59558
59674
  if (!doc) return { phases: [], tasks: [], milestones: [] };
59559
59675
  const meta3 = doc.meta;
59560
59676
  return {
@@ -59735,7 +59851,7 @@ function addMilestoneRecord(ctx, summary, input) {
59735
59851
  dueDate: input.dueDate,
59736
59852
  targetVersion: version2
59737
59853
  });
59738
- const path99 = join31(ctx.rootDir, "milestones", `${id3}.md`);
59854
+ const path100 = join31(ctx.rootDir, "milestones", `${id3}.md`);
59739
59855
  const meta3 = {
59740
59856
  kind: "milestone",
59741
59857
  id: id3,
@@ -59752,7 +59868,7 @@ function addMilestoneRecord(ctx, summary, input) {
59752
59868
  `Target version: ${version2}`,
59753
59869
  ""
59754
59870
  ].join("\n");
59755
- ctx.storage.write(path99, meta3, body);
59871
+ ctx.storage.write(path100, meta3, body);
59756
59872
  return { id: id3, created: true };
59757
59873
  }
59758
59874
  function readPlanSummary(ctx) {
@@ -59956,7 +60072,7 @@ function addIdeaStub(ctx) {
59956
60072
  const tags = args["tags"] ?? [];
59957
60073
  const category = args["category"] ?? "General";
59958
60074
  const id3 = `${nextAdrId(ctx)}-${slugify3(title)}`;
59959
- const path99 = workspaceArtifact(ctx.rootDir, "decisions", id3);
60075
+ const path100 = workspaceArtifact(ctx.rootDir, "decisions", id3);
59960
60076
  const meta3 = {
59961
60077
  kind: "adr",
59962
60078
  status: "proposed",
@@ -59982,7 +60098,7 @@ function addIdeaStub(ctx) {
59982
60098
  ...consequences.map((c) => `- ${c}`),
59983
60099
  ""
59984
60100
  ].join("\n");
59985
- ctx.storage.write(path99, meta3, body);
60101
+ ctx.storage.write(path100, meta3, body);
59986
60102
  return `ADR ${id3} created: "${title}". Status: proposed. Promote to accepted via /update ADR or manual edit.`;
59987
60103
  });
59988
60104
  }
@@ -60064,14 +60180,14 @@ function createDocumentStub(ctx) {
60064
60180
  ctx.storage.write(risksPath, riskMeta, content);
60065
60181
  return `Document "${title}" created at risks.md (workspace root).`;
60066
60182
  }
60067
- const path99 = workspaceArtifact(ctx.rootDir, "docs", slug);
60183
+ const path100 = workspaceArtifact(ctx.rootDir, "docs", slug);
60068
60184
  const meta3 = {
60069
60185
  kind: "doc",
60070
60186
  id: slug,
60071
60187
  date: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10),
60072
60188
  tags
60073
60189
  };
60074
- ctx.storage.write(path99, meta3, content);
60190
+ ctx.storage.write(path100, meta3, content);
60075
60191
  return `Document "${title}" created at docs/${slug}.md.`;
60076
60192
  });
60077
60193
  }
@@ -60696,10 +60812,10 @@ function getUserMcpPath() {
60696
60812
  function getProjectMcpPath(projectRoot) {
60697
60813
  return join32(projectRoot, ".zelari", "mcp.json");
60698
60814
  }
60699
- function readFile7(path99) {
60700
- if (!existsSync42(path99)) return {};
60815
+ function readFile9(path100) {
60816
+ if (!existsSync42(path100)) return {};
60701
60817
  try {
60702
- const parsed = JSON.parse(readFileSync30(path99, "utf8"));
60818
+ const parsed = JSON.parse(readFileSync30(path100, "utf8"));
60703
60819
  const out = {};
60704
60820
  for (const [name, cfg] of Object.entries(parsed.mcpServers ?? {})) {
60705
60821
  const hasCommand = !!cfg && typeof cfg.command === "string" && !!cfg.command.trim();
@@ -60721,17 +60837,17 @@ function readFile7(path99) {
60721
60837
  return {};
60722
60838
  }
60723
60839
  }
60724
- function writeFile3(path99, servers) {
60725
- mkdirSync17(dirname9(path99), { recursive: true });
60840
+ function writeFile3(path100, servers) {
60841
+ mkdirSync17(dirname9(path100), { recursive: true });
60726
60842
  const body = { mcpServers: servers };
60727
- writeFileSync19(path99, `${JSON.stringify(body, null, 2)}
60843
+ writeFileSync19(path100, `${JSON.stringify(body, null, 2)}
60728
60844
  `, "utf8");
60729
60845
  }
60730
60846
  function listMcpServers(projectRoot) {
60731
60847
  const userPath = getUserMcpPath();
60732
- const userServers = readFile7(userPath);
60848
+ const userServers = readFile9(userPath);
60733
60849
  const projectPath = projectRoot && projectRoot.trim() ? getProjectMcpPath(projectRoot.trim()) : null;
60734
- const projectServers = projectPath ? readFile7(projectPath) : {};
60850
+ const projectServers = projectPath ? readFile9(projectPath) : {};
60735
60851
  const servers = [];
60736
60852
  for (const [name, cfg] of Object.entries(userServers)) {
60737
60853
  servers.push({ name, ...cfg, scope: "user", path: userPath });
@@ -60762,9 +60878,9 @@ function upsertMcpServer(opts) {
60762
60878
  error: "either command (stdio) or url (http) is required"
60763
60879
  };
60764
60880
  }
60765
- let path99;
60881
+ let path100;
60766
60882
  if (opts.scope === "user") {
60767
- path99 = getUserMcpPath();
60883
+ path100 = getUserMcpPath();
60768
60884
  } else {
60769
60885
  const root = opts.projectRoot?.trim();
60770
60886
  if (!root) {
@@ -60773,9 +60889,9 @@ function upsertMcpServer(opts) {
60773
60889
  error: "projectRoot required for project scope (Open Folder first)"
60774
60890
  };
60775
60891
  }
60776
- path99 = getProjectMcpPath(root);
60892
+ path100 = getProjectMcpPath(root);
60777
60893
  }
60778
- const current = readFile7(path99);
60894
+ const current = readFile9(path100);
60779
60895
  current[name] = {
60780
60896
  command: hasCommand ? opts.config.command.trim() : void 0,
60781
60897
  args: opts.config.args,
@@ -60786,21 +60902,21 @@ function upsertMcpServer(opts) {
60786
60902
  serial: opts.config.serial,
60787
60903
  enabled: opts.config.enabled !== false
60788
60904
  };
60789
- writeFile3(path99, current);
60790
- return { ok: true, path: path99 };
60905
+ writeFile3(path100, current);
60906
+ return { ok: true, path: path100 };
60791
60907
  }
60792
60908
  function removeMcpServer(opts) {
60793
- const path99 = opts.scope === "user" ? getUserMcpPath() : opts.projectRoot ? getProjectMcpPath(opts.projectRoot) : null;
60794
- if (!path99) {
60909
+ const path100 = opts.scope === "user" ? getUserMcpPath() : opts.projectRoot ? getProjectMcpPath(opts.projectRoot) : null;
60910
+ if (!path100) {
60795
60911
  return { ok: false, error: "projectRoot required for project scope" };
60796
60912
  }
60797
- const current = readFile7(path99);
60913
+ const current = readFile9(path100);
60798
60914
  if (!(opts.name in current)) {
60799
- return { ok: false, error: `Server "${opts.name}" not found in ${path99}` };
60915
+ return { ok: false, error: `Server "${opts.name}" not found in ${path100}` };
60800
60916
  }
60801
60917
  delete current[opts.name];
60802
- writeFile3(path99, current);
60803
- return { ok: true, path: path99 };
60918
+ writeFile3(path100, current);
60919
+ return { ok: true, path: path100 };
60804
60920
  }
60805
60921
  var init_mcpConfigIo = __esm({
60806
60922
  "src/cli/mcp/mcpConfigIo.ts"() {
@@ -61269,12 +61385,12 @@ __export(agentsMd_exports, {
61269
61385
  import { existsSync as existsSync44, readFileSync as readFileSync32, writeFileSync as writeFileSync20 } from "node:fs";
61270
61386
  import { createHash as createHash21 } from "node:crypto";
61271
61387
  import { join as join34 } from "node:path";
61272
- import { readFile as readFile8 } from "node:fs/promises";
61388
+ import { readFile as readFile10 } from "node:fs/promises";
61273
61389
  async function readPackageJson3(projectRoot) {
61274
- const path99 = join34(projectRoot, "package.json");
61275
- if (!existsSync44(path99)) return null;
61390
+ const path100 = join34(projectRoot, "package.json");
61391
+ if (!existsSync44(path100)) return null;
61276
61392
  try {
61277
- return JSON.parse(await readFile8(path99, "utf8"));
61393
+ return JSON.parse(await readFile10(path100, "utf8"));
61278
61394
  } catch {
61279
61395
  return null;
61280
61396
  }
@@ -61356,9 +61472,9 @@ async function genBuild(ctx) {
61356
61472
  ].join("\n");
61357
61473
  }
61358
61474
  async function genOpenQuestions(ctx) {
61359
- const path99 = join34(ctx.rootDir, "risks.md");
61360
- if (!existsSync44(path99)) return "_No open questions._";
61361
- const content = readFileSync32(path99, "utf8");
61475
+ const path100 = join34(ctx.rootDir, "risks.md");
61476
+ if (!existsSync44(path100)) return "_No open questions._";
61477
+ const content = readFileSync32(path100, "utf8");
61362
61478
  const lines = content.split("\n");
61363
61479
  const questions = [];
61364
61480
  let currentTitle = "";
@@ -61632,9 +61748,9 @@ function versionKey(value) {
61632
61748
  function firstString2(v) {
61633
61749
  return typeof v === "string" && v.trim().length > 0 ? v : null;
61634
61750
  }
61635
- function readFileSyncSafe(path99) {
61751
+ function readFileSyncSafe(path100) {
61636
61752
  try {
61637
- return readFileSync33(path99, "utf8");
61753
+ return readFileSync33(path100, "utf8");
61638
61754
  } catch {
61639
61755
  return null;
61640
61756
  }
@@ -61882,7 +61998,7 @@ __export(evidenceFromSpine_exports, {
61882
61998
  evidenceRefsFromEventLines: () => evidenceRefsFromEventLines
61883
61999
  });
61884
62000
  import { existsSync as existsSync47, readFileSync as readFileSync35 } from "node:fs";
61885
- import path70 from "node:path";
62001
+ import path71 from "node:path";
61886
62002
  function asRecord2(v) {
61887
62003
  return v && typeof v === "object" && !Array.isArray(v) ? v : void 0;
61888
62004
  }
@@ -61920,7 +62036,7 @@ function evidenceRefsFromEventLines(lines) {
61920
62036
  }
61921
62037
  function collectSessionEvidenceRefs(sessionId2) {
61922
62038
  try {
61923
- const file2 = path70.join(sessionsDir(), sessionId2, "events.jsonl");
62039
+ const file2 = path71.join(sessionsDir(), sessionId2, "events.jsonl");
61924
62040
  if (!existsSync47(file2)) return [];
61925
62041
  return evidenceRefsFromEventLines(readFileSync35(file2, "utf8").split("\n"));
61926
62042
  } catch {
@@ -62170,8 +62286,8 @@ async function runPostCouncilHook(ctx, options) {
62170
62286
  sources: scope.sources
62171
62287
  } : void 0
62172
62288
  });
62173
- const path99 = writeCouncilCompletion(ctx.rootDir, completion);
62174
- completionHook = { ran: true, path: path99, completion };
62289
+ const path100 = writeCouncilCompletion(ctx.rootDir, completion);
62290
+ completionHook = { ran: true, path: path100, completion };
62175
62291
  } catch (err) {
62176
62292
  completionHook = {
62177
62293
  ran: true,
@@ -62216,7 +62332,7 @@ import {
62216
62332
  writeFileSync as writeFileSync22,
62217
62333
  mkdirSync as mkdirSync18
62218
62334
  } from "node:fs";
62219
- import path71 from "node:path";
62335
+ import path72 from "node:path";
62220
62336
  var FeedbackStore;
62221
62337
  var init_councilFeedback = __esm({
62222
62338
  "src/cli/councilFeedback.ts"() {
@@ -62333,7 +62449,7 @@ var init_councilFeedback = __esm({
62333
62449
  }
62334
62450
  }
62335
62451
  save() {
62336
- mkdirSync18(path71.dirname(this.file), { recursive: true });
62452
+ mkdirSync18(path72.dirname(this.file), { recursive: true });
62337
62453
  writeFileSync22(
62338
62454
  this.file,
62339
62455
  JSON.stringify({ entries: this.entries }, null, 2),
@@ -62408,12 +62524,12 @@ __export(ledger_exports, {
62408
62524
  readLedger: () => readLedger
62409
62525
  });
62410
62526
  import { appendFileSync as appendFileSync4, existsSync as existsSync50, mkdirSync as mkdirSync19, readFileSync as readFileSync38 } from "node:fs";
62411
- import path72 from "node:path";
62527
+ import path73 from "node:path";
62412
62528
  function evolutionMode(env = process.env) {
62413
62529
  return env[EVOLUTION_ENV] === "shadow" ? "shadow" : "0";
62414
62530
  }
62415
62531
  function ledgerPath(cwd) {
62416
- return path72.join(cwd, LEDGER_REL);
62532
+ return path73.join(cwd, LEDGER_REL);
62417
62533
  }
62418
62534
  function appendLedgerEntry(cwd, entry) {
62419
62535
  if (evolutionMode() === "0") {
@@ -62421,7 +62537,7 @@ function appendLedgerEntry(cwd, entry) {
62421
62537
  }
62422
62538
  try {
62423
62539
  const file2 = ledgerPath(cwd);
62424
- mkdirSync19(path72.dirname(file2), { recursive: true });
62540
+ mkdirSync19(path73.dirname(file2), { recursive: true });
62425
62541
  appendFileSync4(file2, `${JSON.stringify(entry)}
62426
62542
  `, "utf8");
62427
62543
  return { written: true, path: file2 };
@@ -62522,7 +62638,7 @@ var init_ledger = __esm({
62522
62638
  "src/cli/evolution/ledger.ts"() {
62523
62639
  "use strict";
62524
62640
  EVOLUTION_ENV = "ZELARI_EVOLUTION";
62525
- LEDGER_REL = path72.join(".zelari", "evolution", "ledger.jsonl");
62641
+ LEDGER_REL = path73.join(".zelari", "evolution", "ledger.jsonl");
62526
62642
  TIER_WEIGHTS = {
62527
62643
  build: 1,
62528
62644
  "tool-output": 1,
@@ -62664,7 +62780,7 @@ __export(fileBackend_exports, {
62664
62780
  });
62665
62781
  import { randomUUID as randomUUID7 } from "node:crypto";
62666
62782
  import { promises as fs31 } from "node:fs";
62667
- import * as path73 from "node:path";
62783
+ import * as path74 from "node:path";
62668
62784
  function tokenize2(text) {
62669
62785
  return text.toLowerCase().split(/[^\p{L}\p{N}]+/u).filter((t) => t.length >= 3);
62670
62786
  }
@@ -62717,8 +62833,8 @@ var init_fileBackend = __esm({
62717
62833
  logPath = "";
62718
62834
  memoryDir = "";
62719
62835
  async init(projectRoot) {
62720
- this.memoryDir = path73.join(projectRoot, ".zelari", "memory");
62721
- this.logPath = path73.join(this.memoryDir, "log.jsonl");
62836
+ this.memoryDir = path74.join(projectRoot, ".zelari", "memory");
62837
+ this.logPath = path74.join(this.memoryDir, "log.jsonl");
62722
62838
  await fs31.mkdir(this.memoryDir, { recursive: true });
62723
62839
  }
62724
62840
  async add(content, metadata2 = {}, graph) {
@@ -62791,12 +62907,12 @@ var init_fileBackend = __esm({
62791
62907
 
62792
62908
  // src/cli/traceStore.ts
62793
62909
  import { promises as fs32 } from "node:fs";
62794
- import * as path74 from "node:path";
62910
+ import * as path75 from "node:path";
62795
62911
  function traceDir(projectRoot) {
62796
- return path74.join(projectRoot, ".zelari", "trace");
62912
+ return path75.join(projectRoot, ".zelari", "trace");
62797
62913
  }
62798
62914
  function tracePath(projectRoot, missionId) {
62799
- return path74.join(traceDir(projectRoot), `${missionId}.json`);
62915
+ return path75.join(traceDir(projectRoot), `${missionId}.json`);
62800
62916
  }
62801
62917
  async function saveTrace(projectRoot, missionId, entries) {
62802
62918
  const dir = traceDir(projectRoot);
@@ -62833,7 +62949,7 @@ __export(zelariMission_exports, {
62833
62949
  });
62834
62950
  import { randomUUID as randomUUID8 } from "node:crypto";
62835
62951
  import { promises as fs33 } from "node:fs";
62836
- import * as path75 from "node:path";
62952
+ import * as path76 from "node:path";
62837
62953
  function resolveMaxIterations(env = process.env) {
62838
62954
  const raw = env.ZELARI_MISSION_MAX_ITER;
62839
62955
  const n = raw ? Number.parseInt(raw, 10) : DEFAULT_MAX_ITER;
@@ -62876,10 +62992,10 @@ function isMissionAutoStart(env = process.env) {
62876
62992
  return env.ZELARI_MISSION_AUTO === "1";
62877
62993
  }
62878
62994
  async function writeMissionState(projectRoot, state3) {
62879
- const dir = path75.join(projectRoot, ".zelari");
62995
+ const dir = path76.join(projectRoot, ".zelari");
62880
62996
  await fs33.mkdir(dir, { recursive: true });
62881
62997
  await fs33.writeFile(
62882
- path75.join(dir, "mission-state.json"),
62998
+ path76.join(dir, "mission-state.json"),
62883
62999
  JSON.stringify(state3, null, 2) + "\n",
62884
63000
  "utf8"
62885
63001
  );
@@ -63568,7 +63684,7 @@ function safeSocketPath(socketPath) {
63568
63684
  return socketPath.trim();
63569
63685
  }
63570
63686
  function startPermissionBroker(socketPath, handlers, opts) {
63571
- const path99 = safeSocketPath(socketPath);
63687
+ const path100 = safeSocketPath(socketPath);
63572
63688
  const requestTimeoutMs = opts?.requestTimeoutMs ?? PERMISSION_BROKER_DEFAULT_TIMEOUT_MS;
63573
63689
  const sockets = /* @__PURE__ */ new Set();
63574
63690
  const server = createServer2((socket) => {
@@ -63668,10 +63784,10 @@ function startPermissionBroker(socketPath, handlers, opts) {
63668
63784
  return new Promise((resolve9, reject) => {
63669
63785
  const onError = (err) => reject(err);
63670
63786
  server.once("error", onError);
63671
- server.listen(path99, () => {
63787
+ server.listen(path100, () => {
63672
63788
  server.removeListener("error", onError);
63673
63789
  resolve9({
63674
- socketPath: path99,
63790
+ socketPath: path100,
63675
63791
  stop: () => new Promise((res) => {
63676
63792
  for (const s of sockets) s.destroy();
63677
63793
  sockets.clear();
@@ -63682,7 +63798,7 @@ function startPermissionBroker(socketPath, handlers, opts) {
63682
63798
  if (done) return;
63683
63799
  done = true;
63684
63800
  if (process.platform !== "win32") {
63685
- unlink(path99, () => res());
63801
+ unlink(path100, () => res());
63686
63802
  } else {
63687
63803
  res();
63688
63804
  }
@@ -63695,11 +63811,11 @@ function startPermissionBroker(socketPath, handlers, opts) {
63695
63811
  });
63696
63812
  }
63697
63813
  function requestBrokerAsk(socketPath, ask, opts) {
63698
- const path99 = safeSocketPath(socketPath);
63814
+ const path100 = safeSocketPath(socketPath);
63699
63815
  const requestTimeoutMs = opts?.requestTimeoutMs ?? PERMISSION_BROKER_DEFAULT_TIMEOUT_MS;
63700
63816
  const connectTimeoutMs = opts?.connectTimeoutMs ?? PERMISSION_BROKER_DEFAULT_CONNECT_TIMEOUT_MS;
63701
63817
  return new Promise((resolve9, reject) => {
63702
- const socket = connect(path99);
63818
+ const socket = connect(path100);
63703
63819
  let buffer = "";
63704
63820
  let settled = false;
63705
63821
  const settle = (fn) => {
@@ -63714,7 +63830,7 @@ function requestBrokerAsk(socketPath, ask, opts) {
63714
63830
  settle(
63715
63831
  () => reject(
63716
63832
  new Error(
63717
- `permission broker unavailable at "${path99}" (connect timed out after ${connectTimeoutMs}ms)`
63833
+ `permission broker unavailable at "${path100}" (connect timed out after ${connectTimeoutMs}ms)`
63718
63834
  )
63719
63835
  )
63720
63836
  );
@@ -64903,7 +65019,7 @@ var init_prereqChecks = __esm({
64903
65019
 
64904
65020
  // src/cli/plugins/prefs.ts
64905
65021
  import { existsSync as existsSync53, readFileSync as readFileSync40, writeFileSync as writeFileSync23, mkdirSync as mkdirSync20 } from "node:fs";
64906
- import path81 from "node:path";
65022
+ import path82 from "node:path";
64907
65023
  function getPluginPrefsPath() {
64908
65024
  return pluginsPrefsPath();
64909
65025
  }
@@ -64926,7 +65042,7 @@ function getPluginPrefs() {
64926
65042
  }
64927
65043
  function writePluginPrefs(prefs) {
64928
65044
  const file2 = getPluginPrefsPath();
64929
- mkdirSync20(path81.dirname(file2), { recursive: true });
65045
+ mkdirSync20(path82.dirname(file2), { recursive: true });
64930
65046
  writeFileSync23(file2, JSON.stringify(prefs, null, 2), {
64931
65047
  encoding: "utf-8",
64932
65048
  mode: 384
@@ -64964,7 +65080,7 @@ __export(registry_exports, {
64964
65080
  isBinaryOnPath: () => isBinaryOnPath
64965
65081
  });
64966
65082
  import { existsSync as existsSync54 } from "node:fs";
64967
- import path82 from "node:path";
65083
+ import path83 from "node:path";
64968
65084
  function detectLocalBin(bin) {
64969
65085
  return (cwd) => {
64970
65086
  try {
@@ -64982,7 +65098,7 @@ function isBinaryOnPath(bin, opts = {}) {
64982
65098
  const platform = opts.platform ?? process.platform;
64983
65099
  const exists = opts.exists ?? existsSync54;
64984
65100
  const pathEnv = opts.pathEnv ?? process.env.PATH ?? "";
64985
- const pathMod = platform === "win32" ? path82.win32 : path82.posix;
65101
+ const pathMod = platform === "win32" ? path83.win32 : path83.posix;
64986
65102
  const sep4 = platform === "win32" ? ";" : ":";
64987
65103
  const dirs = pathEnv.split(sep4).filter((d) => d.length > 0);
64988
65104
  const candidates = [bin];
@@ -66077,7 +66193,7 @@ var init_policy = __esm({
66077
66193
 
66078
66194
  // src/cli/orchestration/facts.ts
66079
66195
  import { promises as fs43 } from "node:fs";
66080
- import path86 from "node:path";
66196
+ import path87 from "node:path";
66081
66197
  async function collectRepoFileCount(root = process.cwd()) {
66082
66198
  try {
66083
66199
  await fs43.readdir(root);
@@ -66097,7 +66213,7 @@ async function collectRepoFileCount(root = process.cwd()) {
66097
66213
  }
66098
66214
  for (const e of entries) {
66099
66215
  if (e.isDirectory()) {
66100
- if (!SKIP_DIRS.has(e.name)) queue.push(path86.join(dir, e.name));
66216
+ if (!SKIP_DIRS.has(e.name)) queue.push(path87.join(dir, e.name));
66101
66217
  } else if (e.isFile()) {
66102
66218
  count++;
66103
66219
  if (count > MAX_WALK_FILES) return count;
@@ -66195,7 +66311,7 @@ var init_streamScrub = __esm({
66195
66311
  });
66196
66312
 
66197
66313
  // src/cli/harnessState.ts
66198
- import path87 from "node:path";
66314
+ import path88 from "node:path";
66199
66315
  function asString4(v) {
66200
66316
  return typeof v === "string" ? v : "";
66201
66317
  }
@@ -66370,7 +66486,7 @@ function contractFor(t) {
66370
66486
  };
66371
66487
  }
66372
66488
  async function readHarnessState(sessionDir) {
66373
- const report = await readSessionLog(path87.join(sessionDir, "events.jsonl"));
66489
+ const report = await readSessionLog(path88.join(sessionDir, "events.jsonl"));
66374
66490
  return deriveHarnessState(report.events);
66375
66491
  }
66376
66492
  var init_harnessState = __esm({
@@ -66381,12 +66497,12 @@ var init_harnessState = __esm({
66381
66497
  });
66382
66498
 
66383
66499
  // src/cli/headless/harnessStateEmit.ts
66384
- import path88 from "node:path";
66500
+ import path89 from "node:path";
66385
66501
  async function emitHarnessStateEvent(opts) {
66386
66502
  if (opts.output !== "json") return;
66387
66503
  try {
66388
66504
  const sessionsDir2 = resolveSessionsDir({ workspaceRoot: opts.workspaceRoot });
66389
- const state3 = await readHarnessState(path88.join(sessionsDir2, opts.spine.sessionId));
66505
+ const state3 = await readHarnessState(path89.join(sessionsDir2, opts.spine.sessionId));
66390
66506
  opts.emitEvent({ type: "harness_state", ...state3 });
66391
66507
  } catch (err) {
66392
66508
  const msg = err instanceof Error ? err.message : String(err);
@@ -66943,13 +67059,13 @@ var init_verifierLifecycle = __esm({
66943
67059
 
66944
67060
  // src/cli/extensions/sandboxedFs.ts
66945
67061
  import { promises as fsp } from "node:fs";
66946
- import path89 from "node:path";
67062
+ import path90 from "node:path";
66947
67063
  function errText(prefix, p3, err) {
66948
67064
  const msg = err instanceof Error ? err.message : String(err);
66949
67065
  return `[extension-fs] ${prefix} "${p3}": ${msg}`;
66950
67066
  }
66951
67067
  function bindSandboxedFs(root) {
66952
- const resolvedRoot = path89.resolve(root);
67068
+ const resolvedRoot = path90.resolve(root);
66953
67069
  return {
66954
67070
  root: resolvedRoot,
66955
67071
  async readFile(relativePath) {
@@ -66965,7 +67081,7 @@ function bindSandboxedFs(root) {
66965
67081
  try {
66966
67082
  const target = resolveSandboxedPath(relativePath, { root: resolvedRoot });
66967
67083
  verifyContainment(target, { root: resolvedRoot });
66968
- await fsp.mkdir(path89.dirname(target), { recursive: true });
67084
+ await fsp.mkdir(path90.dirname(target), { recursive: true });
66969
67085
  await fsp.writeFile(target, data, "utf8");
66970
67086
  return typedOk({ path: target });
66971
67087
  } catch (err) {
@@ -67150,7 +67266,7 @@ var init_loader = __esm({
67150
67266
 
67151
67267
  // src/cli/headless/runOneTurn.ts
67152
67268
  import { promises as fs44 } from "node:fs";
67153
- import path90 from "node:path";
67269
+ import path91 from "node:path";
67154
67270
  function planModeFromOpts(opts) {
67155
67271
  return (opts.phase ?? "build") === "plan";
67156
67272
  }
@@ -67717,7 +67833,7 @@ async function runOneTurn(opts, provider, model, providerStream, extras) {
67717
67833
  if (json3) {
67718
67834
  if (opts.exportSessionPath === "-") process.stdout.write(json3 + "\n");
67719
67835
  else {
67720
- await fs44.mkdir(path90.dirname(opts.exportSessionPath), { recursive: true }).catch(() => void 0);
67836
+ await fs44.mkdir(path91.dirname(opts.exportSessionPath), { recursive: true }).catch(() => void 0);
67721
67837
  await fs44.writeFile(opts.exportSessionPath, json3, "utf8");
67722
67838
  }
67723
67839
  }
@@ -68696,9 +68812,9 @@ __export(triggerLock_exports, {
68696
68812
  releaseLock: () => releaseLock
68697
68813
  });
68698
68814
  import { promises as fs45 } from "node:fs";
68699
- import * as path91 from "node:path";
68815
+ import * as path92 from "node:path";
68700
68816
  function lockPath(projectRoot) {
68701
- return path91.join(projectRoot, ".zelari", "trigger.lock");
68817
+ return path92.join(projectRoot, ".zelari", "trigger.lock");
68702
68818
  }
68703
68819
  function isPidAlive(pid) {
68704
68820
  try {
@@ -68711,7 +68827,7 @@ function isPidAlive(pid) {
68711
68827
  }
68712
68828
  async function acquireLock(projectRoot, now = () => /* @__PURE__ */ new Date()) {
68713
68829
  const lp = lockPath(projectRoot);
68714
- const dir = path91.dirname(lp);
68830
+ const dir = path92.dirname(lp);
68715
68831
  await fs45.mkdir(dir, { recursive: true });
68716
68832
  try {
68717
68833
  const raw = await fs45.readFile(lp, "utf8");
@@ -68743,7 +68859,7 @@ var init_triggerLock = __esm({
68743
68859
 
68744
68860
  // src/cli/runHeadless.ts
68745
68861
  import { promises as fs46 } from "node:fs";
68746
- import path92 from "node:path";
68862
+ import path93 from "node:path";
68747
68863
  import { randomUUID as randomUUID10 } from "node:crypto";
68748
68864
  async function runHeadless(opts) {
68749
68865
  resetTaskSpawnCount();
@@ -68987,7 +69103,7 @@ async function runHeadlessKrakenGraph(opts, provider, model) {
68987
69103
  try {
68988
69104
  let preflightGraph;
68989
69105
  if (opts.runPlan && opts.runPlan.trim() !== "") {
68990
- const planPath = path92.join(cwd, ".zelari", "radio", `plan-${opts.runPlan}.json`);
69106
+ const planPath = path93.join(cwd, ".zelari", "radio", `plan-${opts.runPlan}.json`);
68991
69107
  log(`loading pre-flight plan: ${planPath}`);
68992
69108
  let raw;
68993
69109
  try {
@@ -69030,8 +69146,8 @@ async function runHeadlessKrakenGraph(opts, provider, model) {
69030
69146
  log(formatKrakenGraphAscii2(graph));
69031
69147
  if (opts.planOnly) {
69032
69148
  const planId = randomUUID10();
69033
- const planDir = path92.join(cwd, ".zelari", "radio");
69034
- const planPath = path92.join(planDir, `plan-${planId}.json`);
69149
+ const planDir = path93.join(cwd, ".zelari", "radio");
69150
+ const planPath = path93.join(planDir, `plan-${planId}.json`);
69035
69151
  await fs46.mkdir(planDir, { recursive: true });
69036
69152
  await fs46.writeFile(
69037
69153
  planPath,
@@ -69409,7 +69525,7 @@ async function runHeadlessCouncilBody(opts, provider, model, providerStream, ext
69409
69525
  if (json3) {
69410
69526
  if (opts.exportSessionPath === "-") process.stdout.write(json3 + "\n");
69411
69527
  else {
69412
- await fs46.mkdir(path92.dirname(opts.exportSessionPath), { recursive: true }).catch(() => void 0);
69528
+ await fs46.mkdir(path93.dirname(opts.exportSessionPath), { recursive: true }).catch(() => void 0);
69413
69529
  await fs46.writeFile(opts.exportSessionPath, json3, "utf8");
69414
69530
  }
69415
69531
  }
@@ -69860,7 +69976,7 @@ ${ragContext}` : slicePrompt;
69860
69976
  if (json3) {
69861
69977
  if (opts.exportSessionPath === "-") process.stdout.write(json3 + "\n");
69862
69978
  else {
69863
- await fs46.mkdir(path92.dirname(opts.exportSessionPath), { recursive: true }).catch(() => void 0);
69979
+ await fs46.mkdir(path93.dirname(opts.exportSessionPath), { recursive: true }).catch(() => void 0);
69864
69980
  await fs46.writeFile(opts.exportSessionPath, json3, "utf8");
69865
69981
  }
69866
69982
  }
@@ -70473,7 +70589,7 @@ function upsertSkill(opts) {
70473
70589
  }
70474
70590
  dir = getProjectSkillsDir(root);
70475
70591
  }
70476
- const path99 = skillFilePath(dir, name);
70592
+ const path100 = skillFilePath(dir, name);
70477
70593
  const content = serializeSkillMd({
70478
70594
  name,
70479
70595
  description,
@@ -70482,13 +70598,13 @@ function upsertSkill(opts) {
70482
70598
  tools: opts.tools,
70483
70599
  cost: opts.cost
70484
70600
  });
70485
- const parsed = parseSkillMd(content, path99);
70601
+ const parsed = parseSkillMd(content, path100);
70486
70602
  if (!parsed) {
70487
70603
  return { ok: false, error: "Generated SKILL.md failed validation" };
70488
70604
  }
70489
- mkdirSync23(dirname13(path99), { recursive: true });
70490
- writeFileSync25(path99, content, "utf8");
70491
- return { ok: true, path: path99 };
70605
+ mkdirSync23(dirname13(path100), { recursive: true });
70606
+ writeFileSync25(path100, content, "utf8");
70607
+ return { ok: true, path: path100 };
70492
70608
  }
70493
70609
  function removeSkill(opts) {
70494
70610
  const name = opts.name.trim().toLowerCase();
@@ -70506,8 +70622,8 @@ function removeSkill(opts) {
70506
70622
  dir = getProjectSkillsDir(root);
70507
70623
  }
70508
70624
  const skillDir = join46(dir, name);
70509
- const path99 = skillFilePath(dir, name);
70510
- if (!existsSync59(path99) && !existsSync59(skillDir)) {
70625
+ const path100 = skillFilePath(dir, name);
70626
+ if (!existsSync59(path100) && !existsSync59(skillDir)) {
70511
70627
  return { ok: false, error: `Skill "${name}" not found in ${dir}` };
70512
70628
  }
70513
70629
  try {
@@ -70518,7 +70634,7 @@ function removeSkill(opts) {
70518
70634
  error: err instanceof Error ? err.message : String(err)
70519
70635
  };
70520
70636
  }
70521
- return { ok: true, path: path99 };
70637
+ return { ok: true, path: path100 };
70522
70638
  }
70523
70639
  var NAME_RE, BUILTIN_SKILL_MODULES, builtinsLoaded;
70524
70640
  var init_skillConfigIo = __esm({
@@ -70639,7 +70755,7 @@ var init_jsonApi = __esm({
70639
70755
  });
70640
70756
 
70641
70757
  // src/cli/memory/mcpAdapter.ts
70642
- import * as path93 from "node:path";
70758
+ import * as path94 from "node:path";
70643
70759
  var id2, projectId, source, SearchSchema, AddSchema, LinkSchema, RetractSchema, MEMORY_MCP_TOOLS, MemoryMcpAdapter;
70644
70760
  var init_mcpAdapter = __esm({
70645
70761
  "src/cli/memory/mcpAdapter.ts"() {
@@ -70809,8 +70925,8 @@ var init_mcpAdapter = __esm({
70809
70925
  this.takeWrite();
70810
70926
  const externalFile = args.source?.file;
70811
70927
  if (externalFile) {
70812
- const normalized = path93.normalize(externalFile);
70813
- if (path93.isAbsolute(normalized) || normalized === ".." || normalized.startsWith(`..${path93.sep}`)) {
70928
+ const normalized = path94.normalize(externalFile);
70929
+ if (path94.isAbsolute(normalized) || normalized === ".." || normalized.startsWith(`..${path94.sep}`)) {
70814
70930
  throw new Error("source.file must be project-relative and cannot escape the project");
70815
70931
  }
70816
70932
  }
@@ -71337,12 +71453,12 @@ function ensureHome() {
71337
71453
  }
71338
71454
  }
71339
71455
  function loadCompanionConfig() {
71340
- const path99 = getCompanionConfigPath();
71341
- if (!existsSync60(path99)) {
71456
+ const path100 = getCompanionConfigPath();
71457
+ if (!existsSync60(path100)) {
71342
71458
  return { projects: [] };
71343
71459
  }
71344
71460
  try {
71345
- const raw = JSON.parse(readFileSync45(path99, "utf8"));
71461
+ const raw = JSON.parse(readFileSync45(path100, "utf8"));
71346
71462
  const projects = Array.isArray(raw.projects) ? raw.projects.filter(
71347
71463
  (p3) => p3 && typeof p3.path === "string" && p3.path.trim() && typeof (p3.id ?? p3.name) === "string"
71348
71464
  ).map((p3) => ({
@@ -71380,16 +71496,16 @@ function loadOrCreateToken(explicit) {
71380
71496
  return { token: explicit.trim(), created: false };
71381
71497
  }
71382
71498
  ensureHome();
71383
- const path99 = getCompanionTokenPath();
71384
- if (existsSync60(path99)) {
71385
- const t = readFileSync45(path99, "utf8").trim();
71499
+ const path100 = getCompanionTokenPath();
71500
+ if (existsSync60(path100)) {
71501
+ const t = readFileSync45(path100, "utf8").trim();
71386
71502
  if (t) return { token: t, created: false };
71387
71503
  }
71388
71504
  const token = randomBytes7(24).toString("base64url");
71389
- writeFileSync26(path99, token + "\n", "utf8");
71505
+ writeFileSync26(path100, token + "\n", "utf8");
71390
71506
  try {
71391
71507
  const fs48 = __require("node:fs");
71392
- fs48.chmodSync?.(path99, 384);
71508
+ fs48.chmodSync?.(path100, 384);
71393
71509
  } catch {
71394
71510
  }
71395
71511
  return { token, created: true };
@@ -71414,17 +71530,17 @@ function mergeProjects(cfg, extraPaths) {
71414
71530
  byId.set(p3.id, p3);
71415
71531
  }
71416
71532
  for (const raw of extraPaths) {
71417
- const path99 = raw.trim();
71418
- if (!path99) continue;
71419
- let id3 = slugFromPath(path99);
71533
+ const path100 = raw.trim();
71534
+ if (!path100) continue;
71535
+ let id3 = slugFromPath(path100);
71420
71536
  let n = 2;
71421
- while (byId.has(id3) && byId.get(id3).path !== path99) {
71422
- id3 = `${slugFromPath(path99)}-${n++}`;
71537
+ while (byId.has(id3) && byId.get(id3).path !== path100) {
71538
+ id3 = `${slugFromPath(path100)}-${n++}`;
71423
71539
  }
71424
71540
  byId.set(id3, {
71425
71541
  id: id3,
71426
- name: slugFromPath(path99),
71427
- path: path99
71542
+ name: slugFromPath(path100),
71543
+ path: path100
71428
71544
  });
71429
71545
  }
71430
71546
  return [...byId.values()];
@@ -71667,7 +71783,7 @@ var init_askUserBridge = __esm({
71667
71783
 
71668
71784
  // src/cli/serve/spineLockSweep.ts
71669
71785
  import { promises as fs47 } from "node:fs";
71670
- import path94 from "node:path";
71786
+ import path95 from "node:path";
71671
71787
  async function sweepOrphanSpineLocks(sessionsDir2, options = {}) {
71672
71788
  const dir = sessionsDir2 ?? resolveSessionsDir();
71673
71789
  const onSwept = options.onSwept ?? ((sessionId2, reason) => {
@@ -71685,7 +71801,7 @@ async function sweepOrphanSpineLocks(sessionsDir2, options = {}) {
71685
71801
  return result;
71686
71802
  }
71687
71803
  for (const sessionId2 of entries) {
71688
- const lockPath2 = path94.join(dir, sessionId2, "writer.lock");
71804
+ const lockPath2 = path95.join(dir, sessionId2, "writer.lock");
71689
71805
  try {
71690
71806
  const raw = await fs47.readFile(lockPath2, "utf-8");
71691
71807
  let lockInfo = {};
@@ -72682,9 +72798,9 @@ async function runCompanionServe(opts = {}) {
72682
72798
  return;
72683
72799
  }
72684
72800
  const url2 = parseUrl(req);
72685
- const path99 = url2.pathname.replace(/\/+$/, "") || "/";
72801
+ const path100 = url2.pathname.replace(/\/+$/, "") || "/";
72686
72802
  try {
72687
- if (req.method === "GET" && (path99 === "/health" || path99 === "/v1/health")) {
72803
+ if (req.method === "GET" && (path100 === "/health" || path100 === "/v1/health")) {
72688
72804
  sendJson2(res, 200, {
72689
72805
  ok: true,
72690
72806
  service: "zelari-companion",
@@ -72696,18 +72812,18 @@ async function runCompanionServe(opts = {}) {
72696
72812
  });
72697
72813
  return;
72698
72814
  }
72699
- if (path99.startsWith("/v1")) {
72815
+ if (path100.startsWith("/v1")) {
72700
72816
  if (!tokenMatches(token, getBearer(req))) {
72701
72817
  sendJson2(res, 401, { ok: false, error: "unauthorized" });
72702
72818
  return;
72703
72819
  }
72704
72820
  }
72705
- if (req.method === "GET" && path99 === "/v1/config") {
72821
+ if (req.method === "GET" && path100 === "/v1/config") {
72706
72822
  const snap = buildDesktopConfigSnapshot();
72707
72823
  sendJson2(res, 200, { ok: true, ...snap });
72708
72824
  return;
72709
72825
  }
72710
- if (req.method === "GET" && path99 === "/v1/projects") {
72826
+ if (req.method === "GET" && path100 === "/v1/projects") {
72711
72827
  sendJson2(res, 200, {
72712
72828
  ok: true,
72713
72829
  projects: projects.map((p3) => ({
@@ -72718,7 +72834,7 @@ async function runCompanionServe(opts = {}) {
72718
72834
  });
72719
72835
  return;
72720
72836
  }
72721
- if (req.method === "GET" && path99 === "/v1/runs") {
72837
+ if (req.method === "GET" && path100 === "/v1/runs") {
72722
72838
  sendJson2(res, 200, {
72723
72839
  ok: true,
72724
72840
  active: runs.getActive(),
@@ -72736,7 +72852,7 @@ async function runCompanionServe(opts = {}) {
72736
72852
  });
72737
72853
  return;
72738
72854
  }
72739
- if (req.method === "POST" && path99 === "/v1/runs") {
72855
+ if (req.method === "POST" && path100 === "/v1/runs") {
72740
72856
  const raw = await readBody(req);
72741
72857
  let body = {};
72742
72858
  try {
@@ -72784,7 +72900,7 @@ async function runCompanionServe(opts = {}) {
72784
72900
  });
72785
72901
  return;
72786
72902
  }
72787
- const eventsMatch = /^\/v1\/runs\/([^/]+)\/events$/.exec(path99);
72903
+ const eventsMatch = /^\/v1\/runs\/([^/]+)\/events$/.exec(path100);
72788
72904
  if (req.method === "GET" && eventsMatch) {
72789
72905
  const runId = eventsMatch[1];
72790
72906
  const run = runs.getRun(runId);
@@ -72849,7 +72965,7 @@ async function runCompanionServe(opts = {}) {
72849
72965
  }, 500);
72850
72966
  return;
72851
72967
  }
72852
- const cancelMatch = /^\/v1\/runs\/([^/]+)\/cancel$/.exec(path99);
72968
+ const cancelMatch = /^\/v1\/runs\/([^/]+)\/cancel$/.exec(path100);
72853
72969
  if (req.method === "POST" && cancelMatch) {
72854
72970
  const runId = cancelMatch[1];
72855
72971
  const result = runs.cancel(runId);
@@ -72860,7 +72976,7 @@ async function runCompanionServe(opts = {}) {
72860
72976
  sendJson2(res, 200, { ok: true, cancelled: runId });
72861
72977
  return;
72862
72978
  }
72863
- const steerMatch = /^\/v1\/runs\/([^/]+)\/steer$/.exec(path99);
72979
+ const steerMatch = /^\/v1\/runs\/([^/]+)\/steer$/.exec(path100);
72864
72980
  if (req.method === "POST" && steerMatch) {
72865
72981
  const runId = steerMatch[1];
72866
72982
  const raw = await readBody(req);
@@ -73029,11 +73145,11 @@ import { execSync as execSync2 } from "node:child_process";
73029
73145
  import { existsSync as existsSync62, readFileSync as readFileSync46, readlinkSync, statSync as statSync10 } from "node:fs";
73030
73146
  import { createRequire as createRequire3 } from "node:module";
73031
73147
  import { fileURLToPath as fileURLToPath3 } from "node:url";
73032
- import path95 from "node:path";
73148
+ import path96 from "node:path";
73033
73149
  function findPackageRoot(start) {
73034
73150
  let dir = start;
73035
73151
  for (let i = 0; i < 6; i += 1) {
73036
- const candidate = path95.join(dir, "package.json");
73152
+ const candidate = path96.join(dir, "package.json");
73037
73153
  if (existsSync62(candidate)) {
73038
73154
  try {
73039
73155
  const pkg = JSON.parse(readFileSync46(candidate, "utf8"));
@@ -73041,11 +73157,11 @@ function findPackageRoot(start) {
73041
73157
  } catch {
73042
73158
  }
73043
73159
  }
73044
- const parent = path95.dirname(dir);
73160
+ const parent = path96.dirname(dir);
73045
73161
  if (parent === dir) break;
73046
73162
  dir = parent;
73047
73163
  }
73048
- return path95.resolve(__dirname3, "..", "..", "..");
73164
+ return path96.resolve(__dirname3, "..", "..", "..");
73049
73165
  }
73050
73166
  function tryExec(cmd) {
73051
73167
  try {
@@ -73059,7 +73175,7 @@ function tryExec(cmd) {
73059
73175
  }
73060
73176
  function readPackageJson4() {
73061
73177
  try {
73062
- const pkgPath = path95.join(packageRoot, "package.json");
73178
+ const pkgPath = path96.join(packageRoot, "package.json");
73063
73179
  return JSON.parse(readFileSync46(pkgPath, "utf8"));
73064
73180
  } catch {
73065
73181
  return null;
@@ -73071,7 +73187,7 @@ function getGlobalPrefix() {
73071
73187
  return (process.env.npm_config_prefix || process.env.NPM_CONFIG_PREFIX || "").trim();
73072
73188
  }
73073
73189
  function isSourceCheckout() {
73074
- return existsSync62(path95.join(packageRoot, "src", "cli", "main.ts")) && existsSync62(path95.join(packageRoot, "apps", "desktop", "package.json"));
73190
+ return existsSync62(path96.join(packageRoot, "src", "cli", "main.ts")) && existsSync62(path96.join(packageRoot, "apps", "desktop", "package.json"));
73075
73191
  }
73076
73192
  function checkShim(pkgName) {
73077
73193
  const prefix = getGlobalPrefix();
@@ -73080,9 +73196,9 @@ function checkShim(pkgName) {
73080
73196
  }
73081
73197
  const isWin = process.platform === "win32";
73082
73198
  const shimName = isWin ? "zelari-code.cmd" : "zelari-code";
73083
- const shimPath = path95.join(prefix, shimName);
73199
+ const shimPath = path96.join(prefix, shimName);
73084
73200
  if (!existsSync62(shimPath)) {
73085
- const localBin = path95.join(packageRoot, "bin", "zelari-code.js");
73201
+ const localBin = path96.join(packageRoot, "bin", "zelari-code.js");
73086
73202
  if (isSourceCheckout() && existsSync62(localBin)) {
73087
73203
  return WARN(
73088
73204
  `global shim not found at ${shimPath}
@@ -73116,8 +73232,8 @@ function checkShim(pkgName) {
73116
73232
  fix: npm install -g ${pkgName}@latest --force`
73117
73233
  );
73118
73234
  }
73119
- const resolved = path95.resolve(path95.dirname(shimPath), target);
73120
- const expected = path95.join(
73235
+ const resolved = path96.resolve(path96.dirname(shimPath), target);
73236
+ const expected = path96.join(
73121
73237
  prefix,
73122
73238
  "node_modules",
73123
73239
  pkgName,
@@ -73159,7 +73275,7 @@ function checkNode(pkg) {
73159
73275
  return OK(`node ${raw} (engines.node ${enginesNode ?? ">= 20.0.0"})`);
73160
73276
  }
73161
73277
  function checkBundle() {
73162
- const bundle = path95.join(packageRoot, "dist", "cli", "main.bundled.js");
73278
+ const bundle = path96.join(packageRoot, "dist", "cli", "main.bundled.js");
73163
73279
  if (!existsSync62(bundle)) {
73164
73280
  return FAIL(
73165
73281
  `dist/cli/main.bundled.js missing at ${bundle}
@@ -73180,7 +73296,7 @@ function checkRuntimeDeps() {
73180
73296
  const missing = [];
73181
73297
  for (const dep of required2) {
73182
73298
  try {
73183
- const localReq = createRequire3(path95.join(packageRoot, "package.json"));
73299
+ const localReq = createRequire3(path96.join(packageRoot, "package.json"));
73184
73300
  localReq.resolve(dep);
73185
73301
  } catch {
73186
73302
  missing.push(dep);
@@ -73457,7 +73573,7 @@ var init_doctor = __esm({
73457
73573
  init_metrics3();
73458
73574
  init_contextGrowthSummary();
73459
73575
  require3 = createRequire3(import.meta.url);
73460
- __dirname3 = path95.dirname(fileURLToPath3(import.meta.url));
73576
+ __dirname3 = path96.dirname(fileURLToPath3(import.meta.url));
73461
73577
  packageRoot = findPackageRoot(__dirname3);
73462
73578
  OK = (message) => ({
73463
73579
  ok: true,
@@ -73566,7 +73682,7 @@ __export(userSettings_exports, {
73566
73682
  settingsOverrides: () => settingsOverrides
73567
73683
  });
73568
73684
  import { existsSync as existsSync63, readFileSync as readFileSync47 } from "node:fs";
73569
- import path96 from "node:path";
73685
+ import path97 from "node:path";
73570
73686
  function parseBool(raw) {
73571
73687
  const v = raw.trim().toLowerCase();
73572
73688
  if (["1", "true", "yes", "on"].includes(v)) return true;
@@ -73633,8 +73749,8 @@ function envValueFor(key, env) {
73633
73749
  function resolveUserSettings(opts = {}) {
73634
73750
  const cwd = opts.cwd ?? process.cwd();
73635
73751
  const env = opts.env ?? process.env;
73636
- const userPath = path96.join(zelariHome(), SETTINGS_FILE_NAME);
73637
- const projectPath = path96.join(cwd, ".zelari", SETTINGS_FILE_NAME);
73752
+ const userPath = path97.join(zelariHome(), SETTINGS_FILE_NAME);
73753
+ const projectPath = path97.join(cwd, ".zelari", SETTINGS_FILE_NAME);
73638
73754
  const warnings = [];
73639
73755
  const userLayer = loadFileLayer(userPath, "user", warnings);
73640
73756
  const projectLayer = loadFileLayer(projectPath, "project", warnings);
@@ -73848,7 +73964,7 @@ __export(inspectSession_exports, {
73848
73964
  renderInspectReport: () => renderInspectReport,
73849
73965
  runInspectSession: () => runInspectSession
73850
73966
  });
73851
- import path97 from "node:path";
73967
+ import path98 from "node:path";
73852
73968
  import { existsSync as existsSync64 } from "node:fs";
73853
73969
  function formatLimit(limit) {
73854
73970
  return `${Math.round(limit / 1e3)}k`;
@@ -73882,8 +73998,8 @@ function renderInspectReport(state3) {
73882
73998
  }
73883
73999
  async function runInspectSession(opts) {
73884
74000
  const sessionsDir2 = resolveSessionsDir({ workspaceRoot: opts.cwd ?? process.cwd() });
73885
- const sessionDir = path97.join(sessionsDir2, opts.sessionId);
73886
- const eventsPath = path97.join(sessionDir, "events.jsonl");
74001
+ const sessionDir = path98.join(sessionsDir2, opts.sessionId);
74002
+ const eventsPath = path98.join(sessionDir, "events.jsonl");
73887
74003
  if (!existsSync64(sessionDir)) {
73888
74004
  console.error(`zelari-code inspect: no session directory at ${sessionDir}`);
73889
74005
  return 1;
@@ -73917,14 +74033,14 @@ __export(inspect_exports, {
73917
74033
  collectInspectReport: () => collectInspectReport,
73918
74034
  runInspect: () => runInspect
73919
74035
  });
73920
- import path98 from "node:path";
74036
+ import path99 from "node:path";
73921
74037
  import { existsSync as existsSync65, readFileSync as readFileSync48, readdirSync as readdirSync13 } from "node:fs";
73922
74038
  async function collectInspectReport(cwd = process.cwd()) {
73923
74039
  ensureBuiltinSkillsLoadedSync();
73924
74040
  const snap = listSkillsSnapshot(cwd);
73925
74041
  const mcp = listMcpServers(cwd);
73926
- const userMcpPath = path98.join(zelariHome(), "mcp.json");
73927
- const projectMcpPath = path98.join(cwd, ".zelari", "mcp.json");
74042
+ const userMcpPath = path99.join(zelariHome(), "mcp.json");
74043
+ const projectMcpPath = path99.join(cwd, ".zelari", "mcp.json");
73928
74044
  const globalHooks = globalHooksDir();
73929
74045
  const projectHooks = projectHooksDir(cwd);
73930
74046
  const projectTrusted = isFolderTrusted(cwd);
@@ -73952,9 +74068,9 @@ async function collectInspectReport(cwd = process.cwd()) {
73952
74068
  configSources: [
73953
74069
  { path: userMcpPath, exists: existsSync65(userMcpPath) },
73954
74070
  { path: projectMcpPath, exists: existsSync65(projectMcpPath) },
73955
- { path: path98.join(zelariHome(), "provider.json"), exists: existsSync65(path98.join(zelariHome(), "provider.json")) },
73956
- { path: path98.join(cwd, ".zelari", "AGENTS.md"), exists: existsSync65(path98.join(cwd, ".zelari", "AGENTS.md")) },
73957
- { path: path98.join(cwd, "AGENTS.md"), exists: existsSync65(path98.join(cwd, "AGENTS.md")) }
74071
+ { path: path99.join(zelariHome(), "provider.json"), exists: existsSync65(path99.join(zelariHome(), "provider.json")) },
74072
+ { path: path99.join(cwd, ".zelari", "AGENTS.md"), exists: existsSync65(path99.join(cwd, ".zelari", "AGENTS.md")) },
74073
+ { path: path99.join(cwd, "AGENTS.md"), exists: existsSync65(path99.join(cwd, "AGENTS.md")) }
73958
74074
  ],
73959
74075
  skills: {
73960
74076
  total: snap.skills.length,
@@ -73994,8 +74110,8 @@ function listJsonFiles(dir) {
73994
74110
  }
73995
74111
  function findAgentsMd(cwd) {
73996
74112
  const candidates = [
73997
- path98.join(cwd, "AGENTS.md"),
73998
- path98.join(cwd, ".zelari", "AGENTS.md")
74113
+ path99.join(cwd, "AGENTS.md"),
74114
+ path99.join(cwd, ".zelari", "AGENTS.md")
73999
74115
  ];
74000
74116
  const found = [];
74001
74117
  for (const c of candidates) {
@@ -79250,10 +79366,10 @@ init_ledger();
79250
79366
 
79251
79367
  // src/cli/evolution/proposals.ts
79252
79368
  import { existsSync as existsSync51, readFileSync as readFileSync39 } from "node:fs";
79253
- import path76 from "node:path";
79254
- var PROPOSALS_REL = path76.join(".zelari", "evolution", "proposals.jsonl");
79369
+ import path77 from "node:path";
79370
+ var PROPOSALS_REL = path77.join(".zelari", "evolution", "proposals.jsonl");
79255
79371
  function proposalsPath(cwd) {
79256
- return path76.join(cwd, PROPOSALS_REL);
79372
+ return path77.join(cwd, PROPOSALS_REL);
79257
79373
  }
79258
79374
  function readProposalStore(cwd) {
79259
79375
  const file2 = proposalsPath(cwd);
@@ -80345,11 +80461,11 @@ function handleCacheStats(ctx) {
80345
80461
  init_messageHelpers();
80346
80462
  init_serviceFactory();
80347
80463
  import { promises as fs35 } from "node:fs";
80348
- import * as path78 from "node:path";
80464
+ import * as path79 from "node:path";
80349
80465
 
80350
80466
  // src/cli/memory/promotion.ts
80351
80467
  import { promises as fs34 } from "node:fs";
80352
- import * as path77 from "node:path";
80468
+ import * as path78 from "node:path";
80353
80469
  var START = "<!-- zelari:memory-promotions:start -->";
80354
80470
  var END = "<!-- zelari:memory-promotions:end -->";
80355
80471
  var DURABLE_KINDS = /* @__PURE__ */ new Set(["fact", "decision", "constraint", "preference", "procedure"]);
@@ -80360,16 +80476,16 @@ function lineFor(node) {
80360
80476
  }
80361
80477
  async function promoteMemoryToAgentsMd(projectRoot, node) {
80362
80478
  if (node.status !== "active") {
80363
- return { added: false, path: path77.join(projectRoot, "AGENTS.md"), reason: `memory is ${node.status}` };
80479
+ return { added: false, path: path78.join(projectRoot, "AGENTS.md"), reason: `memory is ${node.status}` };
80364
80480
  }
80365
80481
  if (!DURABLE_KINDS.has(node.kind)) {
80366
- return { added: false, path: path77.join(projectRoot, "AGENTS.md"), reason: `${node.kind} is not a durable instruction kind` };
80482
+ return { added: false, path: path78.join(projectRoot, "AGENTS.md"), reason: `${node.kind} is not a durable instruction kind` };
80367
80483
  }
80368
- const root = await fs34.realpath(projectRoot).catch(() => path77.resolve(projectRoot));
80369
- const target = path77.join(root, "AGENTS.md");
80484
+ const root = await fs34.realpath(projectRoot).catch(() => path78.resolve(projectRoot));
80485
+ const target = path78.join(root, "AGENTS.md");
80370
80486
  try {
80371
- const stat7 = await fs34.lstat(target);
80372
- if (stat7.isSymbolicLink() || !stat7.isFile()) throw new Error("AGENTS.md must be a regular project file.");
80487
+ const stat8 = await fs34.lstat(target);
80488
+ if (stat8.isSymbolicLink() || !stat8.isFile()) throw new Error("AGENTS.md must be a regular project file.");
80373
80489
  } catch (error51) {
80374
80490
  if (error51.code !== "ENOENT") throw error51;
80375
80491
  }
@@ -80431,25 +80547,25 @@ function sourceLine(source2) {
80431
80547
  return entries.length ? entries.map(([key, value]) => `${key}=${value}`).join(" \xB7 ") : "unknown";
80432
80548
  }
80433
80549
  function isInside(root, target) {
80434
- const relative6 = path78.relative(root, target);
80435
- return relative6 === "" || !relative6.startsWith("..") && !path78.isAbsolute(relative6);
80550
+ const relative6 = path79.relative(root, target);
80551
+ return relative6 === "" || !relative6.startsWith("..") && !path79.isAbsolute(relative6);
80436
80552
  }
80437
80553
  async function safeExportPath(cwd, requested) {
80438
- const lexicalRoot = path78.resolve(cwd);
80554
+ const lexicalRoot = path79.resolve(cwd);
80439
80555
  const root = await fs35.realpath(lexicalRoot).catch(() => lexicalRoot);
80440
- const fallback = path78.join(root, ".zelari", "memory", `export-${Date.now()}.json`);
80441
- const target = requested?.trim() ? path78.resolve(root, requested.trim()) : fallback;
80556
+ const fallback = path79.join(root, ".zelari", "memory", `export-${Date.now()}.json`);
80557
+ const target = requested?.trim() ? path79.resolve(root, requested.trim()) : fallback;
80442
80558
  if (!isInside(root, target)) {
80443
80559
  throw new Error("Export path must stay inside the active project.");
80444
80560
  }
80445
- const parent = path78.dirname(target);
80446
- const relativeParent = path78.relative(root, parent);
80561
+ const parent = path79.dirname(target);
80562
+ const relativeParent = path79.relative(root, parent);
80447
80563
  let cursor = root;
80448
- for (const segment of relativeParent.split(path78.sep).filter(Boolean)) {
80449
- cursor = path78.join(cursor, segment);
80564
+ for (const segment of relativeParent.split(path79.sep).filter(Boolean)) {
80565
+ cursor = path79.join(cursor, segment);
80450
80566
  try {
80451
- const stat7 = await fs35.lstat(cursor);
80452
- if (stat7.isSymbolicLink()) {
80567
+ const stat8 = await fs35.lstat(cursor);
80568
+ if (stat8.isSymbolicLink()) {
80453
80569
  throw new Error("Export path must not traverse a symbolic link.");
80454
80570
  }
80455
80571
  } catch (error51) {
@@ -80618,9 +80734,9 @@ ${message}` : message
80618
80734
  }
80619
80735
  case "export": {
80620
80736
  const target = await safeExportPath(ctx.cwd, args.join(" ").trim() || void 0);
80621
- await fs35.mkdir(path78.dirname(target), { recursive: true });
80622
- const root = await fs35.realpath(ctx.cwd).catch(() => path78.resolve(ctx.cwd));
80623
- const realParent = await fs35.realpath(path78.dirname(target));
80737
+ await fs35.mkdir(path79.dirname(target), { recursive: true });
80738
+ const root = await fs35.realpath(ctx.cwd).catch(() => path79.resolve(ctx.cwd));
80739
+ const realParent = await fs35.realpath(path79.dirname(target));
80624
80740
  if (!isInside(root, realParent)) {
80625
80741
  throw new Error("Export path resolves outside the active project.");
80626
80742
  }
@@ -80835,7 +80951,7 @@ import { promises as fs37 } from "node:fs";
80835
80951
  init_zod();
80836
80952
  init_taskTool();
80837
80953
  import { promises as fs36 } from "node:fs";
80838
- import path79 from "node:path";
80954
+ import path80 from "node:path";
80839
80955
  import { randomBytes as randomBytes6 } from "node:crypto";
80840
80956
  var CsvFanoutArgsSchema = external_exports.object({
80841
80957
  csv_path: external_exports.string().min(1),
@@ -80929,8 +81045,8 @@ function resolveMaxConcurrency(env = process.env) {
80929
81045
  }
80930
81046
  async function runCsvFanout(args, deps, opts) {
80931
81047
  const start = Date.now();
80932
- const absCsv = path79.isAbsolute(args.csv_path) ? args.csv_path : path79.join(opts.parentCwd, args.csv_path);
80933
- const absOut = path79.isAbsolute(args.output_csv_path) ? args.output_csv_path : path79.join(opts.parentCwd, args.output_csv_path);
81048
+ const absCsv = path80.isAbsolute(args.csv_path) ? args.csv_path : path80.join(opts.parentCwd, args.csv_path);
81049
+ const absOut = path80.isAbsolute(args.output_csv_path) ? args.output_csv_path : path80.join(opts.parentCwd, args.output_csv_path);
80934
81050
  const { headers: headers2, rows } = await readCsv(absCsv);
80935
81051
  if (headers2.length === 0) {
80936
81052
  throw new Error(`kraken_csv_fanout: ${absCsv} is empty`);
@@ -80986,7 +81102,7 @@ async function runCsvFanout(args, deps, opts) {
80986
81102
  errored += 1;
80987
81103
  errors.push(`${row[args.id_column] ?? i}: ${res.error}`);
80988
81104
  }
80989
- await fs36.mkdir(path79.dirname(absOut), { recursive: true });
81105
+ await fs36.mkdir(path80.dirname(absOut), { recursive: true });
80990
81106
  await queueWrite(serializeCsv(outHeaders, outputRecords));
80991
81107
  }
80992
81108
  }
@@ -81181,7 +81297,7 @@ function splitArgs(s) {
81181
81297
  // src/cli/slashHandlers/krakenWorkbench.ts
81182
81298
  init_messageHelpers();
81183
81299
  import { promises as fs38 } from "node:fs";
81184
- import path80 from "node:path";
81300
+ import path81 from "node:path";
81185
81301
 
81186
81302
  // src/cli/kraken/workbenchView.ts
81187
81303
  var EMPTY = {
@@ -81298,17 +81414,17 @@ function formatWorkbenchForTerminal(p3) {
81298
81414
 
81299
81415
  // src/cli/slashHandlers/krakenWorkbench.ts
81300
81416
  async function handleKrakenWorkbench(ctx) {
81301
- const dir = path80.join(ctx.cwd, ".zelari", "radio");
81417
+ const dir = path81.join(ctx.cwd, ".zelari", "radio");
81302
81418
  let latest = null;
81303
81419
  let latestMtime = 0;
81304
81420
  try {
81305
81421
  const files = await fs38.readdir(dir);
81306
81422
  for (const f of files) {
81307
81423
  if (!f.startsWith("workbench-") || !f.endsWith(".md")) continue;
81308
- const full = path80.join(dir, f);
81309
- const stat7 = await fs38.stat(full);
81310
- if (stat7.mtimeMs > latestMtime) {
81311
- latestMtime = stat7.mtimeMs;
81424
+ const full = path81.join(dir, f);
81425
+ const stat8 = await fs38.stat(full);
81426
+ if (stat8.mtimeMs > latestMtime) {
81427
+ latestMtime = stat8.mtimeMs;
81312
81428
  latest = full;
81313
81429
  }
81314
81430
  }
@@ -81322,10 +81438,10 @@ async function handleKrakenWorkbench(ctx) {
81322
81438
  const parsed = parseWorkbench(content);
81323
81439
  const rendered = formatWorkbenchForTerminal(parsed);
81324
81440
  if (!rendered.trim()) {
81325
- appendSystem(ctx.setMessages, `[kraken workbench] ${path80.basename(latest)}: (no nodes / no events yet)`);
81441
+ appendSystem(ctx.setMessages, `[kraken workbench] ${path81.basename(latest)}: (no nodes / no events yet)`);
81326
81442
  return;
81327
81443
  }
81328
- appendSystem(ctx.setMessages, `[kraken workbench] ${path80.basename(latest)}:
81444
+ appendSystem(ctx.setMessages, `[kraken workbench] ${path81.basename(latest)}:
81329
81445
  ${rendered}`);
81330
81446
  }
81331
81447
 
@@ -81633,14 +81749,14 @@ ${result.output.split("\n").slice(-8).join("\n")}` : "";
81633
81749
  init_messageHelpers();
81634
81750
  init_paths();
81635
81751
  import { promises as fs39 } from "node:fs";
81636
- import path83 from "node:path";
81752
+ import path84 from "node:path";
81637
81753
  async function handlePromoteMember(ctx, memberId) {
81638
81754
  try {
81639
81755
  const { promoteMember: promoteMember2 } = await Promise.resolve().then(() => (init_council(), council_exports));
81640
81756
  const { skill, markdown } = promoteMember2(memberId);
81641
81757
  const skillDir = skillsDir();
81642
81758
  await fs39.mkdir(skillDir, { recursive: true });
81643
- const filePath = path83.join(skillDir, `${skill.id}.md`);
81759
+ const filePath = path84.join(skillDir, `${skill.id}.md`);
81644
81760
  const previous = await fs39.readFile(filePath, "utf8").catch(() => null);
81645
81761
  const { createHash: createHash24 } = await import("node:crypto");
81646
81762
  const sha = (s) => createHash24("sha256").update(s, "utf8").digest("hex");
@@ -81666,7 +81782,7 @@ ${lineage}
81666
81782
  // src/cli/branchManager.ts
81667
81783
  init_paths();
81668
81784
  import { promises as fs40, existsSync as existsSync55, readFileSync as readFileSync41, writeFileSync as writeFileSync24, mkdirSync as mkdirSync21, statSync as statSync7, rmSync as rmSync3 } from "node:fs";
81669
- import path84 from "node:path";
81785
+ import path85 from "node:path";
81670
81786
  var META_FILENAME = "meta.json";
81671
81787
  var SESSIONS_SUBDIR = "sessions";
81672
81788
  function getBranchesBaseDir() {
@@ -81676,13 +81792,13 @@ function getSessionsBaseDir() {
81676
81792
  return sessionsDir();
81677
81793
  }
81678
81794
  function branchPathFor(name, baseDir) {
81679
- return path84.join(baseDir, name);
81795
+ return path85.join(baseDir, name);
81680
81796
  }
81681
81797
  function metaPathFor(name, baseDir) {
81682
- return path84.join(baseDir, name, META_FILENAME);
81798
+ return path85.join(baseDir, name, META_FILENAME);
81683
81799
  }
81684
81800
  function sessionsPathFor(name, baseDir) {
81685
- return path84.join(baseDir, name, SESSIONS_SUBDIR);
81801
+ return path85.join(baseDir, name, SESSIONS_SUBDIR);
81686
81802
  }
81687
81803
  function readBranchMeta(name, baseDir) {
81688
81804
  const metaPath = metaPathFor(name, baseDir);
@@ -81707,7 +81823,7 @@ function readBranchMeta(name, baseDir) {
81707
81823
  }
81708
81824
  function writeBranchMeta(name, baseDir, meta3) {
81709
81825
  const metaPath = metaPathFor(name, baseDir);
81710
- mkdirSync21(path84.dirname(metaPath), { recursive: true });
81826
+ mkdirSync21(path85.dirname(metaPath), { recursive: true });
81711
81827
  writeFileSync24(metaPath, JSON.stringify(meta3, null, 2), "utf-8");
81712
81828
  }
81713
81829
  async function countSessions(name, baseDir) {
@@ -81758,14 +81874,14 @@ async function createBranch(name, fromSessionId, baseDir = getBranchesBaseDir(),
81758
81874
  if (branchExists(name, baseDir)) {
81759
81875
  throw new BranchAlreadyExistsError(name);
81760
81876
  }
81761
- const sourcePath = path84.join(sessionsBaseDir, `${fromSessionId}.jsonl`);
81877
+ const sourcePath = path85.join(sessionsBaseDir, `${fromSessionId}.jsonl`);
81762
81878
  if (!existsSync55(sourcePath)) {
81763
81879
  throw new SessionNotFoundError(`Source session "${fromSessionId}" not found at ${sourcePath}`);
81764
81880
  }
81765
81881
  const branchPath = branchPathFor(name, baseDir);
81766
81882
  const branchSessionsPath = sessionsPathFor(name, baseDir);
81767
81883
  mkdirSync21(branchSessionsPath, { recursive: true });
81768
- const destPath = path84.join(branchSessionsPath, `${fromSessionId}.jsonl`);
81884
+ const destPath = path85.join(branchSessionsPath, `${fromSessionId}.jsonl`);
81769
81885
  await fs40.copyFile(sourcePath, destPath);
81770
81886
  const meta3 = {
81771
81887
  name,
@@ -81869,14 +81985,14 @@ async function handleBranchCheckout(ctx, branchName) {
81869
81985
  // src/cli/slashHandlers/workspace.ts
81870
81986
  init_messageHelpers();
81871
81987
  import { promises as fs41 } from "node:fs";
81872
- import path85 from "node:path";
81988
+ import path86 from "node:path";
81873
81989
  async function handleWorkspaceShow(ctx, what) {
81874
81990
  try {
81875
- const zelari = path85.join(process.cwd(), ".zelari");
81991
+ const zelari = path86.join(process.cwd(), ".zelari");
81876
81992
  let content;
81877
81993
  switch (what) {
81878
81994
  case "plan": {
81879
- const planPath = path85.join(zelari, "plan.md");
81995
+ const planPath = path86.join(zelari, "plan.md");
81880
81996
  try {
81881
81997
  content = await fs41.readFile(planPath, "utf-8");
81882
81998
  } catch {
@@ -81885,7 +82001,7 @@ async function handleWorkspaceShow(ctx, what) {
81885
82001
  break;
81886
82002
  }
81887
82003
  case "decisions": {
81888
- const decisionsDir = path85.join(zelari, "decisions");
82004
+ const decisionsDir = path86.join(zelari, "decisions");
81889
82005
  try {
81890
82006
  const files = (await fs41.readdir(decisionsDir)).filter((f) => f.endsWith(".md")).sort();
81891
82007
  if (files.length === 0) {
@@ -81895,7 +82011,7 @@ async function handleWorkspaceShow(ctx, what) {
81895
82011
  `];
81896
82012
  const { parseFrontmatter: parseFrontmatter2 } = await Promise.resolve().then(() => (init_storage(), storage_exports));
81897
82013
  for (const f of files) {
81898
- const raw = await fs41.readFile(path85.join(decisionsDir, f), "utf-8");
82014
+ const raw = await fs41.readFile(path86.join(decisionsDir, f), "utf-8");
81899
82015
  const { meta: meta3, body } = parseFrontmatter2(raw);
81900
82016
  const title = meta3.title ?? body.split("\n")[0]?.replace(/^#\s*/, "").trim() ?? f;
81901
82017
  lines.push(`- **${f.replace(/\.md$/, "")}** [${meta3.status ?? "unknown"}] ${title}`);
@@ -81908,7 +82024,7 @@ async function handleWorkspaceShow(ctx, what) {
81908
82024
  break;
81909
82025
  }
81910
82026
  case "risks": {
81911
- const risksPath = path85.join(zelari, "risks.md");
82027
+ const risksPath = path86.join(zelari, "risks.md");
81912
82028
  try {
81913
82029
  content = await fs41.readFile(risksPath, "utf-8");
81914
82030
  } catch {
@@ -81917,7 +82033,7 @@ async function handleWorkspaceShow(ctx, what) {
81917
82033
  break;
81918
82034
  }
81919
82035
  case "agents": {
81920
- const agentsPath = path85.join(process.cwd(), "AGENTS.MD");
82036
+ const agentsPath = path86.join(process.cwd(), "AGENTS.MD");
81921
82037
  try {
81922
82038
  content = await fs41.readFile(agentsPath, "utf-8");
81923
82039
  } catch {
@@ -81926,7 +82042,7 @@ async function handleWorkspaceShow(ctx, what) {
81926
82042
  break;
81927
82043
  }
81928
82044
  case "docs": {
81929
- const docsDir = path85.join(zelari, "docs");
82045
+ const docsDir = path86.join(zelari, "docs");
81930
82046
  try {
81931
82047
  const files = (await fs41.readdir(docsDir)).filter((f) => f.endsWith(".md")).sort();
81932
82048
  content = files.length ? `# Docs (${files.length})
@@ -81968,7 +82084,7 @@ async function handleWorkspaceReset(ctx, force) {
81968
82084
  return;
81969
82085
  }
81970
82086
  try {
81971
- const target = path85.join(process.cwd(), ".zelari");
82087
+ const target = path86.join(process.cwd(), ".zelari");
81972
82088
  await fs41.rm(target, { recursive: true, force: true });
81973
82089
  appendSystem(ctx.setMessages, "[workspace] .zelari/ removed");
81974
82090
  } catch (err) {
@@ -83851,8 +83967,8 @@ function normalizeDraft(raw, sourceUrl, provider, model) {
83851
83967
  let name = String(o.name ?? "").trim().toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 64);
83852
83968
  if (!name || !/^[a-z0-9][a-z0-9-]{0,63}$/.test(name)) {
83853
83969
  try {
83854
- const path99 = new URL(sourceUrl).pathname.split("/").filter(Boolean).pop()?.replace(/\.[a-z0-9]+$/i, "").toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 48);
83855
- name = path99 && /^[a-z0-9]/.test(path99) ? path99 : "imported-skill";
83970
+ const path100 = new URL(sourceUrl).pathname.split("/").filter(Boolean).pop()?.replace(/\.[a-z0-9]+$/i, "").toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 48);
83971
+ name = path100 && /^[a-z0-9]/.test(path100) ? path100 : "imported-skill";
83856
83972
  } catch {
83857
83973
  name = "imported-skill";
83858
83974
  }