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 +110 -0
- package/README.md +3 -0
- package/README.zh.md +3 -0
- package/lib/adoption/conflict-resolver.js +12 -1
- package/lib/adoption/detection-engine.js +23 -0
- package/lib/commands/adopt.js +120 -21
- package/package.json +2 -2
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
|
[](https://badge.fury.io/js/kiro-spec-engine)
|
|
4
4
|
[](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
|
[](https://badge.fury.io/js/kiro-spec-engine)
|
|
4
4
|
[](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
|
-
|
|
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
|
*
|
package/lib/commands/adopt.js
CHANGED
|
@@ -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.
|
|
4
|
-
"description": "
|
|
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",
|