mcp-probe-kit 1.11.0 → 1.13.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.
@@ -0,0 +1,779 @@
1
+ import { parseArgs, getString, getNumber } from "../utils/parseArgs.js";
2
+ // 默认值(保守安全)
3
+ const DEFAULTS = {
4
+ mode: "safe",
5
+ completion_promise: "tests passing + requirements met",
6
+ test_command: "npm test",
7
+ cli_command: "claude-code",
8
+ max_iterations: 8,
9
+ max_minutes: 25,
10
+ confirm_every: 1,
11
+ confirm_timeout: 20,
12
+ max_same_output: 2,
13
+ max_diff_lines: 300,
14
+ cooldown_seconds: 8,
15
+ };
16
+ /**
17
+ * 生成 PROMPT.md 模板
18
+ */
19
+ function generatePromptTemplate(goal, completionPromise, testCommand) {
20
+ return `# Ralph Wiggum Loop - Development Prompt
21
+
22
+ ## 🎯 Goal
23
+
24
+ ${goal}
25
+
26
+ ## ✅ Completion Promise
27
+
28
+ **Exit Condition**: ${completionPromise}
29
+
30
+ You MUST satisfy BOTH conditions to exit:
31
+ 1. \`COMPLETION_PROMISE_MET: true\`
32
+ 2. \`EXIT_SIGNAL: true\`
33
+
34
+
35
+ ## 📋 Iteration Rules
36
+
37
+ ### 1. Small Steps
38
+ - Make ONE focused change per iteration
39
+ - Avoid large refactors in a single iteration
40
+ - Keep changes under ${DEFAULTS.max_diff_lines} lines when possible
41
+
42
+ ### 2. Test First
43
+ - **CRITICAL**: First iteration MUST identify the correct test command for this project
44
+ - Check for: package.json scripts, pytest, cargo test, go test, mvn test, etc.
45
+ - Update this PROMPT.md with the correct command
46
+ - Run tests EVERY iteration: \`${testCommand}\`
47
+ - Do NOT proceed if tests fail (unless fixing test failures is the goal)
48
+
49
+ ### 3. Update Progress
50
+ - Update \`@fix_plan.md\` after each iteration
51
+ - Mark completed tasks with ✅
52
+ - Add new discovered tasks
53
+ - Adjust priorities
54
+ - Update \`PROGRESS.md\` with:
55
+ - What was done
56
+ - Test results
57
+ - Next step
58
+ - Current status
59
+
60
+ ### 4. State Block (REQUIRED)
61
+ At the end of EVERY response, output:
62
+
63
+ \`\`\`
64
+ COMPLETION_PROMISE_MET: [true|false]
65
+ EXIT_SIGNAL: [true|false]
66
+ SUMMARY: [one-line summary of this iteration]
67
+ NEXT_STEP: [what to do next, or "EXIT" if done]
68
+ \`\`\`
69
+
70
+ **Exit Logic**:
71
+ - Set \`COMPLETION_PROMISE_MET: true\` only when completion promise is satisfied
72
+ - Set \`EXIT_SIGNAL: true\` only when you're confident to exit
73
+ - Loop continues if EITHER is false
74
+
75
+ ### 5. Safety Checks
76
+ - If stuck or repeating same action → set \`EXIT_SIGNAL: true\` and ask for help
77
+ - If single change exceeds ${DEFAULTS.max_diff_lines} lines → stop and break into smaller tasks
78
+ - If tests keep failing after 3 attempts → stop and ask for help
79
+
80
+ ---
81
+
82
+ ## 📂 Files
83
+
84
+ - \`@fix_plan.md\`: Task breakdown and priorities
85
+ - \`PROGRESS.md\`: Iteration log
86
+ - \`STOP\`: Create this file to emergency stop
87
+
88
+ ---
89
+
90
+ *Generated by MCP Probe Kit - start_ralph*
91
+ `;
92
+ }
93
+ /**
94
+ * 生成 @fix_plan.md 模板
95
+ */
96
+ function generateFixPlanTemplate(goal) {
97
+ return `# Task Plan: ${goal}
98
+
99
+ ## 🎯 Goal
100
+ ${goal}
101
+
102
+ ## 📋 Tasks
103
+
104
+ ### ✅ Completed
105
+ - [ ] Identify correct test command
106
+ - [ ] Verify project structure
107
+
108
+ ### 🚧 In Progress
109
+ - [ ] [Task will be added by agent]
110
+
111
+ ### 📝 Todo
112
+ - [ ] [Tasks will be added by agent]
113
+
114
+ ### 🔍 Discovered Issues
115
+ - [Issues will be added during iterations]
116
+
117
+ ---
118
+
119
+ **Instructions for Agent**:
120
+ 1. First iteration: identify test command and update PROMPT.md
121
+ 2. Break down goal into small, testable tasks
122
+ 3. Mark tasks as completed with ✅
123
+ 4. Add new tasks as discovered
124
+ 5. Keep this file updated every iteration
125
+ `;
126
+ }
127
+ /**
128
+ * 生成 PROGRESS.md 模板
129
+ */
130
+ function generateProgressTemplate() {
131
+ return `# Ralph Loop Progress Log
132
+
133
+ ## Iteration Summary
134
+
135
+ | Iter | Time | Changed Lines | Tests | Status | Summary |
136
+ |------|------|---------------|-------|--------|---------|
137
+ | 0 | - | - | - | START | Loop initialized |
138
+
139
+ ---
140
+
141
+ ## Detailed Log
142
+
143
+ ### Iteration 0 - Initialization
144
+ - **Time**: [timestamp]
145
+ - **Action**: Loop started
146
+ - **Next**: Identify test command and begin first task
147
+
148
+ ---
149
+
150
+ **Instructions for Agent**:
151
+ - Add entry for each iteration
152
+ - Include: iteration number, timestamp, what was done, test results, next step
153
+ - Keep summary table updated
154
+ `;
155
+ }
156
+ /**
157
+ * 生成安全模式脚本 (Bash)
158
+ */
159
+ function generateSafeScript(params) {
160
+ return `#!/bin/bash
161
+ # Ralph Loop - Safe Mode
162
+ # Generated by MCP Probe Kit
163
+
164
+ set -euo pipefail
165
+
166
+ # ============================================
167
+ # SAFETY PARAMETERS (Override with env vars)
168
+ # ============================================
169
+ MAX_ITERS=\${MAX_ITERS:-${params.max_iterations}}
170
+ MAX_MINUTES=\${MAX_MINUTES:-${params.max_minutes}}
171
+ CONFIRM_EVERY=\${CONFIRM_EVERY:-${params.confirm_every}}
172
+ CONFIRM_TIMEOUT=\${CONFIRM_TIMEOUT:-${params.confirm_timeout}}
173
+ MAX_SAME_OUTPUT=\${MAX_SAME_OUTPUT:-${params.max_same_output}}
174
+ MAX_DIFF_LINES=\${MAX_DIFF_LINES:-${params.max_diff_lines}}
175
+ COOLDOWN_SECONDS=\${COOLDOWN_SECONDS:-${params.cooldown_seconds}}
176
+ REQUIRE_TTY=\${REQUIRE_TTY:-1}
177
+ CLI_COMMAND=\${CLI_COMMAND:-${params.cli_command}}
178
+
179
+ # ============================================
180
+ # SAFETY CHECKS
181
+ # ============================================
182
+ if [ "$REQUIRE_TTY" = "1" ] && [ ! -t 0 ]; then
183
+ echo "❌ ERROR: Not running in interactive terminal (TTY required for safety)"
184
+ echo " To override: REQUIRE_TTY=0 $0"
185
+ exit 1
186
+ fi
187
+
188
+ if [ ! -f "PROMPT.md" ]; then
189
+ echo "❌ ERROR: PROMPT.md not found. Run from .ralph/ directory"
190
+ exit 1
191
+ fi
192
+
193
+ # ============================================
194
+ # STARTUP WARNING
195
+ # ============================================
196
+ echo "🚀 Ralph Loop - Safe Mode"
197
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
198
+ echo "⚠️ Safety Limits:"
199
+ echo " • Max iterations: $MAX_ITERS"
200
+ echo " • Max time: $MAX_MINUTES minutes"
201
+ echo " • Confirm every: $CONFIRM_EVERY iteration(s)"
202
+ echo " • Confirm timeout: $CONFIRM_TIMEOUT seconds"
203
+ echo " • Max same output: $MAX_SAME_OUTPUT times"
204
+ echo " • Max diff lines: $MAX_DIFF_LINES lines"
205
+ echo ""
206
+ echo "💡 Emergency stop: touch STOP"
207
+ echo "💡 Pause: Ctrl+C"
208
+ echo ""
209
+ echo "Press Ctrl+C to cancel, or wait 5s to start..."
210
+ sleep 5
211
+
212
+
213
+ # ============================================
214
+ # INITIALIZATION
215
+ # ============================================
216
+ ITER=0
217
+ START_TIME=$(date +%s)
218
+ LAST_OUTPUT_HASH=""
219
+ SAME_OUTPUT_COUNT=0
220
+ LOG_FILE="ralph.log"
221
+
222
+ echo "[$(date '+%Y-%m-%d %H:%M:%S')] [INFO] Loop started" >> "$LOG_FILE"
223
+
224
+ # ============================================
225
+ # MAIN LOOP
226
+ # ============================================
227
+ while [ $ITER -lt $MAX_ITERS ]; do
228
+ ITER=$((ITER + 1))
229
+ echo ""
230
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
231
+ echo "🔄 Iteration $ITER / $MAX_ITERS"
232
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
233
+
234
+ # Check: STOP file
235
+ if [ -f "STOP" ]; then
236
+ echo "[$(date '+%Y-%m-%d %H:%M:%S')] [SAFE] STOP file detected" >> "$LOG_FILE"
237
+ echo "🛑 STOP file detected. Emergency exit."
238
+ exit 0
239
+ fi
240
+
241
+ # Check: Max time
242
+ CURRENT_TIME=$(date +%s)
243
+ ELAPSED_MINUTES=$(( (CURRENT_TIME - START_TIME) / 60 ))
244
+ if [ $ELAPSED_MINUTES -ge $MAX_MINUTES ]; then
245
+ echo "[$(date '+%Y-%m-%d %H:%M:%S')] [SAFE] Max time reached: $ELAPSED_MINUTES min" >> "$LOG_FILE"
246
+ echo "⏰ Max time ($MAX_MINUTES min) reached. Stopping."
247
+ exit 0
248
+ fi
249
+
250
+ # Check: Confirmation required
251
+ if [ $((ITER % CONFIRM_EVERY)) -eq 0 ]; then
252
+ echo ""
253
+ echo "⏸️ Confirmation required (timeout: \${CONFIRM_TIMEOUT}s)"
254
+ echo -n " Continue? [y/N]: "
255
+
256
+ if read -t $CONFIRM_TIMEOUT -r REPLY; then
257
+ if [[ ! $REPLY =~ ^[Yy]$ ]]; then
258
+ echo "[$(date '+%Y-%m-%d %H:%M:%S')] [SAFE] User declined to continue" >> "$LOG_FILE"
259
+ echo "🛑 User stopped the loop."
260
+ exit 0
261
+ fi
262
+ else
263
+ echo ""
264
+ echo "[$(date '+%Y-%m-%d %H:%M:%S')] [SAFE] Confirmation timeout" >> "$LOG_FILE"
265
+ echo "⏰ Confirmation timeout. Stopping for safety."
266
+ exit 0
267
+ fi
268
+ fi
269
+
270
+ # Execute Claude Code
271
+ echo "🤖 Running: $CLI_COMMAND @PROMPT.md"
272
+ echo "[$(date '+%Y-%m-%d %H:%M:%S')] [INFO] Iteration $ITER started" >> "$LOG_FILE"
273
+
274
+ OUTPUT_FILE="last_output_$ITER.txt"
275
+ if $CLI_COMMAND @PROMPT.md > "$OUTPUT_FILE" 2>&1; then
276
+ cat "$OUTPUT_FILE"
277
+ else
278
+ echo "[$(date '+%Y-%m-%d %H:%M:%S')] [ERROR] CLI command failed" >> "$LOG_FILE"
279
+ echo "❌ CLI command failed. Check $OUTPUT_FILE"
280
+ exit 1
281
+ fi
282
+
283
+ # Check: Output repetition
284
+ CURRENT_HASH=$(md5sum "$OUTPUT_FILE" 2>/dev/null | cut -d' ' -f1 || echo "")
285
+ if [ "$CURRENT_HASH" = "$LAST_OUTPUT_HASH" ]; then
286
+ SAME_OUTPUT_COUNT=$((SAME_OUTPUT_COUNT + 1))
287
+ if [ $SAME_OUTPUT_COUNT -ge $MAX_SAME_OUTPUT ]; then
288
+ echo "[$(date '+%Y-%m-%d %H:%M:%S')] [WARN] Output repeated $SAME_OUTPUT_COUNT times" >> "$LOG_FILE"
289
+ echo "⚠️ Output repeated $SAME_OUTPUT_COUNT times. Likely stuck. Stopping."
290
+ exit 0
291
+ fi
292
+ else
293
+ SAME_OUTPUT_COUNT=0
294
+ fi
295
+ LAST_OUTPUT_HASH="$CURRENT_HASH"
296
+
297
+ # Check: Git diff size (if in git repo)
298
+ if git rev-parse --git-dir > /dev/null 2>&1; then
299
+ CHANGED_LINES=$(git diff --stat | tail -1 | grep -oE '[0-9]+ insertion|[0-9]+ deletion' | grep -oE '[0-9]+' | awk '{s+=$1} END {print s}' || echo "0")
300
+ if [ "$CHANGED_LINES" -gt "$MAX_DIFF_LINES" ]; then
301
+ echo "[$(date '+%Y-%m-%d %H:%M:%S')] [WARN] Changed lines ($CHANGED_LINES) exceeds limit ($MAX_DIFF_LINES)" >> "$LOG_FILE"
302
+ echo "⚠️ Changed $CHANGED_LINES lines (limit: $MAX_DIFF_LINES). Please review manually."
303
+ echo " Run: git diff --stat"
304
+ exit 0
305
+ fi
306
+ fi
307
+
308
+ # Check: Exit signals in output
309
+ if grep -q "COMPLETION_PROMISE_MET: true" "$OUTPUT_FILE" && grep -q "EXIT_SIGNAL: true" "$OUTPUT_FILE"; then
310
+ echo "[$(date '+%Y-%m-%d %H:%M:%S')] [INFO] Both exit conditions met" >> "$LOG_FILE"
311
+ echo "✅ Completion promise met and exit signal received. Success!"
312
+ exit 0
313
+ fi
314
+
315
+ # Cooldown
316
+ echo "😴 Cooldown: \${COOLDOWN_SECONDS}s..."
317
+ sleep $COOLDOWN_SECONDS
318
+ done
319
+
320
+ # Max iterations reached
321
+ echo "[$(date '+%Y-%m-%d %H:%M:%S')] [SAFE] Max iterations reached" >> "$LOG_FILE"
322
+ echo "⏰ Max iterations ($MAX_ITERS) reached. Stopping."
323
+ exit 0
324
+ `;
325
+ }
326
+ /**
327
+ * 生成普通模式脚本 (Bash)
328
+ */
329
+ function generateNormalScript(params) {
330
+ return `#!/bin/bash
331
+ # Ralph Loop - Normal Mode (Use with caution!)
332
+ # Generated by MCP Probe Kit
333
+
334
+ set -euo pipefail
335
+
336
+ # ============================================
337
+ # PARAMETERS
338
+ # ============================================
339
+ MAX_ITERS=\${MAX_ITERS:-${params.max_iterations}}
340
+ CLI_COMMAND=\${CLI_COMMAND:-${params.cli_command}}
341
+
342
+ echo "🚀 Ralph Loop - Normal Mode"
343
+ echo "⚠️ WARNING: No confirmation required. Use Ctrl+C to stop."
344
+ echo " Max iterations: $MAX_ITERS"
345
+ echo ""
346
+ sleep 3
347
+
348
+ ITER=0
349
+ LOG_FILE="ralph.log"
350
+
351
+ while [ $ITER -lt $MAX_ITERS ]; do
352
+ ITER=$((ITER + 1))
353
+ echo "🔄 Iteration $ITER / $MAX_ITERS"
354
+
355
+ if [ -f "STOP" ]; then
356
+ echo "🛑 STOP file detected."
357
+ exit 0
358
+ fi
359
+
360
+ OUTPUT_FILE="last_output_$ITER.txt"
361
+ $CLI_COMMAND @PROMPT.md | tee "$OUTPUT_FILE"
362
+
363
+ if grep -q "COMPLETION_PROMISE_MET: true" "$OUTPUT_FILE" && grep -q "EXIT_SIGNAL: true" "$OUTPUT_FILE"; then
364
+ echo "✅ Success!"
365
+ exit 0
366
+ fi
367
+
368
+ sleep 5
369
+ done
370
+
371
+ echo "⏰ Max iterations reached."
372
+ exit 0
373
+ `;
374
+ }
375
+ /**
376
+ * 生成 Windows 安全模式脚本 (PowerShell)
377
+ */
378
+ function generateSafeScriptWindows(params) {
379
+ return `# Ralph Loop - Safe Mode (Windows)
380
+ # Generated by MCP Probe Kit
381
+
382
+ $ErrorActionPreference = "Stop"
383
+
384
+ # ============================================
385
+ # SAFETY PARAMETERS
386
+ # ============================================
387
+ $MAX_ITERS = if ($env:MAX_ITERS) { [int]$env:MAX_ITERS } else { ${params.max_iterations} }
388
+ $MAX_MINUTES = if ($env:MAX_MINUTES) { [int]$env:MAX_MINUTES } else { ${params.max_minutes} }
389
+ $CONFIRM_EVERY = if ($env:CONFIRM_EVERY) { [int]$env:CONFIRM_EVERY } else { ${params.confirm_every} }
390
+ $CONFIRM_TIMEOUT = if ($env:CONFIRM_TIMEOUT) { [int]$env:CONFIRM_TIMEOUT } else { ${params.confirm_timeout} }
391
+ $MAX_SAME_OUTPUT = if ($env:MAX_SAME_OUTPUT) { [int]$env:MAX_SAME_OUTPUT } else { ${params.max_same_output} }
392
+ $MAX_DIFF_LINES = if ($env:MAX_DIFF_LINES) { [int]$env:MAX_DIFF_LINES } else { ${params.max_diff_lines} }
393
+ $COOLDOWN_SECONDS = if ($env:COOLDOWN_SECONDS) { [int]$env:COOLDOWN_SECONDS } else { ${params.cooldown_seconds} }
394
+ $CLI_COMMAND = if ($env:CLI_COMMAND) { $env:CLI_COMMAND } else { "${params.cli_command}" }
395
+
396
+ if (-not (Test-Path "PROMPT.md")) {
397
+ Write-Host "❌ ERROR: PROMPT.md not found" -ForegroundColor Red
398
+ exit 1
399
+ }
400
+
401
+ Write-Host "🚀 Ralph Loop - Safe Mode" -ForegroundColor Cyan
402
+ Write-Host "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
403
+ Write-Host "⚠️ Safety Limits:"
404
+ Write-Host " • Max iterations: $MAX_ITERS"
405
+ Write-Host " • Max time: $MAX_MINUTES minutes"
406
+ Write-Host " • Confirm every: $CONFIRM_EVERY iteration(s)"
407
+ Write-Host ""
408
+ Write-Host "💡 Emergency stop: New-Item -ItemType File -Name STOP"
409
+ Write-Host ""
410
+ Write-Host "Press Ctrl+C to cancel, or wait 5s to start..."
411
+ Start-Sleep -Seconds 5
412
+
413
+ $ITER = 0
414
+ $START_TIME = Get-Date
415
+ $LAST_OUTPUT_HASH = ""
416
+ $SAME_OUTPUT_COUNT = 0
417
+ $LOG_FILE = "ralph.log"
418
+
419
+ Add-Content -Path $LOG_FILE -Value "[$((Get-Date).ToString('yyyy-MM-dd HH:mm:ss'))] [INFO] Loop started"
420
+
421
+ while ($ITER -lt $MAX_ITERS) {
422
+ $ITER++
423
+ Write-Host ""
424
+ Write-Host "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
425
+ Write-Host "🔄 Iteration $ITER / $MAX_ITERS" -ForegroundColor Yellow
426
+ Write-Host "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
427
+
428
+ if (Test-Path "STOP") {
429
+ Add-Content -Path $LOG_FILE -Value "[$((Get-Date).ToString('yyyy-MM-dd HH:mm:ss'))] [SAFE] STOP file detected"
430
+ Write-Host "🛑 STOP file detected. Emergency exit." -ForegroundColor Red
431
+ exit 0
432
+ }
433
+
434
+ $ELAPSED_MINUTES = ((Get-Date) - $START_TIME).TotalMinutes
435
+ if ($ELAPSED_MINUTES -ge $MAX_MINUTES) {
436
+ Add-Content -Path $LOG_FILE -Value "[$((Get-Date).ToString('yyyy-MM-dd HH:mm:ss'))] [SAFE] Max time reached"
437
+ Write-Host "⏰ Max time reached. Stopping." -ForegroundColor Yellow
438
+ exit 0
439
+ }
440
+
441
+ if ($ITER % $CONFIRM_EVERY -eq 0) {
442
+ Write-Host ""
443
+ Write-Host "⏸️ Confirmation required" -ForegroundColor Yellow
444
+ $response = Read-Host " Continue? [y/N]"
445
+ if ($response -notmatch '^[Yy]$') {
446
+ Add-Content -Path $LOG_FILE -Value "[$((Get-Date).ToString('yyyy-MM-dd HH:mm:ss'))] [SAFE] User declined"
447
+ Write-Host "🛑 User stopped the loop." -ForegroundColor Red
448
+ exit 0
449
+ }
450
+ }
451
+
452
+ Write-Host "🤖 Running: $CLI_COMMAND @PROMPT.md"
453
+ $OUTPUT_FILE = "last_output_$ITER.txt"
454
+ & $CLI_COMMAND "@PROMPT.md" | Tee-Object -FilePath $OUTPUT_FILE
455
+
456
+ $CURRENT_HASH = (Get-FileHash -Path $OUTPUT_FILE -Algorithm MD5).Hash
457
+ if ($CURRENT_HASH -eq $LAST_OUTPUT_HASH) {
458
+ $SAME_OUTPUT_COUNT++
459
+ if ($SAME_OUTPUT_COUNT -ge $MAX_SAME_OUTPUT) {
460
+ Write-Host "⚠️ Output repeated. Likely stuck. Stopping." -ForegroundColor Yellow
461
+ exit 0
462
+ }
463
+ } else {
464
+ $SAME_OUTPUT_COUNT = 0
465
+ }
466
+ $LAST_OUTPUT_HASH = $CURRENT_HASH
467
+
468
+ $content = Get-Content $OUTPUT_FILE -Raw
469
+ if ($content -match "COMPLETION_PROMISE_MET: true" -and $content -match "EXIT_SIGNAL: true") {
470
+ Write-Host "✅ Success!" -ForegroundColor Green
471
+ exit 0
472
+ }
473
+
474
+ Write-Host "😴 Cooldown: \${COOLDOWN_SECONDS}s..."
475
+ Start-Sleep -Seconds $COOLDOWN_SECONDS
476
+ }
477
+
478
+ Write-Host "⏰ Max iterations reached." -ForegroundColor Yellow
479
+ exit 0
480
+ `;
481
+ }
482
+ /**
483
+ * 生成执行指南
484
+ */
485
+ function generateGuide(params, isWindows) {
486
+ const scriptName = isWindows ? "ralph_loop_safe.ps1" : "ralph_loop_safe.sh";
487
+ const scriptCmd = isWindows ? `powershell -ExecutionPolicy Bypass -File ${scriptName}` : `./${scriptName}`;
488
+ const chmodCmd = isWindows ? "" : `chmod +x ${scriptName}\n`;
489
+ return `# 🚀 Ralph Loop Setup Complete!
490
+
491
+ ## 📂 Generated Files
492
+
493
+ \`.ralph/\` directory structure:
494
+ - \`PROMPT.md\` - Loop prompt with goal and rules
495
+ - \`@fix_plan.md\` - Task breakdown (updated by agent)
496
+ - \`PROGRESS.md\` - Iteration log (updated by agent)
497
+ - \`${scriptName}\` - Safe mode script (default)
498
+ - \`ralph_loop.sh\` - Normal mode script (optional, use with caution)
499
+
500
+ ---
501
+
502
+ ## 🎯 Goal
503
+
504
+ ${params.goal}
505
+
506
+ **Completion Promise**: ${params.completion_promise}
507
+
508
+ ---
509
+
510
+ ## 🛡️ Safety Configuration (Mode: ${params.mode})
511
+
512
+ | Parameter | Value | Description |
513
+ |-----------|-------|-------------|
514
+ | Max Iterations | ${params.max_iterations} | Hard limit on loop count |
515
+ | Max Minutes | ${params.max_minutes} | Hard limit on runtime |
516
+ | Confirm Every | ${params.confirm_every} | Require confirmation every N iterations |
517
+ | Confirm Timeout | ${params.confirm_timeout}s | Auto-stop if no response |
518
+ | Max Same Output | ${params.max_same_output} | Stop if output repeats N times |
519
+ | Max Diff Lines | ${params.max_diff_lines} | Stop if changes exceed N lines |
520
+ | Cooldown | ${params.cooldown_seconds}s | Pause between iterations |
521
+
522
+ ---
523
+
524
+ ## 🚀 How to Start
525
+
526
+ ### 1. Create .ralph directory
527
+ \`\`\`bash
528
+ mkdir -p .ralph
529
+ cd .ralph
530
+ \`\`\`
531
+
532
+ ### 2. Copy files
533
+ Copy the generated content below into respective files:
534
+ - \`PROMPT.md\`
535
+ - \`@fix_plan.md\`
536
+ - \`PROGRESS.md\`
537
+ - \`${scriptName}\`
538
+
539
+ ### 3. Make script executable${isWindows ? "" : " (Linux/Mac)"}
540
+ \`\`\`bash
541
+ ${chmodCmd}\`\`\`
542
+
543
+ ### 4. Run the loop
544
+ \`\`\`bash
545
+ ${scriptCmd}
546
+ \`\`\`
547
+
548
+ ---
549
+
550
+ ## 🛑 How to Stop
551
+
552
+ ### Emergency Stop
553
+ \`\`\`bash
554
+ touch .ralph/STOP
555
+ \`\`\`
556
+ The loop will exit immediately on next check.
557
+
558
+ ### Manual Stop
559
+ Press \`Ctrl+C\` in the terminal.
560
+
561
+ ### Timeout Stop
562
+ Don't respond to confirmation prompt (waits ${params.confirm_timeout}s then stops).
563
+
564
+ ---
565
+
566
+ ## ⚙️ How to Adjust Parameters
567
+
568
+ Override via environment variables:
569
+
570
+ \`\`\`bash
571
+ # Example: Increase max iterations to 15
572
+ ${isWindows ? "$env:MAX_ITERS=15" : "MAX_ITERS=15"} ${scriptCmd}
573
+
574
+ # Example: Disable confirmation (not recommended!)
575
+ ${isWindows ? "$env:CONFIRM_EVERY=999" : "CONFIRM_EVERY=999"} ${scriptCmd}
576
+
577
+ # Example: Use different CLI command
578
+ ${isWindows ? "$env:CLI_COMMAND='claude'" : "CLI_COMMAND='claude'"} ${scriptCmd}
579
+ \`\`\`
580
+
581
+ Available overrides:
582
+ - \`MAX_ITERS\`
583
+ - \`MAX_MINUTES\`
584
+ - \`CONFIRM_EVERY\`
585
+ - \`CONFIRM_TIMEOUT\`
586
+ - \`MAX_SAME_OUTPUT\`
587
+ - \`MAX_DIFF_LINES\`
588
+ - \`COOLDOWN_SECONDS\`
589
+ - \`CLI_COMMAND\`
590
+
591
+ ---
592
+
593
+ ## 📊 How to Monitor
594
+
595
+ ### View logs
596
+ \`\`\`bash
597
+ tail -f .ralph/ralph.log
598
+ \`\`\`
599
+
600
+ ### Check progress
601
+ \`\`\`bash
602
+ cat .ralph/PROGRESS.md
603
+ \`\`\`
604
+
605
+ ### Check tasks
606
+ \`\`\`bash
607
+ cat .ralph/@fix_plan.md
608
+ \`\`\`
609
+
610
+ ### View last output
611
+ \`\`\`bash
612
+ cat .ralph/last_output_*.txt
613
+ \`\`\`
614
+
615
+ ---
616
+
617
+ ## 💡 Tips
618
+
619
+ 1. **First iteration is critical**: The agent will identify the correct test command for your project
620
+ 2. **Watch for repetition**: If output repeats ${params.max_same_output} times, loop auto-stops
621
+ 3. **Review large changes**: If changes exceed ${params.max_diff_lines} lines, loop stops for manual review
622
+ 4. **Use git**: Loop works best in git repos (tracks changes, can auto-backup)
623
+ 5. **Start small**: Default limits are conservative - adjust after successful runs
624
+
625
+ ---
626
+
627
+ ## ⚠️ Warnings
628
+
629
+ - **Cost**: Each iteration calls the LLM API. Monitor usage!
630
+ - **Normal mode**: Use only when you're confident. No confirmations = potential runaway.
631
+ - **Test command**: Wrong test command = wasted iterations. Verify in first run.
632
+ - **Background execution**: Not recommended. Always run in foreground with TTY.
633
+
634
+ ---
635
+
636
+ ## 🔗 Integration with Other Tools
637
+
638
+ ### Recommended workflow:
639
+
640
+ 1. **Generate context** (optional but recommended):
641
+ \`\`\`bash
642
+ ${params.cli_command} "使用 init_project_context 生成项目文档"
643
+ \`\`\`
644
+
645
+ 2. **Generate feature spec** (if building new feature):
646
+ \`\`\`bash
647
+ ${params.cli_command} "使用 start_feature 生成功能规格,goal='${params.goal}'"
648
+ \`\`\`
649
+
650
+ 3. **Start Ralph Loop**:
651
+ \`\`\`bash
652
+ cd .ralph
653
+ ${scriptCmd}
654
+ \`\`\`
655
+
656
+ ---
657
+
658
+ *Generated by MCP Probe Kit - start_ralph v1.0*
659
+ `;
660
+ }
661
+ /**
662
+ * start_ralph 主函数
663
+ */
664
+ export async function startRalph(args) {
665
+ try {
666
+ const parsedArgs = parseArgs(args, {
667
+ defaultValues: DEFAULTS,
668
+ primaryField: "goal",
669
+ fieldAliases: {
670
+ goal: ["目标", "任务", "task"],
671
+ mode: ["模式"],
672
+ completion_promise: ["完成条件", "退出条件"],
673
+ test_command: ["测试命令"],
674
+ cli_command: ["命令", "cli"],
675
+ max_iterations: ["最大迭代", "max_iters"],
676
+ max_minutes: ["最大时间", "max_time"],
677
+ confirm_every: ["确认频率"],
678
+ confirm_timeout: ["确认超时"],
679
+ max_same_output: ["最大重复"],
680
+ max_diff_lines: ["最大变更行数"],
681
+ cooldown_seconds: ["冷却时间"],
682
+ },
683
+ });
684
+ const goal = getString(parsedArgs.goal) || "Complete the development task";
685
+ const mode = getString(parsedArgs.mode) || DEFAULTS.mode;
686
+ const completionPromise = getString(parsedArgs.completion_promise) || DEFAULTS.completion_promise;
687
+ const testCommand = getString(parsedArgs.test_command) || DEFAULTS.test_command;
688
+ const cliCommand = getString(parsedArgs.cli_command) || DEFAULTS.cli_command;
689
+ const params = {
690
+ goal,
691
+ mode,
692
+ completion_promise: completionPromise,
693
+ test_command: testCommand,
694
+ cli_command: cliCommand,
695
+ max_iterations: getNumber(parsedArgs.max_iterations) ?? DEFAULTS.max_iterations,
696
+ max_minutes: getNumber(parsedArgs.max_minutes) ?? DEFAULTS.max_minutes,
697
+ confirm_every: getNumber(parsedArgs.confirm_every) ?? DEFAULTS.confirm_every,
698
+ confirm_timeout: getNumber(parsedArgs.confirm_timeout) ?? DEFAULTS.confirm_timeout,
699
+ max_same_output: getNumber(parsedArgs.max_same_output) ?? DEFAULTS.max_same_output,
700
+ max_diff_lines: getNumber(parsedArgs.max_diff_lines) ?? DEFAULTS.max_diff_lines,
701
+ cooldown_seconds: getNumber(parsedArgs.cooldown_seconds) ?? DEFAULTS.cooldown_seconds,
702
+ };
703
+ // 检测操作系统
704
+ const isWindows = process.platform === "win32";
705
+ // 生成所有文件内容
706
+ const promptMd = generatePromptTemplate(params.goal, params.completion_promise, params.test_command);
707
+ const fixPlanMd = generateFixPlanTemplate(params.goal);
708
+ const progressMd = generateProgressTemplate();
709
+ const safeScript = isWindows
710
+ ? generateSafeScriptWindows(params)
711
+ : generateSafeScript(params);
712
+ const normalScript = generateNormalScript(params);
713
+ const guide = generateGuide(params, isWindows);
714
+ // 组装输出
715
+ const scriptExt = isWindows ? "ps1" : "sh";
716
+ const output = `${guide}
717
+
718
+ ---
719
+
720
+ ## 📄 File Contents
721
+
722
+ ### 1. PROMPT.md
723
+ \`\`\`markdown
724
+ ${promptMd}
725
+ \`\`\`
726
+
727
+ ---
728
+
729
+ ### 2. @fix_plan.md
730
+ \`\`\`markdown
731
+ ${fixPlanMd}
732
+ \`\`\`
733
+
734
+ ---
735
+
736
+ ### 3. PROGRESS.md
737
+ \`\`\`markdown
738
+ ${progressMd}
739
+ \`\`\`
740
+
741
+ ---
742
+
743
+ ### 4. ralph_loop_safe.${scriptExt} (Safe Mode - Recommended)
744
+ \`\`\`${isWindows ? 'powershell' : 'bash'}
745
+ ${safeScript}
746
+ \`\`\`
747
+
748
+ ---
749
+
750
+ ### 5. ralph_loop.sh (Normal Mode - Use with Caution)
751
+ \`\`\`bash
752
+ ${normalScript}
753
+ \`\`\`
754
+
755
+ ---
756
+
757
+ ## ✅ Next Steps
758
+
759
+ 1. Create \`.ralph/\` directory
760
+ 2. Copy each file content above into respective files
761
+ 3. Make scripts executable (if on Linux/Mac)
762
+ 4. Review PROMPT.md and adjust if needed
763
+ 5. Run \`ralph_loop_safe.${scriptExt}\`
764
+ 6. Monitor progress and logs
765
+
766
+ **Happy coding! 🚀**
767
+ `;
768
+ return {
769
+ content: [{ type: "text", text: output }],
770
+ };
771
+ }
772
+ catch (error) {
773
+ const errorMsg = error instanceof Error ? error.message : String(error);
774
+ return {
775
+ content: [{ type: "text", text: `❌ start_ralph 执行失败: ${errorMsg}` }],
776
+ isError: true,
777
+ };
778
+ }
779
+ }