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,142 @@
1
+ """Validator for orphaned issues."""
2
+
3
+ from pathlib import Path
4
+
5
+ from roadmap.common.logging import get_logger
6
+ from roadmap.core.domain.issue import Status
7
+ from roadmap.core.services.validator_base import HealthStatus
8
+
9
+ logger = get_logger(__name__)
10
+
11
+
12
+ class OrphanedIssuesValidator:
13
+ """Validator for orphaned issues (in wrong folder based on milestone)."""
14
+
15
+ @staticmethod
16
+ def scan_for_orphaned_issues(core) -> list[dict]:
17
+ """Scan for issues in wrong folder (not matching their milestone).
18
+
19
+ Returns a list of misplaced issue dicts with id, title, and details.
20
+ """
21
+ misplaced = []
22
+
23
+ try:
24
+ issues_dir = Path(".roadmap/issues").resolve()
25
+ archive_dir = Path(".roadmap/archive/issues").resolve()
26
+
27
+ if not issues_dir.exists():
28
+ return misplaced
29
+
30
+ # Scan all issues
31
+ for issue in core.issues.list():
32
+ # Determine expected folder
33
+ expected_folder = OrphanedIssuesValidator._get_expected_folder(issue)
34
+
35
+ # Find actual folder
36
+ actual_folder = OrphanedIssuesValidator._find_issue_folder(
37
+ issue.id, issues_dir, archive_dir
38
+ )
39
+
40
+ # Issue is misplaced if:
41
+ # 1. It's at root level (actual_folder == issues_dir)
42
+ # 2. Or it's in wrong folder (actual_folder != expected_folder)
43
+ if actual_folder:
44
+ if actual_folder == issues_dir or actual_folder != expected_folder:
45
+ misplaced.append(
46
+ {
47
+ "id": issue.id,
48
+ "title": issue.title,
49
+ "milestone": issue.milestone or "(none)",
50
+ "current_folder": str(actual_folder),
51
+ "expected_folder": str(expected_folder),
52
+ }
53
+ )
54
+
55
+ except Exception as e:
56
+ logger.debug("scan_orphaned_issues_error", error=str(e))
57
+
58
+ return misplaced
59
+
60
+ @staticmethod
61
+ def check_orphaned_issues(core) -> tuple[str, str]:
62
+ """Check for orphaned issues.
63
+
64
+ Returns:
65
+ Tuple of (status, message) describing the health check result
66
+ """
67
+ try:
68
+ misplaced = OrphanedIssuesValidator.scan_for_orphaned_issues(core)
69
+
70
+ if not misplaced:
71
+ logger.debug("health_check_orphaned_issues", status="none")
72
+ return HealthStatus.HEALTHY, "No orphaned issues found"
73
+
74
+ count = len(misplaced)
75
+ message = (
76
+ f"⚠️ {count} orphaned issue(s) found (in wrong folder): "
77
+ "These issues are not in the folder matching their milestone"
78
+ )
79
+ logger.warning(
80
+ "health_check_orphaned_issues", count=count, severity="operational"
81
+ )
82
+ return HealthStatus.DEGRADED, message
83
+
84
+ except Exception as e:
85
+ logger.debug("health_check_orphaned_issues_failed", error=str(e))
86
+ return HealthStatus.HEALTHY, "Could not check for orphaned issues"
87
+
88
+ @staticmethod
89
+ def _get_expected_folder(issue) -> Path:
90
+ """Determine expected folder for an issue.
91
+
92
+ Args:
93
+ issue: Issue object
94
+
95
+ Returns:
96
+ Path to expected folder
97
+ """
98
+ # Closed issues go to archive
99
+ base_path = (
100
+ Path(".roadmap/archive/issues").resolve()
101
+ if issue.status == Status.CLOSED
102
+ else Path(".roadmap/issues").resolve()
103
+ )
104
+
105
+ # If no milestone, assign to backlog
106
+ milestone = issue.milestone or "backlog"
107
+
108
+ return base_path / milestone
109
+
110
+ @staticmethod
111
+ def _find_issue_folder(
112
+ issue_id: str, issues_dir: Path, archive_dir: Path
113
+ ) -> Path | None:
114
+ """Find the actual folder containing an issue.
115
+
116
+ Args:
117
+ issue_id: Issue ID to find
118
+ issues_dir: Path to .roadmap/issues
119
+ archive_dir: Path to .roadmap/archive/issues
120
+
121
+ Returns:
122
+ Path to folder containing the issue, or None if at root level
123
+ """
124
+ # Check if file is at root level (loose file)
125
+ for file in issues_dir.glob(f"{issue_id}*.md"):
126
+ if file.is_file():
127
+ return issues_dir # Return root to indicate it's loose
128
+
129
+ # Check main issues directory subfolders
130
+ for folder in issues_dir.iterdir():
131
+ if folder.is_dir():
132
+ for _ in folder.glob(f"{issue_id}*.md"):
133
+ return folder
134
+
135
+ # Check archive directory
136
+ if archive_dir.exists():
137
+ for folder in archive_dir.iterdir():
138
+ if folder.is_dir():
139
+ for _ in folder.glob(f"{issue_id}*.md"):
140
+ return folder
141
+
142
+ return None
@@ -0,0 +1,85 @@
1
+ """Validator for orphaned milestones."""
2
+
3
+ from roadmap.common.logging import get_logger
4
+ from roadmap.core.services.validator_base import BaseValidator, HealthStatus
5
+ from roadmap.infrastructure.coordination.core import RoadmapCore
6
+
7
+ logger = get_logger(__name__)
8
+
9
+
10
+ class OrphanedMilestonesValidator(BaseValidator):
11
+ """Validator for orphaned milestones (not assigned to any project)."""
12
+
13
+ @staticmethod
14
+ def get_check_name() -> str:
15
+ """Get the name of this check.
16
+
17
+ Returns:
18
+ String identifier for the orphaned_milestones check.
19
+ """
20
+ return "orphaned_milestones"
21
+
22
+ @staticmethod
23
+ def scan_for_orphaned_milestones(core) -> list[dict]:
24
+ """Scan for milestones not assigned to any project.
25
+
26
+ Returns a list of orphaned milestone dicts with name, description, and details.
27
+ """
28
+ orphaned = []
29
+
30
+ try:
31
+ all_milestones = core.milestones.list()
32
+ all_projects = core.projects.list()
33
+
34
+ # Build set of milestone names assigned to projects
35
+ assigned_milestone_names = set()
36
+ for project in all_projects:
37
+ assigned_milestone_names.update(project.milestones)
38
+
39
+ # Find milestones not in any project
40
+ for milestone in all_milestones:
41
+ if milestone.name not in assigned_milestone_names:
42
+ orphaned.append(
43
+ {
44
+ "name": milestone.name,
45
+ "content": milestone.content or "(no description)",
46
+ "status": milestone.status.value,
47
+ "created": milestone.created.isoformat()
48
+ if milestone.created
49
+ else None,
50
+ }
51
+ )
52
+
53
+ except Exception as e:
54
+ logger.debug("scan_orphaned_milestones_error", error=str(e))
55
+
56
+ return orphaned
57
+
58
+ @staticmethod
59
+ def perform_check() -> tuple[str, str]:
60
+ """Check for orphaned milestones.
61
+
62
+ Returns:
63
+ Tuple of (status, message) describing the health check result
64
+ """
65
+ try:
66
+ core = RoadmapCore()
67
+ orphaned = OrphanedMilestonesValidator.scan_for_orphaned_milestones(core)
68
+
69
+ if not orphaned:
70
+ logger.debug("health_check_orphaned_milestones", status="none")
71
+ return HealthStatus.HEALTHY, "No orphaned milestones found"
72
+
73
+ count = len(orphaned)
74
+ message = (
75
+ f"⚠️ {count} orphaned milestone(s) found (not assigned to any project): "
76
+ "These milestones should be assigned to a project or deleted"
77
+ )
78
+ logger.warning(
79
+ "health_check_orphaned_milestones", count=count, severity="operational"
80
+ )
81
+ return HealthStatus.DEGRADED, message
82
+
83
+ except Exception as e:
84
+ logger.debug("health_check_orphaned_milestones_failed", error=str(e))
85
+ return HealthStatus.HEALTHY, "Could not check for orphaned milestones"
@@ -0,0 +1,83 @@
1
+ """Utility for parsing GitHub information from git remote URLs."""
2
+
3
+ import re
4
+ import subprocess
5
+ from pathlib import Path
6
+
7
+ from structlog import get_logger
8
+
9
+ logger = get_logger()
10
+
11
+
12
+ def parse_github_remote(remote_url: str | None) -> tuple[str | None, str | None]:
13
+ """Parse GitHub owner and repo from a git remote URL.
14
+
15
+ Supports both SSH and HTTPS formats:
16
+ - git@github.com:owner/repo.git
17
+ - https://github.com/owner/repo.git
18
+ - https://github.com/owner/repo
19
+
20
+ Args:
21
+ remote_url: Git remote URL string or None
22
+
23
+ Returns:
24
+ Tuple of (owner, repo) or (None, None) if not a valid GitHub URL
25
+ """
26
+ if not remote_url or "github.com" not in remote_url:
27
+ return None, None
28
+
29
+ # Match SSH format: git@github.com:owner/repo.git
30
+ ssh_match = re.search(r"github\.com:([^/]+)/([^/.]+)", remote_url)
31
+ if ssh_match:
32
+ owner = ssh_match.group(1)
33
+ repo = ssh_match.group(2)
34
+ return owner, repo
35
+
36
+ # Match HTTPS format: https://github.com/owner/repo.git or https://github.com/owner/repo
37
+ https_match = re.search(r"github\.com/([^/]+)/([^/.]+)", remote_url)
38
+ if https_match:
39
+ owner = https_match.group(1)
40
+ repo = https_match.group(2)
41
+ return owner, repo
42
+
43
+ return None, None
44
+
45
+
46
+ def get_github_from_git_remote(
47
+ repo_path: Path | None = None,
48
+ ) -> tuple[str | None, str | None]:
49
+ """Auto-detect GitHub owner and repo from git remote origin.
50
+
51
+ Args:
52
+ repo_path: Path to git repository (defaults to current directory)
53
+
54
+ Returns:
55
+ Tuple of (owner, repo) or (None, None) if not detected
56
+ """
57
+ try:
58
+ cwd = str(repo_path) if repo_path else None
59
+ result = subprocess.run(
60
+ ["git", "config", "--get", "remote.origin.url"],
61
+ capture_output=True,
62
+ text=True,
63
+ timeout=5,
64
+ cwd=cwd,
65
+ )
66
+
67
+ if result.returncode == 0 and result.stdout.strip():
68
+ remote_url = result.stdout.strip()
69
+ owner, repo = parse_github_remote(remote_url)
70
+
71
+ if owner and repo:
72
+ logger.info(
73
+ "github_detected_from_remote",
74
+ owner=owner,
75
+ repo=repo,
76
+ remote_url=remote_url,
77
+ )
78
+ return owner, repo
79
+
80
+ except (subprocess.TimeoutExpired, FileNotFoundError) as e:
81
+ logger.debug("git_remote_detection_failed", error=str(e))
82
+
83
+ return None, None
@@ -0,0 +1,66 @@
1
+ """Utilities for generating GitHub URLs on-demand."""
2
+
3
+
4
+ def get_issue_url(owner: str, repo: str, issue_number: int | str) -> str:
5
+ """Generate a GitHub issue URL.
6
+
7
+ Args:
8
+ owner: Repository owner
9
+ repo: Repository name
10
+ issue_number: Issue number
11
+
12
+ Returns:
13
+ Full GitHub issue URL
14
+ """
15
+ issue_num = int(issue_number) if isinstance(issue_number, str) else issue_number
16
+ return f"https://github.com/{owner}/{repo}/issues/{issue_num}"
17
+
18
+
19
+ def get_milestone_url(owner: str, repo: str, milestone_number: int | str) -> str:
20
+ """Generate a GitHub milestone URL.
21
+
22
+ Args:
23
+ owner: Repository owner
24
+ repo: Repository name
25
+ milestone_number: Milestone number
26
+
27
+ Returns:
28
+ Full GitHub milestone URL
29
+ """
30
+ milestone_num = (
31
+ int(milestone_number) if isinstance(milestone_number, str) else milestone_number
32
+ )
33
+ return f"https://github.com/{owner}/{repo}/milestone/{milestone_num}"
34
+
35
+
36
+ def get_repo_url(owner: str, repo: str) -> str:
37
+ """Generate a GitHub repository URL.
38
+
39
+ Args:
40
+ owner: Repository owner
41
+ repo: Repository name
42
+
43
+ Returns:
44
+ Full GitHub repository URL
45
+ """
46
+ return f"https://github.com/{owner}/{repo}"
47
+
48
+
49
+ def parse_github_number(url: str) -> int | None:
50
+ """Extract issue/milestone number from a GitHub URL.
51
+
52
+ Args:
53
+ url: GitHub URL (e.g., https://github.com/owner/repo/issues/123)
54
+
55
+ Returns:
56
+ Issue/milestone number, or None if not found
57
+ """
58
+ try:
59
+ # Try to extract number from URL
60
+ parts = url.rstrip("/").split("/")
61
+ if parts:
62
+ last_part = parts[-1]
63
+ return int(last_part)
64
+ except (ValueError, IndexError):
65
+ pass
66
+ return None
@@ -0,0 +1,30 @@
1
+ """Validation utilities for roadmap domain logic."""
2
+
3
+ from pathlib import Path
4
+ from typing import Any
5
+
6
+ from roadmap.core.services.validators import (
7
+ DataIntegrityValidator,
8
+ DuplicateIssuesValidator,
9
+ FolderStructureValidator,
10
+ )
11
+
12
+ # Example utility: validate folder structure
13
+
14
+
15
+ def validate_folder_structure(issues_dir: Path, core: Any) -> dict:
16
+ """Validate folder structure and return issues found."""
17
+ return FolderStructureValidator.scan_for_folder_structure_issues(issues_dir, core)
18
+
19
+
20
+ def find_duplicate_issues(issues_dir: Path) -> dict:
21
+ """Find duplicate issues by issue ID."""
22
+ return DuplicateIssuesValidator.scan_for_duplicate_issues(issues_dir)
23
+
24
+
25
+ def find_malformed_issue_files(issues_dir: Path) -> dict:
26
+ """Find malformed issue files (unparseable YAML, etc)."""
27
+ return DataIntegrityValidator.scan_for_data_integrity_issues(issues_dir)
28
+
29
+
30
+ # Add more validation utilities as needed
@@ -0,0 +1,55 @@
1
+ """Infrastructure layer - Coordination, operations, and cross-domain concerns.
2
+
3
+ This module is organized by concern:
4
+ - coordination/: RoadmapCore, domain coordinators, and operations
5
+ - git/: Git integration and branch linking
6
+ - observability/: Health checks and monitoring
7
+ - validation/: Data validation and GitHub integration
8
+ - security/: Credential management and security concerns
9
+ - maintenance/: Cleanup and maintenance operations
10
+
11
+ Re-exports common items for backward compatibility.
12
+ """
13
+
14
+ # Re-export from coordination for backward compatibility
15
+ from roadmap.infrastructure.coordination.core import RoadmapCore
16
+ from roadmap.infrastructure.coordination.git_coordinator import GitCoordinator
17
+ from roadmap.infrastructure.coordination.initialization import InitializationManager
18
+ from roadmap.infrastructure.coordination.issue_coordinator import IssueCoordinator
19
+ from roadmap.infrastructure.coordination.issue_operations import IssueOperations
20
+ from roadmap.infrastructure.coordination.milestone_coordinator import (
21
+ MilestoneCoordinator,
22
+ )
23
+ from roadmap.infrastructure.coordination.milestone_operations import MilestoneOperations
24
+ from roadmap.infrastructure.coordination.project_coordinator import ProjectCoordinator
25
+ from roadmap.infrastructure.coordination.project_operations import ProjectOperations
26
+ from roadmap.infrastructure.coordination.team_coordinator import TeamCoordinator
27
+ from roadmap.infrastructure.coordination.user_operations import UserOperations
28
+ from roadmap.infrastructure.coordination.validation_coordinator import (
29
+ ValidationCoordinator,
30
+ )
31
+
32
+ # Re-export from git for backward compatibility
33
+ from roadmap.infrastructure.git.git_integration_ops import GitIntegrationOps
34
+
35
+ # Re-export from observability for backward compatibility
36
+ from roadmap.infrastructure.observability.health import HealthCheck
37
+ from roadmap.infrastructure.observability.health_formatter import HealthStatusFormatter
38
+
39
+ __all__ = [
40
+ "RoadmapCore",
41
+ "GitCoordinator",
42
+ "InitializationManager",
43
+ "IssueCoordinator",
44
+ "IssueOperations",
45
+ "MilestoneCoordinator",
46
+ "MilestoneOperations",
47
+ "ProjectCoordinator",
48
+ "ProjectOperations",
49
+ "TeamCoordinator",
50
+ "UserOperations",
51
+ "ValidationCoordinator",
52
+ "GitIntegrationOps",
53
+ "HealthCheck",
54
+ "HealthStatusFormatter",
55
+ ]
@@ -0,0 +1,8 @@
1
+ """Coordination layer - Orchestrates domain operations.
2
+
3
+ This module contains:
4
+ - RoadmapCore: Main facade and service container
5
+ - Domain coordinators: Issue, Milestone, Project, Team, Git, Validation
6
+ - Operations: Concrete implementations of domain operations
7
+ - Initialization: Setup and configuration management
8
+ """
@@ -0,0 +1,82 @@
1
+ """Coordinator layer parameter dataclasses.
2
+
3
+ Consolidates coordinator method parameters into well-structured dataclasses
4
+ for improved API consistency and reduced parameter passing complexity.
5
+ """
6
+
7
+ from dataclasses import dataclass, field
8
+ from datetime import datetime
9
+ from typing import Any
10
+
11
+ from roadmap.core.domain import IssueType, Priority
12
+
13
+
14
+ @dataclass
15
+ class IssueCreateParams:
16
+ """Parameters for creating a new issue through IssueCoordinator."""
17
+
18
+ title: str
19
+ priority: Priority = Priority.MEDIUM
20
+ issue_type: IssueType = IssueType.OTHER
21
+ milestone: str | None = None
22
+ labels: list[str] | None = None
23
+ assignee: str | None = None
24
+ estimated_hours: float | None = None
25
+ depends_on: list[str] | None = None
26
+ blocks: list[str] | None = None
27
+
28
+
29
+ @dataclass
30
+ class IssueListParams:
31
+ """Parameters for listing issues through IssueCoordinator."""
32
+
33
+ milestone: str | None = None
34
+ status: str | None = None
35
+ priority: Priority | None = None
36
+ issue_type: IssueType | None = None
37
+ assignee: str | None = None
38
+
39
+
40
+ @dataclass
41
+ class IssueUpdateParams:
42
+ """Parameters for updating an issue through IssueCoordinator."""
43
+
44
+ issue_id: str
45
+ updates: dict[str, Any] = field(default_factory=dict)
46
+
47
+
48
+ @dataclass
49
+ class MilestoneCreateParams:
50
+ """Parameters for creating a new milestone through MilestoneCoordinator."""
51
+
52
+ name: str
53
+ content: str = ""
54
+ due_date: datetime | None = None
55
+
56
+
57
+ @dataclass
58
+ class MilestoneUpdateParams:
59
+ """Parameters for updating a milestone through MilestoneCoordinator."""
60
+
61
+ name: str
62
+ content: str | None = None
63
+ due_date: datetime | None = None
64
+ clear_due_date: bool = False
65
+ status: str | None = None
66
+
67
+
68
+ @dataclass
69
+ class ProjectCreateParams:
70
+ """Parameters for creating a new project through ProjectCoordinator."""
71
+
72
+ name: str
73
+ content: str = ""
74
+ milestones: list[str] | None = None
75
+
76
+
77
+ @dataclass
78
+ class ProjectUpdateParams:
79
+ """Parameters for updating a project through ProjectCoordinator."""
80
+
81
+ project_id: str
82
+ updates: dict[str, Any] = field(default_factory=dict)