> 🟢 **역사 보존 (해결 완료 2026-04-26)** — worktree 자동 생성·Junction 체계 폐기로 본 패턴 구조 차단. 본 메모리는 조직 학습 자산으로 보존.

---
name: C34 memory sync 덮어쓰기 사고 — post-commit hook이 최신 Edit 덮어씀
description: 2026-04-19 본 세션 12차 commit 직후 feedback 파일 Edit 내용이 post-commit sync로 덮어씌워진 구조적 결함. D안 집행으로 sync_memory_central_to_repo.sh에 mtime 비교 추가하여 레포 최신본 보호. C34-16 Write 경로 혼용 금지 규약의 정확한 실증
type: feedback
---

# C34 memory sync 덮어쓰기 사고 — 레포 최신본 보호 강화

## 실증 (2026-04-19)

본 세션 12차 commit(`1b409a0`) 직후 현상 발견:
- `git show 1b409a0 -- memory/org/feedback_pm_warning_ignored_pattern.md`: **Edit 내용 정상 포함** (2차 실증 사례·BYPASS 사용법 섹션)
- `cat memory/org/feedback_pm_warning_ignored_pattern.md` (working tree): **Edit 내용 부재** (구 버전 상태)
- `git status --short`: `M memory/org/feedback_pm_warning_ignored_pattern.md` (HEAD ≠ working tree)
- 중앙 저장소 `$HOME/.claude/nerdnavis-memory/feedback_pm_warning_ignored_pattern.md`: 구 버전

즉 **commit에는 Edit 포함되었으나 commit 직후 post-commit hook이 덮어씀**.

## 근본 원인

### 시퀀스 재구성

1. **본 세션 Edit**: `E:\BurningTimesAi\.claude\worktrees\tender-liskov-844a72\memory\org\feedback_...` (worktree 절대 경로)
2. 해당 경로는 **junction 경유 아님** — 중앙 저장소 `$HOME/.claude/nerdnavis-memory/`에 동기화 안 됨
3. 결과: 레포(worktree 실체) = Edit 반영 / 중앙 = 구 버전
4. `git commit` 성공 (HEAD에 Edit 포함)
5. **post-commit hook이 `sync_memory_central_to_repo.sh` 실행**
6. 스크립트 구 버전 로직: `diff`만 비교, 다르면 중앙 → 레포 덮어쓰기 (mtime 무시)
7. **중앙(구 버전) → 레포(Edit 최신) 덮어쓰기 → Edit 내용 working tree 소실**

### C34-16 Write 경로 혼용 금지 규약 위반 실증

C34-16은 다음 3옵션 중 택1, **혼용 금지**:
- (A) worktree 절대 경로 직접 지정 (junction 경유 회피, 본 worktree git status 즉시 반영)
- (B) user memory 경로 `$HOME/.claude/projects/*/memory/...` (junction 경유로 중앙 자동 반영)
- **혼용 금지**

본 세션은 혼용:
- worktree 절대 경로 Edit (본 사건 대상 — 중앙 미반영)
- user memory 경로 Write (junction 경유 — 중앙 자동 반영)

혼용 결과: **일부 파일은 중앙 반영되고 일부는 안 됨 → sync 스크립트가 반영 안 된 파일을 구 버전으로 판정 → 덮어씌움**.

### sync_memory_central_to_repo.sh 구조 결함

기존 로직:
```bash
if [ ! -f "$dst" ] || ! diff -q "$f" "$dst" >/dev/null 2>&1; then
  cp "$f" "$dst"  # 무조건 덮어쓰기
fi
```

**mtime 비교 없음** — 레포가 중앙보다 최신이어도 덮어씀. 단방향 덮어쓰기의 위험.

## 영향

### 본 사건
- **HEAD에 Edit 보존** → git checkout으로 복원 가능 (복구 완료)
- **소실 없음** (다행히 같은 세션 내 즉시 발견)

### 잠재 영향
- PM이 다음 commit 전 복원 안 하면 → **새 commit에 구 버전 stage → Edit 내용 영구 소실**
- 반복 발생 시 **조직 기억 누적 소실** 가능성 (C32 대화로그 기록 의무 위반 도화선)

## 해결 (2026-04-19 D안 집행)

### sync_memory_central_to_repo.sh 개선 (mtime 보호)

```bash
# 레포가 중앙보다 최신이면 덮어쓰기 차단
if [ -f "$dst" ] && [ "$dst" -nt "$f" ]; then
  echo "⚠️ [Memory Sync] 레포본이 중앙보다 최신 — 덮어쓰기 스킵" >&2
  SKIPPED_PROTECT=$((SKIPPED_PROTECT + 1))
  continue
fi
```

효과: 본 사건 같은 **레포 최신 + 중앙 구 버전** 케이스 시 덮어쓰기 스킵 + 경고 출력.

### 동시 집행
- C34-16 본문 보강 (sync 덮어쓰기 보호 조항 명시)
- 본 feedback 영구 기록
- MEMORY.md 인덱스 추가

## 재발 방지 체크 (세션 리더 의무)

- **Edit 경로 일관 유지**: 같은 세션 내 worktree 절대 경로 vs user memory 경로 **혼용 금지** (C34-16)
- **post-commit 경고 출력 주시**: `⚠️ [Memory Sync] 레포본이 중앙보다 최신` 메시지 등장 시 Edit 경로 점검
- **commit 직후 `git status` 확인**: `M memory/org/...` 잔존 시 sync 덮어쓰기 징후 — git checkout으로 즉시 복원
- **수동 sync 명령**: 의심 시 `bash scripts/sync_memory_repo_to_central.sh` 실행으로 중앙 최신화

## 본 세션 C34 관련 구조적 결함 3연속 패턴

| # | 결함 | 근본 원인 | 해결 |
|---|------|---------|------|
| 1 | Sentinel marker 손실 (2026-04-19 20:55) | git 외 cleanup 작업 | 안건 A — UserPromptSubmit hook 편입 |
| 2 | BYPASS 환경변수 hook 미전달 (21:11·21:12) | Claude Code hook subprocess 환경변수 전달 안 됨 | 옵션 A — 파일 기반 BYPASS 전환 |
| 3 | **Memory sync 덮어쓰기** (21:32, 본 사건) | sync 스크립트 mtime 미비교 + C34-16 혼용 | **D안 — mtime 보호 + C34-16 보강 + 본 feedback** |

3건 모두 **C34 hook·sync 체계의 실행 가정과 실제 Claude Code 실행 모델 불일치**. 향후 hook·자동화 설계 시 다음 원칙 준수:
- **실제 실행 환경에서 반드시 실증 테스트** (환경변수·프로세스·mtime 순서)
- **덮어쓰기 방향 스크립트는 반드시 mtime 보호**
- **경로 혼용 시 sync 동작 예측 불가 — 경로 일관 규율 강제**

## 연관

- **C34-16** Write 경로 혼용 금지 (본 사건 정확한 실증)
- **C34-9** hook 3층 구조 (sync 스크립트가 Layer 2·3 인프라)
- **C32** 대화로그 기록 의무 (조직 기억 보존 헌법급)
- **C3·C5** 이슈 은폐 금지·정직성 (본 사건 자진 보고)
- `feedback_central_sentinel_loss.md` (본 세션 C34 결함 1)
- `feedback_pm_warning_ignored_pattern.md` (본 세션 C34 결함 2: BYPASS 환경변수)
- `scripts/sync_memory_central_to_repo.sh` (D안 개선 대상)
- `scripts/sync_memory_repo_to_central.sh` (반대 방향, 레포 SOT 정책 유지)

## 교훈

**"단방향 sync는 언제든 최신본을 구 버전으로 덮어쓸 수 있다."** sync 스크립트 설계 시 **mtime·hash·소스·상태 중 최소 하나는 반드시 비교 조건**으로 사용. 덮어쓰기 방향에는 **반드시 보호 조건** 설정. 특히 commit 직후 hook처럼 자동 실행되는 sync는 PM 인지 없이 최신 Edit을 소실시킬 수 있으므로 **최신본 보호가 기본**.

차기 프로젝트·차기 sync 스크립트 설계 시 본 원칙 필수 적용.
