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,201 @@
|
|
|
1
|
+
"""Milestone Operations Module - Handles all milestone-related CRUD operations.
|
|
2
|
+
|
|
3
|
+
This module encapsulates milestone management responsibilities extracted from RoadmapCore,
|
|
4
|
+
including creating, reading, updating, and deleting milestones, as well as milestone-related
|
|
5
|
+
queries and progress tracking.
|
|
6
|
+
|
|
7
|
+
Responsibilities:
|
|
8
|
+
- Milestone CRUD operations (create, list, get, update, delete)
|
|
9
|
+
- Milestone progress tracking
|
|
10
|
+
- Next milestone calculation
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from datetime import datetime
|
|
14
|
+
from typing import Any
|
|
15
|
+
|
|
16
|
+
from roadmap.common.errors.error_standards import OperationType, safe_operation
|
|
17
|
+
from roadmap.common.logging import get_logger
|
|
18
|
+
from roadmap.core.domain import Milestone, MilestoneStatus
|
|
19
|
+
from roadmap.core.services import MilestoneService
|
|
20
|
+
|
|
21
|
+
logger = get_logger(__name__)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class MilestoneOperations:
|
|
25
|
+
"""Manager for milestone-related operations."""
|
|
26
|
+
|
|
27
|
+
def __init__(self, milestone_service: MilestoneService):
|
|
28
|
+
"""Initialize milestone operations manager.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
milestone_service: The MilestoneService instance for database operations
|
|
32
|
+
"""
|
|
33
|
+
self.milestone_service = milestone_service
|
|
34
|
+
|
|
35
|
+
@safe_operation(OperationType.CREATE, "Milestone", include_traceback=True)
|
|
36
|
+
def create_milestone(
|
|
37
|
+
self,
|
|
38
|
+
name: str,
|
|
39
|
+
headline: str = "",
|
|
40
|
+
due_date: datetime | None = None,
|
|
41
|
+
status: str | None = None,
|
|
42
|
+
) -> Milestone:
|
|
43
|
+
"""Create a new milestone.
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
name: Milestone name
|
|
47
|
+
headline: Milestone headline (short summary)
|
|
48
|
+
due_date: Due date for the milestone (optional)
|
|
49
|
+
status: Milestone status (optional, defaults to OPEN)
|
|
50
|
+
|
|
51
|
+
Returns:
|
|
52
|
+
Created Milestone object
|
|
53
|
+
"""
|
|
54
|
+
logger.info(
|
|
55
|
+
"creating_milestone",
|
|
56
|
+
milestone_name=name,
|
|
57
|
+
has_headline=headline is not None,
|
|
58
|
+
has_due_date=due_date is not None,
|
|
59
|
+
status=status,
|
|
60
|
+
)
|
|
61
|
+
return self.milestone_service.create_milestone(
|
|
62
|
+
name=name, headline=headline, due_date=due_date, status=status
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
@safe_operation(OperationType.READ, "Milestone")
|
|
66
|
+
def list_milestones(self) -> list[Milestone]:
|
|
67
|
+
"""List all milestones.
|
|
68
|
+
|
|
69
|
+
Returns:
|
|
70
|
+
List of Milestone objects
|
|
71
|
+
"""
|
|
72
|
+
logger.info("listing_milestones")
|
|
73
|
+
return self.milestone_service.list_milestones()
|
|
74
|
+
|
|
75
|
+
@safe_operation(OperationType.READ, "Milestone")
|
|
76
|
+
def get_milestone(self, name: str) -> Milestone | None:
|
|
77
|
+
"""Get a specific milestone by name.
|
|
78
|
+
|
|
79
|
+
Args:
|
|
80
|
+
name: Name of the milestone (searches by YAML name field, not filename)
|
|
81
|
+
|
|
82
|
+
Returns:
|
|
83
|
+
Milestone object if found, None otherwise
|
|
84
|
+
"""
|
|
85
|
+
logger.info("getting_milestone", milestone_name=name)
|
|
86
|
+
return self.milestone_service.get_milestone(name)
|
|
87
|
+
|
|
88
|
+
@safe_operation(OperationType.DELETE, "Milestone", include_traceback=True)
|
|
89
|
+
def delete_milestone(self, name: str) -> bool:
|
|
90
|
+
"""Delete a milestone and unassign all issues from it.
|
|
91
|
+
|
|
92
|
+
Args:
|
|
93
|
+
name: Name of the milestone to delete
|
|
94
|
+
|
|
95
|
+
Returns:
|
|
96
|
+
True if milestone was deleted, False if not found
|
|
97
|
+
"""
|
|
98
|
+
logger.info("deleting_milestone", milestone_name=name)
|
|
99
|
+
return self.milestone_service.delete_milestone(name)
|
|
100
|
+
|
|
101
|
+
@safe_operation(OperationType.UPDATE, "Milestone")
|
|
102
|
+
def update_milestone(
|
|
103
|
+
self,
|
|
104
|
+
name: str,
|
|
105
|
+
headline: str | None = None,
|
|
106
|
+
due_date: datetime | None = None,
|
|
107
|
+
clear_due_date: bool = False,
|
|
108
|
+
status: str | None = None,
|
|
109
|
+
project_id: str | None = None,
|
|
110
|
+
) -> bool:
|
|
111
|
+
"""Update a milestone's properties.
|
|
112
|
+
|
|
113
|
+
Args:
|
|
114
|
+
name: Name of the milestone to update
|
|
115
|
+
headline: New headline (None to keep current)
|
|
116
|
+
due_date: New due date (None to keep current)
|
|
117
|
+
clear_due_date: If True, remove the due date
|
|
118
|
+
status: New status (None to keep current)
|
|
119
|
+
project_id: Project ID to assign milestone to
|
|
120
|
+
|
|
121
|
+
Returns:
|
|
122
|
+
True if milestone was updated, False if not found or error occurred
|
|
123
|
+
"""
|
|
124
|
+
from roadmap.common.errors.exceptions import UpdateError
|
|
125
|
+
|
|
126
|
+
logger.info(
|
|
127
|
+
"updating_milestone",
|
|
128
|
+
milestone_name=name,
|
|
129
|
+
has_headline=headline is not None,
|
|
130
|
+
has_due_date=due_date is not None,
|
|
131
|
+
clear_due_date=clear_due_date,
|
|
132
|
+
has_status=status is not None,
|
|
133
|
+
has_project_id=project_id is not None,
|
|
134
|
+
)
|
|
135
|
+
try:
|
|
136
|
+
return (
|
|
137
|
+
self.milestone_service.update_milestone(
|
|
138
|
+
name=name,
|
|
139
|
+
headline=headline,
|
|
140
|
+
due_date=due_date,
|
|
141
|
+
clear_due_date=clear_due_date,
|
|
142
|
+
status=status,
|
|
143
|
+
project_id=project_id,
|
|
144
|
+
)
|
|
145
|
+
is not None
|
|
146
|
+
)
|
|
147
|
+
except UpdateError as e:
|
|
148
|
+
logger.error(
|
|
149
|
+
"milestone_update_failed",
|
|
150
|
+
name=name,
|
|
151
|
+
error=str(e),
|
|
152
|
+
severity="operational",
|
|
153
|
+
)
|
|
154
|
+
return False
|
|
155
|
+
|
|
156
|
+
@safe_operation(OperationType.READ, "Milestone")
|
|
157
|
+
def get_milestone_progress(self, milestone_name: str) -> dict[str, Any]:
|
|
158
|
+
"""Get progress statistics for a milestone.
|
|
159
|
+
|
|
160
|
+
Args:
|
|
161
|
+
milestone_name: Name of the milestone
|
|
162
|
+
|
|
163
|
+
Returns:
|
|
164
|
+
Dictionary containing progress metrics (completed, total, percentage, etc.)
|
|
165
|
+
"""
|
|
166
|
+
logger.info("getting_milestone_progress", milestone_name=milestone_name)
|
|
167
|
+
return self.milestone_service.get_milestone_progress(milestone_name)
|
|
168
|
+
|
|
169
|
+
def get_next_milestone(self) -> Milestone | None:
|
|
170
|
+
"""Get the next upcoming milestone based on due date.
|
|
171
|
+
|
|
172
|
+
Returns:
|
|
173
|
+
The upcoming milestone with the earliest due date, or None if no upcoming milestones
|
|
174
|
+
"""
|
|
175
|
+
milestones = self.list_milestones()
|
|
176
|
+
|
|
177
|
+
# Filter for open milestones with due dates
|
|
178
|
+
upcoming_milestones = [
|
|
179
|
+
m
|
|
180
|
+
for m in milestones
|
|
181
|
+
if m.status == MilestoneStatus.OPEN and m.due_date is not None
|
|
182
|
+
]
|
|
183
|
+
|
|
184
|
+
if not upcoming_milestones:
|
|
185
|
+
return None
|
|
186
|
+
|
|
187
|
+
# Sort by due date and return the earliest
|
|
188
|
+
# Handle timezone-aware vs timezone-naive datetime comparison
|
|
189
|
+
def get_sortable_date(milestone: Milestone) -> datetime:
|
|
190
|
+
"""Extract sortable date from milestone."""
|
|
191
|
+
due_date = milestone.due_date
|
|
192
|
+
# due_date should not be None since we filtered above, but be safe
|
|
193
|
+
if due_date is None:
|
|
194
|
+
return datetime.max # Put None dates at the end
|
|
195
|
+
# Convert timezone-aware dates to naive for comparison
|
|
196
|
+
if due_date.tzinfo is not None:
|
|
197
|
+
return due_date.replace(tzinfo=None)
|
|
198
|
+
return due_date
|
|
199
|
+
|
|
200
|
+
upcoming_milestones.sort(key=get_sortable_date)
|
|
201
|
+
return upcoming_milestones[0]
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"""Project Coordinator - Coordinates project-related operations.
|
|
2
|
+
|
|
3
|
+
Extracted from RoadmapCore to reduce god object complexity.
|
|
4
|
+
Provides a focused API for all project-related concerns.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from typing import TYPE_CHECKING
|
|
10
|
+
|
|
11
|
+
from roadmap.core.domain import Project
|
|
12
|
+
from roadmap.infrastructure.coordination.project_operations import ProjectOperations
|
|
13
|
+
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from roadmap.infrastructure.coordination.core import RoadmapCore
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class ProjectCoordinator:
|
|
19
|
+
"""Coordinates all project-related operations."""
|
|
20
|
+
|
|
21
|
+
def __init__(self, project_ops: ProjectOperations, core: RoadmapCore | None = None):
|
|
22
|
+
"""Initialize coordinator with project operations manager.
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
project_ops: ProjectOperations instance
|
|
26
|
+
core: RoadmapCore instance for initialization checks
|
|
27
|
+
"""
|
|
28
|
+
self._ops = project_ops
|
|
29
|
+
self._core = core
|
|
30
|
+
|
|
31
|
+
def list(self) -> list[Project]:
|
|
32
|
+
"""List all projects."""
|
|
33
|
+
return self._ops.list_projects()
|
|
34
|
+
|
|
35
|
+
def get(self, project_id: str) -> Project | None:
|
|
36
|
+
"""Get a specific project by ID or name.
|
|
37
|
+
|
|
38
|
+
Tries to find project by ID first, then by name as fallback.
|
|
39
|
+
"""
|
|
40
|
+
# Try direct ID lookup first
|
|
41
|
+
project = self._ops.get_project(project_id)
|
|
42
|
+
if project:
|
|
43
|
+
return project
|
|
44
|
+
|
|
45
|
+
# Fallback: try to find by name
|
|
46
|
+
for project in self._ops.list_projects():
|
|
47
|
+
if project.name.lower() == project_id.lower():
|
|
48
|
+
return project
|
|
49
|
+
|
|
50
|
+
return None
|
|
51
|
+
|
|
52
|
+
def create(
|
|
53
|
+
self,
|
|
54
|
+
name: str,
|
|
55
|
+
headline: str = "",
|
|
56
|
+
milestones: list[str] | None = None,
|
|
57
|
+
status: str | None = None,
|
|
58
|
+
) -> Project:
|
|
59
|
+
"""Create a new project.
|
|
60
|
+
|
|
61
|
+
Args:
|
|
62
|
+
name: Project name
|
|
63
|
+
headline: Project headline (short summary)
|
|
64
|
+
milestones: List of milestone names (optional)
|
|
65
|
+
status: Project status (optional)
|
|
66
|
+
|
|
67
|
+
Returns:
|
|
68
|
+
Created Project object
|
|
69
|
+
"""
|
|
70
|
+
return self._ops.create_project(
|
|
71
|
+
name=name,
|
|
72
|
+
headline=headline,
|
|
73
|
+
milestones=milestones or [],
|
|
74
|
+
status=status,
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
def save(self, project: Project) -> bool:
|
|
78
|
+
"""Save an updated project to disk."""
|
|
79
|
+
return self._ops.save_project(project)
|
|
80
|
+
|
|
81
|
+
def update(self, project_id: str, **updates) -> Project | None:
|
|
82
|
+
"""Update a project with the given fields.
|
|
83
|
+
|
|
84
|
+
Args:
|
|
85
|
+
project_id: Project identifier
|
|
86
|
+
**updates: Fields to update (name, description, status, priority, etc.)
|
|
87
|
+
|
|
88
|
+
Returns:
|
|
89
|
+
Updated Project object if successful, None if not found
|
|
90
|
+
"""
|
|
91
|
+
return self._ops.update_project(project_id, **updates)
|
|
92
|
+
|
|
93
|
+
def delete(self, project_id: str) -> bool:
|
|
94
|
+
"""Delete a project.
|
|
95
|
+
|
|
96
|
+
Args:
|
|
97
|
+
project_id: Project identifier
|
|
98
|
+
|
|
99
|
+
Returns:
|
|
100
|
+
True if deletion successful, False otherwise
|
|
101
|
+
"""
|
|
102
|
+
return self._ops.delete_project(project_id)
|
|
103
|
+
|
|
104
|
+
def complete(self, project_id: str) -> Project | None:
|
|
105
|
+
"""Mark a project as completed.
|
|
106
|
+
|
|
107
|
+
Args:
|
|
108
|
+
project_id: Project identifier
|
|
109
|
+
|
|
110
|
+
Returns:
|
|
111
|
+
Updated Project object if successful, None if not found
|
|
112
|
+
"""
|
|
113
|
+
return self._ops.complete_project(project_id)
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
"""Project Operations Module - Handles all project-related CRUD operations.
|
|
2
|
+
|
|
3
|
+
This module encapsulates project management responsibilities extracted from RoadmapCore,
|
|
4
|
+
including creating, reading, updating, and managing projects.
|
|
5
|
+
|
|
6
|
+
Responsibilities:
|
|
7
|
+
- Project CRUD operations (list, get, save, update)
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from roadmap.common.errors.error_standards import OperationType, safe_operation
|
|
11
|
+
from roadmap.common.logging import get_logger
|
|
12
|
+
from roadmap.core.domain import Project
|
|
13
|
+
from roadmap.core.services import ProjectService
|
|
14
|
+
|
|
15
|
+
logger = get_logger(__name__)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class ProjectOperations:
|
|
19
|
+
"""Manager for project-related operations."""
|
|
20
|
+
|
|
21
|
+
def __init__(self, project_service: ProjectService):
|
|
22
|
+
"""Initialize project operations manager.
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
project_service: The ProjectService instance for database operations
|
|
26
|
+
"""
|
|
27
|
+
self.project_service = project_service
|
|
28
|
+
|
|
29
|
+
@safe_operation(OperationType.READ, "Project")
|
|
30
|
+
def list_projects(self) -> list[Project]:
|
|
31
|
+
"""List all projects.
|
|
32
|
+
|
|
33
|
+
Returns:
|
|
34
|
+
List of Project objects
|
|
35
|
+
"""
|
|
36
|
+
logger.info("listing_projects")
|
|
37
|
+
return self.project_service.list_projects()
|
|
38
|
+
|
|
39
|
+
@safe_operation(OperationType.READ, "Project")
|
|
40
|
+
def get_project(self, project_id: str) -> Project | None:
|
|
41
|
+
"""Get a specific project by ID.
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
project_id: The project ID to retrieve
|
|
45
|
+
|
|
46
|
+
Returns:
|
|
47
|
+
Project object if found, None otherwise
|
|
48
|
+
"""
|
|
49
|
+
logger.info("getting_project", project_id=project_id)
|
|
50
|
+
return self.project_service.get_project(project_id)
|
|
51
|
+
|
|
52
|
+
@safe_operation(OperationType.CREATE, "Project", include_traceback=True)
|
|
53
|
+
def create_project(
|
|
54
|
+
self,
|
|
55
|
+
name: str,
|
|
56
|
+
headline: str = "",
|
|
57
|
+
milestones: list[str] | None = None,
|
|
58
|
+
status: str | None = None,
|
|
59
|
+
) -> Project:
|
|
60
|
+
"""Create a new project.
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
name: Project name
|
|
64
|
+
headline: Project headline (short summary)
|
|
65
|
+
milestones: List of milestone names (optional)
|
|
66
|
+
status: Project status (optional)
|
|
67
|
+
|
|
68
|
+
Returns:
|
|
69
|
+
Created Project object
|
|
70
|
+
"""
|
|
71
|
+
logger.info(
|
|
72
|
+
"creating_project",
|
|
73
|
+
project_name=name,
|
|
74
|
+
has_headline=headline is not None,
|
|
75
|
+
milestone_count=len(milestones or []),
|
|
76
|
+
status=status,
|
|
77
|
+
)
|
|
78
|
+
return self.project_service.create_project(
|
|
79
|
+
name=name,
|
|
80
|
+
headline=headline,
|
|
81
|
+
milestones=milestones or [],
|
|
82
|
+
status=status,
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
@safe_operation(OperationType.UPDATE, "Project")
|
|
86
|
+
def save_project(self, project: Project) -> bool:
|
|
87
|
+
"""Save an updated project to disk.
|
|
88
|
+
|
|
89
|
+
Args:
|
|
90
|
+
project: The Project object to save
|
|
91
|
+
|
|
92
|
+
Returns:
|
|
93
|
+
True if save successful, False otherwise
|
|
94
|
+
"""
|
|
95
|
+
logger.info(
|
|
96
|
+
"saving_project",
|
|
97
|
+
project_id=project.id,
|
|
98
|
+
project_name=project.name,
|
|
99
|
+
)
|
|
100
|
+
return self.project_service.save_project(project)
|
|
101
|
+
|
|
102
|
+
@safe_operation(OperationType.UPDATE, "Project")
|
|
103
|
+
def update_project(self, project_id: str, **updates) -> Project | None:
|
|
104
|
+
"""Update a project with the given fields.
|
|
105
|
+
|
|
106
|
+
Args:
|
|
107
|
+
project_id: Project identifier
|
|
108
|
+
**updates: Fields to update (name, description, status, priority, etc.)
|
|
109
|
+
|
|
110
|
+
Returns:
|
|
111
|
+
Updated Project object if successful, None if not found
|
|
112
|
+
"""
|
|
113
|
+
logger.info(
|
|
114
|
+
"updating_project",
|
|
115
|
+
project_id=project_id,
|
|
116
|
+
update_fields=list(updates.keys()),
|
|
117
|
+
)
|
|
118
|
+
return self.project_service.update_project(project_id, **updates)
|
|
119
|
+
|
|
120
|
+
@safe_operation(OperationType.DELETE, "Project", include_traceback=True)
|
|
121
|
+
def delete_project(self, project_id: str) -> bool:
|
|
122
|
+
"""Delete a project.
|
|
123
|
+
|
|
124
|
+
Args:
|
|
125
|
+
project_id: Project identifier
|
|
126
|
+
|
|
127
|
+
Returns:
|
|
128
|
+
True if deletion successful, False otherwise
|
|
129
|
+
"""
|
|
130
|
+
logger.info("deleting_project", project_id=project_id)
|
|
131
|
+
return self.project_service.delete_project(project_id)
|
|
132
|
+
|
|
133
|
+
@safe_operation(OperationType.UPDATE, "Project")
|
|
134
|
+
def complete_project(self, project_id: str) -> Project | None:
|
|
135
|
+
"""Mark a project as completed.
|
|
136
|
+
|
|
137
|
+
Args:
|
|
138
|
+
project_id: Project identifier
|
|
139
|
+
|
|
140
|
+
Returns:
|
|
141
|
+
Updated Project object if successful, None if not found
|
|
142
|
+
"""
|
|
143
|
+
logger.info("completing_project", project_id=project_id)
|
|
144
|
+
return self.project_service.complete_project(project_id)
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"""Team Coordinator - Coordinates team and user-related operations.
|
|
2
|
+
|
|
3
|
+
Extracted from RoadmapCore to reduce god object complexity.
|
|
4
|
+
Provides a focused API for all team and user management concerns.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from typing import TYPE_CHECKING
|
|
10
|
+
|
|
11
|
+
from roadmap.common.errors.error_standards import OperationType, safe_operation
|
|
12
|
+
from roadmap.common.logging import get_logger
|
|
13
|
+
from roadmap.core.domain import Issue
|
|
14
|
+
from roadmap.infrastructure.coordination.user_operations import UserOperations
|
|
15
|
+
|
|
16
|
+
if TYPE_CHECKING:
|
|
17
|
+
from roadmap.infrastructure.coordination.core import RoadmapCore
|
|
18
|
+
|
|
19
|
+
logger = get_logger(__name__)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class TeamCoordinator:
|
|
23
|
+
"""Coordinates all team and user-related operations."""
|
|
24
|
+
|
|
25
|
+
def __init__(self, user_ops: UserOperations, core: RoadmapCore | None = None):
|
|
26
|
+
"""Initialize coordinator with user operations manager.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
user_ops: UserOperations instance
|
|
30
|
+
core: RoadmapCore instance for initialization checks
|
|
31
|
+
"""
|
|
32
|
+
self._ops = user_ops
|
|
33
|
+
self._core = core
|
|
34
|
+
|
|
35
|
+
@safe_operation(OperationType.READ, "Team")
|
|
36
|
+
def get_members(self) -> list[str]:
|
|
37
|
+
"""Get team members from GitHub repository.
|
|
38
|
+
|
|
39
|
+
Returns:
|
|
40
|
+
List of usernames if GitHub is configured, empty list otherwise
|
|
41
|
+
"""
|
|
42
|
+
logger.info("getting_team_members")
|
|
43
|
+
return self._ops.get_team_members()
|
|
44
|
+
|
|
45
|
+
@safe_operation(OperationType.READ, "User")
|
|
46
|
+
def get_current_user(self) -> str | None:
|
|
47
|
+
"""Get the current user from config.
|
|
48
|
+
|
|
49
|
+
Returns:
|
|
50
|
+
Current user's name from config if set, None otherwise
|
|
51
|
+
"""
|
|
52
|
+
logger.info("getting_current_user")
|
|
53
|
+
return self._ops.get_current_user()
|
|
54
|
+
|
|
55
|
+
@safe_operation(OperationType.READ, "Issue")
|
|
56
|
+
def get_assigned_issues(self, assignee: str) -> list[Issue]:
|
|
57
|
+
"""Get all issues assigned to a specific user."""
|
|
58
|
+
logger.info("getting_assigned_issues", assignee=assignee)
|
|
59
|
+
return self._ops.get_assigned_issues(assignee)
|
|
60
|
+
|
|
61
|
+
@safe_operation(OperationType.READ, "Issue")
|
|
62
|
+
def get_my_issues(self) -> list[Issue]:
|
|
63
|
+
"""Get all issues assigned to the current user."""
|
|
64
|
+
logger.info("getting_my_issues")
|
|
65
|
+
return self._ops.get_my_issues()
|
|
66
|
+
|
|
67
|
+
@safe_operation(OperationType.READ, "Issue")
|
|
68
|
+
def get_all_assigned_issues(self) -> dict[str, list[Issue]]:
|
|
69
|
+
"""Get all issues grouped by assignee.
|
|
70
|
+
|
|
71
|
+
Returns:
|
|
72
|
+
Dictionary mapping assignee usernames to their assigned issues
|
|
73
|
+
"""
|
|
74
|
+
logger.info("getting_all_assigned_issues")
|
|
75
|
+
return self._ops.get_all_assigned_issues()
|
|
76
|
+
|
|
77
|
+
@safe_operation(OperationType.READ, "Assignee")
|
|
78
|
+
def validate_assignee(self, assignee: str) -> tuple[bool, str]:
|
|
79
|
+
"""Validate an assignee using the identity management system.
|
|
80
|
+
|
|
81
|
+
Args:
|
|
82
|
+
assignee: Username to validate
|
|
83
|
+
|
|
84
|
+
Returns:
|
|
85
|
+
Tuple of (is_valid, error_message)
|
|
86
|
+
"""
|
|
87
|
+
logger.info("validating_assignee", assignee=assignee)
|
|
88
|
+
return self._ops.validate_assignee(assignee)
|
|
89
|
+
|
|
90
|
+
@safe_operation(OperationType.READ, "Assignee")
|
|
91
|
+
def get_canonical_assignee(self, assignee: str) -> str:
|
|
92
|
+
"""Get the canonical form of an assignee name.
|
|
93
|
+
|
|
94
|
+
Args:
|
|
95
|
+
assignee: Input assignee name
|
|
96
|
+
|
|
97
|
+
Returns:
|
|
98
|
+
Canonical assignee name (may be same as input if no mapping exists)
|
|
99
|
+
"""
|
|
100
|
+
logger.info("getting_canonical_assignee", assignee=assignee)
|
|
101
|
+
return self._ops.get_canonical_assignee(assignee)
|
|
102
|
+
|
|
103
|
+
@safe_operation(OperationType.READ, "Team")
|
|
104
|
+
def get_cached_team_members(self) -> list[str]:
|
|
105
|
+
"""Get team members with caching (5 minute cache)."""
|
|
106
|
+
logger.info("getting_cached_team_members")
|
|
107
|
+
return self._ops.get_cached_team_members()
|