squadrant 0.26.1 → 0.26.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -594,22 +594,22 @@ function defaultCmuxConfigPath() {
594
594
  return join(homedir(), ".config", "cmux", "cmux.json");
595
595
  }
596
596
  function ensureSocketAutomation(opts = {}) {
597
- const path45 = opts.path ?? defaultCmuxConfigPath();
598
- if (!existsSync(path45)) {
599
- mkdirSync(dirname(path45), { recursive: true });
600
- writeFileSync(path45, MINIMAL_TEMPLATE);
601
- return { path: path45, changed: true, alreadySet: false };
597
+ const path46 = opts.path ?? defaultCmuxConfigPath();
598
+ if (!existsSync(path46)) {
599
+ mkdirSync(dirname(path46), { recursive: true });
600
+ writeFileSync(path46, MINIMAL_TEMPLATE);
601
+ return { path: path46, changed: true, alreadySet: false };
602
602
  }
603
- const text = readFileSync(path45, "utf-8");
603
+ const text = readFileSync(path46, "utf-8");
604
604
  const current = parse(text)?.automation?.socketControlMode;
605
605
  if (current === AUTOMATION_MODE) {
606
- return { path: path45, changed: false, alreadySet: true };
606
+ return { path: path46, changed: false, alreadySet: true };
607
607
  }
608
608
  const edits = modify(text, [...SOCKET_CONTROL_MODE_PATH], AUTOMATION_MODE, {
609
609
  formattingOptions: { insertSpaces: true, tabSize: 2 }
610
610
  });
611
- writeFileSync(path45, applyEdits(text, edits));
612
- return { path: path45, changed: true, alreadySet: false };
611
+ writeFileSync(path46, applyEdits(text, edits));
612
+ return { path: path46, changed: true, alreadySet: false };
613
613
  }
614
614
  var SOCKET_CONTROL_MODE_PATH, AUTOMATION_MODE, MINIMAL_TEMPLATE;
615
615
  var init_cmux_config = __esm({
@@ -762,9 +762,9 @@ import { join as join4 } from "path";
762
762
  function defaultStatePath() {
763
763
  return join4(homedir3(), ".config", "squadrant", "state", "cmux-autoconfig.json");
764
764
  }
765
- function readState(path45) {
765
+ function readState(path46) {
766
766
  try {
767
- return JSON.parse(readConfigFileSync(path45));
767
+ return JSON.parse(readConfigFileSync(path46));
768
768
  } catch {
769
769
  return {};
770
770
  }
@@ -925,18 +925,18 @@ function detectDrift(user, def) {
925
925
  }
926
926
  }
927
927
  }
928
- const checkBackend = (path45, backend, agentName) => {
928
+ const checkBackend = (path46, backend, agentName) => {
929
929
  if (backend === void 0)
930
930
  return;
931
931
  if (!isBackendMode(backend)) {
932
- items.push({ path: path45, kind: "invalid", severity: "warn", current: backend, note: "unknown backend; expected native|direct|proxy" });
932
+ items.push({ path: path46, kind: "invalid", severity: "warn", current: backend, note: "unknown backend; expected native|direct|proxy" });
933
933
  return;
934
934
  }
935
935
  if (backend !== "native") {
936
936
  if (agentName !== "claude") {
937
- items.push({ path: path45, kind: "invalid", severity: "warn", current: backend, note: `backend '${backend}' is claude-only (agent '${agentName ?? "?"}')` });
937
+ items.push({ path: path46, kind: "invalid", severity: "warn", current: backend, note: `backend '${backend}' is claude-only (agent '${agentName ?? "?"}')` });
938
938
  } else if (!router) {
939
- items.push({ path: path45, kind: "invalid", severity: "warn", current: backend, note: `backend '${backend}' requires defaults.router` });
939
+ items.push({ path: path46, kind: "invalid", severity: "warn", current: backend, note: `backend '${backend}' requires defaults.router` });
940
940
  }
941
941
  }
942
942
  };
@@ -1124,8 +1124,8 @@ async function notifyIfUpdateAvailable(opts) {
1124
1124
  const statePath2 = opts.statePath ?? UPDATE_CHECK_STATE_PATH;
1125
1125
  const readState2 = opts.readState ?? readUpdateCheckState;
1126
1126
  const writeState = opts.writeState ?? writeUpdateCheckState;
1127
- const write = opts.write ?? ((line) => process.stderr.write(`
1128
- ${line}
1127
+ const write = opts.write ?? ((line2) => process.stderr.write(`
1128
+ ${line2}
1129
1129
  `));
1130
1130
  const outcome = await checkForUpdate({
1131
1131
  currentVersion: opts.currentVersion,
@@ -1480,8 +1480,8 @@ function parseSkill(raw) {
1480
1480
  return null;
1481
1481
  const [, fmBlock, body] = match;
1482
1482
  const fm = {};
1483
- for (const line of fmBlock.split("\n")) {
1484
- const kv = line.match(/^(\w+):\s*(.+)$/);
1483
+ for (const line2 of fmBlock.split("\n")) {
1484
+ const kv = line2.match(/^(\w+):\s*(.+)$/);
1485
1485
  if (kv)
1486
1486
  fm[kv[1]] = kv[2].trim();
1487
1487
  }
@@ -1595,8 +1595,8 @@ async function readDailyLog(workspace, dateStr) {
1595
1595
  const blockerMatch = content.match(/## Blocked\n([\s\S]*?)(?=\n##|$)/);
1596
1596
  if (blockerMatch) {
1597
1597
  const lines = blockerMatch[1].trim().split("\n");
1598
- for (const line of lines) {
1599
- const trimmed = line.replace(/^[-*]\s*/, "").trim();
1598
+ for (const line2 of lines) {
1599
+ const trimmed = line2.replace(/^[-*]\s*/, "").trim();
1600
1600
  if (trimmed && trimmed !== "(none)" && trimmed !== "None") {
1601
1601
  blockers.push(trimmed);
1602
1602
  }
@@ -2702,12 +2702,12 @@ async function* readFromCursor(opts) {
2702
2702
  continue;
2703
2703
  throw e;
2704
2704
  }
2705
- for (const line of buf.split("\n")) {
2706
- if (!line.trim())
2705
+ for (const line2 of buf.split("\n")) {
2706
+ if (!line2.trim())
2707
2707
  continue;
2708
2708
  let entry;
2709
2709
  try {
2710
- entry = JSON.parse(line);
2710
+ entry = JSON.parse(line2);
2711
2711
  } catch {
2712
2712
  continue;
2713
2713
  }
@@ -2809,17 +2809,17 @@ function createDecoder(onParseError) {
2809
2809
  const out = [];
2810
2810
  let idx;
2811
2811
  while ((idx = buf.indexOf("\n")) >= 0) {
2812
- const line = buf.slice(0, idx);
2812
+ const line2 = buf.slice(0, idx);
2813
2813
  buf = buf.slice(idx + 1);
2814
- if (!line.trim())
2814
+ if (!line2.trim())
2815
2815
  continue;
2816
2816
  try {
2817
- const parsed = JSON.parse(line);
2817
+ const parsed = JSON.parse(line2);
2818
2818
  if (typeof parsed === "object" && parsed !== null && parsed.type === "_keepalive")
2819
2819
  continue;
2820
2820
  out.push(parsed);
2821
2821
  } catch {
2822
- onParseError?.(line);
2822
+ onParseError?.(line2);
2823
2823
  }
2824
2824
  }
2825
2825
  return out;
@@ -2979,11 +2979,11 @@ function encodeFrame(f) {
2979
2979
  }
2980
2980
  function decodeFrames(wire) {
2981
2981
  const out = [];
2982
- for (const line of wire.split("\n")) {
2983
- if (!line.trim())
2982
+ for (const line2 of wire.split("\n")) {
2983
+ if (!line2.trim())
2984
2984
  continue;
2985
2985
  try {
2986
- const parsed = JSON.parse(line);
2986
+ const parsed = JSON.parse(line2);
2987
2987
  if (parsed.type === "_keepalive")
2988
2988
  continue;
2989
2989
  out.push(parsed);
@@ -3465,10 +3465,10 @@ function detectForeignInstall(parsed, thisEntry, registeredEntryExists) {
3465
3465
  isUpgrade: isVersionUpgrade(parsed.daemonEntry, thisEntry)
3466
3466
  };
3467
3467
  }
3468
- function sanitizePathForPlist(path45) {
3468
+ function sanitizePathForPlist(path46) {
3469
3469
  const seen = /* @__PURE__ */ new Set();
3470
3470
  const stable = [];
3471
- for (const p of path45.split(":")) {
3471
+ for (const p of path46.split(":")) {
3472
3472
  if (!p)
3473
3473
  continue;
3474
3474
  if (p.includes("/.claude/plugins/"))
@@ -4171,14 +4171,14 @@ function detectTrailingQuestion(text) {
4171
4171
  let inFence = false;
4172
4172
  let lastLine = null;
4173
4173
  for (const raw of text.split(/\r?\n/)) {
4174
- const line = raw.trim();
4175
- if (line.startsWith("```")) {
4174
+ const line2 = raw.trim();
4175
+ if (line2.startsWith("```")) {
4176
4176
  inFence = !inFence;
4177
4177
  continue;
4178
4178
  }
4179
- if (inFence || line === "")
4179
+ if (inFence || line2 === "")
4180
4180
  continue;
4181
- lastLine = line;
4181
+ lastLine = line2;
4182
4182
  }
4183
4183
  if (lastLine && lastLine.endsWith("?"))
4184
4184
  return lastLine;
@@ -4189,9 +4189,9 @@ function isQuotedLine(raw) {
4189
4189
  return QUOTED_PREFIX_RE.test(noAnsi);
4190
4190
  }
4191
4191
  function stripChrome(raw) {
4192
- let line = raw.replace(/\[[0-9;]*m/g, "");
4193
- line = line.replace(/^[\s│┃▏▕|]+/, "").replace(/[\s│┃▏▕|]+$/, "");
4194
- const trimmed = line.trim();
4192
+ let line2 = raw.replace(/\[[0-9;]*m/g, "");
4193
+ line2 = line2.replace(/^[\s│┃▏▕|]+/, "").replace(/[\s│┃▏▕|]+$/, "");
4194
+ const trimmed = line2.trim();
4195
4195
  if (trimmed === "")
4196
4196
  return null;
4197
4197
  if (PURE_CHROME_RE.test(trimmed))
@@ -4852,12 +4852,12 @@ function extractUserIntentFromTranscript(jsonl) {
4852
4852
  return null;
4853
4853
  const lines = jsonl.split(/\r?\n/);
4854
4854
  for (let i = lines.length - 1; i >= 0; i--) {
4855
- const line = lines[i].trim();
4856
- if (!line)
4855
+ const line2 = lines[i].trim();
4856
+ if (!line2)
4857
4857
  continue;
4858
4858
  let entry;
4859
4859
  try {
4860
- entry = JSON.parse(line);
4860
+ entry = JSON.parse(line2);
4861
4861
  } catch {
4862
4862
  continue;
4863
4863
  }
@@ -5306,10 +5306,10 @@ async function reapCrewChildren(taskId, graceMs = 2e3, execFn = nodeExec) {
5306
5306
  execFn("ps auxE", { maxBuffer: 64 * 1024 * 1024 }, (err, out) => err ? reject(err) : resolve4(out));
5307
5307
  });
5308
5308
  const pids = [];
5309
- for (const line of stdout.split("\n").slice(1)) {
5310
- if (!line.includes(marker))
5309
+ for (const line2 of stdout.split("\n").slice(1)) {
5310
+ if (!line2.includes(marker))
5311
5311
  continue;
5312
- const pid = parseInt(line.trim().split(/\s+/)[1], 10);
5312
+ const pid = parseInt(line2.trim().split(/\s+/)[1], 10);
5313
5313
  if (!isNaN(pid) && pid !== process.pid)
5314
5314
  pids.push(pid);
5315
5315
  }
@@ -5590,9 +5590,13 @@ async function runCrewSpawn(input, config, deps) {
5590
5590
  await deps.runtime.sendToPane(pane2, `cd ${shellQuote(spawnCwd)} && ${envPrefix}${routerPrefix} ${niceCrewCommand(cliCommand2)}`);
5591
5591
  const preLaunchScreen = await deps.runtime.readPaneScreen(pane2) ?? "";
5592
5592
  const claudeFirstTurn = spillOversizedFirstTurn(firstTurnTask, rec.id);
5593
- const sendPromise = deps.sendFirstTurn(pane2, `${claudeFirstTurn}
5593
+ const peerBrief = `${firstTurnTask}
5594
5594
 
5595
- ${buildCompletionProtocol(rec.id, input.project)}`, preLaunchScreen);
5595
+ ${buildCompletionProtocol(rec.id, input.project)}`;
5596
+ const peerResult = deps.sendFirstTurnPeer ? await deps.sendFirstTurnPeer({ pane: pane2, taskId: rec.id, project: input.project, messagingSocketPath, message: peerBrief }).catch(() => ({ kind: "fallback" })) : { kind: "fallback" };
5597
+ const sendPromise = peerResult.kind === "fallback" ? deps.sendFirstTurn(pane2, `${claudeFirstTurn}
5598
+
5599
+ ${buildCompletionProtocol(rec.id, input.project)}`, preLaunchScreen) : Promise.resolve({ delivered: peerResult.kind === "delivered" });
5596
5600
  let agentNotStarted = false;
5597
5601
  const scrapeDelivered = sendPromise.then((r) => {
5598
5602
  agentNotStarted = !!r.agentNotStarted;
@@ -6004,11 +6008,11 @@ var init_captain_record = __esm({
6004
6008
  // packages/core/dist/opencode-session.js
6005
6009
  import { execFileSync as execFileSync4 } from "child_process";
6006
6010
  async function listSessions(port, fetchImpl = fetch, timeoutMs = 5e3) {
6007
- for (const path45 of ["/session", "/api/session"]) {
6011
+ for (const path46 of ["/session", "/api/session"]) {
6008
6012
  const ac = new AbortController();
6009
6013
  const t = setTimeout(() => ac.abort(), timeoutMs);
6010
6014
  try {
6011
- const res = await fetchImpl(`http://127.0.0.1:${port}${path45}`, { signal: ac.signal });
6015
+ const res = await fetchImpl(`http://127.0.0.1:${port}${path46}`, { signal: ac.signal });
6012
6016
  if (!res.ok)
6013
6017
  continue;
6014
6018
  const rows = await res.json();
@@ -6023,8 +6027,8 @@ async function listSessions(port, fetchImpl = fetch, timeoutMs = 5e3) {
6023
6027
  }
6024
6028
  function parseLiveOpencodeServers(psOutput) {
6025
6029
  const out = [];
6026
- for (const line of psOutput.split("\n")) {
6027
- const m = line.match(/^\s*(\d+)\s+(.+)$/);
6030
+ for (const line2 of psOutput.split("\n")) {
6031
+ const m = line2.match(/^\s*(\d+)\s+(.+)$/);
6028
6032
  if (!m)
6029
6033
  continue;
6030
6034
  const pid = Number(m[1]);
@@ -6050,8 +6054,8 @@ function defaultPsOutput() {
6050
6054
  function defaultCwdOf(pid) {
6051
6055
  try {
6052
6056
  const out = execFileSync4("lsof", ["-a", "-p", String(pid), "-d", "cwd", "-Fn"], { encoding: "utf-8", timeout: 2e3 });
6053
- const line = out.split("\n").find((l) => l.startsWith("n"));
6054
- return line ? line.slice(1) : null;
6057
+ const line2 = out.split("\n").find((l) => l.startsWith("n"));
6058
+ return line2 ? line2.slice(1) : null;
6055
6059
  } catch {
6056
6060
  return null;
6057
6061
  }
@@ -6701,10 +6705,10 @@ function distBuiltAt() {
6701
6705
  return 0;
6702
6706
  }
6703
6707
  }
6704
- function gatherLogStats(path45, now, windowMs) {
6708
+ function gatherLogStats(path46, now, windowMs) {
6705
6709
  let sizeBytes = 0;
6706
6710
  try {
6707
- sizeBytes = statSync3(path45).size;
6711
+ sizeBytes = statSync3(path46).size;
6708
6712
  } catch {
6709
6713
  return { errorCount: 0, sizeBytes: 0, windowMs };
6710
6714
  }
@@ -6715,7 +6719,7 @@ function gatherLogStats(path45, now, windowMs) {
6715
6719
  const len = sizeBytes - start;
6716
6720
  let text = "";
6717
6721
  try {
6718
- const fd = openSync2(path45, "r");
6722
+ const fd = openSync2(path46, "r");
6719
6723
  try {
6720
6724
  const buf = Buffer.alloc(len);
6721
6725
  readSync(fd, buf, 0, len, start);
@@ -6728,10 +6732,10 @@ function gatherLogStats(path45, now, windowMs) {
6728
6732
  }
6729
6733
  const cutoff = now - windowMs;
6730
6734
  let errorCount = 0;
6731
- for (const line of text.split("\n")) {
6732
- if (!/error|failed/i.test(line))
6735
+ for (const line2 of text.split("\n")) {
6736
+ if (!/error|failed/i.test(line2))
6733
6737
  continue;
6734
- const m = line.match(/\d{4}-\d{2}-\d{2}T[\d:.]+Z/);
6738
+ const m = line2.match(/\d{4}-\d{2}-\d{2}T[\d:.]+Z/);
6735
6739
  if (m) {
6736
6740
  const ts = Date.parse(m[0]);
6737
6741
  if (!Number.isNaN(ts) && ts < cutoff)
@@ -8906,10 +8910,10 @@ function scan(bufRef, acc) {
8906
8910
  let saw = false;
8907
8911
  let idx;
8908
8912
  while ((idx = bufRef.value.indexOf("\n")) !== -1) {
8909
- const line = bufRef.value.slice(0, idx).trim();
8913
+ const line2 = bufRef.value.slice(0, idx).trim();
8910
8914
  bufRef.value = bufRef.value.slice(idx + 1);
8911
- if (line.startsWith("data:")) {
8912
- const payload = line.slice(5).trim();
8915
+ if (line2.startsWith("data:")) {
8916
+ const payload = line2.slice(5).trim();
8913
8917
  if (payload && payload !== "[DONE]") {
8914
8918
  try {
8915
8919
  if (absorb(JSON.parse(payload), acc))
@@ -8960,8 +8964,8 @@ var init_stream = __esm({
8960
8964
  // packages/core/dist/router/shim.js
8961
8965
  import { createServer as createServer3 } from "http";
8962
8966
  import { Readable } from "stream";
8963
- function joinUrl(base, path45) {
8964
- return base.replace(/\/+$/, "") + path45;
8967
+ function joinUrl(base, path46) {
8968
+ return base.replace(/\/+$/, "") + path46;
8965
8969
  }
8966
8970
  async function readBody(req) {
8967
8971
  const chunks = [];
@@ -9137,8 +9141,8 @@ function createRouterShim(opts) {
9137
9141
  writeJson(res, 200, { input_tokens: Math.max(1, Math.ceil(text.length / 4)) });
9138
9142
  }
9139
9143
  function handler(req, res) {
9140
- const path45 = pathnameOf(req.url);
9141
- if (req.method === "POST" && path45 === "/v1/messages") {
9144
+ const path46 = pathnameOf(req.url);
9145
+ if (req.method === "POST" && path46 === "/v1/messages") {
9142
9146
  void handleMessages(req, res).catch((err) => {
9143
9147
  log(`router internal error: ${err instanceof Error ? err.message : String(err)}`);
9144
9148
  if (!res.headersSent) {
@@ -9150,18 +9154,18 @@ function createRouterShim(opts) {
9150
9154
  });
9151
9155
  return;
9152
9156
  }
9153
- if (req.method === "POST" && path45 === "/v1/messages/count_tokens") {
9157
+ if (req.method === "POST" && path46 === "/v1/messages/count_tokens") {
9154
9158
  void handleCountTokens(req, res).catch(() => {
9155
9159
  if (!res.headersSent)
9156
9160
  writeJson(res, 502, anthropicError(502, "api_error", "router internal error").body);
9157
9161
  });
9158
9162
  return;
9159
9163
  }
9160
- if (req.method === "GET" && path45 === "/v1/models") {
9164
+ if (req.method === "GET" && path46 === "/v1/models") {
9161
9165
  writeJson(res, 200, modelsList([...advertisedModels]));
9162
9166
  return;
9163
9167
  }
9164
- if (req.method === "GET" && path45 === "/healthz") {
9168
+ if (req.method === "GET" && path46 === "/healthz") {
9165
9169
  writeJson(res, 200, { ready: server?.listening === true, upstreamReachable, lastError });
9166
9170
  return;
9167
9171
  }
@@ -9430,11 +9434,11 @@ async function probeCaptainChannel(project, opts = {}) {
9430
9434
  }
9431
9435
  }
9432
9436
  async function httpReachable(port, fetchImpl, timeoutMs) {
9433
- for (const path45 of ["/session", "/api/session"]) {
9437
+ for (const path46 of ["/session", "/api/session"]) {
9434
9438
  const ac = new AbortController();
9435
9439
  const t = setTimeout(() => ac.abort(), timeoutMs);
9436
9440
  try {
9437
- const res = await fetchImpl(`http://127.0.0.1:${port}${path45}`, { signal: ac.signal });
9441
+ const res = await fetchImpl(`http://127.0.0.1:${port}${path46}`, { signal: ac.signal });
9438
9442
  if (res.ok)
9439
9443
  return true;
9440
9444
  } catch {
@@ -9817,6 +9821,30 @@ async function runCrewAnswer(project, name, option, runtime, workspaceId, deps,
9817
9821
  if (!crew) {
9818
9822
  throw new Error(`Crew '${name}' not found for ${project}. Run 'squadrant crew list ${project}'.`);
9819
9823
  }
9824
+ const match = runtime.findDialog && runtime.answerDialog ? await deps.dialogMatch?.() : void 0;
9825
+ if (match) {
9826
+ const dialog = await runtime.findDialog(match).catch(() => void 0);
9827
+ if (dialog) {
9828
+ const log2 = deps.log ?? (() => {
9829
+ });
9830
+ const options2 = dialog.options.map((o) => ({ ...o, highlighted: false }));
9831
+ let target2;
9832
+ try {
9833
+ target2 = resolveOption(options2, option);
9834
+ if (opts?.expect && !target2.label.toLowerCase().includes(opts.expect.toLowerCase()))
9835
+ target2 = void 0;
9836
+ } catch {
9837
+ target2 = void 0;
9838
+ }
9839
+ if (target2) {
9840
+ log2(`\u2192 answering ${target2.index}. "${target2.label}" via the runtime (no keystrokes)`);
9841
+ const ok2 = await runtime.answerDialog(dialog, opts?.text ? { text: opts.text } : { label: target2.label }).catch(() => false);
9842
+ if (ok2)
9843
+ return { selected: target2, closed: true };
9844
+ }
9845
+ log2("runtime answer not applied \u2014 falling back to keystrokes");
9846
+ }
9847
+ }
9820
9848
  const modal = await deps.readModalOptions(crew);
9821
9849
  if (!modal || modal.options.length === 0) {
9822
9850
  throw new Error(`Crew '${name}' has no interactive option prompt visible right now \u2014 nothing to answer. Read its screen with 'squadrant crew read ${project} ${name}' to check its state.`);
@@ -10196,6 +10224,58 @@ var init_source = __esm({
10196
10224
  }
10197
10225
  });
10198
10226
 
10227
+ // packages/core/dist/peer-first-turn.js
10228
+ function screenShowsTrustPanel(screen) {
10229
+ return /do you trust the files in this folder|is this a project you created or one you trust|is this a project you trust/i.test(screen);
10230
+ }
10231
+ function trustPanelAcceptKeys(screen) {
10232
+ return /❯\s*(\d\.\s*)?No\b/.test(screen) ? ["Down", "Enter"] : ["Enter"];
10233
+ }
10234
+ async function deliverFirstTurnViaPeer(message, deps) {
10235
+ const pollMs = deps.pollMs ?? DEFAULT_POLL_MS2;
10236
+ const deadline = deps.now() + (deps.readyTimeoutMs ?? DEFAULT_READY_TIMEOUT_MS);
10237
+ let lastTrustAnswer = -Infinity;
10238
+ for (; ; ) {
10239
+ if (deps.statusOf()?.status === "idle")
10240
+ break;
10241
+ if (deps.now() >= deadline)
10242
+ return { kind: "fallback" };
10243
+ if (!deps.statusOf() && deps.now() - lastTrustAnswer >= TRUST_ANSWER_COOLDOWN_MS) {
10244
+ const screen = await deps.readScreen().catch(() => "");
10245
+ if (screenShowsTrustPanel(screen)) {
10246
+ lastTrustAnswer = deps.now();
10247
+ for (const key of trustPanelAcceptKeys(screen))
10248
+ await deps.pressKey(key).catch(() => {
10249
+ });
10250
+ }
10251
+ }
10252
+ await deps.sleep(pollMs);
10253
+ }
10254
+ const outcome = await deps.send(message);
10255
+ if (fallsBackToPane(outcome))
10256
+ return { kind: "fallback" };
10257
+ if (outcome.status === "accepted" && outcome.confirmed)
10258
+ return { kind: "delivered" };
10259
+ const confirmDeadline = deps.now() + (deps.confirmGraceMs ?? DEFAULT_CONFIRM_GRACE_MS);
10260
+ for (; ; ) {
10261
+ if (await deps.isConfirmed().catch(() => false))
10262
+ return { kind: "delivered" };
10263
+ if (deps.now() >= confirmDeadline)
10264
+ return { kind: "unconfirmed" };
10265
+ await deps.sleep(pollMs);
10266
+ }
10267
+ }
10268
+ var DEFAULT_READY_TIMEOUT_MS, DEFAULT_POLL_MS2, DEFAULT_CONFIRM_GRACE_MS, TRUST_ANSWER_COOLDOWN_MS;
10269
+ var init_peer_first_turn = __esm({
10270
+ "packages/core/dist/peer-first-turn.js"() {
10271
+ init_control_channel();
10272
+ DEFAULT_READY_TIMEOUT_MS = 9e4;
10273
+ DEFAULT_POLL_MS2 = 250;
10274
+ DEFAULT_CONFIRM_GRACE_MS = 1e4;
10275
+ TRUST_ANSWER_COOLDOWN_MS = 5e3;
10276
+ }
10277
+ });
10278
+
10199
10279
  // packages/core/dist/knowledge/paths.js
10200
10280
  import path14 from "path";
10201
10281
  function kbDir(hubVault, kb) {
@@ -10617,28 +10697,28 @@ function requireSnippet() {
10617
10697
  const maxLineLength = options.maxLength - (options.indent + lineNoLength + 3);
10618
10698
  for (let i = 1; i <= options.linesBefore; i++) {
10619
10699
  if (foundLineNo - i < 0) break;
10620
- const line2 = getLine(
10700
+ const line22 = getLine(
10621
10701
  mark2.buffer,
10622
10702
  lineStarts[foundLineNo - i],
10623
10703
  lineEnds[foundLineNo - i],
10624
10704
  mark2.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo - i]),
10625
10705
  maxLineLength
10626
10706
  );
10627
- result = common2.repeat(" ", options.indent) + padStart((mark2.line - i + 1).toString(), lineNoLength) + " | " + line2.str + "\n" + result;
10707
+ result = common2.repeat(" ", options.indent) + padStart((mark2.line - i + 1).toString(), lineNoLength) + " | " + line22.str + "\n" + result;
10628
10708
  }
10629
- const line = getLine(mark2.buffer, lineStarts[foundLineNo], lineEnds[foundLineNo], mark2.position, maxLineLength);
10630
- result += common2.repeat(" ", options.indent) + padStart((mark2.line + 1).toString(), lineNoLength) + " | " + line.str + "\n";
10631
- result += common2.repeat("-", options.indent + lineNoLength + 3 + line.pos) + "^\n";
10709
+ const line2 = getLine(mark2.buffer, lineStarts[foundLineNo], lineEnds[foundLineNo], mark2.position, maxLineLength);
10710
+ result += common2.repeat(" ", options.indent) + padStart((mark2.line + 1).toString(), lineNoLength) + " | " + line2.str + "\n";
10711
+ result += common2.repeat("-", options.indent + lineNoLength + 3 + line2.pos) + "^\n";
10632
10712
  for (let i = 1; i <= options.linesAfter; i++) {
10633
10713
  if (foundLineNo + i >= lineEnds.length) break;
10634
- const line2 = getLine(
10714
+ const line22 = getLine(
10635
10715
  mark2.buffer,
10636
10716
  lineStarts[foundLineNo + i],
10637
10717
  lineEnds[foundLineNo + i],
10638
10718
  mark2.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo + i]),
10639
10719
  maxLineLength
10640
10720
  );
10641
- result += common2.repeat(" ", options.indent) + padStart((mark2.line + i + 1).toString(), lineNoLength) + " | " + line2.str + "\n";
10721
+ result += common2.repeat(" ", options.indent) + padStart((mark2.line + i + 1).toString(), lineNoLength) + " | " + line22.str + "\n";
10642
10722
  }
10643
10723
  return result.replace(/\n$/, "");
10644
10724
  }
@@ -12925,17 +13005,17 @@ function requireDumper() {
12925
13005
  let result = "";
12926
13006
  const length = string.length;
12927
13007
  while (position < length) {
12928
- let line;
13008
+ let line2;
12929
13009
  const next = string.indexOf("\n", position);
12930
13010
  if (next === -1) {
12931
- line = string.slice(position);
13011
+ line2 = string.slice(position);
12932
13012
  position = length;
12933
13013
  } else {
12934
- line = string.slice(position, next + 1);
13014
+ line2 = string.slice(position, next + 1);
12935
13015
  position = next + 1;
12936
13016
  }
12937
- if (line.length && line !== "\n") result += ind;
12938
- result += line;
13017
+ if (line2.length && line2 !== "\n") result += ind;
13018
+ result += line2;
12939
13019
  }
12940
13020
  return result;
12941
13021
  }
@@ -13120,15 +13200,15 @@ function requireDumper() {
13120
13200
  let match;
13121
13201
  while (match = lineRe.exec(string)) {
13122
13202
  const prefix = match[1];
13123
- const line = match[2];
13124
- moreIndented = line[0] === " ";
13125
- result += prefix + (!prevMoreIndented && !moreIndented && line !== "" ? "\n" : "") + foldLine(line, width);
13203
+ const line2 = match[2];
13204
+ moreIndented = line2[0] === " ";
13205
+ result += prefix + (!prevMoreIndented && !moreIndented && line2 !== "" ? "\n" : "") + foldLine(line2, width);
13126
13206
  prevMoreIndented = moreIndented;
13127
13207
  }
13128
13208
  return result;
13129
13209
  }
13130
- function foldLine(line, width) {
13131
- if (line === "" || line[0] === " ") return line;
13210
+ function foldLine(line2, width) {
13211
+ if (line2 === "" || line2[0] === " ") return line2;
13132
13212
  const breakRe = / [^ ]/g;
13133
13213
  let match;
13134
13214
  let start = 0;
@@ -13136,20 +13216,20 @@ function requireDumper() {
13136
13216
  let curr = 0;
13137
13217
  let next = 0;
13138
13218
  let result = "";
13139
- while (match = breakRe.exec(line)) {
13219
+ while (match = breakRe.exec(line2)) {
13140
13220
  next = match.index;
13141
13221
  if (next - start > width) {
13142
13222
  end = curr > start ? curr : next;
13143
- result += "\n" + line.slice(start, end);
13223
+ result += "\n" + line2.slice(start, end);
13144
13224
  start = end + 1;
13145
13225
  }
13146
13226
  curr = next;
13147
13227
  }
13148
13228
  result += "\n";
13149
- if (line.length - start > width && curr > start) {
13150
- result += line.slice(start, curr) + "\n" + line.slice(curr + 1);
13229
+ if (line2.length - start > width && curr > start) {
13230
+ result += line2.slice(start, curr) + "\n" + line2.slice(curr + 1);
13151
13231
  } else {
13152
- result += line.slice(start);
13232
+ result += line2.slice(start);
13153
13233
  }
13154
13234
  return result.slice(1);
13155
13235
  }
@@ -13558,6 +13638,220 @@ var init_sources = __esm({
13558
13638
  }
13559
13639
  });
13560
13640
 
13641
+ // packages/core/dist/knowledge/inject.js
13642
+ import fs19 from "fs";
13643
+ import path18 from "path";
13644
+ function sessionOrder(a, b) {
13645
+ const proj = (r) => r.layer.startsWith("project:") ? 0 : 1;
13646
+ const mod = (r) => r.modality === "must-not" ? 0 : 1;
13647
+ return proj(a) - proj(b) || mod(a) - mod(b) || a.id.localeCompare(b.id);
13648
+ }
13649
+ function formatSessionContext(kbs, rules, cap = SESSION_RULE_CAP) {
13650
+ const hard = rules.filter((r) => r.status === "active" && (r.modality === "must" || r.modality === "must-not")).sort(sessionOrder);
13651
+ const shown = hard.slice(0, cap);
13652
+ const lines = [
13653
+ `<squadrant-project-rules kb="${kbs.join(",")}">`,
13654
+ `Rules KB: ${kbs.join(", ")}. ${DATA_NOTE}`,
13655
+ ...shown.map(line)
13656
+ ];
13657
+ if (hard.length > shown.length)
13658
+ lines.push(`+${hard.length - shown.length} more: squadrant rules list --brief`);
13659
+ lines.push("Look up rules for a task with `squadrant rules search <terms>` / `squadrant rules show <id>` (rules-ops skill).");
13660
+ lines.push("</squadrant-project-rules>");
13661
+ return { text: lines.join("\n"), ids: shown.map((r) => r.id) };
13662
+ }
13663
+ function cleanPromptQuery(prompt) {
13664
+ 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, " ");
13665
+ const terms = [];
13666
+ const add = (t) => {
13667
+ if (t.length < 3 && !SHORT_TERMS.has(t) || /^\d+$/.test(t) || STOPWORDS.has(t) || terms.includes(t))
13668
+ return;
13669
+ terms.push(t);
13670
+ };
13671
+ for (const raw of text.split(/[^a-z0-9._-]+/)) {
13672
+ const t = raw.replace(/^[._-]+|[._-]+$/g, "");
13673
+ if (STOPWORDS.has(t))
13674
+ continue;
13675
+ add(t);
13676
+ const parts = t.split(/[._-]+/);
13677
+ if (parts.length > 1 && parts.every((x) => x.length >= 3 && !PREFIXES.has(x)))
13678
+ parts.forEach(add);
13679
+ if (terms.length >= MAX_TERMS)
13680
+ break;
13681
+ }
13682
+ return terms.slice(0, MAX_TERMS).join(" ");
13683
+ }
13684
+ function wholeWordTerms(rule2, terms) {
13685
+ const text = [
13686
+ rule2.id,
13687
+ ...rule2.triggers?.keywords ?? [],
13688
+ ...rule2.triggers?.expanded ?? [],
13689
+ rule2.triggers?.when ?? "",
13690
+ rule2.statement
13691
+ ].join("\n").toLowerCase();
13692
+ return terms.filter((t) => {
13693
+ const base = t.length > 4 ? t.replace(/(es|s)$/, "") : t;
13694
+ return new RegExp(`(^|[^a-z0-9])(?:${escapeRe(t)}|${escapeRe(base)}(?:s|es)?)($|[^a-z0-9])`).test(text);
13695
+ });
13696
+ }
13697
+ function selectPromptHits(hits, query, seen, opts = {}) {
13698
+ const minScore = opts.minScore ?? PROMPT_MIN_SCORE;
13699
+ const terms = query.split(" ").filter(Boolean);
13700
+ return hits.filter((h) => {
13701
+ if (seen.has(h.rule.id))
13702
+ return false;
13703
+ const n = wholeWordTerms(h.rule, terms).length;
13704
+ return n >= 2 && h.score >= minScore || n === 1 && h.score >= PROMPT_SINGLE_TERM_MIN_SCORE;
13705
+ }).slice(0, opts.cap ?? PROMPT_RULE_CAP);
13706
+ }
13707
+ function isSystemPrompt(prompt) {
13708
+ const t = prompt.trimStart();
13709
+ return /^(⚠|🗒|\[stale\b|CREW [A-Z]|Another Claude session sent a message)/u.test(t) || t.includes("<cross-session-message");
13710
+ }
13711
+ function promptText(prompt) {
13712
+ const m = BRIEF_POINTER_RE.exec(prompt.trimStart());
13713
+ if (!m)
13714
+ return prompt;
13715
+ try {
13716
+ return fs19.readFileSync(m[1], "utf8").slice(0, MAX_PROMPT_CHARS * 2);
13717
+ } catch {
13718
+ return prompt;
13719
+ }
13720
+ }
13721
+ function formatPromptContext(hits) {
13722
+ return [
13723
+ '<squadrant-project-rules match="prompt">',
13724
+ `Rules that may apply to this prompt. ${DATA_NOTE}`,
13725
+ ...hits.map((h) => line(h.rule)),
13726
+ "</squadrant-project-rules>"
13727
+ ].join("\n");
13728
+ }
13729
+ function injectStateDir(stateRoot) {
13730
+ return path18.join(stateRoot, "rules-inject");
13731
+ }
13732
+ function readSeenRules(stateRoot, sessionId) {
13733
+ try {
13734
+ const ids = JSON.parse(fs19.readFileSync(sessionFile(stateRoot, sessionId), "utf8"));
13735
+ return new Set(Array.isArray(ids) ? ids.filter((x) => typeof x === "string") : []);
13736
+ } catch {
13737
+ return /* @__PURE__ */ new Set();
13738
+ }
13739
+ }
13740
+ function recordSeenRules(stateRoot, sessionId, ids) {
13741
+ if (!ids.length)
13742
+ return;
13743
+ const seen = readSeenRules(stateRoot, sessionId);
13744
+ for (const id of ids)
13745
+ seen.add(id);
13746
+ fs19.mkdirSync(injectStateDir(stateRoot), { recursive: true });
13747
+ fs19.writeFileSync(sessionFile(stateRoot, sessionId), JSON.stringify([...seen]));
13748
+ }
13749
+ function pruneSeenRules(stateRoot, now = Date.now()) {
13750
+ const dir = injectStateDir(stateRoot);
13751
+ let names;
13752
+ try {
13753
+ names = fs19.readdirSync(dir);
13754
+ } catch {
13755
+ return;
13756
+ }
13757
+ for (const n of names) {
13758
+ const f = path18.join(dir, n);
13759
+ try {
13760
+ if (now - fs19.statSync(f).mtimeMs > SEEN_TTL_MS)
13761
+ fs19.unlinkSync(f);
13762
+ } catch {
13763
+ }
13764
+ }
13765
+ }
13766
+ async function withBudget(fn, budgetMs = INJECT_BUDGET_MS) {
13767
+ const start = Date.now();
13768
+ let timer;
13769
+ try {
13770
+ const timeout = new Promise((resolve4) => {
13771
+ timer = setTimeout(() => resolve4(null), budgetMs);
13772
+ });
13773
+ const out = await Promise.race([Promise.resolve().then(fn), timeout]);
13774
+ return Date.now() - start > budgetMs ? null : out;
13775
+ } catch {
13776
+ return null;
13777
+ } finally {
13778
+ clearTimeout(timer);
13779
+ }
13780
+ }
13781
+ function resolveInjectProject(cfg, cwd, env, project) {
13782
+ const named = project ?? env.SQUADRANT_CREW_PROJECT;
13783
+ if (named)
13784
+ return cfg.projects[named] ? named : null;
13785
+ let best = null;
13786
+ let bestLen = -1;
13787
+ for (const [name, pc] of Object.entries(cfg.projects)) {
13788
+ const root = resolveHome(pc.path);
13789
+ if ((cwd === root || cwd.startsWith(root + path18.sep)) && root.length > bestLen) {
13790
+ best = name;
13791
+ bestLen = root.length;
13792
+ }
13793
+ }
13794
+ return best;
13795
+ }
13796
+ function computeRulesInjection(i) {
13797
+ if (i.env.SQUADRANT_RULES_INJECT === "0")
13798
+ return null;
13799
+ const p = typeof i.payload === "object" && i.payload !== null ? i.payload : {};
13800
+ const cwd = typeof p.cwd === "string" && p.cwd ? p.cwd : i.cwd;
13801
+ const project = resolveInjectProject(i.cfg, cwd, i.env, i.project);
13802
+ if (!project)
13803
+ return null;
13804
+ const kbs = subscribedKbs(i.cfg, project);
13805
+ if (!kbs.length)
13806
+ return null;
13807
+ const sessionId = typeof p.session_id === "string" && p.session_id ? p.session_id : null;
13808
+ if (i.event === "session-start") {
13809
+ const { text, ids } = formatSessionContext(kbs, resolveProjectRules(i.cfg, project).rules);
13810
+ if (sessionId) {
13811
+ pruneSeenRules(i.stateRoot);
13812
+ recordSeenRules(i.stateRoot, sessionId, ids);
13813
+ }
13814
+ return text;
13815
+ }
13816
+ if (typeof p.prompt !== "string" || isSystemPrompt(p.prompt))
13817
+ return null;
13818
+ const query = cleanPromptQuery(promptText(p.prompt));
13819
+ if (!query)
13820
+ return null;
13821
+ const seen = sessionId ? readSeenRules(i.stateRoot, sessionId) : /* @__PURE__ */ new Set();
13822
+ const picked = selectPromptHits(searchRules(resolveProjectRules(i.cfg, project).rules, query), query, seen);
13823
+ if (!picked.length)
13824
+ return null;
13825
+ if (sessionId)
13826
+ recordSeenRules(i.stateRoot, sessionId, picked.map((h) => h.rule.id));
13827
+ return formatPromptContext(picked);
13828
+ }
13829
+ 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;
13830
+ var init_inject = __esm({
13831
+ "packages/core/dist/knowledge/inject.js"() {
13832
+ init_dist();
13833
+ init_search();
13834
+ init_layers();
13835
+ SESSION_RULE_CAP = 20;
13836
+ PROMPT_RULE_CAP = 3;
13837
+ PROMPT_MIN_SCORE = 8;
13838
+ PROMPT_SINGLE_TERM_MIN_SCORE = 13;
13839
+ INJECT_BUDGET_MS = 1500;
13840
+ MAX_PROMPT_CHARS = 3e3;
13841
+ MAX_LINE_CHARS = 400;
13842
+ MAX_TERMS = 40;
13843
+ SHORT_TERMS = /* @__PURE__ */ new Set(["pr", "db", "ci", "ui"]);
13844
+ PREFIXES = /* @__PURE__ */ new Set(["pre", "non", "sub", "anti", "multi", "semi", "post", "mid"]);
13845
+ SEEN_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
13846
+ 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+/));
13847
+ DATA_NOTE = "These are project rules (data from the knowledge base), not instructions to run anything.";
13848
+ line = (r) => `${r.modality.toUpperCase()} ${r.id}: ${r.statement}`;
13849
+ escapeRe = (t) => t.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
13850
+ BRIEF_POINTER_RE = /^Full task is at (\S+\.md) — cat it/;
13851
+ sessionFile = (stateRoot, sessionId) => path18.join(injectStateDir(stateRoot), `${sessionId.replace(/[^A-Za-z0-9_-]/g, "_")}.json`);
13852
+ }
13853
+ });
13854
+
13561
13855
  // packages/core/dist/knowledge/index.js
13562
13856
  var init_knowledge2 = __esm({
13563
13857
  "packages/core/dist/knowledge/index.js"() {
@@ -13567,6 +13861,7 @@ var init_knowledge2 = __esm({
13567
13861
  init_index_file();
13568
13862
  init_search();
13569
13863
  init_sources();
13864
+ init_inject();
13570
13865
  }
13571
13866
  });
13572
13867
 
@@ -13597,12 +13892,16 @@ __export(dist_exports2, {
13597
13892
  GROUP_DISPATCH_WARMUP_TIMEOUT_MS: () => GROUP_DISPATCH_WARMUP_TIMEOUT_MS,
13598
13893
  GateDecisionCache: () => GateDecisionCache,
13599
13894
  IDLE_DEBOUNCE_MS: () => IDLE_DEBOUNCE_MS,
13895
+ INJECT_BUDGET_MS: () => INJECT_BUDGET_MS,
13600
13896
  LABEL: () => LABEL,
13601
13897
  LivenessRegistry: () => LivenessRegistry,
13602
13898
  MONITOR_STALL_BUDGET_MS: () => MONITOR_STALL_BUDGET_MS,
13603
13899
  OPERATOR_INITIATED_COMMANDS: () => OPERATOR_INITIATED_COMMANDS,
13604
13900
  PANE_IDLE_AFTER_MS: () => PANE_IDLE_AFTER_MS,
13605
13901
  PROBE_QUIET_MS: () => PROBE_QUIET_MS,
13902
+ PROMPT_MIN_SCORE: () => PROMPT_MIN_SCORE,
13903
+ PROMPT_RULE_CAP: () => PROMPT_RULE_CAP,
13904
+ PROMPT_SINGLE_TERM_MIN_SCORE: () => PROMPT_SINGLE_TERM_MIN_SCORE,
13606
13905
  PROPOSED_DIR: () => PROPOSED_DIR,
13607
13906
  PROTOCOL_VERSION: () => PROTOCOL_VERSION,
13608
13907
  READ_ONLY_CREW_SUBCOMMANDS: () => READ_ONLY_CREW_SUBCOMMANDS,
@@ -13610,6 +13909,7 @@ __export(dist_exports2, {
13610
13909
  ROUTER_READY_ATTEMPTS: () => ROUTER_READY_ATTEMPTS,
13611
13910
  ROUTER_READY_DELAY_MS: () => ROUTER_READY_DELAY_MS,
13612
13911
  SERVER_TOOL_TYPE_RE: () => SERVER_TOOL_TYPE_RE,
13912
+ SESSION_RULE_CAP: () => SESSION_RULE_CAP,
13613
13913
  SIDE_SESSION_ENV: () => SIDE_SESSION_ENV,
13614
13914
  SOURCES_TEMPLATE: () => SOURCES_TEMPLATE,
13615
13915
  STALE_THRESHOLD_MS: () => STALE_THRESHOLD_MS,
@@ -13650,9 +13950,11 @@ __export(dist_exports2, {
13650
13950
  classifyCaptainPane: () => classifyCaptainPane,
13651
13951
  classifyHealth: () => classifyHealth,
13652
13952
  claudeEnvShadowsRouter: () => claudeEnvShadowsRouter,
13953
+ cleanPromptQuery: () => cleanPromptQuery,
13653
13954
  clearPending: () => clearPending,
13654
13955
  closeWorkItem: () => closeWorkItem,
13655
13956
  compileIndex: () => compileIndex,
13957
+ computeRulesInjection: () => computeRulesInjection,
13656
13958
  computeTemplateHash: () => computeTemplateHash,
13657
13959
  consumeExitMarker: () => consumeExitMarker,
13658
13960
  createAttach: () => createAttach,
@@ -13693,6 +13995,7 @@ __export(dist_exports2, {
13693
13995
  defaultIsPidAlive: () => defaultIsPidAlive,
13694
13996
  defaultListenError: () => defaultListenError,
13695
13997
  defaultWorkRoot: () => defaultWorkRoot,
13998
+ deliverFirstTurnViaPeer: () => deliverFirstTurnViaPeer,
13696
13999
  deliverStartupPrompt: () => deliverStartupPrompt,
13697
14000
  deliverToCaptain: () => deliverToCaptain,
13698
14001
  deliverable: () => deliverable,
@@ -13726,6 +14029,8 @@ __export(dist_exports2, {
13726
14029
  formatLifecycle: () => formatLifecycle,
13727
14030
  formatMediaReceipt: () => formatMediaReceipt,
13728
14031
  formatPermissionDecision: () => formatPermissionDecision,
14032
+ formatPromptContext: () => formatPromptContext,
14033
+ formatSessionContext: () => formatSessionContext,
13729
14034
  formatUsageLine: () => formatUsageLine,
13730
14035
  formatWatchdogWarning: () => formatWatchdogWarning,
13731
14036
  freshTrace: () => freshTrace,
@@ -13735,6 +14040,7 @@ __export(dist_exports2, {
13735
14040
  hasModalOptionList: () => hasModalOptionList,
13736
14041
  healCmdFor: () => healCmdFor,
13737
14042
  inboundBody: () => inboundBody,
14043
+ injectStateDir: () => injectStateDir,
13738
14044
  isAuthorized: () => isAuthorized,
13739
14045
  isBareSpawn: () => isBareSpawn,
13740
14046
  isCaptainAlive: () => isCaptainAlive,
@@ -13750,6 +14056,7 @@ __export(dist_exports2, {
13750
14056
  isReadOnlyTopLevelCommand: () => isReadOnlyTopLevelCommand,
13751
14057
  isSideTitle: () => isSideTitle,
13752
14058
  isStickyAttention: () => isStickyAttention,
14059
+ isSystemPrompt: () => isSystemPrompt,
13753
14060
  isTurnAccepted: () => isTurnAccepted,
13754
14061
  isVersionUpgrade: () => isVersionUpgrade,
13755
14062
  joinUrl: () => joinUrl,
@@ -13795,6 +14102,7 @@ __export(dist_exports2, {
13795
14102
  programArgsBlock: () => programArgsBlock,
13796
14103
  projectHealth: () => projectHealth,
13797
14104
  projectRulesDir: () => projectRulesDir,
14105
+ pruneSeenRules: () => pruneSeenRules,
13798
14106
  pruneTopics: () => pruneTopics,
13799
14107
  purgeExpiredWorkItems: () => purgeExpiredWorkItems,
13800
14108
  readCaptainAddress: () => readCaptainAddress,
@@ -13802,11 +14110,13 @@ __export(dist_exports2, {
13802
14110
  readFromCursor: () => readFromCursor,
13803
14111
  readIndex: () => readIndex,
13804
14112
  readRunningMarker: () => readRunningMarker,
14113
+ readSeenRules: () => readSeenRules,
13805
14114
  readUserIntent: () => readUserIntent,
13806
14115
  realpathOrSelf: () => realpathOrSelf,
13807
14116
  reapCrewChildren: () => reapCrewChildren,
13808
14117
  reapOrphanedCrews: () => reapOrphanedCrews,
13809
14118
  reconcileLiveness: () => reconcileLiveness,
14119
+ recordSeenRules: () => recordSeenRules,
13810
14120
  recordSession: () => recordSession,
13811
14121
  recoverStall: () => recoverStall,
13812
14122
  reduce: () => reduce,
@@ -13828,6 +14138,7 @@ __export(dist_exports2, {
13828
14138
  resolveGateMode: () => resolveGateMode,
13829
14139
  resolveGatePolicy: () => resolveGatePolicy,
13830
14140
  resolveGateTools: () => resolveGateTools,
14141
+ resolveInjectProject: () => resolveInjectProject,
13831
14142
  resolveProject: () => resolveProject,
13832
14143
  resolveProjectRules: () => resolveProjectRules,
13833
14144
  resolveRouterCredentials: () => resolveRouterCredentials,
@@ -13866,7 +14177,9 @@ __export(dist_exports2, {
13866
14177
  saveState: () => saveState,
13867
14178
  screenHasSplashMarker: () => screenHasSplashMarker,
13868
14179
  screenHash: () => screenHash,
14180
+ screenShowsTrustPanel: () => screenShowsTrustPanel,
13869
14181
  searchRules: () => searchRules,
14182
+ selectPromptHits: () => selectPromptHits,
13870
14183
  sendRequest: () => sendRequest,
13871
14184
  setLastUserId: () => setLastUserId,
13872
14185
  setNotify: () => setNotify,
@@ -13890,11 +14203,14 @@ __export(dist_exports2, {
13890
14203
  toControlEvent: () => toControlEvent,
13891
14204
  topicKey: () => topicKey,
13892
14205
  topicName: () => topicName,
14206
+ trustPanelAcceptKeys: () => trustPanelAcceptKeys,
13893
14207
  tryAcquireDaemonLock: () => tryAcquireDaemonLock,
13894
14208
  usageFromJson: () => usageFromJson,
13895
14209
  validateKb: () => validateKb,
13896
14210
  waitForCaptainDelivery: () => waitForCaptainDelivery,
13897
14211
  waitForWarmup: () => waitForWarmup,
14212
+ wholeWordTerms: () => wholeWordTerms,
14213
+ withBudget: () => withBudget,
13898
14214
  writeCaptainAddress: () => writeCaptainAddress,
13899
14215
  writeCursor: () => writeCursor,
13900
14216
  writeExitMarker: () => writeExitMarker,
@@ -13950,6 +14266,7 @@ var init_dist2 = __esm({
13950
14266
  init_conformance();
13951
14267
  init_source();
13952
14268
  init_control_channel();
14269
+ init_peer_first_turn();
13953
14270
  init_captain_channel();
13954
14271
  init_captain_record();
13955
14272
  init_opencode_session();
@@ -13958,7 +14275,7 @@ var init_dist2 = __esm({
13958
14275
  });
13959
14276
 
13960
14277
  // packages/agents/dist/claude/registry.js
13961
- import fs19 from "fs";
14278
+ import fs20 from "fs";
13962
14279
  import { join as join17 } from "path";
13963
14280
  import { homedir as homedir7 } from "os";
13964
14281
  function parseRegistryDir(files, readFile7) {
@@ -14003,11 +14320,11 @@ function readClaudeStatus(task) {
14003
14320
  return void 0;
14004
14321
  let files;
14005
14322
  try {
14006
- files = fs19.readdirSync(CLAUDE_SESSIONS_DIR);
14323
+ files = fs20.readdirSync(CLAUDE_SESSIONS_DIR);
14007
14324
  } catch {
14008
14325
  return void 0;
14009
14326
  }
14010
- const entries = parseRegistryDir(files, (name) => fs19.readFileSync(join17(CLAUDE_SESSIONS_DIR, name), "utf8"));
14327
+ const entries = parseRegistryDir(files, (name) => fs20.readFileSync(join17(CLAUDE_SESSIONS_DIR, name), "utf8"));
14011
14328
  let entry;
14012
14329
  if (task.messagingSocketPath) {
14013
14330
  entry = entries.find((e) => e.messagingSocketPath === task.messagingSocketPath);
@@ -14022,11 +14339,11 @@ function readClaudeStatus(task) {
14022
14339
  function readClaudeStatusByCwd(cwd) {
14023
14340
  let files;
14024
14341
  try {
14025
- files = fs19.readdirSync(CLAUDE_SESSIONS_DIR);
14342
+ files = fs20.readdirSync(CLAUDE_SESSIONS_DIR);
14026
14343
  } catch {
14027
14344
  return void 0;
14028
14345
  }
14029
- const entries = parseRegistryDir(files, (name) => fs19.readFileSync(join17(CLAUDE_SESSIONS_DIR, name), "utf8"));
14346
+ const entries = parseRegistryDir(files, (name) => fs20.readFileSync(join17(CLAUDE_SESSIONS_DIR, name), "utf8"));
14030
14347
  const entry = entries.find((e) => e.cwd === cwd);
14031
14348
  if (!entry)
14032
14349
  return void 0;
@@ -14035,11 +14352,11 @@ function readClaudeStatusByCwd(cwd) {
14035
14352
  function readClaudeStatusBySocketPath(socketPath2) {
14036
14353
  let files;
14037
14354
  try {
14038
- files = fs19.readdirSync(CLAUDE_SESSIONS_DIR);
14355
+ files = fs20.readdirSync(CLAUDE_SESSIONS_DIR);
14039
14356
  } catch {
14040
14357
  return void 0;
14041
14358
  }
14042
- const entries = parseRegistryDir(files, (name) => fs19.readFileSync(join17(CLAUDE_SESSIONS_DIR, name), "utf8"));
14359
+ const entries = parseRegistryDir(files, (name) => fs20.readFileSync(join17(CLAUDE_SESSIONS_DIR, name), "utf8"));
14043
14360
  const entry = entries.find((e) => e.messagingSocketPath === socketPath2);
14044
14361
  if (!entry)
14045
14362
  return void 0;
@@ -14462,8 +14779,8 @@ var init_registry2 = __esm({
14462
14779
  });
14463
14780
 
14464
14781
  // packages/agents/dist/drivers/launch-cmd.js
14465
- import fs20 from "fs";
14466
- import path18 from "path";
14782
+ import fs21 from "fs";
14783
+ import path19 from "path";
14467
14784
  function buildAgentCmd(agentName, registry, role, fresh, permissionMode, model, templatesDir, messagingSocketPath, sessionName, thinking, captainBoot, settingsPath) {
14468
14785
  const driver = registry.getDriver(agentName);
14469
14786
  if (driver.name === "claude") {
@@ -14490,14 +14807,14 @@ function buildAgentCmd(agentName, registry, role, fresh, permissionMode, model,
14490
14807
  cmd += ` --settings ${settingsPath}`;
14491
14808
  }
14492
14809
  if (templatesDir) {
14493
- const roleFile2 = path18.join(templatesDir, `${role}.claude.md`);
14494
- const legacyRoleFile = path18.join(templatesDir, `${role}.CLAUDE.md`);
14495
- const actualRoleFile = fs20.existsSync(roleFile2) ? roleFile2 : fs20.existsSync(legacyRoleFile) ? legacyRoleFile : null;
14810
+ const roleFile2 = path19.join(templatesDir, `${role}.claude.md`);
14811
+ const legacyRoleFile = path19.join(templatesDir, `${role}.CLAUDE.md`);
14812
+ const actualRoleFile = fs21.existsSync(roleFile2) ? roleFile2 : fs21.existsSync(legacyRoleFile) ? legacyRoleFile : null;
14496
14813
  if (actualRoleFile) {
14497
14814
  cmd += ` --append-system-prompt-file ${actualRoleFile}`;
14498
14815
  }
14499
- const pluginDir = path18.join(templatesDir, "..", "plugin");
14500
- if (fs20.existsSync(pluginDir)) {
14816
+ const pluginDir = path19.join(templatesDir, "..", "plugin");
14817
+ if (fs21.existsSync(pluginDir)) {
14501
14818
  cmd += ` --plugin-dir ${pluginDir}`;
14502
14819
  }
14503
14820
  }
@@ -14506,14 +14823,14 @@ function buildAgentCmd(agentName, registry, role, fresh, permissionMode, model,
14506
14823
  }
14507
14824
  return cmd;
14508
14825
  }
14509
- const roleFile = templatesDir ? path18.join(templatesDir, `${role}.${driver.templateSuffix}.md`) : void 0;
14826
+ const roleFile = templatesDir ? path19.join(templatesDir, `${role}.${driver.templateSuffix}.md`) : void 0;
14510
14827
  return driver.buildCommand({
14511
14828
  prompt: `You are a squadrant ${role}. Read your instructions from ${roleFile ?? role} and begin.`,
14512
14829
  workdir: process.cwd(),
14513
14830
  role,
14514
14831
  model,
14515
14832
  autoApprove: true,
14516
- promptFile: roleFile && fs20.existsSync(roleFile) ? roleFile : void 0,
14833
+ promptFile: roleFile && fs21.existsSync(roleFile) ? roleFile : void 0,
14517
14834
  ...captainBoot && role === "captain" ? {
14518
14835
  interactive: true,
14519
14836
  ...captainBoot.port ? { port: captainBoot.port } : {},
@@ -14543,7 +14860,7 @@ var init_drivers = __esm({
14543
14860
 
14544
14861
  // packages/agents/dist/projection/cursor.js
14545
14862
  import { mkdir, readFile, writeFile } from "fs/promises";
14546
- import path19 from "path";
14863
+ import path20 from "path";
14547
14864
  import os8 from "os";
14548
14865
  function renderMdc(source) {
14549
14866
  const skillSections = source.skills.map((s) => `## Skill: ${s.name}
@@ -14592,7 +14909,7 @@ function createCursorEmitter() {
14592
14909
  if (scope === "user") {
14593
14910
  return [
14594
14911
  {
14595
- path: path19.join(os8.homedir(), ".cursor/rules/squadrant-global.mdc"),
14912
+ path: path20.join(os8.homedir(), ".cursor/rules/squadrant-global.mdc"),
14596
14913
  shared: false,
14597
14914
  format: "mdc"
14598
14915
  }
@@ -14602,7 +14919,7 @@ function createCursorEmitter() {
14602
14919
  return [];
14603
14920
  return [
14604
14921
  {
14605
- path: path19.join(projectRoot, ".cursor/rules/squadrant.mdc"),
14922
+ path: path20.join(projectRoot, ".cursor/rules/squadrant.mdc"),
14606
14923
  shared: false,
14607
14924
  format: "mdc"
14608
14925
  }
@@ -14619,7 +14936,7 @@ function createCursorEmitter() {
14619
14936
  diff: buildDiff(existing, generated)
14620
14937
  };
14621
14938
  }
14622
- await mkdir(path19.dirname(dest.path), { recursive: true });
14939
+ await mkdir(path20.dirname(dest.path), { recursive: true });
14623
14940
  await writeFile(dest.path, generated, "utf-8");
14624
14941
  return {
14625
14942
  written: true,
@@ -14670,7 +14987,7 @@ var init_marker = __esm({
14670
14987
 
14671
14988
  // packages/agents/dist/projection/codex.js
14672
14989
  import { mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
14673
- import path20 from "path";
14990
+ import path21 from "path";
14674
14991
  import os9 from "os";
14675
14992
  function renderMarkdown(source) {
14676
14993
  const skillSections = source.skills.map((s) => `## Skill: ${s.name}
@@ -14695,7 +15012,7 @@ function createCodexEmitter() {
14695
15012
  destinations(scope, projectRoot) {
14696
15013
  if (scope === "user") {
14697
15014
  return [{
14698
- path: path20.join(os9.homedir(), ".codex/AGENTS.md"),
15015
+ path: path21.join(os9.homedir(), ".codex/AGENTS.md"),
14699
15016
  shared: true,
14700
15017
  format: "markdown"
14701
15018
  }];
@@ -14703,7 +15020,7 @@ function createCodexEmitter() {
14703
15020
  if (!projectRoot)
14704
15021
  return [];
14705
15022
  return [{
14706
- path: path20.join(projectRoot, "AGENTS.md"),
15023
+ path: path21.join(projectRoot, "AGENTS.md"),
14707
15024
  shared: true,
14708
15025
  format: "markdown"
14709
15026
  }];
@@ -14724,7 +15041,7 @@ ${existing ?? ""}
14724
15041
  ${generated}`
14725
15042
  };
14726
15043
  }
14727
- await mkdir2(path20.dirname(dest.path), { recursive: true });
15044
+ await mkdir2(path21.dirname(dest.path), { recursive: true });
14728
15045
  await writeFile2(dest.path, generated, "utf-8");
14729
15046
  return {
14730
15047
  written: true,
@@ -14742,7 +15059,7 @@ var init_codex2 = __esm({
14742
15059
 
14743
15060
  // packages/agents/dist/projection/gemini.js
14744
15061
  import { mkdir as mkdir3, readFile as readFile3, writeFile as writeFile3 } from "fs/promises";
14745
- import path21 from "path";
15062
+ import path22 from "path";
14746
15063
  import os10 from "os";
14747
15064
  function renderMarkdown2(source) {
14748
15065
  const skillSections = source.skills.map((s) => `## Skill: ${s.name}
@@ -14767,7 +15084,7 @@ function createGeminiEmitter() {
14767
15084
  destinations(scope, projectRoot) {
14768
15085
  if (scope === "user") {
14769
15086
  return [{
14770
- path: path21.join(os10.homedir(), ".gemini/GEMINI.md"),
15087
+ path: path22.join(os10.homedir(), ".gemini/GEMINI.md"),
14771
15088
  shared: true,
14772
15089
  format: "markdown"
14773
15090
  }];
@@ -14775,7 +15092,7 @@ function createGeminiEmitter() {
14775
15092
  if (!projectRoot)
14776
15093
  return [];
14777
15094
  return [{
14778
- path: path21.join(projectRoot, "GEMINI.md"),
15095
+ path: path22.join(projectRoot, "GEMINI.md"),
14779
15096
  shared: true,
14780
15097
  format: "markdown"
14781
15098
  }];
@@ -14796,7 +15113,7 @@ ${existing ?? ""}
14796
15113
  ${generated}`
14797
15114
  };
14798
15115
  }
14799
- await mkdir3(path21.dirname(dest.path), { recursive: true });
15116
+ await mkdir3(path22.dirname(dest.path), { recursive: true });
14800
15117
  await writeFile3(dest.path, generated, "utf-8");
14801
15118
  return {
14802
15119
  written: true,
@@ -14814,7 +15131,7 @@ var init_gemini2 = __esm({
14814
15131
 
14815
15132
  // packages/agents/dist/projection/opencode.js
14816
15133
  import { mkdir as mkdir4, readFile as readFile4, writeFile as writeFile4 } from "fs/promises";
14817
- import path22 from "path";
15134
+ import path23 from "path";
14818
15135
  import os11 from "os";
14819
15136
  function renderMarkdown3(source) {
14820
15137
  const skillSections = source.skills.map((s) => `## Skill: ${s.name}
@@ -14839,7 +15156,7 @@ function createOpencodeEmitter() {
14839
15156
  destinations(scope, projectRoot) {
14840
15157
  if (scope === "user") {
14841
15158
  return [{
14842
- path: path22.join(os11.homedir(), ".config", "opencode", "AGENTS.md"),
15159
+ path: path23.join(os11.homedir(), ".config", "opencode", "AGENTS.md"),
14843
15160
  shared: true,
14844
15161
  format: "markdown"
14845
15162
  }];
@@ -14847,7 +15164,7 @@ function createOpencodeEmitter() {
14847
15164
  if (!projectRoot)
14848
15165
  return [];
14849
15166
  return [{
14850
- path: path22.join(projectRoot, "AGENTS.md"),
15167
+ path: path23.join(projectRoot, "AGENTS.md"),
14851
15168
  shared: true,
14852
15169
  format: "markdown"
14853
15170
  }];
@@ -14868,7 +15185,7 @@ ${existing ?? ""}
14868
15185
  ${generated}`
14869
15186
  };
14870
15187
  }
14871
- await mkdir4(path22.dirname(dest.path), { recursive: true });
15188
+ await mkdir4(path23.dirname(dest.path), { recursive: true });
14872
15189
  await writeFile4(dest.path, generated, "utf-8");
14873
15190
  return {
14874
15191
  written: true,
@@ -14885,12 +15202,12 @@ var init_opencode2 = __esm({
14885
15202
  });
14886
15203
 
14887
15204
  // packages/agents/dist/projection/opencode-skills.js
14888
- import fs21 from "fs";
15205
+ import fs22 from "fs";
14889
15206
  import os12 from "os";
14890
- import path23 from "path";
15207
+ import path24 from "path";
14891
15208
  function defaultOpencodeSkillsRoot(env = process.env) {
14892
- const configHome = env.XDG_CONFIG_HOME || path23.join(os12.homedir(), ".config");
14893
- return path23.join(configHome, "opencode", "skills");
15209
+ const configHome = env.XDG_CONFIG_HOME || path24.join(os12.homedir(), ".config");
15210
+ return path24.join(configHome, "opencode", "skills");
14894
15211
  }
14895
15212
  function parseSkillName(raw) {
14896
15213
  const fm = raw.match(/^---\r?\n([\s\S]*?)\r?\n---/);
@@ -14904,62 +15221,62 @@ function parseSkillName(raw) {
14904
15221
  }
14905
15222
  function listSourceSkills(sourceSkillsDir) {
14906
15223
  const out = /* @__PURE__ */ new Map();
14907
- if (!fs21.existsSync(sourceSkillsDir))
15224
+ if (!fs22.existsSync(sourceSkillsDir))
14908
15225
  return out;
14909
- for (const entry of fs21.readdirSync(sourceSkillsDir, { withFileTypes: true })) {
15226
+ for (const entry of fs22.readdirSync(sourceSkillsDir, { withFileTypes: true })) {
14910
15227
  if (!entry.isDirectory())
14911
15228
  continue;
14912
- const skillPath = path23.join(sourceSkillsDir, entry.name, "SKILL.md");
14913
- if (!fs21.existsSync(skillPath))
15229
+ const skillPath = path24.join(sourceSkillsDir, entry.name, "SKILL.md");
15230
+ if (!fs22.existsSync(skillPath))
14914
15231
  continue;
14915
- const name = parseSkillName(fs21.readFileSync(skillPath, "utf-8"));
15232
+ const name = parseSkillName(fs22.readFileSync(skillPath, "utf-8"));
14916
15233
  if (name && SAFE_NAME.test(name))
14917
15234
  out.set(name, skillPath);
14918
15235
  }
14919
15236
  return out;
14920
15237
  }
14921
15238
  function hasMarker(dir) {
14922
- return fs21.existsSync(path23.join(dir, OPENCODE_SKILL_MARKER));
15239
+ return fs22.existsSync(path24.join(dir, OPENCODE_SKILL_MARKER));
14923
15240
  }
14924
15241
  function syncOpencodeSkills(opts) {
14925
15242
  const result = { written: [], unchanged: [], removed: [], skipped: [] };
14926
15243
  const wanted = listSourceSkills(opts.sourceSkillsDir);
14927
- if (wanted.size === 0 && !fs21.existsSync(opts.sourceSkillsDir))
15244
+ if (wanted.size === 0 && !fs22.existsSync(opts.sourceSkillsDir))
14928
15245
  return result;
14929
15246
  if (!opts.dryRun)
14930
- fs21.mkdirSync(opts.skillsRoot, { recursive: true });
15247
+ fs22.mkdirSync(opts.skillsRoot, { recursive: true });
14931
15248
  for (const [name, srcPath] of wanted) {
14932
- const targetDir = path23.join(opts.skillsRoot, name);
14933
- const targetSkill = path23.join(targetDir, "SKILL.md");
15249
+ const targetDir = path24.join(opts.skillsRoot, name);
15250
+ const targetSkill = path24.join(targetDir, "SKILL.md");
14934
15251
  const managed = hasMarker(targetDir);
14935
- if (fs21.existsSync(targetSkill) && !managed) {
15252
+ if (fs22.existsSync(targetSkill) && !managed) {
14936
15253
  result.skipped.push({ name, reason: "foreign-collision" });
14937
15254
  continue;
14938
15255
  }
14939
- const current = fs21.existsSync(targetSkill) ? fs21.readFileSync(targetSkill) : null;
14940
- if (current && current.equals(fs21.readFileSync(srcPath))) {
15256
+ const current = fs22.existsSync(targetSkill) ? fs22.readFileSync(targetSkill) : null;
15257
+ if (current && current.equals(fs22.readFileSync(srcPath))) {
14941
15258
  if (!managed && !opts.dryRun) {
14942
- fs21.writeFileSync(path23.join(targetDir, OPENCODE_SKILL_MARKER), MARKER_BODY);
15259
+ fs22.writeFileSync(path24.join(targetDir, OPENCODE_SKILL_MARKER), MARKER_BODY);
14943
15260
  }
14944
15261
  result.unchanged.push(name);
14945
15262
  continue;
14946
15263
  }
14947
15264
  if (!opts.dryRun) {
14948
- fs21.mkdirSync(targetDir, { recursive: true });
14949
- fs21.copyFileSync(srcPath, targetSkill);
14950
- fs21.writeFileSync(path23.join(targetDir, OPENCODE_SKILL_MARKER), MARKER_BODY);
15265
+ fs22.mkdirSync(targetDir, { recursive: true });
15266
+ fs22.copyFileSync(srcPath, targetSkill);
15267
+ fs22.writeFileSync(path24.join(targetDir, OPENCODE_SKILL_MARKER), MARKER_BODY);
14951
15268
  }
14952
15269
  result.written.push(name);
14953
15270
  }
14954
- if (fs21.existsSync(opts.skillsRoot)) {
14955
- for (const entry of fs21.readdirSync(opts.skillsRoot, { withFileTypes: true })) {
15271
+ if (fs22.existsSync(opts.skillsRoot)) {
15272
+ for (const entry of fs22.readdirSync(opts.skillsRoot, { withFileTypes: true })) {
14956
15273
  if (!entry.isDirectory() || wanted.has(entry.name))
14957
15274
  continue;
14958
- const dir = path23.join(opts.skillsRoot, entry.name);
15275
+ const dir = path24.join(opts.skillsRoot, entry.name);
14959
15276
  if (!hasMarker(dir))
14960
15277
  continue;
14961
15278
  if (!opts.dryRun)
14962
- fs21.rmSync(dir, { recursive: true, force: true });
15279
+ fs22.rmSync(dir, { recursive: true, force: true });
14963
15280
  result.removed.push(entry.name);
14964
15281
  }
14965
15282
  }
@@ -14967,7 +15284,7 @@ function syncOpencodeSkills(opts) {
14967
15284
  }
14968
15285
  function syncShippedOpencodeSkills(opts) {
14969
15286
  return syncOpencodeSkills({
14970
- sourceSkillsDir: path23.join(opts.pkgRoot, "plugin", "skills"),
15287
+ sourceSkillsDir: path24.join(opts.pkgRoot, "plugin", "skills"),
14971
15288
  skillsRoot: opts.skillsRoot ?? defaultOpencodeSkillsRoot(),
14972
15289
  dryRun: opts.dryRun
14973
15290
  });
@@ -14983,7 +15300,7 @@ var init_opencode_skills = __esm({
14983
15300
 
14984
15301
  // packages/agents/dist/projection/claude.js
14985
15302
  import { mkdir as mkdir5, readFile as readFile5, writeFile as writeFile5 } from "fs/promises";
14986
- import path24 from "path";
15303
+ import path25 from "path";
14987
15304
  import os13 from "os";
14988
15305
  function renderMarkdown4(source) {
14989
15306
  const skillSections = source.skills.map((s) => `## Skill: ${s.name}
@@ -15008,7 +15325,7 @@ function createClaudeEmitter() {
15008
15325
  destinations(scope, projectRoot) {
15009
15326
  if (scope === "user") {
15010
15327
  return [{
15011
- path: path24.join(os13.homedir(), ".claude/CLAUDE.md"),
15328
+ path: path25.join(os13.homedir(), ".claude/CLAUDE.md"),
15012
15329
  shared: true,
15013
15330
  format: "markdown"
15014
15331
  }];
@@ -15016,7 +15333,7 @@ function createClaudeEmitter() {
15016
15333
  if (!projectRoot)
15017
15334
  return [];
15018
15335
  return [{
15019
- path: path24.join(projectRoot, "CLAUDE.md"),
15336
+ path: path25.join(projectRoot, "CLAUDE.md"),
15020
15337
  shared: true,
15021
15338
  format: "markdown"
15022
15339
  }];
@@ -15037,7 +15354,7 @@ ${existing ?? ""}
15037
15354
  ${generated}`
15038
15355
  };
15039
15356
  }
15040
- await mkdir5(path24.dirname(dest.path), { recursive: true });
15357
+ await mkdir5(path25.dirname(dest.path), { recursive: true });
15041
15358
  await writeFile5(dest.path, generated, "utf-8");
15042
15359
  return {
15043
15360
  written: true,
@@ -15099,12 +15416,12 @@ function _parseChunk(acc, chunk) {
15099
15416
  const out = [];
15100
15417
  let idx;
15101
15418
  while ((idx = acc.buf.indexOf("\n")) >= 0) {
15102
- const line = acc.buf.slice(0, idx);
15419
+ const line2 = acc.buf.slice(0, idx);
15103
15420
  acc.buf = acc.buf.slice(idx + 1);
15104
- if (!line.trim())
15421
+ if (!line2.trim())
15105
15422
  continue;
15106
15423
  try {
15107
- out.push(JSON.parse(line));
15424
+ out.push(JSON.parse(line2));
15108
15425
  } catch {
15109
15426
  }
15110
15427
  }
@@ -15865,9 +16182,9 @@ var init_sse_bridge = __esm({
15865
16182
  buf += decoder.decode(value, { stream: true });
15866
16183
  let nl;
15867
16184
  while ((nl = buf.indexOf("\n")) >= 0) {
15868
- const line = buf.slice(0, nl);
16185
+ const line2 = buf.slice(0, nl);
15869
16186
  buf = buf.slice(nl + 1);
15870
- this.handleLine(taskId, line);
16187
+ this.handleLine(taskId, line2);
15871
16188
  }
15872
16189
  }
15873
16190
  } finally {
@@ -15878,16 +16195,16 @@ var init_sse_bridge = __esm({
15878
16195
  }
15879
16196
  }
15880
16197
  handleLine(taskId, rawLine) {
15881
- let line = rawLine.trim();
15882
- if (!line)
16198
+ let line2 = rawLine.trim();
16199
+ if (!line2)
15883
16200
  return;
15884
- if (line.startsWith("data:"))
15885
- line = line.slice(5).trim();
15886
- if (!line.startsWith("{"))
16201
+ if (line2.startsWith("data:"))
16202
+ line2 = line2.slice(5).trim();
16203
+ if (!line2.startsWith("{"))
15887
16204
  return;
15888
16205
  let json2;
15889
16206
  try {
15890
- json2 = JSON.parse(line);
16207
+ json2 = JSON.parse(line2);
15891
16208
  } catch {
15892
16209
  return;
15893
16210
  }
@@ -16009,14 +16326,14 @@ function detectTrailingQuestion2(text) {
16009
16326
  let inFence = false;
16010
16327
  let lastLine = null;
16011
16328
  for (const raw of text.split(/\r?\n/)) {
16012
- const line = raw.trim();
16013
- if (line.startsWith("```")) {
16329
+ const line2 = raw.trim();
16330
+ if (line2.startsWith("```")) {
16014
16331
  inFence = !inFence;
16015
16332
  continue;
16016
16333
  }
16017
- if (inFence || line === "")
16334
+ if (inFence || line2 === "")
16018
16335
  continue;
16019
- lastLine = line;
16336
+ lastLine = line2;
16020
16337
  }
16021
16338
  if (lastLine && lastLine.endsWith("?"))
16022
16339
  return lastLine;
@@ -16033,12 +16350,12 @@ function readLastAssistantText(transcriptPath) {
16033
16350
  const raw = readFileSync14(transcriptPath, "utf-8");
16034
16351
  const lines = raw.split(/\r?\n/);
16035
16352
  for (let i = lines.length - 1; i >= 0; i--) {
16036
- const line = lines[i].trim();
16037
- if (!line)
16353
+ const line2 = lines[i].trim();
16354
+ if (!line2)
16038
16355
  continue;
16039
16356
  let entry;
16040
16357
  try {
16041
- entry = JSON.parse(line);
16358
+ entry = JSON.parse(line2);
16042
16359
  } catch {
16043
16360
  continue;
16044
16361
  }
@@ -16072,8 +16389,8 @@ function resolveLastAssistantText(payload) {
16072
16389
  const derived = deriveTranscriptPath(p?.session_id, cwd);
16073
16390
  if (derived)
16074
16391
  candidates.push(derived);
16075
- for (const path45 of candidates) {
16076
- const text = readLastAssistantText(path45);
16392
+ for (const path46 of candidates) {
16393
+ const text = readLastAssistantText(path46);
16077
16394
  if (text != null)
16078
16395
  return text;
16079
16396
  }
@@ -16341,9 +16658,9 @@ function isQuotedLine2(raw) {
16341
16658
  return QUOTED_PREFIX_RE2.test(noAnsi);
16342
16659
  }
16343
16660
  function stripChrome2(raw) {
16344
- let line = raw.replace(/\[[0-9;]*m/g, "");
16345
- line = line.replace(/^[\s│┃▏▕|]+/, "").replace(/[\s│┃▏▕|]+$/, "");
16346
- const trimmed = line.trim();
16661
+ let line2 = raw.replace(/\[[0-9;]*m/g, "");
16662
+ line2 = line2.replace(/^[\s│┃▏▕|]+/, "").replace(/[\s│┃▏▕|]+$/, "");
16663
+ const trimmed = line2.trim();
16347
16664
  if (trimmed === "")
16348
16665
  return null;
16349
16666
  if (PURE_CHROME_RE2.test(trimmed))
@@ -16717,13 +17034,13 @@ function buildUserEnvelope(opts) {
16717
17034
  };
16718
17035
  }
16719
17036
  function writeLine(socketPath2, envelope, deps) {
16720
- const line = `${JSON.stringify(envelope)}
17037
+ const line2 = `${JSON.stringify(envelope)}
16721
17038
  `;
16722
- if (Buffer.byteLength(line, "utf8") > MAX_LINE_BYTES) {
17039
+ if (Buffer.byteLength(line2, "utf8") > MAX_LINE_BYTES) {
16723
17040
  return Promise.resolve({
16724
17041
  ok: false,
16725
17042
  reason: "transport",
16726
- error: `line exceeds the receiver's 1 MiB buffer cap (${Buffer.byteLength(line, "utf8")} bytes)`
17043
+ error: `line exceeds the receiver's 1 MiB buffer cap (${Buffer.byteLength(line2, "utf8")} bytes)`
16727
17044
  });
16728
17045
  }
16729
17046
  return new Promise((resolve4) => {
@@ -16743,7 +17060,7 @@ function writeLine(socketPath2, envelope, deps) {
16743
17060
  done({ ok: false, reason: "transport", error: `timeout after ${deps.timeoutMs ?? DEFAULT_TIMEOUT_MS}ms` });
16744
17061
  }, deps.timeoutMs ?? DEFAULT_TIMEOUT_MS);
16745
17062
  sock.on("connect", () => {
16746
- sock.write(line, () => {
17063
+ sock.write(line2, () => {
16747
17064
  clearTimeout(timer);
16748
17065
  try {
16749
17066
  sock.end();
@@ -16920,20 +17237,20 @@ var init_receipt_listener = __esm({
16920
17237
  buf += chunk;
16921
17238
  let nl;
16922
17239
  while ((nl = buf.indexOf("\n")) !== -1) {
16923
- const line = buf.slice(0, nl);
17240
+ const line2 = buf.slice(0, nl);
16924
17241
  buf = buf.slice(nl + 1);
16925
- this.dispatch(line);
17242
+ this.dispatch(line2);
16926
17243
  }
16927
17244
  });
16928
17245
  conn.on("error", () => {
16929
17246
  });
16930
17247
  }
16931
- dispatch(line) {
16932
- if (!line.trim())
17248
+ dispatch(line2) {
17249
+ if (!line2.trim())
16933
17250
  return;
16934
17251
  let f;
16935
17252
  try {
16936
- f = JSON.parse(line);
17253
+ f = JSON.parse(line2);
16937
17254
  } catch {
16938
17255
  this.deps.log?.(`claude-receipt: discarded non-JSON frame`);
16939
17256
  return;
@@ -16962,22 +17279,22 @@ var init_receipt_listener = __esm({
16962
17279
  });
16963
17280
 
16964
17281
  // packages/agents/dist/claude/api-key-approval.js
16965
- import fs22 from "fs";
17282
+ import fs23 from "fs";
16966
17283
  import os14 from "os";
16967
- import path25 from "path";
17284
+ import path26 from "path";
16968
17285
  function ensureClaudeApiKeyApproved(apiKey, opts = {}) {
16969
17286
  const suffix = apiKey.slice(-20);
16970
17287
  if (!suffix)
16971
17288
  return { changed: false, reason: "empty api key" };
16972
- const file = opts.claudeJsonPath ?? path25.join(os14.homedir(), ".claude.json");
17289
+ const file = opts.claudeJsonPath ?? path26.join(os14.homedir(), ".claude.json");
16973
17290
  const log = opts.log ?? (() => {
16974
17291
  });
16975
- if (!fs22.existsSync(file)) {
17292
+ if (!fs23.existsSync(file)) {
16976
17293
  return { changed: false, reason: "no ~/.claude.json yet \u2014 skipping routed-key pre-approval" };
16977
17294
  }
16978
17295
  let doc;
16979
17296
  try {
16980
- doc = JSON.parse(fs22.readFileSync(file, "utf8"));
17297
+ doc = JSON.parse(fs23.readFileSync(file, "utf8"));
16981
17298
  } catch {
16982
17299
  return {
16983
17300
  changed: false,
@@ -16999,11 +17316,11 @@ function ensureClaudeApiKeyApproved(apiKey, opts = {}) {
16999
17316
  };
17000
17317
  const tmp = `${file}.squadrant-tmp`;
17001
17318
  try {
17002
- fs22.writeFileSync(tmp, JSON.stringify(doc, null, 2) + "\n", { mode: fs22.statSync(file).mode & 511 });
17003
- fs22.renameSync(tmp, file);
17319
+ fs23.writeFileSync(tmp, JSON.stringify(doc, null, 2) + "\n", { mode: fs23.statSync(file).mode & 511 });
17320
+ fs23.renameSync(tmp, file);
17004
17321
  } catch (e) {
17005
17322
  try {
17006
- fs22.unlinkSync(tmp);
17323
+ fs23.unlinkSync(tmp);
17007
17324
  } catch {
17008
17325
  }
17009
17326
  return {
@@ -17112,10 +17429,10 @@ var init_http_channel = __esm({
17112
17429
  return cached;
17113
17430
  const directory = this.directoryFor?.(taskId);
17114
17431
  const createdAfterMs = this.createdAfterFor?.(taskId);
17115
- for (const path45 of ["/session?", "/api/session?"]) {
17432
+ for (const path46 of ["/session?", "/api/session?"]) {
17116
17433
  let res;
17117
17434
  try {
17118
- res = await this.request(`http://127.0.0.1:${port}${path45}`, { method: "GET" });
17435
+ res = await this.request(`http://127.0.0.1:${port}${path46}`, { method: "GET" });
17119
17436
  } catch {
17120
17437
  return void 0;
17121
17438
  }
@@ -17349,6 +17666,15 @@ async function cmuxHasInputGuards() {
17349
17666
  inputGuardsCache = major > 0 || minor >= 65;
17350
17667
  return inputGuardsCache;
17351
17668
  }
17669
+ function feedSessionOf(item) {
17670
+ const parts = item.workstream_id?.split(":");
17671
+ if (parts?.[0] !== "cmux-feed-v1" || !parts[2])
17672
+ return void 0;
17673
+ return Buffer.from(parts[2], "base64").toString("utf-8");
17674
+ }
17675
+ async function feedRpc(method, params) {
17676
+ return JSON.parse(await cmux(["rpc", method, JSON.stringify(params)]));
17677
+ }
17352
17678
  function parseList(output) {
17353
17679
  let parsed;
17354
17680
  try {
@@ -17391,13 +17717,13 @@ function parseDraftFromScreen(screen) {
17391
17717
  if (topHR === -1)
17392
17718
  return null;
17393
17719
  const inputLines = lines.slice(topHR + 1, bottomHR);
17394
- for (const line of inputLines) {
17720
+ for (const line2 of inputLines) {
17395
17721
  let extracted;
17396
- const boxMatch = line.match(/│\s*[>❯]\s+(.*?)\s*│/);
17722
+ const boxMatch = line2.match(/│\s*[>❯]\s+(.*?)\s*│/);
17397
17723
  if (boxMatch) {
17398
17724
  extracted = boxMatch[1].trim();
17399
17725
  } else {
17400
- const plainMatch = line.match(/^\s*[>❯]\s*(.*)$/);
17726
+ const plainMatch = line2.match(/^\s*[>❯]\s*(.*)$/);
17401
17727
  if (plainMatch)
17402
17728
  extracted = plainMatch[1].trim();
17403
17729
  }
@@ -17476,8 +17802,8 @@ function parseModalOptions(screen) {
17476
17802
  return null;
17477
17803
  const OPTION_RE3 = /^\s*(❯)?\s*(\d+)\.\s*(.*?)\s*$/;
17478
17804
  const options = [];
17479
- for (const line of lines.slice(topHR + 1, bottomHR)) {
17480
- const m = line.match(OPTION_RE3);
17805
+ for (const line2 of lines.slice(topHR + 1, bottomHR)) {
17806
+ const m = line2.match(OPTION_RE3);
17481
17807
  if (!m)
17482
17808
  continue;
17483
17809
  options.push({ index: Number(m[2]), label: m[3], highlighted: m[1] === "\u276F" });
@@ -17535,8 +17861,8 @@ function readInputBoxRaw(screen, opts) {
17535
17861
  if (topHR === -1)
17536
17862
  return null;
17537
17863
  const parts = [];
17538
- for (const line of lines.slice(topHR + 1, bottomHR)) {
17539
- let s = line.replace(/│/g, " ");
17864
+ for (const line2 of lines.slice(topHR + 1, bottomHR)) {
17865
+ let s = line2.replace(/│/g, " ");
17540
17866
  s = s.replace(/^\s*[>❯]\s?/, "");
17541
17867
  s = s.replace(/\s*[▌█▔▎▏]+\s*$/, "");
17542
17868
  parts.push(s);
@@ -17772,6 +18098,26 @@ function createCmuxDriver() {
17772
18098
  await cmux(["send-key", "--workspace", wsId, "--surface", surfaceId, "Enter"]);
17773
18099
  return { workspaceId: wsId, surfaceId, title: opts.title };
17774
18100
  },
18101
+ // #916: cmux >= 0.65 `surface.input_state` reads the render grid (incl. faint
18102
+ // spans) without touching the pane. The RPC needs a surface UUID, and an
18103
+ // unknown ref would silently fall back to the focused surface, so resolve the
18104
+ // ref through the tree first. Anything unexpected → undefined (old path).
18105
+ async inputState(pane) {
18106
+ try {
18107
+ if (!await cmuxHasInputGuards())
18108
+ return void 0;
18109
+ const tree = JSON.parse(await cmux(["tree", "--workspace", pane.workspaceId, "--json", "--id-format", "both"]));
18110
+ const id = tree.windows?.flatMap((w) => w.workspaces ?? []).flatMap((w) => w.panes ?? []).flatMap((p) => p.surfaces ?? []).find((s) => s.ref === pane.surfaceId)?.id;
18111
+ if (!id)
18112
+ return void 0;
18113
+ const r = JSON.parse(await cmux(["rpc", "surface.input_state", JSON.stringify({ surface_id: id })]));
18114
+ if (r.agent !== true)
18115
+ return "unknown";
18116
+ return r.state === "empty" || r.state === "draft" || r.state === "dialog" ? r.state : "unknown";
18117
+ } catch {
18118
+ return void 0;
18119
+ }
18120
+ },
17775
18121
  async sendToSurface(surface, text, opts) {
17776
18122
  const ws = surface.workspaceId;
17777
18123
  const sf = surface.surfaceId;
@@ -17798,6 +18144,17 @@ function createCmuxDriver() {
17798
18144
  `);
17799
18145
  }
17800
18146
  };
18147
+ if (opts?.agent !== "opencode") {
18148
+ const state = await this.inputState?.(surface);
18149
+ if (state === "draft")
18150
+ throw new DeferDelivery(null, "draft");
18151
+ if (state === "dialog")
18152
+ throw new DeferDelivery(null, "modal");
18153
+ if (state === "empty") {
18154
+ await deliver();
18155
+ return;
18156
+ }
18157
+ }
17801
18158
  let screen = "";
17802
18159
  try {
17803
18160
  screen = await cmux(["read-screen", "--workspace", ws, "--surface", sf]);
@@ -17876,6 +18233,39 @@ function createCmuxDriver() {
17876
18233
  args.push("--focus", "true");
17877
18234
  await cmux(args);
17878
18235
  },
18236
+ // Feed-backed structured answer (#918). cmux >= 0.65 only; any miss
18237
+ // (old cmux, no matching item, unsupported shape) is undefined so the
18238
+ // caller keeps the keystroke path.
18239
+ async findDialog(match) {
18240
+ if (!await cmuxHasInputGuards())
18241
+ return void 0;
18242
+ let items;
18243
+ try {
18244
+ items = (await feedRpc("feed.list", { pending_only: true })).items ?? [];
18245
+ } catch {
18246
+ return void 0;
18247
+ }
18248
+ const mine = items.filter((i) => match.agentSessionId ? feedSessionOf(i) === match.agentSessionId : !!match.cwd && i.cwd === match.cwd);
18249
+ if (mine.length !== 1 || !mine[0].request_id)
18250
+ return void 0;
18251
+ const item = mine[0];
18252
+ if (item.kind !== "question" || item.questions?.length !== 1)
18253
+ return void 0;
18254
+ const labels = (item.questions[0].options ?? []).map((o) => o.label ?? "");
18255
+ if (labels.length === 0)
18256
+ return void 0;
18257
+ return {
18258
+ id: item.request_id,
18259
+ options: labels.map((label, i) => ({ index: i + 1, label }))
18260
+ };
18261
+ },
18262
+ async answerDialog(dialog, answer) {
18263
+ const reply = answer.text ?? answer.label;
18264
+ if (!reply)
18265
+ return false;
18266
+ const res = await feedRpc("feed.question.reply", { request_id: dialog.id, selections: [reply] });
18267
+ return res.delivered === true;
18268
+ },
17879
18269
  async showPatch(opts) {
17880
18270
  const args = ["diff", "-", "--workspace", opts.workspaceId, "--layout", opts.layout ?? "split"];
17881
18271
  if (opts.title)
@@ -18064,13 +18454,13 @@ var init_notifiers = __esm({
18064
18454
  });
18065
18455
 
18066
18456
  // packages/workspaces/dist/workspaces/obsidian.js
18067
- import fs23 from "fs/promises";
18457
+ import fs24 from "fs/promises";
18068
18458
  import { existsSync as existsSync11 } from "fs";
18069
- import path26 from "path";
18459
+ import path27 from "path";
18070
18460
  function resolveInRoot(root, relative) {
18071
- const joined = path26.resolve(root, relative);
18072
- const normalized2 = path26.resolve(root) + path26.sep;
18073
- if (joined !== path26.resolve(root) && !joined.startsWith(normalized2)) {
18461
+ const joined = path27.resolve(root, relative);
18462
+ const normalized2 = path27.resolve(root) + path27.sep;
18463
+ if (joined !== path27.resolve(root) && !joined.startsWith(normalized2)) {
18074
18464
  throw new Error(`Path '${relative}' escapes workspace root`);
18075
18465
  }
18076
18466
  return joined;
@@ -18089,16 +18479,16 @@ function createObsidianDriver(scope) {
18089
18479
  };
18090
18480
  },
18091
18481
  async read(rel) {
18092
- return fs23.readFile(resolveInRoot(root, rel), "utf-8");
18482
+ return fs24.readFile(resolveInRoot(root, rel), "utf-8");
18093
18483
  },
18094
18484
  async write(rel, content) {
18095
18485
  const abs = resolveInRoot(root, rel);
18096
- await fs23.mkdir(path26.dirname(abs), { recursive: true });
18097
- await fs23.writeFile(abs, content);
18486
+ await fs24.mkdir(path27.dirname(abs), { recursive: true });
18487
+ await fs24.writeFile(abs, content);
18098
18488
  },
18099
18489
  async exists(rel) {
18100
18490
  try {
18101
- await fs23.access(resolveInRoot(root, rel));
18491
+ await fs24.access(resolveInRoot(root, rel));
18102
18492
  return true;
18103
18493
  } catch {
18104
18494
  return false;
@@ -18106,13 +18496,13 @@ function createObsidianDriver(scope) {
18106
18496
  },
18107
18497
  async list(rel) {
18108
18498
  try {
18109
- return await fs23.readdir(resolveInRoot(root, rel));
18499
+ return await fs24.readdir(resolveInRoot(root, rel));
18110
18500
  } catch {
18111
18501
  return [];
18112
18502
  }
18113
18503
  },
18114
18504
  async mkdir(rel) {
18115
- await fs23.mkdir(resolveInRoot(root, rel), { recursive: true });
18505
+ await fs24.mkdir(resolveInRoot(root, rel), { recursive: true });
18116
18506
  }
18117
18507
  };
18118
18508
  }
@@ -18266,18 +18656,18 @@ var init_events_bridge = __esm({
18266
18656
  this.buf += typeof chunk === "string" ? chunk : chunk.toString("utf-8");
18267
18657
  let nl;
18268
18658
  while ((nl = this.buf.indexOf("\n")) >= 0) {
18269
- const line = this.buf.slice(0, nl);
18659
+ const line2 = this.buf.slice(0, nl);
18270
18660
  this.buf = this.buf.slice(nl + 1);
18271
- this.handleLine(line);
18661
+ this.handleLine(line2);
18272
18662
  }
18273
18663
  }
18274
18664
  handleLine(rawLine) {
18275
- const line = rawLine.trim();
18276
- if (!line || line[0] !== "{")
18665
+ const line2 = rawLine.trim();
18666
+ if (!line2 || line2[0] !== "{")
18277
18667
  return;
18278
18668
  let f;
18279
18669
  try {
18280
- f = JSON.parse(line);
18670
+ f = JSON.parse(line2);
18281
18671
  } catch {
18282
18672
  return;
18283
18673
  }
@@ -18526,9 +18916,9 @@ function defaultListFiles(dir) {
18526
18916
  return [];
18527
18917
  }
18528
18918
  }
18529
- function defaultReadFile(path45) {
18919
+ function defaultReadFile(path46) {
18530
18920
  try {
18531
- return readFileSync17(path45, "utf-8");
18921
+ return readFileSync17(path46, "utf-8");
18532
18922
  } catch {
18533
18923
  return void 0;
18534
18924
  }
@@ -19021,16 +19411,16 @@ function extractDetail(sub, payload) {
19021
19411
  }
19022
19412
  return void 0;
19023
19413
  }
19024
- function defaultReadFile2(path45) {
19414
+ function defaultReadFile2(path46) {
19025
19415
  try {
19026
- return readFileSync18(path45, "utf-8");
19416
+ return readFileSync18(path46, "utf-8");
19027
19417
  } catch {
19028
19418
  return void 0;
19029
19419
  }
19030
19420
  }
19031
- function defaultWriteFile(path45, content) {
19032
- mkdirSync8(path45.replace(/\/[^/]+$/, ""), { recursive: true });
19033
- writeFileSync11(path45, content, "utf-8");
19421
+ function defaultWriteFile(path46, content) {
19422
+ mkdirSync8(path46.replace(/\/[^/]+$/, ""), { recursive: true });
19423
+ writeFileSync11(path46, content, "utf-8");
19034
19424
  }
19035
19425
  var CLAUDE_HOOK_EVENTS, DEFAULT_CLI_CMD, FOREIGN_AUTO_GATE_MARKER, SUBAGENT_MODEL_KEY, SMALL_FAST_MODEL_KEY, NativeHookSource;
19036
19426
  var init_native_hook_source = __esm({
@@ -19190,6 +19580,11 @@ async function readModalOptions(runtime, pane) {
19190
19580
  return parseModal(screen);
19191
19581
  }
19192
19582
  async function confirmedSendToPane(runtime, pane, message) {
19583
+ const native = await runtime.inputState?.(pane).catch(() => void 0);
19584
+ if (native === "dialog")
19585
+ return { delivered: false, blockedByModal: true };
19586
+ if (native === "draft")
19587
+ return { delivered: false };
19193
19588
  const preSendScreen = await runtime.readPaneScreen(pane) ?? "";
19194
19589
  if (hasModalOptionList2(preSendScreen)) {
19195
19590
  return { delivered: false, blockedByModal: true };
@@ -19459,9 +19854,9 @@ async function runRuntimeSend(arg1, arg2, opts, confirmOpts) {
19459
19854
  const resolved = resolveTarget(registry, config, target, !!opts.command);
19460
19855
  await needRef(resolved);
19461
19856
  const finalProject = opts.command ? config.commandName : target;
19462
- const { join: join37, dirname: dirname13 } = await import("path");
19857
+ const { join: join38, dirname: dirname13 } = await import("path");
19463
19858
  const { DEFAULT_CONFIG_PATH: DEFAULT_CONFIG_PATH2 } = await Promise.resolve().then(() => (init_dist(), dist_exports));
19464
- const stateRoot = join37(dirname13(DEFAULT_CONFIG_PATH2), "state");
19859
+ const stateRoot = join38(dirname13(DEFAULT_CONFIG_PATH2), "state");
19465
19860
  const seq2 = await appendCaptainMessage2({
19466
19861
  stateRoot,
19467
19862
  project: finalProject,
@@ -19584,7 +19979,7 @@ init_dist3();
19584
19979
  import { Command as Command40 } from "commander";
19585
19980
  import { existsSync as existsSync14, readFileSync as readFileSync21 } from "fs";
19586
19981
  import { fileURLToPath as fileURLToPath6 } from "url";
19587
- import { dirname as dirname12, join as join36 } from "path";
19982
+ import { dirname as dirname12, join as join37 } from "path";
19588
19983
  import { homedir as homedir21 } from "os";
19589
19984
 
19590
19985
  // packages/cli/src/commands/doctor.ts
@@ -19595,9 +19990,9 @@ init_dist();
19595
19990
  init_dist4();
19596
19991
  import { Command } from "commander";
19597
19992
  import { execSync as execSync7 } from "child_process";
19598
- import fs24 from "fs";
19993
+ import fs25 from "fs";
19599
19994
  import { stat } from "fs/promises";
19600
- import path27 from "path";
19995
+ import path28 from "path";
19601
19996
  import chalk3 from "chalk";
19602
19997
 
19603
19998
  // packages/cli/src/commands/health-view.ts
@@ -19699,7 +20094,7 @@ function settingsHaveAgentTeams() {
19699
20094
  try {
19700
20095
  const home = process.env.HOME || "";
19701
20096
  const settings = JSON.parse(
19702
- fs24.readFileSync(`${home}/.claude/settings.json`, "utf-8")
20097
+ fs25.readFileSync(`${home}/.claude/settings.json`, "utf-8")
19703
20098
  );
19704
20099
  return settings?.env?.CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS === "1";
19705
20100
  } catch {
@@ -19710,7 +20105,7 @@ function pluginInstalled(pluginKey) {
19710
20105
  try {
19711
20106
  const home = process.env.HOME || "";
19712
20107
  const plugins = JSON.parse(
19713
- fs24.readFileSync(
20108
+ fs25.readFileSync(
19714
20109
  `${home}/.claude/plugins/installed_plugins.json`,
19715
20110
  "utf-8"
19716
20111
  )
@@ -19734,9 +20129,9 @@ function tryGetVersion(cmd) {
19734
20129
  }
19735
20130
  function candidateGlobalInstalls(roots) {
19736
20131
  const out = [];
19737
- if (roots.npm) out.push({ manager: "npm", packageJsonPath: path27.join(roots.npm, "squadrant", "package.json") });
19738
- if (roots.pnpm) out.push({ manager: "pnpm", packageJsonPath: path27.join(roots.pnpm, "squadrant", "package.json") });
19739
- if (roots.yarn) out.push({ manager: "yarn", packageJsonPath: path27.join(roots.yarn, "node_modules", "squadrant", "package.json") });
20132
+ if (roots.npm) out.push({ manager: "npm", packageJsonPath: path28.join(roots.npm, "squadrant", "package.json") });
20133
+ if (roots.pnpm) out.push({ manager: "pnpm", packageJsonPath: path28.join(roots.pnpm, "squadrant", "package.json") });
20134
+ if (roots.yarn) out.push({ manager: "yarn", packageJsonPath: path28.join(roots.yarn, "node_modules", "squadrant", "package.json") });
19740
20135
  return out;
19741
20136
  }
19742
20137
  function findInstalledSquadrants(candidates, readVersion) {
@@ -19756,7 +20151,7 @@ ${lines.join("\n")}
19756
20151
  }
19757
20152
  function readPackageVersion(packageJsonPath) {
19758
20153
  try {
19759
- const pkg2 = JSON.parse(fs24.readFileSync(packageJsonPath, "utf-8"));
20154
+ const pkg2 = JSON.parse(fs25.readFileSync(packageJsonPath, "utf-8"));
19760
20155
  return typeof pkg2.version === "string" ? pkg2.version : null;
19761
20156
  } catch {
19762
20157
  return null;
@@ -19821,7 +20216,7 @@ var doctorCommand = new Command("doctor").description("Check system health and p
19821
20216
  ));
19822
20217
  checkOptional(
19823
20218
  "Obsidian installed",
19824
- commandExists("obsidian") || fs24.existsSync("/Applications/Obsidian.app"),
20219
+ commandExists("obsidian") || fs25.existsSync("/Applications/Obsidian.app"),
19825
20220
  "viewer for the hub vault; the vault is plain Markdown",
19826
20221
  "Install from: https://obsidian.md"
19827
20222
  );
@@ -19918,7 +20313,7 @@ var doctorCommand = new Command("doctor").description("Check system health and p
19918
20313
  const emitter = projectionRegistry.get(name);
19919
20314
  const [userDest] = emitter.destinations("user");
19920
20315
  if (!userDest) continue;
19921
- const dir = path27.dirname(userDest.path);
20316
+ const dir = path28.dirname(userDest.path);
19922
20317
  let status;
19923
20318
  try {
19924
20319
  await stat(dir);
@@ -19939,7 +20334,7 @@ var doctorCommand = new Command("doctor").description("Check system health and p
19939
20334
  results.push(
19940
20335
  check(
19941
20336
  "Squadrant config exists",
19942
- fs24.existsSync(
20337
+ fs25.existsSync(
19943
20338
  process.env.SQUADRANT_CONFIG || `${process.env.HOME}/.config/squadrant/config.json`
19944
20339
  ),
19945
20340
  "Run: squadrant init"
@@ -20023,8 +20418,8 @@ init_dist();
20023
20418
  init_dist4();
20024
20419
  init_dist();
20025
20420
  import { Command as Command2 } from "commander";
20026
- import fs25 from "fs";
20027
- import path28 from "path";
20421
+ import fs26 from "fs";
20422
+ import path29 from "path";
20028
20423
  import os15 from "os";
20029
20424
  import readline from "readline";
20030
20425
  import chalk4 from "chalk";
@@ -20275,22 +20670,22 @@ function detectClaudeAuth(probe = {}) {
20275
20670
  // packages/cli/src/commands/init.ts
20276
20671
  init_dist3();
20277
20672
  function findPackageRoot() {
20278
- let dir = path28.dirname(new URL(import.meta.url).pathname);
20673
+ let dir = path29.dirname(new URL(import.meta.url).pathname);
20279
20674
  while (dir !== "/") {
20280
- if (fs25.existsSync(path28.join(dir, "package.json"))) return dir;
20281
- dir = path28.dirname(dir);
20675
+ if (fs26.existsSync(path29.join(dir, "package.json"))) return dir;
20676
+ dir = path29.dirname(dir);
20282
20677
  }
20283
20678
  return process.cwd();
20284
20679
  }
20285
20680
  function copyDirRecursive(src, dest) {
20286
- fs25.mkdirSync(dest, { recursive: true });
20287
- for (const entry of fs25.readdirSync(src, { withFileTypes: true })) {
20288
- const srcPath = path28.join(src, entry.name);
20289
- const destPath = path28.join(dest, entry.name);
20681
+ fs26.mkdirSync(dest, { recursive: true });
20682
+ for (const entry of fs26.readdirSync(src, { withFileTypes: true })) {
20683
+ const srcPath = path29.join(src, entry.name);
20684
+ const destPath = path29.join(dest, entry.name);
20290
20685
  if (entry.isDirectory()) {
20291
20686
  copyDirRecursive(srcPath, destPath);
20292
20687
  } else {
20293
- fs25.copyFileSync(srcPath, destPath);
20688
+ fs26.copyFileSync(srcPath, destPath);
20294
20689
  }
20295
20690
  }
20296
20691
  }
@@ -20332,7 +20727,7 @@ function warnIfNoAnthropic(preset, auth) {
20332
20727
  var initCommand = new Command2("init").description("Guided first-time setup: provider, hub vault, agents, plugins, projects (re-run-safe)").option("--hub <path>", "Hub vault path", "~/squadrant-hub").option("--preset <id>", "provider preset: a|b|c (non-interactive; d accepted as a deprecated alias for c)").action(async (opts) => {
20333
20728
  const hubPath = resolveHome(opts.hub);
20334
20729
  const pkgRoot = findPackageRoot();
20335
- const configDir = path28.join(os15.homedir(), ".config", "squadrant");
20730
+ const configDir = path29.join(os15.homedir(), ".config", "squadrant");
20336
20731
  const isTTY = process.stdin.isTTY === true;
20337
20732
  console.log(chalk4.bold("\nSquadrant Init\n"));
20338
20733
  let explicitPreset;
@@ -20370,8 +20765,8 @@ var initCommand = new Command2("init").description("Guided first-time setup: pro
20370
20765
  }
20371
20766
  const wsRegistry = new WorkspaceRegistry({ obsidian: createObsidianDriver });
20372
20767
  try {
20373
- if (fs25.existsSync(DEFAULT_CONFIG_PATH)) {
20374
- const existing = JSON.parse(fs25.readFileSync(DEFAULT_CONFIG_PATH, "utf-8"));
20768
+ if (fs26.existsSync(DEFAULT_CONFIG_PATH)) {
20769
+ const existing = JSON.parse(fs26.readFileSync(DEFAULT_CONFIG_PATH, "utf-8"));
20375
20770
  wsRegistry.get(existing.workspace ?? "obsidian");
20376
20771
  }
20377
20772
  } catch (err) {
@@ -20379,7 +20774,7 @@ var initCommand = new Command2("init").description("Guided first-time setup: pro
20379
20774
  return;
20380
20775
  }
20381
20776
  stepHeader(1, 5, "Hub vault");
20382
- const configExists = fs25.existsSync(DEFAULT_CONFIG_PATH);
20777
+ const configExists = fs26.existsSync(DEFAULT_CONFIG_PATH);
20383
20778
  let config;
20384
20779
  if (configExists) {
20385
20780
  console.log(chalk4.yellow(" \u26A0 Config already exists, skipping creation"));
@@ -20417,37 +20812,37 @@ var initCommand = new Command2("init").description("Guided first-time setup: pro
20417
20812
  saveConfig(config);
20418
20813
  console.log(chalk4.green(` \u2714 Config updated at ${DEFAULT_CONFIG_PATH}`));
20419
20814
  }
20420
- const hubTemplate = path28.join(pkgRoot, "obsidian", "hub");
20421
- if (fs25.existsSync(hubPath)) {
20815
+ const hubTemplate = path29.join(pkgRoot, "obsidian", "hub");
20816
+ if (fs26.existsSync(hubPath)) {
20422
20817
  console.log(chalk4.yellow(` \u26A0 Hub vault already exists at ${hubPath}`));
20423
- } else if (fs25.existsSync(hubTemplate)) {
20818
+ } else if (fs26.existsSync(hubTemplate)) {
20424
20819
  copyDirRecursive(hubTemplate, hubPath);
20425
20820
  console.log(chalk4.green(` \u2714 Hub vault scaffolded at ${hubPath}`));
20426
20821
  } else {
20427
- fs25.mkdirSync(hubPath, { recursive: true });
20822
+ fs26.mkdirSync(hubPath, { recursive: true });
20428
20823
  console.log(chalk4.yellow(` \u26A0 Hub template not found; created empty directory at ${hubPath}`));
20429
20824
  }
20430
- const hubDashboardSrc = path28.join(pkgRoot, "obsidian", "hub", "dashboard.md");
20431
- const hubDashboardDest = path28.join(hubPath, "dashboard.md");
20432
- if (fs25.existsSync(hubDashboardSrc)) {
20433
- fs25.copyFileSync(hubDashboardSrc, hubDashboardDest);
20825
+ const hubDashboardSrc = path29.join(pkgRoot, "obsidian", "hub", "dashboard.md");
20826
+ const hubDashboardDest = path29.join(hubPath, "dashboard.md");
20827
+ if (fs26.existsSync(hubDashboardSrc)) {
20828
+ fs26.copyFileSync(hubDashboardSrc, hubDashboardDest);
20434
20829
  console.log(chalk4.green(` \u2714 Dashboard refreshed`));
20435
20830
  }
20436
- fs25.mkdirSync(path28.join(hubPath, "projects"), { recursive: true });
20831
+ fs26.mkdirSync(path29.join(hubPath, "projects"), { recursive: true });
20437
20832
  ensureRuntimeSynced({ sourceRoot: pkgRoot, runtimeRoot: configDir });
20438
20833
  console.log(chalk4.green(` \u2714 Runtime assets synced to ${configDir}`));
20439
20834
  stepHeader(2, 5, "Agent + projection setup");
20440
- const settingsPath = path28.join(os15.homedir(), ".claude", "settings.json");
20835
+ const settingsPath = path29.join(os15.homedir(), ".claude", "settings.json");
20441
20836
  try {
20442
20837
  let settings = {};
20443
- if (fs25.existsSync(settingsPath)) {
20444
- settings = JSON.parse(fs25.readFileSync(settingsPath, "utf-8"));
20838
+ if (fs26.existsSync(settingsPath)) {
20839
+ settings = JSON.parse(fs26.readFileSync(settingsPath, "utf-8"));
20445
20840
  }
20446
20841
  const env = settings.env || {};
20447
20842
  if (env.CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS !== "1") {
20448
20843
  settings.env = { ...env, CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS: "1" };
20449
- fs25.mkdirSync(path28.dirname(settingsPath), { recursive: true });
20450
- fs25.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
20844
+ fs26.mkdirSync(path29.dirname(settingsPath), { recursive: true });
20845
+ fs26.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
20451
20846
  console.log(chalk4.green(" \u2714 Agent Teams enabled in ~/.claude/settings.json"));
20452
20847
  } else {
20453
20848
  console.log(chalk4.green(" \u2714 Agent Teams already enabled"));
@@ -20500,7 +20895,7 @@ var initCommand = new Command2("init").description("Guided first-time setup: pro
20500
20895
  chalk4.cyan(" Absolute path to your first project (Enter to skip): ")
20501
20896
  );
20502
20897
  if (projectPath) {
20503
- const projectName = path28.basename(projectPath);
20898
+ const projectName = path29.basename(projectPath);
20504
20899
  console.log(chalk4.bold(`
20505
20900
  Run this to register it:`));
20506
20901
  console.log(chalk4.cyan(` squadrant projects add ${projectName} ${projectPath}
@@ -20528,8 +20923,8 @@ var initCommand = new Command2("init").description("Guided first-time setup: pro
20528
20923
  init_dist();
20529
20924
  init_dist2();
20530
20925
  import { Command as Command3 } from "commander";
20531
- import fs26 from "fs";
20532
- import path29 from "path";
20926
+ import fs27 from "fs";
20927
+ import path30 from "path";
20533
20928
  import chalk5 from "chalk";
20534
20929
  function restartAfterProjectsAdd(opts) {
20535
20930
  const doRestart = opts.doRestart ?? restartDaemonIfRunning;
@@ -20541,22 +20936,22 @@ function restartAfterProjectsAdd(opts) {
20541
20936
  }
20542
20937
  }
20543
20938
  function findPackageRoot2() {
20544
- let dir = path29.dirname(new URL(import.meta.url).pathname);
20939
+ let dir = path30.dirname(new URL(import.meta.url).pathname);
20545
20940
  while (dir !== "/") {
20546
- if (fs26.existsSync(path29.join(dir, "package.json"))) return dir;
20547
- dir = path29.dirname(dir);
20941
+ if (fs27.existsSync(path30.join(dir, "package.json"))) return dir;
20942
+ dir = path30.dirname(dir);
20548
20943
  }
20549
20944
  return process.cwd();
20550
20945
  }
20551
20946
  function copyDirRecursive2(src, dest) {
20552
- fs26.mkdirSync(dest, { recursive: true });
20553
- for (const entry of fs26.readdirSync(src, { withFileTypes: true })) {
20554
- const srcPath = path29.join(src, entry.name);
20555
- const destPath = path29.join(dest, entry.name);
20947
+ fs27.mkdirSync(dest, { recursive: true });
20948
+ for (const entry of fs27.readdirSync(src, { withFileTypes: true })) {
20949
+ const srcPath = path30.join(src, entry.name);
20950
+ const destPath = path30.join(dest, entry.name);
20556
20951
  if (entry.isDirectory()) {
20557
20952
  copyDirRecursive2(srcPath, destPath);
20558
20953
  } else {
20559
- fs26.copyFileSync(srcPath, destPath);
20954
+ fs27.copyFileSync(srcPath, destPath);
20560
20955
  }
20561
20956
  }
20562
20957
  }
@@ -20592,7 +20987,7 @@ var addCmd = new Command3("add").description("Register a project").argument("<na
20592
20987
  process.exit(1);
20593
20988
  }
20594
20989
  const resolvedPath = resolveHome(projectPath);
20595
- if (!fs26.existsSync(path29.join(resolvedPath, ".git"))) {
20990
+ if (!fs27.existsSync(path30.join(resolvedPath, ".git"))) {
20596
20991
  console.log(chalk5.yellow(`
20597
20992
  \u26A0 No .git found at ${resolvedPath}. Make sure this is the project root, not a parent directory.
20598
20993
  `));
@@ -20645,7 +21040,7 @@ var addCmd = new Command3("add").description("Register a project").argument("<na
20645
21040
  \u26A0 Group '${group}' already has '${primary[0]}' as primary. Overriding.`));
20646
21041
  }
20647
21042
  }
20648
- const spokeVault = opts.spoke ? resolveHome(opts.spoke) : path29.join(config.hubVault, "spokes", name);
21043
+ const spokeVault = opts.spoke ? resolveHome(opts.spoke) : path30.join(config.hubVault, "spokes", name);
20649
21044
  const project = {
20650
21045
  path: resolvedPath,
20651
21046
  captainName,
@@ -20660,20 +21055,20 @@ var addCmd = new Command3("add").description("Register a project").argument("<na
20660
21055
  \u2714 Project '${name}' registered`));
20661
21056
  restartAfterProjectsAdd({ noRestart: opts.restart === false });
20662
21057
  const pkgRoot = findPackageRoot2();
20663
- const spokeTemplate = path29.join(pkgRoot, "obsidian", "spoke");
20664
- if (fs26.existsSync(spokeVault)) {
21058
+ const spokeTemplate = path30.join(pkgRoot, "obsidian", "spoke");
21059
+ if (fs27.existsSync(spokeVault)) {
20665
21060
  console.log(chalk5.yellow(` \u26A0 Spoke vault already exists at ${spokeVault}, skipping scaffold`));
20666
- } else if (fs26.existsSync(spokeTemplate)) {
21061
+ } else if (fs27.existsSync(spokeTemplate)) {
20667
21062
  copyDirRecursive2(spokeTemplate, spokeVault);
20668
- const statusPath = path29.join(spokeVault, "status.md");
20669
- if (fs26.existsSync(statusPath)) {
20670
- const content = fs26.readFileSync(statusPath, "utf-8");
21063
+ const statusPath = path30.join(spokeVault, "status.md");
21064
+ if (fs27.existsSync(statusPath)) {
21065
+ const content = fs27.readFileSync(statusPath, "utf-8");
20671
21066
  const updated = content.replace(/^project: unnamed/m, `project: ${name}`);
20672
- fs26.writeFileSync(statusPath, updated);
21067
+ fs27.writeFileSync(statusPath, updated);
20673
21068
  }
20674
21069
  console.log(chalk5.green(` \u2714 Spoke vault scaffolded at ${spokeVault}`));
20675
21070
  } else {
20676
- fs26.mkdirSync(spokeVault, { recursive: true });
21071
+ fs27.mkdirSync(spokeVault, { recursive: true });
20677
21072
  console.log(chalk5.yellow(` \u26A0 Spoke template not found; created empty dir at ${spokeVault}`));
20678
21073
  }
20679
21074
  console.log("");
@@ -20742,10 +21137,10 @@ init_dist3();
20742
21137
  init_dist();
20743
21138
  import { Command as Command5 } from "commander";
20744
21139
  import { execSync as execSync9 } from "child_process";
20745
- import path30 from "path";
21140
+ import path31 from "path";
20746
21141
  import os16 from "os";
20747
21142
  import chalk7 from "chalk";
20748
- var TEMPLATES_DIR2 = path30.join(os16.homedir(), ".config", "squadrant", "templates");
21143
+ var TEMPLATES_DIR2 = path31.join(os16.homedir(), ".config", "squadrant", "templates");
20749
21144
  var TASK_PROMPTS = {
20750
21145
  briefing: "Run your daily briefing using the squadrant:command-ops skill. Read all spoke handoffs, yesterday's logs, current status; produce a concise cross-project briefing; save to {hubVault}/daily-logs/YYYY-MM-DD.md; then exit.",
20751
21146
  "learnings-review": "Run a learnings review using the squadrant:command-ops skill. Scan {spokeVault}/learnings across all projects, identify cross-project patterns, propose captured-skill or fix actions, and exit when done.",
@@ -20778,7 +21173,7 @@ async function runCommandSpawn(input) {
20778
21173
  if (!agent) {
20779
21174
  throw new Error(`Unknown agent '${agentName}'. Known: claude, codex, gemini, opencode.`);
20780
21175
  }
20781
- const promptFile = path30.join(TEMPLATES_DIR2, `command.${agent.templateSuffix}.md`);
21176
+ const promptFile = path31.join(TEMPLATES_DIR2, `command.${agent.templateSuffix}.md`);
20782
21177
  const cliCommand = agent.buildCommand({
20783
21178
  prompt,
20784
21179
  workdir: process.cwd(),
@@ -20807,9 +21202,9 @@ init_dist4();
20807
21202
  init_dist3();
20808
21203
  init_dist2();
20809
21204
  import { Command as Command10 } from "commander";
20810
- import chalk10 from "chalk";
20811
- import { createServer as createServer4, connect as netConnect } from "net";
20812
- import { randomUUID as randomUUID6 } from "crypto";
21205
+ import chalk11 from "chalk";
21206
+ import { createServer as createServer5, connect as netConnect3 } from "net";
21207
+ import { randomUUID as randomUUID8 } from "crypto";
20813
21208
 
20814
21209
  // packages/cli/src/commands/crew-control.ts
20815
21210
  init_dist2();
@@ -20834,10 +21229,10 @@ function tailLines(text, maxLines = 40, maxBytes = 4096) {
20834
21229
  if (Buffer.byteLength(result, "utf-8") > maxBytes) {
20835
21230
  const truncated = [];
20836
21231
  let bytes = 0;
20837
- for (const line of kept) {
20838
- const lineBytes = Buffer.byteLength(line, "utf-8") + 1;
21232
+ for (const line2 of kept) {
21233
+ const lineBytes = Buffer.byteLength(line2, "utf-8") + 1;
20839
21234
  if (bytes + lineBytes > maxBytes) break;
20840
- truncated.push(line);
21235
+ truncated.push(line2);
20841
21236
  bytes += lineBytes;
20842
21237
  }
20843
21238
  result = truncated.join("\n");
@@ -21567,6 +21962,131 @@ function addControlPlaneCrewCommands(crew) {
21567
21962
  var crewControlCommand = new Command9("crew").description("Dispatch and track crew via the squadrant control plane");
21568
21963
  addControlPlaneCrewCommands(crewControlCommand);
21569
21964
 
21965
+ // packages/cli/src/lib/first-turn-peer.ts
21966
+ init_dist3();
21967
+ init_dist2();
21968
+ import { randomUUID as randomUUID7 } from "crypto";
21969
+ import { connect as netConnect2 } from "net";
21970
+
21971
+ // packages/cli/src/lib/captain-channel-factory.ts
21972
+ init_dist3();
21973
+ init_dist2();
21974
+ import { createServer as createServer4, connect as netConnect } from "net";
21975
+ import fs28 from "fs";
21976
+ import { join as join28 } from "path";
21977
+ import { randomUUID as randomUUID6 } from "crypto";
21978
+ import chalk10 from "chalk";
21979
+ var shared;
21980
+ var registryEntryPath = () => join28(CLAUDE_SESSIONS_DIR, `${process.pid}.json`);
21981
+ function unregisterSenderIdentity() {
21982
+ try {
21983
+ fs28.unlinkSync(registryEntryPath());
21984
+ } catch {
21985
+ }
21986
+ }
21987
+ function registerSenderIdentity(socketPath2) {
21988
+ try {
21989
+ unregisterSenderIdentity();
21990
+ fs28.mkdirSync(CLAUDE_SESSIONS_DIR, { recursive: true });
21991
+ fs28.writeFileSync(
21992
+ registryEntryPath(),
21993
+ JSON.stringify({
21994
+ pid: process.pid,
21995
+ sessionId: randomUUID6(),
21996
+ name: "squadrantd",
21997
+ messagingSocketPath: socketPath2,
21998
+ kind: "daemon",
21999
+ peerProtocol: 1
22000
+ })
22001
+ );
22002
+ process.on("exit", unregisterSenderIdentity);
22003
+ } catch {
22004
+ }
22005
+ }
22006
+ async function sharedReceiptListener() {
22007
+ if (shared) return shared;
22008
+ ensureSocksDir();
22009
+ const socketPath2 = `${CC_SOCKS_DIR}/squadrantd-${process.pid}.sock`;
22010
+ const listener = new ClaudeReceiptListener({
22011
+ socketPath: socketPath2,
22012
+ createServer: (h) => createServer4(h),
22013
+ // A UDS path is not cleaned up when a process is killed, so our own leftover
22014
+ // must never be the reason we refuse to start.
22015
+ unlinkStale: (p) => {
22016
+ try {
22017
+ fs28.unlinkSync(p);
22018
+ } catch {
22019
+ }
22020
+ },
22021
+ log: (m) => console.error(chalk10.dim(m))
22022
+ });
22023
+ await listener.start();
22024
+ registerSenderIdentity(socketPath2);
22025
+ shared = listener;
22026
+ return shared;
22027
+ }
22028
+ function captainSessionIdFor(taskId) {
22029
+ return readClaudeStatusBySocketPath(captainSocketPath(taskId))?.sessionId;
22030
+ }
22031
+ async function buildCaptainChannel() {
22032
+ const receipts = await sharedReceiptListener();
22033
+ return new ClaudePeerChannel({
22034
+ // The port's taskId IS the project name for captains.
22035
+ socketPathFor: (taskId) => captainSocketPath(taskId),
22036
+ sessionIdFor: captainSessionIdFor,
22037
+ // Captains are identified in the registry by their cwd (the project path).
22038
+ // Resolve by the socket path squadrant chose at launch, NOT by cwd: a captain
22039
+ // in /tmp/x registers cwd "/private/tmp/x" on macOS, so cwd matching silently
22040
+ // missed and every captain ping reported accepted-unconfirmed.
22041
+ statusFor: (taskId) => readClaudeStatusBySocketPath(captainSocketPath(taskId)),
22042
+ wire: (p, e) => writeLine(p, e, { connect: (path46) => netConnect(path46) }),
22043
+ receipts,
22044
+ newMsgId: () => randomUUID6(),
22045
+ sleep: (ms) => new Promise((r) => setTimeout(r, ms)),
22046
+ log: (m) => console.error(chalk10.dim(m))
22047
+ });
22048
+ }
22049
+ async function buildCaptainChannels(opts) {
22050
+ const claude = await buildCaptainChannel();
22051
+ const opencode = new OpencodeHttpChannel({
22052
+ portFor: (project) => readCaptainAddress(opts.stateRoot, project)?.port,
22053
+ sessionFor: (project) => readCaptainAddress(opts.stateRoot, project)?.sessionId
22054
+ });
22055
+ return {
22056
+ channels: { claude, opencode },
22057
+ agentFor: (project) => resolveCaptainAgent(opts.stateRoot, project, opts.configAgent)
22058
+ };
22059
+ }
22060
+ function resolveCaptainAgent(stateRoot, project, configAgent) {
22061
+ return readCaptainAddress(stateRoot, project)?.agent ?? configAgent;
22062
+ }
22063
+
22064
+ // packages/cli/src/lib/first-turn-peer.ts
22065
+ async function sendClaudeFirstTurnViaPeer(runtime, o, getTaskRecord) {
22066
+ const receipts = await sharedReceiptListener();
22067
+ const channel = new ClaudePeerChannel({
22068
+ socketPathFor: () => o.messagingSocketPath,
22069
+ sessionIdFor: () => readClaudeStatusBySocketPath(o.messagingSocketPath)?.sessionId,
22070
+ statusFor: () => readClaudeStatusBySocketPath(o.messagingSocketPath),
22071
+ wire: (p, e) => writeLine(p, e, { connect: (path46) => netConnect2(path46) }),
22072
+ receipts,
22073
+ newMsgId: () => randomUUID7(),
22074
+ sleep: (ms) => new Promise((r) => setTimeout(r, ms)),
22075
+ // The UserPromptSubmit hook is the real receipt; don't hold spawn for the
22076
+ // default 4s inferred-flip window.
22077
+ confirmWindowMs: 1500
22078
+ });
22079
+ return deliverFirstTurnViaPeer(o.message, {
22080
+ statusOf: () => readClaudeStatusBySocketPath(o.messagingSocketPath),
22081
+ readScreen: async () => await runtime.readPaneScreen(o.pane) ?? "",
22082
+ pressKey: (key) => runtime.sendKeyToPane(o.pane, key),
22083
+ send: (m) => channel.send(o.taskId, m),
22084
+ isConfirmed: async () => !!(await getTaskRecord())?.firstTurnConfirmedAt,
22085
+ sleep: (ms) => new Promise((r) => setTimeout(r, ms)),
22086
+ now: () => Date.now()
22087
+ });
22088
+ }
22089
+
21570
22090
  // packages/cli/src/lib/model-guard.ts
21571
22091
  var ANTHROPIC_MODEL_PREFIX = "anthropic/";
21572
22092
  var BARE_CLAUDE_MODEL_PREFIX = "claude-";
@@ -21585,8 +22105,8 @@ function anthropicRefusalMessage(role, workspaceName, agentName, model) {
21585
22105
 
21586
22106
  // packages/cli/src/commands/crew.ts
21587
22107
  async function fetchRouterCredentials(project, backend, deps) {
21588
- const log = deps.log ?? ((m) => console.log(chalk10.dim(m)));
21589
- const warn = deps.warn ?? ((m) => console.error(chalk10.yellow(m)));
22108
+ const log = deps.log ?? ((m) => console.log(chalk11.dim(m)));
22109
+ const warn = deps.warn ?? ((m) => console.error(chalk11.yellow(m)));
21590
22110
  const creds = await deps.call(buildRouterCredentialsRequest(project, backend));
21591
22111
  if (creds.backend === "direct" && creds.apiKey) {
21592
22112
  const approve = deps.approveKey ?? ensureClaudeApiKeyApproved;
@@ -21622,6 +22142,11 @@ async function runCrewSpawn2(input) {
21622
22142
  writeOpencodeConfig: writePerCrewOpencodeConfig,
21623
22143
  writeRouterSettings,
21624
22144
  sendFirstTurn: (pane, firstTurn, preLaunchScreen, opts) => sendFirstTurnWhenReady(runtime, pane, firstTurn, preLaunchScreen, opts),
22145
+ // #917: claude crews get their first turn over the peer socket when the
22146
+ // claude control channel is `on`; anything else keeps the pane path.
22147
+ ...resolveControlChannelMode(config.defaults.controlChannel, "claude") === "on" ? {
22148
+ sendFirstTurnPeer: (o) => sendClaudeFirstTurnViaPeer(runtime, o, async () => await squadrantdCall(buildStatusRequest(o.project, o.taskId)).catch(() => void 0))
22149
+ } : {},
21625
22150
  getFreePort,
21626
22151
  sendCodexFirstTurn,
21627
22152
  // #466: wire delivery confirmation so the daemon stamps firstTurnConfirmedAt.
@@ -21634,25 +22159,25 @@ async function runCrewSpawn2(input) {
21634
22159
  getTaskRecord: async (p, id) => await squadrantdCall(buildStatusRequest(p, id)).catch(() => void 0),
21635
22160
  isAgentInstalled: (name) => commandExists(name),
21636
22161
  onRouteSkipped: (route, fallback) => console.log(
21637
- chalk10.dim(`routed: tier=${route.tier} \u2192 ${route.agent} (not installed) \u2192 ${fallback}`)
22162
+ chalk11.dim(`routed: tier=${route.tier} \u2192 ${route.agent} (not installed) \u2192 ${fallback}`)
21638
22163
  ),
21639
22164
  onRouted: (route) => console.log(
21640
- chalk10.dim(
22165
+ chalk11.dim(
21641
22166
  `routed: tier=${route.tier} \u2192 ${route.agent}${route.model ? `/${route.model}` : ""} (rule: "${route.matchedRule}")`
21642
22167
  )
21643
22168
  ),
21644
- onBaseResolved: (base) => console.log(chalk10.dim(`base: ${base}`)),
22169
+ onBaseResolved: (base) => console.log(chalk11.dim(`base: ${base}`)),
21645
22170
  // #627 item B: warn (don't block) when a fallback crew silently resolves to
21646
22171
  // an Anthropic model — less catastrophic than a captain on the same path,
21647
22172
  // and more often intentional, so it just needs to be visible.
21648
22173
  onBackendResolved: ({ backend }) => {
21649
- if (backend !== "native") console.log(chalk10.dim(`backend: ${backend}`));
22174
+ if (backend !== "native") console.log(chalk11.dim(`backend: ${backend}`));
21650
22175
  },
21651
22176
  onModelResolved: ({ agentName, model }) => {
21652
22177
  const effectiveModel = model ?? (agentName === "opencode" ? readGlobalOpencodeModel() : void 0);
21653
22178
  if (isBlockedFallback(agentName, effectiveModel)) {
21654
22179
  console.error(
21655
- chalk10.yellow(
22180
+ chalk11.yellow(
21656
22181
  ` \u26A0 ${anthropicFallbackMessage(agentName, effectiveModel)} (crew \u2014 not blocked; pass --model to pin a different provider)`
21657
22182
  )
21658
22183
  );
@@ -21666,8 +22191,8 @@ async function runCrewSend2(project, name, message, opts) {
21666
22191
  let tasks = [];
21667
22192
  const receipts = new ClaudeReceiptListener({
21668
22193
  socketPath: "/tmp/cc-socks/squadrantd.sock",
21669
- createServer: (h) => createServer4(h),
21670
- log: (m) => console.error(chalk10.dim(m))
22194
+ createServer: (h) => createServer5(h),
22195
+ log: (m) => console.error(chalk11.dim(m))
21671
22196
  });
21672
22197
  await receipts.start();
21673
22198
  const controlChannels = [
@@ -21681,17 +22206,17 @@ async function runCrewSend2(project, name, message, opts) {
21681
22206
  // a prior crew's session. Gate on the crew's createdAt so a stale session
21682
22207
  // the live TUI is not showing is never selected.
21683
22208
  createdAfterFor: (taskId) => tasks.find((t) => t.id === taskId)?.createdAt,
21684
- log: (m) => console.error(chalk10.dim(m))
22209
+ log: (m) => console.error(chalk11.dim(m))
21685
22210
  }),
21686
22211
  new ClaudePeerChannel({
21687
22212
  socketPathFor: (taskId) => tasks.find((t) => t.id === taskId)?.messagingSocketPath,
21688
22213
  sessionIdFor: (taskId) => tasks.find((t) => t.id === taskId)?.sessionId,
21689
22214
  statusFor: (taskId) => readClaudeStatus(tasks.find((t) => t.id === taskId)),
21690
- wire: (p, e) => writeLine(p, e, { connect: (path45) => netConnect(path45) }),
22215
+ wire: (p, e) => writeLine(p, e, { connect: (path46) => netConnect3(path46) }),
21691
22216
  receipts,
21692
- newMsgId: () => randomUUID6(),
22217
+ newMsgId: () => randomUUID8(),
21693
22218
  sleep: (ms) => new Promise((r) => setTimeout(r, ms)),
21694
- log: (m) => console.error(chalk10.dim(m))
22219
+ log: (m) => console.error(chalk11.dim(m))
21695
22220
  })
21696
22221
  ];
21697
22222
  try {
@@ -21707,7 +22232,7 @@ async function runCrewSend2(project, name, message, opts) {
21707
22232
  isBlockedByModal: (pane) => paneHasOpenModal(runtime, pane),
21708
22233
  controlChannels,
21709
22234
  controlChannelMode: (agent) => resolveControlChannelMode(cfg.defaults.controlChannel, agent),
21710
- onChannelLog: (m) => console.error(chalk10.dim(m))
22235
+ onChannelLog: (m) => console.error(chalk11.dim(m))
21711
22236
  }, opts);
21712
22237
  } finally {
21713
22238
  receipts.stop();
@@ -21743,7 +22268,14 @@ async function runCrewAnswer2(project, name, option, opts) {
21743
22268
  workspaceId,
21744
22269
  {
21745
22270
  readModalOptions: (pane) => readModalOptions(runtime, pane),
21746
- log: (m) => console.log(chalk10.dim(m))
22271
+ // #918: only claude has a structured answer path; others keep keystrokes.
22272
+ dialogMatch: async () => {
22273
+ const tasks = await squadrantdCall({ kind: "list", project }).catch(() => []);
22274
+ const t = resolveApproveTarget(tasks, name);
22275
+ if (!t || t.provider !== "claude" || !(t.sessionId || t.cwd)) return void 0;
22276
+ return { agentSessionId: t.sessionId, cwd: t.cwd };
22277
+ },
22278
+ log: (m) => console.log(chalk11.dim(m))
21747
22279
  },
21748
22280
  opts
21749
22281
  );
@@ -21781,9 +22313,9 @@ crewCommand.command("spawn").description(
21781
22313
  // into the isolated worktree root for relative-path access.
21782
22314
  ...opts.taskFile && opts.taskFile !== "-" ? { taskFile: opts.taskFile } : {}
21783
22315
  });
21784
- console.log(chalk10.green(`\u2714 Crew '${pane.title}' spawned (${pane.surfaceId})`));
22316
+ console.log(chalk11.green(`\u2714 Crew '${pane.title}' spawned (${pane.surfaceId})`));
21785
22317
  } catch (err) {
21786
- console.error(chalk10.red(err.message));
22318
+ console.error(chalk11.red(err.message));
21787
22319
  process.exit(1);
21788
22320
  }
21789
22321
  }
@@ -21792,7 +22324,7 @@ crewCommand.command("list").description("List live crew sessions for a project")
21792
22324
  try {
21793
22325
  const crews = await runCrewList2(project);
21794
22326
  if (crews.length === 0) {
21795
- console.log(chalk10.yellow(`No live crew sessions for ${project}.`));
22327
+ console.log(chalk11.yellow(`No live crew sessions for ${project}.`));
21796
22328
  return;
21797
22329
  }
21798
22330
  const tasks = await squadrantdCall({ kind: "list", project }).catch(() => []);
@@ -21823,7 +22355,7 @@ crewCommand.command("list").description("List live crew sessions for a project")
21823
22355
  }
21824
22356
  }
21825
22357
  } catch (err) {
21826
- console.error(chalk10.red(err.message));
22358
+ console.error(chalk11.red(err.message));
21827
22359
  process.exit(1);
21828
22360
  }
21829
22361
  });
@@ -21831,10 +22363,10 @@ crewCommand.command("send").description("Send a follow-up message to an existing
21831
22363
  try {
21832
22364
  const resolvedMessage = await resolveTextInput({ positional: message, filePath: opts.messageFile, label: "message" });
21833
22365
  const { reopened } = await runCrewSend2(project, name, resolvedMessage, opts);
21834
- if (reopened) console.log(chalk10.cyan(`\u21BB Task was terminal \u2014 reopened to working`));
21835
- console.log(chalk10.green(`\u2714 Sent to ${project}:${name}`));
22366
+ if (reopened) console.log(chalk11.cyan(`\u21BB Task was terminal \u2014 reopened to working`));
22367
+ console.log(chalk11.green(`\u2714 Sent to ${project}:${name}`));
21836
22368
  } catch (e) {
21837
- console.error(chalk10.red(e.message));
22369
+ console.error(chalk11.red(e.message));
21838
22370
  process.exit(1);
21839
22371
  }
21840
22372
  });
@@ -21844,12 +22376,12 @@ crewCommand.command("answer").description(
21844
22376
  try {
21845
22377
  const { selected, closed } = await runCrewAnswer2(project, name, option, opts);
21846
22378
  if (closed) {
21847
- console.log(chalk10.green(`\u2714 Answered ${project}:${name} with ${selected.index}. "${selected.label}" \u2014 prompt closed`));
22379
+ console.log(chalk11.green(`\u2714 Answered ${project}:${name} with ${selected.index}. "${selected.label}" \u2014 prompt closed`));
21848
22380
  } else {
21849
- console.log(chalk10.yellow(`\u26A0 Sent ${selected.index}. "${selected.label}" to ${project}:${name}, but the prompt still appears open \u2014 read it again with 'squadrant crew read ${project} ${name}'`));
22381
+ console.log(chalk11.yellow(`\u26A0 Sent ${selected.index}. "${selected.label}" to ${project}:${name}, but the prompt still appears open \u2014 read it again with 'squadrant crew read ${project} ${name}'`));
21850
22382
  }
21851
22383
  } catch (err) {
21852
- console.error(chalk10.red(err.message));
22384
+ console.error(chalk11.red(err.message));
21853
22385
  process.exit(1);
21854
22386
  }
21855
22387
  });
@@ -21859,16 +22391,16 @@ crewCommand.command("read").description("Read the current screen of a crew sessi
21859
22391
  const out = opts.full ? screen : tailLines(screen, Number(opts.lines ?? 40));
21860
22392
  console.log(out);
21861
22393
  } catch (err) {
21862
- console.error(chalk10.red(err.message));
22394
+ console.error(chalk11.red(err.message));
21863
22395
  process.exit(1);
21864
22396
  }
21865
22397
  });
21866
22398
  crewCommand.command("close").description("Shutdown a crew session (closes its tab)").argument("<project>", "Project name").argument("<name>", "Crew name").option("--force", "override an operator takeover (only when the operator told you to)", false).action(async (project, name, opts) => {
21867
22399
  try {
21868
22400
  await runCrewClose2(project, name, opts);
21869
- console.log(chalk10.green(`\u2714 Closed ${project}:${name}`));
22401
+ console.log(chalk11.green(`\u2714 Closed ${project}:${name}`));
21870
22402
  } catch (err) {
21871
- console.error(chalk10.red(err.message));
22403
+ console.error(chalk11.red(err.message));
21872
22404
  process.exit(1);
21873
22405
  }
21874
22406
  });
@@ -21877,7 +22409,7 @@ crewCommand.command("close").description("Shutdown a crew session (closes its ta
21877
22409
  init_dist();
21878
22410
  init_dist4();
21879
22411
  import { Command as Command11 } from "commander";
21880
- import chalk11 from "chalk";
22412
+ import chalk12 from "chalk";
21881
22413
  import { execFileSync as execFileSync10 } from "child_process";
21882
22414
  import readline2 from "readline";
21883
22415
  function resolveDiffTarget(tasks, crew, projectPath) {
@@ -21994,7 +22526,7 @@ async function openCrewDiff(project, proj, crew, opts, runtime, workspaceId) {
21994
22526
  const label = sources.length > 1 ? "staged or unstaged" : sources[0];
21995
22527
  console.log(`No ${label} changes on ${branchLabel}.`);
21996
22528
  } else {
21997
- console.log(chalk11.dim(`Opened ${opened} working-tree diff(s) (${sources.join(", ")}) for ${branchLabel}.`));
22529
+ console.log(chalk12.dim(`Opened ${opened} working-tree diff(s) (${sources.join(", ")}) for ${branchLabel}.`));
21998
22530
  }
21999
22531
  return;
22000
22532
  }
@@ -22017,7 +22549,7 @@ async function openCrewDiff(project, proj, crew, opts, runtime, workspaceId) {
22017
22549
  lastTurn: opts.lastTurn,
22018
22550
  source: "branch"
22019
22551
  });
22020
- console.log(chalk11.dim(`Opened ${branchLabel} vs ${base} in cmux diff.`));
22552
+ console.log(chalk12.dim(`Opened ${branchLabel} vs ${base} in cmux diff.`));
22021
22553
  }
22022
22554
  async function runDiff(project, crewArg, opts) {
22023
22555
  const config = loadConfig();
@@ -22038,7 +22570,7 @@ async function runDiff(project, crewArg, opts) {
22038
22570
  return;
22039
22571
  }
22040
22572
  await runtime.showPatch({ workspaceId, patch, title, layout: opts.layout, focus: opts.focus });
22041
- console.log(chalk11.dim(`Opened ${title} in cmux diff.`));
22573
+ console.log(chalk12.dim(`Opened ${title} in cmux diff.`));
22042
22574
  return;
22043
22575
  }
22044
22576
  let crew;
@@ -22074,11 +22606,11 @@ init_dist4();
22074
22606
  init_dist();
22075
22607
  init_dist2();
22076
22608
  import { Command as Command12 } from "commander";
22077
- import fs27 from "fs";
22078
- import path31 from "path";
22609
+ import fs29 from "fs";
22610
+ import path32 from "path";
22079
22611
  import os17 from "os";
22080
- import chalk12 from "chalk";
22081
- var TEMPLATES_DIR3 = path31.join(os17.homedir(), ".config", "squadrant", "templates");
22612
+ import chalk13 from "chalk";
22613
+ var TEMPLATES_DIR3 = path32.join(os17.homedir(), ".config", "squadrant", "templates");
22082
22614
  async function runSideSpawn2(input) {
22083
22615
  const config = loadConfig();
22084
22616
  const proj = config.projects[input.project];
@@ -22103,7 +22635,7 @@ async function runSideSpawn2(input) {
22103
22635
  }
22104
22636
  const sideModel = sideRole?.model;
22105
22637
  const sideThinking = sideRole?.thinking;
22106
- const promptFile = path31.join(
22638
+ const promptFile = path32.join(
22107
22639
  TEMPLATES_DIR3,
22108
22640
  `side.${input.role}.${agent.templateSuffix}.md`
22109
22641
  );
@@ -22111,7 +22643,7 @@ async function runSideSpawn2(input) {
22111
22643
  prompt: input.topic,
22112
22644
  workdir: spawnCwd,
22113
22645
  role: "side",
22114
- promptFile: fs27.existsSync(promptFile) ? promptFile : void 0,
22646
+ promptFile: fs29.existsSync(promptFile) ? promptFile : void 0,
22115
22647
  interactive: true,
22116
22648
  permissionMode: config.defaults.permissions?.crew ?? "auto",
22117
22649
  ...sideModel ? { model: sideModel } : {},
@@ -22166,9 +22698,9 @@ sideCommand.command("spawn").description(
22166
22698
  direction: opts.direction,
22167
22699
  agent: opts.agent
22168
22700
  });
22169
- console.log(chalk12.green(`\u2714 Side session '${pane.title}' spawned (${pane.surfaceId})`));
22701
+ console.log(chalk13.green(`\u2714 Side session '${pane.title}' spawned (${pane.surfaceId})`));
22170
22702
  } catch (err) {
22171
- console.error(chalk12.red(err.message));
22703
+ console.error(chalk13.red(err.message));
22172
22704
  process.exit(1);
22173
22705
  }
22174
22706
  }
@@ -22177,14 +22709,14 @@ sideCommand.command("list").description("List live side-sessions for a project")
22177
22709
  try {
22178
22710
  const sessions = await runSideList2(project);
22179
22711
  if (sessions.length === 0) {
22180
- console.log(chalk12.yellow(`No live side-sessions for ${project}.`));
22712
+ console.log(chalk13.yellow(`No live side-sessions for ${project}.`));
22181
22713
  return;
22182
22714
  }
22183
22715
  for (const s of sessions) {
22184
22716
  console.log(` ${s.name} (${s.surfaceId})`);
22185
22717
  }
22186
22718
  } catch (err) {
22187
- console.error(chalk12.red(err.message));
22719
+ console.error(chalk13.red(err.message));
22188
22720
  process.exit(1);
22189
22721
  }
22190
22722
  });
@@ -22197,9 +22729,9 @@ sideCommand.command("send").description("Send a follow-up message to an existing
22197
22729
  label: "message"
22198
22730
  });
22199
22731
  await runSideSend2(project, name, resolvedMessage);
22200
- console.log(chalk12.green(`\u2714 Sent to ${project}:${name}`));
22732
+ console.log(chalk13.green(`\u2714 Sent to ${project}:${name}`));
22201
22733
  } catch (err) {
22202
- console.error(chalk12.red(err.message));
22734
+ console.error(chalk13.red(err.message));
22203
22735
  process.exit(1);
22204
22736
  }
22205
22737
  }
@@ -22207,9 +22739,9 @@ sideCommand.command("send").description("Send a follow-up message to an existing
22207
22739
  sideCommand.command("close").description("Close a side-session (closes its tab)").argument("<project>", "Project name").argument("<name>", "Session name").action(async (project, name) => {
22208
22740
  try {
22209
22741
  await runSideClose2(project, name);
22210
- console.log(chalk12.green(`\u2714 Closed ${project}:${name}`));
22742
+ console.log(chalk13.green(`\u2714 Closed ${project}:${name}`));
22211
22743
  } catch (err) {
22212
- console.error(chalk12.red(err.message));
22744
+ console.error(chalk13.red(err.message));
22213
22745
  process.exit(1);
22214
22746
  }
22215
22747
  });
@@ -22219,7 +22751,7 @@ init_dist();
22219
22751
  init_dist4();
22220
22752
  import { Command as Command13 } from "commander";
22221
22753
  import { execSync as execSync10 } from "child_process";
22222
- import chalk14 from "chalk";
22754
+ import chalk15 from "chalk";
22223
22755
 
22224
22756
  // packages/web/dist/read-status.js
22225
22757
  function deriveState(tasks) {
@@ -22296,14 +22828,14 @@ async function readAllStatuses(deps) {
22296
22828
  }
22297
22829
 
22298
22830
  // packages/web/dist/render.js
22299
- import chalk13 from "chalk";
22831
+ import chalk14 from "chalk";
22300
22832
  var ICON = {
22301
- idle: chalk13.green,
22302
- busy: chalk13.cyan,
22303
- blocked: chalk13.yellow,
22304
- errored: chalk13.red,
22305
- offline: chalk13.dim,
22306
- unknown: chalk13.gray
22833
+ idle: chalk14.green,
22834
+ busy: chalk14.cyan,
22835
+ blocked: chalk14.yellow,
22836
+ errored: chalk14.red,
22837
+ offline: chalk14.dim,
22838
+ unknown: chalk14.gray
22307
22839
  };
22308
22840
  var ICON_CHAR = {
22309
22841
  idle: "\u25CF",
@@ -22330,9 +22862,9 @@ function formatAge(lastChecked, now) {
22330
22862
  return "stale";
22331
22863
  }
22332
22864
  function firstLine(s) {
22333
- for (const line of s.split(/\r?\n/)) {
22334
- if (line.trim().length > 0)
22335
- return line.trim();
22865
+ for (const line2 of s.split(/\r?\n/)) {
22866
+ if (line2.trim().length > 0)
22867
+ return line2.trim();
22336
22868
  }
22337
22869
  return "";
22338
22870
  }
@@ -22346,10 +22878,10 @@ function renderDashboard(rows, opts) {
22346
22878
  const width = opts.width ?? 100;
22347
22879
  const lines = [];
22348
22880
  lines.push("");
22349
- lines.push(" " + chalk13.bold("\u{1F4CA} Squadrant Dashboard") + " " + chalk13.dim(opts.now));
22881
+ lines.push(" " + chalk14.bold("\u{1F4CA} Squadrant Dashboard") + " " + chalk14.dim(opts.now));
22350
22882
  lines.push("");
22351
22883
  if (rows.length === 0) {
22352
- lines.push(" " + chalk13.yellow("No projects registered. Add one with: squadrant projects add <name> <path>"));
22884
+ lines.push(" " + chalk14.yellow("No projects registered. Add one with: squadrant projects add <name> <path>"));
22353
22885
  lines.push("");
22354
22886
  return lines.join("\n");
22355
22887
  }
@@ -22360,22 +22892,22 @@ function renderDashboard(rows, opts) {
22360
22892
  const excerptW = Math.max(20, width - FIXED);
22361
22893
  for (const r of rows) {
22362
22894
  const icon = ICON[r.state](ICON_CHAR[r.state]);
22363
- const name = chalk13.cyan(pad(r.project, NAME_W));
22895
+ const name = chalk14.cyan(pad(r.project, NAME_W));
22364
22896
  const state = ICON[r.state](pad(r.state, STATE_W));
22365
22897
  const age = pad(formatAge(r.lastChecked, opts.now), AGE_W);
22366
- const excerpt = chalk13.dim(truncate(firstLine(r.excerpt), excerptW));
22898
+ const excerpt = chalk14.dim(truncate(firstLine(r.excerpt), excerptW));
22367
22899
  lines.push(` ${icon} ${name} ${state} ${age} \u2502 ${excerpt}`);
22368
22900
  }
22369
22901
  lines.push("");
22370
- lines.push(chalk13.dim(" Refreshes every 10s \xB7 Ctrl+C to exit"));
22902
+ lines.push(chalk14.dim(" Refreshes every 10s \xB7 Ctrl+C to exit"));
22371
22903
  lines.push("");
22372
22904
  return lines.join("\n");
22373
22905
  }
22374
22906
 
22375
22907
  // packages/web/dist/sync-hub.js
22376
22908
  init_dist();
22377
- import fs28 from "fs";
22378
- import path32 from "path";
22909
+ import fs30 from "fs";
22910
+ import path33 from "path";
22379
22911
  function buildMirrorMarkdown(s) {
22380
22912
  const fenced = "```";
22381
22913
  return [
@@ -22401,15 +22933,15 @@ function buildMirrorMarkdown(s) {
22401
22933
  function syncHub(deps) {
22402
22934
  if (!deps.config.hubVault)
22403
22935
  return [];
22404
- const writeFile6 = deps.writeFile ?? ((p, c) => fs28.writeFileSync(p, c));
22405
- const mkdir6 = deps.mkdir ?? ((p) => fs28.mkdirSync(p, { recursive: true }));
22406
- const projectsDir = path32.join(resolveHome(deps.config.hubVault), "projects");
22936
+ const writeFile6 = deps.writeFile ?? ((p, c) => fs30.writeFileSync(p, c));
22937
+ const mkdir6 = deps.mkdir ?? ((p) => fs30.mkdirSync(p, { recursive: true }));
22938
+ const projectsDir = path33.join(resolveHome(deps.config.hubVault), "projects");
22407
22939
  mkdir6(projectsDir);
22408
22940
  const out = [];
22409
22941
  for (const s of deps.statuses) {
22410
22942
  if (s.state === "unknown")
22411
22943
  continue;
22412
- const hubPath = path32.join(projectsDir, `${s.project}.md`);
22944
+ const hubPath = path33.join(projectsDir, `${s.project}.md`);
22413
22945
  try {
22414
22946
  writeFile6(hubPath, buildMirrorMarkdown(s));
22415
22947
  out.push({ project: s.project, hubPath });
@@ -22421,8 +22953,8 @@ function syncHub(deps) {
22421
22953
 
22422
22954
  // packages/web/dist/web-server.js
22423
22955
  init_dist2();
22424
- import { createServer as createServer5 } from "http";
22425
- import { dirname as dirname7, join as join29 } from "path";
22956
+ import { createServer as createServer6 } from "http";
22957
+ import { dirname as dirname7, join as join30 } from "path";
22426
22958
 
22427
22959
  // packages/web/dist/snapshot-merge.js
22428
22960
  function mergeSnapshot(daemon, external, now) {
@@ -22432,7 +22964,7 @@ function mergeSnapshot(daemon, external, now) {
22432
22964
  // packages/web/dist/probes.js
22433
22965
  init_dist();
22434
22966
  init_dist();
22435
- import { join as join28 } from "path";
22967
+ import { join as join29 } from "path";
22436
22968
  import { homedir as homedir16 } from "os";
22437
22969
  import { existsSync as existsSync13, readFileSync as readFileSync20 } from "fs";
22438
22970
  import { execFile as execFile4 } from "child_process";
@@ -22470,7 +23002,7 @@ function vaultProbe(run, dir) {
22470
23002
  return { state: "unknown", detail: "no vault configured" };
22471
23003
  if (!run.pathExists(dir))
22472
23004
  return { state: "gone", detail: "vault directory missing" };
22473
- if (!run.pathExists(join28(dir, ".obsidian")))
23005
+ if (!run.pathExists(join29(dir, ".obsidian")))
22474
23006
  return { state: "gone", detail: "no .obsidian/ (not a vault)" };
22475
23007
  return { state: "alive" };
22476
23008
  } catch {
@@ -22538,10 +23070,10 @@ async function runExternalProbes(run, timeoutMs = DEFAULT_TIMEOUT_MS2) {
22538
23070
  const sessions = probeSessions(run);
22539
23071
  return { cmux: cmux2, agentClis, vaults, config: { parseable, projectPaths, sessions } };
22540
23072
  }
22541
- var SESSIONS_PATH = join28(homedir16(), ".config", "squadrant", "sessions.json");
23073
+ var SESSIONS_PATH = join29(homedir16(), ".config", "squadrant", "sessions.json");
22542
23074
  function onPath(cli) {
22543
23075
  const dirs = (process.env.PATH ?? "").split(":").filter(Boolean);
22544
- return dirs.some((d) => existsSync13(join28(d, cli)));
23076
+ return dirs.some((d) => existsSync13(join29(d, cli)));
22545
23077
  }
22546
23078
  function readSessionsHashes() {
22547
23079
  const raw = JSON.parse(readFileSync20(SESSIONS_PATH, "utf-8"));
@@ -23415,18 +23947,18 @@ function renderHtml(snap, opts = {}) {
23415
23947
  import { closeSync as closeSync3, openSync as openSync3, readSync as readSync2, statSync as statSync4 } from "fs";
23416
23948
  var LOG_TAIL_BYTES = 256 * 1024;
23417
23949
  var LOG_RING_SIZE = 1e3;
23418
- function defaultSize(path45) {
23950
+ function defaultSize(path46) {
23419
23951
  try {
23420
- return statSync4(path45).size;
23952
+ return statSync4(path46).size;
23421
23953
  } catch {
23422
23954
  return 0;
23423
23955
  }
23424
23956
  }
23425
- function defaultRead(path45, start, len) {
23957
+ function defaultRead(path46, start, len) {
23426
23958
  if (len <= 0)
23427
23959
  return "";
23428
23960
  try {
23429
- const fd = openSync3(path45, "r");
23961
+ const fd = openSync3(path46, "r");
23430
23962
  try {
23431
23963
  const buf = Buffer.alloc(len);
23432
23964
  const n = readSync2(fd, buf, 0, len, start);
@@ -23446,8 +23978,8 @@ var LogTailer = class {
23446
23978
  ring = [];
23447
23979
  size;
23448
23980
  read;
23449
- constructor(path45, ringSize = LOG_RING_SIZE, deps = {}) {
23450
- this.path = path45;
23981
+ constructor(path46, ringSize = LOG_RING_SIZE, deps = {}) {
23982
+ this.path = path46;
23451
23983
  this.ringSize = ringSize;
23452
23984
  this.size = deps.size ?? defaultSize;
23453
23985
  this.read = deps.read ?? defaultRead;
@@ -23518,7 +24050,7 @@ async function startWebServer(opts) {
23518
24050
  const now = opts.now ?? (() => Date.now());
23519
24051
  const clients = /* @__PURE__ */ new Set();
23520
24052
  const logClients = /* @__PURE__ */ new Set();
23521
- const logPath2 = opts.logPath ?? join29(dirname7(opts.sockPath), "squadrantd.log");
24053
+ const logPath2 = opts.logPath ?? join30(dirname7(opts.sockPath), "squadrantd.log");
23522
24054
  const tailer = new LogTailer(logPath2);
23523
24055
  let latest = null;
23524
24056
  async function tick() {
@@ -23548,7 +24080,7 @@ async function startWebServer(opts) {
23548
24080
  }
23549
24081
  }
23550
24082
  }
23551
- const server = createServer5((req, res) => {
24083
+ const server = createServer6((req, res) => {
23552
24084
  if (req.method !== "GET") {
23553
24085
  res.writeHead(405).end();
23554
24086
  return;
@@ -23679,8 +24211,8 @@ async function runDashboardWeb(input) {
23679
24211
  sockPath: SOCK3,
23680
24212
  runners: defaultProbeRunners()
23681
24213
  });
23682
- console.log(chalk14.green(`\u2714 Squadrant system dashboard \u2192 http://127.0.0.1:${handle.port}`));
23683
- console.log(chalk14.dim(` polling the daemon every ${input.interval}s \xB7 localhost only \xB7 read-only \xB7 Ctrl-C to stop`));
24214
+ console.log(chalk15.green(`\u2714 Squadrant system dashboard \u2192 http://127.0.0.1:${handle.port}`));
24215
+ console.log(chalk15.dim(` polling the daemon every ${input.interval}s \xB7 localhost only \xB7 read-only \xB7 Ctrl-C to stop`));
23684
24216
  }
23685
24217
  var dashboardCommand = new Command13("dashboard").description("Live status grid of all projects (derived from daemon task state)").option("--once", "Print one snapshot and exit (used by --pane's refresh loop)").option("--pane", "Open a refreshing sidebar pane in the current cmux workspace").option("--web", "Serve the live system-health web dashboard on 127.0.0.1 (HTTP + SSE)").option("--port <port>", "Port for --web (default 7878)", (v2) => parseInt(v2, 10), 7878).option("--direction <dir>", "Pane split direction (right|left|up|down)", "right").option("--interval <seconds>", "Daemon poll interval for --web (default 5); refresh interval for --pane (default 10)", (v2) => parseInt(v2, 10)).action(async (opts) => {
23686
24218
  try {
@@ -23690,12 +24222,12 @@ var dashboardCommand = new Command13("dashboard").description("Live status grid
23690
24222
  }
23691
24223
  if (opts.pane) {
23692
24224
  const pane = await runDashboardPane({ direction: opts.direction, interval: opts.interval ?? 10 });
23693
- console.log(chalk14.green(`\u2714 Dashboard pane opened in ${pane.workspaceId} ${pane.surfaceId}`));
24225
+ console.log(chalk15.green(`\u2714 Dashboard pane opened in ${pane.workspaceId} ${pane.surfaceId}`));
23694
24226
  return;
23695
24227
  }
23696
24228
  await runDashboardOnce();
23697
24229
  } catch (err) {
23698
- console.error(chalk14.red(err.message));
24230
+ console.error(chalk15.red(err.message));
23699
24231
  process.exit(1);
23700
24232
  }
23701
24233
  });
@@ -23706,12 +24238,12 @@ dashboardCommand.command("sync-hub").description("Mirror each spoke status.md in
23706
24238
  return;
23707
24239
  }
23708
24240
  if (results.length === 0) {
23709
- console.log(chalk14.dim("\n No mirrors written (no projects with usable status.md, or hubVault unset).\n"));
24241
+ console.log(chalk15.dim("\n No mirrors written (no projects with usable status.md, or hubVault unset).\n"));
23710
24242
  return;
23711
24243
  }
23712
- console.log(chalk14.bold("\n \u{1F4CA} Hub mirror sync\n"));
24244
+ console.log(chalk15.bold("\n \u{1F4CA} Hub mirror sync\n"));
23713
24245
  for (const r of results) {
23714
- console.log(` ${chalk14.green("\u2714")} ${chalk14.cyan(r.project.padEnd(16))} \u2192 ${chalk14.dim(r.hubPath)}`);
24246
+ console.log(` ${chalk15.green("\u2714")} ${chalk15.cyan(r.project.padEnd(16))} \u2192 ${chalk15.dim(r.hubPath)}`);
23715
24247
  }
23716
24248
  console.log("");
23717
24249
  });
@@ -23723,10 +24255,10 @@ init_dist4();
23723
24255
  init_dist2();
23724
24256
  import { Command as Command14 } from "commander";
23725
24257
  import { execSync as execSync11, execFileSync as execFileSync11 } from "child_process";
23726
- import fs29 from "fs";
23727
- import path33 from "path";
24258
+ import fs31 from "fs";
24259
+ import path34 from "path";
23728
24260
  import os18 from "os";
23729
- import chalk15 from "chalk";
24261
+ import chalk16 from "chalk";
23730
24262
 
23731
24263
  // packages/cli/src/commands/launch-interactive.ts
23732
24264
  import checkbox, { Separator } from "@inquirer/checkbox";
@@ -23817,8 +24349,8 @@ function resolveLaunchBackend(o) {
23817
24349
  // packages/cli/src/commands/launch.ts
23818
24350
  init_dist2();
23819
24351
  var CMUX_APP = "/Applications/cmux.app";
23820
- var TEMPLATES_DIR4 = path33.join(os18.homedir(), ".config", "squadrant", "templates");
23821
- var SESSIONS_PATH2 = path33.join(os18.homedir(), ".config", "squadrant", "sessions.json");
24352
+ var TEMPLATES_DIR4 = path34.join(os18.homedir(), ".config", "squadrant", "templates");
24353
+ var SESSIONS_PATH2 = path34.join(os18.homedir(), ".config", "squadrant", "sessions.json");
23822
24354
  function shouldWireCaptainChannel(agentName, config) {
23823
24355
  return agentName === "claude" && resolveCaptainChannelMode(config.defaults) !== "off";
23824
24356
  }
@@ -23853,20 +24385,20 @@ function resolveAnthropicRefusal(role, workspaceName, agentName, model, readOpen
23853
24385
  }
23854
24386
  function ensureCmuxReady(headless) {
23855
24387
  if (headless || isInsideCmux()) return;
23856
- console.log(chalk15.yellow("\n Not running inside cmux. Opening cmux app...\n"));
24388
+ console.log(chalk16.yellow("\n Not running inside cmux. Opening cmux app...\n"));
23857
24389
  execSync11(`open "${CMUX_APP}"`, { stdio: "inherit" });
23858
- console.log(chalk15.bold(" Run `squadrant launch` from inside a cmux workspace.\n"));
24390
+ console.log(chalk16.bold(" Run `squadrant launch` from inside a cmux workspace.\n"));
23859
24391
  process.exit(0);
23860
24392
  }
23861
24393
  var launchCommand = new Command14("launch").description(
23862
24394
  "Launch a project captain (with project arg) or all captains (--all). Use `squadrant command` for one-shot Command tasks."
23863
24395
  ).argument("[project]", "Project name to launch captain for").option("--fresh", "Start a new session instead of resuming the last one").option("--keep", "Resume the latest session even on a new day / after a template change").option("--all", "Launch all captain workspaces").option("--headless", "Skip the interactive cmux-app requirement (used by the daemon to boot captains without a terminal)").option("--agent <name>", "Override captain agent for this launch (claude|codex|gemini|opencode); takes precedence over defaults.roles.captain.agent").option("--model <name>", "Override captain model for this launch; takes precedence over defaults.roles.captain.model").option("--thinking <level>", `Override captain thinking level for this launch (${THINKING_LEVELS.join("|")}) \u2192 claude --effort; takes precedence over defaults.roles.captain.thinking`).option("--backend <mode>", "Override captain backend for this launch (native|direct|proxy); takes precedence over defaults.roles.captain.backend").action(async (project, opts) => {
23864
24396
  if (opts.fresh && opts.keep) {
23865
- console.error(chalk15.red("\n \u2718 --fresh and --keep are mutually exclusive\n"));
24397
+ console.error(chalk16.red("\n \u2718 --fresh and --keep are mutually exclusive\n"));
23866
24398
  process.exit(1);
23867
24399
  }
23868
24400
  if (opts.backend !== void 0 && !isBackendMode(opts.backend)) {
23869
- console.error(chalk15.red(`
24401
+ console.error(chalk16.red(`
23870
24402
  \u2718 Invalid --backend value '${opts.backend}'. Valid values: native, direct, proxy
23871
24403
  `));
23872
24404
  process.exit(1);
@@ -23876,7 +24408,7 @@ var launchCommand = new Command14("launch").description(
23876
24408
  try {
23877
24409
  thinkingOverride = opts.thinking ? parseThinkingLevel(opts.thinking) : void 0;
23878
24410
  } catch (err) {
23879
- console.error(chalk15.red(`
24411
+ console.error(chalk16.red(`
23880
24412
  \u2718 ${err.message}
23881
24413
  `));
23882
24414
  process.exit(1);
@@ -23901,7 +24433,7 @@ var launchCommand = new Command14("launch").description(
23901
24433
  const backend = resolveLaunchBackend({ backendOverride, agentName, roleConfig });
23902
24434
  const refusal = resolveAnthropicRefusal(role, workspaceName, agentName, model);
23903
24435
  if (refusal) {
23904
- console.error(chalk15.red(`
24436
+ console.error(chalk16.red(`
23905
24437
  \u2718 ${refusal}
23906
24438
  `));
23907
24439
  hadFailure = true;
@@ -23915,10 +24447,10 @@ var launchCommand = new Command14("launch").description(
23915
24447
  initialPrompt = "Run your startup checklist: use the squadrant:command-ops skill, complete your daily briefing, then report ready.";
23916
24448
  }
23917
24449
  const runtime = projectName ? runtimes.forProject(projectName, config) : runtimes.global(config);
23918
- const stateRoot = path33.join(os18.homedir(), ".config", "squadrant", "state");
24450
+ const stateRoot = path34.join(os18.homedir(), ".config", "squadrant", "state");
23919
24451
  const isOpencodeCaptain = role === "captain" && agentName === "opencode" && !!projectName;
23920
24452
  if (isOpencodeCaptain && !isOpencodeCaptainDir(cwd)) {
23921
- console.error(chalk15.red(`
24453
+ console.error(chalk16.red(`
23922
24454
  \u2718 '${projectName}' is not a git repo with a commit \u2014 an opencode captain needs a stable project identity. Run 'git commit' first.
23923
24455
  `));
23924
24456
  hadFailure = true;
@@ -23949,10 +24481,10 @@ var launchCommand = new Command14("launch").description(
23949
24481
  routerCredentials: (o) => fetchRouterCredentials(o.project, o.backend, { call: squadrantdCall }),
23950
24482
  writeRouterSettings
23951
24483
  },
23952
- warn: (m) => console.error(chalk15.yellow(` \u26A0 ${m}`))
24484
+ warn: (m) => console.error(chalk16.yellow(` \u26A0 ${m}`))
23953
24485
  });
23954
24486
  } catch (err) {
23955
- console.error(chalk15.red(` \u2718 ${err.message}`));
24487
+ console.error(chalk16.red(` \u2718 ${err.message}`));
23956
24488
  hadFailure = true;
23957
24489
  return;
23958
24490
  }
@@ -23992,7 +24524,7 @@ var launchCommand = new Command14("launch").description(
23992
24524
  route?.settingsPath
23993
24525
  );
23994
24526
  if (gateDecision?.warn) {
23995
- console.error(chalk15.yellow(` \u26A0 gate: ${gateDecision.reason} \u2014 launching opencode captain directly (P6-C safety fallback)`));
24527
+ console.error(chalk16.yellow(` \u26A0 gate: ${gateDecision.reason} \u2014 launching opencode captain directly (P6-C safety fallback)`));
23996
24528
  }
23997
24529
  const effectiveCmd = gateDecision?.wrap && captainBoot?.port ? buildOpencodeGateRunCommand({ port: captainBoot.port, sessionId: captainBoot.sessionId }) : baseCmd;
23998
24530
  const gatePrefix = route && Object.keys(route.env).length > 0 ? `${renderEnvAssignments(route.env)} ` : "";
@@ -24012,10 +24544,10 @@ var launchCommand = new Command14("launch").description(
24012
24544
  return null;
24013
24545
  }
24014
24546
  },
24015
- onFreshReason: (reason) => console.log(chalk15.cyan(` \u21BB ${reason}`)),
24016
- onStoppingStale: (name) => console.log(chalk15.yellow(` Closing stale workspace '${name}' for fresh start`)),
24547
+ onFreshReason: (reason) => console.log(chalk16.cyan(` \u21BB ${reason}`)),
24548
+ onStoppingStale: (name) => console.log(chalk16.yellow(` Closing stale workspace '${name}' for fresh start`)),
24017
24549
  onAlreadyExists: (name) => {
24018
- console.log(chalk15.yellow(` Workspace '${name}' already exists \u2014 switching to it`));
24550
+ console.log(chalk16.yellow(` Workspace '${name}' already exists \u2014 switching to it`));
24019
24551
  if (!projectName || !isOpencodeCaptain) return;
24020
24552
  const live = discoverLiveOpencodeServer({
24021
24553
  directory: realpathOrSelf(cwd),
@@ -24033,7 +24565,7 @@ var launchCommand = new Command14("launch").description(
24033
24565
  });
24034
24566
  },
24035
24567
  onCreated: (name) => {
24036
- console.log(chalk15.green(` \u2714 Workspace '${name}' created`));
24568
+ console.log(chalk16.green(` \u2714 Workspace '${name}' created`));
24037
24569
  if (!projectName) return;
24038
24570
  if (isOpencodeCaptain && captainPort) {
24039
24571
  writeCaptainAddress(stateRoot, projectName, {
@@ -24049,7 +24581,7 @@ var launchCommand = new Command14("launch").description(
24049
24581
  directory: realpathOrSelf(cwd),
24050
24582
  launchedAt,
24051
24583
  sessionId: opencodeResumeSessionId,
24052
- log: (m) => console.error(chalk15.yellow(` \u26A0 ${m}`))
24584
+ log: (m) => console.error(chalk16.yellow(` \u26A0 ${m}`))
24053
24585
  }).catch(() => {
24054
24586
  });
24055
24587
  } else if (role === "captain") {
@@ -24062,23 +24594,23 @@ var launchCommand = new Command14("launch").description(
24062
24594
  }
24063
24595
  });
24064
24596
  } catch (err) {
24065
- console.error(chalk15.red(` \u2718 Failed: ${err.message}`));
24597
+ console.error(chalk16.red(` \u2718 Failed: ${err.message}`));
24066
24598
  hadFailure = true;
24067
24599
  }
24068
24600
  }
24069
24601
  if (opts.all) {
24070
24602
  const hubPath = resolveHome(config.hubVault);
24071
- fs29.mkdirSync(hubPath, { recursive: true });
24072
- console.log(chalk15.bold("\nLaunching all captain workspaces\n"));
24603
+ fs31.mkdirSync(hubPath, { recursive: true });
24604
+ console.log(chalk16.bold("\nLaunching all captain workspaces\n"));
24073
24605
  for (const [name, proj] of Object.entries(config.projects)) {
24074
24606
  const projPath = resolveHome(proj.path);
24075
24607
  const spokePath = resolveHome(proj.spokeVault);
24076
- if (!fs29.existsSync(spokePath)) {
24608
+ if (!fs31.existsSync(spokePath)) {
24077
24609
  const spokeDriver = new WorkspaceRegistry({ obsidian: createObsidianDriver }).forProject(name, config);
24078
24610
  await ensureSpokeLayout(spokeDriver);
24079
- console.log(chalk15.cyan(` \u2714 Created spoke vault at ${spokePath}`));
24611
+ console.log(chalk16.cyan(` \u2714 Created spoke vault at ${spokePath}`));
24080
24612
  }
24081
- console.log(chalk15.bold(`
24613
+ console.log(chalk16.bold(`
24082
24614
  Captain: ${proj.captainName} (${name})`));
24083
24615
  await launchOne(proj.captainName, "captain", projPath, config.defaults.permissions?.captain || "auto", false, true, name);
24084
24616
  }
@@ -24086,7 +24618,7 @@ var launchCommand = new Command14("launch").description(
24086
24618
  } else if (!project) {
24087
24619
  if (!process.stdin.isTTY || !process.stdout.isTTY) {
24088
24620
  console.error(
24089
- chalk15.red(
24621
+ chalk16.red(
24090
24622
  "\n \u2718 Specify a project name, or pass --all to launch every captain.\n For one-shot Command tasks, use `squadrant command --task <briefing|learnings-review|wiki-aggregate>`.\n"
24091
24623
  )
24092
24624
  );
@@ -24101,22 +24633,22 @@ var launchCommand = new Command14("launch").description(
24101
24633
  }));
24102
24634
  const selected = await selectCaptainsInteractive(entries);
24103
24635
  if (selected.length === 0) {
24104
- console.log(chalk15.yellow("\n No captains selected.\n"));
24636
+ console.log(chalk16.yellow("\n No captains selected.\n"));
24105
24637
  return;
24106
24638
  }
24107
- console.log(chalk15.bold(`
24639
+ console.log(chalk16.bold(`
24108
24640
  Launching ${selected.length} captain workspace(s) in parallel
24109
24641
  `));
24110
24642
  await Promise.all(selected.map(async (name) => {
24111
24643
  const proj = config.projects[name];
24112
24644
  const projPath = resolveHome(proj.path);
24113
24645
  const spokePath = resolveHome(proj.spokeVault);
24114
- if (!fs29.existsSync(spokePath)) {
24646
+ if (!fs31.existsSync(spokePath)) {
24115
24647
  const spokeDriver = new WorkspaceRegistry({ obsidian: createObsidianDriver }).forProject(name, config);
24116
24648
  await ensureSpokeLayout(spokeDriver);
24117
- console.log(chalk15.cyan(` \u2714 Created spoke vault at ${spokePath}`));
24649
+ console.log(chalk16.cyan(` \u2714 Created spoke vault at ${spokePath}`));
24118
24650
  }
24119
- console.log(chalk15.bold(`
24651
+ console.log(chalk16.bold(`
24120
24652
  Captain: ${proj.captainName} (${name})`));
24121
24653
  await launchOne(proj.captainName, "captain", projPath, config.defaults.permissions?.captain || "auto", false, true, name);
24122
24654
  }));
@@ -24124,7 +24656,7 @@ Launching ${selected.length} captain workspace(s) in parallel
24124
24656
  } else {
24125
24657
  if (!config.projects[project]) {
24126
24658
  console.error(
24127
- chalk15.red(
24659
+ chalk16.red(
24128
24660
  `
24129
24661
  \u2718 Project '${project}' not found. Run 'squadrant projects list' to see registered projects.
24130
24662
  `
@@ -24135,13 +24667,13 @@ Launching ${selected.length} captain workspace(s) in parallel
24135
24667
  const proj = config.projects[project];
24136
24668
  const projPath = resolveHome(proj.path);
24137
24669
  const spokePath = resolveHome(proj.spokeVault);
24138
- if (!fs29.existsSync(spokePath)) {
24670
+ if (!fs31.existsSync(spokePath)) {
24139
24671
  const spokeDriver = new WorkspaceRegistry({ obsidian: createObsidianDriver }).forProject(project, config);
24140
24672
  await ensureSpokeLayout(spokeDriver);
24141
- console.log(chalk15.cyan(` \u2714 Created spoke vault at ${spokePath}`));
24673
+ console.log(chalk16.cyan(` \u2714 Created spoke vault at ${spokePath}`));
24142
24674
  }
24143
24675
  console.log(
24144
- chalk15.bold(
24676
+ chalk16.bold(
24145
24677
  `
24146
24678
  Launching captain workspace for '${project}' (${proj.captainName})
24147
24679
  `
@@ -24156,7 +24688,7 @@ Launching captain workspace for '${project}' (${proj.captainName})
24156
24688
  init_dist();
24157
24689
  init_dist4();
24158
24690
  import { Command as Command15 } from "commander";
24159
- import chalk16 from "chalk";
24691
+ import chalk17 from "chalk";
24160
24692
  init_dist();
24161
24693
  function nameVariants(name) {
24162
24694
  const stripped = name.replace(/^⚓\s+/, "").trim();
@@ -24169,17 +24701,17 @@ async function closeMatching(runtime, variants, label) {
24169
24701
  const failed = [];
24170
24702
  if (matches.length === 0) {
24171
24703
  console.log(
24172
- chalk16.yellow(` \u26A0 Workspace '${label}' not found \u2014 already closed?`)
24704
+ chalk17.yellow(` \u26A0 Workspace '${label}' not found \u2014 already closed?`)
24173
24705
  );
24174
24706
  return { closed, failed };
24175
24707
  }
24176
24708
  for (const ws of matches) {
24177
24709
  try {
24178
24710
  await runtime.stop(ws.id);
24179
- console.log(chalk16.green(` \u2714 Closed: ${ws.name}`));
24711
+ console.log(chalk17.green(` \u2714 Closed: ${ws.name}`));
24180
24712
  closed.push(ws.name);
24181
24713
  } catch {
24182
- console.log(chalk16.red(` \u2718 Failed to close: ${ws.name}`));
24714
+ console.log(chalk17.red(` \u2718 Failed to close: ${ws.name}`));
24183
24715
  failed.push(ws.name);
24184
24716
  }
24185
24717
  }
@@ -24201,11 +24733,11 @@ var shutdownCommand = new Command15("shutdown").description(
24201
24733
  const allVariants = /* @__PURE__ */ new Set([...captainVariants, ...commandVariants]);
24202
24734
  const squadrantWorkspaces = workspaces.filter((w) => allVariants.has(w.name));
24203
24735
  if (squadrantWorkspaces.length === 0) {
24204
- console.log(chalk16.yellow("\nNo squadrant workspaces found to close.\n"));
24736
+ console.log(chalk17.yellow("\nNo squadrant workspaces found to close.\n"));
24205
24737
  return;
24206
24738
  }
24207
24739
  console.log(
24208
- chalk16.bold(
24740
+ chalk17.bold(
24209
24741
  `
24210
24742
  Shutting down ${squadrantWorkspaces.length} workspace(s)...
24211
24743
  `
@@ -24225,9 +24757,9 @@ Shutting down ${squadrantWorkspaces.length} workspace(s)...
24225
24757
  for (const ws of squadrantWorkspaces) {
24226
24758
  try {
24227
24759
  await globalRuntime.stop(ws.id);
24228
- console.log(chalk16.green(` \u2714 Closed: ${ws.name}`));
24760
+ console.log(chalk17.green(` \u2714 Closed: ${ws.name}`));
24229
24761
  } catch {
24230
- console.log(chalk16.red(` \u2718 Failed to close: ${ws.name}`));
24762
+ console.log(chalk17.red(` \u2718 Failed to close: ${ws.name}`));
24231
24763
  }
24232
24764
  }
24233
24765
  console.log("");
@@ -24235,7 +24767,7 @@ Shutting down ${squadrantWorkspaces.length} workspace(s)...
24235
24767
  }
24236
24768
  if (!config.projects[project]) {
24237
24769
  console.error(
24238
- chalk16.red(
24770
+ chalk17.red(
24239
24771
  `
24240
24772
  \u2718 Project '${project}' not found. Run 'squadrant projects list' to see registered projects.
24241
24773
  `
@@ -24246,7 +24778,7 @@ Shutting down ${squadrantWorkspaces.length} workspace(s)...
24246
24778
  const captainName = config.projects[project].captainName;
24247
24779
  const runtime = runtimes.forProject(project, config);
24248
24780
  console.log(
24249
- chalk16.bold(`
24781
+ chalk17.bold(`
24250
24782
  Shutting down captain workspace for '${project}'...
24251
24783
  `)
24252
24784
  );
@@ -24271,24 +24803,24 @@ Shutting down captain workspace for '${project}'...
24271
24803
  // packages/cli/src/commands/feedback.ts
24272
24804
  init_dist();
24273
24805
  import { Command as Command16 } from "commander";
24274
- import fs30 from "fs";
24806
+ import fs32 from "fs";
24275
24807
  import os19 from "os";
24276
- import path34 from "path";
24808
+ import path35 from "path";
24277
24809
  import { fileURLToPath as fileURLToPath3 } from "url";
24278
24810
  import { execSync as execSync12 } from "child_process";
24279
- import chalk17 from "chalk";
24811
+ import chalk18 from "chalk";
24280
24812
  var REPO_URL = "https://github.com/tu11aa/squadrant";
24281
24813
  function readPkgVersion() {
24282
24814
  try {
24283
- const pkgPath = path34.join(path34.dirname(fileURLToPath3(import.meta.url)), "..", "package.json");
24284
- return JSON.parse(fs30.readFileSync(pkgPath, "utf-8")).version ?? "unknown";
24815
+ const pkgPath = path35.join(path35.dirname(fileURLToPath3(import.meta.url)), "..", "package.json");
24816
+ return JSON.parse(fs32.readFileSync(pkgPath, "utf-8")).version ?? "unknown";
24285
24817
  } catch {
24286
24818
  return "unknown";
24287
24819
  }
24288
24820
  }
24289
24821
  function readMetrics(metricsPath) {
24290
24822
  try {
24291
- return JSON.parse(fs30.readFileSync(metricsPath, "utf-8"));
24823
+ return JSON.parse(fs32.readFileSync(metricsPath, "utf-8"));
24292
24824
  } catch {
24293
24825
  return {};
24294
24826
  }
@@ -24326,19 +24858,19 @@ function buildIssueUrl(metrics, squadrantVersion) {
24326
24858
  }
24327
24859
  var feedbackCommand = new Command16("feedback").description("Open a pre-filled GitHub issue for feedback or bug reports").action(() => {
24328
24860
  const config = loadConfig();
24329
- const metricsPath = config.metrics?.path || path34.join(os19.homedir(), ".config", "squadrant", "metrics.json");
24861
+ const metricsPath = config.metrics?.path || path35.join(os19.homedir(), ".config", "squadrant", "metrics.json");
24330
24862
  const metrics = readMetrics(metricsPath);
24331
24863
  const version = readStamp(config) ?? readPkgVersion();
24332
24864
  const issueUrl = buildIssueUrl(metrics, version);
24333
- console.log(chalk17.bold("\nOpening feedback issue in browser...\n"));
24334
- console.log(chalk17.dim(` URL: ${issueUrl.substring(0, 80)}...
24865
+ console.log(chalk18.bold("\nOpening feedback issue in browser...\n"));
24866
+ console.log(chalk18.dim(` URL: ${issueUrl.substring(0, 80)}...
24335
24867
  `));
24336
24868
  try {
24337
24869
  execSync12(`open "${issueUrl}"`, { stdio: "ignore" });
24338
- console.log(chalk17.green(" \u2714 Browser opened\n"));
24870
+ console.log(chalk18.green(" \u2714 Browser opened\n"));
24339
24871
  } catch {
24340
- console.log(chalk17.yellow(" \u26A0 Could not open browser automatically."));
24341
- console.log(` Open manually: ${chalk17.cyan(issueUrl)}
24872
+ console.log(chalk18.yellow(" \u26A0 Could not open browser automatically."));
24873
+ console.log(` Open manually: ${chalk18.cyan(issueUrl)}
24342
24874
  `);
24343
24875
  }
24344
24876
  });
@@ -24348,7 +24880,7 @@ init_dist();
24348
24880
  init_dist();
24349
24881
  init_dist4();
24350
24882
  import { Command as Command17 } from "commander";
24351
- import chalk18 from "chalk";
24883
+ import chalk19 from "chalk";
24352
24884
  function getDateStr(yesterday) {
24353
24885
  return iso(daysAgo(yesterday ? 1 : 0));
24354
24886
  }
@@ -24367,7 +24899,7 @@ function formatStandup(standups, dateStr, raw) {
24367
24899
  const lines = [];
24368
24900
  const header = `Standup \u2014 ${dateStr}`;
24369
24901
  if (!raw) {
24370
- lines.push(chalk18.bold(`
24902
+ lines.push(chalk19.bold(`
24371
24903
  ${header}
24372
24904
  `));
24373
24905
  } else {
@@ -24377,12 +24909,12 @@ ${header}
24377
24909
  let hasBlockers = false;
24378
24910
  for (const s of standups) {
24379
24911
  if (!raw) {
24380
- lines.push(chalk18.cyan.bold(`## ${s.name}`));
24912
+ lines.push(chalk19.cyan.bold(`## ${s.name}`));
24381
24913
  } else {
24382
24914
  lines.push(`## ${s.name}`);
24383
24915
  }
24384
24916
  if (s.gitCommits.length > 0) {
24385
- lines.push(!raw ? chalk18.green("Done:") : "**Done:**");
24917
+ lines.push(!raw ? chalk19.green("Done:") : "**Done:**");
24386
24918
  for (const commit of s.gitCommits) {
24387
24919
  lines.push(` - ${commit}`);
24388
24920
  }
@@ -24394,7 +24926,7 @@ ${header}
24394
24926
  if (match) {
24395
24927
  const items = match[1].trim().split("\n").filter((l) => l.trim().startsWith("-"));
24396
24928
  if (items.length > 0 && section === "Tomorrow") {
24397
- lines.push(!raw ? chalk18.blue("Next:") : "**Next:**");
24929
+ lines.push(!raw ? chalk19.blue("Next:") : "**Next:**");
24398
24930
  for (const item of items) lines.push(` ${item.trim()}`);
24399
24931
  }
24400
24932
  }
@@ -24402,19 +24934,19 @@ ${header}
24402
24934
  }
24403
24935
  if (s.blockers.length > 0) {
24404
24936
  hasBlockers = true;
24405
- lines.push(!raw ? chalk18.red("Blocked:") : "**Blocked:**");
24937
+ lines.push(!raw ? chalk19.red("Blocked:") : "**Blocked:**");
24406
24938
  for (const b of s.blockers) {
24407
24939
  lines.push(` - ${b}`);
24408
24940
  }
24409
24941
  }
24410
24942
  if (s.gitCommits.length === 0 && !s.dailyLog) {
24411
- lines.push(!raw ? chalk18.dim(" (no activity)") : " (no activity)");
24943
+ lines.push(!raw ? chalk19.dim(" (no activity)") : " (no activity)");
24412
24944
  }
24413
24945
  lines.push("");
24414
24946
  }
24415
24947
  const totalCommits = standups.reduce((sum, s) => sum + s.gitCommits.length, 0);
24416
24948
  if (!raw) {
24417
- lines.push(chalk18.dim(`--- ${totalCommits} commits${hasBlockers ? ", HAS BLOCKERS" : ""} (task tracking: no data source \u2014 #630) ---
24949
+ lines.push(chalk19.dim(`--- ${totalCommits} commits${hasBlockers ? ", HAS BLOCKERS" : ""} (task tracking: no data source \u2014 #630) ---
24418
24950
  `));
24419
24951
  } else {
24420
24952
  lines.push(`---
@@ -24428,7 +24960,7 @@ var standupCommand = new Command17("standup").description("Generate daily standu
24428
24960
  const registry = new WorkspaceRegistry({ obsidian: createObsidianDriver });
24429
24961
  const projects = Object.entries(config.projects);
24430
24962
  if (projects.length === 0) {
24431
- console.log(chalk18.yellow("\nNo projects registered. Use: squadrant projects add <name> <path>\n"));
24963
+ console.log(chalk19.yellow("\nNo projects registered. Use: squadrant projects add <name> <path>\n"));
24432
24964
  return;
24433
24965
  }
24434
24966
  const dateStr = getDateStr(!!opts.yesterday);
@@ -24437,7 +24969,7 @@ var standupCommand = new Command17("standup").description("Generate daily standu
24437
24969
  if (opts.project) {
24438
24970
  const match = projects.find(([name]) => name === opts.project);
24439
24971
  if (!match) {
24440
- console.error(chalk18.red(`Project "${opts.project}" not found.`));
24972
+ console.error(chalk19.red(`Project "${opts.project}" not found.`));
24441
24973
  process.exit(1);
24442
24974
  }
24443
24975
  targets = [match];
@@ -24456,7 +24988,7 @@ init_dist();
24456
24988
  init_dist();
24457
24989
  init_dist4();
24458
24990
  import { Command as Command18 } from "commander";
24459
- import chalk19 from "chalk";
24991
+ import chalk20 from "chalk";
24460
24992
  function dedupe(items) {
24461
24993
  const seen = /* @__PURE__ */ new Set();
24462
24994
  const out = [];
@@ -24512,7 +25044,7 @@ function formatRetro(retros, fromStr, toStr, raw) {
24512
25044
  const lines = [];
24513
25045
  const header = `Retro \u2014 ${fromStr} \u2192 ${toStr}`;
24514
25046
  lines.push(raw ? `# ${header}
24515
- ` : chalk19.bold(`
25047
+ ` : chalk20.bold(`
24516
25048
  ${header}
24517
25049
  `));
24518
25050
  let totalCommits = 0;
@@ -24522,30 +25054,30 @@ ${header}
24522
25054
  totalCommits += r.commits.length;
24523
25055
  totalPRs += r.mergedPRs.length;
24524
25056
  totalShipped += r.shipped.length;
24525
- lines.push(raw ? `## ${r.name}` : chalk19.cyan.bold(`## ${r.name}`));
24526
- renderList(lines, r.shipped, raw, "Shipped", chalk19.green);
25057
+ lines.push(raw ? `## ${r.name}` : chalk20.cyan.bold(`## ${r.name}`));
25058
+ renderList(lines, r.shipped, raw, "Shipped", chalk20.green);
24527
25059
  if (r.mergedPRs.length > 0) {
24528
- lines.push(raw ? `**PRs merged:**` : chalk19.green("PRs merged:"));
25060
+ lines.push(raw ? `**PRs merged:**` : chalk20.green("PRs merged:"));
24529
25061
  for (const pr of r.mergedPRs) lines.push(` - ${pr}`);
24530
25062
  }
24531
- renderList(lines, r.inProgress, raw, "In Progress", chalk19.yellow);
24532
- renderList(lines, r.blocked, raw, "Blocked", chalk19.red);
24533
- renderList(lines, r.decisions, raw, "Key Decisions", chalk19.magenta);
25063
+ renderList(lines, r.inProgress, raw, "In Progress", chalk20.yellow);
25064
+ renderList(lines, r.blocked, raw, "Blocked", chalk20.red);
25065
+ renderList(lines, r.decisions, raw, "Key Decisions", chalk20.magenta);
24534
25066
  const metricBits = [
24535
25067
  `${r.commits.length} commits`,
24536
25068
  `${r.mergedPRs.length} PRs merged`,
24537
25069
  `${r.shipped.length} shipped`
24538
25070
  ];
24539
- lines.push(raw ? `*${metricBits.join(" \xB7 ")}*` : chalk19.dim(` ${metricBits.join(" \xB7 ")}`));
25071
+ lines.push(raw ? `*${metricBits.join(" \xB7 ")}*` : chalk20.dim(` ${metricBits.join(" \xB7 ")}`));
24540
25072
  if (r.shipped.length === 0 && r.commits.length === 0 && r.mergedPRs.length === 0 && r.inProgress.length === 0 && r.blocked.length === 0) {
24541
- lines.push(raw ? "_(no activity in this window)_" : chalk19.dim(" (no activity in this window)"));
25073
+ lines.push(raw ? "_(no activity in this window)_" : chalk20.dim(" (no activity in this window)"));
24542
25074
  }
24543
25075
  lines.push("");
24544
25076
  }
24545
25077
  const summary = `${totalShipped} items shipped \xB7 ${totalCommits} commits \xB7 ${totalPRs} PRs merged`;
24546
25078
  lines.push(raw ? `---
24547
25079
  *${summary}*
24548
- ` : chalk19.dim(`--- ${summary} ---
25080
+ ` : chalk20.dim(`--- ${summary} ---
24549
25081
  `));
24550
25082
  return lines.join("\n");
24551
25083
  }
@@ -24554,7 +25086,7 @@ var retroCommand = new Command18("retro").description("Generate a retro (weekly/
24554
25086
  const registry = new WorkspaceRegistry({ obsidian: createObsidianDriver });
24555
25087
  const projects = Object.entries(config.projects);
24556
25088
  if (projects.length === 0) {
24557
- console.log(chalk19.yellow("\nNo projects registered. Use: squadrant projects add <name> <path>\n"));
25089
+ console.log(chalk20.yellow("\nNo projects registered. Use: squadrant projects add <name> <path>\n"));
24558
25090
  return;
24559
25091
  }
24560
25092
  let windowDays = 7;
@@ -24571,7 +25103,7 @@ var retroCommand = new Command18("retro").description("Generate a retro (weekly/
24571
25103
  if (opts.project) {
24572
25104
  const match = projects.find(([name]) => name === opts.project);
24573
25105
  if (!match) {
24574
- console.error(chalk19.red(`Project "${opts.project}" not found.`));
25106
+ console.error(chalk20.red(`Project "${opts.project}" not found.`));
24575
25107
  process.exit(1);
24576
25108
  }
24577
25109
  targets = [match];
@@ -24591,7 +25123,7 @@ init_runtime2();
24591
25123
  init_dist();
24592
25124
  init_dist4();
24593
25125
  import { Command as Command19 } from "commander";
24594
- import chalk20 from "chalk";
25126
+ import chalk21 from "chalk";
24595
25127
  function buildRegistry2() {
24596
25128
  return new WorkspaceRegistry({
24597
25129
  obsidian: createObsidianDriver
@@ -24626,12 +25158,12 @@ workspaceCommand.command("read").description("Print the contents of a scope-rela
24626
25158
  const config = loadConfig();
24627
25159
  const registry = buildRegistry2();
24628
25160
  try {
24629
- const { projectTarget, path: path45 } = resolveTargetAndPath(arg1, arg2, !!opts.hub);
25161
+ const { projectTarget, path: path46 } = resolveTargetAndPath(arg1, arg2, !!opts.hub);
24630
25162
  const driver = resolveDriver(registry, config, projectTarget, !!opts.hub);
24631
- const content = await driver.read(path45);
25163
+ const content = await driver.read(path46);
24632
25164
  process.stdout.write(content);
24633
25165
  } catch (err) {
24634
- console.error(chalk20.red(err.message));
25166
+ console.error(chalk21.red(err.message));
24635
25167
  process.exit(1);
24636
25168
  }
24637
25169
  });
@@ -24640,28 +25172,28 @@ workspaceCommand.command("write").description("Write content to a scope-relative
24640
25172
  const registry = buildRegistry2();
24641
25173
  try {
24642
25174
  let projectTarget;
24643
- let path45;
25175
+ let path46;
24644
25176
  let rawContent;
24645
25177
  if (opts.hub) {
24646
25178
  if (arg3 !== void 0) {
24647
25179
  throw new Error("With --hub, pass only the path and content");
24648
25180
  }
24649
25181
  projectTarget = void 0;
24650
- path45 = arg1;
25182
+ path46 = arg1;
24651
25183
  rawContent = arg2;
24652
25184
  } else {
24653
25185
  if (arg3 === void 0) {
24654
25186
  throw new Error("Missing content \u2014 usage: <project> <path> <content>");
24655
25187
  }
24656
25188
  projectTarget = arg1;
24657
- path45 = arg2;
25189
+ path46 = arg2;
24658
25190
  rawContent = arg3;
24659
25191
  }
24660
25192
  const driver = resolveDriver(registry, config, projectTarget, !!opts.hub);
24661
25193
  const payload = rawContent === "-" ? await readStdin() : rawContent;
24662
- await driver.write(path45, payload);
25194
+ await driver.write(path46, payload);
24663
25195
  } catch (err) {
24664
- console.error(chalk20.red(err.message));
25196
+ console.error(chalk21.red(err.message));
24665
25197
  process.exit(1);
24666
25198
  }
24667
25199
  });
@@ -24669,12 +25201,12 @@ workspaceCommand.command("list").description("List entries in a scope-relative d
24669
25201
  const config = loadConfig();
24670
25202
  const registry = buildRegistry2();
24671
25203
  try {
24672
- const { projectTarget, path: path45 } = resolveTargetAndPath(arg1, arg2, !!opts.hub);
25204
+ const { projectTarget, path: path46 } = resolveTargetAndPath(arg1, arg2, !!opts.hub);
24673
25205
  const driver = resolveDriver(registry, config, projectTarget, !!opts.hub);
24674
- const entries = await driver.list(path45);
25206
+ const entries = await driver.list(path46);
24675
25207
  for (const entry of entries) console.log(entry);
24676
25208
  } catch (err) {
24677
- console.error(chalk20.red(err.message));
25209
+ console.error(chalk21.red(err.message));
24678
25210
  process.exit(1);
24679
25211
  }
24680
25212
  });
@@ -24682,12 +25214,12 @@ workspaceCommand.command("exists").description("Exit 0 if path exists, 1 if not"
24682
25214
  const config = loadConfig();
24683
25215
  const registry = buildRegistry2();
24684
25216
  try {
24685
- const { projectTarget, path: path45 } = resolveTargetAndPath(arg1, arg2, !!opts.hub);
25217
+ const { projectTarget, path: path46 } = resolveTargetAndPath(arg1, arg2, !!opts.hub);
24686
25218
  const driver = resolveDriver(registry, config, projectTarget, !!opts.hub);
24687
- const ok2 = await driver.exists(path45);
25219
+ const ok2 = await driver.exists(path46);
24688
25220
  process.exit(ok2 ? 0 : 1);
24689
25221
  } catch (err) {
24690
- console.error(chalk20.red(err.message));
25222
+ console.error(chalk21.red(err.message));
24691
25223
  process.exit(2);
24692
25224
  }
24693
25225
  });
@@ -24695,11 +25227,11 @@ workspaceCommand.command("mkdir").description("Recursively create a scope-relati
24695
25227
  const config = loadConfig();
24696
25228
  const registry = buildRegistry2();
24697
25229
  try {
24698
- const { projectTarget, path: path45 } = resolveTargetAndPath(arg1, arg2, !!opts.hub);
25230
+ const { projectTarget, path: path46 } = resolveTargetAndPath(arg1, arg2, !!opts.hub);
24699
25231
  const driver = resolveDriver(registry, config, projectTarget, !!opts.hub);
24700
- await driver.mkdir(path45);
25232
+ await driver.mkdir(path46);
24701
25233
  } catch (err) {
24702
- console.error(chalk20.red(err.message));
25234
+ console.error(chalk21.red(err.message));
24703
25235
  process.exit(1);
24704
25236
  }
24705
25237
  });
@@ -24708,7 +25240,7 @@ workspaceCommand.command("mkdir").description("Recursively create a scope-relati
24708
25240
  init_dist();
24709
25241
  init_dist4();
24710
25242
  import { Command as Command20 } from "commander";
24711
- import chalk21 from "chalk";
25243
+ import chalk22 from "chalk";
24712
25244
  async function readStdin2() {
24713
25245
  const chunks = [];
24714
25246
  for await (const chunk of process.stdin) {
@@ -24724,7 +25256,7 @@ var notifyCommand = new Command20("notify").description("Send a message to the u
24724
25256
  if (!payload) throw new Error("Empty message");
24725
25257
  await registry.get(config).notify(payload);
24726
25258
  } catch (err) {
24727
- console.error(chalk21.red(err.message));
25259
+ console.error(chalk22.red(err.message));
24728
25260
  process.exit(1);
24729
25261
  }
24730
25262
  });
@@ -24735,9 +25267,9 @@ init_dist3();
24735
25267
  init_dist4();
24736
25268
  init_dist();
24737
25269
  import { Command as Command21 } from "commander";
24738
- import chalk22 from "chalk";
24739
- import fs31 from "fs";
24740
- import path35 from "path";
25270
+ import chalk23 from "chalk";
25271
+ import fs33 from "fs";
25272
+ import path36 from "path";
24741
25273
  import { fileURLToPath as fileURLToPath4 } from "url";
24742
25274
  function parseScope(v2) {
24743
25275
  if (v2 !== "user" && v2 !== "project") {
@@ -24746,10 +25278,10 @@ function parseScope(v2) {
24746
25278
  return v2;
24747
25279
  }
24748
25280
  function findPackageRoot3() {
24749
- let dir = path35.dirname(fileURLToPath4(import.meta.url));
25281
+ let dir = path36.dirname(fileURLToPath4(import.meta.url));
24750
25282
  while (dir !== "/" && dir !== "") {
24751
- if (fs31.existsSync(path35.join(dir, "package.json"))) return dir;
24752
- dir = path35.dirname(dir);
25283
+ if (fs33.existsSync(path36.join(dir, "package.json"))) return dir;
25284
+ dir = path36.dirname(dir);
24753
25285
  }
24754
25286
  return process.cwd();
24755
25287
  }
@@ -24783,17 +25315,17 @@ async function runEmit(opts) {
24783
25315
  for (const dest of emitter.destinations(scope, projectRoot)) {
24784
25316
  const result = await emitter.emit(source, dest, { dryRun: opts.dryRun });
24785
25317
  if (opts.dryRun) {
24786
- console.log(chalk22.cyan(`[${emitter.name}] ${dest.path}`));
25318
+ console.log(chalk23.cyan(`[${emitter.name}] ${dest.path}`));
24787
25319
  console.log(result.diff ?? "(no diff)");
24788
25320
  } else if (result.written) {
24789
25321
  console.log(
24790
- chalk22.green(
25322
+ chalk23.green(
24791
25323
  `\u2714 ${emitter.name} \u2192 ${dest.path} (${result.bytesWritten} bytes)`
24792
25324
  )
24793
25325
  );
24794
25326
  emittedCount.written++;
24795
25327
  } else {
24796
- console.log(chalk22.gray(`- ${emitter.name} \u2192 ${dest.path} (skipped)`));
25328
+ console.log(chalk23.gray(`- ${emitter.name} \u2192 ${dest.path} (skipped)`));
24797
25329
  emittedCount.skipped++;
24798
25330
  }
24799
25331
  }
@@ -24816,14 +25348,14 @@ async function runEmit(opts) {
24816
25348
  `Unknown project '${projectName}'. Available: ${Object.keys(cfg.projects).join(", ") || "(none)"}`
24817
25349
  );
24818
25350
  }
24819
- console.error(chalk22.yellow(`\u26A0 unknown project: ${projectName}`));
25351
+ console.error(chalk23.yellow(`\u26A0 unknown project: ${projectName}`));
24820
25352
  continue;
24821
25353
  }
24822
25354
  const source = await readProjectLevelSource(
24823
25355
  createObsidianDriver({ root: proj.path })
24824
25356
  );
24825
25357
  if (!source) {
24826
- console.log(chalk22.gray(`- ${projectName}: no AGENTS.md, skipping`));
25358
+ console.log(chalk23.gray(`- ${projectName}: no AGENTS.md, skipping`));
24827
25359
  continue;
24828
25360
  }
24829
25361
  for (const name of targets) {
@@ -24833,7 +25365,7 @@ async function runEmit(opts) {
24833
25365
  }
24834
25366
  if (!opts.dryRun) {
24835
25367
  console.log(
24836
- chalk22.bold(
25368
+ chalk23.bold(
24837
25369
  `
24838
25370
  Projection complete \u2014 ${emittedCount.written} written, ${emittedCount.skipped} skipped.`
24839
25371
  )
@@ -24847,7 +25379,7 @@ projectionCommand.command("emit").description("Emit projections to disk").option
24847
25379
  try {
24848
25380
  await runEmit({ ...opts, dryRun: false });
24849
25381
  } catch (err) {
24850
- console.error(chalk22.red(err.message));
25382
+ console.error(chalk23.red(err.message));
24851
25383
  process.exit(1);
24852
25384
  }
24853
25385
  });
@@ -24855,7 +25387,7 @@ projectionCommand.command("diff").description("Preview changes without writing")
24855
25387
  try {
24856
25388
  await runEmit({ ...opts, dryRun: true });
24857
25389
  } catch (err) {
24858
- console.error(chalk22.red(err.message));
25390
+ console.error(chalk23.red(err.message));
24859
25391
  process.exit(1);
24860
25392
  }
24861
25393
  });
@@ -24865,7 +25397,7 @@ projectionCommand.command("list").description("List registered projection target
24865
25397
  const emitter = registry.get(name);
24866
25398
  const userDests = emitter.destinations("user").map((d) => d.path);
24867
25399
  const projectDests = emitter.destinations("project", "<project>").map((d) => d.path);
24868
- console.log(chalk22.bold(name));
25400
+ console.log(chalk23.bold(name));
24869
25401
  console.log(` user: ${userDests.join(", ") || "(none)"}`);
24870
25402
  console.log(` project: ${projectDests.join(", ") || "(none)"}`);
24871
25403
  }
@@ -24945,12 +25477,12 @@ init_dist();
24945
25477
  init_dist();
24946
25478
  init_dist2();
24947
25479
  import { Command as Command23 } from "commander";
24948
- import fs32 from "fs";
25480
+ import fs34 from "fs";
24949
25481
  import { fileURLToPath as fileURLToPath5 } from "url";
24950
- import { dirname as dirname8, join as join30 } from "path";
24951
- import chalk23 from "chalk";
25482
+ import { dirname as dirname8, join as join31 } from "path";
25483
+ import chalk24 from "chalk";
24952
25484
  function runConfigCheck(opts) {
24953
- const raw = JSON.parse(fs32.readFileSync(opts.configPath, "utf-8"));
25485
+ const raw = JSON.parse(fs34.readFileSync(opts.configPath, "utf-8"));
24954
25486
  const def = getDefaultConfig();
24955
25487
  const items = detectDrift(raw, def);
24956
25488
  let working = raw;
@@ -25003,14 +25535,14 @@ function runConfigSet(key, value, configPath = DEFAULT_CONFIG_PATH) {
25003
25535
  }
25004
25536
  function printRestartOutcome(outcome) {
25005
25537
  if (outcome === "skipped-not-running") {
25006
- console.log(chalk23.dim("(daemon not running \u2014 change applies on next start)"));
25538
+ console.log(chalk24.dim("(daemon not running \u2014 change applies on next start)"));
25007
25539
  } else if (outcome === "skipped-opt-out") {
25008
- console.log(chalk23.dim("(run 'squadrant heal daemon' to apply)"));
25540
+ console.log(chalk24.dim("(run 'squadrant heal daemon' to apply)"));
25009
25541
  }
25010
25542
  }
25011
25543
  function runConfigSetAction(opts) {
25012
25544
  runConfigSet(opts.key, opts.value, opts.configPath);
25013
- console.log(chalk23.green(`\u2714 set ${opts.key} = ${opts.value}`));
25545
+ console.log(chalk24.green(`\u2714 set ${opts.key} = ${opts.value}`));
25014
25546
  if (isDaemonCachedKey(opts.key)) {
25015
25547
  const doRestart = opts.doRestart ?? restartDaemonIfRunning;
25016
25548
  const outcome = doRestart({ reason: `config ${opts.key}`, noRestart: opts.noRestart });
@@ -25018,9 +25550,9 @@ function runConfigSetAction(opts) {
25018
25550
  }
25019
25551
  }
25020
25552
  var SEV_COLOR = {
25021
- info: chalk23.green,
25022
- advisory: chalk23.yellow,
25023
- warn: chalk23.red
25553
+ info: chalk24.green,
25554
+ advisory: chalk24.yellow,
25555
+ warn: chalk24.red
25024
25556
  };
25025
25557
  var KIND_GLYPH = {
25026
25558
  missing: "+",
@@ -25032,14 +25564,14 @@ function printItems(items) {
25032
25564
  for (const i of items) {
25033
25565
  const color = SEV_COLOR[i.severity] ?? ((s) => s);
25034
25566
  const detail = i.note ? ` (${i.note})` : i.suggested !== void 0 ? ` \u2192 ${JSON.stringify(i.suggested)}` : "";
25035
- console.log(" " + color(`${KIND_GLYPH[i.kind]} ${i.kind}: ${i.path}`) + chalk23.dim(detail));
25567
+ console.log(" " + color(`${KIND_GLYPH[i.kind]} ${i.kind}: ${i.path}`) + chalk24.dim(detail));
25036
25568
  }
25037
25569
  }
25038
25570
  var configCommand = new Command23("config").description("Inspect and reconcile squadrant config");
25039
25571
  configCommand.command("check").description("Detect config drift vs the current default schema").option("--fix", "Apply the safe tier (add missing, remove deprecated)", false).option("--accept", "Stamp the current version without changing config (dismiss advisories)", false).option("--json", "Output drift items as JSON", false).action((opts) => {
25040
25572
  const pkgVersion = readPkgVersion2();
25041
- if (!fs32.existsSync(DEFAULT_CONFIG_PATH)) {
25042
- console.log(chalk23.yellow("No config found \u2014 run `squadrant init` first."));
25573
+ if (!fs34.existsSync(DEFAULT_CONFIG_PATH)) {
25574
+ console.log(chalk24.yellow("No config found \u2014 run `squadrant init` first."));
25043
25575
  return;
25044
25576
  }
25045
25577
  const res = runConfigCheck({ configPath: DEFAULT_CONFIG_PATH, pkgVersion, fix: opts.fix, accept: opts.accept });
@@ -25048,21 +25580,21 @@ configCommand.command("check").description("Detect config drift vs the current d
25048
25580
  return;
25049
25581
  }
25050
25582
  if (res.items.length === 0) {
25051
- console.log(chalk23.green("\u2714 Config is in sync with the current schema."));
25583
+ console.log(chalk24.green("\u2714 Config is in sync with the current schema."));
25052
25584
  return;
25053
25585
  }
25054
- console.log(chalk23.bold("\nConfig drift:\n"));
25586
+ console.log(chalk24.bold("\nConfig drift:\n"));
25055
25587
  printItems(res.items);
25056
25588
  if (opts.fix && res.applied.length) {
25057
- console.log(chalk23.green(`
25589
+ console.log(chalk24.green(`
25058
25590
  \u2714 Applied ${res.applied.length} safe item(s): ${res.applied.join(", ")}`));
25059
25591
  }
25060
25592
  const judgment = res.remaining.filter((i) => i.kind === "changed-default" || i.kind === "invalid");
25061
25593
  if (judgment.length) {
25062
- console.log(chalk23.yellow(`
25594
+ console.log(chalk24.yellow(`
25063
25595
  ${judgment.length} item(s) need review \u2014 run the config-doctor skill, or \`squadrant config check --accept\` to keep your values.`));
25064
25596
  } else if (res.stamped) {
25065
- console.log(chalk23.green("\n\u2714 Config reconciled and stamped."));
25597
+ console.log(chalk24.green("\n\u2714 Config reconciled and stamped."));
25066
25598
  }
25067
25599
  });
25068
25600
  configCommand.command("get").description("Read a config value by dotted key (e.g. defaults.effort)").argument("<key>", "dotted config key").action((key) => {
@@ -25070,7 +25602,7 @@ configCommand.command("get").description("Read a config value by dotted key (e.g
25070
25602
  const value = runConfigGet(key);
25071
25603
  console.log(typeof value === "string" ? value : JSON.stringify(value));
25072
25604
  } catch (e) {
25073
- console.error(chalk23.red(e.message));
25605
+ console.error(chalk24.red(e.message));
25074
25606
  process.exit(1);
25075
25607
  }
25076
25608
  });
@@ -25078,22 +25610,22 @@ configCommand.command("set").description("Write a config value by dotted key (e.
25078
25610
  try {
25079
25611
  runConfigSetAction({ key, value, noRestart: opts.restart === false });
25080
25612
  } catch (e) {
25081
- console.error(chalk23.red(e.message));
25613
+ console.error(chalk24.red(e.message));
25082
25614
  process.exit(1);
25083
25615
  }
25084
25616
  });
25085
25617
  function readPkgVersion2() {
25086
- const pkgPath = join30(dirname8(fileURLToPath5(import.meta.url)), "..", "package.json");
25087
- return JSON.parse(fs32.readFileSync(pkgPath, "utf-8")).version;
25618
+ const pkgPath = join31(dirname8(fileURLToPath5(import.meta.url)), "..", "package.json");
25619
+ return JSON.parse(fs34.readFileSync(pkgPath, "utf-8")).version;
25088
25620
  }
25089
25621
 
25090
25622
  // packages/cli/src/commands/heal.ts
25091
25623
  init_dist();
25092
25624
  import { execFileSync as execFileSync12 } from "child_process";
25093
- import { join as join31 } from "path";
25625
+ import { join as join32 } from "path";
25094
25626
  import { homedir as homedir17 } from "os";
25095
25627
  import { Command as Command24 } from "commander";
25096
- import chalk24 from "chalk";
25628
+ import chalk25 from "chalk";
25097
25629
  init_dist2();
25098
25630
  init_dist2();
25099
25631
  init_dist4();
@@ -25151,11 +25683,11 @@ async function runHealStatus(opts) {
25151
25683
  return result.healthy ? 0 : 2;
25152
25684
  }
25153
25685
  if (result.healthy) {
25154
- stdout.write(chalk24.green("\u2714 all components healthy\n"));
25686
+ stdout.write(chalk25.green("\u2714 all components healthy\n"));
25155
25687
  for (const c of result.components) {
25156
25688
  if (c.kind === "delivery" && c.state === "stale") {
25157
- const glyph = chalk24.yellow("\u2022");
25158
- const stateColor2 = chalk24.yellow;
25689
+ const glyph = chalk25.yellow("\u2022");
25690
+ const stateColor2 = chalk25.yellow;
25159
25691
  stdout.write(` ${glyph} ${c.kind.padEnd(8)} ${c.ref.padEnd(16)} ${stateColor2(c.state.padEnd(8))} ${c.project}
25160
25692
  `);
25161
25693
  if (c.detail) {
@@ -25166,13 +25698,13 @@ async function runHealStatus(opts) {
25166
25698
  }
25167
25699
  return 0;
25168
25700
  }
25169
- stdout.write(chalk24.bold("Unhealthy components:\n\n"));
25701
+ stdout.write(chalk25.bold("Unhealthy components:\n\n"));
25170
25702
  for (const c of result.components) {
25171
25703
  const isUnhealthy = c.kind === "delivery" ? c.stuck === true : c.healCmd !== null;
25172
25704
  const isAdvisoryDelivery = c.kind === "delivery" && c.state === "stale" && c.stuck !== true;
25173
25705
  if (isUnhealthy || isAdvisoryDelivery) {
25174
- const glyph = c.state === "stale" || isAdvisoryDelivery ? chalk24.yellow("\u2022") : chalk24.red("\u2718");
25175
- const stateColor2 = c.state === "stale" || isAdvisoryDelivery ? chalk24.yellow : chalk24.red;
25706
+ const glyph = c.state === "stale" || isAdvisoryDelivery ? chalk25.yellow("\u2022") : chalk25.red("\u2718");
25707
+ const stateColor2 = c.state === "stale" || isAdvisoryDelivery ? chalk25.yellow : chalk25.red;
25176
25708
  stdout.write(` ${glyph} ${c.kind.padEnd(8)} ${c.ref.padEnd(16)} ${stateColor2(c.state.padEnd(8))} ${c.project}
25177
25709
  `);
25178
25710
  if (c.detail) {
@@ -25180,7 +25712,7 @@ async function runHealStatus(opts) {
25180
25712
  `);
25181
25713
  }
25182
25714
  if (c.healCmd) {
25183
- stdout.write(` heal: ${chalk24.cyan(c.healCmd)}
25715
+ stdout.write(` heal: ${chalk25.cyan(c.healCmd)}
25184
25716
  `);
25185
25717
  }
25186
25718
  }
@@ -25193,7 +25725,7 @@ async function runHealDaemon(opts) {
25193
25725
  try {
25194
25726
  const result = opts.ensureDaemon();
25195
25727
  const noteSuffix = result?.note ? ` (${result.note})` : "";
25196
- stdout.write(chalk24.green(`\u2714 daemon kickstart complete${noteSuffix}
25728
+ stdout.write(chalk25.green(`\u2714 daemon kickstart complete${noteSuffix}
25197
25729
  `));
25198
25730
  return 0;
25199
25731
  } catch (e) {
@@ -25248,12 +25780,12 @@ async function runHealCaptain(projects, deps) {
25248
25780
  for (const project of projects) {
25249
25781
  const resolved = resolveLiveCaptain(records, project, deps.isPidAlive);
25250
25782
  if (!resolved) {
25251
- stdout.write(` ${chalk24.yellow("\u2013")} ${project}: no live captain found \u2014 nothing to heal
25783
+ stdout.write(` ${chalk25.yellow("\u2013")} ${project}: no live captain found \u2014 nothing to heal
25252
25784
  `);
25253
25785
  continue;
25254
25786
  }
25255
25787
  if (entryMatchesResolved(deps.getEntry(project), resolved)) {
25256
- stdout.write(` ${chalk24.green("\u2714")} ${project}: already healthy (pid=${resolved.pid})
25788
+ stdout.write(` ${chalk25.green("\u2714")} ${project}: already healthy (pid=${resolved.pid})
25257
25789
  `);
25258
25790
  continue;
25259
25791
  }
@@ -25283,16 +25815,16 @@ async function runHealCaptain(projects, deps) {
25283
25815
  for (const { project, resolved } of targets) {
25284
25816
  if (stillMissingSet.has(project)) {
25285
25817
  stderr.write(
25286
- ` ${chalk24.red("\u2718")} ${project}: heal did not survive the daemon restart after one retry \u2014 pid=${resolved.pid} sessionId=${resolved.sessionId} may be racing the daemon's own periodic persist
25818
+ ` ${chalk25.red("\u2718")} ${project}: heal did not survive the daemon restart after one retry \u2014 pid=${resolved.pid} sessionId=${resolved.sessionId} may be racing the daemon's own periodic persist
25287
25819
  `
25288
25820
  );
25289
25821
  } else {
25290
- stdout.write(` ${chalk24.green("\u2714")} ${project}: re-adopted captain pid=${resolved.pid} sessionId=${resolved.sessionId}
25822
+ stdout.write(` ${chalk25.green("\u2714")} ${project}: re-adopted captain pid=${resolved.pid} sessionId=${resolved.sessionId}
25291
25823
  `);
25292
25824
  }
25293
25825
  }
25294
25826
  if (stillMissingSet.size > 0) return 1;
25295
- stdout.write(chalk24.green(`\u2714 healed ${targets.length} captain(s); daemon kickstarted
25827
+ stdout.write(chalk25.green(`\u2714 healed ${targets.length} captain(s); daemon kickstarted
25296
25828
  `));
25297
25829
  return 0;
25298
25830
  }
@@ -25330,8 +25862,8 @@ var healCommand = new Command24("heal").description("Targeted, idempotent remedi
25330
25862
  }
25331
25863
  const config = loadConfig();
25332
25864
  const projects = opts.all ? Object.keys(config.projects) : [project];
25333
- const stateRoot = join31(homedir17(), ".config", "squadrant", "state");
25334
- const registry = new LivenessRegistry({ path: join31(stateRoot, "liveness.json") });
25865
+ const stateRoot = join32(homedir17(), ".config", "squadrant", "state");
25866
+ const registry = new LivenessRegistry({ path: join32(stateRoot, "liveness.json") });
25335
25867
  registry.load();
25336
25868
  const code = await runHealCaptain(projects, {
25337
25869
  liveness: readCmuxLiveness,
@@ -25357,14 +25889,14 @@ var healCommand = new Command24("heal").description("Targeted, idempotent remedi
25357
25889
 
25358
25890
  // packages/cli/src/commands/group.ts
25359
25891
  import { Command as Command26 } from "commander";
25360
- import chalk26 from "chalk";
25892
+ import chalk27 from "chalk";
25361
25893
 
25362
25894
  // packages/cli/src/commands/dispatch.ts
25363
25895
  init_dist();
25364
25896
  init_dist2();
25365
25897
  import { Command as Command25 } from "commander";
25366
25898
  import { execSync as execSync13 } from "child_process";
25367
- import chalk25 from "chalk";
25899
+ import chalk26 from "chalk";
25368
25900
  async function runDispatch(toProject, task, opts) {
25369
25901
  const fromProject = resolveCurrentProject(loadConfig());
25370
25902
  if (!fromProject) {
@@ -25389,11 +25921,11 @@ async function runDispatch(toProject, task, opts) {
25389
25921
  async function dispatchAction(toProject, task, opts) {
25390
25922
  try {
25391
25923
  const result = await runDispatch(toProject, task, opts);
25392
- console.log(chalk25.green(`\u2714 Dispatched to '${toProject}' (task ${result.id.slice(0, 8)})`));
25393
- console.log(chalk25.dim(` originProject: ${result.originProject ?? "none"}`));
25394
- console.log(chalk25.dim(" You will be notified when the task settles (done/blocked/failed)."));
25924
+ console.log(chalk26.green(`\u2714 Dispatched to '${toProject}' (task ${result.id.slice(0, 8)})`));
25925
+ console.log(chalk26.dim(` originProject: ${result.originProject ?? "none"}`));
25926
+ console.log(chalk26.dim(" You will be notified when the task settles (done/blocked/failed)."));
25395
25927
  } catch (e) {
25396
- console.error(chalk25.red(`\u2718 ${e.message}`));
25928
+ console.error(chalk26.red(`\u2718 ${e.message}`));
25397
25929
  process.exit(1);
25398
25930
  }
25399
25931
  }
@@ -25403,7 +25935,7 @@ var dispatchCommand = new Command25("dispatch").description("Dispatch a task to
25403
25935
  init_dist2();
25404
25936
  var groupCommand = new Command26("group").description("Cross-project intra-group operations (Phase 1: dispatch)").addCommand(
25405
25937
  new Command26("dispatch").description("[DEPRECATED \u2014 use 'squadrant dispatch'] Dispatch a task to a sibling project in the same group").argument("<to-project>", "Target project name").argument("<task>", "Task description to dispatch").option("--provider <p>", "claude|opencode|codex", "claude").option("--mode <m>", "headless|interactive", "headless").option("--warmup-timeout <s>", "seconds to wait for target captain to boot (default: 120)", (v2) => parseInt(v2, 10) * 1e3).action(async (toProject, task, opts) => {
25406
- console.error(chalk26.yellow(
25938
+ console.error(chalk27.yellow(
25407
25939
  `\u26A0 'squadrant group dispatch' is deprecated \u2014 use 'squadrant dispatch <project> "<task>"' instead.`
25408
25940
  ));
25409
25941
  await dispatchAction(toProject, task, opts);
@@ -25419,101 +25951,6 @@ import { join as join33, dirname as dirname9 } from "path";
25419
25951
  import { homedir as homedir18 } from "os";
25420
25952
  import { Command as Command27 } from "commander";
25421
25953
  import chalk28 from "chalk";
25422
-
25423
- // packages/cli/src/lib/captain-channel-factory.ts
25424
- init_dist3();
25425
- init_dist2();
25426
- import { createServer as createServer6, connect as netConnect2 } from "net";
25427
- import fs33 from "fs";
25428
- import { join as join32 } from "path";
25429
- import { randomUUID as randomUUID7 } from "crypto";
25430
- import chalk27 from "chalk";
25431
- var shared;
25432
- var registryEntryPath = () => join32(CLAUDE_SESSIONS_DIR, `${process.pid}.json`);
25433
- function unregisterSenderIdentity() {
25434
- try {
25435
- fs33.unlinkSync(registryEntryPath());
25436
- } catch {
25437
- }
25438
- }
25439
- function registerSenderIdentity(socketPath2) {
25440
- try {
25441
- unregisterSenderIdentity();
25442
- fs33.mkdirSync(CLAUDE_SESSIONS_DIR, { recursive: true });
25443
- fs33.writeFileSync(
25444
- registryEntryPath(),
25445
- JSON.stringify({
25446
- pid: process.pid,
25447
- sessionId: randomUUID7(),
25448
- name: "squadrantd",
25449
- messagingSocketPath: socketPath2,
25450
- kind: "daemon",
25451
- peerProtocol: 1
25452
- })
25453
- );
25454
- process.on("exit", unregisterSenderIdentity);
25455
- } catch {
25456
- }
25457
- }
25458
- async function sharedReceiptListener() {
25459
- if (shared) return shared;
25460
- ensureSocksDir();
25461
- const socketPath2 = `${CC_SOCKS_DIR}/squadrantd-${process.pid}.sock`;
25462
- const listener = new ClaudeReceiptListener({
25463
- socketPath: socketPath2,
25464
- createServer: (h) => createServer6(h),
25465
- // A UDS path is not cleaned up when a process is killed, so our own leftover
25466
- // must never be the reason we refuse to start.
25467
- unlinkStale: (p) => {
25468
- try {
25469
- fs33.unlinkSync(p);
25470
- } catch {
25471
- }
25472
- },
25473
- log: (m) => console.error(chalk27.dim(m))
25474
- });
25475
- await listener.start();
25476
- registerSenderIdentity(socketPath2);
25477
- shared = listener;
25478
- return shared;
25479
- }
25480
- function captainSessionIdFor(taskId) {
25481
- return readClaudeStatusBySocketPath(captainSocketPath(taskId))?.sessionId;
25482
- }
25483
- async function buildCaptainChannel() {
25484
- const receipts = await sharedReceiptListener();
25485
- return new ClaudePeerChannel({
25486
- // The port's taskId IS the project name for captains.
25487
- socketPathFor: (taskId) => captainSocketPath(taskId),
25488
- sessionIdFor: captainSessionIdFor,
25489
- // Captains are identified in the registry by their cwd (the project path).
25490
- // Resolve by the socket path squadrant chose at launch, NOT by cwd: a captain
25491
- // in /tmp/x registers cwd "/private/tmp/x" on macOS, so cwd matching silently
25492
- // missed and every captain ping reported accepted-unconfirmed.
25493
- statusFor: (taskId) => readClaudeStatusBySocketPath(captainSocketPath(taskId)),
25494
- wire: (p, e) => writeLine(p, e, { connect: (path45) => netConnect2(path45) }),
25495
- receipts,
25496
- newMsgId: () => randomUUID7(),
25497
- sleep: (ms) => new Promise((r) => setTimeout(r, ms)),
25498
- log: (m) => console.error(chalk27.dim(m))
25499
- });
25500
- }
25501
- async function buildCaptainChannels(opts) {
25502
- const claude = await buildCaptainChannel();
25503
- const opencode = new OpencodeHttpChannel({
25504
- portFor: (project) => readCaptainAddress(opts.stateRoot, project)?.port,
25505
- sessionFor: (project) => readCaptainAddress(opts.stateRoot, project)?.sessionId
25506
- });
25507
- return {
25508
- channels: { claude, opencode },
25509
- agentFor: (project) => resolveCaptainAgent(opts.stateRoot, project, opts.configAgent)
25510
- };
25511
- }
25512
- function resolveCaptainAgent(stateRoot, project, configAgent) {
25513
- return readCaptainAddress(stateRoot, project)?.agent ?? configAgent;
25514
- }
25515
-
25516
- // packages/cli/src/commands/ping.ts
25517
25954
  function formatPingResult(project, outcome) {
25518
25955
  if (!outcome) return `\u2714 Pinged '${project}'`;
25519
25956
  switch (outcome.status) {
@@ -25624,8 +26061,8 @@ var cmuxCommand = new Command28("cmux").description("cmux integration helpers").
25624
26061
  // packages/cli/src/commands/effort.ts
25625
26062
  init_dist();
25626
26063
  init_dist2();
25627
- import fs34 from "fs";
25628
- import path36 from "path";
26064
+ import fs35 from "fs";
26065
+ import path37 from "path";
25629
26066
  import { Command as Command29 } from "commander";
25630
26067
  import chalk30 from "chalk";
25631
26068
  var VALID_EFFORTS = ["max", "balance", "low"];
@@ -25668,9 +26105,9 @@ function effortScopeLabel(projectName) {
25668
26105
  }
25669
26106
  function canonical(p) {
25670
26107
  try {
25671
- return fs34.realpathSync(p);
26108
+ return fs35.realpathSync(p);
25672
26109
  } catch {
25673
- return path36.resolve(p);
26110
+ return path37.resolve(p);
25674
26111
  }
25675
26112
  }
25676
26113
  async function notifyCaptainsOfEffort(effort, config, driver, cwd = process.cwd(), append, scopeProject, projectConfigRoot) {
@@ -25720,7 +26157,7 @@ var effortCommand = new Command29("effort").description("Get or set the crew tok
25720
26157
  const config = loadConfig();
25721
26158
  const registry = new RuntimeRegistry2({ cmux: createCmuxDriver2() });
25722
26159
  const driver = registry.global(config);
25723
- const stateRoot = path36.join(path36.dirname(DEFAULT_CONFIG_PATH), "state");
26160
+ const stateRoot = path37.join(path37.dirname(DEFAULT_CONFIG_PATH), "state");
25724
26161
  const append = (project, text) => appendCaptainMessage({ stateRoot, project, text, source: "daemon" });
25725
26162
  await notifyCaptainsOfEffort(effort, config, driver, process.cwd(), append, options.project);
25726
26163
  } catch {
@@ -25730,19 +26167,19 @@ var effortCommand = new Command29("effort").description("Get or set the crew tok
25730
26167
 
25731
26168
  // packages/cli/src/commands/tokens.ts
25732
26169
  init_dist();
25733
- import fs35 from "fs";
25734
- import path37 from "path";
26170
+ import fs36 from "fs";
26171
+ import path38 from "path";
25735
26172
  import os20 from "os";
25736
26173
  import readline3 from "readline";
25737
26174
  import { Command as Command30 } from "commander";
25738
26175
  import chalk31 from "chalk";
25739
- var CLAUDE_PROJECTS_DIR = path37.join(os20.homedir(), ".claude", "projects");
26176
+ var CLAUDE_PROJECTS_DIR = path38.join(os20.homedir(), ".claude", "projects");
25740
26177
  function parseTranscriptLine(rawLine) {
25741
- const line = rawLine.trim();
25742
- if (!line) return { timestamp: null, usage: null };
26178
+ const line2 = rawLine.trim();
26179
+ if (!line2) return { timestamp: null, usage: null };
25743
26180
  let obj;
25744
26181
  try {
25745
- obj = JSON.parse(line);
26182
+ obj = JSON.parse(line2);
25746
26183
  } catch {
25747
26184
  return { timestamp: null, usage: null };
25748
26185
  }
@@ -25786,9 +26223,9 @@ function foldTranscriptLine(agg, rawLine, state) {
25786
26223
  async function aggregateTranscriptFile(filePath) {
25787
26224
  const agg = emptySessionAggregate();
25788
26225
  const state = { lastCacheRead: null };
25789
- const rl = readline3.createInterface({ input: fs35.createReadStream(filePath), crlfDelay: Infinity });
25790
- for await (const line of rl) {
25791
- foldTranscriptLine(agg, line, state);
26226
+ const rl = readline3.createInterface({ input: fs36.createReadStream(filePath), crlfDelay: Infinity });
26227
+ for await (const line2 of rl) {
26228
+ foldTranscriptLine(agg, line2, state);
25792
26229
  }
25793
26230
  return agg;
25794
26231
  }
@@ -25854,22 +26291,22 @@ function buildRoleReport(role, sessions) {
25854
26291
  }
25855
26292
  async function readdirSafe(dir) {
25856
26293
  try {
25857
- return await fs35.promises.readdir(dir);
26294
+ return await fs36.promises.readdir(dir);
25858
26295
  } catch {
25859
26296
  return [];
25860
26297
  }
25861
26298
  }
25862
26299
  async function listJsonlFiles(dir) {
25863
26300
  const entries = await readdirSafe(dir);
25864
- return entries.filter((e) => e.endsWith(".jsonl")).map((e) => path37.join(dir, e));
26301
+ return entries.filter((e) => e.endsWith(".jsonl")).map((e) => path38.join(dir, e));
25865
26302
  }
25866
26303
  async function findTranscriptDirs(claudeProjectsDir, captainSlug) {
25867
26304
  const entries = await readdirSafe(claudeProjectsDir);
25868
26305
  const captainDirs = [];
25869
26306
  const crewDirs = [];
25870
26307
  for (const entry of entries) {
25871
- if (entry === captainSlug) captainDirs.push(path37.join(claudeProjectsDir, entry));
25872
- else if (isCrewDirName(entry, captainSlug)) crewDirs.push(path37.join(claudeProjectsDir, entry));
26308
+ if (entry === captainSlug) captainDirs.push(path38.join(claudeProjectsDir, entry));
26309
+ else if (isCrewDirName(entry, captainSlug)) crewDirs.push(path38.join(claudeProjectsDir, entry));
25873
26310
  }
25874
26311
  return { captainDirs, crewDirs };
25875
26312
  }
@@ -26327,7 +26764,7 @@ telegramCommand.command("send").argument("<project>", "project whose topic recei
26327
26764
  const { createInterface: createInterface2 } = await import("readline");
26328
26765
  const lines = [];
26329
26766
  const rl = createInterface2({ input: process.stdin });
26330
- for await (const line of rl) lines.push(line);
26767
+ for await (const line2 of rl) lines.push(line2);
26331
26768
  message = lines.join("\n").trimEnd();
26332
26769
  if (!message) {
26333
26770
  console.error(chalk32.red("no message provided (stdin was empty)"));
@@ -26352,11 +26789,12 @@ init_dist2();
26352
26789
  init_dist3();
26353
26790
  init_dist();
26354
26791
  import { Command as Command33 } from "commander";
26792
+ import { join as join36 } from "path";
26355
26793
  import { homedir as homedir20 } from "os";
26356
26794
 
26357
26795
  // packages/cli/src/lib/captain-session-registry.ts
26358
- import fs36 from "fs";
26359
- import path38 from "path";
26796
+ import fs37 from "fs";
26797
+ import path39 from "path";
26360
26798
 
26361
26799
  // packages/cli/src/lib/handoff-facts.ts
26362
26800
  var STALE_FETCH_WARNING_MS = 24 * 60 * 60 * 1e3;
@@ -26407,18 +26845,18 @@ function assembleHandoffFacts(live, claudeMem, gapSessions, checkpoint, now, ext
26407
26845
  // packages/cli/src/lib/captain-session-registry.ts
26408
26846
  var CAPTAIN_SESSION_REGISTRY_FILE = "captain-sessions.jsonl";
26409
26847
  function appendCaptainSession(spokeVault, record) {
26410
- fs36.mkdirSync(spokeVault, { recursive: true });
26411
- const file = path38.join(spokeVault, CAPTAIN_SESSION_REGISTRY_FILE);
26412
- fs36.appendFileSync(file, JSON.stringify(record) + "\n");
26848
+ fs37.mkdirSync(spokeVault, { recursive: true });
26849
+ const file = path39.join(spokeVault, CAPTAIN_SESSION_REGISTRY_FILE);
26850
+ fs37.appendFileSync(file, JSON.stringify(record) + "\n");
26413
26851
  }
26414
26852
  function readCaptainSessionRegistry(spokeVault) {
26415
- const file = path38.join(spokeVault, CAPTAIN_SESSION_REGISTRY_FILE);
26416
- if (!fs36.existsSync(file)) return [];
26853
+ const file = path39.join(spokeVault, CAPTAIN_SESSION_REGISTRY_FILE);
26854
+ if (!fs37.existsSync(file)) return [];
26417
26855
  const records = [];
26418
- for (const line of fs36.readFileSync(file, "utf-8").split("\n")) {
26419
- if (!line.trim()) continue;
26856
+ for (const line2 of fs37.readFileSync(file, "utf-8").split("\n")) {
26857
+ if (!line2.trim()) continue;
26420
26858
  try {
26421
- records.push(JSON.parse(line));
26859
+ records.push(JSON.parse(line2));
26422
26860
  } catch {
26423
26861
  }
26424
26862
  }
@@ -26730,9 +27168,25 @@ function recordCaptainSessionStart(payload) {
26730
27168
  } catch {
26731
27169
  }
26732
27170
  }
27171
+ var RULES_HOOK_EVENTS = { "session-start": "SessionStart", "prompt-submit": "UserPromptSubmit" };
27172
+ async function rulesHookOutput(sub, payload, opts) {
27173
+ if (sub !== "session-start" && sub !== "prompt-submit") return "";
27174
+ if (opts.env.SQUADRANT_RULES_INJECT === "0") return "";
27175
+ const ctx = await withBudget(() => computeRulesInjection({
27176
+ event: sub,
27177
+ payload,
27178
+ env: opts.env,
27179
+ cwd: opts.cwd,
27180
+ project: opts.project,
27181
+ cfg: (opts.loadCfg ?? loadConfig)(),
27182
+ stateRoot: opts.stateRoot ?? join36(CONFIG_DIR, "state")
27183
+ }), opts.budgetMs ?? INJECT_BUDGET_MS);
27184
+ if (!ctx) return "";
27185
+ return JSON.stringify({ hookSpecificOutput: { hookEventName: RULES_HOOK_EVENTS[sub], additionalContext: ctx } });
27186
+ }
26733
27187
  function hooksCommand() {
26734
27188
  const hooks = new Command33("hooks").description("(internal) receive lifecycle hook events from agent processes");
26735
- hooks.command("claude <sub>", { hidden: true }).description("internal: bridge a NativeHookSource claude hook to squadrantd").action(async (sub) => {
27189
+ hooks.command("claude <sub>", { hidden: true }).description("internal: bridge a NativeHookSource claude hook to squadrantd").option("--project <name>", "project for rules injection (default: SQUADRANT_CREW_PROJECT, then cwd)").action(async (sub, opts) => {
26736
27190
  let stdin = "";
26737
27191
  try {
26738
27192
  for await (const chunk of process.stdin) stdin += chunk;
@@ -26745,6 +27199,8 @@ function hooksCommand() {
26745
27199
  } catch {
26746
27200
  }
26747
27201
  }
27202
+ const rulesOut = await rulesHookOutput(sub, payload, { env: process.env, cwd: process.cwd(), project: opts.project });
27203
+ if (rulesOut) await new Promise((resolve4) => process.stdout.write(rulesOut, () => resolve4()));
26748
27204
  if (sub === "session-start" && process.env.SQUADRANT_ROLE === "captain") {
26749
27205
  recordCaptainSessionStart(payload);
26750
27206
  }
@@ -26801,13 +27257,13 @@ function hooksCommand() {
26801
27257
  // packages/cli/src/commands/work.ts
26802
27258
  init_dist();
26803
27259
  init_dist2();
26804
- import path39 from "path";
27260
+ import path40 from "path";
26805
27261
  import { Command as Command34 } from "commander";
26806
27262
  import chalk34 from "chalk";
26807
27263
  function detectCurrentProject(config, cwd = process.cwd()) {
26808
27264
  for (const [name, proj] of Object.entries(config.projects)) {
26809
27265
  const projPath = resolveHome(proj.path);
26810
- if (cwd === projPath || cwd.startsWith(projPath + path39.sep)) return name;
27266
+ if (cwd === projPath || cwd.startsWith(projPath + path40.sep)) return name;
26811
27267
  }
26812
27268
  return void 0;
26813
27269
  }
@@ -26856,8 +27312,8 @@ function stateColor(state) {
26856
27312
  }
26857
27313
  function printItem(item, indent) {
26858
27314
  const color = stateColor(item.state);
26859
- const line = " ".repeat(indent) + `${chalk34.dim(item.id)} ${item.title} ${color(`[${item.state}]`)}` + (indent === 0 ? chalk34.dim(` (${item.project})`) : "");
26860
- console.log(TERMINAL_WORK_STATES.has(item.state) ? chalk34.dim(line) : line);
27315
+ const line2 = " ".repeat(indent) + `${chalk34.dim(item.id)} ${item.title} ${color(`[${item.state}]`)}` + (indent === 0 ? chalk34.dim(` (${item.project})`) : "");
27316
+ console.log(TERMINAL_WORK_STATES.has(item.state) ? chalk34.dim(line2) : line2);
26861
27317
  }
26862
27318
  function printTree(items) {
26863
27319
  const { roots, childrenOf } = groupByParent(items);
@@ -26939,14 +27395,14 @@ var workCommand = new Command34("work").description("Track your own in-flight wo
26939
27395
  // packages/cli/src/commands/handoff.ts
26940
27396
  init_dist();
26941
27397
  import { Command as Command35 } from "commander";
26942
- import path42 from "path";
27398
+ import path43 from "path";
26943
27399
  import os21 from "os";
26944
27400
 
26945
27401
  // packages/cli/src/lib/handoff-live-repo.ts
26946
27402
  init_dist();
26947
27403
  import { execFileSync as execFileSync13 } from "child_process";
26948
- import fs37 from "fs";
26949
- import path40 from "path";
27404
+ import fs38 from "fs";
27405
+ import path41 from "path";
26950
27406
 
26951
27407
  // packages/cli/src/lib/handoff-branch-state.ts
26952
27408
  function tryRun(runner, cmd, args, cwd) {
@@ -27085,7 +27541,7 @@ function localAheadOfBase(runner, projectPath, base) {
27085
27541
  }
27086
27542
  function readFetchAgeMs(projectPath, now) {
27087
27543
  try {
27088
- const stat2 = fs37.statSync(path40.join(projectPath, ".git", "FETCH_HEAD"));
27544
+ const stat2 = fs38.statSync(path41.join(projectPath, ".git", "FETCH_HEAD"));
27089
27545
  return Math.max(0, now - stat2.mtime.getTime());
27090
27546
  } catch {
27091
27547
  return null;
@@ -27156,7 +27612,7 @@ function gatherLiveRepoState(projectPath, fallbackBaseBranch, tasks, runner = de
27156
27612
 
27157
27613
  // packages/cli/src/lib/handoff-claude-mem.ts
27158
27614
  import { createRequire } from "module";
27159
- import fs38 from "fs";
27615
+ import fs39 from "fs";
27160
27616
  var { DatabaseSync } = createRequire(import.meta.url)("node:sqlite");
27161
27617
  var CLAUDE_MEM_RECENCY_LIMIT = 20;
27162
27618
  function decisionText(row) {
@@ -27170,7 +27626,7 @@ function decisionText(row) {
27170
27626
  return row.narrative ?? "";
27171
27627
  }
27172
27628
  function queryClaudeMem(dbPath, project) {
27173
- if (!fs38.existsSync(dbPath)) return null;
27629
+ if (!fs39.existsSync(dbPath)) return null;
27174
27630
  let db;
27175
27631
  try {
27176
27632
  db = new DatabaseSync(dbPath, { readOnly: true });
@@ -27213,7 +27669,7 @@ function queryClaudeMem(dbPath, project) {
27213
27669
  }
27214
27670
 
27215
27671
  // packages/cli/src/lib/handoff-transcript.ts
27216
- import fs39 from "fs";
27672
+ import fs40 from "fs";
27217
27673
  var TRANSCRIPT_BYTE_CAP = 2e5;
27218
27674
  var DIGEST_BYTE_CAP = 8 * 1024;
27219
27675
  var PROMPT_TRUNCATE_CHARS = 300;
@@ -27276,11 +27732,11 @@ function extractMessages(tailText) {
27276
27732
  const collectRefs = (text) => {
27277
27733
  for (const ref of findRefs(text)) refs.add(ref);
27278
27734
  };
27279
- for (const line of tailText.split("\n")) {
27280
- if (!line.trim()) continue;
27735
+ for (const line2 of tailText.split("\n")) {
27736
+ if (!line2.trim()) continue;
27281
27737
  let obj;
27282
27738
  try {
27283
- obj = JSON.parse(line);
27739
+ obj = JSON.parse(line2);
27284
27740
  } catch {
27285
27741
  continue;
27286
27742
  }
@@ -27322,27 +27778,27 @@ function extractMessages(tailText) {
27322
27778
  return { lastUserMessage, lastAssistantText, digest };
27323
27779
  }
27324
27780
  function extractTranscriptTail(transcriptPath, byteCap = TRANSCRIPT_BYTE_CAP) {
27325
- if (!fs39.existsSync(transcriptPath)) return null;
27326
- const content = fs39.readFileSync(transcriptPath, "utf-8");
27781
+ if (!fs40.existsSync(transcriptPath)) return null;
27782
+ const content = fs40.readFileSync(transcriptPath, "utf-8");
27327
27783
  const { lastUserMessage, lastAssistantText, digest } = extractMessages(tailOf(content, byteCap));
27328
- const mtimeIso = fs39.statSync(transcriptPath).mtime.toISOString();
27784
+ const mtimeIso = fs40.statSync(transcriptPath).mtime.toISOString();
27329
27785
  return { path: transcriptPath, mtimeIso, lastUserMessage, lastAssistantText, digest };
27330
27786
  }
27331
27787
 
27332
27788
  // packages/cli/src/lib/handoff-archive.ts
27333
- import fs40 from "fs";
27334
- import path41 from "path";
27789
+ import fs41 from "fs";
27790
+ import path42 from "path";
27335
27791
  function readNewestArchivedHandoff(spokeVault, now) {
27336
- const dir = path41.join(spokeVault, "handoffs");
27337
- if (!fs40.existsSync(dir)) return null;
27338
- const candidates = fs40.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isFile() && e.name.endsWith(".json")).map((e) => {
27339
- const full = path41.join(dir, e.name);
27340
- return { name: e.name, full, mtime: fs40.statSync(full).mtime };
27792
+ const dir = path42.join(spokeVault, "handoffs");
27793
+ if (!fs41.existsSync(dir)) return null;
27794
+ const candidates = fs41.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isFile() && e.name.endsWith(".json")).map((e) => {
27795
+ const full = path42.join(dir, e.name);
27796
+ return { name: e.name, full, mtime: fs41.statSync(full).mtime };
27341
27797
  }).sort((a, b) => b.mtime.getTime() - a.mtime.getTime());
27342
27798
  for (const candidate of candidates) {
27343
27799
  let content;
27344
27800
  try {
27345
- content = JSON.parse(fs40.readFileSync(candidate.full, "utf-8"));
27801
+ content = JSON.parse(fs41.readFileSync(candidate.full, "utf-8"));
27346
27802
  } catch {
27347
27803
  continue;
27348
27804
  }
@@ -27352,7 +27808,7 @@ function readNewestArchivedHandoff(spokeVault, now) {
27352
27808
  }
27353
27809
 
27354
27810
  // packages/cli/src/commands/handoff.ts
27355
- var CLAUDE_MEM_DB_PATH = path42.join(os21.homedir(), ".claude-mem", "claude-mem.db");
27811
+ var CLAUDE_MEM_DB_PATH = path43.join(os21.homedir(), ".claude-mem", "claude-mem.db");
27356
27812
  async function defaultFetchTasks(project) {
27357
27813
  return await squadrantdCall({ kind: "list", project });
27358
27814
  }
@@ -27420,9 +27876,9 @@ function filterSessions(rows, f) {
27420
27876
  if (f.agent && r.agent !== f.agent) return false;
27421
27877
  if (f.liveOnly && r.status === "stale") return false;
27422
27878
  if (f.project) {
27423
- const path45 = f.projects?.[f.project];
27879
+ const path46 = f.projects?.[f.project];
27424
27880
  const byRecord = r.project === f.project;
27425
- const byCwd = !!path45 && !!r.cwd && (r.cwd === normalized(path45) || r.cwd.startsWith(normalized(path45) + "/"));
27881
+ const byCwd = !!path46 && !!r.cwd && (r.cwd === normalized(path46) || r.cwd.startsWith(normalized(path46) + "/"));
27426
27882
  if (!byRecord && !byCwd) return false;
27427
27883
  }
27428
27884
  return true;
@@ -27442,8 +27898,8 @@ function formatSessionTable(rows) {
27442
27898
  ]);
27443
27899
  const all = [header, ...body];
27444
27900
  const widths = header.map((_, i) => Math.max(...all.map((row) => row[i].length)));
27445
- const line = (row) => row.map((c, i) => c.padEnd(widths[i])).join(" ").trimEnd();
27446
- return [line(header), ...body.map(line)].join("\n");
27901
+ const line2 = (row) => row.map((c, i) => c.padEnd(widths[i])).join(" ").trimEnd();
27902
+ return [line2(header), ...body.map(line2)].join("\n");
27447
27903
  }
27448
27904
  async function collectSessions(drivers) {
27449
27905
  const rows = [];
@@ -27513,7 +27969,7 @@ init_dist();
27513
27969
  init_dist2();
27514
27970
  init_dist3();
27515
27971
  import os22 from "os";
27516
- import path43 from "path";
27972
+ import path44 from "path";
27517
27973
  import { Command as Command37 } from "commander";
27518
27974
  import chalk36 from "chalk";
27519
27975
 
@@ -27631,7 +28087,7 @@ function buildWhoamiDeps(opts = {}) {
27631
28087
  const projects = Object.fromEntries(
27632
28088
  Object.entries(config.projects).map(([n, p]) => [n, resolveHome(p.path)])
27633
28089
  );
27634
- const root = stateRoot ?? path43.join(os22.homedir(), ".config", "squadrant", "state");
28090
+ const root = stateRoot ?? path44.join(os22.homedir(), ".config", "squadrant", "state");
27635
28091
  const store = createStore(root);
27636
28092
  const merged = {
27637
28093
  env: process.env,
@@ -27683,8 +28139,8 @@ var whoamiCommand = new Command37("whoami").description("Show the agent session
27683
28139
  // packages/cli/src/commands/knowledge.ts
27684
28140
  init_dist();
27685
28141
  init_dist2();
27686
- import fs41 from "fs";
27687
- import path44 from "path";
28142
+ import fs42 from "fs";
28143
+ import path45 from "path";
27688
28144
  import { Command as Command38 } from "commander";
27689
28145
  import chalk37 from "chalk";
27690
28146
  var KNOWLEDGE_PRIVACY_NOTICE = "Sources are sent to the extraction crew's model; mark `sensitivity: local-only` to keep a source on local models only.";
@@ -27697,18 +28153,18 @@ function runKnowledgeInit(kb, configPath = DEFAULT_CONFIG_PATH) {
27697
28153
  const hub = resolveHome(cfg.hubVault);
27698
28154
  const dir = kbDir(hub, kb);
27699
28155
  const created = [];
27700
- for (const d of [path44.join(dir, "raw"), kbRulesDir(hub, kb), path44.join(kbRulesDir(hub, kb), PROPOSED_DIR)]) {
27701
- if (!fs41.existsSync(d)) {
27702
- fs41.mkdirSync(d, { recursive: true });
27703
- created.push(path44.relative(dir, d));
28156
+ for (const d of [path45.join(dir, "raw"), kbRulesDir(hub, kb), path45.join(kbRulesDir(hub, kb), PROPOSED_DIR)]) {
28157
+ if (!fs42.existsSync(d)) {
28158
+ fs42.mkdirSync(d, { recursive: true });
28159
+ created.push(path45.relative(dir, d));
27704
28160
  }
27705
28161
  }
27706
- const sourcesFile = path44.join(dir, "sources.yaml");
27707
- if (!fs41.existsSync(sourcesFile)) {
27708
- fs41.writeFileSync(sourcesFile, SOURCES_TEMPLATE);
28162
+ const sourcesFile = path45.join(dir, "sources.yaml");
28163
+ if (!fs42.existsSync(sourcesFile)) {
28164
+ fs42.writeFileSync(sourcesFile, SOURCES_TEMPLATE);
27709
28165
  created.push("sources.yaml");
27710
28166
  }
27711
- if (!fs41.existsSync(path44.join(dir, "index.json"))) {
28167
+ if (!fs42.existsSync(path45.join(dir, "index.json"))) {
27712
28168
  writeIndex(hub, kb, compileIndex(kb, []));
27713
28169
  created.push("index.json");
27714
28170
  }
@@ -27723,7 +28179,7 @@ function runKnowledgeSubscribe(kb, project, configPath = DEFAULT_CONFIG_PATH) {
27723
28179
  const cfg = loadConfig(configPath);
27724
28180
  const pc = cfg.projects[project];
27725
28181
  if (!pc) throw new Error(`Unknown project '${project}'`);
27726
- if (!fs41.existsSync(kbDir(resolveHome(cfg.hubVault), kb))) {
28182
+ if (!fs42.existsSync(kbDir(resolveHome(cfg.hubVault), kb))) {
27727
28183
  throw new Error(`Knowledge base '${kb}' does not exist. Run: squadrant knowledge init ${kb}`);
27728
28184
  }
27729
28185
  const list = pc.knowledge ?? [];
@@ -27761,9 +28217,9 @@ function runKnowledgeReindex(kb, configPath = DEFAULT_CONFIG_PATH) {
27761
28217
  assertKbName(kb);
27762
28218
  const cfg = loadConfig(configPath);
27763
28219
  const hub = resolveHome(cfg.hubVault);
27764
- if (!fs41.existsSync(kbDir(hub, kb))) throw new Error(`Knowledge base '${kb}' does not exist. Run: squadrant knowledge init ${kb}`);
28220
+ if (!fs42.existsSync(kbDir(hub, kb))) throw new Error(`Knowledge base '${kb}' does not exist. Run: squadrant knowledge init ${kb}`);
27765
28221
  const { rules: all, errors } = loadKbRules(cfg, kb, { includeProposed: true });
27766
- const proposedRoot = path44.join(kbRulesDir(hub, kb), PROPOSED_DIR) + path44.sep;
28222
+ const proposedRoot = path45.join(kbRulesDir(hub, kb), PROPOSED_DIR) + path45.sep;
27767
28223
  const live = all.filter((r) => !r.file.startsWith(proposedRoot));
27768
28224
  const file = writeIndex(hub, kb, compileIndex(kb, live));
27769
28225
  return { file, count: live.length, proposed: all.length - live.length, errors: errors.length, invalid: errors };
@@ -27772,7 +28228,7 @@ function runKnowledgeValidate(kb, configPath = DEFAULT_CONFIG_PATH) {
27772
28228
  assertKbName(kb);
27773
28229
  const cfg = loadConfig(configPath);
27774
28230
  const hub = resolveHome(cfg.hubVault);
27775
- if (!fs41.existsSync(kbDir(hub, kb))) throw new Error(`Knowledge base '${kb}' does not exist. Run: squadrant knowledge init ${kb}`);
28231
+ if (!fs42.existsSync(kbDir(hub, kb))) throw new Error(`Knowledge base '${kb}' does not exist. Run: squadrant knowledge init ${kb}`);
27776
28232
  const { sources, errors } = loadSources(hub, kb);
27777
28233
  const res = validateKb({ rulesDir: kbRulesDir(hub, kb), kbRoot: kbDir(hub, kb), sources, domains: cfg.knowledge?.[kb]?.domains });
27778
28234
  const srcChecks = errors.map((e) => ({ level: "fail", message: `sources.yaml: ${e}` }));
@@ -27864,10 +28320,10 @@ function runRulesShow(id, opts, configPath = DEFAULT_CONFIG_PATH) {
27864
28320
  var rulesCommand = new Command39("rules").description("Look up rules from subscribed knowledge bases (#893)");
27865
28321
  rulesCommand.command("search <query...>").description("Search rules by keyword (ranked; best match first)").option("--project <name>", "project (default: from cwd or SQUADRANT_CREW_PROJECT)").option("--all", "include proposed and retired rules").option("--limit <n>", `max results (default ${DEFAULT_SEARCH_LIMIT})`).option("--brief", "one line per rule: [score] MODALITY id: statement").option("--ids-only", "print only rule ids").action((query, opts) => {
27866
28322
  const hits = runRulesSearch(query.join(" "), opts);
27867
- for (const line of renderSearch(hits, opts)) console.log(line);
28323
+ for (const line2 of renderSearch(hits, opts)) console.log(line2);
27868
28324
  });
27869
28325
  rulesCommand.command("list").description("List every resolved rule for the project").option("--project <name>", "project (default: from cwd or SQUADRANT_CREW_PROJECT)").option("--all", "include proposed and retired rules").option("--brief", "one line per rule: MODALITY id: statement").action((opts) => {
27870
- for (const line of renderList2(runRulesList(opts), opts)) console.log(line);
28326
+ for (const line2 of renderList2(runRulesList(opts), opts)) console.log(line2);
27871
28327
  });
27872
28328
  rulesCommand.command("show <ids...>").description("Show one or more rules in full").option("--project <name>", "project (default: from cwd or SQUADRANT_CREW_PROJECT)").option("--all", "include proposed and retired rules").action((ids, opts) => {
27873
28329
  for (const id of ids) {
@@ -27883,14 +28339,14 @@ init_dist();
27883
28339
  init_dist();
27884
28340
  init_dist();
27885
28341
  var __dirname = dirname12(fileURLToPath6(import.meta.url));
27886
- var pkg = JSON.parse(readFileSync21(join36(__dirname, "..", "package.json"), "utf-8"));
28342
+ var pkg = JSON.parse(readFileSync21(join37(__dirname, "..", "package.json"), "utf-8"));
27887
28343
  ensureRuntimeSynced({
27888
- sourceRoot: join36(__dirname, ".."),
27889
- runtimeRoot: join36(homedir21(), ".config", "squadrant")
28344
+ sourceRoot: join37(__dirname, ".."),
28345
+ runtimeRoot: join37(homedir21(), ".config", "squadrant")
27890
28346
  });
27891
28347
  if (!process.env.VITEST) {
27892
28348
  try {
27893
- syncShippedOpencodeSkills({ pkgRoot: join36(__dirname, "..") });
28349
+ syncShippedOpencodeSkills({ pkgRoot: join37(__dirname, "..") });
27894
28350
  } catch (err) {
27895
28351
  process.stderr.write(
27896
28352
  `squadrant: opencode skills sync skipped: ${err.message}
@@ -27900,7 +28356,7 @@ if (!process.env.VITEST) {
27900
28356
  }
27901
28357
  if (process.argv[2] !== "config") {
27902
28358
  try {
27903
- const cfgPath = join36(homedir21(), ".config", "squadrant", "config.json");
28359
+ const cfgPath = join37(homedir21(), ".config", "squadrant", "config.json");
27904
28360
  if (existsSync14(cfgPath)) {
27905
28361
  const cfg = JSON.parse(readConfigFileSync(cfgPath));
27906
28362
  if (needsCheck(cfg, pkg.version)) {