@su-record/vibe 2.2.4 → 2.3.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/.claude/settings.json +0 -117
- package/.claude/settings.local.json +2 -1
- package/.claude/vibe/rules/languages/dart-flutter.md +509 -0
- package/.claude/vibe/rules/languages/go.md +396 -0
- package/.claude/vibe/rules/languages/java-spring.md +586 -0
- package/.claude/vibe/rules/languages/kotlin-android.md +491 -0
- package/.claude/vibe/rules/languages/python-django.md +371 -0
- package/.claude/vibe/rules/languages/python-fastapi.md +386 -0
- package/.claude/vibe/rules/languages/rust.md +425 -0
- package/.claude/vibe/rules/languages/swift-ios.md +516 -0
- package/.claude/vibe/rules/languages/typescript-nextjs.md +441 -0
- package/.claude/vibe/rules/languages/typescript-node.md +375 -0
- package/.claude/vibe/rules/languages/typescript-nuxt.md +521 -0
- package/.claude/vibe/rules/languages/typescript-react-native.md +446 -0
- package/.claude/vibe/rules/languages/typescript-react.md +525 -0
- package/.claude/vibe/rules/languages/typescript-vue.md +353 -0
- package/README.md +96 -96
- package/commands/vibe.analyze.md +14 -73
- package/commands/vibe.reason.md +49 -172
- package/commands/vibe.review.md +72 -260
- package/commands/vibe.utils.md +101 -0
- package/commands/vibe.verify.md +4 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +44 -14
- package/dist/cli/index.js.map +1 -1
- package/{templates/hooks-template.json → hooks/hooks.json} +6 -6
- package/package.json +2 -2
- package/commands/vibe.continue.md +0 -88
- package/commands/vibe.setup.md +0 -97
- /package/{templates → .claude/vibe/templates}/constitution-template.md +0 -0
- /package/{templates → .claude/vibe/templates}/contract-backend-template.md +0 -0
- /package/{templates → .claude/vibe/templates}/contract-frontend-template.md +0 -0
- /package/{templates → .claude/vibe/templates}/feature-template.md +0 -0
- /package/{templates → .claude/vibe/templates}/spec-template.md +0 -0
- /package/{commands/vibe.compound.md → agents/compounder.md} +0 -0
- /package/{commands/vibe.diagram.md → agents/diagrammer.md} +0 -0
- /package/{commands/vibe.e2e.md → agents/e2e-tester.md} +0 -0
- /package/{commands/vibe.ui.md → agents/ui-previewer.md} +0 -0
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
# 🟢 TypeScript + Vue/Nuxt 품질 규칙
|
|
2
|
+
|
|
3
|
+
## 핵심 원칙 (core에서 상속)
|
|
4
|
+
|
|
5
|
+
```markdown
|
|
6
|
+
✅ 단일 책임 (SRP)
|
|
7
|
+
✅ 중복 제거 (DRY)
|
|
8
|
+
✅ 재사용성
|
|
9
|
+
✅ 낮은 복잡도
|
|
10
|
+
✅ 함수 ≤ 30줄, Template ≤ 100줄
|
|
11
|
+
✅ 중첩 ≤ 3단계
|
|
12
|
+
✅ Cyclomatic complexity ≤ 10
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Vue 3 + TypeScript 특화 규칙
|
|
16
|
+
|
|
17
|
+
### 1. Composition API 사용 (Options API 지양)
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
// ❌ Options API (레거시)
|
|
21
|
+
export default {
|
|
22
|
+
data() {
|
|
23
|
+
return { count: 0 };
|
|
24
|
+
},
|
|
25
|
+
methods: {
|
|
26
|
+
increment() {
|
|
27
|
+
this.count++;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
// ✅ Composition API + script setup
|
|
33
|
+
<script setup lang="ts">
|
|
34
|
+
import { ref, computed, onMounted } from 'vue';
|
|
35
|
+
|
|
36
|
+
const count = ref(0);
|
|
37
|
+
const doubled = computed(() => count.value * 2);
|
|
38
|
+
|
|
39
|
+
function increment() {
|
|
40
|
+
count.value++;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
onMounted(() => {
|
|
44
|
+
console.log('컴포넌트 마운트됨');
|
|
45
|
+
});
|
|
46
|
+
</script>
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### 2. 타입 안전한 Props/Emits
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
// ✅ Props 타입 정의
|
|
53
|
+
interface Props {
|
|
54
|
+
userId: string;
|
|
55
|
+
title?: string;
|
|
56
|
+
items: Item[];
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
60
|
+
title: '기본 제목',
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
// ✅ Emits 타입 정의
|
|
64
|
+
interface Emits {
|
|
65
|
+
(e: 'update', value: string): void;
|
|
66
|
+
(e: 'delete', id: number): void;
|
|
67
|
+
(e: 'select', item: Item): void;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const emit = defineEmits<Emits>();
|
|
71
|
+
|
|
72
|
+
// 사용
|
|
73
|
+
emit('update', '새 값');
|
|
74
|
+
emit('delete', 123);
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### 3. Composables로 로직 분리
|
|
78
|
+
|
|
79
|
+
```typescript
|
|
80
|
+
// ✅ composables/useUser.ts
|
|
81
|
+
import { ref, computed } from 'vue';
|
|
82
|
+
import type { User } from '@/types';
|
|
83
|
+
|
|
84
|
+
export function useUser(userId: string) {
|
|
85
|
+
const user = ref<User | null>(null);
|
|
86
|
+
const isLoading = ref(false);
|
|
87
|
+
const error = ref<string | null>(null);
|
|
88
|
+
|
|
89
|
+
const fullName = computed(() =>
|
|
90
|
+
user.value ? `${user.value.firstName} ${user.value.lastName}` : ''
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
async function fetchUser() {
|
|
94
|
+
isLoading.value = true;
|
|
95
|
+
error.value = null;
|
|
96
|
+
try {
|
|
97
|
+
const response = await api.getUser(userId);
|
|
98
|
+
user.value = response.data;
|
|
99
|
+
} catch (e) {
|
|
100
|
+
error.value = '사용자를 불러오지 못했습니다';
|
|
101
|
+
} finally {
|
|
102
|
+
isLoading.value = false;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return {
|
|
107
|
+
user,
|
|
108
|
+
isLoading,
|
|
109
|
+
error,
|
|
110
|
+
fullName,
|
|
111
|
+
fetchUser,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// 컴포넌트에서 사용
|
|
116
|
+
<script setup lang="ts">
|
|
117
|
+
const { user, isLoading, fetchUser } = useUser(props.userId);
|
|
118
|
+
|
|
119
|
+
onMounted(fetchUser);
|
|
120
|
+
</script>
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### 4. Pinia 상태 관리
|
|
124
|
+
|
|
125
|
+
```typescript
|
|
126
|
+
// ✅ stores/user.ts
|
|
127
|
+
import { defineStore } from 'pinia';
|
|
128
|
+
import type { User } from '@/types';
|
|
129
|
+
|
|
130
|
+
interface UserState {
|
|
131
|
+
currentUser: User | null;
|
|
132
|
+
users: User[];
|
|
133
|
+
isLoading: boolean;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export const useUserStore = defineStore('user', {
|
|
137
|
+
state: (): UserState => ({
|
|
138
|
+
currentUser: null,
|
|
139
|
+
users: [],
|
|
140
|
+
isLoading: false,
|
|
141
|
+
}),
|
|
142
|
+
|
|
143
|
+
getters: {
|
|
144
|
+
isLoggedIn: (state) => !!state.currentUser,
|
|
145
|
+
userCount: (state) => state.users.length,
|
|
146
|
+
},
|
|
147
|
+
|
|
148
|
+
actions: {
|
|
149
|
+
async login(email: string, password: string) {
|
|
150
|
+
this.isLoading = true;
|
|
151
|
+
try {
|
|
152
|
+
const user = await authApi.login(email, password);
|
|
153
|
+
this.currentUser = user;
|
|
154
|
+
} finally {
|
|
155
|
+
this.isLoading = false;
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
|
|
159
|
+
logout() {
|
|
160
|
+
this.currentUser = null;
|
|
161
|
+
},
|
|
162
|
+
},
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
// Setup Store 스타일 (권장)
|
|
166
|
+
export const useUserStore = defineStore('user', () => {
|
|
167
|
+
const currentUser = ref<User | null>(null);
|
|
168
|
+
const isLoggedIn = computed(() => !!currentUser.value);
|
|
169
|
+
|
|
170
|
+
async function login(email: string, password: string) {
|
|
171
|
+
currentUser.value = await authApi.login(email, password);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
return { currentUser, isLoggedIn, login };
|
|
175
|
+
});
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### 5. Nuxt 3 특화 규칙
|
|
179
|
+
|
|
180
|
+
```typescript
|
|
181
|
+
// ✅ Server API Routes (server/api/)
|
|
182
|
+
// server/api/users/[id].get.ts
|
|
183
|
+
export default defineEventHandler(async (event) => {
|
|
184
|
+
const id = getRouterParam(event, 'id');
|
|
185
|
+
|
|
186
|
+
if (!id) {
|
|
187
|
+
throw createError({
|
|
188
|
+
statusCode: 400,
|
|
189
|
+
message: 'ID가 필요합니다',
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const user = await prisma.user.findUnique({ where: { id } });
|
|
194
|
+
|
|
195
|
+
if (!user) {
|
|
196
|
+
throw createError({
|
|
197
|
+
statusCode: 404,
|
|
198
|
+
message: '사용자를 찾을 수 없습니다',
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return user;
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
// ✅ useFetch / useAsyncData
|
|
206
|
+
<script setup lang="ts">
|
|
207
|
+
// SSR 지원 데이터 페칭
|
|
208
|
+
const { data: user, pending, error } = await useFetch<User>(
|
|
209
|
+
`/api/users/${props.userId}`
|
|
210
|
+
);
|
|
211
|
+
|
|
212
|
+
// 캐싱 키 지정
|
|
213
|
+
const { data: posts } = await useAsyncData(
|
|
214
|
+
`user-${props.userId}-posts`,
|
|
215
|
+
() => $fetch(`/api/users/${props.userId}/posts`)
|
|
216
|
+
);
|
|
217
|
+
</script>
|
|
218
|
+
|
|
219
|
+
// ✅ Middleware
|
|
220
|
+
// middleware/auth.ts
|
|
221
|
+
export default defineNuxtRouteMiddleware((to, from) => {
|
|
222
|
+
const { isLoggedIn } = useUserStore();
|
|
223
|
+
|
|
224
|
+
if (!isLoggedIn && to.path !== '/login') {
|
|
225
|
+
return navigateTo('/login');
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### 6. 컴포넌트 구조
|
|
231
|
+
|
|
232
|
+
```vue
|
|
233
|
+
<!-- ✅ 권장 컴포넌트 구조 -->
|
|
234
|
+
<script setup lang="ts">
|
|
235
|
+
// 1. 타입 import
|
|
236
|
+
import type { User, Item } from '@/types';
|
|
237
|
+
|
|
238
|
+
// 2. 컴포넌트 import
|
|
239
|
+
import UserAvatar from '@/components/UserAvatar.vue';
|
|
240
|
+
|
|
241
|
+
// 3. Props/Emits
|
|
242
|
+
interface Props {
|
|
243
|
+
user: User;
|
|
244
|
+
editable?: boolean;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
248
|
+
editable: false,
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
const emit = defineEmits<{
|
|
252
|
+
(e: 'update', user: User): void;
|
|
253
|
+
}>();
|
|
254
|
+
|
|
255
|
+
// 4. Composables
|
|
256
|
+
const { isLoading, save } = useUserForm();
|
|
257
|
+
|
|
258
|
+
// 5. Reactive state
|
|
259
|
+
const formData = ref({ ...props.user });
|
|
260
|
+
const isEditing = ref(false);
|
|
261
|
+
|
|
262
|
+
// 6. Computed
|
|
263
|
+
const canSave = computed(() =>
|
|
264
|
+
formData.value.name.length > 0 && !isLoading.value
|
|
265
|
+
);
|
|
266
|
+
|
|
267
|
+
// 7. Methods
|
|
268
|
+
async function handleSave() {
|
|
269
|
+
await save(formData.value);
|
|
270
|
+
emit('update', formData.value);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// 8. Lifecycle
|
|
274
|
+
onMounted(() => {
|
|
275
|
+
console.log('컴포넌트 준비됨');
|
|
276
|
+
});
|
|
277
|
+
</script>
|
|
278
|
+
|
|
279
|
+
<template>
|
|
280
|
+
<div class="user-card">
|
|
281
|
+
<UserAvatar :src="user.avatar" />
|
|
282
|
+
<h2>{{ user.name }}</h2>
|
|
283
|
+
<button
|
|
284
|
+
v-if="editable"
|
|
285
|
+
:disabled="!canSave"
|
|
286
|
+
@click="handleSave"
|
|
287
|
+
>
|
|
288
|
+
저장
|
|
289
|
+
</button>
|
|
290
|
+
</div>
|
|
291
|
+
</template>
|
|
292
|
+
|
|
293
|
+
<style scoped>
|
|
294
|
+
.user-card {
|
|
295
|
+
padding: 1rem;
|
|
296
|
+
border-radius: 8px;
|
|
297
|
+
}
|
|
298
|
+
</style>
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
## 안티패턴
|
|
302
|
+
|
|
303
|
+
```typescript
|
|
304
|
+
// ❌ v-if와 v-for 함께 사용
|
|
305
|
+
<li v-for="user in users" v-if="user.isActive">
|
|
306
|
+
|
|
307
|
+
// ✅ computed로 필터링
|
|
308
|
+
const activeUsers = computed(() => users.value.filter(u => u.isActive));
|
|
309
|
+
<li v-for="user in activeUsers">
|
|
310
|
+
|
|
311
|
+
// ❌ Props 직접 수정
|
|
312
|
+
props.user.name = '새 이름';
|
|
313
|
+
|
|
314
|
+
// ✅ emit으로 부모에게 알림
|
|
315
|
+
emit('update', { ...props.user, name: '새 이름' });
|
|
316
|
+
|
|
317
|
+
// ❌ $refs 남용
|
|
318
|
+
this.$refs.input.focus();
|
|
319
|
+
|
|
320
|
+
// ✅ template ref + expose
|
|
321
|
+
const inputRef = ref<HTMLInputElement>();
|
|
322
|
+
defineExpose({ focus: () => inputRef.value?.focus() });
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
## 파일 구조 (Nuxt 3)
|
|
326
|
+
|
|
327
|
+
```
|
|
328
|
+
project/
|
|
329
|
+
├── components/
|
|
330
|
+
│ ├── ui/ # 기본 UI 컴포넌트
|
|
331
|
+
│ ├── features/ # 기능별 컴포넌트
|
|
332
|
+
│ └── layouts/ # 레이아웃 컴포넌트
|
|
333
|
+
├── composables/ # Composition 함수
|
|
334
|
+
├── stores/ # Pinia 스토어
|
|
335
|
+
├── server/
|
|
336
|
+
│ ├── api/ # API 라우트
|
|
337
|
+
│ ├── middleware/ # 서버 미들웨어
|
|
338
|
+
│ └── utils/ # 서버 유틸리티
|
|
339
|
+
├── pages/ # 파일 기반 라우팅
|
|
340
|
+
├── middleware/ # 클라이언트 미들웨어
|
|
341
|
+
├── types/ # TypeScript 타입
|
|
342
|
+
└── utils/ # 유틸리티 함수
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
## 체크리스트
|
|
346
|
+
|
|
347
|
+
- [ ] Composition API + `<script setup>` 사용
|
|
348
|
+
- [ ] Props/Emits 타입 정의
|
|
349
|
+
- [ ] Composables로 로직 분리
|
|
350
|
+
- [ ] Pinia Setup Store 스타일 사용
|
|
351
|
+
- [ ] `any` 타입 사용 금지
|
|
352
|
+
- [ ] v-if/v-for 분리
|
|
353
|
+
- [ ] scoped 스타일 사용
|
package/README.md
CHANGED
|
@@ -24,7 +24,14 @@ SPEC 문서 하나로 AI가 바로 구현하고, **시나리오별 자동 검증
|
|
|
24
24
|
- **자동 컨텍스트 관리**: 80%+ 시 자동 저장, 세션 자동 복원
|
|
25
25
|
- **36개 내장 도구**: 코드 분석, 품질 검증, 세션 메모리 (MCP 오버헤드 제거)
|
|
26
26
|
|
|
27
|
-
### v2.
|
|
27
|
+
### v2.3.0 신규 기능
|
|
28
|
+
|
|
29
|
+
- **📦 14개 프레임워크별 언어 룰**: Next.js, React, Vue, Nuxt, React Native 등 프레임워크별 최적화 규칙
|
|
30
|
+
- **🔄 모노레포 완벽 지원**: packages/*, apps/* 하위 패키지별 자동 감지 및 룰 적용
|
|
31
|
+
- **🧹 레거시 자동 정리**: `vibe update` 시 이전 버전 파일 자동 정리
|
|
32
|
+
- **⚙️ 명령어 구조 개선**: 7개 core 명령어 + `/vibe.utils` 유틸리티 통합
|
|
33
|
+
|
|
34
|
+
### v2.2.0 기능
|
|
28
35
|
|
|
29
36
|
- **⚡ ULTRAWORK Pipeline**: 구현 중 백그라운드 에이전트로 다음 Phase 준비
|
|
30
37
|
- **🔄 Phase 파이프라이닝**: Phase 간 대기 시간 제거 (~50% 속도 향상)
|
|
@@ -40,18 +47,20 @@ SPEC 문서 하나로 AI가 바로 구현하고, **시나리오별 자동 검증
|
|
|
40
47
|
|
|
41
48
|
## Installation
|
|
42
49
|
|
|
50
|
+
### CLI 설치
|
|
51
|
+
|
|
43
52
|
```bash
|
|
44
53
|
npm install -g @su-record/vibe
|
|
45
54
|
vibe init
|
|
46
55
|
```
|
|
47
56
|
|
|
48
|
-
|
|
57
|
+
CLI 설치 시 생성되는 구조:
|
|
49
58
|
|
|
50
59
|
```text
|
|
51
60
|
project/
|
|
52
61
|
├── CLAUDE.md # 프로젝트 컨텍스트
|
|
53
62
|
└── .claude/
|
|
54
|
-
├── commands/ # 슬래시 커맨드 (
|
|
63
|
+
├── commands/ # 슬래시 커맨드 (7개)
|
|
55
64
|
├── agents/ # 서브에이전트
|
|
56
65
|
│ ├── review/ # 리뷰 에이전트 (12개)
|
|
57
66
|
│ └── research/ # 리서치 에이전트 (4개)
|
|
@@ -91,28 +100,29 @@ cd my-project
|
|
|
91
100
|
## Workflow
|
|
92
101
|
|
|
93
102
|
```
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
103
|
+
/vibe.spec "기능명"
|
|
104
|
+
↓ 대화형 요구사항 수집
|
|
105
|
+
↓ 요구사항 확정 후 4개 병렬 리서치
|
|
106
|
+
↓ .claude/vibe/specs/{기능명}.md + .feature
|
|
107
|
+
|
|
108
|
+
/vibe.run "기능명" ultrawork
|
|
109
|
+
↓ 시나리오별 구현 + 즉시 검증 (SDD)
|
|
110
|
+
↓ Scenario 1 → Scenario 2 → ...
|
|
111
|
+
|
|
112
|
+
/vibe.verify "기능명"
|
|
113
|
+
↓ Given/When/Then 단계별 검증
|
|
114
|
+
|
|
115
|
+
/vibe.review
|
|
116
|
+
↓ 13+ 병렬 리뷰 에이전트 (P1/P2/P3)
|
|
117
|
+
|
|
118
|
+
/vibe.analyze "기능명"
|
|
119
|
+
↓ 코드 탐색/구조 분석
|
|
120
|
+
|
|
121
|
+
/vibe.reason "문제"
|
|
122
|
+
↓ 9단계 체계적 추론
|
|
123
|
+
|
|
124
|
+
/vibe.utils --옵션
|
|
125
|
+
↓ 유틸리티 (--ui, --diagram, --e2e, --compound)
|
|
116
126
|
```
|
|
117
127
|
|
|
118
128
|
### 시나리오 주도 개발 (SDD)
|
|
@@ -161,35 +171,16 @@ Feature 로드 → Scenario 1 [구현→검증] → Scenario 2 [구현→검증]
|
|
|
161
171
|
|
|
162
172
|
### Claude Code 슬래시 커맨드
|
|
163
173
|
|
|
164
|
-
#### 핵심 워크플로우
|
|
165
|
-
|
|
166
174
|
| 명령어 | 설명 |
|
|
167
175
|
|--------|------|
|
|
168
176
|
| `/vibe.spec "기능명"` | SPEC 작성 (PTCF 구조) + 병렬 리서치 |
|
|
169
177
|
| `/vibe.run "기능명"` | 구현 실행 |
|
|
170
178
|
| `/vibe.run "기능명" ultrawork` | 🚀 **최대 성능 모드** (권장) |
|
|
171
|
-
| `/vibe.run "기능명" ulw` | ultrawork 단축어 |
|
|
172
|
-
| `/vibe.run "기능명" --phase N` | 특정 Phase만 실행 |
|
|
173
179
|
| `/vibe.verify "기능명"` | 검증 |
|
|
174
|
-
| `/vibe.review` |
|
|
175
|
-
| `/vibe.
|
|
176
|
-
| `/vibe.compound` | 🆕 **지식 문서화** (해결책 아카이브) |
|
|
177
|
-
| `/vibe.continue` | 🆕 **세션 복원** (이전 컨텍스트 로드) |
|
|
178
|
-
|
|
179
|
-
#### 분석 & 도구
|
|
180
|
-
|
|
181
|
-
| 명령어 | 설명 |
|
|
182
|
-
|--------|------|
|
|
183
|
-
| `/vibe.analyze` | 프로젝트 전체 분석 |
|
|
184
|
-
| `/vibe.analyze "기능명"` | 특정 기능/모듈 분석 |
|
|
185
|
-
| `/vibe.analyze --code` | 코드 품질 분석만 |
|
|
186
|
-
| `/vibe.analyze --deps` | 의존성 분석만 |
|
|
187
|
-
| `/vibe.analyze --arch` | 아키텍처 분석만 |
|
|
180
|
+
| `/vibe.review` | **병렬 코드 리뷰** (13+ 에이전트) |
|
|
181
|
+
| `/vibe.analyze "기능명"` | 코드 탐색/분석 |
|
|
188
182
|
| `/vibe.reason "문제"` | 체계적 추론 (9단계) |
|
|
189
|
-
| `/vibe.
|
|
190
|
-
| `/vibe.diagram` | 아키텍처 다이어그램 |
|
|
191
|
-
| `/vibe.diagram --er` | ERD 다이어그램 |
|
|
192
|
-
| `/vibe.diagram --flow` | 플로우차트 |
|
|
183
|
+
| `/vibe.utils --옵션` | 유틸리티 (--ui, --diagram, --e2e) |
|
|
193
184
|
|
|
194
185
|
---
|
|
195
186
|
|
|
@@ -245,24 +236,18 @@ Scenario 1 → Scenario 2 → Scenario 3 → ... → Scenario N
|
|
|
245
236
|
|
|
246
237
|
`/vibe.verify` 실행 시 자동 생성되는 품질 리포트:
|
|
247
238
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
│ | 4 | 비밀번호 찾기 링크 | ✅ | ✅ | ✅ | ✅ | │
|
|
261
|
-
│ │
|
|
262
|
-
│ 📈 품질 점수: 94/100 │
|
|
263
|
-
│ │
|
|
264
|
-
└─────────────────────────────────────────────────────────────────┘
|
|
265
|
-
```
|
|
239
|
+
**VERIFICATION REPORT: login**
|
|
240
|
+
|
|
241
|
+
시나리오: 4/4 통과 (100%)
|
|
242
|
+
|
|
243
|
+
| # | Scenario | Given | When | Then | Status |
|
|
244
|
+
|---|----------|-------|------|------|--------|
|
|
245
|
+
| 1 | 유효한 로그인 성공 | ✅ | ✅ | ✅ | ✅ |
|
|
246
|
+
| 2 | 잘못된 비밀번호 에러 | ✅ | ✅ | ✅ | ✅ |
|
|
247
|
+
| 3 | 이메일 형식 검증 | ✅ | ✅ | ✅ | ✅ |
|
|
248
|
+
| 4 | 비밀번호 찾기 링크 | ✅ | ✅ | ✅ | ✅ |
|
|
249
|
+
|
|
250
|
+
품질 점수: **94/100**
|
|
266
251
|
|
|
267
252
|
### 검증 실패 시
|
|
268
253
|
|
|
@@ -289,31 +274,27 @@ When: "비밀번호 찾기" 클릭
|
|
|
289
274
|
|
|
290
275
|
13+ 전문 에이전트가 동시에 코드 리뷰:
|
|
291
276
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
│ Language │ Python, TypeScript, Rails, React │
|
|
300
|
-
│ Quality │ Complexity, test coverage, git │
|
|
301
|
-
└─────────────────────────────────────────────────────┘
|
|
302
|
-
```
|
|
277
|
+
| 분야 | 검토 항목 |
|
|
278
|
+
|------|----------|
|
|
279
|
+
| Security | OWASP Top 10, SQL injection, XSS |
|
|
280
|
+
| Performance | N+1 queries, memory leaks |
|
|
281
|
+
| Architecture | SOLID violations, layer breaches |
|
|
282
|
+
| Language | Python, TypeScript, Rails, React |
|
|
283
|
+
| Quality | Complexity, test coverage, git |
|
|
303
284
|
|
|
304
285
|
**우선순위 시스템:**
|
|
305
286
|
- 🔴 **P1 (Critical)**: 머지 차단 - 보안 취약점, 데이터 손실
|
|
306
287
|
- 🟡 **P2 (Important)**: 수정 권장 - 성능 문제, 테스트 누락
|
|
307
288
|
- 🔵 **P3 (Nice-to-have)**: 백로그 - 코드 스타일, 리팩토링
|
|
308
289
|
|
|
309
|
-
### E2E 테스트 (/vibe.e2e)
|
|
290
|
+
### E2E 테스트 (/vibe.utils --e2e)
|
|
310
291
|
|
|
311
292
|
Playwright 기반 브라우저 자동화 테스트:
|
|
312
293
|
|
|
313
294
|
```bash
|
|
314
|
-
/vibe.e2e "login flow"
|
|
315
|
-
/vibe.e2e --visual
|
|
316
|
-
/vibe.e2e --record
|
|
295
|
+
/vibe.utils --e2e "login flow" # 시나리오 테스트
|
|
296
|
+
/vibe.utils --e2e --visual # 시각적 회귀 테스트
|
|
297
|
+
/vibe.utils --e2e --record # 비디오 녹화
|
|
317
298
|
```
|
|
318
299
|
|
|
319
300
|
**기능:**
|
|
@@ -322,7 +303,7 @@ Playwright 기반 브라우저 자동화 테스트:
|
|
|
322
303
|
- 접근성(a11y) 검사
|
|
323
304
|
- 버그 재현 자동화
|
|
324
305
|
|
|
325
|
-
### 지식 복리 (
|
|
306
|
+
### 지식 복리 (자동 트리거)
|
|
326
307
|
|
|
327
308
|
해결한 문제를 자동 문서화하여 지식 축적:
|
|
328
309
|
|
|
@@ -334,7 +315,7 @@ Playwright 기반 브라우저 자동화 테스트:
|
|
|
334
315
|
└── integration/ # 외부 연동
|
|
335
316
|
```
|
|
336
317
|
|
|
337
|
-
|
|
318
|
+
**자동 트리거**: "버그 해결됨", "bug fixed", "PR merged" 등 (Hooks에서 자동 감지)
|
|
338
319
|
|
|
339
320
|
### 리서치 에이전트 강화
|
|
340
321
|
|
|
@@ -386,7 +367,7 @@ Primary 결과만 사용
|
|
|
386
367
|
project/
|
|
387
368
|
├── CLAUDE.md # 프로젝트 컨텍스트 ← git 공유
|
|
388
369
|
└── .claude/ # ⚠️ 반드시 git에 커밋 ← git 공유
|
|
389
|
-
├── commands/ # 슬래시 커맨드 (
|
|
370
|
+
├── commands/ # 슬래시 커맨드 (7개)
|
|
390
371
|
├── agents/ # 서브에이전트
|
|
391
372
|
│ ├── review/ # 리뷰 에이전트 (12개)
|
|
392
373
|
│ └── research/ # 리서치 에이전트 (4개)
|
|
@@ -477,22 +458,41 @@ Then: {예상 결과}
|
|
|
477
458
|
|
|
478
459
|
## Coding Rules (.claude/vibe/rules/)
|
|
479
460
|
|
|
480
|
-
###
|
|
461
|
+
### 14개 프레임워크별 언어 룰 (v2.3.0)
|
|
462
|
+
|
|
463
|
+
`vibe init` / `vibe update` 시 프로젝트의 기술 스택을 감지하여 **프레임워크별 최적화 규칙**을 자동 설치합니다.
|
|
464
|
+
|
|
465
|
+
| 감지 스택 | 룰 파일 | 주요 내용 |
|
|
466
|
+
|----------|---------|----------|
|
|
467
|
+
| Next.js | `typescript-nextjs.md` | App Router, Server Components, Server Actions |
|
|
468
|
+
| React | `typescript-react.md` | Hooks, 컴포넌트 패턴, 상태관리 |
|
|
469
|
+
| Vue.js | `typescript-vue.md` | Composition API, Pinia, script setup |
|
|
470
|
+
| Nuxt 3 | `typescript-nuxt.md` | useFetch, Server API, Auto-imports |
|
|
471
|
+
| React Native | `typescript-react-native.md` | 네이티브 모듈, 성능 최적화 |
|
|
472
|
+
| Node.js | `typescript-node.md` | Express/Fastify/NestJS 패턴 |
|
|
473
|
+
| FastAPI | `python-fastapi.md` | Pydantic, 비동기 처리, 의존성 주입 |
|
|
474
|
+
| Django | `python-django.md` | ORM, 뷰 패턴, 시그널 |
|
|
475
|
+
| Flutter | `dart-flutter.md` | Riverpod/BLoC, 위젯 트리 |
|
|
476
|
+
| Go | `go.md` | 에러 처리, 고루틴, 인터페이스 |
|
|
477
|
+
| Rust | `rust.md` | Result/Option, 소유권, unsafe |
|
|
478
|
+
| Spring Boot | `java-spring.md` | DI, JPA, 트랜잭션 |
|
|
479
|
+
| Android | `kotlin-android.md` | Compose, ViewModel, Coroutines |
|
|
480
|
+
| iOS | `swift-ios.md` | SwiftUI, Combine, 프로토콜 |
|
|
481
481
|
|
|
482
|
-
|
|
482
|
+
### 모노레포 지원
|
|
483
483
|
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
484
|
+
`packages/*`, `apps/*` 하위 패키지별로 각각 감지하여 필요한 룰만 설치:
|
|
485
|
+
|
|
486
|
+
```bash
|
|
487
|
+
# 모노레포 예시
|
|
488
|
+
monorepo/
|
|
489
|
+
├── packages/
|
|
490
|
+
│ ├── web/ → typescript-nextjs.md 설치
|
|
491
|
+
│ ├── mobile/ → typescript-react-native.md 설치
|
|
492
|
+
│ └── api/ → python-fastapi.md 설치
|
|
493
|
+
```
|
|
494
494
|
|
|
495
|
-
>
|
|
495
|
+
> 각 패키지에 맞는 프레임워크 규칙이 자동 적용됩니다.
|
|
496
496
|
|
|
497
497
|
### 핵심 원칙
|
|
498
498
|
|