scene-capability-engine 3.6.38 → 3.6.44
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 +63 -0
- package/bin/scene-capability-engine.js +42 -2
- package/docs/command-reference.md +27 -0
- package/docs/developer-guide.md +1 -1
- package/docs/document-governance.md +22 -2
- package/docs/releases/README.md +6 -0
- package/docs/releases/v3.6.39.md +24 -0
- package/docs/releases/v3.6.40.md +19 -0
- package/docs/releases/v3.6.41.md +20 -0
- package/docs/releases/v3.6.42.md +19 -0
- package/docs/releases/v3.6.43.md +17 -0
- package/docs/releases/v3.6.44.md +17 -0
- package/docs/spec-collaboration-guide.md +1 -1
- package/docs/state-migration-reconciliation-runbook.md +76 -0
- package/docs/state-storage-tiering.md +104 -0
- package/docs/zh/releases/README.md +6 -0
- package/docs/zh/releases/v3.6.39.md +24 -0
- package/docs/zh/releases/v3.6.40.md +19 -0
- package/docs/zh/releases/v3.6.41.md +20 -0
- package/docs/zh/releases/v3.6.42.md +19 -0
- package/docs/zh/releases/v3.6.43.md +17 -0
- package/docs/zh/releases/v3.6.44.md +17 -0
- package/lib/adoption/adoption-logger.js +1 -1
- package/lib/adoption/adoption-strategy.js +29 -29
- package/lib/adoption/detection-engine.js +16 -13
- package/lib/adoption/smart-orchestrator.js +3 -3
- package/lib/adoption/strategy-selector.js +19 -15
- package/lib/adoption/template-sync.js +3 -3
- package/lib/auto/autonomous-engine.js +5 -5
- package/lib/auto/handoff-release-gate-history-loaders-service.js +24 -4
- package/lib/auto/handoff-run-service.js +37 -0
- package/lib/backup/backup-system.js +10 -10
- package/lib/collab/collab-manager.js +8 -5
- package/lib/collab/dependency-manager.js +1 -1
- package/lib/commands/adopt.js +2 -2
- package/lib/commands/auto.js +239 -97
- package/lib/commands/collab.js +10 -4
- package/lib/commands/docs.js +8 -2
- package/lib/commands/scene.js +78 -18
- package/lib/commands/status.js +3 -3
- package/lib/commands/studio.js +8 -0
- package/lib/commands/watch.js +10 -1
- package/lib/governance/config-manager.js +16 -0
- package/lib/governance/diagnostic-engine.js +2 -1
- package/lib/governance/validation-engine.js +3 -2
- package/lib/repo/config-manager.js +2 -2
- package/lib/runtime/session-store.js +8 -0
- package/lib/spec/bootstrap/context-collector.js +5 -4
- package/lib/spec-gate/rules/default-rules.js +8 -8
- package/lib/state/sce-state-store.js +265 -0
- package/lib/state/state-migration-manager.js +27 -2
- package/lib/state/state-storage-policy.js +179 -0
- package/lib/upgrade/migration-engine.js +5 -5
- package/lib/upgrade/migrations/1.0.0-to-1.1.0.js +3 -3
- package/lib/utils/tool-detector.js +4 -4
- package/lib/utils/validation.js +6 -6
- package/lib/watch/action-executor.js +10 -1
- package/lib/watch/event-debouncer.js +3 -0
- package/lib/watch/file-watcher.js +51 -10
- package/lib/watch/watch-manager.js +10 -1
- package/lib/workspace/multi/workspace-context-resolver.js +3 -3
- package/lib/workspace/multi/workspace-registry.js +3 -3
- package/lib/workspace/multi/workspace-state-manager.js +3 -3
- package/lib/workspace/spec-delivery-audit.js +553 -0
- package/lib/workspace/takeover-baseline.js +11 -0
- package/package.json +5 -1
- package/template/.sce/config/state-storage-policy.json +165 -0
|
@@ -4,6 +4,15 @@ const { promisify } = require('util');
|
|
|
4
4
|
|
|
5
5
|
const execAsync = promisify(exec);
|
|
6
6
|
|
|
7
|
+
function sleep(ms) {
|
|
8
|
+
return new Promise(resolve => {
|
|
9
|
+
const timer = setTimeout(resolve, ms);
|
|
10
|
+
if (typeof timer.unref === 'function') {
|
|
11
|
+
timer.unref();
|
|
12
|
+
}
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
|
|
7
16
|
/**
|
|
8
17
|
* ActionExecutor - 动作执行器
|
|
9
18
|
*
|
|
@@ -203,7 +212,7 @@ class ActionExecutor extends EventEmitter {
|
|
|
203
212
|
});
|
|
204
213
|
|
|
205
214
|
// 等待
|
|
206
|
-
await
|
|
215
|
+
await sleep(delay);
|
|
207
216
|
|
|
208
217
|
try {
|
|
209
218
|
// 重新执行
|
|
@@ -41,6 +41,9 @@ class FileWatcher extends EventEmitter {
|
|
|
41
41
|
};
|
|
42
42
|
this.retryCount = 0;
|
|
43
43
|
this.lastError = null;
|
|
44
|
+
this.basePath = process.cwd();
|
|
45
|
+
this.initializationTimer = null;
|
|
46
|
+
this.recoveryTimer = null;
|
|
44
47
|
}
|
|
45
48
|
|
|
46
49
|
/**
|
|
@@ -93,6 +96,8 @@ class FileWatcher extends EventEmitter {
|
|
|
93
96
|
}
|
|
94
97
|
|
|
95
98
|
try {
|
|
99
|
+
this.basePath = basePath;
|
|
100
|
+
|
|
96
101
|
// 将相对路径转换为绝对路径
|
|
97
102
|
const absolutePatterns = this.config.patterns.map(pattern => {
|
|
98
103
|
if (path.isAbsolute(pattern)) {
|
|
@@ -120,19 +125,22 @@ class FileWatcher extends EventEmitter {
|
|
|
120
125
|
|
|
121
126
|
// 等待 watcher 准备就绪
|
|
122
127
|
await new Promise((resolve, reject) => {
|
|
123
|
-
|
|
128
|
+
this._clearInitializationTimer();
|
|
129
|
+
this.initializationTimer = setTimeout(() => {
|
|
130
|
+
this.initializationTimer = null;
|
|
124
131
|
reject(new Error('FileWatcher initialization timeout'));
|
|
125
132
|
}, 10000);
|
|
133
|
+
this._unrefTimer(this.initializationTimer);
|
|
126
134
|
|
|
127
135
|
this.watcher.once('ready', () => {
|
|
128
|
-
|
|
136
|
+
this._clearInitializationTimer();
|
|
129
137
|
this.isWatching = true;
|
|
130
138
|
this.stats.startedAt = new Date();
|
|
131
139
|
resolve();
|
|
132
140
|
});
|
|
133
141
|
|
|
134
142
|
this.watcher.once('error', (error) => {
|
|
135
|
-
|
|
143
|
+
this._clearInitializationTimer();
|
|
136
144
|
reject(error);
|
|
137
145
|
});
|
|
138
146
|
});
|
|
@@ -140,6 +148,7 @@ class FileWatcher extends EventEmitter {
|
|
|
140
148
|
this.emit('started', { patterns: this.config.patterns });
|
|
141
149
|
} catch (error) {
|
|
142
150
|
this.isWatching = false;
|
|
151
|
+
await this._disposeWatcher();
|
|
143
152
|
throw error;
|
|
144
153
|
}
|
|
145
154
|
}
|
|
@@ -150,15 +159,14 @@ class FileWatcher extends EventEmitter {
|
|
|
150
159
|
* @returns {Promise<void>}
|
|
151
160
|
*/
|
|
152
161
|
async stop() {
|
|
153
|
-
if (!this.isWatching) {
|
|
162
|
+
if (!this.isWatching && !this.watcher && !this.initializationTimer && !this.recoveryTimer) {
|
|
154
163
|
return;
|
|
155
164
|
}
|
|
156
165
|
|
|
157
166
|
try {
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
}
|
|
167
|
+
this._clearInitializationTimer();
|
|
168
|
+
this._clearRecoveryTimer();
|
|
169
|
+
await this._disposeWatcher();
|
|
162
170
|
|
|
163
171
|
this.isWatching = false;
|
|
164
172
|
this.watchedFiles.clear();
|
|
@@ -300,10 +308,12 @@ class FileWatcher extends EventEmitter {
|
|
|
300
308
|
});
|
|
301
309
|
|
|
302
310
|
// 延迟后重试
|
|
303
|
-
|
|
311
|
+
this._clearRecoveryTimer();
|
|
312
|
+
this.recoveryTimer = setTimeout(async () => {
|
|
313
|
+
this.recoveryTimer = null;
|
|
304
314
|
try {
|
|
305
315
|
// 重启 watcher
|
|
306
|
-
const basePath = this.
|
|
316
|
+
const basePath = this.basePath || process.cwd();
|
|
307
317
|
|
|
308
318
|
await this.stop();
|
|
309
319
|
await this.start(basePath);
|
|
@@ -326,6 +336,7 @@ class FileWatcher extends EventEmitter {
|
|
|
326
336
|
await this._attemptRecovery(recoveryError);
|
|
327
337
|
}
|
|
328
338
|
}, this.config.retryDelay);
|
|
339
|
+
this._unrefTimer(this.recoveryTimer);
|
|
329
340
|
}
|
|
330
341
|
|
|
331
342
|
/**
|
|
@@ -494,6 +505,36 @@ class FileWatcher extends EventEmitter {
|
|
|
494
505
|
lastError: this.lastError ? this.lastError.message : null
|
|
495
506
|
};
|
|
496
507
|
}
|
|
508
|
+
|
|
509
|
+
_unrefTimer(timer) {
|
|
510
|
+
if (timer && typeof timer.unref === 'function') {
|
|
511
|
+
timer.unref();
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
_clearInitializationTimer() {
|
|
516
|
+
if (this.initializationTimer) {
|
|
517
|
+
clearTimeout(this.initializationTimer);
|
|
518
|
+
this.initializationTimer = null;
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
_clearRecoveryTimer() {
|
|
523
|
+
if (this.recoveryTimer) {
|
|
524
|
+
clearTimeout(this.recoveryTimer);
|
|
525
|
+
this.recoveryTimer = null;
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
async _disposeWatcher() {
|
|
530
|
+
if (!this.watcher) {
|
|
531
|
+
return;
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
const watcher = this.watcher;
|
|
535
|
+
this.watcher = null;
|
|
536
|
+
await watcher.close();
|
|
537
|
+
}
|
|
497
538
|
}
|
|
498
539
|
|
|
499
540
|
module.exports = FileWatcher;
|
|
@@ -6,6 +6,15 @@ const EventDebouncer = require('./event-debouncer');
|
|
|
6
6
|
const ActionExecutor = require('./action-executor');
|
|
7
7
|
const ExecutionLogger = require('./execution-logger');
|
|
8
8
|
|
|
9
|
+
function sleep(ms) {
|
|
10
|
+
return new Promise(resolve => {
|
|
11
|
+
const timer = setTimeout(resolve, ms);
|
|
12
|
+
if (typeof timer.unref === 'function') {
|
|
13
|
+
timer.unref();
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
|
|
9
18
|
/**
|
|
10
19
|
* WatchManager - Watch 模式管理器
|
|
11
20
|
*
|
|
@@ -137,7 +146,7 @@ class WatchManager extends EventEmitter {
|
|
|
137
146
|
*/
|
|
138
147
|
async restart() {
|
|
139
148
|
await this.stop();
|
|
140
|
-
await
|
|
149
|
+
await sleep(1000);
|
|
141
150
|
await this.start();
|
|
142
151
|
}
|
|
143
152
|
|
|
@@ -94,14 +94,14 @@ class WorkspaceContextResolver {
|
|
|
94
94
|
*/
|
|
95
95
|
async isValidSceDirectory(dirPath) {
|
|
96
96
|
try {
|
|
97
|
-
const
|
|
98
|
-
const exists = await fs.pathExists(
|
|
97
|
+
const scePath = path.join(dirPath, '.sce');
|
|
98
|
+
const exists = await fs.pathExists(scePath);
|
|
99
99
|
|
|
100
100
|
if (!exists) {
|
|
101
101
|
return false;
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
-
const stats = await fs.stat(
|
|
104
|
+
const stats = await fs.stat(scePath);
|
|
105
105
|
return stats.isDirectory();
|
|
106
106
|
} catch (error) {
|
|
107
107
|
return false;
|
|
@@ -84,10 +84,10 @@ class WorkspaceRegistry {
|
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
// Check if .sce directory exists
|
|
87
|
-
const
|
|
88
|
-
const
|
|
87
|
+
const scePath = path.join(workspacePath, '.sce');
|
|
88
|
+
const sceExists = await fs.pathExists(scePath);
|
|
89
89
|
|
|
90
|
-
return
|
|
90
|
+
return sceExists;
|
|
91
91
|
} catch (error) {
|
|
92
92
|
return false;
|
|
93
93
|
}
|
|
@@ -192,9 +192,9 @@ class WorkspaceStateManager {
|
|
|
192
192
|
}
|
|
193
193
|
|
|
194
194
|
// Validate path (check for .sce directory)
|
|
195
|
-
const
|
|
196
|
-
const
|
|
197
|
-
if (!
|
|
195
|
+
const scePath = path.join(workspacePath, '.sce');
|
|
196
|
+
const sceExists = await fs.pathExists(scePath);
|
|
197
|
+
if (!sceExists) {
|
|
198
198
|
throw new Error(`Path "${workspacePath}" is not a valid sce project directory. ` +
|
|
199
199
|
`Ensure it exists and contains a .sce/ directory.`);
|
|
200
200
|
}
|