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,227 @@
|
|
|
1
|
+
"""Health check result enhancement with details and recommendations.
|
|
2
|
+
|
|
3
|
+
This module provides infrastructure for enriching health check results with:
|
|
4
|
+
- Affected entities (which issues, milestones, etc. are affected)
|
|
5
|
+
- Fix recommendations (what can be done to resolve issues)
|
|
6
|
+
- Auto-fix commands (ready-to-run commands for common fixes)
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from collections.abc import Mapping
|
|
10
|
+
from dataclasses import dataclass, field
|
|
11
|
+
from typing import Any
|
|
12
|
+
|
|
13
|
+
from roadmap.core.domain.health import HealthStatus
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@dataclass
|
|
17
|
+
class HealthCheckDetail:
|
|
18
|
+
"""Details about a specific health check result.
|
|
19
|
+
|
|
20
|
+
Attributes:
|
|
21
|
+
check_name: Name of the health check (e.g., "duplicate_issues")
|
|
22
|
+
status: Health status (HEALTHY, DEGRADED, UNHEALTHY)
|
|
23
|
+
message: Summary message about the check result
|
|
24
|
+
affected_items: List of affected entity IDs or names
|
|
25
|
+
recommendations: List of recommended fixes or actions
|
|
26
|
+
fix_commands: List of ready-to-run CLI commands that can fix the issue
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
check_name: str
|
|
30
|
+
status: HealthStatus
|
|
31
|
+
message: str
|
|
32
|
+
affected_items: list[str] = field(default_factory=list)
|
|
33
|
+
recommendations: list[str] = field(default_factory=list)
|
|
34
|
+
fix_commands: list[dict[str, str]] = field(default_factory=list)
|
|
35
|
+
|
|
36
|
+
def to_dict(self) -> dict[str, Any]:
|
|
37
|
+
"""Convert to dictionary for JSON serialization."""
|
|
38
|
+
return {
|
|
39
|
+
"check_name": self.check_name,
|
|
40
|
+
"status": self.status.value.upper(),
|
|
41
|
+
"message": self.message,
|
|
42
|
+
"affected_items": self.affected_items,
|
|
43
|
+
"affected_count": len(self.affected_items),
|
|
44
|
+
"recommendations": self.recommendations,
|
|
45
|
+
"fix_commands": self.fix_commands,
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class HealthCheckEnhancer:
|
|
50
|
+
"""Enhances health check results with detailed information.
|
|
51
|
+
|
|
52
|
+
This service enriches basic health check results (status + message) with:
|
|
53
|
+
- Lists of affected entities
|
|
54
|
+
- Specific recommendations for fixes
|
|
55
|
+
- Ready-to-run CLI commands to fix issues
|
|
56
|
+
|
|
57
|
+
Works with both infrastructure and data quality checks.
|
|
58
|
+
"""
|
|
59
|
+
|
|
60
|
+
def __init__(self, core=None):
|
|
61
|
+
"""Initialize enhancer with optional core for entity lookups.
|
|
62
|
+
|
|
63
|
+
Args:
|
|
64
|
+
core: Optional core instance for accessing entities
|
|
65
|
+
"""
|
|
66
|
+
self.core = core
|
|
67
|
+
|
|
68
|
+
def enhance_check_result(
|
|
69
|
+
self,
|
|
70
|
+
check_name: str,
|
|
71
|
+
status: HealthStatus,
|
|
72
|
+
message: str,
|
|
73
|
+
) -> HealthCheckDetail:
|
|
74
|
+
"""Enhance a health check result with details.
|
|
75
|
+
|
|
76
|
+
Args:
|
|
77
|
+
check_name: Name of the health check
|
|
78
|
+
status: Health status from the check
|
|
79
|
+
message: Message from the check
|
|
80
|
+
|
|
81
|
+
Returns:
|
|
82
|
+
HealthCheckDetail with enhanced information
|
|
83
|
+
"""
|
|
84
|
+
detail = HealthCheckDetail(
|
|
85
|
+
check_name=check_name,
|
|
86
|
+
status=status,
|
|
87
|
+
message=message,
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
# Route to check-specific enhancement
|
|
91
|
+
if check_name == "duplicate_issues":
|
|
92
|
+
self._enhance_duplicate_issues(detail)
|
|
93
|
+
elif check_name == "orphaned_issues":
|
|
94
|
+
self._enhance_orphaned_issues(detail)
|
|
95
|
+
elif check_name == "old_backups":
|
|
96
|
+
self._enhance_old_backups(detail)
|
|
97
|
+
elif check_name == "folder_structure":
|
|
98
|
+
self._enhance_folder_structure(detail)
|
|
99
|
+
elif check_name == "comment_integrity":
|
|
100
|
+
self._enhance_comment_integrity(detail)
|
|
101
|
+
else:
|
|
102
|
+
# Generic enhancement for other checks
|
|
103
|
+
self._enhance_generic(detail)
|
|
104
|
+
|
|
105
|
+
return detail
|
|
106
|
+
|
|
107
|
+
def _enhance_duplicate_issues(self, detail: HealthCheckDetail) -> None:
|
|
108
|
+
"""Add details for duplicate_issues check."""
|
|
109
|
+
detail.recommendations = [
|
|
110
|
+
"Review issues with identical titles and status",
|
|
111
|
+
"Merge duplicates, keeping the older issue as primary",
|
|
112
|
+
"Close/delete the newer duplicate issue",
|
|
113
|
+
]
|
|
114
|
+
detail.fix_commands = [
|
|
115
|
+
{
|
|
116
|
+
"command": "roadmap health fix --fix-type duplicate_issues --dry-run",
|
|
117
|
+
"description": "Preview duplicate issues that can be fixed",
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
"command": "roadmap health fix --fix-type duplicate_issues",
|
|
121
|
+
"description": "Automatically fix duplicate issues (requires review)",
|
|
122
|
+
},
|
|
123
|
+
]
|
|
124
|
+
|
|
125
|
+
def _enhance_orphaned_issues(self, detail: HealthCheckDetail) -> None:
|
|
126
|
+
"""Add details for orphaned_issues check."""
|
|
127
|
+
detail.recommendations = [
|
|
128
|
+
"Assign issues without milestones to 'Backlog'",
|
|
129
|
+
"Review issues to ensure correct milestone assignment",
|
|
130
|
+
"Use 'roadmap issue assign' to move to correct milestone",
|
|
131
|
+
]
|
|
132
|
+
detail.fix_commands = [
|
|
133
|
+
{
|
|
134
|
+
"command": "roadmap health fix --fix-type orphaned_issues --dry-run",
|
|
135
|
+
"description": "Preview issues to be assigned to Backlog",
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
"command": "roadmap health fix --fix-type orphaned_issues",
|
|
139
|
+
"description": "Automatically assign orphaned issues to Backlog",
|
|
140
|
+
},
|
|
141
|
+
]
|
|
142
|
+
|
|
143
|
+
def _enhance_old_backups(self, detail: HealthCheckDetail) -> None:
|
|
144
|
+
"""Add details for old_backups check."""
|
|
145
|
+
detail.recommendations = [
|
|
146
|
+
"Delete backup files older than 90 days to save storage",
|
|
147
|
+
"Review archived backups to ensure data is safely stored",
|
|
148
|
+
"Consider moving very old backups to external storage",
|
|
149
|
+
]
|
|
150
|
+
detail.fix_commands = [
|
|
151
|
+
{
|
|
152
|
+
"command": "roadmap health fix --fix-type old_backups --dry-run",
|
|
153
|
+
"description": "Preview old backups that can be deleted",
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
"command": "roadmap health fix --fix-type old_backups",
|
|
157
|
+
"description": "Delete old backup files (>90 days)",
|
|
158
|
+
},
|
|
159
|
+
]
|
|
160
|
+
|
|
161
|
+
def _enhance_folder_structure(self, detail: HealthCheckDetail) -> None:
|
|
162
|
+
"""Add details for folder_structure check."""
|
|
163
|
+
detail.recommendations = [
|
|
164
|
+
"Move issues to their correct milestone folders",
|
|
165
|
+
"Verify milestone folder organization matches issue assignments",
|
|
166
|
+
"Use 'roadmap issue move' to reorganize structure",
|
|
167
|
+
]
|
|
168
|
+
detail.fix_commands = [
|
|
169
|
+
{
|
|
170
|
+
"command": "roadmap health fix --fix-type folder_structure --dry-run",
|
|
171
|
+
"description": "Preview folder structure corrections",
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
"command": "roadmap health fix --fix-type folder_structure",
|
|
175
|
+
"description": "Automatically fix folder structure issues",
|
|
176
|
+
},
|
|
177
|
+
]
|
|
178
|
+
|
|
179
|
+
def _enhance_comment_integrity(self, detail: HealthCheckDetail) -> None:
|
|
180
|
+
"""Add details for comment_integrity check."""
|
|
181
|
+
detail.recommendations = [
|
|
182
|
+
"Review and sanitize malformed JSON in comments",
|
|
183
|
+
"Check for corrupted comment threads",
|
|
184
|
+
"Manually edit comments with formatting issues",
|
|
185
|
+
]
|
|
186
|
+
detail.fix_commands = [
|
|
187
|
+
{
|
|
188
|
+
"command": "roadmap health fix --fix-type corrupted_comments --dry-run",
|
|
189
|
+
"description": "Preview comments that can be sanitized",
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
"command": "roadmap health fix --fix-type corrupted_comments",
|
|
193
|
+
"description": "Automatically sanitize malformed comments (review first)",
|
|
194
|
+
},
|
|
195
|
+
]
|
|
196
|
+
|
|
197
|
+
def _enhance_generic(self, detail: HealthCheckDetail) -> None:
|
|
198
|
+
"""Enhance check with generic recommendations."""
|
|
199
|
+
if detail.status == HealthStatus.HEALTHY:
|
|
200
|
+
detail.recommendations = ["No action needed"]
|
|
201
|
+
elif detail.status == HealthStatus.DEGRADED:
|
|
202
|
+
detail.recommendations = [
|
|
203
|
+
"Monitor this check in future health reports",
|
|
204
|
+
"Take action when status becomes UNHEALTHY",
|
|
205
|
+
]
|
|
206
|
+
else: # UNHEALTHY
|
|
207
|
+
detail.recommendations = [
|
|
208
|
+
"Investigate the root cause immediately",
|
|
209
|
+
"Review the detailed message for specific guidance",
|
|
210
|
+
"Use 'roadmap health scan' for entity-level diagnostics",
|
|
211
|
+
]
|
|
212
|
+
|
|
213
|
+
def enhance_all_checks(
|
|
214
|
+
self, checks: Mapping[str, tuple[HealthStatus, str]]
|
|
215
|
+
) -> dict[str, HealthCheckDetail]:
|
|
216
|
+
"""Enhance all health check results.
|
|
217
|
+
|
|
218
|
+
Args:
|
|
219
|
+
checks: Dict mapping check names to (status, message) tuples
|
|
220
|
+
|
|
221
|
+
Returns:
|
|
222
|
+
Dict mapping check names to HealthCheckDetail objects
|
|
223
|
+
"""
|
|
224
|
+
return {
|
|
225
|
+
check_name: self.enhance_check_result(check_name, status, message)
|
|
226
|
+
for check_name, (status, message) in checks.items()
|
|
227
|
+
}
|
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
"""Health check fixer orchestrator and base infrastructure.
|
|
2
|
+
|
|
3
|
+
Provides framework for automatically fixing detected health issues with:
|
|
4
|
+
- Safe/review categorization
|
|
5
|
+
- Dry-run preview mode (default)
|
|
6
|
+
- Rollback capability tracking
|
|
7
|
+
- Detailed fix result reporting
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from abc import ABC, abstractmethod
|
|
11
|
+
from dataclasses import dataclass, field
|
|
12
|
+
from enum import Enum
|
|
13
|
+
from typing import Any
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class FixSafety(Enum):
|
|
17
|
+
"""Safety level for a fixer.
|
|
18
|
+
|
|
19
|
+
SAFE: Can be applied automatically without human review
|
|
20
|
+
REVIEW: Requires human review before applying
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
SAFE = "safe"
|
|
24
|
+
REVIEW = "review"
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@dataclass
|
|
28
|
+
class FixResult:
|
|
29
|
+
"""Result of a fix operation.
|
|
30
|
+
|
|
31
|
+
Attributes:
|
|
32
|
+
fix_type: Type of fix that was applied
|
|
33
|
+
success: Whether the fix succeeded
|
|
34
|
+
dry_run: Whether this was a dry-run
|
|
35
|
+
message: Description of what was fixed
|
|
36
|
+
affected_items: IDs or names of affected entities
|
|
37
|
+
items_count: Number of items affected
|
|
38
|
+
changes_made: Number of changes actually made
|
|
39
|
+
rollback_info: Information for rolling back (if applicable)
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
fix_type: str
|
|
43
|
+
success: bool
|
|
44
|
+
dry_run: bool
|
|
45
|
+
message: str
|
|
46
|
+
affected_items: list[str] = field(default_factory=list)
|
|
47
|
+
items_count: int = 0
|
|
48
|
+
changes_made: int = 0
|
|
49
|
+
rollback_info: dict[str, Any] | None = None
|
|
50
|
+
|
|
51
|
+
def to_dict(self) -> dict[str, Any]:
|
|
52
|
+
"""Convert to dictionary for JSON serialization."""
|
|
53
|
+
return {
|
|
54
|
+
"fix_type": self.fix_type,
|
|
55
|
+
"success": self.success,
|
|
56
|
+
"dry_run": self.dry_run,
|
|
57
|
+
"message": self.message,
|
|
58
|
+
"affected_items": self.affected_items,
|
|
59
|
+
"items_count": self.items_count,
|
|
60
|
+
"changes_made": self.changes_made,
|
|
61
|
+
"has_rollback": self.rollback_info is not None,
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class HealthFixer(ABC):
|
|
66
|
+
"""Abstract base class for health check fixers.
|
|
67
|
+
|
|
68
|
+
Each fixer handles a specific type of health issue:
|
|
69
|
+
- old_backups: Delete old backup files
|
|
70
|
+
- duplicate_issues: Merge duplicate issues
|
|
71
|
+
- orphaned_issues: Assign unassigned issues to Backlog
|
|
72
|
+
- folder_structure: Move issues to correct milestone folders
|
|
73
|
+
- corrupted_comments: Sanitize malformed JSON comments
|
|
74
|
+
"""
|
|
75
|
+
|
|
76
|
+
def __init__(self, core):
|
|
77
|
+
"""Initialize fixer with core instance.
|
|
78
|
+
|
|
79
|
+
Args:
|
|
80
|
+
core: Core application instance
|
|
81
|
+
"""
|
|
82
|
+
self.core = core
|
|
83
|
+
|
|
84
|
+
@property
|
|
85
|
+
@abstractmethod
|
|
86
|
+
def fix_type(self) -> str:
|
|
87
|
+
"""Identifier for this fixer (e.g., 'duplicate_issues')."""
|
|
88
|
+
pass
|
|
89
|
+
|
|
90
|
+
@property
|
|
91
|
+
@abstractmethod
|
|
92
|
+
def safety_level(self) -> FixSafety:
|
|
93
|
+
"""Safety level: SAFE or REVIEW."""
|
|
94
|
+
pass
|
|
95
|
+
|
|
96
|
+
@property
|
|
97
|
+
@abstractmethod
|
|
98
|
+
def description(self) -> str:
|
|
99
|
+
"""Human-readable description of what this fixer does."""
|
|
100
|
+
pass
|
|
101
|
+
|
|
102
|
+
@abstractmethod
|
|
103
|
+
def scan(self) -> dict[str, Any]:
|
|
104
|
+
"""Scan for issues that can be fixed.
|
|
105
|
+
|
|
106
|
+
Returns:
|
|
107
|
+
Dict with:
|
|
108
|
+
- found: bool (whether issues were found)
|
|
109
|
+
- count: int (number of issues found)
|
|
110
|
+
- message: str (description)
|
|
111
|
+
- details: list (specific issues found)
|
|
112
|
+
"""
|
|
113
|
+
pass
|
|
114
|
+
|
|
115
|
+
@abstractmethod
|
|
116
|
+
def dry_run(self) -> FixResult:
|
|
117
|
+
"""Preview what would be fixed without making changes.
|
|
118
|
+
|
|
119
|
+
Returns:
|
|
120
|
+
FixResult with dry_run=True
|
|
121
|
+
"""
|
|
122
|
+
pass
|
|
123
|
+
|
|
124
|
+
@abstractmethod
|
|
125
|
+
def apply(self, force: bool = False) -> FixResult:
|
|
126
|
+
"""Apply the fix (actually make changes).
|
|
127
|
+
|
|
128
|
+
Args:
|
|
129
|
+
force: If True, apply without prompts
|
|
130
|
+
|
|
131
|
+
Returns:
|
|
132
|
+
FixResult with dry_run=False
|
|
133
|
+
"""
|
|
134
|
+
pass
|
|
135
|
+
|
|
136
|
+
def confirm_apply(self, dry_run_result: FixResult) -> bool:
|
|
137
|
+
"""Ask user to confirm applying a fix.
|
|
138
|
+
|
|
139
|
+
For SAFE fixes, this can auto-approve.
|
|
140
|
+
For REVIEW fixes, user must manually confirm.
|
|
141
|
+
|
|
142
|
+
Args:
|
|
143
|
+
dry_run_result: Result from dry_run()
|
|
144
|
+
|
|
145
|
+
Returns:
|
|
146
|
+
True if user confirms, False otherwise
|
|
147
|
+
"""
|
|
148
|
+
if self.safety_level == FixSafety.SAFE:
|
|
149
|
+
return True
|
|
150
|
+
|
|
151
|
+
# REVIEW fixes require user confirmation
|
|
152
|
+
import click
|
|
153
|
+
|
|
154
|
+
message = f"\nApply {self.fix_type}? {dry_run_result.message}"
|
|
155
|
+
return click.confirm(message, default=False)
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
class HealthFixOrchestrator:
|
|
159
|
+
"""Orchestrates health fixes across all available fixers.
|
|
160
|
+
|
|
161
|
+
Handles:
|
|
162
|
+
- Loading all available fixers
|
|
163
|
+
- Running dry-run previews
|
|
164
|
+
- Applying fixes with proper safety checks
|
|
165
|
+
- Collecting results
|
|
166
|
+
"""
|
|
167
|
+
|
|
168
|
+
def __init__(self, core):
|
|
169
|
+
"""Initialize orchestrator.
|
|
170
|
+
|
|
171
|
+
Args:
|
|
172
|
+
core: Core application instance
|
|
173
|
+
"""
|
|
174
|
+
self.core = core
|
|
175
|
+
self._fixers: dict[str, HealthFixer] = {}
|
|
176
|
+
self._load_fixers()
|
|
177
|
+
|
|
178
|
+
def _load_fixers(self) -> None:
|
|
179
|
+
"""Load all available fixers."""
|
|
180
|
+
from roadmap.adapters.cli.health.fixers.corrupted_comments_fixer import (
|
|
181
|
+
CorruptedCommentsFixer,
|
|
182
|
+
)
|
|
183
|
+
from roadmap.adapters.cli.health.fixers.data_integrity_fixer import (
|
|
184
|
+
DataIntegrityFixer,
|
|
185
|
+
)
|
|
186
|
+
from roadmap.adapters.cli.health.fixers.duplicate_issues_fixer import (
|
|
187
|
+
DuplicateIssuesFixer,
|
|
188
|
+
)
|
|
189
|
+
from roadmap.adapters.cli.health.fixers.folder_structure_fixer import (
|
|
190
|
+
FolderStructureFixer,
|
|
191
|
+
)
|
|
192
|
+
from roadmap.adapters.cli.health.fixers.label_normalization_fixer import (
|
|
193
|
+
LabelNormalizationFixer,
|
|
194
|
+
)
|
|
195
|
+
from roadmap.adapters.cli.health.fixers.milestone_name_normalization_fixer import (
|
|
196
|
+
MilestoneNameNormalizationFixer,
|
|
197
|
+
)
|
|
198
|
+
from roadmap.adapters.cli.health.fixers.milestone_naming_compliance_fixer import (
|
|
199
|
+
MilestoneNamingComplianceFixer,
|
|
200
|
+
)
|
|
201
|
+
from roadmap.adapters.cli.health.fixers.milestone_parse_error_fixer import (
|
|
202
|
+
MilestoneParseErrorFixer,
|
|
203
|
+
)
|
|
204
|
+
from roadmap.adapters.cli.health.fixers.milestone_validation_fixer import (
|
|
205
|
+
MilestoneValidationFixer,
|
|
206
|
+
)
|
|
207
|
+
from roadmap.adapters.cli.health.fixers.old_backups_fixer import (
|
|
208
|
+
OldBackupsFixer,
|
|
209
|
+
)
|
|
210
|
+
from roadmap.adapters.cli.health.fixers.orphaned_issues_fixer import (
|
|
211
|
+
OrphanedIssuesFixer,
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
fixers = [
|
|
215
|
+
OldBackupsFixer(self.core),
|
|
216
|
+
DuplicateIssuesFixer(self.core),
|
|
217
|
+
OrphanedIssuesFixer(self.core),
|
|
218
|
+
FolderStructureFixer(self.core),
|
|
219
|
+
CorruptedCommentsFixer(self.core),
|
|
220
|
+
DataIntegrityFixer(self.core),
|
|
221
|
+
LabelNormalizationFixer(self.core),
|
|
222
|
+
MilestoneNameNormalizationFixer(self.core),
|
|
223
|
+
MilestoneNamingComplianceFixer(self.core),
|
|
224
|
+
MilestoneValidationFixer(self.core),
|
|
225
|
+
MilestoneParseErrorFixer(self.core),
|
|
226
|
+
]
|
|
227
|
+
|
|
228
|
+
for fixer in fixers:
|
|
229
|
+
self._fixers[fixer.fix_type] = fixer
|
|
230
|
+
|
|
231
|
+
def get_fixers(self) -> dict[str, HealthFixer]:
|
|
232
|
+
"""Get all available fixers.
|
|
233
|
+
|
|
234
|
+
Returns:
|
|
235
|
+
Dict mapping fix_type to HealthFixer instance
|
|
236
|
+
"""
|
|
237
|
+
return self._fixers.copy()
|
|
238
|
+
|
|
239
|
+
def get_fixer(self, fix_type: str) -> HealthFixer | None:
|
|
240
|
+
"""Get a specific fixer by type.
|
|
241
|
+
|
|
242
|
+
Args:
|
|
243
|
+
fix_type: The fix type identifier
|
|
244
|
+
|
|
245
|
+
Returns:
|
|
246
|
+
HealthFixer instance or None if not found
|
|
247
|
+
"""
|
|
248
|
+
return self._fixers.get(fix_type)
|
|
249
|
+
|
|
250
|
+
def scan_all(self) -> dict[str, dict[str, Any]]:
|
|
251
|
+
"""Scan for all fixable issues.
|
|
252
|
+
|
|
253
|
+
Returns:
|
|
254
|
+
Dict mapping fix_type to scan results
|
|
255
|
+
"""
|
|
256
|
+
results = {}
|
|
257
|
+
for fix_type, fixer in self._fixers.items():
|
|
258
|
+
results[fix_type] = fixer.scan()
|
|
259
|
+
return results
|
|
260
|
+
|
|
261
|
+
def dry_run_fix(self, fix_type: str) -> FixResult | None:
|
|
262
|
+
"""Preview a specific fix.
|
|
263
|
+
|
|
264
|
+
Args:
|
|
265
|
+
fix_type: Which fix to preview
|
|
266
|
+
|
|
267
|
+
Returns:
|
|
268
|
+
FixResult or None if fixer not found
|
|
269
|
+
"""
|
|
270
|
+
fixer = self.get_fixer(fix_type)
|
|
271
|
+
if not fixer:
|
|
272
|
+
return None
|
|
273
|
+
return fixer.dry_run()
|
|
274
|
+
|
|
275
|
+
def apply_fix(self, fix_type: str, force: bool = False) -> FixResult | None:
|
|
276
|
+
"""Apply a specific fix.
|
|
277
|
+
|
|
278
|
+
Args:
|
|
279
|
+
fix_type: Which fix to apply
|
|
280
|
+
force: If True, apply without confirmation
|
|
281
|
+
|
|
282
|
+
Returns:
|
|
283
|
+
FixResult or None if fixer not found
|
|
284
|
+
"""
|
|
285
|
+
fixer = self.get_fixer(fix_type)
|
|
286
|
+
if not fixer:
|
|
287
|
+
return None
|
|
288
|
+
|
|
289
|
+
# For review fixes, confirm first
|
|
290
|
+
if not force and fixer.safety_level == FixSafety.REVIEW:
|
|
291
|
+
dry_result = fixer.dry_run()
|
|
292
|
+
if not fixer.confirm_apply(dry_result):
|
|
293
|
+
return None
|
|
294
|
+
|
|
295
|
+
return fixer.apply(force=force)
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"""Health check fixers for automatically correcting detected issues.
|
|
2
|
+
|
|
3
|
+
Available fixers:
|
|
4
|
+
- OldBackupsFixer: Delete old backup files (>90 days)
|
|
5
|
+
- DuplicateIssuesFixer: Merge duplicate issues
|
|
6
|
+
- OrphanedIssuesFixer: Assign unassigned issues to Backlog
|
|
7
|
+
- FolderStructureFixer: Move issues to correct milestone folders
|
|
8
|
+
- CorruptedCommentsFixer: Sanitize malformed JSON comments
|
|
9
|
+
- DataIntegrityFixer: Remove malformed issue files
|
|
10
|
+
"""
|