gemma4:26b (25B MoE + vision encoder 550M) 등 대형 vision 모델의
cold-start 가 60-180s 소요. 기본 120s timeout 으로 첫 호출 fail 빈번.
vision path 에 한해 Math.max(timeoutMs, 300_000) — text-only 영향 없음.
gemma4:26b 가 Text+Image 양 modality 지원 검증 완료
(blog.google/gemma-4, ollama.com/library/gemma4:26b).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
vision model 의 markdown fence / prose 섞인 응답에서 JSON 추출 fallback.
prompt 에 title 한국어 / kebab tags / JSON-only 출력 명시 강화.
- LocalOllamaProvider: parseJsonLoose 헬퍼 (첫 { ~ 마지막 } 추출)
- visionPrompt: 4 규칙 + markdown fence 금지 명시
- 단위 +2 (fence 추출 + prose 추출)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
양쪽 창의 CSP 가 img-src 부적합:
- quickcapture/index.html: img-src 미지정 → blob: 차단 → paste thumbnail 안 보임
- inbox/index.html: img-src 에 inkling-media: 누락 → 저장된 노트 이미지 안 보임
v0.3.0 이후 잠재적 회귀. 사용자 dogfood 발견.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
macOS fullscreen Space 위에 QuickCapture 띄우기. 이전엔 핫키 누를 때 강제 Space 전환.
quickCaptureWindow.ts darwin 분기 추가:
- type: 'panel' (fullscreen floating)
- setAlwaysOnTop(true, 'screen-saver') (가장 높은 level)
- setVisibleOnAllWorkspaces(true, visibleOnFullScreen: true)
Windows / Linux 동작 변경 없음.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
audit edge case 3건:
- pending 노트 "건너뛰기" 버튼 (cancelPending: pending → disabled + jobs DELETE)
- failed 노트 per-note "재시도" 버튼 (retryOneFailed: failed → pending + enqueue)
- FTS5 sanitize regex 확장 (backtick/dash/caret 추가)
동시 편집 race 는 EditableField guard 가 이미 처리 (수정 불필요).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
전수 audit 후 핵심 root fix 3 + edge cases 5:
ROOT
- inbox:set-status IPC 가 pushNoteUpdated emit (이전엔 stale → 호출처별 refreshMeta 필요)
- upsertNote 가 current view status 인식 (이전엔 잘못된 status 노트 잔류)
- store async 함수 try/catch (이전엔 IPC fail 시 무한 loading)
EDGE
- restoreNote 가 status='active' 도 갱신
- upsertNote trash 판정 deletedAt → status='trashed'
- Modal Escape dismiss 통일 (5개 modal)
- OnboardingWizard IPC fail fallback (try/catch + skip)
- MoveStatusModal overlay 클릭 close
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
MoveStatusModal 이 완료/보관/휴지통 3 button hardcode 라
완료/보관/휴지통 노트가 inbox 로 돌아오는 path 가 없던 버그 fix.
currentStatus prop 으로 4 status 중 current 제외 동적 render.
'활성' label 도 헤더 탭과 일치하도록 'Inbox' 로 통일.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
v0.3.5 의 이동 dropdown 단순화가 사용자 의도와 어긋남.
사용자는 dropdown 의 목적지 중복 (modal 도 목적지 묻기) 만 거슬렸지,
사유 입력 + AI 자동 분류 + 수동 status 선택을 한 곳에서 처리하는 modal 은
보존해야 하는 핵심 UX 였음. 단일 "이동" 버튼 → MoveStatusModal path 로 정정.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
v0.3.4 까지 누적된 dogfood UX 결함 hotfix.
사용자 직접 보고 3건 (inbox 재진입, 회고 탈출, 이동 modal 중복) + 동반 갭 4건
(count stale, 필터 잔류, 초기 로드 불일치, 배너 컨텍스트 누수).
데이터/마이그레이션 변경 없음 (스키마 v8).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PR #33 머지. SyncHelpModal + ConflictModal inline + README 통합 도움말.
v0.3.0 Cut E dogfood gap fill. 데이터/마이그레이션 변경 없음 (스키마 v8 그대로).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
v0.3.0 Cut E (양방향 sync) dogfood 첫 시도 중 발견된 git init ENOENT
hotfix 1건. 데이터/마이그레이션 변경 없음 (스키마 v8 그대로).
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>
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 유지)
dogfood 발견 — 앱 아이콘 클릭 시마다 새 process 가 떠서 트레이 아이콘 여러 개,
SQLite 동시 접근 + AiWorker 중복 처리 + HealthChecker 중복 polling 등
**데이터 corruption 위험**.
원인: app.requestSingleInstanceLock() 호출 부재. Electron default 가
multi-instance 라 .exe 실행마다 별도 process.
Fix:
- app.requestSingleInstanceLock() 첫 줄에서 호출
- 두 번째 인스턴스 → app.quit() 즉시 종료
- 'second-instance' 이벤트 → 기존 inbox 창 restore + show + focus
(사용자 의도는 "앱 보기" 라 가정)
게이트: typecheck 0 / 단위 413 / e2e 1
version: 0.2.4 → 0.2.5 (critical hotfix patch)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PR #20 직후 Mac arm64 dist 시도 중 발견:
- Cannot detect repository by .git/config 경고 (3회)
- ⨯ Cannot read properties of null (reading 'channel')
at computeChannelNames (updateInfoBuilder.ts:47:74)
원인: electron-builder 가 auto-update 메타파일 (latest-mac.yml) 생성 시
publish config 또는 git remote 에서 채널 정보 추론 실패 → null 접근 crash.
DMG 자체는 빌드 성공 (dist/Inkling-0.2.3-arm64.dmg) — 후처리 단계 crash.
Fix: build.publish = null 명시 — auto-update 메커니즘 미사용 (개인 dogfood)
이라 latest-mac.yml / latest.yml 생성 단계 skip. Windows 빌드도 동일 경고
3회 떴는데 이번 fix 로 함께 사라짐.
검증: npm run dist:dir on Windows → "Cannot detect repository" 경고 사라짐, 정상 빌드.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
8 항목 dogfood-feedback 로드맵 (F1·F2·F3·F4-E·F5·F6-L1·F6-L2·F6-L3·F4-C·F)
한 번에 흡수. migration v2 (due_date) + pre-migration snapshot.
단위 테스트 52 → 197. 신규 npm dep 0, 시스템 dep 추가는 git CLI (이미 사전 요구).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
v4/v7 imports stay API-compatible — typecheck and unit suite (52/52)
both pass against the new resolution. The caret range deviates from
the slice's strict-pin invariant (spec §7.1); revisit if reproducible
builds become an issue.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Vitest needs the node-ABI prebuilt sqlite binary; Electron 41 needs ABI 145.
Add `rebuild:node` / `rebuild:electron` scripts and wire them as
pre-hooks for `test`, `test:e2e`, `start`, `dev`, `test:integration`.
- Smoke test was racing on `firstWindow()`, which non-deterministically
returned the quickcapture window. Strip ELECTRON_RUN_AS_NODE from the
launch env, wait for both windows to register, then pick the inbox by
title and assert the heading via `getByRole`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two related runtime defects surfaced when first attempting
`npm run build` + Electron launch:
1. Renderer html files referenced `/src/.../main.tsx`, which
vite dev resolves but vite production rollup cannot. Changed
both inbox and quickcapture to `./main.tsx` (sibling-relative).
2. Electron 41's main-process module hook only injects the
real `electron` API into `require('electron')` calls inside
CommonJS modules. With package.json `"type": "module"` set,
electron-vite emitted ESM bundles that did
`import { app } from "electron"`; Node's ESM CJS-interop
then loaded the on-disk index.js (which exports the binary
path string) instead, leaving `app` undefined at startup.
Fix: drop `"type": "module"` so electron-vite emits CJS for
main + preload (renderer is unaffected — vite handles its own
ESM transform regardless). Source files keep modern import
syntax via the default-import + destructure pattern
(`import electron from 'electron'; const { app } = electron;`)
which transpiles correctly to `const { app } = require('electron')`
in the CJS output.
Also updated `electron-log/main` -> `electron-log/main.js`
because Node ESM strict resolution requires the `.js` extension
even though the package's CJS entry serves both.
Verification: `npm run build` produces 47-module renderer +
1005KB main bundle without errors. `npm run typecheck` clean.
Unit suite (52 tests) unaffected.
Plan deviation log: Task 4 (logger), Task 30 (main wiring), and
Tasks 17/18/22/30 referencing electron imports landed with named
imports per plan; this commit refactors them to default+destructure
without changing semantics.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds package.json, tsconfig.json, tsconfig.node.json,
electron.vite.config.ts, vitest.config.ts, .gitignore, and
package-lock.json. Verified Node 24.15.0 + npm 11.12.1 via Volta.
better-sqlite3 12.9.0 native build succeeded against VS 2022 +
Python 3.12.
Plan v0.4 had two install pin issues; adjusted live and logged
in plan Task 1 Step 2:
- electron-vite@2.3.0 + vite@6.0.3 ERESOLVE (peer ^4||^5).
Promoted build-tool chain: electron-vite 5.0.0, vite 7.3.2,
@vitejs/plugin-react 5.1.4 (vite@7 is the compatible overlap;
vitest@4.1.5 also accepts vite@7).
- @types/uuid@11.0.0 deprecated stub (uuid@11 ships own types);
removed from devDependencies.
Other deps installed at the planned exact pins. Step 8 sanity:
TypeScript 6.0.3, Vitest 4.1.5, Electron 41.3.0 (npm ls).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>