aiwf 0.3.19 → 0.3.20

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/package.json CHANGED
@@ -1,15 +1,13 @@
1
1
  {
2
2
  "name": "aiwf",
3
- "version": "0.3.19",
3
+ "version": "0.3.20",
4
4
  "description": "AI Workflow Framework for Claude Code with multi-language support (Korean/English)",
5
5
  "main": "index.js",
6
6
  "type": "module",
7
7
  "bin": {
8
8
  "aiwf": "./src/cli/index.js",
9
9
  "aiwf-lang": "./src/cli/language-cli.js",
10
- "aiwf-sprint": "./src/cli/sprint-cli.js",
11
- "aiwf-checkpoint": "./src/cli/checkpoint-cli.js",
12
- "aiwf-cache": "./src/cli/cache-cli.js"
10
+ "aiwf-sprint": "./src/cli/sprint-cli.js"
13
11
  },
14
12
  "scripts": {
15
13
  "test": "node --experimental-vm-modules node_modules/.bin/jest",
@@ -133,4 +131,4 @@
133
131
  "utils/engineering-guard.js"
134
132
  ]
135
133
  }
136
- }
134
+ }
package/src/cli/index.js CHANGED
@@ -4,16 +4,9 @@ import { program } from 'commander';
4
4
  import chalk from 'chalk';
5
5
  import { installAIWF } from '../lib/installer.js';
6
6
  import AIToolCommand from '../commands/ai-tool.js';
7
- import PersonaCommand from '../commands/persona.js';
8
- import { CacheCLI } from './cache-cli.js';
9
7
  import { addTaskToSprint } from '../commands/sprint-task.js';
10
- import CompressCommand from '../commands/compress.js';
11
- import TokenCommand from '../commands/token.js';
12
- import EvaluateCommand from '../commands/evaluate.js';
13
- import { createProject } from '../commands/create-project.js';
14
8
  import StateCommand from '../commands/state.js';
15
9
  import { createIndependentSprint } from '../commands/sprint-independent.js';
16
- import { CheckpointManager } from '../utils/checkpoint-manager.js';
17
10
  import { createYoloConfig, createInteractiveYoloConfig, showYoloConfig } from '../commands/yolo-config.js';
18
11
 
19
12
  // Parse version from package.json
@@ -50,94 +43,7 @@ program
50
43
  });
51
44
 
52
45
  // Cache management commands
53
- const cache = program.command('cache');
54
- cache.description('Manage offline template cache');
55
-
56
- cache
57
- .command('download')
58
- .description('Download templates for offline use')
59
- .option('--all', 'Download all templates')
60
- .option('--type <type>', 'Download specific type (ai-tools, projects)')
61
- .action(async (options) => {
62
- const cacheCLI = new CacheCLI();
63
- try {
64
- await cacheCLI.init();
65
- await cacheCLI.downloadCommand(options);
66
- } catch (error) {
67
- console.error(chalk.red('Cache download failed:', error.message));
68
- process.exit(1);
69
- } finally {
70
- await cacheCLI.cleanup();
71
- }
72
- });
73
-
74
- cache
75
- .command('list')
76
- .description('List cached templates')
77
- .option('--type <type>', 'Filter by type (ai-tools, projects)')
78
- .action(async (options) => {
79
- const cacheCLI = new CacheCLI();
80
- try {
81
- await cacheCLI.init();
82
- await cacheCLI.listCommand(options);
83
- } catch (error) {
84
- console.error(chalk.red('Cache list failed:', error.message));
85
- process.exit(1);
86
- } finally {
87
- await cacheCLI.cleanup();
88
- }
89
- });
90
-
91
- cache
92
- .command('clean')
93
- .description('Clean up cached templates')
94
- .option('--all', 'Clear all cached templates')
95
- .option('--max-age <days>', 'Maximum age in days (default: 7)', '7')
96
- .action(async (options) => {
97
- const cacheCLI = new CacheCLI();
98
- try {
99
- await cacheCLI.init();
100
- await cacheCLI.cleanCommand(options);
101
- } catch (error) {
102
- console.error(chalk.red('Cache clean failed:', error.message));
103
- process.exit(1);
104
- } finally {
105
- await cacheCLI.cleanup();
106
- }
107
- });
108
-
109
- cache
110
- .command('update')
111
- .description('Check for template updates')
112
- .option('--install', 'Install available updates')
113
- .action(async (options) => {
114
- const cacheCLI = new CacheCLI();
115
- try {
116
- await cacheCLI.init();
117
- await cacheCLI.updateCommand(options);
118
- } catch (error) {
119
- console.error(chalk.red('Cache update failed:', error.message));
120
- process.exit(1);
121
- } finally {
122
- await cacheCLI.cleanup();
123
- }
124
- });
125
-
126
- cache
127
- .command('status')
128
- .description('Show cache system status')
129
- .action(async () => {
130
- const cacheCLI = new CacheCLI();
131
- try {
132
- await cacheCLI.init();
133
- await cacheCLI.statusCommand();
134
- } catch (error) {
135
- console.error(chalk.red('Cache status failed:', error.message));
136
- process.exit(1);
137
- } finally {
138
- await cacheCLI.cleanup();
139
- }
140
- });
46
+ // (removed) cache command group
141
47
 
142
48
  // Language management commands
143
49
  const lang = program.command('lang');
@@ -171,45 +77,7 @@ lang
171
77
  await resetLanguage();
172
78
  });
173
79
 
174
- // Persona management commands
175
- const persona = program.command('persona');
176
- persona.description('Manage AI personas / AI 페르소나 관리');
177
-
178
- persona
179
- .command('status')
180
- .alias('s')
181
- .description('Show current persona status / 현재 페르소나 상태 표시')
182
- .action(async () => {
183
- const personaCmd = new PersonaCommand();
184
- await personaCmd.showStatus();
185
- });
186
-
187
- persona
188
- .command('list')
189
- .alias('ls')
190
- .description('List available personas / 사용 가능한 페르소나 목록')
191
- .action(async () => {
192
- const personaCmd = new PersonaCommand();
193
- await personaCmd.listPersonas();
194
- });
195
-
196
- persona
197
- .command('set <persona-name>')
198
- .alias('switch')
199
- .description('Switch to specific persona / 특정 페르소나로 전환')
200
- .action(async (personaName) => {
201
- const personaCmd = new PersonaCommand();
202
- await personaCmd.setPersona(personaName);
203
- });
204
-
205
- persona
206
- .command('reset')
207
- .alias('r')
208
- .description('Reset to default persona / 기본 페르소나로 리셋')
209
- .action(async () => {
210
- const personaCmd = new PersonaCommand();
211
- await personaCmd.resetPersona();
212
- });
80
+ // (removed) persona command group
213
81
 
214
82
  // Sprint task management command
215
83
  program
@@ -225,125 +93,14 @@ program
225
93
  }
226
94
  });
227
95
 
228
- // Create project command
229
- program
230
- .command('create-project')
231
- .alias('create')
232
- .description('Create a new AIWF project / 새 AIWF 프로젝트 생성')
233
- .action(async () => {
234
- try {
235
- await createProject();
236
- } catch (error) {
237
- console.error(chalk.red(`오류: ${error.message}`));
238
- process.exit(1);
239
- }
240
- });
241
-
242
- // Context compression command
243
- program
244
- .command('compress [mode] [path]')
245
- .description('Compress context for token optimization / 토큰 최적화를 위한 컨텍스트 압축')
246
- .option('--persona, -p', 'Enable persona-aware compression / 페르소나 인식 압축 활성화')
247
- .action(async (mode, path, options) => {
248
- const compressCmd = new CompressCommand();
249
- const args = [];
250
- if (mode) args.push(mode);
251
- if (path) args.push(path);
252
- if (options.persona) args.push('--persona');
253
- await compressCmd.execute(args);
254
- });
255
-
256
-
257
- // Token tracking commands
258
- const token = program.command('token');
259
- token.description('Manage token usage tracking / 토큰 사용량 추적 관리');
260
-
261
- token
262
- .command('status')
263
- .alias('s')
264
- .description('Show token usage status / 토큰 사용 현황 표시')
265
- .action(async () => {
266
- const tokenCmd = new TokenCommand();
267
- await tokenCmd.execute(['status']);
268
- });
269
-
270
- token
271
- .command('report [period]')
272
- .description('Generate usage report / 사용 리포트 생성')
273
- .action(async (period) => {
274
- const tokenCmd = new TokenCommand();
275
- const args = ['report'];
276
- if (period) args.push(period);
277
- await tokenCmd.execute(args);
278
- });
279
-
280
- token
281
- .command('track <input> <output>')
282
- .description('Manually track token usage / 토큰 사용량 수동 기록')
283
- .action(async (input, output) => {
284
- const tokenCmd = new TokenCommand();
285
- await tokenCmd.execute(['track', input, output]);
286
- });
287
-
288
- token
289
- .command('limit <type> <value>')
290
- .description('Set usage limits / 사용 한도 설정')
291
- .action(async (type, value) => {
292
- const tokenCmd = new TokenCommand();
293
- await tokenCmd.execute(['limit', type, value]);
294
- });
295
-
296
- token
297
- .command('reset')
298
- .description('Reset tracking data / 추적 데이터 초기화')
299
- .action(async () => {
300
- const tokenCmd = new TokenCommand();
301
- await tokenCmd.execute(['reset']);
302
- });
96
+ // (removed) create-project command
303
97
 
304
- // Evaluation commands
305
- const evaluate = program.command('evaluate');
306
- evaluate.description('Evaluate AI responses and code quality / AI 응답 및 코드 품질 평가');
98
+ // (removed) compress command
307
99
 
308
- evaluate
309
- .command('response <file>')
310
- .description('Evaluate AI response quality / AI 응답 품질 평가')
311
- .action(async (file) => {
312
- const evaluateCmd = new EvaluateCommand();
313
- await evaluateCmd.execute(['response', file]);
314
- });
315
100
 
316
- evaluate
317
- .command('code <file>')
318
- .description('Evaluate code quality / 코드 품질 평가')
319
- .action(async (file) => {
320
- const evaluateCmd = new EvaluateCommand();
321
- await evaluateCmd.execute(['code', file]);
322
- });
101
+ // (removed) token command group
323
102
 
324
- evaluate
325
- .command('persona <file> <persona>')
326
- .description('Evaluate persona appropriateness / 페르소나 적합성 평가')
327
- .action(async (file, persona) => {
328
- const evaluateCmd = new EvaluateCommand();
329
- await evaluateCmd.execute(['persona', file, persona]);
330
- });
331
-
332
- evaluate
333
- .command('report')
334
- .description('Generate evaluation report / 평가 리포트 생성')
335
- .action(async () => {
336
- const evaluateCmd = new EvaluateCommand();
337
- await evaluateCmd.execute(['report']);
338
- });
339
-
340
- evaluate
341
- .command('criteria')
342
- .description('Show evaluation criteria / 평가 기준 표시')
343
- .action(async () => {
344
- const evaluateCmd = new EvaluateCommand();
345
- await evaluateCmd.execute(['criteria']);
346
- });
103
+ // (removed) evaluate command group
347
104
 
348
105
  // State management commands
349
106
  const state = program.command('state');
@@ -503,303 +260,7 @@ yoloConfig
503
260
  }
504
261
  });
505
262
 
506
- // Checkpoint management commands (YOLO recovery)
507
- const checkpoint = program.command('checkpoint');
508
- checkpoint.description('YOLO checkpoint management / YOLO 체크포인트 관리');
509
-
510
- checkpoint
511
- .command('list')
512
- .alias('ls')
513
- .description('List available checkpoints / 사용 가능한 체크포인트 목록')
514
- .option('--limit <n>', 'Limit number of checkpoints / 체크포인트 수 제한', '10')
515
- .action(async (options) => {
516
- try {
517
- // 프로젝트 루트 찾기
518
- const fs = await import('fs/promises');
519
- const path = await import('path');
520
- let currentDir = process.cwd();
521
-
522
- while (currentDir !== path.parse(currentDir).root) {
523
- try {
524
- await fs.access(path.join(currentDir, '.aiwf'));
525
- break;
526
- } catch {
527
- currentDir = path.dirname(currentDir);
528
- }
529
- }
530
-
531
- const manager = new CheckpointManager(currentDir);
532
- const checkpoints = await manager.listCheckpoints();
533
-
534
- console.log(chalk.bold('📊 체크포인트 목록:'));
535
- console.log('');
536
-
537
- if (checkpoints.length === 0) {
538
- console.log(chalk.yellow('📭 체크포인트가 없습니다.'));
539
- return;
540
- }
541
-
542
- const limit = parseInt(options.limit);
543
- const limitedCheckpoints = checkpoints.slice(0, limit);
544
-
545
- for (const cp of limitedCheckpoints) {
546
- const typeIcon = cp.type === 'session_start' ? '🚀' :
547
- cp.type === 'task_complete' ? '✅' : '🔄';
548
- console.log(`${typeIcon} ${chalk.cyan(cp.id)} - ${chalk.yellow(cp.type)}`);
549
- console.log(` 태스크: ${chalk.blue(cp.tasks_completed)}개 완료`);
550
- console.log('');
551
- }
552
- } catch (error) {
553
- console.error(chalk.red('❌ 체크포인트 목록 조회 실패:'), error.message);
554
- process.exit(1);
555
- }
556
- });
557
-
558
- checkpoint
559
- .command('add [type]')
560
- .alias('create')
561
- .description('Create a checkpoint / 체크포인트 생성')
562
- .option('-m, --message <text>', 'Description for the checkpoint / 체크포인트 설명')
563
- .option('--meta <json>', 'Additional metadata as JSON / 추가 메타데이터(JSON)')
564
- .option('--cleanup <n>', 'Keep only last N checkpoints after creating / 생성 후 최근 N개만 보존')
565
- .action(async (type, options) => {
566
- try {
567
- const fs = await import('fs/promises');
568
- const path = await import('path');
569
- let currentDir = process.cwd();
570
-
571
- // 프로젝트 루트 탐색 (.aiwf 기준)
572
- while (currentDir !== path.parse(currentDir).root) {
573
- try {
574
- await fs.access(path.join(currentDir, '.aiwf'));
575
- break;
576
- } catch {
577
- currentDir = path.dirname(currentDir);
578
- }
579
- }
580
-
581
- const manager = new CheckpointManager(currentDir);
582
- await manager.initialize();
583
-
584
- // 메타데이터 구성
585
- const metadata = {};
586
- if (options.message) metadata.message = options.message;
587
- if (options.meta) {
588
- try {
589
- const parsed = JSON.parse(options.meta);
590
- Object.assign(metadata, parsed);
591
- } catch (e) {
592
- console.error(chalk.red('❌ --meta 값이 올바른 JSON 형식이 아닙니다.'));
593
- process.exit(1);
594
- }
595
- }
596
-
597
- const cpType = type || 'manual';
598
- const checkpointId = await manager.createCheckpoint(cpType, metadata);
599
-
600
- console.log(chalk.green('✅ 체크포인트 생성 완료!'));
601
- console.log(` ID: ${chalk.cyan(checkpointId)} 유형: ${chalk.yellow(cpType)}`);
602
- if (metadata.message) {
603
- console.log(` 메시지: ${chalk.blue(metadata.message)}`);
604
- }
605
-
606
- if (options.cleanup) {
607
- const keep = parseInt(options.cleanup, 10);
608
- if (!Number.isNaN(keep) && keep > 0) {
609
- await manager.cleanup(keep);
610
- console.log(`🧹 최근 ${chalk.cyan(keep)}개만 보존하도록 정리했습니다.`);
611
- } else {
612
- console.log(chalk.yellow('⚠️ --cleanup 값이 유효하지 않아 정리를 건너뜁니다. 정수로 입력하세요.'));
613
- }
614
- }
615
- } catch (error) {
616
- console.error(chalk.red('❌ 체크포인트 생성 실패:'), error.message);
617
- process.exit(1);
618
- }
619
- });
620
-
621
- checkpoint
622
- .command('restore <checkpointId>')
623
- .description('Restore from checkpoint / 체크포인트에서 복구')
624
- .action(async (checkpointId) => {
625
- try {
626
- const fs = await import('fs/promises');
627
- const path = await import('path');
628
- let currentDir = process.cwd();
629
-
630
- while (currentDir !== path.parse(currentDir).root) {
631
- try {
632
- await fs.access(path.join(currentDir, '.aiwf'));
633
- break;
634
- } catch {
635
- currentDir = path.dirname(currentDir);
636
- }
637
- }
638
-
639
- const manager = new CheckpointManager(currentDir);
640
- await manager.initialize();
641
-
642
- console.log(chalk.blue(`🔄 체크포인트 ${checkpointId}에서 복구 중...`));
643
-
644
- const result = await manager.restoreFromCheckpoint(checkpointId);
645
-
646
- if (result.success) {
647
- console.log(chalk.green('✅ 체크포인트 복구 성공!'));
648
- console.log(` 세션 ID: ${chalk.cyan(result.checkpoint.state_snapshot.session_id)}`);
649
- console.log(` 스프린트: ${chalk.blue(result.checkpoint.state_snapshot.sprint_id || 'N/A')}`);
650
- console.log('');
651
- console.log(chalk.green('🚀 복구 완료! YOLO 모드를 다시 실행할 수 있습니다.'));
652
- }
653
- } catch (error) {
654
- console.error(chalk.red('❌ 체크포인트 복구 실패:'), error.message);
655
- process.exit(1);
656
- }
657
- });
658
-
659
- checkpoint
660
- .command('status')
661
- .description('Show current YOLO session status / 현재 YOLO 세션 상태')
662
- .action(async () => {
663
- try {
664
- const fs = await import('fs/promises');
665
- const path = await import('path');
666
- let currentDir = process.cwd();
667
-
668
- while (currentDir !== path.parse(currentDir).root) {
669
- try {
670
- await fs.access(path.join(currentDir, '.aiwf'));
671
- break;
672
- } catch {
673
- currentDir = path.dirname(currentDir);
674
- }
675
- }
676
-
677
- const manager = new CheckpointManager(currentDir);
678
- await manager.loadState();
679
-
680
- console.log(chalk.bold('📊 YOLO 세션 상태:'));
681
- console.log('');
682
-
683
- if (!manager.currentState.session_id) {
684
- console.log(chalk.yellow('📭 활성 YOLO 세션이 없습니다.'));
685
- return;
686
- }
687
-
688
- console.log(`세션 ID: ${chalk.cyan(manager.currentState.session_id)}`);
689
- console.log(`스프린트: ${chalk.blue(manager.currentState.sprint_id || 'N/A')}`);
690
- console.log(`완료된 태스크: ${chalk.green(manager.currentState.completed_tasks.length)}개`);
691
- console.log(`체크포인트: ${chalk.blue(manager.currentState.checkpoints.length)}개`);
692
- } catch (error) {
693
- console.error(chalk.red('❌ 상태 확인 실패:'), error.message);
694
- process.exit(1);
695
- }
696
- });
697
-
698
- // 체크포인트 리포트 생성
699
- checkpoint
700
- .command('report')
701
- .description('Generate progress report / 진행 상황 리포트 생성')
702
- .action(async () => {
703
- try {
704
- const fs = await import('fs/promises');
705
- const path = await import('path');
706
- let currentDir = process.cwd();
707
-
708
- while (currentDir !== path.parse(currentDir).root) {
709
- try {
710
- await fs.access(path.join(currentDir, '.aiwf'));
711
- break;
712
- } catch {
713
- currentDir = path.dirname(currentDir);
714
- }
715
- }
716
-
717
- const manager = new CheckpointManager(currentDir);
718
- await manager.loadState();
719
-
720
- console.log(chalk.blue('📊 진행 상황 리포트 생성 중...'));
721
- console.log('');
722
-
723
- const report = await manager.generateProgressReport();
724
-
725
- console.log(chalk.bold('🎯 YOLO 세션 리포트'));
726
- console.log(''.padEnd(50, '='));
727
- console.log('');
728
-
729
- // 세션 정보
730
- console.log(chalk.bold('📋 세션 정보:'));
731
- console.log(` ID: ${chalk.cyan(report.session.id)}`);
732
- console.log(` 시작: ${chalk.gray(new Date(report.session.started).toLocaleString())}`);
733
- console.log(` 스프린트: ${chalk.blue(report.session.sprint || 'N/A')}`);
734
- console.log('');
735
-
736
- // 진행 상황
737
- console.log(chalk.bold('📈 진행 상황:'));
738
- console.log(` 완료: ${chalk.green(report.progress.completed)}개`);
739
- console.log(` 실패: ${chalk.red(report.progress.failed)}개`);
740
- console.log(` 건너뜀: ${chalk.yellow(report.progress.skipped)}개`);
741
- console.log('');
742
-
743
- // 성능 지표
744
- console.log(chalk.bold('⏱️ 성능 지표:'));
745
- console.log(` 총 시간: ${chalk.blue(report.performance.total_time)}`);
746
- console.log(` 평균 태스크 시간: ${chalk.blue(report.performance.avg_task_time)}`);
747
- console.log(` 성공률: ${chalk.green(report.performance.success_rate)}`);
748
-
749
- } catch (error) {
750
- console.error(chalk.red('❌ 리포트 생성 실패:'), error.message);
751
- process.exit(1);
752
- }
753
- });
754
-
755
- // 체크포인트 정리
756
- checkpoint
757
- .command('clean')
758
- .description('Clean old checkpoints / 오래된 체크포인트 정리')
759
- .option('--keep <n>', 'Number of checkpoints to keep / 유지할 체크포인트 수', '10')
760
- .option('--dry-run', 'Preview without deletion / 실제 삭제 없이 미리보기')
761
- .action(async (options) => {
762
- try {
763
- const fs = await import('fs/promises');
764
- const path = await import('path');
765
- let currentDir = process.cwd();
766
-
767
- while (currentDir !== path.parse(currentDir).root) {
768
- try {
769
- await fs.access(path.join(currentDir, '.aiwf'));
770
- break;
771
- } catch {
772
- currentDir = path.dirname(currentDir);
773
- }
774
- }
775
-
776
- const manager = new CheckpointManager(currentDir);
777
- const keepLast = parseInt(options.keep);
778
-
779
- console.log(chalk.blue(`🧹 체크포인트 정리 중... (최근 ${keepLast}개 유지)`));
780
-
781
- if (options.dryRun) {
782
- console.log(chalk.yellow('🔍 드라이런 모드: 실제 삭제는 수행하지 않습니다.'));
783
- const checkpoints = await manager.listCheckpoints();
784
- if (checkpoints.length <= keepLast) {
785
- console.log(chalk.green('✅ 정리할 체크포인트가 없습니다.'));
786
- } else {
787
- const toDelete = checkpoints.slice(keepLast);
788
- console.log(chalk.yellow(`삭제 예정 체크포인트 (${toDelete.length}개):`));
789
- for (const cp of toDelete) {
790
- console.log(` ${chalk.red('🗑️')} ${chalk.cyan(cp.id)}`);
791
- }
792
- }
793
- } else {
794
- await manager.cleanup(keepLast);
795
- console.log(chalk.green('✅ 체크포인트 정리 완료!'));
796
- }
797
-
798
- } catch (error) {
799
- console.error(chalk.red('❌ 체크포인트 정리 실패:'), error.message);
800
- process.exit(1);
801
- }
802
- });
263
+ // (removed) checkpoint command group
803
264
 
804
265
  // Engineering Guard commands (오버엔지니어링 방지)
805
266
  const guard = program.command('guard');