jettypod 4.3.0 → 4.4.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.
@@ -14,6 +14,9 @@
14
14
  // Database will be required lazily when implementing actual functions
15
15
  // const getDb = require('./database');
16
16
 
17
+ // Safe delete module - ALWAYS use this for deletions
18
+ const safeDelete = require('./safe-delete');
19
+
17
20
  /**
18
21
  * Valid worktree statuses
19
22
  */
@@ -44,9 +47,16 @@ async function createWorktree(workItem, options = {}) {
44
47
  return Promise.reject(new Error('SAFETY: repoPath must be explicitly provided to createWorktree'));
45
48
  }
46
49
 
50
+ // SAFETY CHECK 0: Verify we're not running from within a worktree
51
+ try {
52
+ safeDelete.ensureNotInWorktree();
53
+ } catch (err) {
54
+ return Promise.reject(err);
55
+ }
56
+
47
57
  const gitRoot = options.repoPath;
48
58
 
49
- // SAFETY CHECK: Verify gitRoot is actually the main repository
59
+ // SAFETY CHECK 1: Verify gitRoot is actually the main repository
50
60
  try {
51
61
  const gitRootCheck = execSync('git rev-parse --show-toplevel', {
52
62
  cwd: gitRoot,
@@ -205,7 +215,11 @@ async function createWorktree(workItem, options = {}) {
205
215
  }
206
216
  } else {
207
217
  // It's a directory - remove it and create symlink
208
- fs.rmSync(jettypodLink, { recursive: true, force: true });
218
+ // SAFETY: Use safe delete with gitRoot validation
219
+ const deleteResult = safeDelete.safeRmRecursive(jettypodLink, { gitRoot, force: true });
220
+ if (!deleteResult.success) {
221
+ throw new Error(`Failed to remove .jettypod directory: ${deleteResult.error}`);
222
+ }
209
223
  fs.symlinkSync(jettypodTarget, jettypodLink, 'dir');
210
224
  }
211
225
  } else {
@@ -324,10 +338,10 @@ async function createWorktree(workItem, options = {}) {
324
338
 
325
339
  // Cleanup directory
326
340
  if (fs.existsSync(worktreePath)) {
327
- try {
328
- fs.rmSync(worktreePath, { recursive: true, force: true });
329
- } catch (fsErr) {
330
- console.error(`Failed to cleanup worktree directory: ${fsErr.message}`);
341
+ // SAFETY: Use safe delete with gitRoot validation
342
+ const deleteResult = safeDelete.safeRmRecursive(worktreePath, { gitRoot, force: true });
343
+ if (!deleteResult.success) {
344
+ console.error(`Failed to cleanup worktree directory: ${deleteResult.error}`);
331
345
  }
332
346
  }
333
347
 
@@ -478,12 +492,27 @@ async function removeDirectoryResilient(dirPath, gitRoot) {
478
492
  const fs = require('fs');
479
493
  const { execSync } = require('child_process');
480
494
 
495
+ // CRITICAL SAFETY: Validate path before ANY deletion attempt
496
+ const validation = safeDelete.validatePath(dirPath, gitRoot);
497
+ if (!validation.safe) {
498
+ throw new Error(`SAFETY: Cannot remove directory - ${validation.reason}`);
499
+ }
500
+
501
+ // Additional safety: Ensure dirPath is within .jettypod-work
502
+ const path = require('path');
503
+ const resolvedDir = path.resolve(dirPath);
504
+ const worktreeBase = path.resolve(gitRoot, '.jettypod-work');
505
+ if (!resolvedDir.startsWith(worktreeBase)) {
506
+ throw new Error(`SAFETY: Can only remove directories within .jettypod-work/. Got: ${dirPath}`);
507
+ }
508
+
481
509
  // Stage 1: Try standard git worktree remove (silent)
482
510
  try {
483
511
  execSync(`git worktree remove "${dirPath}"`, {
484
512
  cwd: gitRoot,
485
513
  stdio: 'pipe'
486
514
  });
515
+ safeDelete.logDeletion(dirPath, 'git-worktree-remove', true);
487
516
  return; // Success - exit silently
488
517
  } catch (stage1Err) {
489
518
  // Stage 1 failed - escalate with logging
@@ -497,16 +526,18 @@ async function removeDirectoryResilient(dirPath, gitRoot) {
497
526
  stdio: 'pipe'
498
527
  });
499
528
  console.log(`✓ Forced git removal succeeded`);
529
+ safeDelete.logDeletion(dirPath, 'git-worktree-remove-force', true);
500
530
  return;
501
531
  } catch (stage2Err) {
502
- console.log(`⚠️ Forced git removal failed, escalating to filesystem removal...`);
532
+ console.log(`⚠️ Forced git removal failed, escalating to safe filesystem removal...`);
503
533
  }
504
534
 
505
- // Stage 3: Try filesystem removal with force
535
+ // Stage 3: Try SAFE filesystem removal (validates path again)
506
536
  if (fs.existsSync(dirPath)) {
507
- try {
508
- fs.rmSync(dirPath, { recursive: true, force: true });
509
- console.log(`✓ Filesystem removal succeeded`);
537
+ const deleteResult = safeDelete.safeRmRecursive(dirPath, { gitRoot, force: true });
538
+
539
+ if (deleteResult.success) {
540
+ console.log(`✓ Safe filesystem removal succeeded`);
510
541
 
511
542
  // Clean up git metadata
512
543
  try {
@@ -515,25 +546,14 @@ async function removeDirectoryResilient(dirPath, gitRoot) {
515
546
  // Non-fatal
516
547
  }
517
548
  return;
518
- } catch (stage3Err) {
519
- console.log(`⚠️ Filesystem removal failed, escalating to manual deletion...`);
549
+ } else {
550
+ console.log(`⚠️ Safe filesystem removal failed: ${deleteResult.error}`);
551
+ throw new Error(`Directory removal failed: ${deleteResult.error}`);
520
552
  }
521
553
  }
522
554
 
523
- // Stage 4: Manual recursive deletion (last resort)
524
- try {
525
- await manualRecursiveDelete(dirPath);
526
- console.log(`✓ Manual recursive deletion succeeded`);
527
-
528
- // Clean up git metadata
529
- try {
530
- execSync('git worktree prune', { cwd: gitRoot, stdio: 'pipe' });
531
- } catch (pruneErr) {
532
- // Non-fatal
533
- }
534
- } catch (stage4Err) {
535
- throw new Error(`All removal strategies failed: ${stage4Err.message}`);
536
- }
555
+ // If we get here, directory doesn't exist - that's fine
556
+ console.log(`✓ Directory already removed or doesn't exist`);
537
557
  }
538
558
 
539
559
  /**
@@ -566,21 +586,14 @@ async function cleanupWorktree(worktreeId, options = {}) {
566
586
  const db = options.db || getDb();
567
587
  const deleteBranch = options.deleteBranch || false;
568
588
 
569
- // SAFETY CHECK 1: Verify we're not running from within a worktree
570
- try {
571
- const currentGitDir = execSync('git rev-parse --git-dir', {
572
- cwd: process.cwd(),
573
- encoding: 'utf8'
574
- }).trim();
575
-
576
- if (currentGitDir.includes('.jettypod-work') || currentGitDir !== '.git') {
577
- return Promise.reject(new Error('SAFETY: Cannot run cleanup from within a worktree'));
578
- }
579
- } catch (err) {
580
- // Ignore - might not be in a git repo
581
- }
589
+ // NOTE: We intentionally do NOT check ensureNotInWorktree() here.
590
+ // The merge workflow (jettypod work merge) is designed to be run from
591
+ // within the worktree being merged. Safety comes from:
592
+ // 1. Requiring explicit repoPath (not relying on process.cwd())
593
+ // 2. Verifying repoPath is the main repo (check below)
594
+ // 3. Path validation in removeDirectoryResilient()
582
595
 
583
- // SAFETY CHECK 2: Verify gitRoot is actually the main repository
596
+ // SAFETY CHECK: Verify gitRoot is actually the main repository
584
597
  try {
585
598
  const gitRootCheck = execSync('git rev-parse --show-toplevel', {
586
599
  cwd: gitRoot,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jettypod",
3
- "version": "4.3.0",
3
+ "version": "4.4.1",
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,396 @@
1
+ ---
2
+ name: chore-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
+ # Chore Mode Skill
7
+
8
+ ```
9
+ ┌─────────────────────────────────────────────────────────────────────┐
10
+ │ Standalone Chore Execution │
11
+ │ │
12
+ │ chore-planning → [CHORE MODE] → Done │
13
+ │ ▲▲▲▲▲▲▲▲▲▲▲ │
14
+ │ YOU ARE HERE │
15
+ │ │
16
+ │ Chores are focused tasks - no speed/stable/production progression. │
17
+ │ Execute once with type-appropriate verification, then done. │
18
+ └─────────────────────────────────────────────────────────────────────┘
19
+ ```
20
+
21
+ Guides Claude Code through chore execution with type-specific guidance, test handling, and verification criteria from the chore taxonomy.
22
+
23
+ ## Instructions
24
+
25
+ When this skill is activated, you are executing a standalone chore. The chore-planning skill has already classified the type and built enriched context. Follow this structured approach:
26
+
27
+ ### Overview
28
+
29
+ **Chore Mode Goal:** Execute the chore according to type-specific guidance and verify completion using taxonomy criteria.
30
+
31
+ **Key Principles:**
32
+ - **Type-aware execution** - Different chore types have different test handling and verification
33
+ - **Guided verification** - Use taxonomy verification checklist, not arbitrary checks
34
+ - **Iteration with limits** - Max 5 iterations to achieve verification
35
+ - **No mode progression** - Chores don't have speed/stable/production phases
36
+
37
+ **Chore Types Quick Reference:**
38
+
39
+ | Type | Test Handling | Key Constraint |
40
+ |------|---------------|----------------|
41
+ | refactor | Affected tests only | Do NOT modify test assertions |
42
+ | dependency | Full test suite | Check for deprecation warnings |
43
+ | cleanup | Affected tests | Verify code is actually unused |
44
+ | tooling | CI/manual verification | Focus on verification over unit tests |
45
+
46
+ ---
47
+
48
+ ## Implementation Steps
49
+
50
+ ### Step 1: Receive and Display Context
51
+
52
+ **Your task:** Acknowledge the context passed from chore-planning.
53
+
54
+ You will receive:
55
+ - `choreContext.chore` - Chore ID, title, description
56
+ - `choreContext.classification` - Type and confidence
57
+ - `choreContext.guidance` - Scope, verification, testHandling from taxonomy
58
+ - `choreContext.implementationPlan` - Files to modify, affected tests
59
+
60
+ **Display:**
61
+
62
+ ```
63
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
64
+ 🔧 Chore Mode: [Chore Title]
65
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
66
+
67
+ Type: [TYPE] (confidence: [high/medium/low])
68
+ Chore ID: #[id]
69
+
70
+ Implementation Plan:
71
+ • Files to modify: [list from context]
72
+ • Affected tests: [list from context]
73
+ ```
74
+
75
+ **Move to Step 2 automatically.**
76
+
77
+ ### Step 2: Create Worktree
78
+
79
+ **Your task:** Create an isolated worktree for this chore.
80
+
81
+ ```bash
82
+ jettypod work start [chore-id]
83
+ ```
84
+
85
+ This creates a worktree at `.jettypod-work/[id]-[title-slug]` and switches to a new branch.
86
+
87
+ **Display:**
88
+
89
+ ```
90
+ 📁 Worktree created: .jettypod-work/[id]-[title-slug]
91
+ Branch: chore-[id]-[title-slug]
92
+ ```
93
+
94
+ **Move to Step 3 automatically.**
95
+
96
+ ### Step 3: Establish Test Baseline
97
+
98
+ **Your task:** Run tests to establish baseline before making changes.
99
+
100
+ **Test handling varies by type:**
101
+
102
+ **For REFACTOR:**
103
+ ```bash
104
+ # Run only affected module tests
105
+ npm test -- [affected-test-patterns]
106
+ ```
107
+
108
+ **For DEPENDENCY:**
109
+ ```bash
110
+ # Run full test suite
111
+ npm test
112
+ ```
113
+
114
+ **For CLEANUP:**
115
+ ```bash
116
+ # Run affected tests
117
+ npm test -- [affected-test-patterns]
118
+ ```
119
+
120
+ **For TOOLING:**
121
+ ```bash
122
+ # Run CI pipeline or specific verification
123
+ # (may not have unit tests)
124
+ ```
125
+
126
+ **Display:**
127
+
128
+ ```
129
+ 🧪 Establishing test baseline...
130
+
131
+ Baseline Result:
132
+ Tests: [X] passing / [Y] total
133
+ Execution time: [Z]s
134
+
135
+ ✅ Baseline established - all tests passing
136
+ ```
137
+
138
+ **CRITICAL:** If baseline tests fail, STOP. Fix existing failures before proceeding with chore work.
139
+
140
+ **Move to Step 4 automatically.**
141
+
142
+ ### Step 4: Display Type-Specific Guidance
143
+
144
+ **Your task:** Display warnings and constraints based on chore type.
145
+
146
+ **Load guidance from taxonomy:**
147
+
148
+ ```javascript
149
+ const { getGuidance } = require('./lib/chore-taxonomy');
150
+ const guidance = getGuidance('[chore-type]');
151
+ ```
152
+
153
+ **Display type-specific warnings:**
154
+
155
+ **For REFACTOR:**
156
+ ```
157
+ ⚠️ REFACTOR CONSTRAINTS:
158
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
159
+ • All existing tests MUST pass WITHOUT modification
160
+ • If tests fail, the refactor broke behavior - FIX THE CODE, not the tests
161
+ • No new functionality - this is restructuring only
162
+ • Behavior must be preserved exactly
163
+ ```
164
+
165
+ **For DEPENDENCY:**
166
+ ```
167
+ ⚠️ DEPENDENCY CONSTRAINTS:
168
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
169
+ • Run FULL test suite to catch regressions
170
+ • Check for deprecation warnings after update
171
+ • Review changelog for breaking changes
172
+ • Update code if API changed
173
+ ```
174
+
175
+ **For CLEANUP:**
176
+ ```
177
+ ⚠️ CLEANUP CONSTRAINTS:
178
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
179
+ • VERIFY code is actually unused before deleting
180
+ • Search for all references (grep for function names)
181
+ • Remove tests ONLY if they test deleted code
182
+ • Check for dynamic references (string-based imports)
183
+ ```
184
+
185
+ **For TOOLING:**
186
+ ```
187
+ ⚠️ TOOLING CONSTRAINTS:
188
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
189
+ • Verify via CI run or manual testing
190
+ • Focus on verification over unit testing
191
+ • Document current behavior before changes
192
+ • Plan rollback strategy
193
+ ```
194
+
195
+ **Move to Step 5 automatically.**
196
+
197
+ ### Step 5: Execute with Iteration
198
+
199
+ **Your task:** Make changes and iterate until tests pass. Max 5 iterations.
200
+
201
+ ```
202
+ ━━━ Iteration [N]/5 ━━━
203
+
204
+ ✍️ Making changes...
205
+ [Describe what you're changing]
206
+
207
+ 🧪 Running tests...
208
+ ```
209
+
210
+ **On each iteration:**
211
+ 1. Make focused changes based on implementation plan
212
+ 2. Run appropriate tests (type-dependent)
213
+ 3. Check results
214
+
215
+ **Display progress:**
216
+
217
+ ```
218
+ 📊 Progress: [X]/[Y] tests passing
219
+
220
+ ✅ Newly passing:
221
+ • [test name]
222
+
223
+ ❌ Still failing:
224
+ • [test name]: [brief error]
225
+
226
+ 🔧 Next: [what you'll fix]
227
+ ```
228
+
229
+ **Exit conditions:**
230
+ - ✅ All tests pass → Move to Step 6
231
+ - ❌ Max iterations reached → Display failure, ask user for guidance
232
+
233
+ **On max iterations:**
234
+
235
+ ```
236
+ ⚠️ Maximum iterations (5) reached
237
+
238
+ Final Progress: [X]/[Y] tests passing
239
+
240
+ Still failing:
241
+ • [test name]: [error]
242
+
243
+ Options:
244
+ 1. Review implementation approach
245
+ 2. Break into smaller changes
246
+ 3. Get user guidance
247
+
248
+ What would you like to do?
249
+ ```
250
+
251
+ **STOP and wait for user input if max iterations reached.**
252
+
253
+ ### Step 6: Run Verification Checklist
254
+
255
+ **Your task:** Run through type-specific verification criteria from taxonomy.
256
+
257
+ **Load verification from taxonomy:**
258
+
259
+ ```javascript
260
+ const { getGuidance } = require('./lib/chore-taxonomy');
261
+ const guidance = getGuidance('[chore-type]');
262
+ // guidance.verification contains the checklist
263
+ ```
264
+
265
+ **Display and verify each item:**
266
+
267
+ ```
268
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
269
+ 🔍 Verification Checklist
270
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
271
+
272
+ [✅/❌] All existing tests pass without modification
273
+ [✅/❌] No new functionality added
274
+ [✅/❌] Code review confirms behavior preservation
275
+ [✅/❌] Performance is not degraded
276
+ ```
277
+
278
+ **Verification methods:**
279
+ - **Tests pass**: Run `npm test` and check exit code
280
+ - **No new functionality**: Review diff for new features
281
+ - **Behavior preservation**: Compare before/after behavior
282
+ - **Performance**: Run benchmarks if applicable
283
+
284
+ **If any verification fails:**
285
+
286
+ ```
287
+ ❌ Verification failed:
288
+ • [failed item]: [reason]
289
+
290
+ Returning to iteration loop...
291
+ ```
292
+
293
+ Go back to Step 5 to fix issues.
294
+
295
+ **If all verification passes → Move to Step 7.**
296
+
297
+ ### Step 7: Complete and Merge
298
+
299
+ **Your task:** Commit changes and merge to main.
300
+
301
+ ```bash
302
+ # Stage and commit
303
+ git add .
304
+ git commit -m "chore: [brief description]"
305
+ git push
306
+
307
+ # Merge to main (auto-marks chore done)
308
+ jettypod work merge
309
+ ```
310
+
311
+ **Display:**
312
+
313
+ ```
314
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
315
+ ✅ Chore Complete
316
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
317
+
318
+ Type: [TYPE]
319
+ Iterations: [N]/5
320
+ Tests: [X]/[Y] passing
321
+
322
+ Verification:
323
+ ✅ All existing tests pass without modification
324
+ ✅ No new functionality added
325
+ ✅ Code review confirms behavior preservation
326
+ ✅ Performance is not degraded
327
+
328
+ Merged to main. Chore #[id] marked done.
329
+ ```
330
+
331
+ **End skill.**
332
+
333
+ ---
334
+
335
+ ## Error Handling
336
+
337
+ ### Baseline Tests Fail
338
+ ```
339
+ ❌ Cannot proceed - baseline tests failing
340
+
341
+ [X] tests failing before chore work started.
342
+ Fix existing test failures before proceeding.
343
+
344
+ Failing tests:
345
+ • [test name]: [error]
346
+ ```
347
+
348
+ ### Verification Loop
349
+ If verification fails repeatedly (3+ times on same item):
350
+ ```
351
+ ⚠️ Verification stuck on: [item]
352
+
353
+ This has failed [N] times. Options:
354
+ 1. Review the implementation approach
355
+ 2. Check if this verification is applicable
356
+ 3. Ask user for guidance
357
+ ```
358
+
359
+ ### Worktree Issues
360
+ ```
361
+ ❌ Worktree creation failed
362
+
363
+ Error: [message]
364
+
365
+ Try:
366
+ jettypod work cleanup
367
+ jettypod work start [chore-id]
368
+ ```
369
+
370
+ ---
371
+
372
+ ## Type Reference
373
+
374
+ ### REFACTOR
375
+ - **Goal:** Restructure code without changing behavior
376
+ - **Tests:** Affected modules only
377
+ - **Key rule:** NEVER modify test assertions
378
+ - **Verification:** Tests pass, behavior unchanged
379
+
380
+ ### DEPENDENCY
381
+ - **Goal:** Update packages safely
382
+ - **Tests:** Full suite
383
+ - **Key rule:** Check changelogs for breaking changes
384
+ - **Verification:** Tests pass, no deprecation warnings
385
+
386
+ ### CLEANUP
387
+ - **Goal:** Remove unused code
388
+ - **Tests:** Affected modules
389
+ - **Key rule:** Verify code is actually unused
390
+ - **Verification:** No broken references, tests pass
391
+
392
+ ### TOOLING
393
+ - **Goal:** Improve build/CI/dev tools
394
+ - **Tests:** CI pipeline or manual
395
+ - **Key rule:** Plan rollback strategy
396
+ - **Verification:** CI passes, workflows work