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,569 @@
1
+ const fs = require('fs-extra');
2
+ const path = require('path');
3
+ const chalk = require('chalk');
4
+
5
+ const MetricContractLoader = require('../value/metric-contract-loader');
6
+ const WeeklySnapshotBuilder = require('../value/weekly-snapshot-builder');
7
+ const RiskEvaluator = require('../value/risk-evaluator');
8
+ const GateSummaryEmitter = require('../value/gate-summary-emitter');
9
+ const { parsePeriodKey } = require('../value/risk-evaluator');
10
+
11
+ function toProjectPath(projectPath, maybePath) {
12
+ if (!maybePath) {
13
+ return null;
14
+ }
15
+
16
+ return path.isAbsolute(maybePath)
17
+ ? maybePath
18
+ : path.join(projectPath, maybePath);
19
+ }
20
+
21
+ function toPortablePath(projectPath, filePath) {
22
+ return path.relative(projectPath, filePath).replace(/\\/g, '/');
23
+ }
24
+
25
+ async function loadJson(filePath) {
26
+ try {
27
+ return await fs.readJson(filePath);
28
+ } catch (error) {
29
+ throw new Error(`Failed to read JSON file (${filePath}): ${error.message}`);
30
+ }
31
+ }
32
+
33
+ async function loadHistorySnapshots(historyDir) {
34
+ if (!await fs.pathExists(historyDir)) {
35
+ return [];
36
+ }
37
+
38
+ const entries = await fs.readdir(historyDir);
39
+ const snapshots = [];
40
+
41
+ for (const entry of entries) {
42
+ if (!entry.endsWith('.json')) {
43
+ continue;
44
+ }
45
+
46
+ if (entry.startsWith('gate-summary.') || entry.includes('risk-evaluation')) {
47
+ continue;
48
+ }
49
+
50
+ const filePath = path.join(historyDir, entry);
51
+
52
+ let parsed;
53
+ try {
54
+ parsed = await fs.readJson(filePath);
55
+ } catch (error) {
56
+ continue;
57
+ }
58
+
59
+ if (parsed && typeof parsed.period === 'string') {
60
+ snapshots.push(parsed);
61
+ }
62
+ }
63
+
64
+ return snapshots;
65
+ }
66
+
67
+ function sortSnapshotsByPeriod(snapshots = []) {
68
+ return [...snapshots].sort((left, right) => parsePeriodKey(left.period) - parsePeriodKey(right.period));
69
+ }
70
+
71
+ function parsePositiveInteger(input, fallbackValue) {
72
+ const parsed = Number.parseInt(input, 10);
73
+ if (Number.isFinite(parsed) && parsed > 0) {
74
+ return parsed;
75
+ }
76
+
77
+ return fallbackValue;
78
+ }
79
+
80
+ function inferMetricDirection(metric = {}) {
81
+ if (typeof metric.better_direction === 'string' && metric.better_direction.trim()) {
82
+ return metric.better_direction.trim().toLowerCase();
83
+ }
84
+
85
+ const targetRule = metric.target_rule;
86
+ if (!targetRule || typeof targetRule.operator !== 'string') {
87
+ return 'higher';
88
+ }
89
+
90
+ if (targetRule.operator.includes('<')) {
91
+ return 'lower';
92
+ }
93
+
94
+ return 'higher';
95
+ }
96
+
97
+ function evaluateTarget(value, targetRule) {
98
+ const numericValue = Number(value);
99
+ if (!Number.isFinite(numericValue) || !targetRule) {
100
+ return false;
101
+ }
102
+
103
+ switch (targetRule.operator) {
104
+ case '<=':
105
+ return numericValue <= targetRule.value;
106
+ case '>=':
107
+ return numericValue >= targetRule.value;
108
+ case '<':
109
+ return numericValue < targetRule.value;
110
+ case '>':
111
+ return numericValue > targetRule.value;
112
+ case '=':
113
+ return numericValue === targetRule.value;
114
+ default:
115
+ return false;
116
+ }
117
+ }
118
+
119
+ function getImprovement(delta, direction) {
120
+ if (!Number.isFinite(delta) || delta === 0) {
121
+ return 'flat';
122
+ }
123
+
124
+ if (direction === 'lower') {
125
+ return delta < 0 ? 'improved' : 'degraded';
126
+ }
127
+
128
+ return delta > 0 ? 'improved' : 'degraded';
129
+ }
130
+
131
+ function resolveMetricInput(inputPayload) {
132
+ if (inputPayload && typeof inputPayload.metrics === 'object' && inputPayload.metrics !== null) {
133
+ return inputPayload.metrics;
134
+ }
135
+
136
+ return inputPayload;
137
+ }
138
+
139
+ function defaultHistoryDir(projectPath) {
140
+ return path.join(
141
+ projectPath,
142
+ '.kiro',
143
+ 'specs',
144
+ '114-00-kpi-automation-and-observability',
145
+ 'custom',
146
+ 'weekly-metrics'
147
+ );
148
+ }
149
+
150
+ function getIsoWeekPeriod(date = new Date()) {
151
+ const utcDate = new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate()));
152
+ const day = utcDate.getUTCDay() || 7;
153
+ utcDate.setUTCDate(utcDate.getUTCDate() + 4 - day);
154
+
155
+ const yearStart = new Date(Date.UTC(utcDate.getUTCFullYear(), 0, 1));
156
+ const week = Math.ceil((((utcDate - yearStart) / 86400000) + 1) / 7);
157
+
158
+ return `${utcDate.getUTCFullYear()}-W${String(week).padStart(2, '0')}`;
159
+ }
160
+
161
+ function createSampleMetricsInput(period) {
162
+ return {
163
+ period,
164
+ metrics: {
165
+ ttfv_minutes: 25,
166
+ batch_success_rate: 0.86,
167
+ cycle_reduction_rate: 0.34,
168
+ manual_takeover_rate: 0.16
169
+ },
170
+ notes: 'sample metrics input generated by kse value metrics sample'
171
+ };
172
+ }
173
+
174
+ async function runValueMetricsSample(options = {}, dependencies = {}) {
175
+ const projectPath = dependencies.projectPath || process.cwd();
176
+ const period = options.period || getIsoWeekPeriod();
177
+ const sampleInput = createSampleMetricsInput(period);
178
+
179
+ const outputPath = toProjectPath(projectPath, options.out) || path.join(projectPath, 'kpi-input.json');
180
+ await fs.ensureDir(path.dirname(outputPath));
181
+ await fs.writeJson(outputPath, sampleInput, { spaces: 2 });
182
+
183
+ const result = {
184
+ success: true,
185
+ period,
186
+ sample_path: toPortablePath(projectPath, outputPath),
187
+ generated_at: new Date().toISOString()
188
+ };
189
+
190
+ if (options.json) {
191
+ console.log(JSON.stringify(result, null, 2));
192
+ } else if (!options.silent) {
193
+ console.log(chalk.green('✅ KPI sample input generated'));
194
+ console.log(chalk.gray(` period: ${result.period}`));
195
+ console.log(chalk.gray(` sample: ${result.sample_path}`));
196
+ }
197
+
198
+ return result;
199
+ }
200
+
201
+ async function runValueMetricsSnapshot(options = {}, dependencies = {}) {
202
+ const projectPath = dependencies.projectPath || process.cwd();
203
+
204
+ if (!options.input) {
205
+ throw new Error('--input <path> is required for snapshot generation. Tip: run "kse value metrics sample --out ./kpi-input.json" first.');
206
+ }
207
+
208
+ const loader = dependencies.metricContractLoader || new MetricContractLoader(projectPath);
209
+ const builder = dependencies.weeklySnapshotBuilder || new WeeklySnapshotBuilder();
210
+ const evaluator = dependencies.riskEvaluator || new RiskEvaluator();
211
+ const gateEmitter = dependencies.gateSummaryEmitter || new GateSummaryEmitter();
212
+
213
+ const { contract, contractPath } = await loader.load({
214
+ path: options.definitions
215
+ });
216
+
217
+ const inputPath = toProjectPath(projectPath, options.input);
218
+ const inputPayload = await loadJson(inputPath);
219
+
220
+ const period = options.period || inputPayload.period;
221
+ const notes = options.notes || inputPayload.notes || '';
222
+
223
+ const snapshot = builder.build({
224
+ period,
225
+ metrics: resolveMetricInput(inputPayload),
226
+ notes,
227
+ contract
228
+ });
229
+
230
+ const historyDir = toProjectPath(projectPath, options.historyDir) || defaultHistoryDir(projectPath);
231
+ await fs.ensureDir(historyDir);
232
+
233
+ const historySnapshots = await loadHistorySnapshots(historyDir);
234
+ const riskResult = evaluator.evaluate({
235
+ historySnapshots,
236
+ currentSnapshot: snapshot
237
+ });
238
+
239
+ snapshot.risk_level = riskResult.risk_level;
240
+ snapshot.reasons = riskResult.reasons;
241
+
242
+ const snapshotPath = toProjectPath(projectPath, options.out)
243
+ || path.join(historyDir, `${snapshot.period}.json`);
244
+
245
+ await fs.ensureDir(path.dirname(snapshotPath));
246
+ await fs.writeJson(snapshotPath, snapshot, { spaces: 2 });
247
+
248
+ const checkpoint = options.checkpoint || 'day-30';
249
+ const gateSummary = gateEmitter.build({
250
+ checkpoint,
251
+ snapshot,
252
+ contract,
253
+ evidence: [toPortablePath(projectPath, snapshotPath)]
254
+ });
255
+
256
+ const gateSummaryPath = toProjectPath(projectPath, options.gateOut)
257
+ || path.join(path.dirname(snapshotPath), `gate-summary.${snapshot.period}.${checkpoint}.json`);
258
+ await fs.writeJson(gateSummaryPath, gateSummary, { spaces: 2 });
259
+
260
+ const result = {
261
+ success: true,
262
+ period: snapshot.period,
263
+ risk_level: snapshot.risk_level,
264
+ triggered_metrics: riskResult.triggered_metrics,
265
+ snapshot_path: toPortablePath(projectPath, snapshotPath),
266
+ gate_summary_path: toPortablePath(projectPath, gateSummaryPath),
267
+ contract_path: toPortablePath(projectPath, contractPath)
268
+ };
269
+
270
+ if (options.json) {
271
+ console.log(JSON.stringify(result, null, 2));
272
+ } else if (!options.silent) {
273
+ console.log(chalk.green('✅ KPI snapshot generated'));
274
+ console.log(chalk.gray(` period: ${result.period}`));
275
+ console.log(chalk.gray(` risk: ${result.risk_level}`));
276
+ console.log(chalk.gray(` snapshot: ${result.snapshot_path}`));
277
+ console.log(chalk.gray(` gate summary: ${result.gate_summary_path}`));
278
+ }
279
+
280
+ return result;
281
+ }
282
+
283
+ async function runValueMetricsBaseline(options = {}, dependencies = {}) {
284
+ const projectPath = dependencies.projectPath || process.cwd();
285
+ const loader = dependencies.metricContractLoader || new MetricContractLoader(projectPath);
286
+ const builder = dependencies.weeklySnapshotBuilder || new WeeklySnapshotBuilder();
287
+
288
+ const { contract, contractPath } = await loader.load({
289
+ path: options.definitions
290
+ });
291
+
292
+ const historyDir = toProjectPath(projectPath, options.historyDir) || defaultHistoryDir(projectPath);
293
+ await fs.ensureDir(historyDir);
294
+
295
+ let period;
296
+ let notes;
297
+ let metricInput;
298
+ let baselineSource;
299
+
300
+ if (options.input) {
301
+ const inputPath = toProjectPath(projectPath, options.input);
302
+ const inputPayload = await loadJson(inputPath);
303
+
304
+ period = options.period || inputPayload.period;
305
+ notes = options.notes || inputPayload.notes || '';
306
+ metricInput = resolveMetricInput(inputPayload);
307
+ baselineSource = `input:${toPortablePath(projectPath, inputPath)}`;
308
+ } else {
309
+ const allSnapshots = sortSnapshotsByPeriod(await loadHistorySnapshots(historyDir));
310
+ if (allSnapshots.length === 0) {
311
+ throw new Error('--input is required when history directory has no snapshots. Tip: run "kse value metrics sample --out ./kpi-input.json" and then "kse value metrics snapshot --input ./kpi-input.json".');
312
+ }
313
+
314
+ const fromHistory = parsePositiveInteger(options.fromHistory, Math.min(3, allSnapshots.length));
315
+ const selected = allSnapshots.slice(0, Math.min(fromHistory, allSnapshots.length));
316
+
317
+ metricInput = {};
318
+ for (const metric of contract.metrics) {
319
+ const values = selected
320
+ .map(snapshot => Number(snapshot[metric.id]))
321
+ .filter(value => Number.isFinite(value));
322
+
323
+ if (values.length === 0) {
324
+ throw new Error(`Unable to derive baseline metric from history: ${metric.id}`);
325
+ }
326
+
327
+ const average = values.reduce((sum, value) => sum + value, 0) / values.length;
328
+ metricInput[metric.id] = Number(average.toFixed(6));
329
+ }
330
+
331
+ const startPeriod = selected[0].period;
332
+ const endPeriod = selected[selected.length - 1].period;
333
+ period = options.period || endPeriod;
334
+ notes = options.notes || `Baseline derived from ${selected.length} snapshots (${startPeriod} -> ${endPeriod})`;
335
+ baselineSource = `history:${startPeriod}-${endPeriod}`;
336
+ }
337
+
338
+ const baselineSnapshot = builder.build({
339
+ period,
340
+ metrics: metricInput,
341
+ notes,
342
+ contract
343
+ });
344
+
345
+ baselineSnapshot.is_baseline = true;
346
+ baselineSnapshot.baseline_source = baselineSource;
347
+
348
+ const baselinePath = toProjectPath(projectPath, options.out)
349
+ || path.join(historyDir, `${baselineSnapshot.period}.baseline.json`);
350
+ await fs.ensureDir(path.dirname(baselinePath));
351
+ await fs.writeJson(baselinePath, baselineSnapshot, { spaces: 2 });
352
+
353
+ const result = {
354
+ success: true,
355
+ period: baselineSnapshot.period,
356
+ baseline_source: baselineSource,
357
+ baseline_path: toPortablePath(projectPath, baselinePath),
358
+ contract_path: toPortablePath(projectPath, contractPath)
359
+ };
360
+
361
+ if (options.json) {
362
+ console.log(JSON.stringify(result, null, 2));
363
+ } else if (!options.silent) {
364
+ console.log(chalk.green('✅ KPI baseline generated'));
365
+ console.log(chalk.gray(` period: ${result.period}`));
366
+ console.log(chalk.gray(` source: ${result.baseline_source}`));
367
+ console.log(chalk.gray(` baseline: ${result.baseline_path}`));
368
+ }
369
+
370
+ return result;
371
+ }
372
+
373
+ async function runValueMetricsTrend(options = {}, dependencies = {}) {
374
+ const projectPath = dependencies.projectPath || process.cwd();
375
+ const loader = dependencies.metricContractLoader || new MetricContractLoader(projectPath);
376
+ const evaluator = dependencies.riskEvaluator || new RiskEvaluator();
377
+
378
+ const { contract, contractPath } = await loader.load({
379
+ path: options.definitions
380
+ });
381
+
382
+ const historyDir = toProjectPath(projectPath, options.historyDir) || defaultHistoryDir(projectPath);
383
+ const allSnapshots = sortSnapshotsByPeriod(await loadHistorySnapshots(historyDir));
384
+
385
+ if (allSnapshots.length < 2) {
386
+ throw new Error('At least 2 snapshots are required to calculate trends. Tip: generate snapshots first with "kse value metrics snapshot --input ./kpi-input.json".');
387
+ }
388
+
389
+ const window = parsePositiveInteger(options.window, allSnapshots.length);
390
+ const selected = allSnapshots.slice(-Math.min(window, allSnapshots.length));
391
+ const latest = selected[selected.length - 1];
392
+ const previous = selected[selected.length - 2];
393
+
394
+ const metricTrends = contract.metrics.map(metric => {
395
+ const latestValue = Number(latest[metric.id]);
396
+ const previousValue = Number(previous[metric.id]);
397
+
398
+ const delta = Number.isFinite(latestValue) && Number.isFinite(previousValue)
399
+ ? Number((latestValue - previousValue).toFixed(6))
400
+ : null;
401
+
402
+ const direction = inferMetricDirection(metric);
403
+ const trend = !Number.isFinite(delta) || delta === 0
404
+ ? 'flat'
405
+ : (delta > 0 ? 'up' : 'down');
406
+
407
+ const targetPassed = evaluateTarget(latestValue, metric.target_rule);
408
+
409
+ return {
410
+ metric_id: metric.id,
411
+ latest: latestValue,
412
+ previous: previousValue,
413
+ delta,
414
+ trend,
415
+ better_direction: direction,
416
+ status: getImprovement(delta, direction),
417
+ target: metric.target_rule ? metric.target_rule.raw : metric.target,
418
+ target_passed: targetPassed
419
+ };
420
+ });
421
+
422
+ const riskResult = evaluator.evaluate({
423
+ historySnapshots: selected.slice(0, -1),
424
+ currentSnapshot: latest
425
+ });
426
+
427
+ const result = {
428
+ success: true,
429
+ period: latest.period,
430
+ window_size: selected.length,
431
+ range: {
432
+ from: selected[0].period,
433
+ to: latest.period
434
+ },
435
+ risk_level: riskResult.risk_level,
436
+ triggered_metrics: riskResult.triggered_metrics,
437
+ reasons: riskResult.reasons,
438
+ metrics: metricTrends,
439
+ contract_path: toPortablePath(projectPath, contractPath)
440
+ };
441
+
442
+ const outputPath = toProjectPath(projectPath, options.out)
443
+ || path.join(historyDir, 'trend.latest.json');
444
+ await fs.ensureDir(path.dirname(outputPath));
445
+ await fs.writeJson(outputPath, result, { spaces: 2 });
446
+ result.trend_path = toPortablePath(projectPath, outputPath);
447
+
448
+ if (options.json) {
449
+ console.log(JSON.stringify(result, null, 2));
450
+ } else if (!options.silent) {
451
+ console.log(chalk.green('✅ KPI trend calculated'));
452
+ console.log(chalk.gray(` period: ${result.period}`));
453
+ console.log(chalk.gray(` range: ${result.range.from} -> ${result.range.to}`));
454
+ console.log(chalk.gray(` risk: ${result.risk_level}`));
455
+ console.log(chalk.gray(` trend: ${result.trend_path}`));
456
+ }
457
+
458
+ return result;
459
+ }
460
+
461
+ function registerValueCommands(program) {
462
+ const value = program
463
+ .command('value')
464
+ .description('Spec value realization utilities');
465
+
466
+ const metrics = value
467
+ .command('metrics')
468
+ .description('KPI metrics and observability commands');
469
+
470
+ metrics
471
+ .command('sample')
472
+ .description('Generate sample KPI input JSON')
473
+ .option('--period <YYYY-WNN>', 'Week period, e.g. 2026-W10')
474
+ .option('--out <path>', 'Output path for sample input JSON', 'kpi-input.json')
475
+ .option('--json', 'Emit machine-readable JSON')
476
+ .action(async options => {
477
+ try {
478
+ await runValueMetricsSample(options);
479
+ } catch (error) {
480
+ if (options.json) {
481
+ console.log(JSON.stringify({ success: false, error: error.message }, null, 2));
482
+ } else {
483
+ console.error(chalk.red('❌ Value metrics sample failed:'), error.message);
484
+ }
485
+ process.exit(1);
486
+ }
487
+ });
488
+
489
+ metrics
490
+ .command('snapshot')
491
+ .description('Generate weekly KPI snapshot and gate summary')
492
+ .requiredOption('--input <path>', 'Input JSON with metric values')
493
+ .option('--period <YYYY-WNN>', 'Week period, e.g. 2026-W08')
494
+ .option('--definitions <path>', 'Metric definition YAML/JSON path')
495
+ .option('--history-dir <path>', 'History snapshots directory')
496
+ .option('--out <path>', 'Output path for snapshot JSON')
497
+ .option('--gate-out <path>', 'Output path for gate summary JSON')
498
+ .option('--checkpoint <name>', 'Gate checkpoint (day-30/day-60)', 'day-30')
499
+ .option('--json', 'Emit machine-readable JSON')
500
+ .action(async options => {
501
+ try {
502
+ await runValueMetricsSnapshot(options);
503
+ } catch (error) {
504
+ if (options.json) {
505
+ console.log(JSON.stringify({ success: false, error: error.message }, null, 2));
506
+ } else {
507
+ console.error(chalk.red('❌ Value metrics snapshot failed:'), error.message);
508
+ }
509
+ process.exit(1);
510
+ }
511
+ });
512
+
513
+ metrics
514
+ .command('baseline')
515
+ .description('Generate baseline snapshot from input or history')
516
+ .option('--input <path>', 'Input JSON with metric values')
517
+ .option('--from-history <n>', 'Derive baseline from earliest N history snapshots', parseInt)
518
+ .option('--period <YYYY-WNN>', 'Baseline period, e.g. 2026-W07')
519
+ .option('--definitions <path>', 'Metric definition YAML/JSON path')
520
+ .option('--history-dir <path>', 'History snapshots directory')
521
+ .option('--out <path>', 'Output path for baseline JSON')
522
+ .option('--json', 'Emit machine-readable JSON')
523
+ .action(async options => {
524
+ try {
525
+ await runValueMetricsBaseline(options);
526
+ } catch (error) {
527
+ if (options.json) {
528
+ console.log(JSON.stringify({ success: false, error: error.message }, null, 2));
529
+ } else {
530
+ console.error(chalk.red('❌ Value metrics baseline failed:'), error.message);
531
+ }
532
+ process.exit(1);
533
+ }
534
+ });
535
+
536
+ metrics
537
+ .command('trend')
538
+ .description('Analyze KPI trends from historical snapshots')
539
+ .option('--definitions <path>', 'Metric definition YAML/JSON path')
540
+ .option('--history-dir <path>', 'History snapshots directory')
541
+ .option('--window <n>', 'Use latest N snapshots for trend analysis', parseInt)
542
+ .option('--out <path>', 'Output path for trend JSON')
543
+ .option('--json', 'Emit machine-readable JSON')
544
+ .action(async options => {
545
+ try {
546
+ await runValueMetricsTrend(options);
547
+ } catch (error) {
548
+ if (options.json) {
549
+ console.log(JSON.stringify({ success: false, error: error.message }, null, 2));
550
+ } else {
551
+ console.error(chalk.red('❌ Value metrics trend failed:'), error.message);
552
+ }
553
+ process.exit(1);
554
+ }
555
+ });
556
+ }
557
+
558
+ module.exports = {
559
+ registerValueCommands,
560
+ runValueMetricsSample,
561
+ runValueMetricsSnapshot,
562
+ runValueMetricsBaseline,
563
+ runValueMetricsTrend,
564
+ _loadHistorySnapshots: loadHistorySnapshots,
565
+ _resolveMetricInput: resolveMetricInput,
566
+ _sortSnapshotsByPeriod: sortSnapshotsByPeriod,
567
+ _getIsoWeekPeriod: getIsoWeekPeriod,
568
+ _createSampleMetricsInput: createSampleMetricsInput
569
+ };