@su-record/vibe 0.4.4 → 0.4.6
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/simplifier.md +1 -1
- package/.claude/commands/vibe.analyze.md +1 -1
- package/.claude/commands/vibe.run.md +1 -1
- package/.claude/commands/vibe.spec.md +2 -2
- package/.claude/commands/vibe.verify.md +1 -1
- package/.claude/settings.local.json +3 -1
- package/README.md +4 -4
- package/bin/vibe +179 -35
- package/package.json +1 -1
- package/templates/hooks-template.json +1 -1
- package/.agent/rules/core/communication-guide.md +0 -104
- package/.agent/rules/core/development-philosophy.md +0 -53
- package/.agent/rules/core/quick-start.md +0 -121
- package/.agent/rules/languages/dart-flutter.md +0 -509
- package/.agent/rules/languages/python-fastapi.md +0 -386
- package/.agent/rules/languages/typescript-nextjs.md +0 -441
- package/.agent/rules/languages/typescript-react-native.md +0 -446
- package/.agent/rules/languages/typescript-react.md +0 -525
- package/.agent/rules/quality/bdd-contract-testing.md +0 -388
- package/.agent/rules/quality/checklist.md +0 -276
- package/.agent/rules/quality/testing-strategy.md +0 -437
- package/.agent/rules/standards/anti-patterns.md +0 -369
- package/.agent/rules/standards/code-structure.md +0 -291
- package/.agent/rules/standards/complexity-metrics.md +0 -312
- package/.agent/rules/standards/naming-conventions.md +0 -198
- package/.agent/rules/tools/mcp-hi-ai-guide.md +0 -665
- package/.agent/rules/tools/mcp-workflow.md +0 -51
|
@@ -117,7 +117,7 @@ argument-hint: "기능명" or --code or --deps or --arch (optional)
|
|
|
117
117
|
|
|
118
118
|
#### 6. 개발 규칙 확인
|
|
119
119
|
|
|
120
|
-
`.
|
|
120
|
+
`.vibe/rules/`에서 관련 규칙 로드:
|
|
121
121
|
- `core/quick-start.md` - 5가지 핵심 원칙
|
|
122
122
|
- `standards/complexity-metrics.md` - 복잡도 기준
|
|
123
123
|
- `quality/checklist.md` - 품질 체크리스트
|
|
@@ -16,7 +16,7 @@ SPEC을 기반으로 구현합니다 (Implementation Agent).
|
|
|
16
16
|
|
|
17
17
|
## Rules Reference
|
|
18
18
|
|
|
19
|
-
**반드시 `.
|
|
19
|
+
**반드시 `.vibe/rules/` 규칙을 따릅니다:**
|
|
20
20
|
- `core/development-philosophy.md` - 수술적 정밀도, 요청 범위만 수정
|
|
21
21
|
- `core/quick-start.md` - 한국어, DRY, SRP, YAGNI
|
|
22
22
|
- `standards/complexity-metrics.md` - 함수 ≤20줄, 중첩 ≤3단계
|
|
@@ -15,7 +15,7 @@ SPEC 문서를 작성합니다 (Specification Agent).
|
|
|
15
15
|
|
|
16
16
|
## Rules Reference
|
|
17
17
|
|
|
18
|
-
**반드시 `.
|
|
18
|
+
**반드시 `.vibe/rules/` 규칙을 따릅니다:**
|
|
19
19
|
- `core/development-philosophy.md` - 수술적 정밀도, 단순함
|
|
20
20
|
- `core/quick-start.md` - 한국어 우선, DRY, SRP
|
|
21
21
|
- `core/communication-guide.md` - 커뮤니케이션 원칙
|
|
@@ -142,7 +142,7 @@ SPEC 문서를 작성합니다 (Specification Agent).
|
|
|
142
142
|
|
|
143
143
|
### 5. 품질 검증
|
|
144
144
|
|
|
145
|
-
`.
|
|
145
|
+
`.vibe/rules/quality/checklist.md` 기준 자체 평가 (0-100점)
|
|
146
146
|
|
|
147
147
|
## Output
|
|
148
148
|
|
|
@@ -15,7 +15,7 @@ argument-hint: "feature name"
|
|
|
15
15
|
|
|
16
16
|
## Rules Reference
|
|
17
17
|
|
|
18
|
-
**반드시 `.
|
|
18
|
+
**반드시 `.vibe/rules/` 규칙을 따릅니다:**
|
|
19
19
|
- `quality/checklist.md` - 코드 품질 체크리스트 (필수)
|
|
20
20
|
- `standards/complexity-metrics.md` - 복잡도 기준
|
|
21
21
|
- `standards/anti-patterns.md` - 안티패턴 검출
|
|
@@ -40,7 +40,9 @@
|
|
|
40
40
|
"Bash(npm version:*)",
|
|
41
41
|
"Bash(npx @su-record/vibe@latest update)",
|
|
42
42
|
"Bash(gh release:*)",
|
|
43
|
-
"Bash(npx @su-record/vibe@latest init:*)"
|
|
43
|
+
"Bash(npx @su-record/vibe@latest init:*)",
|
|
44
|
+
"Bash(vibe version:*)",
|
|
45
|
+
"Bash(vibe update:*)"
|
|
44
46
|
],
|
|
45
47
|
"deny": [],
|
|
46
48
|
"ask": []
|
package/README.md
CHANGED
|
@@ -15,7 +15,7 @@ SPEC 문서 하나로 AI가 바로 구현하는 2-step 워크플로우.
|
|
|
15
15
|
- **Claude Code 전용**: 네이티브 슬래시 커맨드 + MCP 통합
|
|
16
16
|
- **2-Step 워크플로우**: SPEC → RUN → VERIFY (PLAN/TASKS 불필요)
|
|
17
17
|
- **PTCF 구조**: Persona, Task, Context, Format - Gemini 프롬프트 최적화
|
|
18
|
-
- **코딩 규칙 내장**: `.
|
|
18
|
+
- **코딩 규칙 내장**: `.vibe/rules/` - 품질 기준, 복잡도 제한, 안티패턴
|
|
19
19
|
- **자동 품질 검증**: code-simplifier 서브에이전트
|
|
20
20
|
- **36개 MCP 도구**: @su-record/hi-ai 통합
|
|
21
21
|
|
|
@@ -64,7 +64,7 @@ cd my-project
|
|
|
64
64
|
│ /vibe.run "기능명" │
|
|
65
65
|
│ ↓ SPEC 읽고 바로 구현 │
|
|
66
66
|
│ ↓ Phase별 순차 실행 │
|
|
67
|
-
│ ↓ .
|
|
67
|
+
│ ↓ .vibe/rules/ 규칙 준수 │
|
|
68
68
|
├─────────────────────────────────────────────────────┤
|
|
69
69
|
│ /vibe.verify "기능명" │
|
|
70
70
|
│ ↓ Acceptance Criteria 검증 │
|
|
@@ -117,7 +117,7 @@ project/
|
|
|
117
117
|
├── .claude/
|
|
118
118
|
│ ├── commands/ # 슬래시 커맨드 (7개)
|
|
119
119
|
│ └── agents/ # 서브에이전트 (simplifier)
|
|
120
|
-
├── .
|
|
120
|
+
├── .vibe/rules/ # 코딩 규칙
|
|
121
121
|
│ ├── core/ # 핵심 원칙 (수술적 정밀도, DRY, SRP)
|
|
122
122
|
│ ├── quality/ # 품질 체크리스트
|
|
123
123
|
│ ├── standards/ # 복잡도, 네이밍, 안티패턴
|
|
@@ -182,7 +182,7 @@ AI의 역할과 전문성 정의
|
|
|
182
182
|
|
|
183
183
|
---
|
|
184
184
|
|
|
185
|
-
## Coding Rules (.
|
|
185
|
+
## Coding Rules (.vibe/rules/)
|
|
186
186
|
|
|
187
187
|
### 핵심 원칙
|
|
188
188
|
|
package/bin/vibe
CHANGED
|
@@ -11,6 +11,18 @@ const fs = require('fs');
|
|
|
11
11
|
const args = process.argv.slice(2);
|
|
12
12
|
const command = args[0];
|
|
13
13
|
|
|
14
|
+
// 옵션 파싱
|
|
15
|
+
const options = {
|
|
16
|
+
silent: args.includes('--silent') || args.includes('-s')
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
// 로그 함수 (silent 모드 지원)
|
|
20
|
+
function log(message) {
|
|
21
|
+
if (!options.silent) {
|
|
22
|
+
console.log(message);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
14
26
|
// 유틸리티 함수
|
|
15
27
|
function ensureDir(dir) {
|
|
16
28
|
if (!fs.existsSync(dir)) {
|
|
@@ -43,6 +55,94 @@ function copyDirRecursive(sourceDir, targetDir) {
|
|
|
43
55
|
});
|
|
44
56
|
}
|
|
45
57
|
|
|
58
|
+
// 협업자 자동 설치 설정
|
|
59
|
+
function setupCollaboratorAutoInstall(projectRoot) {
|
|
60
|
+
const packageJsonPath = path.join(projectRoot, 'package.json');
|
|
61
|
+
const vibeDir = path.join(projectRoot, '.vibe');
|
|
62
|
+
const packageJson = require('../package.json');
|
|
63
|
+
const vibeVersion = packageJson.version;
|
|
64
|
+
|
|
65
|
+
// 1. Node.js 프로젝트: package.json에 devDependency + postinstall 추가
|
|
66
|
+
if (fs.existsSync(packageJsonPath)) {
|
|
67
|
+
try {
|
|
68
|
+
const pkg = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
|
|
69
|
+
|
|
70
|
+
let modified = false;
|
|
71
|
+
|
|
72
|
+
// devDependencies에 vibe 추가
|
|
73
|
+
if (!pkg.devDependencies) {
|
|
74
|
+
pkg.devDependencies = {};
|
|
75
|
+
}
|
|
76
|
+
if (!pkg.devDependencies['@su-record/vibe']) {
|
|
77
|
+
pkg.devDependencies['@su-record/vibe'] = `^${vibeVersion}`;
|
|
78
|
+
modified = true;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// scripts에 postinstall 추가
|
|
82
|
+
if (!pkg.scripts) {
|
|
83
|
+
pkg.scripts = {};
|
|
84
|
+
}
|
|
85
|
+
if (!pkg.scripts.postinstall) {
|
|
86
|
+
pkg.scripts.postinstall = 'vibe update --silent';
|
|
87
|
+
modified = true;
|
|
88
|
+
} else if (!pkg.scripts.postinstall.includes('vibe update')) {
|
|
89
|
+
// 기존 postinstall이 있으면 vibe update 추가
|
|
90
|
+
pkg.scripts.postinstall = `${pkg.scripts.postinstall} && vibe update --silent`;
|
|
91
|
+
modified = true;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (modified) {
|
|
95
|
+
fs.writeFileSync(packageJsonPath, JSON.stringify(pkg, null, 2) + '\n');
|
|
96
|
+
log(' ✅ package.json에 협업자 자동 설치 설정 추가\n');
|
|
97
|
+
} else {
|
|
98
|
+
log(' ℹ️ package.json 협업 설정 이미 존재\n');
|
|
99
|
+
}
|
|
100
|
+
} catch (e) {
|
|
101
|
+
log(' ⚠️ package.json 수정 실패: ' + e.message + '\n');
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// 2. 범용: .vibe/setup.sh 생성 (비-Node 프로젝트 또는 추가 지원)
|
|
106
|
+
const setupShPath = path.join(vibeDir, 'setup.sh');
|
|
107
|
+
if (!fs.existsSync(setupShPath)) {
|
|
108
|
+
const setupScript = `#!/bin/bash
|
|
109
|
+
# Vibe 협업자 자동 설치 스크립트
|
|
110
|
+
# 사용법: ./.vibe/setup.sh
|
|
111
|
+
|
|
112
|
+
set -e
|
|
113
|
+
|
|
114
|
+
echo "🔧 Vibe 설치 확인 중..."
|
|
115
|
+
|
|
116
|
+
# npm/npx 확인
|
|
117
|
+
if ! command -v npx &> /dev/null; then
|
|
118
|
+
echo "❌ Node.js/npm이 설치되어 있지 않습니다."
|
|
119
|
+
echo " https://nodejs.org 에서 설치해주세요."
|
|
120
|
+
exit 1
|
|
121
|
+
fi
|
|
122
|
+
|
|
123
|
+
# vibe 설치 확인 및 업데이트
|
|
124
|
+
if command -v vibe &> /dev/null; then
|
|
125
|
+
echo "✅ Vibe가 이미 설치되어 있습니다."
|
|
126
|
+
vibe update --silent
|
|
127
|
+
echo "✅ Vibe 업데이트 완료!"
|
|
128
|
+
else
|
|
129
|
+
echo "📦 Vibe 설치 중..."
|
|
130
|
+
npm install -g @su-record/vibe
|
|
131
|
+
vibe update --silent
|
|
132
|
+
echo "✅ Vibe 설치 및 설정 완료!"
|
|
133
|
+
fi
|
|
134
|
+
|
|
135
|
+
echo ""
|
|
136
|
+
echo "다음 명령어로 시작하세요:"
|
|
137
|
+
echo " /vibe.spec \\"기능명\\" SPEC 작성"
|
|
138
|
+
echo " /vibe.run \\"기능명\\" 구현 실행"
|
|
139
|
+
`;
|
|
140
|
+
fs.writeFileSync(setupShPath, setupScript);
|
|
141
|
+
fs.chmodSync(setupShPath, '755');
|
|
142
|
+
log(' ✅ 협업자 설치 스크립트 생성 (.vibe/setup.sh)\n');
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
46
146
|
// 프로젝트 초기화
|
|
47
147
|
async function init(projectName) {
|
|
48
148
|
try {
|
|
@@ -53,34 +153,34 @@ async function init(projectName) {
|
|
|
53
153
|
projectRoot = path.join(process.cwd(), projectName);
|
|
54
154
|
|
|
55
155
|
if (fs.existsSync(projectRoot)) {
|
|
56
|
-
|
|
156
|
+
log(`❌ 폴더가 이미 존재합니다: ${projectName}/`);
|
|
57
157
|
return;
|
|
58
158
|
}
|
|
59
159
|
|
|
60
|
-
|
|
160
|
+
log(`📁 새 프로젝트 생성: ${projectName}/\n`);
|
|
61
161
|
fs.mkdirSync(projectRoot, { recursive: true });
|
|
62
162
|
isNewProject = true;
|
|
63
163
|
}
|
|
64
164
|
|
|
65
165
|
const vibeDir = path.join(projectRoot, '.vibe');
|
|
66
166
|
if (fs.existsSync(vibeDir)) {
|
|
67
|
-
|
|
167
|
+
log('❌ .vibe/ 폴더가 이미 존재합니다.');
|
|
68
168
|
return;
|
|
69
169
|
}
|
|
70
170
|
|
|
71
171
|
// MCP 서버 등록 (Claude Code)
|
|
72
172
|
const mcpPath = path.join(__dirname, '..', 'node_modules', '@su-record', 'hi-ai', 'dist', 'index.js');
|
|
73
173
|
|
|
74
|
-
|
|
174
|
+
log('🔧 Claude Code MCP 서버 등록 중...\n');
|
|
75
175
|
const { execSync } = require('child_process');
|
|
76
176
|
try {
|
|
77
177
|
execSync(`claude mcp add vibe node "${mcpPath}"`, { stdio: 'pipe' });
|
|
78
|
-
|
|
178
|
+
log(' ✅ MCP 서버 등록 완료\n');
|
|
79
179
|
} catch (e) {
|
|
80
180
|
if (e.message.includes('already exists')) {
|
|
81
|
-
|
|
181
|
+
log(' ℹ️ MCP 서버 이미 등록됨\n');
|
|
82
182
|
} else {
|
|
83
|
-
|
|
183
|
+
log(' ⚠️ MCP 수동 등록 필요\n');
|
|
84
184
|
}
|
|
85
185
|
}
|
|
86
186
|
|
|
@@ -98,7 +198,7 @@ async function init(projectName) {
|
|
|
98
198
|
|
|
99
199
|
const sourceDir = path.join(__dirname, '../.claude/commands');
|
|
100
200
|
copyDirContents(sourceDir, commandsDir);
|
|
101
|
-
|
|
201
|
+
log(' ✅ 슬래시 커맨드 설치 완료 (7개)\n');
|
|
102
202
|
|
|
103
203
|
// 설정 파일 생성
|
|
104
204
|
const templatePath = path.join(__dirname, '../templates/constitution-template.md');
|
|
@@ -126,28 +226,28 @@ async function init(projectName) {
|
|
|
126
226
|
// vibe 섹션이 없으면 끝에 추가
|
|
127
227
|
const mergedContent = existingContent.trim() + '\n\n---\n\n' + vibeContent;
|
|
128
228
|
fs.writeFileSync(projectClaudeMd, mergedContent);
|
|
129
|
-
|
|
229
|
+
log(' ✅ CLAUDE.md에 vibe 섹션 추가\n');
|
|
130
230
|
} else {
|
|
131
|
-
|
|
231
|
+
log(' ℹ️ CLAUDE.md에 vibe 섹션 이미 존재\n');
|
|
132
232
|
}
|
|
133
233
|
} else {
|
|
134
234
|
// 없으면 새로 생성
|
|
135
235
|
fs.copyFileSync(vibeClaudeMd, projectClaudeMd);
|
|
136
|
-
|
|
236
|
+
log(' ✅ CLAUDE.md 생성\n');
|
|
137
237
|
}
|
|
138
238
|
|
|
139
|
-
// .
|
|
140
|
-
const rulesSource = path.join(__dirname, '../.
|
|
141
|
-
const rulesTarget = path.join(
|
|
239
|
+
// .vibe/rules/ 복사 (코딩 규칙)
|
|
240
|
+
const rulesSource = path.join(__dirname, '../.vibe/rules');
|
|
241
|
+
const rulesTarget = path.join(vibeDir, 'rules');
|
|
142
242
|
copyDirRecursive(rulesSource, rulesTarget);
|
|
143
|
-
|
|
243
|
+
log(' ✅ 코딩 규칙 설치 완료 (.vibe/rules/)\n');
|
|
144
244
|
|
|
145
245
|
// .claude/agents/ 복사 (서브에이전트)
|
|
146
246
|
const agentsDir = path.join(claudeDir, 'agents');
|
|
147
247
|
ensureDir(agentsDir);
|
|
148
248
|
const agentsSourceDir = path.join(__dirname, '../.claude/agents');
|
|
149
249
|
copyDirContents(agentsSourceDir, agentsDir);
|
|
150
|
-
|
|
250
|
+
log(' ✅ 서브에이전트 설치 완료 (.claude/agents/)\n');
|
|
151
251
|
|
|
152
252
|
// .claude/settings.local.json 생성 (Hooks 설정)
|
|
153
253
|
const settingsPath = path.join(claudeDir, 'settings.local.json');
|
|
@@ -155,14 +255,17 @@ async function init(projectName) {
|
|
|
155
255
|
const hooksTemplate = path.join(__dirname, '../templates/hooks-template.json');
|
|
156
256
|
if (fs.existsSync(hooksTemplate)) {
|
|
157
257
|
fs.copyFileSync(hooksTemplate, settingsPath);
|
|
158
|
-
|
|
258
|
+
log(' ✅ Hooks 설정 설치 완료 (.claude/settings.local.json)\n');
|
|
159
259
|
}
|
|
160
260
|
} else {
|
|
161
|
-
|
|
261
|
+
log(' ℹ️ Hooks 설정 이미 존재\n');
|
|
162
262
|
}
|
|
163
263
|
|
|
264
|
+
// 협업자 자동 설치 설정
|
|
265
|
+
setupCollaboratorAutoInstall(projectRoot);
|
|
266
|
+
|
|
164
267
|
// 완료 메시지
|
|
165
|
-
|
|
268
|
+
log(`
|
|
166
269
|
✅ vibe 초기화 완료!
|
|
167
270
|
|
|
168
271
|
${isNewProject ? `프로젝트 위치:
|
|
@@ -174,17 +277,19 @@ ${isNewProject ? `프로젝트 위치:
|
|
|
174
277
|
├── commands/ # 슬래시 커맨드 (7개)
|
|
175
278
|
├── agents/ # 서브에이전트 (simplifier)
|
|
176
279
|
└── settings.local.json # Hooks 설정 (자동 품질 검증)
|
|
177
|
-
.agent/rules/ # 코딩 규칙
|
|
178
|
-
├── core/ # 핵심 원칙
|
|
179
|
-
├── quality/ # 품질 체크리스트
|
|
180
|
-
└── standards/ # 코딩 표준
|
|
181
280
|
.vibe/
|
|
182
281
|
├── config.json # 프로젝트 설정
|
|
183
282
|
├── constitution.md # 프로젝트 원칙
|
|
283
|
+
├── setup.sh # 협업자 설치 스크립트
|
|
284
|
+
├── rules/ # 코딩 규칙
|
|
285
|
+
│ ├── core/ # 핵심 원칙
|
|
286
|
+
│ ├── quality/ # 품질 체크리스트
|
|
287
|
+
│ └── languages/ # 언어별 규칙
|
|
184
288
|
├── specs/ # SPEC 문서들
|
|
185
289
|
└── features/ # BDD Feature 파일들
|
|
186
290
|
|
|
187
291
|
MCP 서버 (hi-ai): ✓
|
|
292
|
+
협업자 자동 설치: ✓
|
|
188
293
|
|
|
189
294
|
사용법:
|
|
190
295
|
/vibe.spec "기능명" SPEC 작성 (대화형)
|
|
@@ -232,6 +337,21 @@ Workflow:
|
|
|
232
337
|
`);
|
|
233
338
|
}
|
|
234
339
|
|
|
340
|
+
// 디렉토리 삭제 (재귀)
|
|
341
|
+
function removeDirRecursive(dirPath) {
|
|
342
|
+
if (!fs.existsSync(dirPath)) return;
|
|
343
|
+
|
|
344
|
+
fs.readdirSync(dirPath).forEach(item => {
|
|
345
|
+
const itemPath = path.join(dirPath, item);
|
|
346
|
+
if (fs.statSync(itemPath).isDirectory()) {
|
|
347
|
+
removeDirRecursive(itemPath);
|
|
348
|
+
} else {
|
|
349
|
+
fs.unlinkSync(itemPath);
|
|
350
|
+
}
|
|
351
|
+
});
|
|
352
|
+
fs.rmdirSync(dirPath);
|
|
353
|
+
}
|
|
354
|
+
|
|
235
355
|
// 프로젝트 업데이트
|
|
236
356
|
async function update() {
|
|
237
357
|
try {
|
|
@@ -244,27 +364,40 @@ async function update() {
|
|
|
244
364
|
return;
|
|
245
365
|
}
|
|
246
366
|
|
|
247
|
-
|
|
367
|
+
log('🔄 vibe 업데이트 중...\n');
|
|
368
|
+
|
|
369
|
+
// 마이그레이션: .agent/rules/ → .vibe/rules/
|
|
370
|
+
const oldRulesDir = path.join(projectRoot, '.agent/rules');
|
|
371
|
+
const oldAgentDir = path.join(projectRoot, '.agent');
|
|
372
|
+
if (fs.existsSync(oldRulesDir)) {
|
|
373
|
+
log(' 🔄 마이그레이션: .agent/rules/ → .vibe/rules/\n');
|
|
374
|
+
removeDirRecursive(oldRulesDir);
|
|
375
|
+
// .agent 폴더가 비어있으면 삭제
|
|
376
|
+
if (fs.existsSync(oldAgentDir) && fs.readdirSync(oldAgentDir).length === 0) {
|
|
377
|
+
fs.rmdirSync(oldAgentDir);
|
|
378
|
+
}
|
|
379
|
+
log(' ✅ 기존 .agent/rules/ 폴더 정리 완료\n');
|
|
380
|
+
}
|
|
248
381
|
|
|
249
382
|
// .claude/commands 업데이트
|
|
250
383
|
const commandsDir = path.join(claudeDir, 'commands');
|
|
251
384
|
ensureDir(commandsDir);
|
|
252
385
|
const sourceDir = path.join(__dirname, '../.claude/commands');
|
|
253
386
|
copyDirContents(sourceDir, commandsDir);
|
|
254
|
-
|
|
387
|
+
log(' ✅ 슬래시 커맨드 업데이트 완료 (7개)\n');
|
|
255
388
|
|
|
256
|
-
// .
|
|
257
|
-
const rulesSource = path.join(__dirname, '../.
|
|
258
|
-
const rulesTarget = path.join(
|
|
389
|
+
// .vibe/rules/ 업데이트
|
|
390
|
+
const rulesSource = path.join(__dirname, '../.vibe/rules');
|
|
391
|
+
const rulesTarget = path.join(vibeDir, 'rules');
|
|
259
392
|
copyDirRecursive(rulesSource, rulesTarget);
|
|
260
|
-
|
|
393
|
+
log(' ✅ 코딩 규칙 업데이트 완료 (.vibe/rules/)\n');
|
|
261
394
|
|
|
262
395
|
// .claude/agents/ 업데이트
|
|
263
396
|
const agentsDir = path.join(claudeDir, 'agents');
|
|
264
397
|
ensureDir(agentsDir);
|
|
265
398
|
const agentsSourceDir = path.join(__dirname, '../.claude/agents');
|
|
266
399
|
copyDirContents(agentsSourceDir, agentsDir);
|
|
267
|
-
|
|
400
|
+
log(' ✅ 서브에이전트 업데이트 완료 (.claude/agents/)\n');
|
|
268
401
|
|
|
269
402
|
// settings.local.json에 hooks 병합
|
|
270
403
|
const settingsPath = path.join(claudeDir, 'settings.local.json');
|
|
@@ -280,26 +413,37 @@ async function update() {
|
|
|
280
413
|
if (!existingSettings.hooks) {
|
|
281
414
|
existingSettings.hooks = vibeHooks.hooks;
|
|
282
415
|
fs.writeFileSync(settingsPath, JSON.stringify(existingSettings, null, 2));
|
|
283
|
-
|
|
416
|
+
log(' ✅ Hooks 설정 추가 완료\n');
|
|
284
417
|
} else {
|
|
285
|
-
|
|
418
|
+
log(' ℹ️ Hooks 설정 이미 존재\n');
|
|
286
419
|
}
|
|
287
420
|
} else {
|
|
288
421
|
// 새로 생성
|
|
289
422
|
fs.copyFileSync(hooksTemplate, settingsPath);
|
|
290
|
-
|
|
423
|
+
log(' ✅ Hooks 설정 생성 완료\n');
|
|
291
424
|
}
|
|
292
425
|
}
|
|
293
426
|
|
|
427
|
+
// MCP 서버 등록 확인
|
|
428
|
+
const mcpPath = path.join(__dirname, '..', 'node_modules', '@su-record', 'hi-ai', 'dist', 'index.js');
|
|
429
|
+
const { execSync } = require('child_process');
|
|
430
|
+
try {
|
|
431
|
+
execSync(`claude mcp add vibe node "${mcpPath}"`, { stdio: 'pipe' });
|
|
432
|
+
log(' ✅ MCP 서버 등록 완료\n');
|
|
433
|
+
} catch (e) {
|
|
434
|
+
// 이미 등록됨 - silent
|
|
435
|
+
}
|
|
436
|
+
|
|
294
437
|
const packageJson = require('../package.json');
|
|
295
|
-
|
|
438
|
+
log(`
|
|
296
439
|
✅ vibe 업데이트 완료! (v${packageJson.version})
|
|
297
440
|
|
|
298
441
|
업데이트된 항목:
|
|
299
442
|
- 슬래시 커맨드 (7개)
|
|
300
|
-
- 코딩 규칙 (.
|
|
443
|
+
- 코딩 규칙 (.vibe/rules/)
|
|
301
444
|
- 서브에이전트 (.claude/agents/)
|
|
302
445
|
- Hooks 설정
|
|
446
|
+
- MCP 서버
|
|
303
447
|
`);
|
|
304
448
|
|
|
305
449
|
} catch (error) {
|
package/package.json
CHANGED
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
# 💬 커뮤니케이션 가이드
|
|
2
|
-
|
|
3
|
-
## ⚠️ 최우선 규칙: 한국어로 응답
|
|
4
|
-
|
|
5
|
-
**모든 대화, 설명, 주석은 한국어로 작성합니다.**
|
|
6
|
-
|
|
7
|
-
- ✅ AI 응답: 한국어
|
|
8
|
-
- ✅ 코드 주석: 한국어
|
|
9
|
-
- ✅ 문서: 한국어
|
|
10
|
-
- ✅ 에러 메시지: 한국어
|
|
11
|
-
- ⚠️ 예외: 코드 자체 (함수명, 변수명 등)는 영어
|
|
12
|
-
|
|
13
|
-
## 3.1 코드 제공 형식
|
|
14
|
-
|
|
15
|
-
```markdown
|
|
16
|
-
### 작업 범위
|
|
17
|
-
|
|
18
|
-
"요청하신 대로 UserProfile 컴포넌트의 상태 관리 로직만 수정했습니다."
|
|
19
|
-
|
|
20
|
-
### 변경 사항 요약
|
|
21
|
-
|
|
22
|
-
주문 상태 업데이트 로직 개선 - Optimistic updates 적용
|
|
23
|
-
|
|
24
|
-
### 코드
|
|
25
|
-
|
|
26
|
-
[완전한 코드 블록]
|
|
27
|
-
|
|
28
|
-
### 참고사항
|
|
29
|
-
|
|
30
|
-
- 에러 발생 시 자동 롤백
|
|
31
|
-
- 네트워크 재시도 3회
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
## 3.2 리뷰 응답 형식
|
|
35
|
-
|
|
36
|
-
```markdown
|
|
37
|
-
### 개선점
|
|
38
|
-
|
|
39
|
-
1. memoization 누락 (성능)
|
|
40
|
-
2. error boundary 미적용 (안정성)
|
|
41
|
-
|
|
42
|
-
### 권장사항
|
|
43
|
-
|
|
44
|
-
useMemo 적용 및 ErrorBoundary로 감싸기
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
## 3.3 에러 보고 형식
|
|
48
|
-
|
|
49
|
-
```markdown
|
|
50
|
-
### 문제
|
|
51
|
-
|
|
52
|
-
[발생한 문제 명확히 설명]
|
|
53
|
-
|
|
54
|
-
### 원인
|
|
55
|
-
|
|
56
|
-
[분석된 원인]
|
|
57
|
-
|
|
58
|
-
### 해결 방법
|
|
59
|
-
|
|
60
|
-
[구체적인 해결 단계]
|
|
61
|
-
|
|
62
|
-
### 예방책
|
|
63
|
-
|
|
64
|
-
[향후 방지 방법]
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
## 3.4 변경사항 설명 원칙
|
|
68
|
-
|
|
69
|
-
- **명확성**: 무엇을 왜 변경했는지 명확히
|
|
70
|
-
- **간결성**: 핵심만 전달
|
|
71
|
-
- **완전성**: 부작용과 주의사항 포함
|
|
72
|
-
- **추적성**: 관련 이슈/요청 참조
|
|
73
|
-
|
|
74
|
-
## 3.5 특수 명령어 실행
|
|
75
|
-
|
|
76
|
-
- **"optimize"**: 성능 개선 (memoization, 번들 크기 등)
|
|
77
|
-
- **"enhance accessibility"**: ARIA, 키보드 지원 등 추가
|
|
78
|
-
- **"strengthen types"**: any 제거, 타입 안전성 향상
|
|
79
|
-
- **"cleanup"**: 불필요한 코드 제거 (요청 시에만)
|
|
80
|
-
- **"split"**: 컴포넌트/함수 분리 (요청 시에만)
|
|
81
|
-
|
|
82
|
-
## 3.6 질문 형식
|
|
83
|
-
|
|
84
|
-
### 명확성이 필요할 때
|
|
85
|
-
|
|
86
|
-
```markdown
|
|
87
|
-
다음 사항을 확인해주세요:
|
|
88
|
-
|
|
89
|
-
1. [구체적인 질문 1]
|
|
90
|
-
2. [구체적인 질문 2]
|
|
91
|
-
|
|
92
|
-
이 정보가 있으면 더 정확한 구현이 가능합니다.
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
### 대안 제시
|
|
96
|
-
|
|
97
|
-
```markdown
|
|
98
|
-
요청하신 방법 외에 다음 대안도 가능합니다:
|
|
99
|
-
|
|
100
|
-
**방법 A**: [설명] - 장점: [장점], 단점: [단점]
|
|
101
|
-
**방법 B**: [설명] - 장점: [장점], 단점: [단점]
|
|
102
|
-
|
|
103
|
-
어떤 방식을 선호하시나요?
|
|
104
|
-
```
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
# 🏛️ 개발 철학과 원칙 - "왜"에 대한 답
|
|
2
|
-
|
|
3
|
-
## 1.1 🥇 최우선 순위: 수술적 정밀도
|
|
4
|
-
|
|
5
|
-
> **⚠️ 이것은 모든 작업에 앞서는 TORY의 첫 번째 원칙입니다.**
|
|
6
|
-
>
|
|
7
|
-
> **요청받지 않은 코드는 절대 수정/삭제하지 않습니다.**
|
|
8
|
-
|
|
9
|
-
### 원칙
|
|
10
|
-
|
|
11
|
-
- **엄격한 범위 준수**: 사용자가 명시적으로 요청한 파일과 코드 블록만 수정
|
|
12
|
-
- **기존 코드 보존**: 작동하는 코드를 임의로 리팩토링하거나 제거하지 않음
|
|
13
|
-
- **스타일 존중**: 기존 네이밍, 포맷팅, 주석 스타일 유지
|
|
14
|
-
|
|
15
|
-
## 1.2 핵심 철학
|
|
16
|
-
|
|
17
|
-
### 🎯 개발의 황금률
|
|
18
|
-
|
|
19
|
-
- **한국어 우선**: 모든 커뮤니케이션은 명확한 한국어로
|
|
20
|
-
- **단순함의 미학**: 코드가 적을수록 좋은 코드
|
|
21
|
-
- **DRY 원칙**: 반복하지 말고 재사용
|
|
22
|
-
- **단일 책임**: 하나의 함수는 하나의 목적만
|
|
23
|
-
- **실용주의**: 완벽보다 실용, YAGNI 정신
|
|
24
|
-
|
|
25
|
-
### 🎨 코드 품질 기준
|
|
26
|
-
|
|
27
|
-
- **가독성**: 코드는 사람을 위한 것
|
|
28
|
-
- **예측 가능성**: 코드에서 놀라움은 금물
|
|
29
|
-
- **유지보수성**: 미래의 나를 배려
|
|
30
|
-
- **테스트 가능성**: 검증 가능한 구조
|
|
31
|
-
|
|
32
|
-
## 1.3 아키텍처 원칙
|
|
33
|
-
|
|
34
|
-
### 🏗️ 설계의 지혜
|
|
35
|
-
|
|
36
|
-
- **패턴의 적절한 적용**: Composite, Observer, Factory 등 필요에 따라 적용
|
|
37
|
-
- **과도한 추상화 지양**: 3단계 이상의 wrapper 금지
|
|
38
|
-
- **순환 의존성 방지**: File A → File B → File A ❌
|
|
39
|
-
|
|
40
|
-
### ♿ 접근성은 선택이 아닌 필수
|
|
41
|
-
|
|
42
|
-
- Semantic HTML을 기본으로
|
|
43
|
-
- 키보드 내비게이션 지원
|
|
44
|
-
- 스크린 리더 최적화
|
|
45
|
-
- ARIA 속성 적극 활용
|
|
46
|
-
|
|
47
|
-
## 핵심 가치
|
|
48
|
-
|
|
49
|
-
1. **명확성**: 코드는 자기 설명적이어야 함
|
|
50
|
-
2. **간결성**: 불필요한 복잡도 제거
|
|
51
|
-
3. **일관성**: 일관된 패턴과 스타일 유지
|
|
52
|
-
4. **확장성**: 미래의 변화를 고려한 설계
|
|
53
|
-
5. **안전성**: 오류 처리와 엣지 케이스 고려
|