sleepcode 1.2.0 → 1.4.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.local.json +2 -1
- package/README.md +37 -17
- package/bin/index.js +242 -28
- package/package.json +1 -1
- package/templates/common/README.md +6 -16
- package/templates/common/ai_worker.ps1 +2 -1
- package/templates/common/ai_worker.sh +6 -1
- package/templates/common/base_rules.md +39 -0
- package/templates/common/run_forever.ps1 +3 -2
- package/templates/common/run_forever.sh +7 -2
- package/templates/rules/custom.md +0 -41
- package/templates/rules/nextjs.md +0 -41
- package/templates/rules/react-native.md +0 -41
- package/templates/rules/spring-boot.md +0 -41
|
@@ -11,7 +11,8 @@
|
|
|
11
11
|
"Bash(npm publish)",
|
|
12
12
|
"Bash(npm version:*)",
|
|
13
13
|
"Bash(NPM_TOKEN=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 npm publish:*)",
|
|
14
|
-
"Bash(NPM_TOKEN=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 npm publish)"
|
|
14
|
+
"Bash(NPM_TOKEN=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 npm publish)",
|
|
15
|
+
"Bash(git push:*)"
|
|
15
16
|
]
|
|
16
17
|
}
|
|
17
18
|
}
|
package/README.md
CHANGED
|
@@ -31,7 +31,22 @@ npx sleepcode
|
|
|
31
31
|
|
|
32
32
|
인터랙티브 모드로 프로젝트 타입, 이름, AI 역할 등을 설정합니다.
|
|
33
33
|
|
|
34
|
-
### 2.
|
|
34
|
+
### 2. 참고 자료 추가
|
|
35
|
+
|
|
36
|
+
`.sleepcode/docs/`에 기획서, 피그마 스크린샷 등 참고 자료를 넣습니다.
|
|
37
|
+
|
|
38
|
+
### 3. 태스크 작성
|
|
39
|
+
|
|
40
|
+
**방법 A: 자동 생성 (추천)**
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
npx sleepcode generate
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
참고 자료(docs/, Figma, Notion)와 프로젝트 구조를 분석해서 `tasks.md`를 자동 생성합니다.
|
|
47
|
+
이미 구현된 기능은 제외됩니다.
|
|
48
|
+
|
|
49
|
+
**방법 B: 직접 작성**
|
|
35
50
|
|
|
36
51
|
`.sleepcode/tasks.md` 에 AI가 수행할 작업을 작성합니다:
|
|
37
52
|
|
|
@@ -43,27 +58,19 @@ npx sleepcode
|
|
|
43
58
|
- [ ] 홈 화면 UI 개선
|
|
44
59
|
```
|
|
45
60
|
|
|
46
|
-
###
|
|
61
|
+
### 4. 실행
|
|
47
62
|
|
|
48
|
-
**macOS / Linux:**
|
|
49
63
|
```bash
|
|
50
64
|
# 1회 실행
|
|
51
|
-
|
|
65
|
+
npx sleepcode run
|
|
52
66
|
|
|
53
|
-
# 무한 루프 (
|
|
54
|
-
|
|
67
|
+
# 무한 루프 (잠자기 전)
|
|
68
|
+
npx sleepcode run --loop
|
|
55
69
|
```
|
|
56
70
|
|
|
57
|
-
|
|
58
|
-
```powershell
|
|
59
|
-
# 1회 실행
|
|
60
|
-
powershell -File .\.sleepcode\scripts\ai_worker.ps1
|
|
61
|
-
|
|
62
|
-
# 무한 루프
|
|
63
|
-
powershell -File .\.sleepcode\scripts\run_forever.ps1
|
|
64
|
-
```
|
|
71
|
+
OS에 맞는 스크립트를 자동으로 선택합니다 (macOS/Linux: `.sh`, Windows: `.ps1`).
|
|
65
72
|
|
|
66
|
-
###
|
|
73
|
+
### 5. 아침에 확인
|
|
67
74
|
|
|
68
75
|
```bash
|
|
69
76
|
git log --oneline --since="12 hours ago"
|
|
@@ -82,6 +89,15 @@ git log --oneline --since="12 hours ago"
|
|
|
82
89
|
|
|
83
90
|
---
|
|
84
91
|
|
|
92
|
+
## CLI 명령어
|
|
93
|
+
|
|
94
|
+
| 명령어 | 설명 |
|
|
95
|
+
|--------|------|
|
|
96
|
+
| `npx sleepcode` | 인터랙티브 초기화 |
|
|
97
|
+
| `npx sleepcode run` | 1회 실행 |
|
|
98
|
+
| `npx sleepcode run --loop` | 무한 루프 실행 |
|
|
99
|
+
| `npx sleepcode generate` | 참고자료 기반 tasks.md 자동 생성 |
|
|
100
|
+
|
|
85
101
|
## CLI 옵션
|
|
86
102
|
|
|
87
103
|
인터랙티브 모드 외에 CLI 인자로도 사용 가능합니다:
|
|
@@ -96,6 +112,9 @@ npx sleepcode --type react-native --name my-app --role "쇼핑몰 앱 개발"
|
|
|
96
112
|
| `--name <name>` | 프로젝트 이름 |
|
|
97
113
|
| `--role <desc>` | AI 역할 설명 |
|
|
98
114
|
| `--figma-key <key>` | Figma API Key (선택) |
|
|
115
|
+
| `--figma-file <name>` | Figma 참고 파일명 (선택) |
|
|
116
|
+
| `--notion-key <key>` | Notion API Key (선택) |
|
|
117
|
+
| `--notion-page <name>` | Notion 참고 페이지명 (선택) |
|
|
99
118
|
| `--interval <sec>` | 반복 간격 초 (기본: 30) |
|
|
100
119
|
| `-f, --force` | 기존 `.sleepcode/` 폴더 덮어쓰기 |
|
|
101
120
|
| `-h, --help` | 도움말 |
|
|
@@ -109,7 +128,8 @@ npx sleepcode --type react-native --name my-app --role "쇼핑몰 앱 개발"
|
|
|
109
128
|
rules.md # ✏️ AI 역할 + 작업 규칙 (수정하세요)
|
|
110
129
|
tasks.md # ✏️ 작업 목록 (수정하세요)
|
|
111
130
|
docs/ # ✏️ 참고 자료 (피그마 스크린샷, 기획서 등)
|
|
112
|
-
scripts/ # ⚙️ 시스템
|
|
131
|
+
scripts/ # ⚙️ 시스템 (수정하지 마세요)
|
|
132
|
+
base_rules.md # 공통 작업 규칙
|
|
113
133
|
ai_worker.sh/.ps1 # 1회 실행 스크립트 (OS별)
|
|
114
134
|
run_forever.sh/.ps1 # 무한 루프 스크립트 (OS별)
|
|
115
135
|
log_filter.py # 실시간 로그 필터
|
|
@@ -153,7 +173,7 @@ rules.md + tasks.md → 프롬프트 조합 → claude -p (비대화형) → 코
|
|
|
153
173
|
|
|
154
174
|
| 동작 | 명령어 |
|
|
155
175
|
|------|--------|
|
|
156
|
-
| 세션 생성 + 실행 | `tmux new -s ai '
|
|
176
|
+
| 세션 생성 + 실행 | `tmux new -s ai 'npx sleepcode run --loop'` |
|
|
157
177
|
| 백그라운드 전환 | `Ctrl+B` → `D` |
|
|
158
178
|
| 세션 재접속 | `tmux attach -t ai` |
|
|
159
179
|
| 실시간 로그 | `tail -f .sleepcode/logs/worker_*.log` |
|
package/bin/index.js
CHANGED
|
@@ -190,19 +190,32 @@ function parseArgs() {
|
|
|
190
190
|
else if (args[i] === '--name' && args[i + 1]) parsed.name = args[++i];
|
|
191
191
|
else if (args[i] === '--role' && args[i + 1]) parsed.role = args[++i];
|
|
192
192
|
else if (args[i] === '--figma-key' && args[i + 1]) parsed.figmaKey = args[++i];
|
|
193
|
+
else if (args[i] === '--figma-file' && args[i + 1]) parsed.figmaFileNames = args[++i];
|
|
194
|
+
else if (args[i] === '--notion-key' && args[i + 1]) parsed.notionKey = args[++i];
|
|
195
|
+
else if (args[i] === '--notion-page' && args[i + 1]) parsed.notionPages = args[++i];
|
|
193
196
|
else if (args[i] === '--interval' && args[i + 1]) parsed.interval = args[++i];
|
|
194
197
|
else if (args[i] === '--force' || args[i] === '-f') parsed.force = true;
|
|
195
198
|
else if (args[i] === '--help' || args[i] === '-h') {
|
|
196
199
|
console.log(`
|
|
197
200
|
사용법: sleepcode [옵션]
|
|
201
|
+
sleepcode run [--loop]
|
|
202
|
+
sleepcode generate
|
|
198
203
|
|
|
199
204
|
옵션 없이 실행하면 인터랙티브 모드로 동작합니다.
|
|
200
205
|
|
|
206
|
+
명령어:
|
|
207
|
+
run 1회 실행 (ai_worker 스크립트)
|
|
208
|
+
run --loop 무한 루프 실행 (run_forever 스크립트)
|
|
209
|
+
generate 참고자료 기반으로 tasks.md 자동 생성
|
|
210
|
+
|
|
201
211
|
옵션:
|
|
202
212
|
--type <type> 프로젝트 타입 (spring-boot, react-native, nextjs, custom)
|
|
203
213
|
--name <name> 프로젝트 이름
|
|
204
214
|
--role <desc> AI 역할 설명
|
|
205
215
|
--figma-key <key> Figma API Key
|
|
216
|
+
--figma-file <name> Figma 참고 파일명
|
|
217
|
+
--notion-key <key> Notion API Key
|
|
218
|
+
--notion-page <name> Notion 참고 페이지명
|
|
206
219
|
--interval <sec> 반복 간격 (초, 기본 30)
|
|
207
220
|
-f, --force 기존 .sleepcode/ 덮어쓰기
|
|
208
221
|
-h, --help 도움말
|
|
@@ -246,7 +259,7 @@ function writeFile(filePath, content) {
|
|
|
246
259
|
fs.writeFileSync(filePath, content);
|
|
247
260
|
}
|
|
248
261
|
|
|
249
|
-
function generateFiles(targetDir, { typeKey, projectName, role, buildCmd, testCmd, lintCmd, figmaKey, sleepInterval }) {
|
|
262
|
+
function generateFiles(targetDir, { typeKey, projectName, role, buildCmd, testCmd, lintCmd, figmaKey, figmaFileNames, notionKey, notionPages, sleepInterval }) {
|
|
250
263
|
const scDir = path.join(targetDir, '.sleepcode');
|
|
251
264
|
const claudeDir = path.join(targetDir, '.claude');
|
|
252
265
|
fs.mkdirSync(path.join(scDir, 'docs'), { recursive: true });
|
|
@@ -270,6 +283,36 @@ function generateFiles(targetDir, { typeKey, projectName, role, buildCmd, testCm
|
|
|
270
283
|
}
|
|
271
284
|
}
|
|
272
285
|
|
|
286
|
+
// base_rules.md → scripts/ 하위로 복사 (Figma/Notion 섹션 조건부 처리)
|
|
287
|
+
const baseRulesSrc = path.join(TEMPLATES_DIR, 'common', 'base_rules.md');
|
|
288
|
+
if (fs.existsSync(baseRulesSrc)) {
|
|
289
|
+
let baseRules = fs.readFileSync(baseRulesSrc, 'utf-8');
|
|
290
|
+
|
|
291
|
+
// Figma 섹션
|
|
292
|
+
if (figmaKey) {
|
|
293
|
+
let figmaSection = `## Figma\n\n- **프론트엔드 디자인**: Figma MCP 도구로 직접 조회 가능 (API Key: \`${figmaKey}\`)`;
|
|
294
|
+
if (figmaFileNames) {
|
|
295
|
+
figmaSection += `\n- **참고 파일**: ${figmaFileNames}`;
|
|
296
|
+
}
|
|
297
|
+
baseRules = baseRules.replace('{{FIGMA_SECTION}}', figmaSection);
|
|
298
|
+
} else {
|
|
299
|
+
baseRules = baseRules.replace('\n{{FIGMA_SECTION}}\n', '');
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// Notion 섹션
|
|
303
|
+
if (notionKey) {
|
|
304
|
+
let notionSection = `\n## Notion\n\n- **기획/문서**: Notion MCP 도구로 직접 조회 가능 (API Key: \`${notionKey}\`)`;
|
|
305
|
+
if (notionPages) {
|
|
306
|
+
notionSection += `\n- **참고 페이지**: ${notionPages}`;
|
|
307
|
+
}
|
|
308
|
+
baseRules = baseRules.replace('{{NOTION_SECTION}}', notionSection);
|
|
309
|
+
} else {
|
|
310
|
+
baseRules = baseRules.replace('\n{{NOTION_SECTION}}\n', '');
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
fs.writeFileSync(path.join(scDir, 'scripts', 'base_rules.md'), baseRules);
|
|
314
|
+
}
|
|
315
|
+
|
|
273
316
|
// README.md → .sleepcode/ 루트에 복사
|
|
274
317
|
const readmeSrc = path.join(TEMPLATES_DIR, 'common', 'README.md');
|
|
275
318
|
if (fs.existsSync(readmeSrc)) {
|
|
@@ -308,12 +351,6 @@ function generateFiles(targetDir, { typeKey, projectName, role, buildCmd, testCm
|
|
|
308
351
|
rules = rules.replace(/\{\{BUILD_CMD\}\}/g, buildCmd);
|
|
309
352
|
rules = rules.replace(/\{\{TEST_CMD\}\}/g, testCmd);
|
|
310
353
|
rules = rules.replace(/\{\{LINT_CMD\}\}/g, lintCmd);
|
|
311
|
-
rules = rules.replace(/\{\{FIGMA_API_KEY\}\}/g, figmaKey);
|
|
312
|
-
|
|
313
|
-
if (!figmaKey) {
|
|
314
|
-
rules = rules.replace(/\n## Figma[\s\S]*?(?=\n## |$)/, '');
|
|
315
|
-
}
|
|
316
|
-
|
|
317
354
|
writeFile(path.join(scDir, 'rules.md'), rules);
|
|
318
355
|
}
|
|
319
356
|
|
|
@@ -342,44 +379,195 @@ function printResult() {
|
|
|
342
379
|
console.log(` ${C.green}✓${C.reset} .sleepcode/rules.md ${C.dim}← 수정하세요${C.reset}`);
|
|
343
380
|
console.log(` ${C.green}✓${C.reset} .sleepcode/tasks.md ${C.dim}← 수정하세요${C.reset}`);
|
|
344
381
|
console.log(` ${C.green}✓${C.reset} .sleepcode/docs/ ${C.dim}← 참고자료 추가${C.reset}`);
|
|
382
|
+
console.log(` ${C.green}✓${C.reset} .sleepcode/scripts/base_rules.md`);
|
|
345
383
|
console.log(` ${C.green}✓${C.reset} .sleepcode/scripts/${workerScript}`);
|
|
346
384
|
console.log(` ${C.green}✓${C.reset} .sleepcode/scripts/${foreverScript}`);
|
|
347
385
|
console.log(` ${C.green}✓${C.reset} .sleepcode/scripts/log_filter.py`);
|
|
348
386
|
console.log(` ${C.green}✓${C.reset} .sleepcode/README.md`);
|
|
349
387
|
console.log(` ${C.green}✓${C.reset} .claude/settings.local.json`);
|
|
350
388
|
|
|
351
|
-
|
|
352
|
-
console.log(`
|
|
389
|
+
console.log(`
|
|
353
390
|
${C.bold}${C.green}완료!${C.reset} 다음 단계:
|
|
354
391
|
|
|
355
392
|
${C.bold}1.${C.reset} .sleepcode/rules.md 를 프로젝트에 맞게 수정
|
|
356
|
-
${C.bold}2.${C.reset} .sleepcode/
|
|
357
|
-
${C.bold}3.${C.reset}
|
|
358
|
-
${C.dim}#
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
${C.dim}#
|
|
362
|
-
|
|
393
|
+
${C.bold}2.${C.reset} .sleepcode/docs/ 에 참고 자료 추가 (기획서, 스크린샷 등)
|
|
394
|
+
${C.bold}3.${C.reset} 태스크 생성:
|
|
395
|
+
${C.cyan}npx sleepcode generate${C.reset} ${C.dim}# 참고자료 기반 tasks.md 자동 생성${C.reset}
|
|
396
|
+
${C.dim}또는 .sleepcode/tasks.md 를 직접 작성${C.reset}
|
|
397
|
+
${C.bold}4.${C.reset} 실행:
|
|
398
|
+
${C.cyan}npx sleepcode run${C.reset} ${C.dim}# 1회 실행${C.reset}
|
|
399
|
+
${C.cyan}npx sleepcode run --loop${C.reset} ${C.dim}# 무한 루프${C.reset}
|
|
363
400
|
`);
|
|
364
|
-
|
|
365
|
-
console.log(`
|
|
366
|
-
${C.bold}${C.green}완료!${C.reset} 다음 단계:
|
|
401
|
+
}
|
|
367
402
|
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
./.sleepcode/scripts/ai_worker.sh
|
|
403
|
+
// ─── 실행 명령어 ───
|
|
404
|
+
function runWorker(loop) {
|
|
405
|
+
const targetDir = process.cwd();
|
|
406
|
+
const scDir = path.join(targetDir, '.sleepcode', 'scripts');
|
|
373
407
|
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
408
|
+
if (!fs.existsSync(scDir)) {
|
|
409
|
+
console.error(`${C.red}.sleepcode/scripts/ 폴더가 없습니다. 먼저 'npx sleepcode'로 초기화하세요.${C.reset}`);
|
|
410
|
+
process.exit(1);
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
const scriptName = loop
|
|
414
|
+
? (IS_WIN ? 'run_forever.ps1' : 'run_forever.sh')
|
|
415
|
+
: (IS_WIN ? 'ai_worker.ps1' : 'ai_worker.sh');
|
|
416
|
+
const scriptPath = path.join(scDir, scriptName);
|
|
417
|
+
|
|
418
|
+
if (!fs.existsSync(scriptPath)) {
|
|
419
|
+
console.error(`${C.red}스크립트를 찾을 수 없습니다: ${scriptPath}${C.reset}`);
|
|
420
|
+
process.exit(1);
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
const cmd = IS_WIN
|
|
424
|
+
? `powershell -File "${scriptPath}"`
|
|
425
|
+
: `"${scriptPath}"`;
|
|
426
|
+
|
|
427
|
+
console.log(`${C.cyan}${loop ? '무한 루프' : '1회'} 실행: ${scriptName}${C.reset}\n`);
|
|
428
|
+
|
|
429
|
+
try {
|
|
430
|
+
execSync(cmd, { stdio: 'inherit', cwd: targetDir });
|
|
431
|
+
} catch (e) {
|
|
432
|
+
process.exit(e.status || 1);
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
// ─── 태스크 자동 생성 ───
|
|
437
|
+
function generateTasks() {
|
|
438
|
+
const targetDir = process.cwd();
|
|
439
|
+
const scDir = path.join(targetDir, '.sleepcode');
|
|
440
|
+
|
|
441
|
+
if (!fs.existsSync(scDir)) {
|
|
442
|
+
console.error(`${C.red}.sleepcode/ 폴더가 없습니다. 먼저 'npx sleepcode'로 초기화하세요.${C.reset}`);
|
|
443
|
+
process.exit(1);
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
// claude CLI 확인
|
|
447
|
+
if (!checkCommand('claude --version')) {
|
|
448
|
+
console.error(`${C.red}claude CLI가 설치되어 있지 않습니다.${C.reset}`);
|
|
449
|
+
process.exit(1);
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
console.log(`${C.cyan}태스크 자동 생성 중...${C.reset}\n`);
|
|
453
|
+
|
|
454
|
+
// 참고 자료 수집
|
|
455
|
+
const parts = [];
|
|
456
|
+
|
|
457
|
+
// 1. base_rules.md (프로젝트 공통 규칙 — 역할 파악용)
|
|
458
|
+
const baseRulesPath = path.join(scDir, 'scripts', 'base_rules.md');
|
|
459
|
+
if (fs.existsSync(baseRulesPath)) {
|
|
460
|
+
parts.push(fs.readFileSync(baseRulesPath, 'utf-8'));
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
// 2. rules.md (프로젝트별 역할/작업방식)
|
|
464
|
+
const rulesPath = path.join(scDir, 'rules.md');
|
|
465
|
+
if (fs.existsSync(rulesPath)) {
|
|
466
|
+
parts.push(fs.readFileSync(rulesPath, 'utf-8'));
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
// 3. docs/ 디렉토리 파일 목록 + 내용
|
|
470
|
+
const docsDir = path.join(scDir, 'docs');
|
|
471
|
+
if (fs.existsSync(docsDir)) {
|
|
472
|
+
const files = fs.readdirSync(docsDir).filter(f => f !== '.gitkeep');
|
|
473
|
+
for (const file of files) {
|
|
474
|
+
const filePath = path.join(docsDir, file);
|
|
475
|
+
const stat = fs.statSync(filePath);
|
|
476
|
+
if (stat.isFile() && stat.size < 100000) {
|
|
477
|
+
// 텍스트 파일만 읽기 (이미지 등은 파일명만)
|
|
478
|
+
const ext = path.extname(file).toLowerCase();
|
|
479
|
+
if (['.md', '.txt', '.json', '.yaml', '.yml', '.csv', '.html'].includes(ext)) {
|
|
480
|
+
parts.push(`--- docs/${file} ---\n${fs.readFileSync(filePath, 'utf-8')}`);
|
|
481
|
+
} else {
|
|
482
|
+
parts.push(`--- docs/${file} --- (파일 존재, 내용은 직접 참고)`);
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
// 4. 현재 프로젝트 구조 (이미 구현된 것 파악용)
|
|
489
|
+
try {
|
|
490
|
+
const tree = execSync('git ls-files', { cwd: targetDir, stdio: ['pipe', 'pipe', 'pipe'], timeout: 10000 })
|
|
491
|
+
.toString().trim();
|
|
492
|
+
if (tree) {
|
|
493
|
+
parts.push(`--- 현재 프로젝트 파일 목록 (이미 구현됨) ---\n${tree}`);
|
|
494
|
+
}
|
|
495
|
+
} catch {
|
|
496
|
+
// git이 없거나 실패하면 무시
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
// 5. 기존 tasks.md (있으면 참고)
|
|
500
|
+
const tasksPath = path.join(scDir, 'tasks.md');
|
|
501
|
+
if (fs.existsSync(tasksPath)) {
|
|
502
|
+
const existing = fs.readFileSync(tasksPath, 'utf-8');
|
|
503
|
+
if (existing.includes('[ ]') || existing.includes('[x]')) {
|
|
504
|
+
parts.push(`--- 기존 tasks.md ---\n${existing}`);
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
// 프롬프트 구성
|
|
509
|
+
const context = parts.join('\n\n---\n\n');
|
|
510
|
+
const prompt = `${context}
|
|
511
|
+
|
|
512
|
+
---
|
|
513
|
+
|
|
514
|
+
위 프로젝트 정보와 참고 자료를 바탕으로 .sleepcode/tasks.md 파일을 생성해주세요.
|
|
515
|
+
|
|
516
|
+
규칙:
|
|
517
|
+
- 마크다운 체크리스트 형식으로 작성: \`- [ ] 태스크 내용\`
|
|
518
|
+
- 구체적이고 실행 가능한 단위로 태스크를 나눌 것
|
|
519
|
+
- 태스크 순서는 의존성을 고려하여 배치
|
|
520
|
+
- Figma 디자인이 있으면 UI 구현 태스크도 포함
|
|
521
|
+
- Notion 문서가 있으면 기획 내용을 반영
|
|
522
|
+
- docs/ 폴더의 참고 자료를 반영
|
|
523
|
+
- **이미 프로젝트에 구현되어 있는 기능은 태스크에 포함하지 않는다**
|
|
524
|
+
- 현재 프로젝트 파일 목록을 분석하여 아직 구현되지 않은 것만 태스크로 작성
|
|
525
|
+
- 첫 줄은 \`# 작업 목록\` 으로 시작
|
|
526
|
+
- 태스크 목록 앞에 간단한 안내 문구 포함
|
|
527
|
+
|
|
528
|
+
tasks.md 내용만 출력하세요. 다른 설명은 하지 마세요.`;
|
|
529
|
+
|
|
530
|
+
try {
|
|
531
|
+
const result = execSync(
|
|
532
|
+
'claude -p --output-format text',
|
|
533
|
+
{
|
|
534
|
+
input: prompt,
|
|
535
|
+
cwd: targetDir,
|
|
536
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
537
|
+
timeout: 300000,
|
|
538
|
+
maxBuffer: 1024 * 1024,
|
|
539
|
+
}
|
|
540
|
+
).toString().trim();
|
|
541
|
+
|
|
542
|
+
// tasks.md에 저장
|
|
543
|
+
fs.writeFileSync(tasksPath, result + '\n');
|
|
544
|
+
console.log(`${C.green}✓${C.reset} .sleepcode/tasks.md 생성 완료\n`);
|
|
545
|
+
console.log(`${C.dim}${result}${C.reset}\n`);
|
|
546
|
+
console.log(`필요하면 tasks.md를 직접 수정한 뒤 실행하세요:`);
|
|
547
|
+
console.log(` ${C.cyan}npx sleepcode run${C.reset} ${C.dim}# 1회 실행${C.reset}`);
|
|
548
|
+
console.log(` ${C.cyan}npx sleepcode run --loop${C.reset} ${C.dim}# 무한 루프${C.reset}`);
|
|
549
|
+
} catch (e) {
|
|
550
|
+
console.error(`${C.red}태스크 생성 실패: ${e.message}${C.reset}`);
|
|
551
|
+
process.exit(1);
|
|
377
552
|
}
|
|
378
553
|
}
|
|
379
554
|
|
|
380
555
|
// ─── 메인 ───
|
|
381
556
|
async function main() {
|
|
382
557
|
const targetDir = process.cwd();
|
|
558
|
+
|
|
559
|
+
// 서브커맨드 처리
|
|
560
|
+
const firstArg = process.argv[2];
|
|
561
|
+
if (firstArg === 'run') {
|
|
562
|
+
const loop = process.argv.includes('--loop');
|
|
563
|
+
runWorker(loop);
|
|
564
|
+
return;
|
|
565
|
+
}
|
|
566
|
+
if (firstArg === 'generate') {
|
|
567
|
+
generateTasks();
|
|
568
|
+
return;
|
|
569
|
+
}
|
|
570
|
+
|
|
383
571
|
const cliArgs = parseArgs();
|
|
384
572
|
|
|
385
573
|
console.log(`
|
|
@@ -410,6 +598,9 @@ ${C.bold}${C.magenta} ╔══════════════════
|
|
|
410
598
|
const projectName = cliArgs.name || path.basename(targetDir);
|
|
411
599
|
const role = cliArgs.role || `${projectName} 서비스 개발`;
|
|
412
600
|
const figmaKey = cliArgs.figmaKey || '';
|
|
601
|
+
const figmaFileNames = cliArgs.figmaFileNames || '';
|
|
602
|
+
const notionKey = cliArgs.notionKey || '';
|
|
603
|
+
const notionPages = cliArgs.notionPages || '';
|
|
413
604
|
const sleepInterval = cliArgs.interval || '30';
|
|
414
605
|
|
|
415
606
|
console.log(`${C.dim}타입: ${typeConfig.label}${C.reset}`);
|
|
@@ -424,6 +615,9 @@ ${C.bold}${C.magenta} ╔══════════════════
|
|
|
424
615
|
testCmd: typeConfig.testCmd,
|
|
425
616
|
lintCmd: typeConfig.lintCmd,
|
|
426
617
|
figmaKey,
|
|
618
|
+
figmaFileNames,
|
|
619
|
+
notionKey,
|
|
620
|
+
notionPages,
|
|
427
621
|
sleepInterval,
|
|
428
622
|
});
|
|
429
623
|
|
|
@@ -476,7 +670,24 @@ ${C.bold}${C.magenta} ╔══════════════════
|
|
|
476
670
|
console.log(`${C.dim} 린트: ${lintCmd || '(없음)'}${C.reset}`);
|
|
477
671
|
}
|
|
478
672
|
|
|
479
|
-
|
|
673
|
+
// Figma 연동
|
|
674
|
+
let figmaKey = '';
|
|
675
|
+
let figmaFileNames = '';
|
|
676
|
+
const useFigma = await ask(rl, 'Figma 디자인을 참고하나요? (y/N)', 'N');
|
|
677
|
+
if (useFigma.toLowerCase() === 'y') {
|
|
678
|
+
figmaKey = await ask(rl, 'Figma API Key', '');
|
|
679
|
+
figmaFileNames = await ask(rl, '참고할 Figma 파일명 (예: 홈화면, 로그인)', '');
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
// Notion 연동
|
|
683
|
+
let notionKey = '';
|
|
684
|
+
let notionPages = '';
|
|
685
|
+
const useNotion = await ask(rl, 'Notion 문서를 참고하나요? (y/N)', 'N');
|
|
686
|
+
if (useNotion.toLowerCase() === 'y') {
|
|
687
|
+
notionKey = await ask(rl, 'Notion API Key', '');
|
|
688
|
+
notionPages = await ask(rl, '참고할 Notion 페이지명 (예: 기획서, API명세)', '');
|
|
689
|
+
}
|
|
690
|
+
|
|
480
691
|
const sleepInterval = await ask(rl, '반복 간격 (초)', '30');
|
|
481
692
|
|
|
482
693
|
rl.close();
|
|
@@ -489,6 +700,9 @@ ${C.bold}${C.magenta} ╔══════════════════
|
|
|
489
700
|
testCmd,
|
|
490
701
|
lintCmd,
|
|
491
702
|
figmaKey,
|
|
703
|
+
figmaFileNames,
|
|
704
|
+
notionKey,
|
|
705
|
+
notionPages,
|
|
492
706
|
sleepInterval,
|
|
493
707
|
});
|
|
494
708
|
|
package/package.json
CHANGED
|
@@ -11,7 +11,8 @@ AI codes while you sleep — 밤새 개발 작업을 자동화하는 시스템
|
|
|
11
11
|
rules.md # ✏️ AI 역할 + 작업 규칙 (수정하세요)
|
|
12
12
|
tasks.md # ✏️ 오늘 진행할 작업 목록 (수정하세요)
|
|
13
13
|
docs/ # ✏️ 개발 참고 자료 (피그마 스크린샷, 기획서 등)
|
|
14
|
-
scripts/ # ⚙️ 시스템
|
|
14
|
+
scripts/ # ⚙️ 시스템 (수정하지 마세요)
|
|
15
|
+
base_rules.md # 공통 작업 규칙
|
|
15
16
|
ai_worker.* # 1회 실행 스크립트
|
|
16
17
|
run_forever.* # 무한 루프 감시자 스크립트
|
|
17
18
|
log_filter.py # 로그 필터 (핵심 메시지만 추출)
|
|
@@ -41,26 +42,15 @@ claude --dangerously-skip-permissions
|
|
|
41
42
|
|
|
42
43
|
### 2. 실행
|
|
43
44
|
|
|
44
|
-
**macOS / Linux:**
|
|
45
45
|
```bash
|
|
46
|
-
# 권한 부여
|
|
47
|
-
chmod +x .sleepcode/scripts/*.sh
|
|
48
|
-
|
|
49
46
|
# 1회 실행
|
|
50
|
-
|
|
47
|
+
npx sleepcode run
|
|
51
48
|
|
|
52
|
-
# 무한 루프 (
|
|
53
|
-
|
|
49
|
+
# 무한 루프 (잠자기 전)
|
|
50
|
+
npx sleepcode run --loop
|
|
54
51
|
```
|
|
55
52
|
|
|
56
|
-
|
|
57
|
-
```powershell
|
|
58
|
-
# 1회 실행
|
|
59
|
-
powershell -File .\.sleepcode\scripts\ai_worker.ps1
|
|
60
|
-
|
|
61
|
-
# 무한 루프
|
|
62
|
-
powershell -File .\.sleepcode\scripts\run_forever.ps1
|
|
63
|
-
```
|
|
53
|
+
OS에 맞는 스크립트를 자동으로 선택합니다.
|
|
64
54
|
|
|
65
55
|
### 3. tmux 분리 (백그라운드 전환, macOS/Linux)
|
|
66
56
|
|
|
@@ -7,10 +7,11 @@ Set-Location (Split-Path (Split-Path $PSScriptRoot -Parent) -Parent)
|
|
|
7
7
|
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
|
8
8
|
Write-Host "[$timestamp] AI 단일 실행 시작"
|
|
9
9
|
|
|
10
|
+
$baseRules = Get-Content .sleepcode/scripts/base_rules.md -Raw -Encoding UTF8
|
|
10
11
|
$rules = Get-Content .sleepcode/rules.md -Raw -Encoding UTF8
|
|
11
12
|
$tasks = Get-Content .sleepcode/tasks.md -Raw -Encoding UTF8
|
|
12
13
|
|
|
13
|
-
$prompt = "$rules`n`n---`n`n$tasks"
|
|
14
|
+
$prompt = "$baseRules`n`n---`n`n$rules`n`n---`n`n$tasks"
|
|
14
15
|
|
|
15
16
|
# stream-json + verbose: 토큰 단위 실시간 출력
|
|
16
17
|
$prompt | claude -p --dangerously-skip-permissions --output-format stream-json --verbose 2>&1 |
|
|
@@ -7,10 +7,15 @@ cd "$(dirname "$0")/../.." || exit 1
|
|
|
7
7
|
|
|
8
8
|
echo "[$(date '+%Y-%m-%d %H:%M:%S')] AI 단일 실행 시작"
|
|
9
9
|
|
|
10
|
+
BASE_RULES=$(cat .sleepcode/scripts/base_rules.md)
|
|
10
11
|
RULES=$(cat .sleepcode/rules.md)
|
|
11
12
|
TASKS=$(cat .sleepcode/tasks.md)
|
|
12
13
|
|
|
13
|
-
PROMPT="${
|
|
14
|
+
PROMPT="${BASE_RULES}
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
${RULES}
|
|
14
19
|
|
|
15
20
|
---
|
|
16
21
|
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# 공통 작업 규칙
|
|
2
|
+
|
|
3
|
+
## 기본 원칙
|
|
4
|
+
|
|
5
|
+
- 절대로 사용자에게 질문하지 않는다.
|
|
6
|
+
- 작업이 끝났다고 판단하지 않는다.
|
|
7
|
+
- 항상 다음 작업을 스스로 찾는다.
|
|
8
|
+
- 가능한 한 많은 기능을 구현하며 계속 진행한다.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## 참고 자료
|
|
13
|
+
|
|
14
|
+
- `.sleepcode/docs/` 디렉토리에 업로드된 파일 참고 (피그마 스크린샷, 기획서, 참고 이미지 등)
|
|
15
|
+
|
|
16
|
+
{{FIGMA_SECTION}}
|
|
17
|
+
{{NOTION_SECTION}}
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## 태스크 완료 처리
|
|
22
|
+
|
|
23
|
+
- `.sleepcode/tasks.md` 파일에서 작업 목록을 확인한다.
|
|
24
|
+
- 태스크를 **한 항목씩** 순서대로 진행한다.
|
|
25
|
+
- 한 항목을 완료하면 반드시 아래 순서를 따른다:
|
|
26
|
+
1. 해당 항목의 `[ ]`를 `[x]`로 변경한다.
|
|
27
|
+
2. 관련 파일을 모두 `git add` 한다. (tasks.md 포함)
|
|
28
|
+
3. `git commit` 한다. (커밋 메시지에 태스크 내용을 포함)
|
|
29
|
+
4. 그 다음 항목으로 넘어간다.
|
|
30
|
+
- 여러 항목을 한꺼번에 작업하지 않는다. 반드시 1항목 = 1커밋이다.
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Git 작업 규칙
|
|
35
|
+
|
|
36
|
+
- tasks.md의 항목 1개 완료 = git commit 1개. 이 규칙을 반드시 지킨다.
|
|
37
|
+
- 작업 중간에는 commit 하지 않는다.
|
|
38
|
+
- 기능이 정상 동작한다고 판단되면 commit 한다.
|
|
39
|
+
- commit message 는 변경 내용을 구체적으로 설명한다.
|
|
@@ -35,10 +35,11 @@ while ($true) {
|
|
|
35
35
|
exit 0
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
# rules.md + tasks.md 를 합쳐서 프롬프트 구성
|
|
38
|
+
# base_rules.md + rules.md + tasks.md 를 합쳐서 프롬프트 구성
|
|
39
|
+
$baseRules = Get-Content .sleepcode/scripts/base_rules.md -Raw -Encoding UTF8
|
|
39
40
|
$rules = Get-Content .sleepcode/rules.md -Raw -Encoding UTF8
|
|
40
41
|
$tasks = Get-Content .sleepcode/tasks.md -Raw -Encoding UTF8
|
|
41
|
-
$prompt = "$rules`n`n---`n`n$tasks"
|
|
42
|
+
$prompt = "$baseRules`n`n---`n`n$rules`n`n---`n`n$tasks"
|
|
42
43
|
|
|
43
44
|
Log "claude 실행 중..."
|
|
44
45
|
# stream-json -> log_filter.py 로 핵심 메시지만 추출
|
|
@@ -31,11 +31,16 @@ while true; do
|
|
|
31
31
|
exit 0
|
|
32
32
|
fi
|
|
33
33
|
|
|
34
|
-
# rules.md + tasks.md 를 합쳐서 프롬프트 구성
|
|
34
|
+
# base_rules.md + rules.md + tasks.md 를 합쳐서 프롬프트 구성
|
|
35
|
+
BASE_RULES=$(cat .sleepcode/scripts/base_rules.md)
|
|
35
36
|
RULES=$(cat .sleepcode/rules.md)
|
|
36
37
|
TASKS=$(cat .sleepcode/tasks.md)
|
|
37
38
|
|
|
38
|
-
PROMPT="${
|
|
39
|
+
PROMPT="${BASE_RULES}
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
${RULES}
|
|
39
44
|
|
|
40
45
|
---
|
|
41
46
|
|
|
@@ -8,25 +8,6 @@
|
|
|
8
8
|
|
|
9
9
|
---
|
|
10
10
|
|
|
11
|
-
## 기본 원칙
|
|
12
|
-
|
|
13
|
-
- 절대로 사용자에게 질문하지 않는다.
|
|
14
|
-
- 작업이 끝났다고 판단하지 않는다.
|
|
15
|
-
- 항상 다음 작업을 스스로 찾는다.
|
|
16
|
-
- 가능한 한 많은 기능을 구현하며 계속 진행한다.
|
|
17
|
-
|
|
18
|
-
---
|
|
19
|
-
|
|
20
|
-
## 참고 자료
|
|
21
|
-
|
|
22
|
-
- `.sleepcode/docs/` 디렉토리에 업로드된 파일 참고
|
|
23
|
-
|
|
24
|
-
## Figma
|
|
25
|
-
|
|
26
|
-
- **프론트엔드 디자인**: Figma MCP 도구로 직접 조회 가능 (API Key: `{{FIGMA_API_KEY}}`)
|
|
27
|
-
|
|
28
|
-
---
|
|
29
|
-
|
|
30
11
|
## 작업 방식
|
|
31
12
|
|
|
32
13
|
- 작은 단위로 작업하고 자주 확인한다.
|
|
@@ -45,25 +26,3 @@
|
|
|
45
26
|
|
|
46
27
|
- 기존 프로젝트 구조와 패턴을 존중한다.
|
|
47
28
|
- 중복 코드를 만들지 않는다.
|
|
48
|
-
|
|
49
|
-
---
|
|
50
|
-
|
|
51
|
-
## 태스크 완료 처리
|
|
52
|
-
|
|
53
|
-
- `.sleepcode/tasks.md` 파일에서 작업 목록을 확인한다.
|
|
54
|
-
- 태스크를 **한 항목씩** 순서대로 진행한다.
|
|
55
|
-
- 한 항목을 완료하면 반드시 아래 순서를 따른다:
|
|
56
|
-
1. 해당 항목의 `[ ]`를 `[x]`로 변경한다.
|
|
57
|
-
2. 관련 파일을 모두 `git add` 한다. (tasks.md 포함)
|
|
58
|
-
3. `git commit` 한다. (커밋 메시지에 태스크 내용을 포함)
|
|
59
|
-
4. 그 다음 항목으로 넘어간다.
|
|
60
|
-
- 여러 항목을 한꺼번에 작업하지 않는다. 반드시 1항목 = 1커밋이다.
|
|
61
|
-
|
|
62
|
-
---
|
|
63
|
-
|
|
64
|
-
## Git 작업 규칙
|
|
65
|
-
|
|
66
|
-
- tasks.md의 항목 1개 완료 = git commit 1개. 이 규칙을 반드시 지킨다.
|
|
67
|
-
- 작업 중간에는 commit 하지 않는다.
|
|
68
|
-
- 기능이 정상 동작한다고 판단되면 commit 한다.
|
|
69
|
-
- commit message 는 변경 내용을 구체적으로 설명한다.
|
|
@@ -8,25 +8,6 @@
|
|
|
8
8
|
|
|
9
9
|
---
|
|
10
10
|
|
|
11
|
-
## 기본 원칙
|
|
12
|
-
|
|
13
|
-
- 절대로 사용자에게 질문하지 않는다.
|
|
14
|
-
- 작업이 끝났다고 판단하지 않는다.
|
|
15
|
-
- 항상 다음 작업을 스스로 찾는다.
|
|
16
|
-
- 가능한 한 많은 기능을 구현하며 계속 진행한다.
|
|
17
|
-
|
|
18
|
-
---
|
|
19
|
-
|
|
20
|
-
## 참고 자료
|
|
21
|
-
|
|
22
|
-
- `.sleepcode/docs/` 디렉토리에 업로드된 파일 참고 (피그마 스크린샷, 기획서, 참고 이미지 등)
|
|
23
|
-
|
|
24
|
-
## Figma
|
|
25
|
-
|
|
26
|
-
- **프론트엔드 디자인**: Figma MCP 도구로 직접 조회 가능 (API Key: `{{FIGMA_API_KEY}}`)
|
|
27
|
-
|
|
28
|
-
---
|
|
29
|
-
|
|
30
11
|
## 작업 방식
|
|
31
12
|
|
|
32
13
|
- 작은 단위로 작업하고 자주 확인한다.
|
|
@@ -53,25 +34,3 @@
|
|
|
53
34
|
- 중복 코드를 만들지 않는다.
|
|
54
35
|
- App Router 구조를 따른다.
|
|
55
36
|
- Server Component / Client Component 를 적절히 구분한다.
|
|
56
|
-
|
|
57
|
-
---
|
|
58
|
-
|
|
59
|
-
## 태스크 완료 처리
|
|
60
|
-
|
|
61
|
-
- `.sleepcode/tasks.md` 파일에서 작업 목록을 확인한다.
|
|
62
|
-
- 태스크를 **한 항목씩** 순서대로 진행한다.
|
|
63
|
-
- 한 항목을 완료하면 반드시 아래 순서를 따른다:
|
|
64
|
-
1. 해당 항목의 `[ ]`를 `[x]`로 변경한다.
|
|
65
|
-
2. 관련 파일을 모두 `git add` 한다. (tasks.md 포함)
|
|
66
|
-
3. `git commit` 한다. (커밋 메시지에 태스크 내용을 포함)
|
|
67
|
-
4. 그 다음 항목으로 넘어간다.
|
|
68
|
-
- 여러 항목을 한꺼번에 작업하지 않는다. 반드시 1항목 = 1커밋이다.
|
|
69
|
-
|
|
70
|
-
---
|
|
71
|
-
|
|
72
|
-
## Git 작업 규칙
|
|
73
|
-
|
|
74
|
-
- tasks.md의 항목 1개 완료 = git commit 1개. 이 규칙을 반드시 지킨다.
|
|
75
|
-
- 작업 중간에는 commit 하지 않는다.
|
|
76
|
-
- 기능이 정상 동작한다고 판단되면 commit 한다.
|
|
77
|
-
- commit message 는 변경 내용을 구체적으로 설명한다.
|
|
@@ -8,25 +8,6 @@
|
|
|
8
8
|
|
|
9
9
|
---
|
|
10
10
|
|
|
11
|
-
## 기본 원칙
|
|
12
|
-
|
|
13
|
-
- 절대로 사용자에게 질문하지 않는다.
|
|
14
|
-
- 작업이 끝났다고 판단하지 않는다.
|
|
15
|
-
- 항상 다음 작업을 스스로 찾는다.
|
|
16
|
-
- 가능한 한 많은 기능을 구현하며 계속 진행한다.
|
|
17
|
-
|
|
18
|
-
---
|
|
19
|
-
|
|
20
|
-
## 참고 자료
|
|
21
|
-
|
|
22
|
-
- `.sleepcode/docs/` 디렉토리에 업로드된 파일 참고 (피그마 스크린샷, 기획서, 참고 이미지 등)
|
|
23
|
-
|
|
24
|
-
## Figma
|
|
25
|
-
|
|
26
|
-
- **프론트엔드 디자인**: Figma MCP 도구로 직접 조회 가능 (API Key: `{{FIGMA_API_KEY}}`)
|
|
27
|
-
|
|
28
|
-
---
|
|
29
|
-
|
|
30
11
|
## 작업 방식
|
|
31
12
|
|
|
32
13
|
- 작은 단위로 작업하고 자주 확인한다.
|
|
@@ -52,25 +33,3 @@
|
|
|
52
33
|
- 중복 코드를 만들지 않는다.
|
|
53
34
|
- 기존 컴포넌트를 최대한 재사용한다.
|
|
54
35
|
- 새 컴포넌트는 기존 디렉토리 구조에 맞게 배치한다.
|
|
55
|
-
|
|
56
|
-
---
|
|
57
|
-
|
|
58
|
-
## 태스크 완료 처리
|
|
59
|
-
|
|
60
|
-
- `.sleepcode/tasks.md` 파일에서 작업 목록을 확인한다.
|
|
61
|
-
- 태스크를 **한 항목씩** 순서대로 진행한다.
|
|
62
|
-
- 한 항목을 완료하면 반드시 아래 순서를 따른다:
|
|
63
|
-
1. 해당 항목의 `[ ]`를 `[x]`로 변경한다.
|
|
64
|
-
2. 관련 파일을 모두 `git add` 한다. (tasks.md 포함)
|
|
65
|
-
3. `git commit` 한다. (커밋 메시지에 태스크 내용을 포함)
|
|
66
|
-
4. 그 다음 항목으로 넘어간다.
|
|
67
|
-
- 여러 항목을 한꺼번에 작업하지 않는다. 반드시 1항목 = 1커밋이다.
|
|
68
|
-
|
|
69
|
-
---
|
|
70
|
-
|
|
71
|
-
## Git 작업 규칙
|
|
72
|
-
|
|
73
|
-
- tasks.md의 항목 1개 완료 = git commit 1개. 이 규칙을 반드시 지킨다.
|
|
74
|
-
- 작업 중간에는 commit 하지 않는다.
|
|
75
|
-
- 기능이 정상 동작한다고 판단되면 commit 한다.
|
|
76
|
-
- commit message 는 변경 내용을 구체적으로 설명한다.
|
|
@@ -8,25 +8,6 @@
|
|
|
8
8
|
|
|
9
9
|
---
|
|
10
10
|
|
|
11
|
-
## 기본 원칙
|
|
12
|
-
|
|
13
|
-
- 절대로 사용자에게 질문하지 않는다.
|
|
14
|
-
- 작업이 끝났다고 판단하지 않는다.
|
|
15
|
-
- 항상 다음 작업을 스스로 찾는다.
|
|
16
|
-
- 가능한 한 많은 기능을 구현하며 계속 진행한다.
|
|
17
|
-
|
|
18
|
-
---
|
|
19
|
-
|
|
20
|
-
## 참고 자료
|
|
21
|
-
|
|
22
|
-
- `.sleepcode/docs/` 디렉토리에 업로드된 파일 참고 (ERD, 화면설계, API 명세 등)
|
|
23
|
-
|
|
24
|
-
## Figma
|
|
25
|
-
|
|
26
|
-
- **프론트엔드 디자인**: Figma MCP 도구로 직접 조회 가능 (API Key: `{{FIGMA_API_KEY}}`)
|
|
27
|
-
|
|
28
|
-
---
|
|
29
|
-
|
|
30
11
|
## 작업 방식
|
|
31
12
|
|
|
32
13
|
- 작은 단위로 작업하고 자주 테스트한다.
|
|
@@ -54,25 +35,3 @@
|
|
|
54
35
|
- REST API는 일관된 응답 형식을 유지한다.
|
|
55
36
|
- Entity ↔ DTO 변환을 명확히 분리한다.
|
|
56
37
|
- Service 계층에 비즈니스 로직을 집중한다.
|
|
57
|
-
|
|
58
|
-
---
|
|
59
|
-
|
|
60
|
-
## 태스크 완료 처리
|
|
61
|
-
|
|
62
|
-
- `.sleepcode/tasks.md` 파일에서 작업 목록을 확인한다.
|
|
63
|
-
- 태스크를 **한 항목씩** 순서대로 진행한다.
|
|
64
|
-
- 한 항목을 완료하면 반드시 아래 순서를 따른다:
|
|
65
|
-
1. 해당 항목의 `[ ]`를 `[x]`로 변경한다.
|
|
66
|
-
2. 관련 파일을 모두 `git add` 한다. (tasks.md 포함)
|
|
67
|
-
3. `git commit` 한다. (커밋 메시지에 태스크 내용을 포함)
|
|
68
|
-
4. 그 다음 항목으로 넘어간다.
|
|
69
|
-
- 여러 항목을 한꺼번에 작업하지 않는다. 반드시 1항목 = 1커밋이다.
|
|
70
|
-
|
|
71
|
-
---
|
|
72
|
-
|
|
73
|
-
## Git 작업 규칙
|
|
74
|
-
|
|
75
|
-
- tasks.md의 항목 1개 완료 = git commit 1개. 이 규칙을 반드시 지킨다.
|
|
76
|
-
- 작업 중간에는 commit 하지 않는다.
|
|
77
|
-
- 기능이 정상 동작한다고 판단되면 commit 한다.
|
|
78
|
-
- commit message 는 변경 내용을 구체적으로 설명한다.
|