설계 플레이북 — “이런 요구·제약이면 이런 하네스”

한 줄 요약

내 작업의 성격을 5개 질문으로 좌표 찍으면, 어떤 하네스 부품을 조립할지가 자동으로 결정된다. — 매번 처음부터 고민하지 않고 “요구·제약 → 구성”을 결정트리로 빠르게 내리기 위해 배운다.

이 문서를 관통하는 1원리

7개 하네스(Claude Code · Codex · OMC · gajae-code · ouroboros · fable-ish · 내 패턴)를 10개 축으로 횡단분석해보니, 설계 결정의 절반은 결국 한 문장으로 모인다. “LLM은 똑똑하지만 자기보고(self-report)를 한다. 그래서 설계의 절반은 모델을 어떻게 못 믿을 것인가다.” (3_학습인사이트 메타교훈 2) 모든 결정은 이 전제 위에서 내려진다.


그림

아래는 같은 흐름을 결정트리로 펼친 것이다. 빨간 노드(시작 게이트·검증 폐루프)는 시작과 끝을 봉인하는 두 개의 fail-closed 관문, 초록 노드(다층 가드레일)는 실행 중 행위를 봉인한다. 이 세 봉인이 토대이고 나머지는 증폭기다. (2_통합하네스_설계안 §3 다이어그램 사상 계승)

flowchart TD
    START(["요구·제약 입력"]) --> Q4{"Q4. 요구가 명확한가?"}

    Q4 -->|"모호·대형"| GATE["시작 게이트 必<br/>ouroboros 모호성≤0.2<br/>or OMC 정밀인터뷰·합의계획<br/>→ 불변 Seed 고정"]
    Q4 -->|"명확·소형"| SKIP["시작 게이트 생략<br/>바로 실행"]

    GATE --> Q1
    SKIP --> Q1

    Q1{"Q1. 실행 주체?"}
    Q1 -->|단일 에이전트| SOLO["§3 단일 카드<br/>Stop게이트 + 원장<br/>fable-ish·Codex 골격"]
    Q1 -->|여러 일꾼| ORCH{"작업 성격?"}

    ORCH -->|"탐색·리뷰 위주"| READ["§4-A 모델 자율 위임<br/>요약만 회수·재귀 금지"]
    ORCH -->|"쓰기 多·충돌 위험"| WRITE["§4-B 격리+게이팅<br/>워크트리 격리·충돌 중재"]
    ORCH -->|대형 멀티파일| GRAPH["§4-C 그래프 병렬<br/>의존성 위상정렬"]

    SOLO --> Q2
    READ --> Q2
    WRITE --> Q2
    GRAPH --> Q2

    Q2{"Q2. 안전 기조?"}
    Q2 -->|자율우선| SOFT["soft 가드레일<br/>넓게 허용·비가역만 차단"]
    Q2 -->|안전우선| HARD["§5 다층 가드레일<br/>OS샌드박스+실행정책<br/>+심판 fail-closed"]

    SOFT --> Q3
    HARD --> Q3

    Q3{"Q3. 검증 강도?"}
    Q3 -->|신뢰 가능| LIGHT["경량 검증<br/>Stop게이트 권고"]
    Q3 -->|증거 필수| GATE2["§6 검증 폐루프<br/>저자≠리뷰어 분리<br/>+증거영수증·exit2"]

    LIGHT --> Q5
    GATE2 --> Q5

    Q5{"Q5. 영속·재현?"}
    Q5 -->|휘발 OK| MD["§8 마크다운 상태<br/>CLAUDE.md+노트패드"]
    Q5 -->|"영속·감사 必"| ES["§8 이벤트소싱·DB<br/>리플레이+색인"]

    MD --> DONE([구성 확정])
    ES --> DONE

    classDef gate fill:#fdd,stroke:#c00,stroke-width:2px
    classDef safe fill:#dfd,stroke:#080,stroke-width:2px
    class GATE,GATE2 gate
    class HARD safe

쉽게 풀기

하네스를 집 짓기에 비유하면 이해가 빠르다. 집을 짓기 전에 “방 몇 개? 안전 등급? 검사 강도? 설계도 확정됐나? 나중에 증축할 건가?”를 먼저 묻는 것과 똑같다. 막연히 벽돌부터 쌓으면 다 짓고 나서 “이게 아닌데”가 된다.

먼저 5개 질문으로 내 상황의 좌표를 찍는다. 각 질문의 답이 결정트리의 분기를 하나씩 정해준다.

시작 전 답할 5가지 질문 (시나리오 좌표 찍기)

  • Q1. 실행 주체 — 한 모델이 다 하나(단일), 여러 일꾼을 부리나(오케스트레이션)? → §3 vs §4
  • Q2. 안전 기조 — 빠르게 자율로(자율우선), 사고 방지가 최우선(안전우선)? → §5 가드레일 깊이
  • Q3. 검증 강도 — “다 했다”는 말을 믿어도 되나(신뢰), 증거가 필수인가(fail-closed 증명)? → §6 검증 게이트
  • Q4. 시작 명확도 — 요구가 또렷한가(명확), 막연한가(게이팅 필요)? → §7 시작 게이트
  • Q5. 영속·재현 — 한 세션이면 끝(휘발), 세션 넘어 재개·감사 필요(영속·감사)? → §8 상태 매체

이 5축은 서로 직교한다. 그래서 양 극단의 조합이 자연스럽게 그려진다.

  • 가장 무거운 조합 = 오케스트레이션 + 안전우선 + fail-closed + 모호 + 영속 → ouroboros형
  • 가장 가벼운 조합 = 단일 + 자율 + 신뢰 + 명확 + 휘발 → 맨몸 Claude Code형

좌표를 찍었으면, 다음 단계는 간단하다. 세 곳을 봉인하는 것이다. 시작을 봉인하고(모호하면 게이트), 행위를 봉인하고(위험하면 가드레일), 완료를 봉인한다(증거 없으면 종료 거부). 나머지(오케스트레이션·영속·DX)는 이 세 봉인 위에 얹는 “생산성 증폭기”일 뿐이다.


핵심 정리

시나리오별 추천 조합 (한눈에)

시나리오추천 조합1순위 근거
일상 코드 수정 (단일·명확·신뢰)기생 루프 + Stop게이트 권고 + 마크다운, 게이트 생략fable-ish 경량
위험 작업 (단일·안전·증거필수)Stop게이트 fail-closed + 비가역 봉인 + 원장fable-ish + 내패턴 exit2
멀티 리뷰·탐색 (오케스트레이션·읽기)모델자율 위임 + 요약만 회수 + 모델티어 분배CC subagent
병렬 기능개발 (쓰기·충돌위험)워크트리 격리 + SpawnPlanReceipt + 충돌중재 + 저자≠리뷰어gajae+OMC+ouroboros
대형 리팩터링 (의존성 복잡)의존성 그래프 위상정렬 병렬 + 레벨 게이트ouroboros only
막연한 신규 프로젝트 (모호·영속)모호성 게이트 → 불변Seed → 이벤트소싱 + 다축 검증ouroboros 통째
자기개선 루프 (진화·영속)토너먼트 + 봉인파일 + 반성 + 드리프트게이트 + 비용계단OMC self-improve + ouroboros
자동화 파이프라인 (결정적·재현)LLM=제한된 변환기 + 코드게이트 exit2 + 회귀검증내 패턴

검증의 3대 누수와 봉인

누수봉인 메커니즘출처
자기보고 (“검증했다” 텍스트)타입 있는 증거 계약 + 결정적 용어검증ouroboros
자기승인 (writer가 자기 채점)critic 분리 + false approval 10~100배 비용OMC, 내패턴
커버리지 미반영 (그 파일 검증했나?)coverage 4단계, uncertain은 통과 금지fable-ish 개선

오케스트레이션은 분기마다 다르지만, 3종은 어느 분기든 필수

위임의 1차 목적은 일을 나누는 게 아니라 메인 컨텍스트를 깨끗하게 지키는 것(대량 출력을 서브 창에 가두고 메인엔 요약만).

  • 요약만 반환, raw 금지 — 격리해놓고 raw를 도로 부으면 의미 없음. gajae outputRef=agent://<id>+sha256이 가장 정교.
  • 재귀 폭발 방지 — subagent가 또 subagent 무한 생성 못 하게. 단 Codex v2는 depth/slot으로 제한이지 금지가 아님(“bounded recursion”).
  • 동시성 상한 — 무제한 병렬은 API 레이트를 죽인다(CAS 카운터 / Semaphore / tmux 패인 N).

시나리오별 안티패턴 (자주 밟는 지뢰)

  • 단일인데 OMC 19에이전트·team 모드 켜기 → 오버엔지니어링. gate 없이 ralph 무한루프만 켜면 promise 자기신고로 거짓 탈출.
  • tmux·외부 CLI를 필수로 전제 → 미설치 시 핵심 가치 소실. “선택적 가속, 미설치 시 순차 폴백”으로 격하해야.
  • 정규식 한 줄로 위험 차단 → 우회됨(fable-ish 실측: 위험패턴 16개 중 4개만 잡힘). 안전 훅을 fail-open으로 두면 조용히 무력화.
  • 모든 작업에 LLM reviewer → 비용 2배. 결정적 pre-gate를 앞에 끼워 비용 계단으로.
  • 일상 수정까지 ≤0.2 모호성 게이트 → 마찰 큼. 인터뷰 없이 “쇼핑몰 만들어줘”로 바로 코딩하는 것도 반대편 안티패턴.
  • 비번을 메모리 노트에 평문(내 패턴 실제 약점). “계획”을 “구현”으로 메모리에 과대 기록.

실제 예시

단일 에이전트 — 기생 루프 + Stop 게이트 (fable-ish 골격)

호스트(Claude Code) 루프에 기생한다. 새 while 루프 구현 비용 0. (10_agent-loop 분기 “소유 vs 기생”)

// .claude/settings.json — 종료 통제 + 증거 누적의 훅 배선
{
  "hooks": {
    // PostToolUse: 변경파일·검증명령·exit_code를 세션×cwd 해시 원장에 적재
    //   (훅은 독립 프로세스라 *파일이 유일한 공유 매체*)
    "PostToolUse": [{ "matcher": "Edit|Write|Bash", "command": "ledger-append.mjs" }],
    // Stop: 원장을 읽어 "변경됐는데 검증 증거 없음"이면 종료 거부
    //   decision:block + reason 재주입으로 "끝내려는 순간"을 가로챔
    //   ※ 무한루프 가드 필수: MAX_STOP_BLOCKS=2 + stop_hook_active
    "Stop": [{ "command": "stop-gate.mjs" }]
  }
}

fail 정책의 핵심: 로그·주입은 fail-open({continue:true}), 권한차단·산출물검증은 fail-closed. (30_hooks 공통패턴 5)

오케스트레이션 4-B — 병렬 fan-out 증명 강제 (gajae SpawnPlanReceipt)

4명 초과 병렬이면 “왜 병렬인지” 5필드로 증명해야 통과. 무분별 fan-out을 비용으로 억제.

// 4+ 병렬 spawn 전 필수 영수증 (없으면 거부)
{
  "whyParallel":         "독립 모듈 6개, 상호 의존 없음",
  "whyNotLocal":         "각 모듈 컨텍스트 80k 토큰, 메인 오염 회피",
  "independence":        "Write/Edit 경로 교집합 0 (검증됨)",
  "expectedReceiptShape": "{ file, sha256, testExit }",
  "maxInlineTokens":     2000   // 초과분은 outputRef로 회수
}

충돌 처리: ouroboros LevelCoordinator가 레벨 끝에 Write/Edit 경로 교집합을 감지 → 충돌 있을 때만 critic 세션 중재(비용 0 if no conflict). 모델 라우팅은 frontmatter model로(조회 haiku / 설계 opus) 비용 최적화.

안전우선 — 플러그인 환경(내 스택)의 현실적 가드 배치

Claude Code 호스트가 이미 OS 샌드박스를 제공하므로 중복 구현 말고 그 위에 정책층만. 화이트리스트 미매칭 회색지대만 경량 LLM에게 물어 자동판정.

// permissions — 비가역 행동만 deny에 집중 (자율우선 기조)
{
  "permissions": {
    "deny": ["Bash(rm -rf*)", "Bash(git push --force*)",
             "Read(.env)", "Read(.ssh/**)", "Edit(.git/**)"]
    // 셸 메타문자(; & | $ ( ))는 화이트리스트 *전에* 즉시 탈락
    //   → `git status && rm -rf /` 체이닝 우회 차단
  }
}
// 회색지대 자동판정 3원칙:
//   (a) 트랜스크립트를 "untrusted evidence"로 라벨
//   (b) 타임아웃 = ask 폴백 (human fallback)
//   (c) 연속거부 시 서킷브레이커

검증 폐루프 — 비용 계단 (결정적 게이트를 LLM 앞에)

# Stage 1: 결정적 코드 게이트 — 100% 재현·토큰 0 (형식만 잡음)
node admit/gate.mjs || exit 2     # exit 2 = 물리적 종료 거부
# Stage 2: LLM 심판 — 의미론 판단 (fail-closed, 고위험 경계에서만)
# 타임아웃/파싱실패 = 거부
# Stage 3: 다중 합의 — 고위험 diff(commit/release/destructive)에만

핵심 한 줄: 되돌릴 수 있는 것(Stop훅·재시도)은 fail-open(생산성), 되돌릴 수 없는 것(commit/push/deploy/외부API·승인영수증)은 fail-closed(품질). 단 “디스크 쓰기 전부 fail-closed”는 과함 — 코드 파일은 git으로 되돌리므로 완료선언을 막는 쪽이 낫다.


요약 & 셀프체크

3줄 요약

  1. 5개 질문(주체·안전·검증·명확도·영속)으로 좌표를 찍으면 결정트리가 조립할 부품을 자동으로 골라준다.
  2. 세 곳을 봉인하라 — 시작(모호성 게이트), 행위(다층 가드레일), 완료(fail-closed 검증). 이 세 봉인이 토대다.
  3. 나머지는 증폭기일 뿐 — 오케스트레이션·영속·DX는 세 봉인 위에 얹는 생산성 가속이지 토대가 아니다.

모든 시나리오 관통 3대 규율 (절대 어기지 말 것)

횡단분석 10개 노트 전부에서 수렴한 자연법칙이다.

  1. 절제가 실력이다 — 정보·기능·권한 모두 “필요한 만큼만”(인라인 회피→포인터, deferred+ToolSearch, 위험 비례 차등). (20_context-assembly, 50_tools-mcp)
  2. 자기 일은 남이 검사한다 — writer≠reviewer, 자체승인 금지. 거짓 완료를 막는 거의 유일한 길. (80_verification)
  3. 코드만이 진짜 잠근다 — “지켜지지 않으면 사고 나는 것”만 훅·exit code·샌드박스로 강제, 나머지는 산문. (3_학습인사이트 원칙 10)

스스로 답해보기

  1. 지금 내 작업을 5개 질문으로 좌표 찍으면? 그 좌표가 가리키는 시나리오 카드는 무엇인가?
  2. “시작·행위·완료” 세 봉인 중 지금 내 구성에 빠진 봉인은 무엇인가? 빼도 되는 이유를 댈 수 있나?
  3. fail-open과 fail-closed의 경계선은? “되돌릴 수 있는가”로 답할 수 있나?

연결

하네스엔지니어링이란 · HOME · 1_하네스_설계원칙 · 2_통합하네스_설계안 · 3_학습인사이트 · 4_나만의_하네스_조립가이드 · _비교매트릭스

관련 횡단노트: 10_agent-loop · 20_context-assembly · 30_hooks · 50_tools-mcp · 60_orchestration · 70_guardrails-sandbox · 80_verification · 90_self-improvement · 100_state-memory

Codex 교차검증 / 메타검증으로 보강된 경계들

이 플레이북의 several 결정은 Codex 교차검증으로 경계가 다듬어졌다.

  • 검증 메커니즘 5위치: ①런타임 훅(돌렸는지만 앎, 일상 권장) · ②LLM 심판(의미론, 고위험 경계만) · ③결정적 코드 게이트(100% 재현, 형식만) · ④sha256 무결성 도장(장기 워크플로) · ⑤진화적 수렴(self-improve 루프만).
  • SSOT 3갈래: 마크다운(학습·소규모) · 이벤트 로그(감사·재현) · JSON 원장(검증 상태 전용). 주입형↔제어형 두 축을 섞지 말 것 — 주입형은 얇게·자동·compaction 생존, 제어형은 세션격리·fail-closed·신선도.
  • 알려진 약점: OMC는 검증 문화는 최강이나 verify-deliverables가 ADVISORY 비차단이라 강제력에 구멍. 내 패턴은 프로젝트별 봉인은 강하나 전역 설정이 느슨하면 가드 점수가 하락한다.