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,117 @@
1
+ const DEFAULT_METRIC_DIRECTIONS = {
2
+ ttfv_minutes: 'lower',
3
+ batch_success_rate: 'higher',
4
+ cycle_reduction_rate: 'higher',
5
+ manual_takeover_rate: 'lower'
6
+ };
7
+
8
+ function parsePeriodKey(period) {
9
+ const match = /^(\d{4})-W(\d{2})$/.exec(period || '');
10
+ if (!match) {
11
+ return Number.MAX_SAFE_INTEGER;
12
+ }
13
+
14
+ const year = Number(match[1]);
15
+ const week = Number(match[2]);
16
+ return (year * 100) + week;
17
+ }
18
+
19
+ function isWorse(current, previous, direction) {
20
+ if (!Number.isFinite(current) || !Number.isFinite(previous)) {
21
+ return false;
22
+ }
23
+
24
+ if (direction === 'lower') {
25
+ return current > previous;
26
+ }
27
+
28
+ return current < previous;
29
+ }
30
+
31
+ class RiskEvaluator {
32
+ constructor(options = {}) {
33
+ this.metricDirections = {
34
+ ...DEFAULT_METRIC_DIRECTIONS,
35
+ ...(options.metricDirections || {})
36
+ };
37
+ }
38
+
39
+ evaluate(options = {}) {
40
+ const {
41
+ historySnapshots = [],
42
+ currentSnapshot
43
+ } = options;
44
+
45
+ if (!currentSnapshot || typeof currentSnapshot !== 'object' || !currentSnapshot.period) {
46
+ throw new Error('currentSnapshot with valid period is required');
47
+ }
48
+
49
+ const dedupedByPeriod = new Map();
50
+ historySnapshots.forEach(snapshot => {
51
+ if (snapshot && snapshot.period) {
52
+ dedupedByPeriod.set(snapshot.period, snapshot);
53
+ }
54
+ });
55
+ dedupedByPeriod.set(currentSnapshot.period, currentSnapshot);
56
+
57
+ const snapshots = Array.from(dedupedByPeriod.values())
58
+ .sort((left, right) => parsePeriodKey(left.period) - parsePeriodKey(right.period));
59
+
60
+ const details = {};
61
+ const streaks = {};
62
+
63
+ Object.entries(this.metricDirections).forEach(([metricId, direction]) => {
64
+ details[metricId] = {
65
+ better_direction: direction,
66
+ max_consecutive_worse: 0,
67
+ triggered: false
68
+ };
69
+ streaks[metricId] = 0;
70
+ });
71
+
72
+ for (let index = 1; index < snapshots.length; index += 1) {
73
+ const previous = snapshots[index - 1];
74
+ const current = snapshots[index];
75
+
76
+ Object.entries(this.metricDirections).forEach(([metricId, direction]) => {
77
+ const currentValue = Number(current[metricId]);
78
+ const previousValue = Number(previous[metricId]);
79
+
80
+ if (isWorse(currentValue, previousValue, direction)) {
81
+ streaks[metricId] += 1;
82
+ } else {
83
+ streaks[metricId] = 0;
84
+ }
85
+
86
+ details[metricId].max_consecutive_worse = Math.max(
87
+ details[metricId].max_consecutive_worse,
88
+ streaks[metricId]
89
+ );
90
+
91
+ if (streaks[metricId] >= 2) {
92
+ details[metricId].triggered = true;
93
+ }
94
+ });
95
+ }
96
+
97
+ const triggeredMetrics = Object.entries(details)
98
+ .filter(([, value]) => value.triggered)
99
+ .map(([metricId]) => metricId);
100
+
101
+ const reasons = triggeredMetrics.map(metricId => (
102
+ `${metricId} worsened for 2 consecutive weeks`
103
+ ));
104
+
105
+ return {
106
+ evaluated_period: currentSnapshot.period,
107
+ risk_level: triggeredMetrics.length > 0 ? 'high' : 'medium',
108
+ triggered_metrics: triggeredMetrics,
109
+ reasons,
110
+ details
111
+ };
112
+ }
113
+ }
114
+
115
+ module.exports = RiskEvaluator;
116
+ module.exports.parsePeriodKey = parsePeriodKey;
117
+
@@ -0,0 +1,61 @@
1
+ const PERIOD_REGEX = /^\d{4}-W(0[1-9]|[1-4]\d|5[0-3])$/;
2
+
3
+ function isValidPeriod(period) {
4
+ return typeof period === 'string' && PERIOD_REGEX.test(period.trim());
5
+ }
6
+
7
+ class WeeklySnapshotBuilder {
8
+ constructor(options = {}) {
9
+ this.now = typeof options.now === 'function'
10
+ ? options.now
11
+ : (() => new Date().toISOString());
12
+ }
13
+
14
+ build(options = {}) {
15
+ const {
16
+ period,
17
+ metrics,
18
+ notes = '',
19
+ contract
20
+ } = options;
21
+
22
+ if (!isValidPeriod(period)) {
23
+ throw new Error(`Invalid period format: ${period}. Expected YYYY-WNN.`);
24
+ }
25
+
26
+ if (!contract || !Array.isArray(contract.metrics)) {
27
+ throw new Error('Metric contract is required to build snapshot');
28
+ }
29
+
30
+ if (!metrics || typeof metrics !== 'object') {
31
+ throw new Error('Snapshot metrics input must be an object');
32
+ }
33
+
34
+ const metricValues = {};
35
+ contract.metrics.forEach(metric => {
36
+ if (!Object.prototype.hasOwnProperty.call(metrics, metric.id)) {
37
+ throw new Error(`Missing metric value: ${metric.id}`);
38
+ }
39
+
40
+ const numericValue = Number(metrics[metric.id]);
41
+ if (!Number.isFinite(numericValue)) {
42
+ throw new Error(`Metric value must be numeric: ${metric.id}`);
43
+ }
44
+
45
+ metricValues[metric.id] = numericValue;
46
+ });
47
+
48
+ return {
49
+ period,
50
+ ...metricValues,
51
+ risk_level: 'medium',
52
+ reasons: [],
53
+ notes,
54
+ generated_at: this.now()
55
+ };
56
+ }
57
+ }
58
+
59
+ module.exports = WeeklySnapshotBuilder;
60
+ module.exports.isValidPeriod = isValidPeriod;
61
+
@@ -0,0 +1,156 @@
1
+ /**
2
+ * Version Checker
3
+ *
4
+ * Automatically detects version mismatches between project and installed kse.
5
+ * Displays warnings and upgrade suggestions.
6
+ */
7
+
8
+ const chalk = require('chalk');
9
+ const VersionManager = require('./version-manager');
10
+
11
+ class VersionChecker {
12
+ constructor() {
13
+ this.versionManager = new VersionManager();
14
+ this.suppressWarnings = false;
15
+ }
16
+
17
+ /**
18
+ * Checks for version mismatch and displays warning if needed
19
+ *
20
+ * @param {string} projectPath - Absolute path to project root
21
+ * @param {Object} options - Check options
22
+ * @param {boolean} options.noVersionCheck - Suppress warnings
23
+ * @returns {Promise<VersionCheckResult>}
24
+ */
25
+ async checkVersion(projectPath, options = {}) {
26
+ const { noVersionCheck = false } = options;
27
+
28
+ if (noVersionCheck || this.suppressWarnings) {
29
+ return { mismatch: false, shouldUpgrade: false };
30
+ }
31
+
32
+ try {
33
+ // Read project version
34
+ const projectVersionInfo = await this.versionManager.readVersion(projectPath);
35
+
36
+ if (!projectVersionInfo) {
37
+ // No version.json - project might not be initialized
38
+ return { mismatch: false, shouldUpgrade: false };
39
+ }
40
+
41
+ const projectVersion = projectVersionInfo['kse-version'];
42
+
43
+ // Get current kse version
44
+ const packageJson = require('../../package.json');
45
+ const kseVersion = packageJson.version;
46
+
47
+ // Check if upgrade is needed
48
+ const needsUpgrade = this.versionManager.needsUpgrade(projectVersion, kseVersion);
49
+
50
+ if (needsUpgrade) {
51
+ this.displayWarning(projectVersion, kseVersion);
52
+ }
53
+
54
+ return {
55
+ mismatch: needsUpgrade,
56
+ shouldUpgrade: needsUpgrade,
57
+ projectVersion,
58
+ kseVersion
59
+ };
60
+ } catch (error) {
61
+ // Silently fail - don't block commands if version check fails
62
+ return { mismatch: false, shouldUpgrade: false, error: error.message };
63
+ }
64
+ }
65
+
66
+ /**
67
+ * Displays version mismatch warning
68
+ *
69
+ * @param {string} projectVersion - Project version
70
+ * @param {string} kseVersion - Current kse version
71
+ */
72
+ displayWarning(projectVersion, kseVersion) {
73
+ console.log();
74
+ console.log(chalk.yellow('⚠️ Version Mismatch Detected'));
75
+ console.log(chalk.gray(' Project initialized with kse'), chalk.cyan(`v${projectVersion}`));
76
+ console.log(chalk.gray(' Current kse version:'), chalk.cyan(`v${kseVersion}`));
77
+ console.log();
78
+ console.log(chalk.blue('💡 Tip:'), chalk.gray('Run'), chalk.cyan('kse upgrade'), chalk.gray('to update project templates'));
79
+ console.log(chalk.gray(' Or use'), chalk.cyan('--no-version-check'), chalk.gray('to suppress this warning'));
80
+ console.log();
81
+ }
82
+
83
+ /**
84
+ * Checks version and displays detailed information
85
+ *
86
+ * @param {string} projectPath - Absolute path to project root
87
+ * @returns {Promise<void>}
88
+ */
89
+ async displayVersionInfo(projectPath) {
90
+ try {
91
+ const projectVersionInfo = await this.versionManager.readVersion(projectPath);
92
+
93
+ if (!projectVersionInfo) {
94
+ console.log(chalk.yellow('⚠️ No version information found'));
95
+ console.log(chalk.gray(' This project may not be initialized with kse'));
96
+ console.log(chalk.gray(' Run'), chalk.cyan('kse adopt'), chalk.gray('to adopt this project'));
97
+ return;
98
+ }
99
+
100
+ const packageJson = require('../../package.json');
101
+ const kseVersion = packageJson.version;
102
+
103
+ console.log(chalk.blue('📦 Version Information'));
104
+ console.log();
105
+ console.log(chalk.gray('Project:'));
106
+ console.log(` kse version: ${chalk.cyan(projectVersionInfo['kse-version'])}`);
107
+ console.log(` Template version: ${chalk.cyan(projectVersionInfo['template-version'])}`);
108
+ console.log(` Created: ${chalk.gray(new Date(projectVersionInfo.created).toLocaleString())}`);
109
+ console.log(` Last upgraded: ${chalk.gray(new Date(projectVersionInfo['last-upgraded']).toLocaleString())}`);
110
+
111
+ console.log();
112
+ console.log(chalk.gray('Installed:'));
113
+ console.log(` kse version: ${chalk.cyan(kseVersion)}`);
114
+
115
+ if (projectVersionInfo['upgrade-history'].length > 0) {
116
+ console.log();
117
+ console.log(chalk.gray('Upgrade History:'));
118
+ projectVersionInfo['upgrade-history'].forEach((entry, index) => {
119
+ const icon = entry.success ? chalk.green('✅') : chalk.red('❌');
120
+ const date = new Date(entry.date).toLocaleString();
121
+ console.log(` ${icon} ${entry.from} → ${entry.to} (${date})`);
122
+ if (entry.error) {
123
+ console.log(` ${chalk.red('Error:')} ${entry.error}`);
124
+ }
125
+ });
126
+ }
127
+
128
+ console.log();
129
+
130
+ const needsUpgrade = this.versionManager.needsUpgrade(
131
+ projectVersionInfo['kse-version'],
132
+ kseVersion
133
+ );
134
+
135
+ if (needsUpgrade) {
136
+ console.log(chalk.yellow('⚠️ Upgrade available'));
137
+ console.log(chalk.gray(' Run'), chalk.cyan('kse upgrade'), chalk.gray('to update to'), chalk.cyan(`v${kseVersion}`));
138
+ } else {
139
+ console.log(chalk.green('✅ Project is up to date'));
140
+ }
141
+ } catch (error) {
142
+ console.log(chalk.red('❌ Error:'), error.message);
143
+ }
144
+ }
145
+
146
+ /**
147
+ * Suppresses version check warnings
148
+ *
149
+ * @param {boolean} suppress - Whether to suppress warnings
150
+ */
151
+ setSuppressWarnings(suppress) {
152
+ this.suppressWarnings = suppress;
153
+ }
154
+ }
155
+
156
+ module.exports = VersionChecker;
@@ -0,0 +1,327 @@
1
+ /**
2
+ * Version Manager
3
+ *
4
+ * Manages version tracking, compatibility checking, and upgrade path calculation
5
+ * for the kiro-spec-engine project adoption and upgrade system.
6
+ */
7
+
8
+ const path = require('path');
9
+ const semver = require('semver');
10
+ const { readJSON, writeJSON, pathExists } = require('../utils/fs-utils');
11
+
12
+ /**
13
+ * Compatibility matrix defining which versions can work together
14
+ * Format: { version: { compatible: [versions], breaking: boolean } }
15
+ */
16
+ const COMPATIBILITY_MATRIX = {
17
+ '1.0.0': { compatible: ['1.0.0', '1.1.0', '1.2.0'], breaking: false },
18
+ '1.1.0': { compatible: ['1.0.0', '1.1.0', '1.2.0'], breaking: false },
19
+ '1.2.0': { compatible: ['1.0.0', '1.1.0', '1.2.0'], breaking: false },
20
+ '2.0.0': { compatible: ['2.0.0'], breaking: true, migration: 'required' }
21
+ };
22
+
23
+ class VersionManager {
24
+ constructor() {
25
+ this.versionFileName = 'version.json';
26
+ }
27
+
28
+ /**
29
+ * Gets the path to version.json in a project
30
+ *
31
+ * @param {string} projectPath - Absolute path to project root
32
+ * @returns {string} - Absolute path to version.json
33
+ */
34
+ getVersionFilePath(projectPath) {
35
+ return path.join(projectPath, '.kiro', this.versionFileName);
36
+ }
37
+
38
+ /**
39
+ * Reads version information from project
40
+ *
41
+ * @param {string} projectPath - Absolute path to project root
42
+ * @returns {Promise<VersionInfo|null>} - Version info or null if not found
43
+ */
44
+ async readVersion(projectPath) {
45
+ const versionPath = this.getVersionFilePath(projectPath);
46
+
47
+ try {
48
+ const exists = await pathExists(versionPath);
49
+ if (!exists) {
50
+ return null;
51
+ }
52
+
53
+ const versionInfo = await readJSON(versionPath);
54
+
55
+ // Validate structure
56
+ if (!this.isValidVersionInfo(versionInfo)) {
57
+ throw new Error('Invalid version.json structure');
58
+ }
59
+
60
+ return versionInfo;
61
+ } catch (error) {
62
+ throw new Error(`Failed to read version file: ${error.message}`);
63
+ }
64
+ }
65
+
66
+ /**
67
+ * Writes version information to project
68
+ *
69
+ * @param {string} projectPath - Absolute path to project root
70
+ * @param {VersionInfo} versionInfo - Version information to write
71
+ * @returns {Promise<void>}
72
+ */
73
+ async writeVersion(projectPath, versionInfo) {
74
+ const versionPath = this.getVersionFilePath(projectPath);
75
+
76
+ try {
77
+ // Validate structure before writing
78
+ if (!this.isValidVersionInfo(versionInfo)) {
79
+ throw new Error('Invalid version info structure');
80
+ }
81
+
82
+ await writeJSON(versionPath, versionInfo, { spaces: 2 });
83
+ } catch (error) {
84
+ throw new Error(`Failed to write version file: ${error.message}`);
85
+ }
86
+ }
87
+
88
+ /**
89
+ * Creates initial version info for a new project
90
+ *
91
+ * @param {string} kseVersion - Current kse version
92
+ * @param {string} templateVersion - Template version (default: same as kse)
93
+ * @returns {VersionInfo}
94
+ */
95
+ createVersionInfo(kseVersion, templateVersion = null) {
96
+ const now = new Date().toISOString();
97
+
98
+ return {
99
+ 'kse-version': kseVersion,
100
+ 'template-version': templateVersion || kseVersion,
101
+ 'created': now,
102
+ 'last-upgraded': now,
103
+ 'upgrade-history': []
104
+ };
105
+ }
106
+
107
+ /**
108
+ * Validates version info structure
109
+ *
110
+ * @param {Object} versionInfo - Version info to validate
111
+ * @returns {boolean}
112
+ */
113
+ isValidVersionInfo(versionInfo) {
114
+ if (!versionInfo || typeof versionInfo !== 'object') {
115
+ return false;
116
+ }
117
+
118
+ const requiredFields = [
119
+ 'kse-version',
120
+ 'template-version',
121
+ 'created',
122
+ 'last-upgraded',
123
+ 'upgrade-history'
124
+ ];
125
+
126
+ for (const field of requiredFields) {
127
+ if (!(field in versionInfo)) {
128
+ return false;
129
+ }
130
+ }
131
+
132
+ // Validate upgrade-history is an array
133
+ if (!Array.isArray(versionInfo['upgrade-history'])) {
134
+ return false;
135
+ }
136
+
137
+ return true;
138
+ }
139
+
140
+ /**
141
+ * Checks if upgrade is needed
142
+ *
143
+ * @param {string} projectVersion - Current project version
144
+ * @param {string} kseVersion - Installed kse version
145
+ * @returns {boolean}
146
+ */
147
+ needsUpgrade(projectVersion, kseVersion) {
148
+ if (!projectVersion || !kseVersion) {
149
+ return false;
150
+ }
151
+
152
+ try {
153
+ // Use semver for comparison
154
+ return semver.lt(projectVersion, kseVersion);
155
+ } catch (error) {
156
+ // If semver comparison fails, do string comparison
157
+ return projectVersion !== kseVersion;
158
+ }
159
+ }
160
+
161
+ /**
162
+ * Checks compatibility between versions
163
+ *
164
+ * @param {string} fromVersion - Source version
165
+ * @param {string} toVersion - Target version
166
+ * @returns {CompatibilityResult}
167
+ */
168
+ checkCompatibility(fromVersion, toVersion) {
169
+ // If versions are the same, always compatible
170
+ if (fromVersion === toVersion) {
171
+ return {
172
+ compatible: true,
173
+ breaking: false,
174
+ migration: 'none'
175
+ };
176
+ }
177
+
178
+ // Check compatibility matrix first
179
+ const fromInfo = COMPATIBILITY_MATRIX[fromVersion];
180
+
181
+ if (fromInfo) {
182
+ const isCompatible = fromInfo.compatible.includes(toVersion);
183
+ return {
184
+ compatible: isCompatible,
185
+ breaking: !isCompatible || fromInfo.breaking,
186
+ migration: !isCompatible ? 'required' : 'none'
187
+ };
188
+ }
189
+
190
+ // Fallback: semver-based compatibility for versions not in matrix
191
+ try {
192
+ const fromMajor = semver.major(fromVersion);
193
+ const toMajor = semver.major(toVersion);
194
+
195
+ if (fromMajor === toMajor) {
196
+ // Same major version — compatible, non-breaking
197
+ return {
198
+ compatible: true,
199
+ breaking: false,
200
+ migration: 'none'
201
+ };
202
+ }
203
+
204
+ // Different major version — breaking change
205
+ return {
206
+ compatible: false,
207
+ breaking: true,
208
+ migration: 'required'
209
+ };
210
+ } catch (error) {
211
+ // Invalid semver — assume incompatible
212
+ return {
213
+ compatible: false,
214
+ breaking: true,
215
+ migration: 'unknown',
216
+ message: `Unknown source version: ${fromVersion}`
217
+ };
218
+ }
219
+ }
220
+
221
+ /**
222
+ * Calculates upgrade path for version gap
223
+ * Returns array of intermediate versions to upgrade through
224
+ *
225
+ * @param {string} fromVersion - Current version
226
+ * @param {string} toVersion - Target version
227
+ * @returns {string[]} - Array of versions in upgrade order (including from and to)
228
+ */
229
+ calculateUpgradePath(fromVersion, toVersion) {
230
+ // If same version, no upgrade needed
231
+ if (fromVersion === toVersion) {
232
+ return [fromVersion];
233
+ }
234
+
235
+ // Get all versions from compatibility matrix
236
+ const allVersions = Object.keys(COMPATIBILITY_MATRIX).sort((a, b) => {
237
+ try {
238
+ return semver.compare(a, b);
239
+ } catch (error) {
240
+ return a.localeCompare(b);
241
+ }
242
+ });
243
+
244
+ // Find indices
245
+ const fromIndex = allVersions.indexOf(fromVersion);
246
+ const toIndex = allVersions.indexOf(toVersion);
247
+
248
+ // If both versions are in the matrix, use the matrix path
249
+ if (fromIndex !== -1 && toIndex !== -1) {
250
+ if (fromIndex > toIndex) {
251
+ throw new Error('Cannot downgrade versions');
252
+ }
253
+ return allVersions.slice(fromIndex, toIndex + 1);
254
+ }
255
+
256
+ // Fallback: semver-based direct upgrade for versions not in matrix
257
+ try {
258
+ const from = semver.valid(fromVersion);
259
+ const to = semver.valid(toVersion);
260
+
261
+ if (!from) {
262
+ throw new Error(`Unknown source version: ${fromVersion}`);
263
+ }
264
+ if (!to) {
265
+ throw new Error(`Unknown target version: ${toVersion}`);
266
+ }
267
+
268
+ if (semver.gt(fromVersion, toVersion)) {
269
+ throw new Error('Cannot downgrade versions');
270
+ }
271
+
272
+ // Direct upgrade path
273
+ return [fromVersion, toVersion];
274
+ } catch (error) {
275
+ // Re-throw our own errors
276
+ if (error.message.includes('Unknown') || error.message.includes('downgrade')) {
277
+ throw error;
278
+ }
279
+ throw new Error(`Unknown source version: ${fromVersion}`);
280
+ }
281
+ }
282
+
283
+ /**
284
+ * Adds an upgrade entry to version history
285
+ *
286
+ * @param {VersionInfo} versionInfo - Current version info
287
+ * @param {string} fromVersion - Version upgraded from
288
+ * @param {string} toVersion - Version upgraded to
289
+ * @param {boolean} success - Whether upgrade succeeded
290
+ * @param {string} error - Error message if failed
291
+ * @returns {VersionInfo} - Updated version info
292
+ */
293
+ addUpgradeHistory(versionInfo, fromVersion, toVersion, success, error = null) {
294
+ const entry = {
295
+ from: fromVersion,
296
+ to: toVersion,
297
+ date: new Date().toISOString(),
298
+ success
299
+ };
300
+
301
+ if (error) {
302
+ entry.error = error;
303
+ }
304
+
305
+ versionInfo['upgrade-history'].push(entry);
306
+
307
+ // Update version and last-upgraded if successful
308
+ if (success) {
309
+ versionInfo['kse-version'] = toVersion;
310
+ versionInfo['template-version'] = toVersion;
311
+ versionInfo['last-upgraded'] = entry.date;
312
+ }
313
+
314
+ return versionInfo;
315
+ }
316
+
317
+ /**
318
+ * Gets the compatibility matrix
319
+ *
320
+ * @returns {Object} - Compatibility matrix
321
+ */
322
+ getCompatibilityMatrix() {
323
+ return { ...COMPATIBILITY_MATRIX };
324
+ }
325
+ }
326
+
327
+ module.exports = VersionManager;