viberails 0.5.4 → 0.5.5

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
@@ -131,7 +131,7 @@ async function promptIntegrations(projectRoot, hookManager, tools) {
131
131
  options.push({
132
132
  value: "typecheck",
133
133
  label: "Typecheck (tsc --noEmit)",
134
- hint: "catches type errors before commit"
134
+ hint: "pre-commit hook + CI check"
135
135
  });
136
136
  }
137
137
  if (tools?.linter) {
@@ -139,7 +139,7 @@ async function promptIntegrations(projectRoot, hookManager, tools) {
139
139
  options.push({
140
140
  value: "lint",
141
141
  label: `Lint check (${linterName})`,
142
- hint: "runs linter on staged files before commit"
142
+ hint: "pre-commit hook + CI check"
143
143
  });
144
144
  }
145
145
  options.push(
@@ -1442,7 +1442,8 @@ function formatPackageSummary(pkg) {
1442
1442
  if (pkg.stack.styling) {
1443
1443
  parts.push(formatItem(pkg.stack.styling, import_types2.STYLING_NAMES));
1444
1444
  }
1445
- const files = `${pkg.statistics.totalFiles} files`;
1445
+ const n = pkg.statistics.totalFiles;
1446
+ const files = `${n} ${n === 1 ? "file" : "files"}`;
1446
1447
  const detail = parts.length > 0 ? `${parts.join(", ")} (${files})` : `(${files})`;
1447
1448
  return ` ${pkg.relativePath} \u2014 ${detail}`;
1448
1449
  }
@@ -1498,7 +1499,8 @@ function formatPackageSummaryPlain(pkg) {
1498
1499
  if (pkg.stack.styling) {
1499
1500
  parts.push(formatItem(pkg.stack.styling, import_types2.STYLING_NAMES));
1500
1501
  }
1501
- const files = `${pkg.statistics.totalFiles} files`;
1502
+ const n = pkg.statistics.totalFiles;
1503
+ const files = `${n} ${n === 1 ? "file" : "files"}`;
1502
1504
  const detail = parts.length > 0 ? `${parts.join(", ")} (${files})` : `(${files})`;
1503
1505
  return ` ${pkg.relativePath} \u2014 ${detail}`;
1504
1506
  }
@@ -3034,13 +3036,6 @@ async function initInteractive(projectRoot, configPath, options) {
3034
3036
  const scanResult = await (0, import_scanner2.scan)(projectRoot);
3035
3037
  const config = (0, import_config8.generateConfig)(scanResult);
3036
3038
  s.stop("Scan complete");
3037
- const prereqResult = await promptMissingPrereqs(
3038
- projectRoot,
3039
- checkCoveragePrereqs(projectRoot, scanResult)
3040
- );
3041
- if (prereqResult.disableCoverage) {
3042
- config.rules.testCoverage = 0;
3043
- }
3044
3039
  if (scanResult.statistics.totalFiles === 0) {
3045
3040
  clack8.log.warn(
3046
3041
  "No source files detected. Try running from the project root,\nor check that source files exist. Run viberails sync after adding files."
@@ -3081,15 +3076,23 @@ async function initInteractive(projectRoot, configPath, options) {
3081
3076
  if (denyCount > 0) {
3082
3077
  config.boundaries = inferred;
3083
3078
  config.rules.enforceBoundaries = true;
3084
- bs.stop(`Inferred ${denyCount} boundary rules`);
3085
- const boundaryLines = Object.entries(inferred.deny).map(([pkg, denied]) => `${pkg} must NOT import from: ${denied.join(", ")}`).join("\n");
3086
- clack8.note(boundaryLines, "Boundary rules");
3079
+ const pkgCount = Object.keys(inferred.deny).length;
3080
+ bs.stop(`Inferred ${denyCount} boundary rules across ${pkgCount} packages`);
3087
3081
  } else {
3088
3082
  bs.stop("No boundary rules inferred");
3089
3083
  }
3090
3084
  }
3091
3085
  }
3092
3086
  const hookManager = detectHookManager(projectRoot);
3087
+ const coveragePrereqs = checkCoveragePrereqs(projectRoot, scanResult);
3088
+ const hasMissingPrereqs = coveragePrereqs.some((p) => !p.installed) || !hookManager;
3089
+ if (hasMissingPrereqs) {
3090
+ clack8.log.info("Some dependencies are needed for full functionality.");
3091
+ }
3092
+ const prereqResult = await promptMissingPrereqs(projectRoot, coveragePrereqs);
3093
+ if (prereqResult.disableCoverage) {
3094
+ config.rules.testCoverage = 0;
3095
+ }
3093
3096
  const rootPkgStack = (config.packages.find((p) => p.path === ".") ?? config.packages[0])?.stack;
3094
3097
  const integrations = await promptIntegrations(projectRoot, hookManager, {
3095
3098
  isTypeScript: rootPkgStack?.language === "typescript",
@@ -3107,17 +3110,14 @@ async function initInteractive(projectRoot, configPath, options) {
3107
3110
  `);
3108
3111
  writeGeneratedFiles(projectRoot, config, scanResult);
3109
3112
  updateGitignore(projectRoot);
3110
- const createdFiles = [
3111
- path18.basename(configPath),
3112
- ".viberails/context.md",
3113
- ".viberails/scan-result.json",
3114
- ...setupSelectedIntegrations(projectRoot, integrations, {
3115
- linter: rootPkgStack?.linter?.split("@")[0],
3116
- packageManager: rootPkgStack?.packageManager
3117
- })
3118
- ];
3119
- clack8.log.success(`Created:
3120
- ${createdFiles.map((f) => ` ${f}`).join("\n")}`);
3113
+ const ok = import_chalk11.default.green("\u2713");
3114
+ clack8.log.step(`${ok} ${path18.basename(configPath)}`);
3115
+ clack8.log.step(`${ok} .viberails/context.md`);
3116
+ clack8.log.step(`${ok} .viberails/scan-result.json`);
3117
+ setupSelectedIntegrations(projectRoot, integrations, {
3118
+ linter: rootPkgStack?.linter?.split("@")[0],
3119
+ packageManager: rootPkgStack?.packageManager
3120
+ });
3121
3121
  clack8.outro(
3122
3122
  `Done! Next: review viberails.config.json, then run viberails check
3123
3123
  ${import_chalk11.default.dim("Tip: use")} ${import_chalk11.default.cyan("viberails check --enforce")} ${import_chalk11.default.dim("in CI to block PRs on violations.")}`
@@ -3231,7 +3231,7 @@ ${import_chalk12.default.bold("Synced:")}`);
3231
3231
  }
3232
3232
 
3233
3233
  // src/index.ts
3234
- var VERSION = "0.5.4";
3234
+ var VERSION = "0.5.5";
3235
3235
  var program = new import_commander.Command();
3236
3236
  program.name("viberails").description("Guardrails for vibe coding").version(VERSION);
3237
3237
  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) => {