@su-record/vibe 0.1.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.
Files changed (88) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +448 -0
  3. package/agents/backend-python-expert.md +453 -0
  4. package/agents/database-postgres-expert.md +538 -0
  5. package/agents/frontend-flutter-expert.md +487 -0
  6. package/agents/frontend-react-expert.md +424 -0
  7. package/agents/quality-reviewer.md +542 -0
  8. package/agents/specification-agent.md +505 -0
  9. package/bin/sutory +332 -0
  10. package/bin/vibe +338 -0
  11. package/mcp/dist/__tests__/complexity.test.js +126 -0
  12. package/mcp/dist/__tests__/memory.test.js +120 -0
  13. package/mcp/dist/__tests__/python-dart-complexity.test.js +146 -0
  14. package/mcp/dist/index.js +230 -0
  15. package/mcp/dist/lib/ContextCompressor.js +305 -0
  16. package/mcp/dist/lib/MemoryManager.js +334 -0
  17. package/mcp/dist/lib/ProjectCache.js +126 -0
  18. package/mcp/dist/lib/PythonParser.js +241 -0
  19. package/mcp/dist/tools/browser/browserPool.js +76 -0
  20. package/mcp/dist/tools/browser/browserUtils.js +135 -0
  21. package/mcp/dist/tools/browser/inspectNetworkRequests.js +140 -0
  22. package/mcp/dist/tools/browser/monitorConsoleLogs.js +97 -0
  23. package/mcp/dist/tools/convention/analyzeComplexity.js +248 -0
  24. package/mcp/dist/tools/convention/applyQualityRules.js +102 -0
  25. package/mcp/dist/tools/convention/checkCouplingCohesion.js +233 -0
  26. package/mcp/dist/tools/convention/complexityMetrics.js +133 -0
  27. package/mcp/dist/tools/convention/dartComplexity.js +117 -0
  28. package/mcp/dist/tools/convention/getCodingGuide.js +64 -0
  29. package/mcp/dist/tools/convention/languageDetector.js +50 -0
  30. package/mcp/dist/tools/convention/pythonComplexity.js +109 -0
  31. package/mcp/dist/tools/convention/suggestImprovements.js +257 -0
  32. package/mcp/dist/tools/convention/validateCodeQuality.js +177 -0
  33. package/mcp/dist/tools/memory/autoSaveContext.js +79 -0
  34. package/mcp/dist/tools/memory/database.js +123 -0
  35. package/mcp/dist/tools/memory/deleteMemory.js +39 -0
  36. package/mcp/dist/tools/memory/listMemories.js +38 -0
  37. package/mcp/dist/tools/memory/memoryConfig.js +27 -0
  38. package/mcp/dist/tools/memory/memorySQLite.js +138 -0
  39. package/mcp/dist/tools/memory/memoryUtils.js +34 -0
  40. package/mcp/dist/tools/memory/migrate.js +113 -0
  41. package/mcp/dist/tools/memory/prioritizeMemory.js +109 -0
  42. package/mcp/dist/tools/memory/recallMemory.js +40 -0
  43. package/mcp/dist/tools/memory/restoreSessionContext.js +69 -0
  44. package/mcp/dist/tools/memory/saveMemory.js +34 -0
  45. package/mcp/dist/tools/memory/searchMemories.js +37 -0
  46. package/mcp/dist/tools/memory/startSession.js +100 -0
  47. package/mcp/dist/tools/memory/updateMemory.js +46 -0
  48. package/mcp/dist/tools/planning/analyzeRequirements.js +166 -0
  49. package/mcp/dist/tools/planning/createUserStories.js +119 -0
  50. package/mcp/dist/tools/planning/featureRoadmap.js +202 -0
  51. package/mcp/dist/tools/planning/generatePrd.js +156 -0
  52. package/mcp/dist/tools/prompt/analyzePrompt.js +145 -0
  53. package/mcp/dist/tools/prompt/enhancePrompt.js +105 -0
  54. package/mcp/dist/tools/semantic/findReferences.js +195 -0
  55. package/mcp/dist/tools/semantic/findSymbol.js +200 -0
  56. package/mcp/dist/tools/thinking/analyzeProblem.js +50 -0
  57. package/mcp/dist/tools/thinking/breakDownProblem.js +140 -0
  58. package/mcp/dist/tools/thinking/createThinkingChain.js +39 -0
  59. package/mcp/dist/tools/thinking/formatAsPlan.js +73 -0
  60. package/mcp/dist/tools/thinking/stepByStepAnalysis.js +58 -0
  61. package/mcp/dist/tools/thinking/thinkAloudProcess.js +75 -0
  62. package/mcp/dist/tools/time/getCurrentTime.js +61 -0
  63. package/mcp/dist/tools/ui/previewUiAscii.js +232 -0
  64. package/mcp/dist/types/tool.js +2 -0
  65. package/mcp/package.json +53 -0
  66. package/package.json +49 -0
  67. package/scripts/install-mcp.js +48 -0
  68. package/scripts/install.sh +70 -0
  69. package/skills/core/communication-guide.md +104 -0
  70. package/skills/core/development-philosophy.md +53 -0
  71. package/skills/core/quick-start.md +121 -0
  72. package/skills/languages/dart-flutter.md +509 -0
  73. package/skills/languages/python-fastapi.md +386 -0
  74. package/skills/languages/typescript-nextjs.md +441 -0
  75. package/skills/languages/typescript-react-native.md +446 -0
  76. package/skills/languages/typescript-react.md +525 -0
  77. package/skills/quality/checklist.md +276 -0
  78. package/skills/quality/testing-strategy.md +437 -0
  79. package/skills/standards/anti-patterns.md +369 -0
  80. package/skills/standards/code-structure.md +291 -0
  81. package/skills/standards/complexity-metrics.md +312 -0
  82. package/skills/standards/naming-conventions.md +198 -0
  83. package/skills/tools/mcp-hi-ai-guide.md +665 -0
  84. package/skills/tools/mcp-workflow.md +51 -0
  85. package/templates/constitution-template.md +193 -0
  86. package/templates/plan-template.md +237 -0
  87. package/templates/spec-template.md +142 -0
  88. package/templates/tasks-template.md +132 -0
@@ -0,0 +1,386 @@
1
+ # 🐍 Python + FastAPI 품질 규칙
2
+
3
+ ## 핵심 원칙 (core에서 상속)
4
+
5
+ ```markdown
6
+ ✅ 단일 책임 (SRP)
7
+ ✅ 중복 제거 (DRY)
8
+ ✅ 재사용성
9
+ ✅ 낮은 복잡도
10
+ ✅ 함수 ≤ 30줄 (권장), ≤ 50줄 (허용)
11
+ ✅ 중첩 ≤ 3단계
12
+ ✅ Cyclomatic complexity ≤ 10
13
+ ```
14
+
15
+ ## Python 특화 규칙
16
+
17
+ ### 1. 타입 힌트 100% 필수
18
+
19
+ ```python
20
+ # ❌ 타입 힌트 없음
21
+ def get_user(user_id):
22
+ return db.get(user_id)
23
+
24
+ # ✅ 완전한 타입 힌트
25
+ async def get_user(user_id: str, db: AsyncSession) -> User | None:
26
+ result = await db.execute(select(User).where(User.id == user_id))
27
+ return result.scalar_one_or_none()
28
+ ```
29
+
30
+ ### 2. Pydantic으로 Contract 정의
31
+
32
+ ```python
33
+ from pydantic import BaseModel, Field, EmailStr, field_validator
34
+
35
+ class CreateUserRequest(BaseModel):
36
+ """사용자 생성 요청 스키마"""
37
+ email: EmailStr
38
+ username: str = Field(min_length=3, max_length=50)
39
+ password: str = Field(min_length=8)
40
+ age: int = Field(ge=0, le=150)
41
+
42
+ @field_validator("username")
43
+ def validate_username(cls, v: str) -> str:
44
+ if not v.isalnum():
45
+ raise ValueError("Username must be alphanumeric")
46
+ return v.lower()
47
+
48
+ class Config:
49
+ json_schema_extra = {
50
+ "example": {
51
+ "email": "user@example.com",
52
+ "username": "johndoe",
53
+ "password": "securepass123",
54
+ "age": 25,
55
+ }
56
+ }
57
+
58
+ class UserResponse(BaseModel):
59
+ """사용자 응답 스키마"""
60
+ id: str
61
+ email: str
62
+ username: str
63
+ created_at: datetime
64
+
65
+ class Config:
66
+ from_attributes = True # SQLAlchemy 호환
67
+ ```
68
+
69
+ ### 3. async/await 패턴
70
+
71
+ ```python
72
+ # ✅ 비동기 I/O (데이터베이스, API 호출)
73
+ async def get_user_with_posts(
74
+ user_id: str,
75
+ db: AsyncSession
76
+ ) -> tuple[User, list[Post]]:
77
+ # 병렬 실행
78
+ user_task = db.execute(select(User).where(User.id == user_id))
79
+ posts_task = db.execute(select(Post).where(Post.user_id == user_id))
80
+
81
+ user_result, posts_result = await asyncio.gather(user_task, posts_task)
82
+
83
+ user = user_result.scalar_one_or_none()
84
+ posts = list(posts_result.scalars().all())
85
+
86
+ return user, posts
87
+
88
+ # ❌ 동기 함수 (블로킹)
89
+ def get_user(user_id: str):
90
+ return requests.get(f"/users/{user_id}") # 블로킹!
91
+ ```
92
+
93
+ ### 4. Early Return 선호
94
+
95
+ ```python
96
+ # ❌ 중첩된 if문
97
+ async def process_order(order_id: str, db: AsyncSession):
98
+ order = await get_order(order_id, db)
99
+ if order:
100
+ if order.is_valid:
101
+ if order.items:
102
+ if order.user.is_active:
103
+ return await process_items(order.items)
104
+ return None
105
+
106
+ # ✅ Early return
107
+ async def process_order(order_id: str, db: AsyncSession) -> ProcessResult | None:
108
+ order = await get_order(order_id, db)
109
+ if not order:
110
+ return None
111
+ if not order.is_valid:
112
+ return None
113
+ if not order.items:
114
+ return None
115
+ if not order.user.is_active:
116
+ return None
117
+
118
+ return await process_items(order.items)
119
+ ```
120
+
121
+ ### 5. Repository 패턴 (데이터 액세스 분리)
122
+
123
+ ```python
124
+ # ✅ Repository 레이어
125
+ class UserRepository:
126
+ """데이터 액세스만 담당"""
127
+
128
+ def __init__(self, db: AsyncSession):
129
+ self.db = db
130
+
131
+ async def get_by_id(self, user_id: str) -> User | None:
132
+ result = await self.db.execute(
133
+ select(User).where(User.id == user_id)
134
+ )
135
+ return result.scalar_one_or_none()
136
+
137
+ async def create(self, user: User) -> User:
138
+ self.db.add(user)
139
+ await self.db.commit()
140
+ await self.db.refresh(user)
141
+ return user
142
+
143
+ async def get_by_email(self, email: str) -> User | None:
144
+ result = await self.db.execute(
145
+ select(User).where(User.email == email)
146
+ )
147
+ return result.scalar_one_or_none()
148
+
149
+ # ✅ Service 레이어 (비즈니스 로직)
150
+ class UserService:
151
+ """비즈니스 로직만 담당"""
152
+
153
+ def __init__(self, repository: UserRepository):
154
+ self.repository = repository
155
+
156
+ async def create_user(
157
+ self, request: CreateUserRequest
158
+ ) -> UserResponse:
159
+ # 비즈니스 규칙: 이메일 중복 체크
160
+ existing = await self.repository.get_by_email(request.email)
161
+ if existing:
162
+ raise HTTPException(409, detail="Email already exists")
163
+
164
+ # 비즈니스 규칙: 비밀번호 해싱
165
+ hashed_password = hash_password(request.password)
166
+
167
+ # 생성
168
+ user = User(
169
+ email=request.email,
170
+ username=request.username,
171
+ password_hash=hashed_password,
172
+ )
173
+ user = await self.repository.create(user)
174
+
175
+ return UserResponse.model_validate(user)
176
+ ```
177
+
178
+ ### 6. 의존성 주입 (FastAPI Depends)
179
+
180
+ ```python
181
+ # app/core/deps.py
182
+ from sqlalchemy.ext.asyncio import AsyncSession
183
+
184
+ async def get_db() -> AsyncSession:
185
+ """데이터베이스 세션 의존성"""
186
+ async with async_session_maker() as session:
187
+ yield session
188
+
189
+ async def get_current_user(
190
+ token: str = Depends(oauth2_scheme),
191
+ db: AsyncSession = Depends(get_db)
192
+ ) -> User:
193
+ """현재 사용자 의존성"""
194
+ payload = decode_jwt(token)
195
+ user = await get_user_by_id(payload["sub"], db)
196
+ if not user:
197
+ raise HTTPException(401, detail="Invalid credentials")
198
+ return user
199
+
200
+ # app/api/v1/users.py
201
+ @router.get("/me", response_model=UserResponse)
202
+ async def get_current_user_profile(
203
+ current_user: User = Depends(get_current_user)
204
+ ):
205
+ """현재 사용자 프로필 조회"""
206
+ return UserResponse.model_validate(current_user)
207
+ ```
208
+
209
+ ### 7. 에러 처리 표준
210
+
211
+ ```python
212
+ from fastapi import HTTPException
213
+
214
+ # ✅ 명확한 에러 메시지
215
+ async def get_user(user_id: str, db: AsyncSession) -> User:
216
+ user = await db.get(User, user_id)
217
+ if not user:
218
+ raise HTTPException(
219
+ status_code=404,
220
+ detail=f"User {user_id} not found"
221
+ )
222
+ return user
223
+
224
+ # ✅ 커스텀 예외
225
+ class UserNotFoundError(Exception):
226
+ def __init__(self, user_id: str):
227
+ self.user_id = user_id
228
+ super().__init__(f"User {user_id} not found")
229
+
230
+ # 전역 예외 핸들러
231
+ @app.exception_handler(UserNotFoundError)
232
+ async def user_not_found_handler(request: Request, exc: UserNotFoundError):
233
+ return JSONResponse(
234
+ status_code=404,
235
+ content={"detail": str(exc)}
236
+ )
237
+ ```
238
+
239
+ ### 8. SQLAlchemy 2.0 스타일
240
+
241
+ ```python
242
+ from sqlalchemy import select, func
243
+ from sqlalchemy.orm import selectinload
244
+
245
+ # ✅ 2.0 스타일 (async + select)
246
+ async def get_users_with_posts(db: AsyncSession) -> list[User]:
247
+ result = await db.execute(
248
+ select(User)
249
+ .options(selectinload(User.posts)) # Eager loading
250
+ .where(User.is_active == True)
251
+ .order_by(User.created_at.desc())
252
+ .limit(20)
253
+ )
254
+ return list(result.scalars().all())
255
+
256
+ # ❌ 1.x 스타일 (레거시)
257
+ def get_users():
258
+ return session.query(User).filter_by(is_active=True).all()
259
+ ```
260
+
261
+ ### 9. Python 관용구 활용
262
+
263
+ ```python
264
+ # ✅ List comprehension
265
+ active_users = [u for u in users if u.is_active]
266
+
267
+ # ✅ Dictionary comprehension
268
+ user_dict = {u.id: u.name for u in users}
269
+
270
+ # ✅ Generator expression (메모리 효율)
271
+ total = sum(u.age for u in users)
272
+
273
+ # ✅ Context manager
274
+ async with db.begin():
275
+ user = User(...)
276
+ db.add(user)
277
+ # 자동 commit/rollback
278
+
279
+ # ✅ Dataclass (간단한 데이터 구조)
280
+ from dataclasses import dataclass
281
+
282
+ @dataclass(frozen=True) # Immutable
283
+ class Point:
284
+ x: float
285
+ y: float
286
+ ```
287
+
288
+ ### 10. 로깅 표준
289
+
290
+ ```python
291
+ import structlog
292
+
293
+ logger = structlog.get_logger()
294
+
295
+ # ✅ 구조화된 로깅
296
+ async def create_user(request: CreateUserRequest):
297
+ logger.info(
298
+ "user_creation_started",
299
+ email=request.email,
300
+ username=request.username
301
+ )
302
+
303
+ try:
304
+ user = await user_service.create(request)
305
+ logger.info(
306
+ "user_creation_succeeded",
307
+ user_id=user.id,
308
+ email=user.email
309
+ )
310
+ return user
311
+ except Exception as e:
312
+ logger.error(
313
+ "user_creation_failed",
314
+ email=request.email,
315
+ error=str(e),
316
+ exc_info=True
317
+ )
318
+ raise
319
+ ```
320
+
321
+ ## 안티패턴
322
+
323
+ ```python
324
+ # ❌ any 타입
325
+ def process_data(data: any): # 타입 안전성 상실
326
+ return data
327
+
328
+ # ❌ 블로킹 I/O in async 함수
329
+ async def bad_example():
330
+ data = requests.get("https://api.example.com") # 블로킹!
331
+ return data
332
+
333
+ # ❌ 예외 무시
334
+ try:
335
+ risky_operation()
336
+ except:
337
+ pass # 위험!
338
+
339
+ # ❌ Mutable default argument
340
+ def append_to_list(item, my_list=[]): # 버그!
341
+ my_list.append(item)
342
+ return my_list
343
+
344
+ # ✅ 올바른 방법
345
+ def append_to_list(item, my_list: list | None = None):
346
+ if my_list is None:
347
+ my_list = []
348
+ my_list.append(item)
349
+ return my_list
350
+ ```
351
+
352
+ ## 코드 품질 도구
353
+
354
+ ```bash
355
+ # 포맷팅
356
+ black .
357
+ isort .
358
+
359
+ # 린팅
360
+ flake8 .
361
+ ruff check .
362
+
363
+ # 타입 체크
364
+ mypy app/ --strict
365
+
366
+ # 테스트
367
+ pytest tests/ -v --cov=app
368
+
369
+ # 보안 체크
370
+ bandit -r app/
371
+ ```
372
+
373
+ ## 체크리스트
374
+
375
+ Python/FastAPI 코드 작성 시:
376
+
377
+ - [ ] 타입 힌트 100% (함수 시그니처, 변수)
378
+ - [ ] Pydantic 스키마로 Contract 정의
379
+ - [ ] async/await 사용 (I/O 작업)
380
+ - [ ] Early return 패턴
381
+ - [ ] Repository + Service 레이어 분리
382
+ - [ ] 의존성 주입 (Depends)
383
+ - [ ] 명확한 에러 메시지
384
+ - [ ] 구조화된 로깅
385
+ - [ ] 함수 ≤ 30줄 (SRP 준수)
386
+ - [ ] 복잡도 ≤ 10