thrivekit 2.0.13 → 2.0.14

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/ralph/loop.sh +62 -6
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "thrivekit",
3
- "version": "2.0.13",
3
+ "version": "2.0.14",
4
4
  "description": "Tools to thrive with agentic coding - RALPH autonomous loop, Claude Code hooks, PRD-driven development",
5
5
  "author": "Allie Jones <allie@allthrive.ai>",
6
6
  "license": "MIT",
package/ralph/loop.sh CHANGED
@@ -73,7 +73,11 @@ run_loop() {
73
73
  local iteration=0
74
74
  local last_story=""
75
75
  local consecutive_failures=0
76
- local max_story_retries=3
76
+ local max_story_retries=5
77
+ local total_attempts=0
78
+ local skipped_stories=()
79
+ local start_time
80
+ start_time=$(date +%s)
77
81
 
78
82
  while [[ $iteration -lt $max_iterations ]]; do
79
83
  # Check for stop signal
@@ -108,19 +112,37 @@ run_loop() {
108
112
  fi
109
113
 
110
114
  if [[ -z "$story" ]]; then
115
+ print_progress_summary "$start_time" "$total_attempts" "${#skipped_stories[@]}"
111
116
  send_notification "✅ Ralph finished: All stories passed!"
112
117
  archive_feature
113
118
  return 0
114
119
  fi
115
120
 
121
+ ((total_attempts++))
122
+
116
123
  # Track repeated failures on same story
117
124
  if [[ "$story" == "$last_story" ]]; then
118
125
  ((consecutive_failures++))
119
- if [[ $consecutive_failures -ge $max_story_retries ]]; then
120
- print_warning "$story failed $consecutive_failures times - check failure context above"
121
- else
122
- print_warning "Retry $consecutive_failures/$max_story_retries for $story (failure context included)"
126
+
127
+ # Circuit breaker: skip to next story after max retries
128
+ if [[ $consecutive_failures -gt $max_story_retries ]]; then
129
+ print_error "Circuit breaker: $story failed $max_story_retries times, skipping to next story"
130
+ echo ""
131
+ echo " Saved failure context to: $RALPH_DIR/failures/$story.txt"
132
+ mkdir -p "$RALPH_DIR/failures"
133
+ cp "$RALPH_DIR/last_failure.txt" "$RALPH_DIR/failures/$story.txt" 2>/dev/null || true
134
+ skipped_stories+=("$story")
135
+ # Mark as skipped (not passed, but move on)
136
+ jq --arg id "$story" '(.stories[] | select(.id==$id)) |= . + {skipped: true}' "$RALPH_DIR/prd.json" > "$RALPH_DIR/prd.json.tmp" && mv "$RALPH_DIR/prd.json.tmp" "$RALPH_DIR/prd.json"
137
+ last_story=""
138
+ consecutive_failures=0
139
+ continue
123
140
  fi
141
+
142
+ # Exponential backoff before retry
143
+ local backoff=$((2 ** (consecutive_failures - 1)))
144
+ print_warning "Retry $consecutive_failures/$max_story_retries for $story (waiting ${backoff}s...)"
145
+ sleep "$backoff"
124
146
  else
125
147
  consecutive_failures=1
126
148
  last_story="$story"
@@ -305,9 +327,10 @@ run_loop() {
305
327
  done
306
328
 
307
329
  print_warning "Max iterations ($max_iterations) reached"
330
+ print_progress_summary "$start_time" "$total_attempts" "${#skipped_stories[@]}"
308
331
  local passed failed
309
332
  passed=$(jq '[.stories[] | select(.passes==true)] | length' "$RALPH_DIR/prd.json" 2>/dev/null || echo "0")
310
- failed=$(jq '[.stories[] | select(.passes==false)] | length' "$RALPH_DIR/prd.json" 2>/dev/null || echo "0")
333
+ failed=$(jq '[.stories[] | select(.passes==false and .skipped!=true)] | length' "$RALPH_DIR/prd.json" 2>/dev/null || echo "0")
311
334
  send_notification "⚠️ Ralph stopped: $passed passed, $failed remaining (max iterations reached)"
312
335
  return 1
313
336
  }
@@ -532,6 +555,39 @@ build_prompt() {
532
555
  _inject_developer_dna
533
556
  }
534
557
 
558
+ # Print progress summary at end of run
559
+ print_progress_summary() {
560
+ local start_time="$1"
561
+ local total_attempts="$2"
562
+ local skipped_count="$3"
563
+
564
+ local end_time
565
+ end_time=$(date +%s)
566
+ local duration=$((end_time - start_time))
567
+ local hours=$((duration / 3600))
568
+ local minutes=$(((duration % 3600) / 60))
569
+
570
+ local passed failed total
571
+ passed=$(jq '[.stories[] | select(.passes==true)] | length' "$RALPH_DIR/prd.json" 2>/dev/null || echo "0")
572
+ failed=$(jq '[.stories[] | select(.passes==false and .skipped!=true)] | length' "$RALPH_DIR/prd.json" 2>/dev/null || echo "0")
573
+ total=$(jq '.stories | length' "$RALPH_DIR/prd.json" 2>/dev/null || echo "0")
574
+
575
+ echo ""
576
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
577
+ print_success "COMPLETE"
578
+ echo ""
579
+ echo " Stories: $passed/$total passed"
580
+ [[ "$skipped_count" -gt 0 ]] && echo " Skipped: $skipped_count (hit circuit breaker)"
581
+ echo " Attempts: $total_attempts total iterations"
582
+ if [[ $hours -gt 0 ]]; then
583
+ echo " Duration: ${hours}h ${minutes}m"
584
+ else
585
+ echo " Duration: ${minutes}m"
586
+ fi
587
+ echo ""
588
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
589
+ }
590
+
535
591
  # Mark feature as complete (keep PRD for appending new stories)
536
592
  archive_feature() {
537
593
  local feature_name