aios-core 2.1.4 → 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 (27) hide show
  1. package/.aios-core/development/tasks/analyze-brownfield.md +456 -456
  2. package/.aios-core/development/tasks/setup-project-docs.md +440 -444
  3. package/.aios-core/infrastructure/scripts/documentation-integrity/brownfield-analyzer.js +501 -501
  4. package/.aios-core/infrastructure/scripts/documentation-integrity/config-generator.js +368 -329
  5. package/.aios-core/infrastructure/scripts/documentation-integrity/deployment-config-loader.js +308 -282
  6. package/.aios-core/infrastructure/scripts/documentation-integrity/doc-generator.js +331 -331
  7. package/.aios-core/infrastructure/scripts/documentation-integrity/gitignore-generator.js +312 -312
  8. package/.aios-core/infrastructure/scripts/documentation-integrity/index.js +74 -74
  9. package/.aios-core/infrastructure/scripts/documentation-integrity/mode-detector.js +389 -358
  10. package/.aios-core/infrastructure/scripts/llm-routing/install-llm-routing.js +6 -6
  11. package/.aios-core/infrastructure/templates/core-config/core-config-brownfield.tmpl.yaml +176 -182
  12. package/.aios-core/infrastructure/templates/core-config/core-config-greenfield.tmpl.yaml +127 -127
  13. package/.aios-core/infrastructure/templates/project-docs/coding-standards-tmpl.md +346 -346
  14. package/.aios-core/infrastructure/templates/project-docs/source-tree-tmpl.md +177 -177
  15. package/.aios-core/infrastructure/templates/project-docs/tech-stack-tmpl.md +267 -267
  16. package/package.json +1 -1
  17. package/packages/installer/src/config/templates/env-template.js +2 -2
  18. package/packages/installer/src/wizard/wizard.js +1 -1
  19. package/packages/installer/tests/integration/environment-configuration.test.js +2 -1
  20. package/packages/installer/tests/unit/env-template.test.js +3 -2
  21. package/src/wizard/index.js +2 -2
  22. package/.aios-core/development/tasks/validate-structure.md +0 -243
  23. package/.aios-core/infrastructure/scripts/source-tree-guardian/index.js +0 -375
  24. package/.aios-core/infrastructure/scripts/source-tree-guardian/manifest-generator.js +0 -410
  25. package/.aios-core/infrastructure/scripts/source-tree-guardian/rules/naming-rules.yaml +0 -285
  26. package/.aios-core/infrastructure/scripts/source-tree-guardian/rules/placement-rules.yaml +0 -262
  27. package/.aios-core/infrastructure/scripts/source-tree-guardian/validator.js +0 -468
@@ -1,410 +0,0 @@
1
- /**
2
- * Source-Tree Guardian - Manifest Generator
3
- *
4
- * Generates a JSON manifest of the current codebase structure
5
- * and compares it against the official source-tree.md.
6
- *
7
- * @module source-tree-guardian/manifest-generator
8
- * @version 1.0.0
9
- * @story 6.8
10
- */
11
-
12
- const fs = require('fs').promises;
13
- const path = require('path');
14
- const { glob } = require('glob');
15
-
16
- /**
17
- * Default exclusion patterns for scanning
18
- */
19
- const DEFAULT_EXCLUSIONS = [
20
- 'node_modules/**',
21
- '.git/**',
22
- 'dist/**',
23
- 'build/**',
24
- 'coverage/**',
25
- '.cache/**',
26
- '*.log',
27
- '*.tmp',
28
- '.DS_Store',
29
- 'Thumbs.db',
30
- 'outputs/**',
31
- '.ai/**',
32
- ];
33
-
34
- /**
35
- * File category definitions
36
- */
37
- const FILE_CATEGORIES = {
38
- agent: {
39
- pattern: '.aios-core/development/agents/**/*.md',
40
- description: 'Agent definitions',
41
- },
42
- task: {
43
- pattern: '.aios-core/development/tasks/**/*.md',
44
- description: 'Task workflows',
45
- },
46
- template: {
47
- pattern: '.aios-core/product/templates/**/*',
48
- description: 'Document templates',
49
- },
50
- checklist: {
51
- pattern: '.aios-core/product/checklists/**/*.md',
52
- description: 'Validation checklists',
53
- },
54
- script: {
55
- pattern: '.aios-core/infrastructure/scripts/**/*.js',
56
- description: 'Infrastructure scripts',
57
- },
58
- tool: {
59
- pattern: '.aios-core/infrastructure/tools/**/*.yaml',
60
- description: 'Tool integrations',
61
- },
62
- utility: {
63
- pattern: '.aios-core/core/utils/**/*.js',
64
- description: 'Utility functions',
65
- },
66
- story: {
67
- pattern: 'docs/stories/**/*.md',
68
- description: 'Development stories',
69
- },
70
- guide: {
71
- pattern: 'docs/guides/**/*.md',
72
- description: 'User guides',
73
- },
74
- architecture: {
75
- pattern: 'docs/architecture/**/*.md',
76
- description: 'Architecture documentation',
77
- },
78
- test: {
79
- pattern: 'tests/**/*.test.js',
80
- description: 'Test files',
81
- },
82
- };
83
-
84
- /**
85
- * Generates a file structure tree
86
- * @param {string} dir - Directory to scan
87
- * @param {string} projectRoot - Project root for relative paths
88
- * @param {number} depth - Current depth level
89
- * @param {number} maxDepth - Maximum depth to scan
90
- * @returns {Promise<Object>} Directory tree structure
91
- */
92
- async function generateTree(dir, projectRoot, depth = 0, maxDepth = 10) {
93
- if (depth > maxDepth) {
94
- return { truncated: true };
95
- }
96
-
97
- const result = {
98
- name: path.basename(dir),
99
- type: 'directory',
100
- path: path.relative(projectRoot, dir).replace(/\\/g, '/') || '.',
101
- children: [],
102
- };
103
-
104
- try {
105
- const entries = await fs.readdir(dir, { withFileTypes: true });
106
-
107
- for (const entry of entries) {
108
- // Skip excluded directories
109
- if (DEFAULT_EXCLUSIONS.some((ex) => entry.name === ex.split('/')[0])) {
110
- continue;
111
- }
112
-
113
- const entryPath = path.join(dir, entry.name);
114
-
115
- if (entry.isDirectory()) {
116
- const subtree = await generateTree(entryPath, projectRoot, depth + 1, maxDepth);
117
- result.children.push(subtree);
118
- } else if (entry.isFile()) {
119
- result.children.push({
120
- name: entry.name,
121
- type: 'file',
122
- path: path.relative(projectRoot, entryPath).replace(/\\/g, '/'),
123
- extension: path.extname(entry.name),
124
- });
125
- }
126
- }
127
-
128
- // Sort: directories first, then files, alphabetically
129
- result.children.sort((a, b) => {
130
- if (a.type !== b.type) {
131
- return a.type === 'directory' ? -1 : 1;
132
- }
133
- return a.name.localeCompare(b.name);
134
- });
135
- } catch (error) {
136
- result.error = error.message;
137
- }
138
-
139
- return result;
140
- }
141
-
142
- /**
143
- * Counts files by category
144
- * @param {string} projectRoot - Project root directory
145
- * @returns {Promise<Object>} File counts by category
146
- */
147
- async function countFilesByCategory(projectRoot) {
148
- const counts = {};
149
-
150
- for (const [category, config] of Object.entries(FILE_CATEGORIES)) {
151
- try {
152
- const files = await glob(config.pattern, {
153
- cwd: projectRoot,
154
- nodir: true,
155
- });
156
- counts[category] = {
157
- count: files.length,
158
- description: config.description,
159
- files: files.slice(0, 10), // Sample of first 10 files
160
- };
161
- } catch (error) {
162
- counts[category] = {
163
- count: 0,
164
- description: config.description,
165
- error: error.message,
166
- };
167
- }
168
- }
169
-
170
- return counts;
171
- }
172
-
173
- /**
174
- * Gets file statistics
175
- * @param {string} filePath - Path to the file
176
- * @returns {Promise<Object>} File statistics
177
- */
178
- async function getFileStats(filePath) {
179
- try {
180
- const stats = await fs.stat(filePath);
181
- return {
182
- size: stats.size,
183
- created: stats.birthtime.toISOString(),
184
- modified: stats.mtime.toISOString(),
185
- };
186
- } catch (error) {
187
- return { error: error.message };
188
- }
189
- }
190
-
191
- /**
192
- * Main ManifestGenerator class
193
- */
194
- class ManifestGenerator {
195
- /**
196
- * Creates a new ManifestGenerator instance
197
- * @param {Object} options - Generator options
198
- * @param {string} options.projectRoot - Project root directory
199
- * @param {string} options.outputPath - Path for manifest output
200
- * @param {number} options.maxDepth - Maximum tree depth
201
- */
202
- constructor(options = {}) {
203
- this.projectRoot = options.projectRoot || process.cwd();
204
- this.outputPath = options.outputPath || path.join(
205
- this.projectRoot,
206
- 'docs',
207
- 'architecture',
208
- 'source-tree-manifest.json',
209
- );
210
- this.maxDepth = options.maxDepth || 10;
211
- }
212
-
213
- /**
214
- * Generates the complete manifest
215
- * @returns {Promise<Object>} Generated manifest
216
- */
217
- async generate() {
218
- const startTime = Date.now();
219
-
220
- const manifest = {
221
- version: '1.0.0',
222
- generated: new Date().toISOString(),
223
- generator: 'source-tree-guardian',
224
- story: '6.8',
225
- projectRoot: this.projectRoot,
226
- summary: {
227
- totalFiles: 0,
228
- totalDirectories: 0,
229
- categories: {},
230
- },
231
- tree: null,
232
- categories: {},
233
- duration: 0,
234
- };
235
-
236
- // Generate tree structure
237
- manifest.tree = await generateTree(this.projectRoot, this.projectRoot, 0, this.maxDepth);
238
-
239
- // Count total files and directories
240
- const countItems = (node) => {
241
- if (node.type === 'directory') {
242
- manifest.summary.totalDirectories++;
243
- if (node.children) {
244
- node.children.forEach(countItems);
245
- }
246
- } else if (node.type === 'file') {
247
- manifest.summary.totalFiles++;
248
- }
249
- };
250
- countItems(manifest.tree);
251
-
252
- // Count by category
253
- manifest.categories = await countFilesByCategory(this.projectRoot);
254
- manifest.summary.categories = Object.fromEntries(
255
- Object.entries(manifest.categories).map(([k, v]) => [k, v.count]),
256
- );
257
-
258
- manifest.duration = Date.now() - startTime;
259
-
260
- return manifest;
261
- }
262
-
263
- /**
264
- * Saves the manifest to a file
265
- * @param {Object} manifest - The manifest to save
266
- * @returns {Promise<string>} Path to saved manifest
267
- */
268
- async save(manifest) {
269
- const dir = path.dirname(this.outputPath);
270
- await fs.mkdir(dir, { recursive: true });
271
- await fs.writeFile(this.outputPath, JSON.stringify(manifest, null, 2));
272
- return this.outputPath;
273
- }
274
-
275
- /**
276
- * Loads an existing manifest
277
- * @param {string} manifestPath - Path to the manifest file
278
- * @returns {Promise<Object>} Loaded manifest
279
- */
280
- async load(manifestPath) {
281
- const content = await fs.readFile(manifestPath || this.outputPath, 'utf8');
282
- return JSON.parse(content);
283
- }
284
-
285
- /**
286
- * Compares two manifests and returns differences
287
- * @param {Object} oldManifest - Previous manifest
288
- * @param {Object} newManifest - Current manifest
289
- * @returns {Object} Comparison results
290
- */
291
- compare(oldManifest, newManifest) {
292
- const diff = {
293
- added: [],
294
- removed: [],
295
- modified: [],
296
- summary: {
297
- filesAdded: 0,
298
- filesRemoved: 0,
299
- categoriesChanged: {},
300
- },
301
- };
302
-
303
- // Extract all file paths from tree
304
- const extractPaths = (node, paths = new Set()) => {
305
- if (node.type === 'file') {
306
- paths.add(node.path);
307
- } else if (node.children) {
308
- node.children.forEach((child) => extractPaths(child, paths));
309
- }
310
- return paths;
311
- };
312
-
313
- const oldPaths = extractPaths(oldManifest.tree);
314
- const newPaths = extractPaths(newManifest.tree);
315
-
316
- // Find added files
317
- for (const p of newPaths) {
318
- if (!oldPaths.has(p)) {
319
- diff.added.push(p);
320
- diff.summary.filesAdded++;
321
- }
322
- }
323
-
324
- // Find removed files
325
- for (const p of oldPaths) {
326
- if (!newPaths.has(p)) {
327
- diff.removed.push(p);
328
- diff.summary.filesRemoved++;
329
- }
330
- }
331
-
332
- // Compare categories
333
- for (const [category, oldData] of Object.entries(oldManifest.categories)) {
334
- const newData = newManifest.categories[category];
335
- if (newData && newData.count !== oldData.count) {
336
- diff.summary.categoriesChanged[category] = {
337
- old: oldData.count,
338
- new: newData.count,
339
- delta: newData.count - oldData.count,
340
- };
341
- }
342
- }
343
-
344
- return diff;
345
- }
346
-
347
- /**
348
- * Formats a diff report for console output
349
- * @param {Object} diff - Comparison diff
350
- * @returns {string} Formatted report
351
- */
352
- formatDiffReport(diff) {
353
- const lines = [];
354
-
355
- lines.push('╔═══════════════════════════════════════════════════════════════════════╗');
356
- lines.push('║ SOURCE-TREE MANIFEST COMPARISON ║');
357
- lines.push('╠═══════════════════════════════════════════════════════════════════════╣');
358
- lines.push(`║ Files Added: ${String(diff.summary.filesAdded).padEnd(58)}║`);
359
- lines.push(`║ Files Removed: ${String(diff.summary.filesRemoved).padEnd(56)}║`);
360
- lines.push('║ ║');
361
-
362
- if (diff.added.length > 0) {
363
- lines.push('╠═══════════════════════════════════════════════════════════════════════╣');
364
- lines.push('║ ADDED FILES ║');
365
- lines.push('╠═══════════════════════════════════════════════════════════════════════╣');
366
- for (const file of diff.added.slice(0, 20)) {
367
- lines.push(`║ + ${file.substring(0, 69).padEnd(69)}║`);
368
- }
369
- if (diff.added.length > 20) {
370
- lines.push(`║ ... and ${diff.added.length - 20} more files ║`);
371
- }
372
- }
373
-
374
- if (diff.removed.length > 0) {
375
- lines.push('╠═══════════════════════════════════════════════════════════════════════╣');
376
- lines.push('║ REMOVED FILES ║');
377
- lines.push('╠═══════════════════════════════════════════════════════════════════════╣');
378
- for (const file of diff.removed.slice(0, 20)) {
379
- lines.push(`║ - ${file.substring(0, 69).padEnd(69)}║`);
380
- }
381
- if (diff.removed.length > 20) {
382
- lines.push(`║ ... and ${diff.removed.length - 20} more files ║`);
383
- }
384
- }
385
-
386
- if (Object.keys(diff.summary.categoriesChanged).length > 0) {
387
- lines.push('╠═══════════════════════════════════════════════════════════════════════╣');
388
- lines.push('║ CATEGORY CHANGES ║');
389
- lines.push('╠═══════════════════════════════════════════════════════════════════════╣');
390
- for (const [category, change] of Object.entries(diff.summary.categoriesChanged)) {
391
- const delta = change.delta > 0 ? `+${change.delta}` : String(change.delta);
392
- lines.push(`║ ${category}: ${change.old} → ${change.new} (${delta})`.padEnd(72) + '║');
393
- }
394
- }
395
-
396
- lines.push('╚═══════════════════════════════════════════════════════════════════════╝');
397
-
398
- return lines.join('\n');
399
- }
400
- }
401
-
402
- // Export for use as module
403
- module.exports = {
404
- ManifestGenerator,
405
- generateTree,
406
- countFilesByCategory,
407
- getFileStats,
408
- FILE_CATEGORIES,
409
- DEFAULT_EXCLUSIONS,
410
- };
@@ -1,285 +0,0 @@
1
- # Naming Convention Rules for AIOS Source Tree
2
- # Version: 1.0.0
3
- # Last Updated: 2025-12-14
4
- # Story: 6.8 - Source-Tree Guardian
5
-
6
- version: "1.0"
7
- last_updated: "2025-12-14"
8
-
9
- # =============================================================================
10
- # NAMING CONVENTIONS
11
- # Defines how files and directories should be named
12
- # =============================================================================
13
-
14
- conventions:
15
- # ---------------------------------------------------------------------------
16
- # KEBAB-CASE (default for most files)
17
- # ---------------------------------------------------------------------------
18
- kebab-case:
19
- pattern: "^[a-z][a-z0-9]*(-[a-z0-9]+)*$"
20
- description: "Lowercase letters separated by hyphens"
21
- examples:
22
- valid:
23
- - "agent-executor"
24
- - "task-runner"
25
- - "greeting-builder"
26
- - "source-tree-guardian"
27
- invalid:
28
- - "AgentExecutor"
29
- - "task_runner"
30
- - "greetingBuilder"
31
- - "SOURCE-TREE"
32
-
33
- # ---------------------------------------------------------------------------
34
- # CAMEL-CASE (for variables/functions in code)
35
- # ---------------------------------------------------------------------------
36
- camelCase:
37
- pattern: "^[a-z][a-zA-Z0-9]*$"
38
- description: "First letter lowercase, subsequent words capitalized"
39
- examples:
40
- valid:
41
- - "agentExecutor"
42
- - "taskRunner"
43
- - "greetingBuilder"
44
- invalid:
45
- - "AgentExecutor"
46
- - "agent-executor"
47
- - "agent_executor"
48
-
49
- # ---------------------------------------------------------------------------
50
- # PASCAL-CASE (for classes)
51
- # ---------------------------------------------------------------------------
52
- PascalCase:
53
- pattern: "^[A-Z][a-zA-Z0-9]*$"
54
- description: "Each word starts with uppercase"
55
- examples:
56
- valid:
57
- - "AgentExecutor"
58
- - "TaskRunner"
59
- - "GreetingBuilder"
60
- invalid:
61
- - "agentExecutor"
62
- - "agent-executor"
63
- - "AGENT_EXECUTOR"
64
-
65
- # ---------------------------------------------------------------------------
66
- # SCREAMING-SNAKE-CASE (for constants)
67
- # ---------------------------------------------------------------------------
68
- SCREAMING_SNAKE_CASE:
69
- pattern: "^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$"
70
- description: "Uppercase letters separated by underscores"
71
- examples:
72
- valid:
73
- - "MAX_RETRIES"
74
- - "DEFAULT_TIMEOUT"
75
- - "API_BASE_URL"
76
- invalid:
77
- - "maxRetries"
78
- - "default-timeout"
79
- - "ApiBaseUrl"
80
-
81
- # =============================================================================
82
- # FILE TYPE RULES
83
- # Maps file types to their required naming conventions
84
- # =============================================================================
85
-
86
- file_rules:
87
- # JavaScript files
88
- - extension: ".js"
89
- convention: kebab-case
90
- exceptions:
91
- - pattern: "*.config.js"
92
- allowed: true
93
- - pattern: "*.test.js"
94
- allowed: true
95
- - pattern: "index.js"
96
- allowed: true
97
-
98
- # TypeScript files
99
- - extension: ".ts"
100
- convention: kebab-case
101
- exceptions:
102
- - pattern: "*.config.ts"
103
- allowed: true
104
- - pattern: "*.test.ts"
105
- allowed: true
106
- - pattern: "*.d.ts"
107
- allowed: true
108
- - pattern: "index.ts"
109
- allowed: true
110
-
111
- # Markdown files
112
- - extension: ".md"
113
- convention: kebab-case
114
- exceptions:
115
- - pattern: "README.md"
116
- allowed: true
117
- - pattern: "CHANGELOG.md"
118
- allowed: true
119
- - pattern: "CLAUDE.md"
120
- allowed: true
121
- - pattern: "LICENSE.md"
122
- allowed: true
123
- - pattern: "CONTRIBUTING.md"
124
- allowed: true
125
- - pattern: "STORY-BACKLOG.md"
126
- allowed: true
127
-
128
- # YAML files
129
- - extension: ".yaml"
130
- convention: kebab-case
131
- exceptions:
132
- - pattern: "*.config.yaml"
133
- allowed: true
134
-
135
- - extension: ".yml"
136
- convention: kebab-case
137
-
138
- # JSON files
139
- - extension: ".json"
140
- convention: kebab-case
141
- exceptions:
142
- - pattern: "package.json"
143
- allowed: true
144
- - pattern: "package-lock.json"
145
- allowed: true
146
- - pattern: "tsconfig.json"
147
- allowed: true
148
- - pattern: ".eslintrc.json"
149
- allowed: true
150
-
151
- # =============================================================================
152
- # DIRECTORY RULES
153
- # Naming conventions for directories
154
- # =============================================================================
155
-
156
- directory_rules:
157
- - convention: kebab-case
158
- exceptions:
159
- - pattern: ".aios-core"
160
- allowed: true
161
- reason: "Framework standard directory"
162
- - pattern: ".claude"
163
- allowed: true
164
- reason: "IDE configuration directory"
165
- - pattern: ".cursor"
166
- allowed: true
167
- reason: "IDE configuration directory"
168
- - pattern: ".vscode"
169
- allowed: true
170
- reason: "IDE configuration directory"
171
- - pattern: ".husky"
172
- allowed: true
173
- reason: "Git hooks directory"
174
- - pattern: ".git"
175
- allowed: true
176
- reason: "Git repository directory"
177
- - pattern: ".ai"
178
- allowed: true
179
- reason: "AI artifacts directory"
180
- - pattern: "node_modules"
181
- allowed: true
182
- reason: "npm packages directory"
183
-
184
- # =============================================================================
185
- # SPECIAL PATTERNS
186
- # Files that follow specific naming patterns
187
- # =============================================================================
188
-
189
- special_patterns:
190
- # Story files
191
- - name: story
192
- pattern: "^story-[0-9]+\\.[0-9]+(\\.[0-9]+)*(-[a-z-]+)?\\.md$"
193
- description: "Story files follow story-{id}.md or story-{id}-{slug}.md pattern"
194
- examples:
195
- valid:
196
- - "story-6.8.md"
197
- - "story-6.8-source-tree-guardian.md"
198
- - "story-6.1.2.5.md"
199
- invalid:
200
- - "Story-6.8.md"
201
- - "story_6.8.md"
202
- - "6.8-story.md"
203
-
204
- # Epic files
205
- - name: epic
206
- pattern: "^epic-[0-9]+(\\.[0-9]+)*-[a-z-]+\\.md$"
207
- description: "Epic files follow epic-{number}-{name}.md pattern"
208
- examples:
209
- valid:
210
- - "epic-6.1-agent-identity-system.md"
211
- - "epic-7-deployment-automation.md"
212
- invalid:
213
- - "Epic-6.1.md"
214
- - "epic_6.1.md"
215
-
216
- # Decision files (ADRs)
217
- - name: decision
218
- pattern: "^decision-[0-9]+-[a-z-]+(-FINAL)?\\.md$"
219
- description: "Decision files follow decision-{number}-{name}.md pattern"
220
- examples:
221
- valid:
222
- - "decision-005-repository-restructuring.md"
223
- - "decision-005-repository-restructuring-FINAL.md"
224
- invalid:
225
- - "Decision-005.md"
226
- - "decision_005.md"
227
-
228
- # Template files
229
- - name: template
230
- pattern: "^[a-z-]+-tmpl\\.(yaml|md)$"
231
- description: "Template files follow {name}-tmpl.{ext} pattern"
232
- examples:
233
- valid:
234
- - "story-tmpl.yaml"
235
- - "prd-tmpl.yaml"
236
- - "epic-tmpl.md"
237
- invalid:
238
- - "story-template.yaml"
239
- - "Story-tmpl.yaml"
240
-
241
- # Checklist files
242
- - name: checklist
243
- pattern: "^[a-z-]+-checklist\\.md$"
244
- description: "Checklist files follow {name}-checklist.md pattern"
245
- examples:
246
- valid:
247
- - "po-master-checklist.md"
248
- - "story-draft-checklist.md"
249
- invalid:
250
- - "po-master.checklist.md"
251
- - "POChecklist.md"
252
-
253
- # Test files
254
- - name: test
255
- pattern: "^[a-z-]+\\.test\\.(js|ts)$"
256
- description: "Test files follow {name}.test.{ext} pattern"
257
- examples:
258
- valid:
259
- - "validator.test.js"
260
- - "manifest-generator.test.js"
261
- invalid:
262
- - "ValidatorTest.js"
263
- - "validator_test.js"
264
-
265
- # =============================================================================
266
- # VALIDATION SETTINGS
267
- # =============================================================================
268
-
269
- validation:
270
- strict_mode: false # If true, all files must match a rule
271
- case_sensitive: true # Enforce exact case matching
272
- allow_numbers: true # Allow numbers in names (after first character)
273
- max_length: 100 # Maximum filename length (excluding extension)
274
- min_length: 2 # Minimum filename length (excluding extension)
275
-
276
- # =============================================================================
277
- # SEVERITY LEVELS
278
- # =============================================================================
279
-
280
- severity:
281
- wrong_convention: warning
282
- invalid_characters: error
283
- too_long: warning
284
- too_short: error
285
- special_pattern_mismatch: error