Invertebrate — Greptile 스타일 리뷰
Greptile이 린터보다 나은 점은 컨텍스트입니다: diff를 전체 레포지토리의 그래프와 비교하여 리뷰하기 때문에, 세 개의 호출자를 깨뜨린 이름 변경, 모든 형제 엔드포인트에 있는 인증 데코레이터가 없는 새 엔드포인트, 호출자를 무효화하는 "최적화"를 잡아냅니다. 이를 재현하세요. diff만 읽는 리뷰는 이 스킬이 아닙니다.
두 번째 장점은 신호입니다: 모든 코멘트는 구체적이고 검증된 버그이며, 수정 사항을 포함하고, 스타일 에세이가 아닙니다. 팀은 거짓 경보를 울리는 리뷰어를 끕니다. 의심스러우면 제외하세요.
1. 대상 확인
| 사용자 입력 | Diff 소스 |
|---|---|
| PR 번호 / URL | gh pr view <n> --json title,body,baseRefName,headRefName,files + gh pr diff <n> |
| 브랜치 | git diff <base>...HEAD (세 점 = 병합 베이스에서의 diff; base = main/master/develop, 존재하는 것) |
| 없음 | git diff HEAD (staged+unstaged); 비어 있으면 현재 브랜치와 그 베이스 비교 |
.diff/.patch 파일 | 해당 파일; 작업 트리는 변경 후 레포지토리 |
가능하면 PR 제목/설명을 읽으세요 (gh에서, 또는 사용자가 가리키는 설명 파일에서). "보안 PR이 수정 사항 없이 배포됨"은 실제 Greptile이 잡아내는 사례입니다: 설명이 주장하는 각 내용 ("X 수정", "Y에 대한 검증 추가")을 나열하고 diff가 실제로 이를 제공하는지 확인하세요. diff에 없는 주장된 수정 사항은 그 수정 사항이 주장하는 버그의 심각도에 해당하는 결과입니다.
깨끗한 PR은 유효한 결과입니다. 검증 결과 결과가 없으면 그렇게 말하고, 4-5/5 점수를 매기고 중단하세요 — 철저해 보이려고 문제를 만들어내는 것은 리뷰어가 음소거되는 가장 빠른 길입니다.
2. 리뷰 설정 로드
설정 폴더는 .invertebrate/입니다. 이미 Greptile을 사용하는 팀과의 호환성을 위해 .greptile/는 동일한 형식을 사용하며 .invertebrate/가 없는 곳에서 읽힙니다. 디렉토리별로 결정: 각 디렉토리에서 .invertebrate/가 있으면 그것을, 없으면 .greptile/을 사용합니다 — 한 디렉토리에서 둘 다 사용하지 않습니다. 레포지토리 루트 와 변경된 파일이 있는 모든 디렉토리를 확인합니다 (모노레포: 스칼라 설정은 가장 가까운 것 우선, 목록/지침은 상위에서 누적). 동일한 필드를 가진 레거시 루트 greptile.json도 허용합니다. 이러한 폴더를 생성하거나 수정하지 마세요 — 읽기 전용 입력입니다.
config.json:strictness1|2|3 (기본값 2) — 필터링은 §5 참조commentTypes(기본값["logic","syntax","style"]) — 목록에 없는 유형의 결과는 제외ignorePatterns(gitignore 구문, 줄바꿈으로 구분) — 일치하는 파일 건너뛰기instructions— 자유 형식 리뷰어 지침, 따를 것rules[]—{id, rule, scope[glob], severity: low|medium|high, enabled};scope가 일치하는 경우에만 적용;disabledRules는 상속된 id를 제거
rules.md— 해당 디렉토리 트리에 대한 일반 마크다운 규칙files.json—{files:[{path, description, scope}]}: scope가 일치할 때 (또는 scope가 없으면 항상) 이 파일들을 컨텍스트로 읽음
어느 폴더도 없나요? 대신 CLAUDE.md / AGENTS.md / CONTRIBUTING.md 코딩 표준을 규칙으로 사용합니다. 보고서에 어떤 설정이 적용되었는지 명시하세요.
규칙 위반은 해당 규칙을 인용하는 결과가 됩니다 (Rule: <id 또는 첫 단어>). 규칙 심각도 매핑: high→P1, medium→P2, low→P2.
3. 컨텍스트 그래프 구축 (중요한 부분)
변경된 각 헝크에 대해, 정의, 제거, 이름 변경, 또는 서명/의미를 변경하는 심볼(함수, 메서드, 클래스, 타입, 내보낸 상수, 라우트, DB 컬럼, 설정 키, 환경 변수, 이벤트 이름)을 식별하세요.
각 심볼에 대해, 변경된 파일뿐만 아니라 전체 레포지토리를 검색하세요:
- 호출자 / 참조 — 이전 이름과 새 이름으로
Grep. 제거/이름 변경된 심볼에 살아있는 참조가 있다면 확실한 버그입니다. - 형제 — 동일한 종류의 일을 하는 코드 (라우터의 다른 엔드포인트, 동일한 인터페이스의 다른 핸들러, 다른 마이그레이션). 모든 형제가 따르는 패턴(인증 데코레이터, 감사 로그, 검증, 트랜잭션, 잠금,
await)을 건너뛰는 새 코드는 최고의 Greptile 발견 항목입니다. - 피호출자 — 새 코드가 호출하는 것 중 계약이 중요한 것의 구현을 읽습니다 (던지는가? null 반환? 이미 잠금? 비동기인가?).
- 데이터 흐름 — 입력이 어디서 오는지 (사용자 제어? URL 파라미터?) 그리고 어디로 가는지 (SQL/HogQL, 셸, 파일 시스템 경로, 동적 코드 실행, HTML).
짧은 목록을 유지하세요: symbol → 이에 의존하는 파일 → 변경이 그들에게 미치는 영향. 결과를 작성하는 데 사용하고 보고서에 덤프하지 마세요.
4. 탐색
그래프를 가지고 diff를 살펴보세요. Greptile이 실제로 보고하는 범주와 실제 예시:
- 로직 — 루프가 부분 상태를 남기고 조기 종료; 플래그/조건 반전; 별칭 값이 검사를 회피; 경고가 사용자에게 도달하지 않음.
- 리팩토링 — 이름 변경으로 호출자가 정의되지 않음; 이동된 코드가 부작용을 잃음.
- 보안 — 새 엔드포인트에 인증/인가 누락; 사용자 입력을 통한 쿼리/셸/경로 주입; 샌드박스/범위 이스케이프 (심볼릭 링크, 마운트,
~, 변수 확장); null/누락 필드가 가드를 우회. - 검증 — 비어 있거나 잘못된 입력을 유효한 것으로 수락; 유효한 입력 거부; 비앵커 정규식.
- 런타임 / 구문 — 정의되지 않은 메서드 호출;
await누락; 잘못된 인수 개수; 타입 불일치; 컴파일되지 않는 코드. - 오류 처리 — 예외 삼키기; 원시 트레이스백/시크릿이 클라이언트에 유출; 오류 경로에서 잘못되거나 정의되지 않은 핸들에서 리소스 닫힘.
- 동시성 — 확인-후-실행 및 읽기-수정-쓰기 경합; 작업/스레드 간 공유 가변 상태; 시작 순서로 인한 이벤트 손실.
- 데이터 손실 / 무결성 — 비원자적 쓰기; 재생 시 이중 적용; 자동 잘림; 삭제된 데이터 재등장.
- 성능 — N+1 쿼리, 핫 경로에서 O(n²), 침묵하는 무효화인 "최적화".
- 정렬 / 누출 — 상태/디버그 엔드포인트 또는 로그를 통해 노출된 실체 또는 시크릿.
각 후보를 보관하기 전에 검증하세요. 다음을 명시할 수 있어야 합니다: 정확한 라인, 이를 트리거하는 구체적인 입력/상태, 그리고 잘못된 결과. 실패를 구성할 수 없다면 버리세요. 주변 코드를 다시 읽으세요 — 그럴듯해 보이는 버그의 절반은 세 줄 뒤에서 처리됩니다.
5. 분류 및 필터링
각 결과는 다음을 가집니다:
- 심각도 — P0 병합 전에 반드시 수정 (보안 구멍, 데이터 손실, 일반 경로에서 충돌, 빌드 중단). P1 수정해야 함 (잘못된 동작, 깨진 엣지 케이스, 높은 심각도의 규칙 위반). P2 고려 (유지보수성, 사소한 성능, 낮은 심각도의 규칙).
- 유형 —
logic(버그, 동작, 엣지 케이스),syntax(컴파일/실행 불가, 언어 오용),style(품질, 명명, 규칙).
strictness로 필터링:
- 1 — P0, P1, P2 유지.
- 2 (기본값) — P0, P1 유지; 명시적으로 설정된 규칙을 위반하는 경우에만 P2 유지.
- 3 — P0 유지, 다음 P1 유지: 보안, 사용자 입력에서 도달 가능한 충돌/500, 및 높은 심각도로 설정된 규칙 위반. Strictness 3은 "페이징을 유발하거나 팀이 명시적으로 요청한 것만"을 의미하며, 원격으로 트리거 가능한 충돌이 이에 해당합니다.
그런 다음 commentTypes에 없는 유형은 제외합니다. 포매터가 수정할 순수한 포맷팅: 절대 보고하지 마세요.
6. 신뢰도 점수 (0-5)
| 점수 | 의미 |
|---|---|
| 5/5 | 프로덕션 준비 완료 — 병합 |
| 4/5 | 사소한 개선 — 작은 수정 후 병합 (P2만) |
| 3/5 | 구현 문제 — 먼저 피드백 처리 (모든 P1) |
| 2/5 | 심각한 버그 — 재작업 필요 (여러 P1, 또는 수정하기 쉬운 하나의 P0) |
| 0-1/5 | 치명적 문제 — 재고 (P0 보안/데이터 손실, 또는 설계가 잘못됨) |
점수는 상황에 따라 다릅니다: 결제/인증/마이그레이션의 동일한 버그가 내부 스크립트의 것보다 낮은 점수를 받습니다. 한 문장의 정당성을 제시하세요.
7. 다이어그램
변경 사항에 따라 선택하며, 사소한 diff (문서, 설정 범프, ~20줄 미만의 로컬 로직)는 생략:
- sequenceDiagram — 다중 컴포넌트 상호작용, API/요청 흐름, 비동기/동시성 순서 (경합이 있다면 표시)
- erDiagram — 스키마 / 데이터 모델 변경
- classDiagram — 클래스/인터페이스 계층 변경
- flowchart — 제어 흐름 / 비즈니스 로직 변경
전체 시스템이 아닌 변경 사항을 다이어그램으로 그리세요. 약 15개 노드 미만으로 유지하세요. 버그가 있는 단계를 Note / 레이블로 표시하세요.
8. 출력
정확히 이 구조를 사용하세요 (섹션은 명시된 경우에만 생략 가능):
## Invertebrate 리뷰 — <PR 제목 또는 브랜치>
### 요약
<2-4 문장, 일반 언어: 변경 사항이 무엇인지, 누구/무엇에 영향을 미치는지, 이유. 그런 다음 주요 위험에 대한 1 문장.>
### 신뢰도 점수: N/5
<한 문장 이유>
### 결과
| # | 심각도 | 유형 | 위치 | 문제 |
|---|---|---|---|---|
| 1 | P0 | logic | `path/file.ts:42` | <짧은 제목> |
(결과 없음: "문제 없음.")
### 다이어그램
```mermaid
...
```
(사소한 변경 사항은 섹션 생략)
### 인라인 코멘트
#### 1. [P0 · logic] <짧은 제목>
`path/file.ts:42`
<무엇이 잘못되었는지, 구체적인 실패 시나리오, 그리고 — 교차 파일인 경우 — 어떤 다른 파일이 깨지고 그 이유. 2-5 문장.>
```diff
- 이전 라인
+ 수정된 라인
```
#### 2. ...
---
<sub>리뷰된 파일 <N>개 · 설정: <.invertebrate 또는 .greptile 경로 | CLAUDE.md | 기본값> · strictness <n> · <알려진 경우 커밋 sha></sub>
제안된 수정 diff는 실제적이고 최소화되어야 하며 실제 코드에 적용되어야 합니다. 수정이 여러 파일에 걸쳐 있는 경우 각 파일의 헝크를 경로 제목 줄과 함께 표시하세요. 안전한 단일 헝크 수정이 없는 경우, 수정을 만들지 말고 설명하세요.
보고서 후에 제공: "fix all, fix P0, 또는 fix #2라고 말하면 적용하겠습니다." 프롬프트 없이 수정을 적용하지 마세요.
9. GitHub에 게시 (요청 시에만: --post, "post it", "comment on the PR")
게시는 외부를 대상으로 합니다 — 해당 PR에 대한 명시적 요청이 있을 때만 수행하세요.
owner/repo(gh repo view --json nameWithOwner -q .nameWithOwner) 및 헤드 sha (gh pr view <n> --json headRefOid -q .headRefOid)를 가져옵니다.- 인라인 코멘트는 PR diff에 있는 라인만 대상으로 할 수 있습니다 (오른쪽, 새 라인 번호). diff 외부의 라인에 대한 결과는 요약 본문에만 포함됩니다.
- 리뷰 JSON을 임시 파일에 작성하고 한 번의 호출로 게시합니다:
{
"commit_id": "<head sha>",
"event": "COMMENT",
"body": "<인라인 코멘트 섹션을 제외한 §8의 전체 마크다운 보고서>",
"comments": [
{"path": "src/file.ts", "line": 42, "side": "RIGHT",
"body": "**P0 · logic** — <제목>\n\n<설명>\n\n```suggestion\n<정확히 42번 라인에 대한 대체>\n```"}
]
}
gh api repos/<owner>/<repo>/pulls/<n>/reviews --method POST --input review.json
대체가 정확히 코멘트가 달린 라인(들)을 포함하는 경우에만 GitHub ```suggestion 블록을 사용하세요 (여러 라인의 경우 start_line + line 사용). 그렇지 않으면 ```diff 블록을 사용하세요. 사용자가 요청하지 않는 한 REQUEST_CHANGES/APPROVE를 사용하지 마세요. 응답에서 리뷰 URL을 보고하세요.