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>
This commit is contained in:
@@ -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 트리거.
|
||||
|
||||
368
docs/superpowers/specs/2026-05-06-v027-cross-platform-design.md
Normal file
368
docs/superpowers/specs/2026-05-06-v027-cross-platform-design.md
Normal file
@@ -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<TrayState> 패턴 그대로 활용 — 인터페이스 좁아질 뿐.
|
||||
|
||||
### 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.
|
||||
Reference in New Issue
Block a user