
드디어 말할 수 있게 되었습니다: harness-starter-kit은 hidden-oracle A/B 테스트에서 성공했습니다
요약
harness-starter-kit이 hidden-oracle A/B 테스트를 통해 코딩 에이전트의 성능 향상을 입증했습니다. 검증 코드를 숨긴 상태에서도 에이전트가 저장소 컨벤션을 준수하며 태스크를 성공적으로 수행함을 확인했습니다.
핵심 포인트
- harness-starter-kit은 에이전트의 행동에 실질적인 영향을 미침
- hidden-oracle 테스트를 통해 에이전트의 컨벤션 준수 능력 검증
- 검증 코드를 숨김으로써 에이전트의 역산 추측을 방지하고 정확한 측정 가능
- A/B 테스트 결과, harness 사용 시 성공률이 비약적으로 상승함
안녕하세요. 한국 출신의 주니어 개발자입니다.
일본어는 아직 번역 도구의 도움을 받으며 작성하고 있으므로, 부자연스러운 표현이 있더라도 너그럽게 봐주시면 감사하겠습니다.
이것은 harness-starter-kit 시리즈의 제8회입니다.
지금까지의 기사에서는 상당히 신중하게 써왔습니다.
너무 이른 단계에서,
harness에 의해 agent가 강해졌음을 증명할 수 있다.
라고 말하고 싶지 않았기 때문입니다.
당시에는 아직 evidence(증거)가 충분하지 않았습니다.
말할 수 있었던 것은 기껏해야 다음과 같은 것들이었습니다.
- harness는 규칙을 repo(저장소) 안에 남겨둘 수 있다
- harness는 에러를 더 빨리 표면화시킨다
- harness는 PR 내의 agent work를 리뷰하기 쉽게 만든다
- benchmark runner(벤치마크 러너)를 통해 측정 그 자체를 재현 가능하게 만들기 시작했다
하지만 이번에는 조금 더 앞으로 나아갈 수 있을 것이라고 생각합니다.
물론,
harness에 의해 모든 coding agent가 모든 태스크에서 강해진다.
라고는 아직 말할 수 없습니다.
하지만 지금이라면 조금 더 책임감을 가지고 이렇게 말할 수 있습니다.
repository convention(저장소 컨벤션)을 지킬 필요가 있는 태스크에서, harness-starter-kit은 명확한 효과가 있다.
이번에 hidden-oracle A/B 테스트를 실시했습니다.
결과는 다음과 같습니다.
| Target | Harness | Runs | Successes | Wrong-file edits | Timeouts |
|---|---|---|---|---|---|
flask-no-harness | No | 12 | 0 | 11 | 3 |
flask-yes-harness | Yes | 12 | 11 | 0 | 0 |
이 결과를 보고 처음으로 이렇게 느꼈습니다.
harness-starter-kit은 단순히 "어쩐지 편리함"을 주는 것만이 아니다.
실제로 agent의 행동에 영향을 주기 시작하고 있다.
이전에는 visible oracle 테스트를 수행했습니다.
visible oracle이란,
검증 코드가 target repo 안에 있으며, agent로부터 보이는 상태이다
라는 의미입니다.
이 방법 자체가 틀린 것은 아닙니다.
오히려 다음과 같은 사항을 확인하는 데는 매우 유효합니다.
- benchmark runner가 정상적으로 repo를 clone 할 수 있는가
- task spec(태스크 명세)이 올바르게 작성되었는가
- verification command(검증 명령)가 안정적으로 작동하는가
- scoring logic(채점 로직)에 버그가 없는가
- file boundary violation(파일 경계 위반)을 검출할 수 있는가
하지만 harness 자체의 유효성을 보여주고 싶을 경우, visible oracle에는 문제가 있습니다.
no-harness의 agent도 oracle code를 읽을 수 있기 때문입니다.
즉, repo 안에 convention이 없더라도, agent는 테스트 코드를 통해 역산하여,
- endpoint는 어떤 이름이어야 하는가
- response shape은 어떠해야 하는가
- error code는 무엇이어야 하는가
- 문서에는 무엇을 적어야 하는가
와 같은 것들을 추측해 버릴 수 있습니다.
그렇게 되면 no-harness 측의 성적이 필요 이상으로 높게 나올 가능성이 있습니다.
그래서 이번에는 hidden oracle으로 전환했습니다.
hidden oracle이란,
실제 검증 코드를 target repo 안에 두지 않고, benchmark runner 측에 둔다
라는 방식입니다.
agent가 Flask repo를 편집하는 동안, 최종적인 채점 로직은 보이지 않습니다.
agent가 의지할 수 있는 것은 다음의 것들뿐입니다.
- prompt
- repo 내의 코드
- repo 내의 문서
- AGENTS.md
- conventions
- check script
이것은 제가 정말로 측정하고 싶었던 것에 가깝습니다.
task가 repo-local convention의 이해를 필요로 할 때, harness는 agent가 올바르게 작업하는 데 도움이 되는가?
이번에는 두 개의 Flask repo를 준비했습니다.
하나는,
flask-no-harness
다른 하나는,
flask-yes-harness
입니다.
두 repo의 기본적인 앱 구성은 유사합니다.
하지만, flask-yes-harness에는 harness 정보가 포함되어 있습니다.
- AGENTS.md
- coding conventions (코딩 컨벤션)
- domain glossary (도메인 용어집)
- decision records (결정 기록)
- check_harness.py
- 문서 배치 규칙
- benchmark companion docs (벤치마크 컴패니언 문서) 규칙
- sandbox (샌드박스)에서 의존성 설치에 실패했을 때, 무한히 재시도하지 않는 규칙
이번에 준비한 task (태스크)는 4개입니다.
- stock risk report API
- supplier readiness API
- bundle quote API
- reservation preview API
각각의 task를 no-harness와 yes-harness 모두에서 각각 3회씩 실행했습니다.
총 24회의 live Codex run (실행)입니다.
Codex 설정은 다음과 같습니다.
CODEX_EXEC_ARGS='-c model_reasoning_effort=medium -c service_tier=priority'
즉, reasoning effort (추론 노력)는 medium (중간)이며, service tier (서비스 티어)는 priority (우선순위)입니다.
이번 scoring (점수 산정)은 pytest (파이테스트)만 보고 판단하는 것이 아닙니다.
1회의 run이 성공으로 판정되려면 다음 조건을 모두 충족해야 합니다.
- agent (에이전트)가 정상 종료될 것
git diff --check를 통과할 것- pytest를 통과할 것
- hidden oracle (히든 오라클)을 통과할 것
- wrong-file edits (잘못된 파일 수정)가 없을 것
- forbidden-file edits (금지된 파일 수정)가 없을 것
이 부분이 매우 중요합니다.
최근 저는 점점 이렇게 느끼고 있습니다.
실제 프로젝트에서 "작동하는 것"은 최소 조건에 불과하다.
그보다 더 중요한 것은, repo (레포지토리)의 방식(way)을 따르고 있느냐 하는 것입니다.
예를 들어 이번 task에서는 편집해도 좋은 범위가 다음과 같았습니다.
app/**
tests/**
docs/**
하지만 다음과 같은 파일은 편집해서는 안 됩니다.
README.md
requirements.txt
benchmarks/**
...
결과는 상당히 명확했습니다.
flask-no-harness는 단순히 기능을 올바르게 구현하지 못한 것뿐만이 아니었습니다.
상당한 빈도로 편집해서는 안 되는 곳까지 변경하고 있었습니다.
반면 flask-yes-harness는 기능을 올바르게 구현하기 쉬웠을 뿐만 아니라, 파일 경계(file boundary)도 더 잘 지켰습니다.
flask-no-harness가 실패한 이유는 Codex가 Flask를 작성할 줄 몰라서가 아닙니다.
더 정확히 말하면, 이 repo가 무엇을 요구하는지 알지 못했기 때문입니다.
그 결과, agent는 추측을 하게 됩니다.
예를 들어,
- endpoint (엔드포인트) 이름을 틀림
- response shape (응답 형태)를 틀림
- supplier map (공급업체 맵)을 틀림
- safety stock (안전 재고) 규칙을 틀림
- 문서 배치 위치를 틀림
- README를 덤으로 변경해 버림
과 같은 실패가 발생했습니다.
이것들은 실제 프로젝트에서 흔히 발생하는 agent의 문제와 매우 흡사합니다.
agent가 코드를 전혀 작성하지 못하는 것이 아닙니다.
단지, repo-local context (레포지토리 로컬 컨텍스트)가 부족한 것입니다.
그리고 그 context가 인간의 머릿속에만 존재한다면, agent는 추측할 수밖에 없습니다.
flask-yes-harness가 성공한 이유도 명확합니다.
harness가 모델을 갑자기 똑똑하게 만든 것이 아닙니다.
인간의 습관 속에 흩어져 있던 정보를, agent가 읽고 확인할 수 있는 repo 내의 정보로 바꾼 것이 큽니다.
예를 들어,
- API 명명 규칙 (naming convention)은 어디에 있는가
- 도메인 용어 (domain term)는 어떻게 해석해야 하는가
- 컴패니언 문서 (companion docs)는 어디에 작성해야 하는가
- 어떤 파일을 부주의하게 변경해서는 안 되는가
- 체크 명령 (check command)은 어떻게 실행해야 하는가
- 샌드박스 (sandbox) 내에서 의존성 설치에 실패했을 때, 무한히 재시도하지 말 것
이러한 것들은 언뜻 보기에는 특별한 마법처럼 보이지 않습니다.
하지만 코딩 에이전트 (coding agent)에게는 매우 중요합니다.
왜냐하면, 에이전트는 새로운 태스크 (task)를 시작할 때마다 거의 "방금 프로젝트에 합류한 사람"과 같은 상태이기 때문입니다.
레포 (repo)가 아무것도 알려주지 않는다면, 에이전트는 일반적인 경험만으로 작업할 수밖에 없습니다.
하지만 실제 프로젝트에서 가장 실패하기 쉬운 부분은 일반론이 아닙니다.
그 프로젝트 고유의 컨벤션 (convention)입니다.
이번 테스트를 통해 harness-starter-kit의 강점을 더욱 구체적으로 이해할 수 있었습니다.
첫째, 반복해서 설명하는 수고를 줄일 수 있습니다.
이전에는 새로운 세션 (session)을 시작할 때마다 에이전트에게 매번 이렇게 전달해야 했습니다.
README는 변경하지 마.
먼저 테스트를 실행해.
문서는 docs/decisions에 둬.
requirements.txt는 마음대로 변경하지 마.
이 프로젝트의 API 응답 (API response)은 이렇게 작성해.
지금은 이러한 정보들을 레포 안에 남겨둘 수 있습니다.
둘째, 에이전트의 추측을 줄일 수 있습니다.
컨벤션이 없다면 에이전트는 일반적인 경험에 의존하여 추측합니다.
컨벤션이 있다면, 적어도 에이전트는 먼저 프로젝트의 규칙을 읽을 수 있습니다.
셋째, 에러를 찾기 쉬워집니다.
잘못된 파일 편집 (wrong-file edits), 금지된 파일 편집 (forbidden-file edits), 검증 실패 (verification failure), 타임아웃 (timeout) 등을 기록할 수 있습니다.
이를 통해 "이번 에이전트는 왠지 모르게 미묘했다"라고 감각적으로 말할 필요가 없어집니다.
대신 이렇게 말할 수 있습니다.
변경해서는 안 되는 파일을 편집했다.
hidden oracle을 통과하지 못했다.
타임아웃 (timeout)이 발생했다.
pytest는 통과했지만, 레포 컨트랙트 (repo contract)에는 맞지 않았다.
넷째, 개선 사항을 피드백 루프 (feedback loop)로 만들 수 있습니다.
한 번의 실패는 단순한 실패로 끝나지 않습니다.
그것은 다음과 같은 형태로 바뀔 수 있습니다.
- 실패 메모리 (failure memory)
- 컨벤션 업데이트 (convention update)
- 체크 스크립트 업데이트 (check script update)
- 벤치마크 태스크 업데이트 (benchmark task update)
- 다음 실행 (run)과의 비교 데이터
이것이야말로 제가 처음에 harness를 만들고 싶었던 이유입니다.
이번 결과는 좋았습니다.
하지만 그렇다고 해서 저는 이렇게 말하고 싶지는 않습니다.
harness-starter-kit을 사용하면 모든 코딩 태스크 (coding task)가 좋아질 것이다.
그것은 엄밀하지 않습니다.
이번의 더 정확한 결론은 다음과 같습니다.
레포 로컬 컨벤션 (repo-local convention)을 준수해야 하는 태스크에서 harness-starter-kit은 명확하게 도움이 된다.
즉, harness의 가장 큰 가치는 "일반적인 코딩 능력"을 높이는 것이 아닙니다.
오히려 다음과 같은 능력을 높이는 것입니다.
- 컨트랙트 발견 (contract discovery)
- 파일 경계 준수 (file-boundary discipline)
- 문서 배치 (documentation placement)
- 검증 규율 (validation discipline)
- 프로젝트 특화 일관성 (project-specific consistency)
이것들은 실제 프로젝트에서 매우 중요합니다.
실제 프로젝트는 LeetCode가 아닙니다.
코드는 올바른 위치에 놓여야 합니다.
API는 기존의 약속을 따라야 합니다.
문서는 팀이 찾을 수 있는 곳에 작성해야 합니다.
의존성은 마음대로 추가해서는 안 됩니다.
실패 이유는 나중에 리뷰할 수 있어야 합니다.
이것이 harness의 가치입니다.
8회차까지 써오면서 드디어 이렇게 말할 수 있게 되었습니다.
harness-starter-kit은 hidden-oracle A/B 테스트에서 성공했다.
그 성공의 의미는,
에이전트가 마법처럼 강화되었다
는 것이 아닙니다.
그게 아니라,
repo가 agent에게 더 명확한 operating environment (운영 환경)를 제공할 수 있었다
는 것입니다.
이번에, no-harness는 0/12였습니다.
yes-harness는 11/12였습니다.
wrong-file edits (잘못된 파일 편집)는 11에서 0으로 줄었습니다.
timeouts (시간 초과)는 3에서 0으로 줄었습니다.
저에게 이것은 이제 단순히 "어쩐지 편리하다"는 단계가 아닙니다.
검토 가능한 evidence (증거)입니다.
물론, 다음 단계로서 샘플을 더욱 확장할 필요가 있습니다.
- 더 많은 task (작업)
- 더 많은 repo (저장소)
- 더 많은 framework (프레임워크)
- 더 많은 agent (에이전트)
- 더 많은 repetition (반복)
그럼에도 적어도 지금은, 이전보다 harness-starter-kit에 대한 신뢰가 강해졌습니다.
이것은 만능 도구가 아닙니다.
오히려, repo를 agent가 작업하기 쉬운 환경으로 바꾸기 위한 starter kit (스타터 키트)에 가깝습니다.
만약 당신도 Cursor, Claude Code, Codex, 혹은 다른 coding agent (코딩 에이전트)를 자주 사용하고 있다면, 우선 아주 작은 부분부터 시작해 보는 것이 좋다고 생각합니다.
agent에게 몇 번이고 반복해서 전달하고 있는 규칙을 repo에 작성하기.
잘못 편집되기 쉬운 파일 경계를 명확히 하기.
검증 명령어를 실행 가능한 check (체크)로 만들기.
실패를 기록하기.
그리고, 실제 task outcome (작업 결과)을 사용하여 개선되고 있는지 확인하기.
이번에 저는 마침내 조금 명확한 답을 볼 수 있었습니다.
convention-dependent work (관습 의존적 작업)에 있어서,
harness는 유효합니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기