@jjlabsio/claude-crew 0.1.7 → 0.1.9
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/README.md +1 -1
- package/hud/index.mjs +21 -4
- package/package.json +1 -1
- package/skills/crew/SKILL.md +17 -15
- package/skills/crew-dev/SKILL.md +26 -18
- package/skills/crew-plan/SKILL.md +17 -7
|
@@ -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.9",
|
|
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.9"
|
|
32
32
|
}
|
package/README.md
CHANGED
package/hud/index.mjs
CHANGED
|
@@ -150,11 +150,17 @@ function parseTranscript(transcriptPath) {
|
|
|
150
150
|
|
|
151
151
|
// Map of tool_use_id -> agent info
|
|
152
152
|
const agentMap = new Map();
|
|
153
|
+
let lastTimestamp = null;
|
|
153
154
|
|
|
154
155
|
for (const line of lines) {
|
|
155
156
|
let entry;
|
|
156
157
|
try { entry = JSON.parse(line); } catch { continue; }
|
|
157
158
|
|
|
159
|
+
// Track last known timestamp
|
|
160
|
+
if (entry.timestamp) {
|
|
161
|
+
lastTimestamp = entry.timestamp;
|
|
162
|
+
}
|
|
163
|
+
|
|
158
164
|
// Session start time
|
|
159
165
|
if (!result.sessionStart && entry.timestamp) {
|
|
160
166
|
result.sessionStart = new Date(entry.timestamp);
|
|
@@ -174,12 +180,13 @@ function parseTranscript(transcriptPath) {
|
|
|
174
180
|
const agentType = input.subagent_type || input.type || 'general';
|
|
175
181
|
const model = input.model || null;
|
|
176
182
|
const description = input.description || input.prompt?.slice(0, 50) || '';
|
|
183
|
+
const ts = entry.timestamp || lastTimestamp;
|
|
177
184
|
agentMap.set(id, {
|
|
178
185
|
id,
|
|
179
186
|
type: agentType,
|
|
180
187
|
model,
|
|
181
188
|
description,
|
|
182
|
-
startTime:
|
|
189
|
+
startTime: ts ? new Date(ts) : null,
|
|
183
190
|
status: 'running',
|
|
184
191
|
});
|
|
185
192
|
}
|
|
@@ -219,7 +226,14 @@ function parseTranscript(transcriptPath) {
|
|
|
219
226
|
}
|
|
220
227
|
}
|
|
221
228
|
|
|
222
|
-
|
|
229
|
+
// Filter running agents, mark stale ones (>30min) as completed
|
|
230
|
+
const STALE_THRESHOLD_MS = 30 * 60 * 1000;
|
|
231
|
+
const now = Date.now();
|
|
232
|
+
result.agents = [...agentMap.values()].filter(a => {
|
|
233
|
+
if (a.status !== 'running') return false;
|
|
234
|
+
if (a.startTime && (now - a.startTime.getTime()) > STALE_THRESHOLD_MS) return false;
|
|
235
|
+
return true;
|
|
236
|
+
});
|
|
223
237
|
} catch { /* ignore parse errors */ }
|
|
224
238
|
|
|
225
239
|
return result;
|
|
@@ -241,9 +255,11 @@ function shortModelName(model) {
|
|
|
241
255
|
// Agent duration formatting
|
|
242
256
|
// ---------------------------------------------------------------------------
|
|
243
257
|
function formatAgentDuration(startTime) {
|
|
258
|
+
if (!startTime) return '?';
|
|
244
259
|
const ms = Date.now() - startTime.getTime();
|
|
245
260
|
const seconds = Math.floor(ms / 1000);
|
|
246
261
|
const minutes = Math.floor(seconds / 60);
|
|
262
|
+
if (seconds < 10) return '';
|
|
247
263
|
if (seconds < 60) return `${seconds}s`;
|
|
248
264
|
return `${minutes}m`;
|
|
249
265
|
}
|
|
@@ -265,13 +281,14 @@ function renderAgentsMultiLine(agents, maxLines = 5) {
|
|
|
265
281
|
const isLast = index === displayCount - 1 && sorted.length <= maxLines;
|
|
266
282
|
const prefix = isLast ? '\u2514\u2500' : '\u251c\u2500';
|
|
267
283
|
|
|
268
|
-
const
|
|
284
|
+
const rawType = a.type.includes(':') ? a.type.split(':').pop() : a.type;
|
|
285
|
+
const name = rawType.padEnd(7);
|
|
269
286
|
const model = shortModelName(a.model).padEnd(8);
|
|
270
287
|
const duration = formatAgentDuration(a.startTime).padStart(4);
|
|
271
288
|
const desc = a.description.length > 40 ? a.description.slice(0, 37) + '...' : a.description;
|
|
272
289
|
|
|
273
290
|
detailLines.push(
|
|
274
|
-
`${dim(prefix)} ${cyan(name)}${model}${dim(duration)} ${desc}`
|
|
291
|
+
`${dim(prefix)} ${cyan(name)} ${model}${dim(duration)} ${desc}`
|
|
275
292
|
);
|
|
276
293
|
});
|
|
277
294
|
|
package/package.json
CHANGED
package/skills/crew/SKILL.md
CHANGED
|
@@ -166,22 +166,24 @@ ACTIVE
|
|
|
166
166
|
## 에이전트 라인업
|
|
167
167
|
|
|
168
168
|
### crew-plan
|
|
169
|
-
| 에이전트 | 모델 | 역할 |
|
|
170
|
-
|
|
171
|
-
| PM | Opus | 유저 인터뷰, spec.md 작성 (유저 가치만) |
|
|
172
|
-
| TechLead | Opus | 사전 분석, 아키텍처 방향, 가드레일 |
|
|
173
|
-
| Planner | Opus | 계획 문서 작성 |
|
|
174
|
-
| PlanEvaluator | Sonnet | E1-E4 하드 임계값 검증 |
|
|
169
|
+
| 에이전트 | subagent_type | 모델 | 역할 |
|
|
170
|
+
|----------|--------------|------|------|
|
|
171
|
+
| PM | pm | Opus | 유저 인터뷰, spec.md 작성 (유저 가치만) |
|
|
172
|
+
| TechLead | techlead | Opus | 사전 분석, 아키텍처 방향, 가드레일 |
|
|
173
|
+
| Planner | planner | Opus | 계획 문서 작성 |
|
|
174
|
+
| PlanEvaluator | plan-evaluator | Sonnet | E1-E4 하드 임계값 검증 |
|
|
175
175
|
|
|
176
176
|
### crew-dev
|
|
177
|
-
| 에이전트 | 모델 | 역할 |
|
|
178
|
-
|
|
179
|
-
| Dev | Opus | 코드 구현 + 자체 검증 |
|
|
180
|
-
| CodeReviewer | Opus | 코드 품질 + 가드레일 위반 판정 |
|
|
181
|
-
| QA | Sonnet | 실행 검증 (빌드/테스트/E2E) |
|
|
177
|
+
| 에이전트 | subagent_type | 모델 | 역할 |
|
|
178
|
+
|----------|--------------|------|------|
|
|
179
|
+
| Dev | dev | Opus | 코드 구현 + 자체 검증 |
|
|
180
|
+
| CodeReviewer | code-reviewer | Opus | 코드 품질 + 가드레일 위반 판정 |
|
|
181
|
+
| QA | qa | Sonnet | 실행 검증 (빌드/테스트/E2E) |
|
|
182
182
|
|
|
183
183
|
### 공유 서브에이전트
|
|
184
|
-
| 에이전트 | 모델 | 역할 |
|
|
185
|
-
|
|
186
|
-
| Explorer | Haiku | 코드베이스 탐색 (병렬, Read-only) |
|
|
187
|
-
| Researcher | Sonnet | 외부 정보 조사 (필요시만, Read-only) |
|
|
184
|
+
| 에이전트 | subagent_type | 모델 | 역할 |
|
|
185
|
+
|----------|--------------|------|------|
|
|
186
|
+
| Explorer | explorer | Haiku | 코드베이스 탐색 (병렬, Read-only) |
|
|
187
|
+
| Researcher | researcher | Sonnet | 외부 정보 조사 (필요시만, Read-only) |
|
|
188
|
+
|
|
189
|
+
**중요**: 모든 에이전트 호출 시 반드시 `subagent_type` 파라미터를 지정해야 한다. HUD에서 에이전트 타입을 식별하는 데 사용된다.
|
package/skills/crew-dev/SKILL.md
CHANGED
|
@@ -21,6 +21,7 @@ description: contract.md를 입력으로 받아 Dev + CodeReviewer + QA 파이
|
|
|
21
21
|
- brief.md를 어떤 에이전트에게도 전달하지 않는다.
|
|
22
22
|
- contract.md를 CodeReviewer에게 전달하지 않는다 (가드레일만 인라인 주입).
|
|
23
23
|
- plan.md를 CodeReviewer에게 전달하지 않는다.
|
|
24
|
+
- git commit 시 `--no-verify`를 생략하지 않는다 (호스트 프로젝트의 pre-commit hook 중복 실행 방지).
|
|
24
25
|
- Dev가 자체 검증을 통과하지 못한 상태에서 검증 단계로 넘기지 않는다.
|
|
25
26
|
|
|
26
27
|
---
|
|
@@ -49,11 +50,13 @@ description: contract.md를 입력으로 받아 Dev + CodeReviewer + QA 파이
|
|
|
49
50
|
|
|
50
51
|
## 에이전트 정보 차단 정책
|
|
51
52
|
|
|
52
|
-
| 에이전트 | 볼 수 있는 것 | 차단 | 차단 근거 |
|
|
53
|
-
|
|
54
|
-
| **Dev** | plan.md, contract.md | brief.md, spec.md, analysis.md | 의도 추측 방지, plan+contract에 필요 정보 포함 |
|
|
55
|
-
| **CodeReviewer** | git diff, 가드레일(인라인) | contract.md, plan.md, brief.md, spec.md, dev-log.md | 수용 기준 체리피킹 방지 |
|
|
56
|
-
| **QA** | plan.md | contract.md, brief.md, spec.md | 검증 편향 방지 |
|
|
53
|
+
| 에이전트 | subagent_type | 볼 수 있는 것 | 차단 | 차단 근거 |
|
|
54
|
+
|----------|--------------|-------------|------|----------|
|
|
55
|
+
| **Dev** | dev | plan.md, contract.md | brief.md, spec.md, analysis.md | 의도 추측 방지, plan+contract에 필요 정보 포함 |
|
|
56
|
+
| **CodeReviewer** | code-reviewer | git diff(직접 실행), 가드레일(인라인) | contract.md, plan.md, brief.md, spec.md, dev-log.md | 수용 기준 체리피킹 방지 (.crew/는 .gitignore 대상이므로 diff에 노출되지 않음) |
|
|
57
|
+
| **QA** | qa | plan.md | contract.md, brief.md, spec.md | 검증 편향 방지 |
|
|
58
|
+
|
|
59
|
+
**중요**: 모든 에이전트 호출 시 반드시 `subagent_type` 파라미터를 지정해야 한다. HUD에서 에이전트 타입을 식별하는 데 사용된다.
|
|
57
60
|
|
|
58
61
|
---
|
|
59
62
|
|
|
@@ -104,6 +107,8 @@ IN_PROGRESS — Dev 에이전트가 구현 중이다.
|
|
|
104
107
|
|
|
105
108
|
**모델**: opus
|
|
106
109
|
|
|
110
|
+
에이전트 호출 시 반드시 `subagent_type: "dev"`를 지정한다.
|
|
111
|
+
|
|
107
112
|
**첫 번째 실행 시 에이전트 프롬프트**:
|
|
108
113
|
|
|
109
114
|
```
|
|
@@ -124,6 +129,7 @@ brief.md, spec.md, analysis.md는 읽지 않는다.
|
|
|
124
129
|
- 린트 통과 확인
|
|
125
130
|
- 타입 체크 통과 확인
|
|
126
131
|
- 기존 테스트 스위트 통과 확인
|
|
132
|
+
- lint-staged 검증: `npx lint-staged --dry-run` 실행 (설정이 있는 경우에만)
|
|
127
133
|
6. 자체 검증이 모두 통과하면 완료를 선언한다.
|
|
128
134
|
자체 검증이 실패하면 직접 수정하여 통과시킨다.
|
|
129
135
|
|
|
@@ -132,7 +138,7 @@ brief.md, spec.md, analysis.md는 읽지 않는다.
|
|
|
132
138
|
|
|
133
139
|
## 규칙
|
|
134
140
|
- plan.md에 없는 것을 구현하지 않는다 (스코프 크리프 금지).
|
|
135
|
-
- 자체 검증
|
|
141
|
+
- 자체 검증 5개(빌드/린트/타입/테스트/lint-staged) 모두 PASS 해야 완료를 선언할 수 있다.
|
|
136
142
|
- 기존 코드베이스의 컨벤션을 따른다.
|
|
137
143
|
```
|
|
138
144
|
|
|
@@ -155,11 +161,11 @@ brief.md, spec.md, analysis.md는 읽지 않는다.
|
|
|
155
161
|
1. 피드백에서 FAIL 항목을 모두 파악한다.
|
|
156
162
|
2. 각 FAIL 항목에 대해 수정을 수행한다.
|
|
157
163
|
3. dev-log.md를 갱신한다 (최상단에 "수정 이력 (retry {n})" 섹션 추가).
|
|
158
|
-
4. 자체 검증
|
|
164
|
+
4. 자체 검증 5개를 모두 다시 실행한다.
|
|
159
165
|
|
|
160
166
|
## 규칙
|
|
161
167
|
- 피드백에서 지적하지 않은 부분을 추가로 변경하지 않는다.
|
|
162
|
-
- 자체 검증
|
|
168
|
+
- 자체 검증 5개 모두 PASS 해야 완료를 선언할 수 있다.
|
|
163
169
|
```
|
|
164
170
|
|
|
165
171
|
**Phase 2 실패 조건**: Dev 에이전트가 자체 검증을 통과하지 못한 채 완료를 선언하면 에스컬레이션.
|
|
@@ -174,10 +180,11 @@ CodeReviewer와 QA를 **동시에** Agent tool 2개로 호출한다.
|
|
|
174
180
|
|
|
175
181
|
**모델**: opus
|
|
176
182
|
|
|
183
|
+
에이전트 호출 시 반드시 `subagent_type: "code-reviewer"`를 지정한다.
|
|
184
|
+
|
|
177
185
|
오케스트레이터가 해야 할 사전 작업:
|
|
178
|
-
1.
|
|
179
|
-
2.
|
|
180
|
-
3. 둘 다 CodeReviewer 프롬프트에 인라인으로 주입한다.
|
|
186
|
+
1. contract.md에서 가드레일 섹션(Must/Must NOT)만 추출한다.
|
|
187
|
+
2. 가드레일을 CodeReviewer 프롬프트에 인라인으로 주입한다.
|
|
181
188
|
|
|
182
189
|
에이전트 프롬프트:
|
|
183
190
|
|
|
@@ -185,13 +192,10 @@ CodeReviewer와 QA를 **동시에** Agent tool 2개로 호출한다.
|
|
|
185
192
|
당신은 CodeReviewer 에이전트다. 코드 변경 사항의 품질을 판단한다.
|
|
186
193
|
|
|
187
194
|
## 입력
|
|
188
|
-
|
|
195
|
+
`git diff main...HEAD`를 직접 실행하여 변경 사항을 확인하라.
|
|
189
196
|
contract.md, plan.md, brief.md, spec.md, dev-log.md는 읽지 않는다.
|
|
190
197
|
코드만 보고 판단한다.
|
|
191
198
|
|
|
192
|
-
### diff
|
|
193
|
-
{git diff main...HEAD 출력}
|
|
194
|
-
|
|
195
199
|
### 가드레일 (contract.md에서 추출)
|
|
196
200
|
#### Must
|
|
197
201
|
- {오케스트레이터가 contract.md에서 복사한 내용}
|
|
@@ -221,6 +225,8 @@ contract.md, plan.md, brief.md, spec.md, dev-log.md는 읽지 않는다.
|
|
|
221
225
|
|
|
222
226
|
**모델**: sonnet
|
|
223
227
|
|
|
228
|
+
에이전트 호출 시 반드시 `subagent_type: "qa"`를 지정한다.
|
|
229
|
+
|
|
224
230
|
에이전트 프롬프트:
|
|
225
231
|
|
|
226
232
|
```
|
|
@@ -256,8 +262,8 @@ contract.md, brief.md, spec.md는 읽지 않는다.
|
|
|
256
262
|
오케스트레이터는 한 번의 메시지에서 두 개의 Agent tool 호출을 동시에 수행한다:
|
|
257
263
|
|
|
258
264
|
```
|
|
259
|
-
Agent(name="code-reviewer", model="opus", prompt="...")
|
|
260
|
-
Agent(name="qa", model="sonnet", prompt="...")
|
|
265
|
+
Agent(name="code-reviewer", subagent_type="code-reviewer", model="opus", prompt="...")
|
|
266
|
+
Agent(name="qa", subagent_type="qa", model="sonnet", prompt="...")
|
|
261
267
|
```
|
|
262
268
|
|
|
263
269
|
---
|
|
@@ -278,10 +284,12 @@ Agent(name="qa", model="sonnet", prompt="...")
|
|
|
278
284
|
|
|
279
285
|
```bash
|
|
280
286
|
git add -A
|
|
281
|
-
git commit -m "feat({task-id}): {contract.md 목표 1줄 요약}"
|
|
287
|
+
git commit --no-verify -m "feat({task-id}): {contract.md 목표 1줄 요약}"
|
|
282
288
|
git push -u origin feat/{task-id}
|
|
283
289
|
```
|
|
284
290
|
|
|
291
|
+
> `--no-verify`: crew-dev가 이미 빌드/린트/타입/테스트 + lint-staged 검증을 완료했으므로 호스트 프로젝트의 pre-commit hook을 중복 실행하지 않는다.
|
|
292
|
+
|
|
285
293
|
PR을 생성한다 (머지하지 않는다).
|
|
286
294
|
|
|
287
295
|
**5b. 상태 갱신**
|
|
@@ -63,6 +63,8 @@ brief.md가 없거나 비어 있습니다. 계획 파이프라인을 시작할
|
|
|
63
63
|
**모델**: opus
|
|
64
64
|
**건너뛰기 조건**: 엔지니어링 유형이면 이 단계를 건너뛴다.
|
|
65
65
|
|
|
66
|
+
에이전트 호출 시 반드시 `subagent_type: "pm"`을 지정한다.
|
|
67
|
+
|
|
66
68
|
에이전트 프롬프트:
|
|
67
69
|
|
|
68
70
|
```
|
|
@@ -99,6 +101,8 @@ PM 에이전트가 요구사항 정의에 실패했습니다.
|
|
|
99
101
|
**모델**: opus
|
|
100
102
|
**실행 조건**: 항상 (양쪽 유형 모두)
|
|
101
103
|
|
|
104
|
+
에이전트 호출 시 반드시 `subagent_type: "techlead"`를 지정한다.
|
|
105
|
+
|
|
102
106
|
에이전트 프롬프트:
|
|
103
107
|
|
|
104
108
|
```
|
|
@@ -132,6 +136,8 @@ analysis.md 필수 섹션: 요구사항 보완, 코드베이스 맥락(관련
|
|
|
132
136
|
|
|
133
137
|
**모델**: opus
|
|
134
138
|
|
|
139
|
+
에이전트 호출 시 반드시 `subagent_type: "planner"`를 지정한다.
|
|
140
|
+
|
|
135
141
|
**첫 번째 실행 시 에이전트 프롬프트**:
|
|
136
142
|
|
|
137
143
|
```
|
|
@@ -186,6 +192,8 @@ plan.md 최상단에 "이전 피드백 반영" 섹션을 추가한다.
|
|
|
186
192
|
|
|
187
193
|
**모델**: sonnet (하드 임계값 판정에서 Opus 합리화 방지)
|
|
188
194
|
|
|
195
|
+
에이전트 호출 시 반드시 `subagent_type: "plan-evaluator"`를 지정한다.
|
|
196
|
+
|
|
189
197
|
에이전트 프롬프트:
|
|
190
198
|
|
|
191
199
|
```
|
|
@@ -365,13 +373,15 @@ Planner + PlanEvaluator 사이클은 최대 5회 (초기 1회 + retry 최대 4
|
|
|
365
373
|
|
|
366
374
|
## 에이전트 호출 컨텍스트 규칙
|
|
367
375
|
|
|
368
|
-
| 에이전트 | 모델 | 주입할 파일 | 차단할 파일 |
|
|
369
|
-
|
|
370
|
-
| PM | opus | brief.md | — |
|
|
371
|
-
| TechLead | opus | spec.md (유저 가치) 또는 brief.md (엔지니어링) | — |
|
|
372
|
-
| Planner (첫 번째) | opus | spec.md (유저 가치 시) + analysis.md | brief.md |
|
|
373
|
-
| Planner (retry) | opus | spec.md (유저 가치 시) + analysis.md + review-{n}.md | brief.md |
|
|
374
|
-
| PlanEvaluator | sonnet | spec.md/brief.md + analysis.md + plan.md | brief.md (유저 가치 시) |
|
|
376
|
+
| 에이전트 | subagent_type | 모델 | 주입할 파일 | 차단할 파일 |
|
|
377
|
+
|----------|--------------|------|------------|------------|
|
|
378
|
+
| PM | pm | opus | brief.md | — |
|
|
379
|
+
| TechLead | techlead | opus | spec.md (유저 가치) 또는 brief.md (엔지니어링) | — |
|
|
380
|
+
| Planner (첫 번째) | planner | opus | spec.md (유저 가치 시) + analysis.md | brief.md |
|
|
381
|
+
| Planner (retry) | planner | opus | spec.md (유저 가치 시) + analysis.md + review-{n}.md | brief.md |
|
|
382
|
+
| PlanEvaluator | plan-evaluator | sonnet | spec.md/brief.md + analysis.md + plan.md | brief.md (유저 가치 시) |
|
|
383
|
+
|
|
384
|
+
**중요**: 모든 에이전트 호출 시 반드시 `subagent_type` 파라미터를 지정해야 한다. HUD에서 에이전트 타입을 식별하는 데 사용된다.
|
|
375
385
|
|
|
376
386
|
---
|
|
377
387
|
|