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,561 @@
|
|
|
1
|
+
import fs from 'fs/promises';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import { TOOL_DIRS, AIWF_DIRS, FILES } from '../utils/paths.js';
|
|
5
|
+
|
|
6
|
+
// Essential files configuration for each tool
|
|
7
|
+
const ESSENTIAL_FILES = {
|
|
8
|
+
claudeCode: {
|
|
9
|
+
baseDir: TOOL_DIRS.CLAUDE_COMMANDS,
|
|
10
|
+
requiredFiles: [
|
|
11
|
+
'aiwf_initialize.md',
|
|
12
|
+
'aiwf_do_task.md',
|
|
13
|
+
'aiwf_commit.md',
|
|
14
|
+
'aiwf_create_sprint_tasks.md',
|
|
15
|
+
'aiwf_code_review.md'
|
|
16
|
+
],
|
|
17
|
+
minFileCount: 5,
|
|
18
|
+
description: 'Claude Code Commands'
|
|
19
|
+
},
|
|
20
|
+
geminiCLI: {
|
|
21
|
+
baseDir: TOOL_DIRS.GEMINI_PROMPTS,
|
|
22
|
+
requiredFiles: ['README.md'],
|
|
23
|
+
minFileCount: 1,
|
|
24
|
+
description: 'Gemini-CLI Prompts'
|
|
25
|
+
},
|
|
26
|
+
cursor: {
|
|
27
|
+
baseDir: TOOL_DIRS.CURSOR_RULES,
|
|
28
|
+
requiredFiles: [],
|
|
29
|
+
minFileCount: 2,
|
|
30
|
+
fileExtension: '.mdc',
|
|
31
|
+
description: 'Cursor IDE Rules'
|
|
32
|
+
},
|
|
33
|
+
windsurf: {
|
|
34
|
+
baseDir: TOOL_DIRS.WINDSURF_RULES,
|
|
35
|
+
requiredFiles: [],
|
|
36
|
+
minFileCount: 2,
|
|
37
|
+
fileExtension: '.md',
|
|
38
|
+
description: 'Windsurf IDE Rules'
|
|
39
|
+
},
|
|
40
|
+
aiwf: {
|
|
41
|
+
baseDir: AIWF_DIRS.ROOT,
|
|
42
|
+
requiredFiles: ['CLAUDE.md', '00_PROJECT_MANIFEST.md'],
|
|
43
|
+
minFileCount: 2,
|
|
44
|
+
description: 'AIWF Core Structure'
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Validate tool installation based on configuration
|
|
50
|
+
* @param {Object} config - Tool configuration
|
|
51
|
+
* @returns {Promise<Object>} Validation results
|
|
52
|
+
*/
|
|
53
|
+
async function validateToolInstallation(config) {
|
|
54
|
+
const results = {
|
|
55
|
+
success: true,
|
|
56
|
+
description: config.description,
|
|
57
|
+
baseDir: config.baseDir,
|
|
58
|
+
checks: {
|
|
59
|
+
directoryExists: false,
|
|
60
|
+
fileCount: 0,
|
|
61
|
+
requiredFiles: [],
|
|
62
|
+
totalSize: 0,
|
|
63
|
+
issues: []
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
try {
|
|
68
|
+
// 1. Check directory exists
|
|
69
|
+
await fs.access(config.baseDir);
|
|
70
|
+
const dirStat = await fs.stat(config.baseDir);
|
|
71
|
+
if (dirStat.isDirectory()) {
|
|
72
|
+
results.checks.directoryExists = true;
|
|
73
|
+
} else {
|
|
74
|
+
results.checks.issues.push(`${config.baseDir} is not a directory`);
|
|
75
|
+
results.success = false;
|
|
76
|
+
return results;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// 2. Get file list
|
|
80
|
+
const actualFiles = await fs.readdir(config.baseDir);
|
|
81
|
+
results.checks.fileCount = actualFiles.length;
|
|
82
|
+
|
|
83
|
+
// 3. Check required files
|
|
84
|
+
for (const requiredFile of config.requiredFiles || []) {
|
|
85
|
+
const filePath = path.join(config.baseDir, requiredFile);
|
|
86
|
+
const fileCheck = {
|
|
87
|
+
file: requiredFile,
|
|
88
|
+
exists: false,
|
|
89
|
+
size: 0,
|
|
90
|
+
valid: false
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
if (actualFiles.includes(requiredFile)) {
|
|
94
|
+
fileCheck.exists = true;
|
|
95
|
+
try {
|
|
96
|
+
const stats = await fs.stat(filePath);
|
|
97
|
+
fileCheck.size = stats.size;
|
|
98
|
+
results.checks.totalSize += stats.size;
|
|
99
|
+
|
|
100
|
+
// Validate file size (minimum 10 bytes)
|
|
101
|
+
if (stats.size < 10) {
|
|
102
|
+
results.checks.issues.push(
|
|
103
|
+
`File ${requiredFile} is too small (${stats.size} bytes)`
|
|
104
|
+
);
|
|
105
|
+
results.success = false;
|
|
106
|
+
} else {
|
|
107
|
+
fileCheck.valid = true;
|
|
108
|
+
}
|
|
109
|
+
} catch (error) {
|
|
110
|
+
results.checks.issues.push(
|
|
111
|
+
`Cannot read stats for ${requiredFile}: ${error.message}`
|
|
112
|
+
);
|
|
113
|
+
results.success = false;
|
|
114
|
+
}
|
|
115
|
+
} else {
|
|
116
|
+
results.checks.issues.push(`Required file ${requiredFile} is missing`);
|
|
117
|
+
results.success = false;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
results.checks.requiredFiles.push(fileCheck);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// 4. File extension validation (Cursor/Windsurf)
|
|
124
|
+
if (config.fileExtension) {
|
|
125
|
+
const matchingFiles = actualFiles.filter(f => f.endsWith(config.fileExtension));
|
|
126
|
+
if (matchingFiles.length < config.minFileCount) {
|
|
127
|
+
results.checks.issues.push(
|
|
128
|
+
`Expected at least ${config.minFileCount} ${config.fileExtension} files, found ${matchingFiles.length}`
|
|
129
|
+
);
|
|
130
|
+
results.success = false;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Validate file sizes for extension files
|
|
134
|
+
for (const file of matchingFiles) {
|
|
135
|
+
const filePath = path.join(config.baseDir, file);
|
|
136
|
+
try {
|
|
137
|
+
const stats = await fs.stat(filePath);
|
|
138
|
+
results.checks.totalSize += stats.size;
|
|
139
|
+
|
|
140
|
+
if (stats.size < 50) {
|
|
141
|
+
// Rules files should be at least 50 bytes
|
|
142
|
+
results.checks.issues.push(
|
|
143
|
+
`Rules file ${file} is too small (${stats.size} bytes)`
|
|
144
|
+
);
|
|
145
|
+
results.success = false;
|
|
146
|
+
}
|
|
147
|
+
} catch (error) {
|
|
148
|
+
results.checks.issues.push(`Cannot read ${file}: ${error.message}`);
|
|
149
|
+
results.success = false;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// 5. Minimum file count validation
|
|
155
|
+
if (results.checks.fileCount < config.minFileCount) {
|
|
156
|
+
results.checks.issues.push(
|
|
157
|
+
`Expected at least ${config.minFileCount} files, found ${results.checks.fileCount}`
|
|
158
|
+
);
|
|
159
|
+
results.success = false;
|
|
160
|
+
}
|
|
161
|
+
} catch (error) {
|
|
162
|
+
results.success = false;
|
|
163
|
+
results.checks.issues.push(`Validation error: ${error.message}`);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
return results;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Validate Claude Code installation
|
|
171
|
+
* @returns {Promise<Object>} Validation results
|
|
172
|
+
*/
|
|
173
|
+
export async function validateClaudeInstall() {
|
|
174
|
+
return await validateToolInstallation(ESSENTIAL_FILES.claudeCode);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Validate Gemini CLI installation
|
|
179
|
+
* @returns {Promise<Object>} Validation results
|
|
180
|
+
*/
|
|
181
|
+
export async function validateGeminiInstall() {
|
|
182
|
+
return await validateToolInstallation(ESSENTIAL_FILES.geminiCLI);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Validate Cursor installation
|
|
187
|
+
* @returns {Promise<Object>} Validation results
|
|
188
|
+
*/
|
|
189
|
+
export async function validateCursorInstall() {
|
|
190
|
+
return await validateToolInstallation(ESSENTIAL_FILES.cursor);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Validate Windsurf installation
|
|
195
|
+
* @returns {Promise<Object>} Validation results
|
|
196
|
+
*/
|
|
197
|
+
export async function validateWindsurfInstall() {
|
|
198
|
+
return await validateToolInstallation(ESSENTIAL_FILES.windsurf);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Validate AIWF Core installation
|
|
203
|
+
* @returns {Promise<Object>} Validation results
|
|
204
|
+
*/
|
|
205
|
+
export async function validateAIWFCore() {
|
|
206
|
+
return await validateToolInstallation(ESSENTIAL_FILES.aiwf);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Validate installation with detailed results
|
|
211
|
+
* @returns {Promise<Object>} Detailed validation results
|
|
212
|
+
*/
|
|
213
|
+
export async function validateInstallationDetailed() {
|
|
214
|
+
const validationResults = {
|
|
215
|
+
overall: {
|
|
216
|
+
success: true,
|
|
217
|
+
toolsChecked: 0,
|
|
218
|
+
toolsPassed: 0,
|
|
219
|
+
toolsFailed: 0,
|
|
220
|
+
totalIssues: 0
|
|
221
|
+
},
|
|
222
|
+
tools: {}
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
// Always validate AIWF core
|
|
226
|
+
const aiwfResult = await validateAIWFCore();
|
|
227
|
+
validationResults.tools.aiwf = aiwfResult;
|
|
228
|
+
validationResults.overall.toolsChecked++;
|
|
229
|
+
|
|
230
|
+
if (aiwfResult.success) {
|
|
231
|
+
validationResults.overall.toolsPassed++;
|
|
232
|
+
} else {
|
|
233
|
+
validationResults.overall.toolsFailed++;
|
|
234
|
+
validationResults.overall.success = false;
|
|
235
|
+
validationResults.overall.totalIssues += aiwfResult.checks.issues.length;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// Validate all tools
|
|
239
|
+
const toolValidators = {
|
|
240
|
+
claudeCode: validateClaudeInstall,
|
|
241
|
+
geminiCLI: validateGeminiInstall,
|
|
242
|
+
cursor: validateCursorInstall,
|
|
243
|
+
windsurf: validateWindsurfInstall
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
for (const [toolName, validator] of Object.entries(toolValidators)) {
|
|
247
|
+
const result = await validator();
|
|
248
|
+
validationResults.tools[toolName] = result;
|
|
249
|
+
validationResults.overall.toolsChecked++;
|
|
250
|
+
|
|
251
|
+
if (result.success) {
|
|
252
|
+
validationResults.overall.toolsPassed++;
|
|
253
|
+
} else {
|
|
254
|
+
validationResults.overall.toolsFailed++;
|
|
255
|
+
validationResults.overall.success = false;
|
|
256
|
+
validationResults.overall.totalIssues += result.checks.issues.length;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
return validationResults;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Enhanced installation validation with tool selection
|
|
265
|
+
* @param {Array|null} selectedTools - Tools to validate
|
|
266
|
+
* @param {string} language - Language code
|
|
267
|
+
* @returns {Promise<Object>} Validation results
|
|
268
|
+
*/
|
|
269
|
+
export async function validateInstallationEnhanced(selectedTools = null, language = 'en') {
|
|
270
|
+
const validationResults = {
|
|
271
|
+
overall: {
|
|
272
|
+
success: true,
|
|
273
|
+
toolsChecked: 0,
|
|
274
|
+
toolsPassed: 0,
|
|
275
|
+
toolsFailed: 0,
|
|
276
|
+
totalIssues: 0
|
|
277
|
+
},
|
|
278
|
+
tools: {}
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
// Always validate AIWF core
|
|
282
|
+
const aiwfResult = await validateAIWFCore();
|
|
283
|
+
validationResults.tools.aiwf = aiwfResult;
|
|
284
|
+
validationResults.overall.toolsChecked++;
|
|
285
|
+
|
|
286
|
+
if (aiwfResult.success) {
|
|
287
|
+
validationResults.overall.toolsPassed++;
|
|
288
|
+
} else {
|
|
289
|
+
validationResults.overall.toolsFailed++;
|
|
290
|
+
validationResults.overall.success = false;
|
|
291
|
+
validationResults.overall.totalIssues += aiwfResult.checks.issues.length;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// Determine tools to validate
|
|
295
|
+
const toolsToValidate = selectedTools || ['claudeCode', 'geminiCLI', 'cursor', 'windsurf'];
|
|
296
|
+
|
|
297
|
+
const toolValidators = {
|
|
298
|
+
claudeCode: validateClaudeInstall,
|
|
299
|
+
geminiCLI: validateGeminiInstall,
|
|
300
|
+
cursor: validateCursorInstall,
|
|
301
|
+
windsurf: validateWindsurfInstall
|
|
302
|
+
};
|
|
303
|
+
|
|
304
|
+
for (const toolName of toolsToValidate) {
|
|
305
|
+
if (toolValidators[toolName]) {
|
|
306
|
+
const result = await toolValidators[toolName]();
|
|
307
|
+
validationResults.tools[toolName] = result;
|
|
308
|
+
validationResults.overall.toolsChecked++;
|
|
309
|
+
|
|
310
|
+
if (result.success) {
|
|
311
|
+
validationResults.overall.toolsPassed++;
|
|
312
|
+
} else {
|
|
313
|
+
validationResults.overall.toolsFailed++;
|
|
314
|
+
validationResults.overall.success = false;
|
|
315
|
+
validationResults.overall.totalIssues += result.checks.issues.length;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
return validationResults;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* Simplified validation with clean interface
|
|
325
|
+
* @param {Array} selectedTools - Tools to validate
|
|
326
|
+
* @param {string} language - Language code
|
|
327
|
+
* @returns {Promise<Object>} Validation results
|
|
328
|
+
*/
|
|
329
|
+
export async function validateInstallation(selectedTools, language) {
|
|
330
|
+
const results = {
|
|
331
|
+
success: [],
|
|
332
|
+
failed: [],
|
|
333
|
+
warnings: []
|
|
334
|
+
};
|
|
335
|
+
|
|
336
|
+
// Always validate common files (AIWF core)
|
|
337
|
+
const commonValid = await validateCommonFiles();
|
|
338
|
+
if (!commonValid.success) {
|
|
339
|
+
results.failed.push({ tool: 'aiwf', reason: commonValid.reason });
|
|
340
|
+
} else {
|
|
341
|
+
results.success.push('aiwf');
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// Validate selected tools
|
|
345
|
+
if (selectedTools && selectedTools.length > 0) {
|
|
346
|
+
for (const tool of selectedTools) {
|
|
347
|
+
const validation = await validateTool(tool);
|
|
348
|
+
if (validation.success) {
|
|
349
|
+
results.success.push(tool);
|
|
350
|
+
} else {
|
|
351
|
+
results.failed.push({ tool, reason: validation.reason });
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
} else {
|
|
355
|
+
// Default: validate all tools if no selection provided
|
|
356
|
+
const allTools = ['claudeCode', 'geminiCLI', 'cursor', 'windsurf'];
|
|
357
|
+
for (const tool of allTools) {
|
|
358
|
+
const validation = await validateTool(tool);
|
|
359
|
+
if (validation.success) {
|
|
360
|
+
results.success.push(tool);
|
|
361
|
+
} else {
|
|
362
|
+
results.failed.push({ tool, reason: validation.reason });
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
return results;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* Validate common/core files
|
|
372
|
+
* @returns {Promise<Object>} Validation result
|
|
373
|
+
*/
|
|
374
|
+
async function validateCommonFiles() {
|
|
375
|
+
try {
|
|
376
|
+
const requiredFiles = [
|
|
377
|
+
FILES.CLAUDE_MD.ROOT,
|
|
378
|
+
FILES.PROJECT_MANIFEST
|
|
379
|
+
];
|
|
380
|
+
|
|
381
|
+
for (const file of requiredFiles) {
|
|
382
|
+
const exists = await fs
|
|
383
|
+
.access(file)
|
|
384
|
+
.then(() => true)
|
|
385
|
+
.catch(() => false);
|
|
386
|
+
if (!exists) {
|
|
387
|
+
return { success: false, reason: `Missing core file: ${file}` };
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
return { success: true };
|
|
392
|
+
} catch (error) {
|
|
393
|
+
return { success: false, reason: `Core validation error: ${error.message}` };
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* Validate specific tool
|
|
399
|
+
* @param {string} tool - Tool name
|
|
400
|
+
* @returns {Promise<Object>} Validation result
|
|
401
|
+
*/
|
|
402
|
+
async function validateTool(tool) {
|
|
403
|
+
switch (tool) {
|
|
404
|
+
case 'claudeCode':
|
|
405
|
+
case 'claude-code':
|
|
406
|
+
return validateClaudeCode();
|
|
407
|
+
case 'geminiCLI':
|
|
408
|
+
case 'gemini-cli':
|
|
409
|
+
return validateGeminiCLI();
|
|
410
|
+
case 'cursor':
|
|
411
|
+
return validateCursorTool();
|
|
412
|
+
case 'windsurf':
|
|
413
|
+
return validateWindsurfTool();
|
|
414
|
+
case 'aiwf':
|
|
415
|
+
return validateCommonFiles();
|
|
416
|
+
default:
|
|
417
|
+
return { success: false, reason: `Unknown tool: ${tool}` };
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* Validate Claude Code with simplified interface
|
|
423
|
+
* @returns {Promise<Object>} Validation result
|
|
424
|
+
*/
|
|
425
|
+
async function validateClaudeCode() {
|
|
426
|
+
try {
|
|
427
|
+
const requiredFiles = [
|
|
428
|
+
'aiwf_initialize.md',
|
|
429
|
+
'aiwf_do_task.md',
|
|
430
|
+
'aiwf_commit.md',
|
|
431
|
+
'aiwf_code_review.md'
|
|
432
|
+
];
|
|
433
|
+
|
|
434
|
+
for (const fileName of requiredFiles) {
|
|
435
|
+
const filePath = path.join(TOOL_DIRS.CLAUDE_COMMANDS, fileName);
|
|
436
|
+
const exists = await fs
|
|
437
|
+
.access(filePath)
|
|
438
|
+
.then(() => true)
|
|
439
|
+
.catch(() => false);
|
|
440
|
+
if (!exists) {
|
|
441
|
+
return { success: false, reason: `Missing file: ${filePath}` };
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
return { success: true };
|
|
446
|
+
} catch (error) {
|
|
447
|
+
return { success: false, reason: `Claude Code validation error: ${error.message}` };
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
/**
|
|
452
|
+
* Validate Gemini CLI with simplified interface
|
|
453
|
+
* @returns {Promise<Object>} Validation result
|
|
454
|
+
*/
|
|
455
|
+
async function validateGeminiCLI() {
|
|
456
|
+
try {
|
|
457
|
+
const dirExists = await fs
|
|
458
|
+
.access(TOOL_DIRS.GEMINI_PROMPTS)
|
|
459
|
+
.then(() => true)
|
|
460
|
+
.catch(() => false);
|
|
461
|
+
if (!dirExists) {
|
|
462
|
+
return {
|
|
463
|
+
success: false,
|
|
464
|
+
reason: `Missing Gemini-CLI prompts directory: ${TOOL_DIRS.GEMINI_PROMPTS}`
|
|
465
|
+
};
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
return { success: true };
|
|
469
|
+
} catch (error) {
|
|
470
|
+
return { success: false, reason: `Gemini-CLI validation error: ${error.message}` };
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
/**
|
|
475
|
+
* Validate Cursor tool with simplified interface
|
|
476
|
+
* @returns {Promise<Object>} Validation result
|
|
477
|
+
*/
|
|
478
|
+
async function validateCursorTool() {
|
|
479
|
+
try {
|
|
480
|
+
const dirExists = await fs
|
|
481
|
+
.access(TOOL_DIRS.CURSOR_RULES)
|
|
482
|
+
.then(() => true)
|
|
483
|
+
.catch(() => false);
|
|
484
|
+
if (!dirExists) {
|
|
485
|
+
return { success: false, reason: `Missing Cursor rules directory: ${TOOL_DIRS.CURSOR_RULES}` };
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
return { success: true };
|
|
489
|
+
} catch (error) {
|
|
490
|
+
return { success: false, reason: `Cursor validation error: ${error.message}` };
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
/**
|
|
495
|
+
* Validate Windsurf tool with simplified interface
|
|
496
|
+
* @returns {Promise<Object>} Validation result
|
|
497
|
+
*/
|
|
498
|
+
async function validateWindsurfTool() {
|
|
499
|
+
try {
|
|
500
|
+
const dirExists = await fs
|
|
501
|
+
.access(TOOL_DIRS.WINDSURF_RULES)
|
|
502
|
+
.then(() => true)
|
|
503
|
+
.catch(() => false);
|
|
504
|
+
if (!dirExists) {
|
|
505
|
+
return { success: false, reason: `Missing Windsurf rules directory: ${TOOL_DIRS.WINDSURF_RULES}` };
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
return { success: true };
|
|
509
|
+
} catch (error) {
|
|
510
|
+
return { success: false, reason: `Windsurf validation error: ${error.message}` };
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
/**
|
|
515
|
+
* Display validation results in spec-compliant format
|
|
516
|
+
* @param {Object} validationResults - Validation results
|
|
517
|
+
* @param {string} language - Language code
|
|
518
|
+
*/
|
|
519
|
+
export function displaySpecCompliantValidationResults(validationResults, language) {
|
|
520
|
+
console.log(chalk.blue('\n=== Installation Validation Results ==='));
|
|
521
|
+
|
|
522
|
+
// Success summary
|
|
523
|
+
if (validationResults.success.length > 0) {
|
|
524
|
+
console.log(
|
|
525
|
+
chalk.green(`\n✅ Successfully Validated Tools (${validationResults.success.length}):`)
|
|
526
|
+
);
|
|
527
|
+
validationResults.success.forEach(tool => {
|
|
528
|
+
console.log(chalk.green(` ✓ ${tool}`));
|
|
529
|
+
});
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
// Failed summary
|
|
533
|
+
if (validationResults.failed.length > 0) {
|
|
534
|
+
console.log(chalk.red(`\n❌ Failed Validations (${validationResults.failed.length}):`));
|
|
535
|
+
validationResults.failed.forEach(({ tool, reason }) => {
|
|
536
|
+
console.log(chalk.red(` ✗ ${tool}: ${reason}`));
|
|
537
|
+
});
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
// Warnings summary
|
|
541
|
+
if (validationResults.warnings.length > 0) {
|
|
542
|
+
console.log(chalk.yellow(`\n⚠️ Warnings (${validationResults.warnings.length}):`));
|
|
543
|
+
validationResults.warnings.forEach(warning => {
|
|
544
|
+
console.log(chalk.yellow(` ⚠ ${warning}`));
|
|
545
|
+
});
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
// Overall status
|
|
549
|
+
const isSuccess = validationResults.failed.length === 0;
|
|
550
|
+
const statusIcon = isSuccess ? '✅' : '❌';
|
|
551
|
+
const statusColor = isSuccess ? chalk.green : chalk.red;
|
|
552
|
+
const statusText = isSuccess ? 'PASSED' : 'FAILED';
|
|
553
|
+
|
|
554
|
+
console.log(statusColor(`\n${statusIcon} Overall Validation: ${statusText}`));
|
|
555
|
+
|
|
556
|
+
if (isSuccess) {
|
|
557
|
+
console.log(chalk.green('🎉 All selected tools are properly installed and validated!'));
|
|
558
|
+
} else {
|
|
559
|
+
console.log(chalk.yellow('⚠️ Some installations failed. See details above.'));
|
|
560
|
+
}
|
|
561
|
+
}
|