옵션

plan-orchestrate

affaan-m/ECC affaan-m/ECC

계획 문서를 읽어들이고, 이를 단계별로 분해한 뒤, ECC 카탈로그를 활용해 단계별 에이전트 체인을 설계하며, 이를 실행하지 않고 바로 붙여넣거나 오케스트레이션할 수 있는 맞춤형 프롬프트를 생성합니다.

...모든 것을 확장하십시오
9
업데이트 된 시간 2026년 10월 4일

계획 수립 및 조정

단계별로 붙여넣기만 하면 되는 호출 문구를 하나씩 생성하여 계획 문서를 /orchestrate custom에 연결합니다. 이 스킬은 생성 기능만 제공하며, /orchestrate를 직접 실행하지는 않습니다. 사용자는 준비가 되면 각 줄을 직접 붙여넣어야 합니다.

사용 시점

  • 사용자가 여러 단계로 구성된 계획 문서(PRD, RFC, 구현 계획)를 보유하고 있으며, 이를 /orchestrate를 통해 진행하고 싶어 할 때.
  • 사용자가 “이 계획을 오케스트레이트해 줘”, “각 단계별로 오케스트레이트 프롬프트를 제공해 줘”, “이 계획에 대한 체인을 구성해 줘”라고 말합니다.
  • 단계별 계획은 존재하지만, 사용자가 단계별로 에이전트를 수동으로 선택하고 싶지 않은 경우입니다.

다음의 경우에는 건너뜁니다:

  • 작업이 단일 임시 단계인 경우 → 직접 /orchestrate custom을 호출합니다.
  • 계획서가 읽기 어렵거나 비어 있는 경우. 명시적인 번호 매기기가 없는 것만으로는 건너뛰기 조건이 되지 않습니다 — 아래의 “명확한 단계 없음” 예외 사례를 참조하십시오.

입력

 [--lang=python|typescript|go|rust|cpp|java|kotlin|flutter|auto] [--scope=all|step:|range:-] [--dry-run]
  • — 필수; 상대 경로 또는 절대 경로(@docs/... 허용).
  • --lang — 검토 대상 언어 변형; 기본값은 auto (프로젝트에서 감지됨)입니다.
  • --scope — 출력되는 단계를 제한합니다; 기본값은 all입니다.
  • --dry-run — 분해 및 체인 근거만 출력하고, 최종 프롬프트는 출력하지 않습니다.

권위 있는 /orchestrate 형식 (이로부터 벗어나지 마십시오)

{ORCH_CMD} custom ",,...," ""

여기서 {ORCH_CMD}는 0단계에서 결정됩니다(아래 참조). 출력된 명령 문자열은 항상 하나의 구체적인 형태를 사용해야 하며, 두 가지 형태를 혼용하거나 자리 표시자를 사용해서는 안 됩니다.

  • custom은 순차적인 체인이며, 각 에이전트의 HANDOFF가 다음 에이전트로 전달됩니다.
  • 쉼표로 구분된 에이전트 목록입니다. 공백은 사용하지 않는 것이 좋으나, 한 개의 공백은 허용됩니다.
  • --mode / --gate / --agents=... 플래그는 존재하지 않으므로 절대 임의로 생성하지 마십시오.
  • 에이전트 이름은 이 스킬의 카탈로그에서 가져옵니다. 작업 설명에 포함된 쌍따옴표는 \"로 이스케이프 처리됩니다.

ECC 설치 형식 및 네임스페이스

두 가지 설치 형식이 슬래시 명령어 와 모든 에이전트 이름의 접두사를 결정합니다. 이 두 형식은 반드시 일치해야 하며, 출력마다 하나의 형식만 사용해야 하고 절대로 혼합해서는 안 됩니다:

~ Claude Code 홈 디렉터리를 ~/.claude (macOS/Linux) 또는 %USERPROFILE%\.claude (Windows)로 표기합니다. 호스트 플랫폼에서 사용자 홈 디렉터리를 해결하는 방식에 따라 이를 처리하십시오( ~를 하드코딩하지 마십시오).

형식 탐지 {ORCH_CMD} 에이전트 이름 형식
플러그인 설치 (1.9.0+) /plugins/marketplaces/everything-claude-code/가 존재함 /everything-claude-code:orchestrate everything-claude-code:
레거시 기본 설치 위 경로가 없음; 에이전트 파일은 /agents/ 하위에 있음 /orchestrate

이 문제가 중요한 이유: 플러그인 설치 방식에서는 에이전트가 everything-claude-code:tdd-guide로 등록됩니다. 접미사 없는 이름은 모호한 일치(fuzzy matching)를 유발하며, 이는 병렬 호출 시 간헐적으로 실패합니다. 레거시 방식에서는 접두사가 붙은 형태가 등록되지 않아 아예 실패합니다.

사용 가능한 에이전트 목록 (이 중에서 선택해야 함)

일반:

  • planner — 요구사항 재진술, 위험 분해, 단계별 계획 수립
  • architect — 아키텍처, 시스템 설계, 리팩토링 제안
  • tdd-guide — 테스트 작성 → 구현 → 80% 이상의 커버리지 달성
  • 코드 검토자 — 일반적인 코드 검토
  • 보안 검토자 — 보안 감사, OWASP, 기밀 정보 유출
  • 리팩토링 정리 담당자 — 사멸 코드, 중복 코드, knip 클래스 정리
  • 문서 업데이트 담당자 — 문서, 코드맵, README
  • docs-lookup — 타사 라이브러리 API 조회 (Context7)
  • e2e-runner — 종단 간 테스트 오케스트레이션
  • database-reviewer — PostgreSQL 스키마, 마이그레이션, 성능
  • harness-optimizer — 로컬 에이전트 하네스 구성
  • loop-operator — 장시간 실행되는 자율 루프
  • chief-of-staff — 다중 채널 분류 (계획 단계에는 거의 적합하지 않음)

빌드 오류 해결기:

  • build-error-resolver (일반) / cpp-build-resolver / go-build-resolver / java-build-resolver / kotlin-build-resolver / rust-build-resolver / pytorch-build-resolver

코드 검토자:

  • python-reviewer / typescript-reviewer / go-reviewer / rust-reviewer / cpp-reviewer / java-reviewer / kotlin-reviewer / flutter-reviewer

에이전트 이름에 오타가 있으면 /orchestrate가 실패합니다. 출력하기 전에 이 목록과 대조하여 확인하십시오.

작동 원리

0단계 — ECC 모드 및 언어 감지

  1. 읽기 . 누락되었거나 비어 있으면 보고하고 중단합니다.

  2. ECC 설치 양식을 한 번 감지한 후 ECC_MODE로 고정합니다. 알고리즘 (순서대로 실행하며, 첫 번째 일치 항목에서 중단):

    1. /plugins/marketplaces/everything-claude-code/가 존재하면 → ECC_MODE=plugin.
    2. 그렇지 않은 경우, /agents/가 존재하고 적어도 하나의 ECC 에이전트 파일(예: tdd-guide.md, code-reviewer.md)을 포함하는 경우 → ECC_MODE=legacy.
    3. 그렇지 않은 경우 → 기본적으로 ECC_MODE=legacy로 설정하고 출력 상단에 한 줄의 경고를 표시합니다: > 경고: ECC 설치를 감지할 수 없음; 기본적으로 레거시 형식으로 설정됩니다. 플러그인 설치를 사용하는 경우 접두사를 수동으로 편집하십시오.
    4. 두 마커가 모두 존재하는 경우(혼합 설치), 플러그인이 우선합니다. 즉, 플러그인 네임스페이스만이 퍼지 매칭 없이 에이전트 이름을 해결합니다.

    이 시점부터 출력되는 모든 줄은 슬래시 명령 과 모든 에이전트 이름에 일치하는 접두사를 사용합니다. 동일한 출력에 두 형식을 모두 출력해서는 안 됩니다.

  3. --lang을 해결합니다. 'auto'인 경우, 다중 언어 감지 기능을 실행합니다:

    • 탐지 마커: pyproject.toml / uv.lock / requirements.txt → python; package.json → typescript; go.mod → go; Cargo.toml → rust; CMakeLists.txt 또는 최상위 *.cpp → cpp; pom.xml / build.gradle (Java) → java; build.gradle.kts 또는 최상위 Kotlin → kotlin; pubspec.yaml → flutter.
    • 다중 언어 동점 처리: 일치하는 마커가 두 개 이상인 경우, 소스 파일 수가 가장 많은 언어를 선택합니다( git ls-files를 통해 집계하며, vendor/, node_modules/, dist/, build/, .venv/, 생성된 파일 및 명백한 테스트 피처는 제외). 동점인 경우나 어떤 언어도 소스 파일의 60%를 초과하지 않는 경우, lang=unknown으로 설정합니다.
    • 일치하는 마커가 없는 경우 → lang=unknown으로 설정합니다.
    • lang=unknown은 센티넬(sentinel)이며, 에이전트 이름이 아닙니다. 2단계 규칙 4와 5는 체인 구성 시점에 이를 코드 검토자(code-reviewer) 또는 빌드 오류 해결자(build-error-resolver) 로 변환합니다.
  4. PyTorch 하위 프로필 감지: lang=python이고 pyproject.toml / requirements.txt / uv.lock 중 어느 하나라도 torch에 대한 의존성을 선언하면 pytorch=true로 설정합니다. 이는 빌드 체인 선택(아래 2단계 규칙)에만 영향을 미치며, 검토자는 python-reviewer로 유지됩니다.

  5. 계획에 선언된 모든 에이전트 이름을 정규화: 계획 텍스트에서 에이전트를 플러그인 접두사가 붙은 형태(예: everything-claude-code:tdd-guide)로 참조하는 경우, 체인을 검증하거나 구성하기 전에 접두사를 제거하여 기본 카탈로그 이름을 얻습니다. 접두사 재부여는 ECC_MODE에 따라 출력 시점(4단계)에만 수행됩니다. 접두사가 미리 부여된 이름이 체인 구성 단계로 유입되지 않도록 하십시오. 그렇지 않으면 플러그인 모드에서 접두사가 중복 적용될 수 있습니다.

1단계 — 단계 분해

우선순위 순서대로 “단계 단위”를 식별합니다:

  1. 명시적인 번호 매기기: ## 단계 N / ### 단계 N / ## N. ... / 최상위 순서 목록.
  2. 표의 “단계(Step)” 열.
  3. ----로 구분된 블록과 동사 중심의 제목.
  4. 그렇지 않은 경우 각 H2를 하나의 단계로 취급합니다.

단계별로 ID (1부터 시작), 제목 (80자 이하), 의도 (1~3문장), 태그를 추출합니다.

2단계 — 태그 지정 및 체인 선정

의도에 따라 태그 지정(다중 태그 허용; 1차 태그 + 중첩된 2차 태그로 체인 구성):

아래의 트리거 단어는 대소문자를 구분하지 않고 일치시킵니다. 다국어 계획은 의미가 나열된 영어 트리거 단어와 일치하는 한, 어떤 언어의 어간과도 일치시켜 지원됩니다.

태그 트리거 단어 기본 체인
design 건축, 디자인, 선택, 평가, RFC 기획자, 건축가
계획 계획, 세부 계획, 주요 단계 기획자
구현 구현, 빌드, 추가, 생성, 이식 tdd-guide,-reviewer
테스트 테스트, 커버리지, E2E, 통합 tdd-guide, e2e-runner
리팩토링 리팩토링, 정리, 중복 제거, 분할 아키텍트, 리팩터-클리너,-리뷰어
마이그레이션 마이그레이션, 업그레이드, 재작성, 이식 아키텍트, tdd-guide,-reviewer
db 스키마, 마이그레이션, 인덱스, SQL, Postgres, alembic, sqlmodel 데이터베이스 검토자,-reviewer
보안 암호화, 인증, 비밀 정보, OWASP, PII 보안 검토자,-reviewer
빌드 빌드, 컴파일, 린트 실패, CI -빌드-해결기 ( 빌드-오류-해결기로 대체됨)
문서 문서, readme, 코드맵, 변경 내역 doc-updater
조회 lookup, reference, API 사용법 docs-lookup
검토 검토, 감사, 검증 -검토자, 코드 검토자
루프 루프, 자율, 워치독 루프 연산자

체인 구성 규칙:

  1. 주 태그 선택: 한 단계가 여러 태그와 일치할 경우, 테이블 순서상 첫 번째 태그 (테이블 상단 = 최우선순위)가 주 태그가 되며, 나머지는 보조 태그가 됩니다. 아래의 구성 규칙 2와 3은 특정 다중 태그 조합을 명시적으로 처리하며, 그 외의 경우에는 태그 테이블 순서대로 보조 체인을 추가합니다.
  2. impl + security → tdd-guide,-reviewer, security-reviewer.
  3. impl + db → tdd-guide,database-reviewer,-reviewer.
  4. 결과 체인에서 중복을제거합니다 (첫 번째 발생 항목은 유지). 예: review + lang=unknown은 규칙 5 적용 후 code-reviewer,code-reviewer가 되지만, 중복 제거를 통해 code-reviewer로 통합됩니다.
  5. -reviewer는 lang=unknown일 때 code-reviewer 로 해결됩니다.
  6. - build -resolver는 lang=unknown일 때 build-error-resolver 로 해결됩니다. 특수한 경우: Phase 0에서 pytorch=true로 설정된 경우, . python-build-resolver는 존재하지 않으며, pytorch=true가 설정되지 않은 상태에서 --lang=python을 지정하면 build-error-resolver로 해결됩니다.
  7. 태그가 없는 단계: 일치하는 트리거 단어가 없으면 체인을 code-reviewer로 설정하고 '일치하는 태그 없음'이라고 기록합니다 . "체인 근거" 항목에는 기본적으로 review-only 체인이 표시됩니다.
  8. 중복 제거 후 체인 길이는 4 이하여야 합니다. 이를 초과할 경우 가장 약한 태그(검색 및 문서 태그부터 우선)를 제거합니다.
  9. 임플레멘테이션 체인에서는 플래너와 아키텍트를 짝지우지 마십시오(토큰 낭비). 디자인 단계에서만 짝지우십시오.
  10. impl, refactor 또는 migration 태그가 지정된 단계는 reviewer-class 에이전트( -reviewer, code-reviewer, security-reviewer 또는 database-reviewer 중 하나)로 끝납니다. 해당 도메인에 가장 특화된 검토자가 마지막 위치를 차지합니다(예: 규칙 2의 impl+security는 security-reviewer로 끝나고, 규칙 3의 impl+db는 -reviewer로 끝납니다. database-reviewer가 체인의 앞부분에서 이미 마이그레이션을 게이트 처리했기 때문입니다). 테스트 및 빌드 단계는 각각의 유효성 검사기(각각e2e-runner 및 빌드 해결기)에 의해 제어되며, 추가 검토자가 필요하지 않습니다.

3단계 — 작업 설명 압축

발생된 각 는 다음 조건을 충족해야 합니다:

  • 자립적이어야 합니다(첫 번째 에이전트가 계획 문서를 열어둘 필요가 없음).
  • [Plan: #step-]로 시작해야 합니다.
  • 검증 가능한 1~3개의 수용 기준을 포함해야 합니다.
  • 계획에서 해당 단계에 대한 범위 제한(범위 외: ...) 을 명시한 경우에만 이를 포함해야 합니다. 그대로 그대로 상속받아야 합니다. 계획에 범위 외 문구가 없는 경우, 해당 절을 완전히 생략해야 하며 — 임의로 만들어서는 안 됩니다.
  • 200~600자, 한 줄로 작성하십시오. "는 \"로 이스케이프 처리하고, 리터럴 줄바꿈은 사용하지 마십시오.

4단계 — 출력

ECC_MODE에 의해 결정된 형식을 사용하여 마크다운을 출력하십시오. 출력은 전체적으로 하나의 형식을 사용해야 합니다. 모든 {ORCH_CMD} 와 모든 에이전트 이름은 0단계에서 지정된 일치하는 접두사와 함께 렌더링됩니다. 두 가지 형식을 모두 출력해서는 안 되며, 렌더링된 출력에 “이것은 플러그인 형식입니다” / “접두사를 제거하세요”와 같은 지침을 포함해서는 안 됩니다.

구체적인 렌더링 규칙:

  • {ORCH_CMD} = 플러그인 환경에서는 /everything-claude-code:orchestrate, 레거시 환경에서는 /orchestrate.
  • {AGENT(name)} = 플러그인 환경에서는 everything-claude-code:, 레거시 환경에서는.
  • 개요 표의 "Chain" 열은 동일한 {AGENT(name)} 렌더링을 사용합니다.
  • 단계별 bash 블록에는 실행 가능한 명령만 포함됩니다. # plugin 형식이나 # legacy 형식 주석은 없습니다. 형식은 암시적이며 전체 출력에서 일관되게 적용됩니다.

출력 구조:

# Plan-Orchestrate 결과

**계획**: ``
**언어**: ``
**ECC 모드**: ``
**단계**: 
**범위**: 

## 단계 개요

| # | 제목 | 태그 | 체인 |
|---|---|---|---|
| 1 | ... | impl, db | `{AGENT(tdd-guide)},{AGENT(database-reviewer)},{AGENT(python-reviewer)}` |
| ... | | | |

---

## 1단계 — 

**의도**: <1–3 sentences>
**태그**: <a, b>
**체인 근거**: <why this chain; which agent closes the loop>

```bash
{ORCH_CMD} custom "{AGENT(tdd-guide)},{AGENT(database-reviewer)},{AGENT(python-reviewer)}" "[계획: docs/foo.md#step-1] <compressed task description>; 승인: <1–3 items>; 범위 외: <…>"
```
</code></pre>
<blockquote>
<p>위의 <code>{ORCH_CMD}</code> 및 <code>{AGENT(...)}</code> 표기법은 이 스킬이 실행 시 수행하는 대체 작업을 설명합니다. 실제로 출력되는 마크다운에는 해결된 문자열만 포함되며, 자리 표시자는 절대 포함되지 않습니다.</p>
</blockquote>
<p>사용자가 모든 명령어를 한 번에 붙여넣을 수 있도록, 각 단계의 명령어를 순서대로 집계하는 최종 “일괄 실행” 블록을 추가하십시오. <strong>“개요 전용” 모드에서는 일괄 블록을 생략하십시오</strong> (“대규모 계획” 예외 사례 참조): 개요 테이블만 출력되는 경우, 집계할 단계별 명령어가 없습니다.</p>
<h3>5단계 — 자체 점검 (출력 전 실행)</h3>
<ul>
<li><input disabled="" type="checkbox"> 모든 체인의 모든 에이전트는 카탈로그에서 가져옵니다(계획에 나타난 <code>everything-claude-code:</code> 접두사를 제거한 후; 0단계 5단계 참조).</li>
<li><input disabled="" type="checkbox"> 해결된 <code>{ORCH_CMD}</code> 와 모든 해결된 <code>{AGENT(...)}는</code> <strong>동일한</strong> 형식(<code>플러그인</code> 또는 <code>레거시</code>)을 사용하며, 하나의 출력에서 절대 혼합되지 않습니다.</li>
<li><input disabled="" type="checkbox"> 렌더링된 출력물에는 <code># 플러그인 형식</code> / <code># 레거시 형식</code> 주석이나 “접두사 제거” 지침이 남아 있지 않습니다.</li>
<li><input disabled="" type="checkbox"> <code>--mode</code> / <code>--gate</code> / <code>--agents=...</code> 필드가 임의로 생성되지 않습니다.</li>
<li><input disabled="" type="checkbox"> 각 작업 설명은 한 줄로, 큰따옴표로 묶여 있으며, <code>"는</code> 이스케이프 처리됩니다.</li>
<li><input disabled="" type="checkbox"> 각 작업 설명은 <code>[Plan: <path>#step-<id>]</code> 로 시작하며, Acceptance(1–3개 항목)를 포함합니다. <code>Out of scope:</code> 절은 계획에서 상속된 경우에만 나타납니다.</li>
<li><input disabled="" type="checkbox"> 2단계 중복 제거 후 어떤 체인에서도 중복 에이전트가 없어야 합니다.</li>
<li><input disabled="" type="checkbox"> 체인 길이는 4 이하입니다.</li>
<li><input disabled="" type="checkbox"> <code>impl/refactor/migration</code> 태그가 지정된 단계는 검토자 클래스 에이전트(<code><lang>-reviewer</code>, <code>code-reviewer</code>, <code>security-reviewer</code> 또는 <code>database-reviewer</code>)로 끝납니다. <code>test</code> 및 <code>build는</code> 예외입니다 — 2단계 규칙 10을 참조하십시오.</li>
<li><input disabled="" type="checkbox"> 태그가 없는 단계는 <code>'일치하는 태그가 없음'</code>이라는 근거와 함께 <code>code-reviewer를</code> 출력하며 <code>, 기본값은 검토 전용 체인입니다</code>.</li>
<li><input disabled="" type="checkbox"> 개요 표에는 <code>--scope</code>와 관계없이 계획의 모든 단계가 나열됩니다.</li>
<li><input disabled="" type="checkbox"> 단계별 세부 정보 블록 수는 해결된 <code>--scope와</code> 일치합니다( <code>--scope=all인</code> 경우 전체 계획; <code>step:n</code>인 경우 하나의 블록; <code>range:a-b</code>인 경우 범위 크기). 개요 전용 모드에서는 단계별 블록과 Batch 블록이 생성되지 않습니다.</li>
</ul>
<h2>경계 사례</h2>
<ul>
<li><strong>명확한 단계가 없는 경우</strong>: H2/H3 분할을 우선적으로 고려합니다. 그래도 모호한 경우, 문서 개요와 함께 “구조화된 단계가 감지되지 않음”을 보고하고, 사용자에게 개요에 따라 실행할지 확인을 요청합니다.</li>
<li><strong>대규모 계획(1500줄 초과)</strong>: <strong>개요 전용 모드로</strong> 진입 — 개요 테이블만 출력하고, 세부 정보를 확인하기 위해 다시 실행하기 전에 <code>--scope를</code> 사용하여 범위를 좁힐 것을 사용자에게 요청합니다. 이 모드에서는 단계별 세부 블록과 배치 실행 블록을 생략합니다.</li>
<li><strong>단계가 너무 광범위할</strong> 경우(예: “모든 백엔드 작업 완료”): 단일 체인을 강제로 생성하지 마십시오. N.a와 N.b로 분할할 것을 제안하고 분할 방안을 제시하십시오.</li>
<li><strong>계획에 에이전트가 선언된</strong> 경우(드물게 발생): 먼저 <strong> <code>everything-claude-code:</code> 접두사를 모두 제거하여</strong> 기본 카탈로그 이름만 추출한 후(Phase 0 단계 5), 카탈로그와 대조하여 유효성을 검증합니다. 유효하지 않은 에이전트는 교체하고 "Chain rationale" 항목에 그 이유를 설명합니다. 기본 이름은 출력 시점에 <code>ECC_MODE에</code> 따라 접두사가 다시 추가됩니다.</li>
<li><strong> <code>--lang=auto로</code> 승자를 선택할 수 없는 다국어 프로젝트</strong>: <code>lang=unknown으로</code> 설정하십시오. 검토자는 <code>code-reviewer로</code>, 빌드 해결자는 <code>build-error-resolver로</code> 해결하십시오. “체인 근거” 항목에 대체 방안을 명시하십시오.</li>
</ul>
<h2>예시</h2>
<h3>예시 1 — 플러그인 모드, Python 계획</h3>
<p>입력:</p>
<pre><code>plan-orchestrate @docs/plan/example-feature.md --lang=python
</code></pre>
<p>예상 출력 발췌문:</p>
<pre><code class="language-markdown">## 2단계 — 민감한 UserProfile 필드 암호화

**목적**: `EncryptedString` SQLAlchemy 타입을 도입하고, 데이터 저장 전에 `birth_datetime` / `location`을 AES-GCM으로 암호화하며, 환경 변수에서 키를 불러옵니다.
**태그**: impl, security, db
**체인 구성 근거**: 보안에 민감한 쓰기 경로이므로 `security-reviewer`가 체인을 마무리합니다. `database-reviewer`는 Alembic 마이그레이션을 검증하고, `python-reviewer`는 타입 지정 및 PEP 8 준수를 검토합니다.

```bash
/everything-claude-code:orchestrate custom "everything-claude-code:tdd-guide,everything-claude-code:database-reviewer,everything-claude-code:python-reviewer,everything-claude-code:security-reviewer" "[계획: docs/plan/example-feature.md#step-2] EncryptedString SQLAlchemy 타입을 구현하고 UserProfile.birth_datetime/location 열을 마이그레이션합니다. 키는 ENV의 APP_DB_KEY에서 가져옵니다. 수락 기준: 암호화/복호화 왕복 테스트 통과; 빈 데이터베이스에서 Alembic 업그레이드/다운그레이드 정상 수행; 마이그레이션 후 데이터베이스에 평문 데이터 없음; 범위 외: 테넌트 간 프로필 공유 로직"
```
</code></pre>
<h3>예제 2 — 레거시 모드, 동일한 단계</h3>
<p><code>ECC_MODE=legacy가</code> 감지된 경우, 동일한 단계가 단일 통합 명령어로 출력됩니다(출력 어디에도 플러그인 접두사가 붙은 형식이 없음):</p>
<pre><code class="language-bash">/orchestrate custom "tdd-guide,database-reviewer,python-reviewer,security-reviewer" "[Plan: docs/plan/example-feature.md#step-2] ..."
</code></pre>
<p>위의 두 예시는 서로 다른 두 환경에서 <strong>발생할 수 있는 두 가지 출력 형태를</strong> 보여줍니다. 단일 스킬 호출은 이 중 하나만을 처음부터 끝까지 생성합니다.</p>
<h2>참고</h2>
<ul>
<li>생성 전용입니다. 이 스킬 내부에서 <code>/orchestrate를</code> 호출해서는 안 됩니다.</li>
<li>작업 설명의 언어는 계획 문서의 언어와 일치시켜야 합니다(에이전트 이름은 항상 영어로 유지됩니다).</li>
<li>사용자가 명시적으로 요청하지 않는 한, 출력에 "Co-Authored-By" 줄이나 이모티콘을 삽입하지 마십시오.</li>
</ul>                                </div>
                                <div class="skilldetailsL1_skillmd">
                                    <a href="https://github.com/affaan-m/ECC/tree/main/skills/plan-orchestrate" title="GitHub에서 보기" target="_blank" rel="nofollow"
                                        aria-label="GitHub에서 보기" class="skilldetails_toGitHub">
                                        <span>GitHub에서 보기</span>
                                        <b></b>
                                    </a>
                                    <pre><code>---
name: plan-orchestrate
description: Reads a plan document, decomposes it into steps, designs a per-step agent chain from the ECC catalogue, and emits ready-to-paste /orchestrate custom prompts without executing them.
---

# Plan Orchestrate

Bridge a plan document to `/orchestrate custom` by emitting one ready-to-paste invocation per step. The skill is generative only — it never executes `/orchestrate`. The user pastes each line when ready.

## When to Activate

- User has a multi-step plan document (PRD, RFC, implementation plan) and wants to drive it through `/orchestrate`.
- User says "orchestrate this plan", "give me orchestrate prompts for each step", "compose chains for this plan".
- A step-by-step plan exists but the user does not want to manually pick agents per step.

Skip when:
- The work is one ad-hoc step → call `/orchestrate custom` directly.
- The plan is unreadable or empty. Lack of explicit numbering alone is not a skip condition — see the "No clear steps" edge case below.

## Inputs

```
<plan-doc-path> [--lang=python|typescript|go|rust|cpp|java|kotlin|flutter|auto] [--scope=all|step:<n>|range:<a>-<b>] [--dry-run]
```

- `<plan-doc-path>` — required; relative or absolute path (`@docs/...` accepted).
- `--lang` — reviewer language variant; defaults to `auto` (detected from project).
- `--scope` — limits emitted steps; defaults to `all`.
- `--dry-run` — print decomposition + chain rationale only; do not emit final prompts.

## Authoritative `/orchestrate` shape (do not deviate)

```
{ORCH_CMD} custom "<agent1>,<agent2>,...,<agentN>" "<task description>"
```

Where `{ORCH_CMD}` is determined in Phase 0 (see below). The command string in the emitted output **always uses one concrete form** — never both, never a placeholder.

- `custom` is a sequential chain; each agent's HANDOFF feeds the next.
- Comma-separated agent list. No spaces preferred; one space tolerated.
- No `--mode` / `--gate` / `--agents=...` flags exist — never invent them.
- Agent names come from the catalogue in this skill. Embedded double quotes in the task description are escaped as `\"`.

## ECC install form and namespacing

Two install forms determine the prefix on **both** the slash command and every agent name. The two MUST stay in sync — one form per output, never mixed:

Let `<claude-home>` denote the Claude Code home directory: `~/.claude` on macOS/Linux, `%USERPROFILE%\.claude` on Windows. Resolve it the way the host platform resolves the user home directory (do not hardcode `~`).

| Form | Detection | `{ORCH_CMD}` | Agent name format |
|---|---|---|---|
| Plugin install (1.9.0+) | `<claude-home>/plugins/marketplaces/everything-claude-code/` exists | `/everything-claude-code:orchestrate` | `everything-claude-code:<name>` |
| Legacy bare install | Above absent; agent files under `<claude-home>/agents/` | `/orchestrate` | `<name>` |

Why this matters: under the plugin install, agents register as `everything-claude-code:tdd-guide`. Bare names force fuzzy matching, which fails intermittently under parallel calls. Under legacy, the prefixed forms are not registered and fail outright.

## Available agent catalogue (must pick from these)

General:
- `planner` — requirement restatement, risk decomposition, step planning
- `architect` — architecture, system design, refactor proposals
- `tdd-guide` — write tests → implement → 80%+ coverage
- `code-reviewer` — generic code review
- `security-reviewer` — security audit, OWASP, secret leakage
- `refactor-cleaner` — dead code, duplicates, knip-class cleanup
- `doc-updater` — documentation, codemap, README
- `docs-lookup` — third-party library API lookups (Context7)
- `e2e-runner` — end-to-end test orchestration
- `database-reviewer` — PostgreSQL schema, migration, performance
- `harness-optimizer` — local agent harness configuration
- `loop-operator` — long-running autonomous loops
- `chief-of-staff` — multi-channel triage (rarely a fit for plan steps)

Build error resolvers:
- `build-error-resolver` (generic) / `cpp-build-resolver` / `go-build-resolver` / `java-build-resolver` / `kotlin-build-resolver` / `rust-build-resolver` / `pytorch-build-resolver`

Code reviewers:
- `python-reviewer` / `typescript-reviewer` / `go-reviewer` / `rust-reviewer` / `cpp-reviewer` / `java-reviewer` / `kotlin-reviewer` / `flutter-reviewer`

A misspelled agent name fails `/orchestrate`. Cross-check against this list before emitting.

## How It Works

### Phase 0 — Detect ECC mode + language

1. Read `<plan-doc-path>`. If missing or empty, report and stop.
2. Detect ECC install form once and freeze it into `ECC_MODE`. Algorithm (run in order, stop at the first match):
   1. If `<claude-home>/plugins/marketplaces/everything-claude-code/` exists → `ECC_MODE=plugin`.
   2. Else if `<claude-home>/agents/` exists and contains at least one ECC agent file (e.g. `tdd-guide.md`, `code-reviewer.md`) → `ECC_MODE=legacy`.
   3. Else → default to `ECC_MODE=legacy` and emit a one-line warning at the top of the output: `> Warning: could not detect ECC install; defaulting to legacy form. If you use the plugin install, edit the prefixes manually.`
   4. If both markers exist (mixed install), `plugin` wins — the plugin namespace is the only one that resolves agent names without fuzzy matching.

   From this point on, every emitted line uses the matching prefix on **both** the slash command and every agent name. **Never emit both forms in the same output.**
3. Resolve `--lang`. When `auto`, run a polyglot-aware detection:
   - Probe markers: `pyproject.toml` / `uv.lock` / `requirements.txt` → python; `package.json` → typescript; `go.mod` → go; `Cargo.toml` → rust; `CMakeLists.txt` or top-level `*.cpp` → cpp; `pom.xml` / `build.gradle` (Java) → java; `build.gradle.kts` or top-level Kotlin → kotlin; `pubspec.yaml` → flutter.
   - **Polyglot tie-break**: if more than one marker matches, pick the language whose source files outnumber the others (count via `git ls-files`, excluding `vendor/`, `node_modules/`, `dist/`, `build/`, `.venv/`, generated files, and obvious test fixtures). On a tie or when no language exceeds 60% of source files, set `lang=unknown`.
   - No marker matched → set `lang=unknown`.
   - `lang=unknown` is a sentinel — it is **not** an agent name. Phase 2 rules 4 and 5 turn it into `code-reviewer` / `build-error-resolver` at chain composition time.
4. Detect a **PyTorch sub-profile**: when `lang=python` and any of `pyproject.toml` / `requirements.txt` / `uv.lock` declares a dependency on `torch`, set `pytorch=true`. This only affects `build` chain selection (Phase 2 rule below); the reviewer remains `python-reviewer`.
5. **Normalize any agent names declared in the plan**: if the plan text references agents by their plugin-prefixed form (e.g. `everything-claude-code:tdd-guide`), strip the prefix to get the bare catalogue name before validating or composing chains. Re-prefixing happens only at output time per `ECC_MODE` (Phase 4). Never let a pre-prefixed name flow into chain composition — it would double-prefix in plugin mode.

### Phase 1 — Decompose steps

Identify "step units" in priority order:

1. Explicit numbering: `## Step N` / `### Phase N` / `## N. ...` / top-level ordered list.
2. A "Step" column in a table.
3. `---`-separated blocks with verb-led headings.
4. Otherwise treat each H2 as one step.

Per step extract `id` (1-based), `title` (≤ 80 chars), `intent` (1–3 sentences), `tags`.

### Phase 2 — Tag and pick chain

Tag by intent (multi-tag allowed; chain built from primary + stacked secondaries):

Trigger words below are matched case-insensitively. Multilingual plans are supported by matching the word stems in any language as long as the meaning aligns with the listed English trigger words.

| Tag | Trigger words | Default chain |
|---|---|---|
| `design` | architecture, design, choose, evaluate, RFC | `planner,architect` |
| `plan` | plan, breakdown, milestone | `planner` |
| `impl` | implement, build, add, create, port | `tdd-guide,<lang>-reviewer` |
| `test` | test, coverage, e2e, integration | `tdd-guide,e2e-runner` |
| `refactor` | refactor, cleanup, dedupe, split | `architect,refactor-cleaner,<lang>-reviewer` |
| `migration` | migrate, upgrade, rewrite, port | `architect,tdd-guide,<lang>-reviewer` |
| `db` | schema, migration, index, SQL, Postgres, alembic, sqlmodel | `database-reviewer,<lang>-reviewer` |
| `security` | encrypt, auth, secret, OWASP, PII | `security-reviewer,<lang>-reviewer` |
| `build` | build, compile, lint failure, CI | `<lang>-build-resolver` (falls back to `build-error-resolver`) |
| `docs` | docs, readme, codemap, changelog | `doc-updater` |
| `lookup` | lookup, reference, API usage | `docs-lookup` |
| `review` | review, audit, verify | `<lang>-reviewer,code-reviewer` |
| `loop` | loop, autonomous, watchdog | `loop-operator` |

Chain composition rules:
1. **Primary tag selection**: when a step matches multiple tags, the **first one in table order** (top of the table = highest priority) is the primary; the rest are secondaries. Composition rules 2 and 3 below handle specific multi-tag combinations explicitly; otherwise, append secondary chains in tag table order.
2. `impl` + `security` → `tdd-guide,<lang>-reviewer,security-reviewer`.
3. `impl` + `db` → `tdd-guide,database-reviewer,<lang>-reviewer`.
4. **Deduplicate** the resulting chain (preserve first occurrence). E.g. `review` + `lang=unknown` would yield `code-reviewer,code-reviewer` after rule 5; deduplication collapses it to `code-reviewer`.
5. `<lang>-reviewer` resolves to `code-reviewer` when `lang=unknown`.
6. `<lang>-build-resolver` resolves to `build-error-resolver` when `lang=unknown`. **Special case**: if Phase 0 set `pytorch=true`, use `pytorch-build-resolver` for `build` chains regardless of `<lang>`. There is no `python-build-resolver`; `--lang=python` without `pytorch=true` resolves to `build-error-resolver`.
7. **Zero-tag steps**: if no trigger word matches, set chain to `code-reviewer` and write `no tag matched; default review-only chain` under "Chain rationale".
8. Chain length ≤ 4 after deduplication. If exceeded, drop weakest tag (`lookup` and `docs` first).
9. Do not pair `planner` and `architect` in an `impl` chain (token waste). Pair them only on `design` steps.
10. Steps tagged `impl`, `refactor`, or `migration` end with a **reviewer-class** agent — any of `<lang>-reviewer`, `code-reviewer`, `security-reviewer`, or `database-reviewer`. The most domain-specific reviewer wins the tail position (e.g. rule 2's `impl+security` ends with `security-reviewer`; rule 3's `impl+db` ends with `<lang>-reviewer` because `database-reviewer` already gates the migration earlier in the chain). `test` and `build` steps are gated by their own validators (`e2e-runner` and the build resolver respectively) and do not require an additional reviewer.

### Phase 3 — Compress task description

Each emitted `<task description>` must:
- Be self-contained (the first agent does not need the plan document open).
- Start with `[Plan: <path>#step-<id>]`.
- Include 1–3 verifiable Acceptance criteria.
- Include a Scope guard (`Out of scope: ...`) **only if the plan declares one for this step**. Inherit verbatim. If the plan has no out-of-scope statement, omit the clause entirely — do not invent one.
- Be 200–600 characters; one line; embedded `"` escaped as `\"`; no literal newlines.

### Phase 4 — Output

Emit Markdown using **the form determined by `ECC_MODE`**. The output uses one form throughout — every `{ORCH_CMD}` and every agent name is rendered with the matching prefix from Phase 0. **Do not emit both forms; do not include "this is plugin form" / "strip the prefix" instructions in the rendered output.**

Concrete rendering rules:

- `{ORCH_CMD}` = `/everything-claude-code:orchestrate` under `plugin`, `/orchestrate` under `legacy`.
- `{AGENT(name)}` = `everything-claude-code:<name>` under `plugin`, `<name>` under `legacy`.
- The overview-table "Chain" column uses the same `{AGENT(name)}` rendering.
- Per-step bash blocks contain only the runnable command. **No `# plugin form` or `# legacy form` comments** — the form is implicit and uniform across the whole output.

Output structure:

````markdown
# Plan-Orchestrate Result

**Plan**: `<path>`
**Lang**: `<detected-or-given>`
**ECC mode**: `<plugin | legacy>`
**Steps**: <N>
**Scope**: <all | step:n | range:a-b>

## Steps overview

| # | Title | Tags | Chain |
|---|---|---|---|
| 1 | ... | impl, db | `{AGENT(tdd-guide)},{AGENT(database-reviewer)},{AGENT(python-reviewer)}` |
| ... | | | |

---

## Step 1 — <title>

**Intent**: <1–3 sentences>
**Tags**: <a, b>
**Chain rationale**: <why this chain; which agent closes the loop>

```bash
{ORCH_CMD} custom "{AGENT(tdd-guide)},{AGENT(database-reviewer)},{AGENT(python-reviewer)}" "[Plan: docs/foo.md#step-1] <compressed task description>; Acceptance: <1–3 items>; Out of scope: <…>"
```
````

> The `{ORCH_CMD}` and `{AGENT(...)}` notation above describes the substitution this skill performs at runtime. The actual emitted Markdown contains the resolved strings, never the placeholders.

Append a final "Batch execution" block aggregating every step's command in order so the user can paste them all at once. **Skip the Batch block in overview-only mode** (see "Large plan" edge case): when only the overview table is being emitted, there are no per-step commands to aggregate.

### Phase 5 — Self-check (run before emitting)

- [ ] Every agent in every chain comes from the catalogue (after stripping any `everything-claude-code:` prefix that appeared in the plan; see Phase 0 step 5).
- [ ] Resolved `{ORCH_CMD}` and every resolved `{AGENT(...)}` use the **same** form (`plugin` or `legacy`) — never mixed in one output.
- [ ] No `# plugin form` / `# legacy form` annotations and no "strip the prefix" instructions remain in the rendered output.
- [ ] No invented `--mode` / `--gate` / `--agents=...` fields.
- [ ] Each task description is single-line, double-quoted, with embedded `"` escaped.
- [ ] Each task description begins with `[Plan: <path>#step-<id>]` and includes Acceptance (1–3 items). The `Out of scope:` clause is present only when inherited from the plan.
- [ ] No duplicate agent in any chain after Phase 2 dedup.
- [ ] Chain length ≤ 4.
- [ ] Steps tagged `impl`/`refactor`/`migration` end with a reviewer-class agent (`<lang>-reviewer`, `code-reviewer`, `security-reviewer`, or `database-reviewer`). `test` and `build` are exempt — see Phase 2 rule 10.
- [ ] Zero-tag steps emit `code-reviewer` with the rationale `no tag matched; default review-only chain`.
- [ ] Overview table lists every step in the plan, regardless of `--scope`.
- [ ] Per-step detail block count matches the resolved `--scope` (full plan when `--scope=all`; one block for `step:n`; range size for `range:a-b`). In overview-only mode, no per-step blocks and no Batch block are emitted.

## Edge cases

- **No clear steps**: prefer H2/H3 splitting; if still ambiguous, report "no structured steps detected" with the document outline and ask the user to confirm running by outline.
- **Large plan (>1500 lines)**: enter **overview-only mode** — emit only the overview table and ask the user to narrow with `--scope` before re-running for details. In this mode, skip per-step detail blocks and skip the Batch execution block.
- **Step too broad** (e.g. "complete all backend work"): do not force a single chain. Suggest splitting into N.a and N.b and propose a split.
- **Plan declares agents** (rare): first **strip any `everything-claude-code:` prefix** to get the bare catalogue name (Phase 0 step 5), then validate against the catalogue. Replace invalid agents and explain under "Chain rationale". The bare name is re-prefixed at output time per `ECC_MODE`.
- **Polyglot project where `--lang=auto` cannot pick a winner**: set `lang=unknown`; reviewer resolves to `code-reviewer` and build resolver to `build-error-resolver`. Mention the fallback under "Chain rationale".

## Examples

### Example 1 — Plugin mode, Python plan

Input:
```
plan-orchestrate @docs/plan/example-feature.md --lang=python
```

Excerpt of expected output:
````markdown
## Step 2 — Encrypt sensitive UserProfile fields

**Intent**: Introduce an `EncryptedString` SQLAlchemy type and AES-GCM encrypt `birth_datetime` / `location` before persistence; load the key from an environment variable.
**Tags**: impl, security, db
**Chain rationale**: Security-sensitive write path, so `security-reviewer` closes the chain; `database-reviewer` validates the alembic migration; `python-reviewer` covers typing and PEP 8.

```bash
/everything-claude-code:orchestrate custom "everything-claude-code:tdd-guide,everything-claude-code:database-reviewer,everything-claude-code:python-reviewer,everything-claude-code:security-reviewer" "[Plan: docs/plan/example-feature.md#step-2] Implement EncryptedString SQLAlchemy type and migrate UserProfile.birth_datetime/location columns; key from ENV APP_DB_KEY; Acceptance: encrypt/decrypt roundtrip tests pass; alembic upgrade/downgrade clean on empty DB; no plaintext in DB after migrate; Out of scope: cross-tenant profile sharing logic"
```
````

### Example 2 — Legacy mode, same step

If `ECC_MODE=legacy` were detected, the same step would be emitted as a single uniform command (no plugin-prefixed forms anywhere in the output):

```bash
/orchestrate custom "tdd-guide,database-reviewer,python-reviewer,security-reviewer" "[Plan: docs/plan/example-feature.md#step-2] ..."
```

The two examples above illustrate **the two possible outputs** for two different environments. A single skill invocation produces only one of them, end to end.

## Notes

- Generative only. Never invoke `/orchestrate` from inside this skill.
- Match the language of the plan document for task descriptions (agent names always remain English).
- Do not insert "Co-Authored-By" lines or emoji in the output unless the user explicitly asks.
</code></pre>                                </div>
                            </div>

                        </div>
                        <script>
                            layui.use(function () {
                                var element = layui.element;
                                element.tab({
                                    headerElem: "#skilldetailsL1_header>button",
                                    bodyElem: "#skilldetailsL1_body>div",
                                });
                            });
                        </script>
                        <div class="skilldetailsL2">
                            <div class="skilldetailsL2_title">
                                <h2>모든 파일</h2>
                                <span>1개 파일</span>
                            </div>
                                                        <div class="skillFiles">
                                <div class="skillFilesL">
                                    <b></b>
                                    <a href="https://github.com/affaan-m/ECC/tree/main/skills/plan-orchestrate" title="plan-orchestrate.md" target="_blank"
                                        aria-label="plan-orchestrate.md"
                                        rel="nofollow">plan-orchestrate.md</a>
                                    <span>17.5k</span>
                                </div>
                                <a href="https://github.com/affaan-m/ECC/tree/main/skills/plan-orchestrate" title="보기" target="_blank" aria-label="보기"
                                    rel="nofollow">보기</a>
                            </div>
                                                    </div>
                    </div>
                    <div class="skilldetailsR">
                        <div class="skilldetailsR1">
                            <div class="skilldetailsR1s">
                                <h2>plan-orchestrate 설치</h2>
                                <div class="skilldetailsR1s_header" id="skilldetailsR1s_header">
                                    <button class="layui-this">
                                        <b></b>
                                        <span>ZIP 다운로드</span>
                                    </button>
                                    <button class="">
                                        <b></b>
                                        <span>Git Clone</span>
                                    </button>
                                </div>
                                <div class="skilldetailsR1s_body" id="skilldetailsR1s_body">
                                    <div class="skilldetailsR1s_body1 layui-show">
                                        <p>스킬 파일을 다운로드하여 .claude/skills/ 디렉터리에 압축을 풀어주세요.</p>
                                        <a href="javascript:;" title="ZIP 다운로드" data-source="TeeN26C1ni2ZDZRkOJVh9w"
                                            aria-label="ZIP 다운로드" role="button" class="skill_downloadzip">
                                            <b></b>
                                            <span>ZIP 다운로드</span>
                                        </a>
                                    </div>
                                    <div class="skilldetailsR1s_body2">
                                        <p>저장소를 클론하고 스킬 파일을 프로젝트에 복사하세요.</p>
                                        <div class="skill_clone">
                                            <p>
                                                git clone https://github.com/affaan-m/ECC/tree/main/skills/plan-orchestrate
# Copy SKILL.md to your .claude/skills/ directory                                            </p>
                                            <a href="javascript:;" title="복사" role="button" aria-label="복사"
                                                class="skill_clone_copy">
                                                <img src="/assets/images/prompt_word2RMs_p_btn.png"
                                                    alt="복사" />
                                                <span>복사</span>
                                            </a>
                                        </div>
                                    </div>
                                </div>
                                <div class="skilldetailsR1s_info">
                                    <span>빠른 설정: </span>
                                    스킬 폴더를 .claude/skills/로 복사하세요.
Claude가 해당 스킬을 자동으로 감지하여 사용할 것입니다.                                </div>
                                <div class="skilldetailsR1s_repository">
                                    <span>저장소</span>
                                    <a href="https://github.com/affaan-m/ECC/tree/main/skills/plan-orchestrate" title="affaan-m/ECC" target="_blank"
                                        aria-label="저장소" rel="nofollow">affaan-m/ECC</a>
                                </div>
                            </div>
                        </div>
                        <div class="skilldetailsR2">
                            <h2>관련 스킬</h2>
                            <div>
                                                                <div class="skilldetailsR2s">
                                    <a href="/ko/skill/detail/airtableautomation.html" title="airtable-automation" aria-label="airtable-automation">airtable-automation</a>
                                    <div>
                                        <div class="skilldetailsR2s_time">
                                            <b></b>
                                            <span>업데이트 된 시간                                                2026년 6월 29일</span>
                                        </div>
                                        <button class="xix_star skill_datas"
                                            data-source="P_PqrAzxvKSebU4gaXatSw">
                                            <b></b>
                                            <span
                                                class="collectNums_P_PqrAzxvKSebU4gaXatSw">0</span>
                                        </button>
                                    </div>
                                </div>
                                                                <div class="skilldetailsR2s">
                                    <a href="/ko/skill/detail/notionautomation.html" title="notion-automation" aria-label="notion-automation">notion-automation</a>
                                    <div>
                                        <div class="skilldetailsR2s_time">
                                            <b></b>
                                            <span>업데이트 된 시간                                                2026년 6월 29일</span>
                                        </div>
                                        <button class="xix_star skill_datas"
                                            data-source="yLOF7em0zgx36kG9EQmIAQ">
                                            <b></b>
                                            <span
                                                class="collectNums_yLOF7em0zgx36kG9EQmIAQ">0</span>
                                        </button>
                                    </div>
                                </div>
                                                                <div class="skilldetailsR2s">
                                    <a href="/ko/skill/detail/seoprogrammatic.html" title="seo-programmatic" aria-label="seo-programmatic">seo-programmatic</a>
                                    <div>
                                        <div class="skilldetailsR2s_time">
                                            <b></b>
                                            <span>업데이트 된 시간                                                2026년 6월 29일</span>
                                        </div>
                                        <button class="xix_star skill_datas"
                                            data-source="qrlDZwmv4vNLPwqrODKcOQ">
                                            <b></b>
                                            <span
                                                class="collectNums_qrlDZwmv4vNLPwqrODKcOQ">0</span>
                                        </button>
                                    </div>
                                </div>
                                                                <div class="skilldetailsR2s">
                                    <a href="/ko/skill/detail/revops.html" title="revops" aria-label="revops">revops</a>
                                    <div>
                                        <div class="skilldetailsR2s_time">
                                            <b></b>
                                            <span>업데이트 된 시간                                                2026년 6월 29일</span>
                                        </div>
                                        <button class="xix_star skill_datas"
                                            data-source="ZDIT-veTOzkFQQ0eUEoT-g">
                                            <b></b>
                                            <span
                                                class="collectNums_ZDIT-veTOzkFQQ0eUEoT-g">0</span>
                                        </button>
                                    </div>
                                </div>
                                
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </main>
        <footer>
  <div class="footer">
    <div class="footer1">
      <div class="footer11">
        <span class="footer11_title">핫 AI 도구</span>
        <div class="footer11info">
                    <a href="/ko/tool/ai-clothes-remover.html" aria-label="AI Clothes Remover" class="footer11s">AI Clothes Remover</a>
                    <a href="/ko/tool/deepnude-generator.html" aria-label="DeepNude generator" class="footer11s">DeepNude generator</a>
                    <a href="/ko/tool/purechat.html" aria-label="PureChat" class="footer11s">PureChat</a>
                  </div>
      </div>
      <div class="footer12">
        <span class="footer11_title">잠재력이있는 AI 도구</span>
        <div class="footer11info">
                    <a href="/ko/tool/idea-box-ai-tool.html" aria-label="Name Idea Box" class="footer11s">Name Idea Box</a>
                    <a href="/ko/tool/qi-jing-ai-ai-tool.html" aria-label="奇境 AI" class="footer11s">奇境 AI</a>
                    <a href="/ko/tool/ezaudio-ai-tool.html" aria-label="EZAudio" class="footer11s">EZAudio</a>
                  </div>
      </div>
      <div class="footer13">
        <span class="footer11_title">더 읽으십시오</span>
        <div class="footer11info">
                    <a href="/ko/ainews/ai-hosts-notebooklm-podcast-interviews.html" aria-label="AI Notebooklm Podcast의 AI 호스트는 이제 인터뷰에 참여할 수 있습니다" class="footer11s">AI Notebooklm Podcast의 AI 호스트는 이제 인터뷰에 참여할 수 있습니다</a>
                    <a href="/ko/ainews/corporate-ai-adoption-leveling-ramp-data.html" aria-label="기업 AI 도입 정체기, 램프 데이터에 따르면" class="footer11s">기업 AI 도입 정체기, 램프 데이터에 따르면</a>
                    <a href="/ko/ainews/microsoft-unveils-businessfocused-copilot-surface-devices-powered-intel.html" aria-label="Microsoft는 인텔이 구동하는 비즈니스 중심 Copilot+ 표면 장치를 공개합니다" class="footer11s">Microsoft는 인텔이 구동하는 비즈니스 중심 Copilot+ 표면 장치를 공개합니다</a>
                  </div>
      </div>
      <div class="footer4">
        <span class="footer11_title">따르다</span>
        <div class="footer11info">
          <a href="javascript:;" class="footer11s">저희에게 연락하십시오</a>
          <a href="mailto:admin@xix.ai" role="button" aria-label="저희에게 연락하십시오" class="footer11s">admin@xix.ai</a>
          <a href="/sitemap.xml" class="footer11s" aria-label="SiteMap">SiteMap</a>
        </div>
      </div>
    </div>
    <span class="footer2"></span>
    <div class="footer3">Copyright ©2025 xix.ai All Rights Reserved.</div>
  </div>
</footer>
<div class="ai_cookie" style="display: none">
      <div class="ai_cookie_b">
        <div class="icon_f ai_cookie_close">
          <svg class="icon" aria-hidden="true">
            <use xlink:href="#icon-guanbi1"></use>
          </svg>
        </div>
        <p>
          「모든 쿠키 수락」을 클릭하면 사이트 탐색 개선, 사이트 사용 분석 및 마케팅 활동 지원을 위해 장치에 쿠키를 저장하는 데 동의하게 됩니다.<span>개인정보 취급방침</span> 공지        </p>
        <div class="cokiesetRight">
          <a href="javascript:;" class="cokieA ai_cookie_open"  role="button" aria-label="쿠키 설정">쿠키 설정</a>
          <a href="javascript:;" class="cokieA RefuseCookies" role="button" aria-label="모두 거부">모두 거부</a>
          <a href="javascript:;" class="cokieA cokieAall" role="button" aria-label="모든 쿠키 수락">모든 쿠키 수락</a>
        </div>
      </div>
    </div>
    <div class="ai_cookieSettings" style="display: none">
      <div class="layuiDivcokie layui-layer-wrap" id="layuiDivcokie" style="display: block">
        <div class="cokielayTop dlyflx">
          <img src="/assets/images/logo.png" alt="" />
          <div class="icon_f ai_cookie_close1">
            <svg class="icon" aria-hidden="true">
              <use xlink:href="#icon-guanbi"></use>
            </svg>
          </div>
        </div>
        <hr />
        <div class="cokielayDown dlyflx">
          <p class="cokielaydTop">개인정보 설정</p>
          <p class="cokielaydDesc">
            웹사이트를 방문하면 브라우저에 정보를 저장하거나 불러올 수 있으며, 대부분은 쿠키의 형태입니다. 이 정보는 사용자, 환경설정 또는 기기에 관한 것일 수 있으며, 사이트가 기대한 대로 작동하도록 하는 데 주로 사용됩니다. 이 정보가 직접적으로 사용자를 식별하지는 않지만, 더 개인화된 웹 환경을 제공할 수 있습니다. 당사는 사용자의 개인정보 보호 권리를 존중하기 때문에 일부 유형의 쿠키를 허용하지 않을 수 있습니다. 각 카테고리 제목을 클릭하면 자세히 알아보고 기본 설정을 변경할 수 있습니다. 그러나 일부 유형의 쿠키를 차단하면 사이트 이용 경험 및 제공 가능한 서비스에 영향을 줄 수 있습니다. <a href="#" title="개인정보 취급방침" aria-label="개인정보 취급방침"><span>개인정보 취급방침</span></a> <b>성명</b>          </p>

          <div class="cokielayDivdown">
            <p class="coklaydownP">환경설정 관리</p>
            <ul class="cokidownUl">
              <li class="cokidownli dlyflx" style="padding: 25px 0px 25px">
                <div class="ckdTops">
                  <div class="ckdLeft">
                    <div class="icon_f">
                      <svg class="icon" aria-hidden="true">
                        <use xlink:href="#icon-add"></use>
                      </svg>
                      <svg class="icon icon_active" aria-hidden="true">
                        <use xlink:href="#icon-add1"></use>
                      </svg>
                    </div>
                    <p class="ckdlipmid">필수 쿠키</p>
                  </div>
                  <p class="ckdlipr">항상 활성화</p>
                </div>
                <p class="ckdDowns">
                  이 쿠키는 웹사이트가 정상적으로 기능하는 데 필요하며, 우리 시스템에서 끌 수 없습니다. 이러한 쿠키는 일반적으로 개인정보 설정, 로그인 또는 양식 작성과 같은 서비스 요청에 해당하는 사용자 행동에 응답하여만 설정됩니다. 브라우저를 설정하여 이러한 쿠키를 차단하거나 경고할 수 있지만, 그 경우 사이트의 일부 기능이 작동하지 않을 수 있습니다. 이러한 쿠키는 개인 식별 정보를 저장하지 않습니다.                </p>
              </li>
            </ul>
          </div>
        </div>
        <div class="cklyBtn">
          <a href="javascript:;" role="button" aria-label="모든 쿠키 수락" class="active cokieAall">모든 쿠키 수락</a>
        </div>
      </div>
      <script>
        $(document).on("click", ".ai_cookie_close", function () {
          $(".ai_cookie").hide();
        });
        $(document).on("click", ".ai_cookie_close1", function () {
          $(".ai_cookieSettings").hide();
        });
        $(document).on("click", ".ai_cookie_open", function () {
          $(".ai_cookieSettings").show();
        });
        $(document).on("click", ".ckdLeft", function () {
          var $li = $(this).closest("li"); 
          var $downs = $li.find(".ckdDowns"); 
          var $iconBox = $(this).find(".icon_f"); 

         
          $downs.slideToggle(200, function () {
            if ($downs.is(":visible")) {
              $iconBox.find(".icon").hide();
              $iconBox.find(".icon_active").show();
            } else {
              $iconBox.find(".icon").hide();
              $iconBox.find(".icon").first().show(); 
            }
          });
        });     
      </script>
    </div>
<link rel="stylesheet" type="text/css" href="https://accounts.google.com/gsi/style">
<div class="login_tab">
  <div class="login_mainC">
    <div class="login_tab_top">
      <div class="login_tab_top1">
        <a href="javascript:;" role="tab" aria-label="로그인" aria-selected="true" class="login_tab_top1a ">로그인</a>
        <a href="javascript:;" role="tab" aria-label="가입하십시오" aria-selected="false" class="login_tab_top2a">가입하십시오</a>
      </div>
      <div class="login_tab_top2">
        <a href="javascript:;"><img src="/assets/images/login_mainC_top_m_img.png" alt=""></a>
      </div>

    </div>
    <div class="forms_google">
      <div id="g_id_signin"></div>
    </div>
    <div class="forms_or">
      <div class="forms_line"></div>
      <span>OR</span>
      <div class="forms_line"></div>
    </div>
    <div class="login_tab_bottom">
      <div class="login_tab_top1a_bottom">

        <div class="login_form ">
          <div class="login_forms">
            <img src="/assets/images/login_email.png" alt="이메일">
            <input type="text" placeholder="이메일 주소를 작성하십시오" class="login_forms_email">
            <span></span>
          </div>
          <div class="login_forms">
            <img src="/assets/images/login_password.png" alt="비밀번호">
            <input type="password" placeholder="비밀번호를 입력하십시오" class="login_forms_password">
            <i style="cursor: pointer;" class="layui-icon layui-icon-eye-invisible toggle-password"
              id="toggleLoginPassword"></i>
            <span></span>
          </div>
          <div class="login_forms forms_code1">
            <input type="text" placeholder="그래픽 검증 코드를 입력하십시오"
              class="login_forms_captcha">
            <img src="" alt="그래픽 검증 코드를 입력하십시오" class="login-js-refresh-captcha">
            <span></span>
          </div>
          <div class="login_forms_bottom">
            <label class="login_remember">
              <input type="checkbox" aria-label="나를 기억하십시오">
              <span>나를 기억하십시오</span>
            </label>
            <a href="/ko/account/forgetPassword.html" aria-label="비밀번호를 변경하십시오" class="login_forget">비밀번호를 잊어 버렸습니다</a>
          </div>
          <a href="javascript:;" type="button" role="button" aria-label="로그인" id="login_button" class="login_button">로그인</a>

        </div>
      </div>
      <div class="login_tab_top2a_bottom">
        <div class="login_form">
          <div class="login_forms">
            <img src="/assets/images/login_email.png" alt="이메일">
            <input type="text" placeholder="이메일 주소를 작성하십시오" class="register_forms_email">
            <span></span>
          </div>
          <div class="login_forms">
            <img src="/assets/images/login_password.png" alt="비밀번호">
            <input type="password" placeholder="비밀번호를 입력하십시오" class="register_forms_password">
            <i style="cursor: pointer;" class="layui-icon layui-icon-eye-invisible toggle-password"
              id="toggleRegisterPassword"></i>
            <span></span>
          </div>
          <div class="login_forms forms_code1">
            <input type="text" placeholder="그래픽 검증 코드를 입력하십시오"
              class="register_forms_captcha">
            <img src="" alt="그래픽 검증 코드를 입력하십시오" class="register-js-refresh-captcha" id="register_captcha">
            <span></span>
          </div>
          <div class="login_forms">
            <input type="text" class="verify-code-input" placeholder="확인 코드를 입력하십시오">
            <button id="verifyCodeBtn" class="verify-code-btn" data-text="확인 코드를 가져옵니다">확인 코드를 가져옵니다</button>
            <span></span>
          </div>
          <a href="javascript:;" role="button" aria-label="가입하십시오" class="login_button" id="register_button">가입하십시오</a>
        </div>
      </div>

    </div>
  </div>
</div>
<script src="https://accounts.google.com/gsi/client" async defer></script>
<script>
  $(document).ready(function () {
    LoginRegister.init({
      selectors: {
        email: {
          login: '.login_forms_email',
          register: '.register_forms_email'
        },
        password: {
          login: '.login_forms_password',
          register: '.register_forms_password'
        },
        captcha: {
          login: '.login_forms_captcha',
          register: '.register_forms_captcha',
          verify: '.verify-code-input'
        },
        buttons: {
          login: '#login_button',
          register: '#register_button',
          verifyCode: '#verifyCodeBtn'
        },
        tabs: {
          login: '.login_tab_top1a',
          register: '.login_tab_top2a',
          close: '.login_tab_top2 a'
        }
      },
      messages: {
        email: "이메일 형식이 잘못되었습니다",
        password: {
          empty: "비밀번호를 입력하십시오",
          invalid: "비밀번호는 6-18 자이어야하며 문자와 숫자가 모두 포함되어 있습니다."
        },
        captcha: "그래픽 검증 코드를 입력하십시오",
        verifyCode: "확인 코드를 입력하십시오",
        operationInProgress: "진행중인 운영 중, 기다려주세요",
        unexpectedError: "예상치 못한 오류가 발생했습니다"
      },
      urls: {
        login: "/ko/account/dologin.html",
        register: "/ko/account/register.html",
        getMailSign: "/ko/account/getMailSign",
        sendMail: "/ko/account/registerSendMail.html",
        redirctUrl:'pc'
      }
    });
  });
  function initializeGoogleSignIn() {
    if (typeof google === 'undefined' || !google.accounts) {
      setTimeout(initializeGoogleSignIn, 100);
     
      return;
    }

    google.accounts.id.initialize({
      client_id: "294584378011-s53466qiuig7d30tcqrpjv1ue3ni2gun.apps.googleusercontent.com",
      callback: handlePCCredentialResponse,
      auto_select: false,
      locale: 'ko',
      
    });
    
    google.accounts.id.renderButton(
      document.getElementById("g_id_signin"),
      {
        theme: "outline",
        size: "large",
        type: "standard",
        shape: "rectangular",
        logo_alignment: "left",
        text: "signin_with",
        width: 400,
        locale: 'ko',
      }
    );
    
  }
  document.addEventListener('DOMContentLoaded', initializeGoogleSignIn);
</script>
  <!-- Google tag (gtag.js) -->
  <script  async src="https://www.googletagmanager.com/gtag/js?id=G-LN407DS0B4"></script>
  <script>
    window.dataLayer = window.dataLayer || [];
    function gtag(){dataLayer.push(arguments);}
    gtag('js', new Date());
  
    gtag('config', 'G-LN407DS0B4');
  </script>
  <script src="/kukukuwl.js"   type="text/javascript"></script>
 <a href="javascript:void(0);" class="totop" role="button" aria-label="위로 돌아갑니다"><img src="/assets/images/totop.png" alt="" /></a>
        <script>
            layui.use(function () {
                var element = layui.element;
                element.tab({
                    headerElem: "#skilldetailsR1s_header>button",
                    bodyElem: "#skilldetailsR1s_body>div",
                });
            });
            function initSkillCloneCopy() {
                $(document)
                    .off("click.skillCloneCopy")
                    .on("click.skillCloneCopy", ".skill_clone .skill_clone_copy", function (e) {
                        e.preventDefault();

                        var $btn = $(this);
                        var $img = $btn.find("img");

                        var text = $.trim($btn.siblings("p").text());

                        var $temp = $("<textarea>");
                        $("body").append($temp);
                        $temp.val(text).select();

                        try {
                            document.execCommand("copy");

                            // 切换成功图标
                            $img.attr("src", "/assets/images/prompt_word2RMs_p_btn_ok.png");
                            $btn.addClass("active");
                            // 清除上一次定时器
                            clearTimeout($btn.data("copyTimer"));

                            // 3秒后恢复原图
                            var timer = setTimeout(function () {
                                $img.attr("src", "/assets/images/prompt_word2RMs_p_btn.png");
                                $btn.removeClass("active");
                            }, 3000);

                            $btn.data("copyTimer", timer);
                        } catch (err) {
                            alert("复制失败");
                        }

                        $temp.remove();
                    });
            }

            function initSkilldetailsFixed() {
                var $box = $(".skilldetailsR1");
                if (!$box.length) {
                    return;
                }
                var fixedTop = 20;
                var topOffset = $box.offset().top;
                var boxHeight = $box.outerHeight();
                var $placeholder = $("<div></div>").height(boxHeight).hide();
                $box.before($placeholder);
                function handleFixed() {
                    if ($(window).width() <= 1024) {
                        $placeholder.hide();
                        $box.css({
                            position: "",
                            top: "",
                            width: "",
                            zIndex: "",
                        });
                        return;
                    }
                    var scrollTop = $(window).scrollTop();
                    if (scrollTop >= topOffset - fixedTop) {
                        $placeholder.show();
                        $box.css({
                            position: "fixed",
                            top: fixedTop + "px",
                            width: $placeholder.width() + "px",
                            zIndex: 100,
                        });
                    } else {
                        $placeholder.hide();
                        $box.css({
                            position: "",
                            top: "",
                            width: "",
                            zIndex: "",
                        });
                    }
                }
                $(window).on("scroll.skilldetailsFixed resize.skilldetailsFixed", handleFixed);
                handleFixed();
            }
            function initSkilldetailsExpand() {
                $(".skilldetailsL_p").each(function () {
                    var $item = $(this);

                    $item.find(".skilldetailsL_p_expand").text($item.hasClass("active") ? "...모든 것을 확장하십시오" : "숨겨진");
                });

                $(document)
                    .off("click.skilldetailsExpand")
                    .on("click.skilldetailsExpand", ".skilldetailsL_p_expand", function (e) {
                        e.preventDefault();

                        var $parent = $(this).closest(".skilldetailsL_p");

                        if ($parent.hasClass("active")) {
                            $parent.removeClass("active");
                            $(this).text("숨겨진");
                        } else {
                            $parent.addClass("active");
                            $(this).text("...모든 것을 확장하십시오");
                        }
                    });
            }

            function checkFollow() {
                let dataSources = [];
                $('button.skill_datas').each(function () {
                    let source = $(this).data('source');
                    if (source) {
                        dataSources.push(String(source).trim());
                    }
                });
                dataSources = [...new Set(dataSources)];
                if (dataSources.length === 0) {
                    return;
                }
                $.post('/api/user/FindSkillFollow', {
                    source: dataSources
                }, function (res) {
                    if (res.code == 1 && res.data.length > 0) {
                        res.data.forEach(function (id) {
                            $('button.skill_datas[data-source="' + id + '"]').addClass('active');
                        });
                    }
                }, 'json');
            }
            $(function () {
                checkFollow();
                initSkillCloneCopy();
                initSkilldetailsFixed();
                initSkilldetailsExpand();
            });
            $(document).on('click', 'button.skill_datas', function (e) {
                e.preventDefault();
                const that = $(this);
                let source = that.data('source');
                if (!source || source === undefined || !CommonUtils.checkLogin()) return false;
                layer.load(2, {
                    shade: [0.3, "#000"],
                    time: 0,
                });
                var path = "/user/followSkill";
                var realPath = CommonUtils.getRealPath(path);
                $.post(realPath, { source: source }, function (result) {
                    layer.closeAll();
                    CommonUtils.showMsg(result.msg, result.code);
                    if (result.code == 1) {
                        var values = result.data.data_source;
                        var count = result.data.count;
                        var collected = result.data.collected;
                        var elements = $(".collectNums_" + values);
                        if (elements.length > 0) {
                            elements.each(function () {
                                $(this).parents('button').toggleClass('active', collected);
                                $(this).text(count);
                            });
                        }
                    }
                })
            })

            $(document).on('click', '.skill_downloadzip', function (e) {
                e.preventDefault();
                const url = $(this).data("source");
                if (!url) return;
                window.open("/api/index/download_zip?source=" + encodeURIComponent(url), "_blank");
            })

        </script>
    </body>

</html>