v0.3.5 의 이동 dropdown 단순화가 사용자 의도와 어긋남. 사용자는 dropdown 의 목적지 중복 (modal 도 목적지 묻기) 만 거슬렸지, 사유 입력 + AI 자동 분류 + 수동 status 선택을 한 곳에서 처리하는 modal 은 보존해야 하는 핵심 UX 였음. 단일 "이동" 버튼 → MoveStatusModal path 로 정정. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
200 lines
14 KiB
Markdown
200 lines
14 KiB
Markdown
# Changelog
|
|
|
|
본 파일은 Inkling 의 버전별 사용자 영향 변경 사항을 기록한다.
|
|
형식은 [Keep a Changelog](https://keepachangelog.com/) 를 느슨하게 따른다.
|
|
|
|
## [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 전환 시 검색/태그 필터 잔류.** `setView` 가 `searchResults`/`searchQuery`/`tagFilter` 를 reset 안 해서 이전 view 의 필터가 완료/보관/휴지통/회고에 잘못 적용. 한 번에 reset.
|
|
- **Inbox 첫 로드와 탭 reload 결과 불일치.** `loadInitial` 이 `listNotes()` (= `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 참조.
|
|
|
|
[0.2.2]: https://gitea.altair823.xyz/altair823-org/inkling/releases/tag/v0.2.2
|
|
[0.2.1]: https://gitea.altair823.xyz/altair823-org/inkling/releases/tag/v0.2.1
|
|
[0.2.0]: https://gitea.altair823.xyz/altair823-org/inkling/releases/tag/v0.2.0
|