@vibe-validate/cli 0.9.11 → 0.10.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.
Files changed (33) hide show
  1. package/dist/commands/doctor.d.ts.map +1 -1
  2. package/dist/commands/doctor.js +151 -38
  3. package/dist/commands/doctor.js.map +1 -1
  4. package/dist/commands/init.d.ts.map +1 -1
  5. package/dist/commands/init.js +254 -332
  6. package/dist/commands/init.js.map +1 -1
  7. package/dist/utils/config-loader.d.ts +3 -7
  8. package/dist/utils/config-loader.d.ts.map +1 -1
  9. package/dist/utils/config-loader.js +7 -19
  10. package/dist/utils/config-loader.js.map +1 -1
  11. package/dist/utils/git-detection.d.ts +41 -0
  12. package/dist/utils/git-detection.d.ts.map +1 -0
  13. package/dist/utils/git-detection.js +109 -0
  14. package/dist/utils/git-detection.js.map +1 -0
  15. package/dist/utils/runner-adapter.js +3 -3
  16. package/dist/utils/runner-adapter.js.map +1 -1
  17. package/dist/utils/setup-checks/gitignore-check.d.ts +23 -0
  18. package/dist/utils/setup-checks/gitignore-check.d.ts.map +1 -0
  19. package/dist/utils/setup-checks/gitignore-check.js +156 -0
  20. package/dist/utils/setup-checks/gitignore-check.js.map +1 -0
  21. package/dist/utils/setup-checks/hooks-check.d.ts +27 -0
  22. package/dist/utils/setup-checks/hooks-check.d.ts.map +1 -0
  23. package/dist/utils/setup-checks/hooks-check.js +175 -0
  24. package/dist/utils/setup-checks/hooks-check.js.map +1 -0
  25. package/dist/utils/setup-checks/workflow-check.d.ts +22 -0
  26. package/dist/utils/setup-checks/workflow-check.d.ts.map +1 -0
  27. package/dist/utils/setup-checks/workflow-check.js +147 -0
  28. package/dist/utils/setup-checks/workflow-check.js.map +1 -0
  29. package/dist/utils/setup-engine.d.ts +155 -0
  30. package/dist/utils/setup-engine.d.ts.map +1 -0
  31. package/dist/utils/setup-engine.js +31 -0
  32. package/dist/utils/setup-engine.js.map +1 -0
  33. package/package.json +4 -4
@@ -3,61 +3,45 @@
3
3
  *
4
4
  * Interactive setup wizard for vibe-validate configuration.
5
5
  */
6
- import { writeFileSync } from 'fs';
6
+ import { writeFileSync, existsSync } from 'fs';
7
7
  import { join } from 'path';
8
- import { execSync } from 'child_process';
8
+ import { pathToFileURL } from 'url';
9
+ import { dump as stringifyYaml } from 'js-yaml';
9
10
  import chalk from 'chalk';
10
11
  import { configExists } from '../utils/config-loader.js';
11
- import { GIT_DEFAULTS } from '@vibe-validate/config';
12
+ import { detectGitConfig } from '../utils/git-detection.js';
13
+ import { GitignoreSetupCheck } from '../utils/setup-checks/gitignore-check.js';
14
+ import { HooksSetupCheck } from '../utils/setup-checks/hooks-check.js';
15
+ import { WorkflowSetupCheck } from '../utils/setup-checks/workflow-check.js';
12
16
  export function initCommand(program) {
13
17
  program
14
18
  .command('init')
15
19
  .description('Initialize vibe-validate configuration')
16
20
  .option('-p, --preset <preset>', 'Use preset (typescript-library|typescript-nodejs|typescript-react)')
17
21
  .option('-f, --force', 'Overwrite existing configuration')
22
+ .option('--dry-run', 'Preview changes without writing files')
23
+ .option('--setup-hooks', 'Install pre-commit hook')
24
+ .option('--setup-workflow', 'Create GitHub Actions workflow')
25
+ .option('--fix-gitignore', 'Add state file to .gitignore')
26
+ .option('--migrate', 'Migrate .mjs config to .yaml format')
18
27
  .action(async (options) => {
19
28
  try {
20
29
  const cwd = process.cwd();
21
- // Check if config already exists
22
- if (configExists(cwd) && !options.force) {
23
- console.error(chalk.red('❌ Configuration file already exists'));
24
- console.error(chalk.gray(' Use --force to overwrite'));
25
- process.exit(1);
30
+ const isDryRun = options.dryRun || false;
31
+ // Handle migration
32
+ if (options.migrate) {
33
+ await handleMigration(cwd, options, isDryRun);
34
+ return;
26
35
  }
27
- const preset = options.preset || 'typescript-library';
28
- // Validate preset
29
- const validPresets = ['typescript-library', 'typescript-nodejs', 'typescript-react'];
30
- if (!validPresets.includes(preset)) {
31
- console.error(chalk.red(`❌ Invalid preset: ${preset}`));
32
- console.error(chalk.gray(` Valid presets: ${validPresets.join(', ')}`));
33
- process.exit(1);
36
+ // Check if this is a focused operation
37
+ const isFocusedOperation = options.setupHooks || options.setupWorkflow || options.fixGitignore;
38
+ // Handle focused operations
39
+ if (isFocusedOperation) {
40
+ await handleFocusedOperations(cwd, options, isDryRun);
41
+ return;
34
42
  }
35
- // Detect git configuration
36
- const gitConfig = detectGitConfig();
37
- if (gitConfig.detected) {
38
- console.log(chalk.blue('🔍 Auto-detected git configuration:'));
39
- console.log(chalk.gray(` Main branch: ${gitConfig.mainBranch}`));
40
- console.log(chalk.gray(` Remote: ${gitConfig.remoteOrigin}`));
41
- }
42
- else {
43
- console.log(chalk.gray('ℹ️ Using default git configuration (main, origin)'));
44
- }
45
- // Generate config file content
46
- const configContent = generateConfig(preset, gitConfig);
47
- const configPath = join(cwd, 'vibe-validate.config.ts');
48
- // Write config file
49
- writeFileSync(configPath, configContent, 'utf-8');
50
- console.log(chalk.green('✅ Configuration file created successfully'));
51
- console.log(chalk.blue(`📋 Created: ${configPath}`));
52
- console.log(chalk.gray(` Preset: ${preset}`));
53
- console.log();
54
- console.log(chalk.yellow('Next steps:'));
55
- console.log(chalk.gray(' 1. Review and customize vibe-validate.config.ts'));
56
- console.log(chalk.gray(' 2. Run: vibe-validate validate'));
57
- console.log(chalk.gray(' 3. Add to package.json scripts:'));
58
- console.log(chalk.gray(' "validate": "vibe-validate validate"'));
59
- console.log(chalk.gray(' "pre-commit": "vibe-validate pre-commit"'));
60
- process.exit(0);
43
+ // Handle config initialization
44
+ await handleConfigInitialization(cwd, options, isDryRun);
61
45
  }
62
46
  catch (error) {
63
47
  console.error(chalk.red('❌ Failed to initialize configuration:'), error);
@@ -65,309 +49,247 @@ export function initCommand(program) {
65
49
  }
66
50
  });
67
51
  }
68
- function detectGitConfig() {
69
- const defaults = {
70
- mainBranch: GIT_DEFAULTS.MAIN_BRANCH,
71
- remoteOrigin: GIT_DEFAULTS.REMOTE_ORIGIN,
72
- detected: false,
73
- };
74
- try {
75
- // Check if we're in a git repository
76
- execSync('git rev-parse --git-dir', { stdio: 'pipe' });
52
+ /**
53
+ * Handle focused operations (--setup-hooks, --setup-workflow, --fix-gitignore)
54
+ *
55
+ * Executes specific setup tasks independently without creating config files.
56
+ * All operations are idempotent and can be safely run multiple times.
57
+ *
58
+ * @param cwd - Current working directory
59
+ * @param options - Init command options
60
+ * @param isDryRun - Preview mode (no file modifications)
61
+ * @throws Error if setup check fails
62
+ */
63
+ async function handleFocusedOperations(cwd, options, isDryRun) {
64
+ const fixOptions = { cwd, dryRun: isDryRun, force: options.force };
65
+ const operations = [];
66
+ // Setup gitignore check
67
+ if (options.fixGitignore) {
68
+ operations.push({
69
+ name: 'Gitignore',
70
+ check: new GitignoreSetupCheck(),
71
+ enabled: true,
72
+ });
77
73
  }
78
- catch {
79
- // Not a git repository - use defaults
80
- return defaults;
74
+ // Setup hooks check
75
+ if (options.setupHooks) {
76
+ operations.push({
77
+ name: 'Pre-commit hook',
78
+ check: new HooksSetupCheck(),
79
+ enabled: true,
80
+ });
81
81
  }
82
- let mainBranch = GIT_DEFAULTS.MAIN_BRANCH;
83
- let remoteOrigin = GIT_DEFAULTS.REMOTE_ORIGIN;
84
- let detected = false;
85
- // Try to detect main branch from remote HEAD
86
- try {
87
- // First, get list of remotes
88
- const remotesOutput = execSync('git remote', { encoding: 'utf8', stdio: 'pipe' }).trim();
89
- const remotes = remotesOutput.split('\n').filter(Boolean);
90
- if (remotes.length > 0) {
91
- // Prefer 'upstream' if it exists (forked repo workflow), otherwise use first remote
92
- if (remotes.includes('upstream')) {
93
- remoteOrigin = 'upstream';
94
- }
95
- else if (remotes.includes('origin')) {
96
- remoteOrigin = 'origin';
97
- }
98
- else {
99
- remoteOrigin = remotes[0]; // Use first available remote
100
- }
101
- // Try to detect main branch from remote HEAD
102
- try {
103
- const headRef = execSync(`git symbolic-ref refs/remotes/${remoteOrigin}/HEAD`, {
104
- encoding: 'utf8',
105
- stdio: 'pipe',
106
- }).trim();
107
- mainBranch = headRef.replace(`refs/remotes/${remoteOrigin}/`, '');
108
- detected = true;
109
- }
110
- catch {
111
- // Remote HEAD not set, try to detect from common branch names
112
- try {
113
- const branches = execSync(`git ls-remote --heads ${remoteOrigin}`, {
114
- encoding: 'utf8',
115
- stdio: 'pipe',
116
- }).trim();
117
- // Check for common main branch names in order of preference
118
- if (branches.includes('refs/heads/main')) {
119
- mainBranch = 'main';
120
- detected = true;
121
- }
122
- else if (branches.includes('refs/heads/master')) {
123
- mainBranch = 'master';
124
- detected = true;
125
- }
126
- else if (branches.includes('refs/heads/develop')) {
127
- mainBranch = 'develop';
128
- detected = true;
82
+ // Setup workflow check
83
+ if (options.setupWorkflow) {
84
+ operations.push({
85
+ name: 'GitHub Actions workflow',
86
+ check: new WorkflowSetupCheck(),
87
+ enabled: true,
88
+ });
89
+ }
90
+ // Execute operations
91
+ for (const operation of operations) {
92
+ if (!operation.enabled)
93
+ continue;
94
+ if (isDryRun) {
95
+ // Preview mode
96
+ const preview = await operation.check.preview(fixOptions);
97
+ console.log(chalk.blue(`\n🔍 ${operation.name} (dry-run):`));
98
+ console.log(chalk.gray(` ${preview.description}`));
99
+ if (preview.changes && preview.changes.length > 0) {
100
+ console.log(chalk.yellow(' Would create:'));
101
+ for (const change of preview.changes) {
102
+ console.log(chalk.gray(` - ${change.file} (${change.action})`));
103
+ if (change.content && change.content.length < 500) {
104
+ console.log(chalk.gray('\n' + change.content));
129
105
  }
130
106
  }
131
- catch {
132
- // Failed to list remote branches - use defaults
107
+ }
108
+ }
109
+ else {
110
+ // Fix mode
111
+ const result = await operation.check.fix(fixOptions);
112
+ if (result.success) {
113
+ if (result.filesChanged.length > 0) {
114
+ console.log(chalk.green(`✅ ${operation.name}: ${result.message}`));
133
115
  }
116
+ else {
117
+ console.log(chalk.gray(`ℹ️ ${operation.name}: ${result.message}`));
118
+ }
119
+ }
120
+ else {
121
+ console.error(chalk.red(`❌ ${operation.name}: ${result.message}`));
134
122
  }
135
123
  }
136
124
  }
137
- catch {
138
- // Failed to detect - use defaults
125
+ if (isDryRun) {
126
+ console.log(chalk.yellow('\n💡 Run without --dry-run to apply changes'));
139
127
  }
140
- return {
141
- mainBranch,
142
- remoteOrigin,
143
- detected,
144
- };
128
+ process.exit(0);
145
129
  }
146
130
  /**
147
- * Generate configuration content based on preset
131
+ * Handle config file initialization
132
+ *
133
+ * Creates a new vibe-validate configuration file using the specified preset.
134
+ * Auto-detects git configuration and generates appropriate defaults.
135
+ *
136
+ * @param cwd - Current working directory
137
+ * @param options - Init command options
138
+ * @param isDryRun - Preview mode (no file modifications)
139
+ * @throws Error if config already exists (unless force is true)
140
+ */
141
+ async function handleConfigInitialization(cwd, options, isDryRun) {
142
+ // Check if config already exists
143
+ if (configExists(cwd) && !options.force && !isDryRun) {
144
+ console.error(chalk.red('❌ Configuration file already exists'));
145
+ console.error(chalk.gray(' Use --force to overwrite'));
146
+ process.exit(1);
147
+ }
148
+ const preset = options.preset || 'typescript-library';
149
+ // Validate preset
150
+ const validPresets = ['typescript-library', 'typescript-nodejs', 'typescript-react'];
151
+ if (!validPresets.includes(preset)) {
152
+ console.error(chalk.red(`❌ Invalid preset: ${preset}`));
153
+ console.error(chalk.gray(` Valid presets: ${validPresets.join(', ')}`));
154
+ process.exit(1);
155
+ }
156
+ // Detect git configuration
157
+ const gitConfig = detectGitConfig();
158
+ if (!isDryRun) {
159
+ if (gitConfig.detected) {
160
+ console.log(chalk.blue('🔍 Auto-detected git configuration:'));
161
+ console.log(chalk.gray(` Main branch: ${gitConfig.mainBranch}`));
162
+ console.log(chalk.gray(` Remote: ${gitConfig.remoteOrigin}`));
163
+ }
164
+ else {
165
+ console.log(chalk.gray('ℹ️ Using default git configuration (main, origin)'));
166
+ }
167
+ }
168
+ // Generate YAML config file content
169
+ const configContent = generateYamlConfig(preset, gitConfig);
170
+ const configPath = join(cwd, 'vibe-validate.config.yaml');
171
+ if (isDryRun) {
172
+ // Preview mode - show what would be created
173
+ console.log(chalk.blue('🔍 Configuration preview (dry-run):'));
174
+ console.log(chalk.yellow(' Would create:'));
175
+ console.log(chalk.gray(` - ${configPath}`));
176
+ console.log(chalk.gray(` - Preset: ${preset}`));
177
+ console.log();
178
+ console.log(chalk.yellow('💡 Run without --dry-run to create configuration'));
179
+ process.exit(0);
180
+ }
181
+ // Write config file
182
+ writeFileSync(configPath, configContent, 'utf-8');
183
+ console.log(chalk.green('✅ Configuration file created successfully'));
184
+ console.log(chalk.blue(`📋 Created: ${configPath}`));
185
+ console.log(chalk.gray(` Preset: ${preset}`));
186
+ console.log();
187
+ console.log(chalk.yellow('Next steps:'));
188
+ console.log(chalk.gray(' 1. Review and customize vibe-validate.config.yaml'));
189
+ console.log(chalk.gray(' 2. Run: vibe-validate validate'));
190
+ console.log(chalk.gray(' 3. Add to package.json scripts:'));
191
+ console.log(chalk.gray(' "validate": "vibe-validate validate"'));
192
+ console.log(chalk.gray(' "pre-commit": "vibe-validate pre-commit"'));
193
+ process.exit(0);
194
+ }
195
+ /**
196
+ * Generate YAML configuration content based on preset
197
+ *
198
+ * Creates YAML configuration file content with the specified preset
199
+ * and git configuration values.
200
+ *
201
+ * @param preset - Preset name (typescript-library, typescript-nodejs, typescript-react)
202
+ * @param gitConfig - Detected git configuration
203
+ * @returns YAML configuration file content
148
204
  */
149
- function generateConfig(preset, gitConfig) {
150
- const configs = {
151
- 'typescript-library': `import { defineConfig } from '@vibe-validate/config';
152
-
153
- export default defineConfig({
154
- // Use TypeScript library preset as base
155
- extends: 'typescript-library',
156
-
157
- validation: {
158
- phases: [
159
- // Phase 1: Fast Pre-Qualification (parallel)
160
- {
161
- name: 'Pre-Qualification',
162
- parallel: true,
163
- steps: [
164
- {
165
- name: 'TypeScript Type Check',
166
- command: 'tsc --noEmit',
167
- description: 'Type-check TypeScript files',
168
- },
169
- {
170
- name: 'ESLint',
171
- command: 'eslint src/',
172
- description: 'Lint source code',
173
- },
174
- ],
175
- },
176
-
177
- // Phase 2: Unit Tests
178
- {
179
- name: 'Testing',
180
- parallel: false,
181
- steps: [
182
- {
183
- name: 'Unit Tests',
184
- command: 'npm test',
185
- description: 'Run unit tests with coverage',
186
- },
187
- ],
188
- },
189
-
190
- // Phase 3: Build Verification
191
- {
192
- name: 'Build',
193
- parallel: false,
194
- steps: [
195
- {
196
- name: 'Build Package',
197
- command: 'npm run build',
198
- description: 'Build TypeScript to JavaScript',
199
- },
200
- ],
201
- },
202
- ],
203
-
204
- // Use git tree hash caching for maximum performance
205
- caching: {
206
- strategy: 'git-tree-hash',
207
- enabled: true,
208
- },
209
-
210
- // Fail fast on first error
211
- failFast: true,
212
- },
213
-
214
- // Git integration settings
215
- git: {
216
- mainBranch: '${gitConfig.mainBranch}',
217
- remoteOrigin: '${gitConfig.remoteOrigin}',
218
- autoSync: false, // Never auto-merge - safety first
219
- },
220
-
221
- // Output configuration - state files are always written as YAML
222
- });
223
- `,
224
- 'typescript-nodejs': `import { defineConfig } from '@vibe-validate/config';
225
-
226
- export default defineConfig({
227
- // Use TypeScript Node.js preset as base
228
- extends: 'typescript-nodejs',
229
-
230
- validation: {
231
- phases: [
232
- // Phase 1: Fast Pre-Qualification (parallel)
233
- {
234
- name: 'Pre-Qualification',
235
- parallel: true,
236
- steps: [
237
- {
238
- name: 'TypeScript Type Check',
239
- command: 'tsc --noEmit',
240
- description: 'Type-check TypeScript files',
241
- },
242
- {
243
- name: 'ESLint',
244
- command: 'eslint src/',
245
- description: 'Lint source code',
246
- },
247
- ],
248
- },
249
-
250
- // Phase 2: Unit Tests
251
- {
252
- name: 'Testing',
253
- parallel: false,
254
- steps: [
255
- {
256
- name: 'Unit Tests',
257
- command: 'npm test',
258
- description: 'Run unit tests with coverage',
259
- },
260
- ],
261
- },
262
-
263
- // Phase 3: Build Verification
264
- {
265
- name: 'Build',
266
- parallel: false,
267
- steps: [
268
- {
269
- name: 'Build Application',
270
- command: 'npm run build',
271
- description: 'Build TypeScript to JavaScript',
272
- },
273
- ],
274
- },
275
- ],
276
-
277
- // Use git tree hash caching for maximum performance
278
- caching: {
279
- strategy: 'git-tree-hash',
280
- enabled: true,
281
- },
282
-
283
- // Fail fast on first error
284
- failFast: true,
285
- },
286
-
287
- // Git integration settings
288
- git: {
289
- mainBranch: '${gitConfig.mainBranch}',
290
- remoteOrigin: '${gitConfig.remoteOrigin}',
291
- autoSync: false, // Never auto-merge - safety first
292
- },
293
-
294
- // Output configuration - state files are always written as YAML
295
- });
296
- `,
297
- 'typescript-react': `import { defineConfig } from '@vibe-validate/config';
298
-
299
- export default defineConfig({
300
- // Use TypeScript React preset as base
301
- extends: 'typescript-react',
302
-
303
- validation: {
304
- phases: [
305
- // Phase 1: Fast Pre-Qualification (parallel)
306
- {
307
- name: 'Pre-Qualification',
308
- parallel: true,
309
- steps: [
310
- {
311
- name: 'TypeScript Type Check',
312
- command: 'tsc --noEmit',
313
- description: 'Type-check TypeScript and React files',
314
- },
315
- {
316
- name: 'ESLint',
317
- command: 'eslint src/',
318
- description: 'Lint source code with React rules',
319
- },
320
- ],
321
- },
322
-
323
- // Phase 2: Unit Tests
324
- {
325
- name: 'Testing',
326
- parallel: false,
327
- steps: [
328
- {
329
- name: 'Unit Tests',
330
- command: 'npm test',
331
- description: 'Run unit tests with coverage',
332
- },
333
- ],
334
- },
335
-
336
- // Phase 3: Build Verification
337
- {
338
- name: 'Build',
339
- parallel: false,
340
- steps: [
341
- {
342
- name: 'Build Application',
343
- command: 'npm run build',
344
- description: 'Build React application for production',
345
- },
346
- ],
347
- },
348
- ],
349
-
350
- // Use git tree hash caching for maximum performance
351
- caching: {
352
- strategy: 'git-tree-hash',
353
- enabled: true,
354
- },
355
-
356
- // Fail fast on first error
357
- failFast: true,
358
- },
359
-
360
- // Git integration settings
361
- git: {
362
- mainBranch: '${gitConfig.mainBranch}',
363
- remoteOrigin: '${gitConfig.remoteOrigin}',
364
- autoSync: false, // Never auto-merge - safety first
365
- },
366
-
367
- // Output configuration - state files are always written as YAML
368
- });
369
- `,
205
+ function generateYamlConfig(preset, gitConfig) {
206
+ const baseConfig = {
207
+ // JSON Schema for IDE validation
208
+ $schema: 'https://raw.githubusercontent.com/jdutton/vibe-validate/main/packages/config/vibe-validate.schema.json',
209
+ // Use preset as base configuration
210
+ extends: preset,
211
+ // Git integration settings
212
+ git: {
213
+ mainBranch: gitConfig.mainBranch,
214
+ remoteOrigin: gitConfig.remoteOrigin,
215
+ autoSync: false, // Never auto-merge - safety first
216
+ },
217
+ // Validation configuration (from preset)
218
+ validation: {
219
+ caching: {
220
+ strategy: 'git-tree-hash',
221
+ enabled: true,
222
+ },
223
+ failFast: true,
224
+ },
370
225
  };
371
- return configs[preset] || configs['typescript-library'];
226
+ return stringifyYaml(baseConfig, {
227
+ indent: 2,
228
+ lineWidth: 100,
229
+ noRefs: true,
230
+ });
231
+ }
232
+ /**
233
+ * Handle migration from .mjs to .yaml config format
234
+ *
235
+ * Loads the existing .mjs configuration, converts it to YAML format,
236
+ * and writes it to vibe-validate.config.yaml.
237
+ *
238
+ * @param cwd - Current working directory
239
+ * @param options - Init command options
240
+ * @param isDryRun - Preview mode (no file modifications)
241
+ * @throws Error if .mjs config doesn't exist or .yaml already exists (without --force)
242
+ */
243
+ async function handleMigration(cwd, options, isDryRun) {
244
+ const mjsPath = join(cwd, 'vibe-validate.config.mjs');
245
+ const yamlPath = join(cwd, 'vibe-validate.config.yaml');
246
+ // Check if .mjs config exists
247
+ if (!existsSync(mjsPath)) {
248
+ console.error(chalk.red('❌ No .mjs config found to migrate'));
249
+ console.error(chalk.gray(' Expected: vibe-validate.config.mjs'));
250
+ process.exit(1);
251
+ }
252
+ // Check if .yaml config already exists (unless --force)
253
+ if (existsSync(yamlPath) && !options.force && !isDryRun) {
254
+ console.error(chalk.red('❌ YAML config already exists'));
255
+ console.error(chalk.gray(' Use --force to overwrite'));
256
+ process.exit(1);
257
+ }
258
+ // Load the .mjs config
259
+ const fileUrl = pathToFileURL(mjsPath).href;
260
+ const module = await import(fileUrl);
261
+ const config = module.default || module;
262
+ // Convert to YAML
263
+ const yamlContent = stringifyYaml(config, {
264
+ indent: 2,
265
+ lineWidth: 100,
266
+ noRefs: true,
267
+ });
268
+ if (isDryRun) {
269
+ // Preview mode
270
+ console.log(chalk.blue('🔍 Migration preview (dry-run):'));
271
+ console.log(chalk.yellow(' Would create:'));
272
+ console.log(chalk.gray(` - ${yamlPath}`));
273
+ console.log();
274
+ console.log(chalk.gray('Preview of YAML content:'));
275
+ console.log(chalk.gray('─'.repeat(60)));
276
+ console.log(yamlContent);
277
+ console.log(chalk.gray('─'.repeat(60)));
278
+ console.log();
279
+ console.log(chalk.yellow('💡 Run without --dry-run to apply migration'));
280
+ console.log(chalk.gray(' Original .mjs file will be preserved (you can delete it manually)'));
281
+ process.exit(0);
282
+ }
283
+ // Write YAML config
284
+ writeFileSync(yamlPath, yamlContent, 'utf-8');
285
+ console.log(chalk.green('✅ Migration completed successfully'));
286
+ console.log(chalk.blue(`📋 Created: ${yamlPath}`));
287
+ console.log();
288
+ console.log(chalk.yellow('Next steps:'));
289
+ console.log(chalk.gray(' 1. Review vibe-validate.config.yaml'));
290
+ console.log(chalk.gray(' 2. Test with: vibe-validate validate'));
291
+ console.log(chalk.gray(` 3. Delete old config: rm ${mjsPath}`));
292
+ console.log(chalk.gray(' 4. Commit the new YAML config'));
293
+ process.exit(0);
372
294
  }
373
295
  //# sourceMappingURL=init.js.map