feat: harness + zio-harness Claude Code 플러그인 초기 배포
- harness: 도메인 한 줄 → 에이전트 팀 자동 생성 메타 스킬 (v1.2.0) - zio-harness: React + Spring Boot + Mobile 풀스택 개발 에이전트 팀 (v1.0.0) - 에이전트 4종: orchestrator / analyst / bot / agent - PROJECT_MAP.md 폴더 구조 메모리 시스템 - references/: react, spring-boot, mobile, playwright, database, folder-map Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
commit
c25e55b64b
22
.claude-plugin/marketplace.json
Normal file
22
.claude-plugin/marketplace.json
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"name": "harness-marketplace",
|
||||||
|
"owner": {
|
||||||
|
"name": "ythong",
|
||||||
|
"email": "ythong86@gmail.com",
|
||||||
|
"url": "https://git.zioinfo.co.kr/ythong"
|
||||||
|
},
|
||||||
|
"plugins": [
|
||||||
|
{
|
||||||
|
"name": "harness",
|
||||||
|
"source": "./",
|
||||||
|
"description": "에이전트 팀 & 스킬 아키텍트. 도메인/프로젝트에 맞는 하네스를 구성하고, 전문 에이전트를 정의하며, 에이전트가 사용할 스킬을 생성하는 메타 스킬.",
|
||||||
|
"version": "1.2.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "zio-harness",
|
||||||
|
"source": "./skills/zio-harness",
|
||||||
|
"description": "React + Spring Boot + Mobile App 풀스택 개발 하네스. orchestrator·analyst·bot·agent 에이전트 팀이 기능 개발·테스트·배포를 파이프라인으로 처리. PROJECT_MAP.md로 폴더 구조를 세션 간 기억.",
|
||||||
|
"version": "1.0.0"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
31
.claude-plugin/plugin.json
Normal file
31
.claude-plugin/plugin.json
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
"name": "harness",
|
||||||
|
"description": "The team-architecture factory for Claude Code — a meta-skill that turns a domain description into an agent team and the skills they use, with six pre-defined team-architecture patterns (Pipeline, Fan-out/Fan-in, Expert Pool, Producer-Reviewer, Supervisor, Hierarchical Delegation). Claude Code용 팀 아키텍처 팩토리: 도메인 한 문장을 에이전트 팀과 스킬 세트로 변환하는 메타 스킬.",
|
||||||
|
"version": "1.2.0",
|
||||||
|
"author": {
|
||||||
|
"name": "ythong",
|
||||||
|
"url": "https://git.zioinfo.co.kr/ythong"
|
||||||
|
},
|
||||||
|
"homepage": "https://git.zioinfo.co.kr/ythong/harness",
|
||||||
|
"repository": "https://git.zioinfo.co.kr/ythong/harness",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"keywords": [
|
||||||
|
"harness",
|
||||||
|
"harness-factory",
|
||||||
|
"team-architecture-factory",
|
||||||
|
"agent-team",
|
||||||
|
"skill-architect",
|
||||||
|
"meta-skill",
|
||||||
|
"orchestration",
|
||||||
|
"claude-code",
|
||||||
|
"claude-code-plugin",
|
||||||
|
"agent-scaffolding",
|
||||||
|
"multi-agent",
|
||||||
|
"pipeline",
|
||||||
|
"fan-out-fan-in",
|
||||||
|
"expert-pool",
|
||||||
|
"producer-reviewer",
|
||||||
|
"supervisor",
|
||||||
|
"hierarchical-delegation"
|
||||||
|
]
|
||||||
|
}
|
||||||
86
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
86
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
name: Bug report
|
||||||
|
description: Report a defect in Harness (unexpected behavior, crash, broken install, etc.)
|
||||||
|
title: "[bug] "
|
||||||
|
labels: ["bug", "needs-triage"]
|
||||||
|
assignees:
|
||||||
|
- revfactory
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
Thanks for taking the time to file a bug report.
|
||||||
|
|
||||||
|
Before submitting, please skim open issues to avoid duplicates.
|
||||||
|
|
||||||
|
**Triage SLA:** we aim to label new issues within 48h and respond substantively within 72h on business days (see [CONTRIBUTING.md](../../CONTRIBUTING.md)).
|
||||||
|
|
||||||
|
- type: input
|
||||||
|
id: claude-code-version
|
||||||
|
attributes:
|
||||||
|
label: Claude Code version
|
||||||
|
description: Output of `claude --version` (e.g. `2.3.1`)
|
||||||
|
placeholder: "2.x.y"
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: dropdown
|
||||||
|
id: experimental-flag
|
||||||
|
attributes:
|
||||||
|
label: Experimental Agent Teams flag state
|
||||||
|
description: Is `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1` set in the shell where you hit this bug?
|
||||||
|
options:
|
||||||
|
- "Yes, flag is set to 1"
|
||||||
|
- "No, flag is unset"
|
||||||
|
- "I don't know / N/A"
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: reproduction
|
||||||
|
attributes:
|
||||||
|
label: Reproduction steps
|
||||||
|
description: Minimal steps to reproduce. Commands, config, and inputs please.
|
||||||
|
placeholder: |
|
||||||
|
1. `claude plugin marketplace add harness@harness`
|
||||||
|
2. `export CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1`
|
||||||
|
3. `claude "build a harness for ..."`
|
||||||
|
4. observe ...
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: expected
|
||||||
|
attributes:
|
||||||
|
label: Expected behavior
|
||||||
|
description: What did you expect to happen?
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: actual
|
||||||
|
attributes:
|
||||||
|
label: Actual behavior
|
||||||
|
description: What actually happened? Include error messages / stack traces verbatim.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: dropdown
|
||||||
|
id: os
|
||||||
|
attributes:
|
||||||
|
label: Operating system
|
||||||
|
options:
|
||||||
|
- "macOS"
|
||||||
|
- "Linux"
|
||||||
|
- "Windows (WSL)"
|
||||||
|
- "Windows (native)"
|
||||||
|
- "Other (describe below)"
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: context
|
||||||
|
attributes:
|
||||||
|
label: Additional context (optional)
|
||||||
|
description: Logs, screenshots, or anything else that might help. Redact anything sensitive.
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
8
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
8
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
blank_issues_enabled: false
|
||||||
|
contact_links:
|
||||||
|
- name: GitHub Discussions — open-ended questions & RFCs
|
||||||
|
url: https://github.com/revfactory/harness/discussions
|
||||||
|
about: Prefer this for design discussions, ideas, "how should we think about X", and anything not yet actionable as an issue.
|
||||||
|
- name: Security disclosure (private)
|
||||||
|
url: mailto:robin.hwang@kakaocorp.com?subject=%5Bharness-security%5D
|
||||||
|
about: Report security issues privately. Acknowledgement within 7 days, patch target 30 days.
|
||||||
62
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
Normal file
62
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
name: Feature request
|
||||||
|
description: Propose a new capability or enhancement for Harness
|
||||||
|
title: "[feat] "
|
||||||
|
labels: ["enhancement", "needs-discussion"]
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
Thanks for the idea. Features take a bit of back-and-forth — please help us with the "why" before the "what".
|
||||||
|
|
||||||
|
For anything RFC-sized (new pattern family, runtime support, breaking API), consider starting in [GitHub Discussions](https://github.com/revfactory/harness/discussions) first.
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: problem
|
||||||
|
attributes:
|
||||||
|
label: What problem does this solve?
|
||||||
|
description: Describe the user or engineering pain point. Concrete scenario preferred.
|
||||||
|
placeholder: |
|
||||||
|
When I scaffold a team for ___, I end up manually ___ because ___.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: proposal
|
||||||
|
attributes:
|
||||||
|
label: Proposed solution
|
||||||
|
description: Your idea for fixing it. Sketch API / CLI / workflow if relevant.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: alternatives
|
||||||
|
attributes:
|
||||||
|
label: Alternatives considered
|
||||||
|
description: What other approaches did you think about, and why did you not pick them?
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
|
||||||
|
- type: dropdown
|
||||||
|
id: related-pattern
|
||||||
|
attributes:
|
||||||
|
label: Related team-architecture pattern (if any)
|
||||||
|
description: Which of the 6 built-in patterns is this most relevant to?
|
||||||
|
options:
|
||||||
|
- "Not pattern-specific"
|
||||||
|
- "Pipeline"
|
||||||
|
- "Fan-out / Fan-in"
|
||||||
|
- "Expert Pool"
|
||||||
|
- "Producer–Reviewer"
|
||||||
|
- "Supervisor"
|
||||||
|
- "Hierarchical Delegation"
|
||||||
|
- "A new pattern (please describe below)"
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: additional
|
||||||
|
attributes:
|
||||||
|
label: Additional context (optional)
|
||||||
|
description: Links, prior art, screenshots, anything else.
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
35
.github/ISSUE_TEMPLATE/question.yml
vendored
Normal file
35
.github/ISSUE_TEMPLATE/question.yml
vendored
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
name: Question
|
||||||
|
description: Ask a how-to or clarification question about Harness
|
||||||
|
title: "[question] "
|
||||||
|
labels: ["question", "needs-triage"]
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
Questions are welcome. If your question is open-ended or invites discussion, [GitHub Discussions](https://github.com/revfactory/harness/discussions) is usually a better venue.
|
||||||
|
|
||||||
|
We try to triage questions within 48h.
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: question
|
||||||
|
attributes:
|
||||||
|
label: Your question
|
||||||
|
description: What would you like to know?
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: tried
|
||||||
|
attributes:
|
||||||
|
label: What have you tried?
|
||||||
|
description: Commands run, docs read, related issues you've already found.
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: docs
|
||||||
|
attributes:
|
||||||
|
label: Related docs / links (optional)
|
||||||
|
description: Paste links to sections of the README, docs, or issues you've already read.
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
58
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
58
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
<!--
|
||||||
|
Thanks for sending a PR! Please fill in the sections below so reviewers can move fast.
|
||||||
|
|
||||||
|
See CONTRIBUTING.md for branch naming, commit conventions, and SLAs.
|
||||||
|
-->
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
<!-- 2–4 sentences: what does this PR change, and why now? -->
|
||||||
|
|
||||||
|
## Motivation
|
||||||
|
|
||||||
|
<!-- Link the issue, RFC, or research note that motivated this. If none, a 1-line rationale is fine. -->
|
||||||
|
|
||||||
|
- Closes #
|
||||||
|
- Related to #
|
||||||
|
|
||||||
|
## Scope of change
|
||||||
|
|
||||||
|
<!-- Tick whichever boxes apply. Leave the rest unchecked. -->
|
||||||
|
|
||||||
|
- [ ] Skill / meta-skill logic
|
||||||
|
- [ ] Agent template(s)
|
||||||
|
- [ ] Plugin manifest (`.claude-plugin/plugin.json`, `marketplace.json`)
|
||||||
|
- [ ] Documentation (`README.md`, `README_KO.md`, `README_JA.md`, `docs/`)
|
||||||
|
- [ ] `CHANGELOG.md`
|
||||||
|
- [ ] CI / GitHub Actions
|
||||||
|
- [ ] Tests
|
||||||
|
- [ ] Other (describe):
|
||||||
|
|
||||||
|
## Tests
|
||||||
|
|
||||||
|
<!-- What did you run locally? Paste output or describe. -->
|
||||||
|
|
||||||
|
- [ ] `npx markdownlint '**/*.md'` passes
|
||||||
|
- [ ] Manual repro of the change works as expected
|
||||||
|
- [ ] New unit / integration tests added (if applicable)
|
||||||
|
- [ ] N/A — explain below
|
||||||
|
|
||||||
|
## CHANGELOG update
|
||||||
|
|
||||||
|
<!-- Every user-visible change must land in CHANGELOG.md under the Unreleased section. -->
|
||||||
|
|
||||||
|
- [ ] Yes — added to `CHANGELOG.md`
|
||||||
|
- [ ] No — this change is not user-visible (docs-only / internal refactor)
|
||||||
|
|
||||||
|
## SemVer impact
|
||||||
|
|
||||||
|
<!-- See CONTRIBUTING.md § Commit Message Convention. Choose one. -->
|
||||||
|
|
||||||
|
- [ ] **Patch** — bug fix, no API change (`fix:`)
|
||||||
|
- [ ] **Minor** — additive, backward-compatible (`feat:`)
|
||||||
|
- [ ] **Major** — breaking change (`feat!:` or `BREAKING CHANGE:` in commit footer)
|
||||||
|
- [ ] **None** — docs / chore / refactor / test
|
||||||
|
|
||||||
|
## Additional notes
|
||||||
|
|
||||||
|
<!-- Screenshots, migration notes, follow-ups, things you want reviewers to focus on. -->
|
||||||
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
.DS_Store
|
||||||
|
.claude/
|
||||||
|
_workspace/
|
||||||
|
*.pptx
|
||||||
104
CHANGELOG.md
Normal file
104
CHANGELOG.md
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
이 프로젝트는 [Semantic Versioning](https://semver.org/)을 따릅니다.
|
||||||
|
|
||||||
|
## [Unreleased]
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- 신규 에이전트/스킬 생성 전 중복 검토 단계 (Phase 3-0, Phase 4-0)
|
||||||
|
- `references/agent-design-patterns.md` "에이전트 재사용 설계" 섹션
|
||||||
|
- `references/skill-writing-guide.md` §9 "스킬 재사용 설계"
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Phase 선택 매트릭스에 3-0/4-0 명시
|
||||||
|
- Phase 2-3에 재사용 검토 단계 포인터 추가
|
||||||
|
- 산출물 체크리스트에 재사용 검토 항목 2개 추가
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## [1.2.1] - 2026-04-18
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- **버전 정합성 동기화** — README.md / README_KO.md / README_JA.md 뱃지가 `v1.0.1`, `.claude-plugin/marketplace.json`이 `1.1.0`, `.claude-plugin/plugin.json`이 `1.2.0`으로 3중 불일치 → 모두 **v1.2.0**으로 통일 (plugin.json 기준)
|
||||||
|
- **태그드 릴리스 0건 상태 해소 준비** — v1.0.0 / v1.0.1 / v1.1.0 / v1.2.0 소급 태그 계획 작성 (`_workspace/release/audit-2026-04-18.md` §4 참조)
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- **포지셔닝 선언: "harness factory"** — README 상단에 카테고리 자기 규정 문구를 도입. "에이전트 + 스킬을 도메인별로 찍어내는 하네스 팩토리"로 카테고리 선점 (단일 에이전트/프롬프트 프레임워크 대비 차별화)
|
||||||
|
- **CONTRIBUTING.md** — 기여 가이드 및 SLA 명시 (PR 1차 응답 72h, Issue triage 48h). 커뮤니티 온보딩 장벽 해소
|
||||||
|
- **docs/ 디렉토리** — 장기 문서(아키텍처, 마이그레이션, 패턴 카탈로그) 이전 공간 신설. README 비대화 방지 및 검색성 향상
|
||||||
|
- **Issue #3 응답 정책** — 커뮤니티 이슈에 대한 공식 응답 템플릿 및 트리아지 프로세스 추가
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- `.claude-plugin/marketplace.json` version: `1.1.0` → `1.2.0`
|
||||||
|
- README 뱃지 (EN/KO/JA 3종): `Version-1.0.1` → `Version-1.2.0`
|
||||||
|
- **`.claude-plugin/plugin.json` description 재작성** — `"Agent Team & Skill Architect — Meta-skill that designs..."` → `"The team-architecture factory for Claude Code — a meta-skill that turns a domain description into an agent team and the skills they use, with six pre-defined team-architecture patterns..."` (EN+KO 병기, L3 Meta-Factory 포지셔닝 반영)
|
||||||
|
- **`.claude-plugin/plugin.json` keywords 확장** — 5개 → 17개 (`harness-factory`, `team-architecture-factory`, `claude-code-plugin`, `agent-scaffolding`, `multi-agent`, 6패턴 키워드 6종 추가)
|
||||||
|
|
||||||
|
## [1.2.0] - 2026-04-08
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- **CLAUDE.md 등록 정책 간소화 (중복 제거)** — Phase 5-4 "컨텍스트 등록"을 "포인터 등록"으로 전환. 에이전트 목록·스킬 목록·디렉토리 구조·실행 규칙 상세를 CLAUDE.md에서 제거하고 **트리거 규칙 + 변경 이력**만 남김. 에이전트/스킬 목록은 `.claude/agents/`, `.claude/skills/` 및 오케스트레이터 스킬에서 단일 출처로 관리
|
||||||
|
- **Phase 3/4 임시 동기화 단계 삭제** — CLAUDE.md 동기화 부담을 줄이기 위해 Phase 3/4의 임시 동기화 지시 제거. 최종 포인터 등록은 Phase 5-4에서 1회만 수행
|
||||||
|
- **핵심 원칙 3번 재정의** — "CLAUDE.md에 하네스 컨텍스트를 등록한다" → "CLAUDE.md에 하네스 포인터를 등록한다"
|
||||||
|
- **CLAUDE.md vs 오케스트레이터 역할 분담표 삭제** — 포인터 정책으로 단순화되어 표 자체가 불필요해짐
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- **Phase 2-1: 하이브리드 실행 모드** — 에이전트 팀 / 서브 에이전트에 더해 Phase별로 모드를 섞는 하이브리드 패턴 추가. 자주 쓰이는 조합(병렬 수집→합의 통합, 팀 생성→검증, Phase 간 팀 재구성) 명시
|
||||||
|
- **Phase 2-1 실행 모드 비교표** — 팀/서브/하이브리드 3종 특성 및 의사결정 순서 3단계 제공
|
||||||
|
- **Phase 5-0 하이브리드 오케스트레이터 패턴** — 하이브리드 구성 시 각 Phase 상단에 실행 모드를 명시하는 규칙
|
||||||
|
- **Phase 5-1 반환값 기반 데이터 전달** — 서브 에이전트 모드 전용 데이터 전달 전략 추가 (기존 메시지/태스크/파일 + 반환값)
|
||||||
|
- **Phase 5-1 권장 조합 (서브/하이브리드)** — 팀 모드 외 서브 모드와 하이브리드에서의 데이터 전달 권장 조합 명시
|
||||||
|
|
||||||
|
## [1.1.0] - 2026-04-05
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- **Phase 0: 현황 감사** — 트리거 시 기존 하네스 상태를 먼저 확인하고 신규 구축/기존 확장/운영·유지보수 3분기로 라우팅
|
||||||
|
- **기존 확장 Phase 선택 매트릭스** — 에이전트 추가/스킬 추가/아키텍처 변경별 필요 Phase를 명시한 결정표
|
||||||
|
- **Phase 3/4 CLAUDE.md 임시 동기화** — 에이전트·스킬 생성 직후 CLAUDE.md에 즉시 반영 (세션 중단 내성)
|
||||||
|
- **Phase 5-4: CLAUDE.md 하네스 컨텍스트 등록** — 에이전트 팀 구조·스킬 목록·실행 규칙·디렉토리 구조·변경 이력을 기록. CLAUDE.md vs 오케스트레이터 역할 분담표 포함
|
||||||
|
- **Phase 5-5: 후속 작업 지원** — 오케스트레이터 description에 후속 키워드 필수 포함, Phase 0 컨텍스트 확인 단계로 초기/부분재실행/새실행 자동 판별
|
||||||
|
- **Phase 5 오케스트레이터 수정 경로** — 기존 확장 시 오케스트레이터를 새로 만들지 않고 수정하는 가이드
|
||||||
|
- **Phase 7: 하네스 진화 메커니즘** — 실행 후 피드백 수집 → 피드백 유형별 수정 대상 매핑 → 변경 이력 기록 → 자동 진화 트리거
|
||||||
|
- **Phase 7-5: 운영/유지보수 워크플로우** — 현황 감사→점진적 수정→CLAUDE.md 동기화→변경 검증 4단계
|
||||||
|
- **description에 운영/유지보수 트리거** — '하네스 점검', '하네스 감사', '하네스 현황', '에이전트/스킬 동기화' 키워드
|
||||||
|
- **산출물 체크리스트 강화** — CLAUDE.md 동기화 완료, 변경 이력 기록, Phase 0 컨텍스트 확인 항목 추가
|
||||||
|
- 오케스트레이터 템플릿에 Phase 0 (컨텍스트 확인) 추가 — 에이전트 팀/서브 에이전트 모드 모두 적용
|
||||||
|
- 오케스트레이터 description 템플릿에 후속 작업 키워드 패턴 포함
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- 핵심 원칙 2개 → 4개로 확장 (CLAUDE.md 등록, 진화 시스템 추가)
|
||||||
|
- **"진화 로그" → "변경 이력" 통일** — 이름과 스키마(4컬럼: 날짜/변경내용/대상/사유)를 전 섹션에서 일원화
|
||||||
|
- **Phase 1 Step 3** — Phase 0 감사 결과를 기반으로 충돌 분석하도록 변경 (중복 제거)
|
||||||
|
- **5-4 CLAUDE.md 템플릿 코드 블록** — 중첩 렌더링 깨짐 수정 (3백틱→4백틱)
|
||||||
|
- **역할 분담표 확장** — 스킬 목록, 디렉토리 구조, 변경 이력 행 추가
|
||||||
|
- **오케스트레이터 템플릿** — Phase 0 컨텍스트 확인 단계, 후속 작업 키워드 가이드 추가
|
||||||
|
|
||||||
|
## [1.0.1] - 2026-03-28
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- SKILL.md ↔ references 간 중복 내용 제거 (330줄 → 285줄)
|
||||||
|
- Phase 2-1: 실행 모드 비교표/불릿 → 핵심 원칙 + agent-design-patterns.md 포인터
|
||||||
|
- Phase 2-3: 에이전트 분리 기준 불릿 → 4축 요약 + agent-design-patterns.md 포인터
|
||||||
|
- Phase 3: 에이전트 정의 템플릿 코드블록 → 필수 섹션 나열 + references 포인터
|
||||||
|
- Phase 5-2: 에러 핸들링 5행 테이블 → 핵심 원칙 + orchestrator-template.md 포인터
|
||||||
|
|
||||||
|
## [1.0.0] - 2026-03-27
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- 6 Phase 워크플로우 기반 하네스 구성 메타 스킬
|
||||||
|
- 6가지 에이전트 아키텍처 패턴 (파이프라인, 팬아웃/팬인, 전문가 풀, 생성-검증, 감독자, 계층적 위임)
|
||||||
|
- 에이전트 팀 / 서브 에이전트 실행 모드 지원
|
||||||
|
- Progressive Disclosure 기반 스킬 생성 가이드
|
||||||
|
- 오케스트레이터 템플릿 (에이전트 팀 모드 + 서브 에이전트 모드)
|
||||||
|
- QA 에이전트 통합 가이드 (실제 프로젝트 7개 버그 사례 기반)
|
||||||
|
- 스킬 테스트/평가 방법론 (With-skill vs Without-skill 비교)
|
||||||
|
- 실전 팀 구성 예시 5종 (리서치, 소설, 웹툰, 코드리뷰, 마이그레이션)
|
||||||
63
CLAUDE.md
Normal file
63
CLAUDE.md
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
# harness-main — Claude Code 가이드
|
||||||
|
|
||||||
|
## 하네스: zio-harness (React + Spring Boot + Mobile)
|
||||||
|
|
||||||
|
**목표:** React 프론트엔드 + Spring Boot 백엔드 + 모바일 앱 풀스택 개발을 에이전트 팀이 자동 조율한다.
|
||||||
|
|
||||||
|
**트리거:** 기능 개발, 버그 수정, 테스트, 코드 분석, 폴더 구조 파악 요청 시 `zio-harness` 스킬을 사용하라. 단순 질문은 직접 응답 가능.
|
||||||
|
|
||||||
|
**변경 이력:**
|
||||||
|
| 날짜 | 변경 내용 | 대상 | 사유 |
|
||||||
|
|------|----------|------|------|
|
||||||
|
| 2026-06-17 | zio-harness 초기 구성 | 전체 | React+SpringBoot+Mobile 풀스택 하네스 신규 생성 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 하네스: harness (메타 스킬)
|
||||||
|
|
||||||
|
**목표:** 새 도메인에 맞는 에이전트 팀과 스킬을 자동 생성하는 팩토리.
|
||||||
|
|
||||||
|
**트리거:** "하네스 구성해줘", "에이전트 팀 설계해줘", 새 도메인 하네스 생성 요청 시 `harness` 스킬을 사용하라.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 폴더 구조 빠른 참조
|
||||||
|
|
||||||
|
```
|
||||||
|
harness-main/
|
||||||
|
├── .claude-plugin/ # 플러그인 매니페스트
|
||||||
|
├── .claude/
|
||||||
|
│ ├── agents/ # 에이전트 정의 파일 (4종)
|
||||||
|
│ │ ├── orchestrator.md # 전체 조율
|
||||||
|
│ │ ├── analyst.md # 분석 + PROJECT_MAP 관리
|
||||||
|
│ │ ├── bot.md # 테스트·빌드·자동화
|
||||||
|
│ │ └── agent.md # 코드 구현
|
||||||
|
│ └── skills/ # (추가 스킬 위치)
|
||||||
|
├── skills/
|
||||||
|
│ ├── harness/ # 메타 하네스 스킬
|
||||||
|
│ │ ├── SKILL.md
|
||||||
|
│ │ └── references/ # 패턴·템플릿·가이드
|
||||||
|
│ └── zio-harness/ # 풀스택 개발 하네스 스킬
|
||||||
|
│ ├── SKILL.md
|
||||||
|
│ └── references/
|
||||||
|
│ ├── folder-map.md # PROJECT_MAP 생성 가이드
|
||||||
|
│ ├── react.md # React 개발 패턴
|
||||||
|
│ ├── spring-boot.md # Spring Boot 패턴
|
||||||
|
│ ├── mobile.md # 모바일 앱 패턴
|
||||||
|
│ ├── playwright.md # E2E 테스트 패턴
|
||||||
|
│ ├── database.md # DB + MCP 패턴
|
||||||
|
│ ├── orchestrator.md # 오케스트레이터 에이전트 가이드
|
||||||
|
│ ├── analyst.md # 분석가 에이전트 가이드
|
||||||
|
│ ├── bot.md # 봇 에이전트 가이드
|
||||||
|
│ └── agent.md # 개발 에이전트 가이드
|
||||||
|
└── _workspace/ # 에이전트 작업 중간 산출물
|
||||||
|
```
|
||||||
|
|
||||||
|
## 핵심 파일 역할
|
||||||
|
|
||||||
|
| 파일 | 역할 |
|
||||||
|
|------|------|
|
||||||
|
| `PROJECT_MAP.md` (프로젝트 루트) | 폴더 구조 메모리 — 에이전트가 세션마다 읽는 기준 파일 |
|
||||||
|
| `skills/zio-harness/SKILL.md` | zio-harness 오케스트레이터 진입점 |
|
||||||
|
| `skills/harness/SKILL.md` | harness 메타 스킬 진입점 |
|
||||||
|
| `.claude/agents/*.md` | 에이전트 역할·원칙·통신 프로토콜 정의 |
|
||||||
211
CONTRIBUTING.md
Normal file
211
CONTRIBUTING.md
Normal file
@ -0,0 +1,211 @@
|
|||||||
|
# Contributing to Harness
|
||||||
|
|
||||||
|
Thanks for considering a contribution to **Harness** — a Claude Code meta-skill factory that designs agent teams and generates skills.
|
||||||
|
|
||||||
|
This document covers: response SLAs, how to contribute, development setup, PR conventions, commit message rules, code of conduct, and maintainer list.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Response SLA (commitments)
|
||||||
|
|
||||||
|
These are the maintainer response targets for this repository. They are **conservative** so that a small maintainer team can realistically keep them while scaling.
|
||||||
|
|
||||||
|
| Surface | Target | Notes |
|
||||||
|
|---------|--------|-------|
|
||||||
|
| PR — 1st response | **< 72h** | Business days. A "1st response" means at minimum a label + one comment acknowledging the PR. |
|
||||||
|
| Issue triage & labeling | **< 48h** | Every new issue gets `needs-triage` removed and a type label (`bug` / `enhancement` / `question` / `discussion`) within 48h. |
|
||||||
|
| Bug resolve (P0 / P1) | **< 14d** | P0 = data loss / security / broken install. P1 = common path broken. P2/P3 tracked on roadmap without a hard SLA. |
|
||||||
|
| Security report | **< 7d** | Initial acknowledgement within 7 days. Patch target 30 days. Please see **Security** section below for the private channel. |
|
||||||
|
| Release cadence | **every 2 weeks** | Biweekly tag unless there is nothing shippable. P0 fixes may cut an off-schedule patch release. |
|
||||||
|
|
||||||
|
If we miss an SLA, please feel free to ping the issue/PR — that is not rude, it is the agreed feedback loop.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## How to Contribute
|
||||||
|
|
||||||
|
Different kinds of contributions go through different entry points. Pick the one that fits.
|
||||||
|
|
||||||
|
### Bug report
|
||||||
|
|
||||||
|
- Open an issue using the **Bug report** form (`.github/ISSUE_TEMPLATE/bug_report.yml`).
|
||||||
|
- Required: Claude Code version, `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS` flag state, reproduction steps, expected vs actual, OS.
|
||||||
|
- Small reproductions (< 30 lines) are ideal. If your repro needs a full project, link a public fork.
|
||||||
|
|
||||||
|
### Feature request
|
||||||
|
|
||||||
|
- Open an issue using the **Feature request** form.
|
||||||
|
- We expect a short "what problem does this solve" paragraph. If you have a proposal, put it in the PR-ready shape (which of the 6 team-architecture patterns does it extend / replace?).
|
||||||
|
|
||||||
|
### Question
|
||||||
|
|
||||||
|
- Open an issue using the **Question** form, **or** start a thread in [GitHub Discussions](https://github.com/revfactory/harness/discussions) if the matter is open-ended.
|
||||||
|
|
||||||
|
### Discussion (RFC-sized ideas)
|
||||||
|
|
||||||
|
- Prefer GitHub Discussions. Only promote to an issue once there is rough consensus on direction.
|
||||||
|
|
||||||
|
### Pull Request
|
||||||
|
|
||||||
|
- See **Pull Request Guidelines** below.
|
||||||
|
- Small PRs merge faster. Anything > 400 lines of diff should probably have been a Discussion first.
|
||||||
|
|
||||||
|
### Security
|
||||||
|
|
||||||
|
- Do **not** open a public issue for anything that could be abused.
|
||||||
|
- Email: `robin.hwang@kakaocorp.com` with subject prefix `[harness-security]`.
|
||||||
|
- We aim to acknowledge within 7 days (see SLA table).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Development Setup
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
- Claude Code `v2.x` (Agent Teams API required)
|
||||||
|
- Node.js `>= 18` (for local tooling used in CI)
|
||||||
|
- Git
|
||||||
|
|
||||||
|
### Environment flag
|
||||||
|
|
||||||
|
Harness currently requires Claude Code's experimental Agent Teams feature. Set the flag in your shell profile or per-session:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1
|
||||||
|
```
|
||||||
|
|
||||||
|
We track this dependency in `docs/experimental-dependency.md` (if Anthropic promotes the flag to stable, we update the README within 72h per the SLA above).
|
||||||
|
|
||||||
|
### Local plugin link
|
||||||
|
|
||||||
|
To test your changes in a local Claude Code session without publishing to the marketplace:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# From your checkout
|
||||||
|
claude plugin link ./harness
|
||||||
|
|
||||||
|
# Verify
|
||||||
|
claude plugin list | grep harness
|
||||||
|
```
|
||||||
|
|
||||||
|
Unlink with `claude plugin unlink harness` when you're done.
|
||||||
|
|
||||||
|
### Running the meta-skill
|
||||||
|
|
||||||
|
```bash
|
||||||
|
claude "build a harness for a fintech risk-assessment team"
|
||||||
|
```
|
||||||
|
|
||||||
|
Scaffolded agents and skills land under `.claude/agents/` and `.claude/skills/` in the target project.
|
||||||
|
|
||||||
|
### Tests & lints
|
||||||
|
|
||||||
|
- Markdown lint: `npx markdownlint '**/*.md'`
|
||||||
|
- YAML lint (issue templates & workflows): `npx yaml-lint .github/`
|
||||||
|
- Skill metadata validation: `python scripts/validate_skills.py` (if present)
|
||||||
|
|
||||||
|
CI runs these on every PR. Local execution is encouraged but not required — we won't block on CI-caught issues that are trivial to fix on merge.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Pull Request Guidelines
|
||||||
|
|
||||||
|
### Branch naming
|
||||||
|
|
||||||
|
Use the `type/short-description` shape:
|
||||||
|
|
||||||
|
| Prefix | Use for | Example |
|
||||||
|
|--------|---------|---------|
|
||||||
|
| `feat/` | New user-visible capability | `feat/expert-pool-variance-mode` |
|
||||||
|
| `fix/` | Bug fix | `fix/agent-teams-flag-detection` |
|
||||||
|
| `docs/` | Docs-only changes | `docs/quickstart-gemini-section` |
|
||||||
|
| `refactor/` | Internal structure, no behavior change | `refactor/skill-loader-split` |
|
||||||
|
| `chore/` | Build, deps, housekeeping | `chore/upgrade-markdownlint` |
|
||||||
|
| `test/` | Tests only | `test/fan-out-fan-in-e2e` |
|
||||||
|
|
||||||
|
### Commit message language
|
||||||
|
|
||||||
|
- **Korean and English are both accepted.** Write in whichever you are more precise in.
|
||||||
|
- If the change will appear in the CHANGELOG or release notes, please also provide an English title in the PR description so downstream readers can follow.
|
||||||
|
|
||||||
|
### PR template
|
||||||
|
|
||||||
|
Every PR body is pre-filled from `.github/PULL_REQUEST_TEMPLATE.md`. Please fill in:
|
||||||
|
|
||||||
|
- **Summary** (what & why, 2–4 sentences)
|
||||||
|
- **Motivation** (link issue, reference research, or 1-line rationale)
|
||||||
|
- **Scope of change** (checklist of touched surfaces)
|
||||||
|
- **Tests** (what you ran / added)
|
||||||
|
- **CHANGELOG** (did you update `CHANGELOG.md`? Y/N/NA)
|
||||||
|
- **SemVer impact** (patch / minor / major — see next section)
|
||||||
|
|
||||||
|
### Review expectation
|
||||||
|
|
||||||
|
- One approving review from a maintainer is required.
|
||||||
|
- We try to respond on PRs within 72h (see SLA). If you're blocked, ping.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Commit Message Convention
|
||||||
|
|
||||||
|
We follow a light variant of **Conventional Commits** that maps directly to SemVer.
|
||||||
|
|
||||||
|
```
|
||||||
|
<type>(<scope>)!: <short summary>
|
||||||
|
|
||||||
|
<body — optional>
|
||||||
|
|
||||||
|
<footer — optional>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Types & SemVer mapping
|
||||||
|
|
||||||
|
| Commit type | SemVer impact | Example |
|
||||||
|
|-------------|---------------|---------|
|
||||||
|
| `feat!:` or `BREAKING CHANGE:` in footer | **major** (e.g. 1.x → 2.0) | `feat!: rename primary pattern "Supervisor" → "Orchestrator"` |
|
||||||
|
| `feat:` | **minor** (e.g. 1.2 → 1.3) | `feat: add Producer-Reviewer variance metric` |
|
||||||
|
| `fix:` | **patch** (e.g. 1.2.3 → 1.2.4) | `fix: correct flag detection on zsh` |
|
||||||
|
| `docs:` / `chore:` / `refactor:` / `test:` | no release bump | `docs: clarify Gemini roadmap` |
|
||||||
|
|
||||||
|
- Korean summaries are fine: `feat: 전문가 풀 패턴에 분산 지표 추가`.
|
||||||
|
- The `!` suffix (or `BREAKING CHANGE:` footer) is the **only** canonical major-version trigger. Please do not set it lightly.
|
||||||
|
|
||||||
|
### Release tagging
|
||||||
|
|
||||||
|
- Releases are cut every 2 weeks (see SLA).
|
||||||
|
- Tagging happens from `main` after CI passes and CHANGELOG is updated.
|
||||||
|
- Tags follow `vMAJOR.MINOR.PATCH` (e.g. `v1.3.0`).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Code of Conduct
|
||||||
|
|
||||||
|
This project adheres to the **Contributor Covenant v1.4** — in short:
|
||||||
|
|
||||||
|
- Be welcoming and inclusive. Assume good intent.
|
||||||
|
- No harassment, no personal attacks, no discriminatory language.
|
||||||
|
- Critique ideas, not people. Back claims with references where possible.
|
||||||
|
- Maintainers may moderate, edit, or remove comments/commits/issues/PRs that violate these principles, and may ban offenders.
|
||||||
|
|
||||||
|
Full text: <https://www.contributor-covenant.org/version/1/4/code-of-conduct/>
|
||||||
|
|
||||||
|
Report Code of Conduct violations privately to `robin.hwang@kakaocorp.com` with subject prefix `[harness-coc]`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Maintainers
|
||||||
|
|
||||||
|
| Role | Handle | Area |
|
||||||
|
|------|--------|------|
|
||||||
|
| Lead maintainer | [@revfactory](https://github.com/revfactory) | Project direction, releases, final review |
|
||||||
|
| Contributor | [@hnts03](https://github.com/hnts03) | Skill templates, Korean documentation |
|
||||||
|
| Contributor | [@JunghwanNA](https://github.com/JunghwanNA) | Agent patterns, integration tests |
|
||||||
|
| Contributor | [@shaun0927](https://github.com/shaun0927) | Tooling, CI, infra |
|
||||||
|
|
||||||
|
New contributors become listed here after sustained contribution (not a single PR). Drop a note in a Discussion if you'd like to discuss a maintainer path.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
By contributing, you agree that your contributions will be licensed under the same license as this repository (see [`LICENSE`](./LICENSE)).
|
||||||
190
LICENSE
Normal file
190
LICENSE
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to the Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by the Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding any notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
Copyright 2025 robin
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
163
PROJECT_MAP.md
Normal file
163
PROJECT_MAP.md
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
# PROJECT_MAP
|
||||||
|
|
||||||
|
> 마지막 업데이트: 2026-06-17
|
||||||
|
> 프로젝트: harness — Claude Code Plugin (Team-Architecture Factory)
|
||||||
|
> 버전: 1.2.0 (plugin.json 기준)
|
||||||
|
> 업데이트 방법: "PROJECT_MAP 업데이트해줘" 또는 구조 변경 후 analyst 에이전트 자동 갱신
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 프로젝트 목적
|
||||||
|
|
||||||
|
Claude Code용 **팀 아키텍처 팩토리** 플러그인 저장소.
|
||||||
|
- `harness` 스킬: 도메인 설명 → 에이전트 팀 + 스킬 자동 생성 (메타 스킬)
|
||||||
|
- `zio-harness` 스킬: React + Spring Boot + Mobile 풀스택 개발 에이전트 팀
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 루트 디렉토리 구조
|
||||||
|
|
||||||
|
| 파일/폴더 | 용도 |
|
||||||
|
|----------|------|
|
||||||
|
| `.claude-plugin/` | Claude Code 플러그인 매니페스트 |
|
||||||
|
| `.claude/` | 이 저장소의 에이전트 정의 파일 |
|
||||||
|
| `.github/` | GitHub 이슈/PR 템플릿 |
|
||||||
|
| `skills/` | 플러그인 스킬 정의 |
|
||||||
|
| `docs/` | 장기 참조 문서 (퀵스타트, 실험적 의존성) |
|
||||||
|
| `_workspace/` | 에이전트 작업 중간 산출물 (git 추적 제외 권장) |
|
||||||
|
| `CLAUDE.md` | Claude Code 세션 진입 포인터 + 하네스 트리거 규칙 |
|
||||||
|
| `PROJECT_MAP.md` | 이 파일 — 폴더 구조 메모리 |
|
||||||
|
| `README.md` | 영문 메인 설명 |
|
||||||
|
| `README_KO.md` | 한국어 설명 |
|
||||||
|
| `README_JA.md` | 일본어 설명 |
|
||||||
|
| `CHANGELOG.md` | 버전별 변경 이력 (Semantic Versioning) |
|
||||||
|
| `CONTRIBUTING.md` | 기여 가이드 + SLA (PR 72h, Issue 48h) |
|
||||||
|
| `LICENSE` | Apache 2.0 |
|
||||||
|
| `index.html` | 플러그인 마켓플레이스 랜딩 |
|
||||||
|
| `privacy.html` | 개인정보처리방침 |
|
||||||
|
| `harness_*.png` | 브랜드 이미지 (banner, icon, social, team) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## .claude-plugin/ (플러그인 매니페스트)
|
||||||
|
|
||||||
|
| 파일 | 용도 |
|
||||||
|
|------|------|
|
||||||
|
| `plugin.json` | harness 플러그인 메타 (name, version, author, keywords) |
|
||||||
|
| `marketplace.json` | 마켓플레이스 등록 정보. 현재 등록 플러그인: `harness` (v1.2.0), `zio-harness` (v1.0.0) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## .claude/agents/ (에이전트 정의)
|
||||||
|
|
||||||
|
zio-harness 풀스택 개발 에이전트 팀. 4종 에이전트가 파이프라인으로 협업.
|
||||||
|
|
||||||
|
| 파일 | 에이전트 타입 | 역할 |
|
||||||
|
|------|------------|------|
|
||||||
|
| `orchestrator.md` | general-purpose | 작업 분석, 팀 구성, 결과 종합. PROJECT_MAP 읽기 첫 번째 |
|
||||||
|
| `analyst.md` | Explore | 코드/구조 분석, PROJECT_MAP.md 생성·유지, 구현 계획 수립 |
|
||||||
|
| `bot.md` | general-purpose | 테스트·빌드·린트·Playwright E2E·DB 마이그레이션 자동화 |
|
||||||
|
| `agent.md` | general-purpose | React/Spring Boot/Mobile 코드 구현 |
|
||||||
|
|
||||||
|
**실행 순서**: orchestrator → analyst → agent → bot
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## skills/ (플러그인 스킬)
|
||||||
|
|
||||||
|
### skills/harness/ (메타 하네스 — 핵심 플러그인)
|
||||||
|
|
||||||
|
| 파일 | 용도 |
|
||||||
|
|------|------|
|
||||||
|
| `SKILL.md` | 메인 스킬 정의. 7 Phase 워크플로우 (감사→분석→설계→에이전트→스킬→통합→검증) |
|
||||||
|
| `references/agent-design-patterns.md` | 6가지 아키텍처 패턴 + 에이전트 분리 기준 + 재사용 설계 |
|
||||||
|
| `references/orchestrator-template.md` | 팀/서브에이전트/하이브리드 오케스트레이터 템플릿 3종 |
|
||||||
|
| `references/team-examples.md` | 실전 팀 구성 예시 5종 (파일 전문 포함) |
|
||||||
|
| `references/skill-writing-guide.md` | 스킬 작성 패턴 + Progressive Disclosure + 재사용 설계 |
|
||||||
|
| `references/skill-testing-guide.md` | 테스트/평가/반복 개선 방법론 |
|
||||||
|
| `references/qa-agent-guide.md` | QA 에이전트 통합 가이드 + 7개 버그 패턴 |
|
||||||
|
|
||||||
|
### skills/zio-harness/ (풀스택 개발 하네스)
|
||||||
|
|
||||||
|
| 파일 | 용도 |
|
||||||
|
|------|------|
|
||||||
|
| `SKILL.md` | 오케스트레이터 진입점. 팀 구성·워크플로우·에러 핸들링·테스트 시나리오 포함 |
|
||||||
|
| `references/folder-map.md` | **PROJECT_MAP.md 생성·유지 시스템**. 폴더 구조 메모리 핵심 가이드 |
|
||||||
|
| `references/react.md` | React 18 + TypeScript + TanStack Query + Zustand 패턴 |
|
||||||
|
| `references/spring-boot.md` | Spring Boot 3.x 레이어 아키텍처 + JPA + JWT + Flyway |
|
||||||
|
| `references/mobile.md` | React Native + Expo + React Navigation + AsyncStorage |
|
||||||
|
| `references/playwright.md` | E2E 테스트 + 페이지 오브젝트 패턴 + CI 통합 |
|
||||||
|
| `references/database.md` | PostgreSQL/MySQL MCP 설정 + Flyway 마이그레이션 + JPA 최적화 |
|
||||||
|
| `references/orchestrator.md` | Orchestrator 에이전트 상세 정의 템플릿 |
|
||||||
|
| `references/analyst.md` | Analyst 에이전트 상세 정의 템플릿 |
|
||||||
|
| `references/bot.md` | Bot 에이전트 상세 정의 템플릿 |
|
||||||
|
| `references/agent.md` | Dev Agent 에이전트 상세 정의 템플릿 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## docs/ (참조 문서)
|
||||||
|
|
||||||
|
| 파일 | 용도 |
|
||||||
|
|------|------|
|
||||||
|
| `quickstart.md` | 5분 퀵스타트 (마켓플레이스 설치 → 하네스 생성 → 샘플 실행) |
|
||||||
|
| `experimental-dependency.md` | `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1` 플래그 설명 및 변경 대응 계획 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## .github/ (GitHub 자동화)
|
||||||
|
|
||||||
|
| 경로 | 용도 |
|
||||||
|
|------|------|
|
||||||
|
| `ISSUE_TEMPLATE/bug_report.yml` | 버그 리포트 템플릿 |
|
||||||
|
| `ISSUE_TEMPLATE/feature_request.yml` | 기능 요청 템플릿 |
|
||||||
|
| `ISSUE_TEMPLATE/question.yml` | 질문 템플릿 |
|
||||||
|
| `ISSUE_TEMPLATE/config.yml` | 이슈 템플릿 설정 |
|
||||||
|
| `PULL_REQUEST_TEMPLATE.md` | PR 템플릿 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## _workspace/ (에이전트 작업 공간)
|
||||||
|
|
||||||
|
에이전트가 실행 중 생성하는 중간 산출물. 세션 간 유지되므로 작업 이력 추적 가능.
|
||||||
|
|
||||||
|
| 파일/폴더 | 용도 |
|
||||||
|
|----------|------|
|
||||||
|
| `01_auditor_repo_audit.md` | 저장소 감사 산출물 (이전 실행) |
|
||||||
|
| `02_content_launch_contents.md` | 런치 콘텐츠 산출물 (이전 실행) |
|
||||||
|
| `03_scout_outreach_map.md` | 아웃리치 맵 산출물 (이전 실행) |
|
||||||
|
| `04_strategist_launch_plan.md` | 런치 전략 산출물 (이전 실행) |
|
||||||
|
| `release/audit-2026-04-18.md` | v1.2.0 릴리즈 감사 |
|
||||||
|
| `release/post-m0-audit-2026-04-18.md` | M0 릴리즈 후 감사 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 핵심 컨벤션
|
||||||
|
|
||||||
|
| 항목 | 규칙 |
|
||||||
|
|------|------|
|
||||||
|
| 스킬 위치 | `skills/{skill-name}/SKILL.md` |
|
||||||
|
| 참조 파일 | `skills/{skill-name}/references/*.md` |
|
||||||
|
| 에이전트 정의 | `.claude/agents/{name}.md` |
|
||||||
|
| SKILL.md 크기 제한 | 500줄 이내 (초과 시 references/ 분리) |
|
||||||
|
| 버전 관리 | Semantic Versioning, plugin.json 기준 |
|
||||||
|
| 다국어 문서 | README.md (EN) · README_KO.md · README_JA.md 동기화 필수 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 환경 요구사항
|
||||||
|
|
||||||
|
| 항목 | 값 |
|
||||||
|
|------|-----|
|
||||||
|
| Claude Code 버전 | v2.x 이상 |
|
||||||
|
| 필수 환경 변수 | `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1` |
|
||||||
|
| 설치 명령 | `claude plugin marketplace add revfactory/harness` |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 최근 변경 이력
|
||||||
|
|
||||||
|
| 날짜 | 변경 내용 | 담당 |
|
||||||
|
|------|----------|------|
|
||||||
|
| 2026-06-17 | PROJECT_MAP.md 초기 생성 | analyst |
|
||||||
|
| 2026-06-17 | zio-harness 스킬 + 에이전트 4종 신규 생성 | orchestrator |
|
||||||
|
| 2026-04-18 | v1.2.0/1.2.1 릴리즈: 버전 정합성·포지셔닝·CONTRIBUTING·docs/ 신설 | - |
|
||||||
302
README.md
Normal file
302
README.md
Normal file
@ -0,0 +1,302 @@
|
|||||||
|
<p align="center">
|
||||||
|
<img src="harness_banner.png" alt="Harness Banner" width="600">
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<img src="https://img.shields.io/badge/Version-1.2.0-brightgreen.svg" alt="Version">
|
||||||
|
<a href="LICENSE"><img src="https://img.shields.io/badge/License-Apache_2.0-blue.svg" alt="License"></a>
|
||||||
|
<img src="https://img.shields.io/badge/Claude_Code-Plugin-purple.svg" alt="Claude Code Plugin">
|
||||||
|
<img src="https://img.shields.io/badge/Patterns-6_Architectures-orange.svg" alt="6 Architecture Patterns">
|
||||||
|
<img src="https://img.shields.io/badge/Mode-Agent_Teams-green.svg" alt="Agent Teams">
|
||||||
|
<a href="https://github.com/revfactory/harness/stargazers"><img src="https://img.shields.io/github/stars/revfactory/harness?style=social" alt="GitHub Stars"></a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<a href="#category--where-harness-sits"><img src="https://img.shields.io/badge/Layer-L3%20Meta--Factory-orange" alt="Layer"></a>
|
||||||
|
<a href="#category--where-harness-sits"><img src="https://img.shields.io/badge/Sub--layer-Team--Architecture%20Factory-teal" alt="Sub-layer"></a>
|
||||||
|
<a href="#"><img src="https://img.shields.io/badge/README-EN%20%7C%20KO%20%7C%20JA-lightgrey" alt="i18n"></a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
# Harness — The Team-Architecture Factory for Claude Code
|
||||||
|
|
||||||
|
**English** | [한국어](README_KO.md) | [日本語](README_JA.md)
|
||||||
|
|
||||||
|
> **Harness is a team-architecture factory for Claude Code.** Say **"build a harness for this project"** (English) or **"하네스 구성해줘"** (한국어) or **"ハーネスを構成して"** (日本語), and the plugin turns your domain description into an agent team and the skills they use — picked from six pre-defined team-architecture patterns.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
Harness leverages Claude Code's agent team system to decompose complex tasks into coordinated teams of specialized agents. Say "build a harness for this project" and it automatically generates agent definitions (`.claude/agents/`) and skills (`.claude/skills/`) tailored to your domain.
|
||||||
|
|
||||||
|
## Category — Where Harness Sits
|
||||||
|
|
||||||
|
Harness lives at the **L3 Meta-Factory** layer of the Claude Code ecosystem — the layer that generates other harnesses rather than being one. Inside L3, we pick a specific sub-layer: **Team-Architecture Factory**.
|
||||||
|
|
||||||
|
| Layer | What it does | Neighbors we coexist with |
|
||||||
|
|-------|--------------|---------------------------|
|
||||||
|
| **L3 — Meta-Factory / Team-Architecture Factory** (us) | Domain sentence → agent team + skills, via 6 pre-defined team patterns | — |
|
||||||
|
| L3 — Meta-Factory / Runtime-Configuration Factory | Deterministic, repeatable runtime configurations | [coleam00/Archon](https://github.com/coleam00/Archon) |
|
||||||
|
| L3 — Meta-Factory / Codex Runtime Port | Same concept, Codex runtime | [SaehwanPark/meta-harness](https://github.com/SaehwanPark/meta-harness) |
|
||||||
|
| L2 — Cross-Harness Workflow | Standardize skills/rules/hooks across multiple harnesses | [affaan-m/ECC](https://github.com/affaan-m/everything-claude-code) |
|
||||||
|
|
||||||
|
> Archon generates deterministic runtime configurations. Harness generates team architectures (pipeline, fan-out/fan-in, expert pool, producer-reviewer, supervisor, hierarchical delegation) plus the skills agents use. Different sub-layers of the same L3. Pick Archon for runtime determinism, Harness for team architecture, or combine them.
|
||||||
|
|
||||||
|
## Star History
|
||||||
|
|
||||||
|
<a href="https://www.star-history.com/?repos=revfactory%2Fharness&type=date&legend=top-left">
|
||||||
|
<picture>
|
||||||
|
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/chart?repos=revfactory/harness&type=date&theme=dark&legend=top-left" />
|
||||||
|
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/chart?repos=revfactory/harness&type=date&legend=top-left" />
|
||||||
|
<img alt="Star History Chart" src="https://api.star-history.com/chart?repos=revfactory/harness&type=date&legend=top-left" />
|
||||||
|
</picture>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
## Key Features
|
||||||
|
|
||||||
|
- **Agent Team Design** — 6 architectural patterns: Pipeline, Fan-out/Fan-in, Expert Pool, Producer-Reviewer, Supervisor, and Hierarchical Delegation
|
||||||
|
- **Skill Generation** — Auto-generates skills with Progressive Disclosure for efficient context management
|
||||||
|
- **Orchestration** — Inter-agent data passing, error handling, and team coordination protocols
|
||||||
|
- **Validation** — Trigger verification, dry-run testing, and with-skill vs without-skill comparison tests
|
||||||
|
|
||||||
|
|
||||||
|
## Workflow
|
||||||
|
|
||||||
|
```
|
||||||
|
Phase 1: Domain Analysis
|
||||||
|
↓
|
||||||
|
Phase 2: Team Architecture Design (Agent Teams vs Subagents)
|
||||||
|
↓
|
||||||
|
Phase 3: Agent Definition Generation (.claude/agents/)
|
||||||
|
↓
|
||||||
|
Phase 4: Skill Generation (.claude/skills/)
|
||||||
|
↓
|
||||||
|
Phase 5: Integration & Orchestration
|
||||||
|
↓
|
||||||
|
Phase 6: Validation & Testing
|
||||||
|
```
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
### Via Marketplace
|
||||||
|
|
||||||
|
#### Add the marketplace
|
||||||
|
```shell
|
||||||
|
/plugin marketplace add revfactory/harness
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Install the plugin
|
||||||
|
```shell
|
||||||
|
/plugin install harness@harness-marketplace
|
||||||
|
```
|
||||||
|
|
||||||
|
### Direct Installation as Global Skill
|
||||||
|
|
||||||
|
```shell
|
||||||
|
# Copy the skills directory to ~/.claude/skills/harness/
|
||||||
|
cp -r skills/harness ~/.claude/skills/harness
|
||||||
|
```
|
||||||
|
|
||||||
|
## Plugin Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
harness/
|
||||||
|
├── .claude-plugin/
|
||||||
|
│ └── plugin.json # Plugin manifest
|
||||||
|
├── skills/
|
||||||
|
│ └── harness/
|
||||||
|
│ ├── SKILL.md # Main skill definition (6-Phase workflow)
|
||||||
|
│ └── references/
|
||||||
|
│ ├── agent-design-patterns.md # 6 architectural patterns
|
||||||
|
│ ├── orchestrator-template.md # Team/subagent orchestrator templates
|
||||||
|
│ ├── team-examples.md # 5 real-world team configurations
|
||||||
|
│ ├── skill-writing-guide.md # Skill authoring guide
|
||||||
|
│ ├── skill-testing-guide.md # Testing & evaluation methodology
|
||||||
|
│ └── qa-agent-guide.md # QA agent integration guide
|
||||||
|
└── README.md
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Trigger in Claude Code with prompts like:
|
||||||
|
|
||||||
|
```
|
||||||
|
Build a harness for this project
|
||||||
|
Design an agent team for this domain
|
||||||
|
Set up a harness
|
||||||
|
```
|
||||||
|
|
||||||
|
### Execution Modes
|
||||||
|
|
||||||
|
| Mode | Description | Recommended For |
|
||||||
|
|------|-------------|-----------------|
|
||||||
|
| **Agent Teams** (default) | TeamCreate + SendMessage + TaskCreate | 2+ agents requiring collaboration |
|
||||||
|
| **Subagents** | Direct Agent tool invocation | One-off tasks, no inter-agent communication needed |
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<img src="harness_team.png" alt="Harness Agent Team" width="500">
|
||||||
|
</p>
|
||||||
|
|
||||||
|
### Architecture Patterns
|
||||||
|
|
||||||
|
| Pattern | Description |
|
||||||
|
|---------|-------------|
|
||||||
|
| Pipeline | Sequential dependent tasks |
|
||||||
|
| Fan-out/Fan-in | Parallel independent tasks |
|
||||||
|
| Expert Pool | Context-dependent selective invocation |
|
||||||
|
| Producer-Reviewer | Generation followed by quality review |
|
||||||
|
| Supervisor | Central agent with dynamic task distribution |
|
||||||
|
| Hierarchical Delegation | Top-down recursive delegation |
|
||||||
|
|
||||||
|
## Output
|
||||||
|
|
||||||
|
Files generated by Harness:
|
||||||
|
|
||||||
|
```
|
||||||
|
your-project/
|
||||||
|
├── .claude/
|
||||||
|
│ ├── agents/ # Agent definition files
|
||||||
|
│ │ ├── analyst.md
|
||||||
|
│ │ ├── builder.md
|
||||||
|
│ │ └── qa.md
|
||||||
|
│ └── skills/ # Skill files
|
||||||
|
│ ├── analyze/
|
||||||
|
│ │ └── SKILL.md
|
||||||
|
│ └── build/
|
||||||
|
│ ├── SKILL.md
|
||||||
|
│ └── references/
|
||||||
|
```
|
||||||
|
|
||||||
|
## Use Cases — Try These Prompts
|
||||||
|
|
||||||
|
Copy any prompt below into Claude Code after installing Harness:
|
||||||
|
|
||||||
|
**Deep Research**
|
||||||
|
```
|
||||||
|
Build a harness for deep research. I need an agent team that can investigate
|
||||||
|
any topic from multiple angles — web search, academic sources, community
|
||||||
|
sentiment — then cross-validate findings and produce a comprehensive report.
|
||||||
|
```
|
||||||
|
|
||||||
|
**Website Development**
|
||||||
|
```
|
||||||
|
Build a harness for full-stack website development. The team should handle
|
||||||
|
design, frontend (React/Next.js), backend (API), and QA testing in a
|
||||||
|
coordinated pipeline from wireframe to deployment.
|
||||||
|
```
|
||||||
|
|
||||||
|
**Webtoon / Comic Production**
|
||||||
|
```
|
||||||
|
Build a harness for webtoon episode production. I need agents for story
|
||||||
|
writing, character design prompts, panel layout planning, and dialogue
|
||||||
|
editing. They should review each other's work for style consistency.
|
||||||
|
```
|
||||||
|
|
||||||
|
**YouTube Content Planning**
|
||||||
|
```
|
||||||
|
Build a harness for YouTube content creation. The team should research
|
||||||
|
trending topics, write scripts, optimize titles/tags for SEO, and plan
|
||||||
|
thumbnail concepts — all coordinated by a supervisor agent.
|
||||||
|
```
|
||||||
|
|
||||||
|
**Code Review & Refactoring**
|
||||||
|
```
|
||||||
|
Build a harness for comprehensive code review. I want parallel agents
|
||||||
|
checking architecture, security vulnerabilities, performance bottlenecks,
|
||||||
|
and code style — then merging all findings into a single report.
|
||||||
|
```
|
||||||
|
|
||||||
|
**Technical Documentation**
|
||||||
|
```
|
||||||
|
Build a harness that generates API documentation from this codebase.
|
||||||
|
Agents should analyze endpoints, write descriptions, generate usage
|
||||||
|
examples, and review for completeness.
|
||||||
|
```
|
||||||
|
|
||||||
|
**Data Pipeline Design**
|
||||||
|
```
|
||||||
|
Build a harness for designing data pipelines. I need agents for schema
|
||||||
|
design, ETL logic, data validation rules, and monitoring setup that
|
||||||
|
delegate sub-tasks hierarchically.
|
||||||
|
```
|
||||||
|
|
||||||
|
**Marketing Campaign**
|
||||||
|
```
|
||||||
|
Build a harness for marketing campaign creation. The team should research
|
||||||
|
the target market, write ad copy, design visual concepts, and set up
|
||||||
|
A/B test plans with iterative quality review.
|
||||||
|
```
|
||||||
|
|
||||||
|
## Coexistence — Harness and Neighbors
|
||||||
|
|
||||||
|
Harness is not alone in the Claude Code / agent-framework ecosystem. The following repos live in adjacent layers; each is described in a parallel "X is …, Harness is …" form so you can pick the one that fits your need or combine several.
|
||||||
|
|
||||||
|
| Repo | Their position | Relationship to Harness |
|
||||||
|
|------|----------------|-------------------------|
|
||||||
|
| [coleam00/Archon](https://github.com/coleam00/Archon) | "harness builder" — deterministic, repeatable runtime configurations | **Same L3, neighbor sub-layer.** Archon is a Runtime-Configuration Factory, Harness is a Team-Architecture Factory. Pick Archon for runtime determinism, Harness for team architecture, or combine them. |
|
||||||
|
| [SaehwanPark/meta-harness](https://github.com/SaehwanPark/meta-harness) | Codex port of the same concept | **Same L3, different runtime.** Use Harness on Claude Code, meta-harness on Codex. |
|
||||||
|
| [affaan-m/ECC](https://github.com/affaan-m/everything-claude-code) | "Agent harness performance & workflow layer" (sits on top of existing harnesses) | **Different layer.** ECC is a standardization layer across harnesses; Harness is a factory that generates harnesses. Serial combination possible. |
|
||||||
|
| [wshobson/agents](https://github.com/wshobson/agents) | Subagent / skill catalog (182 agents, 149 skills) | **Factory ↔ parts supply.** wshobson is a catalog to shop from; Harness designs the team. Absorb wshobson entries as parts inside a Harness-generated team. |
|
||||||
|
| [LangGraph](https://langchain-ai.github.io/langgraph/) | State-graph orchestration, LLM-agnostic | **Different track.** LangGraph is for long-running, state-recoverable orchestration; Harness is for fast Claude-Code-native team design. |
|
||||||
|
|
||||||
|
## Built with Harness
|
||||||
|
|
||||||
|
### Harness 100
|
||||||
|
|
||||||
|
**[revfactory/harness-100](https://github.com/revfactory/harness-100)** — 100 production-ready agent team harnesses across 10 domains, available in both English and Korean (200 packages total). Each harness ships with 4-5 specialist agents, an orchestrator skill, and domain-specific skills — all generated by this plugin. 1,808 markdown files covering content creation, software development, data/AI, business strategy, education, legal, health, and more.
|
||||||
|
|
||||||
|
### Research: A/B Testing Harness Effectiveness
|
||||||
|
|
||||||
|
**[revfactory/claude-code-harness](https://github.com/revfactory/claude-code-harness)** — A controlled experiment across 15 software engineering tasks measuring the impact of structured pre-configuration on LLM code agent output quality.
|
||||||
|
|
||||||
|
| Metric | Without Harness | With Harness | Improvement |
|
||||||
|
|--------|:-:|:-:|:-:|
|
||||||
|
| Average Quality Score | 49.5 | 79.3 | **+60%** |
|
||||||
|
| Win Rate | — | — | **100%** (15/15) |
|
||||||
|
| Output Variance | — | — | **-32%** |
|
||||||
|
|
||||||
|
Key finding: effectiveness scales with task complexity — the harder the task, the greater the improvement (+23.8 Basic, +29.6 Advanced, +36.2 Expert).
|
||||||
|
|
||||||
|
**Exact phrasing to use everywhere:** +60% avg quality (49.5 → 79.3), 15/15 win-rate, −32% variance (n=15, author-measured A/B, third-party replications pending).
|
||||||
|
|
||||||
|
> Full paper: *Hwang, M. (2026). Harness: Structured Pre-Configuration for Enhancing LLM Code Agent Output Quality.*
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
- [Agent Teams enabled](https://code.claude.com/docs/en/agent-teams): `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1`
|
||||||
|
|
||||||
|
## FAQ
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary><b>Q1. Isn't "+60%" oversold?</b></summary>
|
||||||
|
|
||||||
|
**A.** The +60% figure comes from an **author-measured A/B (n=15, 15 tasks, measured on the sister repo `claude-code-harness`)**. Every citation in this repo pairs the number with the disclosure "n=15, author-measured, third-party replications pending" in the same sentence. For adoption decisions, we recommend running a 2–4 week internal pilot and measuring your own numbers.
|
||||||
|
|
||||||
|
**Evidence:**
|
||||||
|
- Author A/B: [revfactory/claude-code-harness](https://github.com/revfactory/claude-code-harness)
|
||||||
|
- Paper: *Hwang, M. (2026). Harness: Structured Pre-Configuration for Enhancing LLM Code Agent Output Quality*
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary><b>Q2. Why "harness factory" and not "harness builder"? Isn't this competing with Archon?</b></summary>
|
||||||
|
|
||||||
|
**A.** Archon generates deterministic runtime configurations — it's a **Runtime-Configuration Factory**. Harness generates agent team architectures (team structure, message protocols, review gates) — it's a **Team-Architecture Factory**. They are **neighbor sub-layers of the same L3 Meta-Factory** and serve different needs. Pick Archon for runtime determinism, Harness for team-architecture patterns, or combine them (design architecture with Harness → deploy runtime with Archon).
|
||||||
|
|
||||||
|
**Evidence:**
|
||||||
|
- Archon self-definition: [clawfit docs/reference-levels.md](https://github.com/hongsw/clawfit/blob/main/docs/reference-levels.md)
|
||||||
|
- Sub-layer declaration: see the **Category — Where Harness Sits** section above
|
||||||
|
- Archon repo: [github.com/coleam00/Archon](https://github.com/coleam00/Archon)
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary><b>Q3. Isn't "Claude Code only" too narrow? What about Gemini/Codex?</b></summary>
|
||||||
|
|
||||||
|
**A.** Currently the official runtime is Claude Code only. A Codex port of the same concept — [SaehwanPark/meta-harness](https://github.com/SaehwanPark/meta-harness) — is already public, so Codex teams can start there. Harness chose "Claude-Code-native, deep" over "multi-runtime, shallow"; cross-runtime collaboration with sibling repos (meta-harness, harness-init, OpenRig) is on the roadmap.
|
||||||
|
|
||||||
|
**Evidence:**
|
||||||
|
- Codex port: [github.com/SaehwanPark/meta-harness](https://github.com/SaehwanPark/meta-harness)
|
||||||
|
- Cross-runtime scaffolder: [github.com/Gizele1/harness-init](https://github.com/Gizele1/harness-init)
|
||||||
|
</details>
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
Apache 2.0
|
||||||
305
README_JA.md
Normal file
305
README_JA.md
Normal file
@ -0,0 +1,305 @@
|
|||||||
|
<p align="center">
|
||||||
|
<img src="harness_banner.png" alt="Harness Banner" width="600">
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<img src="https://img.shields.io/badge/Version-1.2.0-brightgreen.svg" alt="Version">
|
||||||
|
<a href="LICENSE"><img src="https://img.shields.io/badge/License-Apache_2.0-blue.svg" alt="License"></a>
|
||||||
|
<img src="https://img.shields.io/badge/Claude_Code-Plugin-purple.svg" alt="Claude Code Plugin">
|
||||||
|
<img src="https://img.shields.io/badge/Patterns-6_Architectures-orange.svg" alt="6 Architecture Patterns">
|
||||||
|
<img src="https://img.shields.io/badge/Mode-Agent_Teams-green.svg" alt="Agent Teams">
|
||||||
|
<a href="https://github.com/revfactory/harness/stargazers"><img src="https://img.shields.io/github/stars/revfactory/harness?style=social" alt="GitHub Stars"></a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<a href="#カテゴリー--harness-はどこに位置するか"><img src="https://img.shields.io/badge/Layer-L3%20Meta--Factory-orange" alt="Layer"></a>
|
||||||
|
<a href="#カテゴリー--harness-はどこに位置するか"><img src="https://img.shields.io/badge/Sub--layer-Team--Architecture%20Factory-teal" alt="Sub-layer"></a>
|
||||||
|
<a href="#"><img src="https://img.shields.io/badge/README-EN%20%7C%20KO%20%7C%20JA-lightgrey" alt="i18n"></a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
# Harness — Claude Code のためのチームアーキテクチャファクトリー
|
||||||
|
|
||||||
|
[English](README.md) | [한국어](README_KO.md) | **日本語**
|
||||||
|
|
||||||
|
> **Harness は Claude Code 向けのチームアーキテクチャファクトリーです。** **「ハーネスを構成して」** (日本語) · **"build a harness for this project"** (English) · **"하네스 구성해줘"** (한국어) と伝えるだけで、プラグインがドメイン記述をエージェントチームとそのチームが使うスキルへと変換します — あらかじめ定義された 6 種類のチームアーキテクチャパターンから 1 つを選んで。
|
||||||
|
|
||||||
|
## 概要
|
||||||
|
|
||||||
|
Harnessは、Claude Codeのエージェントチームシステムを活用し、複雑なタスクを専門エージェントチームに分解・統制するアーキテクチャツールです。「ハーネスを構成して」と伝えるだけで、ドメインに適したエージェント定義(`.claude/agents/`)とスキル(`.claude/skills/`)を自動生成します。
|
||||||
|
|
||||||
|
## カテゴリー — Harness はどこに位置するか
|
||||||
|
|
||||||
|
Harness は Claude Code エコシステムの **L3 Meta-Factory** 層 — 他のハーネスそのものではなく「他のハーネスを生成する層」 — に位置します。その層の中で、**Team-Architecture Factory** というサブ層を選択します。
|
||||||
|
|
||||||
|
| 層 | 担当領域 | 共存する隣人 |
|
||||||
|
|----|----------|--------------|
|
||||||
|
| **L3 — Meta-Factory / Team-Architecture Factory** (当プロジェクト) | ドメイン記述 → エージェントチーム + スキル、事前定義された 6 種のチームパターン経由 | — |
|
||||||
|
| L3 — Meta-Factory / Runtime-Configuration Factory | 決定的で再現可能なランタイム構成 | [coleam00/Archon](https://github.com/coleam00/Archon) |
|
||||||
|
| L3 — Meta-Factory / Codex Runtime Port | 同一コンセプトの Codex ランタイム版 | [SaehwanPark/meta-harness](https://github.com/SaehwanPark/meta-harness) |
|
||||||
|
| L2 — Cross-Harness Workflow | 複数ハーネスにまたがるスキル・ルール・フックの標準化 | [affaan-m/ECC](https://github.com/affaan-m/everything-claude-code) |
|
||||||
|
|
||||||
|
> Archon は決定的なランタイム構成を生成します。Harness はチームアーキテクチャ(パイプライン・ファンアウト/ファンイン・エキスパートプール・プロデューサー-レビューア・スーパーバイザー・階層的委任)と、エージェントが使うスキルを生成します。同じ L3 の異なるサブ層です。ランタイムの決定性が欲しければ Archon、チームアーキテクチャが欲しければ Harness、あるいは両者を組み合わせて利用できます。
|
||||||
|
|
||||||
|
## 主な機能
|
||||||
|
|
||||||
|
- **エージェントチーム設計** — パイプライン、ファンアウト/ファンイン、エキスパートプール、プロデューサー-レビューア、スーパーバイザー、階層的委任の6種アーキテクチャパターンに対応
|
||||||
|
- **スキル生成** — Progressive Disclosureパターンによるコンテキストの効率的管理を備えたスキルを自動生成
|
||||||
|
- **オーケストレーション** — エージェント間のデータ受け渡し、エラーハンドリング、チーム連携プロトコルを内蔵
|
||||||
|
- **検証体制** — トリガー検証、ドライランテスト、With-skill vs Without-skill 比較テスト
|
||||||
|
|
||||||
|
## ハーネス進化メカニズム (Harness Evolution Mechanism)
|
||||||
|
|
||||||
|
ハーネス進化メカニズムは「何が効いて、何が効かなかったか」のデルタをファクトリーへフィードバックし、次世代が測定可能なかたちで改善されるようにします。生成されたハーネスが実プロジェクトで使用されると、`/harness:evolve` スキルが初期アーキテクチャとリリース時アーキテクチャのデルタを捕捉し、ファクトリーへ戻します。次回、同様のドメインでの生成は、このフィードバックを反映して「リリース状態により近いドラフト」から始まります。
|
||||||
|
|
||||||
|
```
|
||||||
|
初期ハーネス ──▶ 実プロジェクト利用 ──▶ リリース版ハーネス
|
||||||
|
│
|
||||||
|
▼ (/harness:evolve によるデルタ取得)
|
||||||
|
┌───────────────┐
|
||||||
|
│ ファクトリー │◀── より良い次世代ドラフト
|
||||||
|
└───────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
これを **ハーネス進化メカニズム (Harness Evolution Mechanism; KR: 하네스 진화 메커니즘)** と呼びます。
|
||||||
|
|
||||||
|
## ワークフロー
|
||||||
|
|
||||||
|
```
|
||||||
|
Phase 1: ドメイン分析
|
||||||
|
↓
|
||||||
|
Phase 2: チームアーキテクチャ設計(Agent Teams vs サブエージェント)
|
||||||
|
↓
|
||||||
|
Phase 3: エージェント定義の生成(.claude/agents/)
|
||||||
|
↓
|
||||||
|
Phase 4: スキル生成(.claude/skills/)
|
||||||
|
↓
|
||||||
|
Phase 5: 統合とオーケストレーション
|
||||||
|
↓
|
||||||
|
Phase 6: 検証とテスト
|
||||||
|
```
|
||||||
|
|
||||||
|
## インストール
|
||||||
|
|
||||||
|
### マーケットプレイス経由
|
||||||
|
|
||||||
|
#### マーケットプレイスの追加
|
||||||
|
```shell
|
||||||
|
/plugin marketplace add revfactory/harness
|
||||||
|
```
|
||||||
|
|
||||||
|
#### プラグインのインストール
|
||||||
|
```shell
|
||||||
|
/plugin install harness-marketplace
|
||||||
|
```
|
||||||
|
|
||||||
|
### グローバルスキルとして直接インストール
|
||||||
|
|
||||||
|
```shell
|
||||||
|
# skillsディレクトリを ~/.claude/skills/harness/ にコピー
|
||||||
|
cp -r skills/harness ~/.claude/skills/harness
|
||||||
|
```
|
||||||
|
|
||||||
|
## プラグイン構成
|
||||||
|
|
||||||
|
```
|
||||||
|
harness/
|
||||||
|
├── .claude-plugin/
|
||||||
|
│ └── plugin.json # プラグインマニフェスト
|
||||||
|
├── skills/
|
||||||
|
│ └── harness/
|
||||||
|
│ ├── SKILL.md # メインスキル定義(6フェーズワークフロー)
|
||||||
|
│ └── references/
|
||||||
|
│ ├── agent-design-patterns.md # 6種のアーキテクチャパターン
|
||||||
|
│ ├── orchestrator-template.md # チーム/サブエージェント オーケストレーターテンプレート
|
||||||
|
│ ├── team-examples.md # 実践チーム構成例 5種
|
||||||
|
│ ├── skill-writing-guide.md # スキル作成ガイド
|
||||||
|
│ ├── skill-testing-guide.md # テスト・評価方法論
|
||||||
|
│ └── qa-agent-guide.md # QAエージェント統合ガイド
|
||||||
|
└── README.md
|
||||||
|
```
|
||||||
|
|
||||||
|
## 使い方
|
||||||
|
|
||||||
|
Claude Codeで以下のように呼び出します:
|
||||||
|
|
||||||
|
```
|
||||||
|
Build a harness for this project
|
||||||
|
Design an agent team for this domain
|
||||||
|
Set up a harness
|
||||||
|
```
|
||||||
|
|
||||||
|
### 実行モード
|
||||||
|
|
||||||
|
| モード | 説明 | 推奨ケース |
|
||||||
|
|--------|------|------------|
|
||||||
|
| **Agent Teams**(デフォルト) | TeamCreate + SendMessage + TaskCreate | エージェント2名以上、コラボレーションが必要な場合 |
|
||||||
|
| **サブエージェント** | Agentツール直接呼び出し | 単発タスク、エージェント間通信不要の場合 |
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<img src="harness_team.png" alt="Harness Agent Team" width="500">
|
||||||
|
</p>
|
||||||
|
|
||||||
|
### アーキテクチャパターン
|
||||||
|
|
||||||
|
| パターン | 説明 |
|
||||||
|
|----------|------|
|
||||||
|
| パイプライン | 順次依存タスク |
|
||||||
|
| ファンアウト/ファンイン | 並列独立タスク |
|
||||||
|
| エキスパートプール | 状況に応じた選択的呼び出し |
|
||||||
|
| プロデューサー-レビューア | 生成後の品質レビュー |
|
||||||
|
| スーパーバイザー | 中央エージェントによる動的タスク分配 |
|
||||||
|
| 階層的委任 | 上位→下位への再帰的委任 |
|
||||||
|
|
||||||
|
## 出力
|
||||||
|
|
||||||
|
Harnessが生成するファイル:
|
||||||
|
|
||||||
|
```
|
||||||
|
your-project/
|
||||||
|
├── .claude/
|
||||||
|
│ ├── agents/ # エージェント定義ファイル
|
||||||
|
│ │ ├── analyst.md
|
||||||
|
│ │ ├── builder.md
|
||||||
|
│ │ └── qa.md
|
||||||
|
│ └── skills/ # スキルファイル
|
||||||
|
│ ├── analyze/
|
||||||
|
│ │ └── SKILL.md
|
||||||
|
│ └── build/
|
||||||
|
│ ├── SKILL.md
|
||||||
|
│ └── references/
|
||||||
|
```
|
||||||
|
|
||||||
|
## ユースケース — そのまま使えるプロンプト
|
||||||
|
|
||||||
|
Harnessインストール後、以下のプロンプトをClaude Codeにコピーしてお使いください:
|
||||||
|
|
||||||
|
**ディープリサーチ**
|
||||||
|
```
|
||||||
|
Build a harness for deep research. I need an agent team that can investigate
|
||||||
|
any topic from multiple angles — web search, academic sources, community
|
||||||
|
sentiment — then cross-validate findings and produce a comprehensive report.
|
||||||
|
```
|
||||||
|
|
||||||
|
**ウェブサイト制作**
|
||||||
|
```
|
||||||
|
Build a harness for full-stack website development. The team should handle
|
||||||
|
design, frontend (React/Next.js), backend (API), and QA testing in a
|
||||||
|
coordinated pipeline from wireframe to deployment.
|
||||||
|
```
|
||||||
|
|
||||||
|
**ウェブトゥーン制作**
|
||||||
|
```
|
||||||
|
Build a harness for webtoon episode production. I need agents for story
|
||||||
|
writing, character design prompts, panel layout planning, and dialogue
|
||||||
|
editing. They should review each other's work for style consistency.
|
||||||
|
```
|
||||||
|
|
||||||
|
**YouTube コンテンツ企画**
|
||||||
|
```
|
||||||
|
Build a harness for YouTube content creation. The team should research
|
||||||
|
trending topics, write scripts, optimize titles/tags for SEO, and plan
|
||||||
|
thumbnail concepts — all coordinated by a supervisor agent.
|
||||||
|
```
|
||||||
|
|
||||||
|
**コードレビュー**
|
||||||
|
```
|
||||||
|
Build a harness for comprehensive code review. I want parallel agents
|
||||||
|
checking architecture, security vulnerabilities, performance bottlenecks,
|
||||||
|
and code style — then merging all findings into a single report.
|
||||||
|
```
|
||||||
|
|
||||||
|
**技術ドキュメント作成**
|
||||||
|
```
|
||||||
|
Build a harness that generates API documentation from this codebase.
|
||||||
|
Agents should analyze endpoints, write descriptions, generate usage
|
||||||
|
examples, and review for completeness.
|
||||||
|
```
|
||||||
|
|
||||||
|
**データパイプライン設計**
|
||||||
|
```
|
||||||
|
Build a harness for designing data pipelines. I need agents for schema
|
||||||
|
design, ETL logic, data validation rules, and monitoring setup that
|
||||||
|
delegate sub-tasks hierarchically.
|
||||||
|
```
|
||||||
|
|
||||||
|
**マーケティングキャンペーン**
|
||||||
|
```
|
||||||
|
Build a harness for marketing campaign creation. The team should research
|
||||||
|
the target market, write ad copy, design visual concepts, and set up
|
||||||
|
A/B test plans with iterative quality review.
|
||||||
|
```
|
||||||
|
|
||||||
|
## 共存 — Harness と隣人たち
|
||||||
|
|
||||||
|
Harness は Claude Code / エージェントフレームワークのエコシステムで一人ではありません。以下のリポジトリは隣接する層に位置しており、いずれも「X は ···、Harness は ···」という並列構造で記述されているため、用途に応じて選んだり、複数を組み合わせて利用できます。
|
||||||
|
|
||||||
|
| リポジトリ | 相手のポジション | Harness との関係 |
|
||||||
|
|------------|------------------|------------------|
|
||||||
|
| [coleam00/Archon](https://github.com/coleam00/Archon) | "harness builder" — 決定的で再現可能なランタイム構成 | **同じ L3、隣のサブ層。** Archon は Runtime-Configuration Factory、Harness は Team-Architecture Factory。ランタイム決定性は Archon、チームアーキテクチャは Harness、または両者の組み合わせ。 |
|
||||||
|
| [SaehwanPark/meta-harness](https://github.com/SaehwanPark/meta-harness) | 同一コンセプトの Codex 移植 | **同じ L3、異なるランタイム。** Claude Code では Harness、Codex では meta-harness。 |
|
||||||
|
| [affaan-m/ECC](https://github.com/affaan-m/everything-claude-code) | "Agent harness performance & workflow layer" — 既存ハーネスの上に乗る標準化層 | **異なる層。** ECC は複数ハーネスの上の標準化層、Harness はハーネスを生成するファクトリー。直列的に組み合わせ可能。 |
|
||||||
|
| [wshobson/agents](https://github.com/wshobson/agents) | サブエージェント / スキルカタログ (182 agents, 149 skills) | **ファクトリー ↔ 部品供給。** wshobson は「ショッピングするカタログ」、Harness は「チーム設計」。Harness が生成したチーム内に wshobson のエントリを部品として取り込み可能。 |
|
||||||
|
| [LangGraph](https://langchain-ai.github.io/langgraph/) | ステートグラフ・オーケストレーション、LLM-agnostic | **異なるトラック。** 長時間実行・状態復元が要なら LangGraph、Claude Code ネイティブでの素早いチーム設計が要なら Harness。 |
|
||||||
|
|
||||||
|
## Harnessで構築されたプロジェクト
|
||||||
|
|
||||||
|
### Harness 100
|
||||||
|
|
||||||
|
**[revfactory/harness-100](https://github.com/revfactory/harness-100)** — 10ドメイン、100のプロダクションレディなエージェントチームハーネス(英韓200パッケージ)。各ハーネスには4〜5名の専門エージェント、オーケストレータースキル、ドメイン特化スキルが含まれており、すべて本プラグインで生成されました。コンテンツ制作、ソフトウェア開発、データ/AI、ビジネス戦略、教育、法律、ヘルスケアなど1,808のMarkdownファイル。
|
||||||
|
|
||||||
|
### 研究:Harness適用前後のA/Bテスト
|
||||||
|
|
||||||
|
**[revfactory/claude-code-harness](https://github.com/revfactory/claude-code-harness)** — 15のソフトウェアエンジニアリング課題を対象とした統制実験で、構造化された事前設定がLLMコードエージェントの出力品質に与える影響を測定しました。
|
||||||
|
|
||||||
|
| 指標 | Harness未適用 | Harness適用 | 改善 |
|
||||||
|
|------|:-:|:-:|:-:|
|
||||||
|
| 平均品質スコア | 49.5 | 79.3 | **+60%** |
|
||||||
|
| 勝率 | — | — | **100%** (15/15) |
|
||||||
|
| 出力分散 | — | — | **-32%** |
|
||||||
|
|
||||||
|
主な発見:課題の難易度が高いほど改善効果が増大(Basic +23.8、Advanced +29.6、Expert +36.2)。
|
||||||
|
|
||||||
|
**あらゆる場面でこの文をそのままお使いください:** 平均品質 +60% (49.5 → 79.3)、15/15 勝率、出力分散 −32% (n=15、著者測定 A/B、第三者再現実験は進行中)。
|
||||||
|
|
||||||
|
> 論文全文:*Hwang, M. (2026). Harness: Structured Pre-Configuration for Enhancing LLM Code Agent Output Quality.*
|
||||||
|
|
||||||
|
## 要件
|
||||||
|
|
||||||
|
- [Agent Teams機能の有効化](https://code.claude.com/docs/en/agent-teams):`CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1`
|
||||||
|
|
||||||
|
## FAQ
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary><b>Q1. "+60%" は誇張では?</b></summary>
|
||||||
|
|
||||||
|
**A.** +60% は **著者自身による A/B(n=15、15 タスク、姉妹リポジトリ `claude-code-harness` で計測)** の結果です。本リポジトリでは、この数値を引用する際は必ず「n=15、著者測定、第三者再現実験は進行中」を同じ文の中に併記しています。組織導入時には、2〜4 週間の社内パイロットで独自の数値を測定することを推奨します。
|
||||||
|
|
||||||
|
**Evidence:**
|
||||||
|
- 著者 A/B: [revfactory/claude-code-harness](https://github.com/revfactory/claude-code-harness)
|
||||||
|
- 論文: *Hwang, M. (2026). Harness: Structured Pre-Configuration for Enhancing LLM Code Agent Output Quality*
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary><b>Q2. なぜ "harness builder" ではなく "harness factory" なのですか? Archon と競合しませんか?</b></summary>
|
||||||
|
|
||||||
|
**A.** Archon は決定的なランタイム構成を生成する **Runtime-Configuration Factory** であり、Harness はエージェントチームアーキテクチャ(チーム構造・メッセージプロトコル・レビューゲート)を生成する **Team-Architecture Factory** です。両者は **同じ L3 Meta-Factory 層の隣接するサブ層** で、用途が異なります。決定的なランタイムが必要なら Archon、6 つのチームアーキテクチャパターンの事前定義が必要なら Harness。両者を組み合わせる(アーキテクチャ設計 → ランタイム配置)ことも可能です。
|
||||||
|
|
||||||
|
**Evidence:**
|
||||||
|
- Archon 自己定義: [clawfit docs/reference-levels.md](https://github.com/hongsw/clawfit/blob/main/docs/reference-levels.md)
|
||||||
|
- サブ層宣言: 本 README の **カテゴリー — Harness はどこに位置するか** セクション
|
||||||
|
- Archon リポジトリ: [github.com/coleam00/Archon](https://github.com/coleam00/Archon)
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary><b>Q3. 「Claude Code 専用」は狭すぎませんか? Gemini・Codex は?</b></summary>
|
||||||
|
|
||||||
|
**A.** 現時点で公式のランタイムは Claude Code のみです。同一コンセプトの Codex 移植 [SaehwanPark/meta-harness](https://github.com/SaehwanPark/meta-harness) がすでに公開されており、既存の Codex チームはそちらから開始できます。Harness は「Claude Code ネイティブ・深く」を選択しており、クロスランタイムの需要は共存リポジトリ(meta-harness、harness-init、OpenRig)との連携計画としてロードマップに反映される予定です。
|
||||||
|
|
||||||
|
**Evidence:**
|
||||||
|
- Codex 移植: [github.com/SaehwanPark/meta-harness](https://github.com/SaehwanPark/meta-harness)
|
||||||
|
- クロスランタイム・スキャフォルダー: [github.com/Gizele1/harness-init](https://github.com/Gizele1/harness-init)
|
||||||
|
</details>
|
||||||
|
|
||||||
|
## ライセンス
|
||||||
|
|
||||||
|
Apache 2.0
|
||||||
298
README_KO.md
Normal file
298
README_KO.md
Normal file
@ -0,0 +1,298 @@
|
|||||||
|
<p align="center">
|
||||||
|
<img src="harness_banner.png" alt="Harness Banner" width="600">
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<img src="https://img.shields.io/badge/Version-1.2.0-brightgreen.svg" alt="Version">
|
||||||
|
<a href="LICENSE"><img src="https://img.shields.io/badge/License-Apache_2.0-blue.svg" alt="License"></a>
|
||||||
|
<img src="https://img.shields.io/badge/Claude_Code-Plugin-purple.svg" alt="Claude Code Plugin">
|
||||||
|
<img src="https://img.shields.io/badge/Patterns-6_Architectures-orange.svg" alt="6 Architecture Patterns">
|
||||||
|
<img src="https://img.shields.io/badge/Mode-Agent_Teams-green.svg" alt="Agent Teams">
|
||||||
|
<a href="https://github.com/revfactory/harness/stargazers"><img src="https://img.shields.io/github/stars/revfactory/harness?style=social" alt="GitHub Stars"></a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<a href="#카테고리--harness는-어디에-서-있나요"><img src="https://img.shields.io/badge/Layer-L3%20Meta--Factory-orange" alt="Layer"></a>
|
||||||
|
<a href="#카테고리--harness는-어디에-서-있나요"><img src="https://img.shields.io/badge/Sub--layer-Team--Architecture%20Factory-teal" alt="Sub-layer"></a>
|
||||||
|
<a href="#"><img src="https://img.shields.io/badge/README-EN%20%7C%20KO%20%7C%20JA-lightgrey" alt="i18n"></a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
# Harness — Claude Code를 위한 팀 아키텍처 팩토리
|
||||||
|
|
||||||
|
[English](README.md) | **한국어** | [日本語](README_JA.md)
|
||||||
|
|
||||||
|
> **Harness는 Claude Code용 팀 아키텍처 팩토리입니다.** **"하네스 구성해줘"** (한국어) · **"build a harness for this project"** (English) · **"ハーネスを構成して"** (日本語) 한 문장으로, 플러그인이 도메인 설명을 에이전트 팀과 그들이 쓸 스킬로 변환합니다 — 사전 정의된 6가지 팀 아키텍처 패턴 중 하나를 골라서요.
|
||||||
|
|
||||||
|
## 개요
|
||||||
|
|
||||||
|
Harness는 Claude Code의 에이전트 팀 시스템을 활용하여 복잡한 작업을 전문 에이전트 팀으로 분해·조율하는 아키텍처 도구다. "하네스 구성해줘"라고 말하면, 사용자의 도메인에 맞는 에이전트 정의(`.claude/agents/`)와 스킬(`.claude/skills/`)을 자동 생성한다.
|
||||||
|
|
||||||
|
## 카테고리 — Harness는 어디에 서 있나요
|
||||||
|
|
||||||
|
Harness는 Claude Code 생태계의 **L3 Meta-Factory** 층 — 다른 하네스들이 아니라 "다른 하네스들을 생성하는 층" — 에 자리합니다. 그 층 안에서 우리는 **Team-Architecture Factory** 서브 층을 선택합니다.
|
||||||
|
|
||||||
|
| 층위 | 하는 일 | 공존하는 이웃 |
|
||||||
|
|------|---------|---------------|
|
||||||
|
| **L3 — Meta-Factory / Team-Architecture Factory** (우리) | 도메인 설명 → 에이전트 팀 + 스킬, 6가지 사전 정의된 팀 패턴 | — |
|
||||||
|
| L3 — Meta-Factory / Runtime-Configuration Factory | 결정적(deterministic)·반복 가능한 런타임 설정 생성 | [coleam00/Archon](https://github.com/coleam00/Archon) |
|
||||||
|
| L3 — Meta-Factory / Codex Runtime Port | 같은 컨셉, Codex 런타임 | [SaehwanPark/meta-harness](https://github.com/SaehwanPark/meta-harness) |
|
||||||
|
| L2 — Cross-Harness Workflow | 여러 하네스 위에서 스킬·규칙·훅을 표준화 | [affaan-m/ECC](https://github.com/affaan-m/everything-claude-code) |
|
||||||
|
|
||||||
|
> Archon은 결정적 런타임 설정을 뽑아냅니다. Harness는 팀 아키텍처(파이프라인·팬아웃/팬인·전문가 풀·생성-검증·감독자·계층적 위임)와 에이전트가 쓸 스킬을 뽑아냅니다. 같은 L3의 서로 다른 서브 층입니다. 런타임 결정성은 Archon, 팀 아키텍처는 Harness, 또는 둘을 조합해서 쓰세요.
|
||||||
|
|
||||||
|
## 핵심 기능
|
||||||
|
|
||||||
|
- **에이전트 팀 설계** — 파이프라인, 팬아웃/팬인, 전문가 풀, 생성-검증, 감독자, 계층적 위임 등 6가지 아키텍처 패턴 지원
|
||||||
|
- **스킬 생성** — Progressive Disclosure 패턴으로 컨텍스트를 효율 관리하는 스킬 자동 생성
|
||||||
|
- **오케스트레이션** — 에이전트 간 데이터 전달, 에러 핸들링, 팀 조율 프로토콜 포함
|
||||||
|
- **검증 체계** — 트리거 검증, 드라이런 테스트, With-skill vs Without-skill 비교 테스트
|
||||||
|
|
||||||
|
## 하네스 진화 메커니즘 (Harness Evolution Mechanism)
|
||||||
|
|
||||||
|
하네스 진화 메커니즘은 "무엇이 먹혔고 무엇이 안 먹혔는가"의 델타를 팩토리로 되먹여, 다음 세대가 측정 가능하게 더 나아지도록 합니다. 실제 프로젝트에서 생성된 하네스가 사용될 때, `/harness:evolve` 스킬이 초기 아키텍처와 최종 출시 아키텍처 간 변화량을 포착해 팩토리로 되먹입니다. 다음번 같은 도메인에 대한 생성은 이 되먹임을 반영해 "출시 상태에 더 가까운 초안"에서 시작합니다.
|
||||||
|
|
||||||
|
```
|
||||||
|
초기 하네스 ──▶ 실 프로젝트 사용 ──▶ 출시 하네스
|
||||||
|
│
|
||||||
|
▼ (/harness:evolve 로 델타 포착)
|
||||||
|
┌───────────────┐
|
||||||
|
│ 팩토리 │◀── 더 나은 다음 세대 초안
|
||||||
|
└───────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
이것이 **하네스 진화 메커니즘 (Harness Evolution Mechanism; JA: ハーネス進化メカニズム)** 입니다.
|
||||||
|
|
||||||
|
## 워크플로우
|
||||||
|
|
||||||
|
```
|
||||||
|
Phase 1: 도메인 분석
|
||||||
|
↓
|
||||||
|
Phase 2: 팀 아키텍처 설계 (에이전트 팀 vs 서브 에이전트)
|
||||||
|
↓
|
||||||
|
Phase 3: 에이전트 정의 생성 (.claude/agents/)
|
||||||
|
↓
|
||||||
|
Phase 4: 스킬 생성 (.claude/skills/)
|
||||||
|
↓
|
||||||
|
Phase 5: 통합 및 오케스트레이션
|
||||||
|
↓
|
||||||
|
Phase 6: 검증 및 테스트
|
||||||
|
```
|
||||||
|
|
||||||
|
## 설치
|
||||||
|
|
||||||
|
### 마켓플레이스 등록 후 설치
|
||||||
|
|
||||||
|
#### 마켓플레이스 추가
|
||||||
|
```shell
|
||||||
|
/plugin marketplace add revfactory/harness
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 플러그인 설치
|
||||||
|
```shell
|
||||||
|
/plugin install harness-marketplace
|
||||||
|
```
|
||||||
|
|
||||||
|
### 글로벌 스킬로 직접 설치
|
||||||
|
|
||||||
|
```shell
|
||||||
|
# skills 디렉토리를 ~/.claude/skills/harness/에 복사
|
||||||
|
cp -r skills/harness ~/.claude/skills/harness
|
||||||
|
```
|
||||||
|
|
||||||
|
## 플러그인 구조
|
||||||
|
|
||||||
|
```
|
||||||
|
harness/
|
||||||
|
├── .claude-plugin/
|
||||||
|
│ └── plugin.json # 플러그인 매니페스트
|
||||||
|
├── skills/
|
||||||
|
│ └── harness/
|
||||||
|
│ ├── SKILL.md # 메인 스킬 정의 (6 Phase 워크플로우)
|
||||||
|
│ └── references/
|
||||||
|
│ ├── agent-design-patterns.md # 6가지 아키텍처 패턴
|
||||||
|
│ ├── orchestrator-template.md # 팀/서브에이전트 오케스트레이터 템플릿
|
||||||
|
│ ├── team-examples.md # 실전 팀 구성 예시 5종
|
||||||
|
│ ├── skill-writing-guide.md # 스킬 작성 가이드
|
||||||
|
│ ├── skill-testing-guide.md # 테스트/평가 방법론
|
||||||
|
│ └── qa-agent-guide.md # QA 에이전트 통합 가이드
|
||||||
|
└── README.md
|
||||||
|
```
|
||||||
|
|
||||||
|
## 사용법
|
||||||
|
|
||||||
|
Claude Code에서 다음과 같이 트리거한다:
|
||||||
|
|
||||||
|
```
|
||||||
|
하네스 구성해줘
|
||||||
|
하네스 설계해줘
|
||||||
|
이 프로젝트에 맞는 에이전트 팀 구축해줘
|
||||||
|
```
|
||||||
|
|
||||||
|
### 실행 모드
|
||||||
|
|
||||||
|
| 모드 | 설명 | 권장 상황 |
|
||||||
|
|------|------|----------|
|
||||||
|
| **에이전트 팀** (기본) | TeamCreate + SendMessage + TaskCreate | 2개 이상 에이전트, 협업 필요 |
|
||||||
|
| **서브 에이전트** | Agent 도구 직접 호출 | 단발성 작업, 통신 불필요 |
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<img src="harness_team.png" alt="Harness Agent Team" width="500">
|
||||||
|
</p>
|
||||||
|
|
||||||
|
### 아키텍처 패턴
|
||||||
|
|
||||||
|
| 패턴 | 설명 |
|
||||||
|
|------|------|
|
||||||
|
| 파이프라인 | 순차 의존 작업 |
|
||||||
|
| 팬아웃/팬인 | 병렬 독립 작업 |
|
||||||
|
| 전문가 풀 | 상황별 선택 호출 |
|
||||||
|
| 생성-검증 | 생성 후 품질 검수 |
|
||||||
|
| 감독자 | 중앙 에이전트가 동적 분배 |
|
||||||
|
| 계층적 위임 | 상위→하위 재귀적 위임 |
|
||||||
|
|
||||||
|
## 산출물
|
||||||
|
|
||||||
|
하네스가 생성하는 파일:
|
||||||
|
|
||||||
|
```
|
||||||
|
프로젝트/
|
||||||
|
├── .claude/
|
||||||
|
│ ├── agents/ # 에이전트 정의 파일
|
||||||
|
│ │ ├── analyst.md
|
||||||
|
│ │ ├── builder.md
|
||||||
|
│ │ └── qa.md
|
||||||
|
│ └── skills/ # 스킬 파일
|
||||||
|
│ ├── analyze/
|
||||||
|
│ │ └── SKILL.md
|
||||||
|
│ └── build/
|
||||||
|
│ ├── SKILL.md
|
||||||
|
│ └── references/
|
||||||
|
```
|
||||||
|
|
||||||
|
## 사용 사례 — 이 프롬프트를 그대로 사용하세요
|
||||||
|
|
||||||
|
Harness 설치 후 아래 프롬프트를 Claude Code에 복사해서 사용하세요:
|
||||||
|
|
||||||
|
**딥 리서치**
|
||||||
|
```
|
||||||
|
리서치 하네스를 구성해줘. 어떤 주제든 여러 각도에서 조사할 수 있는 에이전트 팀이
|
||||||
|
필요해 — 웹 검색, 학술 자료, 커뮤니티 반응 — 교차 검증 후 종합 보고서를 작성하는 팀.
|
||||||
|
```
|
||||||
|
|
||||||
|
**웹사이트 제작**
|
||||||
|
```
|
||||||
|
풀스택 웹사이트 개발 하네스를 구성해줘. 디자인, 프론트엔드(React/Next.js),
|
||||||
|
백엔드(API), QA 테스트를 와이어프레임부터 배포까지 파이프라인으로 조율하는 팀.
|
||||||
|
```
|
||||||
|
|
||||||
|
**웹툰 제작**
|
||||||
|
```
|
||||||
|
웹툰 에피소드 제작 하네스를 구성해줘. 스토리 작성, 캐릭터 디자인 프롬프트,
|
||||||
|
패널 레이아웃 기획, 대사 편집 에이전트가 필요하고 서로의 작업물을
|
||||||
|
스타일 일관성 관점에서 리뷰해야 해.
|
||||||
|
```
|
||||||
|
|
||||||
|
**유튜브 콘텐츠 기획**
|
||||||
|
```
|
||||||
|
유튜브 콘텐츠 제작 하네스를 구성해줘. 트렌드 조사, 대본 작성, 제목/태그 SEO 최적화,
|
||||||
|
썸네일 컨셉 기획을 감독자 에이전트가 조율하는 팀.
|
||||||
|
```
|
||||||
|
|
||||||
|
**코드 리뷰**
|
||||||
|
```
|
||||||
|
종합 코드 리뷰 하네스를 구성해줘. 아키텍처, 보안 취약점, 성능 병목, 코드 스타일을
|
||||||
|
병렬로 감사하는 에이전트들이 결과를 하나의 리포트로 통합하는 팀.
|
||||||
|
```
|
||||||
|
|
||||||
|
**기술 문서 작성**
|
||||||
|
```
|
||||||
|
이 코드베이스에서 API 문서를 자동 생성하는 하네스를 구성해줘. 엔드포인트 분석,
|
||||||
|
설명 작성, 사용 예제 생성, 완성도 리뷰를 파이프라인으로 처리하는 팀.
|
||||||
|
```
|
||||||
|
|
||||||
|
**데이터 파이프라인 설계**
|
||||||
|
```
|
||||||
|
데이터 파이프라인 설계 하네스를 구성해줘. 스키마 설계, ETL 로직, 데이터 검증 규칙,
|
||||||
|
모니터링 설정을 계층적으로 위임하는 에이전트 팀.
|
||||||
|
```
|
||||||
|
|
||||||
|
**마케팅 캠페인**
|
||||||
|
```
|
||||||
|
마케팅 캠페인 제작 하네스를 구성해줘. 타겟 시장 조사, 광고 카피 작성,
|
||||||
|
비주얼 컨셉 디자인, A/B 테스트 계획을 반복적 품질 리뷰와 함께 진행하는 팀.
|
||||||
|
```
|
||||||
|
|
||||||
|
## 공존 — Harness와 이웃 저장소들
|
||||||
|
|
||||||
|
Harness는 Claude Code / 에이전트 프레임워크 생태계에서 혼자가 아닙니다. 아래 저장소들은 인접한 층위에 위치하며, 모두 "X는 ···, Harness는 ···" 병렬 구조로 기술되어 있어 용도에 맞게 선택하거나 조합할 수 있습니다.
|
||||||
|
|
||||||
|
| 저장소 | 저장소의 포지션 | Harness와의 관계 |
|
||||||
|
|--------|-----------------|------------------|
|
||||||
|
| [coleam00/Archon](https://github.com/coleam00/Archon) | "harness builder" — 결정적·반복 가능한 런타임 설정 | **같은 L3, 이웃 서브 층.** Archon은 Runtime-Configuration Factory, Harness는 Team-Architecture Factory. 런타임 결정성은 Archon, 팀 아키텍처는 Harness, 또는 조합. |
|
||||||
|
| [SaehwanPark/meta-harness](https://github.com/SaehwanPark/meta-harness) | 같은 컨셉의 Codex 포트 | **같은 L3, 다른 런타임.** Claude Code에서는 Harness, Codex에서는 meta-harness. |
|
||||||
|
| [affaan-m/ECC](https://github.com/affaan-m/everything-claude-code) | "Agent harness performance & workflow layer" — 기존 하네스 위에 앉는 표준화 층 | **다른 층위.** ECC는 여러 하네스 위 표준화 층, Harness는 하네스를 생성하는 팩토리. 직렬 조합 가능. |
|
||||||
|
| [wshobson/agents](https://github.com/wshobson/agents) | 서브 에이전트 / 스킬 카탈로그 (182 agents, 149 skills) | **팩토리 ↔ 부품 공급.** wshobson은 "쇼핑할 카탈로그", Harness는 "팀 설계". Harness가 만든 팀에 wshobson 항목을 부품으로 흡수. |
|
||||||
|
| [LangGraph](https://langchain-ai.github.io/langgraph/) | 상태 그래프 오케스트레이션, LLM-agnostic | **다른 트랙.** 장기 실행·상태 복구가 핵심이면 LangGraph, Claude Code 네이티브의 빠른 팀 설계가 핵심이면 Harness. |
|
||||||
|
|
||||||
|
## Harness로 만든 프로젝트
|
||||||
|
|
||||||
|
### Harness 100
|
||||||
|
|
||||||
|
**[revfactory/harness-100](https://github.com/revfactory/harness-100)** — 10개 도메인, 100개의 프로덕션 레디 에이전트 팀 하네스 (한영 200패키지). 각 하네스에 4-5명의 전문 에이전트, 오케스트레이터 스킬, 도메인 특화 스킬이 포함되어 있으며, 모두 이 플러그인으로 생성되었습니다. 콘텐츠 제작, 소프트웨어 개발, 데이터/AI, 비즈니스 전략, 교육, 법률, 헬스케어 등 1,808개 마크다운 파일.
|
||||||
|
|
||||||
|
### 연구: Harness 적용 전후 A/B 테스트
|
||||||
|
|
||||||
|
**[revfactory/claude-code-harness](https://github.com/revfactory/claude-code-harness)** — 15개 소프트웨어 엔지니어링 과제에 대한 통제 실험으로, 구조화된 사전 설정이 LLM 코드 에이전트 출력 품질에 미치는 영향을 측정했습니다.
|
||||||
|
|
||||||
|
| 지표 | Harness 미적용 | Harness 적용 | 개선 |
|
||||||
|
|------|:-:|:-:|:-:|
|
||||||
|
| 평균 품질 점수 | 49.5 | 79.3 | **+60%** |
|
||||||
|
| 승률 | — | — | **100%** (15/15) |
|
||||||
|
| 출력 분산 | — | — | **-32%** |
|
||||||
|
|
||||||
|
핵심 발견: 과제 난이도가 높을수록 개선 효과가 증대 (Basic +23.8, Advanced +29.6, Expert +36.2).
|
||||||
|
|
||||||
|
**어디에서나 이 문장을 그대로 사용하세요:** 평균 품질 +60% (49.5 → 79.3), 15/15 승률, 출력 분산 −32% (n=15, 저자 자체 측정 A/B, 제3자 재현 실험 진행 중).
|
||||||
|
|
||||||
|
> 논문 전문: *Hwang, M. (2026). Harness: Structured Pre-Configuration for Enhancing LLM Code Agent Output Quality.*
|
||||||
|
|
||||||
|
## 요구사항
|
||||||
|
|
||||||
|
- [에이전트 팀 기능 활성화](https://code.claude.com/docs/en/agent-teams): `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1`
|
||||||
|
|
||||||
|
## FAQ
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary><b>Q1. "+60%"는 과대 포장 아닌가요?</b></summary>
|
||||||
|
|
||||||
|
**A.** +60%는 **저자 자체 A/B(n=15, 15개 과제, 자매 저장소 `claude-code-harness`에서 측정)** 결과입니다. 본 저장소는 이 수치를 인용할 때 언제나 "n=15, 저자 자체 측정, 제3자 재현 진행 중"을 같은 문장 안에 병기합니다. 조직 도입 시에는 2~4주 내부 파일럿으로 자체 수치를 측정할 것을 권장합니다.
|
||||||
|
|
||||||
|
**Evidence:**
|
||||||
|
- 저자 A/B: [revfactory/claude-code-harness](https://github.com/revfactory/claude-code-harness)
|
||||||
|
- 논문: *Hwang, M. (2026). Harness: Structured Pre-Configuration for Enhancing LLM Code Agent Output Quality*
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary><b>Q2. 왜 "harness builder"가 아니라 "harness factory"인가요? Archon과 경쟁하나요?</b></summary>
|
||||||
|
|
||||||
|
**A.** Archon은 결정적 런타임 설정을 생성하는 **Runtime-Configuration Factory** 성격, Harness는 에이전트 팀 아키텍처(팀 구조·메시지 프로토콜·리뷰 게이트)를 생성하는 **Team-Architecture Factory** 성격입니다. 둘은 **같은 L3 Meta-Factory 층의 이웃 서브 층**이며, 용도가 다릅니다. 결정적 런타임이 필요하면 Archon, 팀 아키텍처 6패턴 사전 정의가 필요하면 Harness. 조합 사용(아키텍처 설계 → 런타임 배포)도 가능합니다.
|
||||||
|
|
||||||
|
**Evidence:**
|
||||||
|
- Archon 자기 규정: [clawfit docs/reference-levels.md](https://github.com/hongsw/clawfit/blob/main/docs/reference-levels.md)
|
||||||
|
- 서브 층 선언: 본 README **카테고리 — Harness는 어디에 서 있나요** 섹션
|
||||||
|
- Archon 저장소: [github.com/coleam00/Archon](https://github.com/coleam00/Archon)
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary><b>Q3. "Claude Code 전용"이 너무 좁은 것 아닌가요? Gemini·Codex는?</b></summary>
|
||||||
|
|
||||||
|
**A.** 현재 공식 런타임은 Claude Code 단일입니다. 같은 컨셉의 Codex 포트 [SaehwanPark/meta-harness](https://github.com/SaehwanPark/meta-harness)가 이미 공개되어 있어, 기존 Codex 팀은 그쪽에서 바로 시작할 수 있습니다. Harness는 "Claude Code 네이티브·깊게"를 택한 상태이며, 크로스 런타임 수요는 공존 저장소(meta-harness, harness-init, OpenRig)와의 연계 계획을 로드맵에 반영할 예정입니다.
|
||||||
|
|
||||||
|
**Evidence:**
|
||||||
|
- Codex 포트: [github.com/SaehwanPark/meta-harness](https://github.com/SaehwanPark/meta-harness)
|
||||||
|
- 크로스 런타임 스캐폴더: [github.com/Gizele1/harness-init](https://github.com/Gizele1/harness-init)
|
||||||
|
</details>
|
||||||
|
|
||||||
|
## 라이선스
|
||||||
|
|
||||||
|
Apache 2.0
|
||||||
153
docs/experimental-dependency.md
Normal file
153
docs/experimental-dependency.md
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
# Experimental Flag Dependency
|
||||||
|
|
||||||
|
> **Status:** Active · **Owner:** revfactory · **Last updated:** 2026-04-18 · **SLA:** See [Monitoring Commitment](#monitoring-commitment)
|
||||||
|
|
||||||
|
This document explains why `harness` requires `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1`, the three plausible futures of that flag, and what this repository will do in each case — with time-boxed commitments so enterprise adopters can plan against it.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Current State
|
||||||
|
|
||||||
|
### Why the flag is required
|
||||||
|
|
||||||
|
`harness` is a meta-skill factory built on top of Claude Code's **Agent Teams API**. Three Claude Code primitives are invoked internally whenever a user runs `claude "build a harness for <domain>"`:
|
||||||
|
|
||||||
|
| Primitive | Purpose | Flag gated? |
|
||||||
|
|-----------|---------|-------------|
|
||||||
|
| `TeamCreate` | Instantiates a multi-agent team with shared context | **Yes** |
|
||||||
|
| `SendMessage` | Routes messages between team members (supervisor ↔ worker) | **Yes** |
|
||||||
|
| `TaskCreate` | Spawns long-running subtasks inside a team | **Yes** |
|
||||||
|
| `Agent` tool (invoke) | Single-agent dispatch | No (GA) |
|
||||||
|
|
||||||
|
All three flag-gated primitives require:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1
|
||||||
|
```
|
||||||
|
|
||||||
|
Without this variable set in the shell that launches `claude`, harness's generated teams fall back to single-agent execution, which silently breaks the Pipeline / Fan-out-in / Supervisor / Hierarchical Delegation patterns.
|
||||||
|
|
||||||
|
### Anthropic references (required reading before filing issues)
|
||||||
|
|
||||||
|
The design rationale and roadmap for this flag live in three Anthropic Engineering posts. Adopters evaluating harness should read at least the first:
|
||||||
|
|
||||||
|
1. [Effective harnesses for long-running agents](https://www.anthropic.com/engineering/effective-harnesses-for-long-running-agents) — defines the "harness" category Anthropic endorses and the long-running agent contract.
|
||||||
|
2. [Harness design for long-running apps](https://www.anthropic.com/engineering/harness-design-long-running-apps) — the patterns `harness` codifies (Pipeline, Producer-Reviewer, Supervisor, etc.).
|
||||||
|
3. [Scaling Managed Agents](https://www.anthropic.com/engineering/managed-agents) — the forward path that may supersede the Experimental flag (see Scenario B).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Dependency Graph
|
||||||
|
|
||||||
|
```
|
||||||
|
harness (v1.2.0)
|
||||||
|
└── Agent Teams API (Claude Code)
|
||||||
|
├── TeamCreate ← EXPERIMENTAL_AGENT_TEAMS=1
|
||||||
|
├── SendMessage ← EXPERIMENTAL_AGENT_TEAMS=1
|
||||||
|
├── TaskCreate ← EXPERIMENTAL_AGENT_TEAMS=1
|
||||||
|
└── Agent (invoke) ← GA (flag-independent)
|
||||||
|
└── Anthropic Roadmap
|
||||||
|
├── Scenario A: Flag removed (GA promotion)
|
||||||
|
├── Scenario B: Managed Agents GA (parallel path)
|
||||||
|
└── Scenario C: Breaking signature change
|
||||||
|
```
|
||||||
|
|
||||||
|
**Read this graph top-down:** harness depends on Agent Teams API, which depends on a single Experimental flag, which depends on Anthropic's own roadmap. If any upstream node changes, this repository is on the hook to adapt within the SLA below.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3 Scenarios
|
||||||
|
|
||||||
|
Each scenario lists the **detection trigger** (how we will know it happened), the **T+24h / T+48h / T+72h actions** this repository commits to, and the **user-visible artifact** at each checkpoint.
|
||||||
|
|
||||||
|
### Scenario A — Flag removed (Agent Teams promoted to GA)
|
||||||
|
|
||||||
|
**Trigger detection:** Anthropic Claude Code Changelog publishes "Agent Teams is now GA" **or** `claude-code` binary no longer requires `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1` (detected by nightly CI in [P-13](#).
|
||||||
|
|
||||||
|
**Probability (subjective):** High — this is the path the three blog posts above telegraph.
|
||||||
|
|
||||||
|
| Checkpoint | Action | Artifact |
|
||||||
|
|------------|--------|----------|
|
||||||
|
| **T+24h** | Open branch `feat/drop-experimental-flag`. Remove `export` line from every README / docs / Quickstart. Add `claude-code >= X.Y.Z` lower bound in `plugin.json`. | Branch + PR (draft) |
|
||||||
|
| **T+48h** | Publish `docs/migrating-from-experimental.md`. Update `docs/experimental-dependency.md` (this file) headline to "no flag required as of vX.Y". Pin GitHub issue: "Action required: drop the export line". | Migration guide + pinned issue |
|
||||||
|
| **T+72h** | Ship **v1.3.0** release with: (a) CHANGELOG entry, (b) `gh release create` with migration note, (c) HN follow-up: "We dropped the experimental flag". | `v1.3.0` git tag + GH Release |
|
||||||
|
|
||||||
|
**Adopter impact:** Positive. Enterprise approval friction drops — one checkbox ("no experimental flags") becomes satisfiable. No breaking change to harness user code.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Scenario B — Managed Agents reaches GA (parallel path)
|
||||||
|
|
||||||
|
**Trigger detection:** Anthropic publishes "[Managed Agents](https://www.anthropic.com/engineering/managed-agents) is generally available" with a stable `claude-agents` CLI or SDK surface.
|
||||||
|
|
||||||
|
**Probability (subjective):** Medium-high within 90 days. Managed Agents is a server-side execution model; harness's client-side team orchestration does **not** automatically translate.
|
||||||
|
|
||||||
|
| Checkpoint | Action | Artifact |
|
||||||
|
|------------|--------|----------|
|
||||||
|
| **T+24h** | Open `feat/managed-agents-compat` PR. Add `adapters/managed-agents/` scaffold that maps harness's 6 team patterns to Managed Agents invocation. Identify incompatible patterns (likely: Hierarchical Delegation). | Compat PR (draft) |
|
||||||
|
| **T+48h** | Publish blog post: **"Harness + Managed Agents: one layer up, not replaced"** on Dev.to and in the repo. Re-frame harness as the **design-time** layer that outputs Managed Agents configs, not a runtime competitor. | Coexistence framing blog |
|
||||||
|
| **T+72h** | Publish `docs/managed-agents-migration.md` with a per-pattern matrix (which of the 6 patterns map 1:1, which need rewrite). Update README sibling-repo section. | Migration guide |
|
||||||
|
|
||||||
|
**Strategic note:** harness re-positions as the **upper layer on top of Managed Agents** — "Managed Agents runs the team, harness designs it." This is the coexistence frame in §4.2 of the GTM plan.
|
||||||
|
|
||||||
|
**Adopter impact:** Neutral to positive. Existing harness users keep working on the Experimental flag path; new users can opt into Managed Agents output.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Scenario C — Breaking change (API signature mutation)
|
||||||
|
|
||||||
|
**Trigger detection:** Nightly CI (`.github/workflows/nightly-compat.yml`, tracked as roadmap P-13) fails against Claude Code's latest nightly build **or** the Changelog announces a renamed env var / changed `TeamCreate` signature.
|
||||||
|
|
||||||
|
**Probability (subjective):** Medium. Experimental APIs are renamed without deprecation windows.
|
||||||
|
|
||||||
|
| Checkpoint | Action | Artifact |
|
||||||
|
|------------|--------|----------|
|
||||||
|
| **T+0 to T+24h** | Nightly CI alert fires in Slack/Discord. Author opens `hotfix/compat-<date>` branch, patches affected call sites. Unit tests green on both old + new signature (best effort). | Hotfix branch |
|
||||||
|
| **T+24h** | Merge hotfix. Push `v1.2.x` patch tag. Update `docs/compatibility-matrix.md` row for affected Claude Code version. | `v1.2.x` patch release |
|
||||||
|
| **T+72h** | If the change is non-trivial (affects harness's public contract), publish a short notice on the repo Discussions tab + X. Otherwise, CHANGELOG entry is sufficient. | Discussions post (conditional) |
|
||||||
|
|
||||||
|
**Adopter impact:** Existing pinned users on the prior Claude Code version are unaffected. Users on latest get a same-week patch.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Monitoring Commitment
|
||||||
|
|
||||||
|
We commit to the following **observable SLA**. Missing it is grounds for filing an issue with the `sla-breach` label.
|
||||||
|
|
||||||
|
| Event | SLA | Measurement |
|
||||||
|
|-------|-----|-------------|
|
||||||
|
| Anthropic publishes Agent Teams / Managed Agents change in official Changelog | This document updated within **72 hours** | Compare Changelog post timestamp to this file's `Last updated` line |
|
||||||
|
| Nightly CI detects compat break | Hotfix branch open within **24 hours** | GitHub Actions run timestamp vs. branch creation timestamp |
|
||||||
|
| New Claude Code stable release (minor or major) | `docs/compatibility-matrix.md` row added within **7 days** | Compatibility matrix diff |
|
||||||
|
|
||||||
|
**Sources we actively monitor:**
|
||||||
|
|
||||||
|
- Claude Code release notes — watched via the [Anthropic Engineering blog](https://www.anthropic.com/engineering) RSS
|
||||||
|
- `anthropics/claude-code` GitHub Releases (nightly tag)
|
||||||
|
- Anthropic Discord `#claude-code` channel (community signal)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## FAQ for Enterprise Adopters
|
||||||
|
|
||||||
|
### Q1. We're in a regulated industry (finance, healthcare, public sector) and can't enable `EXPERIMENTAL` flags in production. How do we adopt harness?
|
||||||
|
|
||||||
|
**Cause:** Many compliance frameworks (SOC 2 Type II, ISO 27001, K-ISMS) disallow unstable / preview features in production.
|
||||||
|
**Action:** Use harness **design-time only**: run it in a sandbox workstation to scaffold `.claude/agents/` and `.claude/skills/` files, then commit the generated artifacts into your production repo. Production Claude Code never needs the flag — only the flag-gated `TeamCreate` runtime does. The generated single-agent skills are GA-path compatible.
|
||||||
|
|
||||||
|
### Q2. If Agent Teams goes GA (Scenario A), will my existing harness-generated code break?
|
||||||
|
|
||||||
|
**Cause:** GA promotion in Anthropic's Claude Code has historically been non-breaking for generated artifacts; the flag simply stops being required.
|
||||||
|
**Action:** No action required for end users. Your `.claude/agents/*.md` and `.claude/skills/*` files are plain Markdown and remain valid. You will be able to `unset CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS` on the day of GA. We will publish a migration note within 48 hours (see Scenario A).
|
||||||
|
|
||||||
|
### Q3. Do you guarantee an SLA in writing? What happens if you miss it?
|
||||||
|
|
||||||
|
**Cause:** Enterprises need a contractual or at-minimum observable commitment before approval.
|
||||||
|
**Action:** The SLA table above is the **public commitment** and is enforced by: (a) a GitHub Action that comments on this file if its `Last updated` line is older than 72 hours after a detected Changelog event, (b) an `sla-breach` issue label adopters may apply, (c) a post-mortem obligation in `CONTRIBUTING.md` for any breach. This is not a paid SLA — it is a community commitment. For a paid SLA, contact the maintainer (see repository README).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Related documents:**
|
||||||
|
- [`docs/quickstart.md`](./quickstart.md) — 5-minute install walkthrough
|
||||||
|
- [`docs/show-hn-launch-kit.md`](./show-hn-launch-kit.md) — Public launch package
|
||||||
|
- `docs/compatibility-matrix.md` *(pending P-13)* — Claude Code × harness version table
|
||||||
117
docs/quickstart.md
Normal file
117
docs/quickstart.md
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
# Quickstart — 5 Minutes to Your First Harness
|
||||||
|
|
||||||
|
> **Time budget: 5 minutes (strict).** If you are not at Step 5 within 5 minutes, stop and file an issue — that is a bug in this document, not a bug in you.
|
||||||
|
|
||||||
|
<!-- TODO: Loom embed — 60s screen recording showing Steps 1→5 end-to-end. Replace this comment with the `<iframe>` once recorded. -->
|
||||||
|
|
||||||
|
**What you will have at the end:** a working `.claude/agents/` directory with 3–5 domain-specialized agents, generated from a single-sentence prompt, ready to run on a sample task.
|
||||||
|
|
||||||
|
**Prerequisites (check before starting):**
|
||||||
|
- Claude Code **v2.x or later** (`claude --version` should return `2.x` or higher)
|
||||||
|
- A shell that persists `export` across commands (bash, zsh, or fish)
|
||||||
|
- Network access to `github.com` and `api.anthropic.com`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 1 — Add the marketplace (60 seconds)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
claude plugin marketplace add revfactory/harness
|
||||||
|
```
|
||||||
|
|
||||||
|
**What this does:** Registers the `harness` marketplace so Claude Code can discover plugins published by `revfactory`.
|
||||||
|
|
||||||
|
**Expected output:** `Added marketplace: revfactory/harness`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 2 — Install the plugin and enable the Experimental flag (40 seconds)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
claude plugin install harness@harness
|
||||||
|
export CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1
|
||||||
|
```
|
||||||
|
|
||||||
|
*(To persist the flag across shell sessions, append the `export` line to `~/.zshrc` or `~/.bashrc`.)*
|
||||||
|
|
||||||
|
**What this does:** Installs the `harness` plugin from the `harness` marketplace, then enables Agent Teams — the Claude Code API harness uses to orchestrate multi-agent workflows. See [`docs/experimental-dependency.md`](./experimental-dependency.md) for why the flag is required.
|
||||||
|
|
||||||
|
**Failure FAQ #1 — `AGENT_TEAMS not found` / teams don't instantiate**
|
||||||
|
**Cause:** Claude Code version is older than v2.x (Agent Teams was introduced in v2.0).
|
||||||
|
**Fix:** Run `claude --version`. If below 2.0, upgrade via `npm i -g @anthropic-ai/claude-code` (or your distribution's installer), then repeat Step 2.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 3 — Generate a harness from one sentence (2 minutes)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
claude "build a harness for a fintech risk-assessment team"
|
||||||
|
```
|
||||||
|
|
||||||
|
**What this does:** Invokes the `/harness:harness` meta-skill, which analyzes your domain sentence and scaffolds a team of specialized agents + their skills into `.claude/agents/` and `.claude/skills/` in the current directory.
|
||||||
|
|
||||||
|
**Try these alternate prompts** — any of them work:
|
||||||
|
- `claude "하네스 구성해줘 — 핀테크 리스크 평가 팀"` (Korean also works)
|
||||||
|
- `claude "build a harness for an e-commerce fraud-detection workflow"`
|
||||||
|
- `claude "design an agent team for technical due diligence on open-source repos"`
|
||||||
|
|
||||||
|
**Expected output:** A streaming plan, then confirmation that 3–5 agent `.md` files and their skills were written.
|
||||||
|
|
||||||
|
**Failure FAQ #2 — The Korean prompt returns nothing / the English one succeeds but Korean doesn't**
|
||||||
|
**Cause:** Locale or tokenizer misrouting; harness's orchestrator matches on Korean trigger words ("하네스 구성"), which are built into the skill definition.
|
||||||
|
**Fix:** If Korean fails, re-run with the English prompt above — the underlying skill is identical. If both fail, jump to Failure FAQ #3.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 4 — Verify the generated files (30 seconds)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ls -la .claude/agents/
|
||||||
|
ls -la .claude/skills/
|
||||||
|
```
|
||||||
|
|
||||||
|
**What this does:** Confirms the meta-skill wrote files to the expected locations.
|
||||||
|
|
||||||
|
**Expected output:** 3–5 files per directory, with names reflecting your domain (e.g., `risk-analyst.md`, `compliance-reviewer.md`, `portfolio-monitor.md` for the fintech example).
|
||||||
|
|
||||||
|
**Failure FAQ #3 — "Nothing was generated" / directories are empty**
|
||||||
|
**Cause:** The plugin is not actually installed or is not active in the current project.
|
||||||
|
**Fix:** Run `claude plugin list`. If `harness@harness` is absent, repeat Step 2. If present but inactive, run `claude plugin enable harness@harness`, then repeat Step 3.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 5 — Run a sample task against the new team (90 seconds)
|
||||||
|
|
||||||
|
Copy a realistic Jira-ticket-style prompt and hand it to your fresh team:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
claude "Ticket FIN-427: A new corporate customer (mid-cap manufacturer, \$80M revenue, South Korea) has applied for a \$5M working-capital line. Produce a risk assessment covering (1) credit-history red flags, (2) sector concentration vs. our existing book, (3) regulatory exposure (KFTC, FSC). Output: a 1-page memo with a go/no-go recommendation."
|
||||||
|
```
|
||||||
|
|
||||||
|
**What this does:** Claude Code detects the new agents in `.claude/agents/`, routes the task through the team patterns harness generated (typically Producer-Reviewer or Expert-Pool for risk work), and returns a structured memo.
|
||||||
|
|
||||||
|
**Failure FAQ #4 — "The team doesn't execute / only one agent responds"**
|
||||||
|
**Cause:** `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1` was set in the shell that ran Step 3 but not in the shell running Step 5 (happens when opening a new terminal).
|
||||||
|
**Fix:** Re-export in the current shell: `export CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1`, then re-run Step 5. To make permanent, add the line to your shell rc file.
|
||||||
|
|
||||||
|
**Failure FAQ #5 — "Too many API calls / cost anxiety"**
|
||||||
|
**Cause:** Multi-agent teams can fan out to 5+ parallel Claude calls per task. A single complex ticket can consume 50K–200K tokens.
|
||||||
|
**Fix:** Limit to a single task per run (don't chain `&&` multiple harness invocations), and use the `--max-turns` flag if your Claude Code version supports it. For production, gate harness invocations behind a cost-aware wrapper — see `docs/cost-controls.md` *(forthcoming)*.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## You're done
|
||||||
|
|
||||||
|
At this point you should have:
|
||||||
|
|
||||||
|
- [x] A `.claude/agents/` directory with domain-specialized agents
|
||||||
|
- [x] A `.claude/skills/` directory with their supporting skills
|
||||||
|
- [x] One successful sample-task execution
|
||||||
|
- [x] A working `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1` environment
|
||||||
|
|
||||||
|
**Next reads:**
|
||||||
|
- [`docs/experimental-dependency.md`](./experimental-dependency.md) — Why the flag, and what we'll do when it changes
|
||||||
|
- [`revfactory/harness-100`](https://github.com/revfactory/harness-100) — Catalog of 100+ pre-built domain harnesses, if you'd rather clone than generate
|
||||||
|
- [`revfactory/claude-code-harness`](https://github.com/revfactory/claude-code-harness) — The A/B test harness we used to measure +60% quality on 15 tasks
|
||||||
|
|
||||||
|
**If you hit something this guide didn't cover:** open an issue with the `quickstart-gap` label and include: (a) which step failed, (b) `claude --version`, (c) the exact error message. The SLA for quickstart-gap issues is **48 hours** to first response (see `CONTRIBUTING.md`).
|
||||||
BIN
harness_banner.png
Normal file
BIN
harness_banner.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.8 MiB |
BIN
harness_icon.png
Normal file
BIN
harness_icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.3 MiB |
BIN
harness_social.png
Normal file
BIN
harness_social.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.4 MiB |
BIN
harness_team.png
Normal file
BIN
harness_team.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.6 MiB |
1418
index.html
Normal file
1418
index.html
Normal file
File diff suppressed because it is too large
Load Diff
90
privacy.html
Normal file
90
privacy.html
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Privacy Policy — Harness</title>
|
||||||
|
<style>
|
||||||
|
*,*::before,*::after{margin:0;padding:0;box-sizing:border-box}
|
||||||
|
:root{--bg:#0a0a0f;--surface:#12121a;--border:#2a2a3a;--text:#e4e4ef;--text-dim:#8888a0;--accent:#7c6bf0;--accent2:#a78bfa;--radius:16px}
|
||||||
|
html{font-size:16px}
|
||||||
|
body{font-family:'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;background:var(--bg);color:var(--text);line-height:1.8}
|
||||||
|
a{color:var(--accent2);text-decoration:none}
|
||||||
|
a:hover{color:#c4b5fd}
|
||||||
|
.container{max-width:760px;margin:0 auto;padding:4rem 2rem}
|
||||||
|
h1{font-size:2rem;font-weight:700;letter-spacing:-.02em;margin-bottom:.5rem}
|
||||||
|
h2{font-size:1.3rem;font-weight:700;margin-top:2.5rem;margin-bottom:.8rem}
|
||||||
|
p,li{color:var(--text-dim);margin-bottom:.8rem}
|
||||||
|
ul{padding-left:1.5rem}
|
||||||
|
li{margin-bottom:.4rem}
|
||||||
|
.meta{font-size:.85rem;color:var(--text-dim);margin-bottom:3rem}
|
||||||
|
.back{display:inline-flex;align-items:center;gap:.4rem;font-size:.9rem;margin-bottom:2rem;color:var(--text-dim)}
|
||||||
|
.back:hover{color:var(--accent2)}
|
||||||
|
.card{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:1.5rem;margin:1.5rem 0}
|
||||||
|
.card h3{font-size:1rem;margin-bottom:.5rem;color:var(--text)}
|
||||||
|
footer{border-top:1px solid var(--border);margin-top:4rem;padding-top:2rem;text-align:center;font-size:.85rem;color:var(--text-dim)}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
|
||||||
|
<a href="index.html" class="back">← Back to Harness</a>
|
||||||
|
|
||||||
|
<h1>Privacy Policy</h1>
|
||||||
|
<p class="meta">Last updated: March 27, 2026</p>
|
||||||
|
|
||||||
|
<p>Harness ("the Plugin") is an open-source Claude Code plugin distributed under the Apache 2.0 license. This Privacy Policy explains how Harness handles user data.</p>
|
||||||
|
|
||||||
|
<div class="card">
|
||||||
|
<h3>The short version</h3>
|
||||||
|
<p style="margin-bottom:0">Harness does <strong>not</strong> collect, store, transmit, or share any personal data. It runs entirely within your local Claude Code environment.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2>1. Data Collection</h2>
|
||||||
|
<p>Harness does not collect any personal information. Specifically:</p>
|
||||||
|
<ul>
|
||||||
|
<li>No user accounts or registration required</li>
|
||||||
|
<li>No analytics, telemetry, or tracking of any kind</li>
|
||||||
|
<li>No cookies or local storage for tracking purposes</li>
|
||||||
|
<li>No network requests to external servers</li>
|
||||||
|
<li>No collection of IP addresses, device identifiers, or usage patterns</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2>2. How the Plugin Works</h2>
|
||||||
|
<p>Harness operates exclusively within the Claude Code runtime environment:</p>
|
||||||
|
<ul>
|
||||||
|
<li>It reads your project files to analyze the domain and codebase</li>
|
||||||
|
<li>It generates Markdown files (<code>.claude/agents/</code> and <code>.claude/skills/</code>) written to your local project directory</li>
|
||||||
|
<li>All processing happens locally through Claude Code's built-in tools</li>
|
||||||
|
<li>No data leaves your machine through the plugin itself</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2>3. Third-Party Services</h2>
|
||||||
|
<p>Harness does not integrate with or send data to any third-party services. However, please note:</p>
|
||||||
|
<ul>
|
||||||
|
<li>Harness runs within <strong>Claude Code</strong>, which is operated by Anthropic. Your interactions with Claude Code are subject to <a href="https://www.anthropic.com/privacy" target="_blank">Anthropic's Privacy Policy</a>.</li>
|
||||||
|
<li>If you install Harness via a GitHub marketplace, your interaction with GitHub is subject to <a href="https://docs.github.com/en/site-policy/privacy-policies/github-general-privacy-statement" target="_blank">GitHub's Privacy Statement</a>.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2>4. Generated Files</h2>
|
||||||
|
<p>Files generated by Harness (agent definitions, skills, orchestrator configurations) are stored locally in your project directory. You have full control over these files — they can be modified, deleted, or version-controlled as you see fit.</p>
|
||||||
|
|
||||||
|
<h2>5. Open Source Transparency</h2>
|
||||||
|
<p>Harness is fully open source. You can audit the complete source code at <a href="https://github.com/revfactory/harness" target="_blank">github.com/revfactory/harness</a> to verify these privacy claims.</p>
|
||||||
|
|
||||||
|
<h2>6. Children's Privacy</h2>
|
||||||
|
<p>Harness does not knowingly collect any data from anyone, including children under 13. Since no data is collected at all, there is no age-specific concern.</p>
|
||||||
|
|
||||||
|
<h2>7. Changes to This Policy</h2>
|
||||||
|
<p>If this privacy policy changes, the updated version will be published in the GitHub repository and on this page. The "Last updated" date at the top will reflect the most recent revision.</p>
|
||||||
|
|
||||||
|
<h2>8. Contact</h2>
|
||||||
|
<p>For questions about this privacy policy or the Harness plugin, please open an issue at <a href="https://github.com/revfactory/harness/issues" target="_blank">github.com/revfactory/harness/issues</a> or contact the maintainer via <a href="https://github.com/revfactory" target="_blank">GitHub</a>.</p>
|
||||||
|
|
||||||
|
<footer>
|
||||||
|
<p>Harness — Apache 2.0 — <a href="https://github.com/revfactory" target="_blank">revfactory</a></p>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
457
skills/harness/SKILL.md
Normal file
457
skills/harness/SKILL.md
Normal file
@ -0,0 +1,457 @@
|
|||||||
|
---
|
||||||
|
name: harness
|
||||||
|
description: "하네스를 구성합니다. 전문 에이전트를 정의하며, 해당 에이전트가 사용할 스킬을 생성하는 메타 스킬. (1) '하네스 구성해줘', '하네스 구축해줘' 요청 시, (2) '하네스 설계', '하네스 엔지니어링' 요청 시, (3) 새로운 도메인/프로젝트에 대한 하네스 기반 자동화 체계를 구축할 때, (4) 하네스 구성을 재구성하거나 확장할 때, (5) '하네스 점검', '하네스 감사', '하네스 현황', '에이전트/스킬 동기화' 등 기존 하네스 운영/유지보수 요청 시 사용."
|
||||||
|
---
|
||||||
|
|
||||||
|
# Harness — Agent Team & Skill Architect
|
||||||
|
|
||||||
|
도메인/프로젝트에 맞는 하네스를 구성하고, 각 에이전트의 역할을 정의하며, 에이전트가 사용할 스킬을 생성하는 메타 스킬.
|
||||||
|
|
||||||
|
**핵심 원칙:**
|
||||||
|
1. 에이전트 정의(`.claude/agents/`)와 스킬(`.claude/skills/`)을 생성한다.
|
||||||
|
2. **에이전트 팀을 기본 실행 모드로 사용한다.**
|
||||||
|
3. **CLAUDE.md에 하네스 포인터를 등록한다.** — 새 세션에서 오케스트레이터 스킬이 트리거되도록 최소한의 포인터(트리거 규칙 + 변경 이력)만 기록한다.
|
||||||
|
4. **하네스는 고정물이 아니라 진화하는 시스템이다.** — 매 실행 후 피드백을 반영하고, 에이전트·스킬·CLAUDE.md를 지속 갱신한다.
|
||||||
|
|
||||||
|
## 워크플로우
|
||||||
|
|
||||||
|
### Phase 0: 현황 감사
|
||||||
|
|
||||||
|
하네스 스킬이 트리거되면 가장 먼저 기존 하네스 현황을 확인한다.
|
||||||
|
|
||||||
|
1. `프로젝트/.claude/agents/`, `프로젝트/.claude/skills/`, `프로젝트/CLAUDE.md`를 읽는다
|
||||||
|
2. 현황에 따라 실행 모드를 분기한다:
|
||||||
|
- **신규 구축**: 에이전트/스킬 디렉토리가 없거나 비어있음 → Phase 1부터 전체 실행
|
||||||
|
- **기존 확장**: 기존 하네스가 있고 새 에이전트/스킬 추가 요청 → 아래 Phase 선택 매트릭스에 따라 필요한 Phase만 실행
|
||||||
|
- **운영/유지보수**: 기존 하네스의 감사·수정·동기화 요청 → Phase 7-5 운영/유지보수 워크플로우로 이동
|
||||||
|
|
||||||
|
**기존 확장 시 Phase 선택 매트릭스:**
|
||||||
|
| 변경 유형 | Phase 1 | Phase 2 | Phase 3 | Phase 4 | Phase 5 | Phase 6 |
|
||||||
|
|----------|---------|---------|---------|---------|---------|---------|
|
||||||
|
| 에이전트 추가 | 건너뜀 (Phase 0 결과 활용) | 배치 결정만 | 필수 (3-0 포함) | 전용 스킬 필요 시 (4-0 포함) | 오케스트레이터 수정 | 필수 |
|
||||||
|
| 스킬 추가/수정 | 건너뜀 | 건너뜀 | 건너뜀 | 필수 (4-0 포함) | 연결 변경 시 | 필수 |
|
||||||
|
| 아키텍처 변경 | 건너뜀 | 필수 | 영향받는 에이전트만 (3-0 포함) | 영향받는 스킬만 (4-0 포함) | 필수 | 필수 |
|
||||||
|
3. 기존 에이전트/스킬 목록과 CLAUDE.md 기록을 대조하여 불일치(drift)를 감지한다
|
||||||
|
4. 감사 결과를 사용자에게 요약 보고하고, 실행 계획을 확인받는다
|
||||||
|
|
||||||
|
### Phase 1: 도메인 분석
|
||||||
|
1. 사용자 요청에서 도메인/프로젝트 파악
|
||||||
|
2. 핵심 작업 유형 식별 (생성, 검증, 편집, 분석 등)
|
||||||
|
3. Phase 0 감사 결과를 기반으로 기존 에이전트/스킬과의 충돌/중복 분석
|
||||||
|
4. 프로젝트 코드베이스 탐색 — 기술 스택, 데이터 모델, 주요 모듈 파악
|
||||||
|
5. **사용자 숙련도 감지** — 대화의 맥락 단서(사용 용어, 질문 수준)로 기술 수준을 파악하고, 이후 커뮤니케이션 톤을 조절한다. 코딩 경험이 적은 사용자에게는 "assertion", "JSON schema" 같은 용어를 설명 없이 쓰지 않는다.
|
||||||
|
|
||||||
|
### Phase 2: 팀 아키텍처 설계
|
||||||
|
|
||||||
|
#### 2-1. 실행 모드 선택
|
||||||
|
|
||||||
|
**에이전트 팀이 최우선 기본값이다.** 2개 이상의 에이전트가 협업할 때는 반드시 에이전트 팀을 먼저 검토한다. 팀원 간 직접 통신(SendMessage)과 공유 작업 목록(TaskCreate)으로 자체 조율하며, 발견 공유·상충 토론·누락 보완이 결과 품질을 높인다.
|
||||||
|
|
||||||
|
| 모드 | 언제 사용 | 특성 |
|
||||||
|
|------|----------|------|
|
||||||
|
| **에이전트 팀** (기본) | 2명 이상 협업, 실시간 조율·피드백 교환이 필요, 중간 산출물 상호 참조 | `TeamCreate` + `SendMessage` + `TaskCreate`로 자체 조율 |
|
||||||
|
| **서브 에이전트** (대안) | 단일 에이전트 작업, 결과만 메인에 반환하면 충분, 팀 통신 오버헤드가 과할 때 | `Agent` 도구 직접 호출, `run_in_background`로 병렬 |
|
||||||
|
| **하이브리드** | Phase마다 특성이 다를 때 — 예: 병렬 수집(서브) → 합의 기반 통합(팀) | Phase 단위로 팀/서브를 섞어 구성 |
|
||||||
|
|
||||||
|
**의사결정 순서:**
|
||||||
|
1. 먼저 에이전트 팀으로 설계 가능한지 검토한다 — 2명 이상이면 기본값
|
||||||
|
2. 팀 통신이 구조적으로 불필요하고(결과 전달만), 팀 오버헤드가 이득보다 클 때만 서브 에이전트 선택
|
||||||
|
3. Phase별 특성이 확연히 다르면 하이브리드 고려 — 각 Phase의 실행 모드를 오케스트레이터에 명시
|
||||||
|
|
||||||
|
> 상세 비교표와 패턴별 의사결정 트리는 `references/agent-design-patterns.md`의 "실행 모드" 참조.
|
||||||
|
|
||||||
|
#### 2-2. 아키텍처 패턴 선택
|
||||||
|
|
||||||
|
1. 작업을 전문 영역으로 분해
|
||||||
|
2. 에이전트 팀 구조 결정 (아키텍처 패턴은 `references/agent-design-patterns.md` 참조)
|
||||||
|
- **파이프라인**: 순차 의존 작업
|
||||||
|
- **팬아웃/팬인**: 병렬 독립 작업
|
||||||
|
- **전문가 풀**: 상황별 선택 호출
|
||||||
|
- **생성-검증**: 생성 후 품질 검수
|
||||||
|
- **감독자**: 중앙 에이전트가 상태 관리 및 동적 분배
|
||||||
|
- **계층적 위임**: 상위 에이전트가 하위에 재귀적 위임
|
||||||
|
|
||||||
|
#### 2-3. 에이전트 분리 기준
|
||||||
|
|
||||||
|
전문성·병렬성·컨텍스트·재사용성 4축으로 판단한다. 상세 기준표는 `references/agent-design-patterns.md`의 "에이전트 분리 기준" 참조. 기존 에이전트와의 중복·재사용 검토는 Phase 3-0에서 다룬다.
|
||||||
|
|
||||||
|
### Phase 3: 에이전트 정의 생성
|
||||||
|
|
||||||
|
#### 3-0. 기존 에이전트 중복 검토
|
||||||
|
|
||||||
|
신규 에이전트 생성 전, `프로젝트/.claude/agents/`의 기존 에이전트와 중복 여부를 확인한다. 하네스를 반복 구축하다 보면 역할이 겹치는 에이전트가 다른 이름으로 누적되기 쉽다.
|
||||||
|
|
||||||
|
> 중복 분류 기준과 재사용 설계는 `references/agent-design-patterns.md`의 "에이전트 재사용 설계" 참조.
|
||||||
|
|
||||||
|
**모든 에이전트는 반드시 `프로젝트/.claude/agents/{name}.md` 파일로 정의한다.** 에이전트 정의 파일 없이 Agent 도구의 prompt에 역할을 직접 넣는 것은 금지한다. 이유:
|
||||||
|
- 에이전트 정의가 파일로 존재해야 다음 세션에서 재사용 가능
|
||||||
|
- 팀 통신 프로토콜이 명시되어야 에이전트 간 협업 품질 보장
|
||||||
|
- 하네스의 핵심 가치는 에이전트(누가)와 스킬(어떻게)의 분리
|
||||||
|
|
||||||
|
빌트인 타입(`general-purpose`, `Explore`, `Plan`)을 사용하더라도 에이전트 정의 파일은 생성한다. 빌트인 타입은 Agent 도구의 `subagent_type` 파라미터로 지정하고, 에이전트 정의 파일에는 역할·원칙·프로토콜을 담는다.
|
||||||
|
|
||||||
|
**모델 설정:** 모든 에이전트는 `model: "opus"`를 사용한다. Agent 도구 호출 시 반드시 `model: "opus"` 파라미터를 명시한다. 하네스의 품질은 에이전트의 추론 능력에 직결되며, opus가 최고 품질을 보장한다.
|
||||||
|
|
||||||
|
**팀 재구성:** 에이전트 팀은 세션당 한 팀만 활성화할 수 있지만, Phase 간에 팀을 해체하고 새 팀을 구성할 수 있다. 파이프라인 패턴처럼 Phase별로 다른 전문가 조합이 필요하면, 이전 팀의 산출물을 파일로 저장한 뒤 팀을 정리하고 새 팀을 생성한다.
|
||||||
|
|
||||||
|
각 에이전트를 `프로젝트/.claude/agents/{name}.md`에 정의한다. 필수 섹션: 핵심 역할, 작업 원칙, 입력/출력 프로토콜, 에러 핸들링, 협업. 에이전트 팀 모드에서는 `## 팀 통신 프로토콜` 섹션을 추가하여 메시지 수신/발신 대상과 작업 요청 범위를 명시한다.
|
||||||
|
|
||||||
|
> 정의 템플릿과 실제 파일 전문은 `references/agent-design-patterns.md`의 "에이전트 정의 구조" + `references/team-examples.md` 참조.
|
||||||
|
|
||||||
|
**QA 에이전트 포함 시 필수 사항:**
|
||||||
|
- QA 에이전트는 `general-purpose` 타입을 사용하라 (`Explore`는 읽기 전용이므로 검증 스크립트 실행 불가)
|
||||||
|
- QA의 핵심은 "존재 확인"이 아니라 **"경계면 교차 비교"** — API 응답과 프론트 훅을 동시에 읽고 shape을 비교
|
||||||
|
- QA는 전체 완성 후 1회가 아니라, **각 모듈 완성 직후 점진적으로 실행** (incremental QA)
|
||||||
|
- 상세 가이드: `references/qa-agent-guide.md` 참조
|
||||||
|
|
||||||
|
### Phase 4: 스킬 생성
|
||||||
|
|
||||||
|
각 에이전트가 사용할 스킬을 `프로젝트/.claude/skills/{name}/SKILL.md`에 생성한다. 상세 작성 가이드는 `references/skill-writing-guide.md` 참조.
|
||||||
|
|
||||||
|
#### 4-0. 기존 스킬 중복 검토
|
||||||
|
|
||||||
|
신규 스킬 생성 전, `프로젝트/.claude/skills/`의 기존 스킬과 중복 여부를 확인한다. 하네스를 반복 구축하다 보면 기능이 겹치는 스킬이 다른 이름으로 누적되기 쉽다.
|
||||||
|
|
||||||
|
> 중복 분류 기준과 일반화 패턴은 `references/skill-writing-guide.md`의 "스킬 재사용 설계" 참조.
|
||||||
|
|
||||||
|
#### 4-1. 스킬 구조
|
||||||
|
|
||||||
|
```
|
||||||
|
skill-name/
|
||||||
|
├── SKILL.md (필수)
|
||||||
|
│ ├── YAML frontmatter (name, description 필수)
|
||||||
|
│ └── Markdown 본문
|
||||||
|
└── Bundled Resources (선택)
|
||||||
|
├── scripts/ - 반복/결정적 작업용 실행 코드
|
||||||
|
├── references/ - 조건부 로딩하는 참조 문서
|
||||||
|
└── assets/ - 출력에 사용되는 파일 (템플릿, 이미지 등)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 4-2. Description 작성 — 적극적 트리거 유도
|
||||||
|
|
||||||
|
description은 스킬의 유일한 트리거 메커니즘이다. Claude는 트리거를 보수적으로 판단하는 경향이 있으므로, description을 **적극적("pushy")**으로 작성한다.
|
||||||
|
|
||||||
|
**나쁜 예:** `"PDF 문서를 처리하는 스킬"`
|
||||||
|
**좋은 예:** `"PDF 파일 읽기, 텍스트/테이블 추출, 병합, 분할, 회전, 워터마크, 암호화, OCR 등 모든 PDF 작업을 수행. .pdf 파일을 언급하거나 PDF 산출물을 요청하면 반드시 이 스킬을 사용할 것."`
|
||||||
|
|
||||||
|
핵심: 스킬이 하는 일 + 구체적 트리거 상황을 모두 기술하고, 유사하지만 트리거하면 안 되는 경우와 구분되도록 작성.
|
||||||
|
|
||||||
|
#### 4-3. 본문 작성 원칙
|
||||||
|
|
||||||
|
| 원칙 | 설명 |
|
||||||
|
|------|------|
|
||||||
|
| **Why를 설명하라** | "ALWAYS/NEVER" 같은 강압적 지시 대신, 왜 그렇게 해야 하는지 이유를 전달한다. LLM은 이유를 이해하면 엣지 케이스에서도 올바르게 판단한다. |
|
||||||
|
| **Lean하게 유지** | 컨텍스트 윈도우는 공공재다. SKILL.md 본문은 500줄 이내를 목표로, 무게를 벌지 않는 내용은 삭제하거나 references/로 이동한다. |
|
||||||
|
| **일반화하라** | 특정 예시에만 맞는 좁은 규칙보다, 원리를 설명하여 다양한 입력에 대응할 수 있게 한다. 오버피팅 금지. |
|
||||||
|
| **반복 코드는 번들링** | 테스트 실행에서 에이전트들이 공통으로 작성하는 스크립트가 발견되면 `scripts/`에 미리 번들링한다. |
|
||||||
|
| **명령형으로 작성** | "~한다", "~하라" 형태의 명령형/지시형 어조를 사용한다. |
|
||||||
|
|
||||||
|
#### 4-4. Progressive Disclosure (단계적 정보 공개)
|
||||||
|
|
||||||
|
스킬은 3단계 로딩 시스템으로 컨텍스트를 관리한다:
|
||||||
|
|
||||||
|
| 단계 | 로딩 시점 | 크기 목표 |
|
||||||
|
|------|----------|----------|
|
||||||
|
| **Metadata** (name + description) | 항상 컨텍스트에 존재 | ~100단어 |
|
||||||
|
| **SKILL.md 본문** | 스킬 트리거 시 | <500줄 |
|
||||||
|
| **references/** | 필요할 때만 | 무제한 (스크립트는 로딩 없이 실행 가능) |
|
||||||
|
|
||||||
|
**크기 관리 규칙:**
|
||||||
|
- SKILL.md가 500줄에 근접하면 세부 내용을 references/로 분리하고, 본문에 "언제 이 파일을 읽으라"는 포인터를 남긴다
|
||||||
|
- 300줄 이상의 reference 파일에는 상단에 **목차(ToC)**를 포함한다
|
||||||
|
- 도메인/프레임워크별 변형이 있으면 references/ 하위에 도메인별로 분리하여, 관련 파일만 로드한다
|
||||||
|
|
||||||
|
```
|
||||||
|
cloud-deploy/
|
||||||
|
├── SKILL.md (워크플로우 + 선택 가이드)
|
||||||
|
└── references/
|
||||||
|
├── aws.md ← AWS 선택 시만 로드
|
||||||
|
├── gcp.md
|
||||||
|
└── azure.md
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 4-5. 스킬-에이전트 연결 원칙
|
||||||
|
|
||||||
|
- 에이전트 1개 ↔ 스킬 1~N개 (1:1 또는 1:다)
|
||||||
|
- 여러 에이전트가 공유하는 스킬도 가능
|
||||||
|
- 스킬은 "어떻게 하는가"를 담고, 에이전트는 "누가 하는가"를 담는다
|
||||||
|
|
||||||
|
> 상세 작성 패턴, 예시, 데이터 스키마 표준은 `references/skill-writing-guide.md` 참조.
|
||||||
|
|
||||||
|
### Phase 5: 통합 및 오케스트레이션
|
||||||
|
|
||||||
|
오케스트레이터는 스킬의 특수한 형태로, 개별 에이전트와 스킬을 하나의 워크플로우로 엮어 팀 전체를 조율한다. Phase 4에서 생성한 개별 스킬이 "각 에이전트가 무엇을 어떻게 하는가"를 정의한다면, 오케스트레이터는 "누가 언제 어떤 순서로 협업하는가"를 정의한다. 구체적 템플릿은 `references/orchestrator-template.md` 참조.
|
||||||
|
|
||||||
|
**기존 확장 시 오케스트레이터 수정:** 신규 구축이 아닌 기존 확장일 때는 오케스트레이터를 새로 생성하지 않고 기존 오케스트레이터를 수정한다. 에이전트 추가 시 팀 구성·작업 할당·데이터 흐름에 새 에이전트를 반영하고, description에 새 에이전트 관련 트리거 키워드를 추가한다.
|
||||||
|
|
||||||
|
Phase 2-1에서 선택한 실행 모드에 따라 오케스트레이터 패턴이 달라진다:
|
||||||
|
|
||||||
|
#### 5-0. 오케스트레이터 패턴 (모드별)
|
||||||
|
|
||||||
|
**에이전트 팀 패턴 (기본):**
|
||||||
|
오케스트레이터가 `TeamCreate`로 팀을 구성하고, `TaskCreate`로 작업을 할당한다. 팀원들은 `SendMessage`로 직접 통신하며 자체 조율한다. 리더(오케스트레이터)는 진행 상황을 모니터링하고 결과를 종합한다.
|
||||||
|
|
||||||
|
```
|
||||||
|
[오케스트레이터/리더]
|
||||||
|
├── TeamCreate(team_name, members)
|
||||||
|
├── TaskCreate(tasks with dependencies)
|
||||||
|
├── 팀원들이 자체 조율 (SendMessage)
|
||||||
|
├── 결과 수집 및 종합
|
||||||
|
└── 팀 정리
|
||||||
|
```
|
||||||
|
|
||||||
|
**서브 에이전트 패턴 (대안):**
|
||||||
|
오케스트레이터가 `Agent` 도구로 서브 에이전트를 직접 호출한다. 병렬 실행은 `run_in_background: true`, 결과는 메인에게만 반환된다. 팀 통신이 불필요하고 오버헤드를 줄이고 싶을 때 사용.
|
||||||
|
|
||||||
|
```
|
||||||
|
[오케스트레이터]
|
||||||
|
├── Agent(agent-1, run_in_background=true)
|
||||||
|
├── Agent(agent-2, run_in_background=true)
|
||||||
|
├── 결과 대기 및 수집
|
||||||
|
└── 통합 산출물 생성
|
||||||
|
```
|
||||||
|
|
||||||
|
**하이브리드 패턴:**
|
||||||
|
Phase마다 다른 모드를 섞어 구성한다. 자주 쓰이는 조합:
|
||||||
|
- **병렬 수집(서브) → 합의 통합(팀)**: Phase 2에서 서브 에이전트로 독립 자료를 병렬 수집 → Phase 3에서 팀을 만들어 토론·합의 기반 통합
|
||||||
|
- **팀 생성(팀) → 검증(서브)**: Phase 2에서 팀이 초안 생성 → Phase 3에서 단일 서브 에이전트가 독립 검증
|
||||||
|
- **Phase 간 팀 재구성**: 각 Phase마다 `TeamDelete` 후 새 `TeamCreate`, 사이에 서브 에이전트 호출 삽입
|
||||||
|
|
||||||
|
하이브리드 선택 시 오케스트레이터의 각 Phase 섹션 상단에 해당 Phase의 실행 모드를 명시한다 (예: `**실행 모드:** 에이전트 팀`).
|
||||||
|
|
||||||
|
#### 5-1. 데이터 전달 프로토콜
|
||||||
|
|
||||||
|
오케스트레이터 내에 에이전트 간 데이터 전달 방식을 명시한다:
|
||||||
|
|
||||||
|
| 전략 | 방식 | 적용 모드 | 적합한 경우 |
|
||||||
|
|------|------|----------|-----------|
|
||||||
|
| **메시지 기반** | `SendMessage`로 팀원 간 직접 통신 | 팀 | 실시간 조율, 피드백 교환, 가벼운 상태 전달 |
|
||||||
|
| **태스크 기반** | `TaskCreate`/`TaskUpdate`로 작업 상태 공유 | 팀 | 진행상황 추적, 의존 관계 관리, 작업 자체 요청 |
|
||||||
|
| **파일 기반** | 약속된 경로에 파일을 쓰고 읽음 | 팀 + 서브 | 대용량 데이터, 구조화된 산출물, 감사 추적 필요 |
|
||||||
|
| **반환값 기반** | `Agent` 도구의 반환 메시지 | 서브 | 서브 에이전트 결과를 메인이 직접 수집 |
|
||||||
|
|
||||||
|
**권장 조합 (팀 모드):** 태스크 기반(조율) + 파일 기반(산출물) + 메시지 기반(실시간 소통)
|
||||||
|
**권장 조합 (서브 모드):** 반환값 기반(결과 수집) + 파일 기반(대용량 산출물)
|
||||||
|
**하이브리드:** 각 Phase의 실행 모드에 맞춰 해당 조합 적용
|
||||||
|
|
||||||
|
파일 기반 전달 시 규칙:
|
||||||
|
- 작업 디렉토리 하위에 `_workspace/` 폴더를 만들어 중간 산출물 저장
|
||||||
|
- 파일명 컨벤션: `{phase}_{agent}_{artifact}.{ext}` (예: `01_analyst_requirements.md`)
|
||||||
|
- 최종 산출물만 사용자 지정 경로에 출력, 중간 파일(`_workspace/`)은 보존 (사후 검증·감사 추적용)
|
||||||
|
|
||||||
|
#### 5-2. 에러 핸들링
|
||||||
|
|
||||||
|
오케스트레이터 내에 에러 처리 방침을 포함한다. 핵심 원칙: 1회 재시도 후 재실패 시 해당 결과 없이 진행(보고서에 누락 명시), 상충 데이터는 삭제하지 않고 출처 병기.
|
||||||
|
|
||||||
|
> 에러 유형별 전략표와 구현 상세는 `references/orchestrator-template.md`의 "에러 핸들링" 참조.
|
||||||
|
|
||||||
|
#### 5-3. 팀 크기 가이드라인
|
||||||
|
|
||||||
|
| 작업 규모 | 권장 팀원 수 | 팀원당 작업 수 |
|
||||||
|
|----------|------------|--------------|
|
||||||
|
| 소규모 (5~10개 작업) | 2~3명 | 3~5개 |
|
||||||
|
| 중규모 (10~20개 작업) | 3~5명 | 4~6개 |
|
||||||
|
| 대규모 (20개+ 작업) | 5~7명 | 4~5개 |
|
||||||
|
|
||||||
|
> 팀원이 많을수록 조율 오버헤드가 커진다. 3명의 집중된 팀원이 5명의 산만한 팀원보다 낫다.
|
||||||
|
|
||||||
|
#### 5-4. CLAUDE.md 하네스 포인터 등록
|
||||||
|
|
||||||
|
하네스 구성 완료 후, 프로젝트의 `CLAUDE.md`에 최소한의 포인터를 등록한다. CLAUDE.md는 새 세션마다 로딩되므로, 하네스 존재와 트리거 규칙만 기록하면 오케스트레이터 스킬이 나머지를 처리한다.
|
||||||
|
|
||||||
|
**CLAUDE.md 템플릿:**
|
||||||
|
|
||||||
|
````markdown
|
||||||
|
## 하네스: {도메인명}
|
||||||
|
|
||||||
|
**목표:** {하네스의 핵심 목표 한 줄}
|
||||||
|
|
||||||
|
**트리거:** {도메인} 관련 작업 요청 시 `{orchestrator-skill-name}` 스킬을 사용하라. 단순 질문은 직접 응답 가능.
|
||||||
|
|
||||||
|
**변경 이력:**
|
||||||
|
| 날짜 | 변경 내용 | 대상 | 사유 |
|
||||||
|
|------|----------|------|------|
|
||||||
|
| {YYYY-MM-DD} | 초기 구성 | 전체 | - |
|
||||||
|
````
|
||||||
|
|
||||||
|
**CLAUDE.md에 넣지 않는 것:** 에이전트 목록, 스킬 목록, 디렉토리 구조, 실행 규칙 상세. 이유: 에이전트/스킬 목록은 오케스트레이터 스킬과 `.claude/agents/`, `.claude/skills/`에서 관리하므로 중복이다. 디렉토리 구조는 파일 시스템에서 직접 확인 가능하다. CLAUDE.md는 **포인터(트리거 규칙) + 변경 이력**만 담는다.
|
||||||
|
|
||||||
|
#### 5-5. 후속 작업 지원
|
||||||
|
|
||||||
|
오케스트레이터는 초기 실행뿐 아니라 후속 작업도 처리해야 한다. 다음 세 가지를 보장하라:
|
||||||
|
|
||||||
|
**1. 오케스트레이터 description에 후속 키워드 포함:**
|
||||||
|
초기 생성 키워드만으로는 후속 요청이 트리거되지 않는다. description에 반드시 포함할 후속 표현:
|
||||||
|
- "다시 실행", "재실행", "업데이트", "수정", "보완"
|
||||||
|
- "{도메인}의 {부분작업}만 다시"
|
||||||
|
- "이전 결과 기반으로", "결과 개선"
|
||||||
|
|
||||||
|
**2. 오케스트레이터 Phase 1에 컨텍스트 확인 단계 추가:**
|
||||||
|
워크플로우 시작 시 기존 산출물 존재 여부를 확인하여 실행 모드를 결정한다:
|
||||||
|
- `_workspace/` 존재 + 사용자가 부분 수정 요청 → **부분 재실행** (해당 에이전트만 재호출)
|
||||||
|
- `_workspace/` 존재 + 사용자가 새 입력 제공 → **새 실행** (기존 _workspace를 `_workspace_prev/`로 이동)
|
||||||
|
- `_workspace/` 미존재 → **초기 실행**
|
||||||
|
|
||||||
|
**3. 에이전트 정의에 재호출 지침 포함:**
|
||||||
|
각 에이전트 `.md` 파일에 "이전 산출물이 있을 때의 행동"을 명시한다:
|
||||||
|
- 이전 결과 파일이 존재하면 읽고 개선점을 반영
|
||||||
|
- 사용자 피드백이 주어지면 해당 부분만 수정
|
||||||
|
|
||||||
|
> 오케스트레이터 템플릿의 "Phase 0: 컨텍스트 확인" 섹션 참조: `references/orchestrator-template.md`
|
||||||
|
|
||||||
|
### Phase 6: 검증 및 테스트
|
||||||
|
|
||||||
|
생성된 하네스를 검증한다. 상세 테스트 방법론은 `references/skill-testing-guide.md` 참조.
|
||||||
|
|
||||||
|
#### 6-1. 구조 검증
|
||||||
|
|
||||||
|
- 모든 에이전트 파일이 올바른 위치에 있는지 확인
|
||||||
|
- 스킬의 frontmatter(name, description) 검증
|
||||||
|
- 에이전트 간 참조 일관성 확인
|
||||||
|
- 커맨드가 생성되지 않았는지 확인
|
||||||
|
|
||||||
|
#### 6-2. 실행 모드별 검증
|
||||||
|
|
||||||
|
- **에이전트 팀**: 팀원 간 통신 경로, 작업 의존성, 팀 크기 적정성 확인
|
||||||
|
- **서브 에이전트**: 각 에이전트의 입출력 연결, `run_in_background` 설정, 반환값 수집 로직 확인
|
||||||
|
- **하이브리드**: 각 Phase의 실행 모드가 오케스트레이터에 명시되었는지, Phase 경계에서 데이터 전달이 끊기지 않는지 확인 (팀 → 서브 전환 시 팀의 산출물이 서브의 입력으로 연결되는지)
|
||||||
|
|
||||||
|
#### 6-3. 스킬 실행 테스트
|
||||||
|
|
||||||
|
생성된 각 스킬에 대해 실제 실행 테스트를 수행한다:
|
||||||
|
|
||||||
|
1. **테스트 프롬프트 작성** — 각 스킬에 대해 2~3개의 현실적인 테스트 프롬프트를 작성한다. 실제 사용자가 입력할 법한 구체적이고 자연스러운 문장으로 작성한다.
|
||||||
|
|
||||||
|
2. **With-skill vs Without-skill 비교 실행** — 가능하면 스킬 있는 실행과 없는 실행을 병렬로 수행하여 스킬의 부가가치를 확인한다. 에이전트를 두 개씩 스폰한다:
|
||||||
|
- **With-skill**: 스킬을 읽고 작업 수행
|
||||||
|
- **Without-skill (baseline)**: 같은 프롬프트를 스킬 없이 수행
|
||||||
|
|
||||||
|
3. **결과 평가** — 산출물의 품질을 정성적(사용자 리뷰) + 정량적(assertion 기반) 으로 평가한다. 산출물이 객관적으로 검증 가능한 경우(파일 생성, 데이터 추출 등) assertion을 정의하고, 주관적인 경우(문체, 디자인) 사용자 피드백에 의존한다.
|
||||||
|
|
||||||
|
4. **반복 개선 루프** — 테스트 결과에서 문제가 발견되면:
|
||||||
|
- 피드백을 **일반화**하여 스킬을 수정한다 (특정 예시에만 맞는 좁은 수정 금지)
|
||||||
|
- 수정 후 재테스트한다
|
||||||
|
- 사용자가 만족하거나 의미 있는 개선이 더 이상 없을 때까지 반복한다
|
||||||
|
|
||||||
|
5. **반복 패턴 번들링** — 테스트 실행에서 에이전트들이 공통으로 작성하는 코드(예: 모든 테스트에서 동일한 헬퍼 스크립트를 생성)가 발견되면, 해당 코드를 `scripts/`에 미리 번들링한다.
|
||||||
|
|
||||||
|
#### 6-4. 트리거 검증
|
||||||
|
|
||||||
|
각 스킬의 description이 올바르게 트리거되는지 검증한다:
|
||||||
|
|
||||||
|
1. **Should-trigger 쿼리** (8~10개) — 스킬을 트리거해야 하는 다양한 표현 (공식적/캐주얼, 명시적/암시적)
|
||||||
|
2. **Should-NOT-trigger 쿼리** (8~10개) — 키워드가 유사하지만 이 스킬이 아닌 다른 도구/스킬이 적합한 "near-miss" 쿼리
|
||||||
|
|
||||||
|
**near-miss 작성 핵심:** "피보나치 함수 작성" 같이 명백히 무관한 쿼리는 테스트 가치가 없다. "이 엑셀 파일의 차트를 PNG로 추출해줘" (xlsx 스킬 vs 이미지 변환)처럼 **경계가 모호한 쿼리**가 좋은 테스트 케이스다.
|
||||||
|
|
||||||
|
기존 스킬과의 트리거 충돌도 이 단계에서 확인한다.
|
||||||
|
|
||||||
|
#### 6-5. 드라이런 테스트
|
||||||
|
|
||||||
|
- 오케스트레이터 스킬의 Phase 순서가 논리적인지 검토
|
||||||
|
- 데이터 전달 경로에 빈 구간(dead link)이 없는지 확인
|
||||||
|
- 모든 에이전트의 입력이 이전 Phase의 출력과 매칭되는지 확인
|
||||||
|
- 에러 시나리오별 폴백 경로가 실행 가능한지 확인
|
||||||
|
|
||||||
|
#### 6-6. 테스트 시나리오 작성
|
||||||
|
|
||||||
|
- 오케스트레이터 스킬에 `## 테스트 시나리오` 섹션 추가
|
||||||
|
- 정상 흐름 1개 + 에러 흐름 1개 이상 기술
|
||||||
|
|
||||||
|
### Phase 7: 하네스 진화
|
||||||
|
|
||||||
|
하네스는 한 번 만들고 끝나는 정적 산출물이 아니다. 사용자 피드백에 따라 계속 진화하는 시스템이다.
|
||||||
|
|
||||||
|
#### 7-1. 실행 후 피드백 수집
|
||||||
|
|
||||||
|
매 하네스 실행 완료 후, 사용자에게 피드백을 요청한다:
|
||||||
|
- "결과에서 개선할 부분이 있나요?"
|
||||||
|
- "에이전트 팀 구성이나 워크플로우에 바꾸고 싶은 점이 있나요?"
|
||||||
|
|
||||||
|
피드백이 없으면 넘어간다. 강요하지 않되, 반드시 기회를 제공한다.
|
||||||
|
|
||||||
|
#### 7-2. 피드백 반영 경로
|
||||||
|
|
||||||
|
피드백 유형에 따라 수정 대상이 다르다:
|
||||||
|
|
||||||
|
| 피드백 유형 | 수정 대상 | 예시 |
|
||||||
|
|-----------|----------|------|
|
||||||
|
| 결과물 품질 | 해당 에이전트의 스킬 | "분석이 너무 피상적" → 스킬에 깊이 기준 추가 |
|
||||||
|
| 에이전트 역할 | 에이전트 정의 `.md` | "보안 검토도 필요" → 새 에이전트 추가 |
|
||||||
|
| 워크플로우 순서 | 오케스트레이터 스킬 | "검증을 먼저 해야" → Phase 순서 변경 |
|
||||||
|
| 팀 구성 | 오케스트레이터 + 에이전트 | "이 둘은 합쳐도 될 듯" → 에이전트 병합 |
|
||||||
|
| 트리거 누락 | 스킬 description | "이 표현으로 하면 작동 안 함" → description 확장 |
|
||||||
|
|
||||||
|
#### 7-3. 변경 이력
|
||||||
|
|
||||||
|
모든 변경은 CLAUDE.md의 **변경 이력** 테이블에 기록한다 (Phase 5-4 템플릿의 "변경 이력" 섹션과 동일 테이블):
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
**변경 이력:**
|
||||||
|
| 날짜 | 변경 내용 | 대상 | 사유 |
|
||||||
|
|------|----------|------|------|
|
||||||
|
| 2026-04-05 | 초기 구성 | 전체 | - |
|
||||||
|
| 2026-04-07 | QA 에이전트 추가 | agents/qa.md | 산출물 품질 검증 부족 피드백 |
|
||||||
|
| 2026-04-10 | 톤 가이드 추가 | skills/content-creator | "너무 딱딱하다" 피드백 |
|
||||||
|
```
|
||||||
|
|
||||||
|
이 이력을 통해 하네스가 어떤 방향으로 진화했는지 추적하고, 퇴행(regression)을 방지한다.
|
||||||
|
|
||||||
|
#### 7-4. 진화 트리거
|
||||||
|
|
||||||
|
사용자가 명시적으로 "하네스 수정해줘"라고 할 때만이 아니라, 다음 상황에서도 진화를 제안한다:
|
||||||
|
- 같은 유형의 피드백이 2회 이상 반복될 때
|
||||||
|
- 에이전트가 반복적으로 실패하는 패턴이 발견될 때
|
||||||
|
- 사용자가 오케스트레이터를 우회하여 수동으로 작업하는 것이 관찰될 때
|
||||||
|
|
||||||
|
#### 7-5. 운영/유지보수 워크플로우
|
||||||
|
|
||||||
|
기존 하네스의 점검·수정·동기화를 체계적으로 수행한다. Phase 0에서 "운영/유지보수" 분기로 진입했을 때 이 워크플로우를 따른다.
|
||||||
|
|
||||||
|
**Step 1: 현황 감사**
|
||||||
|
- `.claude/agents/` 파일 목록과 오케스트레이터 스킬의 에이전트 구성 비교 → 불일치 목록 생성
|
||||||
|
- `.claude/skills/` 디렉토리 목록과 오케스트레이터 스킬의 스킬 구성 비교 → 불일치 목록 생성
|
||||||
|
- 감사 결과를 사용자에게 보고한다
|
||||||
|
|
||||||
|
**Step 2: 점진적 추가/수정**
|
||||||
|
- 사용자 요청에 따라 에이전트 추가/수정/삭제, 스킬 추가/수정/삭제를 수행한다
|
||||||
|
- 변경은 한 번에 하나씩, 각 변경 후 즉시 Step 3(동기화)을 실행한다
|
||||||
|
|
||||||
|
**Step 3: CLAUDE.md 변경 이력 갱신**
|
||||||
|
- 변경 이력 테이블에 날짜, 변경 내용, 대상, 사유를 기록한다
|
||||||
|
|
||||||
|
**Step 4: 변경 검증**
|
||||||
|
- 수정된 에이전트/스킬의 구조 검증 (Phase 6-1 기준)
|
||||||
|
- 수정 범위가 트리거에 영향을 주면 트리거 검증 (Phase 6-4 기준)
|
||||||
|
- 대규모 변경(아키텍처 변경, 에이전트 3개 이상 추가/삭제) 시 Phase 6-3(실행 테스트), 6-5(드라이런)까지 수행
|
||||||
|
- CLAUDE.md와 실제 파일의 일치 여부 최종 확인
|
||||||
|
|
||||||
|
## 산출물 체크리스트
|
||||||
|
|
||||||
|
생성 완료 후 확인:
|
||||||
|
|
||||||
|
- [ ] `프로젝트/.claude/agents/` — **에이전트 정의 파일 필수 생성** (빌트인 타입이라도 파일 생성 필수)
|
||||||
|
- [ ] `프로젝트/.claude/skills/` — 스킬 파일들 (SKILL.md + references/)
|
||||||
|
- [ ] 오케스트레이터 스킬 1개 (데이터 흐름 + 에러 핸들링 + 테스트 시나리오 포함)
|
||||||
|
- [ ] 실행 모드 명시 (에이전트 팀 / 서브 에이전트 / 하이브리드 중 선택, 하이브리드면 Phase별 모드 기재)
|
||||||
|
- [ ] 모든 Agent 호출에 `model: "opus"` 파라미터 명시
|
||||||
|
- [ ] 신규 에이전트 생성 전 기존 에이전트 중복 검토 완료 (Phase 3-0)
|
||||||
|
- [ ] 신규 스킬 생성 전 기존 스킬 중복 검토 완료 (Phase 4-0)
|
||||||
|
- [ ] `.claude/commands/` — 아무것도 생성하지 않음
|
||||||
|
- [ ] 기존 에이전트/스킬과 충돌 없음
|
||||||
|
- [ ] 스킬 description이 적극적("pushy")으로 작성됨 — **후속 작업 키워드 포함**
|
||||||
|
- [ ] SKILL.md 본문이 500줄 이내, 초과 시 references/ 분리
|
||||||
|
- [ ] 테스트 프롬프트 2~3개로 실행 검증 완료
|
||||||
|
- [ ] 트리거 검증 (should-trigger + should-NOT-trigger) 완료
|
||||||
|
- [ ] **CLAUDE.md에 하네스 포인터 등록** (트리거 규칙 + 변경 이력)
|
||||||
|
- [ ] **CLAUDE.md 변경 이력에 에이전트/스킬 추가/삭제/수정 기록**
|
||||||
|
- [ ] **오케스트레이터 Phase 1에 컨텍스트 확인 단계** (초기/후속/부분 재실행 판별)
|
||||||
|
|
||||||
|
## 참고
|
||||||
|
|
||||||
|
- 하네스 패턴: `references/agent-design-patterns.md`
|
||||||
|
- 기존 하네스 예시 (실제 파일 전문 포함): `references/team-examples.md`
|
||||||
|
- 오케스트레이터 템플릿: `references/orchestrator-template.md`
|
||||||
|
- **스킬 작성 가이드**: `references/skill-writing-guide.md` — 작성 패턴, 예시, 데이터 스키마 표준
|
||||||
|
- **스킬 테스트 가이드**: `references/skill-testing-guide.md` — 테스트/평가/반복 개선 방법론
|
||||||
|
- **QA 에이전트 가이드**: `references/qa-agent-guide.md` — 빌드 하네스에 QA 에이전트를 포함할 때 참조. 통합 정합성 검증 방법론, 경계면 버그 패턴, QA 에이전트 정의 템플릿 포함. 실제 프로젝트에서 발견된 7개 버그 사례 기반.
|
||||||
300
skills/harness/references/agent-design-patterns.md
Normal file
300
skills/harness/references/agent-design-patterns.md
Normal file
@ -0,0 +1,300 @@
|
|||||||
|
# Agent Team Design Patterns
|
||||||
|
|
||||||
|
## 실행 모드: 에이전트 팀 vs 서브 에이전트
|
||||||
|
|
||||||
|
두 가지 실행 모드의 핵심 차이를 이해하고 적합한 모드를 선택한다.
|
||||||
|
|
||||||
|
### 에이전트 팀 (Agent Teams) — 기본 모드
|
||||||
|
|
||||||
|
팀 리더가 `TeamCreate`로 팀을 구성하고, 팀원들은 독립적인 Claude Code 인스턴스로 실행된다. 팀원들은 `SendMessage`로 직접 통신하고, 공유 작업 목록(`TaskCreate`/`TaskUpdate`)으로 자체 조율한다.
|
||||||
|
|
||||||
|
```
|
||||||
|
[리더] ←→ [팀원A] ←→ [팀원B]
|
||||||
|
↕ ↕ ↕
|
||||||
|
└──── 공유 작업 목록 ────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
**핵심 도구:**
|
||||||
|
- `TeamCreate`: 팀 생성 + 팀원 스폰
|
||||||
|
- `SendMessage({to: name})`: 특정 팀원에게 메시지
|
||||||
|
- `SendMessage({to: "all"})`: 브로드캐스트 (비용 높음, 드물게)
|
||||||
|
- `TaskCreate`/`TaskUpdate`: 공유 작업 목록 관리
|
||||||
|
|
||||||
|
**특징:**
|
||||||
|
- 팀원끼리 직접 대화, 도전, 검증 가능
|
||||||
|
- 리더가 거치지 않고 팀원 간 정보 교환
|
||||||
|
- 공유 작업 목록으로 자체 조율 (자체 작업 요청 가능)
|
||||||
|
- 팀원이 유휴 상태가 되면 자동으로 리더에게 알림
|
||||||
|
- 계획 승인 모드로 위험한 작업 전 검토 가능
|
||||||
|
|
||||||
|
**제약:**
|
||||||
|
- 세션당 한 팀만 **활성화** 가능 (단, Phase 간에 팀을 해체하고 새 팀 구성은 가능)
|
||||||
|
- 중첩 팀 불가 (팀원이 자신의 팀 생성 불가)
|
||||||
|
- 리더 고정 (이전 불가)
|
||||||
|
- 토큰 비용 높음
|
||||||
|
|
||||||
|
**팀 재구성 패턴:**
|
||||||
|
Phase별로 다른 전문가 조합이 필요하면, 이전 팀의 산출물을 파일로 저장 → 팀 정리 → 새 팀 생성 순서로 진행한다. 이전 팀의 산출물은 `_workspace/` 에 보존되므로 새 팀이 Read로 접근 가능하다.
|
||||||
|
|
||||||
|
### 서브 에이전트 (Sub-agents) — 경량 모드
|
||||||
|
|
||||||
|
메인 에이전트가 `Agent` 도구로 서브 에이전트를 생성한다. 서브 에이전트는 작업 결과를 메인에게만 반환하고 서로 통신하지 않는다.
|
||||||
|
|
||||||
|
```
|
||||||
|
[메인] → [서브A] → 결과 반환
|
||||||
|
→ [서브B] → 결과 반환
|
||||||
|
→ [서브C] → 결과 반환
|
||||||
|
```
|
||||||
|
|
||||||
|
**핵심 도구:**
|
||||||
|
- `Agent(prompt, subagent_type, run_in_background)`: 서브 에이전트 생성
|
||||||
|
|
||||||
|
**특징:**
|
||||||
|
- 가볍고 빠름
|
||||||
|
- 결과가 메인 컨텍스트로 요약 반환
|
||||||
|
- 토큰 효율적
|
||||||
|
|
||||||
|
**제약:**
|
||||||
|
- 서브 에이전트 간 통신 불가
|
||||||
|
- 메인이 모든 조율 담당
|
||||||
|
- 실시간 협업/도전 불가
|
||||||
|
|
||||||
|
### 모드 선택 의사결정 트리
|
||||||
|
|
||||||
|
```
|
||||||
|
에이전트가 2개 이상인가?
|
||||||
|
├── Yes → 에이전트 간 통신이 필요한가?
|
||||||
|
│ ├── Yes → 에이전트 팀 (기본값)
|
||||||
|
│ │ 교차 검증·발견 공유·실시간 피드백으로 품질 향상.
|
||||||
|
│ │
|
||||||
|
│ └── No → 서브 에이전트도 가능
|
||||||
|
│ 결과 전달만 필요한 생성-검증, 전문가 풀 등.
|
||||||
|
│
|
||||||
|
└── No (1개) → 서브 에이전트
|
||||||
|
단일 에이전트는 팀 구성 불필요.
|
||||||
|
```
|
||||||
|
|
||||||
|
> **핵심 원칙:** 에이전트 팀이 기본이다. 서브 에이전트를 선택할 때는 "팀원 간 통신이 정말 불필요한가?"를 자문한다.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 에이전트 팀 아키텍처 유형
|
||||||
|
|
||||||
|
### 1. 파이프라인 (Pipeline)
|
||||||
|
순차적 작업 흐름. 이전 에이전트의 출력이 다음 에이전트의 입력.
|
||||||
|
|
||||||
|
```
|
||||||
|
[분석] → [설계] → [구현] → [검증]
|
||||||
|
```
|
||||||
|
|
||||||
|
**적합한 경우:** 각 단계가 이전 단계의 산출물에 강하게 의존
|
||||||
|
**예시:** 소설 집필 — 세계관 → 캐릭터 → 플롯 → 집필 → 편집
|
||||||
|
**주의:** 병목이 전체 파이프라인을 지연시킴. 각 단계를 가능한 독립적으로 설계할 것.
|
||||||
|
**팀 모드 적합성:** 순차 의존이 강해 팀 모드의 이점이 제한적. 단, 파이프라인 내 병렬 구간이 있으면 팀 모드 유용.
|
||||||
|
|
||||||
|
### 2. 팬아웃/팬인 (Fan-out/Fan-in)
|
||||||
|
병렬 처리 후 결과 통합. 독립적 작업을 동시 수행.
|
||||||
|
|
||||||
|
```
|
||||||
|
┌→ [전문가A] ─┐
|
||||||
|
[분배] → ├→ [전문가B] ─┼→ [통합]
|
||||||
|
└→ [전문가C] ─┘
|
||||||
|
```
|
||||||
|
|
||||||
|
**적합한 경우:** 동일 입력에 대해 서로 다른 관점/영역의 분석이 필요
|
||||||
|
**예시:** 종합 리서치 — 공식/미디어/커뮤니티/배경 동시 조사 → 통합 보고
|
||||||
|
**주의:** 통합 단계의 품질이 전체 품질을 결정.
|
||||||
|
**팀 모드 적합성:** 에이전트 팀의 가장 자연스러운 패턴. **반드시 에이전트 팀으로 구성해야 한다.** 팀원들이 서로 발견을 공유하고 도전하며, 한 에이전트의 발견이 다른 에이전트의 조사 방향을 실시간으로 수정할 수 있어 단독 조사 대비 품질이 크게 향상된다.
|
||||||
|
|
||||||
|
### 3. 전문가 풀 (Expert Pool)
|
||||||
|
상황에 따라 적절한 전문가를 선택 호출.
|
||||||
|
|
||||||
|
```
|
||||||
|
[라우터] → { 전문가A | 전문가B | 전문가C }
|
||||||
|
```
|
||||||
|
|
||||||
|
**적합한 경우:** 입력 유형에 따라 다른 처리가 필요
|
||||||
|
**예시:** 코드 리뷰 — 보안/성능/아키텍처 전문가 중 해당 영역만 호출
|
||||||
|
**주의:** 라우터의 분류 정확도가 핵심.
|
||||||
|
**팀 모드 적합성:** 서브 에이전트가 더 적합. 필요한 전문가만 호출하므로 상시 팀이 불필요.
|
||||||
|
|
||||||
|
### 4. 생성-검증 (Producer-Reviewer)
|
||||||
|
생성 에이전트와 검증 에이전트가 쌍으로 동작.
|
||||||
|
|
||||||
|
```
|
||||||
|
[생성] → [검증] → (문제시) → [생성] 재실행
|
||||||
|
```
|
||||||
|
|
||||||
|
**적합한 경우:** 산출물의 품질 보장이 중요하고 객관적 검증 기준이 존재
|
||||||
|
**예시:** 웹툰 — artist 생성 → reviewer 검수 → 문제 패널 재생성
|
||||||
|
**주의:** 무한 루프 방지를 위해 최대 재시도 횟수(2~3회) 설정 필수.
|
||||||
|
**팀 모드 적합성:** 에이전트 팀이 유용. SendMessage로 생성자↔검증자 간 실시간 피드백 교환.
|
||||||
|
|
||||||
|
### 5. 감독자 (Supervisor)
|
||||||
|
중앙 에이전트가 작업 상태를 관리하며 하위 에이전트에 동적으로 작업을 분배.
|
||||||
|
|
||||||
|
```
|
||||||
|
┌→ [워커A]
|
||||||
|
[감독자] ─┼→ [워커B] ← 감독자가 상태를 보고 동적 분배
|
||||||
|
└→ [워커C]
|
||||||
|
```
|
||||||
|
|
||||||
|
**적합한 경우:** 작업량이 가변적이거나 런타임에 작업 분배를 결정해야 할 때
|
||||||
|
**예시:** 대규모 코드 마이그레이션 — 감독자가 파일 목록을 분석하고 워커들에게 배치 할당
|
||||||
|
**팬아웃과의 차이:** 팬아웃은 사전에 작업을 고정 분배, 감독자는 진행 상황을 보며 동적 조정
|
||||||
|
**주의:** 감독자가 병목이 되지 않도록 위임 단위를 충분히 크게 설정.
|
||||||
|
**팀 모드 적합성:** 에이전트 팀의 공유 작업 목록이 감독자 패턴과 자연스럽게 매칭. TaskCreate로 작업 등록, 팀원들이 자체 요청.
|
||||||
|
|
||||||
|
### 6. 계층적 위임 (Hierarchical Delegation)
|
||||||
|
상위 에이전트가 하위 에이전트에 재귀적으로 위임. 복잡한 문제를 단계적으로 분해.
|
||||||
|
|
||||||
|
```
|
||||||
|
[총괄] → [팀장A] → [실무자A1]
|
||||||
|
→ [실무자A2]
|
||||||
|
→ [팀장B] → [실무자B1]
|
||||||
|
```
|
||||||
|
|
||||||
|
**적합한 경우:** 문제가 자연스럽게 계층적으로 분해되는 구조
|
||||||
|
**예시:** 풀스택 앱 개발 — 총괄 → 프론트엔드팀장 → (UI/로직/테스트) + 백엔드팀장 → (API/DB/테스트)
|
||||||
|
**주의:** 깊이 3단계 이상은 지연과 컨텍스트 손실이 커짐. 2단계 이내 권장.
|
||||||
|
**팀 모드 적합성:** 에이전트 팀은 중첩 불가 (팀원이 팀 생성 불가). 1단계는 팀, 2단계는 서브 에이전트로 구현하거나, 평탄화하여 단일 팀으로 구성.
|
||||||
|
|
||||||
|
## 복합 패턴
|
||||||
|
|
||||||
|
실전에서는 단일 패턴보다 복합 패턴이 흔하다:
|
||||||
|
|
||||||
|
| 복합 패턴 | 구성 | 예시 |
|
||||||
|
|----------|------|------|
|
||||||
|
| **팬아웃 + 생성-검증** | 병렬 생성 후 각각 검증 | 다국어 번역 — 4개 언어 병렬 번역 → 각각 네이티브 리뷰어 검수 |
|
||||||
|
| **파이프라인 + 팬아웃** | 순차 단계 중 일부를 병렬화 | 분석(순차) → 구현(병렬) → 통합 테스트(순차) |
|
||||||
|
| **감독자 + 전문가 풀** | 감독자가 전문가를 동적 호출 | 고객 문의 처리 — 감독자가 문의 분류 후 적합한 전문가 할당 |
|
||||||
|
|
||||||
|
### 복합 패턴에서의 실행 모드
|
||||||
|
|
||||||
|
**기본적으로 모든 복합 패턴에 에이전트 팀을 사용한다.** 팀원 간 활발한 커뮤니케이션이 결과 품질의 핵심 동력이다.
|
||||||
|
|
||||||
|
| 시나리오 | 권장 모드 | 이유 |
|
||||||
|
|---------|----------|------|
|
||||||
|
| **리서치 + 분석** | 에이전트 팀 | 조사자 간 발견 공유, 상충 정보 실시간 토론 |
|
||||||
|
| **설계 + 구현 + 검증** | 에이전트 팀 | 설계자↔구현자↔검증자 간 피드백 루프 |
|
||||||
|
| **감독자 + 워커** | 에이전트 팀 | 공유 작업 목록으로 동적 할당, 워커 간 진행률 공유 |
|
||||||
|
| **생성 + 검증** | 에이전트 팀 | 생성자↔검증자 간 실시간 피드백으로 재작업 최소화 |
|
||||||
|
|
||||||
|
> 서브 에이전트로의 혼합은 단일 에이전트가 완전히 격리된 단발성 작업을 수행할 때만 고려한다.
|
||||||
|
|
||||||
|
## 에이전트 타입 선택
|
||||||
|
|
||||||
|
에이전트를 호출할 때 Agent 도구의 `subagent_type` 파라미터로 타입을 지정한다. 에이전트 팀의 팀원도 커스텀 에이전트 정의를 사용할 수 있다.
|
||||||
|
|
||||||
|
### 빌트인 타입
|
||||||
|
|
||||||
|
| 타입 | 도구 접근 | 적합한 용도 |
|
||||||
|
|------|----------|-----------|
|
||||||
|
| `general-purpose` | 전체 (WebSearch, WebFetch 포함) | 웹 조사, 범용 작업 |
|
||||||
|
| `Explore` | 읽기 전용 (Edit/Write 없음) | 코드베이스 탐색, 분석 |
|
||||||
|
| `Plan` | 읽기 전용 (Edit/Write 없음) | 아키텍처 설계, 계획 수립 |
|
||||||
|
|
||||||
|
### 커스텀 타입
|
||||||
|
|
||||||
|
`.claude/agents/{name}.md`에 에이전트를 정의하면 `subagent_type: "{name}"`으로 호출할 수 있다. 커스텀 에이전트는 전체 도구에 접근 가능.
|
||||||
|
|
||||||
|
### 선택 기준
|
||||||
|
|
||||||
|
| 상황 | 권장 | 이유 |
|
||||||
|
|------|------|------|
|
||||||
|
| 역할이 복잡하고 여러 세션에서 재사용 | **커스텀 타입** (`.claude/agents/`) | 페르소나와 작업 원칙을 파일로 관리 |
|
||||||
|
| 단순 조사/수집이고 프롬프트만으로 충분 | **`general-purpose`** + 상세 프롬프트 | 에이전트 파일 불필요, 프롬프트에 지시 포함 |
|
||||||
|
| 코드 읽기만 필요 (분석/리뷰) | **`Explore`** | 실수로 파일 수정하는 것을 방지 |
|
||||||
|
| 설계/계획만 필요 | **`Plan`** | 분석에 집중, 코드 변경 방지 |
|
||||||
|
| 파일 수정이 필요한 구현 작업 | **커스텀 타입** | 전체 도구 접근 + 전문 지시 |
|
||||||
|
|
||||||
|
**원칙:** 모든 에이전트는 반드시 `.claude/agents/{name}.md` 파일로 정의한다. 빌트인 타입이라도 에이전트 정의 파일을 생성하여 역할·원칙·프로토콜을 명시한다. 파일로 존재해야 다음 세션에서 재사용 가능하고, 팀 통신 프로토콜이 명시되어야 협업 품질이 보장된다.
|
||||||
|
|
||||||
|
**모델:** 모든 에이전트는 `model: "opus"`를 사용한다. Agent 도구 호출 시 반드시 `model: "opus"` 파라미터를 명시한다.
|
||||||
|
|
||||||
|
## 에이전트 정의 구조
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
---
|
||||||
|
name: agent-name
|
||||||
|
description: "1-2문장 역할 설명. 트리거 키워드 나열."
|
||||||
|
---
|
||||||
|
|
||||||
|
# Agent Name — 역할 한줄 요약
|
||||||
|
|
||||||
|
당신은 [도메인]의 [역할] 전문가입니다.
|
||||||
|
|
||||||
|
## 핵심 역할
|
||||||
|
1. 역할1
|
||||||
|
2. 역할2
|
||||||
|
|
||||||
|
## 작업 원칙
|
||||||
|
- 원칙1
|
||||||
|
- 원칙2
|
||||||
|
|
||||||
|
## 입력/출력 프로토콜
|
||||||
|
- 입력: [어디서 무엇을 받는지]
|
||||||
|
- 출력: [어디에 무엇을 쓰는지]
|
||||||
|
- 형식: [파일 포맷, 구조]
|
||||||
|
|
||||||
|
## 팀 통신 프로토콜 (에이전트 팀 모드)
|
||||||
|
- 메시지 수신: [누구로부터 어떤 메시지를 받는지]
|
||||||
|
- 메시지 발신: [누구에게 어떤 메시지를 보내는지]
|
||||||
|
- 작업 요청: [공유 작업 목록에서 어떤 유형의 작업을 요청하는지]
|
||||||
|
|
||||||
|
## 에러 핸들링
|
||||||
|
- [실패 시 행동]
|
||||||
|
- [타임아웃 시 행동]
|
||||||
|
|
||||||
|
## 협업
|
||||||
|
- 다른 에이전트와의 관계
|
||||||
|
```
|
||||||
|
|
||||||
|
## 에이전트 분리 기준
|
||||||
|
|
||||||
|
| 기준 | 분리 | 통합 |
|
||||||
|
|------|------|------|
|
||||||
|
| 전문성 | 영역이 다르면 분리 | 영역이 겹치면 통합 |
|
||||||
|
| 병렬성 | 독립 실행 가능하면 분리 | 순차 종속이면 통합 고려 |
|
||||||
|
| 컨텍스트 | 컨텍스트 부담이 크면 분리 | 가볍고 빠르면 통합 |
|
||||||
|
| 재사용성 | 다른 팀에서도 쓰면 분리 | 이 팀에서만 쓰면 통합 고려 |
|
||||||
|
|
||||||
|
## 에이전트 재사용 설계
|
||||||
|
|
||||||
|
신규 에이전트 생성 전, 기존 에이전트와의 중복을 확인한다. 하네스를 반복 구축하다 보면 역할이 겹치는 에이전트가 다른 이름으로 누적되기 쉽다.
|
||||||
|
|
||||||
|
| 상황 | 조치 |
|
||||||
|
|------|------|
|
||||||
|
| 기존 에이전트가 신규 역할을 완전히 포함 | 신규 생성 금지 — 기존 에이전트 재사용 |
|
||||||
|
| 기존 에이전트가 부분 포함이고 일반화 가능 | 기존 에이전트를 일반화하여 확장 |
|
||||||
|
| 도메인 특화가 의도된 부분 포함 | 신규 생성 진행 — 별개 에이전트로 유지 |
|
||||||
|
| 역할 범위가 완전히 다름 | 신규 생성 진행 |
|
||||||
|
|
||||||
|
**원칙:** 하나의 에이전트가 하나의 역할에 집중할수록 재사용성이 높고 중복이 줄어든다. 역할이 두 가지 이상이면 분리할 수 있는지 먼저 검토한다.
|
||||||
|
|
||||||
|
**기존 에이전트 일반화 시:** 해당 에이전트에 의존하는 오케스트레이터·팀 구성의 동작이 변경될 수 있다. 확장 전 의존성을 확인하고, 일반화 후 드라이런으로 기존 동작 유지를 확인한다.
|
||||||
|
|
||||||
|
## 스킬 vs 에이전트 구분
|
||||||
|
|
||||||
|
| 구분 | 스킬 (Skill) | 에이전트 (Agent) |
|
||||||
|
|------|-------------|-----------------|
|
||||||
|
| 정의 | 절차적 지식 + 도구 번들 | 전문가 페르소나 + 행동 원칙 |
|
||||||
|
| 위치 | `.claude/skills/` | `.claude/agents/` |
|
||||||
|
| 트리거 | 사용자 요청 키워드 매칭 | Agent 도구로 명시적 호출 |
|
||||||
|
| 크기 | 작은~큰 (워크플로우) | 작은 (역할 정의) |
|
||||||
|
| 용도 | "어떻게 하는가" | "누가 하는가" |
|
||||||
|
|
||||||
|
스킬은 에이전트가 작업을 수행할 때 참조하는 **절차적 가이드**.
|
||||||
|
에이전트는 스킬을 활용하는 **전문가 역할 정의**.
|
||||||
|
|
||||||
|
## 스킬 ↔ 에이전트 연결 방식
|
||||||
|
|
||||||
|
에이전트가 스킬을 활용하는 3가지 방식:
|
||||||
|
|
||||||
|
| 방식 | 구현 | 적합한 경우 |
|
||||||
|
|------|------|-----------|
|
||||||
|
| **Skill 도구 호출** | 에이전트 프롬프트에 `Skill 도구로 /skill-name 호출` 명시 | 스킬이 독립 워크플로우이고 사용자 호출 가능한 경우 |
|
||||||
|
| **프롬프트 내 인라인** | 에이전트 정의 내에 스킬 내용을 직접 포함 | 스킬이 짧고(50줄 이하) 이 에이전트 전용인 경우 |
|
||||||
|
| **레퍼런스 로드** | `Read`로 스킬의 references/ 파일을 필요 시 로드 | 스킬 내용이 크고 조건부로만 필요한 경우 |
|
||||||
|
|
||||||
|
권장: 재사용성이 높으면 Skill 도구, 전용이면 인라인, 대용량이면 레퍼런스 로드.
|
||||||
292
skills/harness/references/orchestrator-template.md
Normal file
292
skills/harness/references/orchestrator-template.md
Normal file
@ -0,0 +1,292 @@
|
|||||||
|
# 오케스트레이터 스킬 템플릿
|
||||||
|
|
||||||
|
오케스트레이터는 팀 전체를 조율하는 상위 스킬이다. 실행 모드별로 3가지 템플릿을 제공한다:
|
||||||
|
|
||||||
|
- **템플릿 A: 에이전트 팀 모드 (기본)** — 2명 이상 협업 시 최우선 선택
|
||||||
|
- **템플릿 B: 서브 에이전트 모드 (대안)** — 팀 통신이 불필요한 경우
|
||||||
|
- **템플릿 C: 하이브리드 모드** — Phase마다 모드를 섞어 구성
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 템플릿 A: 에이전트 팀 모드 (기본 · 최우선 선택)
|
||||||
|
|
||||||
|
2명 이상의 에이전트가 협업할 때 **가장 먼저 검토하는 기본 모드**. `TeamCreate`로 팀을 구성하고, 공유 작업 목록과 `SendMessage`로 조율한다.
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
---
|
||||||
|
name: {domain}-orchestrator
|
||||||
|
description: "{도메인} 에이전트 팀을 조율하는 오케스트레이터. {초기 실행 키워드}. 후속 작업: {도메인} 결과 수정, 부분 재실행, 업데이트, 보완, 다시 실행, 이전 결과 개선 요청 시에도 반드시 이 스킬을 사용."
|
||||||
|
---
|
||||||
|
|
||||||
|
# {Domain} Orchestrator
|
||||||
|
|
||||||
|
{도메인}의 에이전트 팀을 조율하여 {최종 산출물}을 생성하는 통합 스킬.
|
||||||
|
|
||||||
|
## 실행 모드: 에이전트 팀
|
||||||
|
|
||||||
|
## 에이전트 구성
|
||||||
|
|
||||||
|
| 팀원 | 에이전트 타입 | 역할 | 스킬 | 출력 |
|
||||||
|
|------|-------------|------|------|------|
|
||||||
|
| {teammate-1} | {커스텀 또는 빌트인} | {역할} | {skill} | {output-file} |
|
||||||
|
| {teammate-2} | {커스텀 또는 빌트인} | {역할} | {skill} | {output-file} |
|
||||||
|
| ... | | | | |
|
||||||
|
|
||||||
|
## 워크플로우
|
||||||
|
|
||||||
|
### Phase 0: 컨텍스트 확인 (후속 작업 지원)
|
||||||
|
|
||||||
|
기존 산출물 존재 여부를 확인하여 실행 모드를 결정한다:
|
||||||
|
|
||||||
|
1. `_workspace/` 디렉토리 존재 여부 확인
|
||||||
|
2. 실행 모드 결정:
|
||||||
|
- **`_workspace/` 미존재** → 초기 실행. Phase 1로 진행
|
||||||
|
- **`_workspace/` 존재 + 사용자가 부분 수정 요청** → 부분 재실행. 해당 에이전트만 재호출하고, 기존 산출물 중 수정 대상만 덮어쓴다
|
||||||
|
- **`_workspace/` 존재 + 새 입력 제공** → 새 실행. 기존 `_workspace/`를 `_workspace_{YYYYMMDD_HHMMSS}/`로 이동한 뒤 Phase 1 진행
|
||||||
|
3. 부분 재실행 시: 이전 산출물 경로를 에이전트 프롬프트에 포함하여, 에이전트가 기존 결과를 읽고 피드백을 반영하도록 지시
|
||||||
|
|
||||||
|
### Phase 1: 준비
|
||||||
|
1. 사용자 입력 분석 — {무엇을 파악하는지}
|
||||||
|
2. 작업 디렉토리에 `_workspace/` 생성
|
||||||
|
- **초기 실행**: 새 `_workspace/` 생성
|
||||||
|
- **새 실행**: 기존 `_workspace/`를 `_workspace_{YYYYMMDD_HHMMSS}/`로 이동한 직후 새 `_workspace/` 재생성
|
||||||
|
3. 입력 데이터를 `_workspace/00_input/`에 저장
|
||||||
|
|
||||||
|
### Phase 2: 팀 구성
|
||||||
|
|
||||||
|
1. 팀 생성:
|
||||||
|
```
|
||||||
|
TeamCreate(
|
||||||
|
team_name: "{domain}-team",
|
||||||
|
members: [
|
||||||
|
{ name: "{teammate-1}", agent_type: "{type}", model: "opus", prompt: "{역할 설명 및 작업 지시}" },
|
||||||
|
{ name: "{teammate-2}", agent_type: "{type}", model: "opus", prompt: "{역할 설명 및 작업 지시}" },
|
||||||
|
...
|
||||||
|
]
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
2. 작업 등록:
|
||||||
|
```
|
||||||
|
TaskCreate(tasks: [
|
||||||
|
{ title: "{작업1}", description: "{상세}", assignee: "{teammate-1}" },
|
||||||
|
{ title: "{작업2}", description: "{상세}", assignee: "{teammate-2}" },
|
||||||
|
{ title: "{작업3}", description: "{상세}", depends_on: ["{작업1}"] },
|
||||||
|
...
|
||||||
|
])
|
||||||
|
```
|
||||||
|
|
||||||
|
> 팀원당 5~6개 작업이 적정. 의존성이 있는 작업은 `depends_on`으로 명시.
|
||||||
|
|
||||||
|
### Phase 3: {주요 작업 — 예: 조사/생성/분석}
|
||||||
|
|
||||||
|
**실행 방식:** 팀원들이 자체 조율
|
||||||
|
|
||||||
|
팀원들은 공유 작업 목록에서 작업을 요청(claim)하고 독립적으로 수행한다.
|
||||||
|
리더는 진행 상황을 모니터링하며 필요 시 개입한다.
|
||||||
|
|
||||||
|
**팀원 간 통신 규칙:**
|
||||||
|
- {teammate-1}은 {teammate-2}에게 {어떤 정보}를 SendMessage로 전달
|
||||||
|
- {teammate-2}는 작업 완료 시 결과를 파일로 저장하고 리더에게 알림
|
||||||
|
- 팀원이 다른 팀원의 결과가 필요하면 SendMessage로 요청
|
||||||
|
|
||||||
|
**산출물 저장:**
|
||||||
|
|
||||||
|
| 팀원 | 출력 경로 |
|
||||||
|
|------|----------|
|
||||||
|
| {teammate-1} | `_workspace/{phase}_{teammate-1}_{artifact}.md` |
|
||||||
|
| {teammate-2} | `_workspace/{phase}_{teammate-2}_{artifact}.md` |
|
||||||
|
|
||||||
|
**리더 모니터링:**
|
||||||
|
- 팀원이 유휴 상태가 되면 자동 알림 수신
|
||||||
|
- 특정 팀원이 막혔을 때 SendMessage로 지시 또는 작업 재할당
|
||||||
|
- 전체 진행률은 TaskGet으로 확인
|
||||||
|
|
||||||
|
### Phase 4: {후속 작업 — 예: 검증/통합}
|
||||||
|
1. 모든 팀원의 작업 완료 대기 (TaskGet으로 상태 확인)
|
||||||
|
2. 각 팀원의 산출물을 Read로 수집
|
||||||
|
3. {통합/검증 로직}
|
||||||
|
4. 최종 산출물 생성: `{output-path}/{filename}`
|
||||||
|
|
||||||
|
### Phase 5: 정리
|
||||||
|
1. 팀원들에게 종료 요청 (SendMessage)
|
||||||
|
2. 팀 정리 (TeamDelete)
|
||||||
|
3. `_workspace/` 디렉토리 보존 (중간 산출물은 삭제하지 않음 — 사후 검증·감사 추적용)
|
||||||
|
4. 사용자에게 결과 요약 보고
|
||||||
|
|
||||||
|
> **팀 재구성이 필요한 경우:** Phase별로 다른 전문가 조합이 필요하면, 현재 팀을 TeamDelete로 정리한 뒤 새 TeamCreate로 다음 Phase의 팀을 구성한다. 이전 팀의 산출물은 `_workspace/`에 보존되므로 새 팀이 Read로 접근 가능.
|
||||||
|
|
||||||
|
## 데이터 흐름
|
||||||
|
|
||||||
|
```
|
||||||
|
[리더] → TeamCreate → [teammate-1] ←SendMessage→ [teammate-2]
|
||||||
|
│ │
|
||||||
|
↓ ↓
|
||||||
|
artifact-1.md artifact-2.md
|
||||||
|
│ │
|
||||||
|
└───────── Read ────────────┘
|
||||||
|
↓
|
||||||
|
[리더: 통합]
|
||||||
|
↓
|
||||||
|
최종 산출물
|
||||||
|
```
|
||||||
|
|
||||||
|
## 에러 핸들링
|
||||||
|
|
||||||
|
| 상황 | 전략 |
|
||||||
|
|------|------|
|
||||||
|
| 팀원 1명 실패/중지 | 리더가 감지 → SendMessage로 상태 확인 → 재시작 또는 대체 팀원 생성 |
|
||||||
|
| 팀원 과반 실패 | 사용자에게 알리고 진행 여부 확인 |
|
||||||
|
| 타임아웃 | 현재까지 수집된 부분 결과 사용, 미완료 팀원 종료 |
|
||||||
|
| 팀원 간 데이터 충돌 | 출처 명시 후 병기, 삭제하지 않음 |
|
||||||
|
| 작업 상태 지연 | 리더가 TaskGet으로 확인 후 수동으로 TaskUpdate |
|
||||||
|
|
||||||
|
## 테스트 시나리오
|
||||||
|
|
||||||
|
### 정상 흐름
|
||||||
|
1. 사용자가 {입력}을 제공
|
||||||
|
2. Phase 1에서 {분석 결과} 도출
|
||||||
|
3. Phase 2에서 팀 구성 ({N}명 팀원 + {M}개 작업)
|
||||||
|
4. Phase 3에서 팀원들이 자체 조율하며 작업 수행
|
||||||
|
5. Phase 4에서 산출물 통합하여 최종 결과 생성
|
||||||
|
6. Phase 5에서 팀 정리
|
||||||
|
7. 예상 결과: `{output-path}/{filename}` 생성
|
||||||
|
|
||||||
|
### 에러 흐름
|
||||||
|
1. Phase 3에서 {teammate-2}가 에러로 중지
|
||||||
|
2. 리더가 유휴 알림 수신
|
||||||
|
3. SendMessage로 상태 확인 → 재시작 시도
|
||||||
|
4. 재시작 실패 시 {teammate-2} 작업을 {teammate-1}에게 재할당
|
||||||
|
5. 나머지 결과로 Phase 4 진행
|
||||||
|
6. 최종 보고서에 "{teammate-2} 영역 일부 미수집" 명시
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 템플릿 B: 서브 에이전트 모드 (대안)
|
||||||
|
|
||||||
|
팀 통신 오버헤드가 불필요한 경우. `Agent` 도구로 직접 호출하고 반환값으로 결과를 수집한다.
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
---
|
||||||
|
name: {domain}-orchestrator
|
||||||
|
description: "{도메인} 에이전트를 조율하는 오케스트레이터. {초기 실행 키워드}. 후속 작업 키워드 포함."
|
||||||
|
---
|
||||||
|
|
||||||
|
## 실행 모드: 서브 에이전트
|
||||||
|
|
||||||
|
## 에이전트 구성
|
||||||
|
|
||||||
|
| 에이전트 | subagent_type | 역할 | 스킬 | 출력 |
|
||||||
|
|---------|--------------|------|------|------|
|
||||||
|
| {agent-1} | {빌트인 또는 커스텀} | {역할} | {skill} | {output-file} |
|
||||||
|
| {agent-2} | ... | ... | ... | ... |
|
||||||
|
|
||||||
|
## 워크플로우
|
||||||
|
|
||||||
|
### Phase 0: 컨텍스트 확인
|
||||||
|
(Template A와 동일 — `_workspace/` 존재 여부 분기)
|
||||||
|
|
||||||
|
### Phase 1: 준비
|
||||||
|
1. 입력 분석
|
||||||
|
2. `_workspace/` 생성 (초기 실행 시, 또는 새 실행에서 기존 `_workspace/`를 보관 디렉토리로 이동한 직후)
|
||||||
|
|
||||||
|
### Phase 2: 병렬 실행
|
||||||
|
단일 메시지에서 N개 Agent 도구를 동시 호출:
|
||||||
|
|
||||||
|
| 에이전트 | 입력 | 출력 | model | run_in_background |
|
||||||
|
|---------|------|------|-------|-------------------|
|
||||||
|
| {agent-1} | {소스} | `_workspace/{phase}_{agent}_{artifact}.md` | opus | true |
|
||||||
|
| {agent-2} | {소스} | `_workspace/{phase}_{agent}_{artifact}.md` | opus | true |
|
||||||
|
|
||||||
|
### Phase 3: 통합
|
||||||
|
1. 각 에이전트의 반환값 수집
|
||||||
|
2. 파일 기반 산출물은 Read로 수집
|
||||||
|
3. 통합 로직 적용 → 최종 산출물
|
||||||
|
|
||||||
|
### Phase 4: 정리
|
||||||
|
1. `_workspace/` 보존
|
||||||
|
2. 결과 요약 보고
|
||||||
|
|
||||||
|
## 에러 핸들링
|
||||||
|
- 에이전트 1개 실패: 1회 재시도. 재실패 시 누락 명시하고 진행
|
||||||
|
- 과반 실패: 사용자에게 알리고 진행 여부 확인
|
||||||
|
- 타임아웃: 현재까지 수집된 부분 결과 사용
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 템플릿 C: 하이브리드 모드
|
||||||
|
|
||||||
|
Phase마다 다른 실행 모드를 사용한다. 각 Phase 상단에 `**실행 모드:** {팀 | 서브}`를 명시한다.
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
---
|
||||||
|
name: {domain}-orchestrator
|
||||||
|
description: "{도메인} 오케스트레이터 (하이브리드). {키워드}. 후속 작업 키워드 포함."
|
||||||
|
---
|
||||||
|
|
||||||
|
## 실행 모드: 하이브리드
|
||||||
|
|
||||||
|
| Phase | 모드 | 이유 |
|
||||||
|
|-------|------|------|
|
||||||
|
| Phase 2 (병렬 수집) | 서브 에이전트 | 독립 자료 수집, 팀 통신 불필요 |
|
||||||
|
| Phase 3 (합의 통합) | 에이전트 팀 | 상충 데이터 토론·합의 필요 |
|
||||||
|
| Phase 4 (독립 검증) | 서브 에이전트 | QA 에이전트 1명이 객관 검증 |
|
||||||
|
|
||||||
|
## 워크플로우
|
||||||
|
|
||||||
|
### Phase 2: 병렬 자료 수집
|
||||||
|
**실행 모드:** 서브 에이전트
|
||||||
|
|
||||||
|
단일 메시지에서 Agent 도구로 N개 에이전트 병렬 호출 (`run_in_background: true`).
|
||||||
|
각 결과는 `_workspace/02_{agent}_raw.md`에 저장.
|
||||||
|
|
||||||
|
### Phase 3: 합의 기반 통합
|
||||||
|
**실행 모드:** 에이전트 팀
|
||||||
|
|
||||||
|
1. `TeamCreate`로 통합 팀 구성 (editor + fact-checker + synthesizer)
|
||||||
|
2. `TaskCreate`로 작업 분배 — 모두 Phase 2의 `_workspace/02_*` 파일을 Read
|
||||||
|
3. 팀원들이 `SendMessage`로 상충 데이터를 논의, 파일 기반으로 합의안 도출
|
||||||
|
4. 최종 통합본 `_workspace/03_integrated.md` 생성
|
||||||
|
5. `TeamDelete`로 팀 정리
|
||||||
|
|
||||||
|
### Phase 4: 독립 검증
|
||||||
|
**실행 모드:** 서브 에이전트
|
||||||
|
|
||||||
|
단일 QA 서브 에이전트가 `_workspace/03_integrated.md`를 입력으로 받아 검증 보고서 생성.
|
||||||
|
```
|
||||||
|
|
||||||
|
**하이브리드 전환 규칙:**
|
||||||
|
- 팀 → 서브: 팀을 반드시 `TeamDelete`로 정리한 후 Agent 도구 호출
|
||||||
|
- 서브 → 팀: 서브 에이전트의 파일 산출물을 팀원들에게 Read 경로로 전달
|
||||||
|
- 팀 → 팀: 이전 팀을 정리한 후 새 `TeamCreate` (세션당 1팀만 활성 가능)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 작성 원칙
|
||||||
|
|
||||||
|
1. **실행 모드를 먼저 명시** — 오케스트레이터 상단에 "에이전트 팀" / "서브 에이전트" / "하이브리드" 중 하나 명시. 하이브리드면 Phase별 모드 표 필수
|
||||||
|
2. **팀 모드는 TeamCreate/SendMessage/TaskCreate 사용법을 구체적으로** — 팀 구성, 작업 등록, 통신 규칙
|
||||||
|
3. **서브 모드는 Agent 도구 파라미터를 완전히 명시** — name, subagent_type, prompt, run_in_background, model
|
||||||
|
4. **파일 경로는 절대적으로** — 상대 경로 금지, `_workspace/` 기준 명확한 경로
|
||||||
|
5. **Phase 간 의존성 명시** — 어떤 Phase가 어떤 Phase의 결과에 의존하는지. 하이브리드는 모드 전환 지점을 특히 강조
|
||||||
|
6. **에러 핸들링은 현실적으로** — "모든 것이 성공한다"고 가정하지 않음
|
||||||
|
7. **테스트 시나리오 필수** — 정상 1 + 에러 1 이상
|
||||||
|
|
||||||
|
## description 작성 시 후속 작업 키워드
|
||||||
|
|
||||||
|
오케스트레이터 description은 초기 실행 키워드만으로는 부족하다. 다음 후속 작업 표현을 반드시 포함하라:
|
||||||
|
|
||||||
|
- 재실행/다시 실행/업데이트/수정/보완
|
||||||
|
- "{도메인}의 {부분}만 다시"
|
||||||
|
- "이전 결과 기반으로", "결과 개선"
|
||||||
|
- 도메인 관련 일상적 요청 (예: 런치 전략 하네스라면 "런치", "홍보", "트렌딩" 등)
|
||||||
|
|
||||||
|
후속 키워드가 없으면 첫 실행 후 하네스가 사실상 죽은 코드가 된다.
|
||||||
|
|
||||||
|
## 실제 오케스트레이터 참고
|
||||||
|
|
||||||
|
팬아웃/팬인 패턴의 오케스트레이터 기본 구조:
|
||||||
|
준비 → Phase 0(컨텍스트 확인) → TeamCreate + TaskCreate → N개 팀원 병렬 실행 → Read + 통합 → 정리.
|
||||||
|
`references/team-examples.md`의 리서치 팀 예시를 참조.
|
||||||
228
skills/harness/references/qa-agent-guide.md
Normal file
228
skills/harness/references/qa-agent-guide.md
Normal file
@ -0,0 +1,228 @@
|
|||||||
|
# QA 에이전트 설계 가이드
|
||||||
|
|
||||||
|
빌드 하네스에 QA 에이전트를 포함할 때 참고하는 가이드. 실제 프로젝트(SatangSlide)에서 발견된 버그 패턴과 그 근본 원인 분석을 바탕으로, QA가 놓치기 쉬운 결함을 체계적으로 잡는 검증 방법론을 제공한다.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 목차
|
||||||
|
|
||||||
|
1. QA 에이전트가 놓치는 결함의 패턴
|
||||||
|
2. 통합 정합성 검증 (Integration Coherence Verification)
|
||||||
|
3. QA 에이전트 설계 원칙
|
||||||
|
4. 검증 체크리스트 템플릿
|
||||||
|
5. QA 에이전트 정의 템플릿
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. QA 에이전트가 놓치는 결함의 패턴
|
||||||
|
|
||||||
|
### 1-1. 경계면 불일치 (Boundary Mismatch)
|
||||||
|
|
||||||
|
가장 빈번한 결함. 두 컴포넌트가 각각 "올바르게" 구현되어 있지만, 연결 지점에서 계약이 어긋남.
|
||||||
|
|
||||||
|
| 경계면 | 불일치 예시 | 놓치는 이유 |
|
||||||
|
|--------|-----------|-----------|
|
||||||
|
| API 응답 → 프론트 훅 | API가 `{ projects: [...] }` 반환, 훅이 `SlideProject[]` 기대 | 각각 개별 검증하면 정상, 교차 비교 안 함 |
|
||||||
|
| API 응답 필드명 → 타입 정의 | API가 `thumbnailUrl`(camelCase), 타입이 `thumbnail_url`(snake_case) | TypeScript 제네릭으로 캐스팅하면 컴파일러가 못 잡음 |
|
||||||
|
| 파일 경로 → 링크 href | 페이지가 `/dashboard/create`에 있는데 링크가 `/create`로 지정 | 파일 구조와 href를 교차 비교하지 않음 |
|
||||||
|
| 상태 전이 맵 → 실제 status 업데이트 | 맵에 `generating_template → template_approved` 정의, 코드에서 전환 누락 | 맵 존재 확인만 하고, 모든 업데이트 코드를 추적하지 않음 |
|
||||||
|
| API 엔드포인트 → 프론트 훅 | API 존재하지만 대응 훅 없음 (호출 안 됨) | API 목록과 훅 목록을 1:1 매핑하지 않음 |
|
||||||
|
| 즉시 응답 → 비동기 결과 | API가 즉시 `{ status }` 반환, 프론트가 `data.failedIndices` 접근 | 동기/비동기 응답 구분 없이 타입만 확인 |
|
||||||
|
|
||||||
|
### 1-2. 왜 정적 코드 리뷰로 못 잡나
|
||||||
|
|
||||||
|
- **TypeScript 제네릭의 한계**: `fetchJson<SlideProject[]>()` — 런타임 응답이 `{ projects: [...] }`여도 컴파일 통과
|
||||||
|
- **`npm run build` 통과 ≠ 정상 동작**: 타입 캐스팅, `any`, 제네릭이 사용되면 빌드는 성공하지만 런타임에 실패
|
||||||
|
- **존재 검증 vs 연결 검증의 차이**: "API가 있는가?"와 "API의 응답이 호출측의 기대와 일치하는가?"는 전혀 다른 검증
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. 통합 정합성 검증 (Integration Coherence Verification)
|
||||||
|
|
||||||
|
QA 에이전트에 반드시 포함해야 하는 **교차 비교 검증** 영역.
|
||||||
|
|
||||||
|
### 2-1. API 응답 ↔ 프론트 훅 타입 교차 검증
|
||||||
|
|
||||||
|
**방법**: 각 API route의 `NextResponse.json()` 호출부와 대응 훅의 `fetchJson<T>` 타입 파라미터를 비교.
|
||||||
|
|
||||||
|
```
|
||||||
|
검증 단계:
|
||||||
|
1. API route에서 NextResponse.json()에 전달하는 객체의 shape 추출
|
||||||
|
2. 대응 훅에서 fetchJson<T>의 T 타입 확인
|
||||||
|
3. shape과 T가 일치하는지 비교
|
||||||
|
4. 래핑 여부 확인 (API가 { data: [...] }를 반환하면 훅이 .data를 꺼내는지)
|
||||||
|
```
|
||||||
|
|
||||||
|
**특히 주의할 패턴:**
|
||||||
|
- 페이지네이션 API: `{ items: [], total, page }` vs 프론트가 배열 기대
|
||||||
|
- snake_case DB 필드 → camelCase API 응답 → 프론트 타입 정의 간 불일치
|
||||||
|
- 즉시 응답 (202 Accepted) vs 최종 결과의 shape 차이
|
||||||
|
|
||||||
|
### 2-2. 파일 경로 ↔ 링크/라우터 경로 매핑
|
||||||
|
|
||||||
|
**방법**: `src/app/` 하위 page 파일의 URL 경로를 추출하고, 코드 내 모든 `href`, `router.push()`, `redirect()` 값과 대조.
|
||||||
|
|
||||||
|
```
|
||||||
|
검증 단계:
|
||||||
|
1. src/app/ 하위 page.tsx 파일 경로에서 URL 패턴 추출
|
||||||
|
- (group) → URL에서 제거
|
||||||
|
- [param] → 동적 세그먼트
|
||||||
|
2. 코드 내 모든 href=, router.push(, redirect( 값 수집
|
||||||
|
3. 각 링크가 실제 존재하는 page 경로와 매칭되는지 확인
|
||||||
|
4. route group 내부 페이지의 URL 접두사 주의 (예: dashboard/ 하위)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2-3. 상태 전이 완전성 추적
|
||||||
|
|
||||||
|
**방법**: 코드에서 모든 `status:` 업데이트를 추출하여 상태 전이 맵과 대조.
|
||||||
|
|
||||||
|
```
|
||||||
|
검증 단계:
|
||||||
|
1. 상태 전이 맵(STATE_TRANSITIONS)에서 허용된 전이 목록 추출
|
||||||
|
2. 모든 API route에서 .update({ status: "..." }) 패턴 검색
|
||||||
|
3. 각 전이가 맵에 정의되어 있는지 확인
|
||||||
|
4. 맵에 정의된 전이 중 코드에서 실행되지 않는 것 식별 (죽은 전이)
|
||||||
|
5. 특히: 중간 상태(예: generating_template)에서 최종 상태(template_approved)로의 전환이 누락되지 않았는지
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2-4. API 엔드포인트 ↔ 프론트 훅 1:1 매핑
|
||||||
|
|
||||||
|
**방법**: 모든 API route와 프론트 훅을 나열하여 짝이 맞는지 확인.
|
||||||
|
|
||||||
|
```
|
||||||
|
검증 단계:
|
||||||
|
1. src/app/api/ 하위 route.ts에서 HTTP 메서드별 엔드포인트 목록 추출
|
||||||
|
2. src/hooks/ 하위 use*.ts에서 fetch 호출 URL 목록 추출
|
||||||
|
3. API 엔드포인트 중 훅에서 호출하지 않는 것 식별 → "사용 안 됨" 플래그
|
||||||
|
4. "사용 안 됨"이 의도적인지 (관리 API 등) 아닌지 (호출 누락) 판단
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. QA 에이전트 설계 원칙
|
||||||
|
|
||||||
|
### 3-1. Explore 타입이 아닌 general-purpose 타입을 사용하라
|
||||||
|
|
||||||
|
QA 에이전트가 `Explore` 타입이면 읽기만 가능하다. 하지만 효과적인 QA는:
|
||||||
|
- Grep으로 패턴 검색 (모든 `NextResponse.json()` 추출)
|
||||||
|
- 스크립트 실행으로 자동 대조 (API shape vs 훅 타입)
|
||||||
|
- 필요 시 수정까지 가능
|
||||||
|
|
||||||
|
**권장**: `general-purpose` 타입으로 설정하되, 에이전트 정의에서 "검증 → 리포트 → 수정 요청" 프로토콜을 명시.
|
||||||
|
|
||||||
|
### 3-2. 체크리스트는 "존재 확인"보다 "교차 비교"를 우선하라
|
||||||
|
|
||||||
|
| 약한 체크리스트 | 강한 체크리스트 |
|
||||||
|
|---------------|---------------|
|
||||||
|
| API 엔드포인트가 존재하는가? | API 엔드포인트의 응답 shape과 대응 훅의 타입이 일치하는가? |
|
||||||
|
| 상태 전이 맵이 정의되어 있는가? | 모든 status 업데이트 코드가 맵의 전이와 일치하는가? |
|
||||||
|
| 페이지 파일이 존재하는가? | 코드 내 모든 링크가 실제 존재하는 페이지를 가리키는가? |
|
||||||
|
| TypeScript strict mode인가? | 제네릭 캐스팅으로 우회된 타입 안전성이 없는가? |
|
||||||
|
|
||||||
|
### 3-3. "양쪽을 동시에 읽어라" 원칙
|
||||||
|
|
||||||
|
QA가 경계면 버그를 잡으려면, 한쪽만 읽어선 안 된다. 반드시:
|
||||||
|
- API route **와** 대응 훅을 **같이** 읽고
|
||||||
|
- 상태 전이 맵 **와** 실제 업데이트 코드를 **같이** 읽고
|
||||||
|
- 파일 구조 **와** 링크 경로를 **같이** 읽어야 한다
|
||||||
|
|
||||||
|
에이전트 정의에 이 원칙을 명시적으로 기재하라.
|
||||||
|
|
||||||
|
### 3-4. QA는 빌드 후가 아니라, 각 모듈 완성 직후에 실행하라
|
||||||
|
|
||||||
|
오케스트레이터에서 QA를 "Phase 4: 전체 완성 후"에만 배치하면:
|
||||||
|
- 버그가 누적되어 수정 비용이 높아짐
|
||||||
|
- 초기 경계면 불일치가 후속 모듈에 전파됨
|
||||||
|
|
||||||
|
**권장 패턴**: 각 백엔드 API 완성 시 즉시 해당 API + 대응 훅의 교차 검증 수행 (incremental QA).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. 검증 체크리스트 템플릿
|
||||||
|
|
||||||
|
QA 에이전트 정의에 포함할 웹 애플리케이션용 통합 정합성 체크리스트.
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
### 통합 정합성 검증 (웹 앱)
|
||||||
|
|
||||||
|
#### API ↔ 프론트엔드 연결
|
||||||
|
- [ ] 모든 API route의 응답 shape과 대응 훅의 제네릭 타입이 일치
|
||||||
|
- [ ] 래핑된 응답({ items: [...] })은 훅에서 unwrap하는지 확인
|
||||||
|
- [ ] snake_case ↔ camelCase 변환이 일관되게 적용
|
||||||
|
- [ ] 즉시 응답(202)과 최종 결과의 shape이 프론트에서 구분되는지 확인
|
||||||
|
- [ ] 모든 API 엔드포인트에 대응하는 프론트 훅이 존재하고 실제로 호출됨
|
||||||
|
|
||||||
|
#### 라우팅 정합성
|
||||||
|
- [ ] 코드 내 모든 href/router.push 값이 실제 page 파일 경로와 매칭
|
||||||
|
- [ ] route group ((group))이 URL에서 제거되는 것을 고려한 경로 검증
|
||||||
|
- [ ] 동적 세그먼트([id])가 올바른 파라미터로 채워지는지 확인
|
||||||
|
|
||||||
|
#### 상태 머신 정합성
|
||||||
|
- [ ] 정의된 모든 상태 전이가 코드에서 실행됨 (죽은 전이 없음)
|
||||||
|
- [ ] 코드의 모든 status 업데이트가 전이 맵에 정의됨 (무단 전이 없음)
|
||||||
|
- [ ] 중간 상태에서 최종 상태로의 전환이 누락되지 않음
|
||||||
|
- [ ] 프론트에서 상태 기반 분기(if status === "X")의 X가 실제 도달 가능
|
||||||
|
|
||||||
|
#### 데이터 흐름 정합성
|
||||||
|
- [ ] DB 스키마 필드명과 API 응답 필드명의 매핑이 일관됨
|
||||||
|
- [ ] 프론트 타입 정의와 API 응답의 필드명이 일치
|
||||||
|
- [ ] 옵셔널 필드에 대한 null/undefined 처리가 양쪽에서 일관됨
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. QA 에이전트 정의 템플릿
|
||||||
|
|
||||||
|
빌드 하네스의 QA 에이전트에 포함할 핵심 섹션.
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
---
|
||||||
|
name: qa-inspector
|
||||||
|
description: "QA 검증 전문가. 스펙 준수, 통합 정합성, 디자인 품질을 검증."
|
||||||
|
---
|
||||||
|
|
||||||
|
# QA Inspector
|
||||||
|
|
||||||
|
## 핵심 역할
|
||||||
|
스펙 대비 구현 품질과 **모듈 간 통합 정합성**을 검증한다.
|
||||||
|
|
||||||
|
## 검증 우선순위
|
||||||
|
|
||||||
|
1. **통합 정합성** (가장 높음) — 경계면 불일치가 런타임 에러의 주요 원인
|
||||||
|
2. **기능 스펙 준수** — API/상태머신/데이터모델
|
||||||
|
3. **디자인 품질** — 색상/타이포/반응형
|
||||||
|
4. **코드 품질** — 미사용 코드, 명명 규칙
|
||||||
|
|
||||||
|
## 검증 방법: "양쪽 동시 읽기"
|
||||||
|
|
||||||
|
경계면 검증은 반드시 **양쪽 코드를 동시에 열어** 비교한다:
|
||||||
|
|
||||||
|
| 검증 대상 | 왼쪽 (생산자) | 오른쪽 (소비자) |
|
||||||
|
|----------|-------------|---------------|
|
||||||
|
| API 응답 shape | route.ts의 NextResponse.json() | hooks/의 fetchJson<T> |
|
||||||
|
| 라우팅 | src/app/ page 파일 경로 | href, router.push 값 |
|
||||||
|
| 상태 전이 | STATE_TRANSITIONS 맵 | .update({ status }) 코드 |
|
||||||
|
| DB → API → UI | 테이블 컬럼명 | API 응답 필드 → 타입 정의 |
|
||||||
|
|
||||||
|
## 팀 통신 프로토콜
|
||||||
|
|
||||||
|
- 발견 즉시 해당 에이전트에게 구체적 수정 요청 (파일:라인 + 수정 방법)
|
||||||
|
- 경계면 이슈는 양쪽 에이전트 **모두**에게 알림
|
||||||
|
- 리더에게: 검증 리포트 (통과/실패/미검증 항목 구분)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 실제 사례: SatangSlide에서 발견된 버그
|
||||||
|
|
||||||
|
이 가이드의 모든 내용은 아래 실제 버그에서 추출한 교훈이다:
|
||||||
|
|
||||||
|
| 버그 | 경계면 | 원인 |
|
||||||
|
|------|--------|------|
|
||||||
|
| `projects?.filter is not a function` | API→훅 | API가 `{projects:[]}` 반환, 훅이 배열 기대 |
|
||||||
|
| 대시보드 모든 링크 404 | 파일경로→href | `/dashboard/` 접두사 누락 |
|
||||||
|
| 테마 이미지 안 보임 | API→컴포넌트 | `thumbnailUrl` vs `thumbnail_url` |
|
||||||
|
| 테마 선택 저장 안 됨 | API→훅 | select-theme API 존재, 훅 없음 |
|
||||||
|
| 생성 페이지 영원히 대기 | 상태전이→코드 | `template_approved` 전이 코드 누락 |
|
||||||
|
| `data.failedIndices` 크래시 | 즉시응답→프론트 | 백그라운드 결과를 즉시 응답에서 접근 |
|
||||||
|
| 완료 후 슬라이드 보기 404 | 파일경로→href | `/projects/` → `/dashboard/projects/` |
|
||||||
307
skills/harness/references/skill-testing-guide.md
Normal file
307
skills/harness/references/skill-testing-guide.md
Normal file
@ -0,0 +1,307 @@
|
|||||||
|
# 스킬 테스트 & 반복 개선 가이드
|
||||||
|
|
||||||
|
하네스에서 생성한 스킬의 품질을 검증하고 반복적으로 개선하는 방법론. SKILL.md Phase 6의 보충 레퍼런스.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 목차
|
||||||
|
|
||||||
|
1. [테스트 프레임워크 개요](#1-테스트-프레임워크-개요)
|
||||||
|
2. [테스트 프롬프트 작성법](#2-테스트-프롬프트-작성법)
|
||||||
|
3. [실행 테스트: With-skill vs Baseline](#3-실행-테스트-with-skill-vs-baseline)
|
||||||
|
4. [정량적 평가: Assertion 기반 채점](#4-정량적-평가-assertion-기반-채점)
|
||||||
|
5. [전문 에이전트 활용](#5-전문-에이전트-활용)
|
||||||
|
6. [반복 개선 루프](#6-반복-개선-루프)
|
||||||
|
7. [Description 트리거 검증](#7-description-트리거-검증)
|
||||||
|
8. [워크스페이스 구조](#8-워크스페이스-구조)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. 테스트 프레임워크 개요
|
||||||
|
|
||||||
|
스킬 품질 검증은 **정성적 평가**와 **정량적 평가**의 조합이다.
|
||||||
|
|
||||||
|
| 평가 유형 | 방법 | 적합한 스킬 |
|
||||||
|
|----------|------|-----------|
|
||||||
|
| **정성적** | 사용자가 산출물을 직접 리뷰 | 문체, 디자인, 창작물 등 주관적 품질 |
|
||||||
|
| **정량적** | assertion 기반 자동 채점 | 파일 생성, 데이터 추출, 코드 생성 등 객관적 검증 가능 |
|
||||||
|
|
||||||
|
핵심 루프: **작성 → 테스트 실행 → 평가 → 개선 → 재테스트**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. 테스트 프롬프트 작성법
|
||||||
|
|
||||||
|
### 원칙
|
||||||
|
|
||||||
|
테스트 프롬프트는 **실제 사용자가 입력할 법한 구체적이고 자연스러운 문장**이어야 한다. 추상적이거나 인공적인 프롬프트는 테스트 가치가 낮다.
|
||||||
|
|
||||||
|
### 나쁜 예
|
||||||
|
|
||||||
|
```
|
||||||
|
"PDF를 처리하라"
|
||||||
|
"데이터를 추출하라"
|
||||||
|
"차트를 생성하라"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 좋은 예
|
||||||
|
|
||||||
|
```
|
||||||
|
"다운로드 폴더에 있는 'Q4_매출_최종_v2.xlsx'에서 C열(매출)과 D열(비용)을
|
||||||
|
사용해서 이익률(%) 열을 추가해줘. 그리고 이익률 기준으로 내림차순 정렬."
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
"이 PDF에서 3페이지 표를 추출해서 CSV로 변환해줘. 표 헤더가 2줄로
|
||||||
|
되어 있어서 첫 번째 줄은 카테고리, 두 번째 줄이 실제 열 이름이야."
|
||||||
|
```
|
||||||
|
|
||||||
|
### 프롬프트 다양성
|
||||||
|
|
||||||
|
- **공식적 / 캐주얼** 톤 혼합
|
||||||
|
- **명시적 / 암시적** 의도 혼합 (파일 형식을 직접 말하는 경우 vs 맥락으로 추론해야 하는 경우)
|
||||||
|
- **단순 / 복잡** 작업 혼합
|
||||||
|
- 일부는 약어, 오타, 캐주얼한 표현 포함
|
||||||
|
|
||||||
|
### 커버리지
|
||||||
|
|
||||||
|
2~3개 프롬프트로 시작하되, 다음을 커버하도록 설계:
|
||||||
|
- 핵심 사용 사례 1개
|
||||||
|
- 엣지 케이스 1개
|
||||||
|
- (선택) 복합 작업 1개
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. 실행 테스트: With-skill vs Baseline
|
||||||
|
|
||||||
|
### 3-1. 비교 실행 구조
|
||||||
|
|
||||||
|
각 테스트 프롬프트에 대해 두 개의 서브에이전트를 **동시에** 스폰한다:
|
||||||
|
|
||||||
|
**With-skill 실행:**
|
||||||
|
```
|
||||||
|
프롬프트: "{테스트 프롬프트}"
|
||||||
|
스킬 경로: {스킬 경로}
|
||||||
|
출력 경로: _workspace/iteration-N/eval-{id}/with_skill/outputs/
|
||||||
|
```
|
||||||
|
|
||||||
|
**Baseline 실행:**
|
||||||
|
```
|
||||||
|
프롬프트: "{테스트 프롬프트}" (동일)
|
||||||
|
스킬: 없음
|
||||||
|
출력 경로: _workspace/iteration-N/eval-{id}/without_skill/outputs/
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3-2. Baseline 선택
|
||||||
|
|
||||||
|
| 상황 | Baseline |
|
||||||
|
|------|----------|
|
||||||
|
| 새 스킬 생성 | 스킬 없이 같은 프롬프트 실행 |
|
||||||
|
| 기존 스킬 개선 | 수정 전 스킬 버전 (스냅샷 보존) |
|
||||||
|
|
||||||
|
### 3-3. 타이밍 데이터 캡처
|
||||||
|
|
||||||
|
서브에이전트 완료 알림에서 `total_tokens`와 `duration_ms`를 **즉시** 저장한다. 이 데이터는 알림 시점에만 접근 가능하고 이후 복구할 수 없다.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"total_tokens": 84852,
|
||||||
|
"duration_ms": 23332,
|
||||||
|
"total_duration_seconds": 23.3
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. 정량적 평가: Assertion 기반 채점
|
||||||
|
|
||||||
|
### 4-1. Assertion 작성
|
||||||
|
|
||||||
|
산출물이 객관적으로 검증 가능한 경우, 자동 채점을 위한 assertion을 정의한다.
|
||||||
|
|
||||||
|
**좋은 assertion:**
|
||||||
|
- 객관적으로 참/거짓 판별 가능
|
||||||
|
- 서술적인 이름으로 결과만 봐도 무엇을 검사하는지 명확
|
||||||
|
- 스킬의 핵심 가치를 검증
|
||||||
|
|
||||||
|
**나쁜 assertion:**
|
||||||
|
- 스킬 유무와 무관하게 항상 통과하는 것 (예: "출력이 존재한다")
|
||||||
|
- 주관적 판단이 필요한 것 (예: "잘 작성되었다")
|
||||||
|
|
||||||
|
### 4-2. 프로그래밍 가능한 검증
|
||||||
|
|
||||||
|
assertion이 코드로 검증 가능하면 스크립트로 작성한다. 눈으로 확인하는 것보다 빠르고 신뢰성 있으며, iteration마다 재사용 가능.
|
||||||
|
|
||||||
|
### 4-3. Non-discriminating assertion 주의
|
||||||
|
|
||||||
|
"두 구성 모두에서 100% 통과"하는 assertion은 스킬의 차별적 가치를 측정하지 못한다. 이런 assertion을 발견하면 제거하거나, 더 도전적인 assertion으로 교체한다.
|
||||||
|
|
||||||
|
### 4-4. 채점 결과 스키마
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"expectations": [
|
||||||
|
{
|
||||||
|
"text": "이익률 열이 추가됨",
|
||||||
|
"passed": true,
|
||||||
|
"evidence": "E열에 'profit_margin_pct' 열 확인"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "이익률 기준 내림차순 정렬",
|
||||||
|
"passed": false,
|
||||||
|
"evidence": "정렬 없이 원본 순서 유지됨"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"summary": {
|
||||||
|
"passed": 1,
|
||||||
|
"failed": 1,
|
||||||
|
"total": 2,
|
||||||
|
"pass_rate": 0.50
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. 전문 에이전트 활용
|
||||||
|
|
||||||
|
테스트/평가 과정에서 전문 역할의 에이전트를 활용하면 품질이 향상된다.
|
||||||
|
|
||||||
|
### 5-1. Grader (채점자)
|
||||||
|
|
||||||
|
assertion 기반 채점을 수행하고, 산출물에서 검증 가능한 주장(claim)을 추출하여 교차 검증한다.
|
||||||
|
|
||||||
|
**역할:**
|
||||||
|
- assertion별 통과/실패 판정 + 근거 제시
|
||||||
|
- 산출물에서 사실적 주장을 추출하고 검증
|
||||||
|
- eval 자체의 품질에 대한 피드백 (assertion이 너무 쉽거나 모호한 경우 제안)
|
||||||
|
|
||||||
|
### 5-2. Comparator (블라인드 비교자)
|
||||||
|
|
||||||
|
두 산출물을 A/B로 익명화하여, 어떤 것이 스킬을 사용한 결과인지 모르는 상태에서 품질을 판정한다.
|
||||||
|
|
||||||
|
**활용 시점:** "새 버전이 정말 더 나은가?"를 엄밀하게 확인하고 싶을 때. 일반적인 반복 개선에서는 생략 가능.
|
||||||
|
|
||||||
|
**판정 기준:**
|
||||||
|
- 내용: 정확성, 완성도
|
||||||
|
- 구조: 조직화, 포맷팅, 사용성
|
||||||
|
- 종합 점수
|
||||||
|
|
||||||
|
### 5-3. Analyzer (분석자)
|
||||||
|
|
||||||
|
벤치마크 데이터에서 통계적 패턴을 분석한다:
|
||||||
|
- Non-discriminating assertion (두 구성 모두 통과 → 차별력 없음)
|
||||||
|
- 고분산 eval (결과가 실행마다 크게 달라짐 → 불안정)
|
||||||
|
- 시간/토큰 트레이드오프 (스킬이 품질은 높이지만 비용도 높이는 경우)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. 반복 개선 루프
|
||||||
|
|
||||||
|
### 6-1. 피드백 수집
|
||||||
|
|
||||||
|
사용자에게 산출물을 보여주고 피드백을 받는다. 빈 피드백은 "이상 없음"으로 해석한다.
|
||||||
|
|
||||||
|
### 6-2. 개선 원칙
|
||||||
|
|
||||||
|
1. **피드백을 일반화하라** — 테스트 예시에만 맞는 좁은 수정은 오버피팅이다. 원리 수준에서 수정한다.
|
||||||
|
2. **무게를 벌지 않는 것은 제거하라** — 트랜스크립트를 읽고, 스킬이 에이전트에게 비생산적인 작업을 시키고 있다면 해당 부분을 삭제한다.
|
||||||
|
3. **Why를 설명하라** — 사용자의 피드백이 간결하더라도, 왜 그것이 중요한지 이해하고 그 이해를 스킬에 반영한다.
|
||||||
|
4. **반복 작업은 번들링하라** — 모든 테스트 실행에서 동일한 헬퍼 스크립트가 생성되면, `scripts/`에 미리 포함한다.
|
||||||
|
|
||||||
|
### 6-3. 반복 절차
|
||||||
|
|
||||||
|
```
|
||||||
|
1. 스킬 수정
|
||||||
|
2. 새 iteration-N+1/ 디렉토리에 모든 테스트 케이스 재실행
|
||||||
|
3. 사용자에게 결과 제시 (이전 iteration과 비교)
|
||||||
|
4. 피드백 수집
|
||||||
|
5. 다시 수정 → 반복
|
||||||
|
```
|
||||||
|
|
||||||
|
**종료 조건:**
|
||||||
|
- 사용자가 만족
|
||||||
|
- 피드백이 모두 비어 있음 (모든 산출물 이상 없음)
|
||||||
|
- 의미 있는 개선이 더 이상 없음
|
||||||
|
|
||||||
|
### 6-4. 초안 → 재검토 패턴
|
||||||
|
|
||||||
|
스킬 수정 시, 초안을 작성한 후 **새로운 시각으로 다시 읽고** 개선한다. 한 번에 완벽하게 쓰려 하지 말고, 초안-검토 사이클을 거친다.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Description 트리거 검증
|
||||||
|
|
||||||
|
### 7-1. 트리거 Eval 쿼리 작성
|
||||||
|
|
||||||
|
20개의 eval 쿼리를 작성한다 — should-trigger 10개 + should-NOT-trigger 10개.
|
||||||
|
|
||||||
|
**쿼리 품질 기준:**
|
||||||
|
- 실제 사용자가 입력할 법한 구체적이고 자연스러운 문장
|
||||||
|
- 파일 경로, 개인적 맥락, 열 이름, 회사명 등 구체적 디테일 포함
|
||||||
|
- 길이, 톤, 형식 다양하게 혼합
|
||||||
|
- 명확한 정답보다 **경계 케이스(edge case)**에 집중
|
||||||
|
|
||||||
|
**Should-trigger 쿼리 (8~10개):**
|
||||||
|
- 다양한 표현의 같은 의도 (공식적/캐주얼)
|
||||||
|
- 스킬/파일 유형을 명시적으로 말하지 않지만 분명히 필요한 경우
|
||||||
|
- 비주류 사용 사례
|
||||||
|
- 다른 스킬과 경쟁하지만 이 스킬이 이겨야 하는 경우
|
||||||
|
|
||||||
|
**Should-NOT-trigger 쿼리 (8~10개):**
|
||||||
|
- **Near-miss가 핵심** — 키워드가 유사하지만 다른 도구/스킬이 적합한 쿼리
|
||||||
|
- 명백히 무관한 쿼리("피보나치 함수 작성")는 테스트 가치 없음
|
||||||
|
- 인접 도메인, 모호한 표현, 키워드 겹침 but 맥락이 다른 경우
|
||||||
|
|
||||||
|
### 7-2. 기존 스킬 충돌 검증
|
||||||
|
|
||||||
|
새 스킬의 description이 기존 스킬의 트리거 영역과 겹치지 않는지 확인한다:
|
||||||
|
|
||||||
|
1. 기존 스킬 목록의 description을 수집
|
||||||
|
2. 새 스킬의 should-trigger 쿼리가 기존 스킬을 잘못 트리거하지 않는지 확인
|
||||||
|
3. 충돌 발견 시 description의 경계 조건을 더 명확히 기술
|
||||||
|
|
||||||
|
### 7-3. 자동 최적화 (선택적 고급 기능)
|
||||||
|
|
||||||
|
description 최적화가 필요한 경우:
|
||||||
|
|
||||||
|
1. 20개 eval 쿼리를 Train(60%) / Test(40%) split
|
||||||
|
2. 현재 description으로 트리거 정확도 측정
|
||||||
|
3. 실패 케이스를 분석하여 개선된 description 생성
|
||||||
|
4. Test set 기준으로 best description 선택 (Train set 기준이 아님 — 과적합 방지)
|
||||||
|
5. 최대 5회 반복
|
||||||
|
|
||||||
|
> 이 과정은 `claude -p`를 사용하는 자동화 스크립트로 수행한다. 토큰 비용이 높으므로 스킬이 충분히 안정화된 후 최종 단계에서 실행한다.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. 워크스페이스 구조
|
||||||
|
|
||||||
|
테스트/평가 결과를 체계적으로 관리하는 디렉토리 구조:
|
||||||
|
|
||||||
|
```
|
||||||
|
{skill-name}-workspace/
|
||||||
|
├── iteration-1/
|
||||||
|
│ ├── eval-descriptive-name-1/
|
||||||
|
│ │ ├── eval_metadata.json
|
||||||
|
│ │ ├── with_skill/
|
||||||
|
│ │ │ ├── outputs/
|
||||||
|
│ │ │ ├── timing.json
|
||||||
|
│ │ │ └── grading.json
|
||||||
|
│ │ └── without_skill/
|
||||||
|
│ │ ├── outputs/
|
||||||
|
│ │ ├── timing.json
|
||||||
|
│ │ └── grading.json
|
||||||
|
│ ├── eval-descriptive-name-2/
|
||||||
|
│ │ └── ...
|
||||||
|
│ └── benchmark.json
|
||||||
|
├── iteration-2/
|
||||||
|
│ └── ...
|
||||||
|
└── evals/
|
||||||
|
└── evals.json
|
||||||
|
```
|
||||||
|
|
||||||
|
**규칙:**
|
||||||
|
- eval 디렉토리는 숫자가 아닌 **서술적 이름** 사용 (예: `eval-multi-page-table-extraction`)
|
||||||
|
- 각 iteration은 독립 디렉토리에 보존 (이전 iteration 덮어쓰기 금지)
|
||||||
|
- `_workspace/`는 삭제하지 않음 — 사후 검증 및 감사 추적용
|
||||||
298
skills/harness/references/skill-writing-guide.md
Normal file
298
skills/harness/references/skill-writing-guide.md
Normal file
@ -0,0 +1,298 @@
|
|||||||
|
# 스킬 작성 가이드
|
||||||
|
|
||||||
|
하네스에서 생성하는 스킬의 품질을 높이기 위한 상세 작성 가이드. SKILL.md Phase 4의 보충 레퍼런스.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 목차
|
||||||
|
|
||||||
|
1. [Description 작성 패턴](#1-description-작성-패턴)
|
||||||
|
2. [본문 작성 스타일](#2-본문-작성-스타일)
|
||||||
|
3. [출력 형식 정의 패턴](#3-출력-형식-정의-패턴)
|
||||||
|
4. [예시 작성 패턴](#4-예시-작성-패턴)
|
||||||
|
5. [Progressive Disclosure 패턴](#5-progressive-disclosure-패턴)
|
||||||
|
6. [스크립트 번들링 판단 기준](#6-스크립트-번들링-판단-기준)
|
||||||
|
7. [데이터 스키마 표준](#7-데이터-스키마-표준)
|
||||||
|
8. [스킬에 포함하지 않을 것](#8-스킬에-포함하지-않을-것)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Description 작성 패턴
|
||||||
|
|
||||||
|
Description은 스킬의 유일한 트리거 메커니즘이다. Claude는 `available_skills` 목록에서 name + description만 보고 스킬 사용 여부를 결정한다.
|
||||||
|
|
||||||
|
### 트리거 메커니즘 이해
|
||||||
|
|
||||||
|
Claude는 자신의 기본 도구로 쉽게 처리할 수 있는 단순 작업에는 스킬을 호출하지 않는 경향이 있다. "이 PDF 읽어줘" 같은 단순 요청은 description이 완벽해도 트리거되지 않을 수 있다. 복잡하고 다단계이며 전문적인 작업일수록 스킬 트리거 확률이 높다.
|
||||||
|
|
||||||
|
### 작성 원칙
|
||||||
|
|
||||||
|
1. **스킬이 하는 일** + **구체적 트리거 상황**을 모두 기술
|
||||||
|
2. 유사하지만 트리거하면 안 되는 경우를 구분하는 경계 조건 명시
|
||||||
|
3. 약간 "pushy"하게 — Claude가 트리거를 보수적으로 판단하는 경향을 보상
|
||||||
|
|
||||||
|
### 좋은 예시
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
description: "PDF 파일 읽기, 텍스트/테이블 추출, 병합, 분할, 회전, 워터마크,
|
||||||
|
암호화/복호화, OCR 등 모든 PDF 작업을 수행. .pdf 파일을 언급하거나
|
||||||
|
PDF 산출물을 요청하면 반드시 이 스킬을 사용할 것. 단순히 PDF를
|
||||||
|
'읽어달라'는 요청이 아닌 변환/편집/분석이 필요할 때 특히 유용."
|
||||||
|
```
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
description: "엑셀/CSV/TSV 파일의 열 추가, 수식 계산, 서식, 차트,
|
||||||
|
데이터 정제를 포함한 모든 스프레드시트 작업. 사용자가 스프레드시트
|
||||||
|
파일을 언급하면 — 심지어 캐주얼하게('다운로드 폴더의 xlsx')라고만
|
||||||
|
해도 — 이 스킬을 사용할 것."
|
||||||
|
```
|
||||||
|
|
||||||
|
### 나쁜 예시
|
||||||
|
|
||||||
|
- `"데이터를 처리하는 스킬"` — 너무 모호, 어떤 파일/작업인지 불분명
|
||||||
|
- `"PDF 관련 작업"` — 구체적 동작 나열 없음, 트리거 상황 미기술
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. 본문 작성 스타일
|
||||||
|
|
||||||
|
### Why-First 원칙
|
||||||
|
|
||||||
|
LLM은 이유를 이해하면 엣지 케이스에서도 올바르게 판단한다. 강압적 규칙보다 맥락 전달이 효과적이다.
|
||||||
|
|
||||||
|
**나쁜 예:**
|
||||||
|
```markdown
|
||||||
|
ALWAYS use pdfplumber for table extraction. NEVER use PyPDF2 for tables.
|
||||||
|
```
|
||||||
|
|
||||||
|
**좋은 예:**
|
||||||
|
```markdown
|
||||||
|
테이블 추출에는 pdfplumber를 사용한다. PyPDF2는 텍스트 추출에 특화되어
|
||||||
|
있어 테이블의 행/열 구조를 보존하지 못하기 때문이다. pdfplumber는
|
||||||
|
셀 경계를 인식하여 구조화된 데이터를 반환한다.
|
||||||
|
```
|
||||||
|
|
||||||
|
### 일반화 원칙
|
||||||
|
|
||||||
|
피드백이나 테스트 결과에서 문제가 발견되면, 특정 예시에만 맞는 좁은 수정 대신 **원리 수준에서 일반화**한다.
|
||||||
|
|
||||||
|
**오버피팅 수정:**
|
||||||
|
```markdown
|
||||||
|
"Q4 매출" 열이 있으면 해당 열을 숫자로 변환하라.
|
||||||
|
```
|
||||||
|
|
||||||
|
**일반화된 수정:**
|
||||||
|
```markdown
|
||||||
|
열 이름에 "매출", "금액", "수량" 등 수치를 암시하는 키워드가 있으면
|
||||||
|
해당 열을 숫자 타입으로 변환한다. 변환 실패 시 원본 값을 유지한다.
|
||||||
|
```
|
||||||
|
|
||||||
|
### 명령형 어조
|
||||||
|
|
||||||
|
"~합니다", "~할 수 있습니다" 대신 "~한다", "~하라" 형태를 사용한다. 스킬은 지시서이다.
|
||||||
|
|
||||||
|
### 컨텍스트 절약
|
||||||
|
|
||||||
|
컨텍스트 윈도우는 공공재다. 모든 문장이 토큰 비용을 정당화하는지 자문한다:
|
||||||
|
- "Claude가 이미 알고 있는 내용인가?" → 삭제
|
||||||
|
- "이 설명이 없으면 Claude가 실수하는가?" → 유지
|
||||||
|
- "구체적 예시 하나가 긴 설명보다 효과적인가?" → 예시로 대체
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. 출력 형식 정의 패턴
|
||||||
|
|
||||||
|
산출물의 형식이 중요한 스킬에서 사용:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
## 보고서 구조
|
||||||
|
다음 템플릿을 정확히 따른다:
|
||||||
|
|
||||||
|
# [제목]
|
||||||
|
## 요약
|
||||||
|
## 핵심 발견
|
||||||
|
## 권장 사항
|
||||||
|
```
|
||||||
|
|
||||||
|
형식 정의는 간결하게, 실제 예시를 포함하면 더 효과적이다.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. 예시 작성 패턴
|
||||||
|
|
||||||
|
예시는 긴 설명보다 효과적이다:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
## 커밋 메시지 형식
|
||||||
|
|
||||||
|
**예시 1:**
|
||||||
|
입력: JWT 토큰 기반 사용자 인증 추가
|
||||||
|
출력: feat(auth): JWT 기반 인증 구현
|
||||||
|
|
||||||
|
**예시 2:**
|
||||||
|
입력: 로그인 페이지에서 비밀번호 표시 버튼이 동작하지 않는 버그 수정
|
||||||
|
출력: fix(login): 비밀번호 표시 토글 버튼 동작 수정
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Progressive Disclosure 패턴
|
||||||
|
|
||||||
|
### 패턴 1: 도메인별 분리
|
||||||
|
|
||||||
|
```
|
||||||
|
bigquery-skill/
|
||||||
|
├── SKILL.md (개요 + 도메인 선택 가이드)
|
||||||
|
└── references/
|
||||||
|
├── finance.md (매출, 빌링 메트릭)
|
||||||
|
├── sales.md (기회, 파이프라인)
|
||||||
|
└── product.md (API 사용량, 기능)
|
||||||
|
```
|
||||||
|
|
||||||
|
사용자가 매출에 대해 물으면 finance.md만 로드.
|
||||||
|
|
||||||
|
### 패턴 2: 조건부 상세
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
# DOCX 처리
|
||||||
|
|
||||||
|
## 문서 생성
|
||||||
|
docx-js로 새 문서를 생성한다. → [DOCX-JS.md](references/docx-js.md) 참조.
|
||||||
|
|
||||||
|
## 문서 편집
|
||||||
|
단순 편집은 XML을 직접 수정.
|
||||||
|
**추적 변경이 필요하면**: [REDLINING.md](references/redlining.md) 참조
|
||||||
|
```
|
||||||
|
|
||||||
|
### 패턴 3: 대형 레퍼런스 파일 구조
|
||||||
|
|
||||||
|
300줄 이상의 reference 파일은 상단에 목차를 포함한다:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
# API 레퍼런스
|
||||||
|
|
||||||
|
## 목차
|
||||||
|
1. [인증](#인증)
|
||||||
|
2. [엔드포인트 목록](#엔드포인트-목록)
|
||||||
|
3. [에러 코드](#에러-코드)
|
||||||
|
4. [레이트 리밋](#레이트-리밋)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 인증
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. 스크립트 번들링 판단 기준
|
||||||
|
|
||||||
|
테스트 실행에서 에이전트들의 트랜스크립트를 관찰한다. 다음 패턴이 보이면 번들링 대상:
|
||||||
|
|
||||||
|
| 신호 | 조치 |
|
||||||
|
|------|------|
|
||||||
|
| 3개 테스트 중 3개에서 동일한 헬퍼 스크립트 생성 | `scripts/`에 번들링 |
|
||||||
|
| 매번 같은 pip install/npm install 실행 | 스킬에 의존성 설치 단계 명시 |
|
||||||
|
| 동일한 다단계 접근법 반복 | 스킬 본문에 표준 절차로 기술 |
|
||||||
|
| 매번 비슷한 에러 후 같은 회피책 적용 | 스킬에 알려진 문제와 해결법 기술 |
|
||||||
|
|
||||||
|
번들링된 스크립트는 반드시 실행 테스트를 거친다.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. 데이터 스키마 표준
|
||||||
|
|
||||||
|
스킬 간 데이터 교환의 일관성을 위해 표준 스키마를 사용한다. 하네스에서 생성하는 스킬의 테스트/평가에 사용할 수 있다.
|
||||||
|
|
||||||
|
### eval_metadata.json
|
||||||
|
|
||||||
|
각 테스트 케이스의 메타데이터:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"eval_id": 0,
|
||||||
|
"eval_name": "descriptive-name-here",
|
||||||
|
"prompt": "사용자의 작업 프롬프트",
|
||||||
|
"assertions": [
|
||||||
|
"산출물에 X가 포함되어 있다",
|
||||||
|
"Y 형식으로 파일이 생성되었다"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### grading.json
|
||||||
|
|
||||||
|
assertion 기반 채점 결과:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"expectations": [
|
||||||
|
{
|
||||||
|
"text": "산출물에 '서울'이 포함됨",
|
||||||
|
"passed": true,
|
||||||
|
"evidence": "3번째 단계에서 '서울 지역 데이터 추출' 확인"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"summary": {
|
||||||
|
"passed": 2,
|
||||||
|
"failed": 1,
|
||||||
|
"total": 3,
|
||||||
|
"pass_rate": 0.67
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**필드명 주의:** `text`, `passed`, `evidence`를 정확히 사용한다 (`name`/`met`/`details` 등 변형 금지).
|
||||||
|
|
||||||
|
### timing.json
|
||||||
|
|
||||||
|
실행 시간/토큰 측정:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"total_tokens": 84852,
|
||||||
|
"duration_ms": 23332,
|
||||||
|
"total_duration_seconds": 23.3
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
서브에이전트 완료 알림에서 `total_tokens`와 `duration_ms`를 즉시 저장한다. 이 데이터는 알림 시점에만 접근 가능하고 이후 복구 불가.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. 스킬에 포함하지 않을 것
|
||||||
|
|
||||||
|
- README.md, CHANGELOG.md, INSTALLATION_GUIDE.md 등 부가 문서
|
||||||
|
- 스킬 생성 과정의 메타 정보 (테스트 결과, 반복 이력)
|
||||||
|
- 사용자 대상 설명서 (스킬은 AI 에이전트를 위한 지시서)
|
||||||
|
- 이미 Claude가 알고 있는 일반적 지식
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. 스킬 재사용 설계
|
||||||
|
|
||||||
|
신규 스킬 생성 전, 기존 스킬과의 중복을 확인한다. 하네스를 반복 구축하다 보면 기능이 겹치는 스킬이 다른 이름으로 누적되기 쉽다.
|
||||||
|
|
||||||
|
| 상황 | 조치 |
|
||||||
|
|------|------|
|
||||||
|
| 기존 스킬이 신규 기능을 완전히 포함 | 신규 생성 금지 — 기존 스킬을 에이전트에 연결 |
|
||||||
|
| 기존 스킬이 부분 포함이고 일반화 가능 | 기존 스킬을 일반화하여 확장 |
|
||||||
|
| 도메인 특화가 의도된 부분 포함 | 신규 생성 진행 — 별개 스킬로 유지 |
|
||||||
|
| 기능 범위가 완전히 다름 | 신규 생성 진행 |
|
||||||
|
|
||||||
|
**원칙:** 하나의 스킬이 하나의 역할에 집중할수록 재사용성이 높고 중복이 줄어든다. 역할이 두 가지 이상이면 분리할 수 있는지 먼저 검토한다.
|
||||||
|
|
||||||
|
### 어디까지 일반화할지
|
||||||
|
|
||||||
|
일반화는 무한히 가능하므로 **의도된 책임 범위**에서 멈춘다. 의도된 도메인 특화는 유지하고, 우연한 종속만 제거한다.
|
||||||
|
|
||||||
|
예: "fintech 리스크 평가 PDF" 스킬
|
||||||
|
|
||||||
|
| 단계 | 결과 |
|
||||||
|
|------|------|
|
||||||
|
| fintech 종속 제거 | "평가 결과 PDF" — 책임 범위가 평가 리포트면 여기서 멈춤 |
|
||||||
|
| 평가 종속 제거 | "PDF 포매팅" — 이미 존재한다면 별개 스킬 생성하지 말고 재사용 |
|
||||||
|
|
||||||
|
책임 범위가 "fintech 리스크 평가"로 의도된 특화라면 일반화하지 않고 별개 스킬로 유지한다.
|
||||||
|
|
||||||
|
해당 스킬에 의존하는 에이전트의 동작이 변경될 수 있다. 확장 전 의존성을 확인하고, description에 확장된 사용 범위를 반영한다.
|
||||||
328
skills/harness/references/team-examples.md
Normal file
328
skills/harness/references/team-examples.md
Normal file
@ -0,0 +1,328 @@
|
|||||||
|
# Agent Team Examples
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 예시 1: 리서치 팀 (에이전트 팀 모드)
|
||||||
|
|
||||||
|
### 팀 아키텍처: 팬아웃/팬인
|
||||||
|
### 실행 모드: 에이전트 팀
|
||||||
|
|
||||||
|
```
|
||||||
|
[리더/오케스트레이터]
|
||||||
|
├── TeamCreate(research-team)
|
||||||
|
├── TaskCreate(4개 조사 작업)
|
||||||
|
├── 팀원들이 자체 조율 (SendMessage)
|
||||||
|
├── 결과 수집 (Read)
|
||||||
|
└── 종합 보고서 생성
|
||||||
|
```
|
||||||
|
|
||||||
|
### 에이전트 구성
|
||||||
|
|
||||||
|
| 팀원 | 에이전트 타입 | 역할 | 출력 |
|
||||||
|
|------|-------------|------|------|
|
||||||
|
| official-researcher | general-purpose | 공식 문서/블로그 | research_official.md |
|
||||||
|
| media-researcher | general-purpose | 미디어/투자 | research_media.md |
|
||||||
|
| community-researcher | general-purpose | 커뮤니티/SNS | research_community.md |
|
||||||
|
| background-researcher | general-purpose | 배경/경쟁/학술 | research_background.md |
|
||||||
|
| (리더 = 오케스트레이터) | — | 통합 보고서 | 종합보고서.md |
|
||||||
|
|
||||||
|
> 리서치 에이전트는 `general-purpose` 빌트인 타입을 사용하되, 반드시 `.claude/agents/{name}.md` 파일로 정의한다. 파일에는 역할·조사 범위·팀 통신 프로토콜을 명시하여 재사용성과 협업 품질을 보장한다.
|
||||||
|
|
||||||
|
### 오케스트레이터 워크플로우 (에이전트 팀)
|
||||||
|
|
||||||
|
```
|
||||||
|
Phase 1: 준비
|
||||||
|
- 사용자 입력 분석 (주제, 조사 모드 파악)
|
||||||
|
- _workspace/ 생성
|
||||||
|
|
||||||
|
Phase 2: 팀 구성
|
||||||
|
- TeamCreate(team_name: "research-team", members: [
|
||||||
|
{ name: "official", prompt: "공식 채널 조사..." },
|
||||||
|
{ name: "media", prompt: "미디어/투자 동향 조사..." },
|
||||||
|
{ name: "community", prompt: "커뮤니티 반응 조사..." },
|
||||||
|
{ name: "background", prompt: "배경/경쟁 환경 조사..." }
|
||||||
|
])
|
||||||
|
- TaskCreate(tasks: [
|
||||||
|
{ title: "공식 채널 조사", assignee: "official" },
|
||||||
|
{ title: "미디어 동향 조사", assignee: "media" },
|
||||||
|
{ title: "커뮤니티 반응 조사", assignee: "community" },
|
||||||
|
{ title: "배경 환경 조사", assignee: "background" }
|
||||||
|
])
|
||||||
|
|
||||||
|
Phase 3: 조사 수행
|
||||||
|
- 4명의 팀원이 독립적으로 조사
|
||||||
|
- 흥미로운 발견이 있으면 팀원 간 SendMessage로 공유
|
||||||
|
(예: media가 발견한 투자 뉴스를 background에게 전달)
|
||||||
|
- 상충 정보 발견 시 팀원 간 직접 토론
|
||||||
|
- 각 팀원은 완료 시 파일 저장 + 리더에게 알림
|
||||||
|
|
||||||
|
Phase 4: 통합
|
||||||
|
- 리더가 4개 산출물 Read
|
||||||
|
- 종합 보고서 생성
|
||||||
|
- 상충 정보는 출처 병기
|
||||||
|
|
||||||
|
Phase 5: 정리
|
||||||
|
- 팀원들 종료 요청
|
||||||
|
- 팀 정리
|
||||||
|
- _workspace/ 보존 (사후 검증·감사 추적용)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 팀 통신 패턴
|
||||||
|
|
||||||
|
```
|
||||||
|
official ──SendMessage──→ background (관련 공식 발표 공유)
|
||||||
|
media ────SendMessage──→ background (투자/인수 정보 공유)
|
||||||
|
community ─SendMessage──→ media (커뮤니티 반응 중 미디어 관련 정보)
|
||||||
|
모든 팀원 ──TaskUpdate──→ 공유 작업 목록 (진행률 업데이트)
|
||||||
|
리더 ←───── 유휴 알림 ──── 완료된 팀원 (자동)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 예시 2: SF 소설 집필 팀 (에이전트 팀 모드)
|
||||||
|
|
||||||
|
### 팀 아키텍처: 파이프라인 + 팬아웃
|
||||||
|
### 실행 모드: 에이전트 팀
|
||||||
|
|
||||||
|
```
|
||||||
|
Phase 1 (병렬 — 에이전트 팀): worldbuilder + character-designer + plot-architect
|
||||||
|
→ 서로 SendMessage로 일관성 조율
|
||||||
|
Phase 2 (순차): prose-stylist (집필)
|
||||||
|
Phase 3 (병렬 — 에이전트 팀): science-consultant + continuity-manager (리뷰)
|
||||||
|
→ 서로 SendMessage로 발견 공유
|
||||||
|
Phase 4 (순차): prose-stylist (리뷰 반영 수정)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 에이전트 구성
|
||||||
|
|
||||||
|
| 팀원 | 에이전트 타입 | 역할 | 스킬 |
|
||||||
|
|------|-------------|------|------|
|
||||||
|
| worldbuilder | 커스텀 | 세계관 구축 | world-setting |
|
||||||
|
| character-designer | 커스텀 | 캐릭터 설계 | character-profile |
|
||||||
|
| plot-architect | 커스텀 | 플롯 구조 | outline |
|
||||||
|
| prose-stylist | 커스텀 | 문체 편집 + 집필 | write-scene, review-chapter |
|
||||||
|
| science-consultant | 커스텀 | 과학 검증 | science-check |
|
||||||
|
| continuity-manager | 커스텀 | 일관성 검증 | consistency-check |
|
||||||
|
|
||||||
|
### 에이전트 파일 전문 예시: `worldbuilder.md`
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
---
|
||||||
|
name: worldbuilder
|
||||||
|
description: "SF 소설의 세계관을 구축하는 전문가. 물리 법칙, 사회 구조, 기술 수준, 역사를 설계한다."
|
||||||
|
---
|
||||||
|
|
||||||
|
# Worldbuilder — SF 세계관 설계 전문가
|
||||||
|
|
||||||
|
당신은 SF 소설의 세계관 설계 전문가입니다. 과학적 사실에 기반하되 상상력을 확장하여, 이야기가 펼쳐질 세계의 물리적·사회적·기술적 토대를 구축합니다.
|
||||||
|
|
||||||
|
## 핵심 역할
|
||||||
|
1. 세계의 물리 법칙과 기술 수준 정의
|
||||||
|
2. 사회 구조, 정치 체계, 경제 시스템 설계
|
||||||
|
3. 역사적 맥락과 현재 갈등 구조 수립
|
||||||
|
4. 장소별 환경과 분위기 묘사
|
||||||
|
|
||||||
|
## 작업 원칙
|
||||||
|
- 내적 일관성 최우선 — 설정 간 모순이 없어야 한다
|
||||||
|
- "만약 이 기술이 있다면?" 연쇄 질문으로 세계의 파급 효과를 추론
|
||||||
|
- 이야기에 봉사하는 세계관 — 플롯을 방해하는 과도한 설정은 지양
|
||||||
|
|
||||||
|
## 입력/출력 프로토콜
|
||||||
|
- 입력: 사용자의 세계관 컨셉, 장르 요구사항
|
||||||
|
- 출력: `_workspace/01_worldbuilder_setting.md`
|
||||||
|
- 형식: 마크다운. 섹션별 (물리/사회/기술/역사/장소)
|
||||||
|
|
||||||
|
## 팀 통신 프로토콜
|
||||||
|
- character-designer에게: 사회 구조, 계급 시스템, 직업군 정보 SendMessage
|
||||||
|
- plot-architect에게: 세계의 주요 갈등 구조, 위기 요소 SendMessage
|
||||||
|
- science-consultant로부터: 과학적 오류 피드백 수신 → 설정 수정
|
||||||
|
- 세계관 변경 시 관련 팀원 전체에 브로드캐스트
|
||||||
|
|
||||||
|
## 에러 핸들링
|
||||||
|
- 컨셉이 모호하면 3가지 방향을 제안하고 선택 요청
|
||||||
|
- 과학적 오류 발견 시 대안을 함께 제시
|
||||||
|
|
||||||
|
## 협업
|
||||||
|
- character-designer에게 사회 구조 정보 제공
|
||||||
|
- plot-architect에게 갈등 구조 정보 제공
|
||||||
|
- science-consultant의 피드백을 반영하여 설정 수정
|
||||||
|
```
|
||||||
|
|
||||||
|
### 팀 워크플로우 상세
|
||||||
|
|
||||||
|
```
|
||||||
|
Phase 1: TeamCreate(team_name: "novel-team", members: [worldbuilder, character-designer, plot-architect])
|
||||||
|
TaskCreate([세계관 구축, 캐릭터 설계, 플롯 구조])
|
||||||
|
→ 팀원들이 자체 조율하며 병렬 작업
|
||||||
|
→ worldbuilder가 사회 구조 완성 시 character-designer에게 SendMessage
|
||||||
|
→ character-designer가 주인공 설정 시 plot-architect에게 SendMessage
|
||||||
|
|
||||||
|
Phase 2: Phase 1 팀 정리 → prose-stylist를 서브 에이전트로 호출 (단독 집필이므로 팀 불필요)
|
||||||
|
prose-stylist가 _workspace/의 3개 산출물을 Read하여 집필
|
||||||
|
→ 결과를 _workspace/02_prose_draft.md에 저장
|
||||||
|
|
||||||
|
Phase 3: 새 팀 생성 — TeamCreate(team_name: "review-team", members: [science-consultant, continuity-manager])
|
||||||
|
(세션당 한 팀만 활성이지만, Phase 1 팀을 정리했으므로 새 팀 생성 가능)
|
||||||
|
→ 두 리뷰어가 draft를 검토, 서로 발견을 공유
|
||||||
|
→ science-consultant가 물리 오류 발견 시 continuity-manager에게도 알림
|
||||||
|
→ 리뷰 완료 후 팀 정리
|
||||||
|
|
||||||
|
Phase 4: prose-stylist를 서브 에이전트로 호출, 리뷰 결과 반영하여 최종 수정
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 예시 3: 웹툰 제작 팀 (서브 에이전트 모드)
|
||||||
|
|
||||||
|
### 팀 아키텍처: 생성-검증
|
||||||
|
### 실행 모드: 서브 에이전트
|
||||||
|
|
||||||
|
> 생성-검증 패턴에서 에이전트가 2개뿐이고, 통신보다는 결과 전달이 핵심이므로 서브 에이전트가 적합.
|
||||||
|
|
||||||
|
```
|
||||||
|
Phase 1: Agent(webtoon-artist) → 패널 생성
|
||||||
|
Phase 2: Agent(webtoon-reviewer) → 검수
|
||||||
|
Phase 3: Agent(webtoon-artist) → 문제 패널 재생성 (최대 2회)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 에이전트 구성
|
||||||
|
|
||||||
|
| 에이전트 | subagent_type | 역할 | 스킬 |
|
||||||
|
|---------|--------------|------|------|
|
||||||
|
| webtoon-artist | 커스텀 | 패널 이미지 생성 | generate-webtoon |
|
||||||
|
| webtoon-reviewer | 커스텀 | 품질 검수 | review-webtoon, fix-webtoon-panel |
|
||||||
|
|
||||||
|
### 에이전트 파일 전문 예시: `webtoon-reviewer.md`
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
---
|
||||||
|
name: webtoon-reviewer
|
||||||
|
description: "웹툰 패널의 품질을 검수하는 전문가. 구도, 캐릭터 일관성, 텍스트 가독성, 연출을 평가한다."
|
||||||
|
---
|
||||||
|
|
||||||
|
# Webtoon Reviewer — 웹툰 품질 검수 전문가
|
||||||
|
|
||||||
|
당신은 웹툰 패널의 품질을 검수하는 전문가입니다. 시각적 완성도, 스토리 전달력, 캐릭터 일관성을 기준으로 패널을 평가합니다.
|
||||||
|
|
||||||
|
## 핵심 역할
|
||||||
|
1. 각 패널의 구도와 시각적 완성도 평가
|
||||||
|
2. 캐릭터 외형의 패널 간 일관성 검증
|
||||||
|
3. 말풍선 텍스트의 가독성과 배치 평가
|
||||||
|
4. 전체 에피소드의 연출 흐름과 페이싱 검토
|
||||||
|
|
||||||
|
## 작업 원칙
|
||||||
|
- PASS/FIX/REDO 3단계로 명확히 판정
|
||||||
|
- FIX는 부분 수정으로 해결 가능한 경우, REDO는 전면 재생성 필요
|
||||||
|
- 주관적 취향이 아닌 객관적 기준(일관성, 가독성, 구도)으로 판단
|
||||||
|
|
||||||
|
## 입력/출력 프로토콜
|
||||||
|
- 입력: `_workspace/panels/` 디렉토리의 패널 이미지들
|
||||||
|
- 출력: `_workspace/review_report.md`
|
||||||
|
- 형식:
|
||||||
|
```
|
||||||
|
## Panel {N}
|
||||||
|
- 판정: PASS | FIX | REDO
|
||||||
|
- 사유: [구체적 이유]
|
||||||
|
- 수정 지시: [FIX/REDO인 경우 구체적 수정 방향]
|
||||||
|
```
|
||||||
|
|
||||||
|
## 에러 핸들링
|
||||||
|
- 이미지 로드 실패 시 해당 패널을 REDO로 판정
|
||||||
|
- 2회 재생성 후에도 REDO인 패널은 경고와 함께 PASS 처리
|
||||||
|
|
||||||
|
## 협업
|
||||||
|
- webtoon-artist에게 수정 지시서 전달 (결과 파일 기반)
|
||||||
|
- 재생성된 패널을 다시 검수 (최대 2회 루프)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 에러 핸들링
|
||||||
|
|
||||||
|
```
|
||||||
|
재시도 정책:
|
||||||
|
- REDO 판정 패널 → artist에게 재생성 요청 (구체적 수정 지시 포함)
|
||||||
|
- 최대 2회 루프 후 강제 PASS
|
||||||
|
- 전체 패널의 50% 이상이 REDO면 사용자에게 프롬프트 수정 제안
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 예시 4: 코드 리뷰 팀 (에이전트 팀 모드)
|
||||||
|
|
||||||
|
### 팀 아키텍처: 팬아웃/팬인 + 토론
|
||||||
|
### 실행 모드: 에이전트 팀
|
||||||
|
|
||||||
|
> 코드 리뷰는 에이전트 팀이 빛나는 대표적 사례. 서로 다른 관점의 리뷰어들이 발견을 공유하고 도전하면서 더 깊은 리뷰가 가능.
|
||||||
|
|
||||||
|
```
|
||||||
|
[리더] → TeamCreate(review-team)
|
||||||
|
├── security-reviewer: 보안 취약점 점검
|
||||||
|
├── performance-reviewer: 성능 영향 분석
|
||||||
|
└── test-reviewer: 테스트 커버리지 검증
|
||||||
|
→ 리뷰어들이 서로 발견 공유 (SendMessage)
|
||||||
|
→ 리더가 결과 종합
|
||||||
|
```
|
||||||
|
|
||||||
|
### 팀 통신 패턴
|
||||||
|
|
||||||
|
```
|
||||||
|
security ──SendMessage──→ performance ("이 SQL 쿼리 주입 가능, 성능 측면에서도 확인 필요")
|
||||||
|
performance ──SendMessage──→ test ("N+1 쿼리 발견, 관련 테스트 있는지 확인 부탁")
|
||||||
|
test ────SendMessage──→ security ("인증 모듈 테스트 없음, 보안 관점에서 우선순위 의견?")
|
||||||
|
```
|
||||||
|
|
||||||
|
핵심: 리뷰어들이 **리더를 거치지 않고** 직접 소통하여 교차 영역 이슈를 빠르게 포착.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 예시 5: 감독자 패턴 — 코드 마이그레이션 팀 (에이전트 팀 모드)
|
||||||
|
|
||||||
|
### 팀 아키텍처: 감독자
|
||||||
|
### 실행 모드: 에이전트 팀
|
||||||
|
|
||||||
|
```
|
||||||
|
[supervisor/리더] → 파일 목록 분석 → 배치 할당
|
||||||
|
├→ [migrator-1] (batch A)
|
||||||
|
├→ [migrator-2] (batch B)
|
||||||
|
└→ [migrator-3] (batch C)
|
||||||
|
← TaskUpdate 수신 → 추가 배치 할당 또는 재할당
|
||||||
|
```
|
||||||
|
|
||||||
|
### 에이전트 구성
|
||||||
|
|
||||||
|
| 팀원 | 역할 |
|
||||||
|
|------|------|
|
||||||
|
| (리더 = migration-supervisor) | 파일 분석, 배치 분배, 진행 관리 |
|
||||||
|
| migrator-1~3 | 할당된 파일 배치를 마이그레이션 |
|
||||||
|
|
||||||
|
### 감독자의 동적 분배 로직 (에이전트 팀 활용)
|
||||||
|
|
||||||
|
```
|
||||||
|
1. 전체 대상 파일 목록 수집
|
||||||
|
2. 복잡도 추정 (파일 크기, import 수, 의존성)
|
||||||
|
3. TaskCreate로 파일 배치를 작업으로 등록 (의존성 포함)
|
||||||
|
4. 팀원들이 자체적으로 작업 요청 (claim)
|
||||||
|
5. 팀원이 TaskUpdate로 완료 보고 시:
|
||||||
|
- 성공 → 다음 작업 자동 요청
|
||||||
|
- 실패 → 리더가 SendMessage로 원인 확인 → 재할당 또는 다른 팀원에게 배정
|
||||||
|
6. 모든 작업 완료 → 리더가 통합 테스트 실행
|
||||||
|
```
|
||||||
|
|
||||||
|
팬아웃과의 차이: 작업이 사전 고정이 아니라 **런타임에 동적으로 할당**된다. 공유 작업 목록의 자체 요청(claim) 기능이 감독자 패턴과 자연스럽게 매칭.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 산출물 패턴 요약
|
||||||
|
|
||||||
|
### 에이전트 정의 파일
|
||||||
|
위치: `프로젝트/.claude/agents/{agent-name}.md`
|
||||||
|
필수 섹션: 핵심 역할, 작업 원칙, 입력/출력 프로토콜, 에러 핸들링, 협업
|
||||||
|
팀 모드 추가 섹션: **팀 통신 프로토콜** (메시지 수신/발신, 작업 요청 범위)
|
||||||
|
|
||||||
|
### 스킬 파일 구조
|
||||||
|
위치: `프로젝트/.claude/skills/{skill-name}/SKILL.md` (프로젝트 레벨)
|
||||||
|
또는: `~/.claude/skills/{skill-name}/SKILL.md` (글로벌 레벨)
|
||||||
|
|
||||||
|
### 통합 스킬 (오케스트레이터)
|
||||||
|
팀 전체를 조율하는 상위 스킬. 시나리오별 에이전트 구성과 워크플로우를 정의.
|
||||||
|
템플릿: `references/orchestrator-template.md` 참조.
|
||||||
|
**실행 모드를 반드시 명시** — 에이전트 팀(기본) 또는 서브 에이전트.
|
||||||
141
skills/zio-harness/SKILL.md
Normal file
141
skills/zio-harness/SKILL.md
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
---
|
||||||
|
name: zio-harness
|
||||||
|
description: "React + Spring Boot + Mobile App 풀스택 개발 하네스. (1) 'zio 실행', 'zio-harness 시작', '풀스택 개발 시작' 요청 시, (2) React 컴포넌트/화면 개발, Spring Boot API 개발, 모바일 앱 개발 요청 시, (3) '프로젝트 분석', '폴더 구조 파악', 'PROJECT_MAP 업데이트' 요청 시, (4) Playwright E2E 테스트, 데이터베이스 MCP 작업 요청 시, (5) 기능 추가, 버그 수정, 리팩터링, 코드 리뷰 요청 시, (6) 오케스트레이터·분석가·봇·에이전트 팀 구성 요청 시 반드시 이 스킬을 사용하라. 다시 실행, 재실행, 업데이트, 보완 요청도 포함."
|
||||||
|
---
|
||||||
|
|
||||||
|
# zio-harness — Full-Stack Dev Orchestrator
|
||||||
|
|
||||||
|
React + Spring Boot + Mobile App 풀스택 개발을 에이전트 팀이 조율하는 통합 하네스.
|
||||||
|
|
||||||
|
## 실행 모드: 에이전트 팀 (파이프라인 패턴)
|
||||||
|
|
||||||
|
```
|
||||||
|
analyst → agent → bot → (orchestrator 종합)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 에이전트 구성
|
||||||
|
|
||||||
|
| 팀원 | 역할 | 주요 스킬 | 출력 |
|
||||||
|
|------|------|---------|------|
|
||||||
|
| analyst | 코드 분석·폴더 구조 파악·구현 계획 | `references/analyst.md` | `_workspace/00_analysis.md` |
|
||||||
|
| agent | React/Spring Boot/Mobile 코드 구현 | `references/react.md`, `spring-boot.md`, `mobile.md` | 실제 코드 파일 |
|
||||||
|
| bot | 테스트 실행·빌드·린트·DB 마이그레이션 | `references/playwright.md`, `database.md` | `_workspace/02_bot_report.md` |
|
||||||
|
|
||||||
|
## 참조 파일 로딩 가이드
|
||||||
|
|
||||||
|
| 작업 유형 | 로드할 파일 |
|
||||||
|
|----------|-----------|
|
||||||
|
| 폴더 구조 파악/업데이트 | `references/folder-map.md` |
|
||||||
|
| React 개발 | `references/react.md` |
|
||||||
|
| Spring Boot 개발 | `references/spring-boot.md` |
|
||||||
|
| 모바일 앱 개발 | `references/mobile.md` |
|
||||||
|
| E2E 테스트 | `references/playwright.md` |
|
||||||
|
| DB/MCP 작업 | `references/database.md` |
|
||||||
|
| 에이전트 설계 | `references/orchestrator.md`, `references/analyst.md`, `references/bot.md`, `references/agent.md` |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 워크플로우
|
||||||
|
|
||||||
|
### Phase 0: PROJECT_MAP 로드 (폴더 구조 메모리)
|
||||||
|
|
||||||
|
프로젝트 루트의 `PROJECT_MAP.md` 존재 여부를 확인한다:
|
||||||
|
|
||||||
|
- **존재**: 파일을 읽어 현재 프로젝트 구조를 파악한다. 이후 분석 시 참조 기준이 된다.
|
||||||
|
- **미존재**: 초기 실행으로 판단. Phase 1 완료 후 `references/folder-map.md`를 읽고 PROJECT_MAP.md를 생성한다.
|
||||||
|
|
||||||
|
PROJECT_MAP.md는 Claude Code가 세션 간에 프로젝트 구조를 기억하는 핵심 파일이다. 항상 최신 상태를 유지한다.
|
||||||
|
|
||||||
|
### Phase 1: 컨텍스트 확인
|
||||||
|
|
||||||
|
```
|
||||||
|
_workspace/ 존재 여부 확인
|
||||||
|
├── 미존재 → 초기 실행 (Phase 2로)
|
||||||
|
├── 존재 + 부분 수정 요청 → 부분 재실행 (해당 에이전트만 재호출)
|
||||||
|
└── 존재 + 새 요청 → 새 실행 (_workspace/ → _workspace_{YYYYMMDD_HHMMSS}/ 이동)
|
||||||
|
```
|
||||||
|
|
||||||
|
작업 유형을 감지한다:
|
||||||
|
- **Feature**: 새 기능 개발 (React 화면 + API + 모바일)
|
||||||
|
- **Bug**: 버그 수정
|
||||||
|
- **Test**: 테스트 작성/실행
|
||||||
|
- **Refactor**: 코드 개선
|
||||||
|
- **Analysis**: 코드/구조 분석만
|
||||||
|
- **Setup**: 초기 프로젝트 설정
|
||||||
|
- **DocMap**: PROJECT_MAP.md 생성/업데이트만
|
||||||
|
|
||||||
|
### Phase 2: 팀 구성
|
||||||
|
|
||||||
|
```
|
||||||
|
TeamCreate(
|
||||||
|
team_name: "zio-dev-team",
|
||||||
|
members: [
|
||||||
|
{ name: "analyst", agent_type: "analyst", model: "opus",
|
||||||
|
prompt: "PROJECT_MAP.md를 읽고 요청 분석 후 _workspace/00_analysis.md 작성. 구현 계획과 영향 파일 목록 포함." },
|
||||||
|
{ name: "agent", agent_type: "general-purpose", model: "opus",
|
||||||
|
prompt: "analyst의 계획을 읽고 코드 구현. React/Spring Boot/Mobile 스택에 맞는 컨벤션 준수." },
|
||||||
|
{ name: "bot", agent_type: "general-purpose", model: "opus",
|
||||||
|
prompt: "구현 완료 후 테스트 실행, 린트, 빌드 검증. 결과를 _workspace/02_bot_report.md에 기록." }
|
||||||
|
]
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
작업 유형별 팀 조정:
|
||||||
|
- **Analysis/DocMap**: analyst만 실행 (팀 불필요)
|
||||||
|
- **Test**: bot만 실행
|
||||||
|
- **Feature/Bug**: 전체 팀 파이프라인
|
||||||
|
|
||||||
|
### Phase 3: 작업 등록 및 실행
|
||||||
|
|
||||||
|
```
|
||||||
|
TaskCreate(tasks: [
|
||||||
|
{ title: "프로젝트 분석 및 구현 계획 수립", assignee: "analyst",
|
||||||
|
description: "PROJECT_MAP.md 기반으로 영향 범위 파악. _workspace/00_analysis.md 작성." },
|
||||||
|
{ title: "코드 구현", assignee: "agent",
|
||||||
|
description: "_workspace/00_analysis.md 읽고 해당 스택 컨벤션으로 구현.",
|
||||||
|
depends_on: ["프로젝트 분석 및 구현 계획 수립"] },
|
||||||
|
{ title: "테스트 및 검증", assignee: "bot",
|
||||||
|
description: "구현 코드 테스트 실행. _workspace/02_bot_report.md 작성.",
|
||||||
|
depends_on: ["코드 구현"] }
|
||||||
|
])
|
||||||
|
```
|
||||||
|
|
||||||
|
팀원 간 통신 프로토콜:
|
||||||
|
- analyst → agent: `SendMessage` ("분석 완료. `_workspace/00_analysis.md` 참조. 구현 시작.")
|
||||||
|
- agent → bot: `SendMessage` ("구현 완료. 테스트 실행 요청.")
|
||||||
|
- bot → orchestrator: `SendMessage` ("검증 완료. `_workspace/02_bot_report.md` 참조.")
|
||||||
|
|
||||||
|
### Phase 4: 결과 종합 및 PROJECT_MAP 업데이트
|
||||||
|
|
||||||
|
1. `_workspace/02_bot_report.md` 확인 — 실패 항목 있으면 agent에 재작업 지시
|
||||||
|
2. 새 파일·폴더가 생성된 경우 `PROJECT_MAP.md` 업데이트 (`references/folder-map.md` 참조)
|
||||||
|
3. 변경 사항 요약을 사용자에게 보고
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 에러 핸들링
|
||||||
|
|
||||||
|
| 상황 | 대응 |
|
||||||
|
|------|------|
|
||||||
|
| analyst 분석 실패 | 기본 파일 스캔으로 대체, 계속 진행 |
|
||||||
|
| agent 구현 오류 | 오류 메시지를 analyst에 전달, 재계획 1회 |
|
||||||
|
| bot 테스트 실패 | 실패 로그를 agent에 전달, 수정 1회 재시도 |
|
||||||
|
| PROJECT_MAP.md 손상 | 삭제 후 재생성 (folder-map.md 절차 따름) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 테스트 시나리오
|
||||||
|
|
||||||
|
**정상 흐름 — Feature 개발:**
|
||||||
|
1. 사용자: "사용자 로그인 기능 추가해줘 (React 화면 + Spring Boot API + 모바일)"
|
||||||
|
2. Phase 0: PROJECT_MAP.md 로드 → 현재 auth 관련 파일 파악
|
||||||
|
3. Phase 2: 3인 팀 구성
|
||||||
|
4. analyst → 영향 파일 식별, API 스펙 정의
|
||||||
|
5. agent → React LoginPage, Spring Boot AuthController, Mobile LoginScreen 구현
|
||||||
|
6. bot → Playwright E2E, JUnit 테스트 실행
|
||||||
|
7. PROJECT_MAP.md 업데이트
|
||||||
|
|
||||||
|
**에러 흐름 — 빌드 실패:**
|
||||||
|
1. bot이 빌드 실패 감지 → agent에 SendMessage
|
||||||
|
2. agent가 오류 수정 → bot이 재검증
|
||||||
|
3. 2회 실패 시 orchestrator가 사용자에게 보고
|
||||||
91
skills/zio-harness/references/agent.md
Normal file
91
skills/zio-harness/references/agent.md
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
# Agent (Dev) 에이전트 정의
|
||||||
|
|
||||||
|
## 역할
|
||||||
|
|
||||||
|
React, Spring Boot, Mobile 코드를 실제로 구현한다. analyst의 계획을 읽고 프로젝트 컨벤션에 맞게 코드를 작성·수정한다.
|
||||||
|
|
||||||
|
## 에이전트 파일 위치
|
||||||
|
|
||||||
|
`.claude/agents/agent.md`
|
||||||
|
|
||||||
|
## 정의 템플릿
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
---
|
||||||
|
name: agent
|
||||||
|
subagent_type: general-purpose
|
||||||
|
model: opus
|
||||||
|
description: "풀스택 코드 구현 전문 에이전트. React, Spring Boot, Mobile 코드를 작성한다."
|
||||||
|
---
|
||||||
|
|
||||||
|
# Agent (Dev)
|
||||||
|
|
||||||
|
## 핵심 역할
|
||||||
|
|
||||||
|
analyst의 구현 계획(`_workspace/00_analysis.md`)을 읽고 React/Spring Boot/Mobile 코드를 PROJECT_MAP.md의 컨벤션에 맞게 구현한다.
|
||||||
|
|
||||||
|
## 작업 절차
|
||||||
|
|
||||||
|
1. `PROJECT_MAP.md` 읽기 — 컨벤션, 폴더 구조 파악
|
||||||
|
2. `_workspace/00_analysis.md` 읽기 — 구현 계획, API 스펙, 영향 파일 확인
|
||||||
|
3. 기존 관련 파일 Read — 패턴 일관성 확인
|
||||||
|
4. 코드 구현 (스택별 컨벤션 적용)
|
||||||
|
5. `_workspace/01_impl_log.md` 작성 — 생성/수정 파일 목록
|
||||||
|
6. bot에 `SendMessage` — 테스트 실행 요청
|
||||||
|
|
||||||
|
## 스택별 구현 원칙
|
||||||
|
|
||||||
|
### React
|
||||||
|
- `references/react.md` 패턴 준수
|
||||||
|
- TypeScript strict 모드 — `any` 타입 사용 금지
|
||||||
|
- 컴포넌트는 단일 책임 원칙 적용
|
||||||
|
- API 호출은 `src/api/` 훅으로 분리
|
||||||
|
|
||||||
|
### Spring Boot
|
||||||
|
- `references/spring-boot.md` 패턴 준수
|
||||||
|
- Controller는 HTTP 처리만 (비즈니스 로직 금지)
|
||||||
|
- 모든 엔티티에 BaseEntity 상속
|
||||||
|
- @Transactional 범위 최소화
|
||||||
|
|
||||||
|
### Mobile
|
||||||
|
- `references/mobile.md` 패턴 준수
|
||||||
|
- 화면 컴포넌트는 `screens/` 폴더에만
|
||||||
|
- 웹과 API 훅 패턴 일치 유지
|
||||||
|
|
||||||
|
## _workspace/01_impl_log.md 구조
|
||||||
|
|
||||||
|
```
|
||||||
|
# Implementation Log
|
||||||
|
시작 시각: {timestamp}
|
||||||
|
|
||||||
|
## 생성된 파일
|
||||||
|
- `frontend/src/pages/UserList.tsx` — 사용자 목록 페이지
|
||||||
|
- `backend/src/main/.../UserController.java` — 사용자 API
|
||||||
|
|
||||||
|
## 수정된 파일
|
||||||
|
- `frontend/src/api/users.ts` — useUsers 훅 추가
|
||||||
|
- `backend/src/main/.../UserService.java` — findAll 메서드 추가
|
||||||
|
|
||||||
|
## 완료 시각: {timestamp}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 이전 산출물 활용
|
||||||
|
|
||||||
|
이전 `_workspace/01_impl_log.md`가 있으면:
|
||||||
|
- 기존 구현 내용 파악 후 수정 범위만 작업
|
||||||
|
- 사용자 피드백이 있으면 해당 부분만 개선
|
||||||
|
|
||||||
|
## 에러 핸들링
|
||||||
|
|
||||||
|
- 파일 충돌: 반드시 Read 후 Edit (덮어쓰기 금지)
|
||||||
|
- 타입 오류: 수정 후 bot에 재검증 요청
|
||||||
|
- 구현 불가 항목: analyst에 재계획 요청
|
||||||
|
|
||||||
|
## 팀 통신 프로토콜
|
||||||
|
|
||||||
|
- **수신**: orchestrator로부터 구현 지시, bot으로부터 테스트 실패 내용
|
||||||
|
- **발신**:
|
||||||
|
- 구현 완료: bot에 `SendMessage("구현 완료. 테스트 실행해줘.")`
|
||||||
|
- bot 피드백 반영 후: bot에 `SendMessage("수정 완료. 재검증 요청.")`
|
||||||
|
- 구현 불가: orchestrator에 `SendMessage("구현 차단 발생. 내용: {설명}")`
|
||||||
|
```
|
||||||
87
skills/zio-harness/references/analyst.md
Normal file
87
skills/zio-harness/references/analyst.md
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
# Analyst 에이전트 정의
|
||||||
|
|
||||||
|
## 역할
|
||||||
|
|
||||||
|
코드와 폴더 구조를 분석하고, PROJECT_MAP.md를 생성·유지하며, 구현 계획을 수립한다.
|
||||||
|
|
||||||
|
## 에이전트 파일 위치
|
||||||
|
|
||||||
|
`.claude/agents/analyst.md`
|
||||||
|
|
||||||
|
## 정의 템플릿
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
---
|
||||||
|
name: analyst
|
||||||
|
subagent_type: Explore
|
||||||
|
model: opus
|
||||||
|
description: "코드 분석 및 PROJECT_MAP 관리 전문 에이전트."
|
||||||
|
---
|
||||||
|
|
||||||
|
# Analyst
|
||||||
|
|
||||||
|
## 핵심 역할
|
||||||
|
|
||||||
|
프로젝트 구조를 분석하고 PROJECT_MAP.md를 최신 상태로 유지한다. 구현 계획을 수립하여 agent에게 명확한 지시를 제공한다.
|
||||||
|
|
||||||
|
## 작업 우선순위
|
||||||
|
|
||||||
|
1. PROJECT_MAP.md 읽기 → 없으면 폴더 스캔 후 생성
|
||||||
|
2. 요청과 관련된 파일/폴더 식별
|
||||||
|
3. 기존 코드 패턴 파악 (컨벤션 일관성)
|
||||||
|
4. 구현 계획 작성 (`_workspace/00_analysis.md`)
|
||||||
|
5. 새 파일/폴더 추가 후 PROJECT_MAP.md 갱신
|
||||||
|
|
||||||
|
## PROJECT_MAP.md 생성 절차
|
||||||
|
|
||||||
|
1. 프로젝트 루트 스캔: `frontend/`, `backend/`, `mobile/`, `e2e/` 폴더 확인
|
||||||
|
2. 각 폴더의 주요 파일 목적 파악 (package.json, build.gradle, pubspec.yaml 기준)
|
||||||
|
3. `references/folder-map.md`의 템플릿으로 PROJECT_MAP.md 작성
|
||||||
|
4. 핵심 컨벤션 섹션에 실제 프로젝트 컨벤션 기록
|
||||||
|
|
||||||
|
## _workspace/00_analysis.md 구조
|
||||||
|
|
||||||
|
```
|
||||||
|
# Analysis Report
|
||||||
|
생성일시: {timestamp}
|
||||||
|
요청: {원본 요청}
|
||||||
|
유형: Feature | Bug | Test | Refactor | Analysis
|
||||||
|
|
||||||
|
## 영향 범위
|
||||||
|
### Frontend
|
||||||
|
- 수정 파일: [경로 목록]
|
||||||
|
- 신규 파일: [경로 목록]
|
||||||
|
|
||||||
|
### Backend
|
||||||
|
- 수정 파일: [경로 목록]
|
||||||
|
- 신규 파일: [경로 목록]
|
||||||
|
|
||||||
|
### Mobile (해당 시)
|
||||||
|
- 수정 파일: [경로 목록]
|
||||||
|
|
||||||
|
## API 스펙 (Feature 시)
|
||||||
|
- Endpoint: POST /api/v1/{resource}
|
||||||
|
- Request: {필드 목록}
|
||||||
|
- Response: {필드 목록}
|
||||||
|
|
||||||
|
## 구현 계획
|
||||||
|
1. [첫 번째 작업]
|
||||||
|
2. [두 번째 작업]
|
||||||
|
...
|
||||||
|
|
||||||
|
## 주의사항
|
||||||
|
- [기존 코드와 충돌 가능성]
|
||||||
|
- [의존 관계]
|
||||||
|
```
|
||||||
|
|
||||||
|
## 에러 핸들링
|
||||||
|
|
||||||
|
- 파일 접근 불가: 부재 명시 후 계속
|
||||||
|
- PROJECT_MAP.md 파싱 오류: 재생성
|
||||||
|
|
||||||
|
## 팀 통신 프로토콜
|
||||||
|
|
||||||
|
- **수신**: orchestrator로부터 분석 요청
|
||||||
|
- **발신**: orchestrator에게 `_workspace/00_analysis.md` 완료 보고
|
||||||
|
- **협업**: agent가 추가 정보 요청 시 해당 파일 경로 제공
|
||||||
|
```
|
||||||
111
skills/zio-harness/references/bot.md
Normal file
111
skills/zio-harness/references/bot.md
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
# Bot 에이전트 정의
|
||||||
|
|
||||||
|
## 역할
|
||||||
|
|
||||||
|
자동화된 반복 작업을 실행한다. 테스트 실행, 빌드 검증, 린트, 데이터베이스 마이그레이션, CI 작업을 처리한다.
|
||||||
|
|
||||||
|
## 에이전트 파일 위치
|
||||||
|
|
||||||
|
`.claude/agents/bot.md`
|
||||||
|
|
||||||
|
## 정의 템플릿
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
---
|
||||||
|
name: bot
|
||||||
|
subagent_type: general-purpose
|
||||||
|
model: opus
|
||||||
|
description: "자동화 작업 전문 에이전트. 테스트 실행, 빌드, 린트, DB 마이그레이션을 처리한다."
|
||||||
|
---
|
||||||
|
|
||||||
|
# Bot
|
||||||
|
|
||||||
|
## 핵심 역할
|
||||||
|
|
||||||
|
구현 완료 후 검증 파이프라인을 실행하고 결과를 `_workspace/02_bot_report.md`에 기록한다.
|
||||||
|
|
||||||
|
## 실행 순서
|
||||||
|
|
||||||
|
1. **Frontend 검증**
|
||||||
|
```bash
|
||||||
|
cd frontend
|
||||||
|
npm run lint # ESLint 린트
|
||||||
|
npm run type-check # TypeScript 타입 체크
|
||||||
|
npm run test # Vitest 단위 테스트
|
||||||
|
npm run build # 빌드 가능 여부
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Backend 검증**
|
||||||
|
```bash
|
||||||
|
cd backend
|
||||||
|
./gradlew ktlintCheck # 코틀린 린트 (또는 checkstyle)
|
||||||
|
./gradlew test # JUnit 테스트
|
||||||
|
./gradlew build # 빌드
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **E2E 테스트 (선택 — 구현 완료 후)**
|
||||||
|
```bash
|
||||||
|
cd e2e
|
||||||
|
npx playwright test --project=chromium
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **DB 마이그레이션 검증**
|
||||||
|
```bash
|
||||||
|
cd backend
|
||||||
|
./gradlew flywayInfo # 마이그레이션 상태 확인
|
||||||
|
./gradlew flywayMigrate # 미적용 마이그레이션 실행
|
||||||
|
```
|
||||||
|
|
||||||
|
## _workspace/02_bot_report.md 구조
|
||||||
|
|
||||||
|
```
|
||||||
|
# Bot Report
|
||||||
|
실행 시각: {timestamp}
|
||||||
|
|
||||||
|
## Frontend
|
||||||
|
- Lint: PASS | FAIL ({오류 수})
|
||||||
|
- Type Check: PASS | FAIL
|
||||||
|
- Unit Tests: {통과}/{전체} ({실패 목록})
|
||||||
|
- Build: PASS | FAIL
|
||||||
|
|
||||||
|
## Backend
|
||||||
|
- Lint: PASS | FAIL
|
||||||
|
- Tests: {통과}/{전체}
|
||||||
|
- Build: PASS | FAIL
|
||||||
|
|
||||||
|
## E2E (실행 시)
|
||||||
|
- Tests: {통과}/{전체}
|
||||||
|
- 실패 스크린샷: {경로}
|
||||||
|
|
||||||
|
## DB Migration
|
||||||
|
- 상태: UP_TO_DATE | {n개 미적용}
|
||||||
|
- 실행 결과: SUCCESS | FAIL
|
||||||
|
|
||||||
|
## 종합 결과: ALL_PASS | FAIL
|
||||||
|
### 실패 항목 (수정 필요)
|
||||||
|
- [실패 내용 + 오류 메시지]
|
||||||
|
```
|
||||||
|
|
||||||
|
## 에러 핸들링
|
||||||
|
|
||||||
|
- 테스트 실패: 로그 수집 후 agent에 `SendMessage`로 실패 내용 전달
|
||||||
|
- 빌드 실패: 오류 메시지 전체 기록
|
||||||
|
- DB 마이그레이션 실패: 롤백 여부 확인 후 orchestrator에 보고
|
||||||
|
|
||||||
|
## 팀 통신 프로토콜
|
||||||
|
|
||||||
|
- **수신**: agent로부터 "구현 완료, 테스트 실행 요청" 메시지
|
||||||
|
- **발신**:
|
||||||
|
- 테스트 실패 시: agent에 `SendMessage("테스트 실패. _workspace/02_bot_report.md 참조.")`
|
||||||
|
- 전체 통과 시: orchestrator에 `SendMessage("검증 완료. ALL_PASS.")`
|
||||||
|
```
|
||||||
|
|
||||||
|
## Bot이 자주 처리하는 시나리오
|
||||||
|
|
||||||
|
| 시나리오 | 실행 명령 | 예상 시간 |
|
||||||
|
|---------|---------|---------|
|
||||||
|
| React 단위 테스트 | `npm run test` | 30초~2분 |
|
||||||
|
| Spring Boot 테스트 | `./gradlew test` | 1~5분 |
|
||||||
|
| E2E 전체 실행 | `npx playwright test` | 5~15분 |
|
||||||
|
| DB 마이그레이션 | `./gradlew flywayMigrate` | 10초~1분 |
|
||||||
|
| 전체 파이프라인 | 위 순서대로 | 10~20분 |
|
||||||
269
skills/zio-harness/references/database.md
Normal file
269
skills/zio-harness/references/database.md
Normal file
@ -0,0 +1,269 @@
|
|||||||
|
# Database + MCP 가이드
|
||||||
|
|
||||||
|
## 개요
|
||||||
|
|
||||||
|
데이터베이스 작업은 두 경로로 처리한다:
|
||||||
|
- **MCP (Model Context Protocol)**: Claude Code가 DB를 직접 조회/탐색할 때
|
||||||
|
- **Spring Boot JPA**: 애플리케이션 코드에서 DB를 다룰 때
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## MCP 데이터베이스 설정
|
||||||
|
|
||||||
|
### PostgreSQL MCP 설정
|
||||||
|
|
||||||
|
```json
|
||||||
|
// .claude/settings.json (프로젝트)
|
||||||
|
{
|
||||||
|
"mcpServers": {
|
||||||
|
"postgres": {
|
||||||
|
"command": "npx",
|
||||||
|
"args": ["-y", "@modelcontextprotocol/server-postgres", "postgresql://localhost/myapp"],
|
||||||
|
"env": {
|
||||||
|
"PGPASSWORD": "${DB_PASSWORD}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### MySQL MCP 설정
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mcpServers": {
|
||||||
|
"mysql": {
|
||||||
|
"command": "npx",
|
||||||
|
"args": ["-y", "@benborla29/mcp-server-mysql"],
|
||||||
|
"env": {
|
||||||
|
"MYSQL_HOST": "localhost",
|
||||||
|
"MYSQL_PORT": "3306",
|
||||||
|
"MYSQL_USER": "root",
|
||||||
|
"MYSQL_PASS": "${DB_PASSWORD}",
|
||||||
|
"MYSQL_DB": "myapp"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### MCP로 DB 탐색하는 방법
|
||||||
|
|
||||||
|
MCP가 활성화되면 Claude Code에서 직접 DB를 조회한다:
|
||||||
|
- 스키마 확인: "현재 DB 테이블 목록 보여줘"
|
||||||
|
- 데이터 조회: "users 테이블에서 최근 가입한 10명 조회해줘"
|
||||||
|
- 스키마 설계: "이 요구사항에 맞는 테이블 구조 제안해줘"
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 데이터베이스 설계 패턴
|
||||||
|
|
||||||
|
### 공통 컬럼 (BaseEntity)
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- 모든 테이블에 포함
|
||||||
|
id BIGSERIAL PRIMARY KEY,
|
||||||
|
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
||||||
|
updated_at TIMESTAMP NOT NULL DEFAULT NOW()
|
||||||
|
```
|
||||||
|
|
||||||
|
### 사용자 테이블 표준
|
||||||
|
|
||||||
|
```sql
|
||||||
|
CREATE TABLE users (
|
||||||
|
id BIGSERIAL PRIMARY KEY,
|
||||||
|
email VARCHAR(255) NOT NULL UNIQUE,
|
||||||
|
password VARCHAR(255) NOT NULL, -- bcrypt 해시
|
||||||
|
name VARCHAR(100) NOT NULL,
|
||||||
|
role VARCHAR(20) NOT NULL DEFAULT 'USER',
|
||||||
|
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||||
|
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
||||||
|
updated_at TIMESTAMP NOT NULL DEFAULT NOW()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX idx_users_email ON users(email);
|
||||||
|
```
|
||||||
|
|
||||||
|
### 관계 설계
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- 1:N 관계 (posts → users)
|
||||||
|
CREATE TABLE posts (
|
||||||
|
id BIGSERIAL PRIMARY KEY,
|
||||||
|
user_id BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||||
|
title VARCHAR(500) NOT NULL,
|
||||||
|
content TEXT,
|
||||||
|
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
||||||
|
updated_at TIMESTAMP NOT NULL DEFAULT NOW()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX idx_posts_user_id ON posts(user_id);
|
||||||
|
|
||||||
|
-- N:M 관계 (users ↔ tags)
|
||||||
|
CREATE TABLE user_tags (
|
||||||
|
user_id BIGINT REFERENCES users(id) ON DELETE CASCADE,
|
||||||
|
tag_id BIGINT REFERENCES tags(id) ON DELETE CASCADE,
|
||||||
|
PRIMARY KEY (user_id, tag_id)
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Flyway 마이그레이션 패턴
|
||||||
|
|
||||||
|
```
|
||||||
|
src/main/resources/db/migration/
|
||||||
|
├── V1__init_schema.sql # 초기 스키마
|
||||||
|
├── V2__add_posts_table.sql # 새 테이블
|
||||||
|
├── V3__add_user_avatar.sql # 컬럼 추가
|
||||||
|
└── V4__create_tags.sql # N:M 관계
|
||||||
|
```
|
||||||
|
|
||||||
|
### 마이그레이션 파일 작성 규칙
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- V2__add_posts_table.sql
|
||||||
|
-- 항상 트랜잭션 안에서 실행됨 (PostgreSQL)
|
||||||
|
CREATE TABLE posts (
|
||||||
|
id BIGSERIAL PRIMARY KEY,
|
||||||
|
user_id BIGINT NOT NULL REFERENCES users(id),
|
||||||
|
title VARCHAR(500) NOT NULL,
|
||||||
|
created_at TIMESTAMP NOT NULL DEFAULT NOW()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX idx_posts_user_id ON posts(user_id);
|
||||||
|
```
|
||||||
|
|
||||||
|
- 파일명: `V{숫자}__{설명}.sql` (밑줄 2개)
|
||||||
|
- 한 번 적용된 파일은 수정 금지 (새 버전 파일 추가)
|
||||||
|
- 롤백 스크립트: `R{버전}__{설명}.sql` (선택)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## JPA Repository 고급 패턴
|
||||||
|
|
||||||
|
### QueryDSL / JPQL
|
||||||
|
|
||||||
|
```java
|
||||||
|
// 커스텀 조회 (인터페이스 + Impl 패턴)
|
||||||
|
public interface UserRepositoryCustom {
|
||||||
|
List<User> findActiveUsersWithPosts(Pageable pageable);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
public class UserRepositoryImpl implements UserRepositoryCustom {
|
||||||
|
@PersistenceContext EntityManager em;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<User> findActiveUsersWithPosts(Pageable pageable) {
|
||||||
|
return em.createQuery(
|
||||||
|
"SELECT DISTINCT u FROM User u JOIN FETCH u.posts WHERE u.isActive = true",
|
||||||
|
User.class)
|
||||||
|
.setFirstResult((int) pageable.getOffset())
|
||||||
|
.setMaxResults(pageable.getPageSize())
|
||||||
|
.getResultList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Spring Data JPA 인터페이스
|
||||||
|
public interface UserRepository extends JpaRepository<User, Long>, UserRepositoryCustom {
|
||||||
|
Optional<User> findByEmail(String email);
|
||||||
|
|
||||||
|
@Query("SELECT u FROM User u WHERE u.role = :role AND u.isActive = true")
|
||||||
|
List<User> findActiveByRole(@Param("role") String role);
|
||||||
|
|
||||||
|
Page<User> findByNameContaining(String name, Pageable pageable);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## DB 연결 설정
|
||||||
|
|
||||||
|
### application.yml
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
spring:
|
||||||
|
datasource:
|
||||||
|
url: ${DB_URL:jdbc:postgresql://localhost:5432/myapp}
|
||||||
|
username: ${DB_USERNAME:postgres}
|
||||||
|
password: ${DB_PASSWORD:password}
|
||||||
|
hikari:
|
||||||
|
maximum-pool-size: 20
|
||||||
|
minimum-idle: 5
|
||||||
|
connection-timeout: 30000
|
||||||
|
|
||||||
|
jpa:
|
||||||
|
hibernate:
|
||||||
|
ddl-auto: validate # Flyway 사용 시 validate (create/update 금지)
|
||||||
|
properties:
|
||||||
|
hibernate:
|
||||||
|
dialect: org.hibernate.dialect.PostgreSQLDialect
|
||||||
|
format_sql: true
|
||||||
|
open-in-view: false # 성능: 트랜잭션 외부 지연 로딩 비활성화
|
||||||
|
|
||||||
|
flyway:
|
||||||
|
enabled: true
|
||||||
|
locations: classpath:db/migration
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 성능 최적화
|
||||||
|
|
||||||
|
### N+1 문제 해결
|
||||||
|
|
||||||
|
```java
|
||||||
|
// 잘못된 예 (N+1 발생)
|
||||||
|
List<User> users = userRepository.findAll();
|
||||||
|
users.forEach(u -> u.getPosts().size()); // 각 사용자마다 쿼리 발생
|
||||||
|
|
||||||
|
// 올바른 예 (fetch join)
|
||||||
|
@Query("SELECT u FROM User u LEFT JOIN FETCH u.posts")
|
||||||
|
List<User> findAllWithPosts();
|
||||||
|
```
|
||||||
|
|
||||||
|
### 페이지네이션
|
||||||
|
|
||||||
|
```java
|
||||||
|
// 컨트롤러
|
||||||
|
@GetMapping
|
||||||
|
public ResponseEntity<Page<UserResponse>> getUsers(
|
||||||
|
@RequestParam(defaultValue = "0") int page,
|
||||||
|
@RequestParam(defaultValue = "20") int size,
|
||||||
|
@RequestParam(defaultValue = "createdAt") String sort) {
|
||||||
|
|
||||||
|
Pageable pageable = PageRequest.of(page, size, Sort.by(sort).descending());
|
||||||
|
return ResponseEntity.ok(userService.findAll(pageable).map(UserResponse::from));
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 로컬 개발 환경 (Docker)
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# docker-compose.yml
|
||||||
|
services:
|
||||||
|
postgres:
|
||||||
|
image: postgres:16
|
||||||
|
environment:
|
||||||
|
POSTGRES_DB: myapp
|
||||||
|
POSTGRES_USER: postgres
|
||||||
|
POSTGRES_PASSWORD: password
|
||||||
|
ports:
|
||||||
|
- "5432:5432"
|
||||||
|
volumes:
|
||||||
|
- postgres_data:/var/lib/postgresql/data
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
postgres_data:
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# DB 시작
|
||||||
|
docker-compose up -d postgres
|
||||||
|
|
||||||
|
# 접속
|
||||||
|
psql -h localhost -U postgres -d myapp
|
||||||
|
```
|
||||||
142
skills/zio-harness/references/folder-map.md
Normal file
142
skills/zio-harness/references/folder-map.md
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
# Folder Map — PROJECT_MAP.md 생성 및 유지 가이드
|
||||||
|
|
||||||
|
Claude Code가 세션 간 프로젝트 구조를 기억하기 위한 `PROJECT_MAP.md` 시스템.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## PROJECT_MAP.md 란
|
||||||
|
|
||||||
|
프로젝트 루트에 위치하는 **폴더 구조 메모리 파일**이다. 모든 에이전트가 작업 시작 시 이 파일을 먼저 읽어 "어떤 폴더에 무엇이 있는지" 파악한다.
|
||||||
|
|
||||||
|
**왜 필요한가:** Claude Code는 세션마다 새로 시작하므로, 프로젝트 구조를 매번 탐색하면 토큰 낭비가 크다. PROJECT_MAP.md 한 파일만 읽으면 전체 구조를 즉시 파악할 수 있다.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 초기 생성 절차
|
||||||
|
|
||||||
|
프로젝트 루트에 PROJECT_MAP.md가 없을 때 실행한다:
|
||||||
|
|
||||||
|
1. 프로젝트 루트에서 최상위 폴더 목록 스캔
|
||||||
|
2. 각 폴더의 목적을 파악 (package.json, build.gradle, pubspec.yaml 등 메타파일 기준)
|
||||||
|
3. 아래 템플릿으로 PROJECT_MAP.md 생성
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## PROJECT_MAP.md 템플릿 (React + Spring Boot + Mobile)
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
# PROJECT_MAP
|
||||||
|
|
||||||
|
> 마지막 업데이트: {YYYY-MM-DD HH:MM}
|
||||||
|
> 스택: React {version} | Spring Boot {version} | {Mobile Framework} {version}
|
||||||
|
> 업데이트 방법: "PROJECT_MAP 업데이트해줘" 또는 zio-harness 실행 시 자동 갱신
|
||||||
|
|
||||||
|
## 프로젝트 구조
|
||||||
|
|
||||||
|
### 루트
|
||||||
|
| 파일/폴더 | 용도 |
|
||||||
|
|----------|------|
|
||||||
|
| `frontend/` | React 웹 프론트엔드 |
|
||||||
|
| `backend/` | Spring Boot 백엔드 API |
|
||||||
|
| `mobile/` | 모바일 앱 (React Native / Flutter) |
|
||||||
|
| `e2e/` | Playwright E2E 테스트 |
|
||||||
|
| `docs/` | 프로젝트 문서 |
|
||||||
|
| `docker-compose.yml` | 로컬 개발 환경 |
|
||||||
|
| `PROJECT_MAP.md` | 이 파일 — 폴더 구조 메모리 |
|
||||||
|
|
||||||
|
### frontend/ (React)
|
||||||
|
| 경로 | 용도 |
|
||||||
|
|------|------|
|
||||||
|
| `src/pages/` | 페이지 컴포넌트 (라우트 단위) |
|
||||||
|
| `src/components/` | 공유 UI 컴포넌트 |
|
||||||
|
| `src/hooks/` | 커스텀 훅 |
|
||||||
|
| `src/store/` | 상태 관리 (Zustand / Redux) |
|
||||||
|
| `src/api/` | API 호출 함수 (Axios / fetch) |
|
||||||
|
| `src/types/` | TypeScript 타입 정의 |
|
||||||
|
| `src/utils/` | 유틸리티 함수 |
|
||||||
|
| `public/` | 정적 에셋 |
|
||||||
|
| `package.json` | 의존성 |
|
||||||
|
| `.env.local` | 로컬 환경 변수 (VITE_API_URL 등) |
|
||||||
|
|
||||||
|
### backend/ (Spring Boot)
|
||||||
|
| 경로 | 용도 |
|
||||||
|
|------|------|
|
||||||
|
| `src/main/java/{package}/controller/` | REST API 컨트롤러 |
|
||||||
|
| `src/main/java/{package}/service/` | 비즈니스 로직 |
|
||||||
|
| `src/main/java/{package}/repository/` | JPA 리포지토리 |
|
||||||
|
| `src/main/java/{package}/domain/` | 엔티티 / 도메인 모델 |
|
||||||
|
| `src/main/java/{package}/dto/` | Request / Response DTO |
|
||||||
|
| `src/main/java/{package}/config/` | Spring 설정 (Security, CORS 등) |
|
||||||
|
| `src/main/java/{package}/exception/` | 예외 처리 |
|
||||||
|
| `src/main/resources/application.yml` | 앱 설정 |
|
||||||
|
| `src/main/resources/db/migration/` | Flyway DB 마이그레이션 |
|
||||||
|
| `src/test/` | 단위/통합 테스트 |
|
||||||
|
| `build.gradle` | 의존성 |
|
||||||
|
|
||||||
|
### mobile/ (React Native / Flutter)
|
||||||
|
| 경로 | 용도 |
|
||||||
|
|------|------|
|
||||||
|
| `src/screens/` | 화면 컴포넌트 |
|
||||||
|
| `src/navigation/` | 네비게이션 설정 |
|
||||||
|
| `src/components/` | 공유 UI 컴포넌트 |
|
||||||
|
| `src/api/` | API 클라이언트 |
|
||||||
|
| `src/store/` | 상태 관리 |
|
||||||
|
| `src/types/` | 타입 정의 |
|
||||||
|
| `android/` | Android 네이티브 코드 |
|
||||||
|
| `ios/` | iOS 네이티브 코드 |
|
||||||
|
|
||||||
|
### e2e/ (Playwright)
|
||||||
|
| 경로 | 용도 |
|
||||||
|
|------|------|
|
||||||
|
| `tests/` | 테스트 파일 |
|
||||||
|
| `pages/` | 페이지 오브젝트 |
|
||||||
|
| `fixtures/` | 테스트 픽스처 |
|
||||||
|
| `playwright.config.ts` | Playwright 설정 |
|
||||||
|
|
||||||
|
## 핵심 컨벤션
|
||||||
|
- **API URL 패턴**: `GET /api/v1/{resource}`, `POST /api/v1/{resource}`
|
||||||
|
- **컴포넌트 네이밍**: PascalCase (예: `UserProfile.tsx`)
|
||||||
|
- **훅 네이밍**: `use` 접두사 (예: `useAuth.ts`)
|
||||||
|
- **서비스 네이밍**: `{Resource}Service.java`
|
||||||
|
- **DTO 네이밍**: `{Action}{Resource}Request.java`, `{Resource}Response.java`
|
||||||
|
|
||||||
|
## 환경 변수
|
||||||
|
| 변수 | 위치 | 설명 |
|
||||||
|
|------|------|------|
|
||||||
|
| `VITE_API_URL` | frontend/.env.local | 백엔드 API 주소 |
|
||||||
|
| `DB_URL` | backend/application.yml | 데이터베이스 주소 |
|
||||||
|
| `JWT_SECRET` | backend/application.yml | JWT 서명 키 |
|
||||||
|
|
||||||
|
## 최근 변경 이력
|
||||||
|
| 날짜 | 변경 내용 | 담당 에이전트 |
|
||||||
|
|------|----------|--------------|
|
||||||
|
| {YYYY-MM-DD} | 초기 맵 생성 | analyst |
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 업데이트 규칙
|
||||||
|
|
||||||
|
다음 상황에서 PROJECT_MAP.md를 업데이트한다:
|
||||||
|
|
||||||
|
1. **새 폴더 생성** → 해당 폴더 행 추가
|
||||||
|
2. **새 컨벤션 발견** → 핵심 컨벤션 섹션에 추가
|
||||||
|
3. **새 환경 변수 추가** → 환경 변수 테이블 업데이트
|
||||||
|
4. **구조 변경** → 해당 섹션 수정
|
||||||
|
|
||||||
|
업데이트 시 `마지막 업데이트` 날짜와 최근 변경 이력을 항상 갱신한다.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 빠른 파악 프로토콜
|
||||||
|
|
||||||
|
에이전트가 새 작업을 시작할 때:
|
||||||
|
|
||||||
|
```
|
||||||
|
1. PROJECT_MAP.md 읽기 (없으면 생성)
|
||||||
|
2. 작업과 관련된 폴더 파악
|
||||||
|
3. 해당 폴더만 탐색 (전체 탐색 금지)
|
||||||
|
4. 작업 완료 후 새 파일/폴더가 생겼으면 PROJECT_MAP.md 갱신
|
||||||
|
```
|
||||||
|
|
||||||
|
이 순서를 지키면 탐색 토큰을 70% 이상 절약할 수 있다.
|
||||||
205
skills/zio-harness/references/mobile.md
Normal file
205
skills/zio-harness/references/mobile.md
Normal file
@ -0,0 +1,205 @@
|
|||||||
|
# Mobile App 개발 가이드
|
||||||
|
|
||||||
|
## 스택 가정
|
||||||
|
- **React Native** (Expo 또는 bare workflow) + TypeScript
|
||||||
|
- 네비게이션: React Navigation v6
|
||||||
|
- 상태 관리: Zustand (웹과 공유 가능)
|
||||||
|
- API: Axios + TanStack Query
|
||||||
|
- 스타일: StyleSheet (네이티브), NativeWind (Tailwind 기반)
|
||||||
|
|
||||||
|
> Flutter를 사용하는 경우: `references/flutter.md` 생성 필요 (별도 확장)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 폴더 구조
|
||||||
|
|
||||||
|
```
|
||||||
|
mobile/
|
||||||
|
├── src/
|
||||||
|
│ ├── screens/ # 화면 단위 컴포넌트
|
||||||
|
│ │ ├── auth/ # 인증 화면 (Login, Register)
|
||||||
|
│ │ ├── home/ # 홈 화면
|
||||||
|
│ │ └── profile/ # 프로필 화면
|
||||||
|
│ ├── navigation/ # 네비게이터 정의
|
||||||
|
│ │ ├── RootNavigator.tsx
|
||||||
|
│ │ ├── AuthNavigator.tsx
|
||||||
|
│ │ └── MainNavigator.tsx
|
||||||
|
│ ├── components/ # 재사용 컴포넌트
|
||||||
|
│ │ ├── ui/ # 기본 UI (Button, Input, Card)
|
||||||
|
│ │ └── features/ # 도메인별 컴포넌트
|
||||||
|
│ ├── api/ # API 클라이언트 + 훅 (웹과 동일 패턴)
|
||||||
|
│ ├── store/ # Zustand stores (웹과 코드 공유 가능)
|
||||||
|
│ ├── types/ # 타입 정의
|
||||||
|
│ ├── utils/ # 유틸리티
|
||||||
|
│ └── constants/ # 상수 (colors, sizes, etc.)
|
||||||
|
├── android/ # Android 네이티브
|
||||||
|
├── ios/ # iOS 네이티브
|
||||||
|
├── app.json # Expo 설정
|
||||||
|
└── package.json
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 네비게이션 구조
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// src/navigation/RootNavigator.tsx
|
||||||
|
export function RootNavigator() {
|
||||||
|
const { token } = useAuthStore();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<NavigationContainer>
|
||||||
|
{token ? <MainNavigator /> : <AuthNavigator />}
|
||||||
|
</NavigationContainer>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// src/navigation/MainNavigator.tsx
|
||||||
|
const Tab = createBottomTabNavigator<MainTabParams>();
|
||||||
|
|
||||||
|
export function MainNavigator() {
|
||||||
|
return (
|
||||||
|
<Tab.Navigator>
|
||||||
|
<Tab.Screen name="Home" component={HomeScreen} />
|
||||||
|
<Tab.Screen name="Profile" component={ProfileScreen} />
|
||||||
|
</Tab.Navigator>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 타입 안전한 네비게이션
|
||||||
|
type MainTabParams = {
|
||||||
|
Home: undefined;
|
||||||
|
Profile: { userId: string };
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 화면 컴포넌트 패턴
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// src/screens/home/HomeScreen.tsx
|
||||||
|
import { NativeStackScreenProps } from '@react-navigation/native-stack';
|
||||||
|
|
||||||
|
type Props = NativeStackScreenProps<MainTabParams, 'Home'>;
|
||||||
|
|
||||||
|
export function HomeScreen({ navigation }: Props) {
|
||||||
|
const { data: posts, isLoading } = usePosts();
|
||||||
|
|
||||||
|
if (isLoading) return <LoadingSpinner />;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SafeAreaView style={styles.container}>
|
||||||
|
<FlatList
|
||||||
|
data={posts}
|
||||||
|
keyExtractor={(item) => item.id.toString()}
|
||||||
|
renderItem={({ item }) => (
|
||||||
|
<PostCard
|
||||||
|
post={item}
|
||||||
|
onPress={() => navigation.navigate('PostDetail', { id: item.id })}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</SafeAreaView>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: { flex: 1, backgroundColor: '#fff' },
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## API 연동 (웹과 코드 공유)
|
||||||
|
|
||||||
|
웹(React)과 모바일은 동일한 API 훅 패턴을 사용한다. 공유 패키지 또는 복사 방식으로 관리:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// src/api/client.ts — 웹과 동일한 패턴
|
||||||
|
const api = axios.create({
|
||||||
|
baseURL: Config.API_URL, // react-native-config 사용
|
||||||
|
timeout: 10000,
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
환경 변수는 `react-native-config` 사용:
|
||||||
|
```
|
||||||
|
# .env
|
||||||
|
API_URL=http://localhost:8080
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 로컬 저장소
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||||
|
|
||||||
|
// 토큰 저장
|
||||||
|
await AsyncStorage.setItem('token', token);
|
||||||
|
|
||||||
|
// 토큰 읽기
|
||||||
|
const token = await AsyncStorage.getItem('token');
|
||||||
|
|
||||||
|
// Zustand 영속성 (zustand/middleware의 persist)
|
||||||
|
const useAuthStore = create(
|
||||||
|
persist<AuthState>(
|
||||||
|
(set) => ({ ... }),
|
||||||
|
{ name: 'auth-store', storage: createJSONStorage(() => AsyncStorage) }
|
||||||
|
)
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 푸시 알림
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Expo Notifications 사용 시
|
||||||
|
import * as Notifications from 'expo-notifications';
|
||||||
|
|
||||||
|
async function registerForPushNotifications() {
|
||||||
|
const { status } = await Notifications.requestPermissionsAsync();
|
||||||
|
if (status !== 'granted') return null;
|
||||||
|
|
||||||
|
const token = await Notifications.getExpoPushTokenAsync({
|
||||||
|
projectId: Constants.expoConfig?.extra?.eas?.projectId,
|
||||||
|
});
|
||||||
|
|
||||||
|
// 서버에 토큰 등록
|
||||||
|
await api.post('/api/v1/users/push-token', { token: token.data });
|
||||||
|
return token.data;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 빌드 및 배포
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 개발 실행
|
||||||
|
npx expo start
|
||||||
|
|
||||||
|
# Android 빌드 (EAS Build)
|
||||||
|
eas build --platform android --profile preview
|
||||||
|
|
||||||
|
# iOS 빌드
|
||||||
|
eas build --platform ios --profile preview
|
||||||
|
|
||||||
|
# 스토어 제출
|
||||||
|
eas submit --platform android
|
||||||
|
eas submit --platform ios
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 컨벤션
|
||||||
|
|
||||||
|
| 항목 | 규칙 |
|
||||||
|
|------|------|
|
||||||
|
| 화면 파일 | `{Name}Screen.tsx` |
|
||||||
|
| 네비게이터 | `{Name}Navigator.tsx` |
|
||||||
|
| 스타일 | 파일 하단에 `StyleSheet.create({})` |
|
||||||
|
| 네이티브 모듈 | `src/native/` 폴더에 분리 |
|
||||||
|
| 플랫폼별 코드 | `.ios.tsx` / `.android.tsx` 확장자 |
|
||||||
67
skills/zio-harness/references/orchestrator.md
Normal file
67
skills/zio-harness/references/orchestrator.md
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
# Orchestrator 에이전트 정의
|
||||||
|
|
||||||
|
## 역할
|
||||||
|
|
||||||
|
전체 풀스택 개발 워크플로우를 조율한다. PROJECT_MAP.md를 읽어 프로젝트 컨텍스트를 파악하고, 작업 유형에 맞는 에이전트 팀을 구성·지시·종합한다.
|
||||||
|
|
||||||
|
## 에이전트 파일 위치
|
||||||
|
|
||||||
|
`.claude/agents/orchestrator.md`
|
||||||
|
|
||||||
|
## 정의 템플릿
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
---
|
||||||
|
name: orchestrator
|
||||||
|
subagent_type: general-purpose
|
||||||
|
model: opus
|
||||||
|
description: "zio-harness 풀스택 개발 오케스트레이터. 작업 분석, 팀 구성, 결과 종합을 담당."
|
||||||
|
---
|
||||||
|
|
||||||
|
# Orchestrator
|
||||||
|
|
||||||
|
## 핵심 역할
|
||||||
|
|
||||||
|
React + Spring Boot + Mobile 풀스택 개발 요청을 받아 에이전트 팀을 조율하고 결과를 종합한다.
|
||||||
|
|
||||||
|
## 작업 절차
|
||||||
|
|
||||||
|
1. PROJECT_MAP.md 읽기 (없으면 analyst에게 생성 지시)
|
||||||
|
2. 요청 유형 판별 (Feature / Bug / Test / Refactor / Analysis)
|
||||||
|
3. 필요한 에이전트 팀 구성
|
||||||
|
4. TaskCreate로 작업 할당 및 의존성 설정
|
||||||
|
5. 팀원 완료 알림 수신 및 결과 종합
|
||||||
|
6. 새 파일/폴더 생성 시 PROJECT_MAP.md 업데이트 지시
|
||||||
|
|
||||||
|
## 팀 구성 규칙
|
||||||
|
|
||||||
|
| 요청 유형 | 팀 구성 |
|
||||||
|
|----------|---------|
|
||||||
|
| Feature 개발 | analyst + agent + bot |
|
||||||
|
| Bug 수정 | analyst + agent + bot |
|
||||||
|
| 테스트만 | bot |
|
||||||
|
| 코드 분석 | analyst |
|
||||||
|
| 문서/구조 | analyst |
|
||||||
|
|
||||||
|
## 에러 핸들링
|
||||||
|
|
||||||
|
- agent 구현 실패: analyst에 재계획 요청 (1회)
|
||||||
|
- bot 테스트 실패: agent에 수정 요청 (1회)
|
||||||
|
- 2회 연속 실패: 사용자에게 보고 후 중단
|
||||||
|
|
||||||
|
## 팀 통신 프로토콜
|
||||||
|
|
||||||
|
- **수신**: 사용자 요청, 팀원 완료 보고
|
||||||
|
- **발신**: analyst에 분석 지시, agent에 구현 지시, bot에 테스트 지시
|
||||||
|
- **브로드캐스트**: 팀 구성 시 전체 컨텍스트 공유
|
||||||
|
```
|
||||||
|
|
||||||
|
## 오케스트레이터가 사용하는 WorkSpace 구조
|
||||||
|
|
||||||
|
```
|
||||||
|
_workspace/
|
||||||
|
├── 00_analysis.md # analyst 산출물
|
||||||
|
├── 01_impl_log.md # agent 구현 로그
|
||||||
|
├── 02_bot_report.md # bot 테스트 결과
|
||||||
|
└── 99_summary.md # orchestrator 최종 요약
|
||||||
|
```
|
||||||
219
skills/zio-harness/references/playwright.md
Normal file
219
skills/zio-harness/references/playwright.md
Normal file
@ -0,0 +1,219 @@
|
|||||||
|
# Playwright E2E 테스트 가이드
|
||||||
|
|
||||||
|
## 스택
|
||||||
|
- Playwright + TypeScript
|
||||||
|
- 페이지 오브젝트 패턴 (POM)
|
||||||
|
- CI 통합 (GitHub Actions)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 폴더 구조
|
||||||
|
|
||||||
|
```
|
||||||
|
e2e/
|
||||||
|
├── tests/
|
||||||
|
│ ├── auth.spec.ts # 인증 시나리오
|
||||||
|
│ ├── users.spec.ts # 사용자 관련 시나리오
|
||||||
|
│ └── ...
|
||||||
|
├── pages/ # 페이지 오브젝트 (POM)
|
||||||
|
│ ├── LoginPage.ts
|
||||||
|
│ ├── HomePage.ts
|
||||||
|
│ └── BasePage.ts
|
||||||
|
├── fixtures/ # 테스트 픽스처 및 헬퍼
|
||||||
|
│ ├── auth.fixture.ts # 로그인 상태 픽스처
|
||||||
|
│ └── data.ts # 테스트 데이터
|
||||||
|
└── playwright.config.ts
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 설정
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// playwright.config.ts
|
||||||
|
import { defineConfig, devices } from '@playwright/test';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
testDir: './tests',
|
||||||
|
fullyParallel: true,
|
||||||
|
retries: process.env.CI ? 2 : 0,
|
||||||
|
workers: process.env.CI ? 1 : undefined,
|
||||||
|
reporter: 'html',
|
||||||
|
use: {
|
||||||
|
baseURL: process.env.BASE_URL || 'http://localhost:5173',
|
||||||
|
trace: 'on-first-retry',
|
||||||
|
screenshot: 'only-on-failure',
|
||||||
|
},
|
||||||
|
projects: [
|
||||||
|
{ name: 'chromium', use: { ...devices['Desktop Chrome'] } },
|
||||||
|
{ name: 'Mobile Chrome', use: { ...devices['Pixel 5'] } },
|
||||||
|
],
|
||||||
|
webServer: {
|
||||||
|
command: 'npm run dev',
|
||||||
|
url: 'http://localhost:5173',
|
||||||
|
reuseExistingServer: !process.env.CI,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 페이지 오브젝트 패턴
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// pages/BasePage.ts
|
||||||
|
export class BasePage {
|
||||||
|
constructor(protected page: Page) {}
|
||||||
|
|
||||||
|
async goto(path: string) {
|
||||||
|
await this.page.goto(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
async waitForLoaded() {
|
||||||
|
await this.page.waitForLoadState('networkidle');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// pages/LoginPage.ts
|
||||||
|
export class LoginPage extends BasePage {
|
||||||
|
readonly emailInput = this.page.getByLabel('Email');
|
||||||
|
readonly passwordInput = this.page.getByLabel('Password');
|
||||||
|
readonly submitButton = this.page.getByRole('button', { name: 'Login' });
|
||||||
|
readonly errorMessage = this.page.getByRole('alert');
|
||||||
|
|
||||||
|
async login(email: string, password: string) {
|
||||||
|
await this.goto('/login');
|
||||||
|
await this.emailInput.fill(email);
|
||||||
|
await this.passwordInput.fill(password);
|
||||||
|
await this.submitButton.click();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 테스트 픽스처 (로그인 상태 재사용)
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// fixtures/auth.fixture.ts
|
||||||
|
type AuthFixtures = {
|
||||||
|
authenticatedPage: Page;
|
||||||
|
loginPage: LoginPage;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const test = base.extend<AuthFixtures>({
|
||||||
|
authenticatedPage: async ({ page }, use) => {
|
||||||
|
// API로 직접 로그인 (UI 우회 — 빠른 셋업)
|
||||||
|
const response = await page.request.post('/api/v1/auth/login', {
|
||||||
|
data: { email: 'test@example.com', password: 'password123' }
|
||||||
|
});
|
||||||
|
const { token } = await response.json();
|
||||||
|
|
||||||
|
await page.context().addCookies([{ name: 'token', value: token, url: 'http://localhost:5173' }]);
|
||||||
|
await use(page);
|
||||||
|
},
|
||||||
|
|
||||||
|
loginPage: async ({ page }, use) => {
|
||||||
|
await use(new LoginPage(page));
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export { expect } from '@playwright/test';
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 테스트 작성 패턴
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// tests/auth.spec.ts
|
||||||
|
import { test, expect } from '../fixtures/auth.fixture';
|
||||||
|
import { LoginPage } from '../pages/LoginPage';
|
||||||
|
|
||||||
|
test.describe('인증', () => {
|
||||||
|
test('유효한 자격증명으로 로그인 성공', async ({ page }) => {
|
||||||
|
const loginPage = new LoginPage(page);
|
||||||
|
await loginPage.login('user@example.com', 'password123');
|
||||||
|
|
||||||
|
await expect(page).toHaveURL('/home');
|
||||||
|
await expect(page.getByText('Welcome')).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('잘못된 비밀번호로 로그인 실패', async ({ page }) => {
|
||||||
|
const loginPage = new LoginPage(page);
|
||||||
|
await loginPage.login('user@example.com', 'wrong');
|
||||||
|
|
||||||
|
await expect(loginPage.errorMessage).toContainText('Invalid credentials');
|
||||||
|
await expect(page).toHaveURL('/login');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('로그인한 사용자는 대시보드 접근 가능', async ({ authenticatedPage }) => {
|
||||||
|
await authenticatedPage.goto('/dashboard');
|
||||||
|
await expect(authenticatedPage).toHaveURL('/dashboard');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## API 모킹 (선택적)
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// 외부 API 모킹 (백엔드 불안정 시)
|
||||||
|
test('결제 성공 시나리오', async ({ page }) => {
|
||||||
|
await page.route('/api/v1/payments', (route) => {
|
||||||
|
route.fulfill({
|
||||||
|
status: 200,
|
||||||
|
contentType: 'application/json',
|
||||||
|
body: JSON.stringify({ success: true, orderId: 'TEST-001' }),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// 테스트 진행...
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## CI 통합 (GitHub Actions)
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# .github/workflows/e2e.yml
|
||||||
|
name: E2E Tests
|
||||||
|
on: [push, pull_request]
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with: { node-version: 20 }
|
||||||
|
- run: npm ci
|
||||||
|
- run: npx playwright install --with-deps chromium
|
||||||
|
- run: npx playwright test
|
||||||
|
env:
|
||||||
|
BASE_URL: http://localhost:5173
|
||||||
|
- uses: actions/upload-artifact@v4
|
||||||
|
if: failure()
|
||||||
|
with:
|
||||||
|
name: playwright-report
|
||||||
|
path: playwright-report/
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 실행 명령
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 전체 테스트
|
||||||
|
npx playwright test
|
||||||
|
|
||||||
|
# 특정 파일
|
||||||
|
npx playwright test auth.spec.ts
|
||||||
|
|
||||||
|
# UI 모드 (인터랙티브)
|
||||||
|
npx playwright test --ui
|
||||||
|
|
||||||
|
# 리포트 열기
|
||||||
|
npx playwright show-report
|
||||||
|
```
|
||||||
160
skills/zio-harness/references/react.md
Normal file
160
skills/zio-harness/references/react.md
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
# React 개발 가이드
|
||||||
|
|
||||||
|
## 스택 가정
|
||||||
|
- React 18+ + TypeScript
|
||||||
|
- Vite 또는 Next.js
|
||||||
|
- 상태 관리: Zustand (소규모) / Redux Toolkit (대규모)
|
||||||
|
- 스타일: Tailwind CSS 또는 shadcn/ui
|
||||||
|
- API 클라이언트: Axios + TanStack Query (서버 상태)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 폴더 구조 원칙
|
||||||
|
|
||||||
|
```
|
||||||
|
src/
|
||||||
|
├── pages/ # 라우트 단위 페이지 (Next.js: app/ 또는 pages/)
|
||||||
|
├── components/
|
||||||
|
│ ├── ui/ # 재사용 원자 컴포넌트 (Button, Input, Modal)
|
||||||
|
│ └── features/ # 도메인별 조합 컴포넌트
|
||||||
|
├── hooks/ # 커스텀 훅 (use 접두사 필수)
|
||||||
|
├── store/ # Zustand store 또는 Redux slices
|
||||||
|
├── api/ # API 호출 함수 + TanStack Query hooks
|
||||||
|
├── types/ # 전역 TypeScript 타입
|
||||||
|
└── utils/ # 순수 유틸리티 함수
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 컴포넌트 작성 패턴
|
||||||
|
|
||||||
|
### 기본 구조
|
||||||
|
```tsx
|
||||||
|
// src/components/features/UserCard.tsx
|
||||||
|
interface UserCardProps {
|
||||||
|
userId: string;
|
||||||
|
onSelect?: (id: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function UserCard({ userId, onSelect }: UserCardProps) {
|
||||||
|
const { data: user } = useUser(userId); // API 훅
|
||||||
|
|
||||||
|
if (!user) return <Skeleton />;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div onClick={() => onSelect?.(userId)}>
|
||||||
|
{user.name}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### API 훅 패턴 (TanStack Query)
|
||||||
|
```typescript
|
||||||
|
// src/api/users.ts
|
||||||
|
export function useUser(id: string) {
|
||||||
|
return useQuery({
|
||||||
|
queryKey: ['user', id],
|
||||||
|
queryFn: () => api.get<User>(`/api/v1/users/${id}`),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useCreateUser() {
|
||||||
|
return useMutation({
|
||||||
|
mutationFn: (data: CreateUserRequest) =>
|
||||||
|
api.post<User>('/api/v1/users', data),
|
||||||
|
onSuccess: () => queryClient.invalidateQueries({ queryKey: ['users'] }),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Zustand Store 패턴
|
||||||
|
```typescript
|
||||||
|
// src/store/authStore.ts
|
||||||
|
interface AuthState {
|
||||||
|
user: User | null;
|
||||||
|
token: string | null;
|
||||||
|
setAuth: (user: User, token: string) => void;
|
||||||
|
logout: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useAuthStore = create<AuthState>((set) => ({
|
||||||
|
user: null,
|
||||||
|
token: null,
|
||||||
|
setAuth: (user, token) => set({ user, token }),
|
||||||
|
logout: () => set({ user: null, token: null }),
|
||||||
|
}));
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## API 클라이언트 설정
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// src/api/client.ts
|
||||||
|
const api = axios.create({
|
||||||
|
baseURL: import.meta.env.VITE_API_URL,
|
||||||
|
timeout: 10000,
|
||||||
|
});
|
||||||
|
|
||||||
|
api.interceptors.request.use((config) => {
|
||||||
|
const token = useAuthStore.getState().token;
|
||||||
|
if (token) config.headers.Authorization = `Bearer ${token}`;
|
||||||
|
return config;
|
||||||
|
});
|
||||||
|
|
||||||
|
api.interceptors.response.use(
|
||||||
|
(res) => res.data,
|
||||||
|
(err) => {
|
||||||
|
if (err.response?.status === 401) useAuthStore.getState().logout();
|
||||||
|
return Promise.reject(err);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 라우팅 구조 (React Router v6)
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// src/pages/Router.tsx
|
||||||
|
const router = createBrowserRouter([
|
||||||
|
{ path: '/', element: <Layout />, children: [
|
||||||
|
{ index: true, element: <Home /> },
|
||||||
|
{ path: 'users', element: <UserList /> },
|
||||||
|
{ path: 'users/:id', element: <UserDetail /> },
|
||||||
|
]},
|
||||||
|
{ path: '/login', element: <Login /> },
|
||||||
|
]);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 환경 변수 패턴
|
||||||
|
|
||||||
|
```
|
||||||
|
# .env.local (git 제외)
|
||||||
|
VITE_API_URL=http://localhost:8080
|
||||||
|
VITE_APP_NAME=MyApp
|
||||||
|
```
|
||||||
|
|
||||||
|
TypeScript에서 타입 안전하게 접근:
|
||||||
|
```typescript
|
||||||
|
// src/config.ts
|
||||||
|
export const config = {
|
||||||
|
apiUrl: import.meta.env.VITE_API_URL,
|
||||||
|
appName: import.meta.env.VITE_APP_NAME,
|
||||||
|
} as const;
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 컨벤션
|
||||||
|
|
||||||
|
| 항목 | 규칙 | 예시 |
|
||||||
|
|------|------|------|
|
||||||
|
| 컴포넌트 파일 | PascalCase.tsx | `UserProfile.tsx` |
|
||||||
|
| 훅 파일 | camelCase.ts, use 접두사 | `useAuth.ts` |
|
||||||
|
| 유틸 함수 | camelCase.ts | `formatDate.ts` |
|
||||||
|
| 상수 | UPPER_SNAKE_CASE | `MAX_RETRY_COUNT` |
|
||||||
|
| 인터페이스 | PascalCase, I 접두사 없음 | `User`, `CreateUserRequest` |
|
||||||
284
skills/zio-harness/references/spring-boot.md
Normal file
284
skills/zio-harness/references/spring-boot.md
Normal file
@ -0,0 +1,284 @@
|
|||||||
|
# Spring Boot 개발 가이드
|
||||||
|
|
||||||
|
## 스택 가정
|
||||||
|
- Spring Boot 3.x + Java 17+ / Kotlin
|
||||||
|
- Spring Data JPA + Hibernate
|
||||||
|
- Spring Security (JWT)
|
||||||
|
- Flyway (DB 마이그레이션)
|
||||||
|
- Gradle 빌드
|
||||||
|
- 데이터베이스: PostgreSQL (기본), MySQL 지원
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 레이어 아키텍처
|
||||||
|
|
||||||
|
```
|
||||||
|
Controller (HTTP 진입점)
|
||||||
|
↓ DTO (Request)
|
||||||
|
Service (비즈니스 로직)
|
||||||
|
↓ Domain/Entity
|
||||||
|
Repository (데이터 접근)
|
||||||
|
↓
|
||||||
|
Database
|
||||||
|
```
|
||||||
|
|
||||||
|
### 폴더 구조
|
||||||
|
|
||||||
|
```
|
||||||
|
src/main/java/{base.package}/
|
||||||
|
├── controller/ # @RestController — HTTP 요청 처리만
|
||||||
|
├── service/ # @Service — 비즈니스 로직
|
||||||
|
├── repository/ # @Repository — JPA 인터페이스
|
||||||
|
├── domain/ # @Entity — JPA 엔티티
|
||||||
|
├── dto/
|
||||||
|
│ ├── request/ # {Action}{Resource}Request
|
||||||
|
│ └── response/ # {Resource}Response
|
||||||
|
├── config/ # SecurityConfig, CorsConfig, etc.
|
||||||
|
├── exception/ # 커스텀 예외 + GlobalExceptionHandler
|
||||||
|
└── util/ # 유틸리티 클래스
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 컨트롤러 패턴
|
||||||
|
|
||||||
|
```java
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/v1/users")
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class UserController {
|
||||||
|
|
||||||
|
private final UserService userService;
|
||||||
|
|
||||||
|
@GetMapping
|
||||||
|
public ResponseEntity<List<UserResponse>> getUsers() {
|
||||||
|
return ResponseEntity.ok(userService.findAll());
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/{id}")
|
||||||
|
public ResponseEntity<UserResponse> getUser(@PathVariable Long id) {
|
||||||
|
return ResponseEntity.ok(userService.findById(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping
|
||||||
|
public ResponseEntity<UserResponse> createUser(@Valid @RequestBody CreateUserRequest request) {
|
||||||
|
return ResponseEntity.status(HttpStatus.CREATED)
|
||||||
|
.body(userService.create(request));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping("/{id}")
|
||||||
|
public ResponseEntity<UserResponse> updateUser(
|
||||||
|
@PathVariable Long id,
|
||||||
|
@Valid @RequestBody UpdateUserRequest request) {
|
||||||
|
return ResponseEntity.ok(userService.update(id, request));
|
||||||
|
}
|
||||||
|
|
||||||
|
@DeleteMapping("/{id}")
|
||||||
|
public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
|
||||||
|
userService.delete(id);
|
||||||
|
return ResponseEntity.noContent().build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 서비스 패턴
|
||||||
|
|
||||||
|
```java
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@Transactional(readOnly = true)
|
||||||
|
public class UserService {
|
||||||
|
|
||||||
|
private final UserRepository userRepository;
|
||||||
|
|
||||||
|
public List<UserResponse> findAll() {
|
||||||
|
return userRepository.findAll().stream()
|
||||||
|
.map(UserResponse::from)
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserResponse findById(Long id) {
|
||||||
|
User user = userRepository.findById(id)
|
||||||
|
.orElseThrow(() -> new EntityNotFoundException("User not found: " + id));
|
||||||
|
return UserResponse.from(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public UserResponse create(CreateUserRequest request) {
|
||||||
|
User user = User.builder()
|
||||||
|
.email(request.getEmail())
|
||||||
|
.name(request.getName())
|
||||||
|
.build();
|
||||||
|
return UserResponse.from(userRepository.save(user));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 엔티티 패턴
|
||||||
|
|
||||||
|
```java
|
||||||
|
@Entity
|
||||||
|
@Table(name = "users")
|
||||||
|
@Getter
|
||||||
|
@NoArgsConstructor(access = AccessLevel.PROTECTED)
|
||||||
|
@Builder
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class User extends BaseEntity { // createdAt, updatedAt 포함
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Column(unique = true, nullable = false)
|
||||||
|
private String email;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private String name;
|
||||||
|
}
|
||||||
|
|
||||||
|
// BaseEntity.java
|
||||||
|
@MappedSuperclass
|
||||||
|
@EntityListeners(AuditingEntityListener.class)
|
||||||
|
public abstract class BaseEntity {
|
||||||
|
@CreatedDate
|
||||||
|
private LocalDateTime createdAt;
|
||||||
|
|
||||||
|
@LastModifiedDate
|
||||||
|
private LocalDateTime updatedAt;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## DTO 패턴
|
||||||
|
|
||||||
|
```java
|
||||||
|
// Request
|
||||||
|
public record CreateUserRequest(
|
||||||
|
@NotBlank @Email String email,
|
||||||
|
@NotBlank @Size(min=2, max=50) String name
|
||||||
|
) {}
|
||||||
|
|
||||||
|
// Response — 정적 팩토리 메서드 포함
|
||||||
|
public record UserResponse(Long id, String email, String name) {
|
||||||
|
public static UserResponse from(User user) {
|
||||||
|
return new UserResponse(user.getId(), user.getEmail(), user.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 예외 처리
|
||||||
|
|
||||||
|
```java
|
||||||
|
@RestControllerAdvice
|
||||||
|
public class GlobalExceptionHandler {
|
||||||
|
|
||||||
|
@ExceptionHandler(EntityNotFoundException.class)
|
||||||
|
public ResponseEntity<ErrorResponse> handleNotFound(EntityNotFoundException e) {
|
||||||
|
return ResponseEntity.status(HttpStatus.NOT_FOUND)
|
||||||
|
.body(new ErrorResponse("NOT_FOUND", e.getMessage()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExceptionHandler(MethodArgumentNotValidException.class)
|
||||||
|
public ResponseEntity<ErrorResponse> handleValidation(MethodArgumentNotValidException e) {
|
||||||
|
String message = e.getBindingResult().getFieldErrors().stream()
|
||||||
|
.map(f -> f.getField() + ": " + f.getDefaultMessage())
|
||||||
|
.collect(Collectors.joining(", "));
|
||||||
|
return ResponseEntity.badRequest()
|
||||||
|
.body(new ErrorResponse("VALIDATION_ERROR", message));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public record ErrorResponse(String code, String message) {}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## JWT 보안 설정
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# application.yml
|
||||||
|
spring:
|
||||||
|
datasource:
|
||||||
|
url: ${DB_URL:jdbc:postgresql://localhost:5432/myapp}
|
||||||
|
username: ${DB_USERNAME:postgres}
|
||||||
|
password: ${DB_PASSWORD:password}
|
||||||
|
jpa:
|
||||||
|
hibernate:
|
||||||
|
ddl-auto: validate # Flyway 사용 시 validate
|
||||||
|
open-in-view: false
|
||||||
|
|
||||||
|
jwt:
|
||||||
|
secret: ${JWT_SECRET}
|
||||||
|
expiration: 86400000 # 24시간 (ms)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## DB 마이그레이션 (Flyway)
|
||||||
|
|
||||||
|
```
|
||||||
|
src/main/resources/db/migration/
|
||||||
|
├── V1__create_users_table.sql
|
||||||
|
├── V2__add_user_role.sql
|
||||||
|
└── V3__create_posts_table.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
네이밍: `V{version}__{description}.sql` (V 대문자, 밑줄 2개)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 테스트 패턴
|
||||||
|
|
||||||
|
```java
|
||||||
|
// 서비스 단위 테스트
|
||||||
|
@ExtendWith(MockitoExtension.class)
|
||||||
|
class UserServiceTest {
|
||||||
|
@InjectMocks UserService userService;
|
||||||
|
@Mock UserRepository userRepository;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void 사용자_생성_성공() {
|
||||||
|
// given
|
||||||
|
given(userRepository.save(any())).willReturn(testUser());
|
||||||
|
// when
|
||||||
|
UserResponse response = userService.create(new CreateUserRequest("a@b.com", "Alice"));
|
||||||
|
// then
|
||||||
|
assertThat(response.email()).isEqualTo("a@b.com");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 통합 테스트
|
||||||
|
@SpringBootTest
|
||||||
|
@AutoConfigureMockMvc
|
||||||
|
class UserControllerTest {
|
||||||
|
@Autowired MockMvc mockMvc;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void GET_users_returns_list() throws Exception {
|
||||||
|
mockMvc.perform(get("/api/v1/users").contentType(APPLICATION_JSON))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$").isArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 컨벤션
|
||||||
|
|
||||||
|
| 항목 | 규칙 |
|
||||||
|
|------|------|
|
||||||
|
| 엔티티 | 단수 명사 (User, Post) |
|
||||||
|
| 컨트롤러 | {Resource}Controller |
|
||||||
|
| 서비스 | {Resource}Service |
|
||||||
|
| 리포지토리 | {Resource}Repository |
|
||||||
|
| Request DTO | {Action}{Resource}Request |
|
||||||
|
| Response DTO | {Resource}Response |
|
||||||
|
| API 경로 | `/api/v1/{resource}` (복수, kebab-case) |
|
||||||
Loading…
Reference in New Issue
Block a user