jettypod 4.1.4 → 4.1.5

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.
@@ -5,6 +5,19 @@ description: Guide implementation of speed mode chores with autonomous code anal
5
5
 
6
6
  # Speed Mode Skill
7
7
 
8
+ ```
9
+ ┌─────────────────────────────────────────────────────────────────────┐
10
+ │ Mode Progression Flow │
11
+ │ │
12
+ │ Feature Planning → [SPEED MODE] → Stable Mode → Production Mode │
13
+ │ ▲▲▲▲▲▲▲▲▲▲▲ │
14
+ │ YOU ARE HERE │
15
+ │ │
16
+ │ Next: After implementation, this skill generates stable mode │
17
+ │ chores and elevates the feature to stable mode. │
18
+ └─────────────────────────────────────────────────────────────────────┘
19
+ ```
20
+
8
21
  Guides Claude Code through speed mode implementation with autonomous analysis and execution. Users confirm approach but Claude Code writes the code.
9
22
 
10
23
  ## Instructions
@@ -27,6 +40,23 @@ When this skill is activated, you are helping implement a speed mode chore to ma
27
40
 
28
41
  ---
29
42
 
43
+ ## Quick Reference: Async Boundaries
44
+
45
+ **Where Claude Code MUST wait for user confirmation:**
46
+
47
+ | Phase | Location | Why |
48
+ |-------|----------|-----|
49
+ | Step 3 Phase 1 | Before implementing | User confirms implementation approach |
50
+ | Step 4 Phase 2 | Before creating chores | User confirms proposed stable mode chores |
51
+
52
+ **Where Claude Code executes autonomously:**
53
+ - Step 1: Scenario analysis
54
+ - Step 2: Codebase analysis
55
+ - Step 3 Phase 2: RED→GREEN iteration loop
56
+ - Step 4 Phases 3-4: Create chores and elevate
57
+
58
+ ---
59
+
30
60
  ## ⚠️ CRITICAL: Speed Mode Workflow Requirements
31
61
 
32
62
  **DO NOT mark features as complete after speed mode implementation.**
@@ -57,6 +87,11 @@ The validation will require you to:
57
87
 
58
88
  ## Implementation Steps
59
89
 
90
+ <!-- ═══════════════════════════════════════════════════════════════════════════
91
+ PHASE 1: AUTONOMOUS ANALYSIS
92
+ No user input required - Claude Code executes independently
93
+ ═══════════════════════════════════════════════════════════════════════════ -->
94
+
60
95
  ### Step 1: Check for Breadcrumbs and Analyze Scenario
61
96
 
62
97
  **CRITICAL:** Claude Code executes this autonomously - no user permission needed.
@@ -71,32 +106,42 @@ The validation will require you to:
71
106
  **Code to check for breadcrumbs:**
72
107
 
73
108
  ```javascript
109
+ // --- Setup and imports ---
74
110
  const { getCurrentWork } = require('../../lib/current-work');
75
111
  const { getDb } = require('../../lib/database');
76
112
  const fs = require('fs');
77
113
  const path = require('path');
78
114
 
79
- const currentWork = getCurrentWork();
80
-
81
- // Check if description has breadcrumbs from feature-planning
82
- const hasBreadcrumbs = currentWork.description &&
83
- currentWork.description.includes('Scenario steps addressed:') &&
84
- currentWork.description.includes('Implementation guidance:') &&
85
- currentWork.description.includes('Verification:');
115
+ (async () => {
116
+ const currentWork = await getCurrentWork();
117
+
118
+ // --- Check for breadcrumbs ---
119
+ const hasBreadcrumbs = currentWork.description &&
120
+ currentWork.description.includes('Scenario steps addressed:') &&
121
+ currentWork.description.includes('Implementation guidance:') &&
122
+ currentWork.description.includes('Verification:');
123
+
124
+ // --- Get parent feature from database ---
125
+ const db = getDb();
126
+ const feature = await new Promise((resolve, reject) => {
127
+ db.get('SELECT * FROM work_items WHERE id = ?', [currentWork.parent_id], (err, row) => {
128
+ if (err) reject(err);
129
+ else resolve(row);
130
+ });
131
+ });
86
132
 
87
- // Get parent feature
88
- const db = getDb();
89
- db.get('SELECT * FROM work_items WHERE id = ?', [currentWork.parent_id], (err, feature) => {
133
+ // --- Validate scenario file exists ---
90
134
  if (!feature.scenario_file) {
91
135
  console.error('No scenario file found for this feature');
92
136
  return;
93
137
  }
94
138
 
139
+ // --- Read scenario content ---
95
140
  const scenarioPath = path.join(process.cwd(), feature.scenario_file);
96
141
  const scenarioContent = fs.readFileSync(scenarioPath, 'utf8');
97
142
 
98
143
  // Parse and analyze...
99
- });
144
+ })();
100
145
  ```
101
146
 
102
147
  **Parse Gherkin:**
@@ -227,6 +272,11 @@ Now proposing implementation approach...
227
272
 
228
273
  **Move to Step 3 automatically.**
229
274
 
275
+ <!-- ═══════════════════════════════════════════════════════════════════════════
276
+ PHASE 2: USER CONFIRMATION REQUIRED
277
+ ⚡ ASYNC BOUNDARY - Must wait for user response before proceeding
278
+ ═══════════════════════════════════════════════════════════════════════════ -->
279
+
230
280
  ### Step 3: Propose and Execute Implementation
231
281
 
232
282
  **Two phases: Propose (get user confirmation) → Execute (autonomous)**
@@ -259,6 +309,11 @@ Sound good? I'll implement this autonomously once you confirm.
259
309
 
260
310
  If user adjusts: revise proposal and confirm again.
261
311
 
312
+ <!-- ═══════════════════════════════════════════════════════════════════════════
313
+ PHASE 3: AUTONOMOUS EXECUTION
314
+ User has confirmed - Claude Code executes RED→GREEN loop independently
315
+ ═══════════════════════════════════════════════════════════════════════════ -->
316
+
262
317
  #### Phase 2: Autonomous Execution
263
318
 
264
319
  **CRITICAL:** After user confirms, Claude Code executes autonomously - no permission needed for individual code changes.
@@ -268,15 +323,23 @@ If user adjusts: revise proposal and confirm again.
268
323
  Before writing any implementation code, run tests to establish the RED state:
269
324
 
270
325
  ```javascript
271
- const { runBddTestWithTimeout, runBddScenarioWithTimeout, getFirstScenarioLine, parseTestProgress, extractErrors } = require('./.claude/skills/speed-mode/test-runner');
326
+ // --- Imports ---
327
+ const { runBddScenarioWithTimeout, getFirstScenarioLine, parseTestProgress, extractErrors } = require('./.claude/skills/speed-mode/test-runner');
272
328
  const { getCurrentWork } = require('./lib/current-work');
273
329
  const { getDb } = require('./lib/database');
274
330
 
275
- const currentWork = getCurrentWork();
276
- const db = getDb();
331
+ (async () => {
332
+ // --- Get current work and parent feature ---
333
+ const currentWork = await getCurrentWork();
334
+ const db = getDb();
335
+
336
+ const feature = await new Promise((resolve, reject) => {
337
+ db.get('SELECT * FROM work_items WHERE id = ?', [currentWork.parent_id], (err, row) => {
338
+ if (err) reject(err);
339
+ else resolve(row);
340
+ });
341
+ });
277
342
 
278
- // Get parent feature and its scenario file
279
- db.get('SELECT * FROM work_items WHERE id = ?', [currentWork.parent_id], async (err, feature) => {
280
343
  if (!feature.scenario_file) {
281
344
  console.error('No scenario file found for this feature');
282
345
  return;
@@ -284,28 +347,31 @@ db.get('SELECT * FROM work_items WHERE id = ?', [currentWork.parent_id], async (
284
347
 
285
348
  console.log('🔴 Establishing RED baseline...\n');
286
349
 
287
- // Find happy path scenario (first scenario in file)
350
+ // --- Find happy path scenario ---
288
351
  const happyPathLine = getFirstScenarioLine(feature.scenario_file);
289
352
  if (!happyPathLine) {
290
353
  console.error('No scenario found in feature file');
291
354
  return;
292
355
  }
293
356
 
294
- // Run only happy path scenario before any code is written
357
+ // --- Run tests before implementation ---
295
358
  const result = await runBddScenarioWithTimeout(feature.scenario_file, happyPathLine);
359
+ let progress = { passed: 0, total: 0, failedSteps: [] };
296
360
 
361
+ // --- Handle timeout ---
297
362
  if (result.timedOut) {
298
363
  console.log('⚠️ Test execution timed out - tests may be hanging');
299
364
  console.log('Proceeding with implementation...\n');
300
365
  } else {
301
- // Parse the test output
302
- const progress = parseTestProgress(result.stdout + result.stderr);
366
+ // --- Parse and display results ---
367
+ progress = parseTestProgress(result.stdout + result.stderr);
303
368
  const errors = extractErrors(result.stdout + result.stderr);
304
369
 
305
370
  console.log(`RED Baseline: ${progress.total - progress.passed} of ${progress.total} steps failing`);
306
371
  console.log('\nFailing steps:');
307
372
  progress.failedSteps.forEach(step => console.log(` ✖ ${step}`));
308
373
 
374
+ // --- Show first error ---
309
375
  if (errors.errors.length > 0) {
310
376
  console.log('\nFirst error:');
311
377
  const firstError = errors.errors[0];
@@ -316,13 +382,13 @@ db.get('SELECT * FROM work_items WHERE id = ?', [currentWork.parent_id], async (
316
382
  console.log('\n🎯 Goal: Make all steps pass\n');
317
383
  }
318
384
 
319
- // Store baseline for comparison in iteration loop (chore #115)
385
+ // --- Store baseline for iteration loop ---
320
386
  global.redBaseline = {
321
387
  passed: progress.passed,
322
388
  total: progress.total,
323
389
  failedSteps: progress.failedSteps
324
390
  };
325
- });
391
+ })();
326
392
  ```
327
393
 
328
394
  **Display RED baseline:**
@@ -351,39 +417,54 @@ Now implementing...
351
417
 
352
418
  Iterate until all tests pass or MAX_ITERATIONS reached:
353
419
 
420
+ <!-- ┌─────────────────────────────────────────────────────────────────────────┐
421
+ │ 🔄 ITERATION LOOP: RED→GREEN │
422
+ │ │
423
+ │ Progress Tracking: │
424
+ │ • Display: "Iteration X/10" at start of each cycle │
425
+ │ • Track: steps passing vs total, newly passing steps │
426
+ │ • Goal: All steps pass (exit code 0) │
427
+ │ │
428
+ │ Return Points: │
429
+ │ • CHECKPOINT_ITERATION: Resume at specific iteration number │
430
+ │ • CHECKPOINT_PROGRESS: Resume with known passing step count │
431
+ │ • If session interrupted, can resume from last known iteration │
432
+ └─────────────────────────────────────────────────────────────────────────┘ -->
433
+
354
434
  ```javascript
435
+ // --- Imports and setup ---
355
436
  const { runBddScenarioWithTimeout, parseTestProgress, findNewlyPassingSteps, extractErrors, MAX_ITERATIONS } = require('./.claude/skills/speed-mode/test-runner');
356
437
 
357
438
  let previousResult = global.redBaseline; // From Step 1
358
439
  let iteration = 0;
359
440
 
441
+ // --- Main iteration loop ---
442
+ // 📊 PROGRESS: Iteration {iteration}/{MAX_ITERATIONS} | Steps: {passed}/{total}
360
443
  while (iteration < MAX_ITERATIONS) {
361
444
  iteration++;
362
-
363
445
  console.log(`\n━━━ Iteration ${iteration}/${MAX_ITERATIONS} ━━━`);
364
446
 
365
- // 1. Make code changes based on current failure
447
+ // --- Make code changes ---
366
448
  console.log(`\n✍️ Making code changes...`);
367
449
  // [Claude Code writes implementation code here using Write/Edit tools]
368
450
 
369
- // 2. Run tests - only happy path scenario during iteration
451
+ // --- Run tests ---
370
452
  console.log(`\n🧪 Running tests...`);
371
453
  const result = await runBddScenarioWithTimeout(feature.scenario_file, happyPathLine);
372
454
 
455
+ // --- Handle timeout ---
373
456
  if (result.timedOut) {
374
457
  console.log(`⚠️ Test execution timed out - tests may be hanging`);
375
458
  console.log(`Stopping iteration loop`);
376
459
  break;
377
460
  }
378
461
 
379
- // 3. Parse results
462
+ // --- Parse results and track progress ---
380
463
  const currentResult = parseTestProgress(result.stdout + result.stderr);
381
464
  const errors = extractErrors(result.stdout + result.stderr);
382
-
383
- // 4. Track progress
384
465
  const newlyPassing = findNewlyPassingSteps(previousResult, currentResult);
385
466
 
386
- // 5. Display progress
467
+ // --- Display progress ---
387
468
  console.log(`\n📊 Progress: ${currentResult.passed}/${currentResult.total} steps passing`);
388
469
 
389
470
  if (newlyPassing.length > 0) {
@@ -391,20 +472,20 @@ while (iteration < MAX_ITERATIONS) {
391
472
  newlyPassing.forEach(step => console.log(` • ${step}`));
392
473
  }
393
474
 
394
- // 6. Check if all tests pass (GREEN state achieved)
475
+ // --- Check for GREEN state ---
395
476
  if (currentResult.exitCode === 0 || currentResult.passed === currentResult.total) {
396
477
  console.log(`\n🎉 GREEN: All tests passing!`);
397
478
  break;
398
479
  }
399
480
 
400
- // 7. Display next failure to address
481
+ // --- Display next failure ---
401
482
  if (errors.errors.length > 0) {
402
483
  const nextError = errors.errors[0];
403
484
  console.log(`\n🔧 Next failure to address:`);
404
485
  console.log(` Step: ${nextError.step}`);
405
486
  console.log(` Error: ${nextError.message}`);
406
487
  if (nextError.stack) {
407
- console.log(` Stack: ${nextError.stack.split('\n')[0]}`); // First line only
488
+ console.log(` Stack: ${nextError.stack.split('\n')[0]}`);
408
489
  }
409
490
  } else if (currentResult.failedSteps.length > 0) {
410
491
  console.log(`\n🔧 Still failing:`);
@@ -414,11 +495,10 @@ while (iteration < MAX_ITERATIONS) {
414
495
  }
415
496
  }
416
497
 
417
- // Store for next iteration comparison
418
498
  previousResult = currentResult;
419
499
  }
420
500
 
421
- // After loop ends
501
+ // --- Handle max iterations reached ---
422
502
  if (iteration >= MAX_ITERATIONS) {
423
503
  console.log(`\n⚠️ Maximum iterations (${MAX_ITERATIONS}) reached without achieving GREEN`);
424
504
  console.log(`Final progress: ${previousResult.passed}/${previousResult.total} steps passing`);
@@ -504,8 +584,8 @@ if (currentResult.exitCode === 0 || currentResult.passed === currentResult.total
504
584
  console.log(`\n🔍 Running full verification (all scenarios)...`);
505
585
 
506
586
  // Run entire feature file once for regression detection
507
- const { runBddTestWithTimeout } = require('./.claude/skills/speed-mode/test-runner');
508
- const fullResult = await runBddTestWithTimeout(feature.scenario_file);
587
+ // Uses the already imported runBddScenarioWithTimeout with no line number to run all scenarios
588
+ const fullResult = await runBddScenarioWithTimeout(feature.scenario_file);
509
589
 
510
590
  if (fullResult.timedOut) {
511
591
  console.log(`⚠️ Full verification timed out`);
@@ -550,35 +630,10 @@ if (filesModified.length > 0) {
550
630
  console.log();
551
631
  }
552
632
 
553
- // Generate unit tests for new functions after GREEN
554
- console.log(`📝 Generating unit tests for new functions...\n`);
555
- const { generateTestsAfterGreen } = require('./lib/unit-test-generator');
556
-
557
- const allFiles = [...filesCreated, ...filesModified];
558
- const testsGenerated = [];
559
-
560
- for (const file of allFiles) {
561
- if (file.endsWith('.js') && !file.includes('test')) {
562
- try {
563
- const result = generateTestsAfterGreen(file);
564
- if (result.created || result.functionsAdded > 0) {
565
- testsGenerated.push({ file: result.testFile, functionsAdded: result.functionsAdded });
566
- console.log(` ✅ ${result.testFile} (${result.functionsAdded} functions)`);
567
- }
568
- } catch (err) {
569
- console.log(` ⚠️ Could not generate tests for ${file}: ${err.message}`);
570
- }
571
- }
572
- }
573
-
574
- if (testsGenerated.length > 0) {
575
- console.log(`\n🧪 Generated tests for ${testsGenerated.length} files`);
576
- console.log(` Tests have TODO placeholders - stable mode will add edge cases\n`);
577
- } else {
578
- console.log(`No unit tests generated (no functions found)\n`);
579
- }
633
+ // Note: Unit tests should be added during stable mode implementation
634
+ // Speed mode focuses on proving the happy path works
580
635
 
581
- console.log(`Next step: Elevate to stable mode using 'node jettypod.js work set-mode <feature-id> stable'\n`);
636
+ console.log(`Next step: Elevate to stable mode using 'jettypod work set-mode <feature-id> stable'\n`);
582
637
  ```
583
638
 
584
639
  **Display:**
@@ -607,10 +662,12 @@ Next step: Elevate to stable mode using 'node jettypod.js work set-mode <feature
607
662
  **On FAILURE (max iterations or timeout):**
608
663
 
609
664
  ```javascript
665
+ // --- Display failure header ---
610
666
  console.log(`\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`);
611
667
  console.log(`⚠️ SPEED MODE INCOMPLETE - STILL IN RED STATE`);
612
668
  console.log(`━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n`);
613
669
 
670
+ // --- Handle timeout case ---
614
671
  if (result.timedOut) {
615
672
  console.log(`❌ Test execution timed out`);
616
673
  console.log(`\nPossible causes:`);
@@ -618,15 +675,18 @@ if (result.timedOut) {
618
675
  console.log(` • Test is waiting for async operation that never completes`);
619
676
  console.log(` • Step definition has blocking code`);
620
677
  } else {
678
+ // --- Handle max iterations case ---
621
679
  console.log(`❌ Maximum iterations (${MAX_ITERATIONS}) reached\n`);
622
680
  console.log(`Final Progress: ${previousResult.passed}/${previousResult.total} steps passing\n`);
623
681
 
682
+ // --- Display failing steps ---
624
683
  if (previousResult.failedSteps.length > 0) {
625
684
  console.log(`Still failing:`);
626
685
  previousResult.failedSteps.forEach(step => console.log(` ✖ ${step}`));
627
686
  console.log();
628
687
  }
629
688
 
689
+ // --- Display remaining errors ---
630
690
  const errors = extractErrors(result.stdout + result.stderr);
631
691
  if (errors.errors.length > 0) {
632
692
  console.log(`Remaining errors:`);
@@ -637,6 +697,7 @@ if (result.timedOut) {
637
697
  }
638
698
  }
639
699
 
700
+ // --- Display next steps ---
640
701
  console.log(`\nWhat to do:`);
641
702
  console.log(` • Review implementation approach - is it the right strategy?`);
642
703
  console.log(` • Check for incorrect assumptions about existing code`);
@@ -678,6 +739,11 @@ DO NOT proceed to generate stable mode chores until GREEN is achieved.
678
739
 
679
740
  **Move to Step 4 only if GREEN achieved.**
680
741
 
742
+ <!-- ═══════════════════════════════════════════════════════════════════════════
743
+ PHASE 4: STABLE CHORE GENERATION
744
+ ⚡ ASYNC BOUNDARY - Must wait for user to confirm proposed chores
745
+ ═══════════════════════════════════════════════════════════════════════════ -->
746
+
681
747
  ### Step 4: Generate Stable Mode Chores
682
748
 
683
749
  **Two phases: Analyze and propose → Get confirmation → Create autonomously**
@@ -741,6 +807,11 @@ Sound good? I'll create these chores once you confirm.
741
807
 
742
808
  If user adjusts: revise chores and confirm again.
743
809
 
810
+ <!-- ═══════════════════════════════════════════════════════════════════════════
811
+ PHASE 5: AUTONOMOUS COMPLETION
812
+ User has confirmed chores - create them and finalize
813
+ ═══════════════════════════════════════════════════════════════════════════ -->
814
+
744
815
  #### Phase 3: Create Chores Autonomously
745
816
 
746
817
  **CRITICAL:** After user confirms, create chores programmatically - no additional permission needed.
@@ -751,11 +822,13 @@ If user adjusts: revise chores and confirm again.
751
822
  const { create } = require('./features/work-tracking');
752
823
  const { getCurrentWork } = require('../../lib/current-work');
753
824
 
754
- const currentWork = getCurrentWork();
755
- const featureId = currentWork.parent_id; // Parent feature
825
+ (async () => {
826
+ const currentWork = await getCurrentWork();
827
+ const featureId = currentWork.parent_id; // Parent feature
756
828
 
757
- // For each confirmed chore:
758
- await create('chore', 'Chore Title', 'Description', featureId, 'stable', false);
829
+ // For each confirmed chore:
830
+ await create('chore', 'Chore Title', 'Description', featureId, 'stable', false);
831
+ })();
759
832
  ```
760
833
 
761
834
  **Display results:**
@@ -773,42 +846,56 @@ Chores created:
773
846
 
774
847
  **CRITICAL: Check if ALL speed mode chores are complete. If yes, auto-elevate to stable mode.**
775
848
 
849
+ <!-- ┌─────────────────────────────────────────────────────────────────────────┐
850
+ │ 🔍 COMPLETION CHECK: Speed Chores │
851
+ │ │
852
+ │ Progress Tracking: │
853
+ │ • Query: Count incomplete speed chores for feature │
854
+ │ • Display: "X speed mode chores remaining" or "All complete" │
855
+ │ • Action: Auto-elevate if all complete │
856
+ │ │
857
+ │ Return Point: │
858
+ │ • CHECKPOINT_CHORE_COUNT: Known incomplete count from last check │
859
+ │ • If session interrupted, re-query to get current count │
860
+ └─────────────────────────────────────────────────────────────────────────┘ -->
861
+
776
862
  ```javascript
777
- // Check if all speed chores for this feature are done
863
+ // --- Imports ---
778
864
  const { getDb } = require('../../lib/database');
779
865
  const { getCurrentWork } = require('../../lib/current-work');
780
866
 
781
- const currentWork = getCurrentWork();
782
- const featureId = currentWork.parent_id;
783
-
784
- const db = getDb();
785
- db.get(`
786
- SELECT COUNT(*) as incomplete_count
787
- FROM work_items
788
- WHERE parent_id = ?
789
- AND type = 'chore'
790
- AND mode = 'speed'
791
- AND status != 'done'
792
- `, [featureId], async (err, result) => {
793
- if (err) {
794
- console.error('Error checking speed chores:', err.message);
795
- db.close();
796
- return;
797
- }
867
+ (async () => {
868
+ // --- Get current work context ---
869
+ const currentWork = await getCurrentWork();
870
+ const featureId = currentWork.parent_id;
871
+ const db = getDb();
872
+
873
+ // --- Query for incomplete speed chores ---
874
+ const result = await new Promise((resolve, reject) => {
875
+ db.get(`
876
+ SELECT COUNT(*) as incomplete_count
877
+ FROM work_items
878
+ WHERE parent_id = ?
879
+ AND type = 'chore'
880
+ AND mode = 'speed'
881
+ AND status != 'done'
882
+ `, [featureId], (err, row) => {
883
+ if (err) reject(err);
884
+ else resolve(row);
885
+ });
886
+ });
798
887
 
888
+ // --- Handle completion or remaining chores ---
799
889
  if (result.incomplete_count === 0) {
800
- // All speed chores done - auto-elevate to stable
801
890
  console.log('\n✅ All speed mode chores complete!');
802
891
  console.log('Auto-elevating feature to stable mode...\n');
803
-
804
892
  // Use Bash tool to execute elevation
805
- // DO NOT display as text - EXECUTE IT
806
893
  } else {
807
894
  console.log(`\n📋 ${result.incomplete_count} speed mode chores remaining`);
808
895
  }
809
896
 
810
897
  db.close();
811
- });
898
+ })();
812
899
  ```
813
900
 
814
901
  **If all speed chores are done, use Bash tool to EXECUTE elevation:**