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.
- package/.aios-core/core/code-intel/helpers/dev-helper.js +206 -0
- package/.aios-core/core/registry/registry-schema.json +166 -166
- package/.aios-core/core/synapse/diagnostics/collectors/hook-collector.js +3 -3
- package/.aios-core/data/entity-registry.yaml +27 -0
- package/.aios-core/development/scripts/approval-workflow.js +642 -642
- package/.aios-core/development/scripts/backup-manager.js +606 -606
- package/.aios-core/development/scripts/branch-manager.js +389 -389
- package/.aios-core/development/scripts/code-quality-improver.js +1311 -1311
- package/.aios-core/development/scripts/commit-message-generator.js +849 -849
- package/.aios-core/development/scripts/conflict-resolver.js +674 -674
- package/.aios-core/development/scripts/dependency-analyzer.js +637 -637
- package/.aios-core/development/scripts/diff-generator.js +351 -351
- package/.aios-core/development/scripts/elicitation-engine.js +384 -384
- package/.aios-core/development/scripts/elicitation-session-manager.js +299 -299
- package/.aios-core/development/scripts/git-wrapper.js +461 -461
- package/.aios-core/development/scripts/manifest-preview.js +244 -244
- package/.aios-core/development/scripts/metrics-tracker.js +775 -775
- package/.aios-core/development/scripts/modification-validator.js +554 -554
- package/.aios-core/development/scripts/pattern-learner.js +1224 -1224
- package/.aios-core/development/scripts/performance-analyzer.js +757 -757
- package/.aios-core/development/scripts/refactoring-suggester.js +1138 -1138
- package/.aios-core/development/scripts/rollback-handler.js +530 -530
- package/.aios-core/development/scripts/security-checker.js +358 -358
- package/.aios-core/development/scripts/template-engine.js +239 -239
- package/.aios-core/development/scripts/template-validator.js +278 -278
- package/.aios-core/development/scripts/test-generator.js +843 -843
- package/.aios-core/development/scripts/transaction-manager.js +589 -589
- package/.aios-core/development/scripts/usage-tracker.js +673 -673
- package/.aios-core/development/scripts/validate-filenames.js +226 -226
- package/.aios-core/development/scripts/version-tracker.js +526 -526
- package/.aios-core/development/scripts/yaml-validator.js +396 -396
- package/.aios-core/development/tasks/build-autonomous.md +10 -4
- package/.aios-core/development/tasks/create-service.md +23 -0
- package/.aios-core/development/tasks/dev-develop-story.md +12 -6
- package/.aios-core/development/tasks/dev-suggest-refactoring.md +7 -1
- package/.aios-core/development/tasks/publish-npm.md +3 -3
- package/.aios-core/hooks/unified/README.md +1 -1
- package/.aios-core/install-manifest.yaml +65 -61
- package/.aios-core/manifests/schema/manifest-schema.json +190 -190
- package/.aios-core/product/templates/component-react-tmpl.tsx +98 -98
- package/.aios-core/product/templates/engine/schemas/adr.schema.json +102 -102
- package/.aios-core/product/templates/engine/schemas/dbdr.schema.json +205 -205
- package/.aios-core/product/templates/engine/schemas/epic.schema.json +175 -175
- package/.aios-core/product/templates/engine/schemas/pmdr.schema.json +175 -175
- package/.aios-core/product/templates/engine/schemas/prd-v2.schema.json +300 -300
- package/.aios-core/product/templates/engine/schemas/prd.schema.json +152 -152
- package/.aios-core/product/templates/engine/schemas/story.schema.json +222 -222
- package/.aios-core/product/templates/engine/schemas/task.schema.json +154 -154
- package/.aios-core/product/templates/eslintrc-security.json +32 -32
- package/.aios-core/product/templates/github-actions-cd.yml +212 -212
- package/.aios-core/product/templates/github-actions-ci.yml +172 -172
- package/.aios-core/product/templates/shock-report-tmpl.html +502 -502
- package/.aios-core/product/templates/token-exports-css-tmpl.css +240 -240
- package/.aios-core/quality/schemas/quality-metrics.schema.json +233 -233
- package/.aios-core/scripts/migrate-framework-docs.sh +300 -300
- package/README.en.md +747 -0
- package/README.md +4 -2
- package/bin/aios.js +7 -4
- package/package.json +1 -1
- package/packages/aios-pro-cli/src/recover.js +1 -1
- package/packages/installer/src/wizard/ide-config-generator.js +6 -6
- package/packages/installer/src/wizard/pro-setup.js +3 -3
- package/pro/license/degradation.js +220 -220
- package/pro/license/errors.js +450 -450
- package/pro/license/feature-gate.js +354 -354
- package/pro/license/index.js +181 -181
- package/pro/license/license-cache.js +523 -523
- package/pro/license/license-crypto.js +303 -303
- package/scripts/package-synapse.js +5 -5
- package/scripts/validate-package-completeness.js +3 -3
- package/.aios-core/.session/current-session.json +0 -14
- package/.aios-core/data/registry-update-log.jsonl +0 -191
- package/.aios-core/docs/SHARD-TRANSLATION-GUIDE.md +0 -335
- package/.aios-core/docs/component-creation-guide.md +0 -458
- package/.aios-core/docs/session-update-pattern.md +0 -307
- package/.aios-core/docs/standards/AIOS-FRAMEWORK-MASTER.md +0 -1963
- package/.aios-core/docs/standards/AIOS-LIVRO-DE-OURO-V2.1-SUMMARY.md +0 -1190
- package/.aios-core/docs/standards/AIOS-LIVRO-DE-OURO-V2.1.md +0 -439
- package/.aios-core/docs/standards/AIOS-LIVRO-DE-OURO.md +0 -5398
- package/.aios-core/docs/standards/V3-ARCHITECTURAL-DECISIONS.md +0 -523
- package/.aios-core/docs/template-syntax.md +0 -267
- package/.aios-core/docs/troubleshooting-guide.md +0 -625
- package/.aios-core/infrastructure/tests/utilities-audit-results.json +0 -501
- package/.aios-core/manifests/agents.csv +0 -29
- package/.aios-core/manifests/tasks.csv +0 -198
- package/.aios-core/manifests/workers.csv +0 -204
- package/.claude/rules/agent-authority.md +0 -105
- package/.claude/rules/coderabbit-integration.md +0 -93
- package/.claude/rules/ids-principles.md +0 -112
- package/.claude/rules/story-lifecycle.md +0 -139
- package/.claude/rules/workflow-execution.md +0 -150
- package/scripts/glue/README.md +0 -355
- package/scripts/glue/compose-agent-prompt.cjs +0 -362
- /package/.claude/hooks/{precompact-session-digest.js → precompact-session-digest.cjs} +0 -0
- /package/.claude/hooks/{synapse-engine.js → synapse-engine.cjs} +0 -0
|
@@ -1,527 +1,527 @@
|
|
|
1
|
-
const fs = require('fs').promises;
|
|
2
|
-
const path = require('path');
|
|
3
|
-
const semver = require('semver');
|
|
4
|
-
const chalk = require('chalk');
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Framework version tracking utility for AIOS-FULLSTACK
|
|
8
|
-
* Manages framework versions, migration history, and compatibility tracking
|
|
9
|
-
*/
|
|
10
|
-
class VersionTracker {
|
|
11
|
-
constructor(options = {}) {
|
|
12
|
-
this.rootPath = options.rootPath || process.cwd();
|
|
13
|
-
this.versionFile = path.join(this.rootPath, '.aios', 'version-info.json');
|
|
14
|
-
this.migrationDir = path.join(this.rootPath, '.aios', 'migrations');
|
|
15
|
-
this.currentVersion = null;
|
|
16
|
-
this.versionInfo = null;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Initialize version tracking system
|
|
21
|
-
*/
|
|
22
|
-
async initialize() {
|
|
23
|
-
try {
|
|
24
|
-
// Ensure directories exist
|
|
25
|
-
await fs.mkdir(path.dirname(this.versionFile), { recursive: true });
|
|
26
|
-
await fs.mkdir(this.migrationDir, { recursive: true });
|
|
27
|
-
|
|
28
|
-
// Check if version info exists
|
|
29
|
-
try {
|
|
30
|
-
await fs.access(this.versionFile);
|
|
31
|
-
this.versionInfo = await this.loadVersionInfo();
|
|
32
|
-
} catch (_error) {
|
|
33
|
-
// Create initial version info
|
|
34
|
-
this.versionInfo = this.createInitialVersionInfo();
|
|
35
|
-
await this.saveVersionInfo();
|
|
36
|
-
console.log(chalk.green('✅ Version tracking initialized'));
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
this.currentVersion = this.versionInfo.current_version;
|
|
40
|
-
return this.versionInfo;
|
|
41
|
-
|
|
42
|
-
} catch (_error) {
|
|
43
|
-
console.error(chalk.red(`Version tracking initialization failed: ${error.message}`));
|
|
44
|
-
throw error;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Get current framework version
|
|
50
|
-
*/
|
|
51
|
-
async getCurrentVersion() {
|
|
52
|
-
if (!this.versionInfo) {
|
|
53
|
-
await this.initialize();
|
|
54
|
-
}
|
|
55
|
-
return this.currentVersion;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Record a new framework version
|
|
60
|
-
*/
|
|
61
|
-
async recordVersion(versionData) {
|
|
62
|
-
try {
|
|
63
|
-
const {
|
|
64
|
-
version,
|
|
65
|
-
description,
|
|
66
|
-
changes = [],
|
|
67
|
-
migration_required = false,
|
|
68
|
-
breaking_changes = [],
|
|
69
|
-
compatibility_notes = '',
|
|
70
|
-
release_notes = ''
|
|
71
|
-
} = versionData;
|
|
72
|
-
|
|
73
|
-
// Validate version format
|
|
74
|
-
if (!semver.valid(version)) {
|
|
75
|
-
throw new Error(`Invalid version format: ${version}`);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// Check if version already exists
|
|
79
|
-
if (this.versionInfo.versions.some(v => v.version === version)) {
|
|
80
|
-
throw new Error(`Version ${version} already exists`);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// Validate version increment
|
|
84
|
-
if (this.currentVersion && !semver.gt(version, this.currentVersion)) {
|
|
85
|
-
throw new Error(`New version ${version} must be greater than current ${this.currentVersion}`);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
const versionEntry = {
|
|
89
|
-
version,
|
|
90
|
-
description,
|
|
91
|
-
timestamp: new Date().toISOString(),
|
|
92
|
-
changes,
|
|
93
|
-
migration_required,
|
|
94
|
-
breaking_changes,
|
|
95
|
-
compatibility_notes,
|
|
96
|
-
release_notes,
|
|
97
|
-
previous_version: this.currentVersion,
|
|
98
|
-
status: 'active',
|
|
99
|
-
components_modified: await this.detectModifiedComponents(),
|
|
100
|
-
api_changes: await this.detectApiChanges(),
|
|
101
|
-
deprecations: [],
|
|
102
|
-
migration_path: migration_required ? `${this.currentVersion}-to-${version}` : null
|
|
103
|
-
};
|
|
104
|
-
|
|
105
|
-
// Add to version history
|
|
106
|
-
this.versionInfo.versions.unshift(versionEntry);
|
|
107
|
-
this.versionInfo.current_version = version;
|
|
108
|
-
this.versionInfo.previous_version = this.currentVersion;
|
|
109
|
-
this.versionInfo.last_updated = new Date().toISOString();
|
|
110
|
-
this.versionInfo.total_versions++;
|
|
111
|
-
|
|
112
|
-
// Update current version
|
|
113
|
-
this.currentVersion = version;
|
|
114
|
-
|
|
115
|
-
// Save updated info
|
|
116
|
-
await this.saveVersionInfo();
|
|
117
|
-
|
|
118
|
-
console.log(chalk.green(`✅ Recorded new framework version: ${version}`));
|
|
119
|
-
|
|
120
|
-
if (migration_required) {
|
|
121
|
-
console.log(chalk.yellow(`⚠️ Migration required from ${this.versionInfo.previous_version} to ${version}`));
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
return versionEntry;
|
|
125
|
-
|
|
126
|
-
} catch (_error) {
|
|
127
|
-
console.error(chalk.red(`Failed to record version: ${error.message}`));
|
|
128
|
-
throw error;
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* Get version history with optional filtering
|
|
134
|
-
*/
|
|
135
|
-
async getVersionHistory(options = {}) {
|
|
136
|
-
const {
|
|
137
|
-
limit = 10,
|
|
138
|
-
include_migrations = true,
|
|
139
|
-
include_breaking = false,
|
|
140
|
-
since_version = null,
|
|
141
|
-
status_filter = null
|
|
142
|
-
} = options;
|
|
143
|
-
|
|
144
|
-
if (!this.versionInfo) {
|
|
145
|
-
await this.initialize();
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
let versions = [...this.versionInfo.versions];
|
|
149
|
-
|
|
150
|
-
// Apply filters
|
|
151
|
-
if (since_version) {
|
|
152
|
-
const sinceIndex = versions.findIndex(v => v.version === since_version);
|
|
153
|
-
if (sinceIndex !== -1) {
|
|
154
|
-
versions = versions.slice(0, sinceIndex);
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
if (status_filter) {
|
|
159
|
-
versions = versions.filter(v => v.status === status_filter);
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
if (include_breaking) {
|
|
163
|
-
versions = versions.filter(v => v.breaking_changes?.length > 0);
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
if (!include_migrations) {
|
|
167
|
-
versions = versions.filter(v => !v.migration_required);
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
// Apply limit
|
|
171
|
-
versions = versions.slice(0, limit);
|
|
172
|
-
|
|
173
|
-
return {
|
|
174
|
-
current_version: this.currentVersion,
|
|
175
|
-
total_versions: this.versionInfo.total_versions,
|
|
176
|
-
filtered_count: versions.length,
|
|
177
|
-
versions: versions.map(v => ({
|
|
178
|
-
version: v.version,
|
|
179
|
-
description: v.description,
|
|
180
|
-
timestamp: v.timestamp,
|
|
181
|
-
migration_required: v.migration_required,
|
|
182
|
-
breaking_changes: v.breaking_changes?.length || 0,
|
|
183
|
-
status: v.status,
|
|
184
|
-
components_modified: v.components_modified?.length || 0
|
|
185
|
-
}))
|
|
186
|
-
};
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
/**
|
|
190
|
-
* Check compatibility between versions
|
|
191
|
-
*/
|
|
192
|
-
async checkCompatibility(fromVersion, toVersion) {
|
|
193
|
-
const compatibility = {
|
|
194
|
-
compatible: false,
|
|
195
|
-
migration_required: false,
|
|
196
|
-
breaking_changes: [],
|
|
197
|
-
warnings: [],
|
|
198
|
-
migration_path: null,
|
|
199
|
-
estimated_effort: 'unknown',
|
|
200
|
-
risk_level: 'low'
|
|
201
|
-
};
|
|
202
|
-
|
|
203
|
-
try {
|
|
204
|
-
// Validate versions
|
|
205
|
-
if (!semver.valid(fromVersion) || !semver.valid(toVersion)) {
|
|
206
|
-
throw new Error('Invalid version format provided');
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
const fromVersionInfo = this.versionInfo.versions.find(v => v.version === fromVersion);
|
|
210
|
-
const toVersionInfo = this.versionInfo.versions.find(v => v.version === toVersion);
|
|
211
|
-
|
|
212
|
-
if (!fromVersionInfo) {
|
|
213
|
-
compatibility.warnings.push(`Source version ${fromVersion} not found in history`);
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
if (!toVersionInfo) {
|
|
217
|
-
compatibility.warnings.push(`Target version ${toVersion} not found in history`);
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
// Check semantic version compatibility
|
|
221
|
-
const versionDiff = semver.diff(fromVersion, toVersion);
|
|
222
|
-
|
|
223
|
-
switch (versionDiff) {
|
|
224
|
-
case 'patch':
|
|
225
|
-
compatibility.compatible = true;
|
|
226
|
-
compatibility.risk_level = 'low';
|
|
227
|
-
compatibility.estimated_effort = 'minimal';
|
|
228
|
-
break;
|
|
229
|
-
|
|
230
|
-
case 'minor':
|
|
231
|
-
compatibility.compatible = true;
|
|
232
|
-
compatibility.migration_required = toVersionInfo?.migration_required || false;
|
|
233
|
-
compatibility.risk_level = 'low';
|
|
234
|
-
compatibility.estimated_effort = 'low';
|
|
235
|
-
break;
|
|
236
|
-
|
|
237
|
-
case 'major':
|
|
238
|
-
compatibility.migration_required = true;
|
|
239
|
-
compatibility.risk_level = 'high';
|
|
240
|
-
compatibility.estimated_effort = 'high';
|
|
241
|
-
compatibility.compatible = false;
|
|
242
|
-
break;
|
|
243
|
-
|
|
244
|
-
case 'premajor':
|
|
245
|
-
case 'preminor':
|
|
246
|
-
case 'prepatch':
|
|
247
|
-
compatibility.migration_required = true;
|
|
248
|
-
compatibility.risk_level = 'medium';
|
|
249
|
-
compatibility.estimated_effort = 'medium';
|
|
250
|
-
compatibility.compatible = false;
|
|
251
|
-
break;
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
// Collect breaking changes in the path
|
|
255
|
-
const versionsInPath = this.getVersionsInPath(fromVersion, toVersion);
|
|
256
|
-
|
|
257
|
-
for (const version of versionsInPath) {
|
|
258
|
-
if (version.breaking_changes?.length > 0) {
|
|
259
|
-
compatibility.breaking_changes.push(...version.breaking_changes);
|
|
260
|
-
compatibility.migration_required = true;
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
// Set migration path if needed
|
|
265
|
-
if (compatibility.migration_required) {
|
|
266
|
-
compatibility.migration_path = `${fromVersion}-to-${toVersion}`;
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
return compatibility;
|
|
270
|
-
|
|
271
|
-
} catch (_error) {
|
|
272
|
-
compatibility.warnings.push(`Compatibility check failed: ${error.message}`);
|
|
273
|
-
return compatibility;
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
/**
|
|
278
|
-
* Mark a version as deprecated
|
|
279
|
-
*/
|
|
280
|
-
async deprecateVersion(version, deprecationInfo = {}) {
|
|
281
|
-
try {
|
|
282
|
-
const versionEntry = this.versionInfo.versions.find(v => v.version === version);
|
|
283
|
-
|
|
284
|
-
if (!versionEntry) {
|
|
285
|
-
throw new Error(`Version ${version} not found`);
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
if (versionEntry.status === 'deprecated') {
|
|
289
|
-
throw new Error(`Version ${version} is already deprecated`);
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
const deprecation = {
|
|
293
|
-
deprecated_at: new Date().toISOString(),
|
|
294
|
-
reason: deprecationInfo.reason || 'Version deprecated',
|
|
295
|
-
migration_target: deprecationInfo.migration_target || this.currentVersion,
|
|
296
|
-
removal_timeline: deprecationInfo.removal_timeline || 'TBD',
|
|
297
|
-
deprecation_notice: deprecationInfo.notice || `Version ${version} is deprecated. Please upgrade to ${this.currentVersion}.`
|
|
298
|
-
};
|
|
299
|
-
|
|
300
|
-
versionEntry.status = 'deprecated';
|
|
301
|
-
versionEntry.deprecation_info = deprecation;
|
|
302
|
-
|
|
303
|
-
await this.saveVersionInfo();
|
|
304
|
-
|
|
305
|
-
console.log(chalk.yellow(`⚠️ Version ${version} marked as deprecated`));
|
|
306
|
-
return deprecation;
|
|
307
|
-
|
|
308
|
-
} catch (_error) {
|
|
309
|
-
console.error(chalk.red(`Failed to deprecate version: ${error.message}`));
|
|
310
|
-
throw error;
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
/**
|
|
315
|
-
* Get migration path between versions
|
|
316
|
-
*/
|
|
317
|
-
async getMigrationPath(fromVersion, toVersion) {
|
|
318
|
-
const path = {
|
|
319
|
-
from_version: fromVersion,
|
|
320
|
-
to_version: toVersion,
|
|
321
|
-
steps: [],
|
|
322
|
-
total_migrations: 0,
|
|
323
|
-
estimated_duration: 0,
|
|
324
|
-
risk_assessment: 'low',
|
|
325
|
-
requirements: [],
|
|
326
|
-
rollback_available: true
|
|
327
|
-
};
|
|
328
|
-
|
|
329
|
-
try {
|
|
330
|
-
const versionsInPath = this.getVersionsInPath(fromVersion, toVersion);
|
|
331
|
-
|
|
332
|
-
for (const version of versionsInPath) {
|
|
333
|
-
if (version.migration_required) {
|
|
334
|
-
const step = {
|
|
335
|
-
from: version.previous_version,
|
|
336
|
-
to: version.version,
|
|
337
|
-
migration_id: version.migration_path,
|
|
338
|
-
breaking_changes: version.breaking_changes || [],
|
|
339
|
-
estimated_time: this.estimateMigrationTime(version),
|
|
340
|
-
risk_level: this.assessMigrationRisk(version),
|
|
341
|
-
prerequisites: version.migration_prerequisites || [],
|
|
342
|
-
rollback_supported: true
|
|
343
|
-
};
|
|
344
|
-
|
|
345
|
-
path.steps.push(step);
|
|
346
|
-
path.total_migrations++;
|
|
347
|
-
path.estimated_duration += step.estimated_time;
|
|
348
|
-
|
|
349
|
-
if (step.risk_level === 'high') {
|
|
350
|
-
path.risk_assessment = 'high';
|
|
351
|
-
} else if (step.risk_level === 'medium' && path.risk_assessment === 'low') {
|
|
352
|
-
path.risk_assessment = 'medium';
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
// Collect unique requirements
|
|
358
|
-
path.requirements = [...new Set(
|
|
359
|
-
path.steps.flatMap(step => step.prerequisites)
|
|
360
|
-
)];
|
|
361
|
-
|
|
362
|
-
return path;
|
|
363
|
-
|
|
364
|
-
} catch (_error) {
|
|
365
|
-
console.error(chalk.red(`Failed to get migration path: ${error.message}`));
|
|
366
|
-
throw error;
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
/**
|
|
371
|
-
* Generate version report
|
|
372
|
-
*/
|
|
373
|
-
async generateVersionReport() {
|
|
374
|
-
if (!this.versionInfo) {
|
|
375
|
-
await this.initialize();
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
const report = {
|
|
379
|
-
timestamp: new Date().toISOString(),
|
|
380
|
-
current_version: this.currentVersion,
|
|
381
|
-
total_versions: this.versionInfo.total_versions,
|
|
382
|
-
version_distribution: {
|
|
383
|
-
active: 0,
|
|
384
|
-
deprecated: 0,
|
|
385
|
-
archived: 0
|
|
386
|
-
},
|
|
387
|
-
migration_summary: {
|
|
388
|
-
total_migrations: 0,
|
|
389
|
-
pending_migrations: 0,
|
|
390
|
-
failed_migrations: 0
|
|
391
|
-
},
|
|
392
|
-
breaking_changes_summary: {
|
|
393
|
-
total_breaking_versions: 0,
|
|
394
|
-
recent_breaking_changes: []
|
|
395
|
-
},
|
|
396
|
-
compatibility_matrix: {},
|
|
397
|
-
recommendations: []
|
|
398
|
-
};
|
|
399
|
-
|
|
400
|
-
// Analyze version distribution
|
|
401
|
-
this.versionInfo.versions.forEach(version => {
|
|
402
|
-
report.version_distribution[version.status]++;
|
|
403
|
-
|
|
404
|
-
if (version.migration_required) {
|
|
405
|
-
report.migration_summary.total_migrations++;
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
if (version.breaking_changes?.length > 0) {
|
|
409
|
-
report.breaking_changes_summary.total_breaking_versions++;
|
|
410
|
-
|
|
411
|
-
if (semver.gte(version.version, semver.major(this.currentVersion) + '.0.0')) {
|
|
412
|
-
report.breaking_changes_summary.recent_breaking_changes.push({
|
|
413
|
-
version: version.version,
|
|
414
|
-
changes: version.breaking_changes.slice(0, 3)
|
|
415
|
-
});
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
});
|
|
419
|
-
|
|
420
|
-
// Generate recommendations
|
|
421
|
-
if (report.version_distribution.deprecated > 5) {
|
|
422
|
-
report.recommendations.push({
|
|
423
|
-
type: 'cleanup',
|
|
424
|
-
priority: 'medium',
|
|
425
|
-
message: `${report.version_distribution.deprecated} deprecated versions should be archived`
|
|
426
|
-
});
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
if (report.breaking_changes_summary.total_breaking_versions > 10) {
|
|
430
|
-
report.recommendations.push({
|
|
431
|
-
type: 'stability',
|
|
432
|
-
priority: 'high',
|
|
433
|
-
message: 'High number of breaking changes detected. Consider stability improvements.'
|
|
434
|
-
});
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
return report;
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
// Private helper methods
|
|
441
|
-
createInitialVersionInfo() {
|
|
442
|
-
return {
|
|
443
|
-
schema_version: '1.0.0',
|
|
444
|
-
current_version: '1.0.0',
|
|
445
|
-
previous_version: null,
|
|
446
|
-
created_at: new Date().toISOString(),
|
|
447
|
-
last_updated: new Date().toISOString(),
|
|
448
|
-
total_versions: 1,
|
|
449
|
-
versions: [{
|
|
450
|
-
version: '1.0.0',
|
|
451
|
-
description: 'Initial framework version',
|
|
452
|
-
timestamp: new Date().toISOString(),
|
|
453
|
-
changes: ['Initial framework setup'],
|
|
454
|
-
migration_required: false,
|
|
455
|
-
breaking_changes: [],
|
|
456
|
-
compatibility_notes: 'Initial version',
|
|
457
|
-
release_notes: 'AIOS-FULLSTACK framework v1.0.0',
|
|
458
|
-
previous_version: null,
|
|
459
|
-
status: 'active',
|
|
460
|
-
components_modified: [],
|
|
461
|
-
api_changes: [],
|
|
462
|
-
deprecations: [],
|
|
463
|
-
migration_path: null
|
|
464
|
-
}],
|
|
465
|
-
migration_history: [],
|
|
466
|
-
compatibility_matrix: {}
|
|
467
|
-
};
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
async loadVersionInfo() {
|
|
471
|
-
try {
|
|
472
|
-
const content = await fs.readFile(this.versionFile, 'utf-8');
|
|
473
|
-
return JSON.parse(content);
|
|
474
|
-
} catch (_error) {
|
|
475
|
-
throw new Error(`Failed to load version info: ${error.message}`);
|
|
476
|
-
}
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
async saveVersionInfo() {
|
|
480
|
-
try {
|
|
481
|
-
const content = JSON.stringify(this.versionInfo, null, 2);
|
|
482
|
-
await fs.writeFile(this.versionFile, content);
|
|
483
|
-
} catch (_error) {
|
|
484
|
-
throw new Error(`Failed to save version info: ${error.message}`);
|
|
485
|
-
}
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
async detectModifiedComponents() {
|
|
489
|
-
// This would analyze git changes or compare with previous state
|
|
490
|
-
// For now, return empty array
|
|
491
|
-
return [];
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
async detectApiChanges() {
|
|
495
|
-
// This would analyze API changes between versions
|
|
496
|
-
// For now, return empty array
|
|
497
|
-
return [];
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
getVersionsInPath(fromVersion, toVersion) {
|
|
501
|
-
const versions = this.versionInfo.versions.filter(v => {
|
|
502
|
-
return semver.gt(v.version, fromVersion) && semver.lte(v.version, toVersion);
|
|
503
|
-
});
|
|
504
|
-
|
|
505
|
-
return versions.sort((a, b) => semver.compare(a.version, b.version));
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
estimateMigrationTime(version) {
|
|
509
|
-
// Simple heuristic based on breaking changes and components modified
|
|
510
|
-
const baseTime = 30; // minutes
|
|
511
|
-
const breakingChangeMultiplier = version.breaking_changes?.length || 0;
|
|
512
|
-
const componentMultiplier = version.components_modified?.length || 0;
|
|
513
|
-
|
|
514
|
-
return baseTime + (breakingChangeMultiplier * 15) + (componentMultiplier * 5);
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
assessMigrationRisk(version) {
|
|
518
|
-
const breakingChanges = version.breaking_changes?.length || 0;
|
|
519
|
-
const componentsModified = version.components_modified?.length || 0;
|
|
520
|
-
|
|
521
|
-
if (breakingChanges > 5 || componentsModified > 20) return 'high';
|
|
522
|
-
if (breakingChanges > 2 || componentsModified > 10) return 'medium';
|
|
523
|
-
return 'low';
|
|
524
|
-
}
|
|
525
|
-
}
|
|
526
|
-
|
|
1
|
+
const fs = require('fs').promises;
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const semver = require('semver');
|
|
4
|
+
const chalk = require('chalk');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Framework version tracking utility for AIOS-FULLSTACK
|
|
8
|
+
* Manages framework versions, migration history, and compatibility tracking
|
|
9
|
+
*/
|
|
10
|
+
class VersionTracker {
|
|
11
|
+
constructor(options = {}) {
|
|
12
|
+
this.rootPath = options.rootPath || process.cwd();
|
|
13
|
+
this.versionFile = path.join(this.rootPath, '.aios', 'version-info.json');
|
|
14
|
+
this.migrationDir = path.join(this.rootPath, '.aios', 'migrations');
|
|
15
|
+
this.currentVersion = null;
|
|
16
|
+
this.versionInfo = null;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Initialize version tracking system
|
|
21
|
+
*/
|
|
22
|
+
async initialize() {
|
|
23
|
+
try {
|
|
24
|
+
// Ensure directories exist
|
|
25
|
+
await fs.mkdir(path.dirname(this.versionFile), { recursive: true });
|
|
26
|
+
await fs.mkdir(this.migrationDir, { recursive: true });
|
|
27
|
+
|
|
28
|
+
// Check if version info exists
|
|
29
|
+
try {
|
|
30
|
+
await fs.access(this.versionFile);
|
|
31
|
+
this.versionInfo = await this.loadVersionInfo();
|
|
32
|
+
} catch (_error) {
|
|
33
|
+
// Create initial version info
|
|
34
|
+
this.versionInfo = this.createInitialVersionInfo();
|
|
35
|
+
await this.saveVersionInfo();
|
|
36
|
+
console.log(chalk.green('✅ Version tracking initialized'));
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
this.currentVersion = this.versionInfo.current_version;
|
|
40
|
+
return this.versionInfo;
|
|
41
|
+
|
|
42
|
+
} catch (_error) {
|
|
43
|
+
console.error(chalk.red(`Version tracking initialization failed: ${error.message}`));
|
|
44
|
+
throw error;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Get current framework version
|
|
50
|
+
*/
|
|
51
|
+
async getCurrentVersion() {
|
|
52
|
+
if (!this.versionInfo) {
|
|
53
|
+
await this.initialize();
|
|
54
|
+
}
|
|
55
|
+
return this.currentVersion;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Record a new framework version
|
|
60
|
+
*/
|
|
61
|
+
async recordVersion(versionData) {
|
|
62
|
+
try {
|
|
63
|
+
const {
|
|
64
|
+
version,
|
|
65
|
+
description,
|
|
66
|
+
changes = [],
|
|
67
|
+
migration_required = false,
|
|
68
|
+
breaking_changes = [],
|
|
69
|
+
compatibility_notes = '',
|
|
70
|
+
release_notes = ''
|
|
71
|
+
} = versionData;
|
|
72
|
+
|
|
73
|
+
// Validate version format
|
|
74
|
+
if (!semver.valid(version)) {
|
|
75
|
+
throw new Error(`Invalid version format: ${version}`);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Check if version already exists
|
|
79
|
+
if (this.versionInfo.versions.some(v => v.version === version)) {
|
|
80
|
+
throw new Error(`Version ${version} already exists`);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Validate version increment
|
|
84
|
+
if (this.currentVersion && !semver.gt(version, this.currentVersion)) {
|
|
85
|
+
throw new Error(`New version ${version} must be greater than current ${this.currentVersion}`);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const versionEntry = {
|
|
89
|
+
version,
|
|
90
|
+
description,
|
|
91
|
+
timestamp: new Date().toISOString(),
|
|
92
|
+
changes,
|
|
93
|
+
migration_required,
|
|
94
|
+
breaking_changes,
|
|
95
|
+
compatibility_notes,
|
|
96
|
+
release_notes,
|
|
97
|
+
previous_version: this.currentVersion,
|
|
98
|
+
status: 'active',
|
|
99
|
+
components_modified: await this.detectModifiedComponents(),
|
|
100
|
+
api_changes: await this.detectApiChanges(),
|
|
101
|
+
deprecations: [],
|
|
102
|
+
migration_path: migration_required ? `${this.currentVersion}-to-${version}` : null
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
// Add to version history
|
|
106
|
+
this.versionInfo.versions.unshift(versionEntry);
|
|
107
|
+
this.versionInfo.current_version = version;
|
|
108
|
+
this.versionInfo.previous_version = this.currentVersion;
|
|
109
|
+
this.versionInfo.last_updated = new Date().toISOString();
|
|
110
|
+
this.versionInfo.total_versions++;
|
|
111
|
+
|
|
112
|
+
// Update current version
|
|
113
|
+
this.currentVersion = version;
|
|
114
|
+
|
|
115
|
+
// Save updated info
|
|
116
|
+
await this.saveVersionInfo();
|
|
117
|
+
|
|
118
|
+
console.log(chalk.green(`✅ Recorded new framework version: ${version}`));
|
|
119
|
+
|
|
120
|
+
if (migration_required) {
|
|
121
|
+
console.log(chalk.yellow(`⚠️ Migration required from ${this.versionInfo.previous_version} to ${version}`));
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return versionEntry;
|
|
125
|
+
|
|
126
|
+
} catch (_error) {
|
|
127
|
+
console.error(chalk.red(`Failed to record version: ${error.message}`));
|
|
128
|
+
throw error;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Get version history with optional filtering
|
|
134
|
+
*/
|
|
135
|
+
async getVersionHistory(options = {}) {
|
|
136
|
+
const {
|
|
137
|
+
limit = 10,
|
|
138
|
+
include_migrations = true,
|
|
139
|
+
include_breaking = false,
|
|
140
|
+
since_version = null,
|
|
141
|
+
status_filter = null
|
|
142
|
+
} = options;
|
|
143
|
+
|
|
144
|
+
if (!this.versionInfo) {
|
|
145
|
+
await this.initialize();
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
let versions = [...this.versionInfo.versions];
|
|
149
|
+
|
|
150
|
+
// Apply filters
|
|
151
|
+
if (since_version) {
|
|
152
|
+
const sinceIndex = versions.findIndex(v => v.version === since_version);
|
|
153
|
+
if (sinceIndex !== -1) {
|
|
154
|
+
versions = versions.slice(0, sinceIndex);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (status_filter) {
|
|
159
|
+
versions = versions.filter(v => v.status === status_filter);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (include_breaking) {
|
|
163
|
+
versions = versions.filter(v => v.breaking_changes?.length > 0);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if (!include_migrations) {
|
|
167
|
+
versions = versions.filter(v => !v.migration_required);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Apply limit
|
|
171
|
+
versions = versions.slice(0, limit);
|
|
172
|
+
|
|
173
|
+
return {
|
|
174
|
+
current_version: this.currentVersion,
|
|
175
|
+
total_versions: this.versionInfo.total_versions,
|
|
176
|
+
filtered_count: versions.length,
|
|
177
|
+
versions: versions.map(v => ({
|
|
178
|
+
version: v.version,
|
|
179
|
+
description: v.description,
|
|
180
|
+
timestamp: v.timestamp,
|
|
181
|
+
migration_required: v.migration_required,
|
|
182
|
+
breaking_changes: v.breaking_changes?.length || 0,
|
|
183
|
+
status: v.status,
|
|
184
|
+
components_modified: v.components_modified?.length || 0
|
|
185
|
+
}))
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Check compatibility between versions
|
|
191
|
+
*/
|
|
192
|
+
async checkCompatibility(fromVersion, toVersion) {
|
|
193
|
+
const compatibility = {
|
|
194
|
+
compatible: false,
|
|
195
|
+
migration_required: false,
|
|
196
|
+
breaking_changes: [],
|
|
197
|
+
warnings: [],
|
|
198
|
+
migration_path: null,
|
|
199
|
+
estimated_effort: 'unknown',
|
|
200
|
+
risk_level: 'low'
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
try {
|
|
204
|
+
// Validate versions
|
|
205
|
+
if (!semver.valid(fromVersion) || !semver.valid(toVersion)) {
|
|
206
|
+
throw new Error('Invalid version format provided');
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
const fromVersionInfo = this.versionInfo.versions.find(v => v.version === fromVersion);
|
|
210
|
+
const toVersionInfo = this.versionInfo.versions.find(v => v.version === toVersion);
|
|
211
|
+
|
|
212
|
+
if (!fromVersionInfo) {
|
|
213
|
+
compatibility.warnings.push(`Source version ${fromVersion} not found in history`);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
if (!toVersionInfo) {
|
|
217
|
+
compatibility.warnings.push(`Target version ${toVersion} not found in history`);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Check semantic version compatibility
|
|
221
|
+
const versionDiff = semver.diff(fromVersion, toVersion);
|
|
222
|
+
|
|
223
|
+
switch (versionDiff) {
|
|
224
|
+
case 'patch':
|
|
225
|
+
compatibility.compatible = true;
|
|
226
|
+
compatibility.risk_level = 'low';
|
|
227
|
+
compatibility.estimated_effort = 'minimal';
|
|
228
|
+
break;
|
|
229
|
+
|
|
230
|
+
case 'minor':
|
|
231
|
+
compatibility.compatible = true;
|
|
232
|
+
compatibility.migration_required = toVersionInfo?.migration_required || false;
|
|
233
|
+
compatibility.risk_level = 'low';
|
|
234
|
+
compatibility.estimated_effort = 'low';
|
|
235
|
+
break;
|
|
236
|
+
|
|
237
|
+
case 'major':
|
|
238
|
+
compatibility.migration_required = true;
|
|
239
|
+
compatibility.risk_level = 'high';
|
|
240
|
+
compatibility.estimated_effort = 'high';
|
|
241
|
+
compatibility.compatible = false;
|
|
242
|
+
break;
|
|
243
|
+
|
|
244
|
+
case 'premajor':
|
|
245
|
+
case 'preminor':
|
|
246
|
+
case 'prepatch':
|
|
247
|
+
compatibility.migration_required = true;
|
|
248
|
+
compatibility.risk_level = 'medium';
|
|
249
|
+
compatibility.estimated_effort = 'medium';
|
|
250
|
+
compatibility.compatible = false;
|
|
251
|
+
break;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// Collect breaking changes in the path
|
|
255
|
+
const versionsInPath = this.getVersionsInPath(fromVersion, toVersion);
|
|
256
|
+
|
|
257
|
+
for (const version of versionsInPath) {
|
|
258
|
+
if (version.breaking_changes?.length > 0) {
|
|
259
|
+
compatibility.breaking_changes.push(...version.breaking_changes);
|
|
260
|
+
compatibility.migration_required = true;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// Set migration path if needed
|
|
265
|
+
if (compatibility.migration_required) {
|
|
266
|
+
compatibility.migration_path = `${fromVersion}-to-${toVersion}`;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
return compatibility;
|
|
270
|
+
|
|
271
|
+
} catch (_error) {
|
|
272
|
+
compatibility.warnings.push(`Compatibility check failed: ${error.message}`);
|
|
273
|
+
return compatibility;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Mark a version as deprecated
|
|
279
|
+
*/
|
|
280
|
+
async deprecateVersion(version, deprecationInfo = {}) {
|
|
281
|
+
try {
|
|
282
|
+
const versionEntry = this.versionInfo.versions.find(v => v.version === version);
|
|
283
|
+
|
|
284
|
+
if (!versionEntry) {
|
|
285
|
+
throw new Error(`Version ${version} not found`);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
if (versionEntry.status === 'deprecated') {
|
|
289
|
+
throw new Error(`Version ${version} is already deprecated`);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
const deprecation = {
|
|
293
|
+
deprecated_at: new Date().toISOString(),
|
|
294
|
+
reason: deprecationInfo.reason || 'Version deprecated',
|
|
295
|
+
migration_target: deprecationInfo.migration_target || this.currentVersion,
|
|
296
|
+
removal_timeline: deprecationInfo.removal_timeline || 'TBD',
|
|
297
|
+
deprecation_notice: deprecationInfo.notice || `Version ${version} is deprecated. Please upgrade to ${this.currentVersion}.`
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
versionEntry.status = 'deprecated';
|
|
301
|
+
versionEntry.deprecation_info = deprecation;
|
|
302
|
+
|
|
303
|
+
await this.saveVersionInfo();
|
|
304
|
+
|
|
305
|
+
console.log(chalk.yellow(`⚠️ Version ${version} marked as deprecated`));
|
|
306
|
+
return deprecation;
|
|
307
|
+
|
|
308
|
+
} catch (_error) {
|
|
309
|
+
console.error(chalk.red(`Failed to deprecate version: ${error.message}`));
|
|
310
|
+
throw error;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Get migration path between versions
|
|
316
|
+
*/
|
|
317
|
+
async getMigrationPath(fromVersion, toVersion) {
|
|
318
|
+
const path = {
|
|
319
|
+
from_version: fromVersion,
|
|
320
|
+
to_version: toVersion,
|
|
321
|
+
steps: [],
|
|
322
|
+
total_migrations: 0,
|
|
323
|
+
estimated_duration: 0,
|
|
324
|
+
risk_assessment: 'low',
|
|
325
|
+
requirements: [],
|
|
326
|
+
rollback_available: true
|
|
327
|
+
};
|
|
328
|
+
|
|
329
|
+
try {
|
|
330
|
+
const versionsInPath = this.getVersionsInPath(fromVersion, toVersion);
|
|
331
|
+
|
|
332
|
+
for (const version of versionsInPath) {
|
|
333
|
+
if (version.migration_required) {
|
|
334
|
+
const step = {
|
|
335
|
+
from: version.previous_version,
|
|
336
|
+
to: version.version,
|
|
337
|
+
migration_id: version.migration_path,
|
|
338
|
+
breaking_changes: version.breaking_changes || [],
|
|
339
|
+
estimated_time: this.estimateMigrationTime(version),
|
|
340
|
+
risk_level: this.assessMigrationRisk(version),
|
|
341
|
+
prerequisites: version.migration_prerequisites || [],
|
|
342
|
+
rollback_supported: true
|
|
343
|
+
};
|
|
344
|
+
|
|
345
|
+
path.steps.push(step);
|
|
346
|
+
path.total_migrations++;
|
|
347
|
+
path.estimated_duration += step.estimated_time;
|
|
348
|
+
|
|
349
|
+
if (step.risk_level === 'high') {
|
|
350
|
+
path.risk_assessment = 'high';
|
|
351
|
+
} else if (step.risk_level === 'medium' && path.risk_assessment === 'low') {
|
|
352
|
+
path.risk_assessment = 'medium';
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
// Collect unique requirements
|
|
358
|
+
path.requirements = [...new Set(
|
|
359
|
+
path.steps.flatMap(step => step.prerequisites)
|
|
360
|
+
)];
|
|
361
|
+
|
|
362
|
+
return path;
|
|
363
|
+
|
|
364
|
+
} catch (_error) {
|
|
365
|
+
console.error(chalk.red(`Failed to get migration path: ${error.message}`));
|
|
366
|
+
throw error;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* Generate version report
|
|
372
|
+
*/
|
|
373
|
+
async generateVersionReport() {
|
|
374
|
+
if (!this.versionInfo) {
|
|
375
|
+
await this.initialize();
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
const report = {
|
|
379
|
+
timestamp: new Date().toISOString(),
|
|
380
|
+
current_version: this.currentVersion,
|
|
381
|
+
total_versions: this.versionInfo.total_versions,
|
|
382
|
+
version_distribution: {
|
|
383
|
+
active: 0,
|
|
384
|
+
deprecated: 0,
|
|
385
|
+
archived: 0
|
|
386
|
+
},
|
|
387
|
+
migration_summary: {
|
|
388
|
+
total_migrations: 0,
|
|
389
|
+
pending_migrations: 0,
|
|
390
|
+
failed_migrations: 0
|
|
391
|
+
},
|
|
392
|
+
breaking_changes_summary: {
|
|
393
|
+
total_breaking_versions: 0,
|
|
394
|
+
recent_breaking_changes: []
|
|
395
|
+
},
|
|
396
|
+
compatibility_matrix: {},
|
|
397
|
+
recommendations: []
|
|
398
|
+
};
|
|
399
|
+
|
|
400
|
+
// Analyze version distribution
|
|
401
|
+
this.versionInfo.versions.forEach(version => {
|
|
402
|
+
report.version_distribution[version.status]++;
|
|
403
|
+
|
|
404
|
+
if (version.migration_required) {
|
|
405
|
+
report.migration_summary.total_migrations++;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
if (version.breaking_changes?.length > 0) {
|
|
409
|
+
report.breaking_changes_summary.total_breaking_versions++;
|
|
410
|
+
|
|
411
|
+
if (semver.gte(version.version, semver.major(this.currentVersion) + '.0.0')) {
|
|
412
|
+
report.breaking_changes_summary.recent_breaking_changes.push({
|
|
413
|
+
version: version.version,
|
|
414
|
+
changes: version.breaking_changes.slice(0, 3)
|
|
415
|
+
});
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
});
|
|
419
|
+
|
|
420
|
+
// Generate recommendations
|
|
421
|
+
if (report.version_distribution.deprecated > 5) {
|
|
422
|
+
report.recommendations.push({
|
|
423
|
+
type: 'cleanup',
|
|
424
|
+
priority: 'medium',
|
|
425
|
+
message: `${report.version_distribution.deprecated} deprecated versions should be archived`
|
|
426
|
+
});
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
if (report.breaking_changes_summary.total_breaking_versions > 10) {
|
|
430
|
+
report.recommendations.push({
|
|
431
|
+
type: 'stability',
|
|
432
|
+
priority: 'high',
|
|
433
|
+
message: 'High number of breaking changes detected. Consider stability improvements.'
|
|
434
|
+
});
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
return report;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
// Private helper methods
|
|
441
|
+
createInitialVersionInfo() {
|
|
442
|
+
return {
|
|
443
|
+
schema_version: '1.0.0',
|
|
444
|
+
current_version: '1.0.0',
|
|
445
|
+
previous_version: null,
|
|
446
|
+
created_at: new Date().toISOString(),
|
|
447
|
+
last_updated: new Date().toISOString(),
|
|
448
|
+
total_versions: 1,
|
|
449
|
+
versions: [{
|
|
450
|
+
version: '1.0.0',
|
|
451
|
+
description: 'Initial framework version',
|
|
452
|
+
timestamp: new Date().toISOString(),
|
|
453
|
+
changes: ['Initial framework setup'],
|
|
454
|
+
migration_required: false,
|
|
455
|
+
breaking_changes: [],
|
|
456
|
+
compatibility_notes: 'Initial version',
|
|
457
|
+
release_notes: 'AIOS-FULLSTACK framework v1.0.0',
|
|
458
|
+
previous_version: null,
|
|
459
|
+
status: 'active',
|
|
460
|
+
components_modified: [],
|
|
461
|
+
api_changes: [],
|
|
462
|
+
deprecations: [],
|
|
463
|
+
migration_path: null
|
|
464
|
+
}],
|
|
465
|
+
migration_history: [],
|
|
466
|
+
compatibility_matrix: {}
|
|
467
|
+
};
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
async loadVersionInfo() {
|
|
471
|
+
try {
|
|
472
|
+
const content = await fs.readFile(this.versionFile, 'utf-8');
|
|
473
|
+
return JSON.parse(content);
|
|
474
|
+
} catch (_error) {
|
|
475
|
+
throw new Error(`Failed to load version info: ${error.message}`);
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
async saveVersionInfo() {
|
|
480
|
+
try {
|
|
481
|
+
const content = JSON.stringify(this.versionInfo, null, 2);
|
|
482
|
+
await fs.writeFile(this.versionFile, content);
|
|
483
|
+
} catch (_error) {
|
|
484
|
+
throw new Error(`Failed to save version info: ${error.message}`);
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
async detectModifiedComponents() {
|
|
489
|
+
// This would analyze git changes or compare with previous state
|
|
490
|
+
// For now, return empty array
|
|
491
|
+
return [];
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
async detectApiChanges() {
|
|
495
|
+
// This would analyze API changes between versions
|
|
496
|
+
// For now, return empty array
|
|
497
|
+
return [];
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
getVersionsInPath(fromVersion, toVersion) {
|
|
501
|
+
const versions = this.versionInfo.versions.filter(v => {
|
|
502
|
+
return semver.gt(v.version, fromVersion) && semver.lte(v.version, toVersion);
|
|
503
|
+
});
|
|
504
|
+
|
|
505
|
+
return versions.sort((a, b) => semver.compare(a.version, b.version));
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
estimateMigrationTime(version) {
|
|
509
|
+
// Simple heuristic based on breaking changes and components modified
|
|
510
|
+
const baseTime = 30; // minutes
|
|
511
|
+
const breakingChangeMultiplier = version.breaking_changes?.length || 0;
|
|
512
|
+
const componentMultiplier = version.components_modified?.length || 0;
|
|
513
|
+
|
|
514
|
+
return baseTime + (breakingChangeMultiplier * 15) + (componentMultiplier * 5);
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
assessMigrationRisk(version) {
|
|
518
|
+
const breakingChanges = version.breaking_changes?.length || 0;
|
|
519
|
+
const componentsModified = version.components_modified?.length || 0;
|
|
520
|
+
|
|
521
|
+
if (breakingChanges > 5 || componentsModified > 20) return 'high';
|
|
522
|
+
if (breakingChanges > 2 || componentsModified > 10) return 'medium';
|
|
523
|
+
return 'low';
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
|
|
527
527
|
module.exports = VersionTracker;
|