squadrant 0.26.0 → 0.26.2

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.
@@ -423,22 +423,22 @@ function defaultCmuxConfigPath() {
423
423
  return join(homedir(), ".config", "cmux", "cmux.json");
424
424
  }
425
425
  function ensureSocketAutomation(opts = {}) {
426
- const path28 = opts.path ?? defaultCmuxConfigPath();
427
- if (!existsSync(path28)) {
428
- mkdirSync(dirname(path28), { recursive: true });
429
- writeFileSync(path28, MINIMAL_TEMPLATE);
430
- return { path: path28, changed: true, alreadySet: false };
426
+ const path29 = opts.path ?? defaultCmuxConfigPath();
427
+ if (!existsSync(path29)) {
428
+ mkdirSync(dirname(path29), { recursive: true });
429
+ writeFileSync(path29, MINIMAL_TEMPLATE);
430
+ return { path: path29, changed: true, alreadySet: false };
431
431
  }
432
- const text = readFileSync(path28, "utf-8");
432
+ const text = readFileSync(path29, "utf-8");
433
433
  const current = parse(text)?.automation?.socketControlMode;
434
434
  if (current === AUTOMATION_MODE) {
435
- return { path: path28, changed: false, alreadySet: true };
435
+ return { path: path29, changed: false, alreadySet: true };
436
436
  }
437
437
  const edits = modify(text, [...SOCKET_CONTROL_MODE_PATH], AUTOMATION_MODE, {
438
438
  formattingOptions: { insertSpaces: true, tabSize: 2 }
439
439
  });
440
- writeFileSync(path28, applyEdits(text, edits));
441
- return { path: path28, changed: true, alreadySet: false };
440
+ writeFileSync(path29, applyEdits(text, edits));
441
+ return { path: path29, changed: true, alreadySet: false };
442
442
  }
443
443
  var SOCKET_CONTROL_MODE_PATH, AUTOMATION_MODE, MINIMAL_TEMPLATE;
444
444
  var init_cmux_config = __esm({
@@ -588,9 +588,9 @@ import { join as join4 } from "path";
588
588
  function defaultStatePath() {
589
589
  return join4(homedir3(), ".config", "squadrant", "state", "cmux-autoconfig.json");
590
590
  }
591
- function readState(path28) {
591
+ function readState(path29) {
592
592
  try {
593
- return JSON.parse(readConfigFileSync(path28));
593
+ return JSON.parse(readConfigFileSync(path29));
594
594
  } catch {
595
595
  return {};
596
596
  }
@@ -1774,12 +1774,12 @@ async function* readFromCursor(opts) {
1774
1774
  continue;
1775
1775
  throw e;
1776
1776
  }
1777
- for (const line of buf.split("\n")) {
1778
- if (!line.trim())
1777
+ for (const line2 of buf.split("\n")) {
1778
+ if (!line2.trim())
1779
1779
  continue;
1780
1780
  let entry;
1781
1781
  try {
1782
- entry = JSON.parse(line);
1782
+ entry = JSON.parse(line2);
1783
1783
  } catch {
1784
1784
  continue;
1785
1785
  }
@@ -1881,17 +1881,17 @@ function createDecoder(onParseError) {
1881
1881
  const out = [];
1882
1882
  let idx;
1883
1883
  while ((idx = buf.indexOf("\n")) >= 0) {
1884
- const line = buf.slice(0, idx);
1884
+ const line2 = buf.slice(0, idx);
1885
1885
  buf = buf.slice(idx + 1);
1886
- if (!line.trim())
1886
+ if (!line2.trim())
1887
1887
  continue;
1888
1888
  try {
1889
- const parsed = JSON.parse(line);
1889
+ const parsed = JSON.parse(line2);
1890
1890
  if (typeof parsed === "object" && parsed !== null && parsed.type === "_keepalive")
1891
1891
  continue;
1892
1892
  out.push(parsed);
1893
1893
  } catch {
1894
- onParseError?.(line);
1894
+ onParseError?.(line2);
1895
1895
  }
1896
1896
  }
1897
1897
  return out;
@@ -2051,11 +2051,11 @@ function encodeFrame(f) {
2051
2051
  }
2052
2052
  function decodeFrames(wire) {
2053
2053
  const out = [];
2054
- for (const line of wire.split("\n")) {
2055
- if (!line.trim())
2054
+ for (const line2 of wire.split("\n")) {
2055
+ if (!line2.trim())
2056
2056
  continue;
2057
2057
  try {
2058
- const parsed = JSON.parse(line);
2058
+ const parsed = JSON.parse(line2);
2059
2059
  if (parsed.type === "_keepalive")
2060
2060
  continue;
2061
2061
  out.push(parsed);
@@ -2537,10 +2537,10 @@ function detectForeignInstall(parsed, thisEntry, registeredEntryExists) {
2537
2537
  isUpgrade: isVersionUpgrade(parsed.daemonEntry, thisEntry)
2538
2538
  };
2539
2539
  }
2540
- function sanitizePathForPlist(path28) {
2540
+ function sanitizePathForPlist(path29) {
2541
2541
  const seen = /* @__PURE__ */ new Set();
2542
2542
  const stable = [];
2543
- for (const p of path28.split(":")) {
2543
+ for (const p of path29.split(":")) {
2544
2544
  if (!p)
2545
2545
  continue;
2546
2546
  if (p.includes("/.claude/plugins/"))
@@ -3243,14 +3243,14 @@ function detectTrailingQuestion(text) {
3243
3243
  let inFence = false;
3244
3244
  let lastLine = null;
3245
3245
  for (const raw of text.split(/\r?\n/)) {
3246
- const line = raw.trim();
3247
- if (line.startsWith("```")) {
3246
+ const line2 = raw.trim();
3247
+ if (line2.startsWith("```")) {
3248
3248
  inFence = !inFence;
3249
3249
  continue;
3250
3250
  }
3251
- if (inFence || line === "")
3251
+ if (inFence || line2 === "")
3252
3252
  continue;
3253
- lastLine = line;
3253
+ lastLine = line2;
3254
3254
  }
3255
3255
  if (lastLine && lastLine.endsWith("?"))
3256
3256
  return lastLine;
@@ -3261,9 +3261,9 @@ function isQuotedLine(raw) {
3261
3261
  return QUOTED_PREFIX_RE.test(noAnsi);
3262
3262
  }
3263
3263
  function stripChrome(raw) {
3264
- let line = raw.replace(/\[[0-9;]*m/g, "");
3265
- line = line.replace(/^[\s│┃▏▕|]+/, "").replace(/[\s│┃▏▕|]+$/, "");
3266
- const trimmed = line.trim();
3264
+ let line2 = raw.replace(/\[[0-9;]*m/g, "");
3265
+ line2 = line2.replace(/^[\s│┃▏▕|]+/, "").replace(/[\s│┃▏▕|]+$/, "");
3266
+ const trimmed = line2.trim();
3267
3267
  if (trimmed === "")
3268
3268
  return null;
3269
3269
  if (PURE_CHROME_RE.test(trimmed))
@@ -3924,12 +3924,12 @@ function extractUserIntentFromTranscript(jsonl) {
3924
3924
  return null;
3925
3925
  const lines = jsonl.split(/\r?\n/);
3926
3926
  for (let i = lines.length - 1; i >= 0; i--) {
3927
- const line = lines[i].trim();
3928
- if (!line)
3927
+ const line2 = lines[i].trim();
3928
+ if (!line2)
3929
3929
  continue;
3930
3930
  let entry;
3931
3931
  try {
3932
- entry = JSON.parse(line);
3932
+ entry = JSON.parse(line2);
3933
3933
  } catch {
3934
3934
  continue;
3935
3935
  }
@@ -4378,10 +4378,10 @@ async function reapCrewChildren(taskId, graceMs = 2e3, execFn = nodeExec) {
4378
4378
  execFn("ps auxE", { maxBuffer: 64 * 1024 * 1024 }, (err, out) => err ? reject(err) : resolve4(out));
4379
4379
  });
4380
4380
  const pids = [];
4381
- for (const line of stdout.split("\n").slice(1)) {
4382
- if (!line.includes(marker))
4381
+ for (const line2 of stdout.split("\n").slice(1)) {
4382
+ if (!line2.includes(marker))
4383
4383
  continue;
4384
- const pid = parseInt(line.trim().split(/\s+/)[1], 10);
4384
+ const pid = parseInt(line2.trim().split(/\s+/)[1], 10);
4385
4385
  if (!isNaN(pid) && pid !== process.pid)
4386
4386
  pids.push(pid);
4387
4387
  }
@@ -5076,11 +5076,11 @@ var init_captain_record = __esm({
5076
5076
  // packages/core/dist/opencode-session.js
5077
5077
  import { execFileSync as execFileSync4 } from "child_process";
5078
5078
  async function listSessions(port, fetchImpl = fetch, timeoutMs = 5e3) {
5079
- for (const path28 of ["/session", "/api/session"]) {
5079
+ for (const path29 of ["/session", "/api/session"]) {
5080
5080
  const ac = new AbortController();
5081
5081
  const t = setTimeout(() => ac.abort(), timeoutMs);
5082
5082
  try {
5083
- const res = await fetchImpl(`http://127.0.0.1:${port}${path28}`, { signal: ac.signal });
5083
+ const res = await fetchImpl(`http://127.0.0.1:${port}${path29}`, { signal: ac.signal });
5084
5084
  if (!res.ok)
5085
5085
  continue;
5086
5086
  const rows = await res.json();
@@ -5095,8 +5095,8 @@ async function listSessions(port, fetchImpl = fetch, timeoutMs = 5e3) {
5095
5095
  }
5096
5096
  function parseLiveOpencodeServers(psOutput) {
5097
5097
  const out = [];
5098
- for (const line of psOutput.split("\n")) {
5099
- const m = line.match(/^\s*(\d+)\s+(.+)$/);
5098
+ for (const line2 of psOutput.split("\n")) {
5099
+ const m = line2.match(/^\s*(\d+)\s+(.+)$/);
5100
5100
  if (!m)
5101
5101
  continue;
5102
5102
  const pid = Number(m[1]);
@@ -5122,8 +5122,8 @@ function defaultPsOutput() {
5122
5122
  function defaultCwdOf(pid) {
5123
5123
  try {
5124
5124
  const out = execFileSync4("lsof", ["-a", "-p", String(pid), "-d", "cwd", "-Fn"], { encoding: "utf-8", timeout: 2e3 });
5125
- const line = out.split("\n").find((l) => l.startsWith("n"));
5126
- return line ? line.slice(1) : null;
5125
+ const line2 = out.split("\n").find((l) => l.startsWith("n"));
5126
+ return line2 ? line2.slice(1) : null;
5127
5127
  } catch {
5128
5128
  return null;
5129
5129
  }
@@ -5773,10 +5773,10 @@ function distBuiltAt() {
5773
5773
  return 0;
5774
5774
  }
5775
5775
  }
5776
- function gatherLogStats(path28, now, windowMs) {
5776
+ function gatherLogStats(path29, now, windowMs) {
5777
5777
  let sizeBytes = 0;
5778
5778
  try {
5779
- sizeBytes = statSync3(path28).size;
5779
+ sizeBytes = statSync3(path29).size;
5780
5780
  } catch {
5781
5781
  return { errorCount: 0, sizeBytes: 0, windowMs };
5782
5782
  }
@@ -5787,7 +5787,7 @@ function gatherLogStats(path28, now, windowMs) {
5787
5787
  const len = sizeBytes - start;
5788
5788
  let text = "";
5789
5789
  try {
5790
- const fd = openSync2(path28, "r");
5790
+ const fd = openSync2(path29, "r");
5791
5791
  try {
5792
5792
  const buf = Buffer.alloc(len);
5793
5793
  readSync(fd, buf, 0, len, start);
@@ -5800,10 +5800,10 @@ function gatherLogStats(path28, now, windowMs) {
5800
5800
  }
5801
5801
  const cutoff = now - windowMs;
5802
5802
  let errorCount = 0;
5803
- for (const line of text.split("\n")) {
5804
- if (!/error|failed/i.test(line))
5803
+ for (const line2 of text.split("\n")) {
5804
+ if (!/error|failed/i.test(line2))
5805
5805
  continue;
5806
- const m = line.match(/\d{4}-\d{2}-\d{2}T[\d:.]+Z/);
5806
+ const m = line2.match(/\d{4}-\d{2}-\d{2}T[\d:.]+Z/);
5807
5807
  if (m) {
5808
5808
  const ts = Date.parse(m[0]);
5809
5809
  if (!Number.isNaN(ts) && ts < cutoff)
@@ -7978,10 +7978,10 @@ function scan(bufRef, acc) {
7978
7978
  let saw = false;
7979
7979
  let idx;
7980
7980
  while ((idx = bufRef.value.indexOf("\n")) !== -1) {
7981
- const line = bufRef.value.slice(0, idx).trim();
7981
+ const line2 = bufRef.value.slice(0, idx).trim();
7982
7982
  bufRef.value = bufRef.value.slice(idx + 1);
7983
- if (line.startsWith("data:")) {
7984
- const payload = line.slice(5).trim();
7983
+ if (line2.startsWith("data:")) {
7984
+ const payload = line2.slice(5).trim();
7985
7985
  if (payload && payload !== "[DONE]") {
7986
7986
  try {
7987
7987
  if (absorb(JSON.parse(payload), acc))
@@ -8032,8 +8032,8 @@ var init_stream = __esm({
8032
8032
  // packages/core/dist/router/shim.js
8033
8033
  import { createServer as createServer3 } from "http";
8034
8034
  import { Readable } from "stream";
8035
- function joinUrl(base, path28) {
8036
- return base.replace(/\/+$/, "") + path28;
8035
+ function joinUrl(base, path29) {
8036
+ return base.replace(/\/+$/, "") + path29;
8037
8037
  }
8038
8038
  async function readBody(req) {
8039
8039
  const chunks = [];
@@ -8209,8 +8209,8 @@ function createRouterShim(opts) {
8209
8209
  writeJson(res, 200, { input_tokens: Math.max(1, Math.ceil(text.length / 4)) });
8210
8210
  }
8211
8211
  function handler(req, res) {
8212
- const path28 = pathnameOf(req.url);
8213
- if (req.method === "POST" && path28 === "/v1/messages") {
8212
+ const path29 = pathnameOf(req.url);
8213
+ if (req.method === "POST" && path29 === "/v1/messages") {
8214
8214
  void handleMessages(req, res).catch((err) => {
8215
8215
  log(`router internal error: ${err instanceof Error ? err.message : String(err)}`);
8216
8216
  if (!res.headersSent) {
@@ -8222,18 +8222,18 @@ function createRouterShim(opts) {
8222
8222
  });
8223
8223
  return;
8224
8224
  }
8225
- if (req.method === "POST" && path28 === "/v1/messages/count_tokens") {
8225
+ if (req.method === "POST" && path29 === "/v1/messages/count_tokens") {
8226
8226
  void handleCountTokens(req, res).catch(() => {
8227
8227
  if (!res.headersSent)
8228
8228
  writeJson(res, 502, anthropicError(502, "api_error", "router internal error").body);
8229
8229
  });
8230
8230
  return;
8231
8231
  }
8232
- if (req.method === "GET" && path28 === "/v1/models") {
8232
+ if (req.method === "GET" && path29 === "/v1/models") {
8233
8233
  writeJson(res, 200, modelsList([...advertisedModels]));
8234
8234
  return;
8235
8235
  }
8236
- if (req.method === "GET" && path28 === "/healthz") {
8236
+ if (req.method === "GET" && path29 === "/healthz") {
8237
8237
  writeJson(res, 200, { ready: server?.listening === true, upstreamReachable, lastError });
8238
8238
  return;
8239
8239
  }
@@ -8502,11 +8502,11 @@ async function probeCaptainChannel(project, opts = {}) {
8502
8502
  }
8503
8503
  }
8504
8504
  async function httpReachable(port, fetchImpl, timeoutMs) {
8505
- for (const path28 of ["/session", "/api/session"]) {
8505
+ for (const path29 of ["/session", "/api/session"]) {
8506
8506
  const ac = new AbortController();
8507
8507
  const t = setTimeout(() => ac.abort(), timeoutMs);
8508
8508
  try {
8509
- const res = await fetchImpl(`http://127.0.0.1:${port}${path28}`, { signal: ac.signal });
8509
+ const res = await fetchImpl(`http://127.0.0.1:${port}${path29}`, { signal: ac.signal });
8510
8510
  if (res.ok)
8511
8511
  return true;
8512
8512
  } catch {
@@ -9288,8 +9288,12 @@ var init_paths = __esm({
9288
9288
 
9289
9289
  // packages/core/dist/knowledge/store.js
9290
9290
  import fs15 from "fs";
9291
+ import os7 from "os";
9291
9292
  import path15 from "path";
9292
9293
  import matter2 from "gray-matter";
9294
+ function duplicateIdProblem(id, ignored, used) {
9295
+ return `duplicate id ${id}: ${ignored} is ignored, ${used} is used (live files win over _proposed, then path order). Fix: rename the id in one file, or delete or move one of them.`;
9296
+ }
9293
9297
  function splitStatement(body) {
9294
9298
  const first = body.trim().split(/\n\s*\n/)[0] ?? "";
9295
9299
  return first.replace(/\s+/g, " ").trim();
@@ -9334,7 +9338,7 @@ function loadRulesDir(dir, layer, opts = {}) {
9334
9338
  const fm = parsed.data;
9335
9339
  const prior = seen.get(fm.id);
9336
9340
  if (prior) {
9337
- errors.push({ file, problems: [`duplicate id ${fm.id} (also in ${prior})`] });
9341
+ errors.push({ file, problems: [duplicateIdProblem(fm.id, file, prior)] });
9338
9342
  continue;
9339
9343
  }
9340
9344
  seen.set(fm.id, file);
@@ -9342,7 +9346,65 @@ function loadRulesDir(dir, layer, opts = {}) {
9342
9346
  }
9343
9347
  return { rules, errors };
9344
9348
  }
9345
- var NO_JS_FRONTMATTER;
9349
+ function resolveSourceRef(ref, kbRoot, sources) {
9350
+ const bases = /* @__PURE__ */ new Set([kbRoot]);
9351
+ for (const s of sources) {
9352
+ let d = path15.resolve(kbRoot, expandHome(s.path.split(/[*?[{]/)[0]));
9353
+ for (let i = 0; i < 6 && d !== path15.dirname(d); i++) {
9354
+ d = path15.dirname(d);
9355
+ bases.add(d);
9356
+ }
9357
+ }
9358
+ const cands = [path15.resolve(kbRoot, expandHome(ref)), ...[...bases].map((b) => path15.join(b, ref))];
9359
+ return cands.find((c) => fs15.existsSync(c) && fs15.statSync(c).isFile());
9360
+ }
9361
+ function validateKb(opts) {
9362
+ const { rules, errors } = loadRulesDir(opts.rulesDir, "kb", { includeProposed: true });
9363
+ const checks = [];
9364
+ const dups = errors.filter((e) => e.problems.some((p) => p.startsWith("duplicate id")));
9365
+ const invalid = errors.filter((e) => !dups.includes(e));
9366
+ const proposed = rules.filter((r) => path15.relative(opts.rulesDir, r.file).split(path15.sep).includes(PROPOSED_DIR)).length;
9367
+ checks.push({ level: "ok", message: `${rules.length + errors.length} rule files read (${rules.length - proposed} live, ${proposed} proposed parsed OK)` });
9368
+ if (invalid.length)
9369
+ for (const e of invalid)
9370
+ checks.push({ level: "fail", message: `invalid ${e.file}: ${e.problems.join("; ")}` });
9371
+ else
9372
+ checks.push({ level: "ok", message: "no invalid rule files" });
9373
+ if (dups.length)
9374
+ for (const e of dups)
9375
+ checks.push({ level: "fail", message: e.problems.join("; ") });
9376
+ else
9377
+ checks.push({ level: "ok", message: "no duplicate ids" });
9378
+ const cache = /* @__PURE__ */ new Map();
9379
+ let verified = 0, unresolved = 0;
9380
+ for (const r of rules) {
9381
+ r.sources.forEach((src, i) => {
9382
+ const file = resolveSourceRef(src.ref, opts.kbRoot, opts.sources);
9383
+ if (!file) {
9384
+ unresolved++;
9385
+ return;
9386
+ }
9387
+ if (!cache.has(file))
9388
+ cache.set(file, fs15.readFileSync(file, "utf8"));
9389
+ if (cache.get(file).includes(src.quote))
9390
+ verified++;
9391
+ else
9392
+ checks.push({ level: "fail", message: `quote not found in ${file}: ${r.id} sources[${i}] (${r.file})` });
9393
+ });
9394
+ }
9395
+ if (!checks.some((c) => c.message.startsWith("quote not found")))
9396
+ checks.push({ level: "ok", message: `${verified} source quotes found in their source files` });
9397
+ if (unresolved)
9398
+ checks.push({ level: "skip", message: `${unresolved} source refs not resolvable on this machine, quote not checked` });
9399
+ if (opts.domains) {
9400
+ for (const r of rules) {
9401
+ if (!opts.domains.includes(r.domain))
9402
+ checks.push({ level: "warn", message: `${r.id}: domain '${r.domain}' not in allowed domains [${opts.domains.join(", ")}] (${r.file})` });
9403
+ }
9404
+ }
9405
+ return { checks, ok: !checks.some((c) => c.level === "fail") };
9406
+ }
9407
+ var NO_JS_FRONTMATTER, expandHome;
9346
9408
  var init_store2 = __esm({
9347
9409
  "packages/core/dist/knowledge/store.js"() {
9348
9410
  init_dist();
@@ -9352,6 +9414,7 @@ var init_store2 = __esm({
9352
9414
  throw new Error("only YAML front matter is allowed");
9353
9415
  } } }
9354
9416
  };
9417
+ expandHome = (p) => p === "~" || p.startsWith("~/") ? path15.join(os7.homedir(), p.slice(1)) : p;
9355
9418
  }
9356
9419
  });
9357
9420
 
@@ -9440,7 +9503,7 @@ var init_index_file = __esm({
9440
9503
 
9441
9504
  // packages/core/dist/knowledge/search.js
9442
9505
  function searchRules(rules, query, opts = {}) {
9443
- const terms = query.toLowerCase().split(/\s+/).filter(Boolean);
9506
+ const terms = [...new Set(query.toLowerCase().split(/\s+/).filter(Boolean))];
9444
9507
  if (terms.length === 0)
9445
9508
  return [];
9446
9509
  const statuses = opts.statuses ?? DEFAULT_SEARCH_STATUSES;
@@ -9452,30 +9515,45 @@ function searchRules(rules, query, opts = {}) {
9452
9515
  const expanded = lower(rule.triggers?.expanded);
9453
9516
  const when = (rule.triggers?.when ?? "").toLowerCase();
9454
9517
  const statement = rule.statement.toLowerCase();
9518
+ const rationale = rationaleOf(rule);
9455
9519
  const id = rule.id.toLowerCase();
9456
9520
  let score = 0;
9521
+ let matched = 0;
9522
+ let curated = false;
9457
9523
  for (const t of terms) {
9524
+ let s = 0;
9458
9525
  if (id.includes(t))
9459
- score += 3;
9526
+ s += 3;
9527
+ if (keywords.includes(t) || expanded.includes(t))
9528
+ curated = true;
9460
9529
  if (keywords.includes(t))
9461
- score += 3;
9530
+ s += 3;
9462
9531
  if (expanded.includes(t))
9463
- score += 2;
9532
+ s += 3;
9464
9533
  if (when.includes(t))
9465
- score += 2;
9534
+ s += 2;
9466
9535
  if (statement.includes(t))
9467
- score += 1;
9536
+ s += 2;
9537
+ if (rationale.includes(t))
9538
+ s += 1;
9539
+ if (s > 0) {
9540
+ matched++;
9541
+ score += s;
9542
+ }
9468
9543
  }
9469
9544
  if (score > 0)
9470
- hits.push({ rule, score });
9545
+ hits.push({ rule, score, matched, curated });
9471
9546
  }
9472
- return hits.sort((a, b) => b.score - a.score || a.rule.id.localeCompare(b.rule.id));
9547
+ const strong = terms.length >= 2 ? hits.filter((h) => h.matched >= 2 || h.curated) : hits;
9548
+ const out = strong.length ? strong : hits;
9549
+ return out.sort((a, b) => b.score - a.score || a.rule.id.localeCompare(b.rule.id));
9473
9550
  }
9474
- var DEFAULT_SEARCH_STATUSES, lower;
9551
+ var DEFAULT_SEARCH_STATUSES, lower, rationaleOf;
9475
9552
  var init_search = __esm({
9476
9553
  "packages/core/dist/knowledge/search.js"() {
9477
9554
  DEFAULT_SEARCH_STATUSES = ["active", "stale"];
9478
9555
  lower = (xs) => (xs ?? []).map((x) => x.toLowerCase());
9556
+ rationaleOf = (rule) => rule.body.slice(rule.statement.length).toLowerCase();
9479
9557
  }
9480
9558
  });
9481
9559
 
@@ -9611,28 +9689,28 @@ function requireSnippet() {
9611
9689
  const maxLineLength = options.maxLength - (options.indent + lineNoLength + 3);
9612
9690
  for (let i = 1; i <= options.linesBefore; i++) {
9613
9691
  if (foundLineNo - i < 0) break;
9614
- const line2 = getLine(
9692
+ const line22 = getLine(
9615
9693
  mark2.buffer,
9616
9694
  lineStarts[foundLineNo - i],
9617
9695
  lineEnds[foundLineNo - i],
9618
9696
  mark2.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo - i]),
9619
9697
  maxLineLength
9620
9698
  );
9621
- result = common2.repeat(" ", options.indent) + padStart((mark2.line - i + 1).toString(), lineNoLength) + " | " + line2.str + "\n" + result;
9699
+ result = common2.repeat(" ", options.indent) + padStart((mark2.line - i + 1).toString(), lineNoLength) + " | " + line22.str + "\n" + result;
9622
9700
  }
9623
- const line = getLine(mark2.buffer, lineStarts[foundLineNo], lineEnds[foundLineNo], mark2.position, maxLineLength);
9624
- result += common2.repeat(" ", options.indent) + padStart((mark2.line + 1).toString(), lineNoLength) + " | " + line.str + "\n";
9625
- result += common2.repeat("-", options.indent + lineNoLength + 3 + line.pos) + "^\n";
9701
+ const line2 = getLine(mark2.buffer, lineStarts[foundLineNo], lineEnds[foundLineNo], mark2.position, maxLineLength);
9702
+ result += common2.repeat(" ", options.indent) + padStart((mark2.line + 1).toString(), lineNoLength) + " | " + line2.str + "\n";
9703
+ result += common2.repeat("-", options.indent + lineNoLength + 3 + line2.pos) + "^\n";
9626
9704
  for (let i = 1; i <= options.linesAfter; i++) {
9627
9705
  if (foundLineNo + i >= lineEnds.length) break;
9628
- const line2 = getLine(
9706
+ const line22 = getLine(
9629
9707
  mark2.buffer,
9630
9708
  lineStarts[foundLineNo + i],
9631
9709
  lineEnds[foundLineNo + i],
9632
9710
  mark2.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo + i]),
9633
9711
  maxLineLength
9634
9712
  );
9635
- result += common2.repeat(" ", options.indent) + padStart((mark2.line + i + 1).toString(), lineNoLength) + " | " + line2.str + "\n";
9713
+ result += common2.repeat(" ", options.indent) + padStart((mark2.line + i + 1).toString(), lineNoLength) + " | " + line22.str + "\n";
9636
9714
  }
9637
9715
  return result.replace(/\n$/, "");
9638
9716
  }
@@ -11919,17 +11997,17 @@ function requireDumper() {
11919
11997
  let result = "";
11920
11998
  const length = string.length;
11921
11999
  while (position < length) {
11922
- let line;
12000
+ let line2;
11923
12001
  const next = string.indexOf("\n", position);
11924
12002
  if (next === -1) {
11925
- line = string.slice(position);
12003
+ line2 = string.slice(position);
11926
12004
  position = length;
11927
12005
  } else {
11928
- line = string.slice(position, next + 1);
12006
+ line2 = string.slice(position, next + 1);
11929
12007
  position = next + 1;
11930
12008
  }
11931
- if (line.length && line !== "\n") result += ind;
11932
- result += line;
12009
+ if (line2.length && line2 !== "\n") result += ind;
12010
+ result += line2;
11933
12011
  }
11934
12012
  return result;
11935
12013
  }
@@ -12114,15 +12192,15 @@ function requireDumper() {
12114
12192
  let match;
12115
12193
  while (match = lineRe.exec(string)) {
12116
12194
  const prefix = match[1];
12117
- const line = match[2];
12118
- moreIndented = line[0] === " ";
12119
- result += prefix + (!prevMoreIndented && !moreIndented && line !== "" ? "\n" : "") + foldLine(line, width);
12195
+ const line2 = match[2];
12196
+ moreIndented = line2[0] === " ";
12197
+ result += prefix + (!prevMoreIndented && !moreIndented && line2 !== "" ? "\n" : "") + foldLine(line2, width);
12120
12198
  prevMoreIndented = moreIndented;
12121
12199
  }
12122
12200
  return result;
12123
12201
  }
12124
- function foldLine(line, width) {
12125
- if (line === "" || line[0] === " ") return line;
12202
+ function foldLine(line2, width) {
12203
+ if (line2 === "" || line2[0] === " ") return line2;
12126
12204
  const breakRe = / [^ ]/g;
12127
12205
  let match;
12128
12206
  let start = 0;
@@ -12130,20 +12208,20 @@ function requireDumper() {
12130
12208
  let curr = 0;
12131
12209
  let next = 0;
12132
12210
  let result = "";
12133
- while (match = breakRe.exec(line)) {
12211
+ while (match = breakRe.exec(line2)) {
12134
12212
  next = match.index;
12135
12213
  if (next - start > width) {
12136
12214
  end = curr > start ? curr : next;
12137
- result += "\n" + line.slice(start, end);
12215
+ result += "\n" + line2.slice(start, end);
12138
12216
  start = end + 1;
12139
12217
  }
12140
12218
  curr = next;
12141
12219
  }
12142
12220
  result += "\n";
12143
- if (line.length - start > width && curr > start) {
12144
- result += line.slice(start, curr) + "\n" + line.slice(curr + 1);
12221
+ if (line2.length - start > width && curr > start) {
12222
+ result += line2.slice(start, curr) + "\n" + line2.slice(curr + 1);
12145
12223
  } else {
12146
- result += line.slice(start);
12224
+ result += line2.slice(start);
12147
12225
  }
12148
12226
  return result.slice(1);
12149
12227
  }
@@ -12552,6 +12630,220 @@ var init_sources = __esm({
12552
12630
  }
12553
12631
  });
12554
12632
 
12633
+ // packages/core/dist/knowledge/inject.js
12634
+ import fs19 from "fs";
12635
+ import path18 from "path";
12636
+ function sessionOrder(a, b) {
12637
+ const proj = (r) => r.layer.startsWith("project:") ? 0 : 1;
12638
+ const mod = (r) => r.modality === "must-not" ? 0 : 1;
12639
+ return proj(a) - proj(b) || mod(a) - mod(b) || a.id.localeCompare(b.id);
12640
+ }
12641
+ function formatSessionContext(kbs, rules, cap = SESSION_RULE_CAP) {
12642
+ const hard = rules.filter((r) => r.status === "active" && (r.modality === "must" || r.modality === "must-not")).sort(sessionOrder);
12643
+ const shown = hard.slice(0, cap);
12644
+ const lines = [
12645
+ `<squadrant-project-rules kb="${kbs.join(",")}">`,
12646
+ `Rules KB: ${kbs.join(", ")}. ${DATA_NOTE}`,
12647
+ ...shown.map(line)
12648
+ ];
12649
+ if (hard.length > shown.length)
12650
+ lines.push(`+${hard.length - shown.length} more: squadrant rules list --brief`);
12651
+ lines.push("Look up rules for a task with `squadrant rules search <terms>` / `squadrant rules show <id>` (rules-ops skill).");
12652
+ lines.push("</squadrant-project-rules>");
12653
+ return { text: lines.join("\n"), ids: shown.map((r) => r.id) };
12654
+ }
12655
+ function cleanPromptQuery(prompt) {
12656
+ const text = prompt.replace(/```[\s\S]*?(```|$)/g, " ").split("\n").filter((l) => l.length <= MAX_LINE_CHARS).join("\n").slice(0, MAX_PROMPT_CHARS).toLowerCase().replace(/https?:\/\/\S+/g, " ");
12657
+ const terms = [];
12658
+ const add = (t) => {
12659
+ if (t.length < 3 && !SHORT_TERMS.has(t) || /^\d+$/.test(t) || STOPWORDS.has(t) || terms.includes(t))
12660
+ return;
12661
+ terms.push(t);
12662
+ };
12663
+ for (const raw of text.split(/[^a-z0-9._-]+/)) {
12664
+ const t = raw.replace(/^[._-]+|[._-]+$/g, "");
12665
+ if (STOPWORDS.has(t))
12666
+ continue;
12667
+ add(t);
12668
+ const parts = t.split(/[._-]+/);
12669
+ if (parts.length > 1 && parts.every((x) => x.length >= 3 && !PREFIXES.has(x)))
12670
+ parts.forEach(add);
12671
+ if (terms.length >= MAX_TERMS)
12672
+ break;
12673
+ }
12674
+ return terms.slice(0, MAX_TERMS).join(" ");
12675
+ }
12676
+ function wholeWordTerms(rule, terms) {
12677
+ const text = [
12678
+ rule.id,
12679
+ ...rule.triggers?.keywords ?? [],
12680
+ ...rule.triggers?.expanded ?? [],
12681
+ rule.triggers?.when ?? "",
12682
+ rule.statement
12683
+ ].join("\n").toLowerCase();
12684
+ return terms.filter((t) => {
12685
+ const base = t.length > 4 ? t.replace(/(es|s)$/, "") : t;
12686
+ return new RegExp(`(^|[^a-z0-9])(?:${escapeRe(t)}|${escapeRe(base)}(?:s|es)?)($|[^a-z0-9])`).test(text);
12687
+ });
12688
+ }
12689
+ function selectPromptHits(hits, query, seen, opts = {}) {
12690
+ const minScore = opts.minScore ?? PROMPT_MIN_SCORE;
12691
+ const terms = query.split(" ").filter(Boolean);
12692
+ return hits.filter((h) => {
12693
+ if (seen.has(h.rule.id))
12694
+ return false;
12695
+ const n = wholeWordTerms(h.rule, terms).length;
12696
+ return n >= 2 && h.score >= minScore || n === 1 && h.score >= PROMPT_SINGLE_TERM_MIN_SCORE;
12697
+ }).slice(0, opts.cap ?? PROMPT_RULE_CAP);
12698
+ }
12699
+ function isSystemPrompt(prompt) {
12700
+ const t = prompt.trimStart();
12701
+ return /^(⚠|🗒|\[stale\b|CREW [A-Z]|Another Claude session sent a message)/u.test(t) || t.includes("<cross-session-message");
12702
+ }
12703
+ function promptText(prompt) {
12704
+ const m = BRIEF_POINTER_RE.exec(prompt.trimStart());
12705
+ if (!m)
12706
+ return prompt;
12707
+ try {
12708
+ return fs19.readFileSync(m[1], "utf8").slice(0, MAX_PROMPT_CHARS * 2);
12709
+ } catch {
12710
+ return prompt;
12711
+ }
12712
+ }
12713
+ function formatPromptContext(hits) {
12714
+ return [
12715
+ '<squadrant-project-rules match="prompt">',
12716
+ `Rules that may apply to this prompt. ${DATA_NOTE}`,
12717
+ ...hits.map((h) => line(h.rule)),
12718
+ "</squadrant-project-rules>"
12719
+ ].join("\n");
12720
+ }
12721
+ function injectStateDir(stateRoot) {
12722
+ return path18.join(stateRoot, "rules-inject");
12723
+ }
12724
+ function readSeenRules(stateRoot, sessionId) {
12725
+ try {
12726
+ const ids = JSON.parse(fs19.readFileSync(sessionFile(stateRoot, sessionId), "utf8"));
12727
+ return new Set(Array.isArray(ids) ? ids.filter((x) => typeof x === "string") : []);
12728
+ } catch {
12729
+ return /* @__PURE__ */ new Set();
12730
+ }
12731
+ }
12732
+ function recordSeenRules(stateRoot, sessionId, ids) {
12733
+ if (!ids.length)
12734
+ return;
12735
+ const seen = readSeenRules(stateRoot, sessionId);
12736
+ for (const id of ids)
12737
+ seen.add(id);
12738
+ fs19.mkdirSync(injectStateDir(stateRoot), { recursive: true });
12739
+ fs19.writeFileSync(sessionFile(stateRoot, sessionId), JSON.stringify([...seen]));
12740
+ }
12741
+ function pruneSeenRules(stateRoot, now = Date.now()) {
12742
+ const dir = injectStateDir(stateRoot);
12743
+ let names;
12744
+ try {
12745
+ names = fs19.readdirSync(dir);
12746
+ } catch {
12747
+ return;
12748
+ }
12749
+ for (const n of names) {
12750
+ const f = path18.join(dir, n);
12751
+ try {
12752
+ if (now - fs19.statSync(f).mtimeMs > SEEN_TTL_MS)
12753
+ fs19.unlinkSync(f);
12754
+ } catch {
12755
+ }
12756
+ }
12757
+ }
12758
+ async function withBudget(fn, budgetMs = INJECT_BUDGET_MS) {
12759
+ const start = Date.now();
12760
+ let timer;
12761
+ try {
12762
+ const timeout = new Promise((resolve4) => {
12763
+ timer = setTimeout(() => resolve4(null), budgetMs);
12764
+ });
12765
+ const out = await Promise.race([Promise.resolve().then(fn), timeout]);
12766
+ return Date.now() - start > budgetMs ? null : out;
12767
+ } catch {
12768
+ return null;
12769
+ } finally {
12770
+ clearTimeout(timer);
12771
+ }
12772
+ }
12773
+ function resolveInjectProject(cfg, cwd, env, project) {
12774
+ const named = project ?? env.SQUADRANT_CREW_PROJECT;
12775
+ if (named)
12776
+ return cfg.projects[named] ? named : null;
12777
+ let best = null;
12778
+ let bestLen = -1;
12779
+ for (const [name, pc] of Object.entries(cfg.projects)) {
12780
+ const root = resolveHome(pc.path);
12781
+ if ((cwd === root || cwd.startsWith(root + path18.sep)) && root.length > bestLen) {
12782
+ best = name;
12783
+ bestLen = root.length;
12784
+ }
12785
+ }
12786
+ return best;
12787
+ }
12788
+ function computeRulesInjection(i) {
12789
+ if (i.env.SQUADRANT_RULES_INJECT === "0")
12790
+ return null;
12791
+ const p = typeof i.payload === "object" && i.payload !== null ? i.payload : {};
12792
+ const cwd = typeof p.cwd === "string" && p.cwd ? p.cwd : i.cwd;
12793
+ const project = resolveInjectProject(i.cfg, cwd, i.env, i.project);
12794
+ if (!project)
12795
+ return null;
12796
+ const kbs = subscribedKbs(i.cfg, project);
12797
+ if (!kbs.length)
12798
+ return null;
12799
+ const sessionId = typeof p.session_id === "string" && p.session_id ? p.session_id : null;
12800
+ if (i.event === "session-start") {
12801
+ const { text, ids } = formatSessionContext(kbs, resolveProjectRules(i.cfg, project).rules);
12802
+ if (sessionId) {
12803
+ pruneSeenRules(i.stateRoot);
12804
+ recordSeenRules(i.stateRoot, sessionId, ids);
12805
+ }
12806
+ return text;
12807
+ }
12808
+ if (typeof p.prompt !== "string" || isSystemPrompt(p.prompt))
12809
+ return null;
12810
+ const query = cleanPromptQuery(promptText(p.prompt));
12811
+ if (!query)
12812
+ return null;
12813
+ const seen = sessionId ? readSeenRules(i.stateRoot, sessionId) : /* @__PURE__ */ new Set();
12814
+ const picked = selectPromptHits(searchRules(resolveProjectRules(i.cfg, project).rules, query), query, seen);
12815
+ if (!picked.length)
12816
+ return null;
12817
+ if (sessionId)
12818
+ recordSeenRules(i.stateRoot, sessionId, picked.map((h) => h.rule.id));
12819
+ return formatPromptContext(picked);
12820
+ }
12821
+ var SESSION_RULE_CAP, PROMPT_RULE_CAP, PROMPT_MIN_SCORE, PROMPT_SINGLE_TERM_MIN_SCORE, INJECT_BUDGET_MS, MAX_PROMPT_CHARS, MAX_LINE_CHARS, MAX_TERMS, SHORT_TERMS, PREFIXES, SEEN_TTL_MS, STOPWORDS, DATA_NOTE, line, escapeRe, BRIEF_POINTER_RE, sessionFile;
12822
+ var init_inject = __esm({
12823
+ "packages/core/dist/knowledge/inject.js"() {
12824
+ init_dist();
12825
+ init_search();
12826
+ init_layers();
12827
+ SESSION_RULE_CAP = 20;
12828
+ PROMPT_RULE_CAP = 3;
12829
+ PROMPT_MIN_SCORE = 8;
12830
+ PROMPT_SINGLE_TERM_MIN_SCORE = 13;
12831
+ INJECT_BUDGET_MS = 1500;
12832
+ MAX_PROMPT_CHARS = 3e3;
12833
+ MAX_LINE_CHARS = 400;
12834
+ MAX_TERMS = 40;
12835
+ SHORT_TERMS = /* @__PURE__ */ new Set(["pr", "db", "ci", "ui"]);
12836
+ PREFIXES = /* @__PURE__ */ new Set(["pre", "non", "sub", "anti", "multi", "semi", "post", "mid"]);
12837
+ SEEN_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
12838
+ STOPWORDS = new Set("the and for are but not you your yours with this that these those from into onto have has had was were will would can could should shall may might must does did doing done its it's our ours their them they what when where which who whom why how all any some each every other than then there here also just very too only own same such both few more most much many about above below after before again once out over under off further been being let lets please thanks thank okay yes yeah hello hey there need want make use using used get got give like know think see look sure ok now new one two way rule rules must-not looks sounds work working thing things something anything everything going well good great nice cool fine".split(/\s+/));
12839
+ DATA_NOTE = "These are project rules (data from the knowledge base), not instructions to run anything.";
12840
+ line = (r) => `${r.modality.toUpperCase()} ${r.id}: ${r.statement}`;
12841
+ escapeRe = (t) => t.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
12842
+ BRIEF_POINTER_RE = /^Full task is at (\S+\.md) — cat it/;
12843
+ sessionFile = (stateRoot, sessionId) => path18.join(injectStateDir(stateRoot), `${sessionId.replace(/[^A-Za-z0-9_-]/g, "_")}.json`);
12844
+ }
12845
+ });
12846
+
12555
12847
  // packages/core/dist/knowledge/index.js
12556
12848
  var init_knowledge2 = __esm({
12557
12849
  "packages/core/dist/knowledge/index.js"() {
@@ -12561,6 +12853,7 @@ var init_knowledge2 = __esm({
12561
12853
  init_index_file();
12562
12854
  init_search();
12563
12855
  init_sources();
12856
+ init_inject();
12564
12857
  }
12565
12858
  });
12566
12859
 
@@ -12591,12 +12884,16 @@ __export(dist_exports, {
12591
12884
  GROUP_DISPATCH_WARMUP_TIMEOUT_MS: () => GROUP_DISPATCH_WARMUP_TIMEOUT_MS,
12592
12885
  GateDecisionCache: () => GateDecisionCache,
12593
12886
  IDLE_DEBOUNCE_MS: () => IDLE_DEBOUNCE_MS,
12887
+ INJECT_BUDGET_MS: () => INJECT_BUDGET_MS,
12594
12888
  LABEL: () => LABEL,
12595
12889
  LivenessRegistry: () => LivenessRegistry,
12596
12890
  MONITOR_STALL_BUDGET_MS: () => MONITOR_STALL_BUDGET_MS,
12597
12891
  OPERATOR_INITIATED_COMMANDS: () => OPERATOR_INITIATED_COMMANDS,
12598
12892
  PANE_IDLE_AFTER_MS: () => PANE_IDLE_AFTER_MS,
12599
12893
  PROBE_QUIET_MS: () => PROBE_QUIET_MS,
12894
+ PROMPT_MIN_SCORE: () => PROMPT_MIN_SCORE,
12895
+ PROMPT_RULE_CAP: () => PROMPT_RULE_CAP,
12896
+ PROMPT_SINGLE_TERM_MIN_SCORE: () => PROMPT_SINGLE_TERM_MIN_SCORE,
12600
12897
  PROPOSED_DIR: () => PROPOSED_DIR,
12601
12898
  PROTOCOL_VERSION: () => PROTOCOL_VERSION,
12602
12899
  READ_ONLY_CREW_SUBCOMMANDS: () => READ_ONLY_CREW_SUBCOMMANDS,
@@ -12604,6 +12901,7 @@ __export(dist_exports, {
12604
12901
  ROUTER_READY_ATTEMPTS: () => ROUTER_READY_ATTEMPTS,
12605
12902
  ROUTER_READY_DELAY_MS: () => ROUTER_READY_DELAY_MS,
12606
12903
  SERVER_TOOL_TYPE_RE: () => SERVER_TOOL_TYPE_RE,
12904
+ SESSION_RULE_CAP: () => SESSION_RULE_CAP,
12607
12905
  SIDE_SESSION_ENV: () => SIDE_SESSION_ENV,
12608
12906
  SOURCES_TEMPLATE: () => SOURCES_TEMPLATE,
12609
12907
  STALE_THRESHOLD_MS: () => STALE_THRESHOLD_MS,
@@ -12644,9 +12942,11 @@ __export(dist_exports, {
12644
12942
  classifyCaptainPane: () => classifyCaptainPane,
12645
12943
  classifyHealth: () => classifyHealth,
12646
12944
  claudeEnvShadowsRouter: () => claudeEnvShadowsRouter,
12945
+ cleanPromptQuery: () => cleanPromptQuery,
12647
12946
  clearPending: () => clearPending,
12648
12947
  closeWorkItem: () => closeWorkItem,
12649
12948
  compileIndex: () => compileIndex,
12949
+ computeRulesInjection: () => computeRulesInjection,
12650
12950
  computeTemplateHash: () => computeTemplateHash,
12651
12951
  consumeExitMarker: () => consumeExitMarker,
12652
12952
  createAttach: () => createAttach,
@@ -12698,6 +12998,7 @@ __export(dist_exports, {
12698
12998
  discoverCaptainSurface: () => discoverCaptainSurface,
12699
12999
  discoverLiveOpencodeServer: () => discoverLiveOpencodeServer,
12700
13000
  dispatchToSibling: () => dispatchToSibling,
13001
+ duplicateIdProblem: () => duplicateIdProblem,
12701
13002
  encodeFrame: () => encodeFrame,
12702
13003
  encodeMsg: () => encodeMsg,
12703
13004
  ensureDaemon: () => ensureDaemon,
@@ -12719,6 +13020,8 @@ __export(dist_exports, {
12719
13020
  formatLifecycle: () => formatLifecycle,
12720
13021
  formatMediaReceipt: () => formatMediaReceipt,
12721
13022
  formatPermissionDecision: () => formatPermissionDecision,
13023
+ formatPromptContext: () => formatPromptContext,
13024
+ formatSessionContext: () => formatSessionContext,
12722
13025
  formatUsageLine: () => formatUsageLine,
12723
13026
  formatWatchdogWarning: () => formatWatchdogWarning,
12724
13027
  freshTrace: () => freshTrace,
@@ -12728,6 +13031,7 @@ __export(dist_exports, {
12728
13031
  hasModalOptionList: () => hasModalOptionList,
12729
13032
  healCmdFor: () => healCmdFor,
12730
13033
  inboundBody: () => inboundBody,
13034
+ injectStateDir: () => injectStateDir,
12731
13035
  isAuthorized: () => isAuthorized,
12732
13036
  isBareSpawn: () => isBareSpawn,
12733
13037
  isCaptainAlive: () => isCaptainAlive,
@@ -12743,6 +13047,7 @@ __export(dist_exports, {
12743
13047
  isReadOnlyTopLevelCommand: () => isReadOnlyTopLevelCommand,
12744
13048
  isSideTitle: () => isSideTitle,
12745
13049
  isStickyAttention: () => isStickyAttention,
13050
+ isSystemPrompt: () => isSystemPrompt,
12746
13051
  isTurnAccepted: () => isTurnAccepted,
12747
13052
  isVersionUpgrade: () => isVersionUpgrade,
12748
13053
  joinUrl: () => joinUrl,
@@ -12788,6 +13093,7 @@ __export(dist_exports, {
12788
13093
  programArgsBlock: () => programArgsBlock,
12789
13094
  projectHealth: () => projectHealth,
12790
13095
  projectRulesDir: () => projectRulesDir,
13096
+ pruneSeenRules: () => pruneSeenRules,
12791
13097
  pruneTopics: () => pruneTopics,
12792
13098
  purgeExpiredWorkItems: () => purgeExpiredWorkItems,
12793
13099
  readCaptainAddress: () => readCaptainAddress,
@@ -12795,11 +13101,13 @@ __export(dist_exports, {
12795
13101
  readFromCursor: () => readFromCursor,
12796
13102
  readIndex: () => readIndex,
12797
13103
  readRunningMarker: () => readRunningMarker,
13104
+ readSeenRules: () => readSeenRules,
12798
13105
  readUserIntent: () => readUserIntent,
12799
13106
  realpathOrSelf: () => realpathOrSelf,
12800
13107
  reapCrewChildren: () => reapCrewChildren,
12801
13108
  reapOrphanedCrews: () => reapOrphanedCrews,
12802
13109
  reconcileLiveness: () => reconcileLiveness,
13110
+ recordSeenRules: () => recordSeenRules,
12803
13111
  recordSession: () => recordSession,
12804
13112
  recoverStall: () => recoverStall,
12805
13113
  reduce: () => reduce,
@@ -12821,6 +13129,7 @@ __export(dist_exports, {
12821
13129
  resolveGateMode: () => resolveGateMode,
12822
13130
  resolveGatePolicy: () => resolveGatePolicy,
12823
13131
  resolveGateTools: () => resolveGateTools,
13132
+ resolveInjectProject: () => resolveInjectProject,
12824
13133
  resolveProject: () => resolveProject,
12825
13134
  resolveProjectRules: () => resolveProjectRules,
12826
13135
  resolveRouterCredentials: () => resolveRouterCredentials,
@@ -12860,6 +13169,7 @@ __export(dist_exports, {
12860
13169
  screenHasSplashMarker: () => screenHasSplashMarker,
12861
13170
  screenHash: () => screenHash,
12862
13171
  searchRules: () => searchRules,
13172
+ selectPromptHits: () => selectPromptHits,
12863
13173
  sendRequest: () => sendRequest,
12864
13174
  setLastUserId: () => setLastUserId,
12865
13175
  setNotify: () => setNotify,
@@ -12885,8 +13195,11 @@ __export(dist_exports, {
12885
13195
  topicName: () => topicName,
12886
13196
  tryAcquireDaemonLock: () => tryAcquireDaemonLock,
12887
13197
  usageFromJson: () => usageFromJson,
13198
+ validateKb: () => validateKb,
12888
13199
  waitForCaptainDelivery: () => waitForCaptainDelivery,
12889
13200
  waitForWarmup: () => waitForWarmup,
13201
+ wholeWordTerms: () => wholeWordTerms,
13202
+ withBudget: () => withBudget,
12890
13203
  writeCaptainAddress: () => writeCaptainAddress,
12891
13204
  writeCursor: () => writeCursor,
12892
13205
  writeExitMarker: () => writeExitMarker,
@@ -12949,6 +13262,20 @@ var init_dist2 = __esm({
12949
13262
  }
12950
13263
  });
12951
13264
 
13265
+ // packages/cli/src/lib/suppress-sqlite-warning.ts
13266
+ function isSqliteExperimentalWarning(warning, type2) {
13267
+ const name = typeof warning === "object" && warning !== null ? warning.name : typeof type2 === "string" ? type2 : void 0;
13268
+ const message = typeof warning === "string" ? warning : warning?.message;
13269
+ return name === "ExperimentalWarning" && typeof message === "string" && /SQLite is an experimental feature/i.test(message);
13270
+ }
13271
+ var original = process.emitWarning.bind(process);
13272
+ process.emitWarning = ((warning, ...rest) => {
13273
+ const first = rest[0];
13274
+ const type2 = typeof first === "string" ? first : first?.type;
13275
+ if (isSqliteExperimentalWarning(warning, type2)) return;
13276
+ original(warning, ...rest);
13277
+ });
13278
+
12952
13279
  // packages/cli/src/squadrantd.ts
12953
13280
  init_dist2();
12954
13281
  init_dist2();
@@ -12975,7 +13302,7 @@ import { readdirSync as readdirSync4, readFileSync as readFileSync12 } from "fs"
12975
13302
  import { join as join18 } from "path";
12976
13303
 
12977
13304
  // packages/agents/dist/claude/registry.js
12978
- import fs19 from "fs";
13305
+ import fs20 from "fs";
12979
13306
  import { join as join17 } from "path";
12980
13307
  import { homedir as homedir7 } from "os";
12981
13308
  var CLAUDE_SESSIONS_DIR = join17(homedir7(), ".claude", "sessions");
@@ -13020,11 +13347,11 @@ function toLifecycleSnapshot(entry, taskId, alive, now) {
13020
13347
  function readClaudeStatusBySocketPath(socketPath) {
13021
13348
  let files;
13022
13349
  try {
13023
- files = fs19.readdirSync(CLAUDE_SESSIONS_DIR);
13350
+ files = fs20.readdirSync(CLAUDE_SESSIONS_DIR);
13024
13351
  } catch {
13025
13352
  return void 0;
13026
13353
  }
13027
- const entries = parseRegistryDir(files, (name) => fs19.readFileSync(join17(CLAUDE_SESSIONS_DIR, name), "utf8"));
13354
+ const entries = parseRegistryDir(files, (name) => fs20.readFileSync(join17(CLAUDE_SESSIONS_DIR, name), "utf8"));
13028
13355
  const entry = entries.find((e) => e.messagingSocketPath === socketPath);
13029
13356
  if (!entry)
13030
13357
  return void 0;
@@ -13047,38 +13374,38 @@ import { homedir as homedir8 } from "os";
13047
13374
  var SQUADRANT_STATE_DIR = join19(homedir8(), ".config", "squadrant", "state");
13048
13375
 
13049
13376
  // packages/agents/dist/drivers/launch-cmd.js
13050
- import fs20 from "fs";
13051
- import path18 from "path";
13377
+ import fs21 from "fs";
13378
+ import path19 from "path";
13052
13379
 
13053
13380
  // packages/agents/dist/projection/cursor.js
13054
13381
  import { mkdir, readFile, writeFile } from "fs/promises";
13055
- import path19 from "path";
13056
- import os7 from "os";
13382
+ import path20 from "path";
13383
+ import os8 from "os";
13057
13384
 
13058
13385
  // packages/agents/dist/projection/codex.js
13059
13386
  import { mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
13060
- import path20 from "path";
13061
- import os8 from "os";
13387
+ import path21 from "path";
13388
+ import os9 from "os";
13062
13389
 
13063
13390
  // packages/agents/dist/projection/gemini.js
13064
13391
  import { mkdir as mkdir3, readFile as readFile3, writeFile as writeFile3 } from "fs/promises";
13065
- import path21 from "path";
13066
- import os9 from "os";
13392
+ import path22 from "path";
13393
+ import os10 from "os";
13067
13394
 
13068
13395
  // packages/agents/dist/projection/opencode.js
13069
13396
  import { mkdir as mkdir4, readFile as readFile4, writeFile as writeFile4 } from "fs/promises";
13070
- import path22 from "path";
13071
- import os10 from "os";
13397
+ import path23 from "path";
13398
+ import os11 from "os";
13072
13399
 
13073
13400
  // packages/agents/dist/projection/opencode-skills.js
13074
- import fs21 from "fs";
13075
- import os11 from "os";
13076
- import path23 from "path";
13401
+ import fs22 from "fs";
13402
+ import os12 from "os";
13403
+ import path24 from "path";
13077
13404
  var OPENCODE_SKILL_MARKER = ".squadrant-managed";
13078
13405
  var MARKER_BODY = "squadrant\n";
13079
13406
  function defaultOpencodeSkillsRoot(env = process.env) {
13080
- const configHome = env.XDG_CONFIG_HOME || path23.join(os11.homedir(), ".config");
13081
- return path23.join(configHome, "opencode", "skills");
13407
+ const configHome = env.XDG_CONFIG_HOME || path24.join(os12.homedir(), ".config");
13408
+ return path24.join(configHome, "opencode", "skills");
13082
13409
  }
13083
13410
  var SAFE_NAME = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
13084
13411
  function parseSkillName(raw) {
@@ -13093,62 +13420,62 @@ function parseSkillName(raw) {
13093
13420
  }
13094
13421
  function listSourceSkills(sourceSkillsDir) {
13095
13422
  const out = /* @__PURE__ */ new Map();
13096
- if (!fs21.existsSync(sourceSkillsDir))
13423
+ if (!fs22.existsSync(sourceSkillsDir))
13097
13424
  return out;
13098
- for (const entry of fs21.readdirSync(sourceSkillsDir, { withFileTypes: true })) {
13425
+ for (const entry of fs22.readdirSync(sourceSkillsDir, { withFileTypes: true })) {
13099
13426
  if (!entry.isDirectory())
13100
13427
  continue;
13101
- const skillPath = path23.join(sourceSkillsDir, entry.name, "SKILL.md");
13102
- if (!fs21.existsSync(skillPath))
13428
+ const skillPath = path24.join(sourceSkillsDir, entry.name, "SKILL.md");
13429
+ if (!fs22.existsSync(skillPath))
13103
13430
  continue;
13104
- const name = parseSkillName(fs21.readFileSync(skillPath, "utf-8"));
13431
+ const name = parseSkillName(fs22.readFileSync(skillPath, "utf-8"));
13105
13432
  if (name && SAFE_NAME.test(name))
13106
13433
  out.set(name, skillPath);
13107
13434
  }
13108
13435
  return out;
13109
13436
  }
13110
13437
  function hasMarker(dir) {
13111
- return fs21.existsSync(path23.join(dir, OPENCODE_SKILL_MARKER));
13438
+ return fs22.existsSync(path24.join(dir, OPENCODE_SKILL_MARKER));
13112
13439
  }
13113
13440
  function syncOpencodeSkills(opts) {
13114
13441
  const result = { written: [], unchanged: [], removed: [], skipped: [] };
13115
13442
  const wanted = listSourceSkills(opts.sourceSkillsDir);
13116
- if (wanted.size === 0 && !fs21.existsSync(opts.sourceSkillsDir))
13443
+ if (wanted.size === 0 && !fs22.existsSync(opts.sourceSkillsDir))
13117
13444
  return result;
13118
13445
  if (!opts.dryRun)
13119
- fs21.mkdirSync(opts.skillsRoot, { recursive: true });
13446
+ fs22.mkdirSync(opts.skillsRoot, { recursive: true });
13120
13447
  for (const [name, srcPath] of wanted) {
13121
- const targetDir = path23.join(opts.skillsRoot, name);
13122
- const targetSkill = path23.join(targetDir, "SKILL.md");
13448
+ const targetDir = path24.join(opts.skillsRoot, name);
13449
+ const targetSkill = path24.join(targetDir, "SKILL.md");
13123
13450
  const managed = hasMarker(targetDir);
13124
- if (fs21.existsSync(targetSkill) && !managed) {
13451
+ if (fs22.existsSync(targetSkill) && !managed) {
13125
13452
  result.skipped.push({ name, reason: "foreign-collision" });
13126
13453
  continue;
13127
13454
  }
13128
- const current = fs21.existsSync(targetSkill) ? fs21.readFileSync(targetSkill) : null;
13129
- if (current && current.equals(fs21.readFileSync(srcPath))) {
13455
+ const current = fs22.existsSync(targetSkill) ? fs22.readFileSync(targetSkill) : null;
13456
+ if (current && current.equals(fs22.readFileSync(srcPath))) {
13130
13457
  if (!managed && !opts.dryRun) {
13131
- fs21.writeFileSync(path23.join(targetDir, OPENCODE_SKILL_MARKER), MARKER_BODY);
13458
+ fs22.writeFileSync(path24.join(targetDir, OPENCODE_SKILL_MARKER), MARKER_BODY);
13132
13459
  }
13133
13460
  result.unchanged.push(name);
13134
13461
  continue;
13135
13462
  }
13136
13463
  if (!opts.dryRun) {
13137
- fs21.mkdirSync(targetDir, { recursive: true });
13138
- fs21.copyFileSync(srcPath, targetSkill);
13139
- fs21.writeFileSync(path23.join(targetDir, OPENCODE_SKILL_MARKER), MARKER_BODY);
13464
+ fs22.mkdirSync(targetDir, { recursive: true });
13465
+ fs22.copyFileSync(srcPath, targetSkill);
13466
+ fs22.writeFileSync(path24.join(targetDir, OPENCODE_SKILL_MARKER), MARKER_BODY);
13140
13467
  }
13141
13468
  result.written.push(name);
13142
13469
  }
13143
- if (fs21.existsSync(opts.skillsRoot)) {
13144
- for (const entry of fs21.readdirSync(opts.skillsRoot, { withFileTypes: true })) {
13470
+ if (fs22.existsSync(opts.skillsRoot)) {
13471
+ for (const entry of fs22.readdirSync(opts.skillsRoot, { withFileTypes: true })) {
13145
13472
  if (!entry.isDirectory() || wanted.has(entry.name))
13146
13473
  continue;
13147
- const dir = path23.join(opts.skillsRoot, entry.name);
13474
+ const dir = path24.join(opts.skillsRoot, entry.name);
13148
13475
  if (!hasMarker(dir))
13149
13476
  continue;
13150
13477
  if (!opts.dryRun)
13151
- fs21.rmSync(dir, { recursive: true, force: true });
13478
+ fs22.rmSync(dir, { recursive: true, force: true });
13152
13479
  result.removed.push(entry.name);
13153
13480
  }
13154
13481
  }
@@ -13156,7 +13483,7 @@ function syncOpencodeSkills(opts) {
13156
13483
  }
13157
13484
  function syncShippedOpencodeSkills(opts) {
13158
13485
  return syncOpencodeSkills({
13159
- sourceSkillsDir: path23.join(opts.pkgRoot, "plugin", "skills"),
13486
+ sourceSkillsDir: path24.join(opts.pkgRoot, "plugin", "skills"),
13160
13487
  skillsRoot: opts.skillsRoot ?? defaultOpencodeSkillsRoot(),
13161
13488
  dryRun: opts.dryRun
13162
13489
  });
@@ -13164,8 +13491,8 @@ function syncShippedOpencodeSkills(opts) {
13164
13491
 
13165
13492
  // packages/agents/dist/projection/claude.js
13166
13493
  import { mkdir as mkdir5, readFile as readFile5, writeFile as writeFile5 } from "fs/promises";
13167
- import path24 from "path";
13168
- import os12 from "os";
13494
+ import path25 from "path";
13495
+ import os13 from "os";
13169
13496
 
13170
13497
  // packages/agents/dist/codex/app-server-client.js
13171
13498
  import { EventEmitter } from "events";
@@ -13175,12 +13502,12 @@ function _parseChunk(acc, chunk) {
13175
13502
  const out = [];
13176
13503
  let idx;
13177
13504
  while ((idx = acc.buf.indexOf("\n")) >= 0) {
13178
- const line = acc.buf.slice(0, idx);
13505
+ const line2 = acc.buf.slice(0, idx);
13179
13506
  acc.buf = acc.buf.slice(idx + 1);
13180
- if (!line.trim())
13507
+ if (!line2.trim())
13181
13508
  continue;
13182
13509
  try {
13183
- out.push(JSON.parse(line));
13510
+ out.push(JSON.parse(line2));
13184
13511
  } catch {
13185
13512
  }
13186
13513
  }
@@ -13902,9 +14229,9 @@ var OpencodeSseBridge = class {
13902
14229
  buf += decoder.decode(value, { stream: true });
13903
14230
  let nl;
13904
14231
  while ((nl = buf.indexOf("\n")) >= 0) {
13905
- const line = buf.slice(0, nl);
14232
+ const line2 = buf.slice(0, nl);
13906
14233
  buf = buf.slice(nl + 1);
13907
- this.handleLine(taskId, line);
14234
+ this.handleLine(taskId, line2);
13908
14235
  }
13909
14236
  }
13910
14237
  } finally {
@@ -13915,16 +14242,16 @@ var OpencodeSseBridge = class {
13915
14242
  }
13916
14243
  }
13917
14244
  handleLine(taskId, rawLine) {
13918
- let line = rawLine.trim();
13919
- if (!line)
14245
+ let line2 = rawLine.trim();
14246
+ if (!line2)
13920
14247
  return;
13921
- if (line.startsWith("data:"))
13922
- line = line.slice(5).trim();
13923
- if (!line.startsWith("{"))
14248
+ if (line2.startsWith("data:"))
14249
+ line2 = line2.slice(5).trim();
14250
+ if (!line2.startsWith("{"))
13924
14251
  return;
13925
14252
  let json2;
13926
14253
  try {
13927
- json2 = JSON.parse(line);
14254
+ json2 = JSON.parse(line2);
13928
14255
  } catch {
13929
14256
  return;
13930
14257
  }
@@ -14282,13 +14609,13 @@ function buildUserEnvelope(opts) {
14282
14609
  };
14283
14610
  }
14284
14611
  function writeLine(socketPath, envelope, deps) {
14285
- const line = `${JSON.stringify(envelope)}
14612
+ const line2 = `${JSON.stringify(envelope)}
14286
14613
  `;
14287
- if (Buffer.byteLength(line, "utf8") > MAX_LINE_BYTES) {
14614
+ if (Buffer.byteLength(line2, "utf8") > MAX_LINE_BYTES) {
14288
14615
  return Promise.resolve({
14289
14616
  ok: false,
14290
14617
  reason: "transport",
14291
- error: `line exceeds the receiver's 1 MiB buffer cap (${Buffer.byteLength(line, "utf8")} bytes)`
14618
+ error: `line exceeds the receiver's 1 MiB buffer cap (${Buffer.byteLength(line2, "utf8")} bytes)`
14292
14619
  });
14293
14620
  }
14294
14621
  return new Promise((resolve4) => {
@@ -14308,7 +14635,7 @@ function writeLine(socketPath, envelope, deps) {
14308
14635
  done({ ok: false, reason: "transport", error: `timeout after ${deps.timeoutMs ?? DEFAULT_TIMEOUT_MS}ms` });
14309
14636
  }, deps.timeoutMs ?? DEFAULT_TIMEOUT_MS);
14310
14637
  sock.on("connect", () => {
14311
- sock.write(line, () => {
14638
+ sock.write(line2, () => {
14312
14639
  clearTimeout(timer);
14313
14640
  try {
14314
14641
  sock.end();
@@ -14469,20 +14796,20 @@ var ClaudeReceiptListener = class {
14469
14796
  buf += chunk;
14470
14797
  let nl;
14471
14798
  while ((nl = buf.indexOf("\n")) !== -1) {
14472
- const line = buf.slice(0, nl);
14799
+ const line2 = buf.slice(0, nl);
14473
14800
  buf = buf.slice(nl + 1);
14474
- this.dispatch(line);
14801
+ this.dispatch(line2);
14475
14802
  }
14476
14803
  });
14477
14804
  conn.on("error", () => {
14478
14805
  });
14479
14806
  }
14480
- dispatch(line) {
14481
- if (!line.trim())
14807
+ dispatch(line2) {
14808
+ if (!line2.trim())
14482
14809
  return;
14483
14810
  let f;
14484
14811
  try {
14485
- f = JSON.parse(line);
14812
+ f = JSON.parse(line2);
14486
14813
  } catch {
14487
14814
  this.deps.log?.(`claude-receipt: discarded non-JSON frame`);
14488
14815
  return;
@@ -14509,9 +14836,9 @@ var ClaudeReceiptListener = class {
14509
14836
  };
14510
14837
 
14511
14838
  // packages/agents/dist/claude/api-key-approval.js
14512
- import fs22 from "fs";
14513
- import os13 from "os";
14514
- import path25 from "path";
14839
+ import fs23 from "fs";
14840
+ import os14 from "os";
14841
+ import path26 from "path";
14515
14842
 
14516
14843
  // packages/agents/dist/opencode/http-channel.js
14517
14844
  init_dist2();
@@ -14603,10 +14930,10 @@ var OpencodeHttpChannel = class {
14603
14930
  return cached;
14604
14931
  const directory = this.directoryFor?.(taskId);
14605
14932
  const createdAfterMs = this.createdAfterFor?.(taskId);
14606
- for (const path28 of ["/session?", "/api/session?"]) {
14933
+ for (const path29 of ["/session?", "/api/session?"]) {
14607
14934
  let res;
14608
14935
  try {
14609
- res = await this.request(`http://127.0.0.1:${port}${path28}`, { method: "GET" });
14936
+ res = await this.request(`http://127.0.0.1:${port}${path29}`, { method: "GET" });
14610
14937
  } catch {
14611
14938
  return void 0;
14612
14939
  }
@@ -14784,13 +15111,13 @@ function parseDraftFromScreen(screen) {
14784
15111
  if (topHR === -1)
14785
15112
  return null;
14786
15113
  const inputLines = lines.slice(topHR + 1, bottomHR);
14787
- for (const line of inputLines) {
15114
+ for (const line2 of inputLines) {
14788
15115
  let extracted;
14789
- const boxMatch = line.match(/│\s*[>❯]\s+(.*?)\s*│/);
15116
+ const boxMatch = line2.match(/│\s*[>❯]\s+(.*?)\s*│/);
14790
15117
  if (boxMatch) {
14791
15118
  extracted = boxMatch[1].trim();
14792
15119
  } else {
14793
- const plainMatch = line.match(/^\s*[>❯]\s*(.*)$/);
15120
+ const plainMatch = line2.match(/^\s*[>❯]\s*(.*)$/);
14794
15121
  if (plainMatch)
14795
15122
  extracted = plainMatch[1].trim();
14796
15123
  }
@@ -14868,8 +15195,8 @@ function readInputBoxRaw(screen, opts) {
14868
15195
  if (topHR === -1)
14869
15196
  return null;
14870
15197
  const parts = [];
14871
- for (const line of lines.slice(topHR + 1, bottomHR)) {
14872
- let s = line.replace(/│/g, " ");
15198
+ for (const line2 of lines.slice(topHR + 1, bottomHR)) {
15199
+ let s = line2.replace(/│/g, " ");
14873
15200
  s = s.replace(/^\s*[>❯]\s?/, "");
14874
15201
  s = s.replace(/\s*[▌█▔▎▏]+\s*$/, "");
14875
15202
  parts.push(s);
@@ -15342,9 +15669,9 @@ var NotifierRegistry = class {
15342
15669
  };
15343
15670
 
15344
15671
  // packages/workspaces/dist/workspaces/obsidian.js
15345
- import fs23 from "fs/promises";
15672
+ import fs24 from "fs/promises";
15346
15673
  import { existsSync as existsSync11 } from "fs";
15347
- import path26 from "path";
15674
+ import path27 from "path";
15348
15675
 
15349
15676
  // packages/workspaces/dist/workspaces/registry.js
15350
15677
  init_dist();
@@ -15442,18 +15769,18 @@ var CmuxEventsBridge = class {
15442
15769
  this.buf += typeof chunk === "string" ? chunk : chunk.toString("utf-8");
15443
15770
  let nl;
15444
15771
  while ((nl = this.buf.indexOf("\n")) >= 0) {
15445
- const line = this.buf.slice(0, nl);
15772
+ const line2 = this.buf.slice(0, nl);
15446
15773
  this.buf = this.buf.slice(nl + 1);
15447
- this.handleLine(line);
15774
+ this.handleLine(line2);
15448
15775
  }
15449
15776
  }
15450
15777
  handleLine(rawLine) {
15451
- const line = rawLine.trim();
15452
- if (!line || line[0] !== "{")
15778
+ const line2 = rawLine.trim();
15779
+ if (!line2 || line2[0] !== "{")
15453
15780
  return;
15454
15781
  let f;
15455
15782
  try {
15456
- f = JSON.parse(line);
15783
+ f = JSON.parse(line2);
15457
15784
  } catch {
15458
15785
  return;
15459
15786
  }
@@ -15894,9 +16221,9 @@ function defaultListFiles(dir) {
15894
16221
  return [];
15895
16222
  }
15896
16223
  }
15897
- function defaultReadFile(path28) {
16224
+ function defaultReadFile(path29) {
15898
16225
  try {
15899
- return readFileSync17(path28, "utf-8");
16226
+ return readFileSync17(path29, "utf-8");
15900
16227
  } catch {
15901
16228
  return void 0;
15902
16229
  }
@@ -16274,16 +16601,16 @@ function extractDetail(sub, payload) {
16274
16601
  }
16275
16602
  return void 0;
16276
16603
  }
16277
- function defaultReadFile2(path28) {
16604
+ function defaultReadFile2(path29) {
16278
16605
  try {
16279
- return readFileSync18(path28, "utf-8");
16606
+ return readFileSync18(path29, "utf-8");
16280
16607
  } catch {
16281
16608
  return void 0;
16282
16609
  }
16283
16610
  }
16284
- function defaultWriteFile(path28, content) {
16285
- mkdirSync8(path28.replace(/\/[^/]+$/, ""), { recursive: true });
16286
- writeFileSync11(path28, content, "utf-8");
16611
+ function defaultWriteFile(path29, content) {
16612
+ mkdirSync8(path29.replace(/\/[^/]+$/, ""), { recursive: true });
16613
+ writeFileSync11(path29, content, "utf-8");
16287
16614
  }
16288
16615
 
16289
16616
  // packages/workspaces/dist/crew-pane.js
@@ -16363,9 +16690,9 @@ init_dist();
16363
16690
 
16364
16691
  // packages/cli/src/lib/daemon-restart-broadcast.ts
16365
16692
  init_dist();
16366
- import path27 from "path";
16693
+ import path28 from "path";
16367
16694
  function statePath2(stateRoot) {
16368
- return path27.join(stateRoot, "daemon-restart-state.json");
16695
+ return path28.join(stateRoot, "daemon-restart-state.json");
16369
16696
  }
16370
16697
  function computeRestartSignature(version, buildMtimeMs) {
16371
16698
  return `${version}::${buildMtimeMs}`;
@@ -16414,7 +16741,7 @@ async function maybeBroadcastDaemonRestart(opts) {
16414
16741
 
16415
16742
  // packages/cli/src/lib/captain-channel-factory.ts
16416
16743
  import { createServer as createServer4, connect as netConnect } from "net";
16417
- import fs24 from "fs";
16744
+ import fs25 from "fs";
16418
16745
  import { join as join26 } from "path";
16419
16746
  import { randomUUID as randomUUID5 } from "crypto";
16420
16747
  import chalk2 from "chalk";
@@ -16423,15 +16750,15 @@ var shared;
16423
16750
  var registryEntryPath = () => join26(CLAUDE_SESSIONS_DIR, `${process.pid}.json`);
16424
16751
  function unregisterSenderIdentity() {
16425
16752
  try {
16426
- fs24.unlinkSync(registryEntryPath());
16753
+ fs25.unlinkSync(registryEntryPath());
16427
16754
  } catch {
16428
16755
  }
16429
16756
  }
16430
16757
  function registerSenderIdentity(socketPath) {
16431
16758
  try {
16432
16759
  unregisterSenderIdentity();
16433
- fs24.mkdirSync(CLAUDE_SESSIONS_DIR, { recursive: true });
16434
- fs24.writeFileSync(
16760
+ fs25.mkdirSync(CLAUDE_SESSIONS_DIR, { recursive: true });
16761
+ fs25.writeFileSync(
16435
16762
  registryEntryPath(),
16436
16763
  JSON.stringify({
16437
16764
  pid: process.pid,
@@ -16457,7 +16784,7 @@ async function sharedReceiptListener() {
16457
16784
  // must never be the reason we refuse to start.
16458
16785
  unlinkStale: (p) => {
16459
16786
  try {
16460
- fs24.unlinkSync(p);
16787
+ fs25.unlinkSync(p);
16461
16788
  } catch {
16462
16789
  }
16463
16790
  },
@@ -16482,7 +16809,7 @@ async function buildCaptainChannel() {
16482
16809
  // in /tmp/x registers cwd "/private/tmp/x" on macOS, so cwd matching silently
16483
16810
  // missed and every captain ping reported accepted-unconfirmed.
16484
16811
  statusFor: (taskId) => readClaudeStatusBySocketPath(captainSocketPath(taskId)),
16485
- wire: (p, e) => writeLine(p, e, { connect: (path28) => netConnect(path28) }),
16812
+ wire: (p, e) => writeLine(p, e, { connect: (path29) => netConnect(path29) }),
16486
16813
  receipts,
16487
16814
  newMsgId: () => randomUUID5(),
16488
16815
  sleep: (ms) => new Promise((r) => setTimeout(r, ms)),