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,70 @@
1
+ const chalk = require('chalk');
2
+
3
+ /**
4
+ * ComplianceErrorReporter - Formats and displays compliance violations
5
+ *
6
+ * Creates user-friendly error messages with clear sections,
7
+ * violation details, and actionable fix suggestions.
8
+ */
9
+ class ComplianceErrorReporter {
10
+ /**
11
+ * Format compliance violations into user-friendly message
12
+ *
13
+ * @param {ComplianceViolation[]} violations - List of violations
14
+ * @returns {string} Formatted error message
15
+ */
16
+ formatError(violations) {
17
+ const disallowedFiles = violations.filter(v => v.type === 'disallowed_file');
18
+ const subdirectories = violations.filter(v => v.type === 'subdirectory');
19
+
20
+ let message = '\n';
21
+ message += chalk.red.bold('❌ Steering Directory Compliance Check Failed') + '\n\n';
22
+ message += 'The .kiro/steering/ directory contains files or subdirectories that are not allowed.\n';
23
+ message += 'This directory is automatically loaded in every AI session, so keeping it clean is critical.\n\n';
24
+
25
+ message += chalk.yellow.bold('Violations Found:') + '\n';
26
+
27
+ if (disallowedFiles.length > 0) {
28
+ message += ' • ' + chalk.yellow('Disallowed files:') + '\n';
29
+ disallowedFiles.forEach(v => {
30
+ message += ` - ${v.name}\n`;
31
+ });
32
+ }
33
+
34
+ if (subdirectories.length > 0) {
35
+ message += ' • ' + chalk.yellow('Subdirectories (not allowed):') + '\n';
36
+ subdirectories.forEach(v => {
37
+ message += ` - ${v.name}/\n`;
38
+ });
39
+ }
40
+
41
+ message += '\n' + chalk.green.bold('Allowed Files:') + '\n';
42
+ message += ' ✓ CORE_PRINCIPLES.md\n';
43
+ message += ' ✓ ENVIRONMENT.md\n';
44
+ message += ' ✓ CURRENT_CONTEXT.md\n';
45
+ message += ' ✓ RULES_GUIDE.md\n';
46
+
47
+ message += '\n' + chalk.cyan.bold('Fix Suggestions:') + '\n';
48
+ message += ' • Move analysis reports to: .kiro/specs/{spec-name}/reports/\n';
49
+ message += ' • Move historical data to: .kiro/specs/{spec-name}/\n';
50
+ message += ' • Move detailed docs to: docs/\n';
51
+ message += ' • Delete temporary files\n';
52
+
53
+ message += '\n' + chalk.gray('To bypass this check (not recommended):') + '\n';
54
+ message += chalk.gray(' kse <command> --skip-steering-check') + '\n';
55
+
56
+ return message;
57
+ }
58
+
59
+ /**
60
+ * Display error and exit
61
+ *
62
+ * @param {ComplianceViolation[]} violations - List of violations
63
+ */
64
+ reportAndExit(violations) {
65
+ console.error(this.formatError(violations));
66
+ process.exit(1);
67
+ }
68
+ }
69
+
70
+ module.exports = ComplianceErrorReporter;
@@ -0,0 +1,273 @@
1
+ /**
2
+ * ContextSyncManager - Maintains CURRENT_CONTEXT.md as multi-Spec progress summary
3
+ *
4
+ * Parses and formats CURRENT_CONTEXT.md between Markdown and structured objects.
5
+ * Uses SteeringFileLock for concurrent write protection in multi-Agent mode.
6
+ * In single-Agent mode, updateSpecProgress is a no-op.
7
+ *
8
+ * Requirements: 3.1, 3.2, 3.3, 3.4, 3.5, 6.2
9
+ */
10
+
11
+ const path = require('path');
12
+ const fs = require('fs-extra');
13
+ const fsUtils = require('../utils/fs-utils');
14
+ const { MultiAgentConfig } = require('../collab/multi-agent-config');
15
+
16
+ const STEERING_DIR = '.kiro/steering';
17
+ const CONTEXT_FILENAME = 'CURRENT_CONTEXT.md';
18
+ const SPECS_DIR = '.kiro/specs';
19
+
20
+ class ContextSyncManager {
21
+ /**
22
+ * @param {string} workspaceRoot - Absolute path to the project root
23
+ * @param {import('../lock/steering-file-lock').SteeringFileLock} steeringFileLock
24
+ */
25
+ constructor(workspaceRoot, steeringFileLock) {
26
+ this._workspaceRoot = workspaceRoot;
27
+ this._steeringFileLock = steeringFileLock;
28
+ this._multiAgentConfig = new MultiAgentConfig(workspaceRoot);
29
+ this._contextPath = path.join(workspaceRoot, STEERING_DIR, CONTEXT_FILENAME);
30
+ }
31
+
32
+ /**
33
+ * Update the progress entry for a specific Spec.
34
+ * Uses SteeringFileLock for concurrent write protection.
35
+ * Single-Agent mode: no-op returning {success: true}.
36
+ *
37
+ * @param {string} specName
38
+ * @param {{status: string, progress: number, summary: string}} entry
39
+ * @returns {Promise<{success: boolean}>}
40
+ */
41
+ async updateSpecProgress(specName, entry) {
42
+ const enabled = await this._multiAgentConfig.isEnabled();
43
+ if (!enabled) {
44
+ return { success: true };
45
+ }
46
+
47
+ await this._steeringFileLock.withLock(CONTEXT_FILENAME, async () => {
48
+ const context = await this.readContext();
49
+ context.specs[specName] = {
50
+ status: entry.status,
51
+ progress: entry.progress,
52
+ summary: entry.summary,
53
+ };
54
+ await this.writeContext(context);
55
+ });
56
+
57
+ return { success: true };
58
+ }
59
+
60
+ /**
61
+ * Read and parse CURRENT_CONTEXT.md into a structured object.
62
+ * Returns default empty object if file doesn't exist.
63
+ *
64
+ * @returns {Promise<{version: string|null, globalStatus: string|null, specs: object}>}
65
+ */
66
+ async readContext() {
67
+ const exists = await fs.pathExists(this._contextPath);
68
+ if (!exists) {
69
+ return { version: null, globalStatus: null, specs: {} };
70
+ }
71
+
72
+ try {
73
+ const content = await fs.readFile(this._contextPath, 'utf8');
74
+ return this.parseContext(content);
75
+ } catch (err) {
76
+ console.warn(`[ContextSyncManager] Failed to read ${this._contextPath}: ${err.message}`);
77
+ return { version: null, globalStatus: null, specs: {} };
78
+ }
79
+ }
80
+
81
+ /**
82
+ * Write a structured context object back to CURRENT_CONTEXT.md.
83
+ * Uses atomic write for file integrity.
84
+ *
85
+ * @param {{version: string|null, globalStatus: string|null, specs: object}} context
86
+ * @returns {Promise<void>}
87
+ */
88
+ async writeContext(context) {
89
+ const dir = path.dirname(this._contextPath);
90
+ await fsUtils.ensureDirectory(dir);
91
+ const content = this.formatContext(context);
92
+ await fsUtils.atomicWrite(this._contextPath, content);
93
+ }
94
+
95
+ /**
96
+ * Compute progress percentage for a Spec based on tasks.md completion.
97
+ * Counts only leaf tasks (lines matching checkbox patterns).
98
+ *
99
+ * @param {string} specName
100
+ * @returns {Promise<number>} 0-100
101
+ */
102
+ async computeProgress(specName) {
103
+ const tasksPath = path.join(this._workspaceRoot, SPECS_DIR, specName, 'tasks.md');
104
+ const exists = await fs.pathExists(tasksPath);
105
+ if (!exists) {
106
+ return 0;
107
+ }
108
+
109
+ try {
110
+ const content = await fs.readFile(tasksPath, 'utf8');
111
+ return this._computeProgressFromContent(content);
112
+ } catch (err) {
113
+ console.warn(`[ContextSyncManager] Failed to read ${tasksPath}: ${err.message}`);
114
+ return 0;
115
+ }
116
+ }
117
+
118
+ /**
119
+ * Parse CURRENT_CONTEXT.md Markdown content into a structured object.
120
+ * Handles both old single-agent format and new multi-agent table format.
121
+ *
122
+ * @param {string} content
123
+ * @returns {{version: string|null, globalStatus: string|null, specs: object}}
124
+ */
125
+ parseContext(content) {
126
+ const result = { version: null, globalStatus: null, specs: {} };
127
+
128
+ if (!content || typeof content !== 'string') {
129
+ return result;
130
+ }
131
+
132
+ const lines = content.split('\n');
133
+
134
+ for (const line of lines) {
135
+ const trimmed = line.trim();
136
+
137
+ // Parse version line: **版本**: ...
138
+ const versionMatch = trimmed.match(/^\*\*版本\*\*:\s*(.+)$/);
139
+ if (versionMatch) {
140
+ result.version = versionMatch[1].trim();
141
+ continue;
142
+ }
143
+
144
+ // Parse global status line: **状态**: ...
145
+ const statusMatch = trimmed.match(/^\*\*状态\*\*:\s*(.+)$/);
146
+ if (statusMatch) {
147
+ result.globalStatus = statusMatch[1].trim();
148
+ continue;
149
+ }
150
+
151
+ // Parse table rows for Spec progress
152
+ // Format: | spec-name | status | progress% | summary |
153
+ if (trimmed.startsWith('|') && !trimmed.startsWith('|---') && !trimmed.startsWith('| Spec')) {
154
+ const cells = trimmed.split('|').map(c => c.trim()).filter(c => c.length > 0);
155
+ if (cells.length >= 4) {
156
+ const specName = cells[0];
157
+ const status = cells[1];
158
+ const progressStr = cells[2].replace('%', '');
159
+ const progress = parseInt(progressStr, 10);
160
+ const summary = cells[3];
161
+
162
+ if (specName && status && !isNaN(progress)) {
163
+ result.specs[specName] = { status, progress, summary };
164
+ }
165
+ }
166
+ }
167
+ }
168
+
169
+ return result;
170
+ }
171
+
172
+ /**
173
+ * Format a structured context object into CURRENT_CONTEXT.md Markdown.
174
+ *
175
+ * @param {{version: string|null, globalStatus: string|null, specs: object}} context
176
+ * @returns {string}
177
+ */
178
+ formatContext(context) {
179
+ const lines = [];
180
+
181
+ lines.push('# 当前场景');
182
+ lines.push('');
183
+
184
+ if (context.version) {
185
+ lines.push(`**版本**: ${context.version}`);
186
+ }
187
+ if (context.globalStatus) {
188
+ lines.push(`**状态**: ${context.globalStatus}`);
189
+ }
190
+
191
+ const specEntries = Object.entries(context.specs || {});
192
+ if (specEntries.length > 0) {
193
+ lines.push('');
194
+ lines.push('## Spec 进度');
195
+ lines.push('');
196
+ lines.push('| Spec | 状态 | 进度 | 摘要 |');
197
+ lines.push('|------|------|------|------|');
198
+
199
+ for (const [name, entry] of specEntries) {
200
+ const status = entry.status || '';
201
+ const progress = entry.progress != null ? `${entry.progress}%` : '0%';
202
+ const summary = entry.summary || '';
203
+ lines.push(`| ${name} | ${status} | ${progress} | ${summary} |`);
204
+ }
205
+ }
206
+
207
+ lines.push('');
208
+ lines.push('---');
209
+ lines.push('');
210
+ const now = new Date();
211
+ const dateStr = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}`;
212
+ lines.push(`v1.0 | ${dateStr} | 自动更新`);
213
+ lines.push('');
214
+
215
+ return lines.join('\n');
216
+ }
217
+
218
+ // ── Private helpers ──────────────────────────────────────────────
219
+
220
+ /**
221
+ * Compute progress from tasks.md content.
222
+ * Counts only leaf tasks (lines with checkbox patterns that have no sub-tasks).
223
+ *
224
+ * @param {string} content
225
+ * @returns {number} 0-100
226
+ * @private
227
+ */
228
+ _computeProgressFromContent(content) {
229
+ const lines = content.split('\n');
230
+ // Checkbox pattern: - [ ], - [x], - [-], - [~]
231
+ const taskPattern = /^(\s*)- \[([ x\-~])\]\*?\s/;
232
+
233
+ // First pass: identify all task lines with their indentation levels
234
+ const tasks = [];
235
+ for (let i = 0; i < lines.length; i++) {
236
+ const match = lines[i].match(taskPattern);
237
+ if (match) {
238
+ tasks.push({
239
+ index: i,
240
+ indent: match[1].length,
241
+ status: match[2],
242
+ });
243
+ }
244
+ }
245
+
246
+ // Second pass: identify leaf tasks (tasks with no sub-tasks)
247
+ let total = 0;
248
+ let completed = 0;
249
+
250
+ for (let i = 0; i < tasks.length; i++) {
251
+ const current = tasks[i];
252
+ const next = tasks[i + 1];
253
+
254
+ // A task is a leaf if the next task is not more indented
255
+ const isLeaf = !next || next.indent <= current.indent;
256
+
257
+ if (isLeaf) {
258
+ total++;
259
+ if (current.status === 'x') {
260
+ completed++;
261
+ }
262
+ }
263
+ }
264
+
265
+ if (total === 0) {
266
+ return 0;
267
+ }
268
+
269
+ return Math.round(completed / total * 100);
270
+ }
271
+ }
272
+
273
+ module.exports = { ContextSyncManager };
@@ -0,0 +1,92 @@
1
+ const path = require('path');
2
+ const SteeringComplianceChecker = require('./steering-compliance-checker');
3
+ const ComplianceCache = require('./compliance-cache');
4
+ const ComplianceErrorReporter = require('./compliance-error-reporter');
5
+ const ComplianceAutoFixer = require('./compliance-auto-fixer');
6
+ const { SpecSteering } = require('./spec-steering');
7
+ const { SteeringLoader } = require('./steering-loader');
8
+ const { ContextSyncManager } = require('./context-sync-manager');
9
+
10
+ /**
11
+ * Run steering directory compliance check
12
+ *
13
+ * @param {Object} options - Check options
14
+ * @param {boolean} options.skip - Skip the check entirely
15
+ * @param {boolean} options.force - Force check even if cache is valid
16
+ * @param {string} options.projectPath - Project root path (defaults to cwd)
17
+ * @param {string} options.version - Current kse version
18
+ * @returns {boolean} True if compliant or check skipped, false otherwise
19
+ */
20
+ async function runSteeringComplianceCheck(options = {}) {
21
+ const {
22
+ skip = false,
23
+ force = false,
24
+ projectPath = process.cwd(),
25
+ version = require('../../package.json').version
26
+ } = options;
27
+
28
+ // Skip check if requested
29
+ if (skip) {
30
+ return true;
31
+ }
32
+
33
+ try {
34
+ const checker = new SteeringComplianceChecker();
35
+ const cache = new ComplianceCache();
36
+ const reporter = new ComplianceErrorReporter();
37
+ const fixer = new ComplianceAutoFixer();
38
+
39
+ // Check cache unless forced
40
+ if (!force && cache.isValid(version)) {
41
+ // Cache is valid, skip check
42
+ return true;
43
+ }
44
+
45
+ // Perform compliance check with performance measurement
46
+ const startTime = Date.now();
47
+ const steeringPath = path.join(projectPath, '.kiro', 'steering');
48
+ const result = checker.check(steeringPath);
49
+ const duration = Date.now() - startTime;
50
+
51
+ // Log warning if check exceeds performance target
52
+ if (duration > 50) {
53
+ console.warn(`Warning: Steering compliance check took ${duration}ms (target: <50ms)`);
54
+ }
55
+
56
+ if (!result.compliant) {
57
+ // Auto-fix violations
58
+ console.log(''); // Empty line for better formatting
59
+ const fixResult = await fixer.fix(steeringPath, result.violations);
60
+
61
+ if (fixResult.success) {
62
+ console.log('✓ Steering directory is now compliant\n');
63
+ // Update cache after successful fix
64
+ cache.update(version);
65
+ return true;
66
+ } else {
67
+ // If fix failed, report and exit
68
+ reporter.reportAndExit(result.violations);
69
+ return false;
70
+ }
71
+ }
72
+
73
+ // Update cache on success
74
+ cache.update(version);
75
+ return true;
76
+ } catch (error) {
77
+ // Log error but don't block execution
78
+ console.warn(`Warning: Steering compliance check failed: ${error.message}`);
79
+ return true; // Allow execution to proceed
80
+ }
81
+ }
82
+
83
+ module.exports = {
84
+ runSteeringComplianceCheck,
85
+ SteeringComplianceChecker,
86
+ ComplianceCache,
87
+ ComplianceErrorReporter,
88
+ ComplianceAutoFixer,
89
+ SpecSteering,
90
+ SteeringLoader,
91
+ ContextSyncManager
92
+ };
@@ -0,0 +1,230 @@
1
+ /**
2
+ * SpecSteering - Spec 级 steering.md 管理
3
+ *
4
+ * 负责 `.kiro/specs/{spec-name}/steering.md` 的 CRUD 操作和模板管理。
5
+ * 在单 Agent 模式下 createTemplate 为 no-op。
6
+ *
7
+ * Requirements: 1.1, 1.3, 1.4, 7.1, 7.2, 7.3
8
+ */
9
+
10
+ const path = require('path');
11
+ const fs = require('fs-extra');
12
+ const fsUtils = require('../utils/fs-utils');
13
+ const { MultiAgentConfig } = require('../collab/multi-agent-config');
14
+
15
+ const STEERING_FILENAME = 'steering.md';
16
+ const SPECS_DIR = '.kiro/specs';
17
+
18
+ /**
19
+ * Section headers used in steering.md template.
20
+ * Order matters for format output.
21
+ */
22
+ const SECTIONS = [
23
+ { key: 'constraints', header: '## 约束 (Constraints)' },
24
+ { key: 'notes', header: '## 注意事项 (Notes)' },
25
+ { key: 'decisions', header: '## 决策记录 (Decisions)' },
26
+ ];
27
+
28
+ class SpecSteering {
29
+ /**
30
+ * @param {string} workspaceRoot - Absolute path to the project root
31
+ */
32
+ constructor(workspaceRoot) {
33
+ this._workspaceRoot = workspaceRoot;
34
+ this._multiAgentConfig = new MultiAgentConfig(workspaceRoot);
35
+ }
36
+
37
+ /**
38
+ * Build the absolute path to a Spec's steering.md.
39
+ * @param {string} specName
40
+ * @returns {string}
41
+ */
42
+ _steeringPath(specName) {
43
+ return path.join(this._workspaceRoot, SPECS_DIR, specName, STEERING_FILENAME);
44
+ }
45
+
46
+ /**
47
+ * Generate a steering.md template for the given Spec.
48
+ * Only executes in multi-Agent mode; single-Agent mode returns no-op.
49
+ *
50
+ * @param {string} specName
51
+ * @returns {Promise<{created: boolean, path: string}>}
52
+ */
53
+ async createTemplate(specName) {
54
+ const enabled = await this._multiAgentConfig.isEnabled();
55
+ if (!enabled) {
56
+ return { created: false, path: '' };
57
+ }
58
+
59
+ const filePath = this._steeringPath(specName);
60
+
61
+ // Don't overwrite an existing steering.md
62
+ const exists = await fs.pathExists(filePath);
63
+ if (exists) {
64
+ return { created: false, path: filePath };
65
+ }
66
+
67
+ const specDir = path.dirname(filePath);
68
+ await fsUtils.ensureDirectory(specDir);
69
+
70
+ const template = this.format({
71
+ constraints: [],
72
+ notes: [],
73
+ decisions: [],
74
+ }, specName);
75
+
76
+ await fsUtils.atomicWrite(filePath, template);
77
+ return { created: true, path: filePath };
78
+ }
79
+
80
+ /**
81
+ * Read and parse a Spec's steering.md into a structured object.
82
+ * Returns null if the file does not exist.
83
+ * Returns empty arrays if the file is corrupted / unparseable.
84
+ *
85
+ * @param {string} specName
86
+ * @returns {Promise<{constraints: string[], notes: string[], decisions: string[]}|null>}
87
+ */
88
+ async read(specName) {
89
+ const filePath = this._steeringPath(specName);
90
+ const exists = await fs.pathExists(filePath);
91
+ if (!exists) {
92
+ return null;
93
+ }
94
+
95
+ try {
96
+ const content = await fs.readFile(filePath, 'utf8');
97
+ return this.parse(content);
98
+ } catch (err) {
99
+ console.warn(`[SpecSteering] Failed to read ${filePath}: ${err.message}`);
100
+ return { constraints: [], notes: [], decisions: [] };
101
+ }
102
+ }
103
+
104
+ /**
105
+ * Write a structured object back to steering.md using atomic write.
106
+ *
107
+ * @param {string} specName
108
+ * @param {{constraints: string[], notes: string[], decisions: string[]}} data
109
+ * @returns {Promise<void>}
110
+ */
111
+ async write(specName, data) {
112
+ const filePath = this._steeringPath(specName);
113
+ const specDir = path.dirname(filePath);
114
+ await fsUtils.ensureDirectory(specDir);
115
+
116
+ const content = this.format(data, specName);
117
+ await fsUtils.atomicWrite(filePath, content);
118
+ }
119
+
120
+ /**
121
+ * Parse steering.md Markdown content into a structured object.
122
+ * Gracefully handles corrupted / unexpected content by returning empty arrays.
123
+ *
124
+ * @param {string} content - Markdown string
125
+ * @returns {{constraints: string[], notes: string[], decisions: string[]}}
126
+ */
127
+ parse(content) {
128
+ const result = { constraints: [], notes: [], decisions: [] };
129
+
130
+ if (!content || typeof content !== 'string') {
131
+ return result;
132
+ }
133
+
134
+ try {
135
+ const lines = content.split('\n');
136
+ let currentSection = null;
137
+
138
+ for (const line of lines) {
139
+ const trimmed = line.trim();
140
+
141
+ // Detect section headers
142
+ const section = this._detectSection(trimmed);
143
+ if (section) {
144
+ currentSection = section;
145
+ continue;
146
+ }
147
+
148
+ // Collect list items under the current section
149
+ if (currentSection && trimmed.startsWith('- ')) {
150
+ const item = trimmed.slice(2).trim();
151
+ if (item && !item.startsWith('[') ) {
152
+ // Skip placeholder items like "[约束条目]"
153
+ result[currentSection].push(item);
154
+ }
155
+ }
156
+ }
157
+ } catch (err) {
158
+ console.warn(`[SpecSteering] Failed to parse steering.md content: ${err.message}`);
159
+ return { constraints: [], notes: [], decisions: [] };
160
+ }
161
+
162
+ return result;
163
+ }
164
+
165
+ /**
166
+ * Format a structured object into steering.md Markdown.
167
+ *
168
+ * @param {{constraints: string[], notes: string[], decisions: string[]}} data
169
+ * @param {string} [specName=''] - Used for the title line
170
+ * @returns {string}
171
+ */
172
+ format(data, specName = '') {
173
+ const lines = [];
174
+
175
+ // Title
176
+ lines.push(`# Spec Steering: ${specName}`);
177
+ lines.push('');
178
+
179
+ for (const { key, header } of SECTIONS) {
180
+ lines.push(header);
181
+ lines.push('');
182
+
183
+ const items = (data && Array.isArray(data[key])) ? data[key] : [];
184
+ if (items.length === 0) {
185
+ // Empty section placeholder
186
+ lines.push(`- [${this._placeholderFor(key)}]`);
187
+ } else {
188
+ for (const item of items) {
189
+ lines.push(`- ${item}`);
190
+ }
191
+ }
192
+
193
+ lines.push('');
194
+ }
195
+
196
+ return lines.join('\n');
197
+ }
198
+
199
+ // ── Private helpers ──────────────────────────────────────────────
200
+
201
+ /**
202
+ * Detect which section a header line belongs to.
203
+ * @param {string} trimmedLine
204
+ * @returns {string|null} Section key or null
205
+ */
206
+ _detectSection(trimmedLine) {
207
+ for (const { key, header } of SECTIONS) {
208
+ if (trimmedLine === header || trimmedLine.startsWith(header.split(' (')[0])) {
209
+ return key;
210
+ }
211
+ }
212
+ return null;
213
+ }
214
+
215
+ /**
216
+ * Return the placeholder text for an empty section.
217
+ * @param {string} sectionKey
218
+ * @returns {string}
219
+ */
220
+ _placeholderFor(sectionKey) {
221
+ const map = {
222
+ constraints: '约束条目',
223
+ notes: '注意事项条目',
224
+ decisions: '决策条目',
225
+ };
226
+ return map[sectionKey] || sectionKey;
227
+ }
228
+ }
229
+
230
+ module.exports = { SpecSteering };