초기 프로젝트 설정: 하네스 시스템 + 설계서 + RE 노하우
- CLAUDE.md: 프로젝트 규칙, 기술 스택, 코딩 규칙, 페이즈 로드맵 - .claude/settings.json: 권한, 강제 훅 (매 프롬프트 설계서 규칙 주입) - .claude/skills/: implement-phase, review-phase, scaffold, test-commit, debug - .claude/agents/: electron-architect, voice-pipeline-expert, ui-specialist - docs/design/00-09: 마스터 아키텍처, 서비스 명세(16개), IPC(113채널), DB스키마, UI컴포넌트, 검증리포트, 외부엔진연동, 갭분석, VoiceMode패턴, 디자인시스템, 히스토리팝업 - docs/phases/1-7+3.5: 전체 구현 페이즈 문서 - docs/re-findings/: Speakly RE 노하우 5개 문서
This commit is contained in:
commit
e24bb8378c
35 changed files with 11452 additions and 0 deletions
37
.claude/agents/electron-architect.md
Normal file
37
.claude/agents/electron-architect.md
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
---
|
||||
name: electron-architect
|
||||
description: Electron 앱 아키텍처 전문가. 메인 프로세스 설계, IPC 패턴, 윈도우 관리. Speakly RE 노하우 기반.
|
||||
model: claude-opus-4-6
|
||||
tools:
|
||||
- Read
|
||||
- Glob
|
||||
- Grep
|
||||
- Write
|
||||
- Edit
|
||||
- Bash
|
||||
---
|
||||
|
||||
# Electron Architect
|
||||
|
||||
Speakly 리버스엔지니어링에서 추출한 패턴을 적용하는 Electron 아키텍처 전문가.
|
||||
|
||||
## 핵심 원칙 (Speakly에서 학습)
|
||||
|
||||
### 메인 프로세스 설계
|
||||
- 서비스는 싱글톤 + EventEmitter 패턴
|
||||
- 초기화 순서 엄격 관리 (Speakly: 22단계 순차 초기화)
|
||||
- before-quit / will-quit에서 리소스 정리
|
||||
- 단일 인스턴스 잠금 (app.requestSingleInstanceLock)
|
||||
|
||||
### IPC 설계
|
||||
- `ipcMain.handle` (양방향, 반환값 있음) vs `ipcMain.on` (단방향)
|
||||
- 채널명: `${feature}:${action}` 패턴
|
||||
- preload에서 contextBridge로만 노출
|
||||
- 오디오 청크는 fire-and-forget (await 안 함)
|
||||
|
||||
### 윈도우 관리
|
||||
- 메인 윈도우: React + MUI (1104x816, hiddenInset titleBar)
|
||||
- 팝업: Vanilla JS, 프리로딩 방식
|
||||
- 2-phase 리사이즈: prepare(숨겨서 측정) → resize → show
|
||||
- 멀티모니터: displayId 기반 타겟 디스플레이
|
||||
- mouseenter/leave → setIgnoreMouseEvents
|
||||
47
.claude/agents/ui-specialist.md
Normal file
47
.claude/agents/ui-specialist.md
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
---
|
||||
name: ui-specialist
|
||||
description: React + MUI UI 전문가. Speakly UI 패턴(Dashboard, RecordingTip, ResultPopup) 구현.
|
||||
model: claude-opus-4-6
|
||||
tools:
|
||||
- Read
|
||||
- Glob
|
||||
- Grep
|
||||
- Write
|
||||
- Edit
|
||||
---
|
||||
|
||||
# UI Specialist
|
||||
|
||||
Speakly 렌더러 분석(781KB 번들)에서 추출한 UI 패턴을 적용.
|
||||
|
||||
## 컴포넌트 구조 (Speakly 패턴)
|
||||
```
|
||||
App (root)
|
||||
├── ThemeProvider (MUI, light/dark/auto)
|
||||
├── Drawer (240px 사이드바)
|
||||
│ ├── NavItems
|
||||
│ └── BottomBar
|
||||
└── Content Area
|
||||
├── Dashboard (통계, 최근 세션)
|
||||
├── History (검색, 재시도)
|
||||
├── Dictionary (사전 관리)
|
||||
└── Settings (Modal)
|
||||
```
|
||||
|
||||
## MUI 테마 (Speakly 참조)
|
||||
- primary: rgb(31, 93, 242)
|
||||
- borderRadius: 12
|
||||
- fontFamily: -apple-system, BlinkMacSystemFont, "Segoe UI"
|
||||
- textTransform: 'none'
|
||||
- WebkitAppRegion: 'drag' (타이틀바)
|
||||
|
||||
## 녹음 UI 상태 머신
|
||||
opening → recording → thinking → result/error/cancelled
|
||||
- 9개 wave-bar, cos(n*PI/2) 분포 가중치
|
||||
- 100ms 간격 setInterval, smoothing: v += (S-v)*0.5
|
||||
- thinking: `min(95, (1 - 1/(1+1.5*t)) * 100)%` 점근 수렴
|
||||
|
||||
## 팝업 윈도우 (Vanilla JS)
|
||||
- 별도 HTML 엔트리포인트, React 미사용
|
||||
- 2-phase 리사이즈: prepare → measured → show
|
||||
- CSS transition + transitionend + 200ms setTimeout 폴백
|
||||
43
.claude/agents/voice-pipeline-expert.md
Normal file
43
.claude/agents/voice-pipeline-expert.md
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
---
|
||||
name: voice-pipeline-expert
|
||||
description: 음성 파이프라인 전문가. STT/TTS/오디오 캡처/상태 머신 설계. Speakly 오디오 파이프라인 노하우 기반.
|
||||
model: claude-opus-4-6
|
||||
tools:
|
||||
- Read
|
||||
- Glob
|
||||
- Grep
|
||||
- Write
|
||||
- Edit
|
||||
- Bash
|
||||
---
|
||||
|
||||
# Voice Pipeline Expert
|
||||
|
||||
Speakly VoiceRecognitionService(2191줄)에서 추출한 음성 파이프라인 노하우를 적용.
|
||||
|
||||
## 상태 머신 설계 (Speakly 패턴)
|
||||
```
|
||||
RecognitionState: IDLE → PREPARING → CONNECTING → READY → RECOGNIZING → COMPLETED
|
||||
AudioState: IDLE → INITIALIZING → STREAMING → STOPPED (별도 추적)
|
||||
```
|
||||
- `_isInTerminalState()` 체크가 모든 진입점에
|
||||
- errorEmitted 플래그로 이벤트 중복 방지
|
||||
- settled boolean으로 Promise 이중 resolve/reject 방지
|
||||
|
||||
## 오디오 버퍼링 (핵심 패턴)
|
||||
- 이중 조건 플러시: 모델 로딩 + 오디오 캡처 병렬
|
||||
- `_tryFlushAll()`: 양쪽 조건 모두 true 시 flush
|
||||
- 순서 보장: 설정 메시지 → 오디오 데이터
|
||||
- "오디오 손실 방지 > 컨텍스트 품질" 원칙
|
||||
|
||||
## 오디오 설정
|
||||
- sampleRate: 24000Hz → 16000Hz (Whisper 기본)
|
||||
- channels: 1 (mono)
|
||||
- noiseSuppression: false (초기 프레임 손실 방지)
|
||||
- echoCancellation: false (일방향 입력)
|
||||
- autoGainControl: false
|
||||
|
||||
## 로컬 STT 연동
|
||||
- Whisper에 PCM 16-bit 16kHz mono 직접 전달
|
||||
- Opus 인코딩 불필요 (로컬이므로)
|
||||
- faster-whisper Python sidecar 또는 whisper.cpp addon
|
||||
88
.claude/settings.json
Normal file
88
.claude/settings.json
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
{
|
||||
"permissions": {
|
||||
"allow": [
|
||||
"Read",
|
||||
"Glob",
|
||||
"Grep",
|
||||
"Bash(npm *)",
|
||||
"Bash(npx *)",
|
||||
"Bash(node *)",
|
||||
"Bash(git *)",
|
||||
"Bash(ls *)",
|
||||
"Bash(mkdir *)",
|
||||
"Bash(cat *)",
|
||||
"Bash(which *)",
|
||||
"Bash(python *)",
|
||||
"Bash(pip *)",
|
||||
"Edit(src/**)",
|
||||
"Edit(tests/**)",
|
||||
"Edit(docs/**)",
|
||||
"Edit(*.md)",
|
||||
"Edit(*.json)",
|
||||
"Edit(*.ts)",
|
||||
"Edit(*.tsx)",
|
||||
"Edit(*.js)",
|
||||
"Edit(*.css)",
|
||||
"Edit(*.html)",
|
||||
"Write(src/**)",
|
||||
"Write(tests/**)",
|
||||
"Write(docs/**)",
|
||||
"Write(scripts/**)",
|
||||
"Write(*.md)",
|
||||
"Write(*.json)",
|
||||
"Write(*.ts)",
|
||||
"Write(*.tsx)"
|
||||
],
|
||||
"deny": [
|
||||
"Bash(rm -rf /)",
|
||||
"Bash(git push --force*)",
|
||||
"Bash(npm publish*)",
|
||||
"Edit(.env*)",
|
||||
"Edit(secrets.*)"
|
||||
]
|
||||
},
|
||||
"hooks": {
|
||||
"UserPromptSubmit": [
|
||||
{
|
||||
"matcher": "",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "cat <<'INJECT'\n[D3RO-VOICE 강제 규칙]\n1. 구현 전 반드시 설계서 참조: docs/design/00~03 (아키텍처, 서비스 명세, IPC 타입, DB/UI)\n2. 서비스: 싱글톤 + EventEmitter. 설계서 01의 인터페이스를 그대로 구현\n3. IPC: 설계서 02의 ipc-channels.ts 채널명/타입을 그대로 사용\n4. 에러: 설계서 02의 D3ROError + ErrorCode enum 사용\n5. DB: 설계서 03의 drizzle-orm 스키마를 그대로 사용\n6. UI: 설계서 03의 컴포넌트 Props/상태/IPC 명세를 그대로 따름\n7. 윈도우: 프리로딩 + 2-phase 리사이즈 (설계서 01 WindowManagerService)\n8. 상태머신: RecognitionState + AudioState 분리 (설계서 01 VoiceModeService)\n9. 팝업: Vanilla JS, 설계서 03의 HTML/CSS/애니메이션 스펙 준수\n10. any 타입 절대 금지, console.log 절대 금지\nINJECT"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"PostToolUse": [
|
||||
{
|
||||
"matcher": "Write|Edit",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "FILE=$(cat /dev/stdin | python -c \"import sys,json; d=json.load(sys.stdin); print(d.get('tool_input',{}).get('file_path',''))\" 2>/dev/null); if echo \"$FILE\" | grep -qE '\\.(ts|tsx)$'; then cd 'D:/workspace/D3ROVoice' && npx tsc --noEmit 2>&1 | head -15 || true; fi"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"matcher": "Write",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "FILE=$(cat /dev/stdin | python -c \"import sys,json; d=json.load(sys.stdin); print(d.get('tool_input',{}).get('file_path',''))\" 2>/dev/null); if echo \"$FILE\" | grep -qE '\\.(ts|tsx)$'; then grep -n 'any' \"$FILE\" 2>/dev/null | grep -v '// eslint-disable' | grep -v 'import' | head -5 && echo '[WARN] any 타입 발견 - 수정 필요' || true; fi"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"PreToolUse": [
|
||||
{
|
||||
"matcher": "Write|Edit",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "FILE=$(cat /dev/stdin | python -c \"import sys,json; d=json.load(sys.stdin); print(d.get('tool_input',{}).get('file_path',''))\" 2>/dev/null); if echo \"$FILE\" | grep -qE '\\.env|\\.secret|credentials'; then echo 'BLOCKED: 시크릿 파일 수정 금지' >&2; exit 2; fi; exit 0"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
29
.claude/skills/debug-electron/SKILL.md
Normal file
29
.claude/skills/debug-electron/SKILL.md
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
---
|
||||
name: debug-electron
|
||||
description: Electron 앱 디버깅. IPC 문제, 메모리 누수, 렌더러 크래시 등 진단.
|
||||
allowed-tools: Read Grep Glob Bash
|
||||
---
|
||||
|
||||
# Electron Debug
|
||||
|
||||
## 일반 디버깅
|
||||
1. 로그 확인 (`electron-log` 출력)
|
||||
2. IPC 채널 매칭 검증 (`shared/ipc-channels.ts` vs 실제 핸들러)
|
||||
3. 프리로드 스크립트 노출 API 확인
|
||||
|
||||
## IPC 문제
|
||||
- `shared/ipc-channels.ts`에 채널 정의 확인
|
||||
- `src/main/ipc/`에 핸들러 등록 확인
|
||||
- `src/preload/index.ts`에 브릿지 노출 확인
|
||||
- 렌더러에서 `window.electronAPI.*` 호출 확인
|
||||
|
||||
## 오디오 문제
|
||||
- Web Audio API 초기화 상태
|
||||
- 마이크 권한 확인
|
||||
- AudioContext sampleRate (24000Hz)
|
||||
- noiseSuppression: false 확인
|
||||
|
||||
## 메모리 누수
|
||||
- useEffect cleanup 함수 확인
|
||||
- IPC 이벤트 리스너 제거 확인
|
||||
- BrowserWindow destroy 확인
|
||||
45
.claude/skills/implement-phase/SKILL.md
Normal file
45
.claude/skills/implement-phase/SKILL.md
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
---
|
||||
name: implement-phase
|
||||
description: Speakly RE 노하우를 기반으로 D3RO-VOICE의 특정 페이즈를 구현. 페이즈 번호를 인자로 전달.
|
||||
argument-hint: "[phase number, e.g. 1]"
|
||||
allowed-tools: Read Write Edit Bash Glob Grep Agent
|
||||
---
|
||||
|
||||
# Phase Implementation
|
||||
|
||||
지정된 페이즈를 구현합니다.
|
||||
|
||||
## 실행 순서
|
||||
|
||||
1. **설계서 로드** (필수, 반드시 먼저):
|
||||
- `docs/design/00-master-architecture.md` — 파일 트리, 초기화 순서, 서비스 의존관계
|
||||
- `docs/design/01-service-specifications.md` — 서비스 인터페이스, 상태 머신, 이벤트
|
||||
- `docs/design/02-ipc-and-types.md` — IPC 채널, TypeScript 타입, 에러 코드
|
||||
- `docs/design/03-db-and-ui.md` — DB 스키마, 컴포넌트 명세, MUI 테마
|
||||
2. **페이즈 문서 로드**: `docs/phases/phase-$ARGUMENTS.md` 읽기
|
||||
3. **RE 참조 문서 확인**: `docs/re-findings/` 에서 관련 노하우 확인
|
||||
4. **현재 코드 상태 파악**: 기존 구현된 코드 검토
|
||||
4. **구현 계획 수립**: TaskCreate로 세부 태스크 생성
|
||||
5. **구현**: 태스크별로 순차 구현
|
||||
- 타입 정의 (shared/) 먼저
|
||||
- 메인 프로세스 서비스 구현
|
||||
- IPC 핸들러 등록
|
||||
- 렌더러 UI 구현
|
||||
- 프리로드 브릿지 업데이트
|
||||
6. **테스트**: 각 모듈 단위 테스트
|
||||
7. **CLAUDE.md 업데이트**: 현재 상태 갱신
|
||||
|
||||
## 구현 규칙 (위반 불가)
|
||||
- 서비스는 **설계서 01**의 인터페이스를 그대로 구현 (메서드 시그니처, 이벤트 페이로드 일치)
|
||||
- IPC 채널은 **설계서 02**의 `IPC_CHANNELS` 상수를 그대로 사용 (임의 채널명 금지)
|
||||
- 타입은 **설계서 02**의 `shared/types.ts` 정의를 그대로 사용 (임의 타입 금지)
|
||||
- 에러는 **설계서 02**의 `D3ROError` + `ErrorCode` enum 사용
|
||||
- DB는 **설계서 03**의 drizzle-orm 스키마 그대로 사용
|
||||
- UI는 **설계서 03**의 컴포넌트 Props/상태 명세 준수
|
||||
- 팝업은 **설계서 03**의 HTML/CSS/애니메이션 수학 공식 준수
|
||||
|
||||
## 완료 조건
|
||||
- 모든 태스크 completed
|
||||
- `npm run typecheck` 통과
|
||||
- `npm run test` 통과
|
||||
- CLAUDE.md "현재 상태" 업데이트됨
|
||||
27
.claude/skills/review-phase/SKILL.md
Normal file
27
.claude/skills/review-phase/SKILL.md
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
---
|
||||
name: review-phase
|
||||
description: 완료된 페이즈를 검토하고 다음 페이즈 준비 상태를 판단. 페이즈 번호를 인자로 전달.
|
||||
argument-hint: "[phase number, e.g. 1]"
|
||||
allowed-tools: Read Glob Grep Bash Agent
|
||||
---
|
||||
|
||||
# Phase Review
|
||||
|
||||
완료된 페이즈를 검토합니다.
|
||||
|
||||
## 검토 항목
|
||||
|
||||
1. **요구사항 충족**: `docs/phases/phase-$ARGUMENTS.md` 대비 구현 완성도
|
||||
2. **Speakly 패턴 적용**: RE 노하우가 제대로 반영되었는지
|
||||
- 상태 머신 설계가 Speakly 수준인가?
|
||||
- 에러 처리가 포괄적인가?
|
||||
- 윈도우 관리가 프리로딩 + 2-phase 리사이즈인가?
|
||||
3. **코드 품질**: TypeScript strict, 일관된 네이밍, 중복 없음
|
||||
4. **테스트 커버리지**: 핵심 서비스에 단위 테스트 존재
|
||||
5. **타입 안전성**: `npm run typecheck` 통과
|
||||
6. **빌드**: `npm run build` 통과
|
||||
|
||||
## 출력
|
||||
- 발견된 이슈 목록 (심각도: critical/major/minor)
|
||||
- 다음 페이즈 진행 가능 여부 (GO/NO-GO)
|
||||
- CLAUDE.md 업데이트 제안
|
||||
31
.claude/skills/scaffold-component/SKILL.md
Normal file
31
.claude/skills/scaffold-component/SKILL.md
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
---
|
||||
name: scaffold-component
|
||||
description: D3RO-VOICE 프로젝트 컨벤션에 맞게 새 컴포넌트/서비스를 스캐폴딩. 이름을 인자로 전달.
|
||||
argument-hint: "[component or service name]"
|
||||
allowed-tools: Read Write Glob
|
||||
---
|
||||
|
||||
# Scaffold
|
||||
|
||||
프로젝트 컨벤션에 맞는 새 모듈을 생성합니다.
|
||||
|
||||
## 서비스 스캐폴딩 (메인 프로세스)
|
||||
Speakly 패턴 적용:
|
||||
- 싱글톤 + EventEmitter
|
||||
- 로거 태그 `[ServiceName]`
|
||||
- 초기화/종료 메서드
|
||||
- IPC 채널 `shared/ipc-channels.ts`에 추가
|
||||
|
||||
## React 컴포넌트 스캐폴딩 (렌더러)
|
||||
- 함수형 컴포넌트 + TypeScript Props 인터페이스
|
||||
- MUI sx prop 기반 스타일링
|
||||
- electronAPI IPC 호출 패턴
|
||||
|
||||
## Vanilla JS 팝업 스캐폴딩
|
||||
Speakly 패턴:
|
||||
- 별도 HTML 엔트리포인트
|
||||
- 순수 DOM 조작 (React 미사용)
|
||||
- 2-phase 리사이즈: prepare(측정) → resize → show
|
||||
- mouseenter/leave 이벤트 메인 프로세스 전달
|
||||
|
||||
모듈명: $ARGUMENTS
|
||||
32
.claude/skills/test-and-commit/SKILL.md
Normal file
32
.claude/skills/test-and-commit/SKILL.md
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
---
|
||||
name: test-and-commit
|
||||
description: 테스트 실행 후 통과하면 커밋. 코드 변경 완료 후 사용.
|
||||
allowed-tools: Bash Read
|
||||
---
|
||||
|
||||
# Test & Commit
|
||||
|
||||
1. **타입 체크**
|
||||
```bash
|
||||
npm run typecheck
|
||||
```
|
||||
|
||||
2. **린트**
|
||||
```bash
|
||||
npm run lint
|
||||
```
|
||||
|
||||
3. **테스트**
|
||||
```bash
|
||||
npm run test
|
||||
```
|
||||
|
||||
4. **모두 통과 시 커밋**
|
||||
- git status로 변경 파일 확인
|
||||
- git diff로 변경 내용 확인
|
||||
- 적절한 커밋 메시지 작성 (한글, Conventional Commits)
|
||||
- Co-Authored-By 절대 추가 금지
|
||||
|
||||
5. **실패 시**
|
||||
- 에러 내용 분석
|
||||
- 수정 후 재시도
|
||||
Loading…
Add table
Add a link
Reference in a new issue