Harness Engineering · Foundation

Harness의 기본,
Hook Pipeline

하네스는 '모델의 지능'이 아니라 그 주변의 결정론적 인프라(Claude Code 소스 기준 98.4%)로 굴러간다. rule·skill·workflow·memory·orchestrator가 전부 그 위에 서는 토대 — 그게 hook pipeline이다. 프롬프트·rule(SOFT)은 입력으로 우회되고 compaction에 지워지지만, hook의 exit code(HARD)는 에이전트 주소 공간 밖에서 무시 불가하게 닫는다. 13개 이벤트127개 hook을 배선해 286개 rule 중 핵심을 exit 2로 강제한다.

근거 — github.com/jung-wan-kim/cc-sync · ~/.claude 공개 미러 (settings.json · hooks/ · rules/)

13
Hook 이벤트
127
Hook 스크립트
286
Rules (승격 소스)
exit 2
차단 = 무시 불가
하네스의 토대 — 모든 층이 그 위에 선다

Claude Code 소스 분석은 에이전트 신뢰성의 98.4%가 결정론적 인프라(권한 게이트·컨텍스트 관리·복구)이고 AI 추론은 1.6%임을 보인다. 하네스를 층으로 보면 — 맨 위 모델 추론, 그 아래 orchestrator·skill·rule·memory(운영 지식). 그리고 이 모든 것을 강제 가능하게 만드는 맨 아래 토대가 hook pipeline이다. rule이 "무엇을 하라"면, hook은 "안 하면 못 지나간다". 토대가 없으면 위층은 전부 부탁일 뿐이다.

하네스 스택에서 hook의 자리 — 위층은 전부 이 토대 위에 선다 SOFT · escapable (부탁) HARD · 강제 모델 추론 (LLM) 지능 · Claude Code 소스 기준 1.6% Orchestrator · Skill · Rule · Memory 운영 지식 — 무엇을 하라 (SOFT) 위에 선다 HOOK PIPELINE 결정론적 강제 · exit code · 별도 프로세스 (HARD) 하네스 인프라 98.4% · 에이전트 주소 공간 밖 · 우회 불가 모든 도구 호출이 토대를 통과 → exit code
하네스는 층으로 쌓인다 — 맨 위 모델 추론, 그 아래 orchestrator·skill·rule·memory. 이 위층은 전부 SOFT(무엇을 하라)라 강제력이 없고, 실제 강제는 맨 아래 토대인 hook pipeline의 exit code에서만 나온다. 모든 도구 호출이 이 토대를 통과한다.

그렇다면 왜 rule(SOFT)은 토대가 못 되고 hook(HARD)만 토대가 되는가 — 같은 규칙이라도 어디에 두느냐가 강제력을 가른다.

SOFT — prose

rule · 시스템 프롬프트

"이렇게 해주세요" — 협력 요청

  • CLAUDE.md · rules/*.md 본문에 자연어로 존재
  • 에이전트 주소 공간 안 → 입력으로 우회 가능
  • compaction 시 조용히 소실 (governance decay)
  • 강제력은 모델의 "협조"에 의존
  • 무시해도 아무 일도 일어나지 않음
HARD — hook exit code

PreToolUse · Stop hook

"조건 미충족 → 차단" — 구조적 강제

  • hooks/*.sh — 별도 프로세스로 실행
  • 에이전트 주소 공간 밖 → 우회 불가
  • 매 이벤트마다 항상 실행 (compaction 무관)
  • exit 0 = 통과 · exit 2 = 도구 호출 차단
  • 증거(파일/해시) 없이는 통과 자체가 없음
SOFT(escapable) vs HARD(exit code) · 규칙이 강제되는 자리 SOFT · 에이전트 주소 공간 안 rule 본문 · 프롬프트 CLAUDE.md · rules/*.md 실행 시점 compaction 소실 governance decay 입력으로 우회 모델이 무시 가능 2회+ 우회 soft→hard 승격 HARD · 주소 공간 밖 (별도 프로세스) hook (PreToolUse/Stop) hooks/*.sh 조건 충족? exit code 판정 NO YES exit 2 도구 호출 차단 exit 0 통과 · 실행 진행
SOFT(rule 본문)는 주소 공간 안이라 compaction 소실·입력 우회에 노출된다. 반복 우회가 감지되면 soft→hard 승격으로 hook(별도 프로세스)에 exit code 게이트로 고정되어 무시 불가능해진다.
토대의 구조 — 에이전트 턴의 모든 경계

에이전트 턴은 열린 채로 흘러가지 않는다. 세션 시작 → 프롬프트 제출 → (도구 실행)× → 종료의 모든 경계에 hook이 끼어든다. 내 시스템은 이 13개 이벤트에 clawd-hook.js(관측 디스패처)를 공통으로 깔고, 그 위에 이벤트별 게이트/주입기를 배선했다. 역할은 넷 — 차단(block, exit 2) · 주입(inject, 컨텍스트) · 검사(check, 기록) · 관측(observe).

HOOK PIPELINE · 에이전트 턴 라이프사이클 (13 이벤트) SessionStart 모델·권한 세팅 · observe UserPromptSubmit 컨텍스트 주입 · INJECT prompt-enhancer · self-improve-check · reminders 주입되는 것 → mid-loop-question-reminder premature-completion-reminder feedback-detector · context-monitor 도구 호출 루프 — 매 도구마다 반복 PreToolUse 실행 전 게이트 · BLOCK (exit 2) git-push-adversarial · no-env-commit · workflow-cost-gate 게이트 (matcher) → [Bash] no-env-commit [Write] qa-inventory-gate [Workflow] workflow-cost-gate exit 2 → 차단 도구 실행 안 됨 exit 0 → 통과 도구 실행 Bash · Edit · Write · Task · … PostToolUse 실행 후 검사·기록 · CHECK formatter · sql-injection · dependency-audit · work-recheck-ledger 다음 도구 반복 루프 종료 Stop 종료 시도 — HARD 재검증 · BLOCK work-recheck-gate · premature/mid-loop detector · self-improve-trigger exit 2 → 종료 차단 미완성·헛완료 재작업 SessionEnd clawd-hook · persist · observe PreCompact 압축 전 스냅샷 block (exit 2) inject check
SessionStart → UserPromptSubmit(주입) → [PreToolUse(게이트, exit 2 차단) → 도구 → PostToolUse(검사)]× → Stop(HARD 재검증) → SessionEnd. PreCompact 등 분기 이벤트가 컨텍스트 압축 경계를 지킨다. 게이트가 exit 2를 반환하면 그 도구 호출·종료 자체가 일어나지 않는다.
SessionStartobserve
ensure-default-modelauto-apply-permissions
UserPromptSubmitinject
prompt-enhancerself-improve-checkmid-loop-reminderpremature-reminder
PreToolUseblock
git-push-adversarialno-env-commitno-localstorageworkflow-cost-gate
PostToolUsecheck
formatter-checksql-injection-checkdependency-auditwork-recheck-ledger
Stopblock
work-recheck-gatepremature-detectormid-loop-detectorself-improve-trigger
SessionEndobserve
clawd-hookfact-extract
SubagentStart / Stopobserve
subagent-snapshotsubagent-qa-directive
PreCompact / PostCompactobserve
context 스냅샷상태 재주입
PostToolUseFailure · Notificationobserve
clawd-hook 디스패처Elicitation · WorktreeCreate
토대가 강제하는 것 — exit 2는 무시할 수 없다

exit 2를 반환하는 hook은 도구 호출을 물리적으로 차단한다. 아래 게이트들은 "완료했다"는 모델의 자기 보고를 신뢰하지 않고, 증거(파일·해시·acceptance)를 요구한다. 증거가 없으면 push도 commit도 workflow도 종료도 통과되지 않는다.

qa-gate-before-push.shPreToolUse[Bash]

코드 변경이 있는데 .qa-cycle-passed(PASS·해시·1시간 이내)가 없으면 push 차단. 해시가 HEAD와 불일치해도 차단.

git-push-adversarial-review-gate.shPreToolUse[Bash]

Codex 적대적 크로스 리뷰에서 CRITICAL이 남아 있으면 push 차단. 단일 모델 자기검증의 맹점을 다른 모델로 닫는다.

workflow-cost-gate.shPreToolUse[Workflow]

Workflow 호출이 6패턴 중 하나를 선언하지 않으면 차단. 무분별한 5-리뷰어 패널 낭비를 구조로 막는다.

work-recheck-gate.shStop · exit 2 ×4

substantive 작업이 acceptance 증거로 재검증되지 않으면 세션 종료 차단. "헛완료(거짓 완료)"를 종료 시점에 잡는다.

no-env-commit.shPreToolUse[Bash]

.env·API 키·시크릿을 stage/commit하려 하면 차단. 인코딩된 시크릿까지 스캔한다.

no-localstorage-universal.shPreToolUse[Edit|Write]

웹 파일의 localStorage 사용을 차단(Supabase Auth 토큰 리터럴만 예외). 사용자 데이터는 서버에.

scaffold-violation-check.shPreToolUse · exit 2 ×2

프로젝트 scaffold의 NEVER DO 패턴 위반을 즉시 차단. 프로젝트 컨벤션을 구조로 강제.

task-quality-gate.shproject · acceptance

UI/비-UI 변경이 verdict=PASS인데 acceptance_verified[]가 없거나 미충족이면 차단(anti-Goodhart).

PUSH 강제 체인 · fail-closed (하나라도 미충족 → 차단) git push 시도 commit 이후 qa-gate-before-push .qa-cycle-passed? codex-review-gate .codex-review-passed? git-push-adversarial CRITICAL = 0? origin push 허용 exit 2 · push 차단 fail-closed — 증거(파일·해시·CRITICAL=0) 하나라도 미충족 시
git push는 3중 게이트를 순차 통과해야 origin에 도달한다 — QA 증거(.qa-cycle-passed) · Codex 리뷰(.codex-review-passed) · 적대적 리뷰(CRITICAL=0). 하나라도 미충족이면 exit 2로 차단(fail-closed). "완료했다"는 자기 보고가 아니라 파일·해시 증거가 통과 조건이다.
실증 — 이 게이트가 방금 나를 막았다

이 페이지를 조사하던 중, 내가 실행한 읽기 전용 명령이 qa-gate-before-push.sh에 의해 HARD BLOCK됐다. 명령 안에 grep '…|git push|…'라는 "git push" 문자열이 들어 있었기 때문이다. 게이트는 명령 문자열에서 그 부분열을 발견하고 fail-closed로 차단했다.

이것이 hook 강제의 본질이다 — 게이트는 의도를 추측하지 않는다. 조건(문자열/증거)이 충족되지 않으면 무조건 막는다. 과대 매칭 false-positive라는 대가가 있지만, "무시 가능한 규칙"보다 "가끔 과하게 막는 규칙"이 하네스 신뢰성에는 이득이다.

# hooks/workflow-cost-gate.sh — Workflow 강제 계약 PreToolUse[Workflow]. dynamic-workflows-harness.md 의 SOFT 두 주장 (opt-in 비용 게이트 / 측정가능)을 HARD exit code 로 닫는다. exit 0 = 통과(패턴 선언됨) exit 2 = 차단(패턴 미선언) 우회: WORKFLOW_COST_GATE=0
토대 위에 서는 것 — workflow도 hook 없이는 못 선다

가장 위층인 dynamic workflow조차 이 토대 위에서만 안전하다. dynamic workflow는 강력하지만 비싸다(수십 개 subagent를 spawn). workflow-cost-gate.sh모든 Workflow 호출이 6개 오케스트레이션 패턴 중 하나를 meta.description이나 // pattern: 주석에 명시적으로 선언하도록 요구한다. 미선언 → exit 2. 통과한 호출은 workflow.jsonl에 기록된다. 즉 동적 ceiling(workflow)이 evidence를 만들고 정적 floor(hook)가 그것을 검증하는 — 토대와 그 위층의 폐루프다.

WORKFLOW 강제 · workflow-cost-gate (PreToolUse[Workflow]) Workflow 호출 dynamic workflow 6패턴 중 하나 선언됐나? meta.description / // pattern: NO exit 2 · 차단 "패턴 못 대면 Agent 병렬 써라" YES exit 0 · workflow 실행 fan-out · verify · synthesize workflow.jsonl 모든 호출 정량 측정 우회: WORKFLOW_COST_GATE=0 기본값: Agent 병렬 tool-use (Workflow는 opt-in)
Workflow 호출 → workflow-cost-gate가 6패턴(classify-and-act / fan-out-and-synthesize / adversarial verification / generate-and-filter / tournament / loop-until-done) 선언 여부 판정 → 미선언 exit 2 차단, 선언 시 실행 + workflow.jsonl 측정. "비용 정신"을 exit code로 인코딩한다.
classify-and-act fan-out-and-synthesize adversarial verification generate-and-filter tournament loop-until-done
floor + ceiling — 정적 hook과 동적 workflow의 폐루프

동적 ceiling(opt-in workflow)이 evidence를 생산하고, 정적 floor(항상 ON인 hook)가 그 evidence를 검증한다. team-deliver.js workflow가 항목별 acceptance_verified[].qa-evidence.json에 기록하면, task-quality-gate.sh(HARD)가 그 증거의 충족 여부를 exit code로 확인한다. workflow가 만들고 hook이 닫는 — 강제의 폐루프.

이 토대가 물려 있는 곳
raground@gmail.com 복사됨