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.
Files changed (67) hide show
  1. package/CHANGELOG.md +63 -0
  2. package/bin/scene-capability-engine.js +42 -2
  3. package/docs/command-reference.md +27 -0
  4. package/docs/developer-guide.md +1 -1
  5. package/docs/document-governance.md +22 -2
  6. package/docs/releases/README.md +6 -0
  7. package/docs/releases/v3.6.39.md +24 -0
  8. package/docs/releases/v3.6.40.md +19 -0
  9. package/docs/releases/v3.6.41.md +20 -0
  10. package/docs/releases/v3.6.42.md +19 -0
  11. package/docs/releases/v3.6.43.md +17 -0
  12. package/docs/releases/v3.6.44.md +17 -0
  13. package/docs/spec-collaboration-guide.md +1 -1
  14. package/docs/state-migration-reconciliation-runbook.md +76 -0
  15. package/docs/state-storage-tiering.md +104 -0
  16. package/docs/zh/releases/README.md +6 -0
  17. package/docs/zh/releases/v3.6.39.md +24 -0
  18. package/docs/zh/releases/v3.6.40.md +19 -0
  19. package/docs/zh/releases/v3.6.41.md +20 -0
  20. package/docs/zh/releases/v3.6.42.md +19 -0
  21. package/docs/zh/releases/v3.6.43.md +17 -0
  22. package/docs/zh/releases/v3.6.44.md +17 -0
  23. package/lib/adoption/adoption-logger.js +1 -1
  24. package/lib/adoption/adoption-strategy.js +29 -29
  25. package/lib/adoption/detection-engine.js +16 -13
  26. package/lib/adoption/smart-orchestrator.js +3 -3
  27. package/lib/adoption/strategy-selector.js +19 -15
  28. package/lib/adoption/template-sync.js +3 -3
  29. package/lib/auto/autonomous-engine.js +5 -5
  30. package/lib/auto/handoff-release-gate-history-loaders-service.js +24 -4
  31. package/lib/auto/handoff-run-service.js +37 -0
  32. package/lib/backup/backup-system.js +10 -10
  33. package/lib/collab/collab-manager.js +8 -5
  34. package/lib/collab/dependency-manager.js +1 -1
  35. package/lib/commands/adopt.js +2 -2
  36. package/lib/commands/auto.js +239 -97
  37. package/lib/commands/collab.js +10 -4
  38. package/lib/commands/docs.js +8 -2
  39. package/lib/commands/scene.js +78 -18
  40. package/lib/commands/status.js +3 -3
  41. package/lib/commands/studio.js +8 -0
  42. package/lib/commands/watch.js +10 -1
  43. package/lib/governance/config-manager.js +16 -0
  44. package/lib/governance/diagnostic-engine.js +2 -1
  45. package/lib/governance/validation-engine.js +3 -2
  46. package/lib/repo/config-manager.js +2 -2
  47. package/lib/runtime/session-store.js +8 -0
  48. package/lib/spec/bootstrap/context-collector.js +5 -4
  49. package/lib/spec-gate/rules/default-rules.js +8 -8
  50. package/lib/state/sce-state-store.js +265 -0
  51. package/lib/state/state-migration-manager.js +27 -2
  52. package/lib/state/state-storage-policy.js +179 -0
  53. package/lib/upgrade/migration-engine.js +5 -5
  54. package/lib/upgrade/migrations/1.0.0-to-1.1.0.js +3 -3
  55. package/lib/utils/tool-detector.js +4 -4
  56. package/lib/utils/validation.js +6 -6
  57. package/lib/watch/action-executor.js +10 -1
  58. package/lib/watch/event-debouncer.js +3 -0
  59. package/lib/watch/file-watcher.js +51 -10
  60. package/lib/watch/watch-manager.js +10 -1
  61. package/lib/workspace/multi/workspace-context-resolver.js +3 -3
  62. package/lib/workspace/multi/workspace-registry.js +3 -3
  63. package/lib/workspace/multi/workspace-state-manager.js +3 -3
  64. package/lib/workspace/spec-delivery-audit.js +553 -0
  65. package/lib/workspace/takeover-baseline.js +11 -0
  66. package/package.json +5 -1
  67. 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 new Promise(resolve => setTimeout(resolve, delay));
215
+ await sleep(delay);
207
216
 
208
217
  try {
209
218
  // 重新执行
@@ -71,6 +71,9 @@ class EventDebouncer extends EventEmitter {
71
71
  this.emit('error', { error, key, type: 'debounce' });
72
72
  }
73
73
  }, actualDelay);
74
+ if (typeof timer.unref === 'function') {
75
+ timer.unref();
76
+ }
74
77
 
75
78
  this.debounceTimers.set(key, timer);
76
79
  }
@@ -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
- const timeout = setTimeout(() => {
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
- clearTimeout(timeout);
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
- clearTimeout(timeout);
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
- if (this.watcher) {
159
- await this.watcher.close();
160
- this.watcher = null;
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
- setTimeout(async () => {
311
+ this._clearRecoveryTimer();
312
+ this.recoveryTimer = setTimeout(async () => {
313
+ this.recoveryTimer = null;
304
314
  try {
305
315
  // 重启 watcher
306
- const basePath = this.watcher ? this.watcher.options.cwd : process.cwd();
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 new Promise(resolve => setTimeout(resolve, 1000));
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 kiroPath = path.join(dirPath, '.sce');
98
- const exists = await fs.pathExists(kiroPath);
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(kiroPath);
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 kiroPath = path.join(workspacePath, '.sce');
88
- const kiroExists = await fs.pathExists(kiroPath);
87
+ const scePath = path.join(workspacePath, '.sce');
88
+ const sceExists = await fs.pathExists(scePath);
89
89
 
90
- return kiroExists;
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 kiroPath = path.join(workspacePath, '.sce');
196
- const kiroExists = await fs.pathExists(kiroPath);
197
- if (!kiroExists) {
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
  }