aios-core 4.2.13 → 4.2.15

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 (95) hide show
  1. package/.aios-core/core/code-intel/helpers/dev-helper.js +206 -0
  2. package/.aios-core/core/registry/registry-schema.json +166 -166
  3. package/.aios-core/core/synapse/diagnostics/collectors/hook-collector.js +3 -3
  4. package/.aios-core/data/entity-registry.yaml +27 -0
  5. package/.aios-core/development/scripts/approval-workflow.js +642 -642
  6. package/.aios-core/development/scripts/backup-manager.js +606 -606
  7. package/.aios-core/development/scripts/branch-manager.js +389 -389
  8. package/.aios-core/development/scripts/code-quality-improver.js +1311 -1311
  9. package/.aios-core/development/scripts/commit-message-generator.js +849 -849
  10. package/.aios-core/development/scripts/conflict-resolver.js +674 -674
  11. package/.aios-core/development/scripts/dependency-analyzer.js +637 -637
  12. package/.aios-core/development/scripts/diff-generator.js +351 -351
  13. package/.aios-core/development/scripts/elicitation-engine.js +384 -384
  14. package/.aios-core/development/scripts/elicitation-session-manager.js +299 -299
  15. package/.aios-core/development/scripts/git-wrapper.js +461 -461
  16. package/.aios-core/development/scripts/manifest-preview.js +244 -244
  17. package/.aios-core/development/scripts/metrics-tracker.js +775 -775
  18. package/.aios-core/development/scripts/modification-validator.js +554 -554
  19. package/.aios-core/development/scripts/pattern-learner.js +1224 -1224
  20. package/.aios-core/development/scripts/performance-analyzer.js +757 -757
  21. package/.aios-core/development/scripts/refactoring-suggester.js +1138 -1138
  22. package/.aios-core/development/scripts/rollback-handler.js +530 -530
  23. package/.aios-core/development/scripts/security-checker.js +358 -358
  24. package/.aios-core/development/scripts/template-engine.js +239 -239
  25. package/.aios-core/development/scripts/template-validator.js +278 -278
  26. package/.aios-core/development/scripts/test-generator.js +843 -843
  27. package/.aios-core/development/scripts/transaction-manager.js +589 -589
  28. package/.aios-core/development/scripts/usage-tracker.js +673 -673
  29. package/.aios-core/development/scripts/validate-filenames.js +226 -226
  30. package/.aios-core/development/scripts/version-tracker.js +526 -526
  31. package/.aios-core/development/scripts/yaml-validator.js +396 -396
  32. package/.aios-core/development/tasks/build-autonomous.md +10 -4
  33. package/.aios-core/development/tasks/create-service.md +23 -0
  34. package/.aios-core/development/tasks/dev-develop-story.md +12 -6
  35. package/.aios-core/development/tasks/dev-suggest-refactoring.md +7 -1
  36. package/.aios-core/development/tasks/publish-npm.md +3 -3
  37. package/.aios-core/hooks/unified/README.md +1 -1
  38. package/.aios-core/install-manifest.yaml +65 -61
  39. package/.aios-core/manifests/schema/manifest-schema.json +190 -190
  40. package/.aios-core/product/templates/component-react-tmpl.tsx +98 -98
  41. package/.aios-core/product/templates/engine/schemas/adr.schema.json +102 -102
  42. package/.aios-core/product/templates/engine/schemas/dbdr.schema.json +205 -205
  43. package/.aios-core/product/templates/engine/schemas/epic.schema.json +175 -175
  44. package/.aios-core/product/templates/engine/schemas/pmdr.schema.json +175 -175
  45. package/.aios-core/product/templates/engine/schemas/prd-v2.schema.json +300 -300
  46. package/.aios-core/product/templates/engine/schemas/prd.schema.json +152 -152
  47. package/.aios-core/product/templates/engine/schemas/story.schema.json +222 -222
  48. package/.aios-core/product/templates/engine/schemas/task.schema.json +154 -154
  49. package/.aios-core/product/templates/eslintrc-security.json +32 -32
  50. package/.aios-core/product/templates/github-actions-cd.yml +212 -212
  51. package/.aios-core/product/templates/github-actions-ci.yml +172 -172
  52. package/.aios-core/product/templates/shock-report-tmpl.html +502 -502
  53. package/.aios-core/product/templates/token-exports-css-tmpl.css +240 -240
  54. package/.aios-core/quality/schemas/quality-metrics.schema.json +233 -233
  55. package/.aios-core/scripts/migrate-framework-docs.sh +300 -300
  56. package/README.en.md +747 -0
  57. package/README.md +4 -2
  58. package/bin/aios.js +7 -4
  59. package/package.json +1 -1
  60. package/packages/aios-pro-cli/src/recover.js +1 -1
  61. package/packages/installer/src/wizard/ide-config-generator.js +6 -6
  62. package/packages/installer/src/wizard/pro-setup.js +3 -3
  63. package/pro/license/degradation.js +220 -220
  64. package/pro/license/errors.js +450 -450
  65. package/pro/license/feature-gate.js +354 -354
  66. package/pro/license/index.js +181 -181
  67. package/pro/license/license-cache.js +523 -523
  68. package/pro/license/license-crypto.js +303 -303
  69. package/scripts/package-synapse.js +5 -5
  70. package/scripts/validate-package-completeness.js +3 -3
  71. package/.aios-core/.session/current-session.json +0 -14
  72. package/.aios-core/data/registry-update-log.jsonl +0 -191
  73. package/.aios-core/docs/SHARD-TRANSLATION-GUIDE.md +0 -335
  74. package/.aios-core/docs/component-creation-guide.md +0 -458
  75. package/.aios-core/docs/session-update-pattern.md +0 -307
  76. package/.aios-core/docs/standards/AIOS-FRAMEWORK-MASTER.md +0 -1963
  77. package/.aios-core/docs/standards/AIOS-LIVRO-DE-OURO-V2.1-SUMMARY.md +0 -1190
  78. package/.aios-core/docs/standards/AIOS-LIVRO-DE-OURO-V2.1.md +0 -439
  79. package/.aios-core/docs/standards/AIOS-LIVRO-DE-OURO.md +0 -5398
  80. package/.aios-core/docs/standards/V3-ARCHITECTURAL-DECISIONS.md +0 -523
  81. package/.aios-core/docs/template-syntax.md +0 -267
  82. package/.aios-core/docs/troubleshooting-guide.md +0 -625
  83. package/.aios-core/infrastructure/tests/utilities-audit-results.json +0 -501
  84. package/.aios-core/manifests/agents.csv +0 -29
  85. package/.aios-core/manifests/tasks.csv +0 -198
  86. package/.aios-core/manifests/workers.csv +0 -204
  87. package/.claude/rules/agent-authority.md +0 -105
  88. package/.claude/rules/coderabbit-integration.md +0 -93
  89. package/.claude/rules/ids-principles.md +0 -112
  90. package/.claude/rules/story-lifecycle.md +0 -139
  91. package/.claude/rules/workflow-execution.md +0 -150
  92. package/scripts/glue/README.md +0 -355
  93. package/scripts/glue/compose-agent-prompt.cjs +0 -362
  94. /package/.claude/hooks/{precompact-session-digest.js → precompact-session-digest.cjs} +0 -0
  95. /package/.claude/hooks/{synapse-engine.js → synapse-engine.cjs} +0 -0
@@ -1,674 +1,674 @@
1
- const fs = require('fs').promises;
2
- const path = require('path');
3
- const chalk = require('chalk');
4
-
5
- /**
6
- * Usage tracker for AIOS-FULLSTACK framework components
7
- * Tracks component usage patterns for deprecation warnings and impact analysis
8
- */
9
- class UsageTracker {
10
- constructor(options = {}) {
11
- this.rootPath = options.rootPath || process.cwd();
12
- this.usageDir = path.join(this.rootPath, '.aios', 'usage');
13
- this.usageCache = new Map();
14
- this.scanPatterns = this.initializeScanPatterns();
15
- }
16
-
17
- /**
18
- * Initialize usage tracker
19
- */
20
- async initialize() {
21
- try {
22
- // Create usage directory
23
- await fs.mkdir(this.usageDir, { recursive: true });
24
-
25
- console.log(chalk.green('✅ Usage tracker initialized'));
26
- return true;
27
-
28
- } catch (_error) {
29
- console.error(chalk.red(`Failed to initialize usage tracker: ${error.message}`));
30
- throw error;
31
- }
32
- }
33
-
34
- /**
35
- * Analyze component usage across the codebase
36
- */
37
- async analyzeComponentUsage(componentId, options = {}) {
38
- const analysis = {
39
- component_id: componentId,
40
- analysis_timestamp: new Date().toISOString(),
41
- total_references: 0,
42
- usage_locations: [],
43
- dependent_components: [],
44
- external_references: [],
45
- usage_patterns: {},
46
- risk_assessment: {
47
- impact_level: 'low',
48
- affected_areas: [],
49
- migration_complexity: 'simple'
50
- }
51
- };
52
-
53
- try {
54
- console.log(chalk.blue(`🔍 Analyzing usage for component: ${componentId}`));
55
-
56
- // Get component information
57
- const component = await this.getComponentInfo(componentId);
58
- if (!component) {
59
- throw new Error(`Component not found: ${componentId}`);
60
- }
61
-
62
- // Scan for direct references
63
- const directReferences = await this.scanForDirectReferences(component, options);
64
- analysis.usage_locations = directReferences;
65
- analysis.total_references = directReferences.length;
66
-
67
- // Analyze dependency relationships
68
- const dependencies = await this.analyzeDependencyRelationships(component, options);
69
- analysis.dependent_components = dependencies;
70
-
71
- // Check for external references (imports, configurations, etc.)
72
- const externalRefs = await this.scanForExternalReferences(component, options);
73
- analysis.external_references = externalRefs;
74
-
75
- // Analyze usage patterns
76
- analysis.usage_patterns = await this.analyzeUsagePatterns(component, directReferences);
77
-
78
- // Assess migration risk
79
- analysis.risk_assessment = this.assessMigrationRisk(analysis);
80
-
81
- // Cache results
82
- this.usageCache.set(componentId, analysis);
83
-
84
- // Save detailed analysis
85
- await this.saveUsageAnalysis(analysis);
86
-
87
- console.log(chalk.green(`✅ Usage analysis completed for ${componentId}`));
88
- console.log(chalk.gray(` Total references: ${analysis.total_references}`));
89
- console.log(chalk.gray(` Dependent components: ${analysis.dependent_components.length}`));
90
- console.log(chalk.gray(` Impact level: ${analysis.risk_assessment.impact_level}`));
91
-
92
- return analysis;
93
-
94
- } catch (_error) {
95
- console.error(chalk.red(`Usage analysis failed for ${componentId}: ${error.message}`));
96
- throw error;
97
- }
98
- }
99
-
100
- /**
101
- * Track usage changes over time for deprecated components
102
- */
103
- async trackUsageChanges(componentId, baselineAnalysis) {
104
- const currentAnalysis = await this.analyzeComponentUsage(componentId);
105
-
106
- const changes = {
107
- component_id: componentId,
108
- comparison_timestamp: new Date().toISOString(),
109
- baseline_timestamp: baselineAnalysis.analysis_timestamp,
110
- changes: {
111
- total_references: {
112
- before: baselineAnalysis.total_references,
113
- after: currentAnalysis.total_references,
114
- change: currentAnalysis.total_references - baselineAnalysis.total_references
115
- },
116
- dependent_components: {
117
- before: baselineAnalysis.dependent_components.length,
118
- after: currentAnalysis.dependent_components.length,
119
- change: currentAnalysis.dependent_components.length - baselineAnalysis.dependent_components.length
120
- },
121
- new_usages: this.findNewUsages(baselineAnalysis.usage_locations, currentAnalysis.usage_locations),
122
- removed_usages: this.findRemovedUsages(baselineAnalysis.usage_locations, currentAnalysis.usage_locations)
123
- },
124
- trend: this.calculateUsageTrend(baselineAnalysis, currentAnalysis),
125
- migration_progress: this.calculateMigrationProgress(baselineAnalysis, currentAnalysis)
126
- };
127
-
128
- // Save change tracking
129
- await this.saveUsageChanges(changes);
130
-
131
- return changes;
132
- }
133
-
134
- /**
135
- * Generate usage warnings for deprecated components
136
- */
137
- async generateUsageWarnings(componentId, deprecationInfo) {
138
- const analysis = await this.analyzeComponentUsage(componentId);
139
- const warnings = [];
140
-
141
- for (const _usage of analysis.usage_locations) {
142
- const warning = {
143
- type: 'deprecation_warning',
144
- component_id: componentId,
145
- usage_location: {
146
- file: usage.file,
147
- line: usage.line,
148
- context: usage.context
149
- },
150
- message: this.generateWarningMessage(componentId, deprecationInfo, usage),
151
- severity: this.calculateWarningSeverity(deprecationInfo, usage),
152
- suggested_actions: this.generateSuggestedActions(componentId, deprecationInfo, usage)
153
- };
154
-
155
- warnings.push(warning);
156
- }
157
-
158
- // Save warnings for later processing
159
- await this.saveUsageWarnings(componentId, warnings);
160
-
161
- return warnings;
162
- }
163
-
164
- /**
165
- * Get usage statistics for reporting
166
- */
167
- async getUsageStatistics(componentIds = null) {
168
- const stats = {
169
- generated_at: new Date().toISOString(),
170
- total_components_analyzed: 0,
171
- high_usage_components: [],
172
- zero_usage_components: [],
173
- usage_distribution: {},
174
- dependency_graph: {}
175
- };
176
-
177
- const componentsToAnalyze = componentIds || await this.getAllTrackedComponents();
178
-
179
- for (const componentId of componentsToAnalyze) {
180
- try {
181
- const analysis = await this.getOrAnalyzeUsage(componentId);
182
- stats.total_components_analyzed++;
183
-
184
- // Categorize by usage level
185
- if (analysis.total_references === 0) {
186
- stats.zero_usage_components.push(componentId);
187
- } else if (analysis.total_references >= 10) {
188
- stats.high_usage_components.push({
189
- component_id: componentId,
190
- reference_count: analysis.total_references,
191
- impact_level: analysis.risk_assessment.impact_level
192
- });
193
- }
194
-
195
- // Add to usage distribution
196
- const usageRange = this.categorizeUsageLevel(analysis.total_references);
197
- stats.usage_distribution[usageRange] = (stats.usage_distribution[usageRange] || 0) + 1;
198
-
199
- // Add to dependency graph
200
- stats.dependency_graph[componentId] = analysis.dependent_components.map(dep => dep.component_id);
201
-
202
- } catch (_error) {
203
- console.warn(chalk.yellow(`Failed to analyze usage for ${componentId}: ${error.message}`));
204
- }
205
- }
206
-
207
- return stats;
208
- }
209
-
210
- /**
211
- * Scan for direct references to a component
212
- */
213
- async scanForDirectReferences(component, options = {}) {
214
- const references = [];
215
- const scanPaths = await this.getScanPaths(_options);
216
-
217
- for (const scanPath of scanPaths) {
218
- try {
219
- const pathReferences = await this.scanPath(scanPath, component);
220
- references.push(...pathReferences);
221
- } catch (_error) {
222
- console.warn(chalk.yellow(`Failed to scan path ${scanPath}: ${error.message}`));
223
- }
224
- }
225
-
226
- return references;
227
- }
228
-
229
- /**
230
- * Scan a specific path for component references
231
- */
232
- async scanPath(scanPath, component) {
233
- const references = [];
234
- const files = await this.getFilesToScan(scanPath);
235
-
236
- for (const file of files) {
237
- try {
238
- const fileReferences = await this.scanFile(file, component);
239
- references.push(...fileReferences);
240
- } catch (_error) {
241
- // Skip files that can't be read
242
- continue;
243
- }
244
- }
245
-
246
- return references;
247
- }
248
-
249
- /**
250
- * Scan a single file for component references
251
- */
252
- async scanFile(filePath, component) {
253
- const references = [];
254
-
255
- try {
256
- const content = await fs.readFile(filePath, 'utf-8');
257
- const lines = content.split('\n');
258
-
259
- for (let i = 0; i < lines.length; i++) {
260
- const line = lines[i];
261
- const lineNumber = i + 1;
262
-
263
- // Check for various reference patterns
264
- const matches = this.findReferencesInLine(line, component);
265
-
266
- for (const match of matches) {
267
- references.push({
268
- file: filePath,
269
- line: lineNumber,
270
- column: match.column,
271
- context: line.trim(),
272
- reference_type: match.type,
273
- match_text: match.text
274
- });
275
- }
276
- }
277
- } catch (_error) {
278
- // File couldn't be read, skip
279
- }
280
-
281
- return references;
282
- }
283
-
284
- /**
285
- * Find references in a single line of code
286
- */
287
- findReferencesInLine(line, component) {
288
- const matches = [];
289
- const patterns = this.scanPatterns[component.type] || this.scanPatterns.default;
290
-
291
- for (const pattern of patterns) {
292
- const regex = new RegExp(pattern.pattern.replace('{component_name}', component.name), pattern.flags || 'gi');
293
- let match;
294
-
295
- while ((match = regex.exec(line)) !== null) {
296
- matches.push({
297
- type: pattern.type,
298
- text: match[0],
299
- column: match.index,
300
- confidence: pattern.confidence || 0.8
301
- });
302
- }
303
- }
304
-
305
- return matches;
306
- }
307
-
308
- /**
309
- * Analyze dependency relationships
310
- */
311
- async analyzeDependencyRelationships(component, options = {}) {
312
- const dependencies = [];
313
-
314
- // This would analyze manifest files, import statements, etc.
315
- // For now, return empty array as placeholder
316
-
317
- return dependencies;
318
- }
319
-
320
- /**
321
- * Scan for external references (config files, documentation, etc.)
322
- */
323
- async scanForExternalReferences(component, options = {}) {
324
- const externalRefs = [];
325
-
326
- // Check configuration files
327
- const configRefs = await this.scanConfigurationFiles(component);
328
- externalRefs.push(...configRefs);
329
-
330
- // Check documentation
331
- const docRefs = await this.scanDocumentationFiles(component);
332
- externalRefs.push(...docRefs);
333
-
334
- return externalRefs;
335
- }
336
-
337
- /**
338
- * Analyze usage patterns
339
- */
340
- async analyzeUsagePatterns(component, references) {
341
- const patterns = {
342
- by_file_type: {},
343
- by_usage_type: {},
344
- temporal_distribution: {},
345
- complexity_indicators: {}
346
- };
347
-
348
- for (const ref of references) {
349
- // Group by file extension
350
- const ext = path.extname(ref.file);
351
- patterns.by_file_type[ext] = (patterns.by_file_type[ext] || 0) + 1;
352
-
353
- // Group by reference type
354
- patterns.by_usage_type[ref.reference_type] = (patterns.by_usage_type[ref.reference_type] || 0) + 1;
355
- }
356
-
357
- return patterns;
358
- }
359
-
360
- /**
361
- * Assess migration risk based on usage analysis
362
- */
363
- assessMigrationRisk(analysis) {
364
- let impactLevel = 'low';
365
- let migrationComplexity = 'simple';
366
- const affectedAreas = [];
367
-
368
- // Assess based on total references
369
- if (analysis.total_references > 20) {
370
- impactLevel = 'high';
371
- migrationComplexity = 'complex';
372
- } else if (analysis.total_references > 10) {
373
- impactLevel = 'medium';
374
- migrationComplexity = 'moderate';
375
- }
376
-
377
- // Check for complex usage patterns
378
- if (analysis.dependent_components.length > 5) {
379
- migrationComplexity = 'complex';
380
- affectedAreas.push('component_dependencies');
381
- }
382
-
383
- if (analysis.external_references.length > 0) {
384
- affectedAreas.push('external_configuration');
385
- }
386
-
387
- return {
388
- impact_level: impactLevel,
389
- affected_areas: affectedAreas,
390
- migration_complexity: migrationComplexity
391
- };
392
- }
393
-
394
- // Helper methods
395
-
396
- async getComponentInfo(componentId) {
397
- // This would typically integrate with the component registry
398
- // For now, return a basic component structure
399
- const [type, name] = componentId.split('/');
400
-
401
- return {
402
- id: componentId,
403
- type: type,
404
- name: name,
405
- file_path: `aios-core/${type}s/${name}.md`
406
- };
407
- }
408
-
409
- async getScanPaths(_options) {
410
- const defaultPaths = [
411
- path.join(this.rootPath, 'aios-core'),
412
- path.join(this.rootPath, 'src'),
413
- path.join(this.rootPath, 'lib')
414
- ];
415
-
416
- if (options.scanPaths) {
417
- return options.scanPaths;
418
- }
419
-
420
- // Filter paths that exist
421
- const existingPaths = [];
422
- for (const scanPath of defaultPaths) {
423
- try {
424
- await fs.access(scanPath);
425
- existingPaths.push(scanPath);
426
- } catch (_error) {
427
- // Path doesn't exist, skip
428
- }
429
- }
430
-
431
- return existingPaths;
432
- }
433
-
434
- async getFilesToScan(scanPath) {
435
- const files = [];
436
-
437
- try {
438
- const entries = await fs.readdir(scanPath, { withFileTypes: true });
439
-
440
- for (const entry of entries) {
441
- const fullPath = path.join(scanPath, entry.name);
442
-
443
- if (entry.isDirectory()) {
444
- // Recursively scan subdirectories
445
- const subFiles = await this.getFilesToScan(fullPath);
446
- files.push(...subFiles);
447
- } else if (this.shouldScanFile(entry.name)) {
448
- files.push(fullPath);
449
- }
450
- }
451
- } catch (_error) {
452
- // Can't read directory, skip
453
- }
454
-
455
- return files;
456
- }
457
-
458
- shouldScanFile(filename) {
459
- const scanExtensions = ['.js', '.ts', '.md', '.yaml', '.yml', '.json'];
460
- const ext = path.extname(filename);
461
- return scanExtensions.includes(ext);
462
- }
463
-
464
- async scanConfigurationFiles(component) {
465
- const configRefs = [];
466
- const configFiles = [
467
- 'package.json',
468
- '.aiosrc',
469
- 'aios.config.js',
470
- 'manifest.yaml'
471
- ];
472
-
473
- for (const configFile of configFiles) {
474
- const configPath = path.join(this.rootPath, configFile);
475
-
476
- try {
477
- const refs = await this.scanFile(configPath, component);
478
- configRefs.push(...refs.map(ref => ({ ...ref, source: 'configuration' })));
479
- } catch (_error) {
480
- // Config file doesn't exist or can't be read
481
- }
482
- }
483
-
484
- return configRefs;
485
- }
486
-
487
- async scanDocumentationFiles(component) {
488
- const docRefs = [];
489
- const docsPath = path.join(this.rootPath, 'docs');
490
-
491
- try {
492
- const files = await this.getFilesToScan(docsPath);
493
-
494
- for (const file of files) {
495
- const refs = await this.scanFile(file, component);
496
- docRefs.push(...refs.map(ref => ({ ...ref, source: 'documentation' })));
497
- }
498
- } catch (_error) {
499
- // Docs directory doesn't exist
500
- }
501
-
502
- return docRefs;
503
- }
504
-
505
- findNewUsages(oldUsages, newUsages) {
506
- return newUsages.filter(newUsage =>
507
- !oldUsages.some(oldUsage =>
508
- oldUsage.file === newUsage.file && oldUsage.line === newUsage.line
509
- )
510
- );
511
- }
512
-
513
- findRemovedUsages(oldUsages, newUsages) {
514
- return oldUsages.filter(oldUsage =>
515
- !newUsages.some(newUsage =>
516
- newUsage.file === oldUsage.file && newUsage.line === oldUsage.line
517
- )
518
- );
519
- }
520
-
521
- calculateUsageTrend(baseline, current) {
522
- const referenceChange = current.total_references - baseline.total_references;
523
-
524
- if (referenceChange > 0) return 'increasing';
525
- if (referenceChange < 0) return 'decreasing';
526
- return 'stable';
527
- }
528
-
529
- calculateMigrationProgress(baseline, current) {
530
- if (baseline.total_references === 0) return 1.0;
531
-
532
- const remainingUsages = current.total_references;
533
- const originalUsages = baseline.total_references;
534
-
535
- return Math.max(0, (originalUsages - remainingUsages) / originalUsages);
536
- }
537
-
538
- generateWarningMessage(componentId, deprecationInfo, usage) {
539
- let message = `DEPRECATED: ${componentId} is deprecated`;
540
-
541
- if (deprecationInfo.replacement) {
542
- message += ` - use ${deprecationInfo.replacement} instead`;
543
- }
544
-
545
- if (deprecationInfo.removalVersion) {
546
- message += ` (will be removed in ${deprecationInfo.removalVersion})`;
547
- }
548
-
549
- return message;
550
- }
551
-
552
- calculateWarningSeverity(deprecationInfo, usage) {
553
- if (deprecationInfo.severity === 'critical') return 'error';
554
- if (deprecationInfo.severity === 'high') return 'warning';
555
- return 'info';
556
- }
557
-
558
- generateSuggestedActions(componentId, deprecationInfo, usage) {
559
- const actions = [];
560
-
561
- if (deprecationInfo.replacement) {
562
- actions.push(`Replace with ${deprecationInfo.replacement}`);
563
- }
564
-
565
- if (deprecationInfo.migrationGuide) {
566
- actions.push(`See migration guide: ${deprecationInfo.migrationGuide}`);
567
- }
568
-
569
- actions.push('Update imports and references');
570
- actions.push('Test functionality after replacement');
571
-
572
- return actions;
573
- }
574
-
575
- categorizeUsageLevel(referenceCount) {
576
- if (referenceCount === 0) return 'zero';
577
- if (referenceCount <= 5) return 'low';
578
- if (referenceCount <= 15) return 'medium';
579
- if (referenceCount <= 30) return 'high';
580
- return 'very_high';
581
- }
582
-
583
- async getOrAnalyzeUsage(componentId) {
584
- if (this.usageCache.has(componentId)) {
585
- return this.usageCache.get(componentId);
586
- }
587
-
588
- return await this.analyzeComponentUsage(componentId);
589
- }
590
-
591
- async getAllTrackedComponents() {
592
- // This would typically come from a component registry
593
- // For now, return empty array
594
- return [];
595
- }
596
-
597
- async saveUsageAnalysis(analysis) {
598
- const filename = `usage-${analysis.component_id.replace('/', '-')}-${Date.now()}.json`;
599
- const filePath = path.join(this.usageDir, filename);
600
-
601
- await fs.writeFile(filePath, JSON.stringify(analysis, null, 2));
602
- }
603
-
604
- async saveUsageChanges(changes) {
605
- const filename = `changes-${changes.component_id.replace('/', '-')}-${Date.now()}.json`;
606
- const filePath = path.join(this.usageDir, filename);
607
-
608
- await fs.writeFile(filePath, JSON.stringify(changes, null, 2));
609
- }
610
-
611
- async saveUsageWarnings(componentId, warnings) {
612
- const filename = `warnings-${componentId.replace('/', '-')}-${Date.now()}.json`;
613
- const filePath = path.join(this.usageDir, filename);
614
-
615
- await fs.writeFile(filePath, JSON.stringify(warnings, null, 2));
616
- }
617
-
618
- initializeScanPatterns() {
619
- return {
620
- agent: [
621
- {
622
- pattern: 'agent:\\s*{component_name}',
623
- type: 'yaml_reference',
624
- confidence: 0.9
625
- },
626
- {
627
- pattern: 'use\\s+{component_name}',
628
- type: 'usage_statement',
629
- confidence: 0.8
630
- }
631
- ],
632
- task: [
633
- {
634
- pattern: '\\*{component_name}',
635
- type: 'task_invocation',
636
- confidence: 0.9
637
- },
638
- {
639
- pattern: 'require\\(.*{component_name}.*\\)',
640
- type: 'import_statement',
641
- confidence: 0.8
642
- }
643
- ],
644
- workflow: [
645
- {
646
- pattern: 'workflow:\\s*{component_name}',
647
- type: 'workflow_reference',
648
- confidence: 0.9
649
- }
650
- ],
651
- util: [
652
- {
653
- pattern: 'require\\(.*{component_name}.*\\)',
654
- type: 'import_statement',
655
- confidence: 0.9
656
- },
657
- {
658
- pattern: 'import.*{component_name}',
659
- type: 'import_statement',
660
- confidence: 0.9
661
- }
662
- ],
663
- default: [
664
- {
665
- pattern: '{component_name}',
666
- type: 'general_reference',
667
- confidence: 0.6
668
- }
669
- ]
670
- };
671
- }
672
- }
673
-
1
+ const fs = require('fs').promises;
2
+ const path = require('path');
3
+ const chalk = require('chalk');
4
+
5
+ /**
6
+ * Usage tracker for AIOS-FULLSTACK framework components
7
+ * Tracks component usage patterns for deprecation warnings and impact analysis
8
+ */
9
+ class UsageTracker {
10
+ constructor(options = {}) {
11
+ this.rootPath = options.rootPath || process.cwd();
12
+ this.usageDir = path.join(this.rootPath, '.aios', 'usage');
13
+ this.usageCache = new Map();
14
+ this.scanPatterns = this.initializeScanPatterns();
15
+ }
16
+
17
+ /**
18
+ * Initialize usage tracker
19
+ */
20
+ async initialize() {
21
+ try {
22
+ // Create usage directory
23
+ await fs.mkdir(this.usageDir, { recursive: true });
24
+
25
+ console.log(chalk.green('✅ Usage tracker initialized'));
26
+ return true;
27
+
28
+ } catch (_error) {
29
+ console.error(chalk.red(`Failed to initialize usage tracker: ${error.message}`));
30
+ throw error;
31
+ }
32
+ }
33
+
34
+ /**
35
+ * Analyze component usage across the codebase
36
+ */
37
+ async analyzeComponentUsage(componentId, options = {}) {
38
+ const analysis = {
39
+ component_id: componentId,
40
+ analysis_timestamp: new Date().toISOString(),
41
+ total_references: 0,
42
+ usage_locations: [],
43
+ dependent_components: [],
44
+ external_references: [],
45
+ usage_patterns: {},
46
+ risk_assessment: {
47
+ impact_level: 'low',
48
+ affected_areas: [],
49
+ migration_complexity: 'simple'
50
+ }
51
+ };
52
+
53
+ try {
54
+ console.log(chalk.blue(`🔍 Analyzing usage for component: ${componentId}`));
55
+
56
+ // Get component information
57
+ const component = await this.getComponentInfo(componentId);
58
+ if (!component) {
59
+ throw new Error(`Component not found: ${componentId}`);
60
+ }
61
+
62
+ // Scan for direct references
63
+ const directReferences = await this.scanForDirectReferences(component, options);
64
+ analysis.usage_locations = directReferences;
65
+ analysis.total_references = directReferences.length;
66
+
67
+ // Analyze dependency relationships
68
+ const dependencies = await this.analyzeDependencyRelationships(component, options);
69
+ analysis.dependent_components = dependencies;
70
+
71
+ // Check for external references (imports, configurations, etc.)
72
+ const externalRefs = await this.scanForExternalReferences(component, options);
73
+ analysis.external_references = externalRefs;
74
+
75
+ // Analyze usage patterns
76
+ analysis.usage_patterns = await this.analyzeUsagePatterns(component, directReferences);
77
+
78
+ // Assess migration risk
79
+ analysis.risk_assessment = this.assessMigrationRisk(analysis);
80
+
81
+ // Cache results
82
+ this.usageCache.set(componentId, analysis);
83
+
84
+ // Save detailed analysis
85
+ await this.saveUsageAnalysis(analysis);
86
+
87
+ console.log(chalk.green(`✅ Usage analysis completed for ${componentId}`));
88
+ console.log(chalk.gray(` Total references: ${analysis.total_references}`));
89
+ console.log(chalk.gray(` Dependent components: ${analysis.dependent_components.length}`));
90
+ console.log(chalk.gray(` Impact level: ${analysis.risk_assessment.impact_level}`));
91
+
92
+ return analysis;
93
+
94
+ } catch (_error) {
95
+ console.error(chalk.red(`Usage analysis failed for ${componentId}: ${error.message}`));
96
+ throw error;
97
+ }
98
+ }
99
+
100
+ /**
101
+ * Track usage changes over time for deprecated components
102
+ */
103
+ async trackUsageChanges(componentId, baselineAnalysis) {
104
+ const currentAnalysis = await this.analyzeComponentUsage(componentId);
105
+
106
+ const changes = {
107
+ component_id: componentId,
108
+ comparison_timestamp: new Date().toISOString(),
109
+ baseline_timestamp: baselineAnalysis.analysis_timestamp,
110
+ changes: {
111
+ total_references: {
112
+ before: baselineAnalysis.total_references,
113
+ after: currentAnalysis.total_references,
114
+ change: currentAnalysis.total_references - baselineAnalysis.total_references
115
+ },
116
+ dependent_components: {
117
+ before: baselineAnalysis.dependent_components.length,
118
+ after: currentAnalysis.dependent_components.length,
119
+ change: currentAnalysis.dependent_components.length - baselineAnalysis.dependent_components.length
120
+ },
121
+ new_usages: this.findNewUsages(baselineAnalysis.usage_locations, currentAnalysis.usage_locations),
122
+ removed_usages: this.findRemovedUsages(baselineAnalysis.usage_locations, currentAnalysis.usage_locations)
123
+ },
124
+ trend: this.calculateUsageTrend(baselineAnalysis, currentAnalysis),
125
+ migration_progress: this.calculateMigrationProgress(baselineAnalysis, currentAnalysis)
126
+ };
127
+
128
+ // Save change tracking
129
+ await this.saveUsageChanges(changes);
130
+
131
+ return changes;
132
+ }
133
+
134
+ /**
135
+ * Generate usage warnings for deprecated components
136
+ */
137
+ async generateUsageWarnings(componentId, deprecationInfo) {
138
+ const analysis = await this.analyzeComponentUsage(componentId);
139
+ const warnings = [];
140
+
141
+ for (const _usage of analysis.usage_locations) {
142
+ const warning = {
143
+ type: 'deprecation_warning',
144
+ component_id: componentId,
145
+ usage_location: {
146
+ file: usage.file,
147
+ line: usage.line,
148
+ context: usage.context
149
+ },
150
+ message: this.generateWarningMessage(componentId, deprecationInfo, usage),
151
+ severity: this.calculateWarningSeverity(deprecationInfo, usage),
152
+ suggested_actions: this.generateSuggestedActions(componentId, deprecationInfo, usage)
153
+ };
154
+
155
+ warnings.push(warning);
156
+ }
157
+
158
+ // Save warnings for later processing
159
+ await this.saveUsageWarnings(componentId, warnings);
160
+
161
+ return warnings;
162
+ }
163
+
164
+ /**
165
+ * Get usage statistics for reporting
166
+ */
167
+ async getUsageStatistics(componentIds = null) {
168
+ const stats = {
169
+ generated_at: new Date().toISOString(),
170
+ total_components_analyzed: 0,
171
+ high_usage_components: [],
172
+ zero_usage_components: [],
173
+ usage_distribution: {},
174
+ dependency_graph: {}
175
+ };
176
+
177
+ const componentsToAnalyze = componentIds || await this.getAllTrackedComponents();
178
+
179
+ for (const componentId of componentsToAnalyze) {
180
+ try {
181
+ const analysis = await this.getOrAnalyzeUsage(componentId);
182
+ stats.total_components_analyzed++;
183
+
184
+ // Categorize by usage level
185
+ if (analysis.total_references === 0) {
186
+ stats.zero_usage_components.push(componentId);
187
+ } else if (analysis.total_references >= 10) {
188
+ stats.high_usage_components.push({
189
+ component_id: componentId,
190
+ reference_count: analysis.total_references,
191
+ impact_level: analysis.risk_assessment.impact_level
192
+ });
193
+ }
194
+
195
+ // Add to usage distribution
196
+ const usageRange = this.categorizeUsageLevel(analysis.total_references);
197
+ stats.usage_distribution[usageRange] = (stats.usage_distribution[usageRange] || 0) + 1;
198
+
199
+ // Add to dependency graph
200
+ stats.dependency_graph[componentId] = analysis.dependent_components.map(dep => dep.component_id);
201
+
202
+ } catch (_error) {
203
+ console.warn(chalk.yellow(`Failed to analyze usage for ${componentId}: ${error.message}`));
204
+ }
205
+ }
206
+
207
+ return stats;
208
+ }
209
+
210
+ /**
211
+ * Scan for direct references to a component
212
+ */
213
+ async scanForDirectReferences(component, options = {}) {
214
+ const references = [];
215
+ const scanPaths = await this.getScanPaths(_options);
216
+
217
+ for (const scanPath of scanPaths) {
218
+ try {
219
+ const pathReferences = await this.scanPath(scanPath, component);
220
+ references.push(...pathReferences);
221
+ } catch (_error) {
222
+ console.warn(chalk.yellow(`Failed to scan path ${scanPath}: ${error.message}`));
223
+ }
224
+ }
225
+
226
+ return references;
227
+ }
228
+
229
+ /**
230
+ * Scan a specific path for component references
231
+ */
232
+ async scanPath(scanPath, component) {
233
+ const references = [];
234
+ const files = await this.getFilesToScan(scanPath);
235
+
236
+ for (const file of files) {
237
+ try {
238
+ const fileReferences = await this.scanFile(file, component);
239
+ references.push(...fileReferences);
240
+ } catch (_error) {
241
+ // Skip files that can't be read
242
+ continue;
243
+ }
244
+ }
245
+
246
+ return references;
247
+ }
248
+
249
+ /**
250
+ * Scan a single file for component references
251
+ */
252
+ async scanFile(filePath, component) {
253
+ const references = [];
254
+
255
+ try {
256
+ const content = await fs.readFile(filePath, 'utf-8');
257
+ const lines = content.split('\n');
258
+
259
+ for (let i = 0; i < lines.length; i++) {
260
+ const line = lines[i];
261
+ const lineNumber = i + 1;
262
+
263
+ // Check for various reference patterns
264
+ const matches = this.findReferencesInLine(line, component);
265
+
266
+ for (const match of matches) {
267
+ references.push({
268
+ file: filePath,
269
+ line: lineNumber,
270
+ column: match.column,
271
+ context: line.trim(),
272
+ reference_type: match.type,
273
+ match_text: match.text
274
+ });
275
+ }
276
+ }
277
+ } catch (_error) {
278
+ // File couldn't be read, skip
279
+ }
280
+
281
+ return references;
282
+ }
283
+
284
+ /**
285
+ * Find references in a single line of code
286
+ */
287
+ findReferencesInLine(line, component) {
288
+ const matches = [];
289
+ const patterns = this.scanPatterns[component.type] || this.scanPatterns.default;
290
+
291
+ for (const pattern of patterns) {
292
+ const regex = new RegExp(pattern.pattern.replace('{component_name}', component.name), pattern.flags || 'gi');
293
+ let match;
294
+
295
+ while ((match = regex.exec(line)) !== null) {
296
+ matches.push({
297
+ type: pattern.type,
298
+ text: match[0],
299
+ column: match.index,
300
+ confidence: pattern.confidence || 0.8
301
+ });
302
+ }
303
+ }
304
+
305
+ return matches;
306
+ }
307
+
308
+ /**
309
+ * Analyze dependency relationships
310
+ */
311
+ async analyzeDependencyRelationships(component, options = {}) {
312
+ const dependencies = [];
313
+
314
+ // This would analyze manifest files, import statements, etc.
315
+ // For now, return empty array as placeholder
316
+
317
+ return dependencies;
318
+ }
319
+
320
+ /**
321
+ * Scan for external references (config files, documentation, etc.)
322
+ */
323
+ async scanForExternalReferences(component, options = {}) {
324
+ const externalRefs = [];
325
+
326
+ // Check configuration files
327
+ const configRefs = await this.scanConfigurationFiles(component);
328
+ externalRefs.push(...configRefs);
329
+
330
+ // Check documentation
331
+ const docRefs = await this.scanDocumentationFiles(component);
332
+ externalRefs.push(...docRefs);
333
+
334
+ return externalRefs;
335
+ }
336
+
337
+ /**
338
+ * Analyze usage patterns
339
+ */
340
+ async analyzeUsagePatterns(component, references) {
341
+ const patterns = {
342
+ by_file_type: {},
343
+ by_usage_type: {},
344
+ temporal_distribution: {},
345
+ complexity_indicators: {}
346
+ };
347
+
348
+ for (const ref of references) {
349
+ // Group by file extension
350
+ const ext = path.extname(ref.file);
351
+ patterns.by_file_type[ext] = (patterns.by_file_type[ext] || 0) + 1;
352
+
353
+ // Group by reference type
354
+ patterns.by_usage_type[ref.reference_type] = (patterns.by_usage_type[ref.reference_type] || 0) + 1;
355
+ }
356
+
357
+ return patterns;
358
+ }
359
+
360
+ /**
361
+ * Assess migration risk based on usage analysis
362
+ */
363
+ assessMigrationRisk(analysis) {
364
+ let impactLevel = 'low';
365
+ let migrationComplexity = 'simple';
366
+ const affectedAreas = [];
367
+
368
+ // Assess based on total references
369
+ if (analysis.total_references > 20) {
370
+ impactLevel = 'high';
371
+ migrationComplexity = 'complex';
372
+ } else if (analysis.total_references > 10) {
373
+ impactLevel = 'medium';
374
+ migrationComplexity = 'moderate';
375
+ }
376
+
377
+ // Check for complex usage patterns
378
+ if (analysis.dependent_components.length > 5) {
379
+ migrationComplexity = 'complex';
380
+ affectedAreas.push('component_dependencies');
381
+ }
382
+
383
+ if (analysis.external_references.length > 0) {
384
+ affectedAreas.push('external_configuration');
385
+ }
386
+
387
+ return {
388
+ impact_level: impactLevel,
389
+ affected_areas: affectedAreas,
390
+ migration_complexity: migrationComplexity
391
+ };
392
+ }
393
+
394
+ // Helper methods
395
+
396
+ async getComponentInfo(componentId) {
397
+ // This would typically integrate with the component registry
398
+ // For now, return a basic component structure
399
+ const [type, name] = componentId.split('/');
400
+
401
+ return {
402
+ id: componentId,
403
+ type: type,
404
+ name: name,
405
+ file_path: `aios-core/${type}s/${name}.md`
406
+ };
407
+ }
408
+
409
+ async getScanPaths(_options) {
410
+ const defaultPaths = [
411
+ path.join(this.rootPath, 'aios-core'),
412
+ path.join(this.rootPath, 'src'),
413
+ path.join(this.rootPath, 'lib')
414
+ ];
415
+
416
+ if (options.scanPaths) {
417
+ return options.scanPaths;
418
+ }
419
+
420
+ // Filter paths that exist
421
+ const existingPaths = [];
422
+ for (const scanPath of defaultPaths) {
423
+ try {
424
+ await fs.access(scanPath);
425
+ existingPaths.push(scanPath);
426
+ } catch (_error) {
427
+ // Path doesn't exist, skip
428
+ }
429
+ }
430
+
431
+ return existingPaths;
432
+ }
433
+
434
+ async getFilesToScan(scanPath) {
435
+ const files = [];
436
+
437
+ try {
438
+ const entries = await fs.readdir(scanPath, { withFileTypes: true });
439
+
440
+ for (const entry of entries) {
441
+ const fullPath = path.join(scanPath, entry.name);
442
+
443
+ if (entry.isDirectory()) {
444
+ // Recursively scan subdirectories
445
+ const subFiles = await this.getFilesToScan(fullPath);
446
+ files.push(...subFiles);
447
+ } else if (this.shouldScanFile(entry.name)) {
448
+ files.push(fullPath);
449
+ }
450
+ }
451
+ } catch (_error) {
452
+ // Can't read directory, skip
453
+ }
454
+
455
+ return files;
456
+ }
457
+
458
+ shouldScanFile(filename) {
459
+ const scanExtensions = ['.js', '.ts', '.md', '.yaml', '.yml', '.json'];
460
+ const ext = path.extname(filename);
461
+ return scanExtensions.includes(ext);
462
+ }
463
+
464
+ async scanConfigurationFiles(component) {
465
+ const configRefs = [];
466
+ const configFiles = [
467
+ 'package.json',
468
+ '.aiosrc',
469
+ 'aios.config.js',
470
+ 'manifest.yaml'
471
+ ];
472
+
473
+ for (const configFile of configFiles) {
474
+ const configPath = path.join(this.rootPath, configFile);
475
+
476
+ try {
477
+ const refs = await this.scanFile(configPath, component);
478
+ configRefs.push(...refs.map(ref => ({ ...ref, source: 'configuration' })));
479
+ } catch (_error) {
480
+ // Config file doesn't exist or can't be read
481
+ }
482
+ }
483
+
484
+ return configRefs;
485
+ }
486
+
487
+ async scanDocumentationFiles(component) {
488
+ const docRefs = [];
489
+ const docsPath = path.join(this.rootPath, 'docs');
490
+
491
+ try {
492
+ const files = await this.getFilesToScan(docsPath);
493
+
494
+ for (const file of files) {
495
+ const refs = await this.scanFile(file, component);
496
+ docRefs.push(...refs.map(ref => ({ ...ref, source: 'documentation' })));
497
+ }
498
+ } catch (_error) {
499
+ // Docs directory doesn't exist
500
+ }
501
+
502
+ return docRefs;
503
+ }
504
+
505
+ findNewUsages(oldUsages, newUsages) {
506
+ return newUsages.filter(newUsage =>
507
+ !oldUsages.some(oldUsage =>
508
+ oldUsage.file === newUsage.file && oldUsage.line === newUsage.line
509
+ )
510
+ );
511
+ }
512
+
513
+ findRemovedUsages(oldUsages, newUsages) {
514
+ return oldUsages.filter(oldUsage =>
515
+ !newUsages.some(newUsage =>
516
+ newUsage.file === oldUsage.file && newUsage.line === oldUsage.line
517
+ )
518
+ );
519
+ }
520
+
521
+ calculateUsageTrend(baseline, current) {
522
+ const referenceChange = current.total_references - baseline.total_references;
523
+
524
+ if (referenceChange > 0) return 'increasing';
525
+ if (referenceChange < 0) return 'decreasing';
526
+ return 'stable';
527
+ }
528
+
529
+ calculateMigrationProgress(baseline, current) {
530
+ if (baseline.total_references === 0) return 1.0;
531
+
532
+ const remainingUsages = current.total_references;
533
+ const originalUsages = baseline.total_references;
534
+
535
+ return Math.max(0, (originalUsages - remainingUsages) / originalUsages);
536
+ }
537
+
538
+ generateWarningMessage(componentId, deprecationInfo, usage) {
539
+ let message = `DEPRECATED: ${componentId} is deprecated`;
540
+
541
+ if (deprecationInfo.replacement) {
542
+ message += ` - use ${deprecationInfo.replacement} instead`;
543
+ }
544
+
545
+ if (deprecationInfo.removalVersion) {
546
+ message += ` (will be removed in ${deprecationInfo.removalVersion})`;
547
+ }
548
+
549
+ return message;
550
+ }
551
+
552
+ calculateWarningSeverity(deprecationInfo, usage) {
553
+ if (deprecationInfo.severity === 'critical') return 'error';
554
+ if (deprecationInfo.severity === 'high') return 'warning';
555
+ return 'info';
556
+ }
557
+
558
+ generateSuggestedActions(componentId, deprecationInfo, usage) {
559
+ const actions = [];
560
+
561
+ if (deprecationInfo.replacement) {
562
+ actions.push(`Replace with ${deprecationInfo.replacement}`);
563
+ }
564
+
565
+ if (deprecationInfo.migrationGuide) {
566
+ actions.push(`See migration guide: ${deprecationInfo.migrationGuide}`);
567
+ }
568
+
569
+ actions.push('Update imports and references');
570
+ actions.push('Test functionality after replacement');
571
+
572
+ return actions;
573
+ }
574
+
575
+ categorizeUsageLevel(referenceCount) {
576
+ if (referenceCount === 0) return 'zero';
577
+ if (referenceCount <= 5) return 'low';
578
+ if (referenceCount <= 15) return 'medium';
579
+ if (referenceCount <= 30) return 'high';
580
+ return 'very_high';
581
+ }
582
+
583
+ async getOrAnalyzeUsage(componentId) {
584
+ if (this.usageCache.has(componentId)) {
585
+ return this.usageCache.get(componentId);
586
+ }
587
+
588
+ return await this.analyzeComponentUsage(componentId);
589
+ }
590
+
591
+ async getAllTrackedComponents() {
592
+ // This would typically come from a component registry
593
+ // For now, return empty array
594
+ return [];
595
+ }
596
+
597
+ async saveUsageAnalysis(analysis) {
598
+ const filename = `usage-${analysis.component_id.replace('/', '-')}-${Date.now()}.json`;
599
+ const filePath = path.join(this.usageDir, filename);
600
+
601
+ await fs.writeFile(filePath, JSON.stringify(analysis, null, 2));
602
+ }
603
+
604
+ async saveUsageChanges(changes) {
605
+ const filename = `changes-${changes.component_id.replace('/', '-')}-${Date.now()}.json`;
606
+ const filePath = path.join(this.usageDir, filename);
607
+
608
+ await fs.writeFile(filePath, JSON.stringify(changes, null, 2));
609
+ }
610
+
611
+ async saveUsageWarnings(componentId, warnings) {
612
+ const filename = `warnings-${componentId.replace('/', '-')}-${Date.now()}.json`;
613
+ const filePath = path.join(this.usageDir, filename);
614
+
615
+ await fs.writeFile(filePath, JSON.stringify(warnings, null, 2));
616
+ }
617
+
618
+ initializeScanPatterns() {
619
+ return {
620
+ agent: [
621
+ {
622
+ pattern: 'agent:\\s*{component_name}',
623
+ type: 'yaml_reference',
624
+ confidence: 0.9
625
+ },
626
+ {
627
+ pattern: 'use\\s+{component_name}',
628
+ type: 'usage_statement',
629
+ confidence: 0.8
630
+ }
631
+ ],
632
+ task: [
633
+ {
634
+ pattern: '\\*{component_name}',
635
+ type: 'task_invocation',
636
+ confidence: 0.9
637
+ },
638
+ {
639
+ pattern: 'require\\(.*{component_name}.*\\)',
640
+ type: 'import_statement',
641
+ confidence: 0.8
642
+ }
643
+ ],
644
+ workflow: [
645
+ {
646
+ pattern: 'workflow:\\s*{component_name}',
647
+ type: 'workflow_reference',
648
+ confidence: 0.9
649
+ }
650
+ ],
651
+ util: [
652
+ {
653
+ pattern: 'require\\(.*{component_name}.*\\)',
654
+ type: 'import_statement',
655
+ confidence: 0.9
656
+ },
657
+ {
658
+ pattern: 'import.*{component_name}',
659
+ type: 'import_statement',
660
+ confidence: 0.9
661
+ }
662
+ ],
663
+ default: [
664
+ {
665
+ pattern: '{component_name}',
666
+ type: 'general_reference',
667
+ confidence: 0.6
668
+ }
669
+ ]
670
+ };
671
+ }
672
+ }
673
+
674
674
  module.exports = UsageTracker;