@ipation/specbridge 1.0.4 → 1.0.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/cli.js CHANGED
@@ -2762,38 +2762,22 @@ npx specbridge hook run --level commit --files "$STAGED_FILES"
2762
2762
 
2763
2763
  exit $?
2764
2764
  `;
2765
- var hookCommand = new Command9("hook").description("Manage Git hooks for verification");
2766
- hookCommand.command("install").description("Install Git pre-commit hook").option("-f, --force", "Overwrite existing hook").option("--husky", "Install for husky").option("--lefthook", "Install for lefthook").action(async (options) => {
2767
- const cwd = process.cwd();
2768
- if (!await pathExists(getSpecBridgeDir(cwd))) {
2769
- throw new NotInitializedError();
2770
- }
2771
- const spinner = ora5("Detecting hook system...").start();
2772
- try {
2773
- let hookPath;
2774
- let hookContent;
2775
- if (options.husky) {
2776
- hookPath = join7(cwd, ".husky", "pre-commit");
2777
- hookContent = HOOK_SCRIPT;
2778
- spinner.text = "Installing husky pre-commit hook...";
2779
- } else if (options.lefthook) {
2780
- spinner.succeed("Lefthook detected");
2781
- console.log("");
2782
- console.log(chalk8.cyan("Add this to your lefthook.yml:"));
2783
- console.log("");
2784
- console.log(chalk8.dim(`pre-commit:
2785
- commands:
2786
- specbridge:
2787
- glob: "*.{ts,tsx}"
2788
- run: npx specbridge hook run --level commit --files {staged_files}
2789
- `));
2790
- return;
2791
- } else {
2792
- if (await pathExists(join7(cwd, ".husky"))) {
2765
+ function createHookCommand() {
2766
+ const hookCommand2 = new Command9("hook").description("Manage Git hooks for verification");
2767
+ hookCommand2.command("install").description("Install Git pre-commit hook").option("-f, --force", "Overwrite existing hook").option("--husky", "Install for husky").option("--lefthook", "Install for lefthook").action(async (options) => {
2768
+ const cwd = process.cwd();
2769
+ if (!await pathExists(getSpecBridgeDir(cwd))) {
2770
+ throw new NotInitializedError();
2771
+ }
2772
+ const spinner = ora5("Detecting hook system...").start();
2773
+ try {
2774
+ let hookPath;
2775
+ let hookContent;
2776
+ if (options.husky) {
2793
2777
  hookPath = join7(cwd, ".husky", "pre-commit");
2794
2778
  hookContent = HOOK_SCRIPT;
2795
2779
  spinner.text = "Installing husky pre-commit hook...";
2796
- } else if (await pathExists(join7(cwd, "lefthook.yml"))) {
2780
+ } else if (options.lefthook) {
2797
2781
  spinner.succeed("Lefthook detected");
2798
2782
  console.log("");
2799
2783
  console.log(chalk8.cyan("Add this to your lefthook.yml:"));
@@ -2806,97 +2790,117 @@ hookCommand.command("install").description("Install Git pre-commit hook").option
2806
2790
  `));
2807
2791
  return;
2808
2792
  } else {
2809
- hookPath = join7(cwd, ".git", "hooks", "pre-commit");
2810
- hookContent = HOOK_SCRIPT;
2811
- spinner.text = "Installing Git pre-commit hook...";
2793
+ if (await pathExists(join7(cwd, ".husky"))) {
2794
+ hookPath = join7(cwd, ".husky", "pre-commit");
2795
+ hookContent = HOOK_SCRIPT;
2796
+ spinner.text = "Installing husky pre-commit hook...";
2797
+ } else if (await pathExists(join7(cwd, "lefthook.yml"))) {
2798
+ spinner.succeed("Lefthook detected");
2799
+ console.log("");
2800
+ console.log(chalk8.cyan("Add this to your lefthook.yml:"));
2801
+ console.log("");
2802
+ console.log(chalk8.dim(`pre-commit:
2803
+ commands:
2804
+ specbridge:
2805
+ glob: "*.{ts,tsx}"
2806
+ run: npx specbridge hook run --level commit --files {staged_files}
2807
+ `));
2808
+ return;
2809
+ } else {
2810
+ hookPath = join7(cwd, ".git", "hooks", "pre-commit");
2811
+ hookContent = HOOK_SCRIPT;
2812
+ spinner.text = "Installing Git pre-commit hook...";
2813
+ }
2814
+ }
2815
+ if (await pathExists(hookPath) && !options.force) {
2816
+ spinner.fail("Hook already exists");
2817
+ console.log(chalk8.yellow(`Use --force to overwrite: ${hookPath}`));
2818
+ return;
2812
2819
  }
2820
+ await writeTextFile(hookPath, hookContent);
2821
+ const { execSync } = await import("child_process");
2822
+ try {
2823
+ execSync(`chmod +x "${hookPath}"`, { stdio: "ignore" });
2824
+ } catch {
2825
+ }
2826
+ spinner.succeed("Pre-commit hook installed");
2827
+ console.log(chalk8.dim(` Path: ${hookPath}`));
2828
+ console.log("");
2829
+ console.log(chalk8.cyan("The hook will run on each commit and verify staged files."));
2830
+ } catch (error) {
2831
+ spinner.fail("Failed to install hook");
2832
+ throw error;
2813
2833
  }
2814
- if (await pathExists(hookPath) && !options.force) {
2815
- spinner.fail("Hook already exists");
2816
- console.log(chalk8.yellow(`Use --force to overwrite: ${hookPath}`));
2817
- return;
2834
+ });
2835
+ hookCommand2.command("run").description("Run verification (called by hook)").option("-l, --level <level>", "Verification level", "commit").option("-f, --files <files>", "Space or comma-separated file list").action(async (options) => {
2836
+ const cwd = process.cwd();
2837
+ if (!await pathExists(getSpecBridgeDir(cwd))) {
2838
+ throw new NotInitializedError();
2818
2839
  }
2819
- await writeTextFile(hookPath, hookContent);
2820
- const { execSync } = await import("child_process");
2821
2840
  try {
2822
- execSync(`chmod +x "${hookPath}"`, { stdio: "ignore" });
2823
- } catch {
2824
- }
2825
- spinner.succeed("Pre-commit hook installed");
2826
- console.log(chalk8.dim(` Path: ${hookPath}`));
2827
- console.log("");
2828
- console.log(chalk8.cyan("The hook will run on each commit and verify staged files."));
2829
- } catch (error) {
2830
- spinner.fail("Failed to install hook");
2831
- throw error;
2832
- }
2833
- });
2834
- hookCommand.command("run").description("Run verification (called by hook)").option("-l, --level <level>", "Verification level", "commit").option("-f, --files <files>", "Space or comma-separated file list").action(async (options) => {
2835
- const cwd = process.cwd();
2836
- if (!await pathExists(getSpecBridgeDir(cwd))) {
2837
- throw new NotInitializedError();
2838
- }
2839
- try {
2840
- const config = await loadConfig(cwd);
2841
- const level = options.level || "commit";
2842
- const files = options.files ? options.files.split(/[\s,]+/).filter((f) => f.length > 0) : void 0;
2843
- if (!files || files.length === 0) {
2844
- process.exit(0);
2845
- }
2846
- const engine = createVerificationEngine();
2847
- const result = await engine.verify(config, {
2848
- level,
2849
- files,
2850
- cwd
2851
- });
2852
- if (result.violations.length === 0) {
2853
- console.log(chalk8.green("\u2713 SpecBridge: All checks passed"));
2854
- process.exit(0);
2855
- }
2856
- console.log(chalk8.red(`\u2717 SpecBridge: ${result.violations.length} violation(s) found`));
2857
- console.log("");
2858
- for (const v of result.violations) {
2859
- const location = v.line ? `:${v.line}` : "";
2860
- console.log(` ${v.file}${location}: ${v.message}`);
2861
- console.log(chalk8.dim(` [${v.severity}] ${v.decisionId}/${v.constraintId}`));
2841
+ const config = await loadConfig(cwd);
2842
+ const level = options.level || "commit";
2843
+ const files = options.files ? options.files.split(/[\s,]+/).filter((f) => f.length > 0) : void 0;
2844
+ if (!files || files.length === 0) {
2845
+ process.exit(0);
2846
+ }
2847
+ const engine = createVerificationEngine();
2848
+ const result = await engine.verify(config, {
2849
+ level,
2850
+ files,
2851
+ cwd
2852
+ });
2853
+ if (result.violations.length === 0) {
2854
+ console.log(chalk8.green("\u2713 SpecBridge: All checks passed"));
2855
+ process.exit(0);
2856
+ }
2857
+ console.log(chalk8.red(`\u2717 SpecBridge: ${result.violations.length} violation(s) found`));
2858
+ console.log("");
2859
+ for (const v of result.violations) {
2860
+ const location = v.line ? `:${v.line}` : "";
2861
+ console.log(` ${v.file}${location}: ${v.message}`);
2862
+ console.log(chalk8.dim(` [${v.severity}] ${v.decisionId}/${v.constraintId}`));
2863
+ }
2864
+ console.log("");
2865
+ console.log(chalk8.yellow("Run `specbridge verify` for full details."));
2866
+ process.exit(result.success ? 0 : 1);
2867
+ } catch (error) {
2868
+ console.error(chalk8.red("SpecBridge verification failed"));
2869
+ console.error(error instanceof Error ? error.message : String(error));
2870
+ process.exit(1);
2862
2871
  }
2863
- console.log("");
2864
- console.log(chalk8.yellow("Run `specbridge verify` for full details."));
2865
- process.exit(result.success ? 0 : 1);
2866
- } catch (error) {
2867
- console.error(chalk8.red("SpecBridge verification failed"));
2868
- console.error(error instanceof Error ? error.message : String(error));
2869
- process.exit(1);
2870
- }
2871
- });
2872
- hookCommand.command("uninstall").description("Remove Git pre-commit hook").action(async () => {
2873
- const cwd = process.cwd();
2874
- const spinner = ora5("Removing hook...").start();
2875
- try {
2876
- const hookPaths = [
2877
- join7(cwd, ".husky", "pre-commit"),
2878
- join7(cwd, ".git", "hooks", "pre-commit")
2879
- ];
2880
- let removed = false;
2881
- for (const hookPath of hookPaths) {
2882
- if (await pathExists(hookPath)) {
2883
- const content = await readTextFile(hookPath);
2884
- if (content.includes("SpecBridge")) {
2885
- const { unlink } = await import("fs/promises");
2886
- await unlink(hookPath);
2887
- spinner.succeed(`Removed hook: ${hookPath}`);
2888
- removed = true;
2872
+ });
2873
+ hookCommand2.command("uninstall").description("Remove Git pre-commit hook").action(async () => {
2874
+ const cwd = process.cwd();
2875
+ const spinner = ora5("Removing hook...").start();
2876
+ try {
2877
+ const hookPaths = [
2878
+ join7(cwd, ".husky", "pre-commit"),
2879
+ join7(cwd, ".git", "hooks", "pre-commit")
2880
+ ];
2881
+ let removed = false;
2882
+ for (const hookPath of hookPaths) {
2883
+ if (await pathExists(hookPath)) {
2884
+ const content = await readTextFile(hookPath);
2885
+ if (content.includes("SpecBridge")) {
2886
+ const { unlink } = await import("fs/promises");
2887
+ await unlink(hookPath);
2888
+ spinner.succeed(`Removed hook: ${hookPath}`);
2889
+ removed = true;
2890
+ }
2889
2891
  }
2890
2892
  }
2893
+ if (!removed) {
2894
+ spinner.info("No SpecBridge hooks found");
2895
+ }
2896
+ } catch (error) {
2897
+ spinner.fail("Failed to remove hook");
2898
+ throw error;
2891
2899
  }
2892
- if (!removed) {
2893
- spinner.info("No SpecBridge hooks found");
2894
- }
2895
- } catch (error) {
2896
- spinner.fail("Failed to remove hook");
2897
- throw error;
2898
- }
2899
- });
2900
+ });
2901
+ return hookCommand2;
2902
+ }
2903
+ var hookCommand = createHookCommand();
2900
2904
 
2901
2905
  // src/cli/commands/report.ts
2902
2906
  import { Command as Command10 } from "commander";
@@ -3303,7 +3307,7 @@ var contextCommand = new Command11("context").description("Generate architectura
3303
3307
  const config = await loadConfig(cwd);
3304
3308
  const output = await generateFormattedContext(file, config, {
3305
3309
  format: options.format,
3306
- includeRationale: options.noRationale !== true,
3310
+ includeRationale: options.rationale !== false,
3307
3311
  cwd
3308
3312
  });
3309
3313
  if (options.output) {