@staff0rd/assist 0.411.0 → 0.413.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -6,7 +6,7 @@ import { Command } from "commander";
6
6
  // package.json
7
7
  var package_default = {
8
8
  name: "@staff0rd/assist",
9
- version: "0.411.0",
9
+ version: "0.413.0",
10
10
  type: "module",
11
11
  main: "dist/index.js",
12
12
  bin: {
@@ -140,13 +140,68 @@ import { dirname, join } from "path";
140
140
  import chalk from "chalk";
141
141
  import { stringify as stringifyYaml } from "yaml";
142
142
 
143
+ // src/commands/backlog/getCurrentOrigin.ts
144
+ import { execFileSync } from "child_process";
145
+ function stripLeadingSlashes(path71) {
146
+ return path71.replace(/^\/+/, "");
147
+ }
148
+ function normalizeOrigin(raw) {
149
+ const trimmed = raw.trim().replace(/\.git$/i, "").replace(/\/+$/, "");
150
+ const url = trimmed.match(
151
+ /^[a-zA-Z][a-zA-Z0-9+.-]*:\/\/(?:[^@/]+@)?([^/:]+)(?::\d+)?\/(.+)$/
152
+ );
153
+ if (url) {
154
+ return `${url[1].toLowerCase()}/${stripLeadingSlashes(url[2])}`;
155
+ }
156
+ if (!trimmed.includes("://")) {
157
+ const scp = trimmed.match(/^(?:[^@/]+@)?([^/:]+):(.+)$/);
158
+ if (scp) {
159
+ return `${scp[1].toLowerCase()}/${stripLeadingSlashes(scp[2])}`;
160
+ }
161
+ }
162
+ return trimmed.toLowerCase();
163
+ }
164
+ function tryGit(cwd, args) {
165
+ const windows = /^[A-Za-z]:[\\/]/.test(cwd);
166
+ const file = windows ? "git.exe" : "git";
167
+ const argv = windows ? ["-C", cwd, ...args] : args;
168
+ try {
169
+ const out = execFileSync(file, argv, {
170
+ encoding: "utf8",
171
+ stdio: ["pipe", "pipe", "pipe"],
172
+ ...windows ? {} : { cwd }
173
+ }).trim();
174
+ return out || null;
175
+ } catch {
176
+ return null;
177
+ }
178
+ }
179
+ function firstRemoteUrl(cwd) {
180
+ const remotes = tryGit(cwd, ["remote"]);
181
+ if (!remotes) return null;
182
+ for (const remote of remotes.split("\n").map((r) => r.trim()).filter(Boolean)) {
183
+ const url = tryGit(cwd, ["remote", "get-url", remote]);
184
+ if (url) return url;
185
+ }
186
+ return null;
187
+ }
188
+ function getRemoteOriginUrl(cwd) {
189
+ return tryGit(cwd, ["remote", "get-url", "origin"]) ?? firstRemoteUrl(cwd);
190
+ }
191
+ function getCurrentOrigin(cwd) {
192
+ const url = getRemoteOriginUrl(cwd);
193
+ if (url) return normalizeOrigin(url);
194
+ const root = tryGit(cwd, ["rev-parse", "--show-toplevel"]);
195
+ return `local:${root ?? cwd}`;
196
+ }
197
+
143
198
  // src/shared/loadRawYaml.ts
144
199
  import { existsSync, readFileSync } from "fs";
145
200
  import { parse as parseYaml } from "yaml";
146
- function loadRawYaml(path70) {
147
- if (!existsSync(path70)) return {};
201
+ function loadRawYaml(path71) {
202
+ if (!existsSync(path71)) return {};
148
203
  try {
149
- const content = readFileSync(path70, "utf8");
204
+ const content = readFileSync(path71, "utf8");
150
205
  return parseYaml(content) || {};
151
206
  } catch {
152
207
  return {};
@@ -179,6 +234,84 @@ function mergeRawConfigs(globalRaw, projectRaw) {
179
234
  return merged;
180
235
  }
181
236
 
237
+ // src/commands/backlog/originDisplayName.ts
238
+ function originDisplayName(origin) {
239
+ if (origin.startsWith("local:")) {
240
+ const path71 = origin.slice("local:".length).replace(/\/+$/, "");
241
+ const segments = path71.split("/").filter(Boolean);
242
+ return segments[segments.length - 1] ?? origin;
243
+ }
244
+ const firstSlash = origin.indexOf("/");
245
+ if (firstSlash === -1) return origin;
246
+ return origin.slice(firstSlash + 1);
247
+ }
248
+
249
+ // src/commands/backlog/originDisplayLabels.ts
250
+ function originDisplayLabels(origins) {
251
+ const isLocal = (origin) => origin.startsWith("local:");
252
+ const bareName = (origin) => {
253
+ const full = originDisplayName(origin);
254
+ const segments = full.split("/");
255
+ return segments[segments.length - 1] ?? full;
256
+ };
257
+ const remoteCounts = /* @__PURE__ */ new Map();
258
+ for (const origin of new Set(origins)) {
259
+ if (isLocal(origin)) continue;
260
+ const name = bareName(origin);
261
+ remoteCounts.set(name, (remoteCounts.get(name) ?? 0) + 1);
262
+ }
263
+ const labels = /* @__PURE__ */ new Map();
264
+ for (const origin of origins) {
265
+ if (isLocal(origin)) {
266
+ labels.set(origin, originDisplayName(origin));
267
+ continue;
268
+ }
269
+ const name = bareName(origin);
270
+ const collides = (remoteCounts.get(name) ?? 0) > 1;
271
+ labels.set(origin, collides ? originDisplayName(origin) : name);
272
+ }
273
+ return labels;
274
+ }
275
+
276
+ // src/shared/resolveRepoOverride.ts
277
+ var AmbiguousRepoConfigError = class extends Error {
278
+ name = "AmbiguousRepoConfigError";
279
+ };
280
+ function originKeyCandidates(origin) {
281
+ const displayName = originDisplayName(origin);
282
+ const segments = displayName.split("/");
283
+ const bare = segments[segments.length - 1] ?? displayName;
284
+ return /* @__PURE__ */ new Set([origin, displayName, bare]);
285
+ }
286
+ function resolveRepoOverride(globalRaw, origin) {
287
+ const repos2 = globalRaw.repos;
288
+ if (!repos2 || typeof repos2 !== "object" || Array.isArray(repos2)) return {};
289
+ const entries = repos2;
290
+ const candidates = originKeyCandidates(origin);
291
+ const matches = Object.keys(entries).filter((key) => candidates.has(key));
292
+ if (matches.length === 0) return {};
293
+ if (matches.length > 1) {
294
+ throw new AmbiguousRepoConfigError(
295
+ `Ambiguous repos config in ~/.assist.yml: keys ${matches.map((m) => `"${m}"`).join(", ")} all match the current repository (${origin}). Keep a single key per repository.`
296
+ );
297
+ }
298
+ const override = entries[matches[0]];
299
+ if (!override || typeof override !== "object" || Array.isArray(override))
300
+ return {};
301
+ return override;
302
+ }
303
+ function resolveRepoWriteLabel(globalRaw, origin) {
304
+ const repos2 = globalRaw.repos;
305
+ if (repos2 && typeof repos2 === "object" && !Array.isArray(repos2)) {
306
+ const candidates = originKeyCandidates(origin);
307
+ const existing = Object.keys(repos2).find(
308
+ (key) => candidates.has(key)
309
+ );
310
+ if (existing) return existing;
311
+ }
312
+ return originDisplayLabels([origin]).get(origin) ?? origin;
313
+ }
314
+
182
315
  // src/shared/types.ts
183
316
  import { z as z2 } from "zod";
184
317
 
@@ -267,6 +400,7 @@ var assistConfigSchema = z2.strictObject({
267
400
  slack: z2.string().optional(),
268
401
  required: z2.boolean().default(false)
269
402
  }).optional(),
403
+ repos: z2.record(z2.string(), z2.record(z2.string(), z2.unknown())).optional(),
270
404
  run: z2.array(z2.union([runConfigSchema, runLinkSchema])).optional(),
271
405
  subtasks: z2.array(
272
406
  z2.strictObject({
@@ -403,7 +537,10 @@ function getProjectRoot() {
403
537
  function loadConfig() {
404
538
  const globalRaw = loadRawYaml(getGlobalConfigPath());
405
539
  const projectRaw = loadRawYaml(getConfigPath());
406
- const merged = mergeRawConfigs(globalRaw, projectRaw);
540
+ const repoOverride = globalRaw.repos ? resolveRepoOverride(globalRaw, getCurrentOrigin(process.cwd())) : {};
541
+ const globalWithRepo = mergeRawConfigs(globalRaw, repoOverride);
542
+ const merged = mergeRawConfigs(globalWithRepo, projectRaw);
543
+ delete merged.repos;
407
544
  delete merged.news;
408
545
  return assistConfigSchema.parse(merged);
409
546
  }
@@ -1442,8 +1579,8 @@ function findUnmergedPaths() {
1442
1579
  }
1443
1580
  const found = /* @__PURE__ */ new Set();
1444
1581
  for (const line of output.split("\n")) {
1445
- const path70 = line.split(" ")[1];
1446
- if (path70) found.add(path70.trim());
1582
+ const path71 = line.split(" ")[1];
1583
+ if (path71) found.add(path71.trim());
1447
1584
  }
1448
1585
  return [...found];
1449
1586
  }
@@ -1542,8 +1679,8 @@ function getPreferredRemoteRepo(cwd) {
1542
1679
  function gitRefUrl(kind, ref, cwd) {
1543
1680
  const repo = getPreferredRemoteRepo(cwd);
1544
1681
  if (!repo) return void 0;
1545
- const path70 = kind === "branch" ? "tree" : "commit";
1546
- return `https://github.com/${repo.org}/${repo.repo}/${path70}/${ref}`;
1682
+ const path71 = kind === "branch" ? "tree" : "commit";
1683
+ return `https://github.com/${repo.org}/${repo.repo}/${path71}/${ref}`;
1547
1684
  }
1548
1685
 
1549
1686
  // src/commands/commit/collectCommitRefs.ts
@@ -3362,7 +3499,7 @@ function enumerateConfigLeafKeys(schema2) {
3362
3499
  }
3363
3500
 
3364
3501
  // src/commands/verify/pendingConfigDocumentation.ts
3365
- var pendingConfigDocumentation = /* @__PURE__ */ new Set();
3502
+ var pendingConfigDocumentation = /* @__PURE__ */ new Set(["repos"]);
3366
3503
 
3367
3504
  // src/commands/verify/configKeys.ts
3368
3505
  function section(label2, keys) {
@@ -3410,9 +3547,9 @@ import { existsSync as existsSync12, readFileSync as readFileSync9 } from "fs";
3410
3547
 
3411
3548
  // src/commands/verify/forbiddenStrings/findForbiddenStrings.ts
3412
3549
  import { minimatch as minimatch2 } from "minimatch";
3413
- function resolveStringsAtPath(data, path70) {
3550
+ function resolveStringsAtPath(data, path71) {
3414
3551
  let current = data;
3415
- for (const segment of path70.split(".")) {
3552
+ for (const segment of path71.split(".")) {
3416
3553
  if (current === null || typeof current !== "object") return [];
3417
3554
  current = current[segment];
3418
3555
  }
@@ -3425,10 +3562,10 @@ function resolveStringsAtPath(data, path70) {
3425
3562
  }
3426
3563
  function findRuleViolations(data, rule) {
3427
3564
  const violations = [];
3428
- for (const path70 of rule.paths) {
3429
- for (const value of resolveStringsAtPath(data, path70)) {
3565
+ for (const path71 of rule.paths) {
3566
+ for (const value of resolveStringsAtPath(data, path71)) {
3430
3567
  if (minimatch2(value, rule.disallowed))
3431
- violations.push({ file: rule.file, path: path70, value });
3568
+ violations.push({ file: rule.file, path: path71, value });
3432
3569
  }
3433
3570
  }
3434
3571
  return violations;
@@ -3467,8 +3604,8 @@ function forbiddenStrings() {
3467
3604
  process.exit(0);
3468
3605
  }
3469
3606
  console.log("Forbidden strings found:\n");
3470
- for (const { file, path: path70, value } of violations) {
3471
- console.log(` ${file} ${path70}: ${value}`);
3607
+ for (const { file, path: path71, value } of violations) {
3608
+ console.log(` ${file} ${path71}: ${value}`);
3472
3609
  }
3473
3610
  console.log(`
3474
3611
  Total: ${violations.length} forbidden string(s).`);
@@ -3760,15 +3897,15 @@ function readBaselineMigrations(repoRelativeDir, ref) {
3760
3897
  } catch {
3761
3898
  return baseline;
3762
3899
  }
3763
- const paths = listing.split("\n").map((line) => line.trim()).filter(Boolean).filter((path70) => MIGRATION_FILE3.test(basename(path70)));
3764
- for (const path70 of paths) {
3900
+ const paths = listing.split("\n").map((line) => line.trim()).filter(Boolean).filter((path71) => MIGRATION_FILE3.test(basename(path71)));
3901
+ for (const path71 of paths) {
3765
3902
  try {
3766
- const content = execSync12(`git show "${ref}:${path70}"`, {
3903
+ const content = execSync12(`git show "${ref}:${path71}"`, {
3767
3904
  encoding: "utf8",
3768
3905
  maxBuffer: 16 * 1024 * 1024,
3769
3906
  stdio: ["pipe", "pipe", "pipe"]
3770
3907
  });
3771
- baseline.set(basename(path70), content);
3908
+ baseline.set(basename(path71), content);
3772
3909
  } catch {
3773
3910
  }
3774
3911
  }
@@ -5106,8 +5243,16 @@ var daemonPaths = {
5106
5243
  };
5107
5244
 
5108
5245
  // src/commands/sessions/daemon/ensureHooksSettings.ts
5109
- var RUNNING = "assist sessions set-status running";
5110
- var WAITING = "assist sessions set-status waiting";
5246
+ var SET_STATUS = "assist sessions set-status";
5247
+ function running(source) {
5248
+ return `${SET_STATUS} running --source ${source}`;
5249
+ }
5250
+ function waiting(source) {
5251
+ return `${SET_STATUS} waiting --source ${source}`;
5252
+ }
5253
+ function ackWaiting(source) {
5254
+ return `${SET_STATUS} waiting --source ${source} --ack`;
5255
+ }
5111
5256
  function on(command, matcher) {
5112
5257
  const hooks = [{ type: "command", command }];
5113
5258
  return [matcher == null ? { hooks } : { matcher, hooks }];
@@ -5116,27 +5261,22 @@ var ASK_USER_QUESTION = "AskUserQuestion";
5116
5261
  var NOT_ASK_USER_QUESTION = `^(?!${ASK_USER_QUESTION}$).*`;
5117
5262
  var hooksSettings = {
5118
5263
  hooks: {
5119
- UserPromptSubmit: on(RUNNING),
5264
+ UserPromptSubmit: on(running("prompt")),
5120
5265
  PreToolUse: [
5121
- ...on(WAITING, ASK_USER_QUESTION),
5122
- ...on(RUNNING, NOT_ASK_USER_QUESTION)
5266
+ ...on(waiting("pretool"), ASK_USER_QUESTION),
5267
+ ...on(running("pretool"), NOT_ASK_USER_QUESTION)
5123
5268
  ],
5124
- // tool finished, agent resumes; restores running
5125
- PostToolUse: on(RUNNING),
5126
- Stop: on(WAITING),
5127
- Notification: on(WAITING),
5128
- /* why: a tool/plan approval prompt appears mid-turn, after PreToolUse has
5129
- * already set running; PermissionRequest fires when the agent blocks on
5130
- * that decision, so the card shows waiting rather than staying running while
5131
- * it is genuinely awaiting the user (#449). */
5132
- PermissionRequest: on(WAITING)
5269
+ PostToolUse: on(running("posttool")),
5270
+ Stop: on(ackWaiting("stop")),
5271
+ Notification: on(ackWaiting("notification")),
5272
+ PermissionRequest: on(ackWaiting("permission"))
5133
5273
  }
5134
5274
  };
5135
5275
  function ensureHooksSettings() {
5136
- const path70 = daemonPaths.hooksSettings;
5137
- mkdirSync5(dirname12(path70), { recursive: true });
5138
- writeFileSync15(path70, JSON.stringify(hooksSettings, null, 2));
5139
- return path70;
5276
+ const path71 = daemonPaths.hooksSettings;
5277
+ mkdirSync5(dirname12(path71), { recursive: true });
5278
+ writeFileSync15(path71, JSON.stringify(hooksSettings, null, 2));
5279
+ return path71;
5140
5280
  }
5141
5281
 
5142
5282
  // src/shared/spawnInherit.ts
@@ -5401,9 +5541,9 @@ var LOCAL_FILES = ["backlog.jsonl", "backlog.db"];
5401
5541
  function backupLocalBacklogFiles(dir) {
5402
5542
  const moved = [];
5403
5543
  for (const name of LOCAL_FILES) {
5404
- const path70 = join15(dir, ".assist", name);
5405
- if (existsSync18(path70)) {
5406
- renameSync(path70, `${path70}.bak`);
5544
+ const path71 = join15(dir, ".assist", name);
5545
+ if (existsSync18(path71)) {
5546
+ renameSync(path71, `${path71}.bak`);
5407
5547
  moved.push(`${name} \u2192 ${name}.bak`);
5408
5548
  }
5409
5549
  }
@@ -5875,8 +6015,8 @@ var backlogItemSchema = z3.strictObject({
5875
6015
  var backlogFileSchema = z3.array(backlogItemSchema);
5876
6016
 
5877
6017
  // src/commands/backlog/parseBacklogJsonl.ts
5878
- function parseBacklogJsonl(path70) {
5879
- const content = readFileSync14(path70, "utf8").trim();
6018
+ function parseBacklogJsonl(path71) {
6019
+ const content = readFileSync14(path71, "utf8").trim();
5880
6020
  if (content.length === 0) return [];
5881
6021
  return content.split("\n").map((line) => line.trim()).filter(Boolean).map((line) => backlogItemSchema.parse(JSON.parse(line)));
5882
6022
  }
@@ -5956,61 +6096,6 @@ function findBacklogUp(startDir) {
5956
6096
  return null;
5957
6097
  }
5958
6098
 
5959
- // src/commands/backlog/getCurrentOrigin.ts
5960
- import { execFileSync } from "child_process";
5961
- function stripLeadingSlashes(path70) {
5962
- return path70.replace(/^\/+/, "");
5963
- }
5964
- function normalizeOrigin(raw) {
5965
- const trimmed = raw.trim().replace(/\.git$/i, "").replace(/\/+$/, "");
5966
- const url = trimmed.match(
5967
- /^[a-zA-Z][a-zA-Z0-9+.-]*:\/\/(?:[^@/]+@)?([^/:]+)(?::\d+)?\/(.+)$/
5968
- );
5969
- if (url) {
5970
- return `${url[1].toLowerCase()}/${stripLeadingSlashes(url[2])}`;
5971
- }
5972
- if (!trimmed.includes("://")) {
5973
- const scp = trimmed.match(/^(?:[^@/]+@)?([^/:]+):(.+)$/);
5974
- if (scp) {
5975
- return `${scp[1].toLowerCase()}/${stripLeadingSlashes(scp[2])}`;
5976
- }
5977
- }
5978
- return trimmed.toLowerCase();
5979
- }
5980
- function tryGit(cwd, args) {
5981
- const windows = /^[A-Za-z]:[\\/]/.test(cwd);
5982
- const file = windows ? "git.exe" : "git";
5983
- const argv = windows ? ["-C", cwd, ...args] : args;
5984
- try {
5985
- const out = execFileSync(file, argv, {
5986
- encoding: "utf8",
5987
- stdio: ["pipe", "pipe", "pipe"],
5988
- ...windows ? {} : { cwd }
5989
- }).trim();
5990
- return out || null;
5991
- } catch {
5992
- return null;
5993
- }
5994
- }
5995
- function firstRemoteUrl(cwd) {
5996
- const remotes = tryGit(cwd, ["remote"]);
5997
- if (!remotes) return null;
5998
- for (const remote of remotes.split("\n").map((r) => r.trim()).filter(Boolean)) {
5999
- const url = tryGit(cwd, ["remote", "get-url", remote]);
6000
- if (url) return url;
6001
- }
6002
- return null;
6003
- }
6004
- function getRemoteOriginUrl(cwd) {
6005
- return tryGit(cwd, ["remote", "get-url", "origin"]) ?? firstRemoteUrl(cwd);
6006
- }
6007
- function getCurrentOrigin(cwd) {
6008
- const url = getRemoteOriginUrl(cwd);
6009
- if (url) return normalizeOrigin(url);
6010
- const root = tryGit(cwd, ["rev-parse", "--show-toplevel"]);
6011
- return `local:${root ?? cwd}`;
6012
- }
6013
-
6014
6099
  // src/commands/backlog/loadItem.ts
6015
6100
  import { eq as eq5 } from "drizzle-orm";
6016
6101
  async function loadItem(orm, id) {
@@ -6307,20 +6392,87 @@ function sendToDaemon(message) {
6307
6392
  });
6308
6393
  }
6309
6394
 
6395
+ // src/commands/sessions/daemon/sendToDaemonAwaitAck.ts
6396
+ var ACK_TIMEOUT_MS = 1e3;
6397
+ function sendToDaemonAwaitAck(message) {
6398
+ return new Promise((resolve19, reject) => {
6399
+ connectToDaemon().then((socket) => {
6400
+ let settled = false;
6401
+ const finish = (error) => {
6402
+ if (settled) return;
6403
+ settled = true;
6404
+ clearTimeout(timer);
6405
+ socket.destroy();
6406
+ if (error) reject(error);
6407
+ else resolve19();
6408
+ };
6409
+ const timer = setTimeout(
6410
+ () => finish(new Error("timed out awaiting daemon ack")),
6411
+ ACK_TIMEOUT_MS
6412
+ );
6413
+ let buffer = "";
6414
+ socket.on("data", (chunk) => {
6415
+ buffer += chunk.toString("utf8");
6416
+ let newline = buffer.indexOf("\n");
6417
+ while (newline !== -1) {
6418
+ const line = buffer.slice(0, newline);
6419
+ buffer = buffer.slice(newline + 1);
6420
+ if (isAck(line)) return finish();
6421
+ newline = buffer.indexOf("\n");
6422
+ }
6423
+ });
6424
+ socket.on("error", (error) => finish(error));
6425
+ socket.on(
6426
+ "close",
6427
+ () => finish(new Error("daemon closed before acknowledging"))
6428
+ );
6429
+ socket.write(`${JSON.stringify(message)}
6430
+ `);
6431
+ }, reject);
6432
+ });
6433
+ }
6434
+ function isAck(line) {
6435
+ try {
6436
+ return JSON.parse(line).type === "ack";
6437
+ } catch {
6438
+ return false;
6439
+ }
6440
+ }
6441
+
6310
6442
  // src/commands/sessions/setSessionStatus.ts
6311
6443
  var DELIVERY_ATTEMPTS = 3;
6312
6444
  var RETRY_DELAY_MS = 100;
6313
- async function setSessionStatus(status3) {
6445
+ async function setSessionStatus(status3, opts = {}) {
6314
6446
  const sessionId = process.env.ASSIST_SESSION_ID;
6315
- logHookFired(status3, sessionId);
6447
+ logHookFired(status3, sessionId, opts.source);
6316
6448
  if (!sessionId) return;
6317
- await deliverStatus(sessionId, status3);
6449
+ const payload = buildPayload(sessionId, status3, opts);
6450
+ if (opts.ack) await deliverReliably(sessionId, status3, payload);
6451
+ else await deliverBestEffort(sessionId, status3, payload);
6452
+ }
6453
+ function buildPayload(sessionId, status3, opts) {
6454
+ const payload = {
6455
+ type: "set-status",
6456
+ sessionId,
6457
+ status: status3
6458
+ };
6459
+ if (opts.source) payload.source = opts.source;
6460
+ if (opts.ack) payload.ack = true;
6461
+ return payload;
6462
+ }
6463
+ async function deliverBestEffort(sessionId, status3, payload) {
6464
+ try {
6465
+ await sendToDaemon(payload);
6466
+ } catch (error) {
6467
+ appendDaemonLog(
6468
+ `set-status best-effort send failed: id=${sessionId} status=${status3}: ${describeError(error)}`
6469
+ );
6470
+ }
6318
6471
  }
6319
- async function deliverStatus(sessionId, status3) {
6320
- const payload = { type: "set-status", sessionId, status: status3 };
6472
+ async function deliverReliably(sessionId, status3, payload) {
6321
6473
  for (let attempt = 1; attempt <= DELIVERY_ATTEMPTS; attempt++) {
6322
6474
  try {
6323
- await sendToDaemon(payload);
6475
+ await sendToDaemonAwaitAck(payload);
6324
6476
  return;
6325
6477
  } catch (error) {
6326
6478
  if (attempt < DELIVERY_ATTEMPTS) {
@@ -6328,7 +6480,7 @@ async function deliverStatus(sessionId, status3) {
6328
6480
  continue;
6329
6481
  }
6330
6482
  appendDaemonLog(
6331
- `set-status delivery failed after ${DELIVERY_ATTEMPTS} attempts: id=${sessionId} status=${status3}: ${describeError(error)}`
6483
+ `set-status ack'd delivery failed after ${DELIVERY_ATTEMPTS} attempts: id=${sessionId} status=${status3}: ${describeError(error)}`
6332
6484
  );
6333
6485
  }
6334
6486
  }
@@ -6339,9 +6491,9 @@ function sleep(ms) {
6339
6491
  function describeError(error) {
6340
6492
  return error instanceof Error ? error.message : String(error);
6341
6493
  }
6342
- function logHookFired(status3, sessionId) {
6494
+ function logHookFired(status3, sessionId, source) {
6343
6495
  appendDaemonLog(
6344
- `set-status hook fired: id=${sessionId ?? "none"} status=${status3}`
6496
+ `set-status hook fired: id=${sessionId ?? "none"} status=${status3}${source ? ` source=${source}` : ""}`
6345
6497
  );
6346
6498
  }
6347
6499
 
@@ -6499,24 +6651,24 @@ function getOwnerPath(itemId2) {
6499
6651
  function recordSignalOwner(itemId2) {
6500
6652
  const sessionId = process.env.ASSIST_SESSION_ID;
6501
6653
  if (!sessionId) return;
6502
- const path70 = getOwnerPath(itemId2);
6503
- mkdirSync7(dirname14(path70), { recursive: true });
6504
- writeFileSync17(path70, JSON.stringify({ sessionId }));
6654
+ const path71 = getOwnerPath(itemId2);
6655
+ mkdirSync7(dirname14(path71), { recursive: true });
6656
+ writeFileSync17(path71, JSON.stringify({ sessionId }));
6505
6657
  }
6506
6658
  function readSignalOwner(itemId2) {
6507
- const path70 = getOwnerPath(itemId2);
6508
- if (!existsSync21(path70)) return void 0;
6659
+ const path71 = getOwnerPath(itemId2);
6660
+ if (!existsSync21(path71)) return void 0;
6509
6661
  try {
6510
- const parsed = JSON.parse(readFileSync15(path70, "utf8"));
6662
+ const parsed = JSON.parse(readFileSync15(path71, "utf8"));
6511
6663
  return parsed.sessionId;
6512
6664
  } catch {
6513
6665
  return void 0;
6514
6666
  }
6515
6667
  }
6516
6668
  function clearSignalOwner(itemId2) {
6517
- const path70 = getOwnerPath(itemId2);
6669
+ const path71 = getOwnerPath(itemId2);
6518
6670
  try {
6519
- rmSync(path70);
6671
+ rmSync(path71);
6520
6672
  } catch {
6521
6673
  }
6522
6674
  }
@@ -6553,19 +6705,19 @@ function resolveSignalTarget(event, data) {
6553
6705
  function writeSignal(event, data) {
6554
6706
  const target = resolveSignalTarget(event, data);
6555
6707
  if (!target) return;
6556
- const path70 = getSignalPath(target);
6557
- if (!path70) return;
6708
+ const path71 = getSignalPath(target);
6709
+ if (!path71) return;
6558
6710
  const signal = { event, sessionId: target, ...data };
6559
- mkdirSync8(dirname15(path70), { recursive: true });
6560
- writeFileSync18(path70, JSON.stringify(signal));
6711
+ mkdirSync8(dirname15(path71), { recursive: true });
6712
+ writeFileSync18(path71, JSON.stringify(signal));
6561
6713
  }
6562
6714
 
6563
6715
  // src/commands/backlog/readSignal.ts
6564
6716
  function readSignal() {
6565
- const path70 = getSignalPath();
6566
- if (!path70 || !existsSync22(path70)) return void 0;
6717
+ const path71 = getSignalPath();
6718
+ if (!path71 || !existsSync22(path71)) return void 0;
6567
6719
  try {
6568
- return JSON.parse(readFileSync16(path70, "utf8"));
6720
+ return JSON.parse(readFileSync16(path71, "utf8"));
6569
6721
  } catch {
6570
6722
  return void 0;
6571
6723
  }
@@ -6698,13 +6850,13 @@ function activityPath(sessionId) {
6698
6850
  function emitActivity(activity2) {
6699
6851
  const sessionId = process.env.ASSIST_ACTIVITY_ID;
6700
6852
  if (!sessionId) return;
6701
- const path70 = activityPath(sessionId);
6702
- mkdirSync9(dirname16(path70), { recursive: true });
6703
- writeFileSync19(path70, JSON.stringify({ ...activity2, startedAt: Date.now() }));
6853
+ const path71 = activityPath(sessionId);
6854
+ mkdirSync9(dirname16(path71), { recursive: true });
6855
+ writeFileSync19(path71, JSON.stringify({ ...activity2, startedAt: Date.now() }));
6704
6856
  }
6705
- function readActivity(path70) {
6857
+ function readActivity(path71) {
6706
6858
  try {
6707
- return JSON.parse(readFileSync17(path70, "utf8"));
6859
+ return JSON.parse(readFileSync17(path71, "utf8"));
6708
6860
  } catch {
6709
6861
  return void 0;
6710
6862
  }
@@ -6714,9 +6866,9 @@ function reconcileActivity(sessionId, activity2) {
6714
6866
  removeActivity(sessionId);
6715
6867
  return;
6716
6868
  }
6717
- const path70 = activityPath(sessionId);
6718
- mkdirSync9(dirname16(path70), { recursive: true });
6719
- writeFileSync19(path70, JSON.stringify(activity2));
6869
+ const path71 = activityPath(sessionId);
6870
+ mkdirSync9(dirname16(path71), { recursive: true });
6871
+ writeFileSync19(path71, JSON.stringify(activity2));
6720
6872
  }
6721
6873
  function removeActivity(sessionId) {
6722
6874
  try {
@@ -7966,45 +8118,6 @@ async function loadItemSummaries(orm, origin) {
7966
8118
  return rows.map(rowToItemSummary);
7967
8119
  }
7968
8120
 
7969
- // src/commands/backlog/originDisplayName.ts
7970
- function originDisplayName(origin) {
7971
- if (origin.startsWith("local:")) {
7972
- const path70 = origin.slice("local:".length).replace(/\/+$/, "");
7973
- const segments = path70.split("/").filter(Boolean);
7974
- return segments[segments.length - 1] ?? origin;
7975
- }
7976
- const firstSlash = origin.indexOf("/");
7977
- if (firstSlash === -1) return origin;
7978
- return origin.slice(firstSlash + 1);
7979
- }
7980
-
7981
- // src/commands/backlog/originDisplayLabels.ts
7982
- function originDisplayLabels(origins) {
7983
- const isLocal = (origin) => origin.startsWith("local:");
7984
- const bareName = (origin) => {
7985
- const full = originDisplayName(origin);
7986
- const segments = full.split("/");
7987
- return segments[segments.length - 1] ?? full;
7988
- };
7989
- const remoteCounts = /* @__PURE__ */ new Map();
7990
- for (const origin of new Set(origins)) {
7991
- if (isLocal(origin)) continue;
7992
- const name = bareName(origin);
7993
- remoteCounts.set(name, (remoteCounts.get(name) ?? 0) + 1);
7994
- }
7995
- const labels = /* @__PURE__ */ new Map();
7996
- for (const origin of origins) {
7997
- if (isLocal(origin)) {
7998
- labels.set(origin, originDisplayName(origin));
7999
- continue;
8000
- }
8001
- const name = bareName(origin);
8002
- const collides = (remoteCounts.get(name) ?? 0) > 1;
8003
- labels.set(origin, collides ? originDisplayName(origin) : name);
8004
- }
8005
- return labels;
8006
- }
8007
-
8008
8121
  // src/commands/backlog/resolveRepoLocation.ts
8009
8122
  import { existsSync as existsSync25 } from "fs";
8010
8123
 
@@ -8406,7 +8519,7 @@ function findSynthesisForBranch(repoReviewsDir, branch2) {
8406
8519
  const parent = dirname20(branchKeyPath);
8407
8520
  const branchPrefix = basename5(branchKeyPath);
8408
8521
  if (!existsSync26(parent)) return null;
8409
- const synthesisFiles = readdirSync2(parent).filter((name) => name.startsWith(branchPrefix)).map((name) => join24(parent, name, "synthesis.md")).filter((path70) => existsSync26(path70)).map((path70) => ({ path: path70, mtime: statSync2(path70).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
8522
+ const synthesisFiles = readdirSync2(parent).filter((name) => name.startsWith(branchPrefix)).map((name) => join24(parent, name, "synthesis.md")).filter((path71) => existsSync26(path71)).map((path71) => ({ path: path71, mtime: statSync2(path71).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
8410
8523
  return synthesisFiles[0]?.path ?? null;
8411
8524
  }
8412
8525
 
@@ -8460,12 +8573,12 @@ async function getReviewSynthesis(req, res) {
8460
8573
  const cwd = getCwdParam(req, res);
8461
8574
  if (!cwd) return;
8462
8575
  try {
8463
- const path70 = await resolveSynthesisPath(cwd);
8464
- if (!path70) {
8576
+ const path71 = await resolveSynthesisPath(cwd);
8577
+ if (!path71) {
8465
8578
  respondJson(res, 404, { error: "No synthesis found" });
8466
8579
  return;
8467
8580
  }
8468
- respondJson(res, 200, { synthesis: readFileSync19(path70, "utf8") });
8581
+ respondJson(res, 200, { synthesis: readFileSync19(path71, "utf8") });
8469
8582
  } catch {
8470
8583
  respondJson(res, 404, { error: "No synthesis found" });
8471
8584
  }
@@ -8612,10 +8725,10 @@ function getStorePath(filename) {
8612
8725
  return join27(getStoreDir(), filename);
8613
8726
  }
8614
8727
  function loadJson(filename) {
8615
- const path70 = getStorePath(filename);
8616
- if (existsSync27(path70)) {
8728
+ const path71 = getStorePath(filename);
8729
+ if (existsSync27(path71)) {
8617
8730
  try {
8618
- return JSON.parse(readFileSync20(path70, "utf8"));
8731
+ return JSON.parse(readFileSync20(path71, "utf8"));
8619
8732
  } catch {
8620
8733
  return {};
8621
8734
  }
@@ -9725,9 +9838,9 @@ function originToSshUrl(origin) {
9725
9838
  const firstSlash = origin.indexOf("/");
9726
9839
  if (firstSlash <= 0) return null;
9727
9840
  const host = origin.slice(0, firstSlash);
9728
- const path70 = origin.slice(firstSlash + 1);
9729
- if (!path70) return null;
9730
- return `git@${host}:${path70}.git`;
9841
+ const path71 = origin.slice(firstSlash + 1);
9842
+ if (!path71) return null;
9843
+ return `git@${host}:${path71}.git`;
9731
9844
  }
9732
9845
 
9733
9846
  // src/commands/backlog/cloneRepo.ts
@@ -12036,9 +12149,9 @@ var __dirname4 = dirname21(__filename3);
12036
12149
  function packageRoot() {
12037
12150
  return __dirname4;
12038
12151
  }
12039
- function readLines(path70) {
12040
- if (!existsSync29(path70)) return [];
12041
- return readFileSync23(path70, "utf8").split("\n").filter((line) => line.trim() !== "");
12152
+ function readLines(path71) {
12153
+ if (!existsSync29(path71)) return [];
12154
+ return readFileSync23(path71, "utf8").split("\n").filter((line) => line.trim() !== "");
12042
12155
  }
12043
12156
  var cachedReads;
12044
12157
  var cachedWrites;
@@ -12530,14 +12643,14 @@ function showProgress(p, label2) {
12530
12643
  const pct = Math.round(p.done / p.total * 100);
12531
12644
  process.stderr.write(`\r\x1B[K[${pct}%] Scanning ${label2}...`);
12532
12645
  }
12533
- async function resolveCommand(cli, path70, description, depth, p) {
12534
- showProgress(p, path70.join(" "));
12535
- const subHelp = await runHelp([cli, ...path70]);
12646
+ async function resolveCommand(cli, path71, description, depth, p) {
12647
+ showProgress(p, path71.join(" "));
12648
+ const subHelp = await runHelp([cli, ...path71]);
12536
12649
  if (!subHelp || !hasSubcommands(subHelp)) {
12537
- return [{ path: path70, description }];
12650
+ return [{ path: path71, description }];
12538
12651
  }
12539
- const children = await discoverAt(cli, path70, depth + 1, p);
12540
- return children.length > 0 ? children : [{ path: path70, description }];
12652
+ const children = await discoverAt(cli, path71, depth + 1, p);
12653
+ return children.length > 0 ? children : [{ path: path71, description }];
12541
12654
  }
12542
12655
  async function discoverAt(cli, parentPath, depth, p) {
12543
12656
  if (depth > SAFETY_DEPTH) return [];
@@ -12685,9 +12798,9 @@ function logPath(cli) {
12685
12798
  return join31(homedir16(), ".assist", `cli-discover-${safeName}.log`);
12686
12799
  }
12687
12800
  function readCache(cli) {
12688
- const path70 = logPath(cli);
12689
- if (!existsSync31(path70)) return void 0;
12690
- return readFileSync25(path70, "utf8");
12801
+ const path71 = logPath(cli);
12802
+ if (!existsSync31(path71)) return void 0;
12803
+ return readFileSync25(path71, "utf8");
12691
12804
  }
12692
12805
  function writeCache(cli, output) {
12693
12806
  const dir = join31(homedir16(), ".assist");
@@ -12859,9 +12972,9 @@ function sweepRestrictedDir(dir = getRestrictedDir()) {
12859
12972
  }
12860
12973
  const cutoff = Date.now() - STALE_AFTER_MS;
12861
12974
  for (const entry of entries) {
12862
- const path70 = join33(dir, entry);
12975
+ const path71 = join33(dir, entry);
12863
12976
  try {
12864
- if (statSync3(path70).mtimeMs < cutoff) unlinkSync7(path70);
12977
+ if (statSync3(path71).mtimeMs < cutoff) unlinkSync7(path71);
12865
12978
  } catch {
12866
12979
  continue;
12867
12980
  }
@@ -12871,10 +12984,10 @@ function sweepRestrictedDir(dir = getRestrictedDir()) {
12871
12984
  // src/commands/codeComment/readPinState.ts
12872
12985
  import { existsSync as existsSync32, readFileSync as readFileSync26 } from "fs";
12873
12986
  function readPinState(pin) {
12874
- const path70 = getPinStatePath(pin);
12875
- if (!existsSync32(path70)) return void 0;
12987
+ const path71 = getPinStatePath(pin);
12988
+ if (!existsSync32(path71)) return void 0;
12876
12989
  try {
12877
- const state = JSON.parse(readFileSync26(path70, "utf8"));
12990
+ const state = JSON.parse(readFileSync26(path71, "utf8"));
12878
12991
  if (state.pin !== pin) return void 0;
12879
12992
  return state;
12880
12993
  } catch {
@@ -13730,26 +13843,69 @@ function registerComplexity(program2) {
13730
13843
  }
13731
13844
 
13732
13845
  // src/commands/config/index.ts
13733
- import chalk122 from "chalk";
13734
13846
  import { stringify as stringifyYaml2 } from "yaml";
13847
+ function configList() {
13848
+ const config = loadConfig();
13849
+ console.log(stringifyYaml2(config, { lineWidth: 0 }).trimEnd());
13850
+ }
13735
13851
 
13736
- // src/commands/config/setNestedValue.ts
13737
- function isPlainObject(val) {
13738
- return val !== null && typeof val === "object" && !Array.isArray(val);
13852
+ // src/commands/config/configGet.ts
13853
+ import chalk122 from "chalk";
13854
+
13855
+ // src/commands/config/getNestedValue.ts
13856
+ function isTraversable(value) {
13857
+ return value !== null && value !== void 0 && typeof value === "object";
13739
13858
  }
13740
- function isNumericKey(key) {
13741
- return /^\d+$/.test(key);
13859
+ function stepInto(current, key) {
13860
+ return isTraversable(current) ? current[key] : void 0;
13742
13861
  }
13743
- function resolveKey(key) {
13744
- return isNumericKey(key) ? Number.parseInt(key, 10) : key;
13862
+ function getNestedValue(obj, path71) {
13863
+ let current = obj;
13864
+ for (const key of path71.split(".")) current = stepInto(current, key);
13865
+ return current;
13745
13866
  }
13746
- function getItem(container, key) {
13747
- if (Array.isArray(container)) return container[key];
13748
- return container[key];
13867
+
13868
+ // src/commands/config/configGet.ts
13869
+ function configGet(key) {
13870
+ console.log(
13871
+ formatOutput(
13872
+ requireNestedValue(loadConfig(), key)
13873
+ )
13874
+ );
13749
13875
  }
13750
- function setItem(container, key, value) {
13751
- if (Array.isArray(container)) container[key] = value;
13752
- else container[key] = value;
13876
+ function formatOutput(value) {
13877
+ return typeof value === "object" && value !== null ? JSON.stringify(value, null, 2) : String(value);
13878
+ }
13879
+ function requireNestedValue(config, key) {
13880
+ const value = getNestedValue(config, key);
13881
+ if (value === void 0) return exitKeyNotSet(key);
13882
+ return value;
13883
+ }
13884
+ function exitKeyNotSet(key) {
13885
+ console.error(chalk122.red(`Key "${key}" is not set`));
13886
+ process.exit(1);
13887
+ }
13888
+
13889
+ // src/commands/config/configSet.ts
13890
+ import chalk124 from "chalk";
13891
+
13892
+ // src/commands/config/setNestedValue.ts
13893
+ function isPlainObject(val) {
13894
+ return val !== null && typeof val === "object" && !Array.isArray(val);
13895
+ }
13896
+ function isNumericKey(key) {
13897
+ return /^\d+$/.test(key);
13898
+ }
13899
+ function resolveKey(key) {
13900
+ return isNumericKey(key) ? Number.parseInt(key, 10) : key;
13901
+ }
13902
+ function getItem(container, key) {
13903
+ if (Array.isArray(container)) return container[key];
13904
+ return container[key];
13905
+ }
13906
+ function setItem(container, key, value) {
13907
+ if (Array.isArray(container)) container[key] = value;
13908
+ else container[key] = value;
13753
13909
  }
13754
13910
  function ensureArray(container, key) {
13755
13911
  const existing = getItem(container, key);
@@ -13770,8 +13926,8 @@ function stepIntoNested(container, key, nextKey) {
13770
13926
  }
13771
13927
  return ensureObject(container, resolved);
13772
13928
  }
13773
- function setNestedValue(obj, path70, value) {
13774
- const keys = path70.split(".");
13929
+ function setNestedValue(obj, path71, value) {
13930
+ const keys = path71.split(".");
13775
13931
  const result = { ...obj };
13776
13932
  let current = result;
13777
13933
  for (let i = 0; i < keys.length - 1; i++) {
@@ -13781,41 +13937,64 @@ function setNestedValue(obj, path70, value) {
13781
13937
  return result;
13782
13938
  }
13783
13939
 
13784
- // src/commands/config/index.ts
13785
- function coerceValue(value) {
13786
- if (value === "true") return true;
13787
- if (value === "false") return false;
13788
- return value;
13940
+ // src/commands/config/validateConfig.ts
13941
+ import chalk123 from "chalk";
13942
+ function validateConfig(updated, key) {
13943
+ const result = assistConfigSchema.safeParse(updated);
13944
+ if (!result.success) return exitValidationFailed(result.error.issues, key);
13945
+ return updated;
13789
13946
  }
13790
- function formatIssuePath(issue, key) {
13791
- return issue.path.length > 0 ? issue.path.join(".") : key;
13947
+ function exitValidationFailed(issues, key) {
13948
+ printValidationErrors(issues, key);
13949
+ process.exit(1);
13792
13950
  }
13793
13951
  function printValidationErrors(issues, key) {
13794
13952
  for (const issue of issues) {
13795
13953
  console.error(
13796
- chalk122.red(`${formatIssuePath(issue, key)}: ${issue.message}`)
13954
+ chalk123.red(`${formatIssuePath(issue, key)}: ${issue.message}`)
13797
13955
  );
13798
13956
  }
13799
13957
  }
13800
- function exitValidationFailed(issues, key) {
13801
- printValidationErrors(issues, key);
13802
- process.exit(1);
13958
+ function formatIssuePath(issue, key) {
13959
+ return issue.path.length > 0 ? issue.path.join(".") : key;
13803
13960
  }
13804
- function validateConfig(updated, key) {
13805
- const result = assistConfigSchema.safeParse(updated);
13806
- if (!result.success) return exitValidationFailed(result.error.issues, key);
13807
- return updated;
13961
+
13962
+ // src/commands/config/applyRepoConfigSet.ts
13963
+ function applyRepoConfigSet(key, coerced) {
13964
+ const globalRaw = loadGlobalConfigRaw();
13965
+ const label2 = resolveRepoWriteLabel(
13966
+ globalRaw,
13967
+ getCurrentOrigin(process.cwd())
13968
+ );
13969
+ const repos2 = isPlainObject2(globalRaw.repos) ? { ...globalRaw.repos } : {};
13970
+ const existingBlock = isPlainObject2(repos2[label2]) ? repos2[label2] : {};
13971
+ const updatedBlock = setNestedValue(existingBlock, key, coerced);
13972
+ validateConfig(updatedBlock, key);
13973
+ repos2[label2] = updatedBlock;
13974
+ saveGlobalConfig({ ...globalRaw, repos: repos2 });
13975
+ return label2;
13808
13976
  }
13977
+ function isPlainObject2(value) {
13978
+ return value !== null && typeof value === "object" && !Array.isArray(value);
13979
+ }
13980
+
13981
+ // src/commands/config/configSet.ts
13809
13982
  var GLOBAL_ONLY_KEYS = ["sync.autoConfirm"];
13810
- function assertNotGlobalOnly(key, global) {
13811
- if (!global && GLOBAL_ONLY_KEYS.some((k) => key.startsWith(k))) {
13812
- console.error(
13813
- chalk122.red(
13814
- `"${key}" is a global-only key. Use --global to set it in ~/.assist.yml`
13815
- )
13816
- );
13983
+ function configSet(key, value, options2 = {}) {
13984
+ const coerced = coerceValue(value);
13985
+ if (options2.repo && options2.global) {
13986
+ console.error(chalk124.red("Use either --repo or --global, not both"));
13817
13987
  process.exit(1);
13818
13988
  }
13989
+ const target = options2.repo ? `repo: ${applyRepoConfigSet(key, coerced)}` : applyConfigSet(key, coerced, options2.global ?? false);
13990
+ console.log(
13991
+ chalk124.green(`Set ${key} = ${JSON.stringify(coerced)} (${target})`)
13992
+ );
13993
+ }
13994
+ function coerceValue(value) {
13995
+ if (value === "true") return true;
13996
+ if (value === "false") return false;
13997
+ return value;
13819
13998
  }
13820
13999
  function applyConfigSet(key, coerced, global) {
13821
14000
  assertNotGlobalOnly(key, global);
@@ -13824,103 +14003,68 @@ function applyConfigSet(key, coerced, global) {
13824
14003
  validateConfig(updated, key);
13825
14004
  if (global) {
13826
14005
  saveGlobalConfig(updated);
13827
- } else {
13828
- saveConfig(updated);
14006
+ return "global";
13829
14007
  }
14008
+ saveConfig(updated);
14009
+ return "project";
13830
14010
  }
13831
- function configSet(key, value, options2 = {}) {
13832
- const coerced = coerceValue(value);
13833
- applyConfigSet(key, coerced, options2.global ?? false);
13834
- const target = options2.global ? "global" : "project";
13835
- console.log(
13836
- chalk122.green(`Set ${key} = ${JSON.stringify(coerced)} (${target})`)
13837
- );
13838
- }
13839
- function configList() {
13840
- const config = loadConfig();
13841
- console.log(stringifyYaml2(config, { lineWidth: 0 }).trimEnd());
13842
- }
13843
-
13844
- // src/commands/config/configGet.ts
13845
- import chalk123 from "chalk";
13846
-
13847
- // src/commands/config/getNestedValue.ts
13848
- function isTraversable(value) {
13849
- return value !== null && value !== void 0 && typeof value === "object";
13850
- }
13851
- function stepInto(current, key) {
13852
- return isTraversable(current) ? current[key] : void 0;
13853
- }
13854
- function getNestedValue(obj, path70) {
13855
- let current = obj;
13856
- for (const key of path70.split(".")) current = stepInto(current, key);
13857
- return current;
13858
- }
13859
-
13860
- // src/commands/config/configGet.ts
13861
- function configGet(key) {
13862
- console.log(
13863
- formatOutput(
13864
- requireNestedValue(loadConfig(), key)
13865
- )
13866
- );
13867
- }
13868
- function formatOutput(value) {
13869
- return typeof value === "object" && value !== null ? JSON.stringify(value, null, 2) : String(value);
13870
- }
13871
- function requireNestedValue(config, key) {
13872
- const value = getNestedValue(config, key);
13873
- if (value === void 0) return exitKeyNotSet(key);
13874
- return value;
13875
- }
13876
- function exitKeyNotSet(key) {
13877
- console.error(chalk123.red(`Key "${key}" is not set`));
13878
- process.exit(1);
14011
+ function assertNotGlobalOnly(key, global) {
14012
+ if (!global && GLOBAL_ONLY_KEYS.some((k) => key.startsWith(k))) {
14013
+ console.error(
14014
+ chalk124.red(
14015
+ `"${key}" is a global-only key. Use --global to set it in ~/.assist.yml`
14016
+ )
14017
+ );
14018
+ process.exit(1);
14019
+ }
13879
14020
  }
13880
14021
 
13881
14022
  // src/commands/registerConfig.ts
13882
14023
  function registerConfig(program2) {
13883
14024
  const configCommand = program2.command("config").description("View and modify assist.yml configuration");
13884
- configCommand.command("set <key> <value>").description("Set a config value (e.g. commit.push true)").option("-g, --global", "Write to global ~/.assist.yml").action((key, value, options2) => configSet(key, value, options2));
14025
+ configCommand.command("set <key> <value>").description("Set a config value (e.g. commit.push true)").option("-g, --global", "Write to global ~/.assist.yml").option(
14026
+ "-r, --repo",
14027
+ "Write to ~/.assist.yml under the current repo's identity"
14028
+ ).action((key, value, options2) => configSet(key, value, options2));
13885
14029
  configCommand.command("get <key>").description("Get a config value").action(configGet);
13886
14030
  configCommand.command("list").description("List all config values").action(configList);
13887
14031
  }
13888
14032
 
13889
14033
  // src/commands/db/reportMigrationStatus.ts
13890
- import chalk124 from "chalk";
14034
+ import chalk125 from "chalk";
13891
14035
  function reportApplied(applied) {
13892
14036
  if (applied.length === 0) {
13893
- console.error(chalk124.green("Database is up to date; nothing to apply."));
14037
+ console.error(chalk125.green("Database is up to date; nothing to apply."));
13894
14038
  return;
13895
14039
  }
13896
14040
  for (const migration of applied) {
13897
14041
  console.error(
13898
- chalk124.green(`Applied migration ${migration.id} (${migration.name}).`)
14042
+ chalk125.green(`Applied migration ${migration.id} (${migration.name}).`)
13899
14043
  );
13900
14044
  }
13901
14045
  }
13902
14046
  function reportMigrationStatus(status3) {
13903
14047
  if (status3.state === "in-sync") {
13904
14048
  console.error(
13905
- chalk124.green(`In sync at migration ${status3.version} (latest).`)
14049
+ chalk125.green(`In sync at migration ${status3.version} (latest).`)
13906
14050
  );
13907
14051
  return;
13908
14052
  }
13909
14053
  if (status3.state === "behind") {
13910
14054
  console.error(
13911
- chalk124.yellow(
14055
+ chalk125.yellow(
13912
14056
  `Behind: applied ${status3.applied}, build expects ${status3.expected}.`
13913
14057
  )
13914
14058
  );
13915
14059
  console.error(
13916
- chalk124.yellow(
14060
+ chalk125.yellow(
13917
14061
  `Pending: ${status3.pending.join(", ")}. Run \`assist db migrate\`.`
13918
14062
  )
13919
14063
  );
13920
14064
  return;
13921
14065
  }
13922
14066
  console.error(
13923
- chalk124.red(
14067
+ chalk125.red(
13924
14068
  `Ahead: applied ${status3.applied}, build knows ${status3.expected}. Update assist.`
13925
14069
  )
13926
14070
  );
@@ -13955,7 +14099,7 @@ function registerDb(program2) {
13955
14099
 
13956
14100
  // src/commands/dbMigration/dbMigrationConfirm.ts
13957
14101
  import { unlinkSync as unlinkSync9, writeFileSync as writeFileSync26 } from "fs";
13958
- import chalk125 from "chalk";
14102
+ import chalk126 from "chalk";
13959
14103
 
13960
14104
  // src/commands/dbMigration/getMigrationPinPath.ts
13961
14105
  import { join as join34 } from "path";
@@ -13969,10 +14113,10 @@ function getMigrationApprovalPath(migrationId) {
13969
14113
  // src/commands/dbMigration/readMigrationPinState.ts
13970
14114
  import { existsSync as existsSync34, readFileSync as readFileSync28 } from "fs";
13971
14115
  function readMigrationPinState(pin) {
13972
- const path70 = getMigrationPinPath(pin);
13973
- if (!existsSync34(path70)) return void 0;
14116
+ const path71 = getMigrationPinPath(pin);
14117
+ if (!existsSync34(path71)) return void 0;
13974
14118
  try {
13975
- const state = JSON.parse(readFileSync28(path70, "utf8"));
14119
+ const state = JSON.parse(readFileSync28(path71, "utf8"));
13976
14120
  if (state.pin !== pin) return void 0;
13977
14121
  if (!Number.isInteger(state.migrationId)) return void 0;
13978
14122
  return state;
@@ -13986,7 +14130,7 @@ function dbMigrationConfirm(pin) {
13986
14130
  sweepRestrictedDir();
13987
14131
  const state = readMigrationPinState(pin);
13988
14132
  if (!state) {
13989
- console.error(chalk125.red(`No pending migration unlock for pin: ${pin}`));
14133
+ console.error(chalk126.red(`No pending migration unlock for pin: ${pin}`));
13990
14134
  process.exitCode = 1;
13991
14135
  return;
13992
14136
  }
@@ -13996,7 +14140,7 @@ function dbMigrationConfirm(pin) {
13996
14140
  );
13997
14141
  unlinkSync9(getMigrationPinPath(pin));
13998
14142
  console.log(
13999
- chalk125.green(
14143
+ chalk126.green(
14000
14144
  `Approved creation of migration ${state.migrationId}. The next write of that migration module will be allowed once.`
14001
14145
  )
14002
14146
  );
@@ -14005,7 +14149,7 @@ function dbMigrationConfirm(pin) {
14005
14149
  // src/commands/dbMigration/dbMigrationUnlock.ts
14006
14150
  import { mkdirSync as mkdirSync15, writeFileSync as writeFileSync27 } from "fs";
14007
14151
  import { randomInt as randomInt2 } from "crypto";
14008
- import chalk126 from "chalk";
14152
+ import chalk127 from "chalk";
14009
14153
 
14010
14154
  // src/commands/dbMigration/nextMigrationId.ts
14011
14155
  function nextMigrationId() {
@@ -14020,7 +14164,7 @@ function dbMigrationUnlock() {
14020
14164
  sweepRestrictedDir();
14021
14165
  writeFileSync27(getMigrationPinPath(pin), JSON.stringify({ pin, migrationId }));
14022
14166
  console.error(
14023
- chalk126.yellow.bold(
14167
+ chalk127.yellow.bold(
14024
14168
  "THIS IS YOUR LAST CHANCE TO RECONSIDER BEFORE INVOLVING A HUMAN.\nRequesting this pin pages a real person to approve a new database migration.\nA schema change is hard to reverse once shipped. You had BETTER have confirmed\nthe change with the user and be certain this migration is genuinely necessary."
14025
14169
  )
14026
14170
  );
@@ -14030,7 +14174,7 @@ function dbMigrationUnlock() {
14030
14174
  });
14031
14175
  if (!delivered) {
14032
14176
  console.error(
14033
- chalk126.red(
14177
+ chalk127.red(
14034
14178
  "Could not deliver the confirmation pin via notification.\nThe migration cannot be approved until the notification channel works."
14035
14179
  )
14036
14180
  );
@@ -14040,7 +14184,7 @@ function dbMigrationUnlock() {
14040
14184
  console.log(
14041
14185
  `A confirmation pin was sent to your desktop notifications.
14042
14186
  To approve creating migration ${migrationId}, run:
14043
- ${chalk126.cyan(" assist db-migration confirm <PIN>")}
14187
+ ${chalk127.cyan(" assist db-migration confirm <PIN>")}
14044
14188
  using the pin from that notification.`
14045
14189
  );
14046
14190
  }
@@ -14060,7 +14204,7 @@ function registerDbMigration(parent) {
14060
14204
 
14061
14205
  // src/commands/deploy/redirect.ts
14062
14206
  import { existsSync as existsSync35, readFileSync as readFileSync29, writeFileSync as writeFileSync28 } from "fs";
14063
- import chalk127 from "chalk";
14207
+ import chalk128 from "chalk";
14064
14208
  var TRAILING_SLASH_SCRIPT = ` <script>
14065
14209
  if (!window.location.pathname.endsWith('/')) {
14066
14210
  window.location.href = \`\${window.location.pathname}/\${window.location.search}\${window.location.hash}\`;
@@ -14069,23 +14213,23 @@ var TRAILING_SLASH_SCRIPT = ` <script>
14069
14213
  function redirect() {
14070
14214
  const indexPath = "index.html";
14071
14215
  if (!existsSync35(indexPath)) {
14072
- console.log(chalk127.yellow("No index.html found"));
14216
+ console.log(chalk128.yellow("No index.html found"));
14073
14217
  return;
14074
14218
  }
14075
14219
  const content = readFileSync29(indexPath, "utf8");
14076
14220
  if (content.includes("window.location.pathname.endsWith('/')")) {
14077
- console.log(chalk127.dim("Trailing slash script already present"));
14221
+ console.log(chalk128.dim("Trailing slash script already present"));
14078
14222
  return;
14079
14223
  }
14080
14224
  const headCloseIndex = content.indexOf("</head>");
14081
14225
  if (headCloseIndex === -1) {
14082
- console.log(chalk127.red("Could not find </head> tag in index.html"));
14226
+ console.log(chalk128.red("Could not find </head> tag in index.html"));
14083
14227
  return;
14084
14228
  }
14085
14229
  const newContent = `${content.slice(0, headCloseIndex) + TRAILING_SLASH_SCRIPT}
14086
14230
  ${content.slice(headCloseIndex)}`;
14087
14231
  writeFileSync28(indexPath, newContent);
14088
- console.log(chalk127.green("Added trailing slash redirect to index.html"));
14232
+ console.log(chalk128.green("Added trailing slash redirect to index.html"));
14089
14233
  }
14090
14234
 
14091
14235
  // src/commands/registerDeploy.ts
@@ -14112,7 +14256,7 @@ function loadBlogSkipDays(repoName) {
14112
14256
 
14113
14257
  // src/commands/devlog/shared.ts
14114
14258
  import { execSync as execSync33 } from "child_process";
14115
- import chalk128 from "chalk";
14259
+ import chalk129 from "chalk";
14116
14260
 
14117
14261
  // src/shared/getRepoName.ts
14118
14262
  import { existsSync as existsSync36, readFileSync as readFileSync30 } from "fs";
@@ -14221,13 +14365,13 @@ function shouldIgnoreCommit(files, ignorePaths) {
14221
14365
  }
14222
14366
  function printCommitsWithFiles(commits2, ignore3, verbose) {
14223
14367
  for (const commit2 of commits2) {
14224
- console.log(` ${chalk128.yellow(commit2.hash)} ${commit2.message}`);
14368
+ console.log(` ${chalk129.yellow(commit2.hash)} ${commit2.message}`);
14225
14369
  if (verbose) {
14226
14370
  const visibleFiles = commit2.files.filter(
14227
14371
  (file) => !ignore3.some((p) => file.startsWith(p))
14228
14372
  );
14229
14373
  for (const file of visibleFiles) {
14230
- console.log(` ${chalk128.dim(file)}`);
14374
+ console.log(` ${chalk129.dim(file)}`);
14231
14375
  }
14232
14376
  }
14233
14377
  }
@@ -14252,15 +14396,15 @@ function parseGitLogCommits(output, ignore3, afterDate) {
14252
14396
  }
14253
14397
 
14254
14398
  // src/commands/devlog/list/printDateHeader.ts
14255
- import chalk129 from "chalk";
14399
+ import chalk130 from "chalk";
14256
14400
  function printDateHeader(date, isSkipped, entries) {
14257
14401
  if (isSkipped) {
14258
- console.log(`${chalk129.bold.blue(date)} ${chalk129.dim("skipped")}`);
14402
+ console.log(`${chalk130.bold.blue(date)} ${chalk130.dim("skipped")}`);
14259
14403
  } else if (entries && entries.length > 0) {
14260
- const entryInfo = entries.map((e) => `${chalk129.green(e.version)} ${e.title}`).join(" | ");
14261
- console.log(`${chalk129.bold.blue(date)} ${entryInfo}`);
14404
+ const entryInfo = entries.map((e) => `${chalk130.green(e.version)} ${e.title}`).join(" | ");
14405
+ console.log(`${chalk130.bold.blue(date)} ${entryInfo}`);
14262
14406
  } else {
14263
- console.log(`${chalk129.bold.blue(date)} ${chalk129.red("\u26A0 devlog missing")}`);
14407
+ console.log(`${chalk130.bold.blue(date)} ${chalk130.red("\u26A0 devlog missing")}`);
14264
14408
  }
14265
14409
  }
14266
14410
 
@@ -14364,24 +14508,24 @@ function bumpVersion(version2, type) {
14364
14508
 
14365
14509
  // src/commands/devlog/next/displayNextEntry/index.ts
14366
14510
  import { execFileSync as execFileSync4 } from "child_process";
14367
- import chalk131 from "chalk";
14511
+ import chalk132 from "chalk";
14368
14512
 
14369
14513
  // src/commands/devlog/next/displayNextEntry/displayVersion.ts
14370
- import chalk130 from "chalk";
14514
+ import chalk131 from "chalk";
14371
14515
  function displayVersion(conventional, firstHash, patchVersion, minorVersion) {
14372
14516
  if (conventional && firstHash) {
14373
14517
  const version2 = getVersionAtCommit(firstHash);
14374
14518
  if (version2) {
14375
- console.log(`${chalk130.bold("version:")} ${stripToMinor(version2)}`);
14519
+ console.log(`${chalk131.bold("version:")} ${stripToMinor(version2)}`);
14376
14520
  } else {
14377
- console.log(`${chalk130.bold("version:")} ${chalk130.red("unknown")}`);
14521
+ console.log(`${chalk131.bold("version:")} ${chalk131.red("unknown")}`);
14378
14522
  }
14379
14523
  } else if (patchVersion && minorVersion) {
14380
14524
  console.log(
14381
- `${chalk130.bold("version:")} ${patchVersion} (patch) or ${minorVersion} (minor)`
14525
+ `${chalk131.bold("version:")} ${patchVersion} (patch) or ${minorVersion} (minor)`
14382
14526
  );
14383
14527
  } else {
14384
- console.log(`${chalk130.bold("version:")} v0.1 (initial)`);
14528
+ console.log(`${chalk131.bold("version:")} v0.1 (initial)`);
14385
14529
  }
14386
14530
  }
14387
14531
 
@@ -14429,16 +14573,16 @@ function noCommitsMessage(hasLastInfo) {
14429
14573
  return hasLastInfo ? "No commits after last versioned entry" : "No commits found";
14430
14574
  }
14431
14575
  function logName(repoName) {
14432
- console.log(`${chalk131.bold("name:")} ${repoName}`);
14576
+ console.log(`${chalk132.bold("name:")} ${repoName}`);
14433
14577
  }
14434
14578
  function displayNextEntry(ctx, targetDate, commits2) {
14435
14579
  logName(ctx.repoName);
14436
14580
  printVersionInfo(ctx.config, ctx.lastInfo, commits2[0]?.hash);
14437
- console.log(chalk131.bold.blue(targetDate));
14581
+ console.log(chalk132.bold.blue(targetDate));
14438
14582
  printCommitsWithFiles(commits2, ctx.ignore, ctx.verbose);
14439
14583
  }
14440
14584
  function logNoCommits(lastInfo) {
14441
- console.log(chalk131.dim(noCommitsMessage(!!lastInfo)));
14585
+ console.log(chalk132.dim(noCommitsMessage(!!lastInfo)));
14442
14586
  }
14443
14587
 
14444
14588
  // src/commands/devlog/next/index.ts
@@ -14479,11 +14623,11 @@ function next2(options2) {
14479
14623
  import { execSync as execSync35 } from "child_process";
14480
14624
 
14481
14625
  // src/commands/devlog/repos/printReposTable.ts
14482
- import chalk132 from "chalk";
14626
+ import chalk133 from "chalk";
14483
14627
  function colorStatus(status3) {
14484
- if (status3 === "missing") return chalk132.red(status3);
14485
- if (status3 === "outdated") return chalk132.yellow(status3);
14486
- return chalk132.green(status3);
14628
+ if (status3 === "missing") return chalk133.red(status3);
14629
+ if (status3 === "outdated") return chalk133.yellow(status3);
14630
+ return chalk133.green(status3);
14487
14631
  }
14488
14632
  function formatRow(row, nameWidth) {
14489
14633
  const devlog = (row.lastDevlog ?? "-").padEnd(11);
@@ -14497,8 +14641,8 @@ function printReposTable(rows) {
14497
14641
  "Last Devlog".padEnd(11),
14498
14642
  "Status"
14499
14643
  ].join(" ");
14500
- console.log(chalk132.dim(header));
14501
- console.log(chalk132.dim("-".repeat(header.length)));
14644
+ console.log(chalk133.dim(header));
14645
+ console.log(chalk133.dim("-".repeat(header.length)));
14502
14646
  for (const row of rows) {
14503
14647
  console.log(formatRow(row, nameWidth));
14504
14648
  }
@@ -14556,14 +14700,14 @@ function repos(options2) {
14556
14700
  // src/commands/devlog/skip.ts
14557
14701
  import { writeFileSync as writeFileSync29 } from "fs";
14558
14702
  import { join as join38 } from "path";
14559
- import chalk133 from "chalk";
14703
+ import chalk134 from "chalk";
14560
14704
  import { stringify as stringifyYaml3 } from "yaml";
14561
14705
  function getBlogConfigPath() {
14562
14706
  return join38(BLOG_REPO_ROOT, "assist.yml");
14563
14707
  }
14564
14708
  function skip(date) {
14565
14709
  if (!/^\d{4}-\d{2}-\d{2}$/.test(date)) {
14566
- console.log(chalk133.red("Invalid date format. Use YYYY-MM-DD"));
14710
+ console.log(chalk134.red("Invalid date format. Use YYYY-MM-DD"));
14567
14711
  process.exit(1);
14568
14712
  }
14569
14713
  const repoName = getRepoName();
@@ -14574,7 +14718,7 @@ function skip(date) {
14574
14718
  const skipDays = skip2[repoName] ?? [];
14575
14719
  if (skipDays.includes(date)) {
14576
14720
  console.log(
14577
- chalk133.yellow(`${date} is already in skip list for ${repoName}`)
14721
+ chalk134.yellow(`${date} is already in skip list for ${repoName}`)
14578
14722
  );
14579
14723
  return;
14580
14724
  }
@@ -14584,20 +14728,20 @@ function skip(date) {
14584
14728
  devlog.skip = skip2;
14585
14729
  config.devlog = devlog;
14586
14730
  writeFileSync29(configPath, stringifyYaml3(config, { lineWidth: 0 }));
14587
- console.log(chalk133.green(`Added ${date} to skip list for ${repoName}`));
14731
+ console.log(chalk134.green(`Added ${date} to skip list for ${repoName}`));
14588
14732
  }
14589
14733
 
14590
14734
  // src/commands/devlog/version.ts
14591
- import chalk134 from "chalk";
14735
+ import chalk135 from "chalk";
14592
14736
  function version() {
14593
14737
  const config = loadConfig();
14594
14738
  const name = getRepoName();
14595
14739
  const lastInfo = getLastVersionInfo(name, config);
14596
14740
  const lastVersion = lastInfo?.version ?? null;
14597
14741
  const nextVersion = lastVersion ? bumpVersion(lastVersion, "patch") : null;
14598
- console.log(`${chalk134.bold("name:")} ${name}`);
14599
- console.log(`${chalk134.bold("last:")} ${lastVersion ?? chalk134.dim("none")}`);
14600
- console.log(`${chalk134.bold("next:")} ${nextVersion ?? chalk134.dim("none")}`);
14742
+ console.log(`${chalk135.bold("name:")} ${name}`);
14743
+ console.log(`${chalk135.bold("last:")} ${lastVersion ?? chalk135.dim("none")}`);
14744
+ console.log(`${chalk135.bold("next:")} ${nextVersion ?? chalk135.dim("none")}`);
14601
14745
  }
14602
14746
 
14603
14747
  // src/commands/devlog/devlogConfigHelp.ts
@@ -14641,7 +14785,7 @@ function registerDevlog(program2) {
14641
14785
  // src/commands/dotnet/checkBuildLocks.ts
14642
14786
  import { closeSync as closeSync3, openSync as openSync3, readdirSync as readdirSync5 } from "fs";
14643
14787
  import { join as join39 } from "path";
14644
- import chalk135 from "chalk";
14788
+ import chalk136 from "chalk";
14645
14789
 
14646
14790
  // src/shared/findRepoRoot.ts
14647
14791
  import { existsSync as existsSync37 } from "fs";
@@ -14704,14 +14848,14 @@ function checkBuildLocks(startDir) {
14704
14848
  const locked = findFirstLockedDll(startDir ?? getSearchRoot());
14705
14849
  if (locked) {
14706
14850
  console.error(
14707
- chalk135.red("Build output locked (is VS debugging?): ") + locked
14851
+ chalk136.red("Build output locked (is VS debugging?): ") + locked
14708
14852
  );
14709
14853
  process.exit(1);
14710
14854
  }
14711
14855
  }
14712
14856
  async function checkBuildLocksCommand() {
14713
14857
  checkBuildLocks();
14714
- console.log(chalk135.green("No build locks detected"));
14858
+ console.log(chalk136.green("No build locks detected"));
14715
14859
  }
14716
14860
 
14717
14861
  // src/commands/dotnet/buildTree.ts
@@ -14810,30 +14954,30 @@ function escapeRegex(s) {
14810
14954
  }
14811
14955
 
14812
14956
  // src/commands/dotnet/printTree.ts
14813
- import chalk136 from "chalk";
14957
+ import chalk137 from "chalk";
14814
14958
  function printNodes(nodes, prefix2) {
14815
14959
  for (let i = 0; i < nodes.length; i++) {
14816
14960
  const isLast = i === nodes.length - 1;
14817
14961
  const connector = isLast ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
14818
14962
  const childPrefix = isLast ? " " : "\u2502 ";
14819
14963
  const isMissing = nodes[i].relativePath.startsWith("[MISSING]");
14820
- const label2 = isMissing ? chalk136.red(nodes[i].relativePath) : nodes[i].relativePath;
14964
+ const label2 = isMissing ? chalk137.red(nodes[i].relativePath) : nodes[i].relativePath;
14821
14965
  console.log(`${prefix2}${connector}${label2}`);
14822
14966
  printNodes(nodes[i].children, prefix2 + childPrefix);
14823
14967
  }
14824
14968
  }
14825
14969
  function printTree(tree, totalCount, solutions) {
14826
- console.log(chalk136.bold("\nProject Dependency Tree"));
14827
- console.log(chalk136.cyan(tree.relativePath));
14970
+ console.log(chalk137.bold("\nProject Dependency Tree"));
14971
+ console.log(chalk137.cyan(tree.relativePath));
14828
14972
  printNodes(tree.children, "");
14829
- console.log(chalk136.dim(`
14973
+ console.log(chalk137.dim(`
14830
14974
  ${totalCount} projects total (including root)`));
14831
- console.log(chalk136.bold("\nSolution Membership"));
14975
+ console.log(chalk137.bold("\nSolution Membership"));
14832
14976
  if (solutions.length === 0) {
14833
- console.log(chalk136.yellow(" Not found in any .sln"));
14977
+ console.log(chalk137.yellow(" Not found in any .sln"));
14834
14978
  } else {
14835
14979
  for (const sln of solutions) {
14836
- console.log(` ${chalk136.green(sln)}`);
14980
+ console.log(` ${chalk137.green(sln)}`);
14837
14981
  }
14838
14982
  }
14839
14983
  console.log();
@@ -14862,16 +15006,16 @@ function printJson(tree, totalCount, solutions) {
14862
15006
  // src/commands/dotnet/resolveCsproj.ts
14863
15007
  import { existsSync as existsSync38 } from "fs";
14864
15008
  import path33 from "path";
14865
- import chalk137 from "chalk";
15009
+ import chalk138 from "chalk";
14866
15010
  function resolveCsproj(csprojPath) {
14867
15011
  const resolved = path33.resolve(csprojPath);
14868
15012
  if (!existsSync38(resolved)) {
14869
- console.error(chalk137.red(`File not found: ${resolved}`));
15013
+ console.error(chalk138.red(`File not found: ${resolved}`));
14870
15014
  process.exit(1);
14871
15015
  }
14872
15016
  const repoRoot = findRepoRoot(path33.dirname(resolved));
14873
15017
  if (!repoRoot) {
14874
- console.error(chalk137.red("Could not find git repository root"));
15018
+ console.error(chalk138.red("Could not find git repository root"));
14875
15019
  process.exit(1);
14876
15020
  }
14877
15021
  return { resolved, repoRoot };
@@ -14921,12 +15065,12 @@ function getChangedCsFiles(scope) {
14921
15065
  }
14922
15066
 
14923
15067
  // src/commands/dotnet/inSln.ts
14924
- import chalk138 from "chalk";
15068
+ import chalk139 from "chalk";
14925
15069
  async function inSln(csprojPath) {
14926
15070
  const { resolved, repoRoot } = resolveCsproj(csprojPath);
14927
15071
  const solutions = findContainingSolutions(resolved, repoRoot);
14928
15072
  if (solutions.length === 0) {
14929
- console.log(chalk138.yellow("Not found in any .sln file"));
15073
+ console.log(chalk139.yellow("Not found in any .sln file"));
14930
15074
  process.exit(1);
14931
15075
  }
14932
15076
  for (const sln of solutions) {
@@ -14935,7 +15079,7 @@ async function inSln(csprojPath) {
14935
15079
  }
14936
15080
 
14937
15081
  // src/commands/dotnet/inspect.ts
14938
- import chalk144 from "chalk";
15082
+ import chalk145 from "chalk";
14939
15083
 
14940
15084
  // src/shared/formatElapsed.ts
14941
15085
  function formatElapsed(ms) {
@@ -14947,12 +15091,12 @@ function formatElapsed(ms) {
14947
15091
  }
14948
15092
 
14949
15093
  // src/commands/dotnet/displayIssues.ts
14950
- import chalk139 from "chalk";
15094
+ import chalk140 from "chalk";
14951
15095
  var SEVERITY_COLOR = {
14952
- ERROR: chalk139.red,
14953
- WARNING: chalk139.yellow,
14954
- SUGGESTION: chalk139.cyan,
14955
- HINT: chalk139.dim
15096
+ ERROR: chalk140.red,
15097
+ WARNING: chalk140.yellow,
15098
+ SUGGESTION: chalk140.cyan,
15099
+ HINT: chalk140.dim
14956
15100
  };
14957
15101
  function groupByFile(issues) {
14958
15102
  const byFile = /* @__PURE__ */ new Map();
@@ -14968,15 +15112,15 @@ function groupByFile(issues) {
14968
15112
  }
14969
15113
  function displayIssues(issues) {
14970
15114
  for (const [file, fileIssues] of groupByFile(issues)) {
14971
- console.log(chalk139.bold(file));
15115
+ console.log(chalk140.bold(file));
14972
15116
  for (const issue of fileIssues.sort((a, b) => a.line - b.line)) {
14973
- const color = SEVERITY_COLOR[issue.severity] ?? chalk139.white;
15117
+ const color = SEVERITY_COLOR[issue.severity] ?? chalk140.white;
14974
15118
  console.log(
14975
- ` ${chalk139.dim(`${issue.line}:`)} ${color(issue.severity)} [${issue.typeId}] ${issue.message}`
15119
+ ` ${chalk140.dim(`${issue.line}:`)} ${color(issue.severity)} [${issue.typeId}] ${issue.message}`
14976
15120
  );
14977
15121
  }
14978
15122
  }
14979
- console.log(chalk139.dim(`
15123
+ console.log(chalk140.dim(`
14980
15124
  ${issues.length} issue(s) found`));
14981
15125
  }
14982
15126
 
@@ -15035,12 +15179,12 @@ function filterIssues(issues, all, cliOnly, cliSuppress) {
15035
15179
  // src/commands/dotnet/resolveSolution.ts
15036
15180
  import { existsSync as existsSync39 } from "fs";
15037
15181
  import path34 from "path";
15038
- import chalk141 from "chalk";
15182
+ import chalk142 from "chalk";
15039
15183
 
15040
15184
  // src/commands/dotnet/findSolution.ts
15041
15185
  import { readdirSync as readdirSync7 } from "fs";
15042
15186
  import { dirname as dirname22, join as join40 } from "path";
15043
- import chalk140 from "chalk";
15187
+ import chalk141 from "chalk";
15044
15188
  function findSlnInDir(dir) {
15045
15189
  try {
15046
15190
  return readdirSync7(dir).filter((f) => f.endsWith(".sln")).map((f) => join40(dir, f));
@@ -15056,17 +15200,17 @@ function findSolution() {
15056
15200
  const slnFiles = findSlnInDir(current);
15057
15201
  if (slnFiles.length === 1) return slnFiles[0];
15058
15202
  if (slnFiles.length > 1) {
15059
- console.error(chalk140.red(`Multiple .sln files found in ${current}:`));
15203
+ console.error(chalk141.red(`Multiple .sln files found in ${current}:`));
15060
15204
  for (const f of slnFiles) console.error(` ${f}`);
15061
15205
  console.error(
15062
- chalk140.yellow("Specify which one: assist dotnet inspect <sln>")
15206
+ chalk141.yellow("Specify which one: assist dotnet inspect <sln>")
15063
15207
  );
15064
15208
  process.exit(1);
15065
15209
  }
15066
15210
  if (current === ceiling) break;
15067
15211
  current = dirname22(current);
15068
15212
  }
15069
- console.error(chalk140.red("No .sln file found between cwd and repo root"));
15213
+ console.error(chalk141.red("No .sln file found between cwd and repo root"));
15070
15214
  process.exit(1);
15071
15215
  }
15072
15216
 
@@ -15075,7 +15219,7 @@ function resolveSolution(sln) {
15075
15219
  if (sln) {
15076
15220
  const resolved = path34.resolve(sln);
15077
15221
  if (!existsSync39(resolved)) {
15078
- console.error(chalk141.red(`Solution file not found: ${resolved}`));
15222
+ console.error(chalk142.red(`Solution file not found: ${resolved}`));
15079
15223
  process.exit(1);
15080
15224
  }
15081
15225
  return resolved;
@@ -15117,14 +15261,14 @@ import { execSync as execSync37 } from "child_process";
15117
15261
  import { existsSync as existsSync40, readFileSync as readFileSync34, unlinkSync as unlinkSync10 } from "fs";
15118
15262
  import { tmpdir as tmpdir3 } from "os";
15119
15263
  import path35 from "path";
15120
- import chalk142 from "chalk";
15264
+ import chalk143 from "chalk";
15121
15265
  function assertJbInstalled() {
15122
15266
  try {
15123
15267
  execSync37("jb inspectcode --version", { stdio: "pipe" });
15124
15268
  } catch {
15125
- console.error(chalk142.red("jb is not installed. Install with:"));
15269
+ console.error(chalk143.red("jb is not installed. Install with:"));
15126
15270
  console.error(
15127
- chalk142.yellow(" dotnet tool install -g JetBrains.ReSharper.GlobalTools")
15271
+ chalk143.yellow(" dotnet tool install -g JetBrains.ReSharper.GlobalTools")
15128
15272
  );
15129
15273
  process.exit(1);
15130
15274
  }
@@ -15142,11 +15286,11 @@ function runInspectCode(slnPath, include, swea) {
15142
15286
  if (error && typeof error === "object" && "stderr" in error) {
15143
15287
  process.stderr.write(error.stderr);
15144
15288
  }
15145
- console.error(chalk142.red("jb inspectcode failed"));
15289
+ console.error(chalk143.red("jb inspectcode failed"));
15146
15290
  process.exit(1);
15147
15291
  }
15148
15292
  if (!existsSync40(reportPath)) {
15149
- console.error(chalk142.red("Report file not generated"));
15293
+ console.error(chalk143.red("Report file not generated"));
15150
15294
  process.exit(1);
15151
15295
  }
15152
15296
  const xml = readFileSync34(reportPath, "utf8");
@@ -15156,7 +15300,7 @@ function runInspectCode(slnPath, include, swea) {
15156
15300
 
15157
15301
  // src/commands/dotnet/runRoslynInspect.ts
15158
15302
  import { execSync as execSync38 } from "child_process";
15159
- import chalk143 from "chalk";
15303
+ import chalk144 from "chalk";
15160
15304
  function resolveMsbuildPath() {
15161
15305
  const { run: run4 } = loadConfig();
15162
15306
  const configs = resolveRunConfigs(run4, getConfigDir());
@@ -15168,9 +15312,9 @@ function assertMsbuildInstalled() {
15168
15312
  try {
15169
15313
  execSync38(`"${msbuild}" -version`, { stdio: "pipe" });
15170
15314
  } catch {
15171
- console.error(chalk143.red(`msbuild not found at: ${msbuild}`));
15315
+ console.error(chalk144.red(`msbuild not found at: ${msbuild}`));
15172
15316
  console.error(
15173
- chalk143.yellow(
15317
+ chalk144.yellow(
15174
15318
  "Configure it via a 'build' run entry in .claude/assist.yml or add msbuild to PATH."
15175
15319
  )
15176
15320
  );
@@ -15217,17 +15361,17 @@ function runEngine(resolved, changedFiles, options2) {
15217
15361
  // src/commands/dotnet/inspect.ts
15218
15362
  function logScope(changedFiles) {
15219
15363
  if (changedFiles === null) {
15220
- console.log(chalk144.dim("Inspecting full solution..."));
15364
+ console.log(chalk145.dim("Inspecting full solution..."));
15221
15365
  } else {
15222
15366
  console.log(
15223
- chalk144.dim(`Inspecting ${changedFiles.length} changed file(s)...`)
15367
+ chalk145.dim(`Inspecting ${changedFiles.length} changed file(s)...`)
15224
15368
  );
15225
15369
  }
15226
15370
  }
15227
15371
  function reportResults(issues, elapsed) {
15228
15372
  if (issues.length > 0) displayIssues(issues);
15229
- else console.log(chalk144.green("No issues found"));
15230
- console.log(chalk144.dim(`Completed in ${formatElapsed(elapsed)}`));
15373
+ else console.log(chalk145.green("No issues found"));
15374
+ console.log(chalk145.dim(`Completed in ${formatElapsed(elapsed)}`));
15231
15375
  if (issues.length > 0) process.exit(1);
15232
15376
  }
15233
15377
  async function inspect(sln, options2) {
@@ -15238,7 +15382,7 @@ async function inspect(sln, options2) {
15238
15382
  const scope = parseScope(options2.scope);
15239
15383
  const changedFiles = getChangedCsFiles(scope);
15240
15384
  if (changedFiles !== null && changedFiles.length === 0) {
15241
- console.log(chalk144.green("No changed .cs files found"));
15385
+ console.log(chalk145.green("No changed .cs files found"));
15242
15386
  return;
15243
15387
  }
15244
15388
  logScope(changedFiles);
@@ -15411,10 +15555,10 @@ function decideCommentGuard(input, existingContent) {
15411
15555
  import { existsSync as existsSync41, unlinkSync as unlinkSync11 } from "fs";
15412
15556
  function consumeMigrationApproval(migrationId) {
15413
15557
  sweepRestrictedDir();
15414
- const path70 = getMigrationApprovalPath(migrationId);
15415
- if (!existsSync41(path70)) return false;
15558
+ const path71 = getMigrationApprovalPath(migrationId);
15559
+ if (!existsSync41(path71)) return false;
15416
15560
  try {
15417
- unlinkSync11(path70);
15561
+ unlinkSync11(path71);
15418
15562
  return true;
15419
15563
  } catch {
15420
15564
  return false;
@@ -15621,25 +15765,25 @@ function fetchRepoCommitAuthors(org, repo, since) {
15621
15765
  }
15622
15766
 
15623
15767
  // src/commands/github/printCountTable.ts
15624
- import chalk145 from "chalk";
15768
+ import chalk146 from "chalk";
15625
15769
  function printCountTable(labelHeader, rows) {
15626
15770
  const labelWidth = Math.max(
15627
15771
  labelHeader.length,
15628
15772
  ...rows.map((row) => row.label.length)
15629
15773
  );
15630
15774
  const header = `${labelHeader.padEnd(labelWidth)} Commits`;
15631
- console.log(chalk145.dim(header));
15632
- console.log(chalk145.dim("-".repeat(header.length)));
15775
+ console.log(chalk146.dim(header));
15776
+ console.log(chalk146.dim("-".repeat(header.length)));
15633
15777
  for (const row of rows) {
15634
15778
  console.log(`${row.label.padEnd(labelWidth)} ${row.count}`);
15635
15779
  }
15636
15780
  }
15637
15781
 
15638
15782
  // src/commands/github/printRepoAuthorBreakdown.ts
15639
- import chalk146 from "chalk";
15783
+ import chalk147 from "chalk";
15640
15784
  function printRepoAuthorBreakdown(repos2) {
15641
15785
  for (const repo of repos2) {
15642
- console.log(chalk146.bold(repo.name));
15786
+ console.log(chalk147.bold(repo.name));
15643
15787
  const authorWidth = Math.max(
15644
15788
  0,
15645
15789
  ...repo.authors.map((a) => a.author.length)
@@ -15957,7 +16101,7 @@ function registerHandover(program2) {
15957
16101
  }
15958
16102
 
15959
16103
  // src/commands/jira/acceptanceCriteria.ts
15960
- import chalk147 from "chalk";
16104
+ import chalk148 from "chalk";
15961
16105
 
15962
16106
  // src/commands/jira/adfToText.ts
15963
16107
  function renderInline(node) {
@@ -16024,7 +16168,7 @@ function acceptanceCriteria(issueKey) {
16024
16168
  const parsed = fetchIssue(issueKey, field);
16025
16169
  const acValue = parsed?.fields?.[field];
16026
16170
  if (!acValue) {
16027
- console.log(chalk147.yellow(`No acceptance criteria found on ${issueKey}.`));
16171
+ console.log(chalk148.yellow(`No acceptance criteria found on ${issueKey}.`));
16028
16172
  return;
16029
16173
  }
16030
16174
  if (typeof acValue === "string") {
@@ -16090,14 +16234,14 @@ async function jiraAuth() {
16090
16234
  }
16091
16235
 
16092
16236
  // src/commands/jira/viewIssue.ts
16093
- import chalk148 from "chalk";
16237
+ import chalk149 from "chalk";
16094
16238
  function viewIssue(issueKey) {
16095
16239
  const parsed = fetchIssue(issueKey, "summary,description");
16096
16240
  const fields = parsed?.fields;
16097
16241
  const summary = fields?.summary;
16098
16242
  const description = fields?.description;
16099
16243
  if (summary) {
16100
- console.log(chalk148.bold(summary));
16244
+ console.log(chalk149.bold(summary));
16101
16245
  }
16102
16246
  if (description) {
16103
16247
  if (summary) console.log();
@@ -16111,7 +16255,7 @@ function viewIssue(issueKey) {
16111
16255
  }
16112
16256
  if (!summary && !description) {
16113
16257
  console.log(
16114
- chalk148.yellow(`No summary or description found on ${issueKey}.`)
16258
+ chalk149.yellow(`No summary or description found on ${issueKey}.`)
16115
16259
  );
16116
16260
  }
16117
16261
  }
@@ -16167,13 +16311,13 @@ function registerRefineLaunch(program2, resumeFlag) {
16167
16311
  // src/commands/reviewPrComments.ts
16168
16312
  import { execFileSync as execFileSync5 } from "child_process";
16169
16313
  import { randomUUID as randomUUID3 } from "crypto";
16170
- import chalk149 from "chalk";
16314
+ import chalk150 from "chalk";
16171
16315
  async function reviewPrComments(number) {
16172
16316
  if (number) {
16173
16317
  try {
16174
16318
  execFileSync5("gh", ["pr", "checkout", number], { stdio: "inherit" });
16175
16319
  } catch {
16176
- console.error(chalk149.red(`gh pr checkout ${number} failed; aborting.`));
16320
+ console.error(chalk150.red(`gh pr checkout ${number} failed; aborting.`));
16177
16321
  process.exit(1);
16178
16322
  }
16179
16323
  }
@@ -16246,15 +16390,15 @@ function registerList(program2) {
16246
16390
  // src/commands/mermaid/index.ts
16247
16391
  import { mkdirSync as mkdirSync16, readdirSync as readdirSync9 } from "fs";
16248
16392
  import { resolve as resolve12 } from "path";
16249
- import chalk152 from "chalk";
16393
+ import chalk153 from "chalk";
16250
16394
 
16251
16395
  // src/commands/mermaid/exportFile.ts
16252
16396
  import { readFileSync as readFileSync36, writeFileSync as writeFileSync31 } from "fs";
16253
16397
  import { basename as basename11, extname, resolve as resolve11 } from "path";
16254
- import chalk151 from "chalk";
16398
+ import chalk152 from "chalk";
16255
16399
 
16256
16400
  // src/commands/mermaid/renderBlock.ts
16257
- import chalk150 from "chalk";
16401
+ import chalk151 from "chalk";
16258
16402
  async function renderBlock(krokiUrl, source) {
16259
16403
  const response = await fetch(`${krokiUrl}/mermaid/svg`, {
16260
16404
  method: "POST",
@@ -16263,7 +16407,7 @@ async function renderBlock(krokiUrl, source) {
16263
16407
  });
16264
16408
  if (!response.ok) {
16265
16409
  console.error(
16266
- chalk150.red(
16410
+ chalk151.red(
16267
16411
  `Kroki request failed: ${response.status} ${response.statusText}`
16268
16412
  )
16269
16413
  );
@@ -16281,19 +16425,19 @@ async function exportFile(file, outDir, krokiUrl, onlyIndex) {
16281
16425
  if (onlyIndex !== void 0) {
16282
16426
  if (onlyIndex < 1 || onlyIndex > blocks.length) {
16283
16427
  console.error(
16284
- chalk151.red(
16428
+ chalk152.red(
16285
16429
  `${file}: --index ${onlyIndex} out of range (file has ${blocks.length} diagram(s))`
16286
16430
  )
16287
16431
  );
16288
16432
  process.exit(1);
16289
16433
  }
16290
16434
  console.log(
16291
- chalk151.gray(
16435
+ chalk152.gray(
16292
16436
  `${file} \u2014 rendering diagram ${onlyIndex} of ${blocks.length}`
16293
16437
  )
16294
16438
  );
16295
16439
  } else {
16296
- console.log(chalk151.gray(`${file} \u2014 ${blocks.length} diagram(s)`));
16440
+ console.log(chalk152.gray(`${file} \u2014 ${blocks.length} diagram(s)`));
16297
16441
  }
16298
16442
  for (const [i, source] of blocks.entries()) {
16299
16443
  const idx = i + 1;
@@ -16301,7 +16445,7 @@ async function exportFile(file, outDir, krokiUrl, onlyIndex) {
16301
16445
  const outPath = resolve11(outDir, `${stem}-${idx}.svg`);
16302
16446
  const svg = await renderBlock(krokiUrl, source);
16303
16447
  writeFileSync31(outPath, svg, "utf8");
16304
- console.log(chalk151.green(` \u2192 ${outPath}`));
16448
+ console.log(chalk152.green(` \u2192 ${outPath}`));
16305
16449
  }
16306
16450
  }
16307
16451
  function extractMermaidBlocks(markdown) {
@@ -16317,18 +16461,18 @@ async function mermaidExport(file, options2 = {}) {
16317
16461
  if (options2.index !== void 0) {
16318
16462
  if (!Number.isInteger(options2.index) || options2.index < 1) {
16319
16463
  console.error(
16320
- chalk152.red(`--index must be a positive integer (got ${options2.index})`)
16464
+ chalk153.red(`--index must be a positive integer (got ${options2.index})`)
16321
16465
  );
16322
16466
  process.exit(1);
16323
16467
  }
16324
16468
  if (!file) {
16325
- console.error(chalk152.red("--index requires a file argument"));
16469
+ console.error(chalk153.red("--index requires a file argument"));
16326
16470
  process.exit(1);
16327
16471
  }
16328
16472
  }
16329
16473
  const files = file ? [file] : readdirSync9(process.cwd()).filter((name) => name.toLowerCase().endsWith(".md")).sort();
16330
16474
  if (files.length === 0) {
16331
- console.log(chalk152.gray("No markdown files found in current directory."));
16475
+ console.log(chalk153.gray("No markdown files found in current directory."));
16332
16476
  return;
16333
16477
  }
16334
16478
  for (const f of files) {
@@ -16361,7 +16505,7 @@ function registerMermaid(program2) {
16361
16505
  import { mkdir as mkdir4 } from "fs/promises";
16362
16506
  import { createServer as createServer2 } from "http";
16363
16507
  import { dirname as dirname24 } from "path";
16364
- import chalk154 from "chalk";
16508
+ import chalk155 from "chalk";
16365
16509
 
16366
16510
  // src/commands/netcap/corsHeaders.ts
16367
16511
  var corsHeaders = {
@@ -16440,7 +16584,7 @@ function createNetcapHandler(options2) {
16440
16584
  import { cp, readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
16441
16585
  import { networkInterfaces } from "os";
16442
16586
  import { join as join46 } from "path";
16443
- import chalk153 from "chalk";
16587
+ import chalk154 from "chalk";
16444
16588
 
16445
16589
  // src/commands/netcap/netcapExtensionDir.ts
16446
16590
  import { dirname as dirname23, join as join45 } from "path";
@@ -16484,7 +16628,7 @@ async function prepareExtensionForLoad(port, filter = "") {
16484
16628
  const host = lanIPv4();
16485
16629
  if (!host) {
16486
16630
  console.log(
16487
- chalk153.yellow("could not determine the WSL IP for the extension")
16631
+ chalk154.yellow("could not determine the WSL IP for the extension")
16488
16632
  );
16489
16633
  await configureBackground(source, "127.0.0.1", port, filter);
16490
16634
  return source;
@@ -16495,7 +16639,7 @@ async function prepareExtensionForLoad(port, filter = "") {
16495
16639
  return WSL_WINDOWS_PATH;
16496
16640
  } catch {
16497
16641
  console.log(
16498
- chalk153.yellow(`could not copy extension to ${WSL_WINDOWS_PATH}`)
16642
+ chalk154.yellow(`could not copy extension to ${WSL_WINDOWS_PATH}`)
16499
16643
  );
16500
16644
  return source;
16501
16645
  }
@@ -16528,30 +16672,30 @@ async function netcap(options2) {
16528
16672
  let count7 = 0;
16529
16673
  const handler = createNetcapHandler({
16530
16674
  outPath,
16531
- onPing: () => console.log(chalk154.dim("ping from extension")),
16675
+ onPing: () => console.log(chalk155.dim("ping from extension")),
16532
16676
  onCapture: (entry) => {
16533
16677
  count7 += 1;
16534
16678
  console.log(
16535
- chalk154.green(`captured #${count7}`),
16536
- chalk154.dim(`${entry.method ?? "?"} ${entry.url ?? "?"}`)
16679
+ chalk155.green(`captured #${count7}`),
16680
+ chalk155.dim(`${entry.method ?? "?"} ${entry.url ?? "?"}`)
16537
16681
  );
16538
16682
  }
16539
16683
  });
16540
16684
  const server = createServer2(handler);
16541
16685
  server.listen(port, () => {
16542
16686
  console.log(
16543
- chalk154.bold(`netcap receiver listening on http://127.0.0.1:${port}`)
16687
+ chalk155.bold(`netcap receiver listening on http://127.0.0.1:${port}`)
16544
16688
  );
16545
- console.log(chalk154.dim(`appending captures to ${outPath}`));
16689
+ console.log(chalk155.dim(`appending captures to ${outPath}`));
16546
16690
  if (filter)
16547
- console.log(chalk154.dim(`forwarding only URLs matching "${filter}"`));
16548
- console.log(chalk154.dim(`load the unpacked extension from ${extensionPath}`));
16549
- console.log(chalk154.dim("press Ctrl-C to stop"));
16691
+ console.log(chalk155.dim(`forwarding only URLs matching "${filter}"`));
16692
+ console.log(chalk155.dim(`load the unpacked extension from ${extensionPath}`));
16693
+ console.log(chalk155.dim("press Ctrl-C to stop"));
16550
16694
  });
16551
16695
  process.on("SIGINT", () => {
16552
16696
  server.close();
16553
16697
  console.log(
16554
- chalk154.bold(
16698
+ chalk155.bold(
16555
16699
  `
16556
16700
  netcap stopped \u2014 captured ${count7} ${count7 === 1 ? "entry" : "entries"} to ${outPath}`
16557
16701
  )
@@ -16563,7 +16707,7 @@ netcap stopped \u2014 captured ${count7} ${count7 === 1 ? "entry" : "entries"} t
16563
16707
  // src/commands/netcap/netcapExtract.ts
16564
16708
  import { writeFileSync as writeFileSync32 } from "fs";
16565
16709
  import { join as join49 } from "path";
16566
- import chalk155 from "chalk";
16710
+ import chalk156 from "chalk";
16567
16711
 
16568
16712
  // src/commands/netcap/extractPostsFromCapture.ts
16569
16713
  import { readFileSync as readFileSync37 } from "fs";
@@ -16588,9 +16732,9 @@ function parseRscRows(flight) {
16588
16732
  }
16589
16733
  function makeRscResolver(rows) {
16590
16734
  return (ref) => {
16591
- const [id, ...path70] = ref.slice(1).replace(/^[L@]/, "").split(":");
16735
+ const [id, ...path71] = ref.slice(1).replace(/^[L@]/, "").split(":");
16592
16736
  let v = rows[id];
16593
- for (const key of path70) {
16737
+ for (const key of path71) {
16594
16738
  if (v == null || typeof v !== "object") return void 0;
16595
16739
  v = v[key];
16596
16740
  }
@@ -17011,8 +17155,8 @@ function netcapExtract(file) {
17011
17155
  writeFileSync32(outFile, `${JSON.stringify(posts, null, 2)}
17012
17156
  `);
17013
17157
  console.log(
17014
- chalk155.green(`extracted ${posts.length} posts`),
17015
- chalk155.dim(`-> ${outFile}`)
17158
+ chalk156.green(`extracted ${posts.length} posts`),
17159
+ chalk156.dim(`-> ${outFile}`)
17016
17160
  );
17017
17161
  }
17018
17162
 
@@ -17033,7 +17177,7 @@ function registerNetcap(program2) {
17033
17177
  }
17034
17178
 
17035
17179
  // src/commands/news/add/index.ts
17036
- import chalk156 from "chalk";
17180
+ import chalk157 from "chalk";
17037
17181
  import enquirer8 from "enquirer";
17038
17182
  async function add2(url) {
17039
17183
  if (!url) {
@@ -17055,10 +17199,10 @@ async function add2(url) {
17055
17199
  const { orm } = await getReady();
17056
17200
  const added = await addFeed(orm, url);
17057
17201
  if (!added) {
17058
- console.log(chalk156.yellow("Feed already exists"));
17202
+ console.log(chalk157.yellow("Feed already exists"));
17059
17203
  return;
17060
17204
  }
17061
- console.log(chalk156.green(`Added feed: ${url}`));
17205
+ console.log(chalk157.green(`Added feed: ${url}`));
17062
17206
  }
17063
17207
 
17064
17208
  // src/commands/registerNews.ts
@@ -17105,7 +17249,7 @@ function registerPiHook(program2) {
17105
17249
  }
17106
17250
 
17107
17251
  // src/commands/prompts/printPromptsTable.ts
17108
- import chalk157 from "chalk";
17252
+ import chalk158 from "chalk";
17109
17253
  function truncate(str, max) {
17110
17254
  if (str.length <= max) return str;
17111
17255
  return `${str.slice(0, max - 1)}\u2026`;
@@ -17123,14 +17267,14 @@ function printPromptsTable(rows) {
17123
17267
  "Command".padEnd(commandWidth),
17124
17268
  "Repos"
17125
17269
  ].join(" ");
17126
- console.log(chalk157.dim(header));
17127
- console.log(chalk157.dim("-".repeat(header.length)));
17270
+ console.log(chalk158.dim(header));
17271
+ console.log(chalk158.dim("-".repeat(header.length)));
17128
17272
  for (const row of rows) {
17129
17273
  const count7 = String(row.count).padStart(countWidth);
17130
17274
  const tool = row.tool.padEnd(toolWidth);
17131
17275
  const command = truncate(row.command, 60).padEnd(commandWidth);
17132
17276
  console.log(
17133
- `${chalk157.yellow(count7)} ${tool} ${command} ${chalk157.dim(row.repos)}`
17277
+ `${chalk158.yellow(count7)} ${tool} ${command} ${chalk158.dim(row.repos)}`
17134
17278
  );
17135
17279
  }
17136
17280
  }
@@ -17274,15 +17418,15 @@ function postComment(vars) {
17274
17418
  const stdout = startLine === void 0 ? runGhGraphql(MUTATION_SINGLE, base) : runGhGraphql(MUTATION_MULTI, { ...base, startLine });
17275
17419
  assertThreadCreated(stdout);
17276
17420
  }
17277
- function comment2(path70, line, body, startLine) {
17421
+ function comment2(path71, line, body, startLine) {
17278
17422
  validateBody(body);
17279
17423
  validateLine(line);
17280
17424
  if (startLine !== void 0) validateLine(startLine);
17281
17425
  try {
17282
17426
  const prId = getCurrentPrNodeId();
17283
- postComment({ prId, body, path: path70, line, startLine });
17427
+ postComment({ prId, body, path: path71, line, startLine });
17284
17428
  const range = startLine !== void 0 ? `${startLine}-${line}` : `${line}`;
17285
- console.log(`Added review comment on ${path70}:${range}`);
17429
+ console.log(`Added review comment on ${path71}:${range}`);
17286
17430
  } catch (error) {
17287
17431
  if (isGhNotInstalled(error)) {
17288
17432
  console.error("Error: GitHub CLI (gh) is not installed.");
@@ -17697,20 +17841,20 @@ function fetchLineComments(org, repo, prNumber, threadInfo) {
17697
17841
  }
17698
17842
 
17699
17843
  // src/commands/prs/listComments/printComments.ts
17700
- import chalk158 from "chalk";
17844
+ import chalk159 from "chalk";
17701
17845
  function formatForHuman(comment3) {
17702
17846
  if (comment3.type === "review") {
17703
- const stateColor = comment3.state === "APPROVED" ? chalk158.green : comment3.state === "CHANGES_REQUESTED" ? chalk158.red : chalk158.yellow;
17847
+ const stateColor = comment3.state === "APPROVED" ? chalk159.green : comment3.state === "CHANGES_REQUESTED" ? chalk159.red : chalk159.yellow;
17704
17848
  return [
17705
- `${chalk158.cyan("Review")} by ${chalk158.bold(comment3.user)} ${stateColor(`[${comment3.state}]`)}`,
17849
+ `${chalk159.cyan("Review")} by ${chalk159.bold(comment3.user)} ${stateColor(`[${comment3.state}]`)}`,
17706
17850
  comment3.body,
17707
17851
  ""
17708
17852
  ].join("\n");
17709
17853
  }
17710
17854
  const location = comment3.line ? `:${comment3.line}` : "";
17711
17855
  return [
17712
- `${chalk158.cyan("Line comment")} by ${chalk158.bold(comment3.user)} on ${chalk158.dim(`${comment3.path}${location}`)}`,
17713
- chalk158.dim(comment3.diff_hunk.split("\n").slice(-3).join("\n")),
17856
+ `${chalk159.cyan("Line comment")} by ${chalk159.bold(comment3.user)} on ${chalk159.dim(`${comment3.path}${location}`)}`,
17857
+ chalk159.dim(comment3.diff_hunk.split("\n").slice(-3).join("\n")),
17714
17858
  comment3.body,
17715
17859
  ""
17716
17860
  ].join("\n");
@@ -17800,13 +17944,13 @@ import { execSync as execSync46 } from "child_process";
17800
17944
  import enquirer9 from "enquirer";
17801
17945
 
17802
17946
  // src/commands/prs/prs/displayPaginated/printPr.ts
17803
- import chalk159 from "chalk";
17947
+ import chalk160 from "chalk";
17804
17948
  var STATUS_MAP = {
17805
- MERGED: (pr) => pr.mergedAt ? { label: chalk159.magenta("merged"), date: pr.mergedAt } : null,
17806
- CLOSED: (pr) => pr.closedAt ? { label: chalk159.red("closed"), date: pr.closedAt } : null
17949
+ MERGED: (pr) => pr.mergedAt ? { label: chalk160.magenta("merged"), date: pr.mergedAt } : null,
17950
+ CLOSED: (pr) => pr.closedAt ? { label: chalk160.red("closed"), date: pr.closedAt } : null
17807
17951
  };
17808
17952
  function defaultStatus(pr) {
17809
- return { label: chalk159.green("opened"), date: pr.createdAt };
17953
+ return { label: chalk160.green("opened"), date: pr.createdAt };
17810
17954
  }
17811
17955
  function getStatus2(pr) {
17812
17956
  return STATUS_MAP[pr.state]?.(pr) ?? defaultStatus(pr);
@@ -17815,11 +17959,11 @@ function formatDate(dateStr) {
17815
17959
  return new Date(dateStr).toISOString().split("T")[0];
17816
17960
  }
17817
17961
  function formatPrHeader(pr, status3) {
17818
- return `${chalk159.cyan(`#${pr.number}`)} ${pr.title} ${chalk159.dim(`(${pr.author.login},`)} ${status3.label} ${chalk159.dim(`${formatDate(status3.date)})`)}`;
17962
+ return `${chalk160.cyan(`#${pr.number}`)} ${pr.title} ${chalk160.dim(`(${pr.author.login},`)} ${status3.label} ${chalk160.dim(`${formatDate(status3.date)})`)}`;
17819
17963
  }
17820
17964
  function logPrDetails(pr) {
17821
17965
  console.log(
17822
- chalk159.dim(` ${pr.changedFiles.toLocaleString()} files | ${pr.url}`)
17966
+ chalk160.dim(` ${pr.changedFiles.toLocaleString()} files | ${pr.url}`)
17823
17967
  );
17824
17968
  console.log();
17825
17969
  }
@@ -18161,17 +18305,17 @@ function registerPrs(program2) {
18161
18305
  prsCommand.command("reply <comment-id> <body>").description("Reply to a comment thread without resolving it").action((commentId, body) => {
18162
18306
  reply(Number.parseInt(commentId, 10), body);
18163
18307
  });
18164
- prsCommand.command("comment <path> <line> <body>").description("Add a line comment to the pending review").action((path70, line, body) => {
18165
- comment2(path70, Number.parseInt(line, 10), body);
18308
+ prsCommand.command("comment <path> <line> <body>").description("Add a line comment to the pending review").action((path71, line, body) => {
18309
+ comment2(path71, Number.parseInt(line, 10), body);
18166
18310
  });
18167
18311
  configHelp(prsCommand, prsConfigHelp);
18168
18312
  }
18169
18313
 
18170
18314
  // src/commands/ravendb/ravendbAuth.ts
18171
- import chalk165 from "chalk";
18315
+ import chalk166 from "chalk";
18172
18316
 
18173
18317
  // src/shared/createConnectionAuth.ts
18174
- import chalk160 from "chalk";
18318
+ import chalk161 from "chalk";
18175
18319
  function listConnections(connections, format) {
18176
18320
  if (connections.length === 0) {
18177
18321
  console.log("No connections configured.");
@@ -18184,7 +18328,7 @@ function listConnections(connections, format) {
18184
18328
  function removeConnection(connections, name, save) {
18185
18329
  const filtered = connections.filter((c) => c.name !== name);
18186
18330
  if (filtered.length === connections.length) {
18187
- console.error(chalk160.red(`Connection "${name}" not found.`));
18331
+ console.error(chalk161.red(`Connection "${name}" not found.`));
18188
18332
  process.exit(1);
18189
18333
  }
18190
18334
  save(filtered);
@@ -18230,15 +18374,15 @@ function saveConnections(connections) {
18230
18374
  }
18231
18375
 
18232
18376
  // src/commands/ravendb/promptConnection.ts
18233
- import chalk163 from "chalk";
18377
+ import chalk164 from "chalk";
18234
18378
 
18235
18379
  // src/commands/ravendb/selectOpSecret.ts
18236
- import chalk162 from "chalk";
18380
+ import chalk163 from "chalk";
18237
18381
  import Enquirer2 from "enquirer";
18238
18382
 
18239
18383
  // src/commands/ravendb/searchItems.ts
18240
18384
  import { execSync as execSync49 } from "child_process";
18241
- import chalk161 from "chalk";
18385
+ import chalk162 from "chalk";
18242
18386
  function opExec(args) {
18243
18387
  return execSync49(`op ${args}`, {
18244
18388
  encoding: "utf8",
@@ -18251,7 +18395,7 @@ function searchItems(search2) {
18251
18395
  items2 = JSON.parse(opExec("item list --format=json"));
18252
18396
  } catch {
18253
18397
  console.error(
18254
- chalk161.red(
18398
+ chalk162.red(
18255
18399
  "Failed to search 1Password. Ensure the CLI is installed and you are signed in."
18256
18400
  )
18257
18401
  );
@@ -18265,7 +18409,7 @@ function getItemFields(itemId2) {
18265
18409
  const item = JSON.parse(opExec(`item get "${itemId2}" --format=json`));
18266
18410
  return item.fields.filter((f) => f.reference && f.label);
18267
18411
  } catch {
18268
- console.error(chalk161.red("Failed to get item details from 1Password."));
18412
+ console.error(chalk162.red("Failed to get item details from 1Password."));
18269
18413
  process.exit(1);
18270
18414
  }
18271
18415
  }
@@ -18284,7 +18428,7 @@ async function selectOpSecret(searchTerm) {
18284
18428
  }).run();
18285
18429
  const items2 = searchItems(search2);
18286
18430
  if (items2.length === 0) {
18287
- console.error(chalk162.red(`No items found matching "${search2}".`));
18431
+ console.error(chalk163.red(`No items found matching "${search2}".`));
18288
18432
  process.exit(1);
18289
18433
  }
18290
18434
  const itemId2 = await selectOne(
@@ -18293,7 +18437,7 @@ async function selectOpSecret(searchTerm) {
18293
18437
  );
18294
18438
  const fields = getItemFields(itemId2);
18295
18439
  if (fields.length === 0) {
18296
- console.error(chalk162.red("No fields with references found on this item."));
18440
+ console.error(chalk163.red("No fields with references found on this item."));
18297
18441
  process.exit(1);
18298
18442
  }
18299
18443
  const ref = await selectOne(
@@ -18307,7 +18451,7 @@ async function selectOpSecret(searchTerm) {
18307
18451
  async function promptConnection(existingNames) {
18308
18452
  const name = await promptInput("name", "Connection name:");
18309
18453
  if (existingNames.includes(name)) {
18310
- console.error(chalk163.red(`Connection "${name}" already exists.`));
18454
+ console.error(chalk164.red(`Connection "${name}" already exists.`));
18311
18455
  process.exit(1);
18312
18456
  }
18313
18457
  const url = await promptInput(
@@ -18316,22 +18460,22 @@ async function promptConnection(existingNames) {
18316
18460
  );
18317
18461
  const database = await promptInput("database", "Database name:");
18318
18462
  if (!name || !url || !database) {
18319
- console.error(chalk163.red("All fields are required."));
18463
+ console.error(chalk164.red("All fields are required."));
18320
18464
  process.exit(1);
18321
18465
  }
18322
18466
  const apiKeyRef = await selectOpSecret();
18323
- console.log(chalk163.dim(`Using: ${apiKeyRef}`));
18467
+ console.log(chalk164.dim(`Using: ${apiKeyRef}`));
18324
18468
  return { name, url, database, apiKeyRef };
18325
18469
  }
18326
18470
 
18327
18471
  // src/commands/ravendb/ravendbSetConnection.ts
18328
- import chalk164 from "chalk";
18472
+ import chalk165 from "chalk";
18329
18473
  function ravendbSetConnection(name) {
18330
18474
  const raw = loadGlobalConfigRaw();
18331
18475
  const ravendb = raw.ravendb ?? {};
18332
18476
  const connections = ravendb.connections ?? [];
18333
18477
  if (!connections.some((c) => c.name === name)) {
18334
- console.error(chalk164.red(`Connection "${name}" not found.`));
18478
+ console.error(chalk165.red(`Connection "${name}" not found.`));
18335
18479
  console.error(
18336
18480
  `Available: ${connections.map((c) => c.name).join(", ") || "(none)"}`
18337
18481
  );
@@ -18347,16 +18491,16 @@ function ravendbSetConnection(name) {
18347
18491
  var ravendbAuth = createConnectionAuth({
18348
18492
  load: loadConnections,
18349
18493
  save: saveConnections,
18350
- format: (c) => `${chalk165.bold(c.name)} ${c.url} db=${c.database} key=${c.apiKeyRef}`,
18494
+ format: (c) => `${chalk166.bold(c.name)} ${c.url} db=${c.database} key=${c.apiKeyRef}`,
18351
18495
  promptNew: promptConnection,
18352
18496
  onFirst: (c) => ravendbSetConnection(c.name)
18353
18497
  });
18354
18498
 
18355
18499
  // src/commands/ravendb/ravendbCollections.ts
18356
- import chalk169 from "chalk";
18500
+ import chalk170 from "chalk";
18357
18501
 
18358
18502
  // src/commands/ravendb/ravenFetch.ts
18359
- import chalk167 from "chalk";
18503
+ import chalk168 from "chalk";
18360
18504
 
18361
18505
  // src/commands/ravendb/getAccessToken.ts
18362
18506
  var OAUTH_URL = "https://amazon-useast-1-oauth.ravenhq.com/ApiKeys/OAuth/AccessToken";
@@ -18393,10 +18537,10 @@ ${errorText}`
18393
18537
 
18394
18538
  // src/commands/ravendb/resolveOpSecret.ts
18395
18539
  import { execSync as execSync50 } from "child_process";
18396
- import chalk166 from "chalk";
18540
+ import chalk167 from "chalk";
18397
18541
  function resolveOpSecret(reference) {
18398
18542
  if (!reference.startsWith("op://")) {
18399
- console.error(chalk166.red(`Invalid secret reference: must start with op://`));
18543
+ console.error(chalk167.red(`Invalid secret reference: must start with op://`));
18400
18544
  process.exit(1);
18401
18545
  }
18402
18546
  try {
@@ -18406,7 +18550,7 @@ function resolveOpSecret(reference) {
18406
18550
  }).trim();
18407
18551
  } catch {
18408
18552
  console.error(
18409
- chalk166.red(
18553
+ chalk167.red(
18410
18554
  "Failed to resolve secret reference. Ensure 1Password CLI is installed and you are signed in."
18411
18555
  )
18412
18556
  );
@@ -18415,10 +18559,10 @@ function resolveOpSecret(reference) {
18415
18559
  }
18416
18560
 
18417
18561
  // src/commands/ravendb/ravenFetch.ts
18418
- async function ravenFetch(connection, path70) {
18562
+ async function ravenFetch(connection, path71) {
18419
18563
  const apiKey = resolveOpSecret(connection.apiKeyRef);
18420
18564
  let accessToken = await getAccessToken(apiKey);
18421
- const url = `${connection.url}${path70}`;
18565
+ const url = `${connection.url}${path71}`;
18422
18566
  const headers = {
18423
18567
  Authorization: `Bearer ${accessToken}`,
18424
18568
  "Content-Type": "application/json"
@@ -18433,7 +18577,7 @@ async function ravenFetch(connection, path70) {
18433
18577
  if (!response.ok) {
18434
18578
  const body = await response.text();
18435
18579
  console.error(
18436
- chalk167.red(`RavenDB error: ${response.status} ${response.statusText}`)
18580
+ chalk168.red(`RavenDB error: ${response.status} ${response.statusText}`)
18437
18581
  );
18438
18582
  console.error(body.substring(0, 500));
18439
18583
  process.exit(1);
@@ -18442,7 +18586,7 @@ async function ravenFetch(connection, path70) {
18442
18586
  }
18443
18587
 
18444
18588
  // src/commands/ravendb/resolveConnection.ts
18445
- import chalk168 from "chalk";
18589
+ import chalk169 from "chalk";
18446
18590
  function loadRavendb() {
18447
18591
  const raw = loadGlobalConfigRaw();
18448
18592
  const ravendb = raw.ravendb;
@@ -18456,7 +18600,7 @@ function resolveConnection(name) {
18456
18600
  const connectionName = name ?? defaultConnection;
18457
18601
  if (!connectionName) {
18458
18602
  console.error(
18459
- chalk168.red(
18603
+ chalk169.red(
18460
18604
  "No connection specified and no default set. Use assist ravendb set-connection <name> or pass a connection name."
18461
18605
  )
18462
18606
  );
@@ -18464,7 +18608,7 @@ function resolveConnection(name) {
18464
18608
  }
18465
18609
  const connection = connections.find((c) => c.name === connectionName);
18466
18610
  if (!connection) {
18467
- console.error(chalk168.red(`Connection "${connectionName}" not found.`));
18611
+ console.error(chalk169.red(`Connection "${connectionName}" not found.`));
18468
18612
  console.error(
18469
18613
  `Available: ${connections.map((c) => c.name).join(", ") || "(none)"}`
18470
18614
  );
@@ -18495,7 +18639,7 @@ async function ravendbCollections(connectionName) {
18495
18639
  return;
18496
18640
  }
18497
18641
  for (const c of collections) {
18498
- console.log(`${chalk169.bold(c.Name)} ${c.CountOfDocuments} docs`);
18642
+ console.log(`${chalk170.bold(c.Name)} ${c.CountOfDocuments} docs`);
18499
18643
  }
18500
18644
  }
18501
18645
 
@@ -18514,24 +18658,24 @@ var ravendbConfigHelp = [
18514
18658
  ];
18515
18659
 
18516
18660
  // src/commands/ravendb/ravendbQuery.ts
18517
- import chalk171 from "chalk";
18661
+ import chalk172 from "chalk";
18518
18662
 
18519
18663
  // src/commands/ravendb/fetchAllPages.ts
18520
- import chalk170 from "chalk";
18664
+ import chalk171 from "chalk";
18521
18665
 
18522
18666
  // src/commands/ravendb/buildQueryPath.ts
18523
18667
  function buildQueryPath(opts) {
18524
18668
  const db = encodeURIComponent(opts.db);
18525
- let path70;
18669
+ let path71;
18526
18670
  if (opts.collection) {
18527
- path70 = `/databases/${db}/indexes/dynamic/${encodeURIComponent(opts.collection)}?start=${opts.start}&pageSize=${opts.pageSize}&sort=${encodeURIComponent(opts.sort)}`;
18671
+ path71 = `/databases/${db}/indexes/dynamic/${encodeURIComponent(opts.collection)}?start=${opts.start}&pageSize=${opts.pageSize}&sort=${encodeURIComponent(opts.sort)}`;
18528
18672
  } else {
18529
- path70 = `/databases/${db}/queries?start=${opts.start}&pageSize=${opts.pageSize}`;
18673
+ path71 = `/databases/${db}/queries?start=${opts.start}&pageSize=${opts.pageSize}`;
18530
18674
  }
18531
18675
  if (opts.query) {
18532
- path70 += `&query=${encodeURIComponent(opts.query)}`;
18676
+ path71 += `&query=${encodeURIComponent(opts.query)}`;
18533
18677
  }
18534
- return path70;
18678
+ return path71;
18535
18679
  }
18536
18680
 
18537
18681
  // src/commands/ravendb/fetchAllPages.ts
@@ -18540,7 +18684,7 @@ async function fetchAllPages(connection, opts) {
18540
18684
  let start3 = 0;
18541
18685
  while (true) {
18542
18686
  const effectivePageSize = opts.limit !== void 0 ? Math.min(opts.pageSize, opts.limit - allResults.length) : opts.pageSize;
18543
- const path70 = buildQueryPath({
18687
+ const path71 = buildQueryPath({
18544
18688
  db: connection.database,
18545
18689
  collection: opts.collection,
18546
18690
  start: start3,
@@ -18548,14 +18692,14 @@ async function fetchAllPages(connection, opts) {
18548
18692
  sort: opts.sort,
18549
18693
  query: opts.query
18550
18694
  });
18551
- const data = await ravenFetch(connection, path70);
18695
+ const data = await ravenFetch(connection, path71);
18552
18696
  const results = data.Results ?? [];
18553
18697
  const totalResults = data.TotalResults ?? 0;
18554
18698
  if (results.length === 0) break;
18555
18699
  allResults.push(...results);
18556
18700
  start3 += results.length;
18557
18701
  process.stderr.write(
18558
- `\r${chalk170.dim(`Fetched ${allResults.length}/${totalResults}`)}`
18702
+ `\r${chalk171.dim(`Fetched ${allResults.length}/${totalResults}`)}`
18559
18703
  );
18560
18704
  if (start3 >= totalResults) break;
18561
18705
  if (opts.limit !== void 0 && allResults.length >= opts.limit) break;
@@ -18570,7 +18714,7 @@ async function fetchAllPages(connection, opts) {
18570
18714
  async function ravendbQuery(connectionName, collection, options2) {
18571
18715
  const resolved = resolveArgs(connectionName, collection);
18572
18716
  if (!resolved.collection && !options2.query) {
18573
- console.error(chalk171.red("Provide a collection name or --query filter."));
18717
+ console.error(chalk172.red("Provide a collection name or --query filter."));
18574
18718
  process.exit(1);
18575
18719
  }
18576
18720
  const { collection: col } = resolved;
@@ -18609,7 +18753,7 @@ import { spawn as spawn5 } from "child_process";
18609
18753
  import * as path36 from "path";
18610
18754
 
18611
18755
  // src/commands/refactor/logViolations.ts
18612
- import chalk172 from "chalk";
18756
+ import chalk173 from "chalk";
18613
18757
  var DEFAULT_MAX_LINES = 100;
18614
18758
  function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
18615
18759
  if (violations.length === 0) {
@@ -18618,43 +18762,43 @@ function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
18618
18762
  }
18619
18763
  return;
18620
18764
  }
18621
- console.error(chalk172.red(`
18765
+ console.error(chalk173.red(`
18622
18766
  Refactor check failed:
18623
18767
  `));
18624
- console.error(chalk172.red(` The following files exceed ${maxLines} lines:
18768
+ console.error(chalk173.red(` The following files exceed ${maxLines} lines:
18625
18769
  `));
18626
18770
  for (const violation of violations) {
18627
- console.error(chalk172.red(` ${violation.file} (${violation.lines} lines)`));
18771
+ console.error(chalk173.red(` ${violation.file} (${violation.lines} lines)`));
18628
18772
  }
18629
18773
  console.error(
18630
- chalk172.yellow(
18774
+ chalk173.yellow(
18631
18775
  `
18632
18776
  Each file needs to be sensibly refactored, or if there is no sensible
18633
18777
  way to refactor it, ignore it with:
18634
18778
  `
18635
18779
  )
18636
18780
  );
18637
- console.error(chalk172.gray(` assist refactor ignore <file>
18781
+ console.error(chalk173.gray(` assist refactor ignore <file>
18638
18782
  `));
18639
18783
  if (process.env.CLAUDECODE) {
18640
- console.error(chalk172.cyan(`
18784
+ console.error(chalk173.cyan(`
18641
18785
  ## Extracting Code to New Files
18642
18786
  `));
18643
18787
  console.error(
18644
- chalk172.cyan(
18788
+ chalk173.cyan(
18645
18789
  ` When extracting logic from one file to another, consider where the extracted code belongs:
18646
18790
  `
18647
18791
  )
18648
18792
  );
18649
18793
  console.error(
18650
- chalk172.cyan(
18794
+ chalk173.cyan(
18651
18795
  ` 1. Keep related logic together: If the extracted code is tightly coupled to the
18652
18796
  original file's domain, create a new folder containing both the original and extracted files.
18653
18797
  `
18654
18798
  )
18655
18799
  );
18656
18800
  console.error(
18657
- chalk172.cyan(
18801
+ chalk173.cyan(
18658
18802
  ` 2. Share common utilities: If the extracted code can be reused across multiple
18659
18803
  domains, move it to a common/shared folder.
18660
18804
  `
@@ -18810,7 +18954,7 @@ async function check(pattern2, options2) {
18810
18954
 
18811
18955
  // src/commands/refactor/extract/index.ts
18812
18956
  import path44 from "path";
18813
- import chalk175 from "chalk";
18957
+ import chalk176 from "chalk";
18814
18958
 
18815
18959
  // src/commands/refactor/extract/applyExtraction.ts
18816
18960
  import { SyntaxKind as SyntaxKind4 } from "ts-morph";
@@ -19409,23 +19553,23 @@ function buildPlan2(functionName, sourceFile, sourcePath, destPath, project) {
19409
19553
 
19410
19554
  // src/commands/refactor/extract/displayPlan.ts
19411
19555
  import path40 from "path";
19412
- import chalk173 from "chalk";
19556
+ import chalk174 from "chalk";
19413
19557
  function section2(title) {
19414
19558
  return `
19415
- ${chalk173.cyan(title)}`;
19559
+ ${chalk174.cyan(title)}`;
19416
19560
  }
19417
19561
  function displayImporters(plan2, cwd) {
19418
19562
  if (plan2.importersToUpdate.length === 0) return;
19419
19563
  console.log(section2("Update importers:"));
19420
19564
  for (const imp of plan2.importersToUpdate) {
19421
19565
  const rel = path40.relative(cwd, imp.file.getFilePath());
19422
- console.log(` ${chalk173.dim(rel)}: \u2192 import from "${imp.relPath}"`);
19566
+ console.log(` ${chalk174.dim(rel)}: \u2192 import from "${imp.relPath}"`);
19423
19567
  }
19424
19568
  }
19425
19569
  function displayPlan(functionName, relDest, plan2, cwd) {
19426
- console.log(chalk173.bold(`Extract: ${functionName} \u2192 ${relDest}
19570
+ console.log(chalk174.bold(`Extract: ${functionName} \u2192 ${relDest}
19427
19571
  `));
19428
- console.log(` ${chalk173.cyan("Functions to move:")}`);
19572
+ console.log(` ${chalk174.cyan("Functions to move:")}`);
19429
19573
  for (const name of plan2.extractedNames) {
19430
19574
  console.log(` ${name}`);
19431
19575
  }
@@ -19459,7 +19603,7 @@ function displayPlan(functionName, relDest, plan2, cwd) {
19459
19603
 
19460
19604
  // src/commands/refactor/extract/loadProjectFile.ts
19461
19605
  import path43 from "path";
19462
- import chalk174 from "chalk";
19606
+ import chalk175 from "chalk";
19463
19607
  import { Project as Project4 } from "ts-morph";
19464
19608
 
19465
19609
  // src/commands/refactor/extract/findTsConfig.ts
@@ -19551,7 +19695,7 @@ function loadProjectFile(file) {
19551
19695
  });
19552
19696
  const sourceFile = project.getSourceFile(sourcePath);
19553
19697
  if (!sourceFile) {
19554
- console.log(chalk174.red(`File not found in project: ${file}`));
19698
+ console.log(chalk175.red(`File not found in project: ${file}`));
19555
19699
  process.exit(1);
19556
19700
  }
19557
19701
  return { project, sourceFile };
@@ -19574,19 +19718,19 @@ async function extract(file, functionName, destination, options2 = {}) {
19574
19718
  displayPlan(functionName, relDest, plan2, cwd);
19575
19719
  if (options2.apply) {
19576
19720
  await applyExtraction(functionName, sourceFile, destPath, plan2, project);
19577
- console.log(chalk175.green("\nExtraction complete"));
19721
+ console.log(chalk176.green("\nExtraction complete"));
19578
19722
  } else {
19579
- console.log(chalk175.dim("\nDry run. Use --apply to execute."));
19723
+ console.log(chalk176.dim("\nDry run. Use --apply to execute."));
19580
19724
  }
19581
19725
  }
19582
19726
 
19583
19727
  // src/commands/refactor/ignore.ts
19584
19728
  import fs28 from "fs";
19585
- import chalk176 from "chalk";
19729
+ import chalk177 from "chalk";
19586
19730
  var REFACTOR_YML_PATH2 = "refactor.yml";
19587
19731
  function ignore2(file) {
19588
19732
  if (!fs28.existsSync(file)) {
19589
- console.error(chalk176.red(`Error: File does not exist: ${file}`));
19733
+ console.error(chalk177.red(`Error: File does not exist: ${file}`));
19590
19734
  process.exit(1);
19591
19735
  }
19592
19736
  const content = fs28.readFileSync(file, "utf8");
@@ -19602,7 +19746,7 @@ function ignore2(file) {
19602
19746
  fs28.writeFileSync(REFACTOR_YML_PATH2, entry);
19603
19747
  }
19604
19748
  console.log(
19605
- chalk176.green(
19749
+ chalk177.green(
19606
19750
  `Added ${file} to refactor ignore list (max ${maxLines} lines)`
19607
19751
  )
19608
19752
  );
@@ -19611,12 +19755,12 @@ function ignore2(file) {
19611
19755
  // src/commands/refactor/rename/index.ts
19612
19756
  import fs31 from "fs";
19613
19757
  import path49 from "path";
19614
- import chalk179 from "chalk";
19758
+ import chalk180 from "chalk";
19615
19759
 
19616
19760
  // src/commands/refactor/rename/applyRename.ts
19617
19761
  import fs30 from "fs";
19618
19762
  import path46 from "path";
19619
- import chalk177 from "chalk";
19763
+ import chalk178 from "chalk";
19620
19764
 
19621
19765
  // src/commands/refactor/restructure/computeRewrites/index.ts
19622
19766
  import path45 from "path";
@@ -19721,13 +19865,13 @@ function applyRename(rewrites, sourcePath, destPath, cwd) {
19721
19865
  const updatedContents = applyRewrites(rewrites);
19722
19866
  for (const [file, content] of updatedContents) {
19723
19867
  fs30.writeFileSync(file, content, "utf8");
19724
- console.log(chalk177.cyan(` Updated imports in ${path46.relative(cwd, file)}`));
19868
+ console.log(chalk178.cyan(` Updated imports in ${path46.relative(cwd, file)}`));
19725
19869
  }
19726
19870
  const destDir = path46.dirname(destPath);
19727
19871
  if (!fs30.existsSync(destDir)) fs30.mkdirSync(destDir, { recursive: true });
19728
19872
  fs30.renameSync(sourcePath, destPath);
19729
19873
  console.log(
19730
- chalk177.white(
19874
+ chalk178.white(
19731
19875
  ` Moved ${path46.relative(cwd, sourcePath)} \u2192 ${path46.relative(cwd, destPath)}`
19732
19876
  )
19733
19877
  );
@@ -19814,16 +19958,16 @@ function computeRenameRewrites(sourcePath, destPath) {
19814
19958
 
19815
19959
  // src/commands/refactor/rename/printRenamePreview.ts
19816
19960
  import path48 from "path";
19817
- import chalk178 from "chalk";
19961
+ import chalk179 from "chalk";
19818
19962
  function printRenamePreview(rewrites, cwd) {
19819
19963
  for (const rewrite of rewrites) {
19820
19964
  console.log(
19821
- chalk178.dim(
19965
+ chalk179.dim(
19822
19966
  ` ${path48.relative(cwd, rewrite.file)}: ${rewrite.oldSpecifier} \u2192 ${rewrite.newSpecifier}`
19823
19967
  )
19824
19968
  );
19825
19969
  }
19826
- console.log(chalk178.dim("Dry run. Use --apply to execute."));
19970
+ console.log(chalk179.dim("Dry run. Use --apply to execute."));
19827
19971
  }
19828
19972
 
19829
19973
  // src/commands/refactor/rename/index.ts
@@ -19834,20 +19978,20 @@ async function rename(source, destination, options2 = {}) {
19834
19978
  const relSource = path49.relative(cwd, sourcePath);
19835
19979
  const relDest = path49.relative(cwd, destPath);
19836
19980
  if (!fs31.existsSync(sourcePath)) {
19837
- console.log(chalk179.red(`File not found: ${source}`));
19981
+ console.log(chalk180.red(`File not found: ${source}`));
19838
19982
  process.exit(1);
19839
19983
  }
19840
19984
  if (destPath !== sourcePath && fs31.existsSync(destPath)) {
19841
- console.log(chalk179.red(`Destination already exists: ${destination}`));
19985
+ console.log(chalk180.red(`Destination already exists: ${destination}`));
19842
19986
  process.exit(1);
19843
19987
  }
19844
- console.log(chalk179.bold(`Rename: ${relSource} \u2192 ${relDest}`));
19845
- console.log(chalk179.dim("Loading project..."));
19846
- console.log(chalk179.dim("Scanning imports across the project..."));
19988
+ console.log(chalk180.bold(`Rename: ${relSource} \u2192 ${relDest}`));
19989
+ console.log(chalk180.dim("Loading project..."));
19990
+ console.log(chalk180.dim("Scanning imports across the project..."));
19847
19991
  const rewrites = computeRenameRewrites(sourcePath, destPath);
19848
19992
  const affectedFiles = new Set(rewrites.map((r) => r.file)).size;
19849
19993
  console.log(
19850
- chalk179.dim(
19994
+ chalk180.dim(
19851
19995
  `${rewrites.length} import path(s) to update across ${affectedFiles} file(s)`
19852
19996
  )
19853
19997
  );
@@ -19856,11 +20000,11 @@ async function rename(source, destination, options2 = {}) {
19856
20000
  return;
19857
20001
  }
19858
20002
  applyRename(rewrites, sourcePath, destPath, cwd);
19859
- console.log(chalk179.green("Done"));
20003
+ console.log(chalk180.green("Done"));
19860
20004
  }
19861
20005
 
19862
20006
  // src/commands/refactor/renameSymbol/index.ts
19863
- import chalk180 from "chalk";
20007
+ import chalk181 from "chalk";
19864
20008
 
19865
20009
  // src/commands/refactor/renameSymbol/findSymbol.ts
19866
20010
  import { SyntaxKind as SyntaxKind15 } from "ts-morph";
@@ -19906,33 +20050,33 @@ async function renameSymbol(file, oldName, newName, options2 = {}) {
19906
20050
  const { project, sourceFile } = loadProjectFile(file);
19907
20051
  const symbol = findSymbol(sourceFile, oldName);
19908
20052
  if (!symbol) {
19909
- console.log(chalk180.red(`Symbol "${oldName}" not found in ${file}`));
20053
+ console.log(chalk181.red(`Symbol "${oldName}" not found in ${file}`));
19910
20054
  process.exit(1);
19911
20055
  }
19912
20056
  const grouped = groupReferences(symbol, cwd);
19913
20057
  const totalRefs = [...grouped.values()].reduce((s, l) => s + l.length, 0);
19914
20058
  console.log(
19915
- chalk180.bold(`Rename: ${oldName} \u2192 ${newName} (${totalRefs} references)
20059
+ chalk181.bold(`Rename: ${oldName} \u2192 ${newName} (${totalRefs} references)
19916
20060
  `)
19917
20061
  );
19918
20062
  for (const [refFile, lines] of grouped) {
19919
20063
  console.log(
19920
- ` ${chalk180.dim(refFile)}: lines ${chalk180.cyan(lines.join(", "))}`
20064
+ ` ${chalk181.dim(refFile)}: lines ${chalk181.cyan(lines.join(", "))}`
19921
20065
  );
19922
20066
  }
19923
20067
  if (options2.apply) {
19924
20068
  symbol.rename(newName);
19925
20069
  await project.save();
19926
- console.log(chalk180.green(`
20070
+ console.log(chalk181.green(`
19927
20071
  Renamed ${oldName} \u2192 ${newName}`));
19928
20072
  } else {
19929
- console.log(chalk180.dim("\nDry run. Use --apply to execute."));
20073
+ console.log(chalk181.dim("\nDry run. Use --apply to execute."));
19930
20074
  }
19931
20075
  }
19932
20076
 
19933
20077
  // src/commands/refactor/restructure/index.ts
19934
20078
  import path57 from "path";
19935
- import chalk183 from "chalk";
20079
+ import chalk184 from "chalk";
19936
20080
 
19937
20081
  // src/commands/refactor/restructure/clusterDirectories.ts
19938
20082
  import path51 from "path";
@@ -20011,50 +20155,50 @@ function clusterFiles(graph) {
20011
20155
 
20012
20156
  // src/commands/refactor/restructure/displayPlan.ts
20013
20157
  import path53 from "path";
20014
- import chalk181 from "chalk";
20158
+ import chalk182 from "chalk";
20015
20159
  function relPath(filePath) {
20016
20160
  return path53.relative(process.cwd(), filePath);
20017
20161
  }
20018
20162
  function displayMoves(plan2) {
20019
20163
  if (plan2.moves.length === 0) return;
20020
- console.log(chalk181.bold("\nFile moves:"));
20164
+ console.log(chalk182.bold("\nFile moves:"));
20021
20165
  for (const move2 of plan2.moves) {
20022
20166
  console.log(
20023
- ` ${chalk181.red(relPath(move2.from))} \u2192 ${chalk181.green(relPath(move2.to))}`
20167
+ ` ${chalk182.red(relPath(move2.from))} \u2192 ${chalk182.green(relPath(move2.to))}`
20024
20168
  );
20025
- console.log(chalk181.dim(` ${move2.reason}`));
20169
+ console.log(chalk182.dim(` ${move2.reason}`));
20026
20170
  }
20027
20171
  }
20028
20172
  function displayRewrites(rewrites) {
20029
20173
  if (rewrites.length === 0) return;
20030
20174
  const affectedFiles = new Set(rewrites.map((r) => r.file));
20031
- console.log(chalk181.bold(`
20175
+ console.log(chalk182.bold(`
20032
20176
  Import rewrites (${affectedFiles.size} files):`));
20033
20177
  for (const file of affectedFiles) {
20034
- console.log(` ${chalk181.cyan(relPath(file))}:`);
20178
+ console.log(` ${chalk182.cyan(relPath(file))}:`);
20035
20179
  for (const { oldSpecifier, newSpecifier } of rewrites.filter(
20036
20180
  (r) => r.file === file
20037
20181
  )) {
20038
20182
  console.log(
20039
- ` ${chalk181.red(`"${oldSpecifier}"`)} \u2192 ${chalk181.green(`"${newSpecifier}"`)}`
20183
+ ` ${chalk182.red(`"${oldSpecifier}"`)} \u2192 ${chalk182.green(`"${newSpecifier}"`)}`
20040
20184
  );
20041
20185
  }
20042
20186
  }
20043
20187
  }
20044
20188
  function displayPlan2(plan2) {
20045
20189
  if (plan2.warnings.length > 0) {
20046
- console.log(chalk181.yellow("\nWarnings:"));
20047
- for (const w of plan2.warnings) console.log(chalk181.yellow(` ${w}`));
20190
+ console.log(chalk182.yellow("\nWarnings:"));
20191
+ for (const w of plan2.warnings) console.log(chalk182.yellow(` ${w}`));
20048
20192
  }
20049
20193
  if (plan2.newDirectories.length > 0) {
20050
- console.log(chalk181.bold("\nNew directories:"));
20194
+ console.log(chalk182.bold("\nNew directories:"));
20051
20195
  for (const dir of plan2.newDirectories)
20052
- console.log(chalk181.green(` ${dir}/`));
20196
+ console.log(chalk182.green(` ${dir}/`));
20053
20197
  }
20054
20198
  displayMoves(plan2);
20055
20199
  displayRewrites(plan2.rewrites);
20056
20200
  console.log(
20057
- chalk181.dim(
20201
+ chalk182.dim(
20058
20202
  `
20059
20203
  Summary: ${plan2.moves.length} file(s) moved, ${plan2.rewrites.length} imports rewritten`
20060
20204
  )
@@ -20064,18 +20208,18 @@ Summary: ${plan2.moves.length} file(s) moved, ${plan2.rewrites.length} imports r
20064
20208
  // src/commands/refactor/restructure/executePlan.ts
20065
20209
  import fs32 from "fs";
20066
20210
  import path54 from "path";
20067
- import chalk182 from "chalk";
20211
+ import chalk183 from "chalk";
20068
20212
  function executePlan(plan2) {
20069
20213
  const updatedContents = applyRewrites(plan2.rewrites);
20070
20214
  for (const [file, content] of updatedContents) {
20071
20215
  fs32.writeFileSync(file, content, "utf8");
20072
20216
  console.log(
20073
- chalk182.cyan(` Rewrote imports in ${path54.relative(process.cwd(), file)}`)
20217
+ chalk183.cyan(` Rewrote imports in ${path54.relative(process.cwd(), file)}`)
20074
20218
  );
20075
20219
  }
20076
20220
  for (const dir of plan2.newDirectories) {
20077
20221
  fs32.mkdirSync(dir, { recursive: true });
20078
- console.log(chalk182.green(` Created ${path54.relative(process.cwd(), dir)}/`));
20222
+ console.log(chalk183.green(` Created ${path54.relative(process.cwd(), dir)}/`));
20079
20223
  }
20080
20224
  for (const move2 of plan2.moves) {
20081
20225
  const targetDir = path54.dirname(move2.to);
@@ -20084,7 +20228,7 @@ function executePlan(plan2) {
20084
20228
  }
20085
20229
  fs32.renameSync(move2.from, move2.to);
20086
20230
  console.log(
20087
- chalk182.white(
20231
+ chalk183.white(
20088
20232
  ` Moved ${path54.relative(process.cwd(), move2.from)} \u2192 ${path54.relative(process.cwd(), move2.to)}`
20089
20233
  )
20090
20234
  );
@@ -20099,7 +20243,7 @@ function removeEmptyDirectories(dirs) {
20099
20243
  if (entries.length === 0) {
20100
20244
  fs32.rmdirSync(dir);
20101
20245
  console.log(
20102
- chalk182.dim(
20246
+ chalk183.dim(
20103
20247
  ` Removed empty directory ${path54.relative(process.cwd(), dir)}`
20104
20248
  )
20105
20249
  );
@@ -20232,22 +20376,22 @@ async function restructure(pattern2, options2 = {}) {
20232
20376
  const targetPattern = pattern2 ?? "src";
20233
20377
  const files = findSourceFiles2(targetPattern);
20234
20378
  if (files.length === 0) {
20235
- console.log(chalk183.yellow("No files found matching pattern"));
20379
+ console.log(chalk184.yellow("No files found matching pattern"));
20236
20380
  return;
20237
20381
  }
20238
20382
  const tsConfigPath = findTsConfig(path57.resolve(files[0]));
20239
20383
  const plan2 = buildPlan3(files, tsConfigPath);
20240
20384
  if (plan2.moves.length === 0) {
20241
- console.log(chalk183.green("No restructuring needed"));
20385
+ console.log(chalk184.green("No restructuring needed"));
20242
20386
  return;
20243
20387
  }
20244
20388
  displayPlan2(plan2);
20245
20389
  if (options2.apply) {
20246
- console.log(chalk183.bold("\nApplying changes..."));
20390
+ console.log(chalk184.bold("\nApplying changes..."));
20247
20391
  executePlan(plan2);
20248
- console.log(chalk183.green("\nRestructuring complete"));
20392
+ console.log(chalk184.green("\nRestructuring complete"));
20249
20393
  } else {
20250
- console.log(chalk183.dim("\nDry run. Use --apply to execute."));
20394
+ console.log(chalk184.dim("\nDry run. Use --apply to execute."));
20251
20395
  }
20252
20396
  }
20253
20397
 
@@ -20830,18 +20974,18 @@ function partitionFindingsByDiff(findings, index3) {
20830
20974
  }
20831
20975
 
20832
20976
  // src/commands/review/warnOutOfDiff.ts
20833
- import chalk184 from "chalk";
20977
+ import chalk185 from "chalk";
20834
20978
  function warnOutOfDiff(outOfDiff) {
20835
20979
  if (outOfDiff.length === 0) return;
20836
20980
  console.warn(
20837
- chalk184.yellow(
20981
+ chalk185.yellow(
20838
20982
  `Skipped ${outOfDiff.length} finding(s) whose lines fall outside the PR diff (GitHub would silently drop these):`
20839
20983
  )
20840
20984
  );
20841
20985
  for (const finding of outOfDiff) {
20842
20986
  const range = finding.startLine !== void 0 ? `${finding.startLine}-${finding.line}` : `${finding.line}`;
20843
20987
  console.warn(
20844
- ` ${chalk184.yellow("\xB7")} ${finding.title} ${chalk184.dim(
20988
+ ` ${chalk185.yellow("\xB7")} ${finding.title} ${chalk185.dim(
20845
20989
  `(${finding.file}:${range})`
20846
20990
  )}`
20847
20991
  );
@@ -20860,18 +21004,18 @@ function selectInDiffFindings(lineBound, prDiff) {
20860
21004
  }
20861
21005
 
20862
21006
  // src/commands/review/warnUnlocated.ts
20863
- import chalk185 from "chalk";
21007
+ import chalk186 from "chalk";
20864
21008
  function warnUnlocated(unlocated) {
20865
21009
  if (unlocated.length === 0) return;
20866
21010
  console.warn(
20867
- chalk185.yellow(
21011
+ chalk186.yellow(
20868
21012
  `Skipped ${unlocated.length} finding(s) without a parseable file:line:`
20869
21013
  )
20870
21014
  );
20871
21015
  for (const finding of unlocated) {
20872
- const where = finding.location || chalk185.dim("missing");
21016
+ const where = finding.location || chalk186.dim("missing");
20873
21017
  console.warn(
20874
- ` ${chalk185.yellow("\xB7")} ${finding.title} ${chalk185.dim(`(${where})`)}`
21018
+ ` ${chalk186.yellow("\xB7")} ${finding.title} ${chalk186.dim(`(${where})`)}`
20875
21019
  );
20876
21020
  }
20877
21021
  }
@@ -20968,8 +21112,8 @@ async function handlePostSynthesis(synthesisPath, options2) {
20968
21112
  // src/commands/review/prepareReviewDir.ts
20969
21113
  import { existsSync as existsSync45, mkdirSync as mkdirSync18, unlinkSync as unlinkSync16, writeFileSync as writeFileSync36 } from "fs";
20970
21114
  function clearReviewFiles(paths) {
20971
- for (const path70 of [paths.claudePath, paths.codexPath, paths.synthesisPath]) {
20972
- if (existsSync45(path70)) unlinkSync16(path70);
21115
+ for (const path71 of [paths.claudePath, paths.codexPath, paths.synthesisPath]) {
21116
+ if (existsSync45(path71)) unlinkSync16(path71);
20973
21117
  }
20974
21118
  }
20975
21119
  function prepareReviewDir(paths, requestBody, force) {
@@ -22043,7 +22187,7 @@ function registerReview(program2) {
22043
22187
  }
22044
22188
 
22045
22189
  // src/commands/seq/seqAuth.ts
22046
- import chalk187 from "chalk";
22190
+ import chalk188 from "chalk";
22047
22191
 
22048
22192
  // src/commands/seq/loadConnections.ts
22049
22193
  function loadConnections2() {
@@ -22072,10 +22216,10 @@ function setDefaultConnection(name) {
22072
22216
  }
22073
22217
 
22074
22218
  // src/shared/assertUniqueName.ts
22075
- import chalk186 from "chalk";
22219
+ import chalk187 from "chalk";
22076
22220
  function assertUniqueName(existingNames, name) {
22077
22221
  if (existingNames.includes(name)) {
22078
- console.error(chalk186.red(`Connection "${name}" already exists.`));
22222
+ console.error(chalk187.red(`Connection "${name}" already exists.`));
22079
22223
  process.exit(1);
22080
22224
  }
22081
22225
  }
@@ -22093,7 +22237,7 @@ async function promptConnection2(existingNames) {
22093
22237
  var seqAuth = createConnectionAuth({
22094
22238
  load: loadConnections2,
22095
22239
  save: saveConnections2,
22096
- format: (c) => `${chalk187.bold(c.name)} ${c.url}`,
22240
+ format: (c) => `${chalk188.bold(c.name)} ${c.url}`,
22097
22241
  promptNew: promptConnection2,
22098
22242
  onFirst: (c) => setDefaultConnection(c.name)
22099
22243
  });
@@ -22113,12 +22257,12 @@ var seqConfigHelp = [
22113
22257
  ];
22114
22258
 
22115
22259
  // src/commands/seq/seqQuery.ts
22116
- import chalk191 from "chalk";
22260
+ import chalk192 from "chalk";
22117
22261
 
22118
22262
  // src/commands/seq/fetchSeq.ts
22119
- import chalk188 from "chalk";
22120
- async function fetchSeq(conn, path70, params) {
22121
- const url = `${conn.url}${path70}?${params}`;
22263
+ import chalk189 from "chalk";
22264
+ async function fetchSeq(conn, path71, params) {
22265
+ const url = `${conn.url}${path71}?${params}`;
22122
22266
  const response = await fetch(url, {
22123
22267
  headers: {
22124
22268
  Accept: "application/json",
@@ -22127,7 +22271,7 @@ async function fetchSeq(conn, path70, params) {
22127
22271
  });
22128
22272
  if (!response.ok) {
22129
22273
  const body = await response.text();
22130
- console.error(chalk188.red(`Seq returned ${response.status}: ${body}`));
22274
+ console.error(chalk189.red(`Seq returned ${response.status}: ${body}`));
22131
22275
  process.exit(1);
22132
22276
  }
22133
22277
  return response;
@@ -22186,23 +22330,23 @@ async function fetchSeqEvents(conn, params) {
22186
22330
  }
22187
22331
 
22188
22332
  // src/commands/seq/formatEvent.ts
22189
- import chalk189 from "chalk";
22333
+ import chalk190 from "chalk";
22190
22334
  function levelColor(level) {
22191
22335
  switch (level) {
22192
22336
  case "Fatal":
22193
- return chalk189.bgRed.white;
22337
+ return chalk190.bgRed.white;
22194
22338
  case "Error":
22195
- return chalk189.red;
22339
+ return chalk190.red;
22196
22340
  case "Warning":
22197
- return chalk189.yellow;
22341
+ return chalk190.yellow;
22198
22342
  case "Information":
22199
- return chalk189.cyan;
22343
+ return chalk190.cyan;
22200
22344
  case "Debug":
22201
- return chalk189.gray;
22345
+ return chalk190.gray;
22202
22346
  case "Verbose":
22203
- return chalk189.dim;
22347
+ return chalk190.dim;
22204
22348
  default:
22205
- return chalk189.white;
22349
+ return chalk190.white;
22206
22350
  }
22207
22351
  }
22208
22352
  function levelAbbrev(level) {
@@ -22243,12 +22387,12 @@ function formatTimestamp(iso) {
22243
22387
  function formatEvent(event) {
22244
22388
  const color = levelColor(event.Level);
22245
22389
  const abbrev = levelAbbrev(event.Level);
22246
- const ts8 = chalk189.dim(formatTimestamp(event.Timestamp));
22390
+ const ts8 = chalk190.dim(formatTimestamp(event.Timestamp));
22247
22391
  const msg = renderMessage(event);
22248
22392
  const lines = [`${ts8} ${color(`[${abbrev}]`)} ${msg}`];
22249
22393
  if (event.Exception) {
22250
22394
  for (const line of event.Exception.split("\n")) {
22251
- lines.push(chalk189.red(` ${line}`));
22395
+ lines.push(chalk190.red(` ${line}`));
22252
22396
  }
22253
22397
  }
22254
22398
  return lines.join("\n");
@@ -22281,11 +22425,11 @@ function rejectTimestampFilter(filter) {
22281
22425
  }
22282
22426
 
22283
22427
  // src/shared/resolveNamedConnection.ts
22284
- import chalk190 from "chalk";
22428
+ import chalk191 from "chalk";
22285
22429
  function resolveNamedConnection(connections, requested, defaultName, kind, authCommand) {
22286
22430
  if (connections.length === 0) {
22287
22431
  console.error(
22288
- chalk190.red(
22432
+ chalk191.red(
22289
22433
  `No ${kind} connections configured. Run '${authCommand}' first.`
22290
22434
  )
22291
22435
  );
@@ -22294,7 +22438,7 @@ function resolveNamedConnection(connections, requested, defaultName, kind, authC
22294
22438
  const target = requested ?? defaultName ?? connections[0].name;
22295
22439
  const connection = connections.find((c) => c.name === target);
22296
22440
  if (!connection) {
22297
- console.error(chalk190.red(`${kind} connection "${target}" not found.`));
22441
+ console.error(chalk191.red(`${kind} connection "${target}" not found.`));
22298
22442
  process.exit(1);
22299
22443
  }
22300
22444
  return connection;
@@ -22323,7 +22467,7 @@ async function seqQuery(filter, options2) {
22323
22467
  new URLSearchParams({ filter, count: String(count7) })
22324
22468
  );
22325
22469
  if (events.length === 0) {
22326
- console.log(chalk191.yellow("No events found."));
22470
+ console.log(chalk192.yellow("No events found."));
22327
22471
  return;
22328
22472
  }
22329
22473
  if (options2.json) {
@@ -22334,11 +22478,11 @@ async function seqQuery(filter, options2) {
22334
22478
  for (const event of chronological) {
22335
22479
  console.log(formatEvent(event));
22336
22480
  }
22337
- console.log(chalk191.dim(`
22481
+ console.log(chalk192.dim(`
22338
22482
  ${events.length} events`));
22339
22483
  if (events.length >= count7) {
22340
22484
  console.log(
22341
- chalk191.yellow(
22485
+ chalk192.yellow(
22342
22486
  `Results limited to ${count7}. Use --count to retrieve more.`
22343
22487
  )
22344
22488
  );
@@ -22346,10 +22490,10 @@ ${events.length} events`));
22346
22490
  }
22347
22491
 
22348
22492
  // src/shared/setNamedDefaultConnection.ts
22349
- import chalk192 from "chalk";
22493
+ import chalk193 from "chalk";
22350
22494
  function setNamedDefaultConnection(connections, name, setDefault, kind) {
22351
22495
  if (!connections.find((c) => c.name === name)) {
22352
- console.error(chalk192.red(`Connection "${name}" not found.`));
22496
+ console.error(chalk193.red(`Connection "${name}" not found.`));
22353
22497
  process.exit(1);
22354
22498
  }
22355
22499
  setDefault(name);
@@ -22398,7 +22542,7 @@ function registerSignal(program2) {
22398
22542
  }
22399
22543
 
22400
22544
  // src/commands/sql/sqlAuth.ts
22401
- import chalk194 from "chalk";
22545
+ import chalk195 from "chalk";
22402
22546
 
22403
22547
  // src/commands/sql/loadConnections.ts
22404
22548
  function loadConnections3() {
@@ -22427,7 +22571,7 @@ function setDefaultConnection2(name) {
22427
22571
  }
22428
22572
 
22429
22573
  // src/commands/sql/promptConnection.ts
22430
- import chalk193 from "chalk";
22574
+ import chalk194 from "chalk";
22431
22575
  async function promptConnection3(existingNames) {
22432
22576
  const name = await promptInput("name", "Connection name:", "default");
22433
22577
  assertUniqueName(existingNames, name);
@@ -22435,7 +22579,7 @@ async function promptConnection3(existingNames) {
22435
22579
  const portStr = await promptInput("port", "Port:", "1433");
22436
22580
  const port = Number.parseInt(portStr, 10);
22437
22581
  if (!Number.isFinite(port)) {
22438
- console.error(chalk193.red(`Invalid port "${portStr}".`));
22582
+ console.error(chalk194.red(`Invalid port "${portStr}".`));
22439
22583
  process.exit(1);
22440
22584
  }
22441
22585
  const user = await promptInput("user", "User:");
@@ -22448,13 +22592,13 @@ async function promptConnection3(existingNames) {
22448
22592
  var sqlAuth = createConnectionAuth({
22449
22593
  load: loadConnections3,
22450
22594
  save: saveConnections3,
22451
- format: (c) => `${chalk194.bold(c.name)} ${c.server}:${c.port}/${c.database} (${c.user})`,
22595
+ format: (c) => `${chalk195.bold(c.name)} ${c.server}:${c.port}/${c.database} (${c.user})`,
22452
22596
  promptNew: promptConnection3,
22453
22597
  onFirst: (c) => setDefaultConnection2(c.name)
22454
22598
  });
22455
22599
 
22456
22600
  // src/commands/sql/printTable.ts
22457
- import chalk195 from "chalk";
22601
+ import chalk196 from "chalk";
22458
22602
  function formatCell(value) {
22459
22603
  if (value === null || value === void 0) return "";
22460
22604
  if (value instanceof Date) return value.toISOString();
@@ -22463,7 +22607,7 @@ function formatCell(value) {
22463
22607
  }
22464
22608
  function printTable(rows) {
22465
22609
  if (rows.length === 0) {
22466
- console.log(chalk195.yellow("(no rows)"));
22610
+ console.log(chalk196.yellow("(no rows)"));
22467
22611
  return;
22468
22612
  }
22469
22613
  const columns = Object.keys(rows[0]);
@@ -22471,13 +22615,13 @@ function printTable(rows) {
22471
22615
  (col) => Math.max(col.length, ...rows.map((r) => formatCell(r[col]).length))
22472
22616
  );
22473
22617
  const header = columns.map((c, i) => c.padEnd(widths[i])).join(" ");
22474
- console.log(chalk195.dim(header));
22475
- console.log(chalk195.dim("-".repeat(header.length)));
22618
+ console.log(chalk196.dim(header));
22619
+ console.log(chalk196.dim("-".repeat(header.length)));
22476
22620
  for (const row of rows) {
22477
22621
  const line = columns.map((c, i) => formatCell(row[c]).padEnd(widths[i])).join(" ");
22478
22622
  console.log(line);
22479
22623
  }
22480
- console.log(chalk195.dim(`
22624
+ console.log(chalk196.dim(`
22481
22625
  ${rows.length} row${rows.length === 1 ? "" : "s"}`));
22482
22626
  }
22483
22627
 
@@ -22551,7 +22695,7 @@ var sqlConfigHelp = [
22551
22695
  ];
22552
22696
 
22553
22697
  // src/commands/sql/sqlMutate.ts
22554
- import chalk196 from "chalk";
22698
+ import chalk197 from "chalk";
22555
22699
 
22556
22700
  // src/commands/sql/isMutation.ts
22557
22701
  var MUTATION_KEYWORDS = [
@@ -22585,7 +22729,7 @@ function isMutation(sql25) {
22585
22729
  async function sqlMutate(query, connectionName) {
22586
22730
  if (!isMutation(query)) {
22587
22731
  console.error(
22588
- chalk196.red(
22732
+ chalk197.red(
22589
22733
  "assist sql mutate refuses non-mutating statements. Use `assist sql query` instead."
22590
22734
  )
22591
22735
  );
@@ -22595,18 +22739,18 @@ async function sqlMutate(query, connectionName) {
22595
22739
  const pool = await sqlConnect(conn);
22596
22740
  try {
22597
22741
  const result = await pool.request().query(query);
22598
- console.log(chalk196.dim(`${result.rowsAffected.join(", ")} row(s) affected`));
22742
+ console.log(chalk197.dim(`${result.rowsAffected.join(", ")} row(s) affected`));
22599
22743
  } finally {
22600
22744
  await pool.close();
22601
22745
  }
22602
22746
  }
22603
22747
 
22604
22748
  // src/commands/sql/sqlQuery.ts
22605
- import chalk197 from "chalk";
22749
+ import chalk198 from "chalk";
22606
22750
  async function sqlQuery(query, connectionName) {
22607
22751
  if (isMutation(query)) {
22608
22752
  console.error(
22609
- chalk197.red(
22753
+ chalk198.red(
22610
22754
  "assist sql query refuses mutating statements. Use `assist sql mutate` instead."
22611
22755
  )
22612
22756
  );
@@ -22621,7 +22765,7 @@ async function sqlQuery(query, connectionName) {
22621
22765
  printTable(rows);
22622
22766
  } else {
22623
22767
  console.log(
22624
- chalk197.dim(`${result.rowsAffected.join(", ")} row(s) affected`)
22768
+ chalk198.dim(`${result.rowsAffected.join(", ")} row(s) affected`)
22625
22769
  );
22626
22770
  }
22627
22771
  } finally {
@@ -23436,7 +23580,7 @@ function registerVoice(program2) {
23436
23580
 
23437
23581
  // src/commands/roam/auth.ts
23438
23582
  import { randomBytes } from "crypto";
23439
- import chalk198 from "chalk";
23583
+ import chalk199 from "chalk";
23440
23584
 
23441
23585
  // src/commands/roam/waitForCallback.ts
23442
23586
  import { createServer as createServer3 } from "http";
@@ -23567,13 +23711,13 @@ async function auth() {
23567
23711
  saveGlobalConfig(config);
23568
23712
  const state = randomBytes(16).toString("hex");
23569
23713
  console.log(
23570
- chalk198.yellow("\nEnsure this Redirect URI is set in your Roam OAuth app:")
23714
+ chalk199.yellow("\nEnsure this Redirect URI is set in your Roam OAuth app:")
23571
23715
  );
23572
- console.log(chalk198.white("http://localhost:14523/callback\n"));
23573
- console.log(chalk198.blue("Opening browser for authorization..."));
23574
- console.log(chalk198.dim("Waiting for authorization callback..."));
23716
+ console.log(chalk199.white("http://localhost:14523/callback\n"));
23717
+ console.log(chalk199.blue("Opening browser for authorization..."));
23718
+ console.log(chalk199.dim("Waiting for authorization callback..."));
23575
23719
  const { code, redirectUri } = await authorizeInBrowser(clientId, state);
23576
- console.log(chalk198.dim("Exchanging code for tokens..."));
23720
+ console.log(chalk199.dim("Exchanging code for tokens..."));
23577
23721
  const tokens = await exchangeToken({
23578
23722
  code,
23579
23723
  clientId,
@@ -23589,7 +23733,7 @@ async function auth() {
23589
23733
  };
23590
23734
  saveGlobalConfig(config);
23591
23735
  console.log(
23592
- chalk198.green("Roam credentials and tokens saved to ~/.assist.yml")
23736
+ chalk199.green("Roam credentials and tokens saved to ~/.assist.yml")
23593
23737
  );
23594
23738
  }
23595
23739
 
@@ -23605,9 +23749,9 @@ function findPortFile(roamDir) {
23605
23749
  return void 0;
23606
23750
  }
23607
23751
  const candidates = entries.filter((name) => /^roam-local-api(-[^.]+)?\.port$/.test(name)).map((name) => {
23608
- const path70 = join62(roamDir, name);
23752
+ const path71 = join62(roamDir, name);
23609
23753
  try {
23610
- return { path: path70, mtimeMs: statSync8(path70).mtimeMs };
23754
+ return { path: path71, mtimeMs: statSync8(path71).mtimeMs };
23611
23755
  } catch {
23612
23756
  return void 0;
23613
23757
  }
@@ -24026,11 +24170,11 @@ function findLinkIndex() {
24026
24170
  function parseLinkArgs() {
24027
24171
  const idx = findLinkIndex();
24028
24172
  if (idx === -1) return null;
24029
- const path70 = process.argv[idx + 1];
24173
+ const path71 = process.argv[idx + 1];
24030
24174
  const rest = process.argv.slice(idx + 2);
24031
24175
  const { value: prefix2 } = extractOption(rest, "--prefix");
24032
24176
  if (!prefix2) return null;
24033
- return { path: path70, prefix: prefix2 };
24177
+ return { path: path71, prefix: prefix2 };
24034
24178
  }
24035
24179
  function hasDuplicateLink(runList, linkPath) {
24036
24180
  return runList.some(
@@ -24132,7 +24276,7 @@ import { execSync as execSync58 } from "child_process";
24132
24276
  import { existsSync as existsSync56, mkdirSync as mkdirSync24, unlinkSync as unlinkSync21, writeFileSync as writeFileSync42 } from "fs";
24133
24277
  import { tmpdir as tmpdir7 } from "os";
24134
24278
  import { join as join66, resolve as resolve16 } from "path";
24135
- import chalk199 from "chalk";
24279
+ import chalk200 from "chalk";
24136
24280
 
24137
24281
  // src/commands/screenshot/captureWindowPs1.ts
24138
24282
  var captureWindowPs1 = `
@@ -24283,13 +24427,13 @@ function screenshot(processName) {
24283
24427
  const config = loadConfig();
24284
24428
  const outputDir = resolve16(config.screenshot.outputDir);
24285
24429
  const outputPath = buildOutputPath(outputDir, processName);
24286
- console.log(chalk199.gray(`Capturing window for process "${processName}" ...`));
24430
+ console.log(chalk200.gray(`Capturing window for process "${processName}" ...`));
24287
24431
  try {
24288
24432
  runPowerShellScript(processName, outputPath);
24289
- console.log(chalk199.green(`Screenshot saved: ${outputPath}`));
24433
+ console.log(chalk200.green(`Screenshot saved: ${outputPath}`));
24290
24434
  } catch (error) {
24291
24435
  const msg = error instanceof Error ? error.message : String(error);
24292
- console.error(chalk199.red(`Failed to capture screenshot: ${msg}`));
24436
+ console.error(chalk200.red(`Failed to capture screenshot: ${msg}`));
24293
24437
  process.exit(1);
24294
24438
  }
24295
24439
  }
@@ -24911,6 +25055,7 @@ function dismissSession(sessions, id) {
24911
25055
  if (!s) return false;
24912
25056
  if (s.status !== "done") s.pty?.kill();
24913
25057
  s.activityWatcher?.close();
25058
+ s.transcriptWatcher?.close();
24914
25059
  removeActivity(s.id);
24915
25060
  if (s.activity?.itemId != null) releaseLock(s.activity.itemId);
24916
25061
  sessions.delete(id);
@@ -25017,113 +25162,18 @@ function logSpawnedSession(session) {
25017
25162
  );
25018
25163
  }
25019
25164
 
25020
- // src/commands/sessions/daemon/setStatus.ts
25021
- function setStatus2(session, newStatus) {
25022
- const now = Date.now();
25023
- if (session.status === "running" && session.runningSince != null) {
25024
- session.runningMs += now - session.runningSince;
25025
- }
25026
- session.runningSince = newStatus === "running" ? now : null;
25027
- session.status = newStatus;
25028
- }
25029
-
25030
- // src/commands/sessions/daemon/shouldAutoDismiss.ts
25031
- function shouldAutoDismiss(session, exitCode) {
25032
- if (session.status !== "done" || exitCode !== 0) {
25033
- return false;
25034
- }
25035
- if (session.reviewStarted) {
25036
- return session.autoAdvance === true;
25037
- }
25038
- const args = session.assistArgs;
25039
- if (args === void 0) return false;
25040
- if (args[0] === "update") return true;
25041
- return args.includes("--once") && args[0] !== "next";
25042
- }
25043
-
25044
- // src/commands/sessions/daemon/shouldAutoRun.ts
25045
- function shouldAutoRun(session) {
25046
- if (!session.autoRun) return { run: false, reason: null };
25047
- if (session.status !== "done")
25048
- return {
25049
- run: false,
25050
- reason: `session status is "${session.status}", not "done"`
25051
- };
25052
- if (session.commandType !== "assist")
25053
- return {
25054
- run: false,
25055
- reason: `command type is "${session.commandType}", not "assist"`
25056
- };
25057
- const cmd = session.assistArgs?.[0];
25058
- if (cmd !== "draft" && cmd !== "bug" && cmd !== "refine")
25059
- return {
25060
- run: false,
25061
- reason: `command "${cmd ?? "(none)"}" is not draft/bug/refine`
25062
- };
25063
- const itemId2 = session.activity?.itemId;
25064
- if (itemId2 == null)
25065
- return {
25066
- run: false,
25067
- reason: "no itemId in activity (draft did not create an item)"
25068
- };
25069
- return { run: true, itemId: itemId2 };
25070
- }
25071
-
25072
- // src/commands/sessions/daemon/watchEscInterrupt.ts
25073
- var ESC3 = "\x1B";
25074
- var SETTLE_MS = 1e3;
25075
- function isInterruptKey(data) {
25076
- return data === ESC3;
25077
- }
25078
- function scheduleSettle(session, onStatusChange) {
25079
- if (session.escInterruptTimer) clearTimeout(session.escInterruptTimer);
25080
- session.escInterruptTimer = setTimeout(() => {
25081
- session.escInterruptTimer = void 0;
25082
- if (session.status !== "running") return;
25083
- daemonLog(`session ${session.id} esc-interrupt settled -> waiting`);
25084
- onStatusChange(session, "waiting");
25085
- }, SETTLE_MS);
25086
- }
25087
- function watchEscInterrupt(session, data, onStatusChange) {
25088
- if (session.status !== "running") return;
25089
- if (!isInterruptKey(data)) return;
25090
- scheduleSettle(session, onStatusChange);
25091
- }
25092
- function noteOutputForEscInterrupt(session, onStatusChange) {
25093
- if (!session.escInterruptTimer) return;
25094
- scheduleSettle(session, onStatusChange);
25095
- }
25096
- function disarmEscInterrupt(session) {
25097
- if (!session.escInterruptTimer) return;
25098
- clearTimeout(session.escInterruptTimer);
25099
- session.escInterruptTimer = void 0;
25100
- }
25101
-
25102
- // src/commands/sessions/daemon/applyStatusChange.ts
25103
- function applyStatusChange(session, status3, exitCode, dismiss, notify2, reuseForRun) {
25104
- disarmEscInterrupt(session);
25105
- if (session.status === status3) return;
25106
- daemonLog(`session ${session.id} status: ${session.status} -> ${status3}`);
25107
- void flushPhaseActiveMs(session);
25108
- setStatus2(session, status3);
25109
- const autoRun = shouldAutoRun(session);
25110
- if (autoRun.run) {
25111
- reuseForRun(session, autoRun.itemId);
25112
- notify2();
25113
- return;
25114
- }
25115
- if (status3 === "done" && autoRun.reason != null) {
25165
+ // src/commands/sessions/daemon/applySetStatus.ts
25166
+ function applySetStatus(sessions, id, status3, source, onStatusChange) {
25167
+ const session = sessions.get(id);
25168
+ if (!session) {
25116
25169
  daemonLog(
25117
- `session ${session.id} auto-run enabled but skipped (exit ${exitCode ?? "none"}): ${autoRun.reason}`
25170
+ `set-status for unknown session id=${id} status=${status3} (no live session; ignoring)`
25118
25171
  );
25172
+ return;
25119
25173
  }
25120
- if (shouldAutoDismiss(session, exitCode)) dismiss(session.id);
25121
- else notify2();
25122
- }
25123
-
25124
- // src/commands/sessions/daemon/makeStatusChangeHandler.ts
25125
- function makeStatusChangeHandler(dismiss, notify2, reuseForRun) {
25126
- return (s, status3, exitCode) => applyStatusChange(s, status3, exitCode, dismiss, notify2, reuseForRun);
25174
+ if (source === "permission") session.permissionActive = true;
25175
+ if (status3 === "running") session.permissionActive = false;
25176
+ onStatusChange(session, status3);
25127
25177
  }
25128
25178
 
25129
25179
  // src/shared/db/recordPhaseCycleContext.ts
@@ -25282,12 +25332,102 @@ function recordSessionUsage(sessions, claudeSessionId, transcriptPath, usedPct,
25282
25332
  return false;
25283
25333
  }
25284
25334
 
25335
+ // src/commands/sessions/daemon/applyUsageRecord.ts
25336
+ function applyUsageRecord(sessions, windows, notify2, claudeSessionId, transcriptPath, usedPct) {
25337
+ if (recordSessionUsage(
25338
+ sessions,
25339
+ claudeSessionId,
25340
+ transcriptPath,
25341
+ usedPct,
25342
+ windows
25343
+ ))
25344
+ notify2();
25345
+ }
25346
+
25347
+ // src/commands/sessions/daemon/setStatus.ts
25348
+ function setStatus2(session, newStatus) {
25349
+ const now = Date.now();
25350
+ if (session.status === "running" && session.runningSince != null) {
25351
+ session.runningMs += now - session.runningSince;
25352
+ }
25353
+ session.runningSince = newStatus === "running" ? now : null;
25354
+ session.status = newStatus;
25355
+ }
25356
+
25357
+ // src/commands/sessions/daemon/shouldAutoDismiss.ts
25358
+ function shouldAutoDismiss(session, exitCode) {
25359
+ if (session.status !== "done" || exitCode !== 0) {
25360
+ return false;
25361
+ }
25362
+ if (session.reviewStarted) {
25363
+ return session.autoAdvance === true;
25364
+ }
25365
+ const args = session.assistArgs;
25366
+ if (args === void 0) return false;
25367
+ if (args[0] === "update") return true;
25368
+ return args.includes("--once") && args[0] !== "next";
25369
+ }
25370
+
25371
+ // src/commands/sessions/daemon/shouldAutoRun.ts
25372
+ function shouldAutoRun(session) {
25373
+ if (!session.autoRun) return { run: false, reason: null };
25374
+ if (session.status !== "done")
25375
+ return {
25376
+ run: false,
25377
+ reason: `session status is "${session.status}", not "done"`
25378
+ };
25379
+ if (session.commandType !== "assist")
25380
+ return {
25381
+ run: false,
25382
+ reason: `command type is "${session.commandType}", not "assist"`
25383
+ };
25384
+ const cmd = session.assistArgs?.[0];
25385
+ if (cmd !== "draft" && cmd !== "bug" && cmd !== "refine")
25386
+ return {
25387
+ run: false,
25388
+ reason: `command "${cmd ?? "(none)"}" is not draft/bug/refine`
25389
+ };
25390
+ const itemId2 = session.activity?.itemId;
25391
+ if (itemId2 == null)
25392
+ return {
25393
+ run: false,
25394
+ reason: "no itemId in activity (draft did not create an item)"
25395
+ };
25396
+ return { run: true, itemId: itemId2 };
25397
+ }
25398
+
25399
+ // src/commands/sessions/daemon/applyStatusChange.ts
25400
+ function applyStatusChange(session, status3, exitCode, dismiss, notify2, reuseForRun) {
25401
+ if (session.status === status3) return;
25402
+ daemonLog(`session ${session.id} status: ${session.status} -> ${status3}`);
25403
+ void flushPhaseActiveMs(session);
25404
+ setStatus2(session, status3);
25405
+ const autoRun = shouldAutoRun(session);
25406
+ if (autoRun.run) {
25407
+ reuseForRun(session, autoRun.itemId);
25408
+ notify2();
25409
+ return;
25410
+ }
25411
+ if (status3 === "done" && autoRun.reason != null) {
25412
+ daemonLog(
25413
+ `session ${session.id} auto-run enabled but skipped (exit ${exitCode ?? "none"}): ${autoRun.reason}`
25414
+ );
25415
+ }
25416
+ if (shouldAutoDismiss(session, exitCode)) dismiss(session.id);
25417
+ else notify2();
25418
+ }
25419
+
25420
+ // src/commands/sessions/daemon/makeStatusChangeHandler.ts
25421
+ function makeStatusChangeHandler(dismiss, notify2, reuseForRun) {
25422
+ return (s, status3, exitCode) => applyStatusChange(s, status3, exitCode, dismiss, notify2, reuseForRun);
25423
+ }
25424
+
25285
25425
  // src/commands/sessions/daemon/errorTail.ts
25286
- var ESC4 = String.fromCharCode(27);
25426
+ var ESC3 = String.fromCharCode(27);
25287
25427
  var CSI = String.fromCharCode(155);
25288
25428
  var BEL = String.fromCharCode(7);
25289
25429
  var ANSI = new RegExp(
25290
- String.raw`[${ESC4}${CSI}][[\]()#;?]*(?:(?:[a-zA-Z\d]*(?:;[a-zA-Z\d]*)*)?${BEL}|(?:\d{1,4}(?:;\d{0,4})*)?[\dA-PR-TZcf-ntqry=><~])`,
25430
+ String.raw`[${ESC3}${CSI}][[\]()#;?]*(?:(?:[a-zA-Z\d]*(?:;[a-zA-Z\d]*)*)?${BEL}|(?:\d{1,4}(?:;\d{0,4})*)?[\dA-PR-TZcf-ntqry=><~])`,
25291
25431
  "g"
25292
25432
  );
25293
25433
  var MAX_TAIL_LINES = 40;
@@ -25355,10 +25495,10 @@ async function seedRunningMsFromUsage(session, notify2) {
25355
25495
 
25356
25496
  // src/commands/sessions/daemon/watchActivity.ts
25357
25497
  var DEBOUNCE_MS = 50;
25358
- function watchActivity(session, notify2) {
25498
+ function watchActivity(session, notify2, onClaudeSessionId) {
25359
25499
  if (session.commandType !== "assist" || !session.cwd) return;
25360
- const path70 = activityPath(session.id);
25361
- const dir = dirname29(path70);
25500
+ const path71 = activityPath(session.id);
25501
+ const dir = dirname29(path71);
25362
25502
  try {
25363
25503
  mkdirSync25(dir, { recursive: true });
25364
25504
  } catch {
@@ -25368,21 +25508,23 @@ function watchActivity(session, notify2) {
25368
25508
  let timer = null;
25369
25509
  const read = () => {
25370
25510
  timer = null;
25371
- const activity2 = readActivity(path70);
25511
+ const activity2 = readActivity(path71);
25372
25512
  if (!activity2) return;
25373
25513
  session.activity = activity2;
25374
- if (activity2.claudeSessionId)
25514
+ if (activity2.claudeSessionId) {
25375
25515
  session.claudeSessionId = activity2.claudeSessionId;
25516
+ onClaudeSessionId?.(session);
25517
+ }
25376
25518
  applyReviewPause(session, activity2);
25377
25519
  void seedRunningMsFromUsage(session, notify2);
25378
25520
  notify2();
25379
25521
  };
25380
25522
  session.activityWatcher = watch(dir, (_event, filename) => {
25381
- if (filename && !path70.endsWith(filename)) return;
25523
+ if (filename && !path71.endsWith(filename)) return;
25382
25524
  if (timer) clearTimeout(timer);
25383
25525
  timer = setTimeout(read, DEBOUNCE_MS);
25384
25526
  });
25385
- if (existsSync58(path70)) read();
25527
+ if (existsSync58(path71)) read();
25386
25528
  }
25387
25529
  function refreshActivity(session) {
25388
25530
  if (session.commandType !== "assist" || !session.cwd) return;
@@ -25445,7 +25587,6 @@ function wirePtyEvents(session, clients, onStatusChange) {
25445
25587
  if (!session.pty) return;
25446
25588
  session.pty.onData((data) => {
25447
25589
  appendScrollback(session, data);
25448
- noteOutputForEscInterrupt(session, onStatusChange);
25449
25590
  broadcast(clients, { type: "output", sessionId: session.id, data });
25450
25591
  });
25451
25592
  session.pty.onExit(
@@ -25613,6 +25754,222 @@ function errorSession(id, persisted, error) {
25613
25754
  };
25614
25755
  }
25615
25756
 
25757
+ // src/commands/sessions/shared/normalizeUser.ts
25758
+ var INTERRUPT_PREFIX = "[Request interrupted";
25759
+ function normalizeUser(entry) {
25760
+ const content = asRecord(entry.message)?.content;
25761
+ if (typeof content === "string")
25762
+ return isInterruptText(content) ? { kind: "interrupt" } : { kind: "user" };
25763
+ if (!Array.isArray(content)) return { kind: "user" };
25764
+ const toolResultIds = [];
25765
+ let hasInterrupt = false;
25766
+ let hasNonToolResult = false;
25767
+ for (const block of content) {
25768
+ const b = asRecord(block);
25769
+ if (!b) continue;
25770
+ if (b.type === "tool_result") {
25771
+ if (typeof b.tool_use_id === "string") toolResultIds.push(b.tool_use_id);
25772
+ } else if (b.type === "text" && isInterruptText(b.text)) {
25773
+ hasInterrupt = true;
25774
+ } else {
25775
+ hasNonToolResult = true;
25776
+ }
25777
+ }
25778
+ if (hasInterrupt) return { kind: "interrupt" };
25779
+ if (hasNonToolResult) return { kind: "user" };
25780
+ return { kind: "toolResult", ids: toolResultIds };
25781
+ }
25782
+ function asRecord(value) {
25783
+ return value && typeof value === "object" ? value : null;
25784
+ }
25785
+ function isInterruptText(value) {
25786
+ return typeof value === "string" && value.startsWith(INTERRUPT_PREFIX);
25787
+ }
25788
+
25789
+ // src/commands/sessions/shared/normalizeTranscriptEvents.ts
25790
+ function normalizeTranscriptEvents(entries) {
25791
+ return entries.map(normalizeEntry).filter((event) => event !== null);
25792
+ }
25793
+ function normalizeEntry(entry) {
25794
+ if (entry.isSidechain || entry.isMeta) return null;
25795
+ if (entry.type === "assistant") return normalizeAssistant(entry);
25796
+ if (entry.type === "user") return normalizeUser(entry);
25797
+ return null;
25798
+ }
25799
+ function normalizeAssistant(entry) {
25800
+ const message = asRecord2(entry.message);
25801
+ const stopReason = typeof message?.stop_reason === "string" ? message.stop_reason : null;
25802
+ const content = message?.content;
25803
+ const toolUses = [];
25804
+ if (Array.isArray(content))
25805
+ for (const block of content) {
25806
+ const b = asRecord2(block);
25807
+ if (b?.type === "tool_use")
25808
+ toolUses.push({
25809
+ id: typeof b.id === "string" ? b.id : "",
25810
+ name: typeof b.name === "string" ? b.name : ""
25811
+ });
25812
+ }
25813
+ return { kind: "assistant", stopReason, toolUses };
25814
+ }
25815
+ function asRecord2(value) {
25816
+ return value && typeof value === "object" ? value : null;
25817
+ }
25818
+
25819
+ // src/commands/sessions/shared/deriveTranscriptStatus.ts
25820
+ var ASK_USER_QUESTION2 = "AskUserQuestion";
25821
+ var TURN_END_STOP_REASONS = /* @__PURE__ */ new Set(["end_turn", "stop_sequence"]);
25822
+ function deriveTranscriptStatus(entries, opts = {}) {
25823
+ const events = normalizeTranscriptEvents(entries);
25824
+ const lastIdx = lastDecisiveIndex(events);
25825
+ if (lastIdx === -1) return null;
25826
+ const ev = events[lastIdx];
25827
+ if (ev.kind === "interrupt") return "waiting";
25828
+ if (ev.kind === "user") return "running";
25829
+ if (ev.kind === "toolResult") return null;
25830
+ if (ev.stopReason != null && TURN_END_STOP_REASONS.has(ev.stopReason))
25831
+ return "waiting";
25832
+ const resolved = resolvedToolUseIds(events, lastIdx);
25833
+ const pending = ev.toolUses.filter((tool) => !resolved.has(tool.id));
25834
+ if (pending.length === 0) return "running";
25835
+ if (pending.some((tool) => tool.name === ASK_USER_QUESTION2))
25836
+ return "waiting";
25837
+ if (opts.permissionActive) return "waiting";
25838
+ return "running";
25839
+ }
25840
+ function lastDecisiveIndex(events) {
25841
+ for (let i = events.length - 1; i >= 0; i--)
25842
+ if (events[i].kind !== "toolResult") return i;
25843
+ return -1;
25844
+ }
25845
+ function resolvedToolUseIds(events, afterIdx) {
25846
+ const ids = /* @__PURE__ */ new Set();
25847
+ for (let i = afterIdx + 1; i < events.length; i++) {
25848
+ const event = events[i];
25849
+ if (event.kind === "toolResult") for (const id of event.ids) ids.add(id);
25850
+ }
25851
+ return ids;
25852
+ }
25853
+
25854
+ // src/commands/sessions/shared/readTranscriptTail.ts
25855
+ import * as fs37 from "fs";
25856
+ var DEFAULT_MAX_BYTES = 256 * 1024;
25857
+ function parseTailEntries(raw) {
25858
+ const entries = [];
25859
+ for (const line of raw.split("\n")) {
25860
+ const trimmed = line.trim();
25861
+ if (!trimmed) continue;
25862
+ try {
25863
+ const parsed = JSON.parse(trimmed);
25864
+ if (parsed && typeof parsed === "object")
25865
+ entries.push(parsed);
25866
+ } catch {
25867
+ }
25868
+ }
25869
+ return entries;
25870
+ }
25871
+ function dropPartialFirstLine(raw, sliced) {
25872
+ if (!sliced) return raw;
25873
+ const newline = raw.indexOf("\n");
25874
+ return newline === -1 ? "" : raw.slice(newline + 1);
25875
+ }
25876
+ async function readTranscriptTail(filePath, maxBytes = DEFAULT_MAX_BYTES) {
25877
+ let handle;
25878
+ try {
25879
+ handle = await fs37.promises.open(filePath, "r");
25880
+ const { size } = await handle.stat();
25881
+ const start3 = Math.max(0, size - maxBytes);
25882
+ const length = size - start3;
25883
+ if (length === 0) return [];
25884
+ const buf = Buffer.alloc(length);
25885
+ await handle.read(buf, 0, length, start3);
25886
+ return parseTailEntries(
25887
+ dropPartialFirstLine(buf.toString("utf8"), start3 > 0)
25888
+ );
25889
+ } catch {
25890
+ return [];
25891
+ } finally {
25892
+ await handle?.close();
25893
+ }
25894
+ }
25895
+ function readTranscriptTailSync(filePath, maxBytes = DEFAULT_MAX_BYTES) {
25896
+ let fd;
25897
+ try {
25898
+ fd = fs37.openSync(filePath, "r");
25899
+ const { size } = fs37.fstatSync(fd);
25900
+ const start3 = Math.max(0, size - maxBytes);
25901
+ const length = size - start3;
25902
+ if (length === 0) return [];
25903
+ const buf = Buffer.alloc(length);
25904
+ fs37.readSync(fd, buf, 0, length, start3);
25905
+ return parseTailEntries(
25906
+ dropPartialFirstLine(buf.toString("utf8"), start3 > 0)
25907
+ );
25908
+ } catch {
25909
+ return [];
25910
+ } finally {
25911
+ if (fd !== void 0) fs37.closeSync(fd);
25912
+ }
25913
+ }
25914
+
25915
+ // src/commands/sessions/shared/findTranscriptPathSync.ts
25916
+ import * as fs38 from "fs";
25917
+ import * as os4 from "os";
25918
+ import * as path60 from "path";
25919
+ function projectDirForCwd(cwd) {
25920
+ return path60.join(
25921
+ os4.homedir(),
25922
+ ".claude",
25923
+ "projects",
25924
+ cwd.replace(/[^a-zA-Z0-9]/g, "-")
25925
+ );
25926
+ }
25927
+ function transcriptPathFor(cwd, claudeSessionId) {
25928
+ return path60.join(projectDirForCwd(cwd), `${claudeSessionId}.jsonl`);
25929
+ }
25930
+ function findTranscriptPathSync(cwd, claudeSessionId) {
25931
+ const direct = transcriptPathFor(cwd, claudeSessionId);
25932
+ if (fs38.existsSync(direct)) return direct;
25933
+ const dir = projectDirForCwd(cwd);
25934
+ let files;
25935
+ try {
25936
+ files = fs38.readdirSync(dir);
25937
+ } catch {
25938
+ return null;
25939
+ }
25940
+ for (const file of files) {
25941
+ if (!file.endsWith(".jsonl")) continue;
25942
+ if (headContainsSessionId(path60.join(dir, file), claudeSessionId))
25943
+ return path60.join(dir, file);
25944
+ }
25945
+ return null;
25946
+ }
25947
+ function headContainsSessionId(filePath, claudeSessionId) {
25948
+ let fd;
25949
+ try {
25950
+ fd = fs38.openSync(filePath, "r");
25951
+ const buf = Buffer.alloc(16384);
25952
+ const bytesRead = fs38.readSync(fd, buf, 0, buf.length, 0);
25953
+ return buf.toString("utf8", 0, bytesRead).includes(claudeSessionId);
25954
+ } catch {
25955
+ return false;
25956
+ } finally {
25957
+ if (fd !== void 0) fs38.closeSync(fd);
25958
+ }
25959
+ }
25960
+
25961
+ // src/commands/sessions/daemon/deriveRestoreStatus.ts
25962
+ function deriveRestoreStatus(persisted) {
25963
+ if (!persisted.claudeSessionId) return "waiting";
25964
+ const filePath = findTranscriptPathSync(
25965
+ persisted.cwd,
25966
+ persisted.claudeSessionId
25967
+ );
25968
+ if (!filePath) return "waiting";
25969
+ const entries = readTranscriptTailSync(filePath);
25970
+ return deriveTranscriptStatus(entries) === "running" ? "running" : "waiting";
25971
+ }
25972
+
25616
25973
  // src/commands/sessions/daemon/runningSession.ts
25617
25974
  function runningSession(base, persisted, pty2) {
25618
25975
  return restoredSession(base, persisted, pty2, "running");
@@ -25636,17 +25993,16 @@ function restoredSession(base, persisted, pty2, status3) {
25636
25993
  }
25637
25994
 
25638
25995
  // src/commands/sessions/daemon/restoreInteractiveSession.ts
25639
- function restoreInteractiveSession(id, persisted, base) {
25996
+ function restoreInteractiveSession(id, persisted, base, idle) {
25640
25997
  if (persisted.commandType !== "run" && persisted.claudeSessionId) {
25641
- return resumeViaClaude(id, persisted, base);
25998
+ return resumeViaClaude(id, persisted, base, idle);
25642
25999
  }
25643
26000
  if (persisted.commandType === "claude") {
25644
26001
  return unrecoverableClaude(id, persisted);
25645
26002
  }
25646
26003
  return notRestoredStub(base, persisted);
25647
26004
  }
25648
- function resumeViaClaude(id, persisted, base) {
25649
- const idle = persisted.status !== "running";
26005
+ function resumeViaClaude(id, persisted, base, idle) {
25650
26006
  const pty2 = spawnClaude2({
25651
26007
  resumeSessionId: persisted.claudeSessionId,
25652
26008
  prompt: idle ? void 0 : buildResumePrompt(),
@@ -25695,8 +26051,8 @@ function isUpdate(persisted) {
25695
26051
  function restoreSession(id, persisted) {
25696
26052
  const base = restoreBase(id, persisted);
25697
26053
  if (isUpdate(persisted)) return updatedSession(id, persisted);
26054
+ const idle = deriveRestoreStatus(persisted) !== "running";
25698
26055
  if (needsWrapperRelaunch(persisted)) {
25699
- const idle = persisted.status !== "running";
25700
26056
  const pty2 = spawnPty(
25701
26057
  assistResumeArgs(persisted),
25702
26058
  persisted.cwd,
@@ -25705,7 +26061,7 @@ function restoreSession(id, persisted) {
25705
26061
  );
25706
26062
  return idle ? waitingSession(base, persisted, pty2) : runningSession(base, persisted, pty2);
25707
26063
  }
25708
- return restoreInteractiveSession(id, persisted, base);
26064
+ return restoreInteractiveSession(id, persisted, base, idle);
25709
26065
  }
25710
26066
  function needsWrapperRelaunch(persisted) {
25711
26067
  return isBacklogRun(persisted) || isOnceLaunch(persisted) && !!persisted.claudeSessionId;
@@ -25846,6 +26202,77 @@ function shutdownSessions(sessions) {
25846
26202
  }
25847
26203
  }
25848
26204
 
26205
+ // src/commands/sessions/daemon/watchTranscript.ts
26206
+ import { existsSync as existsSync60, watch as watch2 } from "fs";
26207
+
26208
+ // src/commands/sessions/daemon/reconcileTranscriptStatus.ts
26209
+ async function resolveTranscriptPath(session) {
26210
+ if (session.transcriptPath) return session.transcriptPath;
26211
+ if (!session.claudeSessionId) return null;
26212
+ const direct = session.cwd ? findTranscriptPathSync(session.cwd, session.claudeSessionId) : null;
26213
+ const filePath = direct ?? await findSessionJsonlPath(session.claudeSessionId);
26214
+ if (filePath) session.transcriptPath = filePath;
26215
+ return filePath;
26216
+ }
26217
+ async function reconcileTranscriptStatus(session, onStatusChange) {
26218
+ if (session.status === "done" || session.status === "error") return;
26219
+ const filePath = await resolveTranscriptPath(session);
26220
+ if (!filePath) return;
26221
+ const entries = await readTranscriptTail(filePath);
26222
+ const derived = deriveTranscriptStatus(entries, {
26223
+ permissionActive: session.permissionActive
26224
+ });
26225
+ if (!derived) return;
26226
+ if (derived === "running") session.permissionActive = false;
26227
+ if (derived === session.status) return;
26228
+ daemonLog(
26229
+ `session ${session.id} transcript reconcile: ${session.status} -> ${derived}`
26230
+ );
26231
+ onStatusChange(session, derived);
26232
+ }
26233
+
26234
+ // src/commands/sessions/daemon/watchTranscript.ts
26235
+ var DEBOUNCE_MS2 = 100;
26236
+ function watchTranscript(session, onStatusChange) {
26237
+ if (!session.cwd || !session.claudeSessionId) return;
26238
+ if (session.watchedTranscriptId === session.claudeSessionId) return;
26239
+ const dir = projectDirForCwd(session.cwd);
26240
+ if (!existsSync60(dir)) return;
26241
+ if (session.transcriptWatcher) {
26242
+ session.transcriptWatcher.close();
26243
+ session.transcriptWatcher = void 0;
26244
+ }
26245
+ session.transcriptPath = void 0;
26246
+ const fileName = `${session.claudeSessionId}.jsonl`;
26247
+ let timer = null;
26248
+ const run4 = () => {
26249
+ timer = null;
26250
+ void reconcileTranscriptStatus(session, onStatusChange);
26251
+ };
26252
+ try {
26253
+ session.transcriptWatcher = watch2(dir, (_event, changed) => {
26254
+ if (changed && changed !== fileName) return;
26255
+ if (timer) clearTimeout(timer);
26256
+ timer = setTimeout(run4, DEBOUNCE_MS2);
26257
+ });
26258
+ } catch (error) {
26259
+ daemonLog(
26260
+ `session ${session.id} transcript watch failed: ${error instanceof Error ? error.message : String(error)}`
26261
+ );
26262
+ return;
26263
+ }
26264
+ session.watchedTranscriptId = session.claudeSessionId;
26265
+ daemonLog(`session ${session.id} watching transcript ${fileName}`);
26266
+ run4();
26267
+ }
26268
+
26269
+ // src/commands/sessions/daemon/wireSessionWatchers.ts
26270
+ function wireSessionWatchers(session, notify2, onStatusChange) {
26271
+ const wireTranscript = (s) => watchTranscript(s, onStatusChange);
26272
+ watchActivity(session, notify2, wireTranscript);
26273
+ wireTranscript(session);
26274
+ }
26275
+
25849
26276
  // src/commands/sessions/daemon/connectToWindowsDaemon.ts
25850
26277
  import * as net2 from "net";
25851
26278
 
@@ -25961,13 +26388,13 @@ async function defaultConnect() {
25961
26388
  }
25962
26389
 
25963
26390
  // src/commands/sessions/daemon/hasPersistedWindowsSessions.ts
25964
- import { existsSync as existsSync59, readFileSync as readFileSync49 } from "fs";
26391
+ import { existsSync as existsSync61, readFileSync as readFileSync49 } from "fs";
25965
26392
  import { posix } from "path";
25966
26393
  function hasPersistedWindowsSessions() {
25967
26394
  const sessionsFile = windowsSessionsFileFromWsl();
25968
26395
  if (!sessionsFile) return false;
25969
26396
  try {
25970
- if (!existsSync59(sessionsFile)) return false;
26397
+ if (!existsSync61(sessionsFile)) return false;
25971
26398
  const data = JSON.parse(readFileSync49(sessionsFile, "utf8"));
25972
26399
  return Array.isArray(data) && data.length > 0;
25973
26400
  } catch (error) {
@@ -26528,7 +26955,6 @@ function writeToSession(sessions, id, data, onStatusChange) {
26528
26955
  const s = sessions.get(id);
26529
26956
  if (!s || s.status === "done") return;
26530
26957
  s.pty?.write(data);
26531
- watchEscInterrupt(s, data, onStatusChange);
26532
26958
  watchPromptSubmit(s, data, onStatusChange);
26533
26959
  }
26534
26960
  function resizeSession(sessions, id, cols, rows) {
@@ -26608,7 +27034,7 @@ var SessionManager = class {
26608
27034
  drain = () => drainSessions(this.sessions, this.notify);
26609
27035
  add(session) {
26610
27036
  this.wire(session);
26611
- watchActivity(session, this.notify);
27037
+ wireSessionWatchers(session, this.notify, this.onStatusChange);
26612
27038
  logSpawnedSession(session);
26613
27039
  return session.id;
26614
27040
  }
@@ -26671,27 +27097,20 @@ var SessionManager = class {
26671
27097
  setStarred(id, starred) {
26672
27098
  if (setStarred2(this.sessions, id, starred)) this.notify();
26673
27099
  }
26674
- setStatus(id, status3) {
26675
- const session = this.sessions.get(id);
26676
- if (!session) {
26677
- daemonLog(
26678
- `set-status for unknown session id=${id} status=${status3} (no live session; ignoring)`
26679
- );
26680
- return;
26681
- }
26682
- this.onStatusChange(session, status3);
27100
+ setStatus(id, status3, source) {
27101
+ applySetStatus(this.sessions, id, status3, source, this.onStatusChange);
26683
27102
  }
26684
27103
  /* why: the status line relays token totals keyed by Claude's session id; join
26685
27104
  * it to the running backlog phase so the spend accumulates against that row. */
26686
27105
  recordUsage(claudeSessionId, transcriptPath, usedPct) {
26687
- if (recordSessionUsage(
27106
+ applyUsageRecord(
26688
27107
  this.sessions.values(),
27108
+ this.clients.currentWindows(),
27109
+ this.notify,
26689
27110
  claudeSessionId,
26690
27111
  transcriptPath,
26691
- usedPct,
26692
- this.clients.currentWindows()
26693
- ))
26694
- this.notify();
27112
+ usedPct
27113
+ );
26695
27114
  }
26696
27115
  listSessions = () => {
26697
27116
  const local = [...this.sessions.values()].map(toSessionInfo);
@@ -26712,8 +27131,30 @@ import * as net3 from "net";
26712
27131
  // src/commands/sessions/daemon/handleConnection.ts
26713
27132
  import { createInterface as createInterface9 } from "readline";
26714
27133
 
27134
+ // src/commands/sessions/daemon/creator.ts
27135
+ function creator(isNew, spawn12) {
27136
+ return (client, m, d) => {
27137
+ if (m.windowsProxy.route(client, d)) return;
27138
+ sendTo(client, { type: "created", sessionId: spawn12(m, d), isNew });
27139
+ };
27140
+ }
27141
+
27142
+ // src/commands/sessions/daemon/handleSetStatus.ts
27143
+ function handleSetStatus(client, m, d) {
27144
+ daemonLog(
27145
+ `set-status received: id=${d.sessionId} status=${d.status}${d.source ? ` source=${d.source}` : ""}`
27146
+ );
27147
+ if (m.windowsProxy.route(client, d)) return;
27148
+ m.setStatus(
27149
+ d.sessionId,
27150
+ d.status,
27151
+ d.source
27152
+ );
27153
+ if (d.ack) sendTo(client, { type: "ack", sessionId: d.sessionId });
27154
+ }
27155
+
26715
27156
  // src/commands/sessions/shared/parseTranscript.ts
26716
- import * as fs37 from "fs";
27157
+ import * as fs39 from "fs";
26717
27158
 
26718
27159
  // src/commands/sessions/shared/toolTarget.ts
26719
27160
  function toolTarget(input) {
@@ -26765,7 +27206,7 @@ async function parseTranscript(sessionId) {
26765
27206
  const filePath = await findSessionJsonlPath(sessionId);
26766
27207
  if (!filePath) return [];
26767
27208
  try {
26768
- const raw = await fs37.promises.readFile(filePath, "utf8");
27209
+ const raw = await fs39.promises.readFile(filePath, "utf8");
26769
27210
  return parseTranscriptLines(raw.split("\n"));
26770
27211
  } catch {
26771
27212
  return [];
@@ -26829,12 +27270,6 @@ function spawnCreate(m, d) {
26829
27270
  }
26830
27271
 
26831
27272
  // src/commands/sessions/daemon/messageHandlers.ts
26832
- function creator(isNew, spawn12) {
26833
- return (client, m, d) => {
26834
- if (m.windowsProxy.route(client, d)) return;
26835
- sendTo(client, { type: "created", sessionId: spawn12(m, d), isNew });
26836
- };
26837
- }
26838
27273
  function routed(local) {
26839
27274
  return (client, m, d) => {
26840
27275
  if (!m.windowsProxy.route(client, d)) local(client, m, d);
@@ -26903,11 +27338,7 @@ var messageHandlers = {
26903
27338
  (_client, m, d) => m.setStarred(d.sessionId, d.starred)
26904
27339
  ),
26905
27340
  "set-active": (_client, m, d) => m.active.set(d.cwd, d.sessionId),
26906
- "set-status": (client, m, d) => {
26907
- daemonLog(`set-status received: id=${d.sessionId} status=${d.status}`);
26908
- if (!m.windowsProxy.route(client, d))
26909
- m.setStatus(d.sessionId, d.status);
26910
- },
27341
+ "set-status": handleSetStatus,
26911
27342
  "ui-status": (_client, _m, d) => daemonLog(`ui rendered: id=${d.sessionId} status=${d.status}`)
26912
27343
  };
26913
27344
 
@@ -27093,18 +27524,33 @@ function registerDaemon(program2) {
27093
27524
  ).action(drainDaemon);
27094
27525
  }
27095
27526
 
27527
+ // src/commands/sessions/registerSetStatusCommand.ts
27528
+ function registerSetStatusCommand(cmd) {
27529
+ cmd.command("set-status <status>").description(
27530
+ "Report the current session's status to the sessions daemon (used by Claude Code hooks)"
27531
+ ).option(
27532
+ "--source <source>",
27533
+ "Originating hook (permission, stop, notification, prompt, pretool, posttool)"
27534
+ ).option(
27535
+ "--ack",
27536
+ "Wait for the daemon to acknowledge delivery, retrying on failure"
27537
+ ).action(
27538
+ (status3, options2) => setSessionStatus(status3, { source: options2.source, ack: options2.ack })
27539
+ );
27540
+ }
27541
+
27096
27542
  // src/commands/sessions/summarise/index.ts
27097
- import * as fs39 from "fs";
27098
- import chalk200 from "chalk";
27543
+ import * as fs41 from "fs";
27544
+ import chalk201 from "chalk";
27099
27545
 
27100
27546
  // src/commands/sessions/summarise/shared.ts
27101
- import * as fs38 from "fs";
27547
+ import * as fs40 from "fs";
27102
27548
  function writeSummary(jsonlPath2, summary) {
27103
- fs38.writeFileSync(summaryPathFor(jsonlPath2), `${summary.trim()}
27549
+ fs40.writeFileSync(summaryPathFor(jsonlPath2), `${summary.trim()}
27104
27550
  `, "utf8");
27105
27551
  }
27106
27552
  function hasSummary(jsonlPath2) {
27107
- return fs38.existsSync(summaryPathFor(jsonlPath2));
27553
+ return fs40.existsSync(summaryPathFor(jsonlPath2));
27108
27554
  }
27109
27555
  function summaryPathFor(jsonlPath2) {
27110
27556
  return jsonlPath2.replace(/\.jsonl$/, ".summary");
@@ -27169,29 +27615,29 @@ ${firstMessage}`);
27169
27615
  async function summarise2(options2) {
27170
27616
  const files = await discoverSessionFiles();
27171
27617
  if (files.length === 0) {
27172
- console.log(chalk200.yellow("No sessions found."));
27618
+ console.log(chalk201.yellow("No sessions found."));
27173
27619
  return;
27174
27620
  }
27175
27621
  const toProcess = selectCandidates(files, options2);
27176
27622
  if (toProcess.length === 0) {
27177
- console.log(chalk200.green("All sessions already summarised."));
27623
+ console.log(chalk201.green("All sessions already summarised."));
27178
27624
  return;
27179
27625
  }
27180
27626
  console.log(
27181
- chalk200.cyan(
27627
+ chalk201.cyan(
27182
27628
  `Summarising ${toProcess.length} session(s) (${files.length} total)\u2026`
27183
27629
  )
27184
27630
  );
27185
27631
  const { succeeded, failed: failed2 } = processSessions(toProcess);
27186
27632
  console.log(
27187
- chalk200.green(`Done: ${succeeded} summarised`) + (failed2 > 0 ? chalk200.yellow(`, ${failed2} skipped`) : "")
27633
+ chalk201.green(`Done: ${succeeded} summarised`) + (failed2 > 0 ? chalk201.yellow(`, ${failed2} skipped`) : "")
27188
27634
  );
27189
27635
  }
27190
27636
  function selectCandidates(files, options2) {
27191
27637
  const candidates = options2.force ? files : files.filter((f) => !hasSummary(f));
27192
27638
  candidates.sort((a, b) => {
27193
27639
  try {
27194
- return fs39.statSync(b).mtimeMs - fs39.statSync(a).mtimeMs;
27640
+ return fs41.statSync(b).mtimeMs - fs41.statSync(a).mtimeMs;
27195
27641
  } catch {
27196
27642
  return 0;
27197
27643
  }
@@ -27204,16 +27650,16 @@ function processSessions(files) {
27204
27650
  let failed2 = 0;
27205
27651
  for (let i = 0; i < files.length; i++) {
27206
27652
  const file = files[i];
27207
- process.stdout.write(chalk200.dim(` [${i + 1}/${files.length}] `));
27653
+ process.stdout.write(chalk201.dim(` [${i + 1}/${files.length}] `));
27208
27654
  const summary = summariseSession(file);
27209
27655
  if (summary) {
27210
27656
  writeSummary(file, summary);
27211
27657
  succeeded++;
27212
- process.stdout.write(`${chalk200.green("\u2713")} ${summary}
27658
+ process.stdout.write(`${chalk201.green("\u2713")} ${summary}
27213
27659
  `);
27214
27660
  } else {
27215
27661
  failed2++;
27216
- process.stdout.write(` ${chalk200.yellow("skip")}
27662
+ process.stdout.write(` ${chalk201.yellow("skip")}
27217
27663
  `);
27218
27664
  }
27219
27665
  }
@@ -27229,9 +27675,7 @@ function registerSessions(program2) {
27229
27675
  (options2, command) => web({ ...options2, open: command.optsWithGlobals().open })
27230
27676
  );
27231
27677
  cmd.command("summarise").description("Generate one-line summaries for Claude sessions").option("-f, --force", "Re-generate all summaries, even existing ones").option("-n, --limit <count>", "Maximum number of sessions to summarise").action(summarise2);
27232
- cmd.command("set-status <status>").description(
27233
- "Report the current session's status to the sessions daemon (used by Claude Code hooks)"
27234
- ).action(setSessionStatus);
27678
+ registerSetStatusCommand(cmd);
27235
27679
  configHelp(cmd, [
27236
27680
  {
27237
27681
  key: "sessions.windowsProjectsRoot",
@@ -27257,7 +27701,7 @@ function registerSessions(program2) {
27257
27701
  }
27258
27702
 
27259
27703
  // src/commands/statusLine.ts
27260
- import chalk202 from "chalk";
27704
+ import chalk203 from "chalk";
27261
27705
 
27262
27706
  // src/shared/contextLevel.ts
27263
27707
  function contextLevel(pct) {
@@ -27267,7 +27711,7 @@ function contextLevel(pct) {
27267
27711
  }
27268
27712
 
27269
27713
  // src/commands/buildLimitsSegment.ts
27270
- import chalk201 from "chalk";
27714
+ import chalk202 from "chalk";
27271
27715
 
27272
27716
  // src/shared/rateLimitLevel.ts
27273
27717
  var FIVE_HOUR_SECONDS = 5 * 3600;
@@ -27298,9 +27742,9 @@ function rateLimitLevel(pct, resetsAt, windowSeconds, now) {
27298
27742
 
27299
27743
  // src/commands/buildLimitsSegment.ts
27300
27744
  var LEVEL_COLOR = {
27301
- ok: chalk201.green,
27302
- warn: chalk201.yellow,
27303
- over: chalk201.red
27745
+ ok: chalk202.green,
27746
+ warn: chalk202.yellow,
27747
+ over: chalk202.red
27304
27748
  };
27305
27749
  function formatLimit(pct, resetsAt, windowSeconds, fallbackLabel, now) {
27306
27750
  const level = rateLimitLevel(pct, resetsAt, windowSeconds, now);
@@ -27332,9 +27776,9 @@ function buildLimitsSegment(rateLimits) {
27332
27776
 
27333
27777
  // src/commands/readGitBranch.ts
27334
27778
  import { readFileSync as readFileSync52, statSync as statSync11 } from "fs";
27335
- import { isAbsolute as isAbsolute2, join as join68, resolve as resolve17 } from "path";
27779
+ import { isAbsolute as isAbsolute2, join as join69, resolve as resolve17 } from "path";
27336
27780
  function resolveGitDir(cwd) {
27337
- const dotGit = join68(cwd, ".git");
27781
+ const dotGit = join69(cwd, ".git");
27338
27782
  let stat2;
27339
27783
  try {
27340
27784
  stat2 = statSync11(dotGit);
@@ -27364,7 +27808,7 @@ function readGitBranch(cwd) {
27364
27808
  }
27365
27809
  let head;
27366
27810
  try {
27367
- head = readFileSync52(join68(gitDir, "HEAD"), "utf8");
27811
+ head = readFileSync52(join69(gitDir, "HEAD"), "utf8");
27368
27812
  } catch {
27369
27813
  return null;
27370
27814
  }
@@ -27396,7 +27840,7 @@ async function relayUsage(claudeSessionId, transcriptPath, usedPct) {
27396
27840
  }
27397
27841
 
27398
27842
  // src/commands/statusLine.ts
27399
- chalk202.level = 3;
27843
+ chalk203.level = 3;
27400
27844
  function formatNumber(num) {
27401
27845
  return num.toLocaleString("en-US");
27402
27846
  }
@@ -27404,9 +27848,9 @@ function colorizePercent(pct) {
27404
27848
  const label2 = `${Math.round(pct)}%`;
27405
27849
  switch (contextLevel(pct)) {
27406
27850
  case "red":
27407
- return chalk202.red(label2);
27851
+ return chalk203.red(label2);
27408
27852
  case "yellow":
27409
- return chalk202.yellow(label2);
27853
+ return chalk203.yellow(label2);
27410
27854
  default:
27411
27855
  return label2;
27412
27856
  }
@@ -27419,7 +27863,7 @@ async function statusLine() {
27419
27863
  const usedPct = data.context_window.used_percentage ?? 0;
27420
27864
  const dir = data.workspace?.current_dir ?? data.cwd;
27421
27865
  const branch2 = dir ? readGitBranch(toGitCwd(dir)) : null;
27422
- const branchSegment = branch2 ? `\u{1F33F}\uFE0F ${chalk202.cyan(branch2)} | ` : "";
27866
+ const branchSegment = branch2 ? `\u{1F33F}\uFE0F ${chalk203.cyan(branch2)} | ` : "";
27423
27867
  console.log(
27424
27868
  `${branchSegment}${model} | Tokens - ${formatNumber(totalIn)} \u2191 : ${formatNumber(totalOut)} \u2193 | Context - ${colorizePercent(usedPct)}${buildLimitsSegment(data.rate_limits)}`
27425
27869
  );
@@ -27432,29 +27876,29 @@ async function statusLine() {
27432
27876
  }
27433
27877
 
27434
27878
  // src/commands/sync.ts
27435
- import * as fs46 from "fs";
27436
- import * as os4 from "os";
27437
- import * as path68 from "path";
27879
+ import * as fs48 from "fs";
27880
+ import * as os5 from "os";
27881
+ import * as path69 from "path";
27438
27882
  import { fileURLToPath as fileURLToPath9 } from "url";
27439
27883
 
27440
27884
  // src/commands/sync/syncClaudeMd.ts
27441
- import * as fs40 from "fs";
27442
- import * as path60 from "path";
27443
- import chalk203 from "chalk";
27885
+ import * as fs42 from "fs";
27886
+ import * as path61 from "path";
27887
+ import chalk204 from "chalk";
27444
27888
  async function syncClaudeMd(claudeDir, targetBase, options2) {
27445
- const source = path60.join(claudeDir, "CLAUDE.md");
27446
- const target = path60.join(targetBase, "CLAUDE.md");
27447
- const sourceContent = fs40.readFileSync(source, "utf8");
27448
- if (fs40.existsSync(target)) {
27449
- const targetContent = fs40.readFileSync(target, "utf8");
27889
+ const source = path61.join(claudeDir, "CLAUDE.md");
27890
+ const target = path61.join(targetBase, "CLAUDE.md");
27891
+ const sourceContent = fs42.readFileSync(source, "utf8");
27892
+ if (fs42.existsSync(target)) {
27893
+ const targetContent = fs42.readFileSync(target, "utf8");
27450
27894
  if (sourceContent !== targetContent) {
27451
27895
  console.log(
27452
- chalk203.yellow("\n\u26A0\uFE0F Warning: CLAUDE.md differs from existing file")
27896
+ chalk204.yellow("\n\u26A0\uFE0F Warning: CLAUDE.md differs from existing file")
27453
27897
  );
27454
27898
  console.log();
27455
27899
  printDiff(targetContent, sourceContent);
27456
27900
  const confirm = options2?.yes || await promptConfirm(
27457
- chalk203.red("Overwrite existing CLAUDE.md?"),
27901
+ chalk204.red("Overwrite existing CLAUDE.md?"),
27458
27902
  false
27459
27903
  );
27460
27904
  if (!confirm) {
@@ -27463,38 +27907,38 @@ async function syncClaudeMd(claudeDir, targetBase, options2) {
27463
27907
  }
27464
27908
  }
27465
27909
  }
27466
- fs40.copyFileSync(source, target);
27910
+ fs42.copyFileSync(source, target);
27467
27911
  console.log("Copied CLAUDE.md to ~/.claude/CLAUDE.md");
27468
27912
  }
27469
27913
 
27470
27914
  // src/commands/sync/syncCodex.ts
27471
- import * as path63 from "path";
27915
+ import * as path64 from "path";
27472
27916
 
27473
27917
  // src/commands/sync/installHarnessCommands.ts
27474
- import * as fs41 from "fs";
27475
- import * as path61 from "path";
27918
+ import * as fs43 from "fs";
27919
+ import * as path62 from "path";
27476
27920
  function installHarnessCommands(claudeDir, harness, transform) {
27477
- const commandsSource = path61.join(claudeDir, "commands");
27478
- const files = fs41.readdirSync(commandsSource);
27921
+ const commandsSource = path62.join(claudeDir, "commands");
27922
+ const files = fs43.readdirSync(commandsSource);
27479
27923
  let synced = 0;
27480
27924
  for (const file of files) {
27481
27925
  if (!file.endsWith(".md")) continue;
27482
27926
  const name = file.replace(/\.md$/, "");
27483
- const content = fs41.readFileSync(path61.join(commandsSource, file), "utf8");
27484
- const target = path61.join(harness.homeDir, harness.sync.commandDest(name));
27485
- fs41.mkdirSync(path61.dirname(target), { recursive: true });
27486
- fs41.writeFileSync(target, transform(name, content));
27927
+ const content = fs43.readFileSync(path62.join(commandsSource, file), "utf8");
27928
+ const target = path62.join(harness.homeDir, harness.sync.commandDest(name));
27929
+ fs43.mkdirSync(path62.dirname(target), { recursive: true });
27930
+ fs43.writeFileSync(target, transform(name, content));
27487
27931
  synced++;
27488
27932
  }
27489
- const agentsTarget = path61.join(harness.homeDir, harness.sync.agentsFile);
27490
- fs41.mkdirSync(path61.dirname(agentsTarget), { recursive: true });
27491
- fs41.copyFileSync(path61.join(claudeDir, "CLAUDE.md"), agentsTarget);
27933
+ const agentsTarget = path62.join(harness.homeDir, harness.sync.agentsFile);
27934
+ fs43.mkdirSync(path62.dirname(agentsTarget), { recursive: true });
27935
+ fs43.copyFileSync(path62.join(claudeDir, "CLAUDE.md"), agentsTarget);
27492
27936
  return { total: files.length, synced };
27493
27937
  }
27494
27938
 
27495
27939
  // src/commands/sync/syncCodexHooks.ts
27496
- import * as fs42 from "fs";
27497
- import * as path62 from "path";
27940
+ import * as fs44 from "fs";
27941
+ import * as path63 from "path";
27498
27942
  var BEGIN = "# >>> assist codex hooks (managed) \u2014 do not edit >>>";
27499
27943
  var END = "# <<< assist codex hooks (managed) <<<";
27500
27944
  function upsertManagedBlock(existing, body) {
@@ -27524,11 +27968,11 @@ ${rest}
27524
27968
  `;
27525
27969
  }
27526
27970
  function syncCodexHooks(sourcePath) {
27527
- const body = fs42.readFileSync(sourcePath, "utf8");
27528
- const configPath = path62.join(harnesses.codex.homeDir, "config.toml");
27529
- const existing = fs42.existsSync(configPath) ? fs42.readFileSync(configPath, "utf8") : "";
27530
- fs42.mkdirSync(path62.dirname(configPath), { recursive: true });
27531
- fs42.writeFileSync(configPath, upsertManagedBlock(existing, body));
27971
+ const body = fs44.readFileSync(sourcePath, "utf8");
27972
+ const configPath = path63.join(harnesses.codex.homeDir, "config.toml");
27973
+ const existing = fs44.existsSync(configPath) ? fs44.readFileSync(configPath, "utf8") : "";
27974
+ fs44.mkdirSync(path63.dirname(configPath), { recursive: true });
27975
+ fs44.writeFileSync(configPath, upsertManagedBlock(existing, body));
27532
27976
  console.log(
27533
27977
  "Registered assist codex-hook in ~/.codex/config.toml (PreToolUse, PermissionRequest)"
27534
27978
  );
@@ -27559,50 +28003,50 @@ function syncCodex(claudeDir) {
27559
28003
  harnesses.codex,
27560
28004
  commandToSkill
27561
28005
  );
27562
- syncCodexHooks(path63.join(claudeDir, "..", "codex", "config.toml"));
28006
+ syncCodexHooks(path64.join(claudeDir, "..", "codex", "config.toml"));
27563
28007
  console.log(
27564
28008
  `Synced ${total} skill(s) to ~/.codex/skills and CLAUDE.md to ~/.codex/AGENTS.md`
27565
28009
  );
27566
28010
  }
27567
28011
 
27568
28012
  // src/commands/sync/syncDesign.ts
27569
- import * as fs43 from "fs";
27570
- import * as path64 from "path";
28013
+ import * as fs45 from "fs";
28014
+ import * as path65 from "path";
27571
28015
  function syncDesign(claudeDir, targetBase) {
27572
- const systemPromptSource = path64.join(claudeDir, "system-prompt.md");
27573
- const systemPromptTarget = path64.join(targetBase, "system-prompt.md");
27574
- fs43.copyFileSync(systemPromptSource, systemPromptTarget);
28016
+ const systemPromptSource = path65.join(claudeDir, "system-prompt.md");
28017
+ const systemPromptTarget = path65.join(targetBase, "system-prompt.md");
28018
+ fs45.copyFileSync(systemPromptSource, systemPromptTarget);
27575
28019
  console.log("Copied system-prompt.md to ~/.claude/system-prompt.md");
27576
- const skillsSource = path64.join(claudeDir, "skills");
27577
- const skillsTarget = path64.join(targetBase, "skills");
27578
- fs43.mkdirSync(skillsTarget, { recursive: true });
27579
- const files = fs43.readdirSync(skillsSource);
28020
+ const skillsSource = path65.join(claudeDir, "skills");
28021
+ const skillsTarget = path65.join(targetBase, "skills");
28022
+ fs45.mkdirSync(skillsTarget, { recursive: true });
28023
+ const files = fs45.readdirSync(skillsSource);
27580
28024
  for (const file of files) {
27581
- fs43.copyFileSync(
27582
- path64.join(skillsSource, file),
27583
- path64.join(skillsTarget, file)
28025
+ fs45.copyFileSync(
28026
+ path65.join(skillsSource, file),
28027
+ path65.join(skillsTarget, file)
27584
28028
  );
27585
28029
  }
27586
28030
  console.log(`Synced ${files.length} design skill(s) to ~/.claude/skills`);
27587
28031
  }
27588
28032
 
27589
28033
  // src/commands/sync/syncPi.ts
27590
- import * as path66 from "path";
28034
+ import * as path67 from "path";
27591
28035
 
27592
28036
  // src/commands/sync/syncPiHooks.ts
27593
- import * as fs44 from "fs";
27594
- import * as path65 from "path";
28037
+ import * as fs46 from "fs";
28038
+ import * as path66 from "path";
27595
28039
  function piExtensionsDir() {
27596
- return path65.join(harnesses.pi.homeDir, "extensions");
28040
+ return path66.join(harnesses.pi.homeDir, "extensions");
27597
28041
  }
27598
28042
  function syncPiHooks(sourceDir) {
27599
28043
  const target = piExtensionsDir();
27600
- fs44.mkdirSync(target, { recursive: true });
27601
- const files = fs44.readdirSync(sourceDir).filter((f) => f.endsWith(".ts"));
28044
+ fs46.mkdirSync(target, { recursive: true });
28045
+ const files = fs46.readdirSync(sourceDir).filter((f) => f.endsWith(".ts"));
27602
28046
  for (const file of files) {
27603
- fs44.copyFileSync(
27604
- path65.join(sourceDir, file),
27605
- path65.join(target, `assist-${file}`)
28047
+ fs46.copyFileSync(
28048
+ path66.join(sourceDir, file),
28049
+ path66.join(target, `assist-${file}`)
27606
28050
  );
27607
28051
  }
27608
28052
  console.log(
@@ -27639,23 +28083,23 @@ function syncPi(claudeDir) {
27639
28083
  harnesses.pi,
27640
28084
  commandToPrompt
27641
28085
  );
27642
- syncPiHooks(path66.join(claudeDir, "..", "pi"));
28086
+ syncPiHooks(path67.join(claudeDir, "..", "pi"));
27643
28087
  console.log(
27644
28088
  `Synced ${synced} prompt(s) to ~/.pi/agent/prompts and CLAUDE.md to ~/.pi/agent/AGENTS.md`
27645
28089
  );
27646
28090
  }
27647
28091
 
27648
28092
  // src/commands/sync/syncSettings.ts
27649
- import * as fs45 from "fs";
27650
- import * as path67 from "path";
27651
- import chalk204 from "chalk";
28093
+ import * as fs47 from "fs";
28094
+ import * as path68 from "path";
28095
+ import chalk205 from "chalk";
27652
28096
  async function syncSettings(claudeDir, targetBase, options2) {
27653
- const source = path67.join(claudeDir, "settings.json");
27654
- const target = path67.join(targetBase, "settings.json");
27655
- const sourceContent = fs45.readFileSync(source, "utf8");
28097
+ const source = path68.join(claudeDir, "settings.json");
28098
+ const target = path68.join(targetBase, "settings.json");
28099
+ const sourceContent = fs47.readFileSync(source, "utf8");
27656
28100
  const sourceSettings = JSON.parse(sourceContent);
27657
- const targetExists = fs45.existsSync(target);
27658
- const targetContent = targetExists ? fs45.readFileSync(target, "utf8") : "";
28101
+ const targetExists = fs47.existsSync(target);
28102
+ const targetContent = targetExists ? fs47.readFileSync(target, "utf8") : "";
27659
28103
  const preservedUserSettings = targetExists ? JSON.parse(targetContent) : {};
27660
28104
  const mergedContent = JSON.stringify(
27661
28105
  { ...preservedUserSettings, ...sourceSettings },
@@ -27667,14 +28111,14 @@ async function syncSettings(claudeDir, targetBase, options2) {
27667
28111
  if (mergedContent !== normalizedTarget) {
27668
28112
  if (!options2?.yes) {
27669
28113
  console.log(
27670
- chalk204.yellow(
28114
+ chalk205.yellow(
27671
28115
  "\n\u26A0\uFE0F Warning: settings.json differs from existing file"
27672
28116
  )
27673
28117
  );
27674
28118
  console.log();
27675
28119
  printDiff(targetContent, mergedContent);
27676
28120
  const confirm = await promptConfirm(
27677
- chalk204.red("Overwrite existing settings.json?"),
28121
+ chalk205.red("Overwrite existing settings.json?"),
27678
28122
  false
27679
28123
  );
27680
28124
  if (!confirm) {
@@ -27684,18 +28128,18 @@ async function syncSettings(claudeDir, targetBase, options2) {
27684
28128
  }
27685
28129
  }
27686
28130
  }
27687
- fs45.writeFileSync(target, mergedContent);
28131
+ fs47.writeFileSync(target, mergedContent);
27688
28132
  console.log("Copied settings.json to ~/.claude/settings.json");
27689
28133
  }
27690
28134
 
27691
28135
  // src/commands/sync.ts
27692
28136
  var __filename5 = fileURLToPath9(import.meta.url);
27693
- var __dirname7 = path68.dirname(__filename5);
28137
+ var __dirname7 = path69.dirname(__filename5);
27694
28138
  async function sync(options2) {
27695
28139
  const config = loadConfig();
27696
28140
  const yes = options2?.yes ?? config.sync.autoConfirm;
27697
- const claudeDir = path68.join(__dirname7, "..", "claude");
27698
- const targetBase = path68.join(os4.homedir(), ".claude");
28141
+ const claudeDir = path69.join(__dirname7, "..", "claude");
28142
+ const targetBase = path69.join(os5.homedir(), ".claude");
27699
28143
  syncCommands(claudeDir, targetBase);
27700
28144
  syncDesign(claudeDir, targetBase);
27701
28145
  await syncSettings(claudeDir, targetBase, { yes });
@@ -27704,12 +28148,12 @@ async function sync(options2) {
27704
28148
  syncPi(claudeDir);
27705
28149
  }
27706
28150
  function syncCommands(claudeDir, targetBase) {
27707
- const sourceDir = path68.join(claudeDir, "commands");
27708
- const targetDir = path68.join(targetBase, "commands");
27709
- fs46.mkdirSync(targetDir, { recursive: true });
27710
- const files = fs46.readdirSync(sourceDir);
28151
+ const sourceDir = path69.join(claudeDir, "commands");
28152
+ const targetDir = path69.join(targetBase, "commands");
28153
+ fs48.mkdirSync(targetDir, { recursive: true });
28154
+ const files = fs48.readdirSync(sourceDir);
27711
28155
  for (const file of files) {
27712
- fs46.copyFileSync(path68.join(sourceDir, file), path68.join(targetDir, file));
28156
+ fs48.copyFileSync(path69.join(sourceDir, file), path69.join(targetDir, file));
27713
28157
  console.log(`Copied ${file} to ${targetDir}`);
27714
28158
  }
27715
28159
  console.log(`Synced ${files.length} command(s) to ~/.claude/commands`);
@@ -27717,7 +28161,7 @@ function syncCommands(claudeDir, targetBase) {
27717
28161
 
27718
28162
  // src/commands/update.ts
27719
28163
  import { execSync as execSync59 } from "child_process";
27720
- import * as path69 from "path";
28164
+ import * as path70 from "path";
27721
28165
 
27722
28166
  // src/commands/restartDaemonAfterUpdate.ts
27723
28167
  async function restartDaemonAfterUpdate() {
@@ -27736,12 +28180,12 @@ async function restartDaemonAfterUpdate() {
27736
28180
  // src/commands/update.ts
27737
28181
  function isGlobalNpmInstall(dir) {
27738
28182
  try {
27739
- const resolved = path69.resolve(dir);
27740
- if (resolved.split(path69.sep).includes("node_modules")) {
28183
+ const resolved = path70.resolve(dir);
28184
+ if (resolved.split(path70.sep).includes("node_modules")) {
27741
28185
  return true;
27742
28186
  }
27743
28187
  const globalPrefix = execSync59("npm prefix -g", { stdio: "pipe" }).toString().trim();
27744
- return resolved.toLowerCase().startsWith(path69.resolve(globalPrefix).toLowerCase());
28188
+ return resolved.toLowerCase().startsWith(path70.resolve(globalPrefix).toLowerCase());
27745
28189
  } catch {
27746
28190
  return false;
27747
28191
  }
@@ -27773,10 +28217,10 @@ async function update2() {
27773
28217
  }
27774
28218
 
27775
28219
  // src/reportCliError.ts
27776
- import chalk205 from "chalk";
28220
+ import chalk206 from "chalk";
27777
28221
  function reportCliError(error) {
27778
- if (error instanceof InvalidItemIdError) {
27779
- console.error(chalk205.red(error.message));
28222
+ if (error instanceof InvalidItemIdError || error instanceof AmbiguousRepoConfigError) {
28223
+ console.error(chalk206.red(error.message));
27780
28224
  } else {
27781
28225
  console.error(error);
27782
28226
  }