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,201 @@
1
+ """Milestone Operations Module - Handles all milestone-related CRUD operations.
2
+
3
+ This module encapsulates milestone management responsibilities extracted from RoadmapCore,
4
+ including creating, reading, updating, and deleting milestones, as well as milestone-related
5
+ queries and progress tracking.
6
+
7
+ Responsibilities:
8
+ - Milestone CRUD operations (create, list, get, update, delete)
9
+ - Milestone progress tracking
10
+ - Next milestone calculation
11
+ """
12
+
13
+ from datetime import datetime
14
+ from typing import Any
15
+
16
+ from roadmap.common.errors.error_standards import OperationType, safe_operation
17
+ from roadmap.common.logging import get_logger
18
+ from roadmap.core.domain import Milestone, MilestoneStatus
19
+ from roadmap.core.services import MilestoneService
20
+
21
+ logger = get_logger(__name__)
22
+
23
+
24
+ class MilestoneOperations:
25
+ """Manager for milestone-related operations."""
26
+
27
+ def __init__(self, milestone_service: MilestoneService):
28
+ """Initialize milestone operations manager.
29
+
30
+ Args:
31
+ milestone_service: The MilestoneService instance for database operations
32
+ """
33
+ self.milestone_service = milestone_service
34
+
35
+ @safe_operation(OperationType.CREATE, "Milestone", include_traceback=True)
36
+ def create_milestone(
37
+ self,
38
+ name: str,
39
+ headline: str = "",
40
+ due_date: datetime | None = None,
41
+ status: str | None = None,
42
+ ) -> Milestone:
43
+ """Create a new milestone.
44
+
45
+ Args:
46
+ name: Milestone name
47
+ headline: Milestone headline (short summary)
48
+ due_date: Due date for the milestone (optional)
49
+ status: Milestone status (optional, defaults to OPEN)
50
+
51
+ Returns:
52
+ Created Milestone object
53
+ """
54
+ logger.info(
55
+ "creating_milestone",
56
+ milestone_name=name,
57
+ has_headline=headline is not None,
58
+ has_due_date=due_date is not None,
59
+ status=status,
60
+ )
61
+ return self.milestone_service.create_milestone(
62
+ name=name, headline=headline, due_date=due_date, status=status
63
+ )
64
+
65
+ @safe_operation(OperationType.READ, "Milestone")
66
+ def list_milestones(self) -> list[Milestone]:
67
+ """List all milestones.
68
+
69
+ Returns:
70
+ List of Milestone objects
71
+ """
72
+ logger.info("listing_milestones")
73
+ return self.milestone_service.list_milestones()
74
+
75
+ @safe_operation(OperationType.READ, "Milestone")
76
+ def get_milestone(self, name: str) -> Milestone | None:
77
+ """Get a specific milestone by name.
78
+
79
+ Args:
80
+ name: Name of the milestone (searches by YAML name field, not filename)
81
+
82
+ Returns:
83
+ Milestone object if found, None otherwise
84
+ """
85
+ logger.info("getting_milestone", milestone_name=name)
86
+ return self.milestone_service.get_milestone(name)
87
+
88
+ @safe_operation(OperationType.DELETE, "Milestone", include_traceback=True)
89
+ def delete_milestone(self, name: str) -> bool:
90
+ """Delete a milestone and unassign all issues from it.
91
+
92
+ Args:
93
+ name: Name of the milestone to delete
94
+
95
+ Returns:
96
+ True if milestone was deleted, False if not found
97
+ """
98
+ logger.info("deleting_milestone", milestone_name=name)
99
+ return self.milestone_service.delete_milestone(name)
100
+
101
+ @safe_operation(OperationType.UPDATE, "Milestone")
102
+ def update_milestone(
103
+ self,
104
+ name: str,
105
+ headline: str | None = None,
106
+ due_date: datetime | None = None,
107
+ clear_due_date: bool = False,
108
+ status: str | None = None,
109
+ project_id: str | None = None,
110
+ ) -> bool:
111
+ """Update a milestone's properties.
112
+
113
+ Args:
114
+ name: Name of the milestone to update
115
+ headline: New headline (None to keep current)
116
+ due_date: New due date (None to keep current)
117
+ clear_due_date: If True, remove the due date
118
+ status: New status (None to keep current)
119
+ project_id: Project ID to assign milestone to
120
+
121
+ Returns:
122
+ True if milestone was updated, False if not found or error occurred
123
+ """
124
+ from roadmap.common.errors.exceptions import UpdateError
125
+
126
+ logger.info(
127
+ "updating_milestone",
128
+ milestone_name=name,
129
+ has_headline=headline is not None,
130
+ has_due_date=due_date is not None,
131
+ clear_due_date=clear_due_date,
132
+ has_status=status is not None,
133
+ has_project_id=project_id is not None,
134
+ )
135
+ try:
136
+ return (
137
+ self.milestone_service.update_milestone(
138
+ name=name,
139
+ headline=headline,
140
+ due_date=due_date,
141
+ clear_due_date=clear_due_date,
142
+ status=status,
143
+ project_id=project_id,
144
+ )
145
+ is not None
146
+ )
147
+ except UpdateError as e:
148
+ logger.error(
149
+ "milestone_update_failed",
150
+ name=name,
151
+ error=str(e),
152
+ severity="operational",
153
+ )
154
+ return False
155
+
156
+ @safe_operation(OperationType.READ, "Milestone")
157
+ def get_milestone_progress(self, milestone_name: str) -> dict[str, Any]:
158
+ """Get progress statistics for a milestone.
159
+
160
+ Args:
161
+ milestone_name: Name of the milestone
162
+
163
+ Returns:
164
+ Dictionary containing progress metrics (completed, total, percentage, etc.)
165
+ """
166
+ logger.info("getting_milestone_progress", milestone_name=milestone_name)
167
+ return self.milestone_service.get_milestone_progress(milestone_name)
168
+
169
+ def get_next_milestone(self) -> Milestone | None:
170
+ """Get the next upcoming milestone based on due date.
171
+
172
+ Returns:
173
+ The upcoming milestone with the earliest due date, or None if no upcoming milestones
174
+ """
175
+ milestones = self.list_milestones()
176
+
177
+ # Filter for open milestones with due dates
178
+ upcoming_milestones = [
179
+ m
180
+ for m in milestones
181
+ if m.status == MilestoneStatus.OPEN and m.due_date is not None
182
+ ]
183
+
184
+ if not upcoming_milestones:
185
+ return None
186
+
187
+ # Sort by due date and return the earliest
188
+ # Handle timezone-aware vs timezone-naive datetime comparison
189
+ def get_sortable_date(milestone: Milestone) -> datetime:
190
+ """Extract sortable date from milestone."""
191
+ due_date = milestone.due_date
192
+ # due_date should not be None since we filtered above, but be safe
193
+ if due_date is None:
194
+ return datetime.max # Put None dates at the end
195
+ # Convert timezone-aware dates to naive for comparison
196
+ if due_date.tzinfo is not None:
197
+ return due_date.replace(tzinfo=None)
198
+ return due_date
199
+
200
+ upcoming_milestones.sort(key=get_sortable_date)
201
+ return upcoming_milestones[0]
@@ -0,0 +1,113 @@
1
+ """Project Coordinator - Coordinates project-related operations.
2
+
3
+ Extracted from RoadmapCore to reduce god object complexity.
4
+ Provides a focused API for all project-related concerns.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from typing import TYPE_CHECKING
10
+
11
+ from roadmap.core.domain import Project
12
+ from roadmap.infrastructure.coordination.project_operations import ProjectOperations
13
+
14
+ if TYPE_CHECKING:
15
+ from roadmap.infrastructure.coordination.core import RoadmapCore
16
+
17
+
18
+ class ProjectCoordinator:
19
+ """Coordinates all project-related operations."""
20
+
21
+ def __init__(self, project_ops: ProjectOperations, core: RoadmapCore | None = None):
22
+ """Initialize coordinator with project operations manager.
23
+
24
+ Args:
25
+ project_ops: ProjectOperations instance
26
+ core: RoadmapCore instance for initialization checks
27
+ """
28
+ self._ops = project_ops
29
+ self._core = core
30
+
31
+ def list(self) -> list[Project]:
32
+ """List all projects."""
33
+ return self._ops.list_projects()
34
+
35
+ def get(self, project_id: str) -> Project | None:
36
+ """Get a specific project by ID or name.
37
+
38
+ Tries to find project by ID first, then by name as fallback.
39
+ """
40
+ # Try direct ID lookup first
41
+ project = self._ops.get_project(project_id)
42
+ if project:
43
+ return project
44
+
45
+ # Fallback: try to find by name
46
+ for project in self._ops.list_projects():
47
+ if project.name.lower() == project_id.lower():
48
+ return project
49
+
50
+ return None
51
+
52
+ def create(
53
+ self,
54
+ name: str,
55
+ headline: str = "",
56
+ milestones: list[str] | None = None,
57
+ status: str | None = None,
58
+ ) -> Project:
59
+ """Create a new project.
60
+
61
+ Args:
62
+ name: Project name
63
+ headline: Project headline (short summary)
64
+ milestones: List of milestone names (optional)
65
+ status: Project status (optional)
66
+
67
+ Returns:
68
+ Created Project object
69
+ """
70
+ return self._ops.create_project(
71
+ name=name,
72
+ headline=headline,
73
+ milestones=milestones or [],
74
+ status=status,
75
+ )
76
+
77
+ def save(self, project: Project) -> bool:
78
+ """Save an updated project to disk."""
79
+ return self._ops.save_project(project)
80
+
81
+ def update(self, project_id: str, **updates) -> Project | None:
82
+ """Update a project with the given fields.
83
+
84
+ Args:
85
+ project_id: Project identifier
86
+ **updates: Fields to update (name, description, status, priority, etc.)
87
+
88
+ Returns:
89
+ Updated Project object if successful, None if not found
90
+ """
91
+ return self._ops.update_project(project_id, **updates)
92
+
93
+ def delete(self, project_id: str) -> bool:
94
+ """Delete a project.
95
+
96
+ Args:
97
+ project_id: Project identifier
98
+
99
+ Returns:
100
+ True if deletion successful, False otherwise
101
+ """
102
+ return self._ops.delete_project(project_id)
103
+
104
+ def complete(self, project_id: str) -> Project | None:
105
+ """Mark a project as completed.
106
+
107
+ Args:
108
+ project_id: Project identifier
109
+
110
+ Returns:
111
+ Updated Project object if successful, None if not found
112
+ """
113
+ return self._ops.complete_project(project_id)
@@ -0,0 +1,144 @@
1
+ """Project Operations Module - Handles all project-related CRUD operations.
2
+
3
+ This module encapsulates project management responsibilities extracted from RoadmapCore,
4
+ including creating, reading, updating, and managing projects.
5
+
6
+ Responsibilities:
7
+ - Project CRUD operations (list, get, save, update)
8
+ """
9
+
10
+ from roadmap.common.errors.error_standards import OperationType, safe_operation
11
+ from roadmap.common.logging import get_logger
12
+ from roadmap.core.domain import Project
13
+ from roadmap.core.services import ProjectService
14
+
15
+ logger = get_logger(__name__)
16
+
17
+
18
+ class ProjectOperations:
19
+ """Manager for project-related operations."""
20
+
21
+ def __init__(self, project_service: ProjectService):
22
+ """Initialize project operations manager.
23
+
24
+ Args:
25
+ project_service: The ProjectService instance for database operations
26
+ """
27
+ self.project_service = project_service
28
+
29
+ @safe_operation(OperationType.READ, "Project")
30
+ def list_projects(self) -> list[Project]:
31
+ """List all projects.
32
+
33
+ Returns:
34
+ List of Project objects
35
+ """
36
+ logger.info("listing_projects")
37
+ return self.project_service.list_projects()
38
+
39
+ @safe_operation(OperationType.READ, "Project")
40
+ def get_project(self, project_id: str) -> Project | None:
41
+ """Get a specific project by ID.
42
+
43
+ Args:
44
+ project_id: The project ID to retrieve
45
+
46
+ Returns:
47
+ Project object if found, None otherwise
48
+ """
49
+ logger.info("getting_project", project_id=project_id)
50
+ return self.project_service.get_project(project_id)
51
+
52
+ @safe_operation(OperationType.CREATE, "Project", include_traceback=True)
53
+ def create_project(
54
+ self,
55
+ name: str,
56
+ headline: str = "",
57
+ milestones: list[str] | None = None,
58
+ status: str | None = None,
59
+ ) -> Project:
60
+ """Create a new project.
61
+
62
+ Args:
63
+ name: Project name
64
+ headline: Project headline (short summary)
65
+ milestones: List of milestone names (optional)
66
+ status: Project status (optional)
67
+
68
+ Returns:
69
+ Created Project object
70
+ """
71
+ logger.info(
72
+ "creating_project",
73
+ project_name=name,
74
+ has_headline=headline is not None,
75
+ milestone_count=len(milestones or []),
76
+ status=status,
77
+ )
78
+ return self.project_service.create_project(
79
+ name=name,
80
+ headline=headline,
81
+ milestones=milestones or [],
82
+ status=status,
83
+ )
84
+
85
+ @safe_operation(OperationType.UPDATE, "Project")
86
+ def save_project(self, project: Project) -> bool:
87
+ """Save an updated project to disk.
88
+
89
+ Args:
90
+ project: The Project object to save
91
+
92
+ Returns:
93
+ True if save successful, False otherwise
94
+ """
95
+ logger.info(
96
+ "saving_project",
97
+ project_id=project.id,
98
+ project_name=project.name,
99
+ )
100
+ return self.project_service.save_project(project)
101
+
102
+ @safe_operation(OperationType.UPDATE, "Project")
103
+ def update_project(self, project_id: str, **updates) -> Project | None:
104
+ """Update a project with the given fields.
105
+
106
+ Args:
107
+ project_id: Project identifier
108
+ **updates: Fields to update (name, description, status, priority, etc.)
109
+
110
+ Returns:
111
+ Updated Project object if successful, None if not found
112
+ """
113
+ logger.info(
114
+ "updating_project",
115
+ project_id=project_id,
116
+ update_fields=list(updates.keys()),
117
+ )
118
+ return self.project_service.update_project(project_id, **updates)
119
+
120
+ @safe_operation(OperationType.DELETE, "Project", include_traceback=True)
121
+ def delete_project(self, project_id: str) -> bool:
122
+ """Delete a project.
123
+
124
+ Args:
125
+ project_id: Project identifier
126
+
127
+ Returns:
128
+ True if deletion successful, False otherwise
129
+ """
130
+ logger.info("deleting_project", project_id=project_id)
131
+ return self.project_service.delete_project(project_id)
132
+
133
+ @safe_operation(OperationType.UPDATE, "Project")
134
+ def complete_project(self, project_id: str) -> Project | None:
135
+ """Mark a project as completed.
136
+
137
+ Args:
138
+ project_id: Project identifier
139
+
140
+ Returns:
141
+ Updated Project object if successful, None if not found
142
+ """
143
+ logger.info("completing_project", project_id=project_id)
144
+ return self.project_service.complete_project(project_id)
@@ -0,0 +1,107 @@
1
+ """Team Coordinator - Coordinates team and user-related operations.
2
+
3
+ Extracted from RoadmapCore to reduce god object complexity.
4
+ Provides a focused API for all team and user management concerns.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from typing import TYPE_CHECKING
10
+
11
+ from roadmap.common.errors.error_standards import OperationType, safe_operation
12
+ from roadmap.common.logging import get_logger
13
+ from roadmap.core.domain import Issue
14
+ from roadmap.infrastructure.coordination.user_operations import UserOperations
15
+
16
+ if TYPE_CHECKING:
17
+ from roadmap.infrastructure.coordination.core import RoadmapCore
18
+
19
+ logger = get_logger(__name__)
20
+
21
+
22
+ class TeamCoordinator:
23
+ """Coordinates all team and user-related operations."""
24
+
25
+ def __init__(self, user_ops: UserOperations, core: RoadmapCore | None = None):
26
+ """Initialize coordinator with user operations manager.
27
+
28
+ Args:
29
+ user_ops: UserOperations instance
30
+ core: RoadmapCore instance for initialization checks
31
+ """
32
+ self._ops = user_ops
33
+ self._core = core
34
+
35
+ @safe_operation(OperationType.READ, "Team")
36
+ def get_members(self) -> list[str]:
37
+ """Get team members from GitHub repository.
38
+
39
+ Returns:
40
+ List of usernames if GitHub is configured, empty list otherwise
41
+ """
42
+ logger.info("getting_team_members")
43
+ return self._ops.get_team_members()
44
+
45
+ @safe_operation(OperationType.READ, "User")
46
+ def get_current_user(self) -> str | None:
47
+ """Get the current user from config.
48
+
49
+ Returns:
50
+ Current user's name from config if set, None otherwise
51
+ """
52
+ logger.info("getting_current_user")
53
+ return self._ops.get_current_user()
54
+
55
+ @safe_operation(OperationType.READ, "Issue")
56
+ def get_assigned_issues(self, assignee: str) -> list[Issue]:
57
+ """Get all issues assigned to a specific user."""
58
+ logger.info("getting_assigned_issues", assignee=assignee)
59
+ return self._ops.get_assigned_issues(assignee)
60
+
61
+ @safe_operation(OperationType.READ, "Issue")
62
+ def get_my_issues(self) -> list[Issue]:
63
+ """Get all issues assigned to the current user."""
64
+ logger.info("getting_my_issues")
65
+ return self._ops.get_my_issues()
66
+
67
+ @safe_operation(OperationType.READ, "Issue")
68
+ def get_all_assigned_issues(self) -> dict[str, list[Issue]]:
69
+ """Get all issues grouped by assignee.
70
+
71
+ Returns:
72
+ Dictionary mapping assignee usernames to their assigned issues
73
+ """
74
+ logger.info("getting_all_assigned_issues")
75
+ return self._ops.get_all_assigned_issues()
76
+
77
+ @safe_operation(OperationType.READ, "Assignee")
78
+ def validate_assignee(self, assignee: str) -> tuple[bool, str]:
79
+ """Validate an assignee using the identity management system.
80
+
81
+ Args:
82
+ assignee: Username to validate
83
+
84
+ Returns:
85
+ Tuple of (is_valid, error_message)
86
+ """
87
+ logger.info("validating_assignee", assignee=assignee)
88
+ return self._ops.validate_assignee(assignee)
89
+
90
+ @safe_operation(OperationType.READ, "Assignee")
91
+ def get_canonical_assignee(self, assignee: str) -> str:
92
+ """Get the canonical form of an assignee name.
93
+
94
+ Args:
95
+ assignee: Input assignee name
96
+
97
+ Returns:
98
+ Canonical assignee name (may be same as input if no mapping exists)
99
+ """
100
+ logger.info("getting_canonical_assignee", assignee=assignee)
101
+ return self._ops.get_canonical_assignee(assignee)
102
+
103
+ @safe_operation(OperationType.READ, "Team")
104
+ def get_cached_team_members(self) -> list[str]:
105
+ """Get team members with caching (5 minute cache)."""
106
+ logger.info("getting_cached_team_members")
107
+ return self._ops.get_cached_team_members()