v0.2.7 release 후 dogfood 9건 누적 (F17~F25) 정리: - F17 휴지통 의미 분기 / F18 사유 입력 / F19 recall / F20 raw_text 가변 - F21 다기기 sync / F22 이미지 렌더링 (이미 v0.2.8 promoted) / F23 Ollama-less - F24 멀티모달 vision / F25 사이드바 + 저장소 추가: - v0.2.8+ roadmap: 7 cut 분할 (A~G), 12주 시간선, dependency graph - Cut A~G design specs (각 cut 별 design 결정 + schema + UI + 테스트 전략) - Cut A implementation plan (이미 v0.2.8 머지로 실행 완료, 참고 보존) PR #26 머지 후 main 에 doc commits rebase 안 되어 manual merge 진행: - F22 entry 는 origin/main 의 promoted 형태 우선 - 신규 9 파일 (specs/plan/roadmap) 은 origin/main 에 없는 파일 - "다음 항목 자리" 안내 F23 → F26 갱신 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
8.6 KiB
v0.3.2 — Cut G Design (사이드바 + notebook 카테고리)
작성일: 2026-05-09 선행 문서:
docs/superpowers/specs/2026-04-25-dogfood-feedback.md(F25)docs/superpowers/strategy/v028plus-roadmap.mdCut G
Cut 라벨: v0.3.2
1. Cut 정체성
inbox layout 재구성 — 사이드바 + 메모 카테고리 (notebook). single-pane → two-pane. 단일 DB 안 notebook_id 컬럼 (옵션 B — 1주 scope, 다중 profile 옵션 A 는 v0.4+ 후보).
2. 범위
| 항목 | 결정 |
|---|---|
| F25 저장소 정의 | B — 카테고리/폴더 (notebook_id, 단일 DB 안 그룹화) |
| 사이드바 가시성 | 사용자 토글 + last state 보존 (settings) |
| 사이드바 내용 | 상단 notebook 목록 + 하단 메모 list (compact view) |
3. Schema 마이그레이션 (m007)
CREATE TABLE notebooks (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
color TEXT, -- accent color for UI (옵션)
created_at TEXT NOT NULL,
position INTEGER NOT NULL DEFAULT 0
);
INSERT INTO notebooks (id, name, created_at, position)
VALUES ('default', '기본', '2026-05-09T00:00:00Z', 0);
ALTER TABLE notes ADD COLUMN notebook_id TEXT NOT NULL DEFAULT 'default'
REFERENCES notebooks(id) ON DELETE RESTRICT;
CREATE INDEX idx_notes_notebook_status ON notes(notebook_id, status, created_at DESC);
기존 모든 notes → notebook_id='default'. 사용자가 새 notebook 생성 후 메모 이동 가능.
ON DELETE RESTRICT — notebook 삭제 시 노트 잔류해야 함. notebook 삭제 흐름은 사용자가 명시 (메모 이동 후 삭제).
4. NotebookRepository
class NotebookRepository {
list(): Notebook[];
get(id: string): Notebook | undefined;
create(name: string, color?: string): Notebook;
rename(id: string, name: string): void;
delete(id: string): void; // notebook 안 메모 0건일 때만 (RESTRICT 위반 시 throw)
reorder(ids: string[]): void; // position 갱신
countNotes(id: string, opts?: { status?: NoteStatus }): number;
}
NoteRepository 의 모든 query 에 notebook_id filter 추가:
listByStatus(status: NoteStatus, opts: { notebookId?: string; limit?: number }): Note[];
moveToNotebook(noteId: string, notebookId: string): void;
5. UI — 사이드바
5-1. layout
┌──────────────┬───────────────────────────────────┐
│ [≡] Inkling │ [Inbox(N) 완료(N) 보관(N) 휴지통(N)] [🔍 search] [⚙] │
├──────────────┼───────────────────────────────────┤
│ 노트북 │ │
│ • 기본 (12) │ NoteCard list (current view) │
│ • 회사 (5) │ │
│ • 학습 (3) │ │
│ + 새 노트북 │ │
├──────────────┤ │
│ 메모 빠른 list│ │
│ - title 1 │ │
│ - title 2 │ │
│ - title 3 │ │
│ ... │ │
└──────────────┴───────────────────────────────────┘
폭: 240px (settings 의 sidebar_width 사용자 조정 가능, default 240, min 180, max 400).
5-2. 토글
헤더 좌측 햄버거 (≡) 버튼 → useInbox.sidebarVisible toggle. last state 저장 (settings.sidebar_visible).
키보드 shortcut: Ctrl+B (또는 Cmd+B macOS) — 빠른 토글.
5-3. Notebook 목록
상단 panel — NotebookRepository.list() + 각 notebook 의 active 메모 count.
- 클릭 →
useInbox.selectedNotebookId갱신 → main pane 의 NoteCard list 가 해당 notebook 만 표시. - 우클릭 → context menu: 이름 변경 / 색 변경 / 삭제 (메모 0건일 때만).
- "+ 새 노트북" 버튼 → modal: name 입력 + color picker (선택사항) → create.
5-4. 메모 빠른 list
하단 panel — selected notebook + selected status (Inbox/완료/보관/휴지통 탭) 의 NoteCard 들의 compact view.
- title + tag chip 1-2 개 + 시간 (relative — "2시간 전")
- 클릭 → main pane 가 해당 NoteCard 위치로 scroll (또는 강조)
main pane 의 NoteCard grid 와 사이드 빠른 list 는 동일 데이터 — 단지 view 다름. 사이드는 navigation, main 은 detail.
5-5. NoteCard 갱신 — notebook 이동
NoteCard 액션 메뉴 (Cut B 의 status 메뉴 옆):
- "다른 노트북으로 이동" → notebook 목록 dropdown → 선택 →
moveToNotebookIPC
6. store 갱신
interface InboxState {
// 기존
view: 'inbox' | 'completed' | 'archived' | 'trash' | 'review-daily' | 'review-weekly' | 'review-monthly' | 'settings';
// 신규 (Cut G)
notebooks: Notebook[];
selectedNotebookId: string;
sidebarVisible: boolean;
loadNotebooks: () => Promise<void>;
selectNotebook: (id: string) => void;
createNotebook: (name: string, color?: string) => Promise<void>;
renameNotebook: (id: string, name: string) => Promise<void>;
deleteNotebook: (id: string) => Promise<void>;
toggleSidebar: () => void;
}
refreshMeta / loadInitial 가 notebooks 도 함께 fetch.
7. IPC
'inbox:list-notebooks': () => Promise<Notebook[]>
'inbox:create-notebook': (name: string, color?: string) => Promise<Notebook>
'inbox:rename-notebook': (id: string, name: string) => Promise<{ ok: true }>
'inbox:delete-notebook': (id: string) => Promise<{ ok: true } | { ok: false; reason: string }>
'inbox:move-to-notebook': (noteId: string, notebookId: string) => Promise<{ ok: true }>
'inbox:reorder-notebooks': (ids: string[]) => Promise<{ ok: true }>
8. F19 search 와 결합 (Cut D 후)
search box — 사이드바 도입 후 위치 검토:
- (a) inbox 헤더 잔류 (Cut D 결정) — 단순. 사이드바 토글 무관.
- (b) 사이드바 안 상단 — 사이드바 visible 일 때만 search. hidden 시 inbox 헤더 fallback.
추천: (a) — Cut D 결정 보존, 사이드바 토글 무관. UX 일관.
search 결과 — current selectedNotebookId 안만 또는 모든 notebook? settings 토글 또는 search options dropdown. 추천: 기본 current notebook 안 검색 + "모든 노트북에서 검색" 옵션.
9. 테스트 전략
| 영역 | 단위 |
|---|---|
| m007 마이그레이션 | notebooks 테이블 + 'default' INSERT + notes.notebook_id backfill |
NotebookRepository.list/create/rename/delete/reorder |
각 메서드 |
delete RESTRICT |
메모 잔류 시 throw |
moveToNotebook |
notebook_id 갱신 + 카운트 영향 |
| 사이드바 토글 | store action + settings 저장 |
| Notebook 목록 렌더 | count badge + 클릭 → selectedNotebookId 갱신 |
| 메모 빠른 list | selectedNotebook + selectedView 필터 |
| Notebook 생성 modal | name 입력 + color picker → create |
| Notebook 삭제 | 메모 잔류 시 error 표시 |
| search + notebook scope | 'current notebook' / 'all' 옵션별 필터 |
목표: 단위 575 → 약 600 (+25), typecheck 0.
10. Risk
| Risk | 대응 |
|---|---|
| 사이드바 폭이 좁은 화면 (1280×720) 에서 너무 큼 | default hidden 옵션? settings 의 width 조정 + 좁은 화면 시 자동 hide |
| Notebook 삭제 시 RESTRICT error UX | error message + "메모 N건 이동 후 다시 시도" 안내 |
| 다중 notebook 시 search default scope 혼란 | search box 옆 'current/all' 토글 + 기본 current |
| F21 sync (Cut E) 와 결합 시 notebook 정합성 | sync markdown export 가 notebook_id 도 frontmatter 에 포함 — Cut E ImportService 갱신 (미리 spec 잔류 — Cut G 머지 시 ImportService 갱신 commit 포함) |
| 다중 profile 옵션 A 로 진화 시 notebook → profile 마이그레이션 | v0.4+ 영역. 본 cut 은 단일 profile + notebook 다 |
11. v0.3.2 후
v0.4 후보 (사용자 dogfood metric 충족 후 외부 확장):
- F25 옵션 A (다중 profile 분리 DB) — 외부 user 확장 시
- F19 옵션 B (context-based recall — 시간/태그/요일)
- F19 옵션 E (spaced repetition)
- F25 옵션 C (다중 sync remote)
dogfood verify:
- 사이드바 사용 빈도 (열린 채로 유지 / 토글 자주)
- notebook 갯수 (본인 dogfood — 1개 vs N개)
- notebook 간 메모 이동 빈도 (분류 욕구 측정)