aios-core 4.0.0 → 4.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/.aios-core/cli/commands/pro/index.js +82 -148
  2. package/.aios-core/core/synapse/domain/domain-loader.js +2 -2
  3. package/.aios-core/core/synapse/engine.js +17 -4
  4. package/.aios-core/core/synapse/memory/memory-bridge.js +246 -0
  5. package/.aios-core/core/synapse/output/formatter.js +34 -12
  6. package/.aios-core/core/synapse/scripts/generate-constitution.js +204 -0
  7. package/.aios-core/core/synapse/utils/tokens.js +25 -0
  8. package/.aios-core/data/aios-kb.md +2 -4
  9. package/.aios-core/data/entity-registry.yaml +61 -8
  10. package/.aios-core/development/scripts/unified-activation-pipeline.js +9 -1
  11. package/.aios-core/framework-config.yaml +1 -1
  12. package/.aios-core/install-manifest.yaml +33 -21
  13. package/.aios-core/lib/build.json +1 -0
  14. package/.aios-core/package.json +2 -1
  15. package/.aios-core/user-guide.md +1 -1
  16. package/.claude/CLAUDE.md +8 -9
  17. package/.claude/hooks/README.md +169 -0
  18. package/.claude/hooks/precompact-session-digest.js +46 -0
  19. package/.claude/hooks/synapse-engine.js +87 -0
  20. package/bin/aios-init.js +4 -4
  21. package/bin/aios-minimal.js +1 -4
  22. package/bin/aios.js +1 -1
  23. package/bin/modules/env-config.js +0 -1
  24. package/package.json +4 -1
  25. package/packages/aios-pro-cli/bin/aios-pro.js +158 -0
  26. package/packages/aios-pro-cli/package.json +32 -0
  27. package/packages/installer/package.json +1 -1
  28. package/packages/installer/src/installer/aios-core-installer.js +23 -0
  29. package/packages/installer/src/wizard/ide-config-generator.js +146 -1
  30. package/packages/installer/src/wizard/index.js +49 -32
@@ -0,0 +1,169 @@
1
+ # Claude Code Hooks
2
+
3
+ Sistema de governança automática para regras do CLAUDE.md.
4
+
5
+ ## Arquitetura
6
+
7
+ ```
8
+ PreToolUse Hooks
9
+ ├── Read → read-protection.py
10
+ ├── Write|Edit → enforce-architecture-first.py
11
+ │ → write-path-validation.py
12
+ │ → mind-clone-governance.py
13
+ └── Bash → sql-governance.py
14
+ → slug-validation.py
15
+ ```
16
+
17
+ ## Hooks Disponíveis
18
+
19
+ ### 1. read-protection.py
20
+ **Trigger:** `Read`
21
+ **Comportamento:** BLOQUEIA (exit 2)
22
+
23
+ Impede leitura parcial (`limit`/`offset`) em arquivos protegidos:
24
+ - `.claude/CLAUDE.md`
25
+ - `.claude/rules/*.md`
26
+ - `.aios-core/development/agents/*.md`
27
+ - `supabase/docs/SCHEMA.md`
28
+ - `package.json`, `tsconfig.json`
29
+ - `app/components/ui/icons/icon-map.ts`
30
+
31
+ ### 2. enforce-architecture-first.py
32
+ **Trigger:** `Write|Edit`
33
+ **Comportamento:** BLOQUEIA (exit 2)
34
+
35
+ Exige documentação aprovada antes de criar código em paths protegidos:
36
+ - `supabase/functions/` → requer doc em `docs/architecture/` ou `docs/approved-plans/`
37
+ - `supabase/migrations/` → requer doc ou permite edição de arquivo existente
38
+
39
+ ### 3. write-path-validation.py
40
+ **Trigger:** `Write|Edit`
41
+ **Comportamento:** AVISA (exit 0 + stderr)
42
+
43
+ Avisa quando documentos parecem estar no path errado:
44
+ - Sessions/handoffs → `docs/sessions/YYYY-MM/`
45
+ - Architecture → `docs/architecture/`
46
+ - Guides → `docs/guides/`
47
+
48
+ ### 4. sql-governance.py
49
+ **Trigger:** `Bash`
50
+ **Comportamento:** BLOQUEIA (exit 2)
51
+
52
+ Intercepta comandos SQL perigosos:
53
+ - `CREATE TABLE/VIEW/FUNCTION/TRIGGER`
54
+ - `ALTER TABLE`
55
+ - `DROP TABLE/VIEW/FUNCTION`
56
+ - `CREATE TABLE AS SELECT` (backup proibido)
57
+
58
+ **Exceções permitidas:**
59
+ - `supabase migration` (CLI oficial)
60
+ - `pg_dump` (backup/export)
61
+
62
+ ### 5. slug-validation.py
63
+ **Trigger:** `Bash`
64
+ **Comportamento:** BLOQUEIA (exit 2)
65
+
66
+ Valida formato snake_case em slugs:
67
+ - Pattern: `^[a-z0-9]+(_[a-z0-9]+)*$`
68
+ - ✅ `jose_carlos_amorim`
69
+ - ❌ `jose-carlos-amorim` (hyphen)
70
+ - ❌ `JoseAmorim` (camelCase)
71
+
72
+ ### 6. mind-clone-governance.py
73
+ **Trigger:** `Write|Edit`
74
+ **Comportamento:** BLOQUEIA (exit 2)
75
+
76
+ Impede criação de mind clones sem DNA extraído previamente.
77
+
78
+ **O que é bloqueado:**
79
+ - Criar novo arquivo `squads/*/agents/*.md` que pareça ser um mind clone
80
+ - Mind clones = agents baseados em pessoas reais (não funcionais)
81
+
82
+ **O que NÃO é bloqueado:**
83
+ - Editar arquivos existentes (permite updates)
84
+ - Agents funcionais (identificados por sufixo):
85
+ - `-chief`, `-orchestrator`, `-chair`
86
+ - `-validator`, `-calculator`, `-generator`, `-extractor`, `-analyzer`
87
+ - `-architect`, `-mapper`, `-designer`, `-engineer`
88
+ - `tools-*`, `process-*`, `workflow-*`
89
+
90
+ **Locais de DNA verificados:**
91
+ - `squads/{pack}/data/minds/{agent_id}_dna.yaml`
92
+ - `squads/{pack}/data/minds/{agent_id}_dna.md`
93
+ - `squads/{pack}/data/{agent_id}-dna.yaml`
94
+ - `outputs/minds/{agent_id}/`
95
+
96
+ **Solução quando bloqueado:**
97
+ 1. Execute o pipeline de extração de DNA: `/squad-creator` → `*collect-sources` → `*extract-voice-dna` → `*extract-thinking-dna`
98
+ 2. OU se é agent funcional, renomeie com sufixo apropriado
99
+
100
+ ## Exit Codes
101
+
102
+ | Code | Significado |
103
+ |------|-------------|
104
+ | 0 | Permitido (operação continua) |
105
+ | 2 | Bloqueado (operação cancelada, mostra stderr) |
106
+ | Outro | Erro não-bloqueante |
107
+
108
+ ## Input Format
109
+
110
+ Hooks recebem JSON via stdin:
111
+
112
+ ```json
113
+ {
114
+ "session_id": "abc123",
115
+ "hook_event_name": "PreToolUse",
116
+ "tool_name": "Read",
117
+ "tool_input": {
118
+ "file_path": "/path/to/file",
119
+ "limit": 100
120
+ },
121
+ "cwd": "/Users/alan/Code/mmos"
122
+ }
123
+ ```
124
+
125
+ ## Debugging
126
+
127
+ Para testar um hook manualmente:
128
+
129
+ ```bash
130
+ echo '{"tool_name": "Read", "tool_input": {"file_path": ".claude/CLAUDE.md", "limit": 100}}' | python3 .claude/hooks/read-protection.py
131
+ echo $? # Deve retornar 2 (bloqueado)
132
+ ```
133
+
134
+ ## Configuração
135
+
136
+ Hooks são configurados em `.claude/settings.local.json`:
137
+
138
+ ```json
139
+ {
140
+ "hooks": {
141
+ "PreToolUse": [
142
+ {
143
+ "matcher": "Read",
144
+ "hooks": [
145
+ {
146
+ "type": "command",
147
+ "command": "python3 \"$CLAUDE_PROJECT_DIR/.claude/hooks/read-protection.py\"",
148
+ "timeout": 5
149
+ }
150
+ ]
151
+ }
152
+ ]
153
+ }
154
+ }
155
+ ```
156
+
157
+ ## Manutenção
158
+
159
+ Para adicionar novo hook:
160
+
161
+ 1. Criar arquivo `.claude/hooks/novo-hook.py`
162
+ 2. Adicionar entrada em `.claude/settings.local.json`
163
+ 3. Documentar neste README
164
+ 4. Testar com casos reais
165
+
166
+ ---
167
+
168
+ *Criado: 2026-01-24*
169
+ *Arquitetura: docs/architecture/claude-md-governance-system.md*
@@ -0,0 +1,46 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Claude Code Hook: PreCompact Session Digest
4
+ *
5
+ * This hook is registered with Claude Code to trigger before context compact.
6
+ * It delegates to the unified hook runner in aios-core.
7
+ *
8
+ * Installation:
9
+ * - Claude Code automatically discovers hooks in .claude/hooks/
10
+ * - Hook naming: {event}-{name}.js (e.g., precompact-session-digest.js)
11
+ *
12
+ * @see .aios-core/hooks/unified/runners/precompact-runner.js
13
+ * @see Story MIS-3 - Session Digest (PreCompact Hook)
14
+ */
15
+
16
+ 'use strict';
17
+
18
+ const path = require('path');
19
+
20
+ // Resolve path to the unified hook runner
21
+ const PROJECT_ROOT = path.resolve(__dirname, '..', '..');
22
+ const runnerPath = path.join(
23
+ PROJECT_ROOT,
24
+ '.aios-core',
25
+ 'hooks',
26
+ 'unified',
27
+ 'runners',
28
+ 'precompact-runner.js',
29
+ );
30
+
31
+ // Load and execute the hook runner
32
+ try {
33
+ const { onPreCompact } = require(runnerPath);
34
+
35
+ // Export the hook handler for Claude Code
36
+ module.exports = async (context) => {
37
+ return await onPreCompact(context);
38
+ };
39
+ } catch (error) {
40
+ console.error('[PreCompact Hook] Failed to load hook runner:', error.message);
41
+
42
+ // Graceful degradation - export no-op function
43
+ module.exports = async () => {
44
+ console.log('[PreCompact Hook] Hook runner not available, skipping');
45
+ };
46
+ }
@@ -0,0 +1,87 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ /**
5
+ * SYNAPSE Hook Entry Point — UserPromptSubmit
6
+ *
7
+ * Thin wrapper that reads JSON from stdin, delegates to SynapseEngine,
8
+ * and writes <synapse-rules> context to stdout.
9
+ *
10
+ * - Silent exit on missing .synapse/ directory
11
+ * - Silent exit on any error (never blocks the user prompt)
12
+ * - All errors logged to stderr with [synapse-hook] prefix
13
+ * - 5s safety timeout as defense-in-depth
14
+ *
15
+ * @module synapse-engine-hook
16
+ */
17
+
18
+ const path = require('path');
19
+ const fs = require('fs');
20
+
21
+ /** Safety timeout (ms) — defense-in-depth; Claude Code also manages hook timeout. */
22
+ const HOOK_TIMEOUT_MS = 5000;
23
+
24
+ /**
25
+ * Read all data from stdin as a JSON object.
26
+ * @returns {Promise<object>} Parsed JSON input
27
+ */
28
+ function readStdin() {
29
+ return new Promise((resolve, reject) => {
30
+ let data = '';
31
+ process.stdin.setEncoding('utf8');
32
+ process.stdin.on('error', (e) => reject(e));
33
+ process.stdin.on('data', (chunk) => { data += chunk; });
34
+ process.stdin.on('end', () => {
35
+ try { resolve(JSON.parse(data)); }
36
+ catch (e) { reject(e); }
37
+ });
38
+ });
39
+ }
40
+
41
+ /** Main hook execution pipeline. */
42
+ async function main() {
43
+ const input = await readStdin();
44
+ const { sessionId, cwd, prompt } = input;
45
+ if (!cwd) return;
46
+ const synapsePath = path.join(cwd, '.synapse');
47
+ if (!fs.existsSync(synapsePath)) return;
48
+
49
+ const { loadSession } = require(
50
+ path.join(cwd, '.aios-core', 'core', 'synapse', 'session', 'session-manager.js')
51
+ );
52
+ const { SynapseEngine } = require(
53
+ path.join(cwd, '.aios-core', 'core', 'synapse', 'engine.js')
54
+ );
55
+
56
+ const sessionsDir = path.join(synapsePath, 'sessions');
57
+ const session = loadSession(sessionId, sessionsDir) || { prompt_count: 0 };
58
+ const engine = new SynapseEngine(synapsePath);
59
+ const result = await engine.process(prompt, session);
60
+
61
+ process.stdout.write(JSON.stringify({
62
+ hookSpecificOutput: { additionalContext: result.xml || '' },
63
+ }));
64
+ }
65
+
66
+ /**
67
+ * Safely exit the process — no-op inside Jest workers to prevent worker crashes.
68
+ * @param {number} code - Exit code
69
+ */
70
+ function safeExit(code) {
71
+ if (process.env.JEST_WORKER_ID) return;
72
+ process.exit(code);
73
+ }
74
+
75
+ /** Entry point runner — sets safety timeout and executes main(). */
76
+ function run() {
77
+ const timer = setTimeout(() => safeExit(0), HOOK_TIMEOUT_MS);
78
+ timer.unref();
79
+ main().catch((err) => {
80
+ console.error(`[synapse-hook] ${err.message}`);
81
+ safeExit(0);
82
+ });
83
+ }
84
+
85
+ if (require.main === module) run();
86
+
87
+ module.exports = { readStdin, main, run, HOOK_TIMEOUT_MS };
package/bin/aios-init.js CHANGED
@@ -5,8 +5,8 @@
5
5
  * Based on the original beautiful visual design with ASCII art
6
6
  * Version: 2.1.0
7
7
  *
8
- * ⚠️ DEPRECATION NOTICE (v3.11.3):
9
- * This file is the LEGACY installer and will be removed in v4.0.0.
8
+ * ⚠️ DEPRECATED (since v3.11.3, scheduled for removal in v5.0.0):
9
+ * This file is the LEGACY installer.
10
10
  * The new modular wizard is located at: packages/installer/src/wizard/index.js
11
11
  *
12
12
  * This file is kept as a fallback for edge cases where the new wizard
@@ -16,8 +16,8 @@
16
16
  * - Use `npx aios-core` which routes through bin/aios.js to the new wizard
17
17
  * - Do NOT call this file directly
18
18
  *
19
- * Supported IDEs (8 total):
20
- * - Claude Code, Cursor, Windsurf, Trae, Roo Code, Cline, Gemini CLI, GitHub Copilot
19
+ * Supported IDEs (7 total):
20
+ * - Claude Code, Cursor, Windsurf, Roo Code, Cline, Gemini CLI, GitHub Copilot
21
21
  */
22
22
 
23
23
  const path = require('path');
@@ -3,13 +3,10 @@
3
3
  /**
4
4
  * AIOS-FullStack Minimal Installation
5
5
  *
6
- * DEPRECATION NOTICE (v3.11.1):
6
+ * DEPRECATED (since v3.11.1, scheduled for removal in v5.0.0):
7
7
  * The --minimal mode was designed for expansion-packs which have been
8
8
  * replaced by the Squads system (OSR-8). This command now runs the
9
9
  * standard wizard through the main router.
10
- *
11
- * This file is kept for backwards compatibility but will be removed
12
- * in a future major version.
13
10
  */
14
11
 
15
12
  const { spawn } = require('child_process');
package/bin/aios.js CHANGED
@@ -3,7 +3,7 @@
3
3
  /**
4
4
  * AIOS-FullStack CLI
5
5
  * Main entry point - Standalone (no external dependencies for npx compatibility)
6
- * Version: 1.2.0
6
+ * Version: 4.0.0
7
7
  */
8
8
 
9
9
  const path = require('path');
@@ -354,7 +354,6 @@ function getIDEConfigFile(ideKey) {
354
354
  const ideConfigMap = {
355
355
  cursor: '.cursorrules',
356
356
  windsurf: '.windsurfrules',
357
- trae: '.trae/config.json',
358
357
  zed: '.zed/settings.json',
359
358
  antigravity: '.antigravity.yaml',
360
359
  continue: '.continue/config.json',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aios-core",
3
- "version": "4.0.0",
3
+ "version": "4.0.2",
4
4
  "description": "Synkra AIOS: AI-Orchestrated System for Full Stack Development - Core Framework",
5
5
  "bin": {
6
6
  "aios": "bin/aios.js",
@@ -18,6 +18,9 @@
18
18
  ".aios-core/",
19
19
  ".claude/CLAUDE.md",
20
20
  ".claude/rules/",
21
+ ".claude/hooks/synapse-engine.js",
22
+ ".claude/hooks/precompact-session-digest.js",
23
+ ".claude/hooks/README.md",
21
24
  "README.md",
22
25
  "LICENSE"
23
26
  ],
@@ -0,0 +1,158 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * aios-pro CLI
5
+ *
6
+ * Thin CLI wrapper for @aios-fullstack/pro.
7
+ * Provides a clean npx interface: npx aios-pro install
8
+ *
9
+ * Commands:
10
+ * install Install @aios-fullstack/pro in the current project
11
+ * activate --key X Activate a license key
12
+ * deactivate Deactivate the current license
13
+ * status Show license status
14
+ * features List available pro features
15
+ * validate Force online license revalidation
16
+ * help Show help
17
+ */
18
+
19
+ const { execSync, spawnSync } = require('child_process');
20
+ const path = require('path');
21
+ const fs = require('fs');
22
+
23
+ const PRO_PACKAGE = '@aios-fullstack/pro';
24
+ const VERSION = require('../package.json').version;
25
+
26
+ const args = process.argv.slice(2);
27
+ const command = args[0];
28
+
29
+ // ─── Helpers ────────────────────────────────────────────────────────────────
30
+
31
+ function run(cmd, options = {}) {
32
+ const result = spawnSync(cmd, {
33
+ shell: true,
34
+ stdio: 'inherit',
35
+ cwd: process.cwd(),
36
+ ...options,
37
+ });
38
+ return result.status;
39
+ }
40
+
41
+ function isProInstalled() {
42
+ try {
43
+ const pkgPath = path.join(process.cwd(), 'node_modules', '@aios-fullstack', 'pro', 'package.json');
44
+ return fs.existsSync(pkgPath);
45
+ } catch {
46
+ return false;
47
+ }
48
+ }
49
+
50
+ function findAiosCli() {
51
+ // Check local node_modules first
52
+ const localBin = path.join(process.cwd(), 'node_modules', '.bin', 'aios');
53
+ if (fs.existsSync(localBin) || fs.existsSync(localBin + '.cmd')) {
54
+ return 'npx aios';
55
+ }
56
+
57
+ // Check global
58
+ try {
59
+ execSync('aios --version', { stdio: 'pipe' });
60
+ return 'aios';
61
+ } catch {
62
+ return null;
63
+ }
64
+ }
65
+
66
+ function delegateToAios(subcommand) {
67
+ const aios = findAiosCli();
68
+ if (!aios) {
69
+ console.error('aios-core CLI not found.');
70
+ console.error('Install it first: npm install aios-core');
71
+ process.exit(1);
72
+ }
73
+
74
+ const spawnArgs = ['pro', subcommand, ...args.slice(1)];
75
+ const result = spawnSync(aios, spawnArgs, { stdio: 'inherit' });
76
+ process.exit(result.status ?? 0);
77
+ }
78
+
79
+ // ─── Commands ───────────────────────────────────────────────────────────────
80
+
81
+ function showHelp() {
82
+ console.log(`
83
+ aios-pro v${VERSION} — AIOS Pro CLI
84
+
85
+ Usage:
86
+ npx aios-pro <command> [options]
87
+
88
+ Commands:
89
+ install Install ${PRO_PACKAGE} in the current project
90
+ activate --key KEY Activate a license key
91
+ deactivate Deactivate the current license
92
+ status Show license status
93
+ features List available pro features
94
+ validate Force online license revalidation
95
+ help Show this help message
96
+
97
+ Examples:
98
+ npx aios-pro install
99
+ npx aios-pro activate --key PRO-XXXX-XXXX-XXXX-XXXX
100
+ npx aios-pro status
101
+
102
+ Documentation: https://synkra.ai/pro/docs
103
+ `);
104
+ }
105
+
106
+ function installPro() {
107
+ console.log(`\nInstalling ${PRO_PACKAGE}...\n`);
108
+
109
+ const exitCode = run(`npm install ${PRO_PACKAGE}`);
110
+
111
+ if (exitCode !== 0) {
112
+ console.error(`\nFailed to install ${PRO_PACKAGE}`);
113
+ process.exit(1);
114
+ }
115
+
116
+ console.log(`\n✅ ${PRO_PACKAGE} installed successfully!\n`);
117
+ console.log('Next steps:');
118
+ console.log(' npx aios-pro activate --key PRO-XXXX-XXXX-XXXX-XXXX');
119
+ console.log(' npx aios-pro status');
120
+ console.log('');
121
+ }
122
+
123
+ // ─── Main ───────────────────────────────────────────────────────────────────
124
+
125
+ if (!command || command === 'help' || command === '--help' || command === '-h') {
126
+ showHelp();
127
+ process.exit(0);
128
+ }
129
+
130
+ if (command === '--version' || command === '-v') {
131
+ console.log(`aios-pro v${VERSION}`);
132
+ process.exit(0);
133
+ }
134
+
135
+ switch (command) {
136
+ case 'install':
137
+ case 'setup':
138
+ installPro();
139
+ break;
140
+
141
+ case 'activate':
142
+ case 'deactivate':
143
+ case 'status':
144
+ case 'features':
145
+ case 'validate':
146
+ if (!isProInstalled()) {
147
+ console.error(`${PRO_PACKAGE} is not installed.`);
148
+ console.error('Run first: npx aios-pro install\n');
149
+ process.exit(1);
150
+ }
151
+ delegateToAios(command);
152
+ break;
153
+
154
+ default:
155
+ console.error(`Unknown command: ${command}\n`);
156
+ showHelp();
157
+ process.exit(1);
158
+ }
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "aios-pro",
3
+ "version": "0.1.0",
4
+ "description": "CLI for AIOS Pro — install, activate and manage your license",
5
+ "bin": {
6
+ "aios-pro": "bin/aios-pro.js"
7
+ },
8
+ "files": [
9
+ "bin/"
10
+ ],
11
+ "keywords": [
12
+ "aios",
13
+ "pro",
14
+ "license",
15
+ "cli",
16
+ "synkra"
17
+ ],
18
+ "author": "SynkraAI",
19
+ "license": "MIT",
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "git+https://github.com/SynkraAI/aios-core.git",
23
+ "directory": "packages/aios-pro-cli"
24
+ },
25
+ "engines": {
26
+ "node": ">=18"
27
+ },
28
+ "publishConfig": {
29
+ "access": "public",
30
+ "registry": "https://registry.npmjs.org"
31
+ }
32
+ }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aios/installer",
3
- "version": "3.2.0",
3
+ "version": "3.2.1",
4
4
  "description": "AIOS Installer - Automated setup wizard for AIOS projects (greenfield & brownfield)",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -321,6 +321,29 @@ async function installAiosCore(options = {}) {
321
321
  });
322
322
  result.versionInfo = versionInfo;
323
323
 
324
+ // BUG-2 fix (INS-1): Install .aios-core dependencies after copy
325
+ // The copied .aios-core/package.json has dependencies (js-yaml, execa, etc.)
326
+ // that must be installed for the activation pipeline to work
327
+ const aiosCorePackageJson = path.join(targetAiosCore, 'package.json');
328
+ if (await fs.pathExists(aiosCorePackageJson)) {
329
+ spinner.text = 'Installing .aios-core dependencies (js-yaml, etc.)...';
330
+ try {
331
+ const { exec } = require('child_process');
332
+ const { promisify } = require('util');
333
+ const execAsync = promisify(exec);
334
+ await execAsync('npm install --production --ignore-scripts', {
335
+ cwd: targetAiosCore,
336
+ timeout: 60000,
337
+ });
338
+ spinner.succeed('Installed .aios-core dependencies');
339
+ spinner.start('Finishing installation...');
340
+ } catch (depError) {
341
+ spinner.warn(`Could not install .aios-core dependencies: ${depError.message}`);
342
+ spinner.start('Continuing installation...');
343
+ result.errors.push(`Dependencies warning: ${depError.message}`);
344
+ }
345
+ }
346
+
324
347
  result.success = true;
325
348
  spinner.succeed(`AIOS core installed (${result.installedFiles.length} files)`);
326
349