worktree + develop 자동 병합
`scripts/sync.mjs --apply` 는 각 target 프로젝트의 working tree 에 규칙 파일을 직접 쓴다. 이 때문에 다음 문제가 있었다.
changes docs/changes/2026-04-15-sync-auto-merge.md
Context
scripts/sync.mjs --apply 는 각 target 프로젝트의 working tree 에 규칙 파일을
직접 쓴다. 이 때문에 다음 문제가 있었다.
- 작업 중 오염 — target 프로젝트에서 feature 브랜치 작업 중이면 sync 결과물이 그 working tree 에 섞여 들어간다. 사용자가 stash 를 잊고 커밋하면 엉뚱한 변경이 commit 에 포함된다.
- 이력 부재 — 언제 어떤 규칙이 배포됐는지 git 이력에 남지 않는다
(
sync-status.json은 JSON 메타만). - 병합 마찰 — 수동 PR 로 바꾸면 "열어만 두고 까먹는" 현실 문제가 발생한다.
Decision
ai-rules 가 자기 자신에게 sync 할 때 (self-sync) 한정으로 아래 흐름을 적용한다.
.claude/sync-tool-allowlist에scripts/sync.mjs가 등록되어 있으면 예외 경로 활성화- target 의
.git/worktrees-sync/{timestamp}에 worktree 생성 (본체 working tree 미변경) - worktree 안에서 파일 쓰기 +
add+commit(chore(sync): apply ai-rules@{sha}) - 본체
develop에ff-only병합 +push - push 실패 시 로컬
develop을 병합 전 SHA 로reset --hard로 롤백 - 병합·push 실패는 feature 브랜치를 살려두고
gh pr create로 PR 폴백
적용 범위는 ai-rules 프로젝트 자기 자신 에 한정한다.
다른 target 프로젝트 (projectName !== 'ai-rules') 는 기존 직접 복사 경로 유지.
Rationale
- sync 는 결정론적 스크립트 — LLM 추론이 개입하지 않는다. "빌드 산출물 배포" 범주로 취급할 수 있다.
- develop 직접 병합은 일반 에이전트 금지 대상 — 하지만 화이트리스트
(
.claude/sync-tool-allowlist) 로 예외를 명시적으로 허용하면, 규칙 체계를 깨지 않고 결정론적 배포만 자동화할 수 있다. - 왜 PR 폴백이 아니라 자동 병합이 기본인가 — PR 방식은 "열어만 두고 까먹는" 현실 문제가 있다. 규칙 파일의 성격상 빠르게 반영돼야 하며, 충돌은 드물다. 충돌이 있을 때만 PR 폴백으로 전환한다.
Scope
- 포함: ai-rules → ai-rules 자기 자신 sync (self-sync)
- 제외: 다른 target 프로젝트 sync, 다른 배포 스크립트, LLM 추론이 개입하는 도구
다른 프로젝트에 워크트리 모드를 확장할지는 별도 PR 에서 판단 한다. 프로젝트마다 develop 운영 방식, push 권한, hook 구성이 달라 일괄 적용이 적절하지 않다.
Safeguards
- 화이트리스트 게이트 —
.claude/sync-tool-allowlist없거나 호출자 미등록 시 worktree 모드 진입 자체를 하지 않는다 (= 기존 직접 복사 경로). - preflight 검증 — git repo / origin /
develop브랜치 / fetch 성공 모두 통과해야 worktree 모드 진입.main/master만 있는 프로젝트는 거부. - 본체 dirty 거부 — target 본체 working tree 가 dirty 면 develop checkout 불가로 보고 중단한다 (사용자가 직접 처리할 시점).
- ff-only 제한 —
merge --ff-only만 허용. rebase·--no-ff자동 시도 없음. - push 실패 롤백 — push 가 rejected 되면 로컬 develop 을 병합 전 SHA 로
reset --hard한다. - PR 폴백 — 어느 단계든 실패하면 feature 브랜치(
sync/ai-rules-{timestamp}) 를 살려두고gh pr create로 PR 생성. gh 가 없으면 브랜치 이름을 로그로 남김. - cleanup 보장 — worktree 제거는 try/finally 에서 수행.
git worktree remove --force실패 시 디렉토리 직접 삭제 후worktree prune. - 원래 브랜치 복원 — 본체 checkout 을 develop 으로 옮겼을 때, 작업 완료 후
finally에서 원래 브랜치로 되돌린다.
Alternatives Considered
- B안 — PR 까지만 생성 (자동 병합 없음): 안전하지만 "PR 열어만 두고 까먹는" 현실 문제가 해결되지 않는다. 규칙 파일이 늦게 반영되면 애초에 이 도구의 존재 이유가 옅어진다. 기각.
- C안 — 모든 target 에 일괄 적용: target 마다 develop 정책, hook, CI 가 다르다. 한 번에 확장하면 실패 지점이 너무 많다. 기각 (향후 개별 PR 로 평가).
- D안 — 현 직접 복사 유지: 본 문서의 Context 에서 나열한 세 가지 문제가 해결되지 않는다. 기각.