설계 플레이북 — '이런 요구·제약이면 이런 하네스'
설계 플레이북 — “이런 요구·제약이면 이런 하네스”
한 줄 요약
내 작업의 성격을 5개 질문으로 좌표 찍으면, 어떤 하네스 부품을 조립할지가 자동으로 결정된다. — 매번 처음부터 고민하지 않고 “요구·제약 → 구성”을 결정트리로 빠르게 내리기 위해 배운다.
[!abstract] 이 문서를 관통하는 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개 질문으로 내 상황의 좌표를 찍는다. 각 질문의 답이 결정트리의 분기를 하나씩 정해준다.
[!question] 시작 전 답할 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 개선 |
[!note] 오케스트레이션은 분기마다 다르지만, 3종은 어느 분기든 필수 위임의 1차 목적은 일을 나누는 게 아니라 메인 컨텍스트를 깨끗하게 지키는 것(대량 출력을 서브 창에 가두고 메인엔 요약만).
- 요약만 반환, raw 금지 — 격리해놓고 raw를 도로 부으면 의미 없음. gajae
outputRef=agent://<id>+sha256이 가장 정교.- 재귀 폭발 방지 — subagent가 또 subagent 무한 생성 못 하게. 단 Codex v2는 depth/slot으로 제한이지 금지가 아님(“bounded recursion”).
- 동시성 상한 — 무제한 병렬은 API 레이트를 죽인다(CAS 카운터 / Semaphore / tmux 패인 N).
[!warning] 시나리오별 안티패턴 (자주 밟는 지뢰)
- 단일인데 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. (40_횡단분석/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. (40_횡단분석/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으로 되돌리므로 완료선언을 막는 쪽이 낫다.
요약 & 셀프체크
[!summary] 3줄 요약
- 5개 질문(주체·안전·검증·명확도·영속)으로 좌표를 찍으면 결정트리가 조립할 부품을 자동으로 골라준다.
- 세 곳을 봉인하라 — 시작(모호성 게이트), 행위(다층 가드레일), 완료(fail-closed 검증). 이 세 봉인이 토대다.
- 나머지는 증폭기일 뿐 — 오케스트레이션·영속·DX는 세 봉인 위에 얹는 생산성 가속이지 토대가 아니다.
[!note] 모든 시나리오 관통 3대 규율 (절대 어기지 말 것) 횡단분석 10개 노트 전부에서 수렴한 자연법칙이다.
- 절제가 실력이다 — 정보·기능·권한 모두 “필요한 만큼만”(인라인 회피→포인터, deferred+ToolSearch, 위험 비례 차등). (40_횡단분석/20_context-assembly, 40_횡단분석/50_tools-mcp)
- 자기 일은 남이 검사한다 — writer≠reviewer, 자체승인 금지. 거짓 완료를 막는 거의 유일한 길. (40_횡단분석/80_verification)
- 코드만이 진짜 잠근다 — “지켜지지 않으면 사고 나는 것”만 훅·exit code·샌드박스로 강제, 나머지는 산문. (3_학습인사이트 원칙 10)
스스로 답해보기
- 지금 내 작업을 5개 질문으로 좌표 찍으면? 그 좌표가 가리키는 시나리오 카드는 무엇인가?
- “시작·행위·완료” 세 봉인 중 지금 내 구성에 빠진 봉인은 무엇인가? 빼도 되는 이유를 댈 수 있나?
- fail-open과 fail-closed의 경계선은? “되돌릴 수 있는가”로 답할 수 있나?
연결
하네스엔지니어링이란 · HOME · 1_하네스_설계원칙 · 2_통합하네스_설계안 · 3_학습인사이트 · 4_나만의_하네스_조립가이드 · _비교매트릭스
관련 횡단노트: 40_횡단분석/10_agent-loop · 40_횡단분석/20_context-assembly · 40_횡단분석/30_hooks · 40_횡단분석/50_tools-mcp · 40_횡단분석/60_orchestration · 40_횡단분석/70_guardrails-sandbox · 40_횡단분석/80_verification · 40_횡단분석/90_self-improvement · 40_횡단분석/100_state-memory
[!tip] Codex 교차검증 / 메타검증으로 보강된 경계들 이 플레이북의 several 결정은 Codex 교차검증으로 경계가 다듬어졌다.
- 검증 메커니즘 5위치: ①런타임 훅(돌렸는지만 앎, 일상 권장) · ②LLM 심판(의미론, 고위험 경계만) · ③결정적 코드 게이트(100% 재현, 형식만) · ④sha256 무결성 도장(장기 워크플로) · ⑤진화적 수렴(self-improve 루프만).
- SSOT 3갈래: 마크다운(학습·소규모) · 이벤트 로그(감사·재현) · JSON 원장(검증 상태 전용). 주입형↔제어형 두 축을 섞지 말 것 — 주입형은 얇게·자동·compaction 생존, 제어형은 세션격리·fail-closed·신선도.
- 알려진 약점: OMC는 검증 문화는 최강이나 verify-deliverables가 ADVISORY 비차단이라 강제력에 구멍. 내 패턴은 프로젝트별 봉인은 강하나 전역 설정이 느슨하면 가드 점수가 하락한다.