{ "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" } ] } ] } }