refactor: Claude 스킬·에이전트 시스템 표준화 및 회귀 방지 린트 도입#104
Conversation
- Phase 3이 Edit 적용을 지시하는데 allowed-tools에 Edit이 없어 권한 문제 발생 가능 - Phase 0/1/2/5의 에이전트 호출을 명시적 subagent_type 표기로 통일해 전용 에이전트의 model/tools frontmatter가 확실히 로드되도록 함
general-purpose 경유 호출은 전용 에이전트의 model/tools frontmatter를 로드하지 않는 버그. style-analyzer, content-writer, content-reviewer, style-learner를 subagent_type으로 직접 지정하도록 수정.
polish-agent의 자체 10개 번호가 translation-patterns.md 정본 번호와 충돌해 리포트의 patterns_found ID가 모호했음. 정본 번호의 부분집합으로 재매핑하고, 28개 패턴 출처를 translation-reviewer.md에서 정본 파일로 교체. polish/polish-file의 예시 ID도 동기화.
사용 예시의 /home/wsl-agent 절대경로를 저장소 상대경로로 교체하고, 예시 Task 호출의 중복 model 파라미터를 제거해 frontmatter model 필드로 단일화. oh-my-claudecode 작성자 푸터 제거.
name → description → argument-hint → allowed-tools 순서로 6개 스킬 통일. agents-md-optimizer는 벤더링 파일로 이미 표준 충족이라 제외. 본문 변경 없음.
portfolio-strategy의 게이트 컨벤션을 표준으로 채택. translate-writer Phase 3/4, blog-writer Phase 3, polish-file Step 4에 게이트 라벨과 진행 금지 규칙을 명시해 어떤 모델이 실행해도 게이트를 건너뛰지 않도록 함.
translation-reviewer의 임베디드 패턴 테이블이 정본과 드리프트(패턴 7 예시 잔여 텍스트)를 일으켜 제거하고 필수 Read 지시로 교체. 차원 매핑(가중치, 하드 임계값)을 정본 파일 헤더로 이관. translation-verifier의 calibration 필수 Read 패턴과 동일 구조.
content-reviewer: 경계 판정 규칙(79 vs 80)과 종료 조건 체크리스트 추가, 번역투 검사를 정본 번호로 연결. content-writer: pubDatetime date -u 검증 규칙 추가(미래 날짜 빌드 제외 예방). content-translator: 번역투 표를 정본 번호로 재표기. style-analyzer/translation-style-analyzer: Windows 심링크 Read 폴백 규칙. resume-specialist: 프로젝트 데이터 소스, 한국어 출력, 사실 검증 규칙, 출력 형식 추가. 두 SKILL.md의 심링크 생성 단계에 git update-index 폴백 명시.
check-claude-assets.mjs: 스킬 frontmatter 필수 키와 name-디렉토리 일치, 에이전트 model 별칭(haiku/sonnet/opus) 강제(fable/claude-* 하드코딩 차단), subagent_type-에이전트 대조(general-purpose 금지), .claude 참조 경로 실존 검사. 게이트 회귀를 커밋 시점에 잡는다.
CLAUDE.md/AGENTS.md 미러 섹션에 check-claude-assets.mjs 린트 규칙 추가, Skills 섹션(CLAUDE.md)에 28개 패턴 정본 위치와 게이트 표기 규약 명시.
스모크 테스트에서 haiku가 활용하다를 #10으로 오기록하는 회귀 발견. 묶음 행 라벨에 어휘별 번호를 괄호로 병기(8(활용하다)·10(제공하다)·11(존재하다))하고 기록 규칙에 오답 경고를 추가. 동일 입력 재검증으로 #8 정상 기록 확인.
런타임 무관 개선 이식: 28개 패턴 정본화(차원 매핑 포함), polish-agent 패턴 ID 재매핑과 오기록 방지 규칙, 게이트 표기(GATE N), Windows 심링크 폴백, content-writer date -u 규칙, content-reviewer 경계 판정 규칙, resume-specialist 프로젝트 컨텍스트, translation-verifier 스테일 경로 정리. Codex 규약(tools/model frontmatter 없음, @ 참조 없음, WebFetch 대신 웹 조회, .agents/ 경로)은 유지. 에이전트 11개는 정규화 diff로 규약 외 동일 검증 완료. data/ 런타임 파일은 불변.
There was a problem hiding this comment.
Code Review
This pull request standardizes translation patterns and agent/skill definitions across the repository, establishing a single source of truth for the 28 translation patterns and introducing explicit user gates. It also adds a new asset linter script, scripts/check-claude-assets.mjs, to enforce invariants on skill and agent frontmatter, model routing, and path references. Feedback on the new linter script suggests robustly handling quoted values in the frontmatter parser and refining the subagent_type regular expression to correctly match unquoted values and balanced quotes.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| const m = lines[i].match(/^([A-Za-z][A-Za-z0-9_-]*):\s*(.*)$/); | ||
| if (m) keys[m[1]] = m[2].trim(); |
There was a problem hiding this comment.
프론트매터의 값(예: name 또는 model)이 따옴표(큰따옴표 또는 작은따옴표)로 감싸져 있는 경우, 파싱된 값에 따옴표가 그대로 포함되어 이후의 비교 검증(keys.name !== dir 또는 ALLOWED_MODELS.has(keys.model))이 실패할 수 있습니다.
프론트매터 값을 파싱할 때 양 끝의 따옴표를 안전하게 제거하도록 개선하는 것이 좋습니다.
const m = lines[i].match(/^([A-Za-z][A-Za-z0-9_-]*):
*(.*)$/);
if (m) {
let val = m[2].trim();
if ((val.startsWith('"') && val.endsWith('"')) || (val.startsWith("'") && val.endsWith("'"))) {
val = val.slice(1, -1);
}
keys[m[1]] = val;
}| const SUBAGENT_RE = /subagent_type["']?\s*[:=]\s*["'`]([A-Za-z0-9_-]+)["'`]/g; | ||
| for (const skillPath of skillFiles) { | ||
| const body = readFileSync(skillPath, "utf8"); | ||
| for (const match of body.matchAll(SUBAGENT_RE)) { | ||
| const name = match[1]; |
There was a problem hiding this comment.
현재 SUBAGENT_RE 정규식은 subagent_type의 값이 반드시 따옴표나 백틱으로 감싸져 있을 때만 매칭됩니다. 만약 YAML 프론트매터나 마크다운 본문에서 따옴표 없이 subagent_type: general-purpose와 같이 작성된 경우 이를 감지하지 못할 수 있습니다.
또한, 열린 따옴표와 닫힌 따옴표의 종류가 일치하는지(balanced quotes) 검증하는 것이 더 안전합니다. 정규식의 캡처 그룹과 역참조(\1)를 활용하여 따옴표가 없거나 일치하는 쌍으로 감싸진 경우를 모두 지원하도록 개선할 수 있습니다.
| const SUBAGENT_RE = /subagent_type["']?\s*[:=]\s*["'`]([A-Za-z0-9_-]+)["'`]/g; | |
| for (const skillPath of skillFiles) { | |
| const body = readFileSync(skillPath, "utf8"); | |
| for (const match of body.matchAll(SUBAGENT_RE)) { | |
| const name = match[1]; | |
| const SUBAGENT_RE = /subagent_type["']?\\s*[:=]\\s*(["'`]?)([A-Za-z0-9_-]+)\\1/g; | |
| for (const skillPath of skillFiles) { | |
| const body = readFileSync(skillPath, "utf8"); | |
| for (const match of body.matchAll(SUBAGENT_RE)) { | |
| const name = match[2]; |
Review: refactor/claude-skills-standardizationScope: this PR touches only Verification performedI couldn't execute
So functionally this looks correct and should pass CI as written. Minor findings (non-blocking)
Things I liked
Test coverageNo dedicated test for the new script, but that matches the existing precedent ( Overall: solid, well-scoped refactor with real bug fixes and a reasonable regression-prevention lint. The two coverage gaps above (#1, #2) don't block merge — they're follow-up material if you want the lint's guarantees to be airtight rather than best-effort. |
claude-review: subagent_type 정규식 사각지대 해소(polish/polish-file/resume-specialist의 프로즈형 호출을 명시적 표기로 통일), 경로 검사 대상에 skills/*/references/*.md 추가. gemini: frontmatter 값의 YAML 따옴표 제거, subagent_type 비따옴표 표기도 매칭하도록 정규식 확장.
|
@claude 리뷰 피드백을 반영했습니다 (커밋 8158dbc). 재리뷰 부탁드립니다. 반영 내역:
|
|
Claude finished @CaesiumY's task in 4m 18s —— View job 재리뷰 완료 ✅커밋 8158dbc를 검증했습니다.
검증 결과
CI: 이전 리뷰에서 지적했던 두 가지 논블로킹 항목(프로즈형 호출 커버리지, references/ 경로 검사)이 정확히 요청대로 해소되었고, gemini의 두 제안도 의도대로 반영되었습니다. 추가로 병합을 막을 문제는 발견하지 못했습니다. |
Description
.claude/스킬 7개·에이전트 13개 시스템을 전면 표준화하고, 실버그 4건을 수정하며, 회귀 방지 린트를 CI에 편입합니다. 개선사항 중 런타임 무관한 것들은 Codex 미러(.agents/)에도 이식했습니다.설계 제약: 산출물은 특정 모델에 의존하지 않습니다. 에이전트
model:필드는 별칭(haiku/sonnet/opus)만 사용하며, 구체 모델 ID 하드코딩은 신규 린트가 CI에서 차단합니다.버그 수정 (P0)
allowed-tools에Edit누락 — Phase 3(Polish)이 Edit 적용을 지시하는데 권한이 없어 주력 파이프라인이 막힐 수 있던 문제subagent_type: "general-purpose"로 호출 — 전용 에이전트의 model/tools frontmatter가 로드되지 않던 버그. 직접 지정으로 교체/home/wsl-agent/...)와 oh-my-claudecode 푸터 잔재 정리표준화 (P1)
name추가 및 키 순서 통일 (name → description → argument-hint → allowed-tools)✋ GATE N — AskUserQuestion으로 통일 + "게이트 없이 진행 금지" 규칙 명시translation-patterns.md단일 정본으로 통합 — reviewer의 임베디드 사본은 이미 드리프트가 발생한 상태였음. 차원 매핑(가중치·하드 임계값)도 정본으로 이관date -u날짜 검증(미래 날짜 빌드 제외 예방), Windows 심링크 Read/생성 폴백, resume-specialist 프로젝트 컨텍스트·한국어 규칙 추가자동화 (CI)
scripts/check-claude-assets.mjs: 스킬 frontmatter 완전성,subagent_type↔ 에이전트 정의 대조(general-purpose금지),.claude/참조 경로 실존,model별칭 강제Code standards & build잡에 편입 (docs sync 다음 단계)Codex 미러 이식
.agents/에 이식@참조 없음,WebFetch대신 "웹 조회") 보존Types of changes
Checklist
Further comments
리뷰어 참고:
node scripts/check-claude-assets.mjs와node scripts/check-agent-docs-sync.mjs모두 통과. polish-agent는 실전 스모크 테스트로 검증했고, 이 과정에서 haiku가 "활용하다"를 #10으로 오기록하는 회귀를 발견해 어휘별 인라인 번호 표기로 수정 후 재검증 통과 (d115976)samples/git 심링크,data/런타임 파일,.claude/agents/backup/,polish-reports/는 무변경git revert가능 (특히 reviewer 임베디드 테이블 제거 커밋4143b2a)Related Issue
Closes: #