ai-rules handbook Sync Operations Guide

Sync Operations Guide

``` profiles/{project}.yaml ↓ 블록 조립 (core/ + extensions/) ↓ 어댑터 변환 (claude-code, cursor, plain, governance, tooling) ↓ output/{project}/ ← 중

guide docs/guide/SYNC_OPERATIONS.md

ai-rules sync 파이프라인의 동작 방식, 파일 쓰기 전략, 프로젝트별 커스터마이징 방법을 설명한다.


1. Sync Pipeline 개요

profiles/{project}.yaml
    ↓
블록 조립 (core/ + extensions/)
    ↓
어댑터 변환 (claude-code, cursor, plain, governance, tooling)
    ↓
output/{project}/   ← 중간 산출물
    ↓  --apply
target_path/        ← 실제 프로젝트 디렉토리

실행 명령

# 특정 프로젝트 sync (output/ 생성만)
node scripts/sync.mjs --project {name}

# 특정 프로젝트 sync + 타겟에 적용
node scripts/sync.mjs --project {name} --apply

# 전체 프로젝트 sync + 적용
node scripts/sync.mjs --apply --yes

# dry-run (실제 쓰기 없이 확인)
node scripts/sync.mjs --project {name} --apply --dry-run

2. Write Strategy

sync는 파일을 타겟 프로젝트에 복사할 때 3가지 전략을 사용한다.

전략 동작 용도
overwrite (기본) 항상 덮어쓴다. 내용이 동일하면 건너뛴다 (skip-if-identical). hooks, agents, CLAUDE.md, 설정 yaml
ifNotExists 파일이 이미 있으면 건너뛴다. 최초 1회만 생성. commitlint.config.mjs, .husky/*, .lintstagedrc.json
mergeJson 기존 JSON에 새 내용을 deep merge한다. hooks/permissions 병합. .claude/settings.json

파일별 전략 매핑

Governance 어댑터 (governance.enabled: true 일 때)

파일 전략 설명
.ai-governance/config.yaml overwrite 거버넌스 설정
.ai-governance/agents.yaml overwrite 에이전트 설정
.ai-governance/thresholds.yaml overwrite 임계값 설정
.ai-governance/safety-manifest.yaml overwrite 안전 매니페스트
.claude/hooks/guard-branch.sh overwrite 보호 브랜치 커밋/PR 차단
.claude/hooks/guard-reversibility.sh overwrite R2 비가역 작업 종합 차단
.claude/hooks/confirm-capture.sh overwrite CONFIRM 토큰 캡처
.claude/hooks/guard-freeze.sh overwrite 디렉토리 스코프 잠금
.claude/.gitignore overwrite .claude/ 내부 제외 규칙
.claude/settings.json mergeJson hook 등록 (기존 설정과 병합)
.github/workflows/cross-verify.yml overwrite CI 워크플로

Tooling 어댑터 (tooling.enabled: true 일 때)

파일 전략 설명
commitlint.config.mjs ifNotExists 커밋 메시지 검증 설정
.husky/pre-commit ifNotExists pre-commit hook
.husky/commit-msg ifNotExists commit-msg hook
.lintstagedrc.json ifNotExists lint-staged 설정
.claude/hooks/guard-secrets.sh overwrite 시크릿 탐지
.claude/hooks/guard-push-force.sh overwrite push --force 차단
.claude/hooks/guard-destructive-db.sh overwrite DB 파괴적 명령 차단
.claude/settings.json mergeJson hook 등록 (governance와 병합)

에이전트 (agents.enabled: true 일 때)

파일 전략 설명
.claude/agents/{name}.md overwrite 에이전트 정의 (base + ext 합성)

스킬 (profile.skills에 정의된 경우)

파일 전략 설명
.claude/commands/{name}.md overwrite 슬래시 명령 스킬

3. .claude/ 디렉토리 구조

sync가 생성하는 .claude/ 내부 파일과 git 커밋 여부:

경로 커밋 여부 설명
.claude/hooks/*.sh 커밋 팀 전체 공유 — 보호 브랜치, 시크릿 탐지 등
.claude/settings.json 커밋 hook 등록, 권한 설정
.claude/agents/*.md 커밋 에이전트 페르소나 정의
.claude/commands/*.md 커밋 슬래시 명령 스킬
.claude/.gitignore 커밋 아래 제외 항목 관리
.claude/confirmed-actions/ 제외 런타임 CONFIRM 토큰 (일회용)
.claude/agent-mode 제외 개발자별 에이전트 모드 설정

부모 .gitignore 주의사항

프로젝트 루트의 .gitignore.claude/ 전체를 제외하는 규칙이 있으면 위 파일들이 git에 커밋되지 않는다. sync 실행 시 이를 감지하면 경고를 출력한다:

⚠️  {path}/.gitignore에 '.claude/' 제외 규칙 감지
    hooks/settings를 git에 커밋하려면 '!.claude/' 예외를 추가하세요.

해결 방법 — 프로젝트 .gitignore에 예외 추가:

# ai-rules가 관리하는 .claude/ 파일은 커밋 허용
.claude/
!.claude/
.claude/confirmed-actions/
.claude/agent-mode

또는 .claude/ 전체 제외 대신 개별 항목만 제외:

.claude/confirmed-actions/
.claude/agent-mode

4. 프로젝트별 커스터마이징

4.1 프로파일 설정 (profiles/{project}.yaml)

project: my-project
target_path: /path/to/project

# 도구별 활성화
tools:
  claude-code:
    enabled: true
    output: CLAUDE.md
  cursor:
    enabled: false

# 안전 수준
safety:
  preset: moderate  # strict | moderate | permissive

# core 블록 선택 (순서 = 출력 순서)
core:
  - 01-git
  - 02-code
  - 03-security

# 확장 블록
extensions:
  - my-custom-extension

# 에이전트
agents:
  enabled: true
  include:
    - planner
    - builder
    - reviewer

# 인라인 오버라이드 (3줄 이하)
overrides:
  01-git: |
    추가 규칙: 이 프로젝트에서는 ...

4.2 Extension 블록 (extensions/)

core 규칙에 추가할 프로젝트별 규칙. extensions/{name}.md 파일로 작성.

4.3 에이전트 확장 (agents-ext/{project}/)

base 에이전트에 프로젝트 전용 내용 추가:

# profile에서
agents:
  include:
    - builder:
        extensions: [builder]  # agents-ext/{project}/builder.md 내용이 끝에 추가

4.4 어떤 파일을 직접 수정해도 되는가?

파일 직접 수정 이유
commitlint.config.mjs 안전 ifNotExists — 다음 sync에서 건너뜀
.husky/* 안전 ifNotExists — 다음 sync에서 건너뜀
.lintstagedrc.json 안전 ifNotExists — 다음 sync에서 건너뜀
.claude/settings.json ⚠️ 주의 mergeJson — 수동 추가 항목은 보존되지만, hook 구조가 병합됨
.claude/hooks/*.sh 비권장 overwrite — 다음 sync에서 덮어씌워짐
.claude/agents/*.md 비권장 overwrite — 다음 sync에서 덮어씌워짐
CLAUDE.md 비권장 overwrite — 다음 sync에서 덮어씌워짐

hooks를 수정하고 싶다면?governance/templates/hooks/ 원본 템플릿을 수정한 후 sync 실행. 모든 프로젝트에 일괄 적용된다.

특정 프로젝트만 다른 규칙을 적용하고 싶다면? → 프로파일의 overrides: 또는 extensions/에 프로젝트별 규칙 추가.


5. Stale 파일 정리

sync는 더 이상 생성되지 않는 파일을 자동 삭제한다.

정리 대상 디렉토리:

  • .cursor/rules/ — cursor 도구가 활성화된 경우
  • .claude/agents/ — agents가 활성화된 경우

동작: 현재 sync에서 생성하지 않은 파일이 해당 디렉토리에 존재하면 삭제한다.

🗑️ → .claude/agents/old-agent.md (stale 파일 삭제)

주의: 수동으로 .claude/agents/에 추가한 파일도 삭제 대상이다. 프로젝트별 에이전트는 agents-ext/{project}/에 작성하고 프로파일에서 참조해야 한다.


6. mergeJson 병합 규칙

.claude/settings.json은 governance와 tooling 양쪽에서 생성한다. 두 소스를 deep merge하며, 기존 파일과도 병합한다.

hooks 병합

기존 settings.json의 hooks:
  PreToolUse:
    - matcher: Bash → [guard-branch.sh]

incoming hooks:
  PreToolUse:
    - matcher: Bash → [guard-secrets.sh]

결과:
  PreToolUse:
    - matcher: Bash → [guard-branch.sh, guard-secrets.sh]  (union)

같은 matcher의 command는 union으로 합쳐진다 (중복 제거).

permissions.allow 병합

기존 + incoming의 합집합. 기존 항목이 삭제되지 않는다.


7. FAQ

Q: sync를 실행하면 내가 수정한 CLAUDE.md가 날아가나요? A: 네. CLAUDE.md는 overwrite 전략이므로 매 sync마다 재생성됩니다. 프로젝트별 규칙은 extensions/나 프로파일 overrides:로 추가하세요.

Q: hooks를 실행 불가능하게 만들고 싶어요. A: .claude/settings.json에서 해당 hook의 등록을 제거하면 됩니다. 단, mergeJson 전략이므로 다음 sync에서 다시 추가됩니다. 영구적으로 비활성화하려면 프로파일에서 governance.enabled: false 또는 tooling.enabled: false로 설정하세요.

Q: 새 프로젝트를 추가하려면? A: profiles/_default.yaml을 복사해서 profiles/{project}.yaml로 만들고, target_path와 필요한 설정을 채운 후 sync를 실행하세요.

Q: governance hooks 없이 tooling hooks만 쓸 수 있나요? A: 네. 프로파일에서 governance.enabled: false로 설정하면 governance hooks(guard-branch, guard-reversibility 등)는 생성되지 않고, tooling hooks(guard-secrets, guard-push-force 등)만 적용됩니다.

Q: sync 후 output/ 디렉토리의 파일을 직접 수정해도 되나요? A: 아니요. output/은 중간 산출물이므로 다음 sync에서 항상 재생성됩니다. 수정은 반드시 소스(core/, extensions/, templates/)에서 하세요.