AI 코딩 에이전트를 위한 하네스(harness) 엔지니어링 프레임워크.
사용자가 자연어로 만들고 싶은 것 또는 고치고 싶은 것을 설명하면, 3-에이전트(Planner / Generator / Evaluator)가 계약 기반 스프린트 루프로 코드를 작성·검사·평가하고, 결정적 센서(ruff·mypy·pytest·구조 검사)와 AI 코드 리뷰를 거쳐 PR 생성·리뷰 반영·머지까지 한 흐름으로 연결한다.
"모델은 점점 좋아지지만, 코딩 에이전트의 성능은 모델 주변의 하네스에 더 많이 좌우된다." — 이 프로젝트는 그 명제를 자기 자신에도 적용한다 (
.claude/셋업, 서브패키지 CLAUDE.md, hooks, skills).
처음이라면 아래 4개 명령만 알면 된다.
harness doctor # 1) 환경이 준비됐는지 점검
harness init --offline "프로젝트 설명" # 2) 프로젝트에 하네스 셋업
harness fix "수정 요청" # 3) 현재 프로젝트를 자연어로 수정
harness ship "수정 요청" # 4) 수정 → PR → 리뷰 반영까지 한 번에 (머지·답글은 확인 플래그 필요)
harness pr # 5) (이미 만든 변경을) PR로 올리고 리뷰 반영# 예시: 환경 점검 → 기존 저장소 수정
export HARNESS_API_ENDPOINT="https://your-internal-endpoint"
harness doctor
harness fix "로그인 실패 시 에러 메시지를 명확히 하고 관련 테스트를 보강해주세요"harness fix는 현재 디렉터리를 수정(modify) 모드로 고친다. 작은 수정은 그대로 동작하며, 큰 작업은harness fix --headless "..."로 Phase 단위 실행을 켤 수 있다.harness ship은 수정 → 헤드리스 Phase 구현 → push → PR 생성 → 리뷰 반영까지 한 번에 묶는다. 자동 머지·리뷰 답글은 팀 공유 권한 밖 GitHub 쓰기라--pr-auto-merge --pr-confirm-github-writes를 명시할 때만 동작한다.harness review는 현재 브랜치에 연결된 PR의 리뷰 코멘트만 다시 처리한다.harness init --offline은 LLM 호출 없이 기본 하네스 파일을 깐다. 자연어 의도로 더 보강하려면HARNESS_API_ENDPOINT설정 후--offline을 빼면 된다.- 이 별칭들은 기존 명령(
harness --mode modify,harness-init,harness-doctor,auto-pr-pipeline)을 그대로 감싼 것이다. 세부 옵션과 고급 전략 플래그는 docs/operations.md에 정리되어 있다.
- 빠른 시작
- 핵심 가치
- 어떤 명령을 써야 하나요?
- 요구 사항 / 설치
- 환경변수
- 전체 워크스루: init부터 머지까지 한 흐름으로
- 시나리오별 CLI 레시피
- CLI 옵션 상세
- 핵심 개념
- Claude Code 하네스 레이어 (자기 도그푸딩)
- Claude Code에서 사용하기
- CLI 빠른 참조
- 자주 묻는 질문 (FAQ)
- 트러블슈팅
- 프로젝트 구조
- 산출물 경로
- 프로젝트 정책 파일
- 품질 기준 / 검증
- ADR 목록
- CI/CD
- 라이선스
| 축 | 무엇을 하는가 |
|---|---|
| 3-에이전트 루프 | Planner → Generator → Evaluator. 계약(SprintContract)을 협상하고 스프린트 단위로 진행 (ADR-0001, ADR-0005). |
| 결정적 센서 우선 | ruff → mypy → 구조분석 → pytest를 먼저 실행하고, AI 코드 리뷰는 보조로 이어진다 (ADR-0002). |
| modify 모드 + 프로젝트 정책 | 기존 코드베이스의 diff / ADR / 컨벤션 / 구조 / 정책을 Planner 컨텍스트에 주입, 최소 변경 원칙 (ADR-0008). |
| 헤드리스 Phase + docs-diff | 첫 Phase에서 문서를 갱신하고 docs-diff.md를 생성한 뒤, 이후 Phase가 컨텍스트 격리된 claude --print 세션으로 순차 실행된다 (ADR-0009). |
| 고정 구조 게이트 | modify/resume/PR 산출물 생성 전에 docs/, tests/, scripts/, 정책 package 등 필수 구조를 확인하고, 누락 시 harness-init --migrate를 안내한다 (ADR-0010, ADR-0011). |
| 결정적 평가 게이트 | 스프린트 평가 직전에 파이프라인을 다시 실행하고, 결정적 검사와 LLM 평가가 모두 pass일 때만 최종 pass로 판정한다 (ADR-0012). |
| PR 자동화 | push → PR → 코멘트 수집 → ACCEPT/DEFER/IGNORE 분류 → ACCEPT만 반영. 한국어 답글과 선택적 머지는 확인 플래그가 있을 때만 실행. CodeRabbit 코멘트도 동일 흐름. |
| 부트스트랩(harness-init) | 외부 프로젝트에 ADR/컨벤션/구조/정책/CLAUDE.md와 .claude 팀 설정·Stop 훅을 일괄 배치. LLM이 자연어 의도로 보강. |
| 자기 도그푸딩 | 본 저장소 스스로 hooks·skills·서브패키지 CLAUDE.md를 적용. CRITICAL 규칙은 모델 기억력이 아니라 hook으로 강제된다. |
처음이라면 빠른 시작의 4개 별칭으로 충분하다. 아래 표는 별칭과 그에 대응하는 전체 명령, 그리고 상황별 선택지를 정리한 것이다. 고급 전략 플래그(--use-headless-phases, --allow-empty-docs-diff, --headless-phase-timeout)는 docs/operations.md에 따로 모아두었다.
| 하고 싶은 일 | 별칭(권장) | 대응하는 전체 명령 |
|---|---|---|
| 시작 전 환경이 준비됐는지 확인하기 | harness doctor |
harness-doctor |
| 프로젝트에 하네스 규칙 파일 깔기 | harness init --offline "프로젝트 설명" |
harness-init --offline "프로젝트 설명" |
| 현재 저장소를 자연어로 수정하기 | harness fix "수정 요청" |
harness --mode modify "수정 요청" |
| 큰 작업을 Phase로 나눠 안정적으로 진행하기 | harness fix --headless "수정 요청" |
harness --mode modify --use-headless-phases --allow-empty-docs-diff "수정 요청" |
| 수정 → PR → 리뷰 반영을 한 번에 (머지·답글 제외) | harness ship "수정 요청" |
harness --mode modify --use-headless-phases --allow-empty-docs-diff --auto-pr --pr-base main "수정 요청" |
| (이미 만든) 변경을 PR로 올리고 리뷰 반영하기 | harness pr |
auto-pr-pipeline |
| 현재 PR의 리뷰 코멘트만 다시 처리하기 | harness review |
auto-pr-pipeline --current-pr |
별칭으로 표현하기 어려운 세부 시나리오(오프라인 부트스트랩, 골격 생성, 마이그레이션, 기존 PR 번호 지정, PR 본문만 생성 등)는 아래 시나리오별 CLI 레시피와 docs/operations.md를 참고한다. 별칭 뒤에는 대응 명령의 모든 플래그를 그대로 붙일 수 있다(예: harness fix --auto-pr --pr-base main "...").
- Python 3.11 이상
- Git (worktree 격리·diff 기반 기능에 사실상 필수)
- (선택)
ghCLI — PR 자동화 / CodeRabbit 연동 시. 사전에gh auth login인증 필요.
git clone <repo-url>
cd python-harness
python3 -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]" # 개발 의존성 포함 (ruff, mypy, pytest, types-PyYAML)pip install -e . 후 다음 5개 CLI가 등록된다:
| CLI | 대응 스크립트 | 용도 |
|---|---|---|
harness |
scripts/run_harness.py |
메인 실행 (create/modify/resume) |
auto-pr-pipeline |
scripts/auto_pr_pipeline.py |
PR 자동화 파이프라인 |
create-pr-body |
scripts/create_pr_body.py |
PR 본문 생성 |
harness-init |
scripts/init_harness.py |
신규/기존 프로젝트 부트스트랩 |
harness-doctor |
scripts/doctor.py |
GitHub/Python 사전 점검 (git·gh·도구·정책 확인) |
harness는 다시 초보자용 서브커맨드 doctor / init / fix / ship / pr / review를 흡수한다. 각각 harness-doctor·harness-init·harness --mode modify(+ PR 자동화)·auto-pr-pipeline로 위임하는 별칭이라, entrypoint 개수(5개)와는 별개다.
| 이름 | 설명 | 필수 |
|---|---|---|
HARNESS_API_ENDPOINT |
Planner / Generator / Evaluator / AI 리뷰가 호출할 비공개 API 엔드포인트 | AI 호출 시 필수 |
CLAUDE_HOOK_SKIP |
1로 설정 시 Stop hook(.claude/hooks/post_session_checks.sh)을 우회 (CI/임시 디버깅용) |
선택 |
HARNESS_API_ENDPOINT를 환경변수로 두는 대신 실행 시 --api-endpoint로 직접 넘길 수도 있다. 토큰·비밀값을 커밋하지 않는다.
예시:
export HARNESS_API_ENDPOINT="https://your-internal-endpoint"
# 환경변수를 쓰고 싶지 않은 일회성 실행
harness --api-endpoint "https://your-internal-endpoint" \
--mode modify "회원가입 에러 처리를 보강해주세요"빈 디렉터리에서 시작해 PR 리뷰 답글·머지까지 도달하는 가장 흔한 경로를 한 시나리오로 잇는다. 각 단계는 앞 단계의 산출물을 그대로 사용하므로 위에서부터 차례로 따라가면 된다. 특정 작업만 빠르게 찾고 싶으면 아래 시나리오별 CLI 레시피를 본다.
가정: 사내 청구 자동화 도구를 새로 만들고, 첫 기능으로 "결제 재시도 로직"을 추가한 뒤 PR을 올려 CodeRabbit + 동료 리뷰를 받아 머지하는 상황.
export HARNESS_API_ENDPOINT="https://your-internal-endpoint" # ~/.zshrc 등에 영구 저장 권장
gh auth login # PR 자동화에서 필요
pip install -e ".[dev]" # 본 저장소 클론한 경우mkdir -p ~/projects/billing && cd ~/projects/billing
git init
harness-init --offline "사내 청구 자동화 도구. Python 3.11, FastAPI, PostgreSQL."
git add -A && git commit -m "chore: bootstrap harness"이 시점에 생기는 것:
docs/adr/0001-initial-architecture.md,docs/code-convention.yaml,harness_structure.yaml.harness/project-policy.yamlCLAUDE.md,.claude/settings.json,.claude/hooks/post_session_checks.sh
CodeRabbit 리뷰까지 함께 쓰려면 --with-coderabbit로 .coderabbit.yaml을 같이 배포한다(설정 파일만 만들며, GitHub 저장소의 CodeRabbit App 설치·권한 승인은 별도).
⚠️ knowledge_base.code_guidelines에 의해CLAUDE.md,docs/adr/*.md,.harness/project-policy.yaml이 CodeRabbit(third-party SaaS)으로 전송된다. 사내 정보가 포함될 수 있으니 노출 가능 여부를 확인한 뒤 사용하라.
이미 코드가 있는 저장소라면 1단계는
harness-init --migrate --offline "..."로 대체한다 (기존 README/스킬은 보존,src/레이아웃 자동 인식).
claude # 또는 VS Code/JetBrains에서 폴더 열기진입과 동시에 .claude/settings.json의 permission, Stop hook, PreToolUse guard가 자동 활성화된다. 이후 단계는 Claude와 대화로 진행해도 되고, 셸에서 직접 CLI를 쳐도 동일하다.
Claude Code 안에서:
사용자:
결제 모듈에 재시도 횟수 환경변수(MAX_RETRY)와 지수 백오프를 추가하고, 단위 테스트와 문서까지 갱신한 뒤 PR을 올려줘
또는 셸에서 직접. 별칭 harness ship이 가장 짧고, 전체 옵션을 직접 통제하려면 풀 명령을 쓴다(둘은 동일한 파이프라인이다):
# 별칭 — 수정 → 헤드리스 Phase 구현 → PR 생성 → 리뷰 반영 (머지·답글 제외)
harness ship "결제 모듈에 재시도 횟수 환경변수(MAX_RETRY)와 지수 백오프를 추가하고, 단위 테스트와 문서를 갱신해주세요"
# 동일한 풀 명령 (harness ship이 확장하는 형태)
harness --mode modify --use-headless-phases --allow-empty-docs-diff \
--auto-pr --pr-base main \
"결제 모듈에 재시도 횟수 환경변수(MAX_RETRY)와 지수 백오프를 추가하고, 단위 테스트와 문서를 갱신해주세요"내부 진행:
- diff·ADR·컨벤션·구조·정책 수집 → Planner 컨텍스트 주입
- Planner →
SprintContract생성 phase-01-docs-update→docs-diff.md갱신 → 이후 Phase가claude --print독립 세션으로 순차 실행- Phase 사이 20줄 핸드오프 (
phase-handoff스킬) - Evaluator가 결정적 센서(ruff/mypy/structure/pytest) + LLM 평가로 최종 판정 (ADR-0012)
- 통과하면 push → PR 본문 자동 생성 → PR 오픈
--auto-pr로 이어지는 전체 파이프라인(머지·답글 플래그 포함)의 단계:
1. 컨텍스트 수집 (diff, ADR, 컨벤션, 구조, 정책)
2. Planner → 수정 계획
3. Phase별 구현 (docs-update → core-impl → integration → tests → validation)
4. Evaluator 평가 (ruff, mypy, pytest, 구조)
5. ──── 여기까지가 구현 단계 ────
6. git push → PR 생성 (PR 본문 자동 생성)
7. 리뷰 코멘트 수집 (사람 + CodeRabbit)
8. ACCEPT / DEFER / IGNORE 분류 → ACCEPT만 자동 반영
9. 반영 커밋 push
10. (--pr-confirm-github-writes가 있으면) 원본 코멘트에 한국어 답글
11. (--pr-auto-merge --pr-confirm-github-writes가 있으면) PR 머지
구현이 실패하면(통과 스프린트 0개) PR 단계를 건너뛴다. PR 파이프라인 실패는 구현 결과에 영향을 주지 않는다. CI 게이트에서 PR 실패까지 잡으려면
--fail-on-pr-error를 더한다.
중간 점검:
cat .harness/artifacts/summary.json # 실행 요약
ls .harness/tasks/sprint-1/ # Phase별 산출물
cat .harness/tasks/sprint-1/docs-diff.md # 문서 변경 요약PR이 열린 뒤 사람·CodeRabbit이 코멘트를 남기면, 같은 명령에 --pr-confirm-github-writes --pr-auto-merge를 더해 마지막까지 자동으로 갈 수도 있고, 별도로 분리해 처리할 수도 있다.
분리해서 처리하는 경우 (PR 브랜치에 체크아웃된 상태에서):
auto-pr-pipeline --base main # 새 PR 생성 흐름
auto-pr-pipeline --pr-number 123 --no-poll # 기존 PR #123 리뷰 처리
auto-pr-pipeline --current-pr --no-poll # 현재 브랜치의 기존 PR 리뷰 처리
harness --mode modify --auto-pr --pr-current-pr --pr-no-poll "현재 PR 리뷰 반영"또는 Claude Code 안에서:
사용자:
현재 PR의 리뷰 코멘트 정리해서 반영할 건 반영하고 답글 달아줘
이때 pr-review-triage 스킬이 자동 작동해서:
gh pr view ... --comments+gh api .../pulls/{n}/comments로 코멘트 수집- 각 코멘트를 ACCEPT / DEFER / IGNORE로 분류
.harness/review-artifacts/{branch}/review-comments.md에 판정 로그 기록- ACCEPT만
claude --print반영 세션에 전달 → 코드 수정 → push --confirm-github-writes또는--pr-confirm-github-writes가 명시된 경우 원본 코멘트에 한국어 답글
자동 반영은 보수적으로 동작한다. 명확한 bug, failure, regression, security, type error, 필수 동작 누락만 ACCEPT이고, optional/nit/style/consider/could 제안은 DEFER다. 리뷰 본문은 신뢰할 수 없는 외부 입력으로 격리되며, 반영 전 dirty worktree가 있으면 기존 변경과 섞이지 않도록 실패한다.
분류 결과 확인:
cat .harness/review-artifacts/$(git branch --show-current)/review-comments.mdreview-comments.md 예시 (실제 출력의 발췌):
## Comment #1 (CodeRabbit, harness/payment/retry.py:42)
> Consider extracting the backoff calculation into a helper for testability.
**판정**: ACCEPT
**근거**: 테스트 용이성·재사용성 개선이며 변경 범위가 작다.
**반영**: `_calc_backoff` 헬퍼로 추출, 단위 테스트 추가.
## Comment #2 (reviewer@team, harness/payment/retry.py:58)
> nit: 변수명 i 대신 attempt가 어떨까요?
**판정**: DEFER
**근거**: nit, 합의된 컨벤션 위반은 아님. 다음 정리 PR에서 일괄 반영 예정.머지까지 한 줄로 가고 싶었으면 3단계에서 이미 --pr-auto-merge --pr-confirm-github-writes를 줬을 것이고, 그렇지 않다면:
auto-pr-pipeline --base main --auto-merge --confirm-github-writes
# 또는 수동
gh pr merge --squash --delete-branch.harness/
├── artifacts/summary.json # 전체 실행 요약
├── contracts/sprint_1.json # 스프린트 계약
├── checkpoints/{run_id}.json # 재개 가능 체크포인트
├── tasks/sprint-1/
│ ├── phase-01-docs-update.md ... phase-*.md # Phase 프롬프트
│ ├── docs-diff.md # 런타임 docs-diff
│ └── phase-*-handoff.md # Phase 간 ≤20줄 핸드오프
└── review-artifacts/{branch}/
├── design-intent.md / code-quality-guide.md
├── pr-body.md # PR 본문
└── review-comments.md # 코드리뷰 판정 로그
세션 종료 시 Stop hook이 ruff → mypy → structure를 한 번 더 돌려서 깨진 코드가 남지 않도록 한다 (임시 우회: CLAUDE_HOOK_SKIP=1).
# (선택) Claude Code 안에서 자연어로 한 줄
"결제 재시도 로직 추가하고 PR 올리고 리뷰 코멘트도 반영해줘"
# 별칭 한 줄 (수정 → PR → 리뷰 반영; 머지·답글 제외)
harness ship "결제 재시도 로직 추가, 단위 테스트·문서 갱신 포함"
# 머지·답글까지 직접 통제하는 한 줄
harness --mode modify --use-headless-phases \
--auto-pr --pr-base main --pr-auto-merge --pr-confirm-github-writes \
"결제 재시도 로직 추가, 단위 테스트·문서 갱신 포함"harness-init만 한 번 깔아두면, 이후 모든 변경은 위 한 줄(또는 자연어 한 문장)로 init·구현·PR·리뷰 반영·머지가 일관된 파이프라인으로 이어진다. 단, 리뷰 답글(gh api --method POST)과 머지(gh pr merge)는 팀 공유 permission 밖 작업이라 확인 플래그가 붙은 실행은 Claude Code에서 별도 승인을 거친다.
"무엇을 하고 싶은지 → 어떤 명령을 칠지" 매핑. 처음 쓰는 사람은 위에서부터 차례로 따라가면 된다.
mkdir -p ~/projects/billing && cd ~/projects/billing
git init
harness-init --offline "사내 청구 자동화 도구. Python 3.11, FastAPI, PostgreSQL"
git add -A && git commit -m "chore: bootstrap harness"확인:
ls docs/adr/ .harness/ .claude/ # ADR/정책/Claude 셋업이 보여야 함LLM 호출 없이 템플릿만 깔고 싶으면 --offline을 그대로 둔다. 사후에 LLM으로 보강하고 싶으면 --offline을 떼고 HARNESS_API_ENDPOINT를 설정한 뒤 같은 명령을 다시 친다 (--force 필요).
cd /path/to/existing-python-repo
harness-init --migrate --offline "기존 Python 서비스에 하네스 적용"생성·보강 대상은 ADR, 코드 컨벤션, 구조 규칙, 프로젝트 정책이다. tests/와 scripts/가 비어 있으면 .gitkeep만 둔다. 기존 CLAUDE.md와 .claude/skills/는 보존한다.
cd /path/to/repo
export HARNESS_API_ENDPOINT="https://your-internal-endpoint"
harness --mode modify "결제 모듈에 재시도 횟수 환경변수(MAX_RETRY)를 추가해주세요"진행 상태 확인:
cat .harness/artifacts/summary.json
ls .harness/contracts/harness --mode modify --use-headless-phases \
"장바구니 도메인 모델을 신규 사양에 맞게 리팩터링해주세요"이때 일어나는 일:
phase-01-docs-update가 먼저 돌면서docs-diff.md가 생성된다- 이후
phase-02-core-impl,phase-03-integration, ... 가 각각 독립claude --print세션으로 실행된다 - Phase 사이에는 20줄 핸드오프 파일이 남는다
진행 상태:
ls .harness/tasks/sprint-1/
cat .harness/tasks/sprint-1/phase-01-docs-update-handoff.mdgh auth login # 처음 한 번만
harness --mode modify --use-headless-phases \
--auto-pr --pr-base main --pr-auto-merge --pr-confirm-github-writes \
"결제 취소 플로우의 테스트 커버리지를 80% 이상으로 끌어올려주세요"이 한 줄이 push → PR 생성 → 리뷰 수집 → ACCEPT 코멘트 반영 → 한국어 답글 → 머지까지 자동 수행한다. 머지 직전에 멈추고 싶으면 --pr-auto-merge만 뺀다. 답글도 남기지 않으려면 --pr-confirm-github-writes를 빼면 된다. 머지·답글을 뺀 기본 흐름은 별칭 harness ship "..."으로 더 짧게 쓸 수 있다(필요하면 harness ship --pr-auto-merge --pr-confirm-github-writes "...").
cd /path/to/repo # PR 브랜치로 체크아웃된 상태
auto-pr-pipeline --base main판정 결과는 .harness/review-artifacts/{branch}/review-comments.md에 남는다. ACCEPT 코멘트만 반영되고, DEFER/IGNORE는 사유만 기록된다.
harness --resume # 가장 최근 run 이어서
# 또는 여러 run이 섞여 있으면 run_id 명시
ls .harness/checkpoints/
harness --run-id <run_id>harness --mode modify --use-headless-phases --allow-empty-docs-diff \
"오타 수정 / 단순 로깅 메시지 변경 등"이 옵션은 명시적 예외다. 기본은 "문서 갱신을 강제"하므로, 빠뜨리고 싶지 않은 변경이 있다면 옵션을 빼고 프롬프트에 문서 갱신 의도를 적는 편이 안전하다.
create-pr-body --base main --output pr-body.md
gh pr create --base main --body-file pr-body.mdharness-init은 .claude/settings.json과 hook만 배포한다. 스킬은 수동 복사가 필요하다.
# 외부 프로젝트 루트에서
cp -R /path/to/python-harness/.claude/skills .claude/skills각 CLI의 자주 쓰는 옵션과 의미. 전체는 --help 또는 docs/operations.md 참조.
| 옵션 | 의미 |
|---|---|
"프롬프트" |
인자로 자연어 의도를 그대로 전달 |
--mode {create,modify} |
create(기본): 새 프로젝트 생성, modify: 현재 코드 수정 |
--use-headless-phases |
Phase별로 claude --print 독립 세션 실행 (큰 작업에서 안정적) |
--allow-empty-docs-diff |
docs-update Phase에서 문서가 안 바뀌어도 통과시킴 (예외 명시) |
--auto-pr |
구현 성공 시 PR 파이프라인 연결 |
--pr-base <branch> |
PR 대상 베이스 브랜치 (예: main) |
--pr-title "..." |
새 PR 생성 시 제목 직접 지정 |
--pr-number <N> |
새 PR을 만들지 않고 기존 PR 번호의 리뷰 처리 |
--pr-current-pr |
현재 브랜치에 연결된 기존 PR 리뷰 처리 |
--pr-no-poll |
리뷰 코멘트 폴링 비활성화 |
--pr-auto-merge |
리뷰 반영 후 자동 머지 |
--pr-confirm-github-writes |
팀 allow 밖 GitHub 쓰기(리뷰 답글, 머지)를 명시 승인 |
--pr-skip-review |
PR 생성까지만 하고 리뷰 수집/반영 건너뜀 |
--fail-on-pr-error |
PR 파이프라인에 오류가 있으면 구현이 성공했어도 종료 코드 1로 끝냄 (CI 게이트용) |
--project-dir <path> |
현재 디렉터리 대신 다른 저장소를 대상으로 |
--api-endpoint <url> |
HARNESS_API_ENDPOINT 환경변수 대신 한 번만 지정 |
--resume |
같은 디렉터리의 최근 체크포인트 이어서 실행 |
--run-id <id> |
특정 run의 체크포인트로 재개 |
modify 모드는 외부 Python 프로젝트 적응을 위해 pyproject.toml, requirements*.txt, setup.py, uv.lock, poetry.lock, Pipfile 존재 여부와 package manager, src/flat 레이아웃, pydantic v1/v2, requests/httpx, click/typer/argparse, pytest/unittest 힌트, 최근 커밋 메시지 일부를 짧게 수집한다. 비밀값이나 환경변수 값은 수집하지 않고 요약만 Planner 컨텍스트에 포함한다.
| 옵션 | 의미 |
|---|---|
--base <branch> |
PR 대상 베이스 (필수에 가까움) |
--auto-merge |
리뷰 반영 후 머지까지 |
--confirm-github-writes |
팀 allow 밖 GitHub 쓰기(리뷰 답글, 머지)를 명시 승인 |
--skip-review |
리뷰 수집/반영 단계 생략 |
--title "..." |
PR 제목 직접 지정 (기본은 자동 생성) |
--pr-number <N> |
새 PR을 만들지 않고 기존 PR 번호의 리뷰 처리 |
--current-pr |
현재 브랜치에 연결된 기존 PR 리뷰 처리 |
--no-poll |
리뷰 코멘트 폴링 비활성화 |
| 옵션 | 의미 |
|---|---|
--base <branch> |
diff 기준 베이스 |
--output <path> |
결과를 파일로 저장 (없으면 stdout) |
--summary "..." |
자동 요약 대신 직접 지정 |
--branch <name> |
브랜치 이름 오버라이드 |
--use-worktree |
git worktree로 격리해서 실행 |
| 옵션 | 의미 |
|---|---|
"의도" |
프로젝트의 자연어 설명 (LLM 보강에 사용) |
--offline |
LLM 호출 없이 내장 템플릿만으로 셋업 |
--project-dir <path> |
다른 디렉터리에 셋업 |
--only <kinds> |
일부만 배포 (adr,policy,claude-config,coderabbit,pyproject,gitignore,ci,smoke,package-init 등 콤마 구분) |
--scaffold |
규칙 파일에 더해 Python 골격(pyproject.toml, .gitignore, .github/workflows/ci.yml, tests/test_smoke.py, {패키지}/__init__.py)까지 배포 |
--with-coderabbit |
.coderabbit.yaml 배포 + 기존 정책 파일의 review_tools.coderabbit를 true로 동기화 (GitHub App 설치는 별도) |
--force |
기존 파일 덮어쓰기 (기본은 보존) |
--dry-run |
만들 파일 목록만 보여주고 실제로 쓰지 않음 |
--migrate |
기존 Python 프로젝트에 하네스 필수 구조를 보강 (adr,convention,structure,policy 중심). src/ 레이아웃 자동 인식 |
GitHub/Python 워크플로를 시작하기 전에 환경이 준비됐는지 한 번에 점검한다. 실패 항목마다 한국어 원인과 다음 조치를 보여주고, 하나라도 실패하면 종료 코드 1로 끝난다.
| 옵션 | 의미 |
|---|---|
--project-dir <path> |
점검할 저장소 경로 (기본: 현재 디렉터리) |
--api-endpoint <url> |
HARNESS_API_ENDPOINT 설정 여부 점검 시 직접 지정 |
점검 항목: git 저장소 여부, origin remote, 현재/기본 브랜치, git·gh·ruff·mypy·pytest·claude 설치, gh 인증, API 엔드포인트, .harness/project-policy.yaml·harness_structure.yaml·docs/code-convention.yaml·ADR 문서 존재. 현재 브랜치 점검은 detached HEAD 상태를 실패로 처리한다(PR 자동화는 실제 브랜치를 요구).
- Planner: 사용자 프롬프트(+ modify 시 컨텍스트) →
ProductSpec/ 스프린트 계획 - Generator:
SprintContract대로 파일 변경 - Evaluator: 계약 + 품질 기준 충족 여부 평가
- Orchestrator: 위 3개를 잇는 루프 + 재시도 + 체크포인트
계약은 .harness/contracts/sprint_{N}.json에 raw 텍스트와 함께 구조화 저장된다 (ADR-0005).
harness/pipeline/harness_pipeline.py가 다음 순서로 실행한다 (ADR-0002):
ruff → mypy → 구조분석(harness_structure.yaml) → pytest → AI 코드 리뷰
앞 단계가 실패하면 빠르게 끊고, 비용 큰 AI 단계로 가지 않는다. 모든 단계는 harness/sensors/의 센서 객체가 담당하고, 센서는 에이전트에 의존하지 않는다 (구조 검사로 강제).
스프린트 최종 평가는 결정적 파이프라인과 LLM 평가를 분리해 기록한다. 둘 중 하나라도 실패하면 최종 스프린트는 fail이다 (ADR-0012).
.harness/project-policy.yaml이 있으면 컨벤션·ADR·구조 규칙 경로와 프로젝트별 정책을 반영한다. 정책 파일이 없거나 파싱 실패 시 기본 정책으로 폴백 (예외 전파 금지). 외부 ADR 디렉터리(adr.external_sources)도 지원 (ADR-0008).
modify 모드는 최소 변경, 기존 패턴 재사용, 정책 준수가 기본 원칙이다.
modify/resume, PR 본문 생성, PR 자동화 시작 전에는 고정 구조 게이트도 실행된다. 필수 경로(docs/, docs/adr/*.md, docs/code-convention.yaml, harness_structure.yaml, .harness/project-policy.yaml, tests/, scripts/, 정책의 패키지 디렉터리)가 없으면 실행을 중단하고 harness-init --migrate를 안내한다. 패키지 디렉터리는 정책의 project.package와 project.source_root를 합친 경로(flat은 <패키지>, src 레이아웃은 src/<패키지>)로 확인한다 (ADR-0010, ADR-0014).
--use-headless-phases 사용 시 오케스트레이터는 스프린트 계약 후:
.harness/tasks/sprint-{N}/phase-*.md자기 완결 프롬프트 생성phase-01-docs-update로 문서 갱신 →docs-diff.md생성- 이후 Phase를 컨텍스트 격리된
claude --print세션으로 순차 실행 - 각 Phase는 20줄 이내 핸드오프를 다음 Phase에 남긴다
기본 정책은 docs-diff가 비어 있으면 실패다. 예외는 --allow-empty-docs-diff로 명시 (ADR-0009).
scripts/auto_pr_pipeline.py는 push → PR → 리뷰 수집 → 분류 → ACCEPT 반영 순서로 기본 동작한다. 답글(gh api --method POST)과 선택적 머지(gh pr merge)는 --confirm-github-writes가 명시된 경우에만 실행한다.
- 코멘트 판정: ACCEPT (즉시 반영) / DEFER (가치는 있으나 범위 밖) / IGNORE (잘못된 지적·칭찬·중복)
- ACCEPT만
claude --print반영 세션에 전달 - CodeRabbit: 외부 리뷰어로 동일 흐름. optional/nit/칭찬성은 DEFER.
- 판정 로그:
.harness/review-artifacts/{branch}/review-comments.md - 답글은 한국어. GitHub review thread resolve는 API 제약 때문에 답글 기반 확인으로 대체. 답글 작성은 팀 공유 permission 밖 GitHub 쓰기라 확인 플래그가 필요하다.
분류·답글 형식은 .claude/skills/pr-review-triage/SKILL.md가 표준이다.
외부 프로젝트나 신규 저장소에 하네스 규칙 묶음을 한 번에 배치한다. ADR/컨벤션/구조/정책/CLAUDE.md와 .claude 팀 설정 + 안전한 Stop 훅 + LLM 보강 + 템플릿 폴백 + dry-run을 지원한다. 생성되는 no_print_debug 구조 규칙은 severity: error라서 외부 프로젝트에서도 print() 디버깅은 구조 검사 실패로 이어진다.
.claude/settings.json은 LLM에 위임하지 않는다 (_LLM_SKIP_KINDS — JSON 보안 설정은 결정적 템플릿만). --only claude-config는 .claude/settings.json과 .claude/hooks/post_session_checks.sh를 함께 배포한다. 기존 settings.json은 보존하되 Stop hook 스크립트가 누락된 경우에는 sidecar hook만 복구한다.
기존 Python 프로젝트에는 harness-init --migrate를 사용한다. 이 경로는 ADR/컨벤션/구조/정책만 대상으로 삼고, 단일 Python 패키지를 정책의 project.package에 고정한다. 루트 패키지뿐 아니라 src/<패키지> 레이아웃도 자동 인식해 정책에 project.source_root: src를 기록한다 (ADR-0014). 패키지 후보가 여러 개라 자동 선택이 위험한 경우에는 명확한 오류로 멈추고 정책에 명시할 패키지를 요구한다 (ADR-0011).
⚠️ harness-init은.claude/settings.json과 hook만 배포하고.claude/skills/는 배포하지 않는다. 외부 프로젝트에서 본 저장소의 스킬을 사용하려면.claude/skills/{name}/디렉터리를 수동으로 복사한다.
본 저장소는 자신이 외부에 권장하는 하네스 5계층을 자기 자신에 적용한다.
| 계층 | 위치 | 역할 |
|---|---|---|
| CLAUDE.md (얇게, 계층적) | 루트 + 9개 서브패키지 | 루트는 포인터·CRITICAL만(≈65줄), 서브패키지별 로컬 규칙은 작업 시에만 추가 로드 |
| Hooks | .claude/hooks/ |
post_session_checks.sh (Stop: ruff→mypy→structure), guard_no_print.py (PreToolUse: harness/ 내 print( 차단) |
| Skills | .claude/skills/ |
pr-review-triage, adr-author, phase-handoff — 작업별 progressive disclosure |
| 팀 공유 설정 | .claude/settings.json (커밋) |
allow/deny + hooks 연결. 개인 오버라이드는 .claude/settings.local.json(.gitignore) |
| 운영 가이드 분리 | docs/operations.md | CLAUDE.md에서 빼낸 명령어·정책 상세를 한 곳에 |
| 부트스트랩 배포 채널 | harness-init이 위 셋업을 함께 배포 |
외부 프로젝트가 첫날부터 동일 검증 환경 |
의미: CRITICAL 규칙이 "모델이 기억해야 하는 것"에서 "시스템이 강제하는 것"으로 이동했다. 예) 본 저장소의 harness/에 print( 작성 시도는 hook이 즉시 차단(exit 2), 외부 프로젝트의 print() 디버깅은 no_print_debug error 구조 규칙으로 실패, 세션 종료 시 ruff/mypy/structure 자동 실행, ADR/리뷰 작업 시 skill 형식 자동 로드.
본 저장소를 클론한 뒤 Claude Code(claude CLI / IDE)에서 열면 별도 설정 없이 hooks·skills·서브패키지 CLAUDE.md가 자동 적용된다.
| 무엇 | 위치 | 동작 시점 | 사용자가 느끼는 효과 |
|---|---|---|---|
| 팀 공유 permission | .claude/settings.json |
세션 시작 시 | ruff/mypy/pytest/gh pr view·list·diff·status·checks·comment·create 등이 매번 승인을 묻지 않고 바로 실행됨. gh api 쓰기와 gh pr merge는 확인 플래그 실행이 deny에 걸려 별도 승인이 필요 |
| Stop hook | .claude/hooks/post_session_checks.sh |
세션 종료 시 | ruff → mypy → structure 검사가 자동 실행돼 깨진 코드를 남기지 않음. 임시 우회는 CLAUDE_HOOK_SKIP=1 |
| PreToolUse guard | .claude/hooks/guard_no_print.py |
Write/Edit/MultiEdit 직전 |
harness/ 내부에 print(을 적는 시도는 exit 2로 즉시 차단. CRITICAL 규칙이 시스템 레벨로 강제됨 |
| 서브패키지 CLAUDE.md | harness/*/CLAUDE.md |
해당 디렉터리 파일을 읽을 때 | 작업 중인 영역의 로컬 규칙만 추가로 컨텍스트에 들어옴 (루트는 얇게 유지) |
세 가지 스킬이 등록되어 있다. 명시적으로 호출하지 않아도 description의 트리거 조건에 맞으면 Claude가 자동으로 따른다. 슬래시 명령으로 강제 호출도 가능.
| 스킬 | 자동 트리거 | 슬래시 호출 | 정의 |
|---|---|---|---|
pr-review-triage |
gh pr view / gh api .../comments 결과 처리, auto-pr-pipeline 실행, review-comments.md 작성 |
/pr-review-triage |
SKILL.md |
adr-author |
"ADR 작성", "결정 사항 기록", "아키텍처 결정" 등의 발화 | /adr-author |
SKILL.md |
phase-handoff |
--use-headless-phases 실행 중 한 Phase 종료 직전 |
/phase-handoff |
SKILL.md |
💡 스킬은 "지시"가 아니라 "형식"이다. Claude가 작업을 할 때 어떤 출력 형식·판정 규칙·파일 위치를 따라야 하는지를 표준화한다. 따라서 같은 작업이라도 스킬이 적용되면 결과가 일관된다.
무엇을 해주는가
PR에 달린 사람·CodeRabbit 코멘트를 ACCEPT / DEFER / IGNORE로 분류하고, ACCEPT만 코드에 반영한다. 한국어 답글 작성은 --confirm-github-writes 또는 --pr-confirm-github-writes가 명시된 승인 흐름에서만 수행한다.
언제 자동으로 트리거되는가
- "PR 리뷰 코멘트 반영해줘", "CodeRabbit 코멘트 처리해줘" 같은 요청
gh pr view,gh api repos/.../pulls/{n}/comments를 실행한 결과를 다룰 때auto-pr-pipeline내부에서 자동 호출
예시 대화
사용자:
현재 PR #42에 달린 리뷰 코멘트를 검토해서 반영할 건 반영하고 답글 달아줘
Claude는 이때:
gh pr view 42 --comments로 코멘트 수집- 각 코멘트를 ACCEPT/DEFER/IGNORE로 분류 (스킬의 표를 따름)
.harness/review-artifacts/{branch}/review-comments.md에 판정 로그 작성- ACCEPT 코멘트만 코드에 반영 후 push
- 원본 코멘트에 한국어로 답글
산출물 확인
cat .harness/review-artifacts/$(git branch --show-current)/review-comments.md수동 강제 호출
사용자:
/pr-review-triage PR #42
분류 기준 요약 (자세히는 SKILL.md)
| 판정 | 조건 |
|---|---|
| ACCEPT | 버그·보안·계약 위반, ADR/컨벤션 위반, 합의된 개선 |
| DEFER | 가치는 있으나 범위 밖, nit·취향, optional 제안 (CodeRabbit Refactor suggestion 등) |
| IGNORE | 잘못된 지적, 중복, 칭찬성 |
무엇을 해주는가 ADR(Architecture Decision Record)을 정해진 형식·번호 규칙·한국어 본문으로 작성하거나 갱신한다. 결번 없는 번호 부여, 상태 라벨, 배경/결정/결과 섹션을 표준화한다.
언제 자동으로 트리거되는가
- 발화에 "ADR 작성", "결정 사항 기록", "아키텍처 결정"이 포함될 때
- 코드 변경이 아키텍처 결정을 동반해야 할 때 (새 검사 단계 추가, 의존성 방향 변경 등)
예시 대화
사용자:
센서가 LLM 호출 캐싱을 갖도록 바꾸려고 해. ADR로 기록해줘
Claude는 이때:
docs/adr/디렉터리를 확인해 다음 번호 결정 (현재 0001~0015 →0016-...)- 스킬이 정의한 형식대로
0016-inferential-sensor-caching.md생성 - 상태(Proposed/Accepted), 배경, 결정, 결과, 대안, 관련 ADR 섹션 채움
산출물 확인
ls docs/adr/ # 0016-... 가 추가됨수동 강제 호출
사용자:
/adr-author "헤드리스 Phase 도입"
무엇을 해주는가 헤드리스 Phase 실행에서 각 Phase가 다음 Phase로 넘기는 20줄 이내 요약을 표준 형식으로 작성한다. Phase 간 컨텍스트 격리에도 필수 정보가 새지 않게 한다.
언제 자동으로 트리거되는가
harness --mode modify --use-headless-phases로 실행되는 각 Phase가 종료될 때.harness/tasks/sprint-{N}/{phase_id}-handoff.md파일 작성·갱신 시점
핸드오프 형식
# Handoff — phase-02-core-impl
## 한 줄 요약
결제 도메인 엔티티를 신규 사양에 맞게 분리했다.
## 변경된 파일 (경로만, 최대 10개)
- src/payment/entity.py
- src/payment/dto.py
## 다음 Phase가 알아야 할 사실
- DTO 변환은 아직 미적용. integration Phase에서 처리 필요.
- 기존 호출처는 호환 어댑터로 임시 연결.산출물 확인
ls .harness/tasks/sprint-1/
cat .harness/tasks/sprint-1/phase-02-core-impl-handoff.md왜 20줄 제한인가
다음 Phase는 claude --print 독립 세션이라 이 핸드오프만 보고 작업을 잇는다. 너무 길면 컨텍스트가 오염되고, 너무 짧으면 정보가 누락된다 (ADR-0009).
export HARNESS_API_ENDPOINT="https://your-internal-endpoint" # ~/.zshrc 등에 영구 저장 권장
gh auth login # PR 자동화 사용 시cd /path/to/python-harness && claude # 터미널 CLI
# 또는 IDE(VS Code/JetBrains)에서 폴더 열기이 시점에 .claude/settings.json의 permission, Stop hook, PreToolUse guard가 자동 적용된다.
대화 안에서 그냥 자연어로 요청하면 된다. Claude가 필요한 CLI를 알아서 호출하고, 스킬·hook이 자동 작동한다.
사용자:
결제 모듈에 재시도 로직 추가하고 PR까지 올려줘
이때 내부적으로:
harness --mode modify --use-headless-phases --auto-pr --pr-base main "..."을 실행phase-handoff스킬이 Phase 사이 핸드오프 작성- PR이 올라가면
pr-review-triage스킬이 리뷰 코멘트 처리 - 세션 종료 시 Stop hook이 ruff/mypy/structure 자동 실행
cat .harness/artifacts/summary.json # 실행 요약
cat .harness/review-artifacts/$(git branch --show-current)/pr-body.md # PR 본문
cat .harness/review-artifacts/$(git branch --show-current)/review-comments.md # 코멘트 판정 로그permission을 개인 단위로 추가하고 싶으면 .claude/settings.local.json에 둔다. 이 파일은 gitignore되어 팀에 영향 주지 않는다.
{
"permissions": {
"allow": ["Bash(open *)", "Bash(code *)"]
}
}상세 옵션은 docs/operations.md 또는 각 명령의 --help를 본다.
# 처음 쓰는 명령
harness doctor # git·gh·도구·정책 준비 상태 점검
harness init --offline "사내 청구 자동화" # 규칙 파일 배치
harness fix "..." # modify 모드
harness fix --headless "..." # 헤드리스 Phase + 문서 변경 없는 작업 허용
harness ship "..." # 수정 → PR → 리뷰 반영 한 번에 (머지·답글은 확인 플래그)
harness pr # (이미 만든 변경을) push → PR → 리뷰 반영
harness review --no-poll # 현재 PR 리뷰만 처리
# 메인 실행(전체 옵션)
harness "..." # create 모드
harness --mode modify "..." # modify
harness --mode modify --use-headless-phases "..." # 헤드리스 Phase
harness --mode modify --use-headless-phases --allow-empty-docs-diff "..." # 문서 변경 없는 작업
harness --mode modify --use-headless-phases --auto-pr --pr-base main "..." # 구현→PR→리뷰 반영(답글/머지 제외, harness ship과 동일)
harness --mode modify --auto-pr --pr-base main --fail-on-pr-error "..." # PR 실패 시 종료 코드 1 (CI 게이트)
harness --mode modify --auto-pr --pr-current-pr --pr-no-poll "..." # 현재 PR 리뷰만 처리
harness --project-dir /path/to/repo --mode modify "..." # 다른 디렉터리 대상
harness --api-endpoint "https://..." "..." # 환경변수 대신 직접 전달
harness --resume # 현재 디렉터리의 최근 체크포인트 재개
harness --run-id <run_id> # 여러 run 중 특정 체크포인트 재개
# PR 자동화 단독
auto-pr-pipeline --base main # push → PR → 리뷰 반영
auto-pr-pipeline --base main --confirm-github-writes # 리뷰 답글까지
auto-pr-pipeline --base main --auto-merge --confirm-github-writes # 머지까지
create-pr-body --base main --output pr-body.md
# 부트스트랩(기존 엔트리포인트)
harness-init --offline "사내 청구 자동화"
harness-init --offline --scaffold "사내 청구 자동화" # 규칙 + Python 골격(pyproject/CI/smoke)
harness-init --only claude-config --offline "팀 셋업만 배포" # .claude/settings.json + Stop hook
harness-init --dry-run --offline "사전 검토"
harness-init --migrate --offline "기존 Python 서비스에 하네스 적용" # src/ 레이아웃 자동 인식
# 사전 점검(기존 엔트리포인트)
harness-doctor # git·gh·도구·정책 준비 상태 점검
# 직접 검증
ruff check . && mypy harness && python3 scripts/check_structure.py && pytestQ. harness와 claude(Claude Code) 중 무엇을 써야 하나?
A. 보통은 Claude Code 안에서 자연어로 요청하는 게 가장 편하다. Claude가 내부에서 harness CLI를 적절한 옵션으로 호출하고, hook·skill이 자동 작동한다. harness CLI를 직접 치는 건 (1) 스크립트/CI에 박을 때, (2) 옵션을 정확히 통제하고 싶을 때다.
Q. create 모드와 modify 모드는 어떻게 다른가?
A. create(기본)는 새 프로젝트를 처음부터 만든다. modify는 현재 코드베이스를 수정하며, 기존 diff·ADR·컨벤션·구조 규칙·정책을 Planner 컨텍스트로 주입한다. 기존 저장소에서 작업할 때는 항상 --mode modify를 쓴다.
Q. --use-headless-phases는 언제 꼭 써야 하나?
A. 변경 범위가 여러 파일·여러 관심사에 걸칠 때(리팩터링, 기능 추가, 테스트 보강 동시 진행). 작은 한 줄 변경에는 굳이 필요 없다. 헤드리스 모드는 Phase별 컨텍스트 격리 덕분에 큰 작업에서 안정적이지만, 그만큼 시간이 더 걸린다.
Q. 스킬이 자동 트리거되지 않았다. 어떻게 강제하나?
A. 슬래시 명령 /pr-review-triage, /adr-author, /phase-handoff로 직접 호출하거나, 프롬프트에 트리거 키워드("ADR 작성", "리뷰 코멘트 분류" 등)를 명시한다.
Q. 외부 프로젝트에 본 저장소의 스킬을 가져갈 수 있나?
A. harness-init은 스킬을 배포하지 않는다 (트러블슈팅 참조). .claude/skills/{name}/ 디렉터리를 수동 복사한다.
Q. PR을 만들지 않고 로컬에서만 검증하려면?
A. --auto-pr을 빼면 된다. 그러면 push·PR 생성 없이 구현·평가 단계까지만 돈다.
Q. LLM 호출 비용이 걱정된다. 어디서 끊을 수 있나?
A. 결정적 센서(ruff → mypy → structure → pytest)가 먼저 돌고, 실패하면 AI 리뷰 단계로 가지 않는다 (ADR-0002). 또 harness-init --offline은 LLM을 아예 호출하지 않고 템플릿만 깔아준다.
Q. 세션 종료 때마다 Stop hook이 도는 게 거슬린다.
A. 일회성 우회는 CLAUDE_HOOK_SKIP=1 claude. 영구 비활성화는 권장하지 않지만, 정말 필요하면 .claude/settings.local.json에서 hooks 항목을 오버라이드한다.
Q. 체크포인트 재개가 다른 run을 잡는다.
A. .harness/checkpoints/ 디렉터리에서 run_id를 확인하고 harness --run-id <id>로 명시한다.
| 증상 | 원인 | 대처 |
|---|---|---|
HARNESS_API_ENDPOINT is not set 등 LLM 호출 에러 |
환경변수 미설정 | export HARNESS_API_ENDPOINT=... 또는 --api-endpoint 옵션 사용. 부트스트랩 미리보기는 harness-init --offline/--dry-run이라 영향 없음 |
--auto-pr 실행이 PR 단계 진입 직전에 멈춤 |
gh CLI 미인증 또는 미설치 |
gh auth login 수행 후 재실행. 시작 전 harness-doctor로 git·gh·도구·정책 준비 상태를 한 번에 점검할 수 있다 |
--auto-pr가 구현은 성공했는데 PR이 실패했고 종료 코드가 0이라 CI가 놓침 |
PR 파이프라인 오류는 기본적으로 종료 코드에 반영되지 않음 | --fail-on-pr-error를 추가하면 PR 오류 시 종료 코드 1. PR 결과는 .harness/artifacts/auto-pr-result.json에도 기록된다 |
docs-diff is empty 같은 메시지로 Phase 실패 |
첫 Phase에서 문서가 갱신되지 않음 (기본 정책) | 문서 변경이 정말 필요 없는 작업이면 --allow-empty-docs-diff 명시. 그렇지 않으면 문서 갱신 의도를 프롬프트에 추가 |
[STRUCTURE VIOLATION]으로 실행이 중단됨 |
하네스 고정 구조 필수 경로 또는 정책 package 디렉터리가 없음 | 안내된 누락 경로를 만들거나 harness-init --migrate --offline "프로젝트 설명"으로 보강 |
--auto-pr 사용했는데 PR이 안 만들어짐 |
통과 스프린트 0개 — 구현 단계가 실패 | .harness/artifacts/summary.json과 Evaluator 로그로 실패 원인 확인 후 재시도. PR 파이프라인 자체는 정상 |
| 세션 종료 시 ruff/mypy/structure 검사가 매번 돌아 거슬림 | 본 저장소의 Stop hook | 임시 우회는 CLAUDE_HOOK_SKIP=1. 외부 프로젝트의 fresh 환경에서는 도구·파일이 없으면 자동 건너뜀 |
print(...) 추가가 차단됨 |
harness/ 디렉터리에 대한 PreToolUse guard |
logging 모듈로 대체. 정말 필요한 경우 harness/ 밖에서만 사용 |
--resume이 다른 run을 잡거나 못 찾음 |
같은 디렉터리에 여러 run 기록 | .harness/checkpoints/에서 run_id 확인 후 --run-id <id>로 명시 |
외부 프로젝트에 부트스트랩했더니 /pr-review-triage 등이 안 보임 |
harness-init은 스킬을 배포하지 않음 |
.claude/skills/{name}/ 디렉터리를 본 저장소에서 수동 복사 |
python-harness/
├── harness/ # 메인 패키지
│ ├── agents/ # Planner, Generator, Evaluator, Orchestrator (+ CLAUDE.md)
│ ├── sensors/
│ │ ├── computational/ # ruff, mypy, pytest, 구조분석 센서
│ │ └── inferential/ # AI 코드 리뷰
│ ├── pipeline/ # 통합 파이프라인 (+ CLAUDE.md)
│ ├── review/ # 리뷰 산출물, PR 본문, docs-diff, worktree, session-fork (+ CLAUDE.md)
│ ├── guides/ # 시스템 프롬프트, GuideRegistry, ContextFilter(메타데이터 RAG) (+ CLAUDE.md)
│ ├── context/ # 체크포인트, modify 컨텍스트, 정책, Phase 매니저, 지식 스토어 (+ CLAUDE.md)
│ ├── contracts/ # SprintContract 모델, 저장소 (+ CLAUDE.md)
│ ├── bootstrap/ # harness-init 부트스트래퍼, 템플릿 (+ CLAUDE.md)
│ └── tools/ # shell, path_safety, file_io, api_client, adr_loader (+ CLAUDE.md)
├── scripts/ # CLI 스크립트
│ ├── run_harness.py # 메인 (create/modify/resume)
│ ├── auto_pr_pipeline.py # PR 자동화
│ ├── create_pr_body.py # PR 본문 생성
│ ├── init_harness.py # harness-init
│ ├── doctor.py # harness-doctor (사전 점검)
│ ├── run_phases.py # Phase별 claude --print 실행
│ ├── check_structure.py # 구조 규칙 검사
│ └── pr_review.py # GitHub Actions PR AI 리뷰
├── tests/ # pytest 테스트
├── docs/
│ ├── adr/ # ADR 0001~0015
│ ├── code-convention.yaml
│ └── operations.md # CLI/운영 상세 가이드
├── .claude/ # Claude Code 하네스 레이어
│ ├── settings.json # 팀 공유 (allow/deny + hooks) — 커밋
│ ├── settings.local.json # 개인 오버라이드 — .gitignore
│ ├── hooks/ # post_session_checks.sh, guard_no_print.py
│ └── skills/ # pr-review-triage/, adr-author/, phase-handoff/
├── harness_structure.yaml # 아키텍처 자동 검증 규칙
├── pyproject.toml
├── CLAUDE.md # 루트 (얇은 포인터)
└── AGENTS.md # 에이전트 런타임 컨텍스트
.harness/
├── artifacts/
│ ├── spec.json # Planner 출력
│ ├── summary.json # 실행 요약
│ └── sprint_{N}_contract.md # 스프린트 계약 원문
├── contracts/
│ └── sprint_{N}.json # 구조화 스프린트 계약
├── checkpoints/
│ ├── {run_id}.json # 실행별 체크포인트
│ └── latest.json # 최근 실행 포인터
├── review-artifacts/{branch}/
│ ├── design-intent.md # 설계 의도
│ ├── code-quality-guide.md # 평가 기준
│ ├── pr-body.md # PR 본문
│ ├── review-comments.md # 리뷰 반영 판단 로그
│ └── docs-diff-sprint{N}.md # 스프린트별 docs-diff
└── tasks/sprint-{N}/
├── task-index.json # Phase 인덱스/상태
├── phase-*.md # 자기 완결 Phase 프롬프트
├── docs-diff.md # docs-update 이후 런타임 docs-diff
└── phase-*-handoff.md # Phase 간 핸드오프 (≤20줄)
.harness/project-policy.yaml가 있으면 컨벤션·ADR·구조 경로와 프로젝트별 정책이 반영된다. 파일이 없거나 파싱 실패하면 기본 정책 사용 (ADR-0008).
project:
name: my-app
package: my_app # 루트 Python 패키지 디렉터리명
language: python
python_version: "3.11+"
policies:
review_language: ko
required_checks: [ruff, mypy, pytest, structure]
conventions:
source: docs/code-convention.yaml
adr:
directory: docs/adr/
external_sources: [] # 외부 프로젝트 ADR 경로 (절대경로)
structure:
source: harness_structure.yaml
artifacts:
design_intent: true
code_quality_guide: true
review_comments: true
pr_body: true
commands:
lint: ruff check .
type: mypy my_app
test: pytest
structure: python3 scripts/check_structure.py
min_coverage: 80
package_manager: pip
pytest:
timeout: 300
coverage: true
custom_rules:
- type: forbidden_import
pattern: "from my_app.internal"
allowed_dirs: ["my_app/"]
message: "internal 모듈은 패키지 내부에서만 import한다."정책 파일에는 토큰·비밀값을 넣지 않는다.
에이전트가 생성한 코드는 다음을 모두 통과해야 한다:
- ruff 에러 0개
- mypy 에러 0개 (strict 모드)
- pytest 전체 통과
harness_structure.yaml규칙 위반 0개
본 저장소 자체 검증:
ruff check . && mypy harness && python3 scripts/check_structure.py && pytest세션 종료 시 본 저장소의 .claude/hooks/post_session_checks.sh는 ruff → mypy → structure를 자동 실행한다 (CLAUDE_HOOK_SKIP=1로 우회 가능). pytest는 CI와 수동 검증 명령에서 실행한다.
| ADR | 제목 | 핵심 결정 |
|---|---|---|
| 0001 | 3-에이전트 아키텍처 | Planner→Generator→Evaluator, 계약 협상 |
| 0002 | 연산적 센서 우선 | ruff→mypy→구조→pytest 결정적 검사 후 AI 리뷰 |
| 0003 | ADR 기반 아키텍처 규칙 | ADR + harness_structure.yaml 검증 |
| 0004 | 리뷰 산출물 워크플로 | 브랜치별 설계 의도·기준·PR 본문·반영 로그 |
| 0005 | 구조화 스프린트 계약 | raw 보존 + 구조화 파싱, JSON 저장 |
| 0006 | 체크포인트와 재개 | Phase enum, run_id 기반 세션 복원 |
| 0007 | 가이드 레지스트리 | 시스템 프롬프트/컨텍스트 중앙 관리 |
| 0008 | 수정 모드와 프로젝트 정책 | modify 구현, project-policy.yaml 정책 적용 |
| 0009 | Phase 실행과 컨텍스트 격리 | docs-diff, Phase 분할, 컨텍스트 필터, 헤드리스 실행, PR 자동화, 세션 포크 |
| 0010 | 외부 프로젝트 고정 구조 강제 | modify/resume/PR 산출물 생성 전 필수 구조 게이트 |
| 0011 | harness-init 마이그레이션 모드 | 기존 Python 프로젝트 보강, package 기반 구조 고정 |
| 0012 | 결정적 파이프라인 평가 게이트 | 결정적 검사와 LLM 평가가 모두 pass일 때만 최종 pass |
| 0013 | argv 명령 경계와 Phase 완료 게이트 | 외부 명령을 argv 안전 경계로 실행하고 Phase handoff/범위 위반을 결정적으로 실패 처리 |
| 0014 | src 레이아웃과 project.source_root | src/<패키지> 레이아웃을 허용하고 project.source_root로 패키지 위치를 단일화 |
| 0015 | 지식 DB 누적과 메타데이터 기반 유사 RAG | ADR 메타데이터 추출·경로 매칭으로 관련도를 높이고, 실행 이력을 .harness/knowledge/에 누적해 Planner/PR이 참조 |
신규 ADR 작성 시 .claude/skills/adr-author/SKILL.md의 번호 규칙·본문 형식을 따른다.
.github/workflows/pr-check.yml이 PR마다 다음 Job을 실행한다:
| Job | 설명 | 의존성 |
|---|---|---|
lint |
ruff | - |
type-check |
mypy (strict) | - |
test |
pytest | - |
structure |
scripts/check_structure.py |
- |
ai-review |
AI 코드 리뷰 | 위 4개 통과 후 |
pr-body |
PR 본문 자동 생성 | lint |
AI 리뷰는 저장소 secret에 HARNESS_API_ENDPOINT가 등록되어 있을 때만 동작한다. secret이 없으면 그 단계만 건너뛴다.
독립 실행: scripts/pr_review.py는 GITHUB_TOKEN, PR_NUMBER, HARNESS_API_ENDPOINT를 받아 PR diff에 AI 리뷰를 단다.
사내 전용 내부 프레임워크. 별도 LICENSE 파일·오픈소스 라이선스는 부여하지 않으며, 외부 배포는 사내 정책을 따른다.