AI 에이전트 TDD 루프, 실패 테스트부터 고치게 하려면

AI 에이전트 TDD 루프는 “코드부터 고치고 테스트는 나중에”가 아니라 실패하는 테스트(red) → 최소 수정으로 통과(green) → 정리(refactor) 순서를 프롬프트·Skill·Rule에 고정하는 방식입니다. 가격·플랜·사용 후기는 다루지 않습니다.

이 글은 특정 IDE 전용 버튼 설명이 아닙니다. 실패 로그를 어떻게 넘기고, 한 사이클을 언제 끝낼지, 무한 수정 루프를 어떻게 끊는지만 정리합니다.

실패 로그를 어떻게 넘기나?

한 줄 답: 에이전트에게 “전체 스위트 돌려 보고 알아서 고치라”보다 이미 실패한 명령의 stdout/stderr·실패 테스트 이름·관련 파일을 한 덩어리로 넘기고, 그 실패만 고치게 합니다.

넘길 최소 묶음:

항목왜 필요한가
재현 명령npm test -- path/to/spec, pytest -k name, cargo test foo처럼 그대로 다시 실행할 수 있어야 함
실패 출력assertion·스택·exit code. “실패했다” 한 줄만 주면 추측이 늘어남
범위고칠 파일·테스트 경로. 레포 전체를 열어 두지 않음
비목표“다른 flaky는 건드리지 말 것”, “새 의존성 추가 금지” 같은 하지 말 것

실무 전달 패턴:

  1. 로컬에서 실패를 먼저 재현한 뒤, 터미널 출력을 그대로 붙이거나 로그 파일을 @로 첨부합니다.
  2. 프롬프트 첫머리에 목표 테스트 이름과 성공 시 재실행 명령을 적습니다.
  3. “관련 없어 보이는 테스트 실패는 보고만 하고 고치지 말 것”을 명시합니다.
  4. 가능하면 Skill/SKILL.md에 “항상 실패 로그 → 최소 패치 → 같은 명령 재실행” 순서를 절차로 둡니다. 짧은 규범(“테스트 없이 done 금지”)은 Rule에 둡니다.

최소 프롬프트 뼈대:

Failing command (re-run exactly):
  <paste command>

Output:
  <paste failing stdout/stderr>

Scope: only make <test-name> pass.
Do not change unrelated tests or add dependencies.
Done when: the same command exits 0.

로그가 길면 첫 assertion·마지막 스택 프레임·파일:라인만 남기고 중간 노이즈를 잘라도 됩니다. 다만 재현 명령과 exit 조건은 지우지 않습니다.

한 사이클 성공 조건은?

한 줄 답: 한 사이클은 지정한 실패 테스트(들)가 같은 명령으로 통과하고, 합의된 범위 밖 변경이 없으며, 필요 시에만 작은 refactor까지 갔을 때 끝입니다. “뭔가 고쳤다”는 성공이 아닙니다.

사이클 정의(에이전트용):

단계에이전트가 해야 할 일완료 신호
red실패 로그·명령을 확인하고, 실패가 재현됨을 전제로 원인 가설 1~2개만 세움“이 테스트가 왜 깨지는지”를 한 문장으로 적음
green최소 패치로 해당 테스트만 통과같은 재현 명령 exit 0
refactor동작 유지한 채 중복·이름만 정리(선택)같은 명령 재통과 + 범위 밖 파일 미터치

성공 조건 체크리스트:

  1. 재현 명령이 greened — 사용자가 준 그 명령(또는 Skill에 고정한 동일 명령)이 성공.
  2. 스코프 준수 — diff가 합의 경로·테스트 주변으로 한정.
  3. 설명 가능 — “무엇을 바꿨고, 왜 그 실패가 사라졌는지”를 짧게 남김.
  4. 다음 사이클 분리 — 새 실패·새 기능은 새 red로 넘김. 한 턴에 몰아넣지 않음.

Skill에 넣을 완료 정의 예:

## Done when
- Re-run the exact failing command; exit code 0.
- Diff touches only files needed for that failure.
- Report: root cause (1–2 sentences) + files changed.
- If still failing after N attempts, stop and ask (see stop rules).

green 전에 refactor하지 않기, 테스트 출력을 바꾸거나 skip으로 “통과” 만들지 않기를 Rule/Skill에 같이 적어두면 한 사이클 의미가 흐려지지 않습니다.

무한 루프를 어떻게 끊나?

한 줄 답: 시도 횟수·동일 에러 반복·스코프 이탈에 하드 스톱을 걸고, stop 훅·loop_limit·프롬프트의 “N회 후 사람 호출”로 자동 이어가기를 막습니다.

끊는 신호(하나라도 해당하면 중단):

신호조치
같은 실패 출력·같은 파일 수정이 N회(예: 3) 반복중단 후 로그·가설을 사람에게 넘김
패치 후 새 실패가 연쇄로 늘고 원래 실패는 남음롤백·스코프 축소, 새 사이클 금지
테스트 skip·assertion 삭제·타임아웃만 늘리기금지 목록으로 즉시 중단
재현 명령이 바뀜(다른 스위트·다른 플래그)“성공”으로 치지 않고 재확인 요청

프롬프트/Skill 스톱 규칙 예:

Stop rules:
- Max 3 patch→re-test attempts for this failure.
- If the error signature is unchanged after 2 attempts, stop and summarize.
- Never mark done by skipping tests or deleting assertions.
- Do not start a new feature while this red is open.

도구 쪽 보조:

  • Cursor hooks의 stop / subagentStop에 loop_limit을 두면 자동 follow-up이 무한히 이어지는 것을 제한할 수 있습니다(공식 Hooks 문서).
  • CI·로컬 스크립트에서 단일 실패 명령만 에이전트 입력으로 넘기고, full suite는 사람·파이프라인이 돌리게 역할을 나눕니다.

무한 루프의 흔한 원인은 “실패 로그 없이 추측 수정”과 “성공 조건이 ‘뭔가 고침’으로 흐림”입니다. 앞 두 절의 로그 묶음과 done when을 먼저 고정한 뒤 스톱 횟수를 걸면 됩니다.

마무리

AI 에이전트 TDD 루프의 핵심은 red→green→refactor를 말이 아니라 입력(실패 로그)·완료 조건·중단 규칙으로 고정하는 것입니다. 실패 명령을 그대로 넘기고, 같은 명령 exit 0을 한 사이클 성공으로 두며, N회·동일 시그니처·skip 금지로 무한 수정을 끊으면 됩니다. 절차는 Skill, 짧은 금지 규범은 Rule에 두는 편이 유지보수에 유리합니다.

출처