From 80959abe16684888bd3430df66386b560e05ce1f Mon Sep 17 00:00:00 2001 From: klaus Date: Tue, 24 Feb 2026 15:49:16 +0900 Subject: [PATCH] =?UTF-8?q?fix(commit):=20AGENTS=20=EA=B7=9C=EC=B9=99?= =?UTF-8?q?=EA=B3=BC=20=EC=BB=A4=EB=B0=8B=20=EB=A9=94=EC=8B=9C=EC=A7=80=20?= =?UTF-8?q?=EA=B2=80=EC=82=AC=20=EC=8A=A4=ED=81=AC=EB=A6=BD=ED=8A=B8?= =?UTF-8?q?=EB=A5=BC=20=EC=A0=95=ED=95=A9=ED=99=94=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/junie.xml | 6 + .opencode/commands/commit.md | 21 +++ .opencode/skills/commit-policy/SKILL.md | 46 ++++++ AGENTS.md | 180 +++++++++++++++++++++--- docs/20260224_AGENTS문서정비.md | 54 +++++++ 5 files changed, 291 insertions(+), 16 deletions(-) create mode 100644 .idea/junie.xml create mode 100644 .opencode/commands/commit.md create mode 100644 .opencode/skills/commit-policy/SKILL.md create mode 100644 docs/20260224_AGENTS문서정비.md diff --git a/.idea/junie.xml b/.idea/junie.xml new file mode 100644 index 00000000..4dcc0836 --- /dev/null +++ b/.idea/junie.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.opencode/commands/commit.md b/.opencode/commands/commit.md new file mode 100644 index 00000000..0528089b --- /dev/null +++ b/.opencode/commands/commit.md @@ -0,0 +1,21 @@ +--- +description: commit-policy 스킬을 로드해 커밋 메시지 생성과 전후 검증을 수행한다 +agent: build +subtask: true +--- + +작업 목표: +현재 변경사항을 안전하게 커밋한다. + +필수 시작 단계: +1. `skill` 도구로 `commit-policy` 스킬을 먼저 로드한다. + - `skill({ name: "commit-policy" })` + +실행 단계: +1. 로드한 `commit-policy` 스킬의 Hard Requirements와 Execution Flow를 그대로 수행한다. +2. `AGENTS.md`의 최소 정책(형식/한글 description/검증 스크립트)을 항상 만족한다. +3. `$ARGUMENTS`가 있으면 scope 또는 description 의도에 반영하되, 스킬 규칙과 형식을 깨지 않는다. +4. 마지막에 실행 명령과 pre-check/post-check PASS/FAIL 핵심 결과를 간단히 보고한다. + +추가 사용자 의도: +$ARGUMENTS diff --git a/.opencode/skills/commit-policy/SKILL.md b/.opencode/skills/commit-policy/SKILL.md new file mode 100644 index 00000000..b13180e7 --- /dev/null +++ b/.opencode/skills/commit-policy/SKILL.md @@ -0,0 +1,46 @@ +--- +name: commit-policy +description: Apply this skill for any git commit task in this repository. It enforces commit message format and validation flow defined in AGENTS.md and work/scripts/check-commit-message-rules.sh, including pre-commit and post-commit verification. +--- + +# Commit Policy Skill + +Use this workflow whenever the task includes creating a commit. + +## Required References + +- `@AGENTS.md` +- `@work/scripts/check-commit-message-rules.sh` + +## Hard Requirements + +1. Use commit subject format: `(scope): `. +2. `type` must be lowercase (for example `feat`, `fix`, `chore`, `docs`, `refactor`, `test`). +3. `description` must include Korean text and stay concise in imperative present tone. +4. Optional footer must use `Refs: #123` or `Refs: #123, #456` format. +5. Never commit secret files (`.env`, key/token/secret credential files). +6. Never bypass hooks with `--no-verify`. + +## Execution Flow + +1. Inspect context with: + - `git status` + - `git diff --cached` + - `git diff` + - `git log -5 --oneline` +2. Stage commit target files only. Exclude suspicious secret-bearing files. +3. Draft commit message from the change intent (focus on why, not only what). +4. Run pre-commit validation with the full draft message: + - `./work/scripts/check-commit-message-rules.sh --message ""` +5. If validation fails, revise message and re-run until PASS. +6. Commit using the validated message. +7. Run post-commit validation: + - `./work/scripts/check-commit-message-rules.sh` +8. Report executed commands and PASS/FAIL summary. + +## Output Checklist + +- Final commit subject. +- Whether pre-check passed. +- Whether post-check passed. +- Any excluded files and reason. diff --git a/AGENTS.md b/AGENTS.md index 8cf6285b..4ee7c3d3 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,18 +1,166 @@ -질문에 대한 답변과 설명은 한국어로 한다. +# AGENTS.md +`SodaLive` 저장소에서 작업하는 에이전트 실행 가이드다. -## Quality Assurance Guidelines +## 커뮤니케이션 규칙 +- **"질문에 대한 답변과 설명은 한국어로 한다."** +- 이 저장소에서 사용자에게 전달하는 설명, 진행 상황, 결과 보고는 한국어로 작성한다. +- 코드 식별자, 경로, 명령어는 원문(영문) 그대로 유지한다. -### Commit Standards -1. Write in Korean. -2. Use the present tense in the subject line (e.g., "Add feature" not "Added feature"). -3. Keep the subject line to 50 characters or less. -4. Add a blank line between the subject and body. -5. Keep the body to 72 characters or less per line. -6. Within a paragraph, only break lines when the text exceeds 72 characters. -7. Describe changes to public API features and do not include implementation details such as package-private code. -8. Do not mention test code in commit messages. -9. Do not use any prefix (such as "fix:", "update:", "docs:", "feat:", etc.) in the subject line. -10. Do not start the subject line with a lowercase letter unless the first word is a function name or another identifier that is conventionally lowercase and there is a clear, justifiable reason for the exception. Otherwise, always start with an uppercase letter. -11. Do not include tool advertisements, branding, or promotional content in commit messages. -12. Use separate git commands to stage files before committing. -13. Always validate commits using `work/scripts/check-commit-message-rules.sh` and fix until validation passes. +## 저장소 범위 +- Android Gradle 프로젝트이며 `settings.gradle` 기준 모듈은 `:app` 단일 구성이다. +- 모든 명령은 저장소 루트에서 실행한다. +- 추측하지 말고 근거 파일(`settings.gradle`, `build.gradle`, `app/build.gradle`, 소스 코드)을 읽고 결정한다. +- 요청 범위를 우선 충족하고, 변경은 작고 안전하게 유지한다. + +## 빌드 / 린트 / 테스트 명령 +기본 실행 형태: +```bash +./gradlew +``` +빌드: +```bash +./gradlew clean +./gradlew :app:assembleDebug +./gradlew :app:assembleRelease +./gradlew :app:build +./gradlew :app:check +``` +린트/포맷: +```bash +./gradlew :app:lint +./gradlew :app:lintDebug +./gradlew :app:lintRelease +./gradlew :app:ktlintCheck +./gradlew :app:ktlintFormat +``` +테스트: +```bash +./gradlew :app:test +./gradlew :app:testDebugUnitTest +./gradlew :app:testReleaseUnitTest +./gradlew :app:connectedDebugAndroidTest +``` +주의: +- `:app:connectedDebugAndroidTest`는 기기/에뮬레이터 연결이 필요하다. +- `app/build.gradle`에 `lint { checkReleaseBuilds false }`가 있어 릴리스 린트는 `:app:lintRelease`를 명시 실행해야 한다. +- 현재 `app/src/androidTest`에는 테스트 소스가 없으므로 계측 테스트 명령은 신규 테스트 추가 시 사용한다. + +### 1) 단일 테스트 실행 (중요) +로컬 단위 테스트(`app/src/test`)는 `--tests` 필터를 사용한다. +클래스 단위: +```bash +./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.chat.talk.room.ChatRepositoryTest" +``` +메서드 단위: +```bash +./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.chat.talk.room.ChatRepositoryTest.enterChatRoom inserts messages and returns response" +``` +패턴 매칭 예시: +```bash +./gradlew :app:testDebugUnitTest --tests "*TimeUtilsTest*" +``` +참고: +- Kotlin backtick 테스트명은 공백이 포함될 수 있으므로 전체 문자열을 인용한다. +- 메서드 매칭이 불안정하면 클래스 단위로 먼저 실행한다. + +### 2) 계측 테스트 클래스/메서드 타깃 실행 +Gradle 인자 방식: +```bash +./gradlew :app:connectedDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=kr.co.vividnext.sodalive.SomeInstrumentedTest +./gradlew :app:connectedDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=kr.co.vividnext.sodalive.SomeInstrumentedTest#someMethod +``` +ADB 대안: +```bash +adb shell am instrument -w -e class kr.co.vividnext.sodalive.SomeInstrumentedTest#someMethod / +``` + +## 코드 스타일 가이드 +### 1) 포맷/기본 규칙 +- `.editorconfig` 기준을 준수한다. +- 인덴트: 공백 4칸, 줄바꿈: LF, 최대 라인 길이: 130. +- 파일 끝 개행 유지, trailing whitespace 제거. +- Kotlin/KTS에서 `import-ordering` ktlint 규칙은 비활성화되어 있으므로 기존 파일 정렬 스타일을 우선 따른다. + +### 2) import 규칙 +- 신규 코드에서는 와일드카드 import(`*`)를 기본적으로 지양한다. +- 사용하지 않는 import를 남기지 않는다. +- import alias(`as`)는 필요한 경우(이름 충돌 회피) 최소 범위로만 사용한다. +- 기존 파일에 와일드카드/alias가 있으면 대규모 정렬 리팩터링 없이 주변 스타일에 맞춘다. + +### 3) 네이밍/레이어 +- UI: `*Activity`, `*Fragment`, dialog/sheet suffix +- 상태/도메인: `*ViewModel` (주로 `BaseViewModel` 상속) +- 데이터 계층: `*Repository`, Retrofit `*Api` +- DTO: `data class` + `*Request`, `*Response` suffix +- 레이어 흐름: `Api` -> `Repository` -> `ViewModel` -> `Activity`/`Fragment` +- DI는 `app/src/main/java/kr/co/vividnext/sodalive/di/AppDI.kt`의 Koin 구성을 따른다. + +### 4) 타입/계약/에러 처리 +- nullability와 제네릭 타입을 의미가 바뀌지 않게 유지한다. +- 공개 API/스키마/리소스 계약은 요청 없이 변경하지 않는다. +- 응답 처리 시 기존 `ApiResponse`와 Rx 타입(`Single`, `Flowable`)을 우선 재사용한다. +- 빈 `catch` 블록을 새로 추가하지 않는다. +- 예외를 조용히 삼키지 않고 로그/주석/대체 흐름 중 하나를 남긴다. + +### 5) 테스트 관례 +- 단위 테스트는 `app/src/test`에 위치하며 클래스명은 `*Test`를 사용한다. +- 기본 스택은 JUnit4 + MockK/Mockito다. +- 테스트 추가 시 단일 실행 명령 예시도 본 문서에 갱신한다. + +## 커밋 메시지 규칙 (표준 Conventional Commits) +- 커밋 상세 가이드/절차는 `.opencode/skills/commit-policy/SKILL.md`를 단일 기준으로 사용한다. +- 커밋 작업 시작 시 `skill` 도구로 `commit-policy`를 먼저 로드한다. +- 기본 형식은 `(scope): `를 사용한다. +- `type`은 소문자(`feat`, `fix`, `chore`, `docs`, `refactor`, `test` 등)를 사용한다. +- 제목(description)은 한글로 작성하고, 명령형/간결한 현재형으로 작성한다. +- 이슈 참조 footer는 `Refs: #123` 또는 `Refs: #123, #456` 형식을 사용한다. + +### 커밋 메시지 검증 절차 +- `git commit` 직전/직후 `work/scripts/check-commit-message-rules.sh`를 실행해 규칙 준수 여부를 확인한다. +- 스크립트 결과가 `[FAIL]`이면 메시지를 수정한 뒤 다시 검증한다. + +## 작업 절차 체크리스트 +- 변경 전: 유사 기능 코드를 먼저 찾아 네이밍/예외/응답 패턴을 맞춘다. +- 변경 중: 공개 API 스키마를 임의 변경하지 말고 작은 단위로 안전하게 수정한다. +- 변경 후: 최소 단일 테스트(`--tests`) 또는 `./gradlew :app:test`를 실행하고 필요 시 `./gradlew :app:ktlintCheck`를 수행한다. +- 커밋 전/후: `commit-policy` 스킬을 먼저 로드하고, `git commit` 직전과 직후에 `work/scripts/check-commit-message-rules.sh`를 실행해 커밋 메시지 규칙 준수 여부를 확인한다. + +## 작업 계획 문서 규칙 (docs) +- 모든 작업 시작 전에 `docs` 폴더 아래 계획 문서를 먼저 생성하고, 해당 문서를 기준으로 구현한다. +- 계획 문서 파일명은 `[날짜]_구현할내용한글.md` 형식을 사용한다. +- 날짜는 `YYYYMMDD` 8자리 숫자를 사용한다. +- 구현 항목은 기능/작업 단위 체크박스(`- [ ]`)로 작성하고 완료 즉시 `- [x]`로 갱신한다. +- 작업 도중 범위가 변경되면 계획 문서 체크리스트를 먼저 업데이트한 뒤 구현한다. +- 결과 보고 시 문서 하단에 검증 기록(무엇/왜/어떻게, 실행 명령, 결과)을 한국어로 남긴다. +- 후속 수정이 발생해도 기존 검증 기록은 삭제/덮어쓰기 없이 누적한다. + +## Cursor/Copilot 규칙 반영 현황 +- 확인 경로: `.cursor/rules/**`, `.cursorrules`, `.github/copilot-instructions.md` +- 현재 저장소에는 위 파일이 존재하지 않는다. +- 추후 규칙 파일이 추가되면 본 문서에 즉시 반영한다. + +## 문서 유지보수 규칙 +- `build.gradle`/`app/build.gradle`/`settings.gradle` 변경 시 실행 명령 섹션을 함께 갱신한다. +- 테스트 클래스 추가/이동 시 단일 테스트 실행 예시를 최신 상태로 유지한다. +- `.editorconfig` 변경 시 포맷 규칙 섹션을 동기화한다. +- 문서 변경 후 최소 한 번 `./gradlew tasks --all`로 명령 유효성을 확인한다. +- 불확실한 규칙은 추측으로 채우지 말고 근거 파일 경로를 먼저 확인한다. +- 에이전트 안내 문구는 한국어 중심으로 유지한다. + +## 에이전트 동작 원칙 +- 추측하지 말고 근거 파일을 읽고 결정한다. +- 기존 관례를 깨는 변경은 이유가 명확할 때만 수행한다. +- 불필요한 리팩터링 확장은 피하고 요청 범위를 우선 충족한다. +- 결과 보고 시 무엇을, 왜, 어떻게 검증했는지 한국어로 간단히 남긴다. + +## 설정/보안 유의사항 +- `local.properties`, 키스토어(`*.jks`, `*.keystore`, `*.p12`, `*.pem`, `*.key`)는 생성/수정 여부와 관계없이 커밋하지 않는다. +- `app/src/debug/google-services.json`, `app/src/release/google-services.json`은 민감 구성으로 취급하고 외부 공유/로그 출력 금지한다. +- `app/build.gradle`의 `buildConfigField` 값(토큰/앱키/시크릿 유사 값)은 신규 하드코딩을 추가하지 않는다. +- `BuildConfig` 값(키/토큰/URL)을 로그, Toast, 크래시 메시지에 직접 노출하지 않는다. +- 네트워크 로깅은 `AppDI.kt` 패턴을 유지한다(디버그만 BODY, 릴리스는 NONE). +- 서명/배포 설정(Crashlytics, Google Services, Proguard, signing)은 요청 없이 변경하지 않는다. +- `AndroidManifest.xml` 권한은 민감 영역이므로 신규 추가/확장은 사유와 영향도를 확인한 뒤 반영한다. +- `applicationId`, `namespace`, OAuth Client ID, 딥링크 호스트는 요청 없이 변경하지 않는다. +- 문서/이슈/PR 본문에 비밀값을 남기지 말고 필요 시 마스킹(`***`) 처리한다. +- Git 작업은 비파괴 명령을 기본으로 사용하고, 강제 푸시/히스토리 재작성은 명시 요청이 있을 때만 수행한다. diff --git a/docs/20260224_AGENTS문서정비.md b/docs/20260224_AGENTS문서정비.md new file mode 100644 index 00000000..efcf50aa --- /dev/null +++ b/docs/20260224_AGENTS문서정비.md @@ -0,0 +1,54 @@ +# AGENTS 문서 정비 계획 + +## 구현 체크리스트 +- [x] 저장소의 빌드/린트/테스트 실행 명령 근거 파일 수집 +- [x] 단일 테스트 실행 명령(클래스/메서드 단위) 근거 확인 +- [x] 코드 스타일 규칙(포맷/타입/네이밍/에러 처리/import) 근거 수집 +- [x] 기존 `AGENTS.md` 존재 여부 확인 및 개선/신규 작성 방향 결정 +- [x] Cursor/Copilot 규칙 파일 존재 여부 확인 및 반영 +- [x] `AGENTS.md` 약 150줄로 작성/갱신 +- [x] `설정/보안 유의사항` 섹션을 현재 프로젝트 민감 항목 기준으로 채우기 +- [x] `AGENTS.md` 내용이 현재 프로젝트 설정(`settings.gradle`, `app/build.gradle`, `.editorconfig`)과 일치하는지 재검증 +- [x] 사용자 추가 요청 반영: `AGENTS.md` 전면 한글화 및 향후 문서 한글 작성 규칙 명시 +- [x] 최소 1회 빌드 시스템 명령 유효성 확인 + +## 작업 메모 +- 본 문서는 요청된 문서 유지보수 규칙에 따라 작업 시작 시점에 생성한다. +- 구현 중 범위 변경이 발생하면 체크리스트를 먼저 갱신한다. + +## 검증 기록 +- 검증 #1 + - 무엇: 문서 파일 문법/형식 진단 + - 왜: 문서 수정 후 오류 여부를 즉시 확인하기 위해 + - 어떻게: `lsp_diagnostics`로 `AGENTS.md`, `docs/20260224_AGENTS문서정비.md` 검사 + - 결과: 오류 없음 +- 검증 #2 + - 무엇: 빌드 시스템 명령 유효성 + - 왜: 문서 규칙(문서 변경 후 최소 1회 빌드 시스템 명령 실행) 충족을 위해 + - 어떻게: `./gradlew :app:help` 실행 + - 결과: `BUILD SUCCESSFUL` +- 검증 #3 + - 무엇: 단일 테스트 실행 명령 유효성 + - 왜: AGENTS.md의 단일 테스트 실행 가이드가 실제로 동작하는지 확인하기 위해 + - 어떻게: `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.chat.talk.room.TimeUtilsTest"` 실행 + - 결과: `BUILD SUCCESSFUL` (테스트 태스크 up-to-date) +- 검증 #4 + - 무엇: AGENTS.md 내용의 현재 프로젝트 적합성 점검 + - 왜: 요청사항(현재 프로젝트에 맞는지 확인)을 충족하기 위해 + - 어떻게: `settings.gradle`, `build.gradle`, `app/build.gradle`, `.editorconfig`, `app/src/main/AndroidManifest.xml`을 재확인하고 명령/규칙 문구를 대조 + - 결과: `:app` 단일 모듈, `lint.checkReleaseBuilds false`, import-ordering 비활성화, 권한/보안 주의 항목 반영 완료 +- 검증 #5 + - 무엇: 문서 변경 후 Gradle 명령 유효성 재확인 + - 왜: 문서 유지보수 규칙(문서 변경 후 `./gradlew tasks --all`)을 충족하기 위해 + - 어떻게: `./gradlew tasks --all` 실행 + - 결과: `BUILD SUCCESSFUL` +- 검증 #6 + - 무엇: 단일 테스트 가이드 재검증 + - 왜: AGENTS.md 단일 테스트 예시의 최신 유효성을 다시 확인하기 위해 + - 어떻게: `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.chat.talk.room.TimeUtilsTest"` 실행 + - 결과: `BUILD SUCCESSFUL` (`:app:testDebugUnitTest UP-TO-DATE`) +- 검증 #7 + - 무엇: 최종 문서 진단 + - 왜: 수정 완료 직후 문서 상태를 확인하기 위해 + - 어떻게: `lsp_diagnostics`로 `AGENTS.md`, `docs/20260224_AGENTS문서정비.md` 검사 + - 결과: 오류 없음