chore: add Claude Code guidelines, rules and skills

- CLAUDE.md: product principles, crate layering, common commands, commits.
- .claude/rules: common, Rust, frontend, Tauri IPC, docs and security rules.
- .claude/skills: check, add-tauri-command, project-model-change,
  change-record, msix-integration-test, backlog-status.

Refs #16

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
jychoi4andClaude Opus 5.5 committed 2026-11-11 11:09:05 +09:00
1 parent 7f5540f148
commit 905e6d4eaa
13 files changed
+654

No files matched your search

+48
View File
@@ -0,0 +1,48 @@
---
paths:
- "src/apps/desktop/src/**"
- "src/apps/desktop/tests/**"
- "src/apps/desktop/index.html"
- "src/apps/desktop/package.json"
- "src/apps/desktop/tsconfig.json"
---
# 프런트엔드(TypeScript · CSS) 규칙
프레임워크 없는 TypeScript. 화면은 문자열 템플릿으로 만들고 `root.innerHTML`에 넣은 뒤 `data-action`/`data-field` 속성으로 이벤트를 연결한다. `tsc --noEmit` strict와 `node --test`를 통과해야 한다.
## 모듈 구조
- `main.ts`는 상태와 조정(invoke 호출, render, action 분기)만 둔다. 화면 조각과 순수 로직은 별도 모듈로 뺀다: `start-screen.ts`, `registry-editor.ts`, `signing-editor.ts`, `project-transition.ts`, `window-chrome.ts`.
- 새 탭·편집기는 `render<Name>(data, disabled): string`을 export하는 모듈로 만들고, `main.ts`에서는 import와 action 분기만 추가한다.
- 테스트는 `tests/<module>.test.mjs`에서 `.ts`를 직접 import한다. Node의 `--experimental-strip-types`로 실행되므로 **`enum`, `namespace`, 매개변수 프로퍼티, 데코레이터를 쓰지 않는다**. 타입은 `type` 별칭과 `import type`으로.
- 순수 함수(그룹화, 경로 표시, 전환 판단)는 DOM 없이 호출 가능해야 테스트할 수 있다. `document`를 쓰는 코드와 분리한다.
## 보안 · 렌더링
- 템플릿에 들어가는 모든 동적 값은 `esc()`/`escape()`를 거친다. 프로젝트 이름, 경로, 오류 메시지, ID도 예외 없다. 테스트는 `<img src=x onerror=...>` 같은 값이 이스케이프되는지 확인한다.
- `tauri.conf.json`의 CSP는 `'self'`만 허용한다. 인라인 `<script>`, 인라인 `style=`, 외부 폰트·CDN을 추가하지 않는다.
- `innerHTML`을 쓰는 곳은 render 함수 안에서만. 이벤트 핸들러는 `addEventListener`로 붙이고 `onclick=` 속성을 쓰지 않는다.
- `any`를 새로 쓰지 않는다. 경로 기반 필드 갱신이 필요하면 `Record<string, unknown>`과 단계별 검사로.
## 상태와 IPC
- `invoke<T>('command', args)`의 `T`는 Rust 반환 DTO와 필드 단위로 일치하는 `type`이어야 한다. Rust 쪽 `#[serde(default)] Option<T>`는 TS에서 `field?: T | null`.
- `isTauri()`가 false인 미리보기 모드에서는 파일 작업을 시도하지 않고 안내 문구를 보여준다.
- 모든 action은 `busy` 플래그로 중복 실행을 막고, `cancel`만 `busy` 중에 허용한다.
- 저장 안 된 변경(`dirty`)이 있을 때 프로젝트를 바꾸는 모든 경로는 `allowProjectTransition`을 거친다. 저장 실패 시 전환하지 않는다.
- 변경 후에는 `invalidate()`로 `report`/`plan`을 무효화한다. 오래된 검증 결과를 화면에 남기지 않는다.
## 접근성 · 문구
- 버튼은 텍스트 또는 `aria-label`을 가진다. 아이콘 전용 버튼(`×`)에는 `aria-label`과 `title`.
- 상태 메시지 영역은 `role="status"` 또는 `aria-live="polite"`.
- 사용자 문구는 한국어, 조치 중심: "변경 사항을 저장한 뒤 다시 검사하세요." 기술 코드는 문장 뒤에 덧붙인다.
- "배포 가능", "설치 완료", "검증됨" 같은 단어는 실제 상태 필드(`deploymentReady`, `installationTest`)가 그렇게 말할 때만 쓴다.
## CSS
- 색상은 `theme.css`의 `var(--color-*)`만 사용한다. 새 색이 필요하면 토큰을 먼저 추가한다. hex 하드코딩 금지(`.primary`의 `#fff`는 기존 예외).
- 선택자는 클래스 기반. ID 선택자와 `!important` 금지.
- 반응형 분기는 기존 `1200px`, `1050px` 중단점을 재사용한다.
- `style.css`는 한 줄 압축 형식이 섞여 있다. 새 규칙은 파일 끝에 사람이 읽을 수 있는 형식으로 추가하고, 기존 압축 블록을 재포맷하지 않는다.