@elyun/bylane 1.16.0 → 1.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +262 -121
- package/commands/bylane-cleanup.md +36 -0
- package/commands/bylane-code-agent.md +3 -24
- package/commands/bylane-commit-agent.md +3 -19
- package/commands/bylane-issue-agent.md +1 -1
- package/commands/bylane-notify-agent.md +1 -1
- package/commands/bylane-orchestrator.md +4 -23
- package/commands/bylane-pr-agent.md +2 -2
- package/commands/bylane-respond-agent.md +22 -31
- package/commands/bylane-respond-loop.md +6 -18
- package/commands/bylane-review-agent.md +112 -120
- package/commands/bylane-review-loop.md +6 -17
- package/commands/bylane-test-agent.md +1 -1
- package/package.json +1 -1
- package/src/cleanup.js +152 -0
- package/src/cli.js +39 -0
- package/src/monitor/index.js +96 -1
- package/src/monitor/layout.js +1 -1
- package/src/respond-loop.js +1 -1
- package/src/review-loop.js +1 -1
- package/templates/review-template.md +17 -47
|
@@ -19,19 +19,11 @@ description: byLane 메인 오케스트레이터. 자연어 의도를 파싱해
|
|
|
19
19
|
각 에이전트 실행 전 사용할 모델을 config에서 읽는다:
|
|
20
20
|
|
|
21
21
|
```bash
|
|
22
|
-
|
|
23
|
-
import('./src/config.js').then(({loadConfig, getAgentModel}) => {
|
|
24
|
-
const config = loadConfig()
|
|
25
|
-
const agents = [
|
|
26
|
-
'orchestrator','issue-agent','code-agent','test-agent',
|
|
27
|
-
'commit-agent','pr-agent','review-agent','respond-agent','notify-agent'
|
|
28
|
-
]
|
|
29
|
-
agents.forEach(a => console.log(a + ': ' + getAgentModel(config, a)))
|
|
30
|
-
// analyze-agent는 항상 opus 사용 (config 무관)
|
|
31
|
-
})
|
|
32
|
-
"
|
|
22
|
+
npx @elyun/bylane models
|
|
33
23
|
```
|
|
34
24
|
|
|
25
|
+
출력 형식: `AGENT_NAME=MODEL_ID` (한 줄씩)
|
|
26
|
+
|
|
35
27
|
에이전트 호출 시 해당 모델을 `model` 파라미터로 전달한다.
|
|
36
28
|
|
|
37
29
|
## 의도 파싱 규칙
|
|
@@ -57,18 +49,7 @@ import('./src/config.js').then(({loadConfig, getAgentModel}) => {
|
|
|
57
49
|
|
|
58
50
|
상태 기록 (각 에이전트 시작 전):
|
|
59
51
|
```bash
|
|
60
|
-
|
|
61
|
-
import('./src/state.js').then(({writeState}) => {
|
|
62
|
-
writeState('AGENT_NAME', {
|
|
63
|
-
status: 'in_progress',
|
|
64
|
-
startedAt: new Date().toISOString(),
|
|
65
|
-
progress: 0,
|
|
66
|
-
currentTask: 'TASK_DESCRIPTION',
|
|
67
|
-
retries: 0,
|
|
68
|
-
log: []
|
|
69
|
-
})
|
|
70
|
-
})
|
|
71
|
-
"
|
|
52
|
+
npx @elyun/bylane state write AGENT_NAME '{"status":"in_progress","startedAt":"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'","progress":0,"currentTask":"TASK_DESCRIPTION","retries":0,"log":[]}'
|
|
72
53
|
```
|
|
73
54
|
|
|
74
55
|
## 피드백 루프
|
|
@@ -43,7 +43,7 @@ ls .github/PULL_REQUEST_TEMPLATE/*.md 2>/dev/null | head -5
|
|
|
43
43
|
## 실행 전 상태 기록
|
|
44
44
|
|
|
45
45
|
```bash
|
|
46
|
-
|
|
46
|
+
npx @elyun/bylane state write pr-agent '{"status":"in_progress","startedAt":"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'","progress":0,"retries":0,"log":[]}'
|
|
47
47
|
```
|
|
48
48
|
|
|
49
49
|
## 실행 흐름
|
|
@@ -90,7 +90,7 @@ node -e "import('./src/state.js').then(({writeState})=>writeState('pr-agent',{st
|
|
|
90
90
|
|
|
91
91
|
4. 상태 업데이트:
|
|
92
92
|
```bash
|
|
93
|
-
|
|
93
|
+
npx @elyun/bylane state write pr-agent '{"status":"completed","progress":100,"prNumber":PR_NUMBER,"prUrl":"PR_URL"}'
|
|
94
94
|
```
|
|
95
95
|
|
|
96
96
|
## 출력
|
|
@@ -16,9 +16,9 @@ description: PR 리뷰 코멘트에 반박하거나 코드를 수정하여 반
|
|
|
16
16
|
| `"api"` | REST API + `$GITHUB_TOKEN` |
|
|
17
17
|
| `"auto"` (기본) | MCP → CLI → API 순서로 시도 |
|
|
18
18
|
|
|
19
|
-
##
|
|
19
|
+
## 대응 템플릿 탐지
|
|
20
20
|
|
|
21
|
-
답글 작성 전 프로젝트 내
|
|
21
|
+
답글 작성 전 프로젝트 내 템플릿을 탐색한다:
|
|
22
22
|
|
|
23
23
|
```bash
|
|
24
24
|
ls .github/REVIEW_RESPONSE_TEMPLATE.md \
|
|
@@ -26,9 +26,7 @@ ls .github/REVIEW_RESPONSE_TEMPLATE.md \
|
|
|
26
26
|
.github/CONTRIBUTING.md 2>/dev/null | head -1
|
|
27
27
|
```
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
- `CONTRIBUTING.md`가 있으면 코드 기여 가이드라인을 참고하여 대응 톤/형식을 맞춘다.
|
|
31
|
-
- 없으면 기본 형식으로 작성한다.
|
|
29
|
+
템플릿이 있으면 답글 형식을 따른다. 없으면 간결하게 작성한다.
|
|
32
30
|
|
|
33
31
|
## 입력
|
|
34
32
|
|
|
@@ -39,28 +37,25 @@ ls .github/REVIEW_RESPONSE_TEMPLATE.md \
|
|
|
39
37
|
|
|
40
38
|
| 모드 | 동작 |
|
|
41
39
|
|---|---|
|
|
42
|
-
| `auto` (
|
|
40
|
+
| `auto` (기본, 미지정 시) | 각 코멘트를 분석하여 수정 반영 또는 반박을 자동 판단 후 진행 |
|
|
43
41
|
| `accept` | 모든 코멘트를 수정 반영 |
|
|
44
42
|
| `rebut` | 모든 코멘트에 반박 |
|
|
45
|
-
| `manual` | 코멘트별로 사용자에게
|
|
43
|
+
| `manual` | 코멘트별로 사용자에게 선택 요청 |
|
|
46
44
|
|
|
47
45
|
### auto 모드 판단 기준
|
|
48
46
|
|
|
49
|
-
각 코멘트를 분석하여:
|
|
50
47
|
- **반영**: 버그 지적, 명확한 컨벤션 위반, 테스트 누락, 성능 문제
|
|
51
|
-
- **반박**: 의견 차이,
|
|
48
|
+
- **반박**: 의견 차이, 의도된 설계, 스펙 요구사항과 일치하는 경우
|
|
52
49
|
|
|
53
|
-
|
|
50
|
+
실행 전 요약을 먼저 보여주고 확인 후 진행:
|
|
54
51
|
```
|
|
55
52
|
코멘트 #1: [반영] null 체크 누락 → 코드 수정
|
|
56
53
|
코멘트 #2: [반박] 의도된 설계 (이슈 #12 참조)
|
|
57
|
-
코멘트 #3: [반영] 타입 오류
|
|
58
54
|
진행할까요? (y/n)
|
|
59
55
|
```
|
|
60
56
|
|
|
61
57
|
### manual 모드
|
|
62
58
|
|
|
63
|
-
각 코멘트를 보여주고 사용자에게 선택을 요청:
|
|
64
59
|
```
|
|
65
60
|
[코멘트 #1] null 체크가 없습니다.
|
|
66
61
|
→ (1) 수정 반영 (2) 반박 (3) 건너뜀
|
|
@@ -69,15 +64,14 @@ ls .github/REVIEW_RESPONSE_TEMPLATE.md \
|
|
|
69
64
|
## 실행 전 상태 기록
|
|
70
65
|
|
|
71
66
|
```bash
|
|
72
|
-
|
|
67
|
+
npx @elyun/bylane state write respond-agent '{"status":"in_progress","startedAt":"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'","progress":0,"retries":0,"log":[]}'
|
|
73
68
|
```
|
|
74
69
|
|
|
75
70
|
## 실행 흐름
|
|
76
71
|
|
|
77
72
|
### 리뷰 코멘트 로드
|
|
78
73
|
|
|
79
|
-
**MCP:**
|
|
80
|
-
→ GitHub MCP `list_review_comments` 도구 사용
|
|
74
|
+
**MCP:** → `list_review_comments` 도구 사용
|
|
81
75
|
|
|
82
76
|
**CLI:**
|
|
83
77
|
```bash
|
|
@@ -91,16 +85,12 @@ curl -s \
|
|
|
91
85
|
https://api.github.com/repos/OWNER/REPO/pulls/PR_NUMBER/comments
|
|
92
86
|
```
|
|
93
87
|
|
|
94
|
-
### accept
|
|
88
|
+
### 수정 반영 (accept)
|
|
95
89
|
|
|
96
|
-
1.
|
|
97
|
-
2.
|
|
98
|
-
3. test-agent로 검증
|
|
99
|
-
4. commit-agent로 수정 커밋 (`fix: address review comments`)
|
|
100
|
-
5. 코멘트에 "반영 완료" 답글 게시:
|
|
90
|
+
1. 코드 수정 후 커밋 (`fix: address review comments`)
|
|
91
|
+
2. 해당 코멘트에 짧은 답글 게시:
|
|
101
92
|
|
|
102
|
-
**MCP:**
|
|
103
|
-
→ GitHub MCP `create_review_comment_reply` 도구 사용
|
|
93
|
+
**MCP:** → `create_review_comment_reply` 사용
|
|
104
94
|
|
|
105
95
|
**CLI:**
|
|
106
96
|
```bash
|
|
@@ -116,13 +106,14 @@ curl -s \
|
|
|
116
106
|
-d '{"body":"REPLY_BODY"}'
|
|
117
107
|
```
|
|
118
108
|
|
|
119
|
-
### rebut
|
|
109
|
+
### 반박 (rebut)
|
|
120
110
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
111
|
+
근거를 간결하게 기술한 답글 작성:
|
|
112
|
+
- 의도적 설계 결정: 배경 한 줄 설명
|
|
113
|
+
- 스펙 요구사항과 일치: 이슈 링크 첨부
|
|
114
|
+
- 성능 트레이드오프: 수치 근거
|
|
115
|
+
|
|
116
|
+
답글은 짧고 명확하게. 불필요한 서두 없이 핵심만.
|
|
126
117
|
|
|
127
118
|
## 출력
|
|
128
119
|
|
|
@@ -132,7 +123,7 @@ curl -s \
|
|
|
132
123
|
"agent": "respond-agent",
|
|
133
124
|
"status": "completed",
|
|
134
125
|
"progress": 100,
|
|
135
|
-
"mode": "
|
|
126
|
+
"mode": "auto",
|
|
136
127
|
"resolvedComments": 3,
|
|
137
128
|
"needsMoreWork": false
|
|
138
129
|
}
|
|
@@ -140,4 +131,4 @@ curl -s \
|
|
|
140
131
|
|
|
141
132
|
## 수동 실행
|
|
142
133
|
|
|
143
|
-
`/bylane respond #45`
|
|
134
|
+
`/bylane respond #45`
|
|
@@ -30,15 +30,12 @@ echo "폴러 PID: $!"
|
|
|
30
30
|
pending PR이 생길 때마다 respond-agent를 실행한다:
|
|
31
31
|
|
|
32
32
|
```bash
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
const q = readState('respond-queue', '.bylane/state')
|
|
36
|
-
const pending = (q?.queue ?? []).filter(p => p.status === 'pending')
|
|
37
|
-
console.log(JSON.stringify(pending))
|
|
38
|
-
})
|
|
39
|
-
"
|
|
33
|
+
# 큐 확인 (pending 항목 필터링)
|
|
34
|
+
npx @elyun/bylane state read respond-queue
|
|
40
35
|
```
|
|
41
36
|
|
|
37
|
+
출력된 JSON에서 `queue` 배열의 `status === "pending"` 항목을 선택한다.
|
|
38
|
+
|
|
42
39
|
pending 항목이 있으면 각 PR에 대해:
|
|
43
40
|
|
|
44
41
|
1. `hasChangesRequested` 여부 확인:
|
|
@@ -50,17 +47,8 @@ pending 항목이 있으면 각 PR에 대해:
|
|
|
50
47
|
3. 완료 후 큐 항목을 `status: "responded"`로 업데이트:
|
|
51
48
|
|
|
52
49
|
```bash
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
const q = readState('respond-queue', '.bylane/state')
|
|
56
|
-
const queue = (q?.queue ?? []).map(p =>
|
|
57
|
-
p.number === PR_NUMBER
|
|
58
|
-
? { ...p, status: 'responded', respondedAt: new Date().toISOString() }
|
|
59
|
-
: p
|
|
60
|
-
)
|
|
61
|
-
writeState('respond-queue', { status: 'running', queue }, '.bylane/state')
|
|
62
|
-
})
|
|
63
|
-
"
|
|
50
|
+
# 현재 큐 읽기 후 PR_NUMBER 항목을 responded로 업데이트하여 다시 쓰기
|
|
51
|
+
npx @elyun/bylane state write respond-queue '{"status":"running","queue":UPDATED_QUEUE_JSON}'
|
|
64
52
|
```
|
|
65
53
|
|
|
66
54
|
4. 다음 pending 항목으로 반복. pending 없으면 5분 대기 후 재확인 (폴러 주기와 동일).
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: bylane-review-agent
|
|
3
|
-
description: PR의 diff를 분석하여 코드 리뷰 코멘트를 작성한다.
|
|
3
|
+
description: PR의 diff를 분석하여 코드 라인별 인라인 리뷰 코멘트를 작성한다.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Review Agent
|
|
@@ -28,35 +28,7 @@ ls .github/REVIEW_TEMPLATE.md \
|
|
|
28
28
|
```
|
|
29
29
|
|
|
30
30
|
GitHub 템플릿이 있으면 해당 형식을 **최우선**으로 따른다.
|
|
31
|
-
없으면
|
|
32
|
-
|
|
33
|
-
## 리뷰 템플릿 로드
|
|
34
|
-
|
|
35
|
-
실행 전 `.bylane/bylane.json`의 `review` 설정 읽기:
|
|
36
|
-
|
|
37
|
-
```bash
|
|
38
|
-
node -e "
|
|
39
|
-
import('./src/config.js').then(({loadConfig}) => {
|
|
40
|
-
const c = loadConfig()
|
|
41
|
-
console.log(JSON.stringify(c.review, null, 2))
|
|
42
|
-
})
|
|
43
|
-
"
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
설정 항목:
|
|
47
|
-
- `model` — 리뷰에 사용할 모델 (기본: `claude-sonnet-4-6`)
|
|
48
|
-
- `language` — 리뷰 언어 (기본: `ko`)
|
|
49
|
-
- `includeModel` — 푸터에 모델명 포함 여부
|
|
50
|
-
- `includeCodeExample` — Before/After 코드 예시 포함 여부
|
|
51
|
-
- `templateFile` — 커스텀 템플릿 파일 경로 (비어있으면 `templates/review-template.md` 사용)
|
|
52
|
-
- `severityEmoji` — 심각도 레이블 커스터마이즈
|
|
53
|
-
- `footer` — 푸터 문자열 (`{model}`, `{date}` 치환 가능)
|
|
54
|
-
|
|
55
|
-
커스텀 템플릿이 있으면 로드:
|
|
56
|
-
```bash
|
|
57
|
-
# templateFile이 설정된 경우
|
|
58
|
-
cat TEMPLATE_FILE_PATH
|
|
59
|
-
```
|
|
31
|
+
없으면 `templates/review-template.md`를 사용한다.
|
|
60
32
|
|
|
61
33
|
## 검사 항목 선택
|
|
62
34
|
|
|
@@ -88,108 +60,128 @@ Enter 또는 아무것도 선택하지 않으면 → `all` (전체 검사)
|
|
|
88
60
|
|
|
89
61
|
| 항목 | 중점 확인 사항 |
|
|
90
62
|
|---|---|
|
|
91
|
-
| `grammar` | 오탈자, 주석 언어 일관성, 변수/함수명
|
|
63
|
+
| `grammar` | 오탈자, 주석 언어 일관성, 변수/함수명 문법 |
|
|
92
64
|
| `domain` | 비즈니스 규칙 위반, 도메인 용어 오용, 로직 정합성 |
|
|
93
65
|
| `code` | 컨벤션 위반, 중복 코드, 복잡도, 불변성, 테스트 커버리지 |
|
|
94
|
-
| `security` | 시크릿 노출, SQL/XSS 인젝션, 인증·인가
|
|
66
|
+
| `security` | 시크릿 노출, SQL/XSS 인젝션, 인증·인가 누락 |
|
|
95
67
|
| `all` | 위 4가지 전체 |
|
|
96
68
|
|
|
97
|
-
|
|
69
|
+
## 실행 전 상태 기록
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
npx @elyun/bylane state write review-agent '{"status":"in_progress","startedAt":"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'","progress":0,"retries":0,"log":[]}'
|
|
98
73
|
```
|
|
99
|
-
|
|
74
|
+
|
|
75
|
+
## 실행 흐름
|
|
76
|
+
|
|
77
|
+
### 1. PR diff 로드
|
|
78
|
+
|
|
79
|
+
**MCP:**
|
|
80
|
+
→ `get_pull_request_files` + `get_pull_request` 도구 사용
|
|
81
|
+
|
|
82
|
+
**CLI:**
|
|
83
|
+
```bash
|
|
84
|
+
gh pr diff PR_NUMBER
|
|
85
|
+
gh pr view PR_NUMBER --json files,headRefName,baseRefName
|
|
100
86
|
```
|
|
101
87
|
|
|
102
|
-
|
|
88
|
+
**API:**
|
|
89
|
+
```bash
|
|
90
|
+
curl -s \
|
|
91
|
+
-H "Authorization: Bearer $GITHUB_TOKEN" \
|
|
92
|
+
https://api.github.com/repos/OWNER/REPO/pulls/PR_NUMBER/files
|
|
93
|
+
```
|
|
103
94
|
|
|
104
|
-
|
|
95
|
+
### 2. 파일별 분석
|
|
105
96
|
|
|
106
|
-
|
|
97
|
+
선택된 검사 항목 범위에서 각 변경 파일 분석:
|
|
98
|
+
- 버그 가능성 (null check, 경계값, 예외 처리)
|
|
99
|
+
- 타입 오류 (TypeScript)
|
|
100
|
+
- 성능 이슈
|
|
101
|
+
- 컨벤션 위반
|
|
102
|
+
- 보안 취약점
|
|
103
|
+
|
|
104
|
+
### 3. 인라인 코멘트 작성 (라인별 개별 등록)
|
|
105
|
+
|
|
106
|
+
**핵심 원칙: 모든 지적사항은 해당 코드 라인에 직접 코멘트로 등록한다.**
|
|
107
|
+
|
|
108
|
+
코멘트 본문 형식:
|
|
109
|
+
```
|
|
110
|
+
{제목}
|
|
111
|
+
|
|
112
|
+
{설명}
|
|
107
113
|
|
|
114
|
+
```suggestion
|
|
115
|
+
{수정 제안 코드 (해당 라인 전체 대체)}
|
|
116
|
+
```
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
- suggestion 블록은 수정 제안이 명확한 경우에만 포함
|
|
120
|
+
- 한 코멘트에 한 가지 지적사항만 담는다
|
|
121
|
+
- 검사 범위가 지정된 경우 첫 코멘트 또는 요약에 명시: `> 검사 범위: code, security`
|
|
122
|
+
|
|
123
|
+
#### 인라인 코멘트 등록 방법
|
|
124
|
+
|
|
125
|
+
**MCP:**
|
|
126
|
+
→ `create_review` 도구의 `comments` 배열에 각 항목 포함
|
|
127
|
+
|
|
128
|
+
**CLI (파일별 개별 등록):**
|
|
108
129
|
```bash
|
|
109
|
-
|
|
130
|
+
# diff의 position 값 또는 line 번호 사용
|
|
131
|
+
gh api repos/OWNER/REPO/pulls/PR_NUMBER/reviews \
|
|
132
|
+
--method POST \
|
|
133
|
+
--field body="" \
|
|
134
|
+
--field event="COMMENT" \
|
|
135
|
+
--field "comments[][path]=파일경로" \
|
|
136
|
+
--field "comments[][line]=라인번호" \
|
|
137
|
+
--field "comments[][body]=코멘트 본문"
|
|
110
138
|
```
|
|
111
139
|
|
|
112
|
-
|
|
140
|
+
여러 코멘트는 `comments[]` 배열에 모두 담아 **한 번의 review 요청**으로 제출한다.
|
|
141
|
+
|
|
142
|
+
**API:**
|
|
143
|
+
```bash
|
|
144
|
+
curl -s -X POST \
|
|
145
|
+
-H "Authorization: Bearer $GITHUB_TOKEN" \
|
|
146
|
+
-H "Content-Type: application/json" \
|
|
147
|
+
https://api.github.com/repos/OWNER/REPO/pulls/PR_NUMBER/reviews \
|
|
148
|
+
-d '{
|
|
149
|
+
"body": "요약 코멘트",
|
|
150
|
+
"event": "COMMENT",
|
|
151
|
+
"comments": [
|
|
152
|
+
{
|
|
153
|
+
"path": "src/foo.js",
|
|
154
|
+
"line": 42,
|
|
155
|
+
"body": "코멘트 본문 (suggestion 포함 가능)"
|
|
156
|
+
}
|
|
157
|
+
]
|
|
158
|
+
}'
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
`event` 값: 지적사항이 있으면 `"REQUEST_CHANGES"`, 없으면 `"APPROVE"`, 코멘트만이면 `"COMMENT"`
|
|
113
162
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
- 코딩 컨벤션 위반
|
|
137
|
-
- 테스트 커버리지 누락
|
|
138
|
-
|
|
139
|
-
3. 코멘트 작성 규칙 (템플릿 적용):
|
|
140
|
-
|
|
141
|
-
각 코멘트 형식:
|
|
142
|
-
```
|
|
143
|
-
{severityEmoji.SEVERITY} {title}
|
|
144
|
-
|
|
145
|
-
{description}
|
|
146
|
-
|
|
147
|
-
[includeCodeExample=true인 경우]
|
|
148
|
-
**Before:**
|
|
149
|
-
```lang
|
|
150
|
-
// 문제 코드
|
|
151
|
-
```
|
|
152
|
-
**After:**
|
|
153
|
-
```lang
|
|
154
|
-
// 개선 코드
|
|
155
|
-
```
|
|
156
|
-
|
|
157
|
-
{suggestion}
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
리뷰 언어(`language`)에 맞게 작성. `ko`이면 한국어, `en`이면 영어.
|
|
161
|
-
|
|
162
|
-
4. 전체 요약 생성:
|
|
163
|
-
- 심각도별 건수 표
|
|
164
|
-
- 주요 발견사항
|
|
165
|
-
- 종합 의견
|
|
166
|
-
- 푸터: `review.footer`의 `{model}`을 실제 모델명으로, `{date}`를 현재 날짜로 치환
|
|
167
|
-
|
|
168
|
-
5. 리뷰 제출 (CRITICAL/HIGH 없으면 `APPROVE`, 있으면 `REQUEST_CHANGES`):
|
|
169
|
-
|
|
170
|
-
**MCP:**
|
|
171
|
-
→ GitHub MCP `create_review` 도구 사용
|
|
172
|
-
|
|
173
|
-
**CLI:**
|
|
174
|
-
```bash
|
|
175
|
-
gh pr review PR_NUMBER --approve --body "REVIEW_BODY"
|
|
176
|
-
# 또는
|
|
177
|
-
gh pr review PR_NUMBER --request-changes --body "REVIEW_BODY"
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
**API:**
|
|
181
|
-
```bash
|
|
182
|
-
curl -s -X POST \
|
|
183
|
-
-H "Authorization: Bearer $GITHUB_TOKEN" \
|
|
184
|
-
-H "Content-Type: application/json" \
|
|
185
|
-
https://api.github.com/repos/OWNER/REPO/pulls/PR_NUMBER/reviews \
|
|
186
|
-
-d '{"body":"REVIEW_BODY","event":"APPROVE","comments":[]}'
|
|
187
|
-
```
|
|
188
|
-
|
|
189
|
-
6. 상태 업데이트:
|
|
190
|
-
```bash
|
|
191
|
-
node -e "import('./src/state.js').then(({writeState})=>writeState('review-agent',{status:'completed',progress:100,approved:APPROVED_BOOL,commentCount:COMMENT_COUNT}))"
|
|
192
|
-
```
|
|
163
|
+
### 4. 전체 요약 (PR 전체 코멘트)
|
|
164
|
+
|
|
165
|
+
```
|
|
166
|
+
## 리뷰 요약
|
|
167
|
+
|
|
168
|
+
> 검사 범위: {scope}
|
|
169
|
+
|
|
170
|
+
### 주요 발견사항
|
|
171
|
+
- ...
|
|
172
|
+
|
|
173
|
+
### 종합 의견
|
|
174
|
+
...
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
푸터: `review.footer`의 `{model}`을 실제 모델명으로, `{date}`를 현재 날짜로 치환.
|
|
178
|
+
기본 푸터: `{model} · {date}` (bylane 문구 없음)
|
|
179
|
+
|
|
180
|
+
### 5. 상태 업데이트
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
npx @elyun/bylane state write review-agent '{"status":"completed","progress":100,"approved":APPROVED_BOOL,"commentCount":COMMENT_COUNT}'
|
|
184
|
+
```
|
|
193
185
|
|
|
194
186
|
## 출력
|
|
195
187
|
|
|
@@ -199,8 +191,8 @@ node -e "import('./src/state.js').then(({writeState})=>writeState('review-agent'
|
|
|
199
191
|
"agent": "review-agent",
|
|
200
192
|
"status": "completed",
|
|
201
193
|
"progress": 100,
|
|
202
|
-
"approved":
|
|
203
|
-
"commentCount":
|
|
194
|
+
"approved": false,
|
|
195
|
+
"commentCount": 5
|
|
204
196
|
}
|
|
205
197
|
```
|
|
206
198
|
|
|
@@ -47,30 +47,19 @@ node src/review-loop.js
|
|
|
47
47
|
아래 루프를 실행하면서 pending PR이 생길 때마다 review-agent를 실행한다:
|
|
48
48
|
|
|
49
49
|
```bash
|
|
50
|
-
# 큐 확인
|
|
51
|
-
|
|
52
|
-
import('./src/state.js').then(({readState}) => {
|
|
53
|
-
const q = readState('review-queue', '.bylane/state')
|
|
54
|
-
const pending = (q?.queue ?? []).filter(p => p.status === 'pending')
|
|
55
|
-
console.log(JSON.stringify(pending))
|
|
56
|
-
})
|
|
57
|
-
"
|
|
50
|
+
# 큐 확인 (pending 항목 필터링)
|
|
51
|
+
npx @elyun/bylane state read review-queue
|
|
58
52
|
```
|
|
59
53
|
|
|
54
|
+
출력된 JSON에서 `queue` 배열의 `status === "pending"` 항목을 선택한다.
|
|
55
|
+
|
|
60
56
|
pending 항목이 있으면 각 PR에 대해:
|
|
61
57
|
1. `bylane-review-agent` skill 실행 (PR 번호 전달)
|
|
62
58
|
2. 리뷰 완료 후 큐 항목을 `status: "reviewed"`로 업데이트:
|
|
63
59
|
|
|
64
60
|
```bash
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
const q = readState('review-queue', '.bylane/state')
|
|
68
|
-
const queue = (q?.queue ?? []).map(p =>
|
|
69
|
-
p.number === PR_NUMBER ? { ...p, status: 'reviewed', reviewedAt: new Date().toISOString() } : p
|
|
70
|
-
)
|
|
71
|
-
writeState('review-queue', { status: 'running', queue }, '.bylane/state')
|
|
72
|
-
})
|
|
73
|
-
"
|
|
61
|
+
# 현재 큐 읽기 후 PR_NUMBER 항목을 reviewed로 업데이트하여 다시 쓰기
|
|
62
|
+
npx @elyun/bylane state write review-queue '{"status":"running","queue":UPDATED_QUEUE_JSON}'
|
|
74
63
|
```
|
|
75
64
|
|
|
76
65
|
3. 다음 pending 항목으로 반복
|
|
@@ -12,7 +12,7 @@ description: 변경된 코드의 테스트를 실행하고 결과를 반환한
|
|
|
12
12
|
## 실행 전 상태 기록
|
|
13
13
|
|
|
14
14
|
```bash
|
|
15
|
-
|
|
15
|
+
npx @elyun/bylane state write test-agent '{"status":"in_progress","startedAt":"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'","progress":0,"retries":0,"log":[]}'
|
|
16
16
|
```
|
|
17
17
|
|
|
18
18
|
## 실행 흐름
|