WIGTN-CUSTOS
Self-Evolving GitLab Repo Custodian
GitLab 리포에 상주하며 MR 리뷰부터 머지된 코드 감시, 이슈 발급까지 24/7 스스로 돌보는 자가진화 리포 커스토디언입니다. 핵심은 자가발전입니다. "승인됐는가"가 아니라 "머지된 뒤 실제로 사고가 났는가"(Truth ≠ Consent)를 진실 신호로 삼아, 그 신호로 스킬을 재보정하고 사고에서 새 탐지 규칙을 합성하며 점점 우리 팀 시니어가 되어갑니다. Google Cloud Rapid Agent Hackathon 2026 · GitLab Track 출품작(심사 중).
개요
이 프로젝트는 Google Cloud Rapid Agent Hackathon 2026 GitLab Track 출품작으로, 트랙 제약상 GitLab 리포 위에서 도는 에이전트를 만드는 것이 출발점이었습니다. 우리가 잡은 질문은 단순했습니다. PR 리뷰 봇은 왜 하나같이 "리뷰까지"에서 멈추는가. 기존 PR 리뷰 봇(Copilot Review, CodeRabbit, GitLab Duo)은 하나같이 수동적입니다. PR이 열려야 깨어나고, 머지되는 순간 그 코드를 잊어버립니다. 정작 사고는 머지된 뒤에 터지는데 말이죠. 좋은 시니어는 정반대입니다. 리포 건강을 끝까지 책임지고, 시간이 갈수록 팀 기준에 맞춰갑니다. 그래서 단순히 리뷰만 잘하는 봇이 아니라, 머지된 뒤 실제 사고를 보고 스스로 기준을 고쳐가며 점점 시니어처럼 되어가는 커스토디언을 목표로 잡았습니다.
도전
자율적으로 도는 봇을 만들려니 어려운 매듭이 세 개 있었습니다. 첫째, 자율은 곧 위험입니다. 봇이 스스로 코멘트를 달고 이슈를 발급하며(나중엔 수정 MR까지) 움직이면, 잘못 돌면 리포를 망가뜨리거나 자기가 만든 MR에 자기가 다시 반응하는 무한 루프에 빠질 수 있습니다. 둘째, "자가진화"는 거짓이 되기 쉽습니다. 팀이 머지했다거나 좋아요를 눌렀다는 신호(수용)만 학습하면 봇은 점점 무난해질 뿐, 더 정확해지지는 않습니다. 셋째, "agentic"은 말로는 쉽지만 증명이 어렵습니다. 진짜로 에이전트가 판단해서 도구를 고르는 건지, 고정 스크립트가 도는 건지 구분되지 않으면 의미가 없습니다.
- 자율 = 위험: 스스로 코멘트·이슈·수정을 하면 오작동·무한 루프·악용 위험
- 자가진화의 함정: 수용(머지·좋아요)만 학습하면 정확해지는 게 아니라 무난해질 뿐
- agentic 증명: 에이전트가 진짜 판단하는지 고정 스크립트인지 측정으로 구분돼야 함
접근
세 매듭을 각각 다른 장치로 풀 수 있다고 봤습니다. 자율의 위험은 권한을 한 번에 주지 않는 3단 신뢰 모드(dry-run → comment-only → full)와 입력 격리, 재귀 가드, 즉시 끄는 kill switch로 묶으면 통제할 수 있다. 자가진화의 함정은 수용이 아니라 "머지 후 진실"을 기준으로 삼으면 피할 수 있다. 머지됐다고 정답이 아니라, 머지된 뒤 실제 사고가 난 파일이 진실 신호이고, 그 신호를 수용보다 3배 무겁게 채점하면 봇은 무난해지는 게 아니라 정확해진다. agentic 증명은 에이전트에게 판단·도구선택·라우팅만 맡기고 결함 탐지 자체는 결정론으로 두면, 도구 선택 정확도를 골든셋으로 측정할 수 있다.
구조
2 레인과 자가진화 척추로 구조를 잡았습니다. Reactive 레인은 MR이 열리면 4개 페르소나(보안·성능·테스트·팀리드)가 병렬로 리뷰해 0~100 risk 점수와 인라인 코멘트를 60초 안에 답니다. Proactive 레인은 6시간마다 머지된 코드를 훑어 중복을 제거하고 우선순위 이슈를 자동 발급합니다. 그 위에서 라이브 ADK LlmAgent(Gemini)가 GitLab 네이티브 MCP를 통해 diff·파이프라인·SAST 같은 읽기 도구를 상황에 맞게 골라 호출하고(plan → act → decide), 그 계획을 MR 코멘트와 대시보드에 그대로 노출합니다. 페르소나의 결함 판정은 결정론으로 두고 합성만 가중평균과 거부권으로 처리해, 같은 입력이면 같은 점수가 나오게 했습니다. 그리고 이 위에 핵심인 자가진화 척추를 얹었습니다. 머지 후 사고 신호로 스킬 confidence를 재보정하고, Gemini가 그 사고에서 후보 탐지 규칙(regex)을 귀납 합성한 뒤, 깨끗한 코드에 단 한 번도 오탐하지 않는 골든 게이트를 통과해야만 격리를 거쳐 정식 스킬로 졸업시킵니다. 즉 진화의 모든 단계가 라벨된 골든셋에 묶여 측정됩니다.
실행
개념을 코드로 옮기면서 실제로 깨진 지점들을 하나씩 잡았습니다. 봇이 만든 MR이 다시 웹훅을 타고 자기 자신을 트리거하는 무한 루프는 봇 계정·메타데이터·idempotency 세 층의 재귀 가드로 끊었습니다. 시드 스킬이 적은 콜드 스타트에서는 벡터 검색 정확도가 낮아, 30개 미만이면 전수 비교 후 LLM rerank로 폴백하게 했습니다. 비용은 Proactive 스윕을 Flash 모델로 다운그레이드하고 파일 해시 캐시로 안 바뀐 파일을 건너뛰어 통제했습니다. Cloud Run에서는 async Firestore 클라이언트가 연결을 못 맺어 웹훅 ACK가 30초씩 멈췄는데, 동기 transport로 바꾸자 0.4초로 떨어졌습니다. 보안 쪽은 입력을 untrusted로 격리하고 시스템 프롬프트를 불변으로 두고, 봇 계정에 Developer 권한만 줘서 보호 브랜치에 직접 push하지 못하게 했습니다.
결과 & 성과
Google Cloud Rapid Agent Hackathon 2026 GitLab Track에 제출했고 현재 심사 결과 발표 전입니다. 수상 여부와 무관하게, 가장 강조하고 싶었던 자가진화 스택을 슬라이드가 아니라 코드와 테스트로 끝까지 구현해 라이브 Cloud Run에 올렸고, 대부분의 지표가 공개 대시보드에서 실시간으로 보입니다. 자가진화는 실제로 돌았습니다. 시드 10개였던 스킬이 실제 사고에서 4개를 자가 합성해 14개로 늘었고(저신뢰 1개는 격리), 골든셋(n=38)으로 측정한 Senior Score는 91/100, 규칙엔진 recall 0.964에 오탐은 0이었습니다. 에이전트도 측정됐습니다. 라이브 trajectory에서 도구 선택의 77%가 에이전트 주도(46건은 GitLab 네이티브 MCP 라이브)였고, 리뷰당 평균 2.38개 도구를 9가지 조합으로 골랐으며, "diff 먼저" 정책을 96.6% 스스로 지켰습니다. 전체는 609개 pytest로 회귀 가드됩니다.
다른 프로젝트