@staff0rd/assist 0.120.0 → 0.121.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.120.0",
9
+ version: "0.121.0",
10
10
  type: "module",
11
11
  main: "dist/index.js",
12
12
  bin: {
@@ -83,17 +83,17 @@ import { execSync } from "child_process";
83
83
  // src/shared/loadConfig.ts
84
84
  import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync } from "fs";
85
85
  import { homedir } from "os";
86
- import { basename, join } from "path";
86
+ import { basename, dirname, join } from "path";
87
87
  import chalk from "chalk";
88
88
  import { stringify as stringifyYaml } from "yaml";
89
89
 
90
90
  // src/shared/loadRawYaml.ts
91
91
  import { existsSync, readFileSync } from "fs";
92
92
  import { parse as parseYaml } from "yaml";
93
- function loadRawYaml(path42) {
94
- if (!existsSync(path42)) return {};
93
+ function loadRawYaml(path44) {
94
+ if (!existsSync(path44)) return {};
95
95
  try {
96
- const content = readFileSync(path42, "utf-8");
96
+ const content = readFileSync(path44, "utf-8");
97
97
  return parseYaml(content) || {};
98
98
  } catch {
99
99
  return {};
@@ -114,7 +114,8 @@ var runConfigSchema = z.strictObject({
114
114
  args: z.array(z.string()).optional(),
115
115
  params: z.array(runParamSchema).optional(),
116
116
  env: z.record(z.string(), z.string()).optional(),
117
- filter: z.string().optional()
117
+ filter: z.string().optional(),
118
+ pre: z.array(z.string()).optional()
118
119
  });
119
120
  var transcriptConfigSchema = z.strictObject({
120
121
  vttDir: z.string(),
@@ -192,11 +193,20 @@ var assistConfigSchema = z.strictObject({
192
193
  });
193
194
 
194
195
  // src/shared/loadConfig.ts
195
- function getConfigPath() {
196
- const claudeConfigPath = join(process.cwd(), ".claude", "assist.yml");
197
- if (existsSync2(claudeConfigPath)) {
198
- return claudeConfigPath;
196
+ function findConfigUp(startDir) {
197
+ let current = startDir;
198
+ while (current !== dirname(current)) {
199
+ const claudePath = join(current, ".claude", "assist.yml");
200
+ if (existsSync2(claudePath)) return claudePath;
201
+ const rootPath = join(current, "assist.yml");
202
+ if (existsSync2(rootPath)) return rootPath;
203
+ current = dirname(current);
199
204
  }
205
+ return null;
206
+ }
207
+ function getConfigPath() {
208
+ const found = findConfigUp(process.cwd());
209
+ if (found) return found;
200
210
  return join(process.cwd(), "assist.yml");
201
211
  }
202
212
  function getGlobalConfigPath() {
@@ -342,9 +352,9 @@ function isTraversable(value) {
342
352
  function stepInto(current, key) {
343
353
  return isTraversable(current) ? current[key] : void 0;
344
354
  }
345
- function getNestedValue(obj, path42) {
355
+ function getNestedValue(obj, path44) {
346
356
  let current = obj;
347
- for (const key of path42.split(".")) current = stepInto(current, key);
357
+ for (const key of path44.split(".")) current = stepInto(current, key);
348
358
  return current;
349
359
  }
350
360
 
@@ -385,8 +395,8 @@ function stepIntoNested(container, key, nextKey) {
385
395
  }
386
396
  return ensureObject(container, resolved);
387
397
  }
388
- function setNestedValue(obj, path42, value) {
389
- const keys = path42.split(".");
398
+ function setNestedValue(obj, path44, value) {
399
+ const keys = path44.split(".");
390
400
  const result = { ...obj };
391
401
  let current = result;
392
402
  for (let i = 0; i < keys.length - 1; i++) {
@@ -693,7 +703,7 @@ import chalk13 from "chalk";
693
703
  // src/commands/lint/init.ts
694
704
  import { execSync as execSync4 } from "child_process";
695
705
  import { existsSync as existsSync7, readFileSync as readFileSync6, writeFileSync as writeFileSync5 } from "fs";
696
- import { dirname as dirname5, join as join4 } from "path";
706
+ import { dirname as dirname6, join as join4 } from "path";
697
707
  import { fileURLToPath } from "url";
698
708
  import chalk12 from "chalk";
699
709
 
@@ -826,7 +836,7 @@ function printDiff(oldContent, newContent) {
826
836
  }
827
837
 
828
838
  // src/commands/lint/init.ts
829
- var __dirname2 = dirname5(fileURLToPath(import.meta.url));
839
+ var __dirname2 = dirname6(fileURLToPath(import.meta.url));
830
840
  async function init() {
831
841
  removeEslint();
832
842
  const biomeConfigPath = "biome.json";
@@ -1977,11 +1987,11 @@ import enquirer3 from "enquirer";
1977
1987
 
1978
1988
  // src/commands/deploy/init/updateWorkflow.ts
1979
1989
  import { existsSync as existsSync10, mkdirSync as mkdirSync3, readFileSync as readFileSync8, writeFileSync as writeFileSync9 } from "fs";
1980
- import { dirname as dirname11, join as join7 } from "path";
1990
+ import { dirname as dirname12, join as join7 } from "path";
1981
1991
  import { fileURLToPath as fileURLToPath2 } from "url";
1982
1992
  import chalk23 from "chalk";
1983
1993
  var WORKFLOW_PATH = ".github/workflows/build.yml";
1984
- var __dirname3 = dirname11(fileURLToPath2(import.meta.url));
1994
+ var __dirname3 = dirname12(fileURLToPath2(import.meta.url));
1985
1995
  function getExistingSiteId() {
1986
1996
  if (!existsSync10(WORKFLOW_PATH)) {
1987
1997
  return null;
@@ -2533,7 +2543,7 @@ import { readFileSync as readFileSync12 } from "fs";
2533
2543
  import {
2534
2544
  createServer
2535
2545
  } from "http";
2536
- import { dirname as dirname12, join as join10 } from "path";
2546
+ import { dirname as dirname13, join as join10 } from "path";
2537
2547
  import { fileURLToPath as fileURLToPath3 } from "url";
2538
2548
  import chalk32 from "chalk";
2539
2549
  function respondJson(res, status2, data) {
@@ -2541,7 +2551,7 @@ function respondJson(res, status2, data) {
2541
2551
  res.end(JSON.stringify(data));
2542
2552
  }
2543
2553
  function createBundleHandler(importMetaUrl, bundlePath) {
2544
- const dir = dirname12(fileURLToPath3(importMetaUrl));
2554
+ const dir = dirname13(fileURLToPath3(importMetaUrl));
2545
2555
  let cache;
2546
2556
  return (_req, res) => {
2547
2557
  if (!cache) {
@@ -2822,22 +2832,22 @@ function extractGraphqlQuery(args) {
2822
2832
 
2823
2833
  // src/shared/loadCliReads.ts
2824
2834
  import { existsSync as existsSync16, readFileSync as readFileSync13, writeFileSync as writeFileSync13 } from "fs";
2825
- import { dirname as dirname13, resolve as resolve2 } from "path";
2835
+ import { dirname as dirname14, resolve as resolve2 } from "path";
2826
2836
  import { fileURLToPath as fileURLToPath4 } from "url";
2827
2837
  var __filename2 = fileURLToPath4(import.meta.url);
2828
- var __dirname4 = dirname13(__filename2);
2838
+ var __dirname4 = dirname14(__filename2);
2829
2839
  function getCliReadsPath() {
2830
2840
  return resolve2(__dirname4, "..", "assist.cli-reads");
2831
2841
  }
2832
2842
  var cachedLines;
2833
2843
  function getCliReadsLines() {
2834
2844
  if (cachedLines) return cachedLines;
2835
- const path42 = getCliReadsPath();
2836
- if (!existsSync16(path42)) {
2845
+ const path44 = getCliReadsPath();
2846
+ if (!existsSync16(path44)) {
2837
2847
  cachedLines = [];
2838
2848
  return cachedLines;
2839
2849
  }
2840
- cachedLines = readFileSync13(path42, "utf-8").split("\n").filter((line) => line.trim() !== "");
2850
+ cachedLines = readFileSync13(path44, "utf-8").split("\n").filter((line) => line.trim() !== "");
2841
2851
  return cachedLines;
2842
2852
  }
2843
2853
  function loadCliReads() {
@@ -3043,10 +3053,10 @@ import { join as join12 } from "path";
3043
3053
 
3044
3054
  // src/shared/getInstallDir.ts
3045
3055
  import { execSync as execSync13 } from "child_process";
3046
- import { dirname as dirname14, resolve as resolve4 } from "path";
3056
+ import { dirname as dirname15, resolve as resolve4 } from "path";
3047
3057
  import { fileURLToPath as fileURLToPath5 } from "url";
3048
3058
  var __filename3 = fileURLToPath5(import.meta.url);
3049
- var __dirname5 = dirname14(__filename3);
3059
+ var __dirname5 = dirname15(__filename3);
3050
3060
  function getInstallDir() {
3051
3061
  return resolve4(__dirname5, "..");
3052
3062
  }
@@ -3189,14 +3199,14 @@ function showProgress(p, label2) {
3189
3199
  const pct = Math.round(p.done / p.total * 100);
3190
3200
  process.stderr.write(`\r\x1B[K[${pct}%] Scanning ${label2}...`);
3191
3201
  }
3192
- async function resolveCommand(cli, path42, description, depth, p) {
3193
- showProgress(p, path42.join(" "));
3194
- const subHelp = await runHelp([cli, ...path42]);
3202
+ async function resolveCommand(cli, path44, description, depth, p) {
3203
+ showProgress(p, path44.join(" "));
3204
+ const subHelp = await runHelp([cli, ...path44]);
3195
3205
  if (!subHelp || !hasSubcommands(subHelp)) {
3196
- return [{ path: path42, description }];
3206
+ return [{ path: path44, description }];
3197
3207
  }
3198
- const children = await discoverAt(cli, path42, depth + 1, p);
3199
- return children.length > 0 ? children : [{ path: path42, description }];
3208
+ const children = await discoverAt(cli, path44, depth + 1, p);
3209
+ return children.length > 0 ? children : [{ path: path44, description }];
3200
3210
  }
3201
3211
  async function discoverAt(cli, parentPath, depth, p) {
3202
3212
  if (depth > SAFETY_DEPTH) return [];
@@ -3344,9 +3354,9 @@ function logPath(cli) {
3344
3354
  return join12(homedir4(), ".assist", `cli-discover-${safeName}.log`);
3345
3355
  }
3346
3356
  function readCache(cli) {
3347
- const path42 = logPath(cli);
3348
- if (!existsSync18(path42)) return void 0;
3349
- return readFileSync15(path42, "utf-8");
3357
+ const path44 = logPath(cli);
3358
+ if (!existsSync18(path44)) return void 0;
3359
+ return readFileSync15(path44, "utf-8");
3350
3360
  }
3351
3361
  function writeCache(cli, output) {
3352
3362
  const dir = join12(homedir4(), ".assist");
@@ -4428,234 +4438,88 @@ function registerDevlog(program2) {
4428
4438
  ).option("--all", "Show all non-archived repos regardless of push date").action(repos);
4429
4439
  }
4430
4440
 
4431
- // src/commands/jira/acceptanceCriteria.ts
4432
- import chalk49 from "chalk";
4433
-
4434
- // src/commands/jira/adfToText.ts
4435
- function renderInline(node) {
4436
- const text = node.text ?? "";
4437
- if (node.marks?.some((m) => m.type === "code")) return `\`${text}\``;
4438
- return text;
4439
- }
4440
- function renderChildren(node, indent) {
4441
- return renderNodes(node.content ?? [], indent);
4442
- }
4443
- function renderOrderedList(node, indent) {
4444
- let counter = 0;
4445
- return (node.content ?? []).map((item) => {
4446
- counter++;
4447
- return renderListItem(item, indent, `${counter}.`);
4448
- }).join("\n");
4449
- }
4450
- function renderBulletList(node, indent) {
4451
- return (node.content ?? []).map((item) => renderListItem(item, indent, "-")).join("\n");
4452
- }
4453
- function renderHeading(node, indent) {
4454
- const level = node.attrs?.level ?? 1;
4455
- return `${"#".repeat(level)} ${renderChildren(node, indent)}`;
4456
- }
4457
- var renderers = {
4458
- text: (node) => renderInline(node),
4459
- paragraph: renderChildren,
4460
- orderedList: renderOrderedList,
4461
- bulletList: renderBulletList,
4462
- listItem: (node, indent) => renderListItem(node, indent, "-"),
4463
- heading: renderHeading,
4464
- doc: renderChildren
4465
- };
4466
- function renderNode(node, indent) {
4467
- const renderer = renderers[node.type];
4468
- if (renderer) return renderer(node, indent);
4469
- return node.content ? renderChildren(node, indent) : "";
4470
- }
4471
- function renderNodes(nodes, indent) {
4472
- return nodes.map((node) => renderNode(node, indent)).join("");
4473
- }
4474
- function isListNode(node) {
4475
- return node.type === "orderedList" || node.type === "bulletList";
4476
- }
4477
- function renderListChild(child, indent, pad, marker, isFirst) {
4478
- if (isListNode(child)) return renderNodes([child], indent + 1);
4479
- if (child.type !== "paragraph") return renderNode(child, indent);
4480
- const text = renderChildren(child, indent);
4481
- return isFirst ? `${pad}${marker} ${text}` : `${pad} ${text}`;
4482
- }
4483
- function renderListItem(node, indent, marker) {
4484
- const pad = " ".repeat(indent);
4485
- return (node.content ?? []).map((child, i) => renderListChild(child, indent, pad, marker, i === 0)).join("\n");
4486
- }
4487
- function adfToText(doc) {
4488
- return renderNodes([doc], 0);
4489
- }
4490
-
4491
- // src/commands/jira/fetchIssue.ts
4492
- import { execSync as execSync20 } from "child_process";
4441
+ // src/commands/dotnet/checkBuildLocks.ts
4442
+ import { closeSync, openSync, readdirSync as readdirSync2 } from "fs";
4443
+ import { join as join16 } from "path";
4493
4444
  import chalk48 from "chalk";
4494
- function fetchIssue(issueKey, fields) {
4495
- let result;
4496
- try {
4497
- result = execSync20(
4498
- `acli jira workitem view ${issueKey} -f ${fields} --json`,
4499
- { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
4500
- );
4501
- } catch (error) {
4502
- if (error instanceof Error && "stderr" in error) {
4503
- const stderr = error.stderr;
4504
- if (stderr.includes("unauthorized")) {
4505
- console.error(
4506
- chalk48.red("Jira authentication expired."),
4507
- "Run",
4508
- chalk48.cyan("assist jira auth"),
4509
- "to re-authenticate."
4510
- );
4511
- process.exit(1);
4512
- }
4445
+
4446
+ // src/shared/findRepoRoot.ts
4447
+ import { existsSync as existsSync20 } from "fs";
4448
+ import path21 from "path";
4449
+ function findRepoRoot(dir) {
4450
+ let current = dir;
4451
+ while (current !== path21.dirname(current)) {
4452
+ if (existsSync20(path21.join(current, ".git"))) {
4453
+ return current;
4513
4454
  }
4514
- console.error(chalk48.red(`Failed to fetch ${issueKey}.`));
4515
- process.exit(1);
4455
+ current = path21.dirname(current);
4516
4456
  }
4517
- return JSON.parse(result);
4457
+ return null;
4518
4458
  }
4519
4459
 
4520
- // src/commands/jira/acceptanceCriteria.ts
4521
- var DEFAULT_AC_FIELD = "customfield_11937";
4522
- function acceptanceCriteria(issueKey) {
4523
- const config = loadConfig();
4524
- const field = config.jira?.acField ?? DEFAULT_AC_FIELD;
4525
- const parsed = fetchIssue(issueKey, field);
4526
- const acValue = parsed?.fields?.[field];
4527
- if (!acValue) {
4528
- console.log(chalk49.yellow(`No acceptance criteria found on ${issueKey}.`));
4529
- return;
4530
- }
4531
- if (typeof acValue === "string") {
4532
- console.log(acValue);
4533
- return;
4534
- }
4535
- if (acValue.type === "doc") {
4536
- console.log(adfToText(acValue));
4537
- return;
4460
+ // src/commands/dotnet/checkBuildLocks.ts
4461
+ var SKIP_DIRS = /* @__PURE__ */ new Set(["node_modules", ".git", "packages"]);
4462
+ function isLockedDll(debugDir) {
4463
+ let files;
4464
+ try {
4465
+ files = readdirSync2(debugDir, { recursive: true });
4466
+ } catch {
4467
+ return null;
4538
4468
  }
4539
- console.log(JSON.stringify(acValue, null, 2));
4540
- }
4541
-
4542
- // src/commands/jira/jiraAuth.ts
4543
- import { execSync as execSync21 } from "child_process";
4544
- import Enquirer from "enquirer";
4545
-
4546
- // src/shared/loadJson.ts
4547
- import { existsSync as existsSync20, mkdirSync as mkdirSync5, readFileSync as readFileSync18, writeFileSync as writeFileSync17 } from "fs";
4548
- import { homedir as homedir6 } from "os";
4549
- import { join as join16 } from "path";
4550
- function getStoreDir() {
4551
- return join16(homedir6(), ".assist");
4552
- }
4553
- function getStorePath(filename) {
4554
- return join16(getStoreDir(), filename);
4555
- }
4556
- function loadJson(filename) {
4557
- const path42 = getStorePath(filename);
4558
- if (existsSync20(path42)) {
4469
+ for (const file of files) {
4470
+ if (!file.toLowerCase().endsWith(".dll")) continue;
4471
+ const dllPath = join16(debugDir, file);
4559
4472
  try {
4560
- return JSON.parse(readFileSync18(path42, "utf-8"));
4473
+ const fd = openSync(dllPath, "r+");
4474
+ closeSync(fd);
4561
4475
  } catch {
4562
- return {};
4476
+ return dllPath;
4563
4477
  }
4564
4478
  }
4565
- return {};
4566
- }
4567
- function saveJson(filename, data) {
4568
- const dir = getStoreDir();
4569
- if (!existsSync20(dir)) {
4570
- mkdirSync5(dir, { recursive: true });
4571
- }
4572
- writeFileSync17(getStorePath(filename), JSON.stringify(data, null, 2));
4573
- }
4574
-
4575
- // src/commands/jira/jiraAuth.ts
4576
- var CONFIG_FILE = "jira.json";
4577
- async function promptCredentials(config) {
4578
- const { Input: Input2, Password } = Enquirer;
4579
- const site = await new Input2({
4580
- name: "site",
4581
- message: "Jira site (e.g., mycompany.atlassian.net):",
4582
- initial: config.site
4583
- }).run();
4584
- const email = await new Input2({
4585
- name: "email",
4586
- message: "Email:",
4587
- initial: config.email
4588
- }).run();
4589
- const token = await new Password({
4590
- name: "token",
4591
- message: "API token (https://id.atlassian.com/manage-profile/security/api-tokens):"
4592
- }).run();
4593
- return { site, email, token };
4479
+ return null;
4594
4480
  }
4595
- async function jiraAuth() {
4596
- const config = loadJson(CONFIG_FILE);
4481
+ function findFirstLockedDll(dir) {
4482
+ let entries;
4597
4483
  try {
4598
- const { site, email, token } = await promptCredentials(config);
4599
- if (!site || !email || !token) {
4600
- console.error("All fields are required.");
4601
- process.exit(1);
4602
- }
4603
- execSync21(`acli jira auth login --site ${site} --email "${email}" --token`, {
4604
- encoding: "utf-8",
4605
- input: token,
4606
- stdio: ["pipe", "inherit", "inherit"]
4607
- });
4608
- saveJson(CONFIG_FILE, { site, email });
4609
- console.log("Successfully authenticated with Jira.");
4610
- } catch (error) {
4611
- if (error instanceof Error) {
4612
- console.error("Error authenticating with Jira:", error.message);
4613
- }
4614
- process.exit(1);
4484
+ entries = readdirSync2(dir);
4485
+ } catch {
4486
+ return null;
4615
4487
  }
4616
- }
4617
-
4618
- // src/commands/jira/viewIssue.ts
4619
- import chalk50 from "chalk";
4620
- function viewIssue(issueKey) {
4621
- const parsed = fetchIssue(issueKey, "summary,description");
4622
- const fields = parsed?.fields;
4623
- const summary = fields?.summary;
4624
- const description = fields?.description;
4625
- if (summary) {
4626
- console.log(chalk50.bold(summary));
4488
+ if (entries.includes("bin")) {
4489
+ const locked = isLockedDll(join16(dir, "bin", "Debug"));
4490
+ if (locked) return locked;
4627
4491
  }
4628
- if (description) {
4629
- if (summary) console.log();
4630
- if (typeof description === "string") {
4631
- console.log(description);
4632
- } else if (description.type === "doc") {
4633
- console.log(adfToText(description));
4634
- } else {
4635
- console.log(JSON.stringify(description, null, 2));
4636
- }
4492
+ for (const entry of entries) {
4493
+ if (SKIP_DIRS.has(entry) || entry === "bin" || entry.startsWith("."))
4494
+ continue;
4495
+ const found = findFirstLockedDll(join16(dir, entry));
4496
+ if (found) return found;
4637
4497
  }
4638
- if (!summary && !description) {
4639
- console.log(
4640
- chalk50.yellow(`No summary or description found on ${issueKey}.`)
4498
+ return null;
4499
+ }
4500
+ function getSearchRoot() {
4501
+ return findRepoRoot(process.cwd()) ?? process.cwd();
4502
+ }
4503
+ function checkBuildLocks(startDir) {
4504
+ const locked = findFirstLockedDll(startDir ?? getSearchRoot());
4505
+ if (locked) {
4506
+ console.error(
4507
+ chalk48.red("Build output locked (is VS debugging?): ") + locked
4641
4508
  );
4509
+ process.exit(1);
4642
4510
  }
4643
4511
  }
4644
-
4645
- // src/commands/registerJira.ts
4646
- function registerJira(program2) {
4647
- const jiraCommand = program2.command("jira").description("Jira utilities");
4648
- jiraCommand.command("auth").description("Authenticate with Jira via API token").action(() => jiraAuth());
4649
- jiraCommand.command("ac <issue-key>").description("Print acceptance criteria for a Jira issue").action((issueKey) => acceptanceCriteria(issueKey));
4650
- jiraCommand.command("view <issue-key>").description("Print the title and description of a Jira issue").action((issueKey) => viewIssue(issueKey));
4512
+ async function checkBuildLocksCommand() {
4513
+ checkBuildLocks();
4514
+ console.log(chalk48.green("No build locks detected"));
4651
4515
  }
4652
4516
 
4653
- // src/commands/netframework/buildTree.ts
4654
- import { readFileSync as readFileSync19 } from "fs";
4655
- import path21 from "path";
4517
+ // src/commands/dotnet/buildTree.ts
4518
+ import { readFileSync as readFileSync18 } from "fs";
4519
+ import path22 from "path";
4656
4520
  var PROJECT_REF_RE = /<ProjectReference\s+Include="([^"]+)"/g;
4657
4521
  function getProjectRefs(csprojPath) {
4658
- const content = readFileSync19(csprojPath, "utf-8");
4522
+ const content = readFileSync18(csprojPath, "utf-8");
4659
4523
  const refs = [];
4660
4524
  for (const match of content.matchAll(PROJECT_REF_RE)) {
4661
4525
  refs.push(match[1].replace(/\\/g, "/"));
@@ -4663,16 +4527,16 @@ function getProjectRefs(csprojPath) {
4663
4527
  return refs;
4664
4528
  }
4665
4529
  function buildTree(csprojPath, repoRoot, visited = /* @__PURE__ */ new Set()) {
4666
- const abs = path21.resolve(csprojPath);
4667
- const rel = path21.relative(repoRoot, abs);
4530
+ const abs = path22.resolve(csprojPath);
4531
+ const rel = path22.relative(repoRoot, abs);
4668
4532
  const node = { path: abs, relativePath: rel, children: [] };
4669
4533
  if (visited.has(abs)) return node;
4670
4534
  visited.add(abs);
4671
- const dir = path21.dirname(abs);
4535
+ const dir = path22.dirname(abs);
4672
4536
  for (const ref of getProjectRefs(abs)) {
4673
- const childAbs = path21.resolve(dir, ref);
4537
+ const childAbs = path22.resolve(dir, ref);
4674
4538
  try {
4675
- readFileSync19(childAbs);
4539
+ readFileSync18(childAbs);
4676
4540
  node.children.push(buildTree(childAbs, repoRoot, visited));
4677
4541
  } catch {
4678
4542
  node.children.push({
@@ -4696,22 +4560,22 @@ function collectAllDeps(node) {
4696
4560
  return result;
4697
4561
  }
4698
4562
 
4699
- // src/commands/netframework/findContainingSolutions.ts
4700
- import { readdirSync as readdirSync2, readFileSync as readFileSync20, statSync } from "fs";
4701
- import path22 from "path";
4563
+ // src/commands/dotnet/findContainingSolutions.ts
4564
+ import { readdirSync as readdirSync3, readFileSync as readFileSync19, statSync } from "fs";
4565
+ import path23 from "path";
4702
4566
  function findSlnFiles(dir, maxDepth, depth = 0) {
4703
4567
  if (depth > maxDepth) return [];
4704
4568
  const results = [];
4705
4569
  let entries;
4706
4570
  try {
4707
- entries = readdirSync2(dir);
4571
+ entries = readdirSync3(dir);
4708
4572
  } catch {
4709
4573
  return results;
4710
4574
  }
4711
4575
  for (const entry of entries) {
4712
4576
  if (entry.startsWith(".") || entry === "node_modules" || entry === "packages")
4713
4577
  continue;
4714
- const full = path22.join(dir, entry);
4578
+ const full = path23.join(dir, entry);
4715
4579
  try {
4716
4580
  const stat = statSync(full);
4717
4581
  if (stat.isFile() && entry.endsWith(".sln")) {
@@ -4725,16 +4589,16 @@ function findSlnFiles(dir, maxDepth, depth = 0) {
4725
4589
  return results;
4726
4590
  }
4727
4591
  function findContainingSolutions(csprojPath, repoRoot) {
4728
- const csprojAbs = path22.resolve(csprojPath);
4729
- const csprojBasename = path22.basename(csprojAbs);
4592
+ const csprojAbs = path23.resolve(csprojPath);
4593
+ const csprojBasename = path23.basename(csprojAbs);
4730
4594
  const slnFiles = findSlnFiles(repoRoot, 3);
4731
4595
  const matches = [];
4732
4596
  const pattern2 = new RegExp(`[\\\\"/]${escapeRegex(csprojBasename)}"`);
4733
4597
  for (const sln of slnFiles) {
4734
4598
  try {
4735
- const content = readFileSync20(sln, "utf-8");
4599
+ const content = readFileSync19(sln, "utf-8");
4736
4600
  if (pattern2.test(content)) {
4737
- matches.push(path22.relative(repoRoot, sln));
4601
+ matches.push(path23.relative(repoRoot, sln));
4738
4602
  }
4739
4603
  } catch {
4740
4604
  }
@@ -4745,31 +4609,31 @@ function escapeRegex(s) {
4745
4609
  return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
4746
4610
  }
4747
4611
 
4748
- // src/commands/netframework/printTree.ts
4749
- import chalk51 from "chalk";
4612
+ // src/commands/dotnet/printTree.ts
4613
+ import chalk49 from "chalk";
4750
4614
  function printNodes(nodes, prefix2) {
4751
4615
  for (let i = 0; i < nodes.length; i++) {
4752
4616
  const isLast = i === nodes.length - 1;
4753
4617
  const connector = isLast ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
4754
4618
  const childPrefix = isLast ? " " : "\u2502 ";
4755
4619
  const isMissing = nodes[i].relativePath.startsWith("[MISSING]");
4756
- const label2 = isMissing ? chalk51.red(nodes[i].relativePath) : nodes[i].relativePath;
4620
+ const label2 = isMissing ? chalk49.red(nodes[i].relativePath) : nodes[i].relativePath;
4757
4621
  console.log(`${prefix2}${connector}${label2}`);
4758
4622
  printNodes(nodes[i].children, prefix2 + childPrefix);
4759
4623
  }
4760
4624
  }
4761
4625
  function printTree(tree, totalCount, solutions) {
4762
- console.log(chalk51.bold("\nProject Dependency Tree"));
4763
- console.log(chalk51.cyan(tree.relativePath));
4626
+ console.log(chalk49.bold("\nProject Dependency Tree"));
4627
+ console.log(chalk49.cyan(tree.relativePath));
4764
4628
  printNodes(tree.children, "");
4765
- console.log(chalk51.dim(`
4629
+ console.log(chalk49.dim(`
4766
4630
  ${totalCount} projects total (including root)`));
4767
- console.log(chalk51.bold("\nSolution Membership"));
4631
+ console.log(chalk49.bold("\nSolution Membership"));
4768
4632
  if (solutions.length === 0) {
4769
- console.log(chalk51.yellow(" Not found in any .sln"));
4633
+ console.log(chalk49.yellow(" Not found in any .sln"));
4770
4634
  } else {
4771
4635
  for (const sln of solutions) {
4772
- console.log(` ${chalk51.green(sln)}`);
4636
+ console.log(` ${chalk49.green(sln)}`);
4773
4637
  }
4774
4638
  }
4775
4639
  console.log();
@@ -4795,41 +4659,25 @@ function printJson(tree, totalCount, solutions) {
4795
4659
  );
4796
4660
  }
4797
4661
 
4798
- // src/commands/netframework/resolveCsproj.ts
4799
- import { existsSync as existsSync22 } from "fs";
4800
- import path24 from "path";
4801
- import chalk52 from "chalk";
4802
-
4803
- // src/commands/netframework/findRepoRoot.ts
4662
+ // src/commands/dotnet/resolveCsproj.ts
4804
4663
  import { existsSync as existsSync21 } from "fs";
4805
- import path23 from "path";
4806
- function findRepoRoot(dir) {
4807
- let current = dir;
4808
- while (current !== path23.dirname(current)) {
4809
- if (existsSync21(path23.join(current, ".git"))) {
4810
- return current;
4811
- }
4812
- current = path23.dirname(current);
4813
- }
4814
- return null;
4815
- }
4816
-
4817
- // src/commands/netframework/resolveCsproj.ts
4664
+ import path24 from "path";
4665
+ import chalk50 from "chalk";
4818
4666
  function resolveCsproj(csprojPath) {
4819
4667
  const resolved = path24.resolve(csprojPath);
4820
- if (!existsSync22(resolved)) {
4821
- console.error(chalk52.red(`File not found: ${resolved}`));
4668
+ if (!existsSync21(resolved)) {
4669
+ console.error(chalk50.red(`File not found: ${resolved}`));
4822
4670
  process.exit(1);
4823
4671
  }
4824
4672
  const repoRoot = findRepoRoot(path24.dirname(resolved));
4825
4673
  if (!repoRoot) {
4826
- console.error(chalk52.red("Could not find git repository root"));
4674
+ console.error(chalk50.red("Could not find git repository root"));
4827
4675
  process.exit(1);
4828
4676
  }
4829
4677
  return { resolved, repoRoot };
4830
4678
  }
4831
4679
 
4832
- // src/commands/netframework/deps.ts
4680
+ // src/commands/dotnet/deps.ts
4833
4681
  async function deps(csprojPath, options2) {
4834
4682
  const { resolved, repoRoot } = resolveCsproj(csprojPath);
4835
4683
  const tree = buildTree(resolved, repoRoot);
@@ -4842,13 +4690,13 @@ async function deps(csprojPath, options2) {
4842
4690
  }
4843
4691
  }
4844
4692
 
4845
- // src/commands/netframework/inSln.ts
4846
- import chalk53 from "chalk";
4693
+ // src/commands/dotnet/inSln.ts
4694
+ import chalk51 from "chalk";
4847
4695
  async function inSln(csprojPath) {
4848
4696
  const { resolved, repoRoot } = resolveCsproj(csprojPath);
4849
4697
  const solutions = findContainingSolutions(resolved, repoRoot);
4850
4698
  if (solutions.length === 0) {
4851
- console.log(chalk53.yellow("Not found in any .sln file"));
4699
+ console.log(chalk51.yellow("Not found in any .sln file"));
4852
4700
  process.exit(1);
4853
4701
  }
4854
4702
  for (const sln of solutions) {
@@ -4856,20 +4704,464 @@ async function inSln(csprojPath) {
4856
4704
  }
4857
4705
  }
4858
4706
 
4859
- // src/commands/registerNetframework.ts
4860
- function registerNetframework(program2) {
4861
- const cmd = program2.command("netframework").description(".NET Framework project utilities");
4862
- cmd.command("deps").description("Show .csproj project dependency tree and solution membership").argument("<csproj>", "Path to a .csproj file").option("--json", "Output as JSON").action(deps);
4863
- cmd.command("in-sln").description("Check whether a .csproj is referenced by any .sln file").argument("<csproj>", "Path to a .csproj file").action(inSln);
4707
+ // src/commands/dotnet/inspect.ts
4708
+ import { existsSync as existsSync23 } from "fs";
4709
+ import path26 from "path";
4710
+ import chalk55 from "chalk";
4711
+
4712
+ // src/shared/formatElapsed.ts
4713
+ function formatElapsed(ms) {
4714
+ const secs = ms / 1e3;
4715
+ if (secs < 60) return `${secs.toFixed(1)}s`;
4716
+ const mins = Math.floor(secs / 60);
4717
+ const remainSecs = secs - mins * 60;
4718
+ return `${mins}m ${remainSecs.toFixed(1)}s`;
4864
4719
  }
4865
4720
 
4866
- // src/commands/news/add/index.ts
4867
- import chalk54 from "chalk";
4868
- import enquirer5 from "enquirer";
4869
- async function add2(url) {
4870
- if (!url) {
4871
- const response = await enquirer5.prompt({
4872
- type: "input",
4721
+ // src/commands/dotnet/deadCodeRules.ts
4722
+ var deadCodeRules = /* @__PURE__ */ new Set([
4723
+ "UnusedMember.Global",
4724
+ "UnusedMember.Local",
4725
+ "UnusedType.Global",
4726
+ "UnusedType.Local",
4727
+ "UnusedParameter.Global",
4728
+ "UnusedParameter.Local",
4729
+ "NotAccessedField.Global",
4730
+ "NotAccessedField.Local",
4731
+ "NotAccessedVariable.Local",
4732
+ "UnusedAutoPropertyAccessor.Global",
4733
+ "UnusedAutoPropertyAccessor.Local",
4734
+ "ClassNeverInstantiated.Global",
4735
+ "ClassNeverInstantiated.Local",
4736
+ "UnusedMethodReturnValue.Global",
4737
+ "UnusedMethodReturnValue.Local",
4738
+ "UnusedVariable.Compiler",
4739
+ "RedundantUsingDirective"
4740
+ ]);
4741
+
4742
+ // src/commands/dotnet/displayIssues.ts
4743
+ import chalk52 from "chalk";
4744
+ var SEVERITY_COLOR = {
4745
+ ERROR: chalk52.red,
4746
+ WARNING: chalk52.yellow,
4747
+ SUGGESTION: chalk52.cyan,
4748
+ HINT: chalk52.dim
4749
+ };
4750
+ function groupByFile(issues) {
4751
+ const byFile = /* @__PURE__ */ new Map();
4752
+ for (const issue of issues) {
4753
+ const existing = byFile.get(issue.file);
4754
+ if (existing) {
4755
+ existing.push(issue);
4756
+ } else {
4757
+ byFile.set(issue.file, [issue]);
4758
+ }
4759
+ }
4760
+ return byFile;
4761
+ }
4762
+ function displayIssues(issues) {
4763
+ for (const [file, fileIssues] of groupByFile(issues)) {
4764
+ console.log(chalk52.bold(file));
4765
+ for (const issue of fileIssues.sort((a, b) => a.line - b.line)) {
4766
+ const color = SEVERITY_COLOR[issue.severity] ?? chalk52.white;
4767
+ console.log(
4768
+ ` ${chalk52.dim(`${issue.line}:`)} ${color(issue.severity)} [${issue.typeId}] ${issue.message}`
4769
+ );
4770
+ }
4771
+ }
4772
+ console.log(chalk52.dim(`
4773
+ ${issues.length} issue(s) found`));
4774
+ }
4775
+
4776
+ // src/commands/dotnet/findSolution.ts
4777
+ import { readdirSync as readdirSync4 } from "fs";
4778
+ import { dirname as dirname16, join as join17 } from "path";
4779
+ import chalk53 from "chalk";
4780
+ function findSlnInDir(dir) {
4781
+ try {
4782
+ return readdirSync4(dir).filter((f) => f.endsWith(".sln")).map((f) => join17(dir, f));
4783
+ } catch {
4784
+ return [];
4785
+ }
4786
+ }
4787
+ function findSolution() {
4788
+ const repoRoot = findRepoRoot(process.cwd());
4789
+ const ceiling = repoRoot ?? process.cwd();
4790
+ let current = process.cwd();
4791
+ while (true) {
4792
+ const slnFiles = findSlnInDir(current);
4793
+ if (slnFiles.length === 1) return slnFiles[0];
4794
+ if (slnFiles.length > 1) {
4795
+ console.error(chalk53.red(`Multiple .sln files found in ${current}:`));
4796
+ for (const f of slnFiles) console.error(` ${f}`);
4797
+ console.error(
4798
+ chalk53.yellow("Specify which one: assist dotnet inspect <sln>")
4799
+ );
4800
+ process.exit(1);
4801
+ }
4802
+ if (current === ceiling) break;
4803
+ current = dirname16(current);
4804
+ }
4805
+ console.error(chalk53.red("No .sln file found between cwd and repo root"));
4806
+ process.exit(1);
4807
+ }
4808
+
4809
+ // src/commands/dotnet/getChangedCsFiles.ts
4810
+ import { execSync as execSync20 } from "child_process";
4811
+ function getChangedCsFiles(ref) {
4812
+ const cmd = ref ? `git diff --name-only ${ref}~1 ${ref}` : "git diff --name-only HEAD";
4813
+ const output = execSync20(cmd, { encoding: "utf-8" }).trim();
4814
+ if (output === "") return [];
4815
+ return output.split("\n").filter((f) => f.toLowerCase().endsWith(".cs"));
4816
+ }
4817
+
4818
+ // src/commands/dotnet/parseInspectReport.ts
4819
+ var LEVEL_TO_SEVERITY = {
4820
+ error: "ERROR",
4821
+ warning: "WARNING",
4822
+ note: "SUGGESTION"
4823
+ };
4824
+ function parseInspectReport(json) {
4825
+ const sarif = JSON.parse(json);
4826
+ const results = sarif.runs?.[0]?.results;
4827
+ if (!Array.isArray(results)) return [];
4828
+ return results.map((r) => ({
4829
+ typeId: r.ruleId,
4830
+ file: r.locations?.[0]?.physicalLocation?.artifactLocation?.uri ?? "",
4831
+ line: r.locations?.[0]?.physicalLocation?.region?.startLine ?? 0,
4832
+ message: r.message?.text ?? "",
4833
+ severity: LEVEL_TO_SEVERITY[r.level] ?? "WARNING"
4834
+ }));
4835
+ }
4836
+
4837
+ // src/commands/dotnet/runInspectCode.ts
4838
+ import { execSync as execSync21 } from "child_process";
4839
+ import { existsSync as existsSync22, readFileSync as readFileSync20, unlinkSync as unlinkSync3 } from "fs";
4840
+ import { tmpdir as tmpdir2 } from "os";
4841
+ import path25 from "path";
4842
+ import chalk54 from "chalk";
4843
+ function assertJbInstalled() {
4844
+ try {
4845
+ execSync21("jb inspectcode --version", { stdio: "pipe" });
4846
+ } catch {
4847
+ console.error(chalk54.red("jb is not installed. Install with:"));
4848
+ console.error(
4849
+ chalk54.yellow(" dotnet tool install -g JetBrains.ReSharper.GlobalTools")
4850
+ );
4851
+ process.exit(1);
4852
+ }
4853
+ }
4854
+ function runInspectCode(slnPath, include, swea) {
4855
+ const reportPath = path25.join(tmpdir2(), `inspect-${Date.now()}.xml`);
4856
+ const sweaFlag = swea ? " --swea" : "";
4857
+ try {
4858
+ execSync21(
4859
+ `jb inspectcode "${slnPath}" -o="${reportPath}" --include="${include}"${sweaFlag} --verbosity=OFF`,
4860
+ { stdio: "pipe" }
4861
+ );
4862
+ } catch (err) {
4863
+ if (err && typeof err === "object" && "stderr" in err) {
4864
+ process.stderr.write(err.stderr);
4865
+ }
4866
+ console.error(chalk54.red("jb inspectcode failed"));
4867
+ process.exit(1);
4868
+ }
4869
+ if (!existsSync22(reportPath)) {
4870
+ console.error(chalk54.red("Report file not generated"));
4871
+ process.exit(1);
4872
+ }
4873
+ const xml = readFileSync20(reportPath, "utf-8");
4874
+ unlinkSync3(reportPath);
4875
+ return xml;
4876
+ }
4877
+
4878
+ // src/commands/dotnet/inspect.ts
4879
+ function resolveSolution(sln) {
4880
+ if (sln) {
4881
+ const resolved = path26.resolve(sln);
4882
+ if (!existsSync23(resolved)) {
4883
+ console.error(chalk55.red(`Solution file not found: ${resolved}`));
4884
+ process.exit(1);
4885
+ }
4886
+ return resolved;
4887
+ }
4888
+ return findSolution();
4889
+ }
4890
+ function runAndParse(resolved, changedFiles, all, swea) {
4891
+ const start3 = Date.now();
4892
+ const report = runInspectCode(resolved, changedFiles.join(";"), swea);
4893
+ const elapsed = Date.now() - start3;
4894
+ const allIssues = parseInspectReport(report);
4895
+ const issues = all ? allIssues : allIssues.filter((i) => deadCodeRules.has(i.typeId));
4896
+ return { issues, elapsed };
4897
+ }
4898
+ function reportResults(issues, elapsed) {
4899
+ if (issues.length > 0) displayIssues(issues);
4900
+ else console.log(chalk55.green("No issues found"));
4901
+ console.log(chalk55.dim(`Completed in ${formatElapsed(elapsed)}`));
4902
+ if (issues.length > 0) process.exit(1);
4903
+ }
4904
+ async function inspect(sln, options2) {
4905
+ const resolved = resolveSolution(sln);
4906
+ checkBuildLocks();
4907
+ assertJbInstalled();
4908
+ const changedFiles = getChangedCsFiles(options2.ref);
4909
+ if (changedFiles.length === 0) {
4910
+ console.log(chalk55.green("No changed .cs files found"));
4911
+ return;
4912
+ }
4913
+ console.log(
4914
+ chalk55.dim(`Inspecting ${changedFiles.length} changed file(s)...`)
4915
+ );
4916
+ const result = runAndParse(
4917
+ resolved,
4918
+ changedFiles,
4919
+ !!options2.all,
4920
+ !!options2.swea
4921
+ );
4922
+ reportResults(result.issues, result.elapsed);
4923
+ }
4924
+
4925
+ // src/commands/registerDotnet.ts
4926
+ function registerDotnet(program2) {
4927
+ const cmd = program2.command("dotnet").description(".NET project utilities");
4928
+ cmd.command("inspect").description(
4929
+ "Run JetBrains inspections on changed .cs files to find dead code"
4930
+ ).argument("[sln]", "Path to a .sln file (auto-detected if omitted)").option("--ref <ref>", "Git commit to inspect (default: working copy)").option("--all", "Show all issues, not just dead code").option("--swea", "Enable solution-wide error analysis").action(inspect);
4931
+ cmd.command("check-locks").description("Check if build output files are locked by a debugger").action(checkBuildLocksCommand);
4932
+ cmd.command("deps").description("Show .csproj project dependency tree and solution membership").argument("<csproj>", "Path to a .csproj file").option("--json", "Output as JSON").action(deps);
4933
+ cmd.command("in-sln").description("Check whether a .csproj is referenced by any .sln file").argument("<csproj>", "Path to a .csproj file").action(inSln);
4934
+ }
4935
+
4936
+ // src/commands/jira/acceptanceCriteria.ts
4937
+ import chalk57 from "chalk";
4938
+
4939
+ // src/commands/jira/adfToText.ts
4940
+ function renderInline(node) {
4941
+ const text = node.text ?? "";
4942
+ if (node.marks?.some((m) => m.type === "code")) return `\`${text}\``;
4943
+ return text;
4944
+ }
4945
+ function renderChildren(node, indent) {
4946
+ return renderNodes(node.content ?? [], indent);
4947
+ }
4948
+ function renderOrderedList(node, indent) {
4949
+ let counter = 0;
4950
+ return (node.content ?? []).map((item) => {
4951
+ counter++;
4952
+ return renderListItem(item, indent, `${counter}.`);
4953
+ }).join("\n");
4954
+ }
4955
+ function renderBulletList(node, indent) {
4956
+ return (node.content ?? []).map((item) => renderListItem(item, indent, "-")).join("\n");
4957
+ }
4958
+ function renderHeading(node, indent) {
4959
+ const level = node.attrs?.level ?? 1;
4960
+ return `${"#".repeat(level)} ${renderChildren(node, indent)}`;
4961
+ }
4962
+ var renderers = {
4963
+ text: (node) => renderInline(node),
4964
+ paragraph: renderChildren,
4965
+ orderedList: renderOrderedList,
4966
+ bulletList: renderBulletList,
4967
+ listItem: (node, indent) => renderListItem(node, indent, "-"),
4968
+ heading: renderHeading,
4969
+ doc: renderChildren
4970
+ };
4971
+ function renderNode(node, indent) {
4972
+ const renderer = renderers[node.type];
4973
+ if (renderer) return renderer(node, indent);
4974
+ return node.content ? renderChildren(node, indent) : "";
4975
+ }
4976
+ function renderNodes(nodes, indent) {
4977
+ return nodes.map((node) => renderNode(node, indent)).join("");
4978
+ }
4979
+ function isListNode(node) {
4980
+ return node.type === "orderedList" || node.type === "bulletList";
4981
+ }
4982
+ function renderListChild(child, indent, pad, marker, isFirst) {
4983
+ if (isListNode(child)) return renderNodes([child], indent + 1);
4984
+ if (child.type !== "paragraph") return renderNode(child, indent);
4985
+ const text = renderChildren(child, indent);
4986
+ return isFirst ? `${pad}${marker} ${text}` : `${pad} ${text}`;
4987
+ }
4988
+ function renderListItem(node, indent, marker) {
4989
+ const pad = " ".repeat(indent);
4990
+ return (node.content ?? []).map((child, i) => renderListChild(child, indent, pad, marker, i === 0)).join("\n");
4991
+ }
4992
+ function adfToText(doc) {
4993
+ return renderNodes([doc], 0);
4994
+ }
4995
+
4996
+ // src/commands/jira/fetchIssue.ts
4997
+ import { execSync as execSync22 } from "child_process";
4998
+ import chalk56 from "chalk";
4999
+ function fetchIssue(issueKey, fields) {
5000
+ let result;
5001
+ try {
5002
+ result = execSync22(
5003
+ `acli jira workitem view ${issueKey} -f ${fields} --json`,
5004
+ { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
5005
+ );
5006
+ } catch (error) {
5007
+ if (error instanceof Error && "stderr" in error) {
5008
+ const stderr = error.stderr;
5009
+ if (stderr.includes("unauthorized")) {
5010
+ console.error(
5011
+ chalk56.red("Jira authentication expired."),
5012
+ "Run",
5013
+ chalk56.cyan("assist jira auth"),
5014
+ "to re-authenticate."
5015
+ );
5016
+ process.exit(1);
5017
+ }
5018
+ }
5019
+ console.error(chalk56.red(`Failed to fetch ${issueKey}.`));
5020
+ process.exit(1);
5021
+ }
5022
+ return JSON.parse(result);
5023
+ }
5024
+
5025
+ // src/commands/jira/acceptanceCriteria.ts
5026
+ var DEFAULT_AC_FIELD = "customfield_11937";
5027
+ function acceptanceCriteria(issueKey) {
5028
+ const config = loadConfig();
5029
+ const field = config.jira?.acField ?? DEFAULT_AC_FIELD;
5030
+ const parsed = fetchIssue(issueKey, field);
5031
+ const acValue = parsed?.fields?.[field];
5032
+ if (!acValue) {
5033
+ console.log(chalk57.yellow(`No acceptance criteria found on ${issueKey}.`));
5034
+ return;
5035
+ }
5036
+ if (typeof acValue === "string") {
5037
+ console.log(acValue);
5038
+ return;
5039
+ }
5040
+ if (acValue.type === "doc") {
5041
+ console.log(adfToText(acValue));
5042
+ return;
5043
+ }
5044
+ console.log(JSON.stringify(acValue, null, 2));
5045
+ }
5046
+
5047
+ // src/commands/jira/jiraAuth.ts
5048
+ import { execSync as execSync23 } from "child_process";
5049
+ import Enquirer from "enquirer";
5050
+
5051
+ // src/shared/loadJson.ts
5052
+ import { existsSync as existsSync24, mkdirSync as mkdirSync5, readFileSync as readFileSync21, writeFileSync as writeFileSync17 } from "fs";
5053
+ import { homedir as homedir6 } from "os";
5054
+ import { join as join18 } from "path";
5055
+ function getStoreDir() {
5056
+ return join18(homedir6(), ".assist");
5057
+ }
5058
+ function getStorePath(filename) {
5059
+ return join18(getStoreDir(), filename);
5060
+ }
5061
+ function loadJson(filename) {
5062
+ const path44 = getStorePath(filename);
5063
+ if (existsSync24(path44)) {
5064
+ try {
5065
+ return JSON.parse(readFileSync21(path44, "utf-8"));
5066
+ } catch {
5067
+ return {};
5068
+ }
5069
+ }
5070
+ return {};
5071
+ }
5072
+ function saveJson(filename, data) {
5073
+ const dir = getStoreDir();
5074
+ if (!existsSync24(dir)) {
5075
+ mkdirSync5(dir, { recursive: true });
5076
+ }
5077
+ writeFileSync17(getStorePath(filename), JSON.stringify(data, null, 2));
5078
+ }
5079
+
5080
+ // src/commands/jira/jiraAuth.ts
5081
+ var CONFIG_FILE = "jira.json";
5082
+ async function promptCredentials(config) {
5083
+ const { Input: Input2, Password } = Enquirer;
5084
+ const site = await new Input2({
5085
+ name: "site",
5086
+ message: "Jira site (e.g., mycompany.atlassian.net):",
5087
+ initial: config.site
5088
+ }).run();
5089
+ const email = await new Input2({
5090
+ name: "email",
5091
+ message: "Email:",
5092
+ initial: config.email
5093
+ }).run();
5094
+ const token = await new Password({
5095
+ name: "token",
5096
+ message: "API token (https://id.atlassian.com/manage-profile/security/api-tokens):"
5097
+ }).run();
5098
+ return { site, email, token };
5099
+ }
5100
+ async function jiraAuth() {
5101
+ const config = loadJson(CONFIG_FILE);
5102
+ try {
5103
+ const { site, email, token } = await promptCredentials(config);
5104
+ if (!site || !email || !token) {
5105
+ console.error("All fields are required.");
5106
+ process.exit(1);
5107
+ }
5108
+ execSync23(`acli jira auth login --site ${site} --email "${email}" --token`, {
5109
+ encoding: "utf-8",
5110
+ input: token,
5111
+ stdio: ["pipe", "inherit", "inherit"]
5112
+ });
5113
+ saveJson(CONFIG_FILE, { site, email });
5114
+ console.log("Successfully authenticated with Jira.");
5115
+ } catch (error) {
5116
+ if (error instanceof Error) {
5117
+ console.error("Error authenticating with Jira:", error.message);
5118
+ }
5119
+ process.exit(1);
5120
+ }
5121
+ }
5122
+
5123
+ // src/commands/jira/viewIssue.ts
5124
+ import chalk58 from "chalk";
5125
+ function viewIssue(issueKey) {
5126
+ const parsed = fetchIssue(issueKey, "summary,description");
5127
+ const fields = parsed?.fields;
5128
+ const summary = fields?.summary;
5129
+ const description = fields?.description;
5130
+ if (summary) {
5131
+ console.log(chalk58.bold(summary));
5132
+ }
5133
+ if (description) {
5134
+ if (summary) console.log();
5135
+ if (typeof description === "string") {
5136
+ console.log(description);
5137
+ } else if (description.type === "doc") {
5138
+ console.log(adfToText(description));
5139
+ } else {
5140
+ console.log(JSON.stringify(description, null, 2));
5141
+ }
5142
+ }
5143
+ if (!summary && !description) {
5144
+ console.log(
5145
+ chalk58.yellow(`No summary or description found on ${issueKey}.`)
5146
+ );
5147
+ }
5148
+ }
5149
+
5150
+ // src/commands/registerJira.ts
5151
+ function registerJira(program2) {
5152
+ const jiraCommand = program2.command("jira").description("Jira utilities");
5153
+ jiraCommand.command("auth").description("Authenticate with Jira via API token").action(() => jiraAuth());
5154
+ jiraCommand.command("ac <issue-key>").description("Print acceptance criteria for a Jira issue").action((issueKey) => acceptanceCriteria(issueKey));
5155
+ jiraCommand.command("view <issue-key>").description("Print the title and description of a Jira issue").action((issueKey) => viewIssue(issueKey));
5156
+ }
5157
+
5158
+ // src/commands/news/add/index.ts
5159
+ import chalk59 from "chalk";
5160
+ import enquirer5 from "enquirer";
5161
+ async function add2(url) {
5162
+ if (!url) {
5163
+ const response = await enquirer5.prompt({
5164
+ type: "input",
4873
5165
  name: "url",
4874
5166
  message: "RSS feed URL:",
4875
5167
  validate: (value) => {
@@ -4887,17 +5179,17 @@ async function add2(url) {
4887
5179
  const news = config.news ?? {};
4888
5180
  const feeds = news.feeds ?? [];
4889
5181
  if (feeds.includes(url)) {
4890
- console.log(chalk54.yellow("Feed already exists in config"));
5182
+ console.log(chalk59.yellow("Feed already exists in config"));
4891
5183
  return;
4892
5184
  }
4893
5185
  feeds.push(url);
4894
5186
  config.news = { ...news, feeds };
4895
5187
  saveGlobalConfig(config);
4896
- console.log(chalk54.green(`Added feed: ${url}`));
5188
+ console.log(chalk59.green(`Added feed: ${url}`));
4897
5189
  }
4898
5190
 
4899
5191
  // src/commands/news/web/handleRequest.ts
4900
- import chalk55 from "chalk";
5192
+ import chalk60 from "chalk";
4901
5193
 
4902
5194
  // src/commands/news/web/shared.ts
4903
5195
  import { decodeHTML } from "entities";
@@ -5033,17 +5325,17 @@ function prefetch() {
5033
5325
  const config = loadConfig();
5034
5326
  const total = config.news.feeds.length;
5035
5327
  if (total === 0) return;
5036
- process.stdout.write(chalk55.dim(`Fetching ${total} feed(s)\u2026 `));
5328
+ process.stdout.write(chalk60.dim(`Fetching ${total} feed(s)\u2026 `));
5037
5329
  prefetchPromise = fetchFeeds(config.news.feeds, (done2, t) => {
5038
5330
  const width = 20;
5039
5331
  const filled = Math.round(done2 / t * width);
5040
5332
  const bar = `${"\u2588".repeat(filled)}${"\u2591".repeat(width - filled)}`;
5041
5333
  process.stdout.write(
5042
- `\r${chalk55.dim(`Fetching feeds ${bar} ${done2}/${t}`)}`
5334
+ `\r${chalk60.dim(`Fetching feeds ${bar} ${done2}/${t}`)}`
5043
5335
  );
5044
5336
  }).then((items) => {
5045
5337
  process.stdout.write(
5046
- `\r${chalk55.green(`Fetched ${items.length} items from ${total} feed(s)`)}
5338
+ `\r${chalk60.green(`Fetched ${items.length} items from ${total} feed(s)`)}
5047
5339
  `
5048
5340
  );
5049
5341
  cachedItems = items;
@@ -5089,12 +5381,12 @@ function registerNews(program2) {
5089
5381
 
5090
5382
  // src/commands/prs/comment.ts
5091
5383
  import { spawnSync as spawnSync2 } from "child_process";
5092
- import { unlinkSync as unlinkSync3, writeFileSync as writeFileSync18 } from "fs";
5093
- import { tmpdir as tmpdir2 } from "os";
5094
- import { join as join17 } from "path";
5384
+ import { unlinkSync as unlinkSync4, writeFileSync as writeFileSync18 } from "fs";
5385
+ import { tmpdir as tmpdir3 } from "os";
5386
+ import { join as join19 } from "path";
5095
5387
 
5096
5388
  // src/commands/prs/shared.ts
5097
- import { execSync as execSync22 } from "child_process";
5389
+ import { execSync as execSync24 } from "child_process";
5098
5390
  function isGhNotInstalled(error) {
5099
5391
  if (error instanceof Error) {
5100
5392
  const msg = error.message.toLowerCase();
@@ -5110,14 +5402,14 @@ function isNotFound(error) {
5110
5402
  }
5111
5403
  function getRepoInfo() {
5112
5404
  const repoInfo = JSON.parse(
5113
- execSync22("gh repo view --json owner,name", { encoding: "utf-8" })
5405
+ execSync24("gh repo view --json owner,name", { encoding: "utf-8" })
5114
5406
  );
5115
5407
  return { org: repoInfo.owner.login, repo: repoInfo.name };
5116
5408
  }
5117
5409
  function getCurrentPrNumber() {
5118
5410
  try {
5119
5411
  const prInfo = JSON.parse(
5120
- execSync22("gh pr view --json number", { encoding: "utf-8" })
5412
+ execSync24("gh pr view --json number", { encoding: "utf-8" })
5121
5413
  );
5122
5414
  return prInfo.number;
5123
5415
  } catch (error) {
@@ -5131,7 +5423,7 @@ function getCurrentPrNumber() {
5131
5423
  function getCurrentPrNodeId() {
5132
5424
  try {
5133
5425
  const prInfo = JSON.parse(
5134
- execSync22("gh pr view --json id", { encoding: "utf-8" })
5426
+ execSync24("gh pr view --json id", { encoding: "utf-8" })
5135
5427
  );
5136
5428
  return prInfo.id;
5137
5429
  } catch (error) {
@@ -5158,12 +5450,12 @@ function validateLine(line) {
5158
5450
  process.exit(1);
5159
5451
  }
5160
5452
  }
5161
- function comment(path42, line, body) {
5453
+ function comment(path44, line, body) {
5162
5454
  validateBody(body);
5163
5455
  validateLine(line);
5164
5456
  try {
5165
5457
  const prId = getCurrentPrNodeId();
5166
- const queryFile = join17(tmpdir2(), `gh-query-${Date.now()}.graphql`);
5458
+ const queryFile = join19(tmpdir3(), `gh-query-${Date.now()}.graphql`);
5167
5459
  writeFileSync18(queryFile, MUTATION);
5168
5460
  try {
5169
5461
  const result = spawnSync2(
@@ -5178,7 +5470,7 @@ function comment(path42, line, body) {
5178
5470
  "-f",
5179
5471
  `body=${body}`,
5180
5472
  "-f",
5181
- `path=${path42}`,
5473
+ `path=${path44}`,
5182
5474
  "-F",
5183
5475
  `line=${line}`
5184
5476
  ],
@@ -5187,9 +5479,9 @@ function comment(path42, line, body) {
5187
5479
  if (result.status !== 0) {
5188
5480
  throw new Error(result.stderr || result.stdout);
5189
5481
  }
5190
- console.log(`Added review comment on ${path42}:${line}`);
5482
+ console.log(`Added review comment on ${path44}:${line}`);
5191
5483
  } finally {
5192
- unlinkSync3(queryFile);
5484
+ unlinkSync4(queryFile);
5193
5485
  }
5194
5486
  } catch (error) {
5195
5487
  if (isGhNotInstalled(error)) {
@@ -5202,55 +5494,55 @@ function comment(path42, line, body) {
5202
5494
  }
5203
5495
 
5204
5496
  // src/commands/prs/fixed.ts
5205
- import { execSync as execSync24 } from "child_process";
5497
+ import { execSync as execSync26 } from "child_process";
5206
5498
 
5207
5499
  // src/commands/prs/resolveCommentWithReply.ts
5208
- import { execSync as execSync23 } from "child_process";
5209
- import { unlinkSync as unlinkSync5, writeFileSync as writeFileSync19 } from "fs";
5210
- import { tmpdir as tmpdir3 } from "os";
5211
- import { join as join19 } from "path";
5500
+ import { execSync as execSync25 } from "child_process";
5501
+ import { unlinkSync as unlinkSync6, writeFileSync as writeFileSync19 } from "fs";
5502
+ import { tmpdir as tmpdir4 } from "os";
5503
+ import { join as join21 } from "path";
5212
5504
 
5213
5505
  // src/commands/prs/loadCommentsCache.ts
5214
- import { existsSync as existsSync23, readFileSync as readFileSync21, unlinkSync as unlinkSync4 } from "fs";
5215
- import { join as join18 } from "path";
5506
+ import { existsSync as existsSync25, readFileSync as readFileSync22, unlinkSync as unlinkSync5 } from "fs";
5507
+ import { join as join20 } from "path";
5216
5508
  import { parse as parse2 } from "yaml";
5217
5509
  function getCachePath(prNumber) {
5218
- return join18(process.cwd(), ".assist", `pr-${prNumber}-comments.yaml`);
5510
+ return join20(process.cwd(), ".assist", `pr-${prNumber}-comments.yaml`);
5219
5511
  }
5220
5512
  function loadCommentsCache(prNumber) {
5221
5513
  const cachePath = getCachePath(prNumber);
5222
- if (!existsSync23(cachePath)) {
5514
+ if (!existsSync25(cachePath)) {
5223
5515
  return null;
5224
5516
  }
5225
- const content = readFileSync21(cachePath, "utf-8");
5517
+ const content = readFileSync22(cachePath, "utf-8");
5226
5518
  return parse2(content);
5227
5519
  }
5228
5520
  function deleteCommentsCache(prNumber) {
5229
5521
  const cachePath = getCachePath(prNumber);
5230
- if (existsSync23(cachePath)) {
5231
- unlinkSync4(cachePath);
5522
+ if (existsSync25(cachePath)) {
5523
+ unlinkSync5(cachePath);
5232
5524
  console.log("No more unresolved line comments. Cache dropped.");
5233
5525
  }
5234
5526
  }
5235
5527
 
5236
5528
  // src/commands/prs/resolveCommentWithReply.ts
5237
5529
  function replyToComment(org, repo, prNumber, commentId, message) {
5238
- execSync23(
5530
+ execSync25(
5239
5531
  `gh api repos/${org}/${repo}/pulls/${prNumber}/comments -f body="${message.replace(/"/g, '\\"')}" -F in_reply_to=${commentId}`,
5240
5532
  { stdio: ["inherit", "pipe", "inherit"] }
5241
5533
  );
5242
5534
  }
5243
5535
  function resolveThread(threadId) {
5244
5536
  const mutation = `mutation($threadId: ID!) { resolveReviewThread(input: {threadId: $threadId}) { thread { isResolved } } }`;
5245
- const queryFile = join19(tmpdir3(), `gh-mutation-${Date.now()}.graphql`);
5537
+ const queryFile = join21(tmpdir4(), `gh-mutation-${Date.now()}.graphql`);
5246
5538
  writeFileSync19(queryFile, mutation);
5247
5539
  try {
5248
- execSync23(
5540
+ execSync25(
5249
5541
  `gh api graphql -F query=@${queryFile} -f threadId="${threadId}"`,
5250
5542
  { stdio: ["inherit", "pipe", "inherit"] }
5251
5543
  );
5252
5544
  } finally {
5253
- unlinkSync5(queryFile);
5545
+ unlinkSync6(queryFile);
5254
5546
  }
5255
5547
  }
5256
5548
  function requireCache(prNumber) {
@@ -5297,7 +5589,7 @@ function resolveCommentWithReply(commentId, message) {
5297
5589
  // src/commands/prs/fixed.ts
5298
5590
  function verifySha(sha) {
5299
5591
  try {
5300
- return execSync24(`git rev-parse --verify ${sha}`, {
5592
+ return execSync26(`git rev-parse --verify ${sha}`, {
5301
5593
  encoding: "utf-8"
5302
5594
  }).trim();
5303
5595
  } catch {
@@ -5311,7 +5603,7 @@ function fixed(commentId, sha) {
5311
5603
  const { org, repo } = getRepoInfo();
5312
5604
  const repoUrl = `https://github.com/${org}/${repo}`;
5313
5605
  const message = `Fixed in [${fullSha}](${repoUrl}/commit/${fullSha})`;
5314
- execSync24("git push", { stdio: "inherit" });
5606
+ execSync26("git push", { stdio: "inherit" });
5315
5607
  resolveCommentWithReply(commentId, message);
5316
5608
  } catch (error) {
5317
5609
  if (isGhNotInstalled(error)) {
@@ -5324,21 +5616,21 @@ function fixed(commentId, sha) {
5324
5616
  }
5325
5617
 
5326
5618
  // src/commands/prs/listComments/index.ts
5327
- import { existsSync as existsSync24, mkdirSync as mkdirSync6, writeFileSync as writeFileSync21 } from "fs";
5328
- import { join as join21 } from "path";
5619
+ import { existsSync as existsSync26, mkdirSync as mkdirSync6, writeFileSync as writeFileSync21 } from "fs";
5620
+ import { join as join23 } from "path";
5329
5621
  import { stringify } from "yaml";
5330
5622
 
5331
5623
  // src/commands/prs/fetchThreadIds.ts
5332
- import { execSync as execSync25 } from "child_process";
5333
- import { unlinkSync as unlinkSync6, writeFileSync as writeFileSync20 } from "fs";
5334
- import { tmpdir as tmpdir4 } from "os";
5335
- import { join as join20 } from "path";
5624
+ import { execSync as execSync27 } from "child_process";
5625
+ import { unlinkSync as unlinkSync7, writeFileSync as writeFileSync20 } from "fs";
5626
+ import { tmpdir as tmpdir5 } from "os";
5627
+ import { join as join22 } from "path";
5336
5628
  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 } } } } } } }`;
5337
5629
  function fetchThreadIds(org, repo, prNumber) {
5338
- const queryFile = join20(tmpdir4(), `gh-query-${Date.now()}.graphql`);
5630
+ const queryFile = join22(tmpdir5(), `gh-query-${Date.now()}.graphql`);
5339
5631
  writeFileSync20(queryFile, THREAD_QUERY);
5340
5632
  try {
5341
- const result = execSync25(
5633
+ const result = execSync27(
5342
5634
  `gh api graphql -F query=@${queryFile} -F owner="${org}" -F repo="${repo}" -F prNumber=${prNumber}`,
5343
5635
  { encoding: "utf-8" }
5344
5636
  );
@@ -5355,14 +5647,14 @@ function fetchThreadIds(org, repo, prNumber) {
5355
5647
  }
5356
5648
  return { threadMap, resolvedThreadIds };
5357
5649
  } finally {
5358
- unlinkSync6(queryFile);
5650
+ unlinkSync7(queryFile);
5359
5651
  }
5360
5652
  }
5361
5653
 
5362
5654
  // src/commands/prs/listComments/fetchReviewComments.ts
5363
- import { execSync as execSync26 } from "child_process";
5655
+ import { execSync as execSync28 } from "child_process";
5364
5656
  function fetchJson(endpoint) {
5365
- const result = execSync26(`gh api --paginate ${endpoint}`, {
5657
+ const result = execSync28(`gh api --paginate ${endpoint}`, {
5366
5658
  encoding: "utf-8"
5367
5659
  });
5368
5660
  if (!result.trim()) return [];
@@ -5404,20 +5696,20 @@ function fetchLineComments(org, repo, prNumber, threadInfo) {
5404
5696
  }
5405
5697
 
5406
5698
  // src/commands/prs/listComments/printComments.ts
5407
- import chalk56 from "chalk";
5699
+ import chalk61 from "chalk";
5408
5700
  function formatForHuman(comment2) {
5409
5701
  if (comment2.type === "review") {
5410
- const stateColor = comment2.state === "APPROVED" ? chalk56.green : comment2.state === "CHANGES_REQUESTED" ? chalk56.red : chalk56.yellow;
5702
+ const stateColor = comment2.state === "APPROVED" ? chalk61.green : comment2.state === "CHANGES_REQUESTED" ? chalk61.red : chalk61.yellow;
5411
5703
  return [
5412
- `${chalk56.cyan("Review")} by ${chalk56.bold(comment2.user)} ${stateColor(`[${comment2.state}]`)}`,
5704
+ `${chalk61.cyan("Review")} by ${chalk61.bold(comment2.user)} ${stateColor(`[${comment2.state}]`)}`,
5413
5705
  comment2.body,
5414
5706
  ""
5415
5707
  ].join("\n");
5416
5708
  }
5417
5709
  const location = comment2.line ? `:${comment2.line}` : "";
5418
5710
  return [
5419
- `${chalk56.cyan("Line comment")} by ${chalk56.bold(comment2.user)} on ${chalk56.dim(`${comment2.path}${location}`)}`,
5420
- chalk56.dim(comment2.diff_hunk.split("\n").slice(-3).join("\n")),
5711
+ `${chalk61.cyan("Line comment")} by ${chalk61.bold(comment2.user)} on ${chalk61.dim(`${comment2.path}${location}`)}`,
5712
+ chalk61.dim(comment2.diff_hunk.split("\n").slice(-3).join("\n")),
5421
5713
  comment2.body,
5422
5714
  ""
5423
5715
  ].join("\n");
@@ -5449,8 +5741,8 @@ function printComments(result) {
5449
5741
 
5450
5742
  // src/commands/prs/listComments/index.ts
5451
5743
  function writeCommentsCache(prNumber, comments) {
5452
- const assistDir = join21(process.cwd(), ".assist");
5453
- if (!existsSync24(assistDir)) {
5744
+ const assistDir = join23(process.cwd(), ".assist");
5745
+ if (!existsSync26(assistDir)) {
5454
5746
  mkdirSync6(assistDir, { recursive: true });
5455
5747
  }
5456
5748
  const cacheData = {
@@ -5458,7 +5750,7 @@ function writeCommentsCache(prNumber, comments) {
5458
5750
  fetchedAt: (/* @__PURE__ */ new Date()).toISOString(),
5459
5751
  comments
5460
5752
  };
5461
- const cachePath = join21(assistDir, `pr-${prNumber}-comments.yaml`);
5753
+ const cachePath = join23(assistDir, `pr-${prNumber}-comments.yaml`);
5462
5754
  writeFileSync21(cachePath, stringify(cacheData));
5463
5755
  }
5464
5756
  function handleKnownErrors(error) {
@@ -5491,7 +5783,7 @@ async function listComments() {
5491
5783
  ];
5492
5784
  updateCache(prNumber, allComments);
5493
5785
  const hasLineComments = allComments.some((c) => c.type === "line");
5494
- const cachePath = hasLineComments ? join21(process.cwd(), ".assist", `pr-${prNumber}-comments.yaml`) : null;
5786
+ const cachePath = hasLineComments ? join23(process.cwd(), ".assist", `pr-${prNumber}-comments.yaml`) : null;
5495
5787
  return { comments: allComments, cachePath };
5496
5788
  } catch (error) {
5497
5789
  const handled = handleKnownErrors(error);
@@ -5501,19 +5793,19 @@ async function listComments() {
5501
5793
  }
5502
5794
 
5503
5795
  // src/commands/prs/prs/index.ts
5504
- import { execSync as execSync27 } from "child_process";
5796
+ import { execSync as execSync29 } from "child_process";
5505
5797
 
5506
5798
  // src/commands/prs/prs/displayPaginated/index.ts
5507
5799
  import enquirer6 from "enquirer";
5508
5800
 
5509
5801
  // src/commands/prs/prs/displayPaginated/printPr.ts
5510
- import chalk57 from "chalk";
5802
+ import chalk62 from "chalk";
5511
5803
  var STATUS_MAP = {
5512
- MERGED: (pr) => pr.mergedAt ? { label: chalk57.magenta("merged"), date: pr.mergedAt } : null,
5513
- CLOSED: (pr) => pr.closedAt ? { label: chalk57.red("closed"), date: pr.closedAt } : null
5804
+ MERGED: (pr) => pr.mergedAt ? { label: chalk62.magenta("merged"), date: pr.mergedAt } : null,
5805
+ CLOSED: (pr) => pr.closedAt ? { label: chalk62.red("closed"), date: pr.closedAt } : null
5514
5806
  };
5515
5807
  function defaultStatus(pr) {
5516
- return { label: chalk57.green("opened"), date: pr.createdAt };
5808
+ return { label: chalk62.green("opened"), date: pr.createdAt };
5517
5809
  }
5518
5810
  function getStatus2(pr) {
5519
5811
  return STATUS_MAP[pr.state]?.(pr) ?? defaultStatus(pr);
@@ -5522,11 +5814,11 @@ function formatDate(dateStr) {
5522
5814
  return new Date(dateStr).toISOString().split("T")[0];
5523
5815
  }
5524
5816
  function formatPrHeader(pr, status2) {
5525
- return `${chalk57.cyan(`#${pr.number}`)} ${pr.title} ${chalk57.dim(`(${pr.author.login},`)} ${status2.label} ${chalk57.dim(`${formatDate(status2.date)})`)}`;
5817
+ return `${chalk62.cyan(`#${pr.number}`)} ${pr.title} ${chalk62.dim(`(${pr.author.login},`)} ${status2.label} ${chalk62.dim(`${formatDate(status2.date)})`)}`;
5526
5818
  }
5527
5819
  function logPrDetails(pr) {
5528
5820
  console.log(
5529
- chalk57.dim(` ${pr.changedFiles.toLocaleString()} files | ${pr.url}`)
5821
+ chalk62.dim(` ${pr.changedFiles.toLocaleString()} files | ${pr.url}`)
5530
5822
  );
5531
5823
  console.log();
5532
5824
  }
@@ -5607,7 +5899,7 @@ async function displayPaginated(pullRequests) {
5607
5899
  async function prs(options2) {
5608
5900
  const state = options2.open ? "open" : options2.closed ? "closed" : "all";
5609
5901
  try {
5610
- const result = execSync27(
5902
+ const result = execSync29(
5611
5903
  `gh pr list --state ${state} --json number,title,url,author,createdAt,mergedAt,closedAt,state,changedFiles --limit 100`,
5612
5904
  { encoding: "utf-8" }
5613
5905
  );
@@ -5630,7 +5922,7 @@ async function prs(options2) {
5630
5922
  }
5631
5923
 
5632
5924
  // src/commands/prs/wontfix.ts
5633
- import { execSync as execSync28 } from "child_process";
5925
+ import { execSync as execSync30 } from "child_process";
5634
5926
  function validateReason(reason) {
5635
5927
  const lowerReason = reason.toLowerCase();
5636
5928
  if (lowerReason.includes("claude") || lowerReason.includes("opus")) {
@@ -5647,7 +5939,7 @@ function validateShaReferences(reason) {
5647
5939
  const invalidShas = [];
5648
5940
  for (const sha of shas) {
5649
5941
  try {
5650
- execSync28(`git cat-file -t ${sha}`, { stdio: "pipe" });
5942
+ execSync30(`git cat-file -t ${sha}`, { stdio: "pipe" });
5651
5943
  } catch {
5652
5944
  invalidShas.push(sha);
5653
5945
  }
@@ -5686,13 +5978,13 @@ function registerPrs(program2) {
5686
5978
  prsCommand.command("wontfix <comment-id> <reason>").description("Reply with reason and resolve thread").action((commentId, reason) => {
5687
5979
  wontfix(Number.parseInt(commentId, 10), reason);
5688
5980
  });
5689
- prsCommand.command("comment <path> <line> <body>").description("Add a line comment to the pending review").action((path42, line, body) => {
5690
- comment(path42, Number.parseInt(line, 10), body);
5981
+ prsCommand.command("comment <path> <line> <body>").description("Add a line comment to the pending review").action((path44, line, body) => {
5982
+ comment(path44, Number.parseInt(line, 10), body);
5691
5983
  });
5692
5984
  }
5693
5985
 
5694
5986
  // src/commands/ravendb/ravendbAuth.ts
5695
- import chalk62 from "chalk";
5987
+ import chalk67 from "chalk";
5696
5988
 
5697
5989
  // src/commands/ravendb/loadConnections.ts
5698
5990
  function loadConnections() {
@@ -5709,18 +6001,18 @@ function saveConnections(connections) {
5709
6001
  }
5710
6002
 
5711
6003
  // src/commands/ravendb/promptConnection.ts
5712
- import chalk60 from "chalk";
6004
+ import chalk65 from "chalk";
5713
6005
  import Enquirer3 from "enquirer";
5714
6006
 
5715
6007
  // src/commands/ravendb/selectOpSecret.ts
5716
- import chalk59 from "chalk";
6008
+ import chalk64 from "chalk";
5717
6009
  import Enquirer2 from "enquirer";
5718
6010
 
5719
6011
  // src/commands/ravendb/searchItems.ts
5720
- import { execSync as execSync29 } from "child_process";
5721
- import chalk58 from "chalk";
6012
+ import { execSync as execSync31 } from "child_process";
6013
+ import chalk63 from "chalk";
5722
6014
  function opExec(args) {
5723
- return execSync29(`op ${args}`, {
6015
+ return execSync31(`op ${args}`, {
5724
6016
  encoding: "utf-8",
5725
6017
  stdio: ["pipe", "pipe", "pipe"]
5726
6018
  }).trim();
@@ -5731,7 +6023,7 @@ function searchItems(search) {
5731
6023
  items = JSON.parse(opExec("item list --format=json"));
5732
6024
  } catch {
5733
6025
  console.error(
5734
- chalk58.red(
6026
+ chalk63.red(
5735
6027
  "Failed to search 1Password. Ensure the CLI is installed and you are signed in."
5736
6028
  )
5737
6029
  );
@@ -5745,7 +6037,7 @@ function getItemFields(itemId) {
5745
6037
  const item = JSON.parse(opExec(`item get "${itemId}" --format=json`));
5746
6038
  return item.fields.filter((f) => f.reference && f.label);
5747
6039
  } catch {
5748
- console.error(chalk58.red("Failed to get item details from 1Password."));
6040
+ console.error(chalk63.red("Failed to get item details from 1Password."));
5749
6041
  process.exit(1);
5750
6042
  }
5751
6043
  }
@@ -5764,7 +6056,7 @@ async function selectOpSecret(searchTerm) {
5764
6056
  }).run();
5765
6057
  const items = searchItems(search);
5766
6058
  if (items.length === 0) {
5767
- console.error(chalk59.red(`No items found matching "${search}".`));
6059
+ console.error(chalk64.red(`No items found matching "${search}".`));
5768
6060
  process.exit(1);
5769
6061
  }
5770
6062
  const itemId = await selectOne(
@@ -5773,7 +6065,7 @@ async function selectOpSecret(searchTerm) {
5773
6065
  );
5774
6066
  const fields = getItemFields(itemId);
5775
6067
  if (fields.length === 0) {
5776
- console.error(chalk59.red("No fields with references found on this item."));
6068
+ console.error(chalk64.red("No fields with references found on this item."));
5777
6069
  process.exit(1);
5778
6070
  }
5779
6071
  const ref = await selectOne(
@@ -5791,7 +6083,7 @@ async function promptConnection(existingNames) {
5791
6083
  message: "Connection name:"
5792
6084
  }).run();
5793
6085
  if (existingNames.includes(name)) {
5794
- console.error(chalk60.red(`Connection "${name}" already exists.`));
6086
+ console.error(chalk65.red(`Connection "${name}" already exists.`));
5795
6087
  process.exit(1);
5796
6088
  }
5797
6089
  const url = await new Input2({
@@ -5803,22 +6095,22 @@ async function promptConnection(existingNames) {
5803
6095
  message: "Database name:"
5804
6096
  }).run();
5805
6097
  if (!name || !url || !database) {
5806
- console.error(chalk60.red("All fields are required."));
6098
+ console.error(chalk65.red("All fields are required."));
5807
6099
  process.exit(1);
5808
6100
  }
5809
6101
  const apiKeyRef = await selectOpSecret();
5810
- console.log(chalk60.dim(`Using: ${apiKeyRef}`));
6102
+ console.log(chalk65.dim(`Using: ${apiKeyRef}`));
5811
6103
  return { name, url, database, apiKeyRef };
5812
6104
  }
5813
6105
 
5814
6106
  // src/commands/ravendb/ravendbSetConnection.ts
5815
- import chalk61 from "chalk";
6107
+ import chalk66 from "chalk";
5816
6108
  function ravendbSetConnection(name) {
5817
6109
  const raw = loadGlobalConfigRaw();
5818
6110
  const ravendb = raw.ravendb ?? {};
5819
6111
  const connections = ravendb.connections ?? [];
5820
6112
  if (!connections.some((c) => c.name === name)) {
5821
- console.error(chalk61.red(`Connection "${name}" not found.`));
6113
+ console.error(chalk66.red(`Connection "${name}" not found.`));
5822
6114
  console.error(
5823
6115
  `Available: ${connections.map((c) => c.name).join(", ") || "(none)"}`
5824
6116
  );
@@ -5840,7 +6132,7 @@ async function ravendbAuth(options2) {
5840
6132
  }
5841
6133
  for (const c of connections) {
5842
6134
  console.log(
5843
- `${chalk62.bold(c.name)} ${c.url} db=${c.database} key=${c.apiKeyRef}`
6135
+ `${chalk67.bold(c.name)} ${c.url} db=${c.database} key=${c.apiKeyRef}`
5844
6136
  );
5845
6137
  }
5846
6138
  return;
@@ -5848,7 +6140,7 @@ async function ravendbAuth(options2) {
5848
6140
  if (options2.remove) {
5849
6141
  const filtered = connections.filter((c) => c.name !== options2.remove);
5850
6142
  if (filtered.length === connections.length) {
5851
- console.error(chalk62.red(`Connection "${options2.remove}" not found.`));
6143
+ console.error(chalk67.red(`Connection "${options2.remove}" not found.`));
5852
6144
  process.exit(1);
5853
6145
  }
5854
6146
  saveConnections(filtered);
@@ -5866,10 +6158,10 @@ async function ravendbAuth(options2) {
5866
6158
  }
5867
6159
 
5868
6160
  // src/commands/ravendb/ravendbCollections.ts
5869
- import chalk66 from "chalk";
6161
+ import chalk71 from "chalk";
5870
6162
 
5871
6163
  // src/commands/ravendb/ravenFetch.ts
5872
- import chalk64 from "chalk";
6164
+ import chalk69 from "chalk";
5873
6165
 
5874
6166
  // src/commands/ravendb/getAccessToken.ts
5875
6167
  var OAUTH_URL = "https://amazon-useast-1-oauth.ravenhq.com/ApiKeys/OAuth/AccessToken";
@@ -5905,21 +6197,21 @@ ${errorText}`
5905
6197
  }
5906
6198
 
5907
6199
  // src/commands/ravendb/resolveOpSecret.ts
5908
- import { execSync as execSync30 } from "child_process";
5909
- import chalk63 from "chalk";
6200
+ import { execSync as execSync32 } from "child_process";
6201
+ import chalk68 from "chalk";
5910
6202
  function resolveOpSecret(reference) {
5911
6203
  if (!reference.startsWith("op://")) {
5912
- console.error(chalk63.red(`Invalid secret reference: must start with op://`));
6204
+ console.error(chalk68.red(`Invalid secret reference: must start with op://`));
5913
6205
  process.exit(1);
5914
6206
  }
5915
6207
  try {
5916
- return execSync30(`op read "${reference}"`, {
6208
+ return execSync32(`op read "${reference}"`, {
5917
6209
  encoding: "utf-8",
5918
6210
  stdio: ["pipe", "pipe", "pipe"]
5919
6211
  }).trim();
5920
6212
  } catch {
5921
6213
  console.error(
5922
- chalk63.red(
6214
+ chalk68.red(
5923
6215
  "Failed to resolve secret reference. Ensure 1Password CLI is installed and you are signed in."
5924
6216
  )
5925
6217
  );
@@ -5928,10 +6220,10 @@ function resolveOpSecret(reference) {
5928
6220
  }
5929
6221
 
5930
6222
  // src/commands/ravendb/ravenFetch.ts
5931
- async function ravenFetch(connection, path42) {
6223
+ async function ravenFetch(connection, path44) {
5932
6224
  const apiKey = resolveOpSecret(connection.apiKeyRef);
5933
6225
  let accessToken = await getAccessToken(apiKey);
5934
- const url = `${connection.url}${path42}`;
6226
+ const url = `${connection.url}${path44}`;
5935
6227
  const headers = {
5936
6228
  Authorization: `Bearer ${accessToken}`,
5937
6229
  "Content-Type": "application/json"
@@ -5946,7 +6238,7 @@ async function ravenFetch(connection, path42) {
5946
6238
  if (!response.ok) {
5947
6239
  const body = await response.text();
5948
6240
  console.error(
5949
- chalk64.red(`RavenDB error: ${response.status} ${response.statusText}`)
6241
+ chalk69.red(`RavenDB error: ${response.status} ${response.statusText}`)
5950
6242
  );
5951
6243
  console.error(body.substring(0, 500));
5952
6244
  process.exit(1);
@@ -5955,7 +6247,7 @@ async function ravenFetch(connection, path42) {
5955
6247
  }
5956
6248
 
5957
6249
  // src/commands/ravendb/resolveConnection.ts
5958
- import chalk65 from "chalk";
6250
+ import chalk70 from "chalk";
5959
6251
  function loadRavendb() {
5960
6252
  const raw = loadGlobalConfigRaw();
5961
6253
  const ravendb = raw.ravendb;
@@ -5969,7 +6261,7 @@ function resolveConnection(name) {
5969
6261
  const connectionName = name ?? defaultConnection;
5970
6262
  if (!connectionName) {
5971
6263
  console.error(
5972
- chalk65.red(
6264
+ chalk70.red(
5973
6265
  "No connection specified and no default set. Use assist ravendb set-connection <name> or pass a connection name."
5974
6266
  )
5975
6267
  );
@@ -5977,7 +6269,7 @@ function resolveConnection(name) {
5977
6269
  }
5978
6270
  const connection = connections.find((c) => c.name === connectionName);
5979
6271
  if (!connection) {
5980
- console.error(chalk65.red(`Connection "${connectionName}" not found.`));
6272
+ console.error(chalk70.red(`Connection "${connectionName}" not found.`));
5981
6273
  console.error(
5982
6274
  `Available: ${connections.map((c) => c.name).join(", ") || "(none)"}`
5983
6275
  );
@@ -6008,29 +6300,29 @@ async function ravendbCollections(connectionName) {
6008
6300
  return;
6009
6301
  }
6010
6302
  for (const c of collections) {
6011
- console.log(`${chalk66.bold(c.Name)} ${c.CountOfDocuments} docs`);
6303
+ console.log(`${chalk71.bold(c.Name)} ${c.CountOfDocuments} docs`);
6012
6304
  }
6013
6305
  }
6014
6306
 
6015
6307
  // src/commands/ravendb/ravendbQuery.ts
6016
- import chalk68 from "chalk";
6308
+ import chalk73 from "chalk";
6017
6309
 
6018
6310
  // src/commands/ravendb/fetchAllPages.ts
6019
- import chalk67 from "chalk";
6311
+ import chalk72 from "chalk";
6020
6312
 
6021
6313
  // src/commands/ravendb/buildQueryPath.ts
6022
6314
  function buildQueryPath(opts) {
6023
6315
  const db = encodeURIComponent(opts.db);
6024
- let path42;
6316
+ let path44;
6025
6317
  if (opts.collection) {
6026
- path42 = `/databases/${db}/indexes/dynamic/${encodeURIComponent(opts.collection)}?start=${opts.start}&pageSize=${opts.pageSize}&sort=${encodeURIComponent(opts.sort)}`;
6318
+ path44 = `/databases/${db}/indexes/dynamic/${encodeURIComponent(opts.collection)}?start=${opts.start}&pageSize=${opts.pageSize}&sort=${encodeURIComponent(opts.sort)}`;
6027
6319
  } else {
6028
- path42 = `/databases/${db}/queries?start=${opts.start}&pageSize=${opts.pageSize}`;
6320
+ path44 = `/databases/${db}/queries?start=${opts.start}&pageSize=${opts.pageSize}`;
6029
6321
  }
6030
6322
  if (opts.query) {
6031
- path42 += `&query=${encodeURIComponent(opts.query)}`;
6323
+ path44 += `&query=${encodeURIComponent(opts.query)}`;
6032
6324
  }
6033
- return path42;
6325
+ return path44;
6034
6326
  }
6035
6327
 
6036
6328
  // src/commands/ravendb/fetchAllPages.ts
@@ -6039,7 +6331,7 @@ async function fetchAllPages(connection, opts) {
6039
6331
  let start3 = 0;
6040
6332
  while (true) {
6041
6333
  const effectivePageSize = opts.limit !== void 0 ? Math.min(opts.pageSize, opts.limit - allResults.length) : opts.pageSize;
6042
- const path42 = buildQueryPath({
6334
+ const path44 = buildQueryPath({
6043
6335
  db: connection.database,
6044
6336
  collection: opts.collection,
6045
6337
  start: start3,
@@ -6047,14 +6339,14 @@ async function fetchAllPages(connection, opts) {
6047
6339
  sort: opts.sort,
6048
6340
  query: opts.query
6049
6341
  });
6050
- const data = await ravenFetch(connection, path42);
6342
+ const data = await ravenFetch(connection, path44);
6051
6343
  const results = data.Results ?? [];
6052
6344
  const totalResults = data.TotalResults ?? 0;
6053
6345
  if (results.length === 0) break;
6054
6346
  allResults.push(...results);
6055
6347
  start3 += results.length;
6056
6348
  process.stderr.write(
6057
- `\r${chalk67.dim(`Fetched ${allResults.length}/${totalResults}`)}`
6349
+ `\r${chalk72.dim(`Fetched ${allResults.length}/${totalResults}`)}`
6058
6350
  );
6059
6351
  if (start3 >= totalResults) break;
6060
6352
  if (opts.limit !== void 0 && allResults.length >= opts.limit) break;
@@ -6069,7 +6361,7 @@ async function fetchAllPages(connection, opts) {
6069
6361
  async function ravendbQuery(connectionName, collection, options2) {
6070
6362
  const resolved = resolveArgs(connectionName, collection);
6071
6363
  if (!resolved.collection && !options2.query) {
6072
- console.error(chalk68.red("Provide a collection name or --query filter."));
6364
+ console.error(chalk73.red("Provide a collection name or --query filter."));
6073
6365
  process.exit(1);
6074
6366
  }
6075
6367
  const { collection: col } = resolved;
@@ -6101,10 +6393,10 @@ function registerRavendb(program2) {
6101
6393
 
6102
6394
  // src/commands/refactor/check/index.ts
6103
6395
  import { spawn as spawn3 } from "child_process";
6104
- import * as path25 from "path";
6396
+ import * as path27 from "path";
6105
6397
 
6106
6398
  // src/commands/refactor/logViolations.ts
6107
- import chalk69 from "chalk";
6399
+ import chalk74 from "chalk";
6108
6400
  var DEFAULT_MAX_LINES = 100;
6109
6401
  function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
6110
6402
  if (violations.length === 0) {
@@ -6113,43 +6405,43 @@ function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
6113
6405
  }
6114
6406
  return;
6115
6407
  }
6116
- console.error(chalk69.red(`
6408
+ console.error(chalk74.red(`
6117
6409
  Refactor check failed:
6118
6410
  `));
6119
- console.error(chalk69.red(` The following files exceed ${maxLines} lines:
6411
+ console.error(chalk74.red(` The following files exceed ${maxLines} lines:
6120
6412
  `));
6121
6413
  for (const violation of violations) {
6122
- console.error(chalk69.red(` ${violation.file} (${violation.lines} lines)`));
6414
+ console.error(chalk74.red(` ${violation.file} (${violation.lines} lines)`));
6123
6415
  }
6124
6416
  console.error(
6125
- chalk69.yellow(
6417
+ chalk74.yellow(
6126
6418
  `
6127
6419
  Each file needs to be sensibly refactored, or if there is no sensible
6128
6420
  way to refactor it, ignore it with:
6129
6421
  `
6130
6422
  )
6131
6423
  );
6132
- console.error(chalk69.gray(` assist refactor ignore <file>
6424
+ console.error(chalk74.gray(` assist refactor ignore <file>
6133
6425
  `));
6134
6426
  if (process.env.CLAUDECODE) {
6135
- console.error(chalk69.cyan(`
6427
+ console.error(chalk74.cyan(`
6136
6428
  ## Extracting Code to New Files
6137
6429
  `));
6138
6430
  console.error(
6139
- chalk69.cyan(
6431
+ chalk74.cyan(
6140
6432
  ` When extracting logic from one file to another, consider where the extracted code belongs:
6141
6433
  `
6142
6434
  )
6143
6435
  );
6144
6436
  console.error(
6145
- chalk69.cyan(
6437
+ chalk74.cyan(
6146
6438
  ` 1. Keep related logic together: If the extracted code is tightly coupled to the
6147
6439
  original file's domain, create a new folder containing both the original and extracted files.
6148
6440
  `
6149
6441
  )
6150
6442
  );
6151
6443
  console.error(
6152
- chalk69.cyan(
6444
+ chalk74.cyan(
6153
6445
  ` 2. Share common utilities: If the extracted code can be reused across multiple
6154
6446
  domains, move it to a common/shared folder.
6155
6447
  `
@@ -6159,7 +6451,7 @@ Refactor check failed:
6159
6451
  }
6160
6452
 
6161
6453
  // src/commands/refactor/check/getViolations/index.ts
6162
- import { execSync as execSync31 } from "child_process";
6454
+ import { execSync as execSync33 } from "child_process";
6163
6455
  import fs16 from "fs";
6164
6456
  import { minimatch as minimatch4 } from "minimatch";
6165
6457
 
@@ -6209,7 +6501,7 @@ function getGitFiles(options2) {
6209
6501
  }
6210
6502
  const files = /* @__PURE__ */ new Set();
6211
6503
  if (options2.staged || options2.modified) {
6212
- const staged = execSync31("git diff --cached --name-only", {
6504
+ const staged = execSync33("git diff --cached --name-only", {
6213
6505
  encoding: "utf-8"
6214
6506
  });
6215
6507
  for (const file of staged.trim().split("\n").filter(Boolean)) {
@@ -6217,7 +6509,7 @@ function getGitFiles(options2) {
6217
6509
  }
6218
6510
  }
6219
6511
  if (options2.unstaged || options2.modified) {
6220
- const unstaged = execSync31("git diff --name-only", { encoding: "utf-8" });
6512
+ const unstaged = execSync33("git diff --name-only", { encoding: "utf-8" });
6221
6513
  for (const file of unstaged.trim().split("\n").filter(Boolean)) {
6222
6514
  files.add(file);
6223
6515
  }
@@ -6278,7 +6570,7 @@ ${failed.length} verify script(s) failed:`);
6278
6570
  async function runVerifyQuietly() {
6279
6571
  const result = findPackageJsonWithVerifyScripts(process.cwd());
6280
6572
  if (!result) return true;
6281
- const packageDir = path25.dirname(result.packageJsonPath);
6573
+ const packageDir = path27.dirname(result.packageJsonPath);
6282
6574
  const results = await Promise.all(
6283
6575
  result.verifyScripts.map((script) => runScript(script, packageDir))
6284
6576
  );
@@ -6305,11 +6597,11 @@ async function check(pattern2, options2) {
6305
6597
 
6306
6598
  // src/commands/refactor/ignore.ts
6307
6599
  import fs17 from "fs";
6308
- import chalk70 from "chalk";
6600
+ import chalk75 from "chalk";
6309
6601
  var REFACTOR_YML_PATH2 = "refactor.yml";
6310
6602
  function ignore(file) {
6311
6603
  if (!fs17.existsSync(file)) {
6312
- console.error(chalk70.red(`Error: File does not exist: ${file}`));
6604
+ console.error(chalk75.red(`Error: File does not exist: ${file}`));
6313
6605
  process.exit(1);
6314
6606
  }
6315
6607
  const content = fs17.readFileSync(file, "utf-8");
@@ -6325,43 +6617,43 @@ function ignore(file) {
6325
6617
  fs17.writeFileSync(REFACTOR_YML_PATH2, entry);
6326
6618
  }
6327
6619
  console.log(
6328
- chalk70.green(
6620
+ chalk75.green(
6329
6621
  `Added ${file} to refactor ignore list (max ${maxLines} lines)`
6330
6622
  )
6331
6623
  );
6332
6624
  }
6333
6625
 
6334
6626
  // src/commands/refactor/rename/index.ts
6335
- import path26 from "path";
6336
- import chalk71 from "chalk";
6627
+ import path28 from "path";
6628
+ import chalk76 from "chalk";
6337
6629
  import { Project as Project2 } from "ts-morph";
6338
6630
  async function rename(source, destination, options2 = {}) {
6339
- const sourcePath = path26.resolve(source);
6340
- const destPath = path26.resolve(destination);
6631
+ const sourcePath = path28.resolve(source);
6632
+ const destPath = path28.resolve(destination);
6341
6633
  const cwd = process.cwd();
6342
- const relSource = path26.relative(cwd, sourcePath);
6343
- const relDest = path26.relative(cwd, destPath);
6634
+ const relSource = path28.relative(cwd, sourcePath);
6635
+ const relDest = path28.relative(cwd, destPath);
6344
6636
  const project = new Project2({
6345
- tsConfigFilePath: path26.resolve("tsconfig.json")
6637
+ tsConfigFilePath: path28.resolve("tsconfig.json")
6346
6638
  });
6347
6639
  const sourceFile = project.getSourceFile(sourcePath);
6348
6640
  if (!sourceFile) {
6349
- console.log(chalk71.red(`File not found in project: ${source}`));
6641
+ console.log(chalk76.red(`File not found in project: ${source}`));
6350
6642
  process.exit(1);
6351
6643
  }
6352
- console.log(chalk71.bold(`Rename: ${relSource} \u2192 ${relDest}`));
6644
+ console.log(chalk76.bold(`Rename: ${relSource} \u2192 ${relDest}`));
6353
6645
  if (options2.apply) {
6354
6646
  sourceFile.move(destPath);
6355
6647
  await project.save();
6356
- console.log(chalk71.green("Done"));
6648
+ console.log(chalk76.green("Done"));
6357
6649
  } else {
6358
- console.log(chalk71.dim("Dry run. Use --apply to execute."));
6650
+ console.log(chalk76.dim("Dry run. Use --apply to execute."));
6359
6651
  }
6360
6652
  }
6361
6653
 
6362
6654
  // src/commands/refactor/renameSymbol/index.ts
6363
- import path28 from "path";
6364
- import chalk72 from "chalk";
6655
+ import path30 from "path";
6656
+ import chalk77 from "chalk";
6365
6657
  import { Project as Project3 } from "ts-morph";
6366
6658
 
6367
6659
  // src/commands/refactor/renameSymbol/findSymbol.ts
@@ -6389,12 +6681,12 @@ function findSymbol(sourceFile, symbolName) {
6389
6681
  }
6390
6682
 
6391
6683
  // src/commands/refactor/renameSymbol/groupReferences.ts
6392
- import path27 from "path";
6684
+ import path29 from "path";
6393
6685
  function groupReferences(symbol, cwd) {
6394
6686
  const refs = symbol.findReferencesAsNodes();
6395
6687
  const grouped = /* @__PURE__ */ new Map();
6396
6688
  for (const ref of refs) {
6397
- const refFile = path27.relative(cwd, ref.getSourceFile().getFilePath());
6689
+ const refFile = path29.relative(cwd, ref.getSourceFile().getFilePath());
6398
6690
  const lines = grouped.get(refFile) ?? [];
6399
6691
  if (!grouped.has(refFile)) grouped.set(refFile, lines);
6400
6692
  lines.push(ref.getStartLineNumber());
@@ -6404,47 +6696,47 @@ function groupReferences(symbol, cwd) {
6404
6696
 
6405
6697
  // src/commands/refactor/renameSymbol/index.ts
6406
6698
  async function renameSymbol(file, oldName, newName, options2 = {}) {
6407
- const filePath = path28.resolve(file);
6408
- const tsConfigPath = path28.resolve("tsconfig.json");
6699
+ const filePath = path30.resolve(file);
6700
+ const tsConfigPath = path30.resolve("tsconfig.json");
6409
6701
  const cwd = process.cwd();
6410
6702
  const project = new Project3({ tsConfigFilePath: tsConfigPath });
6411
6703
  const sourceFile = project.getSourceFile(filePath);
6412
6704
  if (!sourceFile) {
6413
- console.log(chalk72.red(`File not found in project: ${file}`));
6705
+ console.log(chalk77.red(`File not found in project: ${file}`));
6414
6706
  process.exit(1);
6415
6707
  }
6416
6708
  const symbol = findSymbol(sourceFile, oldName);
6417
6709
  if (!symbol) {
6418
- console.log(chalk72.red(`Symbol "${oldName}" not found in ${file}`));
6710
+ console.log(chalk77.red(`Symbol "${oldName}" not found in ${file}`));
6419
6711
  process.exit(1);
6420
6712
  }
6421
6713
  const grouped = groupReferences(symbol, cwd);
6422
6714
  const totalRefs = [...grouped.values()].reduce((s, l) => s + l.length, 0);
6423
6715
  console.log(
6424
- chalk72.bold(`Rename: ${oldName} \u2192 ${newName} (${totalRefs} references)
6716
+ chalk77.bold(`Rename: ${oldName} \u2192 ${newName} (${totalRefs} references)
6425
6717
  `)
6426
6718
  );
6427
6719
  for (const [refFile, lines] of grouped) {
6428
6720
  console.log(
6429
- ` ${chalk72.dim(refFile)}: lines ${chalk72.cyan(lines.join(", "))}`
6721
+ ` ${chalk77.dim(refFile)}: lines ${chalk77.cyan(lines.join(", "))}`
6430
6722
  );
6431
6723
  }
6432
6724
  if (options2.apply) {
6433
6725
  symbol.rename(newName);
6434
6726
  await project.save();
6435
- console.log(chalk72.green(`
6727
+ console.log(chalk77.green(`
6436
6728
  Renamed ${oldName} \u2192 ${newName}`));
6437
6729
  } else {
6438
- console.log(chalk72.dim("\nDry run. Use --apply to execute."));
6730
+ console.log(chalk77.dim("\nDry run. Use --apply to execute."));
6439
6731
  }
6440
6732
  }
6441
6733
 
6442
6734
  // src/commands/refactor/restructure/index.ts
6443
- import path37 from "path";
6444
- import chalk75 from "chalk";
6735
+ import path39 from "path";
6736
+ import chalk80 from "chalk";
6445
6737
 
6446
6738
  // src/commands/refactor/restructure/buildImportGraph/index.ts
6447
- import path29 from "path";
6739
+ import path31 from "path";
6448
6740
  import ts7 from "typescript";
6449
6741
 
6450
6742
  // src/commands/refactor/restructure/buildImportGraph/getImportSpecifiers.ts
@@ -6471,7 +6763,7 @@ function loadParsedConfig(tsConfigPath) {
6471
6763
  return ts7.parseJsonConfigFileContent(
6472
6764
  configFile.config,
6473
6765
  ts7.sys,
6474
- path29.dirname(tsConfigPath)
6766
+ path31.dirname(tsConfigPath)
6475
6767
  );
6476
6768
  }
6477
6769
  function addToSetMap(map, key, value) {
@@ -6487,7 +6779,7 @@ function resolveImport(specifier, filePath, options2) {
6487
6779
  const resolved = ts7.resolveModuleName(specifier, filePath, options2, ts7.sys);
6488
6780
  const resolvedPath = resolved.resolvedModule?.resolvedFileName;
6489
6781
  if (!resolvedPath || resolvedPath.includes("node_modules")) return null;
6490
- return path29.resolve(resolvedPath);
6782
+ return path31.resolve(resolvedPath);
6491
6783
  }
6492
6784
  function buildImportGraph(candidateFiles, tsConfigPath) {
6493
6785
  const parsed = loadParsedConfig(tsConfigPath);
@@ -6496,7 +6788,7 @@ function buildImportGraph(candidateFiles, tsConfigPath) {
6496
6788
  const importedBy = /* @__PURE__ */ new Map();
6497
6789
  const imports = /* @__PURE__ */ new Map();
6498
6790
  for (const sourceFile of program2.getSourceFiles()) {
6499
- const filePath = path29.resolve(sourceFile.fileName);
6791
+ const filePath = path31.resolve(sourceFile.fileName);
6500
6792
  if (filePath.includes("node_modules")) continue;
6501
6793
  for (const specifier of getImportSpecifiers(sourceFile)) {
6502
6794
  const absTarget = resolveImport(specifier, filePath, parsed.options);
@@ -6510,12 +6802,12 @@ function buildImportGraph(candidateFiles, tsConfigPath) {
6510
6802
  }
6511
6803
 
6512
6804
  // src/commands/refactor/restructure/clusterDirectories.ts
6513
- import path30 from "path";
6805
+ import path32 from "path";
6514
6806
  function clusterDirectories(graph) {
6515
6807
  const dirImportedBy = /* @__PURE__ */ new Map();
6516
6808
  for (const edge of graph.edges) {
6517
- const sourceDir = path30.dirname(edge.source);
6518
- const targetDir = path30.dirname(edge.target);
6809
+ const sourceDir = path32.dirname(edge.source);
6810
+ const targetDir = path32.dirname(edge.target);
6519
6811
  if (sourceDir === targetDir) continue;
6520
6812
  if (!graph.files.has(edge.target)) continue;
6521
6813
  const existing = dirImportedBy.get(targetDir) ?? /* @__PURE__ */ new Set();
@@ -6543,20 +6835,20 @@ function clusterDirectories(graph) {
6543
6835
  return clusters;
6544
6836
  }
6545
6837
  function isAncestor(ancestor, descendant) {
6546
- const rel = path30.relative(ancestor, descendant);
6838
+ const rel = path32.relative(ancestor, descendant);
6547
6839
  return !rel.startsWith("..") && rel !== "";
6548
6840
  }
6549
6841
 
6550
6842
  // src/commands/refactor/restructure/clusterFiles.ts
6551
- import path31 from "path";
6843
+ import path33 from "path";
6552
6844
  function findRootParent(file, importedBy, visited) {
6553
6845
  const importers = importedBy.get(file);
6554
6846
  if (!importers || importers.size !== 1) return file;
6555
6847
  const parent = [...importers][0];
6556
- const parentDir = path31.dirname(parent);
6557
- const fileDir = path31.dirname(file);
6848
+ const parentDir = path33.dirname(parent);
6849
+ const fileDir = path33.dirname(file);
6558
6850
  if (parentDir !== fileDir) return file;
6559
- if (path31.basename(parent, path31.extname(parent)) === "index") return file;
6851
+ if (path33.basename(parent, path33.extname(parent)) === "index") return file;
6560
6852
  if (visited.has(parent)) return file;
6561
6853
  visited.add(parent);
6562
6854
  return findRootParent(parent, importedBy, visited);
@@ -6564,16 +6856,16 @@ function findRootParent(file, importedBy, visited) {
6564
6856
  function clusterFiles(graph) {
6565
6857
  const clusters = /* @__PURE__ */ new Map();
6566
6858
  for (const file of graph.files) {
6567
- const basename7 = path31.basename(file, path31.extname(file));
6859
+ const basename7 = path33.basename(file, path33.extname(file));
6568
6860
  if (basename7 === "index") continue;
6569
6861
  const importers = graph.importedBy.get(file);
6570
6862
  if (!importers || importers.size !== 1) continue;
6571
6863
  const parent = [...importers][0];
6572
6864
  if (!graph.files.has(parent)) continue;
6573
- const parentDir = path31.dirname(parent);
6574
- const fileDir = path31.dirname(file);
6865
+ const parentDir = path33.dirname(parent);
6866
+ const fileDir = path33.dirname(file);
6575
6867
  if (parentDir !== fileDir) continue;
6576
- const parentBasename = path31.basename(parent, path31.extname(parent));
6868
+ const parentBasename = path33.basename(parent, path33.extname(parent));
6577
6869
  if (parentBasename === "index") continue;
6578
6870
  const root = findRootParent(parent, graph.importedBy, /* @__PURE__ */ new Set([file]));
6579
6871
  if (!root || root === file) continue;
@@ -6585,7 +6877,7 @@ function clusterFiles(graph) {
6585
6877
  }
6586
6878
 
6587
6879
  // src/commands/refactor/restructure/computeRewrites/index.ts
6588
- import path32 from "path";
6880
+ import path34 from "path";
6589
6881
 
6590
6882
  // src/commands/refactor/restructure/computeRewrites/applyRewrites.ts
6591
6883
  import fs18 from "fs";
@@ -6594,7 +6886,7 @@ function getOrCreateList(map, key) {
6594
6886
  if (!map.has(key)) map.set(key, list4);
6595
6887
  return list4;
6596
6888
  }
6597
- function groupByFile(rewrites) {
6889
+ function groupByFile2(rewrites) {
6598
6890
  const grouped = /* @__PURE__ */ new Map();
6599
6891
  for (const rewrite of rewrites) {
6600
6892
  getOrCreateList(grouped, rewrite.file).push(rewrite);
@@ -6615,7 +6907,7 @@ function applyFileRewrites(file, fileRewrites) {
6615
6907
  }
6616
6908
  function applyRewrites(rewrites) {
6617
6909
  const updatedContents = /* @__PURE__ */ new Map();
6618
- for (const [file, fileRewrites] of groupByFile(rewrites)) {
6910
+ for (const [file, fileRewrites] of groupByFile2(rewrites)) {
6619
6911
  updatedContents.set(file, applyFileRewrites(file, fileRewrites));
6620
6912
  }
6621
6913
  return updatedContents;
@@ -6639,7 +6931,7 @@ function normalizeSpecifier(rel) {
6639
6931
  );
6640
6932
  }
6641
6933
  function computeSpecifier(fromFile, toFile) {
6642
- return normalizeSpecifier(path32.relative(path32.dirname(fromFile), toFile));
6934
+ return normalizeSpecifier(path34.relative(path34.dirname(fromFile), toFile));
6643
6935
  }
6644
6936
  function isAffected(edge, moveMap) {
6645
6937
  return moveMap.has(edge.target) || moveMap.has(edge.source);
@@ -6683,51 +6975,51 @@ function computeRewrites(moves, edges, allProjectFiles) {
6683
6975
  }
6684
6976
 
6685
6977
  // src/commands/refactor/restructure/displayPlan.ts
6686
- import path33 from "path";
6687
- import chalk73 from "chalk";
6978
+ import path35 from "path";
6979
+ import chalk78 from "chalk";
6688
6980
  function relPath(filePath) {
6689
- return path33.relative(process.cwd(), filePath);
6981
+ return path35.relative(process.cwd(), filePath);
6690
6982
  }
6691
6983
  function displayMoves(plan) {
6692
6984
  if (plan.moves.length === 0) return;
6693
- console.log(chalk73.bold("\nFile moves:"));
6985
+ console.log(chalk78.bold("\nFile moves:"));
6694
6986
  for (const move of plan.moves) {
6695
6987
  console.log(
6696
- ` ${chalk73.red(relPath(move.from))} \u2192 ${chalk73.green(relPath(move.to))}`
6988
+ ` ${chalk78.red(relPath(move.from))} \u2192 ${chalk78.green(relPath(move.to))}`
6697
6989
  );
6698
- console.log(chalk73.dim(` ${move.reason}`));
6990
+ console.log(chalk78.dim(` ${move.reason}`));
6699
6991
  }
6700
6992
  }
6701
6993
  function displayRewrites(rewrites) {
6702
6994
  if (rewrites.length === 0) return;
6703
6995
  const affectedFiles = new Set(rewrites.map((r) => r.file));
6704
- console.log(chalk73.bold(`
6996
+ console.log(chalk78.bold(`
6705
6997
  Import rewrites (${affectedFiles.size} files):`));
6706
6998
  for (const file of affectedFiles) {
6707
- console.log(` ${chalk73.cyan(relPath(file))}:`);
6999
+ console.log(` ${chalk78.cyan(relPath(file))}:`);
6708
7000
  for (const { oldSpecifier, newSpecifier } of rewrites.filter(
6709
7001
  (r) => r.file === file
6710
7002
  )) {
6711
7003
  console.log(
6712
- ` ${chalk73.red(`"${oldSpecifier}"`)} \u2192 ${chalk73.green(`"${newSpecifier}"`)}`
7004
+ ` ${chalk78.red(`"${oldSpecifier}"`)} \u2192 ${chalk78.green(`"${newSpecifier}"`)}`
6713
7005
  );
6714
7006
  }
6715
7007
  }
6716
7008
  }
6717
7009
  function displayPlan(plan) {
6718
7010
  if (plan.warnings.length > 0) {
6719
- console.log(chalk73.yellow("\nWarnings:"));
6720
- for (const w of plan.warnings) console.log(chalk73.yellow(` ${w}`));
7011
+ console.log(chalk78.yellow("\nWarnings:"));
7012
+ for (const w of plan.warnings) console.log(chalk78.yellow(` ${w}`));
6721
7013
  }
6722
7014
  if (plan.newDirectories.length > 0) {
6723
- console.log(chalk73.bold("\nNew directories:"));
7015
+ console.log(chalk78.bold("\nNew directories:"));
6724
7016
  for (const dir of plan.newDirectories)
6725
- console.log(chalk73.green(` ${dir}/`));
7017
+ console.log(chalk78.green(` ${dir}/`));
6726
7018
  }
6727
7019
  displayMoves(plan);
6728
7020
  displayRewrites(plan.rewrites);
6729
7021
  console.log(
6730
- chalk73.dim(
7022
+ chalk78.dim(
6731
7023
  `
6732
7024
  Summary: ${plan.moves.length} file(s) moved, ${plan.rewrites.length} imports rewritten`
6733
7025
  )
@@ -6736,33 +7028,33 @@ Summary: ${plan.moves.length} file(s) moved, ${plan.rewrites.length} imports rew
6736
7028
 
6737
7029
  // src/commands/refactor/restructure/executePlan.ts
6738
7030
  import fs19 from "fs";
6739
- import path34 from "path";
6740
- import chalk74 from "chalk";
7031
+ import path36 from "path";
7032
+ import chalk79 from "chalk";
6741
7033
  function executePlan(plan) {
6742
7034
  const updatedContents = applyRewrites(plan.rewrites);
6743
7035
  for (const [file, content] of updatedContents) {
6744
7036
  fs19.writeFileSync(file, content, "utf-8");
6745
7037
  console.log(
6746
- chalk74.cyan(` Rewrote imports in ${path34.relative(process.cwd(), file)}`)
7038
+ chalk79.cyan(` Rewrote imports in ${path36.relative(process.cwd(), file)}`)
6747
7039
  );
6748
7040
  }
6749
7041
  for (const dir of plan.newDirectories) {
6750
7042
  fs19.mkdirSync(dir, { recursive: true });
6751
- console.log(chalk74.green(` Created ${path34.relative(process.cwd(), dir)}/`));
7043
+ console.log(chalk79.green(` Created ${path36.relative(process.cwd(), dir)}/`));
6752
7044
  }
6753
7045
  for (const move of plan.moves) {
6754
- const targetDir = path34.dirname(move.to);
7046
+ const targetDir = path36.dirname(move.to);
6755
7047
  if (!fs19.existsSync(targetDir)) {
6756
7048
  fs19.mkdirSync(targetDir, { recursive: true });
6757
7049
  }
6758
7050
  fs19.renameSync(move.from, move.to);
6759
7051
  console.log(
6760
- chalk74.white(
6761
- ` Moved ${path34.relative(process.cwd(), move.from)} \u2192 ${path34.relative(process.cwd(), move.to)}`
7052
+ chalk79.white(
7053
+ ` Moved ${path36.relative(process.cwd(), move.from)} \u2192 ${path36.relative(process.cwd(), move.to)}`
6762
7054
  )
6763
7055
  );
6764
7056
  }
6765
- removeEmptyDirectories(plan.moves.map((m) => path34.dirname(m.from)));
7057
+ removeEmptyDirectories(plan.moves.map((m) => path36.dirname(m.from)));
6766
7058
  }
6767
7059
  function removeEmptyDirectories(dirs) {
6768
7060
  const unique = [...new Set(dirs)];
@@ -6772,8 +7064,8 @@ function removeEmptyDirectories(dirs) {
6772
7064
  if (entries.length === 0) {
6773
7065
  fs19.rmdirSync(dir);
6774
7066
  console.log(
6775
- chalk74.dim(
6776
- ` Removed empty directory ${path34.relative(process.cwd(), dir)}`
7067
+ chalk79.dim(
7068
+ ` Removed empty directory ${path36.relative(process.cwd(), dir)}`
6777
7069
  )
6778
7070
  );
6779
7071
  }
@@ -6781,7 +7073,7 @@ function removeEmptyDirectories(dirs) {
6781
7073
  }
6782
7074
 
6783
7075
  // src/commands/refactor/restructure/planFileMoves/index.ts
6784
- import path36 from "path";
7076
+ import path38 from "path";
6785
7077
 
6786
7078
  // src/commands/refactor/restructure/planFileMoves/shared.ts
6787
7079
  import fs20 from "fs";
@@ -6796,9 +7088,9 @@ function checkDirConflict(result, label2, dir) {
6796
7088
 
6797
7089
  // src/commands/refactor/restructure/planFileMoves/planDirectoryMoves.ts
6798
7090
  import fs21 from "fs";
6799
- import path35 from "path";
7091
+ import path37 from "path";
6800
7092
  function collectEntry(results, dir, entry) {
6801
- const full = path35.join(dir, entry.name);
7093
+ const full = path37.join(dir, entry.name);
6802
7094
  const items = entry.isDirectory() ? listFilesRecursive(full) : [full];
6803
7095
  results.push(...items);
6804
7096
  }
@@ -6812,15 +7104,15 @@ function listFilesRecursive(dir) {
6812
7104
  }
6813
7105
  function addDirectoryFileMoves(moves, childDir, newLocation, reason) {
6814
7106
  for (const file of listFilesRecursive(childDir)) {
6815
- const rel = path35.relative(childDir, file);
6816
- moves.push({ from: file, to: path35.join(newLocation, rel), reason });
7107
+ const rel = path37.relative(childDir, file);
7108
+ moves.push({ from: file, to: path37.join(newLocation, rel), reason });
6817
7109
  }
6818
7110
  }
6819
7111
  function resolveChildDest(parentDir, childDir) {
6820
- return path35.join(parentDir, path35.basename(childDir));
7112
+ return path37.join(parentDir, path37.basename(childDir));
6821
7113
  }
6822
7114
  function childMoveReason(parentDir) {
6823
- return `Directory only imported from ${path35.basename(parentDir)}/`;
7115
+ return `Directory only imported from ${path37.basename(parentDir)}/`;
6824
7116
  }
6825
7117
  function registerDirectoryMove(result, childDir, dest, parentDir) {
6826
7118
  result.directories.push(dest);
@@ -6845,7 +7137,7 @@ function planDirectoryMoves(clusters) {
6845
7137
 
6846
7138
  // src/commands/refactor/restructure/planFileMoves/index.ts
6847
7139
  function childMoveData(child, newDir, parentBase) {
6848
- const to = path36.join(newDir, path36.basename(child));
7140
+ const to = path38.join(newDir, path38.basename(child));
6849
7141
  return { from: child, to, reason: `Only imported by ${parentBase}` };
6850
7142
  }
6851
7143
  function addChildMoves(moves, children, newDir, parentBase) {
@@ -6853,15 +7145,15 @@ function addChildMoves(moves, children, newDir, parentBase) {
6853
7145
  moves.push(childMoveData(child, newDir, parentBase));
6854
7146
  }
6855
7147
  function getBaseName(filePath) {
6856
- return path36.basename(filePath, path36.extname(filePath));
7148
+ return path38.basename(filePath, path38.extname(filePath));
6857
7149
  }
6858
7150
  function resolveClusterDir(parent) {
6859
- return path36.join(path36.dirname(parent), getBaseName(parent));
7151
+ return path38.join(path38.dirname(parent), getBaseName(parent));
6860
7152
  }
6861
7153
  function createParentMove(parent, newDir) {
6862
7154
  return {
6863
7155
  from: parent,
6864
- to: path36.join(newDir, `index${path36.extname(parent)}`),
7156
+ to: path38.join(newDir, `index${path38.extname(parent)}`),
6865
7157
  reason: `Main module of new ${getBaseName(parent)}/ directory`
6866
7158
  };
6867
7159
  }
@@ -6885,7 +7177,7 @@ function planFileMoves(clusters) {
6885
7177
 
6886
7178
  // src/commands/refactor/restructure/index.ts
6887
7179
  function buildPlan(candidateFiles, tsConfigPath) {
6888
- const candidates = new Set(candidateFiles.map((f) => path37.resolve(f)));
7180
+ const candidates = new Set(candidateFiles.map((f) => path39.resolve(f)));
6889
7181
  const graph = buildImportGraph(candidates, tsConfigPath);
6890
7182
  const allProjectFiles = /* @__PURE__ */ new Set([
6891
7183
  ...graph.importedBy.keys(),
@@ -6905,22 +7197,22 @@ async function restructure(pattern2, options2 = {}) {
6905
7197
  const targetPattern = pattern2 ?? "src";
6906
7198
  const files = findSourceFiles2(targetPattern);
6907
7199
  if (files.length === 0) {
6908
- console.log(chalk75.yellow("No files found matching pattern"));
7200
+ console.log(chalk80.yellow("No files found matching pattern"));
6909
7201
  return;
6910
7202
  }
6911
- const tsConfigPath = path37.resolve("tsconfig.json");
7203
+ const tsConfigPath = path39.resolve("tsconfig.json");
6912
7204
  const plan = buildPlan(files, tsConfigPath);
6913
7205
  if (plan.moves.length === 0) {
6914
- console.log(chalk75.green("No restructuring needed"));
7206
+ console.log(chalk80.green("No restructuring needed"));
6915
7207
  return;
6916
7208
  }
6917
7209
  displayPlan(plan);
6918
7210
  if (options2.apply) {
6919
- console.log(chalk75.bold("\nApplying changes..."));
7211
+ console.log(chalk80.bold("\nApplying changes..."));
6920
7212
  executePlan(plan);
6921
- console.log(chalk75.green("\nRestructuring complete"));
7213
+ console.log(chalk80.green("\nRestructuring complete"));
6922
7214
  } else {
6923
- console.log(chalk75.dim("\nDry run. Use --apply to execute."));
7215
+ console.log(chalk80.dim("\nDry run. Use --apply to execute."));
6924
7216
  }
6925
7217
  }
6926
7218
 
@@ -6948,8 +7240,8 @@ function registerRefactor(program2) {
6948
7240
  }
6949
7241
 
6950
7242
  // src/commands/transcript/shared.ts
6951
- import { existsSync as existsSync25, readdirSync as readdirSync3, statSync as statSync2 } from "fs";
6952
- import { basename as basename4, join as join22, relative } from "path";
7243
+ import { existsSync as existsSync27, readdirSync as readdirSync5, statSync as statSync2 } from "fs";
7244
+ import { basename as basename4, join as join24, relative } from "path";
6953
7245
  import * as readline2 from "readline";
6954
7246
  var DATE_PREFIX_REGEX = /^\d{4}-\d{2}-\d{2}/;
6955
7247
  function getDatePrefix(daysOffset = 0) {
@@ -6964,10 +7256,10 @@ function isValidDatePrefix(filename) {
6964
7256
  return DATE_PREFIX_REGEX.test(filename);
6965
7257
  }
6966
7258
  function collectFiles(dir, extension) {
6967
- if (!existsSync25(dir)) return [];
7259
+ if (!existsSync27(dir)) return [];
6968
7260
  const results = [];
6969
- for (const entry of readdirSync3(dir)) {
6970
- const fullPath = join22(dir, entry);
7261
+ for (const entry of readdirSync5(dir)) {
7262
+ const fullPath = join24(dir, entry);
6971
7263
  if (statSync2(fullPath).isDirectory()) {
6972
7264
  results.push(...collectFiles(fullPath, extension));
6973
7265
  } else if (entry.endsWith(extension)) {
@@ -7061,14 +7353,14 @@ async function configure() {
7061
7353
  }
7062
7354
 
7063
7355
  // src/commands/transcript/format/index.ts
7064
- import { existsSync as existsSync27 } from "fs";
7356
+ import { existsSync as existsSync29 } from "fs";
7065
7357
 
7066
7358
  // src/commands/transcript/format/fixInvalidDatePrefixes/index.ts
7067
- import { dirname as dirname16, join as join24 } from "path";
7359
+ import { dirname as dirname18, join as join26 } from "path";
7068
7360
 
7069
7361
  // src/commands/transcript/format/fixInvalidDatePrefixes/promptForDateFix.ts
7070
7362
  import { renameSync } from "fs";
7071
- import { join as join23 } from "path";
7363
+ import { join as join25 } from "path";
7072
7364
  async function resolveDate(rl, choice) {
7073
7365
  if (choice === "1") return getDatePrefix(0);
7074
7366
  if (choice === "2") return getDatePrefix(-1);
@@ -7083,7 +7375,7 @@ async function resolveDate(rl, choice) {
7083
7375
  }
7084
7376
  function renameWithPrefix(vttDir, vttFile, prefix2) {
7085
7377
  const newFilename = `${prefix2}.${vttFile}`;
7086
- renameSync(join23(vttDir, vttFile), join23(vttDir, newFilename));
7378
+ renameSync(join25(vttDir, vttFile), join25(vttDir, newFilename));
7087
7379
  console.log(`Renamed to: ${newFilename}`);
7088
7380
  return newFilename;
7089
7381
  }
@@ -7114,15 +7406,15 @@ async function fixInvalidDatePrefixes(vttFiles) {
7114
7406
  for (let i = 0; i < vttFiles.length; i++) {
7115
7407
  const vttFile = vttFiles[i];
7116
7408
  if (!isValidDatePrefix(vttFile.filename)) {
7117
- const vttFileDir = dirname16(vttFile.absolutePath);
7409
+ const vttFileDir = dirname18(vttFile.absolutePath);
7118
7410
  const newFilename = await promptForDateFix(vttFile.filename, vttFileDir);
7119
7411
  if (newFilename) {
7120
- const newRelativePath = join24(
7121
- dirname16(vttFile.relativePath),
7412
+ const newRelativePath = join26(
7413
+ dirname18(vttFile.relativePath),
7122
7414
  newFilename
7123
7415
  );
7124
7416
  vttFiles[i] = {
7125
- absolutePath: join24(vttFileDir, newFilename),
7417
+ absolutePath: join26(vttFileDir, newFilename),
7126
7418
  relativePath: newRelativePath,
7127
7419
  filename: newFilename
7128
7420
  };
@@ -7135,8 +7427,8 @@ async function fixInvalidDatePrefixes(vttFiles) {
7135
7427
  }
7136
7428
 
7137
7429
  // src/commands/transcript/format/processVttFile/index.ts
7138
- import { existsSync as existsSync26, mkdirSync as mkdirSync7, readFileSync as readFileSync22, writeFileSync as writeFileSync22 } from "fs";
7139
- import { basename as basename5, dirname as dirname17, join as join25 } from "path";
7430
+ import { existsSync as existsSync28, mkdirSync as mkdirSync7, readFileSync as readFileSync23, writeFileSync as writeFileSync22 } from "fs";
7431
+ import { basename as basename5, dirname as dirname19, join as join27 } from "path";
7140
7432
 
7141
7433
  // src/commands/transcript/cleanText.ts
7142
7434
  function cleanText(text) {
@@ -7346,21 +7638,21 @@ function toMdFilename(vttFilename) {
7346
7638
  return `${basename5(vttFilename, ".vtt").replace(/\s*Transcription\s*/g, " ").trim()}.md`;
7347
7639
  }
7348
7640
  function resolveOutputDir(relativeDir, transcriptsDir) {
7349
- return relativeDir === "." ? transcriptsDir : join25(transcriptsDir, relativeDir);
7641
+ return relativeDir === "." ? transcriptsDir : join27(transcriptsDir, relativeDir);
7350
7642
  }
7351
7643
  function buildOutputPaths(vttFile, transcriptsDir) {
7352
7644
  const mdFile = toMdFilename(vttFile.filename);
7353
- const relativeDir = dirname17(vttFile.relativePath);
7645
+ const relativeDir = dirname19(vttFile.relativePath);
7354
7646
  const outputDir = resolveOutputDir(relativeDir, transcriptsDir);
7355
- const outputPath = join25(outputDir, mdFile);
7647
+ const outputPath = join27(outputDir, mdFile);
7356
7648
  return { outputDir, outputPath, mdFile, relativeDir };
7357
7649
  }
7358
7650
  function logSkipped(relativeDir, mdFile) {
7359
- console.log(`Skipping (already exists): ${join25(relativeDir, mdFile)}`);
7651
+ console.log(`Skipping (already exists): ${join27(relativeDir, mdFile)}`);
7360
7652
  return "skipped";
7361
7653
  }
7362
7654
  function ensureDirectory(dir, label2) {
7363
- if (!existsSync26(dir)) {
7655
+ if (!existsSync28(dir)) {
7364
7656
  mkdirSync7(dir, { recursive: true });
7365
7657
  console.log(`Created ${label2}: ${dir}`);
7366
7658
  }
@@ -7383,7 +7675,7 @@ function logReduction(cueCount, messageCount) {
7383
7675
  }
7384
7676
  function readAndParseCues(inputPath) {
7385
7677
  console.log(`Reading: ${inputPath}`);
7386
- return processCues(readFileSync22(inputPath, "utf-8"));
7678
+ return processCues(readFileSync23(inputPath, "utf-8"));
7387
7679
  }
7388
7680
  function writeFormatted(outputPath, content) {
7389
7681
  writeFileSync22(outputPath, content, "utf-8");
@@ -7396,7 +7688,7 @@ function convertVttToMarkdown(inputPath, outputPath) {
7396
7688
  logReduction(cues.length, chatMessages.length);
7397
7689
  }
7398
7690
  function tryProcessVtt(vttFile, paths) {
7399
- if (existsSync26(paths.outputPath))
7691
+ if (existsSync28(paths.outputPath))
7400
7692
  return logSkipped(paths.relativeDir, paths.mdFile);
7401
7693
  convertVttToMarkdown(vttFile.absolutePath, paths.outputPath);
7402
7694
  return "processed";
@@ -7422,7 +7714,7 @@ function processAllFiles(vttFiles, transcriptsDir) {
7422
7714
  logSummary(counts);
7423
7715
  }
7424
7716
  function requireVttDir(vttDir) {
7425
- if (!existsSync27(vttDir)) {
7717
+ if (!existsSync29(vttDir)) {
7426
7718
  console.error(`VTT directory not found: ${vttDir}`);
7427
7719
  process.exit(1);
7428
7720
  }
@@ -7454,28 +7746,28 @@ async function format() {
7454
7746
  }
7455
7747
 
7456
7748
  // src/commands/transcript/summarise/index.ts
7457
- import { existsSync as existsSync29 } from "fs";
7458
- import { basename as basename6, dirname as dirname19, join as join27, relative as relative2 } from "path";
7749
+ import { existsSync as existsSync31 } from "fs";
7750
+ import { basename as basename6, dirname as dirname21, join as join29, relative as relative2 } from "path";
7459
7751
 
7460
7752
  // src/commands/transcript/summarise/processStagedFile/index.ts
7461
7753
  import {
7462
- existsSync as existsSync28,
7754
+ existsSync as existsSync30,
7463
7755
  mkdirSync as mkdirSync8,
7464
- readFileSync as readFileSync23,
7756
+ readFileSync as readFileSync24,
7465
7757
  renameSync as renameSync2,
7466
7758
  rmSync
7467
7759
  } from "fs";
7468
- import { dirname as dirname18, join as join26 } from "path";
7760
+ import { dirname as dirname20, join as join28 } from "path";
7469
7761
 
7470
7762
  // src/commands/transcript/summarise/processStagedFile/validateStagedContent.ts
7471
- import chalk76 from "chalk";
7763
+ import chalk81 from "chalk";
7472
7764
  var FULL_TRANSCRIPT_REGEX = /^\[Full Transcript\]\(([^)]+)\)/;
7473
7765
  function validateStagedContent(filename, content) {
7474
7766
  const firstLine = content.split("\n")[0];
7475
7767
  const match = firstLine.match(FULL_TRANSCRIPT_REGEX);
7476
7768
  if (!match) {
7477
7769
  console.error(
7478
- chalk76.red(
7770
+ chalk81.red(
7479
7771
  `Staged file ${filename} missing [Full Transcript](<path>) link on first line.`
7480
7772
  )
7481
7773
  );
@@ -7484,7 +7776,7 @@ function validateStagedContent(filename, content) {
7484
7776
  const contentAfterLink = content.slice(firstLine.length).trim();
7485
7777
  if (!contentAfterLink) {
7486
7778
  console.error(
7487
- chalk76.red(
7779
+ chalk81.red(
7488
7780
  `Staged file ${filename} has no summary content after the transcript link.`
7489
7781
  )
7490
7782
  );
@@ -7494,9 +7786,9 @@ function validateStagedContent(filename, content) {
7494
7786
  }
7495
7787
 
7496
7788
  // src/commands/transcript/summarise/processStagedFile/index.ts
7497
- var STAGING_DIR = join26(process.cwd(), ".assist", "transcript");
7789
+ var STAGING_DIR = join28(process.cwd(), ".assist", "transcript");
7498
7790
  function processStagedFile() {
7499
- if (!existsSync28(STAGING_DIR)) {
7791
+ if (!existsSync30(STAGING_DIR)) {
7500
7792
  return false;
7501
7793
  }
7502
7794
  const stagedFiles = findMdFilesRecursive(STAGING_DIR);
@@ -7505,7 +7797,7 @@ function processStagedFile() {
7505
7797
  }
7506
7798
  const { transcriptsDir, summaryDir } = getTranscriptConfig();
7507
7799
  const stagedFile = stagedFiles[0];
7508
- const content = readFileSync23(stagedFile.absolutePath, "utf-8");
7800
+ const content = readFileSync24(stagedFile.absolutePath, "utf-8");
7509
7801
  validateStagedContent(stagedFile.filename, content);
7510
7802
  const stagedBaseName = getTranscriptBaseName(stagedFile.filename);
7511
7803
  const transcriptFiles = findMdFilesRecursive(transcriptsDir);
@@ -7518,9 +7810,9 @@ function processStagedFile() {
7518
7810
  );
7519
7811
  process.exit(1);
7520
7812
  }
7521
- const destPath = join26(summaryDir, matchingTranscript.relativePath);
7522
- const destDir = dirname18(destPath);
7523
- if (!existsSync28(destDir)) {
7813
+ const destPath = join28(summaryDir, matchingTranscript.relativePath);
7814
+ const destDir = dirname20(destPath);
7815
+ if (!existsSync30(destDir)) {
7524
7816
  mkdirSync8(destDir, { recursive: true });
7525
7817
  }
7526
7818
  renameSync2(stagedFile.absolutePath, destPath);
@@ -7533,8 +7825,8 @@ function processStagedFile() {
7533
7825
 
7534
7826
  // src/commands/transcript/summarise/index.ts
7535
7827
  function buildRelativeKey(relativePath, baseName) {
7536
- const relDir = dirname19(relativePath);
7537
- return relDir === "." ? baseName : join27(relDir, baseName);
7828
+ const relDir = dirname21(relativePath);
7829
+ return relDir === "." ? baseName : join29(relDir, baseName);
7538
7830
  }
7539
7831
  function buildSummaryIndex(summaryDir) {
7540
7832
  const summaryFiles = findMdFilesRecursive(summaryDir);
@@ -7547,7 +7839,7 @@ function buildSummaryIndex(summaryDir) {
7547
7839
  function summarise2() {
7548
7840
  processStagedFile();
7549
7841
  const { transcriptsDir, summaryDir } = getTranscriptConfig();
7550
- if (!existsSync29(transcriptsDir)) {
7842
+ if (!existsSync31(transcriptsDir)) {
7551
7843
  console.log("No transcripts directory found.");
7552
7844
  return;
7553
7845
  }
@@ -7568,8 +7860,8 @@ function summarise2() {
7568
7860
  }
7569
7861
  const next2 = missing[0];
7570
7862
  const outputFilename = `${getTranscriptBaseName(next2.filename)}.md`;
7571
- const outputPath = join27(STAGING_DIR, outputFilename);
7572
- const summaryFileDir = join27(summaryDir, dirname19(next2.relativePath));
7863
+ const outputPath = join29(STAGING_DIR, outputFilename);
7864
+ const summaryFileDir = join29(summaryDir, dirname21(next2.relativePath));
7573
7865
  const relativeTranscriptPath = encodeURI(
7574
7866
  relative2(summaryFileDir, next2.absolutePath).replace(/\\/g, "/")
7575
7867
  );
@@ -7615,50 +7907,50 @@ function registerVerify(program2) {
7615
7907
 
7616
7908
  // src/commands/voice/devices.ts
7617
7909
  import { spawnSync as spawnSync3 } from "child_process";
7618
- import { join as join29 } from "path";
7910
+ import { join as join31 } from "path";
7619
7911
 
7620
7912
  // src/commands/voice/shared.ts
7621
7913
  import { homedir as homedir7 } from "os";
7622
- import { dirname as dirname20, join as join28 } from "path";
7914
+ import { dirname as dirname22, join as join30 } from "path";
7623
7915
  import { fileURLToPath as fileURLToPath6 } from "url";
7624
- var __dirname6 = dirname20(fileURLToPath6(import.meta.url));
7625
- var VOICE_DIR = join28(homedir7(), ".assist", "voice");
7916
+ var __dirname6 = dirname22(fileURLToPath6(import.meta.url));
7917
+ var VOICE_DIR = join30(homedir7(), ".assist", "voice");
7626
7918
  var voicePaths = {
7627
7919
  dir: VOICE_DIR,
7628
- pid: join28(VOICE_DIR, "voice.pid"),
7629
- log: join28(VOICE_DIR, "voice.log"),
7630
- venv: join28(VOICE_DIR, ".venv"),
7631
- lock: join28(VOICE_DIR, "voice.lock")
7920
+ pid: join30(VOICE_DIR, "voice.pid"),
7921
+ log: join30(VOICE_DIR, "voice.log"),
7922
+ venv: join30(VOICE_DIR, ".venv"),
7923
+ lock: join30(VOICE_DIR, "voice.lock")
7632
7924
  };
7633
7925
  function getPythonDir() {
7634
- return join28(__dirname6, "commands", "voice", "python");
7926
+ return join30(__dirname6, "commands", "voice", "python");
7635
7927
  }
7636
7928
  function getVenvPython() {
7637
- return process.platform === "win32" ? join28(voicePaths.venv, "Scripts", "python.exe") : join28(voicePaths.venv, "bin", "python");
7929
+ return process.platform === "win32" ? join30(voicePaths.venv, "Scripts", "python.exe") : join30(voicePaths.venv, "bin", "python");
7638
7930
  }
7639
7931
  function getLockDir() {
7640
7932
  const config = loadConfig();
7641
7933
  return config.voice?.lockDir ?? VOICE_DIR;
7642
7934
  }
7643
7935
  function getLockFile() {
7644
- return join28(getLockDir(), "voice.lock");
7936
+ return join30(getLockDir(), "voice.lock");
7645
7937
  }
7646
7938
 
7647
7939
  // src/commands/voice/devices.ts
7648
7940
  function devices() {
7649
- const script = join29(getPythonDir(), "list_devices.py");
7941
+ const script = join31(getPythonDir(), "list_devices.py");
7650
7942
  spawnSync3(getVenvPython(), [script], { stdio: "inherit" });
7651
7943
  }
7652
7944
 
7653
7945
  // src/commands/voice/logs.ts
7654
- import { existsSync as existsSync30, readFileSync as readFileSync24 } from "fs";
7946
+ import { existsSync as existsSync32, readFileSync as readFileSync25 } from "fs";
7655
7947
  function logs(options2) {
7656
- if (!existsSync30(voicePaths.log)) {
7948
+ if (!existsSync32(voicePaths.log)) {
7657
7949
  console.log("No voice log file found");
7658
7950
  return;
7659
7951
  }
7660
7952
  const count = Number.parseInt(options2.lines ?? "150", 10);
7661
- const content = readFileSync24(voicePaths.log, "utf-8").trim();
7953
+ const content = readFileSync25(voicePaths.log, "utf-8").trim();
7662
7954
  if (!content) {
7663
7955
  console.log("Voice log is empty");
7664
7956
  return;
@@ -7681,12 +7973,12 @@ function logs(options2) {
7681
7973
  // src/commands/voice/setup.ts
7682
7974
  import { spawnSync as spawnSync4 } from "child_process";
7683
7975
  import { mkdirSync as mkdirSync10 } from "fs";
7684
- import { join as join31 } from "path";
7976
+ import { join as join33 } from "path";
7685
7977
 
7686
7978
  // src/commands/voice/checkLockFile.ts
7687
- import { execSync as execSync32 } from "child_process";
7688
- import { existsSync as existsSync31, mkdirSync as mkdirSync9, readFileSync as readFileSync25, writeFileSync as writeFileSync23 } from "fs";
7689
- import { join as join30 } from "path";
7979
+ import { execSync as execSync34 } from "child_process";
7980
+ import { existsSync as existsSync33, mkdirSync as mkdirSync9, readFileSync as readFileSync26, writeFileSync as writeFileSync23 } from "fs";
7981
+ import { join as join32 } from "path";
7690
7982
  function isProcessAlive(pid) {
7691
7983
  try {
7692
7984
  process.kill(pid, 0);
@@ -7697,9 +7989,9 @@ function isProcessAlive(pid) {
7697
7989
  }
7698
7990
  function checkLockFile() {
7699
7991
  const lockFile = getLockFile();
7700
- if (!existsSync31(lockFile)) return;
7992
+ if (!existsSync33(lockFile)) return;
7701
7993
  try {
7702
- const lock = JSON.parse(readFileSync25(lockFile, "utf-8"));
7994
+ const lock = JSON.parse(readFileSync26(lockFile, "utf-8"));
7703
7995
  if (lock.pid && isProcessAlive(lock.pid)) {
7704
7996
  console.error(
7705
7997
  `Voice daemon already running (PID ${lock.pid}, env: ${lock.env}). Stop it first with: assist voice stop`
@@ -7710,10 +8002,10 @@ function checkLockFile() {
7710
8002
  }
7711
8003
  }
7712
8004
  function bootstrapVenv() {
7713
- if (existsSync31(getVenvPython())) return;
8005
+ if (existsSync33(getVenvPython())) return;
7714
8006
  console.log("Setting up Python environment...");
7715
8007
  const pythonDir = getPythonDir();
7716
- execSync32(
8008
+ execSync34(
7717
8009
  `uv sync --project "${pythonDir}" --extra runtime --no-install-project`,
7718
8010
  {
7719
8011
  stdio: "inherit",
@@ -7723,7 +8015,7 @@ function bootstrapVenv() {
7723
8015
  }
7724
8016
  function writeLockFile(pid) {
7725
8017
  const lockFile = getLockFile();
7726
- mkdirSync9(join30(lockFile, ".."), { recursive: true });
8018
+ mkdirSync9(join32(lockFile, ".."), { recursive: true });
7727
8019
  writeFileSync23(
7728
8020
  lockFile,
7729
8021
  JSON.stringify({
@@ -7739,7 +8031,7 @@ function setup() {
7739
8031
  mkdirSync10(voicePaths.dir, { recursive: true });
7740
8032
  bootstrapVenv();
7741
8033
  console.log("\nDownloading models...\n");
7742
- const script = join31(getPythonDir(), "setup_models.py");
8034
+ const script = join33(getPythonDir(), "setup_models.py");
7743
8035
  const result = spawnSync4(getVenvPython(), [script], {
7744
8036
  stdio: "inherit",
7745
8037
  env: { ...process.env, VOICE_LOG_FILE: voicePaths.log }
@@ -7753,7 +8045,7 @@ function setup() {
7753
8045
  // src/commands/voice/start.ts
7754
8046
  import { spawn as spawn4 } from "child_process";
7755
8047
  import { mkdirSync as mkdirSync11, writeFileSync as writeFileSync24 } from "fs";
7756
- import { join as join32 } from "path";
8048
+ import { join as join34 } from "path";
7757
8049
 
7758
8050
  // src/commands/voice/buildDaemonEnv.ts
7759
8051
  function buildDaemonEnv(options2) {
@@ -7791,7 +8083,7 @@ function start2(options2) {
7791
8083
  bootstrapVenv();
7792
8084
  const debug = options2.debug || options2.foreground || process.platform === "win32";
7793
8085
  const env = buildDaemonEnv({ debug });
7794
- const script = join32(getPythonDir(), "voice_daemon.py");
8086
+ const script = join34(getPythonDir(), "voice_daemon.py");
7795
8087
  const python = getVenvPython();
7796
8088
  if (options2.foreground) {
7797
8089
  spawnForeground(python, script, env);
@@ -7801,7 +8093,7 @@ function start2(options2) {
7801
8093
  }
7802
8094
 
7803
8095
  // src/commands/voice/status.ts
7804
- import { existsSync as existsSync32, readFileSync as readFileSync26 } from "fs";
8096
+ import { existsSync as existsSync34, readFileSync as readFileSync27 } from "fs";
7805
8097
  function isProcessAlive2(pid) {
7806
8098
  try {
7807
8099
  process.kill(pid, 0);
@@ -7811,16 +8103,16 @@ function isProcessAlive2(pid) {
7811
8103
  }
7812
8104
  }
7813
8105
  function readRecentLogs(count) {
7814
- if (!existsSync32(voicePaths.log)) return [];
7815
- const lines = readFileSync26(voicePaths.log, "utf-8").trim().split("\n");
8106
+ if (!existsSync34(voicePaths.log)) return [];
8107
+ const lines = readFileSync27(voicePaths.log, "utf-8").trim().split("\n");
7816
8108
  return lines.slice(-count);
7817
8109
  }
7818
8110
  function status() {
7819
- if (!existsSync32(voicePaths.pid)) {
8111
+ if (!existsSync34(voicePaths.pid)) {
7820
8112
  console.log("Voice daemon: not running (no PID file)");
7821
8113
  return;
7822
8114
  }
7823
- const pid = Number.parseInt(readFileSync26(voicePaths.pid, "utf-8").trim(), 10);
8115
+ const pid = Number.parseInt(readFileSync27(voicePaths.pid, "utf-8").trim(), 10);
7824
8116
  const alive = isProcessAlive2(pid);
7825
8117
  console.log(`Voice daemon: ${alive ? "running" : "dead"} (PID ${pid})`);
7826
8118
  const recent = readRecentLogs(5);
@@ -7839,13 +8131,13 @@ function status() {
7839
8131
  }
7840
8132
 
7841
8133
  // src/commands/voice/stop.ts
7842
- import { existsSync as existsSync33, readFileSync as readFileSync27, unlinkSync as unlinkSync7 } from "fs";
8134
+ import { existsSync as existsSync35, readFileSync as readFileSync28, unlinkSync as unlinkSync8 } from "fs";
7843
8135
  function stop() {
7844
- if (!existsSync33(voicePaths.pid)) {
8136
+ if (!existsSync35(voicePaths.pid)) {
7845
8137
  console.log("Voice daemon is not running (no PID file)");
7846
8138
  return;
7847
8139
  }
7848
- const pid = Number.parseInt(readFileSync27(voicePaths.pid, "utf-8").trim(), 10);
8140
+ const pid = Number.parseInt(readFileSync28(voicePaths.pid, "utf-8").trim(), 10);
7849
8141
  try {
7850
8142
  process.kill(pid, "SIGTERM");
7851
8143
  console.log(`Sent SIGTERM to voice daemon (PID ${pid})`);
@@ -7853,12 +8145,12 @@ function stop() {
7853
8145
  console.log(`Voice daemon (PID ${pid}) is not running`);
7854
8146
  }
7855
8147
  try {
7856
- unlinkSync7(voicePaths.pid);
8148
+ unlinkSync8(voicePaths.pid);
7857
8149
  } catch {
7858
8150
  }
7859
8151
  try {
7860
8152
  const lockFile = getLockFile();
7861
- if (existsSync33(lockFile)) unlinkSync7(lockFile);
8153
+ if (existsSync35(lockFile)) unlinkSync8(lockFile);
7862
8154
  } catch {
7863
8155
  }
7864
8156
  console.log("Voice daemon stopped");
@@ -7877,14 +8169,14 @@ function registerVoice(program2) {
7877
8169
 
7878
8170
  // src/commands/roam/auth.ts
7879
8171
  import { randomBytes } from "crypto";
7880
- import chalk77 from "chalk";
8172
+ import chalk82 from "chalk";
7881
8173
 
7882
8174
  // src/lib/openBrowser.ts
7883
- import { execSync as execSync33 } from "child_process";
8175
+ import { execSync as execSync35 } from "child_process";
7884
8176
  function tryExec(commands) {
7885
8177
  for (const cmd of commands) {
7886
8178
  try {
7887
- execSync33(cmd);
8179
+ execSync35(cmd);
7888
8180
  return true;
7889
8181
  } catch {
7890
8182
  }
@@ -8052,13 +8344,13 @@ async function auth() {
8052
8344
  saveGlobalConfig(config);
8053
8345
  const state = randomBytes(16).toString("hex");
8054
8346
  console.log(
8055
- chalk77.yellow("\nEnsure this Redirect URI is set in your Roam OAuth app:")
8347
+ chalk82.yellow("\nEnsure this Redirect URI is set in your Roam OAuth app:")
8056
8348
  );
8057
- console.log(chalk77.white("http://localhost:14523/callback\n"));
8058
- console.log(chalk77.blue("Opening browser for authorization..."));
8059
- console.log(chalk77.dim("Waiting for authorization callback..."));
8349
+ console.log(chalk82.white("http://localhost:14523/callback\n"));
8350
+ console.log(chalk82.blue("Opening browser for authorization..."));
8351
+ console.log(chalk82.dim("Waiting for authorization callback..."));
8060
8352
  const { code, redirectUri } = await authorizeInBrowser(clientId, state);
8061
- console.log(chalk77.dim("Exchanging code for tokens..."));
8353
+ console.log(chalk82.dim("Exchanging code for tokens..."));
8062
8354
  const tokens = await exchangeToken({
8063
8355
  code,
8064
8356
  clientId,
@@ -8074,7 +8366,7 @@ async function auth() {
8074
8366
  };
8075
8367
  saveGlobalConfig(config);
8076
8368
  console.log(
8077
- chalk77.green("Roam credentials and tokens saved to ~/.assist.yml")
8369
+ chalk82.green("Roam credentials and tokens saved to ~/.assist.yml")
8078
8370
  );
8079
8371
  }
8080
8372
 
@@ -8085,16 +8377,7 @@ function registerRoam(program2) {
8085
8377
  }
8086
8378
 
8087
8379
  // src/commands/run/index.ts
8088
- import { spawn as spawn5 } from "child_process";
8089
-
8090
- // src/shared/formatElapsed.ts
8091
- function formatElapsed(ms) {
8092
- const secs = ms / 1e3;
8093
- if (secs < 60) return `${secs.toFixed(1)}s`;
8094
- const mins = Math.floor(secs / 60);
8095
- const remainSecs = secs - mins * 60;
8096
- return `${mins}m ${remainSecs.toFixed(1)}s`;
8097
- }
8380
+ import { execSync as execSync36 } from "child_process";
8098
8381
 
8099
8382
  // src/commands/run/resolveParams.ts
8100
8383
  function resolveParams(params, cliArgs) {
@@ -8120,9 +8403,30 @@ function resolveParams(params, cliArgs) {
8120
8403
  return resolved;
8121
8404
  }
8122
8405
 
8406
+ // src/commands/run/spawnRunCommand.ts
8407
+ import { spawn as spawn5 } from "child_process";
8408
+ function spawnRunCommand(fullCommand, env) {
8409
+ const start3 = Date.now();
8410
+ const child = spawn5(fullCommand, [], {
8411
+ stdio: "inherit",
8412
+ shell: true,
8413
+ env: env ? { ...process.env, ...expandEnv(env) } : void 0
8414
+ });
8415
+ child.on("close", (code) => {
8416
+ const elapsed = formatElapsed(Date.now() - start3);
8417
+ console.log(`
8418
+ Done in ${elapsed}`);
8419
+ process.exit(code ?? 0);
8420
+ });
8421
+ child.on("error", (err) => {
8422
+ console.error(`Failed to execute command: ${err.message}`);
8423
+ process.exit(1);
8424
+ });
8425
+ }
8426
+
8123
8427
  // src/commands/run/add.ts
8124
8428
  import { mkdirSync as mkdirSync12, writeFileSync as writeFileSync25 } from "fs";
8125
- import { join as join33 } from "path";
8429
+ import { join as join35 } from "path";
8126
8430
  function findAddIndex() {
8127
8431
  const addIndex = process.argv.indexOf("add");
8128
8432
  if (addIndex === -1 || addIndex + 2 >= process.argv.length) return -1;
@@ -8176,7 +8480,7 @@ function saveNewRunConfig(name, command, args) {
8176
8480
  saveConfig(config);
8177
8481
  }
8178
8482
  function createCommandFile(name) {
8179
- const dir = join33(".claude", "commands");
8483
+ const dir = join35(".claude", "commands");
8180
8484
  mkdirSync12(dir, { recursive: true });
8181
8485
  const content = `---
8182
8486
  description: Run ${name}
@@ -8184,7 +8488,7 @@ description: Run ${name}
8184
8488
 
8185
8489
  Run \`assist run ${name} $ARGUMENTS 2>&1\`.
8186
8490
  `;
8187
- const filePath = join33(dir, `${name}.md`);
8491
+ const filePath = join35(dir, `${name}.md`);
8188
8492
  writeFileSync25(filePath, content);
8189
8493
  console.log(`Created command file: ${filePath}`);
8190
8494
  }
@@ -8226,25 +8530,6 @@ function findRunConfig(name) {
8226
8530
  const configs = requireRunConfigs();
8227
8531
  return configs.find((r) => r.name === name) ?? exitWithConfigNotFound(name, configs);
8228
8532
  }
8229
- function onSpawnError(err) {
8230
- console.error(`Failed to execute command: ${err.message}`);
8231
- process.exit(1);
8232
- }
8233
- function spawnCommand2(fullCommand, env) {
8234
- const start3 = Date.now();
8235
- const child = spawn5(fullCommand, [], {
8236
- stdio: "inherit",
8237
- shell: true,
8238
- env: env ? { ...process.env, ...expandEnv(env) } : void 0
8239
- });
8240
- child.on("close", (code) => {
8241
- const elapsed = formatElapsed(Date.now() - start3);
8242
- console.log(`
8243
- Done in ${elapsed}`);
8244
- process.exit(code ?? 0);
8245
- });
8246
- child.on("error", onSpawnError);
8247
- }
8248
8533
  function listRunConfigs() {
8249
8534
  const configs = requireRunConfigs();
8250
8535
  for (const config of configs) {
@@ -8252,17 +8537,28 @@ function listRunConfigs() {
8252
8537
  console.log(`${config.name}: ${config.command}${args}`);
8253
8538
  }
8254
8539
  }
8540
+ function runPreCommands(pre) {
8541
+ for (const cmd of pre) {
8542
+ try {
8543
+ execSync36(cmd, { stdio: "inherit" });
8544
+ } catch (err) {
8545
+ const code = err && typeof err === "object" && "status" in err ? err.status : 1;
8546
+ process.exit(code);
8547
+ }
8548
+ }
8549
+ }
8255
8550
  function run2(name, args) {
8256
8551
  const runConfig = findRunConfig(name);
8552
+ if (runConfig.pre) runPreCommands(runConfig.pre);
8257
8553
  const resolved = resolveParams(runConfig.params, args);
8258
- spawnCommand2(
8554
+ spawnRunCommand(
8259
8555
  buildCommand(runConfig.command, runConfig.args ?? [], resolved),
8260
8556
  runConfig.env
8261
8557
  );
8262
8558
  }
8263
8559
 
8264
8560
  // src/commands/statusLine.ts
8265
- import chalk78 from "chalk";
8561
+ import chalk83 from "chalk";
8266
8562
  function formatNumber(num) {
8267
8563
  return num.toLocaleString("en-US");
8268
8564
  }
@@ -8277,8 +8573,8 @@ function formatTimeLeft(resetsAt) {
8277
8573
  }
8278
8574
  function colorizePercent(pct) {
8279
8575
  const label2 = `${Math.round(pct)}%`;
8280
- if (pct > 80) return chalk78.red(label2);
8281
- if (pct > 40) return chalk78.yellow(label2);
8576
+ if (pct > 80) return chalk83.red(label2);
8577
+ if (pct > 40) return chalk83.yellow(label2);
8282
8578
  return label2;
8283
8579
  }
8284
8580
  function formatLimit(limit, fallbackLabel) {
@@ -8313,27 +8609,27 @@ async function statusLine() {
8313
8609
  // src/commands/sync.ts
8314
8610
  import * as fs24 from "fs";
8315
8611
  import * as os from "os";
8316
- import * as path40 from "path";
8612
+ import * as path42 from "path";
8317
8613
  import { fileURLToPath as fileURLToPath7 } from "url";
8318
8614
 
8319
8615
  // src/commands/sync/syncClaudeMd.ts
8320
8616
  import * as fs22 from "fs";
8321
- import * as path38 from "path";
8322
- import chalk79 from "chalk";
8617
+ import * as path40 from "path";
8618
+ import chalk84 from "chalk";
8323
8619
  async function syncClaudeMd(claudeDir, targetBase) {
8324
- const source = path38.join(claudeDir, "CLAUDE.md");
8325
- const target = path38.join(targetBase, "CLAUDE.md");
8620
+ const source = path40.join(claudeDir, "CLAUDE.md");
8621
+ const target = path40.join(targetBase, "CLAUDE.md");
8326
8622
  const sourceContent = fs22.readFileSync(source, "utf-8");
8327
8623
  if (fs22.existsSync(target)) {
8328
8624
  const targetContent = fs22.readFileSync(target, "utf-8");
8329
8625
  if (sourceContent !== targetContent) {
8330
8626
  console.log(
8331
- chalk79.yellow("\n\u26A0\uFE0F Warning: CLAUDE.md differs from existing file")
8627
+ chalk84.yellow("\n\u26A0\uFE0F Warning: CLAUDE.md differs from existing file")
8332
8628
  );
8333
8629
  console.log();
8334
8630
  printDiff(targetContent, sourceContent);
8335
8631
  const confirm = await promptConfirm(
8336
- chalk79.red("Overwrite existing CLAUDE.md?"),
8632
+ chalk84.red("Overwrite existing CLAUDE.md?"),
8337
8633
  false
8338
8634
  );
8339
8635
  if (!confirm) {
@@ -8348,11 +8644,11 @@ async function syncClaudeMd(claudeDir, targetBase) {
8348
8644
 
8349
8645
  // src/commands/sync/syncSettings.ts
8350
8646
  import * as fs23 from "fs";
8351
- import * as path39 from "path";
8352
- import chalk80 from "chalk";
8647
+ import * as path41 from "path";
8648
+ import chalk85 from "chalk";
8353
8649
  async function syncSettings(claudeDir, targetBase, options2) {
8354
- const source = path39.join(claudeDir, "settings.json");
8355
- const target = path39.join(targetBase, "settings.json");
8650
+ const source = path41.join(claudeDir, "settings.json");
8651
+ const target = path41.join(targetBase, "settings.json");
8356
8652
  const sourceContent = fs23.readFileSync(source, "utf-8");
8357
8653
  const mergedContent = JSON.stringify(JSON.parse(sourceContent), null, " ");
8358
8654
  if (fs23.existsSync(target)) {
@@ -8365,14 +8661,14 @@ async function syncSettings(claudeDir, targetBase, options2) {
8365
8661
  if (mergedContent !== normalizedTarget) {
8366
8662
  if (!options2?.yes) {
8367
8663
  console.log(
8368
- chalk80.yellow(
8664
+ chalk85.yellow(
8369
8665
  "\n\u26A0\uFE0F Warning: settings.json differs from existing file"
8370
8666
  )
8371
8667
  );
8372
8668
  console.log();
8373
8669
  printDiff(targetContent, mergedContent);
8374
8670
  const confirm = await promptConfirm(
8375
- chalk80.red("Overwrite existing settings.json?"),
8671
+ chalk85.red("Overwrite existing settings.json?"),
8376
8672
  false
8377
8673
  );
8378
8674
  if (!confirm) {
@@ -8388,37 +8684,37 @@ async function syncSettings(claudeDir, targetBase, options2) {
8388
8684
 
8389
8685
  // src/commands/sync.ts
8390
8686
  var __filename4 = fileURLToPath7(import.meta.url);
8391
- var __dirname7 = path40.dirname(__filename4);
8687
+ var __dirname7 = path42.dirname(__filename4);
8392
8688
  async function sync(options2) {
8393
- const claudeDir = path40.join(__dirname7, "..", "claude");
8394
- const targetBase = path40.join(os.homedir(), ".claude");
8689
+ const claudeDir = path42.join(__dirname7, "..", "claude");
8690
+ const targetBase = path42.join(os.homedir(), ".claude");
8395
8691
  syncCommands(claudeDir, targetBase);
8396
8692
  await syncSettings(claudeDir, targetBase, { yes: options2?.yes });
8397
8693
  await syncClaudeMd(claudeDir, targetBase);
8398
8694
  }
8399
8695
  function syncCommands(claudeDir, targetBase) {
8400
- const sourceDir = path40.join(claudeDir, "commands");
8401
- const targetDir = path40.join(targetBase, "commands");
8696
+ const sourceDir = path42.join(claudeDir, "commands");
8697
+ const targetDir = path42.join(targetBase, "commands");
8402
8698
  fs24.mkdirSync(targetDir, { recursive: true });
8403
8699
  const files = fs24.readdirSync(sourceDir);
8404
8700
  for (const file of files) {
8405
- fs24.copyFileSync(path40.join(sourceDir, file), path40.join(targetDir, file));
8701
+ fs24.copyFileSync(path42.join(sourceDir, file), path42.join(targetDir, file));
8406
8702
  console.log(`Copied ${file} to ${targetDir}`);
8407
8703
  }
8408
8704
  console.log(`Synced ${files.length} command(s) to ~/.claude/commands`);
8409
8705
  }
8410
8706
 
8411
8707
  // src/commands/update.ts
8412
- import { execSync as execSync34 } from "child_process";
8413
- import * as path41 from "path";
8708
+ import { execSync as execSync37 } from "child_process";
8709
+ import * as path43 from "path";
8414
8710
  function isGlobalNpmInstall(dir) {
8415
8711
  try {
8416
- const resolved = path41.resolve(dir);
8417
- if (resolved.split(path41.sep).includes("node_modules")) {
8712
+ const resolved = path43.resolve(dir);
8713
+ if (resolved.split(path43.sep).includes("node_modules")) {
8418
8714
  return true;
8419
8715
  }
8420
- const globalPrefix = execSync34("npm prefix -g", { stdio: "pipe" }).toString().trim();
8421
- return resolved.toLowerCase().startsWith(path41.resolve(globalPrefix).toLowerCase());
8716
+ const globalPrefix = execSync37("npm prefix -g", { stdio: "pipe" }).toString().trim();
8717
+ return resolved.toLowerCase().startsWith(path43.resolve(globalPrefix).toLowerCase());
8422
8718
  } catch {
8423
8719
  return false;
8424
8720
  }
@@ -8428,18 +8724,18 @@ async function update() {
8428
8724
  console.log(`Assist is installed at: ${installDir}`);
8429
8725
  if (isGitRepo(installDir)) {
8430
8726
  console.log("Detected git repo installation, pulling latest...");
8431
- execSync34("git pull", { cwd: installDir, stdio: "inherit" });
8727
+ execSync37("git pull", { cwd: installDir, stdio: "inherit" });
8432
8728
  console.log("Installing dependencies...");
8433
- execSync34("npm i", { cwd: installDir, stdio: "inherit" });
8729
+ execSync37("npm i", { cwd: installDir, stdio: "inherit" });
8434
8730
  console.log("Building...");
8435
- execSync34("npm run build", { cwd: installDir, stdio: "inherit" });
8731
+ execSync37("npm run build", { cwd: installDir, stdio: "inherit" });
8436
8732
  console.log("Syncing commands...");
8437
- execSync34("assist sync", { stdio: "inherit" });
8733
+ execSync37("assist sync", { stdio: "inherit" });
8438
8734
  } else if (isGlobalNpmInstall(installDir)) {
8439
8735
  console.log("Detected global npm installation, updating...");
8440
- execSync34("npm i -g @staff0rd/assist@latest", { stdio: "inherit" });
8736
+ execSync37("npm i -g @staff0rd/assist@latest", { stdio: "inherit" });
8441
8737
  console.log("Syncing commands...");
8442
- execSync34("assist sync", { stdio: "inherit" });
8738
+ execSync37("assist sync", { stdio: "inherit" });
8443
8739
  } else {
8444
8740
  console.error(
8445
8741
  "Could not determine installation method. Expected a git repo or global npm install."
@@ -8486,7 +8782,7 @@ registerRefactor(program);
8486
8782
  registerDevlog(program);
8487
8783
  registerDeploy(program);
8488
8784
  registerComplexity(program);
8489
- registerNetframework(program);
8785
+ registerDotnet(program);
8490
8786
  registerNews(program);
8491
8787
  registerRavendb(program);
8492
8788
  registerTranscript(program);