@staff0rd/assist 0.108.2 → 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.108.2",
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(path35) {
92
- if (!existsSync(path35)) return {};
92
+ function loadRawYaml(path43) {
93
+ if (!existsSync(path43)) return {};
93
94
  try {
94
- const content = readFileSync(path35, "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, path35) {
333
+ function getNestedValue(obj, path43) {
333
334
  let current = obj;
334
- for (const key of path35.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, path35, value) {
376
- const keys = path35.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++) {
@@ -442,7 +443,7 @@ function configList() {
442
443
  }
443
444
 
444
445
  // src/commands/verify/init/index.ts
445
- import chalk15 from "chalk";
446
+ import chalk16 from "chalk";
446
447
 
447
448
  // src/shared/promptMultiselect.ts
448
449
  import chalk3 from "chalk";
@@ -515,12 +516,13 @@ 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",
522
523
  "verify:no-venv": "assist verify no-venv",
523
- "verify:maintainability": "assist complexity maintainability ./src --threshold 60"
524
+ "verify:maintainability": "assist complexity maintainability ./src --threshold 60",
525
+ "verify:madge": "madge --circular --ts-config ./tsconfig.json --extensions ts,tsx src/"
524
526
  };
525
527
 
526
528
  // src/commands/verify/setup/setupBuild.ts
@@ -859,12 +861,30 @@ async function setupLint(packageJsonPath) {
859
861
  );
860
862
  }
861
863
 
862
- // src/commands/verify/setup/setupMaintainability.ts
864
+ // src/commands/verify/setup/setupMadge.ts
863
865
  import * as path7 from "path";
864
866
  import chalk13 from "chalk";
867
+ async function setupMadge(packageJsonPath) {
868
+ console.log(chalk13.blue("\nSetting up madge..."));
869
+ const cwd = path7.dirname(packageJsonPath);
870
+ const pkg = readPackageJson(packageJsonPath);
871
+ const hasMadge = !!pkg.dependencies?.madge || !!pkg.devDependencies?.madge;
872
+ if (!hasMadge && !installPackage("madge", cwd)) {
873
+ return;
874
+ }
875
+ setupVerifyScript(
876
+ packageJsonPath,
877
+ "verify:madge",
878
+ expectedScripts["verify:madge"]
879
+ );
880
+ }
881
+
882
+ // src/commands/verify/setup/setupMaintainability.ts
883
+ import * as path8 from "path";
884
+ import chalk14 from "chalk";
865
885
  async function setupMaintainability(packageJsonPath) {
866
- console.log(chalk13.blue("\nSetting up maintainability check..."));
867
- addToKnipIgnoreBinaries(path7.dirname(packageJsonPath), "assist");
886
+ console.log(chalk14.blue("\nSetting up maintainability check..."));
887
+ addToKnipIgnoreBinaries(path8.dirname(packageJsonPath), "assist");
868
888
  setupVerifyScript(
869
889
  packageJsonPath,
870
890
  "verify:maintainability",
@@ -873,11 +893,11 @@ async function setupMaintainability(packageJsonPath) {
873
893
  }
874
894
 
875
895
  // src/commands/verify/setup/setupTest.ts
876
- import * as path8 from "path";
877
- import chalk14 from "chalk";
896
+ import * as path9 from "path";
897
+ import chalk15 from "chalk";
878
898
  async function setupTest(packageJsonPath) {
879
- console.log(chalk14.blue("\nSetting up vitest..."));
880
- const cwd = path8.dirname(packageJsonPath);
899
+ console.log(chalk15.blue("\nSetting up vitest..."));
900
+ const cwd = path9.dirname(packageJsonPath);
881
901
  const pkg = readPackageJson(packageJsonPath);
882
902
  if (!pkg.devDependencies?.vitest && !installPackage("vitest", cwd)) {
883
903
  return;
@@ -901,6 +921,9 @@ function getStatusLabel(status2) {
901
921
  }
902
922
 
903
923
  // src/commands/verify/init/detectExistingSetup/index.ts
924
+ function hasDep(pkg, name) {
925
+ return !!pkg.dependencies?.[name] || !!pkg.devDependencies?.[name];
926
+ }
904
927
  function toolStatus(pkg, scriptName, hasPackage) {
905
928
  const currentScript = pkg.scripts?.[scriptName];
906
929
  const expectedCommand = expectedScripts[scriptName];
@@ -911,26 +934,20 @@ function toolStatus(pkg, scriptName, hasPackage) {
911
934
  };
912
935
  }
913
936
  function detectExistingSetup(pkg) {
937
+ const status2 = (script, has) => toolStatus(pkg, script, has);
914
938
  return {
915
- knip: toolStatus(pkg, "verify:knip", !!pkg.devDependencies?.knip),
916
- biome: toolStatus(
917
- pkg,
918
- "verify:lint",
919
- !!pkg.devDependencies?.["@biomejs/biome"]
920
- ),
921
- jscpd: toolStatus(
922
- pkg,
923
- "verify:duplicate-code",
924
- !!pkg.dependencies?.jscpd || !!pkg.devDependencies?.jscpd
925
- ),
926
- test: toolStatus(pkg, "verify:test", !!pkg.devDependencies?.vitest),
927
- hasVite: !!pkg.devDependencies?.vite || !!pkg.dependencies?.vite,
939
+ knip: status2("verify:knip", hasDep(pkg, "knip")),
940
+ biome: status2("verify:lint", hasDep(pkg, "@biomejs/biome")),
941
+ jscpd: status2("verify:duplicate-code", hasDep(pkg, "jscpd")),
942
+ test: status2("verify:test", hasDep(pkg, "vitest")),
943
+ hasVite: hasDep(pkg, "vite"),
928
944
  hasTypescript: !!pkg.devDependencies?.typescript,
929
- build: toolStatus(pkg, "verify:build", true),
930
- typecheck: toolStatus(pkg, "verify:typecheck", true),
931
- hardcodedColors: toolStatus(pkg, "verify:hardcoded-colors", true),
932
- maintainability: toolStatus(pkg, "verify:maintainability", true),
933
- hasOpenColor: !!pkg.dependencies?.["open-color"] || !!pkg.devDependencies?.["open-color"]
945
+ build: status2("verify:build", true),
946
+ typecheck: status2("verify:typecheck", true),
947
+ hardcodedColors: status2("verify:hardcoded-colors", true),
948
+ madge: status2("verify:madge", hasDep(pkg, "madge")),
949
+ maintainability: status2("verify:maintainability", true),
950
+ hasOpenColor: hasDep(pkg, "open-color")
934
951
  };
935
952
  }
936
953
 
@@ -987,6 +1004,12 @@ var options = [
987
1004
  description: "TypeScript type checking",
988
1005
  extraCondition: (s) => s.hasTypescript && !s.hasVite
989
1006
  },
1007
+ {
1008
+ toolKey: "madge",
1009
+ value: "madge",
1010
+ label: "madge",
1011
+ description: "Circular dependency detection with madge"
1012
+ },
990
1013
  {
991
1014
  toolKey: "maintainability",
992
1015
  value: "maintainability",
@@ -1022,6 +1045,7 @@ function getSetupHandlers(hasVite, hasTypescript, hasOpenColor) {
1022
1045
  build: (p) => setupBuild(p, hasVite, hasTypescript),
1023
1046
  typecheck: (p) => setupTypecheck(p),
1024
1047
  "hardcoded-colors": (p) => setupHardcodedColors(p, hasOpenColor),
1048
+ madge: (p) => setupMadge(p),
1025
1049
  maintainability: (p) => setupMaintainability(p)
1026
1050
  };
1027
1051
  }
@@ -1029,25 +1053,25 @@ async function runSelectedSetups(selected, packageJsonPath, handlers) {
1029
1053
  for (const choice of selected) {
1030
1054
  await handlers[choice]?.(packageJsonPath);
1031
1055
  }
1032
- console.log(chalk15.green(`
1056
+ console.log(chalk16.green(`
1033
1057
  Added ${selected.length} verify script(s):`));
1034
1058
  for (const choice of selected) {
1035
- console.log(chalk15.green(` - verify:${choice}`));
1059
+ console.log(chalk16.green(` - verify:${choice}`));
1036
1060
  }
1037
- console.log(chalk15.dim("\nRun 'assist verify' to run all verify scripts"));
1061
+ console.log(chalk16.dim("\nRun 'assist verify' to run all verify scripts"));
1038
1062
  }
1039
1063
  async function promptForScripts(availableOptions) {
1040
1064
  if (availableOptions.length === 0) {
1041
- console.log(chalk15.green("All verify scripts are already configured!"));
1065
+ console.log(chalk16.green("All verify scripts are already configured!"));
1042
1066
  return null;
1043
1067
  }
1044
- console.log(chalk15.bold("Available verify scripts to add:\n"));
1068
+ console.log(chalk16.bold("Available verify scripts to add:\n"));
1045
1069
  const selected = await promptMultiselect(
1046
1070
  "Select verify scripts to add:",
1047
1071
  availableOptions
1048
1072
  );
1049
1073
  if (selected.length === 0) {
1050
- console.log(chalk15.yellow("No scripts selected"));
1074
+ console.log(chalk16.yellow("No scripts selected"));
1051
1075
  return null;
1052
1076
  }
1053
1077
  return selected;
@@ -1066,21 +1090,21 @@ async function init2() {
1066
1090
  }
1067
1091
 
1068
1092
  // src/commands/vscode/init/index.ts
1069
- import chalk17 from "chalk";
1093
+ import chalk18 from "chalk";
1070
1094
 
1071
1095
  // src/commands/vscode/init/createLaunchJson.ts
1072
1096
  import * as fs3 from "fs";
1073
- import * as path9 from "path";
1074
- import chalk16 from "chalk";
1097
+ import * as path10 from "path";
1098
+ import chalk17 from "chalk";
1075
1099
  function ensureVscodeFolder() {
1076
- const vscodeDir = path9.join(process.cwd(), ".vscode");
1100
+ const vscodeDir = path10.join(process.cwd(), ".vscode");
1077
1101
  if (!fs3.existsSync(vscodeDir)) {
1078
1102
  fs3.mkdirSync(vscodeDir);
1079
- console.log(chalk16.dim("Created .vscode folder"));
1103
+ console.log(chalk17.dim("Created .vscode folder"));
1080
1104
  }
1081
1105
  }
1082
1106
  function removeVscodeFromGitignore() {
1083
- const gitignorePath = path9.join(process.cwd(), ".gitignore");
1107
+ const gitignorePath = path10.join(process.cwd(), ".gitignore");
1084
1108
  if (!fs3.existsSync(gitignorePath)) {
1085
1109
  return;
1086
1110
  }
@@ -1091,7 +1115,7 @@ function removeVscodeFromGitignore() {
1091
1115
  );
1092
1116
  if (filteredLines.length !== lines.length) {
1093
1117
  fs3.writeFileSync(gitignorePath, filteredLines.join("\n"));
1094
- console.log(chalk16.dim("Removed .vscode references from .gitignore"));
1118
+ console.log(chalk17.dim("Removed .vscode references from .gitignore"));
1095
1119
  }
1096
1120
  }
1097
1121
  function createLaunchJson(type) {
@@ -1107,10 +1131,10 @@ function createLaunchJson(type) {
1107
1131
  }
1108
1132
  ]
1109
1133
  };
1110
- const launchPath = path9.join(process.cwd(), ".vscode", "launch.json");
1134
+ const launchPath = path10.join(process.cwd(), ".vscode", "launch.json");
1111
1135
  fs3.writeFileSync(launchPath, `${JSON.stringify(launchConfig, null, " ")}
1112
1136
  `);
1113
- console.log(chalk16.green("Created .vscode/launch.json"));
1137
+ console.log(chalk17.green("Created .vscode/launch.json"));
1114
1138
  }
1115
1139
  function createSettingsJson() {
1116
1140
  const settings = {
@@ -1120,33 +1144,33 @@ function createSettingsJson() {
1120
1144
  "source.organizeImports.biome": "explicit"
1121
1145
  }
1122
1146
  };
1123
- const settingsPath = path9.join(process.cwd(), ".vscode", "settings.json");
1147
+ const settingsPath = path10.join(process.cwd(), ".vscode", "settings.json");
1124
1148
  fs3.writeFileSync(settingsPath, `${JSON.stringify(settings, null, " ")}
1125
1149
  `);
1126
- console.log(chalk16.green("Created .vscode/settings.json"));
1150
+ console.log(chalk17.green("Created .vscode/settings.json"));
1127
1151
  }
1128
1152
  function createExtensionsJson() {
1129
1153
  const extensions = {
1130
1154
  recommendations: ["biomejs.biome"]
1131
1155
  };
1132
- const extensionsPath = path9.join(process.cwd(), ".vscode", "extensions.json");
1156
+ const extensionsPath = path10.join(process.cwd(), ".vscode", "extensions.json");
1133
1157
  fs3.writeFileSync(
1134
1158
  extensionsPath,
1135
1159
  `${JSON.stringify(extensions, null, " ")}
1136
1160
  `
1137
1161
  );
1138
- console.log(chalk16.green("Created .vscode/extensions.json"));
1162
+ console.log(chalk17.green("Created .vscode/extensions.json"));
1139
1163
  }
1140
1164
 
1141
1165
  // src/commands/vscode/init/detectVscodeSetup.ts
1142
1166
  import * as fs4 from "fs";
1143
- import * as path10 from "path";
1167
+ import * as path11 from "path";
1144
1168
  function detectVscodeSetup(pkg) {
1145
- const vscodeDir = path10.join(process.cwd(), ".vscode");
1169
+ const vscodeDir = path11.join(process.cwd(), ".vscode");
1146
1170
  return {
1147
1171
  hasVscodeFolder: fs4.existsSync(vscodeDir),
1148
- hasLaunchJson: fs4.existsSync(path10.join(vscodeDir, "launch.json")),
1149
- hasSettingsJson: fs4.existsSync(path10.join(vscodeDir, "settings.json")),
1172
+ hasLaunchJson: fs4.existsSync(path11.join(vscodeDir, "launch.json")),
1173
+ hasSettingsJson: fs4.existsSync(path11.join(vscodeDir, "settings.json")),
1150
1174
  hasVite: !!pkg.devDependencies?.vite || !!pkg.dependencies?.vite,
1151
1175
  hasTsup: !!pkg.devDependencies?.tsup || !!pkg.dependencies?.tsup
1152
1176
  };
@@ -1192,7 +1216,7 @@ function applySelections(selected, setup2) {
1192
1216
  for (const choice of selected) handlers[choice]?.();
1193
1217
  }
1194
1218
  async function promptForOptions(options2) {
1195
- console.log(chalk17.bold("Available VS Code configurations to add:\n"));
1219
+ console.log(chalk18.bold("Available VS Code configurations to add:\n"));
1196
1220
  return promptMultiselect("Select configurations to add:", options2);
1197
1221
  }
1198
1222
  async function init3({ all = false } = {}) {
@@ -1200,17 +1224,17 @@ async function init3({ all = false } = {}) {
1200
1224
  const setup2 = detectVscodeSetup(pkg);
1201
1225
  const options2 = getAvailableOptions2(setup2);
1202
1226
  if (options2.length === 0) {
1203
- console.log(chalk17.green("VS Code configuration already exists!"));
1227
+ console.log(chalk18.green("VS Code configuration already exists!"));
1204
1228
  return;
1205
1229
  }
1206
1230
  const selected = all ? options2.map((o) => o.value) : await promptForOptions(options2);
1207
1231
  if (selected.length === 0) {
1208
- console.log(chalk17.yellow("No configurations selected"));
1232
+ console.log(chalk18.yellow("No configurations selected"));
1209
1233
  return;
1210
1234
  }
1211
1235
  applySelections(selected, setup2);
1212
1236
  console.log(
1213
- chalk17.green(`
1237
+ chalk18.green(`
1214
1238
  Added ${selected.length} VS Code configuration(s)`)
1215
1239
  );
1216
1240
  }
@@ -1222,13 +1246,16 @@ async function init4() {
1222
1246
  }
1223
1247
 
1224
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
1225
1253
  import fs6 from "fs";
1226
- import path12 from "path";
1227
- import chalk18 from "chalk";
1254
+ import path13 from "path";
1228
1255
 
1229
1256
  // src/shared/findSourceFiles.ts
1230
1257
  import fs5 from "fs";
1231
- import path11 from "path";
1258
+ import path12 from "path";
1232
1259
  var EXTENSIONS = [".ts", ".tsx"];
1233
1260
  function findSourceFiles(dir, options2 = {}) {
1234
1261
  const { includeTests = true } = options2;
@@ -1238,7 +1265,7 @@ function findSourceFiles(dir, options2 = {}) {
1238
1265
  }
1239
1266
  const entries = fs5.readdirSync(dir, { withFileTypes: true });
1240
1267
  for (const entry of entries) {
1241
- const fullPath = path11.join(dir, entry.name);
1268
+ const fullPath = path12.join(dir, entry.name);
1242
1269
  if (entry.isDirectory() && entry.name !== "node_modules") {
1243
1270
  results.push(...findSourceFiles(fullPath, options2));
1244
1271
  } else if (entry.isFile() && EXTENSIONS.some((ext) => entry.name.endsWith(ext))) {
@@ -1251,71 +1278,198 @@ function findSourceFiles(dir, options2 = {}) {
1251
1278
  return results;
1252
1279
  }
1253
1280
 
1254
- // src/commands/lint/lint/runFileNameCheck.ts
1281
+ // src/commands/lint/lint/checkFileNames.ts
1255
1282
  function hasClassOrComponent(content) {
1256
1283
  const classPattern = /^(export\s+)?(abstract\s+)?class\s+\w+/m;
1257
1284
  const functionComponentPattern = /^(export\s+)?(default\s+)?function\s+[A-Z]\w*\s*\(/m;
1258
1285
  const arrowComponentPattern = /^(export\s+)?(const|let)\s+[A-Z]\w*\s*=.*=>/m;
1259
1286
  return classPattern.test(content) || functionComponentPattern.test(content) || arrowComponentPattern.test(content);
1260
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
+ }
1261
1308
  function checkFileNames() {
1262
1309
  const sourceFiles = findSourceFiles("src");
1263
1310
  const violations = [];
1264
1311
  for (const filePath of sourceFiles) {
1265
- const fileName = path12.basename(filePath);
1312
+ const fileName = path13.basename(filePath);
1266
1313
  const nameWithoutExt = fileName.replace(/\.(ts|tsx)$/, "");
1314
+ if (/\.(stories|test)\.(ts|tsx)$/.test(fileName)) continue;
1267
1315
  if (/^[A-Z]/.test(nameWithoutExt)) {
1268
1316
  const content = fs6.readFileSync(filePath, "utf-8");
1269
- if (!hasClassOrComponent(content)) {
1270
- violations.push({ filePath, fileName });
1317
+ if (!hasClassOrComponent(content) && !hasMatchingTypeExport(content, nameWithoutExt)) {
1318
+ violations.push({
1319
+ filePath,
1320
+ fileName,
1321
+ suggestedName: suggestName(fileName)
1322
+ });
1271
1323
  }
1272
1324
  }
1273
1325
  }
1274
1326
  return violations;
1275
1327
  }
1276
- 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) {
1277
1436
  const violations = checkFileNames();
1278
- if (violations.length > 0) {
1279
- console.error(chalk18.red("\nFile name check failed:\n"));
1280
- console.error(
1281
- chalk18.red(
1282
- " Files without classes or React components should not start with a capital letter.\n"
1283
- )
1284
- );
1285
- for (const violation of violations) {
1286
- console.error(chalk18.red(` ${violation.filePath}`));
1287
- console.error(
1288
- chalk18.gray(
1289
- ` Rename to: ${violation.fileName.charAt(0).toLowerCase()}${violation.fileName.slice(1)}
1290
- `
1291
- )
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."
1292
1441
  );
1293
1442
  }
1294
- return false;
1443
+ return true;
1295
1444
  }
1296
- if (!process.env.CLAUDECODE) {
1297
- console.log(
1298
- "File name check passed. All PascalCase files contain classes or components."
1299
- );
1445
+ if (!fix) {
1446
+ reportViolations(violations);
1447
+ return false;
1300
1448
  }
1449
+ fixFileNameViolations(
1450
+ violations.map((v) => ({
1451
+ sourcePath: v.filePath,
1452
+ destPath: path17.join(path17.dirname(v.filePath), v.suggestedName)
1453
+ }))
1454
+ );
1301
1455
  return true;
1302
1456
  }
1303
1457
 
1304
1458
  // src/commands/lint/lint/runImportExtensionCheck.ts
1305
- import fs7 from "fs";
1459
+ import fs9 from "fs";
1306
1460
 
1307
1461
  // src/commands/lint/shared.ts
1308
- import chalk19 from "chalk";
1309
- function reportViolations(violations, checkName, errorMessage, successMessage) {
1462
+ import chalk21 from "chalk";
1463
+ function reportViolations2(violations, checkName, errorMessage, successMessage) {
1310
1464
  if (violations.length > 0) {
1311
- console.error(chalk19.red(`
1465
+ console.error(chalk21.red(`
1312
1466
  ${checkName} failed:
1313
1467
  `));
1314
- console.error(chalk19.red(` ${errorMessage}
1468
+ console.error(chalk21.red(` ${errorMessage}
1315
1469
  `));
1316
1470
  for (const violation of violations) {
1317
- console.error(chalk19.red(` ${violation.filePath}:${violation.line}`));
1318
- console.error(chalk19.gray(` ${violation.content}
1471
+ console.error(chalk21.red(` ${violation.filePath}:${violation.line}`));
1472
+ console.error(chalk21.gray(` ${violation.content}
1319
1473
  `));
1320
1474
  }
1321
1475
  return false;
@@ -1328,7 +1482,7 @@ ${checkName} failed:
1328
1482
 
1329
1483
  // src/commands/lint/lint/runImportExtensionCheck.ts
1330
1484
  function checkForImportExtensions(filePath) {
1331
- const content = fs7.readFileSync(filePath, "utf-8");
1485
+ const content = fs9.readFileSync(filePath, "utf-8");
1332
1486
  const lines = content.split("\n");
1333
1487
  const violations = [];
1334
1488
  const importExtensionPattern = /from\s+["']\..*\.(js|ts)["']/;
@@ -1353,7 +1507,7 @@ function checkImportExtensions() {
1353
1507
  return violations;
1354
1508
  }
1355
1509
  function runImportExtensionCheck() {
1356
- return reportViolations(
1510
+ return reportViolations2(
1357
1511
  checkImportExtensions(),
1358
1512
  "Import extension check",
1359
1513
  "File extensions in imports are not allowed. Use extensionless imports instead.",
@@ -1362,9 +1516,9 @@ function runImportExtensionCheck() {
1362
1516
  }
1363
1517
 
1364
1518
  // src/commands/lint/lint/runStaticImportCheck.ts
1365
- import fs8 from "fs";
1519
+ import fs10 from "fs";
1366
1520
  function checkForDynamicImports(filePath) {
1367
- const content = fs8.readFileSync(filePath, "utf-8");
1521
+ const content = fs10.readFileSync(filePath, "utf-8");
1368
1522
  const lines = content.split("\n");
1369
1523
  const violations = [];
1370
1524
  const requirePattern = /\brequire\s*\(/;
@@ -1390,7 +1544,7 @@ function checkStaticImports() {
1390
1544
  return violations;
1391
1545
  }
1392
1546
  function runStaticImportCheck() {
1393
- return reportViolations(
1547
+ return reportViolations2(
1394
1548
  checkStaticImports(),
1395
1549
  "Static import check",
1396
1550
  "Dynamic imports are not allowed. Use static imports instead.",
@@ -1399,8 +1553,8 @@ function runStaticImportCheck() {
1399
1553
  }
1400
1554
 
1401
1555
  // src/commands/lint/lint/index.ts
1402
- function lint() {
1403
- const fileNamePassed = runFileNameCheck();
1556
+ function lint(options2 = {}) {
1557
+ const fileNamePassed = runFileNameCheck(options2.fix);
1404
1558
  const staticImportPassed = runStaticImportCheck();
1405
1559
  const importExtensionPassed = runImportExtensionCheck();
1406
1560
  if (!fileNamePassed || !staticImportPassed || !importExtensionPassed) {
@@ -1457,7 +1611,7 @@ Total: ${lines.length} hardcoded color(s)`);
1457
1611
  }
1458
1612
 
1459
1613
  // src/commands/verify/run/resolveEntries.ts
1460
- import * as path13 from "path";
1614
+ import * as path18 from "path";
1461
1615
  function buildFullCommand(command, args) {
1462
1616
  return [shellQuote(command), ...(args ?? []).map(shellQuote)].join(" ");
1463
1617
  }
@@ -1474,7 +1628,7 @@ function getRunEntries() {
1474
1628
  function getPackageJsonEntries() {
1475
1629
  const result = findPackageJsonWithVerifyScripts(process.cwd());
1476
1630
  if (!result) return [];
1477
- const cwd = path13.dirname(result.packageJsonPath);
1631
+ const cwd = path18.dirname(result.packageJsonPath);
1478
1632
  return result.verifyScripts.map((script) => ({
1479
1633
  name: script,
1480
1634
  fullCommand: `npm run ${script}`,
@@ -1795,16 +1949,16 @@ import { existsSync as existsSync11, readFileSync as readFileSync9, writeFileSyn
1795
1949
 
1796
1950
  // src/commands/deploy/init/index.ts
1797
1951
  import { execSync as execSync11 } from "child_process";
1798
- import chalk21 from "chalk";
1952
+ import chalk23 from "chalk";
1799
1953
  import enquirer3 from "enquirer";
1800
1954
 
1801
1955
  // src/commands/deploy/init/updateWorkflow.ts
1802
1956
  import { existsSync as existsSync10, mkdirSync as mkdirSync3, readFileSync as readFileSync8, writeFileSync as writeFileSync8 } from "fs";
1803
- import { dirname as dirname10, join as join7 } from "path";
1957
+ import { dirname as dirname11, join as join7 } from "path";
1804
1958
  import { fileURLToPath as fileURLToPath2 } from "url";
1805
- import chalk20 from "chalk";
1959
+ import chalk22 from "chalk";
1806
1960
  var WORKFLOW_PATH = ".github/workflows/build.yml";
1807
- var __dirname3 = dirname10(fileURLToPath2(import.meta.url));
1961
+ var __dirname3 = dirname11(fileURLToPath2(import.meta.url));
1808
1962
  function getExistingSiteId() {
1809
1963
  if (!existsSync10(WORKFLOW_PATH)) {
1810
1964
  return null;
@@ -1827,20 +1981,20 @@ async function updateWorkflow(siteId) {
1827
1981
  if (existsSync10(WORKFLOW_PATH)) {
1828
1982
  const oldContent = readFileSync8(WORKFLOW_PATH, "utf-8");
1829
1983
  if (oldContent === newContent) {
1830
- console.log(chalk20.green("build.yml is already up to date"));
1984
+ console.log(chalk22.green("build.yml is already up to date"));
1831
1985
  return;
1832
1986
  }
1833
- console.log(chalk20.yellow("\nbuild.yml will be updated:"));
1987
+ console.log(chalk22.yellow("\nbuild.yml will be updated:"));
1834
1988
  console.log();
1835
1989
  printDiff(oldContent, newContent);
1836
- const confirm = await promptConfirm(chalk20.red("Update build.yml?"));
1990
+ const confirm = await promptConfirm(chalk22.red("Update build.yml?"));
1837
1991
  if (!confirm) {
1838
1992
  console.log("Skipped build.yml update");
1839
1993
  return;
1840
1994
  }
1841
1995
  }
1842
1996
  writeFileSync8(WORKFLOW_PATH, newContent);
1843
- console.log(chalk20.green(`
1997
+ console.log(chalk22.green(`
1844
1998
  Created ${WORKFLOW_PATH}`));
1845
1999
  }
1846
2000
 
@@ -1851,43 +2005,43 @@ async function ensureNetlifyCli() {
1851
2005
  } catch (error) {
1852
2006
  if (!(error instanceof Error) || !error.message.includes("command not found"))
1853
2007
  throw error;
1854
- console.error(chalk21.red("\nNetlify CLI is not installed.\n"));
2008
+ console.error(chalk23.red("\nNetlify CLI is not installed.\n"));
1855
2009
  const install = await promptConfirm("Would you like to install it now?");
1856
2010
  if (!install) {
1857
2011
  console.log(
1858
- chalk21.yellow(
2012
+ chalk23.yellow(
1859
2013
  "\nInstall it manually with: npm install -g netlify-cli\n"
1860
2014
  )
1861
2015
  );
1862
2016
  process.exit(1);
1863
2017
  }
1864
- console.log(chalk21.dim("\nInstalling netlify-cli...\n"));
2018
+ console.log(chalk23.dim("\nInstalling netlify-cli...\n"));
1865
2019
  execSync11("npm install -g netlify-cli", { stdio: "inherit" });
1866
2020
  console.log();
1867
2021
  execSync11("netlify sites:create --disable-linking", { stdio: "inherit" });
1868
2022
  }
1869
2023
  }
1870
2024
  function printSetupInstructions() {
1871
- console.log(chalk21.bold("\nDeployment initialized successfully!"));
2025
+ console.log(chalk23.bold("\nDeployment initialized successfully!"));
1872
2026
  console.log(
1873
- chalk21.yellow("\nTo complete setup, create a personal access token at:")
2027
+ chalk23.yellow("\nTo complete setup, create a personal access token at:")
1874
2028
  );
1875
2029
  console.log(
1876
- chalk21.cyan(
2030
+ chalk23.cyan(
1877
2031
  "https://app.netlify.com/user/applications#personal-access-tokens"
1878
2032
  )
1879
2033
  );
1880
2034
  console.log(
1881
- chalk21.yellow(
2035
+ chalk23.yellow(
1882
2036
  "\nThen add it as NETLIFY_AUTH_TOKEN in your GitHub repository secrets."
1883
2037
  )
1884
2038
  );
1885
2039
  }
1886
2040
  async function init5() {
1887
- console.log(chalk21.bold("Initializing Netlify deployment...\n"));
2041
+ console.log(chalk23.bold("Initializing Netlify deployment...\n"));
1888
2042
  const existingSiteId = getExistingSiteId();
1889
2043
  if (existingSiteId) {
1890
- console.log(chalk21.dim(`Using existing site ID: ${existingSiteId}
2044
+ console.log(chalk23.dim(`Using existing site ID: ${existingSiteId}
1891
2045
  `));
1892
2046
  await updateWorkflow(existingSiteId);
1893
2047
  return;
@@ -1981,19 +2135,19 @@ function detectPlatform() {
1981
2135
 
1982
2136
  // src/commands/notify/showNotification/showWindowsNotificationFromWsl.ts
1983
2137
  import { spawn as spawn2 } from "child_process";
1984
- import fs9 from "fs";
2138
+ import fs11 from "fs";
1985
2139
  import { createRequire } from "module";
1986
- import path14 from "path";
2140
+ import path19 from "path";
1987
2141
  var require2 = createRequire(import.meta.url);
1988
2142
  function getSnoreToastPath() {
1989
- const notifierPath = path14.dirname(require2.resolve("node-notifier"));
1990
- return path14.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");
1991
2145
  }
1992
2146
  function showWindowsNotificationFromWsl(options2) {
1993
2147
  const { title, message, sound } = options2;
1994
2148
  const snoreToastPath = getSnoreToastPath();
1995
2149
  try {
1996
- fs9.chmodSync(snoreToastPath, 493);
2150
+ fs11.chmodSync(snoreToastPath, 493);
1997
2151
  } catch {
1998
2152
  }
1999
2153
  const args = ["-t", title, "-m", message];
@@ -2067,12 +2221,12 @@ async function notify() {
2067
2221
 
2068
2222
  // src/commands/backlog/add/index.ts
2069
2223
  import { existsSync as existsSync13 } from "fs";
2070
- import chalk23 from "chalk";
2224
+ import chalk25 from "chalk";
2071
2225
 
2072
2226
  // src/commands/backlog/shared.ts
2073
2227
  import { existsSync as existsSync12, readFileSync as readFileSync10, writeFileSync as writeFileSync10 } from "fs";
2074
2228
  import { join as join8 } from "path";
2075
- import chalk22 from "chalk";
2229
+ import chalk24 from "chalk";
2076
2230
  import { parse as parseYaml2, stringify as stringifyYaml3 } from "yaml";
2077
2231
 
2078
2232
  // src/commands/backlog/types.ts
@@ -2116,7 +2270,7 @@ function findItem(items, id) {
2116
2270
  function loadAndFindItem(id) {
2117
2271
  if (!existsSync12(getBacklogPath())) {
2118
2272
  console.log(
2119
- chalk22.yellow(
2273
+ chalk24.yellow(
2120
2274
  "No backlog found. Run 'assist backlog init' to create one."
2121
2275
  )
2122
2276
  );
@@ -2125,7 +2279,7 @@ function loadAndFindItem(id) {
2125
2279
  const items = loadBacklog();
2126
2280
  const item = findItem(items, Number.parseInt(id, 10));
2127
2281
  if (!item) {
2128
- console.log(chalk22.red(`Item #${id} not found.`));
2282
+ console.log(chalk24.red(`Item #${id} not found.`));
2129
2283
  return void 0;
2130
2284
  }
2131
2285
  return { items, item };
@@ -2223,7 +2377,7 @@ async function add() {
2223
2377
  const backlogPath = getBacklogPath();
2224
2378
  if (!existsSync13(backlogPath)) {
2225
2379
  console.log(
2226
- chalk23.yellow(
2380
+ chalk25.yellow(
2227
2381
  "No backlog found. Run 'assist backlog init' to create one."
2228
2382
  )
2229
2383
  );
@@ -2244,67 +2398,67 @@ async function add() {
2244
2398
  status: "todo"
2245
2399
  });
2246
2400
  saveBacklog(items);
2247
- console.log(chalk23.green(`Added item #${id}: ${name}`));
2401
+ console.log(chalk25.green(`Added item #${id}: ${name}`));
2248
2402
  }
2249
2403
 
2250
2404
  // src/commands/backlog/delete/index.ts
2251
- import chalk24 from "chalk";
2405
+ import chalk26 from "chalk";
2252
2406
  async function del(id) {
2253
2407
  const name = removeItem(id);
2254
2408
  if (name) {
2255
- console.log(chalk24.green(`Deleted item #${id}: ${name}`));
2409
+ console.log(chalk26.green(`Deleted item #${id}: ${name}`));
2256
2410
  }
2257
2411
  }
2258
2412
 
2259
2413
  // src/commands/backlog/done/index.ts
2260
- import chalk25 from "chalk";
2414
+ import chalk27 from "chalk";
2261
2415
  async function done(id) {
2262
2416
  const name = setStatus(id, "done");
2263
2417
  if (name) {
2264
- console.log(chalk25.green(`Completed item #${id}: ${name}`));
2418
+ console.log(chalk27.green(`Completed item #${id}: ${name}`));
2265
2419
  }
2266
2420
  }
2267
2421
 
2268
2422
  // src/commands/backlog/init/index.ts
2269
2423
  import { existsSync as existsSync14 } from "fs";
2270
- import chalk26 from "chalk";
2424
+ import chalk28 from "chalk";
2271
2425
  async function init6() {
2272
2426
  const backlogPath = getBacklogPath();
2273
2427
  if (existsSync14(backlogPath)) {
2274
- console.log(chalk26.yellow("assist.backlog.yml already exists."));
2428
+ console.log(chalk28.yellow("assist.backlog.yml already exists."));
2275
2429
  return;
2276
2430
  }
2277
2431
  saveBacklog([]);
2278
- console.log(chalk26.green("Created assist.backlog.yml"));
2432
+ console.log(chalk28.green("Created assist.backlog.yml"));
2279
2433
  }
2280
2434
 
2281
2435
  // src/commands/backlog/list/index.ts
2282
2436
  import { existsSync as existsSync15 } from "fs";
2283
- import chalk27 from "chalk";
2437
+ import chalk29 from "chalk";
2284
2438
  function statusIcon(status2) {
2285
2439
  switch (status2) {
2286
2440
  case "todo":
2287
- return chalk27.dim("[ ]");
2441
+ return chalk29.dim("[ ]");
2288
2442
  case "in-progress":
2289
- return chalk27.yellow("[~]");
2443
+ return chalk29.yellow("[~]");
2290
2444
  case "done":
2291
- return chalk27.green("[x]");
2445
+ return chalk29.green("[x]");
2292
2446
  }
2293
2447
  }
2294
2448
  function typeLabel(type) {
2295
2449
  switch (type) {
2296
2450
  case "bug":
2297
- return chalk27.magenta("Bug");
2451
+ return chalk29.magenta("Bug");
2298
2452
  case "story":
2299
- return chalk27.cyan("Story");
2453
+ return chalk29.cyan("Story");
2300
2454
  }
2301
2455
  }
2302
2456
  function printVerboseDetails(item) {
2303
2457
  if (item.description) {
2304
- console.log(` ${chalk27.dim("Description:")} ${item.description}`);
2458
+ console.log(` ${chalk29.dim("Description:")} ${item.description}`);
2305
2459
  }
2306
2460
  if (item.acceptanceCriteria.length > 0) {
2307
- console.log(` ${chalk27.dim("Acceptance criteria:")}`);
2461
+ console.log(` ${chalk29.dim("Acceptance criteria:")}`);
2308
2462
  for (const criterion of item.acceptanceCriteria) {
2309
2463
  console.log(` - ${criterion}`);
2310
2464
  }
@@ -2320,7 +2474,7 @@ async function list2(options2) {
2320
2474
  const backlogPath = getBacklogPath();
2321
2475
  if (!existsSync15(backlogPath)) {
2322
2476
  console.log(
2323
- chalk27.yellow(
2477
+ chalk29.yellow(
2324
2478
  "No backlog found. Run 'assist backlog init' to create one."
2325
2479
  )
2326
2480
  );
@@ -2328,12 +2482,12 @@ async function list2(options2) {
2328
2482
  }
2329
2483
  const items = filterItems(loadBacklog(), options2);
2330
2484
  if (items.length === 0) {
2331
- console.log(chalk27.dim("Backlog is empty."));
2485
+ console.log(chalk29.dim("Backlog is empty."));
2332
2486
  return;
2333
2487
  }
2334
2488
  for (const item of items) {
2335
2489
  console.log(
2336
- `${statusIcon(item.status)} ${typeLabel(item.type)} ${chalk27.dim(`#${item.id}`)} ${item.name}`
2490
+ `${statusIcon(item.status)} ${typeLabel(item.type)} ${chalk29.dim(`#${item.id}`)} ${item.name}`
2337
2491
  );
2338
2492
  if (options2.verbose) {
2339
2493
  printVerboseDetails(item);
@@ -2342,11 +2496,11 @@ async function list2(options2) {
2342
2496
  }
2343
2497
 
2344
2498
  // src/commands/backlog/start/index.ts
2345
- import chalk28 from "chalk";
2499
+ import chalk30 from "chalk";
2346
2500
  async function start(id) {
2347
2501
  const name = setStatus(id, "in-progress");
2348
2502
  if (name) {
2349
- console.log(chalk28.green(`Started item #${id}: ${name}`));
2503
+ console.log(chalk30.green(`Started item #${id}: ${name}`));
2350
2504
  }
2351
2505
  }
2352
2506
 
@@ -2356,15 +2510,15 @@ import { readFileSync as readFileSync12 } from "fs";
2356
2510
  import {
2357
2511
  createServer
2358
2512
  } from "http";
2359
- import { dirname as dirname11, join as join10 } from "path";
2513
+ import { dirname as dirname12, join as join10 } from "path";
2360
2514
  import { fileURLToPath as fileURLToPath3 } from "url";
2361
- import chalk29 from "chalk";
2515
+ import chalk31 from "chalk";
2362
2516
  function respondJson(res, status2, data) {
2363
2517
  res.writeHead(status2, { "Content-Type": "application/json" });
2364
2518
  res.end(JSON.stringify(data));
2365
2519
  }
2366
2520
  function createBundleHandler(importMetaUrl, bundlePath) {
2367
- const dir = dirname11(fileURLToPath3(importMetaUrl));
2521
+ const dir = dirname12(fileURLToPath3(importMetaUrl));
2368
2522
  let cache;
2369
2523
  return (_req, res) => {
2370
2524
  if (!cache) {
@@ -2402,8 +2556,8 @@ function startWebServer(label2, port, handler) {
2402
2556
  handler(req, res, port);
2403
2557
  });
2404
2558
  server.listen(port, () => {
2405
- console.log(chalk29.green(`${label2}: ${url}`));
2406
- console.log(chalk29.dim("Press Ctrl+C to stop"));
2559
+ console.log(chalk31.green(`${label2}: ${url}`));
2560
+ console.log(chalk31.dim("Press Ctrl+C to stop"));
2407
2561
  exec(`open ${url}`);
2408
2562
  });
2409
2563
  }
@@ -2633,22 +2787,22 @@ function extractGraphqlQuery(args) {
2633
2787
 
2634
2788
  // src/shared/loadCliReads.ts
2635
2789
  import { existsSync as existsSync16, readFileSync as readFileSync13, writeFileSync as writeFileSync12 } from "fs";
2636
- import { dirname as dirname12, resolve as resolve2 } from "path";
2790
+ import { dirname as dirname13, resolve as resolve2 } from "path";
2637
2791
  import { fileURLToPath as fileURLToPath4 } from "url";
2638
2792
  var __filename2 = fileURLToPath4(import.meta.url);
2639
- var __dirname4 = dirname12(__filename2);
2793
+ var __dirname4 = dirname13(__filename2);
2640
2794
  function getCliReadsPath() {
2641
2795
  return resolve2(__dirname4, "..", "assist.cli-reads");
2642
2796
  }
2643
2797
  var cachedLines;
2644
2798
  function getCliReadsLines() {
2645
2799
  if (cachedLines) return cachedLines;
2646
- const path35 = getCliReadsPath();
2647
- if (!existsSync16(path35)) {
2800
+ const path43 = getCliReadsPath();
2801
+ if (!existsSync16(path43)) {
2648
2802
  cachedLines = [];
2649
2803
  return cachedLines;
2650
2804
  }
2651
- cachedLines = readFileSync13(path35, "utf-8").split("\n").filter((line) => line.trim() !== "");
2805
+ cachedLines = readFileSync13(path43, "utf-8").split("\n").filter((line) => line.trim() !== "");
2652
2806
  return cachedLines;
2653
2807
  }
2654
2808
  function loadCliReads() {
@@ -2854,10 +3008,10 @@ import { join as join12 } from "path";
2854
3008
 
2855
3009
  // src/shared/getInstallDir.ts
2856
3010
  import { execSync as execSync13 } from "child_process";
2857
- import { dirname as dirname13, resolve as resolve4 } from "path";
3011
+ import { dirname as dirname14, resolve as resolve4 } from "path";
2858
3012
  import { fileURLToPath as fileURLToPath5 } from "url";
2859
3013
  var __filename3 = fileURLToPath5(import.meta.url);
2860
- var __dirname5 = dirname13(__filename3);
3014
+ var __dirname5 = dirname14(__filename3);
2861
3015
  function getInstallDir() {
2862
3016
  return resolve4(__dirname5, "..");
2863
3017
  }
@@ -2894,11 +3048,11 @@ function assertCliExists(cli) {
2894
3048
  }
2895
3049
 
2896
3050
  // src/commands/permitCliReads/colorize.ts
2897
- import chalk30 from "chalk";
3051
+ import chalk32 from "chalk";
2898
3052
  function colorize(plainOutput) {
2899
3053
  return plainOutput.split("\n").map((line) => {
2900
- if (line.startsWith(" R ")) return chalk30.green(line);
2901
- if (line.startsWith(" W ")) return chalk30.red(line);
3054
+ if (line.startsWith(" R ")) return chalk32.green(line);
3055
+ if (line.startsWith(" W ")) return chalk32.red(line);
2902
3056
  return line;
2903
3057
  }).join("\n");
2904
3058
  }
@@ -3000,14 +3154,14 @@ function showProgress(p, label2) {
3000
3154
  const pct = Math.round(p.done / p.total * 100);
3001
3155
  process.stderr.write(`\r\x1B[K[${pct}%] Scanning ${label2}...`);
3002
3156
  }
3003
- async function resolveCommand(cli, path35, description, depth, p) {
3004
- showProgress(p, path35.join(" "));
3005
- const subHelp = await runHelp([cli, ...path35]);
3157
+ async function resolveCommand(cli, path43, description, depth, p) {
3158
+ showProgress(p, path43.join(" "));
3159
+ const subHelp = await runHelp([cli, ...path43]);
3006
3160
  if (!subHelp || !hasSubcommands(subHelp)) {
3007
- return [{ path: path35, description }];
3161
+ return [{ path: path43, description }];
3008
3162
  }
3009
- const children = await discoverAt(cli, path35, depth + 1, p);
3010
- return children.length > 0 ? children : [{ path: path35, description }];
3163
+ const children = await discoverAt(cli, path43, depth + 1, p);
3164
+ return children.length > 0 ? children : [{ path: path43, description }];
3011
3165
  }
3012
3166
  async function discoverAt(cli, parentPath, depth, p) {
3013
3167
  if (depth > SAFETY_DEPTH) return [];
@@ -3155,9 +3309,9 @@ function logPath(cli) {
3155
3309
  return join12(homedir4(), ".assist", `cli-discover-${safeName}.log`);
3156
3310
  }
3157
3311
  function readCache(cli) {
3158
- const path35 = logPath(cli);
3159
- if (!existsSync18(path35)) return void 0;
3160
- return readFileSync15(path35, "utf-8");
3312
+ const path43 = logPath(cli);
3313
+ if (!existsSync18(path43)) return void 0;
3314
+ return readFileSync15(path43, "utf-8");
3161
3315
  }
3162
3316
  function writeCache(cli, output) {
3163
3317
  const dir = join12(homedir4(), ".assist");
@@ -3209,20 +3363,20 @@ function registerCliHook(program2) {
3209
3363
  }
3210
3364
 
3211
3365
  // src/commands/complexity/analyze.ts
3212
- import chalk36 from "chalk";
3366
+ import chalk38 from "chalk";
3213
3367
 
3214
3368
  // src/commands/complexity/cyclomatic.ts
3215
- import chalk32 from "chalk";
3369
+ import chalk34 from "chalk";
3216
3370
 
3217
3371
  // src/commands/complexity/shared/index.ts
3218
- import fs11 from "fs";
3219
- import path16 from "path";
3220
- import chalk31 from "chalk";
3372
+ import fs13 from "fs";
3373
+ import path21 from "path";
3374
+ import chalk33 from "chalk";
3221
3375
  import ts5 from "typescript";
3222
3376
 
3223
3377
  // src/commands/complexity/findSourceFiles.ts
3224
- import fs10 from "fs";
3225
- import path15 from "path";
3378
+ import fs12 from "fs";
3379
+ import path20 from "path";
3226
3380
  import { minimatch as minimatch3 } from "minimatch";
3227
3381
  function applyIgnoreGlobs(files) {
3228
3382
  const { complexity } = loadConfig();
@@ -3231,13 +3385,13 @@ function applyIgnoreGlobs(files) {
3231
3385
  );
3232
3386
  }
3233
3387
  function walk(dir, results) {
3234
- if (!fs10.existsSync(dir)) {
3388
+ if (!fs12.existsSync(dir)) {
3235
3389
  return;
3236
3390
  }
3237
3391
  const extensions = [".ts", ".tsx"];
3238
- const entries = fs10.readdirSync(dir, { withFileTypes: true });
3392
+ const entries = fs12.readdirSync(dir, { withFileTypes: true });
3239
3393
  for (const entry of entries) {
3240
- const fullPath = path15.join(dir, entry.name);
3394
+ const fullPath = path20.join(dir, entry.name);
3241
3395
  if (entry.isDirectory()) {
3242
3396
  if (entry.name !== "node_modules" && entry.name !== ".git") {
3243
3397
  walk(fullPath, results);
@@ -3253,10 +3407,10 @@ function findSourceFiles2(pattern2, baseDir = ".") {
3253
3407
  walk(baseDir, results);
3254
3408
  return applyIgnoreGlobs(results.filter((f) => minimatch3(f, pattern2)));
3255
3409
  }
3256
- if (fs10.existsSync(pattern2) && fs10.statSync(pattern2).isFile()) {
3410
+ if (fs12.existsSync(pattern2) && fs12.statSync(pattern2).isFile()) {
3257
3411
  return [pattern2];
3258
3412
  }
3259
- if (fs10.existsSync(pattern2) && fs10.statSync(pattern2).isDirectory()) {
3413
+ if (fs12.existsSync(pattern2) && fs12.statSync(pattern2).isDirectory()) {
3260
3414
  walk(pattern2, results);
3261
3415
  return applyIgnoreGlobs(results);
3262
3416
  }
@@ -3451,9 +3605,9 @@ function countSloc(content) {
3451
3605
 
3452
3606
  // src/commands/complexity/shared/index.ts
3453
3607
  function createSourceFromFile(filePath) {
3454
- const content = fs11.readFileSync(filePath, "utf-8");
3608
+ const content = fs13.readFileSync(filePath, "utf-8");
3455
3609
  return ts5.createSourceFile(
3456
- path16.basename(filePath),
3610
+ path21.basename(filePath),
3457
3611
  content,
3458
3612
  ts5.ScriptTarget.Latest,
3459
3613
  true,
@@ -3463,7 +3617,7 @@ function createSourceFromFile(filePath) {
3463
3617
  function withSourceFiles(pattern2, callback) {
3464
3618
  const files = findSourceFiles2(pattern2);
3465
3619
  if (files.length === 0) {
3466
- console.log(chalk31.yellow("No files found matching pattern"));
3620
+ console.log(chalk33.yellow("No files found matching pattern"));
3467
3621
  return void 0;
3468
3622
  }
3469
3623
  return callback(files);
@@ -3496,11 +3650,11 @@ async function cyclomatic(pattern2 = "**/*.ts", options2 = {}) {
3496
3650
  results.sort((a, b) => b.complexity - a.complexity);
3497
3651
  for (const { file, name, complexity } of results) {
3498
3652
  const exceedsThreshold = options2.threshold !== void 0 && complexity > options2.threshold;
3499
- const color = exceedsThreshold ? chalk32.red : chalk32.white;
3500
- console.log(`${color(`${file}:${name}`)} \u2192 ${chalk32.cyan(complexity)}`);
3653
+ const color = exceedsThreshold ? chalk34.red : chalk34.white;
3654
+ console.log(`${color(`${file}:${name}`)} \u2192 ${chalk34.cyan(complexity)}`);
3501
3655
  }
3502
3656
  console.log(
3503
- chalk32.dim(
3657
+ chalk34.dim(
3504
3658
  `
3505
3659
  Analyzed ${results.length} functions across ${files.length} files`
3506
3660
  )
@@ -3512,7 +3666,7 @@ Analyzed ${results.length} functions across ${files.length} files`
3512
3666
  }
3513
3667
 
3514
3668
  // src/commands/complexity/halstead.ts
3515
- import chalk33 from "chalk";
3669
+ import chalk35 from "chalk";
3516
3670
  async function halstead(pattern2 = "**/*.ts", options2 = {}) {
3517
3671
  withSourceFiles(pattern2, (files) => {
3518
3672
  const results = [];
@@ -3527,13 +3681,13 @@ async function halstead(pattern2 = "**/*.ts", options2 = {}) {
3527
3681
  results.sort((a, b) => b.metrics.effort - a.metrics.effort);
3528
3682
  for (const { file, name, metrics } of results) {
3529
3683
  const exceedsThreshold = options2.threshold !== void 0 && metrics.volume > options2.threshold;
3530
- const color = exceedsThreshold ? chalk33.red : chalk33.white;
3684
+ const color = exceedsThreshold ? chalk35.red : chalk35.white;
3531
3685
  console.log(
3532
- `${color(`${file}:${name}`)} \u2192 volume: ${chalk33.cyan(metrics.volume.toFixed(1))}, difficulty: ${chalk33.yellow(metrics.difficulty.toFixed(1))}, effort: ${chalk33.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))}`
3533
3687
  );
3534
3688
  }
3535
3689
  console.log(
3536
- chalk33.dim(
3690
+ chalk35.dim(
3537
3691
  `
3538
3692
  Analyzed ${results.length} functions across ${files.length} files`
3539
3693
  )
@@ -3545,31 +3699,31 @@ Analyzed ${results.length} functions across ${files.length} files`
3545
3699
  }
3546
3700
 
3547
3701
  // src/commands/complexity/maintainability/index.ts
3548
- import fs12 from "fs";
3702
+ import fs14 from "fs";
3549
3703
 
3550
3704
  // src/commands/complexity/maintainability/displayMaintainabilityResults.ts
3551
- import chalk34 from "chalk";
3705
+ import chalk36 from "chalk";
3552
3706
  function displayMaintainabilityResults(results, threshold) {
3553
3707
  const filtered = threshold !== void 0 ? results.filter((r) => r.minMaintainability < threshold) : results;
3554
3708
  if (threshold !== void 0 && filtered.length === 0) {
3555
- console.log(chalk34.green("All files pass maintainability threshold"));
3709
+ console.log(chalk36.green("All files pass maintainability threshold"));
3556
3710
  } else {
3557
3711
  for (const { file, avgMaintainability, minMaintainability } of filtered) {
3558
- const color = threshold !== void 0 ? chalk34.red : chalk34.white;
3712
+ const color = threshold !== void 0 ? chalk36.red : chalk36.white;
3559
3713
  console.log(
3560
- `${color(file)} \u2192 avg: ${chalk34.cyan(avgMaintainability.toFixed(1))}, min: ${chalk34.yellow(minMaintainability.toFixed(1))}`
3714
+ `${color(file)} \u2192 avg: ${chalk36.cyan(avgMaintainability.toFixed(1))}, min: ${chalk36.yellow(minMaintainability.toFixed(1))}`
3561
3715
  );
3562
3716
  }
3563
3717
  }
3564
- console.log(chalk34.dim(`
3718
+ console.log(chalk36.dim(`
3565
3719
  Analyzed ${results.length} files`));
3566
3720
  if (filtered.length > 0 && threshold !== void 0) {
3567
3721
  console.error(
3568
- chalk34.red(
3722
+ chalk36.red(
3569
3723
  `
3570
3724
  Fail: ${filtered.length} file(s) below threshold ${threshold}. Maintainability index (0\u2013100) is derived from Halstead volume, cyclomatic complexity, and lines of code.
3571
3725
 
3572
- \u26A0\uFE0F ${chalk34.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.`
3573
3727
  )
3574
3728
  );
3575
3729
  process.exit(1);
@@ -3587,7 +3741,7 @@ function calculateMaintainabilityIndex(halsteadVolume, cyclomaticComplexity, slo
3587
3741
  function collectFileMetrics(files) {
3588
3742
  const fileMetrics = /* @__PURE__ */ new Map();
3589
3743
  for (const file of files) {
3590
- const content = fs12.readFileSync(file, "utf-8");
3744
+ const content = fs14.readFileSync(file, "utf-8");
3591
3745
  fileMetrics.set(file, { sloc: countSloc(content), functions: [] });
3592
3746
  }
3593
3747
  forEachFunction(files, (file, _name, node) => {
@@ -3625,14 +3779,14 @@ async function maintainability(pattern2 = "**/*.ts", options2 = {}) {
3625
3779
  }
3626
3780
 
3627
3781
  // src/commands/complexity/sloc.ts
3628
- import fs13 from "fs";
3629
- import chalk35 from "chalk";
3782
+ import fs15 from "fs";
3783
+ import chalk37 from "chalk";
3630
3784
  async function sloc(pattern2 = "**/*.ts", options2 = {}) {
3631
3785
  withSourceFiles(pattern2, (files) => {
3632
3786
  const results = [];
3633
3787
  let hasViolation = false;
3634
3788
  for (const file of files) {
3635
- const content = fs13.readFileSync(file, "utf-8");
3789
+ const content = fs15.readFileSync(file, "utf-8");
3636
3790
  const lines = countSloc(content);
3637
3791
  results.push({ file, lines });
3638
3792
  if (options2.threshold !== void 0 && lines > options2.threshold) {
@@ -3642,12 +3796,12 @@ async function sloc(pattern2 = "**/*.ts", options2 = {}) {
3642
3796
  results.sort((a, b) => b.lines - a.lines);
3643
3797
  for (const { file, lines } of results) {
3644
3798
  const exceedsThreshold = options2.threshold !== void 0 && lines > options2.threshold;
3645
- const color = exceedsThreshold ? chalk35.red : chalk35.white;
3646
- console.log(`${color(file)} \u2192 ${chalk35.cyan(lines)} lines`);
3799
+ const color = exceedsThreshold ? chalk37.red : chalk37.white;
3800
+ console.log(`${color(file)} \u2192 ${chalk37.cyan(lines)} lines`);
3647
3801
  }
3648
3802
  const total = results.reduce((sum, r) => sum + r.lines, 0);
3649
3803
  console.log(
3650
- chalk35.dim(`
3804
+ chalk37.dim(`
3651
3805
  Total: ${total} lines across ${files.length} files`)
3652
3806
  );
3653
3807
  if (hasViolation) {
@@ -3661,21 +3815,21 @@ async function analyze(pattern2) {
3661
3815
  const searchPattern = pattern2.includes("*") || pattern2.includes("/") ? pattern2 : `**/${pattern2}`;
3662
3816
  const files = findSourceFiles2(searchPattern);
3663
3817
  if (files.length === 0) {
3664
- console.log(chalk36.yellow("No files found matching pattern"));
3818
+ console.log(chalk38.yellow("No files found matching pattern"));
3665
3819
  return;
3666
3820
  }
3667
3821
  if (files.length === 1) {
3668
3822
  const file = files[0];
3669
- console.log(chalk36.bold.underline("SLOC"));
3823
+ console.log(chalk38.bold.underline("SLOC"));
3670
3824
  await sloc(file);
3671
3825
  console.log();
3672
- console.log(chalk36.bold.underline("Cyclomatic Complexity"));
3826
+ console.log(chalk38.bold.underline("Cyclomatic Complexity"));
3673
3827
  await cyclomatic(file);
3674
3828
  console.log();
3675
- console.log(chalk36.bold.underline("Halstead Metrics"));
3829
+ console.log(chalk38.bold.underline("Halstead Metrics"));
3676
3830
  await halstead(file);
3677
3831
  console.log();
3678
- console.log(chalk36.bold.underline("Maintainability Index"));
3832
+ console.log(chalk38.bold.underline("Maintainability Index"));
3679
3833
  await maintainability(file);
3680
3834
  return;
3681
3835
  }
@@ -3703,7 +3857,7 @@ function registerComplexity(program2) {
3703
3857
 
3704
3858
  // src/commands/deploy/redirect.ts
3705
3859
  import { existsSync as existsSync19, readFileSync as readFileSync16, writeFileSync as writeFileSync14 } from "fs";
3706
- import chalk37 from "chalk";
3860
+ import chalk39 from "chalk";
3707
3861
  var TRAILING_SLASH_SCRIPT = ` <script>
3708
3862
  if (!window.location.pathname.endsWith('/')) {
3709
3863
  window.location.href = \`\${window.location.pathname}/\${window.location.search}\${window.location.hash}\`;
@@ -3712,22 +3866,22 @@ var TRAILING_SLASH_SCRIPT = ` <script>
3712
3866
  function redirect() {
3713
3867
  const indexPath = "index.html";
3714
3868
  if (!existsSync19(indexPath)) {
3715
- console.log(chalk37.yellow("No index.html found"));
3869
+ console.log(chalk39.yellow("No index.html found"));
3716
3870
  return;
3717
3871
  }
3718
3872
  const content = readFileSync16(indexPath, "utf-8");
3719
3873
  if (content.includes("window.location.pathname.endsWith('/')")) {
3720
- console.log(chalk37.dim("Trailing slash script already present"));
3874
+ console.log(chalk39.dim("Trailing slash script already present"));
3721
3875
  return;
3722
3876
  }
3723
3877
  const headCloseIndex = content.indexOf("</head>");
3724
3878
  if (headCloseIndex === -1) {
3725
- console.log(chalk37.red("Could not find </head> tag in index.html"));
3879
+ console.log(chalk39.red("Could not find </head> tag in index.html"));
3726
3880
  return;
3727
3881
  }
3728
3882
  const newContent = content.slice(0, headCloseIndex) + TRAILING_SLASH_SCRIPT + "\n " + content.slice(headCloseIndex);
3729
3883
  writeFileSync14(indexPath, newContent);
3730
- console.log(chalk37.green("Added trailing slash redirect to index.html"));
3884
+ console.log(chalk39.green("Added trailing slash redirect to index.html"));
3731
3885
  }
3732
3886
 
3733
3887
  // src/commands/registerDeploy.ts
@@ -3754,7 +3908,7 @@ function loadBlogSkipDays(repoName) {
3754
3908
 
3755
3909
  // src/commands/devlog/shared.ts
3756
3910
  import { execSync as execSync15 } from "child_process";
3757
- import chalk38 from "chalk";
3911
+ import chalk40 from "chalk";
3758
3912
 
3759
3913
  // src/commands/devlog/loadDevlogEntries.ts
3760
3914
  import { readdirSync, readFileSync as readFileSync17 } from "fs";
@@ -3841,13 +3995,13 @@ function shouldIgnoreCommit(files, ignorePaths) {
3841
3995
  }
3842
3996
  function printCommitsWithFiles(commits, ignore2, verbose) {
3843
3997
  for (const commit2 of commits) {
3844
- console.log(` ${chalk38.yellow(commit2.hash)} ${commit2.message}`);
3998
+ console.log(` ${chalk40.yellow(commit2.hash)} ${commit2.message}`);
3845
3999
  if (verbose) {
3846
4000
  const visibleFiles = commit2.files.filter(
3847
4001
  (file) => !ignore2.some((p) => file.startsWith(p))
3848
4002
  );
3849
4003
  for (const file of visibleFiles) {
3850
- console.log(` ${chalk38.dim(file)}`);
4004
+ console.log(` ${chalk40.dim(file)}`);
3851
4005
  }
3852
4006
  }
3853
4007
  }
@@ -3872,15 +4026,15 @@ function parseGitLogCommits(output, ignore2, afterDate) {
3872
4026
  }
3873
4027
 
3874
4028
  // src/commands/devlog/list/printDateHeader.ts
3875
- import chalk39 from "chalk";
4029
+ import chalk41 from "chalk";
3876
4030
  function printDateHeader(date, isSkipped, entries) {
3877
4031
  if (isSkipped) {
3878
- console.log(`${chalk39.bold.blue(date)} ${chalk39.dim("skipped")}`);
4032
+ console.log(`${chalk41.bold.blue(date)} ${chalk41.dim("skipped")}`);
3879
4033
  } else if (entries && entries.length > 0) {
3880
- const entryInfo = entries.map((e) => `${chalk39.green(e.version)} ${e.title}`).join(" | ");
3881
- console.log(`${chalk39.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}`);
3882
4036
  } else {
3883
- console.log(`${chalk39.bold.blue(date)} ${chalk39.red("\u26A0 devlog missing")}`);
4037
+ console.log(`${chalk41.bold.blue(date)} ${chalk41.red("\u26A0 devlog missing")}`);
3884
4038
  }
3885
4039
  }
3886
4040
 
@@ -3983,24 +4137,24 @@ function bumpVersion(version2, type) {
3983
4137
 
3984
4138
  // src/commands/devlog/next/displayNextEntry/index.ts
3985
4139
  import { execSync as execSync18 } from "child_process";
3986
- import chalk41 from "chalk";
4140
+ import chalk43 from "chalk";
3987
4141
 
3988
4142
  // src/commands/devlog/next/displayNextEntry/displayVersion.ts
3989
- import chalk40 from "chalk";
4143
+ import chalk42 from "chalk";
3990
4144
  function displayVersion(conventional, firstHash, patchVersion, minorVersion) {
3991
4145
  if (conventional && firstHash) {
3992
4146
  const version2 = getVersionAtCommit(firstHash);
3993
4147
  if (version2) {
3994
- console.log(`${chalk40.bold("version:")} ${stripToMinor(version2)}`);
4148
+ console.log(`${chalk42.bold("version:")} ${stripToMinor(version2)}`);
3995
4149
  } else {
3996
- console.log(`${chalk40.bold("version:")} ${chalk40.red("unknown")}`);
4150
+ console.log(`${chalk42.bold("version:")} ${chalk42.red("unknown")}`);
3997
4151
  }
3998
4152
  } else if (patchVersion && minorVersion) {
3999
4153
  console.log(
4000
- `${chalk40.bold("version:")} ${patchVersion} (patch) or ${minorVersion} (minor)`
4154
+ `${chalk42.bold("version:")} ${patchVersion} (patch) or ${minorVersion} (minor)`
4001
4155
  );
4002
4156
  } else {
4003
- console.log(`${chalk40.bold("version:")} v0.1 (initial)`);
4157
+ console.log(`${chalk42.bold("version:")} v0.1 (initial)`);
4004
4158
  }
4005
4159
  }
4006
4160
 
@@ -4047,16 +4201,16 @@ function noCommitsMessage(hasLastInfo) {
4047
4201
  return hasLastInfo ? "No commits after last versioned entry" : "No commits found";
4048
4202
  }
4049
4203
  function logName(repoName) {
4050
- console.log(`${chalk41.bold("name:")} ${repoName}`);
4204
+ console.log(`${chalk43.bold("name:")} ${repoName}`);
4051
4205
  }
4052
4206
  function displayNextEntry(ctx, targetDate, commits) {
4053
4207
  logName(ctx.repoName);
4054
4208
  printVersionInfo(ctx.config, ctx.lastInfo, commits[0]?.hash);
4055
- console.log(chalk41.bold.blue(targetDate));
4209
+ console.log(chalk43.bold.blue(targetDate));
4056
4210
  printCommitsWithFiles(commits, ctx.ignore, ctx.verbose);
4057
4211
  }
4058
4212
  function logNoCommits(lastInfo) {
4059
- console.log(chalk41.dim(noCommitsMessage(!!lastInfo)));
4213
+ console.log(chalk43.dim(noCommitsMessage(!!lastInfo)));
4060
4214
  }
4061
4215
 
4062
4216
  // src/commands/devlog/next/index.ts
@@ -4097,11 +4251,11 @@ function next(options2) {
4097
4251
  import { execSync as execSync19 } from "child_process";
4098
4252
 
4099
4253
  // src/commands/devlog/repos/printReposTable.ts
4100
- import chalk42 from "chalk";
4254
+ import chalk44 from "chalk";
4101
4255
  function colorStatus(status2) {
4102
- if (status2 === "missing") return chalk42.red(status2);
4103
- if (status2 === "outdated") return chalk42.yellow(status2);
4104
- return chalk42.green(status2);
4256
+ if (status2 === "missing") return chalk44.red(status2);
4257
+ if (status2 === "outdated") return chalk44.yellow(status2);
4258
+ return chalk44.green(status2);
4105
4259
  }
4106
4260
  function formatRow(row, nameWidth) {
4107
4261
  const devlog = (row.lastDevlog ?? "-").padEnd(11);
@@ -4115,8 +4269,8 @@ function printReposTable(rows) {
4115
4269
  "Last Devlog".padEnd(11),
4116
4270
  "Status"
4117
4271
  ].join(" ");
4118
- console.log(chalk42.dim(header));
4119
- console.log(chalk42.dim("-".repeat(header.length)));
4272
+ console.log(chalk44.dim(header));
4273
+ console.log(chalk44.dim("-".repeat(header.length)));
4120
4274
  for (const row of rows) {
4121
4275
  console.log(formatRow(row, nameWidth));
4122
4276
  }
@@ -4174,14 +4328,14 @@ function repos(options2) {
4174
4328
  // src/commands/devlog/skip.ts
4175
4329
  import { writeFileSync as writeFileSync15 } from "fs";
4176
4330
  import { join as join15 } from "path";
4177
- import chalk43 from "chalk";
4331
+ import chalk45 from "chalk";
4178
4332
  import { stringify as stringifyYaml4 } from "yaml";
4179
4333
  function getBlogConfigPath() {
4180
4334
  return join15(BLOG_REPO_ROOT, "assist.yml");
4181
4335
  }
4182
4336
  function skip(date) {
4183
4337
  if (!/^\d{4}-\d{2}-\d{2}$/.test(date)) {
4184
- console.log(chalk43.red("Invalid date format. Use YYYY-MM-DD"));
4338
+ console.log(chalk45.red("Invalid date format. Use YYYY-MM-DD"));
4185
4339
  process.exit(1);
4186
4340
  }
4187
4341
  const repoName = getRepoName();
@@ -4192,7 +4346,7 @@ function skip(date) {
4192
4346
  const skipDays = skip2[repoName] ?? [];
4193
4347
  if (skipDays.includes(date)) {
4194
4348
  console.log(
4195
- chalk43.yellow(`${date} is already in skip list for ${repoName}`)
4349
+ chalk45.yellow(`${date} is already in skip list for ${repoName}`)
4196
4350
  );
4197
4351
  return;
4198
4352
  }
@@ -4202,20 +4356,20 @@ function skip(date) {
4202
4356
  devlog.skip = skip2;
4203
4357
  config.devlog = devlog;
4204
4358
  writeFileSync15(configPath, stringifyYaml4(config, { lineWidth: 0 }));
4205
- console.log(chalk43.green(`Added ${date} to skip list for ${repoName}`));
4359
+ console.log(chalk45.green(`Added ${date} to skip list for ${repoName}`));
4206
4360
  }
4207
4361
 
4208
4362
  // src/commands/devlog/version.ts
4209
- import chalk44 from "chalk";
4363
+ import chalk46 from "chalk";
4210
4364
  function version() {
4211
4365
  const config = loadConfig();
4212
4366
  const name = getRepoName();
4213
4367
  const lastInfo = getLastVersionInfo(name, config);
4214
4368
  const lastVersion = lastInfo?.version ?? null;
4215
4369
  const nextVersion = lastVersion ? bumpVersion(lastVersion, "patch") : null;
4216
- console.log(`${chalk44.bold("name:")} ${name}`);
4217
- console.log(`${chalk44.bold("last:")} ${lastVersion ?? chalk44.dim("none")}`);
4218
- console.log(`${chalk44.bold("next:")} ${nextVersion ?? chalk44.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")}`);
4219
4373
  }
4220
4374
 
4221
4375
  // src/commands/registerDevlog.ts
@@ -4238,7 +4392,7 @@ function registerDevlog(program2) {
4238
4392
 
4239
4393
  // src/commands/jira/acceptanceCriteria.ts
4240
4394
  import { execSync as execSync20 } from "child_process";
4241
- import chalk45 from "chalk";
4395
+ import chalk47 from "chalk";
4242
4396
 
4243
4397
  // src/commands/jira/adfToText.ts
4244
4398
  function renderInline(node) {
@@ -4313,21 +4467,21 @@ function acceptanceCriteria(issueKey) {
4313
4467
  const stderr = error.stderr;
4314
4468
  if (stderr.includes("unauthorized")) {
4315
4469
  console.error(
4316
- chalk45.red("Jira authentication expired."),
4470
+ chalk47.red("Jira authentication expired."),
4317
4471
  "Run",
4318
- chalk45.cyan("assist jira auth"),
4472
+ chalk47.cyan("assist jira auth"),
4319
4473
  "to re-authenticate."
4320
4474
  );
4321
4475
  process.exit(1);
4322
4476
  }
4323
4477
  }
4324
- console.error(chalk45.red(`Failed to fetch ${issueKey}.`));
4478
+ console.error(chalk47.red(`Failed to fetch ${issueKey}.`));
4325
4479
  process.exit(1);
4326
4480
  }
4327
4481
  const parsed = JSON.parse(result);
4328
4482
  const acValue = parsed?.fields?.[field];
4329
4483
  if (!acValue) {
4330
- console.log(chalk45.yellow(`No acceptance criteria found on ${issueKey}.`));
4484
+ console.log(chalk47.yellow(`No acceptance criteria found on ${issueKey}.`));
4331
4485
  return;
4332
4486
  }
4333
4487
  if (typeof acValue === "string") {
@@ -4356,10 +4510,10 @@ function getStorePath(filename) {
4356
4510
  return join16(getStoreDir(), filename);
4357
4511
  }
4358
4512
  function loadJson(filename) {
4359
- const path35 = getStorePath(filename);
4360
- if (existsSync20(path35)) {
4513
+ const path43 = getStorePath(filename);
4514
+ if (existsSync20(path43)) {
4361
4515
  try {
4362
- return JSON.parse(readFileSync18(path35, "utf-8"));
4516
+ return JSON.parse(readFileSync18(path43, "utf-8"));
4363
4517
  } catch {
4364
4518
  return {};
4365
4519
  }
@@ -4426,7 +4580,7 @@ function registerJira(program2) {
4426
4580
 
4427
4581
  // src/commands/netframework/buildTree.ts
4428
4582
  import { readFileSync as readFileSync19 } from "fs";
4429
- import path17 from "path";
4583
+ import path22 from "path";
4430
4584
  var PROJECT_REF_RE = /<ProjectReference\s+Include="([^"]+)"/g;
4431
4585
  function getProjectRefs(csprojPath) {
4432
4586
  const content = readFileSync19(csprojPath, "utf-8");
@@ -4437,14 +4591,14 @@ function getProjectRefs(csprojPath) {
4437
4591
  return refs;
4438
4592
  }
4439
4593
  function buildTree(csprojPath, repoRoot, visited = /* @__PURE__ */ new Set()) {
4440
- const abs = path17.resolve(csprojPath);
4441
- const rel = path17.relative(repoRoot, abs);
4594
+ const abs = path22.resolve(csprojPath);
4595
+ const rel = path22.relative(repoRoot, abs);
4442
4596
  const node = { path: abs, relativePath: rel, children: [] };
4443
4597
  if (visited.has(abs)) return node;
4444
4598
  visited.add(abs);
4445
- const dir = path17.dirname(abs);
4599
+ const dir = path22.dirname(abs);
4446
4600
  for (const ref of getProjectRefs(abs)) {
4447
- const childAbs = path17.resolve(dir, ref);
4601
+ const childAbs = path22.resolve(dir, ref);
4448
4602
  try {
4449
4603
  readFileSync19(childAbs);
4450
4604
  node.children.push(buildTree(childAbs, repoRoot, visited));
@@ -4472,7 +4626,7 @@ function collectAllDeps(node) {
4472
4626
 
4473
4627
  // src/commands/netframework/findContainingSolutions.ts
4474
4628
  import { readdirSync as readdirSync2, readFileSync as readFileSync20, statSync } from "fs";
4475
- import path18 from "path";
4629
+ import path23 from "path";
4476
4630
  function findSlnFiles(dir, maxDepth, depth = 0) {
4477
4631
  if (depth > maxDepth) return [];
4478
4632
  const results = [];
@@ -4485,7 +4639,7 @@ function findSlnFiles(dir, maxDepth, depth = 0) {
4485
4639
  for (const entry of entries) {
4486
4640
  if (entry.startsWith(".") || entry === "node_modules" || entry === "packages")
4487
4641
  continue;
4488
- const full = path18.join(dir, entry);
4642
+ const full = path23.join(dir, entry);
4489
4643
  try {
4490
4644
  const stat = statSync(full);
4491
4645
  if (stat.isFile() && entry.endsWith(".sln")) {
@@ -4499,8 +4653,8 @@ function findSlnFiles(dir, maxDepth, depth = 0) {
4499
4653
  return results;
4500
4654
  }
4501
4655
  function findContainingSolutions(csprojPath, repoRoot) {
4502
- const csprojAbs = path18.resolve(csprojPath);
4503
- const csprojBasename = path18.basename(csprojAbs);
4656
+ const csprojAbs = path23.resolve(csprojPath);
4657
+ const csprojBasename = path23.basename(csprojAbs);
4504
4658
  const slnFiles = findSlnFiles(repoRoot, 3);
4505
4659
  const matches = [];
4506
4660
  const pattern2 = new RegExp(`[\\\\"/]${escapeRegex(csprojBasename)}"`);
@@ -4508,7 +4662,7 @@ function findContainingSolutions(csprojPath, repoRoot) {
4508
4662
  try {
4509
4663
  const content = readFileSync20(sln, "utf-8");
4510
4664
  if (pattern2.test(content)) {
4511
- matches.push(path18.relative(repoRoot, sln));
4665
+ matches.push(path23.relative(repoRoot, sln));
4512
4666
  }
4513
4667
  } catch {
4514
4668
  }
@@ -4520,30 +4674,30 @@ function escapeRegex(s) {
4520
4674
  }
4521
4675
 
4522
4676
  // src/commands/netframework/printTree.ts
4523
- import chalk46 from "chalk";
4677
+ import chalk48 from "chalk";
4524
4678
  function printNodes(nodes, prefix2) {
4525
4679
  for (let i = 0; i < nodes.length; i++) {
4526
4680
  const isLast = i === nodes.length - 1;
4527
4681
  const connector = isLast ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
4528
4682
  const childPrefix = isLast ? " " : "\u2502 ";
4529
4683
  const isMissing = nodes[i].relativePath.startsWith("[MISSING]");
4530
- const label2 = isMissing ? chalk46.red(nodes[i].relativePath) : nodes[i].relativePath;
4684
+ const label2 = isMissing ? chalk48.red(nodes[i].relativePath) : nodes[i].relativePath;
4531
4685
  console.log(`${prefix2}${connector}${label2}`);
4532
4686
  printNodes(nodes[i].children, prefix2 + childPrefix);
4533
4687
  }
4534
4688
  }
4535
4689
  function printTree(tree, totalCount, solutions) {
4536
- console.log(chalk46.bold("\nProject Dependency Tree"));
4537
- console.log(chalk46.cyan(tree.relativePath));
4690
+ console.log(chalk48.bold("\nProject Dependency Tree"));
4691
+ console.log(chalk48.cyan(tree.relativePath));
4538
4692
  printNodes(tree.children, "");
4539
- console.log(chalk46.dim(`
4693
+ console.log(chalk48.dim(`
4540
4694
  ${totalCount} projects total (including root)`));
4541
- console.log(chalk46.bold("\nSolution Membership"));
4695
+ console.log(chalk48.bold("\nSolution Membership"));
4542
4696
  if (solutions.length === 0) {
4543
- console.log(chalk46.yellow(" Not found in any .sln"));
4697
+ console.log(chalk48.yellow(" Not found in any .sln"));
4544
4698
  } else {
4545
4699
  for (const sln of solutions) {
4546
- console.log(` ${chalk46.green(sln)}`);
4700
+ console.log(` ${chalk48.green(sln)}`);
4547
4701
  }
4548
4702
  }
4549
4703
  console.log();
@@ -4571,33 +4725,33 @@ function printJson(tree, totalCount, solutions) {
4571
4725
 
4572
4726
  // src/commands/netframework/resolveCsproj.ts
4573
4727
  import { existsSync as existsSync22 } from "fs";
4574
- import path20 from "path";
4575
- import chalk47 from "chalk";
4728
+ import path25 from "path";
4729
+ import chalk49 from "chalk";
4576
4730
 
4577
4731
  // src/commands/netframework/findRepoRoot.ts
4578
4732
  import { existsSync as existsSync21 } from "fs";
4579
- import path19 from "path";
4733
+ import path24 from "path";
4580
4734
  function findRepoRoot(dir) {
4581
4735
  let current = dir;
4582
- while (current !== path19.dirname(current)) {
4583
- if (existsSync21(path19.join(current, ".git"))) {
4736
+ while (current !== path24.dirname(current)) {
4737
+ if (existsSync21(path24.join(current, ".git"))) {
4584
4738
  return current;
4585
4739
  }
4586
- current = path19.dirname(current);
4740
+ current = path24.dirname(current);
4587
4741
  }
4588
4742
  return null;
4589
4743
  }
4590
4744
 
4591
4745
  // src/commands/netframework/resolveCsproj.ts
4592
4746
  function resolveCsproj(csprojPath) {
4593
- const resolved = path20.resolve(csprojPath);
4747
+ const resolved = path25.resolve(csprojPath);
4594
4748
  if (!existsSync22(resolved)) {
4595
- console.error(chalk47.red(`File not found: ${resolved}`));
4749
+ console.error(chalk49.red(`File not found: ${resolved}`));
4596
4750
  process.exit(1);
4597
4751
  }
4598
- const repoRoot = findRepoRoot(path20.dirname(resolved));
4752
+ const repoRoot = findRepoRoot(path25.dirname(resolved));
4599
4753
  if (!repoRoot) {
4600
- console.error(chalk47.red("Could not find git repository root"));
4754
+ console.error(chalk49.red("Could not find git repository root"));
4601
4755
  process.exit(1);
4602
4756
  }
4603
4757
  return { resolved, repoRoot };
@@ -4617,12 +4771,12 @@ async function deps(csprojPath, options2) {
4617
4771
  }
4618
4772
 
4619
4773
  // src/commands/netframework/inSln.ts
4620
- import chalk48 from "chalk";
4774
+ import chalk50 from "chalk";
4621
4775
  async function inSln(csprojPath) {
4622
4776
  const { resolved, repoRoot } = resolveCsproj(csprojPath);
4623
4777
  const solutions = findContainingSolutions(resolved, repoRoot);
4624
4778
  if (solutions.length === 0) {
4625
- console.log(chalk48.yellow("Not found in any .sln file"));
4779
+ console.log(chalk50.yellow("Not found in any .sln file"));
4626
4780
  process.exit(1);
4627
4781
  }
4628
4782
  for (const sln of solutions) {
@@ -4638,7 +4792,7 @@ function registerNetframework(program2) {
4638
4792
  }
4639
4793
 
4640
4794
  // src/commands/news/add/index.ts
4641
- import chalk49 from "chalk";
4795
+ import chalk51 from "chalk";
4642
4796
  import enquirer5 from "enquirer";
4643
4797
  async function add2(url) {
4644
4798
  if (!url) {
@@ -4661,17 +4815,17 @@ async function add2(url) {
4661
4815
  const news = config.news ?? {};
4662
4816
  const feeds = news.feeds ?? [];
4663
4817
  if (feeds.includes(url)) {
4664
- console.log(chalk49.yellow("Feed already exists in config"));
4818
+ console.log(chalk51.yellow("Feed already exists in config"));
4665
4819
  return;
4666
4820
  }
4667
4821
  feeds.push(url);
4668
4822
  config.news = { ...news, feeds };
4669
4823
  saveGlobalConfig(config);
4670
- console.log(chalk49.green(`Added feed: ${url}`));
4824
+ console.log(chalk51.green(`Added feed: ${url}`));
4671
4825
  }
4672
4826
 
4673
4827
  // src/commands/news/web/handleRequest.ts
4674
- import chalk50 from "chalk";
4828
+ import chalk52 from "chalk";
4675
4829
 
4676
4830
  // src/commands/news/web/shared.ts
4677
4831
  import { decodeHTML } from "entities";
@@ -4807,17 +4961,17 @@ function prefetch() {
4807
4961
  const config = loadConfig();
4808
4962
  const total = config.news.feeds.length;
4809
4963
  if (total === 0) return;
4810
- process.stdout.write(chalk50.dim(`Fetching ${total} feed(s)\u2026 `));
4964
+ process.stdout.write(chalk52.dim(`Fetching ${total} feed(s)\u2026 `));
4811
4965
  prefetchPromise = fetchFeeds(config.news.feeds, (done2, t) => {
4812
4966
  const width = 20;
4813
4967
  const filled = Math.round(done2 / t * width);
4814
4968
  const bar = `${"\u2588".repeat(filled)}${"\u2591".repeat(width - filled)}`;
4815
4969
  process.stdout.write(
4816
- `\r${chalk50.dim(`Fetching feeds ${bar} ${done2}/${t}`)}`
4970
+ `\r${chalk52.dim(`Fetching feeds ${bar} ${done2}/${t}`)}`
4817
4971
  );
4818
4972
  }).then((items) => {
4819
4973
  process.stdout.write(
4820
- `\r${chalk50.green(`Fetched ${items.length} items from ${total} feed(s)`)}
4974
+ `\r${chalk52.green(`Fetched ${items.length} items from ${total} feed(s)`)}
4821
4975
  `
4822
4976
  );
4823
4977
  cachedItems = items;
@@ -4932,7 +5086,7 @@ function validateLine(line) {
4932
5086
  process.exit(1);
4933
5087
  }
4934
5088
  }
4935
- function comment(path35, line, body) {
5089
+ function comment(path43, line, body) {
4936
5090
  validateBody(body);
4937
5091
  validateLine(line);
4938
5092
  try {
@@ -4952,7 +5106,7 @@ function comment(path35, line, body) {
4952
5106
  "-f",
4953
5107
  `body=${body}`,
4954
5108
  "-f",
4955
- `path=${path35}`,
5109
+ `path=${path43}`,
4956
5110
  "-F",
4957
5111
  `line=${line}`
4958
5112
  ],
@@ -4961,7 +5115,7 @@ function comment(path35, line, body) {
4961
5115
  if (result.status !== 0) {
4962
5116
  throw new Error(result.stderr || result.stdout);
4963
5117
  }
4964
- console.log(`Added review comment on ${path35}:${line}`);
5118
+ console.log(`Added review comment on ${path43}:${line}`);
4965
5119
  } finally {
4966
5120
  unlinkSync3(queryFile);
4967
5121
  }
@@ -5178,20 +5332,20 @@ function fetchLineComments(org, repo, prNumber, threadInfo) {
5178
5332
  }
5179
5333
 
5180
5334
  // src/commands/prs/listComments/printComments.ts
5181
- import chalk51 from "chalk";
5335
+ import chalk53 from "chalk";
5182
5336
  function formatForHuman(comment2) {
5183
5337
  if (comment2.type === "review") {
5184
- const stateColor = comment2.state === "APPROVED" ? chalk51.green : comment2.state === "CHANGES_REQUESTED" ? chalk51.red : chalk51.yellow;
5338
+ const stateColor = comment2.state === "APPROVED" ? chalk53.green : comment2.state === "CHANGES_REQUESTED" ? chalk53.red : chalk53.yellow;
5185
5339
  return [
5186
- `${chalk51.cyan("Review")} by ${chalk51.bold(comment2.user)} ${stateColor(`[${comment2.state}]`)}`,
5340
+ `${chalk53.cyan("Review")} by ${chalk53.bold(comment2.user)} ${stateColor(`[${comment2.state}]`)}`,
5187
5341
  comment2.body,
5188
5342
  ""
5189
5343
  ].join("\n");
5190
5344
  }
5191
5345
  const location = comment2.line ? `:${comment2.line}` : "";
5192
5346
  return [
5193
- `${chalk51.cyan("Line comment")} by ${chalk51.bold(comment2.user)} on ${chalk51.dim(`${comment2.path}${location}`)}`,
5194
- chalk51.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")),
5195
5349
  comment2.body,
5196
5350
  ""
5197
5351
  ].join("\n");
@@ -5281,13 +5435,13 @@ import { execSync as execSync27 } from "child_process";
5281
5435
  import enquirer6 from "enquirer";
5282
5436
 
5283
5437
  // src/commands/prs/prs/displayPaginated/printPr.ts
5284
- import chalk52 from "chalk";
5438
+ import chalk54 from "chalk";
5285
5439
  var STATUS_MAP = {
5286
- MERGED: (pr) => pr.mergedAt ? { label: chalk52.magenta("merged"), date: pr.mergedAt } : null,
5287
- CLOSED: (pr) => pr.closedAt ? { label: chalk52.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
5288
5442
  };
5289
5443
  function defaultStatus(pr) {
5290
- return { label: chalk52.green("opened"), date: pr.createdAt };
5444
+ return { label: chalk54.green("opened"), date: pr.createdAt };
5291
5445
  }
5292
5446
  function getStatus2(pr) {
5293
5447
  return STATUS_MAP[pr.state]?.(pr) ?? defaultStatus(pr);
@@ -5296,11 +5450,11 @@ function formatDate(dateStr) {
5296
5450
  return new Date(dateStr).toISOString().split("T")[0];
5297
5451
  }
5298
5452
  function formatPrHeader(pr, status2) {
5299
- return `${chalk52.cyan(`#${pr.number}`)} ${pr.title} ${chalk52.dim(`(${pr.author.login},`)} ${status2.label} ${chalk52.dim(`${formatDate(status2.date)})`)}`;
5453
+ return `${chalk54.cyan(`#${pr.number}`)} ${pr.title} ${chalk54.dim(`(${pr.author.login},`)} ${status2.label} ${chalk54.dim(`${formatDate(status2.date)})`)}`;
5300
5454
  }
5301
5455
  function logPrDetails(pr) {
5302
5456
  console.log(
5303
- chalk52.dim(` ${pr.changedFiles.toLocaleString()} files | ${pr.url}`)
5457
+ chalk54.dim(` ${pr.changedFiles.toLocaleString()} files | ${pr.url}`)
5304
5458
  );
5305
5459
  console.log();
5306
5460
  }
@@ -5460,17 +5614,17 @@ function registerPrs(program2) {
5460
5614
  prsCommand.command("wontfix <comment-id> <reason>").description("Reply with reason and resolve thread").action((commentId, reason) => {
5461
5615
  wontfix(Number.parseInt(commentId, 10), reason);
5462
5616
  });
5463
- prsCommand.command("comment <path> <line> <body>").description("Add a line comment to the pending review").action((path35, line, body) => {
5464
- comment(path35, 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);
5465
5619
  });
5466
5620
  }
5467
5621
 
5468
5622
  // src/commands/refactor/check/index.ts
5469
5623
  import { spawn as spawn3 } from "child_process";
5470
- import * as path21 from "path";
5624
+ import * as path26 from "path";
5471
5625
 
5472
5626
  // src/commands/refactor/logViolations.ts
5473
- import chalk53 from "chalk";
5627
+ import chalk55 from "chalk";
5474
5628
  var DEFAULT_MAX_LINES = 100;
5475
5629
  function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
5476
5630
  if (violations.length === 0) {
@@ -5479,43 +5633,43 @@ function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
5479
5633
  }
5480
5634
  return;
5481
5635
  }
5482
- console.error(chalk53.red(`
5636
+ console.error(chalk55.red(`
5483
5637
  Refactor check failed:
5484
5638
  `));
5485
- console.error(chalk53.red(` The following files exceed ${maxLines} lines:
5639
+ console.error(chalk55.red(` The following files exceed ${maxLines} lines:
5486
5640
  `));
5487
5641
  for (const violation of violations) {
5488
- console.error(chalk53.red(` ${violation.file} (${violation.lines} lines)`));
5642
+ console.error(chalk55.red(` ${violation.file} (${violation.lines} lines)`));
5489
5643
  }
5490
5644
  console.error(
5491
- chalk53.yellow(
5645
+ chalk55.yellow(
5492
5646
  `
5493
5647
  Each file needs to be sensibly refactored, or if there is no sensible
5494
5648
  way to refactor it, ignore it with:
5495
5649
  `
5496
5650
  )
5497
5651
  );
5498
- console.error(chalk53.gray(` assist refactor ignore <file>
5652
+ console.error(chalk55.gray(` assist refactor ignore <file>
5499
5653
  `));
5500
5654
  if (process.env.CLAUDECODE) {
5501
- console.error(chalk53.cyan(`
5655
+ console.error(chalk55.cyan(`
5502
5656
  ## Extracting Code to New Files
5503
5657
  `));
5504
5658
  console.error(
5505
- chalk53.cyan(
5659
+ chalk55.cyan(
5506
5660
  ` When extracting logic from one file to another, consider where the extracted code belongs:
5507
5661
  `
5508
5662
  )
5509
5663
  );
5510
5664
  console.error(
5511
- chalk53.cyan(
5665
+ chalk55.cyan(
5512
5666
  ` 1. Keep related logic together: If the extracted code is tightly coupled to the
5513
5667
  original file's domain, create a new folder containing both the original and extracted files.
5514
5668
  `
5515
5669
  )
5516
5670
  );
5517
5671
  console.error(
5518
- chalk53.cyan(
5672
+ chalk55.cyan(
5519
5673
  ` 2. Share common utilities: If the extracted code can be reused across multiple
5520
5674
  domains, move it to a common/shared folder.
5521
5675
  `
@@ -5526,17 +5680,17 @@ Refactor check failed:
5526
5680
 
5527
5681
  // src/commands/refactor/check/getViolations/index.ts
5528
5682
  import { execSync as execSync29 } from "child_process";
5529
- import fs15 from "fs";
5683
+ import fs17 from "fs";
5530
5684
  import { minimatch as minimatch4 } from "minimatch";
5531
5685
 
5532
5686
  // src/commands/refactor/check/getViolations/getIgnoredFiles.ts
5533
- import fs14 from "fs";
5687
+ import fs16 from "fs";
5534
5688
  var REFACTOR_YML_PATH = "refactor.yml";
5535
5689
  function parseRefactorYml() {
5536
- if (!fs14.existsSync(REFACTOR_YML_PATH)) {
5690
+ if (!fs16.existsSync(REFACTOR_YML_PATH)) {
5537
5691
  return [];
5538
5692
  }
5539
- const content = fs14.readFileSync(REFACTOR_YML_PATH, "utf-8");
5693
+ const content = fs16.readFileSync(REFACTOR_YML_PATH, "utf-8");
5540
5694
  const entries = [];
5541
5695
  const lines = content.split("\n");
5542
5696
  let currentEntry = {};
@@ -5566,7 +5720,7 @@ function getIgnoredFiles() {
5566
5720
 
5567
5721
  // src/commands/refactor/check/getViolations/index.ts
5568
5722
  function countLines(filePath) {
5569
- const content = fs15.readFileSync(filePath, "utf-8");
5723
+ const content = fs17.readFileSync(filePath, "utf-8");
5570
5724
  return content.split("\n").length;
5571
5725
  }
5572
5726
  function getGitFiles(options2) {
@@ -5644,7 +5798,7 @@ ${failed.length} verify script(s) failed:`);
5644
5798
  async function runVerifyQuietly() {
5645
5799
  const result = findPackageJsonWithVerifyScripts(process.cwd());
5646
5800
  if (!result) return true;
5647
- const packageDir = path21.dirname(result.packageJsonPath);
5801
+ const packageDir = path26.dirname(result.packageJsonPath);
5648
5802
  const results = await Promise.all(
5649
5803
  result.verifyScripts.map((script) => runScript(script, packageDir))
5650
5804
  );
@@ -5670,39 +5824,147 @@ async function check(pattern2, options2) {
5670
5824
  }
5671
5825
 
5672
5826
  // src/commands/refactor/ignore.ts
5673
- import fs16 from "fs";
5674
- import chalk54 from "chalk";
5827
+ import fs18 from "fs";
5828
+ import chalk56 from "chalk";
5675
5829
  var REFACTOR_YML_PATH2 = "refactor.yml";
5676
5830
  function ignore(file) {
5677
- if (!fs16.existsSync(file)) {
5678
- console.error(chalk54.red(`Error: File does not exist: ${file}`));
5831
+ if (!fs18.existsSync(file)) {
5832
+ console.error(chalk56.red(`Error: File does not exist: ${file}`));
5679
5833
  process.exit(1);
5680
5834
  }
5681
- const content = fs16.readFileSync(file, "utf-8");
5835
+ const content = fs18.readFileSync(file, "utf-8");
5682
5836
  const lineCount = content.split("\n").length;
5683
5837
  const maxLines = lineCount + 10;
5684
5838
  const entry = `- file: ${file}
5685
5839
  maxLines: ${maxLines}
5686
5840
  `;
5687
- if (fs16.existsSync(REFACTOR_YML_PATH2)) {
5688
- const existing = fs16.readFileSync(REFACTOR_YML_PATH2, "utf-8");
5689
- 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);
5690
5844
  } else {
5691
- fs16.writeFileSync(REFACTOR_YML_PATH2, entry);
5845
+ fs18.writeFileSync(REFACTOR_YML_PATH2, entry);
5692
5846
  }
5693
5847
  console.log(
5694
- chalk54.green(
5848
+ chalk56.green(
5695
5849
  `Added ${file} to refactor ignore list (max ${maxLines} lines)`
5696
5850
  )
5697
5851
  );
5698
5852
  }
5699
5853
 
5700
- // src/commands/refactor/restructure/index.ts
5701
- import path30 from "path";
5854
+ // src/commands/refactor/rename/index.ts
5855
+ import path27 from "path";
5702
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";
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";
5703
5965
 
5704
5966
  // src/commands/refactor/restructure/buildImportGraph/index.ts
5705
- import path22 from "path";
5967
+ import path30 from "path";
5706
5968
  import ts7 from "typescript";
5707
5969
 
5708
5970
  // src/commands/refactor/restructure/buildImportGraph/getImportSpecifiers.ts
@@ -5729,7 +5991,7 @@ function loadParsedConfig(tsConfigPath) {
5729
5991
  return ts7.parseJsonConfigFileContent(
5730
5992
  configFile.config,
5731
5993
  ts7.sys,
5732
- path22.dirname(tsConfigPath)
5994
+ path30.dirname(tsConfigPath)
5733
5995
  );
5734
5996
  }
5735
5997
  function addToSetMap(map, key, value) {
@@ -5745,7 +6007,7 @@ function resolveImport(specifier, filePath, options2) {
5745
6007
  const resolved = ts7.resolveModuleName(specifier, filePath, options2, ts7.sys);
5746
6008
  const resolvedPath = resolved.resolvedModule?.resolvedFileName;
5747
6009
  if (!resolvedPath || resolvedPath.includes("node_modules")) return null;
5748
- return path22.resolve(resolvedPath);
6010
+ return path30.resolve(resolvedPath);
5749
6011
  }
5750
6012
  function buildImportGraph(candidateFiles, tsConfigPath) {
5751
6013
  const parsed = loadParsedConfig(tsConfigPath);
@@ -5754,7 +6016,7 @@ function buildImportGraph(candidateFiles, tsConfigPath) {
5754
6016
  const importedBy = /* @__PURE__ */ new Map();
5755
6017
  const imports = /* @__PURE__ */ new Map();
5756
6018
  for (const sourceFile of program2.getSourceFiles()) {
5757
- const filePath = path22.resolve(sourceFile.fileName);
6019
+ const filePath = path30.resolve(sourceFile.fileName);
5758
6020
  if (filePath.includes("node_modules")) continue;
5759
6021
  for (const specifier of getImportSpecifiers(sourceFile)) {
5760
6022
  const absTarget = resolveImport(specifier, filePath, parsed.options);
@@ -5768,12 +6030,12 @@ function buildImportGraph(candidateFiles, tsConfigPath) {
5768
6030
  }
5769
6031
 
5770
6032
  // src/commands/refactor/restructure/clusterDirectories.ts
5771
- import path23 from "path";
6033
+ import path31 from "path";
5772
6034
  function clusterDirectories(graph) {
5773
6035
  const dirImportedBy = /* @__PURE__ */ new Map();
5774
6036
  for (const edge of graph.edges) {
5775
- const sourceDir = path23.dirname(edge.source);
5776
- const targetDir = path23.dirname(edge.target);
6037
+ const sourceDir = path31.dirname(edge.source);
6038
+ const targetDir = path31.dirname(edge.target);
5777
6039
  if (sourceDir === targetDir) continue;
5778
6040
  if (!graph.files.has(edge.target)) continue;
5779
6041
  const existing = dirImportedBy.get(targetDir) ?? /* @__PURE__ */ new Set();
@@ -5801,20 +6063,20 @@ function clusterDirectories(graph) {
5801
6063
  return clusters;
5802
6064
  }
5803
6065
  function isAncestor(ancestor, descendant) {
5804
- const rel = path23.relative(ancestor, descendant);
6066
+ const rel = path31.relative(ancestor, descendant);
5805
6067
  return !rel.startsWith("..") && rel !== "";
5806
6068
  }
5807
6069
 
5808
6070
  // src/commands/refactor/restructure/clusterFiles.ts
5809
- import path24 from "path";
6071
+ import path32 from "path";
5810
6072
  function findRootParent(file, importedBy, visited) {
5811
6073
  const importers = importedBy.get(file);
5812
6074
  if (!importers || importers.size !== 1) return file;
5813
6075
  const parent = [...importers][0];
5814
- const parentDir = path24.dirname(parent);
5815
- const fileDir = path24.dirname(file);
6076
+ const parentDir = path32.dirname(parent);
6077
+ const fileDir = path32.dirname(file);
5816
6078
  if (parentDir !== fileDir) return file;
5817
- if (path24.basename(parent, path24.extname(parent)) === "index") return file;
6079
+ if (path32.basename(parent, path32.extname(parent)) === "index") return file;
5818
6080
  if (visited.has(parent)) return file;
5819
6081
  visited.add(parent);
5820
6082
  return findRootParent(parent, importedBy, visited);
@@ -5822,16 +6084,16 @@ function findRootParent(file, importedBy, visited) {
5822
6084
  function clusterFiles(graph) {
5823
6085
  const clusters = /* @__PURE__ */ new Map();
5824
6086
  for (const file of graph.files) {
5825
- const basename7 = path24.basename(file, path24.extname(file));
6087
+ const basename7 = path32.basename(file, path32.extname(file));
5826
6088
  if (basename7 === "index") continue;
5827
6089
  const importers = graph.importedBy.get(file);
5828
6090
  if (!importers || importers.size !== 1) continue;
5829
6091
  const parent = [...importers][0];
5830
6092
  if (!graph.files.has(parent)) continue;
5831
- const parentDir = path24.dirname(parent);
5832
- const fileDir = path24.dirname(file);
6093
+ const parentDir = path32.dirname(parent);
6094
+ const fileDir = path32.dirname(file);
5833
6095
  if (parentDir !== fileDir) continue;
5834
- const parentBasename = path24.basename(parent, path24.extname(parent));
6096
+ const parentBasename = path32.basename(parent, path32.extname(parent));
5835
6097
  if (parentBasename === "index") continue;
5836
6098
  const root = findRootParent(parent, graph.importedBy, /* @__PURE__ */ new Set([file]));
5837
6099
  if (!root || root === file) continue;
@@ -5843,10 +6105,10 @@ function clusterFiles(graph) {
5843
6105
  }
5844
6106
 
5845
6107
  // src/commands/refactor/restructure/computeRewrites/index.ts
5846
- import path25 from "path";
6108
+ import path33 from "path";
5847
6109
 
5848
6110
  // src/commands/refactor/restructure/computeRewrites/applyRewrites.ts
5849
- import fs17 from "fs";
6111
+ import fs19 from "fs";
5850
6112
  function getOrCreateList(map, key) {
5851
6113
  const list4 = map.get(key) ?? [];
5852
6114
  if (!map.has(key)) map.set(key, list4);
@@ -5865,7 +6127,7 @@ function rewriteSpecifier(content, oldSpecifier, newSpecifier) {
5865
6127
  return content.replace(pattern2, `$1${newSpecifier}$2`);
5866
6128
  }
5867
6129
  function applyFileRewrites(file, fileRewrites) {
5868
- let content = fs17.readFileSync(file, "utf-8");
6130
+ let content = fs19.readFileSync(file, "utf-8");
5869
6131
  for (const { oldSpecifier, newSpecifier } of fileRewrites) {
5870
6132
  content = rewriteSpecifier(content, oldSpecifier, newSpecifier);
5871
6133
  }
@@ -5897,7 +6159,7 @@ function normalizeSpecifier(rel) {
5897
6159
  );
5898
6160
  }
5899
6161
  function computeSpecifier(fromFile, toFile) {
5900
- return normalizeSpecifier(path25.relative(path25.dirname(fromFile), toFile));
6162
+ return normalizeSpecifier(path33.relative(path33.dirname(fromFile), toFile));
5901
6163
  }
5902
6164
  function isAffected(edge, moveMap) {
5903
6165
  return moveMap.has(edge.target) || moveMap.has(edge.source);
@@ -5941,51 +6203,51 @@ function computeRewrites(moves, edges, allProjectFiles) {
5941
6203
  }
5942
6204
 
5943
6205
  // src/commands/refactor/restructure/displayPlan.ts
5944
- import path26 from "path";
5945
- import chalk55 from "chalk";
6206
+ import path34 from "path";
6207
+ import chalk59 from "chalk";
5946
6208
  function relPath(filePath) {
5947
- return path26.relative(process.cwd(), filePath);
6209
+ return path34.relative(process.cwd(), filePath);
5948
6210
  }
5949
6211
  function displayMoves(plan) {
5950
6212
  if (plan.moves.length === 0) return;
5951
- console.log(chalk55.bold("\nFile moves:"));
6213
+ console.log(chalk59.bold("\nFile moves:"));
5952
6214
  for (const move of plan.moves) {
5953
6215
  console.log(
5954
- ` ${chalk55.red(relPath(move.from))} \u2192 ${chalk55.green(relPath(move.to))}`
6216
+ ` ${chalk59.red(relPath(move.from))} \u2192 ${chalk59.green(relPath(move.to))}`
5955
6217
  );
5956
- console.log(chalk55.dim(` ${move.reason}`));
6218
+ console.log(chalk59.dim(` ${move.reason}`));
5957
6219
  }
5958
6220
  }
5959
6221
  function displayRewrites(rewrites) {
5960
6222
  if (rewrites.length === 0) return;
5961
6223
  const affectedFiles = new Set(rewrites.map((r) => r.file));
5962
- console.log(chalk55.bold(`
6224
+ console.log(chalk59.bold(`
5963
6225
  Import rewrites (${affectedFiles.size} files):`));
5964
6226
  for (const file of affectedFiles) {
5965
- console.log(` ${chalk55.cyan(relPath(file))}:`);
6227
+ console.log(` ${chalk59.cyan(relPath(file))}:`);
5966
6228
  for (const { oldSpecifier, newSpecifier } of rewrites.filter(
5967
6229
  (r) => r.file === file
5968
6230
  )) {
5969
6231
  console.log(
5970
- ` ${chalk55.red(`"${oldSpecifier}"`)} \u2192 ${chalk55.green(`"${newSpecifier}"`)}`
6232
+ ` ${chalk59.red(`"${oldSpecifier}"`)} \u2192 ${chalk59.green(`"${newSpecifier}"`)}`
5971
6233
  );
5972
6234
  }
5973
6235
  }
5974
6236
  }
5975
6237
  function displayPlan(plan) {
5976
6238
  if (plan.warnings.length > 0) {
5977
- console.log(chalk55.yellow("\nWarnings:"));
5978
- for (const w of plan.warnings) console.log(chalk55.yellow(` ${w}`));
6239
+ console.log(chalk59.yellow("\nWarnings:"));
6240
+ for (const w of plan.warnings) console.log(chalk59.yellow(` ${w}`));
5979
6241
  }
5980
6242
  if (plan.newDirectories.length > 0) {
5981
- console.log(chalk55.bold("\nNew directories:"));
6243
+ console.log(chalk59.bold("\nNew directories:"));
5982
6244
  for (const dir of plan.newDirectories)
5983
- console.log(chalk55.green(` ${dir}/`));
6245
+ console.log(chalk59.green(` ${dir}/`));
5984
6246
  }
5985
6247
  displayMoves(plan);
5986
6248
  displayRewrites(plan.rewrites);
5987
6249
  console.log(
5988
- chalk55.dim(
6250
+ chalk59.dim(
5989
6251
  `
5990
6252
  Summary: ${plan.moves.length} file(s) moved, ${plan.rewrites.length} imports rewritten`
5991
6253
  )
@@ -5993,45 +6255,45 @@ Summary: ${plan.moves.length} file(s) moved, ${plan.rewrites.length} imports rew
5993
6255
  }
5994
6256
 
5995
6257
  // src/commands/refactor/restructure/executePlan.ts
5996
- import fs18 from "fs";
5997
- import path27 from "path";
5998
- import chalk56 from "chalk";
6258
+ import fs20 from "fs";
6259
+ import path35 from "path";
6260
+ import chalk60 from "chalk";
5999
6261
  function executePlan(plan) {
6000
6262
  const updatedContents = applyRewrites(plan.rewrites);
6001
6263
  for (const [file, content] of updatedContents) {
6002
- fs18.writeFileSync(file, content, "utf-8");
6264
+ fs20.writeFileSync(file, content, "utf-8");
6003
6265
  console.log(
6004
- chalk56.cyan(` Rewrote imports in ${path27.relative(process.cwd(), file)}`)
6266
+ chalk60.cyan(` Rewrote imports in ${path35.relative(process.cwd(), file)}`)
6005
6267
  );
6006
6268
  }
6007
6269
  for (const dir of plan.newDirectories) {
6008
- fs18.mkdirSync(dir, { recursive: true });
6009
- console.log(chalk56.green(` Created ${path27.relative(process.cwd(), dir)}/`));
6270
+ fs20.mkdirSync(dir, { recursive: true });
6271
+ console.log(chalk60.green(` Created ${path35.relative(process.cwd(), dir)}/`));
6010
6272
  }
6011
6273
  for (const move of plan.moves) {
6012
- const targetDir = path27.dirname(move.to);
6013
- if (!fs18.existsSync(targetDir)) {
6014
- fs18.mkdirSync(targetDir, { recursive: true });
6274
+ const targetDir = path35.dirname(move.to);
6275
+ if (!fs20.existsSync(targetDir)) {
6276
+ fs20.mkdirSync(targetDir, { recursive: true });
6015
6277
  }
6016
- fs18.renameSync(move.from, move.to);
6278
+ fs20.renameSync(move.from, move.to);
6017
6279
  console.log(
6018
- chalk56.white(
6019
- ` Moved ${path27.relative(process.cwd(), move.from)} \u2192 ${path27.relative(process.cwd(), move.to)}`
6280
+ chalk60.white(
6281
+ ` Moved ${path35.relative(process.cwd(), move.from)} \u2192 ${path35.relative(process.cwd(), move.to)}`
6020
6282
  )
6021
6283
  );
6022
6284
  }
6023
- removeEmptyDirectories(plan.moves.map((m) => path27.dirname(m.from)));
6285
+ removeEmptyDirectories(plan.moves.map((m) => path35.dirname(m.from)));
6024
6286
  }
6025
6287
  function removeEmptyDirectories(dirs) {
6026
6288
  const unique = [...new Set(dirs)];
6027
6289
  for (const dir of unique) {
6028
- if (!fs18.existsSync(dir)) continue;
6029
- const entries = fs18.readdirSync(dir);
6290
+ if (!fs20.existsSync(dir)) continue;
6291
+ const entries = fs20.readdirSync(dir);
6030
6292
  if (entries.length === 0) {
6031
- fs18.rmdirSync(dir);
6293
+ fs20.rmdirSync(dir);
6032
6294
  console.log(
6033
- chalk56.dim(
6034
- ` Removed empty directory ${path27.relative(process.cwd(), dir)}`
6295
+ chalk60.dim(
6296
+ ` Removed empty directory ${path35.relative(process.cwd(), dir)}`
6035
6297
  )
6036
6298
  );
6037
6299
  }
@@ -6039,36 +6301,36 @@ function removeEmptyDirectories(dirs) {
6039
6301
  }
6040
6302
 
6041
6303
  // src/commands/refactor/restructure/planFileMoves/index.ts
6042
- import fs20 from "fs";
6043
- import path29 from "path";
6304
+ import fs22 from "fs";
6305
+ import path37 from "path";
6044
6306
 
6045
6307
  // src/commands/refactor/restructure/planFileMoves/planDirectoryMoves.ts
6046
- import fs19 from "fs";
6047
- import path28 from "path";
6308
+ import fs21 from "fs";
6309
+ import path36 from "path";
6048
6310
  function collectEntry(results, dir, entry) {
6049
- const full = path28.join(dir, entry.name);
6311
+ const full = path36.join(dir, entry.name);
6050
6312
  const items = entry.isDirectory() ? listFilesRecursive(full) : [full];
6051
6313
  results.push(...items);
6052
6314
  }
6053
6315
  function listFilesRecursive(dir) {
6054
- if (!fs19.existsSync(dir)) return [];
6316
+ if (!fs21.existsSync(dir)) return [];
6055
6317
  const results = [];
6056
- for (const entry of fs19.readdirSync(dir, { withFileTypes: true })) {
6318
+ for (const entry of fs21.readdirSync(dir, { withFileTypes: true })) {
6057
6319
  collectEntry(results, dir, entry);
6058
6320
  }
6059
6321
  return results;
6060
6322
  }
6061
6323
  function addDirectoryFileMoves(moves, childDir, newLocation, reason) {
6062
6324
  for (const file of listFilesRecursive(childDir)) {
6063
- const rel = path28.relative(childDir, file);
6064
- moves.push({ from: file, to: path28.join(newLocation, rel), reason });
6325
+ const rel = path36.relative(childDir, file);
6326
+ moves.push({ from: file, to: path36.join(newLocation, rel), reason });
6065
6327
  }
6066
6328
  }
6067
6329
  function resolveChildDest(parentDir, childDir) {
6068
- return path28.join(parentDir, path28.basename(childDir));
6330
+ return path36.join(parentDir, path36.basename(childDir));
6069
6331
  }
6070
6332
  function childMoveReason(parentDir) {
6071
- return `Directory only imported from ${path28.basename(parentDir)}/`;
6333
+ return `Directory only imported from ${path36.basename(parentDir)}/`;
6072
6334
  }
6073
6335
  function registerDirectoryMove(result, childDir, dest, parentDir) {
6074
6336
  result.directories.push(dest);
@@ -6096,7 +6358,7 @@ function emptyResult() {
6096
6358
  return { moves: [], directories: [], warnings: [] };
6097
6359
  }
6098
6360
  function childMoveData(child, newDir, parentBase) {
6099
- const to = path29.join(newDir, path29.basename(child));
6361
+ const to = path37.join(newDir, path37.basename(child));
6100
6362
  return { from: child, to, reason: `Only imported by ${parentBase}` };
6101
6363
  }
6102
6364
  function addChildMoves(moves, children, newDir, parentBase) {
@@ -6104,20 +6366,20 @@ function addChildMoves(moves, children, newDir, parentBase) {
6104
6366
  moves.push(childMoveData(child, newDir, parentBase));
6105
6367
  }
6106
6368
  function checkDirConflict(result, label2, dir) {
6107
- if (!fs20.existsSync(dir)) return false;
6369
+ if (!fs22.existsSync(dir)) return false;
6108
6370
  result.warnings.push(`Skipping ${label2}: directory ${dir} already exists`);
6109
6371
  return true;
6110
6372
  }
6111
6373
  function getBaseName(filePath) {
6112
- return path29.basename(filePath, path29.extname(filePath));
6374
+ return path37.basename(filePath, path37.extname(filePath));
6113
6375
  }
6114
6376
  function resolveClusterDir(parent) {
6115
- return path29.join(path29.dirname(parent), getBaseName(parent));
6377
+ return path37.join(path37.dirname(parent), getBaseName(parent));
6116
6378
  }
6117
6379
  function createParentMove(parent, newDir) {
6118
6380
  return {
6119
6381
  from: parent,
6120
- to: path29.join(newDir, `index${path29.extname(parent)}`),
6382
+ to: path37.join(newDir, `index${path37.extname(parent)}`),
6121
6383
  reason: `Main module of new ${getBaseName(parent)}/ directory`
6122
6384
  };
6123
6385
  }
@@ -6141,7 +6403,7 @@ function planFileMoves(clusters) {
6141
6403
 
6142
6404
  // src/commands/refactor/restructure/index.ts
6143
6405
  function buildPlan(candidateFiles, tsConfigPath) {
6144
- const candidates = new Set(candidateFiles.map((f) => path30.resolve(f)));
6406
+ const candidates = new Set(candidateFiles.map((f) => path38.resolve(f)));
6145
6407
  const graph = buildImportGraph(candidates, tsConfigPath);
6146
6408
  const allProjectFiles = /* @__PURE__ */ new Set([
6147
6409
  ...graph.importedBy.keys(),
@@ -6161,22 +6423,22 @@ async function restructure(pattern2, options2 = {}) {
6161
6423
  const targetPattern = pattern2 ?? "src";
6162
6424
  const files = findSourceFiles2(targetPattern);
6163
6425
  if (files.length === 0) {
6164
- console.log(chalk57.yellow("No files found matching pattern"));
6426
+ console.log(chalk61.yellow("No files found matching pattern"));
6165
6427
  return;
6166
6428
  }
6167
- const tsConfigPath = path30.resolve("tsconfig.json");
6429
+ const tsConfigPath = path38.resolve("tsconfig.json");
6168
6430
  const plan = buildPlan(files, tsConfigPath);
6169
6431
  if (plan.moves.length === 0) {
6170
- console.log(chalk57.green("No restructuring needed"));
6432
+ console.log(chalk61.green("No restructuring needed"));
6171
6433
  return;
6172
6434
  }
6173
6435
  displayPlan(plan);
6174
6436
  if (options2.apply) {
6175
- console.log(chalk57.bold("\nApplying changes..."));
6437
+ console.log(chalk61.bold("\nApplying changes..."));
6176
6438
  executePlan(plan);
6177
- console.log(chalk57.green("\nRestructuring complete"));
6439
+ console.log(chalk61.green("\nRestructuring complete"));
6178
6440
  } else {
6179
- console.log(chalk57.dim("\nDry run. Use --apply to execute."));
6441
+ console.log(chalk61.dim("\nDry run. Use --apply to execute."));
6180
6442
  }
6181
6443
  }
6182
6444
 
@@ -6189,6 +6451,11 @@ function registerRefactor(program2) {
6189
6451
  Number.parseInt
6190
6452
  ).action(check);
6191
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);
6192
6459
  refactorCommand.command("restructure [pattern]").description(
6193
6460
  "Analyze import graph and restructure tightly-coupled files into nested directories"
6194
6461
  ).option("--apply", "Execute the restructuring (default: dry-run)").option(
@@ -6315,7 +6582,7 @@ async function configure() {
6315
6582
  import { existsSync as existsSync27 } from "fs";
6316
6583
 
6317
6584
  // src/commands/transcript/format/fixInvalidDatePrefixes/index.ts
6318
- import { dirname as dirname15, join as join24 } from "path";
6585
+ import { dirname as dirname16, join as join24 } from "path";
6319
6586
 
6320
6587
  // src/commands/transcript/format/fixInvalidDatePrefixes/promptForDateFix.ts
6321
6588
  import { renameSync } from "fs";
@@ -6365,11 +6632,11 @@ async function fixInvalidDatePrefixes(vttFiles) {
6365
6632
  for (let i = 0; i < vttFiles.length; i++) {
6366
6633
  const vttFile = vttFiles[i];
6367
6634
  if (!isValidDatePrefix(vttFile.filename)) {
6368
- const vttFileDir = dirname15(vttFile.absolutePath);
6635
+ const vttFileDir = dirname16(vttFile.absolutePath);
6369
6636
  const newFilename = await promptForDateFix(vttFile.filename, vttFileDir);
6370
6637
  if (newFilename) {
6371
6638
  const newRelativePath = join24(
6372
- dirname15(vttFile.relativePath),
6639
+ dirname16(vttFile.relativePath),
6373
6640
  newFilename
6374
6641
  );
6375
6642
  vttFiles[i] = {
@@ -6387,7 +6654,7 @@ async function fixInvalidDatePrefixes(vttFiles) {
6387
6654
 
6388
6655
  // src/commands/transcript/format/processVttFile/index.ts
6389
6656
  import { existsSync as existsSync26, mkdirSync as mkdirSync7, readFileSync as readFileSync22, writeFileSync as writeFileSync21 } from "fs";
6390
- import { basename as basename5, dirname as dirname16, join as join25 } from "path";
6657
+ import { basename as basename5, dirname as dirname17, join as join25 } from "path";
6391
6658
 
6392
6659
  // src/commands/transcript/cleanText.ts
6393
6660
  function cleanText(text) {
@@ -6601,7 +6868,7 @@ function resolveOutputDir(relativeDir, transcriptsDir) {
6601
6868
  }
6602
6869
  function buildOutputPaths(vttFile, transcriptsDir) {
6603
6870
  const mdFile = toMdFilename(vttFile.filename);
6604
- const relativeDir = dirname16(vttFile.relativePath);
6871
+ const relativeDir = dirname17(vttFile.relativePath);
6605
6872
  const outputDir = resolveOutputDir(relativeDir, transcriptsDir);
6606
6873
  const outputPath = join25(outputDir, mdFile);
6607
6874
  return { outputDir, outputPath, mdFile, relativeDir };
@@ -6706,7 +6973,7 @@ async function format() {
6706
6973
 
6707
6974
  // src/commands/transcript/summarise/index.ts
6708
6975
  import { existsSync as existsSync29 } from "fs";
6709
- import { basename as basename6, dirname as dirname18, join as join27, relative as relative2 } from "path";
6976
+ import { basename as basename6, dirname as dirname19, join as join27, relative as relative2 } from "path";
6710
6977
 
6711
6978
  // src/commands/transcript/summarise/processStagedFile/index.ts
6712
6979
  import {
@@ -6716,17 +6983,17 @@ import {
6716
6983
  renameSync as renameSync2,
6717
6984
  rmSync
6718
6985
  } from "fs";
6719
- import { dirname as dirname17, join as join26 } from "path";
6986
+ import { dirname as dirname18, join as join26 } from "path";
6720
6987
 
6721
6988
  // src/commands/transcript/summarise/processStagedFile/validateStagedContent.ts
6722
- import chalk58 from "chalk";
6989
+ import chalk62 from "chalk";
6723
6990
  var FULL_TRANSCRIPT_REGEX = /^\[Full Transcript\]\(([^)]+)\)/;
6724
6991
  function validateStagedContent(filename, content) {
6725
6992
  const firstLine = content.split("\n")[0];
6726
6993
  const match = firstLine.match(FULL_TRANSCRIPT_REGEX);
6727
6994
  if (!match) {
6728
6995
  console.error(
6729
- chalk58.red(
6996
+ chalk62.red(
6730
6997
  `Staged file ${filename} missing [Full Transcript](<path>) link on first line.`
6731
6998
  )
6732
6999
  );
@@ -6735,7 +7002,7 @@ function validateStagedContent(filename, content) {
6735
7002
  const contentAfterLink = content.slice(firstLine.length).trim();
6736
7003
  if (!contentAfterLink) {
6737
7004
  console.error(
6738
- chalk58.red(
7005
+ chalk62.red(
6739
7006
  `Staged file ${filename} has no summary content after the transcript link.`
6740
7007
  )
6741
7008
  );
@@ -6770,7 +7037,7 @@ function processStagedFile() {
6770
7037
  process.exit(1);
6771
7038
  }
6772
7039
  const destPath = join26(summaryDir, matchingTranscript.relativePath);
6773
- const destDir = dirname17(destPath);
7040
+ const destDir = dirname18(destPath);
6774
7041
  if (!existsSync28(destDir)) {
6775
7042
  mkdirSync8(destDir, { recursive: true });
6776
7043
  }
@@ -6784,7 +7051,7 @@ function processStagedFile() {
6784
7051
 
6785
7052
  // src/commands/transcript/summarise/index.ts
6786
7053
  function buildRelativeKey(relativePath, baseName) {
6787
- const relDir = dirname18(relativePath);
7054
+ const relDir = dirname19(relativePath);
6788
7055
  return relDir === "." ? baseName : join27(relDir, baseName);
6789
7056
  }
6790
7057
  function buildSummaryIndex(summaryDir) {
@@ -6820,7 +7087,7 @@ function summarise2() {
6820
7087
  const next2 = missing[0];
6821
7088
  const outputFilename = `${getTranscriptBaseName(next2.filename)}.md`;
6822
7089
  const outputPath = join27(STAGING_DIR, outputFilename);
6823
- const summaryFileDir = join27(summaryDir, dirname18(next2.relativePath));
7090
+ const summaryFileDir = join27(summaryDir, dirname19(next2.relativePath));
6824
7091
  const relativeTranscriptPath = encodeURI(
6825
7092
  relative2(summaryFileDir, next2.absolutePath).replace(/\\/g, "/")
6826
7093
  );
@@ -6870,9 +7137,9 @@ import { join as join29 } from "path";
6870
7137
 
6871
7138
  // src/commands/voice/shared.ts
6872
7139
  import { homedir as homedir7 } from "os";
6873
- import { dirname as dirname19, join as join28 } from "path";
7140
+ import { dirname as dirname20, join as join28 } from "path";
6874
7141
  import { fileURLToPath as fileURLToPath6 } from "url";
6875
- var __dirname6 = dirname19(fileURLToPath6(import.meta.url));
7142
+ var __dirname6 = dirname20(fileURLToPath6(import.meta.url));
6876
7143
  var VOICE_DIR = join28(homedir7(), ".assist", "voice");
6877
7144
  var voicePaths = {
6878
7145
  dir: VOICE_DIR,
@@ -7128,7 +7395,7 @@ function registerVoice(program2) {
7128
7395
 
7129
7396
  // src/commands/roam/auth.ts
7130
7397
  import { randomBytes } from "crypto";
7131
- import chalk59 from "chalk";
7398
+ import chalk63 from "chalk";
7132
7399
 
7133
7400
  // src/lib/openBrowser.ts
7134
7401
  import { execSync as execSync31 } from "child_process";
@@ -7303,13 +7570,13 @@ async function auth() {
7303
7570
  saveGlobalConfig(config);
7304
7571
  const state = randomBytes(16).toString("hex");
7305
7572
  console.log(
7306
- chalk59.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:")
7307
7574
  );
7308
- console.log(chalk59.white("http://localhost:14523/callback\n"));
7309
- console.log(chalk59.blue("Opening browser for authorization..."));
7310
- console.log(chalk59.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..."));
7311
7578
  const { code, redirectUri } = await authorizeInBrowser(clientId, state);
7312
- console.log(chalk59.dim("Exchanging code for tokens..."));
7579
+ console.log(chalk63.dim("Exchanging code for tokens..."));
7313
7580
  const tokens = await exchangeToken({
7314
7581
  code,
7315
7582
  clientId,
@@ -7325,7 +7592,7 @@ async function auth() {
7325
7592
  };
7326
7593
  saveGlobalConfig(config);
7327
7594
  console.log(
7328
- chalk59.green("Roam credentials and tokens saved to ~/.assist.yml")
7595
+ chalk63.green("Roam credentials and tokens saved to ~/.assist.yml")
7329
7596
  );
7330
7597
  }
7331
7598
 
@@ -7513,14 +7780,14 @@ function run2(name, args) {
7513
7780
  }
7514
7781
 
7515
7782
  // src/commands/statusLine.ts
7516
- import chalk60 from "chalk";
7783
+ import chalk64 from "chalk";
7517
7784
  function formatNumber(num) {
7518
7785
  return num.toLocaleString("en-US");
7519
7786
  }
7520
7787
  function colorizePercent(pct) {
7521
7788
  const label2 = `${pct}%`;
7522
- if (pct > 80) return chalk60.red(label2);
7523
- if (pct > 40) return chalk60.yellow(label2);
7789
+ if (pct > 80) return chalk64.red(label2);
7790
+ if (pct > 40) return chalk64.yellow(label2);
7524
7791
  return label2;
7525
7792
  }
7526
7793
  async function statusLine() {
@@ -7538,29 +7805,29 @@ async function statusLine() {
7538
7805
  }
7539
7806
 
7540
7807
  // src/commands/sync.ts
7541
- import * as fs23 from "fs";
7808
+ import * as fs25 from "fs";
7542
7809
  import * as os from "os";
7543
- import * as path33 from "path";
7810
+ import * as path41 from "path";
7544
7811
  import { fileURLToPath as fileURLToPath7 } from "url";
7545
7812
 
7546
7813
  // src/commands/sync/syncClaudeMd.ts
7547
- import * as fs21 from "fs";
7548
- import * as path31 from "path";
7549
- import chalk61 from "chalk";
7814
+ import * as fs23 from "fs";
7815
+ import * as path39 from "path";
7816
+ import chalk65 from "chalk";
7550
7817
  async function syncClaudeMd(claudeDir, targetBase) {
7551
- const source = path31.join(claudeDir, "CLAUDE.md");
7552
- const target = path31.join(targetBase, "CLAUDE.md");
7553
- const sourceContent = fs21.readFileSync(source, "utf-8");
7554
- if (fs21.existsSync(target)) {
7555
- 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");
7556
7823
  if (sourceContent !== targetContent) {
7557
7824
  console.log(
7558
- chalk61.yellow("\n\u26A0\uFE0F Warning: CLAUDE.md differs from existing file")
7825
+ chalk65.yellow("\n\u26A0\uFE0F Warning: CLAUDE.md differs from existing file")
7559
7826
  );
7560
7827
  console.log();
7561
7828
  printDiff(targetContent, sourceContent);
7562
7829
  const confirm = await promptConfirm(
7563
- chalk61.red("Overwrite existing CLAUDE.md?"),
7830
+ chalk65.red("Overwrite existing CLAUDE.md?"),
7564
7831
  false
7565
7832
  );
7566
7833
  if (!confirm) {
@@ -7569,21 +7836,21 @@ async function syncClaudeMd(claudeDir, targetBase) {
7569
7836
  }
7570
7837
  }
7571
7838
  }
7572
- fs21.copyFileSync(source, target);
7839
+ fs23.copyFileSync(source, target);
7573
7840
  console.log("Copied CLAUDE.md to ~/.claude/CLAUDE.md");
7574
7841
  }
7575
7842
 
7576
7843
  // src/commands/sync/syncSettings.ts
7577
- import * as fs22 from "fs";
7578
- import * as path32 from "path";
7579
- import chalk62 from "chalk";
7844
+ import * as fs24 from "fs";
7845
+ import * as path40 from "path";
7846
+ import chalk66 from "chalk";
7580
7847
  async function syncSettings(claudeDir, targetBase, options2) {
7581
- const source = path32.join(claudeDir, "settings.json");
7582
- const target = path32.join(targetBase, "settings.json");
7583
- 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");
7584
7851
  const mergedContent = JSON.stringify(JSON.parse(sourceContent), null, " ");
7585
- if (fs22.existsSync(target)) {
7586
- const targetContent = fs22.readFileSync(target, "utf-8");
7852
+ if (fs24.existsSync(target)) {
7853
+ const targetContent = fs24.readFileSync(target, "utf-8");
7587
7854
  const normalizedTarget = JSON.stringify(
7588
7855
  JSON.parse(targetContent),
7589
7856
  null,
@@ -7592,14 +7859,14 @@ async function syncSettings(claudeDir, targetBase, options2) {
7592
7859
  if (mergedContent !== normalizedTarget) {
7593
7860
  if (!options2?.yes) {
7594
7861
  console.log(
7595
- chalk62.yellow(
7862
+ chalk66.yellow(
7596
7863
  "\n\u26A0\uFE0F Warning: settings.json differs from existing file"
7597
7864
  )
7598
7865
  );
7599
7866
  console.log();
7600
7867
  printDiff(targetContent, mergedContent);
7601
7868
  const confirm = await promptConfirm(
7602
- chalk62.red("Overwrite existing settings.json?"),
7869
+ chalk66.red("Overwrite existing settings.json?"),
7603
7870
  false
7604
7871
  );
7605
7872
  if (!confirm) {
@@ -7609,27 +7876,27 @@ async function syncSettings(claudeDir, targetBase, options2) {
7609
7876
  }
7610
7877
  }
7611
7878
  }
7612
- fs22.writeFileSync(target, mergedContent);
7879
+ fs24.writeFileSync(target, mergedContent);
7613
7880
  console.log("Copied settings.json to ~/.claude/settings.json");
7614
7881
  }
7615
7882
 
7616
7883
  // src/commands/sync.ts
7617
7884
  var __filename4 = fileURLToPath7(import.meta.url);
7618
- var __dirname7 = path33.dirname(__filename4);
7885
+ var __dirname7 = path41.dirname(__filename4);
7619
7886
  async function sync(options2) {
7620
- const claudeDir = path33.join(__dirname7, "..", "claude");
7621
- const targetBase = path33.join(os.homedir(), ".claude");
7887
+ const claudeDir = path41.join(__dirname7, "..", "claude");
7888
+ const targetBase = path41.join(os.homedir(), ".claude");
7622
7889
  syncCommands(claudeDir, targetBase);
7623
7890
  await syncSettings(claudeDir, targetBase, { yes: options2?.yes });
7624
7891
  await syncClaudeMd(claudeDir, targetBase);
7625
7892
  }
7626
7893
  function syncCommands(claudeDir, targetBase) {
7627
- const sourceDir = path33.join(claudeDir, "commands");
7628
- const targetDir = path33.join(targetBase, "commands");
7629
- fs23.mkdirSync(targetDir, { recursive: true });
7630
- 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);
7631
7898
  for (const file of files) {
7632
- fs23.copyFileSync(path33.join(sourceDir, file), path33.join(targetDir, file));
7899
+ fs25.copyFileSync(path41.join(sourceDir, file), path41.join(targetDir, file));
7633
7900
  console.log(`Copied ${file} to ${targetDir}`);
7634
7901
  }
7635
7902
  console.log(`Synced ${files.length} command(s) to ~/.claude/commands`);
@@ -7637,15 +7904,15 @@ function syncCommands(claudeDir, targetBase) {
7637
7904
 
7638
7905
  // src/commands/update.ts
7639
7906
  import { execSync as execSync32 } from "child_process";
7640
- import * as path34 from "path";
7907
+ import * as path42 from "path";
7641
7908
  function isGlobalNpmInstall(dir) {
7642
7909
  try {
7643
- const resolved = path34.resolve(dir);
7644
- if (resolved.split(path34.sep).includes("node_modules")) {
7910
+ const resolved = path42.resolve(dir);
7911
+ if (resolved.split(path42.sep).includes("node_modules")) {
7645
7912
  return true;
7646
7913
  }
7647
7914
  const globalPrefix = execSync32("npm prefix -g", { stdio: "pipe" }).toString().trim();
7648
- return resolved.toLowerCase().startsWith(path34.resolve(globalPrefix).toLowerCase());
7915
+ return resolved.toLowerCase().startsWith(path42.resolve(globalPrefix).toLowerCase());
7649
7916
  } catch {
7650
7917
  return false;
7651
7918
  }
@@ -7694,7 +7961,7 @@ runCommand.command("add").description("Add a new run configuration to assist.yml
7694
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'
7695
7962
  ).allowUnknownOption().allowExcessArguments().action(() => add3());
7696
7963
  registerNew(program);
7697
- 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);
7698
7965
  lintCommand.command("init").description("Initialize Biome with standard linter config").action(init);
7699
7966
  var vscodeCommand = program.command("vscode").description("VS Code configuration utilities");
7700
7967
  vscodeCommand.command("init").description("Add VS Code configuration files").action(init3);