aios-core 4.0.2 → 4.1.0
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/.aios-core/cli/commands/migrate/analyze.js +6 -6
- package/.aios-core/cli/commands/migrate/backup.js +2 -2
- package/.aios-core/cli/commands/migrate/execute.js +4 -4
- package/.aios-core/cli/commands/migrate/index.js +5 -5
- package/.aios-core/cli/commands/migrate/rollback.js +6 -6
- package/.aios-core/cli/commands/migrate/update-imports.js +2 -2
- package/.aios-core/cli/commands/migrate/validate.js +2 -2
- package/.aios-core/cli/commands/pro/index.js +52 -0
- package/.aios-core/cli/index.js +1 -1
- package/.aios-core/core/ids/registry-updater.js +29 -3
- package/.aios-core/core/migration/migration-config.yaml +2 -2
- package/.aios-core/core/migration/module-mapping.yaml +2 -2
- package/.aios-core/core/registry/README.md +2 -2
- package/.aios-core/core/synapse/context/context-builder.js +34 -0
- package/.aios-core/core/synapse/diagnostics/collectors/consistency-collector.js +168 -0
- package/.aios-core/core/synapse/diagnostics/collectors/hook-collector.js +129 -0
- package/.aios-core/core/synapse/diagnostics/collectors/manifest-collector.js +82 -0
- package/.aios-core/core/synapse/diagnostics/collectors/output-analyzer.js +134 -0
- package/.aios-core/core/synapse/diagnostics/collectors/pipeline-collector.js +75 -0
- package/.aios-core/core/synapse/diagnostics/collectors/quality-collector.js +252 -0
- package/.aios-core/core/synapse/diagnostics/collectors/relevance-matrix.js +174 -0
- package/.aios-core/core/synapse/diagnostics/collectors/safe-read-json.js +31 -0
- package/.aios-core/core/synapse/diagnostics/collectors/session-collector.js +102 -0
- package/.aios-core/core/synapse/diagnostics/collectors/timing-collector.js +126 -0
- package/.aios-core/core/synapse/diagnostics/collectors/uap-collector.js +83 -0
- package/.aios-core/core/synapse/diagnostics/report-formatter.js +484 -0
- package/.aios-core/core/synapse/diagnostics/synapse-diagnostics.js +95 -0
- package/.aios-core/core/synapse/engine.js +73 -20
- package/.aios-core/core/synapse/runtime/hook-runtime.js +60 -0
- package/.aios-core/core-config.yaml +6 -0
- package/.aios-core/data/agent-config-requirements.yaml +2 -2
- package/.aios-core/data/aios-kb.md +4 -4
- package/.aios-core/data/entity-registry.yaml +5 -5
- package/.aios-core/development/agents/architect.md +10 -10
- package/.aios-core/development/agents/devops.md +93 -50
- package/.aios-core/development/agents/qa.md +94 -40
- package/.aios-core/development/agents/ux-design-expert.md +25 -25
- package/.aios-core/development/scripts/activation-runtime.js +63 -0
- package/.aios-core/development/scripts/generate-greeting.js +9 -8
- package/.aios-core/development/scripts/unified-activation-pipeline.js +102 -2
- package/.aios-core/development/tasks/{db-expansion-pack-integration.md → db-squad-integration.md} +5 -5
- package/.aios-core/development/tasks/{integrate-expansion-pack.md → integrate-squad.md} +2 -2
- package/.aios-core/development/tasks/next.md +3 -3
- package/.aios-core/development/tasks/pr-automation.md +2 -2
- package/.aios-core/development/tasks/publish-npm.md +257 -0
- package/.aios-core/development/tasks/release-management.md +4 -4
- package/.aios-core/development/tasks/setup-github.md +1 -1
- package/.aios-core/development/tasks/squad-creator-migrate.md +1 -1
- package/.aios-core/development/tasks/squad-creator-sync-ide-command.md +14 -14
- package/.aios-core/development/tasks/update-aios.md +1 -1
- package/.aios-core/docs/standards/AIOS-COLOR-PALETTE-QUICK-REFERENCE.md +1 -1
- package/.aios-core/docs/standards/AIOS-COLOR-PALETTE-V2.1.md +5 -5
- package/.aios-core/docs/standards/AIOS-LIVRO-DE-OURO-V2.1-COMPLETE.md +21 -21
- package/.aios-core/docs/standards/AIOS-LIVRO-DE-OURO-V2.2-SUMMARY.md +25 -25
- package/.aios-core/docs/standards/OPEN-SOURCE-VS-SERVICE-DIFFERENCES.md +4 -4
- package/.aios-core/docs/standards/QUALITY-GATES-SPECIFICATION.md +3 -3
- package/.aios-core/docs/standards/STANDARDS-INDEX.md +13 -13
- package/.aios-core/docs/standards/STORY-TEMPLATE-V2-SPECIFICATION.md +1 -1
- package/.aios-core/framework-config.yaml +4 -0
- package/.aios-core/infrastructure/scripts/codex-skills-sync/index.js +182 -0
- package/.aios-core/infrastructure/scripts/codex-skills-sync/validate.js +172 -0
- package/.aios-core/infrastructure/scripts/ide-sync/README.md +14 -0
- package/.aios-core/infrastructure/scripts/ide-sync/index.js +6 -0
- package/.aios-core/infrastructure/scripts/tool-resolver.js +4 -4
- package/.aios-core/infrastructure/scripts/validate-paths.js +142 -0
- package/.aios-core/infrastructure/templates/aios-sync.yaml.template +11 -11
- package/.aios-core/infrastructure/templates/github-workflows/README.md +1 -1
- package/.aios-core/install-manifest.yaml +190 -106
- package/.aios-core/local-config.yaml.template +2 -0
- package/.aios-core/product/README.md +2 -2
- package/.aios-core/product/data/integration-patterns.md +1 -1
- package/.aios-core/product/templates/ide-rules/cline-rules.md +1 -1
- package/.aios-core/product/templates/ide-rules/codex-rules.md +65 -0
- package/.aios-core/product/templates/ide-rules/copilot-rules.md +1 -1
- package/.aios-core/product/templates/ide-rules/roo-rules.md +1 -1
- package/.aios-core/user-guide.md +15 -14
- package/.aios-core/workflow-intelligence/engine/output-formatter.js +1 -1
- package/.claude/hooks/enforce-architecture-first.py +196 -0
- package/.claude/hooks/install-hooks.sh +41 -0
- package/.claude/hooks/mind-clone-governance.py +192 -0
- package/.claude/hooks/pre-commit-mmos-guard.sh +99 -0
- package/.claude/hooks/pre-commit-version-check.sh +156 -0
- package/.claude/hooks/read-protection.py +151 -0
- package/.claude/hooks/slug-validation.py +176 -0
- package/.claude/hooks/sql-governance.py +182 -0
- package/.claude/hooks/synapse-engine.js +9 -20
- package/.claude/hooks/write-path-validation.py +194 -0
- package/README.md +44 -14
- package/bin/aios-init.js +255 -184
- package/bin/aios-minimal.js +2 -2
- package/bin/aios.js +19 -19
- package/package.json +7 -4
- package/packages/aios-pro-cli/bin/aios-pro.js +75 -2
- package/packages/aios-pro-cli/package.json +5 -1
- package/packages/aios-pro-cli/src/recover.js +100 -0
- package/packages/installer/src/__tests__/performance-benchmark.js +382 -0
- package/packages/installer/src/config/ide-configs.js +12 -1
- package/packages/installer/src/config/templates/core-config-template.js +2 -2
- package/packages/installer/src/installer/aios-core-installer.js +2 -2
- package/packages/installer/src/installer/file-hasher.js +97 -0
- package/packages/installer/src/installer/post-install-validator.js +41 -1
- package/packages/installer/src/pro/pro-scaffolder.js +335 -0
- package/packages/installer/src/utils/aios-colors.js +2 -2
- package/packages/installer/src/wizard/feedback.js +1 -1
- package/packages/installer/src/wizard/ide-config-generator.js +2 -2
- package/packages/installer/src/wizard/index.js +58 -19
- package/packages/installer/src/wizard/pro-setup.js +547 -0
- package/packages/installer/src/wizard/questions.js +20 -14
- package/packages/installer/src/wizard/validators.js +1 -1
- package/scripts/package-synapse.js +323 -0
- package/scripts/validate-package-completeness.js +317 -0
package/bin/aios-init.js
CHANGED
|
@@ -24,9 +24,36 @@ const path = require('path');
|
|
|
24
24
|
const fs = require('fs');
|
|
25
25
|
const fse = require('fs-extra');
|
|
26
26
|
const yaml = require('js-yaml');
|
|
27
|
-
const { execSync } = require('child_process');
|
|
27
|
+
const { execSync, exec, spawn } = require('child_process');
|
|
28
|
+
const { promisify } = require('util');
|
|
28
29
|
const inquirer = require('inquirer');
|
|
29
30
|
const chalk = require('chalk');
|
|
31
|
+
const ora = require('ora'); // INS-2 Performance: Progress indicators (AC9)
|
|
32
|
+
|
|
33
|
+
// INS-2 Performance: Promisified exec for async shell commands (AC7)
|
|
34
|
+
const execAsync = promisify(exec);
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Execute command with inherited stdio (for npm install -g that needs user interaction)
|
|
38
|
+
* INS-2 Performance: Async version that doesn't block event loop
|
|
39
|
+
* @param {string} command - Command to execute
|
|
40
|
+
* @param {object} options - Spawn options
|
|
41
|
+
* @returns {Promise<void>}
|
|
42
|
+
*/
|
|
43
|
+
function spawnAsync(command, options = {}) {
|
|
44
|
+
return new Promise((resolve, reject) => {
|
|
45
|
+
const [cmd, ...args] = command.split(' ');
|
|
46
|
+
const child = spawn(cmd, args, { stdio: 'inherit', shell: true, ...options });
|
|
47
|
+
child.on('close', (code) => {
|
|
48
|
+
if (code === 0) {
|
|
49
|
+
resolve();
|
|
50
|
+
} else {
|
|
51
|
+
reject(new Error(`Command failed with code ${code}`));
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
child.on('error', reject);
|
|
55
|
+
});
|
|
56
|
+
}
|
|
30
57
|
|
|
31
58
|
// ASCII Art Banner (Clean blocky style like reference image)
|
|
32
59
|
const BANNER = chalk.cyan(`
|
|
@@ -108,20 +135,23 @@ async function main() {
|
|
|
108
135
|
console.log(chalk.blue('⚙️ Setting up project prerequisites...\n'));
|
|
109
136
|
|
|
110
137
|
// Check for git repository
|
|
138
|
+
// INS-2 Performance: Use async exec (AC7)
|
|
111
139
|
let hasGit = false;
|
|
112
140
|
try {
|
|
113
|
-
|
|
141
|
+
await execAsync('git rev-parse --git-dir', { cwd: projectRoot });
|
|
114
142
|
hasGit = true;
|
|
115
143
|
} catch (_err) {
|
|
116
144
|
// Not a git repo
|
|
117
145
|
}
|
|
118
146
|
|
|
119
147
|
if (!hasGit) {
|
|
148
|
+
// INS-2 Performance: Add spinner for git init (AC9)
|
|
149
|
+
const gitSpinner = ora('Initializing git repository...').start();
|
|
120
150
|
try {
|
|
121
|
-
|
|
122
|
-
|
|
151
|
+
await execAsync('git init', { cwd: projectRoot });
|
|
152
|
+
gitSpinner.succeed('Git repository initialized');
|
|
123
153
|
} catch (_err) {
|
|
124
|
-
|
|
154
|
+
gitSpinner.fail('Failed to initialize git repository');
|
|
125
155
|
process.exit(1);
|
|
126
156
|
}
|
|
127
157
|
}
|
|
@@ -140,7 +170,8 @@ async function main() {
|
|
|
140
170
|
author: '',
|
|
141
171
|
license: 'ISC',
|
|
142
172
|
};
|
|
143
|
-
|
|
173
|
+
// INS-2 Performance: Use async write instead of sync
|
|
174
|
+
await fse.writeFile(packageJsonPath, JSON.stringify(defaultPackage, null, 2));
|
|
144
175
|
console.log(chalk.green('✓') + ' package.json created');
|
|
145
176
|
}
|
|
146
177
|
|
|
@@ -151,7 +182,8 @@ async function main() {
|
|
|
151
182
|
|
|
152
183
|
// If still no context, create minimal one
|
|
153
184
|
if (!context) {
|
|
154
|
-
|
|
185
|
+
// INS-2 Performance: Use async read instead of sync
|
|
186
|
+
const packageJson = JSON.parse(await fse.readFile(packageJsonPath, 'utf8'));
|
|
155
187
|
context = {
|
|
156
188
|
projectRoot,
|
|
157
189
|
packageName: packageJson.name,
|
|
@@ -328,10 +360,12 @@ async function main() {
|
|
|
328
360
|
};
|
|
329
361
|
|
|
330
362
|
const configPath = path.join(context.projectRoot, '.aios-installation-config.yaml');
|
|
331
|
-
|
|
363
|
+
// INS-2 Performance: Use async write instead of sync
|
|
364
|
+
await fse.writeFile(configPath, yaml.dump(config));
|
|
332
365
|
|
|
333
366
|
// Update .gitignore
|
|
334
|
-
|
|
367
|
+
// INS-2 Performance: Now async
|
|
368
|
+
await updateGitIgnore(installMode, context.projectRoot);
|
|
335
369
|
|
|
336
370
|
// Step 2: PM Tool
|
|
337
371
|
console.log('');
|
|
@@ -350,7 +384,8 @@ async function main() {
|
|
|
350
384
|
]);
|
|
351
385
|
|
|
352
386
|
// Save PM config
|
|
353
|
-
|
|
387
|
+
// INS-2 Performance: Now async
|
|
388
|
+
await savePMConfig(pmTool, {}, context.projectRoot);
|
|
354
389
|
|
|
355
390
|
// Step 3: IDE Selection (CHECKBOX with instructions)
|
|
356
391
|
console.log('');
|
|
@@ -369,19 +404,19 @@ async function main() {
|
|
|
369
404
|
message: chalk.white('Which IDE(s) will you use?'),
|
|
370
405
|
choices: [
|
|
371
406
|
{
|
|
372
|
-
name: ' Claude Code ' + chalk.blue('(
|
|
407
|
+
name: ' Claude Code ' + chalk.blue('(v4)') + chalk.gray(' - Recommended'),
|
|
373
408
|
value: 'claude',
|
|
374
409
|
checked: true,
|
|
375
410
|
},
|
|
376
|
-
{ name: ' Cursor ' + chalk.blue('(
|
|
377
|
-
{ name: ' Windsurf ' + chalk.blue('(
|
|
378
|
-
{ name: ' Trae ' + chalk.blue('(
|
|
379
|
-
{ name: ' Roo Code ' + chalk.blue('(
|
|
380
|
-
{ name: ' Cline ' + chalk.blue('(
|
|
381
|
-
{ name: ' Gemini CLI ' + chalk.blue('(
|
|
382
|
-
{ name: ' GitHub Copilot ' + chalk.blue('(
|
|
411
|
+
{ name: ' Cursor ' + chalk.blue('(v4)'), value: 'cursor' },
|
|
412
|
+
{ name: ' Windsurf ' + chalk.blue('(v4)'), value: 'windsurf' },
|
|
413
|
+
{ name: ' Trae ' + chalk.blue('(v4)'), value: 'trae' },
|
|
414
|
+
{ name: ' Roo Code ' + chalk.blue('(v4)'), value: 'roo' },
|
|
415
|
+
{ name: ' Cline ' + chalk.blue('(v4)'), value: 'cline' },
|
|
416
|
+
{ name: ' Gemini CLI ' + chalk.blue('(v4)'), value: 'gemini' },
|
|
417
|
+
{ name: ' GitHub Copilot ' + chalk.blue('(v4)'), value: 'github-copilot' },
|
|
383
418
|
{
|
|
384
|
-
name: ' AntiGravity ' + chalk.blue('(
|
|
419
|
+
name: ' AntiGravity ' + chalk.blue('(v4)') + chalk.gray(' - Google AI IDE'),
|
|
385
420
|
value: 'antigravity',
|
|
386
421
|
},
|
|
387
422
|
new inquirer.Separator(chalk.gray('─'.repeat(40))),
|
|
@@ -409,15 +444,26 @@ async function main() {
|
|
|
409
444
|
console.log('');
|
|
410
445
|
console.log(chalk.blue('🔍 Checking CLI tools...'));
|
|
411
446
|
|
|
447
|
+
// INS-2 Performance: Check CLI tools in parallel (AC7)
|
|
448
|
+
const toolCheckResults = await Promise.all(
|
|
449
|
+
cliToolsToCheck.map(async (tool) => {
|
|
450
|
+
try {
|
|
451
|
+
const checkCmd = process.platform === 'win32' ? `where ${tool.command}` : `command -v ${tool.command}`;
|
|
452
|
+
await execAsync(checkCmd);
|
|
453
|
+
return { tool, installed: true };
|
|
454
|
+
} catch {
|
|
455
|
+
return { tool, installed: false };
|
|
456
|
+
}
|
|
457
|
+
})
|
|
458
|
+
);
|
|
459
|
+
|
|
412
460
|
const missingTools = [];
|
|
413
|
-
for (const
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
console.log(chalk.
|
|
418
|
-
|
|
419
|
-
console.log(chalk.yellow('⚠') + ` ${tool.name} is not installed`);
|
|
420
|
-
missingTools.push(tool);
|
|
461
|
+
for (const result of toolCheckResults) {
|
|
462
|
+
if (result.installed) {
|
|
463
|
+
console.log(chalk.green('✓') + ` ${result.tool.name} is installed`);
|
|
464
|
+
} else {
|
|
465
|
+
console.log(chalk.yellow('⚠') + ` ${result.tool.name} is not installed`);
|
|
466
|
+
missingTools.push(result.tool);
|
|
421
467
|
}
|
|
422
468
|
}
|
|
423
469
|
|
|
@@ -437,7 +483,8 @@ async function main() {
|
|
|
437
483
|
for (const tool of missingTools) {
|
|
438
484
|
console.log(chalk.blue(`📥 Installing ${tool.name}...`));
|
|
439
485
|
try {
|
|
440
|
-
|
|
486
|
+
// INS-2 Performance: Use async spawn instead of sync (AC7)
|
|
487
|
+
await spawnAsync(`npm install -g ${tool.npm}`);
|
|
441
488
|
console.log(chalk.green('✓') + ` ${tool.name} installed successfully`);
|
|
442
489
|
|
|
443
490
|
// Show post-install instructions
|
|
@@ -462,16 +509,16 @@ async function main() {
|
|
|
462
509
|
|
|
463
510
|
// Step 4b: Copy AIOS Core files
|
|
464
511
|
console.log('');
|
|
465
|
-
console.log(chalk.blue('📦 Installing AIOS Core files...'));
|
|
466
512
|
|
|
467
513
|
const sourceCoreDir = path.join(context.frameworkLocation, '.aios-core');
|
|
468
514
|
const targetCoreDir = path.join(context.projectRoot, '.aios-core');
|
|
469
515
|
|
|
470
516
|
if (fs.existsSync(sourceCoreDir)) {
|
|
517
|
+
// INS-2 Performance: Add spinner for file copy (AC9)
|
|
518
|
+
const copySpinner = ora('Installing AIOS Core files...').start();
|
|
471
519
|
await fse.copy(sourceCoreDir, targetCoreDir);
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
' AIOS Core files installed ' +
|
|
520
|
+
copySpinner.succeed(
|
|
521
|
+
'AIOS Core files installed ' +
|
|
475
522
|
chalk.gray('(11 agents, 68 tasks, 23 templates)')
|
|
476
523
|
);
|
|
477
524
|
|
|
@@ -540,10 +587,25 @@ async function main() {
|
|
|
540
587
|
}
|
|
541
588
|
}
|
|
542
589
|
|
|
590
|
+
// INS-2 Performance: Cache directory listings to avoid redundant readdirSync calls
|
|
591
|
+
// The same agent/task directories are read 6-7 times across IDE installations
|
|
592
|
+
// This reduces directory reads from 6-7x to 1x (AC3)
|
|
593
|
+
const coreAgentsSource = path.join(targetCoreDir, 'development', 'agents');
|
|
594
|
+
const coreTasksSource = path.join(targetCoreDir, 'development', 'tasks');
|
|
595
|
+
|
|
596
|
+
// Cache agent files list (read once, use many times)
|
|
597
|
+
const cachedAgentFiles = fs.existsSync(coreAgentsSource)
|
|
598
|
+
? fs.readdirSync(coreAgentsSource).filter((f) => f.endsWith('.md'))
|
|
599
|
+
: [];
|
|
600
|
+
|
|
601
|
+
// Cache task files list
|
|
602
|
+
const cachedTaskFiles = fs.existsSync(coreTasksSource)
|
|
603
|
+
? fs.readdirSync(coreTasksSource).filter((f) => f.endsWith('.md'))
|
|
604
|
+
: [];
|
|
605
|
+
|
|
543
606
|
// Step 2: Install AIOS CORE agents and tasks for Claude Code
|
|
544
|
-
//
|
|
607
|
+
// v4: Agents and tasks are in development/ module
|
|
545
608
|
if (ides.includes('claude')) {
|
|
546
|
-
const coreAgentsSource = path.join(targetCoreDir, 'development', 'agents');
|
|
547
609
|
const coreAgentsTarget = path.join(
|
|
548
610
|
context.projectRoot,
|
|
549
611
|
'.claude',
|
|
@@ -552,7 +614,6 @@ async function main() {
|
|
|
552
614
|
'agents'
|
|
553
615
|
);
|
|
554
616
|
|
|
555
|
-
const coreTasksSource = path.join(targetCoreDir, 'development', 'tasks');
|
|
556
617
|
const coreTasksTarget = path.join(
|
|
557
618
|
context.projectRoot,
|
|
558
619
|
'.claude',
|
|
@@ -561,16 +622,14 @@ async function main() {
|
|
|
561
622
|
'tasks'
|
|
562
623
|
);
|
|
563
624
|
|
|
564
|
-
if (
|
|
625
|
+
if (cachedAgentFiles.length > 0) {
|
|
565
626
|
await fse.copy(coreAgentsSource, coreAgentsTarget);
|
|
566
|
-
|
|
567
|
-
console.log(chalk.green('✓') + ` Claude Code CORE agents installed (${agentCount} agents)`);
|
|
627
|
+
console.log(chalk.green('✓') + ` Claude Code CORE agents installed (${cachedAgentFiles.length} agents)`);
|
|
568
628
|
}
|
|
569
629
|
|
|
570
|
-
if (
|
|
630
|
+
if (cachedTaskFiles.length > 0) {
|
|
571
631
|
await fse.copy(coreTasksSource, coreTasksTarget);
|
|
572
|
-
|
|
573
|
-
console.log(chalk.green('✓') + ` Claude Code CORE tasks installed (${taskCount} tasks)`);
|
|
632
|
+
console.log(chalk.green('✓') + ` Claude Code CORE tasks installed (${cachedTaskFiles.length} tasks)`);
|
|
574
633
|
}
|
|
575
634
|
|
|
576
635
|
// Create AIOS README for Claude Code
|
|
@@ -599,9 +658,9 @@ See .aios-core/user-guide.md for complete documentation.
|
|
|
599
658
|
}
|
|
600
659
|
|
|
601
660
|
// Step 3: Install AIOS CORE agents for Cursor
|
|
602
|
-
//
|
|
661
|
+
// v4: Agents are in development/ module
|
|
662
|
+
// INS-2 Performance: Uses cached agent files list
|
|
603
663
|
if (ides.includes('cursor')) {
|
|
604
|
-
const coreAgentsSource = path.join(targetCoreDir, 'development', 'agents');
|
|
605
664
|
const cursorRulesTarget = path.join(
|
|
606
665
|
context.projectRoot,
|
|
607
666
|
'.cursor',
|
|
@@ -610,12 +669,11 @@ See .aios-core/user-guide.md for complete documentation.
|
|
|
610
669
|
'agents'
|
|
611
670
|
);
|
|
612
671
|
|
|
613
|
-
if (
|
|
672
|
+
if (cachedAgentFiles.length > 0) {
|
|
614
673
|
await fse.ensureDir(cursorRulesTarget);
|
|
615
674
|
|
|
616
|
-
// Convert .md files to .mdc for Cursor
|
|
617
|
-
const
|
|
618
|
-
for (const agentFile of agentFiles) {
|
|
675
|
+
// Convert .md files to .mdc for Cursor (using cached list)
|
|
676
|
+
for (const agentFile of cachedAgentFiles) {
|
|
619
677
|
const sourcePath = path.join(coreAgentsSource, agentFile);
|
|
620
678
|
const targetFileName = agentFile.replace('.md', '.mdc');
|
|
621
679
|
const targetPath = path.join(cursorRulesTarget, targetFileName);
|
|
@@ -623,7 +681,7 @@ See .aios-core/user-guide.md for complete documentation.
|
|
|
623
681
|
}
|
|
624
682
|
|
|
625
683
|
console.log(
|
|
626
|
-
chalk.green('✓') + ` Cursor CORE rules installed (${
|
|
684
|
+
chalk.green('✓') + ` Cursor CORE rules installed (${cachedAgentFiles.length} agents)`
|
|
627
685
|
);
|
|
628
686
|
}
|
|
629
687
|
|
|
@@ -646,11 +704,11 @@ See .aios-core/user-guide.md for complete documentation.
|
|
|
646
704
|
}
|
|
647
705
|
|
|
648
706
|
// Step 4: Install AIOS CORE agents for other IDEs (Trae, Cline, Gemini, AntiGravity)
|
|
649
|
-
//
|
|
707
|
+
// v4: Agents are in development/ module
|
|
708
|
+
// INS-2 Performance: Uses cached agent files list
|
|
650
709
|
const otherIdeInstalls = ['trae', 'cline', 'gemini', 'antigravity'];
|
|
651
710
|
for (const ide of otherIdeInstalls) {
|
|
652
711
|
if (ides.includes(ide)) {
|
|
653
|
-
const coreAgentsSource = path.join(targetCoreDir, 'development', 'agents');
|
|
654
712
|
const ideRulesDir = ide === 'gemini' ? '.gemini' : `.${ide}`;
|
|
655
713
|
const ideRulesTarget = path.join(
|
|
656
714
|
context.projectRoot,
|
|
@@ -660,12 +718,11 @@ See .aios-core/user-guide.md for complete documentation.
|
|
|
660
718
|
'agents'
|
|
661
719
|
);
|
|
662
720
|
|
|
663
|
-
if (
|
|
721
|
+
if (cachedAgentFiles.length > 0) {
|
|
664
722
|
await fse.ensureDir(ideRulesTarget);
|
|
665
723
|
|
|
666
|
-
// Copy agent files
|
|
667
|
-
const
|
|
668
|
-
for (const agentFile of agentFiles) {
|
|
724
|
+
// Copy agent files (using cached list)
|
|
725
|
+
for (const agentFile of cachedAgentFiles) {
|
|
669
726
|
const sourcePath = path.join(coreAgentsSource, agentFile);
|
|
670
727
|
const targetPath = path.join(ideRulesTarget, agentFile);
|
|
671
728
|
await fse.copy(sourcePath, targetPath);
|
|
@@ -673,24 +730,22 @@ See .aios-core/user-guide.md for complete documentation.
|
|
|
673
730
|
|
|
674
731
|
const ideName = ide.charAt(0).toUpperCase() + ide.slice(1);
|
|
675
732
|
console.log(
|
|
676
|
-
chalk.green('✓') + ` ${ideName} CORE agents installed (${
|
|
733
|
+
chalk.green('✓') + ` ${ideName} CORE agents installed (${cachedAgentFiles.length} agents)`
|
|
677
734
|
);
|
|
678
735
|
}
|
|
679
736
|
}
|
|
680
737
|
}
|
|
681
738
|
|
|
682
739
|
// Step 5: Install Roo Code modes
|
|
683
|
-
//
|
|
740
|
+
// v4: Agents are in development/ module
|
|
741
|
+
// INS-2 Performance: Uses cached agent files list
|
|
684
742
|
if (ides.includes('roo')) {
|
|
685
|
-
const coreAgentsSource = path.join(targetCoreDir, 'development', 'agents');
|
|
686
743
|
const rooModesPath = path.join(context.projectRoot, '.roomodes');
|
|
687
744
|
|
|
688
|
-
if (
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
// Create .roomodes JSON file
|
|
745
|
+
if (cachedAgentFiles.length > 0) {
|
|
746
|
+
// Create .roomodes JSON file (using cached list)
|
|
692
747
|
const roomodes = {
|
|
693
|
-
customModes:
|
|
748
|
+
customModes: cachedAgentFiles.map((f) => {
|
|
694
749
|
const agentName = f.replace('.md', '');
|
|
695
750
|
return {
|
|
696
751
|
slug: `bmad-${agentName}`,
|
|
@@ -703,21 +758,21 @@ See .aios-core/user-guide.md for complete documentation.
|
|
|
703
758
|
};
|
|
704
759
|
|
|
705
760
|
await fse.writeFile(rooModesPath, JSON.stringify(roomodes, null, 2));
|
|
706
|
-
console.log(chalk.green('✓') + ` Roo Code modes installed (${
|
|
761
|
+
console.log(chalk.green('✓') + ` Roo Code modes installed (${cachedAgentFiles.length} modes)`);
|
|
707
762
|
}
|
|
708
763
|
}
|
|
709
764
|
|
|
710
765
|
// Step 6: Install GitHub Copilot chat modes
|
|
711
|
-
//
|
|
766
|
+
// v4: Agents are in development/ module
|
|
767
|
+
// INS-2 Performance: Uses cached agent files list
|
|
712
768
|
if (ides.includes('github-copilot')) {
|
|
713
|
-
const coreAgentsSource = path.join(targetCoreDir, 'development', 'agents');
|
|
714
769
|
const copilotModesDir = path.join(context.projectRoot, '.github', 'chatmodes');
|
|
715
770
|
|
|
716
|
-
if (
|
|
771
|
+
if (cachedAgentFiles.length > 0) {
|
|
717
772
|
await fse.ensureDir(copilotModesDir);
|
|
718
773
|
|
|
719
|
-
|
|
720
|
-
for (const agentFile of
|
|
774
|
+
// Copy agent files (using cached list)
|
|
775
|
+
for (const agentFile of cachedAgentFiles) {
|
|
721
776
|
const sourcePath = path.join(coreAgentsSource, agentFile);
|
|
722
777
|
const agentName = agentFile.replace('.md', '');
|
|
723
778
|
const targetPath = path.join(copilotModesDir, `aios-${agentName}.md`);
|
|
@@ -725,52 +780,55 @@ See .aios-core/user-guide.md for complete documentation.
|
|
|
725
780
|
}
|
|
726
781
|
|
|
727
782
|
console.log(
|
|
728
|
-
chalk.green('✓') + ` GitHub Copilot chat modes installed (${
|
|
783
|
+
chalk.green('✓') + ` GitHub Copilot chat modes installed (${cachedAgentFiles.length} modes)`
|
|
729
784
|
);
|
|
730
785
|
}
|
|
731
786
|
}
|
|
732
787
|
}
|
|
733
788
|
|
|
734
|
-
// Step 7:
|
|
735
|
-
// Try multiple locations for
|
|
789
|
+
// Step 7: Squads (CHECKBOX with visual)
|
|
790
|
+
// Try multiple locations for squads (npm package vs local development vs npx)
|
|
736
791
|
// __dirname is the 'bin/' directory of the package, so '..' gives us the package root
|
|
737
792
|
const packageRoot = path.resolve(__dirname, '..');
|
|
738
793
|
|
|
739
|
-
const
|
|
740
|
-
// Primary: relative to this script (works for npx and local)
|
|
741
|
-
path.join(packageRoot, '
|
|
742
|
-
// Secondary: context-based framework location
|
|
743
|
-
path.join(context.frameworkLocation, '
|
|
744
|
-
// Tertiary: installed in project's node_modules
|
|
745
|
-
path.join(context.projectRoot, 'node_modules', '@synkra/aios-core', '
|
|
746
|
-
path.join(context.projectRoot, 'node_modules', '@aios', 'fullstack', '
|
|
794
|
+
const possibleSquadsDirs = [
|
|
795
|
+
// Primary: relative to this script (works for npx and local) - squads/
|
|
796
|
+
path.join(packageRoot, 'squads'),
|
|
797
|
+
// Secondary: context-based framework location - squads/
|
|
798
|
+
path.join(context.frameworkLocation, 'squads'),
|
|
799
|
+
// Tertiary: installed in project's node_modules - squads/
|
|
800
|
+
path.join(context.projectRoot, 'node_modules', '@synkra/aios-core', 'squads'),
|
|
801
|
+
path.join(context.projectRoot, 'node_modules', '@aios', 'fullstack', 'squads'),
|
|
747
802
|
];
|
|
748
803
|
|
|
749
|
-
let
|
|
750
|
-
for (const dir of
|
|
804
|
+
let sourceSquadsDir = null;
|
|
805
|
+
for (const dir of possibleSquadsDirs) {
|
|
751
806
|
if (fs.existsSync(dir)) {
|
|
752
|
-
|
|
807
|
+
sourceSquadsDir = dir;
|
|
753
808
|
break;
|
|
754
809
|
}
|
|
755
810
|
}
|
|
756
811
|
|
|
757
|
-
const
|
|
758
|
-
let
|
|
812
|
+
const availableSquads = [];
|
|
813
|
+
let selectedSquads = []; // Declare here to be accessible in summary
|
|
759
814
|
|
|
760
|
-
if (
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
815
|
+
if (sourceSquadsDir && fs.existsSync(sourceSquadsDir)) {
|
|
816
|
+
// INS-2 Performance: Use withFileTypes to avoid separate statSync calls per entry
|
|
817
|
+
// This reduces N+1 syscalls to just 1 syscall for the entire directory
|
|
818
|
+
let squads = fs
|
|
819
|
+
.readdirSync(sourceSquadsDir, { withFileTypes: true })
|
|
820
|
+
.filter((dirent) => dirent.isDirectory())
|
|
821
|
+
.map((dirent) => dirent.name);
|
|
764
822
|
|
|
765
|
-
// Filter for minimal mode - only show
|
|
823
|
+
// Filter for minimal mode - only show squad-creator
|
|
766
824
|
if (isMinimalMode) {
|
|
767
|
-
|
|
825
|
+
squads = squads.filter((squad) => squad === 'squad-creator');
|
|
768
826
|
}
|
|
769
827
|
|
|
770
|
-
|
|
828
|
+
availableSquads.push(...squads);
|
|
771
829
|
}
|
|
772
830
|
|
|
773
|
-
if (
|
|
831
|
+
if (availableSquads.length > 0) {
|
|
774
832
|
console.log('');
|
|
775
833
|
console.log(chalk.gray('─'.repeat(80)));
|
|
776
834
|
console.log(
|
|
@@ -783,96 +841,103 @@ See .aios-core/user-guide.md for complete documentation.
|
|
|
783
841
|
const result = await inquirer.prompt([
|
|
784
842
|
{
|
|
785
843
|
type: 'checkbox',
|
|
786
|
-
name: '
|
|
787
|
-
message: chalk.white('Select
|
|
788
|
-
choices:
|
|
789
|
-
name: ' ' +
|
|
790
|
-
value:
|
|
844
|
+
name: 'selectedSquads',
|
|
845
|
+
message: chalk.white('Select squads to install (optional)'),
|
|
846
|
+
choices: availableSquads.map((squad) => ({
|
|
847
|
+
name: ' ' + squad,
|
|
848
|
+
value: squad,
|
|
791
849
|
})),
|
|
792
850
|
},
|
|
793
851
|
]);
|
|
794
852
|
|
|
795
|
-
|
|
853
|
+
selectedSquads = result.selectedSquads; // Assign to outer scope variable
|
|
796
854
|
|
|
797
|
-
if (
|
|
855
|
+
if (selectedSquads.length > 0) {
|
|
798
856
|
console.log('');
|
|
799
|
-
console.log(chalk.blue('📦 Installing
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
857
|
+
console.log(chalk.blue('📦 Installing squads...'));
|
|
858
|
+
|
|
859
|
+
// Always install to squads/ directory (modern naming)
|
|
860
|
+
const targetSquadsDir = path.join(context.projectRoot, 'squads');
|
|
861
|
+
|
|
862
|
+
// INS-2 Performance: Copy all squads in parallel first (AC6)
|
|
863
|
+
await Promise.all(
|
|
864
|
+
selectedSquads.map(async (squad) => {
|
|
865
|
+
const sourceSquad = path.join(sourceSquadsDir, squad);
|
|
866
|
+
const targetSquad = path.join(targetSquadsDir, squad);
|
|
867
|
+
await fse.copy(sourceSquad, targetSquad);
|
|
868
|
+
})
|
|
869
|
+
);
|
|
870
|
+
console.log(chalk.green('✓') + ` Squads copied: ${selectedSquads.join(', ')}`);
|
|
871
|
+
|
|
872
|
+
// Process IDE-specific installations sequentially for ordered logging
|
|
873
|
+
for (const squad of selectedSquads) {
|
|
874
|
+
const targetSquad = path.join(targetSquadsDir, squad);
|
|
875
|
+
|
|
876
|
+
// INS-2 Performance: Cache squad file lists once per squad (used by Claude, Cursor, etc.)
|
|
877
|
+
const squadAgentsSource = path.join(targetSquad, 'agents');
|
|
878
|
+
const squadTasksSource = path.join(targetSquad, 'tasks');
|
|
879
|
+
const squadReadmeSource = path.join(targetSquad, 'README.md');
|
|
880
|
+
|
|
881
|
+
// Cache squad agents/tasks lists (read once per squad, use for all IDEs)
|
|
882
|
+
const squadAgentFiles = fs.existsSync(squadAgentsSource)
|
|
883
|
+
? fs.readdirSync(squadAgentsSource).filter((f) => f.endsWith('.md'))
|
|
884
|
+
: [];
|
|
885
|
+
const squadTaskFiles = fs.existsSync(squadTasksSource)
|
|
886
|
+
? fs.readdirSync(squadTasksSource).filter((f) => f.endsWith('.md'))
|
|
887
|
+
: [];
|
|
888
|
+
const hasSquadReadme = fs.existsSync(squadReadmeSource);
|
|
889
|
+
|
|
890
|
+
// Install squad agents/tasks for Claude Code
|
|
810
891
|
if (ides.includes('claude')) {
|
|
811
|
-
const
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
if (fs.existsSync(packAgentsSource)) {
|
|
819
|
-
const packAgentsTarget = path.join(packClaudeTarget, 'agents');
|
|
820
|
-
await fse.copy(packAgentsSource, packAgentsTarget);
|
|
821
|
-
const agentCount = fs
|
|
822
|
-
.readdirSync(packAgentsSource)
|
|
823
|
-
.filter((f) => f.endsWith('.md')).length;
|
|
824
|
-
console.log(chalk.green(' ✓') + ` Claude Code ${pack} agents (${agentCount} agents)`);
|
|
892
|
+
const squadClaudeTarget = path.join(context.projectRoot, '.claude', 'commands', squad);
|
|
893
|
+
|
|
894
|
+
// Copy agents (using cached list)
|
|
895
|
+
if (squadAgentFiles.length > 0) {
|
|
896
|
+
const squadAgentsTarget = path.join(squadClaudeTarget, 'agents');
|
|
897
|
+
await fse.copy(squadAgentsSource, squadAgentsTarget);
|
|
898
|
+
console.log(chalk.green(' ✓') + ` Claude Code ${squad} agents (${squadAgentFiles.length} agents)`);
|
|
825
899
|
}
|
|
826
900
|
|
|
827
|
-
// Copy tasks
|
|
828
|
-
if (
|
|
829
|
-
const
|
|
830
|
-
await fse.copy(
|
|
831
|
-
|
|
832
|
-
.readdirSync(packTasksSource)
|
|
833
|
-
.filter((f) => f.endsWith('.md')).length;
|
|
834
|
-
console.log(chalk.green(' ✓') + ` Claude Code ${pack} tasks (${taskCount} tasks)`);
|
|
901
|
+
// Copy tasks (using cached list)
|
|
902
|
+
if (squadTaskFiles.length > 0) {
|
|
903
|
+
const squadTasksTarget = path.join(squadClaudeTarget, 'tasks');
|
|
904
|
+
await fse.copy(squadTasksSource, squadTasksTarget);
|
|
905
|
+
console.log(chalk.green(' ✓') + ` Claude Code ${squad} tasks (${squadTaskFiles.length} tasks)`);
|
|
835
906
|
}
|
|
836
907
|
|
|
837
|
-
// Copy README
|
|
838
|
-
if (
|
|
839
|
-
await fse.copy(
|
|
908
|
+
// Copy README (using cached check)
|
|
909
|
+
if (hasSquadReadme) {
|
|
910
|
+
await fse.copy(squadReadmeSource, path.join(squadClaudeTarget, 'README.md'));
|
|
840
911
|
}
|
|
841
912
|
}
|
|
842
913
|
|
|
843
|
-
// Install
|
|
844
|
-
if (ides.includes('cursor')) {
|
|
845
|
-
const
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
const sourcePath = path.join(packAgentsSource, agentFile);
|
|
862
|
-
const targetFileName = agentFile.replace('.md', '.mdc');
|
|
863
|
-
const targetPath = path.join(cursorPackTarget, targetFileName);
|
|
864
|
-
await fse.copy(sourcePath, targetPath);
|
|
865
|
-
}
|
|
914
|
+
// Install squad agents for Cursor
|
|
915
|
+
if (ides.includes('cursor') && squadAgentFiles.length > 0) {
|
|
916
|
+
const cursorSquadTarget = path.join(
|
|
917
|
+
context.projectRoot,
|
|
918
|
+
'.cursor',
|
|
919
|
+
'rules',
|
|
920
|
+
squad,
|
|
921
|
+
'agents'
|
|
922
|
+
);
|
|
923
|
+
await fse.ensureDir(cursorSquadTarget);
|
|
924
|
+
|
|
925
|
+
// Convert .md files to .mdc for Cursor (using cached list)
|
|
926
|
+
for (const agentFile of squadAgentFiles) {
|
|
927
|
+
const sourcePath = path.join(squadAgentsSource, agentFile);
|
|
928
|
+
const targetFileName = agentFile.replace('.md', '.mdc');
|
|
929
|
+
const targetPath = path.join(cursorSquadTarget, targetFileName);
|
|
930
|
+
await fse.copy(sourcePath, targetPath);
|
|
931
|
+
}
|
|
866
932
|
|
|
867
|
-
|
|
933
|
+
console.log(chalk.green(' ✓') + ` Cursor ${squad} rules (${squadAgentFiles.length} agents)`);
|
|
868
934
|
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
}
|
|
935
|
+
// Copy README for Cursor (using cached check)
|
|
936
|
+
if (hasSquadReadme) {
|
|
937
|
+
await fse.copy(
|
|
938
|
+
squadReadmeSource,
|
|
939
|
+
path.join(context.projectRoot, '.cursor', 'rules', squad, 'README.md')
|
|
940
|
+
);
|
|
876
941
|
}
|
|
877
942
|
}
|
|
878
943
|
}
|
|
@@ -881,7 +946,8 @@ See .aios-core/user-guide.md for complete documentation.
|
|
|
881
946
|
|
|
882
947
|
// Post-installation validation (Story 6.19)
|
|
883
948
|
console.log('');
|
|
884
|
-
|
|
949
|
+
// INS-2 Performance: Add spinner for validation (AC9)
|
|
950
|
+
const validationSpinner = ora('Validating installation integrity...').start();
|
|
885
951
|
|
|
886
952
|
let validationPassed = true;
|
|
887
953
|
try {
|
|
@@ -905,7 +971,7 @@ See .aios-core/user-guide.md for complete documentation.
|
|
|
905
971
|
report.stats.corruptedFiles > 0
|
|
906
972
|
) {
|
|
907
973
|
validationPassed = false;
|
|
908
|
-
|
|
974
|
+
validationSpinner.warn('Installation validation found issues:');
|
|
909
975
|
console.log(chalk.dim(` - Missing files: ${report.stats.missingFiles}`));
|
|
910
976
|
console.log(chalk.dim(` - Corrupted files: ${report.stats.corruptedFiles}`));
|
|
911
977
|
console.log('');
|
|
@@ -915,14 +981,14 @@ See .aios-core/user-guide.md for complete documentation.
|
|
|
915
981
|
chalk.yellow(' to fix issues')
|
|
916
982
|
);
|
|
917
983
|
} else {
|
|
918
|
-
|
|
984
|
+
validationSpinner.succeed(`Installation verified (${report.stats.validFiles} files)`);
|
|
919
985
|
}
|
|
920
986
|
} catch (validationError) {
|
|
921
987
|
// Log validation errors but don't fail installation
|
|
922
988
|
// This allows installation to proceed even if validator module has issues
|
|
923
989
|
// However, users should investigate validation errors manually
|
|
924
990
|
validationPassed = false;
|
|
925
|
-
|
|
991
|
+
validationSpinner.warn('Post-installation validation encountered an error');
|
|
926
992
|
console.log(chalk.dim(` Error: ${validationError.message}`));
|
|
927
993
|
if (process.env.DEBUG || process.env.AIOS_DEBUG) {
|
|
928
994
|
console.log(chalk.dim(` Stack: ${validationError.stack}`));
|
|
@@ -945,8 +1011,8 @@ See .aios-core/user-guide.md for complete documentation.
|
|
|
945
1011
|
);
|
|
946
1012
|
console.log(' ' + chalk.dim('PM Tool: ') + pmTool);
|
|
947
1013
|
|
|
948
|
-
if (
|
|
949
|
-
console.log(' ' + chalk.dim('
|
|
1014
|
+
if (availableSquads.length > 0 && selectedSquads && selectedSquads.length > 0) {
|
|
1015
|
+
console.log(' ' + chalk.dim('Squads: ') + ' ' + selectedSquads.join(', '));
|
|
950
1016
|
}
|
|
951
1017
|
|
|
952
1018
|
console.log('');
|
|
@@ -958,9 +1024,9 @@ See .aios-core/user-guide.md for complete documentation.
|
|
|
958
1024
|
console.log(' ' + chalk.dim('├─ CLAUDE.md') + ' - Main configuration');
|
|
959
1025
|
console.log(' ' + chalk.dim('└─ commands/'));
|
|
960
1026
|
console.log(' ' + chalk.dim(' ├─ AIOS/') + ' - Core agents & tasks');
|
|
961
|
-
if (
|
|
962
|
-
|
|
963
|
-
console.log(' ' + chalk.dim(` └─ ${
|
|
1027
|
+
if (selectedSquads && selectedSquads.length > 0) {
|
|
1028
|
+
selectedSquads.forEach((squad) => {
|
|
1029
|
+
console.log(' ' + chalk.dim(` └─ ${squad}/`) + ' - Squad commands');
|
|
964
1030
|
});
|
|
965
1031
|
}
|
|
966
1032
|
}
|
|
@@ -970,9 +1036,9 @@ See .aios-core/user-guide.md for complete documentation.
|
|
|
970
1036
|
console.log(' ' + chalk.dim('├─ rules.md') + ' - Main configuration');
|
|
971
1037
|
console.log(' ' + chalk.dim('└─ rules/'));
|
|
972
1038
|
console.log(' ' + chalk.dim(' ├─ AIOS/') + ' - Core agent rules');
|
|
973
|
-
if (
|
|
974
|
-
|
|
975
|
-
console.log(' ' + chalk.dim(` └─ ${
|
|
1039
|
+
if (selectedSquads && selectedSquads.length > 0) {
|
|
1040
|
+
selectedSquads.forEach((squad) => {
|
|
1041
|
+
console.log(' ' + chalk.dim(` └─ ${squad}/`) + ' - Squad rules');
|
|
976
1042
|
});
|
|
977
1043
|
}
|
|
978
1044
|
}
|
|
@@ -1047,7 +1113,7 @@ See .aios-core/user-guide.md for complete documentation.
|
|
|
1047
1113
|
console.log(' • Run ' + chalk.yellow('aios validate') + ' to verify installation integrity');
|
|
1048
1114
|
console.log(' • Run ' + chalk.yellow('aios validate --repair') + ' to fix any missing files');
|
|
1049
1115
|
console.log(' • Check .aios-core/user-guide.md for complete documentation');
|
|
1050
|
-
console.log(' • Explore
|
|
1116
|
+
console.log(' • Explore squads/ for additional capabilities');
|
|
1051
1117
|
console.log('');
|
|
1052
1118
|
console.log(chalk.gray('═'.repeat(80)));
|
|
1053
1119
|
console.log('');
|
|
@@ -1055,13 +1121,15 @@ See .aios-core/user-guide.md for complete documentation.
|
|
|
1055
1121
|
|
|
1056
1122
|
/**
|
|
1057
1123
|
* Updates .gitignore file based on installation mode
|
|
1124
|
+
* INS-2 Performance: Converted to async
|
|
1058
1125
|
*/
|
|
1059
|
-
function updateGitIgnore(mode, projectRoot) {
|
|
1126
|
+
async function updateGitIgnore(mode, projectRoot) {
|
|
1060
1127
|
const gitignorePath = path.join(projectRoot, '.gitignore');
|
|
1061
1128
|
|
|
1062
1129
|
let gitignore = '';
|
|
1063
1130
|
if (fs.existsSync(gitignorePath)) {
|
|
1064
|
-
|
|
1131
|
+
// INS-2 Performance: Use async read
|
|
1132
|
+
gitignore = await fse.readFile(gitignorePath, 'utf8');
|
|
1065
1133
|
}
|
|
1066
1134
|
|
|
1067
1135
|
if (mode === 'project-development') {
|
|
@@ -1080,15 +1148,17 @@ function updateGitIgnore(mode, projectRoot) {
|
|
|
1080
1148
|
|
|
1081
1149
|
if (!hasFrameworkSection) {
|
|
1082
1150
|
gitignore += frameworkRules.join('\n');
|
|
1083
|
-
|
|
1151
|
+
// INS-2 Performance: Use async write
|
|
1152
|
+
await fse.writeFile(gitignorePath, gitignore);
|
|
1084
1153
|
}
|
|
1085
1154
|
}
|
|
1086
1155
|
}
|
|
1087
1156
|
|
|
1088
1157
|
/**
|
|
1089
1158
|
* Save PM configuration
|
|
1159
|
+
* INS-2 Performance: Converted to async
|
|
1090
1160
|
*/
|
|
1091
|
-
function savePMConfig(pmTool, config, projectRoot) {
|
|
1161
|
+
async function savePMConfig(pmTool, config, projectRoot) {
|
|
1092
1162
|
const pmConfigData = {
|
|
1093
1163
|
pm_tool: {
|
|
1094
1164
|
type: pmTool,
|
|
@@ -1103,7 +1173,8 @@ function savePMConfig(pmTool, config, projectRoot) {
|
|
|
1103
1173
|
};
|
|
1104
1174
|
|
|
1105
1175
|
const configPath = path.join(projectRoot, '.aios-pm-config.yaml');
|
|
1106
|
-
|
|
1176
|
+
// INS-2 Performance: Use async write
|
|
1177
|
+
await fse.writeFile(configPath, yaml.dump(pmConfigData));
|
|
1107
1178
|
}
|
|
1108
1179
|
|
|
1109
1180
|
// Run installer with error handling
|