@su-record/vibe 2.8.19 → 2.8.20

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@su-record/vibe",
3
- "version": "2.8.19",
3
+ "version": "2.8.20",
4
4
  "description": "AI Coding Framework for Claude Code — 49 agents, 41+ tools, multi-LLM orchestration",
5
5
  "type": "module",
6
6
  "main": "dist/cli/index.js",
@@ -132,25 +132,129 @@ Popup: 패턴 분류 (확인/취소, 상세 모달, 알림, 입력 폼)
132
132
  - 개요 JSDoc 주석 (A-2에서 추출한 overview)
133
133
  ```
134
134
 
135
- ### 섹션 컴포넌트 필수 포함 사항
135
+ ### HARD RULE: template 금지
136
136
 
137
137
  ```
138
- 섹션 컴포넌트에 반드시 포함:
139
-
140
- 1. JSDoc 주석:
141
- - [기능 정의] — A-2에서 추출한 기능 설명
142
- - [인터랙션] ①②③ 번호 + 동작 설명
143
- - [상태] 해당 섹션의 상태 목록
138
+ 브라우저에서 열었을 화면에 텍스트가 보여야 한다.
139
+ 빈 컴포넌트 shell은 Step A 미완성.
140
+
141
+ <template> 안에 반드시:
142
+ - 스토리보드에서 추출한 실제 텍스트 (제목, 설명, 버튼 라벨)
143
+ - 데이터가 렌더링되는 리스트 (v-for / .map)
144
+ - 클릭 가능한 버튼/링크
145
+ - 조건부 렌더링 (v-if / &&)
146
+ ```
144
147
 
145
- 2. TypeScript 인터페이스:
146
- - 섹션에서 사용하는 데이터 구조 정의
148
+ ### 섹션 컴포넌트 — 실제 코드 예시 (Vue)
149
+
150
+ ```vue
151
+ <template>
152
+ <section class="dailyCheckInSection">
153
+ <h2 class="dailyCheckInSection__title">일일 출석 미션</h2>
154
+ <p class="dailyCheckInSection__description">매일 출석하고 스노우 토큰을 받으세요!</p>
155
+
156
+ <div class="dailyCheckInSection__calendar">
157
+ <div
158
+ v-for="day in checkInDays"
159
+ :key="day.date"
160
+ class="dailyCheckInSection__day"
161
+ :class="{ 'is-checked': day.checked, 'is-today': day.isToday }"
162
+ @click="handleCheckIn(day)"
163
+ >
164
+ <span class="dailyCheckInSection__dayLabel">{{ day.date }}</span>
165
+ <span class="dailyCheckInSection__dayReward">{{ day.reward }} 토큰</span>
166
+ </div>
167
+ </div>
168
+
169
+ <div class="dailyCheckInSection__milestones">
170
+ <div
171
+ v-for="milestone in milestones"
172
+ :key="milestone.days"
173
+ class="dailyCheckInSection__milestone"
174
+ :class="{ 'is-claimable': milestone.claimable, 'is-claimed': milestone.claimed }"
175
+ @click="handleClaimReward(milestone)"
176
+ >
177
+ <span>{{ milestone.days }}일 달성</span>
178
+ <span>{{ milestone.reward }}</span>
179
+ <button v-if="milestone.claimable && !milestone.claimed">받기</button>
180
+ </div>
181
+ </div>
182
+ </section>
183
+ </template>
184
+
185
+ <script setup lang="ts">
186
+ /**
187
+ * 일일 출석 미션 섹션
188
+ *
189
+ * [기능 정의]
190
+ * - 매일 출석 시 스노우 토큰 즉시 지급
191
+ * - 누적 3/5/7일 달성 시 추가 보상
192
+ *
193
+ * [인터랙션]
194
+ * ① 출석하기 클릭 → 출석 처리 → 토큰 지급 표시
195
+ * ② 누적 보상 클릭 → 보상 수령
196
+ *
197
+ * [상태] default, checked, reward-claimed
198
+ */
199
+
200
+ interface CheckInDay {
201
+ date: string
202
+ checked: boolean
203
+ isToday: boolean
204
+ reward: number
205
+ }
206
+
207
+ interface Milestone {
208
+ days: number
209
+ claimable: boolean
210
+ claimed: boolean
211
+ reward: string
212
+ }
213
+
214
+ // 목 데이터 — 빈 배열 금지!
215
+ const checkInDays = ref<CheckInDay[]>([
216
+ { date: 'Day 1', checked: true, isToday: false, reward: 10 },
217
+ { date: 'Day 2', checked: true, isToday: false, reward: 10 },
218
+ { date: 'Day 3', checked: false, isToday: true, reward: 10 },
219
+ { date: 'Day 4', checked: false, isToday: false, reward: 10 },
220
+ { date: 'Day 5', checked: false, isToday: false, reward: 10 },
221
+ { date: 'Day 6', checked: false, isToday: false, reward: 15 },
222
+ { date: 'Day 7', checked: false, isToday: false, reward: 20 },
223
+ ])
224
+
225
+ const milestones = ref<Milestone[]>([
226
+ { days: 3, claimable: false, claimed: false, reward: '보상 상자 1개' },
227
+ { days: 5, claimable: false, claimed: false, reward: '보상 상자 2개' },
228
+ { days: 7, claimable: false, claimed: false, reward: '스페셜 보상' },
229
+ ])
230
+
231
+ function handleCheckIn(day: CheckInDay): void {
232
+ // TODO: 출석 API 호출
233
+ }
234
+
235
+ function handleClaimReward(milestone: Milestone): void {
236
+ // TODO: 누적 보상 수령 API 호출
237
+ }
238
+ </script>
239
+ <!-- 스타일은 외부 파일: styles/{feature}/components/_daily-checkin.scss -->
240
+ ```
147
241
 
148
- 3. 이벤트 핸들러:
149
- - 인터랙션 스펙에 맞는 함수 (body는 // TODO:)
242
+ ### 필수 포함 사항 체크리스트
150
243
 
151
- 4. 목 데이터 (빈 배열 금지):
152
- - 기능 정의서에서 추출한 아이템/보상/상품 정보로 채움
153
- - 배열 = UI가 보임 = Step A 미완성
244
+ ```
245
+ <template> 안에:
246
+ 섹션 제목 <h2> (스토리보드에서 추출한 실제 텍스트)
247
+ □ 설명 텍스트 <p> (스토리보드에서 추출)
248
+ □ 리스트 렌더링 (v-for + 목 데이터, 빈 배열 금지)
249
+ □ 버튼/CTA (실제 라벨 텍스트 + @click 핸들러)
250
+ □ 조건부 렌더링 (상태에 따른 v-if)
251
+ □ 클래스명 (Step B에서 외부 스타일과 매칭)
252
+
253
+ <script> 안에:
254
+ □ JSDoc: [기능 정의] + [인터랙션] + [상태]
255
+ □ TypeScript interface
256
+ □ 목 데이터 (기능 정의서에서 추출, 3~7개 아이템)
257
+ □ 이벤트 핸들러 함수 (body는 // TODO:)
154
258
  ```
155
259
 
156
260
  ### 스타일 분리 규칙
@@ -158,23 +262,21 @@ Popup: 패턴 분류 (확인/취소, 상세 모달, 알림, 입력 폼)
158
262
  ```
159
263
  컴포넌트 파일에 <style> 블록을 작성하지 않는다.
160
264
  스타일은 Step B에서 외부 파일로 생성.
161
- 컴포넌트는 template + script 만 포함.
265
+ 컴포넌트는 <template> + <script setup> 만 포함.
162
266
  ```
163
267
 
164
- ### 핵심 원칙: 스타일 없이 동작하는 코드
268
+ ### Step A 완료 기준
165
269
 
166
270
  ```
167
- 클릭/탭/아코디언 등 인터랙션이 실제로 동작
168
- 모달/팝업 open/close가 연결됨
169
- ✅ 리스트 렌더링이데이터로 동작
170
- 조건부 렌더링이 상태에 따라 전환
171
- emit으로 부모-자식 이벤트 연결
172
- 브라우저에서 열면 스타일은 없지만 인터랙션은 동작하는 상태
173
-
174
- Step A에서는 이미지 자리에 빈 영역이 있을 수 있다.
175
- Step B에서 반드시 실제 이미지로 교체해야 함.
176
- → Step B 완료 후 "placeholder", "Key Visual Image", 빈 dashed box가
177
- 코드에 남아있으면 = 미완성 (vibe-figma-frame HARD RULES 참조)
271
+ 브라우저에서 열었을 때:
272
+ 섹션의 제목/설명 텍스트가 화면에 보인다
273
+ ✅ 리스트 아이템이 렌더링된다 (데이터)
274
+ 버튼을 클릭하면 핸들러가 실행된다
275
+ 탭/아코디언/모달이 동작한다
276
+ 스타일은 없다 (Step B에서)
277
+ ❌ 이미지는 없다 (Step B에서)
278
+
279
+ 화면 = Step A 미완성. 다음 단계로 넘어가지 않는다.
178
280
  ```
179
281
 
180
282
  ## A-6. 인터랙션 매핑 테이블
@@ -197,37 +299,46 @@ Step A에서는 이미지 자리에 빈 영역이 있을 수 있다.
197
299
  ### 검증 항목
198
300
 
199
301
  ```
302
+ 0. 빈 화면 검사 (가장 중요 — 먼저 실행):
303
+ 각 컴포넌트 파일을 Read로 열어서 <template> 안에 확인:
304
+ □ <h2> 또는 <h3> 섹션 제목 텍스트 존재
305
+ □ <p> 설명 텍스트 존재
306
+ □ v-for 또는 .map 렌더링 존재 (리스트 있는 섹션)
307
+ □ @click 또는 onClick 이벤트 존재 (인터랙션 있는 섹션)
308
+ <template> 안에 실제 HTML 태그가 없으면 → 빈 컴포넌트 → 재작성
309
+ Grep: "<template>" 다음 줄이 "</template>"이면 → 빈 template
310
+
200
311
  1. 파일 존재 확인 (Glob 도구):
201
312
  □ 루트 페이지 파일 존재
202
313
  □ PAGE 프레임 수 = 컴포넌트 파일 수
203
314
  □ styles 디렉토리 존재
204
- □ 팝업 컴포넌트 존재 (스토리보드에 팝업이 있었으면)
205
- → 누락 시 Write로 생성
206
-
207
- 2. 기능 주석 확인 (Read 도구):
208
- □ 모든 컴포넌트에 [기능 정의] + [인터랙션] + [상태] JSDoc
209
- → 누락 시 Edit으로 추가
210
315
 
211
- 3. 목 데이터 확인 (Grep 도구):
316
+ 2. 목 데이터 확인 (Grep 도구):
212
317
  □ 빈 배열 (ref([]) 패턴) 검색 → 0건
213
318
  → 발견 시 목 데이터 채움
214
319
 
215
- 4. 스타일 분리 확인 (Grep 도구):
320
+ 3. 스타일 분리 확인 (Grep 도구):
216
321
  □ 컴포넌트 내 <style> 블록 0건
217
- → 발견 시 제거
218
322
 
219
- 5. 빌드 확인 (Bash 도구):
323
+ 4. 빌드 확인 (Bash 도구):
220
324
  □ npm run build 성공
221
- → 에러 시 수정 후 재빌드
325
+
326
+ 5. 브라우저 확인:
327
+ □ dev 서버 열어서 실제 화면 확인
328
+ □ 각 섹션에 텍스트가 보이는지
329
+ □ 빈 화면이면 → 해당 컴포넌트 재작성
222
330
  ```
223
331
 
224
332
  ### 완료 조건
225
333
 
226
334
  ```
335
+ ✅ 빈 template 0개 — 모든 컴포넌트에 실제 HTML 마크업 존재
336
+ ✅ 브라우저에서 텍스트/리스트/버튼이 보인다
227
337
  ✅ 파일 수 = PAGE 프레임 수
228
- ✅ 모든 JSDoc 주석 완비
229
338
  ✅ 빈 배열 0개
230
339
  ✅ <style> 블록 0개
231
340
  ✅ 빌드 성공
341
+
342
+ 빈 화면 = Step A 미완성. Step B로 넘어가지 않는다.
232
343
  → Step B 진행 가능
233
344
  ```