@staff0rd/assist 0.187.0 → 0.189.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.
Files changed (3) hide show
  1. package/README.md +1 -0
  2. package/dist/index.js +384 -233
  3. package/package.json +1 -1
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.187.0",
9
+ version: "0.189.0",
10
10
  type: "module",
11
11
  main: "dist/index.js",
12
12
  bin: {
@@ -421,13 +421,7 @@ import Database from "better-sqlite3";
421
421
  // src/commands/backlog/ensureGitignore.ts
422
422
  import { existsSync as existsSync2, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "fs";
423
423
  import { join as join2 } from "path";
424
- var gitignoreEntries = [
425
- ".assist/backlog.db",
426
- ".assist/backlog.db-shm",
427
- ".assist/backlog.db-wal",
428
- ".assist-signal*.json",
429
- ".assist-lock-*.json"
430
- ];
424
+ var gitignoreEntries = [".assist-*", ".assist/*.db*"];
431
425
  function ensureGitignore(dir) {
432
426
  const gitignorePath = join2(dir, ".gitignore");
433
427
  const existing = existsSync2(gitignorePath) ? readFileSync3(gitignorePath, "utf-8") : "";
@@ -979,8 +973,8 @@ function spawnClaude(prompt, options2 = {}) {
979
973
  const child = spawn("claude", args, {
980
974
  stdio: "inherit"
981
975
  });
982
- const done2 = new Promise((resolve8, reject) => {
983
- child.on("close", (code) => resolve8(code ?? 0));
976
+ const done2 = new Promise((resolve12, reject) => {
977
+ child.on("close", (code) => resolve12(code ?? 0));
984
978
  child.on("error", reject);
985
979
  });
986
980
  return { child, done: done2 };
@@ -1253,16 +1247,16 @@ function printLinks(item, items) {
1253
1247
  const links = item.links ?? [];
1254
1248
  if (links.length === 0) return;
1255
1249
  console.log(chalk12.bold("Links"));
1256
- for (const link2 of links) {
1257
- const target = items.find((i) => i.id === link2.targetId);
1258
- const typeLabel2 = link2.type === "depends-on" ? chalk12.red("depends-on") : chalk12.blue("relates-to");
1250
+ for (const link3 of links) {
1251
+ const target = items.find((i) => i.id === link3.targetId);
1252
+ const typeLabel2 = link3.type === "depends-on" ? chalk12.red("depends-on") : chalk12.blue("relates-to");
1259
1253
  if (target) {
1260
1254
  console.log(
1261
1255
  ` ${typeLabel2} #${target.id} ${target.name} ${chalk12.dim(`(${target.status})`)}`
1262
1256
  );
1263
1257
  } else {
1264
1258
  console.log(
1265
- ` ${typeLabel2} #${link2.targetId} ${chalk12.dim("(not found)")}`
1259
+ ` ${typeLabel2} #${link3.targetId} ${chalk12.dim("(not found)")}`
1266
1260
  );
1267
1261
  }
1268
1262
  }
@@ -1426,12 +1420,12 @@ function getHtml() {
1426
1420
 
1427
1421
  // src/commands/backlog/web/parseItemBody.ts
1428
1422
  function readBody(req) {
1429
- return new Promise((resolve8, reject) => {
1423
+ return new Promise((resolve12, reject) => {
1430
1424
  let body = "";
1431
1425
  req.on("data", (chunk) => {
1432
1426
  body += chunk.toString();
1433
1427
  });
1434
- req.on("end", () => resolve8(body));
1428
+ req.on("end", () => resolve12(body));
1435
1429
  req.on("error", reject);
1436
1430
  });
1437
1431
  }
@@ -1647,6 +1641,10 @@ var runConfigSchema = z2.strictObject({
1647
1641
  pre: z2.array(z2.string()).optional(),
1648
1642
  cwd: z2.string().optional()
1649
1643
  });
1644
+ var runLinkSchema = z2.strictObject({
1645
+ link: z2.string(),
1646
+ prefix: z2.string()
1647
+ });
1650
1648
  var transcriptConfigSchema = z2.strictObject({
1651
1649
  vttDir: z2.string(),
1652
1650
  transcriptsDir: z2.string(),
@@ -1687,7 +1685,7 @@ var assistConfigSchema = z2.strictObject({
1687
1685
  refreshToken: z2.string().optional(),
1688
1686
  tokenExpiresAt: z2.number().optional()
1689
1687
  }).optional(),
1690
- run: z2.array(runConfigSchema).optional(),
1688
+ run: z2.array(z2.union([runConfigSchema, runLinkSchema])).optional(),
1691
1689
  transcript: transcriptConfigSchema.optional(),
1692
1690
  cliReadVerbs: z2.record(z2.string(), z2.array(z2.string())).optional(),
1693
1691
  news: z2.strictObject({
@@ -1751,6 +1749,9 @@ var assistConfigSchema = z2.strictObject({
1751
1749
  models: {}
1752
1750
  })
1753
1751
  });
1752
+ function isRunLink(entry) {
1753
+ return "link" in entry;
1754
+ }
1754
1755
 
1755
1756
  // src/shared/loadConfig.ts
1756
1757
  function findConfigUp(startDir) {
@@ -2394,8 +2395,8 @@ function toolStatus(pkg, scriptName, hasPackage, configScriptNames) {
2394
2395
  };
2395
2396
  }
2396
2397
  function loadConfigScriptNames() {
2397
- const config = loadConfig();
2398
- return new Set((config.run ?? []).map((r) => r.name));
2398
+ const entries = loadConfig().run ?? [];
2399
+ return new Set(entries.flatMap((r) => "name" in r ? [r.name] : []));
2399
2400
  }
2400
2401
  function buildToolStatuses(pkg, configScriptNames) {
2401
2402
  const status2 = (script, has) => toolStatus(pkg, script, has, configScriptNames);
@@ -3040,7 +3041,7 @@ function lint(options2 = {}) {
3040
3041
 
3041
3042
  // src/commands/new/registerNew/newCli/index.ts
3042
3043
  import { execSync as execSync11 } from "child_process";
3043
- import { basename, resolve } from "path";
3044
+ import { basename, resolve as resolve5 } from "path";
3044
3045
 
3045
3046
  // src/commands/verify/hardcodedColors.ts
3046
3047
  import { execSync as execSync6 } from "child_process";
@@ -3088,15 +3089,111 @@ Total: ${lines.length} hardcoded color(s)`);
3088
3089
 
3089
3090
  // src/commands/verify/run/resolveEntries.ts
3090
3091
  import * as path17 from "path";
3092
+
3093
+ // src/shared/resolveRunConfigs.ts
3094
+ import { dirname as dirname12, relative, resolve as resolve3 } from "path";
3095
+
3096
+ // src/shared/assertNoDuplicateRunNames.ts
3097
+ function findDuplicateNames(configs) {
3098
+ const seen = /* @__PURE__ */ new Set();
3099
+ const dupes = /* @__PURE__ */ new Set();
3100
+ for (const c of configs) {
3101
+ if (seen.has(c.name)) dupes.add(c.name);
3102
+ seen.add(c.name);
3103
+ }
3104
+ return [...dupes];
3105
+ }
3106
+ function assertNoDuplicateRunNames(configs) {
3107
+ const duplicates = findDuplicateNames(configs);
3108
+ if (duplicates.length > 0) {
3109
+ throw new Error(
3110
+ `Duplicate run command names: ${duplicates.join(", ")}. Use the prefix option on link entries to namespace linked commands.`
3111
+ );
3112
+ }
3113
+ }
3114
+
3115
+ // src/shared/findLinkedConfigPath.ts
3116
+ import { existsSync as existsSync17 } from "fs";
3117
+ import { join as join14, resolve } from "path";
3118
+ function findLinkedConfigPath(linkPath, fromDir) {
3119
+ const resolved = resolve(fromDir, linkPath);
3120
+ const claudePath = join14(resolved, ".claude", "assist.yml");
3121
+ if (existsSync17(claudePath)) return claudePath;
3122
+ const rootPath = join14(resolved, "assist.yml");
3123
+ if (existsSync17(rootPath)) return rootPath;
3124
+ throw new Error(`No assist.yml found in linked project: ${resolved}`);
3125
+ }
3126
+
3127
+ // src/shared/loadLinkedEntries.ts
3128
+ import { resolve as resolve2 } from "path";
3129
+ function loadLinkedEntries(configPath, visited) {
3130
+ const canonical = resolve2(configPath);
3131
+ if (visited.has(canonical)) {
3132
+ throw new Error(
3133
+ `Circular link detected: ${canonical} has already been visited`
3134
+ );
3135
+ }
3136
+ visited.add(canonical);
3137
+ const raw = loadRawYaml(configPath);
3138
+ return assistConfigSchema.parse(raw).run;
3139
+ }
3140
+
3141
+ // src/shared/resolveRunConfigs.ts
3142
+ function resolveRunConfigs(entries, configDir) {
3143
+ const ctx = { rootConfigDir: configDir, visited: /* @__PURE__ */ new Set() };
3144
+ return resolveRecursive(entries, configDir, ctx);
3145
+ }
3146
+ function applyPrefix(configs, prefix2) {
3147
+ return configs.map((c) => ({ ...c, name: `${prefix2}:${c.name}` }));
3148
+ }
3149
+ function setDefaultCwd(configs, defaultCwd) {
3150
+ return configs.map((c) => c.cwd ? c : { ...c, cwd: defaultCwd });
3151
+ }
3152
+ function relativeToRoot(ctx, absolute) {
3153
+ return relative(ctx.rootConfigDir, absolute);
3154
+ }
3155
+ function loadAndResolveLink(linkPath, configDir, ctx) {
3156
+ const configPath = findLinkedConfigPath(linkPath, configDir);
3157
+ const entries = loadLinkedEntries(configPath, ctx.visited);
3158
+ const defaultCwd = relativeToRoot(ctx, resolve3(configDir, linkPath));
3159
+ return setDefaultCwd(
3160
+ resolveRecursive(entries, dirname12(configPath), ctx),
3161
+ defaultCwd
3162
+ );
3163
+ }
3164
+ function resolveLink(entry, configDir, ctx) {
3165
+ const configs = loadAndResolveLink(entry.link, configDir, ctx);
3166
+ return applyPrefix(configs, entry.prefix);
3167
+ }
3168
+ function resolveEntry(entry, configDir, ctx) {
3169
+ if (isRunLink(entry)) return resolveLink(entry, configDir, ctx);
3170
+ return [resolveLocalCwd(entry, configDir, ctx)];
3171
+ }
3172
+ function resolveRecursive(entries, configDir, ctx) {
3173
+ if (!entries || entries.length === 0) return [];
3174
+ const result = entries.flatMap((e) => resolveEntry(e, configDir, ctx));
3175
+ assertNoDuplicateRunNames(result);
3176
+ return result;
3177
+ }
3178
+ function resolveLocalCwd(config, configDir, ctx) {
3179
+ if (!config.cwd || configDir === ctx.rootConfigDir) return config;
3180
+ return {
3181
+ ...config,
3182
+ cwd: relativeToRoot(ctx, resolve3(configDir, config.cwd))
3183
+ };
3184
+ }
3185
+
3186
+ // src/commands/verify/run/resolveEntries.ts
3091
3187
  function buildFullCommand(command, args) {
3092
3188
  return [shellQuote(command), ...(args ?? []).map(shellQuote)].join(" ");
3093
3189
  }
3094
3190
  function getRunEntries() {
3095
3191
  const { run: run4 } = loadConfig();
3096
- if (!run4) return [];
3097
- return run4.filter((r) => r.name.startsWith("verify:")).map((r) => ({
3192
+ const configs = resolveRunConfigs(run4, getConfigDir());
3193
+ return configs.filter((r) => r.name.startsWith("verify:")).map((r) => ({
3098
3194
  name: r.name,
3099
3195
  fullCommand: buildFullCommand(r.command, r.args),
3196
+ cwd: r.cwd ? path17.resolve(getConfigDir(), r.cwd) : void 0,
3100
3197
  env: r.env,
3101
3198
  filter: r.filter
3102
3199
  }));
@@ -3269,14 +3366,14 @@ function flushIfFailed(exitCode, chunks) {
3269
3366
 
3270
3367
  // src/commands/verify/run/runAllEntries.ts
3271
3368
  function runEntry(entry, onComplete) {
3272
- return new Promise((resolve8) => {
3369
+ return new Promise((resolve12) => {
3273
3370
  const child = spawnCommand(entry.fullCommand, entry.cwd, entry.env);
3274
3371
  const chunks = collectOutput(child);
3275
3372
  child.on("close", (code) => {
3276
3373
  const exitCode = code ?? 1;
3277
3374
  flushIfFailed(exitCode, chunks);
3278
3375
  onComplete?.(exitCode);
3279
- resolve8({ script: entry.name, code: exitCode });
3376
+ resolve12({ script: entry.name, code: exitCode });
3280
3377
  });
3281
3378
  });
3282
3379
  }
@@ -3406,7 +3503,7 @@ program.parse();
3406
3503
 
3407
3504
  // src/commands/new/registerNew/newCli/index.ts
3408
3505
  async function newCli() {
3409
- const name = basename(resolve("."));
3506
+ const name = basename(resolve5("."));
3410
3507
  initGit();
3411
3508
  initPackageJson(name);
3412
3509
  console.log("Installing dependencies...");
@@ -3421,7 +3518,7 @@ async function newCli() {
3421
3518
 
3422
3519
  // src/commands/new/registerNew/newProject.ts
3423
3520
  import { execSync as execSync13 } from "child_process";
3424
- import { existsSync as existsSync18, readFileSync as readFileSync14, writeFileSync as writeFileSync14 } from "fs";
3521
+ import { existsSync as existsSync19, readFileSync as readFileSync14, writeFileSync as writeFileSync14 } from "fs";
3425
3522
 
3426
3523
  // src/commands/deploy/init/index.ts
3427
3524
  import { execSync as execSync12 } from "child_process";
@@ -3429,14 +3526,14 @@ import chalk40 from "chalk";
3429
3526
  import enquirer6 from "enquirer";
3430
3527
 
3431
3528
  // src/commands/deploy/init/updateWorkflow.ts
3432
- import { existsSync as existsSync17, mkdirSync as mkdirSync4, readFileSync as readFileSync13, writeFileSync as writeFileSync13 } from "fs";
3433
- import { dirname as dirname13, join as join14 } from "path";
3529
+ import { existsSync as existsSync18, mkdirSync as mkdirSync4, readFileSync as readFileSync13, writeFileSync as writeFileSync13 } from "fs";
3530
+ import { dirname as dirname14, join as join15 } from "path";
3434
3531
  import { fileURLToPath as fileURLToPath3 } from "url";
3435
3532
  import chalk39 from "chalk";
3436
3533
  var WORKFLOW_PATH = ".github/workflows/build.yml";
3437
- var __dirname3 = dirname13(fileURLToPath3(import.meta.url));
3534
+ var __dirname3 = dirname14(fileURLToPath3(import.meta.url));
3438
3535
  function getExistingSiteId() {
3439
- if (!existsSync17(WORKFLOW_PATH)) {
3536
+ if (!existsSync18(WORKFLOW_PATH)) {
3440
3537
  return null;
3441
3538
  }
3442
3539
  const content = readFileSync13(WORKFLOW_PATH, "utf-8");
@@ -3444,17 +3541,17 @@ function getExistingSiteId() {
3444
3541
  return match ? match[1] : null;
3445
3542
  }
3446
3543
  function getTemplateContent(siteId) {
3447
- const templatePath = join14(__dirname3, "commands/deploy/build.yml");
3544
+ const templatePath = join15(__dirname3, "commands/deploy/build.yml");
3448
3545
  const template = readFileSync13(templatePath, "utf-8");
3449
3546
  return template.replace("{{NETLIFY_SITE_ID}}", siteId);
3450
3547
  }
3451
3548
  async function updateWorkflow(siteId) {
3452
3549
  const newContent = getTemplateContent(siteId);
3453
3550
  const workflowDir = ".github/workflows";
3454
- if (!existsSync17(workflowDir)) {
3551
+ if (!existsSync18(workflowDir)) {
3455
3552
  mkdirSync4(workflowDir, { recursive: true });
3456
3553
  }
3457
- if (existsSync17(WORKFLOW_PATH)) {
3554
+ if (existsSync18(WORKFLOW_PATH)) {
3458
3555
  const oldContent = readFileSync13(WORKFLOW_PATH, "utf-8");
3459
3556
  if (oldContent === newContent) {
3460
3557
  console.log(chalk39.green("build.yml is already up to date"));
@@ -3549,7 +3646,7 @@ async function newProject() {
3549
3646
  }
3550
3647
  function addViteBaseConfig() {
3551
3648
  const viteConfigPath = "vite.config.ts";
3552
- if (!existsSync18(viteConfigPath)) {
3649
+ if (!existsSync19(viteConfigPath)) {
3553
3650
  console.log("No vite.config.ts found, skipping base config");
3554
3651
  return;
3555
3652
  }
@@ -3883,7 +3980,7 @@ import chalk45 from "chalk";
3883
3980
 
3884
3981
  // src/commands/backlog/commitBacklog.ts
3885
3982
  import { execSync as execSync15 } from "child_process";
3886
- import { join as join15 } from "path";
3983
+ import { join as join16 } from "path";
3887
3984
  import chalk44 from "chalk";
3888
3985
  function commitBacklog(id, name) {
3889
3986
  const config = loadConfig();
@@ -3896,7 +3993,7 @@ function commitBacklog(id, name) {
3896
3993
  return;
3897
3994
  }
3898
3995
  try {
3899
- const jsonlPath = join15(getBacklogDir(), ".assist", "backlog.jsonl");
3996
+ const jsonlPath = join16(getBacklogDir(), ".assist", "backlog.jsonl");
3900
3997
  const message = `chore: add backlog item #${id} \u2014 ${name}`;
3901
3998
  execSync15(`git add ${shellQuote(jsonlPath)}`, { stdio: "ignore" });
3902
3999
  execSync15(`git commit -m ${shellQuote(message)}`, { stdio: "ignore" });
@@ -3909,7 +4006,7 @@ function commitBacklog(id, name) {
3909
4006
  import { spawnSync } from "child_process";
3910
4007
  import { mkdtempSync, readFileSync as readFileSync15, unlinkSync as unlinkSync4, writeFileSync as writeFileSync15 } from "fs";
3911
4008
  import { tmpdir } from "os";
3912
- import { join as join16 } from "path";
4009
+ import { join as join17 } from "path";
3913
4010
  import enquirer7 from "enquirer";
3914
4011
  async function promptType() {
3915
4012
  const { type } = await enquirer7.prompt({
@@ -3949,8 +4046,8 @@ async function promptDescription() {
3949
4046
  }
3950
4047
  function openEditor() {
3951
4048
  const editor = process.env.EDITOR || process.env.VISUAL || "vi";
3952
- const dir = mkdtempSync(join16(tmpdir(), "assist-"));
3953
- const filePath = join16(dir, "description.md");
4049
+ const dir = mkdtempSync(join17(tmpdir(), "assist-"));
4050
+ const filePath = join17(dir, "description.md");
3954
4051
  writeFileSync15(filePath, "");
3955
4052
  const result = spawnSync(editor, [filePath], { stdio: "inherit" });
3956
4053
  if (result.status !== 0) {
@@ -4176,9 +4273,9 @@ function hasCycle(items, fromId, toId) {
4176
4273
  visited.add(current);
4177
4274
  const item = items.find((i) => i.id === current);
4178
4275
  if (!item?.links) continue;
4179
- for (const link2 of item.links) {
4180
- if (link2.type === "depends-on") {
4181
- stack.push(link2.targetId);
4276
+ for (const link3 of item.links) {
4277
+ if (link3.type === "depends-on") {
4278
+ stack.push(link3.targetId);
4182
4279
  }
4183
4280
  }
4184
4281
  }
@@ -4748,7 +4845,7 @@ function stripEnvPrefix(parts) {
4748
4845
  }
4749
4846
 
4750
4847
  // src/shared/isApprovedRead.ts
4751
- import { resolve as resolve3 } from "path";
4848
+ import { resolve as resolve7 } from "path";
4752
4849
 
4753
4850
  // src/shared/tokenize.ts
4754
4851
  function tokenize(command) {
@@ -4829,29 +4926,29 @@ function extractGraphqlQuery(args) {
4829
4926
  }
4830
4927
 
4831
4928
  // src/shared/loadCliReads.ts
4832
- import { existsSync as existsSync19, readFileSync as readFileSync16, writeFileSync as writeFileSync16 } from "fs";
4833
- import { dirname as dirname14, resolve as resolve2 } from "path";
4929
+ import { existsSync as existsSync20, readFileSync as readFileSync16, writeFileSync as writeFileSync16 } from "fs";
4930
+ import { dirname as dirname15, resolve as resolve6 } from "path";
4834
4931
  import { fileURLToPath as fileURLToPath4 } from "url";
4835
4932
  var __filename2 = fileURLToPath4(import.meta.url);
4836
- var __dirname4 = dirname14(__filename2);
4933
+ var __dirname4 = dirname15(__filename2);
4837
4934
  function packageRoot() {
4838
4935
  return __dirname4;
4839
4936
  }
4840
4937
  function readLines(path50) {
4841
- if (!existsSync19(path50)) return [];
4938
+ if (!existsSync20(path50)) return [];
4842
4939
  return readFileSync16(path50, "utf-8").split("\n").filter((line) => line.trim() !== "");
4843
4940
  }
4844
4941
  var cachedReads;
4845
4942
  var cachedWrites;
4846
4943
  function getCliReadsLines() {
4847
4944
  if (!cachedReads) {
4848
- cachedReads = readLines(resolve2(packageRoot(), "allowed.cli-reads"));
4945
+ cachedReads = readLines(resolve6(packageRoot(), "allowed.cli-reads"));
4849
4946
  }
4850
4947
  return cachedReads;
4851
4948
  }
4852
4949
  function getCliWritesLines() {
4853
4950
  if (!cachedWrites) {
4854
- cachedWrites = readLines(resolve2(packageRoot(), "allowed.cli-writes"));
4951
+ cachedWrites = readLines(resolve6(packageRoot(), "allowed.cli-writes"));
4855
4952
  }
4856
4953
  return cachedWrites;
4857
4954
  }
@@ -4860,7 +4957,7 @@ function loadCliReads() {
4860
4957
  }
4861
4958
  function saveCliReads(commands) {
4862
4959
  writeFileSync16(
4863
- resolve2(packageRoot(), "allowed.cli-reads"),
4960
+ resolve6(packageRoot(), "allowed.cli-reads"),
4864
4961
  `${commands.join("\n")}
4865
4962
  `
4866
4963
  );
@@ -4885,14 +4982,14 @@ function findCliWrite(command) {
4885
4982
  }
4886
4983
 
4887
4984
  // src/shared/readSettingsPerms.ts
4888
- import { existsSync as existsSync20, readFileSync as readFileSync17 } from "fs";
4985
+ import { existsSync as existsSync21, readFileSync as readFileSync17 } from "fs";
4889
4986
  import { homedir as homedir3 } from "os";
4890
- import { join as join17 } from "path";
4987
+ import { join as join18 } from "path";
4891
4988
  function readSettingsPerms(key) {
4892
4989
  const paths = [
4893
- join17(homedir3(), ".claude", "settings.json"),
4894
- join17(process.cwd(), ".claude", "settings.json"),
4895
- join17(process.cwd(), ".claude", "settings.local.json")
4990
+ join18(homedir3(), ".claude", "settings.json"),
4991
+ join18(process.cwd(), ".claude", "settings.json"),
4992
+ join18(process.cwd(), ".claude", "settings.local.json")
4896
4993
  ];
4897
4994
  const entries = [];
4898
4995
  for (const p of paths) {
@@ -4901,7 +4998,7 @@ function readSettingsPerms(key) {
4901
4998
  return entries;
4902
4999
  }
4903
5000
  function readPermissionArray(filePath, key) {
4904
- if (!existsSync20(filePath)) return [];
5001
+ if (!existsSync21(filePath)) return [];
4905
5002
  try {
4906
5003
  const data = JSON.parse(readFileSync17(filePath, "utf-8"));
4907
5004
  const arr = data?.permissions?.[key];
@@ -4977,8 +5074,8 @@ function isCdToCwd(command) {
4977
5074
  const parts = command.split(/\s+/);
4978
5075
  if (parts[0] !== "cd" || parts.length > 2) return false;
4979
5076
  if (parts.length === 1) return false;
4980
- const resolved = resolve3(normalizeMsysPath(parts[1]));
4981
- return resolved === resolve3(process.cwd());
5077
+ const resolved = resolve7(normalizeMsysPath(parts[1]));
5078
+ return resolved === resolve7(process.cwd());
4982
5079
  }
4983
5080
  function normalizeMsysPath(p) {
4984
5081
  const m = p.match(/^\/([a-zA-Z])(\/.*)/);
@@ -5095,18 +5192,18 @@ ${reasons.join("\n")}`);
5095
5192
  }
5096
5193
 
5097
5194
  // src/commands/permitCliReads/index.ts
5098
- import { existsSync as existsSync21, mkdirSync as mkdirSync5, readFileSync as readFileSync18, writeFileSync as writeFileSync17 } from "fs";
5195
+ import { existsSync as existsSync22, mkdirSync as mkdirSync5, readFileSync as readFileSync18, writeFileSync as writeFileSync17 } from "fs";
5099
5196
  import { homedir as homedir4 } from "os";
5100
- import { join as join18 } from "path";
5197
+ import { join as join19 } from "path";
5101
5198
 
5102
5199
  // src/shared/getInstallDir.ts
5103
5200
  import { execSync as execSync16 } from "child_process";
5104
- import { dirname as dirname15, resolve as resolve4 } from "path";
5201
+ import { dirname as dirname16, resolve as resolve8 } from "path";
5105
5202
  import { fileURLToPath as fileURLToPath5 } from "url";
5106
5203
  var __filename3 = fileURLToPath5(import.meta.url);
5107
- var __dirname5 = dirname15(__filename3);
5204
+ var __dirname5 = dirname16(__filename3);
5108
5205
  function getInstallDir() {
5109
- return resolve4(__dirname5, "..");
5206
+ return resolve8(__dirname5, "..");
5110
5207
  }
5111
5208
  function isGitRepo(dir) {
5112
5209
  try {
@@ -5114,7 +5211,7 @@ function isGitRepo(dir) {
5114
5211
  cwd: dir,
5115
5212
  stdio: "pipe"
5116
5213
  }).toString().trim();
5117
- return resolve4(result) === resolve4(dir);
5214
+ return resolve8(result) === resolve8(dir);
5118
5215
  } catch {
5119
5216
  return false;
5120
5217
  }
@@ -5227,12 +5324,12 @@ function hasSubcommands(helpText) {
5227
5324
  // src/commands/permitCliReads/runHelp.ts
5228
5325
  import { exec as exec2 } from "child_process";
5229
5326
  function runHelp(args) {
5230
- return new Promise((resolve8) => {
5327
+ return new Promise((resolve12) => {
5231
5328
  exec2(
5232
5329
  `${args.join(" ")} --help`,
5233
5330
  { encoding: "utf-8", timeout: 3e4 },
5234
5331
  (_err, stdout, stderr) => {
5235
- resolve8(stdout || stderr || "");
5332
+ resolve12(stdout || stderr || "");
5236
5333
  }
5237
5334
  );
5238
5335
  });
@@ -5399,15 +5496,15 @@ function updateSettings(cli, commands) {
5399
5496
  // src/commands/permitCliReads/index.ts
5400
5497
  function logPath(cli) {
5401
5498
  const safeName = cli.replace(/\s+/g, "-");
5402
- return join18(homedir4(), ".assist", `cli-discover-${safeName}.log`);
5499
+ return join19(homedir4(), ".assist", `cli-discover-${safeName}.log`);
5403
5500
  }
5404
5501
  function readCache(cli) {
5405
5502
  const path50 = logPath(cli);
5406
- if (!existsSync21(path50)) return void 0;
5503
+ if (!existsSync22(path50)) return void 0;
5407
5504
  return readFileSync18(path50, "utf-8");
5408
5505
  }
5409
5506
  function writeCache(cli, output) {
5410
- const dir = join18(homedir4(), ".assist");
5507
+ const dir = join19(homedir4(), ".assist");
5411
5508
  mkdirSync5(dir, { recursive: true });
5412
5509
  writeFileSync17(logPath(cli), output);
5413
5510
  }
@@ -6163,7 +6260,7 @@ function registerConfig(program2) {
6163
6260
  }
6164
6261
 
6165
6262
  // src/commands/deploy/redirect.ts
6166
- import { existsSync as existsSync22, readFileSync as readFileSync19, writeFileSync as writeFileSync18 } from "fs";
6263
+ import { existsSync as existsSync23, readFileSync as readFileSync19, writeFileSync as writeFileSync18 } from "fs";
6167
6264
  import chalk76 from "chalk";
6168
6265
  var TRAILING_SLASH_SCRIPT = ` <script>
6169
6266
  if (!window.location.pathname.endsWith('/')) {
@@ -6172,7 +6269,7 @@ var TRAILING_SLASH_SCRIPT = ` <script>
6172
6269
  </script>`;
6173
6270
  function redirect() {
6174
6271
  const indexPath = "index.html";
6175
- if (!existsSync22(indexPath)) {
6272
+ if (!existsSync23(indexPath)) {
6176
6273
  console.log(chalk76.yellow("No index.html found"));
6177
6274
  return;
6178
6275
  }
@@ -6204,10 +6301,10 @@ import { basename as basename3 } from "path";
6204
6301
 
6205
6302
  // src/commands/devlog/loadBlogSkipDays.ts
6206
6303
  import { homedir as homedir5 } from "os";
6207
- import { join as join19 } from "path";
6208
- var BLOG_REPO_ROOT = join19(homedir5(), "git/blog");
6304
+ import { join as join20 } from "path";
6305
+ var BLOG_REPO_ROOT = join20(homedir5(), "git/blog");
6209
6306
  function loadBlogSkipDays(repoName) {
6210
- const config = loadRawYaml(join19(BLOG_REPO_ROOT, "assist.yml"));
6307
+ const config = loadRawYaml(join20(BLOG_REPO_ROOT, "assist.yml"));
6211
6308
  const devlog = config.devlog;
6212
6309
  const skip2 = devlog?.skip;
6213
6310
  return new Set(skip2?.[repoName] ?? []);
@@ -6218,15 +6315,15 @@ import { execSync as execSync18 } from "child_process";
6218
6315
  import chalk77 from "chalk";
6219
6316
 
6220
6317
  // src/shared/getRepoName.ts
6221
- import { existsSync as existsSync23, readFileSync as readFileSync20 } from "fs";
6222
- import { basename as basename2, join as join20 } from "path";
6318
+ import { existsSync as existsSync24, readFileSync as readFileSync20 } from "fs";
6319
+ import { basename as basename2, join as join21 } from "path";
6223
6320
  function getRepoName() {
6224
6321
  const config = loadConfig();
6225
6322
  if (config.devlog?.name) {
6226
6323
  return config.devlog.name;
6227
6324
  }
6228
- const packageJsonPath = join20(process.cwd(), "package.json");
6229
- if (existsSync23(packageJsonPath)) {
6325
+ const packageJsonPath = join21(process.cwd(), "package.json");
6326
+ if (existsSync24(packageJsonPath)) {
6230
6327
  try {
6231
6328
  const content = readFileSync20(packageJsonPath, "utf-8");
6232
6329
  const pkg = JSON.parse(content);
@@ -6241,8 +6338,8 @@ function getRepoName() {
6241
6338
 
6242
6339
  // src/commands/devlog/loadDevlogEntries.ts
6243
6340
  import { readdirSync, readFileSync as readFileSync21 } from "fs";
6244
- import { join as join21 } from "path";
6245
- var DEVLOG_DIR = join21(BLOG_REPO_ROOT, "src/content/devlog");
6341
+ import { join as join22 } from "path";
6342
+ var DEVLOG_DIR = join22(BLOG_REPO_ROOT, "src/content/devlog");
6246
6343
  function extractFrontmatter(content) {
6247
6344
  const fm = content.match(/^---\n([\s\S]*?)\n---/);
6248
6345
  return fm?.[1] ?? null;
@@ -6270,7 +6367,7 @@ function readDevlogFiles(callback) {
6270
6367
  try {
6271
6368
  const files = readdirSync(DEVLOG_DIR).filter((f) => f.endsWith(".md"));
6272
6369
  for (const file of files) {
6273
- const content = readFileSync21(join21(DEVLOG_DIR, file), "utf-8");
6370
+ const content = readFileSync21(join22(DEVLOG_DIR, file), "utf-8");
6274
6371
  const parsed = parseFrontmatter(content, file);
6275
6372
  if (parsed) callback(parsed);
6276
6373
  }
@@ -6657,11 +6754,11 @@ function repos(options2) {
6657
6754
 
6658
6755
  // src/commands/devlog/skip.ts
6659
6756
  import { writeFileSync as writeFileSync19 } from "fs";
6660
- import { join as join22 } from "path";
6757
+ import { join as join23 } from "path";
6661
6758
  import chalk82 from "chalk";
6662
6759
  import { stringify as stringifyYaml3 } from "yaml";
6663
6760
  function getBlogConfigPath() {
6664
- return join22(BLOG_REPO_ROOT, "assist.yml");
6761
+ return join23(BLOG_REPO_ROOT, "assist.yml");
6665
6762
  }
6666
6763
  function skip(date) {
6667
6764
  if (!/^\d{4}-\d{2}-\d{2}$/.test(date)) {
@@ -6722,16 +6819,16 @@ function registerDevlog(program2) {
6722
6819
 
6723
6820
  // src/commands/dotnet/checkBuildLocks.ts
6724
6821
  import { closeSync, openSync, readdirSync as readdirSync2 } from "fs";
6725
- import { join as join23 } from "path";
6822
+ import { join as join24 } from "path";
6726
6823
  import chalk84 from "chalk";
6727
6824
 
6728
6825
  // src/shared/findRepoRoot.ts
6729
- import { existsSync as existsSync24 } from "fs";
6826
+ import { existsSync as existsSync25 } from "fs";
6730
6827
  import path21 from "path";
6731
6828
  function findRepoRoot(dir) {
6732
6829
  let current = dir;
6733
6830
  while (current !== path21.dirname(current)) {
6734
- if (existsSync24(path21.join(current, ".git"))) {
6831
+ if (existsSync25(path21.join(current, ".git"))) {
6735
6832
  return current;
6736
6833
  }
6737
6834
  current = path21.dirname(current);
@@ -6750,7 +6847,7 @@ function isLockedDll(debugDir) {
6750
6847
  }
6751
6848
  for (const file of files) {
6752
6849
  if (!file.toLowerCase().endsWith(".dll")) continue;
6753
- const dllPath = join23(debugDir, file);
6850
+ const dllPath = join24(debugDir, file);
6754
6851
  try {
6755
6852
  const fd = openSync(dllPath, "r+");
6756
6853
  closeSync(fd);
@@ -6768,13 +6865,13 @@ function findFirstLockedDll(dir) {
6768
6865
  return null;
6769
6866
  }
6770
6867
  if (entries.includes("bin")) {
6771
- const locked = isLockedDll(join23(dir, "bin", "Debug"));
6868
+ const locked = isLockedDll(join24(dir, "bin", "Debug"));
6772
6869
  if (locked) return locked;
6773
6870
  }
6774
6871
  for (const entry of entries) {
6775
6872
  if (SKIP_DIRS.has(entry) || entry === "bin" || entry.startsWith("."))
6776
6873
  continue;
6777
- const found = findFirstLockedDll(join23(dir, entry));
6874
+ const found = findFirstLockedDll(join24(dir, entry));
6778
6875
  if (found) return found;
6779
6876
  }
6780
6877
  return null;
@@ -6942,12 +7039,12 @@ function printJson(tree, totalCount, solutions) {
6942
7039
  }
6943
7040
 
6944
7041
  // src/commands/dotnet/resolveCsproj.ts
6945
- import { existsSync as existsSync25 } from "fs";
7042
+ import { existsSync as existsSync26 } from "fs";
6946
7043
  import path24 from "path";
6947
7044
  import chalk86 from "chalk";
6948
7045
  function resolveCsproj(csprojPath) {
6949
7046
  const resolved = path24.resolve(csprojPath);
6950
- if (!existsSync25(resolved)) {
7047
+ if (!existsSync26(resolved)) {
6951
7048
  console.error(chalk86.red(`File not found: ${resolved}`));
6952
7049
  process.exit(1);
6953
7050
  }
@@ -7115,17 +7212,17 @@ function filterIssues(issues, all, cliOnly, cliSuppress) {
7115
7212
  }
7116
7213
 
7117
7214
  // src/commands/dotnet/resolveSolution.ts
7118
- import { existsSync as existsSync26 } from "fs";
7215
+ import { existsSync as existsSync27 } from "fs";
7119
7216
  import path25 from "path";
7120
7217
  import chalk90 from "chalk";
7121
7218
 
7122
7219
  // src/commands/dotnet/findSolution.ts
7123
7220
  import { readdirSync as readdirSync4 } from "fs";
7124
- import { dirname as dirname16, join as join24 } from "path";
7221
+ import { dirname as dirname17, join as join25 } from "path";
7125
7222
  import chalk89 from "chalk";
7126
7223
  function findSlnInDir(dir) {
7127
7224
  try {
7128
- return readdirSync4(dir).filter((f) => f.endsWith(".sln")).map((f) => join24(dir, f));
7225
+ return readdirSync4(dir).filter((f) => f.endsWith(".sln")).map((f) => join25(dir, f));
7129
7226
  } catch {
7130
7227
  return [];
7131
7228
  }
@@ -7146,7 +7243,7 @@ function findSolution() {
7146
7243
  process.exit(1);
7147
7244
  }
7148
7245
  if (current === ceiling) break;
7149
- current = dirname16(current);
7246
+ current = dirname17(current);
7150
7247
  }
7151
7248
  console.error(chalk89.red("No .sln file found between cwd and repo root"));
7152
7249
  process.exit(1);
@@ -7156,7 +7253,7 @@ function findSolution() {
7156
7253
  function resolveSolution(sln) {
7157
7254
  if (sln) {
7158
7255
  const resolved = path25.resolve(sln);
7159
- if (!existsSync26(resolved)) {
7256
+ if (!existsSync27(resolved)) {
7160
7257
  console.error(chalk90.red(`Solution file not found: ${resolved}`));
7161
7258
  process.exit(1);
7162
7259
  }
@@ -7196,7 +7293,7 @@ function parseInspectReport(json) {
7196
7293
 
7197
7294
  // src/commands/dotnet/runInspectCode.ts
7198
7295
  import { execSync as execSync24 } from "child_process";
7199
- import { existsSync as existsSync27, readFileSync as readFileSync24, unlinkSync as unlinkSync5 } from "fs";
7296
+ import { existsSync as existsSync28, readFileSync as readFileSync24, unlinkSync as unlinkSync5 } from "fs";
7200
7297
  import { tmpdir as tmpdir2 } from "os";
7201
7298
  import path26 from "path";
7202
7299
  import chalk91 from "chalk";
@@ -7227,7 +7324,7 @@ function runInspectCode(slnPath, include, swea) {
7227
7324
  console.error(chalk91.red("jb inspectcode failed"));
7228
7325
  process.exit(1);
7229
7326
  }
7230
- if (!existsSync27(reportPath)) {
7327
+ if (!existsSync28(reportPath)) {
7231
7328
  console.error(chalk91.red("Report file not generated"));
7232
7329
  process.exit(1);
7233
7330
  }
@@ -7240,8 +7337,9 @@ function runInspectCode(slnPath, include, swea) {
7240
7337
  import { execSync as execSync25 } from "child_process";
7241
7338
  import chalk92 from "chalk";
7242
7339
  function resolveMsbuildPath() {
7243
- const config = loadConfig();
7244
- const buildConfig = config.run?.find((r) => r.name === "build");
7340
+ const { run: run4 } = loadConfig();
7341
+ const configs = resolveRunConfigs(run4, getConfigDir());
7342
+ const buildConfig = configs.find((r) => r.name === "build");
7245
7343
  return buildConfig?.command ?? "msbuild";
7246
7344
  }
7247
7345
  function assertMsbuildInstalled() {
@@ -7459,18 +7557,18 @@ function acceptanceCriteria(issueKey) {
7459
7557
  import { execSync as execSync27 } from "child_process";
7460
7558
 
7461
7559
  // src/shared/loadJson.ts
7462
- import { existsSync as existsSync28, mkdirSync as mkdirSync6, readFileSync as readFileSync25, writeFileSync as writeFileSync20 } from "fs";
7560
+ import { existsSync as existsSync29, mkdirSync as mkdirSync6, readFileSync as readFileSync25, writeFileSync as writeFileSync20 } from "fs";
7463
7561
  import { homedir as homedir6 } from "os";
7464
- import { join as join25 } from "path";
7562
+ import { join as join26 } from "path";
7465
7563
  function getStoreDir() {
7466
- return join25(homedir6(), ".assist");
7564
+ return join26(homedir6(), ".assist");
7467
7565
  }
7468
7566
  function getStorePath(filename) {
7469
- return join25(getStoreDir(), filename);
7567
+ return join26(getStoreDir(), filename);
7470
7568
  }
7471
7569
  function loadJson(filename) {
7472
7570
  const path50 = getStorePath(filename);
7473
- if (existsSync28(path50)) {
7571
+ if (existsSync29(path50)) {
7474
7572
  try {
7475
7573
  return JSON.parse(readFileSync25(path50, "utf-8"));
7476
7574
  } catch {
@@ -7481,7 +7579,7 @@ function loadJson(filename) {
7481
7579
  }
7482
7580
  function saveJson(filename, data) {
7483
7581
  const dir = getStoreDir();
7484
- if (!existsSync28(dir)) {
7582
+ if (!existsSync29(dir)) {
7485
7583
  mkdirSync6(dir, { recursive: true });
7486
7584
  }
7487
7585
  writeFileSync20(getStorePath(filename), JSON.stringify(data, null, 2));
@@ -7798,7 +7896,7 @@ function registerNews(program2) {
7798
7896
  import { spawnSync as spawnSync2 } from "child_process";
7799
7897
  import { unlinkSync as unlinkSync6, writeFileSync as writeFileSync21 } from "fs";
7800
7898
  import { tmpdir as tmpdir3 } from "os";
7801
- import { join as join26 } from "path";
7899
+ import { join as join27 } from "path";
7802
7900
 
7803
7901
  // src/commands/prs/shared.ts
7804
7902
  import { execSync as execSync28 } from "child_process";
@@ -7870,7 +7968,7 @@ function comment2(path50, line, body) {
7870
7968
  validateLine(line);
7871
7969
  try {
7872
7970
  const prId = getCurrentPrNodeId();
7873
- const queryFile = join26(tmpdir3(), `gh-query-${Date.now()}.graphql`);
7971
+ const queryFile = join27(tmpdir3(), `gh-query-${Date.now()}.graphql`);
7874
7972
  writeFileSync21(queryFile, MUTATION);
7875
7973
  try {
7876
7974
  const result = spawnSync2(
@@ -7915,18 +8013,18 @@ import { execSync as execSync30 } from "child_process";
7915
8013
  import { execSync as execSync29 } from "child_process";
7916
8014
  import { unlinkSync as unlinkSync8, writeFileSync as writeFileSync22 } from "fs";
7917
8015
  import { tmpdir as tmpdir4 } from "os";
7918
- import { join as join28 } from "path";
8016
+ import { join as join29 } from "path";
7919
8017
 
7920
8018
  // src/commands/prs/loadCommentsCache.ts
7921
- import { existsSync as existsSync29, readFileSync as readFileSync26, unlinkSync as unlinkSync7 } from "fs";
7922
- import { join as join27 } from "path";
8019
+ import { existsSync as existsSync30, readFileSync as readFileSync26, unlinkSync as unlinkSync7 } from "fs";
8020
+ import { join as join28 } from "path";
7923
8021
  import { parse as parse2 } from "yaml";
7924
8022
  function getCachePath(prNumber) {
7925
- return join27(process.cwd(), ".assist", `pr-${prNumber}-comments.yaml`);
8023
+ return join28(process.cwd(), ".assist", `pr-${prNumber}-comments.yaml`);
7926
8024
  }
7927
8025
  function loadCommentsCache(prNumber) {
7928
8026
  const cachePath = getCachePath(prNumber);
7929
- if (!existsSync29(cachePath)) {
8027
+ if (!existsSync30(cachePath)) {
7930
8028
  return null;
7931
8029
  }
7932
8030
  const content = readFileSync26(cachePath, "utf-8");
@@ -7934,7 +8032,7 @@ function loadCommentsCache(prNumber) {
7934
8032
  }
7935
8033
  function deleteCommentsCache(prNumber) {
7936
8034
  const cachePath = getCachePath(prNumber);
7937
- if (existsSync29(cachePath)) {
8035
+ if (existsSync30(cachePath)) {
7938
8036
  unlinkSync7(cachePath);
7939
8037
  console.log("No more unresolved line comments. Cache dropped.");
7940
8038
  }
@@ -7949,7 +8047,7 @@ function replyToComment(org, repo, prNumber, commentId, message) {
7949
8047
  }
7950
8048
  function resolveThread(threadId) {
7951
8049
  const mutation = `mutation($threadId: ID!) { resolveReviewThread(input: {threadId: $threadId}) { thread { isResolved } } }`;
7952
- const queryFile = join28(tmpdir4(), `gh-mutation-${Date.now()}.graphql`);
8050
+ const queryFile = join29(tmpdir4(), `gh-mutation-${Date.now()}.graphql`);
7953
8051
  writeFileSync22(queryFile, mutation);
7954
8052
  try {
7955
8053
  execSync29(
@@ -8031,18 +8129,18 @@ function fixed(commentId, sha) {
8031
8129
  }
8032
8130
 
8033
8131
  // src/commands/prs/listComments/index.ts
8034
- import { existsSync as existsSync30, mkdirSync as mkdirSync7, writeFileSync as writeFileSync24 } from "fs";
8035
- import { join as join30 } from "path";
8132
+ import { existsSync as existsSync31, mkdirSync as mkdirSync7, writeFileSync as writeFileSync24 } from "fs";
8133
+ import { join as join31 } from "path";
8036
8134
  import { stringify } from "yaml";
8037
8135
 
8038
8136
  // src/commands/prs/fetchThreadIds.ts
8039
8137
  import { execSync as execSync31 } from "child_process";
8040
8138
  import { unlinkSync as unlinkSync9, writeFileSync as writeFileSync23 } from "fs";
8041
8139
  import { tmpdir as tmpdir5 } from "os";
8042
- import { join as join29 } from "path";
8140
+ import { join as join30 } from "path";
8043
8141
  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 } } } } } } }`;
8044
8142
  function fetchThreadIds(org, repo, prNumber) {
8045
- const queryFile = join29(tmpdir5(), `gh-query-${Date.now()}.graphql`);
8143
+ const queryFile = join30(tmpdir5(), `gh-query-${Date.now()}.graphql`);
8046
8144
  writeFileSync23(queryFile, THREAD_QUERY);
8047
8145
  try {
8048
8146
  const result = execSync31(
@@ -8156,8 +8254,8 @@ function printComments2(result) {
8156
8254
 
8157
8255
  // src/commands/prs/listComments/index.ts
8158
8256
  function writeCommentsCache(prNumber, comments2) {
8159
- const assistDir = join30(process.cwd(), ".assist");
8160
- if (!existsSync30(assistDir)) {
8257
+ const assistDir = join31(process.cwd(), ".assist");
8258
+ if (!existsSync31(assistDir)) {
8161
8259
  mkdirSync7(assistDir, { recursive: true });
8162
8260
  }
8163
8261
  const cacheData = {
@@ -8165,7 +8263,7 @@ function writeCommentsCache(prNumber, comments2) {
8165
8263
  fetchedAt: (/* @__PURE__ */ new Date()).toISOString(),
8166
8264
  comments: comments2
8167
8265
  };
8168
- const cachePath = join30(assistDir, `pr-${prNumber}-comments.yaml`);
8266
+ const cachePath = join31(assistDir, `pr-${prNumber}-comments.yaml`);
8169
8267
  writeFileSync24(cachePath, stringify(cacheData));
8170
8268
  }
8171
8269
  function handleKnownErrors(error) {
@@ -8198,7 +8296,7 @@ async function listComments() {
8198
8296
  ];
8199
8297
  updateCache(prNumber, allComments);
8200
8298
  const hasLineComments = allComments.some((c) => c.type === "line");
8201
- const cachePath = hasLineComments ? join30(process.cwd(), ".assist", `pr-${prNumber}-comments.yaml`) : null;
8299
+ const cachePath = hasLineComments ? join31(process.cwd(), ".assist", `pr-${prNumber}-comments.yaml`) : null;
8202
8300
  return { comments: allComments, cachePath };
8203
8301
  } catch (error) {
8204
8302
  const handled = handleKnownErrors(error);
@@ -8968,7 +9066,7 @@ function getViolations(pattern2, options2 = {}, maxLines = DEFAULT_MAX_LINES) {
8968
9066
 
8969
9067
  // src/commands/refactor/check/index.ts
8970
9068
  function runScript(script, cwd) {
8971
- return new Promise((resolve8) => {
9069
+ return new Promise((resolve12) => {
8972
9070
  const child = spawn4("npm", ["run", script], {
8973
9071
  stdio: "pipe",
8974
9072
  shell: true,
@@ -8982,7 +9080,7 @@ function runScript(script, cwd) {
8982
9080
  output += data.toString();
8983
9081
  });
8984
9082
  child.on("close", (code) => {
8985
- resolve8({ script, code: code ?? 1, output });
9083
+ resolve12({ script, code: code ?? 1, output });
8986
9084
  });
8987
9085
  });
8988
9086
  }
@@ -10592,8 +10690,8 @@ function registerSeq(program2) {
10592
10690
  }
10593
10691
 
10594
10692
  // src/commands/transcript/shared.ts
10595
- import { existsSync as existsSync31, readdirSync as readdirSync5, statSync as statSync4 } from "fs";
10596
- import { basename as basename4, join as join31, relative } from "path";
10693
+ import { existsSync as existsSync32, readdirSync as readdirSync5, statSync as statSync4 } from "fs";
10694
+ import { basename as basename4, join as join32, relative as relative2 } from "path";
10597
10695
  import * as readline2 from "readline";
10598
10696
  var DATE_PREFIX_REGEX = /^\d{4}-\d{2}-\d{2}/;
10599
10697
  function getDatePrefix(daysOffset = 0) {
@@ -10608,10 +10706,10 @@ function isValidDatePrefix(filename) {
10608
10706
  return DATE_PREFIX_REGEX.test(filename);
10609
10707
  }
10610
10708
  function collectFiles(dir, extension) {
10611
- if (!existsSync31(dir)) return [];
10709
+ if (!existsSync32(dir)) return [];
10612
10710
  const results = [];
10613
10711
  for (const entry of readdirSync5(dir)) {
10614
- const fullPath = join31(dir, entry);
10712
+ const fullPath = join32(dir, entry);
10615
10713
  if (statSync4(fullPath).isDirectory()) {
10616
10714
  results.push(...collectFiles(fullPath, extension));
10617
10715
  } else if (entry.endsWith(extension)) {
@@ -10623,7 +10721,7 @@ function collectFiles(dir, extension) {
10623
10721
  function toFileInfo(baseDir, fullPath) {
10624
10722
  return {
10625
10723
  absolutePath: fullPath,
10626
- relativePath: relative(baseDir, fullPath),
10724
+ relativePath: relative2(baseDir, fullPath),
10627
10725
  filename: basename4(fullPath)
10628
10726
  };
10629
10727
  }
@@ -10643,9 +10741,9 @@ function createReadlineInterface() {
10643
10741
  });
10644
10742
  }
10645
10743
  function askQuestion(rl, question) {
10646
- return new Promise((resolve8) => {
10744
+ return new Promise((resolve12) => {
10647
10745
  rl.question(question, (answer) => {
10648
- resolve8(answer.trim());
10746
+ resolve12(answer.trim());
10649
10747
  });
10650
10748
  });
10651
10749
  }
@@ -10705,14 +10803,14 @@ async function configure() {
10705
10803
  }
10706
10804
 
10707
10805
  // src/commands/transcript/format/index.ts
10708
- import { existsSync as existsSync33 } from "fs";
10806
+ import { existsSync as existsSync34 } from "fs";
10709
10807
 
10710
10808
  // src/commands/transcript/format/fixInvalidDatePrefixes/index.ts
10711
- import { dirname as dirname18, join as join33 } from "path";
10809
+ import { dirname as dirname19, join as join34 } from "path";
10712
10810
 
10713
10811
  // src/commands/transcript/format/fixInvalidDatePrefixes/promptForDateFix.ts
10714
10812
  import { renameSync as renameSync2 } from "fs";
10715
- import { join as join32 } from "path";
10813
+ import { join as join33 } from "path";
10716
10814
  async function resolveDate(rl, choice) {
10717
10815
  if (choice === "1") return getDatePrefix(0);
10718
10816
  if (choice === "2") return getDatePrefix(-1);
@@ -10727,7 +10825,7 @@ async function resolveDate(rl, choice) {
10727
10825
  }
10728
10826
  function renameWithPrefix(vttDir, vttFile, prefix2) {
10729
10827
  const newFilename = `${prefix2}.${vttFile}`;
10730
- renameSync2(join32(vttDir, vttFile), join32(vttDir, newFilename));
10828
+ renameSync2(join33(vttDir, vttFile), join33(vttDir, newFilename));
10731
10829
  console.log(`Renamed to: ${newFilename}`);
10732
10830
  return newFilename;
10733
10831
  }
@@ -10758,15 +10856,15 @@ async function fixInvalidDatePrefixes(vttFiles) {
10758
10856
  for (let i = 0; i < vttFiles.length; i++) {
10759
10857
  const vttFile = vttFiles[i];
10760
10858
  if (!isValidDatePrefix(vttFile.filename)) {
10761
- const vttFileDir = dirname18(vttFile.absolutePath);
10859
+ const vttFileDir = dirname19(vttFile.absolutePath);
10762
10860
  const newFilename = await promptForDateFix(vttFile.filename, vttFileDir);
10763
10861
  if (newFilename) {
10764
- const newRelativePath = join33(
10765
- dirname18(vttFile.relativePath),
10862
+ const newRelativePath = join34(
10863
+ dirname19(vttFile.relativePath),
10766
10864
  newFilename
10767
10865
  );
10768
10866
  vttFiles[i] = {
10769
- absolutePath: join33(vttFileDir, newFilename),
10867
+ absolutePath: join34(vttFileDir, newFilename),
10770
10868
  relativePath: newRelativePath,
10771
10869
  filename: newFilename
10772
10870
  };
@@ -10779,8 +10877,8 @@ async function fixInvalidDatePrefixes(vttFiles) {
10779
10877
  }
10780
10878
 
10781
10879
  // src/commands/transcript/format/processVttFile/index.ts
10782
- import { existsSync as existsSync32, mkdirSync as mkdirSync8, readFileSync as readFileSync27, writeFileSync as writeFileSync25 } from "fs";
10783
- import { basename as basename5, dirname as dirname19, join as join34 } from "path";
10880
+ import { existsSync as existsSync33, mkdirSync as mkdirSync8, readFileSync as readFileSync27, writeFileSync as writeFileSync25 } from "fs";
10881
+ import { basename as basename5, dirname as dirname20, join as join35 } from "path";
10784
10882
 
10785
10883
  // src/commands/transcript/cleanText.ts
10786
10884
  function cleanText(text) {
@@ -10990,21 +11088,21 @@ function toMdFilename(vttFilename) {
10990
11088
  return `${basename5(vttFilename, ".vtt").replace(/\s*Transcription\s*/g, " ").trim()}.md`;
10991
11089
  }
10992
11090
  function resolveOutputDir(relativeDir, transcriptsDir) {
10993
- return relativeDir === "." ? transcriptsDir : join34(transcriptsDir, relativeDir);
11091
+ return relativeDir === "." ? transcriptsDir : join35(transcriptsDir, relativeDir);
10994
11092
  }
10995
11093
  function buildOutputPaths(vttFile, transcriptsDir) {
10996
11094
  const mdFile = toMdFilename(vttFile.filename);
10997
- const relativeDir = dirname19(vttFile.relativePath);
11095
+ const relativeDir = dirname20(vttFile.relativePath);
10998
11096
  const outputDir = resolveOutputDir(relativeDir, transcriptsDir);
10999
- const outputPath = join34(outputDir, mdFile);
11097
+ const outputPath = join35(outputDir, mdFile);
11000
11098
  return { outputDir, outputPath, mdFile, relativeDir };
11001
11099
  }
11002
11100
  function logSkipped(relativeDir, mdFile) {
11003
- console.log(`Skipping (already exists): ${join34(relativeDir, mdFile)}`);
11101
+ console.log(`Skipping (already exists): ${join35(relativeDir, mdFile)}`);
11004
11102
  return "skipped";
11005
11103
  }
11006
11104
  function ensureDirectory(dir, label2) {
11007
- if (!existsSync32(dir)) {
11105
+ if (!existsSync33(dir)) {
11008
11106
  mkdirSync8(dir, { recursive: true });
11009
11107
  console.log(`Created ${label2}: ${dir}`);
11010
11108
  }
@@ -11040,7 +11138,7 @@ function convertVttToMarkdown(inputPath, outputPath) {
11040
11138
  logReduction(cues.length, chatMessages.length);
11041
11139
  }
11042
11140
  function tryProcessVtt(vttFile, paths) {
11043
- if (existsSync32(paths.outputPath))
11141
+ if (existsSync33(paths.outputPath))
11044
11142
  return logSkipped(paths.relativeDir, paths.mdFile);
11045
11143
  convertVttToMarkdown(vttFile.absolutePath, paths.outputPath);
11046
11144
  return "processed";
@@ -11066,7 +11164,7 @@ function processAllFiles(vttFiles, transcriptsDir) {
11066
11164
  logSummary(counts);
11067
11165
  }
11068
11166
  function requireVttDir(vttDir) {
11069
- if (!existsSync33(vttDir)) {
11167
+ if (!existsSync34(vttDir)) {
11070
11168
  console.error(`VTT directory not found: ${vttDir}`);
11071
11169
  process.exit(1);
11072
11170
  }
@@ -11098,18 +11196,18 @@ async function format() {
11098
11196
  }
11099
11197
 
11100
11198
  // src/commands/transcript/summarise/index.ts
11101
- import { existsSync as existsSync35 } from "fs";
11102
- import { basename as basename6, dirname as dirname21, join as join36, relative as relative2 } from "path";
11199
+ import { existsSync as existsSync36 } from "fs";
11200
+ import { basename as basename6, dirname as dirname22, join as join37, relative as relative3 } from "path";
11103
11201
 
11104
11202
  // src/commands/transcript/summarise/processStagedFile/index.ts
11105
11203
  import {
11106
- existsSync as existsSync34,
11204
+ existsSync as existsSync35,
11107
11205
  mkdirSync as mkdirSync9,
11108
11206
  readFileSync as readFileSync28,
11109
11207
  renameSync as renameSync3,
11110
11208
  rmSync
11111
11209
  } from "fs";
11112
- import { dirname as dirname20, join as join35 } from "path";
11210
+ import { dirname as dirname21, join as join36 } from "path";
11113
11211
 
11114
11212
  // src/commands/transcript/summarise/processStagedFile/validateStagedContent.ts
11115
11213
  import chalk130 from "chalk";
@@ -11138,9 +11236,9 @@ function validateStagedContent(filename, content) {
11138
11236
  }
11139
11237
 
11140
11238
  // src/commands/transcript/summarise/processStagedFile/index.ts
11141
- var STAGING_DIR = join35(process.cwd(), ".assist", "transcript");
11239
+ var STAGING_DIR = join36(process.cwd(), ".assist", "transcript");
11142
11240
  function processStagedFile() {
11143
- if (!existsSync34(STAGING_DIR)) {
11241
+ if (!existsSync35(STAGING_DIR)) {
11144
11242
  return false;
11145
11243
  }
11146
11244
  const stagedFiles = findMdFilesRecursive(STAGING_DIR);
@@ -11162,9 +11260,9 @@ function processStagedFile() {
11162
11260
  );
11163
11261
  process.exit(1);
11164
11262
  }
11165
- const destPath = join35(summaryDir, matchingTranscript.relativePath);
11166
- const destDir = dirname20(destPath);
11167
- if (!existsSync34(destDir)) {
11263
+ const destPath = join36(summaryDir, matchingTranscript.relativePath);
11264
+ const destDir = dirname21(destPath);
11265
+ if (!existsSync35(destDir)) {
11168
11266
  mkdirSync9(destDir, { recursive: true });
11169
11267
  }
11170
11268
  renameSync3(stagedFile.absolutePath, destPath);
@@ -11177,8 +11275,8 @@ function processStagedFile() {
11177
11275
 
11178
11276
  // src/commands/transcript/summarise/index.ts
11179
11277
  function buildRelativeKey(relativePath, baseName) {
11180
- const relDir = dirname21(relativePath);
11181
- return relDir === "." ? baseName : join36(relDir, baseName);
11278
+ const relDir = dirname22(relativePath);
11279
+ return relDir === "." ? baseName : join37(relDir, baseName);
11182
11280
  }
11183
11281
  function buildSummaryIndex(summaryDir) {
11184
11282
  const summaryFiles = findMdFilesRecursive(summaryDir);
@@ -11191,7 +11289,7 @@ function buildSummaryIndex(summaryDir) {
11191
11289
  function summarise2() {
11192
11290
  processStagedFile();
11193
11291
  const { transcriptsDir, summaryDir } = getTranscriptConfig();
11194
- if (!existsSync35(transcriptsDir)) {
11292
+ if (!existsSync36(transcriptsDir)) {
11195
11293
  console.log("No transcripts directory found.");
11196
11294
  return;
11197
11295
  }
@@ -11212,10 +11310,10 @@ function summarise2() {
11212
11310
  }
11213
11311
  const next3 = missing[0];
11214
11312
  const outputFilename = `${getTranscriptBaseName(next3.filename)}.md`;
11215
- const outputPath = join36(STAGING_DIR, outputFilename);
11216
- const summaryFileDir = join36(summaryDir, dirname21(next3.relativePath));
11313
+ const outputPath = join37(STAGING_DIR, outputFilename);
11314
+ const summaryFileDir = join37(summaryDir, dirname22(next3.relativePath));
11217
11315
  const relativeTranscriptPath = encodeURI(
11218
- relative2(summaryFileDir, next3.absolutePath).replace(/\\/g, "/")
11316
+ relative3(summaryFileDir, next3.absolutePath).replace(/\\/g, "/")
11219
11317
  );
11220
11318
  console.log(`Missing summaries: ${missing.length}
11221
11319
  `);
@@ -11259,45 +11357,45 @@ function registerVerify(program2) {
11259
11357
 
11260
11358
  // src/commands/voice/devices.ts
11261
11359
  import { spawnSync as spawnSync3 } from "child_process";
11262
- import { join as join38 } from "path";
11360
+ import { join as join39 } from "path";
11263
11361
 
11264
11362
  // src/commands/voice/shared.ts
11265
11363
  import { homedir as homedir7 } from "os";
11266
- import { dirname as dirname22, join as join37 } from "path";
11364
+ import { dirname as dirname23, join as join38 } from "path";
11267
11365
  import { fileURLToPath as fileURLToPath6 } from "url";
11268
- var __dirname6 = dirname22(fileURLToPath6(import.meta.url));
11269
- var VOICE_DIR = join37(homedir7(), ".assist", "voice");
11366
+ var __dirname6 = dirname23(fileURLToPath6(import.meta.url));
11367
+ var VOICE_DIR = join38(homedir7(), ".assist", "voice");
11270
11368
  var voicePaths = {
11271
11369
  dir: VOICE_DIR,
11272
- pid: join37(VOICE_DIR, "voice.pid"),
11273
- log: join37(VOICE_DIR, "voice.log"),
11274
- venv: join37(VOICE_DIR, ".venv"),
11275
- lock: join37(VOICE_DIR, "voice.lock")
11370
+ pid: join38(VOICE_DIR, "voice.pid"),
11371
+ log: join38(VOICE_DIR, "voice.log"),
11372
+ venv: join38(VOICE_DIR, ".venv"),
11373
+ lock: join38(VOICE_DIR, "voice.lock")
11276
11374
  };
11277
11375
  function getPythonDir() {
11278
- return join37(__dirname6, "commands", "voice", "python");
11376
+ return join38(__dirname6, "commands", "voice", "python");
11279
11377
  }
11280
11378
  function getVenvPython() {
11281
- return process.platform === "win32" ? join37(voicePaths.venv, "Scripts", "python.exe") : join37(voicePaths.venv, "bin", "python");
11379
+ return process.platform === "win32" ? join38(voicePaths.venv, "Scripts", "python.exe") : join38(voicePaths.venv, "bin", "python");
11282
11380
  }
11283
11381
  function getLockDir() {
11284
11382
  const config = loadConfig();
11285
11383
  return config.voice?.lockDir ?? VOICE_DIR;
11286
11384
  }
11287
11385
  function getLockFile() {
11288
- return join37(getLockDir(), "voice.lock");
11386
+ return join38(getLockDir(), "voice.lock");
11289
11387
  }
11290
11388
 
11291
11389
  // src/commands/voice/devices.ts
11292
11390
  function devices() {
11293
- const script = join38(getPythonDir(), "list_devices.py");
11391
+ const script = join39(getPythonDir(), "list_devices.py");
11294
11392
  spawnSync3(getVenvPython(), [script], { stdio: "inherit" });
11295
11393
  }
11296
11394
 
11297
11395
  // src/commands/voice/logs.ts
11298
- import { existsSync as existsSync36, readFileSync as readFileSync29 } from "fs";
11396
+ import { existsSync as existsSync37, readFileSync as readFileSync29 } from "fs";
11299
11397
  function logs(options2) {
11300
- if (!existsSync36(voicePaths.log)) {
11398
+ if (!existsSync37(voicePaths.log)) {
11301
11399
  console.log("No voice log file found");
11302
11400
  return;
11303
11401
  }
@@ -11325,12 +11423,12 @@ function logs(options2) {
11325
11423
  // src/commands/voice/setup.ts
11326
11424
  import { spawnSync as spawnSync4 } from "child_process";
11327
11425
  import { mkdirSync as mkdirSync11 } from "fs";
11328
- import { join as join40 } from "path";
11426
+ import { join as join41 } from "path";
11329
11427
 
11330
11428
  // src/commands/voice/checkLockFile.ts
11331
11429
  import { execSync as execSync38 } from "child_process";
11332
- import { existsSync as existsSync37, mkdirSync as mkdirSync10, readFileSync as readFileSync30, writeFileSync as writeFileSync26 } from "fs";
11333
- import { join as join39 } from "path";
11430
+ import { existsSync as existsSync38, mkdirSync as mkdirSync10, readFileSync as readFileSync30, writeFileSync as writeFileSync26 } from "fs";
11431
+ import { join as join40 } from "path";
11334
11432
  function isProcessAlive2(pid) {
11335
11433
  try {
11336
11434
  process.kill(pid, 0);
@@ -11341,7 +11439,7 @@ function isProcessAlive2(pid) {
11341
11439
  }
11342
11440
  function checkLockFile() {
11343
11441
  const lockFile = getLockFile();
11344
- if (!existsSync37(lockFile)) return;
11442
+ if (!existsSync38(lockFile)) return;
11345
11443
  try {
11346
11444
  const lock = JSON.parse(readFileSync30(lockFile, "utf-8"));
11347
11445
  if (lock.pid && isProcessAlive2(lock.pid)) {
@@ -11354,7 +11452,7 @@ function checkLockFile() {
11354
11452
  }
11355
11453
  }
11356
11454
  function bootstrapVenv() {
11357
- if (existsSync37(getVenvPython())) return;
11455
+ if (existsSync38(getVenvPython())) return;
11358
11456
  console.log("Setting up Python environment...");
11359
11457
  const pythonDir = getPythonDir();
11360
11458
  execSync38(
@@ -11367,7 +11465,7 @@ function bootstrapVenv() {
11367
11465
  }
11368
11466
  function writeLockFile(pid) {
11369
11467
  const lockFile = getLockFile();
11370
- mkdirSync10(join39(lockFile, ".."), { recursive: true });
11468
+ mkdirSync10(join40(lockFile, ".."), { recursive: true });
11371
11469
  writeFileSync26(
11372
11470
  lockFile,
11373
11471
  JSON.stringify({
@@ -11383,7 +11481,7 @@ function setup() {
11383
11481
  mkdirSync11(voicePaths.dir, { recursive: true });
11384
11482
  bootstrapVenv();
11385
11483
  console.log("\nDownloading models...\n");
11386
- const script = join40(getPythonDir(), "setup_models.py");
11484
+ const script = join41(getPythonDir(), "setup_models.py");
11387
11485
  const result = spawnSync4(getVenvPython(), [script], {
11388
11486
  stdio: "inherit",
11389
11487
  env: { ...process.env, VOICE_LOG_FILE: voicePaths.log }
@@ -11397,7 +11495,7 @@ function setup() {
11397
11495
  // src/commands/voice/start.ts
11398
11496
  import { spawn as spawn5 } from "child_process";
11399
11497
  import { mkdirSync as mkdirSync12, writeFileSync as writeFileSync27 } from "fs";
11400
- import { join as join41 } from "path";
11498
+ import { join as join42 } from "path";
11401
11499
 
11402
11500
  // src/commands/voice/buildDaemonEnv.ts
11403
11501
  function buildDaemonEnv(options2) {
@@ -11435,7 +11533,7 @@ function start2(options2) {
11435
11533
  bootstrapVenv();
11436
11534
  const debug = options2.debug || options2.foreground || process.platform === "win32";
11437
11535
  const env = buildDaemonEnv({ debug });
11438
- const script = join41(getPythonDir(), "voice_daemon.py");
11536
+ const script = join42(getPythonDir(), "voice_daemon.py");
11439
11537
  const python = getVenvPython();
11440
11538
  if (options2.foreground) {
11441
11539
  spawnForeground(python, script, env);
@@ -11445,7 +11543,7 @@ function start2(options2) {
11445
11543
  }
11446
11544
 
11447
11545
  // src/commands/voice/status.ts
11448
- import { existsSync as existsSync38, readFileSync as readFileSync31 } from "fs";
11546
+ import { existsSync as existsSync39, readFileSync as readFileSync31 } from "fs";
11449
11547
  function isProcessAlive3(pid) {
11450
11548
  try {
11451
11549
  process.kill(pid, 0);
@@ -11455,12 +11553,12 @@ function isProcessAlive3(pid) {
11455
11553
  }
11456
11554
  }
11457
11555
  function readRecentLogs(count) {
11458
- if (!existsSync38(voicePaths.log)) return [];
11556
+ if (!existsSync39(voicePaths.log)) return [];
11459
11557
  const lines = readFileSync31(voicePaths.log, "utf-8").trim().split("\n");
11460
11558
  return lines.slice(-count);
11461
11559
  }
11462
11560
  function status() {
11463
- if (!existsSync38(voicePaths.pid)) {
11561
+ if (!existsSync39(voicePaths.pid)) {
11464
11562
  console.log("Voice daemon: not running (no PID file)");
11465
11563
  return;
11466
11564
  }
@@ -11483,9 +11581,9 @@ function status() {
11483
11581
  }
11484
11582
 
11485
11583
  // src/commands/voice/stop.ts
11486
- import { existsSync as existsSync39, readFileSync as readFileSync32, unlinkSync as unlinkSync10 } from "fs";
11584
+ import { existsSync as existsSync40, readFileSync as readFileSync32, unlinkSync as unlinkSync10 } from "fs";
11487
11585
  function stop() {
11488
- if (!existsSync39(voicePaths.pid)) {
11586
+ if (!existsSync40(voicePaths.pid)) {
11489
11587
  console.log("Voice daemon is not running (no PID file)");
11490
11588
  return;
11491
11589
  }
@@ -11502,7 +11600,7 @@ function stop() {
11502
11600
  }
11503
11601
  try {
11504
11602
  const lockFile = getLockFile();
11505
- if (existsSync39(lockFile)) unlinkSync10(lockFile);
11603
+ if (existsSync40(lockFile)) unlinkSync10(lockFile);
11506
11604
  } catch {
11507
11605
  }
11508
11606
  console.log("Voice daemon stopped");
@@ -11586,7 +11684,7 @@ function extractCode(url, expectedState) {
11586
11684
  return code;
11587
11685
  }
11588
11686
  function waitForCallback(port, expectedState) {
11589
- return new Promise((resolve8, reject) => {
11687
+ return new Promise((resolve12, reject) => {
11590
11688
  const timeout = setTimeout(() => {
11591
11689
  server.close();
11592
11690
  reject(new Error("Authorization timed out after 120 seconds"));
@@ -11603,7 +11701,7 @@ function waitForCallback(port, expectedState) {
11603
11701
  const code = extractCode(url, expectedState);
11604
11702
  respondHtml(res, 200, "Authorization successful!");
11605
11703
  server.close();
11606
- resolve8(code);
11704
+ resolve12(code);
11607
11705
  } catch (err) {
11608
11706
  respondHtml(res, 400, err.message);
11609
11707
  server.close();
@@ -11724,11 +11822,11 @@ async function auth() {
11724
11822
 
11725
11823
  // src/commands/roam/showClaudeCodeIcon.ts
11726
11824
  import { readFileSync as readFileSync33 } from "fs";
11727
- import { join as join42 } from "path";
11825
+ import { join as join43 } from "path";
11728
11826
  async function showClaudeCodeIcon() {
11729
11827
  const appData = process.env.APPDATA;
11730
11828
  if (!appData) return;
11731
- const portFile = join42(appData, "Roam", "roam-local-api.port");
11829
+ const portFile = join43(appData, "Roam", "roam-local-api.port");
11732
11830
  let port;
11733
11831
  try {
11734
11832
  port = readFileSync33(portFile, "utf-8").trim();
@@ -11754,12 +11852,13 @@ function registerRoam(program2) {
11754
11852
  }
11755
11853
 
11756
11854
  // src/commands/run/index.ts
11757
- import { resolve as resolve5 } from "path";
11855
+ import { resolve as resolve9 } from "path";
11758
11856
 
11759
11857
  // src/commands/run/formatConfiguredCommands.ts
11760
11858
  function formatConfiguredCommands() {
11761
- const { run: configs } = loadConfig();
11762
- if (!configs || configs.length === 0) return "\nNo configured commands";
11859
+ const { run: entries } = loadConfig();
11860
+ const configs = resolveRunConfigs(entries, getConfigDir());
11861
+ if (configs.length === 0) return "\nNo configured commands";
11763
11862
  const names = configs.map((r) => ` ${r.name}`).join("\n");
11764
11863
  return `
11765
11864
  Configured commands:
@@ -11842,8 +11941,9 @@ function exitNoRunConfigs() {
11842
11941
  }
11843
11942
  function requireRunConfigs() {
11844
11943
  const { run: run4 } = loadConfig();
11845
- if (!run4 || run4.length === 0) return exitNoRunConfigs();
11846
- return run4;
11944
+ const configs = resolveRunConfigs(run4, getConfigDir());
11945
+ if (configs.length === 0) return exitNoRunConfigs();
11946
+ return configs;
11847
11947
  }
11848
11948
  function exitWithConfigNotFound(name, configs) {
11849
11949
  console.error(`No run configuration found with name: ${name}`);
@@ -11854,38 +11954,41 @@ function findRunConfig(name) {
11854
11954
  const configs = requireRunConfigs();
11855
11955
  return configs.find((r) => r.name === name) ?? exitWithConfigNotFound(name, configs);
11856
11956
  }
11857
- function listRunConfigs() {
11957
+ function listRunConfigs(verbose) {
11858
11958
  const configs = requireRunConfigs();
11859
11959
  for (const config of configs) {
11860
- const args = config.args?.length ? ` ${config.args.join(" ")}` : "";
11861
- console.log(`${config.name}: ${config.command}${args}`);
11960
+ if (verbose) {
11961
+ const args = config.args?.length ? ` ${config.args.join(" ")}` : "";
11962
+ console.log(`${config.name}: ${config.command}${args}`);
11963
+ } else {
11964
+ console.log(config.name);
11965
+ }
11862
11966
  }
11863
11967
  }
11968
+ function execRunConfig(config, args) {
11969
+ const cwd = config.cwd ? resolve9(getConfigDir(), config.cwd) : void 0;
11970
+ if (config.pre) runPreCommands(config.pre, cwd);
11971
+ const resolved = resolveParams(config.params, args);
11972
+ spawnRunCommand(
11973
+ buildCommand(config.command, config.args ?? [], resolved),
11974
+ config.env,
11975
+ cwd
11976
+ );
11977
+ }
11864
11978
  function run3(name, args) {
11865
11979
  if (!name) {
11866
11980
  console.error("error: missing required argument 'name'");
11867
11981
  console.error(formatConfiguredCommands());
11868
11982
  process.exit(1);
11869
11983
  }
11870
- const runConfig = findRunConfig(name);
11871
- const resolvedCwd = runConfig.cwd ? resolve5(getConfigDir(), runConfig.cwd) : void 0;
11872
- if (runConfig.pre) runPreCommands(runConfig.pre, resolvedCwd);
11873
- const resolved = resolveParams(runConfig.params, args);
11874
- spawnRunCommand(
11875
- buildCommand(runConfig.command, runConfig.args ?? [], resolved),
11876
- runConfig.env,
11877
- resolvedCwd
11878
- );
11984
+ execRunConfig(findRunConfig(name), args);
11879
11985
  }
11880
11986
 
11881
11987
  // src/commands/run/add.ts
11882
11988
  import { mkdirSync as mkdirSync13, writeFileSync as writeFileSync28 } from "fs";
11883
- import { join as join43 } from "path";
11884
- function findAddIndex() {
11885
- const addIndex = process.argv.indexOf("add");
11886
- if (addIndex === -1 || addIndex + 2 >= process.argv.length) return -1;
11887
- return addIndex;
11888
- }
11989
+ import { join as join44 } from "path";
11990
+
11991
+ // src/commands/run/extractOption.ts
11889
11992
  function extractOption(args, flag) {
11890
11993
  const index = args.indexOf(flag);
11891
11994
  if (index === -1) return { value: void 0, remaining: args };
@@ -11894,6 +11997,13 @@ function extractOption(args, flag) {
11894
11997
  remaining: [...args.slice(0, index), ...args.slice(index + 2)]
11895
11998
  };
11896
11999
  }
12000
+
12001
+ // src/commands/run/add.ts
12002
+ function findAddIndex() {
12003
+ const addIndex = process.argv.indexOf("add");
12004
+ if (addIndex === -1 || addIndex + 2 >= process.argv.length) return -1;
12005
+ return addIndex;
12006
+ }
11897
12007
  function extractAddArgs(addIndex) {
11898
12008
  const rawArgs = process.argv.slice(addIndex + 3);
11899
12009
  const { value: cwd, remaining: args } = extractOption(rawArgs, "--cwd");
@@ -11937,7 +12047,7 @@ function saveNewRunConfig(name, command, args, cwd) {
11937
12047
  saveConfig(config);
11938
12048
  }
11939
12049
  function createCommandFile(name) {
11940
- const dir = join43(".claude", "commands");
12050
+ const dir = join44(".claude", "commands");
11941
12051
  mkdirSync13(dir, { recursive: true });
11942
12052
  const content = `---
11943
12053
  description: Run ${name}
@@ -11945,7 +12055,7 @@ description: Run ${name}
11945
12055
 
11946
12056
  Run \`assist run ${name} $ARGUMENTS 2>&1\`.
11947
12057
  `;
11948
- const filePath = join43(dir, `${name}.md`);
12058
+ const filePath = join44(dir, `${name}.md`);
11949
12059
  writeFileSync28(filePath, content);
11950
12060
  console.log(`Created command file: ${filePath}`);
11951
12061
  }
@@ -11958,9 +12068,49 @@ function add3() {
11958
12068
  );
11959
12069
  }
11960
12070
 
12071
+ // src/commands/run/link.ts
12072
+ function findLinkIndex() {
12073
+ const idx = process.argv.indexOf("link");
12074
+ if (idx === -1 || idx + 1 >= process.argv.length) return -1;
12075
+ return idx;
12076
+ }
12077
+ function parseLinkArgs() {
12078
+ const idx = findLinkIndex();
12079
+ if (idx === -1) return null;
12080
+ const path50 = process.argv[idx + 1];
12081
+ const rest = process.argv.slice(idx + 2);
12082
+ const { value: prefix2 } = extractOption(rest, "--prefix");
12083
+ if (!prefix2) return null;
12084
+ return { path: path50, prefix: prefix2 };
12085
+ }
12086
+ function hasDuplicateLink(runList, linkPath) {
12087
+ return runList.some(
12088
+ (r) => typeof r === "object" && r !== null && "link" in r && r.link === linkPath
12089
+ );
12090
+ }
12091
+ function link2() {
12092
+ const parsed = parseLinkArgs();
12093
+ if (!parsed) {
12094
+ console.error("Usage: assist run link <path> --prefix <prefix>");
12095
+ process.exit(1);
12096
+ }
12097
+ const config = loadProjectConfig();
12098
+ if (!config.run) config.run = [];
12099
+ const runList = config.run;
12100
+ if (hasDuplicateLink(runList, parsed.path)) {
12101
+ console.error(`Link to "${parsed.path}" already exists`);
12102
+ process.exit(1);
12103
+ }
12104
+ runList.push({ link: parsed.path, prefix: parsed.prefix });
12105
+ saveConfig(config);
12106
+ console.log(
12107
+ `Linked run configurations from: ${parsed.path} (prefix: ${parsed.prefix})`
12108
+ );
12109
+ }
12110
+
11961
12111
  // src/commands/run/remove.ts
11962
- import { existsSync as existsSync40, unlinkSync as unlinkSync11 } from "fs";
11963
- import { join as join44 } from "path";
12112
+ import { existsSync as existsSync41, unlinkSync as unlinkSync11 } from "fs";
12113
+ import { join as join45 } from "path";
11964
12114
  function findRemoveIndex() {
11965
12115
  const idx = process.argv.indexOf("remove");
11966
12116
  if (idx === -1 || idx + 1 >= process.argv.length) return -1;
@@ -11975,8 +12125,8 @@ function parseRemoveName() {
11975
12125
  return process.argv[idx + 1];
11976
12126
  }
11977
12127
  function deleteCommandFile(name) {
11978
- const filePath = join44(".claude", "commands", `${name}.md`);
11979
- if (existsSync40(filePath)) {
12128
+ const filePath = join45(".claude", "commands", `${name}.md`);
12129
+ if (existsSync41(filePath)) {
11980
12130
  unlinkSync11(filePath);
11981
12131
  console.log(`Deleted command file: ${filePath}`);
11982
12132
  }
@@ -11998,7 +12148,7 @@ function remove() {
11998
12148
  // src/commands/run/registerRun.ts
11999
12149
  function registerRun(program2) {
12000
12150
  const runCommand = program2.command("run").description("Run a configured command from assist.yml").argument("[name]", "Name of the configured command").argument("[args...]", "Arguments to pass to the command").allowUnknownOption().addHelpText("after", () => formatConfiguredCommands()).action((name, args) => run3(name, args));
12001
- runCommand.command("list").description("List configured run commands").action(listRunConfigs);
12151
+ runCommand.command("list").description("List configured run commands").option("-v, --verbose", "Show full command details").action((opts) => listRunConfigs(!!opts.verbose));
12002
12152
  runCommand.command("add").description("Add a new run configuration to assist.yml").argument("<name>", "Name for the run configuration").argument("<command>", "Command to execute").argument("[args...]", "Static args to pass to the command").option(
12003
12153
  "--cwd <dir>",
12004
12154
  "Working directory (resolved relative to the config file)"
@@ -12006,14 +12156,15 @@ function registerRun(program2) {
12006
12156
  "after",
12007
12157
  '\nPositional params can be added to the config manually:\n params:\n - name: env # assist run deploy prod \u2192 appends "prod"\n required: true\n - name: tag\n default: latest'
12008
12158
  ).allowUnknownOption().allowExcessArguments().action(() => add3());
12159
+ runCommand.command("link").description("Link run configurations from another project's assist.yml").argument("<path>", "Relative path to the linked project").requiredOption("--prefix <prefix>", "Namespace prefix for linked commands").allowUnknownOption().action(() => link2());
12009
12160
  runCommand.command("remove").description("Remove a run configuration from assist.yml").argument("<name>", "Name of the run configuration to remove").action(() => remove());
12010
12161
  }
12011
12162
 
12012
12163
  // src/commands/screenshot/index.ts
12013
12164
  import { execSync as execSync41 } from "child_process";
12014
- import { existsSync as existsSync41, mkdirSync as mkdirSync14, unlinkSync as unlinkSync12, writeFileSync as writeFileSync29 } from "fs";
12165
+ import { existsSync as existsSync42, mkdirSync as mkdirSync14, unlinkSync as unlinkSync12, writeFileSync as writeFileSync29 } from "fs";
12015
12166
  import { tmpdir as tmpdir6 } from "os";
12016
- import { join as join45, resolve as resolve6 } from "path";
12167
+ import { join as join46, resolve as resolve10 } from "path";
12017
12168
  import chalk132 from "chalk";
12018
12169
 
12019
12170
  // src/commands/screenshot/captureWindowPs1.ts
@@ -12143,14 +12294,14 @@ Write-Output $OutputPath
12143
12294
 
12144
12295
  // src/commands/screenshot/index.ts
12145
12296
  function buildOutputPath(outputDir, processName) {
12146
- if (!existsSync41(outputDir)) {
12297
+ if (!existsSync42(outputDir)) {
12147
12298
  mkdirSync14(outputDir, { recursive: true });
12148
12299
  }
12149
12300
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
12150
- return resolve6(outputDir, `${processName}-${timestamp}.png`);
12301
+ return resolve10(outputDir, `${processName}-${timestamp}.png`);
12151
12302
  }
12152
12303
  function runPowerShellScript(processName, outputPath) {
12153
- const scriptPath = join45(tmpdir6(), `assist-screenshot-${Date.now()}.ps1`);
12304
+ const scriptPath = join46(tmpdir6(), `assist-screenshot-${Date.now()}.ps1`);
12154
12305
  writeFileSync29(scriptPath, captureWindowPs1, "utf-8");
12155
12306
  try {
12156
12307
  execSync41(
@@ -12163,7 +12314,7 @@ function runPowerShellScript(processName, outputPath) {
12163
12314
  }
12164
12315
  function screenshot(processName) {
12165
12316
  const config = loadConfig();
12166
- const outputDir = resolve6(config.screenshot.outputDir);
12317
+ const outputDir = resolve10(config.screenshot.outputDir);
12167
12318
  const outputPath = buildOutputPath(outputDir, processName);
12168
12319
  console.log(chalk132.gray(`Capturing window for process "${processName}" ...`));
12169
12320
  try {