• v0.3.0 a54f134343

    altair823 released this 2026-05-09 19:25:30 +00:00 | 100 commits to main since this release

    v0.3.0 — Cut E (양방향 git sync + Configure UI + Conflict resolution)

    semver MINOR — Major 영역 진입. 기존 push-only SyncService → 양방향 6단계 흐름 + Configure UI + Conflict resolution. F21 옵션 A+B+C 적용 ('both' choice 만 v0.3.1+ deferred).

    주요 변경

    • F21-A 자동 rebase: SyncService.sync() 양방향 6단계 = (1) local export → (2) addAll + commit (변경 시) → (3) fetch → (4) rebase onto origin/main → (5) re-import (applySyncFromDir → upsertFromSync) → (6) push. 첫 push (empty remote) 시 GitClient.refExists('origin/main') guard 로 rebase skip — "invalid upstream" 에러 회피.
    • F21-B Configure UI: SettingsPage 의 신규 "동기화 저장소" SyncSection. URL 입력 + 저장 (settings persist + git init + remote add) + 연결 테스트 (git ls-remote) + 자동 sync 토글 + interval input (default 30분, min 5).
    • F21-C Conflict UI: rebase 실패 시 git diff --name-only --diff-filter=U + git show :2:<path> (ours) / :3:<path> (theirs) 로 localText/remoteText 채우고 abort. ConflictModal 에서 path 별 "내 것 사용" / "원격 사용" 선택 → resolveConflictgit checkout --ours/--theirs + rebase --continue + push.
    • NoteRepository.upsertFromSync (sync 전용 3 분기): id 없음 → INSERT (capture revision + tags FTS sync) / id 있음 + raw_text 동일 + source 더 최신 → metadata 갱신 (title_edited_by_user CASE 보존) / id 있음 + raw_text 다름 + source 더 최신 → updateRawText 호출 (Cut C single write path → user revision INSERT chain). source 옛 → skip. importNote fork-on-id-collision 회피.
    • frontmatter 5 필드 round-trip: Cut B (status) + Cut C (note_revisions) 도입 시 export 누락된 5 필드 (status / status_changed_at / move_reason / due_date / due_date_source) 를 Cut E 에서 추가. ExportNote / ParsedNote interface + composeFrontmatter / parseExportNote / noteToExportNote 모두 갱신 — F5 round-trip 도 동시에 fix.
    • SyncTimer: settings.sync_interval_min 마다 자동 syncSvc.sync(). settings 변경 시 IPC handler 가 await timer.reconfigure() (stop + start). interval mode 실패는 silent. before-quit 훅에서 stop.

    테스트 / 빌드

    • 단위: 608 → 679 pass (+71, 1 pre-existing flake SyncService.test.ts timing test 와 무관):
      • GitClient 5 (fetch / rebaseOnto / rebaseAbort / hasUncommittedChanges / listConflicts)
      • upsertFromSync 5 (3 분기 시나리오)
      • frontmatter round-trip + applySyncFromDir 18 (export 7 + import 5 + applySyncFromDir 6)
      • SyncService bidirectional 5 (happy / commit-skip / conflict / fetch-fail / not-configured)
      • resolveConflict 4 (local / remote / checkout-fail / continue-fail)
      • SettingsService sync 6 (3 필드 × get/set + interval validation)
      • sync IPC 17 (5 sync 채널 + 2 settings setter)
      • SyncSection 4 / ConflictModal 3 / SyncTimer 5
    • typecheck: 0 errors
    • e2e: 세션 내 미수행 — UI 변경 = SettingsPage SyncSection + ConflictModal — capture/onboarding/banner flow 무관. 다기기 (Mac + Windows) dogfood 필수 — sync 가치는 다기기에서만.
    • 산출물: Inkling-Setup-0.3.0.exe (Windows NSIS x64, signed)
    • (macOS dmg / Linux AppImage + deb 차후 추가)

    Schema 변경

    m007 (Cut D) 이후 신규 schema 변경 없음. 양방향 sync 는 m007 이전 schema 호환 — note_revisions (m006) 와 notes_fts (m007) 모두 sync source = 동일 schema 양 기기.

    메모리 정책 갱신 (Cut E 머지 후 적용)

    • 양방향 sync source = path identifier (UUID 아님) — F5 export filename slug, git checkout --ours/--theirs 가 path 받음
    • upsertFromSync 가 sync 전용 in-place update path (importNote 의 fork-on-id-collision 회피)
    • Single write path 강제 4-path: note_tags INSERT (updateAiResult / updateUserAiFields / importNote / upsertFromSync), note_revisions INSERT (create / updateRawText / importNote / upsertFromSync) 모두 helper 경유 — final review 단계 grep 검증
    • timestamp 단조 가정 (NTP) — upsertFromSyncupdatedAt lexicographic compare. v0.3.1+ 에서 vector clock / revision id 검토 가능
    • 'sync' edited_by enum 미도입 — sync 가 적용한 raw_text 변경도 'user' revision (의미상 사용자 의도 전파). m008 회피
    • 명명 정확성 = UX 정직성 패턴 (Cut E 신규): 데이터 식별자가 실제 의미와 일치해야 UI 가 정직 (Cut E final review 의 noteId → path rename 사례)

    다음 (Cut F)

    v0.3.1 Cut F: F24 멀티모달 vision. 다기기 dogfood ≥1주 soak 후 진입.

    Risk 잔재

    • 다기기 환경 필수: Mac + Windows 양 기기 sync 환경에서만 dogfood 가치 검증
    • 인증 외부 의존: SSH key / git credential helper. Configure UI 의 "연결 테스트" 가 첫 진입점
    • timestamp 단조 가정: NTP 부재 + 양 기기 시계 어긋남 시 잘못된 skip/update risk
    • silent interval-mode failures: SyncTimer 가 sync 실패 silent — last-error surface 미구현
    • conflict 'both' deferred: v0.3.1+ revision branch 분기 정책과 함께
    • e2e 본 세션 미수행: 머지 후 main 에서 검증 권장
    Downloads