maskweaver 0.7.26 → 0.7.28
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/assets/agents/squad-operator.md +56 -16
- package/assets/commands/weave-craft.md +189 -92
- package/assets/commands/weave-design.md +59 -31
- package/dist/plugin/index.d.ts.map +1 -1
- package/dist/plugin/index.js +73 -14
- package/dist/plugin/index.js.map +1 -1
- package/dist/plugin/tools/squad.d.ts +1 -0
- package/dist/plugin/tools/squad.d.ts.map +1 -1
- package/dist/plugin/tools/squad.js +49 -2
- package/dist/plugin/tools/squad.js.map +1 -1
- package/dist/plugin/tools/weave.js +8 -12
- package/dist/plugin/tools/weave.js.map +1 -1
- package/dist/shared/config.d.ts +46 -1
- package/dist/shared/config.d.ts.map +1 -1
- package/dist/shared/config.js +34 -0
- package/dist/shared/config.js.map +1 -1
- package/dist/shared/model-registry.d.ts +126 -0
- package/dist/shared/model-registry.d.ts.map +1 -0
- package/dist/shared/model-registry.js +318 -0
- package/dist/shared/model-registry.js.map +1 -0
- package/dist/weave/bridge.d.ts +61 -0
- package/dist/weave/bridge.d.ts.map +1 -0
- package/dist/weave/bridge.js +143 -0
- package/dist/weave/bridge.js.map +1 -0
- package/dist/weave/orchestrator.d.ts +59 -1
- package/dist/weave/orchestrator.d.ts.map +1 -1
- package/dist/weave/orchestrator.js +228 -0
- package/dist/weave/orchestrator.js.map +1 -1
- package/dist/weave/stages/execute.d.ts +35 -7
- package/dist/weave/stages/execute.d.ts.map +1 -1
- package/dist/weave/stages/execute.js +136 -267
- package/dist/weave/stages/execute.js.map +1 -1
- package/dist/weave/types.d.ts +20 -0
- package/dist/weave/types.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -133,17 +133,56 @@ permission:
|
|
|
133
133
|
3. **진행 관리**: task 상태 모니터링 및 업데이트
|
|
134
134
|
4. **결과 통합**: 워커 결과를 수집하고 가면술사에게 보고
|
|
135
135
|
|
|
136
|
-
## 사용 가능한 도구
|
|
137
|
-
|
|
138
|
-
### squad 도구
|
|
139
|
-
- `squad({ action: "assign", squadId, description, assignee, priority })` - task 할당
|
|
140
|
-
- `squad({ action: "update", squadId, taskId, status })` - 상태 업데이트
|
|
141
|
-
- `squad({ action: "complete", squadId, taskId, success, output })` - 완료 처리
|
|
142
|
-
- `squad({ action: "status", squadId })` - 현재 상태 조회
|
|
143
|
-
- `squad({ action: "watchdog", dryRun: true })` - 건강 체크
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
136
|
+
## 사용 가능한 도구
|
|
137
|
+
|
|
138
|
+
### squad 도구
|
|
139
|
+
- `squad({ action: "assign", squadId, description, assignee, priority })` - task 할당
|
|
140
|
+
- `squad({ action: "update", squadId, taskId, status })` - 상태 업데이트
|
|
141
|
+
- `squad({ action: "complete", squadId, taskId, success, output })` - 완료 처리
|
|
142
|
+
- `squad({ action: "status", squadId })` - 현재 상태 조회
|
|
143
|
+
- `squad({ action: "watchdog", dryRun: true })` - 건강 체크
|
|
144
|
+
- `squad({ action: "models" })` - **모델 풀 상태 조회** (가용 슬롯, 능력, 동시실행 현황)
|
|
145
|
+
|
|
146
|
+
### Task 도구
|
|
147
|
+
- 더미인간 소환 가능 (다른 워커에게 위임)
|
|
148
|
+
|
|
149
|
+
## 모델 풀 기반 워커 할당
|
|
150
|
+
|
|
151
|
+
### 모델 풀 시스템
|
|
152
|
+
사용자의 AI 구독 모델들은 **풀(pool)**로 관리됩니다. 각 모델은:
|
|
153
|
+
- **동시실행 제한**: `maxConcurrent` 개까지만 동시에 사용 가능
|
|
154
|
+
- **능력 태그**: 모델마다 잘하는 분야가 다름 (coding, architecture, debugging 등)
|
|
155
|
+
- **비용 등급**: low / medium / high
|
|
156
|
+
|
|
157
|
+
### 작업 할당 전 모델 확인
|
|
158
|
+
작업 할당 전 반드시 `squad({ action: "models" })`로 가용 모델을 확인하세요:
|
|
159
|
+
```
|
|
160
|
+
squad({ action: "models" })
|
|
161
|
+
→ {
|
|
162
|
+
totalCapacity: 6,
|
|
163
|
+
totalAvailable: 4,
|
|
164
|
+
models: [
|
|
165
|
+
{ id: "gemini-flash", agentName: "dummy-gemini-flash", tier: "flash",
|
|
166
|
+
maxConcurrent: 5, activeCount: 1, remainingSlots: 4, capabilities: [...] },
|
|
167
|
+
{ id: "claude-opus", agentName: "dummy-claude-opus", tier: "premium",
|
|
168
|
+
maxConcurrent: 1, activeCount: 1, remainingSlots: 0, available: false },
|
|
169
|
+
]
|
|
170
|
+
}
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### 할당 전략
|
|
174
|
+
1. **모델 확인**: `squad({ action: "models" })`로 가용 현황 파악
|
|
175
|
+
2. **작업 매칭**: 작업의 복잡도와 특성에 맞는 모델 선택
|
|
176
|
+
- 단순 작업 (파일 정리, 포매팅) → flash 티어 모델
|
|
177
|
+
- 일반 코딩 → human 티어 모델
|
|
178
|
+
- 복잡한 설계/디버깅 → premium 티어 모델
|
|
179
|
+
3. **동시실행 고려**: 해당 모델의 `remainingSlots`이 0이면 다른 모델 사용
|
|
180
|
+
4. **fallback**: 원하는 티어가 꽉 찼으면 비슷한 능력의 다른 모델 사용
|
|
181
|
+
|
|
182
|
+
### assignee 지정 방식
|
|
183
|
+
`assignee` 필드에 **에이전트 이름**을 사용합니다:
|
|
184
|
+
- 풀 모델: `"dummy-{모델id}"` (예: `"dummy-gemini-flash"`, `"dummy-claude-opus"`)
|
|
185
|
+
- 레거시: `"dummy-flash"`, `"dummy-human"`, `"dummy-premium"`
|
|
147
186
|
|
|
148
187
|
## 워크플로우
|
|
149
188
|
|
|
@@ -190,8 +229,9 @@ squad({ action: "plan", squadId })
|
|
|
190
229
|
- 실패한 task 및 원인 (있는 경우)
|
|
191
230
|
- 총 소요 시간
|
|
192
231
|
|
|
193
|
-
## 제약사항
|
|
194
|
-
|
|
195
|
-
- 한 번에 최대 5개 워커 관리
|
|
196
|
-
- task당 최대 5분 타임아웃
|
|
197
|
-
- 실패 시 재시도 1회
|
|
232
|
+
## 제약사항
|
|
233
|
+
|
|
234
|
+
- 한 번에 최대 5개 워커 관리
|
|
235
|
+
- task당 최대 5분 타임아웃
|
|
236
|
+
- 실패 시 재시도 1회
|
|
237
|
+
- **모델별 동시실행 제한 준수** (반드시 `squad({ action: "models" })`로 확인 후 할당)
|
|
@@ -50,30 +50,38 @@ AI가 자동으로 검증 루프를 돌리고, 완료되면 유저에게 전달
|
|
|
50
50
|
|
|
51
51
|
---
|
|
52
52
|
|
|
53
|
-
## 실행 흐름
|
|
54
|
-
|
|
55
|
-
```
|
|
56
|
-
0. LOAD PLAN (활성 플랜 + Phase 정보 로드)
|
|
57
|
-
↓
|
|
58
|
-
1.
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
53
|
+
## 실행 흐름
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
0. LOAD PLAN (활성 플랜 + Phase 정보 로드)
|
|
57
|
+
↓
|
|
58
|
+
1. GENERATE EXECUTION PLAN (자동 분석)
|
|
59
|
+
├─ 각 Task의 복잡도 판단 (simple/standard/complex)
|
|
60
|
+
├─ 에이전트 티어 선택 (flash/human/premium)
|
|
61
|
+
├─ 전문가 마스크 자동 선택
|
|
62
|
+
├─ 글로벌 지식에서 트러블슈팅 힌트 검색
|
|
63
|
+
└─ 병렬 실행 가능 여부 분석
|
|
64
|
+
↓
|
|
65
|
+
2. DELEGATE (실행 계획에 따라 작업 위임)
|
|
66
|
+
├─ simple → dummy-flash (빠르고 저렴)
|
|
67
|
+
├─ standard → dummy-human (범용)
|
|
68
|
+
└─ complex → dummy-premium (강력한 추론)
|
|
69
|
+
↓
|
|
70
|
+
3. BUILD + SELF-VERIFY LOOP
|
|
71
|
+
├─ 각 Task에 대해:
|
|
72
|
+
│ ├─ 적합한 마스크 자동 선택
|
|
73
|
+
│ ├─ 테스트 먼저 (Red)
|
|
74
|
+
│ ├─ 최소 구현 (Green)
|
|
75
|
+
│ ├─ 정리 (Refactor)
|
|
76
|
+
│ └─ AI 자동 검증 → PASS/FAIL
|
|
77
|
+
│ ├─ PASS → 다음 Task
|
|
78
|
+
│ └─ FAIL → 글로벌 지식 검색 → 수정 → 재검증
|
|
79
|
+
└─ 5회 초과 → 유저에게 도움 요청
|
|
80
|
+
↓
|
|
81
|
+
4. UPDATE PLAN (Phase 상태 업데이트)
|
|
82
|
+
↓
|
|
83
|
+
5. USER HANDOFF (검증 완료 → 유저 테스트)
|
|
84
|
+
```
|
|
77
85
|
|
|
78
86
|
---
|
|
79
87
|
|
|
@@ -98,9 +106,32 @@ You are the **Mask Weaver**. During execution, your role is to **orchestrate exp
|
|
|
98
106
|
|
|
99
107
|
---
|
|
100
108
|
|
|
101
|
-
### 1. Task Complexity → Execution Strategy
|
|
102
|
-
|
|
103
|
-
|
|
109
|
+
### 1. Task Complexity → Execution Strategy
|
|
110
|
+
|
|
111
|
+
**The Orchestrator automatically assesses task complexity and selects the agent tier.**
|
|
112
|
+
|
|
113
|
+
When `weave craft P1` is called, the system generates an execution plan like:
|
|
114
|
+
|
|
115
|
+
```markdown
|
|
116
|
+
## Phase P1: Emotion Selection UI
|
|
117
|
+
|
|
118
|
+
### Execution Plan
|
|
119
|
+
| # | Task | Complexity | Agent Tier | Mask |
|
|
120
|
+
|---|-------------------|-----------|------------|---------------|
|
|
121
|
+
| 1 | Update imports | simple | flash | auto |
|
|
122
|
+
| 2 | Build component | standard | human | dan-abramov |
|
|
123
|
+
| 3 | Auth refactoring | complex | premium | martin-fowler |
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
**Agent Tier Selection Rules:**
|
|
127
|
+
|
|
128
|
+
| Complexity | Agent Tier | Use When |
|
|
129
|
+
|-----------|------------|----------|
|
|
130
|
+
| simple | `dummy-flash` | File renames, import fixes, formatting, config changes, lint fixes |
|
|
131
|
+
| standard | `dummy-human` | Component implementation, API endpoints, tests, validation |
|
|
132
|
+
| complex | `dummy-premium` | Architecture refactoring, debugging, auth, state management, performance |
|
|
133
|
+
|
|
134
|
+
#### Handle Directly (Simple Tasks)
|
|
104
135
|
|
|
105
136
|
```
|
|
106
137
|
Examples:
|
|
@@ -173,19 +204,22 @@ Mask Weaver:
|
|
|
173
204
|
|
|
174
205
|
---
|
|
175
206
|
|
|
176
|
-
### 3. Execution Decision Flow
|
|
177
|
-
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
↓
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
207
|
+
### 3. Execution Decision Flow
|
|
208
|
+
|
|
209
|
+
```
|
|
210
|
+
Execution Plan Generated (automatic)
|
|
211
|
+
↓
|
|
212
|
+
For each task in plan:
|
|
213
|
+
↓
|
|
214
|
+
Check Agent Tier:
|
|
215
|
+
├─ flash (simple) → Handle directly or Task(dummy-flash)
|
|
216
|
+
├─ human (standard) → Task(dummy-human) with mask
|
|
217
|
+
└─ premium (complex) → Task(dummy-premium) with mask
|
|
218
|
+
↓
|
|
219
|
+
Multiple independent tasks in same wave?
|
|
220
|
+
├─ YES → Run in parallel (Squad system)
|
|
221
|
+
└─ NO → Run sequentially
|
|
222
|
+
```
|
|
189
223
|
|
|
190
224
|
---
|
|
191
225
|
|
|
@@ -235,61 +269,124 @@ Stuck on performance issue:
|
|
|
235
269
|
|
|
236
270
|
---
|
|
237
271
|
|
|
238
|
-
## Step 4: UPDATE PLAN
|
|
239
|
-
|
|
240
|
-
Phase 완료 시 플랜 파일을
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
272
|
+
## Step 4: UPDATE PLAN
|
|
273
|
+
|
|
274
|
+
Phase 완료 시 플랜 파일을 업데이트합니다.
|
|
275
|
+
|
|
276
|
+
> ⚠️ **YAML 작성 규칙 (반드시 준수)**
|
|
277
|
+
>
|
|
278
|
+
> 플랜 YAML을 직접 수정할 때, `done_when` 등 문자열 값은 반드시 아래 규칙을 따릅니다:
|
|
279
|
+
>
|
|
280
|
+
> - **짧은 값** (한 줄): double-quote 사용 → `done_when: "로그인 기능 동작"`
|
|
281
|
+
> - **긴 값** (여러 줄): block scalar(`|`) 사용 → `done_when: |` 후 들여쓰기된 내용
|
|
282
|
+
> - **❌ 절대 금지**: double-quote(`"`)로 시작한 문자열을 다른 줄에서 닫는 것
|
|
283
|
+
>
|
|
284
|
+
> **핵심**: `"` 로 시작했으면 **같은 줄에서** `"` 로 닫기. 줄바꿈이 필요하면 `|` 사용.
|
|
285
|
+
|
|
286
|
+
```yaml
|
|
287
|
+
# .opencode/weave/plans/{active_plan}.yaml 내 해당 Phase 업데이트:
|
|
288
|
+
phases:
|
|
289
|
+
- id: "P1"
|
|
290
|
+
status: "completed" # pending → in_progress → completed
|
|
291
|
+
done_when: "유저가 감정을 선택할 수 있다" # 짧으면 한 줄 quote
|
|
292
|
+
started_at: "2026-02-06T10:30:00"
|
|
293
|
+
completed_at: "2026-02-06T13:00:00"
|
|
294
|
+
masks_used:
|
|
295
|
+
- name: "kent-beck"
|
|
296
|
+
tasks: 2
|
|
297
|
+
effectiveness: 0.9
|
|
298
|
+
- name: "dan-abramov"
|
|
299
|
+
tasks: 1
|
|
300
|
+
effectiveness: 0.85
|
|
301
|
+
retry_count: 1
|
|
302
|
+
issues:
|
|
303
|
+
- "JSON 직렬화 오류 → useEffect 의존성 추가로 해결"
|
|
304
|
+
```
|
|
260
305
|
|
|
261
306
|
---
|
|
262
307
|
|
|
263
|
-
## 유저 핸드오프
|
|
264
|
-
|
|
265
|
-
모든 Task 통과 후:
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
308
|
+
## 유저 핸드오프
|
|
309
|
+
|
|
310
|
+
모든 Task 통과 후:
|
|
311
|
+
|
|
312
|
+
### 1. AI 사전 체험 (Virtual User Test)
|
|
313
|
+
|
|
314
|
+
코드 검증이 끝나면, **가상의 대상 사용자 페르소나**를 만들어 주관적 항목을 먼저 평가한다.
|
|
315
|
+
|
|
316
|
+
#### 페르소나 생성 기준
|
|
317
|
+
|
|
318
|
+
플랜의 목적과 대상 사용자를 기반으로 적절한 페르소나를 구성한다:
|
|
319
|
+
|
|
320
|
+
```yaml
|
|
321
|
+
virtual_user:
|
|
322
|
+
name: "직장인 김지수 (30대)" # 프로젝트 대상에 맞는 가상 인물
|
|
323
|
+
context: "퇴근 후 하루를 정리하며 감정 기록" # 사용 맥락
|
|
324
|
+
goals: "간단하고 빠르게 오늘의 감정을 남기고 싶다"
|
|
325
|
+
tech_level: "일반 사용자" # 기술 수준
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
#### 평가 항목
|
|
329
|
+
|
|
330
|
+
페르소나 관점에서 다음을 평가한다:
|
|
331
|
+
|
|
332
|
+
| 항목 | 평가 관점 |
|
|
333
|
+
|------|----------|
|
|
334
|
+
| **느낌/톤** | UI 분위기가 프로젝트 의도와 맞는가? (스크린샷 기반) |
|
|
335
|
+
| **사용 흐름** | 핵심 동작이 직관적으로 완료되는가? (클릭 수, 동선) |
|
|
336
|
+
| **기능 일치** | 플랜에 정의된 기능이 실제로 동작하는가? |
|
|
337
|
+
| **첫인상** | 처음 본 사용자가 헤매지 않을까? |
|
|
338
|
+
|
|
339
|
+
#### 평가 방법
|
|
340
|
+
|
|
341
|
+
- **스크린샷 촬영**: 브라우저로 주요 화면을 캡처하여 시각적으로 확인
|
|
342
|
+
- **동선 시뮬레이션**: 핵심 시나리오를 실제로 클릭하며 체험
|
|
343
|
+
- **플랜 대조**: 원래 요구사항과 구현 결과를 항목별로 비교
|
|
344
|
+
|
|
345
|
+
### 2. 핸드오프 메시지 형식
|
|
346
|
+
|
|
347
|
+
```markdown
|
|
348
|
+
## ✅ Phase P1 검증 완료!
|
|
349
|
+
|
|
350
|
+
**플랜**: `emotion-diary`
|
|
351
|
+
|
|
352
|
+
### AI 자동 테스트 결과
|
|
353
|
+
| 테스트 | 결과 |
|
|
354
|
+
|--------|------|
|
|
355
|
+
| Build | ✅ 성공 |
|
|
356
|
+
| Unit Tests | ✅ 15/15 |
|
|
357
|
+
| Lint | ✅ 통과 |
|
|
358
|
+
|
|
359
|
+
### 사용된 마스크
|
|
360
|
+
- Kent Beck (테스트)
|
|
361
|
+
- Dan Abramov (React 컴포넌트)
|
|
362
|
+
|
|
363
|
+
### 접속
|
|
364
|
+
http://localhost:5173
|
|
365
|
+
|
|
366
|
+
### AI 사전 체험 결과
|
|
367
|
+
|
|
368
|
+
> 💡 **"직장인 김지수 (30대)"** 관점으로 먼저 사용해봤습니다.
|
|
369
|
+
> 한번 확인해보세요.
|
|
370
|
+
|
|
371
|
+
| 항목 | AI 평가 | 비고 |
|
|
372
|
+
|------|---------|------|
|
|
373
|
+
| 느낌/톤 | ✅ 부드러운 파스텔 톤이 감정 기록 앱에 적합해 보입니다 | 스크린샷 첨부 |
|
|
374
|
+
| 사용 흐름 | ⚠️ 감정 선택 → 저장까지 3탭인데, 2탭이면 더 자연스러울 것 같습니다 | 중간 확인 화면 생략 검토 |
|
|
375
|
+
| 기능 일치 | ✅ 감정 선택 UI가 플랜대로 동작합니다 | - |
|
|
376
|
+
| 첫인상 | ✅ 아이콘만으로 감정이 구분됩니다 | - |
|
|
377
|
+
|
|
378
|
+
> 위 내용은 AI가 가상 사용자로서 판단한 것입니다.
|
|
379
|
+
> 실제 느낌과 다를 수 있으니 직접 확인 부탁드립니다.
|
|
380
|
+
|
|
381
|
+
**다음**: `/weave-craft P2` | **상태**: `/weave-status`
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
### 3. 핵심 원칙
|
|
385
|
+
|
|
386
|
+
- **빈 체크박스를 던지지 않는다**: AI가 먼저 체험하고 소견을 제시한다
|
|
387
|
+
- **단정하지 않는다**: "~해 보입니다", "~인 것 같습니다" 톤으로 제안한다
|
|
388
|
+
- **유저 판단을 대체하지 않는다**: 최종 확인은 반드시 유저 몫
|
|
389
|
+
- **구체적 근거를 붙인다**: 스크린샷, 클릭 수, 플랜 대조 등 판단 근거를 함께 제시
|
|
293
390
|
|
|
294
391
|
---
|
|
295
392
|
|
|
@@ -190,37 +190,65 @@ Mask Weaver:
|
|
|
190
190
|
|
|
191
191
|
---
|
|
192
192
|
|
|
193
|
-
### Step 5: APPROVE
|
|
194
|
-
|
|
195
|
-
**플랜 파일 생성**: `.opencode/weave/plans/{plan-name}.yaml`
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
193
|
+
### Step 5: APPROVE
|
|
194
|
+
|
|
195
|
+
**플랜 파일 생성**: `.opencode/weave/plans/{plan-name}.yaml`
|
|
196
|
+
|
|
197
|
+
> ⚠️ **YAML 작성 규칙 (반드시 준수)**
|
|
198
|
+
>
|
|
199
|
+
> `done_when`, `vision` 등 **긴 문자열 값**은 반드시 아래 규칙을 따릅니다:
|
|
200
|
+
>
|
|
201
|
+
> | 상황 | 사용할 표기법 | 예시 |
|
|
202
|
+
> |------|-------------|------|
|
|
203
|
+
> | 한 줄로 끝나는 짧은 값 | double-quote (`"`) | `done_when: "로그인 기능 동작"` |
|
|
204
|
+
> | 여러 줄 또는 긴 값 | block scalar (`\|`) | 아래 예시 참고 |
|
|
205
|
+
> | ❌ 절대 금지 | 여러 줄에 걸친 double-quote | `done_when: "1단계...\n2단계..."` |
|
|
206
|
+
>
|
|
207
|
+
> ```yaml
|
|
208
|
+
> # ✅ 올바른 예시 - 짧은 값
|
|
209
|
+
> done_when: "유저가 감정을 선택할 수 있다"
|
|
210
|
+
>
|
|
211
|
+
> # ✅ 올바른 예시 - 긴 값 (block scalar)
|
|
212
|
+
> done_when: |
|
|
213
|
+
> 1. 유저가 감정을 선택할 수 있다
|
|
214
|
+
> 2. 선택한 감정이 저장된다
|
|
215
|
+
> 3. 저장 확인 메시지가 표시된다
|
|
216
|
+
>
|
|
217
|
+
> # ❌ 잘못된 예시 - 닫는 따옴표가 다른 줄에 있음 (YAML 파싱 실패!)
|
|
218
|
+
> done_when: "1. 유저가 감정을 선택할 수 있다
|
|
219
|
+
> 2. 선택한 감정이 저장된다
|
|
220
|
+
> 3. 저장 확인 메시지가 표시된다"
|
|
221
|
+
> ```
|
|
222
|
+
>
|
|
223
|
+
> **핵심 원칙**: `"` 로 시작했으면 **같은 줄에서** `"` 로 닫아야 합니다. 줄바꿈이 필요하면 `|` 를 사용하세요.
|
|
224
|
+
|
|
225
|
+
```yaml
|
|
226
|
+
plan_name: "emotion-diary"
|
|
227
|
+
project_name: "감정 일기 앱"
|
|
228
|
+
created_at: "2026-02-06"
|
|
229
|
+
status: "active" # active | paused | completed | archived
|
|
230
|
+
|
|
231
|
+
vision: |
|
|
232
|
+
[전체 비전]
|
|
233
|
+
|
|
234
|
+
architecture:
|
|
235
|
+
frontend: "[...]"
|
|
236
|
+
backend: "[...]"
|
|
237
|
+
database: "[...]"
|
|
238
|
+
|
|
239
|
+
phases:
|
|
240
|
+
- id: "P1"
|
|
241
|
+
name: "[Phase 이름]"
|
|
242
|
+
status: "pending" # pending | in_progress | completed
|
|
243
|
+
done_when: "[짧으면 한 줄 double-quote, 길면 | 블록 스칼라 사용]"
|
|
244
|
+
started_at: null
|
|
245
|
+
completed_at: null
|
|
246
|
+
masks_used: []
|
|
247
|
+
checklist:
|
|
248
|
+
- "[체크 항목 1]"
|
|
249
|
+
- "[체크 항목 2]"
|
|
250
|
+
tasks: []
|
|
251
|
+
```
|
|
224
252
|
|
|
225
253
|
**state.yaml 업데이트**:
|
|
226
254
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/plugin/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;EAcE;AAEF,OAAO,EAAQ,KAAK,MAAM,EAAE,MAAM,qBAAqB,CAAC;AA2xBxD,eAAO,MAAM,gBAAgB,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/plugin/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;EAcE;AAEF,OAAO,EAAQ,KAAK,MAAM,EAAE,MAAM,qBAAqB,CAAC;AA2xBxD,eAAO,MAAM,gBAAgB,EAAE,MAmc9B,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
|
package/dist/plugin/index.js
CHANGED
|
@@ -872,21 +872,80 @@ export const MaskweaverPlugin = async ({ client, directory }) => {
|
|
|
872
872
|
const projectOpencodeDir = path.join(directory, '.opencode');
|
|
873
873
|
// Load from package assets first, then project .opencode (project overrides package)
|
|
874
874
|
const loadedAgents = loadAgentAssets(assetsDir, projectOpencodeDir);
|
|
875
|
-
//
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
875
|
+
// ==========================================================================
|
|
876
|
+
// 8b. Generate agents from model pool (or legacy fallback)
|
|
877
|
+
// ==========================================================================
|
|
878
|
+
{
|
|
879
|
+
const { loadRuntimeConfig, normalizeDummyHumansConfig } = await import('../shared/config.js');
|
|
880
|
+
const { createModelRegistry } = await import('../shared/model-registry.js');
|
|
881
|
+
const runtimeConfig = loadRuntimeConfig(directory);
|
|
882
|
+
if (runtimeConfig.dummyHumans) {
|
|
883
|
+
const pool = normalizeDummyHumansConfig(runtimeConfig.dummyHumans);
|
|
884
|
+
// Initialize the global model registry
|
|
885
|
+
createModelRegistry(pool);
|
|
886
|
+
if (loadedAgents['dummy-human']) {
|
|
887
|
+
// Generate agent variants from pool entries
|
|
888
|
+
for (const entry of pool) {
|
|
889
|
+
const agentName = `dummy-${entry.id}`;
|
|
890
|
+
if (!loadedAgents[agentName]) {
|
|
891
|
+
const tierLabel = entry.tier === 'flash' ? 'Flash' : entry.tier === 'premium' ? 'Premium' : 'Standard';
|
|
892
|
+
const capStr = entry.capabilities.slice(0, 3).join(', ');
|
|
893
|
+
loadedAgents[agentName] = {
|
|
894
|
+
...loadedAgents['dummy-human'],
|
|
895
|
+
description: `Dummy-Human (${entry.id}) - ${tierLabel}. ${entry.description || capStr}. [max ${entry.maxConcurrent} concurrent]`,
|
|
896
|
+
model: entry.model,
|
|
897
|
+
};
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
// Also ensure legacy dummy-flash / dummy-premium aliases exist (for backward compat)
|
|
901
|
+
const flashEntry = pool.find(e => e.tier === 'flash');
|
|
902
|
+
const humanEntry = pool.find(e => e.tier === 'human');
|
|
903
|
+
const premiumEntry = pool.find(e => e.tier === 'premium');
|
|
904
|
+
if (flashEntry && !loadedAgents['dummy-flash']) {
|
|
905
|
+
loadedAgents['dummy-flash'] = loadedAgents[`dummy-${flashEntry.id}`];
|
|
906
|
+
}
|
|
907
|
+
if (humanEntry) {
|
|
908
|
+
// dummy-human already exists as the base agent; just update its model from pool
|
|
909
|
+
loadedAgents['dummy-human'].model = humanEntry.model;
|
|
910
|
+
}
|
|
911
|
+
if (premiumEntry && !loadedAgents['dummy-premium']) {
|
|
912
|
+
loadedAgents['dummy-premium'] = loadedAgents[`dummy-${premiumEntry.id}`];
|
|
913
|
+
}
|
|
914
|
+
// Fallback: if no tier mapping found, use defaults
|
|
915
|
+
if (!loadedAgents['dummy-flash']) {
|
|
916
|
+
loadedAgents['dummy-flash'] = {
|
|
917
|
+
...loadedAgents['dummy-human'],
|
|
918
|
+
description: 'Dummy-Human (Flash) - Fast and cheap',
|
|
919
|
+
model: 'google/gemini-2.0-flash',
|
|
920
|
+
};
|
|
921
|
+
}
|
|
922
|
+
if (!loadedAgents['dummy-premium']) {
|
|
923
|
+
loadedAgents['dummy-premium'] = {
|
|
924
|
+
...loadedAgents['dummy-human'],
|
|
925
|
+
description: 'Dummy-Human (Premium) - Powerful and reasoning',
|
|
926
|
+
model: 'google/gemini-2.0-pro-exp-02-05',
|
|
927
|
+
};
|
|
928
|
+
}
|
|
929
|
+
}
|
|
883
930
|
}
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
931
|
+
else {
|
|
932
|
+
// No pool config → legacy hardcoded defaults
|
|
933
|
+
if (loadedAgents['dummy-human']) {
|
|
934
|
+
if (!loadedAgents['dummy-flash']) {
|
|
935
|
+
loadedAgents['dummy-flash'] = {
|
|
936
|
+
...loadedAgents['dummy-human'],
|
|
937
|
+
description: 'Dummy-Human (Flash) - Fast and cheap',
|
|
938
|
+
model: 'google/gemini-2.0-flash',
|
|
939
|
+
};
|
|
940
|
+
}
|
|
941
|
+
if (!loadedAgents['dummy-premium']) {
|
|
942
|
+
loadedAgents['dummy-premium'] = {
|
|
943
|
+
...loadedAgents['dummy-human'],
|
|
944
|
+
description: 'Dummy-Human (Premium) - Powerful and reasoning',
|
|
945
|
+
model: 'google/gemini-2.0-pro-exp-02-05',
|
|
946
|
+
};
|
|
947
|
+
}
|
|
948
|
+
}
|
|
890
949
|
}
|
|
891
950
|
}
|
|
892
951
|
// Apply config overrides to agents
|