Pre-write and review gates for code changes. Pre-write: before creating any new function, helper, type, or file — 만들어줘, 추가해줘, 구현해줘, 새 파일, 리팩토링, new helper/component. Post-write: after finishing a change — 다 했어, 리뷰해줘, 검토, review my change. Prevents duplicate reimplementation and enforces the review checklist including run-verification (scaled to change size/runtime surface — no full verification for small mechanical changes) and doc sync.
Scanned 9/5/2026
Install to Claude Code
npx -y skills add jx-hxxx/hi-vibe --skill write-gate --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Write Gate?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/jx-hxxx-write-gate)More formats (shields.io, HTML) on the badges page.
---
name: write-gate
description: >-
Pre-write and review gates for code changes. Pre-write: before
creating any new function, helper, type, or file — 만들어줘, 추가해줘,
구현해줘, 새 파일, 리팩토링, new helper/component. Post-write: after
finishing a change — 다 했어, 리뷰해줘, 검토, review my change.
Prevents duplicate reimplementation and enforces the review checklist
including run-verification (scaled to change size/runtime surface — no
full verification for small mechanical changes) and doc sync.
user-invocable: false # 사용자 표면은 /hi-vibe:* 명령 10개다. 스킬까지 슬래시 메뉴에 나오면 16개가 되어 "외울 게 적다"는 약속이 깨진다. Claude의 자동 호출은 그대로 유지된다.
---
# write-gate
> **답변 언어**: 이 지침은 한국어로 쓰였지만, **출력은 항상 사용자가 대화에서 쓰는 언어**를 따른다 (한국어→한국어, 영어→영어). 기존 문서·코드에 언어가 있으면 그쪽을 우선한다.
## 먼저: 안전벨트가 매여 있는지 (두 모드 공통, 세션당 한 번)
**훅은 조용히 실패한다**(fail-open) — 망가져도 에러조차 안 뜬다. 그래서
"훅이 죽었나"를 훅으로는 알 수 없다(자기가 안 도니까). 확인할 수 있는 건
**훅과 무관하게 도는 이 스킬 층뿐**이다. 이 스킬은 사용자 말("만들어줘",
"다 했어")에 걸리므로 훅이 전멸해도 살아 있다.
이 스킬이 이번 세션에서 처음 걸릴 때 한 번만:
`python3 "${CLAUDE_PLUGIN_ROOT}/scripts/doctor.py" --root <repo> --quick`
JSON `state` 하나로 갈린다. **`alive`면 아무 말도 하지 마라** — 정상을
보고하는 건 잔소리다.
- **`alive`** → 침묵. 그대로 아래 작업을 진행한다.
- **`stale` / `never-ran`** → 훅이 이 세션에서 안 돌았다. 한 줄로 알린다:
"hi-vibe 훅이 이 세션에서 안 돌고 있습니다(마지막 기록 N시간 전). 방금
플러그인을 업데이트했다면 Claude Code를 다시 시작하면 되고, 아니면
`/hi-vibe:doctor`로 확인하세요." **막지는 마라** — 훅 없이도 이 스킬은
동작하므로 하던 일은 그대로 진행한다.
- **`not-initialized`** → 이 폴더는 hi-vibe가 꺼져 있다. 한 번만 알린다:
"이 폴더는 hi-vibe가 꺼져 있습니다(자동 감지·기록 없음). 쓰시려면
`/hi-vibe:init`, 안 쓰실 거면 그렇다고 말씀만 주세요." 사용자가 "안
쓴다"고 하면 `.hi-vibe/optout` 파일을 만들어라(`mkdir -p .hi-vibe &&
touch .hi-vibe/optout`) — 그러면 훅은 계속 꺼진 채로, 다시 묻지 않는다.
**여기서 마음대로 init하지 마라.** opt-in은 사용자가 정한다.
- **`optout`** → 침묵. 이 폴더에서 다시는 묻지 않는다.
**`tracked_env`가 비어 있지 않으면** `state`와 별개로 **반드시 알린다**(세션당
한 번). 목록에 있는 `.env` 파일이 Git에 올라가 있다는 뜻이고, **비밀키 검사는
`.env`를 검사 대상에서 빼므로 이건 훅도 `check`도 못 잡는다.**
> `.env`가 Git에 올라가 있습니다(`<파일들>`). 비밀키 검사는 `.env`를 안 보기
> 때문에 이건 아무 검사에도 안 걸립니다. `git rm --cached <파일>` 후
> `.gitignore`에 넣으세요. **이미 push했다면 히스토리에 남아 있으니 그 키는
> 폐기(rotate)해야 합니다.**
파일을 열어 보지 마라 — 내용을 읽는 순간 대화창이 유출 통로가 된다. 지워주지도
마라(사용자가 결정한다). 알리고 하던 일을 계속한다.
조회 자체가 실패하면(스크립트 없음·python3 없음) 조용히 넘어간다 — 확인을
못 한 것이 작업을 막을 이유는 아니다.
## Mode: find (코드 작성 전)
새 function/helper/type/파일을 만들기 전에, 순서대로:
1. **존재 확인**: repo-xray로 그럴듯한 이름 2~3개를 검색한다.
`python3 "${CLAUDE_PLUGIN_ROOT}/skills/repo-xray/scripts/audit.py" find <name> --root <repo>`
결과의 스캔 범위를 인용해 판정한다 (repo-xray 계약).
2. **외부 API 근거 확인**: 새 코드가 외부 라이브러리/프레임워크의
API를 사용하거나 버전에 민감한 부분(파라미터명, 옵션, 반환 형태,
설정 키)을 다루면, 기억으로 쓰지 않는다. context7 MCP가 연결되어
있으면 `resolve-library-id` → `query-docs`로 최신 문서를 확인하고,
없으면 공식 문서를 WebFetch로 확인한다. 둘 다 불가하면 추정임을
밝히고 쓴다 (grounded-answers 계약). 프로젝트 내부 코드만 다루는
경우 이 단계는 건너뛴다.
3. **위치 확인**: 대상 폴더의 `MODULE.md`를 읽는다 — 이 코드가 그
폴더의 책임에 맞는가? 안 맞으면 맞는 폴더를 찾거나 사용자에게 묻는다.
4. **SSOT**: 공용 유틸/타입/shape은 지정된 공용 위치에 한 번만.
로컬 복사본을 만들지 않는다.
5. **배치**: 새 파일은 위계(도메인/레이어)에 맞게. 루트에 평탄하게
쌓지 않는다. 처음부터 파일을 나눈다 — 한 파일에 몰지 않는다.
6. **경계 선언**: 이 코드가 import해도 되는 것 / 이 코드를 import해도
되는 곳을 한 줄로 선언하고 시작한다.
판정은 셋 중 하나: **재사용** (기존 것 그대로) / **확장** (기존 것
수정) / **신규** (근거: 스캔 범위 내 없음).
### 요청 범위 밖을 발견하면 — 고치지 말고 물어라
코드를 보다 보면 요청과 무관한 문제가 눈에 띈다. 그건 좋은 발견이지만
**거기서 손대기 시작하면 "한 줄 고쳐줘"가 기능 추가가 된다.** 실제 사례:
"사이트에 적어줘"라는 요청으로 시작해 봇 기능 신설까지 번졌고, 그 새 기능의
버그를 잡느라 작업이 배로 늘었다.
- **요청한 것만 한다.** 밖에서 발견한 건 **한 줄로 보고하고 사용자가 정한다**:
"사진이 담겼는지 아무도 모르는 상태예요. 지금 고칠까요, 따로 볼까요?"
- 사용자가 "같이 해줘"라고 하면 그때 한다. **묻는 데 드는 건 한 줄이고,
안 물으면 몇 배가 든다.**
- 예외는 **요청한 것을 하려면 반드시 통과해야 하는 것**뿐이다(그게 막혀서
요청 자체가 불가능한 경우). 그땐 왜 필요한지 밝히고 진행한다.
이건 "발견하지 마라"가 아니다. 발견은 하되 **범위를 넓히는 결정은 사용자
것**이라는 뜻이다.
## Mode: review (코드 작성 후)
**플래그가 없다.** 범위·깊이·병렬 여부는 아래 순서대로 **기계가 준 숫자를
보고 여기서 판단한다** — 사용자에게 고르라고 묻지 않는다. 사용자는 무엇을
켜야 좋은지 알 수 없고, 물어보는 순간 제일 좋은 기능이 안 켜진 채로 끝난다.
### 1. 범위 (헬퍼가 코드로 정확히 정한다 — AI가 해시를 세지 않는다)
`python3 "${CLAUDE_PLUGIN_ROOT}/skills/write-gate/scripts/review_scope.py" list --root <repo>`
→ `scope`·`scope_label`(어느 계단에서 잡았나), `to_review`(아직/다시 봐야 할
파일), `skipped`(이미 봤고 그 뒤로 안 바뀐 것), `sizes`·`total_changed_lines`·
`file_count`(규모), `fingerprint`.
- **`deleted`가 비어 있지 않으면** 그 파일들은 열어볼 수 없다. 대신
**남은 호출부**를 찾아라 — `import`·호출·문자열 경로. AI가 파일을 통째로
지우고 부르던 곳을 안 고친 경우가 실제 위험이고, 지운 코드는 리뷰 대상에서
빠지기 쉬워 아무도 안 본다. 남은 참조가 있으면 그 자리에서 고친다.
- **`to_review`가 비었으면**(그리고 `deleted`도 비었으면) "새로 리뷰할 변경이
없습니다 (이미 본 것 N개는 그대로)"만 알리고 끝낸다 — 억지로 훑지 않는다.
- **`scope`가 `uncommitted`가 아니면** 무엇을 보고 있는지 한 줄로 밝힌다:
"안 커밋한 변경이 없어서 <scope_label>을 봅니다." 커밋·푸시했다고 리뷰가
죽지 않게 계단으로 내려가지만, 사용자는 지금 뭘 보는지 알아야 한다.
- **사용자가 범위를 말했으면**(예 "로그인 쪽만", "3일치", "이 파일만") 그쪽을
우선한다. 헬퍼 범위보다 사용자 말이 위다.
- **git 저장소가 아니면** 범위를 못 구한다 — 그 사실을 알리고, 이번 세션에
만진 변경을 사용자와 확인해 아래 체크리스트로 처리한다.
### 2. 규모가 크면 병렬 (묻지 말고 알리고 진행)
**임계값을 코드에 박지 않는다** — 기계는 `total_changed_lines`·`file_count`만
주고, 판단은 여기서 한다. 어림잡아 **파일이 여러 개이면서 수백 줄 이상**이면
병렬로 간다(정확한 컷은 상황 판단). 순차는 뒤로 갈수록 얕아지는데, 그걸
감수하고 순차를 고를 사용자는 없다.
병렬로 갈 때는 **고르라고 묻지 말고, 무엇을 왜 하는지와 대가를 한 줄로 알리고
그대로 진행한다**:
> 변경이 큽니다 (12파일 1,430줄). 얕아지지 않게 병렬로 봅니다. 토큰을 더 씁니다.
`python3 "${CLAUDE_PLUGIN_ROOT}/skills/write-gate/scripts/review_scope.py" chunk <N> --root <repo>`
로 줄 수 균형이 맞은 `buckets`(파일 그룹) N개를 받아, **각 버킷마다 Agent
도구로 리뷰어를 하나씩 병렬 소환**한다. 각 리뷰어에게 "이 파일 묶음에 아래
체크리스트를 적용하고 ✅/⚠️ 요약을 돌려달라"고 시키고, 결과를 모아 통합
보고한다. N은 규모에 맞게(대개 3~6), 버킷 수를 넘기지 않는다. 규모가 작으면
이 단계를 건너뛰고 그냥 순차로 간다.
사용자가 "가볍게 봐줘"(영어로는 "keep it light" / "light review")라고 했으면
병렬도 fresh-eyes도 생략하고 체크리스트만 돌린다 — 끄는 건 플래그가 아니라
말로 한다. 영문 랜딩이 이 말을 escape hatch로 안내하므로 영어 표현도 받는다.
### 3. 체크리스트
`to_review`의 각 파일(=기능 덩어리)에 아래를 적용한다(병렬이면 각 버킷
안에서). 각 항목을 ✅/⚠️로 보고한다. ⚠️는 이유와 수정 방법을 붙인다.
비례 원칙: 이번 변경과 무관한 항목은 "해당 없음" 한 마디로 통과시켜라
— 형식적 도배도, 통째 생략도 금지. 단 9·10(필수)은 항상 답한다. 파일이
많으면 파일별 한두 줄 요약(✅/⚠️)으로 압축하고 ⚠️만 펼치되, 실행 검증·문서
동기화(9·10)는 전체에 대해 마지막에 한 번 종합해 답한다.
**자기 점검 루프 (핵심)**: ⚠️는 보고하고 끝내는 게 아니다. 그 자리에서
고친 뒤 해당 항목을 다시 검사해 ✅로 만든다 — 통과할 때까지 반복.
바로 못 고치는 ⚠️만 남기되, "왜 지금 못 고치는지 + 언제/어떻게 고칠지"를
사용자에게 명시한다. 체크리스트는 흠집 목록이 아니라 흠집을 없애는
루프다.
**단, 고치기 전에 어느 쪽인지 가른다 (필수):**
- **원래 요구사항을 어긴 결함** → 그 자리에서 고친다. 예: "일부만 저장됐는데
전부 성공이라고 표시한다" — 사용자가 요청한 적 없는 거짓 보고이므로 물어볼
게 없다.
- **새 동작·알림·정책이 필요한 것** → **고치지 말고, 발견 사실과 대안을
보고하고 확인받는다.** 예: "권한이 없으면 회의당 한 번 안내 메시지를
보내자" — 없던 사용자 경험을 새로 만드는 결정이다.
가르는 기준 한 줄: **이걸 고치면 사용자가 여태 못 보던 화면·메시지·규칙이
새로 생기는가?** 생기면 묻는다.
이 구분이 없으면 리뷰의 자동 수정 루프가 **기능 확장으로 번진다**. 그건 이
플러그인이 막으려는 증상("헷갈리는 결정을 사용자에게 묻지 않고 임의 진행")을
리뷰가 직접 저지르는 것이고, `fresh-eyes`가 잡으라고 있는 스코프 크립을
같은 리뷰가 만들어내는 자기모순이다.
1. 에러 삼킴을 새로 추가하지 않았는가 (root-cause-first 금지 패턴)
2. 중첩 ≤ 3단계 (넘으면 early return / guard clause로 평탄화)
3. 크기 상한: 함수 ~50줄, 파일 ~400줄. 파일은 `list`의 `oversized`를 그대로
쓴다(눈으로 세지 마라). **`lines - growth`가 400 이하면 이번에 처음 넘긴
것 — 그것만 ⚠️로 펼쳐 분리를 제안한다.** 원래 넘어 있던 파일은 한 줄로
축약하고(`kis_client.py 686줄, 이번 +26`), `growth`가 음수면(줄인 것)
아예 짚지 마라. 같은 경고를 매번 똑같이 펼치면 쌓여서 신호가 아니게
된다. **기준 400은 그대로다 — 무르게 하는 게 아니라 반복을 줄이는 것이다.**
4. 중복 생성 vs 교체: 기존 코드를 대체했다면 옛 버전을 지웠는가,
호출부를 옮겼는가, 죽은 코드/주석 처리 코드가 남지 않았는가
5. 안 쓰는 re-export/import 잔재가 없는가
6. 순환 의존을 새로 만들지 않았는가 (의심되면 repo-xray scan)
7. 숨은 결합을 새로 만들지 않았는가 — 전역 상태 공유, 초기화 순서
의존, import 부수효과, 암묵 계약(호출 순서/형태를 문서 없이
가정), 한 모듈로의 과도한 fan-in/fan-out 쏠림
8. 테스트: 문자열 비교가 아니라 동작을 검증하는가, mock은 외부
경계에서만인가, 엣지케이스(빈 값/None/0/경계값/실패 경로)를
먼저 다뤘는가, 테스트 통과용 방어코드를 프로덕션에 넣지 않았는가
9. **실행 검증 (변경 크기·런타임 표면에 비례)**: 검증 강도는 이번
변경이 실제로 만든 위험에 맞춘다 — **작은 변경에 풀 검증을 요구하지
않는다.** 세 등급으로 판단한다:
- **런타임 표면 없음** (문서·주석·순수 포맷, 동작이 그대로인 설정/
이름 변경) → 실행 검증 불필요. "런타임 표면 없음"으로 통과하고,
앱을 억지로 띄우지 않는다.
- **작은·국소 변경** (기존에 검증된 패턴을 그대로 복제, script 태그·
설정 한 줄 추가, 좁은 범위 수정) → **가벼운 검증으로 충분하다**:
구문/임포트 체크(`node --check`·import), 파일이 실제로 서빙/로드
되는지 확인 정도. 풀 브라우저 E2E나 여러 조건 렌더는 불필요.
- **동작을 바꾸는 변경** (로직·API·스키마·새 기능·버그 수정) →
실제로 실행해 동작을 관찰한다 — 테스트 실행, 앱 구동, 버그면 원래
재현 케이스 재실행. 작성자가 눈으로 읽는 것은 검증이 아니다.
**UI·CSS·레이아웃·스타일 변경 → 사용자가 검증 루프다 (특례)**:
생김새·간격·정렬·색·반응형 같은 시각적 변경은 위 등급과 별개로,
**에이전트가 브라우저(Playwright 등)를 띄워 자가 검증하지 않는다.**
사용자가 앱을 직접 띄워 보고 있으면 화면을 보는 것 자체가 검증이고,
에이전트가 딴 브라우저를 또 띄우는 건 이중일이다(레이아웃이 어긋나면
사용자가 즉시 본다). 대신: ①변경하고 ②캐시버스팅(`?v=N`)했으면 그
사실과 함께 ③"새로고침(⌘⇧R) 후 무엇을 확인하면 되는지"를 한 줄로
알려주고 사용자에게 넘긴다. 같은 화면을 여러 상태(모드·화면폭·로딩중)로
반복 렌더해 자가 확인하는 것은 금지. CSS 값은 브라우저로 픽셀을 실측해
상수로 박지 말고(예: `min-height:529px`는 행 높이가 바뀌면 깨지는 땜빵)
콘텐츠 기반(행 수·`rem`·내용에 맞는 예약)으로 견고하게 잡는다. **예외**:
사용자가 "브라우저로 확인해줘"라고 명시했거나, 특정 화면폭에서만 깨지는
회귀처럼 눈으로 못 잡고 렌더로만 재현되는 경우 → 그때만 최소 렌더.
**최소 충분 원칙 (과잉검증 금지)**: 한 번의 관찰로 확인되면 멈춘다.
같은 것을 여러 조건(화면 폭·브라우저·반복 실행)으로 다시 확인하거나,
요청 범위 밖 코드까지 파고들어 검증하지 않는다 — 그건 꼼꼼함이 아니라
시간 낭비다(사용자가 답변 하나에 12분을 기다리게 만든다). 해당 등급에
필요한 실행을 못 했다면 "실행 검증 안 됨"과 이유를 명시한다 —
"될 겁니다"는 금지 (grounded-answers 계약).
10. **문서 동기화 (필수, 자동)**: 폴더 책임이 바뀌었으면 → 해당
`MODULE.md`를 같은 턴에 갱신. `CLAUDE.md`는 **코드만 봐서는 모를 것**이
바뀌었을 때만 건드린다 (새 제약·새 함정·기록할 결정·새로 만든
MODULE.md 포인터). 파일을 옮긴 것은 여기 해당하지 않는다 — 구조 변경
때마다 CLAUDE.md를 고치게 만들면 결국 거짓말하는 문서가 된다. **실질 변경이면 → 사용자가 `/hi-vibe:log`를 치기를
기다리지 말고, 지금 이 자리에서 `CHANGELOG.md`의 `[Unreleased]`에
직접 항목을 추가한다** (docs-keeper의 log 모드 규칙을 따른다:
`date '+%Y-%m-%d %H:%M'`로 실제 시각, Added/Changed/Fixed/Removed로
분류, 한 변경당 한 줄). **단 "실질 변경"만** — 동작·API·스키마·의존성·
설정 변화. 오타·포맷·주석·동작 동일한 순수 리팩토링은 적지 않는다
(CHANGELOG를 노이즈로 채우지 않는다). `init`이 CHANGELOG를 만들므로
보통은 이미 있다 — 없으면 `docs-keeper`의 템플릿으로 만들고 적는다
(기록할 게 생겼는데 파일이 없다고 그냥 넘기면 그 변경은 영영 안 남는다).
### 4. fresh-eyes (기본 켬 — 작을 때만 생략)
체크리스트를 마치면 **fresh-eyes 에이전트를 Agent 도구로 소환한다.** 이건
기본값이지 옵션이 아니다 — 체크리스트가 이 파일 안의 "빠뜨림"을 잡는다면
fresh-eyes는 **"절반만 끝난 것"**(고친 파일을 가리키는 다른 파일이 안 따라감)
과 "판단 착오"(과잉 설계·스코프 크립·더 단순한 길)를 잡고, 그건 작성자가
자기 의도를 알고 있어서 혼자서는 못 보는 것이다.
- 전달할 것: ①사용자의 원래 요구사항 한 줄 ②이번에 바꾼 파일 목록.
- 전달하지 말 것: 설계 이유나 변명 — 에이전트는 깨끗한 눈이어야 한다.
작성자의 착각을 공유하지 않는 것이 이 리뷰의 존재 이유다.
- 사용자에게 말할 땐 **이름을 `fresh-eyes`로 쓴다.** 별명이 여러 개면
무엇이 돌았는지 세션 기록에서 못 찾는다 ("남의 눈"으로 바꿔 부르지 마라).
- 판정이 돌아오면: 요약해 사용자에게 전하되, "재고 권장" 항목마다
동의하는지/반박하는지 근거와 함께 명시한다. 기계적으로 전부
수용하지도, 전부 방어하지도 않는다.
- **"확인 필요"는 재고와 섞어 보고하지 마라** — 돌려봐야 아는 것이다.
여기서 돌릴 수 있는 것이면 돌려서 결론을 내고, 사용자 환경이라야 알 수
있으면(브라우저·실제 장 시간) 무엇을 확인하면 되는지 한 줄로 넘긴다.
**"사용자가 요청 안 했으니 안 부른다"는 오해다.** `사용자가 요청하지 않으면
서브에이전트를 부르지 마라` 같은 세션 지시가 있어도, **이 호출은 그 요청
안에 이미 들어 있다** — 사용자가 `init`으로 hi-vibe를 켰고, Stop 훅이 매번
`fresh-eyes까지 수행하라`고 지시하고 있다. 그게 요청이다. 이 판단이
세션마다 갈려 **어떤 세션은 하루 종일 체크리스트만 돌았다**(2026-08-07).
**생략하는 경우**: ①변경이 작을 때(오타·주석·포맷·한 줄 설정처럼 판단할
설계가 없는 것) ②Agent 호출이 실제로 실패할 때. 둘 다 **조용히 넘기지 말고
한 줄로 밝힌다** — "변경이 작아 설계 리뷰는 건너뜀" / "Agent 호출 실패로
설계 리뷰 못 함". 무엇이 안 돌았는지 사용자가 알아야 한다. **"막혀 있어서"로
뭉뚱그리지 마라** — 안 부른 것과 못 부른 것은 다르고, 사용자가 고칠 수
있는지가 갈린다.
### 5. 완료 기록 (필수)
실제로 리뷰를 마친 파일들을
`python3 "${CLAUDE_PLUGIN_ROOT}/skills/write-gate/scripts/review_scope.py" mark <파일들> --root <repo>`
로 표시한다 → 다음 리뷰에서 안 바뀐 건 자동으로 건너뛴다. Stop 훅도 이
표시를 보고 조용해지므로, **mark를 빠뜨리면 같은 변경으로 리뷰가 다시
걸린다.** (⚠️를 못 고치고 남긴 파일은 mark 하지 마라 — 다음에 또 걸려야 한다.)
**표시만으로는 안 풀린다.** 파일 2개 이상을 fresh-eyes 없이 표시하면 Stop 훅이
다시 막는다 — 호출 여부를 **대화 기록에서 직접 세기 때문에** 자기신고로는 못
넘긴다. 4번을 정말로 생략해야 하는 상황(작은 변경·Agent 호출 실패)이면 그
사실을 한 줄로 밝혀라. 같은 파일로 두 번은 안 막는다.
`skipped`가 있었으면 "이미 리뷰됨(변경 없음): N개" 한 줄로 밝힌다.
### 보고는 짧게 — 한 번 말한 것을 또 말하지 마라
리뷰가 값을 하려면 사용자가 **읽어야** 한다. 길면 안 읽는다.
- **같은 결함을 두 번 설명하지 마라.** 체크리스트 ⚠️와 마무리 요약에
같은 내용을 반복해 적는 일이 실제로 일어난다. **가장 구체적인 자리 한
곳에만** 쓰고 나머지는 짧게 가리킨다. **단 `👋` 줄은 여기서 뺀다** —
그건 설명이 아니라 **세는 표시**라, 내용이 체크리스트에 이미 있어도
아래 세 조건이 맞으면 붙인다.
- **✅는 나열하지 마라.** "그 외 항목 통과" 한 줄로 묶고 ⚠️만 펼친다.
파일이 많아도 마찬가지다.
- **시간은 묻기 전엔 말하지 말고, 물으면 재서 답하라.** 안 물었는데 붙이는
소요 시간 해명은 노이즈다. 하지만 **"왜 이렇게 오래 걸렸냐"고 물으면
추측하지 말고 실제 시각을 재서 구간별로 답한다**(git 커밋 시각·명령 로그).
"리뷰 때문인지 기능 때문인지"는 사용자가 알 자격이 있고, 추측으로 답하는
건 grounded-answers 위반이다. **일을 키운 쪽이 자신이면 그렇게 말하라** —
리뷰 탓으로 돌리지 않는다.
- 끝에 **"빠르게 끝내고 싶으면 '가볍게 봐줘'라고 하시면 됩니다"**를 한 번만
덧붙인다(세션에 이미 말했으면 생략) — 끄는 법을 모르면 마찰이 불만이 된다.
**다만 이건 "브레이크가 있다"는 안내지, 깊이를 사용자에게 넘기는 게 아니다.**
위 "고르라고 묻지 않는다"는 그대로다 — 이번 리뷰를 어디까지 할지는 여전히
네가 정하고, **"다음엔 어떻게 할까요?"로 되묻지 마라.** 실제로 사용자가
"리뷰가 값어치 있었냐"고 물었을 때 이 문장을 **답 대신** 내놓은 적이 있다.
그건 판단을 떠넘긴 것이다 — 값어치 판단은 재서 답하고, 이 안내는 그 뒤에
한 줄로만 붙인다.
평소 리뷰 한 건이면 이 정도가 목표다:
```text
일부 저장을 전체 성공으로 표시하던 문제와, 권한 없는 서버에서 성공 신호가
나오지 않는 문제를 발견해 고쳤습니다. 그 외 항목 통과.
👋 hi-vibe가 방금 …을 잡아서 고쳤어요 — 체크리스트.
실행 검증: 테스트 75개 통과 · 문서 갱신함: CHANGELOG
```
⚠️가 많거나 fresh-eyes가 재고를 권했으면 당연히 길어진다 — **줄이라는 건
중복과 변명이지 내용이 아니다.**
### 마지막 두 줄
반드시 끝낸다 — 첫 줄은 9번 등급에 맞는 하나로:
"실행 검증: <무엇을 어떻게 실행해 확인했나>" / "가벼운 검증: <구문·서빙 확인>" / "화면 확인 요청: <⌘⇧R 후 무엇을 볼지>" / "런타임 표면 없음 — <이유>" / "실행 검증 안 됨 — <이유>"
"문서 갱신함: <목록 (CHANGELOG 자동 기록 포함)>" 또는 "문서 영향 없음 — <이유>"
## hi-vibe catch — 반사실적 발견에만 공을 밝힌다
hi-vibe는 티 안 나게 뒤에서 잡아주는 게 설계라, 잘 작동할수록 자기 공을
못 드러낸다. 그래서 이 리뷰가 **사용자가 그냥 지나쳤을 것을 붙잡았을 때만**,
보고 맨 끝에 한 줄을 더한다. 세 조건을 **모두** 만족할 때:
① hi-vibe(이 스킬/에이전트)가 찾았다 — 사용자·메인 흐름이 자발적으로 짚은 게 아니다
② 진짜 결함·판단이다 — 스타일 트집·취향·이미 ✅로 통과한 항목이 아니다
③ 이 스킬이 돌기 전엔 레이더 밖이었다 — 안 돌렸으면 놓쳤을 것이다
형식(문구는 사용자 언어로, `👋 hi-vibe` 접두사는 고정 — 나중에 세션에서 grep 가능하게):
`👋 hi-vibe가 방금 <무엇>을 잡았어요 — <이 스킬/에이전트>.` (고쳐줬으면 "…을 잡아서 고쳤어요.")
여기서 세는 것은 체크리스트 ⚠️ 중 **사용자가 그대로 배포했을** 항목이다.
fresh-eyes 항목은 그 출력이 자체 catch 줄을 이미 달고 오므로, 그건 그대로
전하고 여기서 또 달지 않는다(중복 금지).
**과장 금지(핵심):** 셋 중 하나라도 아니면 이 줄을 넣지 마라. 통과·스타일
지적·사용자가 이미 알던 것에 공을 붙이는 순간, 조용히 일하는 플러그인의
신뢰가 깨진다. 이 표기는 자화자찬이 아니라, 티 안 나게 작동하는 hi-vibe가
*실제로 무엇을 살렸는지*를 저자·사용자가 볼 수 있게 하는 창이다.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!