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,119 @@
1
+ """Specialized adapter interfaces for sync services.
2
+
3
+ Defines contracts for sync-specific operations without layer violations.
4
+ """
5
+
6
+ from abc import ABC, abstractmethod
7
+ from typing import Any
8
+
9
+
10
+ class SyncLinkingServiceInterface(ABC):
11
+ """Contract for sync linking operations.
12
+
13
+ Handles linking/unlinking of local and remote issues during sync.
14
+ """
15
+
16
+ @abstractmethod
17
+ def link_issues(self, local_id: str, remote_id: str) -> bool: # noqa: F841
18
+ """Link a local issue to a remote issue.
19
+
20
+ Args:
21
+ local_id: Local issue ID
22
+ remote_id: Remote issue ID
23
+
24
+ Returns:
25
+ True if successful
26
+ """
27
+ pass
28
+
29
+ @abstractmethod
30
+ def unlink_issue(self, local_id: str) -> bool: # noqa: F841
31
+ """Unlink an issue from its remote mapping.
32
+
33
+ Args:
34
+ local_id: Local issue ID
35
+
36
+ Returns:
37
+ True if successful
38
+ """
39
+ pass
40
+
41
+ @abstractmethod
42
+ def get_linked_remote_id(self, local_id: str) -> str | None: # noqa: F841
43
+ """Get the remote issue ID for a local issue.
44
+
45
+ Args:
46
+ local_id: Local issue ID
47
+
48
+ Returns:
49
+ Remote issue ID or None if not linked
50
+ """
51
+ pass
52
+
53
+ @abstractmethod
54
+ def get_linked_local_id(self, remote_id: str) -> str | None:
55
+ """Get the local issue ID for a remote issue.
56
+
57
+ Args:
58
+ remote_id: Remote issue ID
59
+
60
+ Returns:
61
+ Local issue ID or None if not linked
62
+ """
63
+ pass
64
+
65
+
66
+ class SyncCacheServiceInterface(ABC):
67
+ """Contract for sync caching operations.
68
+
69
+ Manages cache of remote state to reduce API calls.
70
+ """
71
+
72
+ @abstractmethod
73
+ def cache_remote_issue(self, issue_id: str, issue_data: dict[str, Any]) -> bool:
74
+ """Cache remote issue data.
75
+
76
+ Args:
77
+ issue_id: Issue identifier
78
+ issue_data: Issue data dictionary
79
+
80
+ Returns:
81
+ True if successful
82
+ """
83
+ pass
84
+
85
+ @abstractmethod
86
+ def get_cached_remote_issue(self, issue_id: str) -> dict[str, Any] | None:
87
+ """Get cached remote issue data.
88
+
89
+ Args:
90
+ issue_id: Issue identifier
91
+
92
+ Returns:
93
+ Issue data or None if not cached
94
+ """
95
+ pass
96
+
97
+ @abstractmethod
98
+ def invalidate_cache(self, issue_id: str | None = None) -> bool:
99
+ """Invalidate cache.
100
+
101
+ Args:
102
+ issue_id: Specific issue ID to invalidate, or None for all
103
+
104
+ Returns:
105
+ True if successful
106
+ """
107
+ pass
108
+
109
+ @abstractmethod
110
+ def is_cache_fresh(self, issue_id: str) -> bool:
111
+ """Check if cached data is still fresh.
112
+
113
+ Args:
114
+ issue_id: Issue identifier
115
+
116
+ Returns:
117
+ True if cache is valid and fresh
118
+ """
119
+ pass
@@ -0,0 +1,180 @@
1
+ """Protocol and abstract base class definitions for sync validation.
2
+
3
+ This module defines validators to ensure data integrity and prevent database
4
+ corruption during sync operations, particularly foreign key constraint violations.
5
+ """
6
+
7
+ from abc import ABC, abstractmethod
8
+ from typing import Any, Protocol
9
+
10
+
11
+ class ForeignKeyValidator(ABC):
12
+ """Abstract base class for validating foreign key constraints before syncing.
13
+
14
+ Ensures prerequisite data exists before syncing dependent entities,
15
+ preventing FOREIGN KEY constraint violations.
16
+
17
+ Example:
18
+ validator = MilestoneFKValidator(db_connection)
19
+ try:
20
+ validator.validate() # Raises if projects table is empty
21
+ except ForeignKeyValidationError as e:
22
+ logger.error(f"Validation failed: {e}")
23
+ raise
24
+ """
25
+
26
+ @abstractmethod
27
+ def validate(self) -> None:
28
+ """Validate that all foreign key prerequisites exist.
29
+
30
+ Raises:
31
+ ForeignKeyValidationError: If prerequisite data doesn't exist
32
+ RuntimeError: If database connection fails
33
+
34
+ Notes:
35
+ - Should fail fast on missing prerequisites
36
+ - Must not swallow exceptions
37
+ - Log specific missing references with entity IDs
38
+ """
39
+ ...
40
+
41
+ @abstractmethod
42
+ def missing_prerequisites(self) -> list[str]:
43
+ """Return list of missing prerequisite entities.
44
+
45
+ Returns:
46
+ List of entity IDs or descriptions that are missing
47
+
48
+ Example:
49
+ ['project-id-1', 'project-id-2']
50
+ """
51
+ ...
52
+
53
+
54
+ class SyncPhaseOrder(Protocol):
55
+ """Protocol defining ordered sync phases to prevent constraint violations.
56
+
57
+ Ensures entities are synced in correct dependency order:
58
+ 1. Projects (no dependencies)
59
+ 2. Milestones (depends on projects)
60
+ 3. Issues (depends on projects and milestones)
61
+
62
+ Implementation should enforce this ordering and fail if called out-of-order.
63
+ """
64
+
65
+ def validate_phase_order(self, _current_phase: str, _next_phase: str) -> bool:
66
+ """Validate that phase transition is allowed.
67
+
68
+ Args:
69
+ current_phase: Current sync phase ('projects', 'milestones', 'issues')
70
+ next_phase: Next sync phase to execute
71
+
72
+ Returns:
73
+ True if transition is valid, False otherwise
74
+
75
+ Raises:
76
+ ValueError: If phases are invalid or transition violates ordering
77
+ """
78
+ ...
79
+
80
+ def get_phase_order(self) -> list[str]:
81
+ """Get the canonical phase execution order.
82
+
83
+ Returns:
84
+ Ordered list of phases: ['projects', 'milestones', 'issues']
85
+ """
86
+ ...
87
+
88
+
89
+ class PreSyncValidator(Protocol):
90
+ """Protocol for pre-sync validation with fail-fast semantics.
91
+
92
+ Validates preconditions before any sync operations begin.
93
+ Failures immediately abort sync to prevent partial state corruptions.
94
+ """
95
+
96
+ def validate_pre_sync(self, _roadmap_dir: str | None = None) -> dict[str, Any]:
97
+ """Validate preconditions before sync.
98
+
99
+ Args:
100
+ roadmap_dir: Optional roadmap directory path to validate
101
+
102
+ Returns:
103
+ dict with validation results:
104
+ {
105
+ 'valid': bool,
106
+ 'errors': list[str],
107
+ 'warnings': list[str],
108
+ 'prerequisite_count': int
109
+ }
110
+
111
+ Raises:
112
+ ValueError: If critical preconditions fail (fail-fast)
113
+ RuntimeError: If database connection fails
114
+
115
+ Notes:
116
+ - Errors (critical) cause immediate abort via exception
117
+ - Warnings (non-critical) logged but allow sync to proceed
118
+ - Should check prerequisite tables before FK-dependent syncing
119
+ """
120
+ ...
121
+
122
+
123
+ class AtomicSyncPhase(Protocol):
124
+ """Protocol for atomic sync operations (transaction-based).
125
+
126
+ Wraps entity sync in transactions to ensure all-or-nothing semantics
127
+ per sync phase.
128
+
129
+ Usage:
130
+ with atomic_sync('projects') as phase:
131
+ sync_project_1() # If any sync fails, entire phase rolls back
132
+ sync_project_2()
133
+ """
134
+
135
+ def __enter__(self) -> "AtomicSyncPhase":
136
+ """Enter atomic sync context (start transaction)."""
137
+ ...
138
+
139
+ def __exit__(
140
+ self,
141
+ _exc_type: type,
142
+ _exc_val: Exception,
143
+ _exc_tb: Any,
144
+ ) -> None:
145
+ """Exit atomic sync context (commit or rollback)."""
146
+ ...
147
+
148
+
149
+ class ForeignKeyValidationError(Exception):
150
+ """Raised when foreign key validation fails.
151
+
152
+ Indicates missing prerequisite data that would cause FK constraint
153
+ violations if sync proceeded.
154
+
155
+ Attributes:
156
+ entity_type: Type of entity with missing FK (e.g., 'milestone')
157
+ missing_references: List of missing referenced entity IDs
158
+ error_details: Detailed error message with context
159
+ """
160
+
161
+ def __init__(
162
+ self,
163
+ entity_type: str,
164
+ missing_references: list[str],
165
+ error_details: str,
166
+ ):
167
+ """Initialize validation error.
168
+
169
+ Args:
170
+ entity_type: Type of entity that failed validation
171
+ missing_references: IDs of missing prerequisite entities
172
+ error_details: Detailed error context
173
+ """
174
+ self.entity_type = entity_type
175
+ self.missing_references = missing_references
176
+ self.error_details = error_details
177
+ super().__init__(
178
+ f"FK validation failed for {entity_type}: "
179
+ f"missing {len(missing_references)} references. {error_details}"
180
+ )
@@ -0,0 +1,31 @@
1
+ """Core models for roadmap."""
2
+
3
+ from pathlib import Path
4
+
5
+ from roadmap.core.services.sync.sync_state import IssueBaseState, SyncState
6
+
7
+ # Import from parent models.py (service params and other models)
8
+ # Get the parent directory's models.py file
9
+ _models_file = Path(__file__).parent.parent / "models.py"
10
+ _models_spec = __import__("importlib.util").util.spec_from_file_location(
11
+ "_models_module", _models_file
12
+ )
13
+ _models_mod = __import__("importlib.util").util.module_from_spec(_models_spec)
14
+ _models_spec.loader.exec_module(_models_mod)
15
+
16
+ # Re-export items from models.py
17
+ NOT_PROVIDED = _models_mod.NOT_PROVIDED
18
+ IssueCreateServiceParams = _models_mod.IssueCreateServiceParams
19
+ IssueUpdateServiceParams = _models_mod.IssueUpdateServiceParams
20
+ ProjectCreateServiceParams = _models_mod.ProjectCreateServiceParams
21
+ ProjectUpdateServiceParams = _models_mod.ProjectUpdateServiceParams
22
+
23
+ __all__ = [
24
+ "NOT_PROVIDED",
25
+ "IssueCreateServiceParams",
26
+ "IssueUpdateServiceParams",
27
+ "ProjectCreateServiceParams",
28
+ "ProjectUpdateServiceParams",
29
+ "IssueBaseState",
30
+ "SyncState",
31
+ ]
@@ -0,0 +1,162 @@
1
+ """Sync dataclasses - canonical representations for sync operations.
2
+
3
+ These dataclasses serve as the common currency between local state and remote state
4
+ during sync operations. Backends normalize their API responses into these types,
5
+ and the generic orchestrator works exclusively with them.
6
+
7
+ This ensures the core sync logic is completely backend-agnostic.
8
+ """
9
+
10
+ from dataclasses import asdict, dataclass, field
11
+ from datetime import datetime
12
+ from typing import Any
13
+
14
+
15
+ @dataclass
16
+ class SyncIssue:
17
+ """Canonical representation of an issue for sync operations.
18
+
19
+ Used as the common currency between local and remote states.
20
+ Backends normalize their API responses into this format.
21
+ """
22
+
23
+ # Core fields (present in all backends)
24
+ id: str
25
+ title: str
26
+ status: str # Normalized: "open", "closed", "in_progress", etc.
27
+
28
+ # Optional fields (may not be present in all backends)
29
+ headline: str = ""
30
+ assignee: str | None = None
31
+ milestone: str | None = None
32
+ labels: list[str] = field(default_factory=list)
33
+
34
+ # Timing
35
+ created_at: datetime | None = None
36
+ updated_at: datetime | None = None
37
+
38
+ # Backend tracking
39
+ backend_name: str = "unknown" # "github", "gitlab", "git", etc.
40
+ backend_id: str | int | None = None # Native backend ID
41
+ remote_ids: dict[str, str | int] = field(
42
+ default_factory=dict
43
+ ) # All known remote IDs
44
+
45
+ # Extensibility for backend-specific data
46
+ custom_fields: dict[str, Any] = field(
47
+ default_factory=dict
48
+ ) # Jira-style custom fields
49
+ raw_response: dict[str, Any] = field(default_factory=dict) # Raw API response
50
+ metadata: dict[str, Any] = field(default_factory=dict) # Custom tracking data
51
+
52
+ def __post_init__(self):
53
+ """Validate sync issue data."""
54
+ if not self.id:
55
+ raise ValueError("SyncIssue.id is required")
56
+ if not self.title:
57
+ raise ValueError("SyncIssue.title is required")
58
+ if not self.status:
59
+ raise ValueError("SyncIssue.status is required")
60
+
61
+ def to_dict(self) -> dict[str, Any]:
62
+ """Convert to dictionary for serialization."""
63
+ return asdict(self)
64
+
65
+ @classmethod
66
+ def from_dict(cls, data: dict[str, Any]) -> "SyncIssue":
67
+ """Create from dictionary (e.g., from JSON/YAML)."""
68
+ # Handle datetime strings
69
+ if isinstance(data.get("created_at"), str):
70
+ data["created_at"] = datetime.fromisoformat(data["created_at"])
71
+ if isinstance(data.get("updated_at"), str):
72
+ data["updated_at"] = datetime.fromisoformat(data["updated_at"])
73
+
74
+ # Filter to only known fields
75
+ valid_fields = {f.name for f in cls.__dataclass_fields__.values()}
76
+ filtered_data = {k: v for k, v in data.items() if k in valid_fields}
77
+ return cls(**filtered_data)
78
+
79
+
80
+ @dataclass
81
+ class SyncMilestone:
82
+ """Canonical representation of a milestone for sync operations."""
83
+
84
+ # Core fields
85
+ id: str
86
+ name: str
87
+ status: str = "open" # "open", "closed"
88
+
89
+ # Optional fields
90
+ headline: str | None = None
91
+ due_date: datetime | None = None
92
+
93
+ # Backend tracking
94
+ backend_name: str = "unknown"
95
+ backend_id: str | int | None = None
96
+ remote_ids: dict[str, str | int] = field(default_factory=dict)
97
+
98
+ # Extensibility
99
+ custom_fields: dict[str, Any] = field(default_factory=dict)
100
+ raw_response: dict[str, Any] = field(default_factory=dict)
101
+ metadata: dict[str, Any] = field(default_factory=dict)
102
+
103
+ def __post_init__(self):
104
+ """Validate sync milestone data."""
105
+ if not self.id:
106
+ raise ValueError("SyncMilestone.id is required")
107
+ if not self.name:
108
+ raise ValueError("SyncMilestone.name is required")
109
+
110
+ def to_dict(self) -> dict[str, Any]:
111
+ """Convert to dictionary for serialization."""
112
+ return asdict(self)
113
+
114
+ @classmethod
115
+ def from_dict(cls, data: dict[str, Any]) -> "SyncMilestone":
116
+ """Create from dictionary."""
117
+ if isinstance(data.get("due_date"), str):
118
+ data["due_date"] = datetime.fromisoformat(data["due_date"])
119
+
120
+ valid_fields = {f.name for f in cls.__dataclass_fields__.values()}
121
+ filtered_data = {k: v for k, v in data.items() if k in valid_fields}
122
+ return cls(**filtered_data)
123
+
124
+
125
+ @dataclass
126
+ class SyncProject:
127
+ """Canonical representation of a project for sync operations."""
128
+
129
+ # Core fields
130
+ id: str
131
+ name: str
132
+
133
+ # Optional fields
134
+ headline: str | None = None
135
+
136
+ # Backend tracking
137
+ backend_name: str = "unknown"
138
+ backend_id: str | int | None = None
139
+ remote_ids: dict[str, str | int] = field(default_factory=dict)
140
+
141
+ # Extensibility
142
+ custom_fields: dict[str, Any] = field(default_factory=dict)
143
+ raw_response: dict[str, Any] = field(default_factory=dict)
144
+ metadata: dict[str, Any] = field(default_factory=dict)
145
+
146
+ def __post_init__(self):
147
+ """Validate sync project data."""
148
+ if not self.id:
149
+ raise ValueError("SyncProject.id is required")
150
+ if not self.name:
151
+ raise ValueError("SyncProject.name is required")
152
+
153
+ def to_dict(self) -> dict[str, Any]:
154
+ """Convert to dictionary for serialization."""
155
+ return asdict(self)
156
+
157
+ @classmethod
158
+ def from_dict(cls, data: dict[str, Any]) -> "SyncProject":
159
+ """Create from dictionary."""
160
+ valid_fields = {f.name for f in cls.__dataclass_fields__.values()}
161
+ filtered_data = {k: v for k, v in data.items() if k in valid_fields}
162
+ return cls(**filtered_data)
roadmap/core/models.py ADDED
@@ -0,0 +1,115 @@
1
+ """Service layer dataclasses for internal parameter passing.
2
+
3
+ These models decouple service method signatures from their implementations.
4
+ They're used internally by services (not exposed to CLI).
5
+
6
+ Benefits:
7
+ - Services have clean, stable signatures
8
+ - Easy to add new fields without breaking callers
9
+ - Self-documenting business logic
10
+ - Better testability (can mock as single object)
11
+ """
12
+
13
+ from dataclasses import dataclass, field
14
+ from datetime import datetime
15
+
16
+
17
+ # Sentinel value to distinguish "not provided" from "None"
18
+ class _NotProvided:
19
+ """Sentinel value indicating a field was not provided in an update."""
20
+
21
+ def __repr__(self):
22
+ return "<NOT_PROVIDED>"
23
+
24
+
25
+ NOT_PROVIDED = _NotProvided()
26
+
27
+
28
+ @dataclass
29
+ class IssueCreateServiceParams:
30
+ """Parameters for creating an issue (service layer)."""
31
+
32
+ title: str
33
+ priority: str | None = None
34
+ status: str = "todo"
35
+ issue_type: str | None = None
36
+ milestone: str | None = None
37
+ assignee: str | None = None
38
+ content: str | None = None
39
+ estimate: float | None = None
40
+ labels: list[str] = field(default_factory=list)
41
+ depends_on: list[str] = field(default_factory=list)
42
+ blocks: list[str] = field(default_factory=list)
43
+
44
+
45
+ @dataclass
46
+ class IssueUpdateServiceParams:
47
+ """Parameters for updating an issue (service layer)."""
48
+
49
+ issue_id: str
50
+ title: str | None | _NotProvided = NOT_PROVIDED
51
+ priority: str | None | _NotProvided = NOT_PROVIDED
52
+ status: str | None | _NotProvided = NOT_PROVIDED
53
+ assignee: str | None | _NotProvided = NOT_PROVIDED
54
+ milestone: str | None | _NotProvided = NOT_PROVIDED
55
+ content: str | None | _NotProvided = NOT_PROVIDED
56
+ estimate: float | None | _NotProvided = NOT_PROVIDED
57
+ reason: str | None | _NotProvided = NOT_PROVIDED
58
+ archived: bool | _NotProvided = NOT_PROVIDED
59
+
60
+
61
+ @dataclass
62
+ class IssueQueryParams:
63
+ """Parameters for querying/filtering issues (service layer)."""
64
+
65
+ status: str | None = None
66
+ priority: str | None = None
67
+ issue_type: str | None = None
68
+ assignee: str | None = None
69
+ milestone: str | None = None
70
+ overdue: bool = False
71
+ blocked: bool = False
72
+ unassigned: bool = False
73
+ limit: int | None = None
74
+ offset: int = 0
75
+
76
+
77
+ @dataclass
78
+ class MilestoneCreateServiceParams:
79
+ """Parameters for creating a milestone (service layer)."""
80
+
81
+ name: str
82
+ content: str = ""
83
+ due_date: datetime | None = None
84
+
85
+
86
+ @dataclass
87
+ class MilestoneUpdateServiceParams:
88
+ """Parameters for updating a milestone (service layer)."""
89
+
90
+ name: str
91
+ content: str | None = None
92
+ due_date: datetime | None = None
93
+ clear_due_date: bool = False
94
+ status: str | None = None
95
+ archived: bool | _NotProvided = NOT_PROVIDED
96
+
97
+
98
+ @dataclass
99
+ class ProjectCreateServiceParams:
100
+ """Parameters for creating a project (service layer)."""
101
+
102
+ name: str
103
+ content: str = ""
104
+ milestones: list | None = None
105
+
106
+
107
+ @dataclass
108
+ class ProjectUpdateServiceParams:
109
+ """Parameters for updating a project (service layer)."""
110
+
111
+ project_id: str
112
+ name: str | None = None
113
+ content: str | None = None
114
+ milestones: list | None = None
115
+ status: str | None = None
@@ -0,0 +1,17 @@
1
+ """Observability and metrics tracking for sync operations.
2
+
3
+ Provides comprehensive metrics collection, aggregation, and reporting
4
+ for sync operations including:
5
+ - Deduplication metrics (local/remote reduction percentages, timing)
6
+ - Fetch/push/pull operation metrics
7
+ - Conflict detection and resolution tracking
8
+ - Duplicate detection and resolution metrics
9
+ - Performance timing and throughput
10
+ """
11
+
12
+ from .sync_metrics import SyncMetrics, SyncObservability
13
+
14
+ __all__ = [
15
+ "SyncMetrics",
16
+ "SyncObservability",
17
+ ]