scene-capability-engine 3.3.14 → 3.3.16
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/CHANGELOG.md +15 -0
- package/README.md +1 -1
- package/README.zh.md +1 -1
- package/bin/scene-capability-engine.js +4 -0
- package/docs/architecture.md +2 -2
- package/docs/command-reference.md +61 -2
- package/docs/developer-guide.md +1 -1
- package/lib/adoption/adoption-strategy.js +20 -11
- package/lib/adoption/backup-manager.js +1 -0
- package/lib/adoption/detection-engine.js +1 -0
- package/lib/adoption/file-classifier.js +3 -2
- package/lib/adoption/smart-orchestrator.js +3 -1
- package/lib/adoption/strategy-selector.js +1 -0
- package/lib/adoption/template-sync.js +1 -0
- package/lib/commands/adopt.js +2 -2
- package/lib/commands/scene.js +2 -24
- package/lib/commands/studio.js +1186 -0
- package/lib/orchestrator/orchestration-engine.js +192 -4
- package/lib/templates/registry-parser.js +23 -14
- package/lib/version/version-checker.js +11 -11
- package/lib/version/version-manager.js +9 -9
- package/package.json +1 -1
- package/template/.sce/config/studio-security.json +9 -0
- package/template/.sce/hooks/{sync-tasks-on-edit.kiro.hook → sync-tasks-on-edit.sce.hook} +1 -1
- /package/template/.sce/hooks/{check-spec-on-create.kiro.hook → check-spec-on-create.sce.hook} +0 -0
- /package/template/.sce/hooks/{run-tests-on-save.kiro.hook → run-tests-on-save.sce.hook} +0 -0
|
@@ -24,6 +24,10 @@ const DEFAULT_RATE_LIMIT_PARALLEL_FLOOR = 1;
|
|
|
24
24
|
const DEFAULT_RATE_LIMIT_COOLDOWN_MS = 45000;
|
|
25
25
|
const DEFAULT_RATE_LIMIT_LAUNCH_BUDGET_PER_MINUTE = 8;
|
|
26
26
|
const DEFAULT_RATE_LIMIT_LAUNCH_BUDGET_WINDOW_MS = 60000;
|
|
27
|
+
const DEFAULT_RATE_LIMIT_SIGNAL_WINDOW_MS = 30000;
|
|
28
|
+
const DEFAULT_RATE_LIMIT_SIGNAL_THRESHOLD = 3;
|
|
29
|
+
const DEFAULT_RATE_LIMIT_SIGNAL_EXTRA_HOLD_MS = 3000;
|
|
30
|
+
const DEFAULT_RATE_LIMIT_DYNAMIC_BUDGET_FLOOR = 1;
|
|
27
31
|
const DEFAULT_AGENT_WAIT_TIMEOUT_SECONDS = 600;
|
|
28
32
|
const AGENT_WAIT_TIMEOUT_GRACE_MS = 30000;
|
|
29
33
|
const RATE_LIMIT_BACKOFF_JITTER_RATIO = 0.5;
|
|
@@ -120,6 +124,14 @@ class OrchestrationEngine extends EventEmitter {
|
|
|
120
124
|
this._rateLimitLaunchBudgetPerMinute = DEFAULT_RATE_LIMIT_LAUNCH_BUDGET_PER_MINUTE;
|
|
121
125
|
/** @type {number} rolling window size for launch-budget throttling */
|
|
122
126
|
this._rateLimitLaunchBudgetWindowMs = DEFAULT_RATE_LIMIT_LAUNCH_BUDGET_WINDOW_MS;
|
|
127
|
+
/** @type {number|null} dynamic launch budget per minute derived from recent rate-limit pressure */
|
|
128
|
+
this._dynamicLaunchBudgetPerMinute = null;
|
|
129
|
+
/** @type {number[]} timestamps (ms) of recent rate-limit signals for spike detection */
|
|
130
|
+
this._rateLimitSignalTimestamps = [];
|
|
131
|
+
/** @type {number} rolling window for rate-limit spike detection */
|
|
132
|
+
this._rateLimitSignalWindowMs = DEFAULT_RATE_LIMIT_SIGNAL_WINDOW_MS;
|
|
133
|
+
/** @type {number} number of rate-limit signals inside window that triggers escalation */
|
|
134
|
+
this._rateLimitSignalThreshold = DEFAULT_RATE_LIMIT_SIGNAL_THRESHOLD;
|
|
123
135
|
/** @type {number[]} timestamps (ms) of recent spec launches for rolling budget accounting */
|
|
124
136
|
this._rateLimitLaunchTimestamps = [];
|
|
125
137
|
/** @type {number} last launch-budget hold telemetry emission timestamp (ms) */
|
|
@@ -1081,6 +1093,8 @@ class OrchestrationEngine extends EventEmitter {
|
|
|
1081
1093
|
this._rateLimitCooldownUntil = 0;
|
|
1082
1094
|
this._rateLimitLaunchHoldUntil = 0;
|
|
1083
1095
|
this._rateLimitLaunchTimestamps = [];
|
|
1096
|
+
this._rateLimitSignalTimestamps = [];
|
|
1097
|
+
this._dynamicLaunchBudgetPerMinute = null;
|
|
1084
1098
|
this._launchBudgetLastHoldSignalAt = 0;
|
|
1085
1099
|
this._launchBudgetLastHoldMs = 0;
|
|
1086
1100
|
this._updateStatusMonitorParallelTelemetry({
|
|
@@ -1147,11 +1161,14 @@ class OrchestrationEngine extends EventEmitter {
|
|
|
1147
1161
|
_onRateLimitSignal(retryDelayMs = 0) {
|
|
1148
1162
|
const now = this._getNow();
|
|
1149
1163
|
const launchHoldMs = this._toNonNegativeInteger(retryDelayMs, 0);
|
|
1164
|
+
this._recordRateLimitSignal(now);
|
|
1150
1165
|
if (launchHoldMs > 0) {
|
|
1151
1166
|
const currentHoldUntil = this._toNonNegativeInteger(this._rateLimitLaunchHoldUntil, 0);
|
|
1152
1167
|
this._rateLimitLaunchHoldUntil = Math.max(currentHoldUntil, now + launchHoldMs);
|
|
1153
1168
|
}
|
|
1154
1169
|
|
|
1170
|
+
this._applyRateLimitEscalation(now);
|
|
1171
|
+
|
|
1155
1172
|
if (!this._isAdaptiveParallelEnabled()) {
|
|
1156
1173
|
return;
|
|
1157
1174
|
}
|
|
@@ -1192,6 +1209,8 @@ class OrchestrationEngine extends EventEmitter {
|
|
|
1192
1209
|
* @private
|
|
1193
1210
|
*/
|
|
1194
1211
|
_maybeRecoverParallelLimit(maxParallel) {
|
|
1212
|
+
this._maybeRecoverLaunchBudget();
|
|
1213
|
+
|
|
1195
1214
|
if (!this._isAdaptiveParallelEnabled()) {
|
|
1196
1215
|
return;
|
|
1197
1216
|
}
|
|
@@ -1261,11 +1280,16 @@ class OrchestrationEngine extends EventEmitter {
|
|
|
1261
1280
|
* @private
|
|
1262
1281
|
*/
|
|
1263
1282
|
_getLaunchBudgetConfig() {
|
|
1283
|
+
const configuredBudget = this._toNonNegativeInteger(
|
|
1284
|
+
this._rateLimitLaunchBudgetPerMinute,
|
|
1285
|
+
DEFAULT_RATE_LIMIT_LAUNCH_BUDGET_PER_MINUTE
|
|
1286
|
+
);
|
|
1287
|
+
const dynamicBudget = this._dynamicLaunchBudgetPerMinute === null
|
|
1288
|
+
|| this._dynamicLaunchBudgetPerMinute === undefined
|
|
1289
|
+
? configuredBudget
|
|
1290
|
+
: this._toNonNegativeInteger(this._dynamicLaunchBudgetPerMinute, configuredBudget);
|
|
1264
1291
|
return {
|
|
1265
|
-
budgetPerMinute:
|
|
1266
|
-
this._rateLimitLaunchBudgetPerMinute,
|
|
1267
|
-
DEFAULT_RATE_LIMIT_LAUNCH_BUDGET_PER_MINUTE
|
|
1268
|
-
),
|
|
1292
|
+
budgetPerMinute: Math.min(configuredBudget, dynamicBudget),
|
|
1269
1293
|
windowMs: this._toPositiveInteger(
|
|
1270
1294
|
this._rateLimitLaunchBudgetWindowMs,
|
|
1271
1295
|
DEFAULT_RATE_LIMIT_LAUNCH_BUDGET_WINDOW_MS
|
|
@@ -1487,6 +1511,168 @@ class OrchestrationEngine extends EventEmitter {
|
|
|
1487
1511
|
return Math.max(1, Math.round(cappedBaseDelay * jitterFactor));
|
|
1488
1512
|
}
|
|
1489
1513
|
|
|
1514
|
+
/**
|
|
1515
|
+
* @param {number} now
|
|
1516
|
+
* @private
|
|
1517
|
+
*/
|
|
1518
|
+
_recordRateLimitSignal(now) {
|
|
1519
|
+
const signalAt = Number.isFinite(now) ? now : this._getNow();
|
|
1520
|
+
const windowMs = this._toPositiveInteger(
|
|
1521
|
+
this._rateLimitSignalWindowMs,
|
|
1522
|
+
DEFAULT_RATE_LIMIT_SIGNAL_WINDOW_MS
|
|
1523
|
+
);
|
|
1524
|
+
if (!Array.isArray(this._rateLimitSignalTimestamps)) {
|
|
1525
|
+
this._rateLimitSignalTimestamps = [];
|
|
1526
|
+
}
|
|
1527
|
+
this._rateLimitSignalTimestamps = this._rateLimitSignalTimestamps
|
|
1528
|
+
.filter((timestamp) => Number.isFinite(timestamp) && timestamp > (signalAt - windowMs));
|
|
1529
|
+
this._rateLimitSignalTimestamps.push(signalAt);
|
|
1530
|
+
}
|
|
1531
|
+
|
|
1532
|
+
/**
|
|
1533
|
+
* @returns {number}
|
|
1534
|
+
* @private
|
|
1535
|
+
*/
|
|
1536
|
+
_getRecentRateLimitSignalCount() {
|
|
1537
|
+
const now = this._getNow();
|
|
1538
|
+
const windowMs = this._toPositiveInteger(
|
|
1539
|
+
this._rateLimitSignalWindowMs,
|
|
1540
|
+
DEFAULT_RATE_LIMIT_SIGNAL_WINDOW_MS
|
|
1541
|
+
);
|
|
1542
|
+
if (!Array.isArray(this._rateLimitSignalTimestamps)) {
|
|
1543
|
+
this._rateLimitSignalTimestamps = [];
|
|
1544
|
+
return 0;
|
|
1545
|
+
}
|
|
1546
|
+
this._rateLimitSignalTimestamps = this._rateLimitSignalTimestamps
|
|
1547
|
+
.filter((timestamp) => Number.isFinite(timestamp) && timestamp > (now - windowMs));
|
|
1548
|
+
return this._rateLimitSignalTimestamps.length;
|
|
1549
|
+
}
|
|
1550
|
+
|
|
1551
|
+
/**
|
|
1552
|
+
* @param {number} now
|
|
1553
|
+
* @private
|
|
1554
|
+
*/
|
|
1555
|
+
_applyRateLimitEscalation(now) {
|
|
1556
|
+
const signalCount = this._getRecentRateLimitSignalCount();
|
|
1557
|
+
const threshold = this._toPositiveInteger(
|
|
1558
|
+
this._rateLimitSignalThreshold,
|
|
1559
|
+
DEFAULT_RATE_LIMIT_SIGNAL_THRESHOLD
|
|
1560
|
+
);
|
|
1561
|
+
|
|
1562
|
+
if (signalCount < threshold) {
|
|
1563
|
+
return;
|
|
1564
|
+
}
|
|
1565
|
+
|
|
1566
|
+
const maxHoldMs = this._toPositiveInteger(
|
|
1567
|
+
this._rateLimitBackoffMaxMs,
|
|
1568
|
+
DEFAULT_RATE_LIMIT_BACKOFF_MAX_MS
|
|
1569
|
+
);
|
|
1570
|
+
const escalationUnits = signalCount - threshold + 1;
|
|
1571
|
+
const extraHoldMs = Math.min(
|
|
1572
|
+
maxHoldMs,
|
|
1573
|
+
escalationUnits * DEFAULT_RATE_LIMIT_SIGNAL_EXTRA_HOLD_MS
|
|
1574
|
+
);
|
|
1575
|
+
if (extraHoldMs > 0) {
|
|
1576
|
+
const currentHoldUntil = this._toNonNegativeInteger(this._rateLimitLaunchHoldUntil, 0);
|
|
1577
|
+
this._rateLimitLaunchHoldUntil = Math.max(currentHoldUntil, now + extraHoldMs);
|
|
1578
|
+
}
|
|
1579
|
+
|
|
1580
|
+
const configuredBudget = this._toNonNegativeInteger(
|
|
1581
|
+
this._rateLimitLaunchBudgetPerMinute,
|
|
1582
|
+
DEFAULT_RATE_LIMIT_LAUNCH_BUDGET_PER_MINUTE
|
|
1583
|
+
);
|
|
1584
|
+
if (configuredBudget <= 0) {
|
|
1585
|
+
return;
|
|
1586
|
+
}
|
|
1587
|
+
|
|
1588
|
+
const currentBudget = this._toPositiveInteger(
|
|
1589
|
+
this._dynamicLaunchBudgetPerMinute == null
|
|
1590
|
+
? configuredBudget
|
|
1591
|
+
: this._dynamicLaunchBudgetPerMinute,
|
|
1592
|
+
configuredBudget
|
|
1593
|
+
);
|
|
1594
|
+
const budgetFloor = Math.max(
|
|
1595
|
+
1,
|
|
1596
|
+
Math.min(configuredBudget, DEFAULT_RATE_LIMIT_DYNAMIC_BUDGET_FLOOR)
|
|
1597
|
+
);
|
|
1598
|
+
const nextBudget = Math.max(budgetFloor, Math.floor(currentBudget / 2));
|
|
1599
|
+
if (nextBudget >= currentBudget) {
|
|
1600
|
+
return;
|
|
1601
|
+
}
|
|
1602
|
+
|
|
1603
|
+
this._dynamicLaunchBudgetPerMinute = nextBudget;
|
|
1604
|
+
const launchBudgetConfig = this._getLaunchBudgetConfig();
|
|
1605
|
+
const holdMs = this._getLaunchBudgetHoldRemainingMs();
|
|
1606
|
+
this._updateStatusMonitorLaunchBudget({
|
|
1607
|
+
event: 'throttled',
|
|
1608
|
+
budgetPerMinute: launchBudgetConfig.budgetPerMinute,
|
|
1609
|
+
windowMs: launchBudgetConfig.windowMs,
|
|
1610
|
+
used: Array.isArray(this._rateLimitLaunchTimestamps) ? this._rateLimitLaunchTimestamps.length : 0,
|
|
1611
|
+
holdMs,
|
|
1612
|
+
});
|
|
1613
|
+
this.emit('launch:budget-throttled', {
|
|
1614
|
+
reason: 'rate-limit-spike',
|
|
1615
|
+
signalCount,
|
|
1616
|
+
budgetPerMinute: launchBudgetConfig.budgetPerMinute,
|
|
1617
|
+
windowMs: launchBudgetConfig.windowMs,
|
|
1618
|
+
holdMs,
|
|
1619
|
+
});
|
|
1620
|
+
}
|
|
1621
|
+
|
|
1622
|
+
/**
|
|
1623
|
+
* @private
|
|
1624
|
+
*/
|
|
1625
|
+
_maybeRecoverLaunchBudget() {
|
|
1626
|
+
const configuredBudget = this._toNonNegativeInteger(
|
|
1627
|
+
this._rateLimitLaunchBudgetPerMinute,
|
|
1628
|
+
DEFAULT_RATE_LIMIT_LAUNCH_BUDGET_PER_MINUTE
|
|
1629
|
+
);
|
|
1630
|
+
if (configuredBudget <= 0) {
|
|
1631
|
+
this._dynamicLaunchBudgetPerMinute = null;
|
|
1632
|
+
return;
|
|
1633
|
+
}
|
|
1634
|
+
|
|
1635
|
+
const currentBudget = this._toPositiveInteger(
|
|
1636
|
+
this._dynamicLaunchBudgetPerMinute == null
|
|
1637
|
+
? configuredBudget
|
|
1638
|
+
: this._dynamicLaunchBudgetPerMinute,
|
|
1639
|
+
configuredBudget
|
|
1640
|
+
);
|
|
1641
|
+
if (currentBudget >= configuredBudget) {
|
|
1642
|
+
this._dynamicLaunchBudgetPerMinute = null;
|
|
1643
|
+
return;
|
|
1644
|
+
}
|
|
1645
|
+
|
|
1646
|
+
if (this._getNow() < this._rateLimitCooldownUntil) {
|
|
1647
|
+
return;
|
|
1648
|
+
}
|
|
1649
|
+
|
|
1650
|
+
if (this._getRecentRateLimitSignalCount() > 0) {
|
|
1651
|
+
return;
|
|
1652
|
+
}
|
|
1653
|
+
|
|
1654
|
+
const nextBudget = Math.min(configuredBudget, currentBudget + 1);
|
|
1655
|
+
this._dynamicLaunchBudgetPerMinute = nextBudget >= configuredBudget
|
|
1656
|
+
? null
|
|
1657
|
+
: nextBudget;
|
|
1658
|
+
|
|
1659
|
+
const launchBudgetConfig = this._getLaunchBudgetConfig();
|
|
1660
|
+
const holdMs = this._getLaunchBudgetHoldRemainingMs();
|
|
1661
|
+
this._updateStatusMonitorLaunchBudget({
|
|
1662
|
+
event: 'recovered',
|
|
1663
|
+
budgetPerMinute: launchBudgetConfig.budgetPerMinute,
|
|
1664
|
+
windowMs: launchBudgetConfig.windowMs,
|
|
1665
|
+
used: Array.isArray(this._rateLimitLaunchTimestamps) ? this._rateLimitLaunchTimestamps.length : 0,
|
|
1666
|
+
holdMs,
|
|
1667
|
+
});
|
|
1668
|
+
this.emit('launch:budget-recovered', {
|
|
1669
|
+
reason: 'rate-limit-cooldown',
|
|
1670
|
+
budgetPerMinute: launchBudgetConfig.budgetPerMinute,
|
|
1671
|
+
windowMs: launchBudgetConfig.windowMs,
|
|
1672
|
+
holdMs,
|
|
1673
|
+
});
|
|
1674
|
+
}
|
|
1675
|
+
|
|
1490
1676
|
/**
|
|
1491
1677
|
* Resolve final retry delay for rate-limit failures.
|
|
1492
1678
|
* Uses larger of computed backoff and retry-after hint, then clamps to configured max.
|
|
@@ -1714,6 +1900,8 @@ class OrchestrationEngine extends EventEmitter {
|
|
|
1714
1900
|
this._rateLimitCooldownUntil = 0;
|
|
1715
1901
|
this._rateLimitLaunchHoldUntil = 0;
|
|
1716
1902
|
this._rateLimitLaunchTimestamps = [];
|
|
1903
|
+
this._rateLimitSignalTimestamps = [];
|
|
1904
|
+
this._dynamicLaunchBudgetPerMinute = null;
|
|
1717
1905
|
this._launchBudgetLastHoldSignalAt = 0;
|
|
1718
1906
|
this._launchBudgetLastHoldMs = 0;
|
|
1719
1907
|
}
|
|
@@ -155,7 +155,8 @@ class RegistryParser {
|
|
|
155
155
|
// Required fields
|
|
156
156
|
const requiredFields = [
|
|
157
157
|
'id', 'name', 'category', 'description',
|
|
158
|
-
'difficulty', 'tags', 'files'
|
|
158
|
+
'difficulty', 'tags', 'applicable_scenarios', 'files',
|
|
159
|
+
'template_type', 'min_sce_version', 'risk_level', 'rollback_contract'
|
|
159
160
|
];
|
|
160
161
|
|
|
161
162
|
for (const field of requiredFields) {
|
|
@@ -213,23 +214,31 @@ class RegistryParser {
|
|
|
213
214
|
}
|
|
214
215
|
}
|
|
215
216
|
|
|
216
|
-
if (
|
|
217
|
-
|
|
218
|
-
|
|
217
|
+
if (!this.validRiskLevels.includes(template.risk_level)) {
|
|
218
|
+
errors.push(`${prefix}: Invalid risk_level "${template.risk_level}". Must be one of: ${this.validRiskLevels.join(', ')}`);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
if (!this._isPlainObject(template.rollback_contract)) {
|
|
222
|
+
errors.push(`${prefix}: Field "rollback_contract" must be an object`);
|
|
223
|
+
} else {
|
|
224
|
+
if (typeof template.rollback_contract.supported !== 'boolean') {
|
|
225
|
+
errors.push(`${prefix}: Field "rollback_contract.supported" must be boolean`);
|
|
226
|
+
}
|
|
227
|
+
if (typeof template.rollback_contract.strategy !== 'string' ||
|
|
228
|
+
template.rollback_contract.strategy.trim().length === 0) {
|
|
229
|
+
errors.push(`${prefix}: Field "rollback_contract.strategy" must be a non-empty string`);
|
|
219
230
|
}
|
|
220
231
|
}
|
|
221
232
|
|
|
222
|
-
if (
|
|
223
|
-
|
|
224
|
-
|
|
233
|
+
if (templateType === 'capability-template') {
|
|
234
|
+
const ontologyScope = template.ontology_scope;
|
|
235
|
+
if (!this._isPlainObject(ontologyScope)) {
|
|
236
|
+
errors.push(`${prefix}: capability-template requires "ontology_scope" object`);
|
|
225
237
|
} else {
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
template.rollback_contract.strategy !== null &&
|
|
231
|
-
typeof template.rollback_contract.strategy !== 'string') {
|
|
232
|
-
errors.push(`${prefix}: Field "rollback_contract.strategy" must be a string when present`);
|
|
238
|
+
const hasAnyScope = ['domains', 'entities', 'relations', 'business_rules', 'decisions']
|
|
239
|
+
.some((fieldName) => Array.isArray(ontologyScope[fieldName]) && ontologyScope[fieldName].length > 0);
|
|
240
|
+
if (!hasAnyScope) {
|
|
241
|
+
errors.push(`${prefix}: capability-template ontology_scope must include at least one non-empty scope array`);
|
|
233
242
|
}
|
|
234
243
|
}
|
|
235
244
|
}
|
|
@@ -42,20 +42,20 @@ class VersionChecker {
|
|
|
42
42
|
|
|
43
43
|
// Get current sce version
|
|
44
44
|
const packageJson = require('../../package.json');
|
|
45
|
-
const
|
|
45
|
+
const sceVersion = packageJson.version;
|
|
46
46
|
|
|
47
47
|
// Check if upgrade is needed
|
|
48
|
-
const needsUpgrade = this.versionManager.needsUpgrade(projectVersion,
|
|
48
|
+
const needsUpgrade = this.versionManager.needsUpgrade(projectVersion, sceVersion);
|
|
49
49
|
|
|
50
50
|
if (needsUpgrade) {
|
|
51
|
-
this.displayWarning(projectVersion,
|
|
51
|
+
this.displayWarning(projectVersion, sceVersion);
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
return {
|
|
55
55
|
mismatch: needsUpgrade,
|
|
56
56
|
shouldUpgrade: needsUpgrade,
|
|
57
57
|
projectVersion,
|
|
58
|
-
|
|
58
|
+
sceVersion
|
|
59
59
|
};
|
|
60
60
|
} catch (error) {
|
|
61
61
|
// Silently fail - don't block commands if version check fails
|
|
@@ -67,13 +67,13 @@ class VersionChecker {
|
|
|
67
67
|
* Displays version mismatch warning
|
|
68
68
|
*
|
|
69
69
|
* @param {string} projectVersion - Project version
|
|
70
|
-
* @param {string}
|
|
70
|
+
* @param {string} sceVersion - Current sce version
|
|
71
71
|
*/
|
|
72
|
-
displayWarning(projectVersion,
|
|
72
|
+
displayWarning(projectVersion, sceVersion) {
|
|
73
73
|
console.log();
|
|
74
74
|
console.log(chalk.yellow('⚠️ Version Mismatch Detected'));
|
|
75
75
|
console.log(chalk.gray(' Project initialized with sce'), chalk.cyan(`v${projectVersion}`));
|
|
76
|
-
console.log(chalk.gray(' Current sce version:'), chalk.cyan(`v${
|
|
76
|
+
console.log(chalk.gray(' Current sce version:'), chalk.cyan(`v${sceVersion}`));
|
|
77
77
|
console.log();
|
|
78
78
|
console.log(chalk.blue('💡 Tip:'), chalk.gray('Run'), chalk.cyan('sce upgrade'), chalk.gray('to update project templates'));
|
|
79
79
|
console.log(chalk.gray(' Or use'), chalk.cyan('--no-version-check'), chalk.gray('to suppress this warning'));
|
|
@@ -98,7 +98,7 @@ class VersionChecker {
|
|
|
98
98
|
}
|
|
99
99
|
|
|
100
100
|
const packageJson = require('../../package.json');
|
|
101
|
-
const
|
|
101
|
+
const sceVersion = packageJson.version;
|
|
102
102
|
|
|
103
103
|
console.log(chalk.blue('📦 Version Information'));
|
|
104
104
|
console.log();
|
|
@@ -110,7 +110,7 @@ class VersionChecker {
|
|
|
110
110
|
|
|
111
111
|
console.log();
|
|
112
112
|
console.log(chalk.gray('Installed:'));
|
|
113
|
-
console.log(` sce version: ${chalk.cyan(
|
|
113
|
+
console.log(` sce version: ${chalk.cyan(sceVersion)}`);
|
|
114
114
|
|
|
115
115
|
if (projectVersionInfo['upgrade-history'].length > 0) {
|
|
116
116
|
console.log();
|
|
@@ -129,12 +129,12 @@ class VersionChecker {
|
|
|
129
129
|
|
|
130
130
|
const needsUpgrade = this.versionManager.needsUpgrade(
|
|
131
131
|
projectVersionInfo['sce-version'],
|
|
132
|
-
|
|
132
|
+
sceVersion
|
|
133
133
|
);
|
|
134
134
|
|
|
135
135
|
if (needsUpgrade) {
|
|
136
136
|
console.log(chalk.yellow('⚠️ Upgrade available'));
|
|
137
|
-
console.log(chalk.gray(' Run'), chalk.cyan('sce upgrade'), chalk.gray('to update to'), chalk.cyan(`v${
|
|
137
|
+
console.log(chalk.gray(' Run'), chalk.cyan('sce upgrade'), chalk.gray('to update to'), chalk.cyan(`v${sceVersion}`));
|
|
138
138
|
} else {
|
|
139
139
|
console.log(chalk.green('✅ Project is up to date'));
|
|
140
140
|
}
|
|
@@ -88,16 +88,16 @@ class VersionManager {
|
|
|
88
88
|
/**
|
|
89
89
|
* Creates initial version info for a new project
|
|
90
90
|
*
|
|
91
|
-
* @param {string}
|
|
91
|
+
* @param {string} sceVersion - Current sce version
|
|
92
92
|
* @param {string} templateVersion - Template version (default: same as sce)
|
|
93
93
|
* @returns {VersionInfo}
|
|
94
94
|
*/
|
|
95
|
-
createVersionInfo(
|
|
95
|
+
createVersionInfo(sceVersion, templateVersion = null) {
|
|
96
96
|
const now = new Date().toISOString();
|
|
97
97
|
|
|
98
98
|
return {
|
|
99
|
-
'sce-version':
|
|
100
|
-
'template-version': templateVersion ||
|
|
99
|
+
'sce-version': sceVersion,
|
|
100
|
+
'template-version': templateVersion || sceVersion,
|
|
101
101
|
'created': now,
|
|
102
102
|
'last-upgraded': now,
|
|
103
103
|
'upgrade-history': []
|
|
@@ -141,20 +141,20 @@ class VersionManager {
|
|
|
141
141
|
* Checks if upgrade is needed
|
|
142
142
|
*
|
|
143
143
|
* @param {string} projectVersion - Current project version
|
|
144
|
-
* @param {string}
|
|
144
|
+
* @param {string} sceVersion - Installed sce version
|
|
145
145
|
* @returns {boolean}
|
|
146
146
|
*/
|
|
147
|
-
needsUpgrade(projectVersion,
|
|
148
|
-
if (!projectVersion || !
|
|
147
|
+
needsUpgrade(projectVersion, sceVersion) {
|
|
148
|
+
if (!projectVersion || !sceVersion) {
|
|
149
149
|
return false;
|
|
150
150
|
}
|
|
151
151
|
|
|
152
152
|
try {
|
|
153
153
|
// Use semver for comparison
|
|
154
|
-
return semver.lt(projectVersion,
|
|
154
|
+
return semver.lt(projectVersion, sceVersion);
|
|
155
155
|
} catch (error) {
|
|
156
156
|
// If semver comparison fails, do string comparison
|
|
157
|
-
return projectVersion !==
|
|
157
|
+
return projectVersion !== sceVersion;
|
|
158
158
|
}
|
|
159
159
|
}
|
|
160
160
|
|
package/package.json
CHANGED
|
@@ -11,6 +11,6 @@
|
|
|
11
11
|
},
|
|
12
12
|
"then": {
|
|
13
13
|
"type": "askAgent",
|
|
14
|
-
"prompt": "The tasks.md file has been updated. Please review the changes and update
|
|
14
|
+
"prompt": "The tasks.md file has been updated. Please review the changes and update workspace status if needed. Run `sce workspace sync` to synchronize."
|
|
15
15
|
}
|
|
16
16
|
}
|
/package/template/.sce/hooks/{check-spec-on-create.kiro.hook → check-spec-on-create.sce.hook}
RENAMED
|
File without changes
|
|
File without changes
|