25 KiB
Tasks: Tauri 기준 데스크톱 앱 전환
Input: specs/004-tauri-shell/ 의 설계 문서 (spec.md, plan.md, research.md, data-model.md, contracts/, quickstart.md)
Tests: 포함한다. CLAUDE.md §1 이 TDD(RED→GREEN)를 파이프라인에 박아뒀고, research R12 가 "자동으로 될 것만 자동으로" 기준으로 대상을 이미 갈라놨다.
Organization: 유저스토리 우선순위대로 쌓는다. US1~US5는 전부 필수이며 중간 중단 경로는 없다.
Format: [ID] [P?] [Story] 설명
- [P]: 병렬 가능 (파일 서로 안 겹치고 선행 task 에 안 물림)
- [Story]: 어느 유저스토리 소속인지 (US1~US5)
- 파일 경로는 repo 루트 기준
Phase 1: Setup (환경·선행 문서)
목적: 첫 Rust 코드보다 먼저 있어야 하는 것들. US1 은 T004 만 있으면 시작 가능.
- T001 rust 툴체인 설치·확인 —
rustup+ MSVC 타깃(x86_64-pc-windows-msvc) + VS Build Tools/Windows SDK.cargo --version·rustc --version·cl.exe존재가 통과 조건 (research R1, quickstart §사전준비) → 2026-08-15 완료. rustc/cargo 1.97.1, 기본 툴체인stable-x86_64-pc-windows-msvc. 별도 Build Tools 를 새로 받지 않고 이미 있던 VS 2026 Community 에 컴포넌트만 추가(VC.Tools.x86.x64+Windows11SDK.26100) — MSVC 14.51.36231, SDK 10.0.26100.0.rustc로 실제 링크까지 통과 확인 - T002 [P]
4_rust_tauri/docs-lib/README.md신규 — 카탈로그 (CLAUDE.md §3 양식) - T003 [P]
4_rust_tauri/docs-lib/tauri-v2.md신규 — 실제 쓸 API 표면 박제: 플러그인 4종 init(global-shortcut/single-instance/window-state/opener),TrayIconBuilder,Menu/CheckMenuItem,WebviewWindow(show/hide/set_focus/set_always_on_top/start_dragging/is_visible),#[tauri::command]+State,app.emit,app.path().app_local_data_dir(), capabilities 권한 이름. R11 의 미확정(Tauri v2 에서 PerMonitorV2 DPI 인지를 어디서 켜는가)도 여기서 확인해 적는다 (research R3) → 2026-08-15 완료. 공식 가이드 예제를 안 믿고cargo fetch로 받은 실제 crate 소스에서 뽑음(가이드 안에 2인자/3인자 예제가 둘 다 있어서 근거로 못 씀). 버전 박제: tauri 2.11.5 / global-shortcut 2.3.2 / single-instance 2.4.3 / window-state 2.4.1 / tao 0.35.3. 원문은tauri-v2-llms-full.md(2.4MB) 로 같이 받아둠 - T004 [P]
2_frontend/docs-lib/tauri-api.md신규 — 프론트가 쓸invoke/listen표면만 박제 (+2_frontend/docs-lib/README.md카탈로그에 한 줄 추가) → 2026-08-15 완료.node_modules/@tauri-apps/api/의 실제.d.ts·.js에서 뽑음 (2.11.1) - T005
2_frontend/package.json에@tauri-apps/apiv2 추가 후npm install— 이 기능의 유일한 신규 프론트 의존성 (plan Complexity Tracking 1번) → 2026-08-15 완료.^2.11.1
Checkpoint: T003 없이 Rust 코드를 쓰지 않는다. T005 없이 US1 을 시작하지 않는다.
📌 Phase 1 이 뒤 단계에 남긴 것 (docs-lib 만들며 새로 확인된 사실)
문서 만들다 계획을 바꿔야 하는 것 3건이 나왔다. 해당 task 본문에도 반영해뒀다.
| 무엇 | 어디에 영향 | 요약 |
|---|---|---|
| DPI 인지는 이미 켜져 있다 | T049 | tao 가 이벤트 루프 만들 때 SetProcessDpiAwarenessContext(PER_MONITOR_AWARE_V2) 를 무조건 부름. R11 의 "매니페스트 넣기"는 할 일이 없어졌다 — 확인만 하고 넘어감 |
| 호스트 판별식을 바꿔야 한다 | T012·T015 | "__TAURI_INTERNALS__" in window 는 틀린다. 공식 clearMocks() 가 속성만 지우고 빈 객체를 남겨서 정리 후에도 계속 true → 브라우저 모드 테스트가 tauri 로 오판됨. typeof window.__TAURI_INTERNALS__?.invoke === "function" 으로 잰다 |
| window-state 기본 플래그가 함정 | T030 | StateFlags 기본값이 all() 이라 VISIBLE·DECORATIONS 까지 저장·복원한다. 트레이 상주 + 프레임리스 앱엔 안 맞음 → SIZE | POSITION 만 켠다 |
공식 테스트 mock 이 있다는 것도 알아냈다 — @tauri-apps/api/mocks 의 mockIPC/clearMocks, shouldMockEvents: true 면 listen/emit 까지 mock 됨. T012~T014 는 이걸 쓴다 (직접 흉내낼 필요 없음).
Phase 2: Foundational (Tauri 빌드 베이스라인)
목적: 4_rust_tauri가 컴파일되고 현재 2_frontend 화면을 띄우는 기준 앱 베이스라인 만들기.
범위 주의: 여기서 제품명·identifier·빌드 경로를 기준 앱 값으로 확정한다. 손으로 쓴 Rust와 설정은 컴파일 검증 0줄이므로 전부 다시 본다.
⚠️ 전제: 손으로 쓴 src-tauri/src/**/*.rs·Cargo.toml·tauri.conf.json 은 컴파일 검증 0줄이다. "있으니 맞겠지"로 넘기지 말고 전부 다시 본다 (research R2).
- T006
4_rust_tauri/src-tauri/src/main.rs의 lib 이름이codeassist_tauri_lib::run()으로[lib] name과 일치하는지 확인 - T007
4_rust_tauri/src-tauri/Cargo.toml재검증 — Tauri 2의tray-icon·image-png, global-shortcut·single-instance·window-state, serde·serde_json만 포함.rusqlite·windows는 필요한 스토리까지 미룸 - T008
4_rust_tauri/src-tauri/tauri.conf.json—productName/창 제목=CodeAssist,identifier=com.codeassist.app, devUrl·frontendDist·프레임리스 설정 확인 - T009
4_rust_tauri/src-tauri/capabilities/default.json— 프론트가 우리 command만 invoke하므로core:default면 listen/emit까지 충분함을 docs-lib 기준으로 확인 - T010
4_rust_tauri/package.json— Tauri CLI 스크립트만 있고 프론트 dev/build는tauri.conf.json이2_frontend에서 실행함을 확인 - T011
cd 4_rust_tauri && npm run tauri dev첫 통과 — Rust dev 빌드 완료, 제목CodeAssist창에서2_frontend로그인 화면 렌더 확인
Checkpoint: 여기까지 되면 실제 Tauri bridge와 데스크톱 기능을 연결할 수 있다.
Phase 3: User Story 1 - 프론트 한 벌로 Tauri와 브라우저에서 뜬다 (Priority: P1) 🎯 MVP
Goal: 2_frontend가 실행 시점에 Tauri·legacy·브라우저를 판별해 맞는 통로를 고른다. 화면 소비자는 바꾸지 않는다.
Independent Test: Tauri 앱에서 실제 invoke/listen 왕복이 되고, 브라우저에서는 화면이 깨지지 않으며, legacy adapter 자동 검사가 통과하면 완료.
위험: 기존 브릿지 테스트의 WebView2 mock을 transport mock으로 바꾸면서 실제 Tauri 경로가 아니라 mock끼리만 맞을 수 있다. 자동 검사 뒤 실제 Tauri 앱을 반드시 실행한다.
Tests for User Story 1 ⚠️ 먼저 쓰고 RED 확인
transport는 사용할 때 호스트를 판별한다. 테스트 전용 reset API는 만들지 않는다. Windows Tauri도 WebView2를 쓸 수 있으므로 판별 순서는
tauri→webview2→browser다.
- T012 [P] [US1]
2_frontend/src/lib/bridge/transport.test.ts신규 — 호스트 3종 판별(tauri→webview2→browser), 브라우저 단방향 no-op·응답 요청 즉시 reject를 먼저 작성하고 RED 확인. Tauri는@tauri-apps/api/mocks의mockIPC/clearMocks사용 - T013 [P] [US1]
2_frontend/src/lib/bridge/bridgeNavigate.test.ts의chrome.webviewmock을 transport 경유 mock으로 교체. 기존 분기·CustomEvent 기대값은 유지 - T014 [P] [US1]
2_frontend/src/lib/bridge/snippetBridge.test.ts와2_frontend/src/features/snippets/api/snippets.api.test.ts의 mock을 transport 경유로 교체. 소비자 소스는 무변경
Implementation for User Story 1
- T015 [US1]
2_frontend/src/lib/bridge/transport.ts신규 —HostKind판별 + 전송수단 3종(tauri:invoke+listen, webview2:postMessage+addEventListener, browser: no-op·reject). Tauri 판별식은typeof window.__TAURI_INTERNALS__?.invoke === "function"이며 호출 시점에 판별 - T016 [US1]
2_frontend/src/lib/bridge/webviewBridge.ts를 transport 위로 얇게 —isWebView/hideWindow/pasteToApp/reportRoute/startWindowDragexport 시그니처 불변, 속만 transport 호출로 교체 (isWebView는 "데스크톱 껍데기 안인가"로 의미 확장) - T017 [US1]
2_frontend/src/lib/bridge/snippetBridge.ts축소 —reqSeq/pendingMap/ensureListener를 지우지 말고transport.ts의 webview2 구현 안으로 옮긴다(기존 껍데기 경로엔 그대로 필요). 여기엔request(type, payload)만 남김 (research R6) - T018 [US1]
2_frontend/src/lib/bridge/bridgeNavigate.ts— 리스너 부착만 transport 로 교체.paste.target/capture.image/navigate분기와CustomEventdispatch 본문은 한 줄도 안 바꾼다 (research R5 — 이게 diff 를 가장 크게 줄이는 한 수). transport 가 흡수해야 하는 차이 2개 (docs-lib/tauri-api.md§2): ① Tauri 는 페이로드가Event<T>로 한 겹 싸여 오므로e.payload를 벗겨서 넘겨야 분기 본문이 그대로 산다 ②listen은Promise<UnlistenFn>이라 async —initBridgeNavigate()를 async 로 바꾸면 호출부가 바뀌어 SC-001 위반이므로 transport 안에서 Promise 를 삼키고 밖은 동기 유지. 붙기 전 도착분은 기존lastPasteTarget스냅샷·pendingCaptureImageread-once 가 이미 막아줌 - T019 [US1]
transport.ts에 타입명→커맨드명 매핑 반영 —snippets.recordUse→snippets_record_use기계 변환 + 예외 1건route.changed→report_route(contracts/transport-mapping.md §1) - T020 [US1] 미구현 응답 규칙 — tauri 경로에서
invokereject 는 한글 메시지 그대로Error로 올라가 react-queryonError→sonner 로 흐르는지 확인. 빈 값([],null)으로 성공을 흉내내지 않는다 (FR-023, transport-mapping §3)
검증 for User Story 1
- T021 [US1] 소비자 diff 0줄 확인 —
2_frontend/src/lib/bridge/와 관련 테스트 바깥의 화면 소비자 소스에 변경이 없는지 확인 - T022 [US1] 자동 검사 —
cd 2_frontend && npm run format && npm run lint && npm run test && npm run build전부 통과 - T023 [US1] 브라우저 —
npm run dev후 챗봇 화면, 콘솔 오류 0, 데스크톱 전용 붙여넣기 버튼 숨김,/snippet의 "데스크톱 전용" 오류 확인 - T024 [US1] 실제 Tauri 앱 —
npm run tauri dev에서 화면→Rustinvoke와 Rust→화면bridge이벤트를 각각 한 번 이상 실제 동작으로 확인 - T025 [US1]
specs/004-tauri-shell/stage-1.md기록 — 한 일 / 검증 결과 / 다음
Checkpoint: Tauri와 브라우저가 같은 화면 한 벌을 쓰고 실제 bridge 왕복이 된다.
Phase 4: User Story 2 - Tauri 앱을 단축키와 트레이로 쓴다 (Priority: P2)
Goal: Tauri 앱이 표준 단축키·트레이·창 상태 복원·단일 인스턴스를 제공한다.
Independent Test: Tauri 앱 하나에서 Ctrl+Shift+7/8/9, 챗봇 토글, 트레이 메뉴, 창 상태 복원, 두 번 실행을 확인한다.
의존: Phase 2 + Phase 3. 챗봇 토글이 route.changed 보고에 물린다.
Tests for User Story 2
- T026 [P] [US2]
4_rust_tauri/src-tauri/src/lib.rs의 챗봇 토글 규칙을 순수 함수로 뽑고cargo test작성 — "창 보이는 중 AND current 가/snippet아님 → 숨김, 그 외 → 띄우고lastSnap으로" +lastSnap갱신 규칙(/snippet으로 시작 안 하면 같이 갱신) (data-model §4). 창·트레이·핫키는 자동 테스트 대상 아님 (research R12)
Implementation for User Story 2
- T027 [P] [US2]
4_rust_tauri/src-tauri/src/shell/window.rs재검증 — show/hide/set_focus/set_always_on_top/start_dragging/is_visible. CodeAssist 를 하나도 모르는 층으로 유지 (plan Structure Decision) - T028 [P] [US2]
4_rust_tauri/src-tauri/src/shell/hotkey.rs재검증 —Ctrl+Shift+7/8/9등록. 등록 실패해도 앱을 죽이지 않고 어느 조합이 실패했는지 알림 - T029 [P] [US2]
4_rust_tauri/src-tauri/src/shell/tray.rs재검증 — 트레이 상주 + 열기/항상 위에 고정/종료 - T030 [US2]
4_rust_tauri/src-tauri/src/lib.rs에 window-state·single-instance 배선 —.with_state_flags(StateFlags::SIZE | StateFlags::POSITION)만 사용. 저장 경로는%LocalAppData%\com.codeassist.app\ - T031 [US2] 핀(항상 위) 상태만 별도 저장/복원 —
app_local_data_dir()아래 단일 파일. window-state 플러그인이 always-on-top 은 안 봄 (research R8) - T032 [US2]
4_rust_tauri/src-tauri/src/lib.rs조립 — 어느 핫키가 무엇을 하는지(7=스니펫, 8=챗봇 토글, 9=캡쳐)와Routes{current,lastSnap}상태를 여기에만 모은다.shell::init(config)통합 진입점은 만들지 않는다 (plan Structure Decision — 구현 하나짜리 추상화 금지) - T033 [US2]
4_rust_tauri/src-tauri/src/bridge/commands.rs—window_hide/window_drag/report_route구현 (transport-mapping §1) - T034 [US2]
4_rust_tauri/src-tauri/src/bridge/mod.rs— 푸시를 단일 이벤트"bridge"에{type, ...}그대로 실어app.emit. 우선navigate부터 (research R5, transport-mapping §2) - T035 [US2] 아직 안 만든 커맨드는 한글 "아직 안 됨" 으로 reject — 빈 값으로 성공 흉내 금지 (FR-023). 이 시점엔
paste_code·snippets_*가 대상 - T036 [US2] 창은 제목표시줄 없이 뜨고 헤더 끌기로 이동 — 프론트의
window.drag가start_dragging까지 도달하는지 (FR-012)
검증 for User Story 2
- T037 [US2] quickstart C 기본 앱 —
CodeAssist프레임리스 창, 현재 챗봇 화면, 트레이, 두 번 실행 시 기존 창 소환 확인 - T038 [US2] quickstart C 표준 단축키 —
Ctrl+Shift+7=스니펫,Ctrl+Shift+8=챗봇 토글,Ctrl+Shift+9=캡쳐만 반응하는지 확인 - T039 [US2] quickstart C 창 상태 — 창 위치·크기·핀을 바꾸고 재실행해 복원되는지 확인
- T040 [US2]
specs/004-tauri-shell/stage-2.md기록 — 한 일 / 검증 결과 / 다음
Checkpoint: CodeAssist를 Tauri 기준 앱으로 상시 켜두고 단축키로 부를 수 있다.
Phase 5: User Story 3 - 코드가 직전 앱에 붙는다 (Priority: P3)
Goal: 단축키로 창 불러 코드 고르면 아까 쓰던 그 앱에 들어간다.
Independent Test: 메모장·VS Code·창전환 느린 앱 각각에 여러 번 붙여넣어 성공률 세기.
- T041 [US3]
4_rust_tauri/src-tauri/Cargo.toml에windowscrate 추가 (Win32 직접 호출 — 플러그인 안 씀, research R10) - T042 [US3]
4_rust_tauri/src-tauri/src/shell/paste.rs신규/재검증 — 순서를 그대로 지킨다: ① 클립보드 적재 → ② 우리 창 숨기기 전에SetForegroundWindow→ ③ 짧게 대기 → ④Ctrl+V주입 → ⑤ 클립보드 원복 안 함. 참조 원본은3_windowsApp/CodeAssist.Shell/Platform/PasteService.cs의 "함정 박제" 주석 (research R10) - T043 [US3] 대기시간을 조정 가능한 값으로 둔다 — .NET 의 80ms 로 시작. 물리 타이밍이라 환경 따라 다름 (research R10 "미해결로 남기는 것")
- T044 [US3] 붙여넣기 대상 스냅샷 — 창 소환 직전에 창 제목·프로세스명을 값으로 복사해 보관(창이 나중에 닫혀도 표시는 남아야 함, data-model §3)
- T045 [US3]
bridge/mod.rs에{type:"paste.target", name, app}푸시 추가 → 프론트 배지에 직전 앱 이름 표시 (FR-015) - T046 [US3]
bridge/commands.rs에paste_code구현 — 실패해도 코드는 클립보드에 남긴다(사용자가 직접Ctrl+V, FR-014). T035 의 "아직 안 됨" reject 제거 - T047 [US3] quickstart C 수동 검증 — 메모장/VS Code/창전환 느린 업무용 앱 3종. 엉뚱한 곳에 붙거나 절반만 붙지 않아야 함. 배지에 앱 이름 보이는지, 실패 시 클립보드에 남는지. 느린 앱에서 어긋나면 T043 값을 올려본다
- T048 [US3]
specs/004-tauri-shell/stage-3.md기록
Checkpoint: SC-004 도달 — 평소 흐름(소환→코드 고름→직전 앱에 붙음)을 처음부터 끝까지 해볼 수 있다.
2026-09-11 통합 상태: T041~T046 관련 구현은 main에 보존했고 Rust 컴파일·단위 검사를 통과함. T047의 실제 대상 앱 검증과 단계 인수는 아직 미완료. 스니펫 DB 읽기 구현도 main에서 가져왔지만 전체 CRUD 완료를 뜻하지 않음. 상세: stage-main-integration.md.
Phase 6: User Story 4 - 화면 일부를 잘라 챗에 붙인다 (Priority: P4)
Goal: 단축키 → 영역 드래그 → 챗 입력창에 그림 첨부. 멀티모니터·다른 배율에서도 고른 영역과 결과가 일치.
Independent Test: 배율 다른 모니터 두 대에서 각각·걸친 영역을 여러 번 캡쳐해 눈으로 대조.
- T049 [US4] PerMonitorV2 DPI 인지 — 확인만 하고 넘어간다.
켜기할 일 없음이 T003 에서 확인됐다:tao0.35.3 이 이벤트 루프 생성 시(event_loop.rs:190)become_dpi_aware()→SetProcessDpiAwarenessContext(PER_MONITOR_AWARE_V2)를 무조건 부른다. .NET 판이app.manifest를 따로 넣어야 했던 것과 다름 (4_rust_tauri/docs-lib/tauri-v2.md§8). 그래서 T054 에서 좌표가 어긋나면 원인이 DPI 설정이 아니다 — 논리↔물리 좌표 변환(T051) 쪽을 본다. R11 의 미확정 항목은 이걸로 닫힘 - T050 [US4]
4_rust_tauri/src-tauri/src/shell/capture.rs신규/재검증 — 전체 가상 화면을 덮는 투명·항상위 오버레이 창 + 드래그 영역 선택 - T051 [US4] 네이티브 오버레이의 물리 픽셀 좌표로 그 영역 잘라내기 —
windowscrate 의BitBlt직접 호출(.NET 판과 같은 API). Tauri의 PerMonitorV2 프로세스에서 Win32 가 주는 client/가상화면 좌표는 이미 물리 픽셀이라 별도 배율 곱을 하지 않음 - T052 [US4] 취소 경로 — Esc, 포커스 이탈, 그리고 드래그 거의 없이 클릭만 하면 조용히 취소하고 화면 원복 (FR-018)
- T053 [US4]
bridge/mod.rs의 기존{type:"capture.image", dataUrl}계약을 실제 캡쳐 완료 경로에 연결 — 프론트의 read-once 소비 경로(consumePendingCaptureImage)에 그대로 물림 - T054 [US4] quickstart D 수동 검증 — 배율 100%/150% 모니터·두 모니터에 걸친 영역·Esc·클릭만. 캡쳐물을 원본과 나란히 놓고 눈으로 대조(어긋나면 보통 일정 비율로 밀림) (SC-005)
- T055 [US4]
specs/004-tauri-shell/stage-4.md기록
Phase 7: User Story 5 - 기존 스니펫을 그대로 쓴다 (Priority: P5)
Goal: Tauri가 기존 CodeAssist 스니펫 DB를 그대로 읽고 쓴다.
Independent Test: 기존 데이터가 Tauri 팔레트에 보이고, 생성·수정·사용기록이 재실행 뒤에도 유지되면 통과.
데이터 주의: %LocalAppData%\CodeAssist\snippets.db의 스키마와 저널 모드를 바꾸지 않는다.
- T056 [US5]
4_rust_tauri/src-tauri/Cargo.toml에rusqlite(bundled feature) 추가 - T057 [US5] 기존
4_rust_tauri/src-tauri/src/bridge/snippets.rs확장 —%LocalAppData%\CodeAssist\snippets.db를 열고 없으면 기존 형식으로 생성. 참고 원본은 legacySnippetRepository.cs - T058 [P] [US5]
cargo test— 이름 중복과 빈 필수 필드 거부 테스트를 먼저 작성하고 RED 확인 - T059 [US5]
bridge/commands.rs에snippets_list/snippets_create/snippets_update/snippets_delete/snippets_record_use구현 - T060 [US5] 오류를 한글 메시지로 reject — 중복 이름·빈 필드·저장 실패가 프론트
Error→sonner로 흐르는지 확인 - T061 [US5]
usageCount+1 /lastUsed갱신 — 재실행 뒤 자주 쓰는 순서에 반영 - T062 [US5] quickstart F — 기존 목록 표시 / 생성·수정 / 사용 횟수·순서 / 재실행 후 유지 / 빈 DB 첫 저장 확인
- T063 [US5]
specs/004-tauri-shell/stage-5.md기록
Checkpoint: 기존 데이터를 잃지 않고 Tauri 앱을 평소 업무에 쓸 수 있다.
Phase 8: Polish & 마무리 (기준 앱 전환)
목적: 미구현 경로를 없애고 제품 정의·문서·release 결과물을 Tauri 기준으로 맞춘다.
- T064 quickstart G 확인 — US1~US5 필수 요청 중 "아직 안 됨" reject가 남아 있지 않은지 실제 흐름으로 확인
- T065 [P] 제품 정의 갱신 —
CLAUDE.md,4_rust_tauri/README.md,4_rust_tauri/src-tauri/Cargo.toml,tauri.conf.json에서 Tauri를 기준 앱, .NET을 참고용 legacy, 제품명을CodeAssist로 통일 - T066 최종 검증 —
2_frontend에서 format+lint+test+build,4_rust_tauri에서 cargo test +npm run tauri build. 기본 검증에3_windowsApp을 요구하지 않음 - T067
/code-review+superpowers:verification-before-completion - T068
specs/004-tauri-shell/report.md작성 — 계획 대비 구현 결과, 자동 검사, Tauri 실제 실행, 붙여넣기·캡쳐·기존 데이터 검증 증거 - T069 사용자 최종 승인 → merge
Dependencies & Execution Order
Phase 의존
Phase 1 (Setup)
└── Phase 2 (Tauri 빌드 베이스라인)
└── Phase 3 (US1 transport)
└── Phase 4 (US2 창·단축키)
├── Phase 5 (US3 붙여넣기)
├── Phase 6 (US4 캡쳐)
└── Phase 7 (US5 스니펫)
└── Phase 8 (기준 앱 전환 마무리)
- Phase 1: 완료
- Phase 2: 모든 구현의 실행 베이스라인
- Phase 3: Phase 2 필요. 실제 Tauri bridge 왕복까지 확인
- Phase 4: Phase 3 필요. route 보고 위에 창 토글을 연결
- Phase 5~7: Phase 4 필요. 세 기능 모두 완료
- Phase 8: US1~US5 전부 끝난 뒤
스토리 간 의존
- US1: Tauri 빌드 베이스라인 필요
- US2: US1 필요
- US3·US4·US5: US2 필요. 셋은 서로 파일 일부가 겹치므로 task 순서대로 합침
병렬 기회
- Phase 2: T009·T010은 서로 다른 설정 파일
- Phase 3 테스트: T012·T013·T014는 테스트 파일이 겹치지 않음
- Phase 4: T027·T028·T029는
shell/아래 독립 파일 - Phase 8: T065 문서·메타데이터 정리와 T064 실제 흐름 확인은 독립
스토리 안에서
- 테스트 먼저 쓰고 RED 확인 후 구현 (CLAUDE.md §1, superpowers:test-driven-development)
- 검증 task 는 그 스토리 구현이 다 끝난 뒤
- 스토리 하나 끝날 때마다
stage-N.md— 승인 대기 없이 계속 (CLAUDE.md §1 7단계)
Parallel Example: Phase 1 / Phase 4
# Phase 1 — 문서 3개 동시
Task: "4_rust_tauri/docs-lib/README.md 카탈로그 작성"
Task: "4_rust_tauri/docs-lib/tauri-v2.md — 쓸 API 표면 박제 (+ R11 DPI 설정 위치 확인)"
Task: "2_frontend/docs-lib/tauri-api.md — invoke/listen 표면 박제"
# Phase 4 — shell 3모듈 동시 (서로 독립·콜백도 다름)
Task: "shell/window.rs 재검증 — show/hide/focus/always-on-top/start_dragging"
Task: "shell/hotkey.rs 재검증 — Ctrl+Shift+7/8/9 + 등록 실패 알림"
Task: "shell/tray.rs 재검증 — 열기/항상위/종료"
Implementation Strategy
첫 실행 가능 상태
- Phase 2 — Tauri 창에 현재 프론트가 뜸
- Phase 3 — 화면과 Tauri bridge가 실제 왕복
- Phase 4 — 표준 단축키·트레이·창 상태가 동작
기능 완성 순서
- US3 — 직전 앱 붙여넣기
- US4 — 멀티모니터 화면 캡쳐
- US5 — 기존 스니펫 데이터 읽기·쓰기
- Phase 8 — 제품 정의·release·완료 보고
US1~US5는 전부 필수다. 비교 결과에 따른 중간 중단은 없다.
Notes
3_windowsApp은 참고용 legacy라 새 기능·기본 배포·완료 검증 대상이 아니다- Tauri v2 API는 T003의 docs-lib을 보고 작성
- 기존 메시지 계약을 Tauri 사정으로 몰래 바꾸지 않음
- 자동 계측 장치는 만들지 않음
- 편집 후
npm run format, 완료 선언 전 lint+test+build (CLAUDE.md §4) - 작업 스텝마다
python z-my-docs/work-log/gen_worklog.py add "<한 일>"(CLAUDE.md §5)