kiro-spec-engine 1.6.3 → 1.7.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/CHANGELOG.md CHANGED
@@ -5,6 +5,116 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.7.0] - 2026-01-24
9
+
10
+ ### Added - Interactive Conflict Resolution System đŸŽ¯
11
+
12
+ **Spec 10-00**: Complete overhaul of `kse adopt` conflict handling with interactive resolution
13
+
14
+ **Core Features**:
15
+ - **Interactive Conflict Resolution**: Choose how to handle each conflicting file
16
+ - Three strategies: Skip all, Overwrite all, Review each file
17
+ - Per-file review with progress tracking ("Conflict 2 of 5")
18
+ - View file differences before deciding
19
+ - **Selective Backup System**: Only backs up files being overwritten (not entire .kiro/)
20
+ - Efficient backup creation with conflict-specific IDs
21
+ - Selective restore capability
22
+ - Automatic backup before any overwrites
23
+ - **File Difference Viewer**: Compare existing vs template files
24
+ - Side-by-side metadata comparison (size, modification date)
25
+ - Line-by-line diff for text files (with line limits)
26
+ - Binary file detection and handling
27
+ - Color-coded output with chalk
28
+
29
+ **Enhanced Modes**:
30
+ - **Force Mode** (`--force`): Automatically overwrite all conflicts with backup
31
+ - Clear warning message before proceeding
32
+ - Selective backup of all conflicting files
33
+ - No interactive prompts
34
+ - **Auto Mode** (`--auto`): Non-interactive adoption
35
+ - Defaults to skip-all strategy (safe default)
36
+ - Can combine with `--force` for auto-overwrite
37
+ - Suitable for CI/CD environments
38
+ - **Dry Run Mode** (`--dry-run`): Preview conflict actions
39
+ - Shows what conflicts would be detected
40
+ - Displays what action would be taken
41
+ - No file modifications or backups created
42
+
43
+ **Improved Reporting**:
44
+ - **Conflict Resolution Summary**: Detailed adoption results
45
+ - List of skipped files with reasons
46
+ - List of overwritten files
47
+ - Backup ID for rollback
48
+ - Total conflict count
49
+ - Rollback instructions when applicable
50
+ - **Error Handling**: Comprehensive error recovery
51
+ - Backup failure detection and abort
52
+ - Individual file overwrite failure handling
53
+ - Diff generation failure graceful degradation
54
+ - Non-interactive environment detection
55
+ - Detailed error summaries with recovery guidance
56
+
57
+ **New Components**:
58
+ - `lib/adoption/conflict-resolver.js` - Interactive conflict resolution prompts
59
+ - `lib/backup/selective-backup.js` - Selective file backup system
60
+ - `lib/adoption/diff-viewer.js` - File difference viewer
61
+ - Enhanced `lib/adoption/detection-engine.js` - Conflict categorization
62
+ - Enhanced `lib/commands/adopt.js` - Integrated conflict resolution flow
63
+ - Enhanced `lib/adoption/adoption-strategy.js` - Resolution map support
64
+
65
+ **Usage Examples**:
66
+ ```bash
67
+ # Interactive mode (default) - prompts for each conflict
68
+ kse adopt
69
+
70
+ # Force mode - overwrite all conflicts with backup
71
+ kse adopt --force
72
+
73
+ # Auto mode - skip all conflicts automatically
74
+ kse adopt --auto
75
+
76
+ # Auto + force - overwrite all conflicts without prompts
77
+ kse adopt --auto --force
78
+
79
+ # Dry run - preview what would happen
80
+ kse adopt --dry-run
81
+ ```
82
+
83
+ **Benefits**:
84
+ - Full control over which files to keep or overwrite
85
+ - View differences before making decisions
86
+ - Efficient backups (only affected files, not entire .kiro/)
87
+ - Safe adoption with automatic rollback support
88
+ - Clear feedback about what changed
89
+ - Suitable for both interactive and automated workflows
90
+
91
+ **Technical Details**:
92
+ - Uses inquirer for interactive prompts
93
+ - Categorizes conflicts by type (steering, documentation, tools, other)
94
+ - Preserves directory structure in selective backups
95
+ - Handles both text and binary files appropriately
96
+ - Cross-platform path handling (Windows/Unix)
97
+ - Non-TTY environment detection for CI/CD
98
+
99
+ ## [1.6.4] - 2026-01-24
100
+
101
+ ### Added
102
+ - **Prominent clarification to prevent confusion with Kiro IDE** đŸŽ¯
103
+ - Added warning box at top of README.md and README.zh.md
104
+ - Clarifies that kse is an npm package/CLI tool, NOT the Kiro IDE desktop application
105
+ - Updated package.json description to explicitly state the difference
106
+ - **Triggered by**: Real user feedback - iFlow (using GLM-4.7) confused kse with Kiro IDE and tried to download the wrong software
107
+
108
+ **Why this matters:**
109
+ - Prevents AI tools (especially smaller models) from confusing kse with Kiro IDE
110
+ - Saves users time by immediately clarifying what kse is
111
+ - Improves first-time user experience
112
+ - Sets foundation for Spec 11 (comprehensive documentation alignment)
113
+
114
+ **User feedback that triggered this:**
115
+ > "iFlow ᔍ GLM-4.7 åĨŊå‚ģ 下čŊŊ kiro äē†"
116
+ > (iFlow using GLM-4.7 was silly and downloaded Kiro [IDE] instead)
117
+
8
118
  ## [1.6.3] - 2026-01-24
9
119
 
10
120
  ### Fixed
package/README.md CHANGED
@@ -3,6 +3,9 @@
3
3
  [![npm version](https://badge.fury.io/js/kiro-spec-engine.svg)](https://badge.fury.io/js/kiro-spec-engine)
4
4
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
5
 
6
+ > **âš ī¸ Important Clarification**: `kiro-spec-engine` (kse) is an **npm package and CLI tool** for spec-driven development.
7
+ > It is **NOT** the Kiro IDE desktop application. If you're looking for Kiro IDE, visit https://kiro.dev
8
+
6
9
  **A context provider for AI coding tools** - Structure your project requirements, design, and tasks so AI assistants can help you build better software.
7
10
 
8
11
  English | [įŽ€äŊ“中文](README.zh.md)
package/README.zh.md CHANGED
@@ -3,6 +3,9 @@
3
3
  [![npm version](https://badge.fury.io/js/kiro-spec-engine.svg)](https://badge.fury.io/js/kiro-spec-engine)
4
4
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
5
 
6
+ > **âš ī¸ 重čĻč¯´æ˜Ž**: `kiro-spec-engine` (kse) 是一ä¸Ē **npm 包和 CLI åˇĨå…ˇ**īŧŒį”¨äēŽ Spec éŠąåŠ¨åŧ€å‘。
7
+ > 厃**不是** Kiro IDE æĄŒéĸåē”ᔍፋåēã€‚åĻ‚æžœäŊ åœ¨å¯ģ扞 Kiro IDEīŧŒč¯ˇčŽŋ问 https://kiro.dev
8
+
6
9
  **AI įŧ–᠁åˇĨå…ˇįš„ä¸Šä¸‹æ–‡æäž›č€…** - į쓿ž„化äŊ įš„éĄšį›Žéœ€æą‚ã€čŽžčŽĄå’ŒäģģåŠĄīŧŒčŽŠ AI 劊手帎äŊ æž„åģēæ›´åĨŊįš„čŊ¯äģļ。
7
10
 
8
11
  [English](README.md) | įŽ€äŊ“中文
@@ -166,7 +166,18 @@ class ConflictResolver {
166
166
  const existingPath = path.join(projectPath, '.kiro', conflict.path);
167
167
  const templatePath = conflict.templatePath || path.join(projectPath, 'template', '.kiro', conflict.path);
168
168
 
169
- await this.diffViewer.showDiff(existingPath, templatePath);
169
+ try {
170
+ await this.diffViewer.showDiff(existingPath, templatePath);
171
+ } catch (diffError) {
172
+ console.log();
173
+ console.log(chalk.yellow('âš ī¸ Unable to generate diff for this file'));
174
+ console.log(chalk.gray(` Reason: ${diffError.message}`));
175
+ console.log();
176
+ console.log(chalk.gray(' You can open the files in your editor to compare:'));
177
+ console.log(chalk.gray(` Existing: ${existingPath}`));
178
+ console.log(chalk.gray(` Template: ${templatePath}`));
179
+ console.log();
180
+ }
170
181
 
171
182
  // Re-prompt with only keep/overwrite options
172
183
  const { finalAction } = await inquirer.prompt([
@@ -187,6 +187,29 @@ class DetectionEngine {
187
187
  }
188
188
  }
189
189
 
190
+ /**
191
+ * Categorizes conflicts by type for better display
192
+ *
193
+ * @param {FileConflict[]} conflicts - Array of conflicts
194
+ * @returns {CategorizedConflicts}
195
+ */
196
+ categorizeConflicts(conflicts) {
197
+ return {
198
+ steering: conflicts.filter(c => c.path.startsWith('steering/')),
199
+ documentation: conflicts.filter(c =>
200
+ c.path.endsWith('.md') &&
201
+ !c.path.startsWith('steering/') &&
202
+ !c.path.startsWith('tools/')
203
+ ),
204
+ tools: conflicts.filter(c => c.path.startsWith('tools/')),
205
+ other: conflicts.filter(c =>
206
+ !c.path.startsWith('steering/') &&
207
+ !c.path.startsWith('tools/') &&
208
+ !c.path.endsWith('.md')
209
+ )
210
+ };
211
+ }
212
+
190
213
  /**
191
214
  * Validates that a project path is valid
192
215
  *
@@ -100,6 +100,45 @@ async function adoptCommand(options = {}) {
100
100
  console.log(chalk.yellow('🔍 Dry run mode - no changes will be made'));
101
101
  console.log();
102
102
 
103
+ // Show how conflicts would be handled
104
+ if (detection.conflicts.length > 0) {
105
+ console.log(chalk.blue('Conflict Resolution Preview:'));
106
+ console.log();
107
+
108
+ if (force) {
109
+ console.log(chalk.yellow(' With --force flag:'));
110
+ console.log(' - All conflicting files would be overwritten');
111
+ console.log(' - Backup would be created before overwriting');
112
+ console.log();
113
+ console.log(' Files that would be overwritten:');
114
+ detection.conflicts.forEach(conflict => {
115
+ console.log(chalk.red(` ~ ${conflict.path}`));
116
+ });
117
+ } else if (auto) {
118
+ console.log(chalk.gray(' With --auto flag:'));
119
+ console.log(' - All conflicting files would be preserved');
120
+ console.log(' - Template files would be skipped');
121
+ console.log();
122
+ console.log(' Files that would be skipped:');
123
+ detection.conflicts.forEach(conflict => {
124
+ console.log(chalk.gray(` - ${conflict.path}`));
125
+ });
126
+ } else {
127
+ console.log(chalk.blue(' In interactive mode:'));
128
+ console.log(' - You would be prompted to choose:');
129
+ console.log(' â€ĸ Skip all conflicting files');
130
+ console.log(' â€ĸ Overwrite all (with backup)');
131
+ console.log(' â€ĸ Review each conflict individually');
132
+ console.log();
133
+ console.log(' Conflicting files:');
134
+ detection.conflicts.forEach(conflict => {
135
+ console.log(chalk.yellow(` ? ${conflict.path}`));
136
+ });
137
+ }
138
+
139
+ console.log();
140
+ }
141
+
103
142
  const adoptionStrategy = getAdoptionStrategy(strategy);
104
143
  const versionManager = new VersionManager();
105
144
  const packageJson = require('../../package.json');
@@ -177,6 +216,36 @@ async function adoptCommand(options = {}) {
177
216
  console.log();
178
217
  console.log(chalk.blue('đŸ“Ļ Creating backup of files to be overwritten...'));
179
218
  const selectiveBackup = new SelectiveBackup();
219
+
220
+ try {
221
+ const backup = await selectiveBackup.createSelectiveBackup(
222
+ projectPath,
223
+ filesToOverwrite,
224
+ { type: 'conflict' }
225
+ );
226
+ conflictBackupId = backup.id;
227
+ console.log(chalk.green(`✅ Backup created: ${conflictBackupId}`));
228
+ } catch (backupError) {
229
+ console.log(chalk.red(`❌ Failed to create backup: ${backupError.message}`));
230
+ console.log();
231
+ console.log(chalk.yellow('âš ī¸ Aborting adoption for safety'));
232
+ console.log(chalk.gray(' Possible causes:'));
233
+ console.log(chalk.gray(' - Insufficient disk space'));
234
+ console.log(chalk.gray(' - Permission denied'));
235
+ console.log(chalk.gray(' - File system error'));
236
+ console.log();
237
+ console.log(chalk.gray(' Please resolve the issue and try again'));
238
+ process.exit(1);
239
+ }
240
+ }
241
+ } else if (force) {
242
+ // Force mode: overwrite all with backup
243
+ console.log();
244
+ console.log(chalk.blue('đŸ“Ļ Creating backup of conflicting files...'));
245
+ const filesToOverwrite = detection.conflicts.map(c => c.path);
246
+ const selectiveBackup = new SelectiveBackup();
247
+
248
+ try {
180
249
  const backup = await selectiveBackup.createSelectiveBackup(
181
250
  projectPath,
182
251
  filesToOverwrite,
@@ -184,20 +253,18 @@ async function adoptCommand(options = {}) {
184
253
  );
185
254
  conflictBackupId = backup.id;
186
255
  console.log(chalk.green(`✅ Backup created: ${conflictBackupId}`));
256
+ } catch (backupError) {
257
+ console.log(chalk.red(`❌ Failed to create backup: ${backupError.message}`));
258
+ console.log();
259
+ console.log(chalk.yellow('âš ī¸ Aborting adoption for safety'));
260
+ console.log(chalk.gray(' Cannot proceed with --force without a backup'));
261
+ console.log();
262
+ console.log(chalk.gray(' Possible solutions:'));
263
+ console.log(chalk.gray(' - Free up disk space'));
264
+ console.log(chalk.gray(' - Check file permissions'));
265
+ console.log(chalk.gray(' - Try without --force to skip conflicts'));
266
+ process.exit(1);
187
267
  }
188
- } else if (force) {
189
- // Force mode: overwrite all with backup
190
- console.log();
191
- console.log(chalk.blue('đŸ“Ļ Creating backup of conflicting files...'));
192
- const filesToOverwrite = detection.conflicts.map(c => c.path);
193
- const selectiveBackup = new SelectiveBackup();
194
- const backup = await selectiveBackup.createSelectiveBackup(
195
- projectPath,
196
- filesToOverwrite,
197
- { type: 'conflict' }
198
- );
199
- conflictBackupId = backup.id;
200
- console.log(chalk.green(`✅ Backup created: ${conflictBackupId}`));
201
268
 
202
269
  resolutionMap = detection.conflicts.reduce((map, conflict) => {
203
270
  map[conflict.path] = 'overwrite';
@@ -300,6 +367,43 @@ async function adoptCommand(options = {}) {
300
367
  console.log(chalk.green('✅ Adoption completed successfully!'));
301
368
  console.log();
302
369
 
370
+ // Show conflict resolution summary if conflicts were handled
371
+ if (detection.conflicts.length > 0) {
372
+ console.log(chalk.blue('📊 Conflict Resolution Summary:'));
373
+ console.log(` Total conflicts: ${detection.conflicts.length}`);
374
+
375
+ const overwrittenFiles = Object.entries(resolutionMap)
376
+ .filter(([_, resolution]) => resolution === 'overwrite')
377
+ .map(([path, _]) => path);
378
+
379
+ const skippedFiles = Object.entries(resolutionMap)
380
+ .filter(([_, resolution]) => resolution === 'keep')
381
+ .map(([path, _]) => path);
382
+
383
+ if (overwrittenFiles.length > 0) {
384
+ console.log(chalk.yellow(` Overwritten: ${overwrittenFiles.length} file(s)`));
385
+ overwrittenFiles.forEach(file => {
386
+ console.log(chalk.red(` ~ ${file}`));
387
+ });
388
+ }
389
+
390
+ if (skippedFiles.length > 0) {
391
+ console.log(chalk.gray(` Skipped: ${skippedFiles.length} file(s)`));
392
+ skippedFiles.forEach(file => {
393
+ console.log(chalk.gray(` - ${file}`));
394
+ });
395
+ }
396
+
397
+ if (conflictBackupId) {
398
+ console.log();
399
+ console.log(chalk.blue('đŸ“Ļ Conflict Backup:'), conflictBackupId);
400
+ console.log(chalk.gray(' To restore overwritten files, run:'));
401
+ console.log(chalk.cyan(` kse rollback ${conflictBackupId}`));
402
+ }
403
+
404
+ console.log();
405
+ }
406
+
303
407
  if (steeringStrategy) {
304
408
  console.log(chalk.blue('Steering Strategy:'), steeringStrategy);
305
409
  if (steeringBackupId) {
@@ -318,17 +422,12 @@ async function adoptCommand(options = {}) {
318
422
  result.filesUpdated.forEach(file => console.log(` ~ ${file}`));
319
423
  }
320
424
 
321
- if (result.filesSkipped.length > 0) {
425
+ if (result.filesSkipped.length > 0 && detection.conflicts.length === 0) {
426
+ // Only show this if not already shown in conflict summary
322
427
  console.log(chalk.gray('Files skipped:'));
323
428
  result.filesSkipped.forEach(file => console.log(` - ${file}`));
324
429
  }
325
430
 
326
- if (conflictBackupId) {
327
- console.log();
328
- console.log(chalk.blue('đŸ“Ļ Conflict Backup:'), conflictBackupId);
329
- console.log(chalk.gray(' Run'), chalk.cyan('kse rollback'), chalk.gray('to restore overwritten files'));
330
- }
331
-
332
431
  if (result.warnings.length > 0) {
333
432
  console.log();
334
433
  console.log(chalk.yellow('âš ī¸ Warnings:'));
@@ -337,7 +436,7 @@ async function adoptCommand(options = {}) {
337
436
 
338
437
  if (backupId) {
339
438
  console.log();
340
- console.log(chalk.blue('đŸ“Ļ Backup:'), backupId);
439
+ console.log(chalk.blue('đŸ“Ļ Full Backup:'), backupId);
341
440
  console.log(chalk.gray(' Run'), chalk.cyan('kse rollback'), chalk.gray('if you need to undo changes'));
342
441
  }
343
442
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "kiro-spec-engine",
3
- "version": "1.6.3",
4
- "description": "Kiro Spec Engine - A spec-driven development engine with steering rules and quality enhancement powered by Ultrawork spirit",
3
+ "version": "1.7.0",
4
+ "description": "kiro-spec-engine (kse) - A CLI tool and npm package for spec-driven development with AI coding assistants. NOT the Kiro IDE desktop application.",
5
5
  "main": "index.js",
6
6
  "bin": {
7
7
  "kiro-spec-engine": "./bin/kiro-spec-engine.js",