viberails 0.6.7 → 0.6.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,14 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/index.ts
4
- import chalk16 from "chalk";
4
+ import chalk17 from "chalk";
5
5
  import { Command } from "commander";
6
6
 
7
7
  // src/commands/boundaries.ts
8
8
  import * as fs3 from "fs";
9
9
  import * as path3 from "path";
10
10
  import { compactConfig, loadConfig } from "@viberails/config";
11
- import chalk from "chalk";
11
+ import chalk2 from "chalk";
12
12
 
13
13
  // src/utils/find-project-root.ts
14
14
  import * as fs from "fs";
@@ -57,6 +57,7 @@ var HINT_AUTO_DETECT = "auto-detect";
57
57
 
58
58
  // src/utils/prompt-submenus.ts
59
59
  import * as clack from "@clack/prompts";
60
+ import chalk from "chalk";
60
61
  var FILE_NAMING_OPTIONS = [
61
62
  { value: "kebab-case", label: "kebab-case" },
62
63
  { value: "camelCase", label: "camelCase" },
@@ -120,7 +121,7 @@ async function promptNamingMenu(state) {
120
121
  {
121
122
  value: "enforceNaming",
122
123
  label: "Enforce file naming",
123
- hint: state.enforceNaming ? "yes" : "no"
124
+ hint: state.enforceNaming ? chalk.green("yes") : chalk.dim("no")
124
125
  }
125
126
  ];
126
127
  if (state.enforceNaming) {
@@ -238,7 +239,7 @@ async function promptTestingMenu(state) {
238
239
  {
239
240
  value: "enforceMissingTests",
240
241
  label: "Enforce missing tests",
241
- hint: state.enforceMissingTests ? "yes" : "no"
242
+ hint: state.enforceMissingTests ? chalk.green("yes") : chalk.dim("no")
242
243
  },
243
244
  {
244
245
  value: "testCoverage",
@@ -734,48 +735,48 @@ async function boundariesCommand(options, cwd) {
734
735
  }
735
736
  function displayRules(config) {
736
737
  if (!config.boundaries || Object.keys(config.boundaries.deny).length === 0) {
737
- console.log(chalk.yellow("No boundary rules configured."));
738
- console.log(`Run ${chalk.cyan("viberails boundaries --infer")} to generate rules.`);
738
+ console.log(chalk2.yellow("No boundary rules configured."));
739
+ console.log(`Run ${chalk2.cyan("viberails boundaries --infer")} to generate rules.`);
739
740
  return;
740
741
  }
741
742
  const { deny } = config.boundaries;
742
743
  const sources = Object.keys(deny).filter((k) => deny[k].length > 0);
743
744
  const totalRules = sources.reduce((sum, k) => sum + deny[k].length, 0);
744
745
  console.log(`
745
- ${chalk.bold(`Boundary rules (${totalRules} deny rules):`)}
746
+ ${chalk2.bold(`Boundary rules (${totalRules} deny rules):`)}
746
747
  `);
747
748
  for (const source of sources) {
748
749
  for (const target of deny[source]) {
749
- console.log(` ${chalk.red("\u2717")} ${source} \u2192 ${target}`);
750
+ console.log(` ${chalk2.red("\u2717")} ${source} \u2192 ${target}`);
750
751
  }
751
752
  }
752
753
  console.log(
753
754
  `
754
- Enforcement: ${config.rules.enforceBoundaries ? chalk.green("on") : chalk.yellow("off")}`
755
+ Enforcement: ${config.rules.enforceBoundaries ? chalk2.green("on") : chalk2.yellow("off")}`
755
756
  );
756
757
  }
757
758
  async function inferAndDisplay(projectRoot, config, configPath) {
758
- console.log(chalk.dim("Analyzing imports..."));
759
+ console.log(chalk2.dim("Analyzing imports..."));
759
760
  const { buildImportGraph, inferBoundaries } = await import("@viberails/graph");
760
761
  const packages = config.packages.length > 1 ? resolveWorkspacePackages(projectRoot, config.packages) : void 0;
761
762
  const graph = await buildImportGraph(projectRoot, {
762
763
  packages,
763
764
  ignore: config.ignore
764
765
  });
765
- console.log(chalk.dim(`${graph.nodes.length} files, ${graph.edges.length} edges`));
766
+ console.log(chalk2.dim(`${graph.nodes.length} files, ${graph.edges.length} edges`));
766
767
  const inferred = inferBoundaries(graph);
767
768
  const sources = Object.keys(inferred.deny).filter((k) => inferred.deny[k].length > 0);
768
769
  const totalRules = sources.reduce((sum, k) => sum + inferred.deny[k].length, 0);
769
770
  if (totalRules === 0) {
770
- console.log(chalk.yellow("No boundary rules could be inferred."));
771
+ console.log(chalk2.yellow("No boundary rules could be inferred."));
771
772
  return;
772
773
  }
773
774
  console.log(`
774
- ${chalk.bold("Inferred boundary rules:")}
775
+ ${chalk2.bold("Inferred boundary rules:")}
775
776
  `);
776
777
  for (const source of sources) {
777
778
  for (const target of inferred.deny[source]) {
778
- console.log(` ${chalk.red("\u2717")} ${source} \u2192 ${target}`);
779
+ console.log(` ${chalk2.red("\u2717")} ${source} \u2192 ${target}`);
779
780
  }
780
781
  }
781
782
  console.log(`
@@ -787,11 +788,11 @@ ${chalk.bold("Inferred boundary rules:")}
787
788
  config.rules.enforceBoundaries = true;
788
789
  fs3.writeFileSync(configPath, `${JSON.stringify(compactConfig(config), null, 2)}
789
790
  `);
790
- console.log(`${chalk.green("\u2713")} Saved ${totalRules} rules`);
791
+ console.log(`${chalk2.green("\u2713")} Saved ${totalRules} rules`);
791
792
  }
792
793
  }
793
794
  async function showGraph(projectRoot, config) {
794
- console.log(chalk.dim("Building import graph..."));
795
+ console.log(chalk2.dim("Building import graph..."));
795
796
  const { buildImportGraph } = await import("@viberails/graph");
796
797
  const packages = config.packages.length > 1 ? resolveWorkspacePackages(projectRoot, config.packages) : void 0;
797
798
  const graph = await buildImportGraph(projectRoot, {
@@ -799,20 +800,20 @@ async function showGraph(projectRoot, config) {
799
800
  ignore: config.ignore
800
801
  });
801
802
  console.log(`
802
- ${chalk.bold("Import dependency graph:")}
803
+ ${chalk2.bold("Import dependency graph:")}
803
804
  `);
804
805
  console.log(` ${graph.nodes.length} files, ${graph.edges.length} imports
805
806
  `);
806
807
  if (graph.packages.length > 0) {
807
808
  for (const pkg of graph.packages) {
808
809
  const deps = pkg.internalDeps.length > 0 ? `
809
- ${pkg.internalDeps.map((d) => ` \u2192 ${d}`).join("\n")}` : chalk.dim(" (no internal deps)");
810
+ ${pkg.internalDeps.map((d) => ` \u2192 ${d}`).join("\n")}` : chalk2.dim(" (no internal deps)");
810
811
  console.log(` ${pkg.name}${deps}`);
811
812
  }
812
813
  }
813
814
  if (graph.cycles.length > 0) {
814
815
  console.log(`
815
- ${chalk.yellow("Cycles detected:")}`);
816
+ ${chalk2.yellow("Cycles detected:")}`);
816
817
  for (const cycle of graph.cycles) {
817
818
  const paths = cycle.map((f) => path3.relative(projectRoot, f));
818
819
  console.log(` ${paths.join(" \u2192 ")}`);
@@ -824,7 +825,7 @@ ${chalk.yellow("Cycles detected:")}`);
824
825
  import * as fs7 from "fs";
825
826
  import * as path7 from "path";
826
827
  import { loadConfig as loadConfig2 } from "@viberails/config";
827
- import chalk3 from "chalk";
828
+ import chalk4 from "chalk";
828
829
 
829
830
  // src/commands/check-config.ts
830
831
  import { BUILTIN_IGNORE } from "@viberails/config";
@@ -1216,7 +1217,7 @@ function collectSourceFiles(dir, projectRoot) {
1216
1217
  }
1217
1218
 
1218
1219
  // src/commands/check-print.ts
1219
- import chalk2 from "chalk";
1220
+ import chalk3 from "chalk";
1220
1221
  function printGroupedViolations(violations, limit) {
1221
1222
  const groups = /* @__PURE__ */ new Map();
1222
1223
  for (const v of violations) {
@@ -1244,12 +1245,12 @@ function printGroupedViolations(violations, limit) {
1244
1245
  const toShow = group.slice(0, remaining);
1245
1246
  const hidden = group.length - toShow.length;
1246
1247
  for (const v of toShow) {
1247
- const icon = v.severity === "error" ? chalk2.red("\u2717") : chalk2.yellow("!");
1248
- console.log(`${icon} ${chalk2.dim(v.rule)} ${v.file}: ${v.message}`);
1248
+ const icon = v.severity === "error" ? chalk3.red("\u2717") : chalk3.yellow("!");
1249
+ console.log(`${icon} ${chalk3.dim(v.rule)} ${v.file}: ${v.message}`);
1249
1250
  }
1250
1251
  totalShown += toShow.length;
1251
1252
  if (hidden > 0) {
1252
- console.log(chalk2.dim(` ... and ${hidden} more ${rule} violations`));
1253
+ console.log(chalk3.dim(` ... and ${hidden} more ${rule} violations`));
1253
1254
  }
1254
1255
  }
1255
1256
  }
@@ -1339,13 +1340,13 @@ async function checkCommand(options, cwd) {
1339
1340
  const startDir = cwd ?? process.cwd();
1340
1341
  const projectRoot = findProjectRoot(startDir);
1341
1342
  if (!projectRoot) {
1342
- console.error(`${chalk3.red("Error:")} No package.json found. Are you in a JS/TS project?`);
1343
+ console.error(`${chalk4.red("Error:")} No package.json found. Are you in a JS/TS project?`);
1343
1344
  return 1;
1344
1345
  }
1345
1346
  const configPath = path7.join(projectRoot, CONFIG_FILE2);
1346
1347
  if (!fs7.existsSync(configPath)) {
1347
1348
  console.error(
1348
- `${chalk3.red("Error:")} No viberails.config.json found. Run \`viberails init\` first.`
1349
+ `${chalk4.red("Error:")} No viberails.config.json found. Run \`viberails init\` first.`
1349
1350
  );
1350
1351
  return 1;
1351
1352
  }
@@ -1359,7 +1360,7 @@ async function checkCommand(options, cwd) {
1359
1360
  } else if (options.diffBase) {
1360
1361
  const diff = getDiffFiles(projectRoot, options.diffBase);
1361
1362
  if (diff.error && options.enforce) {
1362
- console.error(`${chalk3.red("Error:")} ${diff.error}`);
1363
+ console.error(`${chalk4.red("Error:")} ${diff.error}`);
1363
1364
  return 1;
1364
1365
  }
1365
1366
  filesToCheck = diff.all.filter((f) => SOURCE_EXTS.has(path7.extname(f)));
@@ -1374,13 +1375,13 @@ async function checkCommand(options, cwd) {
1374
1375
  if (options.format === "json") {
1375
1376
  console.log(JSON.stringify({ violations: [], checkedFiles: 0 }));
1376
1377
  } else {
1377
- console.log(`${chalk3.green("\u2713")} No files to check.`);
1378
+ console.log(`${chalk4.green("\u2713")} No files to check.`);
1378
1379
  }
1379
1380
  return 0;
1380
1381
  }
1381
1382
  const violations = [];
1382
1383
  const severity = options.enforce ? "error" : "warn";
1383
- const log9 = options.format !== "json" && !options.hook && !options.quiet ? (msg) => process.stderr.write(chalk3.dim(msg)) : () => {
1384
+ const log9 = options.format !== "json" && !options.hook && !options.quiet ? (msg) => process.stderr.write(chalk4.dim(msg)) : () => {
1384
1385
  };
1385
1386
  log9(" Checking files...");
1386
1387
  for (const file of filesToCheck) {
@@ -1475,7 +1476,7 @@ async function checkCommand(options, cwd) {
1475
1476
  return options.enforce && violations.length > 0 ? 1 : 0;
1476
1477
  }
1477
1478
  if (violations.length === 0) {
1478
- console.log(`${chalk3.green("\u2713")} ${filesToCheck.length} files checked \u2014 no violations`);
1479
+ console.log(`${chalk4.green("\u2713")} ${filesToCheck.length} files checked \u2014 no violations`);
1479
1480
  return 0;
1480
1481
  }
1481
1482
  if (!options.quiet) {
@@ -1483,7 +1484,7 @@ async function checkCommand(options, cwd) {
1483
1484
  }
1484
1485
  printSummary(violations);
1485
1486
  if (options.enforce) {
1486
- console.log(chalk3.red("Fix violations before committing."));
1487
+ console.log(chalk4.red("Fix violations before committing."));
1487
1488
  return 1;
1488
1489
  }
1489
1490
  return 0;
@@ -1541,7 +1542,7 @@ import * as path9 from "path";
1541
1542
  import * as clack6 from "@clack/prompts";
1542
1543
  import { compactConfig as compactConfig2, loadConfig as loadConfig3, mergeConfig } from "@viberails/config";
1543
1544
  import { scan } from "@viberails/scanner";
1544
- import chalk6 from "chalk";
1545
+ import chalk7 from "chalk";
1545
1546
 
1546
1547
  // src/display-text.ts
1547
1548
  import {
@@ -1560,7 +1561,7 @@ import {
1560
1561
  ORM_NAMES,
1561
1562
  STYLING_NAMES as STYLING_NAMES2
1562
1563
  } from "@viberails/types";
1563
- import chalk5 from "chalk";
1564
+ import chalk6 from "chalk";
1564
1565
 
1565
1566
  // src/display-helpers.ts
1566
1567
  import { ROLE_DESCRIPTIONS } from "@viberails/types";
@@ -1613,7 +1614,7 @@ function formatRoleGroup(group) {
1613
1614
 
1614
1615
  // src/display-monorepo.ts
1615
1616
  import { FRAMEWORK_NAMES, STYLING_NAMES } from "@viberails/types";
1616
- import chalk4 from "chalk";
1617
+ import chalk5 from "chalk";
1617
1618
  function formatPackageSummary(pkg) {
1618
1619
  const parts = [];
1619
1620
  if (pkg.stack.framework) {
@@ -1630,23 +1631,23 @@ function formatPackageSummary(pkg) {
1630
1631
  function displayMonorepoResults(scanResult) {
1631
1632
  const { stack, packages } = scanResult;
1632
1633
  console.log(`
1633
- ${chalk4.bold(`Detected: (monorepo, ${packages.length} packages)`)}`);
1634
- console.log(` ${chalk4.green("\u2713")} ${formatItem(stack.language)}`);
1634
+ ${chalk5.bold(`Detected: (monorepo, ${packages.length} packages)`)}`);
1635
+ console.log(` ${chalk5.green("\u2713")} ${formatItem(stack.language)}`);
1635
1636
  if (stack.packageManager) {
1636
- console.log(` ${chalk4.green("\u2713")} ${formatItem(stack.packageManager)}`);
1637
+ console.log(` ${chalk5.green("\u2713")} ${formatItem(stack.packageManager)}`);
1637
1638
  }
1638
1639
  if (stack.linter && stack.formatter && stack.linter.name === stack.formatter.name) {
1639
- console.log(` ${chalk4.green("\u2713")} ${formatItem(stack.linter)} (lint + format)`);
1640
+ console.log(` ${chalk5.green("\u2713")} ${formatItem(stack.linter)} (lint + format)`);
1640
1641
  } else {
1641
1642
  if (stack.linter) {
1642
- console.log(` ${chalk4.green("\u2713")} ${formatItem(stack.linter)}`);
1643
+ console.log(` ${chalk5.green("\u2713")} ${formatItem(stack.linter)}`);
1643
1644
  }
1644
1645
  if (stack.formatter) {
1645
- console.log(` ${chalk4.green("\u2713")} ${formatItem(stack.formatter)}`);
1646
+ console.log(` ${chalk5.green("\u2713")} ${formatItem(stack.formatter)}`);
1646
1647
  }
1647
1648
  }
1648
1649
  if (stack.testRunner) {
1649
- console.log(` ${chalk4.green("\u2713")} ${formatItem(stack.testRunner)}`);
1650
+ console.log(` ${chalk5.green("\u2713")} ${formatItem(stack.testRunner)}`);
1650
1651
  }
1651
1652
  console.log("");
1652
1653
  for (const pkg of packages) {
@@ -1657,13 +1658,13 @@ ${chalk4.bold(`Detected: (monorepo, ${packages.length} packages)`)}`);
1657
1658
  );
1658
1659
  if (packagesWithDirs.length > 0) {
1659
1660
  console.log(`
1660
- ${chalk4.bold("Structure:")}`);
1661
+ ${chalk5.bold("Structure:")}`);
1661
1662
  for (const pkg of packagesWithDirs) {
1662
1663
  const groups = groupByRole(pkg.structure.directories);
1663
1664
  if (groups.length === 0) continue;
1664
1665
  console.log(` ${pkg.relativePath}:`);
1665
1666
  for (const group of groups) {
1666
- console.log(` ${chalk4.green("\u2713")} ${formatRoleGroup(group)}`);
1667
+ console.log(` ${chalk5.green("\u2713")} ${formatRoleGroup(group)}`);
1667
1668
  }
1668
1669
  }
1669
1670
  }
@@ -1744,7 +1745,7 @@ function displayConventions(scanResult) {
1744
1745
  const conventionEntries = Object.entries(scanResult.conventions);
1745
1746
  if (conventionEntries.length === 0) return;
1746
1747
  console.log(`
1747
- ${chalk5.bold("Conventions:")}`);
1748
+ ${chalk6.bold("Conventions:")}`);
1748
1749
  for (const [key, convention] of conventionEntries) {
1749
1750
  if (convention.confidence === "low") continue;
1750
1751
  const label = CONVENTION_LABELS[key] ?? key;
@@ -1752,19 +1753,19 @@ ${chalk5.bold("Conventions:")}`);
1752
1753
  const pkgValues = scanResult.packages.filter((pkg) => pkg.conventions[key] && pkg.conventions[key].confidence !== "low").map((pkg) => ({ relativePath: pkg.relativePath, convention: pkg.conventions[key] }));
1753
1754
  const allSame = pkgValues.every((pv) => pv.convention.value === convention.value);
1754
1755
  if (allSame || pkgValues.length <= 1) {
1755
- const ind = convention.confidence === "high" ? chalk5.green("\u2713") : chalk5.yellow("~");
1756
- const detail = chalk5.dim(`(${confidenceLabel(convention)})`);
1756
+ const ind = convention.confidence === "high" ? chalk6.green("\u2713") : chalk6.yellow("~");
1757
+ const detail = chalk6.dim(`(${confidenceLabel(convention)})`);
1757
1758
  console.log(` ${ind} ${label}: ${convention.value} ${detail}`);
1758
1759
  } else {
1759
- console.log(` ${chalk5.yellow("~")} ${label}: varies by package`);
1760
+ console.log(` ${chalk6.yellow("~")} ${label}: varies by package`);
1760
1761
  for (const pv of pkgValues) {
1761
1762
  const pct = Math.round(pv.convention.consistency);
1762
1763
  console.log(` ${pv.relativePath}: ${pv.convention.value} (${pct}%)`);
1763
1764
  }
1764
1765
  }
1765
1766
  } else {
1766
- const ind = convention.confidence === "high" ? chalk5.green("\u2713") : chalk5.yellow("~");
1767
- const detail = chalk5.dim(`(${confidenceLabel(convention)})`);
1767
+ const ind = convention.confidence === "high" ? chalk6.green("\u2713") : chalk6.yellow("~");
1768
+ const detail = chalk6.dim(`(${confidenceLabel(convention)})`);
1768
1769
  console.log(` ${ind} ${label}: ${convention.value} ${detail}`);
1769
1770
  }
1770
1771
  }
@@ -1772,7 +1773,7 @@ ${chalk5.bold("Conventions:")}`);
1772
1773
  function displaySummarySection(scanResult) {
1773
1774
  const pkgCount = scanResult.packages.length > 1 ? scanResult.packages.length : void 0;
1774
1775
  console.log(`
1775
- ${chalk5.bold("Summary:")}`);
1776
+ ${chalk6.bold("Summary:")}`);
1776
1777
  console.log(` ${formatSummary(scanResult.statistics, pkgCount)}`);
1777
1778
  const ext = formatExtensions(scanResult.statistics.filesByExtension);
1778
1779
  if (ext) {
@@ -1786,47 +1787,47 @@ function displayScanResults(scanResult) {
1786
1787
  }
1787
1788
  const { stack } = scanResult;
1788
1789
  console.log(`
1789
- ${chalk5.bold("Detected:")}`);
1790
+ ${chalk6.bold("Detected:")}`);
1790
1791
  if (stack.framework) {
1791
- console.log(` ${chalk5.green("\u2713")} ${formatItem(stack.framework, FRAMEWORK_NAMES2)}`);
1792
+ console.log(` ${chalk6.green("\u2713")} ${formatItem(stack.framework, FRAMEWORK_NAMES2)}`);
1792
1793
  }
1793
- console.log(` ${chalk5.green("\u2713")} ${formatItem(stack.language)}`);
1794
+ console.log(` ${chalk6.green("\u2713")} ${formatItem(stack.language)}`);
1794
1795
  if (stack.styling) {
1795
- console.log(` ${chalk5.green("\u2713")} ${formatItem(stack.styling, STYLING_NAMES2)}`);
1796
+ console.log(` ${chalk6.green("\u2713")} ${formatItem(stack.styling, STYLING_NAMES2)}`);
1796
1797
  }
1797
1798
  if (stack.backend) {
1798
- console.log(` ${chalk5.green("\u2713")} ${formatItem(stack.backend, FRAMEWORK_NAMES2)}`);
1799
+ console.log(` ${chalk6.green("\u2713")} ${formatItem(stack.backend, FRAMEWORK_NAMES2)}`);
1799
1800
  }
1800
1801
  if (stack.orm) {
1801
- console.log(` ${chalk5.green("\u2713")} ${formatItem(stack.orm, ORM_NAMES)}`);
1802
+ console.log(` ${chalk6.green("\u2713")} ${formatItem(stack.orm, ORM_NAMES)}`);
1802
1803
  }
1803
1804
  if (stack.linter && stack.formatter && stack.linter.name === stack.formatter.name) {
1804
- console.log(` ${chalk5.green("\u2713")} ${formatItem(stack.linter)} (lint + format)`);
1805
+ console.log(` ${chalk6.green("\u2713")} ${formatItem(stack.linter)} (lint + format)`);
1805
1806
  } else {
1806
1807
  if (stack.linter) {
1807
- console.log(` ${chalk5.green("\u2713")} ${formatItem(stack.linter)}`);
1808
+ console.log(` ${chalk6.green("\u2713")} ${formatItem(stack.linter)}`);
1808
1809
  }
1809
1810
  if (stack.formatter) {
1810
- console.log(` ${chalk5.green("\u2713")} ${formatItem(stack.formatter)}`);
1811
+ console.log(` ${chalk6.green("\u2713")} ${formatItem(stack.formatter)}`);
1811
1812
  }
1812
1813
  }
1813
1814
  if (stack.testRunner) {
1814
- console.log(` ${chalk5.green("\u2713")} ${formatItem(stack.testRunner)}`);
1815
+ console.log(` ${chalk6.green("\u2713")} ${formatItem(stack.testRunner)}`);
1815
1816
  }
1816
1817
  if (stack.packageManager) {
1817
- console.log(` ${chalk5.green("\u2713")} ${formatItem(stack.packageManager)}`);
1818
+ console.log(` ${chalk6.green("\u2713")} ${formatItem(stack.packageManager)}`);
1818
1819
  }
1819
1820
  if (stack.libraries.length > 0) {
1820
1821
  for (const lib of stack.libraries) {
1821
- console.log(` ${chalk5.green("\u2713")} ${formatItem(lib, LIBRARY_NAMES)}`);
1822
+ console.log(` ${chalk6.green("\u2713")} ${formatItem(lib, LIBRARY_NAMES)}`);
1822
1823
  }
1823
1824
  }
1824
1825
  const groups = groupByRole(scanResult.structure.directories);
1825
1826
  if (groups.length > 0) {
1826
1827
  console.log(`
1827
- ${chalk5.bold("Structure:")}`);
1828
+ ${chalk6.bold("Structure:")}`);
1828
1829
  for (const group of groups) {
1829
- console.log(` ${chalk5.green("\u2713")} ${formatRoleGroup(group)}`);
1830
+ console.log(` ${chalk6.green("\u2713")} ${formatRoleGroup(group)}`);
1830
1831
  }
1831
1832
  }
1832
1833
  displayConventions(scanResult);
@@ -1836,25 +1837,25 @@ ${chalk5.bold("Structure:")}`);
1836
1837
  function displayRulesPreview(config) {
1837
1838
  const root = config.packages.find((p) => p.path === ".") ?? config.packages[0];
1838
1839
  console.log(
1839
- `${chalk5.bold("Rules:")} ${chalk5.dim("(warns on violation; use --enforce in CI to block)")}`
1840
+ `${chalk6.bold("Rules:")} ${chalk6.dim("(warns on violation; use --enforce in CI to block)")}`
1840
1841
  );
1841
- console.log(` ${chalk5.dim("\u2022")} Max file size: ${config.rules.maxFileLines} lines`);
1842
+ console.log(` ${chalk6.dim("\u2022")} Max file size: ${config.rules.maxFileLines} lines`);
1842
1843
  if (config.rules.testCoverage > 0 && root?.structure?.testPattern) {
1843
1844
  console.log(
1844
- ` ${chalk5.dim("\u2022")} Test coverage target: ${config.rules.testCoverage}% (${root.structure.testPattern})`
1845
+ ` ${chalk6.dim("\u2022")} Test coverage target: ${config.rules.testCoverage}% (${root.structure.testPattern})`
1845
1846
  );
1846
1847
  } else if (config.rules.testCoverage > 0) {
1847
- console.log(` ${chalk5.dim("\u2022")} Test coverage target: ${config.rules.testCoverage}%`);
1848
+ console.log(` ${chalk6.dim("\u2022")} Test coverage target: ${config.rules.testCoverage}%`);
1848
1849
  } else {
1849
- console.log(` ${chalk5.dim("\u2022")} Test coverage target: disabled`);
1850
+ console.log(` ${chalk6.dim("\u2022")} Test coverage target: disabled`);
1850
1851
  }
1851
1852
  if (config.rules.enforceNaming && root?.conventions?.fileNaming) {
1852
- console.log(` ${chalk5.dim("\u2022")} Enforce file naming: ${root.conventions.fileNaming}`);
1853
+ console.log(` ${chalk6.dim("\u2022")} Enforce file naming: ${root.conventions.fileNaming}`);
1853
1854
  } else {
1854
- console.log(` ${chalk5.dim("\u2022")} Enforce file naming: no`);
1855
+ console.log(` ${chalk6.dim("\u2022")} Enforce file naming: no`);
1855
1856
  }
1856
1857
  console.log(
1857
- ` ${chalk5.dim("\u2022")} Enforce boundaries: ${config.rules.enforceBoundaries ? "yes" : "no"}`
1858
+ ` ${chalk6.dim("\u2022")} Enforce boundaries: ${config.rules.enforceBoundaries ? "yes" : "no"}`
1858
1859
  );
1859
1860
  console.log("");
1860
1861
  }
@@ -2179,7 +2180,7 @@ async function configCommand(options, cwd) {
2179
2180
  }
2180
2181
  const configPath = path9.join(projectRoot, CONFIG_FILE3);
2181
2182
  if (!fs10.existsSync(configPath)) {
2182
- console.log(`${chalk6.yellow("!")} No config found. Run ${chalk6.cyan("viberails")} first.`);
2183
+ console.log(`${chalk7.yellow("!")} No config found. Run ${chalk7.cyan("viberails")} first.`);
2183
2184
  return;
2184
2185
  }
2185
2186
  if (!options.suppressIntro) {
@@ -2270,22 +2271,22 @@ async function rescanAndMerge(projectRoot, config) {
2270
2271
  import * as fs13 from "fs";
2271
2272
  import * as path13 from "path";
2272
2273
  import { loadConfig as loadConfig4 } from "@viberails/config";
2273
- import chalk8 from "chalk";
2274
+ import chalk9 from "chalk";
2274
2275
 
2275
2276
  // src/commands/fix-helpers.ts
2276
2277
  import { execSync as execSync2 } from "child_process";
2277
- import chalk7 from "chalk";
2278
+ import chalk8 from "chalk";
2278
2279
  function printPlan(renames, stubs) {
2279
2280
  if (renames.length > 0) {
2280
- console.log(chalk7.bold("\nFile renames:"));
2281
+ console.log(chalk8.bold("\nFile renames:"));
2281
2282
  for (const r of renames) {
2282
- console.log(` ${chalk7.red(r.oldPath)} \u2192 ${chalk7.green(r.newPath)}`);
2283
+ console.log(` ${chalk8.red(r.oldPath)} \u2192 ${chalk8.green(r.newPath)}`);
2283
2284
  }
2284
2285
  }
2285
2286
  if (stubs.length > 0) {
2286
- console.log(chalk7.bold("\nTest stubs to create:"));
2287
+ console.log(chalk8.bold("\nTest stubs to create:"));
2287
2288
  for (const s of stubs) {
2288
- console.log(` ${chalk7.green("+")} ${s.path}`);
2289
+ console.log(` ${chalk8.green("+")} ${s.path}`);
2289
2290
  }
2290
2291
  }
2291
2292
  }
@@ -2613,13 +2614,13 @@ async function fixCommand(options, cwd) {
2613
2614
  const startDir = cwd ?? process.cwd();
2614
2615
  const projectRoot = findProjectRoot(startDir);
2615
2616
  if (!projectRoot) {
2616
- console.error(`${chalk8.red("Error:")} No package.json found. Are you in a JS/TS project?`);
2617
+ console.error(`${chalk9.red("Error:")} No package.json found. Are you in a JS/TS project?`);
2617
2618
  return 1;
2618
2619
  }
2619
2620
  const configPath = path13.join(projectRoot, CONFIG_FILE4);
2620
2621
  if (!fs13.existsSync(configPath)) {
2621
2622
  console.error(
2622
- `${chalk8.red("Error:")} No viberails.config.json found. Run \`viberails init\` first.`
2623
+ `${chalk9.red("Error:")} No viberails.config.json found. Run \`viberails init\` first.`
2623
2624
  );
2624
2625
  return 1;
2625
2626
  }
@@ -2628,7 +2629,7 @@ async function fixCommand(options, cwd) {
2628
2629
  const isDirty = checkGitDirty(projectRoot);
2629
2630
  if (isDirty) {
2630
2631
  console.log(
2631
- chalk8.yellow("Warning: You have uncommitted changes. Consider committing first.")
2632
+ chalk9.yellow("Warning: You have uncommitted changes. Consider committing first.")
2632
2633
  );
2633
2634
  }
2634
2635
  }
@@ -2675,41 +2676,41 @@ async function fixCommand(options, cwd) {
2675
2676
  return blockedOldBareNames.has(bare);
2676
2677
  });
2677
2678
  if (safeRenames.length === 0 && testStubs.length === 0 && skippedRenames.length === 0) {
2678
- console.log(`${chalk8.green("\u2713")} No fixable violations found.`);
2679
+ console.log(`${chalk9.green("\u2713")} No fixable violations found.`);
2679
2680
  return 0;
2680
2681
  }
2681
2682
  printPlan(safeRenames, testStubs);
2682
2683
  if (skippedRenames.length > 0) {
2683
2684
  console.log("");
2684
2685
  console.log(
2685
- chalk8.yellow(
2686
+ chalk9.yellow(
2686
2687
  `Skipping ${skippedRenames.length} rename${skippedRenames.length > 1 ? "s" : ""} \u2014 aliased imports would break:`
2687
2688
  )
2688
2689
  );
2689
2690
  for (const r of skippedRenames.slice(0, 5)) {
2690
- console.log(chalk8.dim(` ${r.oldPath} \u2192 ${r.newPath}`));
2691
+ console.log(chalk9.dim(` ${r.oldPath} \u2192 ${r.newPath}`));
2691
2692
  }
2692
2693
  if (skippedRenames.length > 5) {
2693
- console.log(chalk8.dim(` ... and ${skippedRenames.length - 5} more`));
2694
+ console.log(chalk9.dim(` ... and ${skippedRenames.length - 5} more`));
2694
2695
  }
2695
2696
  console.log("");
2696
- console.log(chalk8.yellow("Affected aliased imports:"));
2697
+ console.log(chalk9.yellow("Affected aliased imports:"));
2697
2698
  for (const alias of aliasImports.slice(0, 5)) {
2698
2699
  const relFile = path13.relative(projectRoot, alias.file);
2699
- console.log(chalk8.dim(` ${relFile}:${alias.line} \u2014 ${alias.specifier}`));
2700
+ console.log(chalk9.dim(` ${relFile}:${alias.line} \u2014 ${alias.specifier}`));
2700
2701
  }
2701
2702
  if (aliasImports.length > 5) {
2702
- console.log(chalk8.dim(` ... and ${aliasImports.length - 5} more`));
2703
+ console.log(chalk9.dim(` ... and ${aliasImports.length - 5} more`));
2703
2704
  }
2704
- console.log(chalk8.dim(" Update these imports to relative paths first, then re-run fix."));
2705
+ console.log(chalk9.dim(" Update these imports to relative paths first, then re-run fix."));
2705
2706
  }
2706
2707
  if (safeRenames.length === 0 && testStubs.length === 0) {
2707
2708
  console.log(`
2708
- ${chalk8.yellow("!")} No safe fixes to apply. Resolve aliased imports first.`);
2709
+ ${chalk9.yellow("!")} No safe fixes to apply. Resolve aliased imports first.`);
2709
2710
  return 0;
2710
2711
  }
2711
2712
  if (options.dryRun) {
2712
- console.log(chalk8.dim("\nDry run \u2014 no changes applied."));
2713
+ console.log(chalk9.dim("\nDry run \u2014 no changes applied."));
2713
2714
  return 0;
2714
2715
  }
2715
2716
  if (!options.yes) {
@@ -2740,15 +2741,15 @@ ${chalk8.yellow("!")} No safe fixes to apply. Resolve aliased imports first.`);
2740
2741
  }
2741
2742
  console.log("");
2742
2743
  if (renameCount > 0) {
2743
- console.log(`${chalk8.green("\u2713")} Renamed ${renameCount} file${renameCount > 1 ? "s" : ""}`);
2744
+ console.log(`${chalk9.green("\u2713")} Renamed ${renameCount} file${renameCount > 1 ? "s" : ""}`);
2744
2745
  }
2745
2746
  if (importUpdateCount > 0) {
2746
2747
  console.log(
2747
- `${chalk8.green("\u2713")} Updated ${importUpdateCount} import${importUpdateCount > 1 ? "s" : ""}`
2748
+ `${chalk9.green("\u2713")} Updated ${importUpdateCount} import${importUpdateCount > 1 ? "s" : ""}`
2748
2749
  );
2749
2750
  }
2750
2751
  if (stubCount > 0) {
2751
- console.log(`${chalk8.green("\u2713")} Generated ${stubCount} test stub${stubCount > 1 ? "s" : ""}`);
2752
+ console.log(`${chalk9.green("\u2713")} Generated ${stubCount} test stub${stubCount > 1 ? "s" : ""}`);
2752
2753
  }
2753
2754
  return 0;
2754
2755
  }
@@ -2759,13 +2760,13 @@ import * as path21 from "path";
2759
2760
  import * as clack13 from "@clack/prompts";
2760
2761
  import { compactConfig as compactConfig4, generateConfig as generateConfig2 } from "@viberails/config";
2761
2762
  import { scan as scan3 } from "@viberails/scanner";
2762
- import chalk14 from "chalk";
2763
+ import chalk15 from "chalk";
2763
2764
 
2764
2765
  // src/utils/check-prerequisites.ts
2765
2766
  import * as fs14 from "fs";
2766
2767
  import * as path14 from "path";
2767
2768
  import * as clack7 from "@clack/prompts";
2768
- import chalk9 from "chalk";
2769
+ import chalk10 from "chalk";
2769
2770
 
2770
2771
  // src/utils/spawn-async.ts
2771
2772
  import { spawn } from "child_process";
@@ -2820,9 +2821,9 @@ function displayMissingPrereqs(prereqs) {
2820
2821
  const missing = prereqs.filter((p) => !p.installed);
2821
2822
  for (const m of missing) {
2822
2823
  const suffix = m.affectedPackages ? ` \u2014 needed for coverage in: ${m.affectedPackages.join(", ")}` : ` \u2014 ${m.reason}`;
2823
- console.log(` ${chalk9.yellow("!")} ${m.label} not installed${suffix}`);
2824
+ console.log(` ${chalk10.yellow("!")} ${m.label} not installed${suffix}`);
2824
2825
  if (m.installCommand) {
2825
- console.log(` Install: ${chalk9.cyan(m.installCommand)}`);
2826
+ console.log(` Install: ${chalk10.cyan(m.installCommand)}`);
2826
2827
  }
2827
2828
  }
2828
2829
  }
@@ -3147,7 +3148,7 @@ async function handleIntegrations(state, opts) {
3147
3148
  }
3148
3149
 
3149
3150
  // src/utils/prompt-main-menu-hints.ts
3150
- import chalk10 from "chalk";
3151
+ import chalk11 from "chalk";
3151
3152
  function fileLimitsHint(config) {
3152
3153
  const max = config.rules.maxFileLines;
3153
3154
  const test = config.rules.maxTestFileLines;
@@ -3192,24 +3193,29 @@ function coverageHint(config, hasTestRunner) {
3192
3193
  }
3193
3194
  function advancedNamingHint(config) {
3194
3195
  const rootPkg = getRootPackage(config.packages);
3196
+ if (!config.rules.enforceNaming) return "not enforced";
3195
3197
  const parts = [];
3196
- if (rootPkg.conventions?.componentNaming)
3197
- parts.push(`${rootPkg.conventions.componentNaming} components`);
3198
- if (rootPkg.conventions?.hookNaming) parts.push(`${rootPkg.conventions.hookNaming} hooks`);
3199
- if (rootPkg.conventions?.importAlias) parts.push(rootPkg.conventions.importAlias);
3200
- return parts.length > 0 ? parts.join(", ") : "component, hook, and alias conventions";
3198
+ const naming = rootPkg.conventions?.fileNaming;
3199
+ if (naming) parts.push(chalk11.green(naming));
3200
+ const comp = rootPkg.conventions?.componentNaming;
3201
+ parts.push(comp ? chalk11.green(`${comp} components`) : chalk11.dim("components"));
3202
+ const hook = rootPkg.conventions?.hookNaming;
3203
+ parts.push(hook ? chalk11.green(`${hook} hooks`) : chalk11.dim("hooks"));
3204
+ const alias = rootPkg.conventions?.importAlias;
3205
+ parts.push(alias ? chalk11.green(alias) : chalk11.dim("alias"));
3206
+ return parts.join(chalk11.dim(", "));
3201
3207
  }
3202
3208
  function integrationsHint(state) {
3203
3209
  if (!state.visited.integrations || !state.integrations)
3204
3210
  return "not configured \u2014 select to set up";
3205
3211
  const items = [];
3206
- if (state.integrations.preCommitHook) items.push("pre-commit");
3207
- if (state.integrations.typecheckHook) items.push("typecheck");
3208
- if (state.integrations.lintHook) items.push("lint");
3209
- if (state.integrations.claudeCodeHook) items.push("Claude");
3210
- if (state.integrations.claudeMdRef) items.push("CLAUDE.md");
3211
- if (state.integrations.githubAction) items.push("CI");
3212
- return items.length > 0 ? items.join(" \xB7 ") : "none selected";
3212
+ if (state.integrations.preCommitHook) items.push(chalk11.green("pre-commit"));
3213
+ if (state.integrations.typecheckHook) items.push(chalk11.green("typecheck"));
3214
+ if (state.integrations.lintHook) items.push(chalk11.green("lint"));
3215
+ if (state.integrations.claudeCodeHook) items.push(chalk11.green("Claude"));
3216
+ if (state.integrations.claudeMdRef) items.push(chalk11.green("CLAUDE.md"));
3217
+ if (state.integrations.githubAction) items.push(chalk11.green("CI"));
3218
+ return items.length > 0 ? items.join(chalk11.dim(" \xB7 ")) : "none selected";
3213
3219
  }
3214
3220
  function packageOverridesHint(config) {
3215
3221
  const rootNaming = getRootPackage(config.packages).conventions?.fileNaming;
@@ -3228,8 +3234,9 @@ function boundariesHint(config, state) {
3228
3234
  return `${ruleCount} rules across ${pkgCount} packages`;
3229
3235
  }
3230
3236
  function advancedNamingStatus(config) {
3237
+ if (!config.rules.enforceNaming) return "disabled";
3231
3238
  const rootPkg = getRootPackage(config.packages);
3232
- const hasAny = !!rootPkg.conventions?.componentNaming || !!rootPkg.conventions?.hookNaming || !!rootPkg.conventions?.importAlias;
3239
+ const hasAny = !!rootPkg.conventions?.fileNaming || !!rootPkg.conventions?.componentNaming || !!rootPkg.conventions?.hookNaming || !!rootPkg.conventions?.importAlias;
3233
3240
  return hasAny ? "ok" : "unconfigured";
3234
3241
  }
3235
3242
  function packageOverridesStatus(config) {
@@ -3241,10 +3248,10 @@ function packageOverridesStatus(config) {
3241
3248
  return customized ? "ok" : "unconfigured";
3242
3249
  }
3243
3250
  function statusIcon(status) {
3244
- if (status === "ok") return chalk10.green("\u2713");
3245
- if (status === "needs-input") return chalk10.yellow("?");
3246
- if (status === "unconfigured") return chalk10.dim("-");
3247
- return chalk10.yellow("~");
3251
+ if (status === "ok") return chalk11.green("\u2713");
3252
+ if (status === "needs-input") return chalk11.yellow("?");
3253
+ if (status === "unconfigured") return chalk11.dim("-");
3254
+ return chalk11.yellow("~");
3248
3255
  }
3249
3256
  function buildMainMenuOptions(config, scanResult, state) {
3250
3257
  const namingStatus = fileNamingStatus(config);
@@ -3295,7 +3302,7 @@ function buildMainMenuOptions(config, scanResult, state) {
3295
3302
  options.push(
3296
3303
  { value: "integrations", label: `${iIcon} Integrations`, hint: integrationsHint(state) },
3297
3304
  { value: "reset", label: " Reset all to defaults" },
3298
- { value: "review", label: " Review scan details" },
3305
+ { value: "review", label: " Review scan details", hint: "detected stack & conventions" },
3299
3306
  { value: "done", label: " Done \u2014 write config" }
3300
3307
  );
3301
3308
  return options;
@@ -3375,7 +3382,7 @@ function updateGitignore(projectRoot) {
3375
3382
  // src/commands/init-hooks.ts
3376
3383
  import * as fs18 from "fs";
3377
3384
  import * as path18 from "path";
3378
- import chalk11 from "chalk";
3385
+ import chalk12 from "chalk";
3379
3386
  import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
3380
3387
 
3381
3388
  // src/commands/resolve-typecheck.ts
@@ -3420,13 +3427,13 @@ function setupPreCommitHook(projectRoot) {
3420
3427
  const lefthookPath = path18.join(projectRoot, "lefthook.yml");
3421
3428
  if (fs18.existsSync(lefthookPath)) {
3422
3429
  addLefthookPreCommit(lefthookPath);
3423
- console.log(` ${chalk11.green("\u2713")} lefthook.yml \u2014 added viberails pre-commit`);
3430
+ console.log(` ${chalk12.green("\u2713")} lefthook.yml \u2014 added viberails pre-commit`);
3424
3431
  return "lefthook.yml";
3425
3432
  }
3426
3433
  const huskyDir = path18.join(projectRoot, ".husky");
3427
3434
  if (fs18.existsSync(huskyDir)) {
3428
3435
  writeHuskyPreCommit(huskyDir);
3429
- console.log(` ${chalk11.green("\u2713")} .husky/pre-commit \u2014 added viberails check`);
3436
+ console.log(` ${chalk12.green("\u2713")} .husky/pre-commit \u2014 added viberails check`);
3430
3437
  return ".husky/pre-commit";
3431
3438
  }
3432
3439
  const gitDir = path18.join(projectRoot, ".git");
@@ -3436,7 +3443,7 @@ function setupPreCommitHook(projectRoot) {
3436
3443
  fs18.mkdirSync(hooksDir, { recursive: true });
3437
3444
  }
3438
3445
  writeGitHookPreCommit(hooksDir);
3439
- console.log(` ${chalk11.green("\u2713")} .git/hooks/pre-commit`);
3446
+ console.log(` ${chalk12.green("\u2713")} .git/hooks/pre-commit`);
3440
3447
  return ".git/hooks/pre-commit";
3441
3448
  }
3442
3449
  return void 0;
@@ -3497,9 +3504,9 @@ function setupClaudeCodeHook(projectRoot) {
3497
3504
  settings = JSON.parse(fs18.readFileSync(settingsPath, "utf-8"));
3498
3505
  } catch {
3499
3506
  console.warn(
3500
- ` ${chalk11.yellow("!")} .claude/settings.json contains invalid JSON \u2014 skipping hook setup`
3507
+ ` ${chalk12.yellow("!")} .claude/settings.json contains invalid JSON \u2014 skipping hook setup`
3501
3508
  );
3502
- console.warn(` Fix the JSON manually, then re-run ${chalk11.cyan("viberails init --force")}`);
3509
+ console.warn(` Fix the JSON manually, then re-run ${chalk12.cyan("viberails init --force")}`);
3503
3510
  return;
3504
3511
  }
3505
3512
  }
@@ -3522,7 +3529,7 @@ function setupClaudeCodeHook(projectRoot) {
3522
3529
  settings.hooks = hooks;
3523
3530
  fs18.writeFileSync(settingsPath, `${JSON.stringify(settings, null, 2)}
3524
3531
  `);
3525
- console.log(` ${chalk11.green("\u2713")} .claude/settings.json \u2014 added viberails PostToolUse hook`);
3532
+ console.log(` ${chalk12.green("\u2713")} .claude/settings.json \u2014 added viberails PostToolUse hook`);
3526
3533
  }
3527
3534
  function setupClaudeMdReference(projectRoot) {
3528
3535
  const claudeMdPath = path18.join(projectRoot, "CLAUDE.md");
@@ -3534,7 +3541,7 @@ function setupClaudeMdReference(projectRoot) {
3534
3541
  const ref = "\n@.viberails/context.md\n";
3535
3542
  const prefix = content.length === 0 ? "" : content.trimEnd();
3536
3543
  fs18.writeFileSync(claudeMdPath, prefix + ref);
3537
- console.log(` ${chalk11.green("\u2713")} CLAUDE.md \u2014 added @.viberails/context.md reference`);
3544
+ console.log(` ${chalk12.green("\u2713")} CLAUDE.md \u2014 added @.viberails/context.md reference`);
3538
3545
  }
3539
3546
  function setupGithubAction(projectRoot, packageManager, options) {
3540
3547
  const workflowDir = path18.join(projectRoot, ".github", "workflows");
@@ -3620,7 +3627,7 @@ ${cmd}
3620
3627
  // src/commands/init-hooks-extra.ts
3621
3628
  import * as fs19 from "fs";
3622
3629
  import * as path19 from "path";
3623
- import chalk12 from "chalk";
3630
+ import chalk13 from "chalk";
3624
3631
  import { parse as parseYaml2, stringify as stringifyYaml2 } from "yaml";
3625
3632
  function addPreCommitStep(projectRoot, name, command, marker, lefthookExtra) {
3626
3633
  const lefthookPath = path19.join(projectRoot, "lefthook.yml");
@@ -3680,12 +3687,12 @@ ${command}
3680
3687
  function setupTypecheckHook(projectRoot, packageManager) {
3681
3688
  const resolved = resolveTypecheckCommand(projectRoot, packageManager);
3682
3689
  if (!resolved.command) {
3683
- console.log(` ${chalk12.yellow("!")} Skipped typecheck hook: ${resolved.reason}`);
3690
+ console.log(` ${chalk13.yellow("!")} Skipped typecheck hook: ${resolved.reason}`);
3684
3691
  return void 0;
3685
3692
  }
3686
3693
  const target = addPreCommitStep(projectRoot, "typecheck", resolved.command, "typecheck");
3687
3694
  if (target) {
3688
- console.log(` ${chalk12.green("\u2713")} ${target} \u2014 added typecheck (${resolved.label})`);
3695
+ console.log(` ${chalk13.green("\u2713")} ${target} \u2014 added typecheck (${resolved.label})`);
3689
3696
  }
3690
3697
  return target;
3691
3698
  }
@@ -3706,7 +3713,7 @@ function setupLintHook(projectRoot, linter) {
3706
3713
  }
3707
3714
  const target = addPreCommitStep(projectRoot, "lint", command, linter, lefthookExtra);
3708
3715
  if (target) {
3709
- console.log(` ${chalk12.green("\u2713")} ${target} \u2014 added ${linterName} lint check`);
3716
+ console.log(` ${chalk13.green("\u2713")} ${target} \u2014 added ${linterName} lint check`);
3710
3717
  }
3711
3718
  return target;
3712
3719
  }
@@ -3715,7 +3722,7 @@ function setupSelectedIntegrations(projectRoot, integrations, opts) {
3715
3722
  if (integrations.preCommitHook) {
3716
3723
  const t = setupPreCommitHook(projectRoot);
3717
3724
  if (t && opts.lefthookExpected && !t.includes("lefthook")) {
3718
- console.log(` ${chalk12.yellow("!")} Lefthook install failed \u2014 fell back to ${t}`);
3725
+ console.log(` ${chalk13.yellow("!")} Lefthook install failed \u2014 fell back to ${t}`);
3719
3726
  }
3720
3727
  created.push(t ? `${t} \u2014 added viberails pre-commit` : "pre-commit hook skipped");
3721
3728
  }
@@ -3751,7 +3758,7 @@ import * as path20 from "path";
3751
3758
  import * as clack12 from "@clack/prompts";
3752
3759
  import { compactConfig as compactConfig3, generateConfig } from "@viberails/config";
3753
3760
  import { scan as scan2 } from "@viberails/scanner";
3754
- import chalk13 from "chalk";
3761
+ import chalk14 from "chalk";
3755
3762
 
3756
3763
  // src/utils/filter-confidence.ts
3757
3764
  function filterHighConfidence(conventions, meta) {
@@ -3787,7 +3794,7 @@ async function initNonInteractive(projectRoot, configPath) {
3787
3794
  const exempted = getExemptedPackages(config);
3788
3795
  if (exempted.length > 0) {
3789
3796
  console.log(
3790
- ` ${chalk13.dim("Auto-exempted from coverage:")} ${exempted.join(", ")} ${chalk13.dim("(types-only)")}`
3797
+ ` ${chalk14.dim("Auto-exempted from coverage:")} ${exempted.join(", ")} ${chalk14.dim("(types-only)")}`
3791
3798
  );
3792
3799
  }
3793
3800
  if (config.packages.length > 1) {
@@ -3824,14 +3831,14 @@ async function initNonInteractive(projectRoot, configPath) {
3824
3831
  const hookManager = detectHookManager(projectRoot);
3825
3832
  const hasHookManager = hookManager === "Lefthook" || hookManager === "Husky";
3826
3833
  const preCommitTarget = hasHookManager ? setupPreCommitHook(projectRoot) : void 0;
3827
- const ok = chalk13.green("\u2713");
3834
+ const ok = chalk14.green("\u2713");
3828
3835
  const created = [
3829
3836
  `${ok} ${path20.basename(configPath)}`,
3830
3837
  `${ok} .viberails/context.md`,
3831
3838
  `${ok} .viberails/scan-result.json`,
3832
3839
  `${ok} .claude/settings.json \u2014 added viberails hook`,
3833
3840
  `${ok} CLAUDE.md \u2014 added @.viberails/context.md reference`,
3834
- preCommitTarget ? `${ok} ${preCommitTarget}` : `${chalk13.yellow("!")} pre-commit hook skipped (install lefthook or husky)`,
3841
+ preCommitTarget ? `${ok} ${preCommitTarget}` : `${chalk14.yellow("!")} pre-commit hook skipped (install lefthook or husky)`,
3835
3842
  actionTarget ? `${ok} ${actionTarget} \u2014 blocks PRs on violations` : ""
3836
3843
  ].filter(Boolean);
3837
3844
  if (hasHookManager && isTypeScript) setupTypecheckHook(projectRoot, rootPkgPm);
@@ -3856,8 +3863,8 @@ async function initCommand(options, cwd) {
3856
3863
  return initInteractive(projectRoot, configPath, options);
3857
3864
  }
3858
3865
  console.log(
3859
- `${chalk14.yellow("!")} viberails is already initialized.
3860
- Run ${chalk14.cyan("viberails")} to review or edit the existing setup, ${chalk14.cyan("viberails sync")} to update generated files, or ${chalk14.cyan("viberails init --force")} to replace it.`
3866
+ `${chalk15.yellow("!")} viberails is already initialized.
3867
+ Run ${chalk15.cyan("viberails")} to review or edit the existing setup, ${chalk15.cyan("viberails sync")} to update generated files, or ${chalk15.cyan("viberails init --force")} to replace it.`
3861
3868
  );
3862
3869
  return;
3863
3870
  }
@@ -3934,7 +3941,7 @@ async function initInteractive(projectRoot, configPath, options) {
3934
3941
  writeGeneratedFiles(projectRoot, config, scanResult);
3935
3942
  updateGitignore(projectRoot);
3936
3943
  ws.stop("Configuration written");
3937
- const ok = chalk14.green("\u2713");
3944
+ const ok = chalk15.green("\u2713");
3938
3945
  clack13.log.step(`${ok} ${path21.basename(configPath)}`);
3939
3946
  clack13.log.step(`${ok} .viberails/context.md`);
3940
3947
  clack13.log.step(`${ok} .viberails/scan-result.json`);
@@ -3948,7 +3955,7 @@ async function initInteractive(projectRoot, configPath, options) {
3948
3955
  }
3949
3956
  clack13.outro(
3950
3957
  `Done! Next: review viberails.config.json, then run viberails check
3951
- ${chalk14.dim("Tip: use")} ${chalk14.cyan("viberails check --enforce")} ${chalk14.dim("in CI to block PRs on violations.")}`
3958
+ ${chalk15.dim("Tip: use")} ${chalk15.cyan("viberails check --enforce")} ${chalk15.dim("in CI to block PRs on violations.")}`
3952
3959
  );
3953
3960
  }
3954
3961
 
@@ -3958,7 +3965,7 @@ import * as path22 from "path";
3958
3965
  import * as clack14 from "@clack/prompts";
3959
3966
  import { compactConfig as compactConfig5, loadConfig as loadConfig5, mergeConfig as mergeConfig2 } from "@viberails/config";
3960
3967
  import { scan as scan4 } from "@viberails/scanner";
3961
- import chalk15 from "chalk";
3968
+ import chalk16 from "chalk";
3962
3969
  var CONFIG_FILE6 = "viberails.config.json";
3963
3970
  var SCAN_RESULT_FILE2 = ".viberails/scan-result.json";
3964
3971
  function loadPreviousStats(projectRoot) {
@@ -3999,13 +4006,13 @@ async function syncCommand(options, cwd) {
3999
4006
  const statsDelta = previousStats ? formatStatsDelta(previousStats, scanResult.statistics) : void 0;
4000
4007
  if (changes.length > 0 || statsDelta) {
4001
4008
  console.log(`
4002
- ${chalk15.bold("Changes:")}`);
4009
+ ${chalk16.bold("Changes:")}`);
4003
4010
  for (const change of changes) {
4004
- const icon = change.type === "removed" ? chalk15.red("-") : chalk15.green("+");
4011
+ const icon = change.type === "removed" ? chalk16.red("-") : chalk16.green("+");
4005
4012
  console.log(` ${icon} ${change.description}`);
4006
4013
  }
4007
4014
  if (statsDelta) {
4008
- console.log(` ${chalk15.dim(statsDelta)}`);
4015
+ console.log(` ${chalk16.dim(statsDelta)}`);
4009
4016
  }
4010
4017
  }
4011
4018
  if (options?.interactive) {
@@ -4054,18 +4061,18 @@ ${chalk15.bold("Changes:")}`);
4054
4061
  `);
4055
4062
  writeGeneratedFiles(projectRoot, merged, scanResult);
4056
4063
  console.log(`
4057
- ${chalk15.bold("Synced:")}`);
4064
+ ${chalk16.bold("Synced:")}`);
4058
4065
  if (configChanged) {
4059
- console.log(` ${chalk15.yellow("!")} ${CONFIG_FILE6} \u2014 updated (review changes)`);
4066
+ console.log(` ${chalk16.yellow("!")} ${CONFIG_FILE6} \u2014 updated (review changes)`);
4060
4067
  } else {
4061
- console.log(` ${chalk15.green("\u2713")} ${CONFIG_FILE6} \u2014 unchanged`);
4068
+ console.log(` ${chalk16.green("\u2713")} ${CONFIG_FILE6} \u2014 unchanged`);
4062
4069
  }
4063
- console.log(` ${chalk15.green("\u2713")} .viberails/context.md \u2014 regenerated`);
4064
- console.log(` ${chalk15.green("\u2713")} .viberails/scan-result.json \u2014 updated`);
4070
+ console.log(` ${chalk16.green("\u2713")} .viberails/context.md \u2014 regenerated`);
4071
+ console.log(` ${chalk16.green("\u2713")} .viberails/scan-result.json \u2014 updated`);
4065
4072
  }
4066
4073
 
4067
4074
  // src/index.ts
4068
- var VERSION = "0.6.7";
4075
+ var VERSION = "0.6.8";
4069
4076
  var program = new Command();
4070
4077
  program.name("viberails").description("Guardrails for vibe coding").version(VERSION);
4071
4078
  program.command("init", { isDefault: true }).description("Scan your project and set up enforcement guardrails").option("-y, --yes", "Non-interactive mode (use defaults, high-confidence only)").option("-f, --force", "Re-initialize, replacing existing config").action(async (options) => {
@@ -4073,7 +4080,7 @@ program.command("init", { isDefault: true }).description("Scan your project and
4073
4080
  await initCommand(options);
4074
4081
  } catch (err) {
4075
4082
  const message = err instanceof Error ? err.message : String(err);
4076
- console.error(`${chalk16.red("Error:")} ${message}`);
4083
+ console.error(`${chalk17.red("Error:")} ${message}`);
4077
4084
  process.exit(1);
4078
4085
  }
4079
4086
  });
@@ -4082,7 +4089,7 @@ program.command("sync").description("Re-scan and update generated files").option
4082
4089
  await syncCommand(options);
4083
4090
  } catch (err) {
4084
4091
  const message = err instanceof Error ? err.message : String(err);
4085
- console.error(`${chalk16.red("Error:")} ${message}`);
4092
+ console.error(`${chalk17.red("Error:")} ${message}`);
4086
4093
  process.exit(1);
4087
4094
  }
4088
4095
  });
@@ -4091,7 +4098,7 @@ program.command("config").description("Interactively edit existing config rules"
4091
4098
  await configCommand(options);
4092
4099
  } catch (err) {
4093
4100
  const message = err instanceof Error ? err.message : String(err);
4094
- console.error(`${chalk16.red("Error:")} ${message}`);
4101
+ console.error(`${chalk17.red("Error:")} ${message}`);
4095
4102
  process.exit(1);
4096
4103
  }
4097
4104
  });
@@ -4112,7 +4119,7 @@ program.command("check").description("Check files against enforced rules").optio
4112
4119
  process.exit(exitCode);
4113
4120
  } catch (err) {
4114
4121
  const message = err instanceof Error ? err.message : String(err);
4115
- console.error(`${chalk16.red("Error:")} ${message}`);
4122
+ console.error(`${chalk17.red("Error:")} ${message}`);
4116
4123
  process.exit(1);
4117
4124
  }
4118
4125
  }
@@ -4123,7 +4130,7 @@ program.command("fix").description("Auto-fix file naming violations and generate
4123
4130
  process.exit(exitCode);
4124
4131
  } catch (err) {
4125
4132
  const message = err instanceof Error ? err.message : String(err);
4126
- console.error(`${chalk16.red("Error:")} ${message}`);
4133
+ console.error(`${chalk17.red("Error:")} ${message}`);
4127
4134
  process.exit(1);
4128
4135
  }
4129
4136
  });
@@ -4132,7 +4139,7 @@ program.command("boundaries").description("Display, infer, or inspect import bou
4132
4139
  await boundariesCommand(options);
4133
4140
  } catch (err) {
4134
4141
  const message = err instanceof Error ? err.message : String(err);
4135
- console.error(`${chalk16.red("Error:")} ${message}`);
4142
+ console.error(`${chalk17.red("Error:")} ${message}`);
4136
4143
  process.exit(1);
4137
4144
  }
4138
4145
  });