aiwf 0.3.21 → 0.3.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. package/package.json +3 -2
  2. package/src/cli/index.js +39 -336
  3. package/src/lib/installer.js +310 -90
  4. package/src/utils/messages.js +24 -0
  5. package/src/DEPENDENCY_MAP.md +0 -90
  6. package/src/cli/cache-cli.js +0 -459
  7. package/src/cli/checkpoint-cli.js +0 -417
  8. package/src/cli/language-cli.js +0 -286
  9. package/src/cli/sprint-cli.js +0 -287
  10. package/src/commands/ai-tool.js +0 -383
  11. package/src/commands/compress.js +0 -60
  12. package/src/commands/create-project.js +0 -160
  13. package/src/commands/evaluate.js +0 -459
  14. package/src/commands/persona.js +0 -309
  15. package/src/commands/sprint-task.js +0 -262
  16. package/src/commands/token.js +0 -312
  17. package/src/lib/ai-persona-manager.js +0 -711
  18. package/src/lib/cache-system.js +0 -332
  19. package/src/lib/context-engine.js +0 -568
  20. package/src/lib/github-integration.js +0 -402
  21. package/src/lib/memory-profiler.js +0 -471
  22. package/src/lib/metrics-collector.js +0 -885
  23. package/src/lib/offline-detector.js +0 -386
  24. package/src/lib/resource-loader-enhanced.js +0 -399
  25. package/src/lib/resource-loader.js +0 -250
  26. package/src/lib/resources/commands/ai-persona.js +0 -602
  27. package/src/lib/resources/commands/compress-context.js +0 -389
  28. package/src/lib/resources/commands/evaluate.js +0 -246
  29. package/src/lib/resources/commands/persona-context-apply.js +0 -562
  30. package/src/lib/resources/commands/token-tracking.js +0 -443
  31. package/src/lib/resources/config/commit-patterns.js +0 -103
  32. package/src/lib/resources/config/language.json +0 -6
  33. package/src/lib/resources/personas/PERSONA_INDEX.md +0 -57
  34. package/src/lib/resources/personas/analyst.json +0 -44
  35. package/src/lib/resources/personas/architect/best_practices.md +0 -136
  36. package/src/lib/resources/personas/architect/knowledge_base.md +0 -377
  37. package/src/lib/resources/personas/architect.json +0 -44
  38. package/src/lib/resources/personas/backend/best_practices.md +0 -766
  39. package/src/lib/resources/personas/backend/knowledge_base.md +0 -1070
  40. package/src/lib/resources/personas/data_analyst/best_practices.md +0 -594
  41. package/src/lib/resources/personas/data_analyst/knowledge_base.md +0 -1057
  42. package/src/lib/resources/personas/developer.json +0 -44
  43. package/src/lib/resources/personas/developer.md +0 -37
  44. package/src/lib/resources/personas/evaluation_criteria.json +0 -137
  45. package/src/lib/resources/personas/frontend/best_practices.md +0 -445
  46. package/src/lib/resources/personas/frontend/knowledge_base.md +0 -729
  47. package/src/lib/resources/personas/persona-index.json +0 -31
  48. package/src/lib/resources/personas/reviewer.json +0 -44
  49. package/src/lib/resources/personas/security/best_practices.md +0 -307
  50. package/src/lib/resources/personas/security/knowledge_base.md +0 -498
  51. package/src/lib/resources/personas/tester.json +0 -44
  52. package/src/lib/resources/templates/README.md +0 -78
  53. package/src/lib/resources/templates/api-server/config.json +0 -64
  54. package/src/lib/resources/templates/api-server/template/.aiwf/config.json +0 -56
  55. package/src/lib/resources/templates/api-server/template/.aiwf/feature-ledger.json +0 -42
  56. package/src/lib/resources/templates/api-server/template/.aiwf/personas/backend-engineer.json +0 -40
  57. package/src/lib/resources/templates/api-server/template/.aiwf/scripts/cli.js +0 -111
  58. package/src/lib/resources/templates/api-server/template/.env.example +0 -29
  59. package/src/lib/resources/templates/api-server/template/.eslintrc.json +0 -23
  60. package/src/lib/resources/templates/api-server/template/README.md +0 -171
  61. package/src/lib/resources/templates/api-server/template/jest.config.js +0 -26
  62. package/src/lib/resources/templates/api-server/template/nodemon.json +0 -9
  63. package/src/lib/resources/templates/api-server/template/package.json +0 -61
  64. package/src/lib/resources/templates/api-server/template/src/app.ts +0 -60
  65. package/src/lib/resources/templates/api-server/template/src/config/swagger.ts +0 -38
  66. package/src/lib/resources/templates/api-server/template/src/controllers/aiwfController.ts +0 -54
  67. package/src/lib/resources/templates/api-server/template/src/controllers/authController.ts +0 -128
  68. package/src/lib/resources/templates/api-server/template/src/controllers/statusController.ts +0 -28
  69. package/src/lib/resources/templates/api-server/template/src/index.ts +0 -28
  70. package/src/lib/resources/templates/api-server/template/src/middleware/aiwfMiddleware.ts +0 -50
  71. package/src/lib/resources/templates/api-server/template/src/middleware/authMiddleware.ts +0 -41
  72. package/src/lib/resources/templates/api-server/template/src/middleware/errorHandler.ts +0 -42
  73. package/src/lib/resources/templates/api-server/template/src/middleware/notFoundHandler.ts +0 -14
  74. package/src/lib/resources/templates/api-server/template/src/middleware/requestLogger.ts +0 -20
  75. package/src/lib/resources/templates/api-server/template/src/routes/aiwf.ts +0 -31
  76. package/src/lib/resources/templates/api-server/template/src/routes/index.ts +0 -13
  77. package/src/lib/resources/templates/api-server/template/src/routes/v1/index.ts +0 -67
  78. package/src/lib/resources/templates/api-server/template/src/utils/logger.ts +0 -37
  79. package/src/lib/resources/templates/api-server/template/tests/app.test.ts +0 -40
  80. package/src/lib/resources/templates/api-server/template/tsconfig.json +0 -43
  81. package/src/lib/resources/templates/npm-library/config.json +0 -61
  82. package/src/lib/resources/templates/npm-library/template/LICENSE +0 -21
  83. package/src/lib/resources/templates/npm-library/template/README.md +0 -201
  84. package/src/lib/resources/templates/npm-library/template/package.json +0 -78
  85. package/src/lib/resources/templates/web-app/config.json +0 -53
  86. package/src/lib/resources/templates/web-app/template/.aiwf/config.json +0 -54
  87. package/src/lib/resources/templates/web-app/template/.aiwf/feature-ledger.json +0 -37
  88. package/src/lib/resources/templates/web-app/template/.aiwf/personas/fullstack-developer.json +0 -40
  89. package/src/lib/resources/templates/web-app/template/.aiwf/scripts/cli.js +0 -110
  90. package/src/lib/resources/templates/web-app/template/.eslintrc.cjs +0 -20
  91. package/src/lib/resources/templates/web-app/template/README.md +0 -151
  92. package/src/lib/resources/templates/web-app/template/index.html +0 -14
  93. package/src/lib/resources/templates/web-app/template/package.json +0 -44
  94. package/src/lib/resources/templates/web-app/template/postcss.config.js +0 -6
  95. package/src/lib/resources/templates/web-app/template/public/vite.svg +0 -1
  96. package/src/lib/resources/templates/web-app/template/src/App.tsx +0 -21
  97. package/src/lib/resources/templates/web-app/template/src/components/Layout.tsx +0 -57
  98. package/src/lib/resources/templates/web-app/template/src/components/aiwf/ContextStatus.tsx +0 -107
  99. package/src/lib/resources/templates/web-app/template/src/components/aiwf/TokenUsage.tsx +0 -71
  100. package/src/lib/resources/templates/web-app/template/src/index.css +0 -60
  101. package/src/lib/resources/templates/web-app/template/src/main.tsx +0 -10
  102. package/src/lib/resources/templates/web-app/template/src/pages/AiwfDashboard.tsx +0 -57
  103. package/src/lib/resources/templates/web-app/template/src/pages/HomePage.tsx +0 -89
  104. package/src/lib/resources/templates/web-app/template/src/pages/NotFound.tsx +0 -25
  105. package/src/lib/resources/templates/web-app/template/src/stores/aiwfStore.ts +0 -126
  106. package/src/lib/resources/templates/web-app/template/src/types/global.d.ts +0 -9
  107. package/src/lib/resources/templates/web-app/template/src/vite-env.d.ts +0 -1
  108. package/src/lib/resources/templates/web-app/template/tailwind.config.js +0 -30
  109. package/src/lib/resources/templates/web-app/template/tsconfig.json +0 -37
  110. package/src/lib/resources/templates/web-app/template/tsconfig.node.json +0 -10
  111. package/src/lib/resources/templates/web-app/template/vite.config.ts +0 -23
  112. package/src/lib/resources/utils/background-monitor.js +0 -223
  113. package/src/lib/resources/utils/compression-metrics.js +0 -1031
  114. package/src/lib/resources/utils/compression-strategies.js +0 -557
  115. package/src/lib/resources/utils/content-normalizer.js +0 -455
  116. package/src/lib/resources/utils/context-compressor.js +0 -583
  117. package/src/lib/resources/utils/context-rule-parser.js +0 -180
  118. package/src/lib/resources/utils/context-token-monitor.js +0 -463
  119. package/src/lib/resources/utils/context-update-manager.js +0 -502
  120. package/src/lib/resources/utils/git-utils.js +0 -220
  121. package/src/lib/resources/utils/importance-classifier.js +0 -645
  122. package/src/lib/resources/utils/information-filter.js +0 -710
  123. package/src/lib/resources/utils/persona-aware-compressor.js +0 -598
  124. package/src/lib/resources/utils/prompt-injector.js +0 -242
  125. package/src/lib/resources/utils/simplified-evaluator.js +0 -119
  126. package/src/lib/resources/utils/text-summarizer.js +0 -492
  127. package/src/lib/resources/utils/token-counter.js +0 -177
  128. package/src/lib/resources/utils/token-monitor.js +0 -484
  129. package/src/lib/resources/utils/token-reporter.js +0 -452
  130. package/src/lib/resources/utils/token-storage.js +0 -433
  131. package/src/lib/resources/utils/token-tracker.js +0 -283
  132. package/src/lib/state/priority-calculator.js +0 -217
  133. package/src/lib/state/state-index.js +0 -155
  134. package/src/lib/state/task-scanner.js +0 -328
  135. package/src/lib/task-analyzer.js +0 -599
  136. package/src/lib/template-cache-system.js +0 -559
  137. package/src/lib/template-downloader.js +0 -467
  138. package/src/lib/template-version-manager.js +0 -491
  139. package/src/lib/token-optimizer.js +0 -517
  140. package/src/utils/engineering-guard.js +0 -399
@@ -1,286 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * 언어 관리 CLI 명령어
5
- * AIWF 프레임워크의 언어 설정을 관리하는 CLI 도구입니다.
6
- */
7
-
8
- import { Command } from 'commander';
9
- import chalk from 'chalk';
10
- import prompts from 'prompts';
11
- import {
12
- detectLanguage,
13
- loadUserLanguageConfig,
14
- saveUserLanguageConfig,
15
- switchLanguage,
16
- getLanguageStatus,
17
- getLocalizedMessage,
18
- SUPPORTED_LANGUAGES,
19
- DEFAULT_LANGUAGE
20
- } from '../utils/language-utils.js';
21
-
22
- const program = new Command();
23
-
24
- // 다국어 CLI 메시지
25
- const CLI_MESSAGES = {
26
- ko: {
27
- LANGUAGE_STATUS_TITLE: '🌐 AIWF 언어 설정 상태',
28
- DETECTED_LANGUAGE: '감지된 언어',
29
- CONFIGURED_LANGUAGE: '설정된 언어',
30
- EFFECTIVE_LANGUAGE: '사용 중인 언어',
31
- AUTO_DETECT: '자동 감지',
32
- FALLBACK_LANGUAGE: '폴백 언어',
33
- SUPPORTED_LANGUAGES: '지원 언어',
34
- CONFIG_PATH: '설정 파일 경로',
35
- ENABLED: '활성화',
36
- DISABLED: '비활성화',
37
- NOT_SET: '설정되지 않음',
38
- SELECT_LANGUAGE: '사용할 언어를 선택하세요:',
39
- ENABLE_AUTO_DETECT: '자동 언어 감지를 활성화하시겠습니까?',
40
- LANGUAGE_CHANGED: '언어가 성공적으로 변경되었습니다',
41
- OPERATION_CANCELLED: '작업이 취소되었습니다',
42
- CURRENT_LANGUAGE: '현재 언어',
43
- PREVIOUS_LANGUAGE: '이전 언어',
44
- NEW_LANGUAGE: '새 언어'
45
- },
46
- en: {
47
- LANGUAGE_STATUS_TITLE: '🌐 AIWF Language Configuration Status',
48
- DETECTED_LANGUAGE: 'Detected Language',
49
- CONFIGURED_LANGUAGE: 'Configured Language',
50
- EFFECTIVE_LANGUAGE: 'Effective Language',
51
- AUTO_DETECT: 'Auto Detection',
52
- FALLBACK_LANGUAGE: 'Fallback Language',
53
- SUPPORTED_LANGUAGES: 'Supported Languages',
54
- CONFIG_PATH: 'Configuration Path',
55
- ENABLED: 'Enabled',
56
- DISABLED: 'Disabled',
57
- NOT_SET: 'Not Set',
58
- SELECT_LANGUAGE: 'Select language to use:',
59
- ENABLE_AUTO_DETECT: 'Enable automatic language detection?',
60
- LANGUAGE_CHANGED: 'Language changed successfully',
61
- OPERATION_CANCELLED: 'Operation cancelled',
62
- CURRENT_LANGUAGE: 'Current Language',
63
- PREVIOUS_LANGUAGE: 'Previous Language',
64
- NEW_LANGUAGE: 'New Language'
65
- }
66
- };
67
-
68
- /**
69
- * 로컬라이즈된 CLI 메시지 가져오기
70
- */
71
- function getCliMessage(key, language = DEFAULT_LANGUAGE) {
72
- return CLI_MESSAGES[language]?.[key] || CLI_MESSAGES[DEFAULT_LANGUAGE]?.[key] || key;
73
- }
74
-
75
- /**
76
- * 언어 설정 상태 표시
77
- */
78
- export async function showLanguageStatus() {
79
- try {
80
- const status = await getLanguageStatus();
81
- const currentLang = status.effectiveLanguage;
82
-
83
- console.log(chalk.blue.bold(`\n${getCliMessage('LANGUAGE_STATUS_TITLE', currentLang)}`));
84
- console.log(chalk.gray('─'.repeat(50)));
85
-
86
- console.log(chalk.white(`${getCliMessage('DETECTED_LANGUAGE', currentLang)}: `) +
87
- chalk.green(status.detectedLanguage));
88
-
89
- console.log(chalk.white(`${getCliMessage('CONFIGURED_LANGUAGE', currentLang)}: `) +
90
- (status.configuredLanguage ? chalk.green(status.configuredLanguage) :
91
- chalk.gray(getCliMessage('NOT_SET', currentLang))));
92
-
93
- console.log(chalk.white(`${getCliMessage('EFFECTIVE_LANGUAGE', currentLang)}: `) +
94
- chalk.cyan.bold(status.effectiveLanguage));
95
-
96
- console.log(chalk.white(`${getCliMessage('AUTO_DETECT', currentLang)}: `) +
97
- (status.autoDetect ?
98
- chalk.green(getCliMessage('ENABLED', currentLang)) :
99
- chalk.yellow(getCliMessage('DISABLED', currentLang))));
100
-
101
- console.log(chalk.white(`${getCliMessage('FALLBACK_LANGUAGE', currentLang)}: `) +
102
- chalk.gray(status.fallbackLanguage));
103
-
104
- console.log(chalk.white(`${getCliMessage('SUPPORTED_LANGUAGES', currentLang)}: `) +
105
- chalk.gray(status.supportedLanguages.join(', ')));
106
-
107
- console.log(chalk.white(`${getCliMessage('CONFIG_PATH', currentLang)}: `) +
108
- chalk.gray(status.configPath));
109
-
110
- if (status.error) {
111
- console.log(chalk.red('\n⚠️ Error: ' + status.error));
112
- }
113
-
114
- console.log(chalk.gray('─'.repeat(50)));
115
-
116
- } catch (error) {
117
- console.error(chalk.red('Error showing language status:', error.message));
118
- }
119
- }
120
-
121
- /**
122
- * 언어 설정 변경
123
- */
124
- export async function setLanguage(language = null, options = {}) {
125
- try {
126
- let targetLanguage = language;
127
- let autoDetect = options.autoDetect;
128
-
129
- // 언어가 지정되지 않은 경우 사용자에게 선택 요청
130
- if (!targetLanguage) {
131
- const currentStatus = await getLanguageStatus();
132
- const currentLang = currentStatus.effectiveLanguage;
133
-
134
- const languageResponse = await prompts({
135
- type: 'select',
136
- name: 'language',
137
- message: getCliMessage('SELECT_LANGUAGE', currentLang),
138
- choices: SUPPORTED_LANGUAGES.map(lang => ({
139
- title: lang === 'ko' ? '한국어 (Korean)' : 'English',
140
- value: lang
141
- }))
142
- });
143
-
144
- if (!languageResponse.language) {
145
- console.log(chalk.yellow(getCliMessage('OPERATION_CANCELLED', currentLang)));
146
- return;
147
- }
148
-
149
- targetLanguage = languageResponse.language;
150
-
151
- // 자동 감지 설정이 지정되지 않은 경우 사용자에게 묻기
152
- if (autoDetect === undefined) {
153
- const autoDetectResponse = await prompts({
154
- type: 'confirm',
155
- name: 'autoDetect',
156
- message: getCliMessage('ENABLE_AUTO_DETECT', targetLanguage),
157
- initial: true
158
- });
159
-
160
- autoDetect = autoDetectResponse.autoDetect;
161
- }
162
- }
163
-
164
- // 언어 전환 실행
165
- const result = await switchLanguage(targetLanguage);
166
-
167
- if (result.success) {
168
- console.log(chalk.green(`\n✅ ${getCliMessage('LANGUAGE_CHANGED', targetLanguage)}`));
169
- console.log(chalk.gray(` ${getCliMessage('PREVIOUS_LANGUAGE', targetLanguage)}: ${result.previousLanguage}`));
170
- console.log(chalk.gray(` ${getCliMessage('NEW_LANGUAGE', targetLanguage)}: ${result.newLanguage}`));
171
-
172
- // 자동 감지 설정 업데이트
173
- if (autoDetect !== undefined) {
174
- await saveUserLanguageConfig(targetLanguage, { autoDetect });
175
- console.log(chalk.gray(` ${getCliMessage('AUTO_DETECT', targetLanguage)}: ${autoDetect ? getCliMessage('ENABLED', targetLanguage) : getCliMessage('DISABLED', targetLanguage)}`));
176
- }
177
-
178
- } else {
179
- console.error(chalk.red('\n❌ ' + result.message));
180
- if (result.error) {
181
- console.error(chalk.gray(' Error: ' + result.error));
182
- }
183
- }
184
-
185
- } catch (error) {
186
- console.error(chalk.red('Error setting language:', error.message));
187
- }
188
- }
189
-
190
- /**
191
- * 언어 설정 초기화
192
- */
193
- export async function resetLanguage() {
194
- try {
195
- const currentStatus = await getLanguageStatus();
196
- const currentLang = currentStatus.effectiveLanguage;
197
-
198
- const confirmResponse = await prompts({
199
- type: 'confirm',
200
- name: 'confirm',
201
- message: currentLang === 'ko' ?
202
- '언어 설정을 초기화하시겠습니까? (자동 감지 모드로 돌아갑니다)' :
203
- 'Reset language configuration? (Will return to auto-detection mode)',
204
- initial: false
205
- });
206
-
207
- if (!confirmResponse.confirm) {
208
- console.log(chalk.yellow(getCliMessage('OPERATION_CANCELLED', currentLang)));
209
- return;
210
- }
211
-
212
- // 설정 파일 삭제 (자동 감지 모드로 복원)
213
- const fs = await import('fs/promises');
214
- const { LANGUAGE_CONFIG_PATH } = await import('./language-utils.js');
215
-
216
- try {
217
- await fs.unlink(LANGUAGE_CONFIG_PATH);
218
- console.log(chalk.green('\n✅ ' + (currentLang === 'ko' ?
219
- '언어 설정이 초기화되었습니다' :
220
- 'Language configuration reset successfully')));
221
- console.log(chalk.gray(' ' + (currentLang === 'ko' ?
222
- '이제 시스템 언어가 자동으로 감지됩니다' :
223
- 'System language will now be automatically detected')));
224
- } catch (error) {
225
- if (error.code === 'ENOENT') {
226
- console.log(chalk.yellow('\n⚠️ ' + (currentLang === 'ko' ?
227
- '설정 파일이 존재하지 않습니다' :
228
- 'Configuration file does not exist')));
229
- } else {
230
- throw error;
231
- }
232
- }
233
-
234
- } catch (error) {
235
- console.error(chalk.red('Error resetting language configuration:', error.message));
236
- }
237
- }
238
-
239
- // CLI 명령어 정의
240
- program
241
- .name('aiwf-lang')
242
- .description('AIWF Language Management CLI / AIWF 언어 관리 CLI')
243
- .version('1.0.0');
244
-
245
- program
246
- .command('status')
247
- .alias('s')
248
- .description('Show current language configuration / 현재 언어 설정 표시')
249
- .action(showLanguageStatus);
250
-
251
- program
252
- .command('set [language]')
253
- .alias('switch')
254
- .description('Set or change language / 언어 설정 또는 변경')
255
- .option('-a, --auto-detect [boolean]', 'Enable/disable auto detection / 자동 감지 활성화/비활성화')
256
- .action(setLanguage);
257
-
258
- program
259
- .command('reset')
260
- .alias('r')
261
- .description('Reset language configuration to auto-detection / 언어 설정을 자동 감지로 초기화')
262
- .action(resetLanguage);
263
-
264
- // 기본 명령어 (인수 없이 실행 시)
265
- program
266
- .action(async () => {
267
- await showLanguageStatus();
268
- console.log(chalk.blue('\n💡 사용 가능한 명령어 / Available commands:'));
269
- console.log(chalk.gray(' aiwf-lang status - 현재 설정 표시 / Show current configuration'));
270
- console.log(chalk.gray(' aiwf-lang set - 언어 설정 / Set language'));
271
- console.log(chalk.gray(' aiwf-lang reset - 설정 초기화 / Reset configuration'));
272
- });
273
-
274
- // CLI 실행
275
- if (import.meta.url === `file://${process.argv[1]}`) {
276
- // Deprecated 경고 표시
277
- console.log(chalk.yellow('⚠️ DEPRECATED: `aiwf-lang` is deprecated.'));
278
- console.log(chalk.yellow(' Please use `aiwf lang` instead:'));
279
- console.log(chalk.gray(' aiwf-lang status → aiwf lang status'));
280
- console.log(chalk.gray(' aiwf-lang set → aiwf lang set'));
281
- console.log(chalk.gray(' aiwf-lang reset → aiwf lang reset\n'));
282
-
283
- program.parse(process.argv);
284
- }
285
-
286
- export default program;
@@ -1,287 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * AIWF 스프린트 CLI
5
- * 독립 스프린트 생성 및 관리를 위한 명령어 인터페이스
6
- */
7
-
8
- import { Command } from 'commander';
9
- import chalk from 'chalk';
10
- import { createIndependentSprint } from '../commands/sprint-independent.js';
11
-
12
- const program = new Command();
13
-
14
- program
15
- .name('aiwf-sprint')
16
- .description('AIWF 독립 스프린트 관리 도구')
17
- .version('0.3.12');
18
-
19
- // 독립 스프린트 생성 명령어
20
- program
21
- .command('independent [name]')
22
- .alias('ind')
23
- .description('독립 스프린트 생성')
24
- .option('--from-readme', 'README에서 TODO 추출하여 스프린트 생성')
25
- .option('--from-issue <number>', 'GitHub 이슈에서 스프린트 생성')
26
- .option('--minimal', '최소 엔지니어링 레벨 설정 (기본값)')
27
- .option('--balanced', '균형 엔지니어링 레벨 설정')
28
- .option('--complete', '완전 엔지니어링 레벨 설정')
29
- .option('--description <desc>', '스프린트 설명')
30
- .action(async (name, options) => {
31
- try {
32
- console.log(chalk.blue('🚀 독립 스프린트 생성 중...'));
33
- console.log('');
34
-
35
- // 엔지니어링 레벨 결정
36
- let engineeringLevel = 'minimal';
37
- if (options.balanced) engineeringLevel = 'balanced';
38
- else if (options.complete) engineeringLevel = 'complete';
39
-
40
- // 옵션 구성
41
- const sprintOptions = {
42
- name,
43
- description: options.description,
44
- engineeringLevel,
45
- fromReadme: options.fromReadme,
46
- fromIssue: options.fromIssue,
47
- minimal: engineeringLevel === 'minimal'
48
- };
49
-
50
- // 독립 스프린트 생성
51
- const result = await createIndependentSprint(sprintOptions);
52
-
53
- if (result.success) {
54
- console.log('');
55
- console.log(chalk.green('✅ 독립 스프린트 생성 완료!'));
56
- console.log('');
57
- console.log(chalk.bold('📋 생성된 스프린트 정보:'));
58
- console.log(` 스프린트 ID: ${chalk.cyan(result.sprintId)}`);
59
- console.log(` 태스크 수: ${chalk.blue(result.tasks)}개`);
60
- console.log('');
61
- console.log(chalk.bold('🚀 다음 단계:'));
62
- console.log(` 1. Claude Code에서 ${chalk.cyan(`/project:aiwf:yolo ${result.sprintId}`)} 실행`);
63
- console.log(` 2. 또는 ${chalk.cyan(`/project:aiwf:yolo --from-independent`)} 실행`);
64
- console.log('');
65
- console.log(chalk.gray('💡 팁: YOLO 모드로 전체 스프린트를 자동 완성할 수 있습니다!'));
66
- }
67
-
68
- } catch (error) {
69
- console.error(chalk.red('❌ 독립 스프린트 생성 실패:'), error.message);
70
- process.exit(1);
71
- }
72
- });
73
-
74
- // 스프린트 목록 보기
75
- program
76
- .command('list')
77
- .alias('ls')
78
- .description('현재 프로젝트의 모든 스프린트 목록')
79
- .option('--status <status>', '상태별 필터링 (active, completed, pending)')
80
- .action(async (options) => {
81
- try {
82
- const fs = await import('fs/promises');
83
- const path = await import('path');
84
-
85
- // 프로젝트 루트 찾기
86
- let currentDir = process.cwd();
87
- while (currentDir !== path.parse(currentDir).root) {
88
- try {
89
- await fs.access(path.join(currentDir, '.aiwf'));
90
- break;
91
- } catch {
92
- currentDir = path.dirname(currentDir);
93
- }
94
- }
95
-
96
- const sprintsDir = path.join(currentDir, '.aiwf', '03_SPRINTS');
97
-
98
- try {
99
- const entries = await fs.readdir(sprintsDir);
100
- const sprintDirs = entries.filter(entry => entry.match(/^S\d+_/));
101
-
102
- if (sprintDirs.length === 0) {
103
- console.log(chalk.yellow('📭 스프린트가 없습니다.'));
104
- console.log('');
105
- console.log(chalk.gray('새 독립 스프린트를 생성하려면:'));
106
- console.log(chalk.blue(' aiwf-sprint independent "프로젝트 이름"'));
107
- return;
108
- }
109
-
110
- console.log(chalk.bold('📊 스프린트 목록:'));
111
- console.log('');
112
-
113
- for (const sprintDir of sprintDirs.sort()) {
114
- const sprintPath = path.join(sprintsDir, sprintDir);
115
- const sprintId = sprintDir.match(/^(S\d+)_/)[1];
116
-
117
- // 스프린트 메타 파일 읽기
118
- try {
119
- const metaFiles = (await fs.readdir(sprintPath)).filter(f => f.includes('meta.md'));
120
- if (metaFiles.length > 0) {
121
- const metaContent = await fs.readFile(path.join(sprintPath, metaFiles[0]), 'utf-8');
122
- const statusMatch = metaContent.match(/\*\*상태\*\*:\s*(\w+)/);
123
- const typeMatch = metaContent.match(/\*\*타입\*\*:\s*([^\n]+)/);
124
-
125
- const status = statusMatch ? statusMatch[1] : 'unknown';
126
- const type = typeMatch ? typeMatch[1].trim() : 'normal';
127
-
128
- // 상태 필터링
129
- if (options.status && status !== options.status) {
130
- continue;
131
- }
132
-
133
- const statusIcon = status === 'active' ? '🔄' :
134
- status === 'completed' ? '✅' : '⏳';
135
- const typeIcon = type.includes('독립') ? '🚀' : '📋';
136
-
137
- console.log(`${statusIcon} ${typeIcon} ${chalk.cyan(sprintId)} - ${chalk.white(sprintDir.split('_').slice(1).join('_'))}`);
138
- console.log(` 상태: ${chalk.yellow(status)} | 타입: ${chalk.gray(type)}`);
139
-
140
- // 태스크 수 계산
141
- const taskFiles = (await fs.readdir(sprintPath)).filter(f => f.match(/^T\d+_/));
142
- console.log(` 태스크: ${chalk.blue(taskFiles.length)}개`);
143
- }
144
- } catch (error) {
145
- console.log(`${chalk.red('❌')} ${chalk.cyan(sprintId)} - ${chalk.gray('메타데이터 읽기 실패')}`);
146
- }
147
-
148
- console.log('');
149
- }
150
-
151
- } catch (error) {
152
- console.log(chalk.yellow('📭 스프린트 디렉토리가 없습니다.'));
153
- }
154
-
155
- } catch (error) {
156
- console.error(chalk.red('❌ 스프린트 목록 조회 실패:'), error.message);
157
- process.exit(1);
158
- }
159
- });
160
-
161
- // 스프린트 상태 확인
162
- program
163
- .command('status <sprintId>')
164
- .description('특정 스프린트의 상세 상태 확인')
165
- .action(async (sprintId) => {
166
- try {
167
- const fs = await import('fs/promises');
168
- const path = await import('path');
169
-
170
- // 프로젝트 루트 찾기
171
- let currentDir = process.cwd();
172
- while (currentDir !== path.parse(currentDir).root) {
173
- try {
174
- await fs.access(path.join(currentDir, '.aiwf'));
175
- break;
176
- } catch {
177
- currentDir = path.dirname(currentDir);
178
- }
179
- }
180
-
181
- const sprintsDir = path.join(currentDir, '.aiwf', '03_SPRINTS');
182
- const entries = await fs.readdir(sprintsDir);
183
- const sprintDir = entries.find(entry => entry.startsWith(`${sprintId}_`));
184
-
185
- if (!sprintDir) {
186
- console.error(chalk.red(`❌ 스프린트 ${sprintId}를 찾을 수 없습니다.`));
187
- process.exit(1);
188
- }
189
-
190
- const sprintPath = path.join(sprintsDir, sprintDir);
191
-
192
- console.log(chalk.bold(`📊 스프린트 ${sprintId} 상태`));
193
- console.log('');
194
-
195
- // 메타 파일 읽기
196
- const metaFiles = (await fs.readdir(sprintPath)).filter(f => f.includes('meta.md'));
197
- if (metaFiles.length > 0) {
198
- const metaContent = await fs.readFile(path.join(sprintPath, metaFiles[0]), 'utf-8');
199
-
200
- const statusMatch = metaContent.match(/\*\*상태\*\*:\s*(\w+)/);
201
- const typeMatch = metaContent.match(/\*\*타입\*\*:\s*([^\n]+)/);
202
- const createdMatch = metaContent.match(/\*\*생성일\*\*:\s*([^\n]+)/);
203
-
204
- console.log(`상태: ${chalk.yellow(statusMatch ? statusMatch[1] : 'unknown')}`);
205
- console.log(`타입: ${chalk.blue(typeMatch ? typeMatch[1].trim() : 'normal')}`);
206
- console.log(`생성일: ${chalk.gray(createdMatch ? createdMatch[1].trim() : 'unknown')}`);
207
- console.log('');
208
- }
209
-
210
- // 태스크 목록
211
- const taskFiles = (await fs.readdir(sprintPath)).filter(f => f.match(/^T\d+_/));
212
- console.log(chalk.bold(`📋 태스크 목록 (${taskFiles.length}개):`));
213
- console.log('');
214
-
215
- for (const taskFile of taskFiles.sort()) {
216
- const taskContent = await fs.readFile(path.join(sprintPath, taskFile), 'utf-8');
217
- const taskId = taskFile.match(/^(T\d+)_/)[1];
218
- const statusMatch = taskContent.match(/\*\*상태\*\*:\s*(\w+)/);
219
- const titleMatch = taskContent.match(/^#\s+T\d+:\s*(.+)$/m);
220
-
221
- const status = statusMatch ? statusMatch[1] : 'pending';
222
- const title = titleMatch ? titleMatch[1].trim() : taskFile;
223
-
224
- const statusIcon = status === 'completed' ? '✅' :
225
- status === 'in_progress' ? '🔄' : '⏳';
226
-
227
- console.log(`${statusIcon} ${chalk.cyan(taskId)} - ${chalk.white(title)}`);
228
- console.log(` 상태: ${chalk.yellow(status)}`);
229
- console.log('');
230
- }
231
-
232
- } catch (error) {
233
- console.error(chalk.red('❌ 스프린트 상태 확인 실패:'), error.message);
234
- process.exit(1);
235
- }
236
- });
237
-
238
- // 도움말 명령어
239
- program
240
- .command('help')
241
- .description('AIWF 스프린트 명령어 도움말')
242
- .action(() => {
243
- console.log(chalk.bold('🚀 AIWF 스프린트 CLI 도움말'));
244
- console.log('');
245
- console.log(chalk.yellow('📋 주요 명령어:'));
246
- console.log('');
247
- console.log(` ${chalk.cyan('aiwf-sprint independent [name]')} - 독립 스프린트 생성`);
248
- console.log(` ${chalk.cyan('aiwf-sprint list')} - 스프린트 목록 보기`);
249
- console.log(` ${chalk.cyan('aiwf-sprint status <id>')} - 스프린트 상태 확인`);
250
- console.log('');
251
- console.log(chalk.yellow('🔧 독립 스프린트 옵션:'));
252
- console.log('');
253
- console.log(` ${chalk.blue('--from-readme')} - README TODO에서 자동 추출`);
254
- console.log(` ${chalk.blue('--from-issue <번호>')} - GitHub 이슈에서 생성`);
255
- console.log(` ${chalk.blue('--minimal')} - 최소 엔지니어링 레벨 (기본값)`);
256
- console.log(` ${chalk.blue('--balanced')} - 균형 엔지니어링 레벨`);
257
- console.log(` ${chalk.blue('--complete')} - 완전 엔지니어링 레벨`);
258
- console.log('');
259
- console.log(chalk.yellow('💡 사용 예시:'));
260
- console.log('');
261
- console.log(` ${chalk.gray('# README TODO로 독립 스프린트 생성')}`);
262
- console.log(` ${chalk.blue('aiwf-sprint independent --from-readme')}`);
263
- console.log('');
264
- console.log(` ${chalk.gray('# GitHub 이슈로 스프린트 생성')}`);
265
- console.log(` ${chalk.blue('aiwf-sprint independent --from-issue 123')}`);
266
- console.log('');
267
- console.log(` ${chalk.gray('# 균형 레벨로 커스텀 스프린트 생성')}`);
268
- console.log(` ${chalk.blue('aiwf-sprint independent "API 개발" --balanced')}`);
269
- console.log('');
270
- console.log(chalk.green('✨ 생성 후 Claude Code에서 `/project:aiwf:yolo [스프린트ID]`로 실행하세요!'));
271
- });
272
-
273
- // 에러 핸들링
274
- program.on('command:*', () => {
275
- console.error(chalk.red('❌ 알 수 없는 명령어입니다.'));
276
- console.log('');
277
- console.log(chalk.blue('도움말을 보려면: aiwf-sprint help'));
278
- process.exit(1);
279
- });
280
-
281
- // CLI 실행
282
- program.parse(process.argv);
283
-
284
- // 인수가 없으면 도움말 표시
285
- if (!process.argv.slice(2).length) {
286
- program.outputHelp();
287
- }