콘텐츠로 이동

Lab 04: Ralph 루프 구현

중급 마감: 2026-03-31
  • Ralph 루프(반복적 자율 코딩 루프)의 구조 이해 및 구현
  • harness.sh로 AI 코딩 CLI를 비대화형 모드로 제어
  • PROMPT.md + AGENTS.md 작성 원칙 적용
  • Garbage Collection과 Backpressure로 루프 안정성 확보

Ralph 루프는 “Run → Assess → Loop → Progress → Halt” 사이클로 동작하는 자율 코딩 워크플로우다. AI 코딩 CLI를 헤드리스(headless)로 실행하고, 테스트 결과를 피드백으로 삼아 반복한다.

PROMPT.md + AGENTS.md
Claude Code코드 변경
테스트 실행
성공완료
실패GC → AGENTS.md 갱신 → 재시도

효과적인 PROMPT.md는 역할, 제약, 완료 기준을 명확히 정의한다.

# Role
You are an autonomous coding agent. Your task is to make all tests pass
in the `src/` directory without modifying test files.
**IMPORTANT: Read `AGENTS.md` first** — it contains learned patterns
from previous iterations and known failure modes.
# Constraints
- Do NOT modify any file under `tests/`
- Do NOT install new packages without checking `requirements.txt` first
- Write minimal, focused changes — do not refactor unrelated code
- If stuck after 3 attempts on the same error, write your analysis to
`fix_plan.md` and stop
# Completion Criteria
All pytest tests pass. Run `pytest tests/ -q` to verify.
Write a brief summary to `DONE.md` when complete.
# Working Notes
- Check `AGENTS.md` for learned patterns and anti-patterns
- Check `fix_plan.md` for prior analysis before starting
- Use `git diff` to review your changes before each commit
- Update `AGENTS.md` with new learnings after each attempt

루프가 반복되면서 학습한 패턴과 실패 원인을 기록하는 파일이다. 에이전트는 매 이터레이션 시작 시 이 파일을 읽고, 동일한 실수를 반복하지 않는다.

AGENTS.md
## 학습한 패턴 (Learned Patterns)
- (루프 실행 후 에이전트가 추가)
## 금지 패턴 (Anti-Patterns)
- tests/ 디렉터리의 파일을 수정하지 말 것
- 새 패키지 설치 전 requirements.txt 확인할 것
## 진행 상태 (Progress)
- [ ] test_divide_normal — ?
- [ ] test_divide_zero — ?
- [ ] test_fibonacci — ?
#!/usr/bin/env bash
set -euo pipefail
# 설정
MAX_ITER=${MAX_ITER:-10}
SLEEP_SEC=${SLEEP_SEC:-5}
PROMPT_FILE="PROMPT.md"
LOG_FILE="harness.log"
PASS_MARKER="DONE.md"
AI_CLI="${AI_CLI:-claude}" # 도구 선택: claude, gemini, codex
# --- Git 초기화 (Garbage Collection 전제조건) ---
if [ ! -d .git ]; then
git init
git add -A
git commit -m "initial: harness 시작점"
echo "[harness] Git 저장소 초기화 완료"
fi
iter=0
echo "[harness] Ralph 루프 시작 (최대 ${MAX_ITER}회, 도구: ${AI_CLI})" | tee "$LOG_FILE"
while [ $iter -lt $MAX_ITER ]; do
iter=$((iter + 1))
echo "[harness] === 이터레이션 ${iter}/${MAX_ITER} ===" | tee -a "$LOG_FILE"
# --- Backpressure: 토큰 소비 속도 조절 ---
if [ $iter -gt 1 ]; then
echo "[harness] Backpressure 대기 ${SLEEP_SEC}초..." | tee -a "$LOG_FILE"
sleep "$SLEEP_SEC"
fi
# --- AI 코딩 CLI 헤드리스 실행 ---
case "$AI_CLI" in
claude)
claude --print --no-color --dangerously-skip-permissions \
"$(cat "$PROMPT_FILE")" 2>&1 | tee -a "$LOG_FILE" ;;
gemini)
cat "$PROMPT_FILE" | gemini 2>&1 | tee -a "$LOG_FILE" ;;
codex)
codex --approval-mode full-auto \
"$(cat "$PROMPT_FILE")" 2>&1 | tee -a "$LOG_FILE" ;;
*)
echo "[harness] 지원하지 않는 도구: $AI_CLI" | tee -a "$LOG_FILE"
exit 1 ;;
esac
# --- 완료 조건 확인 ---
if [ -f "$PASS_MARKER" ]; then
echo "[harness] 완료 마커 감지 — 루프 종료" | tee -a "$LOG_FILE"
exit 0
fi
# --- 테스트 실행 및 결과 확인 ---
if python -m pytest tests/ -q --tb=no 2>/dev/null; then
echo "[harness] 모든 테스트 통과 — 루프 종료" | tee -a "$LOG_FILE"
exit 0
fi
# --- Garbage Collection: 실패한 코드 변경 롤백 ---
# AGENTS.md의 학습 내용은 보존
if [ -f AGENTS.md ]; then
cp AGENTS.md /tmp/AGENTS.md.bak
fi
echo "[harness] GC: 실패한 변경 롤백 (git checkout .)" | tee -a "$LOG_FILE"
git checkout .
if [ -f /tmp/AGENTS.md.bak ]; then
cp /tmp/AGENTS.md.bak AGENTS.md
fi
echo "[harness] 테스트 미통과 — 다음 이터레이션 진행" | tee -a "$LOG_FILE"
done
echo "[harness] 최대 이터레이션 도달 — 실패" | tee -a "$LOG_FILE"
exit 1

Backpressure는 루프가 API를 과도하게 호출하거나 무한루프에 빠지는 것을 방지한다. 세 가지 레이어로 구현한다.

Terminal window
# harness.sh에 추가할 Backpressure 강화 로직
# 1. 지수 백오프: 실패 횟수에 비례해 대기 시간 증가
consecutive_failures=0
backoff_base=5
# 실패 시
consecutive_failures=$((consecutive_failures + 1))
sleep_time=$((backoff_base * consecutive_failures))
echo "[harness] 백오프 대기 ${sleep_time}초..." | tee -a "$LOG_FILE"
sleep "$sleep_time"
# 성공 시 초기화
consecutive_failures=0
# backpressure.py — Python 보조 스크립트
import time
import json
from pathlib import Path
def check_progress(log_file: str = "harness.log") -> dict:
"""최근 N개 이터레이션의 진행 상태를 분석한다."""
lines = Path(log_file).read_text().splitlines()
iterations = [l for l in lines if "이터레이션" in l]
return {
"total_iterations": len(iterations),
"last_10_lines": lines[-10:],
"is_stalled": _detect_stall(lines)
}
def _detect_stall(lines: list[str], window: int = 20) -> bool:
"""동일한 에러 패턴이 반복되면 stall로 판단한다."""
recent = lines[-window:]
error_lines = [l for l in recent if "ERROR" in l or "FAILED" in l]
if len(error_lines) < 3:
return False
# 동일 오류 3번 이상 반복 시 stall
return len(set(error_lines)) == 1

다음 버그가 있는 코드를 Ralph 루프로 수정하도록 한다.

# src/calculator.py (버그 포함)
def divide(a: float, b: float) -> float:
return a / b # ZeroDivisionError 미처리
def fibonacci(n: int) -> int:
if n <= 0:
return 0
elif n == 1:
return 1
return fibonacci(n - 1) + fibonacci(n - 2) # n=2 케이스 누락 없음, 성능 문제
# tests/test_calculator.py (수정 금지)
import pytest
from src.calculator import divide, fibonacci
def test_divide_normal():
assert divide(10, 2) == 5.0
def test_divide_zero():
with pytest.raises(ValueError, match="0으로 나눌 수 없습니다"):
divide(10, 0)
def test_fibonacci():
assert fibonacci(10) == 55
assert fibonacci(0) == 0
  1. 실습 디렉터리 구조 생성 (src/, tests/, PROMPT.md, AGENTS.md)
  2. harness.sh에 실행 권한 부여: chmod +x harness.sh
  3. 루프 실행: MAX_ITER=5 bash harness.sh
  4. harness.log에서 이터레이션 흐름 확인
  5. GC 동작 확인: git log --oneline으로 롤백 여부 확인
  6. AGENTS.md에 학습 내용이 누적되었는지 확인
  7. 완료 후 DONE.md와 수정된 src/calculator.py 검토

assignments/lab-04/[학번]/에 PR:

  • PROMPT.md — 역할/제약/완료기준 포함, AGENTS.md 참조 지시
  • AGENTS.md — 루프 실행 후 누적된 학습 기록 (최소 2회 실패 후 성공 과정이 보일 것)
  • harness.sh — Backpressure + Garbage Collection 포함한 완전한 구현
  • backpressure.py — stall 감지 로직
  • harness.log — 실제 실행 로그 (최소 3회 이터레이션)
  • src/calculator.py — Claude가 수정한 최종 버전
  • README.md — 루프가 몇 번 만에 테스트를 통과했는지, GC 동작 확인, stall 발생 여부 기록