aiwf 0.3.14 → 0.3.15

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.
@@ -52,6 +52,61 @@ async function checkExistingInstallation() {
52
52
  return flagExists;
53
53
  }
54
54
 
55
+ /**
56
+ * Check if existing project files exist
57
+ * @returns {Promise<{hasProject: boolean, projectFiles: string[]}>} Project status
58
+ */
59
+ async function checkExistingProject() {
60
+ const projectFiles = [];
61
+ let hasProject = false;
62
+
63
+ // Check for key project files
64
+ const keyFiles = [
65
+ FILES.PROJECT_MANIFEST,
66
+ path.join(AIWF_DIRS.PROJECT_DOCS, 'README.md'),
67
+ path.join(AIWF_DIRS.REQUIREMENTS, 'requirements.md'),
68
+ path.join(AIWF_DIRS.SPRINTS, 'sprint-01.md'),
69
+ path.join(AIWF_DIRS.GENERAL_TASKS, 'tasks.md'),
70
+ path.join(AIWF_DIRS.ARCHITECTURAL_DECISIONS, 'decisions.md'),
71
+ path.join(AIWF_DIRS.STATE_OF_PROJECT, 'current-state.md')
72
+ ];
73
+
74
+ for (const file of keyFiles) {
75
+ try {
76
+ await fs.access(file);
77
+ projectFiles.push(file);
78
+ hasProject = true;
79
+ } catch (error) {
80
+ // File doesn't exist, continue
81
+ }
82
+ }
83
+
84
+ // Check for any .md files in project directories
85
+ const projectDirs = [
86
+ AIWF_DIRS.PROJECT_DOCS,
87
+ AIWF_DIRS.REQUIREMENTS,
88
+ AIWF_DIRS.SPRINTS,
89
+ AIWF_DIRS.GENERAL_TASKS,
90
+ AIWF_DIRS.ARCHITECTURAL_DECISIONS,
91
+ AIWF_DIRS.STATE_OF_PROJECT
92
+ ];
93
+
94
+ for (const dir of projectDirs) {
95
+ try {
96
+ const files = await fs.readdir(dir);
97
+ const mdFiles = files.filter(file => file.endsWith('.md'));
98
+ if (mdFiles.length > 0) {
99
+ hasProject = true;
100
+ projectFiles.push(...mdFiles.map(file => path.join(dir, file)));
101
+ }
102
+ } catch (error) {
103
+ // Directory doesn't exist, continue
104
+ }
105
+ }
106
+
107
+ return { hasProject, projectFiles };
108
+ }
109
+
55
110
  /**
56
111
  * Log with spinner for debug mode
57
112
  * @param {Object} spinner - Ora spinner instance
@@ -146,34 +201,145 @@ async function selectLanguage(options) {
146
201
  * Handle existing installation
147
202
  * @param {Object} msg - Localized messages
148
203
  * @param {Object} options - Installation options
149
- * @returns {Promise<boolean>} Continue with installation
204
+ * @returns {Promise<{continue: boolean, installType: string, preserveProject: boolean}>} Installation decision
150
205
  */
151
206
  async function handleExistingInstallation(msg, options) {
207
+
152
208
  if (options.force) {
153
- return true;
209
+ return { continue: true, installType: 'reinstall', preserveProject: false };
154
210
  }
155
211
 
156
- const response = await prompts({
212
+ // First, ask about installation type
213
+ const installResponse = await prompts({
157
214
  type: 'select',
158
215
  name: 'action',
159
216
  message: msg.existingDetected,
160
217
  choices: [
161
218
  { title: msg.updateOption, value: 'update' },
219
+ { title: msg.reinstallOption, value: 'reinstall' },
162
220
  { title: msg.skipOption, value: 'skip' },
163
221
  { title: msg.cancelOption, value: 'cancel' }
164
222
  ]
165
223
  });
166
224
 
167
- if (response.action === 'skip' || response.action === 'cancel') {
225
+
226
+
227
+ if (installResponse.action === 'skip' || installResponse.action === 'cancel') {
168
228
  console.log(chalk.yellow(msg.installCancelled));
169
229
  process.exit(0);
170
230
  }
171
231
 
172
- if (response.action === 'update') {
232
+ let preserveProject = true; // Default to preserve
233
+
234
+ // If reinstalling, don't preserve project (complete fresh install)
235
+ if (installResponse.action === 'reinstall') {
236
+ preserveProject = false;
237
+ }
238
+
239
+ // Backup if updating
240
+ if (installResponse.action === 'update') {
173
241
  await backupCommandsAndDocs(msg);
174
242
  }
175
243
 
176
- return true;
244
+ return {
245
+ continue: true,
246
+ installType: installResponse.action,
247
+ preserveProject
248
+ };
249
+ }
250
+
251
+ /**
252
+ * Backup project files
253
+ * @param {string[]} projectFiles - List of project files to backup
254
+ * @param {Object} msg - Localized messages
255
+ * @returns {Promise<string>} Backup directory path
256
+ */
257
+ async function backupProjectFiles(projectFiles, msg) {
258
+ if (projectFiles.length === 0) {
259
+ return null;
260
+ }
261
+
262
+ const backupDir = path.join(os.tmpdir(), `aiwf-project-backup-${Date.now()}`);
263
+ await fs.mkdir(backupDir, { recursive: true });
264
+
265
+ console.log(chalk.cyan('💾 Backing up project files...'));
266
+
267
+ for (const file of projectFiles) {
268
+ try {
269
+ const relativePath = path.relative(process.cwd(), file);
270
+ const backupPath = path.join(backupDir, relativePath);
271
+ const backupDirPath = path.dirname(backupPath);
272
+
273
+ await fs.mkdir(backupDirPath, { recursive: true });
274
+ await fs.copyFile(file, backupPath);
275
+ } catch (error) {
276
+ console.log(chalk.yellow(`Warning: Could not backup ${file}: ${error.message}`));
277
+ }
278
+ }
279
+
280
+ console.log(chalk.green(`✅ Project files backed up to: ${backupDir}`));
281
+ return backupDir;
282
+ }
283
+
284
+ /**
285
+ * Restore project files from backup
286
+ * @param {string} backupDir - Backup directory path
287
+ * @param {Object} msg - Localized messages
288
+ */
289
+ async function restoreProjectFiles(backupDir, msg) {
290
+ if (!backupDir) {
291
+ return;
292
+ }
293
+
294
+ console.log(chalk.cyan('🔄 Restoring project files...'));
295
+
296
+ try {
297
+ const backupFiles = await fs.readdir(backupDir, { recursive: true });
298
+
299
+ for (const file of backupFiles) {
300
+ const backupFilePath = path.join(backupDir, file);
301
+ const stat = await fs.stat(backupFilePath);
302
+
303
+ if (stat.isFile()) {
304
+ const targetPath = path.join(process.cwd(), file);
305
+ const targetDir = path.dirname(targetPath);
306
+
307
+ await fs.mkdir(targetDir, { recursive: true });
308
+ await fs.copyFile(backupFilePath, targetPath);
309
+ }
310
+ }
311
+
312
+ console.log(chalk.green(msg.projectPreserved));
313
+
314
+ // Clean up backup directory
315
+ await fs.rm(backupDir, { recursive: true, force: true });
316
+ } catch (error) {
317
+ console.log(chalk.yellow(`Warning: Could not restore some project files: ${error.message}`));
318
+ console.log(chalk.yellow(`Backup preserved at: ${backupDir}`));
319
+ }
320
+ }
321
+
322
+ /**
323
+ * Remove project files
324
+ * @param {string[]} projectFiles - List of project files to remove
325
+ * @param {Object} msg - Localized messages
326
+ */
327
+ async function removeProjectFiles(projectFiles, msg) {
328
+ if (projectFiles.length === 0) {
329
+ return;
330
+ }
331
+
332
+ console.log(chalk.cyan('🗑️ Removing existing project files...'));
333
+
334
+ for (const file of projectFiles) {
335
+ try {
336
+ await fs.unlink(file);
337
+ } catch (error) {
338
+ // File might already be deleted, continue
339
+ }
340
+ }
341
+
342
+ console.log(chalk.green(msg.projectOverwritten));
177
343
  }
178
344
 
179
345
  /**
@@ -609,9 +775,22 @@ export async function installAIWF(options = {}) {
609
775
  // Check existing installation
610
776
  const hasExisting = await checkExistingInstallation();
611
777
 
778
+ let installDecision = { continue: true, installType: 'fresh', preserveProject: false };
779
+ let projectBackupDir = null;
780
+
612
781
  if (hasExisting) {
613
- const shouldContinue = await handleExistingInstallation(msg, options);
614
- if (!shouldContinue) return;
782
+
783
+ installDecision = await handleExistingInstallation(msg, options);
784
+
785
+ if (!installDecision.continue) return;
786
+
787
+ // If reinstalling and preserving project, backup project files
788
+ if (installDecision.installType === 'reinstall' && installDecision.preserveProject) {
789
+ const { hasProject, projectFiles } = await checkExistingProject();
790
+ if (hasProject) {
791
+ projectBackupDir = await backupProjectFiles(projectFiles, msg);
792
+ }
793
+ }
615
794
  }
616
795
 
617
796
  const spinner = ora(msg.fetching).start();
@@ -620,16 +799,20 @@ export async function installAIWF(options = {}) {
620
799
  // Create directory structure
621
800
  await createDirectoryStructure();
622
801
 
623
- // Download manifest (fresh installs only)
624
- if (!hasExisting) {
802
+ // Download manifest (fresh installs only or complete reinstall)
803
+ if (!hasExisting || installDecision.installType === 'reinstall') {
625
804
  await downloadManifest(languagePath, spinner, msg, debugLog);
626
805
  }
627
806
 
628
- // Download templates
629
- await downloadTemplates(languagePath, spinner, msg, debugLog);
807
+ // Download templates (fresh installs and complete reinstall only)
808
+ if (!hasExisting || installDecision.installType === 'reinstall') {
809
+ await downloadTemplates(languagePath, spinner, msg, debugLog);
810
+ }
630
811
 
631
- // Update documentation
632
- await updateDocumentation(languagePath, spinner, msg, debugLog);
812
+ // Update documentation (fresh installs and complete reinstall only)
813
+ if (!hasExisting || installDecision.installType === 'reinstall') {
814
+ await updateDocumentation(languagePath, spinner, msg, debugLog);
815
+ }
633
816
 
634
817
  // Update commands
635
818
  await updateCommands(languagePath, spinner, msg, debugLog);
@@ -637,8 +820,13 @@ export async function installAIWF(options = {}) {
637
820
  // Download and process rules
638
821
  await downloadAndProcessRules(spinner, msg, debugLog);
639
822
 
823
+ // Restore project files if needed
824
+ if (projectBackupDir) {
825
+ await restoreProjectFiles(projectBackupDir, msg);
826
+ }
827
+
640
828
  // Success
641
- if (hasExisting) {
829
+ if (hasExisting && installDecision.installType === 'update') {
642
830
  spinner.succeed(chalk.green(msg.updateSuccess));
643
831
  } else {
644
832
  spinner.succeed(chalk.green(msg.installSuccess));
@@ -11,8 +11,16 @@ export const messages = {
11
11
  english: 'English',
12
12
  existingDetected: '기존 AIWF 설치가 감지되었습니다. 무엇을 하시겠습니까?',
13
13
  updateOption: '업데이트 (명령어와 문서만 업데이트하고 작업 내용은 보존)',
14
+ reinstallOption: '완전 재설치 (모든 내용을 새로 설치, 기존 프로젝트 덮어쓰기)',
14
15
  skipOption: '설치 건너뛰기',
15
16
  cancelOption: '취소',
17
+ projectDetected: '기존 프로젝트가 감지되었습니다. 프로젝트 파일을 어떻게 처리하시겠습니까?',
18
+ preserveProject: '프로젝트 보존 (기존 프로젝트 파일 유지)',
19
+ overwriteProject: '덮어쓰기 (새로 설치하고 기존 프로젝트 삭제)',
20
+ checkingProject: '기존 프로젝트 확인 중...',
21
+ projectFound: '기존 프로젝트가 발견되었습니다:',
22
+ projectPreserved: '💾 프로젝트가 보존되었습니다.',
23
+ projectOverwritten: '🔄 프로젝트가 새로 설치되었습니다.',
16
24
  installCancelled: '\n설치가 취소되었습니다.',
17
25
  backingUp: '기존 명령어 및 문서 백업 중...',
18
26
  fetching: 'GitHub에서 AIWF 프레임워크를 가져오는 중...',
@@ -72,8 +80,16 @@ export const messages = {
72
80
  english: 'English',
73
81
  existingDetected: 'Existing AIWF installation detected. What would you like to do?',
74
82
  updateOption: 'Update (Update commands and docs only, preserve work content)',
83
+ reinstallOption: 'Complete reinstall (Install everything fresh, overwrite existing project)',
75
84
  skipOption: 'Skip installation',
76
85
  cancelOption: 'Cancel',
86
+ projectDetected: 'Existing project detected. How would you like to handle project files?',
87
+ preserveProject: 'Preserve project (Keep existing project files)',
88
+ overwriteProject: 'Overwrite (Fresh install and remove existing project)',
89
+ checkingProject: 'Checking for existing project...',
90
+ projectFound: 'Existing project found:',
91
+ projectPreserved: '💾 Project has been preserved.',
92
+ projectOverwritten: '🔄 Project has been freshly installed.',
77
93
  installCancelled: '\nInstallation cancelled.',
78
94
  backingUp: 'Backing up existing commands and documents...',
79
95
  fetching: 'Fetching AIWF framework from GitHub...',
@@ -22,7 +22,7 @@ export const AIWF_DIRS = {
22
22
  REQUIREMENTS: path.join(BASE_DIRS.AIWF, '02_REQUIREMENTS'),
23
23
  SPRINTS: path.join(BASE_DIRS.AIWF, '03_SPRINTS'),
24
24
  GENERAL_TASKS: path.join(BASE_DIRS.AIWF, '04_GENERAL_TASKS'),
25
- ARCHITECTURE_DECISIONS: path.join(BASE_DIRS.AIWF, '05_ARCHITECTURE_DECISIONS'),
25
+ ARCHITECTURAL_DECISIONS: path.join(BASE_DIRS.AIWF, '05_ARCHITECTURAL_DECISIONS'),
26
26
  STATE_OF_PROJECT: path.join(BASE_DIRS.AIWF, '10_STATE_OF_PROJECT'),
27
27
  PROMPTS: path.join(BASE_DIRS.AIWF, '98_PROMPTS'),
28
28
  TEMPLATES: path.join(BASE_DIRS.AIWF, '99_TEMPLATES'),
@@ -77,7 +77,7 @@ export function getAllAiwfDirectories() {
77
77
  AIWF_DIRS.REQUIREMENTS,
78
78
  AIWF_DIRS.SPRINTS,
79
79
  AIWF_DIRS.GENERAL_TASKS,
80
- AIWF_DIRS.ARCHITECTURE_DECISIONS,
80
+ AIWF_DIRS.ARCHITECTURAL_DECISIONS,
81
81
  AIWF_DIRS.STATE_OF_PROJECT,
82
82
  AIWF_DIRS.PROMPTS,
83
83
  AIWF_DIRS.TEMPLATES
@@ -1,86 +0,0 @@
1
- # AIWF 프로젝트 정리 권장사항
2
-
3
- ## ✅ 완료된 작업
4
-
5
- 1. **import 경로 수정**
6
- - index.js의 잘못된 경로 수정 완료
7
- - `./src/commands/ai-tool.js` → `./commands/ai-tool.js`
8
-
9
- 2. **미사용 파일 삭제** (4개 파일, 1,734줄 제거)
10
- - lib/file-batch-processor.js
11
- - lib/performance-benchmark.js
12
- - lib/template-manager.js
13
- - lib/cache-integration.js
14
-
15
- ## 📋 추가 권장사항
16
-
17
- ### 1. 코드 구조 개선
18
-
19
- #### index.js 모듈화 (1,950줄 → 여러 모듈로 분리)
20
- ```
21
- index.js
22
- ├── lib/installer.js # 설치 로직
23
- ├── lib/validator.js # 검증 로직
24
- ├── lib/backup-manager.js # 백업/복원 로직
25
- └── lib/github-client.js # GitHub API 통신
26
- ```
27
-
28
- #### 토큰 관리 시스템 통합
29
- 현재 8개 파일에 분산된 토큰 기능을 2개로 통합:
30
- - `lib/token-manager.js` - 핵심 토큰 관리
31
- - `commands/token-tracking.js` - CLI 명령어
32
-
33
- ### 2. 파일명 일관성
34
-
35
- 스네이크 케이스를 케밥 케이스로 통일:
36
- ```bash
37
- # 변경 필요
38
- sync-feature-commits.js → sync-feature-commits.js ✓ (완료)
39
- feature-commit-report.js → feature-commit-report.js ✓ (완료)
40
- scan-git-history.js → scan-git-history.js ✓ (완료)
41
- ```
42
-
43
- ### 3. 중복 기능 통합
44
-
45
- #### 압축 시스템 (4개 → 2개)
46
- - 유지: `utils/context-compressor.js`, `commands/compress-context.js`
47
- - 통합: `compression-strategies.js`, `persona-aware-compressor.js`
48
-
49
- ### 4. 문서 정리
50
-
51
- 중복되거나 오래된 문서 통합:
52
- - PRD.md와 PRD.ko.md의 정보 동기화
53
- - 여러 개의 가이드 문서를 하나로 통합
54
- - 사용되지 않는 문서에서만 참조되는 기능 제거
55
-
56
- ### 5. 테스트 개선
57
-
58
- - 큰 테스트 파일 분리 (compression-test-suite.js: 1,251줄)
59
- - 주석 처리된 테스트 코드 정리
60
- - 실제 사용되는 유틸리티에 대한 테스트 추가
61
-
62
- ### 6. 성능 최적화
63
-
64
- - 복잡한 메트릭 수집 간소화 (metrics-collector.js: 884줄)
65
- - 불필요한 추상화 레벨 제거
66
- - 캐시 시스템 단순화
67
-
68
- ## 🎯 예상 효과
69
-
70
- - **코드 감소**: 약 20-30% 코드량 감소
71
- - **유지보수성**: 파일 구조 명확화로 이해도 향상
72
- - **성능**: 불필요한 추상화 제거로 성능 개선
73
- - **일관성**: 명명 규칙 통일로 개발 경험 개선
74
-
75
- ## ⚠️ 주의사항
76
-
77
- 1. **Git 통합 파일들은 유지**: 실제로 활발히 사용 중
78
- 2. **페르소나 시스템 유지**: Claude Code 통합에 필수
79
- 3. **변경 시 테스트 필수**: 기능 손상 방지
80
-
81
- ## 🔄 단계별 진행
82
-
83
- 1. **Phase 1** (즉시): ✅ 미사용 파일 제거 (완료)
84
- 2. **Phase 2** (단기): 파일명 통일, 중복 통합
85
- 3. **Phase 3** (중기): index.js 모듈화, 테스트 개선
86
- 4. **Phase 4** (장기): 전체 구조 최적화
@@ -1,253 +0,0 @@
1
- # Git-Feature 통합 가이드
2
-
3
- 이 문서는 AIWF의 Git 연동 Feature 추적 시스템 사용법을 설명합니다.
4
-
5
- ## 개요
6
-
7
- Git-Feature 통합 시스템은 Git 커밋과 Feature Ledger를 자동으로 연결하여, 개발 진행 상황을 효과적으로 추적할 수 있게 합니다.
8
-
9
- ## 주요 기능
10
-
11
- 1. **커밋 메시지 파싱**: 다양한 형식의 Feature ID 자동 인식
12
- 2. **자동 동기화**: Git hooks를 통한 실시간 Feature 업데이트
13
- 3. **히스토리 스캔**: 기존 커밋 히스토리와 Feature 연결
14
- 4. **리포트 생성**: Feature-커밋 매핑 리포트 자동 생성
15
-
16
- ## 커밋 메시지 규칙
17
-
18
- ### 지원하는 Feature ID 형식
19
-
20
- ```bash
21
- # 직접 참조
22
- git commit -m "FL001 사용자 인증 기능 구현"
23
-
24
- # 대괄호 참조
25
- git commit -m "[FL001] 로그인 폼 스타일 수정"
26
-
27
- # Conventional Commit 형식
28
- git commit -m "feat(FL001): JWT 토큰 발급 로직 추가"
29
- git commit -m "fix(FL001): 로그인 오류 수정"
30
-
31
- # 해시 참조
32
- git commit -m "Update authentication flow #FL001"
33
-
34
- # 여러 Feature 참조
35
- git commit -m "FL001, FL002 관련 공통 유틸리티 추가"
36
- ```
37
-
38
- ### 브랜치 명명 규칙
39
-
40
- ```bash
41
- # Feature 브랜치 형식
42
- git checkout -b feature/FL001-user-authentication
43
- git checkout -b feature/FL002-dashboard-redesign
44
- ```
45
-
46
- ## 명령어 사용법
47
-
48
- ### 1. sync_feature_commits - Feature 동기화
49
-
50
- ```bash
51
- # 특정 Feature 동기화
52
- node claude-code/aiwf/ko/commands/sync_feature_commits.js FL001
53
-
54
- # 모든 활성 Feature 동기화
55
- node claude-code/aiwf/ko/commands/sync_feature_commits.js --all
56
-
57
- # 최근 100개 커밋에서 Feature 찾기
58
- node claude-code/aiwf/ko/commands/sync_feature_commits.js --recent 100
59
-
60
- # 특정 날짜 이후 커밋 검색
61
- node claude-code/aiwf/ko/commands/sync_feature_commits.js --since 2025-01-01
62
-
63
- # 상세 로그 출력
64
- node claude-code/aiwf/ko/commands/sync_feature_commits.js --verbose
65
- ```
66
-
67
- ### 2. scan_git_history - 히스토리 스캔
68
-
69
- ```bash
70
- # 기본 스캔 (2025-01-01부터)
71
- node claude-code/aiwf/ko/commands/scan_git_history.js
72
-
73
- # 날짜 범위 지정
74
- node claude-code/aiwf/ko/commands/scan_git_history.js --since 2024-01-01 --until 2024-12-31
75
-
76
- # 특정 Feature만 스캔
77
- node claude-code/aiwf/ko/commands/scan_git_history.js --feature FL001
78
-
79
- # Dry-run 모드 (실제 업데이트 없음)
80
- node claude-code/aiwf/ko/commands/scan_git_history.js --dry-run
81
-
82
- # 누락된 Feature 파일 자동 생성
83
- node claude-code/aiwf/ko/commands/scan_git_history.js --create-missing
84
- ```
85
-
86
- ### 3. feature_commit_report - 리포트 생성
87
-
88
- ```bash
89
- # 기본 Markdown 리포트 생성
90
- node claude-code/aiwf/ko/commands/feature_commit_report.js
91
-
92
- # 특정 Feature 리포트
93
- node claude-code/aiwf/ko/commands/feature_commit_report.js --feature FL001
94
-
95
- # 활성 Feature만 포함
96
- node claude-code/aiwf/ko/commands/feature_commit_report.js --status active
97
-
98
- # JSON 형식으로 출력
99
- node claude-code/aiwf/ko/commands/feature_commit_report.js --format json --output report.json
100
-
101
- # HTML 형식 + 상세 정보
102
- node claude-code/aiwf/ko/commands/feature_commit_report.js --format html --detailed --output report.html
103
-
104
- # 타임라인 뷰 포함
105
- node claude-code/aiwf/ko/commands/feature_commit_report.js --timeline
106
- ```
107
-
108
- ## Git Hooks 설정
109
-
110
- ### 자동 설치
111
-
112
- ```bash
113
- # 설치 스크립트 실행
114
- ./claude-code/aiwf/ko/hooks/install-hooks.sh
115
-
116
- # 환경 변수 설정 (활성화)
117
- export AIWF_HOOKS_ENABLED=true
118
-
119
- # 상세 로그 활성화 (선택사항)
120
- export AIWF_HOOKS_VERBOSE=true
121
-
122
- # 영구 설정 (~/.bashrc 또는 ~/.zshrc에 추가)
123
- echo 'export AIWF_HOOKS_ENABLED=true' >> ~/.bashrc
124
- ```
125
-
126
- ### 수동 설치
127
-
128
- ```bash
129
- # post-commit hook 복사
130
- cp claude-code/aiwf/ko/hooks/post-commit .git/hooks/
131
- chmod +x .git/hooks/post-commit
132
-
133
- # 환경 변수 설정
134
- export AIWF_HOOKS_ENABLED=true
135
- ```
136
-
137
- ### Hook 동작 확인
138
-
139
- ```bash
140
- # Feature ID를 포함한 커밋 생성
141
- git add .
142
- git commit -m "feat(FL001): 새로운 기능 추가"
143
-
144
- # 콘솔에 다음과 같은 메시지가 표시됩니다:
145
- # 🔄 AIWF Feature Ledger 동기화 중...
146
- # ✅ Feature ID 발견: FL001
147
- # 📝 FL001 동기화 중...
148
- # ✅ FL001 동기화 완료
149
- # ✨ Feature Ledger 동기화 완료!
150
- ```
151
-
152
- ## 워크플로우 예시
153
-
154
- ### 1. 새 Feature 시작
155
-
156
- ```bash
157
- # 1. Feature Ledger 생성
158
- /project:aiwf:create_feature_ledger "User Authentication"
159
-
160
- # 2. Feature 브랜치 생성
161
- git checkout -b feature/FL001-user-authentication
162
-
163
- # 3. 개발 및 커밋
164
- git add src/auth/*
165
- git commit -m "feat(FL001): 사용자 인증 모듈 구현"
166
-
167
- # 4. Feature 자동 업데이트 확인
168
- cat .aiwf/06_FEATURE_LEDGERS/active/FL001_User_Authentication.md
169
- ```
170
-
171
- ### 2. 기존 프로젝트에 적용
172
-
173
- ```bash
174
- # 1. Git 히스토리 스캔
175
- node claude-code/aiwf/ko/commands/scan_git_history.js --since 2024-01-01
176
-
177
- # 2. 누락된 Feature 확인 및 생성
178
- node claude-code/aiwf/ko/commands/scan_git_history.js --create-missing
179
-
180
- # 3. 리포트 생성
181
- node claude-code/aiwf/ko/commands/feature_commit_report.js --detailed
182
-
183
- # 4. Git hooks 설치
184
- ./claude-code/aiwf/ko/hooks/install-hooks.sh
185
- export AIWF_HOOKS_ENABLED=true
186
- ```
187
-
188
- ### 3. 진행 상황 모니터링
189
-
190
- ```bash
191
- # 전체 Feature 상태 확인
192
- node claude-code/aiwf/ko/commands/feature_commit_report.js
193
-
194
- # 특정 Feature 상세 정보
195
- node claude-code/aiwf/ko/commands/sync_feature_commits.js FL001 --verbose
196
-
197
- # 최근 활동 확인
198
- node claude-code/aiwf/ko/commands/sync_feature_commits.js --recent 50 --verbose
199
- ```
200
-
201
- ## 문제 해결
202
-
203
- ### Git hooks가 실행되지 않음
204
-
205
- ```bash
206
- # 환경 변수 확인
207
- echo $AIWF_HOOKS_ENABLED
208
-
209
- # Hook 파일 권한 확인
210
- ls -la .git/hooks/post-commit
211
-
212
- # 수동으로 동기화 실행
213
- node claude-code/aiwf/ko/commands/sync_feature_commits.js --all
214
- ```
215
-
216
- ### Feature ID가 인식되지 않음
217
-
218
- ```bash
219
- # 커밋 메시지 패턴 확인
220
- git log --oneline | grep "FL[0-9]\{3\}"
221
-
222
- # 지원하는 형식 사용
223
- git commit -m "feat(FL001): 기능 설명" # 권장
224
- git commit -m "[FL001] 기능 설명" # 가능
225
- git commit -m "FL001 기능 설명" # 가능
226
- ```
227
-
228
- ### 동기화 오류
229
-
230
- ```bash
231
- # Feature 파일 존재 확인
232
- find .aiwf/06_FEATURE_LEDGERS -name "FL001*"
233
-
234
- # 수동으로 Feature 파일 생성
235
- /project:aiwf:create_feature_ledger "Feature Name"
236
-
237
- # 다시 동기화 시도
238
- node claude-code/aiwf/ko/commands/sync_feature_commits.js FL001
239
- ```
240
-
241
- ## 모범 사례
242
-
243
- 1. **일관된 커밋 메시지**: Conventional Commit 형식 사용 권장
244
- 2. **브랜치 전략**: Feature별 브랜치 생성 및 명명 규칙 준수
245
- 3. **정기적 동기화**: 주기적으로 `--all` 옵션으로 전체 동기화
246
- 4. **리포트 활용**: 스프린트 종료 시 리포트 생성하여 진행 상황 공유
247
- 5. **Hook 활성화**: 팀 전체가 Git hooks를 활성화하여 일관성 유지
248
-
249
- ## 추가 리소스
250
-
251
- - [Feature Ledger 시스템 사양](/.aiwf/02_REQUIREMENTS/M02_Context_Engineering_Enhancement/SPECS_Feature_Ledger_System.md)
252
- - [Git 통합 사양](/.aiwf/06_FEATURE_LEDGERS/FEATURE_GIT_INTEGRATION.md)
253
- - [통합 가이드](/.aiwf/06_FEATURE_LEDGERS/FEATURE_INTEGRATION_GUIDE.md)