scene-capability-engine 3.0.0

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 (336) hide show
  1. package/CHANGELOG.md +2513 -0
  2. package/LICENSE +21 -0
  3. package/README.md +765 -0
  4. package/README.zh.md +630 -0
  5. package/bin/kiro-spec-engine.js +796 -0
  6. package/bin/kse.js +3 -0
  7. package/bin/sce.js +3 -0
  8. package/bin/sco.js +3 -0
  9. package/docs/331-poc-adaptation-roadmap.md +156 -0
  10. package/docs/331-poc-dual-track-integration-guide.md +120 -0
  11. package/docs/331-poc-weekly-delivery-checklist.md +52 -0
  12. package/docs/OFFLINE_INSTALL.md +96 -0
  13. package/docs/README.md +279 -0
  14. package/docs/adopt-migration-guide.md +599 -0
  15. package/docs/adoption-guide.md +616 -0
  16. package/docs/agent-hooks-analysis.md +815 -0
  17. package/docs/architecture.md +733 -0
  18. package/docs/articles/ai-driven-development-philosophy-and-practice-review.md +208 -0
  19. package/docs/articles/ai-driven-development-philosophy-and-practice.en.md +459 -0
  20. package/docs/articles/ai-driven-development-philosophy-and-practice.md +492 -0
  21. package/docs/autonomous-control-guide.md +851 -0
  22. package/docs/command-reference.md +1368 -0
  23. package/docs/community.md +115 -0
  24. package/docs/cross-tool-guide.md +555 -0
  25. package/docs/developer-guide.md +619 -0
  26. package/docs/document-governance.md +865 -0
  27. package/docs/environment-management-guide.md +526 -0
  28. package/docs/examples/add-export-command/design.md +194 -0
  29. package/docs/examples/add-export-command/requirements.md +110 -0
  30. package/docs/examples/add-export-command/tasks.md +88 -0
  31. package/docs/examples/add-rest-api/design.md +855 -0
  32. package/docs/examples/add-rest-api/requirements.md +323 -0
  33. package/docs/examples/add-rest-api/tasks.md +355 -0
  34. package/docs/examples/add-user-dashboard/design.md +192 -0
  35. package/docs/examples/add-user-dashboard/requirements.md +143 -0
  36. package/docs/examples/add-user-dashboard/tasks.md +91 -0
  37. package/docs/faq.md +697 -0
  38. package/docs/handoffs/evidence/ontology/moqui-template-baseline-2026-02-17-232922.json +156 -0
  39. package/docs/handoffs/evidence/ontology/moqui-template-baseline-2026-02-17-232922.md +24 -0
  40. package/docs/images/wechat-qr.png +0 -0
  41. package/docs/integration-modes.md +529 -0
  42. package/docs/integration-philosophy.md +313 -0
  43. package/docs/knowledge-management-guide.md +263 -0
  44. package/docs/manual-workflows-guide.md +418 -0
  45. package/docs/moqui-capability-matrix.md +73 -0
  46. package/docs/moqui-template-core-library-playbook.md +109 -0
  47. package/docs/multi-agent-coordination-guide.md +553 -0
  48. package/docs/multi-repo-management-guide.md +1344 -0
  49. package/docs/quick-start-with-ai-tools.md +375 -0
  50. package/docs/quick-start.md +146 -0
  51. package/docs/release-checklist.md +121 -0
  52. package/docs/releases/README.md +13 -0
  53. package/docs/releases/v1.46.2-validation.md +45 -0
  54. package/docs/releases/v1.46.2.md +50 -0
  55. package/docs/scene-runtime-guide.md +347 -0
  56. package/docs/spec-collaboration-guide.md +369 -0
  57. package/docs/spec-locking-guide.md +225 -0
  58. package/docs/spec-numbering-guide.md +348 -0
  59. package/docs/spec-workflow.md +519 -0
  60. package/docs/steering-strategy-guide.md +196 -0
  61. package/docs/team-collaboration-guide.md +465 -0
  62. package/docs/testing-strategy.md +272 -0
  63. package/docs/tools/claude-guide.md +654 -0
  64. package/docs/tools/cursor-guide.md +706 -0
  65. package/docs/tools/generic-guide.md +446 -0
  66. package/docs/tools/kiro-guide.md +308 -0
  67. package/docs/tools/vscode-guide.md +445 -0
  68. package/docs/tools/windsurf-guide.md +391 -0
  69. package/docs/troubleshooting.md +1135 -0
  70. package/docs/upgrade-guide.md +639 -0
  71. package/docs/value-observability-guide.md +127 -0
  72. package/docs/zh/README.md +341 -0
  73. package/docs/zh/quick-start.md +764 -0
  74. package/docs/zh/release-checklist.md +121 -0
  75. package/docs/zh/releases/README.md +13 -0
  76. package/docs/zh/releases/v1.46.2-validation.md +45 -0
  77. package/docs/zh/releases/v1.46.2.md +50 -0
  78. package/docs/zh/spec-numbering-guide.md +348 -0
  79. package/docs/zh/tools/claude-guide.md +349 -0
  80. package/docs/zh/tools/cursor-guide.md +281 -0
  81. package/docs/zh/tools/generic-guide.md +499 -0
  82. package/docs/zh/tools/kiro-guide.md +342 -0
  83. package/docs/zh/tools/vscode-guide.md +449 -0
  84. package/docs/zh/tools/windsurf-guide.md +378 -0
  85. package/docs/zh/value-observability-guide.md +127 -0
  86. package/docs//344/272/244/344/273/230/346/270/205/345/215/225.md +75 -0
  87. package/lib/adoption/adoption-logger.js +487 -0
  88. package/lib/adoption/adoption-strategy.js +538 -0
  89. package/lib/adoption/backup-manager.js +420 -0
  90. package/lib/adoption/conflict-resolver.js +410 -0
  91. package/lib/adoption/detection-engine.js +275 -0
  92. package/lib/adoption/diff-viewer.js +226 -0
  93. package/lib/adoption/error-formatter.js +509 -0
  94. package/lib/adoption/file-classifier.js +385 -0
  95. package/lib/adoption/progress-reporter.js +534 -0
  96. package/lib/adoption/smart-orchestrator.js +470 -0
  97. package/lib/adoption/strategy-selector.js +218 -0
  98. package/lib/adoption/summary-generator.js +493 -0
  99. package/lib/adoption/template-sync.js +605 -0
  100. package/lib/auto/autonomous-engine.js +485 -0
  101. package/lib/auto/checkpoint-manager.js +300 -0
  102. package/lib/auto/close-loop-runner.js +2476 -0
  103. package/lib/auto/config-schema.js +176 -0
  104. package/lib/auto/decision-engine.js +344 -0
  105. package/lib/auto/error-recovery-manager.js +580 -0
  106. package/lib/auto/goal-decomposer.js +278 -0
  107. package/lib/auto/progress-tracker.js +502 -0
  108. package/lib/auto/safety-manager.js +186 -0
  109. package/lib/auto/semantic-decomposer.js +137 -0
  110. package/lib/auto/state-manager.js +126 -0
  111. package/lib/auto/task-queue-manager.js +340 -0
  112. package/lib/backup/backup-system.js +372 -0
  113. package/lib/backup/selective-backup.js +207 -0
  114. package/lib/collab/agent-registry.js +240 -0
  115. package/lib/collab/collab-manager.js +285 -0
  116. package/lib/collab/contract-manager.js +320 -0
  117. package/lib/collab/coordinator.js +370 -0
  118. package/lib/collab/dependency-manager.js +280 -0
  119. package/lib/collab/index.js +20 -0
  120. package/lib/collab/integration-manager.js +202 -0
  121. package/lib/collab/merge-coordinator.js +252 -0
  122. package/lib/collab/metadata-manager.js +233 -0
  123. package/lib/collab/multi-agent-config.js +120 -0
  124. package/lib/collab/spec-lifecycle-manager.js +304 -0
  125. package/lib/collab/sync-barrier.js +88 -0
  126. package/lib/collab/visualizer.js +208 -0
  127. package/lib/commands/adopt.js +749 -0
  128. package/lib/commands/auto.js +19559 -0
  129. package/lib/commands/collab.js +275 -0
  130. package/lib/commands/context.js +99 -0
  131. package/lib/commands/docs.js +808 -0
  132. package/lib/commands/doctor.js +273 -0
  133. package/lib/commands/env.js +420 -0
  134. package/lib/commands/knowledge.js +309 -0
  135. package/lib/commands/lock.js +235 -0
  136. package/lib/commands/ops.js +409 -0
  137. package/lib/commands/orchestrate.js +446 -0
  138. package/lib/commands/prompt.js +105 -0
  139. package/lib/commands/repo.js +118 -0
  140. package/lib/commands/rollback.js +219 -0
  141. package/lib/commands/scene.js +15549 -0
  142. package/lib/commands/spec-bootstrap.js +147 -0
  143. package/lib/commands/spec-gate.js +157 -0
  144. package/lib/commands/spec-pipeline.js +205 -0
  145. package/lib/commands/status.js +321 -0
  146. package/lib/commands/task.js +199 -0
  147. package/lib/commands/templates.js +654 -0
  148. package/lib/commands/upgrade.js +231 -0
  149. package/lib/commands/value.js +569 -0
  150. package/lib/commands/watch.js +684 -0
  151. package/lib/commands/workflows.js +240 -0
  152. package/lib/commands/workspace-multi.js +325 -0
  153. package/lib/commands/workspace.js +189 -0
  154. package/lib/context/context-exporter.js +378 -0
  155. package/lib/context/prompt-generator.js +482 -0
  156. package/lib/data/moqui-capability-lexicon.json +45 -0
  157. package/lib/environment/backup-system.js +189 -0
  158. package/lib/environment/environment-manager.js +379 -0
  159. package/lib/environment/environment-registry.js +168 -0
  160. package/lib/gitignore/gitignore-backup.js +229 -0
  161. package/lib/gitignore/gitignore-detector.js +239 -0
  162. package/lib/gitignore/gitignore-integration.js +267 -0
  163. package/lib/gitignore/gitignore-transformer.js +193 -0
  164. package/lib/gitignore/layered-rules-template.js +42 -0
  165. package/lib/governance/archive-tool.js +284 -0
  166. package/lib/governance/cleanup-tool.js +237 -0
  167. package/lib/governance/config-manager.js +186 -0
  168. package/lib/governance/diagnostic-engine.js +271 -0
  169. package/lib/governance/doc-reference-checker.js +200 -0
  170. package/lib/governance/execution-logger.js +243 -0
  171. package/lib/governance/file-scanner.js +285 -0
  172. package/lib/governance/hooks-manager.js +333 -0
  173. package/lib/governance/reporter.js +337 -0
  174. package/lib/governance/validation-engine.js +181 -0
  175. package/lib/i18n.js +79 -0
  176. package/lib/knowledge/entry-manager.js +208 -0
  177. package/lib/knowledge/index-manager.js +261 -0
  178. package/lib/knowledge/knowledge-manager.js +273 -0
  179. package/lib/knowledge/template-manager.js +191 -0
  180. package/lib/lock/index.js +21 -0
  181. package/lib/lock/lock-file.js +192 -0
  182. package/lib/lock/lock-manager.js +321 -0
  183. package/lib/lock/machine-identifier.js +135 -0
  184. package/lib/lock/steering-file-lock.js +207 -0
  185. package/lib/lock/task-lock-manager.js +345 -0
  186. package/lib/operations/audit-logger.js +293 -0
  187. package/lib/operations/feedback-manager.js +1147 -0
  188. package/lib/operations/index.js +23 -0
  189. package/lib/operations/models/index.js +170 -0
  190. package/lib/operations/operations-manager.js +151 -0
  191. package/lib/operations/operations-validator.js +280 -0
  192. package/lib/operations/permission-manager.js +354 -0
  193. package/lib/operations/template-loader.js +143 -0
  194. package/lib/orchestrator/agent-spawner.js +629 -0
  195. package/lib/orchestrator/bootstrap-prompt-builder.js +236 -0
  196. package/lib/orchestrator/index.js +19 -0
  197. package/lib/orchestrator/orchestration-engine.js +1270 -0
  198. package/lib/orchestrator/orchestrator-config.js +173 -0
  199. package/lib/orchestrator/status-monitor.js +591 -0
  200. package/lib/python-checker.js +209 -0
  201. package/lib/repo/config-manager.js +580 -0
  202. package/lib/repo/errors/config-error.js +13 -0
  203. package/lib/repo/errors/git-error.js +15 -0
  204. package/lib/repo/errors/repo-error.js +14 -0
  205. package/lib/repo/git-operations.js +181 -0
  206. package/lib/repo/handlers/.gitkeep +1 -0
  207. package/lib/repo/handlers/exec-handler.js +155 -0
  208. package/lib/repo/handlers/health-handler.js +169 -0
  209. package/lib/repo/handlers/init-handler.js +197 -0
  210. package/lib/repo/handlers/status-handler.js +176 -0
  211. package/lib/repo/output-formatter.js +184 -0
  212. package/lib/repo/path-resolver.js +178 -0
  213. package/lib/repo/repo-manager.js +514 -0
  214. package/lib/scene-runtime/audit-emitter.js +59 -0
  215. package/lib/scene-runtime/binding-plugin-loader.js +351 -0
  216. package/lib/scene-runtime/binding-registry.js +349 -0
  217. package/lib/scene-runtime/eval-bridge.js +44 -0
  218. package/lib/scene-runtime/index.js +19 -0
  219. package/lib/scene-runtime/moqui-adapter.js +620 -0
  220. package/lib/scene-runtime/moqui-client.js +606 -0
  221. package/lib/scene-runtime/moqui-extractor.js +2029 -0
  222. package/lib/scene-runtime/plan-compiler.js +208 -0
  223. package/lib/scene-runtime/policy-gate.js +58 -0
  224. package/lib/scene-runtime/runtime-executor.js +358 -0
  225. package/lib/scene-runtime/scene-loader.js +96 -0
  226. package/lib/scene-runtime/scene-ontology.js +959 -0
  227. package/lib/scene-runtime/scene-template-linter.js +852 -0
  228. package/lib/scene-runtime/templates/scene-template-erp-query-v0.1.yaml +28 -0
  229. package/lib/scene-runtime/templates/scene-template-hybrid-shadow-v0.1.yaml +34 -0
  230. package/lib/spec/bootstrap/context-collector.js +48 -0
  231. package/lib/spec/bootstrap/draft-generator.js +158 -0
  232. package/lib/spec/bootstrap/questionnaire-engine.js +70 -0
  233. package/lib/spec/bootstrap/trace-emitter.js +59 -0
  234. package/lib/spec/multi-spec-orchestrate.js +93 -0
  235. package/lib/spec/pipeline/constants.js +6 -0
  236. package/lib/spec/pipeline/stage-adapters.js +118 -0
  237. package/lib/spec/pipeline/stage-runner.js +146 -0
  238. package/lib/spec/pipeline/state-store.js +119 -0
  239. package/lib/spec-gate/engine/gate-engine.js +165 -0
  240. package/lib/spec-gate/policy/default-policy.js +22 -0
  241. package/lib/spec-gate/policy/policy-loader.js +103 -0
  242. package/lib/spec-gate/result-emitter.js +81 -0
  243. package/lib/spec-gate/rules/default-rules.js +156 -0
  244. package/lib/spec-gate/rules/rule-registry.js +51 -0
  245. package/lib/steering/adoption-config.js +164 -0
  246. package/lib/steering/compliance-auto-fixer.js +204 -0
  247. package/lib/steering/compliance-cache.js +99 -0
  248. package/lib/steering/compliance-error-reporter.js +70 -0
  249. package/lib/steering/context-sync-manager.js +273 -0
  250. package/lib/steering/index.js +92 -0
  251. package/lib/steering/spec-steering.js +230 -0
  252. package/lib/steering/steering-compliance-checker.js +73 -0
  253. package/lib/steering/steering-loader.js +144 -0
  254. package/lib/steering/steering-manager.js +289 -0
  255. package/lib/task/index.js +12 -0
  256. package/lib/task/task-claimer.js +489 -0
  257. package/lib/task/task-status-store.js +418 -0
  258. package/lib/templates/cache-manager.js +440 -0
  259. package/lib/templates/content-generalizer.js +247 -0
  260. package/lib/templates/frontmatter-generator.js +128 -0
  261. package/lib/templates/git-handler.js +471 -0
  262. package/lib/templates/metadata-collector.js +328 -0
  263. package/lib/templates/path-utils.js +144 -0
  264. package/lib/templates/registry-parser.js +505 -0
  265. package/lib/templates/spec-reader.js +216 -0
  266. package/lib/templates/template-applicator.js +249 -0
  267. package/lib/templates/template-creator.js +256 -0
  268. package/lib/templates/template-error.js +143 -0
  269. package/lib/templates/template-exporter.js +502 -0
  270. package/lib/templates/template-manager.js +782 -0
  271. package/lib/templates/template-validator.js +361 -0
  272. package/lib/upgrade/migration-engine.js +382 -0
  273. package/lib/upgrade/migrations/.gitkeep +52 -0
  274. package/lib/upgrade/migrations/1.0.0-to-1.1.0.js +78 -0
  275. package/lib/utils/file-diff.js +177 -0
  276. package/lib/utils/fs-utils.js +274 -0
  277. package/lib/utils/tool-detector.js +383 -0
  278. package/lib/utils/validation.js +324 -0
  279. package/lib/value/gate-summary-emitter.js +99 -0
  280. package/lib/value/metric-contract-loader.js +210 -0
  281. package/lib/value/risk-evaluator.js +117 -0
  282. package/lib/value/weekly-snapshot-builder.js +61 -0
  283. package/lib/version/version-checker.js +156 -0
  284. package/lib/version/version-manager.js +327 -0
  285. package/lib/watch/action-executor.js +458 -0
  286. package/lib/watch/event-debouncer.js +323 -0
  287. package/lib/watch/execution-logger.js +550 -0
  288. package/lib/watch/file-watcher.js +499 -0
  289. package/lib/watch/presets.js +266 -0
  290. package/lib/watch/watch-manager.js +533 -0
  291. package/lib/workspace/multi/global-config.js +150 -0
  292. package/lib/workspace/multi/index.js +22 -0
  293. package/lib/workspace/multi/path-utils.js +173 -0
  294. package/lib/workspace/multi/workspace-context-resolver.js +244 -0
  295. package/lib/workspace/multi/workspace-registry.js +196 -0
  296. package/lib/workspace/multi/workspace-state-manager.js +537 -0
  297. package/lib/workspace/multi/workspace.js +90 -0
  298. package/lib/workspace/workspace-manager.js +370 -0
  299. package/lib/workspace/workspace-sync.js +356 -0
  300. package/locales/en.json +114 -0
  301. package/locales/zh.json +114 -0
  302. package/package.json +102 -0
  303. package/template/.kiro/README.md +247 -0
  304. package/template/.kiro/hooks/check-spec-on-create.kiro.hook +17 -0
  305. package/template/.kiro/hooks/run-tests-on-save.kiro.hook +13 -0
  306. package/template/.kiro/hooks/sync-tasks-on-edit.kiro.hook +16 -0
  307. package/template/.kiro/specs/SPEC_WORKFLOW_GUIDE.md +134 -0
  308. package/template/.kiro/steering/CORE_PRINCIPLES.md +133 -0
  309. package/template/.kiro/steering/CURRENT_CONTEXT.md +30 -0
  310. package/template/.kiro/steering/ENVIRONMENT.md +35 -0
  311. package/template/.kiro/steering/RULES_GUIDE.md +46 -0
  312. package/template/.kiro/templates/operations/default/change-impact.md +112 -0
  313. package/template/.kiro/templates/operations/default/deployment.md +91 -0
  314. package/template/.kiro/templates/operations/default/feedback-response.md +269 -0
  315. package/template/.kiro/templates/operations/default/migration-plan.md +172 -0
  316. package/template/.kiro/templates/operations/default/monitoring.md +135 -0
  317. package/template/.kiro/templates/operations/default/operations.md +135 -0
  318. package/template/.kiro/templates/operations/default/rollback.md +143 -0
  319. package/template/.kiro/templates/operations/default/tools.yaml +364 -0
  320. package/template/.kiro/templates/operations/default/troubleshooting.md +123 -0
  321. package/template/.kiro/tools/backup_manager.py +295 -0
  322. package/template/.kiro/tools/configuration_manager.py +218 -0
  323. package/template/.kiro/tools/document_evaluator.py +550 -0
  324. package/template/.kiro/tools/enhancement_logger.py +168 -0
  325. package/template/.kiro/tools/error_handler.py +335 -0
  326. package/template/.kiro/tools/improvement_identifier.py +444 -0
  327. package/template/.kiro/tools/modification_applicator.py +737 -0
  328. package/template/.kiro/tools/quality_gate_enforcer.py +207 -0
  329. package/template/.kiro/tools/quality_scorer.py +305 -0
  330. package/template/.kiro/tools/report_generator.py +154 -0
  331. package/template/.kiro/tools/ultrawork_enhancer.py +676 -0
  332. package/template/.kiro/tools/ultrawork_enhancer_refactored.py +0 -0
  333. package/template/.kiro/tools/ultrawork_enhancer_v2.py +463 -0
  334. package/template/.kiro/tools/ultrawork_enhancer_v3.py +606 -0
  335. package/template/.kiro/tools/workflow_quality_gate.py +100 -0
  336. package/template/README.md +111 -0
@@ -0,0 +1,533 @@
1
+ const EventEmitter = require('events');
2
+ const fs = require('fs-extra');
3
+ const path = require('path');
4
+ const FileWatcher = require('./file-watcher');
5
+ const EventDebouncer = require('./event-debouncer');
6
+ const ActionExecutor = require('./action-executor');
7
+ const ExecutionLogger = require('./execution-logger');
8
+
9
+ /**
10
+ * WatchManager - Watch 模式管理器
11
+ *
12
+ * 协调所有 watch 组件,管理生命周期
13
+ */
14
+ class WatchManager extends EventEmitter {
15
+ constructor(config = {}) {
16
+ super();
17
+
18
+ this.config = {
19
+ configFile: config.configFile || '.kiro/watch-config.json',
20
+ basePath: config.basePath || process.cwd(),
21
+ autoStart: config.autoStart !== false,
22
+ ...config
23
+ };
24
+
25
+ // 组件实例
26
+ this.fileWatcher = null;
27
+ this.debouncer = null;
28
+ this.executor = null;
29
+ this.logger = null;
30
+
31
+ // 状态
32
+ this.isRunning = false;
33
+ this.watchConfig = null;
34
+
35
+ // 统计信息
36
+ this.stats = {
37
+ startedAt: null,
38
+ stoppedAt: null,
39
+ filesWatched: 0,
40
+ eventsProcessed: 0,
41
+ actionsExecuted: 0
42
+ };
43
+ }
44
+
45
+ /**
46
+ * 启动 watch 模式
47
+ *
48
+ * @param {Object} config - 配置(可选,如果不提供则从文件加载)
49
+ * @returns {Promise<void>}
50
+ */
51
+ async start(config = null) {
52
+ if (this.isRunning) {
53
+ throw new Error('WatchManager is already running');
54
+ }
55
+
56
+ try {
57
+ // 1. 加载配置
58
+ if (config) {
59
+ this.watchConfig = config;
60
+ } else {
61
+ this.watchConfig = await this.loadConfig();
62
+ }
63
+
64
+ // 2. 验证配置
65
+ this._validateConfig(this.watchConfig);
66
+
67
+ // 3. 初始化组件
68
+ await this._initializeComponents();
69
+
70
+ // 4. 启动文件监控
71
+ await this._startWatching();
72
+
73
+ // 5. 更新状态
74
+ this.isRunning = true;
75
+ this.stats.startedAt = new Date();
76
+
77
+ this.emit('started', {
78
+ config: this.watchConfig,
79
+ timestamp: new Date()
80
+ });
81
+
82
+ } catch (error) {
83
+ this.isRunning = false;
84
+ this.emit('error', {
85
+ message: 'Failed to start watch mode',
86
+ error,
87
+ timestamp: new Date()
88
+ });
89
+ throw error;
90
+ }
91
+ }
92
+
93
+ /**
94
+ * 停止 watch 模式
95
+ *
96
+ * @returns {Promise<void>}
97
+ */
98
+ async stop() {
99
+ if (!this.isRunning) {
100
+ return;
101
+ }
102
+
103
+ try {
104
+ // 1. 停止文件监控
105
+ if (this.fileWatcher) {
106
+ await this.fileWatcher.stop();
107
+ }
108
+
109
+ // 2. 清理 debouncer
110
+ if (this.debouncer) {
111
+ this.debouncer.clear();
112
+ }
113
+
114
+ // 3. 更新状态
115
+ this.isRunning = false;
116
+ this.stats.stoppedAt = new Date();
117
+
118
+ this.emit('stopped', {
119
+ stats: this.getStats(),
120
+ timestamp: new Date()
121
+ });
122
+
123
+ } catch (error) {
124
+ this.emit('error', {
125
+ message: 'Failed to stop watch mode',
126
+ error,
127
+ timestamp: new Date()
128
+ });
129
+ throw error;
130
+ }
131
+ }
132
+
133
+ /**
134
+ * 重启 watch 模式
135
+ *
136
+ * @returns {Promise<void>}
137
+ */
138
+ async restart() {
139
+ await this.stop();
140
+ await new Promise(resolve => setTimeout(resolve, 1000));
141
+ await this.start();
142
+ }
143
+
144
+ /**
145
+ * 初始化组件
146
+ *
147
+ * @private
148
+ * @returns {Promise<void>}
149
+ */
150
+ async _initializeComponents() {
151
+ // 1. 初始化 logger
152
+ this.logger = new ExecutionLogger({
153
+ logDir: path.join(this.config.basePath, '.kiro/watch/logs'),
154
+ logLevel: this.watchConfig.logging?.level || 'info',
155
+ maxLogSize: this._parseSize(this.watchConfig.logging?.maxSize || '10MB'),
156
+ enableRotation: this.watchConfig.logging?.rotation !== false
157
+ });
158
+
159
+ // 2. 初始化 executor
160
+ this.executor = new ActionExecutor({
161
+ maxRetries: this.watchConfig.retry?.maxAttempts || 3,
162
+ retryBackoff: this.watchConfig.retry?.backoff || 'exponential',
163
+ cwd: this.config.basePath
164
+ });
165
+
166
+ // 监听执行事件
167
+ this.executor.on('execution:success', (data) => {
168
+ this.logger.info('execution:success', data);
169
+ this.stats.actionsExecuted++;
170
+ });
171
+
172
+ this.executor.on('execution:error', (data) => {
173
+ this.logger.error('execution:error', data);
174
+ });
175
+
176
+ // 3. 初始化 debouncer
177
+ this.debouncer = new EventDebouncer({
178
+ defaultDelay: this.watchConfig.debounce?.default || 2000
179
+ });
180
+
181
+ // 4. 初始化 file watcher
182
+ this.fileWatcher = new FileWatcher({
183
+ patterns: this.watchConfig.patterns || [],
184
+ ignored: this.watchConfig.ignored || [],
185
+ persistent: true
186
+ });
187
+
188
+ // 监听文件事件
189
+ this.fileWatcher.on('file:changed', (data) => this._handleFileEvent('changed', data));
190
+ this.fileWatcher.on('file:added', (data) => this._handleFileEvent('added', data));
191
+ this.fileWatcher.on('file:deleted', (data) => this._handleFileEvent('deleted', data));
192
+ }
193
+
194
+ /**
195
+ * 启动文件监控
196
+ *
197
+ * @private
198
+ * @returns {Promise<void>}
199
+ */
200
+ async _startWatching() {
201
+ await this.fileWatcher.start(this.config.basePath);
202
+ this.stats.filesWatched = this.fileWatcher.getWatchedFiles().length;
203
+ }
204
+
205
+ /**
206
+ * 处理文件事件
207
+ *
208
+ * @private
209
+ * @param {string} eventType - 事件类型
210
+ * @param {Object} data - 事件数据
211
+ */
212
+ _handleFileEvent(eventType, data) {
213
+ this.stats.eventsProcessed++;
214
+
215
+ // 查找匹配的动作
216
+ const action = this._findMatchingAction(data.path);
217
+
218
+ if (!action) {
219
+ this.logger.debug('no_action_found', {
220
+ file: data.path,
221
+ eventType
222
+ });
223
+ return;
224
+ }
225
+
226
+ // 获取 debounce 延迟
227
+ const delay = action.debounce ||
228
+ this.watchConfig.debounce?.perPattern?.[data.path] ||
229
+ this.watchConfig.debounce?.default ||
230
+ 2000;
231
+
232
+ // 使用 debouncer 处理
233
+ this.debouncer.debounce(
234
+ data.path,
235
+ async () => {
236
+ await this._executeAction(action, data);
237
+ },
238
+ delay
239
+ );
240
+ }
241
+
242
+ /**
243
+ * 查找匹配的动作
244
+ *
245
+ * @private
246
+ * @param {string} filePath - 文件路径
247
+ * @returns {Object|null} 动作配置
248
+ */
249
+ _findMatchingAction(filePath) {
250
+ if (!this.watchConfig.actions) {
251
+ return null;
252
+ }
253
+
254
+ // 规范化路径
255
+ const normalizedPath = filePath.replace(/\\/g, '/');
256
+
257
+ // 查找匹配的模式
258
+ for (const [pattern, action] of Object.entries(this.watchConfig.actions)) {
259
+ // 使用 FileWatcher 的 matchesPattern 方法
260
+ // 但需要创建一个临时的 FileWatcher 来测试模式
261
+ const { minimatch } = require('minimatch');
262
+
263
+ if (minimatch(normalizedPath, pattern, { dot: true })) {
264
+ return action;
265
+ }
266
+ }
267
+
268
+ return null;
269
+ }
270
+
271
+ /**
272
+ * 执行动作
273
+ *
274
+ * @private
275
+ * @param {Object} action - 动作配置
276
+ * @param {Object} fileData - 文件数据
277
+ * @returns {Promise<void>}
278
+ */
279
+ async _executeAction(action, fileData) {
280
+ try {
281
+ const context = {
282
+ file: fileData.path,
283
+ event: fileData.event,
284
+ timestamp: fileData.timestamp
285
+ };
286
+
287
+ await this.executor.execute(action, context);
288
+
289
+ } catch (error) {
290
+ this.emit('action:error', {
291
+ action,
292
+ file: fileData.path,
293
+ error,
294
+ timestamp: new Date()
295
+ });
296
+ }
297
+ }
298
+
299
+ /**
300
+ * 验证配置
301
+ *
302
+ * @private
303
+ * @param {Object} config - 配置
304
+ */
305
+ _validateConfig(config) {
306
+ if (!config) {
307
+ throw new Error('Configuration is required');
308
+ }
309
+
310
+ if (!config.patterns || !Array.isArray(config.patterns) || config.patterns.length === 0) {
311
+ throw new Error('At least one pattern is required');
312
+ }
313
+
314
+ if (config.actions && typeof config.actions !== 'object') {
315
+ throw new Error('Actions must be an object');
316
+ }
317
+ }
318
+
319
+ /**
320
+ * 解析大小字符串
321
+ *
322
+ * @private
323
+ * @param {string} sizeStr - 大小字符串(如 '10MB')
324
+ * @returns {number} 字节数
325
+ */
326
+ _parseSize(sizeStr) {
327
+ const units = {
328
+ B: 1,
329
+ KB: 1024,
330
+ MB: 1024 * 1024,
331
+ GB: 1024 * 1024 * 1024
332
+ };
333
+
334
+ const match = sizeStr.match(/^(\d+(?:\.\d+)?)\s*([A-Z]+)$/i);
335
+ if (!match) {
336
+ throw new Error(`Invalid size format: ${sizeStr}`);
337
+ }
338
+
339
+ const value = parseFloat(match[1]);
340
+ const unit = match[2].toUpperCase();
341
+
342
+ if (!units[unit]) {
343
+ throw new Error(`Unknown size unit: ${unit}`);
344
+ }
345
+
346
+ return Math.floor(value * units[unit]);
347
+ }
348
+
349
+ /**
350
+ * 加载配置
351
+ *
352
+ * @returns {Promise<Object>} 配置对象
353
+ */
354
+ async loadConfig() {
355
+ const configPath = path.join(this.config.basePath, this.config.configFile);
356
+
357
+ try {
358
+ if (!await fs.pathExists(configPath)) {
359
+ // 返回默认配置
360
+ return this._getDefaultConfig();
361
+ }
362
+
363
+ const config = await fs.readJson(configPath);
364
+
365
+ this.emit('config:loaded', {
366
+ configPath,
367
+ timestamp: new Date()
368
+ });
369
+
370
+ return config;
371
+
372
+ } catch (error) {
373
+ this.emit('error', {
374
+ message: 'Failed to load configuration',
375
+ error,
376
+ configPath,
377
+ timestamp: new Date()
378
+ });
379
+ throw error;
380
+ }
381
+ }
382
+
383
+ /**
384
+ * 保存配置
385
+ *
386
+ * @param {Object} config - 配置对象
387
+ * @returns {Promise<void>}
388
+ */
389
+ async saveConfig(config) {
390
+ const configPath = path.join(this.config.basePath, this.config.configFile);
391
+
392
+ try {
393
+ // 验证配置
394
+ this._validateConfig(config);
395
+
396
+ // 确保目录存在
397
+ await fs.ensureDir(path.dirname(configPath));
398
+
399
+ // 保存配置
400
+ await fs.writeJson(configPath, config, { spaces: 2 });
401
+
402
+ this.emit('config:saved', {
403
+ configPath,
404
+ timestamp: new Date()
405
+ });
406
+
407
+ } catch (error) {
408
+ this.emit('error', {
409
+ message: 'Failed to save configuration',
410
+ error,
411
+ configPath,
412
+ timestamp: new Date()
413
+ });
414
+ throw error;
415
+ }
416
+ }
417
+
418
+ /**
419
+ * 获取默认配置
420
+ *
421
+ * @private
422
+ * @returns {Object} 默认配置
423
+ */
424
+ _getDefaultConfig() {
425
+ return {
426
+ enabled: true,
427
+ patterns: ['**/*.md'],
428
+ ignored: ['**/node_modules/**', '**/.git/**'],
429
+ actions: {},
430
+ debounce: {
431
+ default: 2000
432
+ },
433
+ logging: {
434
+ enabled: true,
435
+ level: 'info',
436
+ maxSize: '10MB',
437
+ rotation: true
438
+ },
439
+ retry: {
440
+ enabled: true,
441
+ maxAttempts: 3,
442
+ backoff: 'exponential'
443
+ }
444
+ };
445
+ }
446
+
447
+ /**
448
+ * 获取状态
449
+ *
450
+ * @returns {Object} 状态信息
451
+ */
452
+ getStatus() {
453
+ return {
454
+ isRunning: this.isRunning,
455
+ config: this.watchConfig,
456
+ stats: this.getStats(),
457
+ components: {
458
+ fileWatcher: this.fileWatcher ? this.fileWatcher.getStatus() : null,
459
+ debouncer: this.debouncer ? this.debouncer.getStats() : null,
460
+ executor: this.executor ? this.executor.getStats() : null,
461
+ logger: this.logger ? this.logger.getMetrics() : null
462
+ }
463
+ };
464
+ }
465
+
466
+ /**
467
+ * 获取统计信息
468
+ *
469
+ * @returns {Object} 统计信息
470
+ */
471
+ getStats() {
472
+ const stats = { ...this.stats };
473
+
474
+ if (stats.startedAt && this.isRunning) {
475
+ stats.uptime = Date.now() - stats.startedAt.getTime();
476
+ }
477
+
478
+ return stats;
479
+ }
480
+
481
+ /**
482
+ * 获取日志
483
+ *
484
+ * @param {number} lines - 行数
485
+ * @returns {Promise<Array>} 日志条目
486
+ */
487
+ async getLogs(lines = 100) {
488
+ if (!this.logger) {
489
+ return [];
490
+ }
491
+
492
+ return await this.logger.readLogs(lines);
493
+ }
494
+
495
+ /**
496
+ * 获取指标
497
+ *
498
+ * @returns {Object} 指标数据
499
+ */
500
+ getMetrics() {
501
+ if (!this.logger) {
502
+ return {
503
+ totalExecutions: 0,
504
+ successfulExecutions: 0,
505
+ failedExecutions: 0,
506
+ successRate: 0,
507
+ averageDuration: 0,
508
+ timeSaved: 0,
509
+ byAction: {},
510
+ errors: []
511
+ };
512
+ }
513
+
514
+ return this.logger.getMetrics();
515
+ }
516
+
517
+ /**
518
+ * 导出指标
519
+ *
520
+ * @param {string} format - 格式
521
+ * @param {string} outputPath - 输出路径
522
+ * @returns {Promise<string>} 输出文件路径
523
+ */
524
+ async exportMetrics(format = 'json', outputPath = null) {
525
+ if (!this.logger) {
526
+ throw new Error('Logger not initialized');
527
+ }
528
+
529
+ return await this.logger.exportMetrics(format, outputPath);
530
+ }
531
+ }
532
+
533
+ module.exports = WatchManager;
@@ -0,0 +1,150 @@
1
+ const WorkspaceStateManager = require('./workspace-state-manager');
2
+
3
+ /**
4
+ * GlobalConfig - Facade for WorkspaceStateManager
5
+ *
6
+ * Provides backward-compatible API for global configuration operations.
7
+ * All operations are delegated to WorkspaceStateManager which implements
8
+ * the Data Atomicity Principle (single source of truth).
9
+ *
10
+ * @deprecated This class is a compatibility layer. New code should use
11
+ * WorkspaceStateManager directly.
12
+ */
13
+ class GlobalConfig {
14
+ /**
15
+ * Create a new GlobalConfig instance
16
+ *
17
+ * @param {string} configPath - Path to workspace-state.json (optional)
18
+ */
19
+ constructor(configPath = null) {
20
+ // Delegate to WorkspaceStateManager
21
+ this.stateManager = new WorkspaceStateManager(configPath);
22
+ // Expose configPath for backward compatibility
23
+ this.configPath = this.stateManager.statePath;
24
+ }
25
+
26
+ /**
27
+ * Get the default configuration file path
28
+ *
29
+ * @returns {string} Path to ~/.kse/workspace-state.json
30
+ * @deprecated Use WorkspaceStateManager.getDefaultStatePath() instead
31
+ */
32
+ getDefaultConfigPath() {
33
+ return this.stateManager.getDefaultStatePath();
34
+ }
35
+
36
+ /**
37
+ * Load configuration from disk
38
+ *
39
+ * @returns {Promise<boolean>} True if loaded successfully
40
+ */
41
+ async load() {
42
+ return await this.stateManager.load();
43
+ }
44
+
45
+ /**
46
+ * Save configuration to disk
47
+ *
48
+ * @returns {Promise<boolean>} True if saved successfully
49
+ */
50
+ async save() {
51
+ return await this.stateManager.save();
52
+ }
53
+
54
+ /**
55
+ * Ensure config is loaded before operations
56
+ *
57
+ * @private
58
+ */
59
+ async ensureLoaded() {
60
+ await this.stateManager.ensureLoaded();
61
+ }
62
+
63
+ /**
64
+ * Get the active workspace name
65
+ *
66
+ * @returns {Promise<string|null>} Active workspace name or null
67
+ */
68
+ async getActiveWorkspace() {
69
+ await this.ensureLoaded();
70
+ // Return the active workspace name directly from state
71
+ // This maintains backward compatibility with tests that set
72
+ // active workspace without creating the workspace first
73
+ return this.stateManager.state.activeWorkspace;
74
+ }
75
+
76
+ /**
77
+ * Set the active workspace
78
+ *
79
+ * @param {string|null} name - Workspace name or null to clear
80
+ * @returns {Promise<void>}
81
+ */
82
+ async setActiveWorkspace(name) {
83
+ await this.ensureLoaded();
84
+
85
+ if (name === null) {
86
+ await this.stateManager.clearActiveWorkspace();
87
+ } else {
88
+ // Check if workspace exists before switching
89
+ const workspace = await this.stateManager.getWorkspace(name);
90
+ if (!workspace) {
91
+ // For backward compatibility, just set the name without validation
92
+ // This allows tests to set active workspace without creating it first
93
+ this.stateManager.state.activeWorkspace = name;
94
+ await this.stateManager.save();
95
+ } else {
96
+ await this.stateManager.switchWorkspace(name);
97
+ }
98
+ }
99
+ }
100
+
101
+ /**
102
+ * Clear the active workspace
103
+ *
104
+ * @returns {Promise<void>}
105
+ */
106
+ async clearActiveWorkspace() {
107
+ await this.stateManager.clearActiveWorkspace();
108
+ }
109
+
110
+ /**
111
+ * Get a preference value
112
+ *
113
+ * @param {string} key - Preference key (camelCase)
114
+ * @returns {Promise<any>} Preference value
115
+ */
116
+ async getPreference(key) {
117
+ return await this.stateManager.getPreference(key);
118
+ }
119
+
120
+ /**
121
+ * Set a preference value
122
+ *
123
+ * @param {string} key - Preference key (camelCase)
124
+ * @param {any} value - Preference value
125
+ * @returns {Promise<void>}
126
+ */
127
+ async setPreference(key, value) {
128
+ await this.stateManager.setPreference(key, value);
129
+ }
130
+
131
+ /**
132
+ * Get all preferences
133
+ *
134
+ * @returns {Promise<Object>} All preferences
135
+ */
136
+ async getPreferences() {
137
+ return await this.stateManager.getPreferences();
138
+ }
139
+
140
+ /**
141
+ * Reset configuration to defaults
142
+ *
143
+ * @returns {Promise<void>}
144
+ */
145
+ async reset() {
146
+ await this.stateManager.reset();
147
+ }
148
+ }
149
+
150
+ module.exports = GlobalConfig;
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Multi-Workspace Management Module
3
+ *
4
+ * Exports core components for multi-workspace functionality.
5
+ * Part of Spec 16-00: Multi-Workspace Management.
6
+ */
7
+
8
+ const Workspace = require('./workspace');
9
+ const WorkspaceRegistry = require('./workspace-registry');
10
+ const GlobalConfig = require('./global-config');
11
+ const WorkspaceContextResolver = require('./workspace-context-resolver');
12
+ const PathUtils = require('./path-utils');
13
+ const WorkspaceStateManager = require('./workspace-state-manager');
14
+
15
+ module.exports = {
16
+ Workspace,
17
+ WorkspaceRegistry,
18
+ GlobalConfig,
19
+ WorkspaceContextResolver,
20
+ PathUtils,
21
+ WorkspaceStateManager
22
+ };