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,420 @@
1
+ /**
2
+ * Backup Manager
3
+ *
4
+ * Manages mandatory backup creation and validation for adoption process.
5
+ * Ensures all modifications are preceded by verified backups.
6
+ *
7
+ * Core Responsibilities:
8
+ * - Create selective backups of files to be modified
9
+ * - Validate backup integrity (file count, size, content)
10
+ * - Provide backup metadata for rollback
11
+ * - Abort operations if backup fails
12
+ */
13
+
14
+ const path = require('path');
15
+ const fs = require('fs-extra');
16
+ const crypto = require('crypto');
17
+ const SelectiveBackup = require('../backup/selective-backup');
18
+
19
+ /**
20
+ * Backup Manager for mandatory backup operations
21
+ */
22
+ class BackupManager {
23
+ constructor(dependencies = {}) {
24
+ // Support dependency injection for testing
25
+ this.selectiveBackup = dependencies.selectiveBackup || new SelectiveBackup();
26
+ }
27
+
28
+ /**
29
+ * Creates mandatory backup before modifications
30
+ *
31
+ * This method MUST be called before any file modifications during adoption.
32
+ * If backup creation or validation fails, the adoption process MUST be aborted.
33
+ *
34
+ * @param {string} projectPath - Absolute path to project root
35
+ * @param {string[]} filesToModify - Relative paths of files to backup (from .kiro/)
36
+ * @param {Object} options - Backup options
37
+ * @param {string} options.type - Backup type (default: 'adopt-smart')
38
+ * @param {boolean} options.validateContent - Validate file content hashes (default: true)
39
+ * @returns {Promise<BackupResult>}
40
+ * @throws {Error} If backup creation or validation fails
41
+ */
42
+ async createMandatoryBackup(projectPath, filesToModify, options = {}) {
43
+ const {
44
+ type = 'adopt-smart',
45
+ validateContent = true
46
+ } = options;
47
+
48
+ // Validate inputs
49
+ if (!projectPath) {
50
+ throw new Error('Project path is required');
51
+ }
52
+
53
+ if (!Array.isArray(filesToModify)) {
54
+ throw new Error('filesToModify must be an array');
55
+ }
56
+
57
+ // If no files to modify, return null (no backup needed)
58
+ if (filesToModify.length === 0) {
59
+ return null;
60
+ }
61
+
62
+ try {
63
+ // Create selective backup using existing system
64
+ const backup = await this.selectiveBackup.createSelectiveBackup(
65
+ projectPath,
66
+ filesToModify,
67
+ { type }
68
+ );
69
+
70
+ // Ensure backup has required properties
71
+ if (!backup || !backup.id) {
72
+ throw new Error('Backup creation returned invalid result');
73
+ }
74
+
75
+ // Transform to standardized BackupResult format
76
+ const backupResult = {
77
+ id: backup.id,
78
+ location: backup.path || backup.backupPath,
79
+ filesCount: backup.fileCount || (backup.files ? backup.files.length : 0),
80
+ totalSize: backup.totalSize || 0,
81
+ timestamp: backup.created ? new Date(backup.created) : new Date(),
82
+ type: backup.type || type,
83
+ files: backup.files || []
84
+ };
85
+
86
+ // Validate backup integrity
87
+ const validation = await this.validateBackup(backupResult, {
88
+ validateContent,
89
+ originalPath: projectPath
90
+ });
91
+
92
+ if (!validation.success) {
93
+ throw new Error(`Backup validation failed: ${validation.error}`);
94
+ }
95
+
96
+ // Add validation info to result
97
+ backupResult.validated = true;
98
+ backupResult.validationDetails = {
99
+ filesVerified: validation.filesVerified,
100
+ contentVerified: validation.contentVerified,
101
+ timestamp: new Date()
102
+ };
103
+
104
+ return backupResult;
105
+
106
+ } catch (error) {
107
+ // Wrap error with context
108
+ throw new Error(`Failed to create mandatory backup: ${error.message}`);
109
+ }
110
+ }
111
+
112
+ /**
113
+ * Validates backup integrity
114
+ *
115
+ * Performs comprehensive validation of backup to ensure it can be used for rollback:
116
+ * 1. Backup directory exists
117
+ * 2. File count matches expected
118
+ * 3. All files exist in backup
119
+ * 4. File sizes match (optional)
120
+ * 5. Content hashes match (optional)
121
+ *
122
+ * @param {BackupResult} backup - Backup result to validate
123
+ * @param {Object} options - Validation options
124
+ * @param {boolean} options.validateContent - Validate file content hashes (default: false)
125
+ * @param {string} options.originalPath - Original project path for content validation
126
+ * @returns {Promise<ValidationResult>}
127
+ */
128
+ async validateBackup(backup, options = {}) {
129
+ const {
130
+ validateContent = false,
131
+ originalPath = null
132
+ } = options;
133
+
134
+ // Handle null backup (no backup needed)
135
+ if (!backup) {
136
+ return {
137
+ success: true,
138
+ filesVerified: 0,
139
+ contentVerified: false,
140
+ message: 'No backup to validate'
141
+ };
142
+ }
143
+
144
+ try {
145
+ // Validation 1: Backup has required properties
146
+ if (!backup.location) {
147
+ return {
148
+ success: false,
149
+ error: 'Backup location not specified',
150
+ filesVerified: 0,
151
+ contentVerified: false
152
+ };
153
+ }
154
+
155
+ // Validation 2: Backup directory exists
156
+ const exists = await fs.pathExists(backup.location);
157
+ if (!exists) {
158
+ return {
159
+ success: false,
160
+ error: 'Backup directory not found',
161
+ filesVerified: 0,
162
+ contentVerified: false
163
+ };
164
+ }
165
+
166
+ // Validation 3: Files subdirectory exists
167
+ const filesDir = path.join(backup.location, 'files');
168
+ const filesDirExists = await fs.pathExists(filesDir);
169
+ if (!filesDirExists) {
170
+ return {
171
+ success: false,
172
+ error: 'Backup files directory not found',
173
+ filesVerified: 0,
174
+ contentVerified: false
175
+ };
176
+ }
177
+
178
+ // Validation 4: Verify file count
179
+ const expectedCount = backup.filesCount || 0;
180
+ const actualFiles = backup.files || [];
181
+
182
+ if (actualFiles.length !== expectedCount) {
183
+ return {
184
+ success: false,
185
+ error: `File count mismatch: expected ${expectedCount}, found ${actualFiles.length}`,
186
+ filesVerified: 0,
187
+ contentVerified: false
188
+ };
189
+ }
190
+
191
+ // Validation 5: Verify each file exists in backup
192
+ let filesVerified = 0;
193
+ for (const filePath of actualFiles) {
194
+ const backupFilePath = path.join(filesDir, filePath);
195
+ const fileExists = await fs.pathExists(backupFilePath);
196
+
197
+ if (!fileExists) {
198
+ return {
199
+ success: false,
200
+ error: `File missing from backup: ${filePath}`,
201
+ filesVerified,
202
+ contentVerified: false
203
+ };
204
+ }
205
+
206
+ filesVerified++;
207
+ }
208
+
209
+ // Validation 6: Optional content validation
210
+ let contentVerified = false;
211
+ if (validateContent && originalPath) {
212
+ const contentValidation = await this._validateContent(
213
+ originalPath,
214
+ backup.location,
215
+ actualFiles
216
+ );
217
+
218
+ if (!contentValidation.success) {
219
+ return {
220
+ success: false,
221
+ error: contentValidation.error,
222
+ filesVerified,
223
+ contentVerified: false
224
+ };
225
+ }
226
+
227
+ contentVerified = true;
228
+ }
229
+
230
+ // All validations passed
231
+ return {
232
+ success: true,
233
+ filesVerified,
234
+ contentVerified,
235
+ message: `Backup validated: ${filesVerified} files verified`
236
+ };
237
+
238
+ } catch (error) {
239
+ return {
240
+ success: false,
241
+ error: `Validation error: ${error.message}`,
242
+ filesVerified: 0,
243
+ contentVerified: false
244
+ };
245
+ }
246
+ }
247
+
248
+ /**
249
+ * Validates backup content matches original files
250
+ *
251
+ * @param {string} originalPath - Original project path
252
+ * @param {string} backupPath - Backup directory path
253
+ * @param {string[]} files - Files to validate
254
+ * @returns {Promise<ContentValidationResult>}
255
+ * @private
256
+ */
257
+ async _validateContent(originalPath, backupPath, files) {
258
+ try {
259
+ const filesDir = path.join(backupPath, 'files');
260
+
261
+ for (const filePath of files) {
262
+ const originalFilePath = path.join(originalPath, '.kiro', filePath);
263
+ const backupFilePath = path.join(filesDir, filePath);
264
+
265
+ // Check if original file still exists
266
+ const originalExists = await fs.pathExists(originalFilePath);
267
+ if (!originalExists) {
268
+ // Original file may have been deleted, skip validation
269
+ continue;
270
+ }
271
+
272
+ // Compare file sizes
273
+ const originalStats = await fs.stat(originalFilePath);
274
+ const backupStats = await fs.stat(backupFilePath);
275
+
276
+ if (originalStats.size !== backupStats.size) {
277
+ return {
278
+ success: false,
279
+ error: `File size mismatch for ${filePath}: original ${originalStats.size}, backup ${backupStats.size}`
280
+ };
281
+ }
282
+
283
+ // Compare content hashes for critical files
284
+ if (this._isCriticalFile(filePath)) {
285
+ const originalHash = await this._calculateFileHash(originalFilePath);
286
+ const backupHash = await this._calculateFileHash(backupFilePath);
287
+
288
+ if (originalHash !== backupHash) {
289
+ return {
290
+ success: false,
291
+ error: `Content hash mismatch for ${filePath}`
292
+ };
293
+ }
294
+ }
295
+ }
296
+
297
+ return { success: true };
298
+
299
+ } catch (error) {
300
+ return {
301
+ success: false,
302
+ error: `Content validation error: ${error.message}`
303
+ };
304
+ }
305
+ }
306
+
307
+ /**
308
+ * Determines if a file is critical and requires hash validation
309
+ *
310
+ * @param {string} filePath - File path
311
+ * @returns {boolean}
312
+ * @private
313
+ */
314
+ _isCriticalFile(filePath) {
315
+ const criticalPatterns = [
316
+ 'steering/CORE_PRINCIPLES.md',
317
+ 'steering/ENVIRONMENT.md',
318
+ 'version.json',
319
+ 'adoption-config.json'
320
+ ];
321
+
322
+ return criticalPatterns.some(pattern => filePath.includes(pattern));
323
+ }
324
+
325
+ /**
326
+ * Calculates SHA-256 hash of a file
327
+ *
328
+ * @param {string} filePath - File path
329
+ * @returns {Promise<string>} - Hex hash string
330
+ * @private
331
+ */
332
+ async _calculateFileHash(filePath) {
333
+ return new Promise((resolve, reject) => {
334
+ const hash = crypto.createHash('sha256');
335
+ const stream = fs.createReadStream(filePath);
336
+
337
+ stream.on('data', data => hash.update(data));
338
+ stream.on('end', () => resolve(hash.digest('hex')));
339
+ stream.on('error', reject);
340
+ });
341
+ }
342
+
343
+ /**
344
+ * Gets backup information
345
+ *
346
+ * @param {string} projectPath - Project path
347
+ * @param {string} backupId - Backup ID
348
+ * @returns {Promise<BackupInfo>}
349
+ */
350
+ async getBackupInfo(projectPath, backupId) {
351
+ const backupPath = path.join(projectPath, '.kiro', 'backups', backupId);
352
+
353
+ // Check if backup exists
354
+ const exists = await fs.pathExists(backupPath);
355
+ if (!exists) {
356
+ throw new Error(`Backup not found: ${backupId}`);
357
+ }
358
+
359
+ // Read metadata
360
+ const metadataPath = path.join(backupPath, 'metadata.json');
361
+ const metadataExists = await fs.pathExists(metadataPath);
362
+
363
+ if (!metadataExists) {
364
+ throw new Error(`Backup metadata not found: ${backupId}`);
365
+ }
366
+
367
+ const metadata = await fs.readJson(metadataPath);
368
+
369
+ return {
370
+ id: metadata.id || backupId,
371
+ type: metadata.type,
372
+ created: metadata.created,
373
+ filesCount: metadata.fileCount || 0,
374
+ totalSize: metadata.totalSize || 0,
375
+ files: metadata.files || [],
376
+ location: backupPath
377
+ };
378
+ }
379
+ }
380
+
381
+ /**
382
+ * @typedef {Object} BackupResult
383
+ * @property {string} id - Unique backup identifier
384
+ * @property {string} location - Absolute path to backup directory
385
+ * @property {number} filesCount - Number of files backed up
386
+ * @property {number} totalSize - Total size of backed up files in bytes
387
+ * @property {Date} timestamp - Backup creation timestamp
388
+ * @property {string} type - Backup type (e.g., 'adopt-smart')
389
+ * @property {string[]} files - List of backed up file paths
390
+ * @property {boolean} validated - Whether backup has been validated
391
+ * @property {Object} validationDetails - Validation details
392
+ */
393
+
394
+ /**
395
+ * @typedef {Object} ValidationResult
396
+ * @property {boolean} success - Whether validation succeeded
397
+ * @property {number} filesVerified - Number of files verified
398
+ * @property {boolean} contentVerified - Whether content was verified
399
+ * @property {string} [error] - Error message if validation failed
400
+ * @property {string} [message] - Success message if validation passed
401
+ */
402
+
403
+ /**
404
+ * @typedef {Object} ContentValidationResult
405
+ * @property {boolean} success - Whether content validation succeeded
406
+ * @property {string} [error] - Error message if validation failed
407
+ */
408
+
409
+ /**
410
+ * @typedef {Object} BackupInfo
411
+ * @property {string} id - Backup identifier
412
+ * @property {string} type - Backup type
413
+ * @property {string} created - Creation timestamp (ISO string)
414
+ * @property {number} filesCount - Number of files
415
+ * @property {number} totalSize - Total size in bytes
416
+ * @property {string[]} files - List of file paths
417
+ * @property {string} location - Backup directory path
418
+ */
419
+
420
+ module.exports = BackupManager;