이 레포에서 일하는 모든 AI 에이전트(Claude Code, Codex, 그 외)의 단일 규칙 원본이다.
CLAUDE.md는 이 파일을 import만 한다. 규칙을 바꿀 때는 이 파일만 고친다. 역할별 지침은docs/agents/<role>.md에 있다.
- 사용자가 직접 입력한 대본을 소리 내어 읽으면, 앱이 온디바이스 음성 인식으로 목소리를 따라가며 어절을 하이라이트하고, 끝까지 읽으면 남은 횟수를 줄여주는 iOS·Android 앱.
- 이 프로젝트의 진짜 산출물은 앱이 아니라 **"AI로 앱을 출시하는 파이프라인"**이다. 기획 → 디자인 → 개발 → QA → 출시 → 운영 전 단계를 에이전트가 수행하고, Marco는 방향과 구조를 리뷰한다.
- 기술: Flutter / Dart 단일 코드베이스와 Cupertino 스타일 UI. iOS 26+는
SpeechAnalyzer+SpeechTranscriber, Android 13/API 33+는 on-deviceSpeechRecognizer를 Pigeon 네이티브 어댑터로 사용한다. 로컬 저장은 drift + SQLite이며 서버는 없다. - 개발 환경: Android Studio를 주 IDE로 사용하고, iOS 빌드·시뮬레이터·서명·배포에는 Xcode를 병행한다.
- 레포는 Public이다.
| # | 원칙 | 상태 |
|---|---|---|
| 1 | 규칙 단일 원본 — AGENTS.md가 원본. CLAUDE.md는 @AGENTS.md 한 줄만 둔다. |
확정 |
| 2 | 검증 루프 — 에이전트는 빌드 → 테스트 → 시뮬레이터 실행 → 스크린샷 확인까지 스스로 수행한다. "될 것 같다"가 아니라 실제 결과로 보고한다. | 확정 |
| 3 | 실패 시 규칙 — 에이전트가 문제를 못 풀어도 Marco는 코드를 고치지 않는다. 프롬프트·규칙·스펙을 고치고, 그 사례를 docs/log/에 기록한다. |
확정 |
| 4 | 리뷰 방식 — AI 1차 리뷰(Codex + CodeRabbit), Marco 2차 리뷰(구조·방향). Marco는 PR 코멘트만 남기고 수정은 에이전트가 한다. | 확정 |
| 5 | 교차 모델 리뷰 — 구현한 모델과 다른 모델이 리뷰한다 (Claude 구현 → Codex 리뷰, 또는 그 반대). | 확정 |
| 6 | 프로젝트 구조 — docs/architecture.md의 feature-first 구조와 View → ViewModel → Repository → Service 의존 방향을 따른다. 낭독 세션·매칭은 순수 Dart로, 저장·플랫폼 STT는 교체 가능한 경계 뒤에 둔다. 네이티브 브리지는 Pigeon을 사용한다. |
확정 — Issue #23 |
| 7 | 시크릿 — 서명 인증서, App Store Connect API 키는 레포 밖에 보관. 에이전트는 시크릿 파일을 읽거나 생성·커밋하지 않는다. 필요하면 user 라벨로 넘긴다. |
확정 |
이 프로젝트의 목표 중 하나는 Marco가 직접 수정한 코드 0줄이다. 에이전트는 Marco의 PR 코멘트를 받으면 코드를 고치고, 규칙이나 스펙이 잘못됐다면 그것을 고친다. Marco에게 "이 부분은 직접 고쳐주세요"라고 요청하지 않는다.
기도문·경전 등의 현행 한국어 번역문은 권리자가 전재·복제에 사전 승인을 요구한다. 따라서 이 앱과 레포는 다음을 지킨다.
- 앱은 텍스트를 제공하지 않는다. 모든 대본은 사용자가 자기 기기에 직접 입력한다.
- 이 레포에 제3자 텍스트를 커밋하지 않는다. 기도문·경전·가사·시 등을 테스트 픽스처, 샘플 데이터, Flutter 프리뷰·예제, 문서, 스크린샷 어디에도 넣지 않는다. 테스트와 프리뷰에는 직접 쓴 더미 문장만 쓴다.
- 서버 없음, 앱 내 공유 갤러리 없음. 사용자 텍스트는 기기 밖으로 나가지 않는다. (나중에 공유를 넣더라도 파일을 주고받는 방식까지만.)
- 특정 출처에서 텍스트를 긁어오는 기능을 만들지 않는다. 붙여넣기는 사용자가 직접 한다.
- OCR 등을 넣을 때는 범용 기능으로 표현한다 ("사진에서 텍스트 가져오기").
- 스토어 문구는 용도 안내 수준으로 한다 ("기도문, 독경, 발표 대본을 입력해 사용할 수 있습니다").
- 앱 이름·아이콘·UI 문구는 특정 종교·용도색 없이 중립으로 한다 ("기도" 대신 "낭독", "대본" 등).
- 기본 탑재 텍스트는 넣지 않는다. 앱은 텍스트를 제공하지 않으므로(1번) 권리자에게 수록 허락을 문의하지도 않는다. 다만 사용자가 직접 입력한 대본을 묶음으로 묶을 수 있도록 데이터 구조는 열어둔다.
- 커밋 히스토리까지 전부 공개된다. 한 번 커밋된 시크릿은 삭제 커밋으로 되돌릴 수 없다(키 폐기·재발급 필요).
- 커밋 전에 항상 시크릿·개인정보(이메일 외 연락처, 계정 정보, 결제 정보 등)가 포함되지 않았는지 확인한다.
.gitignore에 있는 패턴(*.p8,*.p12,*.mobileprovision,.env*, 시크릿 xcconfig 등)을 우회하지 않는다.- CI에 필요한 값은 GitHub Actions Secrets로만 주입하고, 로그에 출력하지 않는다.
- MVP에 포함: 대본 추가·목록·선택·삭제(제목·본문), 반복 횟수 선택(미선택 시 1회), 낭독 화면(현재 반복 횟수·어절 하이라이트·자동 스크롤), 한 어절 뒤로, 나가기, 온디바이스 한국어 STT, 로컬 저장.
- 낭독 진행은 음성 인식으로만 앞으로 이동한다. 버튼은 한 어절 뒤로 이동하거나 낭독을 종료하는 용도로만 제공한다.
- MVP 제외(v1.1 이후 후보): 숙지 모드, 묶음, 묶음 파일 내보내기/가져오기, OCR, 통계·연속 기록·알림, 대사 주고받기·가리기 게임류, 다국어.
- 제외 목록의 기능을 먼저 제안하거나 구현하지 않는다. 범위를 넓히고 싶으면 Marco에게 묻는다.
- 상세 기획은
docs/PRD.md(1단계에서 작성)를 따른다.
- Issue가 모든 작업 단위다. 비개발 작업(기획·디자인·스토어 제출)도 Issue로 만든다.
- Milestone:
0. 기반 세팅~6. 출시 후. - 라벨:
user,agent:planner/agent:designer/agent:developer/agent:qa/agent:marketer. - 자동 할당:
user라벨이 붙은 Issue는 Marco(Marcorable)에게 자동 할당한다. - Project 필드:
Status(Backlog / Ready / In Progress / In Review / Done),Phase(0~6),Model(Claude / Codex / Marco),Role(Planner / Designer / Developer / QA / Marketer). - 기본 브랜치:
develop. 독립 작업과 상위 작업 브랜치는develop에서 따고 PR 베이스도develop이다. 하위 이슈의 스택 PR만 아직 병합되지 않은 상위 작업 브랜치를 베이스로 삼는다.main은 출시용이다. - 브랜치: Issue 번호만 쓴다 —
51. 하위 이슈가 생길 상위 이슈는<번호>/parent, 하위 이슈는<상위>/<하위>. 작업 종류는 브랜치가 아니라 PR 제목에 쓴다. worktree로 병렬 작업. - PR: 제목은
[Category] 한글 제목형식으로 쓴다. Category는Feature/Fix/Documentation/Chore/Refactoring/Test/Style중에서 고른다. 본문에Closes #N. 한 PR은 한 Issue. PR을 한꺼번에 여러 개 열지 않는다(CodeRabbit OSS rate limit). - 커밋 메시지: marcorable-kit
commit스킬(agent-common/marcorable-github/skills/commit/) 형식을 따른다.- 제목:
[#N] type: 요약—#N은 브랜치의 자기 이슈 번호 하나.develop·main처럼 번호 없는 브랜치에서는 prefix를 생략한다. - type:
feat/fix/refactor/modify/rename/docs/style/test/chore. - 요약은 한글 명사형 종결("~추가", "~수정", "~적용"), 마침표 없음. 코드 이름은 그대로 쓴다.
- 본문(선택): 제목과 빈 줄로 구분, 상세는
-목록으로 쓴다. - 리뷰 반영 커밋은
[#N] fix: Code Review K(K는 같은 브랜치의 이전 번호 + 1). Co-Authored-By같은 attribution 줄은 넣지 않는다.
- 제목:
PR 오픈 → Codex 자동 리뷰 (1차, P0/P1만)
+ 에이전트가 PR 생성 직후 `@coderabbitai review` 코멘트 (1차 보조)
→ 에이전트가 피드백 반영 → CI 통과
→ Marco 리뷰 (2차, 구조·방향) → 머지
- 구현한 모델과 다른 모델이 리뷰한다(원칙 5).
- Codex 피드백 반영은
@codex address that feedback코멘트 또는 구현 에이전트가 처리한다.
리뷰어(Codex, CodeRabbit, Claude, Marco)는 아래 기준으로 본다. P0/P1은 머지 차단.
- 제3자 텍스트(기도문·경전·가사·시)가 코드·테스트·프리뷰·문서·스크린샷에 포함됨 (3번 제약)
- 시크릿·개인정보 커밋 (4번)
- 사용자 텍스트나 음성이 기기 밖으로 나가는 코드 (네트워크 호출, 서버 전송, 애널리틱스에 본문 포함)
- 음성 녹음을 저장하는 코드
- MVP 제외 기능을 몰래 구현
- 상태·생명주기: 비동기 STT 결과가 종료된 낭독 세션이나 dispose된 위젯 상태를 변경,
StreamSubscription·네이티브 작업 취소 누락, 앱 백그라운드 전환 시 마이크가 계속 동작 - STT 파이프라인: iOS·Android의 권한,
ko-KR지원, 온디바이스 인식 가능 상태를 확인하지 않음, 부분 결과·최종 결과·오류·취소 계약이 플랫폼마다 다름, 사용자 음성이나 전사문을 외부로 전송하거나 녹음 파일로 저장 - 매칭 로직: 커서가 뒤로 가는 코드, 전체 전사문에서 위치를 검색하는 코드(반복 낭독에서 깨짐), 임계값 하드코딩이 UI에 섞임
- 아키텍처: Dart 매칭·세션 로직이 Flutter UI나 네이티브 STT 구현을 직접 참조, 플랫폼 어댑터 경계 없음, 순수 로직에 유닛 테스트 없음, 로컬 저장 모델 변경에 마이그레이션 고려 없음
- 접근성: 텍스트 배율 미지원, 큰 글씨에서 레이아웃 깨짐, 터치 타깃이 플랫폼 권장 크기 미만, 의미 있는 Semantics 라벨 없음 (어르신 사용자 전제)
- 테스트: 기존 테스트 삭제·비활성화, 테스트 없이 로직 변경
- Flutter 위젯 파일이 200줄 넘음 → 분리
BuildContext를 비동기 경계 뒤에서mounted확인 없이 사용- 불필요한 null 단언(
!)과 unchecked cast - 매직 넘버 → 이름 있는 상수
- 과도한 중첩 위젯과 불필요한 rebuild
- 한국어 UI 문구가 코드에 하드코딩 (Flutter localization 사용)
- 스타일 취향(들여쓰기, 줄바꿈)은
dart format과 정적 분석에 맡긴다. - P2를 이유로 머지를 막지 않는다.
에이전트는 코드를 바꾸면 다음을 스스로 실행하고 결과를 PR에 적는다.
- 포맷·정적 분석 (
dart format --output=none --set-exit-if-changed .,flutter analyze) - 유닛·위젯 테스트 (
flutter test) - Android 빌드·에뮬레이터 실행 + 해당 화면 스크린샷
- iOS 빌드·시뮬레이터 실행 + 해당 화면 스크린샷
- (UI 변경 시) 큰 글씨/확대 텍스트 화면을 양 플랫폼에서 확인하고 스크린샷 첨부
빌드·테스트 실패를 "환경 문제"로 넘기지 않는다. 못 풀면 Issue에 상황을 적고 user를 붙인다.
docs/
├── PRD.md ← 1단계에서 작성
├── agents/<role>.md ← 역할별 지침 원본 (모델 중립)
├── design/tokens.md ← 2단계
└── log/ ← phase-N.md, stt-spike.md, 리뷰 품질 비교 등
- 단계가 끝날 때마다
docs/log/phase-N.md에 "어떤 도구로 / 된 것 / 안 된 것 / Marco가 개입한 지점"을 기록한다. - 에이전트가 못 푼 문제와 그때 고친 규칙·프롬프트도 같은 로그에 남긴다(원칙 3).
- 한 번에 하나의 주제. 여러 결정을 한꺼번에 묻지 않는다.
- 큰 그림을 먼저 보여주고 디테일로 들어간다.
- 추상적 설명보다 구체적인 코드·명령어 예제로 답한다.
- 외부에 드러나는 작업(push, Issue·라벨·Milestone 생성, PR 오픈, 코멘트)은 실행 전에 목록을 보여주고 확인받는다.
- "확정" 표시가 없는 항목은 제안 상태다. 확정된 것처럼 밀어붙이지 않는다.
- 한국어로 소통한다.
| 역할 | 파일 | 홈 |
|---|---|---|
| Planner | docs/agents/planner.md |
Orca / Slack 후보 |
| Designer | docs/agents/designer.md |
Orca |
| Developer | docs/agents/developer.md |
Orca (Android Studio·Android Emulator·Xcode·iOS Simulator 필요) |
| QA | docs/agents/qa.md |
Orca (Android Emulator·iOS Simulator 필요) |
| Marketer | docs/agents/marketer.md |
Orca / Slack 후보 |
Claude Code용 서브에이전트 정의는 .claude/agents/<role>.md에 있으며, 본문은 위 원본을 참조한다.