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,274 @@
1
+ /**
2
+ * File System Utilities
3
+ *
4
+ * Provides safe, atomic file operations for the adoption/upgrade system.
5
+ * Implements path validation, atomic writes, and error handling.
6
+ */
7
+
8
+ const fs = require('fs-extra');
9
+ const path = require('path');
10
+ const os = require('os');
11
+
12
+ /**
13
+ * Validates that a file path is within the project directory
14
+ * Prevents path traversal attacks
15
+ *
16
+ * @param {string} projectPath - Absolute path to project root
17
+ * @param {string} filePath - Relative or absolute file path to validate
18
+ * @returns {string} - Validated absolute path
19
+ * @throws {Error} - If path traversal is detected
20
+ */
21
+ function validatePath(projectPath, filePath) {
22
+ const resolvedProject = path.resolve(projectPath);
23
+ const resolvedFile = path.resolve(projectPath, filePath);
24
+
25
+ if (!resolvedFile.startsWith(resolvedProject)) {
26
+ throw new Error(`Path traversal detected: ${filePath} is outside project directory`);
27
+ }
28
+
29
+ return resolvedFile;
30
+ }
31
+
32
+ /**
33
+ * Atomically writes content to a file
34
+ * Uses temp file + rename for atomicity
35
+ *
36
+ * @param {string} filePath - Absolute path to target file
37
+ * @param {string} content - Content to write
38
+ * @returns {Promise<void>}
39
+ */
40
+ async function atomicWrite(filePath, content) {
41
+ const tempPath = `${filePath}.tmp.${Date.now()}.${Math.random().toString(36).substr(2, 9)}`;
42
+
43
+ try {
44
+ // Write to temp file
45
+ await fs.writeFile(tempPath, content, 'utf8');
46
+
47
+ // Atomic rename (on most systems)
48
+ await fs.rename(tempPath, filePath);
49
+ } catch (error) {
50
+ // Clean up temp file if it exists
51
+ try {
52
+ await fs.unlink(tempPath);
53
+ } catch (cleanupError) {
54
+ // Ignore cleanup errors
55
+ }
56
+
57
+ throw new Error(`Failed to write file atomically: ${error.message}`);
58
+ }
59
+ }
60
+
61
+ /**
62
+ * Safely copies a file with error handling
63
+ * Creates parent directories if needed
64
+ *
65
+ * @param {string} sourcePath - Absolute path to source file
66
+ * @param {string} destPath - Absolute path to destination file
67
+ * @param {Object} options - Copy options
68
+ * @param {boolean} options.overwrite - Whether to overwrite existing file (default: false)
69
+ * @returns {Promise<void>}
70
+ */
71
+ async function safeCopy(sourcePath, destPath, options = {}) {
72
+ const { overwrite = false } = options;
73
+
74
+ try {
75
+ // Check if source exists
76
+ const sourceExists = await fs.pathExists(sourcePath);
77
+ if (!sourceExists) {
78
+ throw new Error(`Source file does not exist: ${sourcePath}`);
79
+ }
80
+
81
+ // Check if destination exists
82
+ const destExists = await fs.pathExists(destPath);
83
+ if (destExists && !overwrite) {
84
+ throw new Error(`Destination file already exists: ${destPath}`);
85
+ }
86
+
87
+ // Ensure parent directory exists
88
+ const parentDir = path.dirname(destPath);
89
+ await fs.ensureDir(parentDir);
90
+
91
+ // Copy file
92
+ await fs.copy(sourcePath, destPath, { overwrite });
93
+ } catch (error) {
94
+ throw new Error(`Failed to copy file: ${error.message}`);
95
+ }
96
+ }
97
+
98
+ /**
99
+ * Recursively creates a directory
100
+ * Safe to call even if directory already exists
101
+ *
102
+ * @param {string} dirPath - Absolute path to directory
103
+ * @returns {Promise<void>}
104
+ */
105
+ async function ensureDirectory(dirPath) {
106
+ try {
107
+ await fs.ensureDir(dirPath);
108
+ } catch (error) {
109
+ throw new Error(`Failed to create directory: ${error.message}`);
110
+ }
111
+ }
112
+
113
+ /**
114
+ * Recursively copies a directory
115
+ *
116
+ * @param {string} sourceDir - Absolute path to source directory
117
+ * @param {string} destDir - Absolute path to destination directory
118
+ * @param {Object} options - Copy options
119
+ * @param {boolean} options.overwrite - Whether to overwrite existing files (default: false)
120
+ * @param {Function} options.filter - Filter function (path) => boolean
121
+ * @returns {Promise<void>}
122
+ */
123
+ async function copyDirectory(sourceDir, destDir, options = {}) {
124
+ const { overwrite = false, filter = null } = options;
125
+
126
+ try {
127
+ await fs.copy(sourceDir, destDir, {
128
+ overwrite,
129
+ filter: filter || (() => true)
130
+ });
131
+ } catch (error) {
132
+ throw new Error(`Failed to copy directory: ${error.message}`);
133
+ }
134
+ }
135
+
136
+ /**
137
+ * Checks if a path exists
138
+ *
139
+ * @param {string} filePath - Path to check
140
+ * @returns {Promise<boolean>}
141
+ */
142
+ async function pathExists(filePath) {
143
+ return fs.pathExists(filePath);
144
+ }
145
+
146
+ /**
147
+ * Reads a JSON file safely
148
+ *
149
+ * @param {string} filePath - Absolute path to JSON file
150
+ * @returns {Promise<Object>} - Parsed JSON object
151
+ * @throws {Error} - If file doesn't exist or JSON is invalid
152
+ */
153
+ async function readJSON(filePath) {
154
+ try {
155
+ return await fs.readJSON(filePath);
156
+ } catch (error) {
157
+ throw new Error(`Failed to read JSON file: ${error.message}`);
158
+ }
159
+ }
160
+
161
+ /**
162
+ * Writes a JSON file atomically
163
+ *
164
+ * @param {string} filePath - Absolute path to JSON file
165
+ * @param {Object} data - Data to write
166
+ * @param {Object} options - Write options
167
+ * @param {number} options.spaces - Number of spaces for indentation (default: 2)
168
+ * @returns {Promise<void>}
169
+ */
170
+ async function writeJSON(filePath, data, options = {}) {
171
+ const { spaces = 2 } = options;
172
+ const content = JSON.stringify(data, null, spaces);
173
+ await atomicWrite(filePath, content);
174
+ }
175
+
176
+ /**
177
+ * Removes a file or directory
178
+ *
179
+ * @param {string} targetPath - Path to remove
180
+ * @returns {Promise<void>}
181
+ */
182
+ async function remove(targetPath) {
183
+ try {
184
+ await fs.remove(targetPath);
185
+ } catch (error) {
186
+ throw new Error(`Failed to remove path: ${error.message}`);
187
+ }
188
+ }
189
+
190
+ /**
191
+ * Gets file stats
192
+ *
193
+ * @param {string} filePath - Path to file
194
+ * @returns {Promise<fs.Stats>}
195
+ */
196
+ async function getStats(filePath) {
197
+ try {
198
+ return await fs.stat(filePath);
199
+ } catch (error) {
200
+ throw new Error(`Failed to get file stats: ${error.message}`);
201
+ }
202
+ }
203
+
204
+ /**
205
+ * Lists files in a directory
206
+ *
207
+ * @param {string} dirPath - Path to directory
208
+ * @returns {Promise<string[]>} - Array of file names
209
+ */
210
+ async function listFiles(dirPath) {
211
+ try {
212
+ return await fs.readdir(dirPath);
213
+ } catch (error) {
214
+ throw new Error(`Failed to list directory: ${error.message}`);
215
+ }
216
+ }
217
+
218
+ /**
219
+ * Recursively lists all files in a directory
220
+ *
221
+ * @param {string} dirPath - Path to directory
222
+ * @param {string[]} fileList - Accumulator for recursive calls
223
+ * @returns {Promise<string[]>} - Array of absolute file paths
224
+ */
225
+ async function listFilesRecursive(dirPath, fileList = []) {
226
+ const files = await fs.readdir(dirPath);
227
+
228
+ for (const file of files) {
229
+ const filePath = path.join(dirPath, file);
230
+ const stat = await fs.stat(filePath);
231
+
232
+ if (stat.isDirectory()) {
233
+ await listFilesRecursive(filePath, fileList);
234
+ } else {
235
+ fileList.push(filePath);
236
+ }
237
+ }
238
+
239
+ return fileList;
240
+ }
241
+
242
+ /**
243
+ * Calculates total size of a directory
244
+ *
245
+ * @param {string} dirPath - Path to directory
246
+ * @returns {Promise<number>} - Total size in bytes
247
+ */
248
+ async function getDirectorySize(dirPath) {
249
+ const files = await listFilesRecursive(dirPath);
250
+ let totalSize = 0;
251
+
252
+ for (const file of files) {
253
+ const stats = await fs.stat(file);
254
+ totalSize += stats.size;
255
+ }
256
+
257
+ return totalSize;
258
+ }
259
+
260
+ module.exports = {
261
+ validatePath,
262
+ atomicWrite,
263
+ safeCopy,
264
+ ensureDirectory,
265
+ copyDirectory,
266
+ pathExists,
267
+ readJSON,
268
+ writeJSON,
269
+ remove,
270
+ getStats,
271
+ listFiles,
272
+ listFilesRecursive,
273
+ getDirectorySize
274
+ };
@@ -0,0 +1,383 @@
1
+ /**
2
+ * Tool Detector
3
+ *
4
+ * Detects which IDE/editor the user is using
5
+ */
6
+
7
+ const fs = require('fs-extra');
8
+ const path = require('path');
9
+
10
+ /**
11
+ * Detect the current IDE/editor environment
12
+ *
13
+ * @param {string} projectPath - Project root path
14
+ * @returns {Promise<Object>} Detection result
15
+ */
16
+ async function detectTool(projectPath) {
17
+ const detections = {
18
+ kiro: await detectKiroIDE(projectPath),
19
+ vscode: await detectVSCode(projectPath),
20
+ cursor: await detectCursor(projectPath),
21
+ other: null
22
+ };
23
+
24
+ // Determine primary tool
25
+ let primaryTool = 'unknown';
26
+ let confidence = 'low';
27
+
28
+ if (detections.kiro.detected) {
29
+ primaryTool = 'kiro';
30
+ confidence = detections.kiro.confidence;
31
+ } else if (detections.cursor.detected && detections.cursor.confidence === 'high') {
32
+ // Only use Cursor if we have high confidence (Cursor-specific indicators)
33
+ primaryTool = 'cursor';
34
+ confidence = detections.cursor.confidence;
35
+ } else if (detections.vscode.detected) {
36
+ primaryTool = 'vscode';
37
+ confidence = detections.vscode.confidence;
38
+ } else if (detections.cursor.detected) {
39
+ // Fallback to Cursor if VS Code not detected
40
+ primaryTool = 'cursor';
41
+ confidence = detections.cursor.confidence;
42
+ } else {
43
+ primaryTool = 'other';
44
+ confidence = 'low';
45
+ }
46
+
47
+ return {
48
+ primaryTool,
49
+ confidence,
50
+ detections,
51
+ recommendations: getRecommendations(primaryTool, detections)
52
+ };
53
+ }
54
+
55
+ /**
56
+ * Detect Kiro IDE
57
+ *
58
+ * @param {string} projectPath - Project root path
59
+ * @returns {Promise<Object>} Detection result
60
+ */
61
+ async function detectKiroIDE(projectPath) {
62
+ const indicators = [];
63
+ let detected = false;
64
+ let confidence = 'low';
65
+
66
+ // Check for .kiro directory
67
+ const kiroDir = path.join(projectPath, '.kiro');
68
+ if (await fs.pathExists(kiroDir)) {
69
+ indicators.push('.kiro directory exists');
70
+ detected = true;
71
+ confidence = 'medium';
72
+ }
73
+
74
+ // Check for Kiro-specific files
75
+ const kiroFiles = [
76
+ '.kiro/steering',
77
+ '.kiro/specs',
78
+ '.kiro/tools'
79
+ ];
80
+
81
+ for (const file of kiroFiles) {
82
+ const filePath = path.join(projectPath, file);
83
+ if (await fs.pathExists(filePath)) {
84
+ indicators.push(`${file} exists`);
85
+ confidence = 'high';
86
+ }
87
+ }
88
+
89
+ // Check for environment variables (if running in Kiro)
90
+ if (process.env.KIRO_IDE === 'true' || process.env.KIRO_VERSION) {
91
+ indicators.push('Kiro environment variables detected');
92
+ detected = true;
93
+ confidence = 'high';
94
+ }
95
+
96
+ return {
97
+ detected,
98
+ confidence,
99
+ indicators,
100
+ features: detected ? ['agent-hooks', 'native-integration'] : []
101
+ };
102
+ }
103
+
104
+ /**
105
+ * Detect VS Code
106
+ *
107
+ * @param {string} projectPath - Project root path
108
+ * @returns {Promise<Object>} Detection result
109
+ */
110
+ async function detectVSCode(projectPath) {
111
+ const indicators = [];
112
+ let detected = false;
113
+ let confidence = 'low';
114
+
115
+ // Check for .vscode directory
116
+ const vscodeDir = path.join(projectPath, '.vscode');
117
+ if (await fs.pathExists(vscodeDir)) {
118
+ indicators.push('.vscode directory exists');
119
+ detected = true;
120
+ confidence = 'medium';
121
+ }
122
+
123
+ // Check for VS Code specific files
124
+ const vscodeFiles = [
125
+ '.vscode/settings.json',
126
+ '.vscode/launch.json',
127
+ '.vscode/tasks.json'
128
+ ];
129
+
130
+ for (const file of vscodeFiles) {
131
+ const filePath = path.join(projectPath, file);
132
+ if (await fs.pathExists(filePath)) {
133
+ indicators.push(`${file} exists`);
134
+ confidence = 'high';
135
+ }
136
+ }
137
+
138
+ // Check for environment variables
139
+ if (process.env.VSCODE_PID || process.env.TERM_PROGRAM === 'vscode') {
140
+ indicators.push('VS Code environment detected');
141
+ detected = true;
142
+ confidence = 'high';
143
+ }
144
+
145
+ return {
146
+ detected,
147
+ confidence,
148
+ indicators,
149
+ features: detected ? ['watch-mode', 'manual-workflows'] : []
150
+ };
151
+ }
152
+
153
+ /**
154
+ * Detect Cursor
155
+ *
156
+ * @param {string} projectPath - Project root path
157
+ * @returns {Promise<Object>} Detection result
158
+ */
159
+ async function detectCursor(projectPath) {
160
+ const indicators = [];
161
+ let detected = false;
162
+ let confidence = 'low';
163
+
164
+ // Cursor uses similar structure to VS Code
165
+ const vscodeDir = path.join(projectPath, '.vscode');
166
+ if (await fs.pathExists(vscodeDir)) {
167
+ indicators.push('.vscode directory exists (Cursor compatible)');
168
+ detected = true;
169
+ confidence = 'low'; // Could be VS Code or Cursor
170
+ }
171
+
172
+ // Check for Cursor-specific indicators
173
+ if (process.env.CURSOR_VERSION || process.env.TERM_PROGRAM === 'cursor') {
174
+ indicators.push('Cursor environment detected');
175
+ detected = true;
176
+ confidence = 'high';
177
+ }
178
+
179
+ // Check for Cursor-specific settings
180
+ const settingsPath = path.join(projectPath, '.vscode/settings.json');
181
+ if (await fs.pathExists(settingsPath)) {
182
+ try {
183
+ const settings = await fs.readJson(settingsPath);
184
+ if (settings['cursor.aiEnabled'] !== undefined ||
185
+ settings['cursor.chat'] !== undefined) {
186
+ indicators.push('Cursor-specific settings found');
187
+ confidence = 'high';
188
+ }
189
+ } catch (error) {
190
+ // Ignore JSON parse errors
191
+ }
192
+ }
193
+
194
+ return {
195
+ detected,
196
+ confidence,
197
+ indicators,
198
+ features: detected ? ['watch-mode', 'manual-workflows', 'ai-integration'] : []
199
+ };
200
+ }
201
+
202
+ /**
203
+ * Get recommendations based on detected tool
204
+ *
205
+ * @param {string} primaryTool - Primary tool name
206
+ * @param {Object} detections - All detections
207
+ * @returns {Array} Recommendations
208
+ */
209
+ function getRecommendations(primaryTool, detections) {
210
+ const recommendations = [];
211
+
212
+ switch (primaryTool) {
213
+ case 'kiro':
214
+ recommendations.push({
215
+ type: 'native',
216
+ title: 'Use Kiro Agent Hooks',
217
+ description: 'You can use native Kiro agent hooks for seamless automation',
218
+ action: 'Configure hooks in .kiro/hooks/'
219
+ });
220
+ recommendations.push({
221
+ type: 'optional',
222
+ title: 'Watch Mode Available',
223
+ description: 'Watch mode is also available as a fallback option',
224
+ action: 'Run: kse watch init'
225
+ });
226
+ break;
227
+
228
+ case 'vscode':
229
+ case 'cursor':
230
+ recommendations.push({
231
+ type: 'primary',
232
+ title: 'Use Watch Mode',
233
+ description: 'Watch mode provides automated file monitoring for your IDE',
234
+ action: 'Run: kse watch init && kse watch install auto-sync'
235
+ });
236
+ recommendations.push({
237
+ type: 'preset',
238
+ title: 'Install Presets',
239
+ description: 'Pre-configured automation patterns for common workflows',
240
+ action: 'Run: kse watch presets'
241
+ });
242
+ break;
243
+
244
+ case 'other':
245
+ default:
246
+ recommendations.push({
247
+ type: 'manual',
248
+ title: 'Manual Workflows',
249
+ description: 'Follow documented manual workflows for your tool',
250
+ action: 'See: docs/cross-tool-guide.md'
251
+ });
252
+ recommendations.push({
253
+ type: 'watch',
254
+ title: 'Try Watch Mode',
255
+ description: 'Watch mode works with most editors and IDEs',
256
+ action: 'Run: kse watch init'
257
+ });
258
+ break;
259
+ }
260
+
261
+ return recommendations;
262
+ }
263
+
264
+ /**
265
+ * Get automation suggestions based on tool
266
+ *
267
+ * @param {string} tool - Tool name
268
+ * @returns {Array} Suggestions
269
+ */
270
+ function getAutomationSuggestions(tool) {
271
+ const suggestions = {
272
+ kiro: [
273
+ 'Configure agent hooks for automatic task sync',
274
+ 'Set up prompt regeneration on spec changes',
275
+ 'Enable context export on task completion'
276
+ ],
277
+ vscode: [
278
+ 'Install auto-sync preset for task synchronization',
279
+ 'Use watch mode for automated workflows',
280
+ 'Configure VS Code tasks for manual triggers'
281
+ ],
282
+ cursor: [
283
+ 'Install auto-sync preset for task synchronization',
284
+ 'Use watch mode for automated workflows',
285
+ 'Leverage Cursor AI for enhanced productivity'
286
+ ],
287
+ other: [
288
+ 'Follow manual workflow documentation',
289
+ 'Consider using watch mode for automation',
290
+ 'Set up shell aliases for common commands'
291
+ ]
292
+ };
293
+
294
+ return suggestions[tool] || suggestions.other;
295
+ }
296
+
297
+ /**
298
+ * Generate auto-configuration for detected tool
299
+ *
300
+ * @param {Object} detection - Detection result from detectTool
301
+ * @param {string} projectPath - Project root path
302
+ * @returns {Promise<Object>} Auto-configuration result
303
+ */
304
+ async function generateAutoConfig(detection, projectPath) {
305
+ const { primaryTool, confidence } = detection;
306
+
307
+ const config = {
308
+ tool: primaryTool,
309
+ confidence,
310
+ suggestedPresets: [],
311
+ suggestedCommands: [],
312
+ configPath: null,
313
+ notes: []
314
+ };
315
+
316
+ switch (primaryTool) {
317
+ case 'kiro':
318
+ config.suggestedPresets = [];
319
+ config.suggestedCommands = [
320
+ 'Use native Kiro agent hooks (see .kiro/hooks/)',
321
+ 'Optional: kse watch init (for watch mode fallback)'
322
+ ];
323
+ config.notes.push('Kiro IDE detected - native hooks are recommended');
324
+ config.notes.push('Watch mode available as fallback option');
325
+ break;
326
+
327
+ case 'vscode':
328
+ case 'cursor':
329
+ config.suggestedPresets = ['auto-sync', 'prompt-regen', 'context-export'];
330
+ config.suggestedCommands = [
331
+ 'kse watch init',
332
+ 'kse watch install auto-sync',
333
+ 'kse watch start'
334
+ ];
335
+ config.configPath = path.join(projectPath, '.kiro/watch-config.json');
336
+ config.notes.push(`${primaryTool === 'vscode' ? 'VS Code' : 'Cursor'} detected - watch mode recommended`);
337
+ config.notes.push('Run suggested commands to set up automation');
338
+ break;
339
+
340
+ case 'other':
341
+ default:
342
+ config.suggestedPresets = ['auto-sync'];
343
+ config.suggestedCommands = [
344
+ 'kse watch init',
345
+ 'kse watch install auto-sync',
346
+ 'See: docs/cross-tool-guide.md for manual workflows'
347
+ ];
348
+ config.notes.push('No specific IDE detected');
349
+ config.notes.push('Watch mode available for basic automation');
350
+ config.notes.push('Manual workflows documented in docs/');
351
+ break;
352
+ }
353
+
354
+ return config;
355
+ }
356
+
357
+ /**
358
+ * Offer to install presets interactively
359
+ *
360
+ * @param {Object} detection - Detection result from detectTool
361
+ * @param {string} projectPath - Project root path
362
+ * @returns {Promise<Object>} Installation result
363
+ */
364
+ async function offerPresetInstallation(detection, projectPath) {
365
+ const config = await generateAutoConfig(detection, projectPath);
366
+
367
+ return {
368
+ success: true,
369
+ config,
370
+ message: 'Auto-configuration generated successfully'
371
+ };
372
+ }
373
+
374
+ module.exports = {
375
+ detectTool,
376
+ detectKiroIDE,
377
+ detectVSCode,
378
+ detectCursor,
379
+ getRecommendations,
380
+ getAutomationSuggestions,
381
+ generateAutoConfig,
382
+ offerPresetInstallation
383
+ };