개요
내부 아키텍처 위키를 구축합니다: 서브시스템별로 하나의 마크다운 페이지 (아키텍처, 런타임 흐름, PR로 추적 가능한 주요 결정, 소스 앵커)로 구성되며, 허브 README.md와 기계적 검사 스크립트로 연결됩니다. 두 가지 모드가 있습니다: generate는 위키를 처음부터 구축하고; refresh는 각 페이지의 소스 앵커를 통해 불일치(drift)를 감지하여 변경된 부분만 업데이트합니다. 아래에서 <skill>/는 이 스킬 자체의 디렉토리(이 파일, references/, assets/가 있는 곳)를 의미하며, 대상 저장소의 위키 출력 디렉토리인 <dir>과는 구별됩니다. 다른 작업을 수행하기 전에, 활성 모드의 번호가 매겨진 각 단계(G1–G7 또는 R1–R3)에 대해 하나의 항목으로 구성된 할 일 목록을 만드세요. 단계 0에서 어떤 모드가 활성인지 결정한 후에 수행합니다.
단계 0 — 인수 구문 분석 및 모드 감지
$ARGUMENTS가 refresh로 시작하면 → refresh 모드; 그 외의 모든 경우(비어 있는 경우 포함)는 → generate 모드입니다. 나머지 인수에서 다음을 추출하고 기록합니다: --dry-run (refresh 전용), --pages a,b (명명된 페이지만 새로고침으로 제한), --dir <path> (위키 디렉토리, 기본값 wiki). refresh 모드에서 <dir>/README.md가 존재하지 않으면 중단하고 사용자에게 먼저 generate를 실행하라고 알립니다 — 새로고침할 항목이 없습니다.
Generate G1 — 사전 점검
확인: 현재 디렉토리가 git 저장소 안에 있는지; Agent 도구를 사용할 수 있는지. 작업 트리가 더티(dirty)하면 AskUserQuestion을 사용하여 진행하기 전에 확인을 받으세요 — 절대 가정하지 마십시오. 기능 확인: gh auth status는 이번 실행에서 PR 본문 소싱 계층(바인딩 규칙 §2)이 존재하는지 여부를 설정합니다. 저장소 루트에서 디자인 문서 디렉토리(docs/, doc/, design/, adr/, rfcs/)를 검색합니다 — 존재 여부만 확인; 어떤 디렉토리를 채굴할지는 G2에서 확인합니다. 작업 브랜치(기본값 docs/internal-wiki, 브랜치 이름은 G2에서 확인)를 생성하고 git rev-parse HEAD > .generate-wiki/branch-base를 기록합니다 (G6에서 전체 브랜치 diff를 위해 이 값을 읽습니다). .generate-wiki/가 대상 저장소의 .gitignore에 나열되어 있는지 확인하고, 그렇지 않으면 추가합니다 — 이 실행 상태 디렉토리(원장, 브리프, 보고서, diff 패키지)는 절대 커밋되어서는 안 됩니다.
Generate G2 — 인터뷰
질문하기 전에, 페이지 세트 제안을 자동으로 도출합니다: 워크스페이스/패키지 매니페스트에서 서브시스템을 열거하거나, 생태계가 매니페스트를 노출하지 않는 경우 최상위 소스 디렉토리에서 열거하고, 서브시스템당 하나의 페이지를 '다루는 항목' 메모와 함께 제안합니다. 그런 다음 정확히 한 번의 AskUserQuestion 라운드를 실행하며, 최대 3개의 질문을 합니다:
- 제안된 페이지 세트 승인 또는 조정 (병합, 분할, 추가, 삭제).
- 출력 디렉토리(
<dir>) 및 브랜치 이름 확인 — 사용자가 G1의 기본값과 다른 이름을 선택하면git branch -m <new-name>으로 브랜치 이름을 변경합니다. - 소싱 입력 확인: 채굴할 디자인 문서 디렉토리(그리고 추적되는지 여부), 그리고 PR 기록이 여기서 의미 있는지.
이 라운드 이후 실행은 완전히 자율적입니다 — generate 모드에서는 더 이상 질문하지 않습니다.
Generate G3 — 스캐폴드
세 가지 에셋을 대상 저장소에 구체화합니다:
assets/TEMPLATE.md→<dir>/TEMPLATE.md, 있는 그대로 복사.assets/hub-template.md→<dir>/README.md, 네 개의{{...}}토큰을 모두 채웁니다:{{PROJECT_NAME}};{{SYSTEM_DESCRIPTION}}(저장소 탐색을 통해 초안 작성된 두 문단);{{CRATE_DAG}}— 실제 매니페스트 종속성에서 파생된 mermaidgraph TD엣지, 절대 만들어 내지 않음; 노드 ID는references/binding-rules.md의 Mermaid 예약어를 피해야 함 (크레인이graph,end등으로 단축되면 렌더링이 깨짐 — ID 이름을 바꾸고 레이블에 크레인 이름 유지);{{PAGE_INDEX}}—| 페이지 | 다루는 항목 | 요약 |테이블, 승인된 페이지당 한 행, 임시 요약 포함 (G5에서 최종 확정).assets/check-wiki.sh.tmpl→scripts/check-wiki.sh모드 0755 (또는 저장소에scripts/규칙이 없으면<dir>/check-wiki.sh), 다음 명령어로 렌더링:여기서sed -e "s|{{CANONICAL_PAGES}}|$PAGES|g" -e "s|{{WIKI_DIR}}|$DIR|g" <skill>/assets/check-wiki.sh.tmpl > scripts/check-wiki.sh$PAGES는 공백으로 구분된 승인된 페이지 파일 이름이고$DIR은<dir>입니다. 이 문서의 나머지 부분에서는 이 렌더링된 스크립트의 경로를$CHECK로 호출합니다 —$CHECK [page.md ...]로 호출 (인수 없음은 README/TEMPLATE를 제외한 모든 페이지를 검사, 명명된 인수는 해당 페이지만 검사).
커밋 하나: 스캐폴드.
Generate G4 — 페이지별 루프
순차적 — 한 번에 한 페이지씩, 절대 병렬로 처리하지 않음: 각 페이지의 커밋이 다음 페이지의 git log 컨텍스트가 되며, 병렬 처리는 두 페이지가 동일한 교차 링크나 용어 선택에서 충돌할 위험이 있습니다. 승인된 각 페이지 <name> (파일 <name>.md)에 대해:
a. BRIEF_PATH = .generate-wiki/page-<name>-brief.md에서 브리프 탐색 및 작성: 소스 테이블 (포함된 디렉토리/모듈, 채굴할 디자인 문서, git log --oneline -- <dirs>의 PR/커밋 및 사용 가능한 경우 gh pr list), 최소 흐름, 최소 결정. 브리프는 최소 요구 사항이지 상한선이 아닙니다.
b. BASE=$(git rev-parse HEAD)를 기록합니다.
c. references/page-implementer.md에서 중간 계층 모델(Claude Code에서는 sonnet) 로 implementer 서브에이전트를 디스패치하고, 일곱 개의 슬롯을 모두 채웁니다: <<BRIEF_PATH>> = (a)의 브리프; <<WIKI_DIR>> = <dir>; <<PAGE_FILE>> = <name>.md; <<STYLE_REF>> = 이전 페이지의 파일 이름, 또는 첫 번째 페이지의 경우 리터럴 문자열 "none — you are writing the first page"; <<CHECK_CMD>> = $CHECK <name>.md; <<BINDING_RULES>> = references/binding-rules.md의 전체 내용을 그대로; <<REPORT_PATH>> = .generate-wiki/report-<name>.md.
d. diff 패키지 생성: git diff $BASE..HEAD > .generate-wiki/review-<name>.diff — 이 경로는 DIFF_PACKAGE_PATH입니다.
e. references/page-reviewer.md에서 중간 계층 모델(Claude Code에서는 sonnet) 로 reviewer 서브에이전트를 디스패치하고, 여섯 개의 슬롯을 모두 채웁니다: <<BRIEF_PATH>> = (a)와 동일한 브리프; <<REPORT_PATH>> = (c)의 implementer 보고서; <<DIFF_PACKAGE_PATH>> = (d)의 diff; <<BINDING_RULES>> = references/binding-rules.md 그대로; <<MIN_COVERAGE>> = 브리프의 최소 흐름 및 결정, 인라인으로 재진술; <<CHECK_CMD>> = (c)와 동일한 값.
f. 중요/심각한 발견 사항 → 완전한 발견 사항 목록과 바인딩 규칙을 사용하여 중간 계층 모델(Claude Code에서는 sonnet) 에서 하나의 fix 서브에이전트를 디스패치하고, 동일한 REPORT_PATH에 추가; git diff $BASE..HEAD > .generate-wiki/review-<name>.diff로 diff 패키지 재생성; 그런 다음 동일한 슬롯으로 reviewer를 다시 디스패치합니다. 사소한 사항 → 최종 검토 분류를 위해 원장에 기록; 지금은 수정하지 않습니다.
g. .generate-wiki/progress.md에 한 줄 추가: Page <name>: complete (commits X..Y, review <outcome>); minors: ...; findings: ....
충돌 복구: 호출 시 먼저 .generate-wiki/progress.md를 읽습니다. 완료로 표시된 페이지는 건너뜁니다 — 원장에 완료된 페이지를 절대 재생성하지 마십시오. 커밋되지 않은 초안이 있는 페이지(git status에 페이지 파일이 표시됨)는 재개됩니다: implementer 절차의 D단계(검사)부터 다시 디스패치합니다.
Generate G5 — 교차 링크 패스
모든 페이지가 구현 및 검토된 후, references/cross-linker.md에서 중간 계층 모델(Claude Code에서는 sonnet) 로 한 번의 서브에이전트를 디스패치하고, 네 개의 슬롯을 모두 채웁니다: <<WIKI_DIR>> = <dir>; <<CHECK_CMD>> = $CHECK (페이지 인수 없음, 모든 페이지 검사); <<BINDING_RULES>> = references/binding-rules.md 그대로; <<REPORT_PATH>> = .generate-wiki/cross-link-report.md. 그런 다음 오케스트레이터가 직접 확인합니다 — 이 패스에는 reviewer 디스패치가 없습니다: 모든 페이지에 대해 $CHECK 통과; 새로운 대칭 링크 그래프 스캔 (서브에이전트의 보고서를 재사용하지 않고 다시 실행); 디자인 문서 경로가 잘못된 곳이 없는지 확인; 패스에서 도입된 새 문장을 소스와 대조하여 샘플 점검.
Generate G6 — 최종 검토
전체 브랜치 diff 패키지 구축: git diff <branch-base>..HEAD > .generate-wiki/final-diff.diff (<branch-base>는 G1에서 기록된 .generate-wiki/branch-base의 내용). .generate-wiki/triage.md 작성: 원장에 기록된 모든 연기된 사소한 사항과 모든 실제 프로젝트 발견 사항. references/final-reviewer.md에서 가장 강력한 사용 가능 모델로 하나의 서브에이전트를 디스패치하고, 다섯 개의 슬롯을 모두 채웁니다: <<WIKI_DIR>> = <dir>; <<CHECK_CMD>> = $CHECK; <<DIFF_PACKAGE_PATH>> = .generate-wiki/final-diff.diff; <<LEDGER_PATH>> = .generate-wiki/progress.md; <<TRIAGE_PATH>> = .generate-wiki/triage.md. 이는 읽기 전용 검토입니다 — 작업 트리를 건드리면 안 됩니다. 발견 사항에 대해 중간 계층 모델(Claude Code에서는 sonnet) 에서 하나의 fix 서브에이전트를 디스패치하여 전체 목록을 처리합니다(오케스트레이터는 대신 한 문장짜리 수정을 직접 적용할 수 있음). 수정 사항이 적용된 후 모든 게이트를 다시 실행합니다 — 모든 페이지에 대해 $CHECK 통과, 대칭 링크 그래프 스캔, 디자인 문서 경로가 잘못된 곳이 없는지 확인.
Generate G7 — 핸드오프
모든 게이트를 마지막으로 한 번 더 실행합니다. 사용자에게 요약: 구축된 페이지, 각 페이지의 검토 결과, 그리고 — 부차적인 것이 아닌 일급 출력으로 — 실행 중 발견된 실제 프로젝트 발견 사항 목록 (죽은 코드, 연결되지 않은 기능, 오래된 주석, 사양 불일치)과 후속 티켓 작성을 제안합니다. 브랜치를 푸시하고 PR을 열 것을 제안하지만, 사용자의 명시적 확인 없이는 절대 실행하지 않습니다.
Refresh R1 — 불일치 감지
사전 점검: 깨끗한 작업 트리 필요 — 더티하면 AskUserQuestion을 사용하여 R3 편집 전에 확인; refresh 커밋은 현재 브랜치에 도착하며, 새 브랜치가 아닙니다.
<dir>의 각 페이지에 대해 README.md와 TEMPLATE.md를 제외하고(또는 --pages 하위 집합이 제공된 경우 해당 페이지만): 소스 앵커 섹션을 구문 분석하여 파일 경로 목록으로 만듭니다. LAST=$(git log -1 --format=%H -- <dir>/<page>). git log --oneline $LAST.. -- <anchor paths>가 비어 있지 않으면 → drifted입니다. 디스크에 더 이상 존재하지 않는 앵커 경로 → hard drift, 별도로 표시됩니다. 경로로 구문 분석할 수 없는 앵커 글머리 기호 → un-refreshable: R2에서 해당 페이지의 구문 분석 문제를 보고하고, 무엇을 의미하는지 추측하지 마십시오.
Refresh R2 — 보고 / 건조 실행 중지
불일치 테이블을 출력합니다: 페이지 → 불일치 커밋(제목 포함) → 하드 드리프트 앵커 → 새로고침 불가 메모. --dry-run은 여기서 실행을 종료합니다 — 작업 트리는 건드리지 않으며, 커밋되지 않습니다.
Refresh R3 — 업데이트 루프
여기서 $CHECK는 구체화된 검사 스크립트입니다 — scripts/check-wiki.sh 또는 <dir>/check-wiki.sh 중 존재하는 것. 각 불일치 페이지에 대해(불일치하지 않은 페이지는 완전히 건너뜀), 다음과 같은 두 가지 변경 사항으로 동일한 G4 메커니즘(단계 a–g, 동일한 슬롯 채우기, 동일한 reviewer 게이트)을 실행합니다: 브리프는 새로고침 브리프입니다 — 처음부터 새로 만드는 소스 테이블 대신 R1의 불일치 증거(페이지의 앵커를 건드린 커밋/PR, 가능한 경우 gh pr view 본문 포함); implementer는 바인딩 규칙 위에 적용되는 새로고침별 규칙을 따릅니다: 실제로 변경된 것만 업데이트; 새 Key Decision 항목은 최신순으로 추가됨; 기존 결정 항목을 절대 다시 쓰거나 삭제하지 않음 — 이는 기록임; 이동된 경로에 대해 소스 앵커 업데이트; 제거된 기능은 기록을 삭제하는 대신 정직하게 문서화. 링크 세트가 변경된 페이지만 교차 링크 검사(G5, 기계적 확인만)를 실행합니다. 새로고침된 페이지당 하나의 커밋.
모델 선택
페이지 implementer, 페이지 reviewer, fix 서브에이전트 및 교차 링커는 중간 계층 모델(Claude Code에서는 sonnet) 로 디스패치됩니다. 전체 위키 최종 검토(G6)는 가장 강력한 사용 가능 모델로 디스패치됩니다. 오케스트레이터는 자신의 세션 모델을 디스패치에 암시적으로 상속하지 않습니다 — 위의 모든 Agent 호출은 모델을 명시적으로 지정합니다.
오류 처리
- 서브에이전트가 작업 중 중단됨: 작업은 복구 가능 — 커밋된 페이지는 git에 있으며
.generate-wiki/progress.md가 이름을 지정; 커밋되지 않은 초안은git status를 통해 발견되어 재개됨. 원장에 완료로 표시된 페이지를 절대 재생성하지 마십시오. gh없음 / 인증되지 않음: 바인딩 규칙 §2에 따라 소싱이 저하됨 (디자인 문서 → 커밋 고고학 → 대체 표현); PR 본문 없이 생성 진행.- 페이지 작업 내 검사 스크립트 실패: implementer가 자체 D단계(검사)에서 커밋 전에 수정; 오케스트레이터에 도달하는 실패(G4 단계 f가 이미 한 번 실행됨)는 충돌이 아닌 수정 주기 트리거입니다.
- 사전 점검 시 더티 트리: 묻고 가정하지 마십시오 (G1).
- 새로고침 중 잘못된 형식의 소스 앵커: 새로고침 불가능으로 표시 (R1); 의도된 경로를 추측하지 마십시오.