Phase 14 구현: 회의 모드 (Meeting Mode)
실시간 녹음 + 타임스탬프 메모 + STT 전사 + LLM 구조화 회의록 + PDF/MD 내보내기. CaptionService 연동, 동시 사용 충돌 방지, 긴 회의 2-pass 요약 지원. DB 2테이블, IPC 15채널, UI 3뷰(목록/녹음/상세), 12개 locale i18n.
This commit is contained in:
parent
dd68fc9ccd
commit
d0c4f9ee53
38 changed files with 2550 additions and 769 deletions
|
|
@ -12,36 +12,37 @@ tools:
|
|||
|
||||
# UI Specialist
|
||||
|
||||
Speakly 렌더러 분석(781KB 번들)에서 추출한 UI 패턴을 적용.
|
||||
D3RO-VOICE의 "정밀 기기(Meteorological Instrument)" 디자인 정체성을 구현.
|
||||
|
||||
## 컴포넌트 구조 (Speakly 패턴)
|
||||
```
|
||||
App (root)
|
||||
├── ThemeProvider (MUI, light/dark/auto)
|
||||
├── Drawer (240px 사이드바)
|
||||
│ ├── NavItems
|
||||
│ └── BottomBar
|
||||
└── Content Area
|
||||
├── Dashboard (통계, 최근 세션)
|
||||
├── History (검색, 재시도)
|
||||
├── Dictionary (사전 관리)
|
||||
└── Settings (Modal)
|
||||
```
|
||||
## 디자인 토큰 체계 (SSOT)
|
||||
- **d3roPalette**: 색상 토큰 (theme.ts에서 export)
|
||||
- **d3roTypo**: 13단계 타이포 (hero 42px ~ nano 7px)
|
||||
- **d3roShadow**: 10종 그림자 (chassis/card/inset/button 등)
|
||||
- **d3roRadius**: 7종 반경 (outer 24px ~ pill 999px)
|
||||
- hex 리터럴 직접 사용 금지 (theme.ts 제외)
|
||||
|
||||
## MUI 테마 (Speakly 참조)
|
||||
- primary: rgb(31, 93, 242)
|
||||
- borderRadius: 12
|
||||
- fontFamily: -apple-system, BlinkMacSystemFont, "Segoe UI"
|
||||
- textTransform: 'none'
|
||||
- WebkitAppRegion: 'drag' (타이틀바)
|
||||
## DS 컴포넌트 (src/renderer/components/ds/)
|
||||
- CrtDisplay: WebGL CRT 셰이더 (파형+스캔라인+비네팅+글리치)
|
||||
- InstrumentPanel: 메탈 섀시 컨테이너
|
||||
- Led: LED 인디케이터 (amber/green/red, pulse)
|
||||
- PhysicalButton: 물리 버튼 (돌출 그림자, 눌림)
|
||||
- MetalCard: 메탈 카드 컨테이너
|
||||
- PhosphorText: 인광 텍스트 (13종 변형)
|
||||
- MetalDial: 메탈 다이얼 (드래그 회전)
|
||||
- ScreenPanel: 글래스 스크린 패널
|
||||
- ButtonGroup: 인셋 버튼 클러스터
|
||||
|
||||
## 녹음 UI 상태 머신
|
||||
opening → recording → thinking → result/error/cancelled
|
||||
- 9개 wave-bar, cos(n*PI/2) 분포 가중치
|
||||
- 100ms 간격 setInterval, smoothing: v += (S-v)*0.5
|
||||
- 100ms 간격, smoothing: v += (S-v)*0.5
|
||||
- thinking: `min(95, (1 - 1/(1+1.5*t)) * 100)%` 점근 수렴
|
||||
|
||||
## 팝업 윈도우 (Vanilla JS)
|
||||
- 별도 HTML 엔트리포인트, React 미사용
|
||||
- 별도 HTML, React 미사용
|
||||
- 2-phase 리사이즈: prepare → measured → show
|
||||
- CSS transition + transitionend + 200ms setTimeout 폴백
|
||||
- 앰버 악센트(#f25b29)
|
||||
|
||||
## i18n
|
||||
- React: t() 함수 사용, 하드코딩 한국어/영어 금지
|
||||
- 리소스: src/renderer/locales/{ko,en}.json
|
||||
|
|
|
|||
|
|
@ -28,16 +28,17 @@ AudioState: IDLE → INITIALIZING → STREAMING → STOPPED (별도 추적)
|
|||
- 이중 조건 플러시: 모델 로딩 + 오디오 캡처 병렬
|
||||
- `_tryFlushAll()`: 양쪽 조건 모두 true 시 flush
|
||||
- 순서 보장: 설정 메시지 → 오디오 데이터
|
||||
- "오디오 손실 방지 > 컨텍스트 품질" 원칙
|
||||
|
||||
## 오디오 설정
|
||||
- sampleRate: 24000Hz → 16000Hz (Whisper 기본)
|
||||
- channels: 1 (mono)
|
||||
- noiseSuppression: false (초기 프레임 손실 방지)
|
||||
- echoCancellation: false (일방향 입력)
|
||||
- autoGainControl: false
|
||||
- sampleRate: 16000Hz (Whisper 기본)
|
||||
- channels: 1 (mono), bitDepth: 16 (PCM16)
|
||||
- noiseSuppression: false, echoCancellation: false, autoGainControl: false
|
||||
|
||||
## 로컬 STT 연동
|
||||
- Whisper에 PCM 16-bit 16kHz mono 직접 전달
|
||||
- Opus 인코딩 불필요 (로컬이므로)
|
||||
- faster-whisper Python sidecar 또는 whisper.cpp addon
|
||||
- PCM 16-bit 16kHz mono → faster-whisper Python sidecar (FastAPI HTTP)
|
||||
- Opus 인코딩 불필요 (로컬)
|
||||
|
||||
## 타이밍 상수
|
||||
- 더블프레스: 300ms, 최소 오디오: 700ms
|
||||
- 녹음 후 대기: 4초 (버퍼 있으면 6초)
|
||||
- 완료 아이들 타임아웃: 30초, 절대 최대: 120초
|
||||
|
|
|
|||
|
|
@ -10,35 +10,26 @@
|
|||
"Bash(git *)",
|
||||
"Bash(ls *)",
|
||||
"Bash(mkdir *)",
|
||||
"Bash(cat *)",
|
||||
"Bash(which *)",
|
||||
"Bash(python *)",
|
||||
"Bash(pip *)",
|
||||
"Bash(taskkill *)",
|
||||
"Bash(sleep *)",
|
||||
"Bash(mv *)",
|
||||
"Bash(tail *)",
|
||||
"Bash(head *)",
|
||||
"Bash(grep *)",
|
||||
"Bash(wc *)",
|
||||
"Bash(rm *)",
|
||||
"Edit(src/**)",
|
||||
"Edit(tests/**)",
|
||||
"Edit(docs/**)",
|
||||
"Edit(scripts/**)",
|
||||
"Edit(.claude/**)",
|
||||
"Edit(*.md)",
|
||||
"Edit(*.json)",
|
||||
"Edit(*.ts)",
|
||||
"Edit(*.tsx)",
|
||||
"Edit(*.js)",
|
||||
"Edit(*.css)",
|
||||
"Edit(*.html)",
|
||||
"Write(src/**)",
|
||||
"Write(tests/**)",
|
||||
"Write(docs/**)",
|
||||
"Write(scripts/**)",
|
||||
"Write(.claude/**)",
|
||||
"Write(*.md)",
|
||||
"Write(*.json)",
|
||||
"Write(*.ts)",
|
||||
"Write(*.tsx)"
|
||||
"Write(*.json)"
|
||||
],
|
||||
"deny": [
|
||||
"Bash(rm -rf /)",
|
||||
|
|
@ -84,7 +75,16 @@
|
|||
"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 'src/renderer/.*\\.(tsx|ts)$' && ! echo \"$FILE\" | grep -q 'theme\\.ts' && ! echo \"$FILE\" | grep -q 'theme-vars'; then HC=$(grep -noE \"'#[0-9a-fA-F]{6}'\" \"$FILE\" 2>/dev/null | grep -v '//' | head -3); if [ -n \"$HC\" ]; then echo \"[SSOT WARN] 하드코딩 hex 색상 — d3roPalette/CSS var 사용:\"; echo \"$HC\"; fi; fi"
|
||||
"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 'src/renderer/.*\\.(tsx|ts)$' && ! echo \"$FILE\" | grep -q 'theme\\.ts' && ! echo \"$FILE\" | grep -q 'theme-vars'; then HC=$(grep -noE '#[0-9a-fA-F]{6}' \"$FILE\" 2>/dev/null | grep -v '//' | grep -v 'var(' | head -3); if [ -n \"$HC\" ]; then echo \"[SSOT WARN] 하드코딩 hex 색상 — d3roPalette/CSS var 사용:\"; echo \"$HC\"; fi; fi"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"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 'src/renderer/.*\\.tsx$' && ! echo \"$FILE\" | grep -qE 'locales/|i18n|test'; then I18N=$(python -c \"import re; lines=open('$FILE','r',encoding='utf-8').readlines(); [print(f'{i+1}:{l.rstrip()}') for i,l in enumerate(lines) if re.search(r'[\\uAC00-\\uD7AF]{2,}',l) and '//' not in l and 'import' not in l]\" 2>/dev/null | head -3); if [ -n \"$I18N\" ]; then echo \"[i18n WARN] 하드코딩 한국어 문자열 — t() 함수 사용 필요:\"; echo \"$I18N\"; fi; fi"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,29 +1,46 @@
|
|||
---
|
||||
name: debug-electron
|
||||
description: Electron 앱 디버깅. IPC 문제, 메모리 누수, 렌더러 크래시 등 진단.
|
||||
allowed-tools: Read Grep Glob Bash
|
||||
allowed-tools: Read Grep Glob Bash Edit
|
||||
---
|
||||
|
||||
# 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.*` 호출 확인
|
||||
## 0. 자동 진단 파이프라인
|
||||
|
||||
## 오디오 문제
|
||||
- Web Audio API 초기화 상태
|
||||
- 마이크 권한 확인
|
||||
- AudioContext sampleRate (24000Hz)
|
||||
- noiseSuppression: false 확인
|
||||
증상 분류 → 해당 섹션 실행 → 원인 보고 → 수정 제안
|
||||
|
||||
## 메모리 누수
|
||||
- useEffect cleanup 함수 확인
|
||||
- IPC 이벤트 리스너 제거 확인
|
||||
- BrowserWindow destroy 확인
|
||||
1. **로그 수집**: `npm run dev` 출력 또는 electron-log 파일 확인
|
||||
2. **에러 분류**: IPC / 오디오 / 메모리 / 렌더러 크래시 / 빌드
|
||||
3. **해당 섹션 진단 실행**
|
||||
4. **원인 + 수정 방안 보고**
|
||||
|
||||
## IPC 문제 진단
|
||||
|
||||
자동 실행할 검증 체인:
|
||||
1. `shared/ipc-channels.ts`에서 문제 채널 Grep → 채널 정의 존재?
|
||||
2. `src/main/ipc/`에서 해당 채널 핸들러 Grep → `ipcMain.handle`/`on` 등록?
|
||||
3. `src/preload/index.ts`에서 `contextBridge.exposeInMainWorld` Grep → 브릿지 노출?
|
||||
4. `src/renderer/`에서 `window.electronAPI.*` 호출 Grep → 렌더러 사용?
|
||||
5. 1~4 중 끊어진 체인 지점이 원인
|
||||
|
||||
## 오디오 문제 진단
|
||||
|
||||
1. SoX 경로 확인: `src/main/utils/paths.ts` → `getSoxPath` 읽기
|
||||
2. AudioCaptureService 설정 확인: sampleRate 16000, noiseSuppression false
|
||||
3. faster-whisper sidecar 프로세스 상태: `tasklist | grep python`
|
||||
4. 마이크 권한: Electron `systemPreferences.getMediaAccessStatus('microphone')`
|
||||
|
||||
## 메모리 누수 진단
|
||||
|
||||
1. `useEffect` cleanup 누락 Grep: `useEffect` 있는데 return 없는 패턴
|
||||
2. IPC 리스너 제거 누락: `ipcRenderer.on` 대비 `removeListener`/`removeAllListeners` 검색
|
||||
3. BrowserWindow destroy 확인: `close` 이벤트에서 `destroy()` 호출 여부
|
||||
|
||||
## 빌드/타입 문제
|
||||
|
||||
1. `npm run typecheck 2>&1 | head -30` 실행
|
||||
2. 에러 파일/라인 추출 후 해당 코드 Read
|
||||
3. 원인 분석 후 수정 제안
|
||||
|
|
|
|||
|
|
@ -1,47 +1,65 @@
|
|||
---
|
||||
name: implement-phase
|
||||
description: Speakly RE 노하우를 기반으로 D3RO-VOICE의 특정 페이즈를 구현. 페이즈 번호를 인자로 전달.
|
||||
argument-hint: "[phase number, e.g. 1]"
|
||||
argument-hint: "[phase number or feature name]"
|
||||
allowed-tools: Read Write Edit Bash Glob Grep Agent
|
||||
---
|
||||
|
||||
# Phase Implementation
|
||||
# Feature / Phase Implementation
|
||||
|
||||
지정된 페이즈를 구현합니다.
|
||||
페이즈 또는 새 기능을 구현합니다.
|
||||
|
||||
## 실행 순서
|
||||
## 0. 사전 조건 가드 (스킵 불가)
|
||||
|
||||
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 업데이트**: 현재 상태 갱신
|
||||
8. **Memory 갱신** (필수): `project_status.md`에 완료된 Phase, 작업 내역, 기술 결정 기록
|
||||
구현 시작 전 반드시 아래를 확인하고, 실패 시 유저에게 보고 후 중단:
|
||||
|
||||
1. **Git 클린 상태**: `git status --porcelain` — 커밋되지 않은 변경이 있으면 경고 후 커밋/스태시 제안
|
||||
2. **페이즈 문서 존재**: 페이즈 번호 전달 시 `docs/phases/phase-$ARGUMENTS.md` 파일 존재 확인. 없으면 중단
|
||||
3. **이전 페이즈 완료 확인**: `memory/project_status.md` 읽어서 선행 페이즈 완료 여부 확인. 미완료 시 경고
|
||||
4. **설계서 4종 존재 확인**: `docs/design/00~03` 파일 모두 존재 확인
|
||||
|
||||
## 1. 설계서 로드 (필수)
|
||||
|
||||
- `docs/design/00-master-architecture.md` — 아키텍처, 서비스 의존관계
|
||||
- `docs/design/01-service-specifications.md` — 서비스 인터페이스, 상태 머신
|
||||
- `docs/design/02-ipc-and-types.md` — IPC 채널, 타입, 에러 코드
|
||||
- `docs/design/03-db-and-ui.md` — DB 스키마, 컴포넌트 명세
|
||||
|
||||
## 2. 요구사항 파악
|
||||
|
||||
- 페이즈 번호 전달 시: `docs/phases/phase-$ARGUMENTS.md` 읽기
|
||||
- 피처명 전달 시: 유저 요구사항 분석 + 기존 코드 검토
|
||||
|
||||
## 3. RE 참조
|
||||
`docs/re-findings/`에서 관련 Speakly 패턴 확인
|
||||
|
||||
## 4. 현재 코드 파악
|
||||
기존 구현 검토, 영향 범위 분석
|
||||
|
||||
## 5. 구현 (순서 중요)
|
||||
|
||||
- shared/ 타입 정의
|
||||
- 메인 프로세스 서비스
|
||||
- IPC 핸들러
|
||||
- Preload 브릿지
|
||||
- 렌더러 UI (d3roPalette + DS 컴포넌트 활용)
|
||||
- i18n 키 추가 (ko/en)
|
||||
|
||||
## 6. 검증
|
||||
`npm run typecheck` 통과
|
||||
|
||||
## 7. 후속 워크플로우
|
||||
|
||||
구현 완료 후 아래 순서로 유저에게 안내:
|
||||
1. `/review-phase $ARGUMENTS` 실행을 제안 (코드 리뷰)
|
||||
2. 리뷰 통과 시 `/test-and-commit` 실행을 제안 (테스트 + 커밋)
|
||||
3. `memory/project_status.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 "현재 상태" 업데이트됨
|
||||
- Memory `project_status.md` 갱신됨 (Phase 완료 내역, 기술 결정, 다음 작업)
|
||||
- 서비스: 싱글톤 + EventEmitter, 설계서 01 인터페이스 준수
|
||||
- IPC: 설계서 02의 IPC_CHANNELS 상수 사용
|
||||
- 에러: D3ROError + ErrorCode enum
|
||||
- DB: drizzle-orm 스키마
|
||||
- UI: d3roPalette/d3roTypo/d3roShadow 토큰만 (hex 리터럴 금지)
|
||||
- i18n: t() 함수 (하드코딩 문자열 금지)
|
||||
- any 타입 절대 금지, console.log 절대 금지
|
||||
|
|
|
|||
|
|
@ -1,27 +1,39 @@
|
|||
---
|
||||
name: review-phase
|
||||
description: 완료된 페이즈를 검토하고 다음 페이즈 준비 상태를 판단. 페이즈 번호를 인자로 전달.
|
||||
argument-hint: "[phase number, e.g. 1]"
|
||||
allowed-tools: Read Glob Grep Bash Agent
|
||||
argument-hint: "[phase number or 'all' for full review]"
|
||||
allowed-tools: Read Edit Write Glob Grep Bash Agent
|
||||
---
|
||||
|
||||
# Phase Review
|
||||
# Code Review
|
||||
|
||||
완료된 페이즈를 검토합니다.
|
||||
완료된 페이즈 또는 전체 코드베이스를 검토합니다.
|
||||
|
||||
## 검토 항목
|
||||
|
||||
1. **요구사항 충족**: `docs/phases/phase-$ARGUMENTS.md` 대비 구현 완성도
|
||||
2. **Speakly 패턴 적용**: RE 노하우가 제대로 반영되었는지
|
||||
- 상태 머신 설계가 Speakly 수준인가?
|
||||
- 에러 처리가 포괄적인가?
|
||||
- 윈도우 관리가 프리로딩 + 2-phase 리사이즈인가?
|
||||
3. **코드 품질**: TypeScript strict, 일관된 네이밍, 중복 없음
|
||||
4. **테스트 커버리지**: 핵심 서비스에 단위 테스트 존재
|
||||
1. **요구사항 충족**: phase 문서 또는 유저 요구사항 대비 구현 완성도
|
||||
2. **Speakly 패턴 적용**:
|
||||
- 상태 머신 (RecognitionState + AudioState 분리)
|
||||
- 이중 조건 플러시
|
||||
- 프리로딩 + 2-phase 리사이즈
|
||||
- 에러 처리 포괄성
|
||||
3. **SSOT 준수** (Grep 도구 사용):
|
||||
- hex 하드코딩: `src/renderer/` 내 `.tsx`/`.ts`에서 `'#[0-9a-fA-F]{6}'` 검색 (theme.ts 제외 0건이어야 함)
|
||||
- i18n: `.tsx` 파일에서 한국어(`[\uAC00-\uD7AF]`) 또는 JSX 내 영어 문자열 리터럴 검색
|
||||
- CSS var 폴백 hex는 허용 (예: `var(--color, #fff)`)
|
||||
4. **코드 품질**: TypeScript strict, any 없음, console.log 없음
|
||||
5. **타입 안전성**: `npm run typecheck` 통과
|
||||
6. **빌드**: `npm run build` 통과
|
||||
|
||||
## 자동 수정
|
||||
|
||||
리뷰 중 발견된 minor 이슈는 유저 확인 후 직접 수정 가능 (Edit/Write 권한 있음):
|
||||
- CLAUDE.md 서비스 목록/현재 상태 갱신
|
||||
- memory/project_status.md 갱신
|
||||
|
||||
critical/major 이슈는 수정하지 말고 보고만 할 것.
|
||||
|
||||
## 출력
|
||||
- 발견된 이슈 목록 (심각도: critical/major/minor)
|
||||
- 다음 페이즈 진행 가능 여부 (GO/NO-GO)
|
||||
- CLAUDE.md 업데이트 제안
|
||||
- 이슈 목록 (심각도: critical/major/minor)
|
||||
- 진행 가능 여부 (GO/NO-GO)
|
||||
- GO일 경우 `/test-and-commit` 실행을 제안
|
||||
|
|
|
|||
|
|
@ -2,30 +2,54 @@
|
|||
name: scaffold-component
|
||||
description: D3RO-VOICE 프로젝트 컨벤션에 맞게 새 컴포넌트/서비스를 스캐폴딩. 이름을 인자로 전달.
|
||||
argument-hint: "[component or service name]"
|
||||
allowed-tools: Read Write Glob
|
||||
allowed-tools: Read Write Glob Grep Edit
|
||||
---
|
||||
|
||||
# Scaffold
|
||||
|
||||
프로젝트 컨벤션에 맞는 새 모듈을 생성합니다.
|
||||
|
||||
모듈명: $ARGUMENTS
|
||||
|
||||
## 0. 중복 방지 가드 (스킵 불가)
|
||||
|
||||
생성 전 반드시 확인:
|
||||
1. **서비스**: `src/main/services/` 내 동일 이름 파일 Glob 검색. 존재 시 유저에게 확인
|
||||
2. **컴포넌트**: `src/renderer/components/` 내 동일 이름 Glob 검색. 존재 시 유저에게 확인
|
||||
3. **IPC 채널**: `shared/ipc-channels.ts`에서 해당 feature 네임스페이스 Grep 검색. 충돌 시 경고
|
||||
4. **i18n 키**: `src/renderer/locales/ko.json`에서 해당 키 접두사 검색. 충돌 시 경고
|
||||
|
||||
## 서비스 스캐폴딩 (메인 프로세스)
|
||||
Speakly 패턴 적용:
|
||||
|
||||
Speakly 패턴:
|
||||
- 싱글톤 + EventEmitter
|
||||
- 로거 태그 `[ServiceName]`
|
||||
- 초기화/종료 메서드
|
||||
- 로거 태그 `[ServiceName]` (electron-log, console.log 금지)
|
||||
- 초기화/종료 메서드 (`initialize()` / `dispose()`)
|
||||
- IPC 채널 `shared/ipc-channels.ts`에 추가
|
||||
- 에러: D3ROError + ErrorCode enum
|
||||
|
||||
생성 파일:
|
||||
- `src/main/services/$ARGUMENTS.ts` — 서비스 본체
|
||||
- `shared/ipc-channels.ts` — 채널 추가 (Edit)
|
||||
- `src/main/ipc/` — 핸들러 등록 (Edit)
|
||||
|
||||
## React 컴포넌트 스캐폴딩 (렌더러)
|
||||
|
||||
- 함수형 컴포넌트 + TypeScript Props 인터페이스
|
||||
- MUI sx prop 기반 스타일링
|
||||
- electronAPI IPC 호출 패턴
|
||||
- 스타일: d3roPalette/d3roTypo/d3roShadow 토큰만 (hex 리터럴 금지)
|
||||
- DS 컴포넌트(MetalCard, PhosphorText, Led, PhysicalButton 등) 적극 활용
|
||||
- i18n: t() 함수 사용, 하드코딩 문자열 금지
|
||||
- IPC: window.electronAPI.* 호출
|
||||
|
||||
생성 파일:
|
||||
- `src/renderer/components/$ARGUMENTS.tsx` — 컴포넌트 본체
|
||||
- `src/renderer/locales/ko.json` — i18n 키 추가 (Edit)
|
||||
- `src/renderer/locales/en.json` — i18n 키 추가 (Edit)
|
||||
|
||||
## Vanilla JS 팝업 스캐폴딩
|
||||
Speakly 패턴:
|
||||
- 별도 HTML 엔트리포인트
|
||||
- 순수 DOM 조작 (React 미사용)
|
||||
- 2-phase 리사이즈: prepare(측정) → resize → show
|
||||
- mouseenter/leave 이벤트 메인 프로세스 전달
|
||||
|
||||
모듈명: $ARGUMENTS
|
||||
Speakly 패턴:
|
||||
- 별도 HTML 엔트리포인트, React 미사용
|
||||
- 순수 DOM 조작
|
||||
- 2-phase 리사이즈: prepare(측정) → resize → show
|
||||
- d3roPalette 토큰의 CSS var 사용
|
||||
|
|
|
|||
|
|
@ -1,32 +1,34 @@
|
|||
---
|
||||
name: test-and-commit
|
||||
description: 테스트 실행 후 통과하면 커밋. 코드 변경 완료 후 사용.
|
||||
allowed-tools: Bash Read
|
||||
allowed-tools: Bash Read Edit Write Glob Grep
|
||||
---
|
||||
|
||||
# Test & Commit
|
||||
|
||||
1. **타입 체크**
|
||||
```bash
|
||||
npm run typecheck
|
||||
```
|
||||
## 1. 검증 파이프라인 (순서대로)
|
||||
|
||||
2. **린트**
|
||||
```bash
|
||||
npm run lint
|
||||
```
|
||||
```bash
|
||||
npm run typecheck
|
||||
npm run lint
|
||||
npm run test
|
||||
```
|
||||
|
||||
3. **테스트**
|
||||
```bash
|
||||
npm run test
|
||||
```
|
||||
## 2. 실패 시 자동 수정
|
||||
|
||||
4. **모두 통과 시 커밋**
|
||||
- git status로 변경 파일 확인
|
||||
- git diff로 변경 내용 확인
|
||||
- 적절한 커밋 메시지 작성 (한글, Conventional Commits)
|
||||
- Co-Authored-By 절대 추가 금지
|
||||
- 에러 메시지를 분석하고 원인 파일을 찾아 수정 (Edit/Write 사용)
|
||||
- 수정 후 실패한 단계부터 재실행
|
||||
- 최대 3회 재시도. 3회 초과 시 유저에게 보고 후 중단
|
||||
- 수정 범위는 에러를 고치는 최소한으로 제한 (리팩토링 금지)
|
||||
|
||||
5. **실패 시**
|
||||
- 에러 내용 분석
|
||||
- 수정 후 재시도
|
||||
## 3. 모두 통과 시 커밋
|
||||
|
||||
- `git status`로 변경 파일 확인
|
||||
- `git diff`로 변경 내용 확인
|
||||
- `git log --oneline -5`로 기존 커밋 스타일 확인
|
||||
- 적절한 커밋 메시지 작성 (한글, Conventional Commits)
|
||||
- Co-Authored-By, Claude 관련 문구 절대 추가 금지
|
||||
|
||||
## 4. 커밋 후
|
||||
|
||||
- `memory/project_status.md` 갱신 필요 여부 유저에게 확인
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue