viberails 0.6.8 → 0.6.10

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.cjs CHANGED
@@ -34,14 +34,14 @@ __export(index_exports, {
34
34
  VERSION: () => VERSION
35
35
  });
36
36
  module.exports = __toCommonJS(index_exports);
37
- var import_chalk17 = __toESM(require("chalk"), 1);
37
+ var import_chalk18 = __toESM(require("chalk"), 1);
38
38
  var import_commander = require("commander");
39
39
 
40
40
  // src/commands/boundaries.ts
41
41
  var fs3 = __toESM(require("fs"), 1);
42
42
  var path3 = __toESM(require("path"), 1);
43
43
  var import_config = require("@viberails/config");
44
- var import_chalk2 = __toESM(require("chalk"), 1);
44
+ var import_chalk3 = __toESM(require("chalk"), 1);
45
45
 
46
46
  // src/utils/find-project-root.ts
47
47
  var fs = __toESM(require("fs"), 1);
@@ -76,6 +76,7 @@ var clack3 = __toESM(require("@clack/prompts"), 1);
76
76
 
77
77
  // src/utils/prompt-package-overrides.ts
78
78
  var clack2 = __toESM(require("@clack/prompts"), 1);
79
+ var import_chalk2 = __toESM(require("chalk"), 1);
79
80
 
80
81
  // src/utils/prompt-constants.ts
81
82
  var SENTINEL_DONE = "__done__";
@@ -150,64 +151,56 @@ async function promptFileLimitsMenu(state) {
150
151
  }
151
152
  async function promptNamingMenu(state) {
152
153
  while (true) {
154
+ const ok = import_chalk.default.green("\u2713");
155
+ const unset = import_chalk.default.dim("-");
156
+ const enforcementLabel = state.enforceNaming ? `enforced ${import_chalk.default.green("\u2713")}` : `not enforced ${import_chalk.default.dim("\u2717")}`;
153
157
  const options = [
154
158
  {
155
- value: "enforceNaming",
156
- label: "Enforce file naming",
157
- hint: state.enforceNaming ? import_chalk.default.green("yes") : import_chalk.default.dim("no")
158
- }
159
- ];
160
- if (state.enforceNaming) {
161
- options.push({
162
159
  value: "fileNaming",
163
- label: "File naming convention",
160
+ label: `${state.fileNamingValue ? ok : unset} File naming convention`,
164
161
  hint: state.fileNamingValue ?? HINT_NOT_SET
165
- });
166
- }
167
- options.push(
162
+ },
168
163
  {
169
164
  value: "componentNaming",
170
- label: "Component naming",
165
+ label: `${state.componentNaming ? ok : unset} Component naming`,
171
166
  hint: state.componentNaming ?? HINT_NOT_SET
172
167
  },
173
168
  {
174
169
  value: "hookNaming",
175
- label: "Hook naming",
170
+ label: `${state.hookNaming ? ok : unset} Hook naming`,
176
171
  hint: state.hookNaming ?? HINT_NOT_SET
177
172
  },
178
173
  {
179
174
  value: "importAlias",
180
- label: "Import alias",
175
+ label: `${state.importAlias ? ok : unset} Import alias`,
181
176
  hint: state.importAlias ?? HINT_NOT_SET
182
177
  },
183
- { value: "back", label: "Back" }
184
- );
185
- const choice = await clack.select({ message: "Naming & conventions", options });
178
+ {
179
+ value: "toggleEnforcement",
180
+ label: state.enforceNaming ? " Turn off enforcement" : " Turn on enforcement"
181
+ },
182
+ { value: "back", label: " Back" }
183
+ ];
184
+ const choice = await clack.select({
185
+ message: `Naming conventions (${enforcementLabel})`,
186
+ options
187
+ });
186
188
  if (isCancelled(choice) || choice === "back") return;
187
- if (choice === "enforceNaming") {
188
- const result = await clack.confirm({
189
- message: state.fileNamingValue ? `Enforce file naming? (detected: ${state.fileNamingValue})` : "Enforce file naming?",
190
- initialValue: state.enforceNaming
191
- });
192
- if (isCancelled(result)) continue;
193
- if (result && !state.fileNamingValue) {
194
- const selected = await clack.select({
195
- message: "Which file naming convention should be enforced?",
196
- options: [...FILE_NAMING_OPTIONS]
197
- });
198
- if (isCancelled(selected)) continue;
199
- state.fileNamingValue = selected;
200
- }
201
- state.enforceNaming = result;
189
+ if (choice === "toggleEnforcement") {
190
+ state.enforceNaming = !state.enforceNaming;
191
+ continue;
202
192
  }
203
193
  if (choice === "fileNaming") {
204
194
  const selected = await clack.select({
205
- message: "Which file naming convention should be enforced?",
206
- options: [...FILE_NAMING_OPTIONS],
207
- initialValue: state.fileNamingValue
195
+ message: "File naming convention",
196
+ options: [
197
+ ...FILE_NAMING_OPTIONS,
198
+ { value: SENTINEL_CLEAR, label: "Clear (no convention)" }
199
+ ],
200
+ initialValue: state.fileNamingValue ?? SENTINEL_CLEAR
208
201
  });
209
202
  if (isCancelled(selected)) continue;
210
- state.fileNamingValue = selected;
203
+ state.fileNamingValue = selected === SENTINEL_CLEAR ? void 0 : selected;
211
204
  }
212
205
  if (choice === "componentNaming") {
213
206
  const selected = await clack.select({
@@ -272,7 +265,7 @@ async function promptTestingMenu(state) {
272
265
  {
273
266
  value: "enforceMissingTests",
274
267
  label: "Enforce missing tests",
275
- hint: state.enforceMissingTests ? import_chalk.default.green("yes") : import_chalk.default.dim("no")
268
+ hint: state.enforceMissingTests ? import_chalk.default.green("\u2713") : import_chalk.default.dim("\u2717")
276
269
  },
277
270
  {
278
271
  value: "testCoverage",
@@ -381,6 +374,19 @@ function packageOverrideHint(pkg, defaults) {
381
374
  if (hasCommandOverride) tags.push("command override");
382
375
  return tags.length > 0 ? tags.join(", ") : HINT_NO_OVERRIDES;
383
376
  }
377
+ function packageOverrideIcon(pkg, defaults) {
378
+ const dc = defaults.coverageCommand ?? "";
379
+ const count = [
380
+ pkg.conventions?.fileNaming !== void 0 && pkg.conventions.fileNaming !== defaults.fileNamingValue,
381
+ pkg.rules?.maxFileLines !== void 0 && pkg.rules.maxFileLines !== defaults.maxFileLines,
382
+ pkg.rules?.testCoverage !== void 0 && pkg.rules.testCoverage !== defaults.testCoverage,
383
+ pkg.coverage?.summaryPath !== void 0 && pkg.coverage.summaryPath !== defaults.coverageSummaryPath,
384
+ pkg.coverage?.command !== void 0 && pkg.coverage.command !== dc
385
+ ].filter(Boolean).length;
386
+ if (count === 5) return import_chalk2.default.green("\u2713");
387
+ if (count > 0) return import_chalk2.default.yellow("~");
388
+ return import_chalk2.default.dim("-");
389
+ }
384
390
  async function promptPackageOverrides(packages, defaults) {
385
391
  const editablePackages = packages.filter((pkg) => pkg.path !== ".");
386
392
  if (editablePackages.length === 0) return packages;
@@ -388,12 +394,15 @@ async function promptPackageOverrides(packages, defaults) {
388
394
  const selectedPath = await clack2.select({
389
395
  message: "Select package to edit overrides",
390
396
  options: [
391
- ...editablePackages.map((pkg) => ({
392
- value: pkg.path,
393
- label: `${pkg.path} (${pkg.name})`,
394
- hint: packageOverrideHint(pkg, defaults)
395
- })),
396
- { value: SENTINEL_DONE, label: "Done" }
397
+ ...editablePackages.map((pkg) => {
398
+ const icon = packageOverrideIcon(pkg, defaults);
399
+ return {
400
+ value: pkg.path,
401
+ label: `${icon} ${pkg.path} (${pkg.name})`,
402
+ hint: packageOverrideHint(pkg, defaults)
403
+ };
404
+ }),
405
+ { value: SENTINEL_DONE, label: " Done" }
397
406
  ]
398
407
  });
399
408
  if (isCancelled(selectedPath) || selectedPath === SENTINEL_DONE) break;
@@ -413,18 +422,47 @@ async function promptSinglePackageOverrides(target, defaults) {
413
422
  const effectiveCommand = target.coverage?.command ?? defaults.coverageCommand ?? HINT_AUTO_DETECT;
414
423
  const hasNamingOverride = target.conventions?.fileNaming !== void 0 && target.conventions.fileNaming !== defaults.fileNamingValue;
415
424
  const hasMaxLinesOverride = target.rules?.maxFileLines !== void 0 && target.rules.maxFileLines !== defaults.maxFileLines;
425
+ const hasCoverageOverride = target.rules?.testCoverage !== void 0 && target.rules.testCoverage !== defaults.testCoverage;
426
+ const hasSummaryOverride = target.coverage?.summaryPath !== void 0 && target.coverage.summaryPath !== defaults.coverageSummaryPath;
427
+ const defaultCommand = defaults.coverageCommand ?? "";
428
+ const hasCommandOverride = target.coverage?.command !== void 0 && target.coverage.command !== defaultCommand;
429
+ const ok = import_chalk2.default.green("\u2713");
430
+ const unset = import_chalk2.default.dim("-");
416
431
  const namingHint = hasNamingOverride ? String(effectiveNaming) : `inherits: ${effectiveNaming ?? "not set"}`;
417
432
  const maxLinesHint = hasMaxLinesOverride ? String(effectiveMaxLines) : `inherits: ${effectiveMaxLines}`;
433
+ const coverageHint2 = hasCoverageOverride ? String(effectiveCoverage) : `inherits: ${effectiveCoverage}`;
434
+ const summaryHint = hasSummaryOverride ? effectiveSummary : `inherits: ${effectiveSummary}`;
435
+ const commandHint = hasCommandOverride ? effectiveCommand : `inherits: ${effectiveCommand}`;
418
436
  const choice = await clack2.select({
419
437
  message: `Edit overrides for ${target.path}`,
420
438
  options: [
421
- { value: "fileNaming", label: "File naming", hint: namingHint },
422
- { value: "maxFileLines", label: "Max file lines", hint: maxLinesHint },
423
- { value: "testCoverage", label: "Test coverage", hint: String(effectiveCoverage) },
424
- { value: "summaryPath", label: "Coverage summary path", hint: effectiveSummary },
425
- { value: "command", label: "Coverage command", hint: effectiveCommand },
426
- { value: "reset", label: "Reset all overrides for this package" },
427
- { value: "back", label: "Back to package list" }
439
+ {
440
+ value: "fileNaming",
441
+ label: `${hasNamingOverride ? ok : unset} File naming`,
442
+ hint: namingHint
443
+ },
444
+ {
445
+ value: "maxFileLines",
446
+ label: `${hasMaxLinesOverride ? ok : unset} Max file lines`,
447
+ hint: maxLinesHint
448
+ },
449
+ {
450
+ value: "testCoverage",
451
+ label: `${hasCoverageOverride ? ok : unset} Test coverage`,
452
+ hint: coverageHint2
453
+ },
454
+ {
455
+ value: "summaryPath",
456
+ label: `${hasSummaryOverride ? ok : unset} Coverage summary path`,
457
+ hint: summaryHint
458
+ },
459
+ {
460
+ value: "command",
461
+ label: `${hasCommandOverride ? ok : unset} Coverage command`,
462
+ hint: commandHint
463
+ },
464
+ { value: "reset", label: " Reset all overrides for this package" },
465
+ { value: "back", label: " Back to package list" }
428
466
  ]
429
467
  });
430
468
  if (isCancelled(choice) || choice === "back") break;
@@ -504,8 +542,8 @@ async function promptSinglePackageOverrides(target, defaults) {
504
542
  });
505
543
  if (isCancelled(result)) continue;
506
544
  const value = result.trim();
507
- const defaultCommand = defaults.coverageCommand ?? "";
508
- if (value.length === 0 || value === defaultCommand) {
545
+ const defaultCommand2 = defaults.coverageCommand ?? "";
546
+ if (value.length === 0 || value === defaultCommand2) {
509
547
  if (target.coverage) delete target.coverage.command;
510
548
  } else {
511
549
  target.coverage = { ...target.coverage ?? {}, command: value };
@@ -768,48 +806,48 @@ async function boundariesCommand(options, cwd) {
768
806
  }
769
807
  function displayRules(config) {
770
808
  if (!config.boundaries || Object.keys(config.boundaries.deny).length === 0) {
771
- console.log(import_chalk2.default.yellow("No boundary rules configured."));
772
- console.log(`Run ${import_chalk2.default.cyan("viberails boundaries --infer")} to generate rules.`);
809
+ console.log(import_chalk3.default.yellow("No boundary rules configured."));
810
+ console.log(`Run ${import_chalk3.default.cyan("viberails boundaries --infer")} to generate rules.`);
773
811
  return;
774
812
  }
775
813
  const { deny } = config.boundaries;
776
814
  const sources = Object.keys(deny).filter((k) => deny[k].length > 0);
777
815
  const totalRules = sources.reduce((sum, k) => sum + deny[k].length, 0);
778
816
  console.log(`
779
- ${import_chalk2.default.bold(`Boundary rules (${totalRules} deny rules):`)}
817
+ ${import_chalk3.default.bold(`Boundary rules (${totalRules} deny rules):`)}
780
818
  `);
781
819
  for (const source of sources) {
782
820
  for (const target of deny[source]) {
783
- console.log(` ${import_chalk2.default.red("\u2717")} ${source} \u2192 ${target}`);
821
+ console.log(` ${import_chalk3.default.red("\u2717")} ${source} \u2192 ${target}`);
784
822
  }
785
823
  }
786
824
  console.log(
787
825
  `
788
- Enforcement: ${config.rules.enforceBoundaries ? import_chalk2.default.green("on") : import_chalk2.default.yellow("off")}`
826
+ Enforcement: ${config.rules.enforceBoundaries ? import_chalk3.default.green("on") : import_chalk3.default.yellow("off")}`
789
827
  );
790
828
  }
791
829
  async function inferAndDisplay(projectRoot, config, configPath) {
792
- console.log(import_chalk2.default.dim("Analyzing imports..."));
830
+ console.log(import_chalk3.default.dim("Analyzing imports..."));
793
831
  const { buildImportGraph, inferBoundaries } = await import("@viberails/graph");
794
832
  const packages = config.packages.length > 1 ? resolveWorkspacePackages(projectRoot, config.packages) : void 0;
795
833
  const graph = await buildImportGraph(projectRoot, {
796
834
  packages,
797
835
  ignore: config.ignore
798
836
  });
799
- console.log(import_chalk2.default.dim(`${graph.nodes.length} files, ${graph.edges.length} edges`));
837
+ console.log(import_chalk3.default.dim(`${graph.nodes.length} files, ${graph.edges.length} edges`));
800
838
  const inferred = inferBoundaries(graph);
801
839
  const sources = Object.keys(inferred.deny).filter((k) => inferred.deny[k].length > 0);
802
840
  const totalRules = sources.reduce((sum, k) => sum + inferred.deny[k].length, 0);
803
841
  if (totalRules === 0) {
804
- console.log(import_chalk2.default.yellow("No boundary rules could be inferred."));
842
+ console.log(import_chalk3.default.yellow("No boundary rules could be inferred."));
805
843
  return;
806
844
  }
807
845
  console.log(`
808
- ${import_chalk2.default.bold("Inferred boundary rules:")}
846
+ ${import_chalk3.default.bold("Inferred boundary rules:")}
809
847
  `);
810
848
  for (const source of sources) {
811
849
  for (const target of inferred.deny[source]) {
812
- console.log(` ${import_chalk2.default.red("\u2717")} ${source} \u2192 ${target}`);
850
+ console.log(` ${import_chalk3.default.red("\u2717")} ${source} \u2192 ${target}`);
813
851
  }
814
852
  }
815
853
  console.log(`
@@ -821,11 +859,11 @@ ${import_chalk2.default.bold("Inferred boundary rules:")}
821
859
  config.rules.enforceBoundaries = true;
822
860
  fs3.writeFileSync(configPath, `${JSON.stringify((0, import_config.compactConfig)(config), null, 2)}
823
861
  `);
824
- console.log(`${import_chalk2.default.green("\u2713")} Saved ${totalRules} rules`);
862
+ console.log(`${import_chalk3.default.green("\u2713")} Saved ${totalRules} rules`);
825
863
  }
826
864
  }
827
865
  async function showGraph(projectRoot, config) {
828
- console.log(import_chalk2.default.dim("Building import graph..."));
866
+ console.log(import_chalk3.default.dim("Building import graph..."));
829
867
  const { buildImportGraph } = await import("@viberails/graph");
830
868
  const packages = config.packages.length > 1 ? resolveWorkspacePackages(projectRoot, config.packages) : void 0;
831
869
  const graph = await buildImportGraph(projectRoot, {
@@ -833,20 +871,20 @@ async function showGraph(projectRoot, config) {
833
871
  ignore: config.ignore
834
872
  });
835
873
  console.log(`
836
- ${import_chalk2.default.bold("Import dependency graph:")}
874
+ ${import_chalk3.default.bold("Import dependency graph:")}
837
875
  `);
838
876
  console.log(` ${graph.nodes.length} files, ${graph.edges.length} imports
839
877
  `);
840
878
  if (graph.packages.length > 0) {
841
879
  for (const pkg of graph.packages) {
842
880
  const deps = pkg.internalDeps.length > 0 ? `
843
- ${pkg.internalDeps.map((d) => ` \u2192 ${d}`).join("\n")}` : import_chalk2.default.dim(" (no internal deps)");
881
+ ${pkg.internalDeps.map((d) => ` \u2192 ${d}`).join("\n")}` : import_chalk3.default.dim(" (no internal deps)");
844
882
  console.log(` ${pkg.name}${deps}`);
845
883
  }
846
884
  }
847
885
  if (graph.cycles.length > 0) {
848
886
  console.log(`
849
- ${import_chalk2.default.yellow("Cycles detected:")}`);
887
+ ${import_chalk3.default.yellow("Cycles detected:")}`);
850
888
  for (const cycle of graph.cycles) {
851
889
  const paths = cycle.map((f) => path3.relative(projectRoot, f));
852
890
  console.log(` ${paths.join(" \u2192 ")}`);
@@ -858,7 +896,7 @@ ${import_chalk2.default.yellow("Cycles detected:")}`);
858
896
  var fs7 = __toESM(require("fs"), 1);
859
897
  var path7 = __toESM(require("path"), 1);
860
898
  var import_config5 = require("@viberails/config");
861
- var import_chalk4 = __toESM(require("chalk"), 1);
899
+ var import_chalk5 = __toESM(require("chalk"), 1);
862
900
 
863
901
  // src/commands/check-config.ts
864
902
  var import_config2 = require("@viberails/config");
@@ -1250,7 +1288,7 @@ function collectSourceFiles(dir, projectRoot) {
1250
1288
  }
1251
1289
 
1252
1290
  // src/commands/check-print.ts
1253
- var import_chalk3 = __toESM(require("chalk"), 1);
1291
+ var import_chalk4 = __toESM(require("chalk"), 1);
1254
1292
  function printGroupedViolations(violations, limit) {
1255
1293
  const groups = /* @__PURE__ */ new Map();
1256
1294
  for (const v of violations) {
@@ -1278,12 +1316,12 @@ function printGroupedViolations(violations, limit) {
1278
1316
  const toShow = group.slice(0, remaining);
1279
1317
  const hidden = group.length - toShow.length;
1280
1318
  for (const v of toShow) {
1281
- const icon = v.severity === "error" ? import_chalk3.default.red("\u2717") : import_chalk3.default.yellow("!");
1282
- console.log(`${icon} ${import_chalk3.default.dim(v.rule)} ${v.file}: ${v.message}`);
1319
+ const icon = v.severity === "error" ? import_chalk4.default.red("\u2717") : import_chalk4.default.yellow("!");
1320
+ console.log(`${icon} ${import_chalk4.default.dim(v.rule)} ${v.file}: ${v.message}`);
1283
1321
  }
1284
1322
  totalShown += toShow.length;
1285
1323
  if (hidden > 0) {
1286
- console.log(import_chalk3.default.dim(` ... and ${hidden} more ${rule} violations`));
1324
+ console.log(import_chalk4.default.dim(` ... and ${hidden} more ${rule} violations`));
1287
1325
  }
1288
1326
  }
1289
1327
  }
@@ -1373,13 +1411,13 @@ async function checkCommand(options, cwd) {
1373
1411
  const startDir = cwd ?? process.cwd();
1374
1412
  const projectRoot = findProjectRoot(startDir);
1375
1413
  if (!projectRoot) {
1376
- console.error(`${import_chalk4.default.red("Error:")} No package.json found. Are you in a JS/TS project?`);
1414
+ console.error(`${import_chalk5.default.red("Error:")} No package.json found. Are you in a JS/TS project?`);
1377
1415
  return 1;
1378
1416
  }
1379
1417
  const configPath = path7.join(projectRoot, CONFIG_FILE2);
1380
1418
  if (!fs7.existsSync(configPath)) {
1381
1419
  console.error(
1382
- `${import_chalk4.default.red("Error:")} No viberails.config.json found. Run \`viberails init\` first.`
1420
+ `${import_chalk5.default.red("Error:")} No viberails.config.json found. Run \`viberails init\` first.`
1383
1421
  );
1384
1422
  return 1;
1385
1423
  }
@@ -1393,7 +1431,7 @@ async function checkCommand(options, cwd) {
1393
1431
  } else if (options.diffBase) {
1394
1432
  const diff = getDiffFiles(projectRoot, options.diffBase);
1395
1433
  if (diff.error && options.enforce) {
1396
- console.error(`${import_chalk4.default.red("Error:")} ${diff.error}`);
1434
+ console.error(`${import_chalk5.default.red("Error:")} ${diff.error}`);
1397
1435
  return 1;
1398
1436
  }
1399
1437
  filesToCheck = diff.all.filter((f) => SOURCE_EXTS.has(path7.extname(f)));
@@ -1408,13 +1446,13 @@ async function checkCommand(options, cwd) {
1408
1446
  if (options.format === "json") {
1409
1447
  console.log(JSON.stringify({ violations: [], checkedFiles: 0 }));
1410
1448
  } else {
1411
- console.log(`${import_chalk4.default.green("\u2713")} No files to check.`);
1449
+ console.log(`${import_chalk5.default.green("\u2713")} No files to check.`);
1412
1450
  }
1413
1451
  return 0;
1414
1452
  }
1415
1453
  const violations = [];
1416
1454
  const severity = options.enforce ? "error" : "warn";
1417
- const log9 = options.format !== "json" && !options.hook && !options.quiet ? (msg) => process.stderr.write(import_chalk4.default.dim(msg)) : () => {
1455
+ const log9 = options.format !== "json" && !options.hook && !options.quiet ? (msg) => process.stderr.write(import_chalk5.default.dim(msg)) : () => {
1418
1456
  };
1419
1457
  log9(" Checking files...");
1420
1458
  for (const file of filesToCheck) {
@@ -1509,7 +1547,7 @@ async function checkCommand(options, cwd) {
1509
1547
  return options.enforce && violations.length > 0 ? 1 : 0;
1510
1548
  }
1511
1549
  if (violations.length === 0) {
1512
- console.log(`${import_chalk4.default.green("\u2713")} ${filesToCheck.length} files checked \u2014 no violations`);
1550
+ console.log(`${import_chalk5.default.green("\u2713")} ${filesToCheck.length} files checked \u2014 no violations`);
1513
1551
  return 0;
1514
1552
  }
1515
1553
  if (!options.quiet) {
@@ -1517,7 +1555,7 @@ async function checkCommand(options, cwd) {
1517
1555
  }
1518
1556
  printSummary(violations);
1519
1557
  if (options.enforce) {
1520
- console.log(import_chalk4.default.red("Fix violations before committing."));
1558
+ console.log(import_chalk5.default.red("Fix violations before committing."));
1521
1559
  return 1;
1522
1560
  }
1523
1561
  return 0;
@@ -1575,14 +1613,14 @@ var path9 = __toESM(require("path"), 1);
1575
1613
  var clack6 = __toESM(require("@clack/prompts"), 1);
1576
1614
  var import_config6 = require("@viberails/config");
1577
1615
  var import_scanner = require("@viberails/scanner");
1578
- var import_chalk7 = __toESM(require("chalk"), 1);
1616
+ var import_chalk8 = __toESM(require("chalk"), 1);
1579
1617
 
1580
1618
  // src/display-text.ts
1581
1619
  var import_types4 = require("@viberails/types");
1582
1620
 
1583
1621
  // src/display.ts
1584
1622
  var import_types3 = require("@viberails/types");
1585
- var import_chalk6 = __toESM(require("chalk"), 1);
1623
+ var import_chalk7 = __toESM(require("chalk"), 1);
1586
1624
 
1587
1625
  // src/display-helpers.ts
1588
1626
  var import_types = require("@viberails/types");
@@ -1635,7 +1673,7 @@ function formatRoleGroup(group) {
1635
1673
 
1636
1674
  // src/display-monorepo.ts
1637
1675
  var import_types2 = require("@viberails/types");
1638
- var import_chalk5 = __toESM(require("chalk"), 1);
1676
+ var import_chalk6 = __toESM(require("chalk"), 1);
1639
1677
  function formatPackageSummary(pkg) {
1640
1678
  const parts = [];
1641
1679
  if (pkg.stack.framework) {
@@ -1652,23 +1690,23 @@ function formatPackageSummary(pkg) {
1652
1690
  function displayMonorepoResults(scanResult) {
1653
1691
  const { stack, packages } = scanResult;
1654
1692
  console.log(`
1655
- ${import_chalk5.default.bold(`Detected: (monorepo, ${packages.length} packages)`)}`);
1656
- console.log(` ${import_chalk5.default.green("\u2713")} ${formatItem(stack.language)}`);
1693
+ ${import_chalk6.default.bold(`Detected: (monorepo, ${packages.length} packages)`)}`);
1694
+ console.log(` ${import_chalk6.default.green("\u2713")} ${formatItem(stack.language)}`);
1657
1695
  if (stack.packageManager) {
1658
- console.log(` ${import_chalk5.default.green("\u2713")} ${formatItem(stack.packageManager)}`);
1696
+ console.log(` ${import_chalk6.default.green("\u2713")} ${formatItem(stack.packageManager)}`);
1659
1697
  }
1660
1698
  if (stack.linter && stack.formatter && stack.linter.name === stack.formatter.name) {
1661
- console.log(` ${import_chalk5.default.green("\u2713")} ${formatItem(stack.linter)} (lint + format)`);
1699
+ console.log(` ${import_chalk6.default.green("\u2713")} ${formatItem(stack.linter)} (lint + format)`);
1662
1700
  } else {
1663
1701
  if (stack.linter) {
1664
- console.log(` ${import_chalk5.default.green("\u2713")} ${formatItem(stack.linter)}`);
1702
+ console.log(` ${import_chalk6.default.green("\u2713")} ${formatItem(stack.linter)}`);
1665
1703
  }
1666
1704
  if (stack.formatter) {
1667
- console.log(` ${import_chalk5.default.green("\u2713")} ${formatItem(stack.formatter)}`);
1705
+ console.log(` ${import_chalk6.default.green("\u2713")} ${formatItem(stack.formatter)}`);
1668
1706
  }
1669
1707
  }
1670
1708
  if (stack.testRunner) {
1671
- console.log(` ${import_chalk5.default.green("\u2713")} ${formatItem(stack.testRunner)}`);
1709
+ console.log(` ${import_chalk6.default.green("\u2713")} ${formatItem(stack.testRunner)}`);
1672
1710
  }
1673
1711
  console.log("");
1674
1712
  for (const pkg of packages) {
@@ -1679,13 +1717,13 @@ ${import_chalk5.default.bold(`Detected: (monorepo, ${packages.length} packages)`
1679
1717
  );
1680
1718
  if (packagesWithDirs.length > 0) {
1681
1719
  console.log(`
1682
- ${import_chalk5.default.bold("Structure:")}`);
1720
+ ${import_chalk6.default.bold("Structure:")}`);
1683
1721
  for (const pkg of packagesWithDirs) {
1684
1722
  const groups = groupByRole(pkg.structure.directories);
1685
1723
  if (groups.length === 0) continue;
1686
1724
  console.log(` ${pkg.relativePath}:`);
1687
1725
  for (const group of groups) {
1688
- console.log(` ${import_chalk5.default.green("\u2713")} ${formatRoleGroup(group)}`);
1726
+ console.log(` ${import_chalk6.default.green("\u2713")} ${formatRoleGroup(group)}`);
1689
1727
  }
1690
1728
  }
1691
1729
  }
@@ -1766,7 +1804,7 @@ function displayConventions(scanResult) {
1766
1804
  const conventionEntries = Object.entries(scanResult.conventions);
1767
1805
  if (conventionEntries.length === 0) return;
1768
1806
  console.log(`
1769
- ${import_chalk6.default.bold("Conventions:")}`);
1807
+ ${import_chalk7.default.bold("Conventions:")}`);
1770
1808
  for (const [key, convention] of conventionEntries) {
1771
1809
  if (convention.confidence === "low") continue;
1772
1810
  const label = import_types3.CONVENTION_LABELS[key] ?? key;
@@ -1774,19 +1812,19 @@ ${import_chalk6.default.bold("Conventions:")}`);
1774
1812
  const pkgValues = scanResult.packages.filter((pkg) => pkg.conventions[key] && pkg.conventions[key].confidence !== "low").map((pkg) => ({ relativePath: pkg.relativePath, convention: pkg.conventions[key] }));
1775
1813
  const allSame = pkgValues.every((pv) => pv.convention.value === convention.value);
1776
1814
  if (allSame || pkgValues.length <= 1) {
1777
- const ind = convention.confidence === "high" ? import_chalk6.default.green("\u2713") : import_chalk6.default.yellow("~");
1778
- const detail = import_chalk6.default.dim(`(${confidenceLabel(convention)})`);
1815
+ const ind = convention.confidence === "high" ? import_chalk7.default.green("\u2713") : import_chalk7.default.yellow("~");
1816
+ const detail = import_chalk7.default.dim(`(${confidenceLabel(convention)})`);
1779
1817
  console.log(` ${ind} ${label}: ${convention.value} ${detail}`);
1780
1818
  } else {
1781
- console.log(` ${import_chalk6.default.yellow("~")} ${label}: varies by package`);
1819
+ console.log(` ${import_chalk7.default.yellow("~")} ${label}: varies by package`);
1782
1820
  for (const pv of pkgValues) {
1783
1821
  const pct = Math.round(pv.convention.consistency);
1784
1822
  console.log(` ${pv.relativePath}: ${pv.convention.value} (${pct}%)`);
1785
1823
  }
1786
1824
  }
1787
1825
  } else {
1788
- const ind = convention.confidence === "high" ? import_chalk6.default.green("\u2713") : import_chalk6.default.yellow("~");
1789
- const detail = import_chalk6.default.dim(`(${confidenceLabel(convention)})`);
1826
+ const ind = convention.confidence === "high" ? import_chalk7.default.green("\u2713") : import_chalk7.default.yellow("~");
1827
+ const detail = import_chalk7.default.dim(`(${confidenceLabel(convention)})`);
1790
1828
  console.log(` ${ind} ${label}: ${convention.value} ${detail}`);
1791
1829
  }
1792
1830
  }
@@ -1794,7 +1832,7 @@ ${import_chalk6.default.bold("Conventions:")}`);
1794
1832
  function displaySummarySection(scanResult) {
1795
1833
  const pkgCount = scanResult.packages.length > 1 ? scanResult.packages.length : void 0;
1796
1834
  console.log(`
1797
- ${import_chalk6.default.bold("Summary:")}`);
1835
+ ${import_chalk7.default.bold("Summary:")}`);
1798
1836
  console.log(` ${formatSummary(scanResult.statistics, pkgCount)}`);
1799
1837
  const ext = formatExtensions(scanResult.statistics.filesByExtension);
1800
1838
  if (ext) {
@@ -1808,47 +1846,47 @@ function displayScanResults(scanResult) {
1808
1846
  }
1809
1847
  const { stack } = scanResult;
1810
1848
  console.log(`
1811
- ${import_chalk6.default.bold("Detected:")}`);
1849
+ ${import_chalk7.default.bold("Detected:")}`);
1812
1850
  if (stack.framework) {
1813
- console.log(` ${import_chalk6.default.green("\u2713")} ${formatItem(stack.framework, import_types3.FRAMEWORK_NAMES)}`);
1851
+ console.log(` ${import_chalk7.default.green("\u2713")} ${formatItem(stack.framework, import_types3.FRAMEWORK_NAMES)}`);
1814
1852
  }
1815
- console.log(` ${import_chalk6.default.green("\u2713")} ${formatItem(stack.language)}`);
1853
+ console.log(` ${import_chalk7.default.green("\u2713")} ${formatItem(stack.language)}`);
1816
1854
  if (stack.styling) {
1817
- console.log(` ${import_chalk6.default.green("\u2713")} ${formatItem(stack.styling, import_types3.STYLING_NAMES)}`);
1855
+ console.log(` ${import_chalk7.default.green("\u2713")} ${formatItem(stack.styling, import_types3.STYLING_NAMES)}`);
1818
1856
  }
1819
1857
  if (stack.backend) {
1820
- console.log(` ${import_chalk6.default.green("\u2713")} ${formatItem(stack.backend, import_types3.FRAMEWORK_NAMES)}`);
1858
+ console.log(` ${import_chalk7.default.green("\u2713")} ${formatItem(stack.backend, import_types3.FRAMEWORK_NAMES)}`);
1821
1859
  }
1822
1860
  if (stack.orm) {
1823
- console.log(` ${import_chalk6.default.green("\u2713")} ${formatItem(stack.orm, import_types3.ORM_NAMES)}`);
1861
+ console.log(` ${import_chalk7.default.green("\u2713")} ${formatItem(stack.orm, import_types3.ORM_NAMES)}`);
1824
1862
  }
1825
1863
  if (stack.linter && stack.formatter && stack.linter.name === stack.formatter.name) {
1826
- console.log(` ${import_chalk6.default.green("\u2713")} ${formatItem(stack.linter)} (lint + format)`);
1864
+ console.log(` ${import_chalk7.default.green("\u2713")} ${formatItem(stack.linter)} (lint + format)`);
1827
1865
  } else {
1828
1866
  if (stack.linter) {
1829
- console.log(` ${import_chalk6.default.green("\u2713")} ${formatItem(stack.linter)}`);
1867
+ console.log(` ${import_chalk7.default.green("\u2713")} ${formatItem(stack.linter)}`);
1830
1868
  }
1831
1869
  if (stack.formatter) {
1832
- console.log(` ${import_chalk6.default.green("\u2713")} ${formatItem(stack.formatter)}`);
1870
+ console.log(` ${import_chalk7.default.green("\u2713")} ${formatItem(stack.formatter)}`);
1833
1871
  }
1834
1872
  }
1835
1873
  if (stack.testRunner) {
1836
- console.log(` ${import_chalk6.default.green("\u2713")} ${formatItem(stack.testRunner)}`);
1874
+ console.log(` ${import_chalk7.default.green("\u2713")} ${formatItem(stack.testRunner)}`);
1837
1875
  }
1838
1876
  if (stack.packageManager) {
1839
- console.log(` ${import_chalk6.default.green("\u2713")} ${formatItem(stack.packageManager)}`);
1877
+ console.log(` ${import_chalk7.default.green("\u2713")} ${formatItem(stack.packageManager)}`);
1840
1878
  }
1841
1879
  if (stack.libraries.length > 0) {
1842
1880
  for (const lib of stack.libraries) {
1843
- console.log(` ${import_chalk6.default.green("\u2713")} ${formatItem(lib, import_types3.LIBRARY_NAMES)}`);
1881
+ console.log(` ${import_chalk7.default.green("\u2713")} ${formatItem(lib, import_types3.LIBRARY_NAMES)}`);
1844
1882
  }
1845
1883
  }
1846
1884
  const groups = groupByRole(scanResult.structure.directories);
1847
1885
  if (groups.length > 0) {
1848
1886
  console.log(`
1849
- ${import_chalk6.default.bold("Structure:")}`);
1887
+ ${import_chalk7.default.bold("Structure:")}`);
1850
1888
  for (const group of groups) {
1851
- console.log(` ${import_chalk6.default.green("\u2713")} ${formatRoleGroup(group)}`);
1889
+ console.log(` ${import_chalk7.default.green("\u2713")} ${formatRoleGroup(group)}`);
1852
1890
  }
1853
1891
  }
1854
1892
  displayConventions(scanResult);
@@ -1858,25 +1896,25 @@ ${import_chalk6.default.bold("Structure:")}`);
1858
1896
  function displayRulesPreview(config) {
1859
1897
  const root = config.packages.find((p) => p.path === ".") ?? config.packages[0];
1860
1898
  console.log(
1861
- `${import_chalk6.default.bold("Rules:")} ${import_chalk6.default.dim("(warns on violation; use --enforce in CI to block)")}`
1899
+ `${import_chalk7.default.bold("Rules:")} ${import_chalk7.default.dim("(warns on violation; use --enforce in CI to block)")}`
1862
1900
  );
1863
- console.log(` ${import_chalk6.default.dim("\u2022")} Max file size: ${config.rules.maxFileLines} lines`);
1901
+ console.log(` ${import_chalk7.default.dim("\u2022")} Max file size: ${config.rules.maxFileLines} lines`);
1864
1902
  if (config.rules.testCoverage > 0 && root?.structure?.testPattern) {
1865
1903
  console.log(
1866
- ` ${import_chalk6.default.dim("\u2022")} Test coverage target: ${config.rules.testCoverage}% (${root.structure.testPattern})`
1904
+ ` ${import_chalk7.default.dim("\u2022")} Test coverage target: ${config.rules.testCoverage}% (${root.structure.testPattern})`
1867
1905
  );
1868
1906
  } else if (config.rules.testCoverage > 0) {
1869
- console.log(` ${import_chalk6.default.dim("\u2022")} Test coverage target: ${config.rules.testCoverage}%`);
1907
+ console.log(` ${import_chalk7.default.dim("\u2022")} Test coverage target: ${config.rules.testCoverage}%`);
1870
1908
  } else {
1871
- console.log(` ${import_chalk6.default.dim("\u2022")} Test coverage target: disabled`);
1909
+ console.log(` ${import_chalk7.default.dim("\u2022")} Test coverage target: disabled`);
1872
1910
  }
1873
1911
  if (config.rules.enforceNaming && root?.conventions?.fileNaming) {
1874
- console.log(` ${import_chalk6.default.dim("\u2022")} Enforce file naming: ${root.conventions.fileNaming}`);
1912
+ console.log(` ${import_chalk7.default.dim("\u2022")} Enforce file naming: ${root.conventions.fileNaming}`);
1875
1913
  } else {
1876
- console.log(` ${import_chalk6.default.dim("\u2022")} Enforce file naming: no`);
1914
+ console.log(` ${import_chalk7.default.dim("\u2022")} Enforce file naming: no`);
1877
1915
  }
1878
1916
  console.log(
1879
- ` ${import_chalk6.default.dim("\u2022")} Enforce boundaries: ${config.rules.enforceBoundaries ? "yes" : "no"}`
1917
+ ` ${import_chalk7.default.dim("\u2022")} Enforce boundaries: ${config.rules.enforceBoundaries ? "yes" : "no"}`
1880
1918
  );
1881
1919
  console.log("");
1882
1920
  }
@@ -2201,7 +2239,7 @@ async function configCommand(options, cwd) {
2201
2239
  }
2202
2240
  const configPath = path9.join(projectRoot, CONFIG_FILE3);
2203
2241
  if (!fs10.existsSync(configPath)) {
2204
- console.log(`${import_chalk7.default.yellow("!")} No config found. Run ${import_chalk7.default.cyan("viberails")} first.`);
2242
+ console.log(`${import_chalk8.default.yellow("!")} No config found. Run ${import_chalk8.default.cyan("viberails")} first.`);
2205
2243
  return;
2206
2244
  }
2207
2245
  if (!options.suppressIntro) {
@@ -2292,22 +2330,22 @@ async function rescanAndMerge(projectRoot, config) {
2292
2330
  var fs13 = __toESM(require("fs"), 1);
2293
2331
  var path13 = __toESM(require("path"), 1);
2294
2332
  var import_config7 = require("@viberails/config");
2295
- var import_chalk9 = __toESM(require("chalk"), 1);
2333
+ var import_chalk10 = __toESM(require("chalk"), 1);
2296
2334
 
2297
2335
  // src/commands/fix-helpers.ts
2298
2336
  var import_node_child_process3 = require("child_process");
2299
- var import_chalk8 = __toESM(require("chalk"), 1);
2337
+ var import_chalk9 = __toESM(require("chalk"), 1);
2300
2338
  function printPlan(renames, stubs) {
2301
2339
  if (renames.length > 0) {
2302
- console.log(import_chalk8.default.bold("\nFile renames:"));
2340
+ console.log(import_chalk9.default.bold("\nFile renames:"));
2303
2341
  for (const r of renames) {
2304
- console.log(` ${import_chalk8.default.red(r.oldPath)} \u2192 ${import_chalk8.default.green(r.newPath)}`);
2342
+ console.log(` ${import_chalk9.default.red(r.oldPath)} \u2192 ${import_chalk9.default.green(r.newPath)}`);
2305
2343
  }
2306
2344
  }
2307
2345
  if (stubs.length > 0) {
2308
- console.log(import_chalk8.default.bold("\nTest stubs to create:"));
2346
+ console.log(import_chalk9.default.bold("\nTest stubs to create:"));
2309
2347
  for (const s of stubs) {
2310
- console.log(` ${import_chalk8.default.green("+")} ${s.path}`);
2348
+ console.log(` ${import_chalk9.default.green("+")} ${s.path}`);
2311
2349
  }
2312
2350
  }
2313
2351
  }
@@ -2635,13 +2673,13 @@ async function fixCommand(options, cwd) {
2635
2673
  const startDir = cwd ?? process.cwd();
2636
2674
  const projectRoot = findProjectRoot(startDir);
2637
2675
  if (!projectRoot) {
2638
- console.error(`${import_chalk9.default.red("Error:")} No package.json found. Are you in a JS/TS project?`);
2676
+ console.error(`${import_chalk10.default.red("Error:")} No package.json found. Are you in a JS/TS project?`);
2639
2677
  return 1;
2640
2678
  }
2641
2679
  const configPath = path13.join(projectRoot, CONFIG_FILE4);
2642
2680
  if (!fs13.existsSync(configPath)) {
2643
2681
  console.error(
2644
- `${import_chalk9.default.red("Error:")} No viberails.config.json found. Run \`viberails init\` first.`
2682
+ `${import_chalk10.default.red("Error:")} No viberails.config.json found. Run \`viberails init\` first.`
2645
2683
  );
2646
2684
  return 1;
2647
2685
  }
@@ -2650,7 +2688,7 @@ async function fixCommand(options, cwd) {
2650
2688
  const isDirty = checkGitDirty(projectRoot);
2651
2689
  if (isDirty) {
2652
2690
  console.log(
2653
- import_chalk9.default.yellow("Warning: You have uncommitted changes. Consider committing first.")
2691
+ import_chalk10.default.yellow("Warning: You have uncommitted changes. Consider committing first.")
2654
2692
  );
2655
2693
  }
2656
2694
  }
@@ -2697,41 +2735,41 @@ async function fixCommand(options, cwd) {
2697
2735
  return blockedOldBareNames.has(bare);
2698
2736
  });
2699
2737
  if (safeRenames.length === 0 && testStubs.length === 0 && skippedRenames.length === 0) {
2700
- console.log(`${import_chalk9.default.green("\u2713")} No fixable violations found.`);
2738
+ console.log(`${import_chalk10.default.green("\u2713")} No fixable violations found.`);
2701
2739
  return 0;
2702
2740
  }
2703
2741
  printPlan(safeRenames, testStubs);
2704
2742
  if (skippedRenames.length > 0) {
2705
2743
  console.log("");
2706
2744
  console.log(
2707
- import_chalk9.default.yellow(
2745
+ import_chalk10.default.yellow(
2708
2746
  `Skipping ${skippedRenames.length} rename${skippedRenames.length > 1 ? "s" : ""} \u2014 aliased imports would break:`
2709
2747
  )
2710
2748
  );
2711
2749
  for (const r of skippedRenames.slice(0, 5)) {
2712
- console.log(import_chalk9.default.dim(` ${r.oldPath} \u2192 ${r.newPath}`));
2750
+ console.log(import_chalk10.default.dim(` ${r.oldPath} \u2192 ${r.newPath}`));
2713
2751
  }
2714
2752
  if (skippedRenames.length > 5) {
2715
- console.log(import_chalk9.default.dim(` ... and ${skippedRenames.length - 5} more`));
2753
+ console.log(import_chalk10.default.dim(` ... and ${skippedRenames.length - 5} more`));
2716
2754
  }
2717
2755
  console.log("");
2718
- console.log(import_chalk9.default.yellow("Affected aliased imports:"));
2756
+ console.log(import_chalk10.default.yellow("Affected aliased imports:"));
2719
2757
  for (const alias of aliasImports.slice(0, 5)) {
2720
2758
  const relFile = path13.relative(projectRoot, alias.file);
2721
- console.log(import_chalk9.default.dim(` ${relFile}:${alias.line} \u2014 ${alias.specifier}`));
2759
+ console.log(import_chalk10.default.dim(` ${relFile}:${alias.line} \u2014 ${alias.specifier}`));
2722
2760
  }
2723
2761
  if (aliasImports.length > 5) {
2724
- console.log(import_chalk9.default.dim(` ... and ${aliasImports.length - 5} more`));
2762
+ console.log(import_chalk10.default.dim(` ... and ${aliasImports.length - 5} more`));
2725
2763
  }
2726
- console.log(import_chalk9.default.dim(" Update these imports to relative paths first, then re-run fix."));
2764
+ console.log(import_chalk10.default.dim(" Update these imports to relative paths first, then re-run fix."));
2727
2765
  }
2728
2766
  if (safeRenames.length === 0 && testStubs.length === 0) {
2729
2767
  console.log(`
2730
- ${import_chalk9.default.yellow("!")} No safe fixes to apply. Resolve aliased imports first.`);
2768
+ ${import_chalk10.default.yellow("!")} No safe fixes to apply. Resolve aliased imports first.`);
2731
2769
  return 0;
2732
2770
  }
2733
2771
  if (options.dryRun) {
2734
- console.log(import_chalk9.default.dim("\nDry run \u2014 no changes applied."));
2772
+ console.log(import_chalk10.default.dim("\nDry run \u2014 no changes applied."));
2735
2773
  return 0;
2736
2774
  }
2737
2775
  if (!options.yes) {
@@ -2762,15 +2800,15 @@ ${import_chalk9.default.yellow("!")} No safe fixes to apply. Resolve aliased imp
2762
2800
  }
2763
2801
  console.log("");
2764
2802
  if (renameCount > 0) {
2765
- console.log(`${import_chalk9.default.green("\u2713")} Renamed ${renameCount} file${renameCount > 1 ? "s" : ""}`);
2803
+ console.log(`${import_chalk10.default.green("\u2713")} Renamed ${renameCount} file${renameCount > 1 ? "s" : ""}`);
2766
2804
  }
2767
2805
  if (importUpdateCount > 0) {
2768
2806
  console.log(
2769
- `${import_chalk9.default.green("\u2713")} Updated ${importUpdateCount} import${importUpdateCount > 1 ? "s" : ""}`
2807
+ `${import_chalk10.default.green("\u2713")} Updated ${importUpdateCount} import${importUpdateCount > 1 ? "s" : ""}`
2770
2808
  );
2771
2809
  }
2772
2810
  if (stubCount > 0) {
2773
- console.log(`${import_chalk9.default.green("\u2713")} Generated ${stubCount} test stub${stubCount > 1 ? "s" : ""}`);
2811
+ console.log(`${import_chalk10.default.green("\u2713")} Generated ${stubCount} test stub${stubCount > 1 ? "s" : ""}`);
2774
2812
  }
2775
2813
  return 0;
2776
2814
  }
@@ -2781,13 +2819,13 @@ var path21 = __toESM(require("path"), 1);
2781
2819
  var clack13 = __toESM(require("@clack/prompts"), 1);
2782
2820
  var import_config9 = require("@viberails/config");
2783
2821
  var import_scanner3 = require("@viberails/scanner");
2784
- var import_chalk15 = __toESM(require("chalk"), 1);
2822
+ var import_chalk16 = __toESM(require("chalk"), 1);
2785
2823
 
2786
2824
  // src/utils/check-prerequisites.ts
2787
2825
  var fs14 = __toESM(require("fs"), 1);
2788
2826
  var path14 = __toESM(require("path"), 1);
2789
2827
  var clack7 = __toESM(require("@clack/prompts"), 1);
2790
- var import_chalk10 = __toESM(require("chalk"), 1);
2828
+ var import_chalk11 = __toESM(require("chalk"), 1);
2791
2829
 
2792
2830
  // src/utils/spawn-async.ts
2793
2831
  var import_node_child_process4 = require("child_process");
@@ -2842,9 +2880,9 @@ function displayMissingPrereqs(prereqs) {
2842
2880
  const missing = prereqs.filter((p) => !p.installed);
2843
2881
  for (const m of missing) {
2844
2882
  const suffix = m.affectedPackages ? ` \u2014 needed for coverage in: ${m.affectedPackages.join(", ")}` : ` \u2014 ${m.reason}`;
2845
- console.log(` ${import_chalk10.default.yellow("!")} ${m.label} not installed${suffix}`);
2883
+ console.log(` ${import_chalk11.default.yellow("!")} ${m.label} not installed${suffix}`);
2846
2884
  if (m.installCommand) {
2847
- console.log(` Install: ${import_chalk10.default.cyan(m.installCommand)}`);
2885
+ console.log(` Install: ${import_chalk11.default.cyan(m.installCommand)}`);
2848
2886
  }
2849
2887
  }
2850
2888
  }
@@ -3169,7 +3207,7 @@ async function handleIntegrations(state, opts) {
3169
3207
  }
3170
3208
 
3171
3209
  // src/utils/prompt-main-menu-hints.ts
3172
- var import_chalk11 = __toESM(require("chalk"), 1);
3210
+ var import_chalk12 = __toESM(require("chalk"), 1);
3173
3211
  function fileLimitsHint(config) {
3174
3212
  const max = config.rules.maxFileLines;
3175
3213
  const test = config.rules.maxTestFileLines;
@@ -3188,7 +3226,7 @@ function fileNamingHint(config, scanResult) {
3188
3226
  return "mixed \u2014 will not enforce if skipped";
3189
3227
  }
3190
3228
  function fileNamingStatus(config) {
3191
- if (!config.rules.enforceNaming) return "disabled";
3229
+ if (!config.rules.enforceNaming) return "unconfigured";
3192
3230
  const rootPkg = getRootPackage(config.packages);
3193
3231
  return rootPkg.conventions?.fileNaming ? "ok" : "needs-input";
3194
3232
  }
@@ -3215,28 +3253,27 @@ function coverageHint(config, hasTestRunner) {
3215
3253
  function advancedNamingHint(config) {
3216
3254
  const rootPkg = getRootPackage(config.packages);
3217
3255
  if (!config.rules.enforceNaming) return "not enforced";
3218
- const parts = [];
3219
- const naming = rootPkg.conventions?.fileNaming;
3220
- if (naming) parts.push(import_chalk11.default.green(naming));
3221
- const comp = rootPkg.conventions?.componentNaming;
3222
- parts.push(comp ? import_chalk11.default.green(`${comp} components`) : import_chalk11.default.dim("components"));
3223
- const hook = rootPkg.conventions?.hookNaming;
3224
- parts.push(hook ? import_chalk11.default.green(`${hook} hooks`) : import_chalk11.default.dim("hooks"));
3225
- const alias = rootPkg.conventions?.importAlias;
3226
- parts.push(alias ? import_chalk11.default.green(alias) : import_chalk11.default.dim("alias"));
3227
- return parts.join(import_chalk11.default.dim(", "));
3256
+ const ok = import_chalk12.default.green("\u2713");
3257
+ const no = import_chalk12.default.dim("\u2717");
3258
+ const parts = [
3259
+ `${rootPkg.conventions?.fileNaming ? ok : no} file naming`,
3260
+ `${rootPkg.conventions?.componentNaming ? ok : no} components`,
3261
+ `${rootPkg.conventions?.hookNaming ? ok : no} hooks`,
3262
+ `${rootPkg.conventions?.importAlias ? ok : no} alias`
3263
+ ];
3264
+ return parts.join(import_chalk12.default.dim(", "));
3228
3265
  }
3229
3266
  function integrationsHint(state) {
3230
3267
  if (!state.visited.integrations || !state.integrations)
3231
3268
  return "not configured \u2014 select to set up";
3232
3269
  const items = [];
3233
- if (state.integrations.preCommitHook) items.push(import_chalk11.default.green("pre-commit"));
3234
- if (state.integrations.typecheckHook) items.push(import_chalk11.default.green("typecheck"));
3235
- if (state.integrations.lintHook) items.push(import_chalk11.default.green("lint"));
3236
- if (state.integrations.claudeCodeHook) items.push(import_chalk11.default.green("Claude"));
3237
- if (state.integrations.claudeMdRef) items.push(import_chalk11.default.green("CLAUDE.md"));
3238
- if (state.integrations.githubAction) items.push(import_chalk11.default.green("CI"));
3239
- return items.length > 0 ? items.join(import_chalk11.default.dim(" \xB7 ")) : "none selected";
3270
+ if (state.integrations.preCommitHook) items.push(import_chalk12.default.green("pre-commit"));
3271
+ if (state.integrations.typecheckHook) items.push(import_chalk12.default.green("typecheck"));
3272
+ if (state.integrations.lintHook) items.push(import_chalk12.default.green("lint"));
3273
+ if (state.integrations.claudeCodeHook) items.push(import_chalk12.default.green("Claude"));
3274
+ if (state.integrations.claudeMdRef) items.push(import_chalk12.default.green("CLAUDE.md"));
3275
+ if (state.integrations.githubAction) items.push(import_chalk12.default.green("CI"));
3276
+ return items.length > 0 ? items.join(import_chalk12.default.dim(" \xB7 ")) : "none selected";
3240
3277
  }
3241
3278
  function packageOverridesHint(config) {
3242
3279
  const rootNaming = getRootPackage(config.packages).conventions?.fileNaming;
@@ -3255,10 +3292,15 @@ function boundariesHint(config, state) {
3255
3292
  return `${ruleCount} rules across ${pkgCount} packages`;
3256
3293
  }
3257
3294
  function advancedNamingStatus(config) {
3258
- if (!config.rules.enforceNaming) return "disabled";
3295
+ if (!config.rules.enforceNaming) return "unconfigured";
3259
3296
  const rootPkg = getRootPackage(config.packages);
3260
- const hasAny = !!rootPkg.conventions?.fileNaming || !!rootPkg.conventions?.componentNaming || !!rootPkg.conventions?.hookNaming || !!rootPkg.conventions?.importAlias;
3261
- return hasAny ? "ok" : "unconfigured";
3297
+ const hasFile = !!rootPkg.conventions?.fileNaming;
3298
+ const hasComp = !!rootPkg.conventions?.componentNaming;
3299
+ const hasHook = !!rootPkg.conventions?.hookNaming;
3300
+ const hasAlias = !!rootPkg.conventions?.importAlias;
3301
+ if (hasFile && hasComp && hasHook && hasAlias) return "ok";
3302
+ if (hasFile || hasComp || hasHook || hasAlias) return "partial";
3303
+ return "unconfigured";
3262
3304
  }
3263
3305
  function packageOverridesStatus(config) {
3264
3306
  const rootNaming = getRootPackage(config.packages).conventions?.fileNaming;
@@ -3269,15 +3311,15 @@ function packageOverridesStatus(config) {
3269
3311
  return customized ? "ok" : "unconfigured";
3270
3312
  }
3271
3313
  function statusIcon(status) {
3272
- if (status === "ok") return import_chalk11.default.green("\u2713");
3273
- if (status === "needs-input") return import_chalk11.default.yellow("?");
3274
- if (status === "unconfigured") return import_chalk11.default.dim("-");
3275
- return import_chalk11.default.yellow("~");
3314
+ if (status === "ok") return import_chalk12.default.green("\u2713");
3315
+ if (status === "needs-input") return import_chalk12.default.yellow("?");
3316
+ if (status === "unconfigured") return import_chalk12.default.dim("-");
3317
+ return import_chalk12.default.yellow("~");
3276
3318
  }
3277
3319
  function buildMainMenuOptions(config, scanResult, state) {
3278
3320
  const namingStatus = fileNamingStatus(config);
3279
- const coverageStatus = config.rules.testCoverage === 0 ? "disabled" : !state.hasTestRunner ? "disabled" : "ok";
3280
- const missingTestsStatus = config.rules.enforceMissingTests ? "ok" : "disabled";
3321
+ const coverageStatus = config.rules.testCoverage === 0 ? "unconfigured" : !state.hasTestRunner ? "partial" : "ok";
3322
+ const missingTestsStatus = config.rules.enforceMissingTests ? "ok" : "unconfigured";
3281
3323
  const options = [
3282
3324
  {
3283
3325
  value: "fileLimits",
@@ -3403,7 +3445,7 @@ function updateGitignore(projectRoot) {
3403
3445
  // src/commands/init-hooks.ts
3404
3446
  var fs18 = __toESM(require("fs"), 1);
3405
3447
  var path18 = __toESM(require("path"), 1);
3406
- var import_chalk12 = __toESM(require("chalk"), 1);
3448
+ var import_chalk13 = __toESM(require("chalk"), 1);
3407
3449
  var import_yaml = require("yaml");
3408
3450
 
3409
3451
  // src/commands/resolve-typecheck.ts
@@ -3448,13 +3490,13 @@ function setupPreCommitHook(projectRoot) {
3448
3490
  const lefthookPath = path18.join(projectRoot, "lefthook.yml");
3449
3491
  if (fs18.existsSync(lefthookPath)) {
3450
3492
  addLefthookPreCommit(lefthookPath);
3451
- console.log(` ${import_chalk12.default.green("\u2713")} lefthook.yml \u2014 added viberails pre-commit`);
3493
+ console.log(` ${import_chalk13.default.green("\u2713")} lefthook.yml \u2014 added viberails pre-commit`);
3452
3494
  return "lefthook.yml";
3453
3495
  }
3454
3496
  const huskyDir = path18.join(projectRoot, ".husky");
3455
3497
  if (fs18.existsSync(huskyDir)) {
3456
3498
  writeHuskyPreCommit(huskyDir);
3457
- console.log(` ${import_chalk12.default.green("\u2713")} .husky/pre-commit \u2014 added viberails check`);
3499
+ console.log(` ${import_chalk13.default.green("\u2713")} .husky/pre-commit \u2014 added viberails check`);
3458
3500
  return ".husky/pre-commit";
3459
3501
  }
3460
3502
  const gitDir = path18.join(projectRoot, ".git");
@@ -3464,7 +3506,7 @@ function setupPreCommitHook(projectRoot) {
3464
3506
  fs18.mkdirSync(hooksDir, { recursive: true });
3465
3507
  }
3466
3508
  writeGitHookPreCommit(hooksDir);
3467
- console.log(` ${import_chalk12.default.green("\u2713")} .git/hooks/pre-commit`);
3509
+ console.log(` ${import_chalk13.default.green("\u2713")} .git/hooks/pre-commit`);
3468
3510
  return ".git/hooks/pre-commit";
3469
3511
  }
3470
3512
  return void 0;
@@ -3525,9 +3567,9 @@ function setupClaudeCodeHook(projectRoot) {
3525
3567
  settings = JSON.parse(fs18.readFileSync(settingsPath, "utf-8"));
3526
3568
  } catch {
3527
3569
  console.warn(
3528
- ` ${import_chalk12.default.yellow("!")} .claude/settings.json contains invalid JSON \u2014 skipping hook setup`
3570
+ ` ${import_chalk13.default.yellow("!")} .claude/settings.json contains invalid JSON \u2014 skipping hook setup`
3529
3571
  );
3530
- console.warn(` Fix the JSON manually, then re-run ${import_chalk12.default.cyan("viberails init --force")}`);
3572
+ console.warn(` Fix the JSON manually, then re-run ${import_chalk13.default.cyan("viberails init --force")}`);
3531
3573
  return;
3532
3574
  }
3533
3575
  }
@@ -3550,7 +3592,7 @@ function setupClaudeCodeHook(projectRoot) {
3550
3592
  settings.hooks = hooks;
3551
3593
  fs18.writeFileSync(settingsPath, `${JSON.stringify(settings, null, 2)}
3552
3594
  `);
3553
- console.log(` ${import_chalk12.default.green("\u2713")} .claude/settings.json \u2014 added viberails PostToolUse hook`);
3595
+ console.log(` ${import_chalk13.default.green("\u2713")} .claude/settings.json \u2014 added viberails PostToolUse hook`);
3554
3596
  }
3555
3597
  function setupClaudeMdReference(projectRoot) {
3556
3598
  const claudeMdPath = path18.join(projectRoot, "CLAUDE.md");
@@ -3562,7 +3604,7 @@ function setupClaudeMdReference(projectRoot) {
3562
3604
  const ref = "\n@.viberails/context.md\n";
3563
3605
  const prefix = content.length === 0 ? "" : content.trimEnd();
3564
3606
  fs18.writeFileSync(claudeMdPath, prefix + ref);
3565
- console.log(` ${import_chalk12.default.green("\u2713")} CLAUDE.md \u2014 added @.viberails/context.md reference`);
3607
+ console.log(` ${import_chalk13.default.green("\u2713")} CLAUDE.md \u2014 added @.viberails/context.md reference`);
3566
3608
  }
3567
3609
  function setupGithubAction(projectRoot, packageManager, options) {
3568
3610
  const workflowDir = path18.join(projectRoot, ".github", "workflows");
@@ -3648,7 +3690,7 @@ ${cmd}
3648
3690
  // src/commands/init-hooks-extra.ts
3649
3691
  var fs19 = __toESM(require("fs"), 1);
3650
3692
  var path19 = __toESM(require("path"), 1);
3651
- var import_chalk13 = __toESM(require("chalk"), 1);
3693
+ var import_chalk14 = __toESM(require("chalk"), 1);
3652
3694
  var import_yaml2 = require("yaml");
3653
3695
  function addPreCommitStep(projectRoot, name, command, marker, lefthookExtra) {
3654
3696
  const lefthookPath = path19.join(projectRoot, "lefthook.yml");
@@ -3708,12 +3750,12 @@ ${command}
3708
3750
  function setupTypecheckHook(projectRoot, packageManager) {
3709
3751
  const resolved = resolveTypecheckCommand(projectRoot, packageManager);
3710
3752
  if (!resolved.command) {
3711
- console.log(` ${import_chalk13.default.yellow("!")} Skipped typecheck hook: ${resolved.reason}`);
3753
+ console.log(` ${import_chalk14.default.yellow("!")} Skipped typecheck hook: ${resolved.reason}`);
3712
3754
  return void 0;
3713
3755
  }
3714
3756
  const target = addPreCommitStep(projectRoot, "typecheck", resolved.command, "typecheck");
3715
3757
  if (target) {
3716
- console.log(` ${import_chalk13.default.green("\u2713")} ${target} \u2014 added typecheck (${resolved.label})`);
3758
+ console.log(` ${import_chalk14.default.green("\u2713")} ${target} \u2014 added typecheck (${resolved.label})`);
3717
3759
  }
3718
3760
  return target;
3719
3761
  }
@@ -3723,18 +3765,19 @@ function setupLintHook(projectRoot, linter) {
3723
3765
  let command;
3724
3766
  let lefthookExtra;
3725
3767
  if (isLefthook) {
3726
- command = linter === "biome" ? "npx biome check {staged_files}" : "npx eslint {staged_files}";
3768
+ command = linter === "biome" ? "npx biome check --write {staged_files}" : "npx eslint --fix {staged_files}";
3727
3769
  lefthookExtra = {
3728
- glob: linter === "biome" ? "*.{js,ts,jsx,tsx,json,css}" : "*.{js,ts,jsx,tsx}"
3770
+ glob: linter === "biome" ? "*.{js,ts,jsx,tsx,json,css}" : "*.{js,ts,jsx,tsx}",
3771
+ stage_fixed: "true"
3729
3772
  };
3730
3773
  } else {
3731
3774
  const exts = linter === "biome" ? "'*.js' '*.ts' '*.jsx' '*.tsx' '*.json' '*.css'" : "'*.js' '*.ts' '*.jsx' '*.tsx'";
3732
- const lintCmd = linter === "biome" ? "biome check" : "eslint";
3775
+ const lintCmd = linter === "biome" ? "biome check --write" : "eslint --fix";
3733
3776
  command = `git diff --cached --name-only --diff-filter=ACMR -- ${exts} | xargs npx ${lintCmd}`;
3734
3777
  }
3735
3778
  const target = addPreCommitStep(projectRoot, "lint", command, linter, lefthookExtra);
3736
3779
  if (target) {
3737
- console.log(` ${import_chalk13.default.green("\u2713")} ${target} \u2014 added ${linterName} lint check`);
3780
+ console.log(` ${import_chalk14.default.green("\u2713")} ${target} \u2014 added ${linterName} lint check`);
3738
3781
  }
3739
3782
  return target;
3740
3783
  }
@@ -3743,7 +3786,7 @@ function setupSelectedIntegrations(projectRoot, integrations, opts) {
3743
3786
  if (integrations.preCommitHook) {
3744
3787
  const t = setupPreCommitHook(projectRoot);
3745
3788
  if (t && opts.lefthookExpected && !t.includes("lefthook")) {
3746
- console.log(` ${import_chalk13.default.yellow("!")} Lefthook install failed \u2014 fell back to ${t}`);
3789
+ console.log(` ${import_chalk14.default.yellow("!")} Lefthook install failed \u2014 fell back to ${t}`);
3747
3790
  }
3748
3791
  created.push(t ? `${t} \u2014 added viberails pre-commit` : "pre-commit hook skipped");
3749
3792
  }
@@ -3779,7 +3822,7 @@ var path20 = __toESM(require("path"), 1);
3779
3822
  var clack12 = __toESM(require("@clack/prompts"), 1);
3780
3823
  var import_config8 = require("@viberails/config");
3781
3824
  var import_scanner2 = require("@viberails/scanner");
3782
- var import_chalk14 = __toESM(require("chalk"), 1);
3825
+ var import_chalk15 = __toESM(require("chalk"), 1);
3783
3826
 
3784
3827
  // src/utils/filter-confidence.ts
3785
3828
  function filterHighConfidence(conventions, meta) {
@@ -3815,7 +3858,7 @@ async function initNonInteractive(projectRoot, configPath) {
3815
3858
  const exempted = getExemptedPackages(config);
3816
3859
  if (exempted.length > 0) {
3817
3860
  console.log(
3818
- ` ${import_chalk14.default.dim("Auto-exempted from coverage:")} ${exempted.join(", ")} ${import_chalk14.default.dim("(types-only)")}`
3861
+ ` ${import_chalk15.default.dim("Auto-exempted from coverage:")} ${exempted.join(", ")} ${import_chalk15.default.dim("(types-only)")}`
3819
3862
  );
3820
3863
  }
3821
3864
  if (config.packages.length > 1) {
@@ -3852,14 +3895,14 @@ async function initNonInteractive(projectRoot, configPath) {
3852
3895
  const hookManager = detectHookManager(projectRoot);
3853
3896
  const hasHookManager = hookManager === "Lefthook" || hookManager === "Husky";
3854
3897
  const preCommitTarget = hasHookManager ? setupPreCommitHook(projectRoot) : void 0;
3855
- const ok = import_chalk14.default.green("\u2713");
3898
+ const ok = import_chalk15.default.green("\u2713");
3856
3899
  const created = [
3857
3900
  `${ok} ${path20.basename(configPath)}`,
3858
3901
  `${ok} .viberails/context.md`,
3859
3902
  `${ok} .viberails/scan-result.json`,
3860
3903
  `${ok} .claude/settings.json \u2014 added viberails hook`,
3861
3904
  `${ok} CLAUDE.md \u2014 added @.viberails/context.md reference`,
3862
- preCommitTarget ? `${ok} ${preCommitTarget}` : `${import_chalk14.default.yellow("!")} pre-commit hook skipped (install lefthook or husky)`,
3905
+ preCommitTarget ? `${ok} ${preCommitTarget}` : `${import_chalk15.default.yellow("!")} pre-commit hook skipped (install lefthook or husky)`,
3863
3906
  actionTarget ? `${ok} ${actionTarget} \u2014 blocks PRs on violations` : ""
3864
3907
  ].filter(Boolean);
3865
3908
  if (hasHookManager && isTypeScript) setupTypecheckHook(projectRoot, rootPkgPm);
@@ -3884,8 +3927,8 @@ async function initCommand(options, cwd) {
3884
3927
  return initInteractive(projectRoot, configPath, options);
3885
3928
  }
3886
3929
  console.log(
3887
- `${import_chalk15.default.yellow("!")} viberails is already initialized.
3888
- Run ${import_chalk15.default.cyan("viberails")} to review or edit the existing setup, ${import_chalk15.default.cyan("viberails sync")} to update generated files, or ${import_chalk15.default.cyan("viberails init --force")} to replace it.`
3930
+ `${import_chalk16.default.yellow("!")} viberails is already initialized.
3931
+ Run ${import_chalk16.default.cyan("viberails")} to review or edit the existing setup, ${import_chalk16.default.cyan("viberails sync")} to update generated files, or ${import_chalk16.default.cyan("viberails init --force")} to replace it.`
3889
3932
  );
3890
3933
  return;
3891
3934
  }
@@ -3926,11 +3969,6 @@ async function initInteractive(projectRoot, configPath, options) {
3926
3969
  );
3927
3970
  }
3928
3971
  const hasTestRunner = !!scanResult.stack.testRunner;
3929
- if (!hasTestRunner) {
3930
- clack13.log.info(
3931
- "No test runner detected. Coverage checks are inactive until a test runner is installed.\nInstall a test runner (e.g. vitest) and re-run viberails init."
3932
- );
3933
- }
3934
3972
  const hookManager = detectHookManager(projectRoot);
3935
3973
  const coveragePrereqs = checkCoveragePrereqs(projectRoot, scanResult);
3936
3974
  const rootPkgStack = (config.packages.find((p) => p.path === ".") ?? config.packages[0])?.stack;
@@ -3962,7 +4000,7 @@ async function initInteractive(projectRoot, configPath, options) {
3962
4000
  writeGeneratedFiles(projectRoot, config, scanResult);
3963
4001
  updateGitignore(projectRoot);
3964
4002
  ws.stop("Configuration written");
3965
- const ok = import_chalk15.default.green("\u2713");
4003
+ const ok = import_chalk16.default.green("\u2713");
3966
4004
  clack13.log.step(`${ok} ${path21.basename(configPath)}`);
3967
4005
  clack13.log.step(`${ok} .viberails/context.md`);
3968
4006
  clack13.log.step(`${ok} .viberails/scan-result.json`);
@@ -3976,7 +4014,7 @@ async function initInteractive(projectRoot, configPath, options) {
3976
4014
  }
3977
4015
  clack13.outro(
3978
4016
  `Done! Next: review viberails.config.json, then run viberails check
3979
- ${import_chalk15.default.dim("Tip: use")} ${import_chalk15.default.cyan("viberails check --enforce")} ${import_chalk15.default.dim("in CI to block PRs on violations.")}`
4017
+ ${import_chalk16.default.dim("Tip: use")} ${import_chalk16.default.cyan("viberails check --enforce")} ${import_chalk16.default.dim("in CI to block PRs on violations.")}`
3980
4018
  );
3981
4019
  }
3982
4020
 
@@ -3986,7 +4024,7 @@ var path22 = __toESM(require("path"), 1);
3986
4024
  var clack14 = __toESM(require("@clack/prompts"), 1);
3987
4025
  var import_config11 = require("@viberails/config");
3988
4026
  var import_scanner4 = require("@viberails/scanner");
3989
- var import_chalk16 = __toESM(require("chalk"), 1);
4027
+ var import_chalk17 = __toESM(require("chalk"), 1);
3990
4028
  var CONFIG_FILE6 = "viberails.config.json";
3991
4029
  var SCAN_RESULT_FILE2 = ".viberails/scan-result.json";
3992
4030
  function loadPreviousStats(projectRoot) {
@@ -4027,13 +4065,13 @@ async function syncCommand(options, cwd) {
4027
4065
  const statsDelta = previousStats ? formatStatsDelta(previousStats, scanResult.statistics) : void 0;
4028
4066
  if (changes.length > 0 || statsDelta) {
4029
4067
  console.log(`
4030
- ${import_chalk16.default.bold("Changes:")}`);
4068
+ ${import_chalk17.default.bold("Changes:")}`);
4031
4069
  for (const change of changes) {
4032
- const icon = change.type === "removed" ? import_chalk16.default.red("-") : import_chalk16.default.green("+");
4070
+ const icon = change.type === "removed" ? import_chalk17.default.red("-") : import_chalk17.default.green("+");
4033
4071
  console.log(` ${icon} ${change.description}`);
4034
4072
  }
4035
4073
  if (statsDelta) {
4036
- console.log(` ${import_chalk16.default.dim(statsDelta)}`);
4074
+ console.log(` ${import_chalk17.default.dim(statsDelta)}`);
4037
4075
  }
4038
4076
  }
4039
4077
  if (options?.interactive) {
@@ -4082,18 +4120,18 @@ ${import_chalk16.default.bold("Changes:")}`);
4082
4120
  `);
4083
4121
  writeGeneratedFiles(projectRoot, merged, scanResult);
4084
4122
  console.log(`
4085
- ${import_chalk16.default.bold("Synced:")}`);
4123
+ ${import_chalk17.default.bold("Synced:")}`);
4086
4124
  if (configChanged) {
4087
- console.log(` ${import_chalk16.default.yellow("!")} ${CONFIG_FILE6} \u2014 updated (review changes)`);
4125
+ console.log(` ${import_chalk17.default.yellow("!")} ${CONFIG_FILE6} \u2014 updated (review changes)`);
4088
4126
  } else {
4089
- console.log(` ${import_chalk16.default.green("\u2713")} ${CONFIG_FILE6} \u2014 unchanged`);
4127
+ console.log(` ${import_chalk17.default.green("\u2713")} ${CONFIG_FILE6} \u2014 unchanged`);
4090
4128
  }
4091
- console.log(` ${import_chalk16.default.green("\u2713")} .viberails/context.md \u2014 regenerated`);
4092
- console.log(` ${import_chalk16.default.green("\u2713")} .viberails/scan-result.json \u2014 updated`);
4129
+ console.log(` ${import_chalk17.default.green("\u2713")} .viberails/context.md \u2014 regenerated`);
4130
+ console.log(` ${import_chalk17.default.green("\u2713")} .viberails/scan-result.json \u2014 updated`);
4093
4131
  }
4094
4132
 
4095
4133
  // src/index.ts
4096
- var VERSION = "0.6.8";
4134
+ var VERSION = "0.6.10";
4097
4135
  var program = new import_commander.Command();
4098
4136
  program.name("viberails").description("Guardrails for vibe coding").version(VERSION);
4099
4137
  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) => {
@@ -4101,7 +4139,7 @@ program.command("init", { isDefault: true }).description("Scan your project and
4101
4139
  await initCommand(options);
4102
4140
  } catch (err) {
4103
4141
  const message = err instanceof Error ? err.message : String(err);
4104
- console.error(`${import_chalk17.default.red("Error:")} ${message}`);
4142
+ console.error(`${import_chalk18.default.red("Error:")} ${message}`);
4105
4143
  process.exit(1);
4106
4144
  }
4107
4145
  });
@@ -4110,7 +4148,7 @@ program.command("sync").description("Re-scan and update generated files").option
4110
4148
  await syncCommand(options);
4111
4149
  } catch (err) {
4112
4150
  const message = err instanceof Error ? err.message : String(err);
4113
- console.error(`${import_chalk17.default.red("Error:")} ${message}`);
4151
+ console.error(`${import_chalk18.default.red("Error:")} ${message}`);
4114
4152
  process.exit(1);
4115
4153
  }
4116
4154
  });
@@ -4119,7 +4157,7 @@ program.command("config").description("Interactively edit existing config rules"
4119
4157
  await configCommand(options);
4120
4158
  } catch (err) {
4121
4159
  const message = err instanceof Error ? err.message : String(err);
4122
- console.error(`${import_chalk17.default.red("Error:")} ${message}`);
4160
+ console.error(`${import_chalk18.default.red("Error:")} ${message}`);
4123
4161
  process.exit(1);
4124
4162
  }
4125
4163
  });
@@ -4140,7 +4178,7 @@ program.command("check").description("Check files against enforced rules").optio
4140
4178
  process.exit(exitCode);
4141
4179
  } catch (err) {
4142
4180
  const message = err instanceof Error ? err.message : String(err);
4143
- console.error(`${import_chalk17.default.red("Error:")} ${message}`);
4181
+ console.error(`${import_chalk18.default.red("Error:")} ${message}`);
4144
4182
  process.exit(1);
4145
4183
  }
4146
4184
  }
@@ -4151,7 +4189,7 @@ program.command("fix").description("Auto-fix file naming violations and generate
4151
4189
  process.exit(exitCode);
4152
4190
  } catch (err) {
4153
4191
  const message = err instanceof Error ? err.message : String(err);
4154
- console.error(`${import_chalk17.default.red("Error:")} ${message}`);
4192
+ console.error(`${import_chalk18.default.red("Error:")} ${message}`);
4155
4193
  process.exit(1);
4156
4194
  }
4157
4195
  });
@@ -4160,7 +4198,7 @@ program.command("boundaries").description("Display, infer, or inspect import bou
4160
4198
  await boundariesCommand(options);
4161
4199
  } catch (err) {
4162
4200
  const message = err instanceof Error ? err.message : String(err);
4163
- console.error(`${import_chalk17.default.red("Error:")} ${message}`);
4201
+ console.error(`${import_chalk18.default.red("Error:")} ${message}`);
4164
4202
  process.exit(1);
4165
4203
  }
4166
4204
  });