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,240 @@
1
+ /**
2
+ * Agent Registry - Manages Agent registration, heartbeat, and lifecycle
3
+ *
4
+ * Stores agent records in `.kiro/config/agent-registry.json`.
5
+ * Uses MachineIdentifier for unique Agent ID generation ({machineId}:{instanceIndex}).
6
+ * All write operations use atomic writes via fs-utils.
7
+ *
8
+ * Requirements: 1.1, 1.2, 1.3, 1.5, 1.6, 1.7
9
+ */
10
+
11
+ const path = require('path');
12
+ const fsUtils = require('../utils/fs-utils');
13
+ const { MultiAgentConfig } = require('./multi-agent-config');
14
+
15
+ const REGISTRY_FILENAME = 'agent-registry.json';
16
+ const CONFIG_DIR = '.kiro/config';
17
+
18
+ const EMPTY_REGISTRY = Object.freeze({
19
+ version: '1.0.0',
20
+ agents: {},
21
+ });
22
+
23
+ class AgentRegistry {
24
+ /**
25
+ * @param {string} workspaceRoot - Absolute path to the project root
26
+ * @param {import('../lock/machine-identifier').MachineIdentifier} machineIdentifier
27
+ * @param {import('../lock/task-lock-manager').TaskLockManager|null} [taskLockManager=null] - Optional, injected to avoid circular deps
28
+ */
29
+ constructor(workspaceRoot, machineIdentifier, taskLockManager = null) {
30
+ this._workspaceRoot = workspaceRoot;
31
+ this._machineIdentifier = machineIdentifier;
32
+ this._taskLockManager = taskLockManager;
33
+ this._registryPath = path.join(workspaceRoot, CONFIG_DIR, REGISTRY_FILENAME);
34
+ this._configDir = path.join(workspaceRoot, CONFIG_DIR);
35
+ this._multiAgentConfig = new MultiAgentConfig(workspaceRoot);
36
+ }
37
+
38
+ /**
39
+ * Read the registry file. Auto-creates an empty registry if it doesn't exist (Req 1.7).
40
+ * @returns {Promise<object>}
41
+ * @private
42
+ */
43
+ async _readRegistry() {
44
+ const exists = await fsUtils.pathExists(this._registryPath);
45
+ if (!exists) {
46
+ return { ...EMPTY_REGISTRY, agents: {} };
47
+ }
48
+ try {
49
+ const data = await fsUtils.readJSON(this._registryPath);
50
+ if (!data || typeof data.agents !== 'object') {
51
+ return { ...EMPTY_REGISTRY, agents: {} };
52
+ }
53
+ return data;
54
+ } catch (_err) {
55
+ // Corrupted file – rebuild empty registry
56
+ return { ...EMPTY_REGISTRY, agents: {} };
57
+ }
58
+ }
59
+
60
+ /**
61
+ * Persist the registry atomically.
62
+ * Ensures the config directory exists before writing (Req 1.7).
63
+ * @param {object} registry
64
+ * @returns {Promise<void>}
65
+ * @private
66
+ */
67
+ async _writeRegistry(registry) {
68
+ await fsUtils.ensureDirectory(this._configDir);
69
+ await fsUtils.writeJSON(this._registryPath, registry);
70
+ }
71
+
72
+ /**
73
+ * Find the next available instanceIndex for a given machineId.
74
+ * Scans existing agents with the same machineId and picks the lowest unused index.
75
+ * @param {object} agents - Current agents map
76
+ * @param {string} machineId
77
+ * @returns {number}
78
+ * @private
79
+ */
80
+ _nextInstanceIndex(agents, machineId) {
81
+ const usedIndices = new Set();
82
+ for (const record of Object.values(agents)) {
83
+ if (record.machineId === machineId) {
84
+ usedIndices.add(record.instanceIndex);
85
+ }
86
+ }
87
+ let index = 0;
88
+ while (usedIndices.has(index)) {
89
+ index++;
90
+ }
91
+ return index;
92
+ }
93
+
94
+ /**
95
+ * Register a new Agent. Generates a unique AgentID based on MachineIdentifier.
96
+ *
97
+ * @param {object} [options={}]
98
+ * @param {object|null} [options.currentTask] - Optional initial task assignment
99
+ * @returns {Promise<{agentId: string, registeredAt: string}>}
100
+ */
101
+ async register(options = {}) {
102
+ const machineInfo = await this._machineIdentifier.getMachineId();
103
+ const registry = await this._readRegistry();
104
+
105
+ const instanceIndex = this._nextInstanceIndex(registry.agents, machineInfo.id);
106
+ const agentId = `${machineInfo.id}:${instanceIndex}`;
107
+ const now = new Date().toISOString();
108
+
109
+ registry.agents[agentId] = {
110
+ agentId,
111
+ machineId: machineInfo.id,
112
+ instanceIndex,
113
+ hostname: machineInfo.hostname,
114
+ registeredAt: now,
115
+ lastHeartbeat: now,
116
+ status: 'active',
117
+ currentTask: options.currentTask || null,
118
+ };
119
+
120
+ await this._writeRegistry(registry);
121
+
122
+ return { agentId, registeredAt: now };
123
+ }
124
+
125
+ /**
126
+ * Deregister an Agent. Removes the record and releases associated resources.
127
+ *
128
+ * @param {string} agentId
129
+ * @returns {Promise<{success: boolean, releasedLocks: Array<{specName: string, taskId: string}>}>}
130
+ */
131
+ async deregister(agentId) {
132
+ const registry = await this._readRegistry();
133
+
134
+ if (!registry.agents[agentId]) {
135
+ return { success: false, releasedLocks: [] };
136
+ }
137
+
138
+ delete registry.agents[agentId];
139
+ await this._writeRegistry(registry);
140
+
141
+ // Release all task locks held by this agent (Req 1.6)
142
+ let releasedLocks = [];
143
+ if (this._taskLockManager) {
144
+ const result = await this._taskLockManager.releaseAllLocks(agentId);
145
+ releasedLocks = result.released;
146
+ }
147
+
148
+ return { success: true, releasedLocks };
149
+ }
150
+
151
+ /**
152
+ * Update heartbeat timestamp for an Agent.
153
+ *
154
+ * @param {string} agentId
155
+ * @returns {Promise<{success: boolean, lastHeartbeat: string|null}>}
156
+ */
157
+ async heartbeat(agentId) {
158
+ const registry = await this._readRegistry();
159
+ const agent = registry.agents[agentId];
160
+
161
+ if (!agent) {
162
+ return { success: false, lastHeartbeat: null };
163
+ }
164
+
165
+ const now = new Date().toISOString();
166
+ agent.lastHeartbeat = now;
167
+ agent.status = 'active';
168
+
169
+ await this._writeRegistry(registry);
170
+
171
+ return { success: true, lastHeartbeat: now };
172
+ }
173
+
174
+ /**
175
+ * Get all agents with status 'active'.
176
+ * @returns {Promise<object[]>}
177
+ */
178
+ async getActiveAgents() {
179
+ const registry = await this._readRegistry();
180
+ return Object.values(registry.agents).filter((a) => a.status === 'active');
181
+ }
182
+
183
+ /**
184
+ * Get a specific Agent record by ID.
185
+ * @param {string} agentId
186
+ * @returns {Promise<object|null>}
187
+ */
188
+ async getAgent(agentId) {
189
+ const registry = await this._readRegistry();
190
+ return registry.agents[agentId] || null;
191
+ }
192
+
193
+ /**
194
+ * Detect and clean up inactive Agents whose heartbeat has timed out.
195
+ * Uses heartbeatTimeoutMs from MultiAgentConfig (default 180 000 ms).
196
+ * Releases all task locks held by each inactive Agent (Req 1.4, 2.4).
197
+ *
198
+ * @returns {Promise<{cleaned: string[], releasedLocks: Array<{specName: string, taskId: string}>}>}
199
+ */
200
+ async cleanupInactive() {
201
+ const config = await this._multiAgentConfig.getConfig();
202
+ const timeoutMs = config.heartbeatTimeoutMs;
203
+ const now = Date.now();
204
+
205
+ const registry = await this._readRegistry();
206
+ const cleaned = [];
207
+
208
+ for (const agent of Object.values(registry.agents)) {
209
+ if (agent.status !== 'active') continue;
210
+
211
+ const lastBeat = new Date(agent.lastHeartbeat).getTime();
212
+ if (now - lastBeat > timeoutMs) {
213
+ agent.status = 'inactive';
214
+ cleaned.push(agent.agentId);
215
+ }
216
+ }
217
+
218
+ if (cleaned.length > 0) {
219
+ await this._writeRegistry(registry);
220
+ }
221
+
222
+ // Release all task locks for each cleaned agent (Req 1.4, 2.4)
223
+ const releasedLocks = [];
224
+ if (this._taskLockManager && cleaned.length > 0) {
225
+ for (const agentId of cleaned) {
226
+ const result = await this._taskLockManager.releaseAllLocks(agentId);
227
+ releasedLocks.push(...result.released);
228
+ }
229
+ }
230
+
231
+ return { cleaned, releasedLocks };
232
+ }
233
+
234
+ /** Absolute path to the registry file (useful for tests / diagnostics). */
235
+ get registryPath() {
236
+ return this._registryPath;
237
+ }
238
+ }
239
+
240
+ module.exports = { AgentRegistry, EMPTY_REGISTRY };
@@ -0,0 +1,285 @@
1
+ const MetadataManager = require('./metadata-manager');
2
+ const DependencyManager = require('./dependency-manager');
3
+ const ContractManager = require('./contract-manager');
4
+ const IntegrationManager = require('./integration-manager');
5
+ const Visualizer = require('./visualizer');
6
+
7
+ /**
8
+ * CollaborationManager orchestrates all collaboration operations
9
+ */
10
+ class CollaborationManager {
11
+ constructor(workspaceRoot) {
12
+ this.workspaceRoot = workspaceRoot;
13
+
14
+ // Initialize managers
15
+ this.metadataManager = new MetadataManager(workspaceRoot);
16
+ this.dependencyManager = new DependencyManager(this.metadataManager);
17
+ this.contractManager = new ContractManager(workspaceRoot, this.metadataManager);
18
+ this.integrationManager = new IntegrationManager(workspaceRoot, this.metadataManager);
19
+ this.visualizer = new Visualizer();
20
+ }
21
+
22
+ /**
23
+ * Initialize a Master Spec with Sub-Specs
24
+ * @param {string} masterName - Name of the master spec
25
+ * @param {Array<Object>} subSpecs - Array of {name, dependencies}
26
+ * @param {Object} options - Additional options
27
+ * @returns {Promise<Object>} Creation result
28
+ */
29
+ async initMasterSpec(masterName, subSpecs, options = {}) {
30
+ // Create master spec metadata
31
+ const masterMetadata = {
32
+ version: '1.0.0',
33
+ type: 'master',
34
+ subSpecs: subSpecs.map(s => s.name),
35
+ dependencies: [],
36
+ status: {
37
+ current: 'in-progress',
38
+ updatedAt: new Date().toISOString()
39
+ },
40
+ interfaces: {
41
+ provides: [],
42
+ consumes: []
43
+ }
44
+ };
45
+
46
+ await this.metadataManager.writeMetadata(masterName, masterMetadata);
47
+
48
+ // Create sub-spec metadata
49
+ const created = [];
50
+ for (const subSpec of subSpecs) {
51
+ const subMetadata = {
52
+ version: '1.0.0',
53
+ type: 'sub',
54
+ masterSpec: masterName,
55
+ dependencies: subSpec.dependencies || [],
56
+ status: {
57
+ current: 'not-started',
58
+ updatedAt: new Date().toISOString()
59
+ },
60
+ interfaces: {
61
+ provides: [],
62
+ consumes: []
63
+ }
64
+ };
65
+
66
+ await this.metadataManager.writeMetadata(subSpec.name, subMetadata);
67
+ created.push(subSpec.name);
68
+ }
69
+
70
+ // Validate dependencies
71
+ const graph = await this.dependencyManager.buildDependencyGraph();
72
+ const cycle = this.dependencyManager.detectCircularDependencies(graph);
73
+
74
+ if (cycle) {
75
+ return {
76
+ success: false,
77
+ error: `Circular dependency detected: ${cycle.join(' → ')}`,
78
+ created: [masterName, ...created]
79
+ };
80
+ }
81
+
82
+ return {
83
+ success: true,
84
+ master: masterName,
85
+ subSpecs: created,
86
+ message: `Created master spec '${masterName}' with ${created.length} sub-specs`
87
+ };
88
+ }
89
+
90
+ /**
91
+ * Get collaboration status for all specs or a specific spec
92
+ * @param {string} specName - Optional spec name
93
+ * @returns {Promise<Object>} Status information
94
+ */
95
+ async getCollaborationStatus(specName = null) {
96
+ if (specName) {
97
+ const metadata = await this.metadataManager.readMetadata(specName);
98
+ if (!metadata) {
99
+ return {
100
+ found: false,
101
+ error: `Spec '${specName}' not found`
102
+ };
103
+ }
104
+
105
+ return {
106
+ found: true,
107
+ spec: specName,
108
+ metadata
109
+ };
110
+ }
111
+
112
+ // Get all specs
113
+ const allSpecs = await this.metadataManager.listAllMetadata();
114
+ const graph = await this.dependencyManager.buildDependencyGraph();
115
+ const ready = this.dependencyManager.getReadySpecs(graph);
116
+
117
+ return {
118
+ total: allSpecs.length,
119
+ specs: allSpecs,
120
+ ready,
121
+ graph
122
+ };
123
+ }
124
+
125
+ /**
126
+ * Assign a spec to a Kiro instance
127
+ * @param {string} specName - Name of the spec
128
+ * @param {string} kiroInstance - Kiro instance identifier
129
+ * @returns {Promise<Object>} Assignment result
130
+ */
131
+ async assignSpec(specName, kiroInstance) {
132
+ const metadata = await this.metadataManager.readMetadata(specName);
133
+
134
+ if (!metadata) {
135
+ return {
136
+ success: false,
137
+ error: `Spec '${specName}' not found`
138
+ };
139
+ }
140
+
141
+ // Check if blocked
142
+ if (metadata.status.current === 'blocked') {
143
+ return {
144
+ success: false,
145
+ error: `Cannot assign blocked spec (reason: ${metadata.status.blockReason || 'unknown'})`
146
+ };
147
+ }
148
+
149
+ // Update assignment
150
+ const updated = await this.metadataManager.atomicUpdate(specName, (meta) => {
151
+ meta.assignment = {
152
+ kiroInstance,
153
+ assignedAt: new Date().toISOString()
154
+ };
155
+ return meta;
156
+ });
157
+
158
+ return {
159
+ success: true,
160
+ spec: specName,
161
+ kiroInstance,
162
+ message: `Assigned '${specName}' to '${kiroInstance}'`
163
+ };
164
+ }
165
+
166
+ /**
167
+ * Update spec status
168
+ * @param {string} specName - Name of the spec
169
+ * @param {string} status - New status
170
+ * @param {string} reason - Optional reason (for blocked status)
171
+ * @returns {Promise<Object>} Update result
172
+ */
173
+ async updateSpecStatus(specName, status, reason = null) {
174
+ const validStatuses = ['not-started', 'in-progress', 'completed', 'blocked'];
175
+
176
+ if (!validStatuses.includes(status)) {
177
+ return {
178
+ success: false,
179
+ error: `Invalid status: ${status}`
180
+ };
181
+ }
182
+
183
+ const updated = await this.metadataManager.atomicUpdate(specName, (meta) => {
184
+ meta.status = {
185
+ current: status,
186
+ updatedAt: new Date().toISOString()
187
+ };
188
+
189
+ if (status === 'blocked' && reason) {
190
+ meta.status.blockReason = reason;
191
+ }
192
+
193
+ return meta;
194
+ });
195
+
196
+ // If completed, update dependent specs
197
+ if (status === 'completed') {
198
+ const nowReady = await this.dependencyManager.updateDependentSpecs(specName);
199
+ return {
200
+ success: true,
201
+ spec: specName,
202
+ status,
203
+ nowReady,
204
+ message: `Updated '${specName}' to '${status}'. ${nowReady.length} specs now ready.`
205
+ };
206
+ }
207
+
208
+ return {
209
+ success: true,
210
+ spec: specName,
211
+ status,
212
+ message: `Updated '${specName}' to '${status}'`
213
+ };
214
+ }
215
+
216
+ /**
217
+ * Verify contracts for a spec
218
+ * @param {string} specName - Name of the spec
219
+ * @returns {Promise<Object>} Verification result
220
+ */
221
+ async verifyContracts(specName) {
222
+ return await this.contractManager.verifyImplementation(specName);
223
+ }
224
+
225
+ /**
226
+ * Run integration tests
227
+ * @param {Array<string>} specNames - Specs to test
228
+ * @returns {Promise<Object>} Test results
229
+ */
230
+ async runIntegrationTests(specNames) {
231
+ return await this.integrationManager.runAllTests(specNames);
232
+ }
233
+
234
+ /**
235
+ * Generate dependency graph visualization
236
+ * @param {string} format - Format ('text' or 'mermaid')
237
+ * @param {Object} options - Visualization options
238
+ * @returns {Promise<string>} Graph visualization
239
+ */
240
+ async generateDependencyGraph(format = 'text', options = {}) {
241
+ const graph = await this.dependencyManager.buildDependencyGraph();
242
+
243
+ if (format === 'mermaid') {
244
+ return this.visualizer.generateMermaidGraph(graph);
245
+ }
246
+
247
+ return this.visualizer.generateTextGraph(graph, options);
248
+ }
249
+
250
+ /**
251
+ * Validate all dependencies
252
+ * @param {string} specName - Optional spec name to validate
253
+ * @returns {Promise<Object>} Validation result
254
+ */
255
+ async validateDependencies(specName = null) {
256
+ const graph = await this.dependencyManager.buildDependencyGraph(
257
+ specName ? [specName] : null
258
+ );
259
+
260
+ const cycle = this.dependencyManager.detectCircularDependencies(graph);
261
+
262
+ if (cycle) {
263
+ return {
264
+ valid: false,
265
+ error: `Circular dependency detected: ${cycle.join(' → ')}`
266
+ };
267
+ }
268
+
269
+ return {
270
+ valid: true,
271
+ message: 'All dependencies are valid'
272
+ };
273
+ }
274
+
275
+ /**
276
+ * Get ready specs (specs that can be started)
277
+ * @returns {Promise<Array<string>>} List of ready spec names
278
+ */
279
+ async getReadySpecs() {
280
+ const graph = await this.dependencyManager.buildDependencyGraph();
281
+ return this.dependencyManager.getReadySpecs(graph);
282
+ }
283
+ }
284
+
285
+ module.exports = CollaborationManager;