sleepcode 1.1.0 → 1.3.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/README.md +20 -23
- package/bin/index.js +133 -40
- package/package.json +1 -1
- package/templates/common/README.md +19 -26
- package/templates/common/ai_worker.ps1 +4 -3
- package/templates/common/ai_worker.sh +8 -3
- package/templates/common/base_rules.md +39 -0
- package/templates/common/run_forever.ps1 +6 -5
- package/templates/common/run_forever.sh +10 -5
- 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
package/README.md
CHANGED
|
@@ -45,23 +45,15 @@ npx sleepcode
|
|
|
45
45
|
|
|
46
46
|
### 3. 실행
|
|
47
47
|
|
|
48
|
-
**macOS / Linux:**
|
|
49
48
|
```bash
|
|
50
49
|
# 1회 실행
|
|
51
|
-
|
|
50
|
+
npx sleepcode run
|
|
52
51
|
|
|
53
|
-
# 무한 루프 (
|
|
54
|
-
|
|
52
|
+
# 무한 루프 (잠자기 전)
|
|
53
|
+
npx sleepcode run --loop
|
|
55
54
|
```
|
|
56
55
|
|
|
57
|
-
|
|
58
|
-
```powershell
|
|
59
|
-
# 1회 실행
|
|
60
|
-
powershell -File .\.sleepcode\ai_worker.ps1
|
|
61
|
-
|
|
62
|
-
# 무한 루프
|
|
63
|
-
powershell -File .\.sleepcode\run_forever.ps1
|
|
64
|
-
```
|
|
56
|
+
OS에 맞는 스크립트를 자동으로 선택합니다 (macOS/Linux: `.sh`, Windows: `.ps1`).
|
|
65
57
|
|
|
66
58
|
### 4. 아침에 확인
|
|
67
59
|
|
|
@@ -96,6 +88,9 @@ npx sleepcode --type react-native --name my-app --role "쇼핑몰 앱 개발"
|
|
|
96
88
|
| `--name <name>` | 프로젝트 이름 |
|
|
97
89
|
| `--role <desc>` | AI 역할 설명 |
|
|
98
90
|
| `--figma-key <key>` | Figma API Key (선택) |
|
|
91
|
+
| `--figma-file <name>` | Figma 참고 파일명 (선택) |
|
|
92
|
+
| `--notion-key <key>` | Notion API Key (선택) |
|
|
93
|
+
| `--notion-page <name>` | Notion 참고 페이지명 (선택) |
|
|
99
94
|
| `--interval <sec>` | 반복 간격 초 (기본: 30) |
|
|
100
95
|
| `-f, --force` | 기존 `.sleepcode/` 폴더 덮어쓰기 |
|
|
101
96
|
| `-h, --help` | 도움말 |
|
|
@@ -106,17 +101,19 @@ npx sleepcode --type react-native --name my-app --role "쇼핑몰 앱 개발"
|
|
|
106
101
|
|
|
107
102
|
```
|
|
108
103
|
.sleepcode/
|
|
109
|
-
rules.md
|
|
110
|
-
tasks.md
|
|
111
|
-
docs/
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
104
|
+
rules.md # ✏️ AI 역할 + 작업 규칙 (수정하세요)
|
|
105
|
+
tasks.md # ✏️ 작업 목록 (수정하세요)
|
|
106
|
+
docs/ # ✏️ 참고 자료 (피그마 스크린샷, 기획서 등)
|
|
107
|
+
scripts/ # ⚙️ 시스템 (수정하지 마세요)
|
|
108
|
+
base_rules.md # 공통 작업 규칙
|
|
109
|
+
ai_worker.sh/.ps1 # 1회 실행 스크립트 (OS별)
|
|
110
|
+
run_forever.sh/.ps1 # 무한 루프 스크립트 (OS별)
|
|
111
|
+
log_filter.py # 실시간 로그 필터
|
|
112
|
+
logs/ # 실행 로그 (자동 생성)
|
|
113
|
+
README.md # 사용 가이드
|
|
117
114
|
|
|
118
115
|
.claude/
|
|
119
|
-
settings.local.json
|
|
116
|
+
settings.local.json # Claude 권한 설정
|
|
120
117
|
```
|
|
121
118
|
|
|
122
119
|
---
|
|
@@ -152,7 +149,7 @@ rules.md + tasks.md → 프롬프트 조합 → claude -p (비대화형) → 코
|
|
|
152
149
|
|
|
153
150
|
| 동작 | 명령어 |
|
|
154
151
|
|------|--------|
|
|
155
|
-
| 세션 생성 + 실행 | `tmux new -s ai '
|
|
152
|
+
| 세션 생성 + 실행 | `tmux new -s ai 'npx sleepcode run --loop'` |
|
|
156
153
|
| 백그라운드 전환 | `Ctrl+B` → `D` |
|
|
157
154
|
| 세션 재접속 | `tmux attach -t ai` |
|
|
158
155
|
| 실시간 로그 | `tail -f .sleepcode/logs/worker_*.log` |
|
|
@@ -214,7 +211,7 @@ Windows에서는 `.sh` 대신 **PowerShell 스크립트(`.ps1`)가 자동 생성
|
|
|
214
211
|
- **AI 역할/규칙 변경**: `.sleepcode/rules.md` 수정
|
|
215
212
|
- **작업 목록 변경**: `.sleepcode/tasks.md` 수정
|
|
216
213
|
- **참고 자료 추가**: `.sleepcode/docs/`에 파일 추가 (스크린샷, 기획서 등)
|
|
217
|
-
- **반복 간격 변경**: `.sleepcode/run_forever.sh` (또는 `.ps1`)의 sleep 값 수정
|
|
214
|
+
- **반복 간격 변경**: `.sleepcode/scripts/run_forever.sh` (또는 `.ps1`)의 sleep 값 수정
|
|
218
215
|
- **Claude 권한 변경**: `.claude/settings.local.json` 수정
|
|
219
216
|
|
|
220
217
|
---
|
package/bin/index.js
CHANGED
|
@@ -190,19 +190,30 @@ 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]
|
|
198
202
|
|
|
199
203
|
옵션 없이 실행하면 인터랙티브 모드로 동작합니다.
|
|
200
204
|
|
|
205
|
+
명령어:
|
|
206
|
+
run 1회 실행 (ai_worker 스크립트)
|
|
207
|
+
run --loop 무한 루프 실행 (run_forever 스크립트)
|
|
208
|
+
|
|
201
209
|
옵션:
|
|
202
210
|
--type <type> 프로젝트 타입 (spring-boot, react-native, nextjs, custom)
|
|
203
211
|
--name <name> 프로젝트 이름
|
|
204
212
|
--role <desc> AI 역할 설명
|
|
205
213
|
--figma-key <key> Figma API Key
|
|
214
|
+
--figma-file <name> Figma 참고 파일명
|
|
215
|
+
--notion-key <key> Notion API Key
|
|
216
|
+
--notion-page <name> Notion 참고 페이지명
|
|
206
217
|
--interval <sec> 반복 간격 (초, 기본 30)
|
|
207
218
|
-f, --force 기존 .sleepcode/ 덮어쓰기
|
|
208
219
|
-h, --help 도움말
|
|
@@ -246,22 +257,23 @@ function writeFile(filePath, content) {
|
|
|
246
257
|
fs.writeFileSync(filePath, content);
|
|
247
258
|
}
|
|
248
259
|
|
|
249
|
-
function generateFiles(targetDir, { typeKey, projectName, role, buildCmd, testCmd, lintCmd, figmaKey, sleepInterval }) {
|
|
260
|
+
function generateFiles(targetDir, { typeKey, projectName, role, buildCmd, testCmd, lintCmd, figmaKey, figmaFileNames, notionKey, notionPages, sleepInterval }) {
|
|
250
261
|
const scDir = path.join(targetDir, '.sleepcode');
|
|
251
262
|
const claudeDir = path.join(targetDir, '.claude');
|
|
252
263
|
fs.mkdirSync(path.join(scDir, 'docs'), { recursive: true });
|
|
264
|
+
fs.mkdirSync(path.join(scDir, 'scripts'), { recursive: true });
|
|
253
265
|
fs.mkdirSync(path.join(scDir, 'logs'), { recursive: true });
|
|
254
266
|
fs.mkdirSync(claudeDir, { recursive: true });
|
|
255
267
|
|
|
256
|
-
//
|
|
268
|
+
// 스크립트 파일 → scripts/ 하위로 복사 (OS별 분기)
|
|
257
269
|
const scriptFiles = IS_WIN
|
|
258
270
|
? ['ai_worker.ps1', 'run_forever.ps1']
|
|
259
271
|
: ['ai_worker.sh', 'run_forever.sh'];
|
|
260
|
-
const
|
|
272
|
+
const allScriptFiles = [...scriptFiles, 'log_filter.py'];
|
|
261
273
|
|
|
262
|
-
for (const file of
|
|
274
|
+
for (const file of allScriptFiles) {
|
|
263
275
|
const src = path.join(TEMPLATES_DIR, 'common', file);
|
|
264
|
-
const dest = path.join(scDir, file);
|
|
276
|
+
const dest = path.join(scDir, 'scripts', file);
|
|
265
277
|
if (fs.existsSync(src)) {
|
|
266
278
|
let content = fs.readFileSync(src, 'utf-8');
|
|
267
279
|
content = content.replace(/\{\{SLEEP_INTERVAL\}\}/g, sleepInterval);
|
|
@@ -269,11 +281,47 @@ function generateFiles(targetDir, { typeKey, projectName, role, buildCmd, testCm
|
|
|
269
281
|
}
|
|
270
282
|
}
|
|
271
283
|
|
|
284
|
+
// base_rules.md → scripts/ 하위로 복사 (Figma/Notion 섹션 조건부 처리)
|
|
285
|
+
const baseRulesSrc = path.join(TEMPLATES_DIR, 'common', 'base_rules.md');
|
|
286
|
+
if (fs.existsSync(baseRulesSrc)) {
|
|
287
|
+
let baseRules = fs.readFileSync(baseRulesSrc, 'utf-8');
|
|
288
|
+
|
|
289
|
+
// Figma 섹션
|
|
290
|
+
if (figmaKey) {
|
|
291
|
+
let figmaSection = `## Figma\n\n- **프론트엔드 디자인**: Figma MCP 도구로 직접 조회 가능 (API Key: \`${figmaKey}\`)`;
|
|
292
|
+
if (figmaFileNames) {
|
|
293
|
+
figmaSection += `\n- **참고 파일**: ${figmaFileNames}`;
|
|
294
|
+
}
|
|
295
|
+
baseRules = baseRules.replace('{{FIGMA_SECTION}}', figmaSection);
|
|
296
|
+
} else {
|
|
297
|
+
baseRules = baseRules.replace('\n{{FIGMA_SECTION}}\n', '');
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// Notion 섹션
|
|
301
|
+
if (notionKey) {
|
|
302
|
+
let notionSection = `\n## Notion\n\n- **기획/문서**: Notion MCP 도구로 직접 조회 가능 (API Key: \`${notionKey}\`)`;
|
|
303
|
+
if (notionPages) {
|
|
304
|
+
notionSection += `\n- **참고 페이지**: ${notionPages}`;
|
|
305
|
+
}
|
|
306
|
+
baseRules = baseRules.replace('{{NOTION_SECTION}}', notionSection);
|
|
307
|
+
} else {
|
|
308
|
+
baseRules = baseRules.replace('\n{{NOTION_SECTION}}\n', '');
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
fs.writeFileSync(path.join(scDir, 'scripts', 'base_rules.md'), baseRules);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// README.md → .sleepcode/ 루트에 복사
|
|
315
|
+
const readmeSrc = path.join(TEMPLATES_DIR, 'common', 'README.md');
|
|
316
|
+
if (fs.existsSync(readmeSrc)) {
|
|
317
|
+
fs.writeFileSync(path.join(scDir, 'README.md'), fs.readFileSync(readmeSrc, 'utf-8'));
|
|
318
|
+
}
|
|
319
|
+
|
|
272
320
|
// 실행 권한 (Unix만)
|
|
273
321
|
if (!IS_WIN) {
|
|
274
|
-
fs.chmodSync(path.join(scDir, 'ai_worker.sh'), 0o755);
|
|
275
|
-
fs.chmodSync(path.join(scDir, 'run_forever.sh'), 0o755);
|
|
276
|
-
fs.chmodSync(path.join(scDir, 'log_filter.py'), 0o755);
|
|
322
|
+
fs.chmodSync(path.join(scDir, 'scripts', 'ai_worker.sh'), 0o755);
|
|
323
|
+
fs.chmodSync(path.join(scDir, 'scripts', 'run_forever.sh'), 0o755);
|
|
324
|
+
fs.chmodSync(path.join(scDir, 'scripts', 'log_filter.py'), 0o755);
|
|
277
325
|
}
|
|
278
326
|
|
|
279
327
|
// docs/.gitkeep
|
|
@@ -301,12 +349,6 @@ function generateFiles(targetDir, { typeKey, projectName, role, buildCmd, testCm
|
|
|
301
349
|
rules = rules.replace(/\{\{BUILD_CMD\}\}/g, buildCmd);
|
|
302
350
|
rules = rules.replace(/\{\{TEST_CMD\}\}/g, testCmd);
|
|
303
351
|
rules = rules.replace(/\{\{LINT_CMD\}\}/g, lintCmd);
|
|
304
|
-
rules = rules.replace(/\{\{FIGMA_API_KEY\}\}/g, figmaKey);
|
|
305
|
-
|
|
306
|
-
if (!figmaKey) {
|
|
307
|
-
rules = rules.replace(/\n## Figma[\s\S]*?(?=\n## |$)/, '');
|
|
308
|
-
}
|
|
309
|
-
|
|
310
352
|
writeFile(path.join(scDir, 'rules.md'), rules);
|
|
311
353
|
}
|
|
312
354
|
|
|
@@ -332,47 +374,72 @@ function printResult() {
|
|
|
332
374
|
const foreverScript = IS_WIN ? 'run_forever.ps1' : 'run_forever.sh';
|
|
333
375
|
|
|
334
376
|
console.log(`\n${C.bold}파일 생성 완료:${C.reset}\n`);
|
|
335
|
-
console.log(` ${C.green}✓${C.reset} .sleepcode/rules.md`);
|
|
336
|
-
console.log(` ${C.green}✓${C.reset} .sleepcode/tasks.md`);
|
|
337
|
-
console.log(` ${C.green}✓${C.reset} .sleepcode
|
|
338
|
-
console.log(` ${C.green}✓${C.reset} .sleepcode
|
|
339
|
-
console.log(` ${C.green}✓${C.reset} .sleepcode/
|
|
377
|
+
console.log(` ${C.green}✓${C.reset} .sleepcode/rules.md ${C.dim}← 수정하세요${C.reset}`);
|
|
378
|
+
console.log(` ${C.green}✓${C.reset} .sleepcode/tasks.md ${C.dim}← 수정하세요${C.reset}`);
|
|
379
|
+
console.log(` ${C.green}✓${C.reset} .sleepcode/docs/ ${C.dim}← 참고자료 추가${C.reset}`);
|
|
380
|
+
console.log(` ${C.green}✓${C.reset} .sleepcode/scripts/base_rules.md`);
|
|
381
|
+
console.log(` ${C.green}✓${C.reset} .sleepcode/scripts/${workerScript}`);
|
|
382
|
+
console.log(` ${C.green}✓${C.reset} .sleepcode/scripts/${foreverScript}`);
|
|
383
|
+
console.log(` ${C.green}✓${C.reset} .sleepcode/scripts/log_filter.py`);
|
|
340
384
|
console.log(` ${C.green}✓${C.reset} .sleepcode/README.md`);
|
|
341
|
-
console.log(` ${C.green}✓${C.reset} .sleepcode/docs/`);
|
|
342
385
|
console.log(` ${C.green}✓${C.reset} .claude/settings.local.json`);
|
|
343
386
|
|
|
344
|
-
|
|
345
|
-
console.log(`
|
|
387
|
+
console.log(`
|
|
346
388
|
${C.bold}${C.green}완료!${C.reset} 다음 단계:
|
|
347
389
|
|
|
348
390
|
${C.bold}1.${C.reset} .sleepcode/rules.md 를 프로젝트에 맞게 수정
|
|
349
391
|
${C.bold}2.${C.reset} .sleepcode/tasks.md 에 작업 목록 작성
|
|
350
|
-
${C.bold}3.${C.reset}
|
|
351
|
-
${C.dim}# 1회 실행${C.reset}
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
${C.dim}# 무한 루프${C.reset}
|
|
355
|
-
powershell -File .\\.sleepcode\\run_forever.ps1
|
|
392
|
+
${C.bold}3.${C.reset} 실행:
|
|
393
|
+
${C.cyan}npx sleepcode run${C.reset} ${C.dim}# 1회 실행${C.reset}
|
|
394
|
+
${C.cyan}npx sleepcode run --loop${C.reset} ${C.dim}# 무한 루프${C.reset}
|
|
356
395
|
`);
|
|
357
|
-
|
|
358
|
-
console.log(`
|
|
359
|
-
${C.bold}${C.green}완료!${C.reset} 다음 단계:
|
|
396
|
+
}
|
|
360
397
|
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
./.sleepcode/ai_worker.sh
|
|
398
|
+
// ─── 실행 명령어 ───
|
|
399
|
+
function runWorker(loop) {
|
|
400
|
+
const targetDir = process.cwd();
|
|
401
|
+
const scDir = path.join(targetDir, '.sleepcode', 'scripts');
|
|
366
402
|
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
403
|
+
if (!fs.existsSync(scDir)) {
|
|
404
|
+
console.error(`${C.red}.sleepcode/scripts/ 폴더가 없습니다. 먼저 'npx sleepcode'로 초기화하세요.${C.reset}`);
|
|
405
|
+
process.exit(1);
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
const scriptName = loop
|
|
409
|
+
? (IS_WIN ? 'run_forever.ps1' : 'run_forever.sh')
|
|
410
|
+
: (IS_WIN ? 'ai_worker.ps1' : 'ai_worker.sh');
|
|
411
|
+
const scriptPath = path.join(scDir, scriptName);
|
|
412
|
+
|
|
413
|
+
if (!fs.existsSync(scriptPath)) {
|
|
414
|
+
console.error(`${C.red}스크립트를 찾을 수 없습니다: ${scriptPath}${C.reset}`);
|
|
415
|
+
process.exit(1);
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
const cmd = IS_WIN
|
|
419
|
+
? `powershell -File "${scriptPath}"`
|
|
420
|
+
: `"${scriptPath}"`;
|
|
421
|
+
|
|
422
|
+
console.log(`${C.cyan}${loop ? '무한 루프' : '1회'} 실행: ${scriptName}${C.reset}\n`);
|
|
423
|
+
|
|
424
|
+
try {
|
|
425
|
+
execSync(cmd, { stdio: 'inherit', cwd: targetDir });
|
|
426
|
+
} catch (e) {
|
|
427
|
+
process.exit(e.status || 1);
|
|
370
428
|
}
|
|
371
429
|
}
|
|
372
430
|
|
|
373
431
|
// ─── 메인 ───
|
|
374
432
|
async function main() {
|
|
375
433
|
const targetDir = process.cwd();
|
|
434
|
+
|
|
435
|
+
// 서브커맨드: sleepcode run / sleepcode run --loop
|
|
436
|
+
const firstArg = process.argv[2];
|
|
437
|
+
if (firstArg === 'run') {
|
|
438
|
+
const loop = process.argv.includes('--loop');
|
|
439
|
+
runWorker(loop);
|
|
440
|
+
return;
|
|
441
|
+
}
|
|
442
|
+
|
|
376
443
|
const cliArgs = parseArgs();
|
|
377
444
|
|
|
378
445
|
console.log(`
|
|
@@ -403,6 +470,9 @@ ${C.bold}${C.magenta} ╔══════════════════
|
|
|
403
470
|
const projectName = cliArgs.name || path.basename(targetDir);
|
|
404
471
|
const role = cliArgs.role || `${projectName} 서비스 개발`;
|
|
405
472
|
const figmaKey = cliArgs.figmaKey || '';
|
|
473
|
+
const figmaFileNames = cliArgs.figmaFileNames || '';
|
|
474
|
+
const notionKey = cliArgs.notionKey || '';
|
|
475
|
+
const notionPages = cliArgs.notionPages || '';
|
|
406
476
|
const sleepInterval = cliArgs.interval || '30';
|
|
407
477
|
|
|
408
478
|
console.log(`${C.dim}타입: ${typeConfig.label}${C.reset}`);
|
|
@@ -417,6 +487,9 @@ ${C.bold}${C.magenta} ╔══════════════════
|
|
|
417
487
|
testCmd: typeConfig.testCmd,
|
|
418
488
|
lintCmd: typeConfig.lintCmd,
|
|
419
489
|
figmaKey,
|
|
490
|
+
figmaFileNames,
|
|
491
|
+
notionKey,
|
|
492
|
+
notionPages,
|
|
420
493
|
sleepInterval,
|
|
421
494
|
});
|
|
422
495
|
|
|
@@ -469,7 +542,24 @@ ${C.bold}${C.magenta} ╔══════════════════
|
|
|
469
542
|
console.log(`${C.dim} 린트: ${lintCmd || '(없음)'}${C.reset}`);
|
|
470
543
|
}
|
|
471
544
|
|
|
472
|
-
|
|
545
|
+
// Figma 연동
|
|
546
|
+
let figmaKey = '';
|
|
547
|
+
let figmaFileNames = '';
|
|
548
|
+
const useFigma = await ask(rl, 'Figma 디자인을 참고하나요? (y/N)', 'N');
|
|
549
|
+
if (useFigma.toLowerCase() === 'y') {
|
|
550
|
+
figmaKey = await ask(rl, 'Figma API Key', '');
|
|
551
|
+
figmaFileNames = await ask(rl, '참고할 Figma 파일명 (예: 홈화면, 로그인)', '');
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
// Notion 연동
|
|
555
|
+
let notionKey = '';
|
|
556
|
+
let notionPages = '';
|
|
557
|
+
const useNotion = await ask(rl, 'Notion 문서를 참고하나요? (y/N)', 'N');
|
|
558
|
+
if (useNotion.toLowerCase() === 'y') {
|
|
559
|
+
notionKey = await ask(rl, 'Notion API Key', '');
|
|
560
|
+
notionPages = await ask(rl, '참고할 Notion 페이지명 (예: 기획서, API명세)', '');
|
|
561
|
+
}
|
|
562
|
+
|
|
473
563
|
const sleepInterval = await ask(rl, '반복 간격 (초)', '30');
|
|
474
564
|
|
|
475
565
|
rl.close();
|
|
@@ -482,6 +572,9 @@ ${C.bold}${C.magenta} ╔══════════════════
|
|
|
482
572
|
testCmd,
|
|
483
573
|
lintCmd,
|
|
484
574
|
figmaKey,
|
|
575
|
+
figmaFileNames,
|
|
576
|
+
notionKey,
|
|
577
|
+
notionPages,
|
|
485
578
|
sleepInterval,
|
|
486
579
|
});
|
|
487
580
|
|
package/package.json
CHANGED
|
@@ -8,13 +8,15 @@ AI codes while you sleep — 밤새 개발 작업을 자동화하는 시스템
|
|
|
8
8
|
|
|
9
9
|
```
|
|
10
10
|
.sleepcode/
|
|
11
|
-
rules.md
|
|
12
|
-
tasks.md
|
|
13
|
-
docs/
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
11
|
+
rules.md # ✏️ AI 역할 + 작업 규칙 (수정하세요)
|
|
12
|
+
tasks.md # ✏️ 오늘 진행할 작업 목록 (수정하세요)
|
|
13
|
+
docs/ # ✏️ 개발 참고 자료 (피그마 스크린샷, 기획서 등)
|
|
14
|
+
scripts/ # ⚙️ 시스템 (수정하지 마세요)
|
|
15
|
+
base_rules.md # 공통 작업 규칙
|
|
16
|
+
ai_worker.* # 1회 실행 스크립트
|
|
17
|
+
run_forever.* # 무한 루프 감시자 스크립트
|
|
18
|
+
log_filter.py # 로그 필터 (핵심 메시지만 추출)
|
|
19
|
+
logs/ # 실행 로그 (자동 생성)
|
|
18
20
|
```
|
|
19
21
|
|
|
20
22
|
---
|
|
@@ -30,13 +32,7 @@ AI codes while you sleep — 밤새 개발 작업을 자동화하는 시스템
|
|
|
30
32
|
|
|
31
33
|
## 실행 방법
|
|
32
34
|
|
|
33
|
-
### 1.
|
|
34
|
-
|
|
35
|
-
```bash
|
|
36
|
-
chmod +x .sleepcode/*.sh
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
### 2. (최초 1회) --dangerously-skip-permissions 수락
|
|
35
|
+
### 1. (최초 1회) --dangerously-skip-permissions 수락
|
|
40
36
|
|
|
41
37
|
```bash
|
|
42
38
|
claude --dangerously-skip-permissions
|
|
@@ -44,24 +40,22 @@ claude --dangerously-skip-permissions
|
|
|
44
40
|
|
|
45
41
|
동의 프롬프트가 뜨면 수락 후 `Ctrl + C`로 나옵니다.
|
|
46
42
|
|
|
47
|
-
###
|
|
43
|
+
### 2. 실행
|
|
48
44
|
|
|
49
45
|
```bash
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
### 4. tmux 분리 (백그라운드 전환)
|
|
46
|
+
# 1회 실행
|
|
47
|
+
npx sleepcode run
|
|
54
48
|
|
|
55
|
-
|
|
56
|
-
|
|
49
|
+
# 무한 루프 (잠자기 전)
|
|
50
|
+
npx sleepcode run --loop
|
|
57
51
|
```
|
|
58
52
|
|
|
59
|
-
|
|
53
|
+
OS에 맞는 스크립트를 자동으로 선택합니다.
|
|
60
54
|
|
|
61
|
-
|
|
55
|
+
### 3. tmux 분리 (백그라운드 전환, macOS/Linux)
|
|
62
56
|
|
|
63
|
-
```
|
|
64
|
-
|
|
57
|
+
```
|
|
58
|
+
Ctrl + B → D
|
|
65
59
|
```
|
|
66
60
|
|
|
67
61
|
---
|
|
@@ -94,4 +88,3 @@ tail -100 .sleepcode/logs/worker_*.log
|
|
|
94
88
|
- **역할/규칙 변경**: `.sleepcode/rules.md` 수정
|
|
95
89
|
- **태스크 변경**: `.sleepcode/tasks.md` 수정
|
|
96
90
|
- **참고 자료 추가**: `.sleepcode/docs/` 에 파일 추가
|
|
97
|
-
- **반복 간격 변경**: `run_forever.sh` 의 `sleep` 값 수정
|
|
@@ -2,19 +2,20 @@
|
|
|
2
2
|
# run_forever.ps1 (무한 루프) 대신 수동으로 1회만 돌릴 때 사용
|
|
3
3
|
|
|
4
4
|
$ErrorActionPreference = "Stop"
|
|
5
|
-
Set-Location (Split-Path $PSScriptRoot -Parent)
|
|
5
|
+
Set-Location (Split-Path (Split-Path $PSScriptRoot -Parent) -Parent)
|
|
6
6
|
|
|
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 |
|
|
17
|
-
python .sleepcode/log_filter.py
|
|
18
|
+
python .sleepcode/scripts/log_filter.py
|
|
18
19
|
|
|
19
20
|
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
|
20
21
|
Write-Host "[$timestamp] AI 단일 실행 종료"
|
|
@@ -3,14 +3,19 @@
|
|
|
3
3
|
# AI Worker - 1회 실행 스크립트
|
|
4
4
|
# run_forever.sh (무한 루프) 대신 수동으로 1회만 돌릴 때 사용
|
|
5
5
|
|
|
6
|
-
cd "$(dirname "$0")
|
|
6
|
+
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
|
|
|
@@ -18,6 +23,6 @@ ${TASKS}"
|
|
|
18
23
|
|
|
19
24
|
# stream-json + verbose: 토큰 단위 실시간 출력
|
|
20
25
|
claude -p "$PROMPT" --dangerously-skip-permissions --output-format stream-json --verbose 2>&1 \
|
|
21
|
-
| python3 .sleepcode/log_filter.py
|
|
26
|
+
| python3 .sleepcode/scripts/log_filter.py
|
|
22
27
|
|
|
23
28
|
echo "[$(date '+%Y-%m-%d %H:%M:%S')] AI 단일 실행 종료"
|
|
@@ -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 는 변경 내용을 구체적으로 설명한다.
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# AI Night Worker - 감시자 스크립트 (Windows PowerShell)
|
|
2
|
-
# 사용법: powershell -File .\.sleepcode\run_forever.ps1
|
|
2
|
+
# 사용법: powershell -File .\.sleepcode\scripts\run_forever.ps1
|
|
3
3
|
|
|
4
4
|
$ErrorActionPreference = "Continue"
|
|
5
|
-
Set-Location (Split-Path $PSScriptRoot -Parent)
|
|
5
|
+
Set-Location (Split-Path (Split-Path $PSScriptRoot -Parent) -Parent)
|
|
6
6
|
|
|
7
7
|
$logDir = ".sleepcode/logs"
|
|
8
8
|
if (!(Test-Path $logDir)) { New-Item -ItemType Directory -Path $logDir -Force | Out-Null }
|
|
@@ -35,15 +35,16 @@ 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 로 핵심 메시지만 추출
|
|
45
46
|
$prompt | claude -p --dangerously-skip-permissions --output-format stream-json --verbose 2>&1 |
|
|
46
|
-
python .sleepcode/log_filter.py |
|
|
47
|
+
python .sleepcode/scripts/log_filter.py |
|
|
47
48
|
Tee-Object -Append $logFile
|
|
48
49
|
$exitCode = $LASTEXITCODE
|
|
49
50
|
Log "claude 종료 (exit code: $exitCode)"
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
2
|
|
|
3
3
|
# AI Night Worker - 감시자 스크립트
|
|
4
|
-
# 사용법: tmux new -s ai './.sleepcode/run_forever.sh'
|
|
4
|
+
# 사용법: tmux new -s ai './.sleepcode/scripts/run_forever.sh'
|
|
5
5
|
|
|
6
|
-
cd "$(dirname "$0")
|
|
6
|
+
cd "$(dirname "$0")/../.." || exit 1
|
|
7
7
|
|
|
8
8
|
LOG_DIR=".sleepcode/logs"
|
|
9
9
|
mkdir -p "$LOG_DIR"
|
|
@@ -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
|
|
|
@@ -44,7 +49,7 @@ ${TASKS}"
|
|
|
44
49
|
log "claude 실행 중..."
|
|
45
50
|
# stream-json → log_filter.py 로 핵심 메시지만 추출
|
|
46
51
|
claude -p "$PROMPT" --dangerously-skip-permissions --output-format stream-json --verbose 2>&1 \
|
|
47
|
-
| python3 .sleepcode/log_filter.py \
|
|
52
|
+
| python3 .sleepcode/scripts/log_filter.py \
|
|
48
53
|
| tee -a "$LOG_FILE"
|
|
49
54
|
EXIT_CODE=${PIPESTATUS[0]}
|
|
50
55
|
log "claude 종료 (exit code: $EXIT_CODE)"
|
|
@@ -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 는 변경 내용을 구체적으로 설명한다.
|