workflow-agent-cli 2.9.0 → 2.9.1

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/index.js CHANGED
@@ -31,7 +31,7 @@ import {
31
31
  installMandatoryTemplates,
32
32
  templateMetadata,
33
33
  updateTemplates
34
- } from "../chunk-Y5N3JJTU.js";
34
+ } from "../chunk-YEOQZ7XC.js";
35
35
 
36
36
  // src/cli/index.ts
37
37
  import { Command } from "commander";
@@ -359,11 +359,11 @@ async function initCommand(options) {
359
359
  if (!existsSync(workflowDir)) {
360
360
  await mkdir(workflowDir, { recursive: true });
361
361
  }
362
- const shouldGenerateGuidelines = await p.confirm({
362
+ const shouldGenerateGuidelines = options.yes || isNonInteractive ? true : await p.confirm({
363
363
  message: "Generate workflow guidelines from templates?",
364
364
  initialValue: true
365
365
  });
366
- if (p.isCancel(shouldGenerateGuidelines)) {
366
+ if (!isNonInteractive && p.isCancel(shouldGenerateGuidelines)) {
367
367
  p.cancel("Initialization cancelled");
368
368
  process.exit(0);
369
369
  }
@@ -403,11 +403,11 @@ Reason: ${error instanceof Error ? error.message : String(error)}`
403
403
  );
404
404
  }
405
405
  }
406
- const shouldAutoSetup = options.yes ? true : await p.confirm({
406
+ const shouldAutoSetup = options.yes || isNonInteractive ? true : await p.confirm({
407
407
  message: "Set up linting, formatting, testing, and CI automatically?",
408
408
  initialValue: true
409
409
  });
410
- if (p.isCancel(shouldAutoSetup)) {
410
+ if (!isNonInteractive && p.isCancel(shouldAutoSetup)) {
411
411
  p.cancel("Initialization cancelled");
412
412
  process.exit(0);
413
413
  }
@@ -590,7 +590,204 @@ async function suggestCommand(feedback, options = {}) {
590
590
 
591
591
  // src/cli/commands/doctor.ts
592
592
  import chalk5 from "chalk";
593
- async function doctorCommand() {
593
+ import { existsSync as existsSync3 } from "fs";
594
+ import { join as join3 } from "path";
595
+
596
+ // src/utils/hooks.ts
597
+ import { existsSync as existsSync2 } from "fs";
598
+ import { readFile, writeFile as writeFile2, unlink, chmod, rename, mkdir as mkdir2 } from "fs/promises";
599
+ import { join as join2 } from "path";
600
+ function getGitHooksDir(projectPath = process.cwd()) {
601
+ return join2(projectPath, ".git", "hooks");
602
+ }
603
+ function hasGitRepo(projectPath = process.cwd()) {
604
+ return existsSync2(join2(projectPath, ".git"));
605
+ }
606
+ function generatePreCommitHook(config) {
607
+ const checks = config?.preCommit || ["validate-branch", "check-guidelines"];
608
+ const checkCommands = checks.map((check) => {
609
+ switch (check) {
610
+ case "validate-branch":
611
+ return " workflow validate branch";
612
+ case "validate-commit":
613
+ return " workflow validate commit";
614
+ case "check-guidelines":
615
+ return " workflow doctor --check-guidelines-only 2>/dev/null || true";
616
+ case "validate-scopes":
617
+ return " workflow config validate";
618
+ default:
619
+ return "";
620
+ }
621
+ }).filter(Boolean).join("\n");
622
+ return `#!/bin/sh
623
+ # Workflow Agent pre-commit hook
624
+ # Auto-generated - do not edit manually
625
+ # To reinstall: workflow hooks install
626
+ # To uninstall: workflow hooks uninstall
627
+
628
+ # Skip in CI environment
629
+ if [ -n "\${CI:-}" ] || [ -n "\${GITHUB_ACTIONS:-}" ] || [ -n "\${GITLAB_CI:-}" ]; then
630
+ exit 0
631
+ fi
632
+
633
+ # Run workflow checks
634
+ ${checkCommands}
635
+
636
+ # Run original hook if it exists
637
+ if [ -f ".git/hooks/pre-commit.original" ]; then
638
+ .git/hooks/pre-commit.original "$@"
639
+ fi
640
+ `;
641
+ }
642
+ function generateCommitMsgHook(config) {
643
+ const checks = config?.commitMsg || ["validate-commit"];
644
+ const checkCommands = checks.map((check) => {
645
+ switch (check) {
646
+ case "validate-commit":
647
+ return ' workflow validate commit "$(cat "$1")"';
648
+ default:
649
+ return "";
650
+ }
651
+ }).filter(Boolean).join("\n");
652
+ return `#!/bin/sh
653
+ # Workflow Agent commit-msg hook
654
+ # Auto-generated - do not edit manually
655
+ # To reinstall: workflow hooks install
656
+ # To uninstall: workflow hooks uninstall
657
+
658
+ # Skip in CI environment
659
+ if [ -n "\${CI:-}" ] || [ -n "\${GITHUB_ACTIONS:-}" ] || [ -n "\${GITLAB_CI:-}" ]; then
660
+ exit 0
661
+ fi
662
+
663
+ # Run workflow checks
664
+ ${checkCommands}
665
+
666
+ # Run original hook if it exists
667
+ if [ -f ".git/hooks/commit-msg.original" ]; then
668
+ .git/hooks/commit-msg.original "$@"
669
+ fi
670
+ `;
671
+ }
672
+ async function isWorkflowHook(hookPath) {
673
+ try {
674
+ const content = await readFile(hookPath, "utf-8");
675
+ return content.includes("Workflow Agent") && content.includes("Auto-generated");
676
+ } catch {
677
+ return false;
678
+ }
679
+ }
680
+ async function getHookStatus(hookType, projectPath = process.cwd()) {
681
+ const hooksDir = getGitHooksDir(projectPath);
682
+ const hookPath = join2(hooksDir, hookType);
683
+ const originalPath = join2(hooksDir, `${hookType}.original`);
684
+ const status = {
685
+ installed: false,
686
+ hookType,
687
+ hasExistingHook: false,
688
+ wrappedOriginal: false
689
+ };
690
+ if (!existsSync2(hookPath)) {
691
+ return status;
692
+ }
693
+ status.hasExistingHook = true;
694
+ if (await isWorkflowHook(hookPath)) {
695
+ status.installed = true;
696
+ status.wrappedOriginal = existsSync2(originalPath);
697
+ }
698
+ return status;
699
+ }
700
+ async function getAllHooksStatus(projectPath = process.cwd()) {
701
+ return Promise.all([
702
+ getHookStatus("pre-commit", projectPath),
703
+ getHookStatus("commit-msg", projectPath)
704
+ ]);
705
+ }
706
+ async function installSingleHook(hookType, config, projectPath = process.cwd()) {
707
+ const hooksDir = getGitHooksDir(projectPath);
708
+ const hookPath = join2(hooksDir, hookType);
709
+ const originalPath = join2(hooksDir, `${hookType}.original`);
710
+ const result = {
711
+ success: false,
712
+ hookType,
713
+ wrappedExisting: false
714
+ };
715
+ try {
716
+ if (!existsSync2(hooksDir)) {
717
+ await mkdir2(hooksDir, { recursive: true });
718
+ }
719
+ if (existsSync2(hookPath)) {
720
+ const isOurs = await isWorkflowHook(hookPath);
721
+ if (!isOurs) {
722
+ await rename(hookPath, originalPath);
723
+ result.wrappedExisting = true;
724
+ }
725
+ }
726
+ const hookContent = hookType === "pre-commit" ? generatePreCommitHook(config) : generateCommitMsgHook(config);
727
+ await writeFile2(hookPath, hookContent, "utf-8");
728
+ await chmod(hookPath, 493);
729
+ result.success = true;
730
+ } catch (error) {
731
+ result.error = error instanceof Error ? error.message : String(error);
732
+ }
733
+ return result;
734
+ }
735
+ async function installHooks(config, projectPath = process.cwd()) {
736
+ if (!hasGitRepo(projectPath)) {
737
+ return [
738
+ {
739
+ success: false,
740
+ hookType: "pre-commit",
741
+ wrappedExisting: false,
742
+ error: "No git repository found. Run git init first."
743
+ }
744
+ ];
745
+ }
746
+ const results = await Promise.all([
747
+ installSingleHook("pre-commit", config, projectPath),
748
+ installSingleHook("commit-msg", config, projectPath)
749
+ ]);
750
+ return results;
751
+ }
752
+ async function uninstallSingleHook(hookType, projectPath = process.cwd()) {
753
+ const hooksDir = getGitHooksDir(projectPath);
754
+ const hookPath = join2(hooksDir, hookType);
755
+ const originalPath = join2(hooksDir, `${hookType}.original`);
756
+ const result = {
757
+ success: false,
758
+ hookType,
759
+ wrappedExisting: false
760
+ };
761
+ try {
762
+ if (!existsSync2(hookPath)) {
763
+ result.success = true;
764
+ return result;
765
+ }
766
+ const isOurs = await isWorkflowHook(hookPath);
767
+ if (!isOurs) {
768
+ result.error = "Hook is not managed by Workflow Agent";
769
+ return result;
770
+ }
771
+ await unlink(hookPath);
772
+ if (existsSync2(originalPath)) {
773
+ await rename(originalPath, hookPath);
774
+ result.wrappedExisting = true;
775
+ }
776
+ result.success = true;
777
+ } catch (error) {
778
+ result.error = error instanceof Error ? error.message : String(error);
779
+ }
780
+ return result;
781
+ }
782
+ async function uninstallHooks(projectPath = process.cwd()) {
783
+ return Promise.all([
784
+ uninstallSingleHook("pre-commit", projectPath),
785
+ uninstallSingleHook("commit-msg", projectPath)
786
+ ]);
787
+ }
788
+
789
+ // src/cli/commands/doctor.ts
790
+ async function doctorCommand(options) {
594
791
  console.log(chalk5.bold.cyan("\n\u{1F3E5} Workflow Agent Health Check\n"));
595
792
  const config = await loadConfig();
596
793
  if (!config) {
@@ -603,25 +800,72 @@ async function doctorCommand() {
603
800
  console.log(chalk5.dim(` Scopes: ${config.scopes.length} configured`));
604
801
  console.log(chalk5.dim(` Enforcement: ${config.enforcement}`));
605
802
  console.log(chalk5.dim(` Language: ${config.language}`));
606
- console.log(chalk5.cyan("\n\u{1F4A1} Suggestions:\n"));
607
- console.log(chalk5.dim(" \u2022 Health check analysis coming soon"));
608
- console.log(chalk5.dim(" \u2022 Git history analysis coming soon"));
609
- console.log(chalk5.dim(" \u2022 Optimization recommendations coming soon"));
803
+ const cwd = process.cwd();
804
+ const guidelinesDir = join3(cwd, "guidelines");
805
+ const mandatoryFiles = getMandatoryTemplateFilenames();
806
+ const missingFiles = [];
807
+ console.log(chalk5.cyan("\n\u{1F4DA} Guidelines Check:\n"));
808
+ for (const filename of mandatoryFiles) {
809
+ const filePath = join3(guidelinesDir, filename);
810
+ if (existsSync3(filePath)) {
811
+ console.log(chalk5.green(`\u2713 ${filename}`));
812
+ } else {
813
+ console.log(chalk5.red(`\u2717 ${filename} (missing)`));
814
+ missingFiles.push(filename);
815
+ }
816
+ }
817
+ if (missingFiles.length === 0) {
818
+ console.log(
819
+ chalk5.green(`
820
+ \u2713 All ${mandatoryFiles.length} mandatory guidelines present`)
821
+ );
822
+ } else {
823
+ console.log(
824
+ chalk5.red(
825
+ `
826
+ \u2717 Missing ${missingFiles.length} mandatory guideline(s)`
827
+ )
828
+ );
829
+ }
830
+ if (options?.checkGuidelinesOnly) {
831
+ process.exit(missingFiles.length > 0 ? 1 : 0);
832
+ }
833
+ console.log(chalk5.cyan("\n\u{1F517} Git Hooks Check:\n"));
834
+ if (!hasGitRepo(cwd)) {
835
+ console.log(chalk5.yellow("\u26A0 No git repository found"));
836
+ console.log(chalk5.dim(" Run: git init"));
837
+ } else {
838
+ const hooksStatus = getAllHooksStatus(cwd);
839
+ for (const status of hooksStatus) {
840
+ if (status.installed) {
841
+ console.log(chalk5.green(`\u2713 ${status.hookType}: installed`));
842
+ } else {
843
+ console.log(chalk5.yellow(`\u26A0 ${status.hookType}: not installed`));
844
+ }
845
+ }
846
+ const allInstalled = hooksStatus.every((s) => s.installed);
847
+ if (!allInstalled) {
848
+ console.log(chalk5.dim("\n Run: workflow hooks install"));
849
+ }
850
+ }
851
+ if (missingFiles.length > 0) {
852
+ process.exit(1);
853
+ }
610
854
  }
611
855
 
612
856
  // src/cli/commands/setup.ts
613
857
  import * as p3 from "@clack/prompts";
614
858
  import chalk6 from "chalk";
615
- import { readFileSync, writeFileSync, existsSync as existsSync2 } from "fs";
616
- import { join as join2, dirname as dirname2 } from "path";
859
+ import { readFileSync, writeFileSync, existsSync as existsSync4 } from "fs";
860
+ import { join as join4, dirname as dirname2 } from "path";
617
861
  import { fileURLToPath as fileURLToPath2 } from "url";
618
862
  var __filename2 = fileURLToPath2(import.meta.url);
619
863
  var __dirname2 = dirname2(__filename2);
620
864
  async function setupCommand() {
621
865
  p3.intro(chalk6.bgBlue(" workflow-agent setup "));
622
866
  const cwd = process.cwd();
623
- const packageJsonPath = join2(cwd, "package.json");
624
- if (!existsSync2(packageJsonPath)) {
867
+ const packageJsonPath = join4(cwd, "package.json");
868
+ if (!existsSync4(packageJsonPath)) {
625
869
  p3.cancel("No package.json found in current directory");
626
870
  process.exit(1);
627
871
  }
@@ -686,8 +930,8 @@ async function setupCommand() {
686
930
  console.log(chalk6.dim("\nRun them with:"));
687
931
  console.log(chalk6.dim(" pnpm run workflow:init"));
688
932
  console.log(chalk6.dim(" npm run workflow:init\n"));
689
- const guidelinesDir = join2(cwd, "guidelines");
690
- if (!existsSync2(guidelinesDir)) {
933
+ const guidelinesDir = join4(cwd, "guidelines");
934
+ if (!existsSync4(guidelinesDir)) {
691
935
  const templatesDir = findTemplatesDirectory(__dirname2);
692
936
  if (templatesDir) {
693
937
  const templateResult = installMandatoryTemplates(cwd, templatesDir, {
@@ -705,7 +949,7 @@ async function setupCommand() {
705
949
  }
706
950
  }
707
951
  }
708
- if (existsSync2(guidelinesDir)) {
952
+ if (existsSync4(guidelinesDir)) {
709
953
  const result = generateCopilotInstructions(cwd, { silent: false });
710
954
  if (result.success) {
711
955
  const status = result.isNew ? "Generated" : "Updated";
@@ -724,14 +968,14 @@ async function setupCommand() {
724
968
  // src/cli/commands/scope-create.ts
725
969
  import * as p4 from "@clack/prompts";
726
970
  import chalk7 from "chalk";
727
- import { existsSync as existsSync3 } from "fs";
728
- import { writeFile as writeFile2, mkdir as mkdir2, readFile } from "fs/promises";
729
- import { join as join3 } from "path";
971
+ import { existsSync as existsSync5 } from "fs";
972
+ import { writeFile as writeFile3, mkdir as mkdir3, readFile as readFile2 } from "fs/promises";
973
+ import { join as join5 } from "path";
730
974
  async function scopeCreateCommand(options) {
731
975
  console.log(chalk7.bold.cyan("\n\u{1F3A8} Create Custom Scope Package\n"));
732
976
  const cwd = process.cwd();
733
977
  const isNonInteractive = !!(options.name && options.scopes && options.presetName);
734
- const isMonorepo2 = existsSync3(join3(cwd, "pnpm-workspace.yaml"));
978
+ const isMonorepo2 = existsSync5(join5(cwd, "pnpm-workspace.yaml"));
735
979
  if (isMonorepo2) {
736
980
  console.log(chalk7.dim("\u2713 Detected monorepo workspace\n"));
737
981
  }
@@ -877,7 +1121,7 @@ async function scopeCreateCommand(options) {
877
1121
  if (options.outputDir) {
878
1122
  outputDir = options.outputDir;
879
1123
  } else if (isMonorepo2) {
880
- outputDir = join3(cwd, "packages", `scopes-${packageName}`);
1124
+ outputDir = join5(cwd, "packages", `scopes-${packageName}`);
881
1125
  } else {
882
1126
  const customDir = await p4.text({
883
1127
  message: "Output directory:",
@@ -888,9 +1132,9 @@ async function scopeCreateCommand(options) {
888
1132
  p4.cancel("Operation cancelled");
889
1133
  process.exit(0);
890
1134
  }
891
- outputDir = join3(cwd, customDir);
1135
+ outputDir = join5(cwd, customDir);
892
1136
  }
893
- if (existsSync3(outputDir)) {
1137
+ if (existsSync5(outputDir)) {
894
1138
  const shouldOverwrite = await p4.confirm({
895
1139
  message: `Directory ${outputDir} already exists. Overwrite?`,
896
1140
  initialValue: false
@@ -903,7 +1147,7 @@ async function scopeCreateCommand(options) {
903
1147
  const spinner10 = p4.spinner();
904
1148
  spinner10.start("Creating package structure...");
905
1149
  try {
906
- await mkdir2(join3(outputDir, "src"), { recursive: true });
1150
+ await mkdir3(join5(outputDir, "src"), { recursive: true });
907
1151
  const packageJson = {
908
1152
  name: `@workflow/scopes-${packageName}`,
909
1153
  version: "1.0.0",
@@ -943,8 +1187,8 @@ async function scopeCreateCommand(options) {
943
1187
  access: "public"
944
1188
  }
945
1189
  };
946
- await writeFile2(
947
- join3(outputDir, "package.json"),
1190
+ await writeFile3(
1191
+ join5(outputDir, "package.json"),
948
1192
  JSON.stringify(packageJson, null, 2),
949
1193
  "utf-8"
950
1194
  );
@@ -956,8 +1200,8 @@ async function scopeCreateCommand(options) {
956
1200
  },
957
1201
  include: ["src/**/*"]
958
1202
  };
959
- await writeFile2(
960
- join3(outputDir, "tsconfig.json"),
1203
+ await writeFile3(
1204
+ join5(outputDir, "tsconfig.json"),
961
1205
  JSON.stringify(tsconfig, null, 2),
962
1206
  "utf-8"
963
1207
  );
@@ -971,7 +1215,7 @@ export default defineConfig({
971
1215
  sourcemap: true,
972
1216
  });
973
1217
  `;
974
- await writeFile2(join3(outputDir, "tsup.config.ts"), tsupConfig, "utf-8");
1218
+ await writeFile3(join5(outputDir, "tsup.config.ts"), tsupConfig, "utf-8");
975
1219
  const indexTs = `import type { Scope } from '@hawkinside_out/workflow-agent/config';
976
1220
 
977
1221
  export const scopes: Scope[] = ${JSON.stringify(scopes, null, 2)};
@@ -985,7 +1229,7 @@ export const preset = {
985
1229
 
986
1230
  export default preset;
987
1231
  `;
988
- await writeFile2(join3(outputDir, "src", "index.ts"), indexTs, "utf-8");
1232
+ await writeFile3(join5(outputDir, "src", "index.ts"), indexTs, "utf-8");
989
1233
  if (!options.noTest) {
990
1234
  const testFile = `import { describe, it, expect } from 'vitest';
991
1235
  import { scopes, preset } from './index.js';
@@ -1026,16 +1270,16 @@ describe('${presetName} Scope Preset', () => {
1026
1270
  });
1027
1271
  });
1028
1272
  `;
1029
- await writeFile2(
1030
- join3(outputDir, "src", "index.test.ts"),
1273
+ await writeFile3(
1274
+ join5(outputDir, "src", "index.test.ts"),
1031
1275
  testFile,
1032
1276
  "utf-8"
1033
1277
  );
1034
1278
  }
1035
1279
  spinner10.stop("\u2713 Package structure created");
1036
1280
  if (isMonorepo2) {
1037
- const workspaceFile = join3(cwd, "pnpm-workspace.yaml");
1038
- const workspaceContent = await readFile(workspaceFile, "utf-8");
1281
+ const workspaceFile = join5(cwd, "pnpm-workspace.yaml");
1282
+ const workspaceContent = await readFile2(workspaceFile, "utf-8");
1039
1283
  const packagePath = `packages/scopes-${packageName}`;
1040
1284
  if (!workspaceContent.includes(packagePath) && !workspaceContent.includes("packages/*")) {
1041
1285
  console.log(
@@ -1093,9 +1337,9 @@ describe('${presetName} Scope Preset', () => {
1093
1337
  // src/cli/commands/scope-migrate.ts
1094
1338
  import * as p5 from "@clack/prompts";
1095
1339
  import chalk8 from "chalk";
1096
- import { existsSync as existsSync4 } from "fs";
1097
- import { writeFile as writeFile3, mkdir as mkdir3, readFile as readFile2 } from "fs/promises";
1098
- import { join as join4 } from "path";
1340
+ import { existsSync as existsSync6 } from "fs";
1341
+ import { writeFile as writeFile4, mkdir as mkdir4, readFile as readFile3 } from "fs/promises";
1342
+ import { join as join6 } from "path";
1099
1343
  async function scopeMigrateCommand(options) {
1100
1344
  console.log(chalk8.bold.cyan("\n\u{1F504} Migrate Scopes to Custom Package\n"));
1101
1345
  const cwd = process.cwd();
@@ -1139,7 +1383,7 @@ async function scopeMigrateCommand(options) {
1139
1383
  p5.cancel("Migration cancelled");
1140
1384
  process.exit(0);
1141
1385
  }
1142
- const isMonorepo2 = existsSync4(join4(cwd, "pnpm-workspace.yaml"));
1386
+ const isMonorepo2 = existsSync6(join6(cwd, "pnpm-workspace.yaml"));
1143
1387
  if (isMonorepo2) {
1144
1388
  console.log(chalk8.dim("\n\u2713 Detected monorepo workspace\n"));
1145
1389
  }
@@ -1189,7 +1433,7 @@ async function scopeMigrateCommand(options) {
1189
1433
  if (options.outputDir) {
1190
1434
  outputDir = options.outputDir;
1191
1435
  } else if (isMonorepo2) {
1192
- outputDir = join4(cwd, "packages", `scopes-${packageName}`);
1436
+ outputDir = join6(cwd, "packages", `scopes-${packageName}`);
1193
1437
  } else {
1194
1438
  const customDir = await p5.text({
1195
1439
  message: "Output directory:",
@@ -1200,9 +1444,9 @@ async function scopeMigrateCommand(options) {
1200
1444
  p5.cancel("Migration cancelled");
1201
1445
  process.exit(0);
1202
1446
  }
1203
- outputDir = join4(cwd, customDir);
1447
+ outputDir = join6(cwd, customDir);
1204
1448
  }
1205
- if (existsSync4(outputDir)) {
1449
+ if (existsSync6(outputDir)) {
1206
1450
  const shouldOverwrite = await p5.confirm({
1207
1451
  message: `Directory ${outputDir} already exists. Overwrite?`,
1208
1452
  initialValue: false
@@ -1215,7 +1459,7 @@ async function scopeMigrateCommand(options) {
1215
1459
  const spinner10 = p5.spinner();
1216
1460
  spinner10.start("Migrating scopes to package...");
1217
1461
  try {
1218
- await mkdir3(join4(outputDir, "src"), { recursive: true });
1462
+ await mkdir4(join6(outputDir, "src"), { recursive: true });
1219
1463
  const packageJson = {
1220
1464
  name: `@workflow/scopes-${packageName}`,
1221
1465
  version: "1.0.0",
@@ -1255,8 +1499,8 @@ async function scopeMigrateCommand(options) {
1255
1499
  access: "public"
1256
1500
  }
1257
1501
  };
1258
- await writeFile3(
1259
- join4(outputDir, "package.json"),
1502
+ await writeFile4(
1503
+ join6(outputDir, "package.json"),
1260
1504
  JSON.stringify(packageJson, null, 2),
1261
1505
  "utf-8"
1262
1506
  );
@@ -1268,8 +1512,8 @@ async function scopeMigrateCommand(options) {
1268
1512
  },
1269
1513
  include: ["src/**/*"]
1270
1514
  };
1271
- await writeFile3(
1272
- join4(outputDir, "tsconfig.json"),
1515
+ await writeFile4(
1516
+ join6(outputDir, "tsconfig.json"),
1273
1517
  JSON.stringify(tsconfig, null, 2),
1274
1518
  "utf-8"
1275
1519
  );
@@ -1283,7 +1527,7 @@ export default defineConfig({
1283
1527
  sourcemap: true,
1284
1528
  });
1285
1529
  `;
1286
- await writeFile3(join4(outputDir, "tsup.config.ts"), tsupConfig, "utf-8");
1530
+ await writeFile4(join6(outputDir, "tsup.config.ts"), tsupConfig, "utf-8");
1287
1531
  const indexTs = `import type { Scope } from '@hawkinside_out/workflow-agent/config';
1288
1532
 
1289
1533
  export const scopes: Scope[] = ${JSON.stringify(config.scopes, null, 2)};
@@ -1297,7 +1541,7 @@ export const preset = {
1297
1541
 
1298
1542
  export default preset;
1299
1543
  `;
1300
- await writeFile3(join4(outputDir, "src", "index.ts"), indexTs, "utf-8");
1544
+ await writeFile4(join6(outputDir, "src", "index.ts"), indexTs, "utf-8");
1301
1545
  const testFile = `import { describe, it, expect } from 'vitest';
1302
1546
  import { scopes, preset } from './index.js';
1303
1547
  import { ScopeSchema } from '@hawkinside_out/workflow-agent/config';
@@ -1340,11 +1584,11 @@ describe('${presetName} Scope Preset (Migrated)', () => {
1340
1584
  });
1341
1585
  });
1342
1586
  `;
1343
- await writeFile3(join4(outputDir, "src", "index.test.ts"), testFile, "utf-8");
1587
+ await writeFile4(join6(outputDir, "src", "index.test.ts"), testFile, "utf-8");
1344
1588
  spinner10.stop("\u2713 Package created from migrated scopes");
1345
1589
  if (isMonorepo2) {
1346
- const workspaceFile = join4(cwd, "pnpm-workspace.yaml");
1347
- const workspaceContent = await readFile2(workspaceFile, "utf-8");
1590
+ const workspaceFile = join6(cwd, "pnpm-workspace.yaml");
1591
+ const workspaceContent = await readFile3(workspaceFile, "utf-8");
1348
1592
  const packagePath = `packages/scopes-${packageName}`;
1349
1593
  if (!workspaceContent.includes(packagePath) && !workspaceContent.includes("packages/*")) {
1350
1594
  console.log(
@@ -1360,7 +1604,7 @@ describe('${presetName} Scope Preset (Migrated)', () => {
1360
1604
  initialValue: false
1361
1605
  });
1362
1606
  if (!p5.isCancel(keepConfig) && !keepConfig) {
1363
- const configPath = join4(cwd, "workflow.config.json");
1607
+ const configPath = join6(cwd, "workflow.config.json");
1364
1608
  const updatedConfig = {
1365
1609
  ...config,
1366
1610
  scopes: [],
@@ -1368,7 +1612,7 @@ describe('${presetName} Scope Preset (Migrated)', () => {
1368
1612
  preset: `scopes-${packageName}`
1369
1613
  // Reference the new package
1370
1614
  };
1371
- await writeFile3(
1615
+ await writeFile4(
1372
1616
  configPath,
1373
1617
  JSON.stringify(updatedConfig, null, 2),
1374
1618
  "utf-8"
@@ -1796,14 +2040,14 @@ function formatAuditReportColored(report) {
1796
2040
  // src/cli/commands/advisory.ts
1797
2041
  import * as p7 from "@clack/prompts";
1798
2042
  import chalk11 from "chalk";
1799
- import { existsSync as existsSync6 } from "fs";
1800
- import { readFile as readFile4, writeFile as writeFile4, mkdir as mkdir4 } from "fs/promises";
1801
- import { join as join6 } from "path";
2043
+ import { existsSync as existsSync8 } from "fs";
2044
+ import { readFile as readFile5, writeFile as writeFile5, mkdir as mkdir5 } from "fs/promises";
2045
+ import { join as join8 } from "path";
1802
2046
 
1803
2047
  // src/utils/advisory-analyzer.ts
1804
- import { existsSync as existsSync5 } from "fs";
1805
- import { readFile as readFile3 } from "fs/promises";
1806
- import { join as join5 } from "path";
2048
+ import { existsSync as existsSync7 } from "fs";
2049
+ import { readFile as readFile4 } from "fs/promises";
2050
+ import { join as join7 } from "path";
1807
2051
  import fg from "fast-glob";
1808
2052
  var AdvisoryAnalyzer = class {
1809
2053
  options;
@@ -2247,11 +2491,11 @@ var AdvisoryAnalyzer = class {
2247
2491
  // Helper Methods
2248
2492
  // ============================================================================
2249
2493
  async readPackageJson() {
2250
- const pkgPath = join5(this.options.cwd, "package.json");
2251
- if (!existsSync5(pkgPath)) {
2494
+ const pkgPath = join7(this.options.cwd, "package.json");
2495
+ if (!existsSync7(pkgPath)) {
2252
2496
  throw new Error("package.json not found");
2253
2497
  }
2254
- const content = await readFile3(pkgPath, "utf-8");
2498
+ const content = await readFile4(pkgPath, "utf-8");
2255
2499
  return JSON.parse(content);
2256
2500
  }
2257
2501
  async countFiles() {
@@ -3619,11 +3863,11 @@ async function advisoryCommand(options) {
3619
3863
  let comparisonReport;
3620
3864
  let comparator;
3621
3865
  if (options.compare) {
3622
- const comparisonPath = options.compare.endsWith(".json") ? join6(cwd, options.compare) : join6(cwd, options.compare, "analysis.json");
3623
- if (existsSync6(comparisonPath)) {
3866
+ const comparisonPath = options.compare.endsWith(".json") ? join8(cwd, options.compare) : join8(cwd, options.compare, "analysis.json");
3867
+ if (existsSync8(comparisonPath)) {
3624
3868
  spinner10.start("Comparing with previous report...");
3625
3869
  try {
3626
- const previousContent = await readFile4(comparisonPath, "utf-8");
3870
+ const previousContent = await readFile5(comparisonPath, "utf-8");
3627
3871
  const previousAnalysis = JSON.parse(previousContent);
3628
3872
  comparator = new ReportComparator(previousAnalysis, analysis);
3629
3873
  comparisonReport = comparator.compare();
@@ -3648,8 +3892,8 @@ async function advisoryCommand(options) {
3648
3892
  console.log(chalk11.dim("\n--dry-run mode: No files written.\n"));
3649
3893
  return;
3650
3894
  }
3651
- const fullOutputDir = join6(cwd, outputDir);
3652
- await mkdir4(fullOutputDir, { recursive: true });
3895
+ const fullOutputDir = join8(cwd, outputDir);
3896
+ await mkdir5(fullOutputDir, { recursive: true });
3653
3897
  spinner10.start("Generating reports...");
3654
3898
  try {
3655
3899
  const timestamp = options.timestamp ? (/* @__PURE__ */ new Date()).toISOString().split("T")[0] : "";
@@ -3674,24 +3918,24 @@ async function advisoryCommand(options) {
3674
3918
  console.log(chalk11.green("\u{1F4DD} Reports written to:"));
3675
3919
  const suffix = options.timestamp ? `-${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}` : "";
3676
3920
  if (options.format === "json") {
3677
- console.log(chalk11.dim(` ${join6(outputDir, `analysis${suffix}.json`)}`));
3678
- console.log(chalk11.dim(` ${join6(outputDir, `questions${suffix}.json`)}`));
3921
+ console.log(chalk11.dim(` ${join8(outputDir, `analysis${suffix}.json`)}`));
3922
+ console.log(chalk11.dim(` ${join8(outputDir, `questions${suffix}.json`)}`));
3679
3923
  } else {
3680
3924
  console.log(
3681
- chalk11.dim(` ${join6(outputDir, `EXECUTIVE_SUMMARY${suffix}.md`)}`)
3925
+ chalk11.dim(` ${join8(outputDir, `EXECUTIVE_SUMMARY${suffix}.md`)}`)
3682
3926
  );
3683
3927
  console.log(
3684
- chalk11.dim(` ${join6(outputDir, `TECHNOLOGY_AUDIT${suffix}.md`)}`)
3928
+ chalk11.dim(` ${join8(outputDir, `TECHNOLOGY_AUDIT${suffix}.md`)}`)
3685
3929
  );
3686
3930
  console.log(
3687
- chalk11.dim(` ${join6(outputDir, `STRATEGIC_ROADMAP${suffix}.md`)}`)
3931
+ chalk11.dim(` ${join8(outputDir, `STRATEGIC_ROADMAP${suffix}.md`)}`)
3688
3932
  );
3689
3933
  console.log(
3690
- chalk11.dim(` ${join6(outputDir, `BOARD_QUESTIONS${suffix}.md`)}`)
3934
+ chalk11.dim(` ${join8(outputDir, `BOARD_QUESTIONS${suffix}.md`)}`)
3691
3935
  );
3692
3936
  if (comparisonReport) {
3693
3937
  console.log(
3694
- chalk11.dim(` ${join6(outputDir, `DIFF_REPORT${suffix}.md`)}`)
3938
+ chalk11.dim(` ${join8(outputDir, `DIFF_REPORT${suffix}.md`)}`)
3695
3939
  );
3696
3940
  }
3697
3941
  }
@@ -3784,47 +4028,47 @@ function displayComparisonSummary(comparison) {
3784
4028
  }
3785
4029
  async function writeAnalysisJson(outputDir, analysis, questions, timestamp) {
3786
4030
  const suffix = timestamp ? `-${timestamp}` : "";
3787
- await writeFile4(
3788
- join6(outputDir, `analysis${suffix}.json`),
4031
+ await writeFile5(
4032
+ join8(outputDir, `analysis${suffix}.json`),
3789
4033
  JSON.stringify(analysis, null, 2),
3790
4034
  "utf-8"
3791
4035
  );
3792
- await writeFile4(
3793
- join6(outputDir, `questions${suffix}.json`),
4036
+ await writeFile5(
4037
+ join8(outputDir, `questions${suffix}.json`),
3794
4038
  JSON.stringify(questions, null, 2),
3795
4039
  "utf-8"
3796
4040
  );
3797
4041
  }
3798
4042
  async function writeMarkdownReports(outputDir, analysis, questions, comparator, timestamp) {
3799
4043
  const suffix = timestamp ? `-${timestamp}` : "";
3800
- await writeFile4(
3801
- join6(outputDir, `analysis.json`),
4044
+ await writeFile5(
4045
+ join8(outputDir, `analysis.json`),
3802
4046
  JSON.stringify(analysis, null, 2),
3803
4047
  "utf-8"
3804
4048
  );
3805
- await writeFile4(
3806
- join6(outputDir, `EXECUTIVE_SUMMARY${suffix}.md`),
4049
+ await writeFile5(
4050
+ join8(outputDir, `EXECUTIVE_SUMMARY${suffix}.md`),
3807
4051
  generateExecutiveSummary(analysis, questions),
3808
4052
  "utf-8"
3809
4053
  );
3810
- await writeFile4(
3811
- join6(outputDir, `TECHNOLOGY_AUDIT${suffix}.md`),
4054
+ await writeFile5(
4055
+ join8(outputDir, `TECHNOLOGY_AUDIT${suffix}.md`),
3812
4056
  generateTechnologyAudit(analysis),
3813
4057
  "utf-8"
3814
4058
  );
3815
- await writeFile4(
3816
- join6(outputDir, `STRATEGIC_ROADMAP${suffix}.md`),
4059
+ await writeFile5(
4060
+ join8(outputDir, `STRATEGIC_ROADMAP${suffix}.md`),
3817
4061
  generateStrategicRoadmap(analysis, questions),
3818
4062
  "utf-8"
3819
4063
  );
3820
- await writeFile4(
3821
- join6(outputDir, `BOARD_QUESTIONS${suffix}.md`),
4064
+ await writeFile5(
4065
+ join8(outputDir, `BOARD_QUESTIONS${suffix}.md`),
3822
4066
  generateBoardQuestions(questions),
3823
4067
  "utf-8"
3824
4068
  );
3825
4069
  if (comparator) {
3826
- await writeFile4(
3827
- join6(outputDir, `DIFF_REPORT${suffix}.md`),
4070
+ await writeFile5(
4071
+ join8(outputDir, `DIFF_REPORT${suffix}.md`),
3828
4072
  comparator.generateMarkdownSummary(),
3829
4073
  "utf-8"
3830
4074
  );
@@ -4441,20 +4685,20 @@ function checkCIThresholds(analysis, config) {
4441
4685
  // src/cli/commands/generate-instructions.ts
4442
4686
  import * as p8 from "@clack/prompts";
4443
4687
  import chalk12 from "chalk";
4444
- import { existsSync as existsSync7 } from "fs";
4445
- import { join as join7 } from "path";
4688
+ import { existsSync as existsSync9 } from "fs";
4689
+ import { join as join9 } from "path";
4446
4690
  async function generateInstructionsCommand(options) {
4447
4691
  p8.intro(chalk12.bgBlue(" workflow-agent generate-instructions "));
4448
4692
  const cwd = process.cwd();
4449
- const guidelinesDir = join7(cwd, "guidelines");
4450
- const outputPath = join7(cwd, ".github", "copilot-instructions.md");
4451
- if (!existsSync7(guidelinesDir)) {
4693
+ const guidelinesDir = join9(cwd, "guidelines");
4694
+ const outputPath = join9(cwd, ".github", "copilot-instructions.md");
4695
+ if (!existsSync9(guidelinesDir)) {
4452
4696
  p8.cancel(
4453
4697
  "No guidelines directory found. Run 'workflow init' first to generate guidelines."
4454
4698
  );
4455
4699
  process.exit(1);
4456
4700
  }
4457
- if (existsSync7(outputPath) && !options.force) {
4701
+ if (existsSync9(outputPath) && !options.force) {
4458
4702
  const shouldRegenerate = await p8.confirm({
4459
4703
  message: ".github/copilot-instructions.md already exists. Regenerate? (Custom content will be preserved)",
4460
4704
  initialValue: true
@@ -4514,8 +4758,8 @@ Reason: ${error instanceof Error ? error.message : String(error)}`
4514
4758
  // src/cli/commands/update-templates.ts
4515
4759
  import * as p9 from "@clack/prompts";
4516
4760
  import chalk13 from "chalk";
4517
- import { existsSync as existsSync8 } from "fs";
4518
- import { join as join8, dirname as dirname3 } from "path";
4761
+ import { existsSync as existsSync10 } from "fs";
4762
+ import { join as join10, dirname as dirname3 } from "path";
4519
4763
  import { fileURLToPath as fileURLToPath3 } from "url";
4520
4764
  var __filename3 = fileURLToPath3(import.meta.url);
4521
4765
  var __dirname3 = dirname3(__filename3);
@@ -4523,13 +4767,13 @@ async function updateTemplatesCommand(options) {
4523
4767
  const { force = false, skip = false } = options;
4524
4768
  p9.intro(chalk13.bgBlue(" workflow-agent update-templates "));
4525
4769
  const cwd = process.cwd();
4526
- const guidelinesDir = join8(cwd, "guidelines");
4770
+ const guidelinesDir = join10(cwd, "guidelines");
4527
4771
  const templatesDir = findTemplatesDirectory(__dirname3);
4528
4772
  if (!templatesDir) {
4529
4773
  p9.cancel("Could not find templates directory");
4530
4774
  process.exit(1);
4531
4775
  }
4532
- const guidelinesExist = existsSync8(guidelinesDir);
4776
+ const guidelinesExist = existsSync10(guidelinesDir);
4533
4777
  if (!guidelinesExist) {
4534
4778
  console.log(chalk13.yellow("\n\u26A0\uFE0F No guidelines directory found."));
4535
4779
  console.log(chalk13.dim("Run 'workflow-agent init' to set up guidelines.\n"));
@@ -4818,8 +5062,124 @@ Fixed: ${fixedCount}, Skipped: ${skippedCount}`)
4818
5062
  }
4819
5063
  }
4820
5064
 
4821
- // src/cli/commands/learn.ts
5065
+ // src/cli/commands/hooks.ts
4822
5066
  import chalk15 from "chalk";
5067
+ async function hooksCommand(action) {
5068
+ const cwd = process.cwd();
5069
+ switch (action) {
5070
+ case "install":
5071
+ await installHooksAction(cwd);
5072
+ break;
5073
+ case "uninstall":
5074
+ await uninstallHooksAction(cwd);
5075
+ break;
5076
+ case "status":
5077
+ await statusHooksAction(cwd);
5078
+ break;
5079
+ default:
5080
+ console.error(chalk15.red(`Unknown action: ${action}`));
5081
+ console.log(chalk15.dim("Available actions: install, uninstall, status"));
5082
+ process.exit(1);
5083
+ }
5084
+ }
5085
+ async function installHooksAction(cwd) {
5086
+ console.log(chalk15.bold.cyan("\n\u{1F517} Installing Workflow Agent Git Hooks\n"));
5087
+ if (!hasGitRepo(cwd)) {
5088
+ console.error(chalk15.red("\u2717 No git repository found"));
5089
+ console.log(chalk15.yellow(" Run: git init"));
5090
+ process.exit(1);
5091
+ }
5092
+ const config = await loadConfig();
5093
+ const hooksConfig = config?.hooks;
5094
+ const results = await installHooks(hooksConfig, cwd);
5095
+ let hasErrors = false;
5096
+ for (const result of results) {
5097
+ if (result.success) {
5098
+ if (result.wrappedExisting) {
5099
+ console.log(
5100
+ chalk15.green(
5101
+ `\u2713 Installed ${result.hookType} hook (wrapped existing hook)`
5102
+ )
5103
+ );
5104
+ } else {
5105
+ console.log(chalk15.green(`\u2713 Installed ${result.hookType} hook`));
5106
+ }
5107
+ } else {
5108
+ console.error(
5109
+ chalk15.red(`\u2717 Failed to install ${result.hookType}: ${result.error}`)
5110
+ );
5111
+ hasErrors = true;
5112
+ }
5113
+ }
5114
+ if (!hasErrors) {
5115
+ console.log(chalk15.green("\n\u2713 Git hooks installed successfully"));
5116
+ console.log(chalk15.dim("\nHooks will run automatically on commit."));
5117
+ console.log(chalk15.dim("They will be skipped in CI environments."));
5118
+ } else {
5119
+ process.exit(1);
5120
+ }
5121
+ }
5122
+ async function uninstallHooksAction(cwd) {
5123
+ console.log(chalk15.bold.cyan("\n\u{1F513} Uninstalling Workflow Agent Git Hooks\n"));
5124
+ if (!hasGitRepo(cwd)) {
5125
+ console.error(chalk15.red("\u2717 No git repository found"));
5126
+ process.exit(1);
5127
+ }
5128
+ const results = await uninstallHooks(cwd);
5129
+ let hasErrors = false;
5130
+ for (const result of results) {
5131
+ if (result.success) {
5132
+ if (result.wrappedExisting) {
5133
+ console.log(
5134
+ chalk15.green(`\u2713 Removed ${result.hookType} hook (restored original)`)
5135
+ );
5136
+ } else {
5137
+ console.log(chalk15.green(`\u2713 Removed ${result.hookType} hook`));
5138
+ }
5139
+ } else if (result.error) {
5140
+ console.error(
5141
+ chalk15.red(`\u2717 Failed to remove ${result.hookType}: ${result.error}`)
5142
+ );
5143
+ hasErrors = true;
5144
+ }
5145
+ }
5146
+ if (!hasErrors) {
5147
+ console.log(chalk15.green("\n\u2713 Git hooks uninstalled successfully"));
5148
+ } else {
5149
+ process.exit(1);
5150
+ }
5151
+ }
5152
+ async function statusHooksAction(cwd) {
5153
+ console.log(chalk15.bold.cyan("\n\u{1F4CA} Workflow Agent Git Hooks Status\n"));
5154
+ if (!hasGitRepo(cwd)) {
5155
+ console.error(chalk15.red("\u2717 No git repository found"));
5156
+ process.exit(1);
5157
+ }
5158
+ const statuses = await getAllHooksStatus(cwd);
5159
+ for (const status of statuses) {
5160
+ const icon = status.installed ? "\u2713" : "\u2717";
5161
+ const color = status.installed ? chalk15.green : chalk15.yellow;
5162
+ let message = `${icon} ${status.hookType}`;
5163
+ if (status.installed) {
5164
+ message += " - installed";
5165
+ if (status.wrappedOriginal) {
5166
+ message += " (wrapping original hook)";
5167
+ }
5168
+ } else if (status.hasExistingHook) {
5169
+ message += " - existing hook (not managed by Workflow Agent)";
5170
+ } else {
5171
+ message += " - not installed";
5172
+ }
5173
+ console.log(color(message));
5174
+ }
5175
+ const allInstalled = statuses.every((s) => s.installed);
5176
+ if (!allInstalled) {
5177
+ console.log(chalk15.dim("\nTo install hooks: workflow hooks install"));
5178
+ }
5179
+ }
5180
+
5181
+ // src/cli/commands/learn.ts
5182
+ import chalk16 from "chalk";
4823
5183
  import * as p11 from "@clack/prompts";
4824
5184
  import {
4825
5185
  PatternStore as PatternStore2,
@@ -4843,7 +5203,7 @@ function formatTags(tags) {
4843
5203
  async function learnRecordCommand(options) {
4844
5204
  const cwd = getWorkspacePath();
4845
5205
  const store = new PatternStore2(cwd);
4846
- console.log(chalk15.cyan("\n\u{1F4DA} Record a Learning Pattern\n"));
5206
+ console.log(chalk16.cyan("\n\u{1F4DA} Record a Learning Pattern\n"));
4847
5207
  let patternType = options.type;
4848
5208
  if (!patternType) {
4849
5209
  const typeChoice = await p11.select({
@@ -5008,14 +5368,14 @@ async function learnRecordCommand(options) {
5008
5368
  };
5009
5369
  const result = await store.saveFixPattern(fixPattern);
5010
5370
  if (result.success) {
5011
- console.log(chalk15.green("\n\u2705 Fix pattern recorded successfully!\n"));
5012
- console.log(chalk15.dim(` ID: ${fixPattern.id}`));
5013
- console.log(chalk15.dim(` Name: ${name}`));
5014
- console.log(chalk15.dim(` Category: ${category}`));
5015
- console.log(chalk15.dim(` Framework: ${framework} ${version}`));
5371
+ console.log(chalk16.green("\n\u2705 Fix pattern recorded successfully!\n"));
5372
+ console.log(chalk16.dim(` ID: ${fixPattern.id}`));
5373
+ console.log(chalk16.dim(` Name: ${name}`));
5374
+ console.log(chalk16.dim(` Category: ${category}`));
5375
+ console.log(chalk16.dim(` Framework: ${framework} ${version}`));
5016
5376
  } else {
5017
- console.log(chalk15.red("\n\u274C Failed to record pattern"));
5018
- console.log(chalk15.dim(` Error: ${result.error}`));
5377
+ console.log(chalk16.red("\n\u274C Failed to record pattern"));
5378
+ console.log(chalk16.dim(` Error: ${result.error}`));
5019
5379
  process.exit(1);
5020
5380
  }
5021
5381
  } else {
@@ -5062,13 +5422,13 @@ async function learnRecordCommand(options) {
5062
5422
  };
5063
5423
  const result = await store.saveBlueprint(blueprint);
5064
5424
  if (result.success) {
5065
- console.log(chalk15.green("\n\u2705 Blueprint recorded successfully!\n"));
5066
- console.log(chalk15.dim(` ID: ${blueprint.id}`));
5067
- console.log(chalk15.dim(` Name: ${name}`));
5068
- console.log(chalk15.dim(` Framework: ${framework} ${version}`));
5425
+ console.log(chalk16.green("\n\u2705 Blueprint recorded successfully!\n"));
5426
+ console.log(chalk16.dim(` ID: ${blueprint.id}`));
5427
+ console.log(chalk16.dim(` Name: ${name}`));
5428
+ console.log(chalk16.dim(` Framework: ${framework} ${version}`));
5069
5429
  } else {
5070
- console.log(chalk15.red("\n\u274C Failed to record blueprint"));
5071
- console.log(chalk15.dim(` Error: ${result.error}`));
5430
+ console.log(chalk16.red("\n\u274C Failed to record blueprint"));
5431
+ console.log(chalk16.dim(` Error: ${result.error}`));
5072
5432
  process.exit(1);
5073
5433
  }
5074
5434
  }
@@ -5078,7 +5438,7 @@ async function learnListCommand(options) {
5078
5438
  const store = new PatternStore2(cwd);
5079
5439
  const patternType = options.type ?? "all";
5080
5440
  const showDeprecated = options.deprecated ?? false;
5081
- console.log(chalk15.cyan("\n\u{1F4DA} Recorded Learning Patterns\n"));
5441
+ console.log(chalk16.cyan("\n\u{1F4DA} Recorded Learning Patterns\n"));
5082
5442
  if (patternType === "all" || patternType === "fix") {
5083
5443
  const fixResult = await store.listFixPatterns({
5084
5444
  tags: options.tag ? [{ category: "framework", name: options.tag }] : void 0,
@@ -5086,29 +5446,29 @@ async function learnListCommand(options) {
5086
5446
  includeDeprecated: showDeprecated
5087
5447
  });
5088
5448
  if (fixResult.success && fixResult.data && fixResult.data.length > 0) {
5089
- console.log(chalk15.bold.yellow("\u{1F527} Fix Patterns:\n"));
5449
+ console.log(chalk16.bold.yellow("\u{1F527} Fix Patterns:\n"));
5090
5450
  for (const pattern of fixResult.data) {
5091
5451
  const isDeprecated = pattern.deprecatedAt !== void 0;
5092
5452
  const statusIcon = isDeprecated ? "\u26A0\uFE0F" : "\u2713";
5093
- const nameColor = isDeprecated ? chalk15.dim : chalk15.white;
5453
+ const nameColor = isDeprecated ? chalk16.dim : chalk16.white;
5094
5454
  console.log(` ${statusIcon} ${nameColor(pattern.name)}`);
5095
- console.log(chalk15.dim(` ID: ${pattern.id}`));
5096
- console.log(chalk15.dim(` Category: ${pattern.category}`));
5455
+ console.log(chalk16.dim(` ID: ${pattern.id}`));
5456
+ console.log(chalk16.dim(` Category: ${pattern.category}`));
5097
5457
  console.log(
5098
- chalk15.dim(` Created: ${formatDate(pattern.createdAt)}`)
5458
+ chalk16.dim(` Created: ${formatDate(pattern.createdAt)}`)
5099
5459
  );
5100
5460
  console.log(
5101
- chalk15.dim(
5461
+ chalk16.dim(
5102
5462
  ` Success Rate: ${(pattern.metrics.successRate * 100).toFixed(0)}% (${pattern.metrics.successes}/${pattern.metrics.applications})`
5103
5463
  )
5104
5464
  );
5105
5465
  if (pattern.tags.length > 0) {
5106
- console.log(chalk15.dim(` Tags: ${formatTags(pattern.tags)}`));
5466
+ console.log(chalk16.dim(` Tags: ${formatTags(pattern.tags)}`));
5107
5467
  }
5108
5468
  console.log("");
5109
5469
  }
5110
5470
  } else if (patternType === "fix") {
5111
- console.log(chalk15.dim(" No fix patterns found.\n"));
5471
+ console.log(chalk16.dim(" No fix patterns found.\n"));
5112
5472
  }
5113
5473
  }
5114
5474
  if (patternType === "all" || patternType === "blueprint") {
@@ -5118,46 +5478,46 @@ async function learnListCommand(options) {
5118
5478
  includeDeprecated: showDeprecated
5119
5479
  });
5120
5480
  if (bpResult.success && bpResult.data && bpResult.data.length > 0) {
5121
- console.log(chalk15.bold.blue("\u{1F4D0} Blueprints:\n"));
5481
+ console.log(chalk16.bold.blue("\u{1F4D0} Blueprints:\n"));
5122
5482
  for (const blueprint of bpResult.data) {
5123
5483
  const isDeprecated = blueprint.deprecatedAt !== void 0;
5124
5484
  const statusIcon = isDeprecated ? "\u26A0\uFE0F" : "\u2713";
5125
- const nameColor = isDeprecated ? chalk15.dim : chalk15.white;
5485
+ const nameColor = isDeprecated ? chalk16.dim : chalk16.white;
5126
5486
  console.log(` ${statusIcon} ${nameColor(blueprint.name)}`);
5127
- console.log(chalk15.dim(` ID: ${blueprint.id}`));
5128
- console.log(chalk15.dim(` Language: ${blueprint.stack.language}`));
5487
+ console.log(chalk16.dim(` ID: ${blueprint.id}`));
5488
+ console.log(chalk16.dim(` Language: ${blueprint.stack.language}`));
5129
5489
  console.log(
5130
- chalk15.dim(` Created: ${formatDate(blueprint.createdAt)}`)
5490
+ chalk16.dim(` Created: ${formatDate(blueprint.createdAt)}`)
5131
5491
  );
5132
5492
  console.log(
5133
- chalk15.dim(
5493
+ chalk16.dim(
5134
5494
  ` Success Rate: ${(blueprint.metrics.successRate * 100).toFixed(0)}% (${blueprint.metrics.successes}/${blueprint.metrics.applications})`
5135
5495
  )
5136
5496
  );
5137
5497
  if (blueprint.tags.length > 0) {
5138
- console.log(chalk15.dim(` Tags: ${formatTags(blueprint.tags)}`));
5498
+ console.log(chalk16.dim(` Tags: ${formatTags(blueprint.tags)}`));
5139
5499
  }
5140
5500
  console.log("");
5141
5501
  }
5142
5502
  } else if (patternType === "blueprint") {
5143
- console.log(chalk15.dim(" No blueprints found.\n"));
5503
+ console.log(chalk16.dim(" No blueprints found.\n"));
5144
5504
  }
5145
5505
  }
5146
5506
  const stats = await store.getStats();
5147
5507
  const totalPatterns = stats.totalFixes + stats.totalBlueprints;
5148
5508
  const totalDeprecated = stats.deprecatedFixes + stats.deprecatedBlueprints;
5149
- console.log(chalk15.dim("\u2501".repeat(40)));
5150
- console.log(chalk15.dim(`Total: ${totalPatterns} patterns`));
5151
- console.log(chalk15.dim(` Fix Patterns: ${stats.totalFixes}`));
5152
- console.log(chalk15.dim(` Blueprints: ${stats.totalBlueprints}`));
5153
- console.log(chalk15.dim(` Deprecated: ${totalDeprecated}`));
5509
+ console.log(chalk16.dim("\u2501".repeat(40)));
5510
+ console.log(chalk16.dim(`Total: ${totalPatterns} patterns`));
5511
+ console.log(chalk16.dim(` Fix Patterns: ${stats.totalFixes}`));
5512
+ console.log(chalk16.dim(` Blueprints: ${stats.totalBlueprints}`));
5513
+ console.log(chalk16.dim(` Deprecated: ${totalDeprecated}`));
5154
5514
  console.log("");
5155
5515
  }
5156
5516
  async function learnApplyCommand(patternId, options) {
5157
5517
  const cwd = getWorkspacePath();
5158
5518
  const store = new PatternStore2(cwd);
5159
5519
  const telemetry = new TelemetryCollector2(cwd);
5160
- console.log(chalk15.cyan("\n\u{1F527} Apply Learning Pattern\n"));
5520
+ console.log(chalk16.cyan("\n\u{1F527} Apply Learning Pattern\n"));
5161
5521
  let pattern = await store.getFixPattern(patternId);
5162
5522
  let patternType = "fix";
5163
5523
  if (!pattern.success || !pattern.data) {
@@ -5166,21 +5526,21 @@ async function learnApplyCommand(patternId, options) {
5166
5526
  pattern = bpResult;
5167
5527
  patternType = "blueprint";
5168
5528
  } else {
5169
- console.log(chalk15.red(`
5529
+ console.log(chalk16.red(`
5170
5530
  \u274C Pattern not found: ${patternId}`));
5171
5531
  console.log(
5172
- chalk15.dim(" Use 'workflow learn:list' to see available patterns")
5532
+ chalk16.dim(" Use 'workflow learn:list' to see available patterns")
5173
5533
  );
5174
5534
  process.exit(1);
5175
5535
  }
5176
5536
  }
5177
5537
  const patternData = pattern.data;
5178
- console.log(chalk15.white(` Pattern: ${patternData.name}`));
5179
- console.log(chalk15.dim(` Type: ${patternType}`));
5180
- console.log(chalk15.dim(` Description: ${patternData.description}`));
5538
+ console.log(chalk16.white(` Pattern: ${patternData.name}`));
5539
+ console.log(chalk16.dim(` Type: ${patternType}`));
5540
+ console.log(chalk16.dim(` Description: ${patternData.description}`));
5181
5541
  if (options.dryRun) {
5182
5542
  console.log(
5183
- chalk15.yellow("\n\u{1F4CB} DRY-RUN MODE: No changes will be applied\n")
5543
+ chalk16.yellow("\n\u{1F4CB} DRY-RUN MODE: No changes will be applied\n")
5184
5544
  );
5185
5545
  }
5186
5546
  const framework = options.framework ?? patternData.compatibility.frameworks[0]?.name ?? "unknown";
@@ -5188,27 +5548,27 @@ async function learnApplyCommand(patternId, options) {
5188
5548
  await telemetry.recordApplication(patternId, patternType, framework, version);
5189
5549
  if (patternType === "fix") {
5190
5550
  const fixPattern = patternData;
5191
- console.log(chalk15.cyan("\n\u{1F4CB} Solution Steps:\n"));
5551
+ console.log(chalk16.cyan("\n\u{1F4CB} Solution Steps:\n"));
5192
5552
  if (fixPattern.solution.steps) {
5193
5553
  for (let i = 0; i < fixPattern.solution.steps.length; i++) {
5194
5554
  const step = fixPattern.solution.steps[i];
5195
5555
  console.log(
5196
- chalk15.white(` ${i + 1}. [${step.action}] ${step.description}`)
5556
+ chalk16.white(` ${i + 1}. [${step.action}] ${step.description}`)
5197
5557
  );
5198
5558
  if (step.file) {
5199
- console.log(chalk15.dim(` File: ${step.file}`));
5559
+ console.log(chalk16.dim(` File: ${step.file}`));
5200
5560
  }
5201
5561
  }
5202
5562
  }
5203
5563
  } else {
5204
5564
  const blueprint = patternData;
5205
- console.log(chalk15.cyan("\n\u{1F4CB} Setup Steps:\n"));
5565
+ console.log(chalk16.cyan("\n\u{1F4CB} Setup Steps:\n"));
5206
5566
  if (blueprint.setup.steps) {
5207
5567
  for (let i = 0; i < blueprint.setup.steps.length; i++) {
5208
5568
  const step = blueprint.setup.steps[i];
5209
- console.log(chalk15.white(` ${i + 1}. ${step.description}`));
5569
+ console.log(chalk16.white(` ${i + 1}. ${step.description}`));
5210
5570
  if (step.command) {
5211
- console.log(chalk15.dim(` Command: ${step.command}`));
5571
+ console.log(chalk16.dim(` Command: ${step.command}`));
5212
5572
  }
5213
5573
  }
5214
5574
  }
@@ -5225,7 +5585,7 @@ async function learnApplyCommand(patternId, options) {
5225
5585
  if (confirmed) {
5226
5586
  await store.updatePatternMetrics(patternId, patternType, true);
5227
5587
  await telemetry.recordSuccess(patternId, patternType, framework, version);
5228
- console.log(chalk15.green("\n\u2705 Pattern marked as successfully applied!"));
5588
+ console.log(chalk16.green("\n\u2705 Pattern marked as successfully applied!"));
5229
5589
  } else {
5230
5590
  await store.updatePatternMetrics(patternId, patternType, false);
5231
5591
  await telemetry.recordFailure(
@@ -5236,7 +5596,7 @@ async function learnApplyCommand(patternId, options) {
5236
5596
  "unknown"
5237
5597
  );
5238
5598
  console.log(
5239
- chalk15.yellow("\n\u26A0\uFE0F Pattern application marked as unsuccessful.")
5599
+ chalk16.yellow("\n\u26A0\uFE0F Pattern application marked as unsuccessful.")
5240
5600
  );
5241
5601
  }
5242
5602
  }
@@ -5244,32 +5604,32 @@ async function learnApplyCommand(patternId, options) {
5244
5604
  async function learnSyncCommand(options) {
5245
5605
  const cwd = getWorkspacePath();
5246
5606
  const contributorManager = new ContributorManager2(cwd);
5247
- console.log(chalk15.cyan("\n\u{1F504} Sync Learning Patterns\n"));
5607
+ console.log(chalk16.cyan("\n\u{1F504} Sync Learning Patterns\n"));
5248
5608
  const config = await contributorManager.getConfig();
5249
5609
  if (!config.success || !config.data?.syncOptIn) {
5250
- console.log(chalk15.yellow("\u26A0\uFE0F Sync is not enabled.\n"));
5251
- console.log(chalk15.dim(" To enable sync, run:"));
5252
- console.log(chalk15.dim(" workflow learn:config --enable-sync\n"));
5610
+ console.log(chalk16.yellow("\u26A0\uFE0F Sync is not enabled.\n"));
5611
+ console.log(chalk16.dim(" To enable sync, run:"));
5612
+ console.log(chalk16.dim(" workflow learn:config --enable-sync\n"));
5253
5613
  console.log(
5254
- chalk15.dim(
5614
+ chalk16.dim(
5255
5615
  " This allows you to share anonymized patterns with the community."
5256
5616
  )
5257
5617
  );
5258
5618
  process.exit(0);
5259
5619
  }
5260
5620
  if (options.dryRun) {
5261
- console.log(chalk15.yellow("\u{1F4CB} DRY-RUN MODE: No changes will be synced\n"));
5621
+ console.log(chalk16.yellow("\u{1F4CB} DRY-RUN MODE: No changes will be synced\n"));
5262
5622
  }
5263
5623
  const store = new PatternStore2(cwd);
5264
5624
  const anonymizer = new PatternAnonymizer();
5265
5625
  const { fixes, blueprints } = await store.getPatternsForSync();
5266
5626
  console.log(
5267
- chalk15.dim(
5627
+ chalk16.dim(
5268
5628
  ` Patterns ready to sync: ${fixes.length} fixes, ${blueprints.length} blueprints`
5269
5629
  )
5270
5630
  );
5271
5631
  if (options.push) {
5272
- console.log(chalk15.cyan("\n\u{1F4E4} Pushing patterns...\n"));
5632
+ console.log(chalk16.cyan("\n\u{1F4E4} Pushing patterns...\n"));
5273
5633
  let anonymizedFixes = 0;
5274
5634
  let anonymizedBlueprints = 0;
5275
5635
  for (const fix of fixes) {
@@ -5277,7 +5637,7 @@ async function learnSyncCommand(options) {
5277
5637
  if (result.success) {
5278
5638
  anonymizedFixes++;
5279
5639
  if (!options.dryRun) {
5280
- console.log(chalk15.dim(` \u2713 Anonymized: ${fix.name}`));
5640
+ console.log(chalk16.dim(` \u2713 Anonymized: ${fix.name}`));
5281
5641
  }
5282
5642
  }
5283
5643
  }
@@ -5286,73 +5646,73 @@ async function learnSyncCommand(options) {
5286
5646
  if (result.success) {
5287
5647
  anonymizedBlueprints++;
5288
5648
  if (!options.dryRun) {
5289
- console.log(chalk15.dim(` \u2713 Anonymized: ${bp.name}`));
5649
+ console.log(chalk16.dim(` \u2713 Anonymized: ${bp.name}`));
5290
5650
  }
5291
5651
  }
5292
5652
  }
5293
5653
  console.log(
5294
- chalk15.green(
5654
+ chalk16.green(
5295
5655
  `
5296
5656
  \u2705 Ready to push ${anonymizedFixes} fixes and ${anonymizedBlueprints} blueprints`
5297
5657
  )
5298
5658
  );
5299
- console.log(chalk15.dim(" (Registry push not yet implemented)"));
5659
+ console.log(chalk16.dim(" (Registry push not yet implemented)"));
5300
5660
  }
5301
5661
  if (options.pull) {
5302
- console.log(chalk15.cyan("\n\u{1F4E5} Pulling patterns from registry...\n"));
5303
- console.log(chalk15.dim(" (Registry pull not yet implemented)"));
5662
+ console.log(chalk16.cyan("\n\u{1F4E5} Pulling patterns from registry...\n"));
5663
+ console.log(chalk16.dim(" (Registry pull not yet implemented)"));
5304
5664
  }
5305
5665
  if (!options.push && !options.pull) {
5306
5666
  console.log(
5307
- chalk15.dim(" Specify --push to upload or --pull to download patterns.\n")
5667
+ chalk16.dim(" Specify --push to upload or --pull to download patterns.\n")
5308
5668
  );
5309
5669
  }
5310
5670
  }
5311
5671
  async function learnConfigCommand(options) {
5312
5672
  const cwd = getWorkspacePath();
5313
5673
  const contributorManager = new ContributorManager2(cwd);
5314
- console.log(chalk15.cyan("\n\u2699\uFE0F Learning Configuration\n"));
5674
+ console.log(chalk16.cyan("\n\u2699\uFE0F Learning Configuration\n"));
5315
5675
  if (options.enableSync) {
5316
5676
  const result = await contributorManager.enableSync();
5317
5677
  if (result.success) {
5318
- console.log(chalk15.green("\u2705 Sync enabled"));
5678
+ console.log(chalk16.green("\u2705 Sync enabled"));
5319
5679
  console.log(
5320
- chalk15.dim(" Your patterns will be anonymized before sharing.")
5680
+ chalk16.dim(" Your patterns will be anonymized before sharing.")
5321
5681
  );
5322
5682
  } else {
5323
- console.log(chalk15.red(`\u274C Failed: ${result.error}`));
5683
+ console.log(chalk16.red(`\u274C Failed: ${result.error}`));
5324
5684
  }
5325
5685
  return;
5326
5686
  }
5327
5687
  if (options.disableSync) {
5328
5688
  const result = await contributorManager.disableSync();
5329
5689
  if (result.success) {
5330
- console.log(chalk15.green("\u2705 Sync disabled"));
5690
+ console.log(chalk16.green("\u2705 Sync disabled"));
5331
5691
  } else {
5332
- console.log(chalk15.red(`\u274C Failed: ${result.error}`));
5692
+ console.log(chalk16.red(`\u274C Failed: ${result.error}`));
5333
5693
  }
5334
5694
  return;
5335
5695
  }
5336
5696
  if (options.enableTelemetry) {
5337
5697
  const result = await contributorManager.enableTelemetry();
5338
5698
  if (result.success) {
5339
- console.log(chalk15.green("\u2705 Telemetry enabled"));
5699
+ console.log(chalk16.green("\u2705 Telemetry enabled"));
5340
5700
  console.log(
5341
- chalk15.dim(
5701
+ chalk16.dim(
5342
5702
  " Anonymous usage data helps improve pattern recommendations."
5343
5703
  )
5344
5704
  );
5345
5705
  } else {
5346
- console.log(chalk15.red(`\u274C Failed: ${result.error}`));
5706
+ console.log(chalk16.red(`\u274C Failed: ${result.error}`));
5347
5707
  }
5348
5708
  return;
5349
5709
  }
5350
5710
  if (options.disableTelemetry) {
5351
5711
  const result = await contributorManager.disableTelemetry();
5352
5712
  if (result.success) {
5353
- console.log(chalk15.green("\u2705 Telemetry disabled"));
5713
+ console.log(chalk16.green("\u2705 Telemetry disabled"));
5354
5714
  } else {
5355
- console.log(chalk15.red(`\u274C Failed: ${result.error}`));
5715
+ console.log(chalk16.red(`\u274C Failed: ${result.error}`));
5356
5716
  }
5357
5717
  return;
5358
5718
  }
@@ -5367,36 +5727,36 @@ async function learnConfigCommand(options) {
5367
5727
  }
5368
5728
  const result = await contributorManager.resetId();
5369
5729
  if (result.success) {
5370
- console.log(chalk15.green("\u2705 Contributor ID reset"));
5371
- console.log(chalk15.dim(` New ID: ${result.data?.id}`));
5730
+ console.log(chalk16.green("\u2705 Contributor ID reset"));
5731
+ console.log(chalk16.dim(` New ID: ${result.data?.id}`));
5372
5732
  } else {
5373
- console.log(chalk15.red(`\u274C Failed: ${result.error}`));
5733
+ console.log(chalk16.red(`\u274C Failed: ${result.error}`));
5374
5734
  }
5375
5735
  return;
5376
5736
  }
5377
5737
  const config = await contributorManager.getConfig();
5378
5738
  if (config.success && config.data) {
5379
- console.log(chalk15.white(" Current Settings:\n"));
5380
- console.log(chalk15.dim(` Contributor ID: ${config.data.id}`));
5381
- console.log(chalk15.dim(` Created: ${formatDate(config.data.createdAt)}`));
5739
+ console.log(chalk16.white(" Current Settings:\n"));
5740
+ console.log(chalk16.dim(` Contributor ID: ${config.data.id}`));
5741
+ console.log(chalk16.dim(` Created: ${formatDate(config.data.createdAt)}`));
5382
5742
  console.log(
5383
- chalk15.dim(` Sync Enabled: ${config.data.syncOptIn ? "Yes" : "No"}`)
5743
+ chalk16.dim(` Sync Enabled: ${config.data.syncOptIn ? "Yes" : "No"}`)
5384
5744
  );
5385
5745
  console.log(
5386
- chalk15.dim(
5746
+ chalk16.dim(
5387
5747
  ` Telemetry Enabled: ${config.data.telemetryEnabled ? "Yes" : "No"}`
5388
5748
  )
5389
5749
  );
5390
5750
  if (config.data.syncEnabledAt) {
5391
5751
  console.log(
5392
- chalk15.dim(
5752
+ chalk16.dim(
5393
5753
  ` Sync Enabled At: ${formatDate(config.data.syncEnabledAt)}`
5394
5754
  )
5395
5755
  );
5396
5756
  }
5397
5757
  } else {
5398
5758
  console.log(
5399
- chalk15.dim(
5759
+ chalk16.dim(
5400
5760
  " No configuration found. Settings will be created on first use.\n"
5401
5761
  )
5402
5762
  );
@@ -5405,7 +5765,7 @@ async function learnConfigCommand(options) {
5405
5765
  async function learnDeprecateCommand(patternId, reason) {
5406
5766
  const cwd = getWorkspacePath();
5407
5767
  const store = new PatternStore2(cwd);
5408
- console.log(chalk15.cyan("\n\u26A0\uFE0F Deprecate Pattern\n"));
5768
+ console.log(chalk16.cyan("\n\u26A0\uFE0F Deprecate Pattern\n"));
5409
5769
  let patternType = "fix";
5410
5770
  let pattern = await store.getFixPattern(patternId);
5411
5771
  if (!pattern.success || !pattern.data) {
@@ -5414,13 +5774,13 @@ async function learnDeprecateCommand(patternId, reason) {
5414
5774
  pattern = bpResult;
5415
5775
  patternType = "blueprint";
5416
5776
  } else {
5417
- console.log(chalk15.red(`
5777
+ console.log(chalk16.red(`
5418
5778
  \u274C Pattern not found: ${patternId}`));
5419
5779
  process.exit(1);
5420
5780
  }
5421
5781
  }
5422
- console.log(chalk15.white(` Pattern: ${pattern.data.name}`));
5423
- console.log(chalk15.dim(` Reason: ${reason}`));
5782
+ console.log(chalk16.white(` Pattern: ${pattern.data.name}`));
5783
+ console.log(chalk16.dim(` Reason: ${reason}`));
5424
5784
  const confirmed = await p11.confirm({
5425
5785
  message: "Are you sure you want to deprecate this pattern?",
5426
5786
  initialValue: false
@@ -5431,9 +5791,9 @@ async function learnDeprecateCommand(patternId, reason) {
5431
5791
  }
5432
5792
  const result = await store.deprecatePattern(patternId, patternType, reason);
5433
5793
  if (result.success) {
5434
- console.log(chalk15.green("\n\u2705 Pattern deprecated successfully"));
5794
+ console.log(chalk16.green("\n\u2705 Pattern deprecated successfully"));
5435
5795
  } else {
5436
- console.log(chalk15.red(`
5796
+ console.log(chalk16.red(`
5437
5797
  \u274C Failed: ${result.error}`));
5438
5798
  process.exit(1);
5439
5799
  }
@@ -5442,31 +5802,31 @@ async function learnStatsCommand() {
5442
5802
  const cwd = getWorkspacePath();
5443
5803
  const store = new PatternStore2(cwd);
5444
5804
  const telemetry = new TelemetryCollector2(cwd);
5445
- console.log(chalk15.cyan("\n\u{1F4CA} Learning Statistics\n"));
5805
+ console.log(chalk16.cyan("\n\u{1F4CA} Learning Statistics\n"));
5446
5806
  const storeStats = await store.getStats();
5447
5807
  const totalPatterns = storeStats.totalFixes + storeStats.totalBlueprints;
5448
5808
  const totalDeprecated = storeStats.deprecatedFixes + storeStats.deprecatedBlueprints;
5449
- console.log(chalk15.bold.white(" Patterns:\n"));
5450
- console.log(chalk15.dim(` Total: ${totalPatterns}`));
5451
- console.log(chalk15.dim(` Fix Patterns: ${storeStats.totalFixes}`));
5452
- console.log(chalk15.dim(` Blueprints: ${storeStats.totalBlueprints}`));
5453
- console.log(chalk15.dim(` Deprecated: ${totalDeprecated}`));
5809
+ console.log(chalk16.bold.white(" Patterns:\n"));
5810
+ console.log(chalk16.dim(` Total: ${totalPatterns}`));
5811
+ console.log(chalk16.dim(` Fix Patterns: ${storeStats.totalFixes}`));
5812
+ console.log(chalk16.dim(` Blueprints: ${storeStats.totalBlueprints}`));
5813
+ console.log(chalk16.dim(` Deprecated: ${totalDeprecated}`));
5454
5814
  const telemetryStats = await telemetry.getStats();
5455
- console.log(chalk15.bold.white("\n Telemetry:\n"));
5456
- console.log(chalk15.dim(` Pending Events: ${telemetryStats.pendingEvents}`));
5815
+ console.log(chalk16.bold.white("\n Telemetry:\n"));
5816
+ console.log(chalk16.dim(` Pending Events: ${telemetryStats.pendingEvents}`));
5457
5817
  console.log(
5458
- chalk15.dim(` Total Events Sent: ${telemetryStats.totalEventsSent}`)
5818
+ chalk16.dim(` Total Events Sent: ${telemetryStats.totalEventsSent}`)
5459
5819
  );
5460
5820
  if (telemetryStats.lastFlushAt) {
5461
5821
  console.log(
5462
- chalk15.dim(` Last Flush: ${formatDate(telemetryStats.lastFlushAt)}`)
5822
+ chalk16.dim(` Last Flush: ${formatDate(telemetryStats.lastFlushAt)}`)
5463
5823
  );
5464
5824
  }
5465
5825
  console.log("");
5466
5826
  }
5467
5827
 
5468
5828
  // src/cli/commands/solution.ts
5469
- import chalk16 from "chalk";
5829
+ import chalk17 from "chalk";
5470
5830
  import * as p12 from "@clack/prompts";
5471
5831
  import * as path2 from "path";
5472
5832
  import {
@@ -5509,7 +5869,7 @@ function truncate(str, maxLen) {
5509
5869
  async function solutionCaptureCommand(options) {
5510
5870
  const cwd = getWorkspacePath2();
5511
5871
  const store = new PatternStore3(cwd);
5512
- console.log(chalk16.cyan("\n\u{1F4E6} Capture Solution Pattern\n"));
5872
+ console.log(chalk17.cyan("\n\u{1F4E6} Capture Solution Pattern\n"));
5513
5873
  let targetPath = options.path;
5514
5874
  if (!targetPath) {
5515
5875
  const pathInput = await p12.text({
@@ -5617,22 +5977,22 @@ async function solutionCaptureCommand(options) {
5617
5977
  keywords
5618
5978
  );
5619
5979
  spinner10.stop("Solution analyzed");
5620
- console.log(chalk16.green("\n\u2713 Solution captured successfully!\n"));
5621
- console.log(chalk16.dim("\u2500".repeat(50)));
5622
- console.log(`${chalk16.bold("Name:")} ${pattern.name}`);
5980
+ console.log(chalk17.green("\n\u2713 Solution captured successfully!\n"));
5981
+ console.log(chalk17.dim("\u2500".repeat(50)));
5982
+ console.log(`${chalk17.bold("Name:")} ${pattern.name}`);
5623
5983
  console.log(
5624
- `${chalk16.bold("Category:")} ${formatCategory(pattern.category)}`
5984
+ `${chalk17.bold("Category:")} ${formatCategory(pattern.category)}`
5625
5985
  );
5626
5986
  console.log(
5627
- `${chalk16.bold("Files:")} ${pattern.implementation.files.length}`
5987
+ `${chalk17.bold("Files:")} ${pattern.implementation.files.length}`
5628
5988
  );
5629
5989
  console.log(
5630
- `${chalk16.bold("Dependencies:")} ${pattern.implementation.dependencies.length}`
5990
+ `${chalk17.bold("Dependencies:")} ${pattern.implementation.dependencies.length}`
5631
5991
  );
5632
5992
  console.log(
5633
- `${chalk16.bold("Framework:")} ${pattern.compatibility.framework || "generic"}`
5993
+ `${chalk17.bold("Framework:")} ${pattern.compatibility.framework || "generic"}`
5634
5994
  );
5635
- console.log(chalk16.dim("\u2500".repeat(50)));
5995
+ console.log(chalk17.dim("\u2500".repeat(50)));
5636
5996
  const confirm10 = await p12.confirm({
5637
5997
  message: "Save this solution pattern?",
5638
5998
  initialValue: true
@@ -5642,12 +6002,12 @@ async function solutionCaptureCommand(options) {
5642
6002
  process.exit(0);
5643
6003
  }
5644
6004
  await store.saveSolution(pattern);
5645
- console.log(chalk16.green(`
6005
+ console.log(chalk17.green(`
5646
6006
  \u2713 Solution saved with ID: ${pattern.id}
5647
6007
  `));
5648
6008
  } catch (error) {
5649
6009
  spinner10.stop("Analysis failed");
5650
- console.error(chalk16.red(`
6010
+ console.error(chalk17.red(`
5651
6011
  \u2717 Error: ${error.message}
5652
6012
  `));
5653
6013
  process.exit(1);
@@ -5656,7 +6016,7 @@ async function solutionCaptureCommand(options) {
5656
6016
  async function solutionSearchCommand(query, options) {
5657
6017
  const cwd = getWorkspacePath2();
5658
6018
  const store = new PatternStore3(cwd);
5659
- console.log(chalk16.cyan("\n\u{1F50D} Search Solution Patterns\n"));
6019
+ console.log(chalk17.cyan("\n\u{1F50D} Search Solution Patterns\n"));
5660
6020
  const keywords = query.split(/\s+/).filter((k) => k.length > 0);
5661
6021
  const result = await store.searchSolutions(keywords, {
5662
6022
  category: options.category,
@@ -5664,39 +6024,39 @@ async function solutionSearchCommand(query, options) {
5664
6024
  limit: options.limit ?? 10
5665
6025
  });
5666
6026
  if (!result.success || !result.data) {
5667
- console.error(chalk16.red(`
6027
+ console.error(chalk17.red(`
5668
6028
  \u2717 Search failed: ${result.error}
5669
6029
  `));
5670
6030
  return;
5671
6031
  }
5672
6032
  const solutions = result.data;
5673
6033
  if (solutions.length === 0) {
5674
- console.log(chalk16.yellow("No solutions found matching your query.\n"));
5675
- console.log(chalk16.dim("Try different keywords or fewer filters."));
6034
+ console.log(chalk17.yellow("No solutions found matching your query.\n"));
6035
+ console.log(chalk17.dim("Try different keywords or fewer filters."));
5676
6036
  return;
5677
6037
  }
5678
- console.log(chalk16.green(`Found ${solutions.length} solution(s):
6038
+ console.log(chalk17.green(`Found ${solutions.length} solution(s):
5679
6039
  `));
5680
- console.log(chalk16.dim("\u2500".repeat(70)));
6040
+ console.log(chalk17.dim("\u2500".repeat(70)));
5681
6041
  for (const solution of solutions) {
5682
6042
  console.log(
5683
- `${chalk16.bold(solution.name)} ${chalk16.dim(`(${solution.id.slice(0, 8)})`)}`
6043
+ `${chalk17.bold(solution.name)} ${chalk17.dim(`(${solution.id.slice(0, 8)})`)}`
5684
6044
  );
5685
6045
  console.log(` ${formatCategory(solution.category)}`);
5686
- console.log(` ${chalk16.dim(truncate(solution.description, 60))}`);
6046
+ console.log(` ${chalk17.dim(truncate(solution.description, 60))}`);
5687
6047
  console.log(
5688
6048
  ` Files: ${solution.implementation.files.length} | Framework: ${solution.compatibility.framework || "generic"} | Uses: ${solution.metrics.applications}`
5689
6049
  );
5690
- console.log(chalk16.dim("\u2500".repeat(70)));
6050
+ console.log(chalk17.dim("\u2500".repeat(70)));
5691
6051
  }
5692
6052
  console.log(
5693
- chalk16.dim("\nUse 'workflow solution:apply <id>' to apply a solution.")
6053
+ chalk17.dim("\nUse 'workflow solution:apply <id>' to apply a solution.")
5694
6054
  );
5695
6055
  }
5696
6056
  async function solutionListCommand(options) {
5697
6057
  const cwd = getWorkspacePath2();
5698
6058
  const store = new PatternStore3(cwd);
5699
- console.log(chalk16.cyan("\n\u{1F4CB} Solution Patterns\n"));
6059
+ console.log(chalk17.cyan("\n\u{1F4CB} Solution Patterns\n"));
5700
6060
  const result = await store.listSolutions({
5701
6061
  category: options.category,
5702
6062
  framework: options.framework,
@@ -5704,20 +6064,20 @@ async function solutionListCommand(options) {
5704
6064
  limit: options.limit ?? 20
5705
6065
  });
5706
6066
  if (!result.success || !result.data) {
5707
- console.error(chalk16.red(`
6067
+ console.error(chalk17.red(`
5708
6068
  \u2717 List failed: ${result.error}
5709
6069
  `));
5710
6070
  return;
5711
6071
  }
5712
6072
  const solutions = result.data;
5713
6073
  if (solutions.length === 0) {
5714
- console.log(chalk16.yellow("No solutions found.\n"));
6074
+ console.log(chalk17.yellow("No solutions found.\n"));
5715
6075
  console.log(
5716
- chalk16.dim("Use 'workflow solution:capture' to capture a solution.")
6076
+ chalk17.dim("Use 'workflow solution:capture' to capture a solution.")
5717
6077
  );
5718
6078
  return;
5719
6079
  }
5720
- console.log(chalk16.green(`${solutions.length} solution(s):
6080
+ console.log(chalk17.green(`${solutions.length} solution(s):
5721
6081
  `));
5722
6082
  const byCategory = /* @__PURE__ */ new Map();
5723
6083
  for (const solution of solutions) {
@@ -5726,24 +6086,24 @@ async function solutionListCommand(options) {
5726
6086
  byCategory.set(solution.category, list);
5727
6087
  }
5728
6088
  for (const [category, items] of byCategory) {
5729
- console.log(chalk16.bold(`
6089
+ console.log(chalk17.bold(`
5730
6090
  ${formatCategory(category)}`));
5731
- console.log(chalk16.dim("\u2500".repeat(50)));
6091
+ console.log(chalk17.dim("\u2500".repeat(50)));
5732
6092
  for (const solution of items) {
5733
- const deprecated = solution.deprecatedAt ? chalk16.red(" [DEPRECATED]") : "";
6093
+ const deprecated = solution.deprecatedAt ? chalk17.red(" [DEPRECATED]") : "";
5734
6094
  console.log(
5735
- ` ${chalk16.cyan(solution.id.slice(0, 8))} ${solution.name}${deprecated}`
6095
+ ` ${chalk17.cyan(solution.id.slice(0, 8))} ${solution.name}${deprecated}`
5736
6096
  );
5737
- console.log(` ${chalk16.dim(truncate(solution.description, 50))}`);
6097
+ console.log(` ${chalk17.dim(truncate(solution.description, 50))}`);
5738
6098
  console.log(
5739
- chalk16.dim(
6099
+ chalk17.dim(
5740
6100
  ` Created: ${formatDate2(solution.createdAt)} | Files: ${solution.implementation.files.length}`
5741
6101
  )
5742
6102
  );
5743
6103
  }
5744
6104
  }
5745
6105
  console.log(
5746
- chalk16.dim(
6106
+ chalk17.dim(
5747
6107
  "\nUse 'workflow solution:search <query>' to find specific solutions."
5748
6108
  )
5749
6109
  );
@@ -5751,10 +6111,10 @@ ${formatCategory(category)}`));
5751
6111
  async function solutionApplyCommand(solutionId, options) {
5752
6112
  const cwd = getWorkspacePath2();
5753
6113
  const store = new PatternStore3(cwd);
5754
- console.log(chalk16.cyan("\n\u{1F680} Apply Solution Pattern\n"));
6114
+ console.log(chalk17.cyan("\n\u{1F680} Apply Solution Pattern\n"));
5755
6115
  const result = await store.getSolution(solutionId);
5756
6116
  if (!result.success || !result.data) {
5757
- console.error(chalk16.red(`
6117
+ console.error(chalk17.red(`
5758
6118
  \u2717 Solution not found: ${solutionId}
5759
6119
  `));
5760
6120
  process.exit(1);
@@ -5762,7 +6122,7 @@ async function solutionApplyCommand(solutionId, options) {
5762
6122
  const solution = result.data;
5763
6123
  if (solution.deprecatedAt) {
5764
6124
  console.log(
5765
- chalk16.yellow(
6125
+ chalk17.yellow(
5766
6126
  `\u26A0\uFE0F This solution is deprecated: ${solution.deprecationReason || "No reason provided"}
5767
6127
  `
5768
6128
  )
@@ -5776,34 +6136,34 @@ async function solutionApplyCommand(solutionId, options) {
5776
6136
  process.exit(0);
5777
6137
  }
5778
6138
  }
5779
- console.log(chalk16.bold(`Solution: ${solution.name}`));
5780
- console.log(chalk16.dim(solution.description));
6139
+ console.log(chalk17.bold(`Solution: ${solution.name}`));
6140
+ console.log(chalk17.dim(solution.description));
5781
6141
  console.log();
5782
- console.log(chalk16.bold("Files to create:"));
6142
+ console.log(chalk17.bold("Files to create:"));
5783
6143
  const filesToApply = options.includeTests ? solution.implementation.files : solution.implementation.files.filter(
5784
6144
  (f) => f.role !== "test"
5785
6145
  );
5786
6146
  for (const file of filesToApply) {
5787
- console.log(chalk16.dim(` \u2022 ${file.path} (${file.role})`));
6147
+ console.log(chalk17.dim(` \u2022 ${file.path} (${file.role})`));
5788
6148
  }
5789
6149
  console.log();
5790
6150
  if (solution.implementation.dependencies.length > 0) {
5791
- console.log(chalk16.bold("Dependencies to install:"));
6151
+ console.log(chalk17.bold("Dependencies to install:"));
5792
6152
  for (const dep of solution.implementation.dependencies) {
5793
- console.log(chalk16.dim(` \u2022 ${dep.name}@${dep.version}`));
6153
+ console.log(chalk17.dim(` \u2022 ${dep.name}@${dep.version}`));
5794
6154
  }
5795
6155
  console.log();
5796
6156
  }
5797
6157
  if (solution.implementation.envVars.length > 0) {
5798
- console.log(chalk16.bold("Environment variables needed:"));
6158
+ console.log(chalk17.bold("Environment variables needed:"));
5799
6159
  for (const env of solution.implementation.envVars) {
5800
- const required = env.required ? chalk16.red("*") : "";
5801
- console.log(chalk16.dim(` \u2022 ${env.name}${required}`));
6160
+ const required = env.required ? chalk17.red("*") : "";
6161
+ console.log(chalk17.dim(` \u2022 ${env.name}${required}`));
5802
6162
  }
5803
6163
  console.log();
5804
6164
  }
5805
6165
  if (options.dryRun) {
5806
- console.log(chalk16.yellow("Dry run mode - no files were created.\n"));
6166
+ console.log(chalk17.yellow("Dry run mode - no files were created.\n"));
5807
6167
  return;
5808
6168
  }
5809
6169
  const confirm10 = await p12.confirm({
@@ -5828,19 +6188,19 @@ async function solutionApplyCommand(solutionId, options) {
5828
6188
  }
5829
6189
  await store.updateSolutionMetrics(solution.id, true);
5830
6190
  spinner10.stop("Solution applied");
5831
- console.log(chalk16.green(`
6191
+ console.log(chalk17.green(`
5832
6192
  \u2713 Solution applied successfully!
5833
6193
  `));
5834
- console.log(chalk16.dim(`Created ${filesToApply.length} file(s).`));
6194
+ console.log(chalk17.dim(`Created ${filesToApply.length} file(s).`));
5835
6195
  if (solution.implementation.dependencies.length > 0) {
5836
- console.log(chalk16.cyan("\nNext step: Install dependencies with:"));
6196
+ console.log(chalk17.cyan("\nNext step: Install dependencies with:"));
5837
6197
  const deps = solution.implementation.dependencies.map((d) => `${d.name}@${d.version}`).join(" ");
5838
- console.log(chalk16.dim(` npm install ${deps}`));
6198
+ console.log(chalk17.dim(` npm install ${deps}`));
5839
6199
  }
5840
6200
  } catch (error) {
5841
6201
  spinner10.stop("Application failed");
5842
6202
  await store.updateSolutionMetrics(solution.id, false);
5843
- console.error(chalk16.red(`
6203
+ console.error(chalk17.red(`
5844
6204
  \u2717 Error: ${error.message}
5845
6205
  `));
5846
6206
  process.exit(1);
@@ -5849,16 +6209,16 @@ async function solutionApplyCommand(solutionId, options) {
5849
6209
  async function solutionDeprecateCommand(solutionId, reason) {
5850
6210
  const cwd = getWorkspacePath2();
5851
6211
  const store = new PatternStore3(cwd);
5852
- console.log(chalk16.cyan("\n\u26A0\uFE0F Deprecate Solution Pattern\n"));
6212
+ console.log(chalk17.cyan("\n\u26A0\uFE0F Deprecate Solution Pattern\n"));
5853
6213
  const result = await store.getSolution(solutionId);
5854
6214
  if (!result.success || !result.data) {
5855
- console.error(chalk16.red(`
6215
+ console.error(chalk17.red(`
5856
6216
  \u2717 Solution not found: ${solutionId}
5857
6217
  `));
5858
6218
  process.exit(1);
5859
6219
  }
5860
6220
  const solution = result.data;
5861
- console.log(`Solution: ${chalk16.bold(solution.name)}`);
6221
+ console.log(`Solution: ${chalk17.bold(solution.name)}`);
5862
6222
  console.log(`Reason: ${reason}
5863
6223
  `);
5864
6224
  const confirm10 = await p12.confirm({
@@ -5870,27 +6230,27 @@ async function solutionDeprecateCommand(solutionId, reason) {
5870
6230
  process.exit(0);
5871
6231
  }
5872
6232
  await store.deprecateSolution(solutionId, reason);
5873
- console.log(chalk16.green(`
6233
+ console.log(chalk17.green(`
5874
6234
  \u2713 Solution deprecated.
5875
6235
  `));
5876
6236
  }
5877
6237
  async function solutionStatsCommand() {
5878
6238
  const cwd = getWorkspacePath2();
5879
6239
  const store = new PatternStore3(cwd);
5880
- console.log(chalk16.cyan("\n\u{1F4CA} Solution Pattern Statistics\n"));
6240
+ console.log(chalk17.cyan("\n\u{1F4CA} Solution Pattern Statistics\n"));
5881
6241
  const stats = await store.getStats();
5882
- console.log(chalk16.dim("\u2500".repeat(40)));
5883
- console.log(`${chalk16.bold("Solutions:")} ${stats.totalSolutions}`);
6242
+ console.log(chalk17.dim("\u2500".repeat(40)));
6243
+ console.log(`${chalk17.bold("Solutions:")} ${stats.totalSolutions}`);
5884
6244
  console.log(` Active: ${stats.totalSolutions - stats.deprecatedSolutions}`);
5885
6245
  console.log(` Deprecated: ${stats.deprecatedSolutions}`);
5886
6246
  console.log(` Private: ${stats.privateSolutions}`);
5887
6247
  console.log(` Synced: ${stats.syncedSolutions}`);
5888
- console.log(chalk16.dim("\u2500".repeat(40)));
5889
- console.log(`${chalk16.bold("Fixes:")} ${stats.totalFixes}`);
5890
- console.log(`${chalk16.bold("Blueprints:")} ${stats.totalBlueprints}`);
5891
- console.log(chalk16.dim("\u2500".repeat(40)));
6248
+ console.log(chalk17.dim("\u2500".repeat(40)));
6249
+ console.log(`${chalk17.bold("Fixes:")} ${stats.totalFixes}`);
6250
+ console.log(`${chalk17.bold("Blueprints:")} ${stats.totalBlueprints}`);
6251
+ console.log(chalk17.dim("\u2500".repeat(40)));
5892
6252
  console.log(`
5893
- ${chalk16.bold("By Category:")}`);
6253
+ ${chalk17.bold("By Category:")}`);
5894
6254
  const listResult = await store.listSolutions({ limit: 1e3 });
5895
6255
  if (listResult.success && listResult.data) {
5896
6256
  const categories = /* @__PURE__ */ new Map();
@@ -5926,7 +6286,8 @@ program.command("suggest").description("Submit an improvement suggestion").argum
5926
6286
  "Category: feature, bug, documentation, performance, other"
5927
6287
  ).action(suggestCommand);
5928
6288
  program.command("setup").description("Add workflow scripts to package.json").action(setupCommand);
5929
- program.command("doctor").description("Run health check and get optimization suggestions").action(doctorCommand);
6289
+ program.command("doctor").description("Run health check and get optimization suggestions").option("--check-guidelines-only", "Only check guidelines presence").action(doctorCommand);
6290
+ program.command("hooks <action>").description("Manage git hooks").action(hooksCommand);
5930
6291
  program.command("scope:create").description("Create a custom scope package").option("--name <name>", 'Package name (e.g., "fintech", "gaming")').option(
5931
6292
  "--scopes <scopes>",
5932
6293
  "Comma-separated scopes (format: name:description:emoji:category)"