Commit Graph

411 Commits

Author SHA1 Message Date
altair823
d3150976d4 feat(v029): classifyStatus AI prompt + ai:classify-status 정식 구현 (Task 8 stub 대체)
- src/main/ai/classifyStatus.ts: prompt + JSON parse + 안전 fallback (archived).
- InferenceProvider.generateRaw 추가 (optional) + LocalOllamaProvider 구현
  (Ollama /api/generate format:'json' 으로 raw JSON 응답 반환).
- inboxApi 의 ai:classify-status 핸들러를 stub 에서 정식 호출로 교체
  (deps.repo.findById + deps.providerHolder.get + classifyStatus()).
- 신규 테스트 7건 (classifyStatus 단위) + IPC 3건 (note 없음 / AI throw / 정상).
- 회귀: 513 → 522 통과.
2026-05-09 16:09:33 +09:00
altair823
495c3d12a2 feat(v029): NoteCard 이동 메뉴 (status 4분기 dropdown)
Cut B Task 6 — 모든 view 공통 "이동 ▾" dropdown.

- 기존 휴지통/삭제 버튼 위치에 dropdown 추가 (모든 mode 공통)
- 현재 status 외 3개 목적지만 표시 (active 노트 → 완료/보관/휴지통)
- 메뉴 항목 클릭 → MoveStatusModal(initialTarget) 열기
- onMoved → local 상태 갱신 + onUpdated + (status 변경 시) onDeleted (list 제거)
- trash mode 의 영구 삭제/복구 버튼은 보존 (휴지통 단독 액션)
- 사용되지 않게 된 handleDelete 제거 (deleteNote 는 capture path 만)
- NoteCard 메뉴 단위 테스트 2건 (메뉴 표시 / 클릭 → modal → setStatus)
2026-05-09 16:03:40 +09:00
altair823
9eb7abc831 feat(v029): MoveStatusModal — 사유 입력 + 4 status 버튼 + AI 자동 분류 placeholder
Cut B Task 7 — NoteCard 메뉴가 여는 modal.

- 사유 textarea (선택) + 활성/완료/보관/휴지통 버튼 (옮기기 즉시 setStatus + onMoved)
- 빈 사유 → null reason 전달 (trim 처리)
- AI 자동 분류 버튼 → classifyStatus(stub) 호출 + 추천 표시 + 확정 버튼
- statusLabel helper export (NoteCard 메뉴에서 재사용)
- 4 단위 테스트 (render / 버튼 클릭 / AI 추천 흐름 / 빈 사유 null)
2026-05-09 16:00:51 +09:00
altair823
d4dce9bf34 feat(v029): inbox:set-status + ai:classify-status (stub) IPC
Cut B Task 8 — Modal/NoteCard 메뉴 path 의 IPC backbone.

- inbox:set-status: id + status + reason → repo.setStatus, invalid status 거부
- ai:classify-status: stub (Task 9 에서 Ollama provider 호출로 정식 구현)
- types.ts InboxApi.setStatus / classifyStatus 시그니처 + preload wire-up
- 4 단위 테스트 (valid/null reason/invalid status/stub shape)
2026-05-09 15:59:43 +09:00
altair823
92375edc31 feat(v029): 헤더 4탭 (Inbox/완료/보관/휴지통) + count badge
- App.tsx: 기존 2탭 (Inbox/휴지통) → 4탭. setView/counts 사용.
- onNavigate 도 setView 로 위임 (mirror state 동기 갱신).
- App.test: 4탭 렌더 + 클릭 → setView('completed') + aria-pressed (3 cases).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 15:51:59 +09:00
altair823
606ac94976 feat(v029): useInbox view enum + counts + setView + listByStatus/countsByStatus IPC
- store.ts: view enum ('inbox'|'completed'|'archived'|'trash'|'settings') + counts +
  setView + loadByView. setShowSettings delegates to setView (mirror).
- types.ts + preload + ipc/inboxApi: listByStatus + countsByStatus IPC.
- NoteRepository.countByStatus 신규.
- store.view.test (5) + NoteRepository.countByStatus test (1).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 15:51:51 +09:00
altair823
fd839f6afe feat(v029): ai_status 'disabled' enum + CaptureService ai_enabled 분기 (skip pending_jobs)
- AiStatus enum 'disabled' 추가 — settings.ai_enabled=false 일 때 새 노트의 초기 status.
- m005 migration: ai_status CHECK 제약을 ('pending','done','failed','disabled') 로 relax.
  SQLite 가 ALTER COLUMN CHECK 미지원 → table recreate (notes_new INSERT SELECT DROP RENAME).
  기존 인덱스 (idx_notes_created_at, idx_notes_ai_status, idx_notes_deleted_at) 재생성.
- SettingsService schema 에 ai_enabled / onboarding_completed (optional) 추가 +
  isAiEnabled / setAiEnabled / isOnboardingCompleted / setOnboardingCompleted accessor.
  기본 fallback (ai_enabled=true, onboarding_completed=false) — 기존 settings.json 무영향.
- NoteRepository.create 가 optional aiStatus 받도록 — 'pending' 외 값일 때 pending_jobs skip.
  기존 caller (rawText 만 전달) 무영향.
- CaptureService deps 에 settings (좁은 AiEnabledSource 인터페이스) 추가.
  submit() 가 ai_enabled 조회 → false 면 ai_status='disabled' insert + enqueue skip.
  settings 미주입 시 기존 동작 (항상 enabled) 보존 — 테스트 케이스 무영향.
- main/index.ts wiring: settings: settingsSvc 주입.

Tests: 489 → 494 (CaptureService ai_enabled 2건 + m005 migration 3건). typecheck 0.
2026-05-09 15:43:01 +09:00
altair823
facbf54025 feat(v029): NoteRepository.setStatus + listByStatus + restoreNote 재구현
- 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 회귀).
2026-05-09 15:33:49 +09:00
altair823
06a1caf2bd feat(v029): m004 마이그레이션 — status/status_changed_at/move_reason 컬럼
- notes 테이블 ADD COLUMN status (DEFAULT 'active'), status_changed_at, move_reason
- deleted_at != NULL 노트 → status='trashed' + status_changed_at=deleted_at 로 backfill
- index.ts registry 에 m004 추가 (runMigrations 자동 적용)
- migrations.test.ts user_version assertion 4 로 갱신
2026-05-09 15:27:15 +09:00
altair823
7d2b8c95ec docs(v028+): F17~F25 dogfood + roadmap + Cut A~G specs + Cut A plan
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>
2026-05-09 15:09:02 +09:00
b20473a593 Merge pull request 'v0.2.8 Cut A — 이미지 렌더링 + 앱 아이콘 (F22 + chore)' (#26) from worktree-v028-cut-a-image-icon into main
Reviewed-on: #26
v0.2.8
2026-05-09 05:57:09 +00:00
altair823
6db449f86d chore(v028): final review minor 3건 cleanup
- inklingMedia.ts:39 no-op replace 제거 + 명료한 host+pathname 결합 코멘트
- inbox:open-media 빈 relPath 명시적 거절 (typeof + length 검사)
- NoteCard <img> alt="" decorative 의도 코멘트

472/472 + typecheck 0 유지.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 14:27:42 +09:00
altair823
29259eef32 chore(release): v0.2.8 — Cut A (이미지 렌더링 + 앱 아이콘) 2026-05-09 14:23:51 +09:00
altair823
4d4dac5523 chore(v028): 앱 아이콘 (assets/icon.svg → ICO/ICNS/PNG) + electron-builder config
- 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>
2026-05-09 14:19:28 +09:00
altair823
9cdea1531c feat(v028): IPC inbox:open-media + path traversal + NoteCard cast 정리 2026-05-09 14:10:57 +09:00
altair823
f6bea623bf feat(v028): NoteCard 이미지 <img> 렌더링 + onClick (openMedia 시그니처는 Task 3)
- 회색 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
2026-05-09 14:06:21 +09:00
altair823
470384bf80 feat(v028): inkling-media:// custom protocol + path traversal 검사
- 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 사용.
2026-05-09 14:00:50 +09:00
e8cddc7889 Merge pull request 'v0.2.7 — cross-platform 입구 정상화 (F12 deeper + F14 + F15 빌드 + F16)' (#25) from worktree-v027-cross-platform into main
Reviewed-on: #25
v0.2.7
2026-05-07 00:50:17 +00:00
altair823
e19f6a8de7 chore(v027): PR review minor cleanup 3건
- 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>
2026-05-07 09:49:09 +09:00
altair823
ccfdbce79b chore(release): v0.2.7 — cross-platform 입구 정상화 (F12 deeper + F14 + F15 빌드 + F16) 2026-05-07 02:37:13 +09:00
altair823
cffd1cec90 refactor(v027): OllamaSettingsModal 제거 + onOpenOllamaSettings 채널 cleanup 2026-05-07 02:35:43 +09:00
altair823
c5f2b8337a test(v027): App/SettingsPage 테스트 mock 을 새 AutostartResponse 형태로 갱신 2026-05-07 02:32:06 +09:00
altair823
836828636c feat(v027): AutostartSection 재등록 버튼 2026-05-07 02:30:29 +09:00
altair823
8a8652e87a feat(v027): AutostartSection 진단 패널 + mismatch 경고 2026-05-07 02:29:17 +09:00
altair823
ce6c5ea756 feat(v027): settings:autostart-set 정식 + 채널 이름 통일 2026-05-07 02:28:17 +09:00
altair823
39bbf8f443 feat(v027): settings:autostart-state IPC 핸들러 2026-05-07 02:26:18 +09:00
altair823
5f964aa2f5 feat(v027): AutostartDiagnostic — Windows registry 조회 + silent fallback 2026-05-07 02:25:21 +09:00
altair823
3a8137f334 feat(v027): AutostartDiagnostic — withArgs/noArgs/execPath 수집 2026-05-07 02:23:52 +09:00
altair823
3b53cec663 fix(v027): F14 — macOS dock 클릭 시 hidden inbox 창 show/focus 2026-05-07 02:22:40 +09:00
altair823
9c8ba8ad09 feat(v027): createTray wiring 3-callback + refreshTray 호출부 슬림 2026-05-07 02:18:32 +09:00
altair823
f30fbddd38 feat(v027): tray.ts 의 showAboutDialog + 자동실행 분기 + 미사용 import 제거 2026-05-07 02:16:55 +09:00
altair823
77effb4526 feat(v027): TrayCallbacks/TrayState 슬림 + buildMenu 4 항목 2026-05-07 02:16:29 +09:00
altair823
feb7c62f19 feat(v027): IPC inbox:navigate — 외부에서 설정 페이지 진입 2026-05-07 02:12:45 +09:00
altair823
95ed0fba93 feat(v027): App.tsx 헤더 톱니바퀴 + showSettings 분기 2026-05-07 02:10:01 +09:00
altair823
6ab518410e feat(v027): InfoSection — 버전/데이터 위치/복사 + IPC 2026-05-07 02:07:20 +09:00
altair823
5cd38f2537 feat(v027): BackupSection — 5 버튼 + IPC 핸들러 2026-05-07 02:03:31 +09:00
altair823
fca28fb0c4 feat(v027): AutostartSection 토글 (진단 패널은 후속 task) 2026-05-07 01:56:58 +09:00
altair823
7301f4d73d feat(v027): AiProviderSection — OllamaSettingsModal 흡수 + 지금 재확인 2026-05-07 01:51:53 +09:00
altair823
91bf98f1a2 feat(v027): SettingsPage scaffold — 4 섹션 placeholder + 돌아가기
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 유지)
2026-05-07 01:42:54 +09:00
altair823
5b37529175 feat(v027): inbox store 에 showSettings state + setShowSettings action 2026-05-07 01:36:26 +09:00
altair823
c9d374ade6 docs(v027): dist:linux 1차 빌드 시도 결과 (Windows 호스트) 2026-05-07 00:23:07 +09:00
altair823
b1b7bfee26 feat(v027): electron-builder linux target (AppImage + deb x64) 2026-05-07 00:18:14 +09:00
altair823
66bae5e317 docs(v027): better-sqlite3 linux-x64 prebuild 가용성 검증 2026-05-07 00:15:12 +09:00
altair823
5a605ef98f docs(v027): cross-platform 입구 정상화 implementation plan 작성
27 task / 6 phase. Phase 1 (Linux 빌드 risk-reduction first) → Phase 2
(설정 페이지 + IPC) → Phase 3 (트레이 슬림) → Phase 4 (F14 dock fix) →
Phase 5 (F12 deeper fix) → Phase 6 (cleanup + version bump).

각 task TDD red→green→typecheck→commit 순서. spec coverage / placeholder
/ type consistency self-review 통과.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 00:10:25 +09:00
altair823
c2be135031 docs(v027): cross-platform 입구 정상화 design 작성
F12 deeper fix + F14 + F15 (Linux 빌드만, CLI 제거) + F16 4묶음 —
v0.2.7 brainstorm 결과. dogfood-feedback.md F15 entry promoted/rejected
표시. F12/F14/F16 promoted 마킹은 design 확정 후 일괄 처리.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 23:59:39 +09:00
altair823
9f47c13649 docs(dogfood): v0.2.6 release 후 dogfood 문서 갱신
dogfood-feedback.md (F1~F7 → F1~F13):
- Header: 진척 흐름 요약 표 추가 (v0.2.3 ~ v0.2.6 cuts + 신규 dogfood 발견)
- F8 Windows 11434 reserved → v0.2.3.1/v0.2.4 (PR #21/#22)
- F9 multi-instance spawn → v0.2.5 critical hotfix (PR #23)
- F10 버전 정보 부재 → v0.2.4 트레이 "Inkling 정보..." 추가
- F11 single-instance lock 부재 (F9 흡수)
- F12 autostart 풀림 → v0.2.6 진단 fallback (drafting, dogfood verify 후 v0.2.7)
- F13 PR review 발견 (restoreNote production path dead code) → v0.2.6 round 1 Critical fix

dogfood-strategy.md (Day 0 환경 step 갱신):
- v0.2.6 binary release 기준
- Ollama 설정: in-app UI (트레이 "Ollama 설정...") 가 1차, env var fallback 그 다음
- 11434 reserved 머신 우회 절차 (OLLAMA_HOST=127.0.0.1:11942)
- 데이터 위치 확인: 트레이 "Inkling 정보..." → "데이터 위치 열기"
- autostart 확인 절차 (F12 dogfood verify 영역)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 02:28:37 +09:00
altair823
a51f241b94 docs(backlog): v0.2.6 cut 16건 처리 갱신 — 잔여 24건
처리 이력 표 갱신:
- v0.2.6 정식 cut (PR #24, 머지 8bc33da) 의 16 backlog 항목 모두  표기
- B1 production path Critical fix (a991008) 별도 row 추가
- v0.2.6 final reviewer + round 1 minors (NoteRepository.countToday inline KST,
  BackupService/ContinuityService inline KST, NoteRepository.test.ts as any,
  OllamaSettingsModal #fce4e4 inline, kstDate naming, store trashCount race,
  ExpiryBanner useEffect closure) deferred 표 추가

총 항목 46 / 처리 21 / stale 1 / 잔여 24.

명명 노트 갱신:
- v0.2.6 = 첫 정식 cut
- v0.2.7 = telemetry data-dependent 14건 + #45 deeper fix + deferred
- backlog file 본 파일은 v0.2.7 cut 시점에 prune + rename 검토

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
v0.2.6
2026-05-05 02:10:04 +09:00
8bc33da954 Merge pull request 'feat(v026): bugs + cleanup — 16 backlog 항목 처리' (#24) from feat/v026-bugs-cleanup into main
Reviewed-on: #24
2026-05-04 17:06:31 +00:00
altair823
a991008689 fix(v026): PR #24 round 1 Critical — B1 production path activation
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>
2026-05-05 01:58:27 +09:00
altair823
54e2f5b10f chore(release): v0.2.6 — bugs + cleanup (16 backlog 항목 처리)
bugs (4):
- #10 restoreNote 가 failed 노트 시 pending_jobs 재생성
- #12 trashCount cap → countTrashed() 정확 N (이미 fix 됨, tests 추가)
- #45 autostart 풀림 — args 비교 정확도 + 진단 로그
- #46 hidden-start race — additionalData 로 두 번째 hidden 구분

cleanup (12 → 9 cluster):
- #3+#19+#34 KST helper 통합 → src/shared/util/kstDate.ts (4 callsite migrate)
- #4+#23+#26+#27 TrayCallbacks 객체화 + state 통합 (10 positional → 1-arg + Partial<TrayState>)
- #5 AiFailedReason union 단일 export (zod z.infer)
- #21 hasNoteId type predicate (TelemetryService.test.ts narrowing 단축)
- #22 NoteRepository hydrate row type 통일 (as Record<string, unknown>[])
- #24+#41 Banner shared component (severity prop, 4 banner migrate)
- #8 stats.md exhaustiveness check (else { _: never })
- #15 IPC channel inbox:delete → inbox:trash
- #29 VOCAB_TOP_N const
- #42 Modal client-side URL pre-check (zod safeParse)
- #9 휴지통 회수율 ratio 의미 코멘트

게이트: typecheck 0 / 단위 424 / e2e 1
잔여 backlog: 14건 (telemetry data-dependent, v0.2.7 brainstorm)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 01:46:25 +09:00