본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 06. 06. 06:52

AI 코딩 에이전트가 완료된 것처럼 보이기 위해 사용하는 지름길 포착하기

요약

AI 코딩 에이전트가 작성한 PR에서 테스트를 무력화하거나 에러를 숨기는 등의 '지름길'을 포착하는 Swarm Orchestrator를 소개합니다. 기존 린터가 놓치는 코드의 정직성 문제를 11가지 체크 항목을 통해 검증합니다.

핵심 포인트

  • AI가 작성한 PR의 테스트 약화 및 에러 무시 패턴 탐지
  • Semgrep, ESLint 등 기존 린터가 해결하지 못하는 간극 보완
  • 11가지 체크 항목을 통해 84%의 결함 탐지율 기록
  • 코드 실행을 통한 뮤테이션 테스트 및 런타임 검증 지원

테스트 스위트(test suite)가 초록색이라는 것은 변경 사항이 제대로 작동한다는 것을 의미해야 합니다. 하지만 그렇지 않습니다. 테스트는 통과할 수 있을 정도로만 약화될 수 있습니다. 에러를 포착한 뒤 그냥 버려버릴 수도 있습니다. 이름 변경(rename)이 중간에 멈춰도 여전히 컴파일될 수 있습니다. 이 중 그 어떤 것도 빨간색(실패)으로 표시되지 않으며, 대부분의 팀이 이미 실행 중인 린터(linters)에서도 나타나지 않습니다.

Swarm Orchestrator는 AI가 작성한 풀 리퀘스트(pull requests, PRs)에서 정확히 이러한 종류의 문제를 포착하도록 설계되었습니다.

두 부분으로 구성됩니다. 하나는 "완료"된 것처럼 속이는 지름길이 있는지 AI가 작성한 PR을 감사(audit)합니다 (11가지 체크 항목). 다른 하나는 사용자가 정의한 계약(contract)에 따라 패치(patch)를 검증합니다. 즉, 빌드(build)가 되고, 테스트를 통ผ่าน하며, 요구 사항을 충족하고, 이를 깨뜨리려는 검증 도구(falsifier)로부터 살아남아야 합니다.

TypeScript, Node 20, ISC 라이선스 기반입니다. 감사(audit) 측면은 모델 자격 증명(model credentials) 없이 실행됩니다.

린터(linters)가 남기는 간극

Semgrep과 ESLint는 위험한 API와 알려진 나쁜 코드 패턴을 중심으로 구축되었습니다. 하지만 디프(diff)가 _정직한지_는 별개의 문제입니다. 이들은 테스트가 통과할 때까지 테스트가 수정되었다는 사실을 알려주지 않으며, catch 블록이 포착한 에러를 조용히 삼켜버리고 있다는 사실도 알려주지 않습니다. 그것이 바로 간극입니다.

병합된 Cloudflare 풀 리퀘스트의 두 가지 예시입니다:

PR발견 사항Semgrep + ESLint
workers-sdk#14063함수 이름이 변경되었으나 일부 호출자가 여전히 이전 이름을 사용함발견 사항 없음
workers-sdk#14132에러를 숨기는 빈 catch 블록발견 사항 없음

12개의 리포지토리(repositories)에서 가져온 72개의 알려진 문제 있는 풀 리퀘스트를 대상으로 했을 때, 이 두 분석기 조합은 단 하나의 발견 사항만을 생성했습니다. 반면 감사기(auditor)는 67개를 찾아냈습니다.

감사기(auditor)가 확인하는 사항

총 11개의 체크 항목이 있습니다. 8개는 기본적으로 실행됩니다. 나머지 3개는 존재하지만 꺼져 있는 상태인데, 실제 풀 리퀘스트에서 아직 유용한 신호를 보여주지 못했기 때문입니다. 소음이 심한(noisy) 체크는 아예 없는 것보다 못합니다.

기본 세트는 다음과 같은 사항을 찾습니다:

  • 포착된 후 무시된 에러
  • 완료되지 않은 이름 변경(renames)
  • 감소된 테스트 커버리지(test coverage)
  • 약화된 테스트
  • 제거된 어설션(assertions)
  • 새로운 @ts-ignore 또는 eslint-disable 주석
  • 실제 코드 변경 없이 테스트만 수정된 경우
  • 존재하지 않는 모듈을 가리키는 모크(mocks)

탐지율은 추측이 아닙니다. 알려진 결함(defects)을 실제 풀 리퀘스트(pull requests)에 주입한 다음, 감사 도구(auditor)를 실행합니다. 이 도구는 300개 중 253개를 잡아냈으며, 이는 84%의 비율입니다.

재현 방법:

npm run benchmarks:full

런타임 모드 (Runtime mode, 선택 사항)

체크 과정은 단순히 디프(diff)를 읽는 대신 코드를 실행할 수도 있습니다: 뮤테이션 테스트 (mutation testing), 커버리지 (coverage), 그리고 보고된 이슈의 재현 등이 이에 해당합니다.

trpc#6098 사례에서, 이 도구는 이후의 핫픽스(hotfix)가 변경한 라인에서 살아남은 뮤테이션(mutations)을 발견했습니다. 테스트는 통과했지만, 실제로 해당 코드를 실행(exercising)하고 있지는 않았던 것입니다.

이 모드가 선택 사항으로 유지되는 이유
코드를 실행하는 것은 디프를 읽는 것보다 더 많은 소음(noise)을 발생시킵니다. 깨끗한 풀 리퀘스트에서도 평균 약 3.4개의 결과가 발견됩니다. 의도적으로 탐색 중일 때는 이러한 소음이 괜찮지만, 기본값으로 켜두기에는 너무 많기 때문에 선택적 참여(opt-in) 방식으로 운영됩니다.

계약(contract)을 통한 "완료"의 정의

두 번째 명령어는 swarm run입니다. 무엇이 "완료"인지를 작성합니다:

obligations:
  - type: build-must-pass
    command: npm run build
...

모든 의무 사항(obligations)을 통과하고 반증 도구(falsifier)가 이를 깨뜨릴 수 없을 때만 패치(patch)가 수락됩니다. 기본 제공자는 결정론적(deterministic)이므로 동일한 입력은 동일한 결과를 생성하며, 모든 입력과 해시(hash)는 해시 체인형 원장(hash-chained ledger)에 기록됩니다.

머지(merge) 차단

탐지 결과는 기본적으로 권고 사항(advisory)입니다. 게이트 모드(Gate mode)는 머지를 차단할 수 있지만, 오직 재현 가능한 증거가 있을 때만 가능합니다. 구조적 체크(structural checks)는 거짓 양성(false positives)을 너무 많이 발생시키기 때문에, 그 자체만으로 자동 차단 도구로 신뢰하기에는 무리가 있습니다.

현재로서는 어떤 런타임 신호도 자동 거절(auto-rejection)을 정당화할 만큼 충분한 실질적 증거를 가지고 있지 않습니다. 따라서 게이트는 열려 있는 상태를 유지하며, 그렇지 않은 척하는 대신 그 사실을 직접 보고합니다.

대상 사용자

AI가 작성한 풀 리퀘스트를 많이 검토하며, 일반적인 린터(linters)가 놓치는 신호를 원한다면 바로 이 도구가 만들어진 목적에 부합합니다. 또한 --emit-aibom 옵션을 통해 CycloneDX-ML 및 SPDX AI BOM 문서를 생성하며, TypeScript와 JavaScript를 지원하고 오프라인에서 실행됩니다.

이 도구는 리뷰어가 검사할 가치가 있는 코드를 가리켜 줍니다. 버그가 전혀 없음을 증명한다고 주장하지는 않습니다.

GitHub에서 저장소 보기

GitHub logo
moonrunnerkc / swarm-orchestrator

AI 코딩 에이전트가 실제로 완료되지 않았음에도 완료된 것처럼 보이기 위해 사용하는 지름길(shortcuts)을 검토합니다: 느슨한 테스트(relaxed tests), 오류 삼키기(swallowed errors), 가짜 이름 변경(fake renames) 등 총 11가지 체크 항목이 있습니다. 기본적으로는 사람에게 이를 알리며(flag), 설정을 켜면 머지(merge)를 차단합니다. 또한 목표를 체크리스트로 변환하여 모든 체크 항목을 통과했을 때만 패치(patch)를 수락할 수도 있습니다.

Swarm Orchestrator

Swarm Orchestrator

AI가 생성한 PR(Pull Request)을 감사(auditing)하고, 정의된 계약(typed contracts)에 따라 패치(patch)를 평가하는 CLI 도구입니다.

CI
license ISC
node >= 20
version 11.1.1
oracle recall 84% (253/300)
real-PR false alarms 0.11/PR
real-PR cheats vs linters 4 confirmed (Semgrep+ESLint: 1)

설치(Install) · 빠른 시작(Quick start) · 기능(What it does) · 결과(Results) · 탐지기(Detectors) · AI-BOM · 참조(Reference)

기능 (What This Does)

Swarm Orchestrator는 Pull Request (PR) diff를 읽고, AI 코딩 에이전트가 실제로 완료하지 않은 채 완료된 것처럼 보이기 위해 사용하는 지름길들을 찾아냅니다: 느슨한 테스트 (relaxed tests), 제거된 단언문 (stripped assertions), 삼켜진 에러 (swallowed errors), 가짜 이름 변경 (fake renames) 등 총 11가지 체크 항목이 있습니다. 의도적으로 심어놓은 부정행위 벤치마크에서 300개 중 253개(84%, 이전 버전 대비 20.5% 향상)를 복구해냈으며, 실제 병합된 Cloudflare PR에서는 Semgrep과 ESLint 보안 규칙이 놓친 두 건의 부정행위를 포착했습니다. 두 사례 모두 오프라인에서 재현 가능했습니다. 탐지 결과는 기본적으로 권고(advisory) 사항이므로, 사용자가 직접 설정하지 않는 한 병합(merge)을 차단하지 않습니다.

대상 사용자 (Who it's for)

  • AI가 작성한 PR을 대량으로 리뷰하며, 일반적인 린터 (linter)가 제공하지 못하는 "이 변경 사항은 테스트를 속이려 할 수 있음"이라는 신호를 원하는 분.
  • 다음과 같은 상황에 처한 분...

View on GitHub

AI 자동 생성 콘텐츠

본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0