Files
CODE_ASSISTANT/specs/004-tauri-shell/tasks.md
T
2026-09-16 17:22:14 +09:00

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/api v2 추가 후 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/mocksmockIPC/clearMocks, shouldMockEvents: truelisten/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.jsonproductName/창 제목=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.json2_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를 쓸 수 있으므로 판별 순서는 tauriwebview2browser다.

  • T012 [P] [US1] 2_frontend/src/lib/bridge/transport.test.ts 신규 — 호스트 3종 판별(tauriwebview2browser), 브라우저 단방향 no-op·응답 요청 즉시 reject를 먼저 작성하고 RED 확인. Tauri는 @tauri-apps/api/mocksmockIPC/clearMocks 사용
  • T013 [P] [US1] 2_frontend/src/lib/bridge/bridgeNavigate.test.tschrome.webview mock을 transport 경유 mock으로 교체. 기존 분기·CustomEvent 기대값은 유지
  • T014 [P] [US1] 2_frontend/src/lib/bridge/snippetBridge.test.ts2_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/startWindowDrag export 시그니처 불변, 속만 transport 호출로 교체 (isWebView 는 "데스크톱 껍데기 안인가"로 의미 확장)
  • T017 [US1] 2_frontend/src/lib/bridge/snippetBridge.ts 축소 — reqSeq/pending Map/ensureListener지우지 말고 transport.ts 의 webview2 구현 안으로 옮긴다(기존 껍데기 경로엔 그대로 필요). 여기엔 request(type, payload) 만 남김 (research R6)
  • T018 [US1] 2_frontend/src/lib/bridge/bridgeNavigate.ts — 리스너 부착만 transport 로 교체. paste.target/capture.image/navigate 분기와 CustomEvent dispatch 본문은 한 줄도 안 바꾼다 (research R5 — 이게 diff 를 가장 크게 줄이는 한 수). transport 가 흡수해야 하는 차이 2개 (docs-lib/tauri-api.md §2): ① Tauri 는 페이로드가 Event<T> 로 한 겹 싸여 오므로 e.payload 를 벗겨서 넘겨야 분기 본문이 그대로 산다 ② listenPromise<UnlistenFn> 이라 asyncinitBridgeNavigate() 를 async 로 바꾸면 호출부가 바뀌어 SC-001 위반이므로 transport 안에서 Promise 를 삼키고 밖은 동기 유지. 붙기 전 도착분은 기존 lastPasteTarget 스냅샷·pendingCaptureImage read-once 가 이미 막아줌
  • T019 [US1] transport.ts 에 타입명→커맨드명 매핑 반영 — snippets.recordUsesnippets_record_use 기계 변환 + 예외 1건 route.changedreport_route (contracts/transport-mapping.md §1)
  • T020 [US1] 미구현 응답 규칙 — tauri 경로에서 invoke reject 는 한글 메시지 그대로 Error 로 올라가 react-query onError→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에서 화면→Rust invoke와 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.rswindow_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.dragstart_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.tomlwindows crate 추가 (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.rspaste_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 에서 확인됐다: tao 0.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] 네이티브 오버레이의 물리 픽셀 좌표로 그 영역 잘라내기 — windows crate 의 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.tomlrusqlite(bundled feature) 추가
  • T057 [US5] 기존 4_rust_tauri/src-tauri/src/bridge/snippets.rs 확장 — %LocalAppData%\CodeAssist\snippets.db를 열고 없으면 기존 형식으로 생성. 참고 원본은 legacy SnippetRepository.cs
  • T058 [P] [US5] cargo test — 이름 중복과 빈 필수 필드 거부 테스트를 먼저 작성하고 RED 확인
  • T059 [US5] bridge/commands.rssnippets_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

첫 실행 가능 상태

  1. Phase 2 — Tauri 창에 현재 프론트가 뜸
  2. Phase 3 — 화면과 Tauri bridge가 실제 왕복
  3. Phase 4 — 표준 단축키·트레이·창 상태가 동작

기능 완성 순서

  1. US3 — 직전 앱 붙여넣기
  2. US4 — 멀티모니터 화면 캡쳐
  3. US5 — 기존 스니펫 데이터 읽기·쓰기
  4. 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)