From 886bd42ae341dcfc49c7fc4908b93a0589182b41 Mon Sep 17 00:00:00 2001 From: happybell80 Date: Thu, 26 Mar 2026 01:21:10 +0900 Subject: [PATCH] =?UTF-8?q?docs:=20=EC=8B=A0=EA=B7=9C=20=EC=8A=A4=ED=82=AC?= =?UTF-8?q?=207=EA=B0=9C=20SKILL.md=20+=20=EC=9B=90=EC=B9=99=20=EB=AC=B8?= =?UTF-8?q?=EC=84=9C=20=EC=A4=91=EB=B3=B5=20=EC=A0=9C=EA=B1=B0=20+=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=20=EA=B2=B0=EA=B3=BC=20=EB=AC=B8=EC=84=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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) --- .../311_backend_coding_principles.md | 65 ++---- .../314_infrastructure-ssot-principle.md | 59 ++---- book/300_architecture/315_테스트_원칙.md | 195 +++++++----------- ...6_evaluation_empty_response_and_polling.md | 40 ++++ .../260326_ir_eval_empty_response_resolved.md | 59 ++++++ .../260326_principle_improvements.md | 33 +++ skills/260325_all_phases_final_result.md | 95 +++++++++ skills/260325_integration_test_result.md | 49 +++++ .../260325_new_skills_implementation_plan.md | 133 ++++++++++++ skills/260325_openclaw_skill_comparison.md | 68 ++++++ skills/260325_phase1_result.md | 41 ++++ skills/260325_phase2_result.md | 37 ++++ skills/260325_phase3_result.md | 19 ++ skills/SKILL.md | 20 +- skills/blogwatcher/SKILL.md | 36 ++++ skills/gitea/SKILL.md | 56 +++++ skills/goosefarm-query/SKILL.md | 45 ++++ skills/himalaya/SKILL.md | 36 ++++ skills/session-logs/SKILL.md | 40 ++++ skills/skill-creator/SKILL.md | 30 +++ skills/skill-translate/SKILL.md | 8 + skills/summarize/SKILL.md | 35 ++++ skills/whisper/SKILL.md | 34 +++ 23 files changed, 1023 insertions(+), 210 deletions(-) create mode 100644 journey/troubleshooting/260326_evaluation_empty_response_and_polling.md create mode 100644 journey/troubleshooting/260326_ir_eval_empty_response_resolved.md create mode 100644 journey/troubleshooting/260326_principle_improvements.md create mode 100644 skills/260325_all_phases_final_result.md create mode 100644 skills/260325_integration_test_result.md create mode 100644 skills/260325_new_skills_implementation_plan.md create mode 100644 skills/260325_openclaw_skill_comparison.md create mode 100644 skills/260325_phase1_result.md create mode 100644 skills/260325_phase2_result.md create mode 100644 skills/260325_phase3_result.md create mode 100644 skills/blogwatcher/SKILL.md create mode 100644 skills/gitea/SKILL.md create mode 100644 skills/himalaya/SKILL.md create mode 100644 skills/session-logs/SKILL.md create mode 100644 skills/skill-creator/SKILL.md create mode 100644 skills/summarize/SKILL.md create mode 100644 skills/whisper/SKILL.md diff --git a/book/300_architecture/311_backend_coding_principles.md b/book/300_architecture/311_backend_coding_principles.md index d68601e..457cb10 100644 --- a/book/300_architecture/311_backend_coding_principles.md +++ b/book/300_architecture/311_backend_coding_principles.md @@ -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. 리팩토링 시 로직 상실 방지 원칙 diff --git a/book/300_architecture/314_infrastructure-ssot-principle.md b/book/300_architecture/314_infrastructure-ssot-principle.md index 636089f..c3414a4 100644 --- a/book/300_architecture/314_infrastructure-ssot-principle.md +++ b/book/300_architecture/314_infrastructure-ssot-principle.md @@ -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 변수로 선언합니다. diff --git a/book/300_architecture/315_테스트_원칙.md b/book/300_architecture/315_테스트_원칙.md index 4fb8d8c..d38dd6b 100644 --- a/book/300_architecture/315_테스트_원칙.md +++ b/book/300_architecture/315_테스트_원칙.md @@ -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` diff --git a/journey/troubleshooting/260326_evaluation_empty_response_and_polling.md b/journey/troubleshooting/260326_evaluation_empty_response_and_polling.md new file mode 100644 index 0000000..2e7e598 --- /dev/null +++ b/journey/troubleshooting/260326_evaluation_empty_response_and_polling.md @@ -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: 프런트 수정 diff --git a/journey/troubleshooting/260326_ir_eval_empty_response_resolved.md b/journey/troubleshooting/260326_ir_eval_empty_response_resolved.md new file mode 100644 index 0000000..9e9cfd5 --- /dev/null +++ b/journey/troubleshooting/260326_ir_eval_empty_response_resolved.md @@ -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 토큰으로 정상 완료 diff --git a/journey/troubleshooting/260326_principle_improvements.md b/journey/troubleshooting/260326_principle_improvements.md new file mode 100644 index 0000000..7647478 --- /dev/null +++ b/journey/troubleshooting/260326_principle_improvements.md @@ -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 | diff --git a/skills/260325_all_phases_final_result.md b/skills/260325_all_phases_final_result.md new file mode 100644 index 0000000..336b086 --- /dev/null +++ b/skills/260325_all_phases_final_result.md @@ -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 | 수정 완료 | diff --git a/skills/260325_integration_test_result.md b/skills/260325_integration_test_result.md new file mode 100644 index 0000000..6238163 --- /dev/null +++ b/skills/260325_integration_test_result.md @@ -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를 덮어쓰게 만들지 않는다. diff --git a/skills/260325_new_skills_implementation_plan.md b/skills/260325_new_skills_implementation_plan.md new file mode 100644 index 0000000..e169e9c --- /dev/null +++ b/skills/260325_new_skills_implementation_plan.md @@ -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 | 메타 도구, 급하지 않음 | diff --git a/skills/260325_openclaw_skill_comparison.md b/skills/260325_openclaw_skill_comparison.md new file mode 100644 index 0000000..f33cde9 --- /dev/null +++ b/skills/260325_openclaw_skill_comparison.md @@ -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 스킬** — 음성 메모/회의록 자동화 diff --git a/skills/260325_phase1_result.md b/skills/260325_phase1_result.md new file mode 100644 index 0000000..1065930 --- /dev/null +++ b/skills/260325_phase1_result.md @@ -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`). 수정 필요. diff --git a/skills/260325_phase2_result.md b/skills/260325_phase2_result.md new file mode 100644 index 0000000..fe2d37d --- /dev/null +++ b/skills/260325_phase2_result.md @@ -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 제거) | diff --git a/skills/260325_phase3_result.md b/skills/260325_phase3_result.md new file mode 100644 index 0000000..7b0892c --- /dev/null +++ b/skills/260325_phase3_result.md @@ -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 수정) diff --git a/skills/SKILL.md b/skills/SKILL.md index b383791..4f3e618 100644 --- a/skills/SKILL.md +++ b/skills/SKILL.md @@ -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/) diff --git a/skills/blogwatcher/SKILL.md b/skills/blogwatcher/SKILL.md new file mode 100644 index 0000000..46c7188 --- /dev/null +++ b/skills/blogwatcher/SKILL.md @@ -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) diff --git a/skills/gitea/SKILL.md b/skills/gitea/SKILL.md new file mode 100644 index 0000000..966f067 --- /dev/null +++ b/skills/gitea/SKILL.md @@ -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` diff --git a/skills/goosefarm-query/SKILL.md b/skills/goosefarm-query/SKILL.md index d4e0a84..7cb0fe8 100644 --- a/skills/goosefarm-query/SKILL.md +++ b/skills/goosefarm-query/SKILL.md @@ -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 + 원칙 문서 중복 제거 + 구현 결과 문서) diff --git a/skills/himalaya/SKILL.md b/skills/himalaya/SKILL.md new file mode 100644 index 0000000..f66029a --- /dev/null +++ b/skills/himalaya/SKILL.md @@ -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` diff --git a/skills/session-logs/SKILL.md b/skills/session-logs/SKILL.md new file mode 100644 index 0000000..c2a0b21 --- /dev/null +++ b/skills/session-logs/SKILL.md @@ -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"] diff --git a/skills/skill-creator/SKILL.md b/skills/skill-creator/SKILL.md new file mode 100644 index 0000000..20b6be5 --- /dev/null +++ b/skills/skill-creator/SKILL.md @@ -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 ` 실행 +- 생성 후 `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` diff --git a/skills/skill-translate/SKILL.md b/skills/skill-translate/SKILL.md index a9e9f87..de07881 100644 --- a/skills/skill-translate/SKILL.md +++ b/skills/skill-translate/SKILL.md @@ -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 diff --git a/skills/summarize/SKILL.md b/skills/summarize/SKILL.md new file mode 100644 index 0000000..5cde92e --- /dev/null +++ b/skills/summarize/SKILL.md @@ -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` diff --git a/skills/whisper/SKILL.md b/skills/whisper/SKILL.md new file mode 100644 index 0000000..37cd65f --- /dev/null +++ b/skills/whisper/SKILL.md @@ -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`