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,146 @@
1
+ """Service for detecting project context from git and file system."""
2
+
3
+ import json
4
+ import re
5
+ import subprocess
6
+ from pathlib import Path
7
+
8
+ import structlog
9
+
10
+ logger = structlog.get_logger()
11
+
12
+
13
+ class ProjectContextDetectionService:
14
+ """Service for detecting project context from git and file system."""
15
+
16
+ @staticmethod
17
+ def detect_project_context() -> dict:
18
+ """Detect project context from git repository and directory structure.
19
+
20
+ Returns:
21
+ Dictionary with detected context:
22
+ - git_repo: Repository in owner/repo format if detected
23
+ - project_name: Project name from git, package files, or directory
24
+ - git_user: Git user name if available
25
+ - has_git: Whether in a git repository
26
+ """
27
+ context = {
28
+ "git_repo": None,
29
+ "project_name": None,
30
+ "git_user": None,
31
+ "has_git": False,
32
+ }
33
+
34
+ try:
35
+ # Check if we're in a git repository
36
+ git_check = subprocess.run(
37
+ ["git", "rev-parse", "--is-inside-work-tree"],
38
+ capture_output=True,
39
+ text=True,
40
+ timeout=5,
41
+ )
42
+ context["has_git"] = git_check.returncode == 0
43
+
44
+ if context["has_git"]:
45
+ ProjectContextDetectionService._detect_git_repo(context)
46
+ ProjectContextDetectionService._detect_git_user(context)
47
+
48
+ except (
49
+ subprocess.TimeoutExpired,
50
+ subprocess.CalledProcessError,
51
+ FileNotFoundError,
52
+ ):
53
+ pass
54
+
55
+ # Fallback to directory name if no git repo detected
56
+ if not context["project_name"]:
57
+ context["project_name"] = Path.cwd().name
58
+
59
+ # Try to detect from package files
60
+ if not context["project_name"] or context["project_name"] == ".":
61
+ ProjectContextDetectionService._detect_from_package_files(context)
62
+
63
+ return context
64
+
65
+ @staticmethod
66
+ def _detect_git_repo(context: dict) -> None:
67
+ """Detect git repository and populate context."""
68
+ try:
69
+ result = subprocess.run(
70
+ ["git", "remote", "get-url", "origin"],
71
+ capture_output=True,
72
+ text=True,
73
+ timeout=5,
74
+ )
75
+ if result.returncode == 0:
76
+ origin_url = result.stdout.strip()
77
+ # Parse GitHub repository from URL
78
+ if "github.com" in origin_url:
79
+ # Handle both SSH and HTTPS URLs
80
+ if origin_url.startswith("git@github.com:"):
81
+ repo_part = origin_url.replace("git@github.com:", "").replace(
82
+ ".git", ""
83
+ )
84
+ elif "github.com/" in origin_url:
85
+ repo_part = origin_url.split("github.com/")[1].replace(
86
+ ".git", ""
87
+ )
88
+ else:
89
+ repo_part = None
90
+
91
+ if repo_part and "/" in repo_part:
92
+ context["git_repo"] = repo_part
93
+ context["project_name"] = repo_part.split("/")[1]
94
+ except Exception as e:
95
+ logger.debug(
96
+ "git_context_detection_failed",
97
+ operation="detect_git_context",
98
+ error=str(e),
99
+ action="Continuing with partial context",
100
+ )
101
+
102
+ @staticmethod
103
+ def _detect_git_user(context: dict) -> None:
104
+ """Detect git user name and populate context."""
105
+ try:
106
+ user_result = subprocess.run(
107
+ ["git", "config", "user.name"],
108
+ capture_output=True,
109
+ text=True,
110
+ timeout=5,
111
+ )
112
+ if user_result.returncode == 0:
113
+ context["git_user"] = user_result.stdout.strip()
114
+ except Exception as e:
115
+ logger.debug(
116
+ "git_user_detection_failed",
117
+ operation="detect_git_user",
118
+ error=str(e),
119
+ action="Skipping git user detection",
120
+ )
121
+
122
+ @staticmethod
123
+ def _detect_from_package_files(context: dict) -> None:
124
+ """Try to detect project name from package files."""
125
+ for config_file in ["pyproject.toml", "package.json", "Cargo.toml"]:
126
+ if Path(config_file).exists():
127
+ try:
128
+ content = Path(config_file).read_text()
129
+ if config_file == "pyproject.toml":
130
+ match = re.search(r'name\s*=\s*["\']([^"\']+)["\']', content)
131
+ if match:
132
+ context["project_name"] = match.group(1)
133
+ break
134
+ elif config_file == "package.json":
135
+ data = json.loads(content)
136
+ if "name" in data:
137
+ context["project_name"] = data["name"]
138
+ break
139
+ except Exception as e:
140
+ logger.debug(
141
+ "package_file_parse_failed",
142
+ operation="parse_package_file",
143
+ file=config_file,
144
+ error=str(e),
145
+ action="Trying next config file",
146
+ )
@@ -0,0 +1,76 @@
1
+ """Service for creating projects."""
2
+
3
+ import uuid
4
+
5
+ from roadmap.common.logging import get_logger
6
+ from roadmap.core.services.project_init.template import ProjectTemplateService
7
+ from roadmap.infrastructure.coordination.core import RoadmapCore
8
+
9
+ logger = get_logger(__name__)
10
+
11
+
12
+ class ProjectCreationService:
13
+ """Service for creating projects."""
14
+
15
+ @staticmethod
16
+ def create_project(
17
+ core: RoadmapCore,
18
+ project_name: str,
19
+ description: str,
20
+ detected_info: dict,
21
+ template: str,
22
+ template_path: str | None = None,
23
+ ) -> dict | None:
24
+ """Create a new project with given parameters.
25
+
26
+ Args:
27
+ core: RoadmapCore instance
28
+ project_name: Name of the project
29
+ description: Project description
30
+ detected_info: Detected project context
31
+ template: Template type to use
32
+ template_path: Optional path to custom template
33
+
34
+ Returns:
35
+ Dictionary with project info (id, name, filename) or None if failed
36
+ """
37
+ try:
38
+ # Generate or load project content
39
+ if template_path:
40
+ project_content = ProjectTemplateService.load_custom_template(
41
+ template_path
42
+ )
43
+ if not project_content:
44
+ project_content = ProjectTemplateService.generate_project_template(
45
+ project_name, description, template, detected_info
46
+ )
47
+ else:
48
+ project_content = ProjectTemplateService.generate_project_template(
49
+ project_name, description, template, detected_info
50
+ )
51
+
52
+ # Save project file
53
+ project_id = str(uuid.uuid4())[:8]
54
+ project_filename = (
55
+ f"{project_id}-{project_name.lower().replace(' ', '-')}.md"
56
+ )
57
+ project_file = core.roadmap_dir / "projects" / project_filename
58
+
59
+ # Ensure projects directory exists
60
+ (core.roadmap_dir / "projects").mkdir(parents=True, exist_ok=True)
61
+
62
+ project_file.write_text(project_content)
63
+
64
+ return {
65
+ "id": project_id,
66
+ "name": project_name,
67
+ "filename": project_filename,
68
+ }
69
+
70
+ except Exception as e:
71
+ logger.error(
72
+ "project_creation_failed",
73
+ error=str(e),
74
+ severity="system_error",
75
+ )
76
+ return None
@@ -0,0 +1,51 @@
1
+ """Service for detecting and analyzing existing projects."""
2
+
3
+ from pathlib import Path
4
+
5
+ import structlog
6
+
7
+ from roadmap.infrastructure.persistence_gateway import PersistenceGateway
8
+
9
+ logger = structlog.get_logger()
10
+
11
+
12
+ class ProjectDetectionService:
13
+ """Service for detecting and analyzing existing projects."""
14
+
15
+ @staticmethod
16
+ def detect_existing_projects(projects_dir: Path) -> list[dict]:
17
+ """Detect existing projects in the projects directory.
18
+
19
+ Args:
20
+ projects_dir: Path to the projects directory
21
+
22
+ Returns:
23
+ List of dicts with 'name', 'id', and 'file' for each existing project
24
+ """
25
+ existing_projects = []
26
+
27
+ if not projects_dir.exists():
28
+ return existing_projects
29
+
30
+ for project_file in projects_dir.glob("*.md"):
31
+ try:
32
+ project = PersistenceGateway.parse_project_file(project_file)
33
+ existing_projects.append(
34
+ {
35
+ "name": project.name,
36
+ "id": project.id,
37
+ "file": project_file.name,
38
+ }
39
+ )
40
+ except Exception as e:
41
+ logger.debug(
42
+ "project_parse_failed",
43
+ operation="parse_project",
44
+ file=project_file.name,
45
+ error=str(e),
46
+ action="Skipping project",
47
+ )
48
+ # Skip projects that can't be parsed
49
+ continue
50
+
51
+ return existing_projects
@@ -0,0 +1,228 @@
1
+ """Service for generating project templates."""
2
+
3
+ import getpass
4
+ from datetime import UTC, datetime
5
+ from pathlib import Path
6
+
7
+ import structlog
8
+
9
+ logger = structlog.get_logger()
10
+
11
+
12
+ class ProjectTemplateService:
13
+ """Service for generating project templates."""
14
+
15
+ # Template snippets for different types
16
+ SOFTWARE_TEMPLATE = """
17
+ - [ ] Develop core functionality
18
+ - [ ] Implement user interface
19
+ - [ ] Write comprehensive tests
20
+ - [ ] Deploy to production
21
+ - [ ] Document API and usage
22
+
23
+ ## Technical Stack
24
+
25
+ - **Language**: Python
26
+ - **Framework**: TBD
27
+ - **Database**: TBD
28
+ - **Deployment**: TBD
29
+
30
+ ## Development Phases
31
+
32
+ ### Phase 1: Foundation
33
+ - Project setup and architecture
34
+ - Core functionality implementation
35
+ - Basic testing framework
36
+
37
+ ### Phase 2: Features
38
+ - Feature development
39
+ - User interface implementation
40
+ - Integration testing
41
+
42
+ ### Phase 3: Polish
43
+ - Performance optimization
44
+ - Documentation
45
+ - Production deployment
46
+ """
47
+
48
+ RESEARCH_TEMPLATE = """
49
+ - [ ] Literature review
50
+ - [ ] Hypothesis formation
51
+ - [ ] Methodology design
52
+ - [ ] Data collection
53
+ - [ ] Analysis and findings
54
+ - [ ] Publication preparation
55
+
56
+ ## Research Questions
57
+
58
+ 1. [Primary research question]
59
+ 2. [Secondary research questions]
60
+
61
+ ## Methodology
62
+
63
+ [Research methodology and approach]
64
+
65
+ ## Timeline
66
+
67
+ - **Phase 1**: Literature review (4 weeks)
68
+ - **Phase 2**: Data collection (8 weeks)
69
+ - **Phase 3**: Analysis (4 weeks)
70
+ - **Phase 4**: Writing (4 weeks)
71
+ """
72
+
73
+ TEAM_TEMPLATE = """
74
+ - [ ] Team onboarding
75
+ - [ ] Process documentation
76
+ - [ ] Workflow optimization
77
+ - [ ] Knowledge sharing
78
+ - [ ] Regular retrospectives
79
+
80
+ ## Team Structure
81
+
82
+ - **Project Lead**: [Name]
83
+ - **Development Team**: [Names]
84
+ - **Stakeholders**: [Names]
85
+
86
+ ## Communication
87
+
88
+ - **Daily Standups**: [Time/Location]
89
+ - **Sprint Planning**: [Schedule]
90
+ - **Retrospectives**: [Schedule]
91
+
92
+ ## Processes
93
+
94
+ ### Development Workflow
95
+ 1. Issue creation and planning
96
+ 2. Feature branch development
97
+ 3. Code review process
98
+ 4. Testing and validation
99
+ 5. Deployment and monitoring
100
+ """
101
+
102
+ BASIC_TEMPLATE = """
103
+ - [ ] Define project scope
104
+ - [ ] Create initial roadmap
105
+ - [ ] Begin implementation
106
+ - [ ] Regular progress reviews
107
+ - [ ] Project completion
108
+
109
+ ## Milestones
110
+
111
+ ### Milestone 1: Setup
112
+ - Initial project structure
113
+ - Team alignment on goals
114
+
115
+ ### Milestone 2: Development
116
+ - Core functionality implementation
117
+ - Regular progress tracking
118
+
119
+ ### Milestone 3: Completion
120
+ - Final deliverables
121
+ - Project retrospective
122
+ """
123
+
124
+ TEMPLATE_FOOTER = """
125
+
126
+ ## Resources
127
+
128
+ - [Link to documentation]
129
+ - [Link to repository]
130
+ - [Link to project tools]
131
+
132
+ ## Notes
133
+
134
+ [Additional project notes and context]
135
+ """
136
+
137
+ @staticmethod
138
+ def generate_project_template(
139
+ project_name: str, description: str, template: str, detected_info: dict
140
+ ) -> str:
141
+ """Generate project content based on template.
142
+
143
+ Args:
144
+ project_name: Name of the project
145
+ description: Project description
146
+ template: Template type (basic, software, research, team)
147
+ detected_info: Detected project context
148
+
149
+ Returns:
150
+ Project content as markdown string
151
+ """
152
+ current_date = datetime.now(UTC).isoformat()
153
+ owner = detected_info.get("git_user", getpass.getuser())
154
+
155
+ # Base project content
156
+ content = f"""---
157
+ name: {project_name}
158
+ description: {description}
159
+ owner: {owner}
160
+ priority: high
161
+ status: active
162
+ created: {current_date}
163
+ updated: {current_date}
164
+ """
165
+
166
+ if detected_info.get("git_repo"):
167
+ content += f"github_repo: {detected_info['git_repo']}\n"
168
+
169
+ content += (
170
+ """timeline:
171
+ start_date: """
172
+ + current_date
173
+ + """
174
+ target_end_date: null
175
+ tags: []
176
+ ---
177
+
178
+ # """
179
+ + project_name
180
+ + """
181
+
182
+ ## Overview
183
+
184
+ """
185
+ + description
186
+ + """
187
+
188
+ ## Project Goals
189
+
190
+ """
191
+ )
192
+
193
+ # Template-specific content
194
+ if template == "software":
195
+ content += ProjectTemplateService.SOFTWARE_TEMPLATE
196
+ elif template == "research":
197
+ content += ProjectTemplateService.RESEARCH_TEMPLATE
198
+ elif template == "team":
199
+ content += ProjectTemplateService.TEAM_TEMPLATE
200
+ else: # basic
201
+ content += ProjectTemplateService.BASIC_TEMPLATE
202
+
203
+ content += ProjectTemplateService.TEMPLATE_FOOTER
204
+ return content
205
+
206
+ @staticmethod
207
+ def load_custom_template(template_path: str) -> str | None:
208
+ """Load custom template from file.
209
+
210
+ Args:
211
+ template_path: Path to template file
212
+
213
+ Returns:
214
+ Template content if valid, None otherwise
215
+ """
216
+ try:
217
+ tpl_path = Path(template_path)
218
+ if tpl_path.exists() and tpl_path.is_file():
219
+ return tpl_path.read_text()
220
+ except Exception as e:
221
+ logger.debug(
222
+ "template_load_failed",
223
+ operation="load_template",
224
+ template_path=str(template_path),
225
+ error=str(e),
226
+ action="Returning None",
227
+ )
228
+ return None
@@ -0,0 +1,88 @@
1
+ """Status change parsing and extraction service for sync operations.
2
+
3
+ This service provides utilities for parsing and extracting information from
4
+ status change strings in the format "old_status -> new_status".
5
+ """
6
+
7
+ from typing import Any
8
+
9
+
10
+ def parse_status_change(change_str: str) -> str | None:
11
+ """Parse and validate change string in format 'old -> new'.
12
+
13
+ Args:
14
+ change_str: Change string in format "old -> new"
15
+
16
+ Returns:
17
+ The new status string (stripped), or None if format is invalid
18
+ """
19
+ if not isinstance(change_str, str) or " -> " not in change_str:
20
+ return None
21
+
22
+ try:
23
+ parts = change_str.split(" -> ")
24
+ if len(parts) != 2:
25
+ return None
26
+ return parts[1].strip()
27
+ except (IndexError, AttributeError):
28
+ return None
29
+
30
+
31
+ def extract_issue_status_update(
32
+ status_change: str,
33
+ ) -> dict[str, Any] | None:
34
+ """Extract and validate issue status update from change string.
35
+
36
+ Args:
37
+ status_change: Change string in format "old -> new"
38
+
39
+ Returns:
40
+ Dict with 'github_state' and 'status_enum', or None if invalid
41
+ """
42
+ from roadmap.common.constants import Status
43
+
44
+ new_status = parse_status_change(status_change)
45
+ if new_status is None:
46
+ return None
47
+
48
+ try:
49
+ # Validate that it's a valid status
50
+ status_enum = Status(new_status)
51
+ # Map local status to GitHub state (closed -> closed, others -> open)
52
+ github_state = "closed" if new_status == Status.CLOSED.value else "open"
53
+ return {
54
+ "github_state": github_state,
55
+ "status_enum": status_enum,
56
+ }
57
+ except (ValueError, KeyError):
58
+ # Invalid status - skip the update
59
+ return None
60
+
61
+
62
+ def extract_milestone_status_update(
63
+ status_change: str,
64
+ ) -> dict[str, Any] | None:
65
+ """Extract and validate milestone status update from change string.
66
+
67
+ Args:
68
+ status_change: Change string in format "old -> new"
69
+
70
+ Returns:
71
+ Dict with 'github_state' and 'status_enum', or None if invalid
72
+ """
73
+ from roadmap.common.constants import MilestoneStatus
74
+
75
+ new_status = parse_status_change(status_change)
76
+ if new_status is None:
77
+ return None
78
+
79
+ github_state = "closed" if new_status == "closed" else "open"
80
+
81
+ try:
82
+ status_enum = MilestoneStatus(new_status)
83
+ return {
84
+ "github_state": github_state,
85
+ "status_enum": status_enum,
86
+ }
87
+ except (ValueError, KeyError):
88
+ return None
@@ -0,0 +1 @@
1
+ """Package initialization file."""