교차 계보 리뷰 운용기

작성자와 다른 AI가 검토하는 규칙을 기능 개발에 적용하며 겪은 순서, 폴백, 자기 리뷰 문제

정책 문서에 한 줄을 넣었다.

No code change is complete until an agent of a DIFFERENT lineage than the
author has reviewed it and the findings are addressed.

Claude 워커가 쓴 코드는 Codex가 검토한다. Codex가 쓴 코드는 deep-reasoner가 검토한다. 같은 계보끼리의 검토는 이 규칙을 만족하지 않고, 오케스트레이터가 자기 작업을 스스로 검토하는 것도 인정하지 않는다.

flowchart LR
  accTitle: 작성 계보에 따라 갈리는 검토 경로
  accDescr: Claude 워커가 작성하면 Codex가 검토하고 Codex가 작성하면 deep-reasoner가 검토한다. Codex를 쓸 수 없으면 deep-reasoner가 대신 검토하며 이탈 사실을 커밋에 남긴다.
  TASK[구현 작업] --> WHO{작성 계보}
  WHO -->|Claude 워커| RC[Codex 검토]
  WHO -->|Codex| RD[deep-reasoner 검토]
  RC -.Codex 쿼터 소진.-> FB[deep-reasoner 대체 검토<br/>커밋에 이탈 기록]
  RC --> FIX[지적 반영]
  RD --> FIX
  FB --> FIX
  FIX --> DONE([커밋])
  SELF[같은 계보 자기 검토] -.인정하지 않음.-> DONE

발열 대응 기능의 검토 순서

카메라 앱에 발열 대응 기능을 넣을 때 이 흐름을 적용했다. 기기의 발열 상태가 올라가면 미리보기 프레임 속도를 낮추고 배너를 띄우는 기능이다.

먼저 deep-reasoner가 설계를 봤다. 프레임 속도를 낮추는 지점과 테스트에서 발열 상태를 주입하는 방법이 쟁점이었다. 이 에이전트는 구현하지 않고 판단과 근거만 반환한다. 카메라가 없는 시뮬레이터에서도 동작하도록 발열 판정은 엔진 안에 두기로 했다.

구현은 워커가 받았다. 여러 파일이 바뀌었고 테스트가 열아홉 개 늘었다. 이 단계에서 버그가 하나 나왔다. 초기 발열 상태를 카메라 준비가 성공했을 때만 알리도록 짜여 있어서, 카메라가 없는 시뮬레이터에서는 배너가 영영 뜨지 않았다. 카메라 가용성과 무관하게 초기 상태를 먼저 내보내도록 고쳤다. 설계 단계에서 시뮬레이터를 고려했는데도 구현에서 다시 걸린 자리다.

구현을 마친 뒤 Claude 워커가 쓴 코드를 Codex가 교차 검토했다. 검토 범위는 커밋 전 작업 트리 전체 차이로 잡았고, 무엇을 볼지도 같이 넘겼다. 스레드 규율, 기존 코드의 패턴과 어긋나는 곳, 테스트가 실제 실행 경로를 지나가는지, 저장소 관례를 지켰는지다.

검토 결과는 번호가 붙은 지적과 심각도, 그리고 커밋해도 되는지에 대한 판정으로 돌아온다. 지적을 반영한 뒤에야 커밋한다. 최종 상태는 새 테스트 열아홉 개를 포함해 541개가 통과했다.

무엇을 볼지 같이 넘긴다

검토 범위를 지정하지 않고 “검토해줘”라고 요청했을 때는 코드 요약과 사소한 스타일 지적이 주로 돌아왔다.

구체적인 지적은 검토 지점을 지정했을 때 나왔다. 미리보기 멈춤 버그를 고친 커밋을 검토시킬 때는 항목을 나열해서 넘겼다. 스트림 생성과 구독이 원자적으로 일어나는지, 액터 경계를 넘나드는 지점이 안전한지, 오래된 초기화가 중단됐다 재개되면서 새 구독을 취소할 수 있는지 같은 것들이다. 마지막 항목은 실제로 의심하던 경합이었고, 검토자가 그 자리를 지적했다.

위험이 큰 변경에는 적대적 검토를 따로 썼다. 일반 검토에는 구현과 요구의 일치를, 적대적 검토에는 실패·우회 경로를 찾도록 요청했다. 인증, 데이터 손실, 되돌리기, 경합처럼 오류 비용이 큰 영역에만 붙였다.

Codex가 없을 때

이 규칙은 Codex가 있다는 전제 위에 있었다. 실제 운용 중 쿼터가 떨어져 검토를 못 하면 커밋도 못 하는 상태가 됐다.

검토 없이 진행하지 않으려면 대체 검토자가 필요했다. 정책에 폴백 경로를 추가해 Codex가 맡던 검토를 deep-reasoner가 대신 받도록 했다. 적대적 검토가 필요한 변경에는 공격 각도를 열거하고 작성자 주장을 반박하라는 지시를 따로 준다.

대신 조건을 붙였다. 대체 검토자는 작성자와 다른 컨텍스트여야 한다. 규칙에서 벗어난 사실은 커밋 본문에 남긴다. 쿼터가 돌아오면 사후 검토를 제안한다. 그리고 쿼터 소진은 킬스위치를 켤 이유가 되지 않는다.

쿼터가 떨어진 뒤에 경로를 정하려 하면 규칙을 끄는 선택도 다시 검토하게 됐다. 대체 경로를 정책에 미리 적은 뒤에는 같은 상황에서 그 절차를 따랐다.

자기가 자기를 검토하겠다고 할 때

운영 후반에 예상 못 한 일이 있었다. Codex에게 큰 구현을 맡겼는데, 이 에이전트가 저장소의 정책 문서를 읽고 스스로 적용하기 시작했다. 자기 작업을 하위 에이전트에게 나누고, 독립 검토까지 자기 안에서 붙였다. 그리고 이렇게 보고했다.

I'm delegating the implementation and independent cross-lineage review as
required by the repository's orchestration contract.

이 보고만 보면 정책이 요구한 검토까지 끝난 것처럼 읽힌다. 하지만 Codex 안에서 나눈 하위 에이전트는 정책에서 정한 계보 기준으로 모두 Codex에 속한다. 이 규칙은 같은 모델 안의 내부 검토를 교차 계보 검토로 인정하지 않았으므로 별도 검토가 필요했다.

그래서 정책에 한 줄을 더 넣었다. 구현을 맡은 모델이 내부 검토를 보고하더라도, 작성자와 다른 계보의 검토를 따로 받는다.

남은 비용

모든 코드 변경에 검토 한 번이 더 붙으므로 작업 시간이 늘어난다. 검토 범위와 확인할 위험을 매번 지정하는 시간도 든다. 범위를 지정하지 않았을 때는 코드 요약과 사소한 스타일 지적에 머무르는 경우가 많았다.

내 작업에서는 작성자가 다시 읽을 때와 다른 컨텍스트에서 처음 읽을 때 발견한 문제가 달랐다. 발열 기능에서도 설계 단계에서 고려한 시뮬레이터 조건이 구현에서 빠졌다. 이 사례를 확인한 뒤에는 추가 검토에 드는 시간을 그 누락을 찾는 데 필요한 시간으로 보았다.

참고

Comments

댓글

    이미지 확대