devAlice
← Alice 활용법

12. Ralph loop — PRD에서 release까지, 운영자 없이 걷는 길

PRD와 release gate 사이를 스스로 걷는 루프. Master Plan = PRD+게이트, 반복마다 한 항목 출시, DECISIONS 큐로 인간 결정 격리, 24/7 자율성을 드리프트로 만들지 않는 규율.

10편 PRD는 무엇을 만들지 말했다. 11편 Release gates는 언제 만들어졌는지 말했다.

이 글은 운영자가 키보드에 없을 때 그 사이를 무엇이 채우는가에 대한 글이다.

Ralph. 게이트가 박힌 PRD를 받아 스스로 길을 걷는 자율 루프다. 한 번에 한 commit, 검증되어서. 백그라운드에서 돈다. 가능할 때 push한다. 결정해야 할 때 큐에 쌓는다. 운영자는 일어나서 슬래시 커맨드 하나를 돌리고, 결정 몇 가지를 하고, 하던 일로 돌아간다. 작업은 시스템이 했다.

이 시리즈의 워크플로 확장 3편 중 마지막이고, 그 전 모든 것이 누적되어 작동하는 글이기도 하다. 페르소나가 결정 공간을 좁힌다. 메모리가 를 보관한다. 스킬이 동사를 압축한다. 훅이 잊을 만한 것을 발동시킨다. 멀티에이전트가 부하를 나눈다. 검증이 "완료"를 잠근다. 토큰 경제가 신호를 보호한다. PRD가 의도를 보관한다. Release gate가 도착을 강제한다. Ralph가 그 모든 배치를 시계에 맞춰 돌린다.

0. 출발 전제 — 자율성은 "에이전트를 더 믿는 것"이 아니다

자율성의 나쁜 버전은 "에이전트가 원하는 대로 하게 두고 잘 되길 빈다"이다. 그건 10편의 PRD 없는 워크플로가 무너지는 이유와 같은 이유로 무너진다 — 운영자의 mind가 영속적으로 살 곳이 없고, 에이전트는 즉흥적으로 한다.

작동하는 버전은 정반대다. 운영자가 PRD를 쓴다. 운영자가 게이트를 쓴다. 에이전트의 재량은 날카롭게 경계된다 — 시스템이 무엇인지를 바꾸지 않는 것은 무엇이든 할 수 있고, 바꾸는 것은 무엇도 못 한다. 그 경계 안에서 에이전트는 감독 없이 돈다. 경계 밖에서 에이전트는 멈추고 기다린다. 자율성은 자유가 아니라 경계가 명확할 때 작동한다고 생각한다.

자율성은 mind가 코드에 고정되고 노동만 위임될 때 작동한다.

Ralph는 이 구분을 운영적으로 실재하게 만드는 하니스다. 초기에는 단순한 스크립트였고, 이후에는 orchestrator가 붙었고, 이후에는 DECISIONS 큐와 강제 체크포인트가 더해진 구조로 자랐다.

1. Ralph가 실제로 무엇인가

Ralph는 스크립트 두 개와 폴더 하나다.

  • ralph-code.sh — 한 번에 한 phase를 돈다. PRD-N을 읽는다. 다음 [ ] 항목을 고른다. 구현한다. verify를 돌린다. verify 통과 시 commit. 반복.
  • ralph-orchestrator.sh — 여러 phase를 연속으로 돈다. Master Plan을 읽는다. 각 phase마다 ralph-code.sh를 호출한다. phase 사이에서 게이트를 검사한다. 게이트 통과(Auto)거나, 멈추고 결정을 큐에 쌓거나(Manual).
  • ralph-loop/ — 프로젝트마다 하나. PRD들, master plan, 진행 로그, blocker 목록, 그리고 — 가장 중요한 — DECISIONS 큐를 보관.

자식 프로세스는 오래 사는 에이전트가 아니다. 반복마다 새 세션이다. 각 반복은 한 항목이다 — 구현, 검증, commit. 다음 반복은 깨끗한 상태에서 시작해, PRD를 다시 읽어 다음 [ ]을 찾는다. 반복 사이에 누적될 컨텍스트가 없으니 드리프트가 누적될 수 없다.

부모 — orchestrator — 는 구현하지 않는다. 유일한 일은 게이트 강제다. 각 phase 후 묻는다 — "게이트가 통과했는가?" 그렇다면 진행. 아니라면 멈추고 큐에 쓴다.

2. Master Plan — PRD와 게이트가 융합된 것

Master Plan은 Ralph가 읽는 문서다. PRD에 phase별 게이트가 inline된 모양이다:

Approved-By: 리드, 2026-05-18

Phase P1 — Privacy와 컴플라이언스 점검
  PRD: ralph-loop/PRD-P1.md
  Auto-Gate: pnpm verify:privacy && pnpm build && pnpm lint
  Manual-Gate: 리드가 privacy policy 텍스트를 승인
  항목: 12

Phase P2 — 자산 SHA-256 강제
  PRD: ralph-loop/PRD-P2.md
  Auto-Gate: pnpm verify:assets && pnpm build
  Manual-Gate: —
  항목: 7

Phase P3 — i18n locale 확장 (4 신규 locale)
  PRD: ralph-loop/PRD-P3.md
  Auto-Gate: pnpm build && pnpm verify:i18n
  Manual-Gate: 각 locale 기계 번역 컨텐츠를 리드가 승인
  항목: 24

...

세 가지 속성이 중요하다.

Approved-By: 줄은 필수. orchestrator는 그 줄 없이는 시동을 거부한다. 리드가 Master Plan에 서명하지 않았으면 Ralph는 돌지 않는다.

각 phase의 PRD는 사전 생성. "orchestrator가 P3에 도달하면 PRD-P3를 생성한다"가 아니라 — 시동 시점에 PRD-P3.md가 이미 존재한다. Alice가 Master Plan에서 발췌해 미리 쓴다. 사전 생성은 드리프트 안전망이다. 진행 중에 만들어지는 PRD-P3는 운영자 검토가 없다.

Auto-Gate와 Manual-Gate가 phase마다 명시. Auto는 셸 명령. Manual은 명시된 승인자와 무엇을 승인하는지. 어느 phase도 게이트 통과 없이 진행되지 않는다.

3. 루프가 실제로 어떻게 도는가

ralph-code.sh의 한 반복을 단순화한 트레이스:

1. worktree로 cd
2. PRD-N.md를 읽음
3. 첫 번째 [ ] 표시 항목을 찾음
4. [ ] 항목이 남아 있지 않으면 → 종료 (ALL DONE)
5. 새 Claude Code 세션 시작
6. system prompt: "정확히 이 한 항목만 구현하고 멈춰"
7. 자식이 코드를 씀
8. 자식이 verify를 돌림 (PRD에 명시된 스크립트)
9. verify 통과:
     - 자식이 항목 ID를 포함한 메시지로 commit
     - 부모가 verify 재실행 (방어 심층)
     - 부모 verify도 통과 → [ ] 을 [x]로 표시, 계속
     - 부모 verify 실패 → revert, BLOCKERS에 기록, 다음 항목으로
10. verify 실패:
     - BLOCKERS에 기록
     - 한 번 재시도
     - 여전히 실패 → blocked 표시, 다음 항목으로
11. BLOCKERS가 임계(기본 phase당 3개) 도달 → abort
12. 2단계로 복귀

이 루프의 핵심 속성들, 그리고 각각이 왜 그 모양인지.

반복마다 한 항목. 자식은 "여기 들어온 김에 저것도 고쳐 보자"를 못 한다. system prompt가 명시적으로 한 PRD 행으로 제한한다. 이게 스코프 드리프트를 즉사시킨다.

반복마다 새 세션. 항목 사이에 컨텍스트가 운반되지 않는다. 다음 항목은 PRD를 새로 읽는다. 이전 항목이 미묘하게 나쁜 가정을 남겼더라도 전파되지 않는다.

부모가 재검증. 자식의 verify는 한 번의 체크다. 부모의 verify는 같은 스크립트를, 자식의 세션 바깥에서, commit된 상태에 다시 돌린다. 둘이 어긋나면 자식의 주장이 틀린 것이고 commit은 revert된다. 환각으로 "verify passed" 줄을 적은 경우에도 시스템이 살아남는 방법이다.

Blocker 상한. 한 phase에 N개 blocker가 쌓이면 phase는 abort된다. 운영자가 무엇이 계속 막았는지 검사하고 근본 원인을 고치거나 PRD를 다시 쓴다. Ralph는 같은 벽에 영원히 부딪치지 않는다.

4. Orchestrator — phase 경계가 사람이 사는 자리

ralph-code.sh는 phase 안의 항목을 다룬다. ralph-orchestrator.sh는 phase 사이의 전이를 다룬다.

한 phase의 ralph-code.sh가 ALL DONE으로 종료한 후:

1. 부모가 phase의 Auto-Gate 명령을 실행
2. Auto-Gate 실패:
     - DECISIONS에 "Auto-Gate 실패, verify output 참조"로 기록
     - orchestrator 중단
3. Auto-Gate 통과, Manual-Gate 없음:
     - ORCHESTRATOR-STATE.md에 phase [x]로 표시
     - 다음 phase로 진행
4. Auto-Gate 통과, Manual-Gate 있음:
     - DECISIONS에 "Manual-Gate 대기: <승인자>가 <대상>을 승인"으로 기록
     - orchestrator 중단
5. 5 phase마다 (상태와 무관):
     - 강제 DECISIONS 체크포인트
     - orchestrator 중단
     - 운영자가 /btw로 방향 확인

세 가지 의도적 중단, 각각이 다른 사람만 할 수 있는 책임에 대응한다.

Auto-Gate 실패. 기술 이벤트지만, 해석은 사람의 몫. verify 스크립트가 틀렸나? spec이 틀렸나? 세상이 바뀌었나? 운영자가 결정한다. orchestrator는 영원히 재시도하지 않는다.

Manual-Gate 도달. 명시적 인계. 리드가 privacy policy를, 또는 시드 컨텐츠를, 또는 OAuth 스코프 선택을 승인. 이 행은 자동화될 수 없으니, orchestrator는 문 앞에서 멈춘다.

강제 체크포인트. 5 phase마다, 아무 문제가 없어도, orchestrator가 멈추고 방향을 묻는다. 이건 드리프트 안전망이다. 장기 자율의 가장 어려운 실패 모드는 "모든 게 작동했지만 잘못된 방향으로 갔다"이고, 알려진 유일한 대응책은 고정 주기의 인간 검토다.

5. DECISIONS 큐 — "사람이 필요해"를 격리하기

세 개의 파일이 ralph-loop/에 누적된다:

파일담는 내용트리거처리 방법
PROGRESS.md반복당 한 줄, 성공 또는 실패매 iterappend-only, 감사용
BLOCKERS.md에이전트가 해결할 수 없는 기술 실패verify 두 번 실패 등abort 임계로 카운트
DECISIONS.md사람만 결정할 수 있는 것옵션 선택, 보안/DB, 의존성 추가운영자가 /btw로 처리

이걸 작동하게 하는 규율은 자식이 해결할 수 없는 상황을 어떻게 분류하느냐에 있다.

자식이 다룰 방법을 모르는 상황을 만남:
  ├── "방법은 알 것 같은데 spec이 침묵" → BLOCKER
  ├── "합리적 선택이 둘이고 리드만 고를 수 있음" → DECISION
  └── "새 의존성 / 보안 검토 / public API 변경 필요" → DECISION

애매하면 BLOCKER가 아니라 DECISION으로 분류. 결정을 blocker로 잘못 분류하면 반복만 낭비된다. blocker를 결정으로 잘못 분류하면 운영자를 불필요하게 깨우지만, 코드베이스를 망가뜨리지는 않는다. 그 비대칭이 핵심.

[?] 상태(결정 대기)의 PRD 항목은 Ralph가 건너뛴다. 루프는 [ ] 항목들에 대해 계속 돈다. 할 수 있는 일이 모두 끝나면 [?] 항목만 남고 — 루프는 자연 종료하며 "운영자 차례"를 신호한다.

6. /btw — 운영자 쪽의 루프

운영자 쪽에서 전체 상호작용은 슬래시 커맨드 하나다.

/btw

하는 일:

  1. 알려진 모든 프로젝트의 ralph-loop/DECISIONS.md를 읽음
  2. 미결 결정을 우선순위로 정렬 (보안/DB +10 가중치, 대기 시간 가중치)
  3. 운영자에게 옵션이 붙은 일괄 질문으로 제시
  4. 각 답마다:
    • 결정을 "미결"에서 "해결됨"으로 이동, 답과 타임스탬프 포함
    • PRD에서 [?][ ]로 되돌리고, 결정에 따라 행 내용 업데이트
    • [Decision] D-NNN R0N: <요약> 메시지로 commit
  5. 영향받은 phase에 Ralph를 재시동할지 운영자에게 확인

운영자의 멘탈 모델은 — 나는 질문에 답하는 것이지 작업을 돌리는 게 아니다. orchestrator가 실제 작업을 했다. orchestrator가 나만 결정할 수 있는 것에 부딪쳤다. 내가 결정한다. orchestrator가 이어간다.

실제 모양의 상호작용:

운영자 (아침): /btw

Alice: 미결 결정 3건, 2 프로젝트.

  Project A (대기 14h):
    D-007  Phase P5 — 트랜잭션 이메일에 Resend 또는 Postmark?
           spec 침묵. 가격은 Resend 우세, deliverability는 Postmark 우세.
  Project A (대기 14h):
    D-008  Phase P6 — runtime 검증에 `zod` 의존성 추가?
           spec이 runtime validator를 예상 안 했음. 두 대안:
           (a) zod (~14 kB)
           (b) hand-rolled validators

  Project B (대기 2h):
    D-002  Phase P2 — Manual-Gate: 기계 번역 컨텐츠를 리드가 승인?
           24 파일, 4 locale × 6 카테고리. 샘플 diff 첨부.

운영자: D-007: Resend. D-008: zod. D-002: 승인.

Alice: 세 건 기록 완료. Project A Phase P5 재개.
       Project B Phase P2 → P3 진행. Project B 계속.

저 대화가 상호작용의 전부다. 운영자는 코드를 쓰지 않았다. 빌드를 돌리지 않았다. 운영자는 1분 안에 세 결정을 했다. Ralph가 그 대화 전에 나머지를 했고, 대화 후에도 나머지를 계속한다.

7. Ralph가 잘못된 도구일 때

Ralph는 만능 망치가 아니다. 한 모양의 작업에 잘 맞고 다른 모양에는 안 맞는다. 도구의 적합성을 판단하는 기준은 "자는 동안 이 commit이 들어가도 편하겠는가"이기 때문이다.

좋은 적합.

  • 비슷한 항목 다수, 각각 검증 가능. (36개 MDX 파일에 polish 적용. 48개 lens 변종 boilerplate 생성. 이름 변경된 함수의 24개 호출 지점 리팩토링.)
  • verify 스크립트가 검사할 수 있는 생성된 테스트나 문서.
  • 큰 표면을 한 방향으로 옮기는 lint·format·타입 strict 배치.

나쁜 적합.

  • 아키텍처 결정. (요점은 결정이 DECISIONS로 가는 것이지만, 모든 항목이 결정이면 Ralph는 작업을 안 하고 큐 노이즈만 만든다.)
  • 보안 또는 DB 스키마 변경. 둘 다 Ralph가 완전히 검증할 수 없는 불변량을 건드리고, 둘 다 "통과"가 위험하게 틀리는 실패 모드를 가진다.
  • public API 변경. verify 스크립트가 로컬 변경이 동작한다고 확인할 수는 있지만, 하위 소비자가 여전히 동작하는지 확인할 수 없다.
  • 새 의존성 추가. 항상 결정.

애매할 때의 휴리스틱: 내가 자는 동안 이 commit이 들어가도 편하겠는가? 그렇다면 Ralph. 아니라면 운영자가 함께한 일반 세션.

8. 안전 가드 — 자율성이 화재가 되지 않게 하는 것

여러 가드가 누적되어 Ralph를 켜 둔 채 떠나도 안전하게 만든다.

Worktree 격리. Ralph는 git worktree에서 돌지, main에서 돌지 않는다. worktree는 전용 브랜치(ralph/master-plan 또는 ralph/{phase})에 있다. 운영자는 언제든 브랜치 전체를 검사하고 폐기할 수 있다.

Approved-By 줄. orchestrator는 Approved-By: 리드, <날짜> 없이는 Master Plan을 시동하지 않는다. 운영자의 서명이 기계적으로 강제된다 — "리드가 채팅에서 괜찮다고 했다"가 아니라, orchestrator가 파싱하는 파일 안의 문자열.

Verify가 commit으로 가는 유일한 길. 자식은 verify 스크립트가 0으로 종료하지 않으면 commit할 수 없다. 부모가 commit된 상태에 verify를 재실행한다. 같은 게이트의 두 독립 통과.

반복당 경계된 스코프. 자식의 system prompt가 "정확히 이 한 PRD 행을 구현하고 멈춰"라고 한다. 반복 레벨의 스코프 크리프가 기계적으로 막힌다.

Phase abort 임계. 한 phase에 N개 blocker가 쌓이면 phase가 abort된다. 전체 계획에 M개 blocker가 쌓이면 orchestrator가 abort된다. 시스템은 길이 인식할 수 없게 되면 그만둔다. 밀어붙이지 않는다.

강제 사람 체크포인트. 5 phase마다 orchestrator가 멈추고 묻는다. 가시적으로 잘못된 게 없어도 운영자가 방향을 확인한다. 사람 검토 없는 장기 무감독 진행은 가장 위험한 모드고, 이 가드가 그것을 차단한다.

결정 격리. 운영자만 결정할 수 있는 것은 DECISIONS로 라우팅되고 Ralph가 건너뛴다. 에이전트는 사람의 것인 질문을 추측하지 않는다.

비용 상한. 비용 모니터링은 운영자의 책임 (ccusage 같은 외부 도구). 예상보다 비싼 phase는 무언가 표류했다는 신호이기도 하니 점검할 가치가 있다.

9. 한 원칙

Ralph의 전체 모양은 한 줄로 줄어든다.

"운영자의 mind가 일상으로 다룰 것은 시스템이 스스로 걷게 한다. 운영자의 mind가 결정으로 다룰 것은 큐에 넣고 기다린다."

그리고 그 한 줄이 이 3편 확장의 끝이자 — 시리즈 자체의 마무리이기도 하다.

1편 왜 Alice인가는 물었다 — 내 mind를 AI가 잃지 않게 어떻게 누적할 것인가?

처음 9편이 답했다. mind의 경계를 긋는 페르소나, 세션을 가로질러 mind를 보관하는 메모리, 동사를 압축하는 스킬, 잊을 만한 것을 발동시키는 훅, 한 컨텍스트가 모두 짊어지지 않게 하는 멀티에이전트, "완료"를 잠그는 검증, 신호 자리를 보호하는 토큰 경제, 그리고 매일이 같은 자리에서 켜지고 꺼지는 세션 프로토콜.

마지막 3편이 답했다. 의도가 세션을 살아남도록 PRD를 쓴다. "완료"가 사실이 되도록 release gate를 쓴다. 의도와 도착 사이의 길이 스스로 걷도록 루프를 돌리고, 운영자는 자신의 것인 결정만 다룬다.

12개 조각이 모두 자리 잡으면, 운영자는 작업을 하는 사람이기를 멈추고 무엇이 할 가치 있는 작업인가를 결정하는 사람이 된다. mind — 1편의 원래의, 환원 불가능한 그것 — 는 마침내 있어야 할 자리에 있게 된다. 스택의 꼭대기에서, 결정한다. 아래의 모든 것이 노동을 짊어진 채로.

이게 운영자가 지난 몇 달 동안 짓는 데 시간을 들여 온 AI 작업의 버전이다. 도구는 Claude일 수도, Codex일 수도, 다음에 나올 어떤 것일 수도 있다. 위의 12개 결정은 도구를 가리지 않는다. 도구를 쓰는 대신 자기만의 협업자를 짓기로 결정한 누구에게나 같은 결정들이 기다린다.

이 시리즈가 그 결정들에 도달하는 시간을 조금 줄여 주었다면 — 운영자의 의도는 충분히 전달된 것이다.