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,252 @@
1
+ /**
2
+ * Merge Coordinator - Manages Agent Git branches and merge operations
3
+ *
4
+ * Handles branch creation, conflict detection, auto-merge, and cleanup
5
+ * for multi-Agent parallel coordination. In single-Agent mode, all
6
+ * branch operations are skipped (agents work on the current branch).
7
+ *
8
+ * Branch naming: `agent/{agentId}/{specName}`
9
+ *
10
+ * Requirements: 4.1, 4.2, 4.3, 4.4, 4.5, 4.6
11
+ */
12
+
13
+ const { execSync } = require('child_process');
14
+ const { MultiAgentConfig } = require('./multi-agent-config');
15
+
16
+ /** Default options for execSync Git commands */
17
+ const EXEC_OPTS = Object.freeze({
18
+ encoding: 'utf8',
19
+ stdio: ['pipe', 'pipe', 'pipe'],
20
+ });
21
+
22
+ class MergeCoordinator {
23
+ /**
24
+ * @param {string} workspaceRoot - Absolute path to the project root
25
+ */
26
+ constructor(workspaceRoot) {
27
+ this._workspaceRoot = workspaceRoot;
28
+ this._multiAgentConfig = new MultiAgentConfig(workspaceRoot);
29
+ }
30
+
31
+ /**
32
+ * Execute a Git command in the workspace root.
33
+ * @param {string} command - Git command (without the leading `git `)
34
+ * @returns {string} Trimmed stdout
35
+ * @private
36
+ */
37
+ _git(command) {
38
+ return execSync(`git ${command}`, {
39
+ ...EXEC_OPTS,
40
+ cwd: this._workspaceRoot,
41
+ }).trim();
42
+ }
43
+
44
+ /**
45
+ * Whether multi-Agent mode is enabled.
46
+ * In single-Agent mode all branch operations are skipped (Req 4.6).
47
+ * @returns {Promise<boolean>}
48
+ */
49
+ async isMultiAgentMode() {
50
+ return this._multiAgentConfig.isEnabled();
51
+ }
52
+
53
+ /**
54
+ * Create an agent-specific branch from the current HEAD.
55
+ * Branch name follows the format `agent/{agentId}/{specName}` (Req 4.1).
56
+ *
57
+ * In single-Agent mode, returns the current branch name without creating
58
+ * a new branch (Req 4.6).
59
+ *
60
+ * @param {string} agentId
61
+ * @param {string} specName
62
+ * @returns {Promise<{branchName: string, created: boolean}>}
63
+ */
64
+ async createAgentBranch(agentId, specName) {
65
+ const multiAgent = await this.isMultiAgentMode();
66
+ if (!multiAgent) {
67
+ // Single-Agent mode – stay on the current branch (Req 4.6)
68
+ const current = this._getCurrentBranch();
69
+ return { branchName: current, created: false };
70
+ }
71
+
72
+ const branchName = `agent/${agentId}/${specName}`;
73
+
74
+ try {
75
+ // Check if branch already exists
76
+ this._git(`rev-parse --verify refs/heads/${branchName}`);
77
+ // Branch exists – just switch to it
78
+ this._git(`checkout ${branchName}`);
79
+ return { branchName, created: false };
80
+ } catch (_err) {
81
+ // Branch does not exist – create it from current HEAD
82
+ try {
83
+ this._git(`checkout -b ${branchName}`);
84
+ return { branchName, created: true };
85
+ } catch (createErr) {
86
+ throw new Error(
87
+ `Failed to create agent branch "${branchName}": ${createErr.message}`
88
+ );
89
+ }
90
+ }
91
+ }
92
+
93
+ /**
94
+ * Detect merge conflicts between a branch and a target branch (Req 4.2).
95
+ *
96
+ * Uses `git merge --no-commit --no-ff` followed by `git merge --abort`
97
+ * to perform a dry-run merge without altering the working tree permanently.
98
+ *
99
+ * @param {string} branchName - Source branch to merge
100
+ * @param {string} targetBranch - Target branch (e.g. "main")
101
+ * @returns {Promise<{hasConflicts: boolean, files: string[]}>}
102
+ */
103
+ async detectConflicts(branchName, targetBranch) {
104
+ const multiAgent = await this.isMultiAgentMode();
105
+ if (!multiAgent) {
106
+ return { hasConflicts: false, files: [] };
107
+ }
108
+
109
+ // Save current branch so we can restore it
110
+ const originalBranch = this._getCurrentBranch();
111
+
112
+ try {
113
+ // Switch to target branch for the trial merge
114
+ this._git(`checkout ${targetBranch}`);
115
+
116
+ try {
117
+ this._git(`merge --no-commit --no-ff ${branchName}`);
118
+ // Merge succeeded without conflicts – abort to undo
119
+ this._safeAbortMerge();
120
+ return { hasConflicts: false, files: [] };
121
+ } catch (_mergeErr) {
122
+ // Merge had conflicts – collect conflicting files
123
+ const files = this._getConflictFiles();
124
+ this._safeAbortMerge();
125
+ return { hasConflicts: true, files };
126
+ }
127
+ } finally {
128
+ // Always restore the original branch
129
+ try {
130
+ this._git(`checkout ${originalBranch}`);
131
+ } catch (_restoreErr) {
132
+ // Best-effort restore; nothing more we can do
133
+ }
134
+ }
135
+ }
136
+
137
+ /**
138
+ * Execute a merge of branchName into targetBranch (Req 4.3, 4.4).
139
+ *
140
+ * When no conflicts exist, performs a fast-forward merge if possible,
141
+ * otherwise creates a merge commit. When conflicts exist, records the
142
+ * conflict details and returns them without modifying the target branch.
143
+ *
144
+ * @param {string} branchName - Source branch to merge
145
+ * @param {string} targetBranch - Target branch
146
+ * @returns {Promise<{success: boolean, strategy: string|null, conflicts: string[]}>}
147
+ */
148
+ async merge(branchName, targetBranch) {
149
+ const multiAgent = await this.isMultiAgentMode();
150
+ if (!multiAgent) {
151
+ return { success: true, strategy: 'single-agent-noop', conflicts: [] };
152
+ }
153
+
154
+ const originalBranch = this._getCurrentBranch();
155
+
156
+ try {
157
+ this._git(`checkout ${targetBranch}`);
158
+
159
+ // Try fast-forward first
160
+ try {
161
+ this._git(`merge --ff-only ${branchName}`);
162
+ return { success: true, strategy: 'fast-forward', conflicts: [] };
163
+ } catch (_ffErr) {
164
+ // Fast-forward not possible – try regular merge
165
+ }
166
+
167
+ try {
168
+ this._git(`merge ${branchName} -m "Merge ${branchName} into ${targetBranch}"`);
169
+ return { success: true, strategy: 'merge-commit', conflicts: [] };
170
+ } catch (_mergeErr) {
171
+ // Conflicts detected (Req 4.4)
172
+ const conflicts = this._getConflictFiles();
173
+ this._safeAbortMerge();
174
+ return { success: false, strategy: null, conflicts };
175
+ }
176
+ } finally {
177
+ try {
178
+ this._git(`checkout ${originalBranch}`);
179
+ } catch (_restoreErr) {
180
+ // Best-effort restore
181
+ }
182
+ }
183
+ }
184
+
185
+ /**
186
+ * Delete a branch that has already been merged (Req 4.5).
187
+ *
188
+ * Uses `git branch -d` which only succeeds if the branch is fully merged.
189
+ *
190
+ * @param {string} branchName
191
+ * @returns {Promise<{success: boolean, error: string|null}>}
192
+ */
193
+ async cleanupBranch(branchName) {
194
+ const multiAgent = await this.isMultiAgentMode();
195
+ if (!multiAgent) {
196
+ return { success: true, error: null };
197
+ }
198
+
199
+ try {
200
+ this._git(`branch -d ${branchName}`);
201
+ return { success: true, error: null };
202
+ } catch (err) {
203
+ return {
204
+ success: false,
205
+ error: `Failed to delete branch "${branchName}": ${err.message}`,
206
+ };
207
+ }
208
+ }
209
+
210
+ // ── Private helpers ──────────────────────────────────────────────
211
+
212
+ /**
213
+ * Get the name of the currently checked-out branch.
214
+ * @returns {string}
215
+ * @private
216
+ */
217
+ _getCurrentBranch() {
218
+ try {
219
+ return this._git('rev-parse --abbrev-ref HEAD');
220
+ } catch (_err) {
221
+ return 'HEAD'; // detached HEAD or not a git repo
222
+ }
223
+ }
224
+
225
+ /**
226
+ * Collect the list of files with merge conflicts from `git diff --name-only --diff-filter=U`.
227
+ * @returns {string[]}
228
+ * @private
229
+ */
230
+ _getConflictFiles() {
231
+ try {
232
+ const output = this._git('diff --name-only --diff-filter=U');
233
+ return output ? output.split('\n').filter(Boolean) : [];
234
+ } catch (_err) {
235
+ return [];
236
+ }
237
+ }
238
+
239
+ /**
240
+ * Safely abort a merge in progress. Swallows errors if no merge is active.
241
+ * @private
242
+ */
243
+ _safeAbortMerge() {
244
+ try {
245
+ this._git('merge --abort');
246
+ } catch (_err) {
247
+ // No merge to abort – that's fine
248
+ }
249
+ }
250
+ }
251
+
252
+ module.exports = { MergeCoordinator };
@@ -0,0 +1,233 @@
1
+ const fs = require('fs').promises;
2
+ const path = require('path');
3
+
4
+ /**
5
+ * MetadataManager handles CRUD operations on collaboration.json files
6
+ * Provides atomic updates and schema validation
7
+ */
8
+ class MetadataManager {
9
+ constructor(workspaceRoot) {
10
+ this.workspaceRoot = workspaceRoot;
11
+ this.specsDir = path.join(workspaceRoot, '.kiro', 'specs');
12
+ }
13
+
14
+ /**
15
+ * Read collaboration metadata for a spec
16
+ * @param {string} specName - Name of the spec
17
+ * @returns {Promise<Object|null>} Metadata object or null if not found
18
+ */
19
+ async readMetadata(specName) {
20
+ const metadataPath = this._getMetadataPath(specName);
21
+
22
+ try {
23
+ const content = await fs.readFile(metadataPath, 'utf8');
24
+ return JSON.parse(content);
25
+ } catch (error) {
26
+ if (error.code === 'ENOENT') {
27
+ return null;
28
+ }
29
+ throw new Error(`Failed to read metadata for ${specName}: ${error.message}`);
30
+ }
31
+ }
32
+
33
+ /**
34
+ * Write collaboration metadata for a spec
35
+ * @param {string} specName - Name of the spec
36
+ * @param {Object} metadata - Metadata object to write
37
+ * @returns {Promise<void>}
38
+ */
39
+ async writeMetadata(specName, metadata) {
40
+ // Validate metadata before writing
41
+ this.validateMetadata(metadata);
42
+
43
+ const metadataPath = this._getMetadataPath(specName);
44
+ const specDir = path.dirname(metadataPath);
45
+
46
+ // Ensure spec directory exists
47
+ await fs.mkdir(specDir, { recursive: true });
48
+
49
+ // Write with pretty formatting
50
+ const content = JSON.stringify(metadata, null, 2);
51
+ await fs.writeFile(metadataPath, content, 'utf8');
52
+ }
53
+
54
+ /**
55
+ * Validate metadata against schema
56
+ * @param {Object} metadata - Metadata to validate
57
+ * @throws {Error} If metadata is invalid
58
+ */
59
+ validateMetadata(metadata) {
60
+ if (!metadata || typeof metadata !== 'object') {
61
+ throw new Error('Metadata must be an object');
62
+ }
63
+
64
+ // Required fields
65
+ if (!metadata.version) {
66
+ throw new Error('Missing required field: version');
67
+ }
68
+
69
+
70
+ if (!metadata.type || !['master', 'sub'].includes(metadata.type)) {
71
+ throw new Error('Invalid or missing type: must be "master" or "sub"');
72
+ }
73
+
74
+ // Validate dependencies array
75
+ if (metadata.dependencies) {
76
+ if (!Array.isArray(metadata.dependencies)) {
77
+ throw new Error('dependencies must be an array');
78
+ }
79
+
80
+ for (const dep of metadata.dependencies) {
81
+ if (!dep.spec || typeof dep.spec !== 'string') {
82
+ throw new Error('Each dependency must have a spec name');
83
+ }
84
+
85
+ if (!dep.type || !['requires-completion', 'requires-interface', 'optional'].includes(dep.type)) {
86
+ throw new Error(`Invalid dependency type: ${dep.type}`);
87
+ }
88
+ }
89
+ }
90
+
91
+ // Validate status
92
+ if (metadata.status) {
93
+ const validStatuses = ['not-started', 'in-progress', 'completed', 'blocked'];
94
+ if (!metadata.status.current || !validStatuses.includes(metadata.status.current)) {
95
+ throw new Error(`Invalid status: ${metadata.status.current}`);
96
+ }
97
+
98
+ if (!metadata.status.updatedAt) {
99
+ throw new Error('Status must have updatedAt timestamp');
100
+ }
101
+ }
102
+
103
+ // Validate interfaces
104
+ if (metadata.interfaces) {
105
+ if (!Array.isArray(metadata.interfaces.provides)) {
106
+ throw new Error('interfaces.provides must be an array');
107
+ }
108
+ if (!Array.isArray(metadata.interfaces.consumes)) {
109
+ throw new Error('interfaces.consumes must be an array');
110
+ }
111
+ }
112
+ }
113
+
114
+ /**
115
+ * Delete collaboration metadata for a spec
116
+ * @param {string} specName - Name of the spec
117
+ * @returns {Promise<boolean>} True if deleted, false if not found
118
+ */
119
+ async deleteMetadata(specName) {
120
+ const metadataPath = this._getMetadataPath(specName);
121
+
122
+ try {
123
+ await fs.unlink(metadataPath);
124
+ return true;
125
+ } catch (error) {
126
+ if (error.code === 'ENOENT') {
127
+ return false;
128
+ }
129
+ throw new Error(`Failed to delete metadata for ${specName}: ${error.message}`);
130
+ }
131
+ }
132
+
133
+ /**
134
+ * List all specs with collaboration metadata
135
+ * @returns {Promise<Array<{name: string, metadata: Object}>>}
136
+ */
137
+ async listAllMetadata() {
138
+ const specs = [];
139
+
140
+ try {
141
+ const specDirs = await fs.readdir(this.specsDir);
142
+
143
+ for (const specName of specDirs) {
144
+ const metadata = await this.readMetadata(specName);
145
+ if (metadata) {
146
+ specs.push({ name: specName, metadata });
147
+ }
148
+ }
149
+ } catch (error) {
150
+ if (error.code === 'ENOENT') {
151
+ return [];
152
+ }
153
+ throw error;
154
+ }
155
+
156
+ return specs;
157
+ }
158
+
159
+ /**
160
+ * Perform atomic update on metadata
161
+ * @param {string} specName - Name of the spec
162
+ * @param {Function} updateFn - Function that receives current metadata and returns updated metadata
163
+ * @returns {Promise<Object>} Updated metadata
164
+ */
165
+ async atomicUpdate(specName, updateFn) {
166
+ const maxRetries = 3;
167
+ let lastError;
168
+
169
+ for (let attempt = 0; attempt < maxRetries; attempt++) {
170
+ try {
171
+ // Read current metadata
172
+ const current = await this.readMetadata(specName) || this._getDefaultMetadata();
173
+
174
+ // Apply update function
175
+ const updated = await updateFn(current);
176
+
177
+ // Write updated metadata
178
+ await this.writeMetadata(specName, updated);
179
+
180
+ return updated;
181
+ } catch (error) {
182
+ lastError = error;
183
+
184
+ // Exponential backoff
185
+ if (attempt < maxRetries - 1) {
186
+ await this._sleep(Math.pow(2, attempt) * 100);
187
+ }
188
+ }
189
+ }
190
+
191
+ throw new Error(`Atomic update failed after ${maxRetries} attempts: ${lastError.message}`);
192
+ }
193
+
194
+ /**
195
+ * Get default metadata structure
196
+ * @returns {Object}
197
+ */
198
+ _getDefaultMetadata() {
199
+ return {
200
+ version: '1.0.0',
201
+ type: 'sub',
202
+ dependencies: [],
203
+ status: {
204
+ current: 'not-started',
205
+ updatedAt: new Date().toISOString()
206
+ },
207
+ interfaces: {
208
+ provides: [],
209
+ consumes: []
210
+ }
211
+ };
212
+ }
213
+
214
+ /**
215
+ * Get metadata file path for a spec
216
+ * @param {string} specName
217
+ * @returns {string}
218
+ */
219
+ _getMetadataPath(specName) {
220
+ return path.join(this.specsDir, specName, 'collaboration.json');
221
+ }
222
+
223
+ /**
224
+ * Sleep for specified milliseconds
225
+ * @param {number} ms
226
+ * @returns {Promise<void>}
227
+ */
228
+ _sleep(ms) {
229
+ return new Promise(resolve => setTimeout(resolve, ms));
230
+ }
231
+ }
232
+
233
+ module.exports = MetadataManager;
@@ -0,0 +1,120 @@
1
+ /**
2
+ * Multi-Agent Configuration Manager
3
+ *
4
+ * Manages `.kiro/config/multi-agent.json` for multi-Agent parallel coordination.
5
+ * When the config file does not exist or is corrupted, returns a default
6
+ * disabled configuration so that single-Agent mode is completely unaffected.
7
+ *
8
+ * Requirements: 7.1 (no extra files when disabled), 7.4 (auto-init on first enable)
9
+ */
10
+
11
+ const path = require('path');
12
+ const fsUtils = require('../utils/fs-utils');
13
+
14
+ const CONFIG_FILENAME = 'multi-agent.json';
15
+ const CONFIG_DIR = '.kiro/config';
16
+
17
+ /** @type {import('./multi-agent-config').MultiAgentConfigData} */
18
+ const DEFAULT_CONFIG = Object.freeze({
19
+ enabled: false,
20
+ heartbeatIntervalMs: 60000,
21
+ heartbeatTimeoutMs: 180000,
22
+ coordinatorEnabled: false,
23
+ maxRetries: 5,
24
+ retryBaseDelayMs: 100,
25
+ });
26
+
27
+ class MultiAgentConfig {
28
+ /**
29
+ * @param {string} workspaceRoot - Absolute path to the project root
30
+ */
31
+ constructor(workspaceRoot) {
32
+ this._workspaceRoot = workspaceRoot;
33
+ this._configPath = path.join(workspaceRoot, CONFIG_DIR, CONFIG_FILENAME);
34
+ this._configDir = path.join(workspaceRoot, CONFIG_DIR);
35
+ }
36
+
37
+ /**
38
+ * Read the current configuration.
39
+ * Returns the default (disabled) config when the file is missing or corrupted.
40
+ *
41
+ * @returns {Promise<object>} Resolved configuration
42
+ */
43
+ async getConfig() {
44
+ const exists = await fsUtils.pathExists(this._configPath);
45
+ if (!exists) {
46
+ return { ...DEFAULT_CONFIG };
47
+ }
48
+
49
+ try {
50
+ const data = await fsUtils.readJSON(this._configPath);
51
+ return { ...DEFAULT_CONFIG, ...data };
52
+ } catch (_err) {
53
+ // Corrupted JSON – fall back to defaults with a warning
54
+ console.warn(
55
+ `[MultiAgentConfig] Failed to parse ${this._configPath}, using default config`
56
+ );
57
+ return { ...DEFAULT_CONFIG };
58
+ }
59
+ }
60
+
61
+ /**
62
+ * Whether multi-Agent mode is enabled.
63
+ * @returns {Promise<boolean>}
64
+ */
65
+ async isEnabled() {
66
+ const config = await this.getConfig();
67
+ return config.enabled === true;
68
+ }
69
+
70
+ /**
71
+ * Whether the central coordinator is enabled.
72
+ * Only meaningful when multi-Agent mode itself is enabled.
73
+ * @returns {Promise<boolean>}
74
+ */
75
+ async isCoordinatorEnabled() {
76
+ const config = await this.getConfig();
77
+ return config.enabled === true && config.coordinatorEnabled === true;
78
+ }
79
+
80
+ /**
81
+ * Persist a (partial) configuration update.
82
+ * Merges the provided values with the current config and writes atomically.
83
+ * Auto-initialises the config directory on first write (Requirement 7.4).
84
+ *
85
+ * @param {object} updates - Partial config values to merge
86
+ * @returns {Promise<object>} The full config after the update
87
+ */
88
+ async updateConfig(updates) {
89
+ await fsUtils.ensureDirectory(this._configDir);
90
+ const current = await this.getConfig();
91
+ const merged = { ...current, ...updates };
92
+ await fsUtils.writeJSON(this._configPath, merged);
93
+ return merged;
94
+ }
95
+
96
+ /**
97
+ * Enable multi-Agent mode.
98
+ * Convenience wrapper that also initialises the required directory structure.
99
+ *
100
+ * @returns {Promise<object>} The full config after enabling
101
+ */
102
+ async enable() {
103
+ return this.updateConfig({ enabled: true });
104
+ }
105
+
106
+ /**
107
+ * Disable multi-Agent mode.
108
+ * @returns {Promise<object>} The full config after disabling
109
+ */
110
+ async disable() {
111
+ return this.updateConfig({ enabled: false });
112
+ }
113
+
114
+ /** Absolute path to the config file (useful for tests / diagnostics). */
115
+ get configPath() {
116
+ return this._configPath;
117
+ }
118
+ }
119
+
120
+ module.exports = { MultiAgentConfig, DEFAULT_CONFIG };