kspec 1.0.11 → 1.0.13

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 (2) hide show
  1. package/package.json +1 -1
  2. package/src/index.js +27 -12
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kspec",
3
- "version": "1.0.11",
3
+ "version": "1.0.13",
4
4
  "description": "Spec-driven development workflow for Kiro CLI",
5
5
  "main": "src/index.js",
6
6
  "bin": {
package/src/index.js CHANGED
@@ -17,7 +17,12 @@ const defaultConfig = {
17
17
 
18
18
  function loadConfig() {
19
19
  if (fs.existsSync(CONFIG_FILE)) {
20
- return { ...defaultConfig, ...JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf8')) };
20
+ try {
21
+ return { ...defaultConfig, ...JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf8')) };
22
+ } catch {
23
+ console.error('Warning: Invalid config.json, using defaults');
24
+ return defaultConfig;
25
+ }
21
26
  }
22
27
  return defaultConfig;
23
28
  }
@@ -65,8 +70,9 @@ function slugify(text) {
65
70
  }
66
71
 
67
72
  function detectCli() {
68
- try { execSync('kiro-cli --version', { stdio: 'ignore' }); return 'kiro-cli'; } catch {}
69
- try { execSync('q --version', { stdio: 'ignore' }); return 'q'; } catch {}
73
+ const opts = { stdio: 'ignore', timeout: 5000 };
74
+ try { execSync('kiro-cli --version', opts); return 'kiro-cli'; } catch {}
75
+ try { execSync('q --version', opts); return 'q'; } catch {}
70
76
  return null;
71
77
  }
72
78
 
@@ -102,8 +108,14 @@ async function confirm(question) {
102
108
  function chat(message, agent) {
103
109
  const cli = requireCli();
104
110
  const args = agent ? ['chat', '--agent', agent, message] : ['chat', message];
105
- const child = spawn(cli, args, { stdio: 'inherit', shell: true });
106
- return new Promise(resolve => child.on('close', resolve));
111
+ const child = spawn(cli, args, { stdio: 'inherit' });
112
+ return new Promise((resolve, reject) => {
113
+ child.on('error', err => {
114
+ console.error(`Failed to start ${cli}: ${err.message}`);
115
+ reject(err);
116
+ });
117
+ child.on('close', resolve);
118
+ });
107
119
  }
108
120
 
109
121
  // Spec management
@@ -155,10 +167,11 @@ function getOrSelectSpec(name) {
155
167
  function getTaskStats(folder) {
156
168
  const tasksFile = path.join(folder, 'tasks.md');
157
169
  if (!fs.existsSync(tasksFile)) return null;
158
-
170
+
159
171
  const content = fs.readFileSync(tasksFile, 'utf8');
160
- const total = (content.match(/^-\s*\[[ x]\]/gm) || []).length;
161
- const done = (content.match(/^-\s*\[x\]/gim) || []).length;
172
+ // Match both [x] and [X] consistently for total and done counts
173
+ const total = (content.match(/^-\s*\[[ xX]\]/gm) || []).length;
174
+ const done = (content.match(/^-\s*\[[xX]\]/gm) || []).length;
162
175
  return { total, done, remaining: total - done };
163
176
  }
164
177
 
@@ -402,11 +415,13 @@ const commands = {
402
415
  }
403
416
  }
404
417
 
405
- // Create agents
418
+ // Create agents (skip if already exist to preserve customizations)
406
419
  for (const [file, content] of Object.entries(agentTemplates)) {
407
420
  const p = path.join(AGENTS_DIR, file);
408
- fs.writeFileSync(p, JSON.stringify(content, null, 2));
409
- log(`Created ${p}`);
421
+ if (!fs.existsSync(p)) {
422
+ fs.writeFileSync(p, JSON.stringify(content, null, 2));
423
+ log(`Created ${p}`);
424
+ }
410
425
  }
411
426
 
412
427
  console.log('\n✅ kspec initialized!\n');
@@ -717,4 +732,4 @@ async function run(args) {
717
732
  }
718
733
  }
719
734
 
720
- module.exports = { run, commands, loadConfig, detectCli, requireCli, agentTemplates };
735
+ module.exports = { run, commands, loadConfig, detectCli, requireCli, agentTemplates, getTaskStats };