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,379 @@
|
|
|
1
|
+
"""Progress calculation engine for automatic milestone and project updates.
|
|
2
|
+
|
|
3
|
+
This module provides the core functionality to automatically calculate and update
|
|
4
|
+
progress for milestones and projects based on issue completion, implementing
|
|
5
|
+
the requirements from issue 515a927c.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from datetime import UTC, datetime, timedelta
|
|
9
|
+
from typing import Any
|
|
10
|
+
|
|
11
|
+
from structlog import get_logger
|
|
12
|
+
|
|
13
|
+
from roadmap.common.constants import MilestoneStatus, RiskLevel
|
|
14
|
+
from roadmap.core.domain import Issue, Milestone, Project
|
|
15
|
+
|
|
16
|
+
logger = get_logger()
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class ProgressCalculationEngine:
|
|
20
|
+
"""Engine for calculating and updating milestone and project progress."""
|
|
21
|
+
|
|
22
|
+
def __init__(self, method: str = "effort_weighted"):
|
|
23
|
+
"""Initialize the progress calculation engine.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
method: Calculation method - 'effort_weighted' or 'count_based'
|
|
27
|
+
"""
|
|
28
|
+
self.method = method
|
|
29
|
+
|
|
30
|
+
def update_milestone_progress(
|
|
31
|
+
self, milestone: Milestone, all_issues: list[Issue]
|
|
32
|
+
) -> bool:
|
|
33
|
+
"""Update milestone progress and status based on assigned issues.
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
milestone: The milestone to update
|
|
37
|
+
all_issues: List of all issues in the system
|
|
38
|
+
|
|
39
|
+
Returns:
|
|
40
|
+
True if the milestone was updated, False otherwise
|
|
41
|
+
"""
|
|
42
|
+
old_progress = milestone.calculated_progress
|
|
43
|
+
old_status = milestone.status
|
|
44
|
+
|
|
45
|
+
# Update automatic fields
|
|
46
|
+
milestone.update_automatic_fields(all_issues, self.method)
|
|
47
|
+
|
|
48
|
+
# Check if anything changed
|
|
49
|
+
progress_changed = old_progress != milestone.calculated_progress
|
|
50
|
+
status_changed = old_status != milestone.status
|
|
51
|
+
|
|
52
|
+
if progress_changed or status_changed:
|
|
53
|
+
old_progress_str = (
|
|
54
|
+
f"{old_progress:.1f}" if old_progress is not None else "None"
|
|
55
|
+
)
|
|
56
|
+
new_progress_str = (
|
|
57
|
+
f"{milestone.calculated_progress:.1f}"
|
|
58
|
+
if milestone.calculated_progress is not None
|
|
59
|
+
else "None"
|
|
60
|
+
)
|
|
61
|
+
logger.info(
|
|
62
|
+
"milestone_progress_updated",
|
|
63
|
+
milestone_name=milestone.name,
|
|
64
|
+
old_progress=old_progress_str,
|
|
65
|
+
new_progress=new_progress_str,
|
|
66
|
+
old_status=old_status,
|
|
67
|
+
new_status=milestone.status,
|
|
68
|
+
)
|
|
69
|
+
return True
|
|
70
|
+
|
|
71
|
+
return False
|
|
72
|
+
|
|
73
|
+
def update_project_progress(
|
|
74
|
+
self, project: Project, all_milestones: list[Milestone], all_issues: list[Issue]
|
|
75
|
+
) -> bool:
|
|
76
|
+
"""Update project progress and status based on assigned milestones.
|
|
77
|
+
|
|
78
|
+
Args:
|
|
79
|
+
project: The project to update
|
|
80
|
+
all_milestones: List of all milestones in the system
|
|
81
|
+
all_issues: List of all issues in the system
|
|
82
|
+
|
|
83
|
+
Returns:
|
|
84
|
+
True if the project was updated, False otherwise
|
|
85
|
+
"""
|
|
86
|
+
old_progress = project.calculated_progress
|
|
87
|
+
old_status = project.status
|
|
88
|
+
|
|
89
|
+
# Update automatic fields
|
|
90
|
+
project.update_automatic_fields(all_milestones, all_issues)
|
|
91
|
+
|
|
92
|
+
# Calculate additional timeline intelligence
|
|
93
|
+
self._update_project_timeline(project, all_milestones, all_issues)
|
|
94
|
+
|
|
95
|
+
# Check if anything changed
|
|
96
|
+
progress_changed = old_progress != project.calculated_progress
|
|
97
|
+
status_changed = old_status != project.status
|
|
98
|
+
|
|
99
|
+
if progress_changed or status_changed:
|
|
100
|
+
old_progress_str = (
|
|
101
|
+
f"{old_progress:.1f}" if old_progress is not None else "None"
|
|
102
|
+
)
|
|
103
|
+
new_progress_str = (
|
|
104
|
+
f"{project.calculated_progress:.1f}"
|
|
105
|
+
if project.calculated_progress is not None
|
|
106
|
+
else "None"
|
|
107
|
+
)
|
|
108
|
+
logger.info(
|
|
109
|
+
"project_progress_updated",
|
|
110
|
+
project_name=project.name,
|
|
111
|
+
old_progress=old_progress_str,
|
|
112
|
+
new_progress=new_progress_str,
|
|
113
|
+
old_status=old_status,
|
|
114
|
+
new_status=project.status,
|
|
115
|
+
)
|
|
116
|
+
return True
|
|
117
|
+
|
|
118
|
+
return False
|
|
119
|
+
|
|
120
|
+
def update_issue_dependencies(
|
|
121
|
+
self,
|
|
122
|
+
updated_issue: Issue,
|
|
123
|
+
all_issues: list[Issue],
|
|
124
|
+
all_milestones: list[Milestone],
|
|
125
|
+
all_projects: list[Project],
|
|
126
|
+
) -> tuple[list[Milestone], list[Project]]:
|
|
127
|
+
"""Update all dependencies when an issue changes.
|
|
128
|
+
|
|
129
|
+
Args:
|
|
130
|
+
updated_issue: The issue that was updated
|
|
131
|
+
all_issues: List of all issues in the system
|
|
132
|
+
all_milestones: List of all milestones in the system
|
|
133
|
+
all_projects: List of all projects in the system
|
|
134
|
+
|
|
135
|
+
Returns:
|
|
136
|
+
Tuple of (updated_milestones, updated_projects)
|
|
137
|
+
"""
|
|
138
|
+
updated_milestones = []
|
|
139
|
+
updated_projects = []
|
|
140
|
+
|
|
141
|
+
# Find milestone affected by this issue
|
|
142
|
+
if updated_issue.milestone:
|
|
143
|
+
for milestone in all_milestones:
|
|
144
|
+
if milestone.name == updated_issue.milestone:
|
|
145
|
+
if self.update_milestone_progress(milestone, all_issues):
|
|
146
|
+
updated_milestones.append(milestone)
|
|
147
|
+
|
|
148
|
+
# Find projects affected by this milestone
|
|
149
|
+
for project in all_projects:
|
|
150
|
+
if milestone.name in project.milestones:
|
|
151
|
+
if self.update_project_progress(
|
|
152
|
+
project, all_milestones, all_issues
|
|
153
|
+
):
|
|
154
|
+
updated_projects.append(project)
|
|
155
|
+
|
|
156
|
+
return updated_milestones, updated_projects
|
|
157
|
+
|
|
158
|
+
def recalculate_all_progress(
|
|
159
|
+
self,
|
|
160
|
+
all_issues: list[Issue],
|
|
161
|
+
all_milestones: list[Milestone],
|
|
162
|
+
all_projects: list[Project],
|
|
163
|
+
) -> dict[str, int]:
|
|
164
|
+
"""Recalculate progress for all milestones and projects.
|
|
165
|
+
|
|
166
|
+
Args:
|
|
167
|
+
all_issues: List of all issues in the system
|
|
168
|
+
all_milestones: List of all milestones in the system
|
|
169
|
+
all_projects: List of all projects in the system
|
|
170
|
+
|
|
171
|
+
Returns:
|
|
172
|
+
Dictionary with counts of updated items
|
|
173
|
+
"""
|
|
174
|
+
updated_milestones = 0
|
|
175
|
+
updated_projects = 0
|
|
176
|
+
|
|
177
|
+
# Update all milestones
|
|
178
|
+
for milestone in all_milestones:
|
|
179
|
+
if self.update_milestone_progress(milestone, all_issues):
|
|
180
|
+
updated_milestones += 1
|
|
181
|
+
|
|
182
|
+
# Update all projects
|
|
183
|
+
for project in all_projects:
|
|
184
|
+
if self.update_project_progress(project, all_milestones, all_issues):
|
|
185
|
+
updated_projects += 1
|
|
186
|
+
|
|
187
|
+
logger.info(
|
|
188
|
+
"progress_recalculated",
|
|
189
|
+
updated_milestones=updated_milestones,
|
|
190
|
+
updated_projects=updated_projects,
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
return {"milestones": updated_milestones, "projects": updated_projects}
|
|
194
|
+
|
|
195
|
+
def _update_project_timeline(
|
|
196
|
+
self, project: Project, all_milestones: list[Milestone], all_issues: list[Issue]
|
|
197
|
+
) -> None:
|
|
198
|
+
"""Update project timeline projections and risk assessment.
|
|
199
|
+
|
|
200
|
+
Args:
|
|
201
|
+
project: The project to update
|
|
202
|
+
all_milestones: List of all milestones
|
|
203
|
+
all_issues: List of all issues
|
|
204
|
+
"""
|
|
205
|
+
project_milestones = project.get_milestones(all_milestones)
|
|
206
|
+
|
|
207
|
+
if not project_milestones:
|
|
208
|
+
return
|
|
209
|
+
|
|
210
|
+
# Calculate completion velocity
|
|
211
|
+
velocity = self._calculate_completion_velocity(project_milestones, all_issues)
|
|
212
|
+
if velocity is not None:
|
|
213
|
+
project.completion_velocity = velocity
|
|
214
|
+
|
|
215
|
+
# Calculate projected completion date
|
|
216
|
+
projected_date = self._calculate_projected_completion(
|
|
217
|
+
project, project_milestones, all_issues
|
|
218
|
+
)
|
|
219
|
+
if projected_date:
|
|
220
|
+
project.projected_end_date = projected_date
|
|
221
|
+
|
|
222
|
+
# Calculate schedule variance
|
|
223
|
+
if project.target_end_date:
|
|
224
|
+
variance_days = (projected_date - project.target_end_date).days
|
|
225
|
+
project.schedule_variance = variance_days
|
|
226
|
+
|
|
227
|
+
# Update risk level based on schedule variance
|
|
228
|
+
if variance_days > 14: # More than 2 weeks behind
|
|
229
|
+
project.risk_level = RiskLevel.HIGH
|
|
230
|
+
elif variance_days > 7: # More than 1 week behind
|
|
231
|
+
project.risk_level = RiskLevel.MEDIUM
|
|
232
|
+
elif variance_days < -7: # More than 1 week ahead
|
|
233
|
+
project.risk_level = RiskLevel.LOW
|
|
234
|
+
else:
|
|
235
|
+
project.risk_level = RiskLevel.LOW
|
|
236
|
+
|
|
237
|
+
def _calculate_completion_velocity(
|
|
238
|
+
self,
|
|
239
|
+
milestones: list[Milestone],
|
|
240
|
+
all_issues: list[Issue],
|
|
241
|
+
window_weeks: int = 4,
|
|
242
|
+
) -> float | None:
|
|
243
|
+
"""Calculate completion velocity based on recent milestone completions.
|
|
244
|
+
|
|
245
|
+
Args:
|
|
246
|
+
milestones: Project milestones
|
|
247
|
+
all_issues: List of all issues
|
|
248
|
+
window_weeks: Time window for velocity calculation
|
|
249
|
+
|
|
250
|
+
Returns:
|
|
251
|
+
Milestones completed per week, or None if insufficient data
|
|
252
|
+
"""
|
|
253
|
+
cutoff_date = datetime.now(UTC) - timedelta(weeks=window_weeks)
|
|
254
|
+
|
|
255
|
+
# Count milestones completed in the time window
|
|
256
|
+
completed_in_window = 0
|
|
257
|
+
for milestone in milestones:
|
|
258
|
+
if (
|
|
259
|
+
milestone.actual_end_date
|
|
260
|
+
and milestone.actual_end_date >= cutoff_date
|
|
261
|
+
and milestone.status == MilestoneStatus.CLOSED
|
|
262
|
+
):
|
|
263
|
+
completed_in_window += 1
|
|
264
|
+
|
|
265
|
+
if completed_in_window == 0:
|
|
266
|
+
return None
|
|
267
|
+
|
|
268
|
+
return completed_in_window / window_weeks
|
|
269
|
+
|
|
270
|
+
def _calculate_projected_completion(
|
|
271
|
+
self, project: Project, milestones: list[Milestone], all_issues: list[Issue]
|
|
272
|
+
) -> datetime | None:
|
|
273
|
+
"""Calculate projected completion date based on velocity and remaining work.
|
|
274
|
+
|
|
275
|
+
Args:
|
|
276
|
+
project: The project
|
|
277
|
+
milestones: Project milestones
|
|
278
|
+
all_issues: List of all issues
|
|
279
|
+
|
|
280
|
+
Returns:
|
|
281
|
+
Projected completion date, or None if cannot calculate
|
|
282
|
+
"""
|
|
283
|
+
if not project.completion_velocity:
|
|
284
|
+
return None
|
|
285
|
+
|
|
286
|
+
# Count incomplete milestones
|
|
287
|
+
incomplete_milestones = [
|
|
288
|
+
m for m in milestones if m.status != MilestoneStatus.CLOSED
|
|
289
|
+
]
|
|
290
|
+
|
|
291
|
+
if not incomplete_milestones:
|
|
292
|
+
# All milestones complete
|
|
293
|
+
return datetime.now(UTC)
|
|
294
|
+
|
|
295
|
+
# Calculate weeks needed to complete remaining milestones
|
|
296
|
+
weeks_needed = len(incomplete_milestones) / project.completion_velocity
|
|
297
|
+
|
|
298
|
+
return datetime.now(UTC) + timedelta(weeks=weeks_needed)
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
class ProgressEventSystem:
|
|
302
|
+
"""Event system for tracking progress updates and triggering cascading updates."""
|
|
303
|
+
|
|
304
|
+
def __init__(self, engine: ProgressCalculationEngine):
|
|
305
|
+
"""Initialize the event system.
|
|
306
|
+
|
|
307
|
+
Args:
|
|
308
|
+
engine: The progress calculation engine
|
|
309
|
+
"""
|
|
310
|
+
self.engine = engine
|
|
311
|
+
self.listeners = []
|
|
312
|
+
|
|
313
|
+
def register_listener(self, callback):
|
|
314
|
+
"""Register a callback for progress update events.
|
|
315
|
+
|
|
316
|
+
Args:
|
|
317
|
+
callback: Function to call when progress updates occur
|
|
318
|
+
"""
|
|
319
|
+
self.listeners.append(callback)
|
|
320
|
+
|
|
321
|
+
def on_issue_updated(
|
|
322
|
+
self,
|
|
323
|
+
updated_issue: Issue,
|
|
324
|
+
changes: dict[str, Any],
|
|
325
|
+
all_issues: list[Issue],
|
|
326
|
+
all_milestones: list[Milestone],
|
|
327
|
+
all_projects: list[Project],
|
|
328
|
+
) -> dict[str, Any]:
|
|
329
|
+
"""Handle issue update events and trigger cascading updates.
|
|
330
|
+
|
|
331
|
+
Args:
|
|
332
|
+
updated_issue: The updated issue
|
|
333
|
+
changes: Dictionary of changed fields
|
|
334
|
+
all_issues: List of all issues
|
|
335
|
+
all_milestones: List of all milestones
|
|
336
|
+
all_projects: List of all projects
|
|
337
|
+
|
|
338
|
+
Returns:
|
|
339
|
+
Dictionary with update results
|
|
340
|
+
"""
|
|
341
|
+
# Check if this change affects progress
|
|
342
|
+
progress_affecting_changes = [
|
|
343
|
+
"status",
|
|
344
|
+
"progress_percentage",
|
|
345
|
+
"milestone",
|
|
346
|
+
"estimated_hours",
|
|
347
|
+
]
|
|
348
|
+
|
|
349
|
+
if not any(field in changes for field in progress_affecting_changes):
|
|
350
|
+
return {"milestones_updated": [], "projects_updated": []}
|
|
351
|
+
|
|
352
|
+
# Update dependent milestones and projects
|
|
353
|
+
updated_milestones, updated_projects = self.engine.update_issue_dependencies(
|
|
354
|
+
updated_issue, all_issues, all_milestones, all_projects
|
|
355
|
+
)
|
|
356
|
+
|
|
357
|
+
# Notify listeners
|
|
358
|
+
for listener in self.listeners:
|
|
359
|
+
try:
|
|
360
|
+
listener(
|
|
361
|
+
{
|
|
362
|
+
"event": "issue_updated",
|
|
363
|
+
"issue": updated_issue,
|
|
364
|
+
"changes": changes,
|
|
365
|
+
"updated_milestones": updated_milestones,
|
|
366
|
+
"updated_projects": updated_projects,
|
|
367
|
+
}
|
|
368
|
+
)
|
|
369
|
+
except Exception as e:
|
|
370
|
+
logger.error(
|
|
371
|
+
"progress_event_listener_error",
|
|
372
|
+
error=str(e),
|
|
373
|
+
severity="system_error",
|
|
374
|
+
)
|
|
375
|
+
|
|
376
|
+
return {
|
|
377
|
+
"milestones_updated": updated_milestones,
|
|
378
|
+
"projects_updated": updated_projects,
|
|
379
|
+
}
|