kiro-spec-engine 1.20.5 → 1.21.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.
- package/CHANGELOG.md +48 -0
- package/docs/multi-repo-management-guide.md +254 -0
- package/lib/repo/config-manager.js +121 -11
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,54 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [1.21.1] - 2026-02-01
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
- **Test Suite Compatibility**: Fixed test failures introduced in v1.21.0
|
|
14
|
+
- Updated tests to reflect optional version field (now defaults to "1.0")
|
|
15
|
+
- Added `skipFilesystemValidation` option to `loadConfig()` for testing scenarios
|
|
16
|
+
- Mocked `_validateRepositoryPath` in handler tests to avoid filesystem dependency
|
|
17
|
+
- All 1697 tests now pass successfully
|
|
18
|
+
|
|
19
|
+
### Technical Details
|
|
20
|
+
- Modified `ConfigManager.loadConfig()` to accept optional `skipFilesystemValidation` parameter
|
|
21
|
+
- Updated test expectations for optional version field validation
|
|
22
|
+
- Enhanced test isolation by mocking filesystem validation in unit tests
|
|
23
|
+
- No functional changes to production code behavior
|
|
24
|
+
|
|
25
|
+
## [1.21.0] - 2026-02-01
|
|
26
|
+
|
|
27
|
+
### Added
|
|
28
|
+
- **Manual Configuration Support**: Users can now manually create and edit `.kiro/project-repos.json` without relying solely on auto-scan
|
|
29
|
+
- Version field is now optional (defaults to "1.0" if omitted)
|
|
30
|
+
- Only `name` and `path` are required for each repository entry
|
|
31
|
+
- All other fields (`remote`, `defaultBranch`, `description`, `tags`, `group`, `parent`) are optional
|
|
32
|
+
- Filesystem validation ensures paths exist and contain valid `.git` directories
|
|
33
|
+
- Clear, actionable error messages guide users in fixing configuration issues
|
|
34
|
+
- Comprehensive documentation in `docs/multi-repo-management-guide.md` with examples and troubleshooting
|
|
35
|
+
|
|
36
|
+
### Changed
|
|
37
|
+
- **Enhanced Validation**: Configuration validation now performs filesystem checks when loading from disk
|
|
38
|
+
- Validates that repository paths exist on the filesystem
|
|
39
|
+
- Verifies each path contains a `.git` directory (not file)
|
|
40
|
+
- Detects and rejects Git worktrees with helpful error messages
|
|
41
|
+
- Reports all validation errors together (not just the first one)
|
|
42
|
+
- Maintains backward compatibility with all v1.18.0+ configurations
|
|
43
|
+
|
|
44
|
+
### Fixed
|
|
45
|
+
- **Manual Configuration Rejection**: Fixed issue where manually-created configurations were rejected even when valid
|
|
46
|
+
- Users can now manually curate repository lists
|
|
47
|
+
- Users can remove false positives from auto-scan results
|
|
48
|
+
- Users can add repositories that weren't auto-detected
|
|
49
|
+
- Minimal configurations (name + path only) now pass validation
|
|
50
|
+
- User-reported issue: 8 real Git repositories rejected by validation
|
|
51
|
+
|
|
52
|
+
### Documentation
|
|
53
|
+
- Added comprehensive "Manual Configuration" section to multi-repo management guide
|
|
54
|
+
- Documented minimal configuration format with examples
|
|
55
|
+
- Added troubleshooting guide for common validation errors
|
|
56
|
+
- Included step-by-step instructions for creating manual configurations
|
|
57
|
+
|
|
10
58
|
## [1.20.5] - 2026-02-01 🔥 HOTFIX
|
|
11
59
|
|
|
12
60
|
### Fixed
|
|
@@ -193,6 +193,260 @@ Paths can be specified as:
|
|
|
193
193
|
"path": "packages/frontend" // Unix/Mac
|
|
194
194
|
```
|
|
195
195
|
|
|
196
|
+
## Manual Configuration
|
|
197
|
+
|
|
198
|
+
### Overview
|
|
199
|
+
|
|
200
|
+
Starting with v1.21.0, you can manually create and edit the `.kiro/project-repos.json` configuration file without relying solely on `kse repo init`. This is useful for:
|
|
201
|
+
|
|
202
|
+
- Curating a specific list of repositories
|
|
203
|
+
- Removing false positives from auto-scan
|
|
204
|
+
- Adding repositories that weren't auto-detected
|
|
205
|
+
- Creating configurations for repositories that don't exist yet
|
|
206
|
+
|
|
207
|
+
### Minimal Configuration Format
|
|
208
|
+
|
|
209
|
+
The simplest valid configuration requires only `name` and `path` for each repository:
|
|
210
|
+
|
|
211
|
+
```json
|
|
212
|
+
{
|
|
213
|
+
"repositories": [
|
|
214
|
+
{
|
|
215
|
+
"name": "my-repo",
|
|
216
|
+
"path": "./my-repo"
|
|
217
|
+
},
|
|
218
|
+
{
|
|
219
|
+
"name": "another-repo",
|
|
220
|
+
"path": "./another-repo"
|
|
221
|
+
}
|
|
222
|
+
]
|
|
223
|
+
}
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
**Key points:**
|
|
227
|
+
- The `version` field is optional (defaults to "1.0")
|
|
228
|
+
- Only `name` and `path` are required for each repository
|
|
229
|
+
- All other fields (`remote`, `defaultBranch`, `description`, `tags`, `group`) are optional
|
|
230
|
+
|
|
231
|
+
### Complete Configuration Example
|
|
232
|
+
|
|
233
|
+
For more detailed configurations, you can include all optional fields:
|
|
234
|
+
|
|
235
|
+
```json
|
|
236
|
+
{
|
|
237
|
+
"version": "1.0",
|
|
238
|
+
"repositories": [
|
|
239
|
+
{
|
|
240
|
+
"name": "frontend",
|
|
241
|
+
"path": "./packages/frontend",
|
|
242
|
+
"remote": "https://github.com/user/frontend.git",
|
|
243
|
+
"defaultBranch": "main",
|
|
244
|
+
"description": "React frontend application",
|
|
245
|
+
"tags": ["ui", "react"],
|
|
246
|
+
"group": "client"
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
"name": "backend",
|
|
250
|
+
"path": "./packages/backend",
|
|
251
|
+
"remote": "https://github.com/user/backend.git",
|
|
252
|
+
"defaultBranch": "develop",
|
|
253
|
+
"description": "Node.js API server",
|
|
254
|
+
"tags": ["api", "nodejs"],
|
|
255
|
+
"group": "server"
|
|
256
|
+
},
|
|
257
|
+
{
|
|
258
|
+
"name": "local-only",
|
|
259
|
+
"path": "./local-repo"
|
|
260
|
+
}
|
|
261
|
+
],
|
|
262
|
+
"groups": {
|
|
263
|
+
"client": {
|
|
264
|
+
"description": "Client-side applications"
|
|
265
|
+
},
|
|
266
|
+
"server": {
|
|
267
|
+
"description": "Server-side services"
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
### Field Requirements
|
|
274
|
+
|
|
275
|
+
#### Required Fields
|
|
276
|
+
- **name**: Unique identifier for the repository
|
|
277
|
+
- Must contain only alphanumeric characters, hyphens, underscores, and dots
|
|
278
|
+
- Examples: `"frontend"`, `"my-repo"`, `"repo.1"`, `".github"`
|
|
279
|
+
|
|
280
|
+
- **path**: Path to the repository directory
|
|
281
|
+
- Can be relative (e.g., `"./my-repo"`) or absolute (e.g., `"/home/user/my-repo"`)
|
|
282
|
+
- Must point to an existing directory containing a `.git` directory
|
|
283
|
+
- Cannot point to a Git worktree (`.git` file instead of directory)
|
|
284
|
+
|
|
285
|
+
#### Optional Fields
|
|
286
|
+
- **remote**: Git remote URL (can be omitted for local-only repositories)
|
|
287
|
+
- **defaultBranch**: Default branch name (e.g., `"main"`, `"develop"`)
|
|
288
|
+
- **description**: Human-readable description
|
|
289
|
+
- **tags**: Array of tags for categorization
|
|
290
|
+
- **group**: Group name for logical organization
|
|
291
|
+
- **parent**: Parent repository path (for nested repositories)
|
|
292
|
+
|
|
293
|
+
### Validation Rules
|
|
294
|
+
|
|
295
|
+
When you manually create or edit the configuration, `kse` validates:
|
|
296
|
+
|
|
297
|
+
1. **File Format**: Must be valid JSON
|
|
298
|
+
2. **Structure**: Must have a `repositories` array
|
|
299
|
+
3. **Required Fields**: Each repository must have `name` and `path`
|
|
300
|
+
4. **Path Existence**: Each path must exist on the filesystem
|
|
301
|
+
5. **Git Repository**: Each path must contain a `.git` directory (not file)
|
|
302
|
+
6. **No Duplicates**: Repository names and paths must be unique
|
|
303
|
+
7. **No Worktrees**: Paths cannot point to Git worktrees
|
|
304
|
+
|
|
305
|
+
### Creating a Manual Configuration
|
|
306
|
+
|
|
307
|
+
**Step 1: Create the directory structure**
|
|
308
|
+
|
|
309
|
+
```bash
|
|
310
|
+
mkdir -p .kiro
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
**Step 2: Create the configuration file**
|
|
314
|
+
|
|
315
|
+
Create `.kiro/project-repos.json` with your repositories:
|
|
316
|
+
|
|
317
|
+
```json
|
|
318
|
+
{
|
|
319
|
+
"repositories": [
|
|
320
|
+
{
|
|
321
|
+
"name": "repo1",
|
|
322
|
+
"path": "./repo1"
|
|
323
|
+
},
|
|
324
|
+
{
|
|
325
|
+
"name": "repo2",
|
|
326
|
+
"path": "./repo2"
|
|
327
|
+
}
|
|
328
|
+
]
|
|
329
|
+
}
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
**Step 3: Verify the configuration**
|
|
333
|
+
|
|
334
|
+
```bash
|
|
335
|
+
kse repo status
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
If there are validation errors, `kse` will display clear error messages:
|
|
339
|
+
|
|
340
|
+
```
|
|
341
|
+
Error: Repository path validation failed
|
|
342
|
+
- Repository "repo1": path "./repo1" does not exist. Please check the path is correct.
|
|
343
|
+
- Repository "repo2": path "./repo2" is not a Git repository (no .git directory found). Please ensure this is a Git repository.
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
### Editing an Existing Configuration
|
|
347
|
+
|
|
348
|
+
You can manually edit the auto-generated configuration to:
|
|
349
|
+
|
|
350
|
+
**Remove repositories:**
|
|
351
|
+
```json
|
|
352
|
+
{
|
|
353
|
+
"repositories": [
|
|
354
|
+
// Remove unwanted entries from this array
|
|
355
|
+
{
|
|
356
|
+
"name": "keep-this",
|
|
357
|
+
"path": "./keep-this"
|
|
358
|
+
}
|
|
359
|
+
// Deleted: { "name": "remove-this", "path": "./remove-this" }
|
|
360
|
+
]
|
|
361
|
+
}
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
**Add new repositories:**
|
|
365
|
+
```json
|
|
366
|
+
{
|
|
367
|
+
"repositories": [
|
|
368
|
+
{
|
|
369
|
+
"name": "existing-repo",
|
|
370
|
+
"path": "./existing-repo"
|
|
371
|
+
},
|
|
372
|
+
{
|
|
373
|
+
"name": "new-repo",
|
|
374
|
+
"path": "./new-repo"
|
|
375
|
+
}
|
|
376
|
+
]
|
|
377
|
+
}
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
**Simplify to minimal format:**
|
|
381
|
+
```json
|
|
382
|
+
{
|
|
383
|
+
"repositories": [
|
|
384
|
+
{
|
|
385
|
+
"name": "repo1",
|
|
386
|
+
"path": "./repo1"
|
|
387
|
+
// Removed: remote, defaultBranch, description, tags, group
|
|
388
|
+
}
|
|
389
|
+
]
|
|
390
|
+
}
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
### Troubleshooting
|
|
394
|
+
|
|
395
|
+
#### Error: "path does not exist"
|
|
396
|
+
|
|
397
|
+
**Cause**: The specified path doesn't exist on the filesystem.
|
|
398
|
+
|
|
399
|
+
**Solution**: Check the path is correct and the directory exists:
|
|
400
|
+
```bash
|
|
401
|
+
ls -la ./my-repo # Unix/Mac
|
|
402
|
+
dir .\my-repo # Windows
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
#### Error: "is not a Git repository"
|
|
406
|
+
|
|
407
|
+
**Cause**: The path exists but doesn't contain a `.git` directory.
|
|
408
|
+
|
|
409
|
+
**Solution**: Initialize the directory as a Git repository:
|
|
410
|
+
```bash
|
|
411
|
+
cd ./my-repo
|
|
412
|
+
git init
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
#### Error: "appears to be a Git worktree"
|
|
416
|
+
|
|
417
|
+
**Cause**: The path contains a `.git` file instead of a directory (Git worktree).
|
|
418
|
+
|
|
419
|
+
**Solution**: Use the main repository path instead of the worktree path:
|
|
420
|
+
```json
|
|
421
|
+
{
|
|
422
|
+
"name": "my-repo",
|
|
423
|
+
"path": "./main-repo" // Use main repo, not worktree
|
|
424
|
+
}
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
#### Error: "Duplicate repository name"
|
|
428
|
+
|
|
429
|
+
**Cause**: Two repositories have the same name.
|
|
430
|
+
|
|
431
|
+
**Solution**: Ensure each repository has a unique name:
|
|
432
|
+
```json
|
|
433
|
+
{
|
|
434
|
+
"repositories": [
|
|
435
|
+
{ "name": "repo1", "path": "./path1" },
|
|
436
|
+
{ "name": "repo2", "path": "./path2" } // Changed from "repo1"
|
|
437
|
+
]
|
|
438
|
+
}
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
#### Error: "Configuration file contains invalid JSON"
|
|
442
|
+
|
|
443
|
+
**Cause**: The JSON syntax is incorrect (missing comma, bracket, etc.).
|
|
444
|
+
|
|
445
|
+
**Solution**: Validate your JSON using a JSON validator or IDE:
|
|
446
|
+
- Check for missing commas between array elements
|
|
447
|
+
- Ensure all brackets and braces are properly closed
|
|
448
|
+
- Use a JSON formatter to identify syntax errors
|
|
449
|
+
|
|
196
450
|
## Nested Repository Support
|
|
197
451
|
|
|
198
452
|
### Overview
|
|
@@ -46,10 +46,13 @@ class ConfigManager {
|
|
|
46
46
|
|
|
47
47
|
/**
|
|
48
48
|
* Load and validate configuration from disk
|
|
49
|
+
* @param {Object} options - Load options
|
|
50
|
+
* @param {boolean} options.skipFilesystemValidation - Skip filesystem validation (for testing)
|
|
49
51
|
* @returns {Promise<Object>} The loaded and validated configuration
|
|
50
52
|
* @throws {ConfigError} If file is missing, invalid JSON, or validation fails
|
|
51
53
|
*/
|
|
52
|
-
async loadConfig() {
|
|
54
|
+
async loadConfig(options = {}) {
|
|
55
|
+
const { skipFilesystemValidation = false } = options;
|
|
53
56
|
const configPath = this.getConfigPath();
|
|
54
57
|
|
|
55
58
|
// Check if file exists
|
|
@@ -78,8 +81,8 @@ class ConfigManager {
|
|
|
78
81
|
);
|
|
79
82
|
}
|
|
80
83
|
|
|
81
|
-
// Validate configuration
|
|
82
|
-
const validation = this.validateConfig(configData);
|
|
84
|
+
// Validate configuration structure
|
|
85
|
+
const validation = this.validateConfig(configData, { validateFilesystem: false });
|
|
83
86
|
if (!validation.valid) {
|
|
84
87
|
throw new ConfigError(
|
|
85
88
|
'Configuration validation failed',
|
|
@@ -87,6 +90,24 @@ class ConfigManager {
|
|
|
87
90
|
);
|
|
88
91
|
}
|
|
89
92
|
|
|
93
|
+
// Perform filesystem validation for each repository (unless skipped)
|
|
94
|
+
if (!skipFilesystemValidation) {
|
|
95
|
+
const filesystemErrors = [];
|
|
96
|
+
for (const repo of configData.repositories) {
|
|
97
|
+
if (repo.path && repo.name) {
|
|
98
|
+
const pathErrors = await this._validateRepositoryPath(repo.path, repo.name);
|
|
99
|
+
filesystemErrors.push(...pathErrors);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (filesystemErrors.length > 0) {
|
|
104
|
+
throw new ConfigError(
|
|
105
|
+
'Repository path validation failed',
|
|
106
|
+
{ errors: filesystemErrors }
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
90
111
|
return configData;
|
|
91
112
|
}
|
|
92
113
|
|
|
@@ -127,9 +148,11 @@ class ConfigManager {
|
|
|
127
148
|
/**
|
|
128
149
|
* Validate configuration structure and content
|
|
129
150
|
* @param {Object} config - The configuration object to validate
|
|
151
|
+
* @param {Object} options - Validation options
|
|
152
|
+
* @param {boolean} options.validateFilesystem - Whether to validate paths on filesystem (default: false)
|
|
130
153
|
* @returns {{valid: boolean, errors: string[]}} Validation result
|
|
131
154
|
*/
|
|
132
|
-
validateConfig(config) {
|
|
155
|
+
validateConfig(config, options = {}) {
|
|
133
156
|
const errors = [];
|
|
134
157
|
|
|
135
158
|
// Check if config is an object
|
|
@@ -137,14 +160,13 @@ class ConfigManager {
|
|
|
137
160
|
return { valid: false, errors: ['Configuration must be an object'] };
|
|
138
161
|
}
|
|
139
162
|
|
|
140
|
-
// Validate version field
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
} else if (typeof config.version !== 'string') {
|
|
163
|
+
// Validate version field (optional, defaults to '1.0')
|
|
164
|
+
const version = config.version || '1.0';
|
|
165
|
+
if (typeof version !== 'string') {
|
|
144
166
|
errors.push('Field "version" must be a string');
|
|
145
|
-
} else if (!this._isSupportedVersion(
|
|
167
|
+
} else if (!this._isSupportedVersion(version)) {
|
|
146
168
|
errors.push(
|
|
147
|
-
`Unsupported configuration version: ${
|
|
169
|
+
`Unsupported configuration version: ${version}. ` +
|
|
148
170
|
'Please upgrade to the latest version of kse.'
|
|
149
171
|
);
|
|
150
172
|
}
|
|
@@ -165,7 +187,7 @@ class ConfigManager {
|
|
|
165
187
|
const repoPaths = [];
|
|
166
188
|
|
|
167
189
|
config.repositories.forEach((repo, index) => {
|
|
168
|
-
const repoErrors = this._validateRepository(repo, index, config.repositories);
|
|
190
|
+
const repoErrors = this._validateRepository(repo, index, config.repositories, options.validateFilesystem);
|
|
169
191
|
errors.push(...repoErrors);
|
|
170
192
|
|
|
171
193
|
// Collect names and paths for duplicate checking
|
|
@@ -454,6 +476,94 @@ class ConfigManager {
|
|
|
454
476
|
return validPattern.test(name);
|
|
455
477
|
}
|
|
456
478
|
|
|
479
|
+
/**
|
|
480
|
+
* Check if a path is a valid Git repository
|
|
481
|
+
* @private
|
|
482
|
+
* @param {string} dirPath - Directory path to check
|
|
483
|
+
* @returns {Promise<boolean>} True if path contains a .git directory (not file)
|
|
484
|
+
*/
|
|
485
|
+
async _isGitRepository(dirPath) {
|
|
486
|
+
try {
|
|
487
|
+
const gitPath = path.join(dirPath, '.git');
|
|
488
|
+
const stats = await fs.stat(gitPath);
|
|
489
|
+
// Return true only if .git is a directory (not a file, which indicates a Git worktree)
|
|
490
|
+
return stats.isDirectory();
|
|
491
|
+
} catch (error) {
|
|
492
|
+
// Path doesn't exist, no permissions, or other error
|
|
493
|
+
return false;
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
/**
|
|
498
|
+
* Validate that a repository path exists and is a valid Git repository
|
|
499
|
+
* @private
|
|
500
|
+
* @param {string} repoPath - Repository path to validate
|
|
501
|
+
* @param {string} repoName - Repository name (for error messages)
|
|
502
|
+
* @returns {Promise<string[]>} Array of validation errors
|
|
503
|
+
*/
|
|
504
|
+
async _validateRepositoryPath(repoPath, repoName) {
|
|
505
|
+
const errors = [];
|
|
506
|
+
|
|
507
|
+
// Resolve path relative to project root
|
|
508
|
+
const absolutePath = path.isAbsolute(repoPath)
|
|
509
|
+
? repoPath
|
|
510
|
+
: path.join(this.projectRoot, repoPath);
|
|
511
|
+
|
|
512
|
+
// Check if path exists
|
|
513
|
+
try {
|
|
514
|
+
await fs.access(absolutePath);
|
|
515
|
+
} catch (error) {
|
|
516
|
+
errors.push(
|
|
517
|
+
`Repository "${repoName}": path "${repoPath}" does not exist. ` +
|
|
518
|
+
'Please check the path is correct.'
|
|
519
|
+
);
|
|
520
|
+
return errors; // Can't continue validation if path doesn't exist
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
// Check if it's a directory
|
|
524
|
+
try {
|
|
525
|
+
const stats = await fs.stat(absolutePath);
|
|
526
|
+
if (!stats.isDirectory()) {
|
|
527
|
+
errors.push(
|
|
528
|
+
`Repository "${repoName}": path "${repoPath}" is not a directory.`
|
|
529
|
+
);
|
|
530
|
+
return errors;
|
|
531
|
+
}
|
|
532
|
+
} catch (error) {
|
|
533
|
+
errors.push(
|
|
534
|
+
`Repository "${repoName}": cannot access path "${repoPath}". ${error.message}`
|
|
535
|
+
);
|
|
536
|
+
return errors;
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
// Check if .git exists
|
|
540
|
+
const gitPath = path.join(absolutePath, '.git');
|
|
541
|
+
try {
|
|
542
|
+
const gitStats = await fs.stat(gitPath);
|
|
543
|
+
|
|
544
|
+
if (gitStats.isFile()) {
|
|
545
|
+
// .git is a file, which indicates a Git worktree
|
|
546
|
+
errors.push(
|
|
547
|
+
`Repository "${repoName}": path "${repoPath}" appears to be a Git worktree (not supported). ` +
|
|
548
|
+
'Please use the main repository path instead.'
|
|
549
|
+
);
|
|
550
|
+
} else if (!gitStats.isDirectory()) {
|
|
551
|
+
errors.push(
|
|
552
|
+
`Repository "${repoName}": path "${repoPath}" has an invalid .git entry.`
|
|
553
|
+
);
|
|
554
|
+
}
|
|
555
|
+
// If .git is a directory, it's valid - no error
|
|
556
|
+
} catch (error) {
|
|
557
|
+
// .git doesn't exist
|
|
558
|
+
errors.push(
|
|
559
|
+
`Repository "${repoName}": path "${repoPath}" is not a Git repository (no .git directory found). ` +
|
|
560
|
+
'Please ensure this is a Git repository.'
|
|
561
|
+
);
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
return errors;
|
|
565
|
+
}
|
|
566
|
+
|
|
457
567
|
/**
|
|
458
568
|
* Check if configuration version is supported
|
|
459
569
|
* @private
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kiro-spec-engine",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.21.1",
|
|
4
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": {
|