Files
inkling/docs/superpowers/specs/2026-05-09-v032-cut-g-design.md
altair823 7d2b8c95ec docs(v028+): F17~F25 dogfood + roadmap + Cut A~G specs + Cut A plan
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>
2026-05-09 15:09:02 +09:00

8.6 KiB
Raw Blame History

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.md Cut 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 → 선택 → moveToNotebook IPC

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:

  1. 사이드바 사용 빈도 (열린 채로 유지 / 토글 자주)
  2. notebook 갯수 (본인 dogfood — 1개 vs N개)
  3. notebook 간 메모 이동 빈도 (분류 욕구 측정)