docs: 신규 스킬 7개 SKILL.md + 원칙 문서 중복 제거 + 구현 결과 문서

- session-logs, blogwatcher, summarize, whisper, gitea, himalaya, skill-creator SKILL.md
- SKILL.md 인덱스 업데이트 (16개 스킬)
- 311/314/315 상위 SSOT 중복 제거 + 링크 수정
- Phase 1-3 결과 + 테스트 결과 + evaluation 트러블슈팅

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
happybell80 2026-03-26 01:21:10 +09:00
parent 8b5eed27d5
commit 886bd42ae3
23 changed files with 1023 additions and 210 deletions

View File

@ -2,7 +2,7 @@
**작성일**: 2025-09-17
**수정일**: 2026-01-21 (파일 크기 제한 300줄 → 500줄 완화)
**상위 원칙**: [0_VALUE Coding Principles](../../../../0_VALUE/02_Governance/coding-principles.md)
**상위 원칙**: [0_VALUE Coding Principles](../../../../0_VALUE/20_Governance/coding-principles.md)
## 1. 계층 분리 원칙
@ -48,10 +48,8 @@
- router 파일에서 main.py의 인스턴스(router, scheduler 등) 사용 시 의존성 주입 패턴 사용
- 예: `set_router_instance()`, `set_scheduler()` 함수로 주입
- router 파일에서 직접 import하지 않음
- **`당장 동작` 우선 구현 절대 금지**
- 운영 중인 `main.py`에 스케줄/복구/외부 호출/무거운 초기화를 임시로 누적해 문제를 덮는 방식 금지
- 임시 우회/폴백으로 증상을 숨기는 구현 금지
- 위반 발견 시 기능 추가보다 책임 분리 리팩토링을 우선 수행
상위 원칙 참조: [0_VALUE Coding Principles](../../../../0_VALUE/20_Governance/coding-principles.md) §1, §2 (`main`·엔트리포인트에 스케줄/복구/외부 호출·무거운 초기화 누적 금지, 임시 우회·폴백으로 증상 숨김 금지, 위반 시 책임 분리 리팩토링 우선)
### 폴더 명명 규칙
- `router/` 또는 `api/`: HTTP 처리
@ -129,25 +127,18 @@ utils
- **워크플로우 중복 실행 방지**: LangGraph 워크플로우가 활성화되면 개별 Phase 단계는 건너뛰기
- 워크플로우 내부에서 이미 처리하는 단계(질문 확장, 의도 분류 등)를 외부에서 중복 실행하지 않음
- 예: `INTENT_USE_LANGGRAPH=true`이면 `message_service`의 Phase 1(질문 확장) 건너뛰기
- **임시 플래그 장기 방치 금지**: 전환용 기본값/우회 플래그는 배포 안정화 기간 종료 시 제거 또는 강제 전환한다.
- 예: `INTENT_ENGINE` 기본값을 구버전(`v1`)으로 장기 유지하는 구성 금지
- 예외가 필요한 경우 문서에 종료 조건(기한, 책임자, 제거 PR)을 함께 기록
### 계층별 원칙
- **router**: 서비스 호출만, DB/비즈니스 로직 금지
- **services**: 비즈니스 로직 구현, state를 통한 DB 접근
- **state**: DB CRUD만, 비즈니스 로직 금지
상위 원칙 참조: [0_VALUE Coding Principles](../../../../0_VALUE/20_Governance/coding-principles.md) §1 (전환용 플래그·우회의 장기 방치 금지, 종료 조건·제거 PR 문서화)
### 예외 처리/웹훅 원칙
상위 원칙 참조: [0_VALUE Coding Principles](../../../../0_VALUE/20_Governance/coding-principles.md) §1, §3, §4, §5 (원인·상태코드·폴백·관측 가능성 일반 기준)
- **HTTPException 재포장 금지**: `except Exception`에서 `HTTPException`까지 500으로 감싸지 않는다. `except HTTPException: raise`를 기본 패턴으로 둔다.
- **Slack 서명 검증 경로 원문 보존**: 프록시 경유 웹훅은 원문 body를 유지해야 하며, 서명 검증 경로에서 body 재직렬화를 금지한다.
- **원인 직접 수정 우선**: 증상을 감추는 광범위 예외 폴백/임시 우회 코드를 금지한다. 재현 가능한 근본 원인(입력/경로/설정/데이터)을 먼저 수정한다.
- **상태코드 의미 보존**: 인증 실패(401/403), 권한 문제(403), 입력 오류(400)는 원래 의미대로 반환하고 500으로 왜곡하지 않는다.
- **폴백 남용 금지**: 폴백은 사용자 보호용 최후 수단으로만 사용한다. 개선 신호를 가리는 무조건 폴백(`catch-all fallback`)을 금지한다.
- **실패와 0건 결과 혼동 금지**: 외부 조회 실패, timeout, refresh 실패를 `[]`, `None`, `"no data"` 같은 정상 결과로 치환하지 않는다. "실패"와 "실제 데이터 없음"은 서로 다른 타입과 로그로 분리한다.
- **스케줄러 성공 오판 금지**: 배치/스케줄러 래퍼는 하위 실패를 삼키지 않고 다시 올린다. 운영 로그의 success는 실제 성공과 같아야 한다.
- **관측 가능한 실패 보장**: 운영/카나리 경로에는 `strict_observe` 모드를 두어 일부 요청은 폴백 없이 실패를 노출하고, 구조화된 오류 로그/메트릭을 반드시 남긴다.
- **로그 없는 폴백 금지**: 폴백이 발생하면 `request_id`, `route`, `template/version`, `fallback_reason`, `upstream_error`를 필수 기록한다.
- **폴백 시 필수 로그 필드**: 폴백이 발생하면 `request_id`, `route`, `template/version`, `fallback_reason`, `upstream_error`를 필수 기록한다.
## 6. DB 접근 규칙
@ -168,7 +159,9 @@ utils
- **별칭 사용**: 가능한 경우 컬럼명 별칭 사용하여 충돌 회피
### 더미/목 데이터 금지 원칙
- **절대 금지**: 프로덕션 환경에서 더미 데이터(mock data, dummy data)를 생성하거나 사용하지 않음
상위 원칙 참조: [0_VALUE Coding Principles](../../../../0_VALUE/20_Governance/coding-principles.md) §6 (운영 경로에 더미·테스트 우회·개발 편의 코드 금지, 개발/실험과 분리)
- **데이터 수집 필수**: 실제 데이터 소스(공식 API, 공개 데이터, 수집 파이프라인)에서 데이터를 수집해야 함
- **임시 데이터**: 개발/테스트 환경에서만 더미 데이터 허용 (명시적으로 `if os.getenv("ENVIRONMENT") == "development"` 조건부 사용)
- **데이터 부재 시**: 데이터가 없는 경우 기능을 비활성화하거나 "데이터 수집 중" 메시지 표시, 절대 랜덤/더미 데이터로 대체하지 않음
@ -231,6 +224,8 @@ utils
## 9. 체크리스트
상위 원칙 참조: [0_VALUE Coding Principles](../../../../0_VALUE/20_Governance/coding-principles.md) §1, §3, §4 (인증·입력 오류의 상태코드 왜곡 금지, 증상 완화 폴백을 해결로 취급 금지)
코드 작성 전:
- [ ] 이 코드는 어느 계층인가?
- [ ] DB 접근은 state를 통하는가?
@ -246,8 +241,6 @@ utils
- [ ] 복잡한 워크플로우는 LangGraph 활용 검토
- [ ] 원칙 문서 확인 완료 (`311_FastAPI_구조_원칙.md`, `312_writing-principles.md`)
- [ ] 웹훅 프록시 경로에서 원문 body 전달(`content=raw_body`) 여부 확인
- [ ] 인증 실패 상태코드(403/401)가 500으로 재매핑되지 않는지 확인
- [ ] 증상 완화용 폴백 대신 근본 원인 수정이 반영되었는지 확인
배포 전/후 확인:
- [ ] 코드 변경 후 `git status`로 커밋되지 않은 변경사항 확인
@ -281,6 +274,8 @@ utils
## 12. 환경변수 관리 원칙
상위 원칙 참조: [0_VALUE Coding Principles](../../../../0_VALUE/20_Governance/coding-principles.md) §7 (시크릿·공통 URL·포트 등 코드 하드코딩 금지, 서비스 간 설정·상태 의미 일치)
**단일 소스 원칙**:
- **`.env`**: 모든 환경변수 값의 단일 소스 (실제 값만 저장)
- **`docker-compose.yml`**: `env_file: - .env`로 자동 로드, `environment:` 섹션은 선택사항
@ -299,6 +294,8 @@ utils
## 13. LLM 우선 접근 원칙
상위 원칙 참조: [0_VALUE Coding Principles](../../../../0_VALUE/20_Governance/coding-principles.md) §9, §10 (질문별 특례·얕은 의도 선판정 금지, 키워드 다운그레이드 금지 등 일반 기준)
**핵심 원칙**: LLM을 기본으로 사용하고, 하드코딩된 규칙(heuristic)은 최소화
### LLM 기본 사용
@ -316,29 +313,11 @@ utils
- **성능/비용 최적화**: 확신도 매우 높은 케이스(> 0.95)만 규칙으로 빠르게 처리
- **규칙 추가 금지**: 새로운 패턴마다 규칙 추가하지 말고 LLM 활용
### 금지 사항
- ❌ LLM 호출을 피하기 위해 규칙/패턴 매칭으로 처리
- ❌ 오타, 별칭, 축약, 복합 발화, 후속 질문 가능성이 있는 도메인을 키워드 몇 개로 앞단에서 잘라내는 방식
- ❌ 키워드 불일치만으로 `UNKNOWN -> 일반 chat`으로 떨어뜨리고, 근거 탐색 가능성을 잃는 방식
- ❌ 의도 분석을 너무 얕고 빠르게 끝내서 실제 도메인 질의를 일반 대화나 추정 응답으로 보내는 방식
### 운영 해석 원칙
1. 엔티티/도메인 질의는 `정규화 -> 엔티티 해석 -> 필요시 근거 탐색 경로 진입`을 먼저 본다.
2. FastPath 규칙은 명확한 인사/명령어/확정 패턴에만 쓴다.
3. 애매한 질의는 `값싼 규칙으로 종료`하지 말고 더 깊은 해석 경로로 넘긴다.
4. 운영상 중요한 질의에서 앞단 규칙 실패는 `일반 chat 허용` 근거가 아니라 `정규화/해석 경로 부족` 신호로 본다.
### 로빙 백엔드에서의 추가 지침
- ❌ 복잡한 규칙 체인 구축 (LLM이 더 정확하고 유지보수 용이)
- ❌ 새로운 패턴마다 규칙 추가하는 방식 (LLM이 자동으로 처리)
- ❌ "규칙으로 처리 가능하면 규칙 사용" 사고방식 (LLM 우선 사고)
- ❌ 질문별 `if` 분기와 질문별 프롬프트/답변 문장을 코드에 누적해 시나리오를 닫는 방식
- ❌ 대표 질문 몇 개만 통과시키는 특례 처리로 `완료` 판단하는 방식
- ❌ `검색 hit 있음 = 성공`처럼 취급하고 질문 적합도/근거 부족 판정을 생략하는 방식
### 추가 강제 규칙
- LLM/RAG 응답 경로는 `질문 유형 계약`, `근거 채택 규칙`, `근거 부족 시 실패 규칙`을 공통 구조로 먼저 정의해야 합니다.
- 질문이 늘어날수록 분기와 프롬프트가 늘어나는 구조는 설계 실패로 간주합니다.
- 특정 질문 대응이 필요하면 질문별 특례를 추가하기 전에 공통 계약으로 올릴 수 없는지 먼저 검토합니다.
### 장점
- **유연성**: 새로운 패턴에 대한 규칙 추가 없이 LLM이 자연스럽게 처리
- **정확도**: 맥락 이해 능력으로 규칙 기반보다 정확한 해석
@ -419,6 +398,8 @@ utils
## 18-1. 변경 실행 워크플로우
상위 원칙 참조: [0_VALUE Coding Principles](../../../../0_VALUE/20_Governance/coding-principles.md) §11 (검증 우선·컨테이너 생존만으로 정상 판정 금지)
**핵심 원칙**: 변경은 `계획 -> 구현 -> 테스트 -> push -> 배포 대기 -> 실제 검증 -> worklog` 순서를 기본으로 고정합니다.
### 기본 순서
@ -428,7 +409,7 @@ utils
2. **구현**
- 계획 범위 안에서만 수정합니다.
- 질문별 특례 하드코딩, 광범위 폴백, 임시 우회로 닫지 않습니다.
- 상위 §1·§4·§9와 충돌하는 구현(질문별 특례 하드코딩, 광범위 폴백, 임시 우회로 이슈 종료)은 금지합니다.
3. **테스트**
- 관련 단위 테스트, 통합 테스트, 최소 재현 질문셋을 먼저 돌립니다.
@ -452,9 +433,7 @@ utils
- `plans`는 완료 보고서로 길게 덮어쓰지 않고, 상태와 연결 문서만 갱신합니다.
### 완료 금지 기준
- 테스트 전 `push`하고 끝냈다고 말하지 않습니다.
- 배포 완료 메시지만 보고 끝냈다고 말하지 않습니다.
- 실제 재현 질문/실제 응답/실제 로그 확인 없이 `해결`이라고 말하지 않습니다.
- 상위 §11에 맞춰, 테스트·배포·실제 검증 없이 완료·해결을 선언하지 않습니다.
- 문제가 남아 있으면 `worklog`로 보내지 않습니다.
## 19. 리팩토링 시 로직 상실 방지 원칙

View File

@ -1,50 +1,17 @@
# 314 인프라 설정 SSOT 원칙
# 인프라 설정 SSOT 원칙
**상위 원칙**: [0_VALUE Infrastructure SSOT Principle](../../../../0_VALUE/02_Governance/infrastructure-ssot-principle.md)
- 상위 원칙 참조: [0_VALUE Infrastructure SSOT](../../../../0_VALUE/20_Governance/infrastructure-ssot-principle.md)
- 본 문서는 robeing 운영 구조에만 필요한 로컬 적용 기준만 다룹니다.
## 1. 목적
- 인프라 핵심 설정(IP, 포트, 업스트림, 공통 URL, 환경별 엔드포인트)을 단일 출처(Single Source of Truth)로 관리한다.
- 값 변경 1건이 다수 코드/설정/문서 수정을 유발하는 구조를 제거한다.
## 런타임 파일 기준
- 런타임 설정 기준 파일 경로는 `/home/admin/infra-config/runtime.env`입니다.
- 민감 정보 기준 파일 경로는 `/home/admin/infra-config/secrets.env`입니다.
## 1.1 상위 원칙 관계
- 상위 공통 원칙의 SSOT는 `0_VALUE/02_Governance/infrastructure-ssot-principle.md`다.
- 본 문서는 robeing 운영 구조에 맞춘 구체화 문서다.
- 원칙 충돌 시 상위 원칙을 먼저 검토하고, 예외가 필요하면 사용자에게 먼저 보고한 뒤 본 문서에 예외를 남긴다.
## Compose 검증 기준
- 적용 완료 판단 전 `docker compose config`로 최종 설정 해석 결과를 검증합니다.
- 검증 완료 기준은 health check 통과와 실제 API 경로 응답 확인까지 포함합니다.
## 2. 원칙
### 2.1 단일 출처
- 런타임 설정의 기준 파일은 `/home/admin/infra-config/runtime.env` 단일 파일로 한다.
- 민감 정보의 기준 파일은 `/home/admin/infra-config/secrets.env` 단일 파일로 한다.
### 2.2 분리 원칙
- `runtime.env`: 비민감 운영값만 포함한다.
- 예: 내부 IP, 포트, 서비스 호스트, 모니터 URL, 기능 플래그
- `secrets.env`: 인증/암호/키 등 민감값만 포함한다.
- 예: JWT secret, OAuth secret, DB password 포함 URL
### 2.3 참조 원칙
- 서비스 컨테이너는 `docker-compose.yml``env_file`에서 위 2개 파일을 우선 참조한다.
- 서비스별 `.env`는 “임시 로컬 오버라이드” 용도로만 사용한다.
- 운영 기본값은 코드 하드코딩으로 두지 않는다.
### 2.4 네트워크 표현 원칙
- 컨테이너 간 통신은 서비스 DNS 이름을 우선 사용한다.
- 호스트 접근이 필요한 경우에만 `host.docker.internal` 또는 운영 표준 호스트 값을 사용한다.
- 고정 IP 직접 참조는 불가피한 경계 구간에서만 허용하고, 반드시 SSOT 변수로 선언한다.
### 2.5 보안 원칙
- `runtime.env``secrets.env`는 git에 커밋하지 않는다.
- 권한 최소화:
- `runtime.env` 640 이하
- `secrets.env` 600
- 디렉터리 권한 제한(예: 750)
### 2.6 문서 원칙
- 트러블슈팅 문서는 “사실/조치/검증”만 기록한다.
- 영구 규칙 변경은 본 원칙 문서에만 반영한다.
- 운영 주소 변경 시, 개별 문서에 직접 IP를 추가하지 말고 SSOT 변수명을 사용한다.
## 3. 적용 기준
- 신규 서비스: 최초 구성부터 본 원칙을 강제 적용한다.
- 기존 서비스: 장애 영향도가 높은 서비스부터 단계적으로 이전한다.
- 변경 검증: `docker compose config`, health check, 실제 API 경로 응답을 모두 통과해야 적용 완료로 본다.
## 네트워크 표현 기준
- 컨테이너 간 통신은 서비스 DNS 이름을 우선 사용합니다.
- 호스트 접근이 필요한 경우에만 `host.docker.internal` 또는 운영 표준 호스트 값을 사용합니다.
- 고정 IP 직접 참조는 불가피한 경계 구간에서만 허용하고, 반드시 SSOT 변수로 선언합니다.

View File

@ -1,15 +1,13 @@
# 테스트 원칙
**작성일**: 2025-01-03
**수정일**: 2026-03-16 (robeing/tests 통합 관리 원칙 반영)
**상위 원칙**: [0_VALUE Test Principles](../../../../0_VALUE/02_Governance/test-principles.md)
**참고**: 311_backend_coding_principles.md, 312_writing-principles.md, ../../../../0_VALUE/02_Governance/coding-principles.md
**수정일**: 2026-03-26 (상위 SSOT 정렬: 중복 제거, `20_Governance` 경로 정정)
**상위 원칙**: [0_VALUE Test Principles](../../../../0_VALUE/20_Governance/test-principles.md)
**참고**: 311_backend_coding_principles.md, 312_writing-principles.md, ../../../../0_VALUE/20_Governance/coding-principles.md
---
## 1. 핵심 원칙
### TDD 원칙
## TDD
**테스트는 TDD로 진행한다.**
@ -19,53 +17,67 @@
DecisionEngine, intent, 캘린더 로직 등은 항상 테스트에서 기대 행동을 확정한 뒤 수정한다.
### 로빙 테스트 환경 단일화 원칙
---
로빙 테스트는 `robeing/tests`에서 통합 관리한다. rb8001, skill-* 등 서비스별 테스트를 `robeing/tests/rb8001/` 등 하위에 두고, 단일 실행 기준만 사용한다. rb8001 푸시 시 Gitea Actions 배포가 트리거되므로, 테스트 수정만으로 배포를 유발하지 않도록 robeing/tests에서 작업한다. 임시/분기 테스트 환경은 만들지 않는다.
## 스킬·라우팅 검증
### UX 검증 원칙
상위 원칙 참조: [0_VALUE Test Principles](../../../../0_VALUE/20_Governance/test-principles.md)
신규 스킬, 의도 분류, `tool_registry` 변경 후 Slack 실메시지 전 검증은 상위 문서의 테스트 엔드포인트 원칙을 따른다. 로빙 rb8001 예시:
```bash
# JWT 없이 전체 플로우 테스트 (의도 분류 → 스킬 선택 → 실행 → 응답)
curl -s -X POST http://localhost:8001/api/test/router-message \
-H "Content-Type: application/json" \
-d '{"text": "테스트할 메시지", "user_id": "53529291-5050-4daa-89fb-008b546feb63"}'
```
- `text`: 사용자 메시지
- `user_id`: 선택 (기본값 있음)
- 응답: `bot_response`, `intent`, `status`
---
## 로빙 테스트 환경 단일화
로빙 테스트는 `robeing/tests`에서 통합 관리한다. rb8001, skill-* 등 서비스별 테스트를 `robeing/tests/rb8001/` 등 하위에 두고, 단일 실행 기준만 사용한다. rb8001 푸시 시 Gitea Actions 배포가 트리거되므로, 테스트 수정만으로 배포를 유발하지 않도록 `robeing/tests`에서 작업한다. 임시/분기 테스트 환경은 만들지 않는다.
---
## UX 검증
- 사용자가 실제로 보는 문구·행동만 검증한다 (예: 응답 문장, 버튼 노출 여부)
- 내부 안내/제약 설명(“직접 언급 금지” 같은 시스템 지시문)은 금지어 검증 대상이 아님
- UX 규칙(감정 직접 표현 금지 등)은 사용자 시나리오 테스트로 재현한다
### 테스트 코드 재작성 비효율 방지
---
**목표**: 테스트 코드를 매번 재작성하지 않고 재사용 가능하게 관리
## 공통 원칙(검증 우선·파일 양산 금지·자산 보존·자동·수동 분리·재사용·레이어·운영 경로·체크리스트)
**원칙** (상세: 섹션 2-5 참조):
- **재사용성 우선**: 공통 테스트 로직은 fixtures/유틸리티로 추출 (섹션 3)
- **자동화 필수**: pytest 기반 자동 테스트만 유지 (섹션 6)
- **중복 제거**: 동일 기능 테스트는 하나로 통합 (섹션 4)
목적, 원칙 전항, 유지 기준, 체크리스트는 상위 SSOT와 동일하다.
상위 원칙 참조: [0_VALUE Test Principles](../../../../0_VALUE/20_Governance/test-principles.md)
---
## 2. 테스트 파일 분류 및 위치
## 로빙 전용 — 테스트 위치 요약
| 유형 | 위치 | 관리 방식 |
|------|------|----------|
| **로빙 통합 테스트** | `robeing/tests/` (rb8001/, test_*.py 등) | robeing 전체 테스트 통합. 배포 트리거 없이 실행. [worklog 260316](../../journey/worklog/260316_rb8001_테스트_로빙테스츠로_이전.md) |
| **pytest 자동 테스트** | `tests/test_*.py` (레포 내) | 버전 관리, 지속 유지 (.gitignore 제외 금지) |
| **실험/관찰 스크립트** | `scripts/` (임시) | 작업 완료 즉시 삭제 |
| **공통 fixtures** | `tests/conftest.py` | 재사용 우선 |
| **로빙 통합 테스트** | `robeing/tests/` (rb8001/, `test_*.py` 등) | robeing 전체 테스트 통합. 배포 트리거 없이 실행. [worklog 260316](../../journey/worklog/260316_rb8001_테스트_로빙테스츠로_이전.md) |
| **pytest 자동 테스트** | `tests/test_*.py` (레포 내) | 버전 관리, 지속 유지 (`.gitignore` 제외 금지) |
| **실험·관찰 스크립트** | `scripts/` (임시) | 작업 완료 즉시 삭제 |
| **공통 fixtures** | `tests/conftest.py` | 상위 재사용 원칙 준수 |
| **테스트 데이터** | `tests/data/`, `tests/fixtures/` | 공유 가능하도록 구조화 |
### 금지 사항
| 금지 | 이유 | 참조 |
|------|------|------|
| `tests/`에 실험 스크립트 저장 | 자동 테스트와 혼재, 정리 어려움 | 섹션 5, 6 |
| 수동 실행 스크립트 장기 보관 | 재작성 비효율 유발 | 섹션 5 |
| 중복 테스트 파일 유지 | 유지보수 비용 증가 | 섹션 4 |
| `.gitignore``tests/test_*.py` 제외 | 버전 관리 필요 | 섹션 2 |
`tests/`에 실험 스크립트·수동 전용 파일을 두지 않는다. 금지 사유와 자동·수동 구분은 상위 문서를 따른다.
---
## 3. 테스트 코드 재사용성
## fixtures·테스트 데이터 예시
### 공통 로직 추출
**권장**: pytest fixtures
**권장**: pytest fixtures 사용
```python
# tests/conftest.py
@pytest.fixture
@ -80,21 +92,17 @@ def test_intent_classification(mock_llm_service):
...
```
**금지**: 각 테스트 파일에서 동일한 모킹 코드 반복 작성
**권장 데이터 경로**: `tests/data/intent_eval_samples.json`, `tests/fixtures/`
### 테스트 데이터 관리
**금지**: 동일 모킹·데이터를 테스트 파일마다 복붙
**권장**: 공통 데이터 파일 사용
- `tests/data/intent_eval_samples.json`: 의도 분류 샘플 데이터
- `tests/fixtures/`: 재사용 가능한 모킹 객체
상위의 재사용·중복 금지 원칙과 함께 적용한다.
**금지**: 테스트 파일 내 하드코딩된 데이터 반복
상위 원칙 참조: [0_VALUE Test Principles](../../../../0_VALUE/20_Governance/test-principles.md)
---
## 4. 중복 테스트 통합
### 통합 대상
## 중복 통합·임시 정리 — 로빙에서 자주 보는 패턴
| 중복 패턴 | 처리 방법 |
|-----------|----------|
@ -102,63 +110,27 @@ def test_intent_classification(mock_llm_service):
| TDD 단계별 테스트 파일 | 최종 버전만 유지 |
| `test_*_vs_*.py` 비교 테스트 | troubleshooting 기록 후 삭제 |
### 유지 기준 (상세: 섹션 6 참조)
임시·비교·수동 스크립트 정리 시점과 유지·삭제 기준은 상위 문서를 따른다.
- **유지**: pytest로 재현 가능한 자동 테스트
- **삭제**: 임시 실험, 비교 테스트, refactoring 테스트 (섹션 5)
상위 원칙 참조: [0_VALUE Test Principles](../../../../0_VALUE/20_Governance/test-principles.md)
---
## 5. 임시 테스트 정리
## pytest 실행 확인·컨테이너에 테스트 반영
### 즉시 삭제 대상
상위 원칙 참조: [0_VALUE Test Principles](../../../../0_VALUE/20_Governance/test-principles.md) (`tests/`에는 자동 회귀용 pytest만, `if __name__` 중심 수동 파일 배치 금지 등)
| 대상 | 패턴 | 처리 시점 |
|------|------|----------|
| **리팩토링 테스트** | `test_*_refactoring.py` | 작업 완료 후 |
| **비교 실험** | `test_*_vs_*.py` | troubleshooting 기록 후 |
| **관찰용 스크립트** | "서비스 코드 수정 없이 관찰" 주석 | 작업 완료 즉시 |
| **수동 실행 스크립트** | `python3` 직접 실행, pytest 미적용 | 작업 완료 즉시 (섹션 6) |
| **실험 결과 파일** | `.md`, `.json` 결과 파일 | troubleshooting 문서화 후 |
**로빙 운영 확인용**:
### 정리 프로세스
1. 문제 해결 → troubleshooting 문서 작성
2. 핵심 교훈 기록
3. 임시 테스트 파일 삭제
---
## 6. pytest 자동 테스트 기준
### 필수 요구사항
**pytest 자동 테스트 확인 방법**:
- `import pytest` 또는 `@pytest.mark.*` 데코레이터 사용
- `pytest tests/test_*.py` 명령으로 실행 가능
- `if __name__ == "__main__"` 직접 실행 코드 없어야 함
**금지 사항**:
- `python3 tests/test_*.py` 방식의 수동 실행 스크립트
- "pytest 없이 직접 실행" 주석이 있는 파일
- pytest import 없이 `def test_*()` 함수만 있는 파일 (pytest 미적용)
### 테스트 파일 검증
**추가 전 확인**:
```bash
# pytest로 실행 가능한지 확인
pytest tests/test_*.py -v
# pytest import 여부 확인
grep -l "import pytest\|@pytest" tests/test_*.py
```
### 컨테이너 테스트 파일 반영
**컨테이너**: `tests`는 볼륨 마운트가 아니라 Dockerfile에서 `COPY ./tests /code/tests`로 빌드 시에만 반영된다.
**배경**: tests 디렉토리는 볼륨 마운트가 아님 (Dockerfile에서 `COPY ./tests /code/tests`로 빌드 시만 복사)
새 테스트 파일을 컨테이너에 올릴 때:
**새 테스트 파일 추가 시**:
```bash
# 방법 1: docker cp (빠름, 재빌드 불필요)
docker cp tests/test_new_feature.py rb8001:/code/tests/
@ -167,13 +139,11 @@ docker cp tests/test_new_feature.py rb8001:/code/tests/
docker compose down && docker compose up -d --build
```
**주의**: 호스트에서 테스트 파일 수정 후 컨테이너에 반영 안 되는 문제 주의
호스트에서 수정한 테스트가 컨테이너에 자동 반영되지 않는다는 점에 주의한다.
---
## 7. 테스트 네이밍 및 구조
### 파일명 규칙
## 파일명·디렉터리 구조
| 패턴 | 용도 | 예시 |
|------|------|------|
@ -181,55 +151,42 @@ docker compose down && docker compose up -d --build
| `test_{엔드포인트}_endpoint.py` | API 엔드포인트 테스트 | `test_diary_endpoint.py` |
| `e2e/test_{워크플로우}.py` | E2E 테스트 | `e2e/test_coldmail_full_flow.py` |
### 금지 네이밍
**피할 네이밍**
- `test_*_refactoring.py` (작업 완료 후 삭제)
- `test_*_vs_*.py` (비교 실험, 결과 기록 후 삭제)
- `e2e_*.py` (tests 루트에, e2e/ 폴더로 이동)
- 중복된 e2e 테스트: `test_e2e_*.py``test_*_e2e.py` (하나로 통합)
- `e2e_*.py` (tests 루트에 두지 말고 `e2e/` 아래로)
- 중복 E2E: `test_e2e_*.py``test_*_e2e.py` (하나로 통합)
---
## 8. 체크리스트
## 로빙 체크리스트(상위에 더함)
### 테스트 작성 전
상위 원칙 참조: [0_VALUE Test Principles](../../../../0_VALUE/20_Governance/test-principles.md)
- [ ] TDD 순서 준수 (Red → Green → Refactor)
- [ ] 동일한 테스트 로직이 이미 존재하는가? (섹션 3 재사용성 확인)
- [ ] 공통 모킹/데이터가 있다면 `conftest.py`에 추가할 수 있는가? (섹션 3)
- [ ] pytest 자동 테스트인가? (섹션 6 기준 확인)
### 테스트 파일 추가 전
- [ ] 중복 테스트 파일이 있는가? (섹션 4 통합 가능한지 확인)
- [ ] 임시 실험 파일인가? (섹션 5 삭제 계획 수립)
- [ ] 네이밍 규칙 준수 (섹션 7)
- [ ] `.gitignore`에 제외 규칙이 있는가? (섹션 2 - 테스트 파일은 버전 관리 필수)
### 정리 시점 (섹션 5, 9 참조)
- [ ] 리팩토링/비교 테스트 → troubleshooting 기록 후 삭제
- [ ] 실험/수동 스크립트 → 작업 완료 즉시 삭제
- [ ] 중복 테스트 → 통합 또는 삭제
- [ ] TDD 순서 (Red → Green → Refactor)
- [ ] 통합 작업은 `robeing/tests` 기준으로 할 것 (배포 트리거·환경 단일화)
- [ ] 스킬·라우팅 변경 후 `/api/test/router-message` 등 테스트 엔드포인트로 선검증
- [ ] 컨테이너로 돌릴 때 테스트 파일 반영 경로(`docker cp` / 재빌드) 확인
- [ ] `.gitignore``tests/test_*.py` 제외 규칙 없음
---
## 9. 정리 프로세스 예시
### 실제 정리 사례 (2025-01-03)
## 정리 사례 (2025-01-03)
**삭제된 파일**:
1. `test_calendar_intent_overlap_cases.py` - "서비스 코드 수정 없이 관찰" 목적, 수동 실행
2. `test_calendar_query_vs_create.py` - `python3` 직접 실행, pytest 미적용
3. `test_all_day_event_simple.py` - 수동 실행 스크립트
4. `e2e/test_e2e_message_flow.py` - "pytest 없이 직접 실행" 주석, 중복 (`test_message_flow_e2e.py` 존재)
1. `test_calendar_intent_overlap_cases.py` — “서비스 코드 수정 없이 관찰” 목적, 수동 실행
2. `test_calendar_query_vs_create.py``python3` 직접 실행, pytest 미적용
3. `test_all_day_event_simple.py` — 수동 실행 스크립트
4. `e2e/test_e2e_message_flow.py` — “pytest 없이 직접 실행” 주석, 중복 (`test_message_flow_e2e.py` 존재)
**결과**: 68개 → 64개 (pytest 자동 테스트만 유지)
---
## 10. 참고
## 참고
- FastAPI 구조 원칙: `311_backend_coding_principles.md` 섹션 18 (테스트 원칙)
- 문서 작성 원칙: `312_writing-principles.md` (troubleshooting 기록 방법)
- FastAPI·백엔드: `311_backend_coding_principles.md` (테스트 관련 절)
- 문서 작성: `312_writing-principles.md` (troubleshooting 기록 방법)
- 트러블슈팅: `journey/troubleshooting/251110_레거시_테스트_폴더_정리.md`

View File

@ -0,0 +1,40 @@
---
date: 2026-03-26
subject: IR Deck 평가 빈 응답 + 무한 폴링 문제
status: open
writer: 24-claude (총괄)
investigators: 24-Cursor(백엔드), 24-Codex(API), 23-Cursor(프런트), 24-Gemini(로그)
---
# IR Deck 평가 빈 응답 + 무한 폴링
## 현상
- LLM evaluation이 빈 응답 반환 시 DB에 아무 상태도 안 남음
- 프런트가 evaluation_id로 조회 시 영원히 404
- 3분간 2초마다 폴링 (최대 90회 무의미한 호출)
## 근본 원인
| 위치 | 문제 | 위반 원칙 |
|------|------|----------|
| `ir_deck_analyzer.py` `_evaluate_comprehensive` | 실패 시 ValueError만 올리고 DB에 기록 없음 | coding-principles §3 (실패 의미 보존) |
| `ir_deck_evaluations` 테이블 | status 컬럼 없음 — 성공 INSERT만 존재 | coding-principles §5 (관측 가능) |
| `ir_deck.py` GET endpoint | DB에 행 없으면 404 — "실패"와 "미존재" 구분 불가 | coding-principles §3 |
| `useEvaluation.ts` | 404를 "아직 처리 중"으로 해석, 폴링 지속 | coding-principles §4 (폴백 절제) |
## 수정 계획
### 백엔드 (24서버, rb8001)
1. `ir_deck_evaluations``status` 컬럼 추가 (pending/completed/failed)
2. POST /evaluate 시 즉시 `status: pending`으로 INSERT
3. 성공 시 `completed`, 실패 시 `failed` + error_message UPDATE
4. GET endpoint: pending→200+pending, failed→200+failed, completed→기존 응답
### 프런트 (23서버, frontend-ir-valuation)
1. 응답 status 필드 분기: pending→계속, completed→중단+표시, failed→중단+"평가 실패"
2. 404 3회 연속 시 폴링 중단
3. 3분 타임아웃 유지
## 에이전트 배분
- 24-Cursor: 백엔드 수정
- 23-Cursor: 프런트 수정

View File

@ -0,0 +1,59 @@
---
date: 2026-03-26
subject: IR Deck 평가 빈 응답 문제 해결
status: closed
closed_date: 2026-03-26
closed_reason: max_tokens + response_format + pending/failed 상태 저장 적용으로 해결
---
# IR Deck 평가 빈 응답 문제 해결
## 현상
- LLM evaluation이 빈 응답 반환 → 평가 실패
- 프런트 3분간 무한 폴링 (404)
- "평가 처리 중 오류가 발생했습니다" 표시 불가
## 근본 원인
- **max_tokens=1000**: IR 평가 JSON은 수천 토큰 필요한데 기본값 1000으로 응답 잘림
- **response_format 미사용**: LLM이 서두/마크다운 혼입 가능
- **DB에 상태 없음**: 실패 시 행 자체가 없어 404 무한 폴링
- **LLM 원문 미로깅**: 뭐가 잘려서 실패했는지 알 수 없음
## 수정 내용
### 백엔드 (rb8001)
- `ir_analyzer.py``call_llm``max_tokens`, `response_format` 파라미터 추가
- `ir_deck_analyzer.py``_evaluate_comprehensive`에서:
- `max_tokens=4000` (env: `IR_EVAL_MAX_TOKENS`)
- `response_format={"type": "json_object"}` (JSON 강제)
- `json.loads` 직접 파싱 (`extract_json_from_text` 제거)
- JSON 파싱 실패 시 원문 첫 500자 로그
- `ir_valuation_repository.py``status` + `error_message` 컬럼 추가, `create_evaluation_pending`, `update_evaluation_status` 함수
- `ir_deck.py` — POST /evaluate에서 즉시 pending INSERT, 실패 시 failed UPDATE, GET에서 pending/failed/completed 분기
### 프런트 (frontend-ir-valuation)
- `useEvaluation.ts` — status 필드 분기 (pending→폴링, failed→중단+"평가 실패", completed→표시)
- 404 3회 연속 시 폴링 중단
### DB
- `ALTER TABLE ir_deck_evaluations ADD COLUMN status VARCHAR(20) DEFAULT 'completed'`
- `ALTER TABLE ir_deck_evaluations ADD COLUMN error_message TEXT`
### 설정
- `/home/admin/robeing/.env``DEFAULT_LLM_MAX_TOKENS=1000`, `IR_EVAL_MAX_TOKENS=4000`
## 원칙 반영
- `coding-principles.md` — "비동기 작업의 상태 추적" 원칙 추가
- `infrastructure-ssot-principle.md` — "프로젝트 루트 env 원칙" 추가
## 검증
- evaluation_id=1efaf078 테스트: pending→completed 12초, 67점 C등급
- 이전: 빈 응답 2회 재시도 후 failed
- 이후: JSON 강제 + 4000 토큰으로 정상 완료

View File

@ -0,0 +1,33 @@
---
date: 2026-03-26
subject: 260325-26 세션에서 발견된 원칙 개선사항
status: open
---
# 원칙 개선사항
## 이미 반영됨
| 원칙 문서 | 변경 | 이유 |
|----------|------|------|
| coding-principles.md §5 | 스케줄러 raise 필수 + exc_info=True | coldmail/headlines 에러 삼킴 |
| AGENTS.md §10 | Docker→Systemd 전환 원칙 | rb8001 전환 후 hostname/SQLite 오류 |
| test-principles.md §9 | 테스트 엔드포인트 활용 원칙 | router-message로 먼저 검증 |
| orchestration rules §9 | 에이전트 균등 사용 필수 | 특정 에이전트 과의존 방지 |
## 반영 필요 (미완료)
| 원칙 문서 | 필요한 변경 | 이유 |
|----------|-----------|------|
| coding-principles.md §5 | 비동기 작업은 시작 시 pending 상태를 DB에 기록, 실패 시 failed로 갱신 | evaluation 빈 응답 문제 |
| coding-principles.md §3 | "실패"와 "미존재"를 같은 HTTP 404로 반환하지 않는다 | evaluation 폴링 무한루프 |
| infrastructure-ssot-principle.md §7 | compose environment에서 env_file과 겹치는 변수를 ${VAR:-default}로 두지 않는다 (이미 있으나 위반 반복) | summarize/whisper 배포 문제 |
| 311_backend_coding_principles.md | 비동기 API 패턴: 즉시 ID 반환 + pending DB INSERT + 완료/실패 UPDATE | 로빙 특화 구체화 |
## SSOT 경로 오류 수정됨
| 위치 | 수정 |
|------|------|
| DOCS/skills/SKILL.md | 02_Governance → 20_Governance |
| 315_테스트_원칙.md 상위 링크 | 02_Governance → 20_Governance |
| 311_backend_coding_principles.md 상위 링크 | 02_Governance → 20_Governance |

View File

@ -0,0 +1,95 @@
---
date: 2026-03-25
subject: 신규 스킬 7개 전체 구현 결과
writer: 24-claude (총괄)
---
# 신규 스킬 7개 구현 결과
## 전체 현황
| Phase | 스킬 | 타입 | 포트 | 상태 |
|-------|------|------|------|------|
| 1 | **session-logs** | rb8001 내장 | 8001 | 완료 (코드+리뷰+수정) |
| 1 | **blogwatcher** | skill-news 확장 | 8505 | 완료 (코드+리뷰+수정) |
| 2 | **summarize** | 신규 서비스 | 8516 | 완료 (코드+리뷰+수정) |
| 2 | **whisper** | 신규 서비스 | 8517 | 완료 (코드+리뷰+수정) |
| 3 | **gitea** | 신규 서비스 | 8518 | 완료 (코드+리뷰+수정) |
| 4 | **himalaya** | skill-email 확장 (SKILL.md만) | 8501 | SKILL.md 완료 |
| 4 | **skill-creator** | 스캐폴딩 스크립트 | - | 스크립트+SKILL.md 완료 |
## 생성된 파일 전체
### 신규 서비스 (Phase 2-3)
```
skill-summarize/ (8516) — URL/유튜브/텍스트 요약
skill-whisper/ (8517) — 음성→텍스트 변환
skill-gitea/ (8518) — Gitea 레포/이슈/PR
```
### 기존 서비스 확장 (Phase 1)
```
rb8001/app/router/session_logs_endpoint.py — 세션 검색/비용 API
rb8001/app/state/session_logs_repository.py — DB 쿼리
skill_news/app/services/rss_service.py — RSS 파싱/구독
skill_news/app/api/rss_endpoints.py — RSS 엔드포인트
```
### SKILL.md (7개)
```
DOCS/skills/session-logs/SKILL.md
DOCS/skills/blogwatcher/SKILL.md
DOCS/skills/summarize/SKILL.md
DOCS/skills/whisper/SKILL.md
DOCS/skills/gitea/SKILL.md
DOCS/skills/himalaya/SKILL.md
DOCS/skills/skill-creator/SKILL.md
```
### 스크립트
```
scripts/create_skill.sh — 스킬 스캐폴딩 자동화
```
## 에이전트 사용 현황
| 에이전트 | 서버 | 구현 | 리뷰 | SKILL.md | 수정 |
|----------|------|------|------|----------|------|
| 24-Cursor | 24 | session-logs, summarize, gitea, blogwatcher, Phase4 | whisper, blogwatcher | - | session-logs, summarize |
| 24-Codex | 24 | whisper | session-logs, summarize, gitea | session-logs, gitea | whisper |
| 24-Gemini | 24 | - | SKILL.md 2건 | blogwatcher, summarize, whisper | gitea 에러노출 |
| 23-Cursor | 23 | (실패: 경로 없음) | blogwatcher (실패: 경로) | - | - |
### 에이전트 평가
| 에이전트 | 평균 | 비고 |
|----------|------|------|
| 24-Cursor | 9/10 | 속도+정확성 최고. 구현+리뷰 양쪽 안정 |
| 24-Codex | 8/10 | 리뷰 철저, 원칙 근거 명시. 구현도 안정 |
| 24-Gemini | 6/10 | SKILL.md 작성은 OK. 코드 접근 시 경로 문제 빈발 |
| 23-Cursor | 3/10 | 24서버 파일 접근 불가. 배분 실수 |
### 교훈
- 23서버 에이전트에 24서버 파일 작업 시키면 안 됨
- Gemini는 코딩 아닌 문서 작성에 적합
- `detail=str(e)` 패턴이 반복 발생 → 템플릿에 반영 필요
## 미완료 작업 (통합 배포 시)
- [ ] rb8001 main.py에 session_logs_router 등록
- [ ] skill-news main.py에 rss_router 등록
- [ ] rb8001 tool_registry SKILL_DIR_ALLOWLIST에 7개 스킬 추가
- [ ] rb8001 decision_engine IntentType 추가
- [ ] feedparser 설치 (skill-news)
- [ ] skill-summarize Docker 빌드 + 실행
- [ ] skill-whisper Docker 빌드 + 실행
- [ ] skill-gitea Docker 빌드 + 실행
- [ ] runtime.env에 SKILL_SUMMARIZE_URL, SKILL_WHISPER_URL, SKILL_GITEA_URL 추가
- [ ] 전체 헬스체크 확인
- [ ] himalaya IMAP 코드 구현 (Phase 4는 SKILL.md만)
## SSOT 이상 발견 및 수정
| 발견 | 위치 | 조치 |
|------|------|------|
| SSOT 링크 경로 02_Governance → 20_Governance | DOCS/skills/SKILL.md | 수정 완료 |

View File

@ -0,0 +1,49 @@
---
date: 2026-03-25
subject: 신규 스킬 통합 테스트 결과
writer: 24-claude (총괄)
testers: 24-Cursor(session-logs), 24-Codex(summarize), 24-Gemini(RSS), 23-Cursor(gitea)
---
# 신규 스킬 통합 테스트 결과
## 테스트 요약
| 스킬 | 상태 | 응답 시간 | 비고 |
|------|------|----------|------|
| **session-logs** | **정상** | ~20ms | 한글 q 파라미터 URL 인코딩 필요 |
| **blogwatcher (RSS)** | **정상** | 테스트 중 | feedparser 동작 확인 |
| **summarize (text)** | **정상** | ~1.5s | LLM 호출 포함 |
| **summarize (url)** | 수정 후 정상 | - | 컨테이너→호스트 IP 문제 해결 |
| **whisper** | **설정 완료** | - | OPENAI_API_KEY compose override 문제 해결 |
| **gitea** | **인증 대기** | ~6.6ms | GITEA_TOKEN 미설정 → 400 정상 에러 반환 |
## 발견된 이슈 및 해결
### 이슈 1: 컨테이너→호스트 통신 (summarize, whisper, gitea)
- **원인**: Docker 브리지 네트워크에서 `localhost:8001` = 컨테이너 자신
- **해결**: `.env``LLM_GATEWAY_URL=http://192.168.0.106:8001/api/llm/generate` 설정
- **근본 원인**: compose `environment``${VAR:-default}` 패턴이 env_file보다 우선
### 이슈 2: OPENAI_API_KEY 빈 값 덮어쓰기 (whisper)
- **원인**: compose `environment: OPENAI_API_KEY=${OPENAI_API_KEY}` → 호스트에 env 없으면 빈 값
- **해결**: compose environment에서 해당 줄 제거, secrets.env에서 직접 주입
### 이슈 3: GITEA_TOKEN 미설정
- **상태**: 의도된 동작 (400 에러 정상 반환)
- **해결**: secrets.env에 GITEA_TOKEN 추가 필요
## 성능
| 스킬 | 응답 시간 | 병목 |
|------|----------|------|
| session-logs | 20ms | DB 쿼리 (빠름) |
| summarize (text) | 1.5s | LLM 호출 |
| gitea | 6.6ms | HTTP 프록시 (빠름) |
## SSOT 교훈
compose `environment``${VAR:-default}` 패턴은 `env_file`보다 우선 적용되어 SSOT 원칙을 위반할 수 있음.
**원칙 추가 권장**: compose `environment`에 env_file과 겹치는 변수를 `${VAR:-default}` 형태로 두지 않는다.
이 원칙은 이미 `infrastructure-ssot-principle.md §7`에 있음:
> 공용 env_file을 읽는 compose는 같은 키를 environment: KEY=${KEY}로 다시 선언해 로컬 .env placeholder가 runtime.env·secrets.env를 덮어쓰게 만들지 않는다.

View File

@ -0,0 +1,133 @@
---
date: 2026-03-25
subject: 로빙 신규 스킬 7개 적용 계획
writer: 24-claude (총괄)
sources: 24-Cursor(스킬 구조), 24-Codex(rb8001 호출), 23-Cursor(SKILL.md 체계), 24-Gemini(외부 도구 조사)
---
# 로빙 신규 스킬 7개 적용 계획
## 1. 현재 스킬 아키텍처 요약
### 스킬 서비스 2가지 패턴
| 패턴 | 대표 | 네트워크 | rb8001 연동 | 적합한 경우 |
|------|------|----------|------------|------------|
| **email형** | skill-email | host 네트워크 | 양방향 콜백 (process + llm_callback) | 대화형, 내부 인증 필요 |
| **news형** | skill-news | 브리지 + robeing-network | 단방향 REST (LLM 게이트웨이 호출) | 수집형, 단순 REST |
### rb8001 스킬 호출 구조
```
사용자 메시지
→ IntentClassifier (SKILL.md name 기반 LLM 분류)
→ DecisionEngine (규칙/시맨틱/LLM fallback)
→ tool_registry (SKILL.md → OpenAI tool schema 동적 생성)
→ message_service (실행 + 결과 요약)
```
### 새 스킬 추가 시 필수 작업
| 작업 | 파일 |
|------|------|
| SKILL.md 작성 | `DOCS/skills/{name}/SKILL.md` |
| 인덱스 추가 | `DOCS/skills/SKILL.md` (목록 + 의도→스킬 매핑) |
| tool_registry 등록 | `rb8001/app/services/brain/tool_registry.py` (SKILL_DIR_ALLOWLIST) |
| 의도 타입 추가 | `rb8001/app/services/brain/decision_engine.py` (IntentType) |
| 실행 매핑 | `rb8001/app/services/message_service.py` |
| 환경변수 (외부 서비스) | `rb8001/app/core/config.py` (SKILL_*_URL) |
## 2. 신규 7개 스킬 적용 계획
### Phase 1 — 기존 인프라 활용 (빠름, 1-2일)
#### 1-1. session-logs (내장)
- **패턴**: rb8001 내장 (신규 서비스 불필요)
- **구현**: 기존 `conversation_repository`에 세션 검색·토큰 집계 API 추가
- **외부 의존**: 없음
- **수정 범위**: rb8001 router + repository 쿼리
- **SKILL.md 트리거**: `session_search`, `cost_check`, "저번에 뭐라 했지", "토큰 얼마 썼어"
#### 1-2. blogwatcher → skill-news 확장
- **패턴**: 기존 skill-news에 RSS 피드 기능 추가
- **구현**: `feedparser` (Python 네이티브, BSD, 6.0.12) 사용
- **외부 의존**: `pip install feedparser`
- **수정 범위**: skill-news에 RSS 엔드포인트 + DB에 구독 피드 테이블
- **SKILL.md 트리거**: `rss_subscribe`, `blog_watch`, "블로그 구독", "RSS 추가"
### Phase 2 — 신규 경량 서비스 (3-5일)
#### 2-1. summarize
- **패턴**: news형 (단방향 REST)
- **구현**: FastAPI + 크롤링(httpx/BeautifulSoup) + LLM 게이트웨이 요약
- **유튜브**: `youtube-transcript-api` (Python 네이티브, MIT, 6.5k★) 자막 추출 → LLM 요약
- **포트**: 8516 (제안)
- **SKILL.md 트리거**: `summarize_url`, `youtube_summary`, "이 링크 요약", "유튜브 요약"
#### 2-2. whisper (skill-whisper)
- **패턴**: news형 (단방향 REST)
- **구현**: OpenAI Whisper API 호출 (로컬 GPU 없으므로 API 우선)
- **외부 의존**: `OPENAI_API_KEY` (이미 있음)
- **포트**: 8517 (제안)
- **SKILL.md 트리거**: `transcribe`, `voice_to_text`, "음성 파일 텍스트로", "회의록"
### Phase 3 — Gitea 연동 (5-7일)
#### 3-1. github → skill-gitea
- **패턴**: news형 (Gitea REST API 호출)
- **구현**: Gitea API v1 (Swagger, MIT, 54.5k★) + `python-gitea` SDK
- **기능**: PR/이슈 조회·생성, CI 상태, 코드 검색
- **포트**: 8518 (제안)
- **SKILL.md 트리거**: `git_issue`, `git_pr`, "PR 목록", "이슈 만들어"
### Phase 4 — 기존 확장 (7-10일)
#### 4-1. himalaya → skill-email 확장
- **패턴**: 기존 skill-email에 IMAP/SMTP 프로바이더 추가
- **구현**: `himalaya` CLI (Rust, MIT, 4.5k★) 래핑 또는 Python `imaplib`/`smtplib` 직접
- **수정 범위**: skill-email에 프로바이더 추상화 레이어 (Gmail + IMAP)
- **SKILL.md 트리거**: 기존 email 트리거 유지, 프로바이더 자동 선택
#### 4-2. skill-creator (메타 스킬)
- **패턴**: rb8001 내장 또는 스크립트
- **구현**: 템플릿 스캐폴딩 (SKILL.md + Dockerfile + docker-compose + main.py + config.py)
- **외부 의존**: 없음
- **트리거**: 개발자 전용, CLI 스크립트로 제공
- **OpenClaw 패턴 채택**: requires 선언, 설치 가이드 포함
## 3. 외부 도구 상태
| 도구 | ★ | 최근 업데이트 | Python | 라이선스 |
|------|---|-------------|--------|---------|
| whisper | 96.6k | 2026.03 | 네이티브 | MIT |
| Gitea API | 54.5k | 2026.03.12 | SDK 있음 | MIT |
| youtube-transcript-api | 6.5k | 2026.02 | 네이티브 | MIT |
| himalaya | 4.5k | 2026.02 | CLI 래핑 | MIT |
| feedparser | 2.3k | 2025.09 | 네이티브 | BSD |
| summarize CLI | ~100 | 2026.03 | CLI | MIT |
| blogwatcher | ~50 | 2026.01 | CLI (Go) | MIT |
## 4. 포트 할당 계획
| 스킬 | 포트 | 비고 |
|------|------|------|
| 기존 skill-email | 8501 | |
| 기존 skill-slack | 8502 | |
| 기존 skill-news | 8505 | + blogwatcher(RSS) 통합 |
| 기존 skill-rag-file | 8508 | |
| 기존 skill-calendar | 8512 | |
| 기존 skill-embedding | 8515 | |
| **신규 summarize** | 8516 | |
| **신규 skill-whisper** | 8517 | |
| **신규 skill-gitea** | 8518 | |
| session-logs | 내장 (8001) | rb8001 엔드포인트 |
| skill-creator | 스크립트 | 포트 불필요 |
## 5. 우선순위 요약
| 순위 | 스킬 | Phase | 이유 |
|------|------|-------|------|
| 1 | session-logs | 1 | 신규 서비스 불필요, 쿼리만 추가 |
| 2 | blogwatcher (RSS) | 1 | 기존 skill-news 확장, feedparser만 추가 |
| 3 | summarize | 2 | 즉시 가치 가장 높음, 경량 |
| 4 | whisper | 2 | API 키 이미 있음 |
| 5 | skill-gitea | 3 | Gitea 이미 운영 중 |
| 6 | himalaya | 4 | 기존 서비스 구조 변경 필요 |
| 7 | skill-creator | 4 | 메타 도구, 급하지 않음 |

View File

@ -0,0 +1,68 @@
---
date: 2026-03-25
subject: OpenClaw 스킬 × 로빙 교차 비교 및 적용 후보
writer: 24-claude (총괄) + 24-Cursor + 24-Codex + 23-Cursor
---
# OpenClaw 스킬 × 로빙 적용 후보 리스트
## 1. 로빙 현재 스킬 (9개)
| 스킬명 | 포트 | 역할 | 현재 한계/갭 |
|--------|------|------|-------------|
| skill-email | 8501 | Gmail 조회·전송·요약 | OAuth 필수, 고급 분류/검색 범위 얇음 |
| skill-news | 8505 | 뉴스 검색·스크래핑·AI 요약 | 저작권 제약, 과거 아카이브 범위 제한 |
| skill-slack | 8502 | Slack 스레드 요약·액션 추출 | 비공개 채널 접근 제약 |
| skill-calendar | 8512 | 캘린더 일정 CRUD | Google Calendar 중심, 네이버웍스 TODO |
| skill-rag-file | 8508 | PDF/DOCX RAG 검색 | 팀 경계 제한, OCR fallback 중심 |
| skill-embedding | 8515 | 임베딩·감정 분류 (내부 전용) | 대용량 배치 rate limit |
| skill-llm | 내장 | 일반 대화·폴백 | 전용 스킬 우선, 폴백 전용 |
| companyx-rag | 8508 경유 | 사내 문서 근거 답변 | 트리거 규칙 불일치 |
| skill-translate | 내장 | 번역·표현 변환 | 문서화 부족 |
## 2. OpenClaw 적용 후보 (우선순위별)
### 높음 — 즉시 가치 있는 스킬
| OpenClaw 스킬 | 로빙 유사 기능 | 추가 가치 | 적용 방식 |
|--------------|---------------|----------|----------|
| **summarize** | skill-news(기사), skill-rag-file(문서) 부분 유사 | URL/유튜브 원샷 요약. RAG 업로드 없이 외부 콘텐츠 처리 | 신규 스킬 또는 skill-rag-file 확장 |
| **github/gh-issues** | 없음 | PR/이슈/CI 자동화. 개발 워크플로 지원 | 신규 스킬 |
| **himalaya** | skill-email (Gmail 전용) | IMAP/SMTP 범용 메일. 네이버웍스 등 확장 | skill-email 보완 |
| **blogwatcher** | skill-news 부분 유사 | RSS/블로그 구독 모니터링. 뉴스 이외 소스 커버 | skill-news 확장 |
| **session-logs** | self-inspect 부분 유사 | 크로스세션 검색, 토큰 비용 집계, 감사 | 신규 스킬 |
| **skill-creator** | 없음 | 스킬 자동 생성·패키징 가이드. 스킬 확장 속도 향상 | 메타 스킬 |
| **whisper/whisper-api** | 없음 | 음성→텍스트. 음성 메모/회의록 자동화 | 신규 스킬 |
### 중간 — 조건부 가치
| OpenClaw 스킬 | 조건 | 비고 |
|--------------|------|------|
| **notion/obsidian** | 사용자가 해당 도구 사용 시 높음 | skill-rag-file과 목적 다름 (읽기/쓰기 동기화 vs 검색) |
| **coding-agent** | 개발자 비중 높으면 높음 | 샌드박스·권한 거버넌스 필요 |
| **voice-call** | CS/알림 자동화 시 높음 | 규제·비용·남용 방지 설계 부담 |
| **trello** | 프로젝트 관리 연동 시 | API key 필요 |
| **gemini** | 멀티 LLM 전략 시 | 이미 skill-llm에서 부분 지원 |
| **weather** | web-search에 이미 포함 | 전용 API면 비용·안정성 이점 |
| **healthcheck** | 내부 운영용 (사용자 기능 아님) | OpenClaw 정의는 보안 감사 워크플로 |
| **tmux** | CLI 자동화 시 | 에이전트 오케스트레이션에 활용 가능 |
### 낮음 — 현재 불필요
스마트홈(openhue, sonoscli, eightctl, blucli), 엔터테인먼트(spotify, gifgrep, songsee), macOS 전용(apple-notes, apple-reminders, imsg, peekaboo, things-mac), SNS(xurl, wacli)
## 3. OpenClaw 문서화 패턴에서 배울 점
| 패턴 | OpenClaw 방식 | 로빙 현재 | 개선 방향 |
|------|-------------|----------|----------|
| YAML frontmatter | name, description, metadata.openclaw | 일부 스킬만 있음 | 전 스킬 통일 |
| requires 선언 | bins, config, anyBins 명시 | 없음 | SKILL.md에 requires 섹션 추가 |
| 설치 가이드 | brew/apt/npm 안내 포함 | 없음 | 신규 스킬 시 포함 |
| 입력 수집 항목 | 명시적 나열 | Do/Do Not 중심 | 입력 계약 명시화 |
## 4. 권장 다음 단계
1. **summarize 스킬 신설** — URL/유튜브 원샷 요약 (가장 높은 즉시 가치)
2. **SKILL.md에 requires 섹션** 추가 — OpenClaw 패턴 채택
3. **github 스킬** — Gitea 연동으로 커스터마이즈
4. **whisper 스킬** — 음성 메모/회의록 자동화

View File

@ -0,0 +1,41 @@
---
date: 2026-03-25
subject: Phase 1 구현 결과 — session-logs + blogwatcher
writer: 24-claude (총괄)
---
# Phase 1 구현 결과
## 생성된 파일
| 파일 | 작성자 | 리뷰어 | 상태 |
|------|--------|--------|------|
| `rb8001/app/router/session_logs_endpoint.py` | 24-Cursor | 24-Codex | 완료 (날짜 검증 추가) |
| `rb8001/app/state/session_logs_repository.py` | 24-Cursor | 24-Codex | 완료 |
| `DOCS/skills/session-logs/SKILL.md` | 24-Codex | 24-Gemini | 완료 (섹션 통일) |
| `skill_news/app/services/rss_service.py` | 24-Cursor-B | 24-Cursor | 완료 (원자 쓰기 추가) |
| `skill_news/app/api/rss_endpoints.py` | 24-Cursor-B | 24-Cursor | 완료 (HTTPException 재전파) |
| `DOCS/skills/blogwatcher/SKILL.md` | 24-Gemini | 24-Gemini | 완료 |
| `DOCS/skills/SKILL.md` (인덱스) | 총괄 | - | 업데이트 완료 |
## 리뷰 지적 및 반영
| 지적 | 원칙 | 반영 |
|------|------|------|
| 날짜 범위 오류 → 0건 반환 | coding-principles §3 실패 의미 보존 | 400 에러 반환으로 변경 |
| SKILL.md 섹션 순서 불일치 | project-artifacts-ssot §3 | skill-email 패턴 통일 |
| HTTPException 재전파 누락 | coding-principles §3 | except HTTPException: raise 추가 |
| JSON 동시성 | coding-principles §5 관측 가능성 | 원자 쓰기 (tempfile + os.replace) |
| 블로킹 I/O 미위임 | 기존 패턴 일관성 | asyncio.to_thread 추가 |
## 남은 작업 (Phase 1 미완료)
- [ ] rb8001 main.py에 session_logs_router 등록
- [ ] skill-news main.py에 rss_router 등록
- [ ] feedparser 패키지 설치 (skill-news 컨테이너)
- [ ] rb8001/skill-news 재시작 후 헬스체크
- [ ] tool_registry SKILL_DIR_ALLOWLIST에 session-logs, blogwatcher 추가
## SSOT 이상 발견
- `DOCS/skills/SKILL.md` 11행: SSOT 링크 경로가 `02_Governance`로 되어 있음 (정확한 경로: `20_Governance`). 수정 필요.

View File

@ -0,0 +1,37 @@
---
date: 2026-03-25
subject: Phase 2 구현 결과 — summarize + whisper
writer: 24-claude (총괄)
---
# Phase 2 구현 결과
## 생성된 서비스
### skill-summarize (포트 8516)
| 파일 | 작성자 | 리뷰어 |
|------|--------|--------|
| main.py, Dockerfile, docker-compose.yml | 24-Cursor | 24-Codex |
| app/core/config.py | 24-Cursor | 24-Codex |
| app/api/summarize_endpoints.py | 24-Cursor | 24-Codex |
| app/services/summarize_service.py | 24-Cursor | 24-Codex |
| DOCS/skills/summarize/SKILL.md | 24-Gemini | - |
### skill-whisper (포트 8517)
| 파일 | 작성자 | 리뷰어 |
|------|--------|--------|
| main.py, Dockerfile, docker-compose.yml | 24-Codex | 24-Cursor |
| app/core/config.py | 24-Codex | 24-Cursor |
| app/api/whisper_endpoints.py | 24-Codex | 24-Cursor |
| app/services/whisper_service.py | 24-Codex | 24-Cursor |
| DOCS/skills/whisper/SKILL.md | 24-Gemini | - |
## 리뷰 지적 및 반영
| 지적 | 서비스 | 반영 |
|------|--------|------|
| compose environment 하드코딩 | 양쪽 | 포트/호스트 제거, env_file에서 주입 |
| load_dotenv + env_file 중복 | summarize | load_dotenv 제거 |
| str(e) 예외 노출 | summarize | "Internal server error"로 변경 |
| file.read() 전체 메모리 | whisper | 1MB 청크 읽기 + 누적 크기 체크 |
| 임시파일 삭제 실패 → 500 | whisper | logger.warning만 (raise 제거) |

View File

@ -0,0 +1,19 @@
---
date: 2026-03-25
subject: Phase 3 구현 결과 — skill-gitea
writer: 24-claude (총괄)
---
# Phase 3 구현 결과
## skill-gitea (포트 8518)
| 파일 | 작성자 | 리뷰어 |
|------|--------|--------|
| main.py, Dockerfile, docker-compose.yml | 24-Cursor | 24-Codex |
| app/api/gitea_endpoints.py | 24-Cursor | 24-Codex → 24-Gemini (수정) |
| app/services/gitea_service.py | 24-Cursor | 24-Codex |
| DOCS/skills/gitea/SKILL.md | 24-Codex | - |
## 리뷰 반영
- detail=str(e) → 'Internal server error' (5곳, 24-Gemini 수정)

View File

@ -8,7 +8,7 @@ tags: [robeing, skills, ssot]
로빙이 사용할 수 있는 스킬 목록과 각 스킬의 역할·트리거를 요약합니다. 의도 분석 시 이 문서를 컨텍스트로 활용할 수 있습니다.
- **SSOT**: [project-artifacts-ssot.md](/home/admin/0_VALUE/02_Governance/project-artifacts-ssot.md) — 스킬 문서는 `DOCS/skills/{skill-name}/SKILL.md` 규칙 준수
- **SSOT**: [project-artifacts-ssot.md](/home/admin/0_VALUE/20_Governance/project-artifacts-ssot.md) — 스킬 문서는 `DOCS/skills/{skill-name}/SKILL.md` 규칙 준수
## 스킬 목록 (링크)
@ -26,6 +26,14 @@ tags: [robeing, skills, ssot]
| **github-analyze** | (내장) | GitHub 레포 분석·코드 리뷰(읽기)·구조·커밋 히스토리 | [github-analyze/SKILL.md](github-analyze/SKILL.md) |
| **github-manage** | (내장) | PR·이슈·브랜치 등 GitHub 호스팅 관리 | [github-manage/SKILL.md](github-manage/SKILL.md) |
| **git-ops** | (내장) | git clone/pull/push/commit 실행 | [git-ops/SKILL.md](git-ops/SKILL.md) |
| **skill-translate** | (내장) | 언어 번역 및 변환 | [skill-translate/SKILL.md](skill-translate/SKILL.md) |
| **session-logs** | (내장, 8001) | 과거 대화 검색·토큰 비용 집계 | [session-logs/SKILL.md](session-logs/SKILL.md) |
| **blogwatcher** | (skill-news, 8505) | RSS/블로그 피드 구독·새 글 모니터링 | [blogwatcher/SKILL.md](blogwatcher/SKILL.md) |
| **summarize** | 8516 | URL/유튜브/텍스트 요약 | [summarize/SKILL.md](summarize/SKILL.md) |
| **whisper** | 8517 | 음성→텍스트 변환 | [whisper/SKILL.md](whisper/SKILL.md) |
| **gitea** | 8518 | Gitea 레포/이슈/PR 관리 | [gitea/SKILL.md](gitea/SKILL.md) |
| **himalaya** | (skill-email, 8501) | IMAP/SMTP 범용 메일 (Gmail 외) | [himalaya/SKILL.md](himalaya/SKILL.md) |
| **skill-creator** | (스크립트) | 새 스킬 서비스 스캐폴딩 | [skill-creator/SKILL.md](skill-creator/SKILL.md) |
## 의도 → 스킬 매핑 (요약)
@ -44,6 +52,14 @@ tags: [robeing, skills, ssot]
| 실시간 웹 검색 (날씨/주가/환율/시세/뉴스) | web-search |
| 사용자 정보/시간/날짜/자기 코드/드래프트/과거 대화 | self-inspect |
| 일반 대화·정보 질의 | skill-llm (내장) |
| 번역 및 언어 변환 | skill-translate |
| 과거 대화 검색·토큰 비용 확인 | session-logs |
| RSS/블로그 구독·새 글 확인 | blogwatcher (skill-news) |
| URL/유튜브/텍스트 요약 | summarize |
| 음성 파일 텍스트 변환 | whisper |
| Gitea 이슈/PR/레포 관리 | gitea (provider=gitea) |
| GitHub 이슈/PR/레포 관리 | gitea (provider=github) |
| IMAP/SMTP 메일 (Gmail 외) | himalaya (skill-email) |
## 상세 스킬 문서
@ -51,5 +67,5 @@ tags: [robeing, skills, ssot]
## 관련 문서
- [project-artifacts-ssot.md](/home/admin/0_VALUE/02_Governance/project-artifacts-ssot.md)
- [project-artifacts-ssot.md](/home/admin/0_VALUE/20_Governance/project-artifacts-ssot.md)
- [robeing DOCS 구조](/home/admin/robeing/DOCS/)

View File

@ -0,0 +1,36 @@
---
name: blogwatcher
description: RSS/블로그 피드 구독 및 새 글 모니터링. 사용자가 "블로그 구독해줘", "RSS 추가해", "새 글 있어?" 등 피드 관련 요청을 할 때 사용.
---
# blogwatcher
RSS 및 블로그 피드 구독 관리 스킬.
## Trigger
- `rss_subscribe`: RSS 추가, 블로그 구독
- `blog_watch`: 피드 확인, 새 글 모니터링
- "블로그 구독", "RSS 추가", "피드 확인"
## Do
- 피드 URL 파싱 및 유효성 검사
- 구독 리스트 관리 (추가/조회)
- 정기적인 새 글 업데이트 확인 및 알림
## Do Not
- 전체 기사 본문 무단 크롤링 금지
- 저작권 침해 소지가 있는 대량 복제 금지
## API
- `POST /api/rss/parse` - 피드 URL 파싱
- `POST /api/rss/subscribe` - 피드 구독 추가
- `GET /api/rss/subscriptions` - 구독 목록 조회
- `GET /api/rss/latest` - 최신 피드 아이템 조회
## 환경변수
- `SKILL_NEWS_URL` (base_url)

56
skills/gitea/SKILL.md Normal file
View File

@ -0,0 +1,56 @@
---
name: gitea
description: Gitea/GitHub 레포/이슈/PR 관리. "이슈 만들어", "PR 목록", "GitHub 레포" 등 Git 호스팅 관련 요청 시 사용. provider 파라미터로 gitea/github 전환.
---
# gitea
Gitea 저장소, 이슈, PR 조회 및 생성용 스킬.
## Trigger
- `git_issue`: 이슈 조회, 이슈 만들어
- `git_pr`: PR 조회, PR 목록
- "PR 목록", "이슈 만들어", "레포 목록"
- "GitHub 이슈", "GitHub PR", "깃허브 레포"
- provider=gitea (기본) 또는 provider=github
## Do
- 레포 목록 조회
- 이슈 조회 및 생성
- PR 조회
## Do Not
- force push 수행 금지
- 브랜치 삭제 금지
- 직접 코드 수정 금지
## API
base_url_env: SKILL_GITEA_URL
routes:
list_repos:
method: GET
path: /api/gitea/repos
list_issues:
method: GET
path: /api/gitea/issues
create_issue:
method: POST
path: /api/gitea/issues
list_pulls:
method: GET
path: /api/gitea/pulls
get_pull:
method: GET
path: /api/gitea/pulls/{number}
## 환경변수
- `SKILL_GITEA_URL`
- `GITEA_URL`
- `GITEA_TOKEN`
- `GITHUB_URL` (기본: https://api.github.com)
- `GITHUB_TOKEN`

View File

@ -1,10 +1,15 @@
---
name: goosefarm-query
<<<<<<< HEAD
description: GooseFarm Investing 백엔드(배당·금·부동산·환율·암호화폐·M2) 데이터 조회. "배당 귀족주", "금 시세 분석", "서울 부동산 워터플로우", "환율", "비트코인 지표", "M2 통화량" 등 GooseFarm 도메인 질의 시 사용.
=======
description: 배당주, 아파트, 금, 환율, M2, 암호화폐 등 자산 데이터를 GooseFarm API에서 조회하여 답변
>>>>>>> 15fe2f3 (docs: 신규 스킬 7개 SKILL.md + 원칙 문서 중복 제거 + 구현 결과 문서)
---
# goosefarm-query
<<<<<<< HEAD
rb8001 `GooseFarmQueryService``GOOSEFARM_API_URL`(기본 `http://192.168.0.100:8200`)로 HTTP 조회합니다.
## Trigger
@ -33,3 +38,43 @@ rb8001 `GooseFarmQueryService`가 `GOOSEFARM_API_URL`(기본 `http://192.168.0.1
- `GET /api/market/forex/list`
- `GET /api/crypto/assets`
- `GET /api/market/m2/list`, `GET /api/market/m2/{country}/analysis`
=======
GooseFarm 공개 API로 자산·시장 데이터를 조회해 수치 기반으로 답하는 스킬.
## Trigger
배당, 배당주, 배당 귀족주, 배당 성장률, CAGR, 아파트, 부동산, 전세, 매매, 서울 아파트, 금, 금값, 금 시세, 환율, 달러, 엔화, 원달러, M2, 통화량, 암호화폐, 비트코인, 이더리움, 저평가, 고평가, 배당수익률
## Do
- GooseFarm API(`goosefarminvesting.com/api`)를 호출하여 실제 데이터 기반 답변
- 의도에 맞는 엔드포인트 선택 (배당→`/api/dividends`, 금→`/api/gold`, 부동산→`/api/realestate` 등)
- 수치를 포함한 구체적 답변
- 데이터 기준일 명시
## Do Not
- GooseFarm API 없이 일반 지식으로만 답변하지 않는다
- 임의 수치를 만들어내지 않는다
- 데이터가 없는 경우 없다고 명시한다
## API
| 의도 | 엔드포인트 | 파라미터 |
|---|---|---|
| 배당 귀족주 목록 | GET /api/dividends/aristocrats | sector, min_yield |
| 종목 배당 이력 | GET /api/dividends/{ticker}/history | |
| 배당 분석 | GET /api/dividends/{ticker}/advanced-analysis | |
| 금 자산 | GET /api/gold/assets | |
| 금 분석 | GET /api/gold/{ticker}/analysis | start_year |
| 환율 목록 | GET /api/market/forex/list | |
| 환율 시계열 | GET /api/market/forex/{base}/{target}/timeseries | days |
| M2 분석 | GET /api/market/m2/{country}/analysis | |
| 아파트 일괄 분석 | GET /api/realestate/analysis/batch | |
| 지역별 분석 | GET /api/realestate/{region_code}/analysis | |
| 암호화폐 목록 | GET /api/crypto/assets | |
## 환경변수
- `GOOSEFARM_API_URL=https://goosefarminvesting.com` — 기본 호스트; 실제 요청 경로는 `{GOOSEFARM_API_URL}` + 위 표의 경로(예: `/api/gold/assets`)
>>>>>>> 15fe2f3 (docs: 신규 스킬 7개 SKILL.md + 원칙 문서 중복 제거 + 구현 결과 문서)

36
skills/himalaya/SKILL.md Normal file
View File

@ -0,0 +1,36 @@
---
name: himalaya
description: IMAP/SMTP 범용 메일 (Gmail 외). 회사·네이버웍스 등 일반 메일함 조회·전송 시 skill-email 확장 경로로 사용.
---
# himalaya
skill-email에 IMAP/SMTP(himalaya 계열) 연동을 붙일 때의 의도·환경 기준. Gmail OAuth 전용 흐름과 구분.
## Trigger
- `imap_read`: IMAP으로 수신함·메일 목록 조회
- `smtp_send`: SMTP로 메일 전송
- 네이버웍스 메일, 회사 메일 등 **Gmail OAuth가 아닌** 일반 메일함
## Do
- IMAP 메일 조회
- SMTP 전송
- 기존 skill-email HTTP API(`SKILL_EMAIL_URL`) 확장 시나리오에 맞춰 호출
## Do Not
- Gmail OAuth·Pub/Sub Push 전용 경로와 **동일 요청으로 충돌**시키지 않음 (provider·의도 분리)
- IMAP/SMTP 자격증명을 로그·응답 본문에 노출하지 않음
## API
- `base_url_env`: `SKILL_EMAIL_URL` (skill-email 베이스 URL; IMAP/SMTP 확장은 동일 서비스에서 엔드포인트 추가를 전제)
- 현행 skill-email 참고: `POST /send`, `GET /messages` 등 — IMAP/SMTP 추가 시 SSOT 문서·OpenAPI와 함께 갱신
## 환경변수
- `IMAP_HOST`, `IMAP_PORT`
- `SMTP_HOST`, `SMTP_PORT`
- `IMAP_USER`, `IMAP_PASSWORD`

View File

@ -0,0 +1,40 @@
---
name: session-logs
description: 세션 로그 검색과 비용 조회. 사용자가 이전에 한 말이나 대화 이력을 찾고 싶을 때, 세션 비용이나 토큰 사용량을 확인하고 싶을 때 사용.
---
# Session Logs
세션 로그와 비용 정보를 조회하는 스킬.
## Trigger
- 세션 검색: "session_search", "저번에 뭐라 했지", "이전에 뭐라고 했어?", "지난 대화 찾아줘"
- 비용 조회: "cost_check", "토큰 얼마 썼어", "비용 얼마나 나왔어?", "이번 세션 비용 보여줘"
## Do
- 이전 대화나 사용자 발화를 찾는 요청이면 세션 검색 API로 조회한다.
- 비용이나 토큰 사용량 요청이면 세션 비용 API로 조회한다.
- 조회 결과가 없으면 없다고 명확히 답한다.
## Do Not
- 추측으로 과거 대화나 비용을 만들어 답하지 않는다.
- `BRAIN_SERVICE_URL`이 없는데 임의 주소로 호출하지 않는다.
- 로그 원문에 비밀값이 포함되어 있으면 그대로 노출하지 않는다.
## API
- `base_url_env`: `BRAIN_SERVICE_URL`
- `GET /api/sessions/search`
- `GET /api/sessions/cost`
## 환경변수
- `BRAIN_SERVICE_URL` — rb8001(브레인) 베이스 URL; 위 API 경로의 호스트
## Requires
requires:
config: ["BRAIN_SERVICE_URL"]

View File

@ -0,0 +1,30 @@
---
name: skill-creator
description: 새 스킬 서비스 디렉터리·FastAPI 스캐폴드 생성. 개발자 전용 CLI 스크립트(create_skill.sh).
---
# skill-creator
`skill-summarize` 레이아웃을 복사해 `skill-{name}/``DOCS/skills/{name}/SKILL.md` 초안을 만든다.
## Trigger
- 새 마이크로서비스 스킬 추가
- 로컬에서 skill 레포 구조를 빠르게 맞출 때
## Do
- `/home/admin/robeing/scripts/create_skill.sh <skill-name> <port>` 실행
- 생성 후 `app/api`, `app/services`, OpenAPI 설명·의도 문서를 실제 기능에 맞게 수정
## Do Not
- 운영 비밀값·토큰을 스크립트나 생성 파일에 넣지 않음
- 스캐폴드를 그대로 두고 프로덕션 배포로 간주하지 않음
## 스크립트
- 경로: `/home/admin/robeing/scripts/create_skill.sh`
- 인자: 스킬 이름(소문자·하이픈 권장), 포트(정수)
- Python 모듈·파일명은 하이픈을 밑줄로 치환함(예: `my-skill``my_skill_endpoints.py`)
- 출력: `robeing/skill-{name}/`(main.py, `app/core|api|services/`, Dockerfile, docker-compose.yml, requirements.txt, .gitignore), `DOCS/skills/{name}/SKILL.md`

View File

@ -1,6 +1,10 @@
---
name: skill-translate
<<<<<<< HEAD
description: Translate text between languages. Triggers on 번역해줘, translate this, 영어로 바꿔줘, ~를 한국어로.
=======
description: Translate text between languages. Triggers on requests like 번역해줘, translate this, 영어로 바꿔줘, ~를 한국어로, etc.
>>>>>>> 15fe2f3 (docs: 신규 스킬 7개 SKILL.md + 원칙 문서 중복 제거 + 구현 결과 문서)
---
# skill-translate
## Trigger
@ -9,7 +13,11 @@ description: Translate text between languages. Triggers on 번역해줘, transla
## Do
- Translate the given text to the target language
- Preserve formatting and tone
<<<<<<< HEAD
- Support: Korean, English, Japanese, Chinese
=======
- Support: Korean, English, Japanese, Chinese at minimum
>>>>>>> 15fe2f3 (docs: 신규 스킬 7개 SKILL.md + 원칙 문서 중복 제거 + 구현 결과 문서)
## Do Not
- Do not add explanations unless asked
- Do not modify the original meaning

35
skills/summarize/SKILL.md Normal file
View File

@ -0,0 +1,35 @@
---
name: summarize
description: URL/유튜브/텍스트 요약. 사용자가 "이 링크 요약해줘", "유튜브 요약", "텍스트 요약해" 등 요약 관련 요청을 할 때 사용.
---
# summarize
URL, 유튜브, 일반 텍스트 요약 스킬.
## Trigger
- `summarize_url`: URL 링크 내용 요약
- `youtube_summary`: 유튜브 영상 자막 및 내용 요약
- "이 링크 요약", "유튜브 요약" 등 자연어 요청
## Do
- URL 기반 웹 페이지 크롤링 및 요약
- 유튜브 영상 자막 추출 및 요약
- 대용량 텍스트 요약
## Do Not
- 저작권 침해 소지가 있는 유료 기사/콘텐츠 우회
- 전체 본문 무단 복사 및 노출
## API
- `POST /api/summarize/url` - URL 요약
- `POST /api/summarize/youtube` - 유튜브 요약
- `POST /api/summarize/text` - 텍스트 요약
## 환경변수
- `SKILL_SUMMARIZE_URL`

34
skills/whisper/SKILL.md Normal file
View File

@ -0,0 +1,34 @@
---
name: whisper
description: 음성 파일을 텍스트로 변환. 사용자가 "음성 파일 텍스트로", "회의록 작성해줘", "전사해줘" 등 음성 인식 요청을 할 때 사용.
---
# whisper
음성 인식 및 텍스트 전사 스킬.
## Trigger
- `transcribe`: 음성 파일 전사 요청
- `voice_to_text`: 음성 데이터를 텍스트로 변환
- "음성 파일 텍스트로", "회의록" 등 자연어 요청
## Do
- 업로드된 음성 파일 전사
- 오디오 URL 기반 음성 전사
## Do Not
- 실시간 스트리밍 음성 전사 (파일 기반만 지원)
- 타인의 음성 무단 전사 및 도용
## API
- `POST /api/whisper/transcribe` - 파일 기반 전사
- `POST /api/whisper/transcribe-url` - URL 기반 전사
## 환경변수
- `SKILL_WHISPER_URL`
- `OPENAI_API_KEY`