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,227 @@
1
+ """Health check result enhancement with details and recommendations.
2
+
3
+ This module provides infrastructure for enriching health check results with:
4
+ - Affected entities (which issues, milestones, etc. are affected)
5
+ - Fix recommendations (what can be done to resolve issues)
6
+ - Auto-fix commands (ready-to-run commands for common fixes)
7
+ """
8
+
9
+ from collections.abc import Mapping
10
+ from dataclasses import dataclass, field
11
+ from typing import Any
12
+
13
+ from roadmap.core.domain.health import HealthStatus
14
+
15
+
16
+ @dataclass
17
+ class HealthCheckDetail:
18
+ """Details about a specific health check result.
19
+
20
+ Attributes:
21
+ check_name: Name of the health check (e.g., "duplicate_issues")
22
+ status: Health status (HEALTHY, DEGRADED, UNHEALTHY)
23
+ message: Summary message about the check result
24
+ affected_items: List of affected entity IDs or names
25
+ recommendations: List of recommended fixes or actions
26
+ fix_commands: List of ready-to-run CLI commands that can fix the issue
27
+ """
28
+
29
+ check_name: str
30
+ status: HealthStatus
31
+ message: str
32
+ affected_items: list[str] = field(default_factory=list)
33
+ recommendations: list[str] = field(default_factory=list)
34
+ fix_commands: list[dict[str, str]] = field(default_factory=list)
35
+
36
+ def to_dict(self) -> dict[str, Any]:
37
+ """Convert to dictionary for JSON serialization."""
38
+ return {
39
+ "check_name": self.check_name,
40
+ "status": self.status.value.upper(),
41
+ "message": self.message,
42
+ "affected_items": self.affected_items,
43
+ "affected_count": len(self.affected_items),
44
+ "recommendations": self.recommendations,
45
+ "fix_commands": self.fix_commands,
46
+ }
47
+
48
+
49
+ class HealthCheckEnhancer:
50
+ """Enhances health check results with detailed information.
51
+
52
+ This service enriches basic health check results (status + message) with:
53
+ - Lists of affected entities
54
+ - Specific recommendations for fixes
55
+ - Ready-to-run CLI commands to fix issues
56
+
57
+ Works with both infrastructure and data quality checks.
58
+ """
59
+
60
+ def __init__(self, core=None):
61
+ """Initialize enhancer with optional core for entity lookups.
62
+
63
+ Args:
64
+ core: Optional core instance for accessing entities
65
+ """
66
+ self.core = core
67
+
68
+ def enhance_check_result(
69
+ self,
70
+ check_name: str,
71
+ status: HealthStatus,
72
+ message: str,
73
+ ) -> HealthCheckDetail:
74
+ """Enhance a health check result with details.
75
+
76
+ Args:
77
+ check_name: Name of the health check
78
+ status: Health status from the check
79
+ message: Message from the check
80
+
81
+ Returns:
82
+ HealthCheckDetail with enhanced information
83
+ """
84
+ detail = HealthCheckDetail(
85
+ check_name=check_name,
86
+ status=status,
87
+ message=message,
88
+ )
89
+
90
+ # Route to check-specific enhancement
91
+ if check_name == "duplicate_issues":
92
+ self._enhance_duplicate_issues(detail)
93
+ elif check_name == "orphaned_issues":
94
+ self._enhance_orphaned_issues(detail)
95
+ elif check_name == "old_backups":
96
+ self._enhance_old_backups(detail)
97
+ elif check_name == "folder_structure":
98
+ self._enhance_folder_structure(detail)
99
+ elif check_name == "comment_integrity":
100
+ self._enhance_comment_integrity(detail)
101
+ else:
102
+ # Generic enhancement for other checks
103
+ self._enhance_generic(detail)
104
+
105
+ return detail
106
+
107
+ def _enhance_duplicate_issues(self, detail: HealthCheckDetail) -> None:
108
+ """Add details for duplicate_issues check."""
109
+ detail.recommendations = [
110
+ "Review issues with identical titles and status",
111
+ "Merge duplicates, keeping the older issue as primary",
112
+ "Close/delete the newer duplicate issue",
113
+ ]
114
+ detail.fix_commands = [
115
+ {
116
+ "command": "roadmap health fix --fix-type duplicate_issues --dry-run",
117
+ "description": "Preview duplicate issues that can be fixed",
118
+ },
119
+ {
120
+ "command": "roadmap health fix --fix-type duplicate_issues",
121
+ "description": "Automatically fix duplicate issues (requires review)",
122
+ },
123
+ ]
124
+
125
+ def _enhance_orphaned_issues(self, detail: HealthCheckDetail) -> None:
126
+ """Add details for orphaned_issues check."""
127
+ detail.recommendations = [
128
+ "Assign issues without milestones to 'Backlog'",
129
+ "Review issues to ensure correct milestone assignment",
130
+ "Use 'roadmap issue assign' to move to correct milestone",
131
+ ]
132
+ detail.fix_commands = [
133
+ {
134
+ "command": "roadmap health fix --fix-type orphaned_issues --dry-run",
135
+ "description": "Preview issues to be assigned to Backlog",
136
+ },
137
+ {
138
+ "command": "roadmap health fix --fix-type orphaned_issues",
139
+ "description": "Automatically assign orphaned issues to Backlog",
140
+ },
141
+ ]
142
+
143
+ def _enhance_old_backups(self, detail: HealthCheckDetail) -> None:
144
+ """Add details for old_backups check."""
145
+ detail.recommendations = [
146
+ "Delete backup files older than 90 days to save storage",
147
+ "Review archived backups to ensure data is safely stored",
148
+ "Consider moving very old backups to external storage",
149
+ ]
150
+ detail.fix_commands = [
151
+ {
152
+ "command": "roadmap health fix --fix-type old_backups --dry-run",
153
+ "description": "Preview old backups that can be deleted",
154
+ },
155
+ {
156
+ "command": "roadmap health fix --fix-type old_backups",
157
+ "description": "Delete old backup files (>90 days)",
158
+ },
159
+ ]
160
+
161
+ def _enhance_folder_structure(self, detail: HealthCheckDetail) -> None:
162
+ """Add details for folder_structure check."""
163
+ detail.recommendations = [
164
+ "Move issues to their correct milestone folders",
165
+ "Verify milestone folder organization matches issue assignments",
166
+ "Use 'roadmap issue move' to reorganize structure",
167
+ ]
168
+ detail.fix_commands = [
169
+ {
170
+ "command": "roadmap health fix --fix-type folder_structure --dry-run",
171
+ "description": "Preview folder structure corrections",
172
+ },
173
+ {
174
+ "command": "roadmap health fix --fix-type folder_structure",
175
+ "description": "Automatically fix folder structure issues",
176
+ },
177
+ ]
178
+
179
+ def _enhance_comment_integrity(self, detail: HealthCheckDetail) -> None:
180
+ """Add details for comment_integrity check."""
181
+ detail.recommendations = [
182
+ "Review and sanitize malformed JSON in comments",
183
+ "Check for corrupted comment threads",
184
+ "Manually edit comments with formatting issues",
185
+ ]
186
+ detail.fix_commands = [
187
+ {
188
+ "command": "roadmap health fix --fix-type corrupted_comments --dry-run",
189
+ "description": "Preview comments that can be sanitized",
190
+ },
191
+ {
192
+ "command": "roadmap health fix --fix-type corrupted_comments",
193
+ "description": "Automatically sanitize malformed comments (review first)",
194
+ },
195
+ ]
196
+
197
+ def _enhance_generic(self, detail: HealthCheckDetail) -> None:
198
+ """Enhance check with generic recommendations."""
199
+ if detail.status == HealthStatus.HEALTHY:
200
+ detail.recommendations = ["No action needed"]
201
+ elif detail.status == HealthStatus.DEGRADED:
202
+ detail.recommendations = [
203
+ "Monitor this check in future health reports",
204
+ "Take action when status becomes UNHEALTHY",
205
+ ]
206
+ else: # UNHEALTHY
207
+ detail.recommendations = [
208
+ "Investigate the root cause immediately",
209
+ "Review the detailed message for specific guidance",
210
+ "Use 'roadmap health scan' for entity-level diagnostics",
211
+ ]
212
+
213
+ def enhance_all_checks(
214
+ self, checks: Mapping[str, tuple[HealthStatus, str]]
215
+ ) -> dict[str, HealthCheckDetail]:
216
+ """Enhance all health check results.
217
+
218
+ Args:
219
+ checks: Dict mapping check names to (status, message) tuples
220
+
221
+ Returns:
222
+ Dict mapping check names to HealthCheckDetail objects
223
+ """
224
+ return {
225
+ check_name: self.enhance_check_result(check_name, status, message)
226
+ for check_name, (status, message) in checks.items()
227
+ }
@@ -0,0 +1,295 @@
1
+ """Health check fixer orchestrator and base infrastructure.
2
+
3
+ Provides framework for automatically fixing detected health issues with:
4
+ - Safe/review categorization
5
+ - Dry-run preview mode (default)
6
+ - Rollback capability tracking
7
+ - Detailed fix result reporting
8
+ """
9
+
10
+ from abc import ABC, abstractmethod
11
+ from dataclasses import dataclass, field
12
+ from enum import Enum
13
+ from typing import Any
14
+
15
+
16
+ class FixSafety(Enum):
17
+ """Safety level for a fixer.
18
+
19
+ SAFE: Can be applied automatically without human review
20
+ REVIEW: Requires human review before applying
21
+ """
22
+
23
+ SAFE = "safe"
24
+ REVIEW = "review"
25
+
26
+
27
+ @dataclass
28
+ class FixResult:
29
+ """Result of a fix operation.
30
+
31
+ Attributes:
32
+ fix_type: Type of fix that was applied
33
+ success: Whether the fix succeeded
34
+ dry_run: Whether this was a dry-run
35
+ message: Description of what was fixed
36
+ affected_items: IDs or names of affected entities
37
+ items_count: Number of items affected
38
+ changes_made: Number of changes actually made
39
+ rollback_info: Information for rolling back (if applicable)
40
+ """
41
+
42
+ fix_type: str
43
+ success: bool
44
+ dry_run: bool
45
+ message: str
46
+ affected_items: list[str] = field(default_factory=list)
47
+ items_count: int = 0
48
+ changes_made: int = 0
49
+ rollback_info: dict[str, Any] | None = None
50
+
51
+ def to_dict(self) -> dict[str, Any]:
52
+ """Convert to dictionary for JSON serialization."""
53
+ return {
54
+ "fix_type": self.fix_type,
55
+ "success": self.success,
56
+ "dry_run": self.dry_run,
57
+ "message": self.message,
58
+ "affected_items": self.affected_items,
59
+ "items_count": self.items_count,
60
+ "changes_made": self.changes_made,
61
+ "has_rollback": self.rollback_info is not None,
62
+ }
63
+
64
+
65
+ class HealthFixer(ABC):
66
+ """Abstract base class for health check fixers.
67
+
68
+ Each fixer handles a specific type of health issue:
69
+ - old_backups: Delete old backup files
70
+ - duplicate_issues: Merge duplicate issues
71
+ - orphaned_issues: Assign unassigned issues to Backlog
72
+ - folder_structure: Move issues to correct milestone folders
73
+ - corrupted_comments: Sanitize malformed JSON comments
74
+ """
75
+
76
+ def __init__(self, core):
77
+ """Initialize fixer with core instance.
78
+
79
+ Args:
80
+ core: Core application instance
81
+ """
82
+ self.core = core
83
+
84
+ @property
85
+ @abstractmethod
86
+ def fix_type(self) -> str:
87
+ """Identifier for this fixer (e.g., 'duplicate_issues')."""
88
+ pass
89
+
90
+ @property
91
+ @abstractmethod
92
+ def safety_level(self) -> FixSafety:
93
+ """Safety level: SAFE or REVIEW."""
94
+ pass
95
+
96
+ @property
97
+ @abstractmethod
98
+ def description(self) -> str:
99
+ """Human-readable description of what this fixer does."""
100
+ pass
101
+
102
+ @abstractmethod
103
+ def scan(self) -> dict[str, Any]:
104
+ """Scan for issues that can be fixed.
105
+
106
+ Returns:
107
+ Dict with:
108
+ - found: bool (whether issues were found)
109
+ - count: int (number of issues found)
110
+ - message: str (description)
111
+ - details: list (specific issues found)
112
+ """
113
+ pass
114
+
115
+ @abstractmethod
116
+ def dry_run(self) -> FixResult:
117
+ """Preview what would be fixed without making changes.
118
+
119
+ Returns:
120
+ FixResult with dry_run=True
121
+ """
122
+ pass
123
+
124
+ @abstractmethod
125
+ def apply(self, force: bool = False) -> FixResult:
126
+ """Apply the fix (actually make changes).
127
+
128
+ Args:
129
+ force: If True, apply without prompts
130
+
131
+ Returns:
132
+ FixResult with dry_run=False
133
+ """
134
+ pass
135
+
136
+ def confirm_apply(self, dry_run_result: FixResult) -> bool:
137
+ """Ask user to confirm applying a fix.
138
+
139
+ For SAFE fixes, this can auto-approve.
140
+ For REVIEW fixes, user must manually confirm.
141
+
142
+ Args:
143
+ dry_run_result: Result from dry_run()
144
+
145
+ Returns:
146
+ True if user confirms, False otherwise
147
+ """
148
+ if self.safety_level == FixSafety.SAFE:
149
+ return True
150
+
151
+ # REVIEW fixes require user confirmation
152
+ import click
153
+
154
+ message = f"\nApply {self.fix_type}? {dry_run_result.message}"
155
+ return click.confirm(message, default=False)
156
+
157
+
158
+ class HealthFixOrchestrator:
159
+ """Orchestrates health fixes across all available fixers.
160
+
161
+ Handles:
162
+ - Loading all available fixers
163
+ - Running dry-run previews
164
+ - Applying fixes with proper safety checks
165
+ - Collecting results
166
+ """
167
+
168
+ def __init__(self, core):
169
+ """Initialize orchestrator.
170
+
171
+ Args:
172
+ core: Core application instance
173
+ """
174
+ self.core = core
175
+ self._fixers: dict[str, HealthFixer] = {}
176
+ self._load_fixers()
177
+
178
+ def _load_fixers(self) -> None:
179
+ """Load all available fixers."""
180
+ from roadmap.adapters.cli.health.fixers.corrupted_comments_fixer import (
181
+ CorruptedCommentsFixer,
182
+ )
183
+ from roadmap.adapters.cli.health.fixers.data_integrity_fixer import (
184
+ DataIntegrityFixer,
185
+ )
186
+ from roadmap.adapters.cli.health.fixers.duplicate_issues_fixer import (
187
+ DuplicateIssuesFixer,
188
+ )
189
+ from roadmap.adapters.cli.health.fixers.folder_structure_fixer import (
190
+ FolderStructureFixer,
191
+ )
192
+ from roadmap.adapters.cli.health.fixers.label_normalization_fixer import (
193
+ LabelNormalizationFixer,
194
+ )
195
+ from roadmap.adapters.cli.health.fixers.milestone_name_normalization_fixer import (
196
+ MilestoneNameNormalizationFixer,
197
+ )
198
+ from roadmap.adapters.cli.health.fixers.milestone_naming_compliance_fixer import (
199
+ MilestoneNamingComplianceFixer,
200
+ )
201
+ from roadmap.adapters.cli.health.fixers.milestone_parse_error_fixer import (
202
+ MilestoneParseErrorFixer,
203
+ )
204
+ from roadmap.adapters.cli.health.fixers.milestone_validation_fixer import (
205
+ MilestoneValidationFixer,
206
+ )
207
+ from roadmap.adapters.cli.health.fixers.old_backups_fixer import (
208
+ OldBackupsFixer,
209
+ )
210
+ from roadmap.adapters.cli.health.fixers.orphaned_issues_fixer import (
211
+ OrphanedIssuesFixer,
212
+ )
213
+
214
+ fixers = [
215
+ OldBackupsFixer(self.core),
216
+ DuplicateIssuesFixer(self.core),
217
+ OrphanedIssuesFixer(self.core),
218
+ FolderStructureFixer(self.core),
219
+ CorruptedCommentsFixer(self.core),
220
+ DataIntegrityFixer(self.core),
221
+ LabelNormalizationFixer(self.core),
222
+ MilestoneNameNormalizationFixer(self.core),
223
+ MilestoneNamingComplianceFixer(self.core),
224
+ MilestoneValidationFixer(self.core),
225
+ MilestoneParseErrorFixer(self.core),
226
+ ]
227
+
228
+ for fixer in fixers:
229
+ self._fixers[fixer.fix_type] = fixer
230
+
231
+ def get_fixers(self) -> dict[str, HealthFixer]:
232
+ """Get all available fixers.
233
+
234
+ Returns:
235
+ Dict mapping fix_type to HealthFixer instance
236
+ """
237
+ return self._fixers.copy()
238
+
239
+ def get_fixer(self, fix_type: str) -> HealthFixer | None:
240
+ """Get a specific fixer by type.
241
+
242
+ Args:
243
+ fix_type: The fix type identifier
244
+
245
+ Returns:
246
+ HealthFixer instance or None if not found
247
+ """
248
+ return self._fixers.get(fix_type)
249
+
250
+ def scan_all(self) -> dict[str, dict[str, Any]]:
251
+ """Scan for all fixable issues.
252
+
253
+ Returns:
254
+ Dict mapping fix_type to scan results
255
+ """
256
+ results = {}
257
+ for fix_type, fixer in self._fixers.items():
258
+ results[fix_type] = fixer.scan()
259
+ return results
260
+
261
+ def dry_run_fix(self, fix_type: str) -> FixResult | None:
262
+ """Preview a specific fix.
263
+
264
+ Args:
265
+ fix_type: Which fix to preview
266
+
267
+ Returns:
268
+ FixResult or None if fixer not found
269
+ """
270
+ fixer = self.get_fixer(fix_type)
271
+ if not fixer:
272
+ return None
273
+ return fixer.dry_run()
274
+
275
+ def apply_fix(self, fix_type: str, force: bool = False) -> FixResult | None:
276
+ """Apply a specific fix.
277
+
278
+ Args:
279
+ fix_type: Which fix to apply
280
+ force: If True, apply without confirmation
281
+
282
+ Returns:
283
+ FixResult or None if fixer not found
284
+ """
285
+ fixer = self.get_fixer(fix_type)
286
+ if not fixer:
287
+ return None
288
+
289
+ # For review fixes, confirm first
290
+ if not force and fixer.safety_level == FixSafety.REVIEW:
291
+ dry_result = fixer.dry_run()
292
+ if not fixer.confirm_apply(dry_result):
293
+ return None
294
+
295
+ return fixer.apply(force=force)
@@ -0,0 +1,10 @@
1
+ """Health check fixers for automatically correcting detected issues.
2
+
3
+ Available fixers:
4
+ - OldBackupsFixer: Delete old backup files (>90 days)
5
+ - DuplicateIssuesFixer: Merge duplicate issues
6
+ - OrphanedIssuesFixer: Assign unassigned issues to Backlog
7
+ - FolderStructureFixer: Move issues to correct milestone folders
8
+ - CorruptedCommentsFixer: Sanitize malformed JSON comments
9
+ - DataIntegrityFixer: Remove malformed issue files
10
+ """