jettypod 4.1.5 → 4.2.0
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/lib/claudemd.js +9 -60
- package/lib/session-writer.js +150 -0
- package/lib/worktree-manager.js +27 -2
- package/package.json +1 -1
- package/skills-templates/feature-planning/SKILL.md +51 -180
- package/skills-templates/speed-mode/SKILL.md +65 -13
package/lib/claudemd.js
CHANGED
|
@@ -2,6 +2,7 @@ const fs = require('fs');
|
|
|
2
2
|
const path = require('path');
|
|
3
3
|
const config = require('./config');
|
|
4
4
|
const { getBugWorkflowForClaudeMd } = require('./bug-workflow');
|
|
5
|
+
const { writeSessionFile } = require('./session-writer');
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Get absolute path to CLAUDE.md file
|
|
@@ -41,7 +42,8 @@ function validateCurrentWork(currentWork) {
|
|
|
41
42
|
// See .claude/skills/ directory for skill implementations
|
|
42
43
|
|
|
43
44
|
/**
|
|
44
|
-
* Update current work
|
|
45
|
+
* Update current work - writes to session file instead of CLAUDE.md
|
|
46
|
+
* Session file is gitignored to prevent merge conflicts and stale context
|
|
45
47
|
* @param {Object} currentWork - Current work item to display
|
|
46
48
|
* @param {string|null} mode - Work item mode (null for epics, undefined to read from config)
|
|
47
49
|
* @throws {Error} If currentWork is invalid or file cannot be written
|
|
@@ -49,19 +51,6 @@ function validateCurrentWork(currentWork) {
|
|
|
49
51
|
function updateCurrentWork(currentWork, mode) {
|
|
50
52
|
validateCurrentWork(currentWork);
|
|
51
53
|
|
|
52
|
-
const claudePath = getClaudeMdPath();
|
|
53
|
-
|
|
54
|
-
if (!fs.existsSync(claudePath)) {
|
|
55
|
-
return;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
let content;
|
|
59
|
-
try {
|
|
60
|
-
content = fs.readFileSync(claudePath, 'utf-8');
|
|
61
|
-
} catch (err) {
|
|
62
|
-
throw new Error(`Failed to read CLAUDE.md: ${err.message}`);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
54
|
// Use provided mode
|
|
66
55
|
// null = epic (no mode), undefined = fallback to config for backwards compatibility
|
|
67
56
|
let currentMode = mode;
|
|
@@ -74,53 +63,13 @@ function updateCurrentWork(currentWork, mode) {
|
|
|
74
63
|
}
|
|
75
64
|
}
|
|
76
65
|
|
|
77
|
-
//
|
|
78
|
-
|
|
79
|
-
Working on: [#${currentWork.id}] ${currentWork.title} (${currentWork.type})`;
|
|
80
|
-
|
|
81
|
-
if (currentWork.epic_title && currentWork.epic_id !== currentWork.id) {
|
|
82
|
-
newCurrentWork += `
|
|
83
|
-
Epic: [#${currentWork.epic_id}] ${currentWork.epic_title}`;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// Only add Mode line if mode is not null (epics don't have modes)
|
|
87
|
-
if (currentMode !== null) {
|
|
88
|
-
newCurrentWork += `
|
|
89
|
-
Mode: ${currentMode}`;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
newCurrentWork += `
|
|
93
|
-
Status: ${currentWork.status}
|
|
94
|
-
</current_work>`;
|
|
95
|
-
|
|
96
|
-
// Replace existing current_work section or add after project context
|
|
97
|
-
if (content.includes('<current_work>')) {
|
|
98
|
-
content = content.replace(/<current_work>[\s\S]*?<\/current_work>/, newCurrentWork);
|
|
99
|
-
} else {
|
|
100
|
-
// Insert after <claude_context> opening
|
|
101
|
-
if (!content.includes('<claude_context')) {
|
|
102
|
-
throw new Error('CLAUDE.md does not contain <claude_context> tag');
|
|
103
|
-
}
|
|
104
|
-
content = content.replace(/(<claude_context[^>]*>)/, `$1\n\n${newCurrentWork}`);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
// Remove both <bug_workflow> and <mode_behavior> sections
|
|
108
|
-
// Skills now provide all mode-specific guidance via activation messages
|
|
109
|
-
content = content.replace(/<bug_workflow>[\s\S]*?<\/bug_workflow>/, '');
|
|
110
|
-
content = content.replace(/<mode_behavior>[\s\S]*?<\/mode_behavior>/, '');
|
|
111
|
-
|
|
112
|
-
// Update <mode> tag
|
|
66
|
+
// Write to session file (gitignored) instead of CLAUDE.md
|
|
67
|
+
// This prevents merge conflicts and stale context on main branch
|
|
113
68
|
if (currentMode !== null) {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
try {
|
|
121
|
-
fs.writeFileSync(claudePath, content);
|
|
122
|
-
} catch (err) {
|
|
123
|
-
throw new Error(`Failed to write CLAUDE.md: ${err.message}`);
|
|
69
|
+
writeSessionFile(currentWork, currentMode, {
|
|
70
|
+
epicId: currentWork.epic_id,
|
|
71
|
+
epicTitle: currentWork.epic_title
|
|
72
|
+
});
|
|
124
73
|
}
|
|
125
74
|
}
|
|
126
75
|
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session File Writer
|
|
3
|
+
*
|
|
4
|
+
* Writes session-specific context to .claude/session.md (gitignored)
|
|
5
|
+
* instead of CLAUDE.md to prevent merge conflicts and stale context.
|
|
6
|
+
*
|
|
7
|
+
* Includes skill invocation directives for auto-invoking mode skills
|
|
8
|
+
* when resuming work on chores.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const fs = require('fs');
|
|
12
|
+
const path = require('path');
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Get absolute path to session file
|
|
16
|
+
* @returns {string} Absolute path to .claude/session.md
|
|
17
|
+
*/
|
|
18
|
+
function getSessionFilePath() {
|
|
19
|
+
return path.join(process.cwd(), '.claude', 'session.md');
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Ensure .claude directory exists
|
|
24
|
+
*/
|
|
25
|
+
function ensureClaudeDir() {
|
|
26
|
+
const claudeDir = path.join(process.cwd(), '.claude');
|
|
27
|
+
if (!fs.existsSync(claudeDir)) {
|
|
28
|
+
fs.mkdirSync(claudeDir, { recursive: true });
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Map mode to skill name
|
|
34
|
+
* @param {string} mode - Work item mode
|
|
35
|
+
* @returns {string} Skill name
|
|
36
|
+
*/
|
|
37
|
+
function modeToSkillName(mode) {
|
|
38
|
+
const mapping = {
|
|
39
|
+
'speed': 'speed-mode',
|
|
40
|
+
'stable': 'stable-mode',
|
|
41
|
+
'production': 'production-mode'
|
|
42
|
+
};
|
|
43
|
+
return mapping[mode] || `${mode}-mode`;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Write session file with current work context and skill invocation directive
|
|
48
|
+
*
|
|
49
|
+
* @param {Object} workItem - Work item object with id, title, type, status
|
|
50
|
+
* @param {string} mode - Work item mode (speed, stable, production)
|
|
51
|
+
* @param {Object} options - Additional options
|
|
52
|
+
* @param {number} options.epicId - Parent epic ID
|
|
53
|
+
* @param {string} options.epicTitle - Parent epic title
|
|
54
|
+
*/
|
|
55
|
+
function writeSessionFile(workItem, mode, options = {}) {
|
|
56
|
+
if (!workItem || typeof workItem !== 'object') {
|
|
57
|
+
throw new Error('Work item must be an object');
|
|
58
|
+
}
|
|
59
|
+
if (!workItem.id || typeof workItem.id !== 'number') {
|
|
60
|
+
throw new Error('Work item must have a numeric id');
|
|
61
|
+
}
|
|
62
|
+
if (!workItem.title || typeof workItem.title !== 'string') {
|
|
63
|
+
throw new Error('Work item must have a string title');
|
|
64
|
+
}
|
|
65
|
+
if (!workItem.type || typeof workItem.type !== 'string') {
|
|
66
|
+
throw new Error('Work item must have a string type');
|
|
67
|
+
}
|
|
68
|
+
if (!workItem.status || typeof workItem.status !== 'string') {
|
|
69
|
+
throw new Error('Work item must have a string status');
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
ensureClaudeDir();
|
|
73
|
+
|
|
74
|
+
const skillName = modeToSkillName(mode);
|
|
75
|
+
|
|
76
|
+
// Build session file content
|
|
77
|
+
let content = `# Current Work Session
|
|
78
|
+
|
|
79
|
+
## Work Context
|
|
80
|
+
|
|
81
|
+
Working on: [#${workItem.id}] ${workItem.title} (${workItem.type})
|
|
82
|
+
`;
|
|
83
|
+
|
|
84
|
+
if (options.epicId && options.epicTitle) {
|
|
85
|
+
content += `Epic: [#${options.epicId}] ${options.epicTitle}
|
|
86
|
+
`;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
content += `Mode: ${mode}
|
|
90
|
+
Status: ${workItem.status}
|
|
91
|
+
|
|
92
|
+
## IMMEDIATE ACTION REQUIRED
|
|
93
|
+
|
|
94
|
+
You are resuming work on a chore in ${mode} mode.
|
|
95
|
+
|
|
96
|
+
**Invoke the ${skillName} skill now to continue the workflow.**
|
|
97
|
+
|
|
98
|
+
This directive ensures the correct mode skill is activated automatically
|
|
99
|
+
when Claude Code starts a new session in this worktree.
|
|
100
|
+
`;
|
|
101
|
+
|
|
102
|
+
const sessionPath = getSessionFilePath();
|
|
103
|
+
|
|
104
|
+
try {
|
|
105
|
+
fs.writeFileSync(sessionPath, content);
|
|
106
|
+
} catch (err) {
|
|
107
|
+
throw new Error(`Failed to write session file: ${err.message}`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Clear the session file (delete it)
|
|
113
|
+
*/
|
|
114
|
+
function clearSessionFile() {
|
|
115
|
+
const sessionPath = getSessionFilePath();
|
|
116
|
+
|
|
117
|
+
if (fs.existsSync(sessionPath)) {
|
|
118
|
+
try {
|
|
119
|
+
fs.unlinkSync(sessionPath);
|
|
120
|
+
} catch (err) {
|
|
121
|
+
throw new Error(`Failed to clear session file: ${err.message}`);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Read the session file content
|
|
128
|
+
* @returns {string|null} Session file content or null if not found
|
|
129
|
+
*/
|
|
130
|
+
function readSessionFile() {
|
|
131
|
+
const sessionPath = getSessionFilePath();
|
|
132
|
+
|
|
133
|
+
if (!fs.existsSync(sessionPath)) {
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
try {
|
|
138
|
+
return fs.readFileSync(sessionPath, 'utf-8');
|
|
139
|
+
} catch (err) {
|
|
140
|
+
throw new Error(`Failed to read session file: ${err.message}`);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
module.exports = {
|
|
145
|
+
writeSessionFile,
|
|
146
|
+
clearSessionFile,
|
|
147
|
+
readSessionFile,
|
|
148
|
+
getSessionFilePath,
|
|
149
|
+
modeToSkillName
|
|
150
|
+
};
|
package/lib/worktree-manager.js
CHANGED
|
@@ -100,9 +100,34 @@ async function createWorktree(workItem, options = {}) {
|
|
|
100
100
|
});
|
|
101
101
|
|
|
102
102
|
// Step 2: Create git worktree
|
|
103
|
-
//
|
|
103
|
+
// Branch from the default branch (main, master, etc.) to avoid nested worktrees
|
|
104
104
|
try {
|
|
105
|
-
|
|
105
|
+
// Detect the default branch name
|
|
106
|
+
let defaultBranch;
|
|
107
|
+
try {
|
|
108
|
+
// Try to get the default branch from git config
|
|
109
|
+
defaultBranch = execSync('git symbolic-ref refs/remotes/origin/HEAD', {
|
|
110
|
+
cwd: gitRoot,
|
|
111
|
+
encoding: 'utf8',
|
|
112
|
+
stdio: ['pipe', 'pipe', 'pipe']
|
|
113
|
+
}).trim().replace('refs/remotes/origin/', '');
|
|
114
|
+
} catch {
|
|
115
|
+
// Fallback: check which common branch names exist
|
|
116
|
+
try {
|
|
117
|
+
execSync('git rev-parse --verify main', { cwd: gitRoot, stdio: 'pipe' });
|
|
118
|
+
defaultBranch = 'main';
|
|
119
|
+
} catch {
|
|
120
|
+
try {
|
|
121
|
+
execSync('git rev-parse --verify master', { cwd: gitRoot, stdio: 'pipe' });
|
|
122
|
+
defaultBranch = 'master';
|
|
123
|
+
} catch {
|
|
124
|
+
// Last resort: use HEAD
|
|
125
|
+
defaultBranch = 'HEAD';
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
execSync(`git worktree add -b "${branchName}" "${worktreePath}" ${defaultBranch}`, {
|
|
106
131
|
cwd: gitRoot,
|
|
107
132
|
stdio: 'pipe'
|
|
108
133
|
});
|
package/package.json
CHANGED
|
@@ -113,7 +113,7 @@ After user tests (or skips prototyping):
|
|
|
113
113
|
Which approach works best?
|
|
114
114
|
```
|
|
115
115
|
|
|
116
|
-
User picks winner.
|
|
116
|
+
User picks winner. Note their choice - you'll record it formally in Step 8 when transitioning to implementation.
|
|
117
117
|
|
|
118
118
|
### Step 6: Generate BDD Scenarios AND Step Definitions
|
|
119
119
|
|
|
@@ -239,74 +239,20 @@ console.log(''); // Extra line before continuing
|
|
|
239
239
|
1. Confirm success with checkmarks
|
|
240
240
|
2. Proceed immediately to Step 6.75
|
|
241
241
|
|
|
242
|
-
### Step 6.75:
|
|
242
|
+
### Step 6.75: Note About Unit Tests
|
|
243
243
|
|
|
244
|
-
**
|
|
244
|
+
**Unit tests will be created during speed mode implementation**, not during feature planning.
|
|
245
245
|
|
|
246
|
-
|
|
246
|
+
The speed-mode skill guides Claude to:
|
|
247
|
+
1. Implement the feature code
|
|
248
|
+
2. Create corresponding unit tests for the happy path
|
|
249
|
+
3. Ensure tests pass before completing the chore
|
|
247
250
|
|
|
248
|
-
|
|
249
|
-
const { scaffoldUnitTestFile } = require('../../lib/unit-test-generator');
|
|
250
|
-
const path = require('path');
|
|
251
|
-
|
|
252
|
-
console.log('📝 Scaffolding unit test files...\n');
|
|
253
|
-
|
|
254
|
-
// Infer implementation files from chore breadcrumbs
|
|
255
|
-
// Parse "Files to create/modify" from each proposed chore
|
|
256
|
-
const implementationFiles = [];
|
|
257
|
-
|
|
258
|
-
// For each chore you're about to propose, extract file paths
|
|
259
|
-
// Example: if chore says "Files to create/modify: src/login.js, src/auth.js"
|
|
260
|
-
// Then implementationFiles = ['src/login.js', 'src/auth.js']
|
|
261
|
-
|
|
262
|
-
for (const chore of proposedChores) {
|
|
263
|
-
const filesMatch = chore.description.match(/Files to create\/modify:\s*([^\n]+)/);
|
|
264
|
-
if (filesMatch) {
|
|
265
|
-
const files = filesMatch[1].split(',').map(f => f.trim());
|
|
266
|
-
implementationFiles.push(...files);
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
// Remove duplicates
|
|
271
|
-
const uniqueFiles = [...new Set(implementationFiles)];
|
|
272
|
-
|
|
273
|
-
// Scaffold test files
|
|
274
|
-
const scaffoldedTests = [];
|
|
275
|
-
for (const filePath of uniqueFiles) {
|
|
276
|
-
if (filePath.endsWith('.js') && !filePath.includes('test')) {
|
|
277
|
-
try {
|
|
278
|
-
const testFile = scaffoldUnitTestFile(filePath);
|
|
279
|
-
scaffoldedTests.push(testFile);
|
|
280
|
-
console.log(` ✅ ${testFile}`);
|
|
281
|
-
} catch (err) {
|
|
282
|
-
console.log(` ⚠️ Could not scaffold ${filePath}: ${err.message}`);
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
if (scaffoldedTests.length > 0) {
|
|
288
|
-
console.log(`\n📦 Scaffolded ${scaffoldedTests.length} unit test files`);
|
|
289
|
-
console.log('These files have empty TODO placeholders - speed mode will fill them.\n');
|
|
290
|
-
} else {
|
|
291
|
-
console.log('No new test files to scaffold\n');
|
|
292
|
-
}
|
|
293
|
-
```
|
|
294
|
-
|
|
295
|
-
**Why scaffold now:**
|
|
296
|
-
- Creates test file structure before implementation
|
|
297
|
-
- Reminds developers tests are required
|
|
298
|
-
- Speed mode can update these TODO placeholders after GREEN
|
|
299
|
-
- Prevents "I'll add tests later" (they never do)
|
|
300
|
-
|
|
301
|
-
**What gets scaffolded:**
|
|
302
|
-
- Empty `test/[path]/[file].test.js` files
|
|
303
|
-
- Basic `describe()` blocks
|
|
304
|
-
- TODO placeholders for actual tests
|
|
305
|
-
- Won't overwrite existing test files
|
|
251
|
+
This keeps feature planning focused on BDD scenarios (what users experience) while speed mode handles unit tests (implementation details).
|
|
306
252
|
|
|
307
253
|
### Step 7: Propose Speed Mode Chores
|
|
308
254
|
|
|
309
|
-
**CRITICAL:** After BDD validation passes, analyze the codebase and propose technical implementation chores
|
|
255
|
+
**CRITICAL:** After BDD validation passes, analyze the codebase and propose technical implementation chores. **DO NOT CREATE CHORES YET** - the feature must transition to implementation mode first (Step 8).
|
|
310
256
|
|
|
311
257
|
**Your analysis should consider:**
|
|
312
258
|
- The BDD scenarios (especially the happy path)
|
|
@@ -315,7 +261,6 @@ if (scaffoldedTests.length > 0) {
|
|
|
315
261
|
- Tech stack and framework conventions
|
|
316
262
|
- Which scenario steps each chore addresses
|
|
317
263
|
- Similar code patterns to follow
|
|
318
|
-
- Specific step definitions that should pass
|
|
319
264
|
|
|
320
265
|
**Say to the user:**
|
|
321
266
|
|
|
@@ -324,7 +269,7 @@ Now let me analyze the codebase and propose implementation chores for speed mode
|
|
|
324
269
|
|
|
325
270
|
[Analyze codebase, read relevant files, check patterns]
|
|
326
271
|
|
|
327
|
-
Based on the scenario and codebase, here are the chores I recommend for speed mode:
|
|
272
|
+
Based on the scenario and my understanding of the codebase, here are the chores I recommend for speed mode:
|
|
328
273
|
|
|
329
274
|
**Chore 1: [Technical task title]**
|
|
330
275
|
- Why: [What this accomplishes toward the scenario]
|
|
@@ -335,7 +280,7 @@ Based on the scenario and codebase, here are the chores I recommend for speed mo
|
|
|
335
280
|
• Patterns to follow: [reference existing similar code]
|
|
336
281
|
• Key functions/components needed: [list]
|
|
337
282
|
- Verification:
|
|
338
|
-
•
|
|
283
|
+
• [Which step definitions should pass]
|
|
339
284
|
|
|
340
285
|
**Chore 2: [Technical task title]**
|
|
341
286
|
- Why: [What this accomplishes]
|
|
@@ -346,7 +291,7 @@ Based on the scenario and codebase, here are the chores I recommend for speed mo
|
|
|
346
291
|
• Patterns to follow: [references]
|
|
347
292
|
• Key functions/components needed: [list]
|
|
348
293
|
- Verification:
|
|
349
|
-
•
|
|
294
|
+
• [Which steps should pass]
|
|
350
295
|
|
|
351
296
|
[etc.]
|
|
352
297
|
|
|
@@ -355,107 +300,7 @@ These chores will make the happy path scenario pass.
|
|
|
355
300
|
Sound good? Any adjustments?
|
|
356
301
|
```
|
|
357
302
|
|
|
358
|
-
**Wait for user confirmation/adjustments.**
|
|
359
|
-
|
|
360
|
-
**Then create the chores with rich descriptions:**
|
|
361
|
-
|
|
362
|
-
```javascript
|
|
363
|
-
// Import breadcrumb generators
|
|
364
|
-
const { parseStepDefinitions } = require('../../lib/step-definition-parser');
|
|
365
|
-
const { findSimilarPatterns } = require('../../lib/pattern-finder');
|
|
366
|
-
const { generateVerificationCommands } = require('../../lib/verification-command-generator');
|
|
367
|
-
const { create } = require('./features/work-tracking');
|
|
368
|
-
const path = require('path');
|
|
369
|
-
|
|
370
|
-
// Parse step definitions for verification breadcrumbs
|
|
371
|
-
const stepDefsPath = path.join(process.cwd(), 'features/step_definitions', `${featureSlug}.steps.js`);
|
|
372
|
-
const stepMap = parseStepDefinitions(stepDefsPath);
|
|
373
|
-
|
|
374
|
-
// For each confirmed chore:
|
|
375
|
-
for (const chore of confirmedChores) {
|
|
376
|
-
// Find similar patterns for implementation guidance
|
|
377
|
-
const patterns = findSimilarPatterns(chore.keywords || []);
|
|
378
|
-
|
|
379
|
-
// Build pattern references
|
|
380
|
-
const patternRefs = patterns.length > 0
|
|
381
|
-
? patterns.map(p => `${p.file} (${p.description})`).join('\n • ')
|
|
382
|
-
: 'No similar patterns found - create new implementation';
|
|
383
|
-
|
|
384
|
-
// Build step definition references with file:line
|
|
385
|
-
const stepRefs = chore.steps
|
|
386
|
-
.map(stepText => {
|
|
387
|
-
const stepInfo = stepMap.get(stepText);
|
|
388
|
-
if (stepInfo) {
|
|
389
|
-
return `${path.basename(stepInfo.file)}:${stepInfo.lineNumber} - "${stepText}"`;
|
|
390
|
-
}
|
|
391
|
-
return `"${stepText}" (not yet implemented)`;
|
|
392
|
-
})
|
|
393
|
-
.join('\n • ');
|
|
394
|
-
|
|
395
|
-
// Generate verification command for the chore's scenario
|
|
396
|
-
const verification = generateVerificationCommands(
|
|
397
|
-
`features/${featureSlug}.feature`,
|
|
398
|
-
chore.scenarioLine
|
|
399
|
-
);
|
|
400
|
-
|
|
401
|
-
const description = `${chore.technicalDescription}
|
|
402
|
-
|
|
403
|
-
Scenario steps addressed:
|
|
404
|
-
${chore.scenarioSteps.map(s => `• ${s}`).join('\n')}
|
|
405
|
-
|
|
406
|
-
Implementation guidance:
|
|
407
|
-
• Files to create/modify: ${chore.files.join(', ')}
|
|
408
|
-
• Patterns to follow:
|
|
409
|
-
• ${patternRefs}
|
|
410
|
-
• Key functions/components needed: ${chore.components.join(', ')}
|
|
411
|
-
|
|
412
|
-
Verification:
|
|
413
|
-
• Step definitions that should pass:
|
|
414
|
-
• ${stepRefs}
|
|
415
|
-
• Test command: ${verification.command}
|
|
416
|
-
• Scenario: ${verification.scenarioName}`;
|
|
417
|
-
|
|
418
|
-
await create('chore', chore.title, description, featureId, 'speed', false);
|
|
419
|
-
}
|
|
420
|
-
```
|
|
421
|
-
|
|
422
|
-
**Example chore description (with breadcrumb generators):**
|
|
423
|
-
|
|
424
|
-
```
|
|
425
|
-
Build login form component with email/password fields
|
|
426
|
-
|
|
427
|
-
Scenario steps addressed:
|
|
428
|
-
• Given I am on the login page
|
|
429
|
-
• When I enter valid credentials and submit
|
|
430
|
-
|
|
431
|
-
Implementation guidance:
|
|
432
|
-
• Files to create/modify: src/components/LoginForm.jsx
|
|
433
|
-
• Patterns to follow:
|
|
434
|
-
• src/components/SignupForm.jsx (Functions: handleSubmit, validateEmail)
|
|
435
|
-
• lib/validation.js (Functions: validateEmailFormat, validatePassword)
|
|
436
|
-
• Key functions/components needed: EmailInput, PasswordInput, SubmitButton
|
|
437
|
-
|
|
438
|
-
Verification:
|
|
439
|
-
• Step definitions that should pass:
|
|
440
|
-
• login.steps.js:15 - "I am on the login page"
|
|
441
|
-
• login.steps.js:23 - "I enter valid credentials and submit"
|
|
442
|
-
• Test command: npm run test:bdd -- features/login.feature:8
|
|
443
|
-
• Scenario: User successfully logs in with valid credentials
|
|
444
|
-
```
|
|
445
|
-
|
|
446
|
-
**Report:**
|
|
447
|
-
```
|
|
448
|
-
✅ Created X chores for speed mode
|
|
449
|
-
|
|
450
|
-
Each chore includes automated breadcrumbs from:
|
|
451
|
-
• Step definition parser - Exact file:line references for verification
|
|
452
|
-
• Pattern finder - Similar code patterns to follow
|
|
453
|
-
• Verification command generator - Ready-to-run test commands
|
|
454
|
-
• Scenario steps addressed
|
|
455
|
-
• Implementation guidance with file paths
|
|
456
|
-
|
|
457
|
-
Ready to start implementation: jettypod work start [first-chore-id]
|
|
458
|
-
```
|
|
303
|
+
**Wait for user confirmation/adjustments, then proceed to Step 8.**
|
|
459
304
|
|
|
460
305
|
### Step 8: Transition to Implementation
|
|
461
306
|
|
|
@@ -482,8 +327,8 @@ Does this rationale capture why you chose this approach? (You can edit it if nee
|
|
|
482
327
|
|
|
483
328
|
**CRITICAL: After user confirms, use Bash tool to EXECUTE the work implement command:**
|
|
484
329
|
|
|
485
|
-
```
|
|
486
|
-
|
|
330
|
+
```bash
|
|
331
|
+
# Use Bash tool to execute:
|
|
487
332
|
node jettypod.js work implement [feature-id] \
|
|
488
333
|
--winner="[approach-name or prototypes/winner-file]" \
|
|
489
334
|
--rationale="[user's confirmed/edited rationale]"
|
|
@@ -491,10 +336,39 @@ node jettypod.js work implement [feature-id] \
|
|
|
491
336
|
|
|
492
337
|
**DO NOT display this as example text. EXECUTE IT using the Bash tool.**
|
|
493
338
|
|
|
494
|
-
|
|
339
|
+
#### Step 8C: Create the Chores
|
|
340
|
+
|
|
341
|
+
**CRITICAL: NOW create the chores.** The feature has transitioned to implementation mode, so chore creation will succeed.
|
|
342
|
+
|
|
343
|
+
For each chore that the user confirmed in Step 7, use the Bash tool to create it:
|
|
344
|
+
|
|
345
|
+
```bash
|
|
346
|
+
# Use Bash tool to execute for each chore:
|
|
347
|
+
node jettypod.js work create chore "[Chore title]" "[Chore description with all the implementation guidance]" --parent=[feature-id]
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
**Build the description from your Step 7 proposal:**
|
|
351
|
+
```
|
|
352
|
+
[Technical description]
|
|
353
|
+
|
|
354
|
+
Scenario steps addressed:
|
|
355
|
+
• [Step 1]
|
|
356
|
+
• [Step 2]
|
|
357
|
+
|
|
358
|
+
Implementation guidance:
|
|
359
|
+
• Files to create/modify: [paths]
|
|
360
|
+
• Patterns to follow: [references]
|
|
361
|
+
• Key functions/components needed: [list]
|
|
362
|
+
|
|
363
|
+
Verification:
|
|
364
|
+
• [Which step definitions should pass]
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
After creating all chores, display:
|
|
495
368
|
|
|
496
369
|
```
|
|
497
370
|
✅ Feature transitioned to implementation phase
|
|
371
|
+
✅ Created X chores for speed mode
|
|
498
372
|
|
|
499
373
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
500
374
|
🎯 Feature Discovery Complete!
|
|
@@ -508,7 +382,7 @@ After execution succeeds, verify the feature transitioned to implementation phas
|
|
|
508
382
|
Ready to start implementation?
|
|
509
383
|
```
|
|
510
384
|
|
|
511
|
-
#### Step
|
|
385
|
+
#### Step 8D: Transition to Speed Mode
|
|
512
386
|
|
|
513
387
|
**WAIT for user confirmation.**
|
|
514
388
|
|
|
@@ -516,8 +390,8 @@ When user confirms they want to proceed with implementation (responds with "yes"
|
|
|
516
390
|
|
|
517
391
|
**IMMEDIATELY invoke the speed-mode skill using the Skill tool:**
|
|
518
392
|
|
|
519
|
-
```
|
|
520
|
-
Skill
|
|
393
|
+
```
|
|
394
|
+
Use the Skill tool with skill: "speed-mode"
|
|
521
395
|
```
|
|
522
396
|
|
|
523
397
|
**The speed-mode skill will then:**
|
|
@@ -610,7 +484,7 @@ Scenario: Prevent unauthorized access
|
|
|
610
484
|
|
|
611
485
|
**User picks:** Option 1 (Simple inline form)
|
|
612
486
|
|
|
613
|
-
**Scenarios generated:**
|
|
487
|
+
**Scenarios generated (happy path only for speed mode):**
|
|
614
488
|
```gherkin
|
|
615
489
|
Feature: Email/Password Login
|
|
616
490
|
|
|
@@ -620,11 +494,8 @@ Scenario: Successful login
|
|
|
620
494
|
Then I am redirected to the dashboard
|
|
621
495
|
And I have an active JWT token
|
|
622
496
|
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
When I enter invalid credentials
|
|
626
|
-
Then I see an error message
|
|
627
|
-
And I remain on the login page
|
|
497
|
+
# SPEED MODE: Only happy path above
|
|
498
|
+
# STABLE MODE: Will add error handling scenarios like "Invalid credentials"
|
|
628
499
|
```
|
|
629
500
|
|
|
630
501
|
**Rationale confirmation:**
|
|
@@ -33,7 +33,7 @@ When this skill is activated, you are helping implement a speed mode chore to ma
|
|
|
33
33
|
- **Assume happy path** - assume inputs are valid, files upload successfully, types are correct
|
|
34
34
|
- **No error handling** - no validation, no edge case handling, no error messages (that's for stable mode)
|
|
35
35
|
- **Fast iteration** - single file when possible, inline code over abstraction
|
|
36
|
-
- **
|
|
36
|
+
- **Use real infrastructure** - use the actual database/storage from your tech stack, not mocks
|
|
37
37
|
- **Autonomous execution** - Claude Code writes code, user confirms approach
|
|
38
38
|
|
|
39
39
|
**User Profile:** May not know how to code - Claude Code does the implementation autonomously.
|
|
@@ -52,7 +52,7 @@ When this skill is activated, you are helping implement a speed mode chore to ma
|
|
|
52
52
|
**Where Claude Code executes autonomously:**
|
|
53
53
|
- Step 1: Scenario analysis
|
|
54
54
|
- Step 2: Codebase analysis
|
|
55
|
-
- Step 3 Phase 2: RED→GREEN
|
|
55
|
+
- Step 3 Phase 2: RED→GREEN→REFACTOR loop
|
|
56
56
|
- Step 4 Phases 3-4: Create chores and elevate
|
|
57
57
|
|
|
58
58
|
---
|
|
@@ -569,13 +569,33 @@ Modified src/dashboard.js
|
|
|
569
569
|
- **Single file when possible** - keep it simple
|
|
570
570
|
- **NO error handling** - no try/catch, no validation, no edge cases
|
|
571
571
|
- **Assume everything works** - valid inputs, successful operations, correct types
|
|
572
|
-
- **
|
|
572
|
+
- **Use real infrastructure** - actual database/storage from your tech stack
|
|
573
573
|
- **Inline code over separate modules** - keep it simple
|
|
574
574
|
- **Focus: Make. All. Features. Work.** (on the happy path)
|
|
575
575
|
|
|
576
|
-
**Step 3:
|
|
576
|
+
**Step 3: REFACTOR**
|
|
577
577
|
|
|
578
|
-
After GREEN is achieved,
|
|
578
|
+
After GREEN is achieved, do a quick refactor pass:
|
|
579
|
+
|
|
580
|
+
1. **Extract duplicated code** - DRY up any copy-pasted logic
|
|
581
|
+
2. **Rename unclear variables** - make intent obvious
|
|
582
|
+
3. **Simplify complex expressions** - break into readable steps
|
|
583
|
+
4. **Remove dead code** - delete unused variables/functions
|
|
584
|
+
|
|
585
|
+
**Keep it fast** - 5 minutes max. Major refactoring happens in stable mode.
|
|
586
|
+
|
|
587
|
+
**Re-run tests after refactoring** to ensure nothing broke:
|
|
588
|
+
|
|
589
|
+
```javascript
|
|
590
|
+
const result = await runBddScenarioWithTimeout(feature.scenario_file, scenarioLine);
|
|
591
|
+
if (result.exitCode !== 0) {
|
|
592
|
+
console.log('⚠️ Refactoring broke tests - revert and try again');
|
|
593
|
+
}
|
|
594
|
+
```
|
|
595
|
+
|
|
596
|
+
**Step 4: Final Verification and Completion**
|
|
597
|
+
|
|
598
|
+
After GREEN + REFACTOR, run full feature file once to verify no regressions:
|
|
579
599
|
|
|
580
600
|
```javascript
|
|
581
601
|
// After iteration loop succeeds (GREEN achieved)
|
|
@@ -630,8 +650,32 @@ if (filesModified.length > 0) {
|
|
|
630
650
|
console.log();
|
|
631
651
|
}
|
|
632
652
|
|
|
633
|
-
//
|
|
634
|
-
//
|
|
653
|
+
// --- Create unit tests for new functions ---
|
|
654
|
+
// For each new function implemented, create a unit test file with happy path coverage
|
|
655
|
+
|
|
656
|
+
// Unit test template for new functions:
|
|
657
|
+
// test/[filename].test.js or __tests__/[filename].test.js
|
|
658
|
+
/*
|
|
659
|
+
const { functionName } = require('../src/path/to/module');
|
|
660
|
+
|
|
661
|
+
describe('functionName', () => {
|
|
662
|
+
it('should handle valid input successfully', () => {
|
|
663
|
+
// Arrange
|
|
664
|
+
const input = validTestData;
|
|
665
|
+
|
|
666
|
+
// Act
|
|
667
|
+
const result = functionName(input);
|
|
668
|
+
|
|
669
|
+
// Assert
|
|
670
|
+
expect(result).toEqual(expectedOutput);
|
|
671
|
+
});
|
|
672
|
+
});
|
|
673
|
+
*/
|
|
674
|
+
|
|
675
|
+
// Speed mode unit tests focus on:
|
|
676
|
+
// - Happy path with valid input
|
|
677
|
+
// - One successful operation per function
|
|
678
|
+
// - Basic return value verification
|
|
635
679
|
|
|
636
680
|
console.log(`Next step: Elevate to stable mode using 'jettypod work set-mode <feature-id> stable'\n`);
|
|
637
681
|
```
|
|
@@ -639,7 +683,7 @@ console.log(`Next step: Elevate to stable mode using 'jettypod work set-mode <fe
|
|
|
639
683
|
**Display:**
|
|
640
684
|
```
|
|
641
685
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
642
|
-
✅
|
|
686
|
+
✅ GREEN STATE ACHIEVED - Now Creating Stable Chores
|
|
643
687
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
644
688
|
|
|
645
689
|
🎉 Happy path scenario: ALL TESTS PASSING
|
|
@@ -656,7 +700,8 @@ Files modified:
|
|
|
656
700
|
✏️ src/app.js
|
|
657
701
|
✏️ src/index.html
|
|
658
702
|
|
|
659
|
-
|
|
703
|
+
⚠️ Speed mode is NOT complete until stable chores exist.
|
|
704
|
+
Proceeding to Step 4 to create stable mode chores...
|
|
660
705
|
```
|
|
661
706
|
|
|
662
707
|
**On FAILURE (max iterations or timeout):**
|
|
@@ -737,14 +782,18 @@ What to do:
|
|
|
737
782
|
DO NOT proceed to generate stable mode chores until GREEN is achieved.
|
|
738
783
|
```
|
|
739
784
|
|
|
740
|
-
**Move to Step 4
|
|
785
|
+
**Move to Step 4 IMMEDIATELY if GREEN achieved.**
|
|
786
|
+
|
|
787
|
+
**CRITICAL: GREEN is NOT completion - it's just a checkpoint. Speed mode is INCOMPLETE until stable mode chores are created. You MUST continue to Step 4.**
|
|
741
788
|
|
|
742
789
|
<!-- ═══════════════════════════════════════════════════════════════════════════
|
|
743
790
|
PHASE 4: STABLE CHORE GENERATION
|
|
744
791
|
⚡ ASYNC BOUNDARY - Must wait for user to confirm proposed chores
|
|
745
792
|
═══════════════════════════════════════════════════════════════════════════ -->
|
|
746
793
|
|
|
747
|
-
### Step 4: Generate Stable Mode Chores
|
|
794
|
+
### Step 4: Generate Stable Mode Chores (REQUIRED - Do Not Skip)
|
|
795
|
+
|
|
796
|
+
**CRITICAL:** This step is MANDATORY. Speed mode is NOT complete until stable mode chores exist. Without them, users cannot resume work on this feature.
|
|
748
797
|
|
|
749
798
|
**Two phases: Analyze and propose → Get confirmation → Create autonomously**
|
|
750
799
|
|
|
@@ -940,15 +989,18 @@ Stable mode adds:
|
|
|
940
989
|
|
|
941
990
|
```
|
|
942
991
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
943
|
-
🎯 Speed Mode Chore
|
|
992
|
+
🎯 Speed Mode Chore Done - Stable Chores Created
|
|
944
993
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
945
994
|
|
|
946
995
|
What we accomplished:
|
|
947
996
|
✅ Happy path scenario passes for this chore
|
|
948
|
-
✅ Stable mode chores created
|
|
997
|
+
✅ Stable mode chores created for when speed mode finishes
|
|
949
998
|
|
|
950
999
|
Remaining speed mode chores: [count]
|
|
951
1000
|
|
|
1001
|
+
⚠️ Speed mode is NOT complete yet - [count] chores remain.
|
|
1002
|
+
You can take a break here - stable mode chores exist and work can resume.
|
|
1003
|
+
|
|
952
1004
|
**Next step:** Continue with next speed mode chore
|
|
953
1005
|
jettypod work start [next-speed-chore-id]
|
|
954
1006
|
```
|