agent update
This commit is contained in:
parent
4fdf8bfdf8
commit
5cd1de6859
31 changed files with 13993 additions and 0 deletions
217
.claude/skills/refactor-wave/SKILL.md
Normal file
217
.claude/skills/refactor-wave/SKILL.md
Normal file
|
|
@ -0,0 +1,217 @@
|
|||
---
|
||||
name: refactor-wave
|
||||
description: 대규모 리팩토링·코드 정리·SSOT 확립 워크플로우 하네스. 사용자가 "리팩토링 한번 싹", "정리 좀 하고 가자", "공격적 감사", "워크스트림 발사", "토큰 일원화", "데드코드 정리", "SSOT", "/simplify 제대로", "더 정리할 여지" 등을 언급하면 반드시 사용. 정책 합의 → 공격적 감사 → 멀티 에이전트 병렬 워크스트림 → 분리 커밋 → 보고서 순서를 강제한다.
|
||||
---
|
||||
|
||||
# 리팩토링 Wave 워크플로우 하네스 (D3RO-VOICE)
|
||||
|
||||
## 트리거
|
||||
- `/refactor-wave` 슬래시 명령
|
||||
- "리팩토링 싹", "정리 좀", "공격적 감사", "워크스트림", "SSOT", "데드코드", "토큰 일원화", "더 정리할 여지" 키워드
|
||||
- /simplify 후 사용자가 "더 큰 정리"를 요청할 때
|
||||
- Phase 완료 후 누적 부채 청소가 필요한 시점
|
||||
|
||||
## 절대 규칙 (Non-Negotiable)
|
||||
|
||||
### R1. 정책을 먼저 박는다
|
||||
**감사·작업 전에 `docs/REFACTOR_POLICY.md` 합의·갱신.** 미합의 정책 위에 작업하면 1주 후 회귀 + 1달 후 갈팡질팡.
|
||||
- 8개 결정 포인트 표준: 디자인 토큰(d3roPalette/theme.ts) / IPC 채널·타입 SSOT / i18n(t() + locale 키) / 서비스 경계(싱글톤+EventEmitter) / 상태 관리(RecognitionState+AudioState) / packages↔apps 의존 방향 / DRY 임계치 / 자동화(lint·typecheck·훅)
|
||||
- 새 결정 포인트 발견 시 정책 문서 즉시 추가
|
||||
- 결정 근거(외부 리서치 포함)는 정책 문서 별도 섹션에 박기
|
||||
|
||||
### R2. 공격적 감사 모드 강제
|
||||
보수적 에이전트는 5건 보고하고 끝남. 공격적 모드 명시:
|
||||
- "false negative > false positive"
|
||||
- "건들지 말자" 결론 금지
|
||||
- "DELETE / REPLACE / REFACTOR / KEEP+사유" 4가지 중 명시
|
||||
- "20~40개 발견되어야 정상"
|
||||
- 확신도(HIGH/MED/LOW) 명시해서 사용자 필터링 가능
|
||||
|
||||
### R3. 멀티 에이전트 병렬 발사 — 파일 충돌 사전 분리
|
||||
워크스트림은 **파일 영역이 겹치지 않도록** 분할:
|
||||
| WS | 영역 |
|
||||
|----|------|
|
||||
| WS1 | 토큰/SSOT 정의 (`packages/ui/src/theme.ts`, `theme-vars.ts`, `components/ds/`) |
|
||||
| WS2 | 메인 프로세스 (`apps/desktop/src/main/services/`, preload, shared 타입, IPC) |
|
||||
| WS3 | 렌더러 UI (`apps/desktop/src/renderer/`, 화면별 분담) — **WS1 의존** |
|
||||
| WS4 | i18n (`packages/i18n/src/locales/`, t() 키 정리) |
|
||||
| WS5 | 빌드/설정/팝업 (package.json, electron.vite.config, electron-builder.yml, turbo.json, Vanilla JS 팝업) |
|
||||
|
||||
- 같은 파일을 두 워크스트림이 건드리면 충돌 → 분담 시 영역 명시
|
||||
- WS3는 WS1 산출물(토큰 정의) 의존이라 1차 완료 후 발사
|
||||
- 화면별 분담(Dashboard/History/Settings/Meeting/Chat 등)으로 추가 병렬화 가능
|
||||
- V2 모노레포 주의: `packages/core`·`ui`·`i18n`은 여러 앱이 공유 — packages 변경 시 영향 앱(desktop/web/mobile) 전부 typecheck
|
||||
|
||||
### R4. 에이전트 작업 위치 명시
|
||||
**메인 작업 디렉터리** vs **worktree** 혼동 차단:
|
||||
- 에이전트 프롬프트에 "메인 디렉터리 `D:\workspace\D3ROVoice`" 절대경로 명시
|
||||
- "shell cwd가 worktree로 잡히면 절대경로로 접근" 강조
|
||||
- 에이전트가 변경한 파일이 메인에 있는지 worktree에 있는지 보고서에서 확인
|
||||
|
||||
### R5. 커밋 직전 staging 청소
|
||||
**처음 분리 커밋 시 가장 흔한 실수**: 이전 staging 묻어들어가 한 커밋에 19 files 등장.
|
||||
```bash
|
||||
git reset HEAD # 모든 staging 해제
|
||||
git add <ws-specific-files> # 정밀하게 add
|
||||
git commit -m "..." # 커밋
|
||||
```
|
||||
워크스트림당 1 커밋 원칙. `git add -A` / `git add .` 금지.
|
||||
|
||||
### R6. 에이전트는 커밋하지 않는다
|
||||
- 에이전트 프롬프트에 "**커밋하지 마세요**" 명시
|
||||
- 메인 작업자(=Claude 본체)가 통합 검토 + 분리 커밋
|
||||
- 에이전트는 "변경 파일 목록 + 요약 + git status" 보고만
|
||||
|
||||
### R7. 검증 체크리스트
|
||||
워크스트림 통합 후 반드시:
|
||||
1. `npm run typecheck` GREEN (packages 변경 시 모노레포 전체). 단 codebase에 pre-existing 타입에러가 있으면 "내가 건드린 영역/workspace GREEN"으로 재해석 + pre-existing은 별도 wave.
|
||||
2. `npm run lint` — 전체가 pre-existing 부채로 붕괴 시(P9), **변경 파일만 lint해 errors 0**를 게이트로. `git diff --name-only HEAD | grep -E '\.(ts|tsx)$' | xargs npx eslint` (삭제 파일 제외).
|
||||
3. `npm run test` GREEN
|
||||
4. `npm run build` GREEN (빌드 영향 워크스트림만이라도)
|
||||
5. UI 변경 있으면 `npm run dev`로 실제 화면 1회 확인 (WS3는 화면별 즉시)
|
||||
6. **배포(tag push) 전 런타임 게이트 — v0.2.1-alpha 교훈, 강제**: typecheck/lint/test GREEN만으로 런타임을 보장하지 않는다. **tag push 전 반드시 `npm run dev`로 main 프로세스 기동을 확인** + 가능하면 산물 설치 e2e. 특히 **config 기본값 누락 / 타입 캐스팅(`as never`) 제거 / 의존성 제거 / 인터페이스-구현체 분리** 변경은 런타임 크래시에 직결 — 정적 검증(GREEN)에 속아 동작 확인을 건너뛰지 말 것. (사례: WS2가 AppConfig 인터페이스에 키 추가 + `as never` 제거했으나 CONFIG_DEFAULTS 기본값 누락 → typecheck GREEN but 런타임 `undefined.map()` 크래시 → v0.2.0-alpha 배포 실패, 사용자가 발견.)
|
||||
|
||||
### R8. 보고서 + 하네스 동시 작성
|
||||
1차 완료 시 두 문서 필수:
|
||||
- `docs/REFACTOR_WAVE{N}_REPORT.md` — 정량 산출물 + SKIP 사유 + 후속 계획 + 메타 학습
|
||||
- 본 SKILL.md 갱신 — 이번 wave에서 배운 패턴 반영
|
||||
|
||||
## 표준 절차 (8단계)
|
||||
|
||||
### Step 1. 진입점 결정
|
||||
- 트리거 발동 → 사용자 의도 확인
|
||||
- 범위 합의 (desktop만? packages/web/mobile/site 포함?)
|
||||
- 실행 검증 빈도 합의 (화면별 vs 한꺼번에)
|
||||
|
||||
### Step 2. 정책 작성·갱신
|
||||
- `docs/REFACTOR_POLICY.md` 작성 또는 갱신
|
||||
- 8개 결정 포인트 사용자에게 한 줄씩 OK 받기
|
||||
- 모르겠다는 항목은 비교 옵션 + 앱 특성 기반 추천 + 외부 리서치까지 제공
|
||||
- 외부 의존성(Electron, Ollama, faster-whisper 등) 결정은 WebSearch/context7로 최신 정보 확인 후
|
||||
|
||||
### Step 3. 공격적 감사 (3 에이전트 병렬)
|
||||
Explore 에이전트 3개에 다음 영역 분담:
|
||||
- Agent A: 메인 프로세스 — 서비스 패턴 위반(싱글톤/EventEmitter), IPC 채널·타입 불일치, D3ROError 미사용, 데드코드, TODO/stub
|
||||
- Agent B: 렌더러/UI — hex 하드코딩, d3roPalette/d3roTypo/d3roShadow 미사용, DS 컴포넌트 미활용, i18n 하드코딩(t() 미사용), any/console.log
|
||||
- Agent C: 리소스/설정 — 미사용 의존성, locale 키 누락·고아 키, 문서-코드 정합(CLAUDE.md 서비스 목록 vs 실제), 스크립트/빌드 설정
|
||||
|
||||
각 에이전트 프롬프트에 "공격적 모드 4원칙"(R2) 박기. 결과 통합 시 중복 제거 + 우선순위 표 작성.
|
||||
|
||||
**유용한 감사 grep** (근사 필터, 결과는 반드시 Read로 재검증):
|
||||
```bash
|
||||
grep -rnE ':\s*any\b' apps/desktop/src packages --include="*.ts" --include="*.tsx"
|
||||
grep -rn 'console\.log' apps/desktop/src packages --include="*.ts" --include="*.tsx"
|
||||
grep -rnE '#[0-9a-fA-F]{3,8}\b' apps/desktop/src/renderer packages/ui/src --include="*.tsx" | grep -v theme
|
||||
grep -rnE '>[가-힣]+' apps/desktop/src/renderer --include="*.tsx" # 하드코딩 한국어 후보
|
||||
```
|
||||
|
||||
### Step 4. 우선순위 합의
|
||||
3 에이전트 결과를 다음 표로 정리해 사용자에게 제시:
|
||||
- 🟢 빠르고 안전 (각 5~10분)
|
||||
- 🟡 중간 작업 (각 30분~1시간)
|
||||
- 🔴 대규모 (반나절~하루, 위험도 있음)
|
||||
- ⚠️ 사용자 판단 필요 (의도 확인)
|
||||
|
||||
번들로 묶어서 "번들 N: ... 시간 예상" 식으로 추천.
|
||||
|
||||
### Step 5. 워크스트림 분리 + 의존성 그래프
|
||||
- 파일 충돌 없도록 영역 분할 (R3)
|
||||
- 의존성 그래프 작성 (예: WS1 → WS3)
|
||||
- 1차/2차/3차 wave로 시간순 분류
|
||||
|
||||
### Step 6. 멀티 에이전트 병렬 발사
|
||||
- 1차 wave: 의존성 없는 워크스트림 모두 병렬 (보통 3~4개)
|
||||
- 각 에이전트 프롬프트에 R4(작업 위치), R6(커밋 금지), R7(검증) 박기
|
||||
- **P8: 에이전트에게 "본인 영역 typecheck를 직접 실행해 EXIT 0 확인; 안 되면 원인 보고"를 hard requirement로 명시** (회피 방지)
|
||||
- 결과 받으면 영역별 변경 파일 매핑 → 충돌 여부 확인. **에이전트가 typecheck를 안 돌렸으면 통합 단계에서 반드시 재검증**
|
||||
|
||||
### Step 7. 통합 + 분리 커밋
|
||||
- `git reset HEAD`로 staging 청소 (R5)
|
||||
- 워크스트림당 1 커밋
|
||||
- 커밋 메시지 형식: `type(scope): 한 줄 요약 (WS{N})` + 본문에 변경 카테고리 + SKIP 사유 + 정책 참조
|
||||
- Co-Authored-By, Claude 관련 문구 절대 금지
|
||||
- 사용자 별도 작업(다른 도구가 만든 파일)은 별도 커밋 또는 보존
|
||||
|
||||
### Step 8. 보고서 + 다음 wave 계획
|
||||
- `docs/REFACTOR_WAVE{N}_REPORT.md` 작성 (R8)
|
||||
- 본 SKILL.md 갱신 (배운 패턴 추가)
|
||||
- `memory/project_status.md` 갱신
|
||||
- 사용자에게 다음 wave 진행 여부 결정 요청
|
||||
|
||||
## 안티패턴 (Don't)
|
||||
|
||||
### A1. 정책 없이 패치 시작
|
||||
"일단 보이는 것부터 고치자" → 1주 후 동일 영역 다시 건드림. **R1 위반**.
|
||||
|
||||
### A2. 단일 에이전트로 큰 감사
|
||||
보수적 에이전트는 5건만 보고. 공격적 모드 + 3 에이전트 병렬이 표준.
|
||||
|
||||
### A3. 같은 파일 두 워크스트림 동시 수정
|
||||
git 충돌 + 의도 분리 불가. **R3 위반**.
|
||||
|
||||
### A4. 에이전트가 직접 커밋
|
||||
커밋 메시지 일관성 깨짐 + 통합 검토 생략 → 회귀 위험. **R6 위반**.
|
||||
|
||||
### A5. `git add -A` 또는 `git add .`로 분리 커밋 시도
|
||||
이전 staging이 묻어들어가서 의도와 다른 파일들이 한 커밋에 합쳐짐. 정밀 add 필수. **R5 위반**.
|
||||
|
||||
### A6. SKIP 사유 모호하게 적기
|
||||
"복잡해서 SKIP"은 1달 후 재시도 시 같은 함정. SKIP은 "기술적 제약 + 별도 Phase 필요" 명확히.
|
||||
|
||||
### A7. 보고서 없이 끝내기
|
||||
다음 wave 시작할 때 1차 산출물 추적 불가. **R8 위반**.
|
||||
|
||||
## 검증 체크리스트 (각 wave 완료 시)
|
||||
|
||||
- [ ] 정책 문서 갱신 완료 (`docs/REFACTOR_POLICY.md`)
|
||||
- [ ] 워크스트림별 분리 커밋 (각 1 커밋)
|
||||
- [ ] `typecheck` + `lint` + `test` 모두 GREEN
|
||||
- [ ] UI 변경 시 `npm run dev` 실행 확인 완료 (또는 미해당 명시)
|
||||
- [ ] SKIP 항목 사유 + 후속 Phase 명시
|
||||
- [ ] `docs/REFACTOR_WAVE{N}_REPORT.md` 작성
|
||||
- [ ] 본 SKILL.md 갱신 (배운 패턴 추가)
|
||||
- [ ] `memory/project_status.md` 업데이트
|
||||
- [ ] 누적 커밋 사용자에게 보고
|
||||
|
||||
## 검증된 범용 인사이트 (HaramLog wave 1~10에서 이식)
|
||||
|
||||
### P1. 감사 에이전트 HIGH 확신도 보고도 **착수 전 30초 재검증** 필수
|
||||
공격적 모드 에이전트는 false positive를 기꺼이 보고한다 (정책대로 R2 수행). 필터링 없이 바로 구현에 들어가면 "이미 되어있는 걸 또 하거나", "잘못된 전제로 리팩토링"할 위험.
|
||||
1. HIGH 보고 각 발견 → 착수 전 파일 Read/Grep 1회 (30초)
|
||||
2. 실제 상태와 다르면 → KEEP+사유로 분류 전환
|
||||
3. 보고서 별 섹션에 false positive 기록 → 다음 wave 학습 데이터
|
||||
|
||||
### P2. "순수 이동" 분할에도 동작 변경이 숨는다
|
||||
거대 파일(god component/service)을 쪼갤 때 import가 빠지면 에이전트가 **동작을 바꿔서 컴파일을 통과**시키는 경우가 있다 (원 사례: modifier 체인을 no-op으로 대체해 import 누락 회피 → UI 회귀). 통합 후 반드시:
|
||||
- "순수 이동"일수록 diff가 1:1이어야 함 — `git show HEAD:<원본>`과 분할 결과의 핵심 로직(훅 체인, useEffect deps, 이벤트 구독/해제) 대조
|
||||
- 단순화된 흔적(제거된 wrapper, 사라진 cleanup)은 곧 회귀 의심
|
||||
|
||||
### P3. 거대 파일 분할은 "순수 이동"이 90%
|
||||
거대 컴포넌트/서비스는 이미 작은 함수들의 모음이라 **클러스터별 파일 분리만으로 해소**된다. 진짜 재설계(상태 끌어올리기, 서비스 분리)는 분리 후에도 남는 명백한 압력(props 20+개)이 있을 때만. 사용자가 "재설계 포함"을 골라도 먼저 순수 이동을 시도하고, 재설계는 분리 결과를 보고 판단.
|
||||
|
||||
### P4. 화면 1개에 고유한 수치는 토큰화하지 말고 file-private 상수로 격리
|
||||
`WAVE_BAR_COUNT = 9`처럼 의미가 화면 1개에 고유한 값은 d3ro 토큰 부적합. 명명상수 + 위치 응집(파일 상단)으로 충분. 토큰 변환 강제하지 말 것.
|
||||
|
||||
### P5. 비컴포넌트 함수의 한국어 반환은 i18n 키 반환으로 전환
|
||||
서비스/유틸 함수가 한국어 리터럴을 반환하면 다국어 불가. 함수는 i18n **키**(또는 enum)를 반환하고, 렌더링 시점에 t()로 풀이. 메인 프로세스 문자열(팝업/트레이 메뉴)도 동일 패턴.
|
||||
|
||||
### P6. 이름 충돌은 역할 접미어로 예방
|
||||
패키지가 달라도 이름이 같으면 import alias 강제 + 독자 혼란. 도메인 타입과 UI 토큰이 겹치면 UI 쪽에 역할 접미어 (예: `RecordingState` enum vs `RecordingStateColor` 토큰 맵).
|
||||
|
||||
### P7. 공유 패키지 토큰 변경은 전체 소비 앱에 영향 — "부분 치환 + 별칭 제거" 불가
|
||||
`packages/ui`의 토큰(deprecated 별칭 등)을 제거하려면, 그 토큰을 import하는 **모든 앱**(desktop/web/admin/site/mobile/ui-native)을 먼저 치환해야 함. 한 앱만 치환하고 공유 패키지에서 별칭을 지우면 다른 앱이 타입에러+런타임 undefined로 깨짐. (Wave 1 사례: `accent.amber` — desktop 치환 후에도 web/admin/site 사용으로 별칭 유지, 전체 치환 별도 wave로 이월.) **DP6(전체 typecheck 강제)이 이걸 방어.**
|
||||
|
||||
### P8. 감사/구현 에이전트는 typecheck를 회피한다 — 프롬프트에 "EXIT 0 직접 확인"을 hard requirement로
|
||||
에이전트가 "메인 작업자가 통합 후 수행 권장" / "환경 이슈로 로컬 실행 필요" 핑계로 typecheck를 안 돌리고 보고하는 경우가 잦음. **에이전트 프롬프트에 "typecheck는 본인이 직접 실행해 EXIT 0를 확인; 안 되면 원인을 명확히 보고(무한 재시도 금지)"를 명시**. 통합 단계에서도 반드시 재검증.
|
||||
|
||||
### P9. lint 게이트의 pre-existing 부채 — "내 영역 errors 0"으로 재해석
|
||||
codebase가 원래 lint GREEN이 아닌 경우가 많음(루트 `eslint .`가 다른 앱의 config 문제로 붕괴, pre-existing errors 다수). "통합 후 lint GREEN"(R7 원문)이 비현실적. 게이트는 **"내가 건드린 영역의 lint errors 0"** + "pre-existing은 별도 wave로 분리"로 재해석. (검증 팁: `git diff --name-only HEAD`로 변경 파일만 lint → 내 책임 분리.)
|
||||
|
||||
## 누적 wave 인덱스
|
||||
|
||||
| Wave | 일시 | 산출 커밋 | 보고서 |
|
||||
|------|------|-----------|--------|
|
||||
| Wave 1 | 2026-07-22 | b820c78(WS1)·aef4428(WS2)·078304d(WS3)·87f2dac(WS4) | `docs/REFACTOR_WAVE1_REPORT.md` |
|
||||
| Wave 2 | 2026-07-22 | efac690(AMBER)·660e622(NATIVE)·00a99e4(POPUP)·4c25620(DEPS)·5b6e7aa(PATTERN) | `docs/REFACTOR_WAVE2_REPORT.md` |
|
||||
|
||||
다음 wave 추가 시 본 표 갱신.
|
||||
Loading…
Add table
Add a link
Reference in a new issue