aios-core 2.1.4 → 2.1.5
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/infrastructure/scripts/llm-routing/install-llm-routing.js +6 -6
- package/package.json +1 -1
- package/packages/installer/src/config/templates/env-template.js +2 -2
- package/packages/installer/src/wizard/wizard.js +34 -185
- package/src/wizard/index.js +2 -2
- package/.aios-core/development/tasks/analyze-brownfield.md +0 -456
- package/.aios-core/development/tasks/setup-project-docs.md +0 -444
- package/.aios-core/infrastructure/scripts/documentation-integrity/brownfield-analyzer.js +0 -501
- package/.aios-core/infrastructure/scripts/documentation-integrity/config-generator.js +0 -329
- package/.aios-core/infrastructure/scripts/documentation-integrity/deployment-config-loader.js +0 -282
- package/.aios-core/infrastructure/scripts/documentation-integrity/doc-generator.js +0 -331
- package/.aios-core/infrastructure/scripts/documentation-integrity/gitignore-generator.js +0 -312
- package/.aios-core/infrastructure/scripts/documentation-integrity/index.js +0 -74
- package/.aios-core/infrastructure/scripts/documentation-integrity/mode-detector.js +0 -358
- package/.aios-core/infrastructure/templates/core-config/core-config-brownfield.tmpl.yaml +0 -182
- package/.aios-core/infrastructure/templates/core-config/core-config-greenfield.tmpl.yaml +0 -127
- package/.aios-core/infrastructure/templates/gitignore/gitignore-aios-base.tmpl +0 -63
- package/.aios-core/infrastructure/templates/gitignore/gitignore-brownfield-merge.tmpl +0 -18
- package/.aios-core/infrastructure/templates/gitignore/gitignore-node.tmpl +0 -85
- package/.aios-core/infrastructure/templates/gitignore/gitignore-python.tmpl +0 -145
- package/.aios-core/infrastructure/templates/project-docs/coding-standards-tmpl.md +0 -346
- package/.aios-core/infrastructure/templates/project-docs/source-tree-tmpl.md +0 -177
- package/.aios-core/infrastructure/templates/project-docs/tech-stack-tmpl.md +0 -267
|
@@ -1,331 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Documentation Generator Module
|
|
3
|
-
*
|
|
4
|
-
* Generates project-specific documentation from templates.
|
|
5
|
-
* Supports Node.js, Python, Go, and Rust projects.
|
|
6
|
-
*
|
|
7
|
-
* @module documentation-integrity/doc-generator
|
|
8
|
-
* @version 1.0.0
|
|
9
|
-
* @story 6.9
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
const fs = require('fs');
|
|
13
|
-
const path = require('path');
|
|
14
|
-
|
|
15
|
-
// Template directory
|
|
16
|
-
const TEMPLATES_DIR = path.join(__dirname, '..', '..', 'templates', 'project-docs');
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Template file names
|
|
20
|
-
* @enum {string}
|
|
21
|
-
*/
|
|
22
|
-
const TemplateFiles = {
|
|
23
|
-
SOURCE_TREE: 'source-tree-tmpl.md',
|
|
24
|
-
CODING_STANDARDS: 'coding-standards-tmpl.md',
|
|
25
|
-
TECH_STACK: 'tech-stack-tmpl.md',
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Output file names
|
|
30
|
-
* @enum {string}
|
|
31
|
-
*/
|
|
32
|
-
const OutputFiles = {
|
|
33
|
-
SOURCE_TREE: 'source-tree.md',
|
|
34
|
-
CODING_STANDARDS: 'coding-standards.md',
|
|
35
|
-
TECH_STACK: 'tech-stack.md',
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Documentation context for template rendering
|
|
40
|
-
* @typedef {Object} DocContext
|
|
41
|
-
* @property {string} PROJECT_NAME - Project name
|
|
42
|
-
* @property {string} GENERATED_DATE - Generation date
|
|
43
|
-
* @property {string} INSTALLATION_MODE - Installation mode
|
|
44
|
-
* @property {string} TECH_STACK - Detected tech stack
|
|
45
|
-
* @property {boolean} IS_NODE - Is Node.js project
|
|
46
|
-
* @property {boolean} IS_PYTHON - Is Python project
|
|
47
|
-
* @property {boolean} IS_GO - Is Go project
|
|
48
|
-
* @property {boolean} IS_RUST - Is Rust project
|
|
49
|
-
* @property {boolean} IS_TYPESCRIPT - Uses TypeScript
|
|
50
|
-
*/
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Builds documentation context from detected markers
|
|
54
|
-
*
|
|
55
|
-
* @param {string} projectName - Project name
|
|
56
|
-
* @param {string} mode - Installation mode
|
|
57
|
-
* @param {Object} markers - Detected project markers
|
|
58
|
-
* @param {Object} [overrides] - Optional context overrides
|
|
59
|
-
* @returns {DocContext} Documentation context
|
|
60
|
-
*/
|
|
61
|
-
function buildDocContext(projectName, mode, markers, overrides = {}) {
|
|
62
|
-
// Detect tech stack from markers
|
|
63
|
-
const techStacks = [];
|
|
64
|
-
if (markers.hasPackageJson) techStacks.push('Node.js');
|
|
65
|
-
if (markers.hasPythonProject) techStacks.push('Python');
|
|
66
|
-
if (markers.hasGoMod) techStacks.push('Go');
|
|
67
|
-
if (markers.hasCargoToml) techStacks.push('Rust');
|
|
68
|
-
|
|
69
|
-
// Determine file extension
|
|
70
|
-
let fileExt = 'js';
|
|
71
|
-
if (markers.hasTsconfig) fileExt = 'ts';
|
|
72
|
-
|
|
73
|
-
// Build context
|
|
74
|
-
const context = {
|
|
75
|
-
// Basic info
|
|
76
|
-
PROJECT_NAME: projectName,
|
|
77
|
-
GENERATED_DATE: new Date().toISOString().split('T')[0],
|
|
78
|
-
INSTALLATION_MODE: mode,
|
|
79
|
-
TECH_STACK: techStacks.join(', ') || 'Unknown',
|
|
80
|
-
|
|
81
|
-
// Language flags
|
|
82
|
-
IS_NODE: markers.hasPackageJson || false,
|
|
83
|
-
IS_PYTHON: markers.hasPythonProject || false,
|
|
84
|
-
IS_GO: markers.hasGoMod || false,
|
|
85
|
-
IS_RUST: markers.hasCargoToml || false,
|
|
86
|
-
IS_TYPESCRIPT: markers.hasTsconfig || false,
|
|
87
|
-
|
|
88
|
-
// Node.js specific
|
|
89
|
-
FILE_EXT: fileExt,
|
|
90
|
-
NODE_VERSION: '18+',
|
|
91
|
-
TYPESCRIPT_VERSION: '5.0+',
|
|
92
|
-
NPM_VERSION: '9+',
|
|
93
|
-
SEMICOLONS: 'Required',
|
|
94
|
-
SEMICOLONS_RULE: 'always',
|
|
95
|
-
PRETTIER_SEMI: true,
|
|
96
|
-
|
|
97
|
-
// Python specific
|
|
98
|
-
PYTHON_PACKAGE_NAME: projectName.toLowerCase().replace(/[^a-z0-9]/g, '_'),
|
|
99
|
-
PYTHON_VERSION: '3.11+',
|
|
100
|
-
PYTHON_SHORT_VERSION: '311',
|
|
101
|
-
POETRY_VERSION: '1.5+',
|
|
102
|
-
|
|
103
|
-
// Go specific
|
|
104
|
-
GO_VERSION: '1.21+',
|
|
105
|
-
GO_MODULE: `github.com/user/${projectName}`,
|
|
106
|
-
|
|
107
|
-
// Rust specific
|
|
108
|
-
RUST_VERSION: '1.70+',
|
|
109
|
-
|
|
110
|
-
// Deployment
|
|
111
|
-
DEPLOYMENT_PLATFORM: null,
|
|
112
|
-
PRODUCTION_BRANCH: 'main',
|
|
113
|
-
STAGING_BRANCH: 'staging',
|
|
114
|
-
HAS_STAGING: false,
|
|
115
|
-
|
|
116
|
-
// Database
|
|
117
|
-
DATABASE: null,
|
|
118
|
-
CACHE: null,
|
|
119
|
-
|
|
120
|
-
// Quality gates
|
|
121
|
-
QUALITY_GATES: ['Lint', 'Type Check', 'Tests'],
|
|
122
|
-
|
|
123
|
-
// Dependencies (to be populated by analyzer)
|
|
124
|
-
DEPENDENCIES: [],
|
|
125
|
-
DEV_DEPENDENCIES: [],
|
|
126
|
-
ENV_VARS: [],
|
|
127
|
-
|
|
128
|
-
// Apply overrides
|
|
129
|
-
...overrides,
|
|
130
|
-
};
|
|
131
|
-
|
|
132
|
-
return context;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* Simple template renderer with Handlebars-like syntax
|
|
137
|
-
* Supports: {{variable}}, {{#if condition}}, {{/if}}, {{#each array}}, {{/each}}
|
|
138
|
-
*
|
|
139
|
-
* @param {string} template - Template string
|
|
140
|
-
* @param {Object} context - Context object
|
|
141
|
-
* @returns {string} Rendered template
|
|
142
|
-
*/
|
|
143
|
-
function renderTemplate(template, context) {
|
|
144
|
-
let result = template;
|
|
145
|
-
|
|
146
|
-
// Process {{#if}} blocks
|
|
147
|
-
result = processIfBlocks(result, context);
|
|
148
|
-
|
|
149
|
-
// Process {{#each}} blocks
|
|
150
|
-
result = processEachBlocks(result, context);
|
|
151
|
-
|
|
152
|
-
// Replace simple variables {{variable}}
|
|
153
|
-
result = result.replace(/\{\{([^#/}][^}]*)\}\}/g, (match, key) => {
|
|
154
|
-
const value = getNestedValue(context, key.trim());
|
|
155
|
-
return value !== undefined ? String(value) : match;
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
// Clean up empty lines from removed blocks
|
|
159
|
-
result = result.replace(/\n{3,}/g, '\n\n');
|
|
160
|
-
|
|
161
|
-
return result;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
/**
|
|
165
|
-
* Process {{#if condition}}...{{/if}} blocks
|
|
166
|
-
*
|
|
167
|
-
* @param {string} template - Template string
|
|
168
|
-
* @param {Object} context - Context object
|
|
169
|
-
* @returns {string} Processed template
|
|
170
|
-
*/
|
|
171
|
-
function processIfBlocks(template, context) {
|
|
172
|
-
// Match if blocks (non-greedy, innermost first)
|
|
173
|
-
const ifRegex = /\{\{#if\s+(\w+)\}\}([\s\S]*?)\{\{\/if\}\}/g;
|
|
174
|
-
|
|
175
|
-
let result = template;
|
|
176
|
-
let iterations = 0;
|
|
177
|
-
const maxIterations = 100; // Prevent infinite loops
|
|
178
|
-
|
|
179
|
-
while (ifRegex.test(result) && iterations < maxIterations) {
|
|
180
|
-
result = result.replace(ifRegex, (match, condition, content) => {
|
|
181
|
-
const value = context[condition];
|
|
182
|
-
if (value) {
|
|
183
|
-
return content;
|
|
184
|
-
}
|
|
185
|
-
return '';
|
|
186
|
-
});
|
|
187
|
-
iterations++;
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
return result;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
/**
|
|
194
|
-
* Process {{#each array}}...{{/each}} blocks
|
|
195
|
-
*
|
|
196
|
-
* @param {string} template - Template string
|
|
197
|
-
* @param {Object} context - Context object
|
|
198
|
-
* @returns {string} Processed template
|
|
199
|
-
*/
|
|
200
|
-
function processEachBlocks(template, context) {
|
|
201
|
-
const eachRegex = /\{\{#each\s+(\w+)\}\}([\s\S]*?)\{\{\/each\}\}/g;
|
|
202
|
-
|
|
203
|
-
return template.replace(eachRegex, (match, arrayName, content) => {
|
|
204
|
-
const array = context[arrayName];
|
|
205
|
-
if (!Array.isArray(array) || array.length === 0) {
|
|
206
|
-
return '';
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
return array
|
|
210
|
-
.map((item) => {
|
|
211
|
-
let itemContent = content;
|
|
212
|
-
if (typeof item === 'object') {
|
|
213
|
-
// Replace {{this.property}} with item properties
|
|
214
|
-
itemContent = itemContent.replace(/\{\{this\.(\w+)\}\}/g, (m, prop) => {
|
|
215
|
-
return item[prop] !== undefined ? String(item[prop]) : m;
|
|
216
|
-
});
|
|
217
|
-
} else {
|
|
218
|
-
// Replace {{this}} with item value
|
|
219
|
-
itemContent = itemContent.replace(/\{\{this\}\}/g, String(item));
|
|
220
|
-
}
|
|
221
|
-
return itemContent;
|
|
222
|
-
})
|
|
223
|
-
.join('');
|
|
224
|
-
});
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
/**
|
|
228
|
-
* Get nested value from object using dot notation
|
|
229
|
-
*
|
|
230
|
-
* @param {Object} obj - Object to search
|
|
231
|
-
* @param {string} path - Dot-notation path
|
|
232
|
-
* @returns {*} Value at path or undefined
|
|
233
|
-
*/
|
|
234
|
-
function getNestedValue(obj, path) {
|
|
235
|
-
return path.split('.').reduce((current, key) => {
|
|
236
|
-
return current && current[key] !== undefined ? current[key] : undefined;
|
|
237
|
-
}, obj);
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
/**
|
|
241
|
-
* Loads a template file
|
|
242
|
-
*
|
|
243
|
-
* @param {string} templateName - Template file name
|
|
244
|
-
* @returns {string} Template content
|
|
245
|
-
* @throws {Error} If template not found
|
|
246
|
-
*/
|
|
247
|
-
function loadTemplate(templateName) {
|
|
248
|
-
const templatePath = path.join(TEMPLATES_DIR, templateName);
|
|
249
|
-
|
|
250
|
-
if (!fs.existsSync(templatePath)) {
|
|
251
|
-
throw new Error(`Template not found: ${templatePath}`);
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
return fs.readFileSync(templatePath, 'utf8');
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
/**
|
|
258
|
-
* Generates all documentation files for a project
|
|
259
|
-
*
|
|
260
|
-
* @param {string} targetDir - Target directory
|
|
261
|
-
* @param {DocContext} context - Documentation context
|
|
262
|
-
* @param {Object} [options] - Generation options
|
|
263
|
-
* @param {boolean} [options.dryRun] - Don't write files, just return content
|
|
264
|
-
* @returns {Object} Generated files with content
|
|
265
|
-
*/
|
|
266
|
-
function generateDocs(targetDir, context, options = {}) {
|
|
267
|
-
const docsDir = path.join(targetDir, 'docs', 'architecture');
|
|
268
|
-
const results = {};
|
|
269
|
-
|
|
270
|
-
// Ensure docs directory exists
|
|
271
|
-
if (!options.dryRun) {
|
|
272
|
-
fs.mkdirSync(docsDir, { recursive: true });
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
// Generate each doc
|
|
276
|
-
const templates = [
|
|
277
|
-
{ template: TemplateFiles.SOURCE_TREE, output: OutputFiles.SOURCE_TREE },
|
|
278
|
-
{ template: TemplateFiles.CODING_STANDARDS, output: OutputFiles.CODING_STANDARDS },
|
|
279
|
-
{ template: TemplateFiles.TECH_STACK, output: OutputFiles.TECH_STACK },
|
|
280
|
-
];
|
|
281
|
-
|
|
282
|
-
for (const { template, output } of templates) {
|
|
283
|
-
try {
|
|
284
|
-
const templateContent = loadTemplate(template);
|
|
285
|
-
const rendered = renderTemplate(templateContent, context);
|
|
286
|
-
const outputPath = path.join(docsDir, output);
|
|
287
|
-
|
|
288
|
-
results[output] = {
|
|
289
|
-
path: outputPath,
|
|
290
|
-
content: rendered,
|
|
291
|
-
success: true,
|
|
292
|
-
};
|
|
293
|
-
|
|
294
|
-
if (!options.dryRun) {
|
|
295
|
-
fs.writeFileSync(outputPath, rendered, 'utf8');
|
|
296
|
-
}
|
|
297
|
-
} catch (error) {
|
|
298
|
-
results[output] = {
|
|
299
|
-
path: path.join(docsDir, output),
|
|
300
|
-
content: null,
|
|
301
|
-
success: false,
|
|
302
|
-
error: error.message,
|
|
303
|
-
};
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
return results;
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
/**
|
|
311
|
-
* Generates a single documentation file
|
|
312
|
-
*
|
|
313
|
-
* @param {string} templateName - Template file name
|
|
314
|
-
* @param {DocContext} context - Documentation context
|
|
315
|
-
* @returns {string} Rendered content
|
|
316
|
-
*/
|
|
317
|
-
function generateDoc(templateName, context) {
|
|
318
|
-
const template = loadTemplate(templateName);
|
|
319
|
-
return renderTemplate(template, context);
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
module.exports = {
|
|
323
|
-
buildDocContext,
|
|
324
|
-
renderTemplate,
|
|
325
|
-
loadTemplate,
|
|
326
|
-
generateDocs,
|
|
327
|
-
generateDoc,
|
|
328
|
-
TemplateFiles,
|
|
329
|
-
OutputFiles,
|
|
330
|
-
TEMPLATES_DIR,
|
|
331
|
-
};
|
|
@@ -1,312 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Gitignore Generator Module
|
|
3
|
-
*
|
|
4
|
-
* Generates .gitignore files based on detected tech stack.
|
|
5
|
-
* Supports brownfield merge mode to preserve existing ignores.
|
|
6
|
-
*
|
|
7
|
-
* @module documentation-integrity/gitignore-generator
|
|
8
|
-
* @version 1.0.0
|
|
9
|
-
* @story 6.9
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
const fs = require('fs');
|
|
13
|
-
const path = require('path');
|
|
14
|
-
|
|
15
|
-
// Template directory
|
|
16
|
-
const TEMPLATES_DIR = path.join(__dirname, '..', '..', 'templates', 'gitignore');
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Template file names
|
|
20
|
-
* @enum {string}
|
|
21
|
-
*/
|
|
22
|
-
const GitignoreTemplates = {
|
|
23
|
-
AIOS_BASE: 'gitignore-aios-base.tmpl',
|
|
24
|
-
NODE: 'gitignore-node.tmpl',
|
|
25
|
-
PYTHON: 'gitignore-python.tmpl',
|
|
26
|
-
BROWNFIELD_MERGE: 'gitignore-brownfield-merge.tmpl',
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Tech stack identifiers
|
|
31
|
-
* @enum {string}
|
|
32
|
-
*/
|
|
33
|
-
const TechStack = {
|
|
34
|
-
NODE: 'node',
|
|
35
|
-
PYTHON: 'python',
|
|
36
|
-
GO: 'go',
|
|
37
|
-
RUST: 'rust',
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Loads a gitignore template
|
|
42
|
-
*
|
|
43
|
-
* @param {string} templateName - Template file name
|
|
44
|
-
* @returns {string} Template content
|
|
45
|
-
* @throws {Error} If template not found
|
|
46
|
-
*/
|
|
47
|
-
function loadGitignoreTemplate(templateName) {
|
|
48
|
-
const templatePath = path.join(TEMPLATES_DIR, templateName);
|
|
49
|
-
|
|
50
|
-
if (!fs.existsSync(templatePath)) {
|
|
51
|
-
throw new Error(`Gitignore template not found: ${templatePath}`);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
return fs.readFileSync(templatePath, 'utf8');
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Detects tech stack from project markers
|
|
59
|
-
*
|
|
60
|
-
* @param {Object} markers - Detected project markers
|
|
61
|
-
* @returns {string[]} List of detected tech stacks
|
|
62
|
-
*/
|
|
63
|
-
function detectTechStacks(markers) {
|
|
64
|
-
const stacks = [];
|
|
65
|
-
|
|
66
|
-
if (markers.hasPackageJson) stacks.push(TechStack.NODE);
|
|
67
|
-
if (markers.hasPythonProject) stacks.push(TechStack.PYTHON);
|
|
68
|
-
if (markers.hasGoMod) stacks.push(TechStack.GO);
|
|
69
|
-
if (markers.hasCargoToml) stacks.push(TechStack.RUST);
|
|
70
|
-
|
|
71
|
-
return stacks;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Gets gitignore templates for detected tech stacks
|
|
76
|
-
*
|
|
77
|
-
* @param {string[]} techStacks - Detected tech stacks
|
|
78
|
-
* @returns {string[]} List of template names to use
|
|
79
|
-
*/
|
|
80
|
-
function getTemplatesForStacks(techStacks) {
|
|
81
|
-
const templates = [GitignoreTemplates.AIOS_BASE];
|
|
82
|
-
|
|
83
|
-
for (const stack of techStacks) {
|
|
84
|
-
switch (stack) {
|
|
85
|
-
case TechStack.NODE:
|
|
86
|
-
templates.push(GitignoreTemplates.NODE);
|
|
87
|
-
break;
|
|
88
|
-
case TechStack.PYTHON:
|
|
89
|
-
templates.push(GitignoreTemplates.PYTHON);
|
|
90
|
-
break;
|
|
91
|
-
// Go and Rust would have their own templates
|
|
92
|
-
// Add when implemented
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
return templates;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* Generates a complete .gitignore file
|
|
101
|
-
*
|
|
102
|
-
* @param {Object} markers - Detected project markers
|
|
103
|
-
* @param {Object} [options] - Generation options
|
|
104
|
-
* @param {string} [options.projectName] - Project name for header
|
|
105
|
-
* @returns {string} Generated gitignore content
|
|
106
|
-
*/
|
|
107
|
-
function generateGitignore(markers, options = {}) {
|
|
108
|
-
const techStacks = detectTechStacks(markers);
|
|
109
|
-
const templates = getTemplatesForStacks(techStacks);
|
|
110
|
-
|
|
111
|
-
const sections = [];
|
|
112
|
-
|
|
113
|
-
// Add project header
|
|
114
|
-
const projectName = options.projectName || 'Project';
|
|
115
|
-
sections.push(`# ${projectName} .gitignore`);
|
|
116
|
-
sections.push('# Generated by AIOS Documentation Integrity System');
|
|
117
|
-
sections.push(`# Date: ${new Date().toISOString().split('T')[0]}`);
|
|
118
|
-
sections.push(`# Tech Stack: ${techStacks.join(', ') || 'Generic'}`);
|
|
119
|
-
sections.push('');
|
|
120
|
-
|
|
121
|
-
// Load and append each template
|
|
122
|
-
for (const templateName of templates) {
|
|
123
|
-
try {
|
|
124
|
-
const content = loadGitignoreTemplate(templateName);
|
|
125
|
-
sections.push(content);
|
|
126
|
-
sections.push(''); // Add blank line between sections
|
|
127
|
-
} catch (error) {
|
|
128
|
-
console.warn(`Warning: Could not load template ${templateName}: ${error.message}`);
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
return sections.join('\n').trim() + '\n';
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* Merges AIOS ignores with existing .gitignore
|
|
137
|
-
*
|
|
138
|
-
* @param {string} existingContent - Existing .gitignore content
|
|
139
|
-
* @param {Object} [options] - Merge options
|
|
140
|
-
* @returns {string} Merged gitignore content
|
|
141
|
-
*/
|
|
142
|
-
function mergeGitignore(existingContent, _options = {}) {
|
|
143
|
-
// Check if AIOS section already exists
|
|
144
|
-
if (existingContent.includes('AIOS Integration Section')) {
|
|
145
|
-
console.log('AIOS section already exists in .gitignore, skipping merge');
|
|
146
|
-
return existingContent;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
// Load merge template
|
|
150
|
-
let mergeSection;
|
|
151
|
-
try {
|
|
152
|
-
mergeSection = loadGitignoreTemplate(GitignoreTemplates.BROWNFIELD_MERGE);
|
|
153
|
-
} catch {
|
|
154
|
-
// Fallback to minimal section
|
|
155
|
-
mergeSection = `
|
|
156
|
-
# ========================================
|
|
157
|
-
# AIOS Integration Section
|
|
158
|
-
# ========================================
|
|
159
|
-
|
|
160
|
-
# AIOS Local Configuration
|
|
161
|
-
.aios-core/local/
|
|
162
|
-
.aios-core/*.local.yaml
|
|
163
|
-
.aios-core/logs/
|
|
164
|
-
.aios-core/cache/
|
|
165
|
-
|
|
166
|
-
# ========================================
|
|
167
|
-
# End of AIOS Integration Section
|
|
168
|
-
# ========================================
|
|
169
|
-
`;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
// Replace date placeholder
|
|
173
|
-
mergeSection = mergeSection.replace(
|
|
174
|
-
'{{GENERATED_DATE}}',
|
|
175
|
-
new Date().toISOString().split('T')[0],
|
|
176
|
-
);
|
|
177
|
-
|
|
178
|
-
// Append to existing content
|
|
179
|
-
const merged = existingContent.trimEnd() + '\n\n' + mergeSection.trim() + '\n';
|
|
180
|
-
|
|
181
|
-
return merged;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
/**
|
|
185
|
-
* Generates or merges .gitignore for a project
|
|
186
|
-
*
|
|
187
|
-
* @param {string} targetDir - Target directory
|
|
188
|
-
* @param {Object} markers - Detected project markers
|
|
189
|
-
* @param {Object} [options] - Generation options
|
|
190
|
-
* @param {boolean} [options.dryRun] - Don't write file, just return content
|
|
191
|
-
* @param {boolean} [options.merge] - Merge with existing instead of replace
|
|
192
|
-
* @param {string} [options.projectName] - Project name for header
|
|
193
|
-
* @returns {Object} Generation result
|
|
194
|
-
*/
|
|
195
|
-
function generateGitignoreFile(targetDir, markers, options = {}) {
|
|
196
|
-
const gitignorePath = path.join(targetDir, '.gitignore');
|
|
197
|
-
const existingPath = fs.existsSync(gitignorePath);
|
|
198
|
-
|
|
199
|
-
let content;
|
|
200
|
-
let mode;
|
|
201
|
-
|
|
202
|
-
if (existingPath && options.merge !== false) {
|
|
203
|
-
// Brownfield mode - merge with existing
|
|
204
|
-
const existing = fs.readFileSync(gitignorePath, 'utf8');
|
|
205
|
-
content = mergeGitignore(existing, options);
|
|
206
|
-
mode = 'merged';
|
|
207
|
-
} else {
|
|
208
|
-
// Greenfield mode - generate new
|
|
209
|
-
content = generateGitignore(markers, options);
|
|
210
|
-
mode = existingPath ? 'replaced' : 'created';
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
const result = {
|
|
214
|
-
success: true,
|
|
215
|
-
path: gitignorePath,
|
|
216
|
-
content,
|
|
217
|
-
mode,
|
|
218
|
-
techStacks: detectTechStacks(markers),
|
|
219
|
-
};
|
|
220
|
-
|
|
221
|
-
if (!options.dryRun) {
|
|
222
|
-
try {
|
|
223
|
-
fs.writeFileSync(gitignorePath, content, 'utf8');
|
|
224
|
-
} catch (error) {
|
|
225
|
-
result.success = false;
|
|
226
|
-
result.error = error.message;
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
return result;
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
/**
|
|
234
|
-
* Checks if a .gitignore file has AIOS integration
|
|
235
|
-
*
|
|
236
|
-
* @param {string} targetDir - Target directory
|
|
237
|
-
* @returns {boolean} True if AIOS section exists
|
|
238
|
-
*/
|
|
239
|
-
function hasAiosIntegration(targetDir) {
|
|
240
|
-
const gitignorePath = path.join(targetDir, '.gitignore');
|
|
241
|
-
|
|
242
|
-
if (!fs.existsSync(gitignorePath)) {
|
|
243
|
-
return false;
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
const content = fs.readFileSync(gitignorePath, 'utf8');
|
|
247
|
-
return content.includes('AIOS Integration Section') || content.includes('.aios-core/');
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
/**
|
|
251
|
-
* Parses an existing .gitignore into sections
|
|
252
|
-
*
|
|
253
|
-
* @param {string} content - .gitignore content
|
|
254
|
-
* @returns {Object} Parsed sections
|
|
255
|
-
*/
|
|
256
|
-
function parseGitignore(content) {
|
|
257
|
-
const lines = content.split('\n');
|
|
258
|
-
const sections = {
|
|
259
|
-
header: [],
|
|
260
|
-
patterns: [],
|
|
261
|
-
aiosSection: null,
|
|
262
|
-
comments: [],
|
|
263
|
-
};
|
|
264
|
-
|
|
265
|
-
let aiosStart = -1;
|
|
266
|
-
let aiosEnd = -1;
|
|
267
|
-
|
|
268
|
-
for (let i = 0; i < lines.length; i++) {
|
|
269
|
-
const line = lines[i];
|
|
270
|
-
|
|
271
|
-
if (line.includes('AIOS Integration Section')) {
|
|
272
|
-
if (aiosStart === -1) {
|
|
273
|
-
aiosStart = i;
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
if (line.includes('End of AIOS Integration Section')) {
|
|
278
|
-
aiosEnd = i;
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
if (line.startsWith('#') && !line.includes('AIOS')) {
|
|
282
|
-
sections.comments.push({ line: i, content: line });
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
if (!line.startsWith('#') && line.trim()) {
|
|
286
|
-
sections.patterns.push({ line: i, pattern: line.trim() });
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
if (aiosStart !== -1) {
|
|
291
|
-
sections.aiosSection = {
|
|
292
|
-
start: aiosStart,
|
|
293
|
-
end: aiosEnd !== -1 ? aiosEnd : lines.length - 1,
|
|
294
|
-
};
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
return sections;
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
module.exports = {
|
|
301
|
-
loadGitignoreTemplate,
|
|
302
|
-
detectTechStacks,
|
|
303
|
-
getTemplatesForStacks,
|
|
304
|
-
generateGitignore,
|
|
305
|
-
mergeGitignore,
|
|
306
|
-
generateGitignoreFile,
|
|
307
|
-
hasAiosIntegration,
|
|
308
|
-
parseGitignore,
|
|
309
|
-
GitignoreTemplates,
|
|
310
|
-
TechStack,
|
|
311
|
-
TEMPLATES_DIR,
|
|
312
|
-
};
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Documentation Integrity System
|
|
3
|
-
*
|
|
4
|
-
* Mode-aware project configuration system for AIOS.
|
|
5
|
-
* Supports three installation modes: framework-dev, greenfield, brownfield.
|
|
6
|
-
*
|
|
7
|
-
* @module documentation-integrity
|
|
8
|
-
* @version 1.0.0
|
|
9
|
-
* @story 6.9
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
const modeDetector = require('./mode-detector');
|
|
13
|
-
const docGenerator = require('./doc-generator');
|
|
14
|
-
const configGenerator = require('./config-generator');
|
|
15
|
-
const deploymentConfigLoader = require('./deployment-config-loader');
|
|
16
|
-
const gitignoreGenerator = require('./gitignore-generator');
|
|
17
|
-
const brownfieldAnalyzer = require('./brownfield-analyzer');
|
|
18
|
-
|
|
19
|
-
// Re-export all modules
|
|
20
|
-
module.exports = {
|
|
21
|
-
// Mode detection
|
|
22
|
-
detectInstallationMode: modeDetector.detectInstallationMode,
|
|
23
|
-
collectMarkers: modeDetector.collectMarkers,
|
|
24
|
-
isAiosCoreRepository: modeDetector.isAiosCoreRepository,
|
|
25
|
-
mapLegacyTypeToMode: modeDetector.mapLegacyTypeToMode,
|
|
26
|
-
validateModeSelection: modeDetector.validateModeSelection,
|
|
27
|
-
getModeOptions: modeDetector.getModeOptions,
|
|
28
|
-
|
|
29
|
-
// Mode constants
|
|
30
|
-
InstallationMode: modeDetector.InstallationMode,
|
|
31
|
-
LegacyProjectType: modeDetector.LegacyProjectType,
|
|
32
|
-
ModeDescriptions: modeDetector.ModeDescriptions,
|
|
33
|
-
|
|
34
|
-
// Documentation generation (Phase 2)
|
|
35
|
-
buildDocContext: docGenerator.buildDocContext,
|
|
36
|
-
generateDocs: docGenerator.generateDocs,
|
|
37
|
-
generateDoc: docGenerator.generateDoc,
|
|
38
|
-
TemplateFiles: docGenerator.TemplateFiles,
|
|
39
|
-
OutputFiles: docGenerator.OutputFiles,
|
|
40
|
-
|
|
41
|
-
// Config generation (Phase 3)
|
|
42
|
-
buildConfigContext: configGenerator.buildConfigContext,
|
|
43
|
-
generateConfig: configGenerator.generateConfig,
|
|
44
|
-
buildDeploymentConfig: configGenerator.buildDeploymentConfig,
|
|
45
|
-
ConfigTemplates: configGenerator.ConfigTemplates,
|
|
46
|
-
DeploymentWorkflow: configGenerator.DeploymentWorkflow,
|
|
47
|
-
DeploymentPlatform: configGenerator.DeploymentPlatform,
|
|
48
|
-
|
|
49
|
-
// Deployment config loader (shared utility)
|
|
50
|
-
loadDeploymentConfig: deploymentConfigLoader.loadDeploymentConfig,
|
|
51
|
-
loadProjectConfig: deploymentConfigLoader.loadProjectConfig,
|
|
52
|
-
getTargetBranch: deploymentConfigLoader.getTargetBranch,
|
|
53
|
-
getEnvironmentConfig: deploymentConfigLoader.getEnvironmentConfig,
|
|
54
|
-
isQualityGateEnabled: deploymentConfigLoader.isQualityGateEnabled,
|
|
55
|
-
getEnabledQualityGates: deploymentConfigLoader.getEnabledQualityGates,
|
|
56
|
-
validateDeploymentConfig: deploymentConfigLoader.validateDeploymentConfig,
|
|
57
|
-
|
|
58
|
-
// Gitignore generation (Phase 4)
|
|
59
|
-
generateGitignore: gitignoreGenerator.generateGitignore,
|
|
60
|
-
mergeGitignore: gitignoreGenerator.mergeGitignore,
|
|
61
|
-
generateGitignoreFile: gitignoreGenerator.generateGitignoreFile,
|
|
62
|
-
hasAiosIntegration: gitignoreGenerator.hasAiosIntegration,
|
|
63
|
-
GitignoreTemplates: gitignoreGenerator.GitignoreTemplates,
|
|
64
|
-
TechStack: gitignoreGenerator.TechStack,
|
|
65
|
-
|
|
66
|
-
// Brownfield analysis (Phase 5)
|
|
67
|
-
analyzeProject: brownfieldAnalyzer.analyzeProject,
|
|
68
|
-
analyzeTechStack: brownfieldAnalyzer.analyzeTechStack,
|
|
69
|
-
analyzeCodeStandards: brownfieldAnalyzer.analyzeCodeStandards,
|
|
70
|
-
analyzeWorkflows: brownfieldAnalyzer.analyzeWorkflows,
|
|
71
|
-
analyzeDirectoryStructure: brownfieldAnalyzer.analyzeDirectoryStructure,
|
|
72
|
-
generateRecommendations: brownfieldAnalyzer.generateRecommendations,
|
|
73
|
-
formatMigrationReport: brownfieldAnalyzer.formatMigrationReport,
|
|
74
|
-
};
|