@jjlabsio/claude-crew 0.1.7 → 0.1.8

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.
@@ -11,7 +11,7 @@
11
11
  "name": "claude-crew",
12
12
  "source": "./",
13
13
  "description": "오케스트레이터 + PM, 플래너, 개발, QA, 마케팅 에이전트 팀으로 단일 제품의 개발과 마케팅을 통합 관리",
14
- "version": "0.1.7",
14
+ "version": "0.1.8",
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.7"
31
+ "version": "0.1.8"
32
32
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-crew",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
4
4
  "description": "1인 SaaS 개발자를 위한 멀티 에이전트 오케스트레이션 — 개발, 마케팅, 일정을 한 대화에서 통합 관리",
5
5
  "author": {
6
6
  "name": "Jaejin Song",
package/README.md CHANGED
@@ -9,7 +9,7 @@
9
9
  Claude Code에서:
10
10
 
11
11
  ```
12
- /plugin marketplace add https://github.com/jjlabsio/claude-crew
12
+ /plugin marketplace add jjlabsio/claude-crew
13
13
  /plugin install claude-crew
14
14
  ```
15
15
 
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: entry.timestamp ? new Date(entry.timestamp) : new Date(),
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
- result.agents = [...agentMap.values()].filter(a => a.status === 'running');
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
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jjlabsio/claude-crew",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
4
4
  "description": "1인 SaaS 개발자를 위한 멀티 에이전트 오케스트레이션 — 개발, 마케팅, 일정을 한 대화에서 통합 관리",
5
5
  "author": "Jaejin Song <wowlxx28@gmail.com>",
6
6
  "license": "MIT",
@@ -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에서 에이전트 타입을 식별하는 데 사용된다.
@@ -49,11 +49,13 @@ description: contract.md를 입력으로 받아 Dev + CodeReviewer + QA 파이
49
49
 
50
50
  ## 에이전트 정보 차단 정책
51
51
 
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 | 검증 편향 방지 |
52
+ | 에이전트 | subagent_type | 볼 수 있는 것 | 차단 | 차단 근거 |
53
+ |----------|--------------|-------------|------|----------|
54
+ | **Dev** | dev | plan.md, contract.md | brief.md, spec.md, analysis.md | 의도 추측 방지, plan+contract에 필요 정보 포함 |
55
+ | **CodeReviewer** | code-reviewer | git diff, 가드레일(인라인) | contract.md, plan.md, brief.md, spec.md, dev-log.md | 수용 기준 체리피킹 방지 |
56
+ | **QA** | qa | plan.md | contract.md, brief.md, spec.md | 검증 편향 방지 |
57
+
58
+ **중요**: 모든 에이전트 호출 시 반드시 `subagent_type` 파라미터를 지정해야 한다. HUD에서 에이전트 타입을 식별하는 데 사용된다.
57
59
 
58
60
  ---
59
61
 
@@ -104,6 +106,8 @@ IN_PROGRESS — Dev 에이전트가 구현 중이다.
104
106
 
105
107
  **모델**: opus
106
108
 
109
+ 에이전트 호출 시 반드시 `subagent_type: "dev"`를 지정한다.
110
+
107
111
  **첫 번째 실행 시 에이전트 프롬프트**:
108
112
 
109
113
  ```
@@ -174,6 +178,8 @@ CodeReviewer와 QA를 **동시에** Agent tool 2개로 호출한다.
174
178
 
175
179
  **모델**: opus
176
180
 
181
+ 에이전트 호출 시 반드시 `subagent_type: "code-reviewer"`를 지정한다.
182
+
177
183
  오케스트레이터가 해야 할 사전 작업:
178
184
  1. `git diff main...HEAD` 출력을 캡처한다.
179
185
  2. contract.md에서 가드레일 섹션(Must/Must NOT)만 추출한다.
@@ -221,6 +227,8 @@ contract.md, plan.md, brief.md, spec.md, dev-log.md는 읽지 않는다.
221
227
 
222
228
  **모델**: sonnet
223
229
 
230
+ 에이전트 호출 시 반드시 `subagent_type: "qa"`를 지정한다.
231
+
224
232
  에이전트 프롬프트:
225
233
 
226
234
  ```
@@ -256,8 +264,8 @@ contract.md, brief.md, spec.md는 읽지 않는다.
256
264
  오케스트레이터는 한 번의 메시지에서 두 개의 Agent tool 호출을 동시에 수행한다:
257
265
 
258
266
  ```
259
- Agent(name="code-reviewer", model="opus", prompt="...")
260
- Agent(name="qa", model="sonnet", prompt="...")
267
+ Agent(name="code-reviewer", subagent_type="code-reviewer", model="opus", prompt="...")
268
+ Agent(name="qa", subagent_type="qa", model="sonnet", prompt="...")
261
269
  ```
262
270
 
263
271
  ---
@@ -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