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,154 @@
|
|
|
1
|
+
"""GitHub configuration management utilities."""
|
|
2
|
+
|
|
3
|
+
import yaml
|
|
4
|
+
from structlog import get_logger
|
|
5
|
+
|
|
6
|
+
from roadmap.common.console import get_console
|
|
7
|
+
from roadmap.common.constants import SyncBackend
|
|
8
|
+
from roadmap.core.utils.git_remote_parser import get_github_from_git_remote
|
|
9
|
+
from roadmap.infrastructure.coordination.core import RoadmapCore
|
|
10
|
+
|
|
11
|
+
logger = get_logger()
|
|
12
|
+
console = get_console()
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class GitHubConfigManager:
|
|
16
|
+
"""Manages GitHub configuration in roadmap config file."""
|
|
17
|
+
|
|
18
|
+
def __init__(self, core: RoadmapCore):
|
|
19
|
+
"""Initialize GitHubConfigManager.
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
core: Core roadmap instance.
|
|
23
|
+
"""
|
|
24
|
+
self.core = core
|
|
25
|
+
self.config_file = core.roadmap_dir / "config.yaml"
|
|
26
|
+
|
|
27
|
+
def save_github_config(
|
|
28
|
+
self, github_repo: str, sync_backend: SyncBackend = SyncBackend.GITHUB
|
|
29
|
+
) -> None:
|
|
30
|
+
"""Save GitHub repository configuration.
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
github_repo: GitHub repository (owner/repo)
|
|
34
|
+
sync_backend: Backend to use (SyncBackend.GITHUB or SyncBackend.GIT)
|
|
35
|
+
|
|
36
|
+
Raises:
|
|
37
|
+
ValueError: If github_repo is invalid format
|
|
38
|
+
"""
|
|
39
|
+
# Validate repository format
|
|
40
|
+
if not github_repo or "/" not in github_repo:
|
|
41
|
+
log = logger.bind(github_repo=github_repo, operation="save_github_config")
|
|
42
|
+
log.error("invalid_github_repo_format")
|
|
43
|
+
raise ValueError(
|
|
44
|
+
f"Invalid GitHub repository format: '{github_repo}'. "
|
|
45
|
+
"Expected format: 'owner/repo'"
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
try:
|
|
49
|
+
if self.config_file.exists():
|
|
50
|
+
with open(self.config_file) as f:
|
|
51
|
+
loaded = yaml.safe_load(f)
|
|
52
|
+
config = loaded if isinstance(loaded, dict) else {}
|
|
53
|
+
else:
|
|
54
|
+
config: dict = {}
|
|
55
|
+
|
|
56
|
+
config["github"] = {
|
|
57
|
+
"repository": github_repo,
|
|
58
|
+
"enabled": True,
|
|
59
|
+
"sync_enabled": True,
|
|
60
|
+
"sync_backend": sync_backend.value,
|
|
61
|
+
"webhook_secret": None,
|
|
62
|
+
"sync_settings": {
|
|
63
|
+
"bidirectional": True,
|
|
64
|
+
"auto_close": True,
|
|
65
|
+
"sync_labels": True,
|
|
66
|
+
"sync_milestones": True,
|
|
67
|
+
},
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
with open(self.config_file, "w") as f:
|
|
71
|
+
yaml.dump(config, f, default_flow_style=False, sort_keys=False)
|
|
72
|
+
|
|
73
|
+
log = logger.bind(
|
|
74
|
+
github_repo=github_repo,
|
|
75
|
+
sync_backend=sync_backend.value,
|
|
76
|
+
operation="save_github_config",
|
|
77
|
+
)
|
|
78
|
+
log.info("github_config_saved")
|
|
79
|
+
get_console().print("⚙️ Configuration saved")
|
|
80
|
+
|
|
81
|
+
except ValueError:
|
|
82
|
+
# Re-raise validation errors
|
|
83
|
+
raise
|
|
84
|
+
except Exception as e:
|
|
85
|
+
log = logger.bind(
|
|
86
|
+
github_repo=github_repo,
|
|
87
|
+
sync_backend=sync_backend.value,
|
|
88
|
+
error=str(e),
|
|
89
|
+
operation="save_github_config",
|
|
90
|
+
)
|
|
91
|
+
log.error("github_config_save_failed")
|
|
92
|
+
raise
|
|
93
|
+
|
|
94
|
+
def auto_detect_and_update(self) -> tuple[str | None, str | None]:
|
|
95
|
+
"""Auto-detect GitHub owner/repo from git remote and update config if needed.
|
|
96
|
+
|
|
97
|
+
Returns:
|
|
98
|
+
Tuple of (owner, repo) or (None, None) if not detected or disabled
|
|
99
|
+
"""
|
|
100
|
+
# Check if auto-detection is enabled in config
|
|
101
|
+
if self.config_file.exists():
|
|
102
|
+
try:
|
|
103
|
+
with open(self.config_file) as f:
|
|
104
|
+
loaded = yaml.safe_load(f)
|
|
105
|
+
config = loaded if isinstance(loaded, dict) else {}
|
|
106
|
+
github_config = config.get("github", {})
|
|
107
|
+
sync_settings = github_config.get("sync_settings", {})
|
|
108
|
+
|
|
109
|
+
# Check if auto-detection is disabled
|
|
110
|
+
if not sync_settings.get("auto_detect_from_git", True):
|
|
111
|
+
return None, None
|
|
112
|
+
|
|
113
|
+
# If owner/repo already set, don't override
|
|
114
|
+
if github_config.get("repository"):
|
|
115
|
+
return None, None
|
|
116
|
+
except Exception as e:
|
|
117
|
+
logger.debug("config_read_failed", error=str(e))
|
|
118
|
+
|
|
119
|
+
# Try to auto-detect from git remote
|
|
120
|
+
owner, repo = get_github_from_git_remote(self.core.root_path)
|
|
121
|
+
|
|
122
|
+
if owner and repo:
|
|
123
|
+
try:
|
|
124
|
+
github_repo = f"{owner}/{repo}"
|
|
125
|
+
logger.info(
|
|
126
|
+
"github_auto_detected",
|
|
127
|
+
owner=owner,
|
|
128
|
+
repo=repo,
|
|
129
|
+
repository=github_repo,
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
# Update config with detected values
|
|
133
|
+
if self.config_file.exists():
|
|
134
|
+
with open(self.config_file) as f:
|
|
135
|
+
loaded = yaml.safe_load(f)
|
|
136
|
+
config = loaded if isinstance(loaded, dict) else {}
|
|
137
|
+
else:
|
|
138
|
+
config = {}
|
|
139
|
+
|
|
140
|
+
if "github" not in config:
|
|
141
|
+
config["github"] = {}
|
|
142
|
+
|
|
143
|
+
config["github"]["repository"] = github_repo
|
|
144
|
+
config["github"]["enabled"] = True
|
|
145
|
+
|
|
146
|
+
with open(self.config_file, "w") as f:
|
|
147
|
+
yaml.dump(config, f, default_flow_style=False, sort_keys=False)
|
|
148
|
+
|
|
149
|
+
return owner, repo
|
|
150
|
+
|
|
151
|
+
except Exception as e:
|
|
152
|
+
logger.debug("github_auto_config_failed", error=str(e))
|
|
153
|
+
|
|
154
|
+
return None, None
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"""GitHub token resolution and management utilities."""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
|
|
5
|
+
import click
|
|
6
|
+
from structlog import get_logger
|
|
7
|
+
|
|
8
|
+
from roadmap.common.console import get_console
|
|
9
|
+
|
|
10
|
+
console = get_console()
|
|
11
|
+
logger = get_logger()
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class GitHubTokenResolver:
|
|
15
|
+
"""Resolves GitHub tokens from multiple sources."""
|
|
16
|
+
|
|
17
|
+
def __init__(self, cred_manager=None): # type: ignore
|
|
18
|
+
"""Initialize GitHubTokenResolver.
|
|
19
|
+
|
|
20
|
+
Args:
|
|
21
|
+
cred_manager: Optional credential manager instance.
|
|
22
|
+
"""
|
|
23
|
+
self.cred_manager = cred_manager
|
|
24
|
+
|
|
25
|
+
def get_existing_token(self) -> str | None:
|
|
26
|
+
"""Get existing stored token."""
|
|
27
|
+
if not self.cred_manager:
|
|
28
|
+
return None
|
|
29
|
+
try:
|
|
30
|
+
return self.cred_manager.get_token()
|
|
31
|
+
except Exception as e:
|
|
32
|
+
logger.debug("stored_token_retrieval_failed", error=str(e))
|
|
33
|
+
return None
|
|
34
|
+
|
|
35
|
+
def resolve_token(
|
|
36
|
+
self,
|
|
37
|
+
cli_token: str | None,
|
|
38
|
+
interactive: bool,
|
|
39
|
+
yes: bool,
|
|
40
|
+
existing_token: str | None,
|
|
41
|
+
) -> tuple[str | None, bool]:
|
|
42
|
+
"""Resolve which token to use.
|
|
43
|
+
|
|
44
|
+
Returns:
|
|
45
|
+
Tuple of (token, should_continue)
|
|
46
|
+
"""
|
|
47
|
+
# Priority: CLI arg > environment > stored > prompt
|
|
48
|
+
env_token = os.environ.get("ROADMAP_GITHUB_TOKEN")
|
|
49
|
+
|
|
50
|
+
if cli_token:
|
|
51
|
+
return cli_token, True
|
|
52
|
+
|
|
53
|
+
if env_token:
|
|
54
|
+
console.print(
|
|
55
|
+
"ℹ️ Using GitHub token from environment variable ROADMAP_GITHUB_TOKEN",
|
|
56
|
+
style="dim",
|
|
57
|
+
)
|
|
58
|
+
return env_token, True
|
|
59
|
+
|
|
60
|
+
if existing_token:
|
|
61
|
+
if interactive and not yes:
|
|
62
|
+
console.print("🔍 Found existing GitHub credentials")
|
|
63
|
+
if click.confirm("Use existing GitHub credentials?"):
|
|
64
|
+
console.print("✅ Using existing GitHub credentials")
|
|
65
|
+
return existing_token, True
|
|
66
|
+
else:
|
|
67
|
+
return existing_token, True
|
|
68
|
+
|
|
69
|
+
# Need to get token from user
|
|
70
|
+
if interactive and not yes:
|
|
71
|
+
console.print(
|
|
72
|
+
"To integrate with GitHub you'll need a personal access token with 'repo' scope."
|
|
73
|
+
)
|
|
74
|
+
console.print("→ Create one: https://github.com/settings/tokens")
|
|
75
|
+
token = click.prompt("Paste your GitHub token", hide_input=True)
|
|
76
|
+
return token, True
|
|
77
|
+
|
|
78
|
+
# Non-interactive without token
|
|
79
|
+
console.print(
|
|
80
|
+
"❌ Non-interactive mode requires providing a token via --github-token "
|
|
81
|
+
"or setting ROADMAP_GITHUB_TOKEN, or use --skip-github to skip integration.",
|
|
82
|
+
style="bold red",
|
|
83
|
+
)
|
|
84
|
+
return None, False
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
"""Console utilities for CLI operations.
|
|
2
|
+
|
|
3
|
+
Provides centralized console instances configured for the current environment:
|
|
4
|
+
- get_console() → Rich console for successful output (stdout)
|
|
5
|
+
- get_console_stderr() → Console for errors/warnings (stderr)
|
|
6
|
+
- is_plain_mode() → Auto-detect plain text mode for POSIX compliance
|
|
7
|
+
|
|
8
|
+
Plain mode is auto-detected based on:
|
|
9
|
+
- Output is not a terminal (piped/redirected)
|
|
10
|
+
- ROADMAP_OUTPUT=plain environment variable
|
|
11
|
+
- NO_COLOR=1 environment variable
|
|
12
|
+
- Running in CI/CD environment
|
|
13
|
+
|
|
14
|
+
This separation ensures:
|
|
15
|
+
- Success output to stdout (can be piped, has colors)
|
|
16
|
+
- Errors to stderr (never interferes with data)
|
|
17
|
+
- POSIX compliance (no ANSI codes when piped)
|
|
18
|
+
- Machine-readable output (can parse stdout, ignore stderr)
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
import os
|
|
22
|
+
import sys
|
|
23
|
+
|
|
24
|
+
from rich.console import Console
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def is_plain_mode() -> bool:
|
|
28
|
+
"""Detect if we should use plain text output (no ANSI codes).
|
|
29
|
+
|
|
30
|
+
Returns True if any of:
|
|
31
|
+
- Output is redirected/piped (not a terminal)
|
|
32
|
+
- ROADMAP_OUTPUT=plain environment variable set
|
|
33
|
+
- NO_COLOR=1 for POSIX compliance
|
|
34
|
+
- Running in CI/CD environment
|
|
35
|
+
- In testing environment
|
|
36
|
+
|
|
37
|
+
Returns:
|
|
38
|
+
bool: True if plain mode should be used
|
|
39
|
+
"""
|
|
40
|
+
return any(
|
|
41
|
+
[
|
|
42
|
+
# Explicit plain mode request
|
|
43
|
+
os.environ.get("ROADMAP_OUTPUT") == "plain",
|
|
44
|
+
# POSIX NO_COLOR standard
|
|
45
|
+
os.environ.get("NO_COLOR") in ("1", "true", "True", "TRUE"),
|
|
46
|
+
# User forced no colors
|
|
47
|
+
os.environ.get("FORCE_COLOR") == "0",
|
|
48
|
+
# Output is piped/redirected (not interactive)
|
|
49
|
+
not sys.stdout.isatty(),
|
|
50
|
+
not sys.stderr.isatty(),
|
|
51
|
+
# CI/CD environments
|
|
52
|
+
any(
|
|
53
|
+
ci_var in os.environ
|
|
54
|
+
for ci_var in [
|
|
55
|
+
"CI",
|
|
56
|
+
"CONTINUOUS_INTEGRATION",
|
|
57
|
+
"GITHUB_ACTIONS",
|
|
58
|
+
"TRAVIS",
|
|
59
|
+
"CIRCLECI",
|
|
60
|
+
"JENKINS_URL",
|
|
61
|
+
"GITLAB_CI",
|
|
62
|
+
]
|
|
63
|
+
),
|
|
64
|
+
# Testing environment
|
|
65
|
+
any(
|
|
66
|
+
test_var in os.environ
|
|
67
|
+
for test_var in [
|
|
68
|
+
"PYTEST_CURRENT_TEST",
|
|
69
|
+
"_PYTEST_RAISE",
|
|
70
|
+
"UNITTEST_MODE",
|
|
71
|
+
]
|
|
72
|
+
),
|
|
73
|
+
]
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def is_testing_environment() -> bool:
|
|
78
|
+
"""Detect if we're running in a testing environment.
|
|
79
|
+
|
|
80
|
+
Returns True if any of the following conditions are met:
|
|
81
|
+
- pytest is running
|
|
82
|
+
- NO_COLOR environment variable is set
|
|
83
|
+
- TERM is set to 'dumb'
|
|
84
|
+
- Output is not a terminal
|
|
85
|
+
- Running under CI/CD
|
|
86
|
+
"""
|
|
87
|
+
return any(
|
|
88
|
+
[
|
|
89
|
+
# Pytest detection
|
|
90
|
+
"PYTEST_CURRENT_TEST" in os.environ,
|
|
91
|
+
"pytest" in sys.modules,
|
|
92
|
+
hasattr(sys, "_called_from_test"),
|
|
93
|
+
# Explicit color disabling
|
|
94
|
+
os.environ.get("NO_COLOR") in ("1", "true", "True", "TRUE"),
|
|
95
|
+
os.environ.get("FORCE_COLOR") == "0",
|
|
96
|
+
# Terminal detection
|
|
97
|
+
os.environ.get("TERM") in ("dumb", ""),
|
|
98
|
+
not sys.stdout.isatty(),
|
|
99
|
+
not sys.stderr.isatty(),
|
|
100
|
+
# CI/CD environments
|
|
101
|
+
any(
|
|
102
|
+
ci_var in os.environ
|
|
103
|
+
for ci_var in [
|
|
104
|
+
"CI",
|
|
105
|
+
"CONTINUOUS_INTEGRATION",
|
|
106
|
+
"GITHUB_ACTIONS",
|
|
107
|
+
"TRAVIS",
|
|
108
|
+
"CIRCLECI",
|
|
109
|
+
"JENKINS_URL",
|
|
110
|
+
"GITLAB_CI",
|
|
111
|
+
]
|
|
112
|
+
),
|
|
113
|
+
# Test frameworks
|
|
114
|
+
any(
|
|
115
|
+
test_var in os.environ
|
|
116
|
+
for test_var in [
|
|
117
|
+
"PYTEST_CURRENT_TEST",
|
|
118
|
+
"_PYTEST_RAISE",
|
|
119
|
+
"UNITTEST_MODE",
|
|
120
|
+
]
|
|
121
|
+
),
|
|
122
|
+
]
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def get_console() -> Console:
|
|
127
|
+
"""Get a console instance configured for successful output (stdout).
|
|
128
|
+
|
|
129
|
+
Returns a console configured for:
|
|
130
|
+
- Rich output when in interactive terminal (colors, tables, styles)
|
|
131
|
+
- Plain text output when piped/testing (POSIX compliance)
|
|
132
|
+
- No ANSI codes when plain mode is detected
|
|
133
|
+
|
|
134
|
+
Returns a fresh instance each time to ensure file handle is current.
|
|
135
|
+
|
|
136
|
+
Returns:
|
|
137
|
+
Console: Configured Rich Console instance
|
|
138
|
+
"""
|
|
139
|
+
plain = is_plain_mode()
|
|
140
|
+
|
|
141
|
+
# Use fresh instance each time to ensure file handle is correct
|
|
142
|
+
# This is critical for testing with CliRunner which replaces sys.stdout
|
|
143
|
+
if plain:
|
|
144
|
+
return Console(
|
|
145
|
+
file=sys.stdout,
|
|
146
|
+
force_terminal=False,
|
|
147
|
+
no_color=True,
|
|
148
|
+
width=80,
|
|
149
|
+
legacy_windows=False,
|
|
150
|
+
force_interactive=False,
|
|
151
|
+
force_jupyter=False,
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
# Interactive mode: full Rich features
|
|
155
|
+
return Console(file=sys.stdout)
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def get_console_stderr() -> Console:
|
|
159
|
+
"""Get a console instance configured for error output (stderr).
|
|
160
|
+
|
|
161
|
+
Returns a console that outputs to stderr for:
|
|
162
|
+
- Error messages
|
|
163
|
+
- Warnings
|
|
164
|
+
- Diagnostic information
|
|
165
|
+
|
|
166
|
+
This ensures errors don't interfere with stdout data.
|
|
167
|
+
|
|
168
|
+
Returns:
|
|
169
|
+
Console: Console instance writing to stderr
|
|
170
|
+
"""
|
|
171
|
+
plain = is_plain_mode()
|
|
172
|
+
|
|
173
|
+
# In testing/plain mode: no terminal, no colors
|
|
174
|
+
if plain:
|
|
175
|
+
return Console(
|
|
176
|
+
file=sys.stderr,
|
|
177
|
+
force_terminal=False,
|
|
178
|
+
no_color=True,
|
|
179
|
+
width=80,
|
|
180
|
+
legacy_windows=False,
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
# Interactive mode: use stderr with colors
|
|
184
|
+
return Console(file=sys.stderr)
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"""Application-wide constants and enums."""
|
|
2
|
+
|
|
3
|
+
from enum import StrEnum
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Priority(StrEnum):
|
|
7
|
+
"""Issue priority levels."""
|
|
8
|
+
|
|
9
|
+
CRITICAL = "critical"
|
|
10
|
+
HIGH = "high"
|
|
11
|
+
MEDIUM = "medium"
|
|
12
|
+
LOW = "low"
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class Status(StrEnum):
|
|
16
|
+
"""Issue status values."""
|
|
17
|
+
|
|
18
|
+
TODO = "todo"
|
|
19
|
+
IN_PROGRESS = "in-progress"
|
|
20
|
+
BLOCKED = "blocked"
|
|
21
|
+
REVIEW = "review"
|
|
22
|
+
CLOSED = "closed"
|
|
23
|
+
ARCHIVED = "archived" # Soft-deleted (duplicate or obsolete)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class MilestoneStatus(StrEnum):
|
|
27
|
+
"""Milestone status values."""
|
|
28
|
+
|
|
29
|
+
OPEN = "open"
|
|
30
|
+
CLOSED = "closed"
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class ProjectStatus(StrEnum):
|
|
34
|
+
"""Project status values."""
|
|
35
|
+
|
|
36
|
+
PLANNING = "planning"
|
|
37
|
+
ACTIVE = "active"
|
|
38
|
+
ON_HOLD = "on-hold"
|
|
39
|
+
COMPLETED = "completed"
|
|
40
|
+
CANCELLED = "cancelled"
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class RiskLevel(StrEnum):
|
|
44
|
+
"""Risk level values for projects and milestones."""
|
|
45
|
+
|
|
46
|
+
LOW = "low"
|
|
47
|
+
MEDIUM = "medium"
|
|
48
|
+
HIGH = "high"
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class IssueType(StrEnum):
|
|
52
|
+
"""Issue type categories."""
|
|
53
|
+
|
|
54
|
+
FEATURE = "feature"
|
|
55
|
+
BUG = "bug"
|
|
56
|
+
OTHER = "other"
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class SyncBackend(StrEnum):
|
|
60
|
+
"""Sync backend types."""
|
|
61
|
+
|
|
62
|
+
GITHUB = "github"
|
|
63
|
+
GIT = "git"
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
# Application Configuration Defaults
|
|
67
|
+
# ============================================================================
|
|
68
|
+
|
|
69
|
+
# File and path defaults
|
|
70
|
+
DEFAULT_ROADMAP_FILE = "ROADMAP.md"
|
|
71
|
+
DEFAULT_CONFIG_FILE = ".roadmaprc"
|
|
72
|
+
DEFAULT_DATA_DIR = ".roadmap"
|
|
73
|
+
DEFAULT_CACHE_FILE = ".roadmap_cache.json"
|
|
74
|
+
|
|
75
|
+
# GitHub API defaults
|
|
76
|
+
GITHUB_API_BASE = "https://api.github.com"
|
|
77
|
+
GITHUB_GRAPHQL_ENDPOINT = "https://api.github.com/graphql"
|
|
78
|
+
GITHUB_API_TIMEOUT = 30 # seconds
|
|
79
|
+
GITHUB_RATE_LIMIT_THRESHOLD = 10 # remaining requests before warning
|
|
80
|
+
|
|
81
|
+
# Display defaults
|
|
82
|
+
DEFAULT_TABLE_WIDTH = 80
|
|
83
|
+
DEFAULT_MAX_ITEMS_DISPLAY = 20
|
|
84
|
+
DEFAULT_DATE_FORMAT = "%Y-%m-%d"
|
|
85
|
+
DEFAULT_DATETIME_FORMAT = "%Y-%m-%d %H:%M:%S"
|
|
86
|
+
|
|
87
|
+
# Caching defaults
|
|
88
|
+
CACHE_TTL_DEFAULT = 3600 # 1 hour in seconds
|
|
89
|
+
CACHE_TTL_LONG = 86400 # 24 hours in seconds
|
|
90
|
+
CACHE_TTL_SHORT = 300 # 5 minutes in seconds
|
|
91
|
+
|
|
92
|
+
# Batch operation defaults
|
|
93
|
+
DEFAULT_BATCH_SIZE = 50
|
|
94
|
+
DEFAULT_MAX_RETRIES = 3
|
|
95
|
+
DEFAULT_RETRY_DELAY = 1 # seconds
|
|
96
|
+
DEFAULT_BACKOFF_FACTOR = 2
|
|
97
|
+
|
|
98
|
+
# Progress tracking defaults
|
|
99
|
+
PROGRESS_REFRESH_INTERVAL = 0.1 # seconds
|
|
100
|
+
PROGRESS_BAR_LENGTH = 30
|
|
101
|
+
|
|
102
|
+
# Logging defaults
|
|
103
|
+
LOG_LEVEL_DEFAULT = "INFO"
|
|
104
|
+
LOG_FORMAT_DEFAULT = "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
|
|
105
|
+
|
|
106
|
+
# Error handling defaults
|
|
107
|
+
ERROR_MESSAGE_MAX_LENGTH = 500
|
|
108
|
+
VALIDATION_ERROR_MAX_FIELDS = 10
|
|
109
|
+
|
|
110
|
+
# Authentication defaults
|
|
111
|
+
AUTH_TOKEN_ENV_VAR = "GITHUB_TOKEN"
|
|
112
|
+
AUTH_TIMEOUT = 30 # seconds
|
|
113
|
+
|
|
114
|
+
# Git defaults
|
|
115
|
+
GIT_TIMEOUT = 60 # seconds
|
|
116
|
+
GIT_MAX_OUTPUT_LINES = 1000
|
|
117
|
+
GIT_COMMIT_MESSAGE_MAX_LENGTH = 72
|
|
118
|
+
|
|
119
|
+
# Project analysis defaults
|
|
120
|
+
ANALYSIS_MIN_SAMPLE_SIZE = 5
|
|
121
|
+
ANALYSIS_MAX_HISTORICAL_DAYS = 365
|
|
122
|
+
ANALYSIS_TREND_WINDOW = 7 # days
|
|
123
|
+
|
|
124
|
+
# Performance defaults
|
|
125
|
+
PERFORMANCE_ENABLE_CACHE = True
|
|
126
|
+
PERFORMANCE_ENABLE_ASYNC = True
|
|
127
|
+
PERFORMANCE_THREAD_POOL_SIZE = 4
|
|
128
|
+
PERFORMANCE_CONNECTION_POOL_SIZE = 10
|
|
129
|
+
|
|
130
|
+
# Validation defaults
|
|
131
|
+
VALIDATION_TITLE_MIN_LENGTH = 1
|
|
132
|
+
VALIDATION_TITLE_MAX_LENGTH = 500
|
|
133
|
+
VALIDATION_DESCRIPTION_MAX_LENGTH = 5000
|
|
134
|
+
VALIDATION_NAME_PATTERN = r"^[a-zA-Z0-9_-]+$"
|