Skill Auditor — 에이전트 능력 감가상각 및 적합도 평가
개요
스킬은 감가상각되는 자산입니다. 모델 버전은 몇 달마다 출시됩니다. 지난 분기에 통과한 스킬이 조용히 성능이 퇴보할 수 있습니다(잘못된 출력 형태, 깨진 도구 호출, 트리거 누락). 사용자는 자신의 에이전트가 더 나빠졌다는 사실을 알지 못합니다.
이 스킬은 평가 방법론입니다. 세 가지 질문에 답합니다:
- 스킬이 퇴보하고 있나요? — 모델 버전 간 기능 회귀.
- 새 스킬이 실제로 좋은가요? — 효과 대 비용.
- 스킬이 이 사용자에게 적합한가요? — 트리거 정확도 + 환경 + 스타일.
다섯 가지 실행 가능한 진입점을 제공합니다:
scripts/console.py— 상주 콘솔(데이터 계층): 호스트별registry.<host>.json을 유지 관리하고, 모델 버전 변경(bump/check)을 감지하며, 추천/제거 패널을 출력합니다. 전체 명령어 세트는USAGE.md를 참조하세요.scripts/regress.py— 골든 세트 재생 결과를 받아 통과율 매트릭스를 계산하고, 성능 저하(임계값 + 방향)를 플래그하며, 편집된 에셋이 있는 경우FINGERPRINT-DRIFT를 플래그합니다.scripts/baseline.py— 재생 체크리스트를 생성한 다음, 기록된 판정을baseline-results.json에 병합합니다(에셋 기준,--replace는 완전 덮어쓰기). 초안 골든 케이스는--allow-draft가 없으면 건너뜁니다.scripts/fingerprint.py— 독립형 보고서 CLI;scan이 사용하는 동일한 해싱 코드의 얇은 래퍼입니다.fingerprint-report.*만 작성하며 레지스트리는 작성하지 않습니다.scripts/install.py— 이 스킬을 머신의 모든 에이전트 호스트(~/.workbuddy-ai/skills,~/.claude/skills,~/.agents/skills,~/.dsh/skills,~/.codex/skills)에 설치합니다. 설치 후 확인하며, 빈 디렉토리를 남기지 않고, 개인 데이터를 복사하지 않습니다.
핵심 원칙: 기준선 없는 측정은 없습니다. 성능 저하 = 변경되지 않은 핑거프린트에서 통과율이 크게 떨어진 경우입니다. 결코 "느낌이 더 나쁘다"가 아닙니다.
다중 호스트 아키텍처 (스킬 vs 플러그인)
하나의 핵심 엔진, 호스트별 어댑터. 동일한 핑거프린트/기준선/회귀/추천/필요 제안 로직이 모든 곳에서 실행됩니다. 어댑터는 에셋이 어디에 있는지와 매니페스트를 읽는 방법만 알면 됩니다.
| 호스트 | 종류 | 기본 루트 | 매니페스트 |
|---|---|---|---|
| workbuddy | 스킬 | 이 스킬을 포함하는 skills 루트 | SKILL.md |
| claude-code | 스킬 | ~/.claude/skills | SKILL.md |
| deepseek | 플러그인 | ~/.dsh/profiles/desktop (package.json deps 읽음) | package.json / plugin.json |
| generic | 에셋 | --root 전달 | plugin.json / manifest.json / SKILL.md / package.json |
- 각 호스트는 자체 레지스트리를 유지합니다:
registry.<host>.json— 호스트 간 덮어쓰기 없음. - 기준선 결과 + 골든 세트는 공유되며, 에셋 이름으로 키가 지정됩니다.
--host <name> --root <path>와 함께 실행하며,hosts.json에 사용자 정의 호스트를 추가하세요.console.py hosts는 모든 프로필, 확인된 루트, 감지된 에셋 수를 보여줍니다.
따라서 WorkBuddy에서는 스킬을 평가하고, DeepSeek harness에서는 플러그인을 평가합니다. 동일한 명령어, 다른 어댑터입니다. 새 호스트를 추가하는 것은 hosts.json 항목(종류 + 루트 + 매니페스트 파일 이름)을 추가하는 것이며, 코드 변경이 필요하지 않습니다.
사용 시기
- 새 스킬이나 플러그인을 배포하기 전에 ("스킬을 만들고 평가 과정을 따라주세요").
- 모델 버전 업데이트 후, 기존 스킬이 퇴보했는지 확인할 때.
- 스킬이 "이상하다"고 느껴질 때 — 데이터로 확인하고, 느낌으로 확인하지 마세요.
- 스킬을 유지/재작성/폐기할지 결정할 때.
- 사용자에게 스킬이나 플러그인을 추천할 때 (적합성 + 증거).
사용하지 말아야 할 때: 재사용 가능한 스킬이 없는 일회성 작업; 순수 서술형 문서.
핵심 개념: 버전 핑거프린트
핑거프린트는 감가상각 매트릭스의 행입니다.
fingerprint = hash(기능 표면 파일 내용 + 상대 경로) # 구경 v2-ability-surface
기능 표면으로 간주되는 것(변경 시 실제 동작이 변경되는 파일):
- 포함:
SKILL.md,scripts/*,lib/*,dist/*,package.json,plugin.json,cordis.patch.yml, 템플릿 - 제외:
README*,CHANGELOG*,LICENSE*, 이미지/오디오/폰트,*.map, lockfiles,node_modules/,test*/,docs/
제외 이유: README 편집은 기능을 변경하지 않지만, 해싱하면 핑거프린트가 이동하여 기능적 변화가 없을 때 가짜 FINGERPRINT-DRIFT("에셋이 편집되었습니다")가 생성됩니다. 플러그인은 이 문제를 악화시킵니다. 설치된 하나의 플러그인이 16MB의 번들 출력과 57KB의 README를 가질 수 있습니다.
규칙:
- 핑거프린트 변경 없음 ⇒ 행이 유지됨; 통과율 하락은 모델 회귀입니다.
- 핑거프린트 변경됨 ⇒ 변경은 스킬 자체의 책임이지, 모델의 책임이 아닙니다. 이전 행과 새 행이 공존하므로 스킬 편집이 모델 드리프트로 잘못 귀속되지 않습니다.
python scripts/console.py scan 을 실행하여 핑거프린트를 계산하고 레지스트리에 저장합니다. fingerprint.py 는 독립형 보고서 래퍼이며 레지스트리를 건드리지 않습니다.
기능 표면 (플러그인이 두 번째 축을 필요로 하는 이유)
핑거프린트는 "파일이 변경되었는가"를 알려줍니다. "여전히 동일한 것을 제공하는가"는 말할 수 없습니다.
따라서 scan 은 에셋별로 기능 표면도 기록하고 이전 스캔과 비교합니다:
| 에셋 종류 | 표면이 기록하는 내용 |
|---|---|
| 플러그인 | patch(dsh.bundle.patch), main/module, bin, exports, deps, skills, mcp, hooks, insert(cordis 행), scripts |
| 스킬 | tools(허용된 도구 수), scripts |
변경되면 scan 은 명시적으로 출력합니다:
[caps] 1개 에셋의 기능 표면이 변경되었습니다(이는 "외부에 제공하는 것이 변경됨"을 의미하며, 통과율과는 무관합니다):
plug-a +bin
플러그인에게 이것이 중요한 이유: 플러그인은 "답변을 더 나쁘게 한다"가 아니라 도구를 등록하지 않음/라우트가 404됨/훅이 실행되지 않음으로 인해 성능이 저하됩니다. 프롬프트의 골든 세트는 플러그인에 대해 잘못된 것을 측정합니다. 표면 diff는 호스트를 부팅할 필요 없이 "v1.1.0이 진입점을 삭제함"을 포착합니다.
알려진 경계(덮어쓰지 마십시오): 표면은 선언된 기능이지, 관찰된 기능이 아닙니다. 매니페스트가 거짓말하는 플러그인(로드에 실패하는 패치를 선언함)의 경우 이를 포착할 수 없습니다.
런타임 증거 (세 번째 축과 그 한계)
"런타임 프로브"라고 불리는 매우 다른 두 가지가 있습니다. 혼동하지 마십시오:
| 능동 프로브 (active probe) | 수동 증거 (passive evidence) — 구현됨 | |
|---|---|---|
| 기능 | 호스트를 부팅하고 "실제로 등록한 도구는 무엇입니까?"라고 묻습니다 | 호스트가 이미 기록한 로그를 읽습니다 |
| 비용 | DSH desktop 프로필은 Electron 전용입니다 — dsh --profile desktop --dump-config 가 거부됨; 헤드리스 진입점 없음 → 역공학 IPC 또는 UI 구동 필요 | 파일 한 번 읽기, ~10ms |
| 포착 가능 | 매니페스트가 거짓말하는 플러그인을 포함한 모든 것 | 플러그인이 기록한 모든 것 |
| 상태 | 구축되지 않음 | console.py probe / skill_audit_probe |
probe 는 ~/.dsh/logs/*.log 를 읽고( hosts.json 의 "logs" 를 통해 호스트별로 구성 가능), <iso> [level] [source] message 를 구문 분석하고, source 가 설치된 에셋 이름과 일치하는 줄을 귀속시키며, 실패 어휘(fail|error|ENOENT|unavailable|timeout|…)와 일치하는 줄을 플래그합니다.
실제 사례 (이 머신에서):
@wxg-prc-cpg/browser-skill-dsh-plugin 2개 장애 징후
bsk probe failed (spawn bsk ENOENT); browser tools will report install guidance…
파일 존재, 매니페스트 유효, caps=4 — 모든 정적 검사 통과. 플러그인이 로드되고 도구가 등록되었지만 작동할 수 없습니다: 셸 아웃하는 bsk CLI가 PATH에 없습니다. 어떤 양의 파일 해싱도 이것을 찾을 수 없습니다.
사각지대 (명시하고 숨기지 마십시오): 아무것도 기록하지 않는 플러그인은 보이지 않습니다. 로그 로테이션은 이전 오류를 지웁니다. 아무도 사용하지 않은 플러그인은 증거가 없습니다. info 수준 오류는 키워드 매칭으로 포착되므로 누락과 오탐 모두 가능합니다. 증거의 부재는 건강의 증거가 아닙니다 — probe 는 녹색 체크 대신 해당 문장 자체를 출력합니다.
구현됨 vs 방법론 전용 (이 선을 흐리지 마십시오)
아래 방법론은 코드보다 광범위합니다. 사용자는 자신이 어떤 절반을 잡고 있는지 알아야 합니다:
| 영역 | 상태 |
|---|---|
기능 표면에 대한 핑거프린트, scan/status, 기능 diff | 구현됨 |
| 골든 생성 + 기준선 수집 (에셋별 병합, 초안 가드) | 구현됨(baseline.py) |
통과율 매트릭스, ≥20pp 임계값 + 방향, FINGERPRINT-DRIFT | 구현됨(regress.py) |
모델 변경 감지(bump/check), 호스트별 스탬프 | 구현됨 — 그러나 이벤트 소스는 수동입니다; 예약된 check는 누군가 bump할 때까지 녹색으로 유지됩니다 |
| 추천/제거 패널, 필요 제안, 기록 기반 초안 | 구현됨(휴리스틱; 제안은 증거가 아닙니다) |
| 호스트 로그의 런타임 증거 | 구현됨(수동; 플러그인이 기록한 것만) |
| 절제, 섀도우 모드 채택률, 순 가치 / 토큰 원격 측정 | 방법론 전용 — 코드 없음 |
| 트리거 정밀도/재현율, 환경 조정, 스타일 기준선 | 방법론 전용 — 코드 없음 |
| K≥3 재생, LLM-판사 교차 검증 | 구현되지 않음; 현재 판정은 K=1 자체 평가입니다 |
risk 열 | 유지보수 표면 프록시 — 가치가 아님 |
이 파일의 주장이 "구현됨"으로 표시된 행에 연결될 수 없는 경우, 도구가 사용자를 위해 수행할 작업이 아닌 감사를 실행하는 사람을 위한 조언으로 취급하십시오.
판단 1 — 기능 저하
네 단계:
- 수동이 아닌 기록에서 골든 세트를 구축하십시오. 과거 세션을 채굴: 사용자가 저항 없이 채택함 → 긍정 재생; 사용자가 반발/재작성 요청 → 부정 재생. 재생이 회귀입니다. 사용자 자신의 사용 기록이 말뭉치입니다 — 발명된 테스트 세트가 아닙니다.
- 동일한 골든 세트에서 두 모델을 모두 실행하십시오, K≥3 (LLM-판사 점수 케이스: K≥5, 판사가 노이즈가 많기 때문). (핑거프린트, 모델 버전)별 통과율을 기록합니다.
- 결정 규칙: ≥20pp 하락 AND 방향성 일관 → 성능 저하 보고; 임계값 미만 → "변동성 관찰". 이것은 "이 출력이 이상하다"를 재현 가능한 기준으로 바꿉니다.
- 플래그만 표시하지 말고 귀속시키십시오. 중간 산출물을 검사:
- 도구 호출 오류 / 형식 변경 → 도구 설명 수정.
- 출력 구조는 맞지만 내용이 틀림 → 지침 다시 작성.
- 트리거되어야 했지만 트리거되지 않음 → 트리거 설명 수정.
- 모든 중간 단계가 올바르고 최종 단계만 잘못됨 → 모델 내부 회귀; 스킬을 "단일 모델 종속"으로 표시, 모델 수정을 기다림.
"7개 성능 저하, 2개 재작성 권장" 라인은 4단계 출력의 귀속 가능한 하위 집합입니다. 이것이 보고서를 실행 가능하게 만드는 것입니다.
판단 2 — 새 스킬이 좋은가?
측정 가능한 두 가지 축으로 분할: 효과성(더 나은 결과)과 경제성(더 낮은 비용).
- 배포 전 절제. 동일한 작업 배치, 두 그룹: 스킬 없는 A군, 스킬 있는 B군. 성공률, 인간 수정 횟수, 토큰 비용을 기록합니다.
순 이익 = 성공률 향상 × 작업 빈도 − 한계 비용성공률을 30% 향상시키지만 연간 3번 트리거되고 각각 +50k 토큰이 드는 스킬은 자산이 아니라 부채입니다. - 배포 후 섀도우 모드. 새 스킬이 자동 실행 없이 조용히 실행됨: 제안을 생성하지만 자동 실행하지 않음; "어떤 일이 일어났을지" 기록. 채택률(수락 vs 재정의)을 관찰. 채택률은 "좋음"의 궁극적인 판단이며, 오프라인 메트릭보다 더 정직합니다. 경계: 쓰기 작업 스킬(파일 삭제, 메일 보내기)은 실제로 실행하지 않고 섀도우에서 시뮬레이션/주석만 달 수 있습니다.
- 순 가치 카드. 스킬당 하나의 대시보드: 호출 횟수, 성공률, 채택률, 평균 토큰, 누적 순 이익. 90일 순 음수 → 재작성 또는 폐기 제안. 이것은 감가상각 테이블의 소비자 측면입니다.
판단 3 — 이 사용자에게 적합한가?
"적합함" = 정확한 트리거 + 가정 성립 + 스타일 일치. 모두 자동화 가능:
- 트리거 정밀도(가장 느낌에 영향을 미치고, 가장 자주 건너뜀). 긍정 샘플(트리거해야 함)과 부정 샘플(유사하지만 트리거하지 않아야 함 — "이 버그 수정" vs "버그가 무엇인지 설명")의 기록을 샘플링. 재생 → 정밀도/재현율. 낮은 정밀도 = 성가심(과다 트리거); 낮은 재현율 = 설치 낭비. 처음 10-20개는 수동으로 레이블링한 다음 반자동화, LLM 비용 제로.
- 환경 조정(설치됨 ≠ 실행됨). 스킬 메타데이터는 종속성을 선언: 어떤 도구 / MCP / 권한 / 경로 습관 / 언어, 그리고 암시적 모델 기능 가정(긴 컨텍스트, 코드 실행, 멀티모달). 사용자의 실제 환경과 조정; 누락 → 적색 경고. "macOS 가정", "일본어 출력", "200k 컨텍스트 필요" — 보이지 않는 가정은 스킬이 사용되지 않는 #1 이유입니다. 이것은 또한 판단 1로 피드백됩니다: 실패한 기능 가정 = 조용한 성능 저하.
- 스타일 기준선(가장 낮은 가중치). 사용자의 과거 출력 + USER.md를 참조로 사용; LLM-판사가 형식, 언어, 장황함을 비교. 동점인 스킬을 구분하는 데에만 사용됩니다.
내장 워크플로우 ("새 스킬 만들기"용)
사용자가 스킬 생성을 요청하면, 전달하기 전에 프로토콜을 인라인으로 실행하십시오:
- 환경 조정 — 사용자의 환경이 스킬의 선언된 종속성 + 기능 가정을 충족합니까?
- 트리거 재생 — 10-20개의 샘플 케이스를 재생; 정밀도/재현율 보고.
- 절제 — 작은 작업 배치에서 향상 대 비용을 측정.
- 모니터링 진입 — 통과 시 핑거프린트 + 골든 세트 등록; 상주 콘솔이 각 모델 업데이트 시 재실행.
필요 기반 제안 (일치하는 스킬이 없을 때)
이것은 "빈 선반" 동작입니다: 사용자(특히 스킬/플러그인이 전혀 없는 사용자)가 설치된 스킬이 다루지 않는 것을 요청합니다. "할 수 없습니다"라고 말하지 말고 — 격차를 표면화하고 채울 것을 제안하십시오.
- 대화에서 필요 감지: 작업 유형 + 도메인 (예: "분기별 재무 보고서" → 금융/분석; "AI 어조 제거" → 휴머나이저; "대시보드 구축" → 프론트엔드/차트).
- 먼저 레지스트리 확인 —
python scripts/console.py suggest --need "<need>". 다음 중 하나를 반환:✓ 사용 가능한 스킬/플러그인이 있습니다: <name>→ 사용, 아무것도 설치하지 마십시오; 또는💡 새로 추가 제안: [install:<slug>] <title>→ 커버 없음, 카테고리 추천.
- 커버되지 않은 경우, 마켓플레이스 검색하여 실제 후보(스킬/플러그인/전문가)를 찾고 증거가 포함된 카드를 제시: 기능, 이 필요에 적합한 이유, 출처. 절대 자동 설치하지 마십시오 — 사용자가 선택합니다.
- 인라인 평가 선택 사항 — 제안 단계는 제안이 평가되지 않았음을 명시적으로 표시해야 하며, 사용자가 요청하는 경우에만 1-3단계를 실행합니다.