@staff0rd/assist 0.253.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.253.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
  );
@@ -5517,7 +5608,8 @@ function buildSlashCommand(slashCommand, description) {
5517
5608
  }
5518
5609
  async function launchMode(slashCommand, options2) {
5519
5610
  pullIfConfigured();
5520
- process.env.ASSIST_SESSION_ID = String(process.pid);
5611
+ process.env.ASSIST_SESSION_ID ??= String(process.pid);
5612
+ emitActivity({ kind: "command", name: slashCommand });
5521
5613
  const { child, done: done2 } = spawnClaude(
5522
5614
  buildSlashCommand(slashCommand, options2?.description),
5523
5615
  { allowEdits: true }
@@ -5538,7 +5630,7 @@ async function launchMode(slashCommand, options2) {
5538
5630
 
5539
5631
  // src/commands/backlog/refine.ts
5540
5632
  async function pickItemForRefine() {
5541
- const items2 = await loadBacklog();
5633
+ const items2 = await loadBacklogSummaries();
5542
5634
  const active = items2.filter(
5543
5635
  (i) => i.status === "todo" || i.status === "in-progress"
5544
5636
  );
@@ -5713,10 +5805,10 @@ async function start(id) {
5713
5805
 
5714
5806
  // src/commands/backlog/stop/index.ts
5715
5807
  import chalk68 from "chalk";
5716
- import { and as and5, eq as eq20 } from "drizzle-orm";
5808
+ import { and as and5, eq as eq22 } from "drizzle-orm";
5717
5809
  async function stop() {
5718
5810
  const { orm } = await getReady();
5719
- 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 });
5720
5812
  if (stopped.length === 0) {
5721
5813
  console.log(chalk68.yellow("No in-progress items to stop."));
5722
5814
  return;
@@ -5751,18 +5843,18 @@ function registerStatusCommands(cmd) {
5751
5843
 
5752
5844
  // src/commands/backlog/removePhase.ts
5753
5845
  import chalk71 from "chalk";
5754
- import { and as and8, eq as eq23 } from "drizzle-orm";
5846
+ import { and as and8, eq as eq25 } from "drizzle-orm";
5755
5847
 
5756
5848
  // src/commands/backlog/findPhase.ts
5757
5849
  import chalk70 from "chalk";
5758
- 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";
5759
5851
  async function findPhase(id, phase) {
5760
5852
  const found = await findOneItem(id);
5761
5853
  if (!found) return void 0;
5762
5854
  const { orm, item } = found;
5763
5855
  const itemId = item.id;
5764
5856
  const phaseIdx = Number.parseInt(phase, 10) - 1;
5765
- 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)));
5766
5858
  if (!row || row.cnt === 0) {
5767
5859
  console.log(
5768
5860
  chalk70.red(`Phase ${phaseIdx + 1} not found on item #${itemId}.`)
@@ -5774,14 +5866,14 @@ async function findPhase(id, phase) {
5774
5866
  }
5775
5867
 
5776
5868
  // src/commands/backlog/reindexPhases.ts
5777
- 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";
5778
5870
  async function reindexPhases(db, itemId) {
5779
- 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));
5780
5872
  for (let i = 0; i < remaining.length; i++) {
5781
5873
  const oldIdx = remaining[i].idx;
5782
5874
  if (oldIdx === i) continue;
5783
- await db.update(planTasks).set({ phaseIdx: i }).where(and7(eq22(planTasks.itemId, itemId), eq22(planTasks.phaseIdx, oldIdx)));
5784
- 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)));
5785
5877
  }
5786
5878
  }
5787
5879
  async function adjustCurrentPhase(db, item, removedIdx) {
@@ -5789,13 +5881,13 @@ async function adjustCurrentPhase(db, item, removedIdx) {
5789
5881
  if (currentPhase === void 0) return;
5790
5882
  const currentIdx = currentPhase - 1;
5791
5883
  if (removedIdx < currentIdx) {
5792
- 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));
5793
5885
  return;
5794
5886
  }
5795
5887
  if (removedIdx !== currentIdx) return;
5796
- 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));
5797
5889
  const cnt = row?.cnt ?? 0;
5798
- 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));
5799
5891
  }
5800
5892
 
5801
5893
  // src/commands/backlog/removePhase.ts
@@ -5805,9 +5897,9 @@ async function removePhase(id, phase) {
5805
5897
  const { item, orm, itemId, phaseIdx } = found;
5806
5898
  await orm.transaction(async (tx) => {
5807
5899
  await tx.delete(planTasks).where(
5808
- and8(eq23(planTasks.itemId, itemId), eq23(planTasks.phaseIdx, phaseIdx))
5900
+ and8(eq25(planTasks.itemId, itemId), eq25(planTasks.phaseIdx, phaseIdx))
5809
5901
  );
5810
- 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)));
5811
5903
  await reindexPhases(tx, itemId);
5812
5904
  await adjustCurrentPhase(tx, item, phaseIdx);
5813
5905
  });
@@ -5818,7 +5910,7 @@ async function removePhase(id, phase) {
5818
5910
 
5819
5911
  // src/commands/backlog/update/index.ts
5820
5912
  import chalk73 from "chalk";
5821
- import { eq as eq24 } from "drizzle-orm";
5913
+ import { eq as eq26 } from "drizzle-orm";
5822
5914
 
5823
5915
  // src/commands/backlog/update/parseListIndex.ts
5824
5916
  function parseListIndex(raw, length, label2) {
@@ -5952,7 +6044,7 @@ async function update(id, options2) {
5952
6044
  if (!built) return;
5953
6045
  const { orm } = found;
5954
6046
  const itemId = found.item.id;
5955
- 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));
5956
6048
  console.log(chalk73.green(`Updated ${built.fields} on item #${itemId}.`));
5957
6049
  }
5958
6050
 
@@ -5960,22 +6052,22 @@ async function update(id, options2) {
5960
6052
  import chalk74 from "chalk";
5961
6053
 
5962
6054
  // src/commands/backlog/applyPhaseUpdate.ts
5963
- import { and as and9, eq as eq25 } from "drizzle-orm";
6055
+ import { and as and9, eq as eq27 } from "drizzle-orm";
5964
6056
  async function applyPhaseUpdate(orm, itemId, phaseIdx, fields) {
5965
6057
  await orm.transaction(async (tx) => {
5966
6058
  if (fields.name) {
5967
6059
  await tx.update(planPhases).set({ name: fields.name }).where(
5968
- and9(eq25(planPhases.itemId, itemId), eq25(planPhases.idx, phaseIdx))
6060
+ and9(eq27(planPhases.itemId, itemId), eq27(planPhases.idx, phaseIdx))
5969
6061
  );
5970
6062
  }
5971
6063
  if (fields.manualCheck) {
5972
6064
  await tx.update(planPhases).set({ manualChecks: JSON.stringify(fields.manualCheck) }).where(
5973
- and9(eq25(planPhases.itemId, itemId), eq25(planPhases.idx, phaseIdx))
6065
+ and9(eq27(planPhases.itemId, itemId), eq27(planPhases.idx, phaseIdx))
5974
6066
  );
5975
6067
  }
5976
6068
  if (fields.task) {
5977
6069
  await tx.delete(planTasks).where(
5978
- and9(eq25(planTasks.itemId, itemId), eq25(planTasks.phaseIdx, phaseIdx))
6070
+ and9(eq27(planTasks.itemId, itemId), eq27(planTasks.phaseIdx, phaseIdx))
5979
6071
  );
5980
6072
  if (fields.task.length) {
5981
6073
  await tx.insert(planTasks).values(
@@ -6265,13 +6357,13 @@ function stripEnvPrefix(parts) {
6265
6357
  }
6266
6358
 
6267
6359
  // src/commands/cliHook/logDeniedToolCall.ts
6268
- import { mkdirSync as mkdirSync5 } from "fs";
6360
+ import { mkdirSync as mkdirSync6 } from "fs";
6269
6361
  import { homedir as homedir4 } from "os";
6270
- import { join as join18 } from "path";
6362
+ import { join as join19 } from "path";
6271
6363
  import Database from "better-sqlite3";
6272
6364
  var _db;
6273
6365
  function getDbDir() {
6274
- return join18(homedir4(), ".assist");
6366
+ return join19(homedir4(), ".assist");
6275
6367
  }
6276
6368
  function initSchema(db) {
6277
6369
  db.exec(`
@@ -6289,8 +6381,8 @@ function initSchema(db) {
6289
6381
  function openPromptsDb(dir) {
6290
6382
  if (_db) return _db;
6291
6383
  const dbDir = dir ?? getDbDir();
6292
- mkdirSync5(dbDir, { recursive: true });
6293
- const db = new Database(join18(dbDir, "assist.db"));
6384
+ mkdirSync6(dbDir, { recursive: true });
6385
+ const db = new Database(join19(dbDir, "assist.db"));
6294
6386
  db.pragma("journal_mode = WAL");
6295
6387
  initSchema(db);
6296
6388
  _db = db;
@@ -6392,17 +6484,17 @@ function extractGraphqlQuery(args) {
6392
6484
  }
6393
6485
 
6394
6486
  // src/shared/loadCliReads.ts
6395
- import { existsSync as existsSync21, readFileSync as readFileSync15, writeFileSync as writeFileSync14 } from "fs";
6396
- 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";
6397
6489
  import { fileURLToPath as fileURLToPath5 } from "url";
6398
6490
  var __filename3 = fileURLToPath5(import.meta.url);
6399
- var __dirname5 = dirname16(__filename3);
6491
+ var __dirname5 = dirname17(__filename3);
6400
6492
  function packageRoot() {
6401
6493
  return __dirname5;
6402
6494
  }
6403
- function readLines(path54) {
6404
- if (!existsSync21(path54)) return [];
6405
- 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() !== "");
6406
6498
  }
6407
6499
  var cachedReads;
6408
6500
  var cachedWrites;
@@ -6422,7 +6514,7 @@ function loadCliReads() {
6422
6514
  return getCliReadsLines();
6423
6515
  }
6424
6516
  function saveCliReads(commands) {
6425
- writeFileSync14(
6517
+ writeFileSync15(
6426
6518
  resolve7(packageRoot(), "allowed.cli-reads"),
6427
6519
  `${commands.join("\n")}
6428
6520
  `
@@ -6448,14 +6540,14 @@ function findCliWrite(command) {
6448
6540
  }
6449
6541
 
6450
6542
  // src/shared/readSettingsPerms.ts
6451
- import { existsSync as existsSync22, readFileSync as readFileSync16 } from "fs";
6543
+ import { existsSync as existsSync22, readFileSync as readFileSync17 } from "fs";
6452
6544
  import { homedir as homedir5 } from "os";
6453
- import { join as join19 } from "path";
6545
+ import { join as join20 } from "path";
6454
6546
  function readSettingsPerms(key) {
6455
6547
  const paths = [
6456
- join19(homedir5(), ".claude", "settings.json"),
6457
- join19(process.cwd(), ".claude", "settings.json"),
6458
- 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")
6459
6551
  ];
6460
6552
  const entries = [];
6461
6553
  for (const p of paths) {
@@ -6466,7 +6558,7 @@ function readSettingsPerms(key) {
6466
6558
  function readPermissionArray(filePath, key) {
6467
6559
  if (!existsSync22(filePath)) return [];
6468
6560
  try {
6469
- const data = JSON.parse(readFileSync16(filePath, "utf-8"));
6561
+ const data = JSON.parse(readFileSync17(filePath, "utf-8"));
6470
6562
  const arr = data?.permissions?.[key];
6471
6563
  return Array.isArray(arr) ? arr.filter((e) => typeof e === "string") : [];
6472
6564
  } catch {
@@ -6746,9 +6838,9 @@ ${reasons.join("\n")}`);
6746
6838
  }
6747
6839
 
6748
6840
  // src/commands/permitCliReads/index.ts
6749
- 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";
6750
6842
  import { homedir as homedir6 } from "os";
6751
- import { join as join20 } from "path";
6843
+ import { join as join21 } from "path";
6752
6844
 
6753
6845
  // src/shared/checkCliAvailable.ts
6754
6846
  import { execSync as execSync19 } from "child_process";
@@ -6885,14 +6977,14 @@ function showProgress(p, label2) {
6885
6977
  const pct = Math.round(p.done / p.total * 100);
6886
6978
  process.stderr.write(`\r\x1B[K[${pct}%] Scanning ${label2}...`);
6887
6979
  }
6888
- async function resolveCommand(cli, path54, description, depth, p) {
6889
- showProgress(p, path54.join(" "));
6890
- 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]);
6891
6983
  if (!subHelp || !hasSubcommands(subHelp)) {
6892
- return [{ path: path54, description }];
6984
+ return [{ path: path53, description }];
6893
6985
  }
6894
- const children = await discoverAt(cli, path54, depth + 1, p);
6895
- 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 }];
6896
6988
  }
6897
6989
  async function discoverAt(cli, parentPath, depth, p) {
6898
6990
  if (depth > SAFETY_DEPTH) return [];
@@ -7037,17 +7129,17 @@ function updateSettings(cli, commands) {
7037
7129
  // src/commands/permitCliReads/index.ts
7038
7130
  function logPath(cli) {
7039
7131
  const safeName = cli.replace(/\s+/g, "-");
7040
- return join20(homedir6(), ".assist", `cli-discover-${safeName}.log`);
7132
+ return join21(homedir6(), ".assist", `cli-discover-${safeName}.log`);
7041
7133
  }
7042
7134
  function readCache(cli) {
7043
- const path54 = logPath(cli);
7044
- if (!existsSync23(path54)) return void 0;
7045
- return readFileSync17(path54, "utf-8");
7135
+ const path53 = logPath(cli);
7136
+ if (!existsSync23(path53)) return void 0;
7137
+ return readFileSync18(path53, "utf-8");
7046
7138
  }
7047
7139
  function writeCache(cli, output) {
7048
- const dir = join20(homedir6(), ".assist");
7049
- mkdirSync6(dir, { recursive: true });
7050
- writeFileSync15(logPath(cli), output);
7140
+ const dir = join21(homedir6(), ".assist");
7141
+ mkdirSync7(dir, { recursive: true });
7142
+ writeFileSync16(logPath(cli), output);
7051
7143
  }
7052
7144
  async function permitCliReads(cli, options2 = { noCache: false }) {
7053
7145
  if (!cli) {
@@ -7641,6 +7733,11 @@ async function analyze(pattern2) {
7641
7733
  await halstead(file);
7642
7734
  console.log();
7643
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
+ );
7644
7741
  await maintainability(file);
7645
7742
  return;
7646
7743
  }
@@ -7707,8 +7804,8 @@ function stepIntoNested(container, key, nextKey) {
7707
7804
  }
7708
7805
  return ensureObject(container, resolved);
7709
7806
  }
7710
- function setNestedValue(obj, path54, value) {
7711
- const keys = path54.split(".");
7807
+ function setNestedValue(obj, path53, value) {
7808
+ const keys = path53.split(".");
7712
7809
  const result = { ...obj };
7713
7810
  let current = result;
7714
7811
  for (let i = 0; i < keys.length - 1; i++) {
@@ -7788,9 +7885,9 @@ function isTraversable(value) {
7788
7885
  function stepInto(current, key) {
7789
7886
  return isTraversable(current) ? current[key] : void 0;
7790
7887
  }
7791
- function getNestedValue(obj, path54) {
7888
+ function getNestedValue(obj, path53) {
7792
7889
  let current = obj;
7793
- for (const key of path54.split(".")) current = stepInto(current, key);
7890
+ for (const key of path53.split(".")) current = stepInto(current, key);
7794
7891
  return current;
7795
7892
  }
7796
7893
 
@@ -7824,7 +7921,7 @@ function registerConfig(program2) {
7824
7921
  }
7825
7922
 
7826
7923
  // src/commands/deploy/redirect.ts
7827
- 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";
7828
7925
  import chalk87 from "chalk";
7829
7926
  var TRAILING_SLASH_SCRIPT = ` <script>
7830
7927
  if (!window.location.pathname.endsWith('/')) {
@@ -7837,7 +7934,7 @@ function redirect() {
7837
7934
  console.log(chalk87.yellow("No index.html found"));
7838
7935
  return;
7839
7936
  }
7840
- const content = readFileSync18(indexPath, "utf-8");
7937
+ const content = readFileSync19(indexPath, "utf-8");
7841
7938
  if (content.includes("window.location.pathname.endsWith('/')")) {
7842
7939
  console.log(chalk87.dim("Trailing slash script already present"));
7843
7940
  return;
@@ -7848,7 +7945,7 @@ function redirect() {
7848
7945
  return;
7849
7946
  }
7850
7947
  const newContent = content.slice(0, headCloseIndex) + TRAILING_SLASH_SCRIPT + "\n " + content.slice(headCloseIndex);
7851
- writeFileSync16(indexPath, newContent);
7948
+ writeFileSync17(indexPath, newContent);
7852
7949
  console.log(chalk87.green("Added trailing slash redirect to index.html"));
7853
7950
  }
7854
7951
 
@@ -7865,10 +7962,10 @@ import { basename as basename4 } from "path";
7865
7962
 
7866
7963
  // src/commands/devlog/loadBlogSkipDays.ts
7867
7964
  import { homedir as homedir7 } from "os";
7868
- import { join as join21 } from "path";
7869
- var BLOG_REPO_ROOT = join21(homedir7(), "git/blog");
7965
+ import { join as join22 } from "path";
7966
+ var BLOG_REPO_ROOT = join22(homedir7(), "git/blog");
7870
7967
  function loadBlogSkipDays(repoName) {
7871
- const config = loadRawYaml(join21(BLOG_REPO_ROOT, "assist.yml"));
7968
+ const config = loadRawYaml(join22(BLOG_REPO_ROOT, "assist.yml"));
7872
7969
  const devlog = config.devlog;
7873
7970
  const skip2 = devlog?.skip;
7874
7971
  return new Set(skip2?.[repoName] ?? []);
@@ -7879,17 +7976,17 @@ import { execSync as execSync20 } from "child_process";
7879
7976
  import chalk88 from "chalk";
7880
7977
 
7881
7978
  // src/shared/getRepoName.ts
7882
- import { existsSync as existsSync25, readFileSync as readFileSync19 } from "fs";
7883
- 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";
7884
7981
  function getRepoName() {
7885
7982
  const config = loadConfig();
7886
7983
  if (config.devlog?.name) {
7887
7984
  return config.devlog.name;
7888
7985
  }
7889
- const packageJsonPath = join22(process.cwd(), "package.json");
7986
+ const packageJsonPath = join23(process.cwd(), "package.json");
7890
7987
  if (existsSync25(packageJsonPath)) {
7891
7988
  try {
7892
- const content = readFileSync19(packageJsonPath, "utf-8");
7989
+ const content = readFileSync20(packageJsonPath, "utf-8");
7893
7990
  const pkg = JSON.parse(content);
7894
7991
  if (pkg.name) {
7895
7992
  return pkg.name;
@@ -7901,9 +7998,9 @@ function getRepoName() {
7901
7998
  }
7902
7999
 
7903
8000
  // src/commands/devlog/loadDevlogEntries.ts
7904
- import { readdirSync, readFileSync as readFileSync20 } from "fs";
7905
- import { join as join23 } from "path";
7906
- 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");
7907
8004
  function extractFrontmatter(content) {
7908
8005
  const fm = content.match(/^---\n([\s\S]*?)\n---/);
7909
8006
  return fm?.[1] ?? null;
@@ -7931,7 +8028,7 @@ function readDevlogFiles(callback) {
7931
8028
  try {
7932
8029
  const files = readdirSync(DEVLOG_DIR).filter((f) => f.endsWith(".md"));
7933
8030
  for (const file of files) {
7934
- const content = readFileSync20(join23(DEVLOG_DIR, file), "utf-8");
8031
+ const content = readFileSync21(join24(DEVLOG_DIR, file), "utf-8");
7935
8032
  const parsed = parseFrontmatter(content, file);
7936
8033
  if (parsed) callback(parsed);
7937
8034
  }
@@ -8318,12 +8415,12 @@ function repos(options2) {
8318
8415
  }
8319
8416
 
8320
8417
  // src/commands/devlog/skip.ts
8321
- import { writeFileSync as writeFileSync17 } from "fs";
8322
- import { join as join24 } from "path";
8418
+ import { writeFileSync as writeFileSync18 } from "fs";
8419
+ import { join as join25 } from "path";
8323
8420
  import chalk93 from "chalk";
8324
8421
  import { stringify as stringifyYaml3 } from "yaml";
8325
8422
  function getBlogConfigPath() {
8326
- return join24(BLOG_REPO_ROOT, "assist.yml");
8423
+ return join25(BLOG_REPO_ROOT, "assist.yml");
8327
8424
  }
8328
8425
  function skip(date) {
8329
8426
  if (!/^\d{4}-\d{2}-\d{2}$/.test(date)) {
@@ -8347,7 +8444,7 @@ function skip(date) {
8347
8444
  skip2[repoName] = skipDays;
8348
8445
  devlog.skip = skip2;
8349
8446
  config.devlog = devlog;
8350
- writeFileSync17(configPath, stringifyYaml3(config, { lineWidth: 0 }));
8447
+ writeFileSync18(configPath, stringifyYaml3(config, { lineWidth: 0 }));
8351
8448
  console.log(chalk93.green(`Added ${date} to skip list for ${repoName}`));
8352
8449
  }
8353
8450
 
@@ -8384,7 +8481,7 @@ function registerDevlog(program2) {
8384
8481
 
8385
8482
  // src/commands/dotnet/checkBuildLocks.ts
8386
8483
  import { closeSync as closeSync2, openSync as openSync2, readdirSync as readdirSync2 } from "fs";
8387
- import { join as join25 } from "path";
8484
+ import { join as join26 } from "path";
8388
8485
  import chalk95 from "chalk";
8389
8486
 
8390
8487
  // src/shared/findRepoRoot.ts
@@ -8412,7 +8509,7 @@ function isLockedDll(debugDir) {
8412
8509
  }
8413
8510
  for (const file of files) {
8414
8511
  if (!file.toLowerCase().endsWith(".dll")) continue;
8415
- const dllPath = join25(debugDir, file);
8512
+ const dllPath = join26(debugDir, file);
8416
8513
  try {
8417
8514
  const fd = openSync2(dllPath, "r+");
8418
8515
  closeSync2(fd);
@@ -8430,13 +8527,13 @@ function findFirstLockedDll(dir) {
8430
8527
  return null;
8431
8528
  }
8432
8529
  if (entries.includes("bin")) {
8433
- const locked = isLockedDll(join25(dir, "bin", "Debug"));
8530
+ const locked = isLockedDll(join26(dir, "bin", "Debug"));
8434
8531
  if (locked) return locked;
8435
8532
  }
8436
8533
  for (const entry of entries) {
8437
8534
  if (SKIP_DIRS.has(entry) || entry === "bin" || entry.startsWith("."))
8438
8535
  continue;
8439
- const found = findFirstLockedDll(join25(dir, entry));
8536
+ const found = findFirstLockedDll(join26(dir, entry));
8440
8537
  if (found) return found;
8441
8538
  }
8442
8539
  return null;
@@ -8459,11 +8556,11 @@ async function checkBuildLocksCommand() {
8459
8556
  }
8460
8557
 
8461
8558
  // src/commands/dotnet/buildTree.ts
8462
- import { readFileSync as readFileSync21 } from "fs";
8559
+ import { readFileSync as readFileSync22 } from "fs";
8463
8560
  import path21 from "path";
8464
8561
  var PROJECT_REF_RE = /<ProjectReference\s+Include="([^"]+)"/g;
8465
8562
  function getProjectRefs(csprojPath) {
8466
- const content = readFileSync21(csprojPath, "utf-8");
8563
+ const content = readFileSync22(csprojPath, "utf-8");
8467
8564
  const refs = [];
8468
8565
  for (const match of content.matchAll(PROJECT_REF_RE)) {
8469
8566
  refs.push(match[1].replace(/\\/g, "/"));
@@ -8480,7 +8577,7 @@ function buildTree(csprojPath, repoRoot, visited = /* @__PURE__ */ new Set()) {
8480
8577
  for (const ref of getProjectRefs(abs)) {
8481
8578
  const childAbs = path21.resolve(dir, ref);
8482
8579
  try {
8483
- readFileSync21(childAbs);
8580
+ readFileSync22(childAbs);
8484
8581
  node.children.push(buildTree(childAbs, repoRoot, visited));
8485
8582
  } catch {
8486
8583
  node.children.push({
@@ -8505,7 +8602,7 @@ function collectAllDeps(node) {
8505
8602
  }
8506
8603
 
8507
8604
  // src/commands/dotnet/findContainingSolutions.ts
8508
- 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";
8509
8606
  import path22 from "path";
8510
8607
  function findSlnFiles(dir, maxDepth, depth = 0) {
8511
8608
  if (depth > maxDepth) return [];
@@ -8540,7 +8637,7 @@ function findContainingSolutions(csprojPath, repoRoot) {
8540
8637
  const pattern2 = new RegExp(`[\\\\"/]${escapeRegex(csprojBasename)}"`);
8541
8638
  for (const sln of slnFiles) {
8542
8639
  try {
8543
- const content = readFileSync22(sln, "utf-8");
8640
+ const content = readFileSync23(sln, "utf-8");
8544
8641
  if (pattern2.test(content)) {
8545
8642
  matches.push(path22.relative(repoRoot, sln));
8546
8643
  }
@@ -8783,11 +8880,11 @@ import chalk101 from "chalk";
8783
8880
 
8784
8881
  // src/commands/dotnet/findSolution.ts
8785
8882
  import { readdirSync as readdirSync4 } from "fs";
8786
- import { dirname as dirname17, join as join26 } from "path";
8883
+ import { dirname as dirname18, join as join27 } from "path";
8787
8884
  import chalk100 from "chalk";
8788
8885
  function findSlnInDir(dir) {
8789
8886
  try {
8790
- 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));
8791
8888
  } catch {
8792
8889
  return [];
8793
8890
  }
@@ -8808,7 +8905,7 @@ function findSolution() {
8808
8905
  process.exit(1);
8809
8906
  }
8810
8907
  if (current === ceiling) break;
8811
- current = dirname17(current);
8908
+ current = dirname18(current);
8812
8909
  }
8813
8910
  console.error(chalk100.red("No .sln file found between cwd and repo root"));
8814
8911
  process.exit(1);
@@ -8858,7 +8955,7 @@ function parseInspectReport(json) {
8858
8955
 
8859
8956
  // src/commands/dotnet/runInspectCode.ts
8860
8957
  import { execSync as execSync24 } from "child_process";
8861
- 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";
8862
8959
  import { tmpdir as tmpdir3 } from "os";
8863
8960
  import path25 from "path";
8864
8961
  import chalk102 from "chalk";
@@ -8893,7 +8990,7 @@ function runInspectCode(slnPath, include, swea) {
8893
8990
  console.error(chalk102.red("Report file not generated"));
8894
8991
  process.exit(1);
8895
8992
  }
8896
- const xml = readFileSync23(reportPath, "utf-8");
8993
+ const xml = readFileSync24(reportPath, "utf-8");
8897
8994
  unlinkSync6(reportPath);
8898
8995
  return xml;
8899
8996
  }
@@ -9020,9 +9117,9 @@ function aggregateCommitters(authorLists) {
9020
9117
 
9021
9118
  // src/shared/runGhGraphql.ts
9022
9119
  import { spawnSync as spawnSync2 } from "child_process";
9023
- import { unlinkSync as unlinkSync7, writeFileSync as writeFileSync18 } from "fs";
9120
+ import { unlinkSync as unlinkSync7, writeFileSync as writeFileSync19 } from "fs";
9024
9121
  import { tmpdir as tmpdir4 } from "os";
9025
- import { join as join27 } from "path";
9122
+ import { join as join28 } from "path";
9026
9123
  function buildArgs(queryFile, vars) {
9027
9124
  const args = ["api", "graphql", "-F", `query=@${queryFile}`];
9028
9125
  for (const [key, value] of Object.entries(vars)) {
@@ -9032,8 +9129,8 @@ function buildArgs(queryFile, vars) {
9032
9129
  return args;
9033
9130
  }
9034
9131
  function runGhGraphql(mutation, vars) {
9035
- const queryFile = join27(tmpdir4(), `gh-query-${Date.now()}.graphql`);
9036
- writeFileSync18(queryFile, mutation);
9132
+ const queryFile = join28(tmpdir4(), `gh-query-${Date.now()}.graphql`);
9133
+ writeFileSync19(queryFile, mutation);
9037
9134
  try {
9038
9135
  const result = spawnSync2("gh", buildArgs(queryFile, vars), {
9039
9136
  encoding: "utf-8"
@@ -9210,8 +9307,8 @@ function registerGithub(program2) {
9210
9307
  }
9211
9308
 
9212
9309
  // src/commands/handover/archive.ts
9213
- import { existsSync as existsSync30, mkdirSync as mkdirSync7, renameSync as renameSync2 } from "fs";
9214
- 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";
9215
9312
 
9216
9313
  // src/commands/handover/formatArchiveTimestamp.ts
9217
9314
  function formatArchiveTimestamp(date = /* @__PURE__ */ new Date()) {
@@ -9226,9 +9323,9 @@ function formatArchiveTimestamp(date = /* @__PURE__ */ new Date()) {
9226
9323
  }
9227
9324
 
9228
9325
  // src/commands/handover/getHandoverArchiveDir.ts
9229
- import { join as join28 } from "path";
9326
+ import { join as join29 } from "path";
9230
9327
  function getHandoverArchiveDir(cwd = process.cwd()) {
9231
- return join28(cwd, ".assist", "handovers", "archive");
9328
+ return join29(cwd, ".assist", "handovers", "archive");
9232
9329
  }
9233
9330
 
9234
9331
  // src/commands/handover/archive.ts
@@ -9238,11 +9335,11 @@ function buildArchiveFilename(timestamp, suffix) {
9238
9335
  return `${base}.md`;
9239
9336
  }
9240
9337
  function resolveCollisionPath(archiveDir, timestamp, suffix) {
9241
- const initial = join29(archiveDir, buildArchiveFilename(timestamp, suffix));
9338
+ const initial = join30(archiveDir, buildArchiveFilename(timestamp, suffix));
9242
9339
  if (!existsSync30(initial)) return initial;
9243
9340
  for (let i = 1; i <= MAX_COLLISION_SUFFIX; i++) {
9244
9341
  const collisionSuffix = suffix ? `${suffix}-${i}` : `${i}`;
9245
- const candidate = join29(
9342
+ const candidate = join30(
9246
9343
  archiveDir,
9247
9344
  buildArchiveFilename(timestamp, collisionSuffix)
9248
9345
  );
@@ -9257,7 +9354,7 @@ function archive(options2 = {}) {
9257
9354
  const handoverPath = getHandoverPath(cwd);
9258
9355
  if (!existsSync30(handoverPath)) return void 0;
9259
9356
  const archiveDir = getHandoverArchiveDir(cwd);
9260
- mkdirSync7(archiveDir, { recursive: true });
9357
+ mkdirSync8(archiveDir, { recursive: true });
9261
9358
  const timestamp = formatArchiveTimestamp(options2.now);
9262
9359
  const destination = resolveCollisionPath(
9263
9360
  archiveDir,
@@ -9269,7 +9366,7 @@ function archive(options2 = {}) {
9269
9366
  }
9270
9367
 
9271
9368
  // src/commands/handover/load.ts
9272
- import { existsSync as existsSync31, readFileSync as readFileSync25 } from "fs";
9369
+ import { existsSync as existsSync31, readFileSync as readFileSync26 } from "fs";
9273
9370
 
9274
9371
  // src/commands/handover/parseLoadInput.ts
9275
9372
  async function parseLoadInput(stdin) {
@@ -9385,7 +9482,7 @@ function normaliseOutput(raw) {
9385
9482
  function loadFromHandover(cwd) {
9386
9483
  const handoverPath = getHandoverPath(cwd);
9387
9484
  if (!existsSync31(handoverPath)) return void 0;
9388
- const content = readFileSync25(handoverPath, "utf-8");
9485
+ const content = readFileSync26(handoverPath, "utf-8");
9389
9486
  archive({ cwd });
9390
9487
  return {
9391
9488
  additionalContext: content,
@@ -9552,20 +9649,20 @@ function acceptanceCriteria(issueKey) {
9552
9649
  import { execSync as execSync27 } from "child_process";
9553
9650
 
9554
9651
  // src/shared/loadJson.ts
9555
- 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";
9556
9653
  import { homedir as homedir8 } from "os";
9557
- import { join as join30 } from "path";
9654
+ import { join as join31 } from "path";
9558
9655
  function getStoreDir() {
9559
- return join30(homedir8(), ".assist");
9656
+ return join31(homedir8(), ".assist");
9560
9657
  }
9561
9658
  function getStorePath(filename) {
9562
- return join30(getStoreDir(), filename);
9659
+ return join31(getStoreDir(), filename);
9563
9660
  }
9564
9661
  function loadJson(filename) {
9565
- const path54 = getStorePath(filename);
9566
- if (existsSync32(path54)) {
9662
+ const path53 = getStorePath(filename);
9663
+ if (existsSync32(path53)) {
9567
9664
  try {
9568
- return JSON.parse(readFileSync26(path54, "utf-8"));
9665
+ return JSON.parse(readFileSync27(path53, "utf-8"));
9569
9666
  } catch {
9570
9667
  return {};
9571
9668
  }
@@ -9575,9 +9672,9 @@ function loadJson(filename) {
9575
9672
  function saveJson(filename, data) {
9576
9673
  const dir = getStoreDir();
9577
9674
  if (!existsSync32(dir)) {
9578
- mkdirSync8(dir, { recursive: true });
9675
+ mkdirSync9(dir, { recursive: true });
9579
9676
  }
9580
- writeFileSync19(getStorePath(filename), JSON.stringify(data, null, 2));
9677
+ writeFileSync20(getStorePath(filename), JSON.stringify(data, null, 2));
9581
9678
  }
9582
9679
 
9583
9680
  // src/shared/promptInput.ts
@@ -9710,12 +9807,12 @@ function registerList(program2) {
9710
9807
  }
9711
9808
 
9712
9809
  // src/commands/mermaid/index.ts
9713
- import { mkdirSync as mkdirSync9, readdirSync as readdirSync5 } from "fs";
9810
+ import { mkdirSync as mkdirSync10, readdirSync as readdirSync5 } from "fs";
9714
9811
  import { resolve as resolve10 } from "path";
9715
9812
  import chalk113 from "chalk";
9716
9813
 
9717
9814
  // src/commands/mermaid/exportFile.ts
9718
- import { readFileSync as readFileSync27, writeFileSync as writeFileSync20 } from "fs";
9815
+ import { readFileSync as readFileSync28, writeFileSync as writeFileSync21 } from "fs";
9719
9816
  import { basename as basename5, extname, resolve as resolve9 } from "path";
9720
9817
  import chalk112 from "chalk";
9721
9818
 
@@ -9741,7 +9838,7 @@ async function renderBlock(krokiUrl, source) {
9741
9838
 
9742
9839
  // src/commands/mermaid/exportFile.ts
9743
9840
  async function exportFile(file, outDir, krokiUrl, onlyIndex) {
9744
- const content = readFileSync27(file, "utf8");
9841
+ const content = readFileSync28(file, "utf8");
9745
9842
  const blocks = extractMermaidBlocks(content);
9746
9843
  const stem = basename5(file, extname(file));
9747
9844
  if (onlyIndex !== void 0) {
@@ -9766,7 +9863,7 @@ async function exportFile(file, outDir, krokiUrl, onlyIndex) {
9766
9863
  if (onlyIndex !== void 0 && idx !== onlyIndex) continue;
9767
9864
  const outPath = resolve9(outDir, `${stem}-${idx}.svg`);
9768
9865
  const svg = await renderBlock(krokiUrl, source);
9769
- writeFileSync20(outPath, svg, "utf8");
9866
+ writeFileSync21(outPath, svg, "utf8");
9770
9867
  console.log(chalk112.green(` \u2192 ${outPath}`));
9771
9868
  }
9772
9869
  }
@@ -9779,7 +9876,7 @@ function extractMermaidBlocks(markdown) {
9779
9876
  async function mermaidExport(file, options2 = {}) {
9780
9877
  const { mermaid } = loadConfig();
9781
9878
  const outDir = resolve10(process.cwd(), options2.out ?? ".");
9782
- mkdirSync9(outDir, { recursive: true });
9879
+ mkdirSync10(outDir, { recursive: true });
9783
9880
  if (options2.index !== void 0) {
9784
9881
  if (!Number.isInteger(options2.index) || options2.index < 1) {
9785
9882
  console.error(
@@ -10249,15 +10346,15 @@ function postComment(vars) {
10249
10346
  }
10250
10347
  runGhGraphql(MUTATION_MULTI, { ...base, startLine });
10251
10348
  }
10252
- function comment2(path54, line, body, startLine) {
10349
+ function comment2(path53, line, body, startLine) {
10253
10350
  validateBody(body);
10254
10351
  validateLine(line);
10255
10352
  if (startLine !== void 0) validateLine(startLine);
10256
10353
  try {
10257
10354
  const prId = getCurrentPrNodeId();
10258
- postComment({ prId, body, path: path54, line, startLine });
10355
+ postComment({ prId, body, path: path53, line, startLine });
10259
10356
  const range = startLine !== void 0 ? `${startLine}-${line}` : `${line}`;
10260
- console.log(`Added review comment on ${path54}:${range}`);
10357
+ console.log(`Added review comment on ${path53}:${range}`);
10261
10358
  } catch (error) {
10262
10359
  if (isGhNotInstalled(error)) {
10263
10360
  console.error("Error: GitHub CLI (gh) is not installed.");
@@ -10335,23 +10432,23 @@ import { execSync as execSync32 } from "child_process";
10335
10432
 
10336
10433
  // src/commands/prs/resolveCommentWithReply.ts
10337
10434
  import { execSync as execSync31 } from "child_process";
10338
- import { unlinkSync as unlinkSync9, writeFileSync as writeFileSync21 } from "fs";
10435
+ import { unlinkSync as unlinkSync9, writeFileSync as writeFileSync22 } from "fs";
10339
10436
  import { tmpdir as tmpdir5 } from "os";
10340
- import { join as join32 } from "path";
10437
+ import { join as join33 } from "path";
10341
10438
 
10342
10439
  // src/commands/prs/loadCommentsCache.ts
10343
- import { existsSync as existsSync33, readFileSync as readFileSync28, unlinkSync as unlinkSync8 } from "fs";
10344
- 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";
10345
10442
  import { parse as parse2 } from "yaml";
10346
10443
  function getCachePath(prNumber) {
10347
- return join31(process.cwd(), ".assist", `pr-${prNumber}-comments.yaml`);
10444
+ return join32(process.cwd(), ".assist", `pr-${prNumber}-comments.yaml`);
10348
10445
  }
10349
10446
  function loadCommentsCache(prNumber) {
10350
10447
  const cachePath = getCachePath(prNumber);
10351
10448
  if (!existsSync33(cachePath)) {
10352
10449
  return null;
10353
10450
  }
10354
- const content = readFileSync28(cachePath, "utf-8");
10451
+ const content = readFileSync29(cachePath, "utf-8");
10355
10452
  return parse2(content);
10356
10453
  }
10357
10454
  function deleteCommentsCache(prNumber) {
@@ -10371,8 +10468,8 @@ function replyToComment(org, repo, prNumber, commentId, message) {
10371
10468
  }
10372
10469
  function resolveThread(threadId) {
10373
10470
  const mutation = `mutation($threadId: ID!) { resolveReviewThread(input: {threadId: $threadId}) { thread { isResolved } } }`;
10374
- const queryFile = join32(tmpdir5(), `gh-mutation-${Date.now()}.graphql`);
10375
- writeFileSync21(queryFile, mutation);
10471
+ const queryFile = join33(tmpdir5(), `gh-mutation-${Date.now()}.graphql`);
10472
+ writeFileSync22(queryFile, mutation);
10376
10473
  try {
10377
10474
  execSync31(
10378
10475
  `gh api graphql -F query=@${queryFile} -f threadId="${threadId}"`,
@@ -10453,19 +10550,19 @@ function fixed(commentId, sha) {
10453
10550
  }
10454
10551
 
10455
10552
  // src/commands/prs/listComments/index.ts
10456
- import { existsSync as existsSync34, mkdirSync as mkdirSync10, writeFileSync as writeFileSync23 } from "fs";
10457
- 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";
10458
10555
  import { stringify } from "yaml";
10459
10556
 
10460
10557
  // src/commands/prs/fetchThreadIds.ts
10461
10558
  import { execSync as execSync33 } from "child_process";
10462
- import { unlinkSync as unlinkSync10, writeFileSync as writeFileSync22 } from "fs";
10559
+ import { unlinkSync as unlinkSync10, writeFileSync as writeFileSync23 } from "fs";
10463
10560
  import { tmpdir as tmpdir6 } from "os";
10464
- import { join as join33 } from "path";
10561
+ import { join as join34 } from "path";
10465
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 } } } } } } }`;
10466
10563
  function fetchThreadIds(org, repo, prNumber) {
10467
- const queryFile = join33(tmpdir6(), `gh-query-${Date.now()}.graphql`);
10468
- writeFileSync22(queryFile, THREAD_QUERY);
10564
+ const queryFile = join34(tmpdir6(), `gh-query-${Date.now()}.graphql`);
10565
+ writeFileSync23(queryFile, THREAD_QUERY);
10469
10566
  try {
10470
10567
  const result = execSync33(
10471
10568
  `gh api graphql -F query=@${queryFile} -F owner="${org}" -F repo="${repo}" -F prNumber=${prNumber}`,
@@ -10578,17 +10675,17 @@ function printComments2(result) {
10578
10675
 
10579
10676
  // src/commands/prs/listComments/index.ts
10580
10677
  function writeCommentsCache(prNumber, comments3) {
10581
- const assistDir = join34(process.cwd(), ".assist");
10678
+ const assistDir = join35(process.cwd(), ".assist");
10582
10679
  if (!existsSync34(assistDir)) {
10583
- mkdirSync10(assistDir, { recursive: true });
10680
+ mkdirSync11(assistDir, { recursive: true });
10584
10681
  }
10585
10682
  const cacheData = {
10586
10683
  prNumber,
10587
10684
  fetchedAt: (/* @__PURE__ */ new Date()).toISOString(),
10588
10685
  comments: comments3
10589
10686
  };
10590
- const cachePath = join34(assistDir, `pr-${prNumber}-comments.yaml`);
10591
- writeFileSync23(cachePath, stringify(cacheData));
10687
+ const cachePath = join35(assistDir, `pr-${prNumber}-comments.yaml`);
10688
+ writeFileSync24(cachePath, stringify(cacheData));
10592
10689
  }
10593
10690
  function handleKnownErrors(error) {
10594
10691
  if (isGhNotInstalled(error)) {
@@ -10620,7 +10717,7 @@ async function listComments() {
10620
10717
  ];
10621
10718
  updateCache(prNumber, allComments);
10622
10719
  const hasLineComments = allComments.some((c) => c.type === "line");
10623
- 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;
10624
10721
  return { comments: allComments, cachePath };
10625
10722
  } catch (error) {
10626
10723
  const handled = handleKnownErrors(error);
@@ -10837,8 +10934,8 @@ function registerPrs(program2) {
10837
10934
  prsCommand.command("wontfix <comment-id> <reason>").description("Reply with reason and resolve thread").action((commentId, reason) => {
10838
10935
  wontfix(Number.parseInt(commentId, 10), reason);
10839
10936
  });
10840
- prsCommand.command("comment <path> <line> <body>").description("Add a line comment to the pending review").action((path54, line, body) => {
10841
- 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);
10842
10939
  });
10843
10940
  }
10844
10941
 
@@ -11090,10 +11187,10 @@ function resolveOpSecret(reference) {
11090
11187
  }
11091
11188
 
11092
11189
  // src/commands/ravendb/ravenFetch.ts
11093
- async function ravenFetch(connection, path54) {
11190
+ async function ravenFetch(connection, path53) {
11094
11191
  const apiKey = resolveOpSecret(connection.apiKeyRef);
11095
11192
  let accessToken = await getAccessToken(apiKey);
11096
- const url = `${connection.url}${path54}`;
11193
+ const url = `${connection.url}${path53}`;
11097
11194
  const headers = {
11098
11195
  Authorization: `Bearer ${accessToken}`,
11099
11196
  "Content-Type": "application/json"
@@ -11183,16 +11280,16 @@ import chalk129 from "chalk";
11183
11280
  // src/commands/ravendb/buildQueryPath.ts
11184
11281
  function buildQueryPath(opts) {
11185
11282
  const db = encodeURIComponent(opts.db);
11186
- let path54;
11283
+ let path53;
11187
11284
  if (opts.collection) {
11188
- 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)}`;
11189
11286
  } else {
11190
- path54 = `/databases/${db}/queries?start=${opts.start}&pageSize=${opts.pageSize}`;
11287
+ path53 = `/databases/${db}/queries?start=${opts.start}&pageSize=${opts.pageSize}`;
11191
11288
  }
11192
11289
  if (opts.query) {
11193
- path54 += `&query=${encodeURIComponent(opts.query)}`;
11290
+ path53 += `&query=${encodeURIComponent(opts.query)}`;
11194
11291
  }
11195
- return path54;
11292
+ return path53;
11196
11293
  }
11197
11294
 
11198
11295
  // src/commands/ravendb/fetchAllPages.ts
@@ -11201,7 +11298,7 @@ async function fetchAllPages(connection, opts) {
11201
11298
  let start3 = 0;
11202
11299
  while (true) {
11203
11300
  const effectivePageSize = opts.limit !== void 0 ? Math.min(opts.pageSize, opts.limit - allResults.length) : opts.pageSize;
11204
- const path54 = buildQueryPath({
11301
+ const path53 = buildQueryPath({
11205
11302
  db: connection.database,
11206
11303
  collection: opts.collection,
11207
11304
  start: start3,
@@ -11209,7 +11306,7 @@ async function fetchAllPages(connection, opts) {
11209
11306
  sort: opts.sort,
11210
11307
  query: opts.query
11211
11308
  });
11212
- const data = await ravenFetch(connection, path54);
11309
+ const data = await ravenFetch(connection, path53);
11213
11310
  const results = data.Results ?? [];
11214
11311
  const totalResults = data.TotalResults ?? 0;
11215
11312
  if (results.length === 0) break;
@@ -12427,8 +12524,8 @@ function findRootParent(file, importedBy, visited) {
12427
12524
  function clusterFiles(graph) {
12428
12525
  const clusters = /* @__PURE__ */ new Map();
12429
12526
  for (const file of graph.files) {
12430
- const basename11 = path38.basename(file, path38.extname(file));
12431
- if (basename11 === "index") continue;
12527
+ const basename10 = path38.basename(file, path38.extname(file));
12528
+ if (basename10 === "index") continue;
12432
12529
  const importers = graph.importedBy.get(file);
12433
12530
  if (!importers || importers.size !== 1) continue;
12434
12531
  const parent = [...importers][0];
@@ -12905,15 +13002,15 @@ ${context.diff.trimEnd()}
12905
13002
  }
12906
13003
 
12907
13004
  // src/commands/review/buildReviewPaths.ts
12908
- import { join as join35 } from "path";
13005
+ import { join as join36 } from "path";
12909
13006
  function buildReviewPaths(repoRoot, key) {
12910
- const reviewDir = join35(repoRoot, ".assist", "reviews", key);
13007
+ const reviewDir = join36(repoRoot, ".assist", "reviews", key);
12911
13008
  return {
12912
13009
  reviewDir,
12913
- requestPath: join35(reviewDir, "request.md"),
12914
- claudePath: join35(reviewDir, "claude.md"),
12915
- codexPath: join35(reviewDir, "codex.md"),
12916
- 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")
12917
13014
  };
12918
13015
  }
12919
13016
 
@@ -12921,24 +13018,24 @@ function buildReviewPaths(repoRoot, key) {
12921
13018
  import {
12922
13019
  appendFileSync,
12923
13020
  existsSync as existsSync35,
12924
- readFileSync as readFileSync29,
12925
- writeFileSync as writeFileSync24
13021
+ readFileSync as readFileSync30,
13022
+ writeFileSync as writeFileSync25
12926
13023
  } from "fs";
12927
- import { join as join36 } from "path";
13024
+ import { join as join37 } from "path";
12928
13025
  var REVIEWS_ENTRY = ".assist/reviews";
12929
13026
  function coversReviews(line) {
12930
13027
  const pattern2 = line.trim().replace(/^\//, "").replace(/\/$/, "");
12931
13028
  return pattern2 === ".assist" || pattern2 === REVIEWS_ENTRY;
12932
13029
  }
12933
13030
  function ensureReviewsIgnored(repoRoot) {
12934
- const gitignorePath = join36(repoRoot, ".gitignore");
13031
+ const gitignorePath = join37(repoRoot, ".gitignore");
12935
13032
  if (!existsSync35(gitignorePath)) {
12936
- writeFileSync24(gitignorePath, `${REVIEWS_ENTRY}
13033
+ writeFileSync25(gitignorePath, `${REVIEWS_ENTRY}
12937
13034
  `);
12938
13035
  console.log(`Created .gitignore with ${REVIEWS_ENTRY} entry.`);
12939
13036
  return;
12940
13037
  }
12941
- const content = readFileSync29(gitignorePath, "utf-8");
13038
+ const content = readFileSync30(gitignorePath, "utf-8");
12942
13039
  if (content.split("\n").some(coversReviews)) return;
12943
13040
  const separator = content === "" || content.endsWith("\n") ? "" : "\n";
12944
13041
  appendFileSync(gitignorePath, `${separator}${REVIEWS_ENTRY}
@@ -13085,7 +13182,7 @@ function gatherContext() {
13085
13182
  }
13086
13183
 
13087
13184
  // src/commands/review/postReviewToPr.ts
13088
- import { readFileSync as readFileSync30 } from "fs";
13185
+ import { readFileSync as readFileSync31 } from "fs";
13089
13186
 
13090
13187
  // src/commands/review/parseFindings.ts
13091
13188
  var SEVERITIES = ["blocker", "major", "minor", "nit"];
@@ -13315,7 +13412,7 @@ async function postReviewToPr(synthesisPath, options2) {
13315
13412
  console.log("No PR found for current branch; nothing posted.");
13316
13413
  return;
13317
13414
  }
13318
- const markdown = readFileSync30(synthesisPath, "utf-8");
13415
+ const markdown = readFileSync31(synthesisPath, "utf-8");
13319
13416
  const findings = parseFindings(markdown);
13320
13417
  if (findings.length === 0) {
13321
13418
  console.log("Synthesis contains no findings; nothing to post.");
@@ -13392,16 +13489,16 @@ async function handlePostSynthesis(synthesisPath, options2) {
13392
13489
  }
13393
13490
 
13394
13491
  // src/commands/review/prepareReviewDir.ts
13395
- 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";
13396
13493
  function clearReviewFiles(paths) {
13397
- for (const path54 of [paths.claudePath, paths.codexPath, paths.synthesisPath]) {
13398
- if (existsSync36(path54)) unlinkSync11(path54);
13494
+ for (const path53 of [paths.claudePath, paths.codexPath, paths.synthesisPath]) {
13495
+ if (existsSync36(path53)) unlinkSync11(path53);
13399
13496
  }
13400
13497
  }
13401
13498
  function prepareReviewDir(paths, requestBody, force) {
13402
- mkdirSync11(paths.reviewDir, { recursive: true });
13499
+ mkdirSync12(paths.reviewDir, { recursive: true });
13403
13500
  if (force) clearReviewFiles(paths);
13404
- writeFileSync25(paths.requestPath, requestBody);
13501
+ writeFileSync26(paths.requestPath, requestBody);
13405
13502
  }
13406
13503
 
13407
13504
  // src/commands/review/runApplySession.ts
@@ -13744,7 +13841,7 @@ The review request is at: ${requestPath}
13744
13841
  }
13745
13842
 
13746
13843
  // src/commands/review/runClaudeReviewer.ts
13747
- import { writeFileSync as writeFileSync26 } from "fs";
13844
+ import { writeFileSync as writeFileSync27 } from "fs";
13748
13845
 
13749
13846
  // src/commands/review/finaliseReviewerSpinner.ts
13750
13847
  var SUMMARY_MAX_LEN = 80;
@@ -14080,7 +14177,7 @@ async function runClaudeReviewer(spec) {
14080
14177
  }
14081
14178
  });
14082
14179
  if (result.exitCode === 0 && finalText)
14083
- writeFileSync26(spec.outputPath, finalText);
14180
+ writeFileSync27(spec.outputPath, finalText);
14084
14181
  return finaliseReviewerRun({ ...spec, command }, spinner, result);
14085
14182
  }
14086
14183
 
@@ -14196,7 +14293,7 @@ async function runReviewers(reviewDir, claudePath, codexPath, stdinPrompt, optio
14196
14293
  }
14197
14294
 
14198
14295
  // src/commands/review/synthesise.ts
14199
- import { readFileSync as readFileSync31 } from "fs";
14296
+ import { readFileSync as readFileSync32 } from "fs";
14200
14297
 
14201
14298
  // src/commands/review/buildSynthesisStdin.ts
14202
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.
@@ -14252,7 +14349,7 @@ Files:
14252
14349
 
14253
14350
  // src/commands/review/synthesise.ts
14254
14351
  function printSummary2(synthesisPath) {
14255
- const markdown = readFileSync31(synthesisPath, "utf-8");
14352
+ const markdown = readFileSync32(synthesisPath, "utf-8");
14256
14353
  console.log("");
14257
14354
  console.log(buildReviewSummary(markdown));
14258
14355
  console.log("");
@@ -14531,8 +14628,8 @@ import chalk147 from "chalk";
14531
14628
 
14532
14629
  // src/commands/seq/fetchSeq.ts
14533
14630
  import chalk144 from "chalk";
14534
- async function fetchSeq(conn, path54, params) {
14535
- const url = `${conn.url}${path54}?${params}`;
14631
+ async function fetchSeq(conn, path53, params) {
14632
+ const url = `${conn.url}${path53}?${params}`;
14536
14633
  const response = await fetch(url, {
14537
14634
  headers: {
14538
14635
  Accept: "application/json",
@@ -15077,7 +15174,7 @@ function registerSql(program2) {
15077
15174
 
15078
15175
  // src/commands/transcript/shared.ts
15079
15176
  import { existsSync as existsSync39, readdirSync as readdirSync6, statSync as statSync4 } from "fs";
15080
- 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";
15081
15178
  import * as readline2 from "readline";
15082
15179
  var DATE_PREFIX_REGEX = /^\d{4}-\d{2}-\d{2}/;
15083
15180
  function getDatePrefix(daysOffset = 0) {
@@ -15095,7 +15192,7 @@ function collectFiles(dir, extension) {
15095
15192
  if (!existsSync39(dir)) return [];
15096
15193
  const results = [];
15097
15194
  for (const entry of readdirSync6(dir)) {
15098
- const fullPath = join37(dir, entry);
15195
+ const fullPath = join38(dir, entry);
15099
15196
  if (statSync4(fullPath).isDirectory()) {
15100
15197
  results.push(...collectFiles(fullPath, extension));
15101
15198
  } else if (entry.endsWith(extension)) {
@@ -15192,11 +15289,11 @@ async function configure() {
15192
15289
  import { existsSync as existsSync41 } from "fs";
15193
15290
 
15194
15291
  // src/commands/transcript/format/fixInvalidDatePrefixes/index.ts
15195
- import { dirname as dirname19, join as join39 } from "path";
15292
+ import { dirname as dirname20, join as join40 } from "path";
15196
15293
 
15197
15294
  // src/commands/transcript/format/fixInvalidDatePrefixes/promptForDateFix.ts
15198
15295
  import { renameSync as renameSync3 } from "fs";
15199
- import { join as join38 } from "path";
15296
+ import { join as join39 } from "path";
15200
15297
  async function resolveDate(rl, choice) {
15201
15298
  if (choice === "1") return getDatePrefix(0);
15202
15299
  if (choice === "2") return getDatePrefix(-1);
@@ -15211,7 +15308,7 @@ async function resolveDate(rl, choice) {
15211
15308
  }
15212
15309
  function renameWithPrefix(vttDir, vttFile, prefix2) {
15213
15310
  const newFilename = `${prefix2}.${vttFile}`;
15214
- renameSync3(join38(vttDir, vttFile), join38(vttDir, newFilename));
15311
+ renameSync3(join39(vttDir, vttFile), join39(vttDir, newFilename));
15215
15312
  console.log(`Renamed to: ${newFilename}`);
15216
15313
  return newFilename;
15217
15314
  }
@@ -15242,15 +15339,15 @@ async function fixInvalidDatePrefixes(vttFiles) {
15242
15339
  for (let i = 0; i < vttFiles.length; i++) {
15243
15340
  const vttFile = vttFiles[i];
15244
15341
  if (!isValidDatePrefix(vttFile.filename)) {
15245
- const vttFileDir = dirname19(vttFile.absolutePath);
15342
+ const vttFileDir = dirname20(vttFile.absolutePath);
15246
15343
  const newFilename = await promptForDateFix(vttFile.filename, vttFileDir);
15247
15344
  if (newFilename) {
15248
- const newRelativePath = join39(
15249
- dirname19(vttFile.relativePath),
15345
+ const newRelativePath = join40(
15346
+ dirname20(vttFile.relativePath),
15250
15347
  newFilename
15251
15348
  );
15252
15349
  vttFiles[i] = {
15253
- absolutePath: join39(vttFileDir, newFilename),
15350
+ absolutePath: join40(vttFileDir, newFilename),
15254
15351
  relativePath: newRelativePath,
15255
15352
  filename: newFilename
15256
15353
  };
@@ -15263,8 +15360,8 @@ async function fixInvalidDatePrefixes(vttFiles) {
15263
15360
  }
15264
15361
 
15265
15362
  // src/commands/transcript/format/processVttFile/index.ts
15266
- import { existsSync as existsSync40, mkdirSync as mkdirSync12, readFileSync as readFileSync32, writeFileSync as writeFileSync27 } from "fs";
15267
- 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";
15268
15365
 
15269
15366
  // src/commands/transcript/cleanText.ts
15270
15367
  function cleanText(text2) {
@@ -15474,22 +15571,22 @@ function toMdFilename(vttFilename) {
15474
15571
  return `${basename7(vttFilename, ".vtt").replace(/\s*Transcription\s*/g, " ").trim()}.md`;
15475
15572
  }
15476
15573
  function resolveOutputDir(relativeDir, transcriptsDir) {
15477
- return relativeDir === "." ? transcriptsDir : join40(transcriptsDir, relativeDir);
15574
+ return relativeDir === "." ? transcriptsDir : join41(transcriptsDir, relativeDir);
15478
15575
  }
15479
15576
  function buildOutputPaths(vttFile, transcriptsDir) {
15480
15577
  const mdFile = toMdFilename(vttFile.filename);
15481
- const relativeDir = dirname20(vttFile.relativePath);
15578
+ const relativeDir = dirname21(vttFile.relativePath);
15482
15579
  const outputDir = resolveOutputDir(relativeDir, transcriptsDir);
15483
- const outputPath = join40(outputDir, mdFile);
15580
+ const outputPath = join41(outputDir, mdFile);
15484
15581
  return { outputDir, outputPath, mdFile, relativeDir };
15485
15582
  }
15486
15583
  function logSkipped(relativeDir, mdFile) {
15487
- console.log(`Skipping (already exists): ${join40(relativeDir, mdFile)}`);
15584
+ console.log(`Skipping (already exists): ${join41(relativeDir, mdFile)}`);
15488
15585
  return "skipped";
15489
15586
  }
15490
15587
  function ensureDirectory(dir, label2) {
15491
15588
  if (!existsSync40(dir)) {
15492
- mkdirSync12(dir, { recursive: true });
15589
+ mkdirSync13(dir, { recursive: true });
15493
15590
  console.log(`Created ${label2}: ${dir}`);
15494
15591
  }
15495
15592
  }
@@ -15511,10 +15608,10 @@ function logReduction(cueCount, messageCount) {
15511
15608
  }
15512
15609
  function readAndParseCues(inputPath) {
15513
15610
  console.log(`Reading: ${inputPath}`);
15514
- return processCues(readFileSync32(inputPath, "utf-8"));
15611
+ return processCues(readFileSync33(inputPath, "utf-8"));
15515
15612
  }
15516
15613
  function writeFormatted(outputPath, content) {
15517
- writeFileSync27(outputPath, content, "utf-8");
15614
+ writeFileSync28(outputPath, content, "utf-8");
15518
15615
  console.log(`Written: ${outputPath}`);
15519
15616
  }
15520
15617
  function convertVttToMarkdown(inputPath, outputPath) {
@@ -15583,17 +15680,17 @@ async function format() {
15583
15680
 
15584
15681
  // src/commands/transcript/summarise/index.ts
15585
15682
  import { existsSync as existsSync43 } from "fs";
15586
- 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";
15587
15684
 
15588
15685
  // src/commands/transcript/summarise/processStagedFile/index.ts
15589
15686
  import {
15590
15687
  existsSync as existsSync42,
15591
- mkdirSync as mkdirSync13,
15592
- readFileSync as readFileSync33,
15688
+ mkdirSync as mkdirSync14,
15689
+ readFileSync as readFileSync34,
15593
15690
  renameSync as renameSync4,
15594
- rmSync
15691
+ rmSync as rmSync2
15595
15692
  } from "fs";
15596
- import { dirname as dirname21, join as join41 } from "path";
15693
+ import { dirname as dirname22, join as join42 } from "path";
15597
15694
 
15598
15695
  // src/commands/transcript/summarise/processStagedFile/validateStagedContent.ts
15599
15696
  import chalk154 from "chalk";
@@ -15622,7 +15719,7 @@ function validateStagedContent(filename, content) {
15622
15719
  }
15623
15720
 
15624
15721
  // src/commands/transcript/summarise/processStagedFile/index.ts
15625
- var STAGING_DIR = join41(process.cwd(), ".assist", "transcript");
15722
+ var STAGING_DIR = join42(process.cwd(), ".assist", "transcript");
15626
15723
  function processStagedFile() {
15627
15724
  if (!existsSync42(STAGING_DIR)) {
15628
15725
  return false;
@@ -15633,7 +15730,7 @@ function processStagedFile() {
15633
15730
  }
15634
15731
  const { transcriptsDir, summaryDir } = getTranscriptConfig();
15635
15732
  const stagedFile = stagedFiles[0];
15636
- const content = readFileSync33(stagedFile.absolutePath, "utf-8");
15733
+ const content = readFileSync34(stagedFile.absolutePath, "utf-8");
15637
15734
  validateStagedContent(stagedFile.filename, content);
15638
15735
  const stagedBaseName = getTranscriptBaseName(stagedFile.filename);
15639
15736
  const transcriptFiles = findMdFilesRecursive(transcriptsDir);
@@ -15646,23 +15743,23 @@ function processStagedFile() {
15646
15743
  );
15647
15744
  process.exit(1);
15648
15745
  }
15649
- const destPath = join41(summaryDir, matchingTranscript.relativePath);
15650
- const destDir = dirname21(destPath);
15746
+ const destPath = join42(summaryDir, matchingTranscript.relativePath);
15747
+ const destDir = dirname22(destPath);
15651
15748
  if (!existsSync42(destDir)) {
15652
- mkdirSync13(destDir, { recursive: true });
15749
+ mkdirSync14(destDir, { recursive: true });
15653
15750
  }
15654
15751
  renameSync4(stagedFile.absolutePath, destPath);
15655
15752
  const remaining = findMdFilesRecursive(STAGING_DIR);
15656
15753
  if (remaining.length === 0) {
15657
- rmSync(STAGING_DIR, { recursive: true });
15754
+ rmSync2(STAGING_DIR, { recursive: true });
15658
15755
  }
15659
15756
  return true;
15660
15757
  }
15661
15758
 
15662
15759
  // src/commands/transcript/summarise/index.ts
15663
15760
  function buildRelativeKey(relativePath, baseName) {
15664
- const relDir = dirname22(relativePath);
15665
- return relDir === "." ? baseName : join42(relDir, baseName);
15761
+ const relDir = dirname23(relativePath);
15762
+ return relDir === "." ? baseName : join43(relDir, baseName);
15666
15763
  }
15667
15764
  function buildSummaryIndex(summaryDir) {
15668
15765
  const summaryFiles = findMdFilesRecursive(summaryDir);
@@ -15696,8 +15793,8 @@ function summarise3() {
15696
15793
  }
15697
15794
  const next3 = missing[0];
15698
15795
  const outputFilename = `${getTranscriptBaseName(next3.filename)}.md`;
15699
- const outputPath = join42(STAGING_DIR, outputFilename);
15700
- const summaryFileDir = join42(summaryDir, dirname22(next3.relativePath));
15796
+ const outputPath = join43(STAGING_DIR, outputFilename);
15797
+ const summaryFileDir = join43(summaryDir, dirname23(next3.relativePath));
15701
15798
  const relativeTranscriptPath = encodeURI(
15702
15799
  relative3(summaryFileDir, next3.absolutePath).replace(/\\/g, "/")
15703
15800
  );
@@ -15746,50 +15843,50 @@ function registerVerify(program2) {
15746
15843
 
15747
15844
  // src/commands/voice/devices.ts
15748
15845
  import { spawnSync as spawnSync4 } from "child_process";
15749
- import { join as join44 } from "path";
15846
+ import { join as join45 } from "path";
15750
15847
 
15751
15848
  // src/commands/voice/shared.ts
15752
15849
  import { homedir as homedir9 } from "os";
15753
- import { dirname as dirname23, join as join43 } from "path";
15850
+ import { dirname as dirname24, join as join44 } from "path";
15754
15851
  import { fileURLToPath as fileURLToPath6 } from "url";
15755
- var __dirname6 = dirname23(fileURLToPath6(import.meta.url));
15756
- var VOICE_DIR = join43(homedir9(), ".assist", "voice");
15852
+ var __dirname6 = dirname24(fileURLToPath6(import.meta.url));
15853
+ var VOICE_DIR = join44(homedir9(), ".assist", "voice");
15757
15854
  var voicePaths = {
15758
15855
  dir: VOICE_DIR,
15759
- pid: join43(VOICE_DIR, "voice.pid"),
15760
- log: join43(VOICE_DIR, "voice.log"),
15761
- venv: join43(VOICE_DIR, ".venv"),
15762
- 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")
15763
15860
  };
15764
15861
  function getPythonDir() {
15765
- return join43(__dirname6, "commands", "voice", "python");
15862
+ return join44(__dirname6, "commands", "voice", "python");
15766
15863
  }
15767
15864
  function getVenvPython() {
15768
- 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");
15769
15866
  }
15770
15867
  function getLockDir() {
15771
15868
  const config = loadConfig();
15772
15869
  return config.voice?.lockDir ?? VOICE_DIR;
15773
15870
  }
15774
15871
  function getLockFile() {
15775
- return join43(getLockDir(), "voice.lock");
15872
+ return join44(getLockDir(), "voice.lock");
15776
15873
  }
15777
15874
 
15778
15875
  // src/commands/voice/devices.ts
15779
15876
  function devices() {
15780
- const script = join44(getPythonDir(), "list_devices.py");
15877
+ const script = join45(getPythonDir(), "list_devices.py");
15781
15878
  spawnSync4(getVenvPython(), [script], { stdio: "inherit" });
15782
15879
  }
15783
15880
 
15784
15881
  // src/commands/voice/logs.ts
15785
- import { existsSync as existsSync44, readFileSync as readFileSync34 } from "fs";
15882
+ import { existsSync as existsSync44, readFileSync as readFileSync35 } from "fs";
15786
15883
  function logs(options2) {
15787
15884
  if (!existsSync44(voicePaths.log)) {
15788
15885
  console.log("No voice log file found");
15789
15886
  return;
15790
15887
  }
15791
15888
  const count6 = Number.parseInt(options2.lines ?? "150", 10);
15792
- const content = readFileSync34(voicePaths.log, "utf-8").trim();
15889
+ const content = readFileSync35(voicePaths.log, "utf-8").trim();
15793
15890
  if (!content) {
15794
15891
  console.log("Voice log is empty");
15795
15892
  return;
@@ -15811,13 +15908,13 @@ function logs(options2) {
15811
15908
 
15812
15909
  // src/commands/voice/setup.ts
15813
15910
  import { spawnSync as spawnSync5 } from "child_process";
15814
- import { mkdirSync as mkdirSync15 } from "fs";
15815
- import { join as join46 } from "path";
15911
+ import { mkdirSync as mkdirSync16 } from "fs";
15912
+ import { join as join47 } from "path";
15816
15913
 
15817
15914
  // src/commands/voice/checkLockFile.ts
15818
15915
  import { execSync as execSync44 } from "child_process";
15819
- import { existsSync as existsSync45, mkdirSync as mkdirSync14, readFileSync as readFileSync35, writeFileSync as writeFileSync28 } from "fs";
15820
- 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";
15821
15918
  function isProcessAlive2(pid) {
15822
15919
  try {
15823
15920
  process.kill(pid, 0);
@@ -15830,7 +15927,7 @@ function checkLockFile() {
15830
15927
  const lockFile = getLockFile();
15831
15928
  if (!existsSync45(lockFile)) return;
15832
15929
  try {
15833
- const lock = JSON.parse(readFileSync35(lockFile, "utf-8"));
15930
+ const lock = JSON.parse(readFileSync36(lockFile, "utf-8"));
15834
15931
  if (lock.pid && isProcessAlive2(lock.pid)) {
15835
15932
  console.error(
15836
15933
  `Voice daemon already running (PID ${lock.pid}, env: ${lock.env}). Stop it first with: assist voice stop`
@@ -15854,8 +15951,8 @@ function bootstrapVenv() {
15854
15951
  }
15855
15952
  function writeLockFile(pid) {
15856
15953
  const lockFile = getLockFile();
15857
- mkdirSync14(join45(lockFile, ".."), { recursive: true });
15858
- writeFileSync28(
15954
+ mkdirSync15(join46(lockFile, ".."), { recursive: true });
15955
+ writeFileSync29(
15859
15956
  lockFile,
15860
15957
  JSON.stringify({
15861
15958
  pid,
@@ -15867,10 +15964,10 @@ function writeLockFile(pid) {
15867
15964
 
15868
15965
  // src/commands/voice/setup.ts
15869
15966
  function setup() {
15870
- mkdirSync15(voicePaths.dir, { recursive: true });
15967
+ mkdirSync16(voicePaths.dir, { recursive: true });
15871
15968
  bootstrapVenv();
15872
15969
  console.log("\nDownloading models...\n");
15873
- const script = join46(getPythonDir(), "setup_models.py");
15970
+ const script = join47(getPythonDir(), "setup_models.py");
15874
15971
  const result = spawnSync5(getVenvPython(), [script], {
15875
15972
  stdio: "inherit",
15876
15973
  env: { ...process.env, VOICE_LOG_FILE: voicePaths.log }
@@ -15883,8 +15980,8 @@ function setup() {
15883
15980
 
15884
15981
  // src/commands/voice/start.ts
15885
15982
  import { spawn as spawn7 } from "child_process";
15886
- import { mkdirSync as mkdirSync16, writeFileSync as writeFileSync29 } from "fs";
15887
- import { join as join47 } from "path";
15983
+ import { mkdirSync as mkdirSync17, writeFileSync as writeFileSync30 } from "fs";
15984
+ import { join as join48 } from "path";
15888
15985
 
15889
15986
  // src/commands/voice/buildDaemonEnv.ts
15890
15987
  function buildDaemonEnv(options2) {
@@ -15912,17 +16009,17 @@ function spawnBackground(python, script, env) {
15912
16009
  console.error("Failed to start voice daemon");
15913
16010
  process.exit(1);
15914
16011
  }
15915
- writeFileSync29(voicePaths.pid, String(pid));
16012
+ writeFileSync30(voicePaths.pid, String(pid));
15916
16013
  writeLockFile(pid);
15917
16014
  console.log(`Voice daemon started (PID ${pid})`);
15918
16015
  }
15919
16016
  function start2(options2) {
15920
- mkdirSync16(voicePaths.dir, { recursive: true });
16017
+ mkdirSync17(voicePaths.dir, { recursive: true });
15921
16018
  checkLockFile();
15922
16019
  bootstrapVenv();
15923
16020
  const debug = options2.debug || options2.foreground || process.platform === "win32";
15924
16021
  const env = buildDaemonEnv({ debug });
15925
- const script = join47(getPythonDir(), "voice_daemon.py");
16022
+ const script = join48(getPythonDir(), "voice_daemon.py");
15926
16023
  const python = getVenvPython();
15927
16024
  if (options2.foreground) {
15928
16025
  spawnForeground(python, script, env);
@@ -15932,7 +16029,7 @@ function start2(options2) {
15932
16029
  }
15933
16030
 
15934
16031
  // src/commands/voice/status.ts
15935
- import { existsSync as existsSync46, readFileSync as readFileSync36 } from "fs";
16032
+ import { existsSync as existsSync46, readFileSync as readFileSync37 } from "fs";
15936
16033
  function isProcessAlive3(pid) {
15937
16034
  try {
15938
16035
  process.kill(pid, 0);
@@ -15943,7 +16040,7 @@ function isProcessAlive3(pid) {
15943
16040
  }
15944
16041
  function readRecentLogs(count6) {
15945
16042
  if (!existsSync46(voicePaths.log)) return [];
15946
- const lines = readFileSync36(voicePaths.log, "utf-8").trim().split("\n");
16043
+ const lines = readFileSync37(voicePaths.log, "utf-8").trim().split("\n");
15947
16044
  return lines.slice(-count6);
15948
16045
  }
15949
16046
  function status() {
@@ -15951,7 +16048,7 @@ function status() {
15951
16048
  console.log("Voice daemon: not running (no PID file)");
15952
16049
  return;
15953
16050
  }
15954
- const pid = Number.parseInt(readFileSync36(voicePaths.pid, "utf-8").trim(), 10);
16051
+ const pid = Number.parseInt(readFileSync37(voicePaths.pid, "utf-8").trim(), 10);
15955
16052
  const alive = isProcessAlive3(pid);
15956
16053
  console.log(`Voice daemon: ${alive ? "running" : "dead"} (PID ${pid})`);
15957
16054
  const recent = readRecentLogs(5);
@@ -15970,13 +16067,13 @@ function status() {
15970
16067
  }
15971
16068
 
15972
16069
  // src/commands/voice/stop.ts
15973
- 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";
15974
16071
  function stop2() {
15975
16072
  if (!existsSync47(voicePaths.pid)) {
15976
16073
  console.log("Voice daemon is not running (no PID file)");
15977
16074
  return;
15978
16075
  }
15979
- const pid = Number.parseInt(readFileSync37(voicePaths.pid, "utf-8").trim(), 10);
16076
+ const pid = Number.parseInt(readFileSync38(voicePaths.pid, "utf-8").trim(), 10);
15980
16077
  try {
15981
16078
  process.kill(pid, "SIGTERM");
15982
16079
  console.log(`Sent SIGTERM to voice daemon (PID ${pid})`);
@@ -16211,8 +16308,8 @@ async function auth() {
16211
16308
 
16212
16309
  // src/commands/roam/postRoamActivity.ts
16213
16310
  import { execFileSync as execFileSync7 } from "child_process";
16214
- import { readdirSync as readdirSync7, readFileSync as readFileSync38, statSync as statSync5 } from "fs";
16215
- 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";
16216
16313
  function findPortFile(roamDir) {
16217
16314
  let entries;
16218
16315
  try {
@@ -16221,9 +16318,9 @@ function findPortFile(roamDir) {
16221
16318
  return void 0;
16222
16319
  }
16223
16320
  const candidates = entries.filter((name) => /^roam-local-api(-[^.]+)?\.port$/.test(name)).map((name) => {
16224
- const path54 = join48(roamDir, name);
16321
+ const path53 = join49(roamDir, name);
16225
16322
  try {
16226
- return { path: path54, mtimeMs: statSync5(path54).mtimeMs };
16323
+ return { path: path53, mtimeMs: statSync5(path53).mtimeMs };
16227
16324
  } catch {
16228
16325
  return void 0;
16229
16326
  }
@@ -16233,11 +16330,11 @@ function findPortFile(roamDir) {
16233
16330
  function postRoamActivity(app, event) {
16234
16331
  const appData = process.env.APPDATA;
16235
16332
  if (!appData) return;
16236
- const portFile = findPortFile(join48(appData, "Roam"));
16333
+ const portFile = findPortFile(join49(appData, "Roam"));
16237
16334
  if (!portFile) return;
16238
16335
  let port;
16239
16336
  try {
16240
- port = readFileSync38(portFile, "utf-8").trim();
16337
+ port = readFileSync39(portFile, "utf-8").trim();
16241
16338
  } catch {
16242
16339
  return;
16243
16340
  }
@@ -16380,13 +16477,13 @@ function runPreCommands(pre, cwd) {
16380
16477
  // src/commands/run/spawnRunCommand.ts
16381
16478
  import { execFileSync as execFileSync8, spawn as spawn8 } from "child_process";
16382
16479
  import { existsSync as existsSync48 } from "fs";
16383
- 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";
16384
16481
  function resolveCommand2(command) {
16385
16482
  if (process.platform !== "win32" || command !== "bash") return command;
16386
16483
  try {
16387
16484
  const gitPath = execFileSync8("where", ["git"], { encoding: "utf8" }).trim().split("\r\n")[0];
16388
- const gitRoot = resolve11(dirname24(gitPath), "..");
16389
- const gitBash = join49(gitRoot, "bin", "bash.exe");
16485
+ const gitRoot = resolve11(dirname25(gitPath), "..");
16486
+ const gitBash = join50(gitRoot, "bin", "bash.exe");
16390
16487
  if (existsSync48(gitBash)) return gitBash;
16391
16488
  } catch {
16392
16489
  }
@@ -16472,8 +16569,8 @@ async function run3(name, args) {
16472
16569
  }
16473
16570
 
16474
16571
  // src/commands/run/add.ts
16475
- import { mkdirSync as mkdirSync17, writeFileSync as writeFileSync30 } from "fs";
16476
- import { join as join50 } from "path";
16572
+ import { mkdirSync as mkdirSync18, writeFileSync as writeFileSync31 } from "fs";
16573
+ import { join as join51 } from "path";
16477
16574
 
16478
16575
  // src/commands/run/extractOption.ts
16479
16576
  function extractOption(args, flag) {
@@ -16534,16 +16631,16 @@ function saveNewRunConfig(name, command, args, cwd) {
16534
16631
  saveConfig(config);
16535
16632
  }
16536
16633
  function createCommandFile(name) {
16537
- const dir = join50(".claude", "commands");
16538
- mkdirSync17(dir, { recursive: true });
16634
+ const dir = join51(".claude", "commands");
16635
+ mkdirSync18(dir, { recursive: true });
16539
16636
  const content = `---
16540
16637
  description: Run ${name}
16541
16638
  ---
16542
16639
 
16543
16640
  Run \`assist run ${name} $ARGUMENTS 2>&1\`.
16544
16641
  `;
16545
- const filePath = join50(dir, `${name}.md`);
16546
- writeFileSync30(filePath, content);
16642
+ const filePath = join51(dir, `${name}.md`);
16643
+ writeFileSync31(filePath, content);
16547
16644
  console.log(`Created command file: ${filePath}`);
16548
16645
  }
16549
16646
  function add3() {
@@ -16566,11 +16663,11 @@ function findLinkIndex() {
16566
16663
  function parseLinkArgs() {
16567
16664
  const idx = findLinkIndex();
16568
16665
  if (idx === -1) return null;
16569
- const path54 = process.argv[idx + 1];
16666
+ const path53 = process.argv[idx + 1];
16570
16667
  const rest = process.argv.slice(idx + 2);
16571
16668
  const { value: prefix2 } = extractOption(rest, "--prefix");
16572
16669
  if (!prefix2) return null;
16573
- return { path: path54, prefix: prefix2 };
16670
+ return { path: path53, prefix: prefix2 };
16574
16671
  }
16575
16672
  function hasDuplicateLink(runList, linkPath) {
16576
16673
  return runList.some(
@@ -16599,7 +16696,7 @@ function link2() {
16599
16696
 
16600
16697
  // src/commands/run/remove.ts
16601
16698
  import { existsSync as existsSync49, unlinkSync as unlinkSync15 } from "fs";
16602
- import { join as join51 } from "path";
16699
+ import { join as join52 } from "path";
16603
16700
  function findRemoveIndex() {
16604
16701
  const idx = process.argv.indexOf("remove");
16605
16702
  if (idx === -1 || idx + 1 >= process.argv.length) return -1;
@@ -16614,7 +16711,7 @@ function parseRemoveName() {
16614
16711
  return process.argv[idx + 1];
16615
16712
  }
16616
16713
  function deleteCommandFile(name) {
16617
- const filePath = join51(".claude", "commands", `${name}.md`);
16714
+ const filePath = join52(".claude", "commands", `${name}.md`);
16618
16715
  if (existsSync49(filePath)) {
16619
16716
  unlinkSync15(filePath);
16620
16717
  console.log(`Deleted command file: ${filePath}`);
@@ -16654,9 +16751,9 @@ function registerRun(program2) {
16654
16751
 
16655
16752
  // src/commands/screenshot/index.ts
16656
16753
  import { execSync as execSync47 } from "child_process";
16657
- 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";
16658
16755
  import { tmpdir as tmpdir7 } from "os";
16659
- import { join as join52, resolve as resolve13 } from "path";
16756
+ import { join as join53, resolve as resolve13 } from "path";
16660
16757
  import chalk156 from "chalk";
16661
16758
 
16662
16759
  // src/commands/screenshot/captureWindowPs1.ts
@@ -16787,14 +16884,14 @@ Write-Output $OutputPath
16787
16884
  // src/commands/screenshot/index.ts
16788
16885
  function buildOutputPath(outputDir, processName) {
16789
16886
  if (!existsSync50(outputDir)) {
16790
- mkdirSync18(outputDir, { recursive: true });
16887
+ mkdirSync19(outputDir, { recursive: true });
16791
16888
  }
16792
16889
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
16793
16890
  return resolve13(outputDir, `${processName}-${timestamp}.png`);
16794
16891
  }
16795
16892
  function runPowerShellScript(processName, outputPath) {
16796
- const scriptPath = join52(tmpdir7(), `assist-screenshot-${Date.now()}.ps1`);
16797
- writeFileSync31(scriptPath, captureWindowPs1, "utf-8");
16893
+ const scriptPath = join53(tmpdir7(), `assist-screenshot-${Date.now()}.ps1`);
16894
+ writeFileSync32(scriptPath, captureWindowPs1, "utf-8");
16798
16895
  try {
16799
16896
  execSync47(
16800
16897
  `powershell -NoProfile -ExecutionPolicy Bypass -File "${scriptPath}" -ProcessName "${processName}" -OutputPath "${outputPath}"`,
@@ -16870,7 +16967,7 @@ function applyLine(result, pending, line) {
16870
16967
  }
16871
16968
 
16872
16969
  // src/commands/sessions/daemon/reportStolenSocket.ts
16873
- import { readFileSync as readFileSync39 } from "fs";
16970
+ import { readFileSync as readFileSync40 } from "fs";
16874
16971
  function reportStolenSocket(socketPid) {
16875
16972
  if (!socketPid) return;
16876
16973
  const filePid = readPidFile();
@@ -16882,7 +16979,7 @@ function reportStolenSocket(socketPid) {
16882
16979
  function readPidFile() {
16883
16980
  try {
16884
16981
  const pid = Number.parseInt(
16885
- readFileSync39(daemonPaths.pid, "utf-8").trim(),
16982
+ readFileSync40(daemonPaths.pid, "utf-8").trim(),
16886
16983
  10
16887
16984
  );
16888
16985
  return Number.isInteger(pid) ? pid : void 0;
@@ -16969,7 +17066,7 @@ async function restartDaemon() {
16969
17066
  }
16970
17067
 
16971
17068
  // src/commands/sessions/daemon/runDaemon.ts
16972
- import { mkdirSync as mkdirSync19 } from "fs";
17069
+ import { mkdirSync as mkdirSync21 } from "fs";
16973
17070
 
16974
17071
  // src/commands/sessions/daemon/createAutoExit.ts
16975
17072
  var DEFAULT_GRACE_MS = 6e4;
@@ -17129,27 +17226,20 @@ function broadcast(clients, msg) {
17129
17226
  }
17130
17227
  }
17131
17228
 
17132
- // src/commands/sessions/daemon/repoPrefix.ts
17133
- import * as path47 from "path";
17134
- function repoPrefix(cwd) {
17135
- if (!cwd) return "";
17136
- return `${path47.basename(cwd)}/`;
17137
- }
17138
-
17139
17229
  // src/commands/sessions/daemon/spawnPty.ts
17140
17230
  import * as pty from "node-pty";
17141
17231
 
17142
17232
  // src/commands/sessions/daemon/ensureSpawnHelperExecutable.ts
17143
17233
  import { chmodSync, existsSync as existsSync51, statSync as statSync6 } from "fs";
17144
17234
  import { createRequire as createRequire3 } from "module";
17145
- import path48 from "path";
17235
+ import path47 from "path";
17146
17236
  var require4 = createRequire3(import.meta.url);
17147
17237
  var ensured = false;
17148
17238
  function ensureSpawnHelperExecutable() {
17149
17239
  if (ensured || process.platform !== "darwin") return;
17150
17240
  ensured = true;
17151
- const ptyRoot = path48.join(path48.dirname(require4.resolve("node-pty")), "..");
17152
- const helper = path48.join(
17241
+ const ptyRoot = path47.join(path47.dirname(require4.resolve("node-pty")), "..");
17242
+ const helper = path47.join(
17153
17243
  ptyRoot,
17154
17244
  "prebuilds",
17155
17245
  `${process.platform}-${process.arch}`,
@@ -17161,7 +17251,7 @@ function ensureSpawnHelperExecutable() {
17161
17251
  }
17162
17252
 
17163
17253
  // src/commands/sessions/daemon/spawnPty.ts
17164
- function spawnPty(args, cwd) {
17254
+ function spawnPty(args, cwd, sessionId) {
17165
17255
  ensureSpawnHelperExecutable();
17166
17256
  const shell = process.platform === "win32" ? "cmd.exe" : process.env.SHELL ?? "bash";
17167
17257
  const shellArgs = process.platform === "win32" ? ["/c", ...args] : ["-c", `exec ${args.map(shellEscape).join(" ")}`];
@@ -17170,7 +17260,13 @@ function spawnPty(args, cwd) {
17170
17260
  cols: 120,
17171
17261
  rows: 30,
17172
17262
  cwd: cwd ?? process.cwd(),
17173
- env: { ...process.env }
17263
+ env: {
17264
+ ...process.env,
17265
+ ...sessionId && {
17266
+ ASSIST_SESSION_ID: sessionId,
17267
+ ASSIST_ACTIVITY_ID: sessionId
17268
+ }
17269
+ }
17174
17270
  });
17175
17271
  }
17176
17272
  function shellEscape(s) {
@@ -17181,11 +17277,11 @@ function shellEscape(s) {
17181
17277
  function createAssistSession(id, assistArgs, cwd) {
17182
17278
  return {
17183
17279
  id,
17184
- name: `${repoPrefix(cwd)}assist ${assistArgs.join(" ")}`,
17280
+ name: `assist ${assistArgs.join(" ")}`,
17185
17281
  commandType: "assist",
17186
17282
  status: "running",
17187
17283
  startedAt: Date.now(),
17188
- pty: spawnPty(["assist", ...assistArgs], cwd),
17284
+ pty: spawnPty(["assist", ...assistArgs], cwd, id),
17189
17285
  scrollback: "",
17190
17286
  idleTimer: null,
17191
17287
  lastResizeAt: 0,
@@ -17213,7 +17309,7 @@ function spawnRun(opts) {
17213
17309
  function createSession(id, prompt, cwd) {
17214
17310
  return {
17215
17311
  id,
17216
- name: `${repoPrefix(cwd)}${prompt?.slice(0, 40) || `Session ${id}`}`,
17312
+ name: prompt?.slice(0, 40) || `Session ${id}`,
17217
17313
  commandType: "claude",
17218
17314
  status: "running",
17219
17315
  startedAt: Date.now(),
@@ -17227,7 +17323,7 @@ function createSession(id, prompt, cwd) {
17227
17323
  function createRunSession(id, runName, runArgs, cwd) {
17228
17324
  return {
17229
17325
  id,
17230
- name: `${repoPrefix(cwd)}run: ${runName}`,
17326
+ name: `run: ${runName}`,
17231
17327
  commandType: "run",
17232
17328
  status: "running",
17233
17329
  startedAt: Date.now(),
@@ -17341,7 +17437,7 @@ function restoreSession(id, persisted) {
17341
17437
  function resumeSession(id, sessionId, cwd, name) {
17342
17438
  return {
17343
17439
  id,
17344
- 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)}`,
17345
17441
  commandType: "claude",
17346
17442
  status: "running",
17347
17443
  startedAt: Date.now(),
@@ -17413,7 +17509,7 @@ function respawnThunk(session) {
17413
17509
  if (session.commandType === "run" && runName)
17414
17510
  return () => spawnRun({ name: runName, args: runArgs, cwd });
17415
17511
  if (session.commandType === "assist" && assistArgs)
17416
- return () => spawnPty(["assist", ...assistArgs], cwd);
17512
+ return () => spawnPty(["assist", ...assistArgs], cwd, session.id);
17417
17513
  return null;
17418
17514
  }
17419
17515
 
@@ -17434,8 +17530,10 @@ function toSessionInfo({
17434
17530
  startedAt,
17435
17531
  runName,
17436
17532
  runArgs,
17533
+ assistArgs,
17437
17534
  cwd,
17438
- restored
17535
+ restored,
17536
+ activity: activity2
17439
17537
  }) {
17440
17538
  return {
17441
17539
  id,
@@ -17445,14 +17543,45 @@ function toSessionInfo({
17445
17543
  startedAt,
17446
17544
  runName,
17447
17545
  runArgs,
17546
+ assistArgs,
17448
17547
  cwd,
17449
- 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();
17450
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();
17451
17580
  }
17452
17581
 
17453
17582
  // src/commands/sessions/daemon/discoverClaudeSessionId.ts
17454
17583
  import * as fs26 from "fs";
17455
- import * as path49 from "path";
17584
+ import * as path48 from "path";
17456
17585
  var POLL_MS = 3e3;
17457
17586
  async function discoverClaudeSessionId(options2) {
17458
17587
  while (options2.isActive()) {
@@ -17468,7 +17597,7 @@ async function findNewSessionId(options2) {
17468
17597
  if (!await isCreatedSince(filePath, options2.sinceMs)) continue;
17469
17598
  const meta = await parseSessionFile(filePath);
17470
17599
  if (!meta?.cwd || options2.isClaimed(meta.sessionId)) continue;
17471
- if (path49.resolve(meta.cwd) === path49.resolve(options2.cwd))
17600
+ if (path48.resolve(meta.cwd) === path48.resolve(options2.cwd))
17472
17601
  return meta.sessionId;
17473
17602
  }
17474
17603
  return null;
@@ -17520,6 +17649,8 @@ function dismissSession(sessions, id) {
17520
17649
  if (!s) return false;
17521
17650
  if (s.status !== "done") s.pty?.kill();
17522
17651
  clearIdle(s);
17652
+ s.activityWatcher?.close();
17653
+ if (s.cwd) removeActivity(s.cwd, s.id);
17523
17654
  sessions.delete(id);
17524
17655
  return true;
17525
17656
  }
@@ -17558,6 +17689,7 @@ var SessionManager = class {
17558
17689
  add(session) {
17559
17690
  this.wire(session);
17560
17691
  watchForClaudeSessionId(session, this.sessions, this.notify);
17692
+ watchActivity(session, this.notify);
17561
17693
  return session.id;
17562
17694
  }
17563
17695
  spawn(prompt, cwd) {
@@ -17722,10 +17854,10 @@ function handleConnection(socket, manager) {
17722
17854
  }
17723
17855
 
17724
17856
  // src/commands/sessions/daemon/onListening.ts
17725
- import { unlinkSync as unlinkSync17, writeFileSync as writeFileSync32 } from "fs";
17857
+ import { unlinkSync as unlinkSync17, writeFileSync as writeFileSync33 } from "fs";
17726
17858
 
17727
17859
  // src/commands/sessions/daemon/startPidFileWatchdog.ts
17728
- import { readFileSync as readFileSync40 } from "fs";
17860
+ import { readFileSync as readFileSync41 } from "fs";
17729
17861
  var WATCHDOG_INTERVAL_MS = 5e3;
17730
17862
  function startPidFileWatchdog(onLost, intervalMs = WATCHDOG_INTERVAL_MS) {
17731
17863
  const timer = setInterval(() => {
@@ -17736,7 +17868,7 @@ function startPidFileWatchdog(onLost, intervalMs = WATCHDOG_INTERVAL_MS) {
17736
17868
  }
17737
17869
  function ownsPidFile() {
17738
17870
  try {
17739
- return readFileSync40(daemonPaths.pid, "utf-8").trim() === String(process.pid);
17871
+ return readFileSync41(daemonPaths.pid, "utf-8").trim() === String(process.pid);
17740
17872
  } catch {
17741
17873
  return false;
17742
17874
  }
@@ -17744,7 +17876,7 @@ function ownsPidFile() {
17744
17876
 
17745
17877
  // src/commands/sessions/daemon/onListening.ts
17746
17878
  function onListening(manager, checkAutoExit) {
17747
- writeFileSync32(daemonPaths.pid, String(process.pid));
17879
+ writeFileSync33(daemonPaths.pid, String(process.pid));
17748
17880
  startPidFileWatchdog(() => {
17749
17881
  daemonLog("lost daemon.pid ownership; shutting down sessions and exiting");
17750
17882
  manager.shutdown();
@@ -17805,7 +17937,7 @@ async function recoverFromAddrInUse(server, manager, checkAutoExit) {
17805
17937
 
17806
17938
  // src/commands/sessions/daemon/runDaemon.ts
17807
17939
  async function runDaemon() {
17808
- mkdirSync19(daemonPaths.dir, { recursive: true });
17940
+ mkdirSync21(daemonPaths.dir, { recursive: true });
17809
17941
  daemonLog(
17810
17942
  `starting (reason: ${process.env.ASSIST_DAEMON_SPAWN_REASON ?? "manual"})`
17811
17943
  );
@@ -18105,16 +18237,16 @@ async function statusLine() {
18105
18237
  // src/commands/sync.ts
18106
18238
  import * as fs32 from "fs";
18107
18239
  import * as os2 from "os";
18108
- import * as path52 from "path";
18240
+ import * as path51 from "path";
18109
18241
  import { fileURLToPath as fileURLToPath7 } from "url";
18110
18242
 
18111
18243
  // src/commands/sync/syncClaudeMd.ts
18112
18244
  import * as fs30 from "fs";
18113
- import * as path50 from "path";
18245
+ import * as path49 from "path";
18114
18246
  import chalk160 from "chalk";
18115
18247
  async function syncClaudeMd(claudeDir, targetBase, options2) {
18116
- const source = path50.join(claudeDir, "CLAUDE.md");
18117
- const target = path50.join(targetBase, "CLAUDE.md");
18248
+ const source = path49.join(claudeDir, "CLAUDE.md");
18249
+ const target = path49.join(targetBase, "CLAUDE.md");
18118
18250
  const sourceContent = fs30.readFileSync(source, "utf-8");
18119
18251
  if (fs30.existsSync(target)) {
18120
18252
  const targetContent = fs30.readFileSync(target, "utf-8");
@@ -18140,11 +18272,11 @@ async function syncClaudeMd(claudeDir, targetBase, options2) {
18140
18272
 
18141
18273
  // src/commands/sync/syncSettings.ts
18142
18274
  import * as fs31 from "fs";
18143
- import * as path51 from "path";
18275
+ import * as path50 from "path";
18144
18276
  import chalk161 from "chalk";
18145
18277
  async function syncSettings(claudeDir, targetBase, options2) {
18146
- const source = path51.join(claudeDir, "settings.json");
18147
- const target = path51.join(targetBase, "settings.json");
18278
+ const source = path50.join(claudeDir, "settings.json");
18279
+ const target = path50.join(targetBase, "settings.json");
18148
18280
  const sourceContent = fs31.readFileSync(source, "utf-8");
18149
18281
  const mergedContent = JSON.stringify(JSON.parse(sourceContent), null, " ");
18150
18282
  if (fs31.existsSync(target)) {
@@ -18180,23 +18312,23 @@ async function syncSettings(claudeDir, targetBase, options2) {
18180
18312
 
18181
18313
  // src/commands/sync.ts
18182
18314
  var __filename4 = fileURLToPath7(import.meta.url);
18183
- var __dirname7 = path52.dirname(__filename4);
18315
+ var __dirname7 = path51.dirname(__filename4);
18184
18316
  async function sync(options2) {
18185
18317
  const config = loadConfig();
18186
18318
  const yes = options2?.yes ?? config.sync.autoConfirm;
18187
- const claudeDir = path52.join(__dirname7, "..", "claude");
18188
- const targetBase = path52.join(os2.homedir(), ".claude");
18319
+ const claudeDir = path51.join(__dirname7, "..", "claude");
18320
+ const targetBase = path51.join(os2.homedir(), ".claude");
18189
18321
  syncCommands(claudeDir, targetBase);
18190
18322
  await syncSettings(claudeDir, targetBase, { yes });
18191
18323
  await syncClaudeMd(claudeDir, targetBase, { yes });
18192
18324
  }
18193
18325
  function syncCommands(claudeDir, targetBase) {
18194
- const sourceDir = path52.join(claudeDir, "commands");
18195
- const targetDir = path52.join(targetBase, "commands");
18326
+ const sourceDir = path51.join(claudeDir, "commands");
18327
+ const targetDir = path51.join(targetBase, "commands");
18196
18328
  fs32.mkdirSync(targetDir, { recursive: true });
18197
18329
  const files = fs32.readdirSync(sourceDir);
18198
18330
  for (const file of files) {
18199
- fs32.copyFileSync(path52.join(sourceDir, file), path52.join(targetDir, file));
18331
+ fs32.copyFileSync(path51.join(sourceDir, file), path51.join(targetDir, file));
18200
18332
  console.log(`Copied ${file} to ${targetDir}`);
18201
18333
  }
18202
18334
  console.log(`Synced ${files.length} command(s) to ~/.claude/commands`);
@@ -18204,15 +18336,15 @@ function syncCommands(claudeDir, targetBase) {
18204
18336
 
18205
18337
  // src/commands/update.ts
18206
18338
  import { execSync as execSync48 } from "child_process";
18207
- import * as path53 from "path";
18339
+ import * as path52 from "path";
18208
18340
  function isGlobalNpmInstall(dir) {
18209
18341
  try {
18210
- const resolved = path53.resolve(dir);
18211
- if (resolved.split(path53.sep).includes("node_modules")) {
18342
+ const resolved = path52.resolve(dir);
18343
+ if (resolved.split(path52.sep).includes("node_modules")) {
18212
18344
  return true;
18213
18345
  }
18214
18346
  const globalPrefix = execSync48("npm prefix -g", { stdio: "pipe" }).toString().trim();
18215
- return resolved.toLowerCase().startsWith(path53.resolve(globalPrefix).toLowerCase());
18347
+ return resolved.toLowerCase().startsWith(path52.resolve(globalPrefix).toLowerCase());
18216
18348
  } catch {
18217
18349
  return false;
18218
18350
  }