aiwf 0.3.2 → 0.3.4
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/.aiwf/config/language.json +1 -1
- package/.aiwf/installed.flag +1 -0
- package/.aiwf/sessions/session_1752877859489_1t7n2fhdb.json +7 -0
- package/.aiwf/sessions/session_1752877859515_cwdv211ry.json +7 -0
- package/.aiwf/sessions/session_1752877860664_huziadmbo.json +7 -0
- package/.aiwf/sessions/session_1752877860666_kyr5u1np6.json +7 -0
- package/.aiwf/sessions/session_1752877861848_9yinepw3t.json +7 -0
- package/.aiwf/sessions/session_1752877861874_y32sputuc.json +7 -0
- package/.aiwf/sessions/session_1752877862685_ivxbl5rhz.json +7 -0
- package/.aiwf/sessions/session_1752877862820_wnq4glvxi.json +7 -0
- package/.aiwf/sessions/session_1752877864632_3ebnpaelb.json +7 -0
- package/.aiwf/sessions/session_1752877864879_b9zgjcb7d.json +7 -0
- package/.aiwf/sessions/session_1752877865533_x14m1vodi.json +7 -0
- package/.aiwf/sessions/session_1752877865562_gkoh19n7d.json +7 -0
- package/.aiwf/sessions/session_1752877866333_wp8qpdcoh.json +7 -0
- package/.aiwf/sessions/session_1752877866509_dawntfpab.json +7 -0
- package/.aiwf/sessions/session_1752877866890_plc5vfucl.json +7 -0
- package/.aiwf/sessions/session_1752877866895_ga8hmq3oi.json +7 -0
- package/.aiwf/sessions/session_1752877867761_ayjp4v5f5.json +7 -0
- package/.aiwf/sessions/session_1752877867892_lfz6jy252.json +7 -0
- package/.aiwf/sessions/session_1752877868139_7bqd9ubli.json +7 -0
- package/.aiwf/sessions/session_1752877868162_zq3ofjbsh.json +7 -0
- package/.aiwf/sessions/session_1752877869054_7rlgm9jt6.json +7 -0
- package/.aiwf/sessions/session_1752877869477_ax3nhbxzr.json +7 -0
- package/.aiwf/sessions/session_1752877870095_6hgp4vl1e.json +7 -0
- package/.aiwf/sessions/session_1752877870381_qfcrdg4li.json +7 -0
- package/.aiwf/sessions/session_1752877871895_pgd5vllhz.json +7 -0
- package/.aiwf/sessions/session_1752877872199_jbhv2g2da.json +7 -0
- package/.aiwf/sessions/session_1752877872680_x04wpffu6.json +7 -0
- package/.aiwf/sessions/session_1752877872895_3y4vbeauo.json +7 -0
- package/.aiwf/sessions/session_1752877873178_3maolzc6b.json +7 -0
- package/.aiwf/sessions/session_1752877873180_ytm83j07f.json +7 -0
- package/.aiwf/sessions/session_1752877874217_dp56c9t42.json +7 -0
- package/.aiwf/sessions/session_1752877874415_epwp1g1og.json +7 -0
- package/.aiwf/sessions/session_1752877874454_heicyuryb.json +7 -0
- package/.aiwf/sessions/session_1752877874869_1c2illeu5.json +7 -0
- package/.aiwf/sessions/session_1752877874879_k1vo4vxyx.json +7 -0
- package/.aiwf/sessions/session_1752877874913_bwgyiz9bp.json +7 -0
- package/.aiwf/sessions/session_1752877876218_44807kztz.json +7 -0
- package/.aiwf/sessions/session_1752877876515_qkhjv5kpw.json +7 -0
- package/.aiwf/sessions/session_1752877876543_p605aud1m.json +7 -0
- package/.aiwf/sessions/session_1752877876819_l65w7ifck.json +7 -0
- package/.aiwf/sessions/session_1752877876867_xrhzss4we.json +7 -0
- package/.aiwf/sessions/session_1752877876872_u7aso54qb.json +7 -0
- package/.aiwf/sessions/session_1752877877705_telnfg4o6.json +7 -0
- package/.aiwf/sessions/session_1752877878285_6s45im2ib.json +7 -0
- package/.aiwf/sessions/session_1752877878506_v0dvguqhz.json +7 -0
- package/.aiwf/sessions/session_1752877878581_3ri3yc66a.json +7 -0
- package/.aiwf/sessions/session_1752877878756_a82x9s2pd.json +7 -0
- package/.aiwf/sessions/session_1752877878886_20pjsfour.json +7 -0
- package/.aiwf/sessions/session_1752877880266_fm1ydjw0g.json +7 -0
- package/.aiwf/sessions/session_1752877881149_xbat4z03d.json +7 -0
- package/.aiwf/sessions/session_1752877881551_qy5sic9qs.json +7 -0
- package/.aiwf/sessions/session_1752877881554_24ugd96wu.json +7 -0
- package/.aiwf/sessions/session_1752877881797_e9mm25uh0.json +7 -0
- package/.aiwf/sessions/session_1752877881822_bxvjj8c9g.json +7 -0
- package/.aiwf/sessions/session_1752877881890_jv7l6jve3.json +7 -0
- package/.aiwf/sessions/session_1752877881991_f0qugdtcq.json +7 -0
- package/.aiwf/sessions/session_1752877883387_0bvw9rvnx.json +7 -0
- package/.aiwf/sessions/session_1752877883820_q6g2md2up.json +7 -0
- package/.aiwf/sessions/session_1752877884393_sqr7trvjl.json +7 -0
- package/.aiwf/sessions/session_1752877884500_whtypmzlf.json +7 -0
- package/.aiwf/sessions/session_1752877884645_y9mvvxli1.json +7 -0
- package/.aiwf/sessions/session_1752877884733_hk46eenel.json +7 -0
- package/.aiwf/sessions/session_1752877884738_c62j6214r.json +7 -0
- package/.aiwf/sessions/session_1752877884771_temhxehoz.json +7 -0
- package/.aiwf/sessions/session_1752877885643_6v5fcktc7.json +7 -0
- package/.aiwf/sessions/session_1752877886426_ee8di2fqh.json +7 -0
- package/.aiwf/sessions/session_1752877886549_3xj6tdoew.json +7 -0
- package/.aiwf/sessions/session_1752877886604_aj80yyfco.json +7 -0
- package/.aiwf/sessions/session_1752877886702_2b8841vyg.json +7 -0
- package/.aiwf/sessions/session_1752877886712_ntqc8b8bz.json +7 -0
- package/.aiwf/sessions/session_1752877886968_946m8tbw6.json +7 -0
- package/.aiwf/sessions/session_1752877887008_wg6zfg8dn.json +7 -0
- package/.aiwf/sessions/session_1752877888479_ciiu2qiqs.json +7 -0
- package/.aiwf/sessions/session_1752877889330_ravg8l66k.json +7 -0
- package/.aiwf/sessions/session_1752877889542_7zepkhjkc.json +7 -0
- package/.aiwf/sessions/session_1752877889638_ev4htqiu0.json +7 -0
- package/.aiwf/sessions/session_1752877889956_szphy2qma.json +7 -0
- package/.aiwf/sessions/session_1752877890220_o6aaa57tt.json +7 -0
- package/.aiwf/sessions/session_1752877890527_v2loy5vu1.json +7 -0
- package/.aiwf/sessions/session_1752877890572_cwq8fiuma.json +7 -0
- package/.aiwf/sessions/session_1752877892200_sgcwq1alt.json +7 -0
- package/.aiwf/sessions/session_1752877892268_v8kexpbc5.json +7 -0
- package/.aiwf/sessions/session_1752877892384_1gbbgrp4y.json +7 -0
- package/.aiwf/sessions/session_1752877893568_9p2n5p31a.json +7 -0
- package/.aiwf/sessions/session_1752877893727_un34a5tvp.json +7 -0
- package/.aiwf/sessions/session_1752877893778_01j79sw9i.json +7 -0
- package/.aiwf/sessions/session_1752877894053_jrhba6wko.json +7 -0
- package/.aiwf/sessions/session_1752877894082_x3bghawox.json +7 -0
- package/.aiwf/sessions/session_1752877894500_iytiav2ku.json +7 -0
- package/.aiwf/sessions/session_1752877894667_ucn0gc2ge.json +7 -0
- package/.aiwf/test-results-s02.json +4 -4
- package/.claude/commands/aiwf/aiwf_changelog.md +82 -0
- package/.claude/commands/aiwf/aiwf_code_review.md +88 -0
- package/.claude/commands/aiwf/aiwf_commit.md +160 -0
- package/.claude/commands/aiwf/aiwf_compress_context.md +116 -0
- package/.claude/commands/aiwf/aiwf_create_feature_ledger.md +54 -0
- package/.claude/commands/aiwf/aiwf_create_general_task.md +147 -0
- package/.claude/commands/aiwf/aiwf_create_milestone_plan.md +194 -0
- package/.claude/commands/aiwf/aiwf_create_prd.md +280 -0
- package/.claude/commands/aiwf/aiwf_create_sprint_tasks.md +189 -0
- package/.claude/commands/aiwf/aiwf_create_sprints_from_milestone.md +121 -0
- package/.claude/commands/aiwf/aiwf_default_mode.md +44 -0
- package/.claude/commands/aiwf/aiwf_discuss_review.md +29 -0
- package/.claude/commands/aiwf/aiwf_do_task.md +109 -0
- package/.claude/commands/aiwf/aiwf_docs.md +225 -0
- package/.claude/commands/aiwf/aiwf_get_feature_details.md +78 -0
- package/.claude/commands/aiwf/aiwf_infinite.md +202 -0
- package/.claude/commands/aiwf/aiwf_initialize.md +134 -0
- package/.claude/commands/aiwf/aiwf_issue_create.md +65 -0
- package/.claude/commands/aiwf/aiwf_link_feature_to_milestone.md +57 -0
- package/.claude/commands/aiwf/aiwf_list_features.md +54 -0
- package/.claude/commands/aiwf/aiwf_mermaid.md +272 -0
- package/.claude/commands/aiwf/aiwf_persona_architect.md +48 -0
- package/.claude/commands/aiwf/aiwf_persona_backend.md +37 -0
- package/.claude/commands/aiwf/aiwf_persona_data_analyst.md +37 -0
- package/.claude/commands/aiwf/aiwf_persona_frontend.md +37 -0
- package/.claude/commands/aiwf/aiwf_persona_security.md +48 -0
- package/.claude/commands/aiwf/aiwf_persona_status.md +50 -0
- package/.claude/commands/aiwf/aiwf_pr_create.md +76 -0
- package/.claude/commands/aiwf/aiwf_prime.md +9 -0
- package/.claude/commands/aiwf/aiwf_project_review.md +261 -0
- package/.claude/commands/aiwf/aiwf_switch_language.md +160 -0
- package/.claude/commands/aiwf/aiwf_test.md +124 -0
- package/.claude/commands/aiwf/aiwf_testing_review.md +198 -0
- package/.claude/commands/aiwf/aiwf_tm-run-all-subtask.md +210 -0
- package/.claude/commands/aiwf/aiwf_ultrathink_code_advanced.md +460 -0
- package/.claude/commands/aiwf/aiwf_ultrathink_code_basic.md +165 -0
- package/.claude/commands/aiwf/aiwf_ultrathink_general.md +305 -0
- package/.claude/commands/aiwf/aiwf_update_docs_kr.md +25 -0
- package/.claude/commands/aiwf/aiwf_update_feature_status.md +53 -0
- package/.claude/commands/aiwf/aiwf_yolo.md +300 -0
- package/.eslintrc.json +26 -0
- package/.prettierrc +10 -0
- package/CLAUDE.md +154 -54
- package/README.ko.md +25 -0
- package/README.md +25 -0
- package/TEST_RECOVERY_PLAN.md +68 -0
- package/docs/CLEANUP_RECOMMENDATIONS.md +86 -0
- package/docs/CLI_USAGE_GUIDE.md +479 -0
- package/package.json +9 -9
- package/scripts/update-feature-status.js +70 -0
- package/{lib → src/cli}/cache-cli.js +4 -4
- package/src/cli/index.js +165 -0
- package/{language-cli.js → src/cli/language-cli.js} +11 -4
- package/src/commands/cache-templates.js +209 -0
- package/src/commands/create-offline.js +86 -0
- package/src/commands/create-project.js +151 -0
- package/src/lib/backup-manager.js +270 -0
- package/src/lib/file-downloader.js +208 -0
- package/src/lib/installer.js +676 -0
- package/src/lib/rollback-manager.js +418 -0
- package/src/lib/validator.js +561 -0
- package/src/utils/git-integration.js +173 -0
- package/{language-utils.js → src/utils/language-utils.js} +2 -1
- package/src/utils/messages.js +136 -0
- package/src/utils/paths.js +130 -0
- package/tests/application.test.js +2 -2
- package/tests/installer.test.js +2 -2
- package/tests/integration/ai-persona-system.test.js +4 -4
- package/tests/integration/test-persona-system/docs/README.md +1 -0
- package/tests/integration/test-persona-system/package.json +1 -0
- package/tests/integration/test-persona-system/src/auth.js +1 -0
- package/tests/integration/test-persona-system/src/index.js +1 -0
- package/tests/integration/test-persona-system/test/test.js +1 -0
- package/tests/language-utils.test.js +1 -1
- package/tests/temp_invalid_json/invalid.json +1 -0
- package/tests/unit/ai-persona-manager.test.js +7 -7
- package/.aiwf/05_DOCUMENTATION/performance-report.md +0 -33
- package/.aiwf/test-cache/86c7f9e80251abb8bedd58953ab0d1779e46b4f43ea33b63bffdb778106373b0.json +0 -6
- package/.aiwf/test-cache/9e252a90b80fce0585d7ed0646e7a9b4343e109f661f42a3ae678ba1ec5e22c7.json +0 -7
- package/.aiwf/token-data/alerts.json +0 -293
- package/.aiwf/token-data/monitor-config.json +0 -12
- package/CHANGELOG_M02.md +0 -52
- package/claude-code/aiwf/ko/bin/aiwf-create.js +0 -56
- package/claude-code/aiwf/ko/bin/aiwf.js +0 -21
- package/claude-code/aiwf/ko/docs/00_PROJECT_MANIFEST.md +0 -183
- package/claude-code/aiwf/ko/docs/ARCHITECTURE.md +0 -121
- package/claude-code/aiwf/ko/docs/FEATURE_LEDGER_ADVANCED_USE_CASES.md +0 -412
- package/claude-code/aiwf/ko/docs/FEATURE_LEDGER_API_REFERENCE.md +0 -361
- package/claude-code/aiwf/ko/docs/FEATURE_LEDGER_COMMANDS_GUIDE.md +0 -254
- package/claude-code/aiwf/ko/docs/FEATURE_LEDGER_FAQ.md +0 -365
- package/claude-code/aiwf/ko/docs/FEATURE_LEDGER_SYSTEM_OVERVIEW.md +0 -305
- package/claude-code/aiwf/ko/docs/FEATURE_LEDGER_USER_GUIDE.md +0 -416
- package/claude-code/aiwf/ko/docs/FEATURE_LEDGER_/354/213/234/354/236/221_/352/260/200/354/235/264/353/223/234.md +0 -247
- package/claude-code/aiwf/ko/token-data/alerts.json +0 -293
- package/claude-code/aiwf/ko/token-data/monitor-config.json +0 -12
- package/docs/m02-dod-checklist.md +0 -125
- package/docs/m02-gap-analysis.md +0 -214
- package/docs/m02-milestone-completion-report.md +0 -186
- package/docs/m02-milestone-executive-summary.md +0 -68
- package/index.js +0 -1947
- package/lib/cache-integration.js +0 -401
- package/lib/file-batch-processor.js +0 -401
- package/lib/performance-benchmark.js +0 -621
- package/lib/template-manager.js +0 -310
- package/scripts/validate-commands.cjs +0 -338
- /package/{.aiwf/.claude → .claude}/commands/aiwf/aiwf_compress_aggressive_persona.md +0 -0
- /package/{.aiwf/.claude → .claude}/commands/aiwf/aiwf_compress_minimal_persona.md +0 -0
- /package/{.aiwf/.claude → .claude}/commands/aiwf/aiwf_compress_stats.md +0 -0
- /package/{.aiwf/.claude → .claude}/commands/aiwf/aiwf_compress_with_persona.md +0 -0
- /package/{.aiwf/.claude → .claude}/commands/aiwf/aiwf_evaluate.md +0 -0
- /package/{lib → src/lib}/ai-persona-manager.js +0 -0
- /package/{lib → src/lib}/cache-system.js +0 -0
- /package/{lib → src/lib}/context-engine.js +0 -0
- /package/{lib → src/lib}/memory-profiler.js +0 -0
- /package/{lib → src/lib}/metrics-collector.js +0 -0
- /package/{lib → src/lib}/offline-detector.js +0 -0
- /package/{lib → src/lib}/task-analyzer.js +0 -0
- /package/{lib → src/lib}/template-cache-system.js +0 -0
- /package/{lib → src/lib}/template-downloader.js +0 -0
- /package/{lib → src/lib}/template-version-manager.js +0 -0
- /package/{lib → src/lib}/token-optimizer.js +0 -0
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { promises as fs } from 'fs';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
import { exec, execSync } from 'child_process';
|
|
6
|
+
import { promisify } from 'util';
|
|
7
|
+
import { fileURLToPath } from 'url';
|
|
8
|
+
|
|
9
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
10
|
+
const execAsync = promisify(exec);
|
|
11
|
+
|
|
12
|
+
// AIWF 경로 설정
|
|
13
|
+
const AIWF_ROOT = path.join(process.cwd(), '.aiwf');
|
|
14
|
+
const FEATURE_LEDGERS_PATH = path.join(AIWF_ROOT, '06_FEATURE_LEDGERS');
|
|
15
|
+
const ACTIVE_PATH = path.join(FEATURE_LEDGERS_PATH, 'active');
|
|
16
|
+
|
|
17
|
+
// 커밋 메시지에서 Feature ID를 추출하는 정규식 패턴들
|
|
18
|
+
const FEATURE_ID_PATTERNS = [
|
|
19
|
+
/FL\d{3}(?!\d)/, // FL001 (not followed by digit)
|
|
20
|
+
/\[FL\d{3}\]/, // [FL001]
|
|
21
|
+
/\(FL\d{3}\)/, // (FL001)
|
|
22
|
+
/(feat|fix|docs|style|refactor|test|chore)\(FL\d{3}\)/, // feat(FL001)
|
|
23
|
+
/FL\d{3}:/, // FL001:
|
|
24
|
+
/#FL\d{3}/, // #FL001
|
|
25
|
+
/relates to FL\d{3}/i, // relates to FL001
|
|
26
|
+
];
|
|
27
|
+
|
|
28
|
+
// Feature ID 추출 함수
|
|
29
|
+
function extractFeatureId(text) {
|
|
30
|
+
for (const pattern of FEATURE_ID_PATTERNS) {
|
|
31
|
+
const match = text.match(pattern);
|
|
32
|
+
if (match) {
|
|
33
|
+
// 순수 Feature ID만 추출 (FL###)
|
|
34
|
+
const idMatch = match[0].match(/FL\d{3}/);
|
|
35
|
+
if (idMatch) {
|
|
36
|
+
return idMatch[0];
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Feature 파일 경로 가져오기
|
|
44
|
+
async function getFeaturePath(featureId) {
|
|
45
|
+
// active 폴더에서 먼저 확인
|
|
46
|
+
const activePath = path.join(ACTIVE_PATH, `${featureId}_*.md`);
|
|
47
|
+
try {
|
|
48
|
+
const files = await fs.readdir(ACTIVE_PATH);
|
|
49
|
+
const featureFile = files.find(file => file.startsWith(`${featureId}_`));
|
|
50
|
+
if (featureFile) {
|
|
51
|
+
return path.join(ACTIVE_PATH, featureFile);
|
|
52
|
+
}
|
|
53
|
+
} catch (error) {
|
|
54
|
+
// 폴더가 없거나 읽기 실패 시 계속 진행
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// completed, archived 폴더도 확인
|
|
58
|
+
const otherPaths = ['completed', 'archived'];
|
|
59
|
+
for (const folder of otherPaths) {
|
|
60
|
+
const folderPath = path.join(FEATURE_LEDGERS_PATH, folder);
|
|
61
|
+
try {
|
|
62
|
+
const files = await fs.readdir(folderPath);
|
|
63
|
+
const featureFile = files.find(file => file.startsWith(`${featureId}_`));
|
|
64
|
+
if (featureFile) {
|
|
65
|
+
return path.join(folderPath, featureFile);
|
|
66
|
+
}
|
|
67
|
+
} catch (error) {
|
|
68
|
+
// 폴더가 없거나 읽기 실패 시 계속 진행
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Git 커밋 정보 가져오기
|
|
76
|
+
async function getCommitInfo(commitHash) {
|
|
77
|
+
try {
|
|
78
|
+
const { stdout } = await execAsync(`git show --no-patch --format="%H|%h|%an|%ae|%ad|%s" ${commitHash}`);
|
|
79
|
+
const [hash, shortHash, author, email, date, message] = stdout.trim().split('|');
|
|
80
|
+
return {
|
|
81
|
+
hash,
|
|
82
|
+
shortHash,
|
|
83
|
+
author,
|
|
84
|
+
email,
|
|
85
|
+
date: new Date(date).toISOString(),
|
|
86
|
+
message
|
|
87
|
+
};
|
|
88
|
+
} catch (error) {
|
|
89
|
+
console.error(`Error getting commit info for ${commitHash}:`, error.message);
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// YAML frontmatter 파싱
|
|
95
|
+
function parseYamlFrontmatter(content) {
|
|
96
|
+
const match = content.match(/^---\n([\s\S]*?)\n---/);
|
|
97
|
+
if (!match) return null;
|
|
98
|
+
|
|
99
|
+
const yaml = match[1];
|
|
100
|
+
const metadata = {};
|
|
101
|
+
|
|
102
|
+
// 간단한 YAML 파싱 (복잡한 구조는 제외)
|
|
103
|
+
yaml.split('\n').forEach(line => {
|
|
104
|
+
const keyValue = line.match(/^(\w+):\s*(.*)$/);
|
|
105
|
+
if (keyValue) {
|
|
106
|
+
const [_, key, value] = keyValue;
|
|
107
|
+
metadata[key] = value.trim();
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
return metadata;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// YAML frontmatter 업데이트
|
|
115
|
+
function updateYamlFrontmatter(content, metadata) {
|
|
116
|
+
const existingMatch = content.match(/^---\n([\s\S]*?)\n---/);
|
|
117
|
+
|
|
118
|
+
let yamlLines = [];
|
|
119
|
+
Object.entries(metadata).forEach(([key, value]) => {
|
|
120
|
+
if (value !== undefined && value !== null) {
|
|
121
|
+
yamlLines.push(`${key}: ${value}`);
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
const newYaml = `---\n${yamlLines.join('\n')}\n---`;
|
|
126
|
+
|
|
127
|
+
if (existingMatch) {
|
|
128
|
+
return content.replace(/^---\n[\s\S]*?\n---/, newYaml);
|
|
129
|
+
} else {
|
|
130
|
+
return `${newYaml}\n\n${content}`;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Git 로그에서 Feature 관련 커밋 가져오기
|
|
135
|
+
async function getFeatureCommits(featureId, since = null) {
|
|
136
|
+
try {
|
|
137
|
+
let gitCommand = `git log --grep="${featureId}" --format="%H|%h|%an|%ad|%s"`;
|
|
138
|
+
if (since) {
|
|
139
|
+
gitCommand += ` --since="${since}"`;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const { stdout } = await execAsync(gitCommand);
|
|
143
|
+
if (!stdout.trim()) return [];
|
|
144
|
+
|
|
145
|
+
const commits = stdout.trim().split('\n').map(line => {
|
|
146
|
+
const [hash, shortHash, author, date, message] = line.split('|');
|
|
147
|
+
return {
|
|
148
|
+
hash,
|
|
149
|
+
shortHash,
|
|
150
|
+
author,
|
|
151
|
+
date: new Date(date).toISOString(),
|
|
152
|
+
message
|
|
153
|
+
};
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
return commits;
|
|
157
|
+
} catch (error) {
|
|
158
|
+
console.error(`Error getting commits for ${featureId}:`, error.message);
|
|
159
|
+
return [];
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export {
|
|
164
|
+
extractFeatureId,
|
|
165
|
+
getFeaturePath,
|
|
166
|
+
getCommitInfo,
|
|
167
|
+
parseYamlFrontmatter,
|
|
168
|
+
updateYamlFrontmatter,
|
|
169
|
+
getFeatureCommits,
|
|
170
|
+
AIWF_ROOT,
|
|
171
|
+
FEATURE_LEDGERS_PATH,
|
|
172
|
+
ACTIVE_PATH
|
|
173
|
+
};
|
|
@@ -7,11 +7,12 @@
|
|
|
7
7
|
|
|
8
8
|
import fs from 'fs/promises';
|
|
9
9
|
import path from 'path';
|
|
10
|
+
import { FILES } from './paths.js';
|
|
10
11
|
|
|
11
12
|
// 지원되는 언어 목록
|
|
12
13
|
export const SUPPORTED_LANGUAGES = ['ko', 'en'];
|
|
13
14
|
export const DEFAULT_LANGUAGE = 'en';
|
|
14
|
-
export const LANGUAGE_CONFIG_PATH =
|
|
15
|
+
export const LANGUAGE_CONFIG_PATH = FILES.LANGUAGE_CONFIG;
|
|
15
16
|
|
|
16
17
|
/**
|
|
17
18
|
* 언어 감지 알고리즘
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Localized messages for AIWF installer
|
|
3
|
+
*/
|
|
4
|
+
export const messages = {
|
|
5
|
+
ko: {
|
|
6
|
+
welcome: '\n🎉 AIWF에 오신 것을 환영합니다!\n',
|
|
7
|
+
description: '이 설치 프로그램은 AIWF AI 프롬프트 프레임워크를 설정합니다',
|
|
8
|
+
optimized: '특별히 Claude Code 에 최적화 되어있습니다.\n',
|
|
9
|
+
selectLanguage: 'Please select language / 언어를 선택해주세요:',
|
|
10
|
+
korean: '한국어 (Korean)',
|
|
11
|
+
english: 'English',
|
|
12
|
+
existingDetected: '기존 AIWF 설치가 감지되었습니다. 무엇을 하시겠습니까?',
|
|
13
|
+
updateOption: '업데이트 (명령어와 문서만 업데이트하고 작업 내용은 보존)',
|
|
14
|
+
skipOption: '설치 건너뛰기',
|
|
15
|
+
cancelOption: '취소',
|
|
16
|
+
installCancelled: '\n설치가 취소되었습니다.',
|
|
17
|
+
backingUp: '기존 명령어 및 문서 백업 중...',
|
|
18
|
+
fetching: 'GitHub에서 AIWF 프레임워크를 가져오는 중...',
|
|
19
|
+
downloading: 'AIWF 프레임워크 파일을 다운로드하는 중...',
|
|
20
|
+
updatingDocs: '문서를 업데이트하는 중...',
|
|
21
|
+
downloadingCommands: 'AIWF 명령어를 새로 다운로드하는 중...',
|
|
22
|
+
updateSuccess: '✅ AIWF 프레임워크가 성공적으로 업데이트되었습니다!',
|
|
23
|
+
installSuccess: '✅ AIWF 프레임워크가 성공적으로 설치되었습니다!',
|
|
24
|
+
enjoy: '\nEnjoy AIWF! 🚀\n',
|
|
25
|
+
backupComplete: '{count}개 파일 백업 완료 (*.bak)',
|
|
26
|
+
noFilesToBackup: '백업할 기존 파일이 없습니다',
|
|
27
|
+
backupFailed: '백업 실패',
|
|
28
|
+
downloadingFile: '{path} 다운로드 중...',
|
|
29
|
+
downloadingTemplates: '템플릿 디렉토리를 다운로드 중...',
|
|
30
|
+
templatesNotFound: '템플릿 디렉토리를 찾을 수 없어 건너뜁니다...',
|
|
31
|
+
deletingOldCommands: '기존 AIWF 명령어 폴더를 삭제하는 중...',
|
|
32
|
+
commandsNotFound: '명령어 디렉토리를 찾을 수 없어 건너뜁니다...',
|
|
33
|
+
downloadingRulesGlobal: 'rules/global 폴더를 다운로드 중...',
|
|
34
|
+
rulesGlobalNotFound: 'rules/global 폴더를 찾을 수 없어 건너뜁니다...',
|
|
35
|
+
downloadingRulesManual: 'rules/manual 폴더를 다운로드 중...',
|
|
36
|
+
rulesManualNotFound: 'rules/manual 폴더를 찾을 수 없어 건너뜁니다...',
|
|
37
|
+
updateHistory: '🔄 업데이트 내역:',
|
|
38
|
+
updatedCommands: '내의 명령어',
|
|
39
|
+
updatedDocs: '문서 (CLAUDE.md 파일)',
|
|
40
|
+
workPreserved: '💾 작업 내용은 보존되었습니다:',
|
|
41
|
+
allFilesPreserved: '모든 작업, 스프린트, 및 프로젝트 파일이 변경되지 않음',
|
|
42
|
+
backupCreated: '백업은 *.bak 파일로 만들어짐',
|
|
43
|
+
structureCreated: '📁 생성된 구조:',
|
|
44
|
+
aiwfRoot: '프로젝트 관리 루트',
|
|
45
|
+
claudeCommands: 'Claude 사용자 명령어',
|
|
46
|
+
nextSteps: '🚀 다음 단계:',
|
|
47
|
+
nextStep1: 'Claude Code에서 이 프로젝트를 엽니다',
|
|
48
|
+
nextStep2: '/aiwf_<command> 명령어를 사용하여 프로젝트를 관리하세요',
|
|
49
|
+
nextStep3: '/aiwf_initialize를 실행하여 프로젝트를 설정하세요',
|
|
50
|
+
gettingStarted: '✨ 시작하려면:',
|
|
51
|
+
startStep1: '새 터미널을 열거나 쉘 프로필을 소싱하세요 (예: source ~/.zshrc)',
|
|
52
|
+
startStep2: '다음을 실행하세요: claude 를 실행하여 사용 가능한 명령어를 확인하세요.',
|
|
53
|
+
checkDocs: '자세한 내용은 .aiwf 디렉토리의 문서를 확인하세요.',
|
|
54
|
+
updateFailed: '업데이트 실패',
|
|
55
|
+
installFailed: '설치 실패',
|
|
56
|
+
noBackupFound: '복원할 백업 폴더가 없습니다.',
|
|
57
|
+
restoringFromBackup: '백업에서 복원 중...',
|
|
58
|
+
restoreSuccess: '성공적으로 복원되었습니다.',
|
|
59
|
+
restoreFailed: '복원에 실패했습니다.',
|
|
60
|
+
cannotRestore: '파일을 복원할 수 없습니다. 수동 확인이 필요합니다.',
|
|
61
|
+
checkingInstallation: 'AIWF 설치 상태를 확인하는 중...',
|
|
62
|
+
creatingDirectories: 'AIWF 디렉토리 구조를 생성하는 중...',
|
|
63
|
+
restoringBackup: '백업에서 파일을 복원하는 중...',
|
|
64
|
+
backupRestored: '{count}개 파일이 복원되었습니다'
|
|
65
|
+
},
|
|
66
|
+
en: {
|
|
67
|
+
welcome: '\n🎉 Welcome to AIWF!\n',
|
|
68
|
+
description: 'This installer sets up the AIWF AI prompt framework',
|
|
69
|
+
optimized: 'Specially optimized for Claude Code.\n',
|
|
70
|
+
selectLanguage: 'Please select language / 언어를 선택해주세요:',
|
|
71
|
+
korean: '한국어 (Korean)',
|
|
72
|
+
english: 'English',
|
|
73
|
+
existingDetected: 'Existing AIWF installation detected. What would you like to do?',
|
|
74
|
+
updateOption: 'Update (Update commands and docs only, preserve work content)',
|
|
75
|
+
skipOption: 'Skip installation',
|
|
76
|
+
cancelOption: 'Cancel',
|
|
77
|
+
installCancelled: '\nInstallation cancelled.',
|
|
78
|
+
backingUp: 'Backing up existing commands and documents...',
|
|
79
|
+
fetching: 'Fetching AIWF framework from GitHub...',
|
|
80
|
+
downloading: 'Downloading AIWF framework files...',
|
|
81
|
+
updatingDocs: 'Updating documentation...',
|
|
82
|
+
downloadingCommands: 'Downloading AIWF commands...',
|
|
83
|
+
updateSuccess: '✅ AIWF framework updated successfully!',
|
|
84
|
+
installSuccess: '✅ AIWF framework installed successfully!',
|
|
85
|
+
enjoy: '\nEnjoy AIWF! 🚀\n',
|
|
86
|
+
backupComplete: '{count} files backed up (*.bak)',
|
|
87
|
+
noFilesToBackup: 'No existing files to backup',
|
|
88
|
+
backupFailed: 'Backup failed',
|
|
89
|
+
downloadingFile: 'Downloading {path}...',
|
|
90
|
+
downloadingTemplates: 'Downloading template directories...',
|
|
91
|
+
templatesNotFound: 'Template directories not found, skipping...',
|
|
92
|
+
deletingOldCommands: 'Deleting existing AIWF commands folder...',
|
|
93
|
+
commandsNotFound: 'Commands directory not found, skipping...',
|
|
94
|
+
downloadingRulesGlobal: 'Downloading rules/global folder...',
|
|
95
|
+
rulesGlobalNotFound: 'rules/global folder not found, skipping...',
|
|
96
|
+
downloadingRulesManual: 'Downloading rules/manual folder...',
|
|
97
|
+
rulesManualNotFound: 'rules/manual folder not found, skipping...',
|
|
98
|
+
updateHistory: '🔄 Update History:',
|
|
99
|
+
updatedCommands: '/ commands',
|
|
100
|
+
updatedDocs: 'Documentation (CLAUDE.md files)',
|
|
101
|
+
workPreserved: '💾 Work preserved:',
|
|
102
|
+
allFilesPreserved: 'All work, sprints, and project files unchanged',
|
|
103
|
+
backupCreated: 'Backups created as *.bak files',
|
|
104
|
+
structureCreated: '📁 Structure created:',
|
|
105
|
+
aiwfRoot: 'Project management root',
|
|
106
|
+
claudeCommands: 'Claude user commands',
|
|
107
|
+
nextSteps: '🚀 Next steps:',
|
|
108
|
+
nextStep1: 'Open this project in Claude Code',
|
|
109
|
+
nextStep2: 'Use /aiwf_<command> commands to manage your project',
|
|
110
|
+
nextStep3: 'Run /aiwf_initialize to set up your project',
|
|
111
|
+
gettingStarted: '✨ Getting started:',
|
|
112
|
+
startStep1: 'Open a new terminal or source your shell profile (e.g. source ~/.zshrc)',
|
|
113
|
+
startStep2: 'Run: claude to see available commands.',
|
|
114
|
+
checkDocs: 'For more details, check the documentation in the .aiwf directory.',
|
|
115
|
+
updateFailed: 'Update failed',
|
|
116
|
+
installFailed: 'Installation failed',
|
|
117
|
+
noBackupFound: 'No backup folder found to restore.',
|
|
118
|
+
restoringFromBackup: 'Restoring from backup...',
|
|
119
|
+
restoreSuccess: 'Successfully restored.',
|
|
120
|
+
restoreFailed: 'Restore failed.',
|
|
121
|
+
cannotRestore: 'Cannot restore file. Manual verification required.',
|
|
122
|
+
checkingInstallation: 'Checking AIWF installation status...',
|
|
123
|
+
creatingDirectories: 'Creating AIWF directory structure...',
|
|
124
|
+
restoringBackup: 'Restoring files from backup...',
|
|
125
|
+
backupRestored: '{count} files restored'
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Get messages for a specific language
|
|
131
|
+
* @param {string} language - Language code ('ko' or 'en')
|
|
132
|
+
* @returns {Object} Messages object for the specified language
|
|
133
|
+
*/
|
|
134
|
+
export function getMessages(language) {
|
|
135
|
+
return messages[language] || messages.en;
|
|
136
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AIWF Directory Paths Configuration
|
|
3
|
+
* Central location for all directory paths used in the AIWF framework
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import path from 'path';
|
|
7
|
+
import os from 'os';
|
|
8
|
+
|
|
9
|
+
// Base directories
|
|
10
|
+
export const BASE_DIRS = {
|
|
11
|
+
AIWF: '.aiwf',
|
|
12
|
+
CLAUDE: '.claude',
|
|
13
|
+
GEMINI: '.gemini',
|
|
14
|
+
CURSOR: '.cursor',
|
|
15
|
+
WINDSURF: '.windsurf'
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
// AIWF subdirectories
|
|
19
|
+
export const AIWF_DIRS = {
|
|
20
|
+
ROOT: BASE_DIRS.AIWF,
|
|
21
|
+
PROJECT_DOCS: path.join(BASE_DIRS.AIWF, '01_PROJECT_DOCS'),
|
|
22
|
+
REQUIREMENTS: path.join(BASE_DIRS.AIWF, '02_REQUIREMENTS'),
|
|
23
|
+
SPRINTS: path.join(BASE_DIRS.AIWF, '03_SPRINTS'),
|
|
24
|
+
GENERAL_TASKS: path.join(BASE_DIRS.AIWF, '04_GENERAL_TASKS'),
|
|
25
|
+
ARCHITECTURE_DECISIONS: path.join(BASE_DIRS.AIWF, '05_ARCHITECTURE_DECISIONS'),
|
|
26
|
+
STATE_OF_PROJECT: path.join(BASE_DIRS.AIWF, '10_STATE_OF_PROJECT'),
|
|
27
|
+
PROMPTS: path.join(BASE_DIRS.AIWF, '98_PROMPTS'),
|
|
28
|
+
TEMPLATES: path.join(BASE_DIRS.AIWF, '99_TEMPLATES'),
|
|
29
|
+
CACHE: path.join(BASE_DIRS.AIWF, 'cache'),
|
|
30
|
+
METRICS: path.join(BASE_DIRS.AIWF, 'metrics'),
|
|
31
|
+
CONFIG: path.join(BASE_DIRS.AIWF, 'config'),
|
|
32
|
+
PERSONAS: path.join(BASE_DIRS.AIWF, 'personas'),
|
|
33
|
+
AI_TOOLS: path.join(BASE_DIRS.AIWF, 'ai-tools'),
|
|
34
|
+
CONTEXT_CACHE: path.join(BASE_DIRS.AIWF, 'cache', 'context')
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
// Tool-specific directories
|
|
38
|
+
export const TOOL_DIRS = {
|
|
39
|
+
CLAUDE_COMMANDS: path.join(BASE_DIRS.CLAUDE, 'commands', 'aiwf'),
|
|
40
|
+
GEMINI_PROMPTS: path.join(BASE_DIRS.GEMINI, 'prompts', 'aiwf'),
|
|
41
|
+
CURSOR_RULES: path.join(BASE_DIRS.CURSOR, 'rules'),
|
|
42
|
+
WINDSURF_RULES: path.join(BASE_DIRS.WINDSURF, 'rules')
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
// Files
|
|
46
|
+
export const FILES = {
|
|
47
|
+
INSTALLED_FLAG: path.join(AIWF_DIRS.ROOT, 'installed.flag'),
|
|
48
|
+
PROJECT_MANIFEST: path.join(AIWF_DIRS.ROOT, '00_PROJECT_MANIFEST.md'),
|
|
49
|
+
LANGUAGE_CONFIG: path.join(AIWF_DIRS.CONFIG, 'language.json'),
|
|
50
|
+
CLAUDE_MD: {
|
|
51
|
+
ROOT: path.join(AIWF_DIRS.ROOT, 'CLAUDE.md'),
|
|
52
|
+
REQUIREMENTS: path.join(AIWF_DIRS.REQUIREMENTS, 'CLAUDE.md'),
|
|
53
|
+
SPRINTS: path.join(AIWF_DIRS.SPRINTS, 'CLAUDE.md'),
|
|
54
|
+
GENERAL_TASKS: path.join(AIWF_DIRS.GENERAL_TASKS, 'CLAUDE.md')
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
// Temporary directories
|
|
59
|
+
export const TEMP_DIRS = {
|
|
60
|
+
RULES_GLOBAL: path.join(AIWF_DIRS.ROOT, '_tmp_rules_global'),
|
|
61
|
+
RULES_MANUAL: path.join(AIWF_DIRS.ROOT, '_tmp_rules_manual')
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
// User cache directory (for global cache)
|
|
65
|
+
export const USER_CACHE_DIR = path.join(
|
|
66
|
+
os.homedir(),
|
|
67
|
+
BASE_DIRS.AIWF,
|
|
68
|
+
'cache'
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
// Get all AIWF directories as array
|
|
72
|
+
export function getAllAiwfDirectories() {
|
|
73
|
+
return [
|
|
74
|
+
AIWF_DIRS.ROOT,
|
|
75
|
+
AIWF_DIRS.PROJECT_DOCS,
|
|
76
|
+
AIWF_DIRS.REQUIREMENTS,
|
|
77
|
+
AIWF_DIRS.SPRINTS,
|
|
78
|
+
AIWF_DIRS.GENERAL_TASKS,
|
|
79
|
+
AIWF_DIRS.ARCHITECTURE_DECISIONS,
|
|
80
|
+
AIWF_DIRS.STATE_OF_PROJECT,
|
|
81
|
+
AIWF_DIRS.PROMPTS,
|
|
82
|
+
AIWF_DIRS.TEMPLATES
|
|
83
|
+
];
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Get all CLAUDE.md files as array
|
|
87
|
+
export function getAllClaudeMdFiles() {
|
|
88
|
+
return Object.values(FILES.CLAUDE_MD);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Get tool directory by name
|
|
92
|
+
export function getToolDirectory(tool) {
|
|
93
|
+
const mapping = {
|
|
94
|
+
claudeCode: TOOL_DIRS.CLAUDE_COMMANDS,
|
|
95
|
+
'claude-code': TOOL_DIRS.CLAUDE_COMMANDS,
|
|
96
|
+
geminiCLI: TOOL_DIRS.GEMINI_PROMPTS,
|
|
97
|
+
'gemini-cli': TOOL_DIRS.GEMINI_PROMPTS,
|
|
98
|
+
cursor: TOOL_DIRS.CURSOR_RULES,
|
|
99
|
+
windsurf: TOOL_DIRS.WINDSURF_RULES,
|
|
100
|
+
aiwf: AIWF_DIRS.ROOT
|
|
101
|
+
};
|
|
102
|
+
return mapping[tool] || null;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Get backup directory name with timestamp
|
|
106
|
+
export function getBackupDirName() {
|
|
107
|
+
const now = new Date();
|
|
108
|
+
const pad = n => n.toString().padStart(2, '0');
|
|
109
|
+
const y = now.getFullYear();
|
|
110
|
+
const m = pad(now.getMonth() + 1);
|
|
111
|
+
const d = pad(now.getDate());
|
|
112
|
+
const h = pad(now.getHours());
|
|
113
|
+
const min = pad(now.getMinutes());
|
|
114
|
+
const s = pad(now.getSeconds());
|
|
115
|
+
return path.join(AIWF_DIRS.ROOT, `backup_${y}${m}${d}_${h}${min}${s}`);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Export all for convenience
|
|
119
|
+
export default {
|
|
120
|
+
BASE_DIRS,
|
|
121
|
+
AIWF_DIRS,
|
|
122
|
+
TOOL_DIRS,
|
|
123
|
+
FILES,
|
|
124
|
+
TEMP_DIRS,
|
|
125
|
+
USER_CACHE_DIR,
|
|
126
|
+
getAllAiwfDirectories,
|
|
127
|
+
getAllClaudeMdFiles,
|
|
128
|
+
getToolDirectory,
|
|
129
|
+
getBackupDirName
|
|
130
|
+
};
|
|
@@ -13,7 +13,7 @@ const __dirname = path.dirname(__filename);
|
|
|
13
13
|
// 애플리케이션 실행 헬퍼
|
|
14
14
|
async function runApp(args = [], timeout = 10000) {
|
|
15
15
|
return new Promise((resolve, reject) => {
|
|
16
|
-
const appPath = path.join(__dirname, '..', 'index.js');
|
|
16
|
+
const appPath = path.join(__dirname, '..', 'src', 'cli', 'index.js');
|
|
17
17
|
const child = spawn('node', [appPath, ...args], {
|
|
18
18
|
stdio: 'pipe',
|
|
19
19
|
timeout: timeout
|
|
@@ -70,7 +70,7 @@ describe('AIWF 애플리케이션 테스트', () => {
|
|
|
70
70
|
describe('Language CLI 테스트', () => {
|
|
71
71
|
async function runLanguageCli(args = [], timeout = 5000) {
|
|
72
72
|
return new Promise((resolve, reject) => {
|
|
73
|
-
const cliPath = path.join(__dirname, '..', 'language-cli.js');
|
|
73
|
+
const cliPath = path.join(__dirname, '..', 'src', 'cli', 'language-cli.js');
|
|
74
74
|
const child = spawn('node', [cliPath, ...args], {
|
|
75
75
|
stdio: 'pipe',
|
|
76
76
|
timeout: timeout
|
package/tests/installer.test.js
CHANGED
|
@@ -30,7 +30,7 @@ describe('AIWF 인스톨러 기능', () => {
|
|
|
30
30
|
});
|
|
31
31
|
|
|
32
32
|
test('버전 명령어가 올바르게 작동한다', () => {
|
|
33
|
-
const result = execSync('node index.js --version', {
|
|
33
|
+
const result = execSync('node src/cli/index.js --version', {
|
|
34
34
|
cwd: path.join(__dirname, '..'),
|
|
35
35
|
encoding: 'utf8',
|
|
36
36
|
timeout: 5000
|
|
@@ -39,7 +39,7 @@ describe('AIWF 인스톨러 기능', () => {
|
|
|
39
39
|
});
|
|
40
40
|
|
|
41
41
|
test('도움말 명령어가 올바르게 작동한다', () => {
|
|
42
|
-
const result = execSync('node index.js --help', {
|
|
42
|
+
const result = execSync('node src/cli/index.js --help', {
|
|
43
43
|
cwd: path.join(__dirname, '..'),
|
|
44
44
|
encoding: 'utf8',
|
|
45
45
|
timeout: 5000
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
* AI Persona System Integration Tests
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import { AIPersonaManager } from '../../lib/ai-persona-manager.js';
|
|
6
|
-
import { ContextEngine } from '../../lib/context-engine.js';
|
|
7
|
-
import { MetricsCollector } from '../../lib/metrics-collector.js';
|
|
8
|
-
import { TaskAnalyzer } from '../../lib/task-analyzer.js';
|
|
5
|
+
import { AIPersonaManager } from '../../src/lib/ai-persona-manager.js';
|
|
6
|
+
import { ContextEngine } from '../../src/lib/context-engine.js';
|
|
7
|
+
import { MetricsCollector } from '../../src/lib/metrics-collector.js';
|
|
8
|
+
import { TaskAnalyzer } from '../../src/lib/task-analyzer.js';
|
|
9
9
|
import fs from 'fs/promises';
|
|
10
10
|
import path from 'path';
|
|
11
11
|
import { fileURLToPath } from 'url';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Project
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"name":"test-project"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
function login() {}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
console.log("Hello");
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
describe("test", () => {});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{ invalid json }
|
|
@@ -3,17 +3,17 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import { jest } from '@jest/globals';
|
|
6
|
-
import { AIPersonaManager } from '../../lib/ai-persona-manager.js';
|
|
7
|
-
import { ContextEngine } from '../../lib/context-engine.js';
|
|
8
|
-
import { MetricsCollector } from '../../lib/metrics-collector.js';
|
|
9
|
-
import { TaskAnalyzer } from '../../lib/task-analyzer.js';
|
|
6
|
+
import { AIPersonaManager } from '../../src/lib/ai-persona-manager.js';
|
|
7
|
+
import { ContextEngine } from '../../src/lib/context-engine.js';
|
|
8
|
+
import { MetricsCollector } from '../../src/lib/metrics-collector.js';
|
|
9
|
+
import { TaskAnalyzer } from '../../src/lib/task-analyzer.js';
|
|
10
10
|
import fs from 'fs/promises';
|
|
11
11
|
import path from 'path';
|
|
12
12
|
|
|
13
13
|
// Mock dependencies
|
|
14
|
-
jest.mock('../../lib/context-engine.js');
|
|
15
|
-
jest.mock('../../lib/metrics-collector.js');
|
|
16
|
-
jest.mock('../../lib/task-analyzer.js');
|
|
14
|
+
jest.mock('../../src/lib/context-engine.js');
|
|
15
|
+
jest.mock('../../src/lib/metrics-collector.js');
|
|
16
|
+
jest.mock('../../src/lib/task-analyzer.js');
|
|
17
17
|
jest.mock('fs/promises');
|
|
18
18
|
|
|
19
19
|
describe('AIPersonaManager', () => {
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
# 성능 보고서
|
|
2
|
-
|
|
3
|
-
## 개요
|
|
4
|
-
이 문서는 AIWF 프레임워크의 성능 벤치마크 결과를 요약합니다.
|
|
5
|
-
|
|
6
|
-
## 토큰 사용량 분석
|
|
7
|
-
### 기준선
|
|
8
|
-
- **이전 버전**: 1,000 토큰
|
|
9
|
-
- **현재 버전**: 500 토큰
|
|
10
|
-
- **절감률**: 50%
|
|
11
|
-
|
|
12
|
-
### 성능 개선 사항
|
|
13
|
-
1. **컨텍스트 압축**: 40% 토큰 절약
|
|
14
|
-
2. **불필요한 정보 제거**: 30% 토큰 절약
|
|
15
|
-
3. **효율적인 구조화**: 20% 토큰 절약
|
|
16
|
-
|
|
17
|
-
## 응답 시간 분석
|
|
18
|
-
- **평균 응답 시간**: 2.3초
|
|
19
|
-
- **최대 응답 시간**: 5.1초
|
|
20
|
-
- **최소 응답 시간**: 0.8초
|
|
21
|
-
|
|
22
|
-
## 메모리 사용량
|
|
23
|
-
- **평균 메모리 사용량**: 256MB
|
|
24
|
-
- **최대 메모리 사용량**: 512MB
|
|
25
|
-
- **메모리 최적화율**: 35%
|
|
26
|
-
|
|
27
|
-
## 결론
|
|
28
|
-
AIWF 프레임워크는 토큰 사용량을 50% 절감하여 성능 목표를 달성했습니다.
|
|
29
|
-
|
|
30
|
-
## 권장사항
|
|
31
|
-
1. 지속적인 모니터링 필요
|
|
32
|
-
2. 추가 최적화 기회 탐색
|
|
33
|
-
3. 성능 회귀 방지 체계 구축
|