@elyun/bylane 1.34.0 → 1.37.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/commands/bylane-code-agent.md +22 -0
- package/commands/bylane-commit-agent.md +20 -0
- package/commands/bylane-issue-agent.md +22 -0
- package/commands/bylane-pr-agent.md +20 -0
- package/commands/bylane-respond-agent.md +20 -0
- package/commands/bylane-review-agent.md +20 -0
- package/commands/bylane-test-agent.md +32 -0
- package/package.json +1 -1
- package/src/cli.js +3 -3
- package/src/loop-utils.js +18 -5
|
@@ -217,6 +217,28 @@ npx @elyun/bylane state write code-agent '{
|
|
|
217
217
|
|
|
218
218
|
---
|
|
219
219
|
|
|
220
|
+
## Slack 완료 알림
|
|
221
|
+
|
|
222
|
+
`.bylane/bylane.json`의 `notifications.slack.enabled: true`이고 `webhookUrl`이 있으면 전송:
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
SLACK_WEBHOOK_URL=$(node -e "try{const c=JSON.parse(require('fs').readFileSync('.bylane/bylane.json','utf8'));const s=c.notifications?.slack;process.stdout.write(s?.enabled&&s?.webhookUrl?s.webhookUrl:'')}catch(e){}" 2>/dev/null)
|
|
226
|
+
|
|
227
|
+
[ -n "$SLACK_WEBHOOK_URL" ] && curl -s -X POST "$SLACK_WEBHOOK_URL" \
|
|
228
|
+
-H "Content-Type: application/json" \
|
|
229
|
+
-d "{
|
|
230
|
+
\"title\": \"[code-agent] #ISSUE_NUMBER 구현 완료\",
|
|
231
|
+
\"status\": \"completed\",
|
|
232
|
+
\"url\": \"ISSUE_URL\",
|
|
233
|
+
\"elapsed\": \"ELAPSED\",
|
|
234
|
+
\"reason\": \"\"
|
|
235
|
+
}"
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
`ISSUE_URL`은 `.bylane/state/issue-agent.json`의 `issueUrl`.
|
|
239
|
+
|
|
240
|
+
---
|
|
241
|
+
|
|
220
242
|
## issueMemory 기록
|
|
221
243
|
|
|
222
244
|
```bash
|
|
@@ -66,6 +66,26 @@ ls .gitmessage .github/commit-template.txt .github/COMMIT_TEMPLATE.md 2>/dev/nul
|
|
|
66
66
|
npx @elyun/bylane state write commit-agent '{"status":"completed","progress":100,"branchName":"BRANCH_NAME","commitSha":"COMMIT_SHA"}'
|
|
67
67
|
```
|
|
68
68
|
|
|
69
|
+
## Slack 완료 알림
|
|
70
|
+
|
|
71
|
+
`.bylane/bylane.json`의 `notifications.slack.enabled: true`이고 `webhookUrl`이 있으면 전송:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
SLACK_WEBHOOK_URL=$(node -e "try{const c=JSON.parse(require('fs').readFileSync('.bylane/bylane.json','utf8'));const s=c.notifications?.slack;process.stdout.write(s?.enabled&&s?.webhookUrl?s.webhookUrl:'')}catch(e){}" 2>/dev/null)
|
|
75
|
+
|
|
76
|
+
[ -n "$SLACK_WEBHOOK_URL" ] && curl -s -X POST "$SLACK_WEBHOOK_URL" \
|
|
77
|
+
-H "Content-Type: application/json" \
|
|
78
|
+
-d "{
|
|
79
|
+
\"title\": \"[commit-agent] 커밋 완료 (BRANCH_NAME)\",
|
|
80
|
+
\"status\": \"completed\",
|
|
81
|
+
\"url\": \"\",
|
|
82
|
+
\"elapsed\": \"ELAPSED\",
|
|
83
|
+
\"reason\": \"\"
|
|
84
|
+
}"
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
69
89
|
## 출력
|
|
70
90
|
|
|
71
91
|
`.bylane/state/commit-agent.json`:
|
|
@@ -296,6 +296,28 @@ npx @elyun/bylane memory append ISSUE_NUMBER issue-agent "유형: ISSUE_TYPE
|
|
|
296
296
|
|
|
297
297
|
---
|
|
298
298
|
|
|
299
|
+
## Slack 완료 알림
|
|
300
|
+
|
|
301
|
+
`.bylane/bylane.json`의 `notifications.slack.enabled: true`이고 `webhookUrl`이 있으면 전송:
|
|
302
|
+
|
|
303
|
+
```bash
|
|
304
|
+
SLACK_WEBHOOK_URL=$(node -e "try{const c=JSON.parse(require('fs').readFileSync('.bylane/bylane.json','utf8'));const s=c.notifications?.slack;process.stdout.write(s?.enabled&&s?.webhookUrl?s.webhookUrl:'')}catch(e){}" 2>/dev/null)
|
|
305
|
+
|
|
306
|
+
[ -n "$SLACK_WEBHOOK_URL" ] && curl -s -X POST "$SLACK_WEBHOOK_URL" \
|
|
307
|
+
-H "Content-Type: application/json" \
|
|
308
|
+
-d "{
|
|
309
|
+
\"title\": \"[issue-agent] #ISSUE_NUMBER SPEC_TITLE\",
|
|
310
|
+
\"status\": \"completed\",
|
|
311
|
+
\"url\": \"ISSUE_URL\",
|
|
312
|
+
\"elapsed\": \"ELAPSED\",
|
|
313
|
+
\"reason\": \"\"
|
|
314
|
+
}"
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
`ELAPSED`는 `startedAt`부터 현재까지의 소요 시간(예: `1m 23s`).
|
|
318
|
+
|
|
319
|
+
---
|
|
320
|
+
|
|
299
321
|
## 수동 실행
|
|
300
322
|
|
|
301
323
|
`/bylane issue #123` 또는 `/bylane issue 다크모드 토글 추가해줘`
|
|
@@ -93,6 +93,26 @@ npx @elyun/bylane state write pr-agent '{"status":"in_progress","startedAt":"'$(
|
|
|
93
93
|
npx @elyun/bylane state write pr-agent '{"status":"completed","progress":100,"prNumber":PR_NUMBER,"prUrl":"PR_URL"}'
|
|
94
94
|
```
|
|
95
95
|
|
|
96
|
+
## Slack 완료 알림
|
|
97
|
+
|
|
98
|
+
`.bylane/bylane.json`의 `notifications.slack.enabled: true`이고 `webhookUrl`이 있으면 전송:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
SLACK_WEBHOOK_URL=$(node -e "try{const c=JSON.parse(require('fs').readFileSync('.bylane/bylane.json','utf8'));const s=c.notifications?.slack;process.stdout.write(s?.enabled&&s?.webhookUrl?s.webhookUrl:'')}catch(e){}" 2>/dev/null)
|
|
102
|
+
|
|
103
|
+
[ -n "$SLACK_WEBHOOK_URL" ] && curl -s -X POST "$SLACK_WEBHOOK_URL" \
|
|
104
|
+
-H "Content-Type: application/json" \
|
|
105
|
+
-d "{
|
|
106
|
+
\"title\": \"[pr-agent] PR #PR_NUMBER 생성\",
|
|
107
|
+
\"status\": \"completed\",
|
|
108
|
+
\"url\": \"PR_URL\",
|
|
109
|
+
\"elapsed\": \"ELAPSED\",
|
|
110
|
+
\"reason\": \"\"
|
|
111
|
+
}"
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
96
116
|
## 출력
|
|
97
117
|
|
|
98
118
|
`.bylane/state/pr-agent.json`:
|
|
@@ -129,6 +129,26 @@ curl -s \
|
|
|
129
129
|
}
|
|
130
130
|
```
|
|
131
131
|
|
|
132
|
+
## Slack 완료 알림
|
|
133
|
+
|
|
134
|
+
`.bylane/bylane.json`의 `notifications.slack.enabled: true`이고 `webhookUrl`이 있으면 전송:
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
SLACK_WEBHOOK_URL=$(node -e "try{const c=JSON.parse(require('fs').readFileSync('.bylane/bylane.json','utf8'));const s=c.notifications?.slack;process.stdout.write(s?.enabled&&s?.webhookUrl?s.webhookUrl:'')}catch(e){}" 2>/dev/null)
|
|
138
|
+
|
|
139
|
+
[ -n "$SLACK_WEBHOOK_URL" ] && curl -s -X POST "$SLACK_WEBHOOK_URL" \
|
|
140
|
+
-H "Content-Type: application/json" \
|
|
141
|
+
-d "{
|
|
142
|
+
\"title\": \"[respond-agent] PR #PR_NUMBER 리뷰 대응 완료 (RESOLVED_COUNT건)\",
|
|
143
|
+
\"status\": \"completed\",
|
|
144
|
+
\"url\": \"PR_URL\",
|
|
145
|
+
\"elapsed\": \"ELAPSED\",
|
|
146
|
+
\"reason\": \"\"
|
|
147
|
+
}"
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
132
152
|
## 수동 실행
|
|
133
153
|
|
|
134
154
|
`/bylane respond #45`
|
|
@@ -200,6 +200,26 @@ curl -s -X POST \
|
|
|
200
200
|
npx @elyun/bylane state write review-agent '{"status":"completed","progress":100,"approved":APPROVED_BOOL,"commentCount":COMMENT_COUNT}'
|
|
201
201
|
```
|
|
202
202
|
|
|
203
|
+
## Slack 완료 알림
|
|
204
|
+
|
|
205
|
+
`.bylane/bylane.json`의 `notifications.slack.enabled: true`이고 `webhookUrl`이 있으면 전송:
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
SLACK_WEBHOOK_URL=$(node -e "try{const c=JSON.parse(require('fs').readFileSync('.bylane/bylane.json','utf8'));const s=c.notifications?.slack;process.stdout.write(s?.enabled&&s?.webhookUrl?s.webhookUrl:'')}catch(e){}" 2>/dev/null)
|
|
209
|
+
|
|
210
|
+
[ -n "$SLACK_WEBHOOK_URL" ] && curl -s -X POST "$SLACK_WEBHOOK_URL" \
|
|
211
|
+
-H "Content-Type: application/json" \
|
|
212
|
+
-d "{
|
|
213
|
+
\"title\": \"[review-agent] PR #PR_NUMBER 리뷰 완료 (COMMENT_COUNT건)\",
|
|
214
|
+
\"status\": \"completed\",
|
|
215
|
+
\"url\": \"PR_URL\",
|
|
216
|
+
\"elapsed\": \"ELAPSED\",
|
|
217
|
+
\"reason\": \"\"
|
|
218
|
+
}"
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
203
223
|
## 출력
|
|
204
224
|
|
|
205
225
|
`.bylane/state/review-agent.json`:
|
|
@@ -58,6 +58,38 @@ npx @elyun/bylane state write test-agent '{"status":"in_progress","startedAt":"'
|
|
|
58
58
|
}
|
|
59
59
|
```
|
|
60
60
|
|
|
61
|
+
## Slack 완료 알림
|
|
62
|
+
|
|
63
|
+
`.bylane/bylane.json`의 `notifications.slack.enabled: true`이고 `webhookUrl`이 있으면 전송:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
SLACK_WEBHOOK_URL=$(node -e "try{const c=JSON.parse(require('fs').readFileSync('.bylane/bylane.json','utf8'));const s=c.notifications?.slack;process.stdout.write(s?.enabled&&s?.webhookUrl?s.webhookUrl:'')}catch(e){}" 2>/dev/null)
|
|
67
|
+
|
|
68
|
+
# 통과 시
|
|
69
|
+
[ -n "$SLACK_WEBHOOK_URL" ] && curl -s -X POST "$SLACK_WEBHOOK_URL" \
|
|
70
|
+
-H "Content-Type: application/json" \
|
|
71
|
+
-d "{
|
|
72
|
+
\"title\": \"[test-agent] 테스트 통과 (PASSED/TOTAL)\",
|
|
73
|
+
\"status\": \"completed\",
|
|
74
|
+
\"url\": \"\",
|
|
75
|
+
\"elapsed\": \"ELAPSED\",
|
|
76
|
+
\"reason\": \"\"
|
|
77
|
+
}"
|
|
78
|
+
|
|
79
|
+
# 실패 시 — status를 escalated로
|
|
80
|
+
[ -n "$SLACK_WEBHOOK_URL" ] && curl -s -X POST "$SLACK_WEBHOOK_URL" \
|
|
81
|
+
-H "Content-Type: application/json" \
|
|
82
|
+
-d "{
|
|
83
|
+
\"title\": \"[test-agent] 테스트 실패 (FAILED/TOTAL)\",
|
|
84
|
+
\"status\": \"escalated\",
|
|
85
|
+
\"url\": \"\",
|
|
86
|
+
\"elapsed\": \"\",
|
|
87
|
+
\"reason\": \"FAILURE_SUMMARY\"
|
|
88
|
+
}"
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
61
93
|
## 수동 실행
|
|
62
94
|
|
|
63
95
|
`/bylane test`
|
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -286,14 +286,14 @@ if (command === 'install') {
|
|
|
286
286
|
const mode = resolveLoopMode()
|
|
287
287
|
|
|
288
288
|
if (mode === 'tmux') {
|
|
289
|
-
startTmuxLoops(sessionName)
|
|
289
|
+
startTmuxLoops(sessionName, { packageRoot: ROOT, projectDir: process.cwd() })
|
|
290
290
|
console.log(`\n tmux 세션에 접속하려면: tmux attach -t ${sessionName}\n`)
|
|
291
291
|
} else {
|
|
292
292
|
// process 모드: 현재 프로세스에서 직접 실행
|
|
293
293
|
console.log('\n process 모드: review-loop + respond-loop 실행\n')
|
|
294
294
|
const { spawn } = await import('child_process')
|
|
295
|
-
const review = spawn(process.execPath, ['src
|
|
296
|
-
const respond = spawn(process.execPath, ['src
|
|
295
|
+
const review = spawn(process.execPath, [join(ROOT, 'src', 'review-loop.js')], { stdio: 'inherit', detached: false, cwd: process.cwd() })
|
|
296
|
+
const respond = spawn(process.execPath, [join(ROOT, 'src', 'respond-loop.js')], { stdio: 'inherit', detached: false, cwd: process.cwd() })
|
|
297
297
|
|
|
298
298
|
function shutdownAll() {
|
|
299
299
|
review.kill('SIGTERM')
|
package/src/loop-utils.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* 루프 프로세스 공통 유틸
|
|
4
4
|
*/
|
|
5
5
|
import { execSync } from 'child_process'
|
|
6
|
+
import { join } from 'path'
|
|
6
7
|
import { readState, writeState } from './state.js'
|
|
7
8
|
import { loadConfig } from './config.js'
|
|
8
9
|
|
|
@@ -152,22 +153,34 @@ export function verifyTmuxLoops(sessionName = 'bylane-loops', stateDir = '.bylan
|
|
|
152
153
|
/**
|
|
153
154
|
* tmux 세션에서 review-loop + respond-loop을 실행
|
|
154
155
|
* @param {string} sessionName
|
|
155
|
-
* @param {
|
|
156
|
+
* @param {object} opts
|
|
157
|
+
* @param {string} [opts.stateDir] 상태 디렉토리 (상대경로)
|
|
158
|
+
* @param {string} [opts.packageRoot] 패키지 루트 경로 (스크립트 절대경로 해석용)
|
|
159
|
+
* @param {string} [opts.projectDir] 프로젝트 디렉토리 (tmux CWD, .bylane/ 기준)
|
|
156
160
|
*/
|
|
157
|
-
export function startTmuxLoops(sessionName = 'bylane-loops',
|
|
161
|
+
export function startTmuxLoops(sessionName = 'bylane-loops', opts = {}) {
|
|
162
|
+
const {
|
|
163
|
+
stateDir = '.bylane/state',
|
|
164
|
+
packageRoot = process.cwd(),
|
|
165
|
+
projectDir = process.cwd()
|
|
166
|
+
} = typeof opts === 'string' ? { stateDir: opts } : opts
|
|
167
|
+
|
|
158
168
|
if (isTmuxSessionAlive(sessionName)) {
|
|
159
169
|
console.log(`[tmux] 세션 '${sessionName}'이 이미 실행 중입니다.`)
|
|
160
170
|
return { started: false, reason: 'already_running' }
|
|
161
171
|
}
|
|
162
172
|
|
|
163
|
-
|
|
173
|
+
const reviewScript = join(packageRoot, 'src', 'review-loop.js')
|
|
174
|
+
const respondScript = join(packageRoot, 'src', 'respond-loop.js')
|
|
175
|
+
|
|
176
|
+
// 첫 번째 윈도우: review-loop (-c 로 프로젝트 디렉토리에서 실행)
|
|
164
177
|
execSync(
|
|
165
|
-
`tmux new-session -d -s ${sessionName} -n review 'node
|
|
178
|
+
`tmux new-session -d -s ${sessionName} -n review -c '${projectDir}' 'node ${reviewScript}'`,
|
|
166
179
|
{ stdio: 'inherit' }
|
|
167
180
|
)
|
|
168
181
|
// 두 번째 윈도우: respond-loop
|
|
169
182
|
execSync(
|
|
170
|
-
`tmux new-window -t ${sessionName} -n respond 'node
|
|
183
|
+
`tmux new-window -t ${sessionName} -n respond -c '${projectDir}' 'node ${respondScript}'`,
|
|
171
184
|
{ stdio: 'inherit' }
|
|
172
185
|
)
|
|
173
186
|
|