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,284 @@
1
+ /**
2
+ * Archive Tool
3
+ *
4
+ * Organizes Spec artifacts into proper subdirectories
5
+ */
6
+
7
+ const fs = require('fs-extra');
8
+ const path = require('path');
9
+ const FileScanner = require('./file-scanner');
10
+
11
+ class ArchiveTool {
12
+ constructor(projectPath, config) {
13
+ this.projectPath = projectPath;
14
+ this.config = config;
15
+ this.scanner = new FileScanner(projectPath);
16
+ this.movedFiles = [];
17
+ this.errors = [];
18
+ }
19
+
20
+ /**
21
+ * Archive artifacts in a Spec directory
22
+ *
23
+ * @param {string} specName - Spec name
24
+ * @param {Object} options - Archive options
25
+ * @param {boolean} options.dryRun - Preview without moving
26
+ * @returns {Promise<ArchiveReport>}
27
+ */
28
+ async archive(specName, options = {}) {
29
+ const specPath = this.scanner.getSpecDirectory(specName);
30
+
31
+ // Check if Spec directory exists
32
+ if (!await this.scanner.exists(specPath)) {
33
+ this.errors.push({
34
+ path: specPath,
35
+ error: `Spec directory does not exist: ${specName}`
36
+ });
37
+ return this.generateReport();
38
+ }
39
+
40
+ const artifacts = await this.identifyArtifacts(specPath);
41
+
42
+ if (options.dryRun) {
43
+ return this.generateDryRunReport(artifacts);
44
+ }
45
+
46
+ for (const artifact of artifacts) {
47
+ await this.moveArtifact(artifact);
48
+ }
49
+
50
+ return this.generateReport();
51
+ }
52
+
53
+ /**
54
+ * Identify artifacts to archive
55
+ *
56
+ * @param {string} specPath - Path to Spec directory
57
+ * @returns {Promise<Artifact[]>}
58
+ */
59
+ async identifyArtifacts(specPath) {
60
+ const artifacts = [];
61
+ const files = await this.scanner.getFiles(specPath);
62
+ const requiredFiles = ['requirements.md', 'design.md', 'tasks.md'];
63
+
64
+ for (const filePath of files) {
65
+ const basename = path.basename(filePath);
66
+
67
+ // Skip required files
68
+ if (requiredFiles.includes(basename)) {
69
+ continue;
70
+ }
71
+
72
+ const targetSubdir = this.determineTargetSubdir(basename);
73
+ artifacts.push({
74
+ sourcePath: filePath,
75
+ targetSubdir: targetSubdir,
76
+ filename: basename
77
+ });
78
+ }
79
+
80
+ return artifacts;
81
+ }
82
+
83
+ /**
84
+ * Determine target subdirectory for a file
85
+ *
86
+ * @param {string} filename - File name
87
+ * @returns {string}
88
+ */
89
+ determineTargetSubdir(filename) {
90
+ const lower = filename.toLowerCase();
91
+
92
+ // Results - check for result keywords FIRST (before test patterns)
93
+ // This ensures "test-results.json" goes to results, not tests
94
+ if (lower.includes('result') || lower.includes('output')) {
95
+ return this.resolveConfiguredSubdir('results');
96
+ }
97
+
98
+ // Tests - check for test patterns (test files, not result files)
99
+ if (lower.endsWith('.test.js') || lower.endsWith('.spec.js') ||
100
+ lower.includes('.test.') || lower.includes('.spec.') ||
101
+ (lower.includes('test') && (lower.endsWith('.js') || lower.endsWith('.py')))) {
102
+ return this.resolveConfiguredSubdir('tests');
103
+ }
104
+
105
+ // Scripts - check for script extensions and keywords
106
+ if (lower.endsWith('.js') || lower.endsWith('.py') ||
107
+ lower.endsWith('.sh') || lower.endsWith('.bat') ||
108
+ lower.includes('script')) {
109
+ return this.resolveConfiguredSubdir('scripts');
110
+ }
111
+
112
+ // Reports - check for report keywords
113
+ if (lower.includes('report') || lower.includes('analysis') ||
114
+ lower.includes('summary') || lower.includes('diagnostic')) {
115
+ return this.resolveConfiguredSubdir('reports');
116
+ }
117
+
118
+ // Data files
119
+ if (lower.includes('data')) {
120
+ return this.resolveConfiguredSubdir('results');
121
+ }
122
+
123
+ // Default to docs for markdown and other documentation files
124
+ return this.resolveConfiguredSubdir('docs');
125
+ }
126
+
127
+ /**
128
+ * Resolve preferred subdirectory against project governance config
129
+ *
130
+ * @param {string} preferredSubdir - Preferred subdirectory name
131
+ * @returns {string}
132
+ */
133
+ resolveConfiguredSubdir(preferredSubdir) {
134
+ const allowedSubdirs = this.getAllowedSpecSubdirs();
135
+
136
+ // Backward compatibility when no config is available
137
+ if (allowedSubdirs.length === 0) {
138
+ return preferredSubdir;
139
+ }
140
+
141
+ if (allowedSubdirs.includes(preferredSubdir)) {
142
+ return preferredSubdir;
143
+ }
144
+
145
+ // Generic safe fallback for governance-customized projects
146
+ if (allowedSubdirs.includes('custom')) {
147
+ return 'custom';
148
+ }
149
+
150
+ // Semantic fallback when custom bucket is unavailable
151
+ const fallbackMap = {
152
+ docs: 'reports',
153
+ tests: 'scripts',
154
+ results: 'reports'
155
+ };
156
+
157
+ const mappedSubdir = fallbackMap[preferredSubdir];
158
+ if (mappedSubdir && allowedSubdirs.includes(mappedSubdir)) {
159
+ return mappedSubdir;
160
+ }
161
+
162
+ return allowedSubdirs[0];
163
+ }
164
+
165
+ /**
166
+ * Get normalized allowed Spec subdirectories from config
167
+ *
168
+ * @returns {string[]}
169
+ */
170
+ getAllowedSpecSubdirs() {
171
+ const configured = this.config && Array.isArray(this.config.specSubdirs)
172
+ ? this.config.specSubdirs
173
+ : [];
174
+
175
+ return configured
176
+ .filter(subdir => typeof subdir === 'string' && subdir.trim().length > 0)
177
+ .map(subdir => subdir.trim().toLowerCase());
178
+ }
179
+
180
+ /**
181
+ * Move an artifact to its target subdirectory
182
+ *
183
+ * @param {Artifact} artifact - Artifact to move
184
+ * @returns {Promise<void>}
185
+ */
186
+ async moveArtifact(artifact) {
187
+ try {
188
+ const targetDir = path.join(
189
+ path.dirname(artifact.sourcePath),
190
+ artifact.targetSubdir
191
+ );
192
+
193
+ // Ensure target directory exists
194
+ await fs.ensureDir(targetDir);
195
+
196
+ const targetPath = path.join(targetDir, artifact.filename);
197
+
198
+ // Check if target file already exists
199
+ if (await fs.pathExists(targetPath)) {
200
+ this.errors.push({
201
+ path: artifact.sourcePath,
202
+ error: `Target file already exists: ${targetPath}`
203
+ });
204
+ return;
205
+ }
206
+
207
+ await fs.move(artifact.sourcePath, targetPath);
208
+
209
+ this.movedFiles.push({
210
+ from: artifact.sourcePath,
211
+ to: targetPath
212
+ });
213
+ } catch (error) {
214
+ this.errors.push({
215
+ path: artifact.sourcePath,
216
+ error: error.message
217
+ });
218
+ }
219
+ }
220
+
221
+ /**
222
+ * Generate dry run report
223
+ *
224
+ * @param {Artifact[]} artifacts - Artifacts that would be moved
225
+ * @returns {ArchiveReport}
226
+ */
227
+ generateDryRunReport(artifacts) {
228
+ const movedFiles = artifacts.map(artifact => ({
229
+ from: artifact.sourcePath,
230
+ to: path.join(
231
+ path.dirname(artifact.sourcePath),
232
+ artifact.targetSubdir,
233
+ artifact.filename
234
+ )
235
+ }));
236
+
237
+ return {
238
+ success: true,
239
+ movedFiles: movedFiles,
240
+ errors: [],
241
+ summary: {
242
+ totalMoved: movedFiles.length,
243
+ totalErrors: 0
244
+ },
245
+ dryRun: true
246
+ };
247
+ }
248
+
249
+ /**
250
+ * Generate archive report
251
+ *
252
+ * @returns {ArchiveReport}
253
+ */
254
+ generateReport() {
255
+ return {
256
+ success: this.errors.length === 0,
257
+ movedFiles: this.movedFiles,
258
+ errors: this.errors,
259
+ summary: {
260
+ totalMoved: this.movedFiles.length,
261
+ totalErrors: this.errors.length
262
+ },
263
+ dryRun: false
264
+ };
265
+ }
266
+ }
267
+
268
+ /**
269
+ * @typedef {Object} Artifact
270
+ * @property {string} sourcePath - Current file path
271
+ * @property {string} targetSubdir - Target subdirectory name
272
+ * @property {string} filename - File name
273
+ */
274
+
275
+ /**
276
+ * @typedef {Object} ArchiveReport
277
+ * @property {boolean} success - Whether archiving succeeded
278
+ * @property {Object[]} movedFiles - Files that were moved
279
+ * @property {Object[]} errors - Errors encountered
280
+ * @property {Object} summary - Summary statistics
281
+ * @property {boolean} dryRun - Whether this was a dry run
282
+ */
283
+
284
+ module.exports = ArchiveTool;
@@ -0,0 +1,237 @@
1
+ /**
2
+ * Cleanup Tool
3
+ *
4
+ * Removes temporary and non-compliant documents
5
+ */
6
+
7
+ const fs = require('fs-extra');
8
+ const path = require('path');
9
+ const inquirer = require('inquirer');
10
+ const FileScanner = require('./file-scanner');
11
+
12
+ class CleanupTool {
13
+ constructor(projectPath, config) {
14
+ this.projectPath = projectPath;
15
+ this.config = config;
16
+ this.scanner = new FileScanner(projectPath);
17
+ this.deletedFiles = [];
18
+ this.errors = [];
19
+ }
20
+
21
+ /**
22
+ * Execute cleanup operation
23
+ *
24
+ * @param {Object} options - Cleanup options
25
+ * @param {boolean} options.dryRun - Preview without deleting
26
+ * @param {boolean} options.interactive - Prompt for each file
27
+ * @param {string} options.spec - Specific Spec to clean
28
+ * @returns {Promise<CleanupReport>}
29
+ */
30
+ async cleanup(options = {}) {
31
+ const filesToDelete = await this.identifyFilesToDelete(options.spec);
32
+
33
+ if (options.dryRun) {
34
+ return this.generateDryRunReport(filesToDelete);
35
+ }
36
+
37
+ for (const file of filesToDelete) {
38
+ if (options.interactive) {
39
+ const shouldDelete = await this.promptForConfirmation(file);
40
+ if (!shouldDelete) continue;
41
+ }
42
+
43
+ await this.deleteFile(file);
44
+ }
45
+
46
+ return this.generateReport();
47
+ }
48
+
49
+ /**
50
+ * Identify files to delete
51
+ *
52
+ * @param {string} specName - Optional specific Spec
53
+ * @returns {Promise<string[]>}
54
+ */
55
+ async identifyFilesToDelete(specName = null) {
56
+ const files = [];
57
+
58
+ // Scan root directory
59
+ files.push(...await this.scanRootForTemporary());
60
+
61
+ // Scan Spec directories
62
+ if (specName) {
63
+ files.push(...await this.scanSpecForTemporary(specName));
64
+ } else {
65
+ files.push(...await this.scanAllSpecsForTemporary());
66
+ }
67
+
68
+ return files;
69
+ }
70
+
71
+ /**
72
+ * Scan root directory for temporary files
73
+ *
74
+ * @returns {Promise<string[]>}
75
+ */
76
+ async scanRootForTemporary() {
77
+ const temporaryFiles = [];
78
+ const mdFiles = await this.scanner.findMarkdownFiles(this.projectPath);
79
+ const allowedFiles = this.config.rootAllowedFiles || [];
80
+ const temporaryPatterns = this.config.temporaryPatterns || [];
81
+
82
+ for (const filePath of mdFiles) {
83
+ const basename = path.basename(filePath);
84
+
85
+ // If not in allowed list, check if it matches temporary patterns
86
+ if (!allowedFiles.includes(basename)) {
87
+ // Check if it matches any temporary pattern
88
+ if (this.scanner.matchesPattern(filePath, temporaryPatterns)) {
89
+ temporaryFiles.push(filePath);
90
+ }
91
+ }
92
+ }
93
+
94
+ return temporaryFiles;
95
+ }
96
+
97
+ /**
98
+ * Scan a specific Spec directory for temporary files
99
+ *
100
+ * @param {string} specName - Spec name
101
+ * @returns {Promise<string[]>}
102
+ */
103
+ async scanSpecForTemporary(specName) {
104
+ const temporaryFiles = [];
105
+ const specPath = this.scanner.getSpecDirectory(specName);
106
+
107
+ // Check if Spec directory exists
108
+ if (!await this.scanner.exists(specPath)) {
109
+ return temporaryFiles;
110
+ }
111
+
112
+ const mdFiles = await this.scanner.findMarkdownFiles(specPath);
113
+ const temporaryPatterns = this.config.temporaryPatterns || [];
114
+ const requiredFiles = ['requirements.md', 'design.md', 'tasks.md'];
115
+
116
+ for (const filePath of mdFiles) {
117
+ const basename = path.basename(filePath);
118
+
119
+ // Don't delete required files even if they match patterns
120
+ if (requiredFiles.includes(basename)) {
121
+ continue;
122
+ }
123
+
124
+ // Check if it matches any temporary pattern
125
+ if (this.scanner.matchesPattern(filePath, temporaryPatterns)) {
126
+ temporaryFiles.push(filePath);
127
+ }
128
+ }
129
+
130
+ return temporaryFiles;
131
+ }
132
+
133
+ /**
134
+ * Scan all Spec directories for temporary files
135
+ *
136
+ * @returns {Promise<string[]>}
137
+ */
138
+ async scanAllSpecsForTemporary() {
139
+ const temporaryFiles = [];
140
+ const specDirs = await this.scanner.findSpecDirectories();
141
+
142
+ for (const specDir of specDirs) {
143
+ const specName = path.basename(specDir);
144
+ const specTemporaryFiles = await this.scanSpecForTemporary(specName);
145
+ temporaryFiles.push(...specTemporaryFiles);
146
+ }
147
+
148
+ return temporaryFiles;
149
+ }
150
+
151
+ /**
152
+ * Prompt user for confirmation to delete a file
153
+ *
154
+ * @param {string} filePath - Path to file
155
+ * @returns {Promise<boolean>}
156
+ */
157
+ async promptForConfirmation(filePath) {
158
+ const relativePath = this.scanner.getRelativePath(filePath);
159
+
160
+ const answer = await inquirer.prompt([
161
+ {
162
+ type: 'confirm',
163
+ name: 'shouldDelete',
164
+ message: `Delete ${relativePath}?`,
165
+ default: false
166
+ }
167
+ ]);
168
+
169
+ return answer.shouldDelete;
170
+ }
171
+
172
+ /**
173
+ * Delete a file safely
174
+ *
175
+ * @param {string} filePath - Path to file
176
+ * @returns {Promise<void>}
177
+ */
178
+ async deleteFile(filePath) {
179
+ try {
180
+ await fs.remove(filePath);
181
+ this.deletedFiles.push(filePath);
182
+ } catch (error) {
183
+ this.errors.push({
184
+ path: filePath,
185
+ error: error.message
186
+ });
187
+ }
188
+ }
189
+
190
+ /**
191
+ * Generate dry run report
192
+ *
193
+ * @param {string[]} filesToDelete - Files that would be deleted
194
+ * @returns {CleanupReport}
195
+ */
196
+ generateDryRunReport(filesToDelete) {
197
+ return {
198
+ success: true,
199
+ deletedFiles: filesToDelete,
200
+ errors: [],
201
+ summary: {
202
+ totalDeleted: filesToDelete.length,
203
+ totalErrors: 0
204
+ },
205
+ dryRun: true
206
+ };
207
+ }
208
+
209
+ /**
210
+ * Generate cleanup report
211
+ *
212
+ * @returns {CleanupReport}
213
+ */
214
+ generateReport() {
215
+ return {
216
+ success: this.errors.length === 0,
217
+ deletedFiles: this.deletedFiles,
218
+ errors: this.errors,
219
+ summary: {
220
+ totalDeleted: this.deletedFiles.length,
221
+ totalErrors: this.errors.length
222
+ },
223
+ dryRun: false
224
+ };
225
+ }
226
+ }
227
+
228
+ /**
229
+ * @typedef {Object} CleanupReport
230
+ * @property {boolean} success - Whether cleanup succeeded
231
+ * @property {string[]} deletedFiles - Files that were deleted
232
+ * @property {Object[]} errors - Errors encountered
233
+ * @property {Object} summary - Summary statistics
234
+ * @property {boolean} dryRun - Whether this was a dry run
235
+ */
236
+
237
+ module.exports = CleanupTool;
@@ -0,0 +1,186 @@
1
+ /**
2
+ * Configuration Manager
3
+ *
4
+ * Manages document governance configuration
5
+ */
6
+
7
+ const fs = require('fs-extra');
8
+ const path = require('path');
9
+
10
+ class ConfigManager {
11
+ constructor(projectPath) {
12
+ this.projectPath = projectPath;
13
+ this.configPath = path.join(projectPath, '.kiro/config/docs.json');
14
+ this.config = null;
15
+ }
16
+
17
+ /**
18
+ * Load configuration
19
+ *
20
+ * @returns {Promise<Object>}
21
+ */
22
+ async load() {
23
+ if (await fs.pathExists(this.configPath)) {
24
+ try {
25
+ this.config = await fs.readJson(this.configPath);
26
+
27
+ // Validate and merge with defaults to ensure all required fields exist
28
+ const defaults = this.getDefaults();
29
+ this.config = { ...defaults, ...this.config };
30
+
31
+ } catch (error) {
32
+ console.warn('Config file corrupted, using defaults');
33
+ this.config = this.getDefaults();
34
+ }
35
+ } else {
36
+ this.config = this.getDefaults();
37
+ }
38
+
39
+ return this.config;
40
+ }
41
+
42
+ /**
43
+ * Get default configuration
44
+ *
45
+ * @returns {Object}
46
+ */
47
+ getDefaults() {
48
+ return {
49
+ rootAllowedFiles: [
50
+ 'README.md',
51
+ 'README.zh.md',
52
+ 'CHANGELOG.md',
53
+ 'CONTRIBUTING.md'
54
+ ],
55
+ specSubdirs: [
56
+ 'reports',
57
+ 'scripts',
58
+ 'tests',
59
+ 'results',
60
+ 'docs'
61
+ ],
62
+ temporaryPatterns: [
63
+ '*-SUMMARY.md',
64
+ 'SESSION-*.md',
65
+ '*-COMPLETE.md',
66
+ 'TEMP-*.md',
67
+ 'WIP-*.md',
68
+ 'MVP-*.md'
69
+ ]
70
+ };
71
+ }
72
+
73
+ /**
74
+ * Save configuration
75
+ *
76
+ * @param {Object} config - Configuration to save
77
+ * @returns {Promise<void>}
78
+ */
79
+ async save(config) {
80
+ await fs.ensureDir(path.dirname(this.configPath));
81
+ await fs.writeJson(this.configPath, config, { spaces: 2 });
82
+ this.config = config;
83
+ }
84
+
85
+ /**
86
+ * Update a configuration value
87
+ *
88
+ * @param {string} key - Configuration key
89
+ * @param {any} value - New value
90
+ * @returns {Promise<void>}
91
+ */
92
+ async set(key, value) {
93
+ if (!this.config) {
94
+ await this.load();
95
+ }
96
+
97
+ this.config[key] = value;
98
+ await this.save(this.config);
99
+ }
100
+
101
+ /**
102
+ * Get a configuration value
103
+ *
104
+ * @param {string} key - Configuration key
105
+ * @returns {any} - Configuration value
106
+ */
107
+ get(key) {
108
+ if (!this.config) {
109
+ throw new Error('Configuration not loaded. Call load() first.');
110
+ }
111
+
112
+ return this.config[key];
113
+ }
114
+
115
+ /**
116
+ * Get all configuration
117
+ *
118
+ * @returns {Object} - Complete configuration object
119
+ */
120
+ getAll() {
121
+ if (!this.config) {
122
+ throw new Error('Configuration not loaded. Call load() first.');
123
+ }
124
+
125
+ return { ...this.config };
126
+ }
127
+
128
+ /**
129
+ * Reset to defaults
130
+ *
131
+ * @returns {Promise<void>}
132
+ */
133
+ async reset() {
134
+ this.config = this.getDefaults();
135
+ await this.save(this.config);
136
+ }
137
+
138
+ /**
139
+ * Validate configuration structure
140
+ *
141
+ * @param {Object} config - Configuration to validate
142
+ * @returns {Object} - Validation result { valid: boolean, errors: string[] }
143
+ */
144
+ validate(config) {
145
+ const errors = [];
146
+
147
+ // Check required fields
148
+ if (!config.rootAllowedFiles || !Array.isArray(config.rootAllowedFiles)) {
149
+ errors.push('rootAllowedFiles must be an array');
150
+ }
151
+
152
+ if (!config.specSubdirs || !Array.isArray(config.specSubdirs)) {
153
+ errors.push('specSubdirs must be an array');
154
+ }
155
+
156
+ if (!config.temporaryPatterns || !Array.isArray(config.temporaryPatterns)) {
157
+ errors.push('temporaryPatterns must be an array');
158
+ }
159
+
160
+ // Check array contents
161
+ if (config.rootAllowedFiles && Array.isArray(config.rootAllowedFiles)) {
162
+ if (config.rootAllowedFiles.some(f => typeof f !== 'string')) {
163
+ errors.push('rootAllowedFiles must contain only strings');
164
+ }
165
+ }
166
+
167
+ if (config.specSubdirs && Array.isArray(config.specSubdirs)) {
168
+ if (config.specSubdirs.some(d => typeof d !== 'string')) {
169
+ errors.push('specSubdirs must contain only strings');
170
+ }
171
+ }
172
+
173
+ if (config.temporaryPatterns && Array.isArray(config.temporaryPatterns)) {
174
+ if (config.temporaryPatterns.some(p => typeof p !== 'string')) {
175
+ errors.push('temporaryPatterns must contain only strings');
176
+ }
177
+ }
178
+
179
+ return {
180
+ valid: errors.length === 0,
181
+ errors
182
+ };
183
+ }
184
+ }
185
+
186
+ module.exports = ConfigManager;