workflow-agent-cli 2.0.1 → 2.2.0

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
@@ -3,15 +3,18 @@ import {
3
3
  validateBranchName,
4
4
  validateCommitMessage,
5
5
  validatePRTitle
6
- } from "../chunk-X2NQJ2ZY.js";
6
+ } from "../chunk-NMHWD2GA.js";
7
7
  import {
8
+ DEFAULT_RESERVED_SCOPE_NAMES,
8
9
  hasConfig,
9
10
  loadConfig,
10
- validateScopeDefinitions
11
- } from "../chunk-4BIDFDSR.js";
11
+ validateConfig,
12
+ validateScopeDefinitions,
13
+ validateScopeName
14
+ } from "../chunk-IPMSSOXR.js";
12
15
 
13
16
  // src/cli/index.ts
14
- import { Command } from "commander";
17
+ import { Command as Command2 } from "commander";
15
18
 
16
19
  // src/cli/commands/init.ts
17
20
  import * as p from "@clack/prompts";
@@ -76,7 +79,7 @@ var adapters = {
76
79
  config: "src"
77
80
  }
78
81
  },
79
- "remix": {
82
+ remix: {
80
83
  name: "Remix",
81
84
  description: "Remix full-stack framework",
82
85
  detect: async () => {
@@ -91,7 +94,7 @@ var adapters = {
91
94
  config: "app/root.tsx"
92
95
  }
93
96
  },
94
- "astro": {
97
+ astro: {
95
98
  name: "Astro",
96
99
  description: "Astro static site framework",
97
100
  detect: async () => {
@@ -106,7 +109,7 @@ var adapters = {
106
109
  config: "src/pages"
107
110
  }
108
111
  },
109
- "sveltekit": {
112
+ sveltekit: {
110
113
  name: "SvelteKit",
111
114
  description: "SvelteKit full-stack framework",
112
115
  detect: async () => {
@@ -121,7 +124,7 @@ var adapters = {
121
124
  config: "src/routes"
122
125
  }
123
126
  },
124
- "generic": {
127
+ generic: {
125
128
  name: "Generic Project",
126
129
  description: "Standard project structure",
127
130
  detect: async () => true,
@@ -207,7 +210,9 @@ async function validateTemplateDirectory(templateDir) {
207
210
  const files = await fs.readdir(templateDir);
208
211
  const templateFiles = files.filter((f) => f.match(/\.(md|ts|json)$/));
209
212
  if (templateFiles.length === 0) {
210
- throw new Error(`No template files found in template directory: ${templateDir}`);
213
+ throw new Error(
214
+ `No template files found in template directory: ${templateDir}`
215
+ );
211
216
  }
212
217
  } catch (error) {
213
218
  if (error.code === "ENOENT") {
@@ -346,6 +351,8 @@ function generatePreCommitHook(config) {
346
351
  return " workflow validate commit";
347
352
  case "check-guidelines":
348
353
  return " workflow doctor --check-guidelines-only 2>/dev/null || true";
354
+ case "validate-scopes":
355
+ return " workflow config validate";
349
356
  default:
350
357
  return "";
351
358
  }
@@ -465,12 +472,14 @@ async function installSingleHook(hookType, config, projectPath = process.cwd())
465
472
  }
466
473
  async function installHooks(config, projectPath = process.cwd()) {
467
474
  if (!hasGitRepo(projectPath)) {
468
- return [{
469
- success: false,
470
- hookType: "pre-commit",
471
- wrappedExisting: false,
472
- error: "No git repository found. Run git init first."
473
- }];
475
+ return [
476
+ {
477
+ success: false,
478
+ hookType: "pre-commit",
479
+ wrappedExisting: false,
480
+ error: "No git repository found. Run git init first."
481
+ }
482
+ ];
474
483
  }
475
484
  const results = await Promise.all([
476
485
  installSingleHook("pre-commit", config, projectPath),
@@ -530,7 +539,9 @@ async function isGitRepo(projectPath = process.cwd()) {
530
539
  }
531
540
  async function getGitRemoteUrl(projectPath = process.cwd()) {
532
541
  try {
533
- const { stdout } = await execa("git", ["remote", "get-url", "origin"], { cwd: projectPath });
542
+ const { stdout } = await execa("git", ["remote", "get-url", "origin"], {
543
+ cwd: projectPath
544
+ });
534
545
  return stdout.trim() || null;
535
546
  } catch {
536
547
  return null;
@@ -553,15 +564,23 @@ function parseGitHubUrl(remoteUrl) {
553
564
  }
554
565
  async function getDefaultBranch(projectPath = process.cwd()) {
555
566
  try {
556
- const { stdout } = await execa("git", ["symbolic-ref", "refs/remotes/origin/HEAD"], {
557
- cwd: projectPath
558
- });
567
+ const { stdout } = await execa(
568
+ "git",
569
+ ["symbolic-ref", "refs/remotes/origin/HEAD"],
570
+ {
571
+ cwd: projectPath
572
+ }
573
+ );
559
574
  return stdout.trim().replace("refs/remotes/origin/", "") || "main";
560
575
  } catch {
561
576
  try {
562
- const { stdout } = await execa("git", ["rev-parse", "--abbrev-ref", "HEAD"], {
563
- cwd: projectPath
564
- });
577
+ const { stdout } = await execa(
578
+ "git",
579
+ ["rev-parse", "--abbrev-ref", "HEAD"],
580
+ {
581
+ cwd: projectPath
582
+ }
583
+ );
565
584
  return stdout.trim() || "main";
566
585
  } catch {
567
586
  return "main";
@@ -753,7 +772,11 @@ function generateCIWorkflowContent(options) {
753
772
  }
754
773
  if (checks.includes("typecheck")) {
755
774
  if (hasTypecheckScript) {
756
- const typecheckCmd = getRunCommand(packageManager, "typecheck", isMonorepo2);
775
+ const typecheckCmd = getRunCommand(
776
+ packageManager,
777
+ "typecheck",
778
+ isMonorepo2
779
+ );
757
780
  steps.push(`
758
781
  - name: Type check
759
782
  run: ${typecheckCmd}`);
@@ -765,7 +788,11 @@ function generateCIWorkflowContent(options) {
765
788
  }
766
789
  if (checks.includes("format")) {
767
790
  if (hasFormatScript) {
768
- const formatCmd = getRunCommand(packageManager, "format:check", isMonorepo2);
791
+ const formatCmd = getRunCommand(
792
+ packageManager,
793
+ "format:check",
794
+ isMonorepo2
795
+ );
769
796
  steps.push(`
770
797
  - name: Format check
771
798
  run: ${formatCmd} || npx prettier --check "**/*.{ts,tsx,js,jsx,json,md}"`);
@@ -839,7 +866,13 @@ async function createCIWorkflow(options = {}) {
839
866
  const projectInfo = await getProjectInfo(projectPath);
840
867
  const packageManager = options.packageManager || projectInfo.packageManager;
841
868
  const isMonorepo2 = options.isMonorepo ?? projectInfo.isMonorepo;
842
- const checks = options.ciConfig?.checks || ["lint", "typecheck", "format", "build", "test"];
869
+ const checks = options.ciConfig?.checks || [
870
+ "lint",
871
+ "typecheck",
872
+ "format",
873
+ "build",
874
+ "test"
875
+ ];
843
876
  const nodeVersions = options.nodeVersions || ["20"];
844
877
  const defaultBranch = options.defaultBranch || "main";
845
878
  if (!existsSync3(workflowsDir)) {
@@ -899,12 +932,30 @@ async function initCommand(options) {
899
932
  const preset = isNonInteractive ? options.preset : await p.select({
900
933
  message: "Choose a scope preset for your project:",
901
934
  options: [
902
- { value: "saas", label: "\u{1F4E6} SaaS Application - 17 scopes (auth, tasks, boards, sprints, etc.)" },
903
- { value: "library", label: "\u{1F4DA} Library/Package - 10 scopes (types, build, docs, examples, etc.)" },
904
- { value: "api", label: "\u{1F50C} API/Backend - 13 scopes (auth, endpoints, models, services, etc.)" },
905
- { value: "ecommerce", label: "\u{1F6D2} E-commerce - 12 scopes (cart, products, payments, orders, etc.)" },
906
- { value: "cms", label: "\u{1F4DD} CMS - 13 scopes (content, pages, media, editor, etc.)" },
907
- { value: "custom", label: "\u2728 Custom (define your own scopes manually)" }
935
+ {
936
+ value: "saas",
937
+ label: "\u{1F4E6} SaaS Application - 17 scopes (auth, tasks, boards, sprints, etc.)"
938
+ },
939
+ {
940
+ value: "library",
941
+ label: "\u{1F4DA} Library/Package - 10 scopes (types, build, docs, examples, etc.)"
942
+ },
943
+ {
944
+ value: "api",
945
+ label: "\u{1F50C} API/Backend - 13 scopes (auth, endpoints, models, services, etc.)"
946
+ },
947
+ {
948
+ value: "ecommerce",
949
+ label: "\u{1F6D2} E-commerce - 12 scopes (cart, products, payments, orders, etc.)"
950
+ },
951
+ {
952
+ value: "cms",
953
+ label: "\u{1F4DD} CMS - 13 scopes (content, pages, media, editor, etc.)"
954
+ },
955
+ {
956
+ value: "custom",
957
+ label: "\u2728 Custom (define your own scopes manually)"
958
+ }
908
959
  ]
909
960
  });
910
961
  if (!isNonInteractive && p.isCancel(preset)) {
@@ -921,27 +972,62 @@ async function initCommand(options) {
921
972
  await new Promise((resolve) => setTimeout(resolve, 500));
922
973
  spinner5.stop(`\u2713 Loaded ${scopes.length} scopes from preset`);
923
974
  } catch (error) {
924
- console.log(chalk.yellow(`
925
- \u26A0\uFE0F Could not load preset package. Using basic scopes.`));
975
+ console.log(
976
+ chalk.yellow(
977
+ `
978
+ \u26A0\uFE0F Could not load preset package. Using basic scopes.`
979
+ )
980
+ );
926
981
  scopes = [
927
- { name: "feat", description: "New features and enhancements", emoji: "\u2728" },
982
+ {
983
+ name: "feat",
984
+ description: "New features and enhancements",
985
+ emoji: "\u2728"
986
+ },
928
987
  { name: "fix", description: "Bug fixes and patches", emoji: "\u{1F41B}" },
929
- { name: "documentation", description: "Documentation updates and improvements", emoji: "\u{1F4DA}" }
988
+ {
989
+ name: "documentation",
990
+ description: "Documentation updates and improvements",
991
+ emoji: "\u{1F4DA}"
992
+ }
930
993
  ];
931
994
  }
932
995
  } else {
933
996
  scopes = [
934
- { name: "feat", description: "New features and enhancements", emoji: "\u2728" },
997
+ {
998
+ name: "feat",
999
+ description: "New features and enhancements",
1000
+ emoji: "\u2728"
1001
+ },
935
1002
  { name: "fix", description: "Bug fixes and patches", emoji: "\u{1F41B}" },
936
- { name: "documentation", description: "Documentation updates and improvements", emoji: "\u{1F4DA}" }
1003
+ {
1004
+ name: "documentation",
1005
+ description: "Documentation updates and improvements",
1006
+ emoji: "\u{1F4DA}"
1007
+ }
937
1008
  ];
938
- console.log(chalk.dim("\n\u{1F4A1} Tip: Edit workflow.config.json to add your custom scopes"));
1009
+ console.log(
1010
+ chalk.dim(
1011
+ "\n\u{1F4A1} Tip: Edit workflow.config.json to add your custom scopes"
1012
+ )
1013
+ );
939
1014
  }
940
1015
  const config = {
941
1016
  projectName,
942
1017
  scopes,
943
1018
  enforcement: "strict",
944
- language: "en"
1019
+ language: "en",
1020
+ hooks: {
1021
+ enabled: true,
1022
+ preCommit: ["validate-branch", "check-guidelines"],
1023
+ commitMsg: ["validate-commit"]
1024
+ },
1025
+ ci: {
1026
+ enabled: true,
1027
+ provider: "github",
1028
+ checks: ["lint", "typecheck", "format", "build", "test"]
1029
+ },
1030
+ reservedScopeNames: DEFAULT_RESERVED_SCOPE_NAMES
945
1031
  };
946
1032
  const configPath = join4(cwd, "workflow.config.json");
947
1033
  await writeFile3(configPath, JSON.stringify(config, null, 2));
@@ -953,8 +1039,12 @@ async function initCommand(options) {
953
1039
  const projectInfo = await getProjectInfo(cwd);
954
1040
  const mandatoryTemplates = getMandatoryTemplates();
955
1041
  const optionalTemplates = getOptionalTemplates();
956
- console.log(chalk.dim(`
957
- \u{1F4CB} Generating ${mandatoryTemplates.length} mandatory guidelines...`));
1042
+ console.log(
1043
+ chalk.dim(
1044
+ `
1045
+ \u{1F4CB} Generating ${mandatoryTemplates.length} mandatory guidelines...`
1046
+ )
1047
+ );
958
1048
  const guidelinesDir = join4(cwd, "guidelines");
959
1049
  const templatesDir = join4(__dirname, "../../templates");
960
1050
  let mandatoryGenerated = 0;
@@ -967,13 +1057,20 @@ async function initCommand(options) {
967
1057
  try {
968
1058
  const templatePath = join4(templatesDir, template.filename);
969
1059
  const outputPath = join4(guidelinesDir, template.filename);
970
- await renderTemplateFile(templatePath, outputPath, context);
1060
+ await renderTemplateFile(templatePath, outputPath, {
1061
+ ...context,
1062
+ reservedScopeNames: (config.reservedScopeNames || []).join(", ")
1063
+ });
971
1064
  mandatoryGenerated++;
972
1065
  } catch (error) {
973
- console.log(chalk.yellow(` \u26A0\uFE0F Could not generate ${template.filename}`));
1066
+ console.log(
1067
+ chalk.yellow(` \u26A0\uFE0F Could not generate ${template.filename}`)
1068
+ );
974
1069
  }
975
1070
  }
976
- console.log(chalk.green(`\u2713 Generated ${mandatoryGenerated} mandatory guidelines`));
1071
+ console.log(
1072
+ chalk.green(`\u2713 Generated ${mandatoryGenerated} mandatory guidelines`)
1073
+ );
977
1074
  let shouldGenerateOptional = isNonInteractive;
978
1075
  if (!isNonInteractive) {
979
1076
  const response = await p.confirm({
@@ -992,11 +1089,17 @@ async function initCommand(options) {
992
1089
  } catch {
993
1090
  }
994
1091
  }
995
- console.log(chalk.green(`\u2713 Generated ${optionalGenerated} optional guidelines`));
1092
+ console.log(
1093
+ chalk.green(`\u2713 Generated ${optionalGenerated} optional guidelines`)
1094
+ );
996
1095
  }
997
1096
  } catch (error) {
998
- console.log(chalk.yellow(`
999
- \u26A0\uFE0F Could not generate guidelines: ${error instanceof Error ? error.message : String(error)}`));
1097
+ console.log(
1098
+ chalk.yellow(
1099
+ `
1100
+ \u26A0\uFE0F Could not generate guidelines: ${error instanceof Error ? error.message : String(error)}`
1101
+ )
1102
+ );
1000
1103
  console.log(chalk.dim("You can manually copy guidelines later if needed."));
1001
1104
  }
1002
1105
  if (hasGitRepo(cwd)) {
@@ -1011,7 +1114,14 @@ async function initCommand(options) {
1011
1114
  if (shouldInstallHooks) {
1012
1115
  const hookSpinner = p.spinner();
1013
1116
  hookSpinner.start("Installing git hooks...");
1014
- const hookResults = await installHooks(config.hooks, cwd);
1117
+ const hookResults = await installHooks(
1118
+ config.hooks || {
1119
+ enabled: true,
1120
+ preCommit: ["validate-branch", "check-guidelines"],
1121
+ commitMsg: ["validate-commit"]
1122
+ },
1123
+ cwd
1124
+ );
1015
1125
  const allSuccess = hookResults.every((r) => r.success);
1016
1126
  if (allSuccess) {
1017
1127
  hookSpinner.stop("\u2713 Installed git hooks");
@@ -1023,19 +1133,29 @@ async function initCommand(options) {
1023
1133
  if (repoInfo.isGitHub) {
1024
1134
  const existingCI = hasCIWorkflow(cwd);
1025
1135
  if (!existingCI) {
1026
- console.log(chalk.dim("\n\u{1F527} Setting up GitHub Actions CI (mandatory for GitHub repos)..."));
1136
+ console.log(
1137
+ chalk.dim(
1138
+ "\n\u{1F527} Setting up GitHub Actions CI (mandatory for GitHub repos)..."
1139
+ )
1140
+ );
1027
1141
  const ciResult = await createCIWorkflow({
1028
1142
  projectPath: cwd,
1029
1143
  packageManager: projectInfo.packageManager,
1030
1144
  isMonorepo: projectInfo.isMonorepo,
1031
- ciConfig: config.ci,
1145
+ ciConfig: config.ci || {
1146
+ enabled: true,
1147
+ provider: "github",
1148
+ checks: ["lint", "typecheck", "format", "build", "test"]
1149
+ },
1032
1150
  defaultBranch: repoInfo.defaultBranch || "main"
1033
1151
  });
1034
1152
  if (ciResult.success) {
1035
1153
  console.log(chalk.green("\u2713 Created GitHub Actions CI workflow"));
1036
1154
  console.log(chalk.dim(` File: .github/workflows/ci.yml`));
1037
1155
  } else {
1038
- console.log(chalk.yellow(`\u26A0\uFE0F Could not create CI workflow: ${ciResult.error}`));
1156
+ console.log(
1157
+ chalk.yellow(`\u26A0\uFE0F Could not create CI workflow: ${ciResult.error}`)
1158
+ );
1039
1159
  }
1040
1160
  } else {
1041
1161
  console.log(chalk.dim("\n\u2713 GitHub Actions CI workflow already exists"));
@@ -1063,13 +1183,21 @@ async function initCommand(options) {
1063
1183
  }
1064
1184
  p.outro(chalk.green("\u2713 Workflow Agent initialized successfully!"));
1065
1185
  console.log(chalk.dim("\nNext steps:"));
1066
- console.log(chalk.dim(" 1. Review your configuration in workflow.config.json"));
1067
- console.log(chalk.dim(" 2. Review generated guidelines in guidelines/ directory"));
1186
+ console.log(
1187
+ chalk.dim(" 1. Review your configuration in workflow.config.json")
1188
+ );
1189
+ console.log(
1190
+ chalk.dim(" 2. Review generated guidelines in guidelines/ directory")
1191
+ );
1068
1192
  console.log(chalk.dim(" 3. Run: workflow validate branch"));
1069
1193
  console.log(chalk.dim(" 4. Run: workflow doctor (for health check)\n"));
1070
1194
  if (repoInfo.isGitHub) {
1071
- console.log(chalk.cyan("\u{1F4A1} Recommended: Enable branch protection on GitHub"));
1072
- console.log(chalk.dim(" Settings \u2192 Branches \u2192 Add rule \u2192 Require status checks\n"));
1195
+ console.log(
1196
+ chalk.cyan("\u{1F4A1} Recommended: Enable branch protection on GitHub")
1197
+ );
1198
+ console.log(
1199
+ chalk.dim(" Settings \u2192 Branches \u2192 Add rule \u2192 Require status checks\n")
1200
+ );
1073
1201
  }
1074
1202
  }
1075
1203
 
@@ -1079,7 +1207,9 @@ import { execa as execa2 } from "execa";
1079
1207
  async function validateCommand(type, value, _options = {}) {
1080
1208
  const config = await loadConfig();
1081
1209
  if (!config) {
1082
- console.error(chalk2.red("\u2717 No workflow configuration found. Run: workflow init"));
1210
+ console.error(
1211
+ chalk2.red("\u2717 No workflow configuration found. Run: workflow init")
1212
+ );
1083
1213
  process.exit(1);
1084
1214
  }
1085
1215
  let targetValue = value;
@@ -1129,8 +1259,12 @@ async function validateCommand(type, value, _options = {}) {
1129
1259
  if (enforcementLevel === "strict") {
1130
1260
  process.exit(1);
1131
1261
  } else {
1132
- console.log(chalk2.yellow(`
1133
- \u26A0\uFE0F Advisory mode: validation failed but not blocking`));
1262
+ console.log(
1263
+ chalk2.yellow(
1264
+ `
1265
+ \u26A0\uFE0F Advisory mode: validation failed but not blocking`
1266
+ )
1267
+ );
1134
1268
  process.exit(0);
1135
1269
  }
1136
1270
  }
@@ -1141,10 +1275,324 @@ async function validateCommand(type, value, _options = {}) {
1141
1275
  }
1142
1276
 
1143
1277
  // src/cli/commands/config.ts
1278
+ import { Command } from "commander";
1279
+ import { join as join5 } from "path";
1280
+ import { existsSync as existsSync5, writeFileSync } from "fs";
1281
+ import prompts from "prompts";
1144
1282
  import chalk3 from "chalk";
1145
- async function configCommand(action, key, value) {
1146
- console.log(chalk3.yellow("Config command not yet implemented"));
1147
- console.log({ action, key, value });
1283
+ function createConfigCommand() {
1284
+ const command = new Command("config").description("Manage workflow configuration").option("-f, --force", "Skip validation checks").option("--cwd <path>", "Working directory", process.cwd());
1285
+ command.command("validate").description("Validate workflow configuration").action(async () => {
1286
+ const opts = command.opts();
1287
+ await validateConfigAction(opts);
1288
+ });
1289
+ command.command("add").description("Add configuration items").argument("<type>", "Type to add (scope)").action(async (type) => {
1290
+ const opts = command.opts();
1291
+ if (type === "scope") {
1292
+ await addScopeAction(opts);
1293
+ } else {
1294
+ console.error(
1295
+ chalk3.red(
1296
+ `Unknown type: ${type}. Currently only "scope" is supported.`
1297
+ )
1298
+ );
1299
+ process.exit(1);
1300
+ }
1301
+ });
1302
+ command.command("remove").description("Remove configuration items").argument("<type>", "Type to remove (scope)").argument("<name>", "Name of the item to remove").action(async (type, name) => {
1303
+ const opts = command.opts();
1304
+ if (type === "scope") {
1305
+ await removeScopeAction(name, opts);
1306
+ } else {
1307
+ console.error(
1308
+ chalk3.red(
1309
+ `Unknown type: ${type}. Currently only "scope" is supported.`
1310
+ )
1311
+ );
1312
+ process.exit(1);
1313
+ }
1314
+ });
1315
+ command.command("list").description("List configuration items").argument("[type]", "Type to list (scopes, reserved, all)", "all").action(async (type) => {
1316
+ const opts = command.opts();
1317
+ await listConfigAction(type, opts);
1318
+ });
1319
+ command.command("get").description("Get a configuration value").argument("<path>", "Configuration path (e.g., scopes[0].name)").action(async (path2) => {
1320
+ const opts = command.opts();
1321
+ await getConfigValue(path2, opts);
1322
+ });
1323
+ command.command("set").description("Set a configuration value").argument("<path>", "Configuration path (e.g., reservedScopeNames)").argument("<value>", "Value to set").action(async (path2, value) => {
1324
+ const opts = command.opts();
1325
+ await setConfigValue(path2, value, opts);
1326
+ });
1327
+ return command;
1328
+ }
1329
+ async function validateConfigAction(opts) {
1330
+ console.log(chalk3.blue("\u{1F50D} Validating workflow configuration..."));
1331
+ const result = await validateConfig(opts.cwd || process.cwd());
1332
+ if (result.valid) {
1333
+ console.log(chalk3.green("\u2713 Configuration is valid"));
1334
+ process.exit(0);
1335
+ } else {
1336
+ console.log(chalk3.red("\u2717 Configuration has errors:\n"));
1337
+ result.errors.forEach((err) => {
1338
+ console.log(chalk3.red(` \u2022 ${err}`));
1339
+ });
1340
+ if (result.warnings.length > 0) {
1341
+ console.log(chalk3.yellow("\n\u26A0 Warnings:\n"));
1342
+ result.warnings.forEach((warn) => {
1343
+ console.log(chalk3.yellow(` \u2022 ${warn}`));
1344
+ });
1345
+ }
1346
+ console.log(chalk3.gray("\n\u{1F4A1} Fix these issues in workflow.config.json"));
1347
+ process.exit(1);
1348
+ }
1349
+ }
1350
+ async function addScopeAction(opts) {
1351
+ const cwd = opts.cwd || process.cwd();
1352
+ const configPath = join5(cwd, "workflow.config.json");
1353
+ if (!existsSync5(configPath)) {
1354
+ console.error(
1355
+ chalk3.red("No workflow.config.json found. Run: workflow init")
1356
+ );
1357
+ process.exit(1);
1358
+ }
1359
+ const config = await loadConfig(cwd);
1360
+ if (!config) {
1361
+ console.error(chalk3.red("Failed to load configuration"));
1362
+ process.exit(1);
1363
+ }
1364
+ const reservedNames = config.reservedScopeNames || DEFAULT_RESERVED_SCOPE_NAMES;
1365
+ const existingNames = config.scopes.map((s) => s.name);
1366
+ const response = await prompts([
1367
+ {
1368
+ type: "text",
1369
+ name: "name",
1370
+ message: "Scope name:",
1371
+ validate: (value) => {
1372
+ if (!value) return "Name is required";
1373
+ if (existingNames.includes(value))
1374
+ return `Scope "${value}" already exists`;
1375
+ const validation = validateScopeName(value, reservedNames);
1376
+ if (!validation.valid) {
1377
+ return validation.error + (validation.suggestion ? ` Try: ${validation.suggestion}` : "");
1378
+ }
1379
+ return true;
1380
+ }
1381
+ },
1382
+ {
1383
+ type: "text",
1384
+ name: "description",
1385
+ message: "Description:",
1386
+ validate: (value) => value ? true : "Description is required"
1387
+ },
1388
+ {
1389
+ type: "multiselect",
1390
+ name: "allowedTypes",
1391
+ message: "Allowed commit types (space to select, enter to continue):",
1392
+ choices: [
1393
+ { title: "feat", value: "feat", selected: true },
1394
+ { title: "fix", value: "fix", selected: true },
1395
+ { title: "docs", value: "docs", selected: false },
1396
+ { title: "style", value: "style", selected: false },
1397
+ { title: "refactor", value: "refactor", selected: false },
1398
+ { title: "perf", value: "perf", selected: false },
1399
+ { title: "test", value: "test", selected: false },
1400
+ { title: "build", value: "build", selected: false },
1401
+ { title: "ci", value: "ci", selected: false },
1402
+ { title: "chore", value: "chore", selected: false },
1403
+ { title: "revert", value: "revert", selected: false }
1404
+ ],
1405
+ min: 1
1406
+ },
1407
+ {
1408
+ type: "text",
1409
+ name: "mandatoryGuidelines",
1410
+ message: "Mandatory guidelines (comma-separated, or press enter to skip):",
1411
+ initial: ""
1412
+ }
1413
+ ]);
1414
+ if (!response.name) {
1415
+ console.log(chalk3.yellow("Cancelled"));
1416
+ process.exit(0);
1417
+ }
1418
+ if (!opts.force) {
1419
+ const validation = validateScopeName(response.name, reservedNames);
1420
+ if (!validation.valid) {
1421
+ console.error(chalk3.red(`
1422
+ \u2717 ${validation.error}`));
1423
+ if (validation.suggestion) {
1424
+ console.log(chalk3.yellow(`\u{1F4A1} Suggestion: ${validation.suggestion}`));
1425
+ }
1426
+ console.log(chalk3.gray("\nUse --force to override this check"));
1427
+ process.exit(1);
1428
+ }
1429
+ }
1430
+ const newScope = {
1431
+ name: response.name,
1432
+ description: response.description,
1433
+ allowedTypes: response.allowedTypes
1434
+ };
1435
+ if (response.mandatoryGuidelines) {
1436
+ const guidelines = response.mandatoryGuidelines.split(",").map((g) => g.trim()).filter((g) => g.length > 0);
1437
+ if (guidelines.length > 0) {
1438
+ newScope.mandatoryGuidelines = guidelines;
1439
+ }
1440
+ }
1441
+ config.scopes.push(newScope);
1442
+ const configContent = JSON.stringify(config, null, 2) + "\n";
1443
+ writeFileSync(configPath, configContent, "utf-8");
1444
+ console.log(chalk3.green(`
1445
+ \u2713 Added scope: ${response.name}`));
1446
+ console.log(chalk3.gray(` Description: ${response.description}`));
1447
+ console.log(chalk3.gray(` Types: ${response.allowedTypes.join(", ")}`));
1448
+ if (newScope.mandatoryGuidelines) {
1449
+ console.log(
1450
+ chalk3.gray(` Guidelines: ${newScope.mandatoryGuidelines.join(", ")}`)
1451
+ );
1452
+ }
1453
+ }
1454
+ async function removeScopeAction(name, opts) {
1455
+ const cwd = opts.cwd || process.cwd();
1456
+ const configPath = join5(cwd, "workflow.config.json");
1457
+ if (!existsSync5(configPath)) {
1458
+ console.error(chalk3.red("No workflow.config.json found"));
1459
+ process.exit(1);
1460
+ }
1461
+ const config = await loadConfig(cwd);
1462
+ if (!config) {
1463
+ console.error(chalk3.red("Failed to load configuration"));
1464
+ process.exit(1);
1465
+ }
1466
+ const scopeIndex = config.scopes.findIndex((s) => s.name === name);
1467
+ if (scopeIndex === -1) {
1468
+ console.error(chalk3.red(`Scope "${name}" not found`));
1469
+ process.exit(1);
1470
+ }
1471
+ const response = await prompts({
1472
+ type: "confirm",
1473
+ name: "confirmed",
1474
+ message: `Remove scope "${name}"?`,
1475
+ initial: false
1476
+ });
1477
+ if (!response.confirmed) {
1478
+ console.log(chalk3.yellow("Cancelled"));
1479
+ process.exit(0);
1480
+ }
1481
+ config.scopes.splice(scopeIndex, 1);
1482
+ const configContent = JSON.stringify(config, null, 2) + "\n";
1483
+ writeFileSync(configPath, configContent, "utf-8");
1484
+ console.log(chalk3.green(`\u2713 Removed scope: ${name}`));
1485
+ }
1486
+ async function listConfigAction(type, opts) {
1487
+ const cwd = opts.cwd || process.cwd();
1488
+ const config = await loadConfig(cwd);
1489
+ if (!config) {
1490
+ console.error(chalk3.red("No configuration found"));
1491
+ process.exit(1);
1492
+ }
1493
+ if (type === "scopes" || type === "all") {
1494
+ console.log(chalk3.blue("\n\u{1F4CB} Scopes:"));
1495
+ if (config.scopes.length === 0) {
1496
+ console.log(chalk3.gray(" (none)"));
1497
+ } else {
1498
+ config.scopes.forEach((scope, index) => {
1499
+ console.log(chalk3.green(`
1500
+ ${index + 1}. ${scope.name}`));
1501
+ console.log(chalk3.gray(` ${scope.description}`));
1502
+ console.log(
1503
+ chalk3.gray(` Types: ${scope.allowedTypes?.join(", ") || "all"}`)
1504
+ );
1505
+ if (scope.mandatoryGuidelines && scope.mandatoryGuidelines.length > 0) {
1506
+ console.log(
1507
+ chalk3.gray(
1508
+ ` Guidelines: ${scope.mandatoryGuidelines.join(", ")}`
1509
+ )
1510
+ );
1511
+ }
1512
+ });
1513
+ }
1514
+ }
1515
+ if (type === "reserved" || type === "all") {
1516
+ const reserved = config.reservedScopeNames || DEFAULT_RESERVED_SCOPE_NAMES;
1517
+ console.log(chalk3.blue("\n\u{1F6AB} Reserved Scope Names:"));
1518
+ console.log(chalk3.gray(` ${reserved.join(", ")}`));
1519
+ console.log(
1520
+ chalk3.gray(
1521
+ '\n \u{1F4A1} Configure in workflow.config.json: "reservedScopeNames"'
1522
+ )
1523
+ );
1524
+ }
1525
+ }
1526
+ async function getConfigValue(path2, opts) {
1527
+ const cwd = opts.cwd || process.cwd();
1528
+ const config = await loadConfig(cwd);
1529
+ if (!config) {
1530
+ console.error(chalk3.red("No configuration found"));
1531
+ process.exit(1);
1532
+ }
1533
+ const value = resolvePath(config, path2);
1534
+ if (value === void 0) {
1535
+ console.error(chalk3.red(`Path not found: ${path2}`));
1536
+ process.exit(1);
1537
+ }
1538
+ console.log(JSON.stringify(value, null, 2));
1539
+ }
1540
+ async function setConfigValue(path2, value, opts) {
1541
+ const cwd = opts.cwd || process.cwd();
1542
+ const configPath = join5(cwd, "workflow.config.json");
1543
+ if (!existsSync5(configPath)) {
1544
+ console.error(chalk3.red("No workflow.config.json found"));
1545
+ process.exit(1);
1546
+ }
1547
+ const config = await loadConfig(cwd);
1548
+ if (!config) {
1549
+ console.error(chalk3.red("Failed to load configuration"));
1550
+ process.exit(1);
1551
+ }
1552
+ let parsedValue;
1553
+ try {
1554
+ parsedValue = JSON.parse(value);
1555
+ } catch {
1556
+ parsedValue = value;
1557
+ }
1558
+ setPath(config, path2, parsedValue);
1559
+ if (!opts.force) {
1560
+ const validation = await validateConfig(cwd);
1561
+ if (!validation.valid) {
1562
+ console.error(chalk3.red("\u2717 Invalid configuration after change:"));
1563
+ validation.errors.forEach(
1564
+ (err) => console.error(chalk3.red(` \u2022 ${err}`))
1565
+ );
1566
+ console.log(chalk3.gray("\nUse --force to skip validation"));
1567
+ process.exit(1);
1568
+ }
1569
+ }
1570
+ const configContent = JSON.stringify(config, null, 2) + "\n";
1571
+ writeFileSync(configPath, configContent, "utf-8");
1572
+ console.log(chalk3.green(`\u2713 Set ${path2} = ${JSON.stringify(parsedValue)}`));
1573
+ }
1574
+ function resolvePath(obj, path2) {
1575
+ const parts = path2.split(/[\.\[\]]+/).filter(Boolean);
1576
+ let current = obj;
1577
+ for (const part of parts) {
1578
+ if (current === void 0 || current === null) {
1579
+ return void 0;
1580
+ }
1581
+ current = current[part];
1582
+ }
1583
+ return current;
1584
+ }
1585
+ function setPath(obj, path2, value) {
1586
+ const parts = path2.split(/[\.\[\]]+/).filter(Boolean);
1587
+ let current = obj;
1588
+ for (let i = 0; i < parts.length - 1; i++) {
1589
+ const part = parts[i];
1590
+ if (current[part] === void 0) {
1591
+ current[part] = {};
1592
+ }
1593
+ current = current[part];
1594
+ }
1595
+ current[parts[parts.length - 1]] = value;
1148
1596
  }
1149
1597
 
1150
1598
  // src/cli/commands/suggest.ts
@@ -1185,16 +1633,18 @@ async function suggestCommand(feedback, options = {}) {
1185
1633
  console.log(chalk4.dim("\nYour suggestion will be:"));
1186
1634
  console.log(chalk4.dim(" 1. Reviewed by the community"));
1187
1635
  console.log(chalk4.dim(" 2. Prioritized based on impact"));
1188
- console.log(chalk4.dim(" 3. Incorporated into future releases if approved\n"));
1636
+ console.log(
1637
+ chalk4.dim(" 3. Incorporated into future releases if approved\n")
1638
+ );
1189
1639
  }
1190
1640
 
1191
1641
  // src/cli/commands/doctor.ts
1192
1642
  import chalk5 from "chalk";
1193
1643
 
1194
1644
  // src/validators/guidelines.ts
1195
- import { existsSync as existsSync5 } from "fs";
1645
+ import { existsSync as existsSync6 } from "fs";
1196
1646
  import { readFile as readFile3, readdir } from "fs/promises";
1197
- import { join as join5 } from "path";
1647
+ import { join as join6 } from "path";
1198
1648
  function getEffectiveMandatoryTemplates(guidelinesConfig) {
1199
1649
  const coreMandatory = getMandatoryTemplateFilenames();
1200
1650
  if (!guidelinesConfig) {
@@ -1209,12 +1659,14 @@ function getEffectiveMandatoryTemplates(guidelinesConfig) {
1209
1659
  }
1210
1660
  }
1211
1661
  if (guidelinesConfig.optionalOverrides) {
1212
- mandatory = mandatory.filter((t) => !guidelinesConfig.optionalOverrides.includes(t));
1662
+ mandatory = mandatory.filter(
1663
+ (t) => !guidelinesConfig.optionalOverrides.includes(t)
1664
+ );
1213
1665
  }
1214
1666
  return mandatory;
1215
1667
  }
1216
1668
  async function validateGuidelinesExist(projectPath = process.cwd(), config) {
1217
- const guidelinesDir = join5(projectPath, "guidelines");
1669
+ const guidelinesDir = join6(projectPath, "guidelines");
1218
1670
  const result = {
1219
1671
  valid: true,
1220
1672
  missingMandatory: [],
@@ -1222,11 +1674,13 @@ async function validateGuidelinesExist(projectPath = process.cwd(), config) {
1222
1674
  presentOptional: [],
1223
1675
  errors: []
1224
1676
  };
1225
- if (!existsSync5(guidelinesDir)) {
1677
+ if (!existsSync6(guidelinesDir)) {
1226
1678
  const mandatory2 = getEffectiveMandatoryTemplates(config?.guidelines);
1227
1679
  result.valid = false;
1228
1680
  result.missingMandatory = mandatory2;
1229
- result.errors.push("Guidelines directory does not exist. Run: workflow init");
1681
+ result.errors.push(
1682
+ "Guidelines directory does not exist. Run: workflow init"
1683
+ );
1230
1684
  return result;
1231
1685
  }
1232
1686
  let existingFiles = [];
@@ -1234,7 +1688,9 @@ async function validateGuidelinesExist(projectPath = process.cwd(), config) {
1234
1688
  existingFiles = await readdir(guidelinesDir);
1235
1689
  } catch (error) {
1236
1690
  result.valid = false;
1237
- result.errors.push(`Cannot read guidelines directory: ${error instanceof Error ? error.message : String(error)}`);
1691
+ result.errors.push(
1692
+ `Cannot read guidelines directory: ${error instanceof Error ? error.message : String(error)}`
1693
+ );
1238
1694
  return result;
1239
1695
  }
1240
1696
  const mandatory = getEffectiveMandatoryTemplates(config?.guidelines);
@@ -1260,7 +1716,7 @@ async function validateGuidelinesExist(projectPath = process.cwd(), config) {
1260
1716
  return result;
1261
1717
  }
1262
1718
  async function validateGitHubActionsSetup(projectPath = process.cwd()) {
1263
- const workflowsDir = join5(projectPath, ".github", "workflows");
1719
+ const workflowsDir = join6(projectPath, ".github", "workflows");
1264
1720
  const result = {
1265
1721
  valid: true,
1266
1722
  hasWorkflowFile: false,
@@ -1272,9 +1728,11 @@ async function validateGitHubActionsSetup(projectPath = process.cwd()) {
1272
1728
  errors: [],
1273
1729
  warnings: []
1274
1730
  };
1275
- if (!existsSync5(workflowsDir)) {
1731
+ if (!existsSync6(workflowsDir)) {
1276
1732
  result.valid = false;
1277
- result.errors.push("GitHub Actions workflows directory does not exist. Run: workflow github:setup");
1733
+ result.errors.push(
1734
+ "GitHub Actions workflows directory does not exist. Run: workflow github:setup"
1735
+ );
1278
1736
  return result;
1279
1737
  }
1280
1738
  let workflowFiles = [];
@@ -1282,23 +1740,38 @@ async function validateGitHubActionsSetup(projectPath = process.cwd()) {
1282
1740
  workflowFiles = await readdir(workflowsDir);
1283
1741
  } catch (error) {
1284
1742
  result.valid = false;
1285
- result.errors.push(`Cannot read workflows directory: ${error instanceof Error ? error.message : String(error)}`);
1743
+ result.errors.push(
1744
+ `Cannot read workflows directory: ${error instanceof Error ? error.message : String(error)}`
1745
+ );
1286
1746
  return result;
1287
1747
  }
1288
- const ciWorkflowNames = ["ci.yml", "ci.yaml", "main.yml", "main.yaml", "build.yml", "build.yaml", "test.yml", "test.yaml"];
1289
- const ciWorkflows = workflowFiles.filter((f) => ciWorkflowNames.includes(f.toLowerCase()));
1748
+ const ciWorkflowNames = [
1749
+ "ci.yml",
1750
+ "ci.yaml",
1751
+ "main.yml",
1752
+ "main.yaml",
1753
+ "build.yml",
1754
+ "build.yaml",
1755
+ "test.yml",
1756
+ "test.yaml"
1757
+ ];
1758
+ const ciWorkflows = workflowFiles.filter(
1759
+ (f) => ciWorkflowNames.includes(f.toLowerCase())
1760
+ );
1290
1761
  if (ciWorkflows.length === 0) {
1291
1762
  result.valid = false;
1292
1763
  result.errors.push("No CI workflow file found. Run: workflow github:setup");
1293
1764
  return result;
1294
1765
  }
1295
1766
  result.hasWorkflowFile = true;
1296
- const workflowPath = join5(workflowsDir, ciWorkflows[0]);
1767
+ const workflowPath = join6(workflowsDir, ciWorkflows[0]);
1297
1768
  let workflowContent = "";
1298
1769
  try {
1299
1770
  workflowContent = await readFile3(workflowPath, "utf-8");
1300
1771
  } catch (error) {
1301
- result.warnings.push(`Cannot read workflow file: ${error instanceof Error ? error.message : String(error)}`);
1772
+ result.warnings.push(
1773
+ `Cannot read workflow file: ${error instanceof Error ? error.message : String(error)}`
1774
+ );
1302
1775
  return result;
1303
1776
  }
1304
1777
  const contentLower = workflowContent.toLowerCase();
@@ -1327,10 +1800,16 @@ async function validateGitHubActionsSetup(projectPath = process.cwd()) {
1327
1800
  } else {
1328
1801
  result.warnings.push("CI workflow may be missing test step");
1329
1802
  }
1330
- const mandatoryChecks = [result.hasLintCheck, result.hasTypecheckCheck, result.hasFormatCheck];
1803
+ const mandatoryChecks = [
1804
+ result.hasLintCheck,
1805
+ result.hasTypecheckCheck,
1806
+ result.hasFormatCheck
1807
+ ];
1331
1808
  if (!mandatoryChecks.every(Boolean)) {
1332
1809
  result.valid = false;
1333
- result.errors.push("CI workflow is missing mandatory checks (lint, typecheck, format)");
1810
+ result.errors.push(
1811
+ "CI workflow is missing mandatory checks (lint, typecheck, format)"
1812
+ );
1334
1813
  }
1335
1814
  return result;
1336
1815
  }
@@ -1367,13 +1846,25 @@ async function doctorCommand(options = {}) {
1367
1846
  console.log(chalk5.bold("\n\u{1F4DA} Guidelines"));
1368
1847
  const guidelinesResult = await validateGuidelinesExist(cwd, config);
1369
1848
  if (guidelinesResult.valid) {
1370
- console.log(chalk5.green(` \u2713 All ${guidelinesResult.presentMandatory.length} mandatory guidelines present`));
1849
+ console.log(
1850
+ chalk5.green(
1851
+ ` \u2713 All ${guidelinesResult.presentMandatory.length} mandatory guidelines present`
1852
+ )
1853
+ );
1371
1854
  if (guidelinesResult.presentOptional.length > 0) {
1372
- console.log(chalk5.dim(` + ${guidelinesResult.presentOptional.length} optional guidelines`));
1855
+ console.log(
1856
+ chalk5.dim(
1857
+ ` + ${guidelinesResult.presentOptional.length} optional guidelines`
1858
+ )
1859
+ );
1373
1860
  }
1374
1861
  } else {
1375
1862
  hasErrors = true;
1376
- console.log(chalk5.red(` \u2717 Missing ${guidelinesResult.missingMandatory.length} mandatory guidelines:`));
1863
+ console.log(
1864
+ chalk5.red(
1865
+ ` \u2717 Missing ${guidelinesResult.missingMandatory.length} mandatory guidelines:`
1866
+ )
1867
+ );
1377
1868
  for (const missing of guidelinesResult.missingMandatory) {
1378
1869
  console.log(chalk5.red(` \u2022 ${missing}`));
1379
1870
  }
@@ -1387,14 +1878,20 @@ async function doctorCommand(options = {}) {
1387
1878
  const hookStatuses = await getAllHooksStatus(cwd);
1388
1879
  const installedHooks = hookStatuses.filter((h) => h.installed);
1389
1880
  if (installedHooks.length === hookStatuses.length) {
1390
- console.log(chalk5.green(` \u2713 All ${installedHooks.length} hooks installed`));
1881
+ console.log(
1882
+ chalk5.green(` \u2713 All ${installedHooks.length} hooks installed`)
1883
+ );
1391
1884
  for (const hook of hookStatuses) {
1392
1885
  const extra = hook.wrappedOriginal ? " (wrapping original)" : "";
1393
1886
  console.log(chalk5.dim(` \u2022 ${hook.hookType}${extra}`));
1394
1887
  }
1395
1888
  } else if (installedHooks.length > 0) {
1396
1889
  hasWarnings = true;
1397
- console.log(chalk5.yellow(` \u26A0 ${installedHooks.length}/${hookStatuses.length} hooks installed`));
1890
+ console.log(
1891
+ chalk5.yellow(
1892
+ ` \u26A0 ${installedHooks.length}/${hookStatuses.length} hooks installed`
1893
+ )
1894
+ );
1398
1895
  for (const hook of hookStatuses) {
1399
1896
  if (hook.installed) {
1400
1897
  console.log(chalk5.green(` \u2713 ${hook.hookType}`));
@@ -1417,7 +1914,11 @@ async function doctorCommand(options = {}) {
1417
1914
  console.log(chalk5.dim(" \u25CB Not a GitHub repository (CI check skipped)"));
1418
1915
  console.log(chalk5.dim(` Remote: ${repoInfo.remoteUrl || "none"}`));
1419
1916
  } else {
1420
- console.log(chalk5.dim(` Repository: ${repoInfo.github?.owner}/${repoInfo.github?.repo}`));
1917
+ console.log(
1918
+ chalk5.dim(
1919
+ ` Repository: ${repoInfo.github?.owner}/${repoInfo.github?.repo}`
1920
+ )
1921
+ );
1421
1922
  const ciResult = await validateGitHubActionsSetup(cwd);
1422
1923
  if (ciResult.valid) {
1423
1924
  console.log(chalk5.green(" \u2713 GitHub Actions CI configured correctly"));
@@ -1446,15 +1947,21 @@ async function doctorCommand(options = {}) {
1446
1947
  if (repoInfo.isGitHub && hasCIWorkflow(cwd)) {
1447
1948
  console.log(chalk5.cyan(" \u2192 Enable branch protection on GitHub"));
1448
1949
  console.log(chalk5.dim(" Settings \u2192 Branches \u2192 Add rule"));
1449
- console.log(chalk5.dim(" \u2611 Require status checks to pass before merging"));
1450
- console.log(chalk5.dim(" \u2611 Require branches to be up to date before merging"));
1950
+ console.log(
1951
+ chalk5.dim(" \u2611 Require status checks to pass before merging")
1952
+ );
1953
+ console.log(
1954
+ chalk5.dim(" \u2611 Require branches to be up to date before merging")
1955
+ );
1451
1956
  }
1452
1957
  if (config.enforcement !== "strict") {
1453
1958
  console.log(chalk5.cyan(` \u2192 Consider switching to 'strict' enforcement`));
1454
1959
  console.log(chalk5.dim(` Current: ${config.enforcement}`));
1455
1960
  }
1456
1961
  if (config.scopes.length < 5) {
1457
- console.log(chalk5.cyan(" \u2192 Consider adding more scopes for better organization"));
1962
+ console.log(
1963
+ chalk5.cyan(" \u2192 Consider adding more scopes for better organization")
1964
+ );
1458
1965
  console.log(chalk5.dim(" Run: workflow config add scope <name>"));
1459
1966
  }
1460
1967
  console.log(chalk5.bold("\n\u{1F4CA} Summary"));
@@ -1472,8 +1979,8 @@ async function doctorCommand(options = {}) {
1472
1979
  // src/cli/commands/setup.ts
1473
1980
  import * as p3 from "@clack/prompts";
1474
1981
  import chalk6 from "chalk";
1475
- import { readFileSync, writeFileSync, existsSync as existsSync6 } from "fs";
1476
- import { join as join6 } from "path";
1982
+ import { readFileSync, writeFileSync as writeFileSync2, existsSync as existsSync7 } from "fs";
1983
+ import { join as join7 } from "path";
1477
1984
  var WORKFLOW_SCRIPTS = {
1478
1985
  "workflow:init": "workflow-agent init",
1479
1986
  "workflow:validate": "workflow-agent validate",
@@ -1483,8 +1990,8 @@ var WORKFLOW_SCRIPTS = {
1483
1990
  async function setupCommand() {
1484
1991
  p3.intro(chalk6.bgBlue(" workflow-agent setup "));
1485
1992
  const cwd = process.cwd();
1486
- const packageJsonPath = join6(cwd, "package.json");
1487
- if (!existsSync6(packageJsonPath)) {
1993
+ const packageJsonPath = join7(cwd, "package.json");
1994
+ if (!existsSync7(packageJsonPath)) {
1488
1995
  p3.cancel("No package.json found in current directory");
1489
1996
  process.exit(1);
1490
1997
  }
@@ -1527,12 +2034,16 @@ async function setupCommand() {
1527
2034
  for (const [scriptName, scriptCommand] of Object.entries(scriptsToAdd)) {
1528
2035
  packageJson.scripts[scriptName] = scriptCommand;
1529
2036
  }
1530
- writeFileSync(
2037
+ writeFileSync2(
1531
2038
  packageJsonPath,
1532
2039
  JSON.stringify(packageJson, null, 2) + "\n",
1533
2040
  "utf-8"
1534
2041
  );
1535
- p3.outro(chalk6.green(`\u2713 Added ${Object.keys(scriptsToAdd).length} workflow scripts to package.json!`));
2042
+ p3.outro(
2043
+ chalk6.green(
2044
+ `\u2713 Added ${Object.keys(scriptsToAdd).length} workflow scripts to package.json!`
2045
+ )
2046
+ );
1536
2047
  console.log(chalk6.dim("\nRun them with:"));
1537
2048
  console.log(chalk6.dim(" pnpm run workflow:init"));
1538
2049
  console.log(chalk6.dim(" npm run workflow:init\n"));
@@ -1541,14 +2052,14 @@ async function setupCommand() {
1541
2052
  // src/cli/commands/scope-create.ts
1542
2053
  import * as p4 from "@clack/prompts";
1543
2054
  import chalk7 from "chalk";
1544
- import { existsSync as existsSync7 } from "fs";
2055
+ import { existsSync as existsSync8 } from "fs";
1545
2056
  import { writeFile as writeFile4, mkdir as mkdir4, readFile as readFile4 } from "fs/promises";
1546
- import { join as join7 } from "path";
2057
+ import { join as join8 } from "path";
1547
2058
  async function scopeCreateCommand(options) {
1548
2059
  console.log(chalk7.bold.cyan("\n\u{1F3A8} Create Custom Scope Package\n"));
1549
2060
  const cwd = process.cwd();
1550
2061
  const isNonInteractive = !!(options.name && options.scopes && options.presetName);
1551
- const isMonorepo2 = existsSync7(join7(cwd, "pnpm-workspace.yaml"));
2062
+ const isMonorepo2 = existsSync8(join8(cwd, "pnpm-workspace.yaml"));
1552
2063
  if (isMonorepo2) {
1553
2064
  console.log(chalk7.dim("\u2713 Detected monorepo workspace\n"));
1554
2065
  }
@@ -1557,8 +2068,10 @@ async function scopeCreateCommand(options) {
1557
2068
  placeholder: "my-custom-scope",
1558
2069
  validate: (value) => {
1559
2070
  if (!value || value.length === 0) return "Package name is required";
1560
- if (!/^[a-z0-9-]+$/.test(value)) return "Package name must be lowercase alphanumeric with hyphens";
1561
- if (value.length > 32) return "Package name must be 32 characters or less";
2071
+ if (!/^[a-z0-9-]+$/.test(value))
2072
+ return "Package name must be lowercase alphanumeric with hyphens";
2073
+ if (value.length > 32)
2074
+ return "Package name must be 32 characters or less";
1562
2075
  return void 0;
1563
2076
  }
1564
2077
  });
@@ -1593,7 +2106,9 @@ async function scopeCreateCommand(options) {
1593
2106
  });
1594
2107
  }
1595
2108
  } else {
1596
- console.log(chalk7.dim("\nAdd scopes to your preset (aim for 8-15 scopes):\n"));
2109
+ console.log(
2110
+ chalk7.dim("\nAdd scopes to your preset (aim for 8-15 scopes):\n")
2111
+ );
1597
2112
  let addMore = true;
1598
2113
  while (addMore) {
1599
2114
  const scopeName = await p4.text({
@@ -1601,9 +2116,11 @@ async function scopeCreateCommand(options) {
1601
2116
  placeholder: "auth",
1602
2117
  validate: (value) => {
1603
2118
  if (!value || value.length === 0) return "Scope name is required";
1604
- if (!/^[a-z0-9-]+$/.test(value)) return "Must be lowercase alphanumeric with hyphens";
2119
+ if (!/^[a-z0-9-]+$/.test(value))
2120
+ return "Must be lowercase alphanumeric with hyphens";
1605
2121
  if (value.length > 32) return "Must be 32 characters or less";
1606
- if (scopes.some((s) => s.name === value)) return "Scope name already exists";
2122
+ if (scopes.some((s) => s.name === value))
2123
+ return "Scope name already exists";
1607
2124
  return void 0;
1608
2125
  }
1609
2126
  });
@@ -1614,7 +2131,8 @@ async function scopeCreateCommand(options) {
1614
2131
  message: "Description:",
1615
2132
  placeholder: "Authentication and authorization",
1616
2133
  validate: (value) => {
1617
- if (!value || value.length < 10) return "Description must be at least 10 characters";
2134
+ if (!value || value.length < 10)
2135
+ return "Description must be at least 10 characters";
1618
2136
  return void 0;
1619
2137
  }
1620
2138
  });
@@ -1672,18 +2190,22 @@ async function scopeCreateCommand(options) {
1672
2190
  const validation = validateScopeDefinitions(scopes);
1673
2191
  if (!validation.valid) {
1674
2192
  console.log(chalk7.red("\n\u2717 Scope validation failed:\n"));
1675
- validation.errors.forEach((error) => console.log(chalk7.red(` \u2022 ${error}`)));
2193
+ validation.errors.forEach(
2194
+ (error) => console.log(chalk7.red(` \u2022 ${error}`))
2195
+ );
1676
2196
  p4.cancel("Operation cancelled");
1677
2197
  process.exit(1);
1678
2198
  }
1679
- console.log(chalk7.green(`
2199
+ console.log(
2200
+ chalk7.green(`
1680
2201
  \u2713 ${scopes.length} scopes validated successfully
1681
- `));
2202
+ `)
2203
+ );
1682
2204
  let outputDir;
1683
2205
  if (options.outputDir) {
1684
2206
  outputDir = options.outputDir;
1685
2207
  } else if (isMonorepo2) {
1686
- outputDir = join7(cwd, "packages", `scopes-${packageName}`);
2208
+ outputDir = join8(cwd, "packages", `scopes-${packageName}`);
1687
2209
  } else {
1688
2210
  const customDir = await p4.text({
1689
2211
  message: "Output directory:",
@@ -1694,9 +2216,9 @@ async function scopeCreateCommand(options) {
1694
2216
  p4.cancel("Operation cancelled");
1695
2217
  process.exit(0);
1696
2218
  }
1697
- outputDir = join7(cwd, customDir);
2219
+ outputDir = join8(cwd, customDir);
1698
2220
  }
1699
- if (existsSync7(outputDir)) {
2221
+ if (existsSync8(outputDir)) {
1700
2222
  const shouldOverwrite = await p4.confirm({
1701
2223
  message: `Directory ${outputDir} already exists. Overwrite?`,
1702
2224
  initialValue: false
@@ -1709,7 +2231,7 @@ async function scopeCreateCommand(options) {
1709
2231
  const spinner5 = p4.spinner();
1710
2232
  spinner5.start("Creating package structure...");
1711
2233
  try {
1712
- await mkdir4(join7(outputDir, "src"), { recursive: true });
2234
+ await mkdir4(join8(outputDir, "src"), { recursive: true });
1713
2235
  const packageJson = {
1714
2236
  name: `@workflow/scopes-${packageName}`,
1715
2237
  version: "1.0.0",
@@ -1750,7 +2272,7 @@ async function scopeCreateCommand(options) {
1750
2272
  }
1751
2273
  };
1752
2274
  await writeFile4(
1753
- join7(outputDir, "package.json"),
2275
+ join8(outputDir, "package.json"),
1754
2276
  JSON.stringify(packageJson, null, 2),
1755
2277
  "utf-8"
1756
2278
  );
@@ -1763,7 +2285,7 @@ async function scopeCreateCommand(options) {
1763
2285
  include: ["src/**/*"]
1764
2286
  };
1765
2287
  await writeFile4(
1766
- join7(outputDir, "tsconfig.json"),
2288
+ join8(outputDir, "tsconfig.json"),
1767
2289
  JSON.stringify(tsconfig, null, 2),
1768
2290
  "utf-8"
1769
2291
  );
@@ -1777,7 +2299,7 @@ export default defineConfig({
1777
2299
  sourcemap: true,
1778
2300
  });
1779
2301
  `;
1780
- await writeFile4(join7(outputDir, "tsup.config.ts"), tsupConfig, "utf-8");
2302
+ await writeFile4(join8(outputDir, "tsup.config.ts"), tsupConfig, "utf-8");
1781
2303
  const indexTs = `import type { Scope } from '@hawkinside_out/workflow-agent/config';
1782
2304
 
1783
2305
  export const scopes: Scope[] = ${JSON.stringify(scopes, null, 2)};
@@ -1791,7 +2313,7 @@ export const preset = {
1791
2313
 
1792
2314
  export default preset;
1793
2315
  `;
1794
- await writeFile4(join7(outputDir, "src", "index.ts"), indexTs, "utf-8");
2316
+ await writeFile4(join8(outputDir, "src", "index.ts"), indexTs, "utf-8");
1795
2317
  if (!options.noTest) {
1796
2318
  const testFile = `import { describe, it, expect } from 'vitest';
1797
2319
  import { scopes, preset } from './index.js';
@@ -1832,21 +2354,29 @@ describe('${presetName} Scope Preset', () => {
1832
2354
  });
1833
2355
  });
1834
2356
  `;
1835
- await writeFile4(join7(outputDir, "src", "index.test.ts"), testFile, "utf-8");
2357
+ await writeFile4(
2358
+ join8(outputDir, "src", "index.test.ts"),
2359
+ testFile,
2360
+ "utf-8"
2361
+ );
1836
2362
  }
1837
2363
  spinner5.stop("\u2713 Package structure created");
1838
2364
  if (isMonorepo2) {
1839
- const workspaceFile = join7(cwd, "pnpm-workspace.yaml");
2365
+ const workspaceFile = join8(cwd, "pnpm-workspace.yaml");
1840
2366
  const workspaceContent = await readFile4(workspaceFile, "utf-8");
1841
2367
  const packagePath = `packages/scopes-${packageName}`;
1842
2368
  if (!workspaceContent.includes(packagePath) && !workspaceContent.includes("packages/*")) {
1843
- console.log(chalk7.yellow("\n\u26A0\uFE0F Add the following to pnpm-workspace.yaml:"));
2369
+ console.log(
2370
+ chalk7.yellow("\n\u26A0\uFE0F Add the following to pnpm-workspace.yaml:")
2371
+ );
1844
2372
  console.log(chalk7.dim(` - '${packagePath}'`));
1845
2373
  } else {
1846
2374
  console.log(chalk7.green("\n\u2713 Package will be included in workspace"));
1847
2375
  }
1848
2376
  }
1849
- console.log(chalk7.green.bold("\n\u2728 Custom scope package created successfully!\n"));
2377
+ console.log(
2378
+ chalk7.green.bold("\n\u2728 Custom scope package created successfully!\n")
2379
+ );
1850
2380
  console.log(chalk7.bold("Package details:"));
1851
2381
  console.log(chalk7.dim(` Location: ${outputDir}`));
1852
2382
  console.log(chalk7.dim(` Package: @workflow/scopes-${packageName}`));
@@ -1859,17 +2389,27 @@ describe('${presetName} Scope Preset', () => {
1859
2389
  if (!options.noTest) {
1860
2390
  console.log(chalk7.dim(` 4. pnpm test`));
1861
2391
  }
1862
- console.log(chalk7.dim(` ${!options.noTest ? "5" : "4"}. Update repository URL in package.json`));
2392
+ console.log(
2393
+ chalk7.dim(
2394
+ ` ${!options.noTest ? "5" : "4"}. Update repository URL in package.json`
2395
+ )
2396
+ );
1863
2397
  const shouldPublish = isNonInteractive ? false : await p4.confirm({
1864
2398
  message: "\nWould you like instructions for publishing to npm?",
1865
2399
  initialValue: false
1866
2400
  });
1867
2401
  if (shouldPublish && !p4.isCancel(shouldPublish)) {
1868
2402
  console.log(chalk7.bold("\n\u{1F4E6} Publishing instructions:\n"));
1869
- console.log(chalk7.dim(" 1. npm login (or configure .npmrc with your registry)"));
2403
+ console.log(
2404
+ chalk7.dim(" 1. npm login (or configure .npmrc with your registry)")
2405
+ );
1870
2406
  console.log(chalk7.dim(" 2. Update version in package.json as needed"));
1871
2407
  console.log(chalk7.dim(" 3. pnpm publish --access public"));
1872
- console.log(chalk7.dim(" 4. Use in other projects: pnpm add @workflow/scopes-" + packageName + "\n"));
2408
+ console.log(
2409
+ chalk7.dim(
2410
+ " 4. Use in other projects: pnpm add @workflow/scopes-" + packageName + "\n"
2411
+ )
2412
+ );
1873
2413
  }
1874
2414
  } catch (error) {
1875
2415
  spinner5.stop("\u2717 Failed to create package");
@@ -1881,9 +2421,9 @@ describe('${presetName} Scope Preset', () => {
1881
2421
  // src/cli/commands/scope-migrate.ts
1882
2422
  import * as p5 from "@clack/prompts";
1883
2423
  import chalk8 from "chalk";
1884
- import { existsSync as existsSync8 } from "fs";
2424
+ import { existsSync as existsSync9 } from "fs";
1885
2425
  import { writeFile as writeFile5, mkdir as mkdir5, readFile as readFile5 } from "fs/promises";
1886
- import { join as join8 } from "path";
2426
+ import { join as join9 } from "path";
1887
2427
  async function scopeMigrateCommand(options) {
1888
2428
  console.log(chalk8.bold.cyan("\n\u{1F504} Migrate Scopes to Custom Package\n"));
1889
2429
  const cwd = process.cwd();
@@ -1906,11 +2446,17 @@ async function scopeMigrateCommand(options) {
1906
2446
  p5.cancel("No scopes found in workflow.config.json");
1907
2447
  process.exit(1);
1908
2448
  }
1909
- console.log(chalk8.dim(`Found ${config.scopes.length} scopes in workflow.config.json
1910
- `));
2449
+ console.log(
2450
+ chalk8.dim(`Found ${config.scopes.length} scopes in workflow.config.json
2451
+ `)
2452
+ );
1911
2453
  console.log(chalk8.bold("Current scopes:"));
1912
2454
  config.scopes.forEach((scope, i) => {
1913
- console.log(chalk8.dim(` ${i + 1}. ${scope.emoji || "\u2022"} ${scope.name} - ${scope.description}`));
2455
+ console.log(
2456
+ chalk8.dim(
2457
+ ` ${i + 1}. ${scope.emoji || "\u2022"} ${scope.name} - ${scope.description}`
2458
+ )
2459
+ );
1914
2460
  });
1915
2461
  console.log();
1916
2462
  const shouldContinue = await p5.confirm({
@@ -1921,7 +2467,7 @@ async function scopeMigrateCommand(options) {
1921
2467
  p5.cancel("Migration cancelled");
1922
2468
  process.exit(0);
1923
2469
  }
1924
- const isMonorepo2 = existsSync8(join8(cwd, "pnpm-workspace.yaml"));
2470
+ const isMonorepo2 = existsSync9(join9(cwd, "pnpm-workspace.yaml"));
1925
2471
  if (isMonorepo2) {
1926
2472
  console.log(chalk8.dim("\n\u2713 Detected monorepo workspace\n"));
1927
2473
  }
@@ -1930,8 +2476,10 @@ async function scopeMigrateCommand(options) {
1930
2476
  placeholder: config.projectName.toLowerCase().replace(/[^a-z0-9-]/g, "-"),
1931
2477
  validate: (value) => {
1932
2478
  if (!value || value.length === 0) return "Package name is required";
1933
- if (!/^[a-z0-9-]+$/.test(value)) return "Package name must be lowercase alphanumeric with hyphens";
1934
- if (value.length > 32) return "Package name must be 32 characters or less";
2479
+ if (!/^[a-z0-9-]+$/.test(value))
2480
+ return "Package name must be lowercase alphanumeric with hyphens";
2481
+ if (value.length > 32)
2482
+ return "Package name must be 32 characters or less";
1935
2483
  return void 0;
1936
2484
  }
1937
2485
  });
@@ -1953,7 +2501,9 @@ async function scopeMigrateCommand(options) {
1953
2501
  const validation = validateScopeDefinitions(config.scopes);
1954
2502
  if (!validation.valid) {
1955
2503
  console.log(chalk8.yellow("\n\u26A0\uFE0F Scope validation warnings:\n"));
1956
- validation.errors.forEach((error) => console.log(chalk8.yellow(` \u2022 ${error}`)));
2504
+ validation.errors.forEach(
2505
+ (error) => console.log(chalk8.yellow(` \u2022 ${error}`))
2506
+ );
1957
2507
  const shouldFix = await p5.confirm({
1958
2508
  message: "Some scopes have validation issues. Continue anyway?",
1959
2509
  initialValue: false
@@ -1967,7 +2517,7 @@ async function scopeMigrateCommand(options) {
1967
2517
  if (options.outputDir) {
1968
2518
  outputDir = options.outputDir;
1969
2519
  } else if (isMonorepo2) {
1970
- outputDir = join8(cwd, "packages", `scopes-${packageName}`);
2520
+ outputDir = join9(cwd, "packages", `scopes-${packageName}`);
1971
2521
  } else {
1972
2522
  const customDir = await p5.text({
1973
2523
  message: "Output directory:",
@@ -1978,9 +2528,9 @@ async function scopeMigrateCommand(options) {
1978
2528
  p5.cancel("Migration cancelled");
1979
2529
  process.exit(0);
1980
2530
  }
1981
- outputDir = join8(cwd, customDir);
2531
+ outputDir = join9(cwd, customDir);
1982
2532
  }
1983
- if (existsSync8(outputDir)) {
2533
+ if (existsSync9(outputDir)) {
1984
2534
  const shouldOverwrite = await p5.confirm({
1985
2535
  message: `Directory ${outputDir} already exists. Overwrite?`,
1986
2536
  initialValue: false
@@ -1993,7 +2543,7 @@ async function scopeMigrateCommand(options) {
1993
2543
  const spinner5 = p5.spinner();
1994
2544
  spinner5.start("Migrating scopes to package...");
1995
2545
  try {
1996
- await mkdir5(join8(outputDir, "src"), { recursive: true });
2546
+ await mkdir5(join9(outputDir, "src"), { recursive: true });
1997
2547
  const packageJson = {
1998
2548
  name: `@workflow/scopes-${packageName}`,
1999
2549
  version: "1.0.0",
@@ -2034,7 +2584,7 @@ async function scopeMigrateCommand(options) {
2034
2584
  }
2035
2585
  };
2036
2586
  await writeFile5(
2037
- join8(outputDir, "package.json"),
2587
+ join9(outputDir, "package.json"),
2038
2588
  JSON.stringify(packageJson, null, 2),
2039
2589
  "utf-8"
2040
2590
  );
@@ -2047,7 +2597,7 @@ async function scopeMigrateCommand(options) {
2047
2597
  include: ["src/**/*"]
2048
2598
  };
2049
2599
  await writeFile5(
2050
- join8(outputDir, "tsconfig.json"),
2600
+ join9(outputDir, "tsconfig.json"),
2051
2601
  JSON.stringify(tsconfig, null, 2),
2052
2602
  "utf-8"
2053
2603
  );
@@ -2061,7 +2611,7 @@ export default defineConfig({
2061
2611
  sourcemap: true,
2062
2612
  });
2063
2613
  `;
2064
- await writeFile5(join8(outputDir, "tsup.config.ts"), tsupConfig, "utf-8");
2614
+ await writeFile5(join9(outputDir, "tsup.config.ts"), tsupConfig, "utf-8");
2065
2615
  const indexTs = `import type { Scope } from '@hawkinside_out/workflow-agent/config';
2066
2616
 
2067
2617
  export const scopes: Scope[] = ${JSON.stringify(config.scopes, null, 2)};
@@ -2075,7 +2625,7 @@ export const preset = {
2075
2625
 
2076
2626
  export default preset;
2077
2627
  `;
2078
- await writeFile5(join8(outputDir, "src", "index.ts"), indexTs, "utf-8");
2628
+ await writeFile5(join9(outputDir, "src", "index.ts"), indexTs, "utf-8");
2079
2629
  const testFile = `import { describe, it, expect } from 'vitest';
2080
2630
  import { scopes, preset } from './index.js';
2081
2631
  import { ScopeSchema } from '@hawkinside_out/workflow-agent/config';
@@ -2118,14 +2668,16 @@ describe('${presetName} Scope Preset (Migrated)', () => {
2118
2668
  });
2119
2669
  });
2120
2670
  `;
2121
- await writeFile5(join8(outputDir, "src", "index.test.ts"), testFile, "utf-8");
2671
+ await writeFile5(join9(outputDir, "src", "index.test.ts"), testFile, "utf-8");
2122
2672
  spinner5.stop("\u2713 Package created from migrated scopes");
2123
2673
  if (isMonorepo2) {
2124
- const workspaceFile = join8(cwd, "pnpm-workspace.yaml");
2674
+ const workspaceFile = join9(cwd, "pnpm-workspace.yaml");
2125
2675
  const workspaceContent = await readFile5(workspaceFile, "utf-8");
2126
2676
  const packagePath = `packages/scopes-${packageName}`;
2127
2677
  if (!workspaceContent.includes(packagePath) && !workspaceContent.includes("packages/*")) {
2128
- console.log(chalk8.yellow("\n\u26A0\uFE0F Add the following to pnpm-workspace.yaml:"));
2678
+ console.log(
2679
+ chalk8.yellow("\n\u26A0\uFE0F Add the following to pnpm-workspace.yaml:")
2680
+ );
2129
2681
  console.log(chalk8.dim(` - '${packagePath}'`));
2130
2682
  } else {
2131
2683
  console.log(chalk8.green("\n\u2713 Package will be included in workspace"));
@@ -2136,7 +2688,7 @@ describe('${presetName} Scope Preset (Migrated)', () => {
2136
2688
  initialValue: false
2137
2689
  });
2138
2690
  if (!p5.isCancel(keepConfig) && !keepConfig) {
2139
- const configPath = join8(cwd, "workflow.config.json");
2691
+ const configPath = join9(cwd, "workflow.config.json");
2140
2692
  const updatedConfig = {
2141
2693
  ...config,
2142
2694
  scopes: [],
@@ -2144,11 +2696,17 @@ describe('${presetName} Scope Preset (Migrated)', () => {
2144
2696
  preset: `scopes-${packageName}`
2145
2697
  // Reference the new package
2146
2698
  };
2147
- await writeFile5(configPath, JSON.stringify(updatedConfig, null, 2), "utf-8");
2699
+ await writeFile5(
2700
+ configPath,
2701
+ JSON.stringify(updatedConfig, null, 2),
2702
+ "utf-8"
2703
+ );
2148
2704
  console.log(chalk8.green("\u2713 Updated workflow.config.json"));
2149
2705
  console.log(chalk8.dim(" \u2022 Cleared inline scopes"));
2150
- console.log(chalk8.dim(` \u2022 Added preset reference: scopes-${packageName}
2151
- `));
2706
+ console.log(
2707
+ chalk8.dim(` \u2022 Added preset reference: scopes-${packageName}
2708
+ `)
2709
+ );
2152
2710
  }
2153
2711
  console.log(chalk8.green.bold("\n\u2728 Migration completed successfully!\n"));
2154
2712
  console.log(chalk8.bold("Package details:"));
@@ -2165,11 +2723,23 @@ describe('${presetName} Scope Preset (Migrated)', () => {
2165
2723
  `));
2166
2724
  if (!keepConfig) {
2167
2725
  console.log(chalk8.bold("To use the migrated scopes:\n"));
2168
- console.log(chalk8.dim(` 1. Install the package: pnpm add -w @workflow/scopes-${packageName}`));
2169
- console.log(chalk8.dim(` 2. The preset is already referenced in workflow.config.json
2170
- `));
2171
- }
2172
- console.log(chalk8.dim("\u{1F4A1} Tip: You can now reuse this scope package across multiple projects!\n"));
2726
+ console.log(
2727
+ chalk8.dim(
2728
+ ` 1. Install the package: pnpm add -w @workflow/scopes-${packageName}`
2729
+ )
2730
+ );
2731
+ console.log(
2732
+ chalk8.dim(
2733
+ ` 2. The preset is already referenced in workflow.config.json
2734
+ `
2735
+ )
2736
+ );
2737
+ }
2738
+ console.log(
2739
+ chalk8.dim(
2740
+ "\u{1F4A1} Tip: You can now reuse this scope package across multiple projects!\n"
2741
+ )
2742
+ );
2173
2743
  } catch (error) {
2174
2744
  spinner5.stop("\u2717 Migration failed");
2175
2745
  console.error(chalk8.red("\nError:"), error);
@@ -2211,12 +2781,18 @@ async function installHooksAction(cwd) {
2211
2781
  for (const result of results) {
2212
2782
  if (result.success) {
2213
2783
  if (result.wrappedExisting) {
2214
- console.log(chalk9.green(`\u2713 Installed ${result.hookType} hook (wrapped existing hook)`));
2784
+ console.log(
2785
+ chalk9.green(
2786
+ `\u2713 Installed ${result.hookType} hook (wrapped existing hook)`
2787
+ )
2788
+ );
2215
2789
  } else {
2216
2790
  console.log(chalk9.green(`\u2713 Installed ${result.hookType} hook`));
2217
2791
  }
2218
2792
  } else {
2219
- console.error(chalk9.red(`\u2717 Failed to install ${result.hookType}: ${result.error}`));
2793
+ console.error(
2794
+ chalk9.red(`\u2717 Failed to install ${result.hookType}: ${result.error}`)
2795
+ );
2220
2796
  hasErrors = true;
2221
2797
  }
2222
2798
  }
@@ -2239,12 +2815,16 @@ async function uninstallHooksAction(cwd) {
2239
2815
  for (const result of results) {
2240
2816
  if (result.success) {
2241
2817
  if (result.wrappedExisting) {
2242
- console.log(chalk9.green(`\u2713 Removed ${result.hookType} hook (restored original)`));
2818
+ console.log(
2819
+ chalk9.green(`\u2713 Removed ${result.hookType} hook (restored original)`)
2820
+ );
2243
2821
  } else {
2244
2822
  console.log(chalk9.green(`\u2713 Removed ${result.hookType} hook`));
2245
2823
  }
2246
2824
  } else if (result.error) {
2247
- console.error(chalk9.red(`\u2717 Failed to remove ${result.hookType}: ${result.error}`));
2825
+ console.error(
2826
+ chalk9.red(`\u2717 Failed to remove ${result.hookType}: ${result.error}`)
2827
+ );
2248
2828
  hasErrors = true;
2249
2829
  }
2250
2830
  }
@@ -2320,7 +2900,11 @@ async function setupAction(cwd) {
2320
2900
  process.exit(0);
2321
2901
  }
2322
2902
  } else {
2323
- console.log(chalk10.dim(`Repository: ${repoInfo.github?.owner}/${repoInfo.github?.repo}`));
2903
+ console.log(
2904
+ chalk10.dim(
2905
+ `Repository: ${repoInfo.github?.owner}/${repoInfo.github?.repo}`
2906
+ )
2907
+ );
2324
2908
  }
2325
2909
  if (hasCIWorkflow(cwd)) {
2326
2910
  const shouldOverwrite = await p6.confirm({
@@ -2354,7 +2938,13 @@ async function setupAction(cwd) {
2354
2938
  console.log(chalk10.dim(" \u2022 Push to main/develop branches"));
2355
2939
  console.log(chalk10.dim(" \u2022 Pull requests to main/develop branches"));
2356
2940
  console.log(chalk10.dim("\nChecks included:"));
2357
- const checks = ciConfig?.checks || ["lint", "typecheck", "format", "build", "test"];
2941
+ const checks = ciConfig?.checks || [
2942
+ "lint",
2943
+ "typecheck",
2944
+ "format",
2945
+ "build",
2946
+ "test"
2947
+ ];
2358
2948
  for (const check of checks) {
2359
2949
  const hasScript = check === "lint" ? projectInfo.hasLintScript : check === "typecheck" ? projectInfo.hasTypecheckScript : check === "format" ? projectInfo.hasFormatScript : check === "test" ? projectInfo.hasTestScript : check === "build" ? projectInfo.hasBuildScript : false;
2360
2950
  const status = hasScript ? chalk10.green("\u2713") : chalk10.yellow("\u26A0");
@@ -2363,7 +2953,9 @@ async function setupAction(cwd) {
2363
2953
  }
2364
2954
  console.log(chalk10.cyan("\n\u{1F4A1} Recommended: Enable branch protection"));
2365
2955
  console.log(chalk10.dim(" Go to GitHub \u2192 Settings \u2192 Branches \u2192 Add rule"));
2366
- console.log(chalk10.dim(' Enable "Require status checks to pass before merging"'));
2956
+ console.log(
2957
+ chalk10.dim(' Enable "Require status checks to pass before merging"')
2958
+ );
2367
2959
  console.log(chalk10.dim(' Select the "ci" status check'));
2368
2960
  } else {
2369
2961
  spinner5.stop(chalk10.red("\u2717 Failed to create CI workflow"));
@@ -2415,17 +3007,37 @@ async function checkAction(cwd) {
2415
3007
  }
2416
3008
 
2417
3009
  // src/cli/index.ts
2418
- var program = new Command();
2419
- program.name("workflow").description("A self-evolving workflow management system for AI agent development").version("1.0.0");
2420
- program.command("init").description("Initialize workflow in current project").option("--migrate", "Auto-detect existing patterns and migrate").option("--workspace", "Initialize for multiple repositories").option("--preset <preset>", "Preset to use (saas, library, api, ecommerce, cms, custom)").option("--name <name>", "Project name").option("-y, --yes", "Skip confirmation prompts").action(initCommand);
2421
- program.command("validate <type>").description("Validate branch name, commit message, or PR title").argument("<type>", "What to validate: branch, commit, or pr").argument("[value]", "Value to validate (defaults to current branch/HEAD commit)").option("--suggest-on-error", "Offer improvement suggestions on validation errors").action(validateCommand);
2422
- program.command("config <action>").description("Manage workflow configuration").argument("<action>", "Action: get, set, add, remove").argument("[key]", "Config key").argument("[value]", "Config value").action(configCommand);
2423
- program.command("suggest").description("Submit an improvement suggestion").argument("<feedback>", "Your improvement suggestion").option("--author <author>", "Your name or username").option("--category <category>", "Category: feature, bug, documentation, performance, other").action(suggestCommand);
3010
+ var program = new Command2();
3011
+ program.name("workflow").description(
3012
+ "A self-evolving workflow management system for AI agent development"
3013
+ ).version("1.0.0");
3014
+ program.command("init").description("Initialize workflow in current project").option("--migrate", "Auto-detect existing patterns and migrate").option("--workspace", "Initialize for multiple repositories").option(
3015
+ "--preset <preset>",
3016
+ "Preset to use (saas, library, api, ecommerce, cms, custom)"
3017
+ ).option("--name <name>", "Project name").option("-y, --yes", "Skip confirmation prompts").action(initCommand);
3018
+ program.command("validate <type>").description("Validate branch name, commit message, or PR title").argument("<type>", "What to validate: branch, commit, or pr").argument(
3019
+ "[value]",
3020
+ "Value to validate (defaults to current branch/HEAD commit)"
3021
+ ).option(
3022
+ "--suggest-on-error",
3023
+ "Offer improvement suggestions on validation errors"
3024
+ ).action(validateCommand);
3025
+ program.addCommand(createConfigCommand());
3026
+ program.command("suggest").description("Submit an improvement suggestion").argument("<feedback>", "Your improvement suggestion").option("--author <author>", "Your name or username").option(
3027
+ "--category <category>",
3028
+ "Category: feature, bug, documentation, performance, other"
3029
+ ).action(suggestCommand);
2424
3030
  program.command("setup").description("Add workflow scripts to package.json").action(setupCommand);
2425
- program.command("doctor").description("Run health check and get optimization suggestions").option("--check-guidelines-only", "Only check mandatory guidelines exist (exits 0 or 1)").action(doctorCommand);
3031
+ program.command("doctor").description("Run health check and get optimization suggestions").option(
3032
+ "--check-guidelines-only",
3033
+ "Only check mandatory guidelines exist (exits 0 or 1)"
3034
+ ).action(doctorCommand);
2426
3035
  program.command("hooks").description("Manage git hooks (install, uninstall, status)").argument("<action>", "Action: install, uninstall, status").action(hooksCommand);
2427
3036
  program.command("github").description("Manage GitHub Actions CI (setup, check)").argument("<action>", "Action: setup, check").action(githubCommand);
2428
- program.command("scope:create").description("Create a custom scope package").option("--name <name>", 'Package name (e.g., "fintech", "gaming")').option("--scopes <scopes>", "Comma-separated scopes (format: name:description:emoji:category)").option("--preset-name <preset>", "Preset display name").option("--output-dir <dir>", "Output directory").option("--no-test", "Skip test file generation").action(scopeCreateCommand);
3037
+ program.command("scope:create").description("Create a custom scope package").option("--name <name>", 'Package name (e.g., "fintech", "gaming")').option(
3038
+ "--scopes <scopes>",
3039
+ "Comma-separated scopes (format: name:description:emoji:category)"
3040
+ ).option("--preset-name <preset>", "Preset display name").option("--output-dir <dir>", "Output directory").option("--no-test", "Skip test file generation").action(scopeCreateCommand);
2429
3041
  program.command("scope:migrate").description("Migrate inline scopes to a custom package").option("--name <name>", "Package name for the preset").option("--output-dir <dir>", "Output directory").option("--keep-config", "Keep inline scopes in config after migration").action(scopeMigrateCommand);
2430
3042
  program.parse();
2431
3043
  //# sourceMappingURL=index.js.map