@staff0rd/assist 0.252.0 → 0.254.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.252.0",
9
+ version: "0.254.0",
10
10
  type: "module",
11
11
  main: "dist/index.js",
12
12
  bin: {
@@ -73,6 +73,8 @@ var package_default = {
73
73
  "@semantic-release/changelog": "^6.0.3",
74
74
  "@semantic-release/exec": "^7.1.0",
75
75
  "@semantic-release/git": "^10.0.1",
76
+ "@testing-library/dom": "^10.4.1",
77
+ "@testing-library/react": "^16.3.2",
76
78
  "@types/better-sqlite3": "^7.6.13",
77
79
  "@types/blessed": "^0.1.27",
78
80
  "@types/mssql": "^12.3.0",
@@ -90,6 +92,7 @@ var package_default = {
90
92
  "@xterm/xterm": "^6.0.0",
91
93
  esbuild: "^0.27.3",
92
94
  jscpd: "^4.0.5",
95
+ jsdom: "^29.1.1",
93
96
  knip: "^5.71.0",
94
97
  marked: "^15.0.12",
95
98
  react: "^19.2.4",
@@ -115,10 +118,10 @@ import { stringify as stringifyYaml } from "yaml";
115
118
  // src/shared/loadRawYaml.ts
116
119
  import { existsSync, readFileSync } from "fs";
117
120
  import { parse as parseYaml } from "yaml";
118
- function loadRawYaml(path54) {
119
- if (!existsSync(path54)) return {};
121
+ function loadRawYaml(path53) {
122
+ if (!existsSync(path53)) return {};
120
123
  try {
121
- const content = readFileSync(path54, "utf-8");
124
+ const content = readFileSync(path53, "utf-8");
122
125
  return parseYaml(content) || {};
123
126
  } catch {
124
127
  return {};
@@ -2743,9 +2746,9 @@ var LOCAL_FILES = ["backlog.jsonl", "backlog.db"];
2743
2746
  function backupLocalBacklogFiles(dir) {
2744
2747
  const moved = [];
2745
2748
  for (const name of LOCAL_FILES) {
2746
- const path54 = join10(dir, ".assist", name);
2747
- if (existsSync14(path54)) {
2748
- renameSync(path54, `${path54}.bak`);
2749
+ const path53 = join10(dir, ".assist", name);
2750
+ if (existsSync14(path53)) {
2751
+ renameSync(path53, `${path53}.bak`);
2749
2752
  moved.push(`${name} \u2192 ${name}.bak`);
2750
2753
  }
2751
2754
  }
@@ -2893,12 +2896,12 @@ var selectTasks = (orm, ids) => orm.select().from(planTasks).where(inArray(planT
2893
2896
  asc(planTasks.phaseIdx),
2894
2897
  asc(planTasks.idx)
2895
2898
  );
2896
- async function loadRelations(orm, ids) {
2899
+ async function loadRelations(orm, ids, { includeComments = true, includeTasks = true } = {}) {
2897
2900
  const [commentRows, linkRows, phaseRows, taskRows] = await Promise.all([
2898
- selectComments(orm, ids),
2901
+ includeComments ? selectComments(orm, ids) : [],
2899
2902
  selectLinks(orm, ids),
2900
2903
  selectPhases(orm, ids),
2901
- selectTasks(orm, ids)
2904
+ includeTasks ? selectTasks(orm, ids) : []
2902
2905
  ]);
2903
2906
  return {
2904
2907
  comments: groupByItem(commentRows),
@@ -2985,7 +2988,8 @@ async function loadAllItems(orm, origin) {
2985
2988
  if (rows.length === 0) return [];
2986
2989
  const rel = await loadRelations(
2987
2990
  orm,
2988
- rows.map((r) => r.id)
2991
+ rows.map((r) => r.id),
2992
+ { includeComments: false, includeTasks: false }
2989
2993
  );
2990
2994
  return rows.map((row) => rowToItem(row, rel));
2991
2995
  }
@@ -3034,8 +3038,8 @@ var backlogItemSchema = z3.strictObject({
3034
3038
  var backlogFileSchema = z3.array(backlogItemSchema);
3035
3039
 
3036
3040
  // src/commands/backlog/parseBacklogJsonl.ts
3037
- function parseBacklogJsonl(path54) {
3038
- const content = readFileSync9(path54, "utf-8").trim();
3041
+ function parseBacklogJsonl(path53) {
3042
+ const content = readFileSync9(path53, "utf-8").trim();
3039
3043
  if (content.length === 0) return [];
3040
3044
  return content.split("\n").map((line) => line.trim()).filter(Boolean).map((line) => backlogItemSchema.parse(JSON.parse(line)));
3041
3045
  }
@@ -3110,8 +3114,8 @@ function findBacklogUp(startDir) {
3110
3114
 
3111
3115
  // src/commands/backlog/getCurrentOrigin.ts
3112
3116
  import { execSync as execSync17 } from "child_process";
3113
- function stripLeadingSlashes(path54) {
3114
- return path54.replace(/^\/+/, "");
3117
+ function stripLeadingSlashes(path53) {
3118
+ return path53.replace(/^\/+/, "");
3115
3119
  }
3116
3120
  function normalizeOrigin(raw) {
3117
3121
  const trimmed = raw.trim().replace(/\.git$/i, "").replace(/\/+$/, "");
@@ -3423,6 +3427,33 @@ async function reloadPlan(id) {
3423
3427
  // src/commands/backlog/executePhase.ts
3424
3428
  import chalk34 from "chalk";
3425
3429
 
3430
+ // src/shared/emitActivity.ts
3431
+ import { mkdirSync as mkdirSync4, readFileSync as readFileSync11, rmSync, writeFileSync as writeFileSync12 } from "fs";
3432
+ import { dirname as dirname14, join as join14 } from "path";
3433
+ function activityPath(cwd, sessionId) {
3434
+ return join14(cwd, ".assist", `activity-${sessionId}.json`);
3435
+ }
3436
+ function emitActivity(activity2) {
3437
+ const sessionId = process.env.ASSIST_ACTIVITY_ID;
3438
+ if (!sessionId) return;
3439
+ const path53 = activityPath(process.cwd(), sessionId);
3440
+ mkdirSync4(dirname14(path53), { recursive: true });
3441
+ writeFileSync12(path53, JSON.stringify({ ...activity2, startedAt: Date.now() }));
3442
+ }
3443
+ function readActivity(path53) {
3444
+ try {
3445
+ return JSON.parse(readFileSync11(path53, "utf-8"));
3446
+ } catch {
3447
+ return void 0;
3448
+ }
3449
+ }
3450
+ function removeActivity(cwd, sessionId) {
3451
+ try {
3452
+ rmSync(activityPath(cwd, sessionId));
3453
+ } catch {
3454
+ }
3455
+ }
3456
+
3426
3457
  // src/shared/spawnClaude.ts
3427
3458
  import { spawn as spawn3 } from "child_process";
3428
3459
  function spawnClaude(prompt, options2 = {}) {
@@ -3430,8 +3461,10 @@ function spawnClaude(prompt, options2 = {}) {
3430
3461
  if (options2.allowEdits) {
3431
3462
  args.push("--permission-mode", "auto");
3432
3463
  }
3464
+ const { ASSIST_ACTIVITY_ID: _activityId, ...env } = process.env;
3433
3465
  const child = spawn3("claude", args, {
3434
- stdio: "inherit"
3466
+ stdio: "inherit",
3467
+ env
3435
3468
  });
3436
3469
  const done2 = new Promise((resolve16, reject) => {
3437
3470
  child.on("close", (code) => resolve16(code ?? 0));
@@ -3565,28 +3598,28 @@ async function handleIncompletePhase() {
3565
3598
  }
3566
3599
 
3567
3600
  // src/commands/backlog/readSignal.ts
3568
- import { existsSync as existsSync18, readFileSync as readFileSync11 } from "fs";
3601
+ import { existsSync as existsSync18, readFileSync as readFileSync12 } from "fs";
3569
3602
 
3570
3603
  // src/commands/backlog/writeSignal.ts
3571
- import { writeFileSync as writeFileSync12 } from "fs";
3572
- import { join as join14 } from "path";
3604
+ import { writeFileSync as writeFileSync13 } from "fs";
3605
+ import { join as join15 } from "path";
3573
3606
  function getSignalPath() {
3574
3607
  const sessionId = process.env.ASSIST_SESSION_ID;
3575
3608
  const filename = sessionId ? `.assist-signal-${sessionId}.json` : ".assist-signal.json";
3576
- return join14(getBacklogDir(), filename);
3609
+ return join15(getBacklogDir(), filename);
3577
3610
  }
3578
3611
  function writeSignal(event, data) {
3579
3612
  const sessionId = process.env.ASSIST_SESSION_ID;
3580
3613
  const signal = { event, ...sessionId && { sessionId }, ...data };
3581
- writeFileSync12(getSignalPath(), JSON.stringify(signal));
3614
+ writeFileSync13(getSignalPath(), JSON.stringify(signal));
3582
3615
  }
3583
3616
 
3584
3617
  // src/commands/backlog/readSignal.ts
3585
3618
  function readSignal() {
3586
- const path54 = getSignalPath();
3587
- if (!existsSync18(path54)) return void 0;
3619
+ const path53 = getSignalPath();
3620
+ if (!existsSync18(path53)) return void 0;
3588
3621
  try {
3589
- return JSON.parse(readFileSync11(path54, "utf-8"));
3622
+ return JSON.parse(readFileSync12(path53, "utf-8"));
3590
3623
  } catch {
3591
3624
  return void 0;
3592
3625
  }
@@ -3600,8 +3633,8 @@ function cleanupSignal() {
3600
3633
  }
3601
3634
  }
3602
3635
  async function isTerminalStatus(itemId) {
3603
- const items2 = await loadBacklog();
3604
- const item = items2.find((i) => i.id === itemId);
3636
+ const { orm } = await getReady();
3637
+ const item = await loadItem(orm, itemId);
3605
3638
  return item?.status === "done" || item?.status === "wontdo";
3606
3639
  }
3607
3640
  async function resolvePhaseResult(phaseIndex, itemId) {
@@ -3644,17 +3677,24 @@ function stopWatching() {
3644
3677
  }
3645
3678
 
3646
3679
  // src/commands/backlog/executePhase.ts
3647
- async function executePhase(item, phaseIndex, phases, spawnOptions) {
3680
+ async function executePhase(item, phaseIndex, phases, spawnOptions, totalPhases = phases.length) {
3648
3681
  const phase = phases[phaseIndex];
3649
3682
  const phaseNumber = phaseIndex + 1;
3650
3683
  console.log(
3651
3684
  chalk34.bold(
3652
3685
  `
3653
- --- Phase ${phaseNumber}/${phases.length}: ${phase.name} ---
3686
+ --- Phase ${phaseNumber}/${totalPhases}: ${phase.name} ---
3654
3687
  `
3655
3688
  )
3656
3689
  );
3657
- process.env.ASSIST_SESSION_ID = String(process.pid);
3690
+ process.env.ASSIST_SESSION_ID ??= String(process.pid);
3691
+ emitActivity({
3692
+ kind: "backlog",
3693
+ itemId: item.id,
3694
+ itemName: item.name,
3695
+ phase: phaseNumber,
3696
+ totalPhases
3697
+ });
3658
3698
  const { child, done: done2 } = spawnClaude(
3659
3699
  buildPhasePrompt(item, phaseNumber, phase),
3660
3700
  spawnOptions
@@ -3674,7 +3714,9 @@ async function runPhases(item, startPhase, plan2, spawnOptions) {
3674
3714
  item,
3675
3715
  phaseIndex,
3676
3716
  currentPlan,
3677
- spawnOptions
3717
+ spawnOptions,
3718
+ // +1 for the review phase appended after the authored phases complete
3719
+ currentPlan.length + 1
3678
3720
  );
3679
3721
  if (phaseIndex < 0) return false;
3680
3722
  currentPlan = await reloadPlan(item.id) ?? currentPlan;
@@ -4023,10 +4065,10 @@ import { WebSocketServer } from "ws";
4023
4065
 
4024
4066
  // src/shared/getInstallDir.ts
4025
4067
  import { execSync as execSync18 } from "child_process";
4026
- import { dirname as dirname14, resolve as resolve6 } from "path";
4068
+ import { dirname as dirname15, resolve as resolve6 } from "path";
4027
4069
  import { fileURLToPath as fileURLToPath3 } from "url";
4028
4070
  var __filename2 = fileURLToPath3(import.meta.url);
4029
- var __dirname4 = dirname14(__filename2);
4071
+ var __dirname4 = dirname15(__filename2);
4030
4072
  function getInstallDir() {
4031
4073
  return resolve6(__dirname4, "..");
4032
4074
  }
@@ -4103,7 +4145,7 @@ function startWebServer(label2, port, handler, initialPath) {
4103
4145
  import { spawn as spawn4 } from "child_process";
4104
4146
  import {
4105
4147
  closeSync,
4106
- mkdirSync as mkdirSync4,
4148
+ mkdirSync as mkdirSync5,
4107
4149
  openSync,
4108
4150
  statSync,
4109
4151
  unlinkSync as unlinkSync4,
@@ -4115,14 +4157,14 @@ import * as net from "net";
4115
4157
 
4116
4158
  // src/commands/sessions/daemon/daemonPaths.ts
4117
4159
  import { homedir as homedir3 } from "os";
4118
- import { join as join15 } from "path";
4119
- var DAEMON_DIR = join15(homedir3(), ".assist", "daemon");
4160
+ import { join as join16 } from "path";
4161
+ var DAEMON_DIR = join16(homedir3(), ".assist", "daemon");
4120
4162
  var daemonPaths = {
4121
4163
  dir: DAEMON_DIR,
4122
- socket: process.platform === "win32" ? "\\\\.\\pipe\\assist-sessions-daemon" : join15(DAEMON_DIR, "daemon.sock"),
4123
- log: join15(DAEMON_DIR, "daemon.log"),
4124
- pid: join15(DAEMON_DIR, "daemon.pid"),
4125
- spawnLock: join15(DAEMON_DIR, "spawn.lock")
4164
+ socket: process.platform === "win32" ? "\\\\.\\pipe\\assist-sessions-daemon" : join16(DAEMON_DIR, "daemon.sock"),
4165
+ log: join16(DAEMON_DIR, "daemon.log"),
4166
+ pid: join16(DAEMON_DIR, "daemon.pid"),
4167
+ spawnLock: join16(DAEMON_DIR, "spawn.lock")
4126
4168
  };
4127
4169
 
4128
4170
  // src/commands/sessions/daemon/connectToDaemon.ts
@@ -4148,7 +4190,7 @@ var RETRY_DELAY_MS = 200;
4148
4190
  var STALE_LOCK_MS = SPAWN_TIMEOUT_MS + 5e3;
4149
4191
  async function ensureDaemonRunning(reason = "unspecified") {
4150
4192
  if (await isDaemonRunning()) return;
4151
- mkdirSync4(daemonPaths.dir, { recursive: true });
4193
+ mkdirSync5(daemonPaths.dir, { recursive: true });
4152
4194
  const holdsLock = acquireSpawnLock();
4153
4195
  if (holdsLock) spawnDaemon(reason);
4154
4196
  try {
@@ -4213,19 +4255,19 @@ function delay(ms) {
4213
4255
  }
4214
4256
 
4215
4257
  // src/commands/sessions/web/handleRequest.ts
4216
- import { readFileSync as readFileSync13 } from "fs";
4258
+ import { readFileSync as readFileSync14 } from "fs";
4217
4259
  import { createRequire as createRequire2 } from "module";
4218
4260
 
4219
4261
  // src/shared/createBundleHandler.ts
4220
- import { readFileSync as readFileSync12 } from "fs";
4221
- import { dirname as dirname15, join as join16 } from "path";
4262
+ import { readFileSync as readFileSync13 } from "fs";
4263
+ import { dirname as dirname16, join as join17 } from "path";
4222
4264
  import { fileURLToPath as fileURLToPath4 } from "url";
4223
4265
  function createBundleHandler(importMetaUrl, bundlePath) {
4224
- const dir = dirname15(fileURLToPath4(importMetaUrl));
4266
+ const dir = dirname16(fileURLToPath4(importMetaUrl));
4225
4267
  let cache;
4226
4268
  return (_req, res) => {
4227
4269
  if (!cache) {
4228
- cache = readFileSync12(join16(dir, bundlePath), "utf-8");
4270
+ cache = readFileSync13(join17(dir, bundlePath), "utf-8");
4229
4271
  }
4230
4272
  res.writeHead(200, { "Content-Type": "application/javascript" });
4231
4273
  res.end(cache);
@@ -4293,31 +4335,79 @@ async function createItem(req, res) {
4293
4335
  respondJson(res, 201, { id, ...newItem });
4294
4336
  }
4295
4337
 
4338
+ // src/commands/backlog/loadBacklogSummaries.ts
4339
+ import { eq as eq11 } from "drizzle-orm";
4340
+
4341
+ // src/commands/backlog/loadItemSummaries.ts
4342
+ import { asc as asc4, eq as eq10 } from "drizzle-orm";
4343
+ async function loadItemSummaries(orm, origin) {
4344
+ const rows = await orm.select({
4345
+ id: items.id,
4346
+ origin: items.origin,
4347
+ type: items.type,
4348
+ name: items.name,
4349
+ status: items.status
4350
+ }).from(items).where(origin === void 0 ? void 0 : eq10(items.origin, origin)).orderBy(asc4(items.id));
4351
+ return rows.map((row) => ({
4352
+ id: row.id,
4353
+ origin: row.origin,
4354
+ type: row.type,
4355
+ name: row.name,
4356
+ status: row.status
4357
+ }));
4358
+ }
4359
+
4360
+ // src/commands/backlog/loadBacklogSummaries.ts
4361
+ async function loadBacklogSummaries(allRepos = false) {
4362
+ const { orm } = await getReady();
4363
+ return loadItemSummaries(orm, allRepos ? void 0 : getOrigin());
4364
+ }
4365
+ async function searchBacklogSummaries(query) {
4366
+ const { orm } = await getReady();
4367
+ const origin = getOrigin();
4368
+ const ids = await searchItemIds(orm, query, origin);
4369
+ const summaries = await loadItemSummaries(orm, origin);
4370
+ return summaries.filter((item) => ids.includes(item.id));
4371
+ }
4372
+ async function backlogHasItems() {
4373
+ const { orm } = await getReady();
4374
+ const [row] = await orm.select({ id: items.id }).from(items).where(eq11(items.origin, getOrigin())).limit(1);
4375
+ return row !== void 0;
4376
+ }
4377
+
4296
4378
  // src/commands/backlog/web/getBacklogExists.ts
4297
4379
  async function getBacklogExists(req, res) {
4298
4380
  applyCwdFromReq(req);
4299
- const items2 = await loadBacklog();
4300
- respondJson(res, 200, { exists: items2.length > 0 });
4381
+ respondJson(res, 200, { exists: await backlogHasItems() });
4301
4382
  }
4302
4383
 
4303
4384
  // src/commands/backlog/web/rewindItemPhase.ts
4304
- import { eq as eq11 } from "drizzle-orm";
4385
+ import { eq as eq13 } from "drizzle-orm";
4305
4386
 
4306
4387
  // src/commands/backlog/deleteComment.ts
4307
- import { and as and2, eq as eq10 } from "drizzle-orm";
4388
+ import { and as and2, eq as eq12 } from "drizzle-orm";
4308
4389
  async function deleteComment(orm, itemId, commentId) {
4309
- const [row] = await orm.select({ type: comments.type }).from(comments).where(and2(eq10(comments.id, commentId), eq10(comments.itemId, itemId)));
4390
+ const [row] = await orm.select({ type: comments.type }).from(comments).where(and2(eq12(comments.id, commentId), eq12(comments.itemId, itemId)));
4310
4391
  if (!row) return "not-found";
4311
4392
  if (row.type === "summary") return "is-summary";
4312
- await orm.delete(comments).where(and2(eq10(comments.id, commentId), eq10(comments.itemId, itemId)));
4393
+ await orm.delete(comments).where(and2(eq12(comments.id, commentId), eq12(comments.itemId, itemId)));
4313
4394
  return "deleted";
4314
4395
  }
4315
4396
 
4397
+ // src/commands/backlog/web/loadVisibleItems.ts
4398
+ var completedStatuses = /* @__PURE__ */ new Set(["done", "wontdo"]);
4399
+ async function loadVisibleItems(req) {
4400
+ const params = new URL(req.url ?? "/", "http://localhost").searchParams;
4401
+ const q = params.get("q");
4402
+ const loaded = q ? await searchBacklogSummaries(q) : await loadBacklogSummaries();
4403
+ if (params.get("showCompleted") === "true") return loaded;
4404
+ return loaded.filter((item) => !completedStatuses.has(item.status));
4405
+ }
4406
+
4316
4407
  // src/commands/backlog/web/shared.ts
4317
4408
  async function listItems(req, res) {
4318
4409
  applyCwdFromReq(req);
4319
- const q = new URL(req.url ?? "/", "http://localhost").searchParams.get("q");
4320
- const items2 = q ? await searchBacklog(q) : await loadBacklog();
4410
+ const items2 = await loadVisibleItems(req);
4321
4411
  respondJson(res, 200, items2.slice().reverse());
4322
4412
  }
4323
4413
  async function findItemOr404(res, id) {
@@ -4384,7 +4474,7 @@ async function rewindItemPhase(req, res, id) {
4384
4474
  `Rewound to phase ${phase} (${phaseName}): ${reason}`,
4385
4475
  { phase }
4386
4476
  );
4387
- await orm.update(items).set({ currentPhase: phase, status: "in-progress" }).where(eq11(items.id, id));
4477
+ await orm.update(items).set({ currentPhase: phase, status: "in-progress" }).where(eq13(items.id, id));
4388
4478
  respondJson(res, 200, await loadItem(orm, id));
4389
4479
  }
4390
4480
  function validateRewind(item, phase) {
@@ -4402,7 +4492,7 @@ function validateRewind(item, phase) {
4402
4492
  }
4403
4493
 
4404
4494
  // src/commands/backlog/web/updateItem.ts
4405
- import { eq as eq12 } from "drizzle-orm";
4495
+ import { eq as eq14 } from "drizzle-orm";
4406
4496
  async function updateItem(req, res, id) {
4407
4497
  const body = await parseItemBody(req);
4408
4498
  const result = await findItemOr404(res, id);
@@ -4413,7 +4503,7 @@ async function updateItem(req, res, id) {
4413
4503
  name: body.name,
4414
4504
  description: body.description ?? null,
4415
4505
  acceptanceCriteria: JSON.stringify(body.acceptanceCriteria ?? [])
4416
- }).where(eq12(items.id, id));
4506
+ }).where(eq14(items.id, id));
4417
4507
  respondJson(res, 200, await loadItem(orm, id));
4418
4508
  }
4419
4509
 
@@ -4525,7 +4615,7 @@ function createCssHandler(packageEntry) {
4525
4615
  return (_req, res) => {
4526
4616
  if (!cache) {
4527
4617
  const resolved = require3.resolve(packageEntry);
4528
- cache = readFileSync13(resolved, "utf-8");
4618
+ cache = readFileSync14(resolved, "utf-8");
4529
4619
  }
4530
4620
  res.writeHead(200, { "Content-Type": "text/css" });
4531
4621
  res.end(cache);
@@ -4996,9 +5086,9 @@ import chalk51 from "chalk";
4996
5086
 
4997
5087
  // src/commands/backlog/add/shared.ts
4998
5088
  import { spawnSync } from "child_process";
4999
- import { mkdtempSync, readFileSync as readFileSync14, unlinkSync as unlinkSync5, writeFileSync as writeFileSync13 } from "fs";
5089
+ import { mkdtempSync, readFileSync as readFileSync15, unlinkSync as unlinkSync5, writeFileSync as writeFileSync14 } from "fs";
5000
5090
  import { tmpdir } from "os";
5001
- import { join as join17 } from "path";
5091
+ import { join as join18 } from "path";
5002
5092
  import enquirer6 from "enquirer";
5003
5093
  async function promptType() {
5004
5094
  const { type } = await enquirer6.prompt({
@@ -5038,15 +5128,15 @@ async function promptDescription() {
5038
5128
  }
5039
5129
  function openEditor() {
5040
5130
  const editor = process.env.EDITOR || process.env.VISUAL || "vi";
5041
- const dir = mkdtempSync(join17(tmpdir(), "assist-"));
5042
- const filePath = join17(dir, "description.md");
5043
- writeFileSync13(filePath, "");
5131
+ const dir = mkdtempSync(join18(tmpdir(), "assist-"));
5132
+ const filePath = join18(dir, "description.md");
5133
+ writeFileSync14(filePath, "");
5044
5134
  const result = spawnSync(editor, [filePath], { stdio: "inherit" });
5045
5135
  if (result.status !== 0) {
5046
5136
  unlinkSync5(filePath);
5047
5137
  return void 0;
5048
5138
  }
5049
- const content = readFileSync14(filePath, "utf-8").trim();
5139
+ const content = readFileSync15(filePath, "utf-8").trim();
5050
5140
  unlinkSync5(filePath);
5051
5141
  return content || void 0;
5052
5142
  }
@@ -5089,22 +5179,22 @@ async function add(options2) {
5089
5179
  import chalk53 from "chalk";
5090
5180
 
5091
5181
  // src/commands/backlog/insertPhaseAt.ts
5092
- import { count, eq as eq14 } from "drizzle-orm";
5182
+ import { count, eq as eq16 } from "drizzle-orm";
5093
5183
 
5094
5184
  // src/commands/backlog/shiftPhasesUp.ts
5095
- import { and as and3, desc, eq as eq13, gte } from "drizzle-orm";
5185
+ import { and as and3, desc, eq as eq15, gte } from "drizzle-orm";
5096
5186
  async function shiftPhasesUp(db, itemId, fromIdx) {
5097
- const toShift = await db.select({ idx: planPhases.idx }).from(planPhases).where(and3(eq13(planPhases.itemId, itemId), gte(planPhases.idx, fromIdx))).orderBy(desc(planPhases.idx));
5187
+ const toShift = await db.select({ idx: planPhases.idx }).from(planPhases).where(and3(eq15(planPhases.itemId, itemId), gte(planPhases.idx, fromIdx))).orderBy(desc(planPhases.idx));
5098
5188
  for (const p of toShift) {
5099
- await db.update(planTasks).set({ phaseIdx: p.idx + 1 }).where(and3(eq13(planTasks.itemId, itemId), eq13(planTasks.phaseIdx, p.idx)));
5100
- await db.update(planPhases).set({ idx: p.idx + 1 }).where(and3(eq13(planPhases.itemId, itemId), eq13(planPhases.idx, p.idx)));
5189
+ await db.update(planTasks).set({ phaseIdx: p.idx + 1 }).where(and3(eq15(planTasks.itemId, itemId), eq15(planTasks.phaseIdx, p.idx)));
5190
+ await db.update(planPhases).set({ idx: p.idx + 1 }).where(and3(eq15(planPhases.itemId, itemId), eq15(planPhases.idx, p.idx)));
5101
5191
  }
5102
5192
  }
5103
5193
 
5104
5194
  // src/commands/backlog/insertPhaseAt.ts
5105
5195
  async function insertPhaseAt(orm, itemId, phaseIdx, name, tasks, manualChecks, currentPhase) {
5106
5196
  await orm.transaction(async (tx) => {
5107
- const [row] = await tx.select({ cnt: count() }).from(planPhases).where(eq14(planPhases.itemId, itemId));
5197
+ const [row] = await tx.select({ cnt: count() }).from(planPhases).where(eq16(planPhases.itemId, itemId));
5108
5198
  const phaseCount = row?.cnt ?? 0;
5109
5199
  await shiftPhasesUp(tx, itemId, phaseIdx);
5110
5200
  await tx.insert(planPhases).values({ itemId, idx: phaseIdx, name, manualChecks });
@@ -5113,16 +5203,16 @@ async function insertPhaseAt(orm, itemId, phaseIdx, name, tasks, manualChecks, c
5113
5203
  }
5114
5204
  if (currentPhase !== void 0 && currentPhase - 1 >= phaseIdx) {
5115
5205
  const atReviewSlot = currentPhase - 1 >= phaseCount;
5116
- await tx.update(items).set({ currentPhase: atReviewSlot ? phaseIdx + 1 : currentPhase + 1 }).where(eq14(items.id, itemId));
5206
+ await tx.update(items).set({ currentPhase: atReviewSlot ? phaseIdx + 1 : currentPhase + 1 }).where(eq16(items.id, itemId));
5117
5207
  }
5118
5208
  });
5119
5209
  }
5120
5210
 
5121
5211
  // src/commands/backlog/resolveInsertPosition.ts
5122
5212
  import chalk52 from "chalk";
5123
- import { count as count2, eq as eq15 } from "drizzle-orm";
5213
+ import { count as count2, eq as eq17 } from "drizzle-orm";
5124
5214
  async function resolveInsertPosition(orm, itemId, position) {
5125
- const [row] = await orm.select({ cnt: count2() }).from(planPhases).where(eq15(planPhases.itemId, itemId));
5215
+ const [row] = await orm.select({ cnt: count2() }).from(planPhases).where(eq17(planPhases.itemId, itemId));
5126
5216
  const phaseCount = row?.cnt ?? 0;
5127
5217
  if (position === void 0) return phaseCount;
5128
5218
  const pos = Number.parseInt(position, 10);
@@ -5180,8 +5270,8 @@ import chalk54 from "chalk";
5180
5270
  // src/commands/backlog/originDisplayName.ts
5181
5271
  function originDisplayName(origin) {
5182
5272
  if (origin.startsWith("local:")) {
5183
- const path54 = origin.slice("local:".length).replace(/\/+$/, "");
5184
- const segments = path54.split("/").filter(Boolean);
5273
+ const path53 = origin.slice("local:".length).replace(/\/+$/, "");
5274
+ const segments = path53.split("/").filter(Boolean);
5185
5275
  return segments[segments.length - 1] ?? origin;
5186
5276
  }
5187
5277
  const firstSlash = origin.indexOf("/");
@@ -5236,9 +5326,9 @@ async function list2(options2) {
5236
5326
  const repoNameOf = (item) => item.origin ? labels.get(item.origin) ?? "" : "";
5237
5327
  const prefixWidth = options2.allRepos ? Math.max(0, ...items2.map((i) => repoNameOf(i).length)) : 0;
5238
5328
  for (const item of items2) {
5239
- const repoPrefix2 = options2.allRepos ? `${chalk54.dim(repoNameOf(item).padEnd(prefixWidth))} ` : "";
5329
+ const repoPrefix = options2.allRepos ? `${chalk54.dim(repoNameOf(item).padEnd(prefixWidth))} ` : "";
5240
5330
  console.log(
5241
- `${repoPrefix2}${statusIcon(item.status)} ${typeLabel(item.type)} ${chalk54.dim(`#${item.id}`)} ${item.name}${phaseLabel(item)}${dependencyLabel(item, allItems)}`
5331
+ `${repoPrefix}${statusIcon(item.status)} ${typeLabel(item.type)} ${chalk54.dim(`#${item.id}`)} ${item.name}${phaseLabel(item)}${dependencyLabel(item, allItems)}`
5242
5332
  );
5243
5333
  if (options2.verbose) {
5244
5334
  printVerboseDetails(item);
@@ -5283,9 +5373,9 @@ function hasCycle(adjacency, fromId, toId) {
5283
5373
  }
5284
5374
 
5285
5375
  // src/commands/backlog/loadDependencyGraph.ts
5286
- import { eq as eq16 } from "drizzle-orm";
5376
+ import { eq as eq18 } from "drizzle-orm";
5287
5377
  async function loadDependencyGraph(orm) {
5288
- const rows = await orm.select({ itemId: links.itemId, targetId: links.targetId }).from(links).where(eq16(links.type, "depends-on"));
5378
+ const rows = await orm.select({ itemId: links.itemId, targetId: links.targetId }).from(links).where(eq18(links.type, "depends-on"));
5289
5379
  const graph = /* @__PURE__ */ new Map();
5290
5380
  for (const { itemId, targetId } of rows) {
5291
5381
  const bucket = graph.get(itemId);
@@ -5348,7 +5438,7 @@ async function link(fromId, toId, opts) {
5348
5438
 
5349
5439
  // src/commands/backlog/unlink.ts
5350
5440
  import chalk57 from "chalk";
5351
- import { and as and4, eq as eq17 } from "drizzle-orm";
5441
+ import { and as and4, eq as eq19 } from "drizzle-orm";
5352
5442
  async function unlink(fromId, toId) {
5353
5443
  const fromNum = Number.parseInt(fromId, 10);
5354
5444
  const toNum = Number.parseInt(toId, 10);
@@ -5366,7 +5456,7 @@ async function unlink(fromId, toId) {
5366
5456
  console.log(chalk57.yellow(`No link from #${fromId} to #${toId} found.`));
5367
5457
  return;
5368
5458
  }
5369
- await orm.delete(links).where(and4(eq17(links.itemId, fromNum), eq17(links.targetId, toNum)));
5459
+ await orm.delete(links).where(and4(eq19(links.itemId, fromNum), eq19(links.targetId, toNum)));
5370
5460
  console.log(chalk57.green(`Removed link from #${fromId} to #${toId}.`));
5371
5461
  }
5372
5462
 
@@ -5382,7 +5472,7 @@ function registerLinkCommands(cmd) {
5382
5472
 
5383
5473
  // src/commands/backlog/move-repo/index.ts
5384
5474
  import chalk59 from "chalk";
5385
- import { eq as eq19 } from "drizzle-orm";
5475
+ import { eq as eq21 } from "drizzle-orm";
5386
5476
 
5387
5477
  // src/commands/backlog/move-repo/confirmMove.ts
5388
5478
  import chalk58 from "chalk";
@@ -5397,9 +5487,9 @@ async function confirmMove(cnt, oldOrigin, newOrigin) {
5397
5487
  }
5398
5488
 
5399
5489
  // src/commands/backlog/move-repo/countByOrigin.ts
5400
- import { count as count3, eq as eq18 } from "drizzle-orm";
5490
+ import { count as count3, eq as eq20 } from "drizzle-orm";
5401
5491
  async function countByOrigin(orm, origin) {
5402
- const [{ cnt }] = await orm.select({ cnt: count3() }).from(items).where(eq18(items.origin, origin));
5492
+ const [{ cnt }] = await orm.select({ cnt: count3() }).from(items).where(eq20(items.origin, origin));
5403
5493
  return cnt;
5404
5494
  }
5405
5495
 
@@ -5442,7 +5532,7 @@ async function moveRepo(oldOriginRaw, newOriginRaw, options2 = {}) {
5442
5532
  console.log(chalk59.yellow("Move cancelled; no changes made."));
5443
5533
  return;
5444
5534
  }
5445
- await orm.update(items).set({ origin: newOrigin }).where(eq19(items.origin, oldOrigin));
5535
+ await orm.update(items).set({ origin: newOrigin }).where(eq21(items.origin, oldOrigin));
5446
5536
  console.log(
5447
5537
  chalk59.green(
5448
5538
  `Moved ${pluralItems(cnt)} from "${oldOrigin}" to "${newOrigin}".`
@@ -5482,9 +5572,9 @@ import chalk61 from "chalk";
5482
5572
  // src/commands/backlog/tryRunById.ts
5483
5573
  import chalk60 from "chalk";
5484
5574
  async function tryRunById(id, options2) {
5485
- const items2 = await loadBacklog();
5486
5575
  const numericId = Number.parseInt(id, 10);
5487
- const item = Number.isNaN(numericId) ? void 0 : items2.find((i) => i.id === numericId);
5576
+ const { orm } = await getReady();
5577
+ const item = Number.isNaN(numericId) ? void 0 : await loadItem(orm, numericId);
5488
5578
  if (!item) {
5489
5579
  console.log(chalk60.red(`Item #${id} not found.`));
5490
5580
  return false;
@@ -5497,7 +5587,8 @@ async function tryRunById(id, options2) {
5497
5587
  console.log(chalk60.red(`Item #${id} is marked won't do.`));
5498
5588
  return false;
5499
5589
  }
5500
- if (isBlocked(item, items2)) {
5590
+ const hasDeps = (item.links ?? []).some((l) => l.type === "depends-on");
5591
+ if (hasDeps && isBlocked(item, await loadItemSummaries(orm, getOrigin()))) {
5501
5592
  console.log(
5502
5593
  chalk60.red(`Item #${id} is blocked by unresolved dependencies.`)
5503
5594
  );
@@ -5511,10 +5602,18 @@ Running backlog item #${id}...
5511
5602
  }
5512
5603
 
5513
5604
  // src/commands/backlog/launchMode.ts
5605
+ function buildSlashCommand(slashCommand, description) {
5606
+ const trimmed = description?.trim();
5607
+ return trimmed ? `/${slashCommand} ${trimmed}` : `/${slashCommand}`;
5608
+ }
5514
5609
  async function launchMode(slashCommand, options2) {
5515
5610
  pullIfConfigured();
5516
- process.env.ASSIST_SESSION_ID = String(process.pid);
5517
- const { child, done: done2 } = spawnClaude(`/${slashCommand}`, { allowEdits: true });
5611
+ process.env.ASSIST_SESSION_ID ??= String(process.pid);
5612
+ emitActivity({ kind: "command", name: slashCommand });
5613
+ const { child, done: done2 } = spawnClaude(
5614
+ buildSlashCommand(slashCommand, options2?.description),
5615
+ { allowEdits: true }
5616
+ );
5518
5617
  watchForMarker(child, { actOnDone: options2?.once });
5519
5618
  await done2;
5520
5619
  stopWatching();
@@ -5531,7 +5630,7 @@ async function launchMode(slashCommand, options2) {
5531
5630
 
5532
5631
  // src/commands/backlog/refine.ts
5533
5632
  async function pickItemForRefine() {
5534
- const items2 = await loadBacklog();
5633
+ const items2 = await loadBacklogSummaries();
5535
5634
  const active = items2.filter(
5536
5635
  (i) => i.status === "todo" || i.status === "in-progress"
5537
5636
  );
@@ -5706,10 +5805,10 @@ async function start(id) {
5706
5805
 
5707
5806
  // src/commands/backlog/stop/index.ts
5708
5807
  import chalk68 from "chalk";
5709
- import { and as and5, eq as eq20 } from "drizzle-orm";
5808
+ import { and as and5, eq as eq22 } from "drizzle-orm";
5710
5809
  async function stop() {
5711
5810
  const { orm } = await getReady();
5712
- const stopped = await orm.update(items).set({ status: "todo", currentPhase: 1 }).where(and5(eq20(items.status, "in-progress"), eq20(items.origin, getOrigin()))).returning({ id: items.id, name: items.name });
5811
+ const stopped = await orm.update(items).set({ status: "todo", currentPhase: 1 }).where(and5(eq22(items.status, "in-progress"), eq22(items.origin, getOrigin()))).returning({ id: items.id, name: items.name });
5713
5812
  if (stopped.length === 0) {
5714
5813
  console.log(chalk68.yellow("No in-progress items to stop."));
5715
5814
  return;
@@ -5744,18 +5843,18 @@ function registerStatusCommands(cmd) {
5744
5843
 
5745
5844
  // src/commands/backlog/removePhase.ts
5746
5845
  import chalk71 from "chalk";
5747
- import { and as and8, eq as eq23 } from "drizzle-orm";
5846
+ import { and as and8, eq as eq25 } from "drizzle-orm";
5748
5847
 
5749
5848
  // src/commands/backlog/findPhase.ts
5750
5849
  import chalk70 from "chalk";
5751
- import { and as and6, count as count4, eq as eq21 } from "drizzle-orm";
5850
+ import { and as and6, count as count4, eq as eq23 } from "drizzle-orm";
5752
5851
  async function findPhase(id, phase) {
5753
5852
  const found = await findOneItem(id);
5754
5853
  if (!found) return void 0;
5755
5854
  const { orm, item } = found;
5756
5855
  const itemId = item.id;
5757
5856
  const phaseIdx = Number.parseInt(phase, 10) - 1;
5758
- const [row] = await orm.select({ cnt: count4() }).from(planPhases).where(and6(eq21(planPhases.itemId, itemId), eq21(planPhases.idx, phaseIdx)));
5857
+ const [row] = await orm.select({ cnt: count4() }).from(planPhases).where(and6(eq23(planPhases.itemId, itemId), eq23(planPhases.idx, phaseIdx)));
5759
5858
  if (!row || row.cnt === 0) {
5760
5859
  console.log(
5761
5860
  chalk70.red(`Phase ${phaseIdx + 1} not found on item #${itemId}.`)
@@ -5767,14 +5866,14 @@ async function findPhase(id, phase) {
5767
5866
  }
5768
5867
 
5769
5868
  // src/commands/backlog/reindexPhases.ts
5770
- import { and as and7, asc as asc4, count as count5, eq as eq22 } from "drizzle-orm";
5869
+ import { and as and7, asc as asc5, count as count5, eq as eq24 } from "drizzle-orm";
5771
5870
  async function reindexPhases(db, itemId) {
5772
- const remaining = await db.select({ idx: planPhases.idx }).from(planPhases).where(eq22(planPhases.itemId, itemId)).orderBy(asc4(planPhases.idx));
5871
+ const remaining = await db.select({ idx: planPhases.idx }).from(planPhases).where(eq24(planPhases.itemId, itemId)).orderBy(asc5(planPhases.idx));
5773
5872
  for (let i = 0; i < remaining.length; i++) {
5774
5873
  const oldIdx = remaining[i].idx;
5775
5874
  if (oldIdx === i) continue;
5776
- await db.update(planTasks).set({ phaseIdx: i }).where(and7(eq22(planTasks.itemId, itemId), eq22(planTasks.phaseIdx, oldIdx)));
5777
- await db.update(planPhases).set({ idx: i }).where(and7(eq22(planPhases.itemId, itemId), eq22(planPhases.idx, oldIdx)));
5875
+ await db.update(planTasks).set({ phaseIdx: i }).where(and7(eq24(planTasks.itemId, itemId), eq24(planTasks.phaseIdx, oldIdx)));
5876
+ await db.update(planPhases).set({ idx: i }).where(and7(eq24(planPhases.itemId, itemId), eq24(planPhases.idx, oldIdx)));
5778
5877
  }
5779
5878
  }
5780
5879
  async function adjustCurrentPhase(db, item, removedIdx) {
@@ -5782,13 +5881,13 @@ async function adjustCurrentPhase(db, item, removedIdx) {
5782
5881
  if (currentPhase === void 0) return;
5783
5882
  const currentIdx = currentPhase - 1;
5784
5883
  if (removedIdx < currentIdx) {
5785
- await db.update(items).set({ currentPhase: currentPhase - 1 }).where(eq22(items.id, item.id));
5884
+ await db.update(items).set({ currentPhase: currentPhase - 1 }).where(eq24(items.id, item.id));
5786
5885
  return;
5787
5886
  }
5788
5887
  if (removedIdx !== currentIdx) return;
5789
- const [row] = await db.select({ cnt: count5() }).from(planPhases).where(eq22(planPhases.itemId, item.id));
5888
+ const [row] = await db.select({ cnt: count5() }).from(planPhases).where(eq24(planPhases.itemId, item.id));
5790
5889
  const cnt = row?.cnt ?? 0;
5791
- await db.update(items).set({ currentPhase: cnt === 0 ? null : Math.min(currentPhase, cnt) }).where(eq22(items.id, item.id));
5890
+ await db.update(items).set({ currentPhase: cnt === 0 ? null : Math.min(currentPhase, cnt) }).where(eq24(items.id, item.id));
5792
5891
  }
5793
5892
 
5794
5893
  // src/commands/backlog/removePhase.ts
@@ -5798,9 +5897,9 @@ async function removePhase(id, phase) {
5798
5897
  const { item, orm, itemId, phaseIdx } = found;
5799
5898
  await orm.transaction(async (tx) => {
5800
5899
  await tx.delete(planTasks).where(
5801
- and8(eq23(planTasks.itemId, itemId), eq23(planTasks.phaseIdx, phaseIdx))
5900
+ and8(eq25(planTasks.itemId, itemId), eq25(planTasks.phaseIdx, phaseIdx))
5802
5901
  );
5803
- await tx.delete(planPhases).where(and8(eq23(planPhases.itemId, itemId), eq23(planPhases.idx, phaseIdx)));
5902
+ await tx.delete(planPhases).where(and8(eq25(planPhases.itemId, itemId), eq25(planPhases.idx, phaseIdx)));
5804
5903
  await reindexPhases(tx, itemId);
5805
5904
  await adjustCurrentPhase(tx, item, phaseIdx);
5806
5905
  });
@@ -5811,7 +5910,7 @@ async function removePhase(id, phase) {
5811
5910
 
5812
5911
  // src/commands/backlog/update/index.ts
5813
5912
  import chalk73 from "chalk";
5814
- import { eq as eq24 } from "drizzle-orm";
5913
+ import { eq as eq26 } from "drizzle-orm";
5815
5914
 
5816
5915
  // src/commands/backlog/update/parseListIndex.ts
5817
5916
  function parseListIndex(raw, length, label2) {
@@ -5945,7 +6044,7 @@ async function update(id, options2) {
5945
6044
  if (!built) return;
5946
6045
  const { orm } = found;
5947
6046
  const itemId = found.item.id;
5948
- await orm.update(items).set(built.set).where(eq24(items.id, itemId));
6047
+ await orm.update(items).set(built.set).where(eq26(items.id, itemId));
5949
6048
  console.log(chalk73.green(`Updated ${built.fields} on item #${itemId}.`));
5950
6049
  }
5951
6050
 
@@ -5953,22 +6052,22 @@ async function update(id, options2) {
5953
6052
  import chalk74 from "chalk";
5954
6053
 
5955
6054
  // src/commands/backlog/applyPhaseUpdate.ts
5956
- import { and as and9, eq as eq25 } from "drizzle-orm";
6055
+ import { and as and9, eq as eq27 } from "drizzle-orm";
5957
6056
  async function applyPhaseUpdate(orm, itemId, phaseIdx, fields) {
5958
6057
  await orm.transaction(async (tx) => {
5959
6058
  if (fields.name) {
5960
6059
  await tx.update(planPhases).set({ name: fields.name }).where(
5961
- and9(eq25(planPhases.itemId, itemId), eq25(planPhases.idx, phaseIdx))
6060
+ and9(eq27(planPhases.itemId, itemId), eq27(planPhases.idx, phaseIdx))
5962
6061
  );
5963
6062
  }
5964
6063
  if (fields.manualCheck) {
5965
6064
  await tx.update(planPhases).set({ manualChecks: JSON.stringify(fields.manualCheck) }).where(
5966
- and9(eq25(planPhases.itemId, itemId), eq25(planPhases.idx, phaseIdx))
6065
+ and9(eq27(planPhases.itemId, itemId), eq27(planPhases.idx, phaseIdx))
5967
6066
  );
5968
6067
  }
5969
6068
  if (fields.task) {
5970
6069
  await tx.delete(planTasks).where(
5971
- and9(eq25(planTasks.itemId, itemId), eq25(planTasks.phaseIdx, phaseIdx))
6070
+ and9(eq27(planTasks.itemId, itemId), eq27(planTasks.phaseIdx, phaseIdx))
5972
6071
  );
5973
6072
  if (fields.task.length) {
5974
6073
  await tx.insert(planTasks).values(
@@ -6258,13 +6357,13 @@ function stripEnvPrefix(parts) {
6258
6357
  }
6259
6358
 
6260
6359
  // src/commands/cliHook/logDeniedToolCall.ts
6261
- import { mkdirSync as mkdirSync5 } from "fs";
6360
+ import { mkdirSync as mkdirSync6 } from "fs";
6262
6361
  import { homedir as homedir4 } from "os";
6263
- import { join as join18 } from "path";
6362
+ import { join as join19 } from "path";
6264
6363
  import Database from "better-sqlite3";
6265
6364
  var _db;
6266
6365
  function getDbDir() {
6267
- return join18(homedir4(), ".assist");
6366
+ return join19(homedir4(), ".assist");
6268
6367
  }
6269
6368
  function initSchema(db) {
6270
6369
  db.exec(`
@@ -6282,8 +6381,8 @@ function initSchema(db) {
6282
6381
  function openPromptsDb(dir) {
6283
6382
  if (_db) return _db;
6284
6383
  const dbDir = dir ?? getDbDir();
6285
- mkdirSync5(dbDir, { recursive: true });
6286
- const db = new Database(join18(dbDir, "assist.db"));
6384
+ mkdirSync6(dbDir, { recursive: true });
6385
+ const db = new Database(join19(dbDir, "assist.db"));
6287
6386
  db.pragma("journal_mode = WAL");
6288
6387
  initSchema(db);
6289
6388
  _db = db;
@@ -6385,17 +6484,17 @@ function extractGraphqlQuery(args) {
6385
6484
  }
6386
6485
 
6387
6486
  // src/shared/loadCliReads.ts
6388
- import { existsSync as existsSync21, readFileSync as readFileSync15, writeFileSync as writeFileSync14 } from "fs";
6389
- import { dirname as dirname16, resolve as resolve7 } from "path";
6487
+ import { existsSync as existsSync21, readFileSync as readFileSync16, writeFileSync as writeFileSync15 } from "fs";
6488
+ import { dirname as dirname17, resolve as resolve7 } from "path";
6390
6489
  import { fileURLToPath as fileURLToPath5 } from "url";
6391
6490
  var __filename3 = fileURLToPath5(import.meta.url);
6392
- var __dirname5 = dirname16(__filename3);
6491
+ var __dirname5 = dirname17(__filename3);
6393
6492
  function packageRoot() {
6394
6493
  return __dirname5;
6395
6494
  }
6396
- function readLines(path54) {
6397
- if (!existsSync21(path54)) return [];
6398
- return readFileSync15(path54, "utf-8").split("\n").filter((line) => line.trim() !== "");
6495
+ function readLines(path53) {
6496
+ if (!existsSync21(path53)) return [];
6497
+ return readFileSync16(path53, "utf-8").split("\n").filter((line) => line.trim() !== "");
6399
6498
  }
6400
6499
  var cachedReads;
6401
6500
  var cachedWrites;
@@ -6415,7 +6514,7 @@ function loadCliReads() {
6415
6514
  return getCliReadsLines();
6416
6515
  }
6417
6516
  function saveCliReads(commands) {
6418
- writeFileSync14(
6517
+ writeFileSync15(
6419
6518
  resolve7(packageRoot(), "allowed.cli-reads"),
6420
6519
  `${commands.join("\n")}
6421
6520
  `
@@ -6441,14 +6540,14 @@ function findCliWrite(command) {
6441
6540
  }
6442
6541
 
6443
6542
  // src/shared/readSettingsPerms.ts
6444
- import { existsSync as existsSync22, readFileSync as readFileSync16 } from "fs";
6543
+ import { existsSync as existsSync22, readFileSync as readFileSync17 } from "fs";
6445
6544
  import { homedir as homedir5 } from "os";
6446
- import { join as join19 } from "path";
6545
+ import { join as join20 } from "path";
6447
6546
  function readSettingsPerms(key) {
6448
6547
  const paths = [
6449
- join19(homedir5(), ".claude", "settings.json"),
6450
- join19(process.cwd(), ".claude", "settings.json"),
6451
- join19(process.cwd(), ".claude", "settings.local.json")
6548
+ join20(homedir5(), ".claude", "settings.json"),
6549
+ join20(process.cwd(), ".claude", "settings.json"),
6550
+ join20(process.cwd(), ".claude", "settings.local.json")
6452
6551
  ];
6453
6552
  const entries = [];
6454
6553
  for (const p of paths) {
@@ -6459,7 +6558,7 @@ function readSettingsPerms(key) {
6459
6558
  function readPermissionArray(filePath, key) {
6460
6559
  if (!existsSync22(filePath)) return [];
6461
6560
  try {
6462
- const data = JSON.parse(readFileSync16(filePath, "utf-8"));
6561
+ const data = JSON.parse(readFileSync17(filePath, "utf-8"));
6463
6562
  const arr = data?.permissions?.[key];
6464
6563
  return Array.isArray(arr) ? arr.filter((e) => typeof e === "string") : [];
6465
6564
  } catch {
@@ -6739,9 +6838,9 @@ ${reasons.join("\n")}`);
6739
6838
  }
6740
6839
 
6741
6840
  // src/commands/permitCliReads/index.ts
6742
- import { existsSync as existsSync23, mkdirSync as mkdirSync6, readFileSync as readFileSync17, writeFileSync as writeFileSync15 } from "fs";
6841
+ import { existsSync as existsSync23, mkdirSync as mkdirSync7, readFileSync as readFileSync18, writeFileSync as writeFileSync16 } from "fs";
6743
6842
  import { homedir as homedir6 } from "os";
6744
- import { join as join20 } from "path";
6843
+ import { join as join21 } from "path";
6745
6844
 
6746
6845
  // src/shared/checkCliAvailable.ts
6747
6846
  import { execSync as execSync19 } from "child_process";
@@ -6878,14 +6977,14 @@ function showProgress(p, label2) {
6878
6977
  const pct = Math.round(p.done / p.total * 100);
6879
6978
  process.stderr.write(`\r\x1B[K[${pct}%] Scanning ${label2}...`);
6880
6979
  }
6881
- async function resolveCommand(cli, path54, description, depth, p) {
6882
- showProgress(p, path54.join(" "));
6883
- const subHelp = await runHelp([cli, ...path54]);
6980
+ async function resolveCommand(cli, path53, description, depth, p) {
6981
+ showProgress(p, path53.join(" "));
6982
+ const subHelp = await runHelp([cli, ...path53]);
6884
6983
  if (!subHelp || !hasSubcommands(subHelp)) {
6885
- return [{ path: path54, description }];
6984
+ return [{ path: path53, description }];
6886
6985
  }
6887
- const children = await discoverAt(cli, path54, depth + 1, p);
6888
- return children.length > 0 ? children : [{ path: path54, description }];
6986
+ const children = await discoverAt(cli, path53, depth + 1, p);
6987
+ return children.length > 0 ? children : [{ path: path53, description }];
6889
6988
  }
6890
6989
  async function discoverAt(cli, parentPath, depth, p) {
6891
6990
  if (depth > SAFETY_DEPTH) return [];
@@ -7030,17 +7129,17 @@ function updateSettings(cli, commands) {
7030
7129
  // src/commands/permitCliReads/index.ts
7031
7130
  function logPath(cli) {
7032
7131
  const safeName = cli.replace(/\s+/g, "-");
7033
- return join20(homedir6(), ".assist", `cli-discover-${safeName}.log`);
7132
+ return join21(homedir6(), ".assist", `cli-discover-${safeName}.log`);
7034
7133
  }
7035
7134
  function readCache(cli) {
7036
- const path54 = logPath(cli);
7037
- if (!existsSync23(path54)) return void 0;
7038
- return readFileSync17(path54, "utf-8");
7135
+ const path53 = logPath(cli);
7136
+ if (!existsSync23(path53)) return void 0;
7137
+ return readFileSync18(path53, "utf-8");
7039
7138
  }
7040
7139
  function writeCache(cli, output) {
7041
- const dir = join20(homedir6(), ".assist");
7042
- mkdirSync6(dir, { recursive: true });
7043
- writeFileSync15(logPath(cli), output);
7140
+ const dir = join21(homedir6(), ".assist");
7141
+ mkdirSync7(dir, { recursive: true });
7142
+ writeFileSync16(logPath(cli), output);
7044
7143
  }
7045
7144
  async function permitCliReads(cli, options2 = { noCache: false }) {
7046
7145
  if (!cli) {
@@ -7634,6 +7733,11 @@ async function analyze(pattern2) {
7634
7733
  await halstead(file);
7635
7734
  console.log();
7636
7735
  console.log(chalk84.bold.underline("Maintainability Index"));
7736
+ console.log(
7737
+ chalk84.dim(
7738
+ "171 - 5.2*ln(HalsteadVolume) - 0.23*CyclomaticComplexity - 16.2*ln(SLOC), clamped 0-100"
7739
+ )
7740
+ );
7637
7741
  await maintainability(file);
7638
7742
  return;
7639
7743
  }
@@ -7700,8 +7804,8 @@ function stepIntoNested(container, key, nextKey) {
7700
7804
  }
7701
7805
  return ensureObject(container, resolved);
7702
7806
  }
7703
- function setNestedValue(obj, path54, value) {
7704
- const keys = path54.split(".");
7807
+ function setNestedValue(obj, path53, value) {
7808
+ const keys = path53.split(".");
7705
7809
  const result = { ...obj };
7706
7810
  let current = result;
7707
7811
  for (let i = 0; i < keys.length - 1; i++) {
@@ -7781,9 +7885,9 @@ function isTraversable(value) {
7781
7885
  function stepInto(current, key) {
7782
7886
  return isTraversable(current) ? current[key] : void 0;
7783
7887
  }
7784
- function getNestedValue(obj, path54) {
7888
+ function getNestedValue(obj, path53) {
7785
7889
  let current = obj;
7786
- for (const key of path54.split(".")) current = stepInto(current, key);
7890
+ for (const key of path53.split(".")) current = stepInto(current, key);
7787
7891
  return current;
7788
7892
  }
7789
7893
 
@@ -7817,7 +7921,7 @@ function registerConfig(program2) {
7817
7921
  }
7818
7922
 
7819
7923
  // src/commands/deploy/redirect.ts
7820
- import { existsSync as existsSync24, readFileSync as readFileSync18, writeFileSync as writeFileSync16 } from "fs";
7924
+ import { existsSync as existsSync24, readFileSync as readFileSync19, writeFileSync as writeFileSync17 } from "fs";
7821
7925
  import chalk87 from "chalk";
7822
7926
  var TRAILING_SLASH_SCRIPT = ` <script>
7823
7927
  if (!window.location.pathname.endsWith('/')) {
@@ -7830,7 +7934,7 @@ function redirect() {
7830
7934
  console.log(chalk87.yellow("No index.html found"));
7831
7935
  return;
7832
7936
  }
7833
- const content = readFileSync18(indexPath, "utf-8");
7937
+ const content = readFileSync19(indexPath, "utf-8");
7834
7938
  if (content.includes("window.location.pathname.endsWith('/')")) {
7835
7939
  console.log(chalk87.dim("Trailing slash script already present"));
7836
7940
  return;
@@ -7841,7 +7945,7 @@ function redirect() {
7841
7945
  return;
7842
7946
  }
7843
7947
  const newContent = content.slice(0, headCloseIndex) + TRAILING_SLASH_SCRIPT + "\n " + content.slice(headCloseIndex);
7844
- writeFileSync16(indexPath, newContent);
7948
+ writeFileSync17(indexPath, newContent);
7845
7949
  console.log(chalk87.green("Added trailing slash redirect to index.html"));
7846
7950
  }
7847
7951
 
@@ -7858,10 +7962,10 @@ import { basename as basename4 } from "path";
7858
7962
 
7859
7963
  // src/commands/devlog/loadBlogSkipDays.ts
7860
7964
  import { homedir as homedir7 } from "os";
7861
- import { join as join21 } from "path";
7862
- var BLOG_REPO_ROOT = join21(homedir7(), "git/blog");
7965
+ import { join as join22 } from "path";
7966
+ var BLOG_REPO_ROOT = join22(homedir7(), "git/blog");
7863
7967
  function loadBlogSkipDays(repoName) {
7864
- const config = loadRawYaml(join21(BLOG_REPO_ROOT, "assist.yml"));
7968
+ const config = loadRawYaml(join22(BLOG_REPO_ROOT, "assist.yml"));
7865
7969
  const devlog = config.devlog;
7866
7970
  const skip2 = devlog?.skip;
7867
7971
  return new Set(skip2?.[repoName] ?? []);
@@ -7872,17 +7976,17 @@ import { execSync as execSync20 } from "child_process";
7872
7976
  import chalk88 from "chalk";
7873
7977
 
7874
7978
  // src/shared/getRepoName.ts
7875
- import { existsSync as existsSync25, readFileSync as readFileSync19 } from "fs";
7876
- import { basename as basename3, join as join22 } from "path";
7979
+ import { existsSync as existsSync25, readFileSync as readFileSync20 } from "fs";
7980
+ import { basename as basename3, join as join23 } from "path";
7877
7981
  function getRepoName() {
7878
7982
  const config = loadConfig();
7879
7983
  if (config.devlog?.name) {
7880
7984
  return config.devlog.name;
7881
7985
  }
7882
- const packageJsonPath = join22(process.cwd(), "package.json");
7986
+ const packageJsonPath = join23(process.cwd(), "package.json");
7883
7987
  if (existsSync25(packageJsonPath)) {
7884
7988
  try {
7885
- const content = readFileSync19(packageJsonPath, "utf-8");
7989
+ const content = readFileSync20(packageJsonPath, "utf-8");
7886
7990
  const pkg = JSON.parse(content);
7887
7991
  if (pkg.name) {
7888
7992
  return pkg.name;
@@ -7894,9 +7998,9 @@ function getRepoName() {
7894
7998
  }
7895
7999
 
7896
8000
  // src/commands/devlog/loadDevlogEntries.ts
7897
- import { readdirSync, readFileSync as readFileSync20 } from "fs";
7898
- import { join as join23 } from "path";
7899
- var DEVLOG_DIR = join23(BLOG_REPO_ROOT, "src/content/devlog");
8001
+ import { readdirSync, readFileSync as readFileSync21 } from "fs";
8002
+ import { join as join24 } from "path";
8003
+ var DEVLOG_DIR = join24(BLOG_REPO_ROOT, "src/content/devlog");
7900
8004
  function extractFrontmatter(content) {
7901
8005
  const fm = content.match(/^---\n([\s\S]*?)\n---/);
7902
8006
  return fm?.[1] ?? null;
@@ -7924,7 +8028,7 @@ function readDevlogFiles(callback) {
7924
8028
  try {
7925
8029
  const files = readdirSync(DEVLOG_DIR).filter((f) => f.endsWith(".md"));
7926
8030
  for (const file of files) {
7927
- const content = readFileSync20(join23(DEVLOG_DIR, file), "utf-8");
8031
+ const content = readFileSync21(join24(DEVLOG_DIR, file), "utf-8");
7928
8032
  const parsed = parseFrontmatter(content, file);
7929
8033
  if (parsed) callback(parsed);
7930
8034
  }
@@ -8311,12 +8415,12 @@ function repos(options2) {
8311
8415
  }
8312
8416
 
8313
8417
  // src/commands/devlog/skip.ts
8314
- import { writeFileSync as writeFileSync17 } from "fs";
8315
- import { join as join24 } from "path";
8418
+ import { writeFileSync as writeFileSync18 } from "fs";
8419
+ import { join as join25 } from "path";
8316
8420
  import chalk93 from "chalk";
8317
8421
  import { stringify as stringifyYaml3 } from "yaml";
8318
8422
  function getBlogConfigPath() {
8319
- return join24(BLOG_REPO_ROOT, "assist.yml");
8423
+ return join25(BLOG_REPO_ROOT, "assist.yml");
8320
8424
  }
8321
8425
  function skip(date) {
8322
8426
  if (!/^\d{4}-\d{2}-\d{2}$/.test(date)) {
@@ -8340,7 +8444,7 @@ function skip(date) {
8340
8444
  skip2[repoName] = skipDays;
8341
8445
  devlog.skip = skip2;
8342
8446
  config.devlog = devlog;
8343
- writeFileSync17(configPath, stringifyYaml3(config, { lineWidth: 0 }));
8447
+ writeFileSync18(configPath, stringifyYaml3(config, { lineWidth: 0 }));
8344
8448
  console.log(chalk93.green(`Added ${date} to skip list for ${repoName}`));
8345
8449
  }
8346
8450
 
@@ -8377,7 +8481,7 @@ function registerDevlog(program2) {
8377
8481
 
8378
8482
  // src/commands/dotnet/checkBuildLocks.ts
8379
8483
  import { closeSync as closeSync2, openSync as openSync2, readdirSync as readdirSync2 } from "fs";
8380
- import { join as join25 } from "path";
8484
+ import { join as join26 } from "path";
8381
8485
  import chalk95 from "chalk";
8382
8486
 
8383
8487
  // src/shared/findRepoRoot.ts
@@ -8405,7 +8509,7 @@ function isLockedDll(debugDir) {
8405
8509
  }
8406
8510
  for (const file of files) {
8407
8511
  if (!file.toLowerCase().endsWith(".dll")) continue;
8408
- const dllPath = join25(debugDir, file);
8512
+ const dllPath = join26(debugDir, file);
8409
8513
  try {
8410
8514
  const fd = openSync2(dllPath, "r+");
8411
8515
  closeSync2(fd);
@@ -8423,13 +8527,13 @@ function findFirstLockedDll(dir) {
8423
8527
  return null;
8424
8528
  }
8425
8529
  if (entries.includes("bin")) {
8426
- const locked = isLockedDll(join25(dir, "bin", "Debug"));
8530
+ const locked = isLockedDll(join26(dir, "bin", "Debug"));
8427
8531
  if (locked) return locked;
8428
8532
  }
8429
8533
  for (const entry of entries) {
8430
8534
  if (SKIP_DIRS.has(entry) || entry === "bin" || entry.startsWith("."))
8431
8535
  continue;
8432
- const found = findFirstLockedDll(join25(dir, entry));
8536
+ const found = findFirstLockedDll(join26(dir, entry));
8433
8537
  if (found) return found;
8434
8538
  }
8435
8539
  return null;
@@ -8452,11 +8556,11 @@ async function checkBuildLocksCommand() {
8452
8556
  }
8453
8557
 
8454
8558
  // src/commands/dotnet/buildTree.ts
8455
- import { readFileSync as readFileSync21 } from "fs";
8559
+ import { readFileSync as readFileSync22 } from "fs";
8456
8560
  import path21 from "path";
8457
8561
  var PROJECT_REF_RE = /<ProjectReference\s+Include="([^"]+)"/g;
8458
8562
  function getProjectRefs(csprojPath) {
8459
- const content = readFileSync21(csprojPath, "utf-8");
8563
+ const content = readFileSync22(csprojPath, "utf-8");
8460
8564
  const refs = [];
8461
8565
  for (const match of content.matchAll(PROJECT_REF_RE)) {
8462
8566
  refs.push(match[1].replace(/\\/g, "/"));
@@ -8473,7 +8577,7 @@ function buildTree(csprojPath, repoRoot, visited = /* @__PURE__ */ new Set()) {
8473
8577
  for (const ref of getProjectRefs(abs)) {
8474
8578
  const childAbs = path21.resolve(dir, ref);
8475
8579
  try {
8476
- readFileSync21(childAbs);
8580
+ readFileSync22(childAbs);
8477
8581
  node.children.push(buildTree(childAbs, repoRoot, visited));
8478
8582
  } catch {
8479
8583
  node.children.push({
@@ -8498,7 +8602,7 @@ function collectAllDeps(node) {
8498
8602
  }
8499
8603
 
8500
8604
  // src/commands/dotnet/findContainingSolutions.ts
8501
- import { readdirSync as readdirSync3, readFileSync as readFileSync22, statSync as statSync2 } from "fs";
8605
+ import { readdirSync as readdirSync3, readFileSync as readFileSync23, statSync as statSync2 } from "fs";
8502
8606
  import path22 from "path";
8503
8607
  function findSlnFiles(dir, maxDepth, depth = 0) {
8504
8608
  if (depth > maxDepth) return [];
@@ -8533,7 +8637,7 @@ function findContainingSolutions(csprojPath, repoRoot) {
8533
8637
  const pattern2 = new RegExp(`[\\\\"/]${escapeRegex(csprojBasename)}"`);
8534
8638
  for (const sln of slnFiles) {
8535
8639
  try {
8536
- const content = readFileSync22(sln, "utf-8");
8640
+ const content = readFileSync23(sln, "utf-8");
8537
8641
  if (pattern2.test(content)) {
8538
8642
  matches.push(path22.relative(repoRoot, sln));
8539
8643
  }
@@ -8776,11 +8880,11 @@ import chalk101 from "chalk";
8776
8880
 
8777
8881
  // src/commands/dotnet/findSolution.ts
8778
8882
  import { readdirSync as readdirSync4 } from "fs";
8779
- import { dirname as dirname17, join as join26 } from "path";
8883
+ import { dirname as dirname18, join as join27 } from "path";
8780
8884
  import chalk100 from "chalk";
8781
8885
  function findSlnInDir(dir) {
8782
8886
  try {
8783
- return readdirSync4(dir).filter((f) => f.endsWith(".sln")).map((f) => join26(dir, f));
8887
+ return readdirSync4(dir).filter((f) => f.endsWith(".sln")).map((f) => join27(dir, f));
8784
8888
  } catch {
8785
8889
  return [];
8786
8890
  }
@@ -8801,7 +8905,7 @@ function findSolution() {
8801
8905
  process.exit(1);
8802
8906
  }
8803
8907
  if (current === ceiling) break;
8804
- current = dirname17(current);
8908
+ current = dirname18(current);
8805
8909
  }
8806
8910
  console.error(chalk100.red("No .sln file found between cwd and repo root"));
8807
8911
  process.exit(1);
@@ -8851,7 +8955,7 @@ function parseInspectReport(json) {
8851
8955
 
8852
8956
  // src/commands/dotnet/runInspectCode.ts
8853
8957
  import { execSync as execSync24 } from "child_process";
8854
- import { existsSync as existsSync29, readFileSync as readFileSync23, unlinkSync as unlinkSync6 } from "fs";
8958
+ import { existsSync as existsSync29, readFileSync as readFileSync24, unlinkSync as unlinkSync6 } from "fs";
8855
8959
  import { tmpdir as tmpdir3 } from "os";
8856
8960
  import path25 from "path";
8857
8961
  import chalk102 from "chalk";
@@ -8886,7 +8990,7 @@ function runInspectCode(slnPath, include, swea) {
8886
8990
  console.error(chalk102.red("Report file not generated"));
8887
8991
  process.exit(1);
8888
8992
  }
8889
- const xml = readFileSync23(reportPath, "utf-8");
8993
+ const xml = readFileSync24(reportPath, "utf-8");
8890
8994
  unlinkSync6(reportPath);
8891
8995
  return xml;
8892
8996
  }
@@ -9013,9 +9117,9 @@ function aggregateCommitters(authorLists) {
9013
9117
 
9014
9118
  // src/shared/runGhGraphql.ts
9015
9119
  import { spawnSync as spawnSync2 } from "child_process";
9016
- import { unlinkSync as unlinkSync7, writeFileSync as writeFileSync18 } from "fs";
9120
+ import { unlinkSync as unlinkSync7, writeFileSync as writeFileSync19 } from "fs";
9017
9121
  import { tmpdir as tmpdir4 } from "os";
9018
- import { join as join27 } from "path";
9122
+ import { join as join28 } from "path";
9019
9123
  function buildArgs(queryFile, vars) {
9020
9124
  const args = ["api", "graphql", "-F", `query=@${queryFile}`];
9021
9125
  for (const [key, value] of Object.entries(vars)) {
@@ -9025,8 +9129,8 @@ function buildArgs(queryFile, vars) {
9025
9129
  return args;
9026
9130
  }
9027
9131
  function runGhGraphql(mutation, vars) {
9028
- const queryFile = join27(tmpdir4(), `gh-query-${Date.now()}.graphql`);
9029
- writeFileSync18(queryFile, mutation);
9132
+ const queryFile = join28(tmpdir4(), `gh-query-${Date.now()}.graphql`);
9133
+ writeFileSync19(queryFile, mutation);
9030
9134
  try {
9031
9135
  const result = spawnSync2("gh", buildArgs(queryFile, vars), {
9032
9136
  encoding: "utf-8"
@@ -9203,8 +9307,8 @@ function registerGithub(program2) {
9203
9307
  }
9204
9308
 
9205
9309
  // src/commands/handover/archive.ts
9206
- import { existsSync as existsSync30, mkdirSync as mkdirSync7, renameSync as renameSync2 } from "fs";
9207
- import { join as join29 } from "path";
9310
+ import { existsSync as existsSync30, mkdirSync as mkdirSync8, renameSync as renameSync2 } from "fs";
9311
+ import { join as join30 } from "path";
9208
9312
 
9209
9313
  // src/commands/handover/formatArchiveTimestamp.ts
9210
9314
  function formatArchiveTimestamp(date = /* @__PURE__ */ new Date()) {
@@ -9219,9 +9323,9 @@ function formatArchiveTimestamp(date = /* @__PURE__ */ new Date()) {
9219
9323
  }
9220
9324
 
9221
9325
  // src/commands/handover/getHandoverArchiveDir.ts
9222
- import { join as join28 } from "path";
9326
+ import { join as join29 } from "path";
9223
9327
  function getHandoverArchiveDir(cwd = process.cwd()) {
9224
- return join28(cwd, ".assist", "handovers", "archive");
9328
+ return join29(cwd, ".assist", "handovers", "archive");
9225
9329
  }
9226
9330
 
9227
9331
  // src/commands/handover/archive.ts
@@ -9231,11 +9335,11 @@ function buildArchiveFilename(timestamp, suffix) {
9231
9335
  return `${base}.md`;
9232
9336
  }
9233
9337
  function resolveCollisionPath(archiveDir, timestamp, suffix) {
9234
- const initial = join29(archiveDir, buildArchiveFilename(timestamp, suffix));
9338
+ const initial = join30(archiveDir, buildArchiveFilename(timestamp, suffix));
9235
9339
  if (!existsSync30(initial)) return initial;
9236
9340
  for (let i = 1; i <= MAX_COLLISION_SUFFIX; i++) {
9237
9341
  const collisionSuffix = suffix ? `${suffix}-${i}` : `${i}`;
9238
- const candidate = join29(
9342
+ const candidate = join30(
9239
9343
  archiveDir,
9240
9344
  buildArchiveFilename(timestamp, collisionSuffix)
9241
9345
  );
@@ -9250,7 +9354,7 @@ function archive(options2 = {}) {
9250
9354
  const handoverPath = getHandoverPath(cwd);
9251
9355
  if (!existsSync30(handoverPath)) return void 0;
9252
9356
  const archiveDir = getHandoverArchiveDir(cwd);
9253
- mkdirSync7(archiveDir, { recursive: true });
9357
+ mkdirSync8(archiveDir, { recursive: true });
9254
9358
  const timestamp = formatArchiveTimestamp(options2.now);
9255
9359
  const destination = resolveCollisionPath(
9256
9360
  archiveDir,
@@ -9262,7 +9366,7 @@ function archive(options2 = {}) {
9262
9366
  }
9263
9367
 
9264
9368
  // src/commands/handover/load.ts
9265
- import { existsSync as existsSync31, readFileSync as readFileSync25 } from "fs";
9369
+ import { existsSync as existsSync31, readFileSync as readFileSync26 } from "fs";
9266
9370
 
9267
9371
  // src/commands/handover/parseLoadInput.ts
9268
9372
  async function parseLoadInput(stdin) {
@@ -9378,7 +9482,7 @@ function normaliseOutput(raw) {
9378
9482
  function loadFromHandover(cwd) {
9379
9483
  const handoverPath = getHandoverPath(cwd);
9380
9484
  if (!existsSync31(handoverPath)) return void 0;
9381
- const content = readFileSync25(handoverPath, "utf-8");
9485
+ const content = readFileSync26(handoverPath, "utf-8");
9382
9486
  archive({ cwd });
9383
9487
  return {
9384
9488
  additionalContext: content,
@@ -9545,20 +9649,20 @@ function acceptanceCriteria(issueKey) {
9545
9649
  import { execSync as execSync27 } from "child_process";
9546
9650
 
9547
9651
  // src/shared/loadJson.ts
9548
- import { existsSync as existsSync32, mkdirSync as mkdirSync8, readFileSync as readFileSync26, writeFileSync as writeFileSync19 } from "fs";
9652
+ import { existsSync as existsSync32, mkdirSync as mkdirSync9, readFileSync as readFileSync27, writeFileSync as writeFileSync20 } from "fs";
9549
9653
  import { homedir as homedir8 } from "os";
9550
- import { join as join30 } from "path";
9654
+ import { join as join31 } from "path";
9551
9655
  function getStoreDir() {
9552
- return join30(homedir8(), ".assist");
9656
+ return join31(homedir8(), ".assist");
9553
9657
  }
9554
9658
  function getStorePath(filename) {
9555
- return join30(getStoreDir(), filename);
9659
+ return join31(getStoreDir(), filename);
9556
9660
  }
9557
9661
  function loadJson(filename) {
9558
- const path54 = getStorePath(filename);
9559
- if (existsSync32(path54)) {
9662
+ const path53 = getStorePath(filename);
9663
+ if (existsSync32(path53)) {
9560
9664
  try {
9561
- return JSON.parse(readFileSync26(path54, "utf-8"));
9665
+ return JSON.parse(readFileSync27(path53, "utf-8"));
9562
9666
  } catch {
9563
9667
  return {};
9564
9668
  }
@@ -9568,9 +9672,9 @@ function loadJson(filename) {
9568
9672
  function saveJson(filename, data) {
9569
9673
  const dir = getStoreDir();
9570
9674
  if (!existsSync32(dir)) {
9571
- mkdirSync8(dir, { recursive: true });
9675
+ mkdirSync9(dir, { recursive: true });
9572
9676
  }
9573
- writeFileSync19(getStorePath(filename), JSON.stringify(data, null, 2));
9677
+ writeFileSync20(getStorePath(filename), JSON.stringify(data, null, 2));
9574
9678
  }
9575
9679
 
9576
9680
  // src/shared/promptInput.ts
@@ -9677,13 +9781,13 @@ function registerLaunch(program2) {
9677
9781
  program2.command("next").argument("[id]", "Backlog item ID to run first").description("Alias for backlog next").option("--once", "Exit after the first completed item run").action(
9678
9782
  (id, opts) => next({ allowEdits: true, once: opts.once }, id)
9679
9783
  );
9680
- program2.command("draft").alias("feat").description(
9784
+ program2.command("draft").alias("feat").argument("[description]", "Text to forward to the /draft slash command").description(
9681
9785
  "Launch Claude in /draft mode, chain into next on /next signal"
9682
9786
  ).option("--once", "Exit when the initial task completes").action(
9683
- (opts) => launchMode("draft", { once: opts.once })
9787
+ (description, opts) => launchMode("draft", { once: opts.once, description })
9684
9788
  );
9685
- program2.command("bug").description("Launch Claude in /bug mode, chain into next on /next signal").option("--once", "Exit when the initial task completes").action(
9686
- (opts) => launchMode("bug", { once: opts.once })
9789
+ program2.command("bug").argument("[description]", "Text to forward to the /bug slash command").description("Launch Claude in /bug mode, chain into next on /next signal").option("--once", "Exit when the initial task completes").action(
9790
+ (description, opts) => launchMode("bug", { once: opts.once, description })
9687
9791
  );
9688
9792
  program2.command("review-comments").argument("[number]", "PR number to check out first").description("Launch Claude in /review-comments mode (single session)").action((number) => reviewComments(number));
9689
9793
  program2.command("refine").argument("[id]", "Backlog item ID").description("Launch Claude in /refine mode to refine a backlog item").option("--once", "Exit when the initial task completes").action(
@@ -9703,12 +9807,12 @@ function registerList(program2) {
9703
9807
  }
9704
9808
 
9705
9809
  // src/commands/mermaid/index.ts
9706
- import { mkdirSync as mkdirSync9, readdirSync as readdirSync5 } from "fs";
9810
+ import { mkdirSync as mkdirSync10, readdirSync as readdirSync5 } from "fs";
9707
9811
  import { resolve as resolve10 } from "path";
9708
9812
  import chalk113 from "chalk";
9709
9813
 
9710
9814
  // src/commands/mermaid/exportFile.ts
9711
- import { readFileSync as readFileSync27, writeFileSync as writeFileSync20 } from "fs";
9815
+ import { readFileSync as readFileSync28, writeFileSync as writeFileSync21 } from "fs";
9712
9816
  import { basename as basename5, extname, resolve as resolve9 } from "path";
9713
9817
  import chalk112 from "chalk";
9714
9818
 
@@ -9734,7 +9838,7 @@ async function renderBlock(krokiUrl, source) {
9734
9838
 
9735
9839
  // src/commands/mermaid/exportFile.ts
9736
9840
  async function exportFile(file, outDir, krokiUrl, onlyIndex) {
9737
- const content = readFileSync27(file, "utf8");
9841
+ const content = readFileSync28(file, "utf8");
9738
9842
  const blocks = extractMermaidBlocks(content);
9739
9843
  const stem = basename5(file, extname(file));
9740
9844
  if (onlyIndex !== void 0) {
@@ -9759,7 +9863,7 @@ async function exportFile(file, outDir, krokiUrl, onlyIndex) {
9759
9863
  if (onlyIndex !== void 0 && idx !== onlyIndex) continue;
9760
9864
  const outPath = resolve9(outDir, `${stem}-${idx}.svg`);
9761
9865
  const svg = await renderBlock(krokiUrl, source);
9762
- writeFileSync20(outPath, svg, "utf8");
9866
+ writeFileSync21(outPath, svg, "utf8");
9763
9867
  console.log(chalk112.green(` \u2192 ${outPath}`));
9764
9868
  }
9765
9869
  }
@@ -9772,7 +9876,7 @@ function extractMermaidBlocks(markdown) {
9772
9876
  async function mermaidExport(file, options2 = {}) {
9773
9877
  const { mermaid } = loadConfig();
9774
9878
  const outDir = resolve10(process.cwd(), options2.out ?? ".");
9775
- mkdirSync9(outDir, { recursive: true });
9879
+ mkdirSync10(outDir, { recursive: true });
9776
9880
  if (options2.index !== void 0) {
9777
9881
  if (!Number.isInteger(options2.index) || options2.index < 1) {
9778
9882
  console.error(
@@ -10242,15 +10346,15 @@ function postComment(vars) {
10242
10346
  }
10243
10347
  runGhGraphql(MUTATION_MULTI, { ...base, startLine });
10244
10348
  }
10245
- function comment2(path54, line, body, startLine) {
10349
+ function comment2(path53, line, body, startLine) {
10246
10350
  validateBody(body);
10247
10351
  validateLine(line);
10248
10352
  if (startLine !== void 0) validateLine(startLine);
10249
10353
  try {
10250
10354
  const prId = getCurrentPrNodeId();
10251
- postComment({ prId, body, path: path54, line, startLine });
10355
+ postComment({ prId, body, path: path53, line, startLine });
10252
10356
  const range = startLine !== void 0 ? `${startLine}-${line}` : `${line}`;
10253
- console.log(`Added review comment on ${path54}:${range}`);
10357
+ console.log(`Added review comment on ${path53}:${range}`);
10254
10358
  } catch (error) {
10255
10359
  if (isGhNotInstalled(error)) {
10256
10360
  console.error("Error: GitHub CLI (gh) is not installed.");
@@ -10328,23 +10432,23 @@ import { execSync as execSync32 } from "child_process";
10328
10432
 
10329
10433
  // src/commands/prs/resolveCommentWithReply.ts
10330
10434
  import { execSync as execSync31 } from "child_process";
10331
- import { unlinkSync as unlinkSync9, writeFileSync as writeFileSync21 } from "fs";
10435
+ import { unlinkSync as unlinkSync9, writeFileSync as writeFileSync22 } from "fs";
10332
10436
  import { tmpdir as tmpdir5 } from "os";
10333
- import { join as join32 } from "path";
10437
+ import { join as join33 } from "path";
10334
10438
 
10335
10439
  // src/commands/prs/loadCommentsCache.ts
10336
- import { existsSync as existsSync33, readFileSync as readFileSync28, unlinkSync as unlinkSync8 } from "fs";
10337
- import { join as join31 } from "path";
10440
+ import { existsSync as existsSync33, readFileSync as readFileSync29, unlinkSync as unlinkSync8 } from "fs";
10441
+ import { join as join32 } from "path";
10338
10442
  import { parse as parse2 } from "yaml";
10339
10443
  function getCachePath(prNumber) {
10340
- return join31(process.cwd(), ".assist", `pr-${prNumber}-comments.yaml`);
10444
+ return join32(process.cwd(), ".assist", `pr-${prNumber}-comments.yaml`);
10341
10445
  }
10342
10446
  function loadCommentsCache(prNumber) {
10343
10447
  const cachePath = getCachePath(prNumber);
10344
10448
  if (!existsSync33(cachePath)) {
10345
10449
  return null;
10346
10450
  }
10347
- const content = readFileSync28(cachePath, "utf-8");
10451
+ const content = readFileSync29(cachePath, "utf-8");
10348
10452
  return parse2(content);
10349
10453
  }
10350
10454
  function deleteCommentsCache(prNumber) {
@@ -10364,8 +10468,8 @@ function replyToComment(org, repo, prNumber, commentId, message) {
10364
10468
  }
10365
10469
  function resolveThread(threadId) {
10366
10470
  const mutation = `mutation($threadId: ID!) { resolveReviewThread(input: {threadId: $threadId}) { thread { isResolved } } }`;
10367
- const queryFile = join32(tmpdir5(), `gh-mutation-${Date.now()}.graphql`);
10368
- writeFileSync21(queryFile, mutation);
10471
+ const queryFile = join33(tmpdir5(), `gh-mutation-${Date.now()}.graphql`);
10472
+ writeFileSync22(queryFile, mutation);
10369
10473
  try {
10370
10474
  execSync31(
10371
10475
  `gh api graphql -F query=@${queryFile} -f threadId="${threadId}"`,
@@ -10446,19 +10550,19 @@ function fixed(commentId, sha) {
10446
10550
  }
10447
10551
 
10448
10552
  // src/commands/prs/listComments/index.ts
10449
- import { existsSync as existsSync34, mkdirSync as mkdirSync10, writeFileSync as writeFileSync23 } from "fs";
10450
- import { join as join34 } from "path";
10553
+ import { existsSync as existsSync34, mkdirSync as mkdirSync11, writeFileSync as writeFileSync24 } from "fs";
10554
+ import { join as join35 } from "path";
10451
10555
  import { stringify } from "yaml";
10452
10556
 
10453
10557
  // src/commands/prs/fetchThreadIds.ts
10454
10558
  import { execSync as execSync33 } from "child_process";
10455
- import { unlinkSync as unlinkSync10, writeFileSync as writeFileSync22 } from "fs";
10559
+ import { unlinkSync as unlinkSync10, writeFileSync as writeFileSync23 } from "fs";
10456
10560
  import { tmpdir as tmpdir6 } from "os";
10457
- import { join as join33 } from "path";
10561
+ import { join as join34 } from "path";
10458
10562
  var THREAD_QUERY = `query($owner: String!, $repo: String!, $prNumber: Int!) { repository(owner: $owner, name: $repo) { pullRequest(number: $prNumber) { reviewThreads(first: 100) { nodes { id isResolved comments(first: 100) { nodes { databaseId } } } } } } }`;
10459
10563
  function fetchThreadIds(org, repo, prNumber) {
10460
- const queryFile = join33(tmpdir6(), `gh-query-${Date.now()}.graphql`);
10461
- writeFileSync22(queryFile, THREAD_QUERY);
10564
+ const queryFile = join34(tmpdir6(), `gh-query-${Date.now()}.graphql`);
10565
+ writeFileSync23(queryFile, THREAD_QUERY);
10462
10566
  try {
10463
10567
  const result = execSync33(
10464
10568
  `gh api graphql -F query=@${queryFile} -F owner="${org}" -F repo="${repo}" -F prNumber=${prNumber}`,
@@ -10571,17 +10675,17 @@ function printComments2(result) {
10571
10675
 
10572
10676
  // src/commands/prs/listComments/index.ts
10573
10677
  function writeCommentsCache(prNumber, comments3) {
10574
- const assistDir = join34(process.cwd(), ".assist");
10678
+ const assistDir = join35(process.cwd(), ".assist");
10575
10679
  if (!existsSync34(assistDir)) {
10576
- mkdirSync10(assistDir, { recursive: true });
10680
+ mkdirSync11(assistDir, { recursive: true });
10577
10681
  }
10578
10682
  const cacheData = {
10579
10683
  prNumber,
10580
10684
  fetchedAt: (/* @__PURE__ */ new Date()).toISOString(),
10581
10685
  comments: comments3
10582
10686
  };
10583
- const cachePath = join34(assistDir, `pr-${prNumber}-comments.yaml`);
10584
- writeFileSync23(cachePath, stringify(cacheData));
10687
+ const cachePath = join35(assistDir, `pr-${prNumber}-comments.yaml`);
10688
+ writeFileSync24(cachePath, stringify(cacheData));
10585
10689
  }
10586
10690
  function handleKnownErrors(error) {
10587
10691
  if (isGhNotInstalled(error)) {
@@ -10613,7 +10717,7 @@ async function listComments() {
10613
10717
  ];
10614
10718
  updateCache(prNumber, allComments);
10615
10719
  const hasLineComments = allComments.some((c) => c.type === "line");
10616
- const cachePath = hasLineComments ? join34(process.cwd(), ".assist", `pr-${prNumber}-comments.yaml`) : null;
10720
+ const cachePath = hasLineComments ? join35(process.cwd(), ".assist", `pr-${prNumber}-comments.yaml`) : null;
10617
10721
  return { comments: allComments, cachePath };
10618
10722
  } catch (error) {
10619
10723
  const handled = handleKnownErrors(error);
@@ -10830,8 +10934,8 @@ function registerPrs(program2) {
10830
10934
  prsCommand.command("wontfix <comment-id> <reason>").description("Reply with reason and resolve thread").action((commentId, reason) => {
10831
10935
  wontfix(Number.parseInt(commentId, 10), reason);
10832
10936
  });
10833
- prsCommand.command("comment <path> <line> <body>").description("Add a line comment to the pending review").action((path54, line, body) => {
10834
- comment2(path54, Number.parseInt(line, 10), body);
10937
+ prsCommand.command("comment <path> <line> <body>").description("Add a line comment to the pending review").action((path53, line, body) => {
10938
+ comment2(path53, Number.parseInt(line, 10), body);
10835
10939
  });
10836
10940
  }
10837
10941
 
@@ -11083,10 +11187,10 @@ function resolveOpSecret(reference) {
11083
11187
  }
11084
11188
 
11085
11189
  // src/commands/ravendb/ravenFetch.ts
11086
- async function ravenFetch(connection, path54) {
11190
+ async function ravenFetch(connection, path53) {
11087
11191
  const apiKey = resolveOpSecret(connection.apiKeyRef);
11088
11192
  let accessToken = await getAccessToken(apiKey);
11089
- const url = `${connection.url}${path54}`;
11193
+ const url = `${connection.url}${path53}`;
11090
11194
  const headers = {
11091
11195
  Authorization: `Bearer ${accessToken}`,
11092
11196
  "Content-Type": "application/json"
@@ -11176,16 +11280,16 @@ import chalk129 from "chalk";
11176
11280
  // src/commands/ravendb/buildQueryPath.ts
11177
11281
  function buildQueryPath(opts) {
11178
11282
  const db = encodeURIComponent(opts.db);
11179
- let path54;
11283
+ let path53;
11180
11284
  if (opts.collection) {
11181
- path54 = `/databases/${db}/indexes/dynamic/${encodeURIComponent(opts.collection)}?start=${opts.start}&pageSize=${opts.pageSize}&sort=${encodeURIComponent(opts.sort)}`;
11285
+ path53 = `/databases/${db}/indexes/dynamic/${encodeURIComponent(opts.collection)}?start=${opts.start}&pageSize=${opts.pageSize}&sort=${encodeURIComponent(opts.sort)}`;
11182
11286
  } else {
11183
- path54 = `/databases/${db}/queries?start=${opts.start}&pageSize=${opts.pageSize}`;
11287
+ path53 = `/databases/${db}/queries?start=${opts.start}&pageSize=${opts.pageSize}`;
11184
11288
  }
11185
11289
  if (opts.query) {
11186
- path54 += `&query=${encodeURIComponent(opts.query)}`;
11290
+ path53 += `&query=${encodeURIComponent(opts.query)}`;
11187
11291
  }
11188
- return path54;
11292
+ return path53;
11189
11293
  }
11190
11294
 
11191
11295
  // src/commands/ravendb/fetchAllPages.ts
@@ -11194,7 +11298,7 @@ async function fetchAllPages(connection, opts) {
11194
11298
  let start3 = 0;
11195
11299
  while (true) {
11196
11300
  const effectivePageSize = opts.limit !== void 0 ? Math.min(opts.pageSize, opts.limit - allResults.length) : opts.pageSize;
11197
- const path54 = buildQueryPath({
11301
+ const path53 = buildQueryPath({
11198
11302
  db: connection.database,
11199
11303
  collection: opts.collection,
11200
11304
  start: start3,
@@ -11202,7 +11306,7 @@ async function fetchAllPages(connection, opts) {
11202
11306
  sort: opts.sort,
11203
11307
  query: opts.query
11204
11308
  });
11205
- const data = await ravenFetch(connection, path54);
11309
+ const data = await ravenFetch(connection, path53);
11206
11310
  const results = data.Results ?? [];
11207
11311
  const totalResults = data.TotalResults ?? 0;
11208
11312
  if (results.length === 0) break;
@@ -12420,8 +12524,8 @@ function findRootParent(file, importedBy, visited) {
12420
12524
  function clusterFiles(graph) {
12421
12525
  const clusters = /* @__PURE__ */ new Map();
12422
12526
  for (const file of graph.files) {
12423
- const basename11 = path38.basename(file, path38.extname(file));
12424
- if (basename11 === "index") continue;
12527
+ const basename10 = path38.basename(file, path38.extname(file));
12528
+ if (basename10 === "index") continue;
12425
12529
  const importers = graph.importedBy.get(file);
12426
12530
  if (!importers || importers.size !== 1) continue;
12427
12531
  const parent = [...importers][0];
@@ -12898,15 +13002,15 @@ ${context.diff.trimEnd()}
12898
13002
  }
12899
13003
 
12900
13004
  // src/commands/review/buildReviewPaths.ts
12901
- import { join as join35 } from "path";
13005
+ import { join as join36 } from "path";
12902
13006
  function buildReviewPaths(repoRoot, key) {
12903
- const reviewDir = join35(repoRoot, ".assist", "reviews", key);
13007
+ const reviewDir = join36(repoRoot, ".assist", "reviews", key);
12904
13008
  return {
12905
13009
  reviewDir,
12906
- requestPath: join35(reviewDir, "request.md"),
12907
- claudePath: join35(reviewDir, "claude.md"),
12908
- codexPath: join35(reviewDir, "codex.md"),
12909
- synthesisPath: join35(reviewDir, "synthesis.md")
13010
+ requestPath: join36(reviewDir, "request.md"),
13011
+ claudePath: join36(reviewDir, "claude.md"),
13012
+ codexPath: join36(reviewDir, "codex.md"),
13013
+ synthesisPath: join36(reviewDir, "synthesis.md")
12910
13014
  };
12911
13015
  }
12912
13016
 
@@ -12914,24 +13018,24 @@ function buildReviewPaths(repoRoot, key) {
12914
13018
  import {
12915
13019
  appendFileSync,
12916
13020
  existsSync as existsSync35,
12917
- readFileSync as readFileSync29,
12918
- writeFileSync as writeFileSync24
13021
+ readFileSync as readFileSync30,
13022
+ writeFileSync as writeFileSync25
12919
13023
  } from "fs";
12920
- import { join as join36 } from "path";
13024
+ import { join as join37 } from "path";
12921
13025
  var REVIEWS_ENTRY = ".assist/reviews";
12922
13026
  function coversReviews(line) {
12923
13027
  const pattern2 = line.trim().replace(/^\//, "").replace(/\/$/, "");
12924
13028
  return pattern2 === ".assist" || pattern2 === REVIEWS_ENTRY;
12925
13029
  }
12926
13030
  function ensureReviewsIgnored(repoRoot) {
12927
- const gitignorePath = join36(repoRoot, ".gitignore");
13031
+ const gitignorePath = join37(repoRoot, ".gitignore");
12928
13032
  if (!existsSync35(gitignorePath)) {
12929
- writeFileSync24(gitignorePath, `${REVIEWS_ENTRY}
13033
+ writeFileSync25(gitignorePath, `${REVIEWS_ENTRY}
12930
13034
  `);
12931
13035
  console.log(`Created .gitignore with ${REVIEWS_ENTRY} entry.`);
12932
13036
  return;
12933
13037
  }
12934
- const content = readFileSync29(gitignorePath, "utf-8");
13038
+ const content = readFileSync30(gitignorePath, "utf-8");
12935
13039
  if (content.split("\n").some(coversReviews)) return;
12936
13040
  const separator = content === "" || content.endsWith("\n") ? "" : "\n";
12937
13041
  appendFileSync(gitignorePath, `${separator}${REVIEWS_ENTRY}
@@ -13078,7 +13182,7 @@ function gatherContext() {
13078
13182
  }
13079
13183
 
13080
13184
  // src/commands/review/postReviewToPr.ts
13081
- import { readFileSync as readFileSync30 } from "fs";
13185
+ import { readFileSync as readFileSync31 } from "fs";
13082
13186
 
13083
13187
  // src/commands/review/parseFindings.ts
13084
13188
  var SEVERITIES = ["blocker", "major", "minor", "nit"];
@@ -13308,7 +13412,7 @@ async function postReviewToPr(synthesisPath, options2) {
13308
13412
  console.log("No PR found for current branch; nothing posted.");
13309
13413
  return;
13310
13414
  }
13311
- const markdown = readFileSync30(synthesisPath, "utf-8");
13415
+ const markdown = readFileSync31(synthesisPath, "utf-8");
13312
13416
  const findings = parseFindings(markdown);
13313
13417
  if (findings.length === 0) {
13314
13418
  console.log("Synthesis contains no findings; nothing to post.");
@@ -13385,16 +13489,16 @@ async function handlePostSynthesis(synthesisPath, options2) {
13385
13489
  }
13386
13490
 
13387
13491
  // src/commands/review/prepareReviewDir.ts
13388
- import { existsSync as existsSync36, mkdirSync as mkdirSync11, unlinkSync as unlinkSync11, writeFileSync as writeFileSync25 } from "fs";
13492
+ import { existsSync as existsSync36, mkdirSync as mkdirSync12, unlinkSync as unlinkSync11, writeFileSync as writeFileSync26 } from "fs";
13389
13493
  function clearReviewFiles(paths) {
13390
- for (const path54 of [paths.claudePath, paths.codexPath, paths.synthesisPath]) {
13391
- if (existsSync36(path54)) unlinkSync11(path54);
13494
+ for (const path53 of [paths.claudePath, paths.codexPath, paths.synthesisPath]) {
13495
+ if (existsSync36(path53)) unlinkSync11(path53);
13392
13496
  }
13393
13497
  }
13394
13498
  function prepareReviewDir(paths, requestBody, force) {
13395
- mkdirSync11(paths.reviewDir, { recursive: true });
13499
+ mkdirSync12(paths.reviewDir, { recursive: true });
13396
13500
  if (force) clearReviewFiles(paths);
13397
- writeFileSync25(paths.requestPath, requestBody);
13501
+ writeFileSync26(paths.requestPath, requestBody);
13398
13502
  }
13399
13503
 
13400
13504
  // src/commands/review/runApplySession.ts
@@ -13737,7 +13841,7 @@ The review request is at: ${requestPath}
13737
13841
  }
13738
13842
 
13739
13843
  // src/commands/review/runClaudeReviewer.ts
13740
- import { writeFileSync as writeFileSync26 } from "fs";
13844
+ import { writeFileSync as writeFileSync27 } from "fs";
13741
13845
 
13742
13846
  // src/commands/review/finaliseReviewerSpinner.ts
13743
13847
  var SUMMARY_MAX_LEN = 80;
@@ -14073,7 +14177,7 @@ async function runClaudeReviewer(spec) {
14073
14177
  }
14074
14178
  });
14075
14179
  if (result.exitCode === 0 && finalText)
14076
- writeFileSync26(spec.outputPath, finalText);
14180
+ writeFileSync27(spec.outputPath, finalText);
14077
14181
  return finaliseReviewerRun({ ...spec, command }, spinner, result);
14078
14182
  }
14079
14183
 
@@ -14189,7 +14293,7 @@ async function runReviewers(reviewDir, claudePath, codexPath, stdinPrompt, optio
14189
14293
  }
14190
14294
 
14191
14295
  // src/commands/review/synthesise.ts
14192
- import { readFileSync as readFileSync31 } from "fs";
14296
+ import { readFileSync as readFileSync32 } from "fs";
14193
14297
 
14194
14298
  // src/commands/review/buildSynthesisStdin.ts
14195
14299
  var SYNTHESIS_PROMPT = `You are consolidating two independent code reviews of the same change. The original review request is in request.md. The two reviews are in claude.md and codex.md in the current working directory.
@@ -14245,7 +14349,7 @@ Files:
14245
14349
 
14246
14350
  // src/commands/review/synthesise.ts
14247
14351
  function printSummary2(synthesisPath) {
14248
- const markdown = readFileSync31(synthesisPath, "utf-8");
14352
+ const markdown = readFileSync32(synthesisPath, "utf-8");
14249
14353
  console.log("");
14250
14354
  console.log(buildReviewSummary(markdown));
14251
14355
  console.log("");
@@ -14524,8 +14628,8 @@ import chalk147 from "chalk";
14524
14628
 
14525
14629
  // src/commands/seq/fetchSeq.ts
14526
14630
  import chalk144 from "chalk";
14527
- async function fetchSeq(conn, path54, params) {
14528
- const url = `${conn.url}${path54}?${params}`;
14631
+ async function fetchSeq(conn, path53, params) {
14632
+ const url = `${conn.url}${path53}?${params}`;
14529
14633
  const response = await fetch(url, {
14530
14634
  headers: {
14531
14635
  Accept: "application/json",
@@ -15070,7 +15174,7 @@ function registerSql(program2) {
15070
15174
 
15071
15175
  // src/commands/transcript/shared.ts
15072
15176
  import { existsSync as existsSync39, readdirSync as readdirSync6, statSync as statSync4 } from "fs";
15073
- import { basename as basename6, join as join37, relative as relative2 } from "path";
15177
+ import { basename as basename6, join as join38, relative as relative2 } from "path";
15074
15178
  import * as readline2 from "readline";
15075
15179
  var DATE_PREFIX_REGEX = /^\d{4}-\d{2}-\d{2}/;
15076
15180
  function getDatePrefix(daysOffset = 0) {
@@ -15088,7 +15192,7 @@ function collectFiles(dir, extension) {
15088
15192
  if (!existsSync39(dir)) return [];
15089
15193
  const results = [];
15090
15194
  for (const entry of readdirSync6(dir)) {
15091
- const fullPath = join37(dir, entry);
15195
+ const fullPath = join38(dir, entry);
15092
15196
  if (statSync4(fullPath).isDirectory()) {
15093
15197
  results.push(...collectFiles(fullPath, extension));
15094
15198
  } else if (entry.endsWith(extension)) {
@@ -15185,11 +15289,11 @@ async function configure() {
15185
15289
  import { existsSync as existsSync41 } from "fs";
15186
15290
 
15187
15291
  // src/commands/transcript/format/fixInvalidDatePrefixes/index.ts
15188
- import { dirname as dirname19, join as join39 } from "path";
15292
+ import { dirname as dirname20, join as join40 } from "path";
15189
15293
 
15190
15294
  // src/commands/transcript/format/fixInvalidDatePrefixes/promptForDateFix.ts
15191
15295
  import { renameSync as renameSync3 } from "fs";
15192
- import { join as join38 } from "path";
15296
+ import { join as join39 } from "path";
15193
15297
  async function resolveDate(rl, choice) {
15194
15298
  if (choice === "1") return getDatePrefix(0);
15195
15299
  if (choice === "2") return getDatePrefix(-1);
@@ -15204,7 +15308,7 @@ async function resolveDate(rl, choice) {
15204
15308
  }
15205
15309
  function renameWithPrefix(vttDir, vttFile, prefix2) {
15206
15310
  const newFilename = `${prefix2}.${vttFile}`;
15207
- renameSync3(join38(vttDir, vttFile), join38(vttDir, newFilename));
15311
+ renameSync3(join39(vttDir, vttFile), join39(vttDir, newFilename));
15208
15312
  console.log(`Renamed to: ${newFilename}`);
15209
15313
  return newFilename;
15210
15314
  }
@@ -15235,15 +15339,15 @@ async function fixInvalidDatePrefixes(vttFiles) {
15235
15339
  for (let i = 0; i < vttFiles.length; i++) {
15236
15340
  const vttFile = vttFiles[i];
15237
15341
  if (!isValidDatePrefix(vttFile.filename)) {
15238
- const vttFileDir = dirname19(vttFile.absolutePath);
15342
+ const vttFileDir = dirname20(vttFile.absolutePath);
15239
15343
  const newFilename = await promptForDateFix(vttFile.filename, vttFileDir);
15240
15344
  if (newFilename) {
15241
- const newRelativePath = join39(
15242
- dirname19(vttFile.relativePath),
15345
+ const newRelativePath = join40(
15346
+ dirname20(vttFile.relativePath),
15243
15347
  newFilename
15244
15348
  );
15245
15349
  vttFiles[i] = {
15246
- absolutePath: join39(vttFileDir, newFilename),
15350
+ absolutePath: join40(vttFileDir, newFilename),
15247
15351
  relativePath: newRelativePath,
15248
15352
  filename: newFilename
15249
15353
  };
@@ -15256,8 +15360,8 @@ async function fixInvalidDatePrefixes(vttFiles) {
15256
15360
  }
15257
15361
 
15258
15362
  // src/commands/transcript/format/processVttFile/index.ts
15259
- import { existsSync as existsSync40, mkdirSync as mkdirSync12, readFileSync as readFileSync32, writeFileSync as writeFileSync27 } from "fs";
15260
- import { basename as basename7, dirname as dirname20, join as join40 } from "path";
15363
+ import { existsSync as existsSync40, mkdirSync as mkdirSync13, readFileSync as readFileSync33, writeFileSync as writeFileSync28 } from "fs";
15364
+ import { basename as basename7, dirname as dirname21, join as join41 } from "path";
15261
15365
 
15262
15366
  // src/commands/transcript/cleanText.ts
15263
15367
  function cleanText(text2) {
@@ -15467,22 +15571,22 @@ function toMdFilename(vttFilename) {
15467
15571
  return `${basename7(vttFilename, ".vtt").replace(/\s*Transcription\s*/g, " ").trim()}.md`;
15468
15572
  }
15469
15573
  function resolveOutputDir(relativeDir, transcriptsDir) {
15470
- return relativeDir === "." ? transcriptsDir : join40(transcriptsDir, relativeDir);
15574
+ return relativeDir === "." ? transcriptsDir : join41(transcriptsDir, relativeDir);
15471
15575
  }
15472
15576
  function buildOutputPaths(vttFile, transcriptsDir) {
15473
15577
  const mdFile = toMdFilename(vttFile.filename);
15474
- const relativeDir = dirname20(vttFile.relativePath);
15578
+ const relativeDir = dirname21(vttFile.relativePath);
15475
15579
  const outputDir = resolveOutputDir(relativeDir, transcriptsDir);
15476
- const outputPath = join40(outputDir, mdFile);
15580
+ const outputPath = join41(outputDir, mdFile);
15477
15581
  return { outputDir, outputPath, mdFile, relativeDir };
15478
15582
  }
15479
15583
  function logSkipped(relativeDir, mdFile) {
15480
- console.log(`Skipping (already exists): ${join40(relativeDir, mdFile)}`);
15584
+ console.log(`Skipping (already exists): ${join41(relativeDir, mdFile)}`);
15481
15585
  return "skipped";
15482
15586
  }
15483
15587
  function ensureDirectory(dir, label2) {
15484
15588
  if (!existsSync40(dir)) {
15485
- mkdirSync12(dir, { recursive: true });
15589
+ mkdirSync13(dir, { recursive: true });
15486
15590
  console.log(`Created ${label2}: ${dir}`);
15487
15591
  }
15488
15592
  }
@@ -15504,10 +15608,10 @@ function logReduction(cueCount, messageCount) {
15504
15608
  }
15505
15609
  function readAndParseCues(inputPath) {
15506
15610
  console.log(`Reading: ${inputPath}`);
15507
- return processCues(readFileSync32(inputPath, "utf-8"));
15611
+ return processCues(readFileSync33(inputPath, "utf-8"));
15508
15612
  }
15509
15613
  function writeFormatted(outputPath, content) {
15510
- writeFileSync27(outputPath, content, "utf-8");
15614
+ writeFileSync28(outputPath, content, "utf-8");
15511
15615
  console.log(`Written: ${outputPath}`);
15512
15616
  }
15513
15617
  function convertVttToMarkdown(inputPath, outputPath) {
@@ -15576,17 +15680,17 @@ async function format() {
15576
15680
 
15577
15681
  // src/commands/transcript/summarise/index.ts
15578
15682
  import { existsSync as existsSync43 } from "fs";
15579
- import { basename as basename8, dirname as dirname22, join as join42, relative as relative3 } from "path";
15683
+ import { basename as basename8, dirname as dirname23, join as join43, relative as relative3 } from "path";
15580
15684
 
15581
15685
  // src/commands/transcript/summarise/processStagedFile/index.ts
15582
15686
  import {
15583
15687
  existsSync as existsSync42,
15584
- mkdirSync as mkdirSync13,
15585
- readFileSync as readFileSync33,
15688
+ mkdirSync as mkdirSync14,
15689
+ readFileSync as readFileSync34,
15586
15690
  renameSync as renameSync4,
15587
- rmSync
15691
+ rmSync as rmSync2
15588
15692
  } from "fs";
15589
- import { dirname as dirname21, join as join41 } from "path";
15693
+ import { dirname as dirname22, join as join42 } from "path";
15590
15694
 
15591
15695
  // src/commands/transcript/summarise/processStagedFile/validateStagedContent.ts
15592
15696
  import chalk154 from "chalk";
@@ -15615,7 +15719,7 @@ function validateStagedContent(filename, content) {
15615
15719
  }
15616
15720
 
15617
15721
  // src/commands/transcript/summarise/processStagedFile/index.ts
15618
- var STAGING_DIR = join41(process.cwd(), ".assist", "transcript");
15722
+ var STAGING_DIR = join42(process.cwd(), ".assist", "transcript");
15619
15723
  function processStagedFile() {
15620
15724
  if (!existsSync42(STAGING_DIR)) {
15621
15725
  return false;
@@ -15626,7 +15730,7 @@ function processStagedFile() {
15626
15730
  }
15627
15731
  const { transcriptsDir, summaryDir } = getTranscriptConfig();
15628
15732
  const stagedFile = stagedFiles[0];
15629
- const content = readFileSync33(stagedFile.absolutePath, "utf-8");
15733
+ const content = readFileSync34(stagedFile.absolutePath, "utf-8");
15630
15734
  validateStagedContent(stagedFile.filename, content);
15631
15735
  const stagedBaseName = getTranscriptBaseName(stagedFile.filename);
15632
15736
  const transcriptFiles = findMdFilesRecursive(transcriptsDir);
@@ -15639,23 +15743,23 @@ function processStagedFile() {
15639
15743
  );
15640
15744
  process.exit(1);
15641
15745
  }
15642
- const destPath = join41(summaryDir, matchingTranscript.relativePath);
15643
- const destDir = dirname21(destPath);
15746
+ const destPath = join42(summaryDir, matchingTranscript.relativePath);
15747
+ const destDir = dirname22(destPath);
15644
15748
  if (!existsSync42(destDir)) {
15645
- mkdirSync13(destDir, { recursive: true });
15749
+ mkdirSync14(destDir, { recursive: true });
15646
15750
  }
15647
15751
  renameSync4(stagedFile.absolutePath, destPath);
15648
15752
  const remaining = findMdFilesRecursive(STAGING_DIR);
15649
15753
  if (remaining.length === 0) {
15650
- rmSync(STAGING_DIR, { recursive: true });
15754
+ rmSync2(STAGING_DIR, { recursive: true });
15651
15755
  }
15652
15756
  return true;
15653
15757
  }
15654
15758
 
15655
15759
  // src/commands/transcript/summarise/index.ts
15656
15760
  function buildRelativeKey(relativePath, baseName) {
15657
- const relDir = dirname22(relativePath);
15658
- return relDir === "." ? baseName : join42(relDir, baseName);
15761
+ const relDir = dirname23(relativePath);
15762
+ return relDir === "." ? baseName : join43(relDir, baseName);
15659
15763
  }
15660
15764
  function buildSummaryIndex(summaryDir) {
15661
15765
  const summaryFiles = findMdFilesRecursive(summaryDir);
@@ -15689,8 +15793,8 @@ function summarise3() {
15689
15793
  }
15690
15794
  const next3 = missing[0];
15691
15795
  const outputFilename = `${getTranscriptBaseName(next3.filename)}.md`;
15692
- const outputPath = join42(STAGING_DIR, outputFilename);
15693
- const summaryFileDir = join42(summaryDir, dirname22(next3.relativePath));
15796
+ const outputPath = join43(STAGING_DIR, outputFilename);
15797
+ const summaryFileDir = join43(summaryDir, dirname23(next3.relativePath));
15694
15798
  const relativeTranscriptPath = encodeURI(
15695
15799
  relative3(summaryFileDir, next3.absolutePath).replace(/\\/g, "/")
15696
15800
  );
@@ -15739,50 +15843,50 @@ function registerVerify(program2) {
15739
15843
 
15740
15844
  // src/commands/voice/devices.ts
15741
15845
  import { spawnSync as spawnSync4 } from "child_process";
15742
- import { join as join44 } from "path";
15846
+ import { join as join45 } from "path";
15743
15847
 
15744
15848
  // src/commands/voice/shared.ts
15745
15849
  import { homedir as homedir9 } from "os";
15746
- import { dirname as dirname23, join as join43 } from "path";
15850
+ import { dirname as dirname24, join as join44 } from "path";
15747
15851
  import { fileURLToPath as fileURLToPath6 } from "url";
15748
- var __dirname6 = dirname23(fileURLToPath6(import.meta.url));
15749
- var VOICE_DIR = join43(homedir9(), ".assist", "voice");
15852
+ var __dirname6 = dirname24(fileURLToPath6(import.meta.url));
15853
+ var VOICE_DIR = join44(homedir9(), ".assist", "voice");
15750
15854
  var voicePaths = {
15751
15855
  dir: VOICE_DIR,
15752
- pid: join43(VOICE_DIR, "voice.pid"),
15753
- log: join43(VOICE_DIR, "voice.log"),
15754
- venv: join43(VOICE_DIR, ".venv"),
15755
- lock: join43(VOICE_DIR, "voice.lock")
15856
+ pid: join44(VOICE_DIR, "voice.pid"),
15857
+ log: join44(VOICE_DIR, "voice.log"),
15858
+ venv: join44(VOICE_DIR, ".venv"),
15859
+ lock: join44(VOICE_DIR, "voice.lock")
15756
15860
  };
15757
15861
  function getPythonDir() {
15758
- return join43(__dirname6, "commands", "voice", "python");
15862
+ return join44(__dirname6, "commands", "voice", "python");
15759
15863
  }
15760
15864
  function getVenvPython() {
15761
- return process.platform === "win32" ? join43(voicePaths.venv, "Scripts", "python.exe") : join43(voicePaths.venv, "bin", "python");
15865
+ return process.platform === "win32" ? join44(voicePaths.venv, "Scripts", "python.exe") : join44(voicePaths.venv, "bin", "python");
15762
15866
  }
15763
15867
  function getLockDir() {
15764
15868
  const config = loadConfig();
15765
15869
  return config.voice?.lockDir ?? VOICE_DIR;
15766
15870
  }
15767
15871
  function getLockFile() {
15768
- return join43(getLockDir(), "voice.lock");
15872
+ return join44(getLockDir(), "voice.lock");
15769
15873
  }
15770
15874
 
15771
15875
  // src/commands/voice/devices.ts
15772
15876
  function devices() {
15773
- const script = join44(getPythonDir(), "list_devices.py");
15877
+ const script = join45(getPythonDir(), "list_devices.py");
15774
15878
  spawnSync4(getVenvPython(), [script], { stdio: "inherit" });
15775
15879
  }
15776
15880
 
15777
15881
  // src/commands/voice/logs.ts
15778
- import { existsSync as existsSync44, readFileSync as readFileSync34 } from "fs";
15882
+ import { existsSync as existsSync44, readFileSync as readFileSync35 } from "fs";
15779
15883
  function logs(options2) {
15780
15884
  if (!existsSync44(voicePaths.log)) {
15781
15885
  console.log("No voice log file found");
15782
15886
  return;
15783
15887
  }
15784
15888
  const count6 = Number.parseInt(options2.lines ?? "150", 10);
15785
- const content = readFileSync34(voicePaths.log, "utf-8").trim();
15889
+ const content = readFileSync35(voicePaths.log, "utf-8").trim();
15786
15890
  if (!content) {
15787
15891
  console.log("Voice log is empty");
15788
15892
  return;
@@ -15804,13 +15908,13 @@ function logs(options2) {
15804
15908
 
15805
15909
  // src/commands/voice/setup.ts
15806
15910
  import { spawnSync as spawnSync5 } from "child_process";
15807
- import { mkdirSync as mkdirSync15 } from "fs";
15808
- import { join as join46 } from "path";
15911
+ import { mkdirSync as mkdirSync16 } from "fs";
15912
+ import { join as join47 } from "path";
15809
15913
 
15810
15914
  // src/commands/voice/checkLockFile.ts
15811
15915
  import { execSync as execSync44 } from "child_process";
15812
- import { existsSync as existsSync45, mkdirSync as mkdirSync14, readFileSync as readFileSync35, writeFileSync as writeFileSync28 } from "fs";
15813
- import { join as join45 } from "path";
15916
+ import { existsSync as existsSync45, mkdirSync as mkdirSync15, readFileSync as readFileSync36, writeFileSync as writeFileSync29 } from "fs";
15917
+ import { join as join46 } from "path";
15814
15918
  function isProcessAlive2(pid) {
15815
15919
  try {
15816
15920
  process.kill(pid, 0);
@@ -15823,7 +15927,7 @@ function checkLockFile() {
15823
15927
  const lockFile = getLockFile();
15824
15928
  if (!existsSync45(lockFile)) return;
15825
15929
  try {
15826
- const lock = JSON.parse(readFileSync35(lockFile, "utf-8"));
15930
+ const lock = JSON.parse(readFileSync36(lockFile, "utf-8"));
15827
15931
  if (lock.pid && isProcessAlive2(lock.pid)) {
15828
15932
  console.error(
15829
15933
  `Voice daemon already running (PID ${lock.pid}, env: ${lock.env}). Stop it first with: assist voice stop`
@@ -15847,8 +15951,8 @@ function bootstrapVenv() {
15847
15951
  }
15848
15952
  function writeLockFile(pid) {
15849
15953
  const lockFile = getLockFile();
15850
- mkdirSync14(join45(lockFile, ".."), { recursive: true });
15851
- writeFileSync28(
15954
+ mkdirSync15(join46(lockFile, ".."), { recursive: true });
15955
+ writeFileSync29(
15852
15956
  lockFile,
15853
15957
  JSON.stringify({
15854
15958
  pid,
@@ -15860,10 +15964,10 @@ function writeLockFile(pid) {
15860
15964
 
15861
15965
  // src/commands/voice/setup.ts
15862
15966
  function setup() {
15863
- mkdirSync15(voicePaths.dir, { recursive: true });
15967
+ mkdirSync16(voicePaths.dir, { recursive: true });
15864
15968
  bootstrapVenv();
15865
15969
  console.log("\nDownloading models...\n");
15866
- const script = join46(getPythonDir(), "setup_models.py");
15970
+ const script = join47(getPythonDir(), "setup_models.py");
15867
15971
  const result = spawnSync5(getVenvPython(), [script], {
15868
15972
  stdio: "inherit",
15869
15973
  env: { ...process.env, VOICE_LOG_FILE: voicePaths.log }
@@ -15876,8 +15980,8 @@ function setup() {
15876
15980
 
15877
15981
  // src/commands/voice/start.ts
15878
15982
  import { spawn as spawn7 } from "child_process";
15879
- import { mkdirSync as mkdirSync16, writeFileSync as writeFileSync29 } from "fs";
15880
- import { join as join47 } from "path";
15983
+ import { mkdirSync as mkdirSync17, writeFileSync as writeFileSync30 } from "fs";
15984
+ import { join as join48 } from "path";
15881
15985
 
15882
15986
  // src/commands/voice/buildDaemonEnv.ts
15883
15987
  function buildDaemonEnv(options2) {
@@ -15905,17 +16009,17 @@ function spawnBackground(python, script, env) {
15905
16009
  console.error("Failed to start voice daemon");
15906
16010
  process.exit(1);
15907
16011
  }
15908
- writeFileSync29(voicePaths.pid, String(pid));
16012
+ writeFileSync30(voicePaths.pid, String(pid));
15909
16013
  writeLockFile(pid);
15910
16014
  console.log(`Voice daemon started (PID ${pid})`);
15911
16015
  }
15912
16016
  function start2(options2) {
15913
- mkdirSync16(voicePaths.dir, { recursive: true });
16017
+ mkdirSync17(voicePaths.dir, { recursive: true });
15914
16018
  checkLockFile();
15915
16019
  bootstrapVenv();
15916
16020
  const debug = options2.debug || options2.foreground || process.platform === "win32";
15917
16021
  const env = buildDaemonEnv({ debug });
15918
- const script = join47(getPythonDir(), "voice_daemon.py");
16022
+ const script = join48(getPythonDir(), "voice_daemon.py");
15919
16023
  const python = getVenvPython();
15920
16024
  if (options2.foreground) {
15921
16025
  spawnForeground(python, script, env);
@@ -15925,7 +16029,7 @@ function start2(options2) {
15925
16029
  }
15926
16030
 
15927
16031
  // src/commands/voice/status.ts
15928
- import { existsSync as existsSync46, readFileSync as readFileSync36 } from "fs";
16032
+ import { existsSync as existsSync46, readFileSync as readFileSync37 } from "fs";
15929
16033
  function isProcessAlive3(pid) {
15930
16034
  try {
15931
16035
  process.kill(pid, 0);
@@ -15936,7 +16040,7 @@ function isProcessAlive3(pid) {
15936
16040
  }
15937
16041
  function readRecentLogs(count6) {
15938
16042
  if (!existsSync46(voicePaths.log)) return [];
15939
- const lines = readFileSync36(voicePaths.log, "utf-8").trim().split("\n");
16043
+ const lines = readFileSync37(voicePaths.log, "utf-8").trim().split("\n");
15940
16044
  return lines.slice(-count6);
15941
16045
  }
15942
16046
  function status() {
@@ -15944,7 +16048,7 @@ function status() {
15944
16048
  console.log("Voice daemon: not running (no PID file)");
15945
16049
  return;
15946
16050
  }
15947
- const pid = Number.parseInt(readFileSync36(voicePaths.pid, "utf-8").trim(), 10);
16051
+ const pid = Number.parseInt(readFileSync37(voicePaths.pid, "utf-8").trim(), 10);
15948
16052
  const alive = isProcessAlive3(pid);
15949
16053
  console.log(`Voice daemon: ${alive ? "running" : "dead"} (PID ${pid})`);
15950
16054
  const recent = readRecentLogs(5);
@@ -15963,13 +16067,13 @@ function status() {
15963
16067
  }
15964
16068
 
15965
16069
  // src/commands/voice/stop.ts
15966
- import { existsSync as existsSync47, readFileSync as readFileSync37, unlinkSync as unlinkSync14 } from "fs";
16070
+ import { existsSync as existsSync47, readFileSync as readFileSync38, unlinkSync as unlinkSync14 } from "fs";
15967
16071
  function stop2() {
15968
16072
  if (!existsSync47(voicePaths.pid)) {
15969
16073
  console.log("Voice daemon is not running (no PID file)");
15970
16074
  return;
15971
16075
  }
15972
- const pid = Number.parseInt(readFileSync37(voicePaths.pid, "utf-8").trim(), 10);
16076
+ const pid = Number.parseInt(readFileSync38(voicePaths.pid, "utf-8").trim(), 10);
15973
16077
  try {
15974
16078
  process.kill(pid, "SIGTERM");
15975
16079
  console.log(`Sent SIGTERM to voice daemon (PID ${pid})`);
@@ -16204,8 +16308,8 @@ async function auth() {
16204
16308
 
16205
16309
  // src/commands/roam/postRoamActivity.ts
16206
16310
  import { execFileSync as execFileSync7 } from "child_process";
16207
- import { readdirSync as readdirSync7, readFileSync as readFileSync38, statSync as statSync5 } from "fs";
16208
- import { join as join48 } from "path";
16311
+ import { readdirSync as readdirSync7, readFileSync as readFileSync39, statSync as statSync5 } from "fs";
16312
+ import { join as join49 } from "path";
16209
16313
  function findPortFile(roamDir) {
16210
16314
  let entries;
16211
16315
  try {
@@ -16214,9 +16318,9 @@ function findPortFile(roamDir) {
16214
16318
  return void 0;
16215
16319
  }
16216
16320
  const candidates = entries.filter((name) => /^roam-local-api(-[^.]+)?\.port$/.test(name)).map((name) => {
16217
- const path54 = join48(roamDir, name);
16321
+ const path53 = join49(roamDir, name);
16218
16322
  try {
16219
- return { path: path54, mtimeMs: statSync5(path54).mtimeMs };
16323
+ return { path: path53, mtimeMs: statSync5(path53).mtimeMs };
16220
16324
  } catch {
16221
16325
  return void 0;
16222
16326
  }
@@ -16226,11 +16330,11 @@ function findPortFile(roamDir) {
16226
16330
  function postRoamActivity(app, event) {
16227
16331
  const appData = process.env.APPDATA;
16228
16332
  if (!appData) return;
16229
- const portFile = findPortFile(join48(appData, "Roam"));
16333
+ const portFile = findPortFile(join49(appData, "Roam"));
16230
16334
  if (!portFile) return;
16231
16335
  let port;
16232
16336
  try {
16233
- port = readFileSync38(portFile, "utf-8").trim();
16337
+ port = readFileSync39(portFile, "utf-8").trim();
16234
16338
  } catch {
16235
16339
  return;
16236
16340
  }
@@ -16373,13 +16477,13 @@ function runPreCommands(pre, cwd) {
16373
16477
  // src/commands/run/spawnRunCommand.ts
16374
16478
  import { execFileSync as execFileSync8, spawn as spawn8 } from "child_process";
16375
16479
  import { existsSync as existsSync48 } from "fs";
16376
- import { dirname as dirname24, join as join49, resolve as resolve11 } from "path";
16480
+ import { dirname as dirname25, join as join50, resolve as resolve11 } from "path";
16377
16481
  function resolveCommand2(command) {
16378
16482
  if (process.platform !== "win32" || command !== "bash") return command;
16379
16483
  try {
16380
16484
  const gitPath = execFileSync8("where", ["git"], { encoding: "utf8" }).trim().split("\r\n")[0];
16381
- const gitRoot = resolve11(dirname24(gitPath), "..");
16382
- const gitBash = join49(gitRoot, "bin", "bash.exe");
16485
+ const gitRoot = resolve11(dirname25(gitPath), "..");
16486
+ const gitBash = join50(gitRoot, "bin", "bash.exe");
16383
16487
  if (existsSync48(gitBash)) return gitBash;
16384
16488
  } catch {
16385
16489
  }
@@ -16465,8 +16569,8 @@ async function run3(name, args) {
16465
16569
  }
16466
16570
 
16467
16571
  // src/commands/run/add.ts
16468
- import { mkdirSync as mkdirSync17, writeFileSync as writeFileSync30 } from "fs";
16469
- import { join as join50 } from "path";
16572
+ import { mkdirSync as mkdirSync18, writeFileSync as writeFileSync31 } from "fs";
16573
+ import { join as join51 } from "path";
16470
16574
 
16471
16575
  // src/commands/run/extractOption.ts
16472
16576
  function extractOption(args, flag) {
@@ -16527,16 +16631,16 @@ function saveNewRunConfig(name, command, args, cwd) {
16527
16631
  saveConfig(config);
16528
16632
  }
16529
16633
  function createCommandFile(name) {
16530
- const dir = join50(".claude", "commands");
16531
- mkdirSync17(dir, { recursive: true });
16634
+ const dir = join51(".claude", "commands");
16635
+ mkdirSync18(dir, { recursive: true });
16532
16636
  const content = `---
16533
16637
  description: Run ${name}
16534
16638
  ---
16535
16639
 
16536
16640
  Run \`assist run ${name} $ARGUMENTS 2>&1\`.
16537
16641
  `;
16538
- const filePath = join50(dir, `${name}.md`);
16539
- writeFileSync30(filePath, content);
16642
+ const filePath = join51(dir, `${name}.md`);
16643
+ writeFileSync31(filePath, content);
16540
16644
  console.log(`Created command file: ${filePath}`);
16541
16645
  }
16542
16646
  function add3() {
@@ -16559,11 +16663,11 @@ function findLinkIndex() {
16559
16663
  function parseLinkArgs() {
16560
16664
  const idx = findLinkIndex();
16561
16665
  if (idx === -1) return null;
16562
- const path54 = process.argv[idx + 1];
16666
+ const path53 = process.argv[idx + 1];
16563
16667
  const rest = process.argv.slice(idx + 2);
16564
16668
  const { value: prefix2 } = extractOption(rest, "--prefix");
16565
16669
  if (!prefix2) return null;
16566
- return { path: path54, prefix: prefix2 };
16670
+ return { path: path53, prefix: prefix2 };
16567
16671
  }
16568
16672
  function hasDuplicateLink(runList, linkPath) {
16569
16673
  return runList.some(
@@ -16592,7 +16696,7 @@ function link2() {
16592
16696
 
16593
16697
  // src/commands/run/remove.ts
16594
16698
  import { existsSync as existsSync49, unlinkSync as unlinkSync15 } from "fs";
16595
- import { join as join51 } from "path";
16699
+ import { join as join52 } from "path";
16596
16700
  function findRemoveIndex() {
16597
16701
  const idx = process.argv.indexOf("remove");
16598
16702
  if (idx === -1 || idx + 1 >= process.argv.length) return -1;
@@ -16607,7 +16711,7 @@ function parseRemoveName() {
16607
16711
  return process.argv[idx + 1];
16608
16712
  }
16609
16713
  function deleteCommandFile(name) {
16610
- const filePath = join51(".claude", "commands", `${name}.md`);
16714
+ const filePath = join52(".claude", "commands", `${name}.md`);
16611
16715
  if (existsSync49(filePath)) {
16612
16716
  unlinkSync15(filePath);
16613
16717
  console.log(`Deleted command file: ${filePath}`);
@@ -16647,9 +16751,9 @@ function registerRun(program2) {
16647
16751
 
16648
16752
  // src/commands/screenshot/index.ts
16649
16753
  import { execSync as execSync47 } from "child_process";
16650
- import { existsSync as existsSync50, mkdirSync as mkdirSync18, unlinkSync as unlinkSync16, writeFileSync as writeFileSync31 } from "fs";
16754
+ import { existsSync as existsSync50, mkdirSync as mkdirSync19, unlinkSync as unlinkSync16, writeFileSync as writeFileSync32 } from "fs";
16651
16755
  import { tmpdir as tmpdir7 } from "os";
16652
- import { join as join52, resolve as resolve13 } from "path";
16756
+ import { join as join53, resolve as resolve13 } from "path";
16653
16757
  import chalk156 from "chalk";
16654
16758
 
16655
16759
  // src/commands/screenshot/captureWindowPs1.ts
@@ -16780,14 +16884,14 @@ Write-Output $OutputPath
16780
16884
  // src/commands/screenshot/index.ts
16781
16885
  function buildOutputPath(outputDir, processName) {
16782
16886
  if (!existsSync50(outputDir)) {
16783
- mkdirSync18(outputDir, { recursive: true });
16887
+ mkdirSync19(outputDir, { recursive: true });
16784
16888
  }
16785
16889
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
16786
16890
  return resolve13(outputDir, `${processName}-${timestamp}.png`);
16787
16891
  }
16788
16892
  function runPowerShellScript(processName, outputPath) {
16789
- const scriptPath = join52(tmpdir7(), `assist-screenshot-${Date.now()}.ps1`);
16790
- writeFileSync31(scriptPath, captureWindowPs1, "utf-8");
16893
+ const scriptPath = join53(tmpdir7(), `assist-screenshot-${Date.now()}.ps1`);
16894
+ writeFileSync32(scriptPath, captureWindowPs1, "utf-8");
16791
16895
  try {
16792
16896
  execSync47(
16793
16897
  `powershell -NoProfile -ExecutionPolicy Bypass -File "${scriptPath}" -ProcessName "${processName}" -OutputPath "${outputPath}"`,
@@ -16863,7 +16967,7 @@ function applyLine(result, pending, line) {
16863
16967
  }
16864
16968
 
16865
16969
  // src/commands/sessions/daemon/reportStolenSocket.ts
16866
- import { readFileSync as readFileSync39 } from "fs";
16970
+ import { readFileSync as readFileSync40 } from "fs";
16867
16971
  function reportStolenSocket(socketPid) {
16868
16972
  if (!socketPid) return;
16869
16973
  const filePid = readPidFile();
@@ -16875,7 +16979,7 @@ function reportStolenSocket(socketPid) {
16875
16979
  function readPidFile() {
16876
16980
  try {
16877
16981
  const pid = Number.parseInt(
16878
- readFileSync39(daemonPaths.pid, "utf-8").trim(),
16982
+ readFileSync40(daemonPaths.pid, "utf-8").trim(),
16879
16983
  10
16880
16984
  );
16881
16985
  return Number.isInteger(pid) ? pid : void 0;
@@ -16962,7 +17066,7 @@ async function restartDaemon() {
16962
17066
  }
16963
17067
 
16964
17068
  // src/commands/sessions/daemon/runDaemon.ts
16965
- import { mkdirSync as mkdirSync19 } from "fs";
17069
+ import { mkdirSync as mkdirSync21 } from "fs";
16966
17070
 
16967
17071
  // src/commands/sessions/daemon/createAutoExit.ts
16968
17072
  var DEFAULT_GRACE_MS = 6e4;
@@ -17122,27 +17226,20 @@ function broadcast(clients, msg) {
17122
17226
  }
17123
17227
  }
17124
17228
 
17125
- // src/commands/sessions/daemon/repoPrefix.ts
17126
- import * as path47 from "path";
17127
- function repoPrefix(cwd) {
17128
- if (!cwd) return "";
17129
- return `${path47.basename(cwd)}/`;
17130
- }
17131
-
17132
17229
  // src/commands/sessions/daemon/spawnPty.ts
17133
17230
  import * as pty from "node-pty";
17134
17231
 
17135
17232
  // src/commands/sessions/daemon/ensureSpawnHelperExecutable.ts
17136
17233
  import { chmodSync, existsSync as existsSync51, statSync as statSync6 } from "fs";
17137
17234
  import { createRequire as createRequire3 } from "module";
17138
- import path48 from "path";
17235
+ import path47 from "path";
17139
17236
  var require4 = createRequire3(import.meta.url);
17140
17237
  var ensured = false;
17141
17238
  function ensureSpawnHelperExecutable() {
17142
17239
  if (ensured || process.platform !== "darwin") return;
17143
17240
  ensured = true;
17144
- const ptyRoot = path48.join(path48.dirname(require4.resolve("node-pty")), "..");
17145
- const helper = path48.join(
17241
+ const ptyRoot = path47.join(path47.dirname(require4.resolve("node-pty")), "..");
17242
+ const helper = path47.join(
17146
17243
  ptyRoot,
17147
17244
  "prebuilds",
17148
17245
  `${process.platform}-${process.arch}`,
@@ -17154,7 +17251,7 @@ function ensureSpawnHelperExecutable() {
17154
17251
  }
17155
17252
 
17156
17253
  // src/commands/sessions/daemon/spawnPty.ts
17157
- function spawnPty(args, cwd) {
17254
+ function spawnPty(args, cwd, sessionId) {
17158
17255
  ensureSpawnHelperExecutable();
17159
17256
  const shell = process.platform === "win32" ? "cmd.exe" : process.env.SHELL ?? "bash";
17160
17257
  const shellArgs = process.platform === "win32" ? ["/c", ...args] : ["-c", `exec ${args.map(shellEscape).join(" ")}`];
@@ -17163,7 +17260,13 @@ function spawnPty(args, cwd) {
17163
17260
  cols: 120,
17164
17261
  rows: 30,
17165
17262
  cwd: cwd ?? process.cwd(),
17166
- env: { ...process.env }
17263
+ env: {
17264
+ ...process.env,
17265
+ ...sessionId && {
17266
+ ASSIST_SESSION_ID: sessionId,
17267
+ ASSIST_ACTIVITY_ID: sessionId
17268
+ }
17269
+ }
17167
17270
  });
17168
17271
  }
17169
17272
  function shellEscape(s) {
@@ -17174,11 +17277,11 @@ function shellEscape(s) {
17174
17277
  function createAssistSession(id, assistArgs, cwd) {
17175
17278
  return {
17176
17279
  id,
17177
- name: `${repoPrefix(cwd)}assist ${assistArgs.join(" ")}`,
17280
+ name: `assist ${assistArgs.join(" ")}`,
17178
17281
  commandType: "assist",
17179
17282
  status: "running",
17180
17283
  startedAt: Date.now(),
17181
- pty: spawnPty(["assist", ...assistArgs], cwd),
17284
+ pty: spawnPty(["assist", ...assistArgs], cwd, id),
17182
17285
  scrollback: "",
17183
17286
  idleTimer: null,
17184
17287
  lastResizeAt: 0,
@@ -17206,7 +17309,7 @@ function spawnRun(opts) {
17206
17309
  function createSession(id, prompt, cwd) {
17207
17310
  return {
17208
17311
  id,
17209
- name: `${repoPrefix(cwd)}${prompt?.slice(0, 40) || `Session ${id}`}`,
17312
+ name: prompt?.slice(0, 40) || `Session ${id}`,
17210
17313
  commandType: "claude",
17211
17314
  status: "running",
17212
17315
  startedAt: Date.now(),
@@ -17220,7 +17323,7 @@ function createSession(id, prompt, cwd) {
17220
17323
  function createRunSession(id, runName, runArgs, cwd) {
17221
17324
  return {
17222
17325
  id,
17223
- name: `${repoPrefix(cwd)}run: ${runName}`,
17326
+ name: `run: ${runName}`,
17224
17327
  commandType: "run",
17225
17328
  status: "running",
17226
17329
  startedAt: Date.now(),
@@ -17334,7 +17437,7 @@ function restoreSession(id, persisted) {
17334
17437
  function resumeSession(id, sessionId, cwd, name) {
17335
17438
  return {
17336
17439
  id,
17337
- name: `${repoPrefix(cwd)}${name ? `${name.slice(0, 36)} (R)` : `Resume ${sessionId.slice(0, 8)}`}`,
17440
+ name: name ? `${name.slice(0, 36)} (R)` : `Resume ${sessionId.slice(0, 8)}`,
17338
17441
  commandType: "claude",
17339
17442
  status: "running",
17340
17443
  startedAt: Date.now(),
@@ -17406,7 +17509,7 @@ function respawnThunk(session) {
17406
17509
  if (session.commandType === "run" && runName)
17407
17510
  return () => spawnRun({ name: runName, args: runArgs, cwd });
17408
17511
  if (session.commandType === "assist" && assistArgs)
17409
- return () => spawnPty(["assist", ...assistArgs], cwd);
17512
+ return () => spawnPty(["assist", ...assistArgs], cwd, session.id);
17410
17513
  return null;
17411
17514
  }
17412
17515
 
@@ -17427,8 +17530,10 @@ function toSessionInfo({
17427
17530
  startedAt,
17428
17531
  runName,
17429
17532
  runArgs,
17533
+ assistArgs,
17430
17534
  cwd,
17431
- restored
17535
+ restored,
17536
+ activity: activity2
17432
17537
  }) {
17433
17538
  return {
17434
17539
  id,
@@ -17438,14 +17543,45 @@ function toSessionInfo({
17438
17543
  startedAt,
17439
17544
  runName,
17440
17545
  runArgs,
17546
+ assistArgs,
17441
17547
  cwd,
17442
- restored
17548
+ restored,
17549
+ activity: activity2
17550
+ };
17551
+ }
17552
+
17553
+ // src/commands/sessions/daemon/watchActivity.ts
17554
+ import { existsSync as existsSync52, mkdirSync as mkdirSync20, watch } from "fs";
17555
+ import { dirname as dirname27 } from "path";
17556
+ var DEBOUNCE_MS = 50;
17557
+ function watchActivity(session, notify2) {
17558
+ if (session.commandType !== "assist" || !session.cwd) return;
17559
+ const path53 = activityPath(session.cwd, session.id);
17560
+ const dir = dirname27(path53);
17561
+ try {
17562
+ mkdirSync20(dir, { recursive: true });
17563
+ } catch {
17564
+ return;
17565
+ }
17566
+ let timer = null;
17567
+ const read = () => {
17568
+ timer = null;
17569
+ const activity2 = readActivity(path53);
17570
+ if (!activity2) return;
17571
+ session.activity = activity2;
17572
+ notify2();
17443
17573
  };
17574
+ session.activityWatcher = watch(dir, (_event, filename) => {
17575
+ if (filename && !path53.endsWith(filename)) return;
17576
+ if (timer) clearTimeout(timer);
17577
+ timer = setTimeout(read, DEBOUNCE_MS);
17578
+ });
17579
+ if (existsSync52(path53)) read();
17444
17580
  }
17445
17581
 
17446
17582
  // src/commands/sessions/daemon/discoverClaudeSessionId.ts
17447
17583
  import * as fs26 from "fs";
17448
- import * as path49 from "path";
17584
+ import * as path48 from "path";
17449
17585
  var POLL_MS = 3e3;
17450
17586
  async function discoverClaudeSessionId(options2) {
17451
17587
  while (options2.isActive()) {
@@ -17461,7 +17597,7 @@ async function findNewSessionId(options2) {
17461
17597
  if (!await isCreatedSince(filePath, options2.sinceMs)) continue;
17462
17598
  const meta = await parseSessionFile(filePath);
17463
17599
  if (!meta?.cwd || options2.isClaimed(meta.sessionId)) continue;
17464
- if (path49.resolve(meta.cwd) === path49.resolve(options2.cwd))
17600
+ if (path48.resolve(meta.cwd) === path48.resolve(options2.cwd))
17465
17601
  return meta.sessionId;
17466
17602
  }
17467
17603
  return null;
@@ -17513,6 +17649,8 @@ function dismissSession(sessions, id) {
17513
17649
  if (!s) return false;
17514
17650
  if (s.status !== "done") s.pty?.kill();
17515
17651
  clearIdle(s);
17652
+ s.activityWatcher?.close();
17653
+ if (s.cwd) removeActivity(s.cwd, s.id);
17516
17654
  sessions.delete(id);
17517
17655
  return true;
17518
17656
  }
@@ -17551,6 +17689,7 @@ var SessionManager = class {
17551
17689
  add(session) {
17552
17690
  this.wire(session);
17553
17691
  watchForClaudeSessionId(session, this.sessions, this.notify);
17692
+ watchActivity(session, this.notify);
17554
17693
  return session.id;
17555
17694
  }
17556
17695
  spawn(prompt, cwd) {
@@ -17715,10 +17854,10 @@ function handleConnection(socket, manager) {
17715
17854
  }
17716
17855
 
17717
17856
  // src/commands/sessions/daemon/onListening.ts
17718
- import { unlinkSync as unlinkSync17, writeFileSync as writeFileSync32 } from "fs";
17857
+ import { unlinkSync as unlinkSync17, writeFileSync as writeFileSync33 } from "fs";
17719
17858
 
17720
17859
  // src/commands/sessions/daemon/startPidFileWatchdog.ts
17721
- import { readFileSync as readFileSync40 } from "fs";
17860
+ import { readFileSync as readFileSync41 } from "fs";
17722
17861
  var WATCHDOG_INTERVAL_MS = 5e3;
17723
17862
  function startPidFileWatchdog(onLost, intervalMs = WATCHDOG_INTERVAL_MS) {
17724
17863
  const timer = setInterval(() => {
@@ -17729,7 +17868,7 @@ function startPidFileWatchdog(onLost, intervalMs = WATCHDOG_INTERVAL_MS) {
17729
17868
  }
17730
17869
  function ownsPidFile() {
17731
17870
  try {
17732
- return readFileSync40(daemonPaths.pid, "utf-8").trim() === String(process.pid);
17871
+ return readFileSync41(daemonPaths.pid, "utf-8").trim() === String(process.pid);
17733
17872
  } catch {
17734
17873
  return false;
17735
17874
  }
@@ -17737,7 +17876,7 @@ function ownsPidFile() {
17737
17876
 
17738
17877
  // src/commands/sessions/daemon/onListening.ts
17739
17878
  function onListening(manager, checkAutoExit) {
17740
- writeFileSync32(daemonPaths.pid, String(process.pid));
17879
+ writeFileSync33(daemonPaths.pid, String(process.pid));
17741
17880
  startPidFileWatchdog(() => {
17742
17881
  daemonLog("lost daemon.pid ownership; shutting down sessions and exiting");
17743
17882
  manager.shutdown();
@@ -17798,7 +17937,7 @@ async function recoverFromAddrInUse(server, manager, checkAutoExit) {
17798
17937
 
17799
17938
  // src/commands/sessions/daemon/runDaemon.ts
17800
17939
  async function runDaemon() {
17801
- mkdirSync19(daemonPaths.dir, { recursive: true });
17940
+ mkdirSync21(daemonPaths.dir, { recursive: true });
17802
17941
  daemonLog(
17803
17942
  `starting (reason: ${process.env.ASSIST_DAEMON_SPAWN_REASON ?? "manual"})`
17804
17943
  );
@@ -18098,16 +18237,16 @@ async function statusLine() {
18098
18237
  // src/commands/sync.ts
18099
18238
  import * as fs32 from "fs";
18100
18239
  import * as os2 from "os";
18101
- import * as path52 from "path";
18240
+ import * as path51 from "path";
18102
18241
  import { fileURLToPath as fileURLToPath7 } from "url";
18103
18242
 
18104
18243
  // src/commands/sync/syncClaudeMd.ts
18105
18244
  import * as fs30 from "fs";
18106
- import * as path50 from "path";
18245
+ import * as path49 from "path";
18107
18246
  import chalk160 from "chalk";
18108
18247
  async function syncClaudeMd(claudeDir, targetBase, options2) {
18109
- const source = path50.join(claudeDir, "CLAUDE.md");
18110
- const target = path50.join(targetBase, "CLAUDE.md");
18248
+ const source = path49.join(claudeDir, "CLAUDE.md");
18249
+ const target = path49.join(targetBase, "CLAUDE.md");
18111
18250
  const sourceContent = fs30.readFileSync(source, "utf-8");
18112
18251
  if (fs30.existsSync(target)) {
18113
18252
  const targetContent = fs30.readFileSync(target, "utf-8");
@@ -18133,11 +18272,11 @@ async function syncClaudeMd(claudeDir, targetBase, options2) {
18133
18272
 
18134
18273
  // src/commands/sync/syncSettings.ts
18135
18274
  import * as fs31 from "fs";
18136
- import * as path51 from "path";
18275
+ import * as path50 from "path";
18137
18276
  import chalk161 from "chalk";
18138
18277
  async function syncSettings(claudeDir, targetBase, options2) {
18139
- const source = path51.join(claudeDir, "settings.json");
18140
- const target = path51.join(targetBase, "settings.json");
18278
+ const source = path50.join(claudeDir, "settings.json");
18279
+ const target = path50.join(targetBase, "settings.json");
18141
18280
  const sourceContent = fs31.readFileSync(source, "utf-8");
18142
18281
  const mergedContent = JSON.stringify(JSON.parse(sourceContent), null, " ");
18143
18282
  if (fs31.existsSync(target)) {
@@ -18173,23 +18312,23 @@ async function syncSettings(claudeDir, targetBase, options2) {
18173
18312
 
18174
18313
  // src/commands/sync.ts
18175
18314
  var __filename4 = fileURLToPath7(import.meta.url);
18176
- var __dirname7 = path52.dirname(__filename4);
18315
+ var __dirname7 = path51.dirname(__filename4);
18177
18316
  async function sync(options2) {
18178
18317
  const config = loadConfig();
18179
18318
  const yes = options2?.yes ?? config.sync.autoConfirm;
18180
- const claudeDir = path52.join(__dirname7, "..", "claude");
18181
- const targetBase = path52.join(os2.homedir(), ".claude");
18319
+ const claudeDir = path51.join(__dirname7, "..", "claude");
18320
+ const targetBase = path51.join(os2.homedir(), ".claude");
18182
18321
  syncCommands(claudeDir, targetBase);
18183
18322
  await syncSettings(claudeDir, targetBase, { yes });
18184
18323
  await syncClaudeMd(claudeDir, targetBase, { yes });
18185
18324
  }
18186
18325
  function syncCommands(claudeDir, targetBase) {
18187
- const sourceDir = path52.join(claudeDir, "commands");
18188
- const targetDir = path52.join(targetBase, "commands");
18326
+ const sourceDir = path51.join(claudeDir, "commands");
18327
+ const targetDir = path51.join(targetBase, "commands");
18189
18328
  fs32.mkdirSync(targetDir, { recursive: true });
18190
18329
  const files = fs32.readdirSync(sourceDir);
18191
18330
  for (const file of files) {
18192
- fs32.copyFileSync(path52.join(sourceDir, file), path52.join(targetDir, file));
18331
+ fs32.copyFileSync(path51.join(sourceDir, file), path51.join(targetDir, file));
18193
18332
  console.log(`Copied ${file} to ${targetDir}`);
18194
18333
  }
18195
18334
  console.log(`Synced ${files.length} command(s) to ~/.claude/commands`);
@@ -18197,15 +18336,15 @@ function syncCommands(claudeDir, targetBase) {
18197
18336
 
18198
18337
  // src/commands/update.ts
18199
18338
  import { execSync as execSync48 } from "child_process";
18200
- import * as path53 from "path";
18339
+ import * as path52 from "path";
18201
18340
  function isGlobalNpmInstall(dir) {
18202
18341
  try {
18203
- const resolved = path53.resolve(dir);
18204
- if (resolved.split(path53.sep).includes("node_modules")) {
18342
+ const resolved = path52.resolve(dir);
18343
+ if (resolved.split(path52.sep).includes("node_modules")) {
18205
18344
  return true;
18206
18345
  }
18207
18346
  const globalPrefix = execSync48("npm prefix -g", { stdio: "pipe" }).toString().trim();
18208
- return resolved.toLowerCase().startsWith(path53.resolve(globalPrefix).toLowerCase());
18347
+ return resolved.toLowerCase().startsWith(path52.resolve(globalPrefix).toLowerCase());
18209
18348
  } catch {
18210
18349
  return false;
18211
18350
  }