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,176 @@
1
+ const RepoManager = require('../repo-manager');
2
+ const ConfigManager = require('../config-manager');
3
+ const OutputFormatter = require('../output-formatter');
4
+
5
+ /**
6
+ * StatusHandler - Handles repository status command
7
+ *
8
+ * Displays the Git status of all configured repositories in a
9
+ * tabular format with optional verbose output.
10
+ */
11
+ class StatusHandler {
12
+ /**
13
+ * Create a new StatusHandler
14
+ * @param {string} projectRoot - The project root directory
15
+ */
16
+ constructor(projectRoot) {
17
+ this.projectRoot = projectRoot;
18
+ this.repoManager = new RepoManager(projectRoot);
19
+ this.configManager = new ConfigManager(projectRoot);
20
+ this.formatter = new OutputFormatter();
21
+ }
22
+
23
+ /**
24
+ * Execute status command
25
+ * @param {Object} options - Status options
26
+ * @param {boolean} options.verbose - Show detailed file-level changes
27
+ * @returns {Promise<void>}
28
+ */
29
+ async execute(options = {}) {
30
+ const { verbose = false } = options;
31
+
32
+ // Load configuration
33
+ let config;
34
+ try {
35
+ config = await this.configManager.loadConfig();
36
+ } catch (error) {
37
+ console.log(this.formatter.error(error.message));
38
+ throw error;
39
+ }
40
+
41
+ if (config.repositories.length === 0) {
42
+ console.log(this.formatter.warning('No repositories configured'));
43
+ return;
44
+ }
45
+
46
+ // Get status for all repositories
47
+ const progress = this.formatter.createProgress('Checking repository status...');
48
+ progress.start();
49
+
50
+ let statuses;
51
+ try {
52
+ statuses = await this.repoManager.getAllRepoStatuses(config.repositories);
53
+ progress.stop();
54
+ } catch (error) {
55
+ progress.fail('Failed to get repository status');
56
+ throw error;
57
+ }
58
+
59
+ // Display status
60
+ if (verbose) {
61
+ this.formatVerboseStatus(statuses);
62
+ } else {
63
+ this.formatStatusTable(statuses);
64
+ }
65
+
66
+ // Display summary
67
+ const cleanRepos = statuses.filter(s => s.isClean && !s.error).length;
68
+ const dirtyRepos = statuses.filter(s => !s.isClean && !s.error).length;
69
+ const errorRepos = statuses.filter(s => s.error).length;
70
+
71
+ console.log('\nSummary:');
72
+ console.log(` Clean: ${cleanRepos}`);
73
+ console.log(` Modified: ${dirtyRepos}`);
74
+ if (errorRepos > 0) {
75
+ console.log(this.formatter.error(` Errors: ${errorRepos}`));
76
+ }
77
+ }
78
+
79
+ /**
80
+ * Format status output as table
81
+ * @param {Array<Object>} statuses - Array of repository statuses
82
+ */
83
+ formatStatusTable(statuses) {
84
+ const tableData = statuses.map(status => {
85
+ if (status.error) {
86
+ return [
87
+ status.name,
88
+ status.path,
89
+ this.formatter.error('ERROR'),
90
+ status.error
91
+ ];
92
+ }
93
+
94
+ const statusStr = status.isClean
95
+ ? this.formatter.success('Clean')
96
+ : this.formatter.warning('Modified');
97
+
98
+ let changes = '';
99
+ if (!status.isClean) {
100
+ const parts = [];
101
+ if (status.modified > 0) parts.push(`M:${status.modified}`);
102
+ if (status.added > 0) parts.push(`A:${status.added}`);
103
+ if (status.deleted > 0) parts.push(`D:${status.deleted}`);
104
+ if (status.ahead > 0) parts.push(`↑${status.ahead}`);
105
+ if (status.behind > 0) parts.push(`↓${status.behind}`);
106
+ changes = parts.join(' ');
107
+ }
108
+
109
+ return [
110
+ status.name,
111
+ status.path,
112
+ status.branch || 'N/A',
113
+ statusStr,
114
+ changes
115
+ ];
116
+ });
117
+
118
+ const table = this.formatter.formatTable([], {
119
+ head: ['Name', 'Path', 'Branch', 'Status', 'Changes'],
120
+ rows: tableData
121
+ });
122
+
123
+ console.log('\n' + table);
124
+ }
125
+
126
+ /**
127
+ * Format verbose status output
128
+ * @param {Array<Object>} statuses - Array of repository statuses
129
+ */
130
+ formatVerboseStatus(statuses) {
131
+ console.log('\n' + this.formatter.info('Repository Status (Verbose)'));
132
+ console.log('='.repeat(80));
133
+
134
+ statuses.forEach((status, index) => {
135
+ if (index > 0) {
136
+ console.log('\n' + '-'.repeat(80));
137
+ }
138
+
139
+ console.log(`\n${this.formatter.info('Repository:')} ${status.name}`);
140
+ console.log(`${this.formatter.info('Path:')} ${status.path}`);
141
+
142
+ if (status.error) {
143
+ console.log(`${this.formatter.error('Error:')} ${status.error}`);
144
+ return;
145
+ }
146
+
147
+ console.log(`${this.formatter.info('Branch:')} ${status.branch}`);
148
+
149
+ if (status.isClean) {
150
+ console.log(this.formatter.success('Status: Clean - no changes'));
151
+ } else {
152
+ console.log(this.formatter.warning('Status: Modified'));
153
+
154
+ if (status.modified > 0) {
155
+ console.log(` Modified files: ${status.modified}`);
156
+ }
157
+ if (status.added > 0) {
158
+ console.log(` Added files: ${status.added}`);
159
+ }
160
+ if (status.deleted > 0) {
161
+ console.log(` Deleted files: ${status.deleted}`);
162
+ }
163
+ if (status.ahead > 0) {
164
+ console.log(` Commits ahead: ${status.ahead}`);
165
+ }
166
+ if (status.behind > 0) {
167
+ console.log(` Commits behind: ${status.behind}`);
168
+ }
169
+ }
170
+ });
171
+
172
+ console.log('\n' + '='.repeat(80));
173
+ }
174
+ }
175
+
176
+ module.exports = StatusHandler;
@@ -0,0 +1,184 @@
1
+ const chalk = require('chalk');
2
+ const Table = require('cli-table3');
3
+
4
+ /**
5
+ * OutputFormatter provides consistent formatting for command output
6
+ * with color-coding and table support.
7
+ */
8
+ class OutputFormatter {
9
+ constructor() {
10
+ this.chalk = chalk;
11
+ }
12
+
13
+ /**
14
+ * Format data as table
15
+ * @param {Object[]} data - Array of data objects
16
+ * @param {Object} options - Table options
17
+ * @param {string[]} options.head - Table header columns
18
+ * @param {string[][]} options.rows - Table rows (optional, will be extracted from data if not provided)
19
+ * @param {Object} options.style - Table style options (optional)
20
+ * @returns {string} Formatted table string
21
+ */
22
+ formatTable(data, options = {}) {
23
+ const tableConfig = {
24
+ head: options.head || [],
25
+ style: {
26
+ head: ['cyan'],
27
+ border: ['gray'],
28
+ ...options.style
29
+ }
30
+ };
31
+
32
+ const table = new Table(tableConfig);
33
+
34
+ // If rows are provided directly, use them
35
+ if (options.rows) {
36
+ options.rows.forEach(row => table.push(row));
37
+ } else if (Array.isArray(data) && data.length > 0) {
38
+ // Otherwise, extract rows from data objects
39
+ data.forEach(item => {
40
+ const row = options.head.map(header => {
41
+ const key = header.toLowerCase().replace(/\s+/g, '');
42
+ return item[key] !== undefined ? String(item[key]) : '';
43
+ });
44
+ table.push(row);
45
+ });
46
+ }
47
+
48
+ return table.toString();
49
+ }
50
+
51
+ /**
52
+ * Format success message
53
+ * @param {string} message - Success message
54
+ * @returns {string} Formatted success message
55
+ */
56
+ success(message) {
57
+ return chalk.green(`✅ ${message}`);
58
+ }
59
+
60
+ /**
61
+ * Format error message
62
+ * @param {string} message - Error message
63
+ * @returns {string} Formatted error message
64
+ */
65
+ error(message) {
66
+ return chalk.red(`❌ ${message}`);
67
+ }
68
+
69
+ /**
70
+ * Format warning message
71
+ * @param {string} message - Warning message
72
+ * @returns {string} Formatted warning message
73
+ */
74
+ warning(message) {
75
+ return chalk.yellow(`⚠️ ${message}`);
76
+ }
77
+
78
+ /**
79
+ * Format info message
80
+ * @param {string} message - Info message
81
+ * @returns {string} Formatted info message
82
+ */
83
+ info(message) {
84
+ return chalk.blue(`ℹ️ ${message}`);
85
+ }
86
+
87
+ /**
88
+ * Create progress indicator
89
+ * @param {string} message - Progress message
90
+ * @returns {ProgressIndicator} Progress indicator object
91
+ */
92
+ createProgress(message) {
93
+ return new ProgressIndicator(message);
94
+ }
95
+ }
96
+
97
+ /**
98
+ * ProgressIndicator provides a simple progress indicator for long-running operations
99
+ */
100
+ class ProgressIndicator {
101
+ constructor(message) {
102
+ this.message = message;
103
+ this.started = false;
104
+ this.frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
105
+ this.currentFrame = 0;
106
+ this.interval = null;
107
+ }
108
+
109
+ /**
110
+ * Start the progress indicator
111
+ */
112
+ start() {
113
+ if (this.started) return;
114
+
115
+ this.started = true;
116
+ process.stdout.write(`${this.frames[0]} ${this.message}`);
117
+
118
+ this.interval = setInterval(() => {
119
+ this.currentFrame = (this.currentFrame + 1) % this.frames.length;
120
+ process.stdout.write(`\r${this.frames[this.currentFrame]} ${this.message}`);
121
+ }, 80);
122
+ if (this.interval && typeof this.interval.unref === 'function') {
123
+ this.interval.unref();
124
+ }
125
+ }
126
+
127
+ /**
128
+ * Update the progress message
129
+ * @param {string} message - New progress message
130
+ */
131
+ update(message) {
132
+ this.message = message;
133
+ if (this.started) {
134
+ process.stdout.write(`\r${this.frames[this.currentFrame]} ${this.message}`);
135
+ }
136
+ }
137
+
138
+ /**
139
+ * Stop the progress indicator with a success message
140
+ * @param {string} message - Success message (optional)
141
+ */
142
+ succeed(message) {
143
+ this.stop();
144
+ const finalMessage = message || this.message;
145
+ console.log(chalk.green(`✅ ${finalMessage}`));
146
+ }
147
+
148
+ /**
149
+ * Stop the progress indicator with an error message
150
+ * @param {string} message - Error message (optional)
151
+ */
152
+ fail(message) {
153
+ this.stop();
154
+ const finalMessage = message || this.message;
155
+ console.log(chalk.red(`❌ ${finalMessage}`));
156
+ }
157
+
158
+ /**
159
+ * Stop the progress indicator with a warning message
160
+ * @param {string} message - Warning message (optional)
161
+ */
162
+ warn(message) {
163
+ this.stop();
164
+ const finalMessage = message || this.message;
165
+ console.log(chalk.yellow(`⚠️ ${finalMessage}`));
166
+ }
167
+
168
+ /**
169
+ * Stop the progress indicator
170
+ */
171
+ stop() {
172
+ if (!this.started) return;
173
+
174
+ if (this.interval) {
175
+ clearInterval(this.interval);
176
+ this.interval = null;
177
+ }
178
+
179
+ process.stdout.write('\r\x1b[K'); // Clear the line
180
+ this.started = false;
181
+ }
182
+ }
183
+
184
+ module.exports = OutputFormatter;
@@ -0,0 +1,178 @@
1
+ const path = require('path');
2
+
3
+ /**
4
+ * PathResolver handles cross-platform path resolution and validation
5
+ * for repository paths. It ensures consistent path handling across
6
+ * Windows, Linux, and Mac platforms.
7
+ */
8
+ class PathResolver {
9
+ /**
10
+ * Resolve repository path relative to project root
11
+ * @param {string} repoPath - The repository path (relative or absolute)
12
+ * @param {string} projectRoot - The project root directory
13
+ * @returns {string} Resolved absolute path
14
+ */
15
+ resolvePath(repoPath, projectRoot) {
16
+ if (!repoPath) {
17
+ throw new Error('Repository path cannot be empty');
18
+ }
19
+ if (!projectRoot) {
20
+ throw new Error('Project root cannot be empty');
21
+ }
22
+
23
+ // If path is absolute, return normalized version
24
+ if (this.isAbsolute(repoPath)) {
25
+ return this.normalizePath(path.resolve(repoPath));
26
+ }
27
+
28
+ // Resolve relative path against project root
29
+ return this.normalizePath(path.resolve(projectRoot, repoPath));
30
+ }
31
+
32
+ /**
33
+ * Normalize path to use forward slashes consistently
34
+ * @param {string} pathStr - The path to normalize
35
+ * @returns {string} Normalized path with forward slashes
36
+ */
37
+ normalizePath(pathStr) {
38
+ if (!pathStr) {
39
+ return pathStr;
40
+ }
41
+
42
+ // Normalize the path first (resolves . and ..)
43
+ let normalized = path.normalize(pathStr);
44
+
45
+ // Convert backslashes to forward slashes
46
+ normalized = normalized.replace(/\\/g, '/');
47
+
48
+ // Handle Windows drive letters - keep them uppercase
49
+ if (this._isWindowsPath(normalized)) {
50
+ normalized = normalized.charAt(0).toUpperCase() + normalized.slice(1);
51
+ }
52
+
53
+ // Remove trailing slashes (except for root paths)
54
+ if (normalized.length > 1 && normalized.endsWith('/')) {
55
+ // Don't remove trailing slash from root paths like '/' or 'C:/'
56
+ if (!(normalized.length === 3 && this._isWindowsPath(normalized))) {
57
+ normalized = normalized.slice(0, -1);
58
+ }
59
+ }
60
+
61
+ return normalized;
62
+ }
63
+
64
+ /**
65
+ * Check if path is absolute (cross-platform)
66
+ * @param {string} pathStr - The path to check
67
+ * @returns {boolean} True if path is absolute
68
+ */
69
+ isAbsolute(pathStr) {
70
+ if (!pathStr) {
71
+ return false;
72
+ }
73
+
74
+ // Check for Windows absolute paths (C:/ or C:\) - must check first
75
+ // because path.isAbsolute() is platform-dependent
76
+ if (this._isWindowsPath(pathStr)) {
77
+ return true;
78
+ }
79
+
80
+ // Check for Unix absolute paths (starts with /)
81
+ // On Unix systems, this will correctly identify /home/user
82
+ // On Windows systems, this will correctly identify C:/... (already handled above)
83
+ return pathStr.startsWith('/');
84
+ }
85
+
86
+ /**
87
+ * Convert absolute path to relative path
88
+ * @param {string} absolutePath - The absolute path
89
+ * @param {string} basePath - The base path to make it relative to
90
+ * @returns {string} Relative path
91
+ */
92
+ toRelative(absolutePath, basePath) {
93
+ if (!absolutePath || !basePath) {
94
+ throw new Error('Both absolutePath and basePath are required');
95
+ }
96
+
97
+ const relativePath = path.relative(basePath, absolutePath);
98
+ return this.normalizePath(relativePath);
99
+ }
100
+
101
+ /**
102
+ * Validate that paths don't overlap or nest within each other
103
+ * @param {string[]} paths - Array of absolute paths to validate
104
+ * @returns {{valid: boolean, errors: string[]}} Validation result
105
+ */
106
+ validateNoOverlap(paths) {
107
+ const errors = [];
108
+
109
+ if (!Array.isArray(paths)) {
110
+ return { valid: false, errors: ['Paths must be an array'] };
111
+ }
112
+
113
+ if (paths.length === 0) {
114
+ return { valid: true, errors: [] };
115
+ }
116
+
117
+ // Normalize all paths for comparison
118
+ const normalizedPaths = paths.map(p => this.normalizePath(p));
119
+
120
+ // Check for duplicates
121
+ const seen = new Set();
122
+ for (let i = 0; i < normalizedPaths.length; i++) {
123
+ const p = normalizedPaths[i];
124
+ if (seen.has(p)) {
125
+ errors.push(`Duplicate path found: ${paths[i]}`);
126
+ }
127
+ seen.add(p);
128
+ }
129
+
130
+ // Check for overlapping/nested paths
131
+ for (let i = 0; i < normalizedPaths.length; i++) {
132
+ for (let j = i + 1; j < normalizedPaths.length; j++) {
133
+ const path1 = normalizedPaths[i];
134
+ const path2 = normalizedPaths[j];
135
+
136
+ // Check if path2 is nested within path1
137
+ if (this._isNestedPath(path2, path1)) {
138
+ errors.push(`Path "${paths[j]}" is nested within "${paths[i]}"`);
139
+ }
140
+ // Check if path1 is nested within path2
141
+ else if (this._isNestedPath(path1, path2)) {
142
+ errors.push(`Path "${paths[i]}" is nested within "${paths[j]}"`);
143
+ }
144
+ }
145
+ }
146
+
147
+ return {
148
+ valid: errors.length === 0,
149
+ errors
150
+ };
151
+ }
152
+
153
+ /**
154
+ * Check if a path is nested within another path
155
+ * @private
156
+ * @param {string} childPath - The potential child path
157
+ * @param {string} parentPath - The potential parent path
158
+ * @returns {boolean} True if childPath is nested within parentPath
159
+ */
160
+ _isNestedPath(childPath, parentPath) {
161
+ // Ensure paths end with separator for accurate comparison
162
+ const normalizedParent = parentPath.endsWith('/') ? parentPath : parentPath + '/';
163
+ return childPath.startsWith(normalizedParent);
164
+ }
165
+
166
+ /**
167
+ * Check if path is a Windows path (has drive letter)
168
+ * @private
169
+ * @param {string} pathStr - The path to check
170
+ * @returns {boolean} True if path is a Windows path
171
+ */
172
+ _isWindowsPath(pathStr) {
173
+ // Check for drive letter pattern: C:/ or C:\
174
+ return /^[a-zA-Z]:/.test(pathStr);
175
+ }
176
+ }
177
+
178
+ module.exports = PathResolver;