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,587 @@
1
+ """Initialize a new roadmap directory structure."""
2
+
3
+ import sys
4
+ from pathlib import Path
5
+
6
+ import click
7
+ from structlog import get_logger
8
+
9
+ from roadmap.adapters.cli.presentation.core_initialization_presenter import (
10
+ CoreInitializationPresenter,
11
+ )
12
+ from roadmap.adapters.cli.services.project_initialization_service import (
13
+ ProjectContextDetectionService,
14
+ ProjectCreationService,
15
+ ProjectDetectionService,
16
+ )
17
+ from roadmap.common.constants import SyncBackend
18
+ from roadmap.common.initialization.github import GitHubInitializationService
19
+ from roadmap.core.services.initialization import (
20
+ InitializationLock,
21
+ InitializationManifest,
22
+ InitializationValidator,
23
+ InitializationWorkflow,
24
+ )
25
+ from roadmap.infrastructure.coordination.core import RoadmapCore
26
+
27
+ logger = get_logger()
28
+ presenter = CoreInitializationPresenter()
29
+
30
+
31
+ def show_dry_run_info(
32
+ name: str, is_initialized: bool, force: bool, skip_project: bool, skip_github: bool
33
+ ) -> None:
34
+ """Display dry-run information without making changes."""
35
+ click.secho("🚀 Roadmap CLI Initialization", fg="cyan", bold=True)
36
+ click.echo()
37
+ click.secho("ℹ️ Dry run mode enabled - no changes will be made.", fg="yellow")
38
+
39
+ if is_initialized and force:
40
+ click.secho(f"🟡 Would remove existing {name}/ and reinitialize", fg="yellow")
41
+ elif is_initialized:
42
+ click.secho(
43
+ f"❌ Roadmap already initialized in {name}/ directory", fg="red", bold=True
44
+ )
45
+ click.secho("Tip: use --force to reinitialize", fg="yellow")
46
+ else:
47
+ actions = [
48
+ f"Create roadmap directory: {name}/",
49
+ "Create default templates and config",
50
+ ]
51
+ if not skip_project:
52
+ actions.append("Create main project")
53
+ if not skip_github:
54
+ actions.append("Optionally configure GitHub")
55
+
56
+ click.echo("Planned actions:")
57
+ for action in actions:
58
+ click.echo(f" - {action}")
59
+
60
+
61
+ def _validate_initialization(custom_core, lock_path, force):
62
+ """Validate initialization prerequisites."""
63
+ is_valid, error_msg = InitializationValidator.validate_lockfile(lock_path)
64
+ if not is_valid:
65
+ presenter.present_error(error_msg or "Unknown error")
66
+ presenter.present_initialization_tip()
67
+ return False
68
+
69
+ is_valid, error_msg = InitializationValidator.check_existing_roadmap(
70
+ custom_core, force
71
+ )
72
+ if not is_valid:
73
+ presenter.present_error(error_msg or "Unknown error")
74
+ presenter.present_initialization_tip()
75
+ return False
76
+
77
+ return True
78
+
79
+
80
+ def _setup_project(
81
+ custom_core,
82
+ skip_project,
83
+ detected_info,
84
+ project_name,
85
+ description,
86
+ template,
87
+ template_path,
88
+ interactive,
89
+ ):
90
+ """Set up project if not skipped."""
91
+ if skip_project:
92
+ return None
93
+
94
+ existing_projects = ProjectDetectionService.detect_existing_projects(
95
+ custom_core.projects_dir
96
+ )
97
+
98
+ if existing_projects:
99
+ if len(existing_projects) > 1 and interactive:
100
+ presenter.present_existing_projects_found(len(existing_projects))
101
+ return {
102
+ "name": existing_projects[0]["name"],
103
+ "id": existing_projects[0]["id"],
104
+ "action": "joined",
105
+ }
106
+
107
+ project_info = ProjectCreationService.create_project(
108
+ custom_core,
109
+ project_name or detected_info.get("project_name", Path.cwd().name),
110
+ description or "A project managed with Roadmap CLI",
111
+ detected_info,
112
+ template or "basic",
113
+ template_path,
114
+ )
115
+ if project_info:
116
+ project_info["action"] = "created"
117
+
118
+ return project_info
119
+
120
+
121
+ def _create_roadmap_structure(workflow, manifest, name):
122
+ """Create roadmap directory structure."""
123
+ presenter.present_creating_structure(name)
124
+ if not workflow.create_structure_preserve_data():
125
+ return False
126
+ workflow.generate_config_file()
127
+ workflow.record_created_paths(manifest)
128
+ workflow.ensure_gitignore_entry()
129
+ return True
130
+
131
+
132
+ def _handle_force_reinitialization(custom_core, workflow, name):
133
+ """Handle force re-initialization of existing roadmap."""
134
+ if custom_core.is_initialized():
135
+ presenter.present_force_reinitialize_warning(name)
136
+ if not workflow.cleanup_existing():
137
+ return False
138
+ return True
139
+
140
+
141
+ def _handle_init_dry_run(
142
+ name: str, force: bool, skip_project: bool, skip_github: bool, log
143
+ ) -> bool:
144
+ """Handle dry-run mode for init.
145
+
146
+ Args:
147
+ name: Roadmap name
148
+ force: Force flag
149
+ skip_project: Skip project setup
150
+ skip_github: Skip GitHub setup
151
+ log: Logger instance
152
+
153
+ Returns:
154
+ True if should continue (not dry-run), False if dry-run was handled
155
+ """
156
+ roadmap_dir = Path.cwd() / name
157
+ config_file = roadmap_dir / "config.yaml"
158
+ is_initialized = roadmap_dir.exists() and config_file.exists()
159
+ log.info("dry_run_mode", is_initialized=is_initialized)
160
+ show_dry_run_info(name, is_initialized, force, skip_project, skip_github)
161
+ return False
162
+
163
+
164
+ def _setup_init_environment(custom_core, name: str, force: bool, log):
165
+ """Set up lock and manifest for initialization.
166
+
167
+ Args:
168
+ custom_core: RoadmapCore instance
169
+ name: Roadmap name
170
+ force: Force flag
171
+ log: Logger instance
172
+
173
+ Returns:
174
+ Tuple of (lock, manifest, workflow) or (None, None, None) on error
175
+ """
176
+ lock_path = Path.cwd() / ".roadmap_init.lock"
177
+ if not _validate_initialization(custom_core, lock_path, force):
178
+ return None, None, None
179
+
180
+ lock = InitializationLock(lock_path)
181
+ if not lock.acquire():
182
+ presenter.present_already_in_progress_error()
183
+ return None, None, None
184
+
185
+ manifest = InitializationManifest(custom_core.roadmap_dir / ".init_manifest.json")
186
+ workflow = InitializationWorkflow(custom_core)
187
+
188
+ return lock, manifest, workflow
189
+
190
+
191
+ def _handle_already_initialized(
192
+ custom_core, force: bool, workflow, name: str
193
+ ) -> tuple[bool, bool]:
194
+ """Handle case where roadmap is already initialized.
195
+
196
+ Args:
197
+ custom_core: RoadmapCore instance
198
+ force: Force re-initialization flag
199
+ workflow: InitializationWorkflow instance
200
+ name: Roadmap name
201
+
202
+ Returns:
203
+ Tuple of (should_continue, should_create_structure)
204
+ - should_continue: Whether to proceed with initialization
205
+ - should_create_structure: Whether to call _create_roadmap_structure
206
+ """
207
+ if force:
208
+ success = _handle_force_reinitialization(custom_core, workflow, name)
209
+ # If force succeeded, we need to create structure (roadmap was cleaned)
210
+ return success, success
211
+ elif custom_core.is_initialized():
212
+ # Show info message but continue - allow team members to join existing projects
213
+ # Do NOT create structure since roadmap already exists
214
+ presenter.present_already_initialized_info(name)
215
+ return True, False
216
+ # Roadmap doesn't exist, so we need to create structure
217
+ return True, True
218
+
219
+
220
+ def _setup_project_and_context(
221
+ custom_core: RoadmapCore,
222
+ skip_project: bool,
223
+ detected_info: dict,
224
+ project_name: str | None,
225
+ description: str | None,
226
+ template: str | None,
227
+ template_path: str | None,
228
+ interactive: bool,
229
+ ) -> dict | None:
230
+ """Set up project and save configuration.
231
+
232
+ Args:
233
+ custom_core: The roadmap core instance
234
+ skip_project: Whether to skip project setup
235
+ detected_info: Detected project context
236
+ project_name: Optional project name
237
+ description: Optional project description
238
+ template: Optional template name
239
+ template_path: Optional path to template
240
+ interactive: Whether interactive mode is enabled
241
+
242
+ Returns:
243
+ Project info dict or None
244
+ """
245
+ project_info = _setup_project(
246
+ custom_core,
247
+ skip_project,
248
+ detected_info,
249
+ project_name,
250
+ description,
251
+ template,
252
+ template_path,
253
+ interactive,
254
+ )
255
+
256
+ # Save default project ID if created
257
+ if project_info and project_info.get("action") == "created":
258
+ from roadmap.common.configuration import ConfigManager
259
+
260
+ config_manager = ConfigManager(custom_core.config_file)
261
+ config = config_manager.load()
262
+ config.behavior.default_project_id = project_info.get("id")
263
+ config_manager.save(config)
264
+
265
+ return project_info
266
+
267
+
268
+ def _present_project_results(project_info: dict | None) -> None:
269
+ """Display project setup results to user.
270
+
271
+ Args:
272
+ project_info: Information about the created/joined project
273
+ """
274
+ if not project_info:
275
+ return
276
+
277
+ if project_info.get("action") == "created":
278
+ presenter.present_project_created(project_info.get("name", "Main Project"))
279
+ elif project_info.get("action") == "joined":
280
+ count = project_info.get("count", 1)
281
+ if count > 1:
282
+ presenter.present_projects_joined(project_info.get("name", ""), count)
283
+ else:
284
+ presenter.present_project_joined(project_info.get("name", ""))
285
+
286
+
287
+ def _persist_sync_backend_config(
288
+ custom_core: RoadmapCore, sync_backend: str, log
289
+ ) -> None:
290
+ """Persist sync backend selection to configuration.
291
+
292
+ Args:
293
+ custom_core: The roadmap core instance
294
+ sync_backend: The sync backend to persist
295
+ log: Logger instance for recording operations
296
+ """
297
+ if sync_backend == "github":
298
+ return
299
+
300
+ try:
301
+ from roadmap.common.configuration import ConfigManager
302
+
303
+ config_manager = ConfigManager(custom_core.config_file)
304
+ config = config_manager.load()
305
+
306
+ if not config.github:
307
+ log.warning("github_config_not_initialized", sync_backend=sync_backend)
308
+ return
309
+
310
+ log.info(
311
+ "persisting_sync_backend",
312
+ sync_backend=sync_backend,
313
+ config_file=str(custom_core.config_file),
314
+ )
315
+ config.github.sync_backend = sync_backend
316
+ config_manager.save(config)
317
+
318
+ # Verify persistence
319
+ verify_config = config_manager.load()
320
+ persisted_backend = verify_config.github.sync_backend
321
+ if persisted_backend == sync_backend:
322
+ log.info("sync_backend_persisted_verified", sync_backend=sync_backend)
323
+ else:
324
+ log.warning(
325
+ "sync_backend_persistence_mismatch",
326
+ expected=sync_backend,
327
+ actual=persisted_backend,
328
+ )
329
+ except Exception as e:
330
+ log.error(
331
+ "sync_backend_persistence_failed",
332
+ sync_backend=sync_backend,
333
+ error=str(e),
334
+ error_type=type(e).__name__,
335
+ )
336
+ presenter.present_initialization_warning(
337
+ f"⚠️ Could not persist sync backend selection: {str(e)}"
338
+ )
339
+
340
+
341
+ def _finalize_initialization(
342
+ custom_core: RoadmapCore,
343
+ name: str,
344
+ project_info: dict | None,
345
+ should_create_structure: bool,
346
+ ) -> None:
347
+ """Finalize initialization with validation and summary.
348
+
349
+ Args:
350
+ custom_core: The roadmap core instance
351
+ name: The roadmap name
352
+ project_info: Information about the setup project
353
+ should_create_structure: Whether new structure was created
354
+ """
355
+ # Validate and show summary
356
+ validation_ok = InitializationValidator.post_init_validate(
357
+ custom_core, name, project_info
358
+ )
359
+ if not validation_ok:
360
+ presenter.present_initialization_warning("Some validation checks failed")
361
+
362
+ # Show completion message with next steps
363
+ presenter.present_initialization_complete(created_new=should_create_structure)
364
+
365
+ # If we joined existing projects (not created), show them
366
+ if project_info and project_info.get("action") == "joined":
367
+ all_projects = ProjectDetectionService.detect_existing_projects(
368
+ custom_core.projects_dir
369
+ )
370
+ if all_projects:
371
+ project_names = [p.get("name", "Unknown") for p in all_projects]
372
+ presenter.present_existing_projects_info(project_names)
373
+
374
+
375
+ @click.command()
376
+ @click.option(
377
+ "--name",
378
+ "-n",
379
+ default=".roadmap",
380
+ help="Name of the roadmap directory (default: .roadmap)",
381
+ )
382
+ @click.option(
383
+ "--project-name",
384
+ "-p",
385
+ default=None,
386
+ help="Name for the initial project",
387
+ )
388
+ @click.option(
389
+ "--description",
390
+ "-d",
391
+ default=None,
392
+ help="Description for the initial project",
393
+ )
394
+ @click.option(
395
+ "--skip-project",
396
+ is_flag=True,
397
+ help="Skip project creation",
398
+ )
399
+ @click.option(
400
+ "--skip-github",
401
+ is_flag=True,
402
+ help="Skip GitHub integration setup",
403
+ )
404
+ @click.option(
405
+ "--sync-backend",
406
+ type=click.Choice(["github", "git"]),
407
+ default="github",
408
+ help="Sync backend to use: 'github' for GitHub API, 'git' for vanilla Git push/pull",
409
+ )
410
+ @click.option(
411
+ "--github-repo",
412
+ default=None,
413
+ help="GitHub repository (owner/repo)",
414
+ )
415
+ @click.option(
416
+ "--github-token",
417
+ default=None,
418
+ help="GitHub personal access token",
419
+ )
420
+ @click.option(
421
+ "--interactive/--non-interactive",
422
+ default=True,
423
+ help="Run in interactive mode with prompts (default: interactive)",
424
+ )
425
+ @click.option(
426
+ "--yes",
427
+ "-y",
428
+ is_flag=True,
429
+ help="Answer yes to all prompts",
430
+ )
431
+ @click.option(
432
+ "--dry-run",
433
+ is_flag=True,
434
+ help="Show what would be initialized without making changes",
435
+ )
436
+ @click.option(
437
+ "--force",
438
+ "-f",
439
+ is_flag=True,
440
+ help="Force reinitialize existing roadmap",
441
+ )
442
+ @click.option(
443
+ "--template",
444
+ "-t",
445
+ default=None,
446
+ help="Template to use for project initialization",
447
+ )
448
+ @click.option(
449
+ "--template-path",
450
+ default=None,
451
+ help="Path to custom template file",
452
+ )
453
+ @click.pass_context
454
+ def init(
455
+ ctx: click.Context,
456
+ name: str,
457
+ project_name: str | None,
458
+ description: str | None,
459
+ skip_project: bool,
460
+ skip_github: bool,
461
+ sync_backend: str,
462
+ github_repo: str | None,
463
+ github_token: str | None,
464
+ interactive: bool,
465
+ yes: bool,
466
+ dry_run: bool,
467
+ force: bool,
468
+ template: str | None,
469
+ template_path: str | None,
470
+ ) -> None:
471
+ """Initialize a new roadmap structure."""
472
+ from roadmap.common.models import InitParams
473
+
474
+ # Create structured parameter object
475
+ params = InitParams(
476
+ name=name,
477
+ project_name=project_name,
478
+ description=description,
479
+ skip_project=skip_project,
480
+ skip_github=skip_github,
481
+ sync_backend=sync_backend,
482
+ github_repo=github_repo,
483
+ github_token=github_token,
484
+ interactive=interactive,
485
+ yes=yes,
486
+ dry_run=dry_run,
487
+ force=force,
488
+ template=template,
489
+ template_path=template_path,
490
+ )
491
+
492
+ log = logger.bind(
493
+ operation="init",
494
+ roadmap_name=params.name,
495
+ skip_github=params.skip_github,
496
+ interactive=params.interactive,
497
+ dry_run=params.dry_run,
498
+ force=params.force,
499
+ )
500
+ log.info("starting_init")
501
+
502
+ custom_core = RoadmapCore(roadmap_dir_name=params.name)
503
+
504
+ # Handle dry-run mode
505
+ if params.dry_run:
506
+ _handle_init_dry_run(
507
+ params.name, params.force, params.skip_project, params.skip_github, log
508
+ )
509
+ return
510
+
511
+ # Setup environment
512
+ lock, manifest, workflow = _setup_init_environment(
513
+ custom_core, params.name, params.force, log
514
+ )
515
+ if not lock:
516
+ sys.exit(1)
517
+
518
+ presenter.present_initialization_header()
519
+
520
+ try:
521
+ # Handle already initialized or force re-init
522
+ should_continue, should_create_structure = _handle_already_initialized(
523
+ custom_core, params.force, workflow, params.name
524
+ )
525
+ if not should_continue:
526
+ return
527
+
528
+ # Detect context (needed for project setup regardless)
529
+ detected_info = ProjectContextDetectionService.detect_project_context()
530
+
531
+ # Create structure only if needed (not already initialized or was force-cleaned)
532
+ if should_create_structure:
533
+ if not _create_roadmap_structure(workflow, manifest, params.name):
534
+ return
535
+
536
+ # Initialize ctx.obj if not already done (can happen in tests)
537
+ if ctx.obj is None:
538
+ ctx.obj = {}
539
+
540
+ ctx.obj["core"] = custom_core
541
+
542
+ # Setup project and context
543
+ project_info = _setup_project_and_context(
544
+ custom_core,
545
+ params.skip_project,
546
+ detected_info,
547
+ params.project_name,
548
+ params.description,
549
+ params.template,
550
+ params.template_path,
551
+ params.interactive,
552
+ )
553
+
554
+ # Present project results
555
+ _present_project_results(project_info)
556
+
557
+ # Configure GitHub
558
+ github_service = GitHubInitializationService(custom_core)
559
+ sync_backend_enum = SyncBackend(params.sync_backend)
560
+ github_service.setup(
561
+ params.skip_github,
562
+ params.github_repo,
563
+ detected_info,
564
+ params.interactive,
565
+ params.yes,
566
+ github_token,
567
+ presenter,
568
+ sync_backend=sync_backend_enum,
569
+ )
570
+
571
+ # Persist sync backend configuration
572
+ _persist_sync_backend_config(custom_core, params.sync_backend, log)
573
+
574
+ # Finalize and validate
575
+ _finalize_initialization(
576
+ custom_core, name, project_info, should_create_structure
577
+ )
578
+
579
+ except Exception as e:
580
+ log.error("init_failed", error=str(e))
581
+ presenter.present_initialization_failed(str(e))
582
+ if manifest:
583
+ manifest.rollback()
584
+ if workflow:
585
+ workflow.rollback_on_error()
586
+ finally:
587
+ lock.release()
@@ -0,0 +1,9 @@
1
+ """Initialize a new roadmap directory structure.
2
+
3
+ This module re-exports the init command from the init package.
4
+ The actual implementation is in adapters/cli/init/commands.py
5
+ """
6
+
7
+ from roadmap.adapters.cli.init.commands import init
8
+
9
+ __all__ = ["init"]
@@ -0,0 +1,70 @@
1
+ """Issue commands module.
2
+
3
+ Provides all issue management commands:
4
+ - list: List issues with various filters
5
+ - create: Create a new issue
6
+ - update: Update an existing issue
7
+ - close: Close an issue (Git-aligned terminology)
8
+ - start: Start work on an issue
9
+ - progress: Update issue progress percentage
10
+ - block: Mark an issue as blocked
11
+ - unblock: Unblock a blocked issue
12
+ - delete: Delete an issue
13
+ - deps: Manage issue dependencies
14
+ - view: View detailed information about an issue
15
+ - archive: Archive an issue to .roadmap/archive/issues/
16
+ - comment: Manage comments and discussions on issues
17
+ - link: Link internal issue to GitHub issue
18
+ - lookup-github: Look up internal issue by GitHub issue number
19
+ - sync-status: View sync history and statistics for GitHub-linked issues
20
+ """
21
+
22
+ import click
23
+
24
+ from roadmap.adapters.cli.issues.archive import archive_issue
25
+ from roadmap.adapters.cli.issues.block import block_issue
26
+ from roadmap.adapters.cli.issues.close import close_issue
27
+ from roadmap.adapters.cli.issues.comment import comment_group
28
+ from roadmap.adapters.cli.issues.create import create_issue
29
+ from roadmap.adapters.cli.issues.delete import delete_issue
30
+ from roadmap.adapters.cli.issues.deps import deps
31
+ from roadmap.adapters.cli.issues.link import link_github_issue
32
+ from roadmap.adapters.cli.issues.list import list_issues
33
+ from roadmap.adapters.cli.issues.lookup import lookup_github_issue
34
+ from roadmap.adapters.cli.issues.progress import update_progress
35
+ from roadmap.adapters.cli.issues.restore import restore_issue
36
+ from roadmap.adapters.cli.issues.start import start_issue
37
+ from roadmap.adapters.cli.issues.sync_status import sync_status
38
+ from roadmap.adapters.cli.issues.unblock import unblock_issue
39
+ from roadmap.adapters.cli.issues.unlink import unlink_github_issue
40
+ from roadmap.adapters.cli.issues.update import update_issue
41
+ from roadmap.adapters.cli.issues.view import view_issue
42
+
43
+
44
+ @click.group()
45
+ def issue():
46
+ """Manage issues."""
47
+ pass
48
+
49
+
50
+ # Register all commands
51
+ issue.add_command(list_issues, name="list")
52
+ issue.add_command(create_issue, name="create")
53
+ issue.add_command(update_issue, name="update")
54
+ issue.add_command(close_issue, name="close")
55
+ issue.add_command(start_issue, name="start")
56
+ issue.add_command(update_progress, name="progress")
57
+ issue.add_command(block_issue, name="block")
58
+ issue.add_command(unblock_issue, name="unblock")
59
+ issue.add_command(delete_issue, name="delete")
60
+ issue.add_command(deps, name="deps")
61
+ issue.add_command(view_issue, name="view")
62
+ issue.add_command(archive_issue, name="archive")
63
+ issue.add_command(restore_issue, name="restore")
64
+ issue.add_command(comment_group, name="comment")
65
+ issue.add_command(link_github_issue, name="link-github")
66
+ issue.add_command(unlink_github_issue, name="unlink-github")
67
+ issue.add_command(lookup_github_issue, name="lookup-github")
68
+ issue.add_command(sync_status, name="sync-status")
69
+
70
+ __all__ = ["issue"]