- F24 promoted (✅ v0.3.1 Cut F — Ollama vision 모델 capability detection + AiWorker integration)
- version 0.3.0 → 0.3.1 (semver patch — 새 기능, 기존 영향 X)
- 단위 679 → 710 (+31): VisionDetect 9 + SettingsService 4 + visionPrompt 2 + LocalOllamaProvider vision 3 + AiWorker vision 3 + IPC 5 + UI 4 + ImportService helper fix 5 (Cut E gap)
- typecheck 0 errors
- 자동 fallback (caption→text) + 'skipped' enum deferred v0.3.2+
112 KiB
Dogfood 피드백 수집
작성일: 2026-04-25 (open, ongoing — v0.4 slice → v0.2.x cuts 까지 누적) 최종 갱신: 2026-05-05 (v0.2.6 정식 cut 후, F8~F13 dogfood 발견 추가) 저자: 김태현 (dlsrks0734@gmail.com) 문서 성격: v0.4 slice → v0.2.x cuts 동안 누적된 본인 dogfood 피드백 수집·정제 living document. 각 항목은 후속 spec/cut 으로 승격될 후보다.
선행 문서:
docs/superpowers/specs/2026-04-24-inkling-vertical-slice-design.mdv0.4 (슬라이스 본문)docs/superpowers/specs/2026-05-01-v023-feedback-roadmap-design.md(v0.2.3 7항목 cut 로드맵)docs/superpowers/strategy/strategy.md(심리학 전략)docs/superpowers/strategy/dogfood-strategy.md(dogfood 운영안)docs/superpowers/v024-backlog.md(PR review deferred + dogfood 발견 누적 backlog, 잔여 24건)
진척 흐름 요약 (2026-05-05 기준)
본 문서가 작성된 v0.4 slice 시점 이후 흐름:
| 시점 | Cut | 주요 피드백 / 발견 |
|---|---|---|
| 2026-05-01 | v0.2.3 7항목 roadmap (PR #13~#19) | v0.2.2 dogfood 발견 6건 (memory/project_v022_feedback.md) → telemetry skeleton + 휴지통 + 만료 추천 + Ollama 회복 + AI retry + 태그 vocab + RecallBanner |
| 2026-05-04 | v0.2.3.1 (PR #21) → v0.2.4 (PR #22, semver 우회) | F8 11434 reserved, F9 multi-instance, F10 버전 정보 부재 |
| 2026-05-05 | v0.2.5 critical hotfix (PR #23) | F11 single-instance lock 부재 (critical, 해결됨) |
| 2026-05-05 | v0.2.6 정식 cut (PR #24) | F12 autostart 풀림, F13 hidden-start race (해결됨) |
v0.2.7 brainstorm 트리거: dogfood ≥1주 soak 후 telemetry export + 신규 피드백 + 잔여 backlog 24건 일괄 triage.
0. 사용 규칙
- 새 피드백은 다음 번호 (
F<N>) 로 추가. 절대 기존 번호 재사용 금지 (외부 링크 안전성). - 각 항목 상단에 상태 라벨 한 줄:
- 🌱 raw — 막 적은 관찰. 가공 안 됨.
- 🔬 drafting — 범위·가설·결정 대기 항목 분석 중.
- 📝 ready-for-spec — 정식 spec 으로 승격 가능. 다음 단계는 별도 파일 추출.
- 🚀 promoted — 별도 spec 파일로 분기 완료. 본 문서엔 요약 + 링크만.
- ❌ rejected — 가설 미달 또는 우선순위 외, 닫음.
- 각 항목의 표준 슬롯: 관찰 / 제안 방향 / 결정 대기 / 가설·측정 / 범위 / 영향. 슬롯이 비어 있으면 비워두고 채워질 때 갱신.
F1. Due Date 추출 (🚀 promoted)
진행 상태: 🚀 promoted → docs/superpowers/specs/2026-04-26-f1-due-date.md
발견: 2026-04-25 dogfood 시작 직전 사고 실험.
관찰
캡처된 노트 본문에 오늘, 내일, 이번 주, 다음 주, 다음 달, N일 뒤, N월 N일, 금요일까지 같은 시간 표현이 자주 들어간다. 현재 슬라이스는 이걸 그냥 평문 본문에 두고 끝. 사용자는 노트가 "언제까지 해야 하는 일" 인지 다시 본문을 읽어 파악해야 한다.
제안 방향
하이브리드 — 규칙 파서 1차, AI 위임 2차.
입력 텍스트
↓
규칙 파서 (정규식 + KST 변환)
↓
매칭 있음? ──→ ISO YYYY-MM-DD + confidence: high
│
└─ 시간 후보 어휘 감지 + 매칭 없음 ──→ AI 프롬프트에 due_date 필드 추가
↓
AI 응답에 ISO 있음? ──→ confidence: medium
AI 응답 비었음? ──→ due_date null
규칙 파서는 결정론적·테스트 쉬움. AI 위임은 같은 generate 응답에 필드만 추가 — 별도 호출 없음. UI 라벨은 작은 회색 📅 YYYY-MM-DD, AI 라벨 정책과 동일하게 사용자 편집 시 진해지고 라벨 사라짐 (Strategy §7-원칙4 "AI 확신도 낮게").
결정 대기
- 시간 표현이 들어간 노트 비율 — 누적 50건 표본 분류 (가설 H1)
- "오늘 PR 리뷰" 같은 노트의 due 가 정말 오늘인가, 단순 맥락어인가? false positive 비율
- due_date 가 있는 노트의 재방문 트리거 — Inbox 정렬 / 별도 뷰 / 알림 중 어디
- NoteCard 의 라벨 슬롯 위치 — 제목 옆, 태그 옆, 별도 줄
- 만료된 노트 처리 — 자동 done ❌, 자동 삭제 ❌, 시각적 표시만? 별도 필터?
- 음력·"월말"·"주말 안에" 등 모호 표현은 AI 위임만으로 충분한가
가설·측정
| # | 가설 | 측정 |
|---|---|---|
| H1 | 누적 캡처 노트 중 시간 표현 포함 비율 ≥ 30% | 표본 50건 본인 라벨링 |
| H2 | 규칙 파서가 일상 한국어 시간 표현의 ≥ 80% 정확 변환 | 골든 픽스처 50건 + 단위 테스트 |
| H3 | due_date 후보 수락률 ≥ 60% | 정식 출시 후 측정 |
H1 이 미달이면 본 항목 ❌ rejected.
범위
- In:
오늘/내일/모레,이번/다음 주,다음 달,N일·주·개월 뒤,N월 N일,MM/DD,YYYY-MM-DD, KST 자정 기준 - Out: 시각 단위 (
오후 3시), 음력·절기, 반복 일정 (매주 월요일), 외부 캘린더 연동
영향
- Schema: migration v2 —
notes.due_date TEXT,notes.due_date_edited_by_user INTEGER NOT NULL DEFAULT 0 - NoteRepository:
updateAiResult시그니처에dueDate?: string | null, edited-flag CASE WHEN 가드. 신규setDueDate(noteId, date) - AI: zod 스키마에
due_date: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).nullable().optional(), 프롬프트 끝에 "추출 가능하면 ISO, 아니면 null" +{{TODAY_KST}}주입 - Renderer: NoteCard 라벨 슬롯, EditableField 재사용, 만료 시 회색 + 취소선 (단어는 "실패"/"지각" 금지 — slice §1.1 카피 정책)
- Lib: 외부 의존성 0 권장. 자체 정규식 + Intl.DateTimeFormat. ContinuityService 의 KST 헬퍼 재사용
골든 픽스처 후보
"오늘 PR 리뷰" → null 또는 today (양가)
"내일 회의 준비" → tomorrow
"다음 주 월요일까지 슬라이드" → next-mon
"3일 뒤 데모" → today+3
"5월 1일 휴가 신청" → 2026-05-01
"이번 주 안에 리팩터링" → 이번 주 일요일
"월말 마감" → 해당 월 말일 (AI 위임)
"주말까지" → 이번 주 일요일 (AI 위임)
"퇴근 전" → today (시각 단위 fallback)
각 케이스의 confidence + 가설 행동(수락/편집/무시) 라벨링이 H2/H3 측정의 근거.
F2. 태그 클릭 = 즉시 삭제 + undo 부재 (🚀 promoted)
진행 상태: 🚀 promoted → docs/superpowers/specs/2026-04-26-f2-tag-click.md
발견: 2026-04-25 dogfood 중. 슬라이스 v0.4 동작.
관찰
NoteCard.tsx:110 에서 태그 칩의 onClick 이 removeTag(t.name) 으로 묶여 있다. 즉시 DB 에 반영되고, 확인 다이얼로그도 undo 도 없다. hover title 은 "클릭으로 제거" 로 의도된 동작이지만, 사용자는 태그 UI 의 일반적 관행 (클릭 = 동일 태그 노트 필터링) 을 기대했다.
문제 두 갈래:
- 기능 부재: "이 태그를 가진 노트만 보기" 가 슬라이스에 없음. 사용자 멘탈 모델과 어긋남.
- 데이터 손실 마찰: 평범한 클릭 한 번으로 AI 가 만든 태그가 사라지는데 되돌릴 수 없음. 슬라이스 §1.1 의 "AI 라벨 → 사용자 편집으로 전환" 정체성 흐름과도 충돌 — 삭제는 편집이 아니라 파괴.
제안 방향
세 동작을 분리한다.
| 동작 | 트리거 | 결과 |
|---|---|---|
| 필터 | 짧은 클릭 | Inbox 가 동일 태그 노트만 표시 (헤더에 "필터: #tag · 해제" 칩) |
| 편집 | 칩 더블클릭 또는 칩 우측 작은 ✕ 아이콘 | 태그 이름 인라인 편집 또는 단일 태그 제거 |
| 재추가 (undo) | 방금 제거한 직후 토스트 "태그 'foo' 를 제거했습니다 · 되돌리기" 5초 노출 | 클릭 시 즉시 복원 |
권장 1차 패치 (작음): 클릭 = 필터로 변경 + 칩에 ✕ 아이콘 추가 (✕ 클릭 시 confirm 또는 5초 undo 토스트). 필터는 zustand 상태에 tagFilter: string | null 추가 + Inbox 의 notes.filter 단계 한 줄.
권장 2차 (별 spec): 다중 태그 필터 (AND/OR), 태그 편집 (rename / merge), 태그 단위 일괄 작업.
결정 대기
- 클릭 = 필터 라는 가정이 dogfood 본인에게도 성립하는가? — 본인 예상 동작 한 번 더 셀프 체크
- AI 태그 vs 사용자 추가 태그 클릭 동작이 같아야 하는가, 달라야 하는가?
- undo 토스트의 dismissal 정책 — 5초 자동 사라짐 vs 다음 작업까지 유지
- 필터링 시 Continuity 배지·Pending 배너의 카운트는 전체 기준인가, 필터된 부분 기준인가?
- 태그 단일 제거 외에 "이 태그가 붙은 모든 노트에서 제거" 같은 일괄 작업도 묶을지 — 별 spec 으로 분리 권장
가설·측정
| # | 가설 | 측정 |
|---|---|---|
| H1 | 슬라이스의 현재 "클릭 = 삭제" 가 본인 dogfood 에서 ≥ 1회 실수 유발 | 일일 로그의 마찰 사건 |
| H2 | 클릭 = 필터로 바꾸면 본인이 태그를 통해 과거 노트를 재방문하는 빈도 ≥ 주 1회 | 사용 로그 |
| H3 | undo 토스트가 있으면 의도된 태그 제거의 인지 부담 감소 | 정성 평가 |
범위
- In: 단일 태그 클릭 동작 변경, 단일 태그 제거 시 undo, Inbox 의 단일 태그 필터
- Out: 다중 태그 필터, 태그 rename / merge, 태그 단위 일괄 작업, 태그 자동완성
영향
- Schema: 없음 (이 패치 자체는 DB 변경 없음. 일괄 작업이 들어오면 별 spec)
- Renderer:
NoteCard.tsx의 칩onClick변경, 칩 우측 ✕ 아이콘 추가, InboxApp.tsx에 필터 상태 + 헤더 칩, undo 토스트 컴포넌트 (RecoveryToast 패턴 재사용 가능) - Store: zustand
tagFilter상태 +setTagFilter,notes셀렉터에 필터 적용 - API: 변경 없음 (필터는 클라이언트 사이드만)
- 카피: 슬라이스 §1.1 "실패"/"끊김"/"연속 실패" 금지 정책 그대로. undo 토스트 문구는 "되돌리기" / "방금 제거" 같은 중립 표현
F3. "구출" 카피가 한국어로 어색함 (🚀 promoted)
Promoted → docs/superpowers/specs/2026-04-26-f3-f4e-copy.md (F4-E 와 함께 한 PR)
발견: 2026-04-26 dogfood 첫날, 메모 1건 캡처 후 OS 토스트 알림에서 "방금 하나의 업무 기억을 구출했습니다" 문구가 떴을 때.
관찰
구출(rescue) 은 한국어 일상어로 거의 쓰이지 않는다. 인질·재난 맥락에서 주로 쓰이는 어휘라서 "메모 한 줄 적었더니 구출됐다" 라는 표현이 어색하게 들린다. 영어 원문 의도(rescue a thought before you lose it) 를 직역한 결과로 추정.
현재 "구출" 등장 표면 (코드 경로 기준):
| # | 표면 | 위치 | 문구 |
|---|---|---|---|
| 1 | OS 토스트 (회전 카피 4종 중 3번째) | src/main/services/NotificationService.ts:6 |
방금 하나의 업무 기억을 구출했습니다. |
| 2 | 트레이 메뉴 | src/main/tray.ts:13 |
기억 구출하기 |
| 3 | 트레이 메뉴 | src/main/tray.ts:12 |
구출한 메모 보기 |
| 4 | Inbox 빈 상태 | src/renderer/inbox/App.tsx:44 |
첫 기억을 구출해보세요. |
| 5 | QuickCapture 힌트 | src/renderer/quickcapture/App.tsx:68 |
Ctrl+Enter 구출 · Esc 취소 · 이미지 붙여넣기 |
추가 영향 표면 (코드 외):
package.jsondescription: "Inkling — local-first 기억 구출 도구"tests/e2e/smoke.spec.ts:29의 단언await expect(inbox.getByText('첫 기억을 구출해보세요.')).toBeVisible()docs/superpowers/specs/2026-04-24-inkling-vertical-slice-design.md§5.5 의 카피 테이블 (519~523행)docs/superpowers/strategy/strategy.md의 §1, §3 — "메모 작성 → 기억 구출" 으로 핵심 행동을 재정의한 전략적 선언 그 자체
제안 방향
카피 변경 + strategy 문서의 어휘 결정 재검토를 한 항목으로 묶음.
대체 후보 (전략 의도 보존도 vs 자연스러움 트레이드오프):
| 후보 | 의도 보존 | 자연스러움 | 비고 |
|---|---|---|---|
| 꺼내 놓기 | 중 | 상 | "머릿속에서 꺼낸다" 직관, 기존 strategy "꺼내는 1회 행동" 표현과 일치 |
| 잡아두기 | 중 | 상 | "잊기 전에 잡아둔다" 어감, 가벼움 |
| 한 줄 던지기 | 상 | 상 | 슬라이스 §1.1 "3초 안에 던지고" 표현 그대로. 캡처 행위에 적합 |
| 남겨두기 | 하 | 상 | 평이함, 의도성 약함 |
| 적어두기/메모하기 | 하 | 상 | 전략 의도 상실 ("메모 작성" 회귀) |
| 챙겨두기 | 중 | 상 | 알림 카피에 자연 ("하나 챙겨뒀습니다") |
| (현행) 구출 | 상 | 하 | 어색함 |
권장 1차안 — 표면별 다른 동사 허용 (한 단어로 통일 강제 안 함):
| 표면 | 권장 카피 |
|---|---|
| 토스트 회전 카피 #3 | 방금 한 줄 잡아뒀습니다. 또는 머릿속에서 한 줄 꺼내뒀습니다. |
| 트레이: 새 메모 | 한 줄 적기 또는 빠르게 한 줄 |
| 트레이: Inbox 열기 | 보관한 메모 보기 또는 Inkling 열기 |
| 빈 상태 | 첫 한 줄을 던져보세요. 또는 머릿속에 떠다니는 한 줄을 적어보세요. |
| QC 힌트 | Ctrl+Enter 저장 · Esc 취소 · 이미지 붙여넣기 |
핵심: "구출" 의 행동적 의미("정리·작성이 아니라 머릿속에서 꺼내기만") 는 보존하되, 직역체 한 단어로 강제하지 않고 표면별 자연 문맥에 맞춰 동사를 분배.
결정 대기
- Strategy 문서 §1, §3 의 "기억 구출" 선언을 함께 수정할 것인가? — "구출" 은 단순 UI 카피가 아니라 전략 어휘다. 카피만 바꾸면 strategy 와 코드가 어긋난다. 같이 바꾸려면 strategy.md §1·§3·§7 갱신 + "꺼내기" / "한 줄" 같은 새 키워드 정의.
- 단일 동사로 통일할 것인가, 표면별 자연어로 분배할 것인가? — 통일은 브랜딩 자산, 분배는 자연스러움.
- 제품명 표어 ("local-first 기억 구출 도구") 는 어디까지 따라가는가? —
package.json description, GitHub README 첫 문단, 향후 onboarding 문구 모두 영향. - e2e smoke 의 단언 문구 변경 시 카피 freeze 관행을 도입할지 — 카피 변경마다 e2e fix 가 따라오면 마찰 큼. 단언을 더 약하게 (
getByRole('main')등) 잡거나 카피 상수 import 가 대안. - 캡처-보상 카피 4종 중 #1, #2, #4 (
이 생각은 이제 Inkling이 들고 있습니다./나중에 찾을 수 있게 보관했습니다./기록 완료. 이제 잊어도 됩니다.) 는 그대로 유지해도 자연스러우니 #3 만 교체로 충분한가? 아니면 전체 톤 재정렬?
가설·측정
| # | 가설 | 측정 |
|---|---|---|
| H1 | 본인 dogfood 1주 누적 시 "구출" 표현에 대한 위화감 토스트/메뉴 노출당 ≥ 1회 보고 | 일일 dogfood 로그의 카피 마찰 항목 |
| H2 | 권장안 적용 시 카피 위화감 보고 0건/주로 감소 | 동일 로그 |
| H3 | 외부인(가족·동료) 1명에게 권장안 vs 현행 블라인드 비교 시 권장안이 자연스럽다고 답함 | 정성 1회 |
범위
- In:
NotificationService.REWARD_COPIES의 #3 교체- 트레이 메뉴 라벨 2개
- Inbox 빈 상태 + QuickCapture 힌트
package.json description- smoke spec 단언 문구 동기화
- 카피 테이블 (
2026-04-24-inkling-vertical-slice-design.md§5.5) - strategy.md §1·§3·§7 의 "기억 구출" 어휘 결정 동시 갱신 여부 결정
- Out:
- 회전 카피 4종 전면 재작성 (필요하면 별 항목으로 분리)
- onboarding 흐름 (슬라이스 외)
- 로고·앱 아이콘 텍스트
- 다국어 (영어 카피)
영향
- Schema: 없음
- 코드:
src/main/services/NotificationService.ts— 회전 카피 한 줄src/main/tray.ts— 메뉴 라벨 2곳src/renderer/inbox/App.tsx— 빈 상태 문구src/renderer/quickcapture/App.tsx— 힌트package.json— descriptiontests/e2e/smoke.spec.ts— 단언 문구 (또는 셀렉터 약화)
- 문서:
docs/superpowers/specs/2026-04-24-inkling-vertical-slice-design.md카피 테이블docs/superpowers/strategy/strategy.md— 결정 대기 #1 결과에 따라 부분 또는 전면- 본 문서 — promoted 시 별 spec 으로 추출
메모
이 항목은 strategy 문서와의 어휘 일관성 결정이 함께 묶여 있어서, 단순 카피 PR 로 끝낼지 / strategy 재검토 미니 spec 으로 승격할지 결정 대기 #1 의 답이 promoted 경로를 좌우함. drafting 단계에서 결정 대기 #1 부터 답하고 ready-for-spec 으로 넘기는 순서 권장.
F4. 떠오른 순간 → "Inkling!" 자동 연상 만들기 (🔬 drafting — C·E·F promoted)
발견: 2026-04-26 dogfood 시작 직전 사고 실험. 슬라이스 v0.4 와 strategy.md §3 가 이미 알고 있는 contextual cue (회의 후, 퇴근 전, 디버깅 후) 의 if-then 만 다루고, ambient/spontaneous 떠오름 (샤워, 산책, 대화 중, 자기 전) 은 사각지대.
진행 상태:
- E (Zeigarnik priming) — 🚀 promoted →
docs/superpowers/specs/2026-04-26-f3-f4e-copy.md - C (환경 앵커) — 🚀 promoted →
docs/superpowers/specs/2026-04-26-f4-cf-cue.md - F (정체성 고리) — 🚀 promoted →
docs/superpowers/specs/2026-04-26-f4-cf-cue.md - A (잠금 hook), D (variable interval prompt), B (ambient if-then) — 🌱 raw, 측정 후 결정
관찰
캡처 자체의 마찰은 거의 0 — Ctrl+Shift+J + 한 줄 + Enter = 3초. 하지만 dogfood 의 진짜 실패 모드는 "3초가 너무 길다" 가 아니라 "그 3초가 머릿속에 안 떠오른다" 다. 떠오름 → Inkling 연상 사이의 인지적 다리가 약하면, 메모 자체가 시도되지 않는다.
strategy.md 가 다루는 cue 는:
| 위치 | 내용 | 강한 cue 여부 |
|---|---|---|
| §3 회의형 | "회의가 끝나면" | ✅ 외부 신호 (Zoom 종료, 자리 일어남) |
| §3 퇴근 회고형 | "업무 종료 10분 전" | ✅ 시계·전등·동료 |
| §3 디버깅형 | "오류를 해결하면" | ✅ 테스트 PASS 화면 |
| §3 학습형 | "새로 배운 것이 있으면" | ⚠ 내부 인식, 약함 |
| §3 요청 관리형 | "누군가 업무를 요청하면" | ✅ 메시지/대화 |
남은 사각지대는 외부 신호 없이 머릿속에서만 떠오르는 생각 — 샤워, 운전, 산책, 자기 직전, 책 읽다가, 잡담 중. 본인 dogfood 에서 가장 풍부한 메모 후보가 이 영역에서 발생할 가능성이 큰데 (RTX 4070 owner profile, 퇴근 후 사이드 프로젝트형 사고 패턴), 슬라이스가 cue 를 안 만들어주면 그냥 잊혀짐.
제안 방향
6개 메커니즘 후보 — 각각 Inkling 의 좁은 실행 가능 단위로 변환.
A. 습관 쌓기 (Habit Stacking · BJ Fogg, James Clear)
기존 강한 자동 행동 직후에 새 행동을 붙임. "X 하면 Y 한다" — Y 가 X 의 부산물처럼 느껴지게.
| 강한 기존 자동 행동 | 붙일 Inkling 행동 |
|---|---|
| 노트북 덮음 / 잠금 (Win+L) | 30초 짧은 캡처 윈도우 자동 호출 |
| 휴대폰을 책상에 엎어놓음 | (휴대폰 앱이 생기면) 트리거 |
| 커피·물 가지러 일어남 | 타임랩스 카운트로 "자리 떴음 → 돌아왔을 때 한 줄" 프롬프트 |
| 메신저 알림 dismiss | 트레이 미니 입력 — Quick Capture 단축 |
슬라이스 가능: 잠금 화면 진입 직후 3초 캡처 윈도우. Windows API SystemEvents.SessionSwitch (lock/unlock) 로 unlock 시 한 번만 가벼운 토스트 ("머릿속에 남은 한 줄?"). 토스트 클릭 = QC. 무시 = 사라짐.
B. 실행 의도의 확장 (Gollwitzer, ambient 영역)
§3 의 if-then 을 "내적 인식" 트리거로 확장.
"무언가 해야 한다는 생각이 들면 → 그 자리에서 Ctrl+Shift+J"
"어제 그거 어떻게 됐지? 라는 생각이 들면 → 그 자리에서 Ctrl+Shift+J"
"이거 까먹을 것 같다는 느낌이 들면 → 그 자리에서 Ctrl+Shift+J"
내적 cue 의 약점은 인식 자체가 안 일어난다는 점이지만, 12주 의식적 반복 후 자동화 가능 (Lally 18254일 범위, 본 사례는 행동이 단순해서 짧은 쪽). 온보딩에서 사용자에게 본인의 ambient 떠오름 패턴 을 1개 직접 적게 하고 그걸 if-then 으로 변환.
C. 환경 앵커 (Cue Salience · 시각·물리적 단서)
생각이 떠오를 때 시야에 Inkling 이 있으면 연상 강화.
| 앵커 | 비용 | 슬라이스 적합도 |
|---|---|---|
| 잠금화면 배경에 Ctrl+Shift+J 안내 | 0 (사용자 셀프) | 외부 |
| 책상 모니터에 작은 펜 그림 스티커 | 0 (사용자 셀프) | 외부 |
| 작업 표시줄 트레이 아이콘 (이미 있음) | 0 | 슬라이스 ✅ |
| 트레이 아이콘 색을 "오늘 미캡처 시간" 에 따라 변화 | 작음 | 슬라이스 후속 |
| 윈도우 위젯 (Windows 11 위젯 보드) | 큼 | 슬라이스 외 |
가장 가벼운 즉시 적용: 트레이 아이콘에 색·뱃지 — 오늘 캡처 0건이면 점선 동그라미, 1건 이상이면 실선. 사용자가 무의식 중에 시야 끝에서 "비어있다" 신호를 받음.
D. 무작위 부드러운 알림 (Spaced retrieval · Variable interval)
랜덤 간격으로 "지금 머릿속에 떠다니는 한 줄?" 토스트. variable interval reinforcement 가 fixed interval 보다 행동 강화에 강하다는 행동주의 결과 응용. 단 거슬리면 즉시 망함 — 회복 친화 톤 강제.
| 변수 | 권장 1차 |
|---|---|
| 빈도 | 평일 09 |
| 작업 컨텍스트 가드 | full-screen 앱 감지 시 skip (회의·발표 중 보호) |
| 카피 톤 | "지금 한 줄 던져두면 좋을 게 있나요?" (강요 없음) |
| Off-toggle | 트레이 메뉴 1클릭 |
| 안티패턴 | 캡처 0/일 자체에 대한 죄책감 유발 카피 — 슬라이스 §1.1 위반 |
슬라이스 적합도: 중. Hotkey + Tray 만으로도 충분하다는 §3 결정과 충돌 가능. dogfood 1주 후 본인 캡처 빈도 데이터 본 뒤 결정.
E. Zeigarnik 효과 활용 (미완 텐션 → 외재화)
미완 과제는 인지 자원을 점유하며 회상이 더 잘 된다는 Zeigarnik 1927. Inkling 의 "이제 잊어도 됩니다" 보상이 이미 이 방향이지만, 떠올림 → 캡처 다리에서는 활용 안 됨. 강화 방향:
- 메인 토스트 카피 1개를 사용 전 priming 으로 재배치: 앱 첫 설치 직후 / 매일 첫 캡처 직후 짧게 "머릿속에 떠다니면 잡아두세요" 주입. 반복 노출이 ambient 떠오름 시 자동 reactivation.
- inbox 빈 상태 카피를 유발 어휘 로 변경: "오늘 머릿속에서 그냥 흘러간 생각 1개만 적어보세요" — 사용자에게 "흘러갔던 게 분명 있었지" 회상을 자극.
비용 0, 슬라이스 내 적용 가능. F3 (구출 카피 재검토) 와 자연스럽게 묶임.
F. 정체성 고리 (Identity-based habit · James Clear)
"메모 잘하는 사람이 되자" 가 아니라 "나는 머릿속을 비워두는 사람" 이라는 자기개념. 매 캡처마다 정체성 강화 카피 1개:
"오늘 7번째 비웠습니다." (count visible)
"한 주 누적 23개. 잊을 자유 23번."
"이번 주 다시 본 메모 4건 — 외부 기억이 일하고 있음."
이미 §4.2 능력감 보상에 일부 있음. 차이는 "기억력" 이 아니라 "비움/외재화" 정체성으로 frame. 트레이 메뉴 또는 inbox 헤더에 작은 카운터.
결정 대기
- 슬라이스 외부 vs 후속 미니 spec: A·D 는 새 IPC + Windows API + 알림 스케줄링이 필요해 슬라이스 §3 ("Hotkey + Tray + Notification 만") 와 충돌. C·E·F 는 슬라이스 내 적용 가능. 어디까지 슬라이스에서 시도하고 어디서부터 별 spec 으로 분기?
- 무작위 알림 (D) 의 거슬림 임계점: 본인 dogfood 1주 누적 데이터 (캡처 빈도 중간값) 를 보기 전에 결정 미루기. 데이터 없이 도입하면 anti-pattern 될 위험.
- 메커니즘 결합 vs 격리 시험: 6개 동시 적용 시 어느 게 효과 있었는지 분리 불가. dogfood 단계에서 격리 A/B 가능한가? 본인 단일 사용자라 통계 의미 약함 — 정성 라벨링으로 대체.
- strategy.md 와의 관계: 본 항목이 strategy.md §3 ambient cue 절을 신규 §3.6 으로 추가할 만큼 무거운가, 아니면 specs/ 만으로 충분한가? F3 와 동일한 "strategy 동반 갱신 여부" 결정 패턴.
- 외부 의존 (Win API) 도입의 슬라이스 의의: A 의 SessionSwitch hook 은 슬라이스에서 한 번도 열어본 적 없는 native API. 도입 시 §7 dependency invariant 에 추가, 그 비용 vs cue 효과 가치 비교 필요.
가설·측정
| # | 가설 | 측정 |
|---|---|---|
| H1 | E (Zeigarnik 카피 재배치) 만 적용해도 본인 dogfood 1주 캡처 빈도 ≥ 30% 증가 | 캡처/일 카운트, 적용 전후 1주씩 |
| H2 | C (트레이 뱃지 0/N 표시) 가 시각적 cue 로 작동하여 12~18시 사이 "지금 비어있네" 자각 사건 ≥ 2회/주 | 본인 라벨링 |
| H3 | D (무작위 알림) 가 캡처 빈도를 늘리지만 거슬림 점수 (1~5) 가 평균 ≤ 2 | 정성 점수 |
| H4 | F (정체성 카피) 가 dogfood 종료 시 "Inkling 을 계속 쓰고 싶다" 점수에 양의 영향 | exit 인터뷰 |
| H5 | B (ambient if-then 온보딩) 의 사용자 작성 if-then 1~2개가 1주 후에도 회상 가능 | 본인 self-report |
범위
- In (슬라이스 가능 — 가벼운 적용):
- C 의 일부 — 트레이 아이콘 색·뱃지 (오늘 캡처 0/≥1)
- E — Zeigarnik priming 카피 1줄 + 빈 상태 카피 재작성 (F3 와 묶기)
- F — 트레이/Inbox 헤더의 정체성 카피 1줄 (count 표시)
- In (슬라이스 후속 미니 spec):
- A — 잠금/잠금해제 시 부드러운 캡처 프롬프트
- B — 온보딩에 ambient if-then 1~2개 작성 단계 추가
- D — 무작위 알림 + 가드 (full-screen, off-toggle)
- Out:
- 음성 ("Hey Inkling")
- 휴대폰 앱
- 위젯 보드 통합
- 외부 캘린더 cue 연동
영향
- Schema: 없음 (모두 클라이언트 사이드 또는 카피)
- 코드:
- C 트레이 뱃지:
tray.ts— 이미지 동적 갱신,repo.countToday(): number또는getInbox필터로 오늘 카운트 조회. 10분 간격 또는 새 노트 생성 IPC 신호로 갱신. - E priming 카피:
NotificationService.REWARD_COPIES,inbox/App.tsx빈 상태,quickcapture/App.tsx힌트 - F 정체성 카피:
inbox/App.tsx헤더 영역 (count + 한 줄), 또는 트레이 tooltip - A 후속:
electron.powerMonitor의lock-screen/unlock-screen이벤트, 새LockHookService - D 후속: 새
RandomPromptService— setInterval + jitter, full-screen 감지는screen.getDisplayNearestPoint또는 native 호출
- C 트레이 뱃지:
- 문서:
- 본 항목 promoted 시
2026-04-26-cue-strengthening.md(가칭) 으로 추출 - strategy.md 결정 #4 결과에 따라 §3.6 신설 또는 본 spec 만으로 종결
- 본 항목 promoted 시
- 테스트:
- C 의 단위 테스트 — 카운트 0/N 분기, 날짜 경계 KST
- E·F 카피 변경에 따른 e2e smoke 단언 동기화 (F3 와 묶음)
비고
본 항목은 슬라이스 §1.3 의 종료 조건 ("본인 2주 dogfood 완주") 을 달성하기 위한 메타-행동 설계다. 즉 slice 의 "기능 엣지" 가 아니라 "사용자가 slice 를 안 잊고 쓰게 하는 메타 레이어". 우선순위는 H1 (E 만 1주 시도) → 데이터 확인 → C·F 추가 → A·D 검토 순서 권장. 6개 메커니즘 동시 도입은 신호 분리 불가로 안티패턴.
F5. 마크다운 일괄 export (RAG 활용 가정) (🚀 promoted)
진행 상태: 🚀 promoted → docs/superpowers/specs/2026-04-26-f5-export.md
발견: 2026-04-26 dogfood 시작 직전 사고 실험. 슬라이스 v0.4 는 노트가 SQLite + 로컬 미디어 폴더에만 존재. 외부 도구 (Obsidian, RAG 파이프라인, 로컬 LLM 컨텍스트, 검색 엔진) 로 빼낼 통로가 0.
관찰
스키마에 이미 export 에 필요한 모든 정보가 있다 (m001_initial.ts:7~57):
notes— id, raw_text, ai_{title,summary}, *_edited_by_user, user_intent, intent_prompted_at, created_at, updated_at, ai_provider, ai_generated_atnote_tags(+tags) — 태그 + source(ai/user)media— note 첨부 이미지 메타 (rel_path가 MediaStore 의 프로필 디렉터리 기준)- (F1 promoted 시)
due_date,due_date_edited_by_user
내보낼 자산은 두 종류:
- 노트 본문 + 메타데이터 — 텍스트
- 첨부 이미지 — 바이너리 파일 (현재는
<profile>/media/<rel_path>)
RAG 파이프라인 (LangChain, LlamaIndex, ChromaDB, 로컬 embedding) 의 표준 입력은 YAML frontmatter 가 붙은 단일-노트-단일-파일 마크다운 + 안정 ID + 카테고리/태그 메타. 본 export 는 이 형식에 정렬해야 후속 의사결정 (RAG 도입, Confluence 동기화, Obsidian vault 사용) 모두 한 형식으로 흡수 가능.
제안 방향
1차 권장 — 디렉터리 트리 + frontmatter 마크다운 + index.jsonl + 미디어 동봉.
inkling-export-2026-04-26/
notes/
2026-04-25-014a3b9c-주간회고-PR-리뷰.md
2026-04-25-02f17de8-새-디버깅-패턴.md
...
media/
014a3b9c__1.png # MediaStore rel_path 평탄화
02f17de8__1.jpg
index.jsonl # RAG 친화 1줄=1노트 메타
manifest.json # 스키마 버전, 내보낸 시각, 노트 수, 검증 해시
README.md # 형식 설명, RAG 적용 가이드
노트 파일 포맷 (one file per note, RAG 친화):
---
id: 014a3b9c-...
created_at: 2026-04-25T14:23:11+09:00
updated_at: 2026-04-25T14:24:02+09:00
title: 주간 회고 PR 리뷰
title_source: ai # ai | user (edited 면 user)
summary: 회고 양식 통일을 위한 PR 리뷰 메모.
summary_source: ai
tags:
- { name: pr, source: ai }
- { name: review, source: user }
user_intent: 팀에서 회고 양식 통일
intent_prompted_at: 2026-04-25T14:24:02+09:00
due_date: 2026-05-01 # F1 promoted 시
due_date_source: ai
ai_provider: local-ollama/gemma4:e4b
ai_generated_at: 2026-04-25T14:23:34+09:00
images:
- rel: media/014a3b9c__1.png
mime: image/png
bytes: 152834
inkling_export_version: 1
---
# 주간 회고 PR 리뷰
> 회고 양식 통일을 위한 PR 리뷰 메모.
내일 까지 PR 리뷰 마무리하고, 회고 양식은 팀에 공유.
오후 미팅 중에 떠올랐음.

index.jsonl (RAG 인덱싱용 1줄=1노트):
{"id":"014a3b9c-...","path":"notes/2026-04-25-014a3b9c-주간회고-PR-리뷰.md","created_at":"2026-04-25T14:23:11+09:00","tags":["pr","review"],"due_date":"2026-05-01","embedding_text":"주간 회고 PR 리뷰\n\n내일 까지 PR 리뷰 마무리하고..."}
embedding_text 는 title + raw_text + tags 를 결합한 임베딩 입력 후보. 사용자가 별도 가공 없이 LangChain JSONLoader 또는 LlamaIndex JSONReader 로 바로 적재 가능.
파일명 컨벤션: YYYY-MM-DD-{id8}-{slugified-title}.md. 충돌 회피 + 인간 가독 + 디렉터리 정렬 친화.
id8= UUIDv7 의 처음 8자리. 시간 정렬 + 충돌 0.slugified-title= title 의 한글 보존, 공백→하이픈, 파일시스템 금지 문자 제거 (/\\:*?"<>|), 32자 제한.- title 비어있으면
untitled폴백.
트리거 (1차 권장): 트레이 메뉴 → "마크다운으로 내보내기..." → Electron dialog.showOpenDialog({ properties: ['openDirectory'] }) 로 사용자가 폴더 선택 → 진행 토스트 → 완료 토스트 (성공 시 노트 수 + "폴더 열기" 버튼).
증분 vs 전체: 1차는 전체 덮어쓰기만. 증분(변경된 노트만 갱신)은 후속.
결정 대기
- 포맷 1차안 확정: one-file-per-note + frontmatter + index.jsonl 트리플 vs 단일 monolithic .md vs 두 형식 동시 출력? → RAG 우선이면 트리플이 압도적이지만 사용자 선호 확인 필요.
- 미디어 포함 기본값: 항상 동봉 vs 사용자 선택 (체크박스). 슬라이스 §1.1 의 "raw_text 본문에 민감정보 가능" 정책 — 이미지가 스크린샷인 경우 export 가 의도치 않은 노출 통로가 될 수 있음. 기본 동봉 + export 시 다이얼로그에 "이미지 N개 포함됩니다" 명시 가 안전.
- 삭제된 노트 처리: SQLite 에 soft-delete 컬럼이 없음. 현재는 hard delete. export 결과는 현 시점 스냅샷만 — 삭제 이력 없음. 충분한가, 별 issue 인가?
- 필드 정책 — provenance 표현:
title_source: ai|user같은 단일 enum vstitle: { value, source, edited_at }객체. RAG 파이프라인의 frontmatter parser 마다 다름 — 평탄한 enum 이 호환성 좋음. - embedding_text 합성 규칙: title + raw_text + tags 단순 결합 vs raw_text 만 (가장 untouched) vs title + summary + raw_text. 본인 RAG 사용 패턴 미정 — 1차는 raw_text 단독으로 시작 + 옵션화.
- 파일명에서 raw_text vs ai_title 사용: ai_title 사용이 가독성 좋지만 AI 변경 시 파일명도 변하는 안티패턴. ai_title 사용 + 사용자가 수동 export 트리거 시점 기준 으로 동결 (재 export 시 새 파일명). 파일명 안정성 vs 가독성 트레이드오프 명시.
- 트리거 표면: 트레이 메뉴만 vs Inbox 헤더 버튼도 추가 vs CLI 플래그 (
--export <dir>). 자동화 사용자라면 CLI 가 매력. 슬라이스 후속 미니 spec 으로 분리 가능. - export 형식 버전 정책:
inkling_export_version: 1박아두고 후속 변경 시 마이그레이션 가이드 동봉. 처음부터 박는 게 깔끔. - 민감정보 표시 경고: 본 사용자는
dlsrks0734@gmail.com계정 본인 단일 사용자라 위험 낮지만, export 후 폴더가 어디 가는지에 따라 위험 발생. 트레이 export 다이얼로그에 "이 export 는 평문이며 raw_text 가 그대로 포함됩니다" 명시 필요.
가설·측정
| # | 가설 | 측정 |
|---|---|---|
| H1 | dogfood 1주 후 본인이 export 한 마크다운 더미를 LlamaIndex 기본 markdown loader 로 직접 적재 가능 (사이즈 변환 0) | 실측 — 1회 시도 |
| H2 | export 결과의 frontmatter 가 Obsidian 의 frontmatter renderer 에도 호환 | 실측 — Obsidian 에 폴더 import 후 메타 표시 확인 |
| H3 | 노트당 평균 raw_text 길이 ≤ 200 토큰 → RAG chunking 불필요 | 표본 50건 토크나이저 통계 |
| H4 | export 누적 사이즈가 1MB / 100 노트 이하 (미디어 제외) | 측정 |
| H5 | 본인이 export → 외부 도구 적재 → 적어도 1번 의미 있는 회수 (검색·RAG·재방문) 발생, dogfood 2주 내 | 본인 라벨링 |
범위
- In:
ExportService신규 — DB 쿼리 + 파일 쓰기 + 미디어 복사- 트레이 메뉴 항목 1개 추가 ("마크다운으로 내보내기...")
- Electron
dialog디렉터리 선택 - frontmatter 합성 + 파일명 슬러그
index.jsonl+manifest.json+README.md동시 생성- 미디어 평탄화 복사 (rel_path →
media/{id8}__{n}.{ext}) - 진행 상태 토스트 (노트 수 ≥ 100 시 진행률)
- 단위 테스트 — frontmatter 합성, 슬러그, JSON 직렬화
- Out (후속 미니 spec):
- 증분 export
- 자동 export (cron / watch)
- CLI 플래그
- import (역방향)
- 다중 형식 (CSV, JSON 단일 파일, OPML)
- 외부 SaaS 동기화 (Confluence, Notion)
- export 시 raw_text 마스킹·익명화
영향
- Schema: 없음 — 현 스키마로 충분
- 신규 파일:
src/main/services/ExportService.tssrc/main/ipc/exportApi.ts- 테스트
tests/unit/ExportService.spec.ts
- 변경 파일:
src/main/index.ts— 등록src/main/tray.ts— 메뉴 항목 추가src/preload/index.ts— IPC expose
- 외부 의존:
- 없음 — Node
fs/promises+path+node:crypto(해시) 만 사용 - YAML 직렬화는 frontmatter 가 단순 하므로 자체 구현 (외부 dep 추가 불필요)
- 없음 — Node
- 로깅:
- export 시작·완료·노트 수만 기록. raw_text·title·summary 미기록 (slice §1.1 invariant 4 그대로)
- 문서:
- 본 항목 promoted 시
2026-04-26-markdown-export.md(가칭) 으로 추출 - 추출 후 README 의 doc map 갱신
- export 폴더 안의
README.md— RAG 적재 예시 코드 포함
- 본 항목 promoted 시
비고
본 항목은 읽기 전용 이라 dogfood 안전성 영향 0 (raw_text 변경 없음, AI 호출 없음, 네트워크 0). 우선순위 측면에선 F1·F2·F3 보다 후순위지만 F4 의 H5 (외부 도구로 회수) 평가 자체가 export 없이는 측정 불가 — 즉 F4-H5 = F5 dependency. F4 의 데이터 수집을 위해 F5 가 먼저 promoted 되는 경로도 있음.
F6. 메모 데이터 백업 + 복원 (3-layer 권장) (🔬 drafting — L1 promoted)
진행 상태:
- L1 (로컬 스냅샷) — 🚀 promoted →
docs/superpowers/specs/2026-04-26-f6-l1-local-snapshot.md - L2 (git sync) — 🚀 promoted (MVP) →
docs/superpowers/specs/2026-04-26-f6-l2-git-sync.md - L3 (import) — 🚀 promoted →
docs/superpowers/specs/2026-04-26-f6-l3-import.md
발견: 2026-04-26 dogfood 시작 직전 사고 실험. 슬라이스 v0.4 의 메모 데이터는 %APPDATA%\Inkling\Inkling\profiles\default\ 단 한 위치에만 존재. 디스크 고장·실수 삭제·DB 손상·OS 재설치 = 총 손실. Strategy.md §1 의 "이제 잊어도 됩니다" 보상이 데이터 영속성 신뢰 위에 서 있어서, 이 신뢰가 깨지면 슬라이스 §1.3 의 종료 조건 ("본인 2주 dogfood 완주") 자체가 위협받음.
관찰
현재 단일 실패 지점 (SPOF):
inkling.sqlite(WAL 두 파일 포함) — 노트·태그·AI 메타·intent 전부media/— 클립보드 이미지 바이너리 (DB 의rel_path와 짝)- 부팅 시
MediaGc가 DB 미참조 미디어를 정리 — DB 가 손상되면 미디어도 GC 사이클에서 사라질 수 있음 (위험 증폭)
기존 부분 완화는 0:
- 자동 백업 0
- 외부 동기화 0
- import 경로 0
- F5 (export) 가 promoted 되어도 단방향 + 수동
본인 dogfood 운영 환경 신호:
- 이미
gitea.altair823.xyz자체 호스팅 중 — 사적 git remote 인프라가 있음 - 프로젝트 메모리: Mac=업무 / Windows=개인+dogfood — 디바이스 전환 가능성 (단일 활성, 동시 X)
- RTX 4070 Windows = 메인 dogfood 머신, 디스크 1대 SSD 가정 → 디스크 고장 1회 = 전체 손실
제안 방향
3-layer 다층 백업. 각 layer 가 다른 위협 모델을 커버.
| Layer | 위협 모델 | 비용 | 슬라이스 적합 |
|---|---|---|---|
| L1 로컬 원자 스냅샷 | 실수 삭제, DB 손상, AI 마이그레이션 실패 | 작음 | ✅ 슬라이스 후속 가벼움 |
| L2 git remote 마크다운 동기화 | 디스크 고장, 디바이스 이동, 버전 이력 필요 | 중 | 🔬 별도 미니 spec |
| L3 전체 export/import | OS 재설치, 디바이스 이주, 사용자 통제 백업 | 작음 (L1 + F5 위) | ✅ F5 위에 import 만 추가 |
L1 — 로컬 원자 스냅샷
better-sqlite3 의 db.backup(path) API 사용. WAL 활성 상태에서도 안전한 원자적 복제 (파일 단순 cp 와 다름 — WAL 미반영분 누락 위험 없음).
// 의사코드
async function snapshot(): Promise<void> {
const ts = format(new Date(), 'yyyy-MM-dd');
const dest = join(profileDir, 'backups', `inkling-${ts}.sqlite`);
await db.backup(dest);
await rotate({ daily: 14, weekly: 4, monthly: 6 });
}
스케줄:
- 앱 종료 직전 1회 (
before-quit) - 매일 첫 캡처 시 (
<profileDir>/backups/.last-snapshotmtime 비교) - 명시 트리거: 트레이 메뉴 "지금 백업"
저장 정책 — Grandfather-Father-Son:
- 일일 14개 → 주간 4개 → 월간 6개. 누적 24개 안팎, 평균 사이즈 가정 시 < 50MB.
backups/는 미디어 미포함 (DB 만). 미디어는 L2 또는 L3 책임.
위협 미커버: 디스크 자체 고장. SSD 가 죽으면 backups/ 도 같이 죽음. L2 가 이 위협 담당.
L2 — git remote 동기화 (RECOMMENDED 핵심 layer)
핵심 결정: SQLite 바이너리를 push 하지 말고, F5 마크다운 트리를 push 한다.
| SQLite 바이너리 | F5 마크다운 트리 | |
|---|---|---|
| diff 의미성 | 0 (전체 blob 변경) | ✅ 노트별 라인 diff |
| repo 사이즈 | 매 push 마다 풀 DB | 변경 노트만 |
| 멀티 디바이스 머지 | 불가 (binary conflict) | 가능 (텍스트 merge) |
| 외부 도구 호환 | 0 | RAG / Obsidian / grep 즉시 |
| F5 와 의 시너지 | 0 | F5 그대로 재사용 |
→ F5 의 export 형식을 git 추적 대상으로 그대로 사용. F5 가 promoted 되면 F6-L2 는 그 위에 자동화 layer 만 얹는 구조.
아키텍처:
[CaptureService / NoteRepository]
│ (write)
▼
inkling.sqlite ← Layer 0 (primary)
│
│ (DB write 후 dirty 마크)
▼
<profileDir>/sync/ ← Git working tree (L2)
├── notes/ ← F5 형식 마크다운
├── media/
├── index.jsonl
└── manifest.json
│
▼ (BackgroundSyncWorker, 5분 주기 또는 dirty=true 후 30초 debounce)
git add . && git commit -m "..." && git push
커밋 메시지 컨벤션 (자동 생성):
chore(notes): +3 ~1 -0 (2026-04-26T14:23+09:00)
added: 01H89aab... 주간 회고 PR 리뷰
added: 01H89bcd... ...
modified: 01H78xyz... 어제 회의 메모
기존 inkling 본 저장소 commit 스타일과 분리되며, "automated note sync" 임이 명확.
Auth & 보안:
- Personal Access Token 또는 SSH key. Electron
safeStorageAPI (OS keychain 백엔드 — Windows 는 DPAPI) 로 평문 미저장. - 토큰은 절대 로그/오류 메시지에 노출 금지 (slice §1.1 invariant 4 확장).
- repo 는 반드시 private — 평문 raw_text 노출 위험. 처음 설정 시 다이얼로그에 굵은 경고.
Conflict 정책 — single-active-device 가정:
- push 가 거부되면 (다른 디바이스가 먼저 push) →
git pull --rebase→ 자동 머지 시도 - 머지 실패 (같은 노트 양쪽 수정) → 트레이 알림 + 수동 해결 다이얼로그. 노트별 "내 버전 / 원격 버전 / 둘 다 보존" 3-way 선택
- 본인 dogfood = 단일 활성 디바이스라 거의 발생 안 함 — 멀티 디바이스 시나리오 정식 지원은 L2 의 v2
Repo 초기화:
- 첫 설정 시 사용자가 빈 remote URL 입력 → 앱이
git init+ 초기 export + 첫 커밋 + push - 또는 기존 repo URL 입력 → clone → 검증 (이전 manifest 호환성) → 동기화 시작
미디어 정책:
- 평문 push 가 default — 텍스트 노트와 함께 미디어도 git 에 올라감
- repo 사이즈 폭발 위험 → 토큰 옵션: "이미지 제외" 토글 또는 Git LFS (선택). 1차는 옵션 X, 단순 push, 사이즈 모니터링만.
- 이미지 제외 시 frontmatter 의
images항목은 보존하되 파일은 미포함 → 복원 시 placeholder 표시
L3 — 수동 전체 export / import
- export: F5 가 그대로 담당. 변경 없음.
- import: 신규. F5 형식 폴더를 읽고 DB 에 upsert. 충돌 정책:
- id 충돌 + 본문 동일 → skip
- id 충돌 + 본문 상이 → 사용자 선택 (덮어쓰기 / skip / 양쪽 보존하며 새 id 생성)
- id 신규 → insert
- 미디어 → MediaStore 에 복사
- 트레이 메뉴 "백업에서 복원..." → 폴더 선택 → 미리보기 (n개 신규, m개 변경, k개 충돌) → 확인 → 적용
결정 대기
- 3-layer 동시 도입 vs 단계적: L1 → L3 → L2 순서가 비용·위험 단조 증가라 권장. L1 만으로도 SPOF 완화의 80% 커버.
- L2 sync 단위: 매 변경 vs 5분 debounce vs 종료 시 1회 vs 명시 동기화만. 실시간일수록 데이터 손실 윈도우 작지만 git push 빈도 폭발 + 네트워크 마찰. 5분 debounce + 종료 시 즉시 push 가 1차 권장.
- L2 repo 분리: 기존
gitea.altair823.xyz/altair823-org/inkling(소스 코드) 와 분리된 별 repo (예:altair823-org/inkling-data) — 반드시 분리. 데이터·코드 라이프사이클 다름, 외부 협업자에게 데이터 노출 위험. - L2 충돌 시 정책 — slice §1.1 vs 사용자 선택: 자동 "내 디바이스 우선" 가속 vs 매번 묻기. dogfood 단일 디바이스 가정으론 자동 OK, but defensive 차원에서 충돌 발생 시 1회 확인이 안전.
- media 의 git 추적: 포함 vs 제외 vs LFS. 1차는 포함 + 사이즈 < 100MB 경고. 누적 시점에 후속 결정.
- L1 백업 위치:
<profileDir>/backups/(현 프로필 안) vs 별 디렉터리 (%APPDATA%\Inkling\backups\) vs 사용자 지정 외부 경로. 외부 경로 옵션이 OneDrive 등 클라우드 sync 폴더 이용 가능 — 거의 공짜 cloud backup. - import 시 raw_text invariant 보호: slice §1.1 "raw_text 불변" 은 동일 id 내 의미. import 가 같은 id 의 raw_text 를 다른 값으로 덮어쓰면 invariant 위반. 충돌 시 raw_text 다르면 새 id 강제 정책이 안전.
- L2 첫 설정의 UX 부담: token 입력 + remote 검증 + 초기 push 가 dogfood 1일차 첫 인상에 마찰. 첫 설치 후 N 일 (예: 7일) 까지는 L1 만 켜두고 L2 는 트레이 메뉴 "원격 백업 설정" 으로 opt-in 권장.
- 암호화 — local-first 라도 token 외 추가 보호 필요한가: SQLite·미디어·git 모두 평문. 디스크 도난 시 노출. 1차는 평문 (slice §1.1 미적용 영역), 후속에 SQLCipher / age 암호화 검토.
- slice §7 strict-pin invariant 영향: L1 은
better-sqlite3.backup()만 사용 — 추가 dep 0. L2 는simple-git또는nodegit같은 git 바인딩 또는 child_process 로 git CLI 호출. CLI 호출이 dep 0 + 사용자 git 환경 재사용. CLI 호출 권장.
가설·측정
| # | 가설 | 측정 |
|---|---|---|
| H1 | dogfood 2주 누적 동안 디스크 측 사건 (실수 삭제, DB 손상, 디스크 고장) ≥ 1회 발생할 정성 가능성 | 발생 시 라벨링 |
| H2 | L1 단독 만 도입해도 SPOF 발생 시 회복 가능 (백업으로 ≥ 95% 데이터 복원) | 복원 시뮬레이션 1회 (의도적 DB 삭제 후 복원) |
| H3 | L2 5분 debounce push 가 일평균 ≤ 30 commit. repo 사이즈 누적 < 100MB / 1년 | 로그 측정 |
| H4 | L2 commit 메시지 통계 (added·modified·deleted) 가 dogfood 활동 회고 자료로 가치 발생 | 정성 평가 |
| H5 | "이제 잊어도 됩니다" 보상의 신뢰도 — 백업이 있다는 인지가 capture 빈도 또는 심리적 부담 감소에 영향 | 본인 self-report |
범위
- In (L1 — 슬라이스 후속 가벼움):
BackupService신규 —db.backup()래핑 + 로테이션- 트레이 메뉴 "지금 백업" + 타임스탬프 표시
- 종료·일일 1회 자동 트리거
backups/디렉터리 —.gitignore와 같은 .ignored 마커 고려- 단위 테스트 — 로테이션 GFS 정책
- In (L3 — F5 위에 import 만):
ImportService신규- 충돌 미리보기 다이얼로그
- 트레이 메뉴 "백업에서 복원..."
- In (L2 — 별 spec, 가장 큼):
SyncService(BackgroundSyncWorker)- F5 ExportService 의 incremental 모드 (변경 노트만)
- git CLI 래퍼 + safeStorage 토큰 관리
- 설정 UI — remote URL, 토큰, 동기화 주기, 미디어 포함 여부, 충돌 정책
- 충돌 해결 다이얼로그
- 상태 표시 (트레이 아이콘 색·tooltip)
- Out:
- SQLCipher 암호화
- 다중 활성 디바이스 실시간 sync
- 외부 SaaS (Dropbox API, Google Drive API) 직접 연동
- Rsync 전송
- SQLite WAL 의 logical replication
영향
- Schema: 없음
- 신규 파일 (L1 + L3):
src/main/services/BackupService.tssrc/main/services/ImportService.tssrc/main/ipc/backupApi.ts- 테스트
tests/unit/BackupService.spec.ts,ImportService.spec.ts
- 신규 파일 (L2 별 spec):
src/main/services/SyncService.tssrc/main/services/GitClient.ts(git CLI 래퍼)src/main/services/CredentialStore.ts(safeStorage 래퍼)- 설정 UI (Settings 창 신설 — 슬라이스 §5 의 "Settings 창 없음" 결정 재검토 필요)
- 외부 의존:
- L1: 0
- L3: 0
- L2: 사용자 머신의 git CLI 필요. README 사전 요구 항목 추가
- 로깅:
- 백업 시작·완료·사이즈만. 본문·파일명 미기록
- 동기화 push 결과·conflict 발생만. 토큰·URL 일부 마스킹
- 문서:
- 본 항목 promoted 시 분리 권장:
2026-04-26-local-snapshot.md(L1)2026-04-26-import.md(L3, F5 와 자매)2026-04-26-git-sync.md(L2)
- 또는 단일
2026-04-26-backup-strategy.md로 통합 후 §A·§B·§C 로 분리
- 본 항목 promoted 시 분리 권장:
비고
본 항목과 F5 는 완벽한 데이터 라이프사이클 그림 의 두 절반:
- F5 = 외부 회수 (read 방향)
- F6 = 외부 백업 + 내부 복원 (write·sync 방향)
L2 (git sync) 가 dogfood 본인의 기존 인프라 (gitea 자체 호스팅) 와 자연스럽게 맞물리는 점은 본 사용자에게 특히 강한 가치. 다른 사용자였다면 GitHub Actions 등 외부 서비스 의존이라 우선순위 낮을 수 있음.
slice §1.3 종료 조건 ("크래시 0회") 와 별개로, "데이터 손실 0회" 가 silent invariant 로 추가되어야 함. 본 항목 → slice spec §1.3 추가 갱신 후보.
F7. Due Date 규칙 파서가 합성 표현을 first-match-wins 로 오인 (🚀 promoted)
진행 상태: 🚀 promoted (D AI-primary 채택) → docs/superpowers/specs/2026-04-26-f7-ai-primary-due-date.md
발견: 2026-04-26 v0.2.1 dogfood 첫 사이클. 본문에 "내일 모레" 가 들어간 노트가 due_date = 내일 (today + 1) 로 추출됨. 사용자 의도는 "모레" 또는 "이틀 안" 정도의 모호 표현.
관찰
src/main/services/dueDateParser.ts 의 매칭 로직:
- 14 high-confidence 규칙을 순회 (모레가 내일보다 우선순위 위)
- 같은 텍스트에 여러 토큰 발견 시
text.indexOf로 가장 먼저 등장한 위치 의 토큰 채택 (내일도 모레도 바쁨→ 내일이라는 기존 fixture 가 이 동작을 lock-in)
문제 케이스:
"내일 모레"— 합성 표현 (내일+모레 ≈ "곧" / "1-2일 안") 인데 첫 토큰 "내일" 만 잡힘"오늘 내일 안에"— 동일 패턴"이번 주 다음 주"— 양가 표현"3일 4일 뒤"— 범위 표현
규칙 파서의 한계 3가지:
- 합성/양가 표현: 두 시간 토큰이 인접하면 단일 의미로 해석되는 한국어 관용 (사용자 의도 ≠ 첫 토큰)
- 범위 표현: "2~3일 뒤", "이번 주 안에", "다음 주 중", "월말 즈음" — 명확한 ISO 가 없는 본질
- 모호 표현: "곧", "조만간", "여건 되면" — 사람도 ISO 변환 못함
현재 동작은 첫 토큰 기반이라 확신도 낮은 매치도 high confidence 로 표기되어 NoteCard 에 그대로 박힘. 사용자가 매번 editing 해야 하는 마찰.
제안 방향
5가지 후보, 짧은 시간 / 긴 시간 layered:
| ID | 방향 | 비용 | 효과 | 슬라이스 적합 |
|---|---|---|---|---|
| A | "내일 모레" / "오늘 내일" / "이번 주 다음 주" 등 합성 패턴 화이트리스트 추가 — 인접한 두 시간 토큰 발견 시 확신도 낮춰서 AI 위임 | 작음 | 한정적 (알려진 패턴만) | ✅ 작은 PR |
| B | 한 노트에 여러 high-confidence 매치 발견 시 충돌 감지 → 모두 medium 으로 강등 → AI 위임 | 작음 | 중 — 단일 토큰은 그대로, 다중만 영향 | ✅ 작은 PR |
| C | 규칙 매치 결과에 항상 confidence 정보 + matched span 첨부 + UI 에 ? 마크 (낮은 확신도) 노출 + 클릭 1번에 빠른 dismiss |
중 | 중-상 — 사용자가 인지 + 빠른 수정 가능 | 중 |
| D | AI 우선 + 규칙은 후위 검증 으로 흐름 반전 — AI 가 due_date 응답하면 규칙으로 sanity check (확실한 매치만 그대로, 충돌 시 AI 우선) | 큼 | 가장 정확 | 후속 |
| E | 규칙 파서 폐기, AI 단독 | 작음 (코드 삭제) | AI 모델 의존도 ↑, latency 의존, 결정론 손실 | 후속 |
권장 조합 (단계적):
- 즉시 (slice MVP +): B + 일부 A — 첫 발견 시 충돌 / 화이트리스트 매치는 medium 으로 강등 (AI 위임). 골든 픽스처에
"내일 모레" → null추가. - 다음 cycle: C — UI 신호 (확신도 표시 + 빠른 편집)
- 누적 데이터 후: D 또는 E — AI 우선/단독 흐름 반전 결정. dogfood 1주 데이터 (수용률 / 편집률 / 충돌 발생률) 가 의사결정 기반.
결정 대기
- 합성 패턴 화이트리스트 (A) 의 크기: 2 토큰 (
내일 모레,오늘 내일,이번 주 다음 주,오늘 내일 모레같은 3-token) 까지 — 어디까지가 합리적 범위인가? - 충돌 감지 (B) 의 임계값: "high-confidence 토큰이 동일 텍스트에 N개 이상 등장 시 medium 강등" — N = 2 OK? 또는 토큰 간 거리 (한 줄 안 vs 떨어진 문장) 로 다르게?
- fixture 유지: 기존
'내일도 모레도 바쁨' → 내일테스트는 현재 동작을 lock-in 하는 케이스. B 도입 시 이걸 → null 로 바꿔야 일관됨. 의도된 변경? - C 의 UI 위치: 확신도
?를 어디에 표시?📅 YYYY-MM-DD ?(라벨 옆) vs hover tooltip vs 별 색 (회색 = 확신 낮음). - D vs E: 결정론적 fallback 가치 vs AI 단순화. dogfood 누적 데이터 본 뒤 결정.
- F1 spec 의 후속 리스트 에 본 항목을 추가할지, 별 항목으로 분리할지. 별 항목 권장 (영향 큼, 수정 복잡도 다름).
가설·측정
| # | 가설 | 측정 |
|---|---|---|
| H1 | dogfood 1주 동안 합성 표현 ("내일 모레", "이번 주 다음 주" 등) 등장 ≥ 3회 | 본인 라벨링 + grep |
| H2 | A+B 적용 시 false positive 매치율 > 50% 감소 | 적용 전후 1주씩 비교 |
| H3 | C 의 ? 표시가 사용자 편집 빈도를 ≥ 30% 증가시킴 (자각 → 행동) |
편집 이벤트 카운트 |
| H4 | 본인 dogfood 에서 due_date 가 한 번이라도 잘못 박혀서 무시되는 노트 비율 < 10% (현재 측정 없으나 첫 케이스가 발생함) | 정성 라벨링 |
| H5 | D (AI 우선) 적용 시 latency 영향 ≤ 200ms / 노트 (현재 ~1-3초 대비 무시 가능) | LocalOllamaProvider 응답 시간 측정 |
범위
- In (1차 — A + B):
dueDateParser.ts— 합성 패턴 화이트리스트 (2-token 인접 시 medium 강등) + 충돌 감지 (≥2 high-confidence 매치 시 모두 medium)tests/unit/dueDateParser.test.ts— 새 fixture ("내일 모레" → null,"오늘 내일" → null,"이번 주 다음 주" → null)- 기존
'내일도 모레도 바쁨' → 내일fixture 결정 — 유지 vs 변경 - AiWorker 의 머지 로직 그대로 (
ruleResult.iso ?? aiResponse.dueDate ?? null) — medium 매치는 iso=null 이므로 자동으로 AI 위임
- In (2차 — C):
ParseResult에matchedSpan: { start, end }추가dueDateParser가 confidence 와 함께 매치한 토큰 span 반환- AiWorker 가 final result 에
dueDateConfidence: 'high' | 'medium' | 'low'추가 - DB 컬럼
due_date_confidence신규 (migration v3) — 또는 transient 만 (UI 만 표시, DB 미저장) NoteCard.DueDateBadge— 확신도 낮음 시?표시 + tooltip
- In (후속 — D):
- AiWorker 흐름 반전: AI 먼저 호출 → 응답에 due_date 있으면 채택 → 규칙은 sanity (AI 응답이 명백히 틀린 경우 — 예: AI 가 과거 날짜 반환) 검증
- 또는 E: 규칙 파서 deprecate
- Out:
- "월말", "주말" 같은 모호 표현 (이미 medium 처리 중)
- 시각 단위 (오후 3시 등)
- 음력 / 절기
영향
- Schema (1차): 없음
- Schema (2차 C): migration v3 후보 —
due_date_confidence컬럼. 또는 transient 만 (DB 미저장). - 코드 (1차):
src/main/services/dueDateParser.ts— 충돌 감지 로직 + 화이트리스트 추가 (~30 줄)tests/unit/dueDateParser.test.ts— 새 fixture 5+ 케이스
- 코드 (2차 C):
dueDateParser의ParseResultinterface 확장NoteCard.DueDateBadge의 props 확장 + 시각 표시- IPC / preload / store 의 due_date 타입 동반 갱신 (confidence 도 expose 시)
- 로깅:
AiWorker의ai.done메타에dueDateConfidence추가 (기존dueDateSource: rule|ai|none와 함께)
- 문서:
- 본 항목 promoted 시
2026-04-MM-due-date-rule-limits.md(가칭) 으로 추출 - F1 spec (
2026-04-26-f1-due-date.md) 의 §"후속" 에 본 항목 링크 추가
- 본 항목 promoted 시
- slice spec §1.3 영향: dogfood 종료 조건 "AI 결과 7/10 수용" 의 측정에 due_date confidence 가 들어가야 의미 있는 데이터 됨 — 본 항목이 그 측정 인프라 제공.
비고
본 피드백은 F1 promoted 후 첫 실사용 신호다. v0.2.1 dogfood 의 의도된 측정 사이클 (≥1주 soak → F4-A·D 결정) 와 같은 흐름에 자연스럽게 합류하는 항목이고, 다음 cut (v0.2.2 또는 v0.3.0) 의 후보. 단계 1 (A+B) 만 작은 PR 로 분리 가능 — 즉시 시도해도 위험 0.
규칙 파서 폐기 (E) 는 매력적이지만 AI 가 항상 떠 있는 dogfood 환경 가정 이 중요. OllamaBanner 가 자주 뜨는 환경 (LAN 박스 다운 등) 에선 결정론적 매치가 가치 있음. 이 트레이드오프는 dogfood 1주 데이터 (Ollama uptime · health success rate) 보고 결정.
F8. Windows 11434 포트 OS-level reserved (🚀 promoted → v0.2.3.1/v0.2.4)
진행 상태: 🚀 promoted → PR #21 (in-app Ollama 설정), v0.2.4 release.
발견: 2026-05-04 dogfood 시작 시도 직후, Windows 머신.
관찰
v0.2.3 binary 설치 후 첫 실행 시 OllamaBanner 가 "unreachable" 상태 지속. curl http://localhost:11434/api/tags 응답 없음. 하지만 ollama app.exe 프로세스는 떠있음. 진단 결과:
- Ollama server 가 11434 bind 무한 실패:
Error: listen tcp 127.0.0.1:11434: bind: An attempt was made to access a socket in a way forbidden by its access permissions. netsh int ipv4 show excludedportrange protocol=tcp→ 11242–11941 범위 (8개 100-port 블록) reserved- 원인: WSL2 (Ubuntu Running) + Hyper-V
hns(Host Network Service) 가 부팅 시 동적 NAT 용 포트 블록 할당 — 11434 가 포함됨
제안 방향
v0.2.3.1 → v0.2.4 cut: env var 의존 제거, in-app endpoint/model 설정 UI 추가. 트레이 메뉴 + OllamaBanner "설정" 링크 → modal → JSON 영속화 (<profileDir>/settings.json).
추가: 사용자가 빈 포트 (11942 등) 로 Ollama 재시작 후 in-app 에서 endpoint 변경 — 시스템 설정 변경 (excludedportrange 등) 없이 dogfood 즉시 unblock.
결정 대기
- (해결됨) endpoint + model 둘 다 in-app 설정 가능해야 하는가 → Q1=B 결정 (v0.2.3.1 spec)
- (해결됨) JSON 영속화 vs SQLite 새 테이블 → Q3=B JSON (migration 회피)
- (해결됨) Settings precedence → settings > env > default
가설·측정
| # | 가설 | 측정 |
|---|---|---|
| H8.1 | dogfood 사용자 의 ≥30% 가 비기본 endpoint 사용 (LAN 또는 다른 포트) | telemetry ollama_settings_changed (count-only, v0.2.7) |
| H8.2 | 11434 reserved 가 다른 머신에도 발생 | LAN 머신 / 동료 dogfood |
범위
- In: SettingsService + ProviderHolder + OllamaSettingsModal + IPC + 트레이 메뉴 항목
- Out: Multi-provider abstraction (OpenAI 등), Settings dropdown UI (v0.2.4 freetext)
영향
- Spec:
docs/superpowers/specs/2026-05-04-v0231-ollama-settings-design.md - Backlog 잔여: #39 (
ollama_unreachable.reason의 endpoint URL PII 우회 노출 — telemetry 하드닝 v0.2.7)
F9. 앱 다중 인스턴스 spawn — SQLite race 위험 (🚀 promoted → v0.2.5 critical hotfix)
진행 상태: 🚀 promoted → PR #23 critical hotfix, v0.2.5 release.
발견: 2026-05-05 dogfood 도중. v0.2.4 설치 후 단축키 / 트레이 / 시작메뉴 클릭 반복 시.
관찰
앱 아이콘 클릭 시마다 새 process spawn. 트레이 아이콘 여러 개 누적. 작업관리자 에서 Inkling.exe process 다중 확인. 잠재 영향:
- SQLite WAL 동시 write → DB 손상 가능
- AiWorker 중복 polling → 같은 pending_jobs 두 process race
- HealthChecker 중복 polling → Ollama 부하 + telemetry 이중 emit
settings.jsonatomic write 의 temp/rename race
제안 방향
Critical hotfix — app.requestSingleInstanceLock() 호출 + second-instance event handler 로 기존 inbox 창 restore + show + focus.
결정 대기
(해결됨) — Electron 표준 패턴 직접 적용.
범위
- In:
src/main/index.ts진입점 (whenReady 전 lock 획득). 단일 21줄 변경. - Out: None — cross-platform 자동 동작.
영향
- v0.2.5 critical hotfix release (
Inkling Setup 0.2.5.exe) - Backlog 잔여: #46 hidden-start race (NSIS 직후 사용자 클릭 + autostart
--hidden동시 시도) — v0.2.6 (PR #24) 에서additionalData패턴으로 해결 완료.
비고
dogfood 발견 → 4시간 안에 hotfix release. 잠재 데이터 손실급 버그라 patch increment (v0.2.5) 사용. v0.2.4 사용자 즉시 업그레이드 권장.
F10. 버전 / 빌드 정보 표시 surface 부재 (🚀 promoted → v0.2.4)
진행 상태: 🚀 promoted → PR #22, v0.2.4 release.
발견: 2026-05-04 dogfood 도중. 머신 간 버전 일치 검증 시도 시.
관찰
설치된 Inkling 의 버전을 UI 어디서도 확인 못함. 트레이 메뉴 / Inbox 푸터 / About 모달 모두 부재. 핸드오프 후 다른 머신 (Mac vs Windows) 에서 같은 버전인지 검증 path 없음. issue report 시 첨부할 디버그 정보 (Electron / Node / OS / profileDir) 도 노출 안 됨.
제안 방향
트레이 메뉴 마지막 항목 (종료 직전) "Inkling 정보..." → native dialog.showMessageBox. 표시:
- 버전 (
app.getVersion()) - Electron / Node 버전
- OS (
platform()+release()) - 데이터 위치 (
app.getPath('userData'))
버튼: 확인 / 데이터 위치 열기 (shell.openPath) / 정보 복사 (clipboard.writeText).
영향
- v0.2.4 cut 동봉. 별도 spec 없음 (단순 추가).
- Backlog 잔여: Inbox footer 형태 검토 (v0.2.7 — 항상 보이는 작은 버전 라벨)
F11. Single-instance lock 부재 (🚀 promoted)
진행 상태: 🚀 promoted → F9 와 동일 cut (v0.2.5 hotfix).
F9 와 root cause 동일. 원래 별개 발견이었지만 fix 가 같음 — 본 항목은 F9 의 부분으로 흡수.
F12. 윈도우 자동 실행 옵션이 재시작 후 풀려있는 버그 (🚀 promoted — v0.2.7 deeper fix)
진행 상태: 🚀 promoted → docs/superpowers/specs/2026-05-06-v027-cross-platform-design.md §9. v0.2.7 진단 노출 (withArgs/noArgs/registry/execPath + mismatch 경고 + 재등록 버튼) 적용 — 설정 페이지 "자동 실행" 섹션에서 사용자가 진단 정보 직접 확인 + 1-클릭 재등록 가능.
발견: 2026-05-05 dogfood 도중. autostart 토글 후 재시작.
관찰
트레이 메뉴 "윈도우 시작 시 자동 실행" 체크 → 종료 → 재실행 → 체크박스 풀려있음. app.setLoginItemSettings({ openAtLogin, args: ['--hidden'] }) 호출 후 다음 부팅 시 app.getLoginItemSettings() 가 openAtLogin=false 반환.
제안 방향 (현 cut: 진단 fallback)
추정 원인:
- (a) Windows registry path mismatch (NSIS 설치 위치 변경 / 버전 업데이트 시 새 디렉터리)
- (b) Electron
setLoginItemSettingsWindows 구현 의 path canonicalization - (c)
args: ['--hidden']와 actual launch args 비교 mismatch —getLoginItemSettings()가 args 없이 호출되면 mismatch
v0.2.6 적용:
getLoginItemSettings({ args: ['--hidden'] })명시 → 트레이 checkbox checked 상태 가 실제 args 와 정합 비교autostart.state진단 로그 (withArgs vs noArgs 비교 + executableWillLaunchAtLogin) — dogfood 에서 실제 동작 로그 수집
결정 대기
dogfood 후 autostart.state 로그 분석:
- args 명시 fix 만으로 충분 → close
- 여전히 mismatch → registry 직접 inspect (HKCU\Software\Microsoft\Windows\CurrentVersion\Run\inkling) → exe path 확인 → executable path canonicalization 검토
영향
- dogfood UX 핵심 마찰 — autostart 가 핸드오프 시 매번 수동 재설정 필요. 자동 실행 의도 자체가 dogfood "잊지 않고 매일 사용" 목적인데 깨짐.
- v0.2.6 진단 fallback 로 일단 시도, v0.2.7 deeper fix 영역.
F13. PR review 발견: restoreNote production path dead code (🚀 promoted → v0.2.6 round 1 Critical fix)
진행 상태: 🚀 promoted → PR #24 round 1 Critical fix, v0.2.6 release.
발견: 2026-05-05 PR #24 round 1 reviewer (Claude code-reviewer subagent).
관찰
v0.2.6 cut 의 B1 (#10 restoreNote) 작업이 새 메서드 NoteRepository.restoreNote(id) 추가했지만 — production path 가 옛 메서드 repo.restore() 호출 중. CaptureService.restoreNote (line 93) 가 this.repo.restore(noteId) 호출 → deleted_at = NULL 만 set, ai_status='failed' 그대로 + pending_jobs 미재생성.
즉 새 메서드는 unit test 만 검증, 실제 사용자가 trash → AI fail → restore 흐름 시 영구 fail 상태 그대로.
Fix
Round 1 Critical fix (commit a991008):
CaptureService.restoreNote가repo.restoreNote호출 (production path 활성화)before의ai_status가failed또는pending이면worker.enqueue(noteId)추가 호출 — in-memory AiWorker queue 갱신 (다음 app start 까지 대기 X)
테스트 +2 (CaptureService 의 enqueue 호출 검증).
비고
Round 1 reviewer 의 발견 가치 = production path 와 unit test 가 갈라진 dead code 패턴. 비슷한 패턴 다른 곳도 점검 가치. v0.2.7 brainstorm 시 grep 으로 "신 메서드 vs 옛 메서드 둘 다 존재 + 호출자 옛 사용" 패턴 검사.
F14. macOS dock 클릭 시 hidden 창 재현 안 됨 (🚀 promoted → v0.2.7)
진행 상태: 🚀 promoted → docs/superpowers/specs/2026-05-06-v027-cross-platform-design.md §8. 2026-05-05 v0.2.6 dogfood 발견.
발견: 2026-05-05 김태현 macOS dogfood 도중.
관찰
- macOS 에서 inbox 창 닫음 (빨간 신호등) → 창 사라짐.
- Dock 에는 Inkling 아이콘이 "켜져 있음" 표시 (점) 으로 그대로.
- Dock 아이콘 클릭 → 창이 안 뜸. 클릭이 그냥 무시됨.
- 트레이 메뉴 "보관한 메모 보기" 로는 정상 호출 가능 (별 이슈 없음).
- 앱을 완전히 종료 후 재실행 해야만 창이 다시 뜸.
제안 방향
추정 원인 (코드 확인 결과):
- src/main/windows/inboxWindow.ts:39-44 — close 이벤트에서
app.isQuitting === false면e.preventDefault()+inboxWindow.hide(). 즉 창은 살아있고 단지 hidden. - src/main/index.ts:411-413 —
app.on('activate', () => { if (BrowserWindow.getAllWindows().length === 0) createInboxWindow(); }). 하지만 hidden 창은 destroy 되지 않았으므로getAllWindows().length === 1. 분기 안 타고 no-op.
따라서 fix 방향은 단순:
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.tsactivate 핸들러 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 로
notesINSERT (raw_text) +pending_jobsINSERT (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. 트레이 의존도 ↓ + 별도 설정 페이지 (🚀 promoted → v0.2.7)
진행 상태: 🚀 promoted → docs/superpowers/specs/2026-05-06-v027-cross-platform-design.md §6, §7. 트레이 = quick-capture / 보관함 / 설정 / 종료 4-항목 minimum 으로 강등 + inbox window 안 SettingsPage (AI provider · 자동 실행 · 백업/복원 · 내보내기/가져오기 · 텔레메트리 · 정보 6 섹션) 신설.
발견: 2026-05-05 dogfood 후속 결정.
관찰
- 현재 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 흡수 자연스러움.
- (a) inbox 안 별도 라우트 (e.g.,
- 트레이 잔류 항목: "설정..." 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 설정 변경, 백업 등) 만 이동하고 자주 쓰는 캡처/보관함 은 트레이 잔류 → 체감 마찰 ↓ 예상.
F17. 휴지통의 의미 혼재 — 완료/보관과 버림 구분 (🚀 promoted → docs/superpowers/specs/2026-05-09-v029-cut-b-design.md)
진행 상태: 🚀 promoted → v0.2.9 Cut B. status 4분기 (active/completed/archived/trashed) + AI 자동 분류 버튼 + 자유 텍스트 사유.
발견: 2026-05-09 v0.2.7 release 후 본인 dogfood.
관찰
- 현재 메모 destination = active(
deleted_at IS NULL) 또는 휴지통(deleted_at != NULL) 단일 분기. - 사용자 의도가 갈리는 case:
- (a) 불필요해서 버림 — 잘못 적은 캡처, 더 이상 의미 없음. 휴지통 자연스러움.
- (b) 완료해서 더 이상 안 띄움 — 작업 끝났지만 기록은 보존하고 싶음. 휴지통은 의미 부적합 (회수 대상이 아니라 정리 대상).
- (c) 급하지 않아 미루기 — 지금은 안 띄우지만 나중에 다시 보고 싶음. 휴지통도 active 도 어색.
- 모두 휴지통으로 보내면 의미 혼재 + 30일 후 영구 삭제 정책 (현재) 이 (b)/(c) 의도 깨뜨림.
제안 방향 (옵션 분석)
A. status 컬럼 분기 (notes 테이블에 status: 'active' | 'completed' | 'archived' | 'trashed'):
completed: 작업 끝, 영구 보관 (회수 대상 아님, 검색 가능)archived: 장기 보관 (회수 가능, 별도 view)trashed: 30일 후 영구 삭제 (현재 휴지통)- inbox 탭 + 휴지통 탭 외에 "완료" / "보관함" 탭 추가
- 마이그레이션 비용 + UI 변경 (NoteCard 액션 메뉴 + 헤더 탭)
B. AI 자동 분류 (옵션 A 의 extension):
- "완료" 키워드 / 패턴 (예: "X 끝남", "처리됨", "결재됨") AI 가 감지 → 자동
status='completed'제안 - 사용자가 confirm/dismiss
- F19 의 recall 강화와 결합 시 효율 ↑
C. 휴지통 의미 유지 + 보관함만 별도 (간단):
- 휴지통은 그대로 (불필요 — 30일 영구 삭제)
- 보관함만 신규 —
status='archived'(회수 가능, 영구 보존) - 완료 / 미루기 모두 보관함 사용
- 변경 작음, 의미 명확
결정 대기 (v0.2.8 brainstorm)
- 보관함 detail UI: 별도 탭 vs 별도 라우트 vs filter 토글
- "완료" 와 "보관" 을 같은 destination 으로 둘지 (옵션 C) vs 분리 (옵션 A)
- AI 자동 분류 (옵션 B) — 정확도 + false-positive risk 측정 필요. v0.2.8 본 cut 보다 나중 가능.
가설·측정
- 본인 dogfood: 2주간 휴지통 이동한 메모 중 (a)/(b)/(c) 비율 — telemetry 또는 자기 회상 으로 측정. (b)/(c) 비율 ≥30% 면 의미 분기 가치 큼.
- 옵션 C 후 보관함 사용 빈도 — active 메모 대비 비율.
범위
- 옵션 A: 큰 작업 (DB 마이그레이션 + UI 탭 + IPC + telemetry kind 추가). 별도 spec 가치.
- 옵션 C: 1주 spike 가능 (status 컬럼 또는 별도
archived_at추가 + UI 탭). - 옵션 B: 추가 cut — 옵션 A/C 안정 후.
영향
- 메모 의미가 명확해짐 — "버림" vs "정리" 구분.
- 휴지통의 30일 영구 삭제 정책 유지 가능 (의미 혼재 X).
- F18 (사유 입력) 와 결합 시 사용자 의도 데이터 누적 → recall 알고리즘 (F19) 기여.
F18. 메모 휴지통/보관 이동 시 사유 입력 (🚀 promoted → docs/superpowers/specs/2026-05-09-v029-cut-b-design.md)
진행 상태: 🚀 promoted → v0.2.9 Cut B. notes.move_reason 자유 텍스트 컬럼 + MoveStatusModal 사유 입력.
발견: 2026-05-09 v0.2.7 release 후 본인 dogfood.
관찰
- 휴지통 이동 = silent (단순
deleted_at셋팅). - 사용자 의도 다양 ("완료", "급하지 않음", "더 이상 필요 없음", "잘못 적음" 등) — 데이터로 보존 안 됨.
- 사유 데이터가 있으면:
- 자기 회상 (왜 버렸는지 다시 보기)
- recall 알고리즘 (F19) 학습 입력 — "급하지 않음" 메모는 N일 후 재surface
- telemetry 분석 (어떤 종류 메모가 빠르게 trash 되는가)
제안 방향
A. 자유 텍스트 reason 필드 (notes.deleted_reason VARCHAR 또는 별도 trash_log 테이블):
- 휴지통 이동 시 prompt: "왜 버려? (선택사항)" 한 줄 입력
- 빈 값 허용
- 검색/필터 가능
B. preset 사유 + 자유 텍스트 옵션:
- 빠른 선택: "완료" / "급하지 않음" / "잘못 적음" / "기타"
- "기타" 선택 시 자유 텍스트
- 통계 가능 (preset 분류)
C. F17 의 status 분기 + 사유 결합:
- status='completed' 이면 사유 = "완료" 자동 inferred
- status='archived' 이면 사유 입력 prompt
- status='trashed' 이면 사유 선택사항
결정 대기
- 사유 입력 friction vs 데이터 가치 — 매번 묻으면 capture 흐름 깨짐 risk
- preset 만 vs 자유 텍스트 — preset 만이 friction 최소
- 위치: NoteCard 인라인 dropdown vs 별도 modal
가설·측정
- 본인 dogfood 1주 — 사유 입력 비율 (skip 없이 입력) ≥50% 면 데이터 가치 충분.
- 사유 distribution — preset N개 / "기타" 비율 — preset 명세 검증.
범위
- A: 1일 (DB column + UI prompt + IPC). 가장 작음.
- B: 1.5일 (+ preset UI).
- C: F17 의 옵션 A/C 안에 포함 가능 (한 cut).
영향
- 사용자 의도 데이터 누적 → F19 recall 알고리즘 입력 + 자기 회상 surface.
- F17 의 status 분기 가치 ↑ (사유 + status 의 의미 결합).
- friction 우려 — preset 또는 skip 가능 으로 완화.
F19. 획기적 recall 메커니즘 (✅ promoted v0.2.11 Cut D — A+D 옵션)
진행 상태: ✅ promoted v0.2.11 Cut D — A (FTS5 search) + D (일/주/월 회고 view) 적용. m007 마이그레이션 + NoteRepository.search + reviewAggregate + SearchBox + ReviewView. B/C/E/F 옵션은 v0.3+ deferred.
발견: 2026-05-09 v0.2.7 release 후 본인 dogfood. "메모의 빠른 기록도 중요하지만 적절한 recall 도 훨씬 중요" — 본인 표현.
관찰
- 현재 recall surface:
- RecallBanner (v0.2.3 #6) — 1일 1회, 14~21일 전 candidate 1건. 한 번에 1건 + dismiss 후 다음 날까지 안 뜸.
- RecoveryToast — 주간 회복 ping (1주 capture 끊김 시 한정).
- search/filter — tag 필터링만, free text search 없음.
- 빠른 기록 (capture) 는 잘 됨 — 한 줄 적기 + 트레이 hotkey 가 ≤1초 완성.
- recall 은 약함:
- 적극적 recall 안 됨 (메모를 다시 봐야 의미 있는데 surface 가 너무 약함)
- search 부재 — "뭐였더라" 회상 시 인덱스 없음
- context-based recall 없음 (시간/태그/장소 기반)
- AI 가 capture 단계에서만 활용, recall 단계 X
- 사용자 표현 "획기적 방법" — 현 RecallBanner 의 점진 개선이 아니라 질적 변화 요구.
제안 방향 (브레인스토밍 후보 — v0.2.8 spec 단계에서 압축)
A. Free text search:
- inbox 헤더 search box → raw_text + summary + tags 인덱스 검색
- SQLite FTS5 (Full-Text Search) 활용
- 가장 작은 단위 첫걸음. 다른 옵션의 prerequisite.
B. Context-based recall:
- 시간: "이 시간대 (오전/오후)" 메모 추천
- 요일: "이전 월요일" 메모
- 태그 클러스터링 — 현재 active tag 와 연관 메모 surface
- 사용자가 inbox 보고 있을 때 sidebar 또는 banner 로 노출
C. AI-driven 연관 메모 추천:
- 현재 보고 있는 메모와 의미 유사한 옛 메모 surface (embedding-based or LLM-judged)
- "이거랑 비슷한 옛날 메모 N건" UI
- Ollama embedding API 활용 가능 (모델 추가 부담)
D. 회고 view (일/주/월):
- "지난 주 기록" 한 페이지 — N건 메모 + tag distribution + due date 진행
- 정해진 시점 (월요일 아침 등) banner 또는 별도 라우트
E. Spaced repetition recall:
- Anki 같은 SM-2 알고리즘 — "잊을 만한 시점" 에 surface
- 사용자가 confirm/dismiss → 다음 surface 시점 학습
- 현 RecallBanner 의 발전형
F. 검색 + AI 자연어 query:
- "지난 달 회의 메모 보여줘" 자연어 → SQL or filter 자동 변환
- Ollama function-calling 또는 prompt template
- C/D 의 통합 진입점.
결정 대기 (v0.2.8 brainstorm)
- "획기적" 의 정의: 현 RecallBanner 점진 vs 새 핵심 surface
- 1차 cut scope — A (search) 만으로 충분한 가치인가, B/C 와 묶어야 가치인가
- AI 의존 (C/F) 의 latency / 정확도 trade-off — Ollama 추론 비용
- F17/F18 의 status + 사유 데이터 가 recall 입력으로 활용 가능한가
가설·측정
- 본인 dogfood: 옛 메모 다시 본 횟수 / 캡처 수 비율 — 현재 < 5% 추정. ≥20% 까지 끌어올리는 것이 "획기적" 기준.
- search 사용 빈도 (A 만 도입 시) — 일 1회 미만이면 의미 약함.
범위
- A: 3-4일 (FTS5 + UI search box).
- B: 1주 + (시간/태그/요일 로직 + UI).
- C: 2주 (embedding 인프라 추가 — Ollama embedding 모델 + 벡터 저장).
- D: 1주 (회고 라우트 + aggregate query).
- E: 2주 (SM-2 + UI + 사용자 feedback loop).
- F: C 위에 추가 1주.
→ 한 cut 에 다 넣기 무리. v0.2.8 = A + D 또는 A + B 권장. C/E/F 는 v0.3+.
영향
- 핵심 가치 (capture → 의미 있는 보존 → 다시 보기) 의 후반 절반 완성.
- F1 (Due Date), F4 (Aha Moment), F17 (status 분기) 모두 recall 강화로 가치 ↑.
- v0.4 slice 종료 조건 (본인 2주 dogfood 완주) 의 1주차 검증 항목 = recall 효과 측정.
- 큰 cut — separate spec 이 자연스러움.
F20. 기존 메모 본문 (raw_text) 수정 가능성 (✅ promoted v0.2.10 Cut C — invariant 폐기)
진행 상태: ✅ promoted v0.2.10 Cut C — raw_text 불변 invariant 폐기, note_revisions 테이블로 변경 이력 보존. m006 마이그레이션 + updateRawText/listRevisions/restoreRevision repo API + RevisionHistoryModal UI. AI 재실행 input = current latest raw_text (옵션 B).
발견: 2026-05-09 v0.2.7 release 후 본인 dogfood.
관찰
- 현재 NoteCard 의 EditableField 는 AI 결과 필드 (title / summary / tags) 만 수정 가능.
- raw_text (capture 시점 원본 본문) 는 read-only — 메모리 정책상 load-bearing invariant.
- dogfood 시 빈도 높은 use case:
- 오타 정정 — 빠른 capture 중 잘못 입력 (예: "회으" → "회의")
- 의미 보강 — 나중에 보니 정보 부족 ("회의" → "월요일 분기 회의 안건")
- 잘못된 캡처 정정 — 음성/clipboard 자동 입력 시 오인식
제안 방향 (옵션 분석 — invariant trade-off)
A. raw_text 수정 허용 (invariant 폐기):
- 가장 단순 — EditableField 가 raw_text 도 수정 가능.
- 비용: capture 시점 원본 lost. AI 재실행 시 input 이 user-edited 본문 — 그 시점 의도와 다를 수 있음.
- 영향: 다른 spec (F1 Due Date, F4 Aha Moment 등) 의 raw_text 불변 가정 재검토 필요.
B. raw_text 불변 유지 + user_edited_text 필드 추가:
- 원본 보존 + 사용자 정정 별도 컬럼.
- NoteCard 가 user_edited_text 우선 표시 (없으면 raw_text fallback).
- AI 재실행 시 어느 입력을 사용할지 결정 — 원본 (안정성) 또는 사용자 정정 (의도 정확성).
- 마이그레이션 + UI 분기 비용.
C. raw_text 수정 허용 + revision history:
note_revisions테이블 — 변경 이력 보존.- 사용자가 옛 버전 회수 가능.
- 비용 가장 큼 (스키마 + UI + 회수 흐름).
D. invariant 유지 (현 동작) — 이 피드백 reject:
- 정책 사유: capture = "기록", 수정 시 의미 본질 변경.
- 그러나 dogfood 실용 마찰 클 가능성.
결정 대기 (v0.2.8 brainstorm — 핵심 결정)
- invariant 재검토: 본인 dogfood 1주 누적 시 raw_text 정정 욕구 빈도 측정. 주 ≥3건 면 옵션 A/B/C 검토 가치.
- AI 재실행 input: raw_text vs user_edited — 메모리 정책
AI 재실행은 user-edited 필드 덮어쓰기 금지와 정합 검토. - F1 (Due Date 파서), F4 (Aha Moment) 의 raw_text 가정 영향 분석.
가설·측정
- 본인 dogfood 1주: 메모 정정 욕구 발생 횟수 / 캡처 수. ≥10% 면 옵션 A 또는 B 강한 motivation.
- 옵션 B 시 user_edited 사용 비율 — ≥30% 면 분기 가치.
범위
- A: 1일 (EditableField 가 raw_text 도 처리 + IPC 수정).
- B: 3-4일 (스키마 마이그레이션 + UI 분기 + AI 재실행 정책 결정).
- C: 1주 + (revisions 테이블 + UI 회수 흐름).
영향
- load-bearing invariant 재검토 — 메모리 정책 갱신 가치.
- F1 / F4 / F17 / F19 모두 raw_text 가정 재검토 영향.
- 사용자 마찰 ↓ (오타/오인식 정정 가능) vs 기록 본질 약화 trade-off.
- 옵션 B 가 가장 균형 — 원본 보존 + 사용자 정정 모두 가능.
F21. 다기기 git-based 동기화 (✅ promoted v0.3.0 Cut E — 양방향 + Configure UI + Conflict)
진행 상태: ✅ promoted v0.3.0 Cut E — 옵션 A (자동 rebase) + B (Configure UI) + C (conflict UI). SyncService 양방향 6단계 (export → commit → fetch → rebase → re-import → push), NoteRepository.upsertFromSync (sync 전용 3 분기), SettingsService.{getSyncRepoUrl,isAutoSyncEnabled,getSyncIntervalMin} + SyncTimer (자동 주기 + reconfigure), SyncSection UI + ConflictModal (local/remote 2 choice, both deferred v0.3.1+). 단위 608 → 679. dogfood 1주 soak 후 Cut F (F24 vision) 진입.
발견: 2026-05-09 v0.2.7 release 후 본인 dogfood. 사용자 표현: "그 중심에 git repo 를 쓸 수 있으면 좋겠어".
관찰 (현재 동작)
src/main/services/SyncService.ts 의 sync():
- SQLite → markdown export (ExportService) 를
<profileDir>/sync/에 산출 git add -A && git commit -m "chore(notes): sync <ts>" && git pushnot_configured시 skip (<profileDir>/sync/가 git repo + origin remote 가져야 함)
즉 outbound only — 다른 기기로 보내는 흐름은 있음.
누락 부분 (다기기 동기화 충족 X)
- Pull: 다른 기기에서 push 한 변경 가져오기 —
git fetch && git pull흐름 부재 - Re-import: pull 한 markdown 을 SQLite 로 다시 적재 (
ImportService가 활용 가능 — F6 백업 복원 흐름과 유사) - Conflict resolution: 같은 노트를 두 기기에서 동시 수정 시 우선순위 + merge 정책
- Configure UI: 사용자가
<profileDir>/sync/에 git init +git remote add origin <url>수동 — GUI 부재 - raw_text 불변 + user-edited 덮어쓰기 금지 (메모리 정책) 다기기 환경에서 어느 기기 user-edited 가 정답인가 결정 필요 — F20 (raw_text 수정 옵션 B
user_edited_text) 와 강하게 연관
제안 방향
A. SyncService 양방향화 (가장 작은 첫걸음):
sync()가 push 전 pull 먼저 —git fetch && git rebase origin/main또는merge- pull 후 변경된 markdown → re-import 하여 SQLite 갱신
- conflict 시 user prompt (또는 일단 fail + 수동 resolve 안내)
B. Configure UI (설정 페이지 안 신규 sub-section 또는 별도 섹션):
- "동기화 저장소 URL" 입력 → SyncService 가
<profileDir>/sync/에 git init + remote add origin 자동 - 인증 안내 (SSH key / token) — Gitea/GitHub 양쪽 호환
- 마지막 sync 결과 + 시간 표시
C. Conflict resolution UX:
- 옵션 1:
git merge시도 → 실패하면 "양쪽 비교" UI (note id 단위, 각 기기 본문 + AI 결과 비교) - 옵션 2: timestamp 기반 자동 (마지막 수정 우선) — 데이터 lost risk
- 옵션 3: "내 기기 우선" / "원격 우선" / "수동 merge" 사용자 선택
D. F20 (user_edited_text) 옵션 B 와 결합:
- raw_text = 캡처 시점 원본 (절대 충돌 X — capture 는 한 기기에서만)
- user_edited_text = 다기기 sync 대상. timestamp + conflict resolution 적용
- AI 결과 (title/summary/tags) = 어느 기기 가장 최근 결과 사용
결정 대기 (v0.2.8 brainstorm)
- 충돌 처리 정책 — A 옵션의 default (rebase / merge / fail) 결정
- F20 invariant 결정 후 결합 — F20 옵션 B (
user_edited_text) 가 채택되면 sync 가치 ↑ - pull 후 re-import 시점 — manual ("지금 동기화" 클릭) vs 주기적 (5분/30분 자동)
- 다기기 운영 시 Aha Moment metric (7일/3일) 측정 — sync lag 영향
가설·측정
- 본인 dogfood: Mac + Windows 두 기기 사용 시 (메모: 본인 Mac=업무, Windows=개인+dogfood) — 현재 single-device. 양방향 sync 후 Mac dogfood 가능성 측정.
- conflict 발생 빈도 — 양 기기에서 동일 노트 수정 케이스 (낮을 것 추정).
범위
- A (양방향 sync) + B (Configure UI): 1주 spike 가능.
- A + B + C (conflict UI): 2주.
- D (F20 결합): F20 채택 후 추가 1주.
영향
- 다기기 운영 → Aha Moment metric 직접 기여 (Mac 업무 시간에도 capture 가능).
- F20 (raw_text 수정) + F19 (recall) 모두 sync 데이터 일관성 의존.
- v0.4 slice 종료 조건 (본인 2주 dogfood 완주) 의 핵심 인프라 — 단일 기기 dogfood 의 한계 극복.
F22. NoteCard 이미지가 회색 placeholder 만 표시 (🚀 promoted → docs/superpowers/specs/2026-05-09-v028-cut-a-design.md)
진행 상태: 🚀 promoted → v0.2.8 Cut A. inkling-media:// custom protocol + NoteCard <img> + IPC inbox:open-media + OS viewer 클릭. (commit 470384b + f6bea62 + 9cdea15)
발견: 2026-05-09 v0.2.7 release 후 본인 dogfood. 사용자 표현: "이미지 렌더링이 제대로 되지 않는 것 같아".
관찰
src/renderer/inbox/components/NoteCard.tsx:334-340:
{local.media.length > 0 && (
<div style={{ marginTop: 10, display: 'flex', gap: 6 }}>
{local.media.map((m) => (
<div key={m.id} style={{ width: 48, height: 48, background: '#eee', borderRadius: 4 }} title={m.relPath} />
))}
</div>
)}
<img> 가 아니라 회색 <div>. 즉 capture 시 첨부한 이미지가 보관함에서 회색 48x48 사각형만 표시 — title attribute (relPath) 만 hover tooltip 으로 보임. 실제 이미지 렌더링 자체 부재.
MediaStore 는 <profileDir>/media/<noteId>/<filename> 절대 경로로 파일 보존. relPath = media/<noteId>/<filename> 형태. Electron renderer 에서 직접 file:// 또는 custom protocol 로 src 매핑 필요.
추정 원인 (placeholder 인 이유)
- 초기 v0.4 slice 단계에 thumbnail 렌더는 후순위로 미루고 placeholder 로 둔 채 그대로 잔류.
- Electron renderer 가 raw
file://경로 보안 정책상 직접 접근 어려움 — custom protocol (inkling-media://) 또는 IPC handle 로 base64 변환 필요.
제안 방향
A. Custom protocol 등록 (권장):
- main process 에서
protocol.registerFileProtocol('inkling-media', ...)등록 —<profileDir>/media/하위 경로를inkling-media://<noteId>/<filename>으로 매핑 - NoteCard:
<img src={inkling-media://${m.relPath.slice(6)}} alt="" /> - 보안: scheme 별 allowlist + protocol handler 가 path traversal 검사
B. IPC 로 base64 변환 (작은 이미지에 한정):
inboxApi.getMediaDataUrl(relPath)→ main 이 file 읽고data:image/png;base64,...반환- renderer 에
<img src={dataUrl} /> - 큰 이미지 (수 MB) 시 메모리 부담
C. file:// 직접 (Electron 특수 설정 필요):
webPreferences.webSecurity: false— 보안 약화 risk. Reject.
결정 대기
- thumbnail 표시 vs 클릭 시 full-size modal — UX 선택
- 다중 이미지 (현재 capture 가 N개 첨부 가능) 의 grid layout
- 이미지 alt text — capture 시 입력 또는 AI 자동 생성 (옵션)
가설·측정
- 본인 dogfood: capture 시 이미지 첨부 빈도 — 현재 추정치 < 일 1건. ≥ 일 1건이면 이미지 흐름 가치 큼.
- 옵션 A 도입 후 NoteCard 클릭 시 modal full-size 사용 빈도 — UX 선택 검증.
범위
- A (custom protocol + thumbnail): 1-2일.
- A + click → full-size modal: + 0.5일.
- alt text AI 생성: 별도 cut.
영향
- 명확한 bug 수정 — 사용자 마찰 명백.
- F19 (recall) 의 시각적 단서 — 이미지 보일 때 메모 회상 ↑.
- v0.2.8 narrow scope 에 포함 가치 (1-2일 작업).
F23. 로컬 LLM 활성화 옵션 (Ollama-less 모드) (🚀 promoted → docs/superpowers/specs/2026-05-09-v029-cut-b-design.md)
진행 상태: 🚀 promoted → v0.2.9 Cut B. ai_status='disabled' enum + Onboarding wizard + 설정 토글 + Banner/HealthChecker 비활성 + requeueDisabled.
발견: 2026-05-09 v0.2.7 release 후 본인 dogfood. 사용자 표현: "Ollama 를 쓰지 못하는 환경을 위해 로컬 llm 활성화 옵션을 만들고, Ollama 를 안 쓰는 경우 그냥 원문만 저장하고 보여주도록".
관찰
- 현재 capture 흐름:
CaptureService.create()→ notes INSERT (ai_status='pending') →pending_jobsenqueue → AiWorker → Ollama 호출 → title/summary/tags 채움 → NoteCard 표시. - Ollama 의존 강제 — 회사 환경 / offline / low-resource device / 사용자 선호도 등 Ollama 안 쓰고 싶은 경우 옵션 부재.
- 현재 Ollama 끊긴 동안 capture 는 가능 (notes INSERT + pending_jobs enqueue), 단 ai_status 가 'pending' 또는 'failed' 로 고착 → FailedBanner / OllamaBanner 가 지속 노출 (사용자 불필요한 마찰).
제안 방향
핵심 설계: "AI 활성화" 토글 (default ON, OFF 시 raw-only 모드)
설정 페이지 → AI 제공자 섹션 → 새 토글 "AI 자동 처리 사용" (default ON).
A. OFF 일 때 동작
CaptureService.create()가 notes INSERT 시 ai_status='disabled' (신규 enum value) + pending_jobs enqueue skip.- AiWorker 가 'disabled' 상태 노트를 pull 안 함.
- NoteCard 표시:
- title = raw_text 첫 줄 (또는 빈 값) — fallback rendering
- summary = 빈 값 (UI 에서 hide)
- tags = 빈 배열 (tag filter 비활성)
- raw_text 그대로 노출 (이미 NoteCard 가 표시함)
- OllamaBanner / FailedBanner 비활성 (AI off 면 의미 없음).
- 트레이/banner 의 "지금 AI 처리" / "Ollama 재확인" surface 비활성.
B. OFF → ON 전환 시
기존 ai_status='disabled' 노트들 — 두 옵션:
- B1: 기존 disabled 잔류 (사용자가 "지금 처리" 버튼 1회 눌러야 재처리). 안전.
- B2: 자동 enqueue (모든 disabled → pending + pending_jobs INSERT). 사용자 의도 불일치 risk (옛 메모 갑자기 AI 처리되며 큐 폭증).
추천: B1 — 사용자 명시적 trigger 만 옛 노트 처리. 새 노트는 ON 이후 capture 분만 자동 처리.
C. ON → OFF 전환 시
- 큐의 pending 잔재 — drain (현 실행 중) + enqueue stop.
- 옵션: pending → disabled 자동 변환 (대량 cleanup) vs 잔류 (다시 ON 시 재개).
- 추천: 잔류 (사용자 의도 보존).
결정 대기 (v0.2.8 brainstorm)
- ai_status 새 enum 값 'disabled' vs 별도 컬럼 (notes.ai_enabled BOOLEAN)
- B1 vs B2 default — B1 추천.
- raw-only 모드의 NoteCard title fallback — raw_text 첫 줄 / 첫 N자 / 사용자 입력 prompt.
- F19 (recall) 가 raw-only 모드에서도 동작 — tag 부재 시 시간 기반 candidate 만.
- F17 (status 분기) 의 AI 자동 분류 (옵션 B) 가 raw-only 모드에서 비활성 — 정합 검토.
- 처음 설치 시 default — 메모리 정책 "주 타깃 OS 는 Windows + 본인 dogfood 우선" 고려, default ON 유지 (LAN Ollama 가정).
가설·측정
- 본인 dogfood: 회사 환경 (Mac 업무) 에서 Ollama 못 쓰는 시간 — raw-only 모드로 capture 만 가능해지면 dogfood metric 영향 측정.
- 사용자 (외부) 가 raw-only 시작 후 ON 전환 비율 — onboarding 흐름 검증.
범위
- A 기본 (토글 + ai_status 'disabled' + capture skip): 2-3일.
- B/C 전환 정책 (B1 추천 — 가장 작음): + 0.5일.
- raw-only NoteCard fallback (title=raw_text 첫 줄): + 0.5일.
- 합 3-4일 — v0.2.8 narrow scope 가능.
영향
- Ollama 의존성 옵션화 — 환경 다양성 (회사 / offline / 저사양) 대응.
- F17 (status 자동 분류 옵션 B) 무력화 — AI off 시 옵션 C (보관함만 별도) 가 default 흐름.
- F19 (recall) 가 tag 데이터 부재로 단순화 — context-based / spaced repetition 기반 가능 (search 는 raw_text 가 인덱스 source).
- F1 (Due Date 파서) 는 raw_text 정규식 기반이라 raw-only 모드에서도 동작 ✅.
- 메모리 정책 "raw_text 불변" 의 가치 ↑ — raw_text 자체가 1차 surface 가 되므로 보존 의의 강화.
- v0.4 slice 종료 조건 (본인 2주 dogfood 완주) 의 대안 경로 — Mac 업무 시간 raw-only capture + 저녁 Windows 에서 batch AI 처리 가능.
F24. 이미지 멀티모달 AI 분석 (✅ promoted v0.3.1 Cut F)
진행 상태: ✅ promoted v0.3.1 Cut F — Ollama vision 모델 (gemma3 family default) 활용. capability detection (app launch + manual refresh) + Configure UI dropdown + AiWorker vision integration (5MB cap + base64 변환). 자동 fallback (caption → text) + 'skipped' enum deferred v0.3.2+. 단위 679 → 710. dogfood: vision 결과 정확도 + 한국어 token 정확도 검증.
발견: 2026-05-09 v0.2.7 release 후 본인 dogfood. F22 (이미지 렌더링) + F23 (Ollama-less 모드) 와 강하게 연관.
관찰
src/main/ai/LocalOllamaProvider.ts:33-42 — 현재 /api/generate 호출 시 text-only prompt:
const res = await request(`${this.endpoint}/api/generate`, {
prompt: buildPrompt(input.text, input.todayKst, input.dueDateCandidates, input.vocab ?? []),
...
});
InferenceProvider.GenerateInput 인터페이스에 images 필드 부재. Ollama API 자체는 images: string[] (base64) 지원하나 모델이 vision 지원해야 함.
이미지가 있는 capture (paste 또는 첨부) 의 경우:
- 현재: title/summary/tags 모두 raw_text 기반만 — 이미지 내용 ignore
- 이미지만 있는 capture (raw_text 빈 값): AI 처리 무의미 → 사용자가 빈 메모 받음
제안 방향
A. Vision capability detection + opt-in 모델 선택 (권장):
- 설정 페이지 → AI 제공자 섹션 → "이미지 분석 모델" 입력 (별도 필드, default 빈 값 = 비활성).
- main process 가 startup / 사용자 트리거 시
GET /api/tags로 사용자 Ollama 의 모델 목록 조회 + vision capable 모델 (llava / llama3.2-vision / gemma3 family 등) 자동 감지 → 추천 표시. - 사용자가 vision 모델 명시 + 본인 cluster 에 해당 모델 pull 되어 있어야 enable.
- capability 부재 (모델 없음 / endpoint 끊김 / 빈 값) 면 vision 분석 skip — 텍스트만 + raw_text 처리.
B. 분석 흐름 (vision enabled 시):
각 capture 의 이미지 + raw_text 결합 prompt 전송:
- raw_text 있음 + 이미지 있음 → "다음 텍스트 + 이미지를 종합 요약" prompt
- raw_text 빈 값 + 이미지만 → "이미지 내용 요약 + 한국어 태그" prompt
- AI 응답 형식은 기존 (
title/summary/tags) 그대로 — vision 결과가 raw_text 자리에 들어가 자연스럽게 채워짐
C. InferenceProvider 인터페이스 확장:
interface GenerateInput {
text: string;
images?: Array<{ base64: string; mime: string }>;
...
}
LocalOllamaProvider 가 images 비어 있지 않으면 Ollama /api/generate 의 images: [base64...] 필드 추가 + vision 모델로 호출. provider 가 vision capability 부재 시 images ignore (graceful degrade).
결정 대기 (v0.2.8/v0.3 brainstorm)
- vision 모델 default 추천 — 한국어 + 이미지 동시 잘하는 모델 (llama3.2-vision / gemma3 family 등 — dogfood 검증 후 결정)
- 이미지 base64 변환 위치 — main process (MediaStore 가 이미 file path 보유) 가 자연스러움
- 처리 비용 — vision 모델 추론 시간 (수 초~수십 초) + 메모리 부담. capture 흐름 backend 처리 라 사용자 대기 X.
- raw-only 모드 (F23 OFF) 와 정합 — F23 토글 OFF 시 vision 도 OFF (자명).
- 이미지 alt text 자동 생성 (F22 가설 슬롯) 가능 — vision 모델이 alt 도 같이 출력하도록 prompt 설계.
가설·측정
- 본인 dogfood: capture 시 이미지 첨부 비율 — 현재 추정 < 일 1건. 일 ≥ 1건 누적 + vision 분석 결과 정확도 측정.
- vision 결과의 사용자 수정 비율 — 높으면 모델 부적합 (다른 모델 / prompt 튜닝).
- "이미지만 있는 capture" 의 처리 가능성 — vision 으로 의미 있는 title/summary 생성 가능한지 검증.
범위
- A (capability detection + 설정) + B (vision prompt) + C (InferenceProvider 확장): 1주.
- 이미지 alt text 자동 생성: + 0.5일.
- F22 (이미지 렌더링) 가 선행 prerequisite — 같이 묶으면 1.5주.
영향
- 멀티모달 capture — "사진만 찍고 끝" 흐름 가능 (회의 화이트보드 / 영수증 / 메뉴판 등).
- F22 (이미지 렌더링) 의 가치 ↑ — 보이는 이미지 + AI 가 의미 추출.
- F19 (recall) 강화 — vision-derived tags + summary 가 이미지 내용 기반 검색 가능하게 함.
- F23 (Ollama-less 모드) 와 trade-off — AI 토글 OFF 시 vision 도 자동 OFF (자명, 추가 분기 X).
- 메모리 정책 "raw_text 불변" 그대로 — vision 결과는 summary/tags 에만 반영.
- Ollama 의존성 ↑ (vision 모델 추가 pull 부담) — F23 OFF 시 회피 가능.
F25. 사이드바 — 메모 리스트 + 메모 저장소 리스트 (🌱 raw — v0.2.8/v0.3 후보, layout 큰 변화)
진행 상태: 🌱 raw — layout 재구성 + "저장소" 정의 필요. v0.2.8 brainstorm 시 F17/F21 와 함께 triage.
발견: 2026-05-09 v0.2.7 release 후 본인 dogfood. 사용자 표현: "사이드에 메모 리스트, 메모 저장소 리스트도 보여줬으면".
관찰
- 현재 inbox layout = single-pane (header + NoteCard list). 사이드바 부재.
- "메모 저장소" 의미 모호 — 추정 옵션:
- (a) 다중 profile/database — "회사 메모 / 개인 / 학습" 등 분리. 현재 single profile (
<userData>/default/). - (b) 카테고리/폴더 — 단일 DB 안 그룹화. 현재 tag 만 존재.
- (c) 다중 sync repo — F21 의 git sync 가 여러 remote 가능. 본인 + 외부 collaborator.
- (a) 다중 profile/database — "회사 메모 / 개인 / 학습" 등 분리. 현재 single profile (
- 사용자 의도 = (a) 가 가장 자연스러움 ("저장소" 표현). 본인이 dogfood 중 분리 욕구 발생 추정.
제안 방향 (사이드바 + 저장소 모델 분리 결정)
1. 사이드바 layout
좌측 또는 우측 column. 폭 240-320px. 상단: 저장소 selector. 하단: 메모 list (현 inbox compact view).
┌───────────┬────────────────────────────┐
│ 저장소 │ inbox / 휴지통 (탭) │
│ • 기본 ├────────────────────────────┤
│ • 회사 │ │
│ • 학습 │ NoteCard detail or grid │
├───────────┤ │
│ 메모 리스트│ │
│ - title 1│ │
│ - title 2│ │
│ - title 3│ │
└───────────┴────────────────────────────┘
2. "저장소" 정의 (큰 결정)
A. 다중 profile (<userData>/<profile-name>/ 별도 DB):
- 가장 정의 명확 — sqlite db / media / sync 모두 저장소 단위 분리
- 사용자가 새 저장소 생성 → migrations 새로 적용 → 빈 DB
- 메모 / 태그 / due / pending_jobs 모두 저장소 안 격리
- 마이그레이션 부담 —
resolveProfilePaths가 'default' fixed 인 부분 다중 지원 - AiWorker / HealthChecker / SyncService 등 모두 active profile 기반 재초기화 필요 (큰 refactor)
B. 카테고리/폴더 (단일 DB 안 notebook_id 컬럼):
- 가벼움 — schema 추가만, services 영향 적음
- 단점: "회사 메모 따로 백업/sync" 불가 (단일 DB 백업)
- F17 (status 분기) 와 비슷한 의미 layer (status + notebook 두 분기 가치 충돌 가능)
C. 단일 profile + 다중 git remote (F21 sync 관련):
- 한 DB → 여러 sync 대상 (회사 git + 개인 git)
- "저장소" 가 sync target 의미라면 자연스러움
- 데이터 자체는 분리 안 됨 — "메모 저장소" 이름과 의미 불일치 risk
추천: A — "저장소" 의 사용자 의도가 데이터 분리 (회사/개인) 라면 명확. 그러나 큰 refactor. 대안: B — 빠른 구현, 사용자 의도 (a) 일부 충족.
3. 메모 리스트 (사이드바 안)
현 inbox NoteCard list 의 compact 버전 — title + tag chip 만, raw_text/summary hide. 클릭 시 main 에서 NoteCard expand.
main pane 의 view 옵션:
- (i) 단일 detail (사이드 클릭으로 전환)
- (ii) 현재처럼 NoteCard grid (사이드는 scroll/jump 용)
추천: (ii) — 현 흐름 보존, 사이드바는 navigation 보조.
결정 대기 (v0.2.8 brainstorm)
- "저장소" 정의 — A/B/C 중 사용자 의도 확인 (직접 묻거나, dogfood 중 욕구 정확히 파악)
- 사이드바 토글 — default visible vs hide-by-default (좁은 화면 + 단일 저장소 시 noise)
- 메모 리스트 sort 기준 — 최신순 / tag / due date
- F17 (status 분기), F19 (recall search) 와 layout 조화 — 검색 박스 위치 (사이드 vs header)
가설·측정
- 본인 dogfood: "회사" / "개인" 메모 분리 욕구 빈도 — 1주 soak 후 측정. 빈도 낮으면 옵션 B 또는 C 충분.
- 사이드바 사용 빈도 — main pane 만으로 동작 가능하면 사이드바 noise.
범위
- A (다중 profile + 사이드바 + 저장소 selector): 2-3주. AiWorker / HealthChecker / SyncService / 마이그레이션 모두 영향.
- B (notebook_id + 사이드바): 1주. schema + repo 메서드 + UI.
- C (다중 sync remote + 사이드바 navigation 만): 0.5주 (F21 의 일부).
- 사이드바 자체 (저장소 결정 무관, navigation 기능만): 2-3일.
영향
- layout 큰 변화 — 현재 single-pane → two-pane. 좁은 화면 (1280×720 dev) 영향 검증 필요.
- F17 (status 분기) 와 conceptual overlap — "저장소" + "status" + "tag" 세 분기 layer 가 사용자 정신 부담.
- F19 (recall search) — 사이드바에 search box 둘지 결정.
- F21 (git sync) — 옵션 A 시 저장소별 별도 sync repo 자연스러움.
- 본인 dogfood metric — Mac 업무 (회사 메모) + Windows 개인 (dogfood) 분리 시 가치 ↑.
(다음 항목 자리)
새 피드백 추가 시 ## F26. 짧은 제목 (🌱 raw) 헤더로 시작. 표준 슬롯 6개 채우거나 비워둔 채 시작 가능.
v0.2.8 release 후 dogfood ≥1주 soak 동안 새 발견 항목들 여기 누적 → v0.2.9 brainstorm 트리거.