@jjlabsio/claude-crew 0.1.21 → 0.1.23
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/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/data/provider-catalog.json +24 -0
- package/hud/index.mjs +55 -4
- package/package.json +2 -1
- package/skills/crew-dev/SKILL.md +176 -18
- package/skills/crew-setup/SKILL.md +118 -6
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"name": "claude-crew",
|
|
12
12
|
"source": "./",
|
|
13
13
|
"description": "오케스트레이터 + PM, 플래너, 개발, QA, 마케팅 에이전트 팀으로 단일 제품의 개발과 마케팅을 통합 관리",
|
|
14
|
-
"version": "0.1.
|
|
14
|
+
"version": "0.1.23",
|
|
15
15
|
"author": {
|
|
16
16
|
"name": "Jaejin Song",
|
|
17
17
|
"email": "wowlxx28@gmail.com"
|
|
@@ -28,5 +28,5 @@
|
|
|
28
28
|
"category": "workflow"
|
|
29
29
|
}
|
|
30
30
|
],
|
|
31
|
-
"version": "0.1.
|
|
31
|
+
"version": "0.1.23"
|
|
32
32
|
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"claude": {
|
|
3
|
+
"models": [
|
|
4
|
+
{ "id": "opus", "label": "Opus 4.6 — 최고 품질, 복잡한 구현", "default_for": ["dev", "code-reviewer"] },
|
|
5
|
+
{ "id": "sonnet", "label": "Sonnet 4.6 — 빠르고 저렴, Opus급 성능", "default_for": ["qa"] },
|
|
6
|
+
{ "id": "haiku", "label": "Haiku 4.5 — 최저 비용, 단순 태스크", "default_for": [] }
|
|
7
|
+
]
|
|
8
|
+
},
|
|
9
|
+
"codex": {
|
|
10
|
+
"models": [
|
|
11
|
+
{ "id": "gpt-5.4", "reasoning": "xhigh", "label": "GPT-5.4 xhigh (추천) — 최고 성능, 토큰 多", "default_for": ["dev", "code-reviewer"] },
|
|
12
|
+
{ "id": "gpt-5.4", "reasoning": "high", "label": "GPT-5.4 high — 고성능, 균형잡힌 비용", "default_for": [] },
|
|
13
|
+
{ "id": "gpt-5.4", "reasoning": "medium", "label": "GPT-5.4 medium — 빠르고 저렴", "default_for": [] },
|
|
14
|
+
{ "id": "o3", "reasoning": "high", "label": "o3 high — 추론 특화", "default_for": [] },
|
|
15
|
+
{ "id": "o3", "reasoning": "medium", "label": "o3 medium — 추론 특화, 저비용", "default_for": [] },
|
|
16
|
+
{ "id": "gpt-5.4-mini", "reasoning": null, "label": "GPT-5.4 Mini — 최저 비용", "default_for": ["qa"] }
|
|
17
|
+
]
|
|
18
|
+
},
|
|
19
|
+
"agent_defaults": {
|
|
20
|
+
"dev": { "provider": "claude", "model": "opus" },
|
|
21
|
+
"code-reviewer": { "provider": "claude", "model": "opus" },
|
|
22
|
+
"qa": { "provider": "claude", "model": "sonnet" }
|
|
23
|
+
}
|
|
24
|
+
}
|
package/hud/index.mjs
CHANGED
|
@@ -21,6 +21,7 @@ import { homedir } from 'node:os';
|
|
|
21
21
|
const RESET = '\x1b[0m';
|
|
22
22
|
const bold = (s) => `\x1b[1m${s}\x1b[22m`;
|
|
23
23
|
const dim = (s) => `\x1b[2m${s}\x1b[22m`;
|
|
24
|
+
const subdued = (s) => `\x1b[38;5;248m${s}${RESET}`;
|
|
24
25
|
const yellow = (s) => `\x1b[33m${s}\x1b[39m`;
|
|
25
26
|
const red = (s) => `\x1b[31m${s}\x1b[39m`;
|
|
26
27
|
const green = (s) => `\x1b[32m${s}\x1b[39m`;
|
|
@@ -237,7 +238,7 @@ function colorizeRateLimits(limits) {
|
|
|
237
238
|
};
|
|
238
239
|
const formatWindow = (label, pct, resetAt) => {
|
|
239
240
|
const reset = formatResetTime(resetAt);
|
|
240
|
-
const resetStr = reset ? ` ${
|
|
241
|
+
const resetStr = reset ? ` ${subdued(`(${reset})`)}` : '';
|
|
241
242
|
return `${label}:${colorize(pct)}${resetStr}`;
|
|
242
243
|
};
|
|
243
244
|
const parts = [];
|
|
@@ -246,6 +247,41 @@ function colorizeRateLimits(limits) {
|
|
|
246
247
|
return parts.join(' ');
|
|
247
248
|
}
|
|
248
249
|
|
|
250
|
+
// ---------------------------------------------------------------------------
|
|
251
|
+
// Worktree-aware transcript path resolution
|
|
252
|
+
// ---------------------------------------------------------------------------
|
|
253
|
+
// When Claude Code enters a worktree, stdin.transcript_path points to a
|
|
254
|
+
// worktree-specific project directory whose transcript only contains events
|
|
255
|
+
// after worktree entry — todos created before are lost.
|
|
256
|
+
//
|
|
257
|
+
// Fix: detect worktree, locate the original project transcript with the same
|
|
258
|
+
// session ID, and merge todos from the original into the worktree result.
|
|
259
|
+
//
|
|
260
|
+
// Parallel worktrees: each gets its own transcript_path but the original
|
|
261
|
+
// project transcript is shared. Each worktree merges from the same original,
|
|
262
|
+
// so all see the full todo list without interfering with each other.
|
|
263
|
+
function resolveOriginalTranscriptPath(transcriptPath, cwd) {
|
|
264
|
+
if (!transcriptPath || !cwd) return null;
|
|
265
|
+
|
|
266
|
+
const commonDir = gitExec('git rev-parse --git-common-dir', cwd);
|
|
267
|
+
if (!commonDir || commonDir === '.git' || commonDir.startsWith('.')) return null;
|
|
268
|
+
|
|
269
|
+
// commonDir is absolute: /path/to/main-repo/.git
|
|
270
|
+
const mainRepoPath = dirname(commonDir);
|
|
271
|
+
const transcriptFilename = basename(transcriptPath);
|
|
272
|
+
const transcriptDir = dirname(transcriptPath);
|
|
273
|
+
const projectsBase = dirname(transcriptDir);
|
|
274
|
+
|
|
275
|
+
// Convert main repo path to Claude Code project dir format:
|
|
276
|
+
// /Users/foo/myproject → -Users-foo-myproject
|
|
277
|
+
const mainProjectDirName = mainRepoPath.replace(/\//g, '-');
|
|
278
|
+
const originalPath = join(projectsBase, mainProjectDirName, transcriptFilename);
|
|
279
|
+
|
|
280
|
+
if (originalPath === transcriptPath) return null;
|
|
281
|
+
if (existsSync(originalPath)) return originalPath;
|
|
282
|
+
return null;
|
|
283
|
+
}
|
|
284
|
+
|
|
249
285
|
// ---------------------------------------------------------------------------
|
|
250
286
|
// Transcript parsing (agents + skills)
|
|
251
287
|
// ---------------------------------------------------------------------------
|
|
@@ -510,7 +546,7 @@ function renderAgentsMultiLine(agents, maxLines = 5) {
|
|
|
510
546
|
const desc = a.description.length > 40 ? a.description.slice(0, 37) + '...' : a.description;
|
|
511
547
|
|
|
512
548
|
detailLines.push(
|
|
513
|
-
`${dim(prefix)} ${cyan(name)} ${
|
|
549
|
+
`${dim(prefix)} ${cyan(name)} ${subdued(model)} : ${desc} ${subdued(`(${duration})`)}`
|
|
514
550
|
);
|
|
515
551
|
});
|
|
516
552
|
|
|
@@ -534,7 +570,7 @@ function renderTodosLine(todos) {
|
|
|
534
570
|
|
|
535
571
|
if (!inProgress) {
|
|
536
572
|
if (completed === total && total > 0) {
|
|
537
|
-
return `${green('\u2713')} all done ${
|
|
573
|
+
return `${green('\u2713')} all done ${subdued(`(${completed}/${total})`)}`;
|
|
538
574
|
}
|
|
539
575
|
return null;
|
|
540
576
|
}
|
|
@@ -542,7 +578,7 @@ function renderTodosLine(todos) {
|
|
|
542
578
|
const content = inProgress.content.length > 50
|
|
543
579
|
? inProgress.content.slice(0, 47) + '...'
|
|
544
580
|
: inProgress.content;
|
|
545
|
-
return `${yellow('\u25b8')} ${content} ${
|
|
581
|
+
return `${yellow('\u25b8')} ${content} ${subdued(`(${completed}/${total})`)}`;
|
|
546
582
|
}
|
|
547
583
|
|
|
548
584
|
// ---------------------------------------------------------------------------
|
|
@@ -628,6 +664,21 @@ async function main() {
|
|
|
628
664
|
|
|
629
665
|
const transcript = parseTranscript(stdin.transcript_path);
|
|
630
666
|
|
|
667
|
+
// In worktrees, merge todos from the original project transcript.
|
|
668
|
+
// The worktree transcript only has events after EnterWorktree, so todos
|
|
669
|
+
// created before are missing. The original transcript has the full history.
|
|
670
|
+
// If the worktree transcript also has todos (created after worktree entry),
|
|
671
|
+
// use the worktree's todos since they are more up-to-date for that session.
|
|
672
|
+
if (transcript.todos.length === 0) {
|
|
673
|
+
const originalPath = resolveOriginalTranscriptPath(stdin.transcript_path, cwd);
|
|
674
|
+
if (originalPath) {
|
|
675
|
+
const originalTranscript = parseTranscript(originalPath);
|
|
676
|
+
if (originalTranscript.todos.length > 0) {
|
|
677
|
+
transcript.todos = originalTranscript.todos;
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
|
|
631
682
|
const { headerPart, detailLines } = renderAgentsMultiLine(transcript.agents);
|
|
632
683
|
if (headerPart) {
|
|
633
684
|
midElements.push(headerPart);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jjlabsio/claude-crew",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.23",
|
|
4
4
|
"description": "1인 SaaS 개발자를 위한 멀티 에이전트 오케스트레이션 — 개발, 마케팅, 일정을 한 대화에서 통합 관리",
|
|
5
5
|
"author": "Jaejin Song <wowlxx28@gmail.com>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
"files": [
|
|
19
19
|
".claude-plugin/",
|
|
20
20
|
"agents/",
|
|
21
|
+
"data/",
|
|
21
22
|
"skills/",
|
|
22
23
|
"hooks/",
|
|
23
24
|
"hud/",
|
package/skills/crew-dev/SKILL.md
CHANGED
|
@@ -14,6 +14,47 @@ description: contract.md를 입력으로 받아 Dev + CodeReviewer + QA 파이
|
|
|
14
14
|
|
|
15
15
|
---
|
|
16
16
|
|
|
17
|
+
## Multi-Provider 지원
|
|
18
|
+
|
|
19
|
+
에이전트별로 claude 또는 codex provider를 사용할 수 있다. `/crew-setup`에서 설정한 `.crew/config.json`을 기반으로 디스패치한다.
|
|
20
|
+
|
|
21
|
+
### Provider 설정 해석
|
|
22
|
+
|
|
23
|
+
오케스트레이터는 Phase 1에서 `.crew/config.json`과 `data/provider-catalog.json`을 읽어 각 에이전트의 provider 설정을 결정한다.
|
|
24
|
+
|
|
25
|
+
**우선순위:**
|
|
26
|
+
1. `.crew/config.json`의 `providers.{role}` — 있으면 사용
|
|
27
|
+
2. `data/provider-catalog.json`의 `agent_defaults.{role}` — 폴백
|
|
28
|
+
|
|
29
|
+
**해석된 설정 예시:**
|
|
30
|
+
```json
|
|
31
|
+
{ "provider": "codex", "model": "gpt-5.4", "reasoning": "xhigh" }
|
|
32
|
+
{ "provider": "claude", "model": "opus" }
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### 디스패치 규칙
|
|
36
|
+
|
|
37
|
+
**claude provider:**
|
|
38
|
+
```
|
|
39
|
+
Agent(subagent_type="{role}", model="{model}", description="...", prompt="...")
|
|
40
|
+
```
|
|
41
|
+
기존과 동일. `model` 파라미터를 설정값으로 전달한다.
|
|
42
|
+
|
|
43
|
+
**codex provider:**
|
|
44
|
+
```
|
|
45
|
+
Bash("codex exec --model {model} -c model_reasoning_effort=\"{reasoning}\" --dangerously-bypass-approvals-and-sandbox \"{prompt}\"")
|
|
46
|
+
```
|
|
47
|
+
- 프롬프트가 길면 임시 파일에 저장 후 `cat`으로 전달한다.
|
|
48
|
+
- Codex는 CWD 기준으로 작업하므로 워크트리 안에서 실행한다.
|
|
49
|
+
- Codex의 stdout에서 결과를 캡처한다.
|
|
50
|
+
|
|
51
|
+
**codex provider 제약:**
|
|
52
|
+
- Codex는 Claude Code의 Read/Edit/Glob 도구가 아닌 자체 도구를 사용한다.
|
|
53
|
+
- Codex 에이전트는 `.crew/` 파일에 직접 접근할 수 없으므로, 프롬프트에 필요한 내용을 인라인으로 주입해야 한다.
|
|
54
|
+
- Codex dev-log.md 작성: Codex stdout을 오케스트레이터가 파싱하여 dev-log.md를 생성한다.
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
17
58
|
## 절대 금지
|
|
18
59
|
|
|
19
60
|
- 오케스트레이터가 코드를 직접 작성하지 않는다.
|
|
@@ -64,7 +105,16 @@ description: contract.md를 입력으로 받아 Dev + CodeReviewer + QA 파이
|
|
|
64
105
|
|
|
65
106
|
### Phase 1 — 환경 준비 (오케스트레이터 직접)
|
|
66
107
|
|
|
67
|
-
**1a.
|
|
108
|
+
**1a. Provider 설정 로드**
|
|
109
|
+
|
|
110
|
+
1. `data/provider-catalog.json`을 읽어 `agent_defaults`를 로드한다.
|
|
111
|
+
2. `.crew/config.json`이 있으면 `providers` 필드를 읽어 `agent_defaults`를 오버라이드한다.
|
|
112
|
+
3. codex provider가 하나라도 설정되어 있으면 `which codex`로 가용성을 확인한다.
|
|
113
|
+
- codex가 없으면 경고를 출력하고 해당 에이전트를 기본값(claude)으로 폴백한다.
|
|
114
|
+
|
|
115
|
+
해석된 설정을 Phase 2, 3에서 ��용한다.
|
|
116
|
+
|
|
117
|
+
**1b. contract.md 유효성 검사**
|
|
68
118
|
|
|
69
119
|
`.crew/plans/{task-id}/contract.md`를 읽는다.
|
|
70
120
|
- 파일이 존재하는가?
|
|
@@ -82,17 +132,25 @@ contract.md 유효성 검사에 실패했습니다.
|
|
|
82
132
|
[3] 이 태스크를 보류
|
|
83
133
|
```
|
|
84
134
|
|
|
85
|
-
**
|
|
135
|
+
**1c. 워크트리 생성**
|
|
136
|
+
|
|
137
|
+
Claude Code의 `EnterWorktree` 도구를 사용한다:
|
|
138
|
+
|
|
139
|
+
```
|
|
140
|
+
EnterWorktree(name="feat/{task-id}")
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
워크트리 진입 후 브랜치를 `origin/main` 기준으로 리셋한다:
|
|
86
144
|
|
|
87
145
|
```bash
|
|
88
146
|
git fetch origin main
|
|
89
|
-
git
|
|
147
|
+
git reset --hard origin/main
|
|
90
148
|
```
|
|
91
149
|
|
|
92
|
-
|
|
93
|
-
환경 파일(`.env*` 등)이 있으면 복사한다.
|
|
150
|
+
이후 모든 작업은 워크트리에서 수행한다.
|
|
151
|
+
환경 파일(`.env*` 등)이 원본 프로젝트에 있으면 복사한다.
|
|
94
152
|
|
|
95
|
-
**
|
|
153
|
+
**1d. 상태 갱신**
|
|
96
154
|
|
|
97
155
|
contract.md의 `## 상태` 섹션을 갱신한다:
|
|
98
156
|
|
|
@@ -105,12 +163,14 @@ IN_PROGRESS — Dev 에이전트가 구현 중이다.
|
|
|
105
163
|
|
|
106
164
|
### Phase 2 — 구현 (Dev 에이전트)
|
|
107
165
|
|
|
108
|
-
|
|
166
|
+
Phase 1a에서 해석된 dev 설정에 따라 디스패치한다.
|
|
167
|
+
|
|
168
|
+
#### Phase 2 — claude provider인 경우
|
|
109
169
|
|
|
110
170
|
호출:
|
|
111
171
|
|
|
112
172
|
```
|
|
113
|
-
Agent(subagent_type="dev", description="Dev: {task-id} 구현", prompt="...")
|
|
173
|
+
Agent(subagent_type="dev", model="{설정된 모델}", description="Dev: {task-id} 구현", prompt="...")
|
|
114
174
|
```
|
|
115
175
|
|
|
116
176
|
**첫 번째 실행 시 에이전트 프롬프트**:
|
|
@@ -180,6 +240,53 @@ brief.md, spec.md, analysis.md는 읽지 않는다.
|
|
|
180
240
|
- 자체 검증 5개 모두 PASS 해야 완료를 선언할 수 있다.
|
|
181
241
|
```
|
|
182
242
|
|
|
243
|
+
#### Phase 2 — codex provider인 경우
|
|
244
|
+
|
|
245
|
+
오케스트레이터가 다음을 수행한다:
|
|
246
|
+
|
|
247
|
+
1. plan.md와 contract.md의 내용을 읽어 프롬프트에 인라인으로 주입한다.
|
|
248
|
+
2. Codex를 실행한다:
|
|
249
|
+
|
|
250
|
+
```bash
|
|
251
|
+
codex exec --model {model} -c model_reasoning_effort="{reasoning}" --dangerously-bypass-approvals-and-sandbox "$(cat <<'PROMPT'
|
|
252
|
+
당신은 Dev 에이전트다. 아래 plan.md를 기반으로 코드를 구현한다.
|
|
253
|
+
|
|
254
|
+
## plan.md
|
|
255
|
+
{오케스트레이터가 plan.md 내용을 여기에 인라인 삽입}
|
|
256
|
+
|
|
257
|
+
## contract.md (수용 기준)
|
|
258
|
+
{오케스트레이터가 contract.md의 수용 기준 섹션을 여기에 인라인 삽입}
|
|
259
|
+
|
|
260
|
+
## 작업 순서
|
|
261
|
+
1. 코드베이스를 탐색하여 관련 파일을 파악한다.
|
|
262
|
+
2. 유저 스토리 단위로 순차 구현한다.
|
|
263
|
+
3. 모든 구현 완료 후 자체 검증을 실행한다:
|
|
264
|
+
- 빌드 성공 확인
|
|
265
|
+
- 린트 통과 확인
|
|
266
|
+
- 타입 체크 통과 확인
|
|
267
|
+
- 기존 테스트 스위트 통과 확인
|
|
268
|
+
4. 자체 검증이 실패하면 직접 수정하여 통과시킨다.
|
|
269
|
+
|
|
270
|
+
## 규칙
|
|
271
|
+
- plan.md에 없는 것을 구현하지 않는다.
|
|
272
|
+
- 자체 검증 모두 PASS 해야 완료를 선언할 수 있다.
|
|
273
|
+
- 기존 코드베이스의 컨벤션을 따른다.
|
|
274
|
+
|
|
275
|
+
## 완료 시 출력
|
|
276
|
+
구현 요약을 마지막에 출력하라:
|
|
277
|
+
- 변경한 파일 목록
|
|
278
|
+
- 각 유저 스토리별 구현 내용 1줄 요약
|
|
279
|
+
- 자체 검증 결과 (각 항목별 PASS/FAIL + 명령어 + 출력)
|
|
280
|
+
PROMPT
|
|
281
|
+
)"
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
3. Codex stdout을 캡처하여 `.crew/plans/{task-id}/dev-log.md`를 생성한다.
|
|
285
|
+
|
|
286
|
+
**retry 시 (codex provider)**:
|
|
287
|
+
|
|
288
|
+
동일한 패턴으로, 프롬프트에 review-report-{n}.md와 qa-report-{n}.md 내용을 인라인 삽입한다.
|
|
289
|
+
|
|
183
290
|
**Phase 2 실패 조건**: Dev 에이전트가 자체 검증을 통과하지 못한 채 완료를 선언하면 에스컬레이션.
|
|
184
291
|
|
|
185
292
|
---
|
|
@@ -190,14 +297,41 @@ CodeReviewer와 QA를 **동시에** Agent tool 2개로 호출한다.
|
|
|
190
297
|
|
|
191
298
|
#### Phase 3a — CodeReviewer
|
|
192
299
|
|
|
193
|
-
|
|
300
|
+
Phase 1a에서 해석된 code-reviewer 설정에 따라 디스패치한다.
|
|
194
301
|
|
|
195
|
-
|
|
302
|
+
**claude provider 호출:**
|
|
196
303
|
|
|
197
304
|
```
|
|
198
|
-
Agent(subagent_type="code-reviewer", description="CodeReviewer: {task-id} 코드 리뷰", prompt="...")
|
|
305
|
+
Agent(subagent_type="code-reviewer", model="{설정된 모델}", description="CodeReviewer: {task-id} 코드 리뷰", prompt="...")
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
**codex provider 호출:**
|
|
309
|
+
|
|
310
|
+
오케스트레이터가 `git diff main...HEAD`를 실행하여 diff를 캡처한 뒤, diff와 가드레일을 프롬프트에 인라인 삽입하여 Codex를 실행한다.
|
|
311
|
+
|
|
312
|
+
```bash
|
|
313
|
+
codex exec --model {model} -c model_reasoning_effort="{reasoning}" --dangerously-bypass-approvals-and-sandbox "$(cat <<'PROMPT'
|
|
314
|
+
당신은 CodeReviewer다. 아래 코드 변경 사항의 품질을 판단하라.
|
|
315
|
+
|
|
316
|
+
## 변경 사항 (git diff)
|
|
317
|
+
{오케스트레이터가 git diff 결과를 인라인 삽입}
|
|
318
|
+
|
|
319
|
+
## 가드레일
|
|
320
|
+
### Must
|
|
321
|
+
{contract.md에서 추출한 Must 항목}
|
|
322
|
+
### Must NOT
|
|
323
|
+
{contract.md에서 추출한 Must NOT 항목}
|
|
324
|
+
|
|
325
|
+
## 검토 항목 / 판정 규칙 / 출력 형식
|
|
326
|
+
(claude provider 프롬프트와 동일)
|
|
327
|
+
PROMPT
|
|
328
|
+
)"
|
|
199
329
|
```
|
|
200
330
|
|
|
331
|
+
Codex stdout을 캡처하여 review-report.md 내용으로 사용한다.
|
|
332
|
+
|
|
333
|
+
**공통 사전 작업 (provider 무관):**
|
|
334
|
+
|
|
201
335
|
오케스트레이터가 해야 할 사전 작업:
|
|
202
336
|
1. contract.md에서 가드레일 섹션(Must/Must NOT)만 추출한다.
|
|
203
337
|
2. 가드레일을 CodeReviewer 프롬프트에 인라인으로 주입한다.
|
|
@@ -239,12 +373,20 @@ contract.md, plan.md, brief.md, spec.md, dev-log.md는 읽지 않는다.
|
|
|
239
373
|
|
|
240
374
|
#### Phase 3b — QA
|
|
241
375
|
|
|
242
|
-
|
|
376
|
+
Phase 1a에서 해석된 qa 설정에 따라 디스패치한다.
|
|
243
377
|
|
|
244
|
-
|
|
378
|
+
**claude provider 호출:**
|
|
245
379
|
|
|
246
380
|
```
|
|
247
|
-
Agent(subagent_type="qa", description="QA: {task-id} 검증", prompt="...")
|
|
381
|
+
Agent(subagent_type="qa", model="{설정된 모델}", description="QA: {task-id} 검증", prompt="...")
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
**codex provider 호출:**
|
|
385
|
+
|
|
386
|
+
오케스트레이터가 plan.md 내용을 읽어 프롬프트에 인라인 삽입하여 Codex를 실행한다. Codex stdout을 캡처하여 qa-report.md 내용으로 사용한다.
|
|
387
|
+
|
|
388
|
+
```bash
|
|
389
|
+
codex exec --model {model} -c model_reasoning_effort="{reasoning}" --dangerously-bypass-approvals-and-sandbox "{QA 프롬프트 + plan.md 인라인}"
|
|
248
390
|
```
|
|
249
391
|
|
|
250
392
|
에이전트 프롬프트:
|
|
@@ -290,11 +432,16 @@ CodeReviewer와 QA 에이전트는 read-only이므로 파일을 직접 작성하
|
|
|
290
432
|
|
|
291
433
|
**Phase 3 병렬 실행 방법**:
|
|
292
434
|
|
|
293
|
-
오케스트레이터는
|
|
435
|
+
오케스트레이터는 CodeReviewer와 QA를 **동시에** 호출한다. provider 조합에 따라:
|
|
436
|
+
|
|
437
|
+
- 둘 다 claude → Agent tool 2개를 한 번에 호출
|
|
438
|
+
- 둘 다 codex → Bash tool 2개를 한 번에 호출
|
|
439
|
+
- 혼합 → Agent + Bash를 한 번에 호출
|
|
294
440
|
|
|
295
441
|
```
|
|
296
|
-
|
|
297
|
-
Agent(subagent_type="
|
|
442
|
+
# 예: code-reviewer=claude, qa=codex
|
|
443
|
+
Agent(subagent_type="code-reviewer", model="opus", description="CodeReviewer: {task-id}", prompt="...")
|
|
444
|
+
Bash("codex exec --model gpt-5.4 ... '{QA 프롬프트}'")
|
|
298
445
|
```
|
|
299
446
|
|
|
300
447
|
---
|
|
@@ -339,7 +486,15 @@ PR: {PR URL}
|
|
|
339
486
|
|
|
340
487
|
`.dev_loop_count` 파일이 존재하면 삭제한다.
|
|
341
488
|
|
|
342
|
-
**5d.
|
|
489
|
+
**5d. 워크트리 종료**
|
|
490
|
+
|
|
491
|
+
```
|
|
492
|
+
ExitWorktree(action="remove")
|
|
493
|
+
```
|
|
494
|
+
|
|
495
|
+
PR push가 완료되었으므로 로컬 워크트리를 제거하고 원본 프로젝트 디렉토리로 복귀한다.
|
|
496
|
+
|
|
497
|
+
**5e. 완료 반환**
|
|
343
498
|
|
|
344
499
|
```
|
|
345
500
|
상태: COMPLETE
|
|
@@ -378,6 +533,7 @@ Phase 4에서 FAIL이면:
|
|
|
378
533
|
에스컬레이션 시:
|
|
379
534
|
- `.dev_loop_count` 파일을 삭제한다.
|
|
380
535
|
- contract.md 상태를 `BLOCKED`으로 갱신한다.
|
|
536
|
+
- `ExitWorktree(action="keep")`으로 원본 프로젝트 디렉토리로 복귀한다.
|
|
381
537
|
|
|
382
538
|
**조건 2 — 같은 기준 3회 연속 실패**:
|
|
383
539
|
|
|
@@ -391,6 +547,8 @@ review-report.md와 qa-report.md에서 FAIL 항목을 확인한다.
|
|
|
391
547
|
[3] 이 태스크를 보류
|
|
392
548
|
```
|
|
393
549
|
|
|
550
|
+
에스컬레이션 시 `ExitWorktree(action="keep")`으로 원본 프로젝트 디렉토리로 복귀한다.
|
|
551
|
+
|
|
394
552
|
**6c. 피드백 아카이브**
|
|
395
553
|
|
|
396
554
|
`n = 카운터 + 1`
|
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: crew-setup
|
|
3
|
-
description: claude-crew 플러그인 초기 설정 — HUD statusline 설치
|
|
3
|
+
description: claude-crew 플러그인 초기 설정 — HUD statusline 설치 + provider 설정
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
## 역할
|
|
7
7
|
|
|
8
|
-
claude-crew 플러그인의
|
|
8
|
+
claude-crew 플러그인의 초기 설정을 수행한다:
|
|
9
|
+
1. HUD statusline 설치
|
|
10
|
+
2. 에이전트별 provider/model 설정
|
|
9
11
|
|
|
10
|
-
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Step 1 — HUD statusline 설치
|
|
11
15
|
|
|
12
16
|
1. `~/.claude/settings.json`을 읽는다.
|
|
13
17
|
2. `statusLine` 필드를 crew HUD 스크립트로 설정한다:
|
|
@@ -23,7 +27,115 @@ claude-crew 플러그인의 HUD statusline을 사용자 환경에 설치한다.
|
|
|
23
27
|
- 성공 시: "CREW HUD가 설치되었습니다. 다음 세션부터 statusline에 표시됩니다."
|
|
24
28
|
- 실패 시: 에러 내용을 알린다.
|
|
25
29
|
|
|
26
|
-
|
|
30
|
+
**주의**: `settings.json`의 다른 필드는 절대 수정하지 않는다. statusLine만 교체한다.
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Step 2 — Provider 설정
|
|
35
|
+
|
|
36
|
+
에이전트별로 어떤 provider(claude/codex)와 model을 사용할지 설정한다.
|
|
37
|
+
|
|
38
|
+
### 2a. 카탈로그 로드
|
|
39
|
+
|
|
40
|
+
`data/provider-catalog.json`을 읽어 사용 가능한 provider와 model 목록을 로드한다.
|
|
41
|
+
|
|
42
|
+
### 2b. Codex CLI 가용성 확인
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
which codex
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
- codex가 없으면: "Codex CLI가 설치되어 있지 않습니다. 모든 에이전트가 Claude를 사용합니다." 안내 후 Step 2를 스킵한다.
|
|
49
|
+
- codex가 있으면: 계속 진행한다.
|
|
50
|
+
|
|
51
|
+
### 2c. 기존 설정 표시
|
|
52
|
+
|
|
53
|
+
`.crew/config.json`이 있으면 현재 설정을 표시한다. 없으면 기본값을 표시한다.
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
현재 에이전트 설정:
|
|
57
|
+
- dev: claude / opus (기본값)
|
|
58
|
+
- code-reviewer: claude / opus (기본값)
|
|
59
|
+
- qa: claude / sonnet (기본값)
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### 2d. 설정할 에이전트 선택
|
|
63
|
+
|
|
64
|
+
사용자에게 설정을 변경할 에이전트를 선택하게 한다.
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
설정을 변경할 에이전트를 선택하세요 (쉼표 구분, 엔터 = 스킵):
|
|
68
|
+
dev, code-reviewer, qa
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
- 사용자가 엔터만 누르거나 "없음"/"스킵"을 입력하면 Step 2를 종료한다.
|
|
72
|
+
- 예시 입력: `dev`, `dev, code-reviewer`
|
|
73
|
+
|
|
74
|
+
### 2e. 선택된 에이전트별 설정
|
|
75
|
+
|
|
76
|
+
선택된 각 에이전트에 대해 순차적으로:
|
|
77
|
+
|
|
78
|
+
**Provider 선택:**
|
|
79
|
+
```
|
|
80
|
+
── {agent} ──
|
|
81
|
+
Provider:
|
|
82
|
+
[1] claude
|
|
83
|
+
[2] codex
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
**Model 선택 (provider에 따라 목록이 다름):**
|
|
87
|
+
|
|
88
|
+
카탈로그에서 해당 provider의 models 배열을 번호 목록으로 표시한다. 1번이 추천.
|
|
89
|
+
|
|
90
|
+
claude 선택 시:
|
|
91
|
+
```
|
|
92
|
+
Model:
|
|
93
|
+
[1] Opus 4.6 — 최고 품질, 복잡한 구현 (추천)
|
|
94
|
+
[2] Sonnet 4.6 — 빠르고 저렴, Opus급 성능
|
|
95
|
+
[3] Haiku 4.5 — 최저 비용, 단순 태스크
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
codex 선택 시:
|
|
99
|
+
```
|
|
100
|
+
Model:
|
|
101
|
+
[1] GPT-5.4 xhigh (추천) — 최고 성능, 토큰 多
|
|
102
|
+
[2] GPT-5.4 high — 고성능, 균형잡힌 비용
|
|
103
|
+
[3] GPT-5.4 medium — 빠르고 저렴
|
|
104
|
+
[4] o3 high — 추론 특화
|
|
105
|
+
[5] o3 medium — 추론 특화, 저비용
|
|
106
|
+
[6] GPT-5.4 Mini — 최저 비용
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### 2f. 설정 저장
|
|
110
|
+
|
|
111
|
+
선택 결과를 `.crew/config.json`에 저장한다.
|
|
112
|
+
|
|
113
|
+
**규칙:**
|
|
114
|
+
- 기본값과 동일한 설정은 저장하지 않는다 (기본값은 `agent_defaults` 참조).
|
|
115
|
+
- 기본값과 다른 설정만 `providers` 객체에 기록한다.
|
|
116
|
+
- 기존 `.crew/config.json`이 있으면 `providers` 필드만 머지한다 (다른 필드 보존).
|
|
117
|
+
- `.crew/` 디렉토리가 없으면 생성한다.
|
|
118
|
+
|
|
119
|
+
**저장 형식:**
|
|
120
|
+
|
|
121
|
+
```json
|
|
122
|
+
{
|
|
123
|
+
"providers": {
|
|
124
|
+
"dev": { "provider": "codex", "model": "gpt-5.4", "reasoning": "xhigh" }
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
- claude provider일 때: `reasoning` 필드 생략
|
|
130
|
+
- codex provider일 때: 카탈로그의 `reasoning` 값 포함 (`null`이면 생략)
|
|
131
|
+
|
|
132
|
+
### 2g. 확인 메시지
|
|
133
|
+
|
|
134
|
+
```
|
|
135
|
+
✓ Provider 설정 완료:
|
|
136
|
+
- dev: codex / gpt-5.4 xhigh
|
|
137
|
+
- code-reviewer: claude / opus (기본값)
|
|
138
|
+
- qa: claude / sonnet (기본값)
|
|
27
139
|
|
|
28
|
-
|
|
29
|
-
|
|
140
|
+
설정 파일: .crew/config.json
|
|
141
|
+
```
|