vibe-and-thrive 1.6.8 → 1.7.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vibe-and-thrive",
3
- "version": "1.6.8",
3
+ "version": "1.7.1",
4
4
  "description": "Ship quality code faster with AI - RALPH autonomous loop, Claude Code hooks, and pre-commit checks",
5
5
  "author": "Allie Jones <allie@allthrive.ai>",
6
6
  "license": "MIT",
package/ralph/init.sh CHANGED
@@ -2,6 +2,13 @@
2
2
  # init.sh - Initialize ralph in a project
3
3
 
4
4
  ralph_init() {
5
+ # Check if already initialized (progress.txt is created by full init)
6
+ if [[ -f "$RALPH_DIR/progress.txt" ]]; then
7
+ echo "Ralph already initialized in this directory."
8
+ echo "Use 'ralph run' to start the loop or 'ralph status' to check status."
9
+ return 0
10
+ fi
11
+
5
12
  echo "Initializing ralph..."
6
13
 
7
14
  # Create directory structure
package/ralph/loop.sh CHANGED
@@ -251,55 +251,59 @@ startup_checklist() {
251
251
  fi
252
252
  }
253
253
 
254
- # Build the prompt with story context injected
255
- build_prompt() {
256
- local story="$1"
257
- local failure_context="${2:-}"
258
-
259
- # Read base PROMPT.md
260
- cat "$PROMPT_FILE"
254
+ # Helper: Inject story details into prompt
255
+ _inject_story_context() {
256
+ local story_json="$1"
261
257
 
262
258
  echo ""
263
259
  echo "---"
264
260
  echo ""
265
261
  echo "## Current Story"
266
262
  echo ""
267
-
268
- # Inject story details
269
- local story_json
270
- story_json=$(jq --arg id "$story" '.stories[] | select(.id==$id)' "$RALPH_DIR/prd.json")
271
263
  echo '```json'
272
264
  echo "$story_json"
273
265
  echo '```'
266
+ }
267
+
268
+ # Helper: Inject file guidance into prompt
269
+ _inject_file_guidance() {
270
+ local story_json="$1"
274
271
 
275
- # Extract file guidance if present
276
272
  local has_files
277
273
  has_files=$(echo "$story_json" | jq -r '.files // empty' 2>/dev/null)
278
- if [[ -n "$has_files" ]]; then
279
- echo ""
280
- echo "### File Guidance for This Story"
281
- echo ""
282
- echo "**Create these files:**"
283
- echo "$story_json" | jq -r '.files.create[]? // empty' | sed 's/^/- /'
284
- echo ""
285
- echo "**Modify these files:**"
286
- echo "$story_json" | jq -r '.files.modify[]? // empty' | sed 's/^/- /'
287
- echo ""
288
- echo "**Reuse/import from:**"
289
- echo "$story_json" | jq -r '.files.reuse[]? // empty' | sed 's/^/- /'
290
- fi
274
+ [[ -z "$has_files" ]] && return
275
+
276
+ echo ""
277
+ echo "### File Guidance for This Story"
278
+ echo ""
279
+ echo "**Create these files:**"
280
+ echo "$story_json" | jq -r '.files.create[]? // empty' | sed 's/^/- /'
281
+ echo ""
282
+ echo "**Modify these files:**"
283
+ echo "$story_json" | jq -r '.files.modify[]? // empty' | sed 's/^/- /'
284
+ echo ""
285
+ echo "**Reuse/import from:**"
286
+ echo "$story_json" | jq -r '.files.reuse[]? // empty' | sed 's/^/- /'
287
+ }
288
+
289
+ # Helper: Inject scalability guidance for story
290
+ _inject_story_scale() {
291
+ local story_json="$1"
291
292
 
292
- # Extract scalability guidance if present (for backend stories)
293
293
  local has_scale
294
294
  has_scale=$(echo "$story_json" | jq -r '.scale // empty' 2>/dev/null)
295
- if [[ -n "$has_scale" ]]; then
296
- echo ""
297
- echo "### Scalability Requirements for This Story"
298
- echo ""
299
- echo "$story_json" | jq -r '.scale | to_entries[] | "- **\(.key):** \(.value)"' 2>/dev/null
300
- fi
295
+ [[ -z "$has_scale" ]] && return
296
+
297
+ echo ""
298
+ echo "### Scalability Requirements for This Story"
299
+ echo ""
300
+ echo "$story_json" | jq -r '.scale | to_entries[] | "- **\(.key):** \(.value)"' 2>/dev/null
301
+ }
302
+
303
+ # Helper: Inject styleguide reference for frontend stories
304
+ _inject_styleguide() {
305
+ local story_json="$1"
301
306
 
302
- # For frontend stories, instruct Claude to read the styleguide first
303
307
  local story_type
304
308
  story_type=$(echo "$story_json" | jq -r '.type // "frontend"' 2>/dev/null)
305
309
  local styleguide_path
@@ -312,74 +316,87 @@ build_prompt() {
312
316
  echo "**FIRST:** Read the project styleguide at \`$styleguide_path\` before implementing."
313
317
  echo "Use existing components, colors, and patterns from the styleguide."
314
318
  fi
319
+ }
315
320
 
321
+ # Helper: Inject feature-level context
322
+ _inject_feature_context() {
316
323
  echo ""
317
324
  echo "## Feature Context"
318
325
  echo ""
319
326
  echo '```json'
320
327
  jq '{feature: .feature, metadata: .metadata}' "$RALPH_DIR/prd.json"
321
328
  echo '```'
329
+ }
322
330
 
323
- # Include scalability if defined
331
+ # Helper: Inject scalability requirements
332
+ _inject_scalability() {
324
333
  local has_scalability
325
334
  has_scalability=$(jq -r '.scalability // empty' "$RALPH_DIR/prd.json" 2>/dev/null)
326
- if [[ -n "$has_scalability" ]]; then
327
- echo ""
328
- echo "## Scalability Requirements"
329
- echo ""
330
- echo "**IMPORTANT:** Follow these scalability rules."
331
- echo ""
332
- echo '```json'
333
- jq '.scalability' "$RALPH_DIR/prd.json"
334
- echo '```'
335
- echo ""
336
- echo "### Key Rules:"
337
- echo "- Always paginate list endpoints (never return unbounded arrays)"
338
- echo "- Avoid N+1 queries - eager load relationships"
339
- echo "- Add database indexes for frequently queried fields"
340
- echo "- Implement caching strategy as specified"
341
- echo "- Add rate limiting to public endpoints"
342
- fi
335
+ [[ -z "$has_scalability" ]] && return
336
+
337
+ echo ""
338
+ echo "## Scalability Requirements"
339
+ echo ""
340
+ echo "**IMPORTANT:** Follow these scalability rules."
341
+ echo ""
342
+ echo '```json'
343
+ jq '.scalability' "$RALPH_DIR/prd.json"
344
+ echo '```'
345
+ echo ""
346
+ echo "### Key Rules:"
347
+ echo "- Always paginate list endpoints (never return unbounded arrays)"
348
+ echo "- Avoid N+1 queries - eager load relationships"
349
+ echo "- Add database indexes for frequently queried fields"
350
+ echo "- Implement caching strategy as specified"
351
+ echo "- Add rate limiting to public endpoints"
352
+ }
343
353
 
344
- # Include architecture if defined
354
+ # Helper: Inject architecture guidelines
355
+ _inject_architecture() {
345
356
  local has_architecture
346
357
  has_architecture=$(jq -r '.architecture // empty' "$RALPH_DIR/prd.json" 2>/dev/null)
347
- if [[ -n "$has_architecture" ]]; then
348
- echo ""
349
- echo "## Architecture Guidelines"
350
- echo ""
351
- echo "**IMPORTANT:** Follow these architecture rules strictly."
352
- echo ""
353
- echo '```json'
354
- jq '.architecture' "$RALPH_DIR/prd.json"
355
- echo '```'
356
- echo ""
357
- echo "### Key Rules:"
358
- echo "- Put files in the specified directories"
359
- echo "- Reuse existing components listed in 'patterns.reuse'"
360
- echo "- Do NOT create anything in 'doNotCreate'"
361
- echo "- Keep files under $(jq -r '.architecture.principles.maxFileLines // 300' "$RALPH_DIR/prd.json") lines"
362
- echo "- Scripts go in scripts/, docs go in docs/"
363
- fi
358
+ [[ -z "$has_architecture" ]] && return
364
359
 
365
- # Include failure context from previous iteration if available
366
- if [[ -n "$failure_context" ]]; then
367
- echo ""
368
- echo "## Previous Iteration Failed"
369
- echo ""
370
- echo "**IMPORTANT:** The previous attempt at this story failed verification. Review the errors below and fix them."
371
- echo ""
372
- echo '```'
373
- echo "$failure_context"
374
- echo '```'
375
- echo ""
376
- echo "### What to do:"
377
- echo "1. Read the error messages carefully"
378
- echo "2. Identify the root cause"
379
- echo "3. Fix the issue (do not just retry the same approach)"
380
- echo "4. Run verification again"
381
- fi
360
+ echo ""
361
+ echo "## Architecture Guidelines"
362
+ echo ""
363
+ echo "**IMPORTANT:** Follow these architecture rules strictly."
364
+ echo ""
365
+ echo '```json'
366
+ jq '.architecture' "$RALPH_DIR/prd.json"
367
+ echo '```'
368
+ echo ""
369
+ echo "### Key Rules:"
370
+ echo "- Put files in the specified directories"
371
+ echo "- Reuse existing components listed in 'patterns.reuse'"
372
+ echo "- Do NOT create anything in 'doNotCreate'"
373
+ echo "- Keep files under $(jq -r '.architecture.principles.maxFileLines // 300' "$RALPH_DIR/prd.json") lines"
374
+ echo "- Scripts go in scripts/, docs go in docs/"
375
+ }
376
+
377
+ # Helper: Inject failure context from previous iteration
378
+ _inject_failure_context() {
379
+ local failure_context="$1"
380
+ [[ -z "$failure_context" ]] && return
381
+
382
+ echo ""
383
+ echo "## Previous Iteration Failed"
384
+ echo ""
385
+ echo "**IMPORTANT:** The previous attempt at this story failed verification. Review the errors below and fix them."
386
+ echo ""
387
+ echo '```'
388
+ echo "$failure_context"
389
+ echo '```'
390
+ echo ""
391
+ echo "### What to do:"
392
+ echo "1. Read the error messages carefully"
393
+ echo "2. Identify the root cause"
394
+ echo "3. Fix the issue (do not just retry the same approach)"
395
+ echo "4. Run verification again"
396
+ }
382
397
 
398
+ # Helper: Inject signs (learned patterns)
399
+ _inject_signs() {
383
400
  echo ""
384
401
  echo "## Signs (Learned Patterns)"
385
402
  echo ""
@@ -390,16 +407,43 @@ build_prompt() {
390
407
  else
391
408
  echo "(none yet)"
392
409
  fi
410
+ }
393
411
 
394
- # Include user's DNA (personal preferences) if it exists
395
- if [[ -f "$HOME/.claude/DNA.md" ]]; then
396
- echo ""
397
- echo "## Developer DNA"
398
- echo ""
399
- echo "The developer has these working preferences:"
400
- echo ""
401
- cat "$HOME/.claude/DNA.md"
402
- fi
412
+ # Helper: Inject developer DNA
413
+ _inject_developer_dna() {
414
+ [[ ! -f "$HOME/.claude/DNA.md" ]] && return
415
+
416
+ echo ""
417
+ echo "## Developer DNA"
418
+ echo ""
419
+ echo "The developer has these working preferences:"
420
+ echo ""
421
+ cat "$HOME/.claude/DNA.md"
422
+ }
423
+
424
+ # Build the prompt with story context injected
425
+ build_prompt() {
426
+ local story="$1"
427
+ local failure_context="${2:-}"
428
+
429
+ # Read base PROMPT.md
430
+ cat "$PROMPT_FILE"
431
+
432
+ # Get story JSON once
433
+ local story_json
434
+ story_json=$(jq --arg id "$story" '.stories[] | select(.id==$id)' "$RALPH_DIR/prd.json")
435
+
436
+ # Inject all sections
437
+ _inject_story_context "$story_json"
438
+ _inject_file_guidance "$story_json"
439
+ _inject_story_scale "$story_json"
440
+ _inject_styleguide "$story_json"
441
+ _inject_feature_context
442
+ _inject_scalability
443
+ _inject_architecture
444
+ _inject_failure_context "$failure_context"
445
+ _inject_signs
446
+ _inject_developer_dna
403
447
  }
404
448
 
405
449
  # Mark feature as complete (keep PRD for appending new stories)
@@ -418,7 +462,14 @@ archive_feature() {
418
462
  if ! git commit -m "feat: complete $feature_name" 2>/dev/null; then
419
463
  # Retry after pre-commit auto-fixes
420
464
  git add -A
421
- git commit -m "feat: complete $feature_name" 2>/dev/null || true
465
+ if ! git commit -m "feat: complete $feature_name" 2>/dev/null; then
466
+ # Check if it's "nothing to commit" vs real error
467
+ if git diff --cached --quiet 2>/dev/null; then
468
+ echo " (no changes to commit)"
469
+ else
470
+ print_warning "Final commit failed - check git status"
471
+ fi
472
+ fi
422
473
  fi
423
474
  fi
424
475
 
package/ralph/utils.sh CHANGED
@@ -6,9 +6,17 @@ readonly MAX_LOG_LINES=30
6
6
  readonly MAX_PROGRESS_LINES=10
7
7
  readonly MAX_GIT_STATUS_LINES=10
8
8
  readonly MAX_OUTPUT_PREVIEW_LINES=20
9
+ readonly MAX_ERROR_PREVIEW_LINES=40
10
+ readonly MAX_LINT_ERROR_LINES=20
9
11
  readonly ITERATION_DELAY_SECONDS=2
10
12
  readonly DEFAULT_TIMEOUT_SECONDS=600
11
13
  readonly DEFAULT_MAX_ITERATIONS=20
14
+ readonly CODE_REVIEW_TIMEOUT_SECONDS=120
15
+ readonly MAX_PROGRESS_FILE_LINES=1000
16
+
17
+ # Common project directories (avoid duplication across files)
18
+ readonly FRONTEND_DIRS=("apps/web" "frontend" "client" "web")
19
+ readonly BACKEND_DIRS=("apps/api" "api" "backend" "server")
12
20
 
13
21
  # Track temp files for safe cleanup
14
22
  RALPH_TEMP_FILES=()
@@ -20,6 +28,24 @@ YELLOW='\033[1;33m'
20
28
  BLUE='\033[0;34m'
21
29
  NC='\033[0m' # No Color
22
30
 
31
+ # Get existing frontend directories in this project
32
+ get_frontend_dirs() {
33
+ local dirs=()
34
+ for d in "${FRONTEND_DIRS[@]}"; do
35
+ [[ -d "$d" ]] && dirs+=("$d")
36
+ done
37
+ [[ ${#dirs[@]} -gt 0 ]] && printf '%s\n' "${dirs[@]}"
38
+ }
39
+
40
+ # Get existing backend directories in this project
41
+ get_backend_dirs() {
42
+ local dirs=()
43
+ for d in "${BACKEND_DIRS[@]}"; do
44
+ [[ -d "$d" ]] && dirs+=("$d")
45
+ done
46
+ [[ ${#dirs[@]} -gt 0 ]] && printf '%s\n' "${dirs[@]}"
47
+ }
48
+
23
49
  # Progress bar for story display
24
50
  progress_bar() {
25
51
  local current=$1 total=$2 width=${3:-6}
@@ -95,14 +121,26 @@ check_dependencies() {
95
121
  fi
96
122
  }
97
123
 
98
- # Log progress to progress.txt
124
+ # Log progress to progress.txt (with rotation to prevent unbounded growth)
99
125
  log_progress() {
100
126
  local story="$1"
101
127
  local status="$2"
102
128
  local msg="${3:-}"
103
129
  local timestamp
130
+ local progress_file="$RALPH_DIR/progress.txt"
131
+
104
132
  timestamp=$(date -Iseconds 2>/dev/null || date +%Y-%m-%dT%H:%M:%S)
105
- echo "[$timestamp] $status $story $msg" >> "$RALPH_DIR/progress.txt"
133
+ echo "[$timestamp] $status $story $msg" >> "$progress_file"
134
+
135
+ # Rotate if file exceeds max lines (keep last half)
136
+ if [[ -f "$progress_file" ]]; then
137
+ local line_count
138
+ line_count=$(wc -l < "$progress_file" 2>/dev/null || echo "0")
139
+ if [[ "$line_count" -gt "$MAX_PROGRESS_FILE_LINES" ]]; then
140
+ local keep_lines=$((MAX_PROGRESS_FILE_LINES / 2))
141
+ tail -"$keep_lines" "$progress_file" > "$progress_file.tmp" && mv "$progress_file.tmp" "$progress_file"
142
+ fi
143
+ fi
106
144
  }
107
145
 
108
146
  # Get a value from config.json with a default