kiro-spec-engine 1.0.0 → 1.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.
@@ -0,0 +1,231 @@
1
+ /**
2
+ * Adopt Command
3
+ *
4
+ * Intelligently adopts existing projects into kiro-spec-engine.
5
+ * Supports fresh, partial, and full adoption modes.
6
+ */
7
+
8
+ const chalk = require('chalk');
9
+ const inquirer = require('inquirer');
10
+ const path = require('path');
11
+ const DetectionEngine = require('../adoption/detection-engine');
12
+ const { getAdoptionStrategy } = require('../adoption/adoption-strategy');
13
+ const BackupSystem = require('../backup/backup-system');
14
+ const VersionManager = require('../version/version-manager');
15
+
16
+ /**
17
+ * Executes the adopt command
18
+ *
19
+ * @param {Object} options - Command options
20
+ * @param {boolean} options.auto - Skip confirmations
21
+ * @param {boolean} options.dryRun - Show what would change without making changes
22
+ * @param {string} options.mode - Force specific adoption mode (fresh/partial/full)
23
+ * @returns {Promise<void>}
24
+ */
25
+ async function adoptCommand(options = {}) {
26
+ const { auto = false, dryRun = false, mode: forcedMode = null } = options;
27
+ const projectPath = process.cwd();
28
+
29
+ console.log(chalk.red('🔥') + ' Kiro Spec Engine - Project Adoption');
30
+ console.log();
31
+
32
+ try {
33
+ // 1. Detect project structure
34
+ console.log(chalk.blue('📦 Analyzing project structure...'));
35
+ const detectionEngine = new DetectionEngine();
36
+ const detection = await detectionEngine.analyze(projectPath);
37
+
38
+ // 2. Determine strategy
39
+ const strategy = forcedMode || detectionEngine.determineStrategy(detection);
40
+
41
+ // 3. Show analysis to user
42
+ console.log();
43
+ console.log(detectionEngine.getSummary(detection));
44
+ console.log();
45
+
46
+ // 4. Show adoption plan
47
+ console.log(chalk.blue('📋 Adoption Plan:'));
48
+ console.log(` Mode: ${chalk.cyan(strategy)}`);
49
+
50
+ if (strategy === 'fresh') {
51
+ console.log(' Actions:');
52
+ console.log(' - Create .kiro/ directory structure');
53
+ console.log(' - Copy template files (steering, tools, docs)');
54
+ console.log(' - Create version.json');
55
+ } else if (strategy === 'partial') {
56
+ console.log(' Actions:');
57
+ console.log(' - Preserve existing specs/ and steering/');
58
+ console.log(' - Add missing components');
59
+ console.log(' - Create/update version.json');
60
+ if (detection.hasKiroDir) {
61
+ console.log(' - Create backup before changes');
62
+ }
63
+ } else if (strategy === 'full') {
64
+ console.log(' Actions:');
65
+ console.log(` - Upgrade from ${detection.existingVersion || 'unknown'} to current version`);
66
+ console.log(' - Update template files');
67
+ console.log(' - Preserve user content (specs/)');
68
+ console.log(' - Create backup before changes');
69
+ }
70
+
71
+ // Show conflicts if any
72
+ if (detection.conflicts.length > 0) {
73
+ console.log();
74
+ console.log(chalk.yellow('⚠️ Conflicts detected:'));
75
+ detection.conflicts.forEach(conflict => {
76
+ console.log(` - ${conflict.path}`);
77
+ });
78
+ console.log(' Existing files will be preserved, template files will be skipped');
79
+ }
80
+
81
+ console.log();
82
+
83
+ // 5. Dry run mode
84
+ if (dryRun) {
85
+ console.log(chalk.yellow('🔍 Dry run mode - no changes will be made'));
86
+ console.log();
87
+
88
+ const adoptionStrategy = getAdoptionStrategy(strategy);
89
+ const versionManager = new VersionManager();
90
+ const packageJson = require('../../package.json');
91
+
92
+ const result = await adoptionStrategy.execute(projectPath, strategy, {
93
+ kseVersion: packageJson.version,
94
+ dryRun: true
95
+ });
96
+
97
+ if (result.success) {
98
+ console.log(chalk.green('✅ Dry run completed successfully'));
99
+ console.log();
100
+ console.log('Files that would be created:');
101
+ result.filesCreated.forEach(file => console.log(` + ${file}`));
102
+ if (result.filesUpdated.length > 0) {
103
+ console.log('Files that would be updated:');
104
+ result.filesUpdated.forEach(file => console.log(` ~ ${file}`));
105
+ }
106
+ if (result.filesSkipped.length > 0) {
107
+ console.log('Files that would be skipped:');
108
+ result.filesSkipped.forEach(file => console.log(` - ${file}`));
109
+ }
110
+ } else {
111
+ console.log(chalk.red('❌ Dry run failed'));
112
+ result.errors.forEach(error => console.log(` ${error}`));
113
+ }
114
+
115
+ return;
116
+ }
117
+
118
+ // 6. Confirm with user (unless --auto)
119
+ if (!auto) {
120
+ const { confirmed } = await inquirer.prompt([
121
+ {
122
+ type: 'confirm',
123
+ name: 'confirmed',
124
+ message: 'Proceed with adoption?',
125
+ default: true
126
+ }
127
+ ]);
128
+
129
+ if (!confirmed) {
130
+ console.log(chalk.yellow('Adoption cancelled'));
131
+ return;
132
+ }
133
+ }
134
+
135
+ console.log();
136
+
137
+ // 7. Create backup if needed
138
+ let backupId = null;
139
+ if (detection.hasKiroDir && (strategy === 'partial' || strategy === 'full')) {
140
+ console.log(chalk.blue('📦 Creating backup...'));
141
+ const backupSystem = new BackupSystem();
142
+
143
+ try {
144
+ const backup = await backupSystem.createBackup(projectPath, { type: 'adopt' });
145
+ backupId = backup.id;
146
+ console.log(chalk.green(`✅ Backup created: ${backupId}`));
147
+ } catch (error) {
148
+ console.log(chalk.red(`❌ Failed to create backup: ${error.message}`));
149
+ console.log(chalk.yellow('Aborting adoption for safety'));
150
+ return;
151
+ }
152
+ }
153
+
154
+ console.log();
155
+
156
+ // 8. Execute adoption
157
+ console.log(chalk.blue('🚀 Executing adoption...'));
158
+ const adoptionStrategy = getAdoptionStrategy(strategy);
159
+ const packageJson = require('../../package.json');
160
+
161
+ const result = await adoptionStrategy.execute(projectPath, strategy, {
162
+ kseVersion: packageJson.version,
163
+ dryRun: false,
164
+ backupId
165
+ });
166
+
167
+ console.log();
168
+
169
+ // 9. Report results
170
+ if (result.success) {
171
+ console.log(chalk.green('✅ Adoption completed successfully!'));
172
+ console.log();
173
+
174
+ if (result.filesCreated.length > 0) {
175
+ console.log(chalk.blue('Files created:'));
176
+ result.filesCreated.forEach(file => console.log(` + ${file}`));
177
+ }
178
+
179
+ if (result.filesUpdated.length > 0) {
180
+ console.log(chalk.blue('Files updated:'));
181
+ result.filesUpdated.forEach(file => console.log(` ~ ${file}`));
182
+ }
183
+
184
+ if (result.filesSkipped.length > 0) {
185
+ console.log(chalk.gray('Files skipped:'));
186
+ result.filesSkipped.forEach(file => console.log(` - ${file}`));
187
+ }
188
+
189
+ if (result.warnings.length > 0) {
190
+ console.log();
191
+ console.log(chalk.yellow('⚠️ Warnings:'));
192
+ result.warnings.forEach(warning => console.log(` ${warning}`));
193
+ }
194
+
195
+ if (backupId) {
196
+ console.log();
197
+ console.log(chalk.blue('📦 Backup:'), backupId);
198
+ console.log(chalk.gray(' Run'), chalk.cyan('kse rollback'), chalk.gray('if you need to undo changes'));
199
+ }
200
+
201
+ console.log();
202
+ console.log(chalk.blue('💡 Next steps:'));
203
+ console.log(' 1. Review the .kiro/ directory structure');
204
+ console.log(' 2. Create your first spec: ' + chalk.cyan('kse create-spec my-feature'));
205
+ console.log(' 3. Check project status: ' + chalk.cyan('kse status'));
206
+ console.log();
207
+ console.log(chalk.red('🔥') + ' Ready to build with Kiro Spec Engine!');
208
+ } else {
209
+ console.log(chalk.red('❌ Adoption failed'));
210
+ console.log();
211
+ result.errors.forEach(error => console.log(chalk.red(` ${error}`)));
212
+
213
+ if (backupId) {
214
+ console.log();
215
+ console.log(chalk.blue('📦 Backup available:'), backupId);
216
+ console.log(chalk.gray(' Run'), chalk.cyan('kse rollback'), chalk.gray('to restore'));
217
+ }
218
+
219
+ process.exit(1);
220
+ }
221
+ } catch (error) {
222
+ console.log();
223
+ console.log(chalk.red('❌ Error:'), error.message);
224
+ console.log();
225
+ console.log(chalk.gray('If you need help, please report this issue:'));
226
+ console.log(chalk.cyan('https://github.com/heguangyong/kiro-spec-engine/issues'));
227
+ process.exit(1);
228
+ }
229
+ }
230
+
231
+ module.exports = adoptCommand;
@@ -0,0 +1,219 @@
1
+ /**
2
+ * Rollback Command
3
+ *
4
+ * Restores project from a backup.
5
+ * Provides safety net for failed adoptions or upgrades.
6
+ */
7
+
8
+ const chalk = require('chalk');
9
+ const inquirer = require('inquirer');
10
+ const BackupSystem = require('../backup/backup-system');
11
+
12
+ /**
13
+ * Executes the rollback command
14
+ *
15
+ * @param {Object} options - Command options
16
+ * @param {boolean} options.auto - Skip confirmations
17
+ * @param {string} options.backup - Specific backup ID to restore
18
+ * @returns {Promise<void>}
19
+ */
20
+ async function rollbackCommand(options = {}) {
21
+ const { auto = false, backup: backupId = null } = options;
22
+ const projectPath = process.cwd();
23
+
24
+ console.log(chalk.red('🔥') + ' Kiro Spec Engine - Rollback');
25
+ console.log();
26
+
27
+ try {
28
+ const backupSystem = new BackupSystem();
29
+
30
+ // 1. List available backups
31
+ console.log(chalk.blue('📦 Loading backups...'));
32
+ const backups = await backupSystem.listBackups(projectPath);
33
+
34
+ if (backups.length === 0) {
35
+ console.log(chalk.yellow('⚠️ No backups found'));
36
+ console.log();
37
+ console.log(chalk.gray('Backups are created automatically during:'));
38
+ console.log(' - Project adoption (kse adopt)');
39
+ console.log(' - Version upgrades (kse upgrade)');
40
+ return;
41
+ }
42
+
43
+ console.log();
44
+ console.log(chalk.blue('Available backups:'));
45
+ backups.forEach((backup, index) => {
46
+ const date = new Date(backup.created).toLocaleString();
47
+ const size = (backup.size / 1024).toFixed(1);
48
+ console.log(` ${index + 1}. ${chalk.cyan(backup.id)}`);
49
+ console.log(` Type: ${backup.type}`);
50
+ console.log(` Version: ${backup.version}`);
51
+ console.log(` Created: ${date}`);
52
+ console.log(` Size: ${size} KB (${backup.files} files)`);
53
+ console.log();
54
+ });
55
+
56
+ // 2. Select backup
57
+ let selectedBackup;
58
+
59
+ if (backupId) {
60
+ // Use specified backup ID
61
+ selectedBackup = backups.find(b => b.id === backupId);
62
+
63
+ if (!selectedBackup) {
64
+ console.log(chalk.red(`❌ Backup not found: ${backupId}`));
65
+ console.log();
66
+ console.log(chalk.gray('Available backups:'));
67
+ backups.forEach(b => console.log(` - ${b.id}`));
68
+ return;
69
+ }
70
+ } else {
71
+ // Interactive selection
72
+ const { selection } = await inquirer.prompt([
73
+ {
74
+ type: 'list',
75
+ name: 'selection',
76
+ message: 'Select backup to restore:',
77
+ choices: backups.map((backup, index) => ({
78
+ name: `${backup.id} (${backup.type}, ${new Date(backup.created).toLocaleString()})`,
79
+ value: index
80
+ }))
81
+ }
82
+ ]);
83
+
84
+ selectedBackup = backups[selection];
85
+ }
86
+
87
+ console.log();
88
+ console.log(chalk.blue('Selected backup:'));
89
+ console.log(` ID: ${chalk.cyan(selectedBackup.id)}`);
90
+ console.log(` Type: ${selectedBackup.type}`);
91
+ console.log(` Version: ${selectedBackup.version}`);
92
+ console.log(` Created: ${new Date(selectedBackup.created).toLocaleString()}`);
93
+ console.log();
94
+
95
+ // 3. Validate backup
96
+ console.log(chalk.blue('🔍 Validating backup...'));
97
+ const isValid = await backupSystem.validateBackup(selectedBackup.path);
98
+
99
+ if (!isValid) {
100
+ console.log(chalk.red('❌ Backup validation failed'));
101
+ console.log();
102
+ console.log(chalk.yellow('This backup may be corrupted or incomplete.'));
103
+ console.log(chalk.gray('Proceeding with restore may cause data loss.'));
104
+
105
+ if (!auto) {
106
+ const { proceed } = await inquirer.prompt([
107
+ {
108
+ type: 'confirm',
109
+ name: 'proceed',
110
+ message: 'Proceed anyway? (not recommended)',
111
+ default: false
112
+ }
113
+ ]);
114
+
115
+ if (!proceed) {
116
+ console.log(chalk.yellow('Rollback cancelled'));
117
+ return;
118
+ }
119
+ } else {
120
+ console.log(chalk.red('Aborting rollback (use --force to override)'));
121
+ return;
122
+ }
123
+ } else {
124
+ console.log(chalk.green('✅ Backup is valid'));
125
+ }
126
+
127
+ console.log();
128
+
129
+ // 4. Confirm with user (unless --auto)
130
+ if (!auto) {
131
+ console.log(chalk.yellow('⚠️ Warning: This will replace your current .kiro/ directory'));
132
+ console.log(chalk.gray('A backup of the current state will be created first'));
133
+ console.log();
134
+
135
+ const { confirmed } = await inquirer.prompt([
136
+ {
137
+ type: 'confirm',
138
+ name: 'confirmed',
139
+ message: `Restore from backup ${selectedBackup.id}?`,
140
+ default: false
141
+ }
142
+ ]);
143
+
144
+ if (!confirmed) {
145
+ console.log(chalk.yellow('Rollback cancelled'));
146
+ return;
147
+ }
148
+ }
149
+
150
+ console.log();
151
+
152
+ // 5. Create backup of current state
153
+ console.log(chalk.blue('📦 Creating backup of current state...'));
154
+
155
+ let currentBackup;
156
+ try {
157
+ currentBackup = await backupSystem.createBackup(projectPath, { type: 'pre-rollback' });
158
+ console.log(chalk.green(`✅ Current state backed up: ${currentBackup.id}`));
159
+ } catch (error) {
160
+ console.log(chalk.yellow(`⚠️ Could not create backup: ${error.message}`));
161
+ console.log(chalk.gray('Continuing with rollback...'));
162
+ }
163
+
164
+ console.log();
165
+
166
+ // 6. Restore from backup
167
+ console.log(chalk.blue('🔄 Restoring from backup...'));
168
+
169
+ const result = await backupSystem.restore(projectPath, selectedBackup.id);
170
+
171
+ console.log();
172
+
173
+ // 7. Report results
174
+ if (result.success) {
175
+ console.log(chalk.green('✅ Rollback completed successfully!'));
176
+ console.log();
177
+ console.log(` Restored ${result.filesRestored} files from backup`);
178
+ console.log(` Backup: ${chalk.cyan(selectedBackup.id)}`);
179
+
180
+ if (currentBackup) {
181
+ console.log();
182
+ console.log(chalk.blue('📦 Previous state backed up:'), currentBackup.id);
183
+ console.log(chalk.gray(' You can restore it if needed'));
184
+ }
185
+
186
+ console.log();
187
+ console.log(chalk.blue('💡 Next steps:'));
188
+ console.log(' 1. Verify your project is working correctly');
189
+ console.log(' 2. Check project status: ' + chalk.cyan('kse status'));
190
+ console.log();
191
+ console.log(chalk.red('🔥') + ' Rollback complete!');
192
+ } else {
193
+ console.log(chalk.red('❌ Rollback failed'));
194
+ console.log();
195
+ console.log(chalk.red('This is a critical error. Your project may be in an inconsistent state.'));
196
+
197
+ if (currentBackup) {
198
+ console.log();
199
+ console.log(chalk.blue('📦 Pre-rollback backup available:'), currentBackup.id);
200
+ console.log(chalk.gray(' You may be able to restore from this backup'));
201
+ }
202
+
203
+ console.log();
204
+ console.log(chalk.gray('Please report this issue:'));
205
+ console.log(chalk.cyan('https://github.com/heguangyong/kiro-spec-engine/issues'));
206
+
207
+ process.exit(1);
208
+ }
209
+ } catch (error) {
210
+ console.log();
211
+ console.log(chalk.red('❌ Error:'), error.message);
212
+ console.log();
213
+ console.log(chalk.gray('If you need help, please report this issue:'));
214
+ console.log(chalk.cyan('https://github.com/heguangyong/kiro-spec-engine/issues'));
215
+ process.exit(1);
216
+ }
217
+ }
218
+
219
+ module.exports = rollbackCommand;
@@ -0,0 +1,231 @@
1
+ /**
2
+ * Upgrade Command
3
+ *
4
+ * Upgrades project to a newer version of kiro-spec-engine.
5
+ * Handles incremental upgrades and migration scripts.
6
+ */
7
+
8
+ const chalk = require('chalk');
9
+ const inquirer = require('inquirer');
10
+ const path = require('path');
11
+ const VersionManager = require('../version/version-manager');
12
+ const MigrationEngine = require('../upgrade/migration-engine');
13
+ const BackupSystem = require('../backup/backup-system');
14
+
15
+ /**
16
+ * Executes the upgrade command
17
+ *
18
+ * @param {Object} options - Command options
19
+ * @param {boolean} options.auto - Skip confirmations
20
+ * @param {boolean} options.dryRun - Show upgrade plan without making changes
21
+ * @param {string} options.to - Target version (default: current kse version)
22
+ * @returns {Promise<void>}
23
+ */
24
+ async function upgradeCommand(options = {}) {
25
+ const { auto = false, dryRun = false, to: targetVersion = null } = options;
26
+ const projectPath = process.cwd();
27
+
28
+ console.log(chalk.red('🔥') + ' Kiro Spec Engine - Project Upgrade');
29
+ console.log();
30
+
31
+ try {
32
+ const versionManager = new VersionManager();
33
+ const migrationEngine = new MigrationEngine();
34
+ const packageJson = require('../../package.json');
35
+
36
+ // 1. Read current version
37
+ console.log(chalk.blue('📦 Checking project version...'));
38
+ const currentVersionInfo = await versionManager.readVersion(projectPath);
39
+
40
+ if (!currentVersionInfo) {
41
+ console.log(chalk.red('❌ No version.json found'));
42
+ console.log();
43
+ console.log(chalk.yellow('This project may not be initialized with kse.'));
44
+ console.log(chalk.gray('Run'), chalk.cyan('kse adopt'), chalk.gray('to adopt this project first.'));
45
+ return;
46
+ }
47
+
48
+ const currentVersion = currentVersionInfo['kse-version'];
49
+ const targetVer = targetVersion || packageJson.version;
50
+
51
+ console.log(` Current version: ${chalk.cyan(currentVersion)}`);
52
+ console.log(` Target version: ${chalk.cyan(targetVer)}`);
53
+ console.log();
54
+
55
+ // 2. Check if upgrade is needed
56
+ if (!versionManager.needsUpgrade(currentVersion, targetVer)) {
57
+ console.log(chalk.green(`✅ Already at version ${targetVer}`));
58
+ console.log(chalk.gray('No upgrade needed'));
59
+ return;
60
+ }
61
+
62
+ // 3. Plan upgrade
63
+ console.log(chalk.blue('📋 Planning upgrade...'));
64
+ const plan = await migrationEngine.planUpgrade(currentVersion, targetVer);
65
+
66
+ console.log();
67
+ console.log(chalk.blue('Upgrade Plan:'));
68
+ console.log(` From: ${chalk.cyan(plan.fromVersion)}`);
69
+ console.log(` To: ${chalk.cyan(plan.toVersion)}`);
70
+ console.log(` Path: ${plan.path.map(v => chalk.cyan(v)).join(' → ')}`);
71
+ console.log(` Estimated time: ${plan.estimatedTime}`);
72
+
73
+ if (plan.migrations.length > 0) {
74
+ console.log();
75
+ console.log(chalk.blue('Migrations:'));
76
+ plan.migrations.forEach((migration, index) => {
77
+ const icon = migration.breaking ? chalk.red('⚠️ ') : chalk.green('✅');
78
+ const label = migration.breaking ? chalk.red('BREAKING') : chalk.green('safe');
79
+ console.log(` ${index + 1}. ${migration.from} → ${migration.to} [${label}]`);
80
+ if (migration.script) {
81
+ console.log(` Script: ${chalk.gray(path.basename(migration.script))}`);
82
+ } else {
83
+ console.log(` ${chalk.gray('No migration script needed')}`);
84
+ }
85
+ });
86
+ } else {
87
+ console.log();
88
+ console.log(chalk.gray('No migrations needed'));
89
+ }
90
+
91
+ console.log();
92
+
93
+ // 4. Dry run mode
94
+ if (dryRun) {
95
+ console.log(chalk.yellow('🔍 Dry run mode - no changes will be made'));
96
+ console.log();
97
+
98
+ const result = await migrationEngine.executeUpgrade(projectPath, plan, {
99
+ dryRun: true
100
+ });
101
+
102
+ if (result.success) {
103
+ console.log(chalk.green('✅ Dry run completed successfully'));
104
+ console.log();
105
+ console.log('Migrations that would be executed:');
106
+ result.migrationsExecuted.forEach((migration, index) => {
107
+ console.log(` ${index + 1}. ${migration.from} → ${migration.to}`);
108
+ migration.changes.forEach(change => {
109
+ console.log(` - ${change}`);
110
+ });
111
+ });
112
+ } else {
113
+ console.log(chalk.red('❌ Dry run failed'));
114
+ result.errors.forEach(error => console.log(` ${error}`));
115
+ }
116
+
117
+ return;
118
+ }
119
+
120
+ // 5. Confirm with user (unless --auto)
121
+ if (!auto) {
122
+ const { confirmed } = await inquirer.prompt([
123
+ {
124
+ type: 'confirm',
125
+ name: 'confirmed',
126
+ message: 'Proceed with upgrade?',
127
+ default: true
128
+ }
129
+ ]);
130
+
131
+ if (!confirmed) {
132
+ console.log(chalk.yellow('Upgrade cancelled'));
133
+ return;
134
+ }
135
+ }
136
+
137
+ console.log();
138
+
139
+ // 6. Create backup
140
+ console.log(chalk.blue('📦 Creating backup...'));
141
+ const backupSystem = new BackupSystem();
142
+
143
+ let backup;
144
+ try {
145
+ backup = await backupSystem.createBackup(projectPath, { type: 'upgrade' });
146
+ console.log(chalk.green(`✅ Backup created: ${backup.id}`));
147
+ } catch (error) {
148
+ console.log(chalk.red(`❌ Failed to create backup: ${error.message}`));
149
+ console.log(chalk.yellow('Aborting upgrade for safety'));
150
+ return;
151
+ }
152
+
153
+ console.log();
154
+
155
+ // 7. Execute upgrade
156
+ console.log(chalk.blue('🚀 Executing upgrade...'));
157
+
158
+ const result = await migrationEngine.executeUpgrade(projectPath, plan, {
159
+ dryRun: false,
160
+ onProgress: (step, total, message) => {
161
+ console.log(` [${step}/${total}] ${message}`);
162
+ }
163
+ });
164
+
165
+ console.log();
166
+
167
+ // 8. Validate
168
+ console.log(chalk.blue('🔍 Validating upgrade...'));
169
+ const validation = await migrationEngine.validate(projectPath);
170
+
171
+ if (!validation.success) {
172
+ console.log(chalk.yellow('⚠️ Validation warnings:'));
173
+ validation.warnings.forEach(warning => console.log(` ${warning}`));
174
+ }
175
+
176
+ console.log();
177
+
178
+ // 9. Report results
179
+ if (result.success) {
180
+ console.log(chalk.green('✅ Upgrade completed successfully!'));
181
+ console.log();
182
+ console.log(` Upgraded from ${chalk.cyan(result.fromVersion)} to ${chalk.cyan(result.toVersion)}`);
183
+
184
+ if (result.migrationsExecuted.length > 0) {
185
+ console.log();
186
+ console.log(chalk.blue('Migrations executed:'));
187
+ result.migrationsExecuted.forEach((migration, index) => {
188
+ const icon = migration.success ? chalk.green('✅') : chalk.red('❌');
189
+ console.log(` ${icon} ${migration.from} → ${migration.to}`);
190
+ if (migration.changes.length > 0) {
191
+ migration.changes.forEach(change => {
192
+ console.log(` - ${change}`);
193
+ });
194
+ }
195
+ });
196
+ }
197
+
198
+ if (result.warnings.length > 0) {
199
+ console.log();
200
+ console.log(chalk.yellow('⚠️ Warnings:'));
201
+ result.warnings.forEach(warning => console.log(` ${warning}`));
202
+ }
203
+
204
+ console.log();
205
+ console.log(chalk.blue('📦 Backup:'), backup.id);
206
+ console.log(chalk.gray(' Run'), chalk.cyan('kse rollback'), chalk.gray('if you encounter issues'));
207
+
208
+ console.log();
209
+ console.log(chalk.red('🔥') + ' Upgrade complete!');
210
+ } else {
211
+ console.log(chalk.red('❌ Upgrade failed'));
212
+ console.log();
213
+ result.errors.forEach(error => console.log(chalk.red(` ${error}`)));
214
+
215
+ console.log();
216
+ console.log(chalk.blue('📦 Backup available:'), backup.id);
217
+ console.log(chalk.gray(' Run'), chalk.cyan('kse rollback'), chalk.gray('to restore'));
218
+
219
+ process.exit(1);
220
+ }
221
+ } catch (error) {
222
+ console.log();
223
+ console.log(chalk.red('❌ Error:'), error.message);
224
+ console.log();
225
+ console.log(chalk.gray('If you need help, please report this issue:'));
226
+ console.log(chalk.cyan('https://github.com/heguangyong/kiro-spec-engine/issues'));
227
+ process.exit(1);
228
+ }
229
+ }
230
+
231
+ module.exports = upgradeCommand;