GateGuard — 사실 확인 기반 사전 조치 게이트
편집 전에 Claude가 조사하도록 강제하는 PreToolUse 훅입니다. '확실합니까?' 같은 자기 평가 대신 구체적인 사실을 요구합니다. 조사 행위 자체가 자기 평가로는 결코 얻을 수 없는 인식을 만들어냅니다.
활성화 시점
- 파일 편집이 여러 모듈에 영향을 미치는 코드베이스에서 작업할 때
- 특정 스키마나 날짜 형식을 가진 데이터 파일이 있는 프로젝트
- AI 생성 코드가 기존 패턴과 일치해야 하는 팀
- Claude가 조사 대신 추측하는 경향이 있는 모든 워크플로
핵심 개념
LLM 자기 평가는 작동하지 않습니다. '정책을 위반했습니까?'라고 물으면 항상 '아니요'라는 답이 돌아옵니다. 이는 실험적으로 검증되었습니다.
그러나 '이 모듈을 임포트하는 모든 파일을 나열하라'고 요구하면 LLM은 Grep과 Read를 실행해야 합니다. 조사 자체가 맥락을 만들어 출력을 바꿉니다.
3단계 게이트:
1. DENY — 첫 번째 편집/쓰기/Bash 시도 차단
2. FORCE — 모델이 정확히 어떤 사실을 수집해야 하는지 지시
3. ALLOW — 사실 제시 후 재시도 허용
어떤 경쟁 제품도 세 단계를 모두 구현하지 않습니다. 대부분은 거부에서 멈춥니다.
증거
두 번의 독립적인 A/B 테스트, 동일한 에이전트, 동일한 작업:
| 작업 | 게이트 적용 | 게이트 미적용 | 차이 |
|---|---|---|---|
| 분석 모듈 | 8.0/10 | 6.5/10 | +1.5 |
| 웹훅 검증기 | 10.0/10 | 7.0/10 | +3.0 |
| 평균 | 9.0 | 6.75 | +2.25 |
두 에이전트 모두 실행되고 테스트를 통과하는 코드를 생성합니다. 차이는 설계 깊이에 있습니다.
게이트 유형
편집 / MultiEdit 게이트 (파일당 첫 편집)
MultiEdit도 동일하게 처리됩니다 — 배치의 각 파일이 개별적으로 게이트됩니다.
{file_path}을(를) 편집하기 전에 다음 사실을 제시하십시오:
1. 이 파일을 임포트/require하는 모든 파일을 나열하십시오 (트리 검색 — Glob/Grep, 또는 Bash를 통한 find/grep)
2. 이 변경으로 영향을 받는 공개 함수/클래스를 나열하십시오
3. 이 파일이 데이터 파일을 읽거나 쓰는 경우, 필드 이름, 구조 및 날짜 형식을 제시하십시오 (원시 프로덕션 데이터가 아닌 수정 또는 합성 값 사용)
4. 사용자의 현재 지시사항을 그대로 인용하십시오
쓰기 게이트 (첫 새 파일 생성)
{file_path}을(를) 생성하기 전에 다음 사실을 제시하십시오:
1. 이 새 파일을 호출할 파일 및 라인 번호를 지정하십시오
2. 동일한 용도를 제공하는 기존 파일이 없는지 확인하십시오 (트리 검색 — Glob/Grep, 또는 Bash를 통한 find/grep)
3. 이 파일이 데이터 파일을 읽거나 쓰는 경우, 필드 이름, 구조 및 날짜 형식을 제시하십시오 (원시 프로덕션 데이터가 아닌 수정 또는 합성 값 사용)
4. 사용자의 현재 지시사항을 그대로 인용하십시오
파괴적 Bash 게이트 (모든 파괴적 명령)
다음에 트리거됨: rm -rf, git reset --hard, git push --force, drop table 등
1. 이 명령이 수정하거나 삭제할 모든 파일/데이터를 나열하십시오
2. 한 줄짜리 롤백 절차를 작성하십시오
3. 사용자의 현재 지시사항을 그대로 인용하십시오
일상 Bash 게이트 (세션당 한 번)
1. 현재 사용자 요청을 한 문장으로 요약하십시오
2. 이 특정 명령이 검증하거나 생성하는 것이 무엇인지 설명하십시오
병렬 배치 및 부분 적용
최초 접촉 게이트는 각 도구 호출을 독립적으로 평가합니다. 아직 접촉되지 않은 파일에 대한 여러 편집이 하나의 병렬 배치로 전송되면, 첫 번째 호출이 거부되고 해당 파일이 검사됨으로 표시되어 해당 배치의 형제 편집은 적용됩니다. 롤백되는 것은 없습니다: 거부된 편집 없이 형제 편집이 파일에 반영될 수 있습니다.
거부 메시지는 파일 이름을 명시하고 배치 형제가 이미 적용되었을 수 있음을 경고합니다. 이를 문자 그대로 처리하십시오:
- 아직 접촉되지 않은 파일에 대한 의존적 편집은 병렬 배치가 아닌 순차적으로 전송하십시오. 정의와 첫 사용, 또는 임포트와 호출 지점은 동일한 배치에 포함되어서는 안 됩니다.
- 최초 접촉 거부 후, 사실을 제시하고 거부된 편집을 재시도한 후 배치의 다른 내용을 기반으로 작업하기 전에 파일을 다시 읽으십시오.
배치 전체 잠금은 불가능합니다: 훅은 도구 호출을 한 번에 하나씩 보므로 게이트는 어떤 호출이 함께 도착했는지 알 수 없습니다.
빠른 시작
옵션 A: ECC 훅 사용 (설치 불필요)
scripts/hooks/gateguard-fact-force.js 훅이 이 플러그인에 포함되어 있습니다. hooks.json을 통해 활성화하십시오.
GateGuard가 설정 또는 복구 작업을 차단하는 경우, 세션을 ECC_GATEGUARD=off로 시작하십시오. 훅 레벨 제어를 위해 ECC_DISABLED_HOOKS와 GateGuard 훅 ID를 계속 사용하십시오.
긴 세션에서는 처음 GATEGUARD_FACT_FORCE_FULL_DENIALS(기본값 3)개의 사실 확인 거부가 전체 4-팩트 블록을 출력하고, 이후 거부는 거부 순번을 포함한 한 줄로 축약되어 거의 동일한 블록이 컨텍스트 윈도우에 누적되어 모델 반복 루프를 증폭시키는 것을 방지합니다(#2142). 사실 제시 후 동일한 파일이나 명령을 재시도하면 게이트가 다시 트리거되지 않습니다.
점진적 제어
ECC_GATEGUARD=off (또는 GATEGUARD_DISABLED=1)는 게이트를 완전히 끕니다. 이 표의 변수들은 그렇지 않습니다 — 각 변수는 하나의 동작을 좁히는 반면, 핵심적인 파괴적 Bash 검사는 계속 실행됩니다:
| 변수 | 기본값 | 효과 |
|---|---|---|
GATEGUARD_BASH_ROUTINE_DISABLED | 설정 안 됨 (게이트 켜짐) | 일상 Bash 게이트만 비활성화합니다. 파괴적 Bash 게이트(rm -rf, git reset --hard, drop table, dd if=, …)는 영향을 받지 않습니다. |
GATEGUARD_EXEMPT_GLOBS | 설정 안 됨 (면제 없음) | 쉼표로 구분된 글로브; 일치하는 편집/쓰기/MultiEdit 대상은 최초 접촉 사실 강제를 건너뜁니다. '누가 이것을 임포트하는가/스키마가 무엇인가'에 신호가 없는 낮은 임포트 가치 트리(테스트, 생성된 아티팩트, 스크래치 디렉토리)를 위한 것입니다. |
GATEGUARD_FACT_FORCE_FULL_DENIALS | 3 | 전체 4-팩트 블록을 출력하는 거부 횟수, 이후 거부는 한 줄로 축약됩니다. 0은 첫 번째 거부부터 축약합니다. |
GATEGUARD_BASH_EXTRA_DESTRUCTIVE | 설정 안 됨 | 정규식 소스 형태의 추가 파괴적 명령 패턴, 내장 집합에 추가됩니다. 잘못된 형식의 정규식은 설정되지 않은 것으로 처리되고(내장 패턴은 계속 적용됨) stderr에 한 번 로깅됩니다. |
GATEGUARD_STATE_DIR | ~/.gateguard | 세션별 게이트 상태가 유지되는 위치입니다. 상태를 유지할 수 없는 경우 게이트는 루핑 대신 작업을 허용하고 경고에 이 변수를 명시합니다. |
GATEGUARD_BASH_ROUTINE_DISABLED는 1, true, on, enabled, enable 또는 yes를 허용합니다(대소문자 및 공백 무시); 다른 값은 게이트를 켠 상태로 둡니다.
게이트 완전 끄기
| 변수 | 효과 |
|---|---|
ECC_GATEGUARD=off | 세션에 대해 GateGuard를 비활성화합니다. 0, false, off, disabled 또는 disable을 허용합니다. |
GATEGUARD_DISABLED=1 | 동일한 효과입니다. 1만 인식합니다 — 위의 철자는 여기에 적용되지 않습니다. |
훅 레벨 제어를 위해 ECC_DISABLED_HOOKS와 GateGuard 훅 ID를 계속 사용하십시오.
GATEGUARD_EXEMPT_GLOBS의 글로브 의미
패턴은 프로젝트 기준 전체 대상 경로와 일치합니다. 프로젝트 루트는 CLAUDE_PROJECT_DIR이며, 훅 페이로드의 cwd로 폴백한 다음 훅 프로세스 작업 디렉토리로 폴백합니다. 상대 글로브는 해당 루트 외부의 대상을 면제하지 않습니다. 명시적 절대 글로브는 전체 절대 대상 경로와 일치하며 의도적으로 프로젝트 외부 경로를 면제할 수 있습니다.
패턴과 경로 모두 / 구분자를 사용하고 소문자 일치를 사용합니다. *는 세그먼트 내에서 일치하고, **는 세그먼트를 넘어 일치하며, ?는 하나의 비구분자 문자와 일치합니다. **/는 0개의 디렉토리를 포함하므로 **/tests/**는 tests/foo.js와도 일치합니다. 잘못된 형식의 패턴은 면제를 부여하지 않고 삭제됩니다.
2.2.1부터 services/**는 프로젝트 루트 services 트리만, *.md는 루트 Markdown 파일만 포함합니다. 프로젝트 내 모든 Markdown 파일에는 **/*.md를 사용하십시오. 기존의 고정되지 않은 면제는 조정이 필요할 수 있습니다:
{
"env": {
"GATEGUARD_BASH_ROUTINE_DISABLED": "1",
"GATEGUARD_EXEMPT_GLOBS": "**/tests/**,tests/**,**/*.test.*,**/docs/**,**/dist/**"
}
}
옵션 B: 구성이 포함된 전체 패키지
pip install gateguard-ai
gateguard init
이 명령은 프로젝트별 구성(사용자 정의 메시지, 무시 경로, 게이트 전환)을 위한 .gateguard.yml을 추가합니다.
안티 패턴
- 자기 평가를 대신 사용하지 마십시오. '확실합니까?'는 항상 '예'라는 답을 받습니다. 이는 실험적으로 검증되었습니다.
- 데이터 스키마 검사를 건너뛰지 마십시오. 두 A/B 테스트 에이전트 모두 실제 데이터가
%Y/%m/%d %H:%M을 사용할 때 ISO-8601 날짜를 가정했습니다. 데이터 구조 확인(수정된 값 사용)은 이러한 전체 버그 클래스를 방지합니다. - 모든 단일 Bash 명령을 게이트하지 마십시오. 일상 bash 게이트는 세션당 한 번만 실행됩니다. 파괴적 bash 게이트는 매번 실행됩니다. 이 균형은 속도 저하를 피하면서 실제 위험을 포착합니다.
모범 사례
- 게이트가 자연스럽게 작동하도록 두십시오. 게이트 질문에 미리 답변하려고 하지 마십시오 — 조사 자체가 품질을 향상시킵니다.
- 게이트 메시지를 도메인에 맞게 사용자 정의하십시오. 프로젝트에 특정 규칙이 있는 경우 게이트 프롬프트에 추가하십시오.
.gateguard.yml을 사용하여.venv/,node_modules/,.git/같은 경로를 무시하십시오.
관련 기술
safety-guard— 런타임 안전 검사 (보완적, 중복되지 않음)code-reviewer— 사후 편집 검토 (GateGuard는 사전 편집 조사임)