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.
- package/SECURITY-AUDIT-CATASTROPHIC-DELETE.md +196 -0
- package/TEST_HOOK.md +1 -0
- package/docs/DECISIONS.md +4 -52
- package/jettypod.js +210 -24
- package/lib/chore-classifier.js +232 -0
- package/lib/chore-taxonomy.js +172 -0
- package/lib/jettypod-backup.js +124 -8
- package/lib/safe-delete.js +794 -0
- package/lib/worktree-manager.js +54 -41
- package/package.json +1 -1
- package/skills-templates/chore-mode/SKILL.md +396 -0
- package/skills-templates/chore-mode/verification.js +255 -0
- package/skills-templates/chore-planning/SKILL.md +229 -0
- package/skills-templates/epic-planning/SKILL.md +13 -5
- package/skills-templates/feature-planning/SKILL.md +113 -158
- package/skills-templates/production-mode/SKILL.md +7 -4
- package/skills-templates/speed-mode/SKILL.md +463 -471
- package/skills-templates/stable-mode/SKILL.md +371 -319
package/lib/worktree-manager.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
console.error(`Failed to cleanup worktree directory: ${
|
|
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
|
|
535
|
+
// Stage 3: Try SAFE filesystem removal (validates path again)
|
|
506
536
|
if (fs.existsSync(dirPath)) {
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
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
|
-
}
|
|
519
|
-
console.log(`⚠️
|
|
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
|
-
//
|
|
524
|
-
|
|
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
|
-
//
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
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
|
|
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
|
@@ -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
|