aios-core 2.1.5 → 2.1.6

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 (29) hide show
  1. package/.aios-core/development/tasks/analyze-brownfield.md +456 -0
  2. package/.aios-core/development/tasks/setup-project-docs.md +440 -0
  3. package/.aios-core/infrastructure/scripts/documentation-integrity/brownfield-analyzer.js +501 -0
  4. package/.aios-core/infrastructure/scripts/documentation-integrity/config-generator.js +368 -0
  5. package/.aios-core/infrastructure/scripts/documentation-integrity/deployment-config-loader.js +308 -0
  6. package/.aios-core/infrastructure/scripts/documentation-integrity/doc-generator.js +331 -0
  7. package/.aios-core/infrastructure/scripts/documentation-integrity/gitignore-generator.js +312 -0
  8. package/.aios-core/infrastructure/scripts/documentation-integrity/index.js +74 -0
  9. package/.aios-core/infrastructure/scripts/documentation-integrity/mode-detector.js +389 -0
  10. package/.aios-core/infrastructure/templates/core-config/core-config-brownfield.tmpl.yaml +176 -0
  11. package/.aios-core/infrastructure/templates/core-config/core-config-greenfield.tmpl.yaml +127 -0
  12. package/.aios-core/infrastructure/templates/gitignore/gitignore-aios-base.tmpl +63 -0
  13. package/.aios-core/infrastructure/templates/gitignore/gitignore-brownfield-merge.tmpl +18 -0
  14. package/.aios-core/infrastructure/templates/gitignore/gitignore-node.tmpl +85 -0
  15. package/.aios-core/infrastructure/templates/gitignore/gitignore-python.tmpl +145 -0
  16. package/.aios-core/infrastructure/templates/project-docs/coding-standards-tmpl.md +346 -0
  17. package/.aios-core/infrastructure/templates/project-docs/source-tree-tmpl.md +177 -0
  18. package/.aios-core/infrastructure/templates/project-docs/tech-stack-tmpl.md +267 -0
  19. package/package.json +1 -1
  20. package/packages/installer/src/config/templates/env-template.js +2 -2
  21. package/packages/installer/src/wizard/wizard.js +185 -34
  22. package/packages/installer/tests/integration/environment-configuration.test.js +2 -1
  23. package/packages/installer/tests/unit/env-template.test.js +3 -2
  24. package/.aios-core/development/tasks/validate-structure.md +0 -243
  25. package/.aios-core/infrastructure/scripts/source-tree-guardian/index.js +0 -375
  26. package/.aios-core/infrastructure/scripts/source-tree-guardian/manifest-generator.js +0 -410
  27. package/.aios-core/infrastructure/scripts/source-tree-guardian/rules/naming-rules.yaml +0 -285
  28. package/.aios-core/infrastructure/scripts/source-tree-guardian/rules/placement-rules.yaml +0 -262
  29. package/.aios-core/infrastructure/scripts/source-tree-guardian/validator.js +0 -468
@@ -0,0 +1,501 @@
1
+ /**
2
+ * Brownfield Analyzer Module
3
+ *
4
+ * Analyzes existing projects to detect structure, standards, and tech stack.
5
+ * Used for brownfield mode installation to adapt AIOS to existing projects.
6
+ *
7
+ * @module documentation-integrity/brownfield-analyzer
8
+ * @version 1.0.0
9
+ * @story 6.9
10
+ */
11
+
12
+ const fs = require('fs');
13
+ const path = require('path');
14
+
15
+ /**
16
+ * Analysis result structure
17
+ * @typedef {Object} BrownfieldAnalysis
18
+ * @property {boolean} hasExistingStructure - Has defined directory structure
19
+ * @property {boolean} hasExistingWorkflows - Has CI/CD workflows
20
+ * @property {boolean} hasExistingStandards - Has coding standard configs
21
+ * @property {string} mergeStrategy - Recommended merge strategy
22
+ * @property {string[]} techStack - Detected technologies
23
+ * @property {string[]} frameworks - Detected frameworks
24
+ * @property {Object} configs - Detected config file paths
25
+ * @property {string[]} recommendations - Recommendations for integration
26
+ * @property {string[]} conflicts - Potential conflicts detected
27
+ * @property {string[]} manualReviewItems - Items needing manual review
28
+ */
29
+
30
+ /**
31
+ * Analyzes an existing project for brownfield integration
32
+ *
33
+ * @param {string} targetDir - Directory to analyze
34
+ * @returns {BrownfieldAnalysis} Analysis results
35
+ */
36
+ function analyzeProject(targetDir) {
37
+ const normalizedDir = path.resolve(targetDir);
38
+
39
+ if (!fs.existsSync(normalizedDir)) {
40
+ throw new Error(`Directory does not exist: ${normalizedDir}`);
41
+ }
42
+
43
+ const analysis = {
44
+ // Basic flags
45
+ hasExistingStructure: false,
46
+ hasExistingWorkflows: false,
47
+ hasExistingStandards: false,
48
+
49
+ // Merge strategy
50
+ mergeStrategy: 'parallel',
51
+
52
+ // Detected stack
53
+ techStack: [],
54
+ frameworks: [],
55
+ version: null,
56
+
57
+ // Config paths
58
+ configs: {
59
+ eslint: null,
60
+ prettier: null,
61
+ tsconfig: null,
62
+ flake8: null,
63
+ packageJson: null,
64
+ requirements: null,
65
+ goMod: null,
66
+ githubWorkflows: null,
67
+ gitlabCi: null,
68
+ },
69
+
70
+ // Detected settings
71
+ linting: 'none',
72
+ formatting: 'none',
73
+ testing: 'none',
74
+
75
+ // Integration guidance
76
+ recommendations: [],
77
+ conflicts: [],
78
+ manualReviewItems: [],
79
+
80
+ // Summary
81
+ summary: '',
82
+ };
83
+
84
+ // Run all analyzers
85
+ analyzeTechStack(normalizedDir, analysis);
86
+ analyzeCodeStandards(normalizedDir, analysis);
87
+ analyzeWorkflows(normalizedDir, analysis);
88
+ analyzeDirectoryStructure(normalizedDir, analysis);
89
+ generateRecommendations(analysis);
90
+ generateSummary(analysis);
91
+
92
+ return analysis;
93
+ }
94
+
95
+ /**
96
+ * Analyzes the tech stack from project files
97
+ *
98
+ * @param {string} targetDir - Directory to analyze
99
+ * @param {BrownfieldAnalysis} analysis - Analysis object to populate
100
+ */
101
+ function analyzeTechStack(targetDir, analysis) {
102
+ // Check for Node.js
103
+ const packageJsonPath = path.join(targetDir, 'package.json');
104
+ if (fs.existsSync(packageJsonPath)) {
105
+ analysis.techStack.push('Node.js');
106
+ analysis.configs.packageJson = 'package.json';
107
+
108
+ try {
109
+ const pkg = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
110
+ analysis.version = pkg.version;
111
+
112
+ // Detect frameworks from dependencies
113
+ const allDeps = {
114
+ ...(pkg.dependencies || {}),
115
+ ...(pkg.devDependencies || {}),
116
+ };
117
+
118
+ if (allDeps.react) analysis.frameworks.push('React');
119
+ if (allDeps.vue) analysis.frameworks.push('Vue');
120
+ if (allDeps.angular || allDeps['@angular/core']) analysis.frameworks.push('Angular');
121
+ if (allDeps.next) analysis.frameworks.push('Next.js');
122
+ if (allDeps.nuxt) analysis.frameworks.push('Nuxt');
123
+ if (allDeps.express) analysis.frameworks.push('Express');
124
+ if (allDeps.fastify) analysis.frameworks.push('Fastify');
125
+ if (allDeps.nest || allDeps['@nestjs/core']) analysis.frameworks.push('NestJS');
126
+
127
+ // Detect TypeScript
128
+ if (allDeps.typescript || fs.existsSync(path.join(targetDir, 'tsconfig.json'))) {
129
+ analysis.techStack.push('TypeScript');
130
+ }
131
+
132
+ // Detect testing frameworks
133
+ if (allDeps.jest) analysis.testing = 'Jest';
134
+ else if (allDeps.mocha) analysis.testing = 'Mocha';
135
+ else if (allDeps.vitest) analysis.testing = 'Vitest';
136
+ } catch (error) {
137
+ console.warn(`Warning: Could not parse package.json: ${error.message}`);
138
+ }
139
+ }
140
+
141
+ // Check for Python
142
+ if (
143
+ fs.existsSync(path.join(targetDir, 'requirements.txt')) ||
144
+ fs.existsSync(path.join(targetDir, 'pyproject.toml')) ||
145
+ fs.existsSync(path.join(targetDir, 'setup.py'))
146
+ ) {
147
+ analysis.techStack.push('Python');
148
+
149
+ if (fs.existsSync(path.join(targetDir, 'requirements.txt'))) {
150
+ analysis.configs.requirements = 'requirements.txt';
151
+
152
+ try {
153
+ const requirements = fs.readFileSync(
154
+ path.join(targetDir, 'requirements.txt'),
155
+ 'utf8',
156
+ );
157
+
158
+ if (requirements.includes('django')) analysis.frameworks.push('Django');
159
+ if (requirements.includes('flask')) analysis.frameworks.push('Flask');
160
+ if (requirements.includes('fastapi')) analysis.frameworks.push('FastAPI');
161
+ if (requirements.includes('pytest')) analysis.testing = 'pytest';
162
+ } catch {
163
+ // Ignore parse errors
164
+ }
165
+ }
166
+ }
167
+
168
+ // Check for Go
169
+ if (fs.existsSync(path.join(targetDir, 'go.mod'))) {
170
+ analysis.techStack.push('Go');
171
+ analysis.configs.goMod = 'go.mod';
172
+ }
173
+
174
+ // Check for Rust
175
+ if (fs.existsSync(path.join(targetDir, 'Cargo.toml'))) {
176
+ analysis.techStack.push('Rust');
177
+ }
178
+ }
179
+
180
+ /**
181
+ * Analyzes existing coding standards configurations
182
+ *
183
+ * @param {string} targetDir - Directory to analyze
184
+ * @param {BrownfieldAnalysis} analysis - Analysis object to populate
185
+ */
186
+ function analyzeCodeStandards(targetDir, analysis) {
187
+ // ESLint
188
+ const eslintConfigs = [
189
+ '.eslintrc.js',
190
+ '.eslintrc.json',
191
+ '.eslintrc.yaml',
192
+ '.eslintrc.yml',
193
+ '.eslintrc',
194
+ 'eslint.config.js',
195
+ ];
196
+
197
+ for (const config of eslintConfigs) {
198
+ if (fs.existsSync(path.join(targetDir, config))) {
199
+ analysis.configs.eslint = config;
200
+ analysis.linting = 'ESLint';
201
+ analysis.hasExistingStandards = true;
202
+ break;
203
+ }
204
+ }
205
+
206
+ // Prettier
207
+ const prettierConfigs = [
208
+ '.prettierrc',
209
+ '.prettierrc.json',
210
+ '.prettierrc.yaml',
211
+ '.prettierrc.yml',
212
+ '.prettierrc.js',
213
+ 'prettier.config.js',
214
+ ];
215
+
216
+ for (const config of prettierConfigs) {
217
+ if (fs.existsSync(path.join(targetDir, config))) {
218
+ analysis.configs.prettier = config;
219
+ analysis.formatting = 'Prettier';
220
+ analysis.hasExistingStandards = true;
221
+ break;
222
+ }
223
+ }
224
+
225
+ // TypeScript
226
+ if (fs.existsSync(path.join(targetDir, 'tsconfig.json'))) {
227
+ analysis.configs.tsconfig = 'tsconfig.json';
228
+ analysis.hasExistingStandards = true;
229
+ }
230
+
231
+ // Python - Flake8
232
+ if (fs.existsSync(path.join(targetDir, '.flake8'))) {
233
+ analysis.configs.flake8 = '.flake8';
234
+ analysis.linting = 'Flake8';
235
+ analysis.hasExistingStandards = true;
236
+ }
237
+
238
+ // Python - Black
239
+ const pyprojectPath = path.join(targetDir, 'pyproject.toml');
240
+ if (fs.existsSync(pyprojectPath)) {
241
+ try {
242
+ const content = fs.readFileSync(pyprojectPath, 'utf8');
243
+ if (content.includes('[tool.black]')) {
244
+ analysis.formatting = 'Black';
245
+ analysis.hasExistingStandards = true;
246
+ }
247
+ } catch {
248
+ // Ignore
249
+ }
250
+ }
251
+ }
252
+
253
+ /**
254
+ * Analyzes existing CI/CD workflows
255
+ *
256
+ * @param {string} targetDir - Directory to analyze
257
+ * @param {BrownfieldAnalysis} analysis - Analysis object to populate
258
+ */
259
+ function analyzeWorkflows(targetDir, analysis) {
260
+ // GitHub Actions
261
+ const githubWorkflowsDir = path.join(targetDir, '.github', 'workflows');
262
+ if (fs.existsSync(githubWorkflowsDir)) {
263
+ analysis.hasExistingWorkflows = true;
264
+ analysis.configs.githubWorkflows = '.github/workflows/';
265
+
266
+ try {
267
+ const workflows = fs.readdirSync(githubWorkflowsDir);
268
+ if (workflows.length > 0) {
269
+ analysis.manualReviewItems.push(
270
+ `Review ${workflows.length} existing GitHub workflow(s) for potential conflicts`,
271
+ );
272
+ }
273
+ } catch {
274
+ // Ignore
275
+ }
276
+ }
277
+
278
+ // GitLab CI
279
+ if (fs.existsSync(path.join(targetDir, '.gitlab-ci.yml'))) {
280
+ analysis.hasExistingWorkflows = true;
281
+ analysis.configs.gitlabCi = '.gitlab-ci.yml';
282
+ analysis.manualReviewItems.push('Review existing GitLab CI configuration');
283
+ }
284
+
285
+ // CircleCI
286
+ if (fs.existsSync(path.join(targetDir, '.circleci', 'config.yml'))) {
287
+ analysis.hasExistingWorkflows = true;
288
+ analysis.manualReviewItems.push('Review existing CircleCI configuration');
289
+ }
290
+ }
291
+
292
+ /**
293
+ * Analyzes the directory structure
294
+ *
295
+ * @param {string} targetDir - Directory to analyze
296
+ * @param {BrownfieldAnalysis} analysis - Analysis object to populate
297
+ */
298
+ function analyzeDirectoryStructure(targetDir, analysis) {
299
+ // Common source directories
300
+ const srcDirs = ['src', 'lib', 'app', 'source', 'pkg', 'cmd', 'internal'];
301
+ const testDirs = ['test', 'tests', '__tests__', 'spec'];
302
+ const docDirs = ['docs', 'doc', 'documentation'];
303
+
304
+ let hasSrcDir = false;
305
+ let hasTestDir = false;
306
+ let hasDocDir = false;
307
+
308
+ try {
309
+ const contents = fs.readdirSync(targetDir);
310
+
311
+ for (const item of contents) {
312
+ const itemPath = path.join(targetDir, item);
313
+ if (fs.statSync(itemPath).isDirectory()) {
314
+ if (srcDirs.includes(item.toLowerCase())) hasSrcDir = true;
315
+ if (testDirs.includes(item.toLowerCase())) hasTestDir = true;
316
+ if (docDirs.includes(item.toLowerCase())) hasDocDir = true;
317
+ }
318
+ }
319
+ } catch {
320
+ // Ignore
321
+ }
322
+
323
+ analysis.hasExistingStructure = hasSrcDir || hasTestDir;
324
+
325
+ // Check for docs/architecture conflict
326
+ if (hasDocDir) {
327
+ const archDir = path.join(targetDir, 'docs', 'architecture');
328
+ if (fs.existsSync(archDir)) {
329
+ analysis.conflicts.push(
330
+ 'docs/architecture/ already exists - AIOS docs may need different location',
331
+ );
332
+ }
333
+ }
334
+ }
335
+
336
+ /**
337
+ * Generates recommendations based on analysis
338
+ *
339
+ * @param {BrownfieldAnalysis} analysis - Analysis object to update
340
+ */
341
+ function generateRecommendations(analysis) {
342
+ // Linting recommendations
343
+ if (analysis.linting !== 'none') {
344
+ analysis.recommendations.push(
345
+ `Preserve existing ${analysis.linting} configuration - AIOS will adapt`,
346
+ );
347
+ } else {
348
+ analysis.recommendations.push('Consider adding ESLint/Flake8 for code quality');
349
+ }
350
+
351
+ // Formatting recommendations
352
+ if (analysis.formatting !== 'none') {
353
+ analysis.recommendations.push(
354
+ `Keep existing ${analysis.formatting} settings - AIOS coding-standards.md will document them`,
355
+ );
356
+ }
357
+
358
+ // Workflow recommendations
359
+ if (analysis.hasExistingWorkflows) {
360
+ analysis.recommendations.push('Review existing CI/CD before adding AIOS workflows');
361
+ analysis.mergeStrategy = 'manual';
362
+ } else {
363
+ analysis.recommendations.push('Use *setup-github to add AIOS standard workflows');
364
+ analysis.mergeStrategy = 'parallel';
365
+ }
366
+
367
+ // TypeScript recommendations
368
+ if (analysis.configs.tsconfig) {
369
+ analysis.recommendations.push('AIOS will use existing tsconfig.json settings');
370
+ }
371
+
372
+ // Framework-specific
373
+ if (analysis.frameworks.includes('Next.js')) {
374
+ analysis.recommendations.push('Next.js detected - use pages/ or app/ structure');
375
+ }
376
+
377
+ if (analysis.frameworks.includes('NestJS')) {
378
+ analysis.recommendations.push('NestJS detected - AIOS will adapt to module structure');
379
+ }
380
+ }
381
+
382
+ /**
383
+ * Generates a summary of the analysis
384
+ *
385
+ * @param {BrownfieldAnalysis} analysis - Analysis object to update
386
+ */
387
+ function generateSummary(analysis) {
388
+ const parts = [];
389
+
390
+ parts.push(`Tech Stack: ${analysis.techStack.join(', ') || 'Unknown'}`);
391
+
392
+ if (analysis.frameworks.length > 0) {
393
+ parts.push(`Frameworks: ${analysis.frameworks.join(', ')}`);
394
+ }
395
+
396
+ if (analysis.hasExistingStandards) {
397
+ parts.push(`Standards: ${analysis.linting}/${analysis.formatting}`);
398
+ }
399
+
400
+ if (analysis.hasExistingWorkflows) {
401
+ parts.push('CI/CD: Existing workflows detected');
402
+ }
403
+
404
+ parts.push(`Recommended Strategy: ${analysis.mergeStrategy}`);
405
+
406
+ analysis.summary = parts.join(' | ');
407
+ }
408
+
409
+ /**
410
+ * Gets a migration report for display
411
+ *
412
+ * @param {BrownfieldAnalysis} analysis - Analysis results
413
+ * @returns {string} Formatted migration report
414
+ */
415
+ function formatMigrationReport(analysis) {
416
+ const lines = [];
417
+ const width = 70;
418
+ const border = '═'.repeat(width);
419
+
420
+ lines.push(`╔${border}╗`);
421
+ lines.push(`║${'BROWNFIELD ANALYSIS REPORT'.padStart((width + 26) / 2).padEnd(width)}║`);
422
+ lines.push(`╠${border}╣`);
423
+
424
+ // Tech Stack
425
+ lines.push(`║${''.padEnd(width)}║`);
426
+ lines.push(`║ Tech Stack: ${(analysis.techStack.join(', ') || 'Unknown').padEnd(width - 16)}║`);
427
+
428
+ if (analysis.frameworks.length > 0) {
429
+ lines.push(`║ Frameworks: ${analysis.frameworks.join(', ').padEnd(width - 16)}║`);
430
+ }
431
+
432
+ // Standards
433
+ lines.push(`║${''.padEnd(width)}║`);
434
+ lines.push(`║ Linting: ${analysis.linting.padEnd(width - 13)}║`);
435
+ lines.push(`║ Formatting: ${analysis.formatting.padEnd(width - 16)}║`);
436
+ lines.push(`║ Testing: ${analysis.testing.padEnd(width - 13)}║`);
437
+
438
+ // Workflows
439
+ lines.push(`║${''.padEnd(width)}║`);
440
+ lines.push(
441
+ `║ Existing Workflows: ${(analysis.hasExistingWorkflows ? 'Yes' : 'No').padEnd(width - 24)}║`,
442
+ );
443
+ lines.push(`║ Merge Strategy: ${analysis.mergeStrategy.padEnd(width - 20)}║`);
444
+
445
+ // Recommendations
446
+ if (analysis.recommendations.length > 0) {
447
+ lines.push(`║${''.padEnd(width)}║`);
448
+ lines.push(`╠${border}╣`);
449
+ lines.push(`║ RECOMMENDATIONS${' '.repeat(width - 18)}║`);
450
+ lines.push(`╠${border}╣`);
451
+ lines.push(`║${''.padEnd(width)}║`);
452
+
453
+ for (const rec of analysis.recommendations) {
454
+ const truncated = rec.substring(0, width - 6);
455
+ lines.push(`║ • ${truncated.padEnd(width - 5)}║`);
456
+ }
457
+ }
458
+
459
+ // Conflicts
460
+ if (analysis.conflicts.length > 0) {
461
+ lines.push(`║${''.padEnd(width)}║`);
462
+ lines.push(`╠${border}╣`);
463
+ lines.push(`║ ⚠️ POTENTIAL CONFLICTS${' '.repeat(width - 25)}║`);
464
+ lines.push(`╠${border}╣`);
465
+ lines.push(`║${''.padEnd(width)}║`);
466
+
467
+ for (const conflict of analysis.conflicts) {
468
+ const truncated = conflict.substring(0, width - 6);
469
+ lines.push(`║ • ${truncated.padEnd(width - 5)}║`);
470
+ }
471
+ }
472
+
473
+ // Manual Review Items
474
+ if (analysis.manualReviewItems.length > 0) {
475
+ lines.push(`║${''.padEnd(width)}║`);
476
+ lines.push(`╠${border}╣`);
477
+ lines.push(`║ 📋 MANUAL REVIEW REQUIRED${' '.repeat(width - 28)}║`);
478
+ lines.push(`╠${border}╣`);
479
+ lines.push(`║${''.padEnd(width)}║`);
480
+
481
+ for (const item of analysis.manualReviewItems) {
482
+ const truncated = item.substring(0, width - 6);
483
+ lines.push(`║ • ${truncated.padEnd(width - 5)}║`);
484
+ }
485
+ }
486
+
487
+ lines.push(`║${''.padEnd(width)}║`);
488
+ lines.push(`╚${border}╝`);
489
+
490
+ return lines.join('\n');
491
+ }
492
+
493
+ module.exports = {
494
+ analyzeProject,
495
+ analyzeTechStack,
496
+ analyzeCodeStandards,
497
+ analyzeWorkflows,
498
+ analyzeDirectoryStructure,
499
+ generateRecommendations,
500
+ formatMigrationReport,
501
+ };