# github_service_request 워크플로우

## 목적
GitHub 관련 의도(`github_analyze`, `github_manage`, `git_ops`)를 하나의 서비스 계약으로 묶는다. `github_service.py`는 LLM이 SKILL.md 기반으로 분류한 intent와 slots를 받아, 분석/관리/실행을 위험도 기준으로 처리한다.

## 흐름
```text
Webhook In -> Normalize Payload -> Validate Intent/Slots -> Risk Gate
                                                   -> (github_analyze) Analyze Target
                                                   -> (github_manage) Manage GitHub Resource
                                                   -> (git_ops) Run Git Operation
                                                   -> Return Result
```

## 주요 노드
| 노드 | 설명 |
|---|---|
| Webhook In | `POST /skills/github/request` 수신 |
| Normalize Payload | intent, slots, user_id, channel, robeing_id 정규화 |
| Validate Intent/Slots | `github_analyze`, `github_manage`, `git_ops`만 허용. `target_url`, `repo`, `action`, `risk_level`, `requires_confirmation` 확인 |
| Risk Gate | `risk_level`과 `requires_confirmation`으로 실행 가능 여부 판정 |
| Analyze Target | 읽기 전용 GitHub 분석. repo/PR/issue/blob/tree 요약, 코드 리뷰 초안 |
| Manage GitHub Resource | PR/Issue/Branch 메타 작업 |
| Run Git Operation | clone/status/log/diff/pull/commit/push 등 git 명령 실행 |
| Return Result | 실행 결과 또는 확인 요청 반환 |

## `github_service.py` 인터페이스 계약

### 핵심 함수 시그니처
```python
async def execute_github_intent(
    *,
    intent: str,
    slots: dict[str, object],
    user_id: str,
    channel: str,
    robeing_id: str = "rb8001",
) -> dict[str, object]:
    ...

async def analyze_target(
    *,
    target_url: str | None,
    repo: str | None,
    resource_type: str,
    action: str,
    user_id: str,
) -> dict[str, object]:
    ...

async def manage_resource(
    *,
    repo: str,
    resource_type: str,
    action: str,
    slots: dict[str, object],
    user_id: str,
) -> dict[str, object]:
    ...

async def run_git_operation(
    *,
    repo: str | None,
    action: str,
    slots: dict[str, object],
    user_id: str,
) -> dict[str, object]:
    ...

def evaluate_risk(
    *,
    intent: str,
    action: str,
    slots: dict[str, object],
) -> dict[str, object]:
    ...
```

### slots 계약
- `target_url`: GitHub URL. repo/blob/tree/pull/issue/commit 중 하나
- `repo`: `owner/name`
- `resource_type`: `repo|pull|issue|commit|blob|tree|branch`
- `action`: `summarize|review|history|clone|status|diff|pull|commit|push|create_pr|comment_pr|close_issue`
- `risk_level`: `low|medium|high|critical`
- `requires_confirmation`: `true|false`
- `branch`: 선택
- `pr_number`, `issue_number`, `commit_sha`, `path`: 리소스별 선택

### 안전 계약
- `low`: 자동 실행 가능. 읽기/분석/조회
- `medium`: 로컬 변경 가능. 원격 반영 전 확인 필요
- `high`: push, merge, close, delete 계열. 확인 필수
- `critical`: `push --force`, `reset --hard`, branch delete, release delete. 기본 거부

## 인바운드 payload 예시
```json
{
  "intent": "github_analyze",
  "slots": {
    "target_url": "https://github.com/owner/repo",
    "repo": "owner/repo",
    "resource_type": "repo",
    "action": "summarize",
    "risk_level": "low",
    "requires_confirmation": false
  },
  "user_id": "uuid",
  "channel": "slack",
  "robeing_id": "rb8001"
}
```

## 엔드포인트
- 인바운드: `POST /skills/github/request`
- 내부 실행: `github_service.py`

## 적용 기준
- 1차 분류 기준은 `DOCS/skills/{skill-name}/SKILL.md`
- 이 워크플로우는 LLM이 분류한 intent를 실행하는 계약이다
- 정규식 예외, URL 화이트리스트, command 하드코딩으로 intent를 덮어쓰지 않는다

## 관련 문서
- [skill_calendar_request](./skill_calendar_request.md)
- [skill_email_send_request](./skill_email_send_request.md)
- [../README.md](../README.md)
