# 공통 클린코드 규칙 모든 파일에 적용한다. 언어별 규칙은 `rust.md`, `frontend.md`, `tauri-ipc.md`, `docs.md`가 보충한다. ## 범위와 변경 크기 - 요청한 범위만 바꾼다. 지나가는 코드의 스타일 정리·리네임·재배치를 섞지 않는다. - 새 기능보다 기존 함수 재사용을 먼저 찾는다. `package-infra`에 이미 있는 `hash_file`, `atomic_json`, `reject_links`, `lock_project`, `appended_path` 같은 헬퍼를 다시 만들지 않는다. - 한 함수는 한 가지 일을 한다. 분기가 3단계를 넘으면 이름 있는 함수로 뺀다. - 파일 하나가 500줄을 넘기 시작하면 모듈 분리를 제안한다(현재 `main.ts`, `store.rs`가 경계선). ## 이름 - 코드 식별자는 영어. 사용자에게 보이는 문자열(오류 메시지, UI 텍스트, 문서)은 한국어. - 불리언은 상태를 그대로 읽히게 짓는다: `dirty`, `busy`, `available`, `trusted_people`. `is_`/`has_` 접두사는 Rust 메서드에서만. - 약어를 새로 만들지 않는다. `doc`(ProjectDocument), `esc`(HTML escape)처럼 이미 쓰는 것만 유지한다. - JSON 필드는 camelCase, Rust 필드는 snake_case, 변환은 serde `rename_all`에 맡기고 수동 매핑을 하지 않는다. ## 오류 처리 - 오류 메시지 형식: `ErrorCode: 한국어 설명과 조치`. 코드는 PascalCase 한 단어(`RevisionConflict`, `MissingTool`, `InputChanged`). 기존 코드가 있으면 재사용하고, 새 코드는 README 또는 변경 기록에 적는다. - 오류를 삼키지 않는다. 실패를 기본값으로 대체하는 fallback(미서명으로 자동 전환, 빈 설정으로 조용히 진행 등)을 만들지 않는다. 예외는 명시된 두 곳만: 최근 목록 저장 실패는 경고로 표시하고 프로젝트 열기를 막지 않는다, 이전 v2 프로젝트의 누락 `registry`/`signing` 필드는 기본값으로 연다. - 조치 방법을 담는다. 사용자가 무엇을 고쳐야 하는지 한 문장으로. ## 결정성 - 파일 목록·맵은 정렬된 자료구조(`BTreeMap`, `BTreeSet`, 정렬된 `Vec`)로 다룬다. 같은 입력은 같은 출력을 내야 한다. - 시각은 UNIX 초(u64)로 저장한다. 표시 형식 변환은 UI에서만. - 바이트 수처럼 JS `number` 정밀도를 넘을 수 있는 값은 IPC 경계에서 10진 문자열로 보낸다. ## 주석과 문서화 - 주석은 "왜"만 쓴다. 코드가 말하는 "무엇"을 반복하지 않는다. 주석은 영어 한 문장. - 공개 함수에 문서 주석을 달 때는 계약(입력 제약, 실패 조건, 부작용 없음)을 쓴다. - TODO를 남기지 않는다. 미구현은 명시 오류로 거부하고 README의 "다음 작업"이나 백로그에 적는다. ## 테스트 - 동작을 바꾸면 테스트를 함께 바꾼다. 실패 경로(거부, 충돌, 취소, 변조 탐지)를 성공 경로와 같은 비중으로 검사한다. - 테스트 이름은 검증하는 규칙을 문장으로 쓴다: `json_and_duplicate_extensions_are_rejected_even_with_valid_contents`. - 실제 SDK·네트워크·레지스트리·인증서 저장소를 건드리는 테스트는 `#[ignore]` 또는 환경 변수 게이트 뒤에 둔다. - 테스트가 실패하면 그대로 보고한다. 테스트를 약화시켜 통과시키지 않는다. ## 줄 끝과 인코딩 - UTF-8. `.gitattributes`에 따라 `*.md`, `*.json`, `*.html`은 LF. Rust/TS는 `text=auto`를 따른다. - 파일 끝에 개행 하나. BOM 없음(현재 `style.css`의 BOM은 기존 상태이며 건드리지 않는다).