@su-record/vibe 0.4.8 → 1.0.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/agents/explorer.md +48 -0
- package/.claude/agents/implementer.md +53 -0
- package/.claude/agents/tester.md +49 -0
- package/.claude/commands/vibe.run.md +130 -5
- package/.claude/commands/vibe.spec.md +66 -4
- package/.claude/commands/vibe.verify.md +102 -114
- package/.claude/{settings.local.json → settings.json} +3 -1
- package/CLAUDE.md +17 -0
- package/README.md +10 -3
- package/bin/vibe +287 -21
- package/package.json +1 -1
- package/templates/feature-template.md +22 -211
- package/templates/hooks-template.json +90 -1
|
@@ -1,12 +1,8 @@
|
|
|
1
1
|
# Feature: {기능명}
|
|
2
2
|
|
|
3
|
-
**
|
|
4
|
-
**Language**: {ko | en}
|
|
5
|
-
**Priority**: {HIGH | MEDIUM | LOW}
|
|
3
|
+
**SPEC**: `.vibe/specs/{기능명}.md`
|
|
6
4
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
## Feature Description
|
|
5
|
+
## User Story
|
|
10
6
|
|
|
11
7
|
**As a** {사용자 역할}
|
|
12
8
|
**I want** {원하는 기능}
|
|
@@ -14,246 +10,61 @@
|
|
|
14
10
|
|
|
15
11
|
---
|
|
16
12
|
|
|
17
|
-
## Background (Optional)
|
|
18
|
-
|
|
19
|
-
```gherkin
|
|
20
|
-
Background:
|
|
21
|
-
Given {공통 전제 조건 1}
|
|
22
|
-
And {공통 전제 조건 2}
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
---
|
|
26
|
-
|
|
27
13
|
## Scenarios
|
|
28
14
|
|
|
29
|
-
### Scenario 1: {
|
|
30
|
-
|
|
31
|
-
**Mapped to**: REQ-001 in SPEC
|
|
15
|
+
### Scenario 1: {Happy Path - 정상 케이스}
|
|
32
16
|
|
|
33
17
|
```gherkin
|
|
34
18
|
Scenario: {시나리오 제목}
|
|
35
19
|
Given {전제 조건}
|
|
36
|
-
And {추가 전제 조건}
|
|
37
20
|
When {사용자 행동}
|
|
38
|
-
And {추가 행동}
|
|
39
21
|
Then {예상 결과}
|
|
40
|
-
And {추가 검증}
|
|
41
22
|
```
|
|
42
23
|
|
|
43
|
-
|
|
44
|
-
- [ ] {SPEC의 Acceptance Criteria 1}
|
|
45
|
-
- [ ] {SPEC의 Acceptance Criteria 2}
|
|
46
|
-
|
|
47
|
-
**Test Data**:
|
|
48
|
-
```json
|
|
49
|
-
{
|
|
50
|
-
"input": {...},
|
|
51
|
-
"expected_output": {...}
|
|
52
|
-
}
|
|
53
|
-
```
|
|
24
|
+
**검증 기준**: SPEC Acceptance Criteria #1
|
|
54
25
|
|
|
55
26
|
---
|
|
56
27
|
|
|
57
|
-
### Scenario 2: {
|
|
28
|
+
### Scenario 2: {Edge Case - 예외 케이스}
|
|
58
29
|
|
|
59
30
|
```gherkin
|
|
60
|
-
Scenario: {에러
|
|
31
|
+
Scenario: {에러 시나리오 제목}
|
|
61
32
|
Given {전제 조건}
|
|
62
33
|
When {잘못된 입력}
|
|
63
|
-
Then {에러
|
|
64
|
-
And {에러 메시지 검증}
|
|
34
|
+
Then {에러 처리}
|
|
65
35
|
```
|
|
66
36
|
|
|
37
|
+
**검증 기준**: SPEC Acceptance Criteria #2
|
|
38
|
+
|
|
67
39
|
---
|
|
68
40
|
|
|
69
|
-
### Scenario Outline: {
|
|
41
|
+
### Scenario Outline: {파라미터화 테스트}
|
|
70
42
|
|
|
71
43
|
```gherkin
|
|
72
44
|
Scenario Outline: {시나리오 제목}
|
|
73
45
|
Given {전제 조건}
|
|
74
|
-
When I
|
|
75
|
-
Then I should see "<
|
|
46
|
+
When I input "<input>"
|
|
47
|
+
Then I should see "<output>"
|
|
76
48
|
|
|
77
49
|
Examples:
|
|
78
|
-
|
|
|
79
|
-
| value1
|
|
80
|
-
| value2
|
|
81
|
-
| value3 | result3 |
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
---
|
|
85
|
-
|
|
86
|
-
## Implementation Guide
|
|
87
|
-
|
|
88
|
-
### Backend Tests (Python + Pytest-BDD)
|
|
89
|
-
|
|
90
|
-
**File**: `tests/features/{기능명}.feature`
|
|
91
|
-
|
|
92
|
-
```python
|
|
93
|
-
# tests/step_defs/test_{기능명}.py
|
|
94
|
-
import pytest
|
|
95
|
-
from pytest_bdd import scenarios, given, when, then, parsers
|
|
96
|
-
|
|
97
|
-
# Load scenarios
|
|
98
|
-
scenarios('features/{기능명}.feature')
|
|
99
|
-
|
|
100
|
-
@given(parsers.parse('사용자가 {role}로 로그인되어 있다'))
|
|
101
|
-
def user_logged_in(context, role):
|
|
102
|
-
context.user = create_user(role)
|
|
103
|
-
context.token = authenticate(context.user)
|
|
104
|
-
|
|
105
|
-
@when(parsers.parse('{action}을 실행한다'))
|
|
106
|
-
def execute_action(context, action):
|
|
107
|
-
context.response = api_call(action, context.token)
|
|
108
|
-
|
|
109
|
-
@then(parsers.parse('응답 코드는 {status_code:d}이어야 한다'))
|
|
110
|
-
def check_status_code(context, status_code):
|
|
111
|
-
assert context.response.status_code == status_code
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
**Run**:
|
|
115
|
-
```bash
|
|
116
|
-
pytest tests/features/{기능명}.feature --verbose
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
---
|
|
120
|
-
|
|
121
|
-
### Frontend Tests (Flutter + Gherkin)
|
|
122
|
-
|
|
123
|
-
**File**: `integration_test/features/{기능명}.feature`
|
|
124
|
-
|
|
125
|
-
```dart
|
|
126
|
-
// integration_test/step_definitions/{기능명}_test.dart
|
|
127
|
-
import 'package:flutter_gherkin/flutter_gherkin.dart';
|
|
128
|
-
|
|
129
|
-
class UserLoggedInStep extends Given1WithWorld<String, FlutterWorld> {
|
|
130
|
-
@override
|
|
131
|
-
Future<void> executeStep(String role) async {
|
|
132
|
-
await world.appDriver.waitForAppToSettle();
|
|
133
|
-
// Login logic
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
@override
|
|
137
|
-
RegExp get pattern => RegExp(r'사용자가 {string}로 로그인되어 있다');
|
|
138
|
-
}
|
|
139
|
-
```
|
|
140
|
-
|
|
141
|
-
**Run**:
|
|
142
|
-
```bash
|
|
143
|
-
flutter test integration_test/{기능명}_test.dart
|
|
50
|
+
| input | output |
|
|
51
|
+
| value1 | result1 |
|
|
52
|
+
| value2 | result2 |
|
|
144
53
|
```
|
|
145
54
|
|
|
146
55
|
---
|
|
147
56
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
**File**: `tests/features/{기능명}.feature`
|
|
151
|
-
|
|
152
|
-
```javascript
|
|
153
|
-
// tests/step_definitions/{기능명}.steps.js
|
|
154
|
-
const { Given, When, Then } = require('@cucumber/cucumber');
|
|
155
|
-
const { render, screen, fireEvent } = require('@testing-library/react');
|
|
156
|
-
|
|
157
|
-
Given('사용자가 {string}로 로그인되어 있다', async function (role) {
|
|
158
|
-
this.user = await createUser(role);
|
|
159
|
-
this.token = await authenticate(this.user);
|
|
160
|
-
});
|
|
161
|
-
|
|
162
|
-
When('{string}을 실행한다', async function (action) {
|
|
163
|
-
this.response = await apiCall(action, this.token);
|
|
164
|
-
});
|
|
57
|
+
## Coverage
|
|
165
58
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
**Run**:
|
|
172
|
-
```bash
|
|
173
|
-
npm test -- --features tests/features/{기능명}.feature
|
|
174
|
-
```
|
|
59
|
+
| Scenario | SPEC Acceptance | Status |
|
|
60
|
+
|----------|-----------------|--------|
|
|
61
|
+
| Scenario 1 | AC-1 | ⬜ |
|
|
62
|
+
| Scenario 2 | AC-2 | ⬜ |
|
|
175
63
|
|
|
176
64
|
---
|
|
177
65
|
|
|
178
|
-
##
|
|
66
|
+
## Verification
|
|
179
67
|
|
|
180
|
-
```gherkin
|
|
181
|
-
@priority-high
|
|
182
|
-
@smoke
|
|
183
|
-
@regression
|
|
184
|
-
@backend
|
|
185
|
-
@frontend
|
|
186
|
-
```
|
|
187
|
-
|
|
188
|
-
**Run by tag**:
|
|
189
68
|
```bash
|
|
190
|
-
|
|
191
|
-
pytest -m "priority-high"
|
|
192
|
-
|
|
193
|
-
# JavaScript
|
|
194
|
-
npm test -- --tags "@smoke"
|
|
69
|
+
/vibe.verify "{기능명}"
|
|
195
70
|
```
|
|
196
|
-
|
|
197
|
-
---
|
|
198
|
-
|
|
199
|
-
## Coverage Mapping
|
|
200
|
-
|
|
201
|
-
| Scenario | SPEC REQ | Acceptance Criteria | Status |
|
|
202
|
-
|----------|----------|---------------------|--------|
|
|
203
|
-
| Scenario 1 | REQ-001 | AC-1, AC-2, AC-3 | ⬜ |
|
|
204
|
-
| Scenario 2 | REQ-002 | AC-4, AC-5 | ⬜ |
|
|
205
|
-
| Scenario 3 | REQ-003 | AC-6, AC-7 | ⬜ |
|
|
206
|
-
|
|
207
|
-
**Coverage**: 0 / {총 시나리오 수} (0%)
|
|
208
|
-
|
|
209
|
-
---
|
|
210
|
-
|
|
211
|
-
## Test Execution Report
|
|
212
|
-
|
|
213
|
-
**Last Run**: {날짜 시간}
|
|
214
|
-
**Environment**: {dev | staging | production}
|
|
215
|
-
|
|
216
|
-
| Scenario | Status | Duration | Error |
|
|
217
|
-
|----------|--------|----------|-------|
|
|
218
|
-
| Scenario 1 | ⬜ PENDING | - | - |
|
|
219
|
-
| Scenario 2 | ⬜ PENDING | - | - |
|
|
220
|
-
|
|
221
|
-
**Total**: 0 passed, 0 failed, {총 수} pending
|
|
222
|
-
|
|
223
|
-
---
|
|
224
|
-
|
|
225
|
-
## Next Steps
|
|
226
|
-
|
|
227
|
-
1. **구현 전 테스트 작성** (Test-First):
|
|
228
|
-
```bash
|
|
229
|
-
# Create feature file first
|
|
230
|
-
vibe feature "{기능명}"
|
|
231
|
-
|
|
232
|
-
# Then implement
|
|
233
|
-
vibe run "Task 1-1"
|
|
234
|
-
```
|
|
235
|
-
|
|
236
|
-
2. **구현 중 테스트 실행**:
|
|
237
|
-
```bash
|
|
238
|
-
vibe test "{기능명}" --watch
|
|
239
|
-
```
|
|
240
|
-
|
|
241
|
-
3. **완료 후 검증**:
|
|
242
|
-
```bash
|
|
243
|
-
vibe verify "{기능명}"
|
|
244
|
-
```
|
|
245
|
-
|
|
246
|
-
---
|
|
247
|
-
|
|
248
|
-
## Notes
|
|
249
|
-
|
|
250
|
-
- ✅ **Given**: 테스트 전제 조건 (상태 설정)
|
|
251
|
-
- ✅ **When**: 사용자 행동 (액션 실행)
|
|
252
|
-
- ✅ **Then**: 예상 결과 (검증)
|
|
253
|
-
- ✅ **And/But**: 추가 조건/검증
|
|
254
|
-
|
|
255
|
-
**Best Practices**:
|
|
256
|
-
- 시나리오는 비즈니스 언어로 작성
|
|
257
|
-
- 구현 세부사항은 Step Definitions에
|
|
258
|
-
- 각 시나리오는 독립적으로 실행 가능해야 함
|
|
259
|
-
- Background는 중복 제거용으로만 사용
|
|
@@ -1,12 +1,101 @@
|
|
|
1
1
|
{
|
|
2
2
|
"hooks": {
|
|
3
|
+
"PreToolUse": [
|
|
4
|
+
{
|
|
5
|
+
"matcher": "Read",
|
|
6
|
+
"hooks": [
|
|
7
|
+
{
|
|
8
|
+
"type": "prompt",
|
|
9
|
+
"prompt": "파일 읽기 전: 1) 전체 파일이 필요한가? offset/limit 파라미터로 필요한 부분만 읽기 2) 이미 읽은 파일인가? 중복 읽기 방지 3) Grep으로 특정 부분만 검색 가능한가?"
|
|
10
|
+
}
|
|
11
|
+
]
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"matcher": "Grep|Glob",
|
|
15
|
+
"hooks": [
|
|
16
|
+
{
|
|
17
|
+
"type": "prompt",
|
|
18
|
+
"prompt": "검색 전: head_limit 파라미터를 활용하여 결과 수를 제한하세요. 너무 많은 결과는 컨텍스트를 낭비합니다."
|
|
19
|
+
}
|
|
20
|
+
]
|
|
21
|
+
}
|
|
22
|
+
],
|
|
3
23
|
"PostToolUse": [
|
|
4
24
|
{
|
|
5
25
|
"matcher": "Write|Edit",
|
|
6
26
|
"hooks": [
|
|
7
27
|
{
|
|
8
28
|
"type": "prompt",
|
|
9
|
-
"prompt": ".vibe/rules/quality/checklist.md 기준으로 방금 수정한 코드를
|
|
29
|
+
"prompt": ".vibe/rules/quality/checklist.md 기준으로 방금 수정한 코드를 검토하세요. 과도한 주석이 있으면 제거하세요. 문제가 있으면 간단히 알려주세요."
|
|
30
|
+
}
|
|
31
|
+
]
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"matcher": "Task",
|
|
35
|
+
"hooks": [
|
|
36
|
+
{
|
|
37
|
+
"type": "prompt",
|
|
38
|
+
"prompt": "Task 완료 후: 핵심 결과만 요약하여 mcp__vibe__save_memory로 저장하세요. 전체 출력이 아닌 중요한 결정사항/발견 패턴/다음 단계만 기록하세요."
|
|
39
|
+
}
|
|
40
|
+
]
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"matcher": "Read",
|
|
44
|
+
"hooks": [
|
|
45
|
+
{
|
|
46
|
+
"type": "prompt",
|
|
47
|
+
"prompt": "파일 읽기 후: 전체 내용을 기억하지 마세요. 필요한 정보만 추출하고 나머지는 필요시 다시 읽으세요. 중복 읽기 감지: 같은 파일을 다시 읽었다면 이전 내용은 무시하세요."
|
|
48
|
+
}
|
|
49
|
+
]
|
|
50
|
+
}
|
|
51
|
+
],
|
|
52
|
+
"Notification": [
|
|
53
|
+
{
|
|
54
|
+
"matcher": "context_window_70",
|
|
55
|
+
"hooks": [
|
|
56
|
+
{
|
|
57
|
+
"type": "prompt",
|
|
58
|
+
"prompt": "📊 컨텍스트 70% 도달. 아직 충분한 여유가 있습니다. 작업을 서두르지 말고 품질에 집중하세요. 불필요한 파일 전체 읽기를 피하고 필요한 부분만 참조하세요."
|
|
59
|
+
}
|
|
60
|
+
]
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"matcher": "context_window_85",
|
|
64
|
+
"hooks": [
|
|
65
|
+
{
|
|
66
|
+
"type": "prompt",
|
|
67
|
+
"prompt": "⚠️ 컨텍스트 85% 도달 (선제적 압축 권고). 1) mcp__vibe__auto_save_context로 현재 상태 저장 2) 오래된 도구 출력은 요약으로 대체 3) 중복 읽은 파일 내용 정리 4) 핵심 정보만 유지하면서 작업 계속"
|
|
68
|
+
}
|
|
69
|
+
]
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"matcher": "context_window_95",
|
|
73
|
+
"hooks": [
|
|
74
|
+
{
|
|
75
|
+
"type": "prompt",
|
|
76
|
+
"prompt": "🚨 컨텍스트 95% 도달! 즉시: 1) mcp__vibe__auto_save_context 실행 2) TodoWrite로 현재 진행 상황과 다음 단계 기록 3) CLAUDE.md, .vibe/specs/ 등 핵심 컨텍스트만 유지 4) 세션 전환 준비"
|
|
77
|
+
}
|
|
78
|
+
]
|
|
79
|
+
}
|
|
80
|
+
],
|
|
81
|
+
"Stop": [
|
|
82
|
+
{
|
|
83
|
+
"matcher": ".*",
|
|
84
|
+
"hooks": [
|
|
85
|
+
{
|
|
86
|
+
"type": "prompt",
|
|
87
|
+
"prompt": "세션 종료 전 체크리스트: 1) TodoWrite로 미완료 작업 기록 (구체적인 다음 단계 포함) 2) mcp__vibe__auto_save_context로 현재 상태 저장 3) 다음 세션 시작 시 mcp__vibe__start_session으로 복원 안내"
|
|
88
|
+
}
|
|
89
|
+
]
|
|
90
|
+
}
|
|
91
|
+
],
|
|
92
|
+
"UserPromptSubmit": [
|
|
93
|
+
{
|
|
94
|
+
"matcher": ".*",
|
|
95
|
+
"hooks": [
|
|
96
|
+
{
|
|
97
|
+
"type": "prompt",
|
|
98
|
+
"prompt": "세션 시작 시: mcp__vibe__start_session을 호출하여 이전 세션 컨텍스트를 복원하세요. 저장된 메모리와 미완료 작업을 확인하세요."
|
|
10
99
|
}
|
|
11
100
|
]
|
|
12
101
|
}
|