Files
inkling/CHANGELOG.md

33 KiB
Raw Blame History

Changelog

본 파일은 Inkling 의 버전별 사용자 영향 변경 사항을 기록한다. 형식은 Keep a Changelog 를 느슨하게 따른다.

[0.4.0] — 2026-05-15 (force re-tag, dogfood UX 2회 보완)

추가 dogfood UX 2회차 (2026-05-15 force re-tag)

dogfood 2일차 피드백 묶음. force re-tag 로 같은 v0.4.0 에 추가.

  • AI 정리하기 (default notebook batch 분류) — 사이드바 default notebook 선택 시 main 영역 상단에 "🪄 AI 정리하기" 버튼. 클릭 → AI 가 default 의 active 노트들을 한 prompt 에 묶어 분석 → BatchMoveModal 에 noteId 별 추천 notebook + checkbox → 사용자 confirm 후 일괄 moveNote. top N=50 cap, 한국어 prompt, hallucinated notebook 이름은 null 로 coerce.
  • 노트북 순서 변경notebooks.sort_order 컬럼 (m009 마이그레이션) + NotebookList row hover 시 ↑↓ 버튼. 인접 sort_order swap. drag-drop 은 v0.5+ 후보.
  • 이동 UX 정리 — NoteCard 의 notebook chip 을 tag 영역 → footer 의 "이동" 버튼 옆으로 이동. tag(키워드) / notebook(컨텍스트) 의미 분리. dropdown 도 위쪽으로 펼침.

추가 dogfood UX 1회차 (2026-05-15)

  • NotebookChip 시각 강화 — 청색 배경 + 📓 아이콘 + ▾ caret + dropdown 헤더 "이동할 노트북". chip 클릭 시 다른 notebook 선택 dropdown 이 보이는 affordance 명확화. 다른 notebook 없으면 disabled.
  • 헤더 좌측 ☰ 햄버거 버튼 — 마우스 클릭으로 사이드바 토글 (Cmd/Ctrl+B 단축키와 동일).
  • 사이드바 default visible — 새 사용자가 처음부터 사이드바 보이게 (settings.getSidebarVisible default false → true). 기존 사용자가 명시적으로 false 저장했다면 그 값 그대로.
  • inboxWindow 기본 크기 확장 — 900×720 → 1200×800. 사이드바 240px 가 default 가시화되므로 main 영역 확보.

게이트 (2회차 후)

  • 단위 877 PASS
  • typecheck 0 errors

원본 release (2026-05-15)

Notebooks + Lifecycle Simplification. 19일 dogfood 데이터 (archived 0건 / mlx-ops tag 가 사실상 컨텍스트 그룹 역할) 가 묶음 변경의 근거.

추가

  • Notebook 카테고리 — 좌측 사이드바 (Cmd+B / Ctrl+B 토글), 색 + count badge. notebooks 테이블 + notes.notebook_id FK RESTRICT. m008 마이그레이션이 default "기본" notebook 자동 생성 후 모든 기존 노트 배치.
  • AI 자동 fit 매칭 — 매 capture 시 AI 가 prompt 의 notebooks 목록을 보고 best-fit 자동 배치 (응답의 notebook_match 필드). NoteCard 의 chip 으로 1-click 변경 가능.
  • Promotion 제안 — 같은 tag 가 3건 이상 default notebook 에 누적되면 "새 notebook 으로 분리?" banner 표시. 24h snooze + 영구 dismiss 지원 (settings 의 promotion_snoozed_until_ms / promotion_dismissed_tags 영속화).
  • 사이드바 UX — NotebookCreateModal (이름 + 6색 palette + 중복 검증), NotebookList (선택 highlight + count), 모달/사이드바 toggle 단축키.
  • 검색 scope 토글 — "이 노트북" / "모든 노트북" dropdown.

변경

  • lifecycle 3분기archived status 제거. 헤더 탭이 Inbox / 완료 / 휴지통 (3탭). MoveStatusModal 의 "보관" 옵션도 제거. classifyStatus 의 AI 응답이 archived 면 completed 로 coerce. ImportService 가 backward compat 위해 archived 노트 import 시 completed 로 변환.
  • NoteRepository.findExpiredCandidates 의 scope 가 inbox 만 → notebook 별 scope (Task 4 의 countByStatus 옵션 등 통합 효과).
  • selectedNotebookId 변경 시 list / counts 자동 refresh.

게이트

  • 단위 테스트 851 PASS (m008 마이그레이션 / NotebookRepository / AI prompt + schema / AiWorker matching / store + settings 영속화 / Sidebar / NotebookCreateModal / PromotionBanner / NoteCard chip / SearchBox scope / archived 제거 회귀 가드).
  • typecheck 0 errors.
  • 신규 npm dependency 0.

업그레이드

v0.3.14 인스톨러 위에 v0.4.0 인스톨러를 같은 위치에 실행하면 in-place 업그레이드. m008 마이그레이션이 첫 launch 시 자동 실행되어 default notebook "기본" 생성 + 모든 기존 노트 배치.

[0.3.14] — 2026-05-12 (force re-tag: 2026-05-14, 추가 dogfood fixes 7건)

추가 dogfood fixes (2026-05-14 force re-tag)

force re-tag 로 같은 v0.3.14 안에 묶인 후속 변경. 새 minor 안 늘리고 동일 release notes 확장.

  • fix(capture): QuickCapture blur-on-hide 제거. 다른 창 클릭해도 ESC / Cmd+Enter 까지 창 유지. alwaysOnTop + screen-saver level 로 다른 앱 위에 떠 있음.
  • chore(ux): macOS 사용자 위해 Cmd 키 hint 안내. Inbox empty state 와 QuickCapture 하단 hint 가 platform-aware 로 분기 — Mac 에선 Cmd+Shift+J / Cmd+Enter.
  • fix(macos): hidden autostart dock indicator + autostart mismatch false positive. ① LoginItems --hidden spawn 시 NSPanel 만 떠 있어 dock 점 안 보이던 문제 — inboxWindow 를 hidden 으로 미리 create + showInactive → hide trick 으로 NSApp register. ② SettingsPage 의 자동실행 mismatch 경고가 macOS 13+ SMAppService 한계로 false positive 떠 있던 문제 — willLaunch 신호는 win32 에서만 mismatch 판정에 사용.
  • feat(notes): 원문 편집/이력 복원 시 AI 재처리. NoteRepository.markAiPendingForReprocess 신설 — done/failed/pending 노트를 pending reset + pending_jobs 재투입. disabled 는 사용자 의도 존중 no-op. NoteCard.saveRaw 가 optimistic 으로 aiStatus='pending' 표시. updateAiResult 의 user-edit 가드로 사용자가 직접 편집한 필드는 보존.
  • feat(expiry): 마감 알림 inbox 제한 + 오늘 당일 포함 + 헤딩/라벨/메모 바로가기.findExpiredCandidatesdue_date <= today + status='active' 로 변경, 완료/보관 노트는 제외. 정렬도 due_date DESC 로 오늘 → 어제 순. ② ExpiryBanner 헤딩 분리 카운트 "오늘 마감 X · 지난 Y", 노트 라벨 [오늘] / [N일 지남]. ③ 노트 제목 클릭 → note-{id} smooth scroll.
  • fix(sync): manifest.exported_at 제거 — no-op push 회피. 노트 변경 0건이어도 매 sync 마다 timestamp 1줄 commit + push 가 쌓이던 문제. composeManifest 에서 cosmetic 필드 제거. 이제 진짜 변경 있을 때만 commit.
  • feat(settings): SectionIntro + SyncHelpModal 풀어쓰기. 설정 페이지 6 section 상단에 1-2 문장 안내. SyncHelpModal 의 기술 용어 (rebase, fast-forward, NTP) 를 사용자 언어로 풀어쓰기.

게이트 (추가 fix 후)

  • 단위 763 PASS
  • typecheck 0 errors

원본 release (2026-05-12)

AI 처리 fail 원인 가시화. 이전엔 ai_error 가 NoteCard tooltip (title attribute) 에만 있어 사용자가 마우스 오버해야 보이는 데다 raw 메시지만 노출 → 무엇이 fail 했는지 불명.

수정

  • NoteCard failed 노트에 "원인 보기" 접힘 섹션 (P1). <details> summary 클릭하면 <pre>ai_error 전체 노출. wrap + word-break 적용. 사용자가 직접 메시지를 보고 모델/네트워크/JSON 등 fail 카테고리 진단 가능.
  • ai_error 에 reason + provider name prefix 추가. AiWorker 의 markAiFailed 시 [schema|other] local-ollama/gemma4:26b\n<원본 message> 형식. 사용자가 어느 카테고리에서, 어느 모델로 실패했는지 즉시 식별. log 의 ai.failed 에도 reason/provider 필드 함께 출력.

게이트

  • 단위 752 PASS (ai_error 포맷 변경은 test 영향 없음 — 기존 test 가 정확한 prefix 매칭 안 함)
  • typecheck 0 errors
  • 신규 npm dependency 0

사용자 안내

이미지 AI 처리가 fail 한다면 NoteCard 의 "정리 보류" 옆 "원인 보기" 클릭 → 표시되는 메시지로:

  • [timeout] ... → vision 모델 cold-start 가 5분 초과. ollama run gemma4:26b 으로 한번 warm-up 후 재시도
  • [schema] title must contain Korean characters → vision 모델이 영어 title 반환. prompt 가 한국어 강조했지만 일부 모델은 여전히 영어. gemma3:27b 등 다른 vision 모델로 대체 고려
  • [schema] unparseable response: ... → vision 모델 JSON 출력 안 따름. v0.3.12 의 loose parse 가 실패한 경우
  • [other] missing response field → Ollama 가 빈 응답 반환. 모델 자체 문제

업그레이드

v0.3.13 인스톨러 위에 v0.3.14 인스톨러를 같은 위치에 실행하면 in-place 업그레이드.

[0.3.13] — 2026-05-12

대형 vision 모델 (gemma4:26b 등) 의 cold-start timeout 으로 인한 AI 처리 실패 fix.

수정

  • Vision generate 의 timeout 확장 120s → 300s (P1). gemma4:26b (25B MoE 가중치 + vision encoder 550M) 같은 대형 vision 모델은 첫 generate 시 모델 load + 이미지 encoding 으로 60-180s 소요. 기본 120s timeout 으로 첫 호출 시 abort → fail 빈번. vision path 에 한해 Math.max(timeoutMs, 300_000) 적용 (text-only path 영향 없음).

확인: gemma4 family 는 공식 release — 26B variant 가 Text+Image 양 modality 지원 (ollama library). 본 코드의 VisionDetect 가 'gemma4' family 인식하므로 사용자가 settings → Vision 섹션에서 선택 가능.

사용자 안내

이미지 AI 처리가 여전히 실패한다면:

  1. 설정 → AI 제공자 → Vision 섹션에서 gemma4:26b (또는 vision-capable 모델) 가 선택돼있는지 확인
  2. ollama list 로 모델 실제 설치 여부 확인 (ollama pull gemma4:26b 필요)
  3. NoteCard 의 failed 노트 텍스트 위에 마우스 오버 → tooltip 의 ai_error 확인 (구체 fail mode 진단)

게이트

  • 단위 752 PASS (timeout 상수만 변경 — 회귀 없음)
  • typecheck 0 errors
  • 신규 npm dependency 0

업그레이드

v0.3.12 인스톨러 위에 v0.3.13 인스톨러를 같은 위치에 실행하면 in-place 업그레이드.

[0.3.12] — 2026-05-12

이미지 AI 처리 실패 fix. vision model 의 응답이 strict JSON 이 아닌 경우 (markdown fence / prose 섞임) 가 흔해 schema parse 단계에서 throw → ai_status='failed' 도달.

수정

  • Vision model 응답 JSON loose parse (P1). LocalOllamaProvider.generateJSON.parse 가 strict 라 vision-tuned 모델의 markdown 코드 펜스 / 앞뒤 prose 응답에서 throw. parseJsonLoose 헬퍼 추가 — 첫 { ~ 마지막 } substring 추출 fallback. 실패 시 raw response 200자 snippet 포함한 에러 throw (디버깅 가시화).
  • Vision prompt 강화 (P1). buildVisionPrompt 가 "title 한국어로 요약" 만 명시 → schema 의 KOREAN_REGEX/KEBAB_REGEX 강제와 불일치. 규칙 4건 명시: title 한국어 60자, summary 3줄, tags 영문 kebab-case 3개, due_date ISO 또는 null. "markdown 코드 펜스 금지" 명시로 JSON-only 출력 강제.

알려진 한계:

  • gemma4:26b 같이 Ollama 에 실제로 release 안 된 모델명 사용 시 healthCheck 통과해도 generate 가 unknown model 로 throw. 모델 설치 여부는 사용자가 ollama list 확인 필요.

게이트

  • 단위 750 → 752 PASS (+2: markdown fence 추출 + prose 추출)
  • typecheck 0 errors
  • 신규 npm dependency 0

업그레이드

v0.3.11 인스톨러 위에 v0.3.12 인스톨러를 같은 위치에 실행하면 in-place 업그레이드. 데이터/마이그레이션 변경 없음.

[0.3.11] — 2026-05-12

붙여넣은 이미지 / 저장된 이미지가 양쪽 창에서 표시 안 되던 CSP 누락 hotfix.

수정

  • QuickCapture: paste 이미지 thumbnail 렌더 실패. quickcapture/index.html 의 CSP 가 img-src 미지정 → default-src 'self' fallback → URL.createObjectURLblob: URL 차단. img-src 'self' data: blob: 추가.
  • Inbox: 저장된 노트 이미지 렌더 실패. inbox/index.html 의 CSP img-src 'self' data: blob: file:inkling-media: 미허용 → NoteCard<img src="inkling-media://media/..." /> 차단 (custom protocol 자체는 main 에서 등록됐지만 renderer CSP 별도). inkling-media: 추가.

v0.3.0 (Cut A 이미지 첨부) 이후 양쪽 창에서 paste/render 가 잠재적으로 깨져있던 회귀. 사용자가 dogfood 중 발견.

게이트

  • 단위 750 PASS (CSP meta tag 만 변경 — 코드 path 영향 없음)
  • typecheck 0 errors
  • 신규 npm dependency 0

업그레이드

v0.3.10 인스톨러 위에 v0.3.11 인스톨러를 같은 위치에 실행하면 in-place 업그레이드. 데이터/마이그레이션 변경 없음.

[0.3.10] — 2026-05-12

macOS fullscreen 환경에서 QuickCapture 핫키 (Cmd+Shift+J) 가 작동하지만 강제로 홈 데스크탑으로 Space 전환 후 표시되던 버그 fix.

수정

  • macOS fullscreen Space 위에 QuickCapture 표시 (P1). 기본 BrowserWindow 는 첫 생성된 Space (홈 데스크탑) 에만 표시 → 사용자가 다른 앱 fullscreen 중에 핫키 누르면 macOS 가 강제로 Space 전환 → 사용자 흐름 단절. quickCaptureWindow.ts 에 darwin 분기 추가:
    • type: 'panel' — fullscreen Space 위에 floating 가능한 macOS native panel
    • setAlwaysOnTop(true, 'screen-saver') — fullscreen app 위에 띄울 수 있는 가장 높은 level
    • setVisibleOnAllWorkspaces(true, { visibleOnFullScreen: true }) — 현재 Space (fullscreen 포함) 에 함께 표시, Space 전환 차단

Windows / Linux 동작은 변경 없음 (darwin 분기만).

게이트

  • 단위 750 PASS (변경 없음 — main window 코드는 단위 테스트 대상 아님)
  • typecheck 0 errors (src)
  • 신규 npm dependency 0
  • macOS 사용자 수동 검증 완료

업그레이드

v0.3.9 인스톨러 위에 v0.3.10 인스톨러를 같은 위치에 실행하면 in-place 업그레이드. 데이터/마이그레이션 변경 없음.

[0.3.9] — 2026-05-11

v0.3.8 audit 의 미수정 edge case 3건 완료. AI 처리 흐름의 사용자 unblock path + FTS5 query 안전성.

수정

  • ai_status='pending' 노트 cancel UI 부재 (P1). Ollama 끊김 / 무한 pending 상태에서 사용자가 빠져나오는 path 가 없었음. NoteCard 의 pending 표시 옆에 "건너뛰기" 버튼 추가 → inboxApi.cancelPending(id)repo.cancelPending: ai_status='disabled' + pending_jobs DELETE. raw_text 는 보존. pushNoteUpdated emit 으로 renderer 자동 sync.
  • ai_status='failed' 노트 per-note 재시도 UI 부재 (P2). 이전엔 FailedBanner 의 일괄 재시도만 가능. NoteCard 의 failed 표시 옆에 "재시도" 버튼 추가 → inboxApi.retryOneFailed(id)repo.retryOneFailed: failed → pending + pending_jobs INSERT + worker enqueue. pushNoteUpdated emit.
  • FTS5 query escape 불완전 (P2). sanitizeFtsQuery 의 special chars regex 가 ["*():] 만 처리 → backtick/dash/caret 미escape 로 일부 입력이 FTS5 parser throw 야기. ["*():^-]` 로 확장. 한국어 사용자가 의도 없이 입력할 가능성 높은 punctuation 까지 안전 처리.

미수정 (의도)

  • 동시 편집 race (P2). EditableField 가 이미 editing=true 중 value prop 변경을 무시하는 guard 보유. 사용자 입력은 보존됨 (last-write-wins). 추가 코드 불필요.

게이트

  • 단위 745 → 750 PASS (+5: repo retryOneFailed 2 + cancelPending 2 + FTS sanitize 1)
  • typecheck 0 errors (src)
  • 신규 npm dependency 0

업그레이드

v0.3.8 인스톨러 위에 v0.3.9 인스톨러를 같은 위치에 실행하면 in-place 업그레이드. 데이터/마이그레이션 변경 없음.

[0.3.8] — 2026-05-11

전수 audit 후 발견된 사용자 상호작용 hole 8건 일괄 hotfix. 핵심은 (1) push-based status 동기화 root fix, (2) modal Escape affordance 통일, (3) IPC 실패 resilience.

수정

  • inbox:set-status IPC 가 pushNoteUpdated emit 안 함 (root fix). 이전엔 setStatus 후 counts/list/search 가 모두 stale → 호출처마다 refreshMeta() 명시 호출이 필요했음 (v0.3.5 워크어라운드). 이제 IPC 핸들러가 repo.findById()pushNoteUpdated 호출. renderer 의 onNoteUpdated 콜백 1개 path 로 모든 status 전이가 일관 갱신.
  • upsertNote 가 current view 무시 → 잘못된 status 노트 잔류. 이전엔 trashed 외 모든 status 를 notes 에 누적 → 사용자가 inbox 에서 완료로 옮긴 노트가 list 에 잔류. v0.3.8 부터 viewStatus (inbox→active, completed→completed, archived→archived) 와 매칭되는 status 만 유지. searchResults 도 동일 패턴.
  • upsertNote 의 trash 판정을 deletedAtstatus='trashed' 로 전환. m004 이후 status 가 single source of truth, deletedAt 은 backward-compat mirror. sync conflict 후 두 컬럼 불일치 가능성 대비.
  • restoreNote 가 status 도 'active' 로 갱신. 이전엔 deletedAt: null 만 clear → upsertNote 가 status='trashed' 그대로 라 여전히 trashNotes 에 잔류.
  • OnboardingWizard close path 부재. IPC 실패 시 무한 wizard 잠금 → try/catch + setBusy/error state + "지금 건너뛰기" 버튼 + Escape 추가. 첫 launch 사용자 막힘 회피.
  • Modal Escape key dismiss 통일. MoveStatusModal / RevisionHistoryModal / ConflictModal / SyncHelpModal / OnboardingWizard 모두 keydown listener 추가. MoveStatusModal 은 overlay 클릭 close 도 추가 (다른 modal 들은 이미 외부 클릭 지원).
  • store.ts async 함수 error-resilient. loadInitial / loadByView / searchNotes / loadReview / refreshMeta 가 IPC throw 시 try/catch 로 감싸 무한 loading / stale data 회피. loadInitial 은 catch 시 loading: false, loadByView 는 빈 list, searchNotes 는 빈 결과, loadReview 는 빈 aggregate 로 graceful fallback.

갱신

  • NoteCard 의 명시적 refreshMeta 호출 보존 — onNoteUpdated path 가 이미 refreshMeta 호출하므로 redundant 지만 backup 으로 유지 (2번 fetch 만 발생, 무해).

게이트

  • 단위 739 → 745 PASS (+6: view-aware upsertNote 3 + setStatus push emit 1 + Modal Escape 1 + Modal overlay 클릭 1)
  • typecheck 0 errors (src)
  • 신규 npm dependency 0

업그레이드

v0.3.7 인스톨러 위에 v0.3.8 인스톨러를 같은 위치에 실행하면 in-place 업그레이드. 데이터/마이그레이션 변경 없음.

미수정 (낮은 우선순위 / 별도 작업)

  • ai_status='pending' 노트 cancel UI (P1, 별도 spec 필요)
  • ai_status='failed' 노트 per-note 재시도 UI (P2)
  • FTS5 query escape (P2, 확인 필요)
  • 동시 편집 race condition (P2)

[0.3.7] — 2026-05-11

MoveStatusModal 의 button hardcode 로 인해 완료/보관/휴지통 노트가 inbox 로 돌아올 수 없던 버그 fix. v0.2.9 Cut B 부터 존재한 잠재 결함 (dropdown 의 possibleTargets 필터가 modal 까지 흐르지 못함).

수정

  • 완료/보관/휴지통 노트의 Inbox 복원 path 부재. MoveStatusModal완료/보관/휴지통 3 button hardcode 라 currentStatus 외 3 status 만 동적으로 노출해야 한다는 의도가 누락. currentStatus: NoteStatus prop 추가 + 4 status 중 current 제외 동적 render. NoteCard 가 local.status 전달.
  • status label 일관성statusLabel('active') 가 '활성' 이었으나 헤더 탭 표기는 'Inbox'. modal button + AI 추천 텍스트 양쪽 모두 'Inbox' 로 통일.

게이트

  • 단위 736 → 739 PASS (+3: completed/archived/trashed currentStatus button list 검증)
  • typecheck 0 errors (src)
  • 신규 npm dependency 0

업그레이드

v0.3.6 인스톨러 위에 v0.3.7 인스톨러를 같은 위치에 실행하면 in-place 업그레이드. 데이터/마이그레이션 변경 없음.

[0.3.6] — 2026-05-11

v0.3.5 의 이동 dropdown 단순화가 사용자 의도와 어긋난 점 정정. 이동 modal (사유 + AI 자동 분류 + 수동 status 선택) 은 보존해야 하는 핵심 UX 였음.

수정

  • 이동 dropdown → 단일 "이동" 버튼 + MoveStatusModal 복원. v0.3.5 에서 dropdown 항목 클릭 = 즉시 setStatus 로 단순화한 path 를 되돌림. 사용자 의도는 dropdown 의 목적지 중복 (modal 도 목적지 묻기) 제거였지, modal 자체 제거가 아니었음. 단일 "이동" 버튼 → modal → 사유 입력 + AI 자동 분류 + 수동 status 선택 path 로 통일.
  • MoveStatusModal.tsx + 테스트 6 case 복원 — v0.3.5 에서 dead code 로 판단해 삭제했으나 다시 mount 됨. statusLabel 헬퍼 위치는 modal 내부로 회귀 (orphan statusLabel.ts 제거).
  • 이동 후 refreshMeta() 호출 유지 — v0.3.5 D1 fix (setStatus IPC 가 pushNoteUpdated emit 안 함 → 헤더 탭 count stale) 는 modal onMoved callback path 에서도 동일하게 트리거.

게이트

  • 단위 734 → 736 PASS (NoteCard 이동 case 3 → 2 + MoveStatusModal 6 복원)
  • typecheck 0 errors (src)
  • 신규 npm dependency 0

업그레이드

v0.3.5 인스톨러 위에 v0.3.6 인스톨러를 같은 위치에 실행하면 in-place 업그레이드. 데이터/마이그레이션 변경 없음.

[0.3.5] — 2026-05-11

v0.3.4 까지 누적된 dogfood UX 결함 7건 hotfix. 사용자가 막혔던 inbox/회고/이동 3건 + 그 부류의 동반 갭 4건. 데이터/마이그레이션 변경 없음 (스키마 v8 그대로).

수정

  • Inbox 탭 진입 실패: 다른 보관함에서 inbox 로 못 돌아옴. setView('inbox') 가 reload 를 호출 안 해서 notes state 가 이전 view 의 status 로 stale. loadByView 시그니처에 'inbox' → 'active' 매핑 추가 + setView 의 reload 분기에 inbox 포함.
  • 회고 view 탈출 불가. ReviewView 가 App 의 헤더를 우회 (early return) 해서 사용자가 뒤로 갈 길이 없던 문제. ← 돌아가기 버튼 추가 — 클릭 시 setView('inbox').
  • 이동 dropdown 의 modal 중복 질문. dropdown 에서 "완료로 이동" 선택해도 MoveStatusModal 이 떠서 목적지를 재확인. dropdown 클릭 = inboxApi.setStatus(id, target, null) 즉시 호출로 단순화. modal path 자체 제거 (MoveStatusModal.tsx + 동반 테스트 삭제, statusLabel 헬퍼는 별도 statusLabel.ts 로 분리).
  • 이동 후 헤더 탭 count stale. setStatus IPC 가 pushNoteUpdated emit 을 안 해서 refreshMeta 가 트리거되지 않던 잠재 버그. dropdown 이동 path 끝에 refreshMeta() 명시 호출 추가.
  • View 전환 시 검색/태그 필터 잔류. setViewsearchResults/searchQuery/tagFilter 를 reset 안 해서 이전 view 의 필터가 완료/보관/휴지통/회고에 잘못 적용. 한 번에 reset.
  • Inbox 첫 로드와 탭 reload 결과 불일치. loadInitiallistNotes() (= deleted_at IS NULL = active+completed+archived 혼재) 사용 → 헤더 inbox count (active 만) 와 list 불일치. listByStatus('active', limit:50) 로 통일.
  • AI 배너가 completed/archived 탭에서도 노출. OllamaBanner/PendingBanner/FailedBanner/ExpiryBanner/RecallBanner/RecoveryToast 가 !showTrash 만 체크해서 active 무관 컨텍스트에서도 그림. view === 'inbox' 분기로 한정.

갱신

  • 이동 dropdown UX — 메뉴 열린 상태에서 외부 클릭 / Escape 로 닫힘 (mousedown + keydown listener, useEffect 로 menuOpen=true 일 때만 활성).

게이트

  • 단위 738 → 734 PASS (MoveStatusModal 6 case 삭제 + NoteCard 메뉴 case 1 → 3 (직접 이동/외부 클릭/Escape) 로 재구성)
  • typecheck 0 errors (src)
  • 신규 npm dependency 0

업그레이드

v0.3.4 인스톨러 위에 v0.3.5 인스톨러를 같은 위치에 실행하면 in-place 업그레이드. 데이터/마이그레이션 변경 없음.

[0.3.4] — 2026-05-11

v0.3.0 Cut E (양방향 sync) dogfood 의 결과로, 사용자가 conflict 시나리오에 막힌 순간 도움받을 곳이 부재한 갭을 메운 cut. 3 표면 (in-app modal + ConflictModal inline + README) 통합 도움말. PR #33 머지.

신규

  • SyncHelpModal (4 anchor 섹션) — 설정 → 동기화 저장소 → "도움말" 버튼 또는 ConflictModal 의 "자세히 보기 →" 링크에서 진입. #main-conflict (편집/편집·삭제/편집·AI 결과 충돌 결정 트리) / #auto (fetch+rebase·첫 sync·push 거부·자동 주기) / #silent (NTP·동시 수정·자동 sync 실패 silent) / #setup (URL SSH/HTTPS 형식·잘못된 git@https:// 사례·인증 helper·연결 테스트 실패 troubleshoot·URL 재설정).

갱신

  • ConflictModal inline 설명 — 각 conflict row 의 "내 것 사용" / "원격 사용" 의미를 1-2 줄 인라인 안내 + (옵션) "자세히 보기 →" 링크 (onOpenHelp callback). 기존 caller backward-compatible (optional prop).
  • SyncSection 도움말 버튼 — URL row 마지막에 추가. busy (저장/테스트/sync 진행) 중에도 도움말 reachable (read-only).
  • README 동기화 섹션 통째 재작성 — stale "원격 백업 (F6-L2)" (v0.2.1 MVP, 트레이 "지금 동기화" + 수동 git init 안내) → "동기화 (Git, F21 Cut E)". 일회 설정 / 일상 사용 / 충돌 해결 (3 케이스) / Silent risk / Troubleshoot. in-app SyncHelpModal 과 동일 정보 산문체.

게이트

  • 단위 727 → 738 PASS (+11): SyncHelpModal 7 + ConflictModal 회귀 3 + SyncSection 회귀 1
  • typecheck 0 errors
  • 신규 npm dependency 0

후속 (deferred)

  • ESC key handler (현재 SyncHelpModal / ConflictModal 모두 X + overlay 만, 프로젝트 패턴 정합. 도입 시 양쪽 동시).
  • 1주 dogfood soak 후 도움말 텍스트 정합성 1차 갱신 (실제 사용자 경험과 어긋난 부분 보강).

업그레이드

v0.3.3 인스톨러 위에 v0.3.4 인스톨러를 같은 위치에 실행하면 in-place 업그레이드. 데이터/마이그레이션 변경 없음 (스키마 v8 그대로).

[0.3.3] — 2026-05-10

v0.3.0 Cut E (양방향 sync) dogfood 첫 시도 중 발견된 sync 설정 ENOENT 버그 hotfix.

수정

  • Sync 설정 첫 저장 실패 (git init ENOENT): 설정 → 동기화 저장소에서 URL 입력 후 "저장" 클릭 시 git init failed: fatal: cannot change to '<profileDir>/sync': No such file or directory 로 실패하던 문제. settings:configure-sync IPC 핸들러가 git -C <syncDir> init 호출 전에 syncDir 디렉토리를 생성하지 않아 git 이 chdir 단계에서 죽음. SyncService.runSync() 의 동일 패턴 (mkdir(syncDir, { recursive: true })) 을 핸들러에도 추가. 결과적으로 "연결 테스트" 버튼이 영영 활성화되지 않던 연쇄 증상 (저장 성공 시에만 url state 채워지고 버튼 enable) 도 자동 해소.

게이트

  • 단위 테스트: tests/unit/sync-ipc.test.ts 18 (mkdir 호출 순서 회귀 1 추가)
  • typecheck: 0 errors
  • 신규 npm dependency: 0

업그레이드

v0.3.2 인스톨러 위에 v0.3.3 인스톨러를 같은 위치에 실행하면 in-place 업그레이드. 데이터/마이그레이션 변경 없음 (스키마 v8 그대로).

0.2.2 — 2026-04-26

v0.2.1 dogfood 중 발견된 F7 (Due Date 합성 표현) + Quick Capture 스크롤 버그를 묶은 패치.

수정

  • F7 — AI-primary due_date flow (#11, 1c72b64·723dccd·579450e): "내일 모레" 가 "내일" 로 잘못 매칭되던 문제. 규칙 파서를 first-match-wins 단일 추출에서 parseAllCandidates 다중 후보 추출로 확장하고, 후보 리스트를 프롬프트 힌트로 주입해 AI 의 dueDate 를 최종값으로 채택. 모호한 합성 표현 ("내일 모레", "다음 주 이번 주") 은 AI 가 null 반환 → 사용자 수동 입력으로 위임. PROMPT_VERSION 3.
  • Quick Capture 창 스크롤 차단: Ctrl+Shift+J 캡처 창에서 입력이 길어지면 textarea 가 flex min-height: auto 때문에 hint (Ctrl+Enter 저장 · Esc 취소 · 이미지 붙여넣기) 를 카드 밖으로 밀어내고 윈도우에 스크롤바가 생기던 문제. textarea { min-height: 0 } + .card/html, body, #root { overflow: hidden } 로 textarea 자체 스크롤로만 동작하도록 격리.

게이트

  • 단위 테스트: 197 → 205 (+8, F7 parseAllCandidates 7 + AiWorker flow flip 1)
  • e2e smoke: 1/1
  • typecheck: 0 errors
  • 신규 npm dependency: 0

업그레이드

v0.2.1 인스톨러 위에 v0.2.2 인스톨러를 같은 위치에 실행하면 in-place 업그레이드. 데이터/마이그레이션 변경 없음 (스키마 v2 그대로).

0.2.1 — 2026-04-26

v0.2.0 dogfood-feedback 8 항목 로드맵 (docs/superpowers/specs/2026-04-26-feedback-roadmap-design.md) 을 한 번에 흡수한 cut.

신규 기능

  • F6-L1 로컬 스냅샷<profileDir>/backups/inkling-YYYY-MM-DD.sqlite 자동 백업 (앱 시작/종료 시) + GFS 로테이션 (14 daily · 5 Mondays · 6 monthly). 트레이 → "지금 백업".
  • F5 마크다운 export — 모든 노트를 frontmatter 마크다운 + index.jsonl + manifest.json + 미디어 트리로 사용자 지정 폴더에 내보내기. RAG 친화 형식. 트레이 → "내보내기...".
  • F6-L3 Import — F5 export 트리를 DB 에 다시 적재. 충돌 정책: id 동일 + raw_text 동일 → skip; id 동일 + raw_text 상이 → 새 uuidv7 (raw_text 불변 invariant 보호); id 신규 → insert. 트레이 → "백업에서 복원...".
  • F1 Due Date 추출 — 한국어 노트 본문에서 마감일 자동 추출 (규칙 파서 14 카테고리 + AI 폴백). NoteCard 에 📅 YYYY-MM-DD 인라인 라벨 + 클릭 편집. 만료 시 회색 + 취소선.
  • F2 태그 클릭 동작 분리 — 칩 텍스트 클릭 = 동일 태그 노트만 필터, 별도 ✕ 버튼이 제거 (5초 undo 토스트).
  • F6-L2 Git sync (MVP) — 트레이 → "지금 동기화" 가 F5 export 트리를 <profileDir>/sync/ 에 쓰고 git add/commit/push. 앱 종료 시 자동 1회. 사용자가 일회 git init && git remote add origin <url> 설정 필요. README 의 "원격 백업" 섹션 참고.
  • F4-C·F cue 강화 — 트레이 tooltip + 메뉴 첫 항목 + Inbox 헤더에 오늘 KST 캡처 카운트 (오늘 N번 잡아뒀다).

카피 변경 (F3 + F4-E)

표면별 자연 한국어로 재배치 — "기억 구출" → 표면별 다른 동사:

표면 이전 신규
트레이: Inbox 구출한 메모 보기 보관한 메모 보기
트레이: 새 메모 기억 구출하기 한 줄 적기
토스트 #2 나중에 찾을 수 있게 보관했습니다. 머릿속에서 꺼내 두었습니다.
토스트 #3 방금 하나의 업무 기억을 구출했습니다. 방금 한 줄 잡아뒀습니다.
Inbox 빈 상태 첫 기억을 구출해보세요. 머릿속에 떠다니는 한 줄을 적어보세요.
QC 힌트 Ctrl+Enter 구출 Ctrl+Enter 저장
제품 표어 local-first 기억 구출 도구 local-first 한 줄 보관 도구

strategy.md §1, §4.1, §9, §11 도 동반 갱신. F4-E (Zeigarnik priming) 효과를 빈 상태 카피에 반영.

데이터 / 마이그레이션

  • Migration v2: notes 테이블에 due_date TEXT, due_date_edited_by_user INTEGER NOT NULL DEFAULT 0 컬럼 추가 (NULL 기본, 비파괴).
  • Pre-migration snapshot: openDb() 가 마이그레이션 직전 <dbFile>.pre-v<N>.bak 생성 (v0.2.0 → v0.2.1 첫 실행 시 자동, 한 번만). 마이그레이션 결함 시 회수 가능 (F6-L1 후속 #4 반영).
  • raw_text 불변 invariant 그대로. F6-L3 import 의 충돌 정책이 이 invariant 를 보호.

시스템 의존

  • git CLI — F6-L2 가 사용자 시스템의 git 을 호출. Windows: Git for Windows + Credential Manager 자동 설정. 이미 README 사전 요구에 포함.

게이트

  • 단위 테스트: 52 → 197 (+145)
  • e2e smoke: 1/1
  • typecheck: 0 errors
  • 신규 npm dependency: 0

Deferred / 후속

다음 기능은 데이터 측정이 필요하여 v0.2.1 dogfood soak 후 별도 brainstorm 으로 이동:

  • F4-A: 잠금/잠금해제 hook (variable interval prompt)
  • F4-B: ambient if-then 온보딩
  • F4-D: 무작위 부드러운 알림

또한 F6-L2 의 Settings UI · safeStorage 토큰 관리 · 자동 conflict resolution · 5분 debounce 등은 MVP 외이며, 데이터 손실 위협 없이 일단 사용 후 우선순위 결정.

업그레이드

v0.2.0 인스톨러 위에 v0.2.1 인스톨러를 같은 위치에 실행하면 in-place 업그레이드. %APPDATA%\Inkling\Inkling\profiles\default\ 데이터 보존. 첫 실행 시 자동 pre-migration snapshot + migration v2 + F6-L1 첫 백업 생성.

권장 절차 (안전):

  1. v0.2.0 트레이 → "지금 백업" 1회
  2. v0.2.0 트레이 → "내보내기..." 1회 (F5 — schema-agnostic 마크다운)
  3. v0.2.0 종료
  4. Inkling Setup 0.2.1.exe 실행 → 같은 폴더에 설치
  5. 첫 실행 시 migration v2 자동 적용

복원 경로 2 가지:

  • (a) <dbFile>.pre-v2.bak 으로 SQLite 자체 복원 (v0.2.0 인스톨러 재설치 필요)
  • (b) F5 export → v0.2.1 의 F6-L3 import 로 schema-agnostic 복원 (더 빠름)

0.2.0 — 2026-04-25

슬라이스 v0.4 — 가장 얇은 종단 경로 (Quick Capture → SQLite → 로컬 Ollama → Inbox) + electron-builder NSIS 인스톨러 + Windows autostart hook + post-slice 마이그레이션 정리. 자세한 결정 이력은 docs/superpowers/specs/2026-04-24-inkling-vertical-slice-design.md 와 git log 참조.