diff --git a/docs/superpowers/specs/2026-04-25-dogfood-feedback.md b/docs/superpowers/specs/2026-04-25-dogfood-feedback.md index af6d190..ad9efe1 100644 --- a/docs/superpowers/specs/2026-04-25-dogfood-feedback.md +++ b/docs/superpowers/specs/2026-04-25-dogfood-feedback.md @@ -1120,8 +1120,195 @@ Round 1 reviewer 의 발견 가치 = **production path 와 unit test 가 갈라 --- +## F14. macOS dock 클릭 시 hidden 창 재현 안 됨 (🌱 raw — v0.2.7 후보) + +**진행 상태:** 🌱 raw — 2026-05-05 v0.2.6 dogfood 발견. v0.2.7 brainstorm 후보. + +**발견:** 2026-05-05 김태현 macOS dogfood 도중. + +### 관찰 + +- macOS 에서 inbox 창 닫음 (빨간 신호등) → 창 사라짐. +- Dock 에는 Inkling 아이콘이 "켜져 있음" 표시 (점) 으로 그대로. +- Dock 아이콘 클릭 → **창이 안 뜸**. 클릭이 그냥 무시됨. +- 트레이 메뉴 "보관한 메모 보기" 로는 정상 호출 가능 (별 이슈 없음). +- 앱을 완전히 종료 후 재실행 해야만 창이 다시 뜸. + +### 제안 방향 + +추정 원인 (코드 확인 결과): + +- [src/main/windows/inboxWindow.ts:39-44](src/main/windows/inboxWindow.ts#L39-L44) — close 이벤트에서 `app.isQuitting === false` 면 `e.preventDefault()` + `inboxWindow.hide()`. 즉 창은 살아있고 단지 hidden. +- [src/main/index.ts:411-413](src/main/index.ts#L411-L413) — `app.on('activate', () => { if (BrowserWindow.getAllWindows().length === 0) createInboxWindow(); })`. 하지만 hidden 창은 destroy 되지 않았으므로 `getAllWindows().length === 1`. 분기 안 타고 no-op. + +따라서 fix 방향은 단순: + +```ts +app.on('activate', () => { + const win = getInboxWindow(); + if (win && !win.isDestroyed()) { + win.show(); + win.focus(); + } else { + createInboxWindow(); + } +}); +``` + +(B4 #46 second-instance 핸들러의 windows-restore 로직과 동일 패턴 — 거기서는 macOS dock 이 아닌 Windows multi-launch 경로지만 의도가 같음.) + +### 결정 대기 + +- macOS 에서 트레이 (menubar extra) 도 사용 중인가? Windows 에서 트레이가 핵심 surface 인 반면 macOS 에서는 dock 클릭이 자연스러운 1차 surface. +- 현재 macOS 빌드는 "기본 동작 유지" 수준 (메모리 우선순위 정책). dogfood 1차 타깃이 Windows 라 macOS 마찰을 어디까지 잡을지 cost-benefit 결정 필요. + +### 가설·측정 + +- Fix 후 macOS dogfood 시 dock click → 창 즉시 등장 (1 클릭, < 100ms 체감). +- regression 측정: Windows 에서 close→tray 메뉴 경로 영향 없음 (activate 이벤트는 macOS 전용 흐름이라 Windows 무관해야 함). + +### 범위 + +- 1-file edit (`src/main/index.ts` activate 핸들러 5줄). +- 단위 테스트 추가 어려움 (BrowserWindow + activate 이벤트 mocking 비용 ↑) — manual dogfood 검증 으로 충분. +- v0.2.7 telemetry export 와 함께 묶어 cut. + +### 영향 + +- macOS dogfood UX 마찰. "앱이 떠 있는데 안 보임 + 클릭 무반응" 은 사용자가 "고장났나?" 의심하게 만드는 첫 신호 — 신뢰 손상 큼. +- Windows 는 트레이 중심이라 동일 증상 없음. macOS 단독 이슈. +- v0.2.7 우선순위: F12 autostart 풀림 (Windows) 와 동급의 "잊지 않고 매일 쓰는" 흐름 마찰. + +--- + +## F15. Linux 앱 빌드 (🚀 promoted → v0.2.7 / CLI 부분 거부) + +**진행 상태:** 🚀 promoted (Linux 빌드만) → `docs/superpowers/specs/2026-05-06-v027-cross-platform-design.md` §5. CLI 부분은 ❌ rejected (DB/Ollama 동시접근 race + monorepo 부담 대비 본인 dogfood metric 직접 기여 적음). + +**발견:** 2026-05-05 dogfood 외부 피드백 + 본인 후속 결정. + +### 관찰 + +- Linux 터미널 사용자가 "Inkling 을 터미널에서 쓰고 싶다" 요청. +- 본인 macOS 흐름에서도 GUI quick-capture 띄우는 비용 > `ink "한 줄"` 한 방 비용. +- 현재 빌드 타겟: Windows NSIS x64 + macOS DMG arm64. Linux 타겟 자체 없음 → Linux 사용자에게 입구 자체 부재. + +### 결정된 방향 (narrow scope) + +**범위 (v0.2.7 narrow):** +- CLI **capture-only**: `inkling capture "한 줄"` 만 노출. search/recall/restore/edit 등 v0.3+ 로 deferred. +- 플랫폼: **Linux + macOS** (Windows CLI 제외 — 본인 Windows 는 GUI 흐름). +- Linux 앱 빌드 추가: **AppImage + deb** 1차. rpm 은 외부 demand 후. + +**아키텍처 — race-free 설계:** +- CLI = SQLite WAL writer 로 `notes` INSERT (raw_text) + `pending_jobs` INSERT (note_id) 만 수행. +- AI 워커는 **Electron 메인 단일 보유**. CLI 는 워커 안 띄움. +- Electron 떠있으면 → 워커가 즉시 pending_jobs poll → AI 처리. +- Electron 안 떠있으면 → 다음 launch 시 처리 (기존 pending_jobs 큐 모델 그대로). +- 동일 DB 파일 동시 접근은 SQLite WAL 로 안전 (1 writer + N readers). Single-instance lock 은 **Electron 인스턴스 끼리만** 적용 — CLI 는 짧은 transaction 만 수행 후 종료, lock 우회 무관. + +**플랫폼별 build 비용:** + +| 타겟 | 빌드 비용 | 커버 | +|---|---|---| +| AppImage | 매우 낮음 (Mac/Linux cross-build 가능) | 모든 desktop linux 배포판 (1-file portable) | +| deb | 낮음 (Mac brew `dpkg` `fakeroot`) | Debian/Ubuntu/Mint | +| rpm | 중간 (Linux 호스트 또는 Docker) — **defer** | Fedora/RHEL/openSUSE | + +**CLI 패키징:** +- pkg / nexe 로 Node CLI → 단일 바이너리. Linux + macOS 각각 빌드. +- 또는 Electron 앱 안에 `inkling` 심볼릭 링크 노출 (Mac: `/Applications/Inkling.app/Contents/MacOS/inkling`, Linux: AppImage 내 path 노출 / deb postinst hook). +- 결정 대기 — v0.2.7 brainstorm 때 spike. + +### 결정 대기 (v0.2.7 brainstorm) + +- CLI 패키징: 별도 단일 바이너리 vs Electron 앱 번들 내 노출 — install UX 영향 큼. +- AI 처리 시점 표기: capture 시 즉시 stdout 으로 "queued" 만 회신할지, `--wait` 플래그로 처리 완료 대기할지. +- AppImage + deb 동시 vs 단계적. + +### 가설·측정 + +- 본인 macOS 흐름에서 quick-capture window 호출 vs `ink "..."` time-to-capture 비교. 후자가 의미 있게 빠르면 본인 Aha metric (7일/3일) 에도 기여 가능. +- 외부 Linux 사용자 1주 soak 후 capture 발생 빈도 (telemetry) — 채널 살아있는지 확인. + +### 범위 + +- Linux 앱 빌드 + AppImage + deb: 1~2일. +- CLI capture-only (Mac/Linux 양쪽): 2~3일. +- better-sqlite3 prebuild 매트릭스 확장 (linux-x64): 부수 작업, 0.5일. +- 합 약 4~5일 spike — v0.2.7 cut 1개로 가능. + +### 영향 + +- 본인 macOS dogfood capture 가속 (직접 효용). +- Linux 사용자 입구 제공 (외부 확장 첫걸음). +- v0.4 slice 자기 종료 조건 (본인 2주 완주) 와 병행 가능 — capture 만 노출하므로 v0.4 핵심 흐름 (recall, AI tag, due) 변경 없음. +- Risk: Linux native ABI 첫 진입 — better-sqlite3 prebuild 가 linux-x64 에서 깔끔히 떨어질지 dogfood 검증 필요. + +--- + +## F16. 트레이 의존도 ↓ + 별도 설정 페이지 (🌱 raw — v0.2.7 후보, 광범위 영향) + +**진행 상태:** 🌱 raw — 본인 결정: "트레이 사용 최소화하자". v0.2.7 brainstorm 시 트레이 deemphasis 정책 + 설정 페이지 spec 합의 필요. + +**발견:** 2026-05-05 dogfood 후속 결정. + +### 관찰 + +- 현재 [src/main/tray.ts](src/main/tray.ts) 가 **13개 항목** 보유: 보관함 열기, 한 줄 적기, 백업, 내보내기, 복원, 동기화, telemetry export, Ollama 재확인, AI 재처리, **Ollama 설정...**, **자동 실행 토글**, 정보, 종료. +- Windows: SysTray 잘 보임 → 핵심 surface 로 기능했음. +- **macOS**: menubar extra 로 뜨지만 사용자가 메뉴바 가득찼을 때 가려짐. dock 사용자 흐름과 분리되어 발견성 ↓. +- **Linux**: 모던 GNOME 등 일부 DE 는 system tray 자체 없음 (extension 필요). KDE/Cinnamon 은 보임. +- 결과: macOS / Linux 사용자가 **Ollama 설정 / 자동 실행 토글 등 핵심 설정에 접근 불가**. + +### 결정된 방향 (정책 변화) + +**1. 트레이 = 최소 surface 로 강등.** +- 잔류: 한 줄 적기 (quick capture), 보관함 열기, 종료. +- 이동: Ollama 설정, 자동 실행, 백업/복원/내보내기, telemetry export, AI 재처리, Ollama 재확인, 정보 → **설정 페이지** 또는 inbox window 안 메뉴. + +**2. 별도 설정 페이지 신설 (inbox window 안 또는 별도 윈도우).** +- 예상 섹션: AI provider (Ollama endpoint/model — 기존 OllamaSettingsModal 흡수), 자동 실행, 백업/복원, 내보내기/가져오기, 텔레메트리, 정보. +- 현재 OllamaSettingsModal 은 inbox 안 modal — 그대로 활용하거나 페이지화 검토. + +**3. 1차 액션 진입점 재설계.** +- macOS: dock 클릭 (F14 fix 와 동시) → inbox 창 → 메뉴 또는 톱니바퀴 → 설정. +- Linux: 앱 launcher 또는 CLI (`inkling settings` 후보) → inbox 창 → 설정. +- Windows: 트레이 우클릭 "한 줄 적기" + "보관함 열기" 만 잔류 + 트레이에서 "설정..." 한 항목 추가 (inbox 안 설정 페이지로 라우팅). + +### 결정 대기 (v0.2.7 brainstorm) + +- 설정 surface 형태: + - (a) inbox 안 별도 라우트 (e.g., `/settings`) — SPA 내부 페이지 + - (b) 별도 BrowserWindow — 독립 윈도우 + - (c) 메뉴바 (Application Menu) 사용 — macOS 표준이지만 Win/Linux 와 일관성 깨짐 + - 추천 잠정: (a) — 최소 비용, 기존 inbox UI 연속성, OllamaSettingsModal 흡수 자연스러움. +- 트레이 잔류 항목: "설정..." 1줄 잔류 vs 완전 제거 (Windows 사용자 경험 시 trade-off). +- 자동 실행 토글의 실제 동작 — F12 deeper fix 가 설정 페이지 안에서 더 명확한 진단 노출 가능 (registry path 확인, args 미스매치 표시 등). + +### 가설·측정 + +- 새 사용자 (macOS) 가 Ollama endpoint 변경 작업 완료까지 클릭 수: 현재 (트레이 메뉴에 가려짐) vs 설정 페이지 (inbox → 설정) — 후자가 의미 있게 짧으면 채택. +- 트레이 메뉴 항목별 사용 빈도 telemetry — v0.2.7 export 후 실제 어떤 항목이 자주 클릭되는지 보고 잔류 우선순위 결정. + +### 범위 + +- 1~2일: OllamaSettingsModal 을 설정 페이지 섹션으로 흡수. +- 1~2일: 자동 실행 / 백업 / 복원 / 내보내기 등 트레이 click 핸들러를 설정 페이지 버튼으로 이동 (메인 IPC 는 그대로). +- 0.5일: 트레이 메뉴 슬림화 (3~4 항목으로). +- 합 3~5일. CLI (F15) 와 묶으면 v0.2.7 한 cut 가능. + +### 영향 + +- **macOS / Linux 입구 정상화** — F14 (dock 클릭) + F15 (CLI 입구) 와 정합. 외부 Linux 사용자 + 본인 macOS 모두 설정 접근 가능. +- **F12 autostart 영향**: 자동 실행 토글이 설정 페이지로 이동하면 진단 정보 (registry path, args 비교 결과) 노출 가능 → deeper fix 자연스럽게 결합. +- **트레이 코드 단순화**: 13 항목 → 3~4 항목. v0.2.6 의 TrayCallbacks 객체화 (C2) 효과 가시화. +- Risk: Windows 사용자 흐름 변경 — 트레이 한 클릭으로 끝나던 동작이 inbox 열기 → 설정 → 항목 클릭 으로 늘어남. 단, 빈도 낮은 동작 (Ollama 설정 변경, 백업 등) 만 이동하고 자주 쓰는 캡처/보관함 은 트레이 잔류 → 체감 마찰 ↓ 예상. + +--- + ## (다음 항목 자리) -새 피드백 추가 시 `## F14. 짧은 제목 (🌱 raw)` 헤더로 시작. 표준 슬롯 6개 채우거나 비워둔 채 시작 가능. +새 피드백 추가 시 `## F17. 짧은 제목 (🌱 raw)` 헤더로 시작. 표준 슬롯 6개 채우거나 비워둔 채 시작 가능. dogfood ≥1주 soak (v0.2.6 release 후) 동안 새 발견 항목들 여기 누적 → v0.2.7 brainstorm 트리거. diff --git a/docs/superpowers/specs/2026-05-06-v027-cross-platform-design.md b/docs/superpowers/specs/2026-05-06-v027-cross-platform-design.md new file mode 100644 index 0000000..27a5a5a --- /dev/null +++ b/docs/superpowers/specs/2026-05-06-v027-cross-platform-design.md @@ -0,0 +1,368 @@ +# v0.2.7 — Cross-Platform 입구 정상화 (Design) + +**작성일:** 2026-05-06 +**저자:** 김태현 (dlsrks0734@gmail.com) +**선행 문서:** + +- `docs/superpowers/specs/2026-04-25-dogfood-feedback.md` (F12, F14, F15, F16) +- `docs/superpowers/v024-backlog.md` (잔여 24건) +- `docs/superpowers/strategy/dogfood-strategy.md` (운영안) + +**Cut 라벨:** v0.2.7 (semver 엄밀히는 MINOR — 새 플랫폼 + 새 surface — 이지만 본 프로젝트 관습상 v0.2.x 를 feature lane 으로 사용 중이므로 v0.2.7 라벨 유지) + +--- + +## 1. Cut 정체성 + +**"Cross-platform 입구 정상화" cut.** F12 / F14 / F15 / F16 4개 항목을 한 묶음으로 처리. 핵심 동기: + +> Windows 트레이 의존을 끊고 macOS / Linux 사용자에게 동등한 입구를 제공한다. + +현재 13개 트레이 메뉴 항목이 macOS / Linux (특히 모던 GNOME) 에서 발견 / 접근성이 떨어져 핵심 설정 (Ollama endpoint, 자동 실행 등) 진입이 막히는 구조적 문제. 트레이를 deemphasis 하고 inbox 윈도우 안에 통합 설정 페이지를 둔다. 동시에 macOS dock 동작 정상화 (F14) + Linux 앱 빌드 추가 (F15 축소판) + 자동 실행 진단 노출 (F12 deeper fix) 까지 함께 처리한다. + +**의도적으로 빠진 것:** + +- ~~CLI (`inkling capture` 등)~~ — DB / Ollama 동시접근 race + monorepo 재구성 부담 대비 본인 dogfood metric 직접 기여 적음. v0.2.7 에서 제외. 외부 demand 누적 시 v0.3+ 재거론. + +--- + +## 2. 범위 + +| 항목 | 출처 | 작업 | +|---|---|---| +| **F15 (축소판)** | dogfood F15 | Linux 앱 빌드 (AppImage + deb x64) + better-sqlite3 prebuild linux-x64 매트릭스 | +| **F16** | dogfood F16 | 트레이 슬림 (13 → 4) + inbox 안 설정 페이지 (4 섹션) | +| **F14** | dogfood F14 | macOS dock 클릭 시 hidden 창 show/focus (activate 핸들러 5줄 수정) | +| **F12 deeper fix** | dogfood F12 (v0.2.6 진단 fallback 후속) | 설정 페이지 "자동 실행" 섹션 안에 진단 패널 노출 (withArgs vs noArgs / executableWillLaunchAtLogin / registry path) | + +--- + +## 3. Architecture 변화 + +| 영역 | 현재 (v0.2.6) | v0.2.7 | +|---|---|---| +| 설정 진입 | 트레이 메뉴 13개 항목 | 트레이 4개 + 설정 페이지 (inbox 내부 라우트) | +| Ollama 설정 | OllamaSettingsModal (트레이에서만 진입) | 설정 페이지 안 "AI 제공자" 섹션 (modal 흡수) | +| 자동 실행 | 트레이 checkbox + args 명시 | 설정 페이지 안 섹션 + 진단 패널 | +| macOS dock 클릭 | activate 핸들러 no-op (length===0 분기 못 탐) | `getInboxWindow().show() + focus()` 분기 추가 | +| Linux 배포 | 없음 | AppImage + deb 산출물 | +| 빌드 매트릭스 | win-x64 + mac-arm64 | + linux-x64 | + +--- + +## 4. 구현 순서 (Approach 2: Risk-reduction first) + +``` +1. Linux 빌드 (가장 unknown — better-sqlite3 prebuild linux-x64 검증) + ↓ AppImage + deb 산출 + Linux VM/WSL2 smoke test +2. 설정 페이지 (inbox 내부 라우트 + 4 섹션) + ↓ OllamaSettingsModal 흡수 +3. 트레이 슬림 (13 → 4) + ↓ 제거된 click 핸들러 → 설정 페이지 버튼으로 이동 +4. F14 macOS dock 클릭 fix + ↓ activate 핸들러 5줄 +5. F12 deeper fix (자동 실행 진단 노출) + ↓ IPC settings:autostart-state + 진단 panel UI +``` + +Linux 빌드를 먼저 두는 이유: native ABI 트랩 (메모 `project_inkling_status.md`) 이 linux-x64 에서 재발할 수 있음. 만약 prebuild 가 깔끔히 떨어지지 않으면 v0.2.7 scope 조정 (예: AppImage 만, deb 는 v0.2.8) 여유. 설정 페이지 / 트레이 슬림 / F14 / F12 는 모두 코드 작성 risk 가 낮은 영역이라 후순위로 안전. + +--- + +## 5. Linux 빌드 디테일 + +### 5-1. electron-builder config 추가 + +```json +"linux": { + "target": [ + { "target": "AppImage", "arch": ["x64"] }, + { "target": "deb", "arch": ["x64"] } + ], + "category": "Utility", + "synopsis": "로컬 메모 캡처 + AI 태그", + "description": "Inkling — 잠깐 스친 생각을 잡아두는 로컬-우선 메모 도구." +} +``` + +### 5-2. npm scripts 추가 + +```json +"predist:linux": "npm run rebuild:electron && npm run build", +"dist:linux": "electron-builder --linux --x64" +``` + +`rebuild:electron` 의 `--target=41.3.0` 그대로. `prebuild-install` 이 linux-x64 prebuild 를 npm 레지스트리에서 받아오는지 검증. 없으면 `node-gyp` fallback 으로 로컬 컴파일. + +### 5-3. 빌드 호스트 전략 + +**1차: macOS 호스트** (이미 DMG 빌드 호스트). brew 로 도구 설치: + +```bash +brew install dpkg fakeroot +``` + +electron-builder 가 cross-build 지원. AppImage 는 Mac 에서 직접 빌드 가능 (Linux 유저랜드 도구만 필요한 부분은 electron-builder 내장 + AppImageKit 자동 다운로드). deb 는 dpkg-deb 필요. + +**Fallback (1차 실패 시): Docker on Mac/Windows.** `electronuserland/builder` 이미지로 Linux 빌드 환경 격리. v0.2.7 scope 안에서 결정. + +### 5-4. Smoke test + +`dist/` 산출물: + +- `Inkling-0.2.7.AppImage` (x64) — Linux VM 또는 WSL2 에서 chmod +x → 실행 → 마이그레이션 통과 확인 → capture / recall 한 사이클. +- `inkling_0.2.7_amd64.deb` — Ubuntu/Debian VM 또는 WSL2 에서 `sudo dpkg -i` → `inkling` 실행 → 동일 검증. + +검증 항목: + +1. better-sqlite3 native module 로드 성공 (마이그레이션 0 → m003 통과) +2. Ollama 연결 시도 (settings.json 의 endpoint 또는 `INKLING_OLLAMA_ENDPOINT` env) — 본인 LAN 서버 `http://192.168.0.47:11434` 사용 +3. capture 한 줄 → AI 처리 → tag 표시 +4. 트레이 (KDE/Cinnamon DE 가정) 4 항목 표시 +5. 트레이 없는 DE (모던 GNOME) — launcher 에서 앱 실행 → inbox 윈도우 → 톱니바퀴 → 설정 페이지 진입 + +--- + +## 6. 설정 페이지 디테일 + +### 6-1. 라우팅 방식 + +React Router 도입 안 함 (의존성 + 학습 비용). zustand store 의 `view: 'inbox' | 'trash' | 'settings'` state + 조건부 렌더 — 기존 trash view 와 동일 패턴. 새 의존성 0. + +### 6-2. 진입점 + +| 진입 | 동작 | +|---|---| +| 트레이 "설정..." 클릭 | main → IPC `inbox:navigate` 'settings' → renderer store action `setView('settings')` + inbox 윈도우 show/focus | +| inbox 헤더 톱니바퀴 아이콘 | renderer store action `setView('settings')` | +| 설정 페이지 안 "← 돌아가기" 버튼 | `setView('inbox')` | + +### 6-3. 섹션 4개 + +#### 6-3-1. AI 제공자 + +흡수 대상: OllamaSettingsModal 전체 + 트레이 "Ollama 재확인". + +UI 요소: + +- Endpoint URL 입력 (zod 검증 — 기존 modal 의 `safeParse` 재활용) +- Model 입력 (빈 값 guard) +- "지금 재확인" 버튼 → ProviderHolder 의 health check trigger +- 마지막 ping 결과 표시 (성공 시각 또는 실패 사유) +- "기본값으로 되돌리기" 버튼 + +저장: 기존 SettingsService (atomic temp+rename + zod) 그대로. + +#### 6-3-2. 자동 실행 + +흡수 대상: 트레이 "윈도우 시작 시 자동 실행" checkbox. + +UI 요소: + +- 토글 ("앱 시작 시 자동으로 실행") +- 진단 패널 (펼치기 가능 — 평소엔 접혀 있음) +- "재등록" 버튼 (setLoginItemSettings 강제 재호출) + +진단 패널 디테일은 §9 (F12 deeper fix) 참조. + +#### 6-3-3. 백업 / 복원 / 내보내기 + +흡수 대상: 트레이의 5개 항목 — "지금 백업" / "내보내기..." / "백업에서 복원..." / "지금 동기화" / "사용 로그 내보내기...". + +UI 요소: 5개 버튼 + 각 작업 마지막 실행 시각 (가능하면) + 결과 toast. + +IPC 핸들러는 기존 그대로 — 트레이 click 핸들러였던 함수를 IPC 핸들러로 등록 + renderer 에서 invoke. + +#### 6-3-4. 정보 + +흡수 대상: 트레이 "Inkling 정보..." dialog. + +UI 요소: 버전 / Electron / Node / OS / 데이터 위치 텍스트 + "데이터 위치 열기" 버튼 + "정보 복사" 버튼. + +기존 `showAboutDialog` 의 detail 문자열 그대로 활용 — clipboard.writeText / shell.openPath 호출도 동일. + +### 6-4. 제외 항목 + +- "지금 AI 처리 (실패 N건)" — 이미 inbox FailedBanner 가 surface. 트레이 / 설정 둘 다 제거. +- "Ollama 재확인" 트레이 메뉴 단독 — OllamaBanner (끊김 시) + 설정 페이지 AI 섹션 "지금 재확인" 버튼이 surface. 트레이 단독 메뉴 제거. + +--- + +## 7. 트레이 슬림 디테일 + +### 7-1. 잔류 4개 (Win / Mac / Linux 동일) + +```ts +items.push({ label: '한 줄 적기', click: cb.showCapture }); +items.push({ label: '보관한 메모 보기', click: cb.showInbox }); +items.push({ type: 'separator' }); +items.push({ label: '설정...', click: cb.showSettings }); +items.push({ type: 'separator' }); +items.push({ label: '종료', click: () => { app.isQuitting = true; app.quit(); } }); +``` + +todayCount tooltip (`Inkling — 오늘 N`) 잔류. F4-C 의 "오늘 N번 잡아둠" 비활성 라벨도 잔류 (정체성 신호). + +### 7-2. TrayCallbacks / TrayState 갱신 + +```ts +export interface TrayCallbacks { + showInbox: () => void; + showCapture: () => void; + showSettings: () => void; // NEW — IPC 'inbox:navigate' 'settings' 송출 +} + +// 메뉴 영향 state 슬림 +export interface TrayState { + todayCount: number; +} +``` + +**제거 대상:** + +- `runBackup`, `runExport`, `runImport`, `runSync`, `runExportTelemetry` callback (5개) → 설정 페이지 버튼으로 이동 +- `runOllamaRecheck`, `runRetryAllFailed`, `runOpenOllamaSettings` callback (3개) → 설정 페이지 또는 banner 로 이동 +- `ollamaOk`, `failedCount` state field (2개) → 트레이 메뉴 영향 사라짐 (banner 가 surface) +- `refreshTray({ ollamaOk })`, `refreshTray({ failedCount })` 호출부 (HealthChecker, AiWorker) → 제거. todayCount 만 남음. + +v0.2.6 의 Partial 패턴 그대로 활용 — 인터페이스 좁아질 뿐. + +### 7-3. 자동 실행 토글 트레이 잔류 X + +기존 트레이 안 checkbox (`type: 'checkbox'`) 는 제거. 설정 페이지 "자동 실행" 섹션 토글이 단일 진입점. + +이유: 자동 실행 토글은 빈도 낮은 액션 + F12 진단이 같은 자리에 있어야 의미. 트레이 잔류 시 두 surface mismatch 위험. + +--- + +## 8. F14 macOS dock 클릭 fix + +[src/main/index.ts:411-413](src/main/index.ts#L411-L413) 수정: + +```ts +app.on('activate', () => { + const win = getInboxWindow(); + if (win && !win.isDestroyed()) { + if (!win.isVisible()) win.show(); + win.focus(); + } else { + createInboxWindow(); + } +}); +``` + +second-instance 핸들러 (B4 #46) 와 패턴 일치 — 양쪽 모두 "살아있으면 show, 죽었으면 create". + +테스트: BrowserWindow + activate 이벤트 mocking 비용 ↑ → manual dogfood 검증으로 충분 (macOS 빨간 신호등 → dock 클릭 → 즉시 창 등장). + +--- + +## 9. F12 deeper fix — 자동 실행 진단 노출 + +### 9-1. 정보 모델 + +```ts +// 신규 IPC: settings:autostart-state +interface AutostartState { + withArgs: { openAtLogin: boolean; executableWillLaunchAtLogin: boolean }; + noArgs: { openAtLogin: boolean; executableWillLaunchAtLogin: boolean }; + execPath: string; // process.execPath + registryPath?: string; // Windows only + registryValue?: string; // Windows only — null 또는 string +} +``` + +### 9-2. main process 핸들러 + +```ts +ipcMain.handle('settings:autostart-state', async () => { + const withArgs = app.getLoginItemSettings({ args: ['--hidden'] }); + const noArgs = app.getLoginItemSettings(); + const state: AutostartState = { + withArgs: { + openAtLogin: withArgs.openAtLogin, + executableWillLaunchAtLogin: withArgs.executableWillLaunchAtLogin + }, + noArgs: { + openAtLogin: noArgs.openAtLogin, + executableWillLaunchAtLogin: noArgs.executableWillLaunchAtLogin + }, + execPath: process.execPath + }; + if (process.platform === 'win32') { + state.registryPath = 'HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run\\Inkling'; + state.registryValue = await readRegistryValueSilent(state.registryPath); + } + return state; +}); +``` + +`readRegistryValueSilent`: `child_process.execFile('reg', ['query', path, '/v', 'Inkling'])` 1회. 실패 시 null 반환 (silent fallback — 사용자에 에러 노출 X). + +새 dependency 추가 X (`winreg` 등 X) — built-in `child_process` + Windows `reg.exe` 만 활용. + +### 9-3. UI + +설정 페이지 "자동 실행" 섹션: + +``` +[ ] 앱 시작 시 자동으로 실행 + 상태: ✅ 등록됨 / ⚠️ 등록 안 됨 / ⚠️ args 미스매치 + ▾ 진단 정보 (펼치기) + - 표준 조회 (args 명시): openAtLogin=true, willLaunch=true + - 비교 조회 (args 없이): openAtLogin=false, willLaunch=true ← mismatch ⚠️ + - 실행 파일 경로: /Applications/Inkling.app/Contents/MacOS/Inkling + - registry 경로 (Windows): HKCU\...\Run\Inkling + - registry 값: "C:\Users\...\Inkling.exe" --hidden + [ 재등록 ] 버튼 +``` + +### 9-4. dogfood 시나리오 + +1. 토글 ON → 재시작 → 풀려있으면 진단 패널 펼침. +2. withArgs vs noArgs mismatch 보임 → args canonicalization 문제 확인. +3. registry 값 vs execPath 비교 — 다르면 path canonicalization 문제 (NSIS 재설치 시 path 바뀜). +4. "재등록" 버튼 → setLoginItemSettings 재호출 → 다시 재시작 → 효과 측정. + +수집된 데이터로 v0.2.8 root cause fix 작성. + +--- + +## 10. 테스트 전략 + +| 영역 | 단위 | e2e | Manual dogfood | +|---|---|---|---| +| Linux 빌드 (F15) | - | - | AppImage + deb 산출 + Linux VM 실행 + 마이그레이션/캡처/recall 한 사이클 | +| 설정 페이지 라우팅 | zustand store action `setView('settings')` 단위 | (선택) 트레이 "설정..." → IPC → view 전환 e2e | 실제 클릭 흐름 | +| Ollama 섹션 흡수 | 기존 OllamaSettingsModal 단위 + 흡수 후 회귀 | - | 1회 | +| 자동 실행 진단 IPC | autostart-state 핸들러 단위 (mock electron API + child_process) | - | Win 토글 → 재시작 → 진단 패널 mismatch 검출 | +| 트레이 슬림 | tray.ts buildMenu 단위 (4 항목 검증 + 제거된 항목 부재) | - | - | +| F14 dock fix | (mock 비용 ↑) — manual 만 | - | macOS dock 클릭 | +| F12 진단 UI | mismatch 시 ⚠️ 렌더 단위 | - | F12 시나리오 재현 | + +**목표**: 단위 426 → 약 450 (+24), e2e 1 유지 또는 +1. + +--- + +## 11. Risk / Known unknowns + +| Risk | 발생 시 대응 | +|---|---| +| linux-x64 prebuild 부재 → node-gyp 빌드 실패 | Docker `electronuserland/builder` fallback. 그래도 실패 시 v0.2.7 scope 조정: AppImage 만, deb 는 v0.2.8. | +| ELECTRON_RUN_AS_NODE 함정 (메모) 가 Linux 환경에서 재현 | smoke test launch env 에서 strip — 기존 e2e 의 strip 패턴 그대로 | +| AppImage 가 모던 GNOME 에서 트레이 표시 안 됨 | 의도적 — 그래서 dock/launcher → inbox → 설정 페이지 흐름이 안전망. F14 fix 가 이 흐름의 핵심. | +| 설정 페이지 라우팅이 inbox 의 keyboard shortcut / hotkey 와 충돌 | view='settings' 시 inbox-only shortcut 비활성. zustand state 분기. | +| 자동 실행 진단 패널이 Mac/Linux 에선 의미 없는 정보 노출 | 플랫폼 분기 — Mac/Linux 는 registry 행 숨김 + executableWillLaunchAtLogin 만 표시 | +| 트레이 callback 8개 제거 시 import 그래프에서 dead code 잔존 | 제거 후 typecheck + grep 으로 검증 | + +--- + +## 12. v0.2.7 후 + +**잔여 backlog (24건)** — `docs/superpowers/v024-backlog.md`: + +- v0.2.6 final reviewer minor cleanup 6건 — kstDate 의미 정정 / NoteRepository.test.ts as any / store.ts trashCount race 등 +- telemetry data-dependent 14건 — VOCAB_TOP_N 튜닝, recallBanner 임계값 등 — v0.2.8 후보 (v0.2.7 dogfood soak ≥1주 후 telemetry export 누적) +- v0.2.7 본 cut 안 신규 발견 — F12 root cause 가 진단 데이터 누적 후 결정될 가능성 + +**v0.2.8 트리거**: v0.2.7 release 후 dogfood ≥1주 soak + telemetry export + F12 진단 데이터 → v0.2.8 brainstorm.