문제는 AI가 자기가 쓴 코드를 스스로 검사하면 자기 빈틈을 못 본다는 것이었습니다. 원래는 Claude Code(앤트로픽이 만든, 터미널에서 코드를 대신 써 주는 AI 도구)가 자기 코드를 스스로 QA(품질 검사)했습니다. 사람이 자기 글의 오타를 잘 못 찾듯, AI도 자기가 쓴 코드의 빈틈은 스스로 보기 어렵습니다. 그래서 OpenAI가 만든 다른 코딩 AI인 Codex를 두 번째 검사자로 붙였습니다. 이제 AI가 쓴 코드는 서로 다른 두 AI가 번갈아 검사합니다. 한쪽의 사각지대를 다른 쪽이 대신 잡아냅니다. 이 글은 그 구조를 내 하네스(harness, AI가 '다 했다'고 거짓말 못 하게 증거를 강제하는 감시 장치) 안에 어떻게 넣었는지 정리한 기록입니다.
Claude는 이 프로젝트만의 규칙을 잘 압니다. 검사하는 것은 세 가지입니다. '이건 절대 하지 말라'고 정해둔 금지 규칙, 프로젝트마다 다른 코드 패턴과 작성 스타일, 자료형(타입)이 서로 어긋나지 않는지입니다. 프로젝트의 맥락을 깊이 이해하는 것이 강점입니다.
Codex는 같은 코드를 다른 관점에서 봅니다. Claude가 놓친 패턴, 보안 허점, 드물게만 터지는 예외 상황(엣지 케이스)을 잡아냅니다. 특히 적대 리뷰(adversarial-review, 일부러 약점을 찾아 공격하듯 살펴보는 검토)로 숨은 결함을 파고듭니다.
codex review --uncommitted 명령을 자동으로 돌립니다. 아직 저장(커밋)하지 않은 코드를 Codex가 검사하라는 명령입니다. 검사에서 찾은 결함에는 심각한 순서로 등급이 붙습니다. 가장 심각한 등급이 0건이면 통과로 판정하고 그 증거 파일을 남깁니다. 아래 상자는 이 검사를 돌리는 스크립트 이름과 판정 규칙입니다. 앞이 가장 심각한 등급의 이름이고, 뒤가 통과 판정의 이름입니다.codex-review-gate.sh · CRITICAL 0 → PASSdecision: "block" (차단 결정)이면 Claude는 답변을 멈추지 못하고 문제를 계속 고쳐야 합니다. 통과 결정이면 답변이 그대로 끝납니다. 아래 상자가 이 검문을 맡는 훅 스크립트입니다.stop-review-gate-hook.mjs.qa-cycle-passed + .codex-review-passed 이 두 개의 통과 증거 파일이 모두 있어야만 코드를 서버에 올릴(push) 수 있습니다. 앞 파일은 품질 검사(QA)를 통과했다는 표시이고, 뒤 파일은 Codex 리뷰를 통과했다는 표시입니다. 하나라도 없으면 올리기 명령이 종료 코드 2로 실패합니다. 아래 상자에 적힌 무조건 차단이 바로 그것입니다.exit 2 — HARD BLOCKcode-quality-check.shno-localstorage.shscaffold-violation-check.shcodex-review-gate.sh → .codex-review-passeduser-proxy agent hookfailure-counter.sh (1/3, 2/3, 3/3→RESCUE)error-fixer agent hookstop-review-gate-hook.mjs → ALLOW or BLOCKself-improve-trigger.sh.qa-cycle-passed.codex-review-passed코드에 오류가 났을 때 고치는 순서를 3단계에서 4단계로 늘렸습니다. 새로 넣은 3번째 단계에서는 문제를 통째로 Codex(OpenAI의 코딩 AI, GPT-5.4 모델)에게 넘깁니다. 서로 다른 AI는 문제를 푸는 방식도 다릅니다. 그래서 앞 단계에서 막혔던 부분을 새로운 방법으로 풀어낼 수 있습니다.
네 단계를 모두 시도해도 실패하면, 텔레그램 메시지로 사용자에게 알려 직접 판단을 맡깁니다.
| 상황 | Review Gate | Stop Gate | Push Gate | 강제 수준 |
|---|---|---|---|---|
| 직접 처리 (하위 작업 위임 Task 사용) | O | O | O | 3단계 모두 강제 |
| /team | O | O | O | 3단계 모두 강제 |
| /manager | O | O | O | 3단계 모두 강제 |
| 직접 처리 (하위 작업 위임 Task 안 씀) | X | O | 차단* | Stop 검문소만 |
| slash command | 불확실 | O | 불확실 | Stop 검문소만 확실 |
* 하위 작업(Task)을 쓰지 않으면 아래 이름의 Codex 리뷰 통과 증거 파일이 만들어지지 않습니다. 그러면 코드를 서버에 올리는(push) 길이 영구히 막힙니다. 이때는 /codex:review 명령을 직접 실행해 검사를 통과시켜야 합니다. 만들어지지 않는 파일: .codex-review-passed
HARD SOFT| Hook | 차단 방식 (exit 2는 종료 코드 2로 명령을 실패시켜 막는다는 뜻) | 분류 (무조건 차단 / 권고) |
|---|---|---|
qa-gate-before-push.sh .qa-cycle-passed |
exit 2 | HARD |
qa-gate-before-push.sh .codex-review-passed |
exit 2 | HARD |
stop-review-gate-hook.mjs |
decision: "block" |
HARD |
scaffold-violation-check.sh |
NEVER DO 라고 표시해 둔 '절대 금지' 패턴이 코드에 보이면 차단 |
HARD |
no-env-commit.sh |
exit 2 | HARD |
failure-counter.sh |
3번 실패하면 codex:rescue(막힌 작업을 Codex에 통째로 넘기는 명령)를 쓰라고 안내만 함 (막지는 않음) | SOFT |
codex-review-gate.sh |
통과 증거 파일만 만들고 막지는 않음 | SOFT |
| agent hook prompts | 말로 된 지시(프롬프트)라 지킬지는 Claude의 판단에 맡김 | SOFT |