@staff0rd/assist 0.109.0 → 0.110.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.109.0",
9
+ version: "0.110.0",
10
10
  type: "module",
11
11
  main: "dist/index.js",
12
12
  bin: {
@@ -46,6 +46,7 @@ var package_default = {
46
46
  "node-notifier": "^10.0.1",
47
47
  semver: "^7.7.3",
48
48
  "shell-quote": "^1.8.3",
49
+ "ts-morph": "^27.0.2",
49
50
  typescript: "^5.9.3",
50
51
  yaml: "^2.8.2",
51
52
  zod: "^4.3.6"
@@ -88,10 +89,10 @@ import { stringify as stringifyYaml } from "yaml";
88
89
  // src/shared/loadRawYaml.ts
89
90
  import { existsSync, readFileSync } from "fs";
90
91
  import { parse as parseYaml } from "yaml";
91
- function loadRawYaml(path36) {
92
- if (!existsSync(path36)) return {};
92
+ function loadRawYaml(path43) {
93
+ if (!existsSync(path43)) return {};
93
94
  try {
94
- const content = readFileSync(path36, "utf-8");
95
+ const content = readFileSync(path43, "utf-8");
95
96
  return parseYaml(content) || {};
96
97
  } catch {
97
98
  return {};
@@ -329,9 +330,9 @@ function isTraversable(value) {
329
330
  function stepInto(current, key) {
330
331
  return isTraversable(current) ? current[key] : void 0;
331
332
  }
332
- function getNestedValue(obj, path36) {
333
+ function getNestedValue(obj, path43) {
333
334
  let current = obj;
334
- for (const key of path36.split(".")) current = stepInto(current, key);
335
+ for (const key of path43.split(".")) current = stepInto(current, key);
335
336
  return current;
336
337
  }
337
338
 
@@ -372,8 +373,8 @@ function stepIntoNested(container, key, nextKey) {
372
373
  }
373
374
  return ensureObject(container, resolved);
374
375
  }
375
- function setNestedValue(obj, path36, value) {
376
- const keys = path36.split(".");
376
+ function setNestedValue(obj, path43, value) {
377
+ const keys = path43.split(".");
377
378
  const result = { ...obj };
378
379
  let current = result;
379
380
  for (let i = 0; i < keys.length - 1; i++) {
@@ -515,7 +516,7 @@ function findPackageJsonWithVerifyScripts(startDir) {
515
516
  // src/commands/verify/setup/expectedScripts.ts
516
517
  var expectedScripts = {
517
518
  "verify:knip": "knip --no-progress --treat-config-hints-as-errors",
518
- "verify:lint": "biome check --write .",
519
+ "verify:lint": "biome check --write --error-on-warnings .",
519
520
  "verify:duplicate-code": "jscpd --format 'typescript,tsx' --exitCode 1 --ignore '**/*.test.*' -r consoleFull src",
520
521
  "verify:test": "vitest run --reporter=dot --silent",
521
522
  "verify:hardcoded-colors": "assist verify hardcoded-colors",
@@ -1245,9 +1246,12 @@ async function init4() {
1245
1246
  }
1246
1247
 
1247
1248
  // src/commands/lint/lint/runFileNameCheck.ts
1249
+ import path17 from "path";
1250
+ import chalk20 from "chalk";
1251
+
1252
+ // src/commands/lint/lint/checkFileNames.ts
1248
1253
  import fs6 from "fs";
1249
1254
  import path13 from "path";
1250
- import chalk19 from "chalk";
1251
1255
 
1252
1256
  // src/shared/findSourceFiles.ts
1253
1257
  import fs5 from "fs";
@@ -1274,71 +1278,198 @@ function findSourceFiles(dir, options2 = {}) {
1274
1278
  return results;
1275
1279
  }
1276
1280
 
1277
- // src/commands/lint/lint/runFileNameCheck.ts
1281
+ // src/commands/lint/lint/checkFileNames.ts
1278
1282
  function hasClassOrComponent(content) {
1279
1283
  const classPattern = /^(export\s+)?(abstract\s+)?class\s+\w+/m;
1280
1284
  const functionComponentPattern = /^(export\s+)?(default\s+)?function\s+[A-Z]\w*\s*\(/m;
1281
1285
  const arrowComponentPattern = /^(export\s+)?(const|let)\s+[A-Z]\w*\s*=.*=>/m;
1282
1286
  return classPattern.test(content) || functionComponentPattern.test(content) || arrowComponentPattern.test(content);
1283
1287
  }
1288
+ function hasMatchingTypeExport(content, nameWithoutExt) {
1289
+ const typePattern = new RegExp(
1290
+ `^export\\s+type\\s+${nameWithoutExt}\\b`,
1291
+ "m"
1292
+ );
1293
+ const interfacePattern = new RegExp(
1294
+ `^export\\s+interface\\s+${nameWithoutExt}\\b`,
1295
+ "m"
1296
+ );
1297
+ return typePattern.test(content) || interfacePattern.test(content);
1298
+ }
1299
+ function suggestName(fileName) {
1300
+ const nameWithoutExt = fileName.replace(/\.(ts|tsx)$/, "");
1301
+ const ext = fileName.slice(nameWithoutExt.length);
1302
+ if (/^[A-Z][A-Z0-9]*(_[A-Z0-9]+)+$/.test(nameWithoutExt)) {
1303
+ const camel = nameWithoutExt.toLowerCase().replace(/_([a-z0-9])/g, (_, c) => c.toUpperCase());
1304
+ return `${camel}${ext}`;
1305
+ }
1306
+ return `${nameWithoutExt.charAt(0).toLowerCase()}${nameWithoutExt.slice(1)}${ext}`;
1307
+ }
1284
1308
  function checkFileNames() {
1285
1309
  const sourceFiles = findSourceFiles("src");
1286
1310
  const violations = [];
1287
1311
  for (const filePath of sourceFiles) {
1288
1312
  const fileName = path13.basename(filePath);
1289
1313
  const nameWithoutExt = fileName.replace(/\.(ts|tsx)$/, "");
1314
+ if (/\.(stories|test)\.(ts|tsx)$/.test(fileName)) continue;
1290
1315
  if (/^[A-Z]/.test(nameWithoutExt)) {
1291
1316
  const content = fs6.readFileSync(filePath, "utf-8");
1292
- if (!hasClassOrComponent(content)) {
1293
- violations.push({ filePath, fileName });
1317
+ if (!hasClassOrComponent(content) && !hasMatchingTypeExport(content, nameWithoutExt)) {
1318
+ violations.push({
1319
+ filePath,
1320
+ fileName,
1321
+ suggestedName: suggestName(fileName)
1322
+ });
1294
1323
  }
1295
1324
  }
1296
1325
  }
1297
1326
  return violations;
1298
1327
  }
1299
- function runFileNameCheck() {
1328
+
1329
+ // src/commands/lint/lint/fixFileNameViolations.ts
1330
+ import chalk19 from "chalk";
1331
+
1332
+ // src/commands/lint/lint/applyMoves.ts
1333
+ import fs7 from "fs";
1334
+ import path15 from "path";
1335
+
1336
+ // src/commands/lint/lint/renameExports.ts
1337
+ import path14 from "path";
1338
+ import { SyntaxKind } from "ts-morph";
1339
+ function nameWithoutExtension(filePath) {
1340
+ return path14.basename(filePath).replace(/\.(ts|tsx)$/, "");
1341
+ }
1342
+ function renameExports(project, absSource, absDest) {
1343
+ const oldName = nameWithoutExtension(absSource);
1344
+ const newName = nameWithoutExtension(absDest);
1345
+ const sourceFile = project.getSourceFile(absSource);
1346
+ if (!sourceFile) return [];
1347
+ const renamed = [];
1348
+ for (const [, declarations] of sourceFile.getExportedDeclarations()) {
1349
+ for (const decl of declarations) {
1350
+ const kind = decl.getKind();
1351
+ if (kind === SyntaxKind.TypeAliasDeclaration || kind === SyntaxKind.InterfaceDeclaration) {
1352
+ continue;
1353
+ }
1354
+ const nameNode = decl.getFirstChildByKind(SyntaxKind.Identifier);
1355
+ if (!nameNode || nameNode.getText() !== oldName) continue;
1356
+ nameNode.rename(newName);
1357
+ renamed.push(`${oldName} \u2192 ${newName}`);
1358
+ }
1359
+ }
1360
+ return renamed;
1361
+ }
1362
+
1363
+ // src/commands/lint/lint/applyMoves.ts
1364
+ function isCaseOnly(a, b) {
1365
+ return a.toLowerCase() === b.toLowerCase();
1366
+ }
1367
+ function moveCaseInsensitive(absSource, absDest) {
1368
+ const tmp = `${absSource}.tmp`;
1369
+ fs7.renameSync(absSource, tmp);
1370
+ fs7.renameSync(tmp, absDest);
1371
+ }
1372
+ function applyMoves(project, moves, cwd, emit) {
1373
+ for (const { sourcePath, destPath } of moves) {
1374
+ const start3 = performance.now();
1375
+ const absSource = path15.resolve(sourcePath);
1376
+ const absDest = path15.resolve(destPath);
1377
+ for (const r of renameExports(project, absSource, absDest)) {
1378
+ emit(` Renamed export ${r} in ${sourcePath}`);
1379
+ }
1380
+ const sourceFile = project.getSourceFile(absSource);
1381
+ if (sourceFile) sourceFile.move(absDest);
1382
+ const ms = (performance.now() - start3).toFixed(0);
1383
+ const rel = `${path15.relative(cwd, absSource)} \u2192 ${path15.relative(cwd, absDest)}`;
1384
+ emit(` Renamed ${rel} (${ms}ms)`);
1385
+ }
1386
+ project.saveSync();
1387
+ for (const { sourcePath, destPath } of moves) {
1388
+ const absSource = path15.resolve(sourcePath);
1389
+ const absDest = path15.resolve(destPath);
1390
+ if (isCaseOnly(absSource, absDest) && fs7.existsSync(absSource)) {
1391
+ moveCaseInsensitive(absSource, absDest);
1392
+ }
1393
+ }
1394
+ }
1395
+
1396
+ // src/commands/lint/lint/createLintProject.ts
1397
+ import fs8 from "fs";
1398
+ import path16 from "path";
1399
+ import { Project } from "ts-morph";
1400
+ function createLintProject() {
1401
+ const tsConfigPath = path16.resolve("tsconfig.json");
1402
+ const project = fs8.existsSync(tsConfigPath) ? new Project({
1403
+ tsConfigFilePath: tsConfigPath,
1404
+ skipAddingFilesFromTsConfig: true
1405
+ }) : new Project();
1406
+ project.addSourceFilesAtPaths("src/**/*.{ts,tsx}");
1407
+ return project;
1408
+ }
1409
+
1410
+ // src/commands/lint/lint/fixFileNameViolations.ts
1411
+ function fixFileNameViolations(moves) {
1412
+ const start3 = performance.now();
1413
+ const project = createLintProject();
1414
+ const cwd = process.cwd();
1415
+ applyMoves(project, moves, cwd, (line) => console.log(chalk19.green(line)));
1416
+ const ms = (performance.now() - start3).toFixed(0);
1417
+ console.log(chalk19.dim(` Done in ${ms}ms`));
1418
+ }
1419
+
1420
+ // src/commands/lint/lint/runFileNameCheck.ts
1421
+ function reportViolations(violations) {
1422
+ console.error(chalk20.red("\nFile name check failed:\n"));
1423
+ console.error(
1424
+ chalk20.red(
1425
+ " Files without classes or React components should not start with a capital letter.\n"
1426
+ )
1427
+ );
1428
+ for (const violation of violations) {
1429
+ console.error(chalk20.red(` ${violation.filePath}`));
1430
+ console.error(chalk20.gray(` Rename to: ${violation.suggestedName}
1431
+ `));
1432
+ }
1433
+ console.error(chalk20.dim(" Run with -f to auto-fix.\n"));
1434
+ }
1435
+ function runFileNameCheck(fix = false) {
1300
1436
  const violations = checkFileNames();
1301
- if (violations.length > 0) {
1302
- console.error(chalk19.red("\nFile name check failed:\n"));
1303
- console.error(
1304
- chalk19.red(
1305
- " Files without classes or React components should not start with a capital letter.\n"
1306
- )
1307
- );
1308
- for (const violation of violations) {
1309
- console.error(chalk19.red(` ${violation.filePath}`));
1310
- console.error(
1311
- chalk19.gray(
1312
- ` Rename to: ${violation.fileName.charAt(0).toLowerCase()}${violation.fileName.slice(1)}
1313
- `
1314
- )
1437
+ if (violations.length === 0) {
1438
+ if (!process.env.CLAUDECODE) {
1439
+ console.log(
1440
+ "File name check passed. All PascalCase files contain classes or components."
1315
1441
  );
1316
1442
  }
1317
- return false;
1443
+ return true;
1318
1444
  }
1319
- if (!process.env.CLAUDECODE) {
1320
- console.log(
1321
- "File name check passed. All PascalCase files contain classes or components."
1322
- );
1445
+ if (!fix) {
1446
+ reportViolations(violations);
1447
+ return false;
1323
1448
  }
1449
+ fixFileNameViolations(
1450
+ violations.map((v) => ({
1451
+ sourcePath: v.filePath,
1452
+ destPath: path17.join(path17.dirname(v.filePath), v.suggestedName)
1453
+ }))
1454
+ );
1324
1455
  return true;
1325
1456
  }
1326
1457
 
1327
1458
  // src/commands/lint/lint/runImportExtensionCheck.ts
1328
- import fs7 from "fs";
1459
+ import fs9 from "fs";
1329
1460
 
1330
1461
  // src/commands/lint/shared.ts
1331
- import chalk20 from "chalk";
1332
- function reportViolations(violations, checkName, errorMessage, successMessage) {
1462
+ import chalk21 from "chalk";
1463
+ function reportViolations2(violations, checkName, errorMessage, successMessage) {
1333
1464
  if (violations.length > 0) {
1334
- console.error(chalk20.red(`
1465
+ console.error(chalk21.red(`
1335
1466
  ${checkName} failed:
1336
1467
  `));
1337
- console.error(chalk20.red(` ${errorMessage}
1468
+ console.error(chalk21.red(` ${errorMessage}
1338
1469
  `));
1339
1470
  for (const violation of violations) {
1340
- console.error(chalk20.red(` ${violation.filePath}:${violation.line}`));
1341
- console.error(chalk20.gray(` ${violation.content}
1471
+ console.error(chalk21.red(` ${violation.filePath}:${violation.line}`));
1472
+ console.error(chalk21.gray(` ${violation.content}
1342
1473
  `));
1343
1474
  }
1344
1475
  return false;
@@ -1351,7 +1482,7 @@ ${checkName} failed:
1351
1482
 
1352
1483
  // src/commands/lint/lint/runImportExtensionCheck.ts
1353
1484
  function checkForImportExtensions(filePath) {
1354
- const content = fs7.readFileSync(filePath, "utf-8");
1485
+ const content = fs9.readFileSync(filePath, "utf-8");
1355
1486
  const lines = content.split("\n");
1356
1487
  const violations = [];
1357
1488
  const importExtensionPattern = /from\s+["']\..*\.(js|ts)["']/;
@@ -1376,7 +1507,7 @@ function checkImportExtensions() {
1376
1507
  return violations;
1377
1508
  }
1378
1509
  function runImportExtensionCheck() {
1379
- return reportViolations(
1510
+ return reportViolations2(
1380
1511
  checkImportExtensions(),
1381
1512
  "Import extension check",
1382
1513
  "File extensions in imports are not allowed. Use extensionless imports instead.",
@@ -1385,9 +1516,9 @@ function runImportExtensionCheck() {
1385
1516
  }
1386
1517
 
1387
1518
  // src/commands/lint/lint/runStaticImportCheck.ts
1388
- import fs8 from "fs";
1519
+ import fs10 from "fs";
1389
1520
  function checkForDynamicImports(filePath) {
1390
- const content = fs8.readFileSync(filePath, "utf-8");
1521
+ const content = fs10.readFileSync(filePath, "utf-8");
1391
1522
  const lines = content.split("\n");
1392
1523
  const violations = [];
1393
1524
  const requirePattern = /\brequire\s*\(/;
@@ -1413,7 +1544,7 @@ function checkStaticImports() {
1413
1544
  return violations;
1414
1545
  }
1415
1546
  function runStaticImportCheck() {
1416
- return reportViolations(
1547
+ return reportViolations2(
1417
1548
  checkStaticImports(),
1418
1549
  "Static import check",
1419
1550
  "Dynamic imports are not allowed. Use static imports instead.",
@@ -1422,8 +1553,8 @@ function runStaticImportCheck() {
1422
1553
  }
1423
1554
 
1424
1555
  // src/commands/lint/lint/index.ts
1425
- function lint() {
1426
- const fileNamePassed = runFileNameCheck();
1556
+ function lint(options2 = {}) {
1557
+ const fileNamePassed = runFileNameCheck(options2.fix);
1427
1558
  const staticImportPassed = runStaticImportCheck();
1428
1559
  const importExtensionPassed = runImportExtensionCheck();
1429
1560
  if (!fileNamePassed || !staticImportPassed || !importExtensionPassed) {
@@ -1480,7 +1611,7 @@ Total: ${lines.length} hardcoded color(s)`);
1480
1611
  }
1481
1612
 
1482
1613
  // src/commands/verify/run/resolveEntries.ts
1483
- import * as path14 from "path";
1614
+ import * as path18 from "path";
1484
1615
  function buildFullCommand(command, args) {
1485
1616
  return [shellQuote(command), ...(args ?? []).map(shellQuote)].join(" ");
1486
1617
  }
@@ -1497,7 +1628,7 @@ function getRunEntries() {
1497
1628
  function getPackageJsonEntries() {
1498
1629
  const result = findPackageJsonWithVerifyScripts(process.cwd());
1499
1630
  if (!result) return [];
1500
- const cwd = path14.dirname(result.packageJsonPath);
1631
+ const cwd = path18.dirname(result.packageJsonPath);
1501
1632
  return result.verifyScripts.map((script) => ({
1502
1633
  name: script,
1503
1634
  fullCommand: `npm run ${script}`,
@@ -1818,14 +1949,14 @@ import { existsSync as existsSync11, readFileSync as readFileSync9, writeFileSyn
1818
1949
 
1819
1950
  // src/commands/deploy/init/index.ts
1820
1951
  import { execSync as execSync11 } from "child_process";
1821
- import chalk22 from "chalk";
1952
+ import chalk23 from "chalk";
1822
1953
  import enquirer3 from "enquirer";
1823
1954
 
1824
1955
  // src/commands/deploy/init/updateWorkflow.ts
1825
1956
  import { existsSync as existsSync10, mkdirSync as mkdirSync3, readFileSync as readFileSync8, writeFileSync as writeFileSync8 } from "fs";
1826
1957
  import { dirname as dirname11, join as join7 } from "path";
1827
1958
  import { fileURLToPath as fileURLToPath2 } from "url";
1828
- import chalk21 from "chalk";
1959
+ import chalk22 from "chalk";
1829
1960
  var WORKFLOW_PATH = ".github/workflows/build.yml";
1830
1961
  var __dirname3 = dirname11(fileURLToPath2(import.meta.url));
1831
1962
  function getExistingSiteId() {
@@ -1850,20 +1981,20 @@ async function updateWorkflow(siteId) {
1850
1981
  if (existsSync10(WORKFLOW_PATH)) {
1851
1982
  const oldContent = readFileSync8(WORKFLOW_PATH, "utf-8");
1852
1983
  if (oldContent === newContent) {
1853
- console.log(chalk21.green("build.yml is already up to date"));
1984
+ console.log(chalk22.green("build.yml is already up to date"));
1854
1985
  return;
1855
1986
  }
1856
- console.log(chalk21.yellow("\nbuild.yml will be updated:"));
1987
+ console.log(chalk22.yellow("\nbuild.yml will be updated:"));
1857
1988
  console.log();
1858
1989
  printDiff(oldContent, newContent);
1859
- const confirm = await promptConfirm(chalk21.red("Update build.yml?"));
1990
+ const confirm = await promptConfirm(chalk22.red("Update build.yml?"));
1860
1991
  if (!confirm) {
1861
1992
  console.log("Skipped build.yml update");
1862
1993
  return;
1863
1994
  }
1864
1995
  }
1865
1996
  writeFileSync8(WORKFLOW_PATH, newContent);
1866
- console.log(chalk21.green(`
1997
+ console.log(chalk22.green(`
1867
1998
  Created ${WORKFLOW_PATH}`));
1868
1999
  }
1869
2000
 
@@ -1874,43 +2005,43 @@ async function ensureNetlifyCli() {
1874
2005
  } catch (error) {
1875
2006
  if (!(error instanceof Error) || !error.message.includes("command not found"))
1876
2007
  throw error;
1877
- console.error(chalk22.red("\nNetlify CLI is not installed.\n"));
2008
+ console.error(chalk23.red("\nNetlify CLI is not installed.\n"));
1878
2009
  const install = await promptConfirm("Would you like to install it now?");
1879
2010
  if (!install) {
1880
2011
  console.log(
1881
- chalk22.yellow(
2012
+ chalk23.yellow(
1882
2013
  "\nInstall it manually with: npm install -g netlify-cli\n"
1883
2014
  )
1884
2015
  );
1885
2016
  process.exit(1);
1886
2017
  }
1887
- console.log(chalk22.dim("\nInstalling netlify-cli...\n"));
2018
+ console.log(chalk23.dim("\nInstalling netlify-cli...\n"));
1888
2019
  execSync11("npm install -g netlify-cli", { stdio: "inherit" });
1889
2020
  console.log();
1890
2021
  execSync11("netlify sites:create --disable-linking", { stdio: "inherit" });
1891
2022
  }
1892
2023
  }
1893
2024
  function printSetupInstructions() {
1894
- console.log(chalk22.bold("\nDeployment initialized successfully!"));
2025
+ console.log(chalk23.bold("\nDeployment initialized successfully!"));
1895
2026
  console.log(
1896
- chalk22.yellow("\nTo complete setup, create a personal access token at:")
2027
+ chalk23.yellow("\nTo complete setup, create a personal access token at:")
1897
2028
  );
1898
2029
  console.log(
1899
- chalk22.cyan(
2030
+ chalk23.cyan(
1900
2031
  "https://app.netlify.com/user/applications#personal-access-tokens"
1901
2032
  )
1902
2033
  );
1903
2034
  console.log(
1904
- chalk22.yellow(
2035
+ chalk23.yellow(
1905
2036
  "\nThen add it as NETLIFY_AUTH_TOKEN in your GitHub repository secrets."
1906
2037
  )
1907
2038
  );
1908
2039
  }
1909
2040
  async function init5() {
1910
- console.log(chalk22.bold("Initializing Netlify deployment...\n"));
2041
+ console.log(chalk23.bold("Initializing Netlify deployment...\n"));
1911
2042
  const existingSiteId = getExistingSiteId();
1912
2043
  if (existingSiteId) {
1913
- console.log(chalk22.dim(`Using existing site ID: ${existingSiteId}
2044
+ console.log(chalk23.dim(`Using existing site ID: ${existingSiteId}
1914
2045
  `));
1915
2046
  await updateWorkflow(existingSiteId);
1916
2047
  return;
@@ -2004,19 +2135,19 @@ function detectPlatform() {
2004
2135
 
2005
2136
  // src/commands/notify/showNotification/showWindowsNotificationFromWsl.ts
2006
2137
  import { spawn as spawn2 } from "child_process";
2007
- import fs9 from "fs";
2138
+ import fs11 from "fs";
2008
2139
  import { createRequire } from "module";
2009
- import path15 from "path";
2140
+ import path19 from "path";
2010
2141
  var require2 = createRequire(import.meta.url);
2011
2142
  function getSnoreToastPath() {
2012
- const notifierPath = path15.dirname(require2.resolve("node-notifier"));
2013
- return path15.join(notifierPath, "vendor", "snoreToast", "snoretoast-x64.exe");
2143
+ const notifierPath = path19.dirname(require2.resolve("node-notifier"));
2144
+ return path19.join(notifierPath, "vendor", "snoreToast", "snoretoast-x64.exe");
2014
2145
  }
2015
2146
  function showWindowsNotificationFromWsl(options2) {
2016
2147
  const { title, message, sound } = options2;
2017
2148
  const snoreToastPath = getSnoreToastPath();
2018
2149
  try {
2019
- fs9.chmodSync(snoreToastPath, 493);
2150
+ fs11.chmodSync(snoreToastPath, 493);
2020
2151
  } catch {
2021
2152
  }
2022
2153
  const args = ["-t", title, "-m", message];
@@ -2090,12 +2221,12 @@ async function notify() {
2090
2221
 
2091
2222
  // src/commands/backlog/add/index.ts
2092
2223
  import { existsSync as existsSync13 } from "fs";
2093
- import chalk24 from "chalk";
2224
+ import chalk25 from "chalk";
2094
2225
 
2095
2226
  // src/commands/backlog/shared.ts
2096
2227
  import { existsSync as existsSync12, readFileSync as readFileSync10, writeFileSync as writeFileSync10 } from "fs";
2097
2228
  import { join as join8 } from "path";
2098
- import chalk23 from "chalk";
2229
+ import chalk24 from "chalk";
2099
2230
  import { parse as parseYaml2, stringify as stringifyYaml3 } from "yaml";
2100
2231
 
2101
2232
  // src/commands/backlog/types.ts
@@ -2139,7 +2270,7 @@ function findItem(items, id) {
2139
2270
  function loadAndFindItem(id) {
2140
2271
  if (!existsSync12(getBacklogPath())) {
2141
2272
  console.log(
2142
- chalk23.yellow(
2273
+ chalk24.yellow(
2143
2274
  "No backlog found. Run 'assist backlog init' to create one."
2144
2275
  )
2145
2276
  );
@@ -2148,7 +2279,7 @@ function loadAndFindItem(id) {
2148
2279
  const items = loadBacklog();
2149
2280
  const item = findItem(items, Number.parseInt(id, 10));
2150
2281
  if (!item) {
2151
- console.log(chalk23.red(`Item #${id} not found.`));
2282
+ console.log(chalk24.red(`Item #${id} not found.`));
2152
2283
  return void 0;
2153
2284
  }
2154
2285
  return { items, item };
@@ -2246,7 +2377,7 @@ async function add() {
2246
2377
  const backlogPath = getBacklogPath();
2247
2378
  if (!existsSync13(backlogPath)) {
2248
2379
  console.log(
2249
- chalk24.yellow(
2380
+ chalk25.yellow(
2250
2381
  "No backlog found. Run 'assist backlog init' to create one."
2251
2382
  )
2252
2383
  );
@@ -2267,67 +2398,67 @@ async function add() {
2267
2398
  status: "todo"
2268
2399
  });
2269
2400
  saveBacklog(items);
2270
- console.log(chalk24.green(`Added item #${id}: ${name}`));
2401
+ console.log(chalk25.green(`Added item #${id}: ${name}`));
2271
2402
  }
2272
2403
 
2273
2404
  // src/commands/backlog/delete/index.ts
2274
- import chalk25 from "chalk";
2405
+ import chalk26 from "chalk";
2275
2406
  async function del(id) {
2276
2407
  const name = removeItem(id);
2277
2408
  if (name) {
2278
- console.log(chalk25.green(`Deleted item #${id}: ${name}`));
2409
+ console.log(chalk26.green(`Deleted item #${id}: ${name}`));
2279
2410
  }
2280
2411
  }
2281
2412
 
2282
2413
  // src/commands/backlog/done/index.ts
2283
- import chalk26 from "chalk";
2414
+ import chalk27 from "chalk";
2284
2415
  async function done(id) {
2285
2416
  const name = setStatus(id, "done");
2286
2417
  if (name) {
2287
- console.log(chalk26.green(`Completed item #${id}: ${name}`));
2418
+ console.log(chalk27.green(`Completed item #${id}: ${name}`));
2288
2419
  }
2289
2420
  }
2290
2421
 
2291
2422
  // src/commands/backlog/init/index.ts
2292
2423
  import { existsSync as existsSync14 } from "fs";
2293
- import chalk27 from "chalk";
2424
+ import chalk28 from "chalk";
2294
2425
  async function init6() {
2295
2426
  const backlogPath = getBacklogPath();
2296
2427
  if (existsSync14(backlogPath)) {
2297
- console.log(chalk27.yellow("assist.backlog.yml already exists."));
2428
+ console.log(chalk28.yellow("assist.backlog.yml already exists."));
2298
2429
  return;
2299
2430
  }
2300
2431
  saveBacklog([]);
2301
- console.log(chalk27.green("Created assist.backlog.yml"));
2432
+ console.log(chalk28.green("Created assist.backlog.yml"));
2302
2433
  }
2303
2434
 
2304
2435
  // src/commands/backlog/list/index.ts
2305
2436
  import { existsSync as existsSync15 } from "fs";
2306
- import chalk28 from "chalk";
2437
+ import chalk29 from "chalk";
2307
2438
  function statusIcon(status2) {
2308
2439
  switch (status2) {
2309
2440
  case "todo":
2310
- return chalk28.dim("[ ]");
2441
+ return chalk29.dim("[ ]");
2311
2442
  case "in-progress":
2312
- return chalk28.yellow("[~]");
2443
+ return chalk29.yellow("[~]");
2313
2444
  case "done":
2314
- return chalk28.green("[x]");
2445
+ return chalk29.green("[x]");
2315
2446
  }
2316
2447
  }
2317
2448
  function typeLabel(type) {
2318
2449
  switch (type) {
2319
2450
  case "bug":
2320
- return chalk28.magenta("Bug");
2451
+ return chalk29.magenta("Bug");
2321
2452
  case "story":
2322
- return chalk28.cyan("Story");
2453
+ return chalk29.cyan("Story");
2323
2454
  }
2324
2455
  }
2325
2456
  function printVerboseDetails(item) {
2326
2457
  if (item.description) {
2327
- console.log(` ${chalk28.dim("Description:")} ${item.description}`);
2458
+ console.log(` ${chalk29.dim("Description:")} ${item.description}`);
2328
2459
  }
2329
2460
  if (item.acceptanceCriteria.length > 0) {
2330
- console.log(` ${chalk28.dim("Acceptance criteria:")}`);
2461
+ console.log(` ${chalk29.dim("Acceptance criteria:")}`);
2331
2462
  for (const criterion of item.acceptanceCriteria) {
2332
2463
  console.log(` - ${criterion}`);
2333
2464
  }
@@ -2343,7 +2474,7 @@ async function list2(options2) {
2343
2474
  const backlogPath = getBacklogPath();
2344
2475
  if (!existsSync15(backlogPath)) {
2345
2476
  console.log(
2346
- chalk28.yellow(
2477
+ chalk29.yellow(
2347
2478
  "No backlog found. Run 'assist backlog init' to create one."
2348
2479
  )
2349
2480
  );
@@ -2351,12 +2482,12 @@ async function list2(options2) {
2351
2482
  }
2352
2483
  const items = filterItems(loadBacklog(), options2);
2353
2484
  if (items.length === 0) {
2354
- console.log(chalk28.dim("Backlog is empty."));
2485
+ console.log(chalk29.dim("Backlog is empty."));
2355
2486
  return;
2356
2487
  }
2357
2488
  for (const item of items) {
2358
2489
  console.log(
2359
- `${statusIcon(item.status)} ${typeLabel(item.type)} ${chalk28.dim(`#${item.id}`)} ${item.name}`
2490
+ `${statusIcon(item.status)} ${typeLabel(item.type)} ${chalk29.dim(`#${item.id}`)} ${item.name}`
2360
2491
  );
2361
2492
  if (options2.verbose) {
2362
2493
  printVerboseDetails(item);
@@ -2365,11 +2496,11 @@ async function list2(options2) {
2365
2496
  }
2366
2497
 
2367
2498
  // src/commands/backlog/start/index.ts
2368
- import chalk29 from "chalk";
2499
+ import chalk30 from "chalk";
2369
2500
  async function start(id) {
2370
2501
  const name = setStatus(id, "in-progress");
2371
2502
  if (name) {
2372
- console.log(chalk29.green(`Started item #${id}: ${name}`));
2503
+ console.log(chalk30.green(`Started item #${id}: ${name}`));
2373
2504
  }
2374
2505
  }
2375
2506
 
@@ -2381,7 +2512,7 @@ import {
2381
2512
  } from "http";
2382
2513
  import { dirname as dirname12, join as join10 } from "path";
2383
2514
  import { fileURLToPath as fileURLToPath3 } from "url";
2384
- import chalk30 from "chalk";
2515
+ import chalk31 from "chalk";
2385
2516
  function respondJson(res, status2, data) {
2386
2517
  res.writeHead(status2, { "Content-Type": "application/json" });
2387
2518
  res.end(JSON.stringify(data));
@@ -2425,8 +2556,8 @@ function startWebServer(label2, port, handler) {
2425
2556
  handler(req, res, port);
2426
2557
  });
2427
2558
  server.listen(port, () => {
2428
- console.log(chalk30.green(`${label2}: ${url}`));
2429
- console.log(chalk30.dim("Press Ctrl+C to stop"));
2559
+ console.log(chalk31.green(`${label2}: ${url}`));
2560
+ console.log(chalk31.dim("Press Ctrl+C to stop"));
2430
2561
  exec(`open ${url}`);
2431
2562
  });
2432
2563
  }
@@ -2666,12 +2797,12 @@ function getCliReadsPath() {
2666
2797
  var cachedLines;
2667
2798
  function getCliReadsLines() {
2668
2799
  if (cachedLines) return cachedLines;
2669
- const path36 = getCliReadsPath();
2670
- if (!existsSync16(path36)) {
2800
+ const path43 = getCliReadsPath();
2801
+ if (!existsSync16(path43)) {
2671
2802
  cachedLines = [];
2672
2803
  return cachedLines;
2673
2804
  }
2674
- cachedLines = readFileSync13(path36, "utf-8").split("\n").filter((line) => line.trim() !== "");
2805
+ cachedLines = readFileSync13(path43, "utf-8").split("\n").filter((line) => line.trim() !== "");
2675
2806
  return cachedLines;
2676
2807
  }
2677
2808
  function loadCliReads() {
@@ -2917,11 +3048,11 @@ function assertCliExists(cli) {
2917
3048
  }
2918
3049
 
2919
3050
  // src/commands/permitCliReads/colorize.ts
2920
- import chalk31 from "chalk";
3051
+ import chalk32 from "chalk";
2921
3052
  function colorize(plainOutput) {
2922
3053
  return plainOutput.split("\n").map((line) => {
2923
- if (line.startsWith(" R ")) return chalk31.green(line);
2924
- if (line.startsWith(" W ")) return chalk31.red(line);
3054
+ if (line.startsWith(" R ")) return chalk32.green(line);
3055
+ if (line.startsWith(" W ")) return chalk32.red(line);
2925
3056
  return line;
2926
3057
  }).join("\n");
2927
3058
  }
@@ -3023,14 +3154,14 @@ function showProgress(p, label2) {
3023
3154
  const pct = Math.round(p.done / p.total * 100);
3024
3155
  process.stderr.write(`\r\x1B[K[${pct}%] Scanning ${label2}...`);
3025
3156
  }
3026
- async function resolveCommand(cli, path36, description, depth, p) {
3027
- showProgress(p, path36.join(" "));
3028
- const subHelp = await runHelp([cli, ...path36]);
3157
+ async function resolveCommand(cli, path43, description, depth, p) {
3158
+ showProgress(p, path43.join(" "));
3159
+ const subHelp = await runHelp([cli, ...path43]);
3029
3160
  if (!subHelp || !hasSubcommands(subHelp)) {
3030
- return [{ path: path36, description }];
3161
+ return [{ path: path43, description }];
3031
3162
  }
3032
- const children = await discoverAt(cli, path36, depth + 1, p);
3033
- return children.length > 0 ? children : [{ path: path36, description }];
3163
+ const children = await discoverAt(cli, path43, depth + 1, p);
3164
+ return children.length > 0 ? children : [{ path: path43, description }];
3034
3165
  }
3035
3166
  async function discoverAt(cli, parentPath, depth, p) {
3036
3167
  if (depth > SAFETY_DEPTH) return [];
@@ -3178,9 +3309,9 @@ function logPath(cli) {
3178
3309
  return join12(homedir4(), ".assist", `cli-discover-${safeName}.log`);
3179
3310
  }
3180
3311
  function readCache(cli) {
3181
- const path36 = logPath(cli);
3182
- if (!existsSync18(path36)) return void 0;
3183
- return readFileSync15(path36, "utf-8");
3312
+ const path43 = logPath(cli);
3313
+ if (!existsSync18(path43)) return void 0;
3314
+ return readFileSync15(path43, "utf-8");
3184
3315
  }
3185
3316
  function writeCache(cli, output) {
3186
3317
  const dir = join12(homedir4(), ".assist");
@@ -3232,20 +3363,20 @@ function registerCliHook(program2) {
3232
3363
  }
3233
3364
 
3234
3365
  // src/commands/complexity/analyze.ts
3235
- import chalk37 from "chalk";
3366
+ import chalk38 from "chalk";
3236
3367
 
3237
3368
  // src/commands/complexity/cyclomatic.ts
3238
- import chalk33 from "chalk";
3369
+ import chalk34 from "chalk";
3239
3370
 
3240
3371
  // src/commands/complexity/shared/index.ts
3241
- import fs11 from "fs";
3242
- import path17 from "path";
3243
- import chalk32 from "chalk";
3372
+ import fs13 from "fs";
3373
+ import path21 from "path";
3374
+ import chalk33 from "chalk";
3244
3375
  import ts5 from "typescript";
3245
3376
 
3246
3377
  // src/commands/complexity/findSourceFiles.ts
3247
- import fs10 from "fs";
3248
- import path16 from "path";
3378
+ import fs12 from "fs";
3379
+ import path20 from "path";
3249
3380
  import { minimatch as minimatch3 } from "minimatch";
3250
3381
  function applyIgnoreGlobs(files) {
3251
3382
  const { complexity } = loadConfig();
@@ -3254,13 +3385,13 @@ function applyIgnoreGlobs(files) {
3254
3385
  );
3255
3386
  }
3256
3387
  function walk(dir, results) {
3257
- if (!fs10.existsSync(dir)) {
3388
+ if (!fs12.existsSync(dir)) {
3258
3389
  return;
3259
3390
  }
3260
3391
  const extensions = [".ts", ".tsx"];
3261
- const entries = fs10.readdirSync(dir, { withFileTypes: true });
3392
+ const entries = fs12.readdirSync(dir, { withFileTypes: true });
3262
3393
  for (const entry of entries) {
3263
- const fullPath = path16.join(dir, entry.name);
3394
+ const fullPath = path20.join(dir, entry.name);
3264
3395
  if (entry.isDirectory()) {
3265
3396
  if (entry.name !== "node_modules" && entry.name !== ".git") {
3266
3397
  walk(fullPath, results);
@@ -3276,10 +3407,10 @@ function findSourceFiles2(pattern2, baseDir = ".") {
3276
3407
  walk(baseDir, results);
3277
3408
  return applyIgnoreGlobs(results.filter((f) => minimatch3(f, pattern2)));
3278
3409
  }
3279
- if (fs10.existsSync(pattern2) && fs10.statSync(pattern2).isFile()) {
3410
+ if (fs12.existsSync(pattern2) && fs12.statSync(pattern2).isFile()) {
3280
3411
  return [pattern2];
3281
3412
  }
3282
- if (fs10.existsSync(pattern2) && fs10.statSync(pattern2).isDirectory()) {
3413
+ if (fs12.existsSync(pattern2) && fs12.statSync(pattern2).isDirectory()) {
3283
3414
  walk(pattern2, results);
3284
3415
  return applyIgnoreGlobs(results);
3285
3416
  }
@@ -3474,9 +3605,9 @@ function countSloc(content) {
3474
3605
 
3475
3606
  // src/commands/complexity/shared/index.ts
3476
3607
  function createSourceFromFile(filePath) {
3477
- const content = fs11.readFileSync(filePath, "utf-8");
3608
+ const content = fs13.readFileSync(filePath, "utf-8");
3478
3609
  return ts5.createSourceFile(
3479
- path17.basename(filePath),
3610
+ path21.basename(filePath),
3480
3611
  content,
3481
3612
  ts5.ScriptTarget.Latest,
3482
3613
  true,
@@ -3486,7 +3617,7 @@ function createSourceFromFile(filePath) {
3486
3617
  function withSourceFiles(pattern2, callback) {
3487
3618
  const files = findSourceFiles2(pattern2);
3488
3619
  if (files.length === 0) {
3489
- console.log(chalk32.yellow("No files found matching pattern"));
3620
+ console.log(chalk33.yellow("No files found matching pattern"));
3490
3621
  return void 0;
3491
3622
  }
3492
3623
  return callback(files);
@@ -3519,11 +3650,11 @@ async function cyclomatic(pattern2 = "**/*.ts", options2 = {}) {
3519
3650
  results.sort((a, b) => b.complexity - a.complexity);
3520
3651
  for (const { file, name, complexity } of results) {
3521
3652
  const exceedsThreshold = options2.threshold !== void 0 && complexity > options2.threshold;
3522
- const color = exceedsThreshold ? chalk33.red : chalk33.white;
3523
- console.log(`${color(`${file}:${name}`)} \u2192 ${chalk33.cyan(complexity)}`);
3653
+ const color = exceedsThreshold ? chalk34.red : chalk34.white;
3654
+ console.log(`${color(`${file}:${name}`)} \u2192 ${chalk34.cyan(complexity)}`);
3524
3655
  }
3525
3656
  console.log(
3526
- chalk33.dim(
3657
+ chalk34.dim(
3527
3658
  `
3528
3659
  Analyzed ${results.length} functions across ${files.length} files`
3529
3660
  )
@@ -3535,7 +3666,7 @@ Analyzed ${results.length} functions across ${files.length} files`
3535
3666
  }
3536
3667
 
3537
3668
  // src/commands/complexity/halstead.ts
3538
- import chalk34 from "chalk";
3669
+ import chalk35 from "chalk";
3539
3670
  async function halstead(pattern2 = "**/*.ts", options2 = {}) {
3540
3671
  withSourceFiles(pattern2, (files) => {
3541
3672
  const results = [];
@@ -3550,13 +3681,13 @@ async function halstead(pattern2 = "**/*.ts", options2 = {}) {
3550
3681
  results.sort((a, b) => b.metrics.effort - a.metrics.effort);
3551
3682
  for (const { file, name, metrics } of results) {
3552
3683
  const exceedsThreshold = options2.threshold !== void 0 && metrics.volume > options2.threshold;
3553
- const color = exceedsThreshold ? chalk34.red : chalk34.white;
3684
+ const color = exceedsThreshold ? chalk35.red : chalk35.white;
3554
3685
  console.log(
3555
- `${color(`${file}:${name}`)} \u2192 volume: ${chalk34.cyan(metrics.volume.toFixed(1))}, difficulty: ${chalk34.yellow(metrics.difficulty.toFixed(1))}, effort: ${chalk34.magenta(metrics.effort.toFixed(1))}`
3686
+ `${color(`${file}:${name}`)} \u2192 volume: ${chalk35.cyan(metrics.volume.toFixed(1))}, difficulty: ${chalk35.yellow(metrics.difficulty.toFixed(1))}, effort: ${chalk35.magenta(metrics.effort.toFixed(1))}`
3556
3687
  );
3557
3688
  }
3558
3689
  console.log(
3559
- chalk34.dim(
3690
+ chalk35.dim(
3560
3691
  `
3561
3692
  Analyzed ${results.length} functions across ${files.length} files`
3562
3693
  )
@@ -3568,31 +3699,31 @@ Analyzed ${results.length} functions across ${files.length} files`
3568
3699
  }
3569
3700
 
3570
3701
  // src/commands/complexity/maintainability/index.ts
3571
- import fs12 from "fs";
3702
+ import fs14 from "fs";
3572
3703
 
3573
3704
  // src/commands/complexity/maintainability/displayMaintainabilityResults.ts
3574
- import chalk35 from "chalk";
3705
+ import chalk36 from "chalk";
3575
3706
  function displayMaintainabilityResults(results, threshold) {
3576
3707
  const filtered = threshold !== void 0 ? results.filter((r) => r.minMaintainability < threshold) : results;
3577
3708
  if (threshold !== void 0 && filtered.length === 0) {
3578
- console.log(chalk35.green("All files pass maintainability threshold"));
3709
+ console.log(chalk36.green("All files pass maintainability threshold"));
3579
3710
  } else {
3580
3711
  for (const { file, avgMaintainability, minMaintainability } of filtered) {
3581
- const color = threshold !== void 0 ? chalk35.red : chalk35.white;
3712
+ const color = threshold !== void 0 ? chalk36.red : chalk36.white;
3582
3713
  console.log(
3583
- `${color(file)} \u2192 avg: ${chalk35.cyan(avgMaintainability.toFixed(1))}, min: ${chalk35.yellow(minMaintainability.toFixed(1))}`
3714
+ `${color(file)} \u2192 avg: ${chalk36.cyan(avgMaintainability.toFixed(1))}, min: ${chalk36.yellow(minMaintainability.toFixed(1))}`
3584
3715
  );
3585
3716
  }
3586
3717
  }
3587
- console.log(chalk35.dim(`
3718
+ console.log(chalk36.dim(`
3588
3719
  Analyzed ${results.length} files`));
3589
3720
  if (filtered.length > 0 && threshold !== void 0) {
3590
3721
  console.error(
3591
- chalk35.red(
3722
+ chalk36.red(
3592
3723
  `
3593
3724
  Fail: ${filtered.length} file(s) below threshold ${threshold}. Maintainability index (0\u2013100) is derived from Halstead volume, cyclomatic complexity, and lines of code.
3594
3725
 
3595
- \u26A0\uFE0F ${chalk35.bold("Diagnose and fix one file at a time")} \u2014 do not investigate or fix multiple files in parallel. Run 'assist complexity <file>' to see all metrics. For larger files, start by extracting responsibilities into smaller files.`
3726
+ \u26A0\uFE0F ${chalk36.bold("Diagnose and fix one file at a time")} \u2014 do not investigate or fix multiple files in parallel. Run 'assist complexity <file>' to see all metrics. For larger files, start by extracting responsibilities into smaller files.`
3596
3727
  )
3597
3728
  );
3598
3729
  process.exit(1);
@@ -3610,7 +3741,7 @@ function calculateMaintainabilityIndex(halsteadVolume, cyclomaticComplexity, slo
3610
3741
  function collectFileMetrics(files) {
3611
3742
  const fileMetrics = /* @__PURE__ */ new Map();
3612
3743
  for (const file of files) {
3613
- const content = fs12.readFileSync(file, "utf-8");
3744
+ const content = fs14.readFileSync(file, "utf-8");
3614
3745
  fileMetrics.set(file, { sloc: countSloc(content), functions: [] });
3615
3746
  }
3616
3747
  forEachFunction(files, (file, _name, node) => {
@@ -3648,14 +3779,14 @@ async function maintainability(pattern2 = "**/*.ts", options2 = {}) {
3648
3779
  }
3649
3780
 
3650
3781
  // src/commands/complexity/sloc.ts
3651
- import fs13 from "fs";
3652
- import chalk36 from "chalk";
3782
+ import fs15 from "fs";
3783
+ import chalk37 from "chalk";
3653
3784
  async function sloc(pattern2 = "**/*.ts", options2 = {}) {
3654
3785
  withSourceFiles(pattern2, (files) => {
3655
3786
  const results = [];
3656
3787
  let hasViolation = false;
3657
3788
  for (const file of files) {
3658
- const content = fs13.readFileSync(file, "utf-8");
3789
+ const content = fs15.readFileSync(file, "utf-8");
3659
3790
  const lines = countSloc(content);
3660
3791
  results.push({ file, lines });
3661
3792
  if (options2.threshold !== void 0 && lines > options2.threshold) {
@@ -3665,12 +3796,12 @@ async function sloc(pattern2 = "**/*.ts", options2 = {}) {
3665
3796
  results.sort((a, b) => b.lines - a.lines);
3666
3797
  for (const { file, lines } of results) {
3667
3798
  const exceedsThreshold = options2.threshold !== void 0 && lines > options2.threshold;
3668
- const color = exceedsThreshold ? chalk36.red : chalk36.white;
3669
- console.log(`${color(file)} \u2192 ${chalk36.cyan(lines)} lines`);
3799
+ const color = exceedsThreshold ? chalk37.red : chalk37.white;
3800
+ console.log(`${color(file)} \u2192 ${chalk37.cyan(lines)} lines`);
3670
3801
  }
3671
3802
  const total = results.reduce((sum, r) => sum + r.lines, 0);
3672
3803
  console.log(
3673
- chalk36.dim(`
3804
+ chalk37.dim(`
3674
3805
  Total: ${total} lines across ${files.length} files`)
3675
3806
  );
3676
3807
  if (hasViolation) {
@@ -3684,21 +3815,21 @@ async function analyze(pattern2) {
3684
3815
  const searchPattern = pattern2.includes("*") || pattern2.includes("/") ? pattern2 : `**/${pattern2}`;
3685
3816
  const files = findSourceFiles2(searchPattern);
3686
3817
  if (files.length === 0) {
3687
- console.log(chalk37.yellow("No files found matching pattern"));
3818
+ console.log(chalk38.yellow("No files found matching pattern"));
3688
3819
  return;
3689
3820
  }
3690
3821
  if (files.length === 1) {
3691
3822
  const file = files[0];
3692
- console.log(chalk37.bold.underline("SLOC"));
3823
+ console.log(chalk38.bold.underline("SLOC"));
3693
3824
  await sloc(file);
3694
3825
  console.log();
3695
- console.log(chalk37.bold.underline("Cyclomatic Complexity"));
3826
+ console.log(chalk38.bold.underline("Cyclomatic Complexity"));
3696
3827
  await cyclomatic(file);
3697
3828
  console.log();
3698
- console.log(chalk37.bold.underline("Halstead Metrics"));
3829
+ console.log(chalk38.bold.underline("Halstead Metrics"));
3699
3830
  await halstead(file);
3700
3831
  console.log();
3701
- console.log(chalk37.bold.underline("Maintainability Index"));
3832
+ console.log(chalk38.bold.underline("Maintainability Index"));
3702
3833
  await maintainability(file);
3703
3834
  return;
3704
3835
  }
@@ -3726,7 +3857,7 @@ function registerComplexity(program2) {
3726
3857
 
3727
3858
  // src/commands/deploy/redirect.ts
3728
3859
  import { existsSync as existsSync19, readFileSync as readFileSync16, writeFileSync as writeFileSync14 } from "fs";
3729
- import chalk38 from "chalk";
3860
+ import chalk39 from "chalk";
3730
3861
  var TRAILING_SLASH_SCRIPT = ` <script>
3731
3862
  if (!window.location.pathname.endsWith('/')) {
3732
3863
  window.location.href = \`\${window.location.pathname}/\${window.location.search}\${window.location.hash}\`;
@@ -3735,22 +3866,22 @@ var TRAILING_SLASH_SCRIPT = ` <script>
3735
3866
  function redirect() {
3736
3867
  const indexPath = "index.html";
3737
3868
  if (!existsSync19(indexPath)) {
3738
- console.log(chalk38.yellow("No index.html found"));
3869
+ console.log(chalk39.yellow("No index.html found"));
3739
3870
  return;
3740
3871
  }
3741
3872
  const content = readFileSync16(indexPath, "utf-8");
3742
3873
  if (content.includes("window.location.pathname.endsWith('/')")) {
3743
- console.log(chalk38.dim("Trailing slash script already present"));
3874
+ console.log(chalk39.dim("Trailing slash script already present"));
3744
3875
  return;
3745
3876
  }
3746
3877
  const headCloseIndex = content.indexOf("</head>");
3747
3878
  if (headCloseIndex === -1) {
3748
- console.log(chalk38.red("Could not find </head> tag in index.html"));
3879
+ console.log(chalk39.red("Could not find </head> tag in index.html"));
3749
3880
  return;
3750
3881
  }
3751
3882
  const newContent = content.slice(0, headCloseIndex) + TRAILING_SLASH_SCRIPT + "\n " + content.slice(headCloseIndex);
3752
3883
  writeFileSync14(indexPath, newContent);
3753
- console.log(chalk38.green("Added trailing slash redirect to index.html"));
3884
+ console.log(chalk39.green("Added trailing slash redirect to index.html"));
3754
3885
  }
3755
3886
 
3756
3887
  // src/commands/registerDeploy.ts
@@ -3777,7 +3908,7 @@ function loadBlogSkipDays(repoName) {
3777
3908
 
3778
3909
  // src/commands/devlog/shared.ts
3779
3910
  import { execSync as execSync15 } from "child_process";
3780
- import chalk39 from "chalk";
3911
+ import chalk40 from "chalk";
3781
3912
 
3782
3913
  // src/commands/devlog/loadDevlogEntries.ts
3783
3914
  import { readdirSync, readFileSync as readFileSync17 } from "fs";
@@ -3864,13 +3995,13 @@ function shouldIgnoreCommit(files, ignorePaths) {
3864
3995
  }
3865
3996
  function printCommitsWithFiles(commits, ignore2, verbose) {
3866
3997
  for (const commit2 of commits) {
3867
- console.log(` ${chalk39.yellow(commit2.hash)} ${commit2.message}`);
3998
+ console.log(` ${chalk40.yellow(commit2.hash)} ${commit2.message}`);
3868
3999
  if (verbose) {
3869
4000
  const visibleFiles = commit2.files.filter(
3870
4001
  (file) => !ignore2.some((p) => file.startsWith(p))
3871
4002
  );
3872
4003
  for (const file of visibleFiles) {
3873
- console.log(` ${chalk39.dim(file)}`);
4004
+ console.log(` ${chalk40.dim(file)}`);
3874
4005
  }
3875
4006
  }
3876
4007
  }
@@ -3895,15 +4026,15 @@ function parseGitLogCommits(output, ignore2, afterDate) {
3895
4026
  }
3896
4027
 
3897
4028
  // src/commands/devlog/list/printDateHeader.ts
3898
- import chalk40 from "chalk";
4029
+ import chalk41 from "chalk";
3899
4030
  function printDateHeader(date, isSkipped, entries) {
3900
4031
  if (isSkipped) {
3901
- console.log(`${chalk40.bold.blue(date)} ${chalk40.dim("skipped")}`);
4032
+ console.log(`${chalk41.bold.blue(date)} ${chalk41.dim("skipped")}`);
3902
4033
  } else if (entries && entries.length > 0) {
3903
- const entryInfo = entries.map((e) => `${chalk40.green(e.version)} ${e.title}`).join(" | ");
3904
- console.log(`${chalk40.bold.blue(date)} ${entryInfo}`);
4034
+ const entryInfo = entries.map((e) => `${chalk41.green(e.version)} ${e.title}`).join(" | ");
4035
+ console.log(`${chalk41.bold.blue(date)} ${entryInfo}`);
3905
4036
  } else {
3906
- console.log(`${chalk40.bold.blue(date)} ${chalk40.red("\u26A0 devlog missing")}`);
4037
+ console.log(`${chalk41.bold.blue(date)} ${chalk41.red("\u26A0 devlog missing")}`);
3907
4038
  }
3908
4039
  }
3909
4040
 
@@ -4006,24 +4137,24 @@ function bumpVersion(version2, type) {
4006
4137
 
4007
4138
  // src/commands/devlog/next/displayNextEntry/index.ts
4008
4139
  import { execSync as execSync18 } from "child_process";
4009
- import chalk42 from "chalk";
4140
+ import chalk43 from "chalk";
4010
4141
 
4011
4142
  // src/commands/devlog/next/displayNextEntry/displayVersion.ts
4012
- import chalk41 from "chalk";
4143
+ import chalk42 from "chalk";
4013
4144
  function displayVersion(conventional, firstHash, patchVersion, minorVersion) {
4014
4145
  if (conventional && firstHash) {
4015
4146
  const version2 = getVersionAtCommit(firstHash);
4016
4147
  if (version2) {
4017
- console.log(`${chalk41.bold("version:")} ${stripToMinor(version2)}`);
4148
+ console.log(`${chalk42.bold("version:")} ${stripToMinor(version2)}`);
4018
4149
  } else {
4019
- console.log(`${chalk41.bold("version:")} ${chalk41.red("unknown")}`);
4150
+ console.log(`${chalk42.bold("version:")} ${chalk42.red("unknown")}`);
4020
4151
  }
4021
4152
  } else if (patchVersion && minorVersion) {
4022
4153
  console.log(
4023
- `${chalk41.bold("version:")} ${patchVersion} (patch) or ${minorVersion} (minor)`
4154
+ `${chalk42.bold("version:")} ${patchVersion} (patch) or ${minorVersion} (minor)`
4024
4155
  );
4025
4156
  } else {
4026
- console.log(`${chalk41.bold("version:")} v0.1 (initial)`);
4157
+ console.log(`${chalk42.bold("version:")} v0.1 (initial)`);
4027
4158
  }
4028
4159
  }
4029
4160
 
@@ -4070,16 +4201,16 @@ function noCommitsMessage(hasLastInfo) {
4070
4201
  return hasLastInfo ? "No commits after last versioned entry" : "No commits found";
4071
4202
  }
4072
4203
  function logName(repoName) {
4073
- console.log(`${chalk42.bold("name:")} ${repoName}`);
4204
+ console.log(`${chalk43.bold("name:")} ${repoName}`);
4074
4205
  }
4075
4206
  function displayNextEntry(ctx, targetDate, commits) {
4076
4207
  logName(ctx.repoName);
4077
4208
  printVersionInfo(ctx.config, ctx.lastInfo, commits[0]?.hash);
4078
- console.log(chalk42.bold.blue(targetDate));
4209
+ console.log(chalk43.bold.blue(targetDate));
4079
4210
  printCommitsWithFiles(commits, ctx.ignore, ctx.verbose);
4080
4211
  }
4081
4212
  function logNoCommits(lastInfo) {
4082
- console.log(chalk42.dim(noCommitsMessage(!!lastInfo)));
4213
+ console.log(chalk43.dim(noCommitsMessage(!!lastInfo)));
4083
4214
  }
4084
4215
 
4085
4216
  // src/commands/devlog/next/index.ts
@@ -4120,11 +4251,11 @@ function next(options2) {
4120
4251
  import { execSync as execSync19 } from "child_process";
4121
4252
 
4122
4253
  // src/commands/devlog/repos/printReposTable.ts
4123
- import chalk43 from "chalk";
4254
+ import chalk44 from "chalk";
4124
4255
  function colorStatus(status2) {
4125
- if (status2 === "missing") return chalk43.red(status2);
4126
- if (status2 === "outdated") return chalk43.yellow(status2);
4127
- return chalk43.green(status2);
4256
+ if (status2 === "missing") return chalk44.red(status2);
4257
+ if (status2 === "outdated") return chalk44.yellow(status2);
4258
+ return chalk44.green(status2);
4128
4259
  }
4129
4260
  function formatRow(row, nameWidth) {
4130
4261
  const devlog = (row.lastDevlog ?? "-").padEnd(11);
@@ -4138,8 +4269,8 @@ function printReposTable(rows) {
4138
4269
  "Last Devlog".padEnd(11),
4139
4270
  "Status"
4140
4271
  ].join(" ");
4141
- console.log(chalk43.dim(header));
4142
- console.log(chalk43.dim("-".repeat(header.length)));
4272
+ console.log(chalk44.dim(header));
4273
+ console.log(chalk44.dim("-".repeat(header.length)));
4143
4274
  for (const row of rows) {
4144
4275
  console.log(formatRow(row, nameWidth));
4145
4276
  }
@@ -4197,14 +4328,14 @@ function repos(options2) {
4197
4328
  // src/commands/devlog/skip.ts
4198
4329
  import { writeFileSync as writeFileSync15 } from "fs";
4199
4330
  import { join as join15 } from "path";
4200
- import chalk44 from "chalk";
4331
+ import chalk45 from "chalk";
4201
4332
  import { stringify as stringifyYaml4 } from "yaml";
4202
4333
  function getBlogConfigPath() {
4203
4334
  return join15(BLOG_REPO_ROOT, "assist.yml");
4204
4335
  }
4205
4336
  function skip(date) {
4206
4337
  if (!/^\d{4}-\d{2}-\d{2}$/.test(date)) {
4207
- console.log(chalk44.red("Invalid date format. Use YYYY-MM-DD"));
4338
+ console.log(chalk45.red("Invalid date format. Use YYYY-MM-DD"));
4208
4339
  process.exit(1);
4209
4340
  }
4210
4341
  const repoName = getRepoName();
@@ -4215,7 +4346,7 @@ function skip(date) {
4215
4346
  const skipDays = skip2[repoName] ?? [];
4216
4347
  if (skipDays.includes(date)) {
4217
4348
  console.log(
4218
- chalk44.yellow(`${date} is already in skip list for ${repoName}`)
4349
+ chalk45.yellow(`${date} is already in skip list for ${repoName}`)
4219
4350
  );
4220
4351
  return;
4221
4352
  }
@@ -4225,20 +4356,20 @@ function skip(date) {
4225
4356
  devlog.skip = skip2;
4226
4357
  config.devlog = devlog;
4227
4358
  writeFileSync15(configPath, stringifyYaml4(config, { lineWidth: 0 }));
4228
- console.log(chalk44.green(`Added ${date} to skip list for ${repoName}`));
4359
+ console.log(chalk45.green(`Added ${date} to skip list for ${repoName}`));
4229
4360
  }
4230
4361
 
4231
4362
  // src/commands/devlog/version.ts
4232
- import chalk45 from "chalk";
4363
+ import chalk46 from "chalk";
4233
4364
  function version() {
4234
4365
  const config = loadConfig();
4235
4366
  const name = getRepoName();
4236
4367
  const lastInfo = getLastVersionInfo(name, config);
4237
4368
  const lastVersion = lastInfo?.version ?? null;
4238
4369
  const nextVersion = lastVersion ? bumpVersion(lastVersion, "patch") : null;
4239
- console.log(`${chalk45.bold("name:")} ${name}`);
4240
- console.log(`${chalk45.bold("last:")} ${lastVersion ?? chalk45.dim("none")}`);
4241
- console.log(`${chalk45.bold("next:")} ${nextVersion ?? chalk45.dim("none")}`);
4370
+ console.log(`${chalk46.bold("name:")} ${name}`);
4371
+ console.log(`${chalk46.bold("last:")} ${lastVersion ?? chalk46.dim("none")}`);
4372
+ console.log(`${chalk46.bold("next:")} ${nextVersion ?? chalk46.dim("none")}`);
4242
4373
  }
4243
4374
 
4244
4375
  // src/commands/registerDevlog.ts
@@ -4261,7 +4392,7 @@ function registerDevlog(program2) {
4261
4392
 
4262
4393
  // src/commands/jira/acceptanceCriteria.ts
4263
4394
  import { execSync as execSync20 } from "child_process";
4264
- import chalk46 from "chalk";
4395
+ import chalk47 from "chalk";
4265
4396
 
4266
4397
  // src/commands/jira/adfToText.ts
4267
4398
  function renderInline(node) {
@@ -4336,21 +4467,21 @@ function acceptanceCriteria(issueKey) {
4336
4467
  const stderr = error.stderr;
4337
4468
  if (stderr.includes("unauthorized")) {
4338
4469
  console.error(
4339
- chalk46.red("Jira authentication expired."),
4470
+ chalk47.red("Jira authentication expired."),
4340
4471
  "Run",
4341
- chalk46.cyan("assist jira auth"),
4472
+ chalk47.cyan("assist jira auth"),
4342
4473
  "to re-authenticate."
4343
4474
  );
4344
4475
  process.exit(1);
4345
4476
  }
4346
4477
  }
4347
- console.error(chalk46.red(`Failed to fetch ${issueKey}.`));
4478
+ console.error(chalk47.red(`Failed to fetch ${issueKey}.`));
4348
4479
  process.exit(1);
4349
4480
  }
4350
4481
  const parsed = JSON.parse(result);
4351
4482
  const acValue = parsed?.fields?.[field];
4352
4483
  if (!acValue) {
4353
- console.log(chalk46.yellow(`No acceptance criteria found on ${issueKey}.`));
4484
+ console.log(chalk47.yellow(`No acceptance criteria found on ${issueKey}.`));
4354
4485
  return;
4355
4486
  }
4356
4487
  if (typeof acValue === "string") {
@@ -4379,10 +4510,10 @@ function getStorePath(filename) {
4379
4510
  return join16(getStoreDir(), filename);
4380
4511
  }
4381
4512
  function loadJson(filename) {
4382
- const path36 = getStorePath(filename);
4383
- if (existsSync20(path36)) {
4513
+ const path43 = getStorePath(filename);
4514
+ if (existsSync20(path43)) {
4384
4515
  try {
4385
- return JSON.parse(readFileSync18(path36, "utf-8"));
4516
+ return JSON.parse(readFileSync18(path43, "utf-8"));
4386
4517
  } catch {
4387
4518
  return {};
4388
4519
  }
@@ -4449,7 +4580,7 @@ function registerJira(program2) {
4449
4580
 
4450
4581
  // src/commands/netframework/buildTree.ts
4451
4582
  import { readFileSync as readFileSync19 } from "fs";
4452
- import path18 from "path";
4583
+ import path22 from "path";
4453
4584
  var PROJECT_REF_RE = /<ProjectReference\s+Include="([^"]+)"/g;
4454
4585
  function getProjectRefs(csprojPath) {
4455
4586
  const content = readFileSync19(csprojPath, "utf-8");
@@ -4460,14 +4591,14 @@ function getProjectRefs(csprojPath) {
4460
4591
  return refs;
4461
4592
  }
4462
4593
  function buildTree(csprojPath, repoRoot, visited = /* @__PURE__ */ new Set()) {
4463
- const abs = path18.resolve(csprojPath);
4464
- const rel = path18.relative(repoRoot, abs);
4594
+ const abs = path22.resolve(csprojPath);
4595
+ const rel = path22.relative(repoRoot, abs);
4465
4596
  const node = { path: abs, relativePath: rel, children: [] };
4466
4597
  if (visited.has(abs)) return node;
4467
4598
  visited.add(abs);
4468
- const dir = path18.dirname(abs);
4599
+ const dir = path22.dirname(abs);
4469
4600
  for (const ref of getProjectRefs(abs)) {
4470
- const childAbs = path18.resolve(dir, ref);
4601
+ const childAbs = path22.resolve(dir, ref);
4471
4602
  try {
4472
4603
  readFileSync19(childAbs);
4473
4604
  node.children.push(buildTree(childAbs, repoRoot, visited));
@@ -4495,7 +4626,7 @@ function collectAllDeps(node) {
4495
4626
 
4496
4627
  // src/commands/netframework/findContainingSolutions.ts
4497
4628
  import { readdirSync as readdirSync2, readFileSync as readFileSync20, statSync } from "fs";
4498
- import path19 from "path";
4629
+ import path23 from "path";
4499
4630
  function findSlnFiles(dir, maxDepth, depth = 0) {
4500
4631
  if (depth > maxDepth) return [];
4501
4632
  const results = [];
@@ -4508,7 +4639,7 @@ function findSlnFiles(dir, maxDepth, depth = 0) {
4508
4639
  for (const entry of entries) {
4509
4640
  if (entry.startsWith(".") || entry === "node_modules" || entry === "packages")
4510
4641
  continue;
4511
- const full = path19.join(dir, entry);
4642
+ const full = path23.join(dir, entry);
4512
4643
  try {
4513
4644
  const stat = statSync(full);
4514
4645
  if (stat.isFile() && entry.endsWith(".sln")) {
@@ -4522,8 +4653,8 @@ function findSlnFiles(dir, maxDepth, depth = 0) {
4522
4653
  return results;
4523
4654
  }
4524
4655
  function findContainingSolutions(csprojPath, repoRoot) {
4525
- const csprojAbs = path19.resolve(csprojPath);
4526
- const csprojBasename = path19.basename(csprojAbs);
4656
+ const csprojAbs = path23.resolve(csprojPath);
4657
+ const csprojBasename = path23.basename(csprojAbs);
4527
4658
  const slnFiles = findSlnFiles(repoRoot, 3);
4528
4659
  const matches = [];
4529
4660
  const pattern2 = new RegExp(`[\\\\"/]${escapeRegex(csprojBasename)}"`);
@@ -4531,7 +4662,7 @@ function findContainingSolutions(csprojPath, repoRoot) {
4531
4662
  try {
4532
4663
  const content = readFileSync20(sln, "utf-8");
4533
4664
  if (pattern2.test(content)) {
4534
- matches.push(path19.relative(repoRoot, sln));
4665
+ matches.push(path23.relative(repoRoot, sln));
4535
4666
  }
4536
4667
  } catch {
4537
4668
  }
@@ -4543,30 +4674,30 @@ function escapeRegex(s) {
4543
4674
  }
4544
4675
 
4545
4676
  // src/commands/netframework/printTree.ts
4546
- import chalk47 from "chalk";
4677
+ import chalk48 from "chalk";
4547
4678
  function printNodes(nodes, prefix2) {
4548
4679
  for (let i = 0; i < nodes.length; i++) {
4549
4680
  const isLast = i === nodes.length - 1;
4550
4681
  const connector = isLast ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
4551
4682
  const childPrefix = isLast ? " " : "\u2502 ";
4552
4683
  const isMissing = nodes[i].relativePath.startsWith("[MISSING]");
4553
- const label2 = isMissing ? chalk47.red(nodes[i].relativePath) : nodes[i].relativePath;
4684
+ const label2 = isMissing ? chalk48.red(nodes[i].relativePath) : nodes[i].relativePath;
4554
4685
  console.log(`${prefix2}${connector}${label2}`);
4555
4686
  printNodes(nodes[i].children, prefix2 + childPrefix);
4556
4687
  }
4557
4688
  }
4558
4689
  function printTree(tree, totalCount, solutions) {
4559
- console.log(chalk47.bold("\nProject Dependency Tree"));
4560
- console.log(chalk47.cyan(tree.relativePath));
4690
+ console.log(chalk48.bold("\nProject Dependency Tree"));
4691
+ console.log(chalk48.cyan(tree.relativePath));
4561
4692
  printNodes(tree.children, "");
4562
- console.log(chalk47.dim(`
4693
+ console.log(chalk48.dim(`
4563
4694
  ${totalCount} projects total (including root)`));
4564
- console.log(chalk47.bold("\nSolution Membership"));
4695
+ console.log(chalk48.bold("\nSolution Membership"));
4565
4696
  if (solutions.length === 0) {
4566
- console.log(chalk47.yellow(" Not found in any .sln"));
4697
+ console.log(chalk48.yellow(" Not found in any .sln"));
4567
4698
  } else {
4568
4699
  for (const sln of solutions) {
4569
- console.log(` ${chalk47.green(sln)}`);
4700
+ console.log(` ${chalk48.green(sln)}`);
4570
4701
  }
4571
4702
  }
4572
4703
  console.log();
@@ -4594,33 +4725,33 @@ function printJson(tree, totalCount, solutions) {
4594
4725
 
4595
4726
  // src/commands/netframework/resolveCsproj.ts
4596
4727
  import { existsSync as existsSync22 } from "fs";
4597
- import path21 from "path";
4598
- import chalk48 from "chalk";
4728
+ import path25 from "path";
4729
+ import chalk49 from "chalk";
4599
4730
 
4600
4731
  // src/commands/netframework/findRepoRoot.ts
4601
4732
  import { existsSync as existsSync21 } from "fs";
4602
- import path20 from "path";
4733
+ import path24 from "path";
4603
4734
  function findRepoRoot(dir) {
4604
4735
  let current = dir;
4605
- while (current !== path20.dirname(current)) {
4606
- if (existsSync21(path20.join(current, ".git"))) {
4736
+ while (current !== path24.dirname(current)) {
4737
+ if (existsSync21(path24.join(current, ".git"))) {
4607
4738
  return current;
4608
4739
  }
4609
- current = path20.dirname(current);
4740
+ current = path24.dirname(current);
4610
4741
  }
4611
4742
  return null;
4612
4743
  }
4613
4744
 
4614
4745
  // src/commands/netframework/resolveCsproj.ts
4615
4746
  function resolveCsproj(csprojPath) {
4616
- const resolved = path21.resolve(csprojPath);
4747
+ const resolved = path25.resolve(csprojPath);
4617
4748
  if (!existsSync22(resolved)) {
4618
- console.error(chalk48.red(`File not found: ${resolved}`));
4749
+ console.error(chalk49.red(`File not found: ${resolved}`));
4619
4750
  process.exit(1);
4620
4751
  }
4621
- const repoRoot = findRepoRoot(path21.dirname(resolved));
4752
+ const repoRoot = findRepoRoot(path25.dirname(resolved));
4622
4753
  if (!repoRoot) {
4623
- console.error(chalk48.red("Could not find git repository root"));
4754
+ console.error(chalk49.red("Could not find git repository root"));
4624
4755
  process.exit(1);
4625
4756
  }
4626
4757
  return { resolved, repoRoot };
@@ -4640,12 +4771,12 @@ async function deps(csprojPath, options2) {
4640
4771
  }
4641
4772
 
4642
4773
  // src/commands/netframework/inSln.ts
4643
- import chalk49 from "chalk";
4774
+ import chalk50 from "chalk";
4644
4775
  async function inSln(csprojPath) {
4645
4776
  const { resolved, repoRoot } = resolveCsproj(csprojPath);
4646
4777
  const solutions = findContainingSolutions(resolved, repoRoot);
4647
4778
  if (solutions.length === 0) {
4648
- console.log(chalk49.yellow("Not found in any .sln file"));
4779
+ console.log(chalk50.yellow("Not found in any .sln file"));
4649
4780
  process.exit(1);
4650
4781
  }
4651
4782
  for (const sln of solutions) {
@@ -4661,7 +4792,7 @@ function registerNetframework(program2) {
4661
4792
  }
4662
4793
 
4663
4794
  // src/commands/news/add/index.ts
4664
- import chalk50 from "chalk";
4795
+ import chalk51 from "chalk";
4665
4796
  import enquirer5 from "enquirer";
4666
4797
  async function add2(url) {
4667
4798
  if (!url) {
@@ -4684,17 +4815,17 @@ async function add2(url) {
4684
4815
  const news = config.news ?? {};
4685
4816
  const feeds = news.feeds ?? [];
4686
4817
  if (feeds.includes(url)) {
4687
- console.log(chalk50.yellow("Feed already exists in config"));
4818
+ console.log(chalk51.yellow("Feed already exists in config"));
4688
4819
  return;
4689
4820
  }
4690
4821
  feeds.push(url);
4691
4822
  config.news = { ...news, feeds };
4692
4823
  saveGlobalConfig(config);
4693
- console.log(chalk50.green(`Added feed: ${url}`));
4824
+ console.log(chalk51.green(`Added feed: ${url}`));
4694
4825
  }
4695
4826
 
4696
4827
  // src/commands/news/web/handleRequest.ts
4697
- import chalk51 from "chalk";
4828
+ import chalk52 from "chalk";
4698
4829
 
4699
4830
  // src/commands/news/web/shared.ts
4700
4831
  import { decodeHTML } from "entities";
@@ -4830,17 +4961,17 @@ function prefetch() {
4830
4961
  const config = loadConfig();
4831
4962
  const total = config.news.feeds.length;
4832
4963
  if (total === 0) return;
4833
- process.stdout.write(chalk51.dim(`Fetching ${total} feed(s)\u2026 `));
4964
+ process.stdout.write(chalk52.dim(`Fetching ${total} feed(s)\u2026 `));
4834
4965
  prefetchPromise = fetchFeeds(config.news.feeds, (done2, t) => {
4835
4966
  const width = 20;
4836
4967
  const filled = Math.round(done2 / t * width);
4837
4968
  const bar = `${"\u2588".repeat(filled)}${"\u2591".repeat(width - filled)}`;
4838
4969
  process.stdout.write(
4839
- `\r${chalk51.dim(`Fetching feeds ${bar} ${done2}/${t}`)}`
4970
+ `\r${chalk52.dim(`Fetching feeds ${bar} ${done2}/${t}`)}`
4840
4971
  );
4841
4972
  }).then((items) => {
4842
4973
  process.stdout.write(
4843
- `\r${chalk51.green(`Fetched ${items.length} items from ${total} feed(s)`)}
4974
+ `\r${chalk52.green(`Fetched ${items.length} items from ${total} feed(s)`)}
4844
4975
  `
4845
4976
  );
4846
4977
  cachedItems = items;
@@ -4955,7 +5086,7 @@ function validateLine(line) {
4955
5086
  process.exit(1);
4956
5087
  }
4957
5088
  }
4958
- function comment(path36, line, body) {
5089
+ function comment(path43, line, body) {
4959
5090
  validateBody(body);
4960
5091
  validateLine(line);
4961
5092
  try {
@@ -4975,7 +5106,7 @@ function comment(path36, line, body) {
4975
5106
  "-f",
4976
5107
  `body=${body}`,
4977
5108
  "-f",
4978
- `path=${path36}`,
5109
+ `path=${path43}`,
4979
5110
  "-F",
4980
5111
  `line=${line}`
4981
5112
  ],
@@ -4984,7 +5115,7 @@ function comment(path36, line, body) {
4984
5115
  if (result.status !== 0) {
4985
5116
  throw new Error(result.stderr || result.stdout);
4986
5117
  }
4987
- console.log(`Added review comment on ${path36}:${line}`);
5118
+ console.log(`Added review comment on ${path43}:${line}`);
4988
5119
  } finally {
4989
5120
  unlinkSync3(queryFile);
4990
5121
  }
@@ -5201,20 +5332,20 @@ function fetchLineComments(org, repo, prNumber, threadInfo) {
5201
5332
  }
5202
5333
 
5203
5334
  // src/commands/prs/listComments/printComments.ts
5204
- import chalk52 from "chalk";
5335
+ import chalk53 from "chalk";
5205
5336
  function formatForHuman(comment2) {
5206
5337
  if (comment2.type === "review") {
5207
- const stateColor = comment2.state === "APPROVED" ? chalk52.green : comment2.state === "CHANGES_REQUESTED" ? chalk52.red : chalk52.yellow;
5338
+ const stateColor = comment2.state === "APPROVED" ? chalk53.green : comment2.state === "CHANGES_REQUESTED" ? chalk53.red : chalk53.yellow;
5208
5339
  return [
5209
- `${chalk52.cyan("Review")} by ${chalk52.bold(comment2.user)} ${stateColor(`[${comment2.state}]`)}`,
5340
+ `${chalk53.cyan("Review")} by ${chalk53.bold(comment2.user)} ${stateColor(`[${comment2.state}]`)}`,
5210
5341
  comment2.body,
5211
5342
  ""
5212
5343
  ].join("\n");
5213
5344
  }
5214
5345
  const location = comment2.line ? `:${comment2.line}` : "";
5215
5346
  return [
5216
- `${chalk52.cyan("Line comment")} by ${chalk52.bold(comment2.user)} on ${chalk52.dim(`${comment2.path}${location}`)}`,
5217
- chalk52.dim(comment2.diff_hunk.split("\n").slice(-3).join("\n")),
5347
+ `${chalk53.cyan("Line comment")} by ${chalk53.bold(comment2.user)} on ${chalk53.dim(`${comment2.path}${location}`)}`,
5348
+ chalk53.dim(comment2.diff_hunk.split("\n").slice(-3).join("\n")),
5218
5349
  comment2.body,
5219
5350
  ""
5220
5351
  ].join("\n");
@@ -5304,13 +5435,13 @@ import { execSync as execSync27 } from "child_process";
5304
5435
  import enquirer6 from "enquirer";
5305
5436
 
5306
5437
  // src/commands/prs/prs/displayPaginated/printPr.ts
5307
- import chalk53 from "chalk";
5438
+ import chalk54 from "chalk";
5308
5439
  var STATUS_MAP = {
5309
- MERGED: (pr) => pr.mergedAt ? { label: chalk53.magenta("merged"), date: pr.mergedAt } : null,
5310
- CLOSED: (pr) => pr.closedAt ? { label: chalk53.red("closed"), date: pr.closedAt } : null
5440
+ MERGED: (pr) => pr.mergedAt ? { label: chalk54.magenta("merged"), date: pr.mergedAt } : null,
5441
+ CLOSED: (pr) => pr.closedAt ? { label: chalk54.red("closed"), date: pr.closedAt } : null
5311
5442
  };
5312
5443
  function defaultStatus(pr) {
5313
- return { label: chalk53.green("opened"), date: pr.createdAt };
5444
+ return { label: chalk54.green("opened"), date: pr.createdAt };
5314
5445
  }
5315
5446
  function getStatus2(pr) {
5316
5447
  return STATUS_MAP[pr.state]?.(pr) ?? defaultStatus(pr);
@@ -5319,11 +5450,11 @@ function formatDate(dateStr) {
5319
5450
  return new Date(dateStr).toISOString().split("T")[0];
5320
5451
  }
5321
5452
  function formatPrHeader(pr, status2) {
5322
- return `${chalk53.cyan(`#${pr.number}`)} ${pr.title} ${chalk53.dim(`(${pr.author.login},`)} ${status2.label} ${chalk53.dim(`${formatDate(status2.date)})`)}`;
5453
+ return `${chalk54.cyan(`#${pr.number}`)} ${pr.title} ${chalk54.dim(`(${pr.author.login},`)} ${status2.label} ${chalk54.dim(`${formatDate(status2.date)})`)}`;
5323
5454
  }
5324
5455
  function logPrDetails(pr) {
5325
5456
  console.log(
5326
- chalk53.dim(` ${pr.changedFiles.toLocaleString()} files | ${pr.url}`)
5457
+ chalk54.dim(` ${pr.changedFiles.toLocaleString()} files | ${pr.url}`)
5327
5458
  );
5328
5459
  console.log();
5329
5460
  }
@@ -5483,17 +5614,17 @@ function registerPrs(program2) {
5483
5614
  prsCommand.command("wontfix <comment-id> <reason>").description("Reply with reason and resolve thread").action((commentId, reason) => {
5484
5615
  wontfix(Number.parseInt(commentId, 10), reason);
5485
5616
  });
5486
- prsCommand.command("comment <path> <line> <body>").description("Add a line comment to the pending review").action((path36, line, body) => {
5487
- comment(path36, Number.parseInt(line, 10), body);
5617
+ prsCommand.command("comment <path> <line> <body>").description("Add a line comment to the pending review").action((path43, line, body) => {
5618
+ comment(path43, Number.parseInt(line, 10), body);
5488
5619
  });
5489
5620
  }
5490
5621
 
5491
5622
  // src/commands/refactor/check/index.ts
5492
5623
  import { spawn as spawn3 } from "child_process";
5493
- import * as path22 from "path";
5624
+ import * as path26 from "path";
5494
5625
 
5495
5626
  // src/commands/refactor/logViolations.ts
5496
- import chalk54 from "chalk";
5627
+ import chalk55 from "chalk";
5497
5628
  var DEFAULT_MAX_LINES = 100;
5498
5629
  function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
5499
5630
  if (violations.length === 0) {
@@ -5502,43 +5633,43 @@ function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
5502
5633
  }
5503
5634
  return;
5504
5635
  }
5505
- console.error(chalk54.red(`
5636
+ console.error(chalk55.red(`
5506
5637
  Refactor check failed:
5507
5638
  `));
5508
- console.error(chalk54.red(` The following files exceed ${maxLines} lines:
5639
+ console.error(chalk55.red(` The following files exceed ${maxLines} lines:
5509
5640
  `));
5510
5641
  for (const violation of violations) {
5511
- console.error(chalk54.red(` ${violation.file} (${violation.lines} lines)`));
5642
+ console.error(chalk55.red(` ${violation.file} (${violation.lines} lines)`));
5512
5643
  }
5513
5644
  console.error(
5514
- chalk54.yellow(
5645
+ chalk55.yellow(
5515
5646
  `
5516
5647
  Each file needs to be sensibly refactored, or if there is no sensible
5517
5648
  way to refactor it, ignore it with:
5518
5649
  `
5519
5650
  )
5520
5651
  );
5521
- console.error(chalk54.gray(` assist refactor ignore <file>
5652
+ console.error(chalk55.gray(` assist refactor ignore <file>
5522
5653
  `));
5523
5654
  if (process.env.CLAUDECODE) {
5524
- console.error(chalk54.cyan(`
5655
+ console.error(chalk55.cyan(`
5525
5656
  ## Extracting Code to New Files
5526
5657
  `));
5527
5658
  console.error(
5528
- chalk54.cyan(
5659
+ chalk55.cyan(
5529
5660
  ` When extracting logic from one file to another, consider where the extracted code belongs:
5530
5661
  `
5531
5662
  )
5532
5663
  );
5533
5664
  console.error(
5534
- chalk54.cyan(
5665
+ chalk55.cyan(
5535
5666
  ` 1. Keep related logic together: If the extracted code is tightly coupled to the
5536
5667
  original file's domain, create a new folder containing both the original and extracted files.
5537
5668
  `
5538
5669
  )
5539
5670
  );
5540
5671
  console.error(
5541
- chalk54.cyan(
5672
+ chalk55.cyan(
5542
5673
  ` 2. Share common utilities: If the extracted code can be reused across multiple
5543
5674
  domains, move it to a common/shared folder.
5544
5675
  `
@@ -5549,17 +5680,17 @@ Refactor check failed:
5549
5680
 
5550
5681
  // src/commands/refactor/check/getViolations/index.ts
5551
5682
  import { execSync as execSync29 } from "child_process";
5552
- import fs15 from "fs";
5683
+ import fs17 from "fs";
5553
5684
  import { minimatch as minimatch4 } from "minimatch";
5554
5685
 
5555
5686
  // src/commands/refactor/check/getViolations/getIgnoredFiles.ts
5556
- import fs14 from "fs";
5687
+ import fs16 from "fs";
5557
5688
  var REFACTOR_YML_PATH = "refactor.yml";
5558
5689
  function parseRefactorYml() {
5559
- if (!fs14.existsSync(REFACTOR_YML_PATH)) {
5690
+ if (!fs16.existsSync(REFACTOR_YML_PATH)) {
5560
5691
  return [];
5561
5692
  }
5562
- const content = fs14.readFileSync(REFACTOR_YML_PATH, "utf-8");
5693
+ const content = fs16.readFileSync(REFACTOR_YML_PATH, "utf-8");
5563
5694
  const entries = [];
5564
5695
  const lines = content.split("\n");
5565
5696
  let currentEntry = {};
@@ -5589,7 +5720,7 @@ function getIgnoredFiles() {
5589
5720
 
5590
5721
  // src/commands/refactor/check/getViolations/index.ts
5591
5722
  function countLines(filePath) {
5592
- const content = fs15.readFileSync(filePath, "utf-8");
5723
+ const content = fs17.readFileSync(filePath, "utf-8");
5593
5724
  return content.split("\n").length;
5594
5725
  }
5595
5726
  function getGitFiles(options2) {
@@ -5667,7 +5798,7 @@ ${failed.length} verify script(s) failed:`);
5667
5798
  async function runVerifyQuietly() {
5668
5799
  const result = findPackageJsonWithVerifyScripts(process.cwd());
5669
5800
  if (!result) return true;
5670
- const packageDir = path22.dirname(result.packageJsonPath);
5801
+ const packageDir = path26.dirname(result.packageJsonPath);
5671
5802
  const results = await Promise.all(
5672
5803
  result.verifyScripts.map((script) => runScript(script, packageDir))
5673
5804
  );
@@ -5693,39 +5824,147 @@ async function check(pattern2, options2) {
5693
5824
  }
5694
5825
 
5695
5826
  // src/commands/refactor/ignore.ts
5696
- import fs16 from "fs";
5697
- import chalk55 from "chalk";
5827
+ import fs18 from "fs";
5828
+ import chalk56 from "chalk";
5698
5829
  var REFACTOR_YML_PATH2 = "refactor.yml";
5699
5830
  function ignore(file) {
5700
- if (!fs16.existsSync(file)) {
5701
- console.error(chalk55.red(`Error: File does not exist: ${file}`));
5831
+ if (!fs18.existsSync(file)) {
5832
+ console.error(chalk56.red(`Error: File does not exist: ${file}`));
5702
5833
  process.exit(1);
5703
5834
  }
5704
- const content = fs16.readFileSync(file, "utf-8");
5835
+ const content = fs18.readFileSync(file, "utf-8");
5705
5836
  const lineCount = content.split("\n").length;
5706
5837
  const maxLines = lineCount + 10;
5707
5838
  const entry = `- file: ${file}
5708
5839
  maxLines: ${maxLines}
5709
5840
  `;
5710
- if (fs16.existsSync(REFACTOR_YML_PATH2)) {
5711
- const existing = fs16.readFileSync(REFACTOR_YML_PATH2, "utf-8");
5712
- fs16.writeFileSync(REFACTOR_YML_PATH2, existing + entry);
5841
+ if (fs18.existsSync(REFACTOR_YML_PATH2)) {
5842
+ const existing = fs18.readFileSync(REFACTOR_YML_PATH2, "utf-8");
5843
+ fs18.writeFileSync(REFACTOR_YML_PATH2, existing + entry);
5713
5844
  } else {
5714
- fs16.writeFileSync(REFACTOR_YML_PATH2, entry);
5845
+ fs18.writeFileSync(REFACTOR_YML_PATH2, entry);
5715
5846
  }
5716
5847
  console.log(
5717
- chalk55.green(
5848
+ chalk56.green(
5718
5849
  `Added ${file} to refactor ignore list (max ${maxLines} lines)`
5719
5850
  )
5720
5851
  );
5721
5852
  }
5722
5853
 
5723
- // src/commands/refactor/restructure/index.ts
5724
- import path31 from "path";
5854
+ // src/commands/refactor/rename/index.ts
5855
+ import path27 from "path";
5856
+ import chalk57 from "chalk";
5857
+ import { Project as Project2 } from "ts-morph";
5858
+ async function rename(source, destination, options2 = {}) {
5859
+ const sourcePath = path27.resolve(source);
5860
+ const destPath = path27.resolve(destination);
5861
+ const cwd = process.cwd();
5862
+ const relSource = path27.relative(cwd, sourcePath);
5863
+ const relDest = path27.relative(cwd, destPath);
5864
+ const project = new Project2({
5865
+ tsConfigFilePath: path27.resolve("tsconfig.json")
5866
+ });
5867
+ const sourceFile = project.getSourceFile(sourcePath);
5868
+ if (!sourceFile) {
5869
+ console.log(chalk57.red(`File not found in project: ${source}`));
5870
+ process.exit(1);
5871
+ }
5872
+ console.log(chalk57.bold(`Rename: ${relSource} \u2192 ${relDest}`));
5873
+ if (options2.apply) {
5874
+ sourceFile.move(destPath);
5875
+ await project.save();
5876
+ console.log(chalk57.green("Done"));
5877
+ } else {
5878
+ console.log(chalk57.dim("Dry run. Use --apply to execute."));
5879
+ }
5880
+ }
5881
+
5882
+ // src/commands/refactor/renameSymbol/index.ts
5883
+ import path29 from "path";
5725
5884
  import chalk58 from "chalk";
5885
+ import { Project as Project3 } from "ts-morph";
5886
+
5887
+ // src/commands/refactor/renameSymbol/findSymbol.ts
5888
+ import { SyntaxKind as SyntaxKind2 } from "ts-morph";
5889
+ var declarationKinds = [
5890
+ SyntaxKind2.VariableDeclaration,
5891
+ SyntaxKind2.FunctionDeclaration,
5892
+ SyntaxKind2.ClassDeclaration,
5893
+ SyntaxKind2.InterfaceDeclaration,
5894
+ SyntaxKind2.TypeAliasDeclaration,
5895
+ SyntaxKind2.EnumDeclaration,
5896
+ SyntaxKind2.PropertyDeclaration,
5897
+ SyntaxKind2.MethodDeclaration,
5898
+ SyntaxKind2.Parameter
5899
+ ];
5900
+ function isDeclaration(identifier) {
5901
+ const parent = identifier.getParent();
5902
+ return parent !== void 0 && declarationKinds.includes(parent.getKind());
5903
+ }
5904
+ function findSymbol(sourceFile, symbolName) {
5905
+ for (const id of sourceFile.getDescendantsOfKind(SyntaxKind2.Identifier)) {
5906
+ if (id.getText() === symbolName && isDeclaration(id)) return id;
5907
+ }
5908
+ return void 0;
5909
+ }
5910
+
5911
+ // src/commands/refactor/renameSymbol/groupReferences.ts
5912
+ import path28 from "path";
5913
+ function groupReferences(symbol, cwd) {
5914
+ const refs = symbol.findReferencesAsNodes();
5915
+ const grouped = /* @__PURE__ */ new Map();
5916
+ for (const ref of refs) {
5917
+ const refFile = path28.relative(cwd, ref.getSourceFile().getFilePath());
5918
+ const lines = grouped.get(refFile) ?? [];
5919
+ if (!grouped.has(refFile)) grouped.set(refFile, lines);
5920
+ lines.push(ref.getStartLineNumber());
5921
+ }
5922
+ return grouped;
5923
+ }
5924
+
5925
+ // src/commands/refactor/renameSymbol/index.ts
5926
+ async function renameSymbol(file, oldName, newName, options2 = {}) {
5927
+ const filePath = path29.resolve(file);
5928
+ const tsConfigPath = path29.resolve("tsconfig.json");
5929
+ const cwd = process.cwd();
5930
+ const project = new Project3({ tsConfigFilePath: tsConfigPath });
5931
+ const sourceFile = project.getSourceFile(filePath);
5932
+ if (!sourceFile) {
5933
+ console.log(chalk58.red(`File not found in project: ${file}`));
5934
+ process.exit(1);
5935
+ }
5936
+ const symbol = findSymbol(sourceFile, oldName);
5937
+ if (!symbol) {
5938
+ console.log(chalk58.red(`Symbol "${oldName}" not found in ${file}`));
5939
+ process.exit(1);
5940
+ }
5941
+ const grouped = groupReferences(symbol, cwd);
5942
+ const totalRefs = [...grouped.values()].reduce((s, l) => s + l.length, 0);
5943
+ console.log(
5944
+ chalk58.bold(`Rename: ${oldName} \u2192 ${newName} (${totalRefs} references)
5945
+ `)
5946
+ );
5947
+ for (const [refFile, lines] of grouped) {
5948
+ console.log(
5949
+ ` ${chalk58.dim(refFile)}: lines ${chalk58.cyan(lines.join(", "))}`
5950
+ );
5951
+ }
5952
+ if (options2.apply) {
5953
+ symbol.rename(newName);
5954
+ await project.save();
5955
+ console.log(chalk58.green(`
5956
+ Renamed ${oldName} \u2192 ${newName}`));
5957
+ } else {
5958
+ console.log(chalk58.dim("\nDry run. Use --apply to execute."));
5959
+ }
5960
+ }
5961
+
5962
+ // src/commands/refactor/restructure/index.ts
5963
+ import path38 from "path";
5964
+ import chalk61 from "chalk";
5726
5965
 
5727
5966
  // src/commands/refactor/restructure/buildImportGraph/index.ts
5728
- import path23 from "path";
5967
+ import path30 from "path";
5729
5968
  import ts7 from "typescript";
5730
5969
 
5731
5970
  // src/commands/refactor/restructure/buildImportGraph/getImportSpecifiers.ts
@@ -5752,7 +5991,7 @@ function loadParsedConfig(tsConfigPath) {
5752
5991
  return ts7.parseJsonConfigFileContent(
5753
5992
  configFile.config,
5754
5993
  ts7.sys,
5755
- path23.dirname(tsConfigPath)
5994
+ path30.dirname(tsConfigPath)
5756
5995
  );
5757
5996
  }
5758
5997
  function addToSetMap(map, key, value) {
@@ -5768,7 +6007,7 @@ function resolveImport(specifier, filePath, options2) {
5768
6007
  const resolved = ts7.resolveModuleName(specifier, filePath, options2, ts7.sys);
5769
6008
  const resolvedPath = resolved.resolvedModule?.resolvedFileName;
5770
6009
  if (!resolvedPath || resolvedPath.includes("node_modules")) return null;
5771
- return path23.resolve(resolvedPath);
6010
+ return path30.resolve(resolvedPath);
5772
6011
  }
5773
6012
  function buildImportGraph(candidateFiles, tsConfigPath) {
5774
6013
  const parsed = loadParsedConfig(tsConfigPath);
@@ -5777,7 +6016,7 @@ function buildImportGraph(candidateFiles, tsConfigPath) {
5777
6016
  const importedBy = /* @__PURE__ */ new Map();
5778
6017
  const imports = /* @__PURE__ */ new Map();
5779
6018
  for (const sourceFile of program2.getSourceFiles()) {
5780
- const filePath = path23.resolve(sourceFile.fileName);
6019
+ const filePath = path30.resolve(sourceFile.fileName);
5781
6020
  if (filePath.includes("node_modules")) continue;
5782
6021
  for (const specifier of getImportSpecifiers(sourceFile)) {
5783
6022
  const absTarget = resolveImport(specifier, filePath, parsed.options);
@@ -5791,12 +6030,12 @@ function buildImportGraph(candidateFiles, tsConfigPath) {
5791
6030
  }
5792
6031
 
5793
6032
  // src/commands/refactor/restructure/clusterDirectories.ts
5794
- import path24 from "path";
6033
+ import path31 from "path";
5795
6034
  function clusterDirectories(graph) {
5796
6035
  const dirImportedBy = /* @__PURE__ */ new Map();
5797
6036
  for (const edge of graph.edges) {
5798
- const sourceDir = path24.dirname(edge.source);
5799
- const targetDir = path24.dirname(edge.target);
6037
+ const sourceDir = path31.dirname(edge.source);
6038
+ const targetDir = path31.dirname(edge.target);
5800
6039
  if (sourceDir === targetDir) continue;
5801
6040
  if (!graph.files.has(edge.target)) continue;
5802
6041
  const existing = dirImportedBy.get(targetDir) ?? /* @__PURE__ */ new Set();
@@ -5824,20 +6063,20 @@ function clusterDirectories(graph) {
5824
6063
  return clusters;
5825
6064
  }
5826
6065
  function isAncestor(ancestor, descendant) {
5827
- const rel = path24.relative(ancestor, descendant);
6066
+ const rel = path31.relative(ancestor, descendant);
5828
6067
  return !rel.startsWith("..") && rel !== "";
5829
6068
  }
5830
6069
 
5831
6070
  // src/commands/refactor/restructure/clusterFiles.ts
5832
- import path25 from "path";
6071
+ import path32 from "path";
5833
6072
  function findRootParent(file, importedBy, visited) {
5834
6073
  const importers = importedBy.get(file);
5835
6074
  if (!importers || importers.size !== 1) return file;
5836
6075
  const parent = [...importers][0];
5837
- const parentDir = path25.dirname(parent);
5838
- const fileDir = path25.dirname(file);
6076
+ const parentDir = path32.dirname(parent);
6077
+ const fileDir = path32.dirname(file);
5839
6078
  if (parentDir !== fileDir) return file;
5840
- if (path25.basename(parent, path25.extname(parent)) === "index") return file;
6079
+ if (path32.basename(parent, path32.extname(parent)) === "index") return file;
5841
6080
  if (visited.has(parent)) return file;
5842
6081
  visited.add(parent);
5843
6082
  return findRootParent(parent, importedBy, visited);
@@ -5845,16 +6084,16 @@ function findRootParent(file, importedBy, visited) {
5845
6084
  function clusterFiles(graph) {
5846
6085
  const clusters = /* @__PURE__ */ new Map();
5847
6086
  for (const file of graph.files) {
5848
- const basename7 = path25.basename(file, path25.extname(file));
6087
+ const basename7 = path32.basename(file, path32.extname(file));
5849
6088
  if (basename7 === "index") continue;
5850
6089
  const importers = graph.importedBy.get(file);
5851
6090
  if (!importers || importers.size !== 1) continue;
5852
6091
  const parent = [...importers][0];
5853
6092
  if (!graph.files.has(parent)) continue;
5854
- const parentDir = path25.dirname(parent);
5855
- const fileDir = path25.dirname(file);
6093
+ const parentDir = path32.dirname(parent);
6094
+ const fileDir = path32.dirname(file);
5856
6095
  if (parentDir !== fileDir) continue;
5857
- const parentBasename = path25.basename(parent, path25.extname(parent));
6096
+ const parentBasename = path32.basename(parent, path32.extname(parent));
5858
6097
  if (parentBasename === "index") continue;
5859
6098
  const root = findRootParent(parent, graph.importedBy, /* @__PURE__ */ new Set([file]));
5860
6099
  if (!root || root === file) continue;
@@ -5866,10 +6105,10 @@ function clusterFiles(graph) {
5866
6105
  }
5867
6106
 
5868
6107
  // src/commands/refactor/restructure/computeRewrites/index.ts
5869
- import path26 from "path";
6108
+ import path33 from "path";
5870
6109
 
5871
6110
  // src/commands/refactor/restructure/computeRewrites/applyRewrites.ts
5872
- import fs17 from "fs";
6111
+ import fs19 from "fs";
5873
6112
  function getOrCreateList(map, key) {
5874
6113
  const list4 = map.get(key) ?? [];
5875
6114
  if (!map.has(key)) map.set(key, list4);
@@ -5888,7 +6127,7 @@ function rewriteSpecifier(content, oldSpecifier, newSpecifier) {
5888
6127
  return content.replace(pattern2, `$1${newSpecifier}$2`);
5889
6128
  }
5890
6129
  function applyFileRewrites(file, fileRewrites) {
5891
- let content = fs17.readFileSync(file, "utf-8");
6130
+ let content = fs19.readFileSync(file, "utf-8");
5892
6131
  for (const { oldSpecifier, newSpecifier } of fileRewrites) {
5893
6132
  content = rewriteSpecifier(content, oldSpecifier, newSpecifier);
5894
6133
  }
@@ -5920,7 +6159,7 @@ function normalizeSpecifier(rel) {
5920
6159
  );
5921
6160
  }
5922
6161
  function computeSpecifier(fromFile, toFile) {
5923
- return normalizeSpecifier(path26.relative(path26.dirname(fromFile), toFile));
6162
+ return normalizeSpecifier(path33.relative(path33.dirname(fromFile), toFile));
5924
6163
  }
5925
6164
  function isAffected(edge, moveMap) {
5926
6165
  return moveMap.has(edge.target) || moveMap.has(edge.source);
@@ -5964,51 +6203,51 @@ function computeRewrites(moves, edges, allProjectFiles) {
5964
6203
  }
5965
6204
 
5966
6205
  // src/commands/refactor/restructure/displayPlan.ts
5967
- import path27 from "path";
5968
- import chalk56 from "chalk";
6206
+ import path34 from "path";
6207
+ import chalk59 from "chalk";
5969
6208
  function relPath(filePath) {
5970
- return path27.relative(process.cwd(), filePath);
6209
+ return path34.relative(process.cwd(), filePath);
5971
6210
  }
5972
6211
  function displayMoves(plan) {
5973
6212
  if (plan.moves.length === 0) return;
5974
- console.log(chalk56.bold("\nFile moves:"));
6213
+ console.log(chalk59.bold("\nFile moves:"));
5975
6214
  for (const move of plan.moves) {
5976
6215
  console.log(
5977
- ` ${chalk56.red(relPath(move.from))} \u2192 ${chalk56.green(relPath(move.to))}`
6216
+ ` ${chalk59.red(relPath(move.from))} \u2192 ${chalk59.green(relPath(move.to))}`
5978
6217
  );
5979
- console.log(chalk56.dim(` ${move.reason}`));
6218
+ console.log(chalk59.dim(` ${move.reason}`));
5980
6219
  }
5981
6220
  }
5982
6221
  function displayRewrites(rewrites) {
5983
6222
  if (rewrites.length === 0) return;
5984
6223
  const affectedFiles = new Set(rewrites.map((r) => r.file));
5985
- console.log(chalk56.bold(`
6224
+ console.log(chalk59.bold(`
5986
6225
  Import rewrites (${affectedFiles.size} files):`));
5987
6226
  for (const file of affectedFiles) {
5988
- console.log(` ${chalk56.cyan(relPath(file))}:`);
6227
+ console.log(` ${chalk59.cyan(relPath(file))}:`);
5989
6228
  for (const { oldSpecifier, newSpecifier } of rewrites.filter(
5990
6229
  (r) => r.file === file
5991
6230
  )) {
5992
6231
  console.log(
5993
- ` ${chalk56.red(`"${oldSpecifier}"`)} \u2192 ${chalk56.green(`"${newSpecifier}"`)}`
6232
+ ` ${chalk59.red(`"${oldSpecifier}"`)} \u2192 ${chalk59.green(`"${newSpecifier}"`)}`
5994
6233
  );
5995
6234
  }
5996
6235
  }
5997
6236
  }
5998
6237
  function displayPlan(plan) {
5999
6238
  if (plan.warnings.length > 0) {
6000
- console.log(chalk56.yellow("\nWarnings:"));
6001
- for (const w of plan.warnings) console.log(chalk56.yellow(` ${w}`));
6239
+ console.log(chalk59.yellow("\nWarnings:"));
6240
+ for (const w of plan.warnings) console.log(chalk59.yellow(` ${w}`));
6002
6241
  }
6003
6242
  if (plan.newDirectories.length > 0) {
6004
- console.log(chalk56.bold("\nNew directories:"));
6243
+ console.log(chalk59.bold("\nNew directories:"));
6005
6244
  for (const dir of plan.newDirectories)
6006
- console.log(chalk56.green(` ${dir}/`));
6245
+ console.log(chalk59.green(` ${dir}/`));
6007
6246
  }
6008
6247
  displayMoves(plan);
6009
6248
  displayRewrites(plan.rewrites);
6010
6249
  console.log(
6011
- chalk56.dim(
6250
+ chalk59.dim(
6012
6251
  `
6013
6252
  Summary: ${plan.moves.length} file(s) moved, ${plan.rewrites.length} imports rewritten`
6014
6253
  )
@@ -6016,45 +6255,45 @@ Summary: ${plan.moves.length} file(s) moved, ${plan.rewrites.length} imports rew
6016
6255
  }
6017
6256
 
6018
6257
  // src/commands/refactor/restructure/executePlan.ts
6019
- import fs18 from "fs";
6020
- import path28 from "path";
6021
- import chalk57 from "chalk";
6258
+ import fs20 from "fs";
6259
+ import path35 from "path";
6260
+ import chalk60 from "chalk";
6022
6261
  function executePlan(plan) {
6023
6262
  const updatedContents = applyRewrites(plan.rewrites);
6024
6263
  for (const [file, content] of updatedContents) {
6025
- fs18.writeFileSync(file, content, "utf-8");
6264
+ fs20.writeFileSync(file, content, "utf-8");
6026
6265
  console.log(
6027
- chalk57.cyan(` Rewrote imports in ${path28.relative(process.cwd(), file)}`)
6266
+ chalk60.cyan(` Rewrote imports in ${path35.relative(process.cwd(), file)}`)
6028
6267
  );
6029
6268
  }
6030
6269
  for (const dir of plan.newDirectories) {
6031
- fs18.mkdirSync(dir, { recursive: true });
6032
- console.log(chalk57.green(` Created ${path28.relative(process.cwd(), dir)}/`));
6270
+ fs20.mkdirSync(dir, { recursive: true });
6271
+ console.log(chalk60.green(` Created ${path35.relative(process.cwd(), dir)}/`));
6033
6272
  }
6034
6273
  for (const move of plan.moves) {
6035
- const targetDir = path28.dirname(move.to);
6036
- if (!fs18.existsSync(targetDir)) {
6037
- fs18.mkdirSync(targetDir, { recursive: true });
6274
+ const targetDir = path35.dirname(move.to);
6275
+ if (!fs20.existsSync(targetDir)) {
6276
+ fs20.mkdirSync(targetDir, { recursive: true });
6038
6277
  }
6039
- fs18.renameSync(move.from, move.to);
6278
+ fs20.renameSync(move.from, move.to);
6040
6279
  console.log(
6041
- chalk57.white(
6042
- ` Moved ${path28.relative(process.cwd(), move.from)} \u2192 ${path28.relative(process.cwd(), move.to)}`
6280
+ chalk60.white(
6281
+ ` Moved ${path35.relative(process.cwd(), move.from)} \u2192 ${path35.relative(process.cwd(), move.to)}`
6043
6282
  )
6044
6283
  );
6045
6284
  }
6046
- removeEmptyDirectories(plan.moves.map((m) => path28.dirname(m.from)));
6285
+ removeEmptyDirectories(plan.moves.map((m) => path35.dirname(m.from)));
6047
6286
  }
6048
6287
  function removeEmptyDirectories(dirs) {
6049
6288
  const unique = [...new Set(dirs)];
6050
6289
  for (const dir of unique) {
6051
- if (!fs18.existsSync(dir)) continue;
6052
- const entries = fs18.readdirSync(dir);
6290
+ if (!fs20.existsSync(dir)) continue;
6291
+ const entries = fs20.readdirSync(dir);
6053
6292
  if (entries.length === 0) {
6054
- fs18.rmdirSync(dir);
6293
+ fs20.rmdirSync(dir);
6055
6294
  console.log(
6056
- chalk57.dim(
6057
- ` Removed empty directory ${path28.relative(process.cwd(), dir)}`
6295
+ chalk60.dim(
6296
+ ` Removed empty directory ${path35.relative(process.cwd(), dir)}`
6058
6297
  )
6059
6298
  );
6060
6299
  }
@@ -6062,36 +6301,36 @@ function removeEmptyDirectories(dirs) {
6062
6301
  }
6063
6302
 
6064
6303
  // src/commands/refactor/restructure/planFileMoves/index.ts
6065
- import fs20 from "fs";
6066
- import path30 from "path";
6304
+ import fs22 from "fs";
6305
+ import path37 from "path";
6067
6306
 
6068
6307
  // src/commands/refactor/restructure/planFileMoves/planDirectoryMoves.ts
6069
- import fs19 from "fs";
6070
- import path29 from "path";
6308
+ import fs21 from "fs";
6309
+ import path36 from "path";
6071
6310
  function collectEntry(results, dir, entry) {
6072
- const full = path29.join(dir, entry.name);
6311
+ const full = path36.join(dir, entry.name);
6073
6312
  const items = entry.isDirectory() ? listFilesRecursive(full) : [full];
6074
6313
  results.push(...items);
6075
6314
  }
6076
6315
  function listFilesRecursive(dir) {
6077
- if (!fs19.existsSync(dir)) return [];
6316
+ if (!fs21.existsSync(dir)) return [];
6078
6317
  const results = [];
6079
- for (const entry of fs19.readdirSync(dir, { withFileTypes: true })) {
6318
+ for (const entry of fs21.readdirSync(dir, { withFileTypes: true })) {
6080
6319
  collectEntry(results, dir, entry);
6081
6320
  }
6082
6321
  return results;
6083
6322
  }
6084
6323
  function addDirectoryFileMoves(moves, childDir, newLocation, reason) {
6085
6324
  for (const file of listFilesRecursive(childDir)) {
6086
- const rel = path29.relative(childDir, file);
6087
- moves.push({ from: file, to: path29.join(newLocation, rel), reason });
6325
+ const rel = path36.relative(childDir, file);
6326
+ moves.push({ from: file, to: path36.join(newLocation, rel), reason });
6088
6327
  }
6089
6328
  }
6090
6329
  function resolveChildDest(parentDir, childDir) {
6091
- return path29.join(parentDir, path29.basename(childDir));
6330
+ return path36.join(parentDir, path36.basename(childDir));
6092
6331
  }
6093
6332
  function childMoveReason(parentDir) {
6094
- return `Directory only imported from ${path29.basename(parentDir)}/`;
6333
+ return `Directory only imported from ${path36.basename(parentDir)}/`;
6095
6334
  }
6096
6335
  function registerDirectoryMove(result, childDir, dest, parentDir) {
6097
6336
  result.directories.push(dest);
@@ -6119,7 +6358,7 @@ function emptyResult() {
6119
6358
  return { moves: [], directories: [], warnings: [] };
6120
6359
  }
6121
6360
  function childMoveData(child, newDir, parentBase) {
6122
- const to = path30.join(newDir, path30.basename(child));
6361
+ const to = path37.join(newDir, path37.basename(child));
6123
6362
  return { from: child, to, reason: `Only imported by ${parentBase}` };
6124
6363
  }
6125
6364
  function addChildMoves(moves, children, newDir, parentBase) {
@@ -6127,20 +6366,20 @@ function addChildMoves(moves, children, newDir, parentBase) {
6127
6366
  moves.push(childMoveData(child, newDir, parentBase));
6128
6367
  }
6129
6368
  function checkDirConflict(result, label2, dir) {
6130
- if (!fs20.existsSync(dir)) return false;
6369
+ if (!fs22.existsSync(dir)) return false;
6131
6370
  result.warnings.push(`Skipping ${label2}: directory ${dir} already exists`);
6132
6371
  return true;
6133
6372
  }
6134
6373
  function getBaseName(filePath) {
6135
- return path30.basename(filePath, path30.extname(filePath));
6374
+ return path37.basename(filePath, path37.extname(filePath));
6136
6375
  }
6137
6376
  function resolveClusterDir(parent) {
6138
- return path30.join(path30.dirname(parent), getBaseName(parent));
6377
+ return path37.join(path37.dirname(parent), getBaseName(parent));
6139
6378
  }
6140
6379
  function createParentMove(parent, newDir) {
6141
6380
  return {
6142
6381
  from: parent,
6143
- to: path30.join(newDir, `index${path30.extname(parent)}`),
6382
+ to: path37.join(newDir, `index${path37.extname(parent)}`),
6144
6383
  reason: `Main module of new ${getBaseName(parent)}/ directory`
6145
6384
  };
6146
6385
  }
@@ -6164,7 +6403,7 @@ function planFileMoves(clusters) {
6164
6403
 
6165
6404
  // src/commands/refactor/restructure/index.ts
6166
6405
  function buildPlan(candidateFiles, tsConfigPath) {
6167
- const candidates = new Set(candidateFiles.map((f) => path31.resolve(f)));
6406
+ const candidates = new Set(candidateFiles.map((f) => path38.resolve(f)));
6168
6407
  const graph = buildImportGraph(candidates, tsConfigPath);
6169
6408
  const allProjectFiles = /* @__PURE__ */ new Set([
6170
6409
  ...graph.importedBy.keys(),
@@ -6184,22 +6423,22 @@ async function restructure(pattern2, options2 = {}) {
6184
6423
  const targetPattern = pattern2 ?? "src";
6185
6424
  const files = findSourceFiles2(targetPattern);
6186
6425
  if (files.length === 0) {
6187
- console.log(chalk58.yellow("No files found matching pattern"));
6426
+ console.log(chalk61.yellow("No files found matching pattern"));
6188
6427
  return;
6189
6428
  }
6190
- const tsConfigPath = path31.resolve("tsconfig.json");
6429
+ const tsConfigPath = path38.resolve("tsconfig.json");
6191
6430
  const plan = buildPlan(files, tsConfigPath);
6192
6431
  if (plan.moves.length === 0) {
6193
- console.log(chalk58.green("No restructuring needed"));
6432
+ console.log(chalk61.green("No restructuring needed"));
6194
6433
  return;
6195
6434
  }
6196
6435
  displayPlan(plan);
6197
6436
  if (options2.apply) {
6198
- console.log(chalk58.bold("\nApplying changes..."));
6437
+ console.log(chalk61.bold("\nApplying changes..."));
6199
6438
  executePlan(plan);
6200
- console.log(chalk58.green("\nRestructuring complete"));
6439
+ console.log(chalk61.green("\nRestructuring complete"));
6201
6440
  } else {
6202
- console.log(chalk58.dim("\nDry run. Use --apply to execute."));
6441
+ console.log(chalk61.dim("\nDry run. Use --apply to execute."));
6203
6442
  }
6204
6443
  }
6205
6444
 
@@ -6212,6 +6451,11 @@ function registerRefactor(program2) {
6212
6451
  Number.parseInt
6213
6452
  ).action(check);
6214
6453
  refactorCommand.command("ignore <file>").description("Add a file to the refactor ignore list").action(ignore);
6454
+ const renameCommand = refactorCommand.command("rename").description("Rename files or symbols with automatic import updates");
6455
+ renameCommand.command("file <source> <destination>").description("Rename/move a TypeScript file and update all imports").option("--apply", "Execute the rename (default: dry-run)").action(rename);
6456
+ renameCommand.command("symbol <file> <oldName> <newName>").description(
6457
+ "Rename a variable, function, class, or type across the project"
6458
+ ).option("--apply", "Execute the rename (default: dry-run)").action(renameSymbol);
6215
6459
  refactorCommand.command("restructure [pattern]").description(
6216
6460
  "Analyze import graph and restructure tightly-coupled files into nested directories"
6217
6461
  ).option("--apply", "Execute the restructuring (default: dry-run)").option(
@@ -6742,14 +6986,14 @@ import {
6742
6986
  import { dirname as dirname18, join as join26 } from "path";
6743
6987
 
6744
6988
  // src/commands/transcript/summarise/processStagedFile/validateStagedContent.ts
6745
- import chalk59 from "chalk";
6989
+ import chalk62 from "chalk";
6746
6990
  var FULL_TRANSCRIPT_REGEX = /^\[Full Transcript\]\(([^)]+)\)/;
6747
6991
  function validateStagedContent(filename, content) {
6748
6992
  const firstLine = content.split("\n")[0];
6749
6993
  const match = firstLine.match(FULL_TRANSCRIPT_REGEX);
6750
6994
  if (!match) {
6751
6995
  console.error(
6752
- chalk59.red(
6996
+ chalk62.red(
6753
6997
  `Staged file ${filename} missing [Full Transcript](<path>) link on first line.`
6754
6998
  )
6755
6999
  );
@@ -6758,7 +7002,7 @@ function validateStagedContent(filename, content) {
6758
7002
  const contentAfterLink = content.slice(firstLine.length).trim();
6759
7003
  if (!contentAfterLink) {
6760
7004
  console.error(
6761
- chalk59.red(
7005
+ chalk62.red(
6762
7006
  `Staged file ${filename} has no summary content after the transcript link.`
6763
7007
  )
6764
7008
  );
@@ -7151,7 +7395,7 @@ function registerVoice(program2) {
7151
7395
 
7152
7396
  // src/commands/roam/auth.ts
7153
7397
  import { randomBytes } from "crypto";
7154
- import chalk60 from "chalk";
7398
+ import chalk63 from "chalk";
7155
7399
 
7156
7400
  // src/lib/openBrowser.ts
7157
7401
  import { execSync as execSync31 } from "child_process";
@@ -7326,13 +7570,13 @@ async function auth() {
7326
7570
  saveGlobalConfig(config);
7327
7571
  const state = randomBytes(16).toString("hex");
7328
7572
  console.log(
7329
- chalk60.yellow("\nEnsure this Redirect URI is set in your Roam OAuth app:")
7573
+ chalk63.yellow("\nEnsure this Redirect URI is set in your Roam OAuth app:")
7330
7574
  );
7331
- console.log(chalk60.white("http://localhost:14523/callback\n"));
7332
- console.log(chalk60.blue("Opening browser for authorization..."));
7333
- console.log(chalk60.dim("Waiting for authorization callback..."));
7575
+ console.log(chalk63.white("http://localhost:14523/callback\n"));
7576
+ console.log(chalk63.blue("Opening browser for authorization..."));
7577
+ console.log(chalk63.dim("Waiting for authorization callback..."));
7334
7578
  const { code, redirectUri } = await authorizeInBrowser(clientId, state);
7335
- console.log(chalk60.dim("Exchanging code for tokens..."));
7579
+ console.log(chalk63.dim("Exchanging code for tokens..."));
7336
7580
  const tokens = await exchangeToken({
7337
7581
  code,
7338
7582
  clientId,
@@ -7348,7 +7592,7 @@ async function auth() {
7348
7592
  };
7349
7593
  saveGlobalConfig(config);
7350
7594
  console.log(
7351
- chalk60.green("Roam credentials and tokens saved to ~/.assist.yml")
7595
+ chalk63.green("Roam credentials and tokens saved to ~/.assist.yml")
7352
7596
  );
7353
7597
  }
7354
7598
 
@@ -7536,14 +7780,14 @@ function run2(name, args) {
7536
7780
  }
7537
7781
 
7538
7782
  // src/commands/statusLine.ts
7539
- import chalk61 from "chalk";
7783
+ import chalk64 from "chalk";
7540
7784
  function formatNumber(num) {
7541
7785
  return num.toLocaleString("en-US");
7542
7786
  }
7543
7787
  function colorizePercent(pct) {
7544
7788
  const label2 = `${pct}%`;
7545
- if (pct > 80) return chalk61.red(label2);
7546
- if (pct > 40) return chalk61.yellow(label2);
7789
+ if (pct > 80) return chalk64.red(label2);
7790
+ if (pct > 40) return chalk64.yellow(label2);
7547
7791
  return label2;
7548
7792
  }
7549
7793
  async function statusLine() {
@@ -7561,29 +7805,29 @@ async function statusLine() {
7561
7805
  }
7562
7806
 
7563
7807
  // src/commands/sync.ts
7564
- import * as fs23 from "fs";
7808
+ import * as fs25 from "fs";
7565
7809
  import * as os from "os";
7566
- import * as path34 from "path";
7810
+ import * as path41 from "path";
7567
7811
  import { fileURLToPath as fileURLToPath7 } from "url";
7568
7812
 
7569
7813
  // src/commands/sync/syncClaudeMd.ts
7570
- import * as fs21 from "fs";
7571
- import * as path32 from "path";
7572
- import chalk62 from "chalk";
7814
+ import * as fs23 from "fs";
7815
+ import * as path39 from "path";
7816
+ import chalk65 from "chalk";
7573
7817
  async function syncClaudeMd(claudeDir, targetBase) {
7574
- const source = path32.join(claudeDir, "CLAUDE.md");
7575
- const target = path32.join(targetBase, "CLAUDE.md");
7576
- const sourceContent = fs21.readFileSync(source, "utf-8");
7577
- if (fs21.existsSync(target)) {
7578
- const targetContent = fs21.readFileSync(target, "utf-8");
7818
+ const source = path39.join(claudeDir, "CLAUDE.md");
7819
+ const target = path39.join(targetBase, "CLAUDE.md");
7820
+ const sourceContent = fs23.readFileSync(source, "utf-8");
7821
+ if (fs23.existsSync(target)) {
7822
+ const targetContent = fs23.readFileSync(target, "utf-8");
7579
7823
  if (sourceContent !== targetContent) {
7580
7824
  console.log(
7581
- chalk62.yellow("\n\u26A0\uFE0F Warning: CLAUDE.md differs from existing file")
7825
+ chalk65.yellow("\n\u26A0\uFE0F Warning: CLAUDE.md differs from existing file")
7582
7826
  );
7583
7827
  console.log();
7584
7828
  printDiff(targetContent, sourceContent);
7585
7829
  const confirm = await promptConfirm(
7586
- chalk62.red("Overwrite existing CLAUDE.md?"),
7830
+ chalk65.red("Overwrite existing CLAUDE.md?"),
7587
7831
  false
7588
7832
  );
7589
7833
  if (!confirm) {
@@ -7592,21 +7836,21 @@ async function syncClaudeMd(claudeDir, targetBase) {
7592
7836
  }
7593
7837
  }
7594
7838
  }
7595
- fs21.copyFileSync(source, target);
7839
+ fs23.copyFileSync(source, target);
7596
7840
  console.log("Copied CLAUDE.md to ~/.claude/CLAUDE.md");
7597
7841
  }
7598
7842
 
7599
7843
  // src/commands/sync/syncSettings.ts
7600
- import * as fs22 from "fs";
7601
- import * as path33 from "path";
7602
- import chalk63 from "chalk";
7844
+ import * as fs24 from "fs";
7845
+ import * as path40 from "path";
7846
+ import chalk66 from "chalk";
7603
7847
  async function syncSettings(claudeDir, targetBase, options2) {
7604
- const source = path33.join(claudeDir, "settings.json");
7605
- const target = path33.join(targetBase, "settings.json");
7606
- const sourceContent = fs22.readFileSync(source, "utf-8");
7848
+ const source = path40.join(claudeDir, "settings.json");
7849
+ const target = path40.join(targetBase, "settings.json");
7850
+ const sourceContent = fs24.readFileSync(source, "utf-8");
7607
7851
  const mergedContent = JSON.stringify(JSON.parse(sourceContent), null, " ");
7608
- if (fs22.existsSync(target)) {
7609
- const targetContent = fs22.readFileSync(target, "utf-8");
7852
+ if (fs24.existsSync(target)) {
7853
+ const targetContent = fs24.readFileSync(target, "utf-8");
7610
7854
  const normalizedTarget = JSON.stringify(
7611
7855
  JSON.parse(targetContent),
7612
7856
  null,
@@ -7615,14 +7859,14 @@ async function syncSettings(claudeDir, targetBase, options2) {
7615
7859
  if (mergedContent !== normalizedTarget) {
7616
7860
  if (!options2?.yes) {
7617
7861
  console.log(
7618
- chalk63.yellow(
7862
+ chalk66.yellow(
7619
7863
  "\n\u26A0\uFE0F Warning: settings.json differs from existing file"
7620
7864
  )
7621
7865
  );
7622
7866
  console.log();
7623
7867
  printDiff(targetContent, mergedContent);
7624
7868
  const confirm = await promptConfirm(
7625
- chalk63.red("Overwrite existing settings.json?"),
7869
+ chalk66.red("Overwrite existing settings.json?"),
7626
7870
  false
7627
7871
  );
7628
7872
  if (!confirm) {
@@ -7632,27 +7876,27 @@ async function syncSettings(claudeDir, targetBase, options2) {
7632
7876
  }
7633
7877
  }
7634
7878
  }
7635
- fs22.writeFileSync(target, mergedContent);
7879
+ fs24.writeFileSync(target, mergedContent);
7636
7880
  console.log("Copied settings.json to ~/.claude/settings.json");
7637
7881
  }
7638
7882
 
7639
7883
  // src/commands/sync.ts
7640
7884
  var __filename4 = fileURLToPath7(import.meta.url);
7641
- var __dirname7 = path34.dirname(__filename4);
7885
+ var __dirname7 = path41.dirname(__filename4);
7642
7886
  async function sync(options2) {
7643
- const claudeDir = path34.join(__dirname7, "..", "claude");
7644
- const targetBase = path34.join(os.homedir(), ".claude");
7887
+ const claudeDir = path41.join(__dirname7, "..", "claude");
7888
+ const targetBase = path41.join(os.homedir(), ".claude");
7645
7889
  syncCommands(claudeDir, targetBase);
7646
7890
  await syncSettings(claudeDir, targetBase, { yes: options2?.yes });
7647
7891
  await syncClaudeMd(claudeDir, targetBase);
7648
7892
  }
7649
7893
  function syncCommands(claudeDir, targetBase) {
7650
- const sourceDir = path34.join(claudeDir, "commands");
7651
- const targetDir = path34.join(targetBase, "commands");
7652
- fs23.mkdirSync(targetDir, { recursive: true });
7653
- const files = fs23.readdirSync(sourceDir);
7894
+ const sourceDir = path41.join(claudeDir, "commands");
7895
+ const targetDir = path41.join(targetBase, "commands");
7896
+ fs25.mkdirSync(targetDir, { recursive: true });
7897
+ const files = fs25.readdirSync(sourceDir);
7654
7898
  for (const file of files) {
7655
- fs23.copyFileSync(path34.join(sourceDir, file), path34.join(targetDir, file));
7899
+ fs25.copyFileSync(path41.join(sourceDir, file), path41.join(targetDir, file));
7656
7900
  console.log(`Copied ${file} to ${targetDir}`);
7657
7901
  }
7658
7902
  console.log(`Synced ${files.length} command(s) to ~/.claude/commands`);
@@ -7660,15 +7904,15 @@ function syncCommands(claudeDir, targetBase) {
7660
7904
 
7661
7905
  // src/commands/update.ts
7662
7906
  import { execSync as execSync32 } from "child_process";
7663
- import * as path35 from "path";
7907
+ import * as path42 from "path";
7664
7908
  function isGlobalNpmInstall(dir) {
7665
7909
  try {
7666
- const resolved = path35.resolve(dir);
7667
- if (resolved.split(path35.sep).includes("node_modules")) {
7910
+ const resolved = path42.resolve(dir);
7911
+ if (resolved.split(path42.sep).includes("node_modules")) {
7668
7912
  return true;
7669
7913
  }
7670
7914
  const globalPrefix = execSync32("npm prefix -g", { stdio: "pipe" }).toString().trim();
7671
- return resolved.toLowerCase().startsWith(path35.resolve(globalPrefix).toLowerCase());
7915
+ return resolved.toLowerCase().startsWith(path42.resolve(globalPrefix).toLowerCase());
7672
7916
  } catch {
7673
7917
  return false;
7674
7918
  }
@@ -7717,7 +7961,7 @@ runCommand.command("add").description("Add a new run configuration to assist.yml
7717
7961
  '\nPositional params can be added to the config manually:\n params:\n - name: env # assist run deploy prod \u2192 appends "prod"\n required: true\n - name: tag\n default: latest'
7718
7962
  ).allowUnknownOption().allowExcessArguments().action(() => add3());
7719
7963
  registerNew(program);
7720
- var lintCommand = program.command("lint").description("Run lint checks for conventions not enforced by biomejs").action(lint);
7964
+ var lintCommand = program.command("lint").description("Run lint checks for conventions not enforced by biomejs").option("-f, --fix", "Auto-fix violations where possible").action(lint);
7721
7965
  lintCommand.command("init").description("Initialize Biome with standard linter config").action(init);
7722
7966
  var vscodeCommand = program.command("vscode").description("VS Code configuration utilities");
7723
7967
  vscodeCommand.command("init").description("Add VS Code configuration files").action(init3);