- NoteStatus 타입 추가 ('active'/'completed'/'archived'/'trashed')
- Note interface 에 status / statusChangedAt / moveReason 필드 추가
- setStatus(id, status, reason, now?) — 단일 transaction 으로 status + move_reason +
status_changed_at + updated_at 갱신. status='trashed' ↔ deleted_at 동기화
(backward compat). 그 외 status 는 deleted_at NULL.
- listByStatus(status, opts) — status 별 필터 + ORDER BY COALESCE(status_changed_at,
created_at) DESC. limit cap 200.
- hydrate 에 status / statusChangedAt / moveReason 매핑 추가. 미설정 row 는 'active' fallback.
- restoreNote 재구현 — setStatus('active', null) 로 status + deleted_at 동기화 +
v0.2.6 #10 round 1 fix (ai_status='failed'/'pending' → pending_jobs 재투입) 보존.
- 기존 테스트 fixture 5건에 새 필드 추가 (NoteCard, store.expired/recall/tagFilter/trash).
- 신규 테스트 11건 (setStatus + listByStatus + restoreNote 회귀).
v0.2.7 release 후 dogfood 9건 누적 (F17~F25) 정리:
- F17 휴지통 의미 분기 / F18 사유 입력 / F19 recall / F20 raw_text 가변
- F21 다기기 sync / F22 이미지 렌더링 (이미 v0.2.8 promoted) / F23 Ollama-less
- F24 멀티모달 vision / F25 사이드바 + 저장소
추가:
- v0.2.8+ roadmap: 7 cut 분할 (A~G), 12주 시간선, dependency graph
- Cut A~G design specs (각 cut 별 design 결정 + schema + UI + 테스트 전략)
- Cut A implementation plan (이미 v0.2.8 머지로 실행 완료, 참고 보존)
PR #26 머지 후 main 에 doc commits rebase 안 되어 manual merge 진행:
- F22 entry 는 origin/main 의 promoted 형태 우선
- 신규 9 파일 (specs/plan/roadmap) 은 origin/main 에 없는 파일
- "다음 항목 자리" 안내 F23 → F26 갱신
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- electron-icon-builder + sharp devDep 추가
- assets/icon.svg → build/icon.{ico,icns,png} 산출 + git 추적
- electron-icon-builder 가 SVG 직접 input 안 받음 (Jimp MIME 에러) — sharp 로 SVG → PNG 1024 변환 후 input
- scripts/svg-to-png.mjs (sharp 사용 SVG→PNG) + scripts/finalize-icons.mjs (build/icons/ → build/ 정규 위치 정리)
- package.json build.{win,mac,linux}.icon 키 추가
- .gitignore: build/icons/ 와 build/icon-source.png (중간 산출물) 무시, build/icon.* 는 추적
- typecheck 0 errors + 472/472 단위 통과 유지 (회귀 없음)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- 회색 placeholder div → <img src=inkling-media://...> 로 교체
- onClick 으로 inboxApi.openMedia(relPath) 호출 (현재는 InboxApi 인터페이스에 부재 → unknown cast 사용; Task 3 에서 정식 시그니처 추가 후 cast 제거 예정)
- alt='' 로 decorative 처리 (role=presentation), title 에 relPath 유지
- flex-wrap 추가 — 다수 이미지 시 줄바꿈
Tests: tests/unit/NoteCard.test.tsx 신규 2건 (img src 검증, click → openMedia 호출)
회귀: 468 → 470 pass
- registerSchemesAsPrivileged: inkling-media 스킴을 secure + supportFetchAPI + stream 으로 등록 (whenReady 이전 호출 필수).
- registerInklingMediaProtocol: profileDir/media 하위 파일을 raw URL traversal (.., %2e%2e) 검사 + normalize 후 mediaRoot 봉쇄로 이중 검증 후 readFile.
- inferMime: png/jpg/jpeg/gif/webp → image/*, 그 외 → application/octet-stream.
- src/main/index.ts: 모듈 import 직후 registerSchemesAsPrivileged(), whenReady 안 paths 결정 직후 registerInklingMediaProtocol(paths.profileDir).
- tests/unit/inklingMedia.test.ts: 8 unit (5 inferMime + 3 handler — valid/403/404). vitest 의 new Request() 가 url 을 normalize 하므로 raw url 보존을 위해 minimal mock req 사용.
- types.ts:119 stale "Task 25 cleanup" comment 제거 (Task 25 이미 완료)
- BackupSection.tsx 의 dead try/catch 제거 + status 단순화 — 모든 IPC 핸들러가 자체 try/catch + Notification 으로 결과 알림. 컴포넌트 status 는 진행 표시 보조용
- index.ts startup #45 autostart 진단 로그를 AutostartDiagnostic.collectAutostartState() 호출로 통합 — single source of truth (SettingsPage 진단 패널과 동일 데이터 소스)
460/460 pass, typecheck 0.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
v027 plan Task 7. zustand store 의 showSettings 를 사용하는 첫 컴포넌트.
4 섹션 (AI 제공자/자동 실행/백업·복원/정보) placeholder 와 헤더 + 돌아가기 버튼만.
실 콘텐츠는 후속 Task 8-11 에서 채움.
테스트 인프라 동시 추가 (v027 의 첫 React 컴포넌트 테스트):
- @testing-library/react + @testing-library/jest-dom + jsdom devDep 추가
- vitest.config: plugin-react 적용, include 에 .test.tsx 포함
- 환경 분리는 per-file `// @vitest-environment jsdom` directive 로 처리
(vitest 4.x 에서 environmentMatchGlobs 미지원 — 기존 .ts 단위 테스트는 node env 유지)
Round 1 reviewer 발견: B1 (#10) fix 가 dead code. NoteRepository.restoreNote
새 메서드는 unit test 만 호출, production path (CaptureService.restoreNote)
는 옛 repo.restore() 호출 → ai_status reset + pending_jobs INSERT 우회.
Fix:
- CaptureService.restoreNote 가 repo.restoreNote 호출
- before 의 ai_status 가 'failed' or 'pending' 이면 worker.enqueue(id) 도 호출
(in-memory queue 갱신 — restoreNote 가 DB 만 갱신하면 다음 app start 까지
처리 안 됨)
Round 1 Important 도 함께 처리.
단위 +2 cases (failed → enqueue, done → skip enqueue).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
createTray(callbacks: TrayCallbacks) 1-arg signature. 기존 10 positional 폐기.
TrayState 통합 (ollamaOk, todayCount, failedCount) — refreshTray({...partial})
1개 setter 로 일원화.
기존 refreshTrayOllama / refreshTrayFailedCount export 제거 — 호출자 모두
refreshTray({ ollamaOk: ... }) / refreshTray({ failedCount: ... }) 로 migrate.
module-scoped 개별 state 변수 (_failedCount 등) 제거.
backlog 4건 일괄: #4 (positional 폭주) / #23 (8 callbacks) / #26 (10 callbacks) /
#27 (refreshTrayFailedCount singleton). 다음 menu item 추가 시 callback
프로퍼티 추가만 — readability blocker 해소.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
if/else if 체인 끝에 const _exhaustive: never = ev — 새 telemetry kind
추가 시 본 함수 분기 누락을 컴파일 단계에서 catch.
silent fall-through 방지 — kind 추가 → typecheck 실패 → 강제 분기 추가.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
db.prepare().all() 의 row type cast s any[] / s unknown[] →
s Record<string, unknown>[] 일괄 통일. hydrate() signature 도 동일
(이미 그렇거나 갱신).
- TS strict 환경 친화 (any 보다 narrow)
- 향후 explicit row interface 추가 시 base 형 명확
- runtime 동작 변경 0
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>