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.
- roadmap/__init__.py +27 -0
- roadmap/adapters/__init__.py +1 -0
- roadmap/adapters/base_paginated_adapter.py +117 -0
- roadmap/adapters/cli/__init__.py +249 -0
- roadmap/adapters/cli/analysis/__init__.py +5 -0
- roadmap/adapters/cli/analysis/commands.py +370 -0
- roadmap/adapters/cli/analysis/presenter.py +125 -0
- roadmap/adapters/cli/archive_operations.py +86 -0
- roadmap/adapters/cli/cli_command_helpers.py +109 -0
- roadmap/adapters/cli/cli_confirmations.py +74 -0
- roadmap/adapters/cli/cli_error_handlers.py +146 -0
- roadmap/adapters/cli/cli_validators.py +39 -0
- roadmap/adapters/cli/commands/sync_status.py +308 -0
- roadmap/adapters/cli/comment/__init__.py +5 -0
- roadmap/adapters/cli/comment/commands.py +106 -0
- roadmap/adapters/cli/config/__init__.py +5 -0
- roadmap/adapters/cli/config/commands.py +198 -0
- roadmap/adapters/cli/console_exports.py +10 -0
- roadmap/adapters/cli/core.py +26 -0
- roadmap/adapters/cli/crud/__init__.py +47 -0
- roadmap/adapters/cli/crud/base_archive.py +208 -0
- roadmap/adapters/cli/crud/base_create.py +154 -0
- roadmap/adapters/cli/crud/base_delete.py +155 -0
- roadmap/adapters/cli/crud/base_restore.py +283 -0
- roadmap/adapters/cli/crud/base_update.py +193 -0
- roadmap/adapters/cli/crud/crud_helpers.py +206 -0
- roadmap/adapters/cli/crud/crud_utils.py +152 -0
- roadmap/adapters/cli/crud/entity_builders.py +374 -0
- roadmap/adapters/cli/data/__init__.py +8 -0
- roadmap/adapters/cli/data/commands.py +149 -0
- roadmap/adapters/cli/decorators.py +208 -0
- roadmap/adapters/cli/dtos/__init__.py +155 -0
- roadmap/adapters/cli/exception_handler.py +105 -0
- roadmap/adapters/cli/git/__init__.py +8 -0
- roadmap/adapters/cli/git/commands.py +475 -0
- roadmap/adapters/cli/git/handlers/__init__.py +1 -0
- roadmap/adapters/cli/git/handlers/git_authentication_handler.py +124 -0
- roadmap/adapters/cli/git/handlers/git_branch_handler.py +238 -0
- roadmap/adapters/cli/git/handlers/git_connectivity_handler.py +122 -0
- roadmap/adapters/cli/git/handlers/git_hooks_handler.py +105 -0
- roadmap/adapters/cli/git/hooks_config.py +327 -0
- roadmap/adapters/cli/git/status_display.py +158 -0
- roadmap/adapters/cli/health/__init__.py +8 -0
- roadmap/adapters/cli/health/db_integrity.py +204 -0
- roadmap/adapters/cli/health/enhancer.py +227 -0
- roadmap/adapters/cli/health/fixer.py +295 -0
- roadmap/adapters/cli/health/fixers/__init__.py +10 -0
- roadmap/adapters/cli/health/fixers/corrupted_comments_fixer.py +231 -0
- roadmap/adapters/cli/health/fixers/data_integrity_fixer.py +137 -0
- roadmap/adapters/cli/health/fixers/duplicate_issues_fixer.py +138 -0
- roadmap/adapters/cli/health/fixers/folder_structure_fixer.py +114 -0
- roadmap/adapters/cli/health/fixers/label_normalization_fixer.py +162 -0
- roadmap/adapters/cli/health/fixers/milestone_name_normalization_fixer.py +181 -0
- roadmap/adapters/cli/health/fixers/milestone_naming_compliance_fixer.py +244 -0
- roadmap/adapters/cli/health/fixers/milestone_parse_error_fixer.py +162 -0
- roadmap/adapters/cli/health/fixers/milestone_validation_fixer.py +211 -0
- roadmap/adapters/cli/health/fixers/old_backups_fixer.py +135 -0
- roadmap/adapters/cli/health/fixers/orphaned_issues_fixer.py +252 -0
- roadmap/adapters/cli/health/formatter.py +250 -0
- roadmap/adapters/cli/health/formatters.py +427 -0
- roadmap/adapters/cli/health/scan.py +293 -0
- roadmap/adapters/cli/init/__init__.py +5 -0
- roadmap/adapters/cli/init/commands.py +587 -0
- roadmap/adapters/cli/init.py +9 -0
- roadmap/adapters/cli/issues/__init__.py +70 -0
- roadmap/adapters/cli/issues/archive.py +137 -0
- roadmap/adapters/cli/issues/archive_class.py +253 -0
- roadmap/adapters/cli/issues/block.py +39 -0
- roadmap/adapters/cli/issues/close.py +216 -0
- roadmap/adapters/cli/issues/comment.py +178 -0
- roadmap/adapters/cli/issues/create.py +162 -0
- roadmap/adapters/cli/issues/delete.py +31 -0
- roadmap/adapters/cli/issues/deps.py +161 -0
- roadmap/adapters/cli/issues/issue_status_helpers.py +111 -0
- roadmap/adapters/cli/issues/link.py +308 -0
- roadmap/adapters/cli/issues/list.py +402 -0
- roadmap/adapters/cli/issues/lookup.py +96 -0
- roadmap/adapters/cli/issues/progress.py +102 -0
- roadmap/adapters/cli/issues/restore.py +96 -0
- roadmap/adapters/cli/issues/restore_class.py +57 -0
- roadmap/adapters/cli/issues/start.py +165 -0
- roadmap/adapters/cli/issues/sync_status.py +374 -0
- roadmap/adapters/cli/issues/unblock.py +43 -0
- roadmap/adapters/cli/issues/unlink.py +104 -0
- roadmap/adapters/cli/issues/update.py +120 -0
- roadmap/adapters/cli/issues/view.py +36 -0
- roadmap/adapters/cli/layout.py +220 -0
- roadmap/adapters/cli/mappers.py +200 -0
- roadmap/adapters/cli/milestones/__init__.py +52 -0
- roadmap/adapters/cli/milestones/archive.py +125 -0
- roadmap/adapters/cli/milestones/archive_class.py +236 -0
- roadmap/adapters/cli/milestones/assign.py +62 -0
- roadmap/adapters/cli/milestones/close.py +177 -0
- roadmap/adapters/cli/milestones/create.py +131 -0
- roadmap/adapters/cli/milestones/delete.py +27 -0
- roadmap/adapters/cli/milestones/kanban.py +123 -0
- roadmap/adapters/cli/milestones/list.py +87 -0
- roadmap/adapters/cli/milestones/recalculate.py +79 -0
- roadmap/adapters/cli/milestones/restore.py +87 -0
- roadmap/adapters/cli/milestones/restore_class.py +99 -0
- roadmap/adapters/cli/milestones/update.py +61 -0
- roadmap/adapters/cli/milestones/view.py +142 -0
- roadmap/adapters/cli/output_manager.py +319 -0
- roadmap/adapters/cli/presentation/base_presenter.py +121 -0
- roadmap/adapters/cli/presentation/cleanup_presenter.py +235 -0
- roadmap/adapters/cli/presentation/core_initialization_presenter.py +277 -0
- roadmap/adapters/cli/presentation/crud_presenter.py +134 -0
- roadmap/adapters/cli/presentation/daily_summary_presenter.py +266 -0
- roadmap/adapters/cli/presentation/issue_presenter.py +258 -0
- roadmap/adapters/cli/presentation/milestone_list_presenter.py +135 -0
- roadmap/adapters/cli/presentation/milestone_presenter.py +297 -0
- roadmap/adapters/cli/presentation/project_presenter.py +233 -0
- roadmap/adapters/cli/presentation/project_status_presenter.py +186 -0
- roadmap/adapters/cli/presentation/table_builders.py +95 -0
- roadmap/adapters/cli/projects/__init__.py +42 -0
- roadmap/adapters/cli/projects/archive.py +127 -0
- roadmap/adapters/cli/projects/archive_class.py +96 -0
- roadmap/adapters/cli/projects/close.py +94 -0
- roadmap/adapters/cli/projects/create.py +50 -0
- roadmap/adapters/cli/projects/delete.py +27 -0
- roadmap/adapters/cli/projects/list.py +227 -0
- roadmap/adapters/cli/projects/restore.py +87 -0
- roadmap/adapters/cli/projects/restore_class.py +56 -0
- roadmap/adapters/cli/projects/update.py +57 -0
- roadmap/adapters/cli/projects/view.py +157 -0
- roadmap/adapters/cli/services/__init__.py +1 -0
- roadmap/adapters/cli/services/daily_summary_service.py +313 -0
- roadmap/adapters/cli/services/export_manager.py +268 -0
- roadmap/adapters/cli/services/milestone_list_service.py +266 -0
- roadmap/adapters/cli/services/project_initialization_service.py +29 -0
- roadmap/adapters/cli/services/project_status_service.py +462 -0
- roadmap/adapters/cli/services/sync_service.py +62 -0
- roadmap/adapters/cli/status.py +408 -0
- roadmap/adapters/cli/styling.py +21 -0
- roadmap/adapters/cli/sync.py +1117 -0
- roadmap/adapters/cli/sync_context.py +432 -0
- roadmap/adapters/cli/sync_handlers/__init__.py +77 -0
- roadmap/adapters/cli/sync_handlers/apply_ops.py +522 -0
- roadmap/adapters/cli/sync_handlers/baseline_ops.py +366 -0
- roadmap/adapters/cli/sync_handlers/conflict_ops.py +161 -0
- roadmap/adapters/cli/sync_handlers/dry_run_display.py +237 -0
- roadmap/adapters/cli/sync_handlers/interactive_resolver.py +396 -0
- roadmap/adapters/cli/sync_handlers/progress_tracker.py +128 -0
- roadmap/adapters/cli/sync_metrics_command.py +190 -0
- roadmap/adapters/cli/sync_presenter.py +58 -0
- roadmap/adapters/cli/sync_validation.py +295 -0
- roadmap/adapters/cli/today.py +52 -0
- roadmap/adapters/cli/utils/click_options.py +38 -0
- roadmap/adapters/git/__init__.py +1 -0
- roadmap/adapters/git/git.py +208 -0
- roadmap/adapters/git/git_branch_manager.py +400 -0
- roadmap/adapters/git/git_command_executor.py +56 -0
- roadmap/adapters/git/git_commit_analyzer.py +334 -0
- roadmap/adapters/git/git_hooks.py +22 -0
- roadmap/adapters/git/git_hooks_manager.py +455 -0
- roadmap/adapters/git/git_repository_info.py +65 -0
- roadmap/adapters/git/hook_installer.py +106 -0
- roadmap/adapters/git/hook_registry.py +97 -0
- roadmap/adapters/git/hook_script_generator.py +58 -0
- roadmap/adapters/git/sync_monitor.py +409 -0
- roadmap/adapters/git/workflow_automation.py +286 -0
- roadmap/adapters/github/__init__.py +1 -0
- roadmap/adapters/github/github.py +360 -0
- roadmap/adapters/github/handlers/__init__.py +17 -0
- roadmap/adapters/github/handlers/base.py +337 -0
- roadmap/adapters/github/handlers/collaborators.py +165 -0
- roadmap/adapters/github/handlers/comments.py +118 -0
- roadmap/adapters/github/handlers/issues.py +150 -0
- roadmap/adapters/github/handlers/labels.py +164 -0
- roadmap/adapters/github/handlers/milestones.py +104 -0
- roadmap/adapters/persistence/__init__.py +35 -0
- roadmap/adapters/persistence/conflict_resolver.py +190 -0
- roadmap/adapters/persistence/database_manager.py +492 -0
- roadmap/adapters/persistence/entity_sync_coordinators.py +672 -0
- roadmap/adapters/persistence/file_locking.py +348 -0
- roadmap/adapters/persistence/file_parser.py +92 -0
- roadmap/adapters/persistence/file_synchronizer.py +107 -0
- roadmap/adapters/persistence/focused_managers.py +140 -0
- roadmap/adapters/persistence/git_history.py +330 -0
- roadmap/adapters/persistence/parser/__init__.py +20 -0
- roadmap/adapters/persistence/parser/frontmatter.py +152 -0
- roadmap/adapters/persistence/parser/issue.py +245 -0
- roadmap/adapters/persistence/parser/milestone.py +146 -0
- roadmap/adapters/persistence/parser/project.py +106 -0
- roadmap/adapters/persistence/persistence.py +288 -0
- roadmap/adapters/persistence/repositories/__init__.py +15 -0
- roadmap/adapters/persistence/repositories/issue_repository.py +223 -0
- roadmap/adapters/persistence/repositories/milestone_repository.py +140 -0
- roadmap/adapters/persistence/repositories/project_repository.py +168 -0
- roadmap/adapters/persistence/repositories/remote_link_repository.py +355 -0
- roadmap/adapters/persistence/repositories/sync_state_repository.py +66 -0
- roadmap/adapters/persistence/storage/__init__.py +36 -0
- roadmap/adapters/persistence/storage/conflicts.py +101 -0
- roadmap/adapters/persistence/storage/connection_manager.py +79 -0
- roadmap/adapters/persistence/storage/issue_storage.py +89 -0
- roadmap/adapters/persistence/storage/milestone_storage.py +80 -0
- roadmap/adapters/persistence/storage/project_storage.py +102 -0
- roadmap/adapters/persistence/storage/queries.py +227 -0
- roadmap/adapters/persistence/storage/state_manager.py +652 -0
- roadmap/adapters/persistence/storage/sync_state_storage.py +207 -0
- roadmap/adapters/persistence/sync_metrics_repository.py +342 -0
- roadmap/adapters/persistence/sync_orchestrator.py +293 -0
- roadmap/adapters/persistence/sync_state_tracker.py +86 -0
- roadmap/adapters/persistence/yaml_repositories.py +711 -0
- roadmap/adapters/sync/__init__.py +21 -0
- roadmap/adapters/sync/backend_factory.py +108 -0
- roadmap/adapters/sync/backends/__init__.py +15 -0
- roadmap/adapters/sync/backends/converters.py +209 -0
- roadmap/adapters/sync/backends/github_backend_helpers.py +380 -0
- roadmap/adapters/sync/backends/github_client.py +99 -0
- roadmap/adapters/sync/backends/github_sync_backend.py +792 -0
- roadmap/adapters/sync/backends/github_sync_ops.py +908 -0
- roadmap/adapters/sync/backends/services/__init__.py +1 -0
- roadmap/adapters/sync/backends/services/github_authentication_service.py +105 -0
- roadmap/adapters/sync/backends/services/github_issue_delete_service.py +423 -0
- roadmap/adapters/sync/backends/services/github_issue_dependency_service.py +63 -0
- roadmap/adapters/sync/backends/services/github_issue_fetch_service.py +158 -0
- roadmap/adapters/sync/backends/services/github_label_sync_service.py +126 -0
- roadmap/adapters/sync/backends/services/github_local_issue_sync_service.py +229 -0
- roadmap/adapters/sync/backends/services/github_milestone_fetch_service.py +204 -0
- roadmap/adapters/sync/backends/vanilla_git_sync_backend.py +198 -0
- roadmap/adapters/sync/services/__init__.py +11 -0
- roadmap/adapters/sync/services/baseline_state_handler.py +83 -0
- roadmap/adapters/sync/services/conflict_converter.py +85 -0
- roadmap/adapters/sync/services/issue_persistence_service.py +263 -0
- roadmap/adapters/sync/services/issue_state_service.py +243 -0
- roadmap/adapters/sync/services/local_change_filter.py +129 -0
- roadmap/adapters/sync/services/pull_result_processor.py +71 -0
- roadmap/adapters/sync/services/remote_issue_creation_service.py +112 -0
- roadmap/adapters/sync/services/sync_analysis_service.py +250 -0
- roadmap/adapters/sync/services/sync_authentication_service.py +57 -0
- roadmap/adapters/sync/services/sync_data_fetch_service.py +212 -0
- roadmap/adapters/sync/services/sync_linking_service.py +329 -0
- roadmap/adapters/sync/services/sync_report_service.py +62 -0
- roadmap/adapters/sync/services/sync_state_update_service.py +51 -0
- roadmap/adapters/sync/sync_cache_orchestrator.py +454 -0
- roadmap/adapters/sync/sync_merge_engine.py +416 -0
- roadmap/adapters/sync/sync_merge_orchestrator.py +1313 -0
- roadmap/adapters/sync/sync_retrieval_orchestrator.py +810 -0
- roadmap/application/services/__init__.py +1 -0
- roadmap/application/services/deduplicate_service.py +517 -0
- roadmap/application/use_cases/__init__.py +1 -0
- roadmap/common/__init__.py +308 -0
- roadmap/common/cache.py +209 -0
- roadmap/common/cli_errors.py +147 -0
- roadmap/common/configuration/__init__.py +33 -0
- roadmap/common/configuration/config_loader.py +264 -0
- roadmap/common/configuration/config_manager.py +164 -0
- roadmap/common/configuration/config_schema.py +145 -0
- roadmap/common/configuration/github/__init__.py +9 -0
- roadmap/common/configuration/github/config_manager.py +154 -0
- roadmap/common/configuration/github/token_resolver.py +84 -0
- roadmap/common/console.py +184 -0
- roadmap/common/constants.py +134 -0
- roadmap/common/datetime_parser.py +319 -0
- roadmap/common/error_formatter.py +84 -0
- roadmap/common/errors/__init__.py +143 -0
- roadmap/common/errors/error_base.py +73 -0
- roadmap/common/errors/error_file.py +82 -0
- roadmap/common/errors/error_git.py +67 -0
- roadmap/common/errors/error_handler.py +166 -0
- roadmap/common/errors/error_network.py +90 -0
- roadmap/common/errors/error_security.py +78 -0
- roadmap/common/errors/error_standards.py +561 -0
- roadmap/common/errors/error_validation.py +111 -0
- roadmap/common/errors/exceptions.py +432 -0
- roadmap/common/formatters/__init__.py +29 -0
- roadmap/common/formatters/base_table_formatter.py +96 -0
- roadmap/common/formatters/export/__init__.py +7 -0
- roadmap/common/formatters/export/issue_exporter.py +97 -0
- roadmap/common/formatters/helpers.py +28 -0
- roadmap/common/formatters/kanban/__init__.py +9 -0
- roadmap/common/formatters/kanban/layout.py +48 -0
- roadmap/common/formatters/kanban/organizer.py +81 -0
- roadmap/common/formatters/output/__init__.py +15 -0
- roadmap/common/formatters/tables/__init__.py +11 -0
- roadmap/common/formatters/tables/column_factory.py +312 -0
- roadmap/common/formatters/tables/issue_table.py +276 -0
- roadmap/common/formatters/tables/milestone_table.py +247 -0
- roadmap/common/formatters/tables/project_table.py +195 -0
- roadmap/common/formatters/text/__init__.py +57 -0
- roadmap/common/formatters/text/basic.py +217 -0
- roadmap/common/formatters/text/display.py +42 -0
- roadmap/common/formatters/text/duration.py +36 -0
- roadmap/common/formatters/text/operations.py +325 -0
- roadmap/common/formatters/text/status_badges.py +57 -0
- roadmap/common/initialization/github/__init__.py +11 -0
- roadmap/common/initialization/github/setup_service.py +238 -0
- roadmap/common/initialization/github/setup_validator.py +78 -0
- roadmap/common/logging/__init__.py +113 -0
- roadmap/common/logging/audit_logging.py +5 -0
- roadmap/common/logging/correlation.py +45 -0
- roadmap/common/logging/decorators.py +267 -0
- roadmap/common/logging/error_logging.py +217 -0
- roadmap/common/logging/formatters.py +124 -0
- roadmap/common/logging/loggers.py +68 -0
- roadmap/common/logging/performance_tracking.py +267 -0
- roadmap/common/logging/utils.py +335 -0
- roadmap/common/models/__init__.py +44 -0
- roadmap/common/models/cli_models.py +118 -0
- roadmap/common/models/config_models.py +199 -0
- roadmap/common/models/output_models.py +381 -0
- roadmap/common/observability/__init__.py +28 -0
- roadmap/common/observability/instrumentation.py +103 -0
- roadmap/common/observability/observability.py +76 -0
- roadmap/common/observability/otel_init.py +109 -0
- roadmap/common/output_formatter.py +393 -0
- roadmap/common/progress.py +379 -0
- roadmap/common/result.py +396 -0
- roadmap/common/security/__init__.py +48 -0
- roadmap/common/security/exceptions.py +13 -0
- roadmap/common/security/export_cleanup.py +79 -0
- roadmap/common/security/file_operations.py +104 -0
- roadmap/common/security/filename_sanitization.py +54 -0
- roadmap/common/security/logging.py +27 -0
- roadmap/common/security/path_validation.py +137 -0
- roadmap/common/security/temp_files.py +41 -0
- roadmap/common/services/__init__.py +65 -0
- roadmap/common/services/decorators.py +183 -0
- roadmap/common/services/logging_utils.py +208 -0
- roadmap/common/services/metrics.py +161 -0
- roadmap/common/services/performance.py +219 -0
- roadmap/common/services/profiling.py +288 -0
- roadmap/common/services/retry.py +288 -0
- roadmap/common/status_style_manager.py +114 -0
- roadmap/common/union_find.py +88 -0
- roadmap/common/update_constants.py +13 -0
- roadmap/common/utils/__init__.py +65 -0
- roadmap/common/utils/cli_helpers.py +381 -0
- roadmap/common/utils/file_utils.py +440 -0
- roadmap/common/utils/path_utils.py +38 -0
- roadmap/common/utils/status_utils.py +130 -0
- roadmap/common/utils/timezone_utils.py +480 -0
- roadmap/common/validation/__init__.py +37 -0
- roadmap/common/validation/field_validator.py +104 -0
- roadmap/common/validation/result.py +37 -0
- roadmap/common/validation/roadmap_validator.py +310 -0
- roadmap/common/validation/schema_validator.py +36 -0
- roadmap/common/validation/validators.py +50 -0
- roadmap/core/__init__.py +1 -0
- roadmap/core/domain/__init__.py +30 -0
- roadmap/core/domain/comment.py +24 -0
- roadmap/core/domain/health.py +15 -0
- roadmap/core/domain/issue.py +274 -0
- roadmap/core/domain/milestone.py +173 -0
- roadmap/core/domain/ports/__init__.py +1 -0
- roadmap/core/domain/ports/baseline_repository.py +24 -0
- roadmap/core/domain/ports/issue_repository.py +34 -0
- roadmap/core/domain/ports/remote_backend_port.py +31 -0
- roadmap/core/domain/project.py +130 -0
- roadmap/core/interfaces/__init__.py +109 -0
- roadmap/core/interfaces/assignee_validator.py +40 -0
- roadmap/core/interfaces/backend_factory.py +175 -0
- roadmap/core/interfaces/github.py +102 -0
- roadmap/core/interfaces/parsers.py +140 -0
- roadmap/core/interfaces/persistence.py +45 -0
- roadmap/core/interfaces/repositories.py +174 -0
- roadmap/core/interfaces/state_managers.py +111 -0
- roadmap/core/interfaces/state_storage.py +64 -0
- roadmap/core/interfaces/sync_backend.py +275 -0
- roadmap/core/interfaces/sync_services.py +119 -0
- roadmap/core/interfaces/sync_validators.py +180 -0
- roadmap/core/models/__init__.py +31 -0
- roadmap/core/models/sync_models.py +162 -0
- roadmap/core/models.py +115 -0
- roadmap/core/observability/__init__.py +17 -0
- roadmap/core/observability/sync_metrics.py +699 -0
- roadmap/core/repositories.py +200 -0
- roadmap/core/services/__init__.py +313 -0
- roadmap/core/services/baseline/__init__.py +1 -0
- roadmap/core/services/baseline/baseline_builder_progress.py +274 -0
- roadmap/core/services/baseline/baseline_retriever.py +63 -0
- roadmap/core/services/baseline/baseline_selector.py +248 -0
- roadmap/core/services/baseline/baseline_state_retriever.py +284 -0
- roadmap/core/services/baseline/optimized_baseline_builder.py +425 -0
- roadmap/core/services/comment/__init__.py +1 -0
- roadmap/core/services/comment/comment_service.py +277 -0
- roadmap/core/services/git/__init__.py +1 -0
- roadmap/core/services/git/git_hook_auto_sync_service.py +403 -0
- roadmap/core/services/github/__init__.py +1 -0
- roadmap/core/services/github/github_change_detector.py +162 -0
- roadmap/core/services/github/github_config_validator.py +148 -0
- roadmap/core/services/github/github_conflict_detector.py +179 -0
- roadmap/core/services/github/github_entity_classifier.py +51 -0
- roadmap/core/services/github/github_integration_service.py +439 -0
- roadmap/core/services/github/github_issue_client.py +346 -0
- roadmap/core/services/health/__init__.py +1 -0
- roadmap/core/services/health/backup_cleanup_service.py +202 -0
- roadmap/core/services/health/data_integrity_validator_service.py +90 -0
- roadmap/core/services/health/entity_health_scanner.py +460 -0
- roadmap/core/services/health/file_repair_service.py +193 -0
- roadmap/core/services/health/health_check_service.py +166 -0
- roadmap/core/services/health/health_models.py +80 -0
- roadmap/core/services/health/infrastructure_validator_service.py +328 -0
- roadmap/core/services/health/issue_health_scanner.py +263 -0
- roadmap/core/services/helpers/__init__.py +18 -0
- roadmap/core/services/helpers/status_change_helpers.py +88 -0
- roadmap/core/services/initialization/__init__.py +19 -0
- roadmap/core/services/initialization/utils.py +104 -0
- roadmap/core/services/initialization/validator.py +78 -0
- roadmap/core/services/initialization/workflow.py +182 -0
- roadmap/core/services/initialization_service.py +111 -0
- roadmap/core/services/issue/__init__.py +1 -0
- roadmap/core/services/issue/assignee_validation_service.py +312 -0
- roadmap/core/services/issue/issue_creation_service.py +309 -0
- roadmap/core/services/issue/issue_filter_service.py +302 -0
- roadmap/core/services/issue/issue_matching_service.py +127 -0
- roadmap/core/services/issue/issue_service.py +765 -0
- roadmap/core/services/issue/issue_update_service.py +144 -0
- roadmap/core/services/issue/start_issue_service.py +174 -0
- roadmap/core/services/issue_helpers/__init__.py +18 -0
- roadmap/core/services/issue_helpers/issue_filters.py +296 -0
- roadmap/core/services/milestone_service.py +438 -0
- roadmap/core/services/project/__init__.py +1 -0
- roadmap/core/services/project/project_service.py +434 -0
- roadmap/core/services/project/project_status_service.py +125 -0
- roadmap/core/services/project_init/__init__.py +22 -0
- roadmap/core/services/project_init/context_detection.py +146 -0
- roadmap/core/services/project_init/creation.py +76 -0
- roadmap/core/services/project_init/detection.py +51 -0
- roadmap/core/services/project_init/template.py +228 -0
- roadmap/core/services/status_change_service.py +88 -0
- roadmap/core/services/sync/__init__.py +1 -0
- roadmap/core/services/sync/batch_processor.py +290 -0
- roadmap/core/services/sync/conflict_resolver.py +154 -0
- roadmap/core/services/sync/dependency_resolver.py +367 -0
- roadmap/core/services/sync/duplicate_detector.py +771 -0
- roadmap/core/services/sync/duplicate_resolver.py +315 -0
- roadmap/core/services/sync/error_classification.py +470 -0
- roadmap/core/services/sync/performance.py +263 -0
- roadmap/core/services/sync/sync_change_computer.py +211 -0
- roadmap/core/services/sync/sync_checkpoint.py +348 -0
- roadmap/core/services/sync/sync_conflict_detector.py +147 -0
- roadmap/core/services/sync/sync_conflict_resolver.py +448 -0
- roadmap/core/services/sync/sync_errors.py +383 -0
- roadmap/core/services/sync/sync_key_normalizer.py +222 -0
- roadmap/core/services/sync/sync_metadata_service.py +361 -0
- roadmap/core/services/sync/sync_plan.py +171 -0
- roadmap/core/services/sync/sync_plan_executor.py +447 -0
- roadmap/core/services/sync/sync_report.py +296 -0
- roadmap/core/services/sync/sync_state.py +173 -0
- roadmap/core/services/sync/sync_state_comparator.py +690 -0
- roadmap/core/services/sync/sync_state_manager.py +431 -0
- roadmap/core/services/sync/sync_state_normalizer.py +98 -0
- roadmap/core/services/sync/sync_three_way.py +78 -0
- roadmap/core/services/sync/three_way_merger.py +178 -0
- roadmap/core/services/utils/__init__.py +1 -0
- roadmap/core/services/utils/configuration_service.py +113 -0
- roadmap/core/services/utils/critical_path_calculator.py +418 -0
- roadmap/core/services/utils/dependency_analyzer.py +360 -0
- roadmap/core/services/utils/field_conflict_detector.py +126 -0
- roadmap/core/services/utils/remote_fetcher.py +202 -0
- roadmap/core/services/utils/remote_state_normalizer.py +110 -0
- roadmap/core/services/utils/retry_policy.py +51 -0
- roadmap/core/services/validator_base.py +130 -0
- roadmap/core/services/validators/__init__.py +28 -0
- roadmap/core/services/validators/_utils.py +20 -0
- roadmap/core/services/validators/archivable_issues_validator.py +71 -0
- roadmap/core/services/validators/archivable_milestones_validator.py +69 -0
- roadmap/core/services/validators/backup_validator.py +89 -0
- roadmap/core/services/validators/data_integrity_validator.py +84 -0
- roadmap/core/services/validators/duplicate_issues_validator.py +75 -0
- roadmap/core/services/validators/duplicate_milestones_validator.py +141 -0
- roadmap/core/services/validators/folder_structure_validator.py +165 -0
- roadmap/core/services/validators/health_status_utils.py +28 -0
- roadmap/core/services/validators/milestone_naming_validator.py +146 -0
- roadmap/core/services/validators/missing_headlines_validator.py +97 -0
- roadmap/core/services/validators/orphaned_issues_validator.py +142 -0
- roadmap/core/services/validators/orphaned_milestones_validator.py +85 -0
- roadmap/core/utils/git_remote_parser.py +83 -0
- roadmap/core/utils/github_urls.py +66 -0
- roadmap/domain/validation.py +30 -0
- roadmap/infrastructure/__init__.py +55 -0
- roadmap/infrastructure/coordination/__init__.py +8 -0
- roadmap/infrastructure/coordination/coordinator_params.py +82 -0
- roadmap/infrastructure/coordination/core.py +446 -0
- roadmap/infrastructure/coordination/git_coordinator.py +160 -0
- roadmap/infrastructure/coordination/initialization.py +348 -0
- roadmap/infrastructure/coordination/issue_coordinator.py +154 -0
- roadmap/infrastructure/coordination/issue_operations.py +456 -0
- roadmap/infrastructure/coordination/milestone_coordinator.py +135 -0
- roadmap/infrastructure/coordination/milestone_operations.py +201 -0
- roadmap/infrastructure/coordination/project_coordinator.py +113 -0
- roadmap/infrastructure/coordination/project_operations.py +144 -0
- roadmap/infrastructure/coordination/team_coordinator.py +107 -0
- roadmap/infrastructure/coordination/user_operations.py +150 -0
- roadmap/infrastructure/coordination/validation_coordinator.py +249 -0
- roadmap/infrastructure/coordination_gateway.py +152 -0
- roadmap/infrastructure/git/__init__.py +6 -0
- roadmap/infrastructure/git/git_integration_ops.py +234 -0
- roadmap/infrastructure/git_gateway.py +35 -0
- roadmap/infrastructure/github_gateway.py +52 -0
- roadmap/infrastructure/maintenance/__init__.py +5 -0
- roadmap/infrastructure/maintenance/cleanup.py +483 -0
- roadmap/infrastructure/observability/__init__.py +7 -0
- roadmap/infrastructure/observability/health.py +196 -0
- roadmap/infrastructure/observability/health_formatter.py +73 -0
- roadmap/infrastructure/observability/specialized_health_checkers.py +188 -0
- roadmap/infrastructure/persistence_gateway.py +164 -0
- roadmap/infrastructure/security/__init__.py +1 -0
- roadmap/infrastructure/security/credentials.py +489 -0
- roadmap/infrastructure/sync_gateway.py +94 -0
- roadmap/infrastructure/validation/__init__.py +7 -0
- roadmap/infrastructure/validation/file_enumeration.py +219 -0
- roadmap/infrastructure/validation/github_assignee_validator.py +47 -0
- roadmap/infrastructure/validation/github_validator.py +101 -0
- roadmap/infrastructure/validation/milestone_consistency_validator.py +96 -0
- roadmap/infrastructure/validation/vanilla_assignee_validator.py +37 -0
- roadmap/infrastructure/validation_gateway.py +96 -0
- roadmap/presentation/formatters/sync_metrics_formatter.py +355 -0
- roadmap/settings.py +345 -0
- roadmap/templates/github_workflows/ci-cd-roadmap.yml +241 -0
- roadmap/templates/github_workflows/issue-lifecycle.yml +236 -0
- roadmap/templates/github_workflows/roadmap-integration.yml +137 -0
- roadmap/templates/github_workflows/roadmap-starter.yml +59 -0
- roadmap/version.py +381 -0
- roadmap_cli-0.1.1.dist-info/METADATA +448 -0
- roadmap_cli-0.1.1.dist-info/RECORD +521 -0
- roadmap_cli-0.1.1.dist-info/WHEEL +4 -0
- roadmap_cli-0.1.1.dist-info/entry_points.txt +2 -0
- roadmap_cli-0.1.1.dist-info/licenses/LICENSE.md +21 -0
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
"""Validator for orphaned issues."""
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
from roadmap.common.logging import get_logger
|
|
6
|
+
from roadmap.core.domain.issue import Status
|
|
7
|
+
from roadmap.core.services.validator_base import HealthStatus
|
|
8
|
+
|
|
9
|
+
logger = get_logger(__name__)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class OrphanedIssuesValidator:
|
|
13
|
+
"""Validator for orphaned issues (in wrong folder based on milestone)."""
|
|
14
|
+
|
|
15
|
+
@staticmethod
|
|
16
|
+
def scan_for_orphaned_issues(core) -> list[dict]:
|
|
17
|
+
"""Scan for issues in wrong folder (not matching their milestone).
|
|
18
|
+
|
|
19
|
+
Returns a list of misplaced issue dicts with id, title, and details.
|
|
20
|
+
"""
|
|
21
|
+
misplaced = []
|
|
22
|
+
|
|
23
|
+
try:
|
|
24
|
+
issues_dir = Path(".roadmap/issues").resolve()
|
|
25
|
+
archive_dir = Path(".roadmap/archive/issues").resolve()
|
|
26
|
+
|
|
27
|
+
if not issues_dir.exists():
|
|
28
|
+
return misplaced
|
|
29
|
+
|
|
30
|
+
# Scan all issues
|
|
31
|
+
for issue in core.issues.list():
|
|
32
|
+
# Determine expected folder
|
|
33
|
+
expected_folder = OrphanedIssuesValidator._get_expected_folder(issue)
|
|
34
|
+
|
|
35
|
+
# Find actual folder
|
|
36
|
+
actual_folder = OrphanedIssuesValidator._find_issue_folder(
|
|
37
|
+
issue.id, issues_dir, archive_dir
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
# Issue is misplaced if:
|
|
41
|
+
# 1. It's at root level (actual_folder == issues_dir)
|
|
42
|
+
# 2. Or it's in wrong folder (actual_folder != expected_folder)
|
|
43
|
+
if actual_folder:
|
|
44
|
+
if actual_folder == issues_dir or actual_folder != expected_folder:
|
|
45
|
+
misplaced.append(
|
|
46
|
+
{
|
|
47
|
+
"id": issue.id,
|
|
48
|
+
"title": issue.title,
|
|
49
|
+
"milestone": issue.milestone or "(none)",
|
|
50
|
+
"current_folder": str(actual_folder),
|
|
51
|
+
"expected_folder": str(expected_folder),
|
|
52
|
+
}
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
except Exception as e:
|
|
56
|
+
logger.debug("scan_orphaned_issues_error", error=str(e))
|
|
57
|
+
|
|
58
|
+
return misplaced
|
|
59
|
+
|
|
60
|
+
@staticmethod
|
|
61
|
+
def check_orphaned_issues(core) -> tuple[str, str]:
|
|
62
|
+
"""Check for orphaned issues.
|
|
63
|
+
|
|
64
|
+
Returns:
|
|
65
|
+
Tuple of (status, message) describing the health check result
|
|
66
|
+
"""
|
|
67
|
+
try:
|
|
68
|
+
misplaced = OrphanedIssuesValidator.scan_for_orphaned_issues(core)
|
|
69
|
+
|
|
70
|
+
if not misplaced:
|
|
71
|
+
logger.debug("health_check_orphaned_issues", status="none")
|
|
72
|
+
return HealthStatus.HEALTHY, "No orphaned issues found"
|
|
73
|
+
|
|
74
|
+
count = len(misplaced)
|
|
75
|
+
message = (
|
|
76
|
+
f"⚠️ {count} orphaned issue(s) found (in wrong folder): "
|
|
77
|
+
"These issues are not in the folder matching their milestone"
|
|
78
|
+
)
|
|
79
|
+
logger.warning(
|
|
80
|
+
"health_check_orphaned_issues", count=count, severity="operational"
|
|
81
|
+
)
|
|
82
|
+
return HealthStatus.DEGRADED, message
|
|
83
|
+
|
|
84
|
+
except Exception as e:
|
|
85
|
+
logger.debug("health_check_orphaned_issues_failed", error=str(e))
|
|
86
|
+
return HealthStatus.HEALTHY, "Could not check for orphaned issues"
|
|
87
|
+
|
|
88
|
+
@staticmethod
|
|
89
|
+
def _get_expected_folder(issue) -> Path:
|
|
90
|
+
"""Determine expected folder for an issue.
|
|
91
|
+
|
|
92
|
+
Args:
|
|
93
|
+
issue: Issue object
|
|
94
|
+
|
|
95
|
+
Returns:
|
|
96
|
+
Path to expected folder
|
|
97
|
+
"""
|
|
98
|
+
# Closed issues go to archive
|
|
99
|
+
base_path = (
|
|
100
|
+
Path(".roadmap/archive/issues").resolve()
|
|
101
|
+
if issue.status == Status.CLOSED
|
|
102
|
+
else Path(".roadmap/issues").resolve()
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
# If no milestone, assign to backlog
|
|
106
|
+
milestone = issue.milestone or "backlog"
|
|
107
|
+
|
|
108
|
+
return base_path / milestone
|
|
109
|
+
|
|
110
|
+
@staticmethod
|
|
111
|
+
def _find_issue_folder(
|
|
112
|
+
issue_id: str, issues_dir: Path, archive_dir: Path
|
|
113
|
+
) -> Path | None:
|
|
114
|
+
"""Find the actual folder containing an issue.
|
|
115
|
+
|
|
116
|
+
Args:
|
|
117
|
+
issue_id: Issue ID to find
|
|
118
|
+
issues_dir: Path to .roadmap/issues
|
|
119
|
+
archive_dir: Path to .roadmap/archive/issues
|
|
120
|
+
|
|
121
|
+
Returns:
|
|
122
|
+
Path to folder containing the issue, or None if at root level
|
|
123
|
+
"""
|
|
124
|
+
# Check if file is at root level (loose file)
|
|
125
|
+
for file in issues_dir.glob(f"{issue_id}*.md"):
|
|
126
|
+
if file.is_file():
|
|
127
|
+
return issues_dir # Return root to indicate it's loose
|
|
128
|
+
|
|
129
|
+
# Check main issues directory subfolders
|
|
130
|
+
for folder in issues_dir.iterdir():
|
|
131
|
+
if folder.is_dir():
|
|
132
|
+
for _ in folder.glob(f"{issue_id}*.md"):
|
|
133
|
+
return folder
|
|
134
|
+
|
|
135
|
+
# Check archive directory
|
|
136
|
+
if archive_dir.exists():
|
|
137
|
+
for folder in archive_dir.iterdir():
|
|
138
|
+
if folder.is_dir():
|
|
139
|
+
for _ in folder.glob(f"{issue_id}*.md"):
|
|
140
|
+
return folder
|
|
141
|
+
|
|
142
|
+
return None
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"""Validator for orphaned milestones."""
|
|
2
|
+
|
|
3
|
+
from roadmap.common.logging import get_logger
|
|
4
|
+
from roadmap.core.services.validator_base import BaseValidator, HealthStatus
|
|
5
|
+
from roadmap.infrastructure.coordination.core import RoadmapCore
|
|
6
|
+
|
|
7
|
+
logger = get_logger(__name__)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class OrphanedMilestonesValidator(BaseValidator):
|
|
11
|
+
"""Validator for orphaned milestones (not assigned to any project)."""
|
|
12
|
+
|
|
13
|
+
@staticmethod
|
|
14
|
+
def get_check_name() -> str:
|
|
15
|
+
"""Get the name of this check.
|
|
16
|
+
|
|
17
|
+
Returns:
|
|
18
|
+
String identifier for the orphaned_milestones check.
|
|
19
|
+
"""
|
|
20
|
+
return "orphaned_milestones"
|
|
21
|
+
|
|
22
|
+
@staticmethod
|
|
23
|
+
def scan_for_orphaned_milestones(core) -> list[dict]:
|
|
24
|
+
"""Scan for milestones not assigned to any project.
|
|
25
|
+
|
|
26
|
+
Returns a list of orphaned milestone dicts with name, description, and details.
|
|
27
|
+
"""
|
|
28
|
+
orphaned = []
|
|
29
|
+
|
|
30
|
+
try:
|
|
31
|
+
all_milestones = core.milestones.list()
|
|
32
|
+
all_projects = core.projects.list()
|
|
33
|
+
|
|
34
|
+
# Build set of milestone names assigned to projects
|
|
35
|
+
assigned_milestone_names = set()
|
|
36
|
+
for project in all_projects:
|
|
37
|
+
assigned_milestone_names.update(project.milestones)
|
|
38
|
+
|
|
39
|
+
# Find milestones not in any project
|
|
40
|
+
for milestone in all_milestones:
|
|
41
|
+
if milestone.name not in assigned_milestone_names:
|
|
42
|
+
orphaned.append(
|
|
43
|
+
{
|
|
44
|
+
"name": milestone.name,
|
|
45
|
+
"content": milestone.content or "(no description)",
|
|
46
|
+
"status": milestone.status.value,
|
|
47
|
+
"created": milestone.created.isoformat()
|
|
48
|
+
if milestone.created
|
|
49
|
+
else None,
|
|
50
|
+
}
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
except Exception as e:
|
|
54
|
+
logger.debug("scan_orphaned_milestones_error", error=str(e))
|
|
55
|
+
|
|
56
|
+
return orphaned
|
|
57
|
+
|
|
58
|
+
@staticmethod
|
|
59
|
+
def perform_check() -> tuple[str, str]:
|
|
60
|
+
"""Check for orphaned milestones.
|
|
61
|
+
|
|
62
|
+
Returns:
|
|
63
|
+
Tuple of (status, message) describing the health check result
|
|
64
|
+
"""
|
|
65
|
+
try:
|
|
66
|
+
core = RoadmapCore()
|
|
67
|
+
orphaned = OrphanedMilestonesValidator.scan_for_orphaned_milestones(core)
|
|
68
|
+
|
|
69
|
+
if not orphaned:
|
|
70
|
+
logger.debug("health_check_orphaned_milestones", status="none")
|
|
71
|
+
return HealthStatus.HEALTHY, "No orphaned milestones found"
|
|
72
|
+
|
|
73
|
+
count = len(orphaned)
|
|
74
|
+
message = (
|
|
75
|
+
f"⚠️ {count} orphaned milestone(s) found (not assigned to any project): "
|
|
76
|
+
"These milestones should be assigned to a project or deleted"
|
|
77
|
+
)
|
|
78
|
+
logger.warning(
|
|
79
|
+
"health_check_orphaned_milestones", count=count, severity="operational"
|
|
80
|
+
)
|
|
81
|
+
return HealthStatus.DEGRADED, message
|
|
82
|
+
|
|
83
|
+
except Exception as e:
|
|
84
|
+
logger.debug("health_check_orphaned_milestones_failed", error=str(e))
|
|
85
|
+
return HealthStatus.HEALTHY, "Could not check for orphaned milestones"
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"""Utility for parsing GitHub information from git remote URLs."""
|
|
2
|
+
|
|
3
|
+
import re
|
|
4
|
+
import subprocess
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
from structlog import get_logger
|
|
8
|
+
|
|
9
|
+
logger = get_logger()
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def parse_github_remote(remote_url: str | None) -> tuple[str | None, str | None]:
|
|
13
|
+
"""Parse GitHub owner and repo from a git remote URL.
|
|
14
|
+
|
|
15
|
+
Supports both SSH and HTTPS formats:
|
|
16
|
+
- git@github.com:owner/repo.git
|
|
17
|
+
- https://github.com/owner/repo.git
|
|
18
|
+
- https://github.com/owner/repo
|
|
19
|
+
|
|
20
|
+
Args:
|
|
21
|
+
remote_url: Git remote URL string or None
|
|
22
|
+
|
|
23
|
+
Returns:
|
|
24
|
+
Tuple of (owner, repo) or (None, None) if not a valid GitHub URL
|
|
25
|
+
"""
|
|
26
|
+
if not remote_url or "github.com" not in remote_url:
|
|
27
|
+
return None, None
|
|
28
|
+
|
|
29
|
+
# Match SSH format: git@github.com:owner/repo.git
|
|
30
|
+
ssh_match = re.search(r"github\.com:([^/]+)/([^/.]+)", remote_url)
|
|
31
|
+
if ssh_match:
|
|
32
|
+
owner = ssh_match.group(1)
|
|
33
|
+
repo = ssh_match.group(2)
|
|
34
|
+
return owner, repo
|
|
35
|
+
|
|
36
|
+
# Match HTTPS format: https://github.com/owner/repo.git or https://github.com/owner/repo
|
|
37
|
+
https_match = re.search(r"github\.com/([^/]+)/([^/.]+)", remote_url)
|
|
38
|
+
if https_match:
|
|
39
|
+
owner = https_match.group(1)
|
|
40
|
+
repo = https_match.group(2)
|
|
41
|
+
return owner, repo
|
|
42
|
+
|
|
43
|
+
return None, None
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def get_github_from_git_remote(
|
|
47
|
+
repo_path: Path | None = None,
|
|
48
|
+
) -> tuple[str | None, str | None]:
|
|
49
|
+
"""Auto-detect GitHub owner and repo from git remote origin.
|
|
50
|
+
|
|
51
|
+
Args:
|
|
52
|
+
repo_path: Path to git repository (defaults to current directory)
|
|
53
|
+
|
|
54
|
+
Returns:
|
|
55
|
+
Tuple of (owner, repo) or (None, None) if not detected
|
|
56
|
+
"""
|
|
57
|
+
try:
|
|
58
|
+
cwd = str(repo_path) if repo_path else None
|
|
59
|
+
result = subprocess.run(
|
|
60
|
+
["git", "config", "--get", "remote.origin.url"],
|
|
61
|
+
capture_output=True,
|
|
62
|
+
text=True,
|
|
63
|
+
timeout=5,
|
|
64
|
+
cwd=cwd,
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
if result.returncode == 0 and result.stdout.strip():
|
|
68
|
+
remote_url = result.stdout.strip()
|
|
69
|
+
owner, repo = parse_github_remote(remote_url)
|
|
70
|
+
|
|
71
|
+
if owner and repo:
|
|
72
|
+
logger.info(
|
|
73
|
+
"github_detected_from_remote",
|
|
74
|
+
owner=owner,
|
|
75
|
+
repo=repo,
|
|
76
|
+
remote_url=remote_url,
|
|
77
|
+
)
|
|
78
|
+
return owner, repo
|
|
79
|
+
|
|
80
|
+
except (subprocess.TimeoutExpired, FileNotFoundError) as e:
|
|
81
|
+
logger.debug("git_remote_detection_failed", error=str(e))
|
|
82
|
+
|
|
83
|
+
return None, None
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"""Utilities for generating GitHub URLs on-demand."""
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def get_issue_url(owner: str, repo: str, issue_number: int | str) -> str:
|
|
5
|
+
"""Generate a GitHub issue URL.
|
|
6
|
+
|
|
7
|
+
Args:
|
|
8
|
+
owner: Repository owner
|
|
9
|
+
repo: Repository name
|
|
10
|
+
issue_number: Issue number
|
|
11
|
+
|
|
12
|
+
Returns:
|
|
13
|
+
Full GitHub issue URL
|
|
14
|
+
"""
|
|
15
|
+
issue_num = int(issue_number) if isinstance(issue_number, str) else issue_number
|
|
16
|
+
return f"https://github.com/{owner}/{repo}/issues/{issue_num}"
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def get_milestone_url(owner: str, repo: str, milestone_number: int | str) -> str:
|
|
20
|
+
"""Generate a GitHub milestone URL.
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
owner: Repository owner
|
|
24
|
+
repo: Repository name
|
|
25
|
+
milestone_number: Milestone number
|
|
26
|
+
|
|
27
|
+
Returns:
|
|
28
|
+
Full GitHub milestone URL
|
|
29
|
+
"""
|
|
30
|
+
milestone_num = (
|
|
31
|
+
int(milestone_number) if isinstance(milestone_number, str) else milestone_number
|
|
32
|
+
)
|
|
33
|
+
return f"https://github.com/{owner}/{repo}/milestone/{milestone_num}"
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def get_repo_url(owner: str, repo: str) -> str:
|
|
37
|
+
"""Generate a GitHub repository URL.
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
owner: Repository owner
|
|
41
|
+
repo: Repository name
|
|
42
|
+
|
|
43
|
+
Returns:
|
|
44
|
+
Full GitHub repository URL
|
|
45
|
+
"""
|
|
46
|
+
return f"https://github.com/{owner}/{repo}"
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def parse_github_number(url: str) -> int | None:
|
|
50
|
+
"""Extract issue/milestone number from a GitHub URL.
|
|
51
|
+
|
|
52
|
+
Args:
|
|
53
|
+
url: GitHub URL (e.g., https://github.com/owner/repo/issues/123)
|
|
54
|
+
|
|
55
|
+
Returns:
|
|
56
|
+
Issue/milestone number, or None if not found
|
|
57
|
+
"""
|
|
58
|
+
try:
|
|
59
|
+
# Try to extract number from URL
|
|
60
|
+
parts = url.rstrip("/").split("/")
|
|
61
|
+
if parts:
|
|
62
|
+
last_part = parts[-1]
|
|
63
|
+
return int(last_part)
|
|
64
|
+
except (ValueError, IndexError):
|
|
65
|
+
pass
|
|
66
|
+
return None
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"""Validation utilities for roadmap domain logic."""
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
from roadmap.core.services.validators import (
|
|
7
|
+
DataIntegrityValidator,
|
|
8
|
+
DuplicateIssuesValidator,
|
|
9
|
+
FolderStructureValidator,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
# Example utility: validate folder structure
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def validate_folder_structure(issues_dir: Path, core: Any) -> dict:
|
|
16
|
+
"""Validate folder structure and return issues found."""
|
|
17
|
+
return FolderStructureValidator.scan_for_folder_structure_issues(issues_dir, core)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def find_duplicate_issues(issues_dir: Path) -> dict:
|
|
21
|
+
"""Find duplicate issues by issue ID."""
|
|
22
|
+
return DuplicateIssuesValidator.scan_for_duplicate_issues(issues_dir)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def find_malformed_issue_files(issues_dir: Path) -> dict:
|
|
26
|
+
"""Find malformed issue files (unparseable YAML, etc)."""
|
|
27
|
+
return DataIntegrityValidator.scan_for_data_integrity_issues(issues_dir)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
# Add more validation utilities as needed
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"""Infrastructure layer - Coordination, operations, and cross-domain concerns.
|
|
2
|
+
|
|
3
|
+
This module is organized by concern:
|
|
4
|
+
- coordination/: RoadmapCore, domain coordinators, and operations
|
|
5
|
+
- git/: Git integration and branch linking
|
|
6
|
+
- observability/: Health checks and monitoring
|
|
7
|
+
- validation/: Data validation and GitHub integration
|
|
8
|
+
- security/: Credential management and security concerns
|
|
9
|
+
- maintenance/: Cleanup and maintenance operations
|
|
10
|
+
|
|
11
|
+
Re-exports common items for backward compatibility.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
# Re-export from coordination for backward compatibility
|
|
15
|
+
from roadmap.infrastructure.coordination.core import RoadmapCore
|
|
16
|
+
from roadmap.infrastructure.coordination.git_coordinator import GitCoordinator
|
|
17
|
+
from roadmap.infrastructure.coordination.initialization import InitializationManager
|
|
18
|
+
from roadmap.infrastructure.coordination.issue_coordinator import IssueCoordinator
|
|
19
|
+
from roadmap.infrastructure.coordination.issue_operations import IssueOperations
|
|
20
|
+
from roadmap.infrastructure.coordination.milestone_coordinator import (
|
|
21
|
+
MilestoneCoordinator,
|
|
22
|
+
)
|
|
23
|
+
from roadmap.infrastructure.coordination.milestone_operations import MilestoneOperations
|
|
24
|
+
from roadmap.infrastructure.coordination.project_coordinator import ProjectCoordinator
|
|
25
|
+
from roadmap.infrastructure.coordination.project_operations import ProjectOperations
|
|
26
|
+
from roadmap.infrastructure.coordination.team_coordinator import TeamCoordinator
|
|
27
|
+
from roadmap.infrastructure.coordination.user_operations import UserOperations
|
|
28
|
+
from roadmap.infrastructure.coordination.validation_coordinator import (
|
|
29
|
+
ValidationCoordinator,
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
# Re-export from git for backward compatibility
|
|
33
|
+
from roadmap.infrastructure.git.git_integration_ops import GitIntegrationOps
|
|
34
|
+
|
|
35
|
+
# Re-export from observability for backward compatibility
|
|
36
|
+
from roadmap.infrastructure.observability.health import HealthCheck
|
|
37
|
+
from roadmap.infrastructure.observability.health_formatter import HealthStatusFormatter
|
|
38
|
+
|
|
39
|
+
__all__ = [
|
|
40
|
+
"RoadmapCore",
|
|
41
|
+
"GitCoordinator",
|
|
42
|
+
"InitializationManager",
|
|
43
|
+
"IssueCoordinator",
|
|
44
|
+
"IssueOperations",
|
|
45
|
+
"MilestoneCoordinator",
|
|
46
|
+
"MilestoneOperations",
|
|
47
|
+
"ProjectCoordinator",
|
|
48
|
+
"ProjectOperations",
|
|
49
|
+
"TeamCoordinator",
|
|
50
|
+
"UserOperations",
|
|
51
|
+
"ValidationCoordinator",
|
|
52
|
+
"GitIntegrationOps",
|
|
53
|
+
"HealthCheck",
|
|
54
|
+
"HealthStatusFormatter",
|
|
55
|
+
]
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"""Coordination layer - Orchestrates domain operations.
|
|
2
|
+
|
|
3
|
+
This module contains:
|
|
4
|
+
- RoadmapCore: Main facade and service container
|
|
5
|
+
- Domain coordinators: Issue, Milestone, Project, Team, Git, Validation
|
|
6
|
+
- Operations: Concrete implementations of domain operations
|
|
7
|
+
- Initialization: Setup and configuration management
|
|
8
|
+
"""
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"""Coordinator layer parameter dataclasses.
|
|
2
|
+
|
|
3
|
+
Consolidates coordinator method parameters into well-structured dataclasses
|
|
4
|
+
for improved API consistency and reduced parameter passing complexity.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from dataclasses import dataclass, field
|
|
8
|
+
from datetime import datetime
|
|
9
|
+
from typing import Any
|
|
10
|
+
|
|
11
|
+
from roadmap.core.domain import IssueType, Priority
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass
|
|
15
|
+
class IssueCreateParams:
|
|
16
|
+
"""Parameters for creating a new issue through IssueCoordinator."""
|
|
17
|
+
|
|
18
|
+
title: str
|
|
19
|
+
priority: Priority = Priority.MEDIUM
|
|
20
|
+
issue_type: IssueType = IssueType.OTHER
|
|
21
|
+
milestone: str | None = None
|
|
22
|
+
labels: list[str] | None = None
|
|
23
|
+
assignee: str | None = None
|
|
24
|
+
estimated_hours: float | None = None
|
|
25
|
+
depends_on: list[str] | None = None
|
|
26
|
+
blocks: list[str] | None = None
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@dataclass
|
|
30
|
+
class IssueListParams:
|
|
31
|
+
"""Parameters for listing issues through IssueCoordinator."""
|
|
32
|
+
|
|
33
|
+
milestone: str | None = None
|
|
34
|
+
status: str | None = None
|
|
35
|
+
priority: Priority | None = None
|
|
36
|
+
issue_type: IssueType | None = None
|
|
37
|
+
assignee: str | None = None
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@dataclass
|
|
41
|
+
class IssueUpdateParams:
|
|
42
|
+
"""Parameters for updating an issue through IssueCoordinator."""
|
|
43
|
+
|
|
44
|
+
issue_id: str
|
|
45
|
+
updates: dict[str, Any] = field(default_factory=dict)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@dataclass
|
|
49
|
+
class MilestoneCreateParams:
|
|
50
|
+
"""Parameters for creating a new milestone through MilestoneCoordinator."""
|
|
51
|
+
|
|
52
|
+
name: str
|
|
53
|
+
content: str = ""
|
|
54
|
+
due_date: datetime | None = None
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
@dataclass
|
|
58
|
+
class MilestoneUpdateParams:
|
|
59
|
+
"""Parameters for updating a milestone through MilestoneCoordinator."""
|
|
60
|
+
|
|
61
|
+
name: str
|
|
62
|
+
content: str | None = None
|
|
63
|
+
due_date: datetime | None = None
|
|
64
|
+
clear_due_date: bool = False
|
|
65
|
+
status: str | None = None
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
@dataclass
|
|
69
|
+
class ProjectCreateParams:
|
|
70
|
+
"""Parameters for creating a new project through ProjectCoordinator."""
|
|
71
|
+
|
|
72
|
+
name: str
|
|
73
|
+
content: str = ""
|
|
74
|
+
milestones: list[str] | None = None
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
@dataclass
|
|
78
|
+
class ProjectUpdateParams:
|
|
79
|
+
"""Parameters for updating a project through ProjectCoordinator."""
|
|
80
|
+
|
|
81
|
+
project_id: str
|
|
82
|
+
updates: dict[str, Any] = field(default_factory=dict)
|