# F6-L1 Local Snapshot Spec (Promoted)

**Extracted from:** `2026-04-25-dogfood-feedback.md` F6 §"L1 — 로컬 원자 스냅샷"
**Plan:** `docs/superpowers/plans/2026-04-26-f6-l1-local-snapshot.md`
**Status:** 🚀 promoted — implemented 2026-04-26

## 결정 (mini-brainstorm 결과)

| 결정 항목 | 값 | 근거 |
|----------|-----|------|
| 백업 위치 | `<profileDir>/backups/` | 프로필 단위 묶음, 코드 단순. 외부 디렉터리/사용자 지정 경로는 후속. |
| 파일명 | `inkling-YYYY-MM-DD.sqlite` (KST 날짜) | 인간 가독 + 정렬 친화 |
| 마커 | `<profileDir>/backups/.last-snapshot` (ISO 날짜 본문) | 같은 날 중복 백업 방지 |
| 트리거 | `app.whenReady` 시 1회 + `before-quit` 1회 + 트레이 "지금 백업" | 슬라이스 §3 외부 dep 없이 만족 |
| 보존 | 14 daily + 4 weekly (월요일, anchor + 4 prior = 최대 5 Mondays) + 6 monthly (1일) | 사용자 결정. plan 산문은 "4 weekly" 였으나 plan 테스트 케이스가 5 Mondays 를 요구 → 테스트 우선 채택. |
| 원자성 | tmp + rename + 실패 시 tmp 정리 | 파셜 파일 방지, 코드 review I1 반영 |

## 범위 (PR 안에 포함됨)

- `src/main/services/backupRotation.ts` (pure GFS function)
- `src/main/services/BackupService.ts` (snapshot + rotate + runDaily + lastSnapshotAt)
- `src/main/index.ts` 수정 (whenReady wiring + before-quit hook 통합 + createTray 콜백 추가)
- `src/main/tray.ts` 수정 (지금 백업 메뉴)
- `tests/unit/backupRotation.test.ts` (10 단위 테스트)
- `tests/unit/BackupService.test.ts` (14 단위 테스트)

## 후속 (별 spec 또는 후속 항목 후보)

- 외부 디렉터리 백업 (예: OneDrive 폴더 지정)
- 미디어 포함 백업
- 암호화 (SQLCipher / age)
- 백업 무결성 검증 (PRAGMA integrity_check)
- F6-L2 git sync 와 연결 (백업 디렉터리도 sync 대상에 포함할지)
- KST 헬퍼 추출 (현재 ContinuityService + BackupService + recoveryToast 3개 인라인 — 다음 consumer 시 추출)
- WAL 모드 source DB 통합 검증 테스트
- runDaily 마커의 read-then-write race 보호 (현재 단일 사용자라 사실상 무시 가능)
- 시작 시점 `*.sqlite.tmp` orphan sweep — Windows 강제 종료(`session-end`) 가 `db.backup()` 중간에 들어올 때 잔존 가능. `parseBackupFilename` 이 `.tmp` 를 거부하므로 rotation 에 영향 0 이지만 디스크 누수 차원
- `rotate()` 부분 실패 허용 — `unlink` 한 파일이 antivirus 등으로 잠긴 경우 현재는 전체 abort. 파일별 try/catch + `partial_rotation` 로깅 권장
- `before-quit` hook 이 `whenReady()` 안에 있어서 whenReady 도달 전 quit 시 미설치 — 보통은 OK (백업할 DB 자체가 없는 시점) 지만 코멘트 권장
- **F1 마이그레이션 전 강제 스냅샷** — `openDb()` 가 `runMigrations()` 를 호출 후 `BackupService` 가 인스턴스화되므로 v2 마이그레이션 결함 시 첫 실행 직전 상태 회수 불가. F1 (Due Date) PR 시 마이그레이션 직전 스냅샷 단계 추가 권장
