aios-core 3.8.0 → 3.9.1

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.
@@ -392,7 +392,7 @@ class SessionContextLoader {
392
392
  lastActivity: sessionState.lastActivity,
393
393
  };
394
394
  }
395
- } catch (_error) {
395
+ } catch {
396
396
  // Ignore
397
397
  }
398
398
  return null;
@@ -409,7 +409,7 @@ class SessionContextLoader {
409
409
  const sessionState = this.loadSessionState();
410
410
  const history = sessionState.taskHistory || [];
411
411
  return history.slice(-limit);
412
- } catch (_error) {
412
+ } catch {
413
413
  return [];
414
414
  }
415
415
  }
@@ -36,7 +36,7 @@ class TestGenerator {
36
36
  console.log(chalk.green('✅ Test generator initialized'));
37
37
  return true;
38
38
 
39
- } catch (_error) {
39
+ } catch (error) {
40
40
  console.error(chalk.red(`Failed to initialize test generator: ${error.message}`));
41
41
  throw error;
42
42
  }
@@ -67,7 +67,7 @@ class TestGenerator {
67
67
 
68
68
  return processedContent;
69
69
 
70
- } catch (_error) {
70
+ } catch (error) {
71
71
  this.updateGenerationStats(false, Date.now() - startTime);
72
72
  console.error(chalk.red(`Failed to generate test for ${component.name}: ${error.message}`));
73
73
  throw error;
@@ -95,7 +95,7 @@ class TestGenerator {
95
95
  test_count: testFile.test_count,
96
96
  });
97
97
 
98
- } catch (_error) {
98
+ } catch (error) {
99
99
  errors.push({
100
100
  file_path: testFile.file_path,
101
101
  test_type: testFile.test_type,
@@ -167,7 +167,7 @@ class TestGenerator {
167
167
  enhancedContent = this.injectSetupTeardown(enhancedContent, setupTeardown);
168
168
  }
169
169
 
170
- } catch (_error) {
170
+ } catch (error) {
171
171
  console.warn(chalk.yellow(`Failed to enhance test content: ${error.message}`));
172
172
  // Return base content if enhancement fails
173
173
  }
@@ -221,7 +221,7 @@ class TestGenerator {
221
221
  analysis.configuration = this.extractTaskConfig(content);
222
222
  }
223
223
 
224
- } catch (_error) {
224
+ } catch (error) {
225
225
  console.warn(chalk.yellow(`Failed to analyze component ${component.id}: ${error.message}`));
226
226
  }
227
227
 
@@ -547,7 +547,7 @@ ${content}`;
547
547
  throw new Error('Unbalanced brackets in generated test');
548
548
  }
549
549
 
550
- } catch (_error) {
550
+ } catch (error) {
551
551
  console.warn(chalk.yellow(`Test syntax validation warning: ${error.message}`));
552
552
  }
553
553
  }
@@ -723,7 +723,7 @@ ${content}`;
723
723
  try {
724
724
  const yaml = require('js-yaml');
725
725
  return yaml.load(yamlMatch[1]);
726
- } catch (_error) {
726
+ } catch {
727
727
  return null;
728
728
  }
729
729
  }
@@ -734,7 +734,7 @@ ${content}`;
734
734
  try {
735
735
  const yaml = require('js-yaml');
736
736
  return yaml.load(content);
737
- } catch (_error) {
737
+ } catch {
738
738
  return null;
739
739
  }
740
740
  }
@@ -29,7 +29,7 @@ class TestQualityAssessment {
29
29
  console.log(chalk.green('✅ Test quality assessment initialized'));
30
30
  return true;
31
31
 
32
- } catch (_error) {
32
+ } catch (error) {
33
33
  console.error(chalk.red(`Failed to initialize test quality assessment: ${error.message}`));
34
34
  throw error;
35
35
  }
@@ -81,7 +81,7 @@ class TestQualityAssessment {
81
81
 
82
82
  return assessment;
83
83
 
84
- } catch (_error) {
84
+ } catch (error) {
85
85
  console.error(chalk.red(`Failed to assess test quality for ${testFilePath}: ${error.message}`));
86
86
  throw error;
87
87
  }
@@ -117,7 +117,7 @@ class TestQualityAssessment {
117
117
  allIssues.push(...assessment.issues);
118
118
  qualityRatings[assessment.quality_rating]++;
119
119
 
120
- } catch (_error) {
120
+ } catch (error) {
121
121
  console.warn(chalk.yellow(`Failed to assess ${testFile}: ${error.message}`));
122
122
  }
123
123
  }
@@ -985,7 +985,7 @@ class TestQualityAssessment {
985
985
  const data = JSON.parse(await fs.readFile(historyFile, 'utf-8'));
986
986
  this.qualityHistory = data.quality_history || [];
987
987
  }
988
- } catch (_error) {
988
+ } catch {
989
989
  // No existing data, start fresh
990
990
  }
991
991
  }
@@ -1015,7 +1015,7 @@ class TestQualityAssessment {
1015
1015
 
1016
1016
  console.log(chalk.gray(`Quality assessment saved: ${assessmentFile}`));
1017
1017
 
1018
- } catch (_error) {
1018
+ } catch (error) {
1019
1019
  console.warn(chalk.yellow(`Failed to save quality assessment: ${error.message}`));
1020
1020
  }
1021
1021
  }
@@ -41,7 +41,7 @@ async function countIntegrationReferences(utilityName) {
41
41
  { shell: '/bin/bash' },
42
42
  );
43
43
  totalCount += parseInt(stdout.trim()) || 0;
44
- } catch (_error) {
44
+ } catch {
45
45
  // Directory doesn't exist or grep failed - not a problem
46
46
  }
47
47
  }
@@ -98,7 +98,7 @@ async function testUtility(utilityFile) {
98
98
  : 'Keep but document usage';
99
99
  }
100
100
 
101
- } catch (_error) {
101
+ } catch (error) {
102
102
  result.errors.push(error.message);
103
103
 
104
104
  // Classify error type
@@ -119,7 +119,7 @@ async function testUtility(utilityFile) {
119
119
  // Count integration even if broken
120
120
  try {
121
121
  result.integrationCount = await countIntegrationReferences(utilityFile);
122
- } catch (_e) {
122
+ } catch {
123
123
  // Ignore counting errors
124
124
  }
125
125
  }
@@ -7,8 +7,8 @@
7
7
  # - SHA256 hashes for change detection
8
8
  # - File types for categorization
9
9
  #
10
- version: 3.8.0
11
- generated_at: "2025-12-26T21:45:10.223Z"
10
+ version: 3.9.1
11
+ generated_at: "2025-12-26T23:36:47.885Z"
12
12
  generator: scripts/generate-install-manifest.js
13
13
  file_count: 595
14
14
  files:
@@ -333,9 +333,9 @@ files:
333
333
  type: core
334
334
  size: 7217
335
335
  - path: core/session/context-loader.js
336
- hash: sha256:368214ee83593867cef7a220289ec1ec0e4c06ff1998432322e2f7d852345b51
336
+ hash: sha256:eaef1e3a11feb2d355c5dc8fc2813ae095e27911cdf1261e5d003b22be16d8f0
337
337
  type: core
338
- size: 13747
338
+ size: 13729
339
339
  - path: core/utils/output-formatter.js
340
340
  hash: sha256:9c386d8b0232f92887dc6f8d32671444a5857b6c848c84b561eedef27a178470
341
341
  type: core
@@ -1657,21 +1657,21 @@ files:
1657
1657
  type: script
1658
1658
  size: 8334
1659
1659
  - path: infrastructure/scripts/test-generator.js
1660
- hash: sha256:16ba63b101880bc0689ddebaa7d98e10e2028740a55ea01445bac3048a7986d3
1660
+ hash: sha256:90485b00c0b9e490f2394ff0fb456ea5a5614ca2431d9df55d95b54213b15184
1661
1661
  type: script
1662
- size: 24969
1662
+ size: 24945
1663
1663
  - path: infrastructure/scripts/test-quality-assessment.js
1664
- hash: sha256:d2f9e322dbe255c733e8a257955ffb78b147a9d0e1f598650fa11e7dcec181f6
1664
+ hash: sha256:300699a7a5003ef1f18b4e865f761a8e76d0b82e001f0ba17317ef05d41c79db
1665
1665
  type: script
1666
- size: 36911
1666
+ size: 36898
1667
1667
  - path: infrastructure/scripts/test-utilities-fast.js
1668
1668
  hash: sha256:70d87a74dac153c65d622afa4d62816e41d8d81eee6d42e1c0e498999bec7c40
1669
1669
  type: script
1670
1670
  size: 3743
1671
1671
  - path: infrastructure/scripts/test-utilities.js
1672
- hash: sha256:7af31c9ff42b8fe6fae8e74e403ca2d5165c33b30438d39d408031e330333d60
1672
+ hash: sha256:da7c868b105892e3995ed6e6517188a79b8f62a079a61d4d38242c4f357c9d75
1673
1673
  type: script
1674
- size: 5885
1674
+ size: 5870
1675
1675
  - path: infrastructure/scripts/tool-resolver.js
1676
1676
  hash: sha256:94a5ab46dc1939d87fbb741619d8013ce17c5eae1e18ccdc78707eac2c4c927b
1677
1677
  type: script
@@ -2373,9 +2373,9 @@ files:
2373
2373
  type: script
2374
2374
  size: 1583
2375
2375
  - path: scripts/test-template-system.js
2376
- hash: sha256:4e365df5372a8e09abb43f1f92e99d3e654a51b333dde232bad956e534a481db
2376
+ hash: sha256:87465ac02b079166479b9d50fe6e12a101bcaa81d47f1aace9b346e264c04712
2377
2377
  type: script
2378
- size: 26051
2378
+ size: 26029
2379
2379
  - path: scripts/validate-phase1.ps1
2380
2380
  hash: sha256:2f694151ae90af1a9cb8fe890037a51e60115ff8edf636704e8f11e7ac23b23a
2381
2381
  type: script
@@ -34,7 +34,7 @@ class TestTemplateSystem {
34
34
  console.log(chalk.green('✅ Test template system initialized'));
35
35
  return true;
36
36
 
37
- } catch (_error) {
37
+ } catch (error) {
38
38
  console.error(chalk.red(`Failed to initialize test template system: ${error.message}`));
39
39
  throw error;
40
40
  }
@@ -121,7 +121,7 @@ class TestTemplateSystem {
121
121
  console.log(chalk.green(`✅ Custom template created: ${templateName}`));
122
122
  return templateWrapper;
123
123
 
124
- } catch (_error) {
124
+ } catch (error) {
125
125
  console.error(chalk.red(`Failed to create custom template: ${error.message}`));
126
126
  throw error;
127
127
  }
@@ -136,7 +136,7 @@ class TestTemplateSystem {
136
136
  try {
137
137
  const content = await fs.readFile(templatePath, 'utf-8');
138
138
  return JSON.parse(content);
139
- } catch (_error) {
139
+ } catch {
140
140
  // Template file doesn't exist
141
141
  return null;
142
142
  }
@@ -837,14 +837,14 @@ afterAll(async () => {
837
837
  const templateKey = path.basename(templateFile, '.template.js');
838
838
 
839
839
  this.templateCache.set(templateKey, template);
840
- } catch (_error) {
840
+ } catch (error) {
841
841
  console.warn(chalk.yellow(`Failed to load template ${templateFile}: ${error.message}`));
842
842
  }
843
843
  }
844
844
 
845
845
  console.log(chalk.gray(`Loaded ${this.templateCache.size} template(s)`));
846
846
 
847
- } catch (_error) {
847
+ } catch (error) {
848
848
  console.warn(chalk.yellow(`Failed to load templates: ${error.message}`));
849
849
  }
850
850
  }
@@ -872,7 +872,7 @@ afterAll(async () => {
872
872
  templateFiles.push(path.join(this.templatesDir, entry.name));
873
873
  }
874
874
  }
875
- } catch (_error) {
875
+ } catch {
876
876
  // Templates directory doesn't exist yet
877
877
  }
878
878
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aios-core",
3
- "version": "3.8.0",
3
+ "version": "3.9.1",
4
4
  "description": "Synkra AIOS: AI-Orchestrated System for Full Stack Development - Core Framework",
5
5
  "main": "index.js",
6
6
  "module": "index.esm.js",
@@ -99,7 +99,7 @@ function isUserModified(filePath, expectedHash) {
99
99
  try {
100
100
  const currentHash = `sha256:${hashFile(filePath)}`;
101
101
  return !hashesMatch(currentHash, expectedHash);
102
- } catch (_error) {
102
+ } catch {
103
103
  // If we can't hash, assume it's modified
104
104
  return true;
105
105
  }
@@ -1,352 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * AIOS-FullStack Modern Installation Wizard
5
- * Uses @clack/prompts for beautiful CLI experience
6
- * Version: 1.1.4
7
- */
8
-
9
- const path = require('path');
10
- const fs = require('fs');
11
- const fse = require('fs-extra');
12
- const yaml = require('yaml');
13
- const { execSync } = require('child_process');
14
- const p = require('@clack/prompts');
15
- const pc = require('picocolors');
16
-
17
- /**
18
- * Smart path resolution for AIOS Core modules
19
- */
20
- function resolveAiosCoreModule(modulePath) {
21
- const aiosCoreModule = path.join(__dirname, '..', '.aios-core', modulePath);
22
-
23
- const moduleExists = fs.existsSync(aiosCoreModule + '.js') ||
24
- fs.existsSync(aiosCoreModule + '/index.js') ||
25
- fs.existsSync(aiosCoreModule);
26
-
27
- if (!moduleExists) {
28
- throw new Error(
29
- `Cannot find AIOS Core module: ${modulePath}\n` +
30
- `Searched: ${aiosCoreModule}\n` +
31
- 'Please ensure @synkra/aios-core is installed correctly.',
32
- );
33
- }
34
-
35
- return require(aiosCoreModule);
36
- }
37
-
38
- // Load AIOS Core modules
39
- const { detectRepositoryContext } = resolveAiosCoreModule('utils/repository-detector');
40
- const { ClickUpAdapter } = resolveAiosCoreModule('utils/pm-adapters/clickup-adapter');
41
- const { GitHubProjectsAdapter } = resolveAiosCoreModule('utils/pm-adapters/github-adapter');
42
- const { JiraAdapter } = resolveAiosCoreModule('utils/pm-adapters/jira-adapter');
43
-
44
- async function main() {
45
- console.clear();
46
-
47
- p.intro(pc.bgCyan(pc.black(' AIOS-FullStack Installation ')));
48
-
49
- const projectRoot = process.cwd();
50
- let context = detectRepositoryContext();
51
-
52
- // Setup prerequisites if needed
53
- if (!context) {
54
- const s = p.spinner();
55
- s.start('Setting up project prerequisites');
56
-
57
- // Check for git repository
58
- let hasGit = false;
59
- try {
60
- execSync('git rev-parse --git-dir', { cwd: projectRoot, stdio: 'ignore' });
61
- hasGit = true;
62
- } catch (err) {
63
- // Not a git repo
64
- }
65
-
66
- if (!hasGit) {
67
- try {
68
- execSync('git init', { cwd: projectRoot, stdio: 'ignore' });
69
- s.message('Git repository initialized');
70
- } catch (err) {
71
- s.stop('Failed to initialize git repository');
72
- p.cancel('Installation cancelled');
73
- process.exit(1);
74
- }
75
- }
76
-
77
- // Check for package.json
78
- const packageJsonPath = path.join(projectRoot, 'package.json');
79
- if (!fs.existsSync(packageJsonPath)) {
80
- const dirName = path.basename(projectRoot);
81
- const defaultPackage = {
82
- name: dirName.toLowerCase().replace(/\s+/g, '-'),
83
- version: '1.0.0',
84
- description: 'AIOS-FullStack project',
85
- main: 'index.js',
86
- scripts: { test: 'echo "Error: no test specified" && exit 1' },
87
- keywords: [],
88
- author: '',
89
- license: 'ISC',
90
- };
91
- fs.writeFileSync(packageJsonPath, JSON.stringify(defaultPackage, null, 2));
92
- s.message('package.json created');
93
- }
94
-
95
- s.stop('Prerequisites ready');
96
-
97
- // Try to detect context again
98
- context = detectRepositoryContext();
99
-
100
- // If still no context, create minimal one
101
- if (!context) {
102
- const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
103
- context = {
104
- projectRoot,
105
- packageName: packageJson.name,
106
- packageVersion: packageJson.version,
107
- repositoryUrl: 'local-repository',
108
- frameworkLocation: path.join(__dirname, '..'),
109
- };
110
- }
111
- }
112
-
113
- p.note(`Package: ${context.packageName}`, 'Project Context');
114
-
115
- // Step 1: Installation Mode
116
- const installMode = await p.select({
117
- message: 'How are you using AIOS-FullStack?',
118
- options: [
119
- {
120
- value: 'project-development',
121
- label: 'Using AIOS in a project',
122
- hint: 'Framework files added to .gitignore',
123
- },
124
- {
125
- value: 'framework-development',
126
- label: 'Developing AIOS framework itself',
127
- hint: 'Framework files are source code',
128
- },
129
- ],
130
- });
131
-
132
- if (p.isCancel(installMode)) {
133
- p.cancel('Installation cancelled');
134
- process.exit(0);
135
- }
136
-
137
- // Save installation config
138
- const config = {
139
- installation: {
140
- mode: installMode,
141
- detected_at: new Date().toISOString(),
142
- },
143
- repository: {
144
- url: context.repositoryUrl,
145
- auto_detect: true,
146
- },
147
- framework: {
148
- source: installMode === 'framework-development' ? 'local' : 'npm',
149
- version: context.packageVersion,
150
- location: context.frameworkLocation,
151
- },
152
- git_ignore_rules: {
153
- mode: installMode,
154
- ignore_framework_files: installMode === 'project-development',
155
- },
156
- };
157
-
158
- const configPath = path.join(context.projectRoot, '.aios-installation-config.yaml');
159
- fs.writeFileSync(configPath, yaml.stringify(config));
160
-
161
- // Update .gitignore
162
- updateGitIgnore(installMode, context.projectRoot);
163
-
164
- // Step 2: PM Tool
165
- const pmTool = await p.select({
166
- message: 'Do you use a project management tool?',
167
- options: [
168
- { value: 'local', label: 'None (local YAML files only)', hint: 'Recommended' },
169
- { value: 'clickup', label: 'ClickUp', hint: 'Requires API token' },
170
- { value: 'github-projects', label: 'GitHub Projects', hint: 'Uses gh auth' },
171
- { value: 'jira', label: 'Jira', hint: 'Requires API token' },
172
- ],
173
- });
174
-
175
- if (p.isCancel(pmTool)) {
176
- p.cancel('Installation cancelled');
177
- process.exit(0);
178
- }
179
-
180
- // Save PM config
181
- savePMConfig(pmTool, {}, context.projectRoot);
182
-
183
- // Step 3: IDE Selection
184
- const ide = await p.select({
185
- message: 'Which IDE will you use?',
186
- options: [
187
- { value: 'claude', label: 'Claude Code', hint: 'Recommended' },
188
- { value: 'windsurf', label: 'Windsurf' },
189
- { value: 'cursor', label: 'Cursor' },
190
- { value: 'none', label: 'Skip IDE setup' },
191
- ],
192
- });
193
-
194
- if (p.isCancel(ide)) {
195
- p.cancel('Installation cancelled');
196
- process.exit(0);
197
- }
198
-
199
- // Step 4: Copy AIOS Core files
200
- const s = p.spinner();
201
- s.start('Installing AIOS Core files');
202
-
203
- const sourceCoreDir = path.join(context.frameworkLocation, '.aios-core');
204
- const targetCoreDir = path.join(context.projectRoot, '.aios-core');
205
-
206
- if (fs.existsSync(sourceCoreDir)) {
207
- await fse.copy(sourceCoreDir, targetCoreDir);
208
- s.message('AIOS Core files installed (11 agents, 68 tasks, 23 templates)');
209
- } else {
210
- s.stop('AIOS Core files not found');
211
- p.cancel('Installation failed');
212
- process.exit(1);
213
- }
214
-
215
- // Copy IDE rules if IDE was selected
216
- if (ide !== 'none') {
217
- const ideRulesMap = {
218
- 'claude': { source: 'claude-rules.md', target: '.claude/CLAUDE.md' },
219
- 'windsurf': { source: 'windsurf-rules.md', target: '.windsurf/rules.md' },
220
- 'cursor': { source: 'cursor-rules.md', target: '.cursor/rules.md' },
221
- };
222
-
223
- const ideConfig = ideRulesMap[ide];
224
- if (ideConfig) {
225
- const sourceRules = path.join(targetCoreDir, 'templates', 'ide-rules', ideConfig.source);
226
- const targetRules = path.join(context.projectRoot, ideConfig.target);
227
-
228
- if (fs.existsSync(sourceRules)) {
229
- await fse.ensureDir(path.dirname(targetRules));
230
- await fse.copy(sourceRules, targetRules);
231
- s.message(`${ide.charAt(0).toUpperCase() + ide.slice(1)} rules installed`);
232
- }
233
- }
234
- }
235
-
236
- s.stop('Core files installed');
237
-
238
- // Step 5: Expansion Packs
239
- const sourceExpansionDir = path.join(context.frameworkLocation, 'expansion-packs');
240
- const availablePacks = [];
241
-
242
- if (fs.existsSync(sourceExpansionDir)) {
243
- const packs = fs.readdirSync(sourceExpansionDir).filter(f =>
244
- fs.statSync(path.join(sourceExpansionDir, f)).isDirectory(),
245
- );
246
- availablePacks.push(...packs);
247
- }
248
-
249
- if (availablePacks.length > 0) {
250
- const expansionPacks = await p.multiselect({
251
- message: 'Select expansion packs to install (optional)',
252
- options: availablePacks.map(pack => ({
253
- value: pack,
254
- label: pack,
255
- })),
256
- required: false,
257
- });
258
-
259
- if (!p.isCancel(expansionPacks) && expansionPacks.length > 0) {
260
- const s2 = p.spinner();
261
- s2.start('Installing expansion packs');
262
-
263
- const targetExpansionDir = path.join(context.projectRoot, 'expansion-packs');
264
-
265
- for (const pack of expansionPacks) {
266
- const sourcePack = path.join(sourceExpansionDir, pack);
267
- const targetPack = path.join(targetExpansionDir, pack);
268
- await fse.copy(sourcePack, targetPack);
269
- s2.message(`Installed: ${pack}`);
270
- }
271
-
272
- s2.stop(`${expansionPacks.length} expansion pack(s) installed`);
273
- }
274
- }
275
-
276
- p.outro(pc.green('✓ AIOS-FullStack installation complete!'));
277
-
278
- console.log('');
279
- p.note(
280
- `Mode: ${installMode}\n` +
281
- `Repository: ${context.repositoryUrl}\n` +
282
- `IDE: ${ide !== 'none' ? ide : 'none'}\n` +
283
- `PM Tool: ${pmTool}`,
284
- 'Configuration Summary',
285
- );
286
-
287
- console.log('');
288
- console.log(pc.cyan('Next steps:'));
289
- console.log(' • Activate agents using @agent-name (e.g., @dev, @github-devops)');
290
- console.log(' • Run "aios --help" to see available commands');
291
- console.log(' • Check documentation in docs/ directory');
292
- console.log('');
293
- }
294
-
295
- /**
296
- * Updates .gitignore file based on installation mode
297
- */
298
- function updateGitIgnore(mode, projectRoot) {
299
- const gitignorePath = path.join(projectRoot, '.gitignore');
300
-
301
- let gitignore = '';
302
- if (fs.existsSync(gitignorePath)) {
303
- gitignore = fs.readFileSync(gitignorePath, 'utf8');
304
- }
305
-
306
- if (mode === 'project-development') {
307
- const frameworkRules = [
308
- '',
309
- '# AIOS-FullStack Framework Files (auto-managed - do not edit)',
310
- '.aios-core/',
311
- 'node_modules/@aios/',
312
- 'outputs/minds/',
313
- '.aios-installation-config.yaml',
314
- '# End AIOS-FullStack auto-managed section',
315
- '',
316
- ];
317
-
318
- const hasFrameworkSection = gitignore.includes('# AIOS-FullStack Framework Files');
319
-
320
- if (!hasFrameworkSection) {
321
- gitignore += frameworkRules.join('\n');
322
- fs.writeFileSync(gitignorePath, gitignore);
323
- }
324
- }
325
- }
326
-
327
- /**
328
- * Save PM configuration
329
- */
330
- function savePMConfig(pmTool, config, projectRoot) {
331
- const pmConfigData = {
332
- pm_tool: {
333
- type: pmTool,
334
- configured_at: new Date().toISOString(),
335
- config: config,
336
- },
337
- sync_behavior: {
338
- auto_sync_on_status_change: true,
339
- create_tasks_on_story_creation: false,
340
- bidirectional_sync: false,
341
- },
342
- };
343
-
344
- const configPath = path.join(projectRoot, '.aios-pm-config.yaml');
345
- fs.writeFileSync(configPath, yaml.stringify(pmConfigData));
346
- }
347
-
348
- // Run installer with error handling
349
- main().catch((error) => {
350
- p.log.error('Installation failed: ' + error.message);
351
- process.exit(1);
352
- });