syr-d2c-workflow-mcp 0.3.0 → 0.4.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.
- package/README.md +377 -16
- package/dist/index.js +533 -228
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -115,14 +115,16 @@ AI가 다음 키워드를 감지하면 이 MCP를 사용합니다:
|
|
|
115
115
|
}
|
|
116
116
|
```
|
|
117
117
|
|
|
118
|
-
### `
|
|
119
|
-
|
|
118
|
+
### `d2c_log_step`
|
|
119
|
+
워크플로우 진행 상황을 실시간으로 출력합니다.
|
|
120
120
|
|
|
121
121
|
```typescript
|
|
122
122
|
{
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
123
|
+
step: number; // 현재 단계 번호 (1-6)
|
|
124
|
+
stepName: string; // 단계 이름
|
|
125
|
+
status: "start" | "done" | "error";
|
|
126
|
+
message?: string; // 추가 메시지
|
|
127
|
+
iteration?: number; // 반복 횟수
|
|
126
128
|
}
|
|
127
129
|
```
|
|
128
130
|
|
|
@@ -156,7 +158,73 @@ Figma 디자인과 렌더링 결과를 비교 분석합니다.
|
|
|
156
158
|
- `d2c://rules/default` - 기본 디자인 규칙
|
|
157
159
|
- `d2c://templates/react` - React 컴포넌트 템플릿
|
|
158
160
|
|
|
159
|
-
## 워크플로우
|
|
161
|
+
## 3단계 Phase 워크플로우
|
|
162
|
+
|
|
163
|
+
v0.3.0부터 객관적인 성공률 측정을 위한 3단계 Phase 시스템을 지원합니다.
|
|
164
|
+
|
|
165
|
+
| Phase | 목표 성공률 | 비교 방법 | 수정 주체 |
|
|
166
|
+
|-------|-----------|----------|----------|
|
|
167
|
+
| **Phase 1** | 60% | Playwright 스크린샷 비교 | Figma MCP (재추출) |
|
|
168
|
+
| **Phase 2** | 70% | Playwright 이미지 diff | LLM (코드 수정) |
|
|
169
|
+
| **Phase 3** | 90% | Playwright DOM 비교 | LLM (코드 수정) |
|
|
170
|
+
|
|
171
|
+
### 워크플로우 개요
|
|
172
|
+
|
|
173
|
+
```mermaid
|
|
174
|
+
flowchart TD
|
|
175
|
+
Start[Figma 디자인] --> Preflight[사전 검사]
|
|
176
|
+
Preflight --> FigmaGet[Figma 디자인 가져오기]
|
|
177
|
+
|
|
178
|
+
subgraph Phase1 [Phase 1: Figma MCP 추출 - 60%]
|
|
179
|
+
P1_Extract[Figma MCP로 코드 추출]
|
|
180
|
+
P1_Render[Playwright 렌더링]
|
|
181
|
+
P1_Compare[스크린샷 비교]
|
|
182
|
+
P1_Check{성공률 >= 60%?}
|
|
183
|
+
P1_HITL[HITL: 계속?]
|
|
184
|
+
|
|
185
|
+
P1_Extract --> P1_Render --> P1_Compare --> P1_Check
|
|
186
|
+
P1_Check -->|No| P1_HITL
|
|
187
|
+
P1_HITL -->|Yes| P1_Extract
|
|
188
|
+
P1_HITL -->|Manual| P1_Render
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
FigmaGet --> Phase1
|
|
192
|
+
P1_Check -->|Yes| Phase2
|
|
193
|
+
|
|
194
|
+
subgraph Phase2 [Phase 2: LLM 이미지 Diff - 70%]
|
|
195
|
+
P2_Diff[이미지 Diff 분석]
|
|
196
|
+
P2_LLM[LLM 코드 수정]
|
|
197
|
+
P2_Render[Playwright 렌더링]
|
|
198
|
+
P2_Compare[스크린샷 비교]
|
|
199
|
+
P2_Check{성공률 >= 70%?}
|
|
200
|
+
P2_HITL[HITL: 계속?]
|
|
201
|
+
|
|
202
|
+
P2_Diff --> P2_LLM --> P2_Render --> P2_Compare --> P2_Check
|
|
203
|
+
P2_Check -->|No| P2_HITL
|
|
204
|
+
P2_HITL -->|Yes| P2_Diff
|
|
205
|
+
P2_HITL -->|Manual| P2_Render
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
P2_Check -->|Yes| Phase3
|
|
209
|
+
|
|
210
|
+
subgraph Phase3 [Phase 3: LLM DOM 비교 - 90%]
|
|
211
|
+
P3_DOM[DOM 스냅샷 비교]
|
|
212
|
+
P3_LLM[LLM 코드 수정]
|
|
213
|
+
P3_Render[Playwright 렌더링]
|
|
214
|
+
P3_Compare[DOM 비교]
|
|
215
|
+
P3_Check{성공률 >= 90%?}
|
|
216
|
+
P3_HITL[HITL: 계속?]
|
|
217
|
+
|
|
218
|
+
P3_DOM --> P3_LLM --> P3_Render --> P3_Compare --> P3_Check
|
|
219
|
+
P3_Check -->|No| P3_HITL
|
|
220
|
+
P3_HITL -->|Yes| P3_DOM
|
|
221
|
+
P3_HITL -->|Manual| P3_Render
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
P3_Check -->|Yes| Done[완료]
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### 시퀀스 다이어그램
|
|
160
228
|
|
|
161
229
|
```mermaid
|
|
162
230
|
sequenceDiagram
|
|
@@ -168,26 +236,319 @@ sequenceDiagram
|
|
|
168
236
|
|
|
169
237
|
User->>AI: "syr로 이 Figma 변환해줘"
|
|
170
238
|
|
|
239
|
+
Note over AI,D2C: Step 1: 사전 검사
|
|
171
240
|
AI->>D2C: d2c_preflight_check()
|
|
172
241
|
AI->>Figma: get_design_context() 확인
|
|
173
242
|
AI->>PW: browser_snapshot() 확인
|
|
174
243
|
|
|
175
|
-
AI
|
|
244
|
+
Note over AI,Figma: Step 2: Figma 디자인 가져오기
|
|
176
245
|
AI->>Figma: get_design_context(figmaUrl)
|
|
177
246
|
AI->>Figma: get_screenshot()
|
|
178
247
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
248
|
+
rect rgb(255, 240, 240)
|
|
249
|
+
Note over AI,PW: Phase 1: Figma MCP 추출 (목표 60%)
|
|
250
|
+
loop 성공률 < 60% && HITL 승인
|
|
251
|
+
AI->>Figma: 코드 재추출
|
|
252
|
+
AI->>PW: browser_navigate() + screenshot
|
|
253
|
+
AI->>D2C: d2c_phase1_compare(successRate, iteration)
|
|
254
|
+
AI->>User: HITL 확인 요청
|
|
255
|
+
end
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
rect rgb(240, 255, 240)
|
|
259
|
+
Note over AI,PW: Phase 2: LLM 이미지 Diff (목표 70%)
|
|
260
|
+
loop 성공률 < 70% && HITL 승인
|
|
261
|
+
AI->>PW: 이미지 diff 분석
|
|
262
|
+
AI->>AI: LLM 코드 수정
|
|
263
|
+
AI->>PW: browser_navigate() + screenshot
|
|
264
|
+
AI->>D2C: d2c_phase2_image_diff(successRate, diffAreas)
|
|
265
|
+
AI->>User: HITL 확인 요청
|
|
266
|
+
end
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
rect rgb(240, 240, 255)
|
|
270
|
+
Note over AI,PW: Phase 3: LLM DOM 비교 (목표 90%)
|
|
271
|
+
loop 성공률 < 90% && HITL 승인
|
|
272
|
+
AI->>PW: DOM 스냅샷 비교
|
|
273
|
+
AI->>AI: LLM 코드 수정
|
|
274
|
+
AI->>PW: browser_navigate() + DOM 비교
|
|
275
|
+
AI->>D2C: d2c_phase3_dom_compare(successRate, domDiffs)
|
|
276
|
+
AI->>User: HITL 확인 요청
|
|
277
|
+
end
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
AI->>D2C: d2c_workflow_status(phase1, phase2, phase3)
|
|
281
|
+
AI-->>User: 완성된 컴포넌트 + 최종 리포트
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
### HITL (Human-in-the-Loop)
|
|
285
|
+
|
|
286
|
+
모든 Phase에서 사용자 개입이 가능합니다:
|
|
287
|
+
|
|
288
|
+
- **[Y]** 계속 - 자동 수정 후 반복
|
|
289
|
+
- **[N]** 완료 - 현재 상태로 다음 단계 진행
|
|
290
|
+
- **[M]** 수동 수정 - 사용자가 직접 코드 수정 후 재비교
|
|
291
|
+
- **[S]** 중단 - 워크플로우 종료
|
|
292
|
+
|
|
293
|
+
## OpenSpec 규칙 통합
|
|
294
|
+
|
|
295
|
+
v0.4.0부터 사용자 프로젝트의 OpenSpec 규칙을 자동으로 탐지하고 워크플로우에 적용합니다.
|
|
296
|
+
|
|
297
|
+
### OpenSpec 규칙 구조
|
|
298
|
+
|
|
299
|
+
```
|
|
300
|
+
your-project/
|
|
301
|
+
├── openspec/
|
|
302
|
+
│ └── specs/
|
|
303
|
+
│ ├── figma-standard/ ← Figma 변환 규칙
|
|
304
|
+
│ │ └── spec.md
|
|
305
|
+
│ ├── design-rules/ ← 디자인 규칙
|
|
306
|
+
│ │ └── spec.md
|
|
307
|
+
│ └── custom-rules/ ← 커스텀 규칙
|
|
308
|
+
│ └── spec.md
|
|
309
|
+
└── src/
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
### 탐지 경로
|
|
313
|
+
|
|
314
|
+
다음 경로에서 OpenSpec 규칙을 자동으로 탐지합니다:
|
|
315
|
+
|
|
316
|
+
1. `./openspec/specs/*/spec.md`
|
|
317
|
+
2. `./.cursor/openspec/specs/*/spec.md`
|
|
318
|
+
3. `./docs/openspec/specs/*/spec.md`
|
|
319
|
+
|
|
320
|
+
### OpenSpec 도구
|
|
321
|
+
|
|
322
|
+
#### `d2c_load_openspec_rules`
|
|
323
|
+
프로젝트의 OpenSpec 규칙을 탐지하고 로드합니다.
|
|
324
|
+
|
|
325
|
+
```typescript
|
|
326
|
+
{
|
|
327
|
+
forceReload?: boolean; // 캐시 무시하고 다시 로드
|
|
328
|
+
specNames?: string[]; // 특정 spec만 필터링
|
|
329
|
+
}
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
**반환값 예시:**
|
|
333
|
+
```
|
|
334
|
+
📋 OpenSpec 규칙 로드 결과
|
|
335
|
+
|
|
336
|
+
## 발견된 규칙 (2개)
|
|
337
|
+
|
|
338
|
+
### figma-standard
|
|
339
|
+
- 경로: `openspec/specs/figma-standard/spec.md`
|
|
340
|
+
- Requirements (3개):
|
|
341
|
+
- 컴포넌트 네이밍 규칙 (2개 시나리오)
|
|
342
|
+
- Props 인터페이스 정의 (1개 시나리오)
|
|
343
|
+
- 접근성 속성 (2개 시나리오)
|
|
344
|
+
|
|
345
|
+
### design-rules
|
|
346
|
+
- 경로: `openspec/specs/design-rules/spec.md`
|
|
347
|
+
- Requirements (2개):
|
|
348
|
+
- 색상 시스템 (1개 시나리오)
|
|
349
|
+
- 타이포그래피 (1개 시나리오)
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
#### `d2c_get_workflow_tasks`
|
|
353
|
+
현재 Phase에 맞는 체크리스트를 반환합니다.
|
|
354
|
+
|
|
355
|
+
```typescript
|
|
356
|
+
{
|
|
357
|
+
phase: 1 | 2 | 3; // 현재 Phase
|
|
358
|
+
completedTasks?: string[]; // 완료된 task ID 목록
|
|
359
|
+
includeRules?: boolean; // 적용 규칙 목록 포함
|
|
360
|
+
}
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
**반환값 예시:**
|
|
364
|
+
```markdown
|
|
365
|
+
## Phase 1: Figma MCP 추출 (목표 60%)
|
|
366
|
+
|
|
367
|
+
### 진행률: 33% (2/6)
|
|
368
|
+
███░░░░░░░
|
|
369
|
+
|
|
370
|
+
### Tasks
|
|
371
|
+
- [x] 1.1 Figma 디자인 컨텍스트 가져오기
|
|
372
|
+
- [x] 1.2 Figma MCP로 코드 추출
|
|
373
|
+
- [ ] 1.3 Playwright 렌더링
|
|
374
|
+
- [ ] 1.4 스크린샷 비교 (toHaveScreenshot)
|
|
375
|
+
- [ ] 1.5 d2c_phase1_compare 호출
|
|
376
|
+
- [ ] 1.6 HITL 확인
|
|
377
|
+
|
|
378
|
+
### 적용 규칙
|
|
379
|
+
- **figma-standard**: 컴포넌트 네이밍 규칙, Props 인터페이스 정의, 접근성 속성
|
|
380
|
+
- **design-rules**: 색상 시스템, 타이포그래피
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
#### `d2c_validate_against_spec`
|
|
384
|
+
생성된 코드가 OpenSpec 규칙을 준수하는지 검증합니다.
|
|
385
|
+
|
|
386
|
+
```typescript
|
|
387
|
+
{
|
|
388
|
+
code: string; // 검증할 코드
|
|
389
|
+
specName?: string; // 특정 spec만 검증
|
|
390
|
+
componentName?: string; // 컴포넌트 이름
|
|
391
|
+
}
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
**반환값 예시:**
|
|
395
|
+
```
|
|
396
|
+
📋 OpenSpec 규칙 검증 결과
|
|
397
|
+
|
|
398
|
+
## 요약
|
|
399
|
+
- 통과: 3개 ✅
|
|
400
|
+
- 실패: 1개 ❌
|
|
401
|
+
- 경고: 1개 ⚠️
|
|
402
|
+
- 준수율: 60%
|
|
403
|
+
|
|
404
|
+
██████░░░░ 60%
|
|
405
|
+
|
|
406
|
+
## 상세 결과
|
|
407
|
+
|
|
408
|
+
✅ **컴포넌트 네이밍 규칙** (default)
|
|
409
|
+
ButtonPrimary은(는) PascalCase 준수
|
|
410
|
+
|
|
411
|
+
✅ **Props 인터페이스 정의** (default)
|
|
412
|
+
TypeScript Props 인터페이스 정의됨
|
|
413
|
+
|
|
414
|
+
❌ **색상 시스템** (design-rules)
|
|
415
|
+
검증 필요: 디자인 시스템 색상 사용
|
|
416
|
+
|
|
417
|
+
## 수정 필요 항목
|
|
418
|
+
- 색상 시스템: 디자인 시스템 색상 사용
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
### OpenSpec 워크플로우 통합 다이어그램
|
|
422
|
+
|
|
423
|
+
```mermaid
|
|
424
|
+
flowchart TD
|
|
425
|
+
Start[워크플로우 시작] --> LoadRules[d2c_load_openspec_rules]
|
|
426
|
+
LoadRules --> CheckRules{규칙 발견?}
|
|
427
|
+
|
|
428
|
+
CheckRules -->|Yes| ApplyRules[규칙 적용]
|
|
429
|
+
CheckRules -->|No| DefaultRules[기본 규칙 사용]
|
|
430
|
+
|
|
431
|
+
ApplyRules --> Phase1
|
|
432
|
+
DefaultRules --> Phase1
|
|
433
|
+
|
|
434
|
+
subgraph Phase1 [Phase 1]
|
|
435
|
+
P1_Tasks[d2c_get_workflow_tasks - phase:1]
|
|
436
|
+
P1_Work[Figma MCP 추출]
|
|
437
|
+
P1_Validate[d2c_validate_against_spec]
|
|
438
|
+
P1_Compare[d2c_phase1_compare]
|
|
439
|
+
|
|
440
|
+
P1_Tasks --> P1_Work --> P1_Validate --> P1_Compare
|
|
441
|
+
end
|
|
442
|
+
|
|
443
|
+
subgraph Phase2 [Phase 2]
|
|
444
|
+
P2_Tasks[d2c_get_workflow_tasks - phase:2]
|
|
445
|
+
P2_Work[LLM 이미지 Diff 수정]
|
|
446
|
+
P2_Validate[d2c_validate_against_spec]
|
|
447
|
+
P2_Compare[d2c_phase2_image_diff]
|
|
448
|
+
|
|
449
|
+
P2_Tasks --> P2_Work --> P2_Validate --> P2_Compare
|
|
450
|
+
end
|
|
182
451
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
452
|
+
subgraph Phase3 [Phase 3]
|
|
453
|
+
P3_Tasks[d2c_get_workflow_tasks - phase:3]
|
|
454
|
+
P3_Work[LLM DOM 비교 수정]
|
|
455
|
+
P3_Validate[d2c_validate_against_spec - 최종]
|
|
456
|
+
P3_Compare[d2c_phase3_dom_compare]
|
|
457
|
+
|
|
458
|
+
P3_Tasks --> P3_Work --> P3_Validate --> P3_Compare
|
|
188
459
|
end
|
|
189
460
|
|
|
190
|
-
|
|
461
|
+
Phase1 --> Phase2 --> Phase3 --> Done[완료]
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
### OpenSpec 규칙 예시
|
|
465
|
+
|
|
466
|
+
`openspec/specs/figma-standard/spec.md`:
|
|
467
|
+
|
|
468
|
+
```markdown
|
|
469
|
+
# Capability: Figma 변환 표준
|
|
470
|
+
|
|
471
|
+
## ADDED Requirements
|
|
472
|
+
|
|
473
|
+
### Requirement: 컴포넌트 네이밍 규칙
|
|
474
|
+
|
|
475
|
+
컴포넌트 이름은 PascalCase를 따라야 합니다(SHALL).
|
|
476
|
+
|
|
477
|
+
#### Scenario: PascalCase 검증
|
|
478
|
+
|
|
479
|
+
- **GIVEN** Figma에서 추출한 컴포넌트가 있을 때
|
|
480
|
+
- **WHEN** 컴포넌트 이름을 생성하면
|
|
481
|
+
- **THEN** PascalCase 형식이어야 한다 (예: ButtonPrimary)
|
|
482
|
+
|
|
483
|
+
### Requirement: Props 인터페이스 정의
|
|
484
|
+
|
|
485
|
+
모든 컴포넌트는 TypeScript Props 인터페이스를 정의해야 합니다(SHALL).
|
|
486
|
+
|
|
487
|
+
#### Scenario: Props 인터페이스 존재
|
|
488
|
+
|
|
489
|
+
- **GIVEN** React 컴포넌트가 생성될 때
|
|
490
|
+
- **WHEN** Props를 받는 경우
|
|
491
|
+
- **THEN** interface ComponentNameProps {} 형태로 정의한다
|
|
492
|
+
```
|
|
493
|
+
|
|
494
|
+
### Phase별 도구
|
|
495
|
+
|
|
496
|
+
#### `d2c_phase1_compare`
|
|
497
|
+
Phase 1 스크린샷 비교 결과를 처리합니다.
|
|
498
|
+
|
|
499
|
+
```typescript
|
|
500
|
+
{
|
|
501
|
+
successRate: number; // Playwright 비교 성공률 (0-100)
|
|
502
|
+
targetRate?: number; // 목표 성공률 (기본: 60)
|
|
503
|
+
iteration: number; // 현재 반복 횟수
|
|
504
|
+
maxIterations?: number; // 최대 반복 (기본: 5)
|
|
505
|
+
diffDetails?: string; // 차이점 설명
|
|
506
|
+
}
|
|
507
|
+
```
|
|
508
|
+
|
|
509
|
+
#### `d2c_phase2_image_diff`
|
|
510
|
+
Phase 2 이미지 diff 결과를 처리합니다.
|
|
511
|
+
|
|
512
|
+
```typescript
|
|
513
|
+
{
|
|
514
|
+
successRate: number; // Playwright 비교 성공률 (0-100)
|
|
515
|
+
targetRate?: number; // 목표 성공률 (기본: 70)
|
|
516
|
+
iteration: number; // 현재 반복 횟수
|
|
517
|
+
diffAreas?: Array<{ // 차이 영역들
|
|
518
|
+
area: string; // 영역 (예: "header", "button")
|
|
519
|
+
type: string; // 유형 (color, layout, spacing)
|
|
520
|
+
severity: "high" | "medium" | "low";
|
|
521
|
+
}>;
|
|
522
|
+
}
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
#### `d2c_phase3_dom_compare`
|
|
526
|
+
Phase 3 DOM 비교 결과를 처리합니다.
|
|
527
|
+
|
|
528
|
+
```typescript
|
|
529
|
+
{
|
|
530
|
+
successRate: number; // DOM 비교 성공률 (0-100)
|
|
531
|
+
targetRate?: number; // 목표 성공률 (기본: 90)
|
|
532
|
+
iteration: number; // 현재 반복 횟수
|
|
533
|
+
domDiffs?: Array<{ // DOM 차이점들
|
|
534
|
+
selector: string; // 요소 선택자
|
|
535
|
+
type: string; // missing, extra, attribute, text
|
|
536
|
+
expected?: string; // 예상 값
|
|
537
|
+
actual?: string; // 실제 값
|
|
538
|
+
}>;
|
|
539
|
+
}
|
|
540
|
+
```
|
|
541
|
+
|
|
542
|
+
#### `d2c_workflow_status`
|
|
543
|
+
전체 워크플로우 진행 상황을 표시합니다.
|
|
544
|
+
|
|
545
|
+
```typescript
|
|
546
|
+
{
|
|
547
|
+
currentPhase: 1 | 2 | 3;
|
|
548
|
+
phase1?: { status: string; successRate: number; iterations: number; };
|
|
549
|
+
phase2?: { status: string; successRate: number; iterations: number; };
|
|
550
|
+
phase3?: { status: string; successRate: number; iterations: number; };
|
|
551
|
+
}
|
|
191
552
|
```
|
|
192
553
|
|
|
193
554
|
## 개발
|