jettypod 4.4.70 → 4.4.71

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/jettypod.js CHANGED
@@ -2135,15 +2135,22 @@ switch (command) {
2135
2135
  }
2136
2136
  }
2137
2137
 
2138
- // Start WebSocket server for real-time updates
2138
+ // Start WebSocket server as background process for real-time updates
2139
2139
  const WS_PORT = 8080;
2140
2140
  const { getDbPath } = require('./lib/database');
2141
- try {
2142
- await wsServer.start(WS_PORT, { dbPath: getDbPath() });
2143
- } catch (err) {
2144
- // WebSocket server failed to start (port in use?) - continue without it
2145
- console.log('⚠️ WebSocket server unavailable (real-time updates disabled)');
2146
- }
2141
+ const wsServerScript = `
2142
+ const wsServer = require('./lib/ws-server');
2143
+ const { getDbPath } = require('./lib/database');
2144
+ wsServer.start(${WS_PORT}, { dbPath: getDbPath() })
2145
+ .catch(() => process.exit(1));
2146
+ `;
2147
+ const wsProcess = spawn('node', ['-e', wsServerScript], {
2148
+ cwd: __dirname,
2149
+ detached: true,
2150
+ stdio: 'ignore',
2151
+ env: { ...process.env, JETTYPOD_PROJECT_PATH: process.cwd() }
2152
+ });
2153
+ wsProcess.unref();
2147
2154
 
2148
2155
  // Start dashboard in background with project path
2149
2156
  console.log('🚀 Starting dashboard...');
@@ -1665,20 +1665,10 @@ async function mergeWork(options = {}) {
1665
1665
 
1666
1666
  console.log(`✓ Successfully merged work item #${currentWork.id}`);
1667
1667
 
1668
- // Mark work item as done
1669
- console.log('Marking work item as done...');
1670
- await new Promise((resolve, reject) => {
1671
- db.run(
1672
- `UPDATE work_items SET status = 'done', completed_at = datetime('now') WHERE id = ?`,
1673
- [currentWork.id],
1674
- (err) => {
1675
- if (err) return reject(err);
1676
- resolve();
1677
- }
1678
- );
1679
- });
1668
+ // Check if this is a test worktree (tests/ prefix) - only set scenario_file, don't mark done
1669
+ const isTestWorktree = currentBranch.startsWith('tests/');
1680
1670
 
1681
- // Get worktree info from database
1671
+ // Get worktree info from database (needed for cleanup message)
1682
1672
  const worktree = await new Promise((resolve, reject) => {
1683
1673
  db.get(
1684
1674
  `SELECT id, worktree_path, branch_name FROM worktrees WHERE work_item_id = ? AND status = 'active'`,
@@ -1690,6 +1680,65 @@ async function mergeWork(options = {}) {
1690
1680
  );
1691
1681
  });
1692
1682
 
1683
+ if (isTestWorktree) {
1684
+ // Test worktree: set scenario_file but don't mark feature as done
1685
+ console.log('📝 Test worktree detected - setting scenario_file only');
1686
+
1687
+ // Find and set scenario_file on the feature
1688
+ try {
1689
+ const addedFiles = execSync(`git diff --name-only --diff-filter=A HEAD~1 HEAD`, {
1690
+ cwd: gitRoot,
1691
+ encoding: 'utf8',
1692
+ stdio: 'pipe'
1693
+ }).trim();
1694
+
1695
+ const featureFiles = addedFiles
1696
+ .split('\n')
1697
+ .filter(f => f.endsWith('.feature') && f.startsWith('features/'));
1698
+
1699
+ if (featureFiles.length > 0) {
1700
+ const scenarioFile = featureFiles[0];
1701
+ await new Promise((resolve, reject) => {
1702
+ db.run(
1703
+ `UPDATE work_items SET scenario_file = ? WHERE id = ?`,
1704
+ [scenarioFile, currentWork.id],
1705
+ (err) => {
1706
+ if (err) return reject(err);
1707
+ resolve();
1708
+ }
1709
+ );
1710
+ });
1711
+ console.log(`✅ Set scenario_file: ${scenarioFile}`);
1712
+ }
1713
+ } catch (err) {
1714
+ console.log('⚠️ Could not auto-detect scenario file:', err.message);
1715
+ }
1716
+
1717
+ console.log(`✅ BDD tests merged for feature #${currentWork.id}`);
1718
+ console.log(' Feature remains in discovery phase - create chores to continue');
1719
+ } else if (currentWork.type !== 'chore') {
1720
+ // Non-test branch for a non-chore - this shouldn't happen
1721
+ return Promise.reject(new Error(
1722
+ `Cannot merge ${currentWork.type} #${currentWork.id} directly.\n\n` +
1723
+ `Only chores can be merged. Features complete when all their chores are done.\n` +
1724
+ `Test worktrees (tests/* branches) merge BDD scenarios without completing the feature.`
1725
+ ));
1726
+ } else {
1727
+ // Chore worktree: mark as done (existing behavior)
1728
+ console.log('Marking chore as done...');
1729
+ await new Promise((resolve, reject) => {
1730
+ db.run(
1731
+ `UPDATE work_items SET status = 'done', completed_at = datetime('now') WHERE id = ?`,
1732
+ [currentWork.id],
1733
+ (err) => {
1734
+ if (err) return reject(err);
1735
+ resolve();
1736
+ }
1737
+ );
1738
+ });
1739
+ console.log(`✅ Chore #${currentWork.id} marked as done`);
1740
+ }
1741
+
1693
1742
  // Mark worktree as merged but DON'T delete it yet
1694
1743
  // This prevents shell CWD corruption when merge is run from inside the worktree
1695
1744
  // User must run `jettypod work cleanup` separately after cd'ing to main repo
@@ -1706,8 +1755,6 @@ async function mergeWork(options = {}) {
1706
1755
  });
1707
1756
  }
1708
1757
 
1709
- console.log(`✅ Work item #${currentWork.id} marked as done`);
1710
-
1711
1758
  // Instruct user to cleanup worktree separately - be aggressive so AI doesn't forget
1712
1759
  if (worktree && worktree.worktree_path && fs.existsSync(worktree.worktree_path)) {
1713
1760
  console.log('');
@@ -764,6 +764,13 @@ function setBranch(id, branch) {
764
764
  });
765
765
  }
766
766
 
767
+ // Set scenario file
768
+ function setScenario(id, scenarioFile) {
769
+ db.run(`UPDATE work_items SET scenario_file = ? WHERE id = ?`, [scenarioFile, id], () => {
770
+ console.log(`Set #${id} scenario_file to ${scenarioFile}`);
771
+ });
772
+ }
773
+
767
774
  // Set mode
768
775
  function setMode(id, mode) {
769
776
  return new Promise((resolve, reject) => {
@@ -1584,6 +1591,13 @@ async function main() {
1584
1591
  break;
1585
1592
  }
1586
1593
 
1594
+ case 'set-scenario': {
1595
+ const id = parseInt(args[0]);
1596
+ const file = args[1];
1597
+ setScenario(id, file);
1598
+ break;
1599
+ }
1600
+
1587
1601
  case 'current': {
1588
1602
  if (!args[0]) {
1589
1603
  // No ID provided - show current work
@@ -2426,6 +2440,9 @@ Commands:
2426
2440
  jettypod work set-mode <id> <mode>
2427
2441
  Set mode (speed/discovery/stable/production)
2428
2442
 
2443
+ jettypod work set-scenario <id> <file>
2444
+ Set scenario_file for a feature (e.g., features/my-feature.feature)
2445
+
2429
2446
  jettypod work current <id>
2430
2447
  Set as current work item
2431
2448
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jettypod",
3
- "version": "4.4.70",
3
+ "version": "4.4.71",
4
4
  "description": "AI-powered development workflow manager with TDD, BDD, and automatic test generation",
5
5
  "main": "jettypod.js",
6
6
  "bin": {
@@ -0,0 +1,392 @@
1
+ ---
2
+ name: bug-mode
3
+ description: Guide implementation of standalone chores with type-appropriate guidance, verification steps, and test handling. Receives enriched context from chore-planning and executes with iteration until verification passes.
4
+ ---
5
+
6
+ # Bug Mode Skill
7
+
8
+ ```
9
+ ┌─────────────────────────────────────────────────────────────────────┐
10
+ │ Bug Fix Flow │
11
+ │ │
12
+ │ Bug Planning → [BUG MODE] → Done │
13
+ │ ▲▲▲▲▲▲▲▲▲▲ │
14
+ │ YOU ARE HERE │
15
+ │ │
16
+ │ Single pass: Covers speed through stable (internal) or │
17
+ │ through production (external) comprehensively. │
18
+ └─────────────────────────────────────────────────────────────────────┘
19
+ ```
20
+
21
+ ## Key Difference from Feature Modes
22
+
23
+ **Bug fixes do NOT follow speed → stable → production progression.**
24
+
25
+ - **Features:** Iterative refinement (speed makes it work, stable makes it robust, production makes it scalable)
26
+ - **Bugs:** Single comprehensive fix (fix the root cause properly the first time)
27
+
28
+ Why? A bug fix should:
29
+ 1. Fix the root cause completely
30
+ 2. Include proper error handling from the start
31
+ 3. Pass the regression test
32
+ 4. Be production-ready immediately
33
+
34
+ ---
35
+
36
+ Guides Claude Code through comprehensive bug fix implementation. Receives context from bug-planning skill (root cause, breadcrumbs, regression test).
37
+
38
+ ## Instructions
39
+
40
+ When this skill is activated, you are implementing a bug fix chore. The bug-planning skill has already:
41
+ - Identified root cause
42
+ - Created the bug work item and fix chore
43
+ - Written a regression test (currently failing)
44
+ - Started the worktree with `work start`
45
+
46
+ Your job: Make the regression test pass with a comprehensive fix.
47
+
48
+ ## 🔑 Critical Context
49
+
50
+ **You are working in an isolated git worktree:**
51
+ - `work start [chore-id]` already created a dedicated worktree
52
+ - All file operations must use **absolute paths** from the worktree
53
+ - The worktree has its own branch - changes are isolated from main
54
+
55
+ **Worktree path is available in Step 0 output** - use it for all file operations.
56
+
57
+ ---
58
+
59
+ ## 🚨 SHELL CWD RECOVERY
60
+
61
+ **If ALL bash commands start failing with "Error: Exit code 1" and no output:**
62
+
63
+ Your shell's working directory was likely inside a worktree that was deleted. The CWD no longer exists.
64
+
65
+ **Recovery steps:**
66
+ 1. Get the main repo path from your session context
67
+ 2. Run: `cd <main-repo-path>`
68
+ 3. Verify: `pwd && ls .jettypod`
69
+ 4. Resume your work
70
+
71
+ ---
72
+
73
+ ## 🛑 PRE-FLIGHT VALIDATION (REQUIRED)
74
+
75
+ **Before proceeding, validate the worktree exists.**
76
+
77
+ ```bash
78
+ sqlite3 .jettypod/work.db "SELECT wi.id, wi.title, wi.status, wt.worktree_path, wt.branch_name FROM work_items wi LEFT JOIN worktrees wt ON wi.id = wt.work_item_id WHERE wi.status = 'in_progress' AND wi.type = 'chore'"
79
+ ```
80
+
81
+ **Check the result:**
82
+
83
+ | worktree_path | What it means | Action |
84
+ |---------------|---------------|--------|
85
+ | **Has a path** | ✅ Worktree exists, ready to proceed | Continue to Step 0 |
86
+ | **NULL or empty** | ❌ `work start` was not called | **STOP - run `jettypod work start [chore-id]` first** |
87
+ | **No rows returned** | ❌ No chore is in progress | **STOP - verify the chore exists and run `work start`** |
88
+
89
+ ---
90
+
91
+ ## Implementation Steps
92
+
93
+ ### Step 0: Initialize Bug Mode Context
94
+
95
+ **Get the current work context:**
96
+
97
+ ```bash
98
+ sqlite3 .jettypod/work.db "SELECT wi.id, wi.title, wi.description, wi.parent_id, parent.title as parent_title, parent.type as parent_type, wt.worktree_path, wt.branch_name FROM work_items wi LEFT JOIN work_items parent ON wi.parent_id = parent.id LEFT JOIN worktrees wt ON wi.id = wt.work_item_id WHERE wi.status = 'in_progress' AND wi.type = 'chore'"
99
+ ```
100
+
101
+ **Verify parent is a bug:**
102
+ - `parent_type` should be `bug`
103
+ - If not, this skill may not be appropriate
104
+
105
+ **Extract breadcrumbs from chore description:**
106
+ The bug-planning skill embedded implementation guidance:
107
+ - Root cause location (file:line)
108
+ - Fix approach (steps)
109
+ - Files to modify
110
+ - Verification criteria
111
+
112
+ **Display to user:**
113
+
114
+ ```
115
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
116
+ 🐛 BUG MODE: Fixing #[bug-id]
117
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
118
+
119
+ Chore: [title]
120
+ Bug: #[parent-id] [parent-title]
121
+ Worktree: [worktree_path]
122
+ Branch: [branch_name]
123
+
124
+ Root Cause:
125
+ [From breadcrumbs - what's broken and where]
126
+
127
+ Fix Approach:
128
+ [From breadcrumbs - steps to fix]
129
+
130
+ Establishing RED baseline...
131
+ ```
132
+
133
+ **Proceed to Step 1.**
134
+
135
+ ---
136
+
137
+ ### Step 1: Establish RED Baseline
138
+
139
+ **Run the regression test to confirm it fails:**
140
+
141
+ ```bash
142
+ # Find the regression test file
143
+ sqlite3 .jettypod/work.db "SELECT id FROM work_items WHERE id = <bug-id>"
144
+ # Look for features/*<bug-id>*.feature or features/*<bug-slug>*.feature
145
+ ```
146
+
147
+ ```bash
148
+ # Run the regression test
149
+ npx cucumber-js features/<bug-slug>.feature --format progress
150
+ ```
151
+
152
+ **Confirm RED state:**
153
+ - The regression test should FAIL
154
+ - This proves the bug exists and the test catches it
155
+
156
+ **Display RED baseline:**
157
+
158
+ ```
159
+ 🔴 RED Baseline Confirmed
160
+
161
+ Regression test: features/<bug-slug>.feature
162
+ Status: FAILING (as expected)
163
+
164
+ Error:
165
+ [Error message from test]
166
+
167
+ 🎯 Goal: Make the regression test pass with a comprehensive fix
168
+
169
+ Now implementing fix...
170
+ ```
171
+
172
+ **Proceed to Step 2.**
173
+
174
+ ---
175
+
176
+ ### Step 2: Implement Comprehensive Fix
177
+
178
+ **CRITICAL:** Bug fixes must be comprehensive from the start.
179
+
180
+ **Use breadcrumbs to guide implementation:**
181
+ 1. Navigate to the root cause location
182
+ 2. Understand the surrounding code
183
+ 3. Implement the fix following the approach from bug-planning
184
+ 4. Add proper error handling (don't just fix the happy path)
185
+ 5. Consider edge cases related to the bug
186
+
187
+ **What "comprehensive" means:**
188
+
189
+ **INTERNAL projects (project_state = 'internal'):**
190
+ - Fix the root cause
191
+ - Add validation to prevent the bug condition
192
+ - Handle the error gracefully if it somehow occurs
193
+ - Ensure related edge cases are covered
194
+
195
+ **EXTERNAL projects (project_state = 'external'):**
196
+ - Everything for internal, PLUS:
197
+ - Consider security implications
198
+ - Add logging for debugging
199
+ - Ensure graceful degradation
200
+ - Consider concurrent access if relevant
201
+
202
+ **Check project state:**
203
+
204
+ ```bash
205
+ sqlite3 .jettypod/work.db "SELECT project_state FROM project_config WHERE id = 1"
206
+ ```
207
+
208
+ **Implement iteratively:**
209
+
210
+ ```
211
+ ━━━ Iteration 1 ━━━
212
+ 📂 Reading: [file:line from breadcrumbs]
213
+ 🔧 Change: [what you're fixing]
214
+ ```
215
+
216
+ **After each change, run the regression test:**
217
+
218
+ ```bash
219
+ npx cucumber-js features/<bug-slug>.feature --format progress
220
+ ```
221
+
222
+ **Track progress:**
223
+
224
+ ```
225
+ ━━━ Iteration 2 ━━━
226
+ 🧪 Running regression test...
227
+ 📊 Status: Still failing
228
+ 🔧 Next: [what else needs to change]
229
+ ```
230
+
231
+ **Continue until GREEN:**
232
+
233
+ ```
234
+ 🎉 GREEN: Regression test passing!
235
+
236
+ Fix implemented:
237
+ - [Change 1]
238
+ - [Change 2]
239
+ - [Error handling added]
240
+
241
+ Now verifying no regressions...
242
+ ```
243
+
244
+ **Proceed to Step 3.**
245
+
246
+ ---
247
+
248
+ ### Step 3: Verify No Regressions
249
+
250
+ **Run the full test suite to ensure the fix didn't break anything:**
251
+
252
+ ```bash
253
+ # Run all BDD tests
254
+ npx cucumber-js --format progress
255
+
256
+ # Run unit tests if they exist
257
+ npm test 2>/dev/null || echo "No unit tests configured"
258
+ ```
259
+
260
+ **If regressions found:**
261
+
262
+ ```
263
+ ⚠️ Regression Detected
264
+
265
+ Failing test: [test name]
266
+ Error: [error message]
267
+
268
+ Investigating...
269
+ ```
270
+
271
+ Fix the regression and re-run tests. Iterate until all tests pass.
272
+
273
+ **When all tests pass:**
274
+
275
+ ```
276
+ ✅ All Tests Passing
277
+
278
+ - Regression test: ✅ PASS
279
+ - Other BDD tests: ✅ [X] scenarios passing
280
+ - Unit tests: ✅ [Y] tests passing (if applicable)
281
+
282
+ Ready to commit and merge.
283
+ ```
284
+
285
+ **Proceed to Step 4.**
286
+
287
+ ---
288
+
289
+ ### Step 4: Commit and Merge
290
+
291
+ **Commit the fix:**
292
+
293
+ ```bash
294
+ git add . && git commit -m "fix: [Brief description of the bug fix]
295
+
296
+ Root cause: [What was broken]
297
+ Fix: [What was changed]
298
+
299
+ Closes #<bug-id>
300
+
301
+ 🤖 Generated with [Claude Code](https://claude.com/claude-code)
302
+
303
+ Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>"
304
+ ```
305
+
306
+ **Merge (3 steps):**
307
+
308
+ ```bash
309
+ # Step 1: Merge (can run from worktree - it won't delete it)
310
+ jettypod work merge
311
+ ```
312
+
313
+ ```bash
314
+ # Step 2: cd to main repo
315
+ cd <main-repo-path>
316
+ pwd && ls .jettypod # verify
317
+ ```
318
+
319
+ ```bash
320
+ # Step 3: Clean up the worktree
321
+ jettypod work cleanup <chore-id>
322
+ ```
323
+
324
+ **Proceed to Step 5.**
325
+
326
+ ---
327
+
328
+ ### Step 5: Mark Bug as Done
329
+
330
+ **After the fix chore is merged, mark the parent bug as done:**
331
+
332
+ ```bash
333
+ jettypod work status <bug-id> done
334
+ ```
335
+
336
+ **Display completion:**
337
+
338
+ ```
339
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
340
+ ✅ Bug Fix Complete
341
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
342
+
343
+ 🐛 Bug: #[bug-id] [title]
344
+ 🔧 Fix: #[chore-id] [title]
345
+ 🧪 Regression test: ✅ Passing
346
+
347
+ What was fixed:
348
+ - Root cause: [brief description]
349
+ - Fix: [what changed]
350
+ - Prevention: [validation/error handling added]
351
+
352
+ The bug is now fixed and protected by a regression test.
353
+ ```
354
+
355
+ **End bug-mode skill.**
356
+
357
+ ---
358
+
359
+ ## Validation Checklist
360
+
361
+ Before ending bug-mode skill, ensure:
362
+ - [ ] Regression test was failing (RED baseline confirmed)
363
+ - [ ] Fix implemented comprehensively (not just happy path)
364
+ - [ ] Regression test now passes (GREEN)
365
+ - [ ] No other tests broken (no regressions)
366
+ - [ ] Fix committed with descriptive message
367
+ - [ ] Chore merged to main
368
+ - [ ] Worktree cleaned up
369
+ - [ ] Bug marked as done
370
+
371
+ ---
372
+
373
+ ## Command Reference
374
+
375
+ **Merge fix (CRITICAL: cd to main repo separately):**
376
+ ```bash
377
+ jettypod work merge # Merge current chore
378
+ ```
379
+
380
+ ```bash
381
+ cd <main-repo> # Change to main repo
382
+ jettypod work cleanup <id> # Clean up worktree
383
+ ```
384
+
385
+ **Mark bug complete:**
386
+ ```bash
387
+ jettypod work status <bug-id> done
388
+ ```
389
+
390
+ **❌ DO NOT use these to complete chores:**
391
+ - `jettypod work status <chore-id> done`
392
+ - `jettypod work complete <id>`