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,96 @@
|
|
|
1
|
+
"""Lookup issue by GitHub ID command - find internal issue by GitHub issue number."""
|
|
2
|
+
|
|
3
|
+
import click
|
|
4
|
+
|
|
5
|
+
from roadmap.adapters.cli.cli_command_helpers import require_initialized
|
|
6
|
+
from roadmap.common.console import get_console
|
|
7
|
+
from roadmap.common.formatters.text.operations import (
|
|
8
|
+
format_operation_failure,
|
|
9
|
+
)
|
|
10
|
+
from roadmap.common.logging import (
|
|
11
|
+
log_command,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
console = get_console()
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@click.command("lookup-github")
|
|
18
|
+
@click.argument("github_id", type=int)
|
|
19
|
+
@click.pass_context
|
|
20
|
+
@log_command("issue_lookup_github", entity_type="issue", track_duration=True)
|
|
21
|
+
@require_initialized
|
|
22
|
+
def lookup_github_issue(ctx: click.Context, github_id: int) -> None:
|
|
23
|
+
"""Look up an internal issue by its GitHub issue number.
|
|
24
|
+
|
|
25
|
+
Searches for an internal issue linked to the provided GitHub issue number
|
|
26
|
+
and displays its details.
|
|
27
|
+
|
|
28
|
+
Example:
|
|
29
|
+
roadmap issue lookup-github 456
|
|
30
|
+
"""
|
|
31
|
+
core = ctx.obj["core"]
|
|
32
|
+
|
|
33
|
+
# Validate GitHub ID is positive
|
|
34
|
+
if github_id <= 0:
|
|
35
|
+
lines = format_operation_failure(
|
|
36
|
+
"lookup GitHub issue", None, "Invalid GitHub issue number"
|
|
37
|
+
)
|
|
38
|
+
for line in lines:
|
|
39
|
+
# Use click.echo for proper output capture in Click's CliRunner
|
|
40
|
+
click.echo(line)
|
|
41
|
+
ctx.exit(1)
|
|
42
|
+
|
|
43
|
+
# Get all issues and search for one with matching github_issue
|
|
44
|
+
all_issues = core.issues.get_all()
|
|
45
|
+
matching_issue = None
|
|
46
|
+
|
|
47
|
+
for issue in all_issues:
|
|
48
|
+
if issue.github_issue == github_id:
|
|
49
|
+
matching_issue = issue
|
|
50
|
+
break
|
|
51
|
+
|
|
52
|
+
if not matching_issue:
|
|
53
|
+
lines = format_operation_failure(
|
|
54
|
+
"lookup GitHub issue",
|
|
55
|
+
None,
|
|
56
|
+
f"No issue found linked to GitHub issue #{github_id}",
|
|
57
|
+
)
|
|
58
|
+
for line in lines:
|
|
59
|
+
# Use click.echo for proper output capture in Click's CliRunner
|
|
60
|
+
click.echo(line)
|
|
61
|
+
ctx.exit(1)
|
|
62
|
+
|
|
63
|
+
# Display issue details
|
|
64
|
+
console.print(
|
|
65
|
+
f"✅ Found issue linked to GitHub issue #{github_id}", style="bold green"
|
|
66
|
+
)
|
|
67
|
+
console.print()
|
|
68
|
+
console.print(f" ID: {matching_issue.id}", style="cyan")
|
|
69
|
+
console.print(f" Title: {matching_issue.title}", style="bold")
|
|
70
|
+
console.print(f" Status: {matching_issue.status.value}", style="cyan")
|
|
71
|
+
console.print(f" Priority: {matching_issue.priority.value}", style="cyan")
|
|
72
|
+
|
|
73
|
+
if matching_issue.assignee:
|
|
74
|
+
console.print(f" Assigned to: {matching_issue.assignee}", style="cyan")
|
|
75
|
+
|
|
76
|
+
if matching_issue.milestone:
|
|
77
|
+
console.print(f" Milestone: {matching_issue.milestone}", style="cyan")
|
|
78
|
+
|
|
79
|
+
if matching_issue.labels:
|
|
80
|
+
console.print(f" Labels: {', '.join(matching_issue.labels)}", style="cyan")
|
|
81
|
+
|
|
82
|
+
if matching_issue.estimated_hours:
|
|
83
|
+
console.print(
|
|
84
|
+
f" Estimated: {matching_issue.estimated_time_display}", style="cyan"
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
if matching_issue.content:
|
|
88
|
+
console.print()
|
|
89
|
+
console.print("Description:", style="bold cyan")
|
|
90
|
+
console.print(matching_issue.content, style="dim")
|
|
91
|
+
|
|
92
|
+
console.print()
|
|
93
|
+
console.print(
|
|
94
|
+
f" Use 'roadmap issue view {matching_issue.id}' for full details",
|
|
95
|
+
style="dim",
|
|
96
|
+
)
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"""Update progress command - thin wrapper around update.
|
|
2
|
+
|
|
3
|
+
This command is syntactic sugar for: roadmap issue update <ID> --progress <PERCENT>
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import click
|
|
7
|
+
|
|
8
|
+
from roadmap.adapters.cli.cli_command_helpers import (
|
|
9
|
+
ensure_entity_exists,
|
|
10
|
+
require_initialized,
|
|
11
|
+
)
|
|
12
|
+
from roadmap.adapters.cli.cli_error_handlers import handle_cli_error
|
|
13
|
+
from roadmap.common.console import get_console
|
|
14
|
+
from roadmap.common.formatters.text.operations import (
|
|
15
|
+
format_operation_failure,
|
|
16
|
+
format_operation_success,
|
|
17
|
+
)
|
|
18
|
+
from roadmap.common.logging import (
|
|
19
|
+
log_command,
|
|
20
|
+
track_database_operation,
|
|
21
|
+
)
|
|
22
|
+
from roadmap.core.domain import Status
|
|
23
|
+
|
|
24
|
+
console = get_console()
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@click.command("progress")
|
|
28
|
+
@click.argument("issue_id")
|
|
29
|
+
@click.argument("percentage", type=float)
|
|
30
|
+
@click.pass_context
|
|
31
|
+
@log_command("issue_progress", entity_type="issue", track_duration=True)
|
|
32
|
+
@require_initialized
|
|
33
|
+
def update_progress(ctx: click.Context, issue_id: str, percentage: float):
|
|
34
|
+
"""Update the progress percentage for an issue (0-100).
|
|
35
|
+
|
|
36
|
+
Syntactic sugar for: roadmap issue update <ID> --progress <PERCENT>
|
|
37
|
+
"""
|
|
38
|
+
core = ctx.obj["core"]
|
|
39
|
+
|
|
40
|
+
if not 0 <= percentage <= 100:
|
|
41
|
+
console.print(
|
|
42
|
+
"❌ Progress percentage must be between 0 and 100", style="bold red"
|
|
43
|
+
)
|
|
44
|
+
return
|
|
45
|
+
|
|
46
|
+
try:
|
|
47
|
+
# Get the issue
|
|
48
|
+
issue = ensure_entity_exists(core, "issue", issue_id)
|
|
49
|
+
|
|
50
|
+
# Update progress via core.update_issue
|
|
51
|
+
with track_database_operation("update", "issue", entity_id=issue_id):
|
|
52
|
+
updated = core.issues.update(issue_id, progress_percentage=percentage)
|
|
53
|
+
|
|
54
|
+
if updated:
|
|
55
|
+
# Build extra details for display
|
|
56
|
+
extra_details = {"Progress": f"{percentage:.0f}%"}
|
|
57
|
+
|
|
58
|
+
# Auto-update status based on progress
|
|
59
|
+
if percentage == 0:
|
|
60
|
+
extra_details["Note"] = "Resetting to todo"
|
|
61
|
+
elif percentage == 100:
|
|
62
|
+
extra_details["Tip"] = "roadmap issue close to mark complete"
|
|
63
|
+
else:
|
|
64
|
+
if issue.status == Status.TODO:
|
|
65
|
+
core.issues.update(issue_id, status=Status.IN_PROGRESS)
|
|
66
|
+
extra_details["Status"] = "Auto-updated to In Progress"
|
|
67
|
+
|
|
68
|
+
# Display success with formatter
|
|
69
|
+
lines = format_operation_success(
|
|
70
|
+
emoji="📊",
|
|
71
|
+
action="Updated progress",
|
|
72
|
+
entity_title=issue.title,
|
|
73
|
+
entity_id=issue_id,
|
|
74
|
+
extra_details=extra_details,
|
|
75
|
+
)
|
|
76
|
+
for line in lines:
|
|
77
|
+
console.print(line, style="bold green" if "Updated" in line else "cyan")
|
|
78
|
+
else:
|
|
79
|
+
lines = format_operation_failure(
|
|
80
|
+
action="update progress",
|
|
81
|
+
entity_id=issue_id,
|
|
82
|
+
error="No changes made",
|
|
83
|
+
)
|
|
84
|
+
for line in lines:
|
|
85
|
+
console.print(line, style="bold red")
|
|
86
|
+
|
|
87
|
+
except Exception as e:
|
|
88
|
+
handle_cli_error(
|
|
89
|
+
error=e,
|
|
90
|
+
operation="update_issue_progress",
|
|
91
|
+
entity_type="issue",
|
|
92
|
+
entity_id=issue_id,
|
|
93
|
+
context={"percentage": percentage},
|
|
94
|
+
fatal=True,
|
|
95
|
+
)
|
|
96
|
+
lines = format_operation_failure(
|
|
97
|
+
action="update progress",
|
|
98
|
+
entity_id=issue_id,
|
|
99
|
+
error=str(e),
|
|
100
|
+
)
|
|
101
|
+
for line in lines:
|
|
102
|
+
console.print(line, style="bold red")
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"""Restore issue command - move archived issues back to active."""
|
|
2
|
+
|
|
3
|
+
import click
|
|
4
|
+
|
|
5
|
+
from roadmap.adapters.cli.cli_command_helpers import require_initialized
|
|
6
|
+
from roadmap.adapters.cli.issues.restore_class import IssueRestore
|
|
7
|
+
from roadmap.common.console import get_console
|
|
8
|
+
from roadmap.common.logging import (
|
|
9
|
+
log_command,
|
|
10
|
+
verbose_output,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@click.command()
|
|
15
|
+
@click.argument("issue_id", required=False)
|
|
16
|
+
@click.option(
|
|
17
|
+
"--all",
|
|
18
|
+
is_flag=True,
|
|
19
|
+
help="Restore all archived issues",
|
|
20
|
+
)
|
|
21
|
+
@click.option(
|
|
22
|
+
"--status",
|
|
23
|
+
type=click.Choice(["todo", "in-progress", "blocked", "review", "closed"]),
|
|
24
|
+
help="Set status when restoring (default: keep current status)",
|
|
25
|
+
)
|
|
26
|
+
@click.option(
|
|
27
|
+
"--dry-run",
|
|
28
|
+
is_flag=True,
|
|
29
|
+
help="Preview what would be restored without actually doing it",
|
|
30
|
+
)
|
|
31
|
+
@click.option(
|
|
32
|
+
"--force",
|
|
33
|
+
is_flag=True,
|
|
34
|
+
help="Skip confirmation prompt",
|
|
35
|
+
)
|
|
36
|
+
@click.option(
|
|
37
|
+
"--verbose",
|
|
38
|
+
"-v",
|
|
39
|
+
is_flag=True,
|
|
40
|
+
help="Show detailed debug information",
|
|
41
|
+
)
|
|
42
|
+
@click.pass_context
|
|
43
|
+
@verbose_output
|
|
44
|
+
@log_command("issue_restore", entity_type="issue", track_duration=True)
|
|
45
|
+
@require_initialized
|
|
46
|
+
def restore_issue(
|
|
47
|
+
ctx: click.Context,
|
|
48
|
+
issue_id: str | None,
|
|
49
|
+
all: bool,
|
|
50
|
+
status: str | None,
|
|
51
|
+
dry_run: bool,
|
|
52
|
+
force: bool,
|
|
53
|
+
verbose: bool, # noqa: F841
|
|
54
|
+
):
|
|
55
|
+
"""Restore an archived issue back to active issues.
|
|
56
|
+
|
|
57
|
+
This moves an issue from .roadmap/archive/issues/ back to
|
|
58
|
+
.roadmap/issues/, making it active again. Optionally update
|
|
59
|
+
the status when restoring.
|
|
60
|
+
|
|
61
|
+
Examples:
|
|
62
|
+
roadmap issue restore 8a00a17e
|
|
63
|
+
roadmap issue restore 8a00a17e --status todo
|
|
64
|
+
roadmap issue restore --all
|
|
65
|
+
roadmap issue restore 8a00a17e --dry-run
|
|
66
|
+
"""
|
|
67
|
+
core = ctx.obj["core"]
|
|
68
|
+
console = get_console()
|
|
69
|
+
|
|
70
|
+
restore = IssueRestore(core, console)
|
|
71
|
+
|
|
72
|
+
if not issue_id and not all:
|
|
73
|
+
console.print(
|
|
74
|
+
"❌ Error: Specify an issue ID or use --all",
|
|
75
|
+
style="bold red",
|
|
76
|
+
)
|
|
77
|
+
ctx.exit(1)
|
|
78
|
+
|
|
79
|
+
if issue_id and all:
|
|
80
|
+
console.print(
|
|
81
|
+
"❌ Error: Cannot specify issue ID with --all",
|
|
82
|
+
style="bold red",
|
|
83
|
+
)
|
|
84
|
+
ctx.exit(1)
|
|
85
|
+
|
|
86
|
+
try:
|
|
87
|
+
restore.execute(
|
|
88
|
+
entity_id=issue_id,
|
|
89
|
+
all=all,
|
|
90
|
+
status=status,
|
|
91
|
+
dry_run=dry_run,
|
|
92
|
+
force=force,
|
|
93
|
+
)
|
|
94
|
+
except Exception as e:
|
|
95
|
+
console.print(f"❌ Restore operation failed: {str(e)}", style="bold red")
|
|
96
|
+
ctx.exit(1)
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"""IssueRestore command implementation using base class."""
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
from roadmap.adapters.cli.crud import BaseRestore, EntityType
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class IssueRestore(BaseRestore):
|
|
9
|
+
"""Restore issue command implementation."""
|
|
10
|
+
|
|
11
|
+
entity_type = EntityType.ISSUE
|
|
12
|
+
|
|
13
|
+
def get_archived_files_to_restore(
|
|
14
|
+
self, entity_id: str | None = None, **filters
|
|
15
|
+
) -> list[Path]:
|
|
16
|
+
"""Get archived issue files to restore.
|
|
17
|
+
|
|
18
|
+
Args:
|
|
19
|
+
entity_id: Specific issue ID to restore
|
|
20
|
+
**filters: Additional filter criteria
|
|
21
|
+
|
|
22
|
+
Returns:
|
|
23
|
+
List of archived file paths
|
|
24
|
+
"""
|
|
25
|
+
from roadmap.adapters.cli.crud.crud_helpers import get_archive_dir
|
|
26
|
+
|
|
27
|
+
archive_dir = get_archive_dir(self.entity_type)
|
|
28
|
+
|
|
29
|
+
if not archive_dir.exists():
|
|
30
|
+
return []
|
|
31
|
+
|
|
32
|
+
if entity_id:
|
|
33
|
+
# Find specific issue file by ID prefix
|
|
34
|
+
matching = list(archive_dir.rglob(f"{entity_id[:8]}*.md"))
|
|
35
|
+
return matching if matching else []
|
|
36
|
+
else:
|
|
37
|
+
# Return all archived issues
|
|
38
|
+
return list(archive_dir.rglob("*.md"))
|
|
39
|
+
|
|
40
|
+
def post_restore_hook(self, restored_files: list[Path], **kwargs) -> None:
|
|
41
|
+
"""Handle post-restore state updates.
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
restored_files: Files that were restored
|
|
45
|
+
**kwargs: Additional arguments
|
|
46
|
+
"""
|
|
47
|
+
# Mark issues as restored in database
|
|
48
|
+
for file_path in restored_files:
|
|
49
|
+
try:
|
|
50
|
+
# Extract issue ID from filename
|
|
51
|
+
issue_id = file_path.stem.split("-")[0]
|
|
52
|
+
self.core.db.mark_issue_archived(issue_id, archived=False)
|
|
53
|
+
except Exception as e:
|
|
54
|
+
self.console.print(
|
|
55
|
+
f"⚠️ Warning: Failed to update restoration status for {file_path.name}: {e}",
|
|
56
|
+
style="yellow",
|
|
57
|
+
)
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
"""Start issue command - thin wrapper around update.
|
|
2
|
+
|
|
3
|
+
This command is syntactic sugar for: roadmap issue update <ID> --status in-progress
|
|
4
|
+
with optional Git branch creation.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import click
|
|
8
|
+
|
|
9
|
+
from roadmap.adapters.cli.cli_command_helpers import require_initialized
|
|
10
|
+
from roadmap.adapters.cli.cli_error_handlers import handle_cli_error
|
|
11
|
+
from roadmap.common.console import get_console
|
|
12
|
+
from roadmap.common.formatters.text.operations import (
|
|
13
|
+
format_operation_failure,
|
|
14
|
+
format_operation_success,
|
|
15
|
+
)
|
|
16
|
+
from roadmap.common.logging import (
|
|
17
|
+
log_command,
|
|
18
|
+
track_database_operation,
|
|
19
|
+
)
|
|
20
|
+
from roadmap.core.services import StartIssueService
|
|
21
|
+
|
|
22
|
+
console = get_console()
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@click.command("start")
|
|
26
|
+
@click.argument("issue_id")
|
|
27
|
+
@click.option("--date", help="Start date (YYYY-MM-DD HH:MM, defaults to now)")
|
|
28
|
+
@click.option(
|
|
29
|
+
"--git-branch/--no-git-branch",
|
|
30
|
+
default=False,
|
|
31
|
+
help="Create a Git branch for this issue when starting",
|
|
32
|
+
)
|
|
33
|
+
@click.option(
|
|
34
|
+
"--checkout/--no-checkout",
|
|
35
|
+
default=True,
|
|
36
|
+
help="Checkout the created branch (when --git-branch is used)",
|
|
37
|
+
)
|
|
38
|
+
@click.option("--branch-name", default=None, help="Override suggested branch name")
|
|
39
|
+
@click.option(
|
|
40
|
+
"--force", is_flag=True, help="Force branch creation even if working tree is dirty"
|
|
41
|
+
)
|
|
42
|
+
@click.pass_context
|
|
43
|
+
@log_command("issue_start", entity_type="issue", track_duration=True)
|
|
44
|
+
@require_initialized
|
|
45
|
+
def start_issue(
|
|
46
|
+
ctx: click.Context,
|
|
47
|
+
issue_id: str,
|
|
48
|
+
date: str,
|
|
49
|
+
git_branch: bool,
|
|
50
|
+
checkout: bool,
|
|
51
|
+
branch_name: str,
|
|
52
|
+
force: bool,
|
|
53
|
+
):
|
|
54
|
+
"""Start work on an issue (sets status to in-progress and records start date).
|
|
55
|
+
|
|
56
|
+
Syntactic sugar for: roadmap issue update <ID> --status in-progress
|
|
57
|
+
"""
|
|
58
|
+
core = ctx.obj["core"]
|
|
59
|
+
|
|
60
|
+
try:
|
|
61
|
+
# Create start issue service
|
|
62
|
+
service = StartIssueService(core)
|
|
63
|
+
|
|
64
|
+
# Parse start date
|
|
65
|
+
try:
|
|
66
|
+
start_date = service.parse_start_date(date)
|
|
67
|
+
except ValueError:
|
|
68
|
+
console.print(
|
|
69
|
+
"❌ Invalid date format. Use YYYY-MM-DD or YYYY-MM-DD HH:MM",
|
|
70
|
+
style="bold red",
|
|
71
|
+
)
|
|
72
|
+
return
|
|
73
|
+
|
|
74
|
+
# Get the issue
|
|
75
|
+
issue = core.issues.get(issue_id)
|
|
76
|
+
if not issue:
|
|
77
|
+
console.print(f"❌ Issue not found: {issue_id}", style="bold red")
|
|
78
|
+
return
|
|
79
|
+
|
|
80
|
+
# Start work on issue via core.update_issue
|
|
81
|
+
with track_database_operation("update", "issue", entity_id=issue_id):
|
|
82
|
+
success = service.start_work(issue_id, start_date)
|
|
83
|
+
|
|
84
|
+
if success:
|
|
85
|
+
# Build extra details
|
|
86
|
+
extra_details = {
|
|
87
|
+
"Status": "🚀 In Progress",
|
|
88
|
+
"Started": start_date.strftime("%Y-%m-%d %H:%M"),
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
# Display success with formatter
|
|
92
|
+
lines = format_operation_success(
|
|
93
|
+
emoji="🚀",
|
|
94
|
+
action="Started",
|
|
95
|
+
entity_title=issue.title,
|
|
96
|
+
entity_id=issue_id,
|
|
97
|
+
extra_details=extra_details,
|
|
98
|
+
)
|
|
99
|
+
for line in lines:
|
|
100
|
+
console.print(line, style="bold green" if "Started" in line else "cyan")
|
|
101
|
+
|
|
102
|
+
# Handle git branch creation
|
|
103
|
+
if service.should_create_branch(git_branch):
|
|
104
|
+
_handle_git_branch_creation(
|
|
105
|
+
core, service, issue, branch_name, checkout, force
|
|
106
|
+
)
|
|
107
|
+
else:
|
|
108
|
+
lines = format_operation_failure(
|
|
109
|
+
action="start",
|
|
110
|
+
entity_id=issue_id,
|
|
111
|
+
error="Failed to update status",
|
|
112
|
+
)
|
|
113
|
+
for line in lines:
|
|
114
|
+
console.print(line, style="bold red")
|
|
115
|
+
|
|
116
|
+
except Exception as e:
|
|
117
|
+
handle_cli_error(
|
|
118
|
+
error=e,
|
|
119
|
+
operation="start_issue",
|
|
120
|
+
entity_type="issue",
|
|
121
|
+
entity_id=issue_id,
|
|
122
|
+
context={
|
|
123
|
+
"git_branch": git_branch,
|
|
124
|
+
"checkout": checkout,
|
|
125
|
+
"branch_name": branch_name,
|
|
126
|
+
},
|
|
127
|
+
fatal=True,
|
|
128
|
+
)
|
|
129
|
+
lines = format_operation_failure(
|
|
130
|
+
action="start",
|
|
131
|
+
entity_id=issue_id,
|
|
132
|
+
error=str(e),
|
|
133
|
+
)
|
|
134
|
+
for line in lines:
|
|
135
|
+
console.print(line, style="bold red")
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def _handle_git_branch_creation(core, service, issue, branch_name, checkout, force):
|
|
139
|
+
"""Handle git branch creation for started issue."""
|
|
140
|
+
try:
|
|
141
|
+
if hasattr(core, "git") and core.git.is_git_repository():
|
|
142
|
+
success, resolved_branch_name = service.core.git.create_branch_for_issue(
|
|
143
|
+
issue, checkout=checkout, force=force
|
|
144
|
+
)
|
|
145
|
+
if success and resolved_branch_name:
|
|
146
|
+
service.display_branch_created(resolved_branch_name, checkout)
|
|
147
|
+
else:
|
|
148
|
+
service.display_branch_warning()
|
|
149
|
+
else:
|
|
150
|
+
console.print(
|
|
151
|
+
"⚠️ Not in a Git repository, skipping branch creation",
|
|
152
|
+
style="yellow",
|
|
153
|
+
)
|
|
154
|
+
except Exception as e:
|
|
155
|
+
handle_cli_error(
|
|
156
|
+
error=e,
|
|
157
|
+
operation="create_git_branch",
|
|
158
|
+
entity_type="issue",
|
|
159
|
+
entity_id=issue.id,
|
|
160
|
+
context={"branch_name": branch_name},
|
|
161
|
+
fatal=False,
|
|
162
|
+
)
|
|
163
|
+
console.print(
|
|
164
|
+
f"⚠️ Git branch creation skipped due to error: {e}", style="yellow"
|
|
165
|
+
)
|