## 2026-05-30 — Vault 강화: 주석 오버레이 Undo/Redo·선택 도구 + 그래프 태그 색상·.vaultignore 필터

### 배경

Vault 프리뷰의 낙서(annotation) 오버레이가 한 번 그으면 되돌릴 방법이 없었고, 오버레이가 켜져 있는 동안에는 밑의 콘텐츠를 클릭할 수 없었다. 또 그래프 뷰는 프로젝트의 모든 마크다운 파일을 구분 없이 같은 색으로 보여줬고, 보고 싶지 않은 파일을 숨길 방법도 없었다. 이 네 가지를 한 번에 해결했다.

### 주요 변경

#### 1. 주석 오버레이 Undo/Redo (`f0f778a`)

- **`AnnotationOverlay.tsx`**: `past` / `future` 스택으로 history 관리. 펜/형광펜 한 stroke, 지우개 한 drag-gesture(pointerdown→pointerup), 모두 지우기가 각각 하나의 undo 스텝이 되도록 처리. 지우개는 첫 erase 변화 시점의 strokes를 ref에 snapshot으로 잡아 pointerup 시 한 번에 커밋 → drag 중 여러 stroke를 지워도 전체가 한 스텝. `undo()` / `redo()` imperative 메소드와 `onStateChange` prop으로 `canUndo` / `canRedo`를 외부에 알림.
- **`PreviewPanel.tsx`**: 툴바에 Undo/Redo 버튼(상태에 따라 disable), annotate 모드 활성 시 `Ctrl+Z` / `Ctrl+Y` / `Ctrl+Shift+Z` 단축키 처리.
- **i18n**: `annotate.undo` / `annotate.redo` 한·영.

#### 2. 주석 오버레이 선택(select) 도구 (`e482e74`)

- **`AnnotationOverlay.tsx`**: `AnnotationTool` 타입에 `'select'` 추가. select 모드일 때는 그리기/지우기를 스킵하고 **오버레이의 pointer events를 끔** → 밑의 콘텐츠(링크 클릭, 텍스트 선택 등)가 그대로 동작.
- **`PreviewPanel.tsx`**: `MousePointer2` 툴바 버튼 추가. annotate 모드 진입 시 기본 도구를 select로 설정해 실수로 바로 그어지지 않게 함.
- **i18n**: `annotate.select` 한·영.

#### 3. 그래프 노드 태그 기반 색상 (`b3579a9`)

- **`VaultGraph.tsx`**: 각 파일의 (알파벳순) 첫 번째 태그를 키로 결정론적 HSL 해싱해 노드 색을 자동 부여. 선택/검색 매치 색상은 태그 색보다 우선. 좌하단에 현재 사용 중인 태그→색 매핑을 보여주는 범례 패널 추가.
- 검색 입력·범례 텍스트가 `text-warm-50`(배경색 CSS 변수에 매핑돼 어두운 그래프 배경에서 안 보이던 문제)을 쓰던 것을 `text-warm-800`으로 교체해 가시성 fix.

#### 4. `.vaultignore` 필터링 (`b3579a9`)

- **`file-scanner.ts`**: `ignore` 패키지를 `scanVault`에 연결. 프로젝트 루트의 `.vaultignore`를 읽어 `DEFAULT_EXCLUDES`와 함께 적용하고, walk 중 디렉터리를 가지치기. gitignore 문법 전체 지원.
- **서버 라우트**: `GET /api/projects/:id/vault/ignore`(없으면 빈 문자열) / `PUT .../vault/ignore`(루트에 `.vaultignore` 기록) 추가.
- **`VaultIgnoreModal.tsx`** + **`SidebarRail.tsx`**: 좌측 사이드바 레일의 새 Settings 액션 슬롯에서 모달을 띄워 `.vaultignore`를 편집. 저장 시 그래프를 즉시 리로드.
- 의존성: `ignore` 패키지 추가(`package.json`).

### 수정된 주요 파일

| 파일 | 변경 내용 |
|------|----------|
| `src/client/src/components/vault/AnnotationOverlay.tsx` | past/future history + undo/redo + select 도구(pointer-events off) |
| `src/client/src/components/vault/PreviewPanel.tsx` | Undo/Redo·Select 툴바 버튼 + 단축키 |
| `src/client/src/components/VaultGraph.tsx` | 태그 기반 HSL 노드 색상 + 범례 패널 + 텍스트 가시성 fix |
| `src/client/src/components/vault/VaultIgnoreModal.tsx` | `.vaultignore` 편집 모달 (신규) |
| `src/client/src/components/vault/SidebarRail.tsx` | Settings 액션 슬롯 (모달 트리거) |
| `src/client/src/components/vault/VaultLayout.tsx` | 모달 배선 + 저장 후 그래프 리로드 |
| `src/server/routes/vault.ts` | `GET`/`PUT /vault/ignore` 라우트 |
| `src/server/services/file-scanner.ts` | `ignore` 패키지로 `.vaultignore` 적용 |
| `src/client/src/api/vault.ts` | `getVaultIgnore` / `saveVaultIgnore` |

### 아키텍처 결정

1. **지우개는 drag-gesture 단위로 한 undo 스텝**: pointerdown 시 strokes를 snapshot하고 pointerup에 한 번 커밋. drag 중 여러 stroke가 지워져도 사용자 입장에선 "한 번 지운 것"이므로 한 번에 되돌아감.
2. **select 도구는 오버레이 pointer-events를 끄는 방식**: 별도 hit-test 없이 오버레이를 투명 통과시켜 밑 콘텐츠를 그대로 인터랙티브하게 둠. annotate 진입 기본값을 select로 둬 실수 낙서 방지.
3. **노드 색은 결정론적 HSL 해시**: 첫 태그 문자열만으로 색이 정해지므로 리로드해도 같은 태그는 같은 색. 선택/검색 상태 색이 우선해 시각 피드백 충돌 없음.
4. **`.vaultignore`는 gitignore 문법 재사용**: 별도 패턴 언어를 만들지 않고 `ignore` 패키지로 위임. `DEFAULT_EXCLUDES`(하드코딩 제외)와 사용자 패턴을 함께 적용.
