vibe-and-thrive 1.6.8 → 1.7.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/package.json +1 -1
- package/ralph/loop.sh +147 -96
- package/ralph/utils.sh +40 -2
- package/ralph/verify.sh +30 -25
package/package.json
CHANGED
package/ralph/loop.sh
CHANGED
|
@@ -251,55 +251,59 @@ startup_checklist() {
|
|
|
251
251
|
fi
|
|
252
252
|
}
|
|
253
253
|
|
|
254
|
-
#
|
|
255
|
-
|
|
256
|
-
local
|
|
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
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
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
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
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
|
-
|
|
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
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
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
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
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
|
|
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
|
+
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
|
+
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" >> "$
|
|
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
|
package/ralph/verify.sh
CHANGED
|
@@ -225,8 +225,8 @@ EOF
|
|
|
225
225
|
echo " Reviewing changes..."
|
|
226
226
|
|
|
227
227
|
local result
|
|
228
|
-
#
|
|
229
|
-
result=$(echo "$prompt" | run_with_timeout
|
|
228
|
+
# Timeout for code review (defined in utils.sh)
|
|
229
|
+
result=$(echo "$prompt" | run_with_timeout "$CODE_REVIEW_TIMEOUT_SECONDS" claude -p --dangerously-skip-permissions 2>/dev/null) || {
|
|
230
230
|
print_warning " Code review skipped (Claude unavailable or timed out)"
|
|
231
231
|
return 0
|
|
232
232
|
}
|
|
@@ -345,13 +345,13 @@ run_auto_fix() {
|
|
|
345
345
|
fi
|
|
346
346
|
fi
|
|
347
347
|
|
|
348
|
-
# Check frontend
|
|
349
|
-
local
|
|
350
|
-
|
|
351
|
-
[[ -d "client" ]] && fe_dir="client"
|
|
352
|
-
[[ -d "web" ]] && fe_dir="web"
|
|
348
|
+
# Check frontend directories (monorepo support)
|
|
349
|
+
local fe_dirs
|
|
350
|
+
fe_dirs=$(get_frontend_dirs)
|
|
353
351
|
|
|
354
|
-
|
|
352
|
+
while IFS= read -r fe_dir; do
|
|
353
|
+
[[ -z "$fe_dir" ]] && continue
|
|
354
|
+
[[ ! -f "$fe_dir/package.json" ]] && continue
|
|
355
355
|
# ESLint fix
|
|
356
356
|
if grep -q '"eslint"' "$fe_dir/package.json" 2>/dev/null; then
|
|
357
357
|
(cd "$fe_dir" && npx eslint --fix . 2>/dev/null) || true
|
|
@@ -366,7 +366,7 @@ run_auto_fix() {
|
|
|
366
366
|
if grep -q '"prettier"' "$fe_dir/package.json" 2>/dev/null; then
|
|
367
367
|
(cd "$fe_dir" && npx prettier --write . 2>/dev/null) || true
|
|
368
368
|
fi
|
|
369
|
-
|
|
369
|
+
done <<< "$fe_dirs"
|
|
370
370
|
|
|
371
371
|
# Prettier fix (root - for non-monorepo)
|
|
372
372
|
if [[ -f "package.json" ]] && grep -q '"prettier"' package.json 2>/dev/null; then
|
|
@@ -387,14 +387,18 @@ verify_lint() {
|
|
|
387
387
|
print_error "failed"
|
|
388
388
|
echo ""
|
|
389
389
|
echo " Unfixable lint errors:"
|
|
390
|
-
ruff check . 2>/dev/null | head -
|
|
390
|
+
ruff check . 2>/dev/null | head -"$MAX_LINT_ERROR_LINES" | sed 's/^/ /'
|
|
391
391
|
failed=1
|
|
392
392
|
fi
|
|
393
393
|
fi
|
|
394
394
|
|
|
395
395
|
# Check for monorepo backend directories
|
|
396
|
-
|
|
397
|
-
|
|
396
|
+
local api_dirs
|
|
397
|
+
api_dirs=$(get_backend_dirs)
|
|
398
|
+
|
|
399
|
+
while IFS= read -r api_dir; do
|
|
400
|
+
[[ -z "$api_dir" ]] && continue
|
|
401
|
+
if [[ -f "$api_dir/pyproject.toml" || -f "$api_dir/ruff.toml" ]]; then
|
|
398
402
|
echo -n " Ruff lint check ($api_dir)... "
|
|
399
403
|
if (cd "$api_dir" && ruff check . --quiet 2>/dev/null); then
|
|
400
404
|
print_success "passed"
|
|
@@ -402,11 +406,11 @@ verify_lint() {
|
|
|
402
406
|
print_error "failed"
|
|
403
407
|
echo ""
|
|
404
408
|
echo " Unfixable lint errors in $api_dir:"
|
|
405
|
-
(cd "$api_dir" && ruff check . 2>/dev/null) | head -
|
|
409
|
+
(cd "$api_dir" && ruff check . 2>/dev/null) | head -"$MAX_LINT_ERROR_LINES" | sed 's/^/ /'
|
|
406
410
|
failed=1
|
|
407
411
|
fi
|
|
408
412
|
fi
|
|
409
|
-
done
|
|
413
|
+
done <<< "$api_dirs"
|
|
410
414
|
|
|
411
415
|
return $failed
|
|
412
416
|
}
|
|
@@ -418,15 +422,16 @@ run_fastapi_response_check() {
|
|
|
418
422
|
# Skip if check script doesn't exist
|
|
419
423
|
[[ ! -f "$check_script" ]] && return 0
|
|
420
424
|
|
|
421
|
-
# Find FastAPI directories
|
|
425
|
+
# Find FastAPI directories (check root + backend dirs)
|
|
422
426
|
local fastapi_dirs=()
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
427
|
+
local all_dirs=("." $(get_backend_dirs))
|
|
428
|
+
|
|
429
|
+
for dir in "${all_dirs[@]}"; do
|
|
430
|
+
[[ ! -d "$dir" ]] && continue
|
|
431
|
+
# Check for FastAPI imports
|
|
432
|
+
if grep -rq "from fastapi" "$dir"/*.py 2>/dev/null || \
|
|
433
|
+
grep -rq "from fastapi" "$dir"/**/*.py 2>/dev/null; then
|
|
434
|
+
fastapi_dirs+=("$dir")
|
|
430
435
|
fi
|
|
431
436
|
done
|
|
432
437
|
|
|
@@ -445,7 +450,7 @@ run_fastapi_response_check() {
|
|
|
445
450
|
else
|
|
446
451
|
print_error "failed"
|
|
447
452
|
echo ""
|
|
448
|
-
echo "$output" | head -
|
|
453
|
+
echo "$output" | head -"$MAX_ERROR_PREVIEW_LINES" | sed 's/^/ /'
|
|
449
454
|
# Save for failure context so Claude can fix
|
|
450
455
|
echo "$output" > "$log_file"
|
|
451
456
|
failed=1
|
|
@@ -493,7 +498,7 @@ run_configured_checks() {
|
|
|
493
498
|
print_error "failed"
|
|
494
499
|
echo ""
|
|
495
500
|
echo " Pre-commit hook errors (after auto-fix):"
|
|
496
|
-
grep -A 20 "Failed\|error\|Error" "$precommit_log" | head -
|
|
501
|
+
grep -A 20 "Failed\|error\|Error" "$precommit_log" | head -"$MAX_ERROR_PREVIEW_LINES" | sed 's/^/ /'
|
|
497
502
|
return 1
|
|
498
503
|
fi
|
|
499
504
|
else
|
|
@@ -501,7 +506,7 @@ run_configured_checks() {
|
|
|
501
506
|
print_error "failed"
|
|
502
507
|
echo ""
|
|
503
508
|
echo " Pre-commit hook errors:"
|
|
504
|
-
grep -A 20 "Failed\|error\|Error" "$precommit_log" | head -
|
|
509
|
+
grep -A 20 "Failed\|error\|Error" "$precommit_log" | head -"$MAX_ERROR_PREVIEW_LINES" | sed 's/^/ /'
|
|
505
510
|
return 1
|
|
506
511
|
fi
|
|
507
512
|
fi
|