Skip to Content
KoUsersFeatures코드 리뷰

코드 리뷰

/review를 사용하여 코드 변경의 정확성, 보안, 성능 및 코드 품질을 검토하세요.

빠른 시작

# 로컬 미커밋 변경 사항 리뷰 /review # pull request 리뷰 (번호 또는 URL) /review 123 /review https://github.com/org/repo/pull/123 # PR에 인라인 댓글을 달며 리뷰 /review 123 --comment # 로컬 변경 사항을 리뷰하고 결과를 작업 트리에 적용 /review --fix # 특정 파일 리뷰 /review src/utils/auth.ts # 빠른 미검증 패스 (서브에이전트 없음) /review --effort low /review 123 --effort medium

미커밋 변경 사항이 없으면 /review가 알려주고 중단됩니다 — 에이전트가 실행되지 않습니다.

노력 수준

--effort low|medium|high는 깊이와 속도를 조절합니다:

수준실행 내용발견 상한판정PR에 게시
lowdiff에 대한 3-6개의 방향 인라인 각도(diff 크기에 따라 조절) 및 갭 스윕 — 서브에이전트 없음, 빌드/테스트 없음, 프로젝트 규칙 없음10 (미검증)없음절대 안 함
mediumhigh 파이프라인에서 가장 비용이 큰 패스를 제외한 것: 축소된 차원 세트에 대한 병렬 파인더 팬아웃, 빌드/테스트 및 단일 검증 패스상한 없음 (검증됨)Approve가 Comment로 제한됨절대 안 함
high전체 파이프라인: 14개 병렬 에이전트 → 샤드 검증 → 반복 역감사상한 없음 (검증됨)Approve / Request changes / Comment--comment와 함께

기본값: PR 리뷰는 high, 로컬 및 파일 리뷰는 medium. 효과적인 --comment는 high를 강제합니다(게시된 댓글은 검증을 통과해야 함) — PR이 아닌 대상에서 --comment는 경고와 함께 무시되며 노력을 변경하지 않습니다. Medium은 보안 및 테스트 커버리지 에이전트와 빌드/테스트를 유지하고, 적대적 페르소나, diff 전문 파인더 및 역감사를 제거합니다 — 따라서 두 번째 검토에서만 발견될 미묘한 Critical이 빠질 수 있습니다; 보안에 민감하거나 출시 전 리뷰에는 --effort high를 사용하세요. low만 미검증입니다. Worktree 격리는 동일 저장소 PR 리뷰에 적용되며; 교차 저장소 PR은 경량 모드(diff 전용, worktree나 빌드/테스트 없음)로 실행됩니다. Low 패스는 미검증으로 표시되고, 판정을 내리지 않으며, 증분 리뷰 캐시를 작성하지 않으므로 이후 --effort high 실행이 “이미 리뷰됨”으로 건너뛰어지지 않습니다; medium은 검증되지만 Approve가 Comment로 제한됩니다. 두 번째 검토가 없는 것은 첫 번째 패스에서 놓친 것을 찾기 때문입니다. Diff 획득 메커니즘은 모든 수준에서 동일합니다 — PR 리뷰는 항상 격리된 worktree와 동일한 기본 해상도를 사용하므로 잘못된 기본 대상에 대한 리뷰가 없습니다. 하나의 범위 차이만 남아 있습니다: 증분 캐시는 high 전용이므로 high 재리뷰는 새 커밋(lastCommitSha..HEAD)만 다루는 반면, low/medium은 항상 전체 PR diff를 리뷰합니다.

작동 방식

/review 명령은 다단계 파이프라인을 실행합니다:

단계 1: 범위 + 노력 수준 결정 (로컬 diff / PR worktree / 파일) diff를 파일로 캡처 + 청크로 분할 단계 2: 프로젝트 리뷰 규칙 로드 (medium/high) 단계 3C: low 노력: 3-6개 인라인 각도 + 갭 스윕 [0 서브에이전트 호출] 단계 3A: high, <=500 src AND <=3200 전체: 14개 에이전트 [14+ LLM 호출] |-- 에이전트 0: Issue Fidelity & Root-Cause Ownership |-- 에이전트 1a: Correctness — 라인별 스캔 | (언어 함정 + 래퍼 라우팅 검사 포함) |-- 에이전트 1b: Correctness — 제거된 동작 감사 |-- 에이전트 1c: Correctness — 교차 파일 추적기 |-- 에이전트 2: Security |-- 에이전트 3a: Reuse & duplication |-- 에이전트 3b: Altitude & abstraction fit |-- 에이전트 3c: Consistency & clarity |-- 에이전트 4: Performance & Efficiency |-- 에이전트 5: Test Coverage |-- 에이전트 6: Undirected Audit (3개 페르소나: 6a/6b/6c) |-- 에이전트 8: Diff 전문 파인더 (0-2개, | diff의 도메인에서 필요할 때만) '-- 에이전트 7: Build & Test (셸 명령 실행) 단계 3B: high, >500 src OR >3200 전체: territory x dim. [N+5..7+3H 호출] (N개 청크, 5-7개 전체 diff 에이전트, 무겁게 재작성된 파일 H당 3개 불변 에이전트) |-- ~400 diff 라인당 1개 청크 에이전트 (모든 차원, | 자체 territory만, 커버리지 영수증 반환) |-- 무겁게 재작성된 소스 파일당 3개 불변 에이전트 | (전체 파일; state/timers, counters/ | returns/errors, config/early-returns) |-- 에이전트 0: Issue Fidelity (전체 diff) |-- 에이전트 7: Build & Test (전체 저장소) |-- 에이전트 1b: Removed-behavior (전체 diff — | 교차 청크 절반; 청크는 로컬 절반 유지) |-- 에이전트 1c: Cross-file tracer (전체 diff) |-- 에이전트 8: Specialized finders (전체 diff, 0-2개) '-- Test coverage matrix (전체 diff) 단계 4: 중복 제거 --> 샤드 검증 (에이전트당 <=8개 발견) --> 집계 [ceil(F/8) 호출, F=발견 수] 단계 5: 반복 역감사, 청크당 팬아웃; 2회 연속 빈 라운드 후 중지 (상한 5) 단계 6: 발견 + 판정 제시 (high; low 패스: 발견만) 발견 표준화 -> .qwen/tmp/...-findings.json 단계 6B: 발견 적용 + 발견별 결과 기록 (--fix만) 단계 7: PR 리뷰 제출 (인라인 댓글, 요청된 경우; high만) 단계 8: 보고서 + 증분 캐시 저장 (캐시: high만) 단계 9: 정리 (worktree + 임시 파일 제거)

단계 3A/3B/4/5는 high 노력 파이프라인입니다; --effort low|medium에서는 단일 인라인 패스(단계 3C)가 이들을 대체합니다.

리뷰 에이전트

에이전트초점
에이전트 0: Issue Fidelity연결된 이슈 증거, 근인 소유권, PR이 보고된 문제를 해결하는지 여부
에이전트 1a: 라인별 스캔각 hunk와 이를 감싸는 함수를 순회: 잘못된 조건, off-by-one, 누락된 await, 언어별 함정, 래퍼/프록시 라우팅
에이전트 1b: 제거된 동작 감사삭제/대체된 모든 라인을 순회: 강제하던 불변을 명시하고 새 코드에서 어디서 다시 확립하는지 추적 — 다른 파일에 있는 exports의 교체도 포함하며, 이는 조용히 기본값을 변경합니다. 3B에서는 전체 diff로 실행됩니다(청크 에이전트가 로컬 절반 유지)
에이전트 1c: 교차 파일 추적기변경된 각 심볼의 호출자(소비자 방향)와 추가된 각 필드의 읽기 사이트(생산자 방향)를 순회하며, 동일 PR의 callee 변경도 포함
에이전트 2: SecurityInjection, XSS, SSRF, auth 우회, 민감한 데이터 노출
에이전트 3a: Reuse & duplication코드베이스에 이미 이것이 있는가? 동작을 grep하고 호출할 기존 helper를 이름으로 지정하며, diff가 남긴 dead code를 플래그
에이전트 3b: Altitude & abstraction수정이 올바른 깊이에 있는가 — 아니면 공유 인프라에 대한 반창고, 업스트림 버그에 대한 다운스트림 보상, 또는 하나의 호출 사이트를 위한 추상화인가?
에이전트 3c: Consistency & clarity형제 일관성(병렬 패밀리의 한 멤버에는 있는 가드가 다른 멤버에는 없는), 인용된 로컬 예제에 대한 규칙 드리프트, 오해의 소지가 있는 이름/주석, 불필요한 복잡성
에이전트 4: Performance & EfficiencyN+1 쿼리, 메모리 누수, 불필요한 리렌더링, 번들 크기
에이전트 5: Test Coveragediff의 테스트되지 않은 코드 경로, 누락된 분기 커버리지, 약한 어서션
에이전트 6: Undirected Audit3개 병렬 페르소나 (공격자 / 3am-oncall / 유지보수자) — 교차 차원 이슈를 잡음
에이전트 7: Build & Test빌드 및 테스트 명령을 실행하고 실패를 보고
에이전트 8: Diff 전문 파인더diff가 알려진 실패 모드가 있는 도메인(재연결 로직, 모듈 로더, 스케줄러, 코덱)에 집중될 때 리뷰당 0-2개의 추가 파인더 작성

세 Correctness 에이전트는 절차적입니다: 각 에이전트는 diff를 어떻게 순회하는지(라인별 / 삭제된 라인 / 교차 파일 엣지)로 정의되며, 버그 분류로 정의되지 않습니다 — 따라서 커버리지가 중복되지 않고 상호 보완적입니다. 동일한 추론이 코드 품질을 세 개로 분할합니다(3a/3b/3c): 6개 항목 체크리스트를 가진 하나의 에이전트는 한 항목을 처리합니다 — 무겁게 재작성된 파일에서 측정하면, 8개 항목 체크리스트를 가진 하나의 에이전트는 5개 결함 중 1개를 찾았지만 같은 모델이 세 방향으로 분할되면 모두 5개를 찾았습니다 — 따라서 품질 체크리스트는 질문이 실제로 달라지는 지점에서 분할됩니다. 모든 에이전트는 병렬로 실행됩니다(에이전트 1은 3개 절차적 변형을 실행, 에이전트 3은 3개 체크리스트 슬라이스를 실행, 에이전트 6은 3개 페르소나 변형을 병렬로 실행하여, 동일 저장소 PR 리뷰에 대해 총 14개 병렬 작업, diff의 도메인에서 필요할 때 0-2개의 에이전트 8 파인더 추가 — 따라서 실제로 14-16개; 에이전트 0은 로컬 diff 및 파일 경로 리뷰에서 건너뛰어져 13-15개 실행; 교차 저장소 경량 모드도 에이전트 1c와 7을 건너뛰어 12-14개 실행).

모든 발견은 실패 시나리오를 명시해야 합니다 — 이를 트리거하는 구체적인 입력, 상태 또는 타이밍과 그로 인한 잘못된 결과(품질 발견의 경우 구체적인 비용). 시나리오를 명시할 수 없는 발견은 소스에서 삭제되며, 검증은 발견의 문구가 아닌 실제 코드를 통해 주장된 시나리오를 재추적합니다.

PR이 500줄 이상의 소스 변경을 초과하면 — 또는 전체 diff 라인이 3,200줄을 초과하면, 이를 넘으면 11개의 전체 diff 리더가 각각 주의 깊게 읽기에는 너무 희석됩니다(호출 수의 약속이 아닌 주의력 한계 — 무거운 파일과 전문 파인더는 3B 비용을 더 만들 수 있습니다) — 이 차원 팬아웃은 territory × dimension 팬아웃으로 대체됩니다: diff는 ~400라인 청크로 분할되며 — 경계는 hunk 경계에 떨어지며, 맞지 않을 정도로 큰 hunk는 최상위 선언에서만 분할되며 함수 내부는 분할되지 않습니다 — 각 청크는 해당 청크에만 모든 리뷰 차원을 적용하는 자체 에이전트를 받습니다.

게이트는 의도적으로 diff 라인이 아닌 소스 라인을 셉니다. 테스트 코드, 산문 및 lockfile이 diff 크기를 지배합니다 — 이 저장소의 최근 40개 병합 PR에서 중앙값 diff는 41%가 테스트입니다 — 따라서 원시 크기의 게이트는 489줄의 새 테스트와 함께 제공되는 173라인 프로덕션 변경을 territory로 분할 것이며, 해당 프로덕션 코드는 10개의 렌즈(diff 읽기 차원 에이전트 — Issue Fidelity와 Build & Test를 제외한 12개) 대신 하나의 리뷰어를 갖게 됩니다. 청킹은 어쨌든 모든 라인을 커버합니다; 테스트도 포함됩니다; 게이트가 결정하는 것은 리뷰어의 수와 각각이 수행하는 작업입니다. 하나의 큰 diff를 순회하는 10개의 diff 읽기 렌즈는 같은 초기 hunk를 10번 반복해서 읽습니다; 청크당 하나의 에이전트는 diff의 모든 라인에 정확히 하나의 책임 있는 리뷰어가 있음을 의미합니다. 각 청크 에이전트는 Covered: 영수증을 반환하며, 영수증이 없는 청크는 실행이 진행되기 전에 재리뷰됩니다 — 따라서 “차단기 없음”은 아무도 읽지 않은 코드에 대해 보고될 수 없습니다.

대부분 재작성된 소스 파일(300줄 이상의 기존 파일이 이제 40% 이상 새롭거나 800줄 이상의 변경된 라인이 있는 경우)도 3개의 전체 파일 불변 에이전트를 받습니다. 테스트 및 생성 파일은 절대 자격이 없습니다 — 체크리스트는 필드, 타이머 및 오류 분류에 대해 묻는데, 재작성된 테스트 파일에는 이러한 것이 없습니다. 버그는 보통 하나의 hunk 내부가 아니라 새 라인 _사이_에 있습니다 — 파일 상단 근처에 설정된 타이머와 2천 줄 아래의 teardown 경로. 각 에이전트는 전체 변경 후 파일을 읽고 고정 체크리스트의 2-3개 항목을 순회합니다: 모든 종료 경로에서 지워지는 가변 필드, 모든 종료에서 취소되는 타이머(취소가 캡처된 데이터를 폐기하지 않음), delete와 매칭되는 map insert, 모든 진입에서 증가되는 재시도 카운터, 실제로 확인되는 상태 반환값, 영구/일시로 철저히 분류되는 오류 코드, 모든 경로에서 준수되는 구성 필드, 필수 부작용을 건너뛰는 early return.

체크리스트는 의도적으로 세 방향으로 분할됩니다. 2,400라인 파일에 대해 8개 검사를 모두 하나의 에이전트에게 주면 하나를 제대로 처리합니다; 2-3개 검사를 가진 3개의 에이전트는 모두 처리합니다. 청크 에이전트는 이를 대체하지 않습니다 — PR #6457에서 그들은 할당된 territory 내에 이러한 결함을 모두 보유했지만 아무것도 보고하지 않았습니다. 그들이 부족했던 것은 라인이 아니라 질문이었습니다.

발견은 샤드 배치로 검증됩니다(검증 에이전트당 최대 8개 발견, 모두 함께 실행). 검증자는 이를 모순하는 코드를 인용해야만 Critical을 거부할 수 있습니다(또는 diff 자체의 댓글이 플래그된 동작을 의도적인 것으로 문서화하는 경우); 덜 확실한 것은 삭제되지 않고 낮은 신뢰도로 다운그레이드됩니다 — 조용히 거부된 Critical은 이후 모든 단계에서 보이지 않지만, 다운그레이드된 것은 여전히 사람에게 도달합니다. 검증 후, 반복 역감사가 갭을 추적하며, 라운드당 청크당 하나의 감사자로 팬아웃되고, 각각 누적 발견 목록을 가집니다. 루프는 2회 연속 빈 라운드(또는 5라운드, 하드 캡 — 수렴이 아닌 것으로 보고) 후에 중지됩니다. 한 번의 빈 라운드는 수렴의 증거가 아니며, 역감사 발견은 다른 발견과 동일하게 검증됩니다.

심각도 수준

심각도의미PR 댓글로 게시?
Critical병합 전 수정 필수 (버그, 보안, 데이터 손실, 빌드 실패)예 (높은 신뢰도만)
Suggestion권장 개선 사항예 (높은 신뢰도만)
Nice to have선택적 최적화아니오 (터미널만)

낮은 신뢰도의 발견은 터미널의 별도 “Needs Human Review” 섹션에 나타나며 PR 댓글로 게시되지 않습니다.

Worktree 격리

PR을 리뷰할 때, /review는 현재 브랜치를 전환하는 대신 임시 git worktree(.qwen/tmp/review-pr-<number>)를 생성합니다. 즉:

  • 작업 트리, 스테이징된 변경 사항 및 현재 브랜치는 절대 건드리지 않습니다
  • 빌드/테스트가 작동하도록 worktree에 의존성이 설치됩니다(npm ci 등)
  • 빌드 및 테스트 명령이 로컬 빌드 캐시를 오염시키지 않고 격리되어 실행됩니다
  • 문제가 발생하면 환경에 영향을 주지 않습니다 — worktree를 삭제하면 됩니다
  • 리뷰 완료 후 worktree가 자동으로 정리됩니다
  • 리뷰가 중단되면(Ctrl+C, 크래시), 같은 PR의 다음 /review가 오래된 worktree를 자동으로 정리하고 새로 시작합니다
  • 리뷰 보고서와 캐시는 메인 프로젝트 디렉토리에 저장됩니다(worktree가 아님)

교차 저장소 PR 리뷰

전체 URL을 전달하여 다른 저장소의 PR을 리뷰할 수 있습니다:

/review https://github.com/other-org/other-repo/pull/456

이는 경량 모드로 실행됩니다 — worktree 없음, 빌드/테스트 없음. 리뷰는 diff 텍스트만을 기반으로 합니다(GitHub API를 통해 가져옴). 쓰기 권한이 있으면 PR 댓글을 계속 게시할 수 있습니다.

기능동일 저장소교차 저장소
LLM 리뷰 (에이전트 0, 1a, 1b, 2-6 + 검증 + 반복 역감사)
에이전트 1c: Cross-file tracer❌ (grep할 로컬 코드베이스 없음)
에이전트 7: Build & test❌ (로컬 코드베이스 없음)
에이전트 8: Diff 전문 파인더 (0-2개, 도메인에서 필요할 때)✅ (diff만 필요)
PR 인라인 댓글✅ (쓰기 권한이 있는 경우)
증분 리뷰 캐시

PR 인라인 댓글

--comment를 사용하여 PR에 직접 발견을 게시하세요:

/review 123 --comment

또는 /review 123을 실행한 후 post comments를 입력하여 리뷰를 다시 실행하지 않고 발견을 게시하세요.

게시되는 내용:

  • 높은 신뢰도의 Critical 및 Suggestion 발견이 특정 라인의 인라인 댓글로 게시되며, 각각 **[Critical]** 또는 **[Suggestion]**으로 접두사가 붙어 차단기와 권장 사항을 구별할 수 있습니다
  • 수정이 단일 로컬 편집인 경우, 한 번의 클릭으로 적용할 수 있는 ```suggestion 블록
  • Approve/Request changes 판정의 경우: 판정이 포함된 리뷰 요약
  • 모든 인라인 댓글이 게시된 Comment 판정의 경우: 별도 요약 없음 (인라인 댓글으로 충분)
  • 각 댓글에 모델 및 CLI 버전 속성 푸터 (예: — qwen3-coder via Qwen Code /review (v0.21.2))

터미널에만 남는 내용:

  • Nice to have 발견
  • 낮은 신뢰도의 발견

자체 작성 PR: GitHub에서는 자신의 pull request에 APPROVE 또는 REQUEST_CHANGES 리뷰를 제출할 수 없습니다 — 둘 다 HTTP 422로 실패합니다. /review가 PR 작성자가 현재 인증된 사용자와 일치한다고 감지하면, 판정에 관계없이 API 이벤트를 자동으로 COMMENT로 다운그레이드하여 제출이 성공하도록 합니다. 터미널에는 여전히 정직한 판정(“Approve” / “Request changes” / “Comment”)이 표시됩니다 — GitHub 측 리뷰 이벤트만 중립화됩니다. 실제 발견은 여전히 특정 라인의 인라인 댓글으로 나타나므로 실질적인 피드백은 변경되지 않습니다.

이전 Qwen Code 댓글이 있는 PR 재리뷰: /review가 이전 Qwen Code 리뷰 댓글이 이미 있는 PR에서 실행되면, 새 댓글을 게시하기 전에 이를 분류합니다. 같은 라인 중복(새 발견과 같은 (path, line)에 기존 댓글이 있는 경우)만 확인을 요청합니다 — 같은 코드 라인에 시각적 중복이 보이는 경우입니다. 이전 커밋의 댓글, 답글이 달린 댓글(해결된 것으로 처리) 및 새 발견과 중복되지 않는 댓글은 조용히 건너뛰며, 무엇이 필터링되었는지 알 수 있도록 터미널 로그 라인이 남습니다.

APPROVE 전 CI / 빌드 상태 확인: 판정이 “Approve”이면, /review는 제출 전에 PR의 check-run 및 커밋 상태를 조회합니다. 어떤 검사가 실패했거나(또는 모든 검사가 아직 대기 중인 경우) API 이벤트가 자동으로 APPROVE에서 COMMENT로 다운그레이드되며, 리뷰 본문에 이유가 설명됩니다. 근거: LLM 리뷰는 코드를 정적으로 읽으며 런타임 테스트 실패를 볼 수 없습니다; CI가 빨간색인 동안 승인하는 것은 오해의 소지가 있습니다. 인라인 발견은 변경 없이 계속 게시됩니다. 어쨌든 승인하고 싶다면(예: 알려진 flaky CI 실패), 확인 후 GitHub 승인을 수동으로 제출하세요.

발견 적용 (--fix)

--fix--comment의 반영입니다. --commentpull request에 쓰므로 PR이 필요합니다; --fix작업 트리에 쓰므로 리뷰보다 오래 지속되는 작업 트리가 필요합니다:

/review --fix # 로컬 미커밋 변경 /review src/auth.ts --fix # 단일 파일

PR 대상에서는 경고와 함께 무시됩니다 — PR 리뷰는 리뷰가 끝나면 삭제되는 일시적 worktree에서 실행되므로, 해당 “수정된” 편집은 몇 분 후에 폐기됩니다. 대신 --comment를 사용하여 발견을 게시하세요.

효과적인 --fix노력을 medium으로 바닥으로 설정합니다. 파일을 편집하고 low는 검증을 실행하지 않기 때문입니다: 미검증 발견을 적용하는 것은 PR이 아닌 작업 트리를 대상으로 한다는 점만 제외하면 게시하는 것과 같은 실수입니다. high를 강제하지는 않습니다 — medium의 발견은 검증되며, high가 추가하는 역감사는 누락된 발견을 찾지만, 적용 여부를 결정하는 것은 이에 의존하지 않습니다.

리뷰 후, 각 발견은 edit 도구로 적용된 다음 결과가 기록되며, 세 가지 중 하나입니다:

결과의미사용자 책임?
fixed편집이 트리에 적용됨아니오
skipped실제 발견이지만 적용되지 않음 — 이유가 함께 보고됨
no_change_needed발견이 잘못되었거나 코드가 이미 처리함아니오

발견이 건너뛰어지는 경우는 수정이 의도된 동작을 변경하거나, 리뷰된 diff를 훨씬 벗어난 변경이 필요하거나, 두 번째 검토에서 거짓 양상으로 판명되는 경우입니다.

모든 발견은 결과를 가지며, 이것은 요청이 아닌 강제됩니다. 레저는 qwen review findings --outcomes을 통과하며, 모두를 커버하지 않는 세트를 거부합니다 — 9개 중 6개를 적용하고 6개를 보고하는 수정기는 어느 것에도 거짓말하지 않았지만, 조용히 목록을 단축했으며, 빠진 3개를 볼 방법이 없습니다.

데이터로서의 발견

확인된 발견은 다른 무엇이 소비하기 전에 .qwen/tmp/qwen-review-<target>-findings.json으로 표준화됩니다 — 터미널 보고서, 저장된 Markdown 보고서 및 PR 리뷰 JSON이 모두 목록을 재입력하는 대신 이 단일 아티팩트를 읽습니다. 각 발견은 고유한 id(결과와 해결된 앵커가 조인하는 것), severity, confidence, source, summary, 목록 렌더링용 60자 제한 shortSummary, failureScenario 및 하나 이상의 locations를 가집니다 — 패턴 집계 발견은 발생당 하나의 위치를 유지하므로 각각 고유한 인라인 댓글을 받습니다.

명령은 쓰기 시 유효성을 검사합니다: 중복 id, 실패 시나리오가 없는 발견, 빈 locations 배열 또는 알 수 없는 심각도는 조용히 망가진 항목이 아닌 오류입니다.

PR 댓글의 증거 이미지

GitHub의 API는 리뷰 댓글에 이미지를 첨부할 수 없으므로, /review는 증거 이미지(TUI 스크린샷, 렌더링 출력 비교)를 지정된 저장소에서 호스팅하고 URL로 삽입할 수 있습니다.

에셋 저장소는 PR이 병합되거나 닫힐 때 자동으로 정리되는 전용 GitHub 저장소입니다. 리뷰는 이미지 참조를 커밋 고정 URL로 작성합니다 — 브랜치가 나중에 이동해도 불변이며, GitHub Enterprise에서도 변경 없이 작동합니다.

에셋 저장소를 구성하려면:

export QWEN_REVIEW_ASSETS_REPO=your-org/your-repo # push할 수 있는 저장소 /review 123 --comment

유지관리자는 일반적으로 리뷰 대상 저장소를 가리키며; 다른 사람은 포크나 임시 저장소를 사용할 수 있습니다. 이미지는 pr-assets/<pr>-review 브랜치에 콘텐츠 해시된 이름으로 저장되며, 댓글은 커밋 고정 URL로 참조합니다 — 브랜치가 나중에 이동해도 불변이며, GitHub Enterprise에서도 변경 없이 작동합니다.

GitHub 트리거 리뷰(PR 리뷰 워크플로)의 경우, 같은 이름의 저장소 변수에서 동일한 변수가 연결됩니다: 변수가 설정되지 않으면 워크플로는 빈 값을 전달하고 게시가 거부됩니다 — 아무것도 변경되지 않습니다. 유지관리자가 저장소의 Actions 변수에 QWEN_REVIEW_ASSETS_REPO를 설정하면(일반적으로 저장소 자체로) 리뷰 댓글이 캡처 PNG를 포함할 수 있습니다; 변수가 같은 저장소를 가리키면 작성하는 브랜치는 시각적 정리 워크플로에 의해 정리되며, 포크나 임시 대상은 자체 보존을 관리합니다.

게시는 게시와 정확히 동일하게 게이팅됩니다: 지정된 저장소가 없으면 게시하지 않으며, 권한이 없는 실행(효과적인 --comment 없음)은 submit이 거부하는 것과 동일한 방식으로 거부됩니다. 이미지 유형만 허용되며(SVG는 의도적으로 제외), 크기 제한이 있고, 각 파일의 바이트는 확장자가 주장하는 형식과 일치해야 합니다 — 잘못 레이블되거나 인식되지 않는 콘텐츠는 거부됩니다. 매니페스트가 푸시된 모든 파일을 기록합니다. 지정이 없으면 발견은 터미널과 저장된 보고서에서 로컬 파일 경로로 증거를 유지합니다 — 아무것도 깨지지 않으며, 댓글은 텍스트 전용으로 유지됩니다.

후속 조치

리뷰 후, 컨텍스트 인식 팁이 고스트 텍스트로 나타납니다. Tab을 눌러 수락하세요:

리뷰 후 상태동작
로컬 리뷰, --fix 미전달fix these issuesLLM이 각 발견을 대화형으로 수정
발견이 있는 PR 리뷰post commentsPR 인라인 댓글 게시 (재리뷰 없음)
PR 리뷰, 발견 0개post commentsGitHub에서 PR 승인 (LGTM)
로컬 리뷰, 모두 이상 없음commit변경 사항 커밋

참고: fix these issues는 로컬 리뷰에서만 사용 가능합니다. --fix와 같은 이유로 — PR 리뷰는 리뷰 후 worktree가 정리되므로 리뷰 후 대화형 수정이 불가능합니다; 대신 --comment 또는 post comments를 사용하여 발견을 게시하세요. --fix가 전달되면 발견에 이미 결과가 포함되어 있으므로 fix 팁이 제공되지 않습니다.

프로젝트 리뷰 규칙

프로젝트별로 리뷰 기준을 사용자 정의할 수 있습니다. /review는 다음 파일에서 규칙을 읽습니다(순서대로):

  1. .qwen/review-rules.md (Qwen Code 네이티브)
  2. .github/copilot-instructions.md (선호) 또는 copilot-instructions.md (폴백 — 하나만 로드됨, 둘 다 아님)
  3. AGENTS.md## Code Review 섹션
  4. QWEN.md## Code Review 섹션

규칙은 LLM 리뷰 에이전트(0-6)에 추가 기준으로 주입됩니다. PR 리뷰의 경우, 악의적인 PR이 우회 규칙을 주입하는 것을 방지하기 위해 기본 브랜치에서 규칙이 읽힙니다.

.qwen/review-rules.md 예시:

# Review Rules - All API endpoints must validate authentication - Database queries must use parameterized statements - React components must not use inline styles - Error messages must not expose internal paths

저장소 컨텍스트

저장소는 .qwen/review-context.json에 엄격한 JSON 매니페스트를 커밋하여 리뷰어에게 유한한 저장소별 가이드를 제공할 수 있습니다. medium 또는 high 노력에서, /review는 계획을 캡처한 후 매니페스트를 읽고 에이전트가 실행되기 전에 일치하는 가이드를 첨부합니다:

{ "version": 1, "label": "Example repository", "rules": [ { "paths": ["packages/*/src/**"], "domains": ["runtime"], "relatedPaths": ["packages/runtime/src/**"], "recommendedTests": ["npm run test:runtime"], "requiredConfigurations": ["debug"], "requiredAgents": ["test-matrix"], "unverifiedDimensions": ["Alternate runtime was not exercised"], "verificationNotes": ["Use the repository native test runner"] } ] }

규칙은 변경된 파일 중 하나가 paths glob 중 하나와 일치할 때 적용됩니다(*, ?** 세그먼트; 대소문자 구분). 일치하는 모든 규칙은 가이드를 병합합니다: 리뷰 에이전트를 위한 도메인 및 관련 파일, 빌드 앤 테스트 에이전트를 위한 권장 테스트 및 필수 구성, 추가 리뷰어 역할(선택된 노력과 토폴로지에서만 실행될 때 존중됨), 그리고 최종 리뷰가 미검증 차원으로 공개하는 증명 경계. 배열은 어떤 순서로든 작성될 수 있으며; 중복 항목은 거부됩니다.

PR 리뷰의 경우 매니페스트는 병합 기반에서 읽히므로 리뷰 중인 PR이 가이드를 선택적으로 켜거나 끌 수 없습니다; 로컬 리뷰는 현재 worktree에서 읽습니다. Low 노력 및 교차 저장소 리뷰는 저장소 컨텍스트를 건너뜁니다. 전체 계약과 신뢰 모델은 디자인 문서에 있습니다.

Issue Fidelity

버그 수정 PR의 경우, Issue Fidelity 에이전트는 PR 설명 텍스트에 의존하는 대신 이슈 증거를 직접 가져옵니다. GitHub의 강력한 closing-issue 메타데이터를 위해 gh pr view <pr> --repo <owner/repo> --json closingIssuesReferences를 사용한 후, 원본 보고서 및 토론을 위해 gh issue view <number> --repo <issue_owner>/<issue_repo> --json title,body,comments를 사용합니다 — --json 형식은 이슈 body(보고자의 원본 재현)를 포함하며, --comments만으로는 생략되는 부분이며, 이슈의 자체 저장소는 각 참조에서 읽힙니다(PR은 다른 저장소의 이슈를 닫을 수 있음). 이 에이전트는 PR 대상에서만 실행됩니다; 로컬 diff 및 파일 경로 리뷰는 건너뜁니다.

closingIssuesReferences는 발견 힌트이지 작성자가 올바른 이슈를 연결했다는 증명은 아닙니다: 비어 있지만 PR이 명백한 대상 이슈를 참조하면, 에이전트는 관련성을 판단한 후 여전히 가져옵니다. 가져온 이슈 텍스트는 신뢰할 수 없는 데이터로 처리됩니다(사실 추출, 포함된 지시 무시). 관련 이슈의 경우, 원본 재현, 관찰된 페이로드, 예상 동작 및 유지관리자 댓글이 PR이 올바른 문제를 수정하는지에 대한 최우선 증거로 처리됩니다.

이슈 증거가 업스트림 서비스나 제공자가 클라이언트 계약을 벗어난 잘못된 데이터를 반환한 것을 보여주면, 클라이언트 측 파서 또는 새니타이저 변경은 유지관리자가 명시적으로 방어적 우회 방법을 요청하지 않는 한 유효한 근인 수정으로 처리되지 않습니다. 잘못된 업스트림 출력을 재생하는 테스트는 우회 방법이 해당 형태를 처리한다는 것만 증명하며; 우회 방법이 아키텍처적으로 적절한지는 증명하지 않습니다.

증분 리뷰

이전에 리뷰된 PR을 리뷰할 때, /review는 마지막 리뷰 이후의 변경 사항만 검토합니다:

# 첫 리뷰 — 전체 리뷰, 캐시 생성 /review 123 # PR이 새 커밋으로 업데이트됨 — 새 변경 사항만 리뷰 /review 123

교차 모델 리뷰

/model을 통해 모델을 전환하고 같은 PR을 재리뷰하면, /review가 모델 변경을 감지하여 건너뛰지 않고 전체 리뷰를 실행합니다:

# 모델 A로 리뷰 /review 123 # 모델 전환 /model # 다시 리뷰 — 모델 B로 전체 리뷰 (건너뛰지 않음) /review 123 # → "Previous review used qwen3-coder. Running full review with gpt-4o for a second opinion."

캐시는 .qwen/review-cache/에 저장되며 커밋 SHA와 모델 ID를 모두 추적합니다. 이 디렉토리가 .gitignore에 있는지 확인하세요(.qwen/*와 같은 더 넓은 규칙도 작동합니다). 캐시된 커밋이 리베이스로 사라진 경우 전체 리뷰로 폴백합니다. High 노력 리뷰만 캐시를 참조하거나 작성합니다 — --effort low|medium 퀵 패스는 절대 “이미 리뷰됨”으로 간주되지 않습니다.

리뷰 보고서

동일 저장소 리뷰의 경우, 결과가 프로젝트의 .qwen/reviews/ 디렉토리에 Markdown 파일로 저장됩니다(교차 저장소 경량 리뷰는 보고서 저장을 건너뜁니다):

.qwen/reviews/2026-04-06-143022-pr-123.md .qwen/reviews/2026-04-06-150510-local.md

보고서에는 다음이 포함됩니다: 타임스탬프, diff 통계, 빌드/테스트 결과, 검증 상태가 포함된 모든 발견, 판정. 섹션 제목과 설명 산문은 출력 언어 환경설정을 따릅니다; 기술 식별자(SHA, 파일 경로, 게이트 이름, 발견 id)는 그대로 유지됩니다.

Medium 및 High 노력 리뷰는 또한 같은 스템을 가진 구조화된 JSON 동반 파일을 저장합니다(예: 2026-04-06-143022-pr-123.json). 표준화된 발견과 합성 판정을 데이터로 포함합니다. Qwen Code의 Web Shell은 해당 문서를 필터링 가능한 발견이 있는 대화형 리뷰 뷰로 렌더링합니다; Markdown 보고서는 사람이 읽을 수 있는 아카이브로 유지됩니다.

파이프라인의 결정적 부분 — 인수 파싱(qwen review parse-args) 및 이벤트/본문 결정(qwen review compose-review) — 은 프롬프트 텍스트가 아닌 테스트된 서브커맨드이므로, --effort 문법, --comment 강제, 판정 캡 및 다운그레이드 동작은 단위 테스트로 고정되며 모델에 따라 변하지 않습니다.

GitHub Enterprise: github.com이 아닌 호스트의 PR URL을 리뷰하면 해당 호스트의 모든 GitHub 호출이 라우팅됩니다 — 리뷰 서브커맨드(fetch-pr, pr-context, comment-status, presubmit)가 --host를 수용하고 코드에서 설정하므로, 잊힌 호스트가 조용히 github.com으로 리뷰를 재타겟팅할 수 없습니다.

모든 실행은 하나의 기계 판독 가능한 라인(Review complete: <target> — <disposition>)으로 끝나므로, 스크립트와 CI 래퍼가 단일 ^Review complete: 매치로 완료와 결과를 감지할 수 있습니다.

헤드리스 실행 (qwen review run)

/review는 대화형입니다. 스크립트나 CI 작업이 리뷰를 실행하고 결과에 따라 조치해야 하는 경우, 헤드리스 래퍼를 사용하세요:

qwen review run [target] [--json] [--fail-on request-changes] [--comment] [--quiet]

target은 PR 번호, PR URL 또는 파일 경로입니다; 로컬 작업 트리를 리뷰하려면 생략하세요. 명령은 이 빌드의 자체 CLI를 비대화형으로 실행하며(stdin이 닫힌 상태로, 슬래시 명령 감지가 유지됨), 자식의 진행 상황을 stderr로 스트리밍하고, 판정을 stdout에 출력합니다 — 또는 --json과 함께 전체 결과 객체를 출력합니다. 판정은 compose-review가 작성하는 아티팩트에서 읽힙니다(skill이 판정 권한으로 취급하는 동일한 JSON). 모델의 산문에서 파싱되지 않습니다.

종료 코드는 게이트가 읽어야 하는 계약입니다:

종료의미
0리뷰가 완료됨 (무엇을 결정했든)
1판정에 도달하지 못함 — 자식이 실패, 타임아웃 또는 합성 아티팩트를 남기지 않음
3REQUEST_CHANGES로 완료되었고 --fail-on request-changes가 설정됨 (옵인 차단)

3(이 아닌 2)은 게이트가 “리뷰가 차단 중”과 “도구가 고장남”을 구분할 수 있게 합니다 — yargs는 이미 1을 사용 오류에 사용합니다 — 출력 파싱 없이. --timeout-minutes(기본 120, 최소 1)는 중단된 리뷰를 종료하고 1로 종료하며, 명령 취소(Ctrl+C / SIGTERM)는 리뷰의 프로세스 그룹을 종료하여 고아로 만들지 않습니다.

시간 예산 실행은 또한 소프트 마감 시간을 내보낼 수 있어 리뷰가 아직 검증, 합성 및 게시할 시간이 있는 동안 오픈 엔디드 역감사 루프를 중지합니다: QWEN_REVIEW_DEADLINE_EPOCH는 실행이 종료될 Unix-초 순간이며, QWEN_REVIEW_DEADLINE_RESERVE_SECONDS(기본 3600; 0은 라운드 추정만 유지)는 마지막 라운드의 검증, compose-review 및 제출을 위해 남아 있어야 하는 꼬리입니다. 남은 예산이 또 다른 라운드와 해당 꼬리에 맞지 않으면, 라운드 빌더가 구축을 거부하고, 합성 판정은 잘린 감사를 공개합니다(그렇지 않으면-Approve 판정이 Comment로 제한됨). 누락되거나 잘못된 마감 시간은 리뷰를 게이트 없이 둡니다 — 외부 타임아웃이 여전히 실행을 제한합니다.

교차 파일 영향 분석

전용 교차 파일 추적기(에이전트 1c)가 이 순회를 처음부터 끝까지 담당합니다. 코드가 내보낸 함수, 클래스 또는 인터페이스를 수정할 때, 모든 호출자를 검색하고 호환성을 확인합니다:

  • 매개변수 수/타입 변경
  • 반환 타입 변경
  • 제거되거나 이름이 변경된 공개 메서드
  • 호환성을 깨는 API 변경

또한 생산자 방향을 순회합니다: diff가 추가하는 모든 필드, 옵션 또는 선택적 매개변수는 읽기 사이트로 추적됩니다 — diff가 건드리지 않는 파일도 포함합니다. 아무것도 채우지 않는 필드를 읽는 활성 코드 경로는 해당 기능이 조용히 아무것도 하지 않는다는 것을 의미하며, 이는 읽기 사이트에서 Critical로 플래그됩니다.

큰 diff(>10개 수정된 심볼)의 경우, 호출자 방향 분석은 시그니처 변경이 있는 함수를 우선시합니다; 생산자 방향은 예산 제한이 없습니다 — 변경되지 않은 시그니처가 바로 그 요점이기 때문입니다.

리뷰 예산

diff 크기에 대해 탄력적인 파이프라인의 부분은 diff 크기에서 확장되며, 확장은 diff 계획에 기록되어 모든 단계가 하나의 숫자를 읽습니다:

예산 필드범위확장 방식
inlineAngleslow 각도 수 (단계 3C)3 + 소스 라인 60개당 1개, 존재하는 6개로 제한
sweeplow의 갭 스윕 실행 여부소스 라인 25개 미만에서는 끄기
specialistCap에이전트 8 상한소스 라인 80개 미만에서는 0, 그렇지 않으면 2
verifyShard검증 에이전트당 발견 수8로 고정 — 검증자의 속성, diff의 속성이 아님

의도적으로 하지 않는 두 가지. 차원을 절대 확장하지 않습니다: 리뷰가 owe하는 에이전트는 명단에 의해 결정되며, 명단은 노력 수준을 읽으므로, 작은 diff도 보안 패스와 테스트 커버리지 패스를 받습니다. 그리고 diff 라인이 아닌 소스 라인을 읽습니다 — 900줄의 새 테스트와 함께 제공되는 40라인 프로덕션 변경은 작은 변경이며, 동일한 추론이 이미 territory-팬아웃 게이트를 지배합니다.

바닥이 왜 거기 있는가: 9라인의 오타 수정에서, 6개의 인라인 순회는 아무것도 없는 5개의 순회이며, 스윕 — 첫 번째 패스가 도달하지 못한 것을 찾는 새로운 리더 — 는 첫 번째 패스가 모두 도달했을 때 찾을 것이 없습니다. 에이전트 8의 바닥은 실질적인 것입니다: “하나의 도메인이 diff를 지배한다”는 것은 판단이며, 40라인에 대해 만들어진 판단은 우세한 도메인을 매번 찾습니다. 40라인은 보통 한 가지 것이기 때문입니다.

토큰 효율성

High 노력 파이프라인은 각 단계를 제한하지만(샤드 크기, 감사 라운드), 총 호출은 발견에 따라 확장됩니다 — ceil(F/8) 검증 샤드 — 그리고 3B에서는 청크 수에 따라(역감사는 라운드당 청크당 실행됨). 일반적인 3A 프로파일:

단계LLM 호출참고
리뷰 에이전트 (단계 3)14 (+0-2)병렬 실행; 교차 저장소는 에이전트 1c와 7 건너뛰기 (12), 로컬/파일은 에이전트 0 건너뛰기 (13)
샤드 검증 (단계 4)ceil(F/8)F = 발견 수; 검증 에이전트당 최대 8개, 함께 실행
반복 역감사 (단계 5)2-5 (3A); 라운드 × 청크 (3B)2회 연속 빈 라운드에서 중지 (상한 5); 3B는 라운드당 청크당 하나의 감사자로 팬아웃
합계~17-23 (~15-22)3A 동일 저장소: ~17-23 (일반적 ~17-19); 교차 저장소 또는 로컬/파일: ~15-22; 3B는 청크에 따라 확장 (DESIGN.md 참조)

대부분의 PR은 범위의 낮은 쪽으로 수렴합니다; 캡은 병리적 경우의 비용 폭주를 방지합니다. --effort low에서 리뷰는 완전히 인라인으로 실행됩니다 — 0 서브에이전트 호출 — 전체가 아닌 각도당 한 번씩 diff를 순회합니다.

플래그되지 않는 것

리뷰는 의도적으로 다음을 제외합니다:

  • 변경되지 않은 코드의 기존 이슈 (diff에만 집중)
  • 포맷터가 자동으로 정규화하는 스타일이나 포맷, 또는 코드베이스 규칙에 맞는 명명 — 하지만 린터나 타입 체커가 플래그할 실질적인 이슈(미사용 변수, 도달 불가능한 코드, 타입 오류)는 아니며, 이는 범위 내입니다
  • 실제 문제 없는 주관적인 “X를 고려해보세요” 제안
  • 버그나 위험을 수정하지 않는 경미한 리팩토링
  • 로직이 진정으로 혼란스럽지 않는 한 누락된 문서
  • 기존 PR 댓글에서 이미 논의된 이슈 (인간 피드백 중복 방지)

디자인 철학

침묵은 소음보다 낫다. 모든 댓글은 독자의 시간을 가치 있게 해야 합니다.

  • 무언가가 문제인지 확실하지 않으면 → 보고하지 않습니다
  • 모든 발견은 구체적인 실패 시나리오(트리거 → 잘못된 결과) 또는 구체적인 비용을 명시합니다 — 그렇지 못한 발견은 도달 전에 삭제됩니다
  • N개 파일에 걸친 같은 패턴 → 하나의 발견으로 집계
  • PR 댓글은 높은 신뢰도만 (high 노력, 검증된 리뷰에서만)
Last updated on