@elyun/bylane 1.28.0 → 1.30.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.
@@ -30,9 +30,27 @@ npx @elyun/bylane state write code-agent '{"status":"in_progress","startedAt":"'
30
30
  | `spec.figmaSpec` | Figma 컬러토큰·컴포넌트 구조 |
31
31
  | `issueType` | `new-feature` / `bug` / `improvement` / `chore` |
32
32
  | `issueNumber` | GitHub 이슈 번호 |
33
+ | `branchName` | issue-agent가 생성한 브랜치명 |
34
+ | `worktreePath` | 워크트리 경로 (없으면 `null`) |
33
35
 
34
36
  없으면 GitHub 이슈 본문을 직접 로드하여 파싱한다.
35
37
 
38
+ ### 브랜치/워크트리 확인
39
+
40
+ issue-agent가 이미 브랜치를 생성했는지 확인한다:
41
+
42
+ 1. `branchName`이 있으면 → 해당 브랜치로 checkout
43
+ 2. `worktreePath`가 있으면 → 해당 워크트리 디렉토리에서 작업
44
+ 3. 둘 다 없으면 (`issue.autoCreateBranch: false`) → code-agent가 직접 브랜치 생성
45
+
46
+ ```bash
47
+ # branchName이 있는 경우
48
+ git checkout "$BRANCH_NAME"
49
+
50
+ # worktreePath가 있는 경우 — 해당 디렉토리에서 모든 작업 수행
51
+ cd "$WORKTREE_PATH"
52
+ ```
53
+
36
54
  issueMemory 로드:
37
55
  ```bash
38
56
  npx @elyun/bylane memory read ISSUE_NUMBER
@@ -211,6 +211,49 @@ curl -s -X POST \
211
211
 
212
212
  ---
213
213
 
214
+ ### Phase 5 — 브랜치/워크트리 생성 (설정에 따라)
215
+
216
+ 이슈 생성 직후, `issue.autoCreateBranch`가 `true`이면 브랜치를 자동 생성한다.
217
+ 브랜치명은 `branch.pattern` 설정에 따라 결정된다.
218
+
219
+ ```bash
220
+ # 브랜치명 생성 (src/branch.js 활용)
221
+ BRANCH_NAME=$(node -e "
222
+ import('./src/branch.js').then(({buildBranchNameFromConfig}) => {
223
+ import('./src/config.js').then(({loadConfig}) => {
224
+ const config = loadConfig()
225
+ const name = buildBranchNameFromConfig(config, {
226
+ issueNumber: ISSUE_NUMBER,
227
+ type: 'ISSUE_TYPE',
228
+ title: 'ISSUE_TITLE'
229
+ })
230
+ process.stdout.write(name)
231
+ })
232
+ })
233
+ ")
234
+
235
+ git checkout -b "$BRANCH_NAME"
236
+ ```
237
+
238
+ #### 워크트리 생성 (`issue.autoCreateWorktree: true`인 경우)
239
+
240
+ 브랜치 대신 워크트리를 생성하여 독립된 작업 디렉토리를 만든다:
241
+
242
+ ```bash
243
+ WORKTREE_DIR=".bylane/worktrees/$BRANCH_NAME"
244
+ git worktree add "$WORKTREE_DIR" -b "$BRANCH_NAME"
245
+ ```
246
+
247
+ 이후 모든 에이전트(code-agent, test-agent, commit-agent 등)는 이 워크트리 경로에서 작업한다.
248
+ state에 `branchName`과 `worktreePath`를 기록하여 후속 에이전트가 참조할 수 있게 한다.
249
+
250
+ #### 설정이 꺼져 있는 경우
251
+
252
+ `issue.autoCreateBranch: false`이면 이 단계를 건너뛴다.
253
+ code-agent가 실행 시점에 브랜치를 직접 생성한다.
254
+
255
+ ---
256
+
214
257
  ## 출력
215
258
 
216
259
  `.bylane/state/issue-agent.json`:
@@ -230,7 +273,9 @@ curl -s -X POST \
230
273
  "affectedFiles": ["src/hooks/useTheme.ts", "src/components/Header/"],
231
274
  "checklist": ["ThemeToggle 컴포넌트 생성", "useTheme hook 수정", "테스트 작성"],
232
275
  "figmaSpec": { "enabled": false, "components": [], "colorTokens": {} }
233
- }
276
+ },
277
+ "branchName": "issues-123-dark-mode-toggle",
278
+ "worktreePath": null
234
279
  }
235
280
  ```
236
281
 
@@ -83,7 +83,25 @@ Linear API Key는 환경변수명(`LINEAR_API_KEY`)으로 저장. 실제 키값
83
83
 
84
84
  `permissions.scope`에 저장.
85
85
 
86
- ## Step 5/9리뷰 자동 Approve
86
+ ## Step 5/10이슈 생성 시 브랜치/워크트리
87
+
88
+ > 이슈 생성 후 자동으로 브랜치를 만들까요? (y/n, 기본: y)
89
+
90
+ - `y` (기본) → `issue.autoCreateBranch = true` — 이슈 생성 직후 브랜치 네이밍 패턴에 따라 브랜치 자동 생성
91
+ - `n` → `issue.autoCreateBranch = false` — code-agent 실행 시 수동 생성
92
+
93
+ `y` 선택 시 추가 질문:
94
+
95
+ > 브랜치와 함께 git worktree도 생성할까요? (y/n, 기본: n)
96
+ > worktree를 사용하면 이슈별로 독립된 작업 디렉토리가 생성됩니다.
97
+ > 여러 이슈를 동시에 작업할 때 유용합니다.
98
+
99
+ - `y` → `issue.autoCreateWorktree = true` — `.bylane/worktrees/{branch-name}/`에 워크트리 생성
100
+ - `n` (기본) → `issue.autoCreateWorktree = false` — 브랜치만 생성하고 checkout
101
+
102
+ 모든 후속 에이전트(code-agent, test-agent, commit-agent 등)는 이슈 번호 기준으로 해당 브랜치/워크트리에서 작업한다.
103
+
104
+ ## Step 6/10 — 리뷰 자동 Approve
87
105
 
88
106
  > AI 리뷰에서 지적사항이 없을 때 자동으로 Approve할까요? (y/n, 기본: n)
89
107
 
@@ -92,7 +110,7 @@ Linear API Key는 환경변수명(`LINEAR_API_KEY`)으로 저장. 실제 키값
92
110
 
93
111
  대부분의 팀에서는 사람이 최종 Approve하는 것을 권장한다.
94
112
 
95
- ## Step 6/9 — Loop 실행 모드
113
+ ## Step 7/10 — Loop 실행 모드
96
114
 
97
115
  > Loop 실행 모드를 선택하세요:
98
116
  > 1. tmux — tmux 세션에서 백그라운드 실행 (터미널 종료 후에도 유지, 권장)
@@ -117,7 +135,7 @@ bylane loop stop # loop 종료
117
135
  bylane loop status # 상태 확인
118
136
  ```
119
137
 
120
- ## Step 7/9 — 고급 설정
138
+ ## Step 8/10 — 고급 설정
121
139
 
122
140
  > 고급 설정을 변경하시겠습니까? (Enter = 기본값 사용)
123
141
 
@@ -126,7 +144,7 @@ bylane loop status # 상태 확인
126
144
  - `loopTimeoutMinutes` (기본: 30): 루프 타임아웃 (분)
127
145
  - Figma MCP 활성화? (y/n, 기본: n)
128
146
 
129
- ## Step 8/9 — 브랜치 네이밍
147
+ ## Step 9/10 — 브랜치 네이밍
130
148
 
131
149
  > 브랜치 네이밍 패턴을 선택하세요:
132
150
  > 1. {tracker}-{issue-number} 예) issues-32
@@ -141,7 +159,7 @@ bylane loop status # 상태 확인
141
159
  직접 입력 시 사용 가능한 토큰 목록 안내:
142
160
  `{tracker}`, `{type}`, `{issue-number}`, `{custom-id}`, `{title-slug}`, `{date}`, `{username}`
143
161
 
144
- ## Step 9/9 — 에이전트 모델 설정
162
+ ## Step 10/10 — 에이전트 모델 설정
145
163
 
146
164
  > 각 에이전트에 사용할 AI 모델을 설정하시겠습니까? (Enter = 기본값 사용)
147
165
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elyun/bylane",
3
- "version": "1.28.0",
3
+ "version": "1.30.0",
4
4
  "description": "Frontend development harness for Claude Code",
5
5
  "type": "module",
6
6
  "bin": {
package/src/cli.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { mkdirSync, symlinkSync, existsSync, readdirSync, copyFileSync, renameSync, readFileSync, writeFileSync } from 'fs'
2
+ import { mkdirSync, symlinkSync, existsSync, readdirSync, copyFileSync, renameSync, readFileSync, writeFileSync, rmSync } from 'fs'
3
3
  import { join, dirname } from 'path'
4
4
  import { fileURLToPath } from 'url'
5
5
  import { homedir } from 'os'
@@ -33,10 +33,8 @@ function backupAndCopy(src, dest, file, label) {
33
33
  console.log(` = ${label}: ${file} (변경 없음, 건너뜀)`)
34
34
  return
35
35
  }
36
- const backupPath = `${destFile}.bak`
37
- renameSync(destFile, backupPath)
38
36
  copyFileSync(srcFile, destFile)
39
- console.log(` ~ ${label}: ${file} (업데이트됨, 기존 파일 -> ${file}.bak)`)
37
+ console.log(` ~ ${label}: ${file} (업데이트됨)`)
40
38
  } else {
41
39
  copyFileSync(srcFile, destFile)
42
40
  console.log(` + ${label}: ${file}`)
@@ -139,8 +137,48 @@ function install() {
139
137
  }
140
138
  }
141
139
 
140
+ function uninstall() {
141
+ console.log('\n byLane 제거 중...\n')
142
+
143
+ for (const { src, dest, label } of TARGETS) {
144
+ if (!existsSync(dest)) continue
145
+ const files = readdirSync(src)
146
+ for (const file of files) {
147
+ const destFile = join(dest, file)
148
+ if (existsSync(destFile)) {
149
+ rmSync(destFile)
150
+ console.log(` - ${label}: ${file}`)
151
+ }
152
+ }
153
+ }
154
+
155
+ // settings.json에서 bylane 훅 제거
156
+ const settingsPath = join(CLAUDE_DIR, 'settings.json')
157
+ if (existsSync(settingsPath)) {
158
+ try {
159
+ const settings = JSON.parse(readFileSync(settingsPath, 'utf8'))
160
+ const stripBylane = (arr) =>
161
+ (arr ?? []).filter(h => !h.hooks?.some(hh => hh.command?.includes('bylane-agent-tracker')))
162
+ settings.hooks = settings.hooks ?? {}
163
+ settings.hooks.PreToolUse = stripBylane(settings.hooks.PreToolUse)
164
+ settings.hooks.PostToolUse = stripBylane(settings.hooks.PostToolUse)
165
+ writeFileSync(settingsPath, JSON.stringify(settings, null, 2))
166
+ console.log(' - Hook: bylane-agent-tracker 제거')
167
+ } catch {}
168
+ }
169
+
170
+ console.log(`
171
+ byLane 제거 완료.
172
+
173
+ 사용자 설정(.bylane/bylane.json)은 유지됩니다.
174
+ Claude Code를 재시작하면 변경사항이 적용됩니다.
175
+ `)
176
+ }
177
+
142
178
  if (command === 'install') {
143
179
  install()
180
+ } else if (command === 'uninstall') {
181
+ uninstall()
144
182
  } else if (command === 'preflight') {
145
183
  const { runPreflight, formatPreflight } = await import('./preflight.js')
146
184
  const result = runPreflight()
@@ -320,6 +358,6 @@ if (command === 'install') {
320
358
  child.on('exit', code => process.exit(code ?? 0))
321
359
  } else {
322
360
  console.error(`알 수 없는 명령: ${command}`)
323
- console.error('사용법: npx @elyun/bylane [install|loop|monitor|preflight|state|memory|cleanup] [--symlink]')
361
+ console.error('사용법: npx @elyun/bylane [install|uninstall|loop|monitor|preflight|state|memory|cleanup] [--symlink]')
324
362
  process.exit(1)
325
363
  }
package/src/config.js CHANGED
@@ -40,6 +40,10 @@ export const DEFAULT_CONFIG = {
40
40
  owner: '',
41
41
  repo: ''
42
42
  },
43
+ issue: {
44
+ autoCreateBranch: true,
45
+ autoCreateWorktree: false
46
+ },
43
47
  memory: {
44
48
  enabled: true,
45
49
  dir: '.bylane/memory'