@elyun/bylane 1.2.0 → 1.4.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/.githooks/pre-commit +88 -0
- package/commands/bylane.md +4 -0
- package/package.json +4 -2
- package/scripts/release.sh +26 -0
- package/skills/issue-agent.md +61 -42
- package/skills/pr-agent.md +43 -24
- package/skills/respond-agent.md +54 -11
- package/skills/respond-loop.md +109 -0
- package/skills/review-agent.md +107 -18
- package/skills/review-loop.md +105 -0
- package/skills/setup.md +22 -0
- package/src/config.js +19 -0
- package/src/respond-loop.js +190 -0
- package/src/review-loop.js +137 -0
- package/templates/review-template.md +86 -0
- package/docs/superpowers/plans/2026-04-04-bylane-implementation.md +0 -1821
- package/docs/superpowers/specs/2026-04-04-bylane-design.md +0 -324
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# byLane pre-commit 보안 검사
|
|
3
|
+
|
|
4
|
+
RED='\033[0;31m'
|
|
5
|
+
YELLOW='\033[1;33m'
|
|
6
|
+
GREEN='\033[0;32m'
|
|
7
|
+
NC='\033[0m'
|
|
8
|
+
|
|
9
|
+
ERRORS=0
|
|
10
|
+
WARNINGS=0
|
|
11
|
+
|
|
12
|
+
echo "보안 검사 실행 중..."
|
|
13
|
+
|
|
14
|
+
# 스테이징된 파일 목록
|
|
15
|
+
STAGED=$(git diff --cached --name-only --diff-filter=ACMR)
|
|
16
|
+
|
|
17
|
+
if [ -z "$STAGED" ]; then
|
|
18
|
+
echo -e "${GREEN}스테이징된 파일 없음. 건너뜀.${NC}"
|
|
19
|
+
exit 0
|
|
20
|
+
fi
|
|
21
|
+
|
|
22
|
+
# 1. 민감한 파일명 패턴
|
|
23
|
+
SENSITIVE_FILES=$(echo "$STAGED" | grep -iE \
|
|
24
|
+
'\.env$|\.env\.|credentials|secrets|\.pem$|\.key$|\.p12$|\.pfx$|id_rsa|id_dsa|\.secret' \
|
|
25
|
+
|| true)
|
|
26
|
+
|
|
27
|
+
if [ -n "$SENSITIVE_FILES" ]; then
|
|
28
|
+
echo -e "${RED}[CRITICAL] 민감한 파일이 커밋에 포함되어 있습니다:${NC}"
|
|
29
|
+
echo "$SENSITIVE_FILES" | sed 's/^/ - /'
|
|
30
|
+
ERRORS=$((ERRORS + 1))
|
|
31
|
+
fi
|
|
32
|
+
|
|
33
|
+
# 2. 하드코딩된 시크릿 패턴
|
|
34
|
+
SECRET_PATTERNS=(
|
|
35
|
+
'AKIA[0-9A-Z]{16}' # AWS Access Key
|
|
36
|
+
'sk-[a-zA-Z0-9]{32,}' # OpenAI / Anthropic API Key
|
|
37
|
+
'ghp_[a-zA-Z0-9]{36}' # GitHub Personal Access Token
|
|
38
|
+
'ghs_[a-zA-Z0-9]{36}' # GitHub Actions Token
|
|
39
|
+
'xox[baprs]-[0-9a-zA-Z]{10,}' # Slack Token
|
|
40
|
+
'AIza[0-9A-Za-z_-]{35}' # Google API Key
|
|
41
|
+
'ya29\.[0-9A-Za-z_-]+' # Google OAuth Token
|
|
42
|
+
'Bearer [a-zA-Z0-9._-]{20,}' # Generic Bearer Token (긴 것만)
|
|
43
|
+
'password[[:space:]]*=[[:space:]]*"[^"]{6,}' # Hardcoded password (double quote)
|
|
44
|
+
"password[[:space:]]*=[[:space:]]*'[^']{6,}" # Hardcoded password (single quote)
|
|
45
|
+
'api_key[[:space:]]*[=:][[:space:]]*"[^"]{8,}' # Hardcoded API key
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
for pattern in "${SECRET_PATTERNS[@]}"; do
|
|
49
|
+
MATCHES=$(git diff --cached -U0 | grep '^+' | grep -v '^+++' | grep -iE "$pattern" || true)
|
|
50
|
+
if [ -n "$MATCHES" ]; then
|
|
51
|
+
echo -e "${RED}[CRITICAL] 하드코딩된 시크릿 의심 패턴 발견 (${pattern}):${NC}"
|
|
52
|
+
echo "$MATCHES" | head -3 | sed 's/^/ /'
|
|
53
|
+
ERRORS=$((ERRORS + 1))
|
|
54
|
+
fi
|
|
55
|
+
done
|
|
56
|
+
|
|
57
|
+
# 3. console.log (JS/TS 파일)
|
|
58
|
+
JS_FILES=$(echo "$STAGED" | grep -E '\.(js|ts|jsx|tsx)$' || true)
|
|
59
|
+
if [ -n "$JS_FILES" ]; then
|
|
60
|
+
CONSOLE_MATCHES=$(git diff --cached -U0 -- $JS_FILES | grep '^+' | grep -v '^+++' | grep 'console\.log' || true)
|
|
61
|
+
if [ -n "$CONSOLE_MATCHES" ]; then
|
|
62
|
+
echo -e "${YELLOW}[WARN] console.log 발견:${NC}"
|
|
63
|
+
echo "$CONSOLE_MATCHES" | head -3 | sed 's/^/ /'
|
|
64
|
+
WARNINGS=$((WARNINGS + 1))
|
|
65
|
+
fi
|
|
66
|
+
fi
|
|
67
|
+
|
|
68
|
+
# 4. node_modules 실수 커밋
|
|
69
|
+
NODE_MODULES=$(echo "$STAGED" | grep '^node_modules/' || true)
|
|
70
|
+
if [ -n "$NODE_MODULES" ]; then
|
|
71
|
+
echo -e "${RED}[CRITICAL] node_modules가 커밋에 포함되어 있습니다.${NC}"
|
|
72
|
+
ERRORS=$((ERRORS + 1))
|
|
73
|
+
fi
|
|
74
|
+
|
|
75
|
+
# 5. 결과 출력
|
|
76
|
+
echo ""
|
|
77
|
+
if [ $ERRORS -gt 0 ]; then
|
|
78
|
+
echo -e "${RED}보안 검사 실패: $ERRORS 개의 오류가 있습니다.${NC}"
|
|
79
|
+
echo "커밋이 차단되었습니다. 오류를 수정하세요."
|
|
80
|
+
echo "(검사를 건너뛰려면: git commit --no-verify)"
|
|
81
|
+
exit 1
|
|
82
|
+
elif [ $WARNINGS -gt 0 ]; then
|
|
83
|
+
echo -e "${YELLOW}경고: $WARNINGS 개의 주의 사항이 있습니다. 커밋은 계속됩니다.${NC}"
|
|
84
|
+
else
|
|
85
|
+
echo -e "${GREEN}보안 검사 통과.${NC}"
|
|
86
|
+
fi
|
|
87
|
+
|
|
88
|
+
exit 0
|
package/commands/bylane.md
CHANGED
|
@@ -17,7 +17,9 @@ description: byLane 메인 커맨드. 자연어로 전체 개발 워크플로우
|
|
|
17
17
|
/bylane commit
|
|
18
18
|
/bylane pr
|
|
19
19
|
/bylane review [PR번호]
|
|
20
|
+
/bylane review-loop — 5분 주기 자동 리뷰 루프 시작
|
|
20
21
|
/bylane respond [PR번호]
|
|
22
|
+
/bylane respond-loop — 5분 주기 자동 대응 루프 시작
|
|
21
23
|
/bylane notify
|
|
22
24
|
/bylane status — 현재 상태 한 줄 요약
|
|
23
25
|
```
|
|
@@ -37,7 +39,9 @@ description: byLane 메인 커맨드. 자연어로 전체 개발 워크플로우
|
|
|
37
39
|
| `commit` | `bylane-commit-agent` |
|
|
38
40
|
| `pr` | `bylane-pr-agent` |
|
|
39
41
|
| `review` | `bylane-review-agent` |
|
|
42
|
+
| `review-loop` | `bylane-review-loop` |
|
|
40
43
|
| `respond` | `bylane-respond-agent` |
|
|
44
|
+
| `respond-loop` | `bylane-respond-loop` |
|
|
41
45
|
| `notify` | `bylane-notify-agent` |
|
|
42
46
|
| `status` | `.bylane/state/` 파일 읽어 한 줄 요약 출력 |
|
|
43
47
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elyun/bylane",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "Frontend development harness for Claude Code",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -10,7 +10,9 @@
|
|
|
10
10
|
"scripts": {
|
|
11
11
|
"monitor": "node src/monitor/index.js",
|
|
12
12
|
"test": "vitest run",
|
|
13
|
-
"test:watch": "vitest"
|
|
13
|
+
"test:watch": "vitest",
|
|
14
|
+
"release": "bash scripts/release.sh",
|
|
15
|
+
"prepare": "git config core.hooksPath .githooks && chmod +x .githooks/pre-commit"
|
|
14
16
|
},
|
|
15
17
|
"dependencies": {
|
|
16
18
|
"blessed": "^0.1.81",
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
set -e
|
|
3
|
+
|
|
4
|
+
VERSION="v$(node -p "require('./package.json').version")"
|
|
5
|
+
|
|
6
|
+
echo "byLane npm 배포 시작: $VERSION"
|
|
7
|
+
|
|
8
|
+
# 작업 디렉토리 클린 확인 (untracked 파일 제외, 수정/스테이징된 파일만 체크)
|
|
9
|
+
DIRTY=$(git status --short | grep -v '^?' || true)
|
|
10
|
+
if [ -n "$DIRTY" ]; then
|
|
11
|
+
echo "오류: 커밋되지 않은 변경사항이 있습니다. 먼저 커밋하고 푸시하세요."
|
|
12
|
+
echo "$DIRTY"
|
|
13
|
+
exit 1
|
|
14
|
+
fi
|
|
15
|
+
|
|
16
|
+
# 테스트 실행
|
|
17
|
+
echo "테스트 실행 중..."
|
|
18
|
+
npm test
|
|
19
|
+
|
|
20
|
+
# npm 배포 (2FA 필요 시 프롬프트)
|
|
21
|
+
echo "npm 배포 중... (2FA 코드가 필요할 수 있습니다)"
|
|
22
|
+
npm publish --access public
|
|
23
|
+
|
|
24
|
+
echo ""
|
|
25
|
+
echo "배포 완료: $VERSION"
|
|
26
|
+
echo "https://www.npmjs.com/package/@elyun/bylane"
|
package/skills/issue-agent.md
CHANGED
|
@@ -5,6 +5,17 @@ description: GitHub Issue 생성 및 분석. Figma 링크 감지 시 스펙 추
|
|
|
5
5
|
|
|
6
6
|
# Issue Agent
|
|
7
7
|
|
|
8
|
+
## GitHub 접근 방법
|
|
9
|
+
|
|
10
|
+
`.bylane/bylane.json`의 `github.method` 확인:
|
|
11
|
+
|
|
12
|
+
| 값 | 동작 |
|
|
13
|
+
|----|------|
|
|
14
|
+
| `"mcp"` | GitHub MCP 도구 사용 |
|
|
15
|
+
| `"cli"` | `gh` CLI 사용 |
|
|
16
|
+
| `"api"` | REST API + `$GITHUB_TOKEN` |
|
|
17
|
+
| `"auto"` (기본) | MCP → CLI → API 순서로 시도 |
|
|
18
|
+
|
|
8
19
|
## 입력
|
|
9
20
|
|
|
10
21
|
- 자유 텍스트 (새 이슈 생성용) OR GitHub Issue 번호 (#N)
|
|
@@ -13,44 +24,65 @@ description: GitHub Issue 생성 및 분석. Figma 링크 감지 시 스펙 추
|
|
|
13
24
|
|
|
14
25
|
### 새 이슈 생성 모드 (텍스트 입력)
|
|
15
26
|
|
|
16
|
-
1. 입력 텍스트에서
|
|
17
|
-
- 제목 (50자 이내)
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
27
|
+
1. 입력 텍스트에서 추출:
|
|
28
|
+
- 제목 (50자 이내), 상세 설명, 구현 체크리스트, Figma URL
|
|
29
|
+
|
|
30
|
+
2. 이슈 생성:
|
|
31
|
+
|
|
32
|
+
**MCP:**
|
|
33
|
+
→ GitHub MCP `create_issue` 도구 사용
|
|
34
|
+
|
|
35
|
+
**CLI:**
|
|
36
|
+
```bash
|
|
37
|
+
gh issue create \
|
|
38
|
+
--title "TITLE" \
|
|
39
|
+
--body "BODY" \
|
|
40
|
+
--label "bylane-auto"
|
|
41
|
+
```
|
|
21
42
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
-
|
|
25
|
-
|
|
43
|
+
**API:**
|
|
44
|
+
```bash
|
|
45
|
+
curl -s -X POST \
|
|
46
|
+
-H "Authorization: Bearer $GITHUB_TOKEN" \
|
|
47
|
+
-H "Content-Type: application/json" \
|
|
48
|
+
https://api.github.com/repos/OWNER/REPO/issues \
|
|
49
|
+
-d '{"title":"TITLE","body":"BODY","labels":["bylane-auto"]}'
|
|
50
|
+
```
|
|
26
51
|
|
|
27
|
-
3. Figma MCP 활성화 여부 확인 (
|
|
28
|
-
- `true`이고 Figma URL
|
|
29
|
-
- `false
|
|
52
|
+
3. Figma MCP 활성화 여부 확인 (`extensions.figma.enabled`):
|
|
53
|
+
- `true`이고 Figma URL 있으면 → Figma 분석 단계 실행
|
|
54
|
+
- `false` → 텍스트 기반 스펙만 생성
|
|
30
55
|
|
|
31
56
|
### 기존 이슈 분석 모드 (Issue 번호 입력)
|
|
32
57
|
|
|
33
|
-
1.
|
|
34
|
-
2. 본문에서 Figma URL 추출 시도
|
|
35
|
-
3. 스펙 생성 (아래 참조)
|
|
58
|
+
1. 이슈 내용 로드:
|
|
36
59
|
|
|
37
|
-
|
|
60
|
+
**MCP:**
|
|
61
|
+
→ GitHub MCP `get_issue` 도구 사용
|
|
62
|
+
|
|
63
|
+
**CLI:**
|
|
64
|
+
```bash
|
|
65
|
+
gh issue view NUMBER --json title,body,labels
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
**API:**
|
|
69
|
+
```bash
|
|
70
|
+
curl -s \
|
|
71
|
+
-H "Authorization: Bearer $GITHUB_TOKEN" \
|
|
72
|
+
https://api.github.com/repos/OWNER/REPO/issues/NUMBER
|
|
73
|
+
```
|
|
38
74
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
- 타이포그래피
|
|
43
|
-
- 스페이싱 값
|
|
75
|
+
2. 본문에서 Figma URL 추출 시도 후 스펙 생성
|
|
76
|
+
|
|
77
|
+
### Figma 분석 (활성화된 경우)
|
|
44
78
|
|
|
45
|
-
|
|
79
|
+
Figma MCP `get_file` 또는 `get_node` 도구로 프레임/컴포넌트 분석.
|
|
46
80
|
|
|
47
|
-
|
|
48
|
-
- MCP 미설치 또는 URL 유효하지 않은 경우: 경고 로그 기록 후 텍스트 기반 스펙만 사용
|
|
49
|
-
- `figmaSpec.enabled = false`로 출력
|
|
81
|
+
**실패 시 fallback:** 경고 로그 후 텍스트 기반 스펙 사용
|
|
50
82
|
|
|
51
|
-
##
|
|
83
|
+
## 출력
|
|
52
84
|
|
|
53
|
-
`.bylane/state/issue-agent.json
|
|
85
|
+
`.bylane/state/issue-agent.json`:
|
|
54
86
|
|
|
55
87
|
```json
|
|
56
88
|
{
|
|
@@ -63,27 +95,14 @@ Figma MCP `get_file` 또는 `get_node` 도구로 해당 프레임/컴포넌트
|
|
|
63
95
|
"title": "다크모드 토글 버튼 추가",
|
|
64
96
|
"description": "...",
|
|
65
97
|
"checklist": ["ThemeToggle 컴포넌트 생성", "useTheme hook 구현"],
|
|
66
|
-
"figmaSpec": {
|
|
67
|
-
"enabled": false,
|
|
68
|
-
"components": [],
|
|
69
|
-
"colorTokens": {}
|
|
70
|
-
}
|
|
98
|
+
"figmaSpec": { "enabled": false, "components": [], "colorTokens": {} }
|
|
71
99
|
}
|
|
72
100
|
}
|
|
73
101
|
```
|
|
74
102
|
|
|
75
103
|
상태 기록:
|
|
76
104
|
```bash
|
|
77
|
-
node -e "
|
|
78
|
-
import('./src/state.js').then(({writeState, appendLog}) => {
|
|
79
|
-
writeState('issue-agent', {
|
|
80
|
-
status: 'in_progress',
|
|
81
|
-
startedAt: new Date().toISOString(),
|
|
82
|
-
progress: 0,
|
|
83
|
-
retries: 0
|
|
84
|
-
})
|
|
85
|
-
})
|
|
86
|
-
"
|
|
105
|
+
node -e "import('./src/state.js').then(({writeState})=>writeState('issue-agent',{status:'in_progress',startedAt:new Date().toISOString(),progress:0,retries:0}))"
|
|
87
106
|
```
|
|
88
107
|
|
|
89
108
|
## 수동 실행
|
package/skills/pr-agent.md
CHANGED
|
@@ -5,6 +5,17 @@ description: 현재 브랜치의 커밋들로 GitHub Pull Request를 생성한
|
|
|
5
5
|
|
|
6
6
|
# PR Agent
|
|
7
7
|
|
|
8
|
+
## GitHub 접근 방법
|
|
9
|
+
|
|
10
|
+
`.bylane/bylane.json`의 `github.method` 확인:
|
|
11
|
+
|
|
12
|
+
| 값 | 동작 |
|
|
13
|
+
|----|------|
|
|
14
|
+
| `"mcp"` | GitHub MCP 도구 사용 |
|
|
15
|
+
| `"cli"` | `gh` CLI 사용 |
|
|
16
|
+
| `"api"` | REST API + `$GITHUB_TOKEN` |
|
|
17
|
+
| `"auto"` (기본) | MCP → CLI → API 순서로 시도 |
|
|
18
|
+
|
|
8
19
|
## 입력
|
|
9
20
|
|
|
10
21
|
- `.bylane/state/commit-agent.json`의 `branchName`, `commitSha`
|
|
@@ -23,36 +34,44 @@ node -e "import('./src/state.js').then(({writeState})=>writeState('pr-agent',{st
|
|
|
23
34
|
git push -u origin BRANCH_NAME
|
|
24
35
|
```
|
|
25
36
|
|
|
26
|
-
2. PR
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
37
|
+
2. PR 본문 생성:
|
|
38
|
+
```
|
|
39
|
+
## Summary
|
|
40
|
+
- [변경 요약]
|
|
41
|
+
|
|
42
|
+
## Test Plan
|
|
43
|
+
- [ ] 변경된 기능 동작 확인
|
|
44
|
+
- [ ] 기존 테스트 통과 확인
|
|
45
|
+
|
|
46
|
+
Closes #ISSUE_NUMBER
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
3. PR 생성:
|
|
32
50
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
- [ ] 기존 테스트 통과 확인
|
|
51
|
+
**MCP:**
|
|
52
|
+
→ GitHub MCP `create_pull_request` 도구 사용
|
|
36
53
|
|
|
37
|
-
|
|
38
|
-
|
|
54
|
+
**CLI:**
|
|
55
|
+
```bash
|
|
56
|
+
gh pr create \
|
|
57
|
+
--title "TITLE" \
|
|
58
|
+
--body "BODY" \
|
|
59
|
+
--head BRANCH_NAME \
|
|
60
|
+
--base main
|
|
61
|
+
```
|
|
39
62
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
-
|
|
43
|
-
|
|
44
|
-
|
|
63
|
+
**API:**
|
|
64
|
+
```bash
|
|
65
|
+
curl -s -X POST \
|
|
66
|
+
-H "Authorization: Bearer $GITHUB_TOKEN" \
|
|
67
|
+
-H "Content-Type: application/json" \
|
|
68
|
+
https://api.github.com/repos/OWNER/REPO/pulls \
|
|
69
|
+
-d '{"title":"TITLE","body":"BODY","head":"BRANCH_NAME","base":"main"}'
|
|
70
|
+
```
|
|
45
71
|
|
|
46
72
|
4. 상태 업데이트:
|
|
47
73
|
```bash
|
|
48
|
-
node -e "
|
|
49
|
-
import('./src/state.js').then(({writeState})=>writeState('pr-agent',{
|
|
50
|
-
status:'completed',
|
|
51
|
-
progress:100,
|
|
52
|
-
prNumber:'PR_NUMBER',
|
|
53
|
-
prUrl:'PR_URL'
|
|
54
|
-
}))
|
|
55
|
-
"
|
|
74
|
+
node -e "import('./src/state.js').then(({writeState})=>writeState('pr-agent',{status:'completed',progress:100,prNumber:PR_NUMBER,prUrl:'PR_URL'}))"
|
|
56
75
|
```
|
|
57
76
|
|
|
58
77
|
## 출력
|
package/skills/respond-agent.md
CHANGED
|
@@ -5,6 +5,17 @@ description: PR 리뷰 코멘트에 반박하거나 코드를 수정하여 반
|
|
|
5
5
|
|
|
6
6
|
# Respond Agent
|
|
7
7
|
|
|
8
|
+
## GitHub 접근 방법
|
|
9
|
+
|
|
10
|
+
`.bylane/bylane.json`의 `github.method` 확인:
|
|
11
|
+
|
|
12
|
+
| 값 | 동작 |
|
|
13
|
+
|----|------|
|
|
14
|
+
| `"mcp"` | GitHub MCP 도구 사용 |
|
|
15
|
+
| `"cli"` | `gh` CLI 사용 |
|
|
16
|
+
| `"api"` | REST API + `$GITHUB_TOKEN` |
|
|
17
|
+
| `"auto"` (기본) | MCP → CLI → API 순서로 시도 |
|
|
18
|
+
|
|
8
19
|
## 입력
|
|
9
20
|
|
|
10
21
|
- PR 번호
|
|
@@ -18,23 +29,55 @@ node -e "import('./src/state.js').then(({writeState})=>writeState('respond-agent
|
|
|
18
29
|
|
|
19
30
|
## 실행 흐름
|
|
20
31
|
|
|
32
|
+
### 리뷰 코멘트 로드
|
|
33
|
+
|
|
34
|
+
**MCP:**
|
|
35
|
+
→ GitHub MCP `list_review_comments` 도구 사용
|
|
36
|
+
|
|
37
|
+
**CLI:**
|
|
38
|
+
```bash
|
|
39
|
+
gh pr view PR_NUMBER --json reviews,comments
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
**API:**
|
|
43
|
+
```bash
|
|
44
|
+
curl -s \
|
|
45
|
+
-H "Authorization: Bearer $GITHUB_TOKEN" \
|
|
46
|
+
https://api.github.com/repos/OWNER/REPO/pulls/PR_NUMBER/comments
|
|
47
|
+
```
|
|
48
|
+
|
|
21
49
|
### accept 모드
|
|
22
50
|
|
|
23
|
-
1.
|
|
24
|
-
2.
|
|
25
|
-
3.
|
|
26
|
-
4.
|
|
27
|
-
5.
|
|
28
|
-
|
|
51
|
+
1. 각 코멘트별 수정 사항 결정
|
|
52
|
+
2. 코드 수정 (code-agent 서브 실행)
|
|
53
|
+
3. test-agent로 검증
|
|
54
|
+
4. commit-agent로 수정 커밋 (`fix: address review comments`)
|
|
55
|
+
5. 코멘트에 "반영 완료" 답글 게시:
|
|
56
|
+
|
|
57
|
+
**MCP:**
|
|
58
|
+
→ GitHub MCP `create_review_comment_reply` 도구 사용
|
|
59
|
+
|
|
60
|
+
**CLI:**
|
|
61
|
+
```bash
|
|
62
|
+
gh pr comment PR_NUMBER --body "REPLY_BODY"
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
**API:**
|
|
66
|
+
```bash
|
|
67
|
+
curl -s -X POST \
|
|
68
|
+
-H "Authorization: Bearer $GITHUB_TOKEN" \
|
|
69
|
+
-H "Content-Type: application/json" \
|
|
70
|
+
https://api.github.com/repos/OWNER/REPO/issues/PR_NUMBER/comments \
|
|
71
|
+
-d '{"body":"REPLY_BODY"}'
|
|
72
|
+
```
|
|
29
73
|
|
|
30
74
|
### rebut 모드
|
|
31
75
|
|
|
32
|
-
1.
|
|
33
|
-
|
|
34
|
-
-
|
|
35
|
-
- 성능 트레이드오프: 구체적 수치 근거 제시
|
|
76
|
+
1. 각 코멘트에 근거를 기술한 반박 답글 작성:
|
|
77
|
+
- 의도적 설계 결정: 배경 설명
|
|
78
|
+
- 성능 트레이드오프: 구체적 수치 근거
|
|
36
79
|
- 스펙 요구사항과 일치하는 경우: 이슈 링크 첨부
|
|
37
|
-
|
|
80
|
+
2. 위와 동일한 방법으로 답글 게시
|
|
38
81
|
|
|
39
82
|
## 출력
|
|
40
83
|
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: bylane-respond-loop
|
|
3
|
+
description: 5분 주기로 내 PR에 달린 리뷰/코멘트를 감지하여 자동으로 반박하거나 반영한다.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Respond Loop Agent
|
|
7
|
+
|
|
8
|
+
## 개요
|
|
9
|
+
|
|
10
|
+
백그라운드 폴러(`src/respond-loop.js`)가 5분마다 내 PR에 달린 리뷰/코멘트를 감지하여
|
|
11
|
+
`.bylane/state/respond-queue.json`에 기록한다. 이 skill은 해당 큐를 감시하다가
|
|
12
|
+
`status: "pending"` 항목이 생기면 `bylane-respond-agent`를 실행한다.
|
|
13
|
+
|
|
14
|
+
감지 대상:
|
|
15
|
+
- `CHANGES_REQUESTED` 리뷰
|
|
16
|
+
- 일반 코멘트 (COMMENTED)
|
|
17
|
+
- 대응 후 추가된 새 코멘트 (updatedAt 변경 감지)
|
|
18
|
+
|
|
19
|
+
## 시작
|
|
20
|
+
|
|
21
|
+
### 1. 폴러 시작 (백그라운드)
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
node src/respond-loop.js &
|
|
25
|
+
echo "폴러 PID: $!"
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### 2. 큐 감시 루프
|
|
29
|
+
|
|
30
|
+
pending PR이 생길 때마다 respond-agent를 실행한다:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
node -e "
|
|
34
|
+
import('./src/state.js').then(({readState}) => {
|
|
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
|
+
"
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
pending 항목이 있으면 각 PR에 대해:
|
|
43
|
+
|
|
44
|
+
1. `hasChangesRequested` 여부 확인:
|
|
45
|
+
- `true` → 사용자에게 `accept` / `rebut` 모드 선택 요청 후 `bylane-respond-agent` 실행
|
|
46
|
+
- `false` (코멘트만) → 코멘트 내용 확인 후 `accept` / `rebut` 모드 자동 판단 또는 사용자에게 선택 요청
|
|
47
|
+
|
|
48
|
+
2. `bylane-respond-agent` skill 실행 (PR 번호 + 모드 전달)
|
|
49
|
+
|
|
50
|
+
3. 완료 후 큐 항목을 `status: "responded"`로 업데이트:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
node -e "
|
|
54
|
+
import('./src/state.js').then(({readState, writeState}) => {
|
|
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
|
+
"
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
4. 다음 pending 항목으로 반복. pending 없으면 30초 대기 후 재확인.
|
|
67
|
+
|
|
68
|
+
## 큐 항목 스키마
|
|
69
|
+
|
|
70
|
+
`.bylane/state/respond-queue.json`:
|
|
71
|
+
|
|
72
|
+
```json
|
|
73
|
+
{
|
|
74
|
+
"agent": "respond-queue",
|
|
75
|
+
"status": "running",
|
|
76
|
+
"queue": [
|
|
77
|
+
{
|
|
78
|
+
"number": 45,
|
|
79
|
+
"title": "Add dark mode toggle",
|
|
80
|
+
"url": "https://github.com/owner/repo/pull/45",
|
|
81
|
+
"branch": "feature/45-dark-mode",
|
|
82
|
+
"updatedAt": "2026-04-05T10:00:00Z",
|
|
83
|
+
"hasChangesRequested": true,
|
|
84
|
+
"status": "pending",
|
|
85
|
+
"detectedAt": "2026-04-05T10:01:00Z"
|
|
86
|
+
}
|
|
87
|
+
]
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
`status` 값:
|
|
92
|
+
- `pending` — 대응 대기 중
|
|
93
|
+
- `responding` — 현재 respond-agent 실행 중
|
|
94
|
+
- `responded` — 대응 완료 (새 코멘트 오면 pending으로 재전환)
|
|
95
|
+
|
|
96
|
+
## 재감지
|
|
97
|
+
|
|
98
|
+
폴러가 이미 `responded` 상태인 PR의 `updatedAt`이 변경된 것을 감지하면
|
|
99
|
+
자동으로 `status: "pending"`으로 되돌린다.
|
|
100
|
+
|
|
101
|
+
## 종료
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
kill $(pgrep -f respond-loop.js)
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## 수동 실행
|
|
108
|
+
|
|
109
|
+
`/bylane respond-loop`
|