@staff0rd/assist 0.48.0 → 0.50.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +2 -1
  2. package/dist/index.js +718 -586
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1,13 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/index.ts
4
- import { execSync as execSync20 } from "child_process";
4
+ import { execSync as execSync22 } from "child_process";
5
5
  import { Command } from "commander";
6
6
 
7
7
  // package.json
8
8
  var package_default = {
9
9
  name: "@staff0rd/assist",
10
- version: "0.48.0",
10
+ version: "0.50.0",
11
11
  type: "module",
12
12
  main: "dist/index.js",
13
13
  bin: {
@@ -222,9 +222,9 @@ function isTraversable(value) {
222
222
  function stepInto(current, key) {
223
223
  return isTraversable(current) ? current[key] : void 0;
224
224
  }
225
- function getNestedValue(obj, path29) {
225
+ function getNestedValue(obj, path30) {
226
226
  let current = obj;
227
- for (const key of path29.split(".")) current = stepInto(current, key);
227
+ for (const key of path30.split(".")) current = stepInto(current, key);
228
228
  return current;
229
229
  }
230
230
  function isPlainObject(val) {
@@ -241,8 +241,8 @@ function buildNestedPath(root, keys) {
241
241
  }
242
242
  return current;
243
243
  }
244
- function setNestedValue(obj, path29, value) {
245
- const keys = path29.split(".");
244
+ function setNestedValue(obj, path30, value) {
245
+ const keys = path30.split(".");
246
246
  const result = { ...obj };
247
247
  buildNestedPath(result, keys)[keys[keys.length - 1]] = value;
248
248
  return result;
@@ -311,17 +311,17 @@ function configList() {
311
311
  }
312
312
 
313
313
  // src/commands/verify/init/index.ts
314
- import chalk14 from "chalk";
314
+ import chalk15 from "chalk";
315
315
 
316
316
  // src/shared/promptMultiselect.ts
317
317
  import chalk3 from "chalk";
318
318
  import enquirer from "enquirer";
319
- async function promptMultiselect(message, options) {
319
+ async function promptMultiselect(message, options2) {
320
320
  const { selected } = await enquirer.prompt({
321
321
  type: "multiselect",
322
322
  name: "selected",
323
323
  message,
324
- choices: options.map((opt) => ({
324
+ choices: options2.map((opt) => ({
325
325
  name: opt.value,
326
326
  message: `${opt.name} - ${chalk3.dim(opt.description)}`
327
327
  })),
@@ -387,7 +387,8 @@ var expectedScripts = {
387
387
  "verify:lint": "biome check --write .",
388
388
  "verify:duplicate-code": "jscpd --format 'typescript,tsx' --exitCode 1 --ignore '**/*.test.*' -r consoleFull src",
389
389
  "verify:test": "vitest run --reporter=dot --silent",
390
- "verify:hardcoded-colors": "assist verify hardcoded-colors"
390
+ "verify:hardcoded-colors": "assist verify hardcoded-colors",
391
+ "verify:maintainability": "assist complexity maintainability ./src --threshold 60"
391
392
  };
392
393
 
393
394
  // src/commands/verify/setup/setupBuild.ts
@@ -460,12 +461,22 @@ async function setupBuild(packageJsonPath, hasVite, hasTypescript) {
460
461
  } else if (hasVite) {
461
462
  command = "vite build --logLevel error";
462
463
  } else {
463
- command = "tsc --noEmit";
464
+ command = "npm run build";
464
465
  }
465
466
  console.log(chalk6.dim(`Using: ${command}`));
466
467
  const pkg = readPackageJson(packageJsonPath);
467
468
  writePackageJson(packageJsonPath, addScript(pkg, "verify:build", command));
468
469
  }
470
+ async function setupTypecheck(packageJsonPath) {
471
+ console.log(chalk6.blue("\nSetting up typecheck verification..."));
472
+ const command = "tsc --noEmit";
473
+ console.log(chalk6.dim(`Using: ${command}`));
474
+ const pkg = readPackageJson(packageJsonPath);
475
+ writePackageJson(
476
+ packageJsonPath,
477
+ addScript(pkg, "verify:typecheck", command)
478
+ );
479
+ }
469
480
 
470
481
  // src/commands/verify/setup/setupDuplicateCode.ts
471
482
  import * as path3 from "path";
@@ -578,8 +589,8 @@ function removeEslintConfigFiles() {
578
589
  }
579
590
 
580
591
  // src/shared/removeEslint/index.ts
581
- function removeEslint(options = {}) {
582
- const removedFromPackageJson = removeEslintFromPackageJson(options);
592
+ function removeEslint(options2 = {}) {
593
+ const removedFromPackageJson = removeEslintFromPackageJson(options2);
583
594
  const removedConfigFiles = removeEslintConfigFiles();
584
595
  if (removedFromPackageJson || removedConfigFiles) {
585
596
  console.log("Running npm install...");
@@ -588,7 +599,7 @@ function removeEslint(options = {}) {
588
599
  }
589
600
  return false;
590
601
  }
591
- function removeEslintFromPackageJson(options) {
602
+ function removeEslintFromPackageJson(options2) {
592
603
  const packageJsonPath = "package.json";
593
604
  if (!existsSync5(packageJsonPath)) {
594
605
  return false;
@@ -597,7 +608,7 @@ function removeEslintFromPackageJson(options) {
597
608
  let modified = false;
598
609
  modified = removeEslintDeps(packageJson.dependencies) || modified;
599
610
  modified = removeEslintDeps(packageJson.devDependencies) || modified;
600
- modified = removeEslintScripts(packageJson.scripts, options) || modified;
611
+ modified = removeEslintScripts(packageJson.scripts, options2) || modified;
601
612
  if (modified) {
602
613
  writeFileSync3(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}
603
614
  `);
@@ -616,11 +627,11 @@ function removeEslintDeps(deps) {
616
627
  }
617
628
  return modified;
618
629
  }
619
- function removeEslintScripts(scripts, options) {
630
+ function removeEslintScripts(scripts, options2) {
620
631
  if (!scripts) return false;
621
632
  let modified = false;
622
633
  for (const key of Object.keys(scripts)) {
623
- const isEslintScript = key.includes("eslint") || scripts[key].includes("eslint") || options.removeLintScripts && key.includes("lint");
634
+ const isEslintScript = key.includes("eslint") || scripts[key].includes("eslint") || options2.removeLintScripts && key.includes("lint");
624
635
  if (isEslintScript) {
625
636
  delete scripts[key];
626
637
  modified = true;
@@ -716,12 +727,25 @@ async function setupLint(packageJsonPath) {
716
727
  );
717
728
  }
718
729
 
719
- // src/commands/verify/setup/setupTest.ts
730
+ // src/commands/verify/setup/setupMaintainability.ts
720
731
  import * as path7 from "path";
721
732
  import chalk13 from "chalk";
733
+ async function setupMaintainability(packageJsonPath) {
734
+ console.log(chalk13.blue("\nSetting up maintainability check..."));
735
+ addToKnipIgnoreBinaries(path7.dirname(packageJsonPath), "assist");
736
+ setupVerifyScript(
737
+ packageJsonPath,
738
+ "verify:maintainability",
739
+ expectedScripts["verify:maintainability"]
740
+ );
741
+ }
742
+
743
+ // src/commands/verify/setup/setupTest.ts
744
+ import * as path8 from "path";
745
+ import chalk14 from "chalk";
722
746
  async function setupTest(packageJsonPath) {
723
- console.log(chalk13.blue("\nSetting up vitest..."));
724
- const cwd = path7.dirname(packageJsonPath);
747
+ console.log(chalk14.blue("\nSetting up vitest..."));
748
+ const cwd = path8.dirname(packageJsonPath);
725
749
  const pkg = readPackageJson(packageJsonPath);
726
750
  if (!pkg.devDependencies?.vitest && !installPackage("vitest", cwd)) {
727
751
  return;
@@ -770,34 +794,22 @@ function detectExistingSetup(pkg) {
770
794
  test: toolStatus(pkg, "verify:test", !!pkg.devDependencies?.vitest),
771
795
  hasVite: !!pkg.devDependencies?.vite || !!pkg.dependencies?.vite,
772
796
  hasTypescript: !!pkg.devDependencies?.typescript,
773
- build: {
774
- hasPackage: true,
775
- hasScript: !!pkg.scripts?.["verify:build"],
776
- isOutdated: false
777
- },
797
+ build: toolStatus(pkg, "verify:build", true),
798
+ typecheck: toolStatus(pkg, "verify:typecheck", true),
778
799
  hardcodedColors: toolStatus(pkg, "verify:hardcoded-colors", true),
800
+ maintainability: toolStatus(pkg, "verify:maintainability", true),
779
801
  hasOpenColor: !!pkg.dependencies?.["open-color"] || !!pkg.devDependencies?.["open-color"]
780
802
  };
781
803
  }
782
804
 
783
- // src/commands/verify/init/getAvailableOptions.ts
805
+ // src/commands/verify/init/options.ts
784
806
  function getBuildDescription(setup) {
785
807
  if (setup.hasVite && setup.hasTypescript)
786
808
  return "TypeScript + Vite build verification";
787
809
  if (setup.hasVite) return "Vite build verification";
788
- return "TypeScript type checking";
789
- }
790
- function shouldInclude(setup, def) {
791
- return needsSetup(setup[def.toolKey]) && (def.extraCondition ?? true);
810
+ return "Build verification";
792
811
  }
793
- function toVerifyOption(setup, def) {
794
- return {
795
- name: `${def.label}${getStatusLabel(setup[def.toolKey])}`,
796
- value: def.value,
797
- description: def.description
798
- };
799
- }
800
- var STATIC_OPTIONS = [
812
+ var options = [
801
813
  {
802
814
  toolKey: "knip",
803
815
  value: "knip",
@@ -821,31 +833,51 @@ var STATIC_OPTIONS = [
821
833
  value: "hardcoded-colors",
822
834
  label: "hardcoded-colors",
823
835
  description: "Detect hardcoded hex colors (use open-color instead)"
836
+ },
837
+ {
838
+ toolKey: "test",
839
+ value: "test",
840
+ label: "test",
841
+ description: "Run tests with vitest",
842
+ extraCondition: (s) => s.test.hasPackage
843
+ },
844
+ {
845
+ toolKey: "build",
846
+ value: "build",
847
+ label: "build",
848
+ description: getBuildDescription,
849
+ extraCondition: (s) => s.hasTypescript || s.hasVite
850
+ },
851
+ {
852
+ toolKey: "typecheck",
853
+ value: "typecheck",
854
+ label: "typecheck",
855
+ description: "TypeScript type checking",
856
+ extraCondition: (s) => s.hasTypescript && !s.hasVite
857
+ },
858
+ {
859
+ toolKey: "maintainability",
860
+ value: "maintainability",
861
+ label: "maintainability",
862
+ description: "Maintainability index threshold check"
824
863
  }
825
864
  ];
826
- function getConditionalOptions(setup) {
827
- return [
828
- {
829
- toolKey: "test",
830
- value: "test",
831
- label: "test",
832
- description: "Run tests with vitest",
833
- extraCondition: setup.test.hasPackage
834
- },
835
- {
836
- toolKey: "build",
837
- value: "build",
838
- label: "build",
839
- description: getBuildDescription(setup),
840
- extraCondition: setup.hasTypescript || setup.hasVite
841
- }
842
- ];
865
+
866
+ // src/commands/verify/init/getAvailableOptions.ts
867
+ function resolveDescription(desc, setup) {
868
+ return typeof desc === "function" ? desc(setup) : desc;
843
869
  }
844
- function getAllOptionDefs(setup) {
845
- return [...STATIC_OPTIONS, ...getConditionalOptions(setup)];
870
+ function toVerifyOption(def, setup) {
871
+ return {
872
+ name: `${def.label}${getStatusLabel(setup[def.toolKey])}`,
873
+ value: def.value,
874
+ description: resolveDescription(def.description, setup)
875
+ };
846
876
  }
847
877
  function getAvailableOptions(setup) {
848
- return getAllOptionDefs(setup).filter((def) => shouldInclude(setup, def)).map((def) => toVerifyOption(setup, def));
878
+ return options.filter(
879
+ (def) => needsSetup(setup[def.toolKey]) && (def.extraCondition?.(setup) ?? true)
880
+ ).map((def) => toVerifyOption(def, setup));
849
881
  }
850
882
 
851
883
  // src/commands/verify/init/index.ts
@@ -856,37 +888,43 @@ function getSetupHandlers(hasVite, hasTypescript, hasOpenColor) {
856
888
  "duplicate-code": (p) => setupDuplicateCode(p),
857
889
  test: (p) => setupTest(p),
858
890
  build: (p) => setupBuild(p, hasVite, hasTypescript),
859
- "hardcoded-colors": (p) => setupHardcodedColors(p, hasOpenColor)
891
+ typecheck: (p) => setupTypecheck(p),
892
+ "hardcoded-colors": (p) => setupHardcodedColors(p, hasOpenColor),
893
+ maintainability: (p) => setupMaintainability(p)
860
894
  };
861
895
  }
862
896
  async function runSelectedSetups(selected, packageJsonPath, handlers) {
863
897
  for (const choice of selected) {
864
898
  await handlers[choice]?.(packageJsonPath);
865
899
  }
866
- console.log(chalk14.green(`
900
+ console.log(chalk15.green(`
867
901
  Added ${selected.length} verify script(s):`));
868
902
  for (const choice of selected) {
869
- console.log(chalk14.green(` - verify:${choice}`));
903
+ console.log(chalk15.green(` - verify:${choice}`));
870
904
  }
871
- console.log(chalk14.dim("\nRun 'assist verify' to run all verify scripts"));
905
+ console.log(chalk15.dim("\nRun 'assist verify' to run all verify scripts"));
872
906
  }
873
- async function init2() {
874
- const { packageJsonPath, pkg } = requirePackageJson();
875
- const setup = detectExistingSetup(pkg);
876
- const availableOptions = getAvailableOptions(setup);
907
+ async function promptForScripts(availableOptions) {
877
908
  if (availableOptions.length === 0) {
878
- console.log(chalk14.green("All verify scripts are already configured!"));
879
- return;
909
+ console.log(chalk15.green("All verify scripts are already configured!"));
910
+ return null;
880
911
  }
881
- console.log(chalk14.bold("Available verify scripts to add:\n"));
912
+ console.log(chalk15.bold("Available verify scripts to add:\n"));
882
913
  const selected = await promptMultiselect(
883
914
  "Select verify scripts to add:",
884
915
  availableOptions
885
916
  );
886
917
  if (selected.length === 0) {
887
- console.log(chalk14.yellow("No scripts selected"));
888
- return;
918
+ console.log(chalk15.yellow("No scripts selected"));
919
+ return null;
889
920
  }
921
+ return selected;
922
+ }
923
+ async function init2() {
924
+ const { packageJsonPath, pkg } = requirePackageJson();
925
+ const setup = detectExistingSetup(pkg);
926
+ const selected = await promptForScripts(getAvailableOptions(setup));
927
+ if (!selected) return;
890
928
  const handlers = getSetupHandlers(
891
929
  setup.hasVite,
892
930
  setup.hasTypescript,
@@ -896,21 +934,21 @@ async function init2() {
896
934
  }
897
935
 
898
936
  // src/commands/vscode/init/index.ts
899
- import chalk16 from "chalk";
937
+ import chalk17 from "chalk";
900
938
 
901
939
  // src/commands/vscode/init/createLaunchJson.ts
902
940
  import * as fs3 from "fs";
903
- import * as path8 from "path";
904
- import chalk15 from "chalk";
941
+ import * as path9 from "path";
942
+ import chalk16 from "chalk";
905
943
  function ensureVscodeFolder() {
906
- const vscodeDir = path8.join(process.cwd(), ".vscode");
944
+ const vscodeDir = path9.join(process.cwd(), ".vscode");
907
945
  if (!fs3.existsSync(vscodeDir)) {
908
946
  fs3.mkdirSync(vscodeDir);
909
- console.log(chalk15.dim("Created .vscode folder"));
947
+ console.log(chalk16.dim("Created .vscode folder"));
910
948
  }
911
949
  }
912
950
  function removeVscodeFromGitignore() {
913
- const gitignorePath = path8.join(process.cwd(), ".gitignore");
951
+ const gitignorePath = path9.join(process.cwd(), ".gitignore");
914
952
  if (!fs3.existsSync(gitignorePath)) {
915
953
  return;
916
954
  }
@@ -921,7 +959,7 @@ function removeVscodeFromGitignore() {
921
959
  );
922
960
  if (filteredLines.length !== lines.length) {
923
961
  fs3.writeFileSync(gitignorePath, filteredLines.join("\n"));
924
- console.log(chalk15.dim("Removed .vscode references from .gitignore"));
962
+ console.log(chalk16.dim("Removed .vscode references from .gitignore"));
925
963
  }
926
964
  }
927
965
  function createLaunchJson() {
@@ -936,10 +974,10 @@ function createLaunchJson() {
936
974
  }
937
975
  ]
938
976
  };
939
- const launchPath = path8.join(process.cwd(), ".vscode", "launch.json");
977
+ const launchPath = path9.join(process.cwd(), ".vscode", "launch.json");
940
978
  fs3.writeFileSync(launchPath, `${JSON.stringify(launchConfig, null, " ")}
941
979
  `);
942
- console.log(chalk15.green("Created .vscode/launch.json"));
980
+ console.log(chalk16.green("Created .vscode/launch.json"));
943
981
  }
944
982
  function createSettingsJson() {
945
983
  const settings = {
@@ -949,33 +987,33 @@ function createSettingsJson() {
949
987
  "source.organizeImports.biome": "explicit"
950
988
  }
951
989
  };
952
- const settingsPath = path8.join(process.cwd(), ".vscode", "settings.json");
990
+ const settingsPath = path9.join(process.cwd(), ".vscode", "settings.json");
953
991
  fs3.writeFileSync(settingsPath, `${JSON.stringify(settings, null, " ")}
954
992
  `);
955
- console.log(chalk15.green("Created .vscode/settings.json"));
993
+ console.log(chalk16.green("Created .vscode/settings.json"));
956
994
  }
957
995
  function createExtensionsJson() {
958
996
  const extensions = {
959
997
  recommendations: ["biomejs.biome"]
960
998
  };
961
- const extensionsPath = path8.join(process.cwd(), ".vscode", "extensions.json");
999
+ const extensionsPath = path9.join(process.cwd(), ".vscode", "extensions.json");
962
1000
  fs3.writeFileSync(
963
1001
  extensionsPath,
964
1002
  `${JSON.stringify(extensions, null, " ")}
965
1003
  `
966
1004
  );
967
- console.log(chalk15.green("Created .vscode/extensions.json"));
1005
+ console.log(chalk16.green("Created .vscode/extensions.json"));
968
1006
  }
969
1007
 
970
1008
  // src/commands/vscode/init/detectVscodeSetup.ts
971
1009
  import * as fs4 from "fs";
972
- import * as path9 from "path";
1010
+ import * as path10 from "path";
973
1011
  function detectVscodeSetup(pkg) {
974
- const vscodeDir = path9.join(process.cwd(), ".vscode");
1012
+ const vscodeDir = path10.join(process.cwd(), ".vscode");
975
1013
  return {
976
1014
  hasVscodeFolder: fs4.existsSync(vscodeDir),
977
- hasLaunchJson: fs4.existsSync(path9.join(vscodeDir, "launch.json")),
978
- hasSettingsJson: fs4.existsSync(path9.join(vscodeDir, "settings.json")),
1015
+ hasLaunchJson: fs4.existsSync(path10.join(vscodeDir, "launch.json")),
1016
+ hasSettingsJson: fs4.existsSync(path10.join(vscodeDir, "settings.json")),
979
1017
  hasVite: !!pkg.devDependencies?.vite || !!pkg.dependencies?.vite
980
1018
  };
981
1019
  }
@@ -989,43 +1027,43 @@ var SETUP_HANDLERS = {
989
1027
  }
990
1028
  };
991
1029
  function getAvailableOptions2(setup) {
992
- const options = [];
1030
+ const options2 = [];
993
1031
  if (!setup.hasLaunchJson && setup.hasVite)
994
- options.push({
1032
+ options2.push({
995
1033
  name: "launch",
996
1034
  value: "launch",
997
1035
  description: "Debug configuration for Vite dev server"
998
1036
  });
999
1037
  if (!setup.hasSettingsJson)
1000
- options.push({
1038
+ options2.push({
1001
1039
  name: "settings",
1002
1040
  value: "settings",
1003
1041
  description: "Biome formatter configuration"
1004
1042
  });
1005
- return options;
1043
+ return options2;
1006
1044
  }
1007
1045
  async function init3() {
1008
1046
  const { pkg } = requirePackageJson();
1009
1047
  const setup = detectVscodeSetup(pkg);
1010
1048
  const availableOptions = getAvailableOptions2(setup);
1011
1049
  if (availableOptions.length === 0) {
1012
- console.log(chalk16.green("VS Code configuration already exists!"));
1050
+ console.log(chalk17.green("VS Code configuration already exists!"));
1013
1051
  return;
1014
1052
  }
1015
- console.log(chalk16.bold("Available VS Code configurations to add:\n"));
1053
+ console.log(chalk17.bold("Available VS Code configurations to add:\n"));
1016
1054
  const selected = await promptMultiselect(
1017
1055
  "Select configurations to add:",
1018
1056
  availableOptions
1019
1057
  );
1020
1058
  if (selected.length === 0) {
1021
- console.log(chalk16.yellow("No configurations selected"));
1059
+ console.log(chalk17.yellow("No configurations selected"));
1022
1060
  return;
1023
1061
  }
1024
1062
  removeVscodeFromGitignore();
1025
1063
  ensureVscodeFolder();
1026
1064
  for (const choice of selected) SETUP_HANDLERS[choice]?.();
1027
1065
  console.log(
1028
- chalk16.green(`
1066
+ chalk17.green(`
1029
1067
  Added ${selected.length} VS Code configuration(s)`)
1030
1068
  );
1031
1069
  }
@@ -1038,24 +1076,24 @@ async function init4() {
1038
1076
 
1039
1077
  // src/commands/lint/lint/runFileNameCheck.ts
1040
1078
  import fs6 from "fs";
1041
- import path11 from "path";
1042
- import chalk17 from "chalk";
1079
+ import path12 from "path";
1080
+ import chalk18 from "chalk";
1043
1081
 
1044
1082
  // src/shared/findSourceFiles.ts
1045
1083
  import fs5 from "fs";
1046
- import path10 from "path";
1084
+ import path11 from "path";
1047
1085
  var EXTENSIONS = [".ts", ".tsx"];
1048
- function findSourceFiles(dir, options = {}) {
1049
- const { includeTests = true } = options;
1086
+ function findSourceFiles(dir, options2 = {}) {
1087
+ const { includeTests = true } = options2;
1050
1088
  const results = [];
1051
1089
  if (!fs5.existsSync(dir)) {
1052
1090
  return results;
1053
1091
  }
1054
1092
  const entries = fs5.readdirSync(dir, { withFileTypes: true });
1055
1093
  for (const entry of entries) {
1056
- const fullPath = path10.join(dir, entry.name);
1094
+ const fullPath = path11.join(dir, entry.name);
1057
1095
  if (entry.isDirectory() && entry.name !== "node_modules") {
1058
- results.push(...findSourceFiles(fullPath, options));
1096
+ results.push(...findSourceFiles(fullPath, options2));
1059
1097
  } else if (entry.isFile() && EXTENSIONS.some((ext) => entry.name.endsWith(ext))) {
1060
1098
  if (!includeTests && entry.name.includes(".test.")) {
1061
1099
  continue;
@@ -1077,7 +1115,7 @@ function checkFileNames() {
1077
1115
  const sourceFiles = findSourceFiles("src");
1078
1116
  const violations = [];
1079
1117
  for (const filePath of sourceFiles) {
1080
- const fileName = path11.basename(filePath);
1118
+ const fileName = path12.basename(filePath);
1081
1119
  const nameWithoutExt = fileName.replace(/\.(ts|tsx)$/, "");
1082
1120
  if (/^[A-Z]/.test(nameWithoutExt)) {
1083
1121
  const content = fs6.readFileSync(filePath, "utf-8");
@@ -1091,16 +1129,16 @@ function checkFileNames() {
1091
1129
  function runFileNameCheck() {
1092
1130
  const violations = checkFileNames();
1093
1131
  if (violations.length > 0) {
1094
- console.error(chalk17.red("\nFile name check failed:\n"));
1132
+ console.error(chalk18.red("\nFile name check failed:\n"));
1095
1133
  console.error(
1096
- chalk17.red(
1134
+ chalk18.red(
1097
1135
  " Files without classes or React components should not start with a capital letter.\n"
1098
1136
  )
1099
1137
  );
1100
1138
  for (const violation of violations) {
1101
- console.error(chalk17.red(` ${violation.filePath}`));
1139
+ console.error(chalk18.red(` ${violation.filePath}`));
1102
1140
  console.error(
1103
- chalk17.gray(
1141
+ chalk18.gray(
1104
1142
  ` Rename to: ${violation.fileName.charAt(0).toLowerCase()}${violation.fileName.slice(1)}
1105
1143
  `
1106
1144
  )
@@ -1120,17 +1158,17 @@ function runFileNameCheck() {
1120
1158
  import fs7 from "fs";
1121
1159
 
1122
1160
  // src/commands/lint/shared.ts
1123
- import chalk18 from "chalk";
1161
+ import chalk19 from "chalk";
1124
1162
  function reportViolations(violations, checkName, errorMessage, successMessage) {
1125
1163
  if (violations.length > 0) {
1126
- console.error(chalk18.red(`
1164
+ console.error(chalk19.red(`
1127
1165
  ${checkName} failed:
1128
1166
  `));
1129
- console.error(chalk18.red(` ${errorMessage}
1167
+ console.error(chalk19.red(` ${errorMessage}
1130
1168
  `));
1131
1169
  for (const violation of violations) {
1132
- console.error(chalk18.red(` ${violation.filePath}:${violation.line}`));
1133
- console.error(chalk18.gray(` ${violation.content}
1170
+ console.error(chalk19.red(` ${violation.filePath}:${violation.line}`));
1171
+ console.error(chalk19.gray(` ${violation.content}
1134
1172
  `));
1135
1173
  }
1136
1174
  return false;
@@ -1223,22 +1261,261 @@ function lint() {
1223
1261
  }
1224
1262
  }
1225
1263
 
1226
- // src/commands/new/newProject.ts
1264
+ // src/commands/new/newCli.ts
1265
+ import { execSync as execSync7 } from "child_process";
1266
+ import { basename as basename2, resolve } from "path";
1267
+
1268
+ // src/commands/verify/hardcodedColors.ts
1269
+ import { execSync as execSync5 } from "child_process";
1270
+ var pattern = "0x[0-9a-fA-F]{6}|#[0-9a-fA-F]{3,6}";
1271
+ function hardcodedColors() {
1272
+ try {
1273
+ const output = execSync5(`grep -rEnH '${pattern}' src/`, {
1274
+ encoding: "utf-8"
1275
+ });
1276
+ const lines = output.trim().split("\n");
1277
+ console.log("Hardcoded colors found:\n");
1278
+ for (const line of lines) {
1279
+ const match = line.match(/^(.+):(\d+):(.+)$/);
1280
+ if (match) {
1281
+ const [, file, lineNum, content] = match;
1282
+ const colorMatch = content.match(/0x[0-9a-fA-F]{6}|#[0-9a-fA-F]{3,6}/);
1283
+ const color = colorMatch?.[0] ?? "unknown";
1284
+ console.log(`${file}:${lineNum} \u2192 ${color}`);
1285
+ }
1286
+ }
1287
+ console.log(`
1288
+ Total: ${lines.length} hardcoded color(s)`);
1289
+ console.log("\nUse colors from the 'open-color' (oc) library instead.");
1290
+ console.log("\nExample fix:");
1291
+ console.log(" Before: color: '#228be6'");
1292
+ console.log(" After: color: oc.blue[6]");
1293
+ console.log("\nImport open-color with: import oc from 'open-color'");
1294
+ process.exit(1);
1295
+ } catch {
1296
+ console.log("No hardcoded colors found.");
1297
+ process.exit(0);
1298
+ }
1299
+ }
1300
+
1301
+ // src/commands/verify/run/index.ts
1302
+ import { spawn } from "child_process";
1303
+ import * as path13 from "path";
1304
+
1305
+ // src/commands/verify/run/createTimerCallback/printTaskStatuses.ts
1306
+ function formatDuration(ms) {
1307
+ if (ms < 1e3) {
1308
+ return `${ms}ms`;
1309
+ }
1310
+ const seconds = (ms / 1e3).toFixed(1);
1311
+ return `${seconds}s`;
1312
+ }
1313
+ function printTaskStatuses(tasks) {
1314
+ console.log("\n--- Task Status ---");
1315
+ for (const task of tasks) {
1316
+ if (task.endTime !== void 0) {
1317
+ const duration = formatDuration(task.endTime - task.startTime);
1318
+ const status = task.code === 0 ? "\u2713" : "\u2717";
1319
+ console.log(` ${status} ${task.script}: ${duration}`);
1320
+ } else {
1321
+ const elapsed = formatDuration(Date.now() - task.startTime);
1322
+ console.log(` \u22EF ${task.script}: running (${elapsed})`);
1323
+ }
1324
+ }
1325
+ console.log("-------------------\n");
1326
+ }
1327
+
1328
+ // src/commands/verify/run/createTimerCallback/index.ts
1329
+ function logFailedScripts(failed) {
1330
+ console.error(`
1331
+ ${failed.length} script(s) failed:`);
1332
+ for (const f of failed) {
1333
+ console.error(` - ${f.script} (exit code ${f.code})`);
1334
+ }
1335
+ }
1336
+ function createTimerCallback(taskStatuses, index) {
1337
+ return (exitCode) => {
1338
+ taskStatuses[index].endTime = Date.now();
1339
+ taskStatuses[index].code = exitCode;
1340
+ printTaskStatuses(taskStatuses);
1341
+ };
1342
+ }
1343
+ function initTaskStatuses(scripts) {
1344
+ return scripts.map((script) => ({ script, startTime: Date.now() }));
1345
+ }
1346
+
1347
+ // src/commands/verify/run/index.ts
1348
+ function spawnScript(script, cwd) {
1349
+ return spawn("npm", ["run", script], { stdio: "inherit", shell: true, cwd });
1350
+ }
1351
+ function onScriptClose(script, onComplete, resolve2) {
1352
+ return (code) => {
1353
+ const exitCode = code ?? 1;
1354
+ onComplete?.(exitCode);
1355
+ resolve2({ script, code: exitCode });
1356
+ };
1357
+ }
1358
+ function runScript(script, cwd, onComplete) {
1359
+ return new Promise((resolve2) => {
1360
+ spawnScript(script, cwd).on(
1361
+ "close",
1362
+ onScriptClose(script, onComplete, resolve2)
1363
+ );
1364
+ });
1365
+ }
1366
+ function runAllScripts(verifyScripts, packageDir, timer) {
1367
+ const taskStatuses = initTaskStatuses(verifyScripts);
1368
+ return Promise.all(
1369
+ verifyScripts.map(
1370
+ (script, index) => runScript(
1371
+ script,
1372
+ packageDir,
1373
+ timer ? createTimerCallback(taskStatuses, index) : void 0
1374
+ )
1375
+ )
1376
+ );
1377
+ }
1378
+ function printScriptList(scripts) {
1379
+ console.log(`Running ${scripts.length} verify script(s) in parallel:`);
1380
+ for (const script of scripts) {
1381
+ console.log(` - ${script}`);
1382
+ }
1383
+ }
1384
+ function exitIfFailed(failed) {
1385
+ if (failed.length === 0) return;
1386
+ logFailedScripts(failed);
1387
+ process.exit(1);
1388
+ }
1389
+ function handleResults(results, totalCount) {
1390
+ exitIfFailed(results.filter((r) => r.code !== 0));
1391
+ console.log(`
1392
+ All ${totalCount} verify script(s) passed`);
1393
+ }
1394
+ function resolveVerifyScripts() {
1395
+ const result = findPackageJsonWithVerifyScripts(process.cwd());
1396
+ if (!result) {
1397
+ console.log("No package.json with verify:* scripts found");
1398
+ return null;
1399
+ }
1400
+ return result;
1401
+ }
1402
+ function getPackageDir(found) {
1403
+ return path13.dirname(found.packageJsonPath);
1404
+ }
1405
+ async function executeVerifyScripts(found, timer) {
1406
+ printScriptList(found.verifyScripts);
1407
+ const results = await runAllScripts(
1408
+ found.verifyScripts,
1409
+ getPackageDir(found),
1410
+ timer
1411
+ );
1412
+ handleResults(results, found.verifyScripts.length);
1413
+ }
1414
+ async function run(options2 = {}) {
1415
+ const found = resolveVerifyScripts();
1416
+ if (!found) return;
1417
+ await executeVerifyScripts(found, options2.timer ?? false);
1418
+ }
1419
+
1420
+ // src/commands/new/initPackageJson.ts
1227
1421
  import { execSync as execSync6 } from "child_process";
1228
- import { existsSync as existsSync10, readFileSync as readFileSync8, writeFileSync as writeFileSync7 } from "fs";
1422
+ function initPackageJson(name) {
1423
+ console.log("Initializing package.json...");
1424
+ execSync6("npm init -y", { stdio: "inherit" });
1425
+ console.log("Configuring package.json...");
1426
+ execSync6("npm pkg delete main", { stdio: "inherit" });
1427
+ execSync6("npm pkg set type=module", { stdio: "inherit" });
1428
+ execSync6(`npm pkg set bin.${name}=./dist/index.js`, { stdio: "inherit" });
1429
+ execSync6("npm pkg set scripts.build=tsup", { stdio: "inherit" });
1430
+ execSync6('npm pkg set scripts.start="node dist/index.js"', {
1431
+ stdio: "inherit"
1432
+ });
1433
+ }
1434
+
1435
+ // src/commands/new/writeCliTemplate.ts
1436
+ import { mkdirSync as mkdirSync2, writeFileSync as writeFileSync6 } from "fs";
1437
+ function writeCliTemplate(name) {
1438
+ console.log("Writing tsconfig.json...");
1439
+ writeFileSync6(
1440
+ "tsconfig.json",
1441
+ JSON.stringify(
1442
+ {
1443
+ compilerOptions: {
1444
+ target: "ES2022",
1445
+ module: "ESNext",
1446
+ moduleResolution: "bundler",
1447
+ outDir: "./dist",
1448
+ rootDir: "./src",
1449
+ strict: true,
1450
+ esModuleInterop: true,
1451
+ resolveJsonModule: true,
1452
+ skipLibCheck: true,
1453
+ forceConsistentCasingInFileNames: true
1454
+ },
1455
+ include: ["src/**/*"],
1456
+ exclude: ["node_modules"]
1457
+ },
1458
+ null,
1459
+ " "
1460
+ )
1461
+ );
1462
+ console.log("Writing tsup.config.ts...");
1463
+ writeFileSync6(
1464
+ "tsup.config.ts",
1465
+ `import { defineConfig } from "tsup";
1466
+ export default defineConfig({
1467
+ entry: ["src/index.ts"],
1468
+ format: ["esm"],
1469
+ target: "node22",
1470
+ outDir: "dist",
1471
+ clean: true,
1472
+ shims: true,
1473
+ });
1474
+ `
1475
+ );
1476
+ console.log("Writing src/index.ts...");
1477
+ mkdirSync2("src", { recursive: true });
1478
+ writeFileSync6(
1479
+ "src/index.ts",
1480
+ `#!/usr/bin/env node
1481
+ import { Command } from "commander";
1482
+ const program = new Command();
1483
+ program.name("${name}").description("").version("0.0.0");
1484
+ program.parse();
1485
+ `
1486
+ );
1487
+ }
1488
+
1489
+ // src/commands/new/newCli.ts
1490
+ async function newCli() {
1491
+ const name = basename2(resolve("."));
1492
+ initPackageJson(name);
1493
+ console.log("Installing dependencies...");
1494
+ execSync7("npm install commander", { stdio: "inherit" });
1495
+ execSync7("npm install -D tsup typescript @types/node", {
1496
+ stdio: "inherit"
1497
+ });
1498
+ writeCliTemplate(name);
1499
+ await init4();
1500
+ await run();
1501
+ }
1502
+
1503
+ // src/commands/new/newProject.ts
1504
+ import { execSync as execSync9 } from "child_process";
1505
+ import { existsSync as existsSync10, readFileSync as readFileSync8, writeFileSync as writeFileSync8 } from "fs";
1229
1506
 
1230
1507
  // src/commands/deploy/init/index.ts
1231
- import { execSync as execSync5 } from "child_process";
1232
- import chalk20 from "chalk";
1508
+ import { execSync as execSync8 } from "child_process";
1509
+ import chalk21 from "chalk";
1233
1510
  import enquirer3 from "enquirer";
1234
1511
 
1235
1512
  // src/commands/deploy/init/updateWorkflow.ts
1236
- import { existsSync as existsSync9, mkdirSync as mkdirSync2, readFileSync as readFileSync7, writeFileSync as writeFileSync6 } from "fs";
1237
- import { dirname as dirname8, join as join7 } from "path";
1513
+ import { existsSync as existsSync9, mkdirSync as mkdirSync3, readFileSync as readFileSync7, writeFileSync as writeFileSync7 } from "fs";
1514
+ import { dirname as dirname10, join as join7 } from "path";
1238
1515
  import { fileURLToPath as fileURLToPath2 } from "url";
1239
- import chalk19 from "chalk";
1516
+ import chalk20 from "chalk";
1240
1517
  var WORKFLOW_PATH = ".github/workflows/build.yml";
1241
- var __dirname3 = dirname8(fileURLToPath2(import.meta.url));
1518
+ var __dirname3 = dirname10(fileURLToPath2(import.meta.url));
1242
1519
  function getExistingSiteId() {
1243
1520
  if (!existsSync9(WORKFLOW_PATH)) {
1244
1521
  return null;
@@ -1256,72 +1533,72 @@ async function updateWorkflow(siteId) {
1256
1533
  const newContent = getTemplateContent(siteId);
1257
1534
  const workflowDir = ".github/workflows";
1258
1535
  if (!existsSync9(workflowDir)) {
1259
- mkdirSync2(workflowDir, { recursive: true });
1536
+ mkdirSync3(workflowDir, { recursive: true });
1260
1537
  }
1261
1538
  if (existsSync9(WORKFLOW_PATH)) {
1262
1539
  const oldContent = readFileSync7(WORKFLOW_PATH, "utf-8");
1263
1540
  if (oldContent === newContent) {
1264
- console.log(chalk19.green("build.yml is already up to date"));
1541
+ console.log(chalk20.green("build.yml is already up to date"));
1265
1542
  return;
1266
1543
  }
1267
- console.log(chalk19.yellow("\nbuild.yml will be updated:"));
1544
+ console.log(chalk20.yellow("\nbuild.yml will be updated:"));
1268
1545
  console.log();
1269
1546
  printDiff(oldContent, newContent);
1270
- const confirm = await promptConfirm(chalk19.red("Update build.yml?"));
1547
+ const confirm = await promptConfirm(chalk20.red("Update build.yml?"));
1271
1548
  if (!confirm) {
1272
1549
  console.log("Skipped build.yml update");
1273
1550
  return;
1274
1551
  }
1275
1552
  }
1276
- writeFileSync6(WORKFLOW_PATH, newContent);
1277
- console.log(chalk19.green(`
1553
+ writeFileSync7(WORKFLOW_PATH, newContent);
1554
+ console.log(chalk20.green(`
1278
1555
  Created ${WORKFLOW_PATH}`));
1279
1556
  }
1280
1557
 
1281
1558
  // src/commands/deploy/init/index.ts
1282
1559
  async function ensureNetlifyCli() {
1283
1560
  try {
1284
- execSync5("netlify sites:create --disable-linking", { stdio: "inherit" });
1561
+ execSync8("netlify sites:create --disable-linking", { stdio: "inherit" });
1285
1562
  } catch (error) {
1286
1563
  if (!(error instanceof Error) || !error.message.includes("command not found"))
1287
1564
  throw error;
1288
- console.error(chalk20.red("\nNetlify CLI is not installed.\n"));
1565
+ console.error(chalk21.red("\nNetlify CLI is not installed.\n"));
1289
1566
  const install = await promptConfirm("Would you like to install it now?");
1290
1567
  if (!install) {
1291
1568
  console.log(
1292
- chalk20.yellow(
1569
+ chalk21.yellow(
1293
1570
  "\nInstall it manually with: npm install -g netlify-cli\n"
1294
1571
  )
1295
1572
  );
1296
1573
  process.exit(1);
1297
1574
  }
1298
- console.log(chalk20.dim("\nInstalling netlify-cli...\n"));
1299
- execSync5("npm install -g netlify-cli", { stdio: "inherit" });
1575
+ console.log(chalk21.dim("\nInstalling netlify-cli...\n"));
1576
+ execSync8("npm install -g netlify-cli", { stdio: "inherit" });
1300
1577
  console.log();
1301
- execSync5("netlify sites:create --disable-linking", { stdio: "inherit" });
1578
+ execSync8("netlify sites:create --disable-linking", { stdio: "inherit" });
1302
1579
  }
1303
1580
  }
1304
1581
  function printSetupInstructions() {
1305
- console.log(chalk20.bold("\nDeployment initialized successfully!"));
1582
+ console.log(chalk21.bold("\nDeployment initialized successfully!"));
1306
1583
  console.log(
1307
- chalk20.yellow("\nTo complete setup, create a personal access token at:")
1584
+ chalk21.yellow("\nTo complete setup, create a personal access token at:")
1308
1585
  );
1309
1586
  console.log(
1310
- chalk20.cyan(
1587
+ chalk21.cyan(
1311
1588
  "https://app.netlify.com/user/applications#personal-access-tokens"
1312
1589
  )
1313
1590
  );
1314
1591
  console.log(
1315
- chalk20.yellow(
1592
+ chalk21.yellow(
1316
1593
  "\nThen add it as NETLIFY_AUTH_TOKEN in your GitHub repository secrets."
1317
1594
  )
1318
1595
  );
1319
1596
  }
1320
1597
  async function init5() {
1321
- console.log(chalk20.bold("Initializing Netlify deployment...\n"));
1598
+ console.log(chalk21.bold("Initializing Netlify deployment...\n"));
1322
1599
  const existingSiteId = getExistingSiteId();
1323
1600
  if (existingSiteId) {
1324
- console.log(chalk20.dim(`Using existing site ID: ${existingSiteId}
1601
+ console.log(chalk21.dim(`Using existing site ID: ${existingSiteId}
1325
1602
  `));
1326
1603
  await updateWorkflow(existingSiteId);
1327
1604
  return;
@@ -1341,7 +1618,7 @@ async function init5() {
1341
1618
  // src/commands/new/newProject.ts
1342
1619
  async function newProject() {
1343
1620
  console.log("Initializing Vite with react-ts template...");
1344
- execSync6("npm create vite@latest . -- --template react-ts", {
1621
+ execSync9("npm create vite@latest . -- --template react-ts", {
1345
1622
  stdio: "inherit"
1346
1623
  });
1347
1624
  removeEslint({ removeLintScripts: true });
@@ -1365,11 +1642,18 @@ function addViteBaseConfig() {
1365
1642
  'defineConfig({\n base: "./",'
1366
1643
  );
1367
1644
  if (updated !== content) {
1368
- writeFileSync7(viteConfigPath, updated);
1645
+ writeFileSync8(viteConfigPath, updated);
1369
1646
  console.log('Added base: "./" to vite.config.ts');
1370
1647
  }
1371
1648
  }
1372
1649
 
1650
+ // src/commands/new/registerNew.ts
1651
+ function registerNew(program2) {
1652
+ const newCommand = program2.command("new").description("Scaffold a new project");
1653
+ newCommand.command("vite").description("Initialize a new Vite React TypeScript project").action(newProject);
1654
+ newCommand.command("cli").description("Initialize a new tsup CLI project").action(newCli);
1655
+ }
1656
+
1373
1657
  // src/lib/readStdin.ts
1374
1658
  import * as readline from "readline";
1375
1659
  async function readStdin() {
@@ -1405,17 +1689,17 @@ function detectPlatform() {
1405
1689
  }
1406
1690
 
1407
1691
  // src/commands/notify/showNotification/showWindowsNotificationFromWsl.ts
1408
- import { spawn } from "child_process";
1692
+ import { spawn as spawn2 } from "child_process";
1409
1693
  import fs9 from "fs";
1410
1694
  import { createRequire } from "module";
1411
- import path12 from "path";
1695
+ import path14 from "path";
1412
1696
  var require2 = createRequire(import.meta.url);
1413
1697
  function getSnoreToastPath() {
1414
- const notifierPath = path12.dirname(require2.resolve("node-notifier"));
1415
- return path12.join(notifierPath, "vendor", "snoreToast", "snoretoast-x64.exe");
1698
+ const notifierPath = path14.dirname(require2.resolve("node-notifier"));
1699
+ return path14.join(notifierPath, "vendor", "snoreToast", "snoretoast-x64.exe");
1416
1700
  }
1417
- function showWindowsNotificationFromWsl(options) {
1418
- const { title, message, sound } = options;
1701
+ function showWindowsNotificationFromWsl(options2) {
1702
+ const { title, message, sound } = options2;
1419
1703
  const snoreToastPath = getSnoreToastPath();
1420
1704
  try {
1421
1705
  fs9.chmodSync(snoreToastPath, 493);
@@ -1427,7 +1711,7 @@ function showWindowsNotificationFromWsl(options) {
1427
1711
  } else if (sound === "Reminder") {
1428
1712
  args.push("-s", "ms-winsoundevent:Notification.Reminder");
1429
1713
  }
1430
- const child = spawn(snoreToastPath, args, {
1714
+ const child = spawn2(snoreToastPath, args, {
1431
1715
  detached: true,
1432
1716
  stdio: "ignore"
1433
1717
  });
@@ -1436,8 +1720,8 @@ function showWindowsNotificationFromWsl(options) {
1436
1720
  }
1437
1721
 
1438
1722
  // src/commands/notify/showNotification/index.ts
1439
- function showNotification(options) {
1440
- const { title, message, sound } = options;
1723
+ function showNotification(options2) {
1724
+ const { title, message, sound } = options2;
1441
1725
  const platform = detectPlatform();
1442
1726
  if (platform === "wsl") {
1443
1727
  return showWindowsNotificationFromWsl({ title, message, sound });
@@ -1493,20 +1777,20 @@ async function notify() {
1493
1777
  }
1494
1778
 
1495
1779
  // src/commands/complexity/analyze.ts
1496
- import chalk26 from "chalk";
1780
+ import chalk27 from "chalk";
1497
1781
 
1498
1782
  // src/commands/complexity/cyclomatic.ts
1499
- import chalk22 from "chalk";
1783
+ import chalk23 from "chalk";
1500
1784
 
1501
1785
  // src/commands/complexity/shared/index.ts
1502
1786
  import fs11 from "fs";
1503
- import path14 from "path";
1504
- import chalk21 from "chalk";
1787
+ import path16 from "path";
1788
+ import chalk22 from "chalk";
1505
1789
  import ts5 from "typescript";
1506
1790
 
1507
1791
  // src/commands/complexity/findSourceFiles.ts
1508
1792
  import fs10 from "fs";
1509
- import path13 from "path";
1793
+ import path15 from "path";
1510
1794
  import { minimatch } from "minimatch";
1511
1795
  function applyIgnoreGlobs(files) {
1512
1796
  const { complexity } = loadConfig();
@@ -1521,7 +1805,7 @@ function walk(dir, results) {
1521
1805
  const extensions = [".ts", ".tsx"];
1522
1806
  const entries = fs10.readdirSync(dir, { withFileTypes: true });
1523
1807
  for (const entry of entries) {
1524
- const fullPath = path13.join(dir, entry.name);
1808
+ const fullPath = path15.join(dir, entry.name);
1525
1809
  if (entry.isDirectory()) {
1526
1810
  if (entry.name !== "node_modules" && entry.name !== ".git") {
1527
1811
  walk(fullPath, results);
@@ -1737,7 +2021,7 @@ function countSloc(content) {
1737
2021
  function createSourceFromFile(filePath) {
1738
2022
  const content = fs11.readFileSync(filePath, "utf-8");
1739
2023
  return ts5.createSourceFile(
1740
- path14.basename(filePath),
2024
+ path16.basename(filePath),
1741
2025
  content,
1742
2026
  ts5.ScriptTarget.Latest,
1743
2027
  true,
@@ -1747,7 +2031,7 @@ function createSourceFromFile(filePath) {
1747
2031
  function withSourceFiles(pattern2, callback) {
1748
2032
  const files = findSourceFiles2(pattern2);
1749
2033
  if (files.length === 0) {
1750
- console.log(chalk21.yellow("No files found matching pattern"));
2034
+ console.log(chalk22.yellow("No files found matching pattern"));
1751
2035
  return void 0;
1752
2036
  }
1753
2037
  return callback(files);
@@ -1766,25 +2050,25 @@ function forEachFunction(files, callback) {
1766
2050
  }
1767
2051
 
1768
2052
  // src/commands/complexity/cyclomatic.ts
1769
- async function cyclomatic(pattern2 = "**/*.ts", options = {}) {
2053
+ async function cyclomatic(pattern2 = "**/*.ts", options2 = {}) {
1770
2054
  withSourceFiles(pattern2, (files) => {
1771
2055
  const results = [];
1772
2056
  let hasViolation = false;
1773
2057
  forEachFunction(files, (file, name, node) => {
1774
2058
  const complexity = calculateCyclomaticComplexity(node);
1775
2059
  results.push({ file, name, complexity });
1776
- if (options.threshold !== void 0 && complexity > options.threshold) {
2060
+ if (options2.threshold !== void 0 && complexity > options2.threshold) {
1777
2061
  hasViolation = true;
1778
2062
  }
1779
2063
  });
1780
2064
  results.sort((a, b) => b.complexity - a.complexity);
1781
2065
  for (const { file, name, complexity } of results) {
1782
- const exceedsThreshold = options.threshold !== void 0 && complexity > options.threshold;
1783
- const color = exceedsThreshold ? chalk22.red : chalk22.white;
1784
- console.log(`${color(`${file}:${name}`)} \u2192 ${chalk22.cyan(complexity)}`);
2066
+ const exceedsThreshold = options2.threshold !== void 0 && complexity > options2.threshold;
2067
+ const color = exceedsThreshold ? chalk23.red : chalk23.white;
2068
+ console.log(`${color(`${file}:${name}`)} \u2192 ${chalk23.cyan(complexity)}`);
1785
2069
  }
1786
2070
  console.log(
1787
- chalk22.dim(
2071
+ chalk23.dim(
1788
2072
  `
1789
2073
  Analyzed ${results.length} functions across ${files.length} files`
1790
2074
  )
@@ -1796,28 +2080,28 @@ Analyzed ${results.length} functions across ${files.length} files`
1796
2080
  }
1797
2081
 
1798
2082
  // src/commands/complexity/halstead.ts
1799
- import chalk23 from "chalk";
1800
- async function halstead(pattern2 = "**/*.ts", options = {}) {
2083
+ import chalk24 from "chalk";
2084
+ async function halstead(pattern2 = "**/*.ts", options2 = {}) {
1801
2085
  withSourceFiles(pattern2, (files) => {
1802
2086
  const results = [];
1803
2087
  let hasViolation = false;
1804
2088
  forEachFunction(files, (file, name, node) => {
1805
2089
  const metrics = calculateHalstead(node);
1806
2090
  results.push({ file, name, metrics });
1807
- if (options.threshold !== void 0 && metrics.volume > options.threshold) {
2091
+ if (options2.threshold !== void 0 && metrics.volume > options2.threshold) {
1808
2092
  hasViolation = true;
1809
2093
  }
1810
2094
  });
1811
2095
  results.sort((a, b) => b.metrics.effort - a.metrics.effort);
1812
2096
  for (const { file, name, metrics } of results) {
1813
- const exceedsThreshold = options.threshold !== void 0 && metrics.volume > options.threshold;
1814
- const color = exceedsThreshold ? chalk23.red : chalk23.white;
2097
+ const exceedsThreshold = options2.threshold !== void 0 && metrics.volume > options2.threshold;
2098
+ const color = exceedsThreshold ? chalk24.red : chalk24.white;
1815
2099
  console.log(
1816
- `${color(`${file}:${name}`)} \u2192 volume: ${chalk23.cyan(metrics.volume.toFixed(1))}, difficulty: ${chalk23.yellow(metrics.difficulty.toFixed(1))}, effort: ${chalk23.magenta(metrics.effort.toFixed(1))}`
2100
+ `${color(`${file}:${name}`)} \u2192 volume: ${chalk24.cyan(metrics.volume.toFixed(1))}, difficulty: ${chalk24.yellow(metrics.difficulty.toFixed(1))}, effort: ${chalk24.magenta(metrics.effort.toFixed(1))}`
1817
2101
  );
1818
2102
  }
1819
2103
  console.log(
1820
- chalk23.dim(
2104
+ chalk24.dim(
1821
2105
  `
1822
2106
  Analyzed ${results.length} functions across ${files.length} files`
1823
2107
  )
@@ -1832,24 +2116,24 @@ Analyzed ${results.length} functions across ${files.length} files`
1832
2116
  import fs12 from "fs";
1833
2117
 
1834
2118
  // src/commands/complexity/maintainability/displayMaintainabilityResults.ts
1835
- import chalk24 from "chalk";
2119
+ import chalk25 from "chalk";
1836
2120
  function displayMaintainabilityResults(results, threshold) {
1837
2121
  const filtered = threshold !== void 0 ? results.filter((r) => r.minMaintainability < threshold) : results;
1838
2122
  if (threshold !== void 0 && filtered.length === 0) {
1839
- console.log(chalk24.green("All files pass maintainability threshold"));
2123
+ console.log(chalk25.green("All files pass maintainability threshold"));
1840
2124
  } else {
1841
2125
  for (const { file, avgMaintainability, minMaintainability } of filtered) {
1842
- const color = threshold !== void 0 ? chalk24.red : chalk24.white;
2126
+ const color = threshold !== void 0 ? chalk25.red : chalk25.white;
1843
2127
  console.log(
1844
- `${color(file)} \u2192 avg: ${chalk24.cyan(avgMaintainability.toFixed(1))}, min: ${chalk24.yellow(minMaintainability.toFixed(1))}`
2128
+ `${color(file)} \u2192 avg: ${chalk25.cyan(avgMaintainability.toFixed(1))}, min: ${chalk25.yellow(minMaintainability.toFixed(1))}`
1845
2129
  );
1846
2130
  }
1847
2131
  }
1848
- console.log(chalk24.dim(`
2132
+ console.log(chalk25.dim(`
1849
2133
  Analyzed ${results.length} files`));
1850
2134
  if (filtered.length > 0 && threshold !== void 0) {
1851
2135
  console.error(
1852
- chalk24.red(
2136
+ chalk25.red(
1853
2137
  `
1854
2138
  Fail: ${filtered.length} file(s) below threshold ${threshold}. Maintainability index (0\u2013100) is derived from Halstead volume, cyclomatic complexity, and lines of code. Focus on one file at a time \u2014 run 'assist complexity <file>' to see all metrics. For larger files, start by extracting responsibilities into smaller files.`
1855
2139
  )
@@ -1898,18 +2182,18 @@ function aggregateResults(fileMetrics) {
1898
2182
  results.sort((a, b) => a.minMaintainability - b.minMaintainability);
1899
2183
  return results;
1900
2184
  }
1901
- async function maintainability(pattern2 = "**/*.ts", options = {}) {
2185
+ async function maintainability(pattern2 = "**/*.ts", options2 = {}) {
1902
2186
  withSourceFiles(pattern2, (files) => {
1903
2187
  const fileMetrics = collectFileMetrics(files);
1904
2188
  const results = aggregateResults(fileMetrics);
1905
- displayMaintainabilityResults(results, options.threshold);
2189
+ displayMaintainabilityResults(results, options2.threshold);
1906
2190
  });
1907
2191
  }
1908
2192
 
1909
2193
  // src/commands/complexity/sloc.ts
1910
2194
  import fs13 from "fs";
1911
- import chalk25 from "chalk";
1912
- async function sloc(pattern2 = "**/*.ts", options = {}) {
2195
+ import chalk26 from "chalk";
2196
+ async function sloc(pattern2 = "**/*.ts", options2 = {}) {
1913
2197
  withSourceFiles(pattern2, (files) => {
1914
2198
  const results = [];
1915
2199
  let hasViolation = false;
@@ -1917,19 +2201,19 @@ async function sloc(pattern2 = "**/*.ts", options = {}) {
1917
2201
  const content = fs13.readFileSync(file, "utf-8");
1918
2202
  const lines = countSloc(content);
1919
2203
  results.push({ file, lines });
1920
- if (options.threshold !== void 0 && lines > options.threshold) {
2204
+ if (options2.threshold !== void 0 && lines > options2.threshold) {
1921
2205
  hasViolation = true;
1922
2206
  }
1923
2207
  }
1924
2208
  results.sort((a, b) => b.lines - a.lines);
1925
2209
  for (const { file, lines } of results) {
1926
- const exceedsThreshold = options.threshold !== void 0 && lines > options.threshold;
1927
- const color = exceedsThreshold ? chalk25.red : chalk25.white;
1928
- console.log(`${color(file)} \u2192 ${chalk25.cyan(lines)} lines`);
2210
+ const exceedsThreshold = options2.threshold !== void 0 && lines > options2.threshold;
2211
+ const color = exceedsThreshold ? chalk26.red : chalk26.white;
2212
+ console.log(`${color(file)} \u2192 ${chalk26.cyan(lines)} lines`);
1929
2213
  }
1930
2214
  const total = results.reduce((sum, r) => sum + r.lines, 0);
1931
2215
  console.log(
1932
- chalk25.dim(`
2216
+ chalk26.dim(`
1933
2217
  Total: ${total} lines across ${files.length} files`)
1934
2218
  );
1935
2219
  if (hasViolation) {
@@ -1943,21 +2227,21 @@ async function analyze(pattern2) {
1943
2227
  const searchPattern = pattern2.includes("*") || pattern2.includes("/") ? pattern2 : `**/${pattern2}`;
1944
2228
  const files = findSourceFiles2(searchPattern);
1945
2229
  if (files.length === 0) {
1946
- console.log(chalk26.yellow("No files found matching pattern"));
2230
+ console.log(chalk27.yellow("No files found matching pattern"));
1947
2231
  return;
1948
2232
  }
1949
2233
  if (files.length === 1) {
1950
2234
  const file = files[0];
1951
- console.log(chalk26.bold.underline("SLOC"));
2235
+ console.log(chalk27.bold.underline("SLOC"));
1952
2236
  await sloc(file);
1953
2237
  console.log();
1954
- console.log(chalk26.bold.underline("Cyclomatic Complexity"));
2238
+ console.log(chalk27.bold.underline("Cyclomatic Complexity"));
1955
2239
  await cyclomatic(file);
1956
2240
  console.log();
1957
- console.log(chalk26.bold.underline("Halstead Metrics"));
2241
+ console.log(chalk27.bold.underline("Halstead Metrics"));
1958
2242
  await halstead(file);
1959
2243
  console.log();
1960
- console.log(chalk26.bold.underline("Maintainability Index"));
2244
+ console.log(chalk27.bold.underline("Maintainability Index"));
1961
2245
  await maintainability(file);
1962
2246
  return;
1963
2247
  }
@@ -1984,8 +2268,8 @@ function registerComplexity(program2) {
1984
2268
  }
1985
2269
 
1986
2270
  // src/commands/deploy/redirect.ts
1987
- import { existsSync as existsSync11, readFileSync as readFileSync9, writeFileSync as writeFileSync8 } from "fs";
1988
- import chalk27 from "chalk";
2271
+ import { existsSync as existsSync11, readFileSync as readFileSync9, writeFileSync as writeFileSync9 } from "fs";
2272
+ import chalk28 from "chalk";
1989
2273
  var TRAILING_SLASH_SCRIPT = ` <script>
1990
2274
  if (!window.location.pathname.endsWith('/')) {
1991
2275
  window.location.href = \`\${window.location.pathname}/\${window.location.search}\${window.location.hash}\`;
@@ -1994,22 +2278,22 @@ var TRAILING_SLASH_SCRIPT = ` <script>
1994
2278
  function redirect() {
1995
2279
  const indexPath = "index.html";
1996
2280
  if (!existsSync11(indexPath)) {
1997
- console.log(chalk27.yellow("No index.html found"));
2281
+ console.log(chalk28.yellow("No index.html found"));
1998
2282
  return;
1999
2283
  }
2000
2284
  const content = readFileSync9(indexPath, "utf-8");
2001
2285
  if (content.includes("window.location.pathname.endsWith('/')")) {
2002
- console.log(chalk27.dim("Trailing slash script already present"));
2286
+ console.log(chalk28.dim("Trailing slash script already present"));
2003
2287
  return;
2004
2288
  }
2005
2289
  const headCloseIndex = content.indexOf("</head>");
2006
2290
  if (headCloseIndex === -1) {
2007
- console.log(chalk27.red("Could not find </head> tag in index.html"));
2291
+ console.log(chalk28.red("Could not find </head> tag in index.html"));
2008
2292
  return;
2009
2293
  }
2010
2294
  const newContent = content.slice(0, headCloseIndex) + TRAILING_SLASH_SCRIPT + "\n " + content.slice(headCloseIndex);
2011
- writeFileSync8(indexPath, newContent);
2012
- console.log(chalk27.green("Added trailing slash redirect to index.html"));
2295
+ writeFileSync9(indexPath, newContent);
2296
+ console.log(chalk28.green("Added trailing slash redirect to index.html"));
2013
2297
  }
2014
2298
 
2015
2299
  // src/commands/registerDeploy.ts
@@ -2020,12 +2304,12 @@ function registerDeploy(program2) {
2020
2304
  }
2021
2305
 
2022
2306
  // src/commands/devlog/list/index.ts
2023
- import { execSync as execSync8 } from "child_process";
2024
- import { basename as basename2 } from "path";
2307
+ import { execSync as execSync11 } from "child_process";
2308
+ import { basename as basename3 } from "path";
2025
2309
 
2026
2310
  // src/commands/devlog/shared.ts
2027
- import { execSync as execSync7 } from "child_process";
2028
- import chalk28 from "chalk";
2311
+ import { execSync as execSync10 } from "child_process";
2312
+ import chalk29 from "chalk";
2029
2313
 
2030
2314
  // src/commands/devlog/loadDevlogEntries.ts
2031
2315
  import { readdirSync, readFileSync as readFileSync10 } from "fs";
@@ -2068,7 +2352,7 @@ function loadDevlogEntries(repoName) {
2068
2352
  // src/commands/devlog/shared.ts
2069
2353
  function getCommitFiles(hash) {
2070
2354
  try {
2071
- const output = execSync7(`git show --name-only --format="" ${hash}`, {
2355
+ const output = execSync10(`git show --name-only --format="" ${hash}`, {
2072
2356
  encoding: "utf-8"
2073
2357
  });
2074
2358
  return output.trim().split("\n").filter(Boolean);
@@ -2086,13 +2370,13 @@ function shouldIgnoreCommit(files, ignorePaths) {
2086
2370
  }
2087
2371
  function printCommitsWithFiles(commits, ignore2, verbose) {
2088
2372
  for (const commit2 of commits) {
2089
- console.log(` ${chalk28.yellow(commit2.hash)} ${commit2.message}`);
2373
+ console.log(` ${chalk29.yellow(commit2.hash)} ${commit2.message}`);
2090
2374
  if (verbose) {
2091
2375
  const visibleFiles = commit2.files.filter(
2092
2376
  (file) => !ignore2.some((p) => file.startsWith(p))
2093
2377
  );
2094
2378
  for (const file of visibleFiles) {
2095
- console.log(` ${chalk28.dim(file)}`);
2379
+ console.log(` ${chalk29.dim(file)}`);
2096
2380
  }
2097
2381
  }
2098
2382
  }
@@ -2117,29 +2401,29 @@ function parseGitLogCommits(output, ignore2, afterDate) {
2117
2401
  }
2118
2402
 
2119
2403
  // src/commands/devlog/list/printDateHeader.ts
2120
- import chalk29 from "chalk";
2404
+ import chalk30 from "chalk";
2121
2405
  function printDateHeader(date, isSkipped, entries) {
2122
2406
  if (isSkipped) {
2123
- console.log(`${chalk29.bold.blue(date)} ${chalk29.dim("skipped")}`);
2407
+ console.log(`${chalk30.bold.blue(date)} ${chalk30.dim("skipped")}`);
2124
2408
  } else if (entries && entries.length > 0) {
2125
- const entryInfo = entries.map((e) => `${chalk29.green(e.version)} ${e.title}`).join(" | ");
2126
- console.log(`${chalk29.bold.blue(date)} ${entryInfo}`);
2409
+ const entryInfo = entries.map((e) => `${chalk30.green(e.version)} ${e.title}`).join(" | ");
2410
+ console.log(`${chalk30.bold.blue(date)} ${entryInfo}`);
2127
2411
  } else {
2128
- console.log(`${chalk29.bold.blue(date)} ${chalk29.red("\u26A0 devlog missing")}`);
2412
+ console.log(`${chalk30.bold.blue(date)} ${chalk30.red("\u26A0 devlog missing")}`);
2129
2413
  }
2130
2414
  }
2131
2415
 
2132
2416
  // src/commands/devlog/list/index.ts
2133
- function list(options) {
2417
+ function list(options2) {
2134
2418
  const config = loadConfig();
2135
- const days = options.days ?? 30;
2136
- const ignore2 = options.ignore ?? config.devlog?.ignore ?? [];
2419
+ const days = options2.days ?? 30;
2420
+ const ignore2 = options2.ignore ?? config.devlog?.ignore ?? [];
2137
2421
  const skipDays = new Set(config.devlog?.skip?.days ?? []);
2138
- const repoName = basename2(process.cwd());
2422
+ const repoName = basename3(process.cwd());
2139
2423
  const devlogEntries = loadDevlogEntries(repoName);
2140
- const reverseFlag = options.reverse ? "--reverse " : "";
2141
- const limitFlag = options.reverse ? "" : "-n 500 ";
2142
- const output = execSync8(
2424
+ const reverseFlag = options2.reverse ? "--reverse " : "";
2425
+ const limitFlag = options2.reverse ? "" : "-n 500 ";
2426
+ const output = execSync11(
2143
2427
  `git log ${reverseFlag}${limitFlag}--pretty=format:'%ad|%h|%s' --date=short`,
2144
2428
  { encoding: "utf-8" }
2145
2429
  );
@@ -2147,8 +2431,8 @@ function list(options) {
2147
2431
  let dateCount = 0;
2148
2432
  let isFirst = true;
2149
2433
  for (const [date, dateCommits] of commitsByDate) {
2150
- if (options.since) {
2151
- if (date < options.since) {
2434
+ if (options2.since) {
2435
+ if (date < options2.since) {
2152
2436
  break;
2153
2437
  }
2154
2438
  } else if (dateCount >= days) {
@@ -2160,16 +2444,16 @@ function list(options) {
2160
2444
  }
2161
2445
  isFirst = false;
2162
2446
  printDateHeader(date, skipDays.has(date), devlogEntries.get(date));
2163
- printCommitsWithFiles(dateCommits, ignore2, options.verbose ?? false);
2447
+ printCommitsWithFiles(dateCommits, ignore2, options2.verbose ?? false);
2164
2448
  }
2165
2449
  }
2166
2450
 
2167
2451
  // src/commands/devlog/getLastVersionInfo.ts
2168
- import { execSync as execSync9 } from "child_process";
2452
+ import { execSync as execSync12 } from "child_process";
2169
2453
  import semver from "semver";
2170
2454
  function getVersionAtCommit(hash) {
2171
2455
  try {
2172
- const content = execSync9(`git show ${hash}:package.json`, {
2456
+ const content = execSync12(`git show ${hash}:package.json`, {
2173
2457
  encoding: "utf-8"
2174
2458
  });
2175
2459
  const pkg = JSON.parse(content);
@@ -2184,7 +2468,7 @@ function stripToMinor(version2) {
2184
2468
  }
2185
2469
  function getLastVersionInfoFromGit() {
2186
2470
  try {
2187
- const output = execSync9(
2471
+ const output = execSync12(
2188
2472
  "git log -1 --pretty=format:'%ad|%h' --date=short",
2189
2473
  {
2190
2474
  encoding: "utf-8"
@@ -2227,25 +2511,25 @@ function bumpVersion(version2, type) {
2227
2511
  }
2228
2512
 
2229
2513
  // src/commands/devlog/next/displayNextEntry/index.ts
2230
- import { execSync as execSync10 } from "child_process";
2231
- import chalk31 from "chalk";
2514
+ import { execSync as execSync13 } from "child_process";
2515
+ import chalk32 from "chalk";
2232
2516
 
2233
2517
  // src/commands/devlog/next/displayNextEntry/displayVersion.ts
2234
- import chalk30 from "chalk";
2518
+ import chalk31 from "chalk";
2235
2519
  function displayVersion(conventional, firstHash, patchVersion, minorVersion) {
2236
2520
  if (conventional && firstHash) {
2237
2521
  const version2 = getVersionAtCommit(firstHash);
2238
2522
  if (version2) {
2239
- console.log(`${chalk30.bold("version:")} ${stripToMinor(version2)}`);
2523
+ console.log(`${chalk31.bold("version:")} ${stripToMinor(version2)}`);
2240
2524
  } else {
2241
- console.log(`${chalk30.bold("version:")} ${chalk30.red("unknown")}`);
2525
+ console.log(`${chalk31.bold("version:")} ${chalk31.red("unknown")}`);
2242
2526
  }
2243
2527
  } else if (patchVersion && minorVersion) {
2244
2528
  console.log(
2245
- `${chalk30.bold("version:")} ${patchVersion} (patch) or ${minorVersion} (minor)`
2529
+ `${chalk31.bold("version:")} ${patchVersion} (patch) or ${minorVersion} (minor)`
2246
2530
  );
2247
2531
  } else {
2248
- console.log(`${chalk30.bold("version:")} v0.1 (initial)`);
2532
+ console.log(`${chalk31.bold("version:")} v0.1 (initial)`);
2249
2533
  }
2250
2534
  }
2251
2535
 
@@ -2261,7 +2545,7 @@ function findTargetDate(commitsByDate, skipDays) {
2261
2545
  return Array.from(commitsByDate.keys()).filter((d) => !skipDays.has(d)).sort()[0];
2262
2546
  }
2263
2547
  function fetchCommitsByDate(ignore2, lastDate) {
2264
- const output = execSync10(
2548
+ const output = execSync13(
2265
2549
  "git log --pretty=format:'%ad|%h|%s' --date=short -n 500",
2266
2550
  { encoding: "utf-8" }
2267
2551
  );
@@ -2276,8 +2560,8 @@ function printVersionInfo(config, lastInfo, firstHash) {
2276
2560
  versions.minor
2277
2561
  );
2278
2562
  }
2279
- function resolveIgnoreList(options, config) {
2280
- return options.ignore ?? config.devlog?.ignore ?? [];
2563
+ function resolveIgnoreList(options2, config) {
2564
+ return options2.ignore ?? config.devlog?.ignore ?? [];
2281
2565
  }
2282
2566
  function resolveSkipDays(config) {
2283
2567
  return new Set(config.devlog?.skip?.days ?? []);
@@ -2292,28 +2576,28 @@ function noCommitsMessage(hasLastInfo) {
2292
2576
  return hasLastInfo ? "No commits after last versioned entry" : "No commits found";
2293
2577
  }
2294
2578
  function logName(repoName) {
2295
- console.log(`${chalk31.bold("name:")} ${repoName}`);
2579
+ console.log(`${chalk32.bold("name:")} ${repoName}`);
2296
2580
  }
2297
2581
  function displayNextEntry(ctx, targetDate, commits) {
2298
2582
  logName(ctx.repoName);
2299
2583
  printVersionInfo(ctx.config, ctx.lastInfo, commits[0]?.hash);
2300
- console.log(chalk31.bold.blue(targetDate));
2584
+ console.log(chalk32.bold.blue(targetDate));
2301
2585
  printCommitsWithFiles(commits, ctx.ignore, ctx.verbose);
2302
2586
  }
2303
2587
  function logNoCommits(lastInfo) {
2304
- console.log(chalk31.dim(noCommitsMessage(!!lastInfo)));
2588
+ console.log(chalk32.dim(noCommitsMessage(!!lastInfo)));
2305
2589
  }
2306
2590
 
2307
2591
  // src/commands/devlog/next/index.ts
2308
- function resolveContextData(config, options) {
2592
+ function resolveContextData(config, options2) {
2309
2593
  const repoName = getRepoName();
2310
2594
  const lastInfo = getLastVersionInfo(repoName, config);
2311
- return { repoName, lastInfo, ignore: resolveIgnoreList(options, config) };
2595
+ return { repoName, lastInfo, ignore: resolveIgnoreList(options2, config) };
2312
2596
  }
2313
- function buildContext(options) {
2597
+ function buildContext(options2) {
2314
2598
  const config = loadConfig();
2315
- const data = resolveContextData(config, options);
2316
- return { config, ...data, verbose: options.verbose ?? false };
2599
+ const data = resolveContextData(config, options2);
2600
+ return { config, ...data, verbose: options2.verbose ?? false };
2317
2601
  }
2318
2602
  function fetchNextCommits(ctx) {
2319
2603
  const commitsByDate = fetchCommitsByDate(
@@ -2330,22 +2614,22 @@ function showResult(ctx, found) {
2330
2614
  }
2331
2615
  displayNextEntry(ctx, found.targetDate, found.commits);
2332
2616
  }
2333
- function next(options) {
2334
- const ctx = buildContext(options);
2617
+ function next(options2) {
2618
+ const ctx = buildContext(options2);
2335
2619
  showResult(ctx, fetchNextCommits(ctx));
2336
2620
  }
2337
2621
 
2338
2622
  // src/commands/devlog/skip.ts
2339
- import chalk32 from "chalk";
2623
+ import chalk33 from "chalk";
2340
2624
  function skip(date) {
2341
2625
  if (!/^\d{4}-\d{2}-\d{2}$/.test(date)) {
2342
- console.log(chalk32.red("Invalid date format. Use YYYY-MM-DD"));
2626
+ console.log(chalk33.red("Invalid date format. Use YYYY-MM-DD"));
2343
2627
  process.exit(1);
2344
2628
  }
2345
2629
  const config = loadConfig();
2346
2630
  const skipDays = config.devlog?.skip?.days ?? [];
2347
2631
  if (skipDays.includes(date)) {
2348
- console.log(chalk32.yellow(`${date} is already in skip list`));
2632
+ console.log(chalk33.yellow(`${date} is already in skip list`));
2349
2633
  return;
2350
2634
  }
2351
2635
  skipDays.push(date);
@@ -2358,20 +2642,20 @@ function skip(date) {
2358
2642
  }
2359
2643
  };
2360
2644
  saveConfig(config);
2361
- console.log(chalk32.green(`Added ${date} to skip list`));
2645
+ console.log(chalk33.green(`Added ${date} to skip list`));
2362
2646
  }
2363
2647
 
2364
2648
  // src/commands/devlog/version.ts
2365
- import chalk33 from "chalk";
2649
+ import chalk34 from "chalk";
2366
2650
  function version() {
2367
2651
  const config = loadConfig();
2368
2652
  const name = getRepoName();
2369
2653
  const lastInfo = getLastVersionInfo(name, config);
2370
2654
  const lastVersion = lastInfo?.version ?? null;
2371
2655
  const nextVersion = lastVersion ? bumpVersion(lastVersion, "patch") : null;
2372
- console.log(`${chalk33.bold("name:")} ${name}`);
2373
- console.log(`${chalk33.bold("last:")} ${lastVersion ?? chalk33.dim("none")}`);
2374
- console.log(`${chalk33.bold("next:")} ${nextVersion ?? chalk33.dim("none")}`);
2656
+ console.log(`${chalk34.bold("name:")} ${name}`);
2657
+ console.log(`${chalk34.bold("last:")} ${lastVersion ?? chalk34.dim("none")}`);
2658
+ console.log(`${chalk34.bold("next:")} ${nextVersion ?? chalk34.dim("none")}`);
2375
2659
  }
2376
2660
 
2377
2661
  // src/commands/registerDevlog.ts
@@ -2388,11 +2672,11 @@ function registerDevlog(program2) {
2388
2672
  }
2389
2673
 
2390
2674
  // src/commands/prs/fixed.ts
2391
- import { execSync as execSync13 } from "child_process";
2675
+ import { execSync as execSync16 } from "child_process";
2392
2676
 
2393
2677
  // src/commands/prs/resolveCommentWithReply.ts
2394
- import { execSync as execSync12 } from "child_process";
2395
- import { unlinkSync as unlinkSync3, writeFileSync as writeFileSync9 } from "fs";
2678
+ import { execSync as execSync15 } from "child_process";
2679
+ import { unlinkSync as unlinkSync3, writeFileSync as writeFileSync10 } from "fs";
2396
2680
  import { tmpdir } from "os";
2397
2681
  import { join as join10 } from "path";
2398
2682
 
@@ -2420,7 +2704,7 @@ function deleteCommentsCache(prNumber) {
2420
2704
  }
2421
2705
 
2422
2706
  // src/commands/prs/shared.ts
2423
- import { execSync as execSync11 } from "child_process";
2707
+ import { execSync as execSync14 } from "child_process";
2424
2708
  function isGhNotInstalled(error) {
2425
2709
  if (error instanceof Error) {
2426
2710
  const msg = error.message.toLowerCase();
@@ -2436,14 +2720,14 @@ function isNotFound(error) {
2436
2720
  }
2437
2721
  function getRepoInfo() {
2438
2722
  const repoInfo = JSON.parse(
2439
- execSync11("gh repo view --json owner,name", { encoding: "utf-8" })
2723
+ execSync14("gh repo view --json owner,name", { encoding: "utf-8" })
2440
2724
  );
2441
2725
  return { org: repoInfo.owner.login, repo: repoInfo.name };
2442
2726
  }
2443
2727
  function getCurrentPrNumber() {
2444
2728
  try {
2445
2729
  const prInfo = JSON.parse(
2446
- execSync11("gh pr view --json number", { encoding: "utf-8" })
2730
+ execSync14("gh pr view --json number", { encoding: "utf-8" })
2447
2731
  );
2448
2732
  return prInfo.number;
2449
2733
  } catch (error) {
@@ -2457,7 +2741,7 @@ function getCurrentPrNumber() {
2457
2741
 
2458
2742
  // src/commands/prs/resolveCommentWithReply.ts
2459
2743
  function replyToComment(org, repo, prNumber, commentId, message) {
2460
- execSync12(
2744
+ execSync15(
2461
2745
  `gh api repos/${org}/${repo}/pulls/${prNumber}/comments -f body="${message.replace(/"/g, '\\"')}" -F in_reply_to=${commentId}`,
2462
2746
  { stdio: "inherit" }
2463
2747
  );
@@ -2465,9 +2749,9 @@ function replyToComment(org, repo, prNumber, commentId, message) {
2465
2749
  function resolveThread(threadId) {
2466
2750
  const mutation = `mutation($threadId: ID!) { resolveReviewThread(input: {threadId: $threadId}) { thread { isResolved } } }`;
2467
2751
  const queryFile = join10(tmpdir(), `gh-mutation-${Date.now()}.graphql`);
2468
- writeFileSync9(queryFile, mutation);
2752
+ writeFileSync10(queryFile, mutation);
2469
2753
  try {
2470
- execSync12(
2754
+ execSync15(
2471
2755
  `gh api graphql -F query=@${queryFile} -f threadId="${threadId}"`,
2472
2756
  { stdio: "inherit" }
2473
2757
  );
@@ -2519,7 +2803,7 @@ function resolveCommentWithReply(commentId, message) {
2519
2803
  // src/commands/prs/fixed.ts
2520
2804
  function verifySha(sha) {
2521
2805
  try {
2522
- return execSync13(`git rev-parse --verify ${sha}`, {
2806
+ return execSync16(`git rev-parse --verify ${sha}`, {
2523
2807
  encoding: "utf-8"
2524
2808
  }).trim();
2525
2809
  } catch {
@@ -2545,7 +2829,7 @@ function fixed(commentId, sha) {
2545
2829
  }
2546
2830
 
2547
2831
  // src/commands/prs/listComments/index.ts
2548
- import { existsSync as existsSync13, mkdirSync as mkdirSync3, writeFileSync as writeFileSync11 } from "fs";
2832
+ import { existsSync as existsSync13, mkdirSync as mkdirSync4, writeFileSync as writeFileSync12 } from "fs";
2549
2833
  import { join as join12 } from "path";
2550
2834
  import { stringify } from "yaml";
2551
2835
 
@@ -2555,16 +2839,16 @@ function isClaudeCode() {
2555
2839
  }
2556
2840
 
2557
2841
  // src/commands/prs/fetchThreadIds.ts
2558
- import { execSync as execSync14 } from "child_process";
2559
- import { unlinkSync as unlinkSync4, writeFileSync as writeFileSync10 } from "fs";
2842
+ import { execSync as execSync17 } from "child_process";
2843
+ import { unlinkSync as unlinkSync4, writeFileSync as writeFileSync11 } from "fs";
2560
2844
  import { tmpdir as tmpdir2 } from "os";
2561
2845
  import { join as join11 } from "path";
2562
2846
  var THREAD_QUERY = `query($owner: String!, $repo: String!, $prNumber: Int!) { repository(owner: $owner, name: $repo) { pullRequest(number: $prNumber) { reviewThreads(first: 100) { nodes { id isResolved comments(first: 100) { nodes { databaseId } } } } } } }`;
2563
2847
  function fetchThreadIds(org, repo, prNumber) {
2564
2848
  const queryFile = join11(tmpdir2(), `gh-query-${Date.now()}.graphql`);
2565
- writeFileSync10(queryFile, THREAD_QUERY);
2849
+ writeFileSync11(queryFile, THREAD_QUERY);
2566
2850
  try {
2567
- const result = execSync14(
2851
+ const result = execSync17(
2568
2852
  `gh api graphql -F query=@${queryFile} -F owner="${org}" -F repo="${repo}" -F prNumber=${prNumber}`,
2569
2853
  { encoding: "utf-8" }
2570
2854
  );
@@ -2586,9 +2870,9 @@ function fetchThreadIds(org, repo, prNumber) {
2586
2870
  }
2587
2871
 
2588
2872
  // src/commands/prs/listComments/fetchReviewComments.ts
2589
- import { execSync as execSync15 } from "child_process";
2873
+ import { execSync as execSync18 } from "child_process";
2590
2874
  function fetchJson(endpoint) {
2591
- const result = execSync15(`gh api ${endpoint}`, { encoding: "utf-8" });
2875
+ const result = execSync18(`gh api ${endpoint}`, { encoding: "utf-8" });
2592
2876
  if (!result.trim()) return [];
2593
2877
  return JSON.parse(result);
2594
2878
  }
@@ -2628,20 +2912,20 @@ function fetchLineComments(org, repo, prNumber, threadInfo) {
2628
2912
  }
2629
2913
 
2630
2914
  // src/commands/prs/listComments/formatForHuman.ts
2631
- import chalk34 from "chalk";
2915
+ import chalk35 from "chalk";
2632
2916
  function formatForHuman(comment) {
2633
2917
  if (comment.type === "review") {
2634
- const stateColor = comment.state === "APPROVED" ? chalk34.green : comment.state === "CHANGES_REQUESTED" ? chalk34.red : chalk34.yellow;
2918
+ const stateColor = comment.state === "APPROVED" ? chalk35.green : comment.state === "CHANGES_REQUESTED" ? chalk35.red : chalk35.yellow;
2635
2919
  return [
2636
- `${chalk34.cyan("Review")} by ${chalk34.bold(comment.user)} ${stateColor(`[${comment.state}]`)}`,
2920
+ `${chalk35.cyan("Review")} by ${chalk35.bold(comment.user)} ${stateColor(`[${comment.state}]`)}`,
2637
2921
  comment.body,
2638
2922
  ""
2639
2923
  ].join("\n");
2640
2924
  }
2641
2925
  const location = comment.line ? `:${comment.line}` : "";
2642
2926
  return [
2643
- `${chalk34.cyan("Line comment")} by ${chalk34.bold(comment.user)} on ${chalk34.dim(`${comment.path}${location}`)}`,
2644
- chalk34.dim(comment.diff_hunk.split("\n").slice(-3).join("\n")),
2927
+ `${chalk35.cyan("Line comment")} by ${chalk35.bold(comment.user)} on ${chalk35.dim(`${comment.path}${location}`)}`,
2928
+ chalk35.dim(comment.diff_hunk.split("\n").slice(-3).join("\n")),
2645
2929
  comment.body,
2646
2930
  ""
2647
2931
  ].join("\n");
@@ -2666,7 +2950,7 @@ function printComments(comments) {
2666
2950
  function writeCommentsCache(prNumber, comments) {
2667
2951
  const assistDir = join12(process.cwd(), ".assist");
2668
2952
  if (!existsSync13(assistDir)) {
2669
- mkdirSync3(assistDir, { recursive: true });
2953
+ mkdirSync4(assistDir, { recursive: true });
2670
2954
  }
2671
2955
  const cacheData = {
2672
2956
  prNumber,
@@ -2674,7 +2958,7 @@ function writeCommentsCache(prNumber, comments) {
2674
2958
  comments
2675
2959
  };
2676
2960
  const cachePath = join12(assistDir, `pr-${prNumber}-comments.yaml`);
2677
- writeFileSync11(cachePath, stringify(cacheData));
2961
+ writeFileSync12(cachePath, stringify(cacheData));
2678
2962
  }
2679
2963
  function handleKnownErrors(error) {
2680
2964
  if (isGhNotInstalled(error)) {
@@ -2714,19 +2998,19 @@ async function listComments() {
2714
2998
  }
2715
2999
 
2716
3000
  // src/commands/prs/prs/index.ts
2717
- import { execSync as execSync16 } from "child_process";
3001
+ import { execSync as execSync19 } from "child_process";
2718
3002
 
2719
3003
  // src/commands/prs/prs/displayPaginated/index.ts
2720
3004
  import enquirer4 from "enquirer";
2721
3005
 
2722
3006
  // src/commands/prs/prs/displayPaginated/printPr.ts
2723
- import chalk35 from "chalk";
3007
+ import chalk36 from "chalk";
2724
3008
  var STATUS_MAP = {
2725
- MERGED: (pr) => pr.mergedAt ? { label: chalk35.magenta("merged"), date: pr.mergedAt } : null,
2726
- CLOSED: (pr) => pr.closedAt ? { label: chalk35.red("closed"), date: pr.closedAt } : null
3009
+ MERGED: (pr) => pr.mergedAt ? { label: chalk36.magenta("merged"), date: pr.mergedAt } : null,
3010
+ CLOSED: (pr) => pr.closedAt ? { label: chalk36.red("closed"), date: pr.closedAt } : null
2727
3011
  };
2728
3012
  function defaultStatus(pr) {
2729
- return { label: chalk35.green("opened"), date: pr.createdAt };
3013
+ return { label: chalk36.green("opened"), date: pr.createdAt };
2730
3014
  }
2731
3015
  function getStatus(pr) {
2732
3016
  return STATUS_MAP[pr.state]?.(pr) ?? defaultStatus(pr);
@@ -2735,11 +3019,11 @@ function formatDate(dateStr) {
2735
3019
  return new Date(dateStr).toISOString().split("T")[0];
2736
3020
  }
2737
3021
  function formatPrHeader(pr, status) {
2738
- return `${chalk35.cyan(`#${pr.number}`)} ${pr.title} ${chalk35.dim(`(${pr.author.login},`)} ${status.label} ${chalk35.dim(`${formatDate(status.date)})`)}`;
3022
+ return `${chalk36.cyan(`#${pr.number}`)} ${pr.title} ${chalk36.dim(`(${pr.author.login},`)} ${status.label} ${chalk36.dim(`${formatDate(status.date)})`)}`;
2739
3023
  }
2740
3024
  function logPrDetails(pr) {
2741
3025
  console.log(
2742
- chalk35.dim(` ${pr.changedFiles.toLocaleString()} files | ${pr.url}`)
3026
+ chalk36.dim(` ${pr.changedFiles.toLocaleString()} files | ${pr.url}`)
2743
3027
  );
2744
3028
  console.log();
2745
3029
  }
@@ -2817,10 +3101,10 @@ async function displayPaginated(pullRequests) {
2817
3101
  }
2818
3102
 
2819
3103
  // src/commands/prs/prs/index.ts
2820
- async function prs(options) {
2821
- const state = options.open ? "open" : options.closed ? "closed" : "all";
3104
+ async function prs(options2) {
3105
+ const state = options2.open ? "open" : options2.closed ? "closed" : "all";
2822
3106
  try {
2823
- const result = execSync16(
3107
+ const result = execSync19(
2824
3108
  `gh pr list --state ${state} --json number,title,url,author,createdAt,mergedAt,closedAt,state,changedFiles --limit 100`,
2825
3109
  { encoding: "utf-8" }
2826
3110
  );
@@ -2843,7 +3127,7 @@ async function prs(options) {
2843
3127
  }
2844
3128
 
2845
3129
  // src/commands/prs/wontfix.ts
2846
- import { execSync as execSync17 } from "child_process";
3130
+ import { execSync as execSync20 } from "child_process";
2847
3131
  function validateReason(reason) {
2848
3132
  const lowerReason = reason.toLowerCase();
2849
3133
  if (lowerReason.includes("claude") || lowerReason.includes("opus")) {
@@ -2860,7 +3144,7 @@ function validateShaReferences(reason) {
2860
3144
  const invalidShas = [];
2861
3145
  for (const sha of shas) {
2862
3146
  try {
2863
- execSync17(`git cat-file -t ${sha}`, { stdio: "pipe" });
3147
+ execSync20(`git cat-file -t ${sha}`, { stdio: "pipe" });
2864
3148
  } catch {
2865
3149
  invalidShas.push(sha);
2866
3150
  }
@@ -2902,11 +3186,11 @@ function registerPrs(program2) {
2902
3186
  }
2903
3187
 
2904
3188
  // src/commands/refactor/check/index.ts
2905
- import { spawn as spawn2 } from "child_process";
2906
- import * as path15 from "path";
3189
+ import { spawn as spawn3 } from "child_process";
3190
+ import * as path17 from "path";
2907
3191
 
2908
3192
  // src/commands/refactor/logViolations.ts
2909
- import chalk36 from "chalk";
3193
+ import chalk37 from "chalk";
2910
3194
  var DEFAULT_MAX_LINES = 100;
2911
3195
  function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
2912
3196
  if (violations.length === 0) {
@@ -2915,43 +3199,43 @@ function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
2915
3199
  }
2916
3200
  return;
2917
3201
  }
2918
- console.error(chalk36.red(`
3202
+ console.error(chalk37.red(`
2919
3203
  Refactor check failed:
2920
3204
  `));
2921
- console.error(chalk36.red(` The following files exceed ${maxLines} lines:
3205
+ console.error(chalk37.red(` The following files exceed ${maxLines} lines:
2922
3206
  `));
2923
3207
  for (const violation of violations) {
2924
- console.error(chalk36.red(` ${violation.file} (${violation.lines} lines)`));
3208
+ console.error(chalk37.red(` ${violation.file} (${violation.lines} lines)`));
2925
3209
  }
2926
3210
  console.error(
2927
- chalk36.yellow(
3211
+ chalk37.yellow(
2928
3212
  `
2929
3213
  Each file needs to be sensibly refactored, or if there is no sensible
2930
3214
  way to refactor it, ignore it with:
2931
3215
  `
2932
3216
  )
2933
3217
  );
2934
- console.error(chalk36.gray(` assist refactor ignore <file>
3218
+ console.error(chalk37.gray(` assist refactor ignore <file>
2935
3219
  `));
2936
3220
  if (process.env.CLAUDECODE) {
2937
- console.error(chalk36.cyan(`
3221
+ console.error(chalk37.cyan(`
2938
3222
  ## Extracting Code to New Files
2939
3223
  `));
2940
3224
  console.error(
2941
- chalk36.cyan(
3225
+ chalk37.cyan(
2942
3226
  ` When extracting logic from one file to another, consider where the extracted code belongs:
2943
3227
  `
2944
3228
  )
2945
3229
  );
2946
3230
  console.error(
2947
- chalk36.cyan(
3231
+ chalk37.cyan(
2948
3232
  ` 1. Keep related logic together: If the extracted code is tightly coupled to the
2949
3233
  original file's domain, create a new folder containing both the original and extracted files.
2950
3234
  `
2951
3235
  )
2952
3236
  );
2953
3237
  console.error(
2954
- chalk36.cyan(
3238
+ chalk37.cyan(
2955
3239
  ` 2. Share common utilities: If the extracted code can be reused across multiple
2956
3240
  domains, move it to a common/shared folder.
2957
3241
  `
@@ -2961,7 +3245,7 @@ Refactor check failed:
2961
3245
  }
2962
3246
 
2963
3247
  // src/commands/refactor/check/getViolations/index.ts
2964
- import { execSync as execSync18 } from "child_process";
3248
+ import { execSync as execSync21 } from "child_process";
2965
3249
  import fs15 from "fs";
2966
3250
  import { minimatch as minimatch2 } from "minimatch";
2967
3251
 
@@ -3005,31 +3289,31 @@ function countLines(filePath) {
3005
3289
  const content = fs15.readFileSync(filePath, "utf-8");
3006
3290
  return content.split("\n").length;
3007
3291
  }
3008
- function getGitFiles(options) {
3009
- if (!options.modified && !options.staged && !options.unstaged) {
3292
+ function getGitFiles(options2) {
3293
+ if (!options2.modified && !options2.staged && !options2.unstaged) {
3010
3294
  return null;
3011
3295
  }
3012
3296
  const files = /* @__PURE__ */ new Set();
3013
- if (options.staged || options.modified) {
3014
- const staged = execSync18("git diff --cached --name-only", {
3297
+ if (options2.staged || options2.modified) {
3298
+ const staged = execSync21("git diff --cached --name-only", {
3015
3299
  encoding: "utf-8"
3016
3300
  });
3017
3301
  for (const file of staged.trim().split("\n").filter(Boolean)) {
3018
3302
  files.add(file);
3019
3303
  }
3020
3304
  }
3021
- if (options.unstaged || options.modified) {
3022
- const unstaged = execSync18("git diff --name-only", { encoding: "utf-8" });
3305
+ if (options2.unstaged || options2.modified) {
3306
+ const unstaged = execSync21("git diff --name-only", { encoding: "utf-8" });
3023
3307
  for (const file of unstaged.trim().split("\n").filter(Boolean)) {
3024
3308
  files.add(file);
3025
3309
  }
3026
3310
  }
3027
3311
  return files;
3028
3312
  }
3029
- function getViolations(pattern2, options = {}, maxLines = DEFAULT_MAX_LINES) {
3313
+ function getViolations(pattern2, options2 = {}, maxLines = DEFAULT_MAX_LINES) {
3030
3314
  let sourceFiles = findSourceFiles("src", { includeTests: false });
3031
3315
  const ignoredFiles = getIgnoredFiles();
3032
- const gitFiles = getGitFiles(options);
3316
+ const gitFiles = getGitFiles(options2);
3033
3317
  if (pattern2) {
3034
3318
  sourceFiles = sourceFiles.filter((f) => minimatch2(f, pattern2));
3035
3319
  }
@@ -3048,9 +3332,9 @@ function getViolations(pattern2, options = {}, maxLines = DEFAULT_MAX_LINES) {
3048
3332
  }
3049
3333
 
3050
3334
  // src/commands/refactor/check/index.ts
3051
- function runScript(script, cwd) {
3052
- return new Promise((resolve) => {
3053
- const child = spawn2("npm", ["run", script], {
3335
+ function runScript2(script, cwd) {
3336
+ return new Promise((resolve2) => {
3337
+ const child = spawn3("npm", ["run", script], {
3054
3338
  stdio: "pipe",
3055
3339
  shell: true,
3056
3340
  cwd
@@ -3063,7 +3347,7 @@ function runScript(script, cwd) {
3063
3347
  output += data.toString();
3064
3348
  });
3065
3349
  child.on("close", (code) => {
3066
- resolve({ script, code: code ?? 1, output });
3350
+ resolve2({ script, code: code ?? 1, output });
3067
3351
  });
3068
3352
  });
3069
3353
  }
@@ -3080,9 +3364,9 @@ ${failed.length} verify script(s) failed:`);
3080
3364
  async function runVerifyQuietly() {
3081
3365
  const result = findPackageJsonWithVerifyScripts(process.cwd());
3082
3366
  if (!result) return true;
3083
- const packageDir = path15.dirname(result.packageJsonPath);
3367
+ const packageDir = path17.dirname(result.packageJsonPath);
3084
3368
  const results = await Promise.all(
3085
- result.verifyScripts.map((script) => runScript(script, packageDir))
3369
+ result.verifyScripts.map((script) => runScript2(script, packageDir))
3086
3370
  );
3087
3371
  const failed = results.filter((r) => r.code !== 0);
3088
3372
  if (failed.length > 0) {
@@ -3091,13 +3375,13 @@ async function runVerifyQuietly() {
3091
3375
  }
3092
3376
  return true;
3093
3377
  }
3094
- async function check(pattern2, options) {
3378
+ async function check(pattern2, options2) {
3095
3379
  const verifyPassed = await runVerifyQuietly();
3096
3380
  if (!verifyPassed) {
3097
3381
  process.exit(1);
3098
3382
  }
3099
- const maxLines = options.maxLines ?? DEFAULT_MAX_LINES;
3100
- const violations = getViolations(pattern2, options, maxLines);
3383
+ const maxLines = options2.maxLines ?? DEFAULT_MAX_LINES;
3384
+ const violations = getViolations(pattern2, options2, maxLines);
3101
3385
  violations.sort((a, b) => b.lines - a.lines);
3102
3386
  logViolations(violations, maxLines);
3103
3387
  if (violations.length > 0) {
@@ -3107,11 +3391,11 @@ async function check(pattern2, options) {
3107
3391
 
3108
3392
  // src/commands/refactor/ignore.ts
3109
3393
  import fs16 from "fs";
3110
- import chalk37 from "chalk";
3394
+ import chalk38 from "chalk";
3111
3395
  var REFACTOR_YML_PATH2 = "refactor.yml";
3112
3396
  function ignore(file) {
3113
3397
  if (!fs16.existsSync(file)) {
3114
- console.error(chalk37.red(`Error: File does not exist: ${file}`));
3398
+ console.error(chalk38.red(`Error: File does not exist: ${file}`));
3115
3399
  process.exit(1);
3116
3400
  }
3117
3401
  const content = fs16.readFileSync(file, "utf-8");
@@ -3127,18 +3411,18 @@ function ignore(file) {
3127
3411
  fs16.writeFileSync(REFACTOR_YML_PATH2, entry);
3128
3412
  }
3129
3413
  console.log(
3130
- chalk37.green(
3414
+ chalk38.green(
3131
3415
  `Added ${file} to refactor ignore list (max ${maxLines} lines)`
3132
3416
  )
3133
3417
  );
3134
3418
  }
3135
3419
 
3136
3420
  // src/commands/refactor/restructure/index.ts
3137
- import path24 from "path";
3138
- import chalk40 from "chalk";
3421
+ import path26 from "path";
3422
+ import chalk41 from "chalk";
3139
3423
 
3140
3424
  // src/commands/refactor/restructure/buildImportGraph/index.ts
3141
- import path16 from "path";
3425
+ import path18 from "path";
3142
3426
  import ts7 from "typescript";
3143
3427
 
3144
3428
  // src/commands/refactor/restructure/buildImportGraph/getImportSpecifiers.ts
@@ -3165,7 +3449,7 @@ function loadParsedConfig(tsConfigPath) {
3165
3449
  return ts7.parseJsonConfigFileContent(
3166
3450
  configFile.config,
3167
3451
  ts7.sys,
3168
- path16.dirname(tsConfigPath)
3452
+ path18.dirname(tsConfigPath)
3169
3453
  );
3170
3454
  }
3171
3455
  function addToSetMap(map, key, value) {
@@ -3176,12 +3460,12 @@ function addToSetMap(map, key, value) {
3176
3460
  }
3177
3461
  set.add(value);
3178
3462
  }
3179
- function resolveImport(specifier, filePath, options) {
3463
+ function resolveImport(specifier, filePath, options2) {
3180
3464
  if (!specifier.startsWith(".")) return null;
3181
- const resolved = ts7.resolveModuleName(specifier, filePath, options, ts7.sys);
3465
+ const resolved = ts7.resolveModuleName(specifier, filePath, options2, ts7.sys);
3182
3466
  const resolvedPath = resolved.resolvedModule?.resolvedFileName;
3183
3467
  if (!resolvedPath || resolvedPath.includes("node_modules")) return null;
3184
- return path16.resolve(resolvedPath);
3468
+ return path18.resolve(resolvedPath);
3185
3469
  }
3186
3470
  function buildImportGraph(candidateFiles, tsConfigPath) {
3187
3471
  const parsed = loadParsedConfig(tsConfigPath);
@@ -3190,7 +3474,7 @@ function buildImportGraph(candidateFiles, tsConfigPath) {
3190
3474
  const importedBy = /* @__PURE__ */ new Map();
3191
3475
  const imports = /* @__PURE__ */ new Map();
3192
3476
  for (const sourceFile of program2.getSourceFiles()) {
3193
- const filePath = path16.resolve(sourceFile.fileName);
3477
+ const filePath = path18.resolve(sourceFile.fileName);
3194
3478
  if (filePath.includes("node_modules")) continue;
3195
3479
  for (const specifier of getImportSpecifiers(sourceFile)) {
3196
3480
  const absTarget = resolveImport(specifier, filePath, parsed.options);
@@ -3204,12 +3488,12 @@ function buildImportGraph(candidateFiles, tsConfigPath) {
3204
3488
  }
3205
3489
 
3206
3490
  // src/commands/refactor/restructure/clusterDirectories.ts
3207
- import path17 from "path";
3491
+ import path19 from "path";
3208
3492
  function clusterDirectories(graph) {
3209
3493
  const dirImportedBy = /* @__PURE__ */ new Map();
3210
3494
  for (const edge of graph.edges) {
3211
- const sourceDir = path17.dirname(edge.source);
3212
- const targetDir = path17.dirname(edge.target);
3495
+ const sourceDir = path19.dirname(edge.source);
3496
+ const targetDir = path19.dirname(edge.target);
3213
3497
  if (sourceDir === targetDir) continue;
3214
3498
  if (!graph.files.has(edge.target)) continue;
3215
3499
  const existing = dirImportedBy.get(targetDir) ?? /* @__PURE__ */ new Set();
@@ -3237,20 +3521,20 @@ function clusterDirectories(graph) {
3237
3521
  return clusters;
3238
3522
  }
3239
3523
  function isAncestor(ancestor, descendant) {
3240
- const rel = path17.relative(ancestor, descendant);
3524
+ const rel = path19.relative(ancestor, descendant);
3241
3525
  return !rel.startsWith("..") && rel !== "";
3242
3526
  }
3243
3527
 
3244
3528
  // src/commands/refactor/restructure/clusterFiles.ts
3245
- import path18 from "path";
3529
+ import path20 from "path";
3246
3530
  function findRootParent(file, importedBy, visited) {
3247
3531
  const importers = importedBy.get(file);
3248
3532
  if (!importers || importers.size !== 1) return file;
3249
3533
  const parent = [...importers][0];
3250
- const parentDir = path18.dirname(parent);
3251
- const fileDir = path18.dirname(file);
3534
+ const parentDir = path20.dirname(parent);
3535
+ const fileDir = path20.dirname(file);
3252
3536
  if (parentDir !== fileDir) return file;
3253
- if (path18.basename(parent, path18.extname(parent)) === "index") return file;
3537
+ if (path20.basename(parent, path20.extname(parent)) === "index") return file;
3254
3538
  if (visited.has(parent)) return file;
3255
3539
  visited.add(parent);
3256
3540
  return findRootParent(parent, importedBy, visited);
@@ -3258,16 +3542,16 @@ function findRootParent(file, importedBy, visited) {
3258
3542
  function clusterFiles(graph) {
3259
3543
  const clusters = /* @__PURE__ */ new Map();
3260
3544
  for (const file of graph.files) {
3261
- const basename6 = path18.basename(file, path18.extname(file));
3262
- if (basename6 === "index") continue;
3545
+ const basename7 = path20.basename(file, path20.extname(file));
3546
+ if (basename7 === "index") continue;
3263
3547
  const importers = graph.importedBy.get(file);
3264
3548
  if (!importers || importers.size !== 1) continue;
3265
3549
  const parent = [...importers][0];
3266
3550
  if (!graph.files.has(parent)) continue;
3267
- const parentDir = path18.dirname(parent);
3268
- const fileDir = path18.dirname(file);
3551
+ const parentDir = path20.dirname(parent);
3552
+ const fileDir = path20.dirname(file);
3269
3553
  if (parentDir !== fileDir) continue;
3270
- const parentBasename = path18.basename(parent, path18.extname(parent));
3554
+ const parentBasename = path20.basename(parent, path20.extname(parent));
3271
3555
  if (parentBasename === "index") continue;
3272
3556
  const root = findRootParent(parent, graph.importedBy, /* @__PURE__ */ new Set([file]));
3273
3557
  if (!root || root === file) continue;
@@ -3279,7 +3563,7 @@ function clusterFiles(graph) {
3279
3563
  }
3280
3564
 
3281
3565
  // src/commands/refactor/restructure/computeRewrites/index.ts
3282
- import path19 from "path";
3566
+ import path21 from "path";
3283
3567
 
3284
3568
  // src/commands/refactor/restructure/computeRewrites/applyRewrites.ts
3285
3569
  import fs17 from "fs";
@@ -3333,7 +3617,7 @@ function normalizeSpecifier(rel) {
3333
3617
  );
3334
3618
  }
3335
3619
  function computeSpecifier(fromFile, toFile) {
3336
- return normalizeSpecifier(path19.relative(path19.dirname(fromFile), toFile));
3620
+ return normalizeSpecifier(path21.relative(path21.dirname(fromFile), toFile));
3337
3621
  }
3338
3622
  function isAffected(edge, moveMap) {
3339
3623
  return moveMap.has(edge.target) || moveMap.has(edge.source);
@@ -3377,51 +3661,51 @@ function computeRewrites(moves, edges, allProjectFiles) {
3377
3661
  }
3378
3662
 
3379
3663
  // src/commands/refactor/restructure/displayPlan.ts
3380
- import path20 from "path";
3381
- import chalk38 from "chalk";
3664
+ import path22 from "path";
3665
+ import chalk39 from "chalk";
3382
3666
  function relPath(filePath) {
3383
- return path20.relative(process.cwd(), filePath);
3667
+ return path22.relative(process.cwd(), filePath);
3384
3668
  }
3385
3669
  function displayMoves(plan) {
3386
3670
  if (plan.moves.length === 0) return;
3387
- console.log(chalk38.bold("\nFile moves:"));
3671
+ console.log(chalk39.bold("\nFile moves:"));
3388
3672
  for (const move of plan.moves) {
3389
3673
  console.log(
3390
- ` ${chalk38.red(relPath(move.from))} \u2192 ${chalk38.green(relPath(move.to))}`
3674
+ ` ${chalk39.red(relPath(move.from))} \u2192 ${chalk39.green(relPath(move.to))}`
3391
3675
  );
3392
- console.log(chalk38.dim(` ${move.reason}`));
3676
+ console.log(chalk39.dim(` ${move.reason}`));
3393
3677
  }
3394
3678
  }
3395
3679
  function displayRewrites(rewrites) {
3396
3680
  if (rewrites.length === 0) return;
3397
3681
  const affectedFiles = new Set(rewrites.map((r) => r.file));
3398
- console.log(chalk38.bold(`
3682
+ console.log(chalk39.bold(`
3399
3683
  Import rewrites (${affectedFiles.size} files):`));
3400
3684
  for (const file of affectedFiles) {
3401
- console.log(` ${chalk38.cyan(relPath(file))}:`);
3685
+ console.log(` ${chalk39.cyan(relPath(file))}:`);
3402
3686
  for (const { oldSpecifier, newSpecifier } of rewrites.filter(
3403
3687
  (r) => r.file === file
3404
3688
  )) {
3405
3689
  console.log(
3406
- ` ${chalk38.red(`"${oldSpecifier}"`)} \u2192 ${chalk38.green(`"${newSpecifier}"`)}`
3690
+ ` ${chalk39.red(`"${oldSpecifier}"`)} \u2192 ${chalk39.green(`"${newSpecifier}"`)}`
3407
3691
  );
3408
3692
  }
3409
3693
  }
3410
3694
  }
3411
3695
  function displayPlan(plan) {
3412
3696
  if (plan.warnings.length > 0) {
3413
- console.log(chalk38.yellow("\nWarnings:"));
3414
- for (const w of plan.warnings) console.log(chalk38.yellow(` ${w}`));
3697
+ console.log(chalk39.yellow("\nWarnings:"));
3698
+ for (const w of plan.warnings) console.log(chalk39.yellow(` ${w}`));
3415
3699
  }
3416
3700
  if (plan.newDirectories.length > 0) {
3417
- console.log(chalk38.bold("\nNew directories:"));
3701
+ console.log(chalk39.bold("\nNew directories:"));
3418
3702
  for (const dir of plan.newDirectories)
3419
- console.log(chalk38.green(` ${dir}/`));
3703
+ console.log(chalk39.green(` ${dir}/`));
3420
3704
  }
3421
3705
  displayMoves(plan);
3422
3706
  displayRewrites(plan.rewrites);
3423
3707
  console.log(
3424
- chalk38.dim(
3708
+ chalk39.dim(
3425
3709
  `
3426
3710
  Summary: ${plan.moves.length} file(s) moved, ${plan.rewrites.length} imports rewritten`
3427
3711
  )
@@ -3430,33 +3714,33 @@ Summary: ${plan.moves.length} file(s) moved, ${plan.rewrites.length} imports rew
3430
3714
 
3431
3715
  // src/commands/refactor/restructure/executePlan.ts
3432
3716
  import fs18 from "fs";
3433
- import path21 from "path";
3434
- import chalk39 from "chalk";
3717
+ import path23 from "path";
3718
+ import chalk40 from "chalk";
3435
3719
  function executePlan(plan) {
3436
3720
  const updatedContents = applyRewrites(plan.rewrites);
3437
3721
  for (const [file, content] of updatedContents) {
3438
3722
  fs18.writeFileSync(file, content, "utf-8");
3439
3723
  console.log(
3440
- chalk39.cyan(` Rewrote imports in ${path21.relative(process.cwd(), file)}`)
3724
+ chalk40.cyan(` Rewrote imports in ${path23.relative(process.cwd(), file)}`)
3441
3725
  );
3442
3726
  }
3443
3727
  for (const dir of plan.newDirectories) {
3444
3728
  fs18.mkdirSync(dir, { recursive: true });
3445
- console.log(chalk39.green(` Created ${path21.relative(process.cwd(), dir)}/`));
3729
+ console.log(chalk40.green(` Created ${path23.relative(process.cwd(), dir)}/`));
3446
3730
  }
3447
3731
  for (const move of plan.moves) {
3448
- const targetDir = path21.dirname(move.to);
3732
+ const targetDir = path23.dirname(move.to);
3449
3733
  if (!fs18.existsSync(targetDir)) {
3450
3734
  fs18.mkdirSync(targetDir, { recursive: true });
3451
3735
  }
3452
3736
  fs18.renameSync(move.from, move.to);
3453
3737
  console.log(
3454
- chalk39.white(
3455
- ` Moved ${path21.relative(process.cwd(), move.from)} \u2192 ${path21.relative(process.cwd(), move.to)}`
3738
+ chalk40.white(
3739
+ ` Moved ${path23.relative(process.cwd(), move.from)} \u2192 ${path23.relative(process.cwd(), move.to)}`
3456
3740
  )
3457
3741
  );
3458
3742
  }
3459
- removeEmptyDirectories(plan.moves.map((m) => path21.dirname(m.from)));
3743
+ removeEmptyDirectories(plan.moves.map((m) => path23.dirname(m.from)));
3460
3744
  }
3461
3745
  function removeEmptyDirectories(dirs) {
3462
3746
  const unique = [...new Set(dirs)];
@@ -3466,8 +3750,8 @@ function removeEmptyDirectories(dirs) {
3466
3750
  if (entries.length === 0) {
3467
3751
  fs18.rmdirSync(dir);
3468
3752
  console.log(
3469
- chalk39.dim(
3470
- ` Removed empty directory ${path21.relative(process.cwd(), dir)}`
3753
+ chalk40.dim(
3754
+ ` Removed empty directory ${path23.relative(process.cwd(), dir)}`
3471
3755
  )
3472
3756
  );
3473
3757
  }
@@ -3476,13 +3760,13 @@ function removeEmptyDirectories(dirs) {
3476
3760
 
3477
3761
  // src/commands/refactor/restructure/planFileMoves/index.ts
3478
3762
  import fs20 from "fs";
3479
- import path23 from "path";
3763
+ import path25 from "path";
3480
3764
 
3481
3765
  // src/commands/refactor/restructure/planFileMoves/planDirectoryMoves.ts
3482
3766
  import fs19 from "fs";
3483
- import path22 from "path";
3767
+ import path24 from "path";
3484
3768
  function collectEntry(results, dir, entry) {
3485
- const full = path22.join(dir, entry.name);
3769
+ const full = path24.join(dir, entry.name);
3486
3770
  const items = entry.isDirectory() ? listFilesRecursive(full) : [full];
3487
3771
  results.push(...items);
3488
3772
  }
@@ -3496,15 +3780,15 @@ function listFilesRecursive(dir) {
3496
3780
  }
3497
3781
  function addDirectoryFileMoves(moves, childDir, newLocation, reason) {
3498
3782
  for (const file of listFilesRecursive(childDir)) {
3499
- const rel = path22.relative(childDir, file);
3500
- moves.push({ from: file, to: path22.join(newLocation, rel), reason });
3783
+ const rel = path24.relative(childDir, file);
3784
+ moves.push({ from: file, to: path24.join(newLocation, rel), reason });
3501
3785
  }
3502
3786
  }
3503
3787
  function resolveChildDest(parentDir, childDir) {
3504
- return path22.join(parentDir, path22.basename(childDir));
3788
+ return path24.join(parentDir, path24.basename(childDir));
3505
3789
  }
3506
3790
  function childMoveReason(parentDir) {
3507
- return `Directory only imported from ${path22.basename(parentDir)}/`;
3791
+ return `Directory only imported from ${path24.basename(parentDir)}/`;
3508
3792
  }
3509
3793
  function registerDirectoryMove(result, childDir, dest, parentDir) {
3510
3794
  result.directories.push(dest);
@@ -3532,7 +3816,7 @@ function emptyResult() {
3532
3816
  return { moves: [], directories: [], warnings: [] };
3533
3817
  }
3534
3818
  function childMoveData(child, newDir, parentBase) {
3535
- const to = path23.join(newDir, path23.basename(child));
3819
+ const to = path25.join(newDir, path25.basename(child));
3536
3820
  return { from: child, to, reason: `Only imported by ${parentBase}` };
3537
3821
  }
3538
3822
  function addChildMoves(moves, children, newDir, parentBase) {
@@ -3545,15 +3829,15 @@ function checkDirConflict(result, label, dir) {
3545
3829
  return true;
3546
3830
  }
3547
3831
  function getBaseName(filePath) {
3548
- return path23.basename(filePath, path23.extname(filePath));
3832
+ return path25.basename(filePath, path25.extname(filePath));
3549
3833
  }
3550
3834
  function resolveClusterDir(parent) {
3551
- return path23.join(path23.dirname(parent), getBaseName(parent));
3835
+ return path25.join(path25.dirname(parent), getBaseName(parent));
3552
3836
  }
3553
3837
  function createParentMove(parent, newDir) {
3554
3838
  return {
3555
3839
  from: parent,
3556
- to: path23.join(newDir, `index${path23.extname(parent)}`),
3840
+ to: path25.join(newDir, `index${path25.extname(parent)}`),
3557
3841
  reason: `Main module of new ${getBaseName(parent)}/ directory`
3558
3842
  };
3559
3843
  }
@@ -3577,7 +3861,7 @@ function planFileMoves(clusters) {
3577
3861
 
3578
3862
  // src/commands/refactor/restructure/index.ts
3579
3863
  function buildPlan(candidateFiles, tsConfigPath) {
3580
- const candidates = new Set(candidateFiles.map((f) => path24.resolve(f)));
3864
+ const candidates = new Set(candidateFiles.map((f) => path26.resolve(f)));
3581
3865
  const graph = buildImportGraph(candidates, tsConfigPath);
3582
3866
  const allProjectFiles = /* @__PURE__ */ new Set([
3583
3867
  ...graph.importedBy.keys(),
@@ -3593,26 +3877,26 @@ function buildPlan(candidateFiles, tsConfigPath) {
3593
3877
  const rewrites = computeRewrites(moves, graph.edges, allProjectFiles);
3594
3878
  return { moves, rewrites, newDirectories: directories, warnings };
3595
3879
  }
3596
- async function restructure(pattern2, options = {}) {
3880
+ async function restructure(pattern2, options2 = {}) {
3597
3881
  const targetPattern = pattern2 ?? "src";
3598
3882
  const files = findSourceFiles2(targetPattern);
3599
3883
  if (files.length === 0) {
3600
- console.log(chalk40.yellow("No files found matching pattern"));
3884
+ console.log(chalk41.yellow("No files found matching pattern"));
3601
3885
  return;
3602
3886
  }
3603
- const tsConfigPath = path24.resolve("tsconfig.json");
3887
+ const tsConfigPath = path26.resolve("tsconfig.json");
3604
3888
  const plan = buildPlan(files, tsConfigPath);
3605
3889
  if (plan.moves.length === 0) {
3606
- console.log(chalk40.green("No restructuring needed"));
3890
+ console.log(chalk41.green("No restructuring needed"));
3607
3891
  return;
3608
3892
  }
3609
3893
  displayPlan(plan);
3610
- if (options.apply) {
3611
- console.log(chalk40.bold("\nApplying changes..."));
3894
+ if (options2.apply) {
3895
+ console.log(chalk41.bold("\nApplying changes..."));
3612
3896
  executePlan(plan);
3613
- console.log(chalk40.green("\nRestructuring complete"));
3897
+ console.log(chalk41.green("\nRestructuring complete"));
3614
3898
  } else {
3615
- console.log(chalk40.dim("\nDry run. Use --apply to execute."));
3899
+ console.log(chalk41.dim("\nDry run. Use --apply to execute."));
3616
3900
  }
3617
3901
  }
3618
3902
 
@@ -3636,7 +3920,7 @@ function registerRefactor(program2) {
3636
3920
 
3637
3921
  // src/commands/transcript/shared.ts
3638
3922
  import { existsSync as existsSync14, readdirSync as readdirSync2, statSync } from "fs";
3639
- import { basename as basename3, join as join13, relative } from "path";
3923
+ import { basename as basename4, join as join13, relative } from "path";
3640
3924
  import * as readline2 from "readline";
3641
3925
  var DATE_PREFIX_REGEX = /^\d{4}-\d{2}-\d{2}/;
3642
3926
  function getDatePrefix(daysOffset = 0) {
@@ -3667,7 +3951,7 @@ function toFileInfo(baseDir, fullPath) {
3667
3951
  return {
3668
3952
  absolutePath: fullPath,
3669
3953
  relativePath: relative(baseDir, fullPath),
3670
- filename: basename3(fullPath)
3954
+ filename: basename4(fullPath)
3671
3955
  };
3672
3956
  }
3673
3957
  function findVttFilesRecursive(dir, baseDir = dir) {
@@ -3677,7 +3961,7 @@ function findMdFilesRecursive(dir, baseDir = dir) {
3677
3961
  return collectFiles(dir, ".md").map((f) => toFileInfo(baseDir, f));
3678
3962
  }
3679
3963
  function getTranscriptBaseName(transcriptFile) {
3680
- return basename3(transcriptFile, ".md").replace(/ Transcription$/, "");
3964
+ return basename4(transcriptFile, ".md").replace(/ Transcription$/, "");
3681
3965
  }
3682
3966
  function createReadlineInterface() {
3683
3967
  return readline2.createInterface({
@@ -3686,9 +3970,9 @@ function createReadlineInterface() {
3686
3970
  });
3687
3971
  }
3688
3972
  function askQuestion(rl, question) {
3689
- return new Promise((resolve) => {
3973
+ return new Promise((resolve2) => {
3690
3974
  rl.question(question, (answer) => {
3691
- resolve(answer.trim());
3975
+ resolve2(answer.trim());
3692
3976
  });
3693
3977
  });
3694
3978
  }
@@ -3751,7 +4035,7 @@ async function configure() {
3751
4035
  import { existsSync as existsSync16 } from "fs";
3752
4036
 
3753
4037
  // src/commands/transcript/format/fixInvalidDatePrefixes/index.ts
3754
- import { dirname as dirname10, join as join15 } from "path";
4038
+ import { dirname as dirname12, join as join15 } from "path";
3755
4039
 
3756
4040
  // src/commands/transcript/format/fixInvalidDatePrefixes/promptForDateFix.ts
3757
4041
  import { renameSync } from "fs";
@@ -3801,11 +4085,11 @@ async function fixInvalidDatePrefixes(vttFiles) {
3801
4085
  for (let i = 0; i < vttFiles.length; i++) {
3802
4086
  const vttFile = vttFiles[i];
3803
4087
  if (!isValidDatePrefix(vttFile.filename)) {
3804
- const vttFileDir = dirname10(vttFile.absolutePath);
4088
+ const vttFileDir = dirname12(vttFile.absolutePath);
3805
4089
  const newFilename = await promptForDateFix(vttFile.filename, vttFileDir);
3806
4090
  if (newFilename) {
3807
4091
  const newRelativePath = join15(
3808
- dirname10(vttFile.relativePath),
4092
+ dirname12(vttFile.relativePath),
3809
4093
  newFilename
3810
4094
  );
3811
4095
  vttFiles[i] = {
@@ -3822,8 +4106,8 @@ async function fixInvalidDatePrefixes(vttFiles) {
3822
4106
  }
3823
4107
 
3824
4108
  // src/commands/transcript/format/processVttFile/index.ts
3825
- import { existsSync as existsSync15, mkdirSync as mkdirSync4, readFileSync as readFileSync12, writeFileSync as writeFileSync12 } from "fs";
3826
- import { basename as basename4, dirname as dirname11, join as join16 } from "path";
4109
+ import { existsSync as existsSync15, mkdirSync as mkdirSync5, readFileSync as readFileSync12, writeFileSync as writeFileSync13 } from "fs";
4110
+ import { basename as basename5, dirname as dirname13, join as join16 } from "path";
3827
4111
 
3828
4112
  // src/commands/transcript/cleanText.ts
3829
4113
  function cleanText(text) {
@@ -4030,14 +4314,14 @@ function formatChatLog(messages) {
4030
4314
 
4031
4315
  // src/commands/transcript/format/processVttFile/index.ts
4032
4316
  function toMdFilename(vttFilename) {
4033
- return `${basename4(vttFilename, ".vtt").replace(/\s*Transcription\s*/g, " ").trim()}.md`;
4317
+ return `${basename5(vttFilename, ".vtt").replace(/\s*Transcription\s*/g, " ").trim()}.md`;
4034
4318
  }
4035
4319
  function resolveOutputDir(relativeDir, transcriptsDir) {
4036
4320
  return relativeDir === "." ? transcriptsDir : join16(transcriptsDir, relativeDir);
4037
4321
  }
4038
4322
  function buildOutputPaths(vttFile, transcriptsDir) {
4039
4323
  const mdFile = toMdFilename(vttFile.filename);
4040
- const relativeDir = dirname11(vttFile.relativePath);
4324
+ const relativeDir = dirname13(vttFile.relativePath);
4041
4325
  const outputDir = resolveOutputDir(relativeDir, transcriptsDir);
4042
4326
  const outputPath = join16(outputDir, mdFile);
4043
4327
  return { outputDir, outputPath, mdFile, relativeDir };
@@ -4048,7 +4332,7 @@ function logSkipped(relativeDir, mdFile) {
4048
4332
  }
4049
4333
  function ensureDirectory(dir, label) {
4050
4334
  if (!existsSync15(dir)) {
4051
- mkdirSync4(dir, { recursive: true });
4335
+ mkdirSync5(dir, { recursive: true });
4052
4336
  console.log(`Created ${label}: ${dir}`);
4053
4337
  }
4054
4338
  }
@@ -4073,7 +4357,7 @@ function readAndParseCues(inputPath) {
4073
4357
  return processCues(readFileSync12(inputPath, "utf-8"));
4074
4358
  }
4075
4359
  function writeFormatted(outputPath, content) {
4076
- writeFileSync12(outputPath, content, "utf-8");
4360
+ writeFileSync13(outputPath, content, "utf-8");
4077
4361
  console.log(`Written: ${outputPath}`);
4078
4362
  }
4079
4363
  function convertVttToMarkdown(inputPath, outputPath) {
@@ -4142,27 +4426,27 @@ async function format() {
4142
4426
 
4143
4427
  // src/commands/transcript/summarise/index.ts
4144
4428
  import { existsSync as existsSync18 } from "fs";
4145
- import { basename as basename5, dirname as dirname13, join as join18, relative as relative2 } from "path";
4429
+ import { basename as basename6, dirname as dirname15, join as join18, relative as relative2 } from "path";
4146
4430
 
4147
4431
  // src/commands/transcript/summarise/processStagedFile/index.ts
4148
4432
  import {
4149
4433
  existsSync as existsSync17,
4150
- mkdirSync as mkdirSync5,
4434
+ mkdirSync as mkdirSync6,
4151
4435
  readFileSync as readFileSync13,
4152
4436
  renameSync as renameSync2,
4153
4437
  rmSync
4154
4438
  } from "fs";
4155
- import { dirname as dirname12, join as join17 } from "path";
4439
+ import { dirname as dirname14, join as join17 } from "path";
4156
4440
 
4157
4441
  // src/commands/transcript/summarise/processStagedFile/validateStagedContent.ts
4158
- import chalk41 from "chalk";
4442
+ import chalk42 from "chalk";
4159
4443
  var FULL_TRANSCRIPT_REGEX = /^\[Full Transcript\]\(([^)]+)\)/;
4160
4444
  function validateStagedContent(filename, content) {
4161
4445
  const firstLine = content.split("\n")[0];
4162
4446
  const match = firstLine.match(FULL_TRANSCRIPT_REGEX);
4163
4447
  if (!match) {
4164
4448
  console.error(
4165
- chalk41.red(
4449
+ chalk42.red(
4166
4450
  `Staged file ${filename} missing [Full Transcript](<path>) link on first line.`
4167
4451
  )
4168
4452
  );
@@ -4171,7 +4455,7 @@ function validateStagedContent(filename, content) {
4171
4455
  const contentAfterLink = content.slice(firstLine.length).trim();
4172
4456
  if (!contentAfterLink) {
4173
4457
  console.error(
4174
- chalk41.red(
4458
+ chalk42.red(
4175
4459
  `Staged file ${filename} has no summary content after the transcript link.`
4176
4460
  )
4177
4461
  );
@@ -4206,9 +4490,9 @@ function processStagedFile() {
4206
4490
  process.exit(1);
4207
4491
  }
4208
4492
  const destPath = join17(summaryDir, matchingTranscript.relativePath);
4209
- const destDir = dirname12(destPath);
4493
+ const destDir = dirname14(destPath);
4210
4494
  if (!existsSync17(destDir)) {
4211
- mkdirSync5(destDir, { recursive: true });
4495
+ mkdirSync6(destDir, { recursive: true });
4212
4496
  }
4213
4497
  renameSync2(stagedFile.absolutePath, destPath);
4214
4498
  const remaining = findMdFilesRecursive(STAGING_DIR);
@@ -4220,14 +4504,14 @@ function processStagedFile() {
4220
4504
 
4221
4505
  // src/commands/transcript/summarise/index.ts
4222
4506
  function buildRelativeKey(relativePath, baseName) {
4223
- const relDir = dirname13(relativePath);
4507
+ const relDir = dirname15(relativePath);
4224
4508
  return relDir === "." ? baseName : join18(relDir, baseName);
4225
4509
  }
4226
4510
  function buildSummaryIndex(summaryDir) {
4227
4511
  const summaryFiles = findMdFilesRecursive(summaryDir);
4228
4512
  return new Set(
4229
4513
  summaryFiles.map(
4230
- (f) => buildRelativeKey(f.relativePath, basename5(f.filename, ".md"))
4514
+ (f) => buildRelativeKey(f.relativePath, basename6(f.filename, ".md"))
4231
4515
  )
4232
4516
  );
4233
4517
  }
@@ -4256,7 +4540,7 @@ function summarise() {
4256
4540
  const next2 = missing[0];
4257
4541
  const outputFilename = `${getTranscriptBaseName(next2.filename)}.md`;
4258
4542
  const outputPath = join18(STAGING_DIR, outputFilename);
4259
- const summaryFileDir = join18(summaryDir, dirname13(next2.relativePath));
4543
+ const summaryFileDir = join18(summaryDir, dirname15(next2.relativePath));
4260
4544
  const relativeTranscriptPath = encodeURI(
4261
4545
  relative2(summaryFileDir, next2.absolutePath).replace(/\\/g, "/")
4262
4546
  );
@@ -4280,161 +4564,9 @@ function registerTranscript(program2) {
4280
4564
  transcriptCommand.command("summarise").description("List transcripts that do not have summaries").action(summarise);
4281
4565
  }
4282
4566
 
4283
- // src/commands/verify/hardcodedColors.ts
4284
- import { execSync as execSync19 } from "child_process";
4285
- var pattern = "0x[0-9a-fA-F]{6}|#[0-9a-fA-F]{3,6}";
4286
- function hardcodedColors() {
4287
- try {
4288
- const output = execSync19(`grep -rEnH '${pattern}' src/`, {
4289
- encoding: "utf-8"
4290
- });
4291
- const lines = output.trim().split("\n");
4292
- console.log("Hardcoded colors found:\n");
4293
- for (const line of lines) {
4294
- const match = line.match(/^(.+):(\d+):(.+)$/);
4295
- if (match) {
4296
- const [, file, lineNum, content] = match;
4297
- const colorMatch = content.match(/0x[0-9a-fA-F]{6}|#[0-9a-fA-F]{3,6}/);
4298
- const color = colorMatch?.[0] ?? "unknown";
4299
- console.log(`${file}:${lineNum} \u2192 ${color}`);
4300
- }
4301
- }
4302
- console.log(`
4303
- Total: ${lines.length} hardcoded color(s)`);
4304
- console.log("\nUse colors from the 'open-color' (oc) library instead.");
4305
- console.log("\nExample fix:");
4306
- console.log(" Before: color: '#228be6'");
4307
- console.log(" After: color: oc.blue[6]");
4308
- console.log("\nImport open-color with: import oc from 'open-color'");
4309
- process.exit(1);
4310
- } catch {
4311
- console.log("No hardcoded colors found.");
4312
- process.exit(0);
4313
- }
4314
- }
4315
-
4316
- // src/commands/verify/run/index.ts
4317
- import { spawn as spawn3 } from "child_process";
4318
- import * as path25 from "path";
4319
-
4320
- // src/commands/verify/run/createTimerCallback/printTaskStatuses.ts
4321
- function formatDuration(ms) {
4322
- if (ms < 1e3) {
4323
- return `${ms}ms`;
4324
- }
4325
- const seconds = (ms / 1e3).toFixed(1);
4326
- return `${seconds}s`;
4327
- }
4328
- function printTaskStatuses(tasks) {
4329
- console.log("\n--- Task Status ---");
4330
- for (const task of tasks) {
4331
- if (task.endTime !== void 0) {
4332
- const duration = formatDuration(task.endTime - task.startTime);
4333
- const status = task.code === 0 ? "\u2713" : "\u2717";
4334
- console.log(` ${status} ${task.script}: ${duration}`);
4335
- } else {
4336
- const elapsed = formatDuration(Date.now() - task.startTime);
4337
- console.log(` \u22EF ${task.script}: running (${elapsed})`);
4338
- }
4339
- }
4340
- console.log("-------------------\n");
4341
- }
4342
-
4343
- // src/commands/verify/run/createTimerCallback/index.ts
4344
- function logFailedScripts(failed) {
4345
- console.error(`
4346
- ${failed.length} script(s) failed:`);
4347
- for (const f of failed) {
4348
- console.error(` - ${f.script} (exit code ${f.code})`);
4349
- }
4350
- }
4351
- function createTimerCallback(taskStatuses, index) {
4352
- return (exitCode) => {
4353
- taskStatuses[index].endTime = Date.now();
4354
- taskStatuses[index].code = exitCode;
4355
- printTaskStatuses(taskStatuses);
4356
- };
4357
- }
4358
- function initTaskStatuses(scripts) {
4359
- return scripts.map((script) => ({ script, startTime: Date.now() }));
4360
- }
4361
-
4362
- // src/commands/verify/run/index.ts
4363
- function spawnScript(script, cwd) {
4364
- return spawn3("npm", ["run", script], { stdio: "inherit", shell: true, cwd });
4365
- }
4366
- function onScriptClose(script, onComplete, resolve) {
4367
- return (code) => {
4368
- const exitCode = code ?? 1;
4369
- onComplete?.(exitCode);
4370
- resolve({ script, code: exitCode });
4371
- };
4372
- }
4373
- function runScript2(script, cwd, onComplete) {
4374
- return new Promise((resolve) => {
4375
- spawnScript(script, cwd).on(
4376
- "close",
4377
- onScriptClose(script, onComplete, resolve)
4378
- );
4379
- });
4380
- }
4381
- function runAllScripts(verifyScripts, packageDir, timer) {
4382
- const taskStatuses = initTaskStatuses(verifyScripts);
4383
- return Promise.all(
4384
- verifyScripts.map(
4385
- (script, index) => runScript2(
4386
- script,
4387
- packageDir,
4388
- timer ? createTimerCallback(taskStatuses, index) : void 0
4389
- )
4390
- )
4391
- );
4392
- }
4393
- function printScriptList(scripts) {
4394
- console.log(`Running ${scripts.length} verify script(s) in parallel:`);
4395
- for (const script of scripts) {
4396
- console.log(` - ${script}`);
4397
- }
4398
- }
4399
- function exitIfFailed(failed) {
4400
- if (failed.length === 0) return;
4401
- logFailedScripts(failed);
4402
- process.exit(1);
4403
- }
4404
- function handleResults(results, totalCount) {
4405
- exitIfFailed(results.filter((r) => r.code !== 0));
4406
- console.log(`
4407
- All ${totalCount} verify script(s) passed`);
4408
- }
4409
- function resolveVerifyScripts() {
4410
- const result = findPackageJsonWithVerifyScripts(process.cwd());
4411
- if (!result) {
4412
- console.log("No package.json with verify:* scripts found");
4413
- return null;
4414
- }
4415
- return result;
4416
- }
4417
- function getPackageDir(found) {
4418
- return path25.dirname(found.packageJsonPath);
4419
- }
4420
- async function executeVerifyScripts(found, timer) {
4421
- printScriptList(found.verifyScripts);
4422
- const results = await runAllScripts(
4423
- found.verifyScripts,
4424
- getPackageDir(found),
4425
- timer
4426
- );
4427
- handleResults(results, found.verifyScripts.length);
4428
- }
4429
- async function run(options = {}) {
4430
- const found = resolveVerifyScripts();
4431
- if (!found) return;
4432
- await executeVerifyScripts(found, options.timer ?? false);
4433
- }
4434
-
4435
4567
  // src/commands/registerVerify.ts
4436
4568
  function registerVerify(program2) {
4437
- const verifyCommand = program2.command("verify").description("Run all verify:* scripts from package.json in parallel").option("--timer", "Show timing information for each task as they complete").action((options) => run(options));
4569
+ const verifyCommand = program2.command("verify").description("Run all verify:* scripts from package.json in parallel").option("--timer", "Show timing information for each task as they complete").action((options2) => run(options2));
4438
4570
  verifyCommand.command("init").description("Add verify scripts to a project").action(init2);
4439
4571
  verifyCommand.command("hardcoded-colors").description("Check for hardcoded hex colors in src/").action(hardcodedColors);
4440
4572
  }
@@ -4570,27 +4702,27 @@ async function statusLine() {
4570
4702
  // src/commands/sync.ts
4571
4703
  import * as fs23 from "fs";
4572
4704
  import * as os from "os";
4573
- import * as path28 from "path";
4705
+ import * as path29 from "path";
4574
4706
  import { fileURLToPath as fileURLToPath3 } from "url";
4575
4707
 
4576
4708
  // src/commands/sync/syncClaudeMd.ts
4577
4709
  import * as fs21 from "fs";
4578
- import * as path26 from "path";
4579
- import chalk42 from "chalk";
4710
+ import * as path27 from "path";
4711
+ import chalk43 from "chalk";
4580
4712
  async function syncClaudeMd(claudeDir, targetBase) {
4581
- const source = path26.join(claudeDir, "CLAUDE.md");
4582
- const target = path26.join(targetBase, "CLAUDE.md");
4713
+ const source = path27.join(claudeDir, "CLAUDE.md");
4714
+ const target = path27.join(targetBase, "CLAUDE.md");
4583
4715
  const sourceContent = fs21.readFileSync(source, "utf-8");
4584
4716
  if (fs21.existsSync(target)) {
4585
4717
  const targetContent = fs21.readFileSync(target, "utf-8");
4586
4718
  if (sourceContent !== targetContent) {
4587
4719
  console.log(
4588
- chalk42.yellow("\n\u26A0\uFE0F Warning: CLAUDE.md differs from existing file")
4720
+ chalk43.yellow("\n\u26A0\uFE0F Warning: CLAUDE.md differs from existing file")
4589
4721
  );
4590
4722
  console.log();
4591
4723
  printDiff(targetContent, sourceContent);
4592
4724
  const confirm = await promptConfirm(
4593
- chalk42.red("Overwrite existing CLAUDE.md?"),
4725
+ chalk43.red("Overwrite existing CLAUDE.md?"),
4594
4726
  false
4595
4727
  );
4596
4728
  if (!confirm) {
@@ -4605,11 +4737,11 @@ async function syncClaudeMd(claudeDir, targetBase) {
4605
4737
 
4606
4738
  // src/commands/sync/syncSettings.ts
4607
4739
  import * as fs22 from "fs";
4608
- import * as path27 from "path";
4609
- import chalk43 from "chalk";
4740
+ import * as path28 from "path";
4741
+ import chalk44 from "chalk";
4610
4742
  async function syncSettings(claudeDir, targetBase) {
4611
- const source = path27.join(claudeDir, "settings.json");
4612
- const target = path27.join(targetBase, "settings.json");
4743
+ const source = path28.join(claudeDir, "settings.json");
4744
+ const target = path28.join(targetBase, "settings.json");
4613
4745
  const sourceContent = fs22.readFileSync(source, "utf-8");
4614
4746
  const normalizedSource = JSON.stringify(JSON.parse(sourceContent), null, 2);
4615
4747
  if (fs22.existsSync(target)) {
@@ -4617,12 +4749,12 @@ async function syncSettings(claudeDir, targetBase) {
4617
4749
  const normalizedTarget = JSON.stringify(JSON.parse(targetContent), null, 2);
4618
4750
  if (normalizedSource !== normalizedTarget) {
4619
4751
  console.log(
4620
- chalk43.yellow("\n\u26A0\uFE0F Warning: settings.json differs from existing file")
4752
+ chalk44.yellow("\n\u26A0\uFE0F Warning: settings.json differs from existing file")
4621
4753
  );
4622
4754
  console.log();
4623
4755
  printDiff(targetContent, sourceContent);
4624
4756
  const confirm = await promptConfirm(
4625
- chalk43.red("Overwrite existing settings.json?"),
4757
+ chalk44.red("Overwrite existing settings.json?"),
4626
4758
  false
4627
4759
  );
4628
4760
  if (!confirm) {
@@ -4637,21 +4769,21 @@ async function syncSettings(claudeDir, targetBase) {
4637
4769
 
4638
4770
  // src/commands/sync.ts
4639
4771
  var __filename2 = fileURLToPath3(import.meta.url);
4640
- var __dirname4 = path28.dirname(__filename2);
4772
+ var __dirname4 = path29.dirname(__filename2);
4641
4773
  async function sync() {
4642
- const claudeDir = path28.join(__dirname4, "..", "claude");
4643
- const targetBase = path28.join(os.homedir(), ".claude");
4774
+ const claudeDir = path29.join(__dirname4, "..", "claude");
4775
+ const targetBase = path29.join(os.homedir(), ".claude");
4644
4776
  syncCommands(claudeDir, targetBase);
4645
4777
  await syncSettings(claudeDir, targetBase);
4646
4778
  await syncClaudeMd(claudeDir, targetBase);
4647
4779
  }
4648
4780
  function syncCommands(claudeDir, targetBase) {
4649
- const sourceDir = path28.join(claudeDir, "commands");
4650
- const targetDir = path28.join(targetBase, "commands");
4781
+ const sourceDir = path29.join(claudeDir, "commands");
4782
+ const targetDir = path29.join(targetBase, "commands");
4651
4783
  fs23.mkdirSync(targetDir, { recursive: true });
4652
4784
  const files = fs23.readdirSync(sourceDir);
4653
4785
  for (const file of files) {
4654
- fs23.copyFileSync(path28.join(sourceDir, file), path28.join(targetDir, file));
4786
+ fs23.copyFileSync(path29.join(sourceDir, file), path29.join(targetDir, file));
4655
4787
  console.log(`Copied ${file} to ${targetDir}`);
4656
4788
  }
4657
4789
  console.log(`Synced ${files.length} command(s) to ~/.claude/commands`);
@@ -4665,7 +4797,7 @@ program.command("init").description("Initialize VS Code and verify configuration
4665
4797
  program.command("commit <message>").description("Create a git commit with validation").action(commit);
4666
4798
  program.command("update").description("Update claude-code to the latest version").action(() => {
4667
4799
  console.log("Updating claude-code...");
4668
- execSync20("npm install -g @anthropic-ai/claude-code", { stdio: "inherit" });
4800
+ execSync22("npm install -g @anthropic-ai/claude-code", { stdio: "inherit" });
4669
4801
  });
4670
4802
  var configCommand = program.command("config").description("View and modify assist.yml configuration");
4671
4803
  configCommand.command("set <key> <value>").description("Set a config value (e.g. commit.push true)").action(configSet);
@@ -4675,7 +4807,7 @@ var runCommand = program.command("run").description("Run a configured command fr
4675
4807
  run2(name, args);
4676
4808
  });
4677
4809
  runCommand.command("add").description("Add a new run configuration to assist.yml").allowUnknownOption().allowExcessArguments().action(() => add());
4678
- program.command("new").description("Initialize a new Vite React TypeScript project").action(newProject);
4810
+ registerNew(program);
4679
4811
  var lintCommand = program.command("lint").description("Run lint checks for conventions not enforced by biomejs").action(lint);
4680
4812
  lintCommand.command("init").description("Initialize Biome with standard linter config").action(init);
4681
4813
  var vscodeCommand = program.command("vscode").description("VS Code configuration utilities");