roadmap-cli 0.1.1__py3-none-any.whl

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 (521) hide show
  1. roadmap/__init__.py +27 -0
  2. roadmap/adapters/__init__.py +1 -0
  3. roadmap/adapters/base_paginated_adapter.py +117 -0
  4. roadmap/adapters/cli/__init__.py +249 -0
  5. roadmap/adapters/cli/analysis/__init__.py +5 -0
  6. roadmap/adapters/cli/analysis/commands.py +370 -0
  7. roadmap/adapters/cli/analysis/presenter.py +125 -0
  8. roadmap/adapters/cli/archive_operations.py +86 -0
  9. roadmap/adapters/cli/cli_command_helpers.py +109 -0
  10. roadmap/adapters/cli/cli_confirmations.py +74 -0
  11. roadmap/adapters/cli/cli_error_handlers.py +146 -0
  12. roadmap/adapters/cli/cli_validators.py +39 -0
  13. roadmap/adapters/cli/commands/sync_status.py +308 -0
  14. roadmap/adapters/cli/comment/__init__.py +5 -0
  15. roadmap/adapters/cli/comment/commands.py +106 -0
  16. roadmap/adapters/cli/config/__init__.py +5 -0
  17. roadmap/adapters/cli/config/commands.py +198 -0
  18. roadmap/adapters/cli/console_exports.py +10 -0
  19. roadmap/adapters/cli/core.py +26 -0
  20. roadmap/adapters/cli/crud/__init__.py +47 -0
  21. roadmap/adapters/cli/crud/base_archive.py +208 -0
  22. roadmap/adapters/cli/crud/base_create.py +154 -0
  23. roadmap/adapters/cli/crud/base_delete.py +155 -0
  24. roadmap/adapters/cli/crud/base_restore.py +283 -0
  25. roadmap/adapters/cli/crud/base_update.py +193 -0
  26. roadmap/adapters/cli/crud/crud_helpers.py +206 -0
  27. roadmap/adapters/cli/crud/crud_utils.py +152 -0
  28. roadmap/adapters/cli/crud/entity_builders.py +374 -0
  29. roadmap/adapters/cli/data/__init__.py +8 -0
  30. roadmap/adapters/cli/data/commands.py +149 -0
  31. roadmap/adapters/cli/decorators.py +208 -0
  32. roadmap/adapters/cli/dtos/__init__.py +155 -0
  33. roadmap/adapters/cli/exception_handler.py +105 -0
  34. roadmap/adapters/cli/git/__init__.py +8 -0
  35. roadmap/adapters/cli/git/commands.py +475 -0
  36. roadmap/adapters/cli/git/handlers/__init__.py +1 -0
  37. roadmap/adapters/cli/git/handlers/git_authentication_handler.py +124 -0
  38. roadmap/adapters/cli/git/handlers/git_branch_handler.py +238 -0
  39. roadmap/adapters/cli/git/handlers/git_connectivity_handler.py +122 -0
  40. roadmap/adapters/cli/git/handlers/git_hooks_handler.py +105 -0
  41. roadmap/adapters/cli/git/hooks_config.py +327 -0
  42. roadmap/adapters/cli/git/status_display.py +158 -0
  43. roadmap/adapters/cli/health/__init__.py +8 -0
  44. roadmap/adapters/cli/health/db_integrity.py +204 -0
  45. roadmap/adapters/cli/health/enhancer.py +227 -0
  46. roadmap/adapters/cli/health/fixer.py +295 -0
  47. roadmap/adapters/cli/health/fixers/__init__.py +10 -0
  48. roadmap/adapters/cli/health/fixers/corrupted_comments_fixer.py +231 -0
  49. roadmap/adapters/cli/health/fixers/data_integrity_fixer.py +137 -0
  50. roadmap/adapters/cli/health/fixers/duplicate_issues_fixer.py +138 -0
  51. roadmap/adapters/cli/health/fixers/folder_structure_fixer.py +114 -0
  52. roadmap/adapters/cli/health/fixers/label_normalization_fixer.py +162 -0
  53. roadmap/adapters/cli/health/fixers/milestone_name_normalization_fixer.py +181 -0
  54. roadmap/adapters/cli/health/fixers/milestone_naming_compliance_fixer.py +244 -0
  55. roadmap/adapters/cli/health/fixers/milestone_parse_error_fixer.py +162 -0
  56. roadmap/adapters/cli/health/fixers/milestone_validation_fixer.py +211 -0
  57. roadmap/adapters/cli/health/fixers/old_backups_fixer.py +135 -0
  58. roadmap/adapters/cli/health/fixers/orphaned_issues_fixer.py +252 -0
  59. roadmap/adapters/cli/health/formatter.py +250 -0
  60. roadmap/adapters/cli/health/formatters.py +427 -0
  61. roadmap/adapters/cli/health/scan.py +293 -0
  62. roadmap/adapters/cli/init/__init__.py +5 -0
  63. roadmap/adapters/cli/init/commands.py +587 -0
  64. roadmap/adapters/cli/init.py +9 -0
  65. roadmap/adapters/cli/issues/__init__.py +70 -0
  66. roadmap/adapters/cli/issues/archive.py +137 -0
  67. roadmap/adapters/cli/issues/archive_class.py +253 -0
  68. roadmap/adapters/cli/issues/block.py +39 -0
  69. roadmap/adapters/cli/issues/close.py +216 -0
  70. roadmap/adapters/cli/issues/comment.py +178 -0
  71. roadmap/adapters/cli/issues/create.py +162 -0
  72. roadmap/adapters/cli/issues/delete.py +31 -0
  73. roadmap/adapters/cli/issues/deps.py +161 -0
  74. roadmap/adapters/cli/issues/issue_status_helpers.py +111 -0
  75. roadmap/adapters/cli/issues/link.py +308 -0
  76. roadmap/adapters/cli/issues/list.py +402 -0
  77. roadmap/adapters/cli/issues/lookup.py +96 -0
  78. roadmap/adapters/cli/issues/progress.py +102 -0
  79. roadmap/adapters/cli/issues/restore.py +96 -0
  80. roadmap/adapters/cli/issues/restore_class.py +57 -0
  81. roadmap/adapters/cli/issues/start.py +165 -0
  82. roadmap/adapters/cli/issues/sync_status.py +374 -0
  83. roadmap/adapters/cli/issues/unblock.py +43 -0
  84. roadmap/adapters/cli/issues/unlink.py +104 -0
  85. roadmap/adapters/cli/issues/update.py +120 -0
  86. roadmap/adapters/cli/issues/view.py +36 -0
  87. roadmap/adapters/cli/layout.py +220 -0
  88. roadmap/adapters/cli/mappers.py +200 -0
  89. roadmap/adapters/cli/milestones/__init__.py +52 -0
  90. roadmap/adapters/cli/milestones/archive.py +125 -0
  91. roadmap/adapters/cli/milestones/archive_class.py +236 -0
  92. roadmap/adapters/cli/milestones/assign.py +62 -0
  93. roadmap/adapters/cli/milestones/close.py +177 -0
  94. roadmap/adapters/cli/milestones/create.py +131 -0
  95. roadmap/adapters/cli/milestones/delete.py +27 -0
  96. roadmap/adapters/cli/milestones/kanban.py +123 -0
  97. roadmap/adapters/cli/milestones/list.py +87 -0
  98. roadmap/adapters/cli/milestones/recalculate.py +79 -0
  99. roadmap/adapters/cli/milestones/restore.py +87 -0
  100. roadmap/adapters/cli/milestones/restore_class.py +99 -0
  101. roadmap/adapters/cli/milestones/update.py +61 -0
  102. roadmap/adapters/cli/milestones/view.py +142 -0
  103. roadmap/adapters/cli/output_manager.py +319 -0
  104. roadmap/adapters/cli/presentation/base_presenter.py +121 -0
  105. roadmap/adapters/cli/presentation/cleanup_presenter.py +235 -0
  106. roadmap/adapters/cli/presentation/core_initialization_presenter.py +277 -0
  107. roadmap/adapters/cli/presentation/crud_presenter.py +134 -0
  108. roadmap/adapters/cli/presentation/daily_summary_presenter.py +266 -0
  109. roadmap/adapters/cli/presentation/issue_presenter.py +258 -0
  110. roadmap/adapters/cli/presentation/milestone_list_presenter.py +135 -0
  111. roadmap/adapters/cli/presentation/milestone_presenter.py +297 -0
  112. roadmap/adapters/cli/presentation/project_presenter.py +233 -0
  113. roadmap/adapters/cli/presentation/project_status_presenter.py +186 -0
  114. roadmap/adapters/cli/presentation/table_builders.py +95 -0
  115. roadmap/adapters/cli/projects/__init__.py +42 -0
  116. roadmap/adapters/cli/projects/archive.py +127 -0
  117. roadmap/adapters/cli/projects/archive_class.py +96 -0
  118. roadmap/adapters/cli/projects/close.py +94 -0
  119. roadmap/adapters/cli/projects/create.py +50 -0
  120. roadmap/adapters/cli/projects/delete.py +27 -0
  121. roadmap/adapters/cli/projects/list.py +227 -0
  122. roadmap/adapters/cli/projects/restore.py +87 -0
  123. roadmap/adapters/cli/projects/restore_class.py +56 -0
  124. roadmap/adapters/cli/projects/update.py +57 -0
  125. roadmap/adapters/cli/projects/view.py +157 -0
  126. roadmap/adapters/cli/services/__init__.py +1 -0
  127. roadmap/adapters/cli/services/daily_summary_service.py +313 -0
  128. roadmap/adapters/cli/services/export_manager.py +268 -0
  129. roadmap/adapters/cli/services/milestone_list_service.py +266 -0
  130. roadmap/adapters/cli/services/project_initialization_service.py +29 -0
  131. roadmap/adapters/cli/services/project_status_service.py +462 -0
  132. roadmap/adapters/cli/services/sync_service.py +62 -0
  133. roadmap/adapters/cli/status.py +408 -0
  134. roadmap/adapters/cli/styling.py +21 -0
  135. roadmap/adapters/cli/sync.py +1117 -0
  136. roadmap/adapters/cli/sync_context.py +432 -0
  137. roadmap/adapters/cli/sync_handlers/__init__.py +77 -0
  138. roadmap/adapters/cli/sync_handlers/apply_ops.py +522 -0
  139. roadmap/adapters/cli/sync_handlers/baseline_ops.py +366 -0
  140. roadmap/adapters/cli/sync_handlers/conflict_ops.py +161 -0
  141. roadmap/adapters/cli/sync_handlers/dry_run_display.py +237 -0
  142. roadmap/adapters/cli/sync_handlers/interactive_resolver.py +396 -0
  143. roadmap/adapters/cli/sync_handlers/progress_tracker.py +128 -0
  144. roadmap/adapters/cli/sync_metrics_command.py +190 -0
  145. roadmap/adapters/cli/sync_presenter.py +58 -0
  146. roadmap/adapters/cli/sync_validation.py +295 -0
  147. roadmap/adapters/cli/today.py +52 -0
  148. roadmap/adapters/cli/utils/click_options.py +38 -0
  149. roadmap/adapters/git/__init__.py +1 -0
  150. roadmap/adapters/git/git.py +208 -0
  151. roadmap/adapters/git/git_branch_manager.py +400 -0
  152. roadmap/adapters/git/git_command_executor.py +56 -0
  153. roadmap/adapters/git/git_commit_analyzer.py +334 -0
  154. roadmap/adapters/git/git_hooks.py +22 -0
  155. roadmap/adapters/git/git_hooks_manager.py +455 -0
  156. roadmap/adapters/git/git_repository_info.py +65 -0
  157. roadmap/adapters/git/hook_installer.py +106 -0
  158. roadmap/adapters/git/hook_registry.py +97 -0
  159. roadmap/adapters/git/hook_script_generator.py +58 -0
  160. roadmap/adapters/git/sync_monitor.py +409 -0
  161. roadmap/adapters/git/workflow_automation.py +286 -0
  162. roadmap/adapters/github/__init__.py +1 -0
  163. roadmap/adapters/github/github.py +360 -0
  164. roadmap/adapters/github/handlers/__init__.py +17 -0
  165. roadmap/adapters/github/handlers/base.py +337 -0
  166. roadmap/adapters/github/handlers/collaborators.py +165 -0
  167. roadmap/adapters/github/handlers/comments.py +118 -0
  168. roadmap/adapters/github/handlers/issues.py +150 -0
  169. roadmap/adapters/github/handlers/labels.py +164 -0
  170. roadmap/adapters/github/handlers/milestones.py +104 -0
  171. roadmap/adapters/persistence/__init__.py +35 -0
  172. roadmap/adapters/persistence/conflict_resolver.py +190 -0
  173. roadmap/adapters/persistence/database_manager.py +492 -0
  174. roadmap/adapters/persistence/entity_sync_coordinators.py +672 -0
  175. roadmap/adapters/persistence/file_locking.py +348 -0
  176. roadmap/adapters/persistence/file_parser.py +92 -0
  177. roadmap/adapters/persistence/file_synchronizer.py +107 -0
  178. roadmap/adapters/persistence/focused_managers.py +140 -0
  179. roadmap/adapters/persistence/git_history.py +330 -0
  180. roadmap/adapters/persistence/parser/__init__.py +20 -0
  181. roadmap/adapters/persistence/parser/frontmatter.py +152 -0
  182. roadmap/adapters/persistence/parser/issue.py +245 -0
  183. roadmap/adapters/persistence/parser/milestone.py +146 -0
  184. roadmap/adapters/persistence/parser/project.py +106 -0
  185. roadmap/adapters/persistence/persistence.py +288 -0
  186. roadmap/adapters/persistence/repositories/__init__.py +15 -0
  187. roadmap/adapters/persistence/repositories/issue_repository.py +223 -0
  188. roadmap/adapters/persistence/repositories/milestone_repository.py +140 -0
  189. roadmap/adapters/persistence/repositories/project_repository.py +168 -0
  190. roadmap/adapters/persistence/repositories/remote_link_repository.py +355 -0
  191. roadmap/adapters/persistence/repositories/sync_state_repository.py +66 -0
  192. roadmap/adapters/persistence/storage/__init__.py +36 -0
  193. roadmap/adapters/persistence/storage/conflicts.py +101 -0
  194. roadmap/adapters/persistence/storage/connection_manager.py +79 -0
  195. roadmap/adapters/persistence/storage/issue_storage.py +89 -0
  196. roadmap/adapters/persistence/storage/milestone_storage.py +80 -0
  197. roadmap/adapters/persistence/storage/project_storage.py +102 -0
  198. roadmap/adapters/persistence/storage/queries.py +227 -0
  199. roadmap/adapters/persistence/storage/state_manager.py +652 -0
  200. roadmap/adapters/persistence/storage/sync_state_storage.py +207 -0
  201. roadmap/adapters/persistence/sync_metrics_repository.py +342 -0
  202. roadmap/adapters/persistence/sync_orchestrator.py +293 -0
  203. roadmap/adapters/persistence/sync_state_tracker.py +86 -0
  204. roadmap/adapters/persistence/yaml_repositories.py +711 -0
  205. roadmap/adapters/sync/__init__.py +21 -0
  206. roadmap/adapters/sync/backend_factory.py +108 -0
  207. roadmap/adapters/sync/backends/__init__.py +15 -0
  208. roadmap/adapters/sync/backends/converters.py +209 -0
  209. roadmap/adapters/sync/backends/github_backend_helpers.py +380 -0
  210. roadmap/adapters/sync/backends/github_client.py +99 -0
  211. roadmap/adapters/sync/backends/github_sync_backend.py +792 -0
  212. roadmap/adapters/sync/backends/github_sync_ops.py +908 -0
  213. roadmap/adapters/sync/backends/services/__init__.py +1 -0
  214. roadmap/adapters/sync/backends/services/github_authentication_service.py +105 -0
  215. roadmap/adapters/sync/backends/services/github_issue_delete_service.py +423 -0
  216. roadmap/adapters/sync/backends/services/github_issue_dependency_service.py +63 -0
  217. roadmap/adapters/sync/backends/services/github_issue_fetch_service.py +158 -0
  218. roadmap/adapters/sync/backends/services/github_label_sync_service.py +126 -0
  219. roadmap/adapters/sync/backends/services/github_local_issue_sync_service.py +229 -0
  220. roadmap/adapters/sync/backends/services/github_milestone_fetch_service.py +204 -0
  221. roadmap/adapters/sync/backends/vanilla_git_sync_backend.py +198 -0
  222. roadmap/adapters/sync/services/__init__.py +11 -0
  223. roadmap/adapters/sync/services/baseline_state_handler.py +83 -0
  224. roadmap/adapters/sync/services/conflict_converter.py +85 -0
  225. roadmap/adapters/sync/services/issue_persistence_service.py +263 -0
  226. roadmap/adapters/sync/services/issue_state_service.py +243 -0
  227. roadmap/adapters/sync/services/local_change_filter.py +129 -0
  228. roadmap/adapters/sync/services/pull_result_processor.py +71 -0
  229. roadmap/adapters/sync/services/remote_issue_creation_service.py +112 -0
  230. roadmap/adapters/sync/services/sync_analysis_service.py +250 -0
  231. roadmap/adapters/sync/services/sync_authentication_service.py +57 -0
  232. roadmap/adapters/sync/services/sync_data_fetch_service.py +212 -0
  233. roadmap/adapters/sync/services/sync_linking_service.py +329 -0
  234. roadmap/adapters/sync/services/sync_report_service.py +62 -0
  235. roadmap/adapters/sync/services/sync_state_update_service.py +51 -0
  236. roadmap/adapters/sync/sync_cache_orchestrator.py +454 -0
  237. roadmap/adapters/sync/sync_merge_engine.py +416 -0
  238. roadmap/adapters/sync/sync_merge_orchestrator.py +1313 -0
  239. roadmap/adapters/sync/sync_retrieval_orchestrator.py +810 -0
  240. roadmap/application/services/__init__.py +1 -0
  241. roadmap/application/services/deduplicate_service.py +517 -0
  242. roadmap/application/use_cases/__init__.py +1 -0
  243. roadmap/common/__init__.py +308 -0
  244. roadmap/common/cache.py +209 -0
  245. roadmap/common/cli_errors.py +147 -0
  246. roadmap/common/configuration/__init__.py +33 -0
  247. roadmap/common/configuration/config_loader.py +264 -0
  248. roadmap/common/configuration/config_manager.py +164 -0
  249. roadmap/common/configuration/config_schema.py +145 -0
  250. roadmap/common/configuration/github/__init__.py +9 -0
  251. roadmap/common/configuration/github/config_manager.py +154 -0
  252. roadmap/common/configuration/github/token_resolver.py +84 -0
  253. roadmap/common/console.py +184 -0
  254. roadmap/common/constants.py +134 -0
  255. roadmap/common/datetime_parser.py +319 -0
  256. roadmap/common/error_formatter.py +84 -0
  257. roadmap/common/errors/__init__.py +143 -0
  258. roadmap/common/errors/error_base.py +73 -0
  259. roadmap/common/errors/error_file.py +82 -0
  260. roadmap/common/errors/error_git.py +67 -0
  261. roadmap/common/errors/error_handler.py +166 -0
  262. roadmap/common/errors/error_network.py +90 -0
  263. roadmap/common/errors/error_security.py +78 -0
  264. roadmap/common/errors/error_standards.py +561 -0
  265. roadmap/common/errors/error_validation.py +111 -0
  266. roadmap/common/errors/exceptions.py +432 -0
  267. roadmap/common/formatters/__init__.py +29 -0
  268. roadmap/common/formatters/base_table_formatter.py +96 -0
  269. roadmap/common/formatters/export/__init__.py +7 -0
  270. roadmap/common/formatters/export/issue_exporter.py +97 -0
  271. roadmap/common/formatters/helpers.py +28 -0
  272. roadmap/common/formatters/kanban/__init__.py +9 -0
  273. roadmap/common/formatters/kanban/layout.py +48 -0
  274. roadmap/common/formatters/kanban/organizer.py +81 -0
  275. roadmap/common/formatters/output/__init__.py +15 -0
  276. roadmap/common/formatters/tables/__init__.py +11 -0
  277. roadmap/common/formatters/tables/column_factory.py +312 -0
  278. roadmap/common/formatters/tables/issue_table.py +276 -0
  279. roadmap/common/formatters/tables/milestone_table.py +247 -0
  280. roadmap/common/formatters/tables/project_table.py +195 -0
  281. roadmap/common/formatters/text/__init__.py +57 -0
  282. roadmap/common/formatters/text/basic.py +217 -0
  283. roadmap/common/formatters/text/display.py +42 -0
  284. roadmap/common/formatters/text/duration.py +36 -0
  285. roadmap/common/formatters/text/operations.py +325 -0
  286. roadmap/common/formatters/text/status_badges.py +57 -0
  287. roadmap/common/initialization/github/__init__.py +11 -0
  288. roadmap/common/initialization/github/setup_service.py +238 -0
  289. roadmap/common/initialization/github/setup_validator.py +78 -0
  290. roadmap/common/logging/__init__.py +113 -0
  291. roadmap/common/logging/audit_logging.py +5 -0
  292. roadmap/common/logging/correlation.py +45 -0
  293. roadmap/common/logging/decorators.py +267 -0
  294. roadmap/common/logging/error_logging.py +217 -0
  295. roadmap/common/logging/formatters.py +124 -0
  296. roadmap/common/logging/loggers.py +68 -0
  297. roadmap/common/logging/performance_tracking.py +267 -0
  298. roadmap/common/logging/utils.py +335 -0
  299. roadmap/common/models/__init__.py +44 -0
  300. roadmap/common/models/cli_models.py +118 -0
  301. roadmap/common/models/config_models.py +199 -0
  302. roadmap/common/models/output_models.py +381 -0
  303. roadmap/common/observability/__init__.py +28 -0
  304. roadmap/common/observability/instrumentation.py +103 -0
  305. roadmap/common/observability/observability.py +76 -0
  306. roadmap/common/observability/otel_init.py +109 -0
  307. roadmap/common/output_formatter.py +393 -0
  308. roadmap/common/progress.py +379 -0
  309. roadmap/common/result.py +396 -0
  310. roadmap/common/security/__init__.py +48 -0
  311. roadmap/common/security/exceptions.py +13 -0
  312. roadmap/common/security/export_cleanup.py +79 -0
  313. roadmap/common/security/file_operations.py +104 -0
  314. roadmap/common/security/filename_sanitization.py +54 -0
  315. roadmap/common/security/logging.py +27 -0
  316. roadmap/common/security/path_validation.py +137 -0
  317. roadmap/common/security/temp_files.py +41 -0
  318. roadmap/common/services/__init__.py +65 -0
  319. roadmap/common/services/decorators.py +183 -0
  320. roadmap/common/services/logging_utils.py +208 -0
  321. roadmap/common/services/metrics.py +161 -0
  322. roadmap/common/services/performance.py +219 -0
  323. roadmap/common/services/profiling.py +288 -0
  324. roadmap/common/services/retry.py +288 -0
  325. roadmap/common/status_style_manager.py +114 -0
  326. roadmap/common/union_find.py +88 -0
  327. roadmap/common/update_constants.py +13 -0
  328. roadmap/common/utils/__init__.py +65 -0
  329. roadmap/common/utils/cli_helpers.py +381 -0
  330. roadmap/common/utils/file_utils.py +440 -0
  331. roadmap/common/utils/path_utils.py +38 -0
  332. roadmap/common/utils/status_utils.py +130 -0
  333. roadmap/common/utils/timezone_utils.py +480 -0
  334. roadmap/common/validation/__init__.py +37 -0
  335. roadmap/common/validation/field_validator.py +104 -0
  336. roadmap/common/validation/result.py +37 -0
  337. roadmap/common/validation/roadmap_validator.py +310 -0
  338. roadmap/common/validation/schema_validator.py +36 -0
  339. roadmap/common/validation/validators.py +50 -0
  340. roadmap/core/__init__.py +1 -0
  341. roadmap/core/domain/__init__.py +30 -0
  342. roadmap/core/domain/comment.py +24 -0
  343. roadmap/core/domain/health.py +15 -0
  344. roadmap/core/domain/issue.py +274 -0
  345. roadmap/core/domain/milestone.py +173 -0
  346. roadmap/core/domain/ports/__init__.py +1 -0
  347. roadmap/core/domain/ports/baseline_repository.py +24 -0
  348. roadmap/core/domain/ports/issue_repository.py +34 -0
  349. roadmap/core/domain/ports/remote_backend_port.py +31 -0
  350. roadmap/core/domain/project.py +130 -0
  351. roadmap/core/interfaces/__init__.py +109 -0
  352. roadmap/core/interfaces/assignee_validator.py +40 -0
  353. roadmap/core/interfaces/backend_factory.py +175 -0
  354. roadmap/core/interfaces/github.py +102 -0
  355. roadmap/core/interfaces/parsers.py +140 -0
  356. roadmap/core/interfaces/persistence.py +45 -0
  357. roadmap/core/interfaces/repositories.py +174 -0
  358. roadmap/core/interfaces/state_managers.py +111 -0
  359. roadmap/core/interfaces/state_storage.py +64 -0
  360. roadmap/core/interfaces/sync_backend.py +275 -0
  361. roadmap/core/interfaces/sync_services.py +119 -0
  362. roadmap/core/interfaces/sync_validators.py +180 -0
  363. roadmap/core/models/__init__.py +31 -0
  364. roadmap/core/models/sync_models.py +162 -0
  365. roadmap/core/models.py +115 -0
  366. roadmap/core/observability/__init__.py +17 -0
  367. roadmap/core/observability/sync_metrics.py +699 -0
  368. roadmap/core/repositories.py +200 -0
  369. roadmap/core/services/__init__.py +313 -0
  370. roadmap/core/services/baseline/__init__.py +1 -0
  371. roadmap/core/services/baseline/baseline_builder_progress.py +274 -0
  372. roadmap/core/services/baseline/baseline_retriever.py +63 -0
  373. roadmap/core/services/baseline/baseline_selector.py +248 -0
  374. roadmap/core/services/baseline/baseline_state_retriever.py +284 -0
  375. roadmap/core/services/baseline/optimized_baseline_builder.py +425 -0
  376. roadmap/core/services/comment/__init__.py +1 -0
  377. roadmap/core/services/comment/comment_service.py +277 -0
  378. roadmap/core/services/git/__init__.py +1 -0
  379. roadmap/core/services/git/git_hook_auto_sync_service.py +403 -0
  380. roadmap/core/services/github/__init__.py +1 -0
  381. roadmap/core/services/github/github_change_detector.py +162 -0
  382. roadmap/core/services/github/github_config_validator.py +148 -0
  383. roadmap/core/services/github/github_conflict_detector.py +179 -0
  384. roadmap/core/services/github/github_entity_classifier.py +51 -0
  385. roadmap/core/services/github/github_integration_service.py +439 -0
  386. roadmap/core/services/github/github_issue_client.py +346 -0
  387. roadmap/core/services/health/__init__.py +1 -0
  388. roadmap/core/services/health/backup_cleanup_service.py +202 -0
  389. roadmap/core/services/health/data_integrity_validator_service.py +90 -0
  390. roadmap/core/services/health/entity_health_scanner.py +460 -0
  391. roadmap/core/services/health/file_repair_service.py +193 -0
  392. roadmap/core/services/health/health_check_service.py +166 -0
  393. roadmap/core/services/health/health_models.py +80 -0
  394. roadmap/core/services/health/infrastructure_validator_service.py +328 -0
  395. roadmap/core/services/health/issue_health_scanner.py +263 -0
  396. roadmap/core/services/helpers/__init__.py +18 -0
  397. roadmap/core/services/helpers/status_change_helpers.py +88 -0
  398. roadmap/core/services/initialization/__init__.py +19 -0
  399. roadmap/core/services/initialization/utils.py +104 -0
  400. roadmap/core/services/initialization/validator.py +78 -0
  401. roadmap/core/services/initialization/workflow.py +182 -0
  402. roadmap/core/services/initialization_service.py +111 -0
  403. roadmap/core/services/issue/__init__.py +1 -0
  404. roadmap/core/services/issue/assignee_validation_service.py +312 -0
  405. roadmap/core/services/issue/issue_creation_service.py +309 -0
  406. roadmap/core/services/issue/issue_filter_service.py +302 -0
  407. roadmap/core/services/issue/issue_matching_service.py +127 -0
  408. roadmap/core/services/issue/issue_service.py +765 -0
  409. roadmap/core/services/issue/issue_update_service.py +144 -0
  410. roadmap/core/services/issue/start_issue_service.py +174 -0
  411. roadmap/core/services/issue_helpers/__init__.py +18 -0
  412. roadmap/core/services/issue_helpers/issue_filters.py +296 -0
  413. roadmap/core/services/milestone_service.py +438 -0
  414. roadmap/core/services/project/__init__.py +1 -0
  415. roadmap/core/services/project/project_service.py +434 -0
  416. roadmap/core/services/project/project_status_service.py +125 -0
  417. roadmap/core/services/project_init/__init__.py +22 -0
  418. roadmap/core/services/project_init/context_detection.py +146 -0
  419. roadmap/core/services/project_init/creation.py +76 -0
  420. roadmap/core/services/project_init/detection.py +51 -0
  421. roadmap/core/services/project_init/template.py +228 -0
  422. roadmap/core/services/status_change_service.py +88 -0
  423. roadmap/core/services/sync/__init__.py +1 -0
  424. roadmap/core/services/sync/batch_processor.py +290 -0
  425. roadmap/core/services/sync/conflict_resolver.py +154 -0
  426. roadmap/core/services/sync/dependency_resolver.py +367 -0
  427. roadmap/core/services/sync/duplicate_detector.py +771 -0
  428. roadmap/core/services/sync/duplicate_resolver.py +315 -0
  429. roadmap/core/services/sync/error_classification.py +470 -0
  430. roadmap/core/services/sync/performance.py +263 -0
  431. roadmap/core/services/sync/sync_change_computer.py +211 -0
  432. roadmap/core/services/sync/sync_checkpoint.py +348 -0
  433. roadmap/core/services/sync/sync_conflict_detector.py +147 -0
  434. roadmap/core/services/sync/sync_conflict_resolver.py +448 -0
  435. roadmap/core/services/sync/sync_errors.py +383 -0
  436. roadmap/core/services/sync/sync_key_normalizer.py +222 -0
  437. roadmap/core/services/sync/sync_metadata_service.py +361 -0
  438. roadmap/core/services/sync/sync_plan.py +171 -0
  439. roadmap/core/services/sync/sync_plan_executor.py +447 -0
  440. roadmap/core/services/sync/sync_report.py +296 -0
  441. roadmap/core/services/sync/sync_state.py +173 -0
  442. roadmap/core/services/sync/sync_state_comparator.py +690 -0
  443. roadmap/core/services/sync/sync_state_manager.py +431 -0
  444. roadmap/core/services/sync/sync_state_normalizer.py +98 -0
  445. roadmap/core/services/sync/sync_three_way.py +78 -0
  446. roadmap/core/services/sync/three_way_merger.py +178 -0
  447. roadmap/core/services/utils/__init__.py +1 -0
  448. roadmap/core/services/utils/configuration_service.py +113 -0
  449. roadmap/core/services/utils/critical_path_calculator.py +418 -0
  450. roadmap/core/services/utils/dependency_analyzer.py +360 -0
  451. roadmap/core/services/utils/field_conflict_detector.py +126 -0
  452. roadmap/core/services/utils/remote_fetcher.py +202 -0
  453. roadmap/core/services/utils/remote_state_normalizer.py +110 -0
  454. roadmap/core/services/utils/retry_policy.py +51 -0
  455. roadmap/core/services/validator_base.py +130 -0
  456. roadmap/core/services/validators/__init__.py +28 -0
  457. roadmap/core/services/validators/_utils.py +20 -0
  458. roadmap/core/services/validators/archivable_issues_validator.py +71 -0
  459. roadmap/core/services/validators/archivable_milestones_validator.py +69 -0
  460. roadmap/core/services/validators/backup_validator.py +89 -0
  461. roadmap/core/services/validators/data_integrity_validator.py +84 -0
  462. roadmap/core/services/validators/duplicate_issues_validator.py +75 -0
  463. roadmap/core/services/validators/duplicate_milestones_validator.py +141 -0
  464. roadmap/core/services/validators/folder_structure_validator.py +165 -0
  465. roadmap/core/services/validators/health_status_utils.py +28 -0
  466. roadmap/core/services/validators/milestone_naming_validator.py +146 -0
  467. roadmap/core/services/validators/missing_headlines_validator.py +97 -0
  468. roadmap/core/services/validators/orphaned_issues_validator.py +142 -0
  469. roadmap/core/services/validators/orphaned_milestones_validator.py +85 -0
  470. roadmap/core/utils/git_remote_parser.py +83 -0
  471. roadmap/core/utils/github_urls.py +66 -0
  472. roadmap/domain/validation.py +30 -0
  473. roadmap/infrastructure/__init__.py +55 -0
  474. roadmap/infrastructure/coordination/__init__.py +8 -0
  475. roadmap/infrastructure/coordination/coordinator_params.py +82 -0
  476. roadmap/infrastructure/coordination/core.py +446 -0
  477. roadmap/infrastructure/coordination/git_coordinator.py +160 -0
  478. roadmap/infrastructure/coordination/initialization.py +348 -0
  479. roadmap/infrastructure/coordination/issue_coordinator.py +154 -0
  480. roadmap/infrastructure/coordination/issue_operations.py +456 -0
  481. roadmap/infrastructure/coordination/milestone_coordinator.py +135 -0
  482. roadmap/infrastructure/coordination/milestone_operations.py +201 -0
  483. roadmap/infrastructure/coordination/project_coordinator.py +113 -0
  484. roadmap/infrastructure/coordination/project_operations.py +144 -0
  485. roadmap/infrastructure/coordination/team_coordinator.py +107 -0
  486. roadmap/infrastructure/coordination/user_operations.py +150 -0
  487. roadmap/infrastructure/coordination/validation_coordinator.py +249 -0
  488. roadmap/infrastructure/coordination_gateway.py +152 -0
  489. roadmap/infrastructure/git/__init__.py +6 -0
  490. roadmap/infrastructure/git/git_integration_ops.py +234 -0
  491. roadmap/infrastructure/git_gateway.py +35 -0
  492. roadmap/infrastructure/github_gateway.py +52 -0
  493. roadmap/infrastructure/maintenance/__init__.py +5 -0
  494. roadmap/infrastructure/maintenance/cleanup.py +483 -0
  495. roadmap/infrastructure/observability/__init__.py +7 -0
  496. roadmap/infrastructure/observability/health.py +196 -0
  497. roadmap/infrastructure/observability/health_formatter.py +73 -0
  498. roadmap/infrastructure/observability/specialized_health_checkers.py +188 -0
  499. roadmap/infrastructure/persistence_gateway.py +164 -0
  500. roadmap/infrastructure/security/__init__.py +1 -0
  501. roadmap/infrastructure/security/credentials.py +489 -0
  502. roadmap/infrastructure/sync_gateway.py +94 -0
  503. roadmap/infrastructure/validation/__init__.py +7 -0
  504. roadmap/infrastructure/validation/file_enumeration.py +219 -0
  505. roadmap/infrastructure/validation/github_assignee_validator.py +47 -0
  506. roadmap/infrastructure/validation/github_validator.py +101 -0
  507. roadmap/infrastructure/validation/milestone_consistency_validator.py +96 -0
  508. roadmap/infrastructure/validation/vanilla_assignee_validator.py +37 -0
  509. roadmap/infrastructure/validation_gateway.py +96 -0
  510. roadmap/presentation/formatters/sync_metrics_formatter.py +355 -0
  511. roadmap/settings.py +345 -0
  512. roadmap/templates/github_workflows/ci-cd-roadmap.yml +241 -0
  513. roadmap/templates/github_workflows/issue-lifecycle.yml +236 -0
  514. roadmap/templates/github_workflows/roadmap-integration.yml +137 -0
  515. roadmap/templates/github_workflows/roadmap-starter.yml +59 -0
  516. roadmap/version.py +381 -0
  517. roadmap_cli-0.1.1.dist-info/METADATA +448 -0
  518. roadmap_cli-0.1.1.dist-info/RECORD +521 -0
  519. roadmap_cli-0.1.1.dist-info/WHEEL +4 -0
  520. roadmap_cli-0.1.1.dist-info/entry_points.txt +2 -0
  521. roadmap_cli-0.1.1.dist-info/licenses/LICENSE.md +21 -0
@@ -0,0 +1,220 @@
1
+ """Smart table layout system with responsive formatting.
2
+
3
+ Automatically detects terminal width and switches to vertical layout
4
+ when horizontal table is too wide.
5
+ """
6
+
7
+ import shutil
8
+ from dataclasses import dataclass
9
+
10
+ from rich.console import Console
11
+ from rich.panel import Panel
12
+ from rich.table import Table
13
+
14
+ from roadmap.common.models import TableData
15
+
16
+
17
+ @dataclass
18
+ class LayoutConfig:
19
+ """Configuration for smart table layouts."""
20
+
21
+ min_column_width: int = 15
22
+ max_horizontal_width: int = 120
23
+ vertical_threshold: float = (
24
+ 0.8 # Switch to vertical if table > 80% of terminal width
25
+ )
26
+ responsive_enabled: bool = True
27
+
28
+
29
+ class SmartTableLayout:
30
+ """Renders tables with responsive layout based on terminal width."""
31
+
32
+ def __init__(self, config: LayoutConfig | None = None):
33
+ """Initialize layout system.
34
+
35
+ Args:
36
+ config: Layout configuration
37
+ """
38
+ self.config = config or LayoutConfig()
39
+
40
+ def get_terminal_width(self) -> int:
41
+ """Get terminal width in columns.
42
+
43
+ Returns:
44
+ Terminal width, defaults to 80 if unable to detect
45
+ """
46
+ try:
47
+ width = shutil.get_terminal_size().columns
48
+ return max(width, 40) # Minimum 40 columns
49
+ except Exception as e:
50
+ from roadmap.common.logging import get_logger
51
+
52
+ logger = get_logger(__name__)
53
+ logger.debug(
54
+ "terminal_width_detection_failed",
55
+ error=str(e),
56
+ action="get_terminal_width",
57
+ )
58
+ return 80 # Default fallback
59
+
60
+ def calculate_table_width(self, table_data: TableData) -> int:
61
+ """Calculate estimated table width based on column headers and data.
62
+
63
+ Args:
64
+ table_data: Table data to measure
65
+
66
+ Returns:
67
+ Estimated table width in columns
68
+ """
69
+ if not table_data.columns or not table_data.rows:
70
+ return 20
71
+
72
+ # Estimate based on column headers and sample data
73
+ total_width = 0
74
+ max_samples = min(5, len(table_data.rows))
75
+
76
+ for i, column in enumerate(table_data.columns):
77
+ # Start with header width
78
+ col_width = len(column.display_name) + 2
79
+
80
+ # Check sample data for this column
81
+ for row_idx in range(max_samples):
82
+ if row_idx < len(table_data.rows) and i < len(table_data.rows[row_idx]):
83
+ value = table_data.rows[row_idx][i]
84
+ col_width = max(col_width, len(str(value)))
85
+
86
+ # Add padding and separators
87
+ col_width = min(col_width + 2, 30) # Cap at 30 per column
88
+ total_width += col_width
89
+
90
+ # Add separators and padding
91
+ total_width += len(table_data.columns) + 4
92
+
93
+ return total_width
94
+
95
+ def should_use_vertical_layout(self, table_data: TableData) -> bool:
96
+ """Determine if vertical layout should be used.
97
+
98
+ Args:
99
+ table_data: Table data to evaluate
100
+
101
+ Returns:
102
+ True if vertical layout is recommended
103
+ """
104
+ if not self.config.responsive_enabled:
105
+ return False
106
+
107
+ terminal_width = self.get_terminal_width()
108
+ table_width = self.calculate_table_width(table_data)
109
+
110
+ # Use vertical if table would take > threshold of terminal width
111
+ return table_width > (terminal_width * self.config.vertical_threshold)
112
+
113
+ def render_horizontal(self, table_data: TableData) -> Table:
114
+ """Render table in horizontal layout.
115
+
116
+ Args:
117
+ table_data: Table data to render
118
+
119
+ Returns:
120
+ Rich Table object
121
+ """
122
+ table = Table(
123
+ title=table_data.title,
124
+ show_header=True,
125
+ header_style="bold cyan",
126
+ )
127
+
128
+ # Add columns
129
+ for column in table_data.columns:
130
+ table.add_column(column.display_name, style=column.display_style or "")
131
+
132
+ # Add rows
133
+ for row in table_data.rows:
134
+ values = [str(val) if val is not None else "" for val in row]
135
+ table.add_row(*values)
136
+
137
+ return table
138
+
139
+ def render_vertical(self, table_data: TableData) -> Panel:
140
+ """Render table in vertical layout (one field per line).
141
+
142
+ Args:
143
+ table_data: Table data to render
144
+
145
+ Returns:
146
+ Rich Panel with vertical layout
147
+ """
148
+ from rich.text import Text
149
+
150
+ panels_content = []
151
+
152
+ for row_idx, row in enumerate(table_data.rows):
153
+ # Create header for this row
154
+ row_header = f"Entry {row_idx + 1}"
155
+
156
+ # Build content for this row
157
+ row_text = Text()
158
+ row_text.append(row_header + "\n", style="bold cyan")
159
+
160
+ for col_idx, column in enumerate(table_data.columns):
161
+ value = row[col_idx] if col_idx < len(row) else ""
162
+ row_text.append(f" {column.display_name}: ", style="bold")
163
+ row_text.append(f"{value}\n")
164
+
165
+ panels_content.append(row_text)
166
+
167
+ # Combine all panels
168
+ combined = Text()
169
+ for i, text in enumerate(panels_content):
170
+ combined.append(text)
171
+ if i < len(panels_content) - 1:
172
+ combined.append("\n" + "─" * 40 + "\n\n")
173
+
174
+ return Panel(
175
+ combined,
176
+ title=table_data.title,
177
+ expand=False,
178
+ )
179
+
180
+ def render(self, table_data: TableData) -> Table | Panel:
181
+ """Render table with appropriate layout based on terminal width.
182
+
183
+ Args:
184
+ table_data: Table data to render
185
+
186
+ Returns:
187
+ Rich Table or Panel object
188
+ """
189
+ if self.should_use_vertical_layout(table_data):
190
+ return self.render_vertical(table_data)
191
+ else:
192
+ return self.render_horizontal(table_data)
193
+
194
+ def render_as_string(self, table_data: TableData, width: int | None = None) -> str:
195
+ """Render table to string representation.
196
+
197
+ Useful for testing and non-interactive environments.
198
+
199
+ Args:
200
+ table_data: Table data to render
201
+ width: Override terminal width
202
+
203
+ Returns:
204
+ String representation of table
205
+ """
206
+ # Temporarily override terminal width for testing
207
+ original_get_width = self.get_terminal_width
208
+ if width is not None:
209
+ self.get_terminal_width = lambda: width
210
+
211
+ try:
212
+ renderable = self.render(table_data)
213
+ from io import StringIO
214
+
215
+ string_io = StringIO()
216
+ temp_console = Console(file=string_io)
217
+ temp_console.print(renderable)
218
+ return string_io.getvalue()
219
+ finally:
220
+ self.get_terminal_width = original_get_width
@@ -0,0 +1,200 @@
1
+ """Mappers for converting between domain models and CLI DTOs.
2
+
3
+ Mappers handle the conversion logic between domain models (internal representation)
4
+ and DTOs (CLI presentation representation). They ensure DTOs don't leak domain
5
+ implementation details.
6
+ """
7
+
8
+ from roadmap.adapters.cli.dtos import CommentDTO, IssueDTO, MilestoneDTO, ProjectDTO
9
+ from roadmap.core.domain.issue import Issue
10
+ from roadmap.core.domain.milestone import Milestone
11
+ from roadmap.core.domain.project import Project
12
+
13
+
14
+ class IssueMapper:
15
+ """Maps between Issue domain model and IssueDTO."""
16
+
17
+ @staticmethod
18
+ def domain_to_dto(issue: Issue) -> IssueDTO:
19
+ """Convert domain Issue to CLI DTO.
20
+
21
+ Converts enums to strings and selects only CLI-relevant fields.
22
+
23
+ Args:
24
+ issue: Domain model Issue instance
25
+
26
+ Returns:
27
+ IssueDTO instance ready for CLI display
28
+ """
29
+ # Convert comments to DTOs
30
+ comments = []
31
+ if hasattr(issue, "comments") and issue.comments:
32
+ comments = [
33
+ CommentDTO(
34
+ id=comment.id,
35
+ author=comment.author,
36
+ body=comment.body,
37
+ created_at=comment.created_at,
38
+ updated_at=comment.updated_at,
39
+ in_reply_to=comment.in_reply_to,
40
+ )
41
+ for comment in issue.comments
42
+ ]
43
+
44
+ return IssueDTO(
45
+ id=issue.id,
46
+ title=issue.title,
47
+ headline=issue.headline or "",
48
+ priority=issue.priority.value, # Convert enum to string
49
+ status=issue.status.value, # Convert enum to string
50
+ issue_type=issue.issue_type.value, # Convert enum to string
51
+ assignee=issue.assignee,
52
+ milestone=issue.milestone,
53
+ due_date=issue.due_date,
54
+ estimated_hours=issue.estimated_hours,
55
+ actual_end_date=issue.actual_end_date,
56
+ progress_percentage=issue.progress_percentage,
57
+ created=issue.created,
58
+ updated=issue.updated,
59
+ content=issue.content,
60
+ labels=issue.labels.copy() if issue.labels else [],
61
+ github_issue=str(issue.github_issue) if issue.github_issue else None,
62
+ comments=comments,
63
+ )
64
+
65
+ @staticmethod
66
+ def dto_to_domain(dto: IssueDTO) -> Issue:
67
+ """Convert CLI DTO to domain Issue.
68
+
69
+ Converts string fields back to appropriate enums.
70
+
71
+ Args:
72
+ dto: IssueDTO instance from CLI
73
+
74
+ Returns:
75
+ Domain model Issue instance
76
+ """
77
+ from roadmap.common.constants import IssueType, Priority, Status
78
+
79
+ return Issue(
80
+ id=dto.id,
81
+ title=dto.title,
82
+ headline=dto.headline or "",
83
+ priority=Priority(dto.priority),
84
+ status=Status(dto.status),
85
+ issue_type=IssueType(dto.issue_type),
86
+ assignee=dto.assignee,
87
+ milestone=dto.milestone,
88
+ due_date=dto.due_date,
89
+ estimated_hours=dto.estimated_hours,
90
+ actual_end_date=dto.actual_end_date,
91
+ progress_percentage=dto.progress_percentage,
92
+ content=dto.content or "",
93
+ labels=dto.labels.copy() if dto.labels else [],
94
+ remote_ids=(
95
+ {"github": int(dto.github_issue)}
96
+ if dto.github_issue and dto.github_issue.isdigit()
97
+ else {}
98
+ ),
99
+ )
100
+
101
+
102
+ class MilestoneMapper:
103
+ """Maps between Milestone domain model and MilestoneDTO."""
104
+
105
+ @staticmethod
106
+ def domain_to_dto(milestone: Milestone) -> MilestoneDTO:
107
+ """Convert domain Milestone to CLI DTO.
108
+
109
+ Args:
110
+ milestone: Domain model Milestone instance
111
+
112
+ Returns:
113
+ MilestoneDTO instance ready for CLI display
114
+ """
115
+ return MilestoneDTO(
116
+ id=milestone.name, # Use name as ID
117
+ name=milestone.name,
118
+ status=milestone.status.value, # Convert enum to string
119
+ headline=milestone.headline or "",
120
+ due_date=milestone.due_date,
121
+ progress_percentage=milestone.calculated_progress,
122
+ created=milestone.created,
123
+ updated=milestone.updated,
124
+ )
125
+
126
+ @staticmethod
127
+ def dto_to_domain(dto: MilestoneDTO) -> Milestone:
128
+ """Convert CLI DTO to domain Milestone.
129
+
130
+ Args:
131
+ dto: MilestoneDTO instance from CLI
132
+
133
+ Returns:
134
+ Domain model Milestone instance
135
+ """
136
+ from roadmap.common.constants import MilestoneStatus
137
+
138
+ return Milestone(
139
+ name=dto.name,
140
+ headline=dto.headline or "",
141
+ status=MilestoneStatus(dto.status),
142
+ due_date=dto.due_date,
143
+ content="",
144
+ )
145
+
146
+
147
+ class ProjectMapper:
148
+ """Maps between Project domain model and ProjectDTO."""
149
+
150
+ @staticmethod
151
+ def domain_to_dto(project: Project) -> ProjectDTO:
152
+ """Convert domain Project to CLI DTO.
153
+
154
+ Args:
155
+ project: Domain model Project instance
156
+
157
+ Returns:
158
+ ProjectDTO instance ready for CLI display
159
+ """
160
+ return ProjectDTO(
161
+ id=project.id,
162
+ name=project.name,
163
+ status=project.status.value, # Convert enum to string
164
+ headline=project.headline or "",
165
+ owner=project.owner,
166
+ target_end_date=project.target_end_date,
167
+ actual_end_date=project.actual_end_date,
168
+ created=project.created,
169
+ updated=project.updated,
170
+ )
171
+
172
+ @staticmethod
173
+ def dto_to_domain(dto: ProjectDTO) -> Project:
174
+ """Convert CLI DTO to domain Project.
175
+
176
+ Args:
177
+ dto: ProjectDTO instance from CLI
178
+
179
+ Returns:
180
+ Domain model Project instance
181
+ """
182
+ from roadmap.common.constants import ProjectStatus
183
+
184
+ return Project(
185
+ id=dto.id,
186
+ name=dto.name,
187
+ headline=dto.headline or "",
188
+ status=ProjectStatus(dto.status),
189
+ content="",
190
+ owner=dto.owner,
191
+ target_end_date=dto.target_end_date,
192
+ actual_end_date=dto.actual_end_date,
193
+ )
194
+
195
+
196
+ __all__ = [
197
+ "IssueMapper",
198
+ "MilestoneMapper",
199
+ "ProjectMapper",
200
+ ]
@@ -0,0 +1,52 @@
1
+ """Milestone commands module.
2
+
3
+ Provides all milestone management commands:
4
+ - create: Create a new milestone
5
+ - list: List all milestones
6
+ - assign: Assign an issue to a milestone
7
+ - delete: Delete a milestone
8
+ - close: Close a milestone
9
+ - update: Update milestone properties
10
+ - recalculate: Recalculate milestone progress
11
+ - kanban: Display milestone in kanban board layout
12
+ - view: View detailed information about a milestone
13
+ - archive: Archive a milestone to .roadmap/archive/milestones/
14
+ """
15
+
16
+ import click
17
+
18
+ from roadmap.adapters.cli.milestones.archive import archive_milestone
19
+ from roadmap.adapters.cli.milestones.assign import assign_milestone
20
+ from roadmap.adapters.cli.milestones.close import close_milestone
21
+ from roadmap.adapters.cli.milestones.create import create_milestone
22
+ from roadmap.adapters.cli.milestones.delete import delete_milestone
23
+ from roadmap.adapters.cli.milestones.kanban import milestone_kanban
24
+ from roadmap.adapters.cli.milestones.list import list_milestones
25
+ from roadmap.adapters.cli.milestones.recalculate import (
26
+ recalculate_milestone_progress,
27
+ )
28
+ from roadmap.adapters.cli.milestones.restore import restore_milestone
29
+ from roadmap.adapters.cli.milestones.update import update_milestone
30
+ from roadmap.adapters.cli.milestones.view import view_milestone
31
+
32
+
33
+ @click.group()
34
+ def milestone():
35
+ """Manage milestones."""
36
+ pass
37
+
38
+
39
+ # Register all commands
40
+ milestone.add_command(create_milestone, name="create")
41
+ milestone.add_command(list_milestones, name="list")
42
+ milestone.add_command(assign_milestone, name="assign")
43
+ milestone.add_command(update_milestone, name="update")
44
+ milestone.add_command(delete_milestone, name="delete")
45
+ milestone.add_command(close_milestone, name="close")
46
+ milestone.add_command(recalculate_milestone_progress, name="recalculate")
47
+ milestone.add_command(milestone_kanban, name="kanban")
48
+ milestone.add_command(view_milestone, name="view")
49
+ milestone.add_command(archive_milestone, name="archive")
50
+ milestone.add_command(restore_milestone, name="restore")
51
+
52
+ __all__ = ["milestone"]
@@ -0,0 +1,125 @@
1
+ """Archive milestone command - move closed milestones to archive."""
2
+
3
+ import click
4
+
5
+ from roadmap.adapters.cli.cli_command_helpers import require_initialized
6
+ from roadmap.adapters.cli.milestones.archive_class import MilestoneArchive
7
+ from roadmap.common.console import get_console
8
+ from roadmap.common.logging import (
9
+ log_command,
10
+ verbose_output,
11
+ )
12
+
13
+
14
+ @click.command()
15
+ @click.argument("milestone_name", required=False)
16
+ @click.option(
17
+ "--all-closed",
18
+ is_flag=True,
19
+ help="Archive all closed milestones",
20
+ )
21
+ @click.option(
22
+ "--list",
23
+ "list_archived",
24
+ is_flag=True,
25
+ help="List archived milestones",
26
+ )
27
+ @click.option(
28
+ "--dry-run",
29
+ is_flag=True,
30
+ help="Preview what would be archived without actually doing it",
31
+ )
32
+ @click.option(
33
+ "--force",
34
+ is_flag=True,
35
+ help="Skip confirmation prompt",
36
+ )
37
+ @click.option(
38
+ "--verbose",
39
+ "-v",
40
+ is_flag=True,
41
+ help="Show detailed debug information",
42
+ )
43
+ @click.pass_context
44
+ @verbose_output
45
+ @log_command("milestone_archive", entity_type="milestone", track_duration=True)
46
+ @require_initialized
47
+ def archive_milestone(
48
+ ctx: click.Context,
49
+ milestone_name: str | None,
50
+ all_closed: bool,
51
+ list_archived: bool,
52
+ dry_run: bool,
53
+ force: bool,
54
+ verbose: bool, # noqa: F841
55
+ ):
56
+ """Archive a milestone by moving it to .roadmap/archive/milestones/.
57
+
58
+ This is a non-destructive operation that preserves milestone data while
59
+ cleaning up the active workspace.
60
+
61
+ Examples:
62
+ roadmap milestone archive "v1.0"
63
+ roadmap milestone archive --all-closed
64
+ roadmap milestone archive --list
65
+ """
66
+ core = ctx.obj["core"]
67
+ console = get_console()
68
+
69
+ archive = MilestoneArchive(core, console)
70
+
71
+ if list_archived:
72
+ from pathlib import Path
73
+
74
+ from roadmap.adapters.persistence.parser import MilestoneParser
75
+
76
+ roadmap_dir = Path.cwd() / ".roadmap"
77
+ archive_dir = roadmap_dir / "archive" / "milestones"
78
+
79
+ if not archive_dir.exists():
80
+ console.print("šŸ“‹ No archived milestones.", style="yellow")
81
+ return
82
+
83
+ archived_files = list(archive_dir.glob("*.md"))
84
+ if not archived_files:
85
+ console.print("šŸ“‹ No archived milestones.", style="yellow")
86
+ return
87
+
88
+ console.print("\nšŸ“¦ Archived Milestones:\n", style="bold blue")
89
+ for file_path in sorted(archived_files):
90
+ try:
91
+ milestone = MilestoneParser.parse_milestone_file(file_path)
92
+ console.print(
93
+ f" • {milestone.name} ({milestone.status.value})", style="cyan"
94
+ )
95
+ except Exception:
96
+ console.print(
97
+ f" • {file_path.name} (error reading file)", style="yellow"
98
+ )
99
+ return
100
+
101
+ # Validate arguments
102
+ if not milestone_name and not all_closed:
103
+ console.print(
104
+ "āŒ Error: Specify a milestone name or use --all-closed",
105
+ style="bold red",
106
+ )
107
+ ctx.exit(1)
108
+
109
+ if milestone_name and all_closed:
110
+ console.print(
111
+ "āŒ Error: Specify only one of: milestone name or --all-closed",
112
+ style="bold red",
113
+ )
114
+ ctx.exit(1)
115
+
116
+ try:
117
+ archive.execute(
118
+ entity_id=milestone_name,
119
+ all_closed=all_closed,
120
+ dry_run=dry_run,
121
+ force=force,
122
+ )
123
+ except Exception as e:
124
+ console.print(f"āŒ Archive operation failed: {str(e)}", style="bold red")
125
+ ctx.exit(1)