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,308 @@
1
+ """Shared Layer - Common Utilities & Patterns.
2
+
3
+ This layer contains utilities and patterns used across all layers.
4
+ Common code that would otherwise be duplicated.
5
+
6
+ Modules:
7
+ - datetime_parser.py: Universal datetime parsing
8
+ - timezone_utils.py: Timezone-aware datetime handling
9
+ - validation.py: Data validation rules and validators
10
+ - logging.py: Structured logging configuration
11
+ - progress.py: Progress calculation engine
12
+ - errors.py: Exception definitions
13
+ - constants.py: Application constants and enums
14
+ - file_utils.py: Secure file I/O operations
15
+ - security.py: Security utilities and path validation
16
+
17
+ Guidelines:
18
+ - No layer-specific logic
19
+ - Shared by all other layers
20
+ - Pure functions or simple utilities
21
+ - No external dependencies
22
+ - Focused on one concern per module
23
+ """
24
+
25
+ from .constants import (
26
+ ANALYSIS_MAX_HISTORICAL_DAYS,
27
+ ANALYSIS_MIN_SAMPLE_SIZE,
28
+ ANALYSIS_TREND_WINDOW,
29
+ AUTH_TIMEOUT,
30
+ # Configuration defaults
31
+ AUTH_TOKEN_ENV_VAR,
32
+ CACHE_TTL_DEFAULT,
33
+ CACHE_TTL_LONG,
34
+ CACHE_TTL_SHORT,
35
+ DEFAULT_BACKOFF_FACTOR,
36
+ DEFAULT_BATCH_SIZE,
37
+ DEFAULT_CACHE_FILE,
38
+ DEFAULT_CONFIG_FILE,
39
+ DEFAULT_DATA_DIR,
40
+ DEFAULT_DATE_FORMAT,
41
+ DEFAULT_DATETIME_FORMAT,
42
+ DEFAULT_MAX_ITEMS_DISPLAY,
43
+ DEFAULT_MAX_RETRIES,
44
+ DEFAULT_RETRY_DELAY,
45
+ DEFAULT_ROADMAP_FILE,
46
+ DEFAULT_TABLE_WIDTH,
47
+ ERROR_MESSAGE_MAX_LENGTH,
48
+ GIT_COMMIT_MESSAGE_MAX_LENGTH,
49
+ GIT_MAX_OUTPUT_LINES,
50
+ GIT_TIMEOUT,
51
+ GITHUB_API_BASE,
52
+ GITHUB_API_TIMEOUT,
53
+ GITHUB_GRAPHQL_ENDPOINT,
54
+ GITHUB_RATE_LIMIT_THRESHOLD,
55
+ LOG_FORMAT_DEFAULT,
56
+ LOG_LEVEL_DEFAULT,
57
+ PERFORMANCE_CONNECTION_POOL_SIZE,
58
+ PERFORMANCE_ENABLE_ASYNC,
59
+ PERFORMANCE_ENABLE_CACHE,
60
+ PERFORMANCE_THREAD_POOL_SIZE,
61
+ PROGRESS_BAR_LENGTH,
62
+ PROGRESS_REFRESH_INTERVAL,
63
+ VALIDATION_ERROR_MAX_FIELDS,
64
+ VALIDATION_NAME_PATTERN,
65
+ VALIDATION_TITLE_MAX_LENGTH,
66
+ VALIDATION_TITLE_MIN_LENGTH,
67
+ IssueType,
68
+ MilestoneStatus,
69
+ Priority,
70
+ ProjectStatus,
71
+ RiskLevel,
72
+ Status,
73
+ )
74
+ from .datetime_parser import (
75
+ UnifiedDateTimeParser,
76
+ parse_datetime,
77
+ parse_file_datetime,
78
+ parse_github_datetime,
79
+ parse_user_datetime,
80
+ )
81
+ from .errors import (
82
+ AuthenticationError,
83
+ ConfigurationError,
84
+ DirectoryCreationError,
85
+ ErrorCategory,
86
+ ErrorSeverity,
87
+ ExportError,
88
+ FileLockError,
89
+ FileOperationError,
90
+ FileReadError,
91
+ FileWriteError,
92
+ GitHubAPIError,
93
+ GitOperationError,
94
+ IssueNotFoundError,
95
+ MilestoneNotFoundError,
96
+ NetworkError,
97
+ ParseError,
98
+ PathValidationError,
99
+ PersistenceError,
100
+ RoadmapError,
101
+ SecurityError,
102
+ StateError,
103
+ ValidationError,
104
+ )
105
+ from .logging import (
106
+ configure_for_testing,
107
+ get_logger,
108
+ get_security_logger,
109
+ log_operation,
110
+ setup_logging,
111
+ )
112
+ from .progress import ProgressCalculationEngine, ProgressEventSystem
113
+ from .security import (
114
+ cleanup_old_backups,
115
+ create_secure_directory,
116
+ create_secure_file,
117
+ create_secure_temp_file,
118
+ log_security_event,
119
+ sanitize_filename,
120
+ secure_file_permissions,
121
+ validate_export_size,
122
+ validate_path,
123
+ )
124
+ from .services import (
125
+ API_RETRY,
126
+ DATABASE_RETRY,
127
+ NETWORK_RETRY,
128
+ MetricsCollector,
129
+ OperationMetric,
130
+ OperationTimer,
131
+ RetryConfig,
132
+ async_retry,
133
+ async_timed_operation,
134
+ get_metrics_collector,
135
+ retry,
136
+ timed_operation,
137
+ )
138
+ from .utils import (
139
+ SecureFileManager,
140
+ TimezoneManager,
141
+ backup_file,
142
+ cleanup_temp_files,
143
+ ensure_directory_exists,
144
+ ensure_timezone_aware,
145
+ file_exists_check,
146
+ format_datetime,
147
+ format_relative_time,
148
+ get_file_size,
149
+ get_timezone_manager,
150
+ migrate_naive_datetime,
151
+ now_local,
152
+ now_utc,
153
+ safe_read_file,
154
+ safe_write_file,
155
+ )
156
+ from .validation import (
157
+ FieldValidator,
158
+ RoadmapValidator,
159
+ SchemaValidator,
160
+ ValidationResult,
161
+ ValidationType,
162
+ default_validator,
163
+ validate_and_raise,
164
+ validate_frontmatter_structure,
165
+ )
166
+
167
+ __all__ = [
168
+ # DateTime parsing
169
+ "UnifiedDateTimeParser",
170
+ "parse_datetime",
171
+ "parse_file_datetime",
172
+ "parse_github_datetime",
173
+ "parse_user_datetime",
174
+ # Timezone utilities
175
+ "TimezoneManager",
176
+ "get_timezone_manager",
177
+ "now_utc",
178
+ "now_local",
179
+ "ensure_timezone_aware",
180
+ "migrate_naive_datetime",
181
+ "format_datetime",
182
+ "format_relative_time",
183
+ # Validation
184
+ "ValidationType",
185
+ "ValidationResult",
186
+ "FieldValidator",
187
+ "SchemaValidator",
188
+ "RoadmapValidator",
189
+ "default_validator",
190
+ "validate_and_raise",
191
+ "validate_frontmatter_structure",
192
+ # File utilities
193
+ "SecureFileManager",
194
+ "backup_file",
195
+ "cleanup_temp_files",
196
+ "ensure_directory_exists",
197
+ "file_exists_check",
198
+ "get_file_size",
199
+ "safe_read_file",
200
+ "safe_write_file",
201
+ # Security utilities
202
+ "cleanup_old_backups",
203
+ "create_secure_directory",
204
+ "create_secure_file",
205
+ "create_secure_temp_file",
206
+ "log_security_event",
207
+ "sanitize_filename",
208
+ "secure_file_permissions",
209
+ "validate_export_size",
210
+ "validate_path",
211
+ # Logging
212
+ "setup_logging",
213
+ "get_logger",
214
+ "get_security_logger",
215
+ "configure_for_testing",
216
+ # Progress
217
+ "ProgressCalculationEngine",
218
+ "ProgressEventSystem",
219
+ # Errors
220
+ "RoadmapError",
221
+ "FileOperationError",
222
+ "ValidationError",
223
+ "NetworkError",
224
+ "GitOperationError",
225
+ "ConfigurationError",
226
+ "ErrorSeverity",
227
+ "ErrorCategory",
228
+ # Constants and enums
229
+ "Priority",
230
+ "Status",
231
+ "MilestoneStatus",
232
+ "ProjectStatus",
233
+ "RiskLevel",
234
+ "IssueType",
235
+ # Configuration defaults
236
+ "DEFAULT_ROADMAP_FILE",
237
+ "DEFAULT_CONFIG_FILE",
238
+ "DEFAULT_DATA_DIR",
239
+ "DEFAULT_CACHE_FILE",
240
+ "GITHUB_API_BASE",
241
+ "GITHUB_GRAPHQL_ENDPOINT",
242
+ "GITHUB_API_TIMEOUT",
243
+ "GITHUB_RATE_LIMIT_THRESHOLD",
244
+ "DEFAULT_TABLE_WIDTH",
245
+ "DEFAULT_MAX_ITEMS_DISPLAY",
246
+ "DEFAULT_DATE_FORMAT",
247
+ "DEFAULT_DATETIME_FORMAT",
248
+ "CACHE_TTL_DEFAULT",
249
+ "CACHE_TTL_LONG",
250
+ "CACHE_TTL_SHORT",
251
+ "DEFAULT_BATCH_SIZE",
252
+ "DEFAULT_MAX_RETRIES",
253
+ "DEFAULT_RETRY_DELAY",
254
+ "DEFAULT_BACKOFF_FACTOR",
255
+ "PROGRESS_REFRESH_INTERVAL",
256
+ "PROGRESS_BAR_LENGTH",
257
+ "LOG_LEVEL_DEFAULT",
258
+ "LOG_FORMAT_DEFAULT",
259
+ "ERROR_MESSAGE_MAX_LENGTH",
260
+ "VALIDATION_ERROR_MAX_FIELDS",
261
+ "AUTH_TOKEN_ENV_VAR",
262
+ "AUTH_TIMEOUT",
263
+ "GIT_TIMEOUT",
264
+ "GIT_MAX_OUTPUT_LINES",
265
+ "GIT_COMMIT_MESSAGE_MAX_LENGTH",
266
+ "ANALYSIS_MIN_SAMPLE_SIZE",
267
+ "ANALYSIS_MAX_HISTORICAL_DAYS",
268
+ "ANALYSIS_TREND_WINDOW",
269
+ "PERFORMANCE_ENABLE_CACHE",
270
+ "PERFORMANCE_ENABLE_ASYNC",
271
+ "PERFORMANCE_THREAD_POOL_SIZE",
272
+ "PERFORMANCE_CONNECTION_POOL_SIZE",
273
+ "VALIDATION_TITLE_MIN_LENGTH",
274
+ "VALIDATION_TITLE_MAX_LENGTH",
275
+ "VALIDATION_NAME_PATTERN",
276
+ # Error types
277
+ "AuthenticationError",
278
+ "DirectoryCreationError",
279
+ "ExportError",
280
+ "FileLockError",
281
+ "FileReadError",
282
+ "FileWriteError",
283
+ "GitHubAPIError",
284
+ "IssueNotFoundError",
285
+ "MilestoneNotFoundError",
286
+ "ParseError",
287
+ "PathValidationError",
288
+ "PersistenceError",
289
+ "SecurityError",
290
+ "StateError",
291
+ # Logging operations
292
+ "log_operation",
293
+ # Metrics
294
+ "MetricsCollector",
295
+ "OperationMetric",
296
+ "get_metrics_collector",
297
+ # Performance
298
+ "OperationTimer",
299
+ "async_timed_operation",
300
+ "timed_operation",
301
+ # Retry
302
+ "API_RETRY",
303
+ "DATABASE_RETRY",
304
+ "NETWORK_RETRY",
305
+ "RetryConfig",
306
+ "async_retry",
307
+ "retry",
308
+ ]
@@ -0,0 +1,209 @@
1
+ """Session-level caching for performance optimization.
2
+
3
+ This module provides a thread-safe cache for storing results during a single
4
+ command execution. The cache is designed to be cleared between commands to
5
+ ensure data freshness while reducing redundant operations.
6
+ """
7
+
8
+ import time
9
+ from threading import Lock
10
+ from typing import Any, TypeVar
11
+
12
+ from .logging import get_logger
13
+
14
+ logger = get_logger(__name__)
15
+
16
+ T = TypeVar("T")
17
+
18
+
19
+ class SessionCache:
20
+ """Thread-safe cache for session-level (single command) data.
21
+
22
+ This cache stores results with optional TTL (time-to-live) to balance
23
+ performance with data freshness. It's intended to be used within a
24
+ single command execution and cleared afterward.
25
+
26
+ Example:
27
+ cache = SessionCache()
28
+ cache.set("team_members", members, ttl=60)
29
+ result = cache.get("team_members") # Returns cached value if not expired
30
+
31
+ Attributes:
32
+ _cache: Dictionary mapping cache keys to (value, timestamp) tuples
33
+ _ttl: Dictionary mapping cache keys to their TTL in seconds
34
+ _lock: Thread lock for concurrent access safety
35
+ """
36
+
37
+ def __init__(self) -> None:
38
+ """Initialize an empty cache with no stored values."""
39
+ self._cache: dict[str, tuple[Any, float]] = {}
40
+ self._ttl: dict[str, float] = {}
41
+ self._lock = Lock()
42
+ logger.debug("session_cache_initialized")
43
+
44
+ def get(self, key: str) -> Any | None:
45
+ """Retrieve a value from cache if it exists and hasn't expired.
46
+
47
+ Args:
48
+ key: The cache key to retrieve
49
+
50
+ Returns:
51
+ The cached value if found and not expired, None otherwise
52
+
53
+ Example:
54
+ value = cache.get("issues")
55
+ if value is not None:
56
+ # Use cached value
57
+ print(value)
58
+ """
59
+ with self._lock:
60
+ if key not in self._cache:
61
+ logger.debug("cache_miss", key=key)
62
+ return None
63
+
64
+ value, timestamp = self._cache[key]
65
+ ttl = self._ttl.get(key, float("inf"))
66
+
67
+ # Check if cached value has expired
68
+ if time.time() - timestamp > ttl:
69
+ logger.debug("cache_expired", key=key)
70
+ del self._cache[key]
71
+ if key in self._ttl:
72
+ del self._ttl[key]
73
+ return None
74
+
75
+ logger.debug("cache_hit", key=key)
76
+ return value
77
+
78
+ def set(self, key: str, value: Any, ttl: float = float("inf")) -> None:
79
+ """Store a value in cache with optional TTL.
80
+
81
+ Args:
82
+ key: The cache key to store under
83
+ value: The value to cache
84
+ ttl: Time-to-live in seconds (default: infinite)
85
+
86
+ Example:
87
+ cache.set("team_members", members, ttl=60) # Expires after 60s
88
+ cache.set("config", config) # Never expires
89
+ """
90
+ with self._lock:
91
+ self._cache[key] = (value, time.time())
92
+ self._ttl[key] = ttl
93
+ logger.debug("cache_set", key=key, ttl=ttl)
94
+
95
+ def clear(self) -> None:
96
+ """Clear all cached values.
97
+
98
+ Use this at the end of a command to reset for the next execution.
99
+
100
+ Example:
101
+ # After command completes
102
+ cache.clear()
103
+ """
104
+ with self._lock:
105
+ count = len(self._cache)
106
+ self._cache.clear()
107
+ self._ttl.clear()
108
+ logger.debug("cache_cleared", entries_cleared=count)
109
+
110
+ def invalidate(self, key: str) -> None:
111
+ """Remove a specific key from cache.
112
+
113
+ Useful for invalidating stale data without clearing entire cache.
114
+
115
+ Args:
116
+ key: The cache key to remove
117
+
118
+ Example:
119
+ cache.invalidate("team_members") # Force refresh on next access
120
+ """
121
+ with self._lock:
122
+ if key in self._cache:
123
+ del self._cache[key]
124
+ if key in self._ttl:
125
+ del self._ttl[key]
126
+ logger.debug("cache_invalidated", key=key)
127
+
128
+ def get_stats(self) -> dict[str, Any]:
129
+ """Get current cache statistics.
130
+
131
+ Returns:
132
+ Dictionary with cache metrics:
133
+ - entries: Number of cached items
134
+ - keys: List of all cache keys
135
+
136
+ Example:
137
+ stats = cache.get_stats()
138
+ print(f"Cached {stats['entries']} items")
139
+ """
140
+ with self._lock:
141
+ return {
142
+ "entries": len(self._cache),
143
+ "keys": list(self._cache.keys()),
144
+ }
145
+
146
+
147
+ # Global session cache instance
148
+ _session_cache = SessionCache()
149
+
150
+
151
+ def get_session_cache() -> SessionCache:
152
+ """Get the global session cache instance.
153
+
154
+ Returns:
155
+ The singleton SessionCache instance
156
+
157
+ Example:
158
+ cache = get_session_cache()
159
+ cache.set("data", value)
160
+ """
161
+ return _session_cache
162
+
163
+
164
+ def clear_session_cache() -> None:
165
+ """Clear the global session cache.
166
+
167
+ Call this at the beginning of each command execution to ensure
168
+ a clean slate while allowing intra-command caching benefits.
169
+
170
+ Example:
171
+ # In CLI command entry point
172
+ clear_session_cache()
173
+ # ... run command
174
+ """
175
+ _session_cache.clear()
176
+
177
+
178
+ def cache_result(key: str, ttl: float = float("inf")):
179
+ """Cache function results in session cache.
180
+
181
+ Args:
182
+ key: The cache key to use (can contain {arg_name} placeholders)
183
+ ttl: Time-to-live in seconds
184
+
185
+ Example:
186
+ @cache_result("team_members", ttl=60)
187
+ def get_team_members() -> list[str]:
188
+ # ... fetch from API
189
+ return members
190
+
191
+ # Second call within 60s returns cached result
192
+ members = get_team_members()
193
+ """
194
+
195
+ def decorator(func):
196
+ def wrapper(*args, **kwargs):
197
+ # Try to get from cache first
198
+ cached = get_session_cache().get(key)
199
+ if cached is not None:
200
+ return cached
201
+
202
+ # Call function and cache result
203
+ result = func(*args, **kwargs)
204
+ get_session_cache().set(key, result, ttl=ttl)
205
+ return result
206
+
207
+ return wrapper
208
+
209
+ return decorator
@@ -0,0 +1,147 @@
1
+ """Unified error handling for CLI commands.
2
+
3
+ Provides consistent error handling, logging, and user feedback across all CLI commands.
4
+ """
5
+
6
+ import functools
7
+ import sys
8
+ import time
9
+ from collections.abc import Callable
10
+ from typing import Any, TypeVar, cast
11
+
12
+ import click
13
+
14
+ from roadmap.common.console import get_console
15
+ from roadmap.common.logging import (
16
+ clear_correlation_id,
17
+ get_logger,
18
+ set_correlation_id,
19
+ )
20
+
21
+ logger = get_logger(__name__)
22
+ console = get_console()
23
+
24
+ # Type variable for decorator
25
+ F = TypeVar("F", bound=Callable[..., Any])
26
+
27
+
28
+ def handle_cli_errors(
29
+ command_name: str | None = None, show_traceback: bool = False, log_args: bool = True
30
+ ) -> Callable[[F], F]:
31
+ """Add unified error handling to CLI commands with timing and correlation tracking.
32
+
33
+ Args:
34
+ command_name: Name of the command (for logging)
35
+ show_traceback: Whether to show full traceback on errors
36
+ log_args: Whether to log function arguments (filtered to remove sensitive data)
37
+
38
+ Example:
39
+ @click.command()
40
+ @handle_cli_errors(command_name="issue create")
41
+ def create_issue(...):
42
+ # Your command logic here
43
+ pass
44
+ """
45
+
46
+ def decorator(func: F) -> F:
47
+ @functools.wraps(func)
48
+ def wrapper(*args: Any, **kwargs: Any) -> Any:
49
+ cmd_name = command_name or func.__name__
50
+ start_time = time.perf_counter()
51
+
52
+ # Set correlation ID for this command invocation
53
+ correlation_id = set_correlation_id()
54
+
55
+ # Filter sensitive data from arguments
56
+ if log_args:
57
+ filtered_kwargs = {
58
+ k: "***REDACTED***"
59
+ if any(s in k.lower() for s in ["token", "password", "secret"])
60
+ else v
61
+ for k, v in kwargs.items()
62
+ }
63
+ logger.info(
64
+ "command_invoked",
65
+ operation=cmd_name,
66
+ correlation_id=correlation_id,
67
+ args=filtered_kwargs,
68
+ )
69
+ else:
70
+ logger.info(
71
+ "command_invoked",
72
+ operation=cmd_name,
73
+ correlation_id=correlation_id,
74
+ )
75
+
76
+ try:
77
+ result = func(*args, **kwargs)
78
+
79
+ # Log successful completion with timing
80
+ duration = time.perf_counter() - start_time
81
+ logger.info(
82
+ "command_completed",
83
+ operation=cmd_name,
84
+ correlation_id=correlation_id,
85
+ duration_ms=round(duration * 1000, 2),
86
+ success=True,
87
+ )
88
+
89
+ return result
90
+
91
+ except KeyboardInterrupt:
92
+ duration = time.perf_counter() - start_time
93
+ logger.warning(
94
+ "Operation cancelled by user",
95
+ operation=cmd_name,
96
+ correlation_id=correlation_id,
97
+ duration_ms=round(duration * 1000, 2),
98
+ )
99
+ console.print("\n[yellow]⚠️ Operation cancelled by user[/yellow]")
100
+ sys.exit(130)
101
+
102
+ except click.Abort:
103
+ # Already handled, just re-raise
104
+ raise
105
+
106
+ except Exception as e:
107
+ duration = time.perf_counter() - start_time
108
+ logger.error(
109
+ "command_failed",
110
+ operation=cmd_name,
111
+ correlation_id=correlation_id,
112
+ duration_ms=round(duration * 1000, 2),
113
+ error_type=type(e).__name__,
114
+ error_message=str(e),
115
+ )
116
+ if show_traceback:
117
+ console.print(f"\n[red]❌ Error: {e}[/red]")
118
+ import traceback
119
+
120
+ console.print(f"[dim]{traceback.format_exc()}[/dim]")
121
+ raise
122
+
123
+ finally:
124
+ # Clear correlation ID after command completes
125
+ clear_correlation_id()
126
+
127
+ return cast(F, wrapper)
128
+
129
+ return decorator
130
+
131
+
132
+ def validate_required_args(**kwargs: Any) -> None:
133
+ """Validate that required arguments are provided.
134
+
135
+ Args:
136
+ **kwargs: Dictionary of argument names and values to validate
137
+
138
+ Raises:
139
+ click.UsageError: If any required argument is missing
140
+
141
+ Example:
142
+ validate_required_args(title=title, assignee=assignee)
143
+ """
144
+ missing = [name for name, value in kwargs.items() if value is None or value == ""]
145
+ if missing:
146
+ missing_args = ", ".join(f"--{name.replace('_', '-')}" for name in missing)
147
+ raise click.UsageError(f"Missing required arguments: {missing_args}")
@@ -0,0 +1,33 @@
1
+ """Configuration management utilities."""
2
+
3
+ # Import Pydantic configuration models for backward compatibility
4
+ from roadmap.common.models.config_models import ( # noqa: F401
5
+ ExportConfig,
6
+ GitConfig,
7
+ OutputConfig,
8
+ )
9
+
10
+ from .config_loader import ConfigLoader # noqa: F401
11
+ from .config_manager import ConfigManager # noqa: F401
12
+ from .config_schema import ( # noqa: F401
13
+ BehaviorConfig,
14
+ DisplayConfig,
15
+ GitHubConfig,
16
+ PathsConfig,
17
+ RoadmapConfig,
18
+ UserConfig,
19
+ )
20
+
21
+ __all__ = [
22
+ "ConfigLoader",
23
+ "ConfigManager",
24
+ "RoadmapConfig",
25
+ "BehaviorConfig",
26
+ "DisplayConfig",
27
+ "GitHubConfig",
28
+ "PathsConfig",
29
+ "UserConfig",
30
+ "ExportConfig",
31
+ "OutputConfig",
32
+ "GitConfig",
33
+ ]