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,150 @@
|
|
|
1
|
+
"""User and Team Operations Module - Handles user management and validation.
|
|
2
|
+
|
|
3
|
+
This module encapsulates user and team management responsibilities extracted from RoadmapCore,
|
|
4
|
+
including team member retrieval, user validation, and assignee management.
|
|
5
|
+
|
|
6
|
+
Responsibilities:
|
|
7
|
+
- Team member retrieval and caching
|
|
8
|
+
- Current user management
|
|
9
|
+
- Assignee validation and normalization
|
|
10
|
+
- Issue assignment queries by user
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from roadmap.core.domain import Issue
|
|
14
|
+
from roadmap.core.interfaces.assignee_validator import AssigneeValidator
|
|
15
|
+
from roadmap.core.services import GitHubIntegrationService, IssueService
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class UserOperations:
|
|
19
|
+
"""Manager for user and team-related operations."""
|
|
20
|
+
|
|
21
|
+
def __init__(
|
|
22
|
+
self,
|
|
23
|
+
github_service: GitHubIntegrationService,
|
|
24
|
+
issue_service: IssueService,
|
|
25
|
+
assignee_validator: AssigneeValidator | None = None,
|
|
26
|
+
):
|
|
27
|
+
"""Initialize user operations manager.
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
github_service: The GitHubIntegrationService instance
|
|
31
|
+
issue_service: The IssueService instance
|
|
32
|
+
assignee_validator: Validator for assignees (injected based on backend).
|
|
33
|
+
If None, uses vanilla validator for backwards compatibility.
|
|
34
|
+
"""
|
|
35
|
+
self.github_service = github_service
|
|
36
|
+
self.issue_service = issue_service
|
|
37
|
+
|
|
38
|
+
# Use injected validator, or fall back to vanilla validator
|
|
39
|
+
if assignee_validator is None:
|
|
40
|
+
from roadmap.infrastructure.validation.vanilla_assignee_validator import (
|
|
41
|
+
VanillaAssigneeValidator,
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
assignee_validator = VanillaAssigneeValidator()
|
|
45
|
+
|
|
46
|
+
self.assignee_validator = assignee_validator
|
|
47
|
+
|
|
48
|
+
def get_team_members(self) -> list[str]:
|
|
49
|
+
"""Get team members from GitHub repository.
|
|
50
|
+
|
|
51
|
+
Returns:
|
|
52
|
+
List of usernames if GitHub is configured, empty list otherwise
|
|
53
|
+
"""
|
|
54
|
+
return self.github_service.get_team_members()
|
|
55
|
+
|
|
56
|
+
def get_current_user(self) -> str | None:
|
|
57
|
+
"""Get the current user from config.
|
|
58
|
+
|
|
59
|
+
Returns:
|
|
60
|
+
Current user's name from config if set, None otherwise
|
|
61
|
+
"""
|
|
62
|
+
return self.github_service.get_current_user()
|
|
63
|
+
|
|
64
|
+
def get_assigned_issues(self, assignee: str) -> list[Issue]:
|
|
65
|
+
"""Get all issues assigned to a specific user.
|
|
66
|
+
|
|
67
|
+
Args:
|
|
68
|
+
assignee: The username to get issues for
|
|
69
|
+
|
|
70
|
+
Returns:
|
|
71
|
+
List of Issue objects assigned to the user
|
|
72
|
+
"""
|
|
73
|
+
return self.issue_service.list_issues(assignee=assignee)
|
|
74
|
+
|
|
75
|
+
def get_my_issues(self) -> list[Issue]:
|
|
76
|
+
"""Get all issues assigned to the current user.
|
|
77
|
+
|
|
78
|
+
Returns:
|
|
79
|
+
List of Issue objects assigned to current user, or empty list if not set
|
|
80
|
+
"""
|
|
81
|
+
current_user = self.get_current_user()
|
|
82
|
+
if not current_user:
|
|
83
|
+
return []
|
|
84
|
+
return self.get_assigned_issues(current_user)
|
|
85
|
+
|
|
86
|
+
def get_all_assigned_issues(self) -> dict[str, list[Issue]]:
|
|
87
|
+
"""Get all issues grouped by assignee.
|
|
88
|
+
|
|
89
|
+
Returns:
|
|
90
|
+
Dictionary mapping assignee usernames to their assigned issues
|
|
91
|
+
"""
|
|
92
|
+
all_issues = self.issue_service.list_issues()
|
|
93
|
+
assigned_issues: dict[str, list[Issue]] = {}
|
|
94
|
+
|
|
95
|
+
for issue in all_issues:
|
|
96
|
+
if issue.assignee:
|
|
97
|
+
if issue.assignee not in assigned_issues:
|
|
98
|
+
assigned_issues[issue.assignee] = []
|
|
99
|
+
assigned_issues[issue.assignee].append(issue)
|
|
100
|
+
|
|
101
|
+
return assigned_issues
|
|
102
|
+
|
|
103
|
+
def get_cached_team_members(self) -> list[str]:
|
|
104
|
+
"""Get team members with caching (5 minute cache).
|
|
105
|
+
|
|
106
|
+
Returns:
|
|
107
|
+
List of cached team member usernames
|
|
108
|
+
"""
|
|
109
|
+
return self.github_service.get_cached_team_members()
|
|
110
|
+
|
|
111
|
+
def validate_assignee(self, assignee: str) -> tuple[bool, str]:
|
|
112
|
+
"""Validate an assignee using the configured validator.
|
|
113
|
+
|
|
114
|
+
The validator is backend-specific:
|
|
115
|
+
- GitHub backend: validates against repository collaborators
|
|
116
|
+
- Git backend: accepts any assignee (no-op validator)
|
|
117
|
+
|
|
118
|
+
Args:
|
|
119
|
+
assignee: Username to validate
|
|
120
|
+
|
|
121
|
+
Returns:
|
|
122
|
+
Tuple of (is_valid, error_message)
|
|
123
|
+
- (True, "") if valid
|
|
124
|
+
- (False, error_message) if invalid
|
|
125
|
+
"""
|
|
126
|
+
return self.assignee_validator.validate(assignee)
|
|
127
|
+
|
|
128
|
+
def legacy_validate_assignee(self, assignee: str) -> tuple[bool, str]:
|
|
129
|
+
"""Legacy validation fallback for when validation strategy fails.
|
|
130
|
+
|
|
131
|
+
Args:
|
|
132
|
+
assignee: Username to validate
|
|
133
|
+
|
|
134
|
+
Returns:
|
|
135
|
+
Tuple of (is_valid, error_message)
|
|
136
|
+
"""
|
|
137
|
+
return self.github_service._legacy_validate_assignee(assignee)
|
|
138
|
+
|
|
139
|
+
def get_canonical_assignee(self, assignee: str) -> str:
|
|
140
|
+
"""Get the canonical form of an assignee name.
|
|
141
|
+
|
|
142
|
+
This method should be called after validate_assignee to get the canonical form.
|
|
143
|
+
|
|
144
|
+
Args:
|
|
145
|
+
assignee: Input assignee name
|
|
146
|
+
|
|
147
|
+
Returns:
|
|
148
|
+
Canonical assignee name (may be same as input if no mapping exists)
|
|
149
|
+
"""
|
|
150
|
+
return self.assignee_validator.get_canonical_assignee(assignee)
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
"""Validation Coordinator - Coordinates validation operations.
|
|
2
|
+
|
|
3
|
+
Extracted from RoadmapCore to reduce god object complexity.
|
|
4
|
+
Provides a focused API for validation concerns.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
from typing import TYPE_CHECKING
|
|
11
|
+
|
|
12
|
+
from roadmap.common.errors.error_standards import OperationType, safe_operation
|
|
13
|
+
from roadmap.common.logging import get_logger
|
|
14
|
+
from roadmap.core.services import GitHubIntegrationService
|
|
15
|
+
|
|
16
|
+
if TYPE_CHECKING:
|
|
17
|
+
from roadmap.infrastructure.coordination.core import RoadmapCore
|
|
18
|
+
|
|
19
|
+
logger = get_logger(__name__)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class ValidationCoordinator:
|
|
23
|
+
"""Coordinates all validation operations."""
|
|
24
|
+
|
|
25
|
+
def __init__(
|
|
26
|
+
self, github_service: GitHubIntegrationService, core: RoadmapCore | None = None
|
|
27
|
+
):
|
|
28
|
+
"""Initialize coordinator with GitHub service.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
github_service: GitHubIntegrationService instance
|
|
32
|
+
core: RoadmapCore instance for initialization checks
|
|
33
|
+
"""
|
|
34
|
+
self._github_service = github_service
|
|
35
|
+
self._core = core
|
|
36
|
+
|
|
37
|
+
@safe_operation(OperationType.READ, "Configuration")
|
|
38
|
+
def get_github_config(self) -> tuple[str | None, str | None, str | None]:
|
|
39
|
+
"""Get GitHub configuration from config file and credentials.
|
|
40
|
+
|
|
41
|
+
Returns:
|
|
42
|
+
Tuple of (token, owner, repo) or (None, None, None) if not configured
|
|
43
|
+
"""
|
|
44
|
+
logger.info("getting_github_config")
|
|
45
|
+
return self._github_service.get_github_config()
|
|
46
|
+
|
|
47
|
+
@safe_operation(OperationType.READ, "RemoteLinks")
|
|
48
|
+
def collect_remote_link_validation_data(
|
|
49
|
+
self,
|
|
50
|
+
issues_dir: Path,
|
|
51
|
+
backend_name: str = "github",
|
|
52
|
+
) -> dict:
|
|
53
|
+
"""Collect YAML and database remote link data for validation.
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
issues_dir: Directory containing issue markdown files
|
|
57
|
+
backend_name: Backend name to validate
|
|
58
|
+
|
|
59
|
+
Returns:
|
|
60
|
+
Dict with issue_files, total_files, yaml_remote_ids, unparseable_files, db_links
|
|
61
|
+
"""
|
|
62
|
+
if not self._core:
|
|
63
|
+
raise ValueError("ValidationCoordinator requires RoadmapCore")
|
|
64
|
+
|
|
65
|
+
issue_files = sorted(issues_dir.glob("**/*.md")) if issues_dir.exists() else []
|
|
66
|
+
yaml_remote_ids: dict[str, dict[str, str | int]] = {}
|
|
67
|
+
unparseable_files: list[tuple[str, str]] = []
|
|
68
|
+
|
|
69
|
+
if issue_files:
|
|
70
|
+
from roadmap.adapters.persistence.parser.issue import IssueParser
|
|
71
|
+
|
|
72
|
+
for file_path in issue_files:
|
|
73
|
+
try:
|
|
74
|
+
issue = IssueParser.parse_issue_file(file_path)
|
|
75
|
+
if issue.remote_ids:
|
|
76
|
+
yaml_remote_ids[issue.id] = issue.remote_ids
|
|
77
|
+
except Exception as e:
|
|
78
|
+
logger.warning(
|
|
79
|
+
"failed_to_parse_issue_file",
|
|
80
|
+
file_path=str(file_path),
|
|
81
|
+
error=str(e),
|
|
82
|
+
)
|
|
83
|
+
unparseable_files.append((str(file_path), str(e)))
|
|
84
|
+
|
|
85
|
+
db_links = self._core.db.remote_links.get_all_links_for_backend(backend_name)
|
|
86
|
+
|
|
87
|
+
return {
|
|
88
|
+
"issue_files": issue_files,
|
|
89
|
+
"total_files": len(issue_files),
|
|
90
|
+
"yaml_remote_ids": yaml_remote_ids,
|
|
91
|
+
"unparseable_files": unparseable_files,
|
|
92
|
+
"db_links": db_links,
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
@safe_operation(OperationType.READ, "RemoteLinks")
|
|
96
|
+
def build_remote_link_report(
|
|
97
|
+
self,
|
|
98
|
+
yaml_remote_ids: dict[str, dict[str, str | int]],
|
|
99
|
+
db_links: dict[str, str | int],
|
|
100
|
+
) -> dict:
|
|
101
|
+
"""Build a report of remote link discrepancies and duplicates.
|
|
102
|
+
|
|
103
|
+
Args:
|
|
104
|
+
yaml_remote_ids: Mapping of issue_id -> backend_name -> remote_id
|
|
105
|
+
db_links: Mapping of issue_uuid -> remote_id
|
|
106
|
+
|
|
107
|
+
Returns:
|
|
108
|
+
Dict with validation summary fields
|
|
109
|
+
"""
|
|
110
|
+
yaml_issue_uuids = set(yaml_remote_ids.keys())
|
|
111
|
+
db_issue_uuids = set(db_links.keys())
|
|
112
|
+
|
|
113
|
+
missing_in_db = [
|
|
114
|
+
uuid for uuid in yaml_issue_uuids if uuid not in db_issue_uuids
|
|
115
|
+
]
|
|
116
|
+
extra_in_db = [uuid for uuid in db_issue_uuids if uuid not in yaml_issue_uuids]
|
|
117
|
+
|
|
118
|
+
duplicate_remote_ids: dict[str, list[str]] = {}
|
|
119
|
+
remote_id_map: dict[str, list[str]] = {}
|
|
120
|
+
for issue_uuid, remote_id in db_links.items():
|
|
121
|
+
remote_id_key = str(remote_id)
|
|
122
|
+
remote_id_map.setdefault(remote_id_key, []).append(issue_uuid)
|
|
123
|
+
|
|
124
|
+
for remote_id, issue_uuids in remote_id_map.items():
|
|
125
|
+
if len(issue_uuids) > 1:
|
|
126
|
+
duplicate_remote_ids[remote_id] = issue_uuids
|
|
127
|
+
|
|
128
|
+
return {
|
|
129
|
+
"files_with_remote_ids": len(yaml_remote_ids),
|
|
130
|
+
"database_links": len(db_links),
|
|
131
|
+
"missing_in_db": missing_in_db,
|
|
132
|
+
"extra_in_db": extra_in_db,
|
|
133
|
+
"duplicate_remote_ids": duplicate_remote_ids,
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
@safe_operation(OperationType.UPDATE, "RemoteLinks")
|
|
137
|
+
def apply_remote_link_fixes(
|
|
138
|
+
self,
|
|
139
|
+
yaml_remote_ids: dict[str, dict[str, str | int]],
|
|
140
|
+
report: dict,
|
|
141
|
+
backend_name: str = "github",
|
|
142
|
+
prune_extra: bool = False,
|
|
143
|
+
dedupe: bool = False,
|
|
144
|
+
dry_run: bool = False,
|
|
145
|
+
) -> dict:
|
|
146
|
+
"""Apply fixes for missing, extra, and duplicate remote links.
|
|
147
|
+
|
|
148
|
+
Args:
|
|
149
|
+
yaml_remote_ids: Mapping of issue_id -> backend_name -> remote_id
|
|
150
|
+
report: Validation report dict
|
|
151
|
+
backend_name: Backend name to fix
|
|
152
|
+
prune_extra: Remove links missing from YAML
|
|
153
|
+
dedupe: Remove duplicate remote_id links
|
|
154
|
+
dry_run: If True, do not apply changes
|
|
155
|
+
|
|
156
|
+
Returns:
|
|
157
|
+
Dict with counts for fixed, removed, and deduped links
|
|
158
|
+
"""
|
|
159
|
+
if not self._core:
|
|
160
|
+
raise ValueError("ValidationCoordinator requires RoadmapCore")
|
|
161
|
+
|
|
162
|
+
fixed_count = self._fix_missing_links(
|
|
163
|
+
report.get("missing_in_db", []), yaml_remote_ids, dry_run
|
|
164
|
+
)
|
|
165
|
+
removed_count = (
|
|
166
|
+
self._prune_extra_links(
|
|
167
|
+
report.get("extra_in_db", []), backend_name, dry_run
|
|
168
|
+
)
|
|
169
|
+
if prune_extra
|
|
170
|
+
else 0
|
|
171
|
+
)
|
|
172
|
+
deduped_count = (
|
|
173
|
+
self._dedupe_links(
|
|
174
|
+
report.get("duplicate_remote_ids", {}),
|
|
175
|
+
set(yaml_remote_ids.keys()),
|
|
176
|
+
backend_name,
|
|
177
|
+
dry_run,
|
|
178
|
+
)
|
|
179
|
+
if dedupe
|
|
180
|
+
else 0
|
|
181
|
+
)
|
|
182
|
+
return {
|
|
183
|
+
"fixed_count": fixed_count,
|
|
184
|
+
"removed_count": removed_count,
|
|
185
|
+
"deduped_count": deduped_count,
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
def _fix_missing_links(
|
|
189
|
+
self, missing_ids: list, yaml_remote_ids: dict, dry_run: bool
|
|
190
|
+
) -> int:
|
|
191
|
+
core = self._core
|
|
192
|
+
if core is None:
|
|
193
|
+
raise ValueError("ValidationCoordinator requires RoadmapCore")
|
|
194
|
+
|
|
195
|
+
fixed = 0
|
|
196
|
+
for issue_uuid in missing_ids:
|
|
197
|
+
remote_ids = yaml_remote_ids.get(issue_uuid)
|
|
198
|
+
if not remote_ids:
|
|
199
|
+
continue
|
|
200
|
+
if dry_run:
|
|
201
|
+
fixed += 1
|
|
202
|
+
continue
|
|
203
|
+
for backend_key, remote_id in remote_ids.items():
|
|
204
|
+
core.db.remote_links.link_issue(issue_uuid, backend_key, remote_id)
|
|
205
|
+
fixed += 1
|
|
206
|
+
return fixed
|
|
207
|
+
|
|
208
|
+
def _prune_extra_links(
|
|
209
|
+
self, extra_ids: list, backend_name: str, dry_run: bool
|
|
210
|
+
) -> int:
|
|
211
|
+
core = self._core
|
|
212
|
+
if core is None:
|
|
213
|
+
raise ValueError("ValidationCoordinator requires RoadmapCore")
|
|
214
|
+
|
|
215
|
+
removed = 0
|
|
216
|
+
for issue_uuid in extra_ids:
|
|
217
|
+
if dry_run:
|
|
218
|
+
removed += 1
|
|
219
|
+
continue
|
|
220
|
+
if core.db.remote_links.unlink_issue(issue_uuid, backend_name):
|
|
221
|
+
removed += 1
|
|
222
|
+
return removed
|
|
223
|
+
|
|
224
|
+
def _dedupe_links(
|
|
225
|
+
self,
|
|
226
|
+
duplicates: dict,
|
|
227
|
+
yaml_issue_uuids: set,
|
|
228
|
+
backend_name: str,
|
|
229
|
+
dry_run: bool,
|
|
230
|
+
) -> int:
|
|
231
|
+
core = self._core
|
|
232
|
+
if core is None:
|
|
233
|
+
raise ValueError("ValidationCoordinator requires RoadmapCore")
|
|
234
|
+
|
|
235
|
+
deduped = 0
|
|
236
|
+
for issue_uuids in duplicates.values():
|
|
237
|
+
keep_uuid = next(
|
|
238
|
+
(uuid for uuid in issue_uuids if uuid in yaml_issue_uuids),
|
|
239
|
+
issue_uuids[0],
|
|
240
|
+
)
|
|
241
|
+
for issue_uuid in issue_uuids:
|
|
242
|
+
if issue_uuid == keep_uuid:
|
|
243
|
+
continue
|
|
244
|
+
if dry_run:
|
|
245
|
+
deduped += 1
|
|
246
|
+
continue
|
|
247
|
+
if core.db.remote_links.unlink_issue(issue_uuid, backend_name):
|
|
248
|
+
deduped += 1
|
|
249
|
+
return deduped
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
"""Gateway to coordination infrastructure adapter access for core services.
|
|
2
|
+
|
|
3
|
+
This module mediates all core service access to infrastructure coordination
|
|
4
|
+
implementations, ensuring proper layer separation between Core and Infrastructure.
|
|
5
|
+
|
|
6
|
+
All imports from roadmap.adapters accessed via coordination are localized here.
|
|
7
|
+
Core services use this gateway instead of importing coordination modules directly
|
|
8
|
+
or accessing adapters through coordination.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
from typing import Any
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class CoordinationGateway:
|
|
16
|
+
"""Gateway for infrastructure coordination operations.
|
|
17
|
+
|
|
18
|
+
Provides a centralized interface for core services to access coordination
|
|
19
|
+
functionality that internally uses adapters (git, persistence, etc.)
|
|
20
|
+
without direct adapter imports in core.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
@staticmethod
|
|
24
|
+
def get_git_integration(repo_path: Path | None = None, config: Any = None) -> Any:
|
|
25
|
+
"""Get GitIntegration adapter for git operations.
|
|
26
|
+
|
|
27
|
+
Args:
|
|
28
|
+
repo_path: Path to git repository
|
|
29
|
+
config: Configuration object
|
|
30
|
+
|
|
31
|
+
Returns:
|
|
32
|
+
GitIntegration instance from adapters
|
|
33
|
+
"""
|
|
34
|
+
from roadmap.adapters.git.git import GitIntegration
|
|
35
|
+
|
|
36
|
+
return GitIntegration(repo_path=repo_path, config=config)
|
|
37
|
+
|
|
38
|
+
@staticmethod
|
|
39
|
+
def get_state_manager(db_path: Path | str | None = None) -> Any:
|
|
40
|
+
"""Get StateManager for database operations.
|
|
41
|
+
|
|
42
|
+
Args:
|
|
43
|
+
db_path: Path to database file (optional)
|
|
44
|
+
|
|
45
|
+
Returns:
|
|
46
|
+
StateManager instance from adapters
|
|
47
|
+
"""
|
|
48
|
+
from roadmap.adapters.persistence.storage import StateManager
|
|
49
|
+
|
|
50
|
+
if db_path:
|
|
51
|
+
return StateManager(db_path)
|
|
52
|
+
return StateManager()
|
|
53
|
+
|
|
54
|
+
@staticmethod
|
|
55
|
+
def get_yaml_issue_repository(
|
|
56
|
+
db: Any | None = None, issues_dir: Path | None = None
|
|
57
|
+
) -> Any:
|
|
58
|
+
"""Get YAML repository for issue persistence.
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
db: Database instance
|
|
62
|
+
issues_dir: Path to issues directory
|
|
63
|
+
|
|
64
|
+
Returns:
|
|
65
|
+
YAMLIssueRepository instance from adapters
|
|
66
|
+
"""
|
|
67
|
+
from roadmap.adapters.persistence.yaml_repositories import (
|
|
68
|
+
YAMLIssueRepository,
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
# Both parameters are required
|
|
72
|
+
if db is None or issues_dir is None:
|
|
73
|
+
raise ValueError("Both 'db' and 'issues_dir' are required parameters")
|
|
74
|
+
return YAMLIssueRepository(db, issues_dir)
|
|
75
|
+
|
|
76
|
+
@staticmethod
|
|
77
|
+
def get_git_sync_monitor(
|
|
78
|
+
repo_path: Path | None = None, state_manager: Any = None
|
|
79
|
+
) -> Any:
|
|
80
|
+
"""Get GitSyncMonitor for git sync tracking.
|
|
81
|
+
|
|
82
|
+
Args:
|
|
83
|
+
repo_path: Path to git repository
|
|
84
|
+
state_manager: State manager instance
|
|
85
|
+
|
|
86
|
+
Returns:
|
|
87
|
+
GitSyncMonitor instance from adapters
|
|
88
|
+
"""
|
|
89
|
+
from roadmap.adapters.git.sync_monitor import GitSyncMonitor
|
|
90
|
+
|
|
91
|
+
return GitSyncMonitor(repo_path=repo_path, state_manager=state_manager)
|
|
92
|
+
|
|
93
|
+
@staticmethod
|
|
94
|
+
def get_git_hook_manager(core: Any) -> Any:
|
|
95
|
+
"""Get GitHookManager for git hook operations.
|
|
96
|
+
|
|
97
|
+
Args:
|
|
98
|
+
core: RoadmapCore instance (required)
|
|
99
|
+
|
|
100
|
+
Returns:
|
|
101
|
+
GitHookManager instance from adapters
|
|
102
|
+
"""
|
|
103
|
+
from roadmap.adapters.git.git_hooks import GitHookManager
|
|
104
|
+
|
|
105
|
+
return GitHookManager(core)
|
|
106
|
+
|
|
107
|
+
@staticmethod
|
|
108
|
+
def parse_issue(file_path: Any) -> Any:
|
|
109
|
+
"""Parse issue from file.
|
|
110
|
+
|
|
111
|
+
Args:
|
|
112
|
+
file_path: Path to issue file
|
|
113
|
+
|
|
114
|
+
Returns:
|
|
115
|
+
Parsed Issue object
|
|
116
|
+
"""
|
|
117
|
+
from roadmap.adapters.persistence.parser import IssueParser
|
|
118
|
+
|
|
119
|
+
return IssueParser.parse_issue_file(file_path)
|
|
120
|
+
|
|
121
|
+
@staticmethod
|
|
122
|
+
def parse_milestone(file_path: Any) -> Any:
|
|
123
|
+
"""Parse milestone from file.
|
|
124
|
+
|
|
125
|
+
Args:
|
|
126
|
+
file_path: Path to milestone file
|
|
127
|
+
|
|
128
|
+
Returns:
|
|
129
|
+
Parsed Milestone object
|
|
130
|
+
"""
|
|
131
|
+
from roadmap.adapters.persistence.parser import MilestoneParser
|
|
132
|
+
|
|
133
|
+
return MilestoneParser.parse_milestone_file(file_path)
|
|
134
|
+
|
|
135
|
+
@staticmethod
|
|
136
|
+
def get_yaml_repositories_manager() -> Any:
|
|
137
|
+
"""Get combined repositories manager for multi-repo operations.
|
|
138
|
+
|
|
139
|
+
Returns:
|
|
140
|
+
Dictionary of repository classes available
|
|
141
|
+
"""
|
|
142
|
+
from roadmap.adapters.persistence.yaml_repositories import (
|
|
143
|
+
YAMLIssueRepository,
|
|
144
|
+
YAMLMilestoneRepository,
|
|
145
|
+
YAMLProjectRepository,
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
return {
|
|
149
|
+
"issue": YAMLIssueRepository,
|
|
150
|
+
"milestone": YAMLMilestoneRepository,
|
|
151
|
+
"project": YAMLProjectRepository,
|
|
152
|
+
}
|