스킬·플러그인·변환도구
0874a27입니다.agents는 AI 코딩 도구에 전문 역할·지식·작업 절차를 추가하는 플러그인 모음과 Python 변환 도구입니다. 전문 지식은 하나의 Markdown 원본으로 관리하고, 도구마다 다른 형식과 제약은 어댑터가 처리합니다.
지원 대상으로 열거한 도구는 Claude Code, OpenAI Codex CLI, Cursor, OpenCode, Google Antigravity CLI, GitHub Copilot, Pi입니다. 저장소 자체가 이 일곱 도구를 동시에 실행하는 서비스는 아닙니다. 실제 파일 읽기·수정·모델 호출은 설치한 구성요소를 읽는 각 코딩 도구가 담당합니다.
plugins/는 원고 보관함입니다. 에이전트는 “누가 담당하는가”, 스킬은 “무엇을 참고하는가”, 명령은 “어떤 순서로 진행하는가”를 적습니다. 플러그인은 관련 원고를 묶은 한 권의 책입니다.
회사마다 서식과 권한 체계가 다르므로 납품 담당자가 내용을 변환합니다. 그 담당자가 tools/adapters/입니다. 책을 전달했다고 회사의 모든 업무 시스템까지 똑같아지는 것은 아니듯, 변환 후 기능에도 차이가 남습니다.
| 단위 | 실제 위치 | 쉬운 역할 |
|---|---|---|
| 플러그인 | plugins/python-development/ | Python 관련 에이전트·스킬·명령을 묶는 설치 단위 |
| 에이전트 | plugins/python-development/agents/python-pro.md | Python 전문가에게 어떤 책임과 태도를 줄지 정의 |
| 스킬 | plugins/python-development/skills/python-testing-patterns/SKILL.md | 테스트 작업에 필요한 개념·지침·참고 자료 제공 |
| 명령 | plugins/python-development/commands/python-scaffold.md | 요구사항을 받아 프로젝트 뼈대를 만드는 절차 정의 |
위 세 구성요소는 모두 plugins/python-development/에 묶여 있습니다. plugins/python-development/agents/python-pro.md를 열면 Python 클래스 대신 YAML 머리말과 자연어 지침이 나옵니다. 그 파일을 읽는 코딩 도구가 모델에게 역할을 전달합니다.
plugins/python-development/agents/python-pro.md
↓ load_plugin(): 머리말과 본문 읽기
AgentSource(plugin, name, frontmatter, body)
↓ CodexAdapter._emit_agent(): 형식·모델·권한 변환
.codex/agents/python-development__python-pro.toml
↓ 해당 하네스의 발견·호출 규칙
전문 역할을 사용하는 코딩 작업
핵심 학습 대상은 “좋은 문장을 많이 모으는 법”에 그치지 않습니다. 문서를 구조화된 데이터로 읽고, 서로 다른 시스템에 배포하며, 변환 중 지켜야 할 조건을 자동 검사하는 방법을 배울 수 있습니다.
2026-10-23 GitHub Trending Python 주간 6위로 선정된 저장소이며, 같은 날짜 GitHub 기준 스타는 41,588개입니다. 다만 순위와 누적 스타만으로 유입 경로나 특정 기능의 효과까지 알 수는 없습니다. 아래의 주목 요인은 저장소에서 관찰되는 특징을 바탕으로 한 해석입니다.
plugins/에 남고, 변환 규칙은 Python 코드로 분리됩니다. 여러 도구용 사본을 사람이 계속 고치는 일을 줄입니다.이 프로젝트의 장점은 실행 엔진을 새로 만드는 데보다, 이미 사용하는 코딩 도구 사이에서 업무 지식을 재사용하는 데 있습니다.
| 선택지 | 주로 만드는 것 | agents와 비교해 볼 지점 |
|---|---|---|
| 개인 지침 파일 | 한 프로젝트에 맞춘 규칙과 역할 | 가볍게 시작하기 좋지만, 여러 도구의 형식·충돌·배포 규칙은 직접 관리해야 함 |
| wshobson/agents | 공유 Markdown 카탈로그와 도구별 배포 파일 | 전문 지침을 재사용하고 변환 규칙을 학습하기 좋음. 실제 작업 실행은 하네스에 의존 |
| LangGraph | 상태를 유지하는 에이전트 실행 그래프 | 중단 후 재개·상태·장기 실행 흐름을 코드로 설계할 때 초점이 맞음 |
| CrewAI | 협업 에이전트 팀과 실행 흐름 | Crews의 역할 분담과 Flows의 상태·이벤트 제어로 애플리케이션을 구성 |
LangGraph의 상태·지속 실행 설명은 공식 저장소, CrewAI의 Crews·Flows 구분은 공식 소개에 근거합니다. 이들은 설계 대상이 다르므로, 위 비교는 속도나 모델 성능의 우열을 뜻하지 않습니다.
팀이 사용할 조리법을 정리하고 여러 주방의 양식으로 배포하려면 agents의 구조가 좋은 참고가 됩니다. 주문 상태·작업 순서·실패 후 재개까지 제어하는 주방 운영 프로그램을 만들려면 실행 프레임워크의 개념을 추가로 배워야 합니다.
tools/adapters/capabilities.py는 하네스별 기능을 Capability 데이터로 표현합니다. skills_native, commands_native, tool_allowlist_per_agent 같은 필드가 따로 있는 이유입니다. 명령이 어떤 도구에서는 스킬이 되고, 다른 도구에서는 프롬프트 템플릿이 됩니다.
특히 Codex의 네이티브 마켓플레이스 경로는 skills: "./skills/"를 가리킵니다. 변환된 TOML 에이전트와 명령 유래 스킬은 별도 어댑터 경로에 있습니다. Pi의 에이전트 파일은 기본 코어가 아니라 참조용 subagent 확장 또는 호환 확장을 전제로 합니다. 설치 경로까지 확인해야 실제로 얻는 구성이 분명해집니다.
설명 파일이 많다고 단순한 자료실은 아닙니다. 파일 이름, 설명문, 참조 경로, 권한, 모델 별칭이 모두 동작에 영향을 줍니다. 이 저장소는 그 경계를 Python으로 다루는 작은 시스템을 보여줍니다.
핵심은 HTTP 요청을 받는 서버가 아니라 명령행 도구입니다. tools/generate.py는 표준 라이브러리 argparse로 옵션을 받고, pathlib로 파일을 다룹니다. tools/adapters/base.py는 dataclasses와 abc를 사용합니다. 평가 CLI는 Typer, 결과 데이터 검증은 Pydantic, 터미널 표시는 Rich를 사용합니다.
공통 Python 도구 환경은 plugins/plugin-eval/pyproject.toml에서 관리합니다. 프로젝트 버전은 0.1.0, 요구 Python은 >=3.12입니다. 같은 디렉토리의 .python-version은 3.14를 지정하며, 일부 CI 작업은 UV_PYTHON: "3.12"로 덮어씁니다.
| 패키지 | pyproject.toml 선언 | uv.lock 버전과 역할 |
|---|---|---|
| Pydantic | >=2.13.4 | 2.14.1 · 평가 설정·결과 모델의 범위와 형식 검사 |
| Typer | >=0.27.1 | 0.27.3 · plugin-eval 명령행 인터페이스 |
| Rich | >=15.0.0 | 15.0.0 · 터미널 출력 |
| PyYAML | >=6.0 | 6.0.3 · YAML을 사용하는 평가·검증·테스트 |
| Claude Agent SDK | >=0.2.138 · 선택 llm | 0.2.165 · 실험적 모델 심사·반복 평가 |
| pytest | >=9.1.1 · 선택 dev | 9.1.1 · 단위·통합 테스트 |
| pytest-asyncio | >=1.4.0 · 선택 dev | 1.4.0 · 비동기 테스트 |
| Ruff | >=0.16.3 · 선택 dev | 0.17.0 · 린트와 포맷 검사 |
| ty | >=0.0.71 · 선택 dev | 0.0.86 · 정적 타입 검사 |
이 표의 선언과 고정 버전은 모두 커밋 0874a27 기준입니다. >=는 허용 범위의 하한이고, 잠금 파일의 숫자는 해당 의존성 해석 결과입니다. hatchling.build는 패키지 빌드 백엔드로 선언되어 있지만, 그 선언에 버전 핀은 없습니다.
저장소 루트에는 package.json, Cargo.toml, pyproject.toml, go.mod, Dockerfile이 없습니다. 자체 React 화면이나 웹 서버를 실행하는 구조로 읽으면 흐름이 어긋납니다. 독자가 접하는 주된 화면은 각 하네스의 CLI·에디터와 저장소의 Markdown 문서입니다.
plugins/python-development/commands/python-scaffold.md 안에는 FastAPI·Django·Uvicorn 설정 예제가 있습니다. 이것은 사용자의 새 프로젝트를 만들기 위한 지침입니다. 그 예제에 나온 패키지가 agents 자체의 서버 의존성이라는 뜻은 아닙니다. 다른 플러그인에 등장하는 React·Kubernetes·데이터베이스도 같은 방식으로 구분해서 읽어야 합니다.
Makefile은 생성·검증·문서 검사·테스트 명령을 묶습니다. UV_TOOLS := uv run --project plugins/plugin-eval python이 공통 실행 환경을 선택하고, HARNESSES에는 원본 형식인 Claude Code를 제외한 여섯 대상이 들어 있습니다.
# Makefile의 핵심 변수
GENERATE := tools/generate.py
HARNESSES := codex copilot cursor opencode antigravity pi
# plugins/plugin-eval/pyproject.toml의 품질 설정
[tool.ruff]
target-version = "py312"
line-length = 100
[tool.pytest.ini_options]
testpaths = ["tests"]
asyncio_mode = "auto"
.github/workflows/validate.yml은 ubuntu-latest에서 JSON 검사, 평가 테스트, 어댑터 테스트, 재생성 후 변경 감지, 구조 검증, 실제 CLI 스모크 테스트를 정의합니다. 실제 CLI 작업에는 OpenCode 1.18.30, Pi 0.85.1, Node.js 22가 명시되어 있습니다. Antigravity 설치 단계에는 버전 핀이 없고, 어댑터 주석의 검증 대상은 agy 1.1.14입니다.
Actions 자체도 actions/checkout@34e1148…처럼 전체 커밋 SHA로 고정합니다. 다만 ubuntu-latest, Bun의 latest, 버전 없는 설치 단계까지 모두 고정된 환경은 아닙니다. “일부를 고정했다”와 “완전히 재현 가능하다”를 구분하는 좋은 사례입니다.
tools/yt-design-extractor/는 패키지를 설치하지 않고 의존성만 관리하는 별도 uv 프로젝트입니다. Python 요구사항은 >=3.10이고 package = false로 설정되어 있습니다. tools/yt-design-extractor/yt-design-extractor.py의 get_transcript(), extract_frames_interval(), run_ocr_on_frames()가 자막·프레임·문자 인식을 다룹니다.
| 분야 | 선언한 하한 | 잠금 버전 |
|---|---|---|
| 영상·자막 | yt-dlp>=2026.7.4, youtube-transcript-api>=0.6.0 | 2026.8.19, 1.2.4 |
| 이미지·OCR | Pillow>=10.0.0, pytesseract>=0.3.10 | 12.3.0, 0.3.13 |
| 색상 추출 | colorthief>=0.2.1 | 0.2.1 |
| 선택 EasyOCR | easyocr>=1.7, torch>=2.13.0 | 1.7.2, 2.14.1 · 플러그인 변환의 필수 의존성이 아님 |
| 분류 | 파일 수 / 줄 수 | 해석 |
|---|---|---|
| Markdown | 794개 / 204,346줄 | 업무 지침·문서·코드 블록 예제 포함 |
| Python | 70개 / 19,646줄 | 어댑터·평가·설치 도구·테스트·샘플 포함 |
| JSON | 254개 / 9,292줄 | 마켓플레이스·플러그인 선언·평가 스냅샷 등 |
| YAML | 17개 / 2,515줄 | .yml과 .yaml 합계, CI·템플릿 포함 |
| Shell | 10개 / 894줄 | 일부 플러그인 훅·보조 검사 |
| C# | 2개 / 859줄 | 플러그인 안의 교육용 템플릿 자산 |
집계는 Git 내부 파일과 심볼릭 링크를 제외하고, 각 텍스트 파일의 빈 줄·주석도 포함한 물리적 줄 수입니다. Markdown 내부 코드 블록은 Markdown에만 셉니다. Python 중 tools/adapters/는 2,769줄, 평가 패키지 구현은 3,214줄, 두 테스트 디렉토리는 합계 8,637줄입니다. GitHub의 언어 비율을 다시 계산한 결과는 아닙니다.
이 저장소를 읽을 때는 Python이 지식을 운반하는 도구이고, Markdown이 운반할 핵심 데이터라는 관계를 먼저 잡아야 합니다.
전체 구조에는 두 길이 있습니다. 하나는 마켓플레이스 선언이 원본 플러그인 디렉토리를 가리키는 길이고, 다른 하나는 Python 어댑터가 도구 전용 파일을 생성하는 길입니다. 모든 설치가 반드시 모든 변환 단계를 거치는 것은 아닙니다.
tools/adapters/base.py의 parse_frontmatter()는 Markdown을 머리말 사전과 본문 문자열로 나눕니다. load_plugin()은 디렉토리를 탐색해 AgentSource, SkillSource, CommandSource를 만들고, 이를 PluginSource에 모읍니다.
# tools/adapters/base.py — 실제 데이터 구조 일부
@dataclass
class AgentSource:
plugin: str
name: str
path: Path
frontmatter: dict
body: str
@dataclass
class PluginSource:
name: str
dir: Path
plugin_json: dict
agents: list[AgentSource] = field(default_factory=list)
skills: list[SkillSource] = field(default_factory=list)
commands: list[CommandSource] = field(default_factory=list)
어댑터는 디스크를 다시 해석하는 대신 이 공통 객체를 받습니다. 입력 규칙이 바뀌면 파싱 쪽을, 출력 형식이 바뀌면 해당 어댑터를 중심으로 수정할 수 있습니다. 한 번 읽은 원본을 공통 데이터로 정리한다는 점에서 컴파일러의 중간 표현과 비슷합니다.
--- 사이에 적는 이름·설명·설정입니다. 중간 표현은 입력 파일도 최종 출력 파일도 아닌, 프로그램이 다루기 편하게 정리한 공통 데이터입니다. 이 구현의 PluginSource 계열이 그 역할을 합니다.주의할 점도 있습니다. 어댑터의 parse_frontmatter()는 완전한 YAML 구현이 아니라, 목록·한 단계 사전·일부 여러 줄 값을 다루는 관대한 자체 파서입니다. 문서의 모든 YAML 표현이 동일하게 해석될 것이라고 가정하면 안 됩니다. 뒤의 출력 검증 단계가 필요한 이유입니다.
HarnessAdapter는 추상 메서드 emit_plugin()과 기본 구현이 비어 있는 emit_global()을 제공합니다. tools/generate.py의 get_adapter()가 대상 이름에 맞는 클래스를 지연 import합니다. 공통 실행 흐름은 유지하면서 출력 전략만 바꾸는 구조입니다.
# tools/adapters/base.py — 공통 계약의 핵심
class HarnessAdapter(ABC):
@abstractmethod
def emit_plugin(self, plugin: PluginSource) -> EmitResult:
...
# tools/adapters/capabilities.py — 커밋 기준 변환표 일부
MODEL_ALIASES = {
"codex": {
"opus": "gpt-5.5",
"sonnet": "gpt-5.4-mini",
"inherit": "gpt-5.5",
},
}
위 표는 저장소에 들어 있는 매핑의 일부이며, 현재 모델 선택을 권장하는 표가 아닙니다. resolve_model()은 알려진 별칭을 바꾸고, 알 수 없는 별칭은 대체값과 경고를 반환합니다. 이 커밋에서 Codex의 inherit는 문자열 그대로 전달되지 않고 고정 모델로 해석됩니다. Antigravity는 inherit를 유지하고, Pi는 상속일 때 출력에서 model 필드를 생략합니다.
| 원본 tools 설정 | Codex _emit_agent() | OpenCode _build_permission_block() |
|---|---|---|
| 필드 없음 | workspace-write로 추론 | 권한 블록을 만들지 않음 |
[Read, Grep] | read-only로 추론 | 매핑된 읽기 기능 허용, 다른 기능 거부. 기본 skill·task 허용 |
[] | read-only로 축약 | 기본 skill·task 외의 권한 거부 |
[Read, Write] | workspace-write로 추론 | 매핑된 읽기·쓰기와 기본 기능 허용 |
빈 목록과 필드 누락은 다릅니다. AgentSource.tools 속성만 보면 둘 다 빈 목록이 될 수 있어, 어댑터는 "tools" in agent.frontmatter도 함께 확인합니다. 또한 Codex의 샌드박스 모드는 도구별 허용 목록을 완전히 보존하지 못합니다. read-only가 “도구를 하나도 쓰지 못한다”와 같은 뜻은 아닙니다.
OpenCode 변환도 만능은 아닙니다. MCP 전용처럼 원본 도구 이름이 하나도 매핑되지 않으면 빈 권한 블록을 반환하며, MCP 설정 쪽에 맡깁니다. Pi는 원본 tools: []를 빈 목록으로 전달하지 않고 읽기 도구 목록으로 바꿉니다. 원본의 의도를 얼마나 보존하는지 확인하는 일이 파일 확장자를 바꾸는 일보다 중요합니다.
tools/adapters/codex.py의 SKILL_BODY_CAP = 7400은 이 구현이 정한 본문 예산입니다. 기능 행렬과 검증기는 전체 스킬 파일에 대해 8 * 1024바이트를 기준으로 삼습니다. 본문 외에 머리말과 참조 안내가 붙기 때문에 본문 예산을 더 작게 둡니다.
_split_body_if_oversized()는 우선 제목 ## 경계를 활용해 본문과 초과분을 나눕니다. 어댑터는 초과분을 references/details.md에 저장하되, 스킬 원본에 같은 파일이 있으면 references/_overflow.md에 저장합니다. _split_body_fence_aware()는 백틱 코드 울타리 안의 제목을 절 구분자로 오인하지 않도록 처리합니다. 아주 긴 첫 부분은 _utf8_safe_cut()로 잘라냅니다.
# tools/adapters/codex.py — UTF-8 문자 경계로 뒤로 이동
end = cap
while end > 0 and (encoded[end] & 0xC0) == 0x80:
end -= 1
# 문자 수와 바이트 수가 다른 이유
len("가") # 1
len("가".encode("utf-8")) # 3
UTF-8의 이어지는 바이트는 상위 비트가 10으로 시작합니다. 위 조건은 절단 위치가 그 중간에 놓이면 뒤로 이동합니다. 단순히 문자열 7,400자를 고르는 방식으로는 한국어·이모지가 있는 파일의 바이트 상한을 지킬 수 없습니다.
스킬 본문에는 목차와 바로 필요한 절차를 두고, 두꺼운 상세 설명은 참고 파일로 옮깁니다. 작업자가 처음부터 책 전체를 들고 다니는 대신 필요한 장을 펼치는 방식입니다. 다만 참고 파일을 언제 읽을지는 하네스와 모델의 행동에도 영향을 받습니다.
이 구조는 모델의 지식을 새로 학습시키는 과정이 아닙니다. 작업 중 읽는 문서를 어떻게 나누어 배치할지 정하는 방식입니다. 짧은 본문과 풍부한 참고 자료가 서로 연결되어 있어야 효과가 있습니다.
Codex의 에이전트·변환 스킬 이름은 <plugin>__<leaf>처럼 묶어 충돌을 줄입니다. 같은 플러그인 안의 명령과 스킬 이름이 같으면 Codex 어댑터는 명령 쪽에 __command를 붙이고, 그 이름도 스킬과 겹치면 __cmd로 우회합니다. load_plugin()은 구분자와 혼동되는 __가 포함된 플러그인 이름을 거부합니다.
HarnessAdapter.write()는 출력 경로를 resolve()한 다음 is_relative_to()로 출력 루트 안에 있는지 검사합니다. tools/generate.py는 EmitResult.written에 기록된 파일을 모으고, --all과 --prune을 함께 지정한 전체 생성에 오류가 없을 때만 prune_orphans()로 더 이상 생성되지 않는 산출물을 정리합니다.
| 검사 층 | 실제 코드 | 찾으려는 문제 |
|---|---|---|
| 출력 형식 | tools/validate_generated.py의 validate_codex() 등 | TOML 파싱 실패, 필수 필드 누락, 이름 불일치, 파일 크기 초과 |
| 문서·원본 관계 | tools/doc_gardener.py의 check_doc_counts(), check_dead_links() | 카탈로그 수치 불일치, 끊어진 내부 참조, 오래된 산출물 |
| 변환 동작 | tools/tests/test_adapters.py, tools/tests/test_round_trip.py | 변환 규칙, 원본·출력 수량, 파싱 가능 여부 |
| 도구의 실제 해석 | tools/tests/test_cli_smoke.py | Python 파서로는 맞지만 실제 CLI에서 발견·해석되지 않는 구성 |
좋은 어댑터는 파일을 만들어 내는 데서 끝나지 않고, 변환 뒤에도 무엇이 유지되어야 하는지 검사합니다.
단, 오류 발생 시 이미 쓴 파일까지 모두 되돌리는 트랜잭션 구조는 아닙니다. 생성 함수는 플러그인별 오류를 모아 계속 진행하고, 오류가 있으면 정리 단계를 건너뜁니다. “정리하지 않아 손실을 줄인다”와 “전체 생성이 원자적이다”는 구분해야 합니다.
다음 트리는 핵심 경로를 추린 것입니다. 점(.)으로 시작하는 폴더에는 하네스별 배포 설정이 담겨 있습니다. 생성되는 디렉토리와 버전 관리되는 선언 파일을 구분해서 봅시다.
| 경로 | 역할 | 읽을 때 확인할 질문 |
|---|---|---|
plugins/ | 사람이 작성하는 지식과 플러그인 구성 | 역할·지식·절차를 어떤 파일로 나누었나? |
tools/adapters/ | 하네스별 변환 규칙 | 같은 원본이 어디서 다른 의미로 바뀌나? |
tools/tests/ | 변환과 설치 동작의 계약 검사 | 어떤 경계 조건을 특히 보호하나? |
plugins/plugin-eval/ | 평가 구현과 공통 Python 개발 환경 | 점수는 무엇을 측정하며 무엇을 못 보나? |
evals/ | 평가 데이터와 기준 스냅샷 | 점수 변화와 입력 변경을 어떻게 구분하나? |
docs/ | 설계 이유·하네스 차이·작성 규약 | 구현에 남아 있는 제약을 어디서 설명하나? |
.github/workflows/ | 검사를 자동화하는 CI 정의 | 어떤 오류가 병합을 막고, 어떤 경고는 통과하나? |
.gitignore는 .codex/, .opencode/, .copilot/, .antigravity/, .pi/의 생성물을 제외합니다. 반면 작은 네이티브 설치 선언인 .agents/plugins/marketplace.json, plugins/*/.codex-plugin/plugin.json, .cursor-plugin/, .cursor/는 커밋합니다.
커밋하는 생성 파일에도 이유가 있습니다. 원본 디렉토리를 가리키는 작은 선언을 함께 배포하면 사용자가 전체 변환기를 돌리지 않고 해당 설치 경로를 이용할 수 있습니다. CI는 재생성 후 git status --porcelain이 비어 있는지 검사해, 선언이 원본과 어긋나지 않게 합니다.
보조 파일 복사 범위도 읽어야 합니다. Codex의 _emit_skill()은 기존 references/를 복사합니다. Copilot의 _emit_skill()은 숨김 파일을 제외한 스킬 지원 트리를 복사하고 심볼릭 링크를 거부합니다. assets/라는 폴더가 원본에 있다고 모든 어댑터가 똑같이 옮기는 것은 아닙니다.
python-development의 세 문서를 읽고 → tools/adapters/base.py의 load_plugin()으로 자료 구조를 이해하고 → tools/adapters/codex.py의 _emit_agent()에서 한 파일의 변환을 따라가고 → tools/tests/test_adapters.py에서 결과의 기대 형태를 확인합니다.
처음부터 플러그인 92개를 모두 읽기보다, 입력 하나가 출력 하나가 되는 과정을 끝까지 설명할 수 있는지를 확인하는 편이 학습에 도움이 됩니다.
어댑터의 PluginSource 계열은 @dataclass입니다. 이미 읽은 정보를 묶어 전달하는 데 초점을 맞춥니다. 평가 쪽 plugins/plugin-eval/src/plugin_eval/models.py는 Pydantic의 BaseModel과 Field로 사용자 옵션과 결과 범위를 검사합니다.
# plugins/plugin-eval/src/plugin_eval/models.py — 동시성 옵션의 유효 범위
class EvalConfig(BaseModel):
depth: Depth = Depth.STANDARD
concurrency: int = Field(default=4, ge=1, le=20)
output_format: str = "json"
verbose: bool = False
corpus_path: str | None = None
judges: int = Field(default=1, ge=1, le=5)
monte_carlo_n: int | None = None
concurrency=0이나 21은 선언된 범위 밖입니다. 내부 자료를 담는 객체와 외부 입력을 검증하는 객체가 같은 도구를 쓸 필요는 없습니다. 실습 아이디어: “파일 위치를 보관한다”와 “점수가 0~1인지 확인한다”를 각각 어느 종류의 모델에 맡길지 적어 보세요.
parse_frontmatter()는 원본을 관대하게 읽고, yaml_scalar()는 출력할 때 특수 문자를 처리합니다. tools/adapters/codex.py의 _toml_kv()는 줄바꿈·따옴표·역슬래시를 고려합니다. 입력 파싱과 출력 이스케이프는 서로 다른 문제입니다.
예를 들어 설명이 Read: configuration이면 콜론 때문에 출력 문법을 신경 써야 합니다. tools: []는 빈 문자열과도 다릅니다. 실습 아이디어: 콜론, 쉼표, 따옴표, 여러 줄 문자열, 한국어가 들어간 예시를 각각 만들고 출력할 때 어떤 표현이 필요한지 표시해 보세요.
tools/tests/test_adapters.py는 작은 synthetic_plugin과 격리된 output_root를 사용합니다. test_emits_agent_toml_with_remapped_model()은 출력 파일 존재만 보지 않고 TOML을 다시 파싱해 이름·모델·샌드박스를 검사합니다.
# tools/tests/test_adapters.py — 검사의 핵심 일부
parsed = tomllib.loads(content)
assert parsed["name"] == "demo__greeter"
assert parsed["model"] == "gpt-5.5"
assert parsed["sandbox_mode"] == "read-only"
assert "color" not in parsed
tools/tests/test_round_trip.py는 에이전트 수량, 전체 스킬 파일의 바이트 상한, 출력 파싱 등을 봅니다. 이런 검사는 텍스트가 조금 바뀌어도 유지해야 할 계약을 확인합니다. 실습 아이디어: “큰 파일도 만들어진다” 대신 “한글이 손상되지 않고 전체 크기가 상한 안이다”라는 검증 문장을 적어 보세요.
plugins/plugin-eval/src/plugin_eval/layers/monte_carlo.py는 asyncio.Semaphore로 동시 실행 수를 제어하며, 기본 설정은 n_runs=50, concurrency=4입니다. EvalEngine.evaluate_skill()은 깊이에 따라 심사와 반복 평가를 선택합니다.
# plugins/plugin-eval/src/plugin_eval/engine.py — 실제 실행 순서
async def _run_llm_layers(judge, mc, skill):
judge_result = await judge.analyze_skill(skill)
mc_result = await mc.analyze_skill(skill)
return judge_result, mc_result
주변 주석에는 두 층을 함께 실행한다는 표현이 있지만, 위 함수에서는 첫 번째 평가를 기다린 다음 두 번째 평가를 시작합니다. 각 층 내부의 동시성과 층 사이의 동시성은 별개입니다. 실습 아이디어: 두 층의 내부 작업 수와 동시성 상한을 상자 그림으로 나누어 표현하고, 순차 실행과 병렬 실행의 차이를 설명해 보세요.
StaticAnalyzer.analyze_skill()은 머리말·오케스트레이션 문서·점진적 공개·구조·토큰 효율·생태계 일관성·하네스 이식성을 점수로 합칩니다. 정적 가중치는 각각 0.32 / 0.23 / 0.14 / 0.10 / 0.09 / 0.06 / 0.06입니다. 이름과 설명, 특정 문구, 문서 길이 같은 신호를 사용합니다.
anti_pattern_penalty()는 문제 개수에 대해 max(0.5, 1.0 - 0.05 * count)를 반환합니다. 문서 구조의 이상을 찾는 데는 유용하지만, 업무 결과물이 정확한지 직접 실행해 채점하는 식은 아닙니다. 정적 점수의 가중치와 plugins/plugin-eval/src/plugin_eval/engine.py의 최종 차원 가중치도 서로 다른 표입니다.
| 평가 깊이 | 스킬 단위에서 실행하는 층 | 읽어야 할 의미 |
|---|---|---|
quick | 정적 분석 | 문서 구조와 규칙의 신호. 모델 호출 없음 |
standard | 정적 분석 + LLM 심사 | 실험적 모델 판단이 추가됨. 사용자 평가와의 검증은 별개 |
deep | 위 두 층 + 기본 50회 반복 평가 | 반복 응답의 여러 통계를 수집. 작업 성공의 직접 측정은 아님 |
thorough | 같은 세 층 + 기본 100회 반복 평가 | 반복 수를 늘림. 표본 수 증가가 지표의 타당성까지 보장하지 않음 |
EvalEngine.evaluate_plugin()은 요청한 깊이에 상관없이 플러그인 전체를 정적 층으로만 평가하며, 신뢰도 표기를 Estimated로 둡니다. 스킬 단위 깊은 평가의 표시인 Certified·Certified+도 이 프로그램이 정한 이름이지 외부 인증은 아닙니다.
# plugins/plugin-eval/src/plugin_eval/layers/monte_carlo.py — _simresult_from_messages() 일부
raw = "" if output.errored else (
output.text.strip() or (output.result or "").strip()
)
activated = bool(raw)
quality_score = min(1.0, len(raw) / 500) if activated else 0.0
오류가 없고 응답이 있으면 활성화로 기록하며, 500자에 도달하면 길이 기반 품질값은 1이 됩니다. 500자의 틀린 설명과 500자의 정확한 설명을 이 식만으로 구별할 수 없습니다. run_simulation()은 호출 옵션에 allowed_tools=[]를 전달하고, 스킬 내용과 요청에 대한 모델 응답을 수집합니다. 실제 저장소 수정 결과와 테스트 통과 여부를 판정하는 평가 구조는 아닙니다.
점수가 높다는 말보다 먼저 확인할 것은, 그 점수가 실제로 어떤 관찰값에서 계산되었는가입니다.
plugins/plugin-eval/README.md와 evals/README.md도 LLM 심사·반복 평가를 실험적이라고 설명하고, 사람의 정답 라벨과 검증하지 않았음을 밝힙니다. 실습 아이디어: 정확한 짧은 답과 틀린 긴 답을 만들어 어떤 지표가 오판할지 표로 예측해 보세요.
plugins/python-development/commands/python-scaffold.md는 요구사항을 <user_request>로 감싼 $ARGUMENTS에 두고, 호출자가 준 내용이 명령 전체의 지침을 덮어쓰는 권한은 없다고 명시합니다. 입력 데이터와 제어 지침을 구분하려는 설계입니다. 이 문장만으로 모든 지침 오염 문제가 해결되지는 않습니다.
또한 plugins/python-development/agents/python-pro.md에는 mypy·pyright 같은 일반 Python 도구가 언급되지만, 저장소의 실제 개발 규칙과 plugins/plugin-eval/pyproject.toml은 Ruff·ty를 사용합니다. 전문가 역할 문서의 폭넓은 권장 목록과 이 저장소를 개발할 때 적용하는 규칙은 다릅니다. 실습 아이디어: 대상·입력·출력·완료 조건을 각각 한 문장으로 써서 작은 코드 리뷰 스킬의 설계안을 만드세요.
핵심 어댑터는 텍스트 파일을 읽고 변환하는 도구입니다. 저장소에는 공통 CPU 코어 수나 RAM 최저 사양이 명시되어 있지 않습니다. GPU나 대규모 모델 가중치를 기본으로 요구하는 프로젝트로 볼 근거도 없습니다. 하네스 자체의 요구사항은 별도로 적용됩니다.
| 하려는 일 | 필요한 환경 | 용량·비용에서 볼 점 |
|---|---|---|
| 문서·소스 학습 | UTF-8 편집기, 선택적으로 Git·검색 도구 | Git 내부와 심볼릭 링크를 제외한 파일 내용 합계 약 8.29MB. 의존성 환경·Git 이력 용량은 별도 |
| 어댑터 개발·생성 | Python 3.12 이상, uv, Make | Python 패키지와 가상환경·캐시 공간 필요. 생성물 규모에 따른 실측 메모리 수치는 없음 |
| 네이티브 플러그인 사용 | 해당 하네스, 해당 설치 경로 | Python 변환 환경이 불필요한 경로도 있음. 모델 이용 계정·요금은 하네스에 따름 |
| 정적 스킬 평가 | plugin-eval 기본 의존성 | quick은 모델 호출 없이 문서 구조 검사 |
| 실험적 LLM 평가 | 선택 llm 의존성과 SDK 인증 | 반복 수·동시성·모델에 따라 이용량 발생 |
| 동영상·OCR 도구 | 별도 Python 프로젝트, ffmpeg·Tesseract 등 | 영상 다운로드 공간 필요. EasyOCR·PyTorch는 무거운 선택 의존성 |
Makefile의 install-easyocr 설명에는 PyTorch·EasyOCR 다운로드가 약 2GB라는 안내가 있습니다. 이는 문서상 대략치이며 환경별 실제 용량은 달라집니다. 기본 플러그인 변환과 분리된 선택 경로입니다.
tools/yt-design-extractor/yt-design-extractor.py의 run_ocr_on_frames()는 EasyOCR 경로에서 easyocr.Reader(["en"], gpu=False, verbose=False)를 만듭니다. 이 경로는 CPU 사용과 영어 인식으로 설정되어 있습니다. 패키지 목록에 PyTorch가 있다고 GPU 추론 서버나 한국어 OCR 지원까지 추론하면 안 됩니다.
문서를 읽고 파일 수를 세는 일에는 모델 계정이 필요하지 않습니다. 패키지 설치는 배포 저장소, 플러그인 설치는 해당 소스, 모델 사용은 해당 제공자와의 연결이 필요합니다. Markdown 원고를 로컬에 보관한다는 사실만으로 실제 모델 작업이 모두 로컬에서 처리되지는 않습니다.
docs/plugin-eval.md의 설명 기준으로, 모델 평가 호출은 ANTHROPIC_API_KEY가 있으면 그 API 계정을 사용하고, 없으면 Claude Code 로그인 경로를 사용합니다. 정적 검사와 LLM 평가를 선택할 때 이용량이 발생하는 경계를 확인해야 합니다.
또한 make install-opencode, make install-copilot, make install-antigravity, make install-pi는 단순한 읽기 명령이 아닙니다. 산출물을 생성하고 사용자 설정 위치에 심볼릭 링크를 만드는 설치 경로입니다. 어떤 도구를 사용할지 정한 뒤 docs/harnesses.md의 범위와 구성요소 차이를 읽는 것이 순서입니다.
아래 실습은 원본 문서 탐색·직접 집계·예상 출력 작성·평가 설계로 구성되어 있습니다. 설치나 모델 호출 없이도 어댑터의 핵심 계약을 공부할 수 있습니다. 실제 실행 속도나 메모리 요구량은 사용하는 환경에서 별도로 측정해야 합니다.
각 과제는 저장소 원본을 읽고, 답안은 별도 연습 문서에 정리하는 방식입니다. 명령 예시는 저장소 루트를 기준으로 합니다. 설치 스크립트나 저장소의 Python 모듈을 실행하지 않아도 완료할 수 있습니다.
목표: 플러그인·에이전트·스킬·명령을 경로만 보고 구분합니다. python-development를 골라 구성요소별 이름과 개수를 적으세요.
python3 - <<'PY'
from pathlib import Path
root = Path("plugins/python-development")
patterns = {
"에이전트": "agents/*.md",
"스킬": "skills/*/SKILL.md",
"명령": "commands/*.md",
}
for label, pattern in patterns.items():
files = sorted(root.glob(pattern))
print(label, len(files))
for path in files:
print(" ", path.relative_to(root))
PY
완료 기준: 에이전트 3개·스킬 16개·명령 1개를 구분하고, references/details.md를 스킬 한 개로 추가 집계하지 않는 이유를 설명합니다. 이 예시는 표준 라이브러리로 파일 이름만 읽습니다.
목표: plugins/python-development/agents/python-pro.md, plugins/python-development/skills/python-testing-patterns/SKILL.md, plugins/python-development/commands/python-scaffold.md를 읽고 각 파일이 무엇을 책임지는지 정리합니다.
# 읽기 전용으로 세 문서의 첫 부분 비교
sed -n '1,45p' plugins/python-development/agents/python-pro.md
sed -n '1,45p' plugins/python-development/skills/python-testing-patterns/SKILL.md
sed -n '1,45p' plugins/python-development/commands/python-scaffold.md
만들 것: “코드 리뷰 담당자”라는 새 역할을 가정하고, 역할의 책임·참고 지식·호출 시 진행할 절차를 각각 한 문장으로 작성합니다.
완료 기준: 같은 문장을 세 파일에 복제하지 않고, 스킬의 설명에 “언제 사용할지”를 포함합니다. 명령의 입력을 처리해야 할 데이터로 정의하고 완료 조건도 한 줄 붙입니다.
목표: CodexAdapter._emit_agent()와 MODEL_ALIASES만 읽고 어떤 TOML 필드가 나올지 예측합니다. 아래는 실제 본문을 번역·요약한 형식 학습용 예시입니다.
name = "python-development__python-pro"
description = "Python 개발 전문 역할"
model = "gpt-5.5"
sandbox_mode = "workspace-write"
developer_instructions = """
Python 개발 역할의 본문 지침이 여기에 들어갑니다.
"""
완료 기준: 원본의 model: opus가 변환되는 이유와, tools 필드가 없는 이 원본이 workspace-write로 분류되는 이유를 설명합니다. TOML에서 원본의 tools·color를 그대로 보존하지 않는다는 점도 확인합니다.
추가 질문: 가상의 원본에 tools: [Read, Grep]를 넣으면 어떤 출력 필드가 달라질까요? tools: []가 “도구 완전 차단”으로 보존되는지도 따져 보세요.
목표: _utf8_safe_cut()과 _split_body_if_oversized()를 읽고, 코드 실행 전에 검증해야 할 조건을 적습니다.
| 입력 예 | 확인할 성질 |
|---|---|
| 짧은 ASCII 본문 | 상한 안이면 참고 파일로 분리할 필요가 없음 |
"가" * 3000 | 3,000자이지만 9,000바이트. 문자 수만으로 판정하면 틀림 |
| 절단 위치의 이모지 | 절단 뒤 양쪽을 UTF-8로 해석할 수 있고 바이트가 손실되지 않아야 함 |
코드 울타리 안의 ## | 제목처럼 보여도 절 경계로 취급하면 안 됨 |
완료 기준: 하위 함수에서는 head + tail == encoded와 len(head) <= cap을, 최종 출력에서는 머리말과 안내문까지 포함한 전체 파일 크기를 확인해야 함을 설명합니다. UTF-8 보존과 Markdown 의미 보존이 같은 검사는 아니라는 점도 적습니다.
목표: StaticAnalyzer와 _simresult_from_messages()가 관찰하는 값에서 출발해, 평가의 빈틈을 찾습니다. 모델 호출 대신 사람이 작성한 가상 응답으로 설계합니다.
완료 기준: 응답이 나왔다는 사실만으로 스킬이 올바르게 선택되었다고 결론 내릴 수 없음을 반례 하나로 보입니다. 사람의 판정 기준, 실패 사례, 자동 점수와 비교할 항목이 들어 있는 채점표를 제출합니다.
실습의 완료 기준은 명령이 끝났는지가 아니라, 입력이 출력으로 바뀔 때 지켜야 할 조건을 설명할 수 있는지입니다.
Python의 변수·함수·목록을 알고 있다는 전제의 학습 순서입니다. 주차는 분량을 나누는 기준이며, 실제 학습 속도에 맞춰 조정하면 됩니다. 먼저 한 플러그인을 끝까지 이해하고, 이후 다른 하네스를 비교하는 방식으로 범위를 넓힙니다.
| 주차 | 공부할 기술과 읽을 파일 | 한 주의 결과물 |
|---|---|---|
| 1주차 | Markdown·YAML·JSON, pathlib와 파일 탐색. python-development의 구성요소 | 플러그인 재고표와 역할·스킬·명령의 차이를 설명하는 메모 |
| 2주차 | dataclass, 타입 힌트, 파싱. tools/adapters/base.py | 머리말과 본문을 공통 객체로 바꾸는 흐름도, 빈 값 사례 표 |
| 3주차 | 추상 클래스·전략 패턴·네임스페이스. tools/generate.py, tools/adapters/codex.py | 에이전트 하나의 예상 TOML과 이름 충돌 해결 표 |
| 4주차 | UTF-8·바이트 예산·파일 경로 안전성. _utf8_safe_cut(), HarnessAdapter.write() | 한글·이모지·코드 울타리를 포함한 경계 조건 목록 |
| 5주차 | pytest·출력 재파싱·CI·잠금 파일. tools/tests/test_adapters.py, .github/workflows/validate.yml | 형식·의미·실제 도구 확인을 나눈 검증 계획 |
| 6주차 | 평가 타당성·대용 지표·비동기. plugins/plugin-eval/src/plugin_eval/engine.py, plugins/plugin-eval/src/plugin_eval/layers/, evals/README.md | 10개 요청의 수동 평가표와 현재 점수 체계의 반례 |
docs/authoring.md와 docs/harnesses.md를 비교하며 하나의 지침을 두 하네스에서 어떤 의미로 읽는지 설계합니다.처음에는 번역할 한 문서가 틀리지 않았는지 확인하고, 다음에는 여러 언어의 납품 규칙을 비교합니다. 마지막에는 그 문서를 받은 작업자가 실제 일을 잘했는지 측정합니다. 파일 변환과 업무 성과는 연결되어 있지만 서로 다른 단계입니다.
문서를 읽는 능력에서 시작해 변환 계약을 설계하는 능력으로, 마지막에는 결과를 검증하는 능력으로 확장해 보세요.
| 용어 | 쉬운 설명 |
|---|---|
| 에이전트 | 특정 역할을 맡도록 지침을 받은 모델 작업 단위. 이 저장소에서는 주로 역할을 정의한 Markdown 파일로 제공 |
| 스킬 | 작업 상황에 맞춰 참고하는 지식·절차·지원 파일 묶음. 중심 파일은 SKILL.md |
| 명령 | 사용자가 이름으로 호출하는 작업 절차. 하네스에 따라 스킬이나 템플릿으로 변환됨 |
| 플러그인 | 관련 에이전트·스킬·명령 등을 함께 배포하는 묶음 |
| 마켓플레이스 | 설치 가능한 플러그인의 이름과 위치 등을 알려 주는 목록. 반드시 웹 상점을 뜻하지 않음 |
| 하네스 | 모델에 문맥과 도구를 제공하며 실제 작업을 실행하는 코딩 환경 |
| 어댑터 | 공통 원본을 대상 시스템의 형식과 규칙에 맞게 바꾸는 코드 |
| 프런트매터 | 문서 맨 위에 이름·설명·모델·도구 같은 설정을 적는 머리말 |
| 중간 표현 | 입력을 읽은 뒤 출력하기 전, 프로그램이 다루기 좋게 정리한 공통 객체 |
| 전략 패턴 | 공통 인터페이스를 유지하면서 대상에 따라 실제 처리 방식을 바꾸는 설계 |
| 기능 행렬 | 하네스별로 어떤 기능이 있고 제약이 무엇인지 정리한 표나 데이터 |
| 모델 별칭 | opus·inherit처럼 원본에 적는 이름. 변환 후 값은 하네스마다 다를 수 있음 |
| 네임스페이스 | 소속 이름을 덧붙여 같은 이름의 구성요소가 충돌하지 않게 구분하는 범위 |
| 점진적 공개 | 처음에는 짧은 안내를 제공하고 자세한 내용은 필요할 때 읽도록 나누는 방식 |
| 컨텍스트 예산 | 한 번의 작업에서 모델에게 전달할 수 있는 정보량의 한도. 토큰·바이트 제한은 구분해야 함 |
| UTF-8 | 문자를 바이트로 저장하는 인코딩. 문자 하나의 크기가 항상 한 바이트인 것은 아님 |
| 샌드박스 | 작업이 파일이나 시스템에 미칠 수 있는 범위를 제한하는 환경 또는 정책 |
| 도구 허용 목록 | 에이전트가 쓸 수 있는 도구를 열거한 설정. 빈 목록과 설정 누락이 다르게 해석될 수 있음 |
| MCP | 모델을 사용하는 앱이 외부 도구·데이터와 연결하는 표준 프로토콜. 설정 지원과 개별 플러그인의 이식 가능성은 별개 |
| 정적 분석 | 작업을 실제 수행하지 않고 파일 구조·문구·설정을 읽어 문제를 찾는 검사 |
| 대용 지표 | 직접 알고 싶은 성질 대신 측정하는 값. 응답 길이를 품질 대신 쓰는 경우가 한 예 |
| 몬테카를로 평가 | 여러 번의 시행을 통해 변동과 비율 등을 살피는 방식. 이 구현의 반복 응답 지표는 실제 업무 성공률과 다름 |
| 스냅샷 | 특정 시점의 결과를 저장한 기준. 다음 변경에서 무엇이 달라졌는지 비교하는 데 사용 |
| 스모크 테스트 | 실제 도구가 파일을 발견하고 읽는지처럼 기본 연결이 살아 있는지 빠르게 확인하는 검사 |
| 드리프트 | 원본과 생성물, 구현과 문서처럼 함께 맞아야 할 대상이 시간이 지나며 어긋나는 현상 |
| 심볼릭 링크 | 다른 파일이나 디렉토리를 가리키는 링크. CLAUDE.md와 사용자 단위 설치에 활용 |
용어를 외웠는지보다 tools: []가 각 어댑터에서 어떻게 바뀌는지 설명할 수 있는지가 좋은 확인 문제입니다. 실제 파일 하나와 연결해 말할 수 있으면 개념이 훨씬 오래 남습니다.
Agent Skills 명세는 메타데이터·본문·지원 자료를 필요에 따라 읽는 구조를 설명합니다. 다만 표준의 일반 권장사항과 이 저장소의 하네스별 예산은 구분해야 합니다. 예를 들어 Codex 어댑터의 7400은 이 구현의 본문 예산이며, 모든 스킬 표준에 공통인 숫자가 아닙니다.
| 항목 | 상태 |
|---|---|
| 저장소 | wshobson/agents |
| 선정 | GitHub Trending Python Weekly #6 · 2026-10-23 |
| 스타 / 포크 | 41,588 / 4,412 · 2026-10-23 GitHub 기준 |
| 주 언어 | Python · 핵심 지침 데이터는 Markdown으로 작성 |
| 생성일 | 2025-07-24 |
| 최근 push | 2026-10-19 · 저장소 메타데이터의 push 시각 기준 |
| 분석 기준 커밋 | 0874a27 · 2026-10-18 (한국 시간) · documentation-generation의 목차 예제가 ADR README를 덮어쓰지 않도록 문서를 수정한 변경 (#778) |
| 최신 릴리스 | GitHub 릴리스 없음. 개별 플러그인·Python 프로젝트의 버전 표기와는 별개 |
| 카탈로그 | 94개 항목 = 로컬 플러그인 92개 + 외부 항목 2개. 로컬 에이전트 202개·스킬 185개·명령 105개 |
| 코드 규모 | Python 70개 파일·19,646줄. Markdown 794개 파일·204,346줄. 빈 줄·주석·예제 포함, Git 내부·심볼릭 링크 제외 |
| 파일 내용 용량 | 1,169개 파일 합계 8,287,001바이트. Git 내부·심볼릭 링크·설치 환경 제외 |
| 라이선스 | MIT · 외부 플러그인은 각 저장소의 라이선스 적용. LICENSE의 저작권 연도 표기는 2024 |
최근 push 시각과 분석 기준 커밋의 시각은 서로 다른 기준이므로 일치하지 않을 수 있습니다. 또한 커밋 하나의 정보만으로 저장소 전체의 누적 커밋 수나 과거 성장률을 단정할 수 없습니다. 주간 순위는 해당 날짜의 기록이며, 이후의 Trending 화면과 다를 수 있습니다.
지원은 동일 동작의 보장이 아닙니다. Codex의 네이티브 스킬 경로와 생성된 에이전트 경로는 다릅니다. Pi 에이전트에는 확장이 필요합니다. 훅·MCP 구성·지원 자산·도구 권한이 모든 하네스에 같은 의미로 옮겨지는 것도 아닙니다.
지침은 실행을 강제하는 코드와 다릅니다. 설명문이 역할 선택에 영향을 주더라도 항상 원하는 시점에 호출된다고 보장하지 않습니다. 코드 예제와 권장 기술 목록도 현재 프로젝트의 실제 의존성이나 검증된 운영 설정으로 받아들이면 안 됩니다.
평가 점수는 작업 성공의 증명이 아닙니다. 정적 점수는 구조 신호이며, 실험적 반복 평가에는 응답 길이 같은 대용값이 사용됩니다. 사람의 판정·실제 수정 결과·테스트 통과와 연결된 별도 검증이 필요합니다.
주석과 구현이 어긋난 부분이 있습니다. Copilot 어댑터 클래스 설명에는 GPT-5 계열 매핑이라는 문장이 남아 있지만, 실제 resolve_model("copilot", ...)과 변환표는 Claude 모델 ID를 사용합니다. 평가 층의 순서도 주석보다 await 흐름을 기준으로 읽어야 합니다.
파일 크기 준수와 의미 보존은 다릅니다. UTF-8 경계에서 자른다고 모든 코드 블록·문장·참조의 의미가 유지되는 것은 아닙니다. 실제 모델 정확도, 실행 속도, 메모리 사용량과 모든 하네스 버전의 호환성은 소스 구조만으로 입증되지 않습니다.