diff --git a/docs/superpowers/specs/2026-04-25-dogfood-feedback.md b/docs/superpowers/specs/2026-04-25-dogfood-feedback.md index c150c73..3f8c75c 100644 --- a/docs/superpowers/specs/2026-04-25-dogfood-feedback.md +++ b/docs/superpowers/specs/2026-04-25-dogfood-feedback.md @@ -418,6 +418,165 @@ strategy.md 가 다루는 cue 는: --- +## F5. 마크다운 일괄 export (RAG 활용 가정) (🌱 raw) + +**발견:** 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_at +- `note_tags` (+`tags`) — 태그 + source(ai/user) +- `media` — note 첨부 이미지 메타 (`rel_path` 가 MediaStore 의 프로필 디렉터리 기준) +- (F1 promoted 시) `due_date`, `due_date_edited_by_user` + +내보낼 자산은 두 종류: +1. **노트 본문 + 메타데이터** — 텍스트 +2. **첨부 이미지** — 바이너리 파일 (현재는 `/media/`) + +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 친화): + +```markdown +--- +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 리뷰 마무리하고, 회고 양식은 팀에 공유. +오후 미팅 중에 떠올랐음. + +![](media/014a3b9c__1.png) +``` + +**index.jsonl** (RAG 인덱싱용 1줄=1노트): + +```json +{"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. **포맷 1차안 확정**: one-file-per-note + frontmatter + index.jsonl 트리플 vs 단일 monolithic .md vs 두 형식 동시 출력? → RAG 우선이면 트리플이 압도적이지만 사용자 선호 확인 필요. +2. **미디어 포함 기본값**: 항상 동봉 vs 사용자 선택 (체크박스). 슬라이스 §1.1 의 "raw_text 본문에 민감정보 가능" 정책 — 이미지가 스크린샷인 경우 export 가 의도치 않은 노출 통로가 될 수 있음. **기본 동봉 + export 시 다이얼로그에 "이미지 N개 포함됩니다" 명시** 가 안전. +3. **삭제된 노트 처리**: SQLite 에 soft-delete 컬럼이 없음. 현재는 hard delete. export 결과는 *현 시점* 스냅샷만 — 삭제 이력 없음. 충분한가, 별 issue 인가? +4. **필드 정책 — provenance 표현**: `title_source: ai|user` 같은 단일 enum vs `title: { value, source, edited_at }` 객체. RAG 파이프라인의 frontmatter parser 마다 다름 — 평탄한 enum 이 호환성 좋음. +5. **embedding_text 합성 규칙**: title + raw_text + tags 단순 결합 vs raw_text 만 (가장 untouched) vs title + summary + raw_text. 본인 RAG 사용 패턴 미정 — 1차는 raw_text 단독으로 시작 + 옵션화. +6. **파일명에서 raw_text vs ai_title 사용**: ai_title 사용이 가독성 좋지만 AI 변경 시 파일명도 변하는 안티패턴. **ai_title 사용 + 사용자가 수동 export 트리거 시점 기준** 으로 동결 (재 export 시 새 파일명). 파일명 안정성 vs 가독성 트레이드오프 명시. +7. **트리거 표면**: 트레이 메뉴만 vs Inbox 헤더 버튼도 추가 vs CLI 플래그 (`--export `). 자동화 사용자라면 CLI 가 매력. 슬라이스 후속 미니 spec 으로 분리 가능. +8. **export 형식 버전 정책**: `inkling_export_version: 1` 박아두고 후속 변경 시 마이그레이션 가이드 동봉. 처음부터 박는 게 깔끔. +9. **민감정보 표시 경고**: 본 사용자는 `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.ts` + - `src/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 추가 불필요) +- **로깅:** + - export 시작·완료·노트 수만 기록. raw_text·title·summary 미기록 (slice §1.1 invariant 4 그대로) +- **문서:** + - 본 항목 promoted 시 `2026-04-26-markdown-export.md` (가칭) 으로 추출 + - 추출 후 README 의 doc map 갱신 + - export 폴더 안의 `README.md` — RAG 적재 예시 코드 포함 + +### 비고 + +본 항목은 **읽기 전용** 이라 dogfood 안전성 영향 0 (raw_text 변경 없음, AI 호출 없음, 네트워크 0). 우선순위 측면에선 F1·F2·F3 보다 후순위지만 **F4 의 H5 (외부 도구로 회수) 평가 자체가 export 없이는 측정 불가** — 즉 F4-H5 = F5 dependency. F4 의 데이터 수집을 위해 F5 가 먼저 promoted 되는 경로도 있음. + +--- + ## (다음 항목 자리) -새 피드백 추가 시 `## F5. 짧은 제목 (🌱 raw)` 헤더로 시작. 표준 슬롯 6개 채우거나 비워둔 채 시작 가능. +새 피드백 추가 시 `## F6. 짧은 제목 (🌱 raw)` 헤더로 시작. 표준 슬롯 6개 채우거나 비워둔 채 시작 가능.