초기 프로젝트 설정: 하네스 시스템 + 설계서 + 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:
Yun Chan 2026-04-05 01:03:03 +09:00
commit e24bb8378c
35 changed files with 11452 additions and 0 deletions

88
.claude/settings.json Normal file
View 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"
}
]
}
]
}
}