한국어 · English
증거로 강제하는 정액제 멀티모델 코딩 규약. 한 모델로 만들고, 다른 모델로 리뷰한다 — 그리고 작업이 "정말 끝났는지"는 정중한 프롬프트가 아니라 토큰 0짜리 셸 게이트가 판정한다.
상태: 참조 구현 / 설정 패턴. 거창한 프레임워크가 아니라 규약을 강제하는 작은 도구다. 그 솔직함이 핵심이다.
대부분의 "AI 코딩 하네스" 레포는 모델한테 잘 행동해달라고 부탁하는 프롬프트 더미다. 모델은 컨텍스트가 길어지면 그 부탁을 잊는다. harness-kit은 좋은 아이디어 (두 모델 교차 리뷰, 로그 물증)는 유지하되, 강제(enforcement)를 LLM에서 떼어내 토큰 0으로 도는 결정론적 코드로 내린다.
두 엔진 모두 토큰당 API 키가 아니라 정액 구독으로 인증한다:
| 역할 | 엔진 | 인증 | 과금 |
|---|---|---|---|
| 빌드 / 오케스트레이션 | Claude (CLI) | 구독 | 정액 |
| 리뷰 / 검증 | Codex (codex exec) |
ChatGPT 로그인 | 정액 |
강제층과 이식층이 전부 순수 셸이라, 규약의 약점을 고치는 비용은 정확히 $0 — 종량으로 새어나갈 경로 자체가 없다.
┌─────────────────────────────────────────────────────────────┐
│ 가치층 빌드 + 리뷰 Claude · Codex (구독) │ 정액제, 해자
├─────────────────────────────────────────────────────────────┤
│ 강제층 게이트 + 셀프테스트 bin/gate.sh · tests/ │ 결정론적, 0 토큰
├─────────────────────────────────────────────────────────────┤
│ 이식층 프리플라이트 + 설정 preflight.sh · *.yaml │ 환경 / 모델 무관
└─────────────────────────────────────────────────────────────┘
약점 수정은 아래 두 층만 건드린다. 가치층(네 구독)은 절대 바뀌지 않는다 — 그래서 영영 종량으로 변할 수 없다.
"스마트 라우팅(프롬프트 분류 기반 동적 라우팅)"이라고 하면 보통 요청을 LLM한테 한 번 더 물어봐서 "이건 코딩, 저건 리뷰" 하고 분기하는 걸 떠올린다. 그런데 그 분류 호출 자체가 토큰을 쓴다 — 즉 라우팅하려고 종량 과금 경로를 하나 더 여는 셈이다. 이건 이 키트의 해자(무종량)와 정면으로 충돌한다.
해법은 해자를 만든 트릭과 정확히 똑같다:
강제를 LLM에서 떼어내 토큰 0짜리 셸로 내린 것처럼, 분류도 LLM에서 떼어내 토큰 0짜리 결정론적 규칙으로 내린다.
분류 기준을 모델한테 묻지 않고, 요청의 관찰 가능한 신호로 셸에서 판정한다:
요청 들어옴
└─ 결정론적 분류기 (키워드 · 파일 확장자 · diff 크기 — 토큰 0)
├─ 코드 생성/수정 → Claude CLI (빌드)
├─ 리뷰/검증 요청 → codex exec (리뷰)
└─ 단순 Q&A → Claude만, Codex 호출 스킵
| LLM 분류 (흔한 방식) | 결정론 분류 (이 키트) | |
|---|---|---|
| 분기 판단 | 모델에게 추가 질문 | 키워드·확장자·diff 크기로 셸이 판정 |
| 비용 | 분류마다 토큰 | 0 토큰 |
| 해자 영향 | 종량 경로 신설 | 해자 보존(강화) |
| 재현성 | 호출마다 달라질 수 있음 | 같은 입력 → 항상 같은 분기 |
이게 바로 "프롬프트 분류 기반 동적 라우팅"의 토큰 0짜리 버전이다. 지금 SOUL.md의 "Claude=구현 / Codex=리뷰"는 무조건 고정 분배지만, 여기에 결정론 분류 한 겹만 얹으면 — 리뷰가 필요한 요청에만 Codex를 깨우고, 단순 질문엔 Codex를 건너뛰는 동적 라우팅이 된다. 분류가 셸이라 토큰을 안 쓰니, 해자를 위협하기는커녕 같은 원리로 강화한다.
참고: Hermes 내장 "스마트 라우팅"(프로바이더를 동적 선택)과는 다른 층이다. 그쪽은 분류가 LLM 호출이라 토큰이 들 수 있다. 여기서 말하는 건 프롬프트 층의 결정론적 분기 — 무종량을 지키는 버전이다.
| 파일 | 역할 |
|---|---|
harness.config.yaml |
단일 진실원 — 모델/프로바이더 이름 + 게이트 규칙 |
bin/gate.sh |
게이트: 산출물 + 검증 + 인용된 메트릭이 없으면 "완료"를 막는다 |
bin/preflight.sh |
엔진이 설치돼 있고 구독 인증으로 로그인됐는지 점검한다 |
tests/test_gate.sh |
게이트를 셀프테스트(가짜 프로젝트를 깨뜨려 차단을 검증) |
install.sh |
SOUL.md + 스킬을 Hermes 프로파일에 설치(먼저 백업, 토큰 0) |
hermes/SOUL.md |
드롭인 정체성: 에이전트를 AI 코딩 오케스트레이터로 선언 + 규약을 강제 |
hermes/skills/coding-harness-protocol/SKILL.md |
SOUL이 트리거하는 전체 규약(모델 라우팅 · 12단계 흐름 · 물증 규칙) |
docs/SKILL.en.md |
규약 전문(영문) |
docs/INSTALL_PROMPT.md |
자기 Hermes 에이전트로 설치하는 원페이스트 프롬프트 |
LICENSE |
MIT |
핵심은 텍스트 파일 두 개다: 모든 코딩 요청에 규약을 강제하는 SOUL.md,
그리고 그게 트리거하는 coding-harness-protocol 스킬. install.sh가 둘 다
Hermes 프로파일에 깔아준다(덮어쓰는 건 먼저 백업):
git clone https://github.com/ssap-pa/ssap-free-harness-kit.git
cd ssap-free-harness-kit
./install.sh --dry-run # 미리보기 — 아무것도 안 바꿈
./install.sh # ~/.hermes/SOUL.md + 스킬 설치(백업 포함)
./bin/preflight.sh # Claude + Codex가 구독 인증으로 닿는지 확인기본이 아닌 프로파일에 설치:
HERMES_HOME=~/.hermes/profiles/work ./install.sh에이전트한테 시키고 싶으면 docs/INSTALL_PROMPT.md의
블록을 Hermes 채팅에 붙여넣어라. 설치 후에는 어떤 코딩 요청이든 규약이 자동
로드되고, bin/gate.sh가 통과할 때까지 완료가 막힌다.
| 연결 | 역할 | 방법 |
|---|---|---|
| Claude CLI | 빌드 / 오케스트레이션 엔진 | Hermes 메인 프로바이더 = claude-cli / claude-opus-4-8 |
| Codex CLI | 리뷰 / 검증 엔진 | npm i -g @openai/codex |
| ChatGPT 로그인 | Codex CLI를 돌리는 인증 | codex login → codex login status에 Logged in using ChatGPT 표시 |
bin/preflight.sh가 이 셋을 대신 점검해준다.
| # | 프롬프트-온리 하네스의 약점 | 여기서의 해결 | 비용 |
|---|---|---|---|
| 1 | "반드시 X를 만들어라"는 모델이 건너뛸 수 있는 부탁일 뿐 | 산출물/검증이 없으면 bin/gate.sh가 exit 1 반환 |
0 토큰 |
| 2 | 모델 이름이 곳곳에 하드코딩 → 몇 달 뒤 부패 | 모든 이름은 harness.config.yaml에; 스크립트가 읽음 |
0 토큰 |
| 3 | "로드는 되는데 라우팅할 엔진이 없음" | bin/preflight.sh가 설치 및 구독 로그인 검증 |
0 토큰 |
| 4 | 한글 전용 문서가 다수 독자를 배제 | 영문 README.en.md + docs/SKILL.en.md |
0 토큰 |
| 5 | 하네스 자신엔 테스트가 없었음 | tests/test_gate.sh가 게이트의 차단을 증명 |
0 토큰 |
# 1. 엔진이 구독 인증으로 닿는지 확인
bin/preflight.sh
# 2. ... 작업: Claude가 빌드, `codex exec`가 리뷰, AI_HARNESS_LOG.md + CODEX_REVIEW*.md 작성 ...
# 3. "완료" 선언 전에 프로젝트를 게이트에 통과시킴
bin/gate.sh path/to/project # exit 0 = 허용, exit 1 = 차단
# 게이트 셀프테스트는 언제든
bash tests/test_gate.shbin/gate.sh를 완료-전/stop 훅(또는 CI 단계)에서 호출해라. 그래야 게이트
실패가 실제로 출시를 막는다 — 이게 규약을 부탁에서 보증으로 바꾸는 지점이다.
MIT — LICENSE 참고.