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,348 @@
|
|
|
1
|
+
"""Roadmap initialization and setup management.
|
|
2
|
+
|
|
3
|
+
Handles creation of new roadmap projects, directory structures,
|
|
4
|
+
configuration files, and git integration setup.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import sqlite3
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from typing import Optional
|
|
10
|
+
|
|
11
|
+
from roadmap.adapters.persistence.database_manager import DatabaseError, DatabaseManager
|
|
12
|
+
from roadmap.common.logging import get_logger
|
|
13
|
+
from roadmap.common.security import (
|
|
14
|
+
create_secure_directory,
|
|
15
|
+
create_secure_file,
|
|
16
|
+
)
|
|
17
|
+
from roadmap.common.utils.path_utils import build_roadmap_paths
|
|
18
|
+
|
|
19
|
+
logger = get_logger(__name__)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class InitializationManager:
|
|
23
|
+
"""Manages roadmap initialization, configuration, and setup."""
|
|
24
|
+
|
|
25
|
+
def __init__(self, root_path: Path, roadmap_dir_name: str = ".roadmap"):
|
|
26
|
+
"""Initialize the manager with paths.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
root_path: Root directory of the project
|
|
30
|
+
roadmap_dir_name: Name of the roadmap directory (default: .roadmap)
|
|
31
|
+
"""
|
|
32
|
+
self.root_path = root_path
|
|
33
|
+
self.roadmap_dir_name = roadmap_dir_name
|
|
34
|
+
|
|
35
|
+
# Build all standard roadmap paths
|
|
36
|
+
paths = build_roadmap_paths(root_path, roadmap_dir_name)
|
|
37
|
+
self.roadmap_dir = paths["roadmap_dir"]
|
|
38
|
+
self.issues_dir = paths["issues_dir"]
|
|
39
|
+
self.milestones_dir = paths["milestones_dir"]
|
|
40
|
+
self.projects_dir = paths["projects_dir"]
|
|
41
|
+
self.templates_dir = paths["templates_dir"]
|
|
42
|
+
self.artifacts_dir = paths["artifacts_dir"]
|
|
43
|
+
self.config_file = paths["config_file"]
|
|
44
|
+
self.db_dir = paths["db_dir"]
|
|
45
|
+
|
|
46
|
+
def is_initialized(self) -> bool:
|
|
47
|
+
"""Check if roadmap is already initialized."""
|
|
48
|
+
return self.roadmap_dir.exists() and self.config_file.exists()
|
|
49
|
+
|
|
50
|
+
@classmethod
|
|
51
|
+
def find_existing_roadmap(
|
|
52
|
+
cls, root_path: Path | None = None, roadmap_dir_name: str = ".roadmap"
|
|
53
|
+
) -> Optional["InitializationManager"]:
|
|
54
|
+
"""Find an existing roadmap directory in the current path.
|
|
55
|
+
|
|
56
|
+
Searches for roadmap directory and returns a manager instance if found,
|
|
57
|
+
or None if no roadmap is detected.
|
|
58
|
+
|
|
59
|
+
Args:
|
|
60
|
+
root_path: Root path to search from (defaults to current directory)
|
|
61
|
+
roadmap_dir_name: Name of the roadmap directory to search for
|
|
62
|
+
|
|
63
|
+
Returns:
|
|
64
|
+
InitializationManager if roadmap found, None otherwise
|
|
65
|
+
"""
|
|
66
|
+
search_path = root_path or Path.cwd()
|
|
67
|
+
|
|
68
|
+
# Common roadmap directory names to search for
|
|
69
|
+
possible_names = [roadmap_dir_name]
|
|
70
|
+
|
|
71
|
+
# Also check for any directory containing the expected structure
|
|
72
|
+
try:
|
|
73
|
+
for item in search_path.iterdir():
|
|
74
|
+
if item.is_dir() and item.name not in possible_names:
|
|
75
|
+
possible_names.append(item.name)
|
|
76
|
+
except (OSError, PermissionError):
|
|
77
|
+
pass
|
|
78
|
+
|
|
79
|
+
# Check each possible directory
|
|
80
|
+
for dir_name in possible_names:
|
|
81
|
+
try:
|
|
82
|
+
potential_manager = cls(
|
|
83
|
+
root_path=search_path, roadmap_dir_name=dir_name
|
|
84
|
+
)
|
|
85
|
+
if potential_manager.is_initialized():
|
|
86
|
+
return potential_manager
|
|
87
|
+
except (OSError, PermissionError, sqlite3.OperationalError):
|
|
88
|
+
# Skip directories that can't be accessed
|
|
89
|
+
continue
|
|
90
|
+
|
|
91
|
+
return None
|
|
92
|
+
|
|
93
|
+
def initialize(self) -> None:
|
|
94
|
+
"""Initialize a new roadmap in the current directory.
|
|
95
|
+
|
|
96
|
+
Raises:
|
|
97
|
+
ValueError: If roadmap is already initialized
|
|
98
|
+
"""
|
|
99
|
+
if self.is_initialized():
|
|
100
|
+
raise ValueError("Roadmap already initialized in this directory")
|
|
101
|
+
|
|
102
|
+
# Create directory structure with secure permissions
|
|
103
|
+
create_secure_directory(self.roadmap_dir, 0o755)
|
|
104
|
+
create_secure_directory(self.issues_dir, 0o755)
|
|
105
|
+
create_secure_directory(self.milestones_dir, 0o755)
|
|
106
|
+
create_secure_directory(self.projects_dir, 0o755)
|
|
107
|
+
create_secure_directory(self.templates_dir, 0o755)
|
|
108
|
+
create_secure_directory(self.artifacts_dir, 0o755)
|
|
109
|
+
|
|
110
|
+
# Update .gitignore to exclude roadmap local data
|
|
111
|
+
self._update_gitignore()
|
|
112
|
+
|
|
113
|
+
# Create templates
|
|
114
|
+
self._create_default_templates()
|
|
115
|
+
|
|
116
|
+
# Create default config file
|
|
117
|
+
self._create_default_config()
|
|
118
|
+
|
|
119
|
+
# Initialize database file in project-local directory
|
|
120
|
+
self._initialize_database()
|
|
121
|
+
|
|
122
|
+
def _initialize_database(self) -> None:
|
|
123
|
+
"""Create and validate the project-local database file."""
|
|
124
|
+
try:
|
|
125
|
+
create_secure_directory(self.db_dir, 0o755)
|
|
126
|
+
db_path = self.db_dir / "state.db"
|
|
127
|
+
db_manager = DatabaseManager(db_path=db_path)
|
|
128
|
+
db_manager.validate_read_write()
|
|
129
|
+
except (OSError, DatabaseError) as e:
|
|
130
|
+
logger.error(
|
|
131
|
+
"database_init_failed",
|
|
132
|
+
db_path=str(self.db_dir / "state.db"),
|
|
133
|
+
error=str(e),
|
|
134
|
+
error_type=type(e).__name__,
|
|
135
|
+
severity="system_error",
|
|
136
|
+
)
|
|
137
|
+
raise RuntimeError(
|
|
138
|
+
f"Failed to initialize database at {self.db_dir / 'state.db'}: {e}"
|
|
139
|
+
) from e
|
|
140
|
+
|
|
141
|
+
def _create_default_templates(self) -> None:
|
|
142
|
+
"""Create default templates for issues, milestones, and projects."""
|
|
143
|
+
# Issue template
|
|
144
|
+
issue_template = """---
|
|
145
|
+
id: "{{ issue_id }}"
|
|
146
|
+
title: "{{ title }}"
|
|
147
|
+
priority: "medium"
|
|
148
|
+
status: "todo"
|
|
149
|
+
milestone: ""
|
|
150
|
+
labels: []
|
|
151
|
+
github_issue: null
|
|
152
|
+
created: "{{ created_date }}"
|
|
153
|
+
updated: "{{ updated_date }}"
|
|
154
|
+
assignee: ""
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
# {{ title }}
|
|
158
|
+
|
|
159
|
+
## Description
|
|
160
|
+
|
|
161
|
+
Brief description of the issue or feature request.
|
|
162
|
+
|
|
163
|
+
## Acceptance Criteria
|
|
164
|
+
|
|
165
|
+
- [ ] Criterion 1
|
|
166
|
+
- [ ] Criterion 2
|
|
167
|
+
- [ ] Criterion 3
|
|
168
|
+
|
|
169
|
+
## Technical Notes
|
|
170
|
+
|
|
171
|
+
Any technical details, considerations, or implementation notes.
|
|
172
|
+
|
|
173
|
+
## Related Issues
|
|
174
|
+
|
|
175
|
+
- Links to related issues
|
|
176
|
+
- Dependencies
|
|
177
|
+
|
|
178
|
+
## Additional Context
|
|
179
|
+
|
|
180
|
+
Any additional context, screenshots, or examples."""
|
|
181
|
+
|
|
182
|
+
with create_secure_file(self.templates_dir / "issue.md", "w", 0o644) as f:
|
|
183
|
+
f.write(issue_template)
|
|
184
|
+
|
|
185
|
+
# Milestone template
|
|
186
|
+
milestone_template = """---
|
|
187
|
+
name: "{{ milestone_name }}"
|
|
188
|
+
description: "{{ description }}"
|
|
189
|
+
due_date: "{{ due_date }}"
|
|
190
|
+
status: "open"
|
|
191
|
+
github_milestone: null
|
|
192
|
+
created: "{{ created_date }}"
|
|
193
|
+
updated: "{{ updated_date }}"
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
# {{ milestone_name }}
|
|
197
|
+
|
|
198
|
+
## Description
|
|
199
|
+
|
|
200
|
+
{{ description }}
|
|
201
|
+
|
|
202
|
+
## Goals
|
|
203
|
+
|
|
204
|
+
- [ ] Goal 1
|
|
205
|
+
- [ ] Goal 2
|
|
206
|
+
- [ ] Goal 3
|
|
207
|
+
|
|
208
|
+
## Success Criteria
|
|
209
|
+
|
|
210
|
+
Define what success looks like for this milestone.
|
|
211
|
+
|
|
212
|
+
## Notes
|
|
213
|
+
|
|
214
|
+
Any additional notes or considerations for this milestone."""
|
|
215
|
+
|
|
216
|
+
with create_secure_file(self.templates_dir / "milestone.md", "w", 0o644) as f:
|
|
217
|
+
f.write(milestone_template)
|
|
218
|
+
|
|
219
|
+
# Project template
|
|
220
|
+
project_template = """---
|
|
221
|
+
id: "{{ project_id }}"
|
|
222
|
+
name: "{{ project_name }}"
|
|
223
|
+
description: "{{ project_description }}"
|
|
224
|
+
status: "planning"
|
|
225
|
+
priority: "medium"
|
|
226
|
+
owner: "{{ project_owner }}"
|
|
227
|
+
start_date: "{{ start_date }}"
|
|
228
|
+
target_end_date: "{{ target_end_date }}"
|
|
229
|
+
actual_end_date: null
|
|
230
|
+
created: "{{ created_date }}"
|
|
231
|
+
updated: "{{ updated_date }}"
|
|
232
|
+
milestones:
|
|
233
|
+
- "{{ milestone_1 }}"
|
|
234
|
+
- "{{ milestone_2 }}"
|
|
235
|
+
estimated_hours: {{ estimated_hours }}
|
|
236
|
+
actual_hours: null
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
# {{ project_name }}
|
|
240
|
+
|
|
241
|
+
## Project Overview
|
|
242
|
+
|
|
243
|
+
{{ project_description }}
|
|
244
|
+
|
|
245
|
+
**Project Owner:** {{ project_owner }}
|
|
246
|
+
**Status:** {{ status }}
|
|
247
|
+
**Timeline:** {{ start_date }} → {{ target_end_date }}
|
|
248
|
+
|
|
249
|
+
## Objectives
|
|
250
|
+
|
|
251
|
+
- [ ] Objective 1
|
|
252
|
+
- [ ] Objective 2
|
|
253
|
+
- [ ] Objective 3
|
|
254
|
+
|
|
255
|
+
## Milestones & Timeline
|
|
256
|
+
|
|
257
|
+
{% for milestone in milestones %}
|
|
258
|
+
- **{{ milestone }}** - [Link to milestone](../milestones/{{ milestone }}.md)
|
|
259
|
+
{% endfor %}
|
|
260
|
+
|
|
261
|
+
## Timeline Tracking
|
|
262
|
+
|
|
263
|
+
- **Start Date:** {{ start_date }}
|
|
264
|
+
- **Target End Date:** {{ target_end_date }}
|
|
265
|
+
- **Actual End Date:** {{ actual_end_date }}
|
|
266
|
+
- **Estimated Hours:** {{ estimated_hours }}
|
|
267
|
+
- **Actual Hours:** {{ actual_hours }}
|
|
268
|
+
|
|
269
|
+
## Notes
|
|
270
|
+
|
|
271
|
+
Project notes and additional context.
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
*Last updated: {{ updated_date }}*"""
|
|
275
|
+
|
|
276
|
+
with create_secure_file(self.templates_dir / "project.md", "w", 0o644) as f:
|
|
277
|
+
f.write(project_template)
|
|
278
|
+
|
|
279
|
+
def _create_default_config(self) -> None:
|
|
280
|
+
"""Create default configuration file."""
|
|
281
|
+
import yaml
|
|
282
|
+
|
|
283
|
+
config_data = {
|
|
284
|
+
"project_name": "My Roadmap",
|
|
285
|
+
"github": {
|
|
286
|
+
"owner": None,
|
|
287
|
+
"repo": None,
|
|
288
|
+
"enabled": False,
|
|
289
|
+
"sync_enabled": False,
|
|
290
|
+
"sync_backend": "github", # Default to github backend
|
|
291
|
+
"webhook_secret": None,
|
|
292
|
+
"sync_settings": {
|
|
293
|
+
"bidirectional": True,
|
|
294
|
+
"auto_close": True,
|
|
295
|
+
"sync_labels": True,
|
|
296
|
+
"sync_milestones": True,
|
|
297
|
+
},
|
|
298
|
+
},
|
|
299
|
+
"defaults": {
|
|
300
|
+
"priority": "medium",
|
|
301
|
+
"issue_type": "other",
|
|
302
|
+
},
|
|
303
|
+
"features": {
|
|
304
|
+
"github_integration": False,
|
|
305
|
+
"git_sync": False,
|
|
306
|
+
},
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
with create_secure_file(self.config_file, "w", 0o644) as f:
|
|
310
|
+
yaml.dump(config_data, f, default_flow_style=False)
|
|
311
|
+
|
|
312
|
+
def _update_gitignore(self) -> None:
|
|
313
|
+
"""Update .gitignore to exclude roadmap local data from version control."""
|
|
314
|
+
gitignore_path = self.root_path / ".gitignore"
|
|
315
|
+
|
|
316
|
+
# Define patterns to ignore
|
|
317
|
+
roadmap_patterns = [
|
|
318
|
+
f"{self.roadmap_dir_name}/artifacts/",
|
|
319
|
+
f"{self.roadmap_dir_name}/backups/",
|
|
320
|
+
f"{self.roadmap_dir_name}/logs/",
|
|
321
|
+
f"{self.roadmap_dir_name}/*.tmp",
|
|
322
|
+
f"{self.roadmap_dir_name}/*.lock",
|
|
323
|
+
]
|
|
324
|
+
gitignore_comment = (
|
|
325
|
+
"# Roadmap local data (generated exports, backups, logs, temp files)"
|
|
326
|
+
)
|
|
327
|
+
|
|
328
|
+
# Read existing .gitignore if it exists
|
|
329
|
+
existing_lines = []
|
|
330
|
+
if gitignore_path.exists():
|
|
331
|
+
existing_lines = gitignore_path.read_text().splitlines()
|
|
332
|
+
|
|
333
|
+
# Check which patterns are already present
|
|
334
|
+
missing_patterns = []
|
|
335
|
+
for pattern in roadmap_patterns:
|
|
336
|
+
if not any(line.strip() == pattern for line in existing_lines):
|
|
337
|
+
missing_patterns.append(pattern)
|
|
338
|
+
|
|
339
|
+
if missing_patterns:
|
|
340
|
+
# Add missing patterns
|
|
341
|
+
if existing_lines and not existing_lines[-1].strip() == "":
|
|
342
|
+
existing_lines.append("")
|
|
343
|
+
|
|
344
|
+
existing_lines.append(gitignore_comment)
|
|
345
|
+
existing_lines.extend(missing_patterns)
|
|
346
|
+
|
|
347
|
+
# Write updated .gitignore
|
|
348
|
+
gitignore_path.write_text("\n".join(existing_lines) + "\n")
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
"""Issue Coordinator - Coordinates issue-related operations.
|
|
2
|
+
|
|
3
|
+
Extracted from RoadmapCore to reduce god object complexity.
|
|
4
|
+
Provides a focused API for all issue-related concerns.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from typing import TYPE_CHECKING
|
|
10
|
+
|
|
11
|
+
from roadmap.core.domain import IssueType, Priority, Status
|
|
12
|
+
from roadmap.infrastructure.coordination.issue_operations import IssueOperations
|
|
13
|
+
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from roadmap.core.domain import Issue
|
|
16
|
+
from roadmap.infrastructure.coordination.core import RoadmapCore
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class IssueCoordinator:
|
|
20
|
+
"""Coordinates all issue-related operations."""
|
|
21
|
+
|
|
22
|
+
def __init__(self, issue_ops: IssueOperations, core: RoadmapCore | None = None):
|
|
23
|
+
"""Initialize coordinator with issue operations manager.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
issue_ops: IssueOperations instance
|
|
27
|
+
core: RoadmapCore instance for initialization checks
|
|
28
|
+
"""
|
|
29
|
+
self._ops = issue_ops
|
|
30
|
+
self._core = core
|
|
31
|
+
|
|
32
|
+
# CRUD Operations
|
|
33
|
+
def create(
|
|
34
|
+
self,
|
|
35
|
+
title: str,
|
|
36
|
+
priority: Priority = Priority.MEDIUM,
|
|
37
|
+
issue_type: IssueType = IssueType.OTHER,
|
|
38
|
+
milestone: str | None = None,
|
|
39
|
+
labels: list[str] | None = None,
|
|
40
|
+
assignee: str | None = None,
|
|
41
|
+
estimated_hours: float | None = None,
|
|
42
|
+
depends_on: list[str] | None = None,
|
|
43
|
+
blocks: list[str] | None = None,
|
|
44
|
+
status: str | None = None,
|
|
45
|
+
content: str | None = None,
|
|
46
|
+
) -> Issue:
|
|
47
|
+
"""Create a new issue."""
|
|
48
|
+
return self._ops.create_issue(
|
|
49
|
+
title=title,
|
|
50
|
+
priority=priority,
|
|
51
|
+
issue_type=issue_type,
|
|
52
|
+
milestone=milestone,
|
|
53
|
+
labels=labels,
|
|
54
|
+
assignee=assignee,
|
|
55
|
+
estimated_hours=estimated_hours,
|
|
56
|
+
depends_on=depends_on,
|
|
57
|
+
blocks=blocks,
|
|
58
|
+
status=status,
|
|
59
|
+
content=content,
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
def list(
|
|
63
|
+
self,
|
|
64
|
+
milestone: str | None = None,
|
|
65
|
+
status: Status | None = None,
|
|
66
|
+
priority: Priority | None = None,
|
|
67
|
+
issue_type: IssueType | None = None,
|
|
68
|
+
assignee: str | None = None,
|
|
69
|
+
) -> list[Issue]:
|
|
70
|
+
"""List issues with optional filtering."""
|
|
71
|
+
return self._ops.list_issues(
|
|
72
|
+
milestone=milestone,
|
|
73
|
+
status=status,
|
|
74
|
+
priority=priority,
|
|
75
|
+
issue_type=issue_type,
|
|
76
|
+
assignee=assignee,
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
def list_all_including_archived(self) -> list[Issue]:
|
|
80
|
+
"""List all issues including archived ones.
|
|
81
|
+
|
|
82
|
+
Used by sync operations that need to compare both active and archived issues.
|
|
83
|
+
|
|
84
|
+
Returns:
|
|
85
|
+
List of all Issue objects (both active and archived)
|
|
86
|
+
"""
|
|
87
|
+
return self._ops.list_all_including_archived()
|
|
88
|
+
|
|
89
|
+
def get(self, issue_id: str) -> Issue | None:
|
|
90
|
+
"""Get a specific issue by ID."""
|
|
91
|
+
return self._ops.get_issue(issue_id)
|
|
92
|
+
|
|
93
|
+
def update(self, issue_id: str, **updates) -> Issue | None:
|
|
94
|
+
"""Update an existing issue."""
|
|
95
|
+
return self._ops.update_issue(issue_id, **updates)
|
|
96
|
+
|
|
97
|
+
def delete(self, issue_id: str) -> bool:
|
|
98
|
+
"""Delete an issue."""
|
|
99
|
+
return self._ops.delete_issue(issue_id)
|
|
100
|
+
|
|
101
|
+
# Milestone-related queries
|
|
102
|
+
def get_backlog(self) -> list[Issue]:
|
|
103
|
+
"""Get all issues not assigned to any milestone (backlog)."""
|
|
104
|
+
return self._ops.get_backlog_issues()
|
|
105
|
+
|
|
106
|
+
def get_by_milestone(self, milestone_name: str) -> list[Issue]:
|
|
107
|
+
"""Get all issues assigned to a specific milestone."""
|
|
108
|
+
return self._ops.get_milestone_issues(milestone_name)
|
|
109
|
+
|
|
110
|
+
def get_grouped_by_milestone(self) -> dict[str, list[Issue]]:
|
|
111
|
+
"""Get all issues grouped by milestone, including backlog."""
|
|
112
|
+
return self._ops.get_issues_by_milestone()
|
|
113
|
+
|
|
114
|
+
def move_to_milestone(self, issue_id: str, milestone_name: str | None) -> bool:
|
|
115
|
+
"""Move an issue to a milestone or to backlog if milestone_name is None."""
|
|
116
|
+
return self._ops.move_issue_to_milestone(issue_id, milestone_name)
|
|
117
|
+
|
|
118
|
+
def assign_to_milestone(self, issue_id: str, milestone_name: str) -> bool:
|
|
119
|
+
"""Assign an issue to a milestone."""
|
|
120
|
+
return self._ops.assign_issue_to_milestone(issue_id, milestone_name)
|
|
121
|
+
|
|
122
|
+
def batch_assign_to_milestone(
|
|
123
|
+
self,
|
|
124
|
+
issue_ids: list[str],
|
|
125
|
+
milestone_name: str,
|
|
126
|
+
preloaded_issues: list | None = None,
|
|
127
|
+
) -> tuple[int, int]:
|
|
128
|
+
"""Batch assign multiple issues to a milestone in a single pass.
|
|
129
|
+
|
|
130
|
+
Args:
|
|
131
|
+
issue_ids: List of issue IDs to assign
|
|
132
|
+
milestone_name: The milestone name to assign to
|
|
133
|
+
preloaded_issues: Optional pre-loaded list of issues (avoids filesystem scan)
|
|
134
|
+
|
|
135
|
+
Returns:
|
|
136
|
+
Tuple of (successful_count, failed_count)
|
|
137
|
+
"""
|
|
138
|
+
return self._ops.batch_assign_to_milestone(
|
|
139
|
+
issue_ids, milestone_name, preloaded_issues
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
def get_similar_milestone_names(
|
|
143
|
+
self, milestone_name: str, max_results: int = 3
|
|
144
|
+
) -> list[str]:
|
|
145
|
+
"""Find milestone names similar to the given name.
|
|
146
|
+
|
|
147
|
+
Args:
|
|
148
|
+
milestone_name: The milestone name to find similar matches for
|
|
149
|
+
max_results: Maximum number of suggestions to return
|
|
150
|
+
|
|
151
|
+
Returns:
|
|
152
|
+
List of similar milestone names found
|
|
153
|
+
"""
|
|
154
|
+
return self._ops.get_similar_milestone_names(milestone_name, max_results)
|