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,146 @@
|
|
|
1
|
+
"""Service for detecting project context from git and file system."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
import re
|
|
5
|
+
import subprocess
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
import structlog
|
|
9
|
+
|
|
10
|
+
logger = structlog.get_logger()
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class ProjectContextDetectionService:
|
|
14
|
+
"""Service for detecting project context from git and file system."""
|
|
15
|
+
|
|
16
|
+
@staticmethod
|
|
17
|
+
def detect_project_context() -> dict:
|
|
18
|
+
"""Detect project context from git repository and directory structure.
|
|
19
|
+
|
|
20
|
+
Returns:
|
|
21
|
+
Dictionary with detected context:
|
|
22
|
+
- git_repo: Repository in owner/repo format if detected
|
|
23
|
+
- project_name: Project name from git, package files, or directory
|
|
24
|
+
- git_user: Git user name if available
|
|
25
|
+
- has_git: Whether in a git repository
|
|
26
|
+
"""
|
|
27
|
+
context = {
|
|
28
|
+
"git_repo": None,
|
|
29
|
+
"project_name": None,
|
|
30
|
+
"git_user": None,
|
|
31
|
+
"has_git": False,
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
try:
|
|
35
|
+
# Check if we're in a git repository
|
|
36
|
+
git_check = subprocess.run(
|
|
37
|
+
["git", "rev-parse", "--is-inside-work-tree"],
|
|
38
|
+
capture_output=True,
|
|
39
|
+
text=True,
|
|
40
|
+
timeout=5,
|
|
41
|
+
)
|
|
42
|
+
context["has_git"] = git_check.returncode == 0
|
|
43
|
+
|
|
44
|
+
if context["has_git"]:
|
|
45
|
+
ProjectContextDetectionService._detect_git_repo(context)
|
|
46
|
+
ProjectContextDetectionService._detect_git_user(context)
|
|
47
|
+
|
|
48
|
+
except (
|
|
49
|
+
subprocess.TimeoutExpired,
|
|
50
|
+
subprocess.CalledProcessError,
|
|
51
|
+
FileNotFoundError,
|
|
52
|
+
):
|
|
53
|
+
pass
|
|
54
|
+
|
|
55
|
+
# Fallback to directory name if no git repo detected
|
|
56
|
+
if not context["project_name"]:
|
|
57
|
+
context["project_name"] = Path.cwd().name
|
|
58
|
+
|
|
59
|
+
# Try to detect from package files
|
|
60
|
+
if not context["project_name"] or context["project_name"] == ".":
|
|
61
|
+
ProjectContextDetectionService._detect_from_package_files(context)
|
|
62
|
+
|
|
63
|
+
return context
|
|
64
|
+
|
|
65
|
+
@staticmethod
|
|
66
|
+
def _detect_git_repo(context: dict) -> None:
|
|
67
|
+
"""Detect git repository and populate context."""
|
|
68
|
+
try:
|
|
69
|
+
result = subprocess.run(
|
|
70
|
+
["git", "remote", "get-url", "origin"],
|
|
71
|
+
capture_output=True,
|
|
72
|
+
text=True,
|
|
73
|
+
timeout=5,
|
|
74
|
+
)
|
|
75
|
+
if result.returncode == 0:
|
|
76
|
+
origin_url = result.stdout.strip()
|
|
77
|
+
# Parse GitHub repository from URL
|
|
78
|
+
if "github.com" in origin_url:
|
|
79
|
+
# Handle both SSH and HTTPS URLs
|
|
80
|
+
if origin_url.startswith("git@github.com:"):
|
|
81
|
+
repo_part = origin_url.replace("git@github.com:", "").replace(
|
|
82
|
+
".git", ""
|
|
83
|
+
)
|
|
84
|
+
elif "github.com/" in origin_url:
|
|
85
|
+
repo_part = origin_url.split("github.com/")[1].replace(
|
|
86
|
+
".git", ""
|
|
87
|
+
)
|
|
88
|
+
else:
|
|
89
|
+
repo_part = None
|
|
90
|
+
|
|
91
|
+
if repo_part and "/" in repo_part:
|
|
92
|
+
context["git_repo"] = repo_part
|
|
93
|
+
context["project_name"] = repo_part.split("/")[1]
|
|
94
|
+
except Exception as e:
|
|
95
|
+
logger.debug(
|
|
96
|
+
"git_context_detection_failed",
|
|
97
|
+
operation="detect_git_context",
|
|
98
|
+
error=str(e),
|
|
99
|
+
action="Continuing with partial context",
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
@staticmethod
|
|
103
|
+
def _detect_git_user(context: dict) -> None:
|
|
104
|
+
"""Detect git user name and populate context."""
|
|
105
|
+
try:
|
|
106
|
+
user_result = subprocess.run(
|
|
107
|
+
["git", "config", "user.name"],
|
|
108
|
+
capture_output=True,
|
|
109
|
+
text=True,
|
|
110
|
+
timeout=5,
|
|
111
|
+
)
|
|
112
|
+
if user_result.returncode == 0:
|
|
113
|
+
context["git_user"] = user_result.stdout.strip()
|
|
114
|
+
except Exception as e:
|
|
115
|
+
logger.debug(
|
|
116
|
+
"git_user_detection_failed",
|
|
117
|
+
operation="detect_git_user",
|
|
118
|
+
error=str(e),
|
|
119
|
+
action="Skipping git user detection",
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
@staticmethod
|
|
123
|
+
def _detect_from_package_files(context: dict) -> None:
|
|
124
|
+
"""Try to detect project name from package files."""
|
|
125
|
+
for config_file in ["pyproject.toml", "package.json", "Cargo.toml"]:
|
|
126
|
+
if Path(config_file).exists():
|
|
127
|
+
try:
|
|
128
|
+
content = Path(config_file).read_text()
|
|
129
|
+
if config_file == "pyproject.toml":
|
|
130
|
+
match = re.search(r'name\s*=\s*["\']([^"\']+)["\']', content)
|
|
131
|
+
if match:
|
|
132
|
+
context["project_name"] = match.group(1)
|
|
133
|
+
break
|
|
134
|
+
elif config_file == "package.json":
|
|
135
|
+
data = json.loads(content)
|
|
136
|
+
if "name" in data:
|
|
137
|
+
context["project_name"] = data["name"]
|
|
138
|
+
break
|
|
139
|
+
except Exception as e:
|
|
140
|
+
logger.debug(
|
|
141
|
+
"package_file_parse_failed",
|
|
142
|
+
operation="parse_package_file",
|
|
143
|
+
file=config_file,
|
|
144
|
+
error=str(e),
|
|
145
|
+
action="Trying next config file",
|
|
146
|
+
)
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"""Service for creating projects."""
|
|
2
|
+
|
|
3
|
+
import uuid
|
|
4
|
+
|
|
5
|
+
from roadmap.common.logging import get_logger
|
|
6
|
+
from roadmap.core.services.project_init.template import ProjectTemplateService
|
|
7
|
+
from roadmap.infrastructure.coordination.core import RoadmapCore
|
|
8
|
+
|
|
9
|
+
logger = get_logger(__name__)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class ProjectCreationService:
|
|
13
|
+
"""Service for creating projects."""
|
|
14
|
+
|
|
15
|
+
@staticmethod
|
|
16
|
+
def create_project(
|
|
17
|
+
core: RoadmapCore,
|
|
18
|
+
project_name: str,
|
|
19
|
+
description: str,
|
|
20
|
+
detected_info: dict,
|
|
21
|
+
template: str,
|
|
22
|
+
template_path: str | None = None,
|
|
23
|
+
) -> dict | None:
|
|
24
|
+
"""Create a new project with given parameters.
|
|
25
|
+
|
|
26
|
+
Args:
|
|
27
|
+
core: RoadmapCore instance
|
|
28
|
+
project_name: Name of the project
|
|
29
|
+
description: Project description
|
|
30
|
+
detected_info: Detected project context
|
|
31
|
+
template: Template type to use
|
|
32
|
+
template_path: Optional path to custom template
|
|
33
|
+
|
|
34
|
+
Returns:
|
|
35
|
+
Dictionary with project info (id, name, filename) or None if failed
|
|
36
|
+
"""
|
|
37
|
+
try:
|
|
38
|
+
# Generate or load project content
|
|
39
|
+
if template_path:
|
|
40
|
+
project_content = ProjectTemplateService.load_custom_template(
|
|
41
|
+
template_path
|
|
42
|
+
)
|
|
43
|
+
if not project_content:
|
|
44
|
+
project_content = ProjectTemplateService.generate_project_template(
|
|
45
|
+
project_name, description, template, detected_info
|
|
46
|
+
)
|
|
47
|
+
else:
|
|
48
|
+
project_content = ProjectTemplateService.generate_project_template(
|
|
49
|
+
project_name, description, template, detected_info
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
# Save project file
|
|
53
|
+
project_id = str(uuid.uuid4())[:8]
|
|
54
|
+
project_filename = (
|
|
55
|
+
f"{project_id}-{project_name.lower().replace(' ', '-')}.md"
|
|
56
|
+
)
|
|
57
|
+
project_file = core.roadmap_dir / "projects" / project_filename
|
|
58
|
+
|
|
59
|
+
# Ensure projects directory exists
|
|
60
|
+
(core.roadmap_dir / "projects").mkdir(parents=True, exist_ok=True)
|
|
61
|
+
|
|
62
|
+
project_file.write_text(project_content)
|
|
63
|
+
|
|
64
|
+
return {
|
|
65
|
+
"id": project_id,
|
|
66
|
+
"name": project_name,
|
|
67
|
+
"filename": project_filename,
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
except Exception as e:
|
|
71
|
+
logger.error(
|
|
72
|
+
"project_creation_failed",
|
|
73
|
+
error=str(e),
|
|
74
|
+
severity="system_error",
|
|
75
|
+
)
|
|
76
|
+
return None
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"""Service for detecting and analyzing existing projects."""
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
import structlog
|
|
6
|
+
|
|
7
|
+
from roadmap.infrastructure.persistence_gateway import PersistenceGateway
|
|
8
|
+
|
|
9
|
+
logger = structlog.get_logger()
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class ProjectDetectionService:
|
|
13
|
+
"""Service for detecting and analyzing existing projects."""
|
|
14
|
+
|
|
15
|
+
@staticmethod
|
|
16
|
+
def detect_existing_projects(projects_dir: Path) -> list[dict]:
|
|
17
|
+
"""Detect existing projects in the projects directory.
|
|
18
|
+
|
|
19
|
+
Args:
|
|
20
|
+
projects_dir: Path to the projects directory
|
|
21
|
+
|
|
22
|
+
Returns:
|
|
23
|
+
List of dicts with 'name', 'id', and 'file' for each existing project
|
|
24
|
+
"""
|
|
25
|
+
existing_projects = []
|
|
26
|
+
|
|
27
|
+
if not projects_dir.exists():
|
|
28
|
+
return existing_projects
|
|
29
|
+
|
|
30
|
+
for project_file in projects_dir.glob("*.md"):
|
|
31
|
+
try:
|
|
32
|
+
project = PersistenceGateway.parse_project_file(project_file)
|
|
33
|
+
existing_projects.append(
|
|
34
|
+
{
|
|
35
|
+
"name": project.name,
|
|
36
|
+
"id": project.id,
|
|
37
|
+
"file": project_file.name,
|
|
38
|
+
}
|
|
39
|
+
)
|
|
40
|
+
except Exception as e:
|
|
41
|
+
logger.debug(
|
|
42
|
+
"project_parse_failed",
|
|
43
|
+
operation="parse_project",
|
|
44
|
+
file=project_file.name,
|
|
45
|
+
error=str(e),
|
|
46
|
+
action="Skipping project",
|
|
47
|
+
)
|
|
48
|
+
# Skip projects that can't be parsed
|
|
49
|
+
continue
|
|
50
|
+
|
|
51
|
+
return existing_projects
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
"""Service for generating project templates."""
|
|
2
|
+
|
|
3
|
+
import getpass
|
|
4
|
+
from datetime import UTC, datetime
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
import structlog
|
|
8
|
+
|
|
9
|
+
logger = structlog.get_logger()
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class ProjectTemplateService:
|
|
13
|
+
"""Service for generating project templates."""
|
|
14
|
+
|
|
15
|
+
# Template snippets for different types
|
|
16
|
+
SOFTWARE_TEMPLATE = """
|
|
17
|
+
- [ ] Develop core functionality
|
|
18
|
+
- [ ] Implement user interface
|
|
19
|
+
- [ ] Write comprehensive tests
|
|
20
|
+
- [ ] Deploy to production
|
|
21
|
+
- [ ] Document API and usage
|
|
22
|
+
|
|
23
|
+
## Technical Stack
|
|
24
|
+
|
|
25
|
+
- **Language**: Python
|
|
26
|
+
- **Framework**: TBD
|
|
27
|
+
- **Database**: TBD
|
|
28
|
+
- **Deployment**: TBD
|
|
29
|
+
|
|
30
|
+
## Development Phases
|
|
31
|
+
|
|
32
|
+
### Phase 1: Foundation
|
|
33
|
+
- Project setup and architecture
|
|
34
|
+
- Core functionality implementation
|
|
35
|
+
- Basic testing framework
|
|
36
|
+
|
|
37
|
+
### Phase 2: Features
|
|
38
|
+
- Feature development
|
|
39
|
+
- User interface implementation
|
|
40
|
+
- Integration testing
|
|
41
|
+
|
|
42
|
+
### Phase 3: Polish
|
|
43
|
+
- Performance optimization
|
|
44
|
+
- Documentation
|
|
45
|
+
- Production deployment
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
RESEARCH_TEMPLATE = """
|
|
49
|
+
- [ ] Literature review
|
|
50
|
+
- [ ] Hypothesis formation
|
|
51
|
+
- [ ] Methodology design
|
|
52
|
+
- [ ] Data collection
|
|
53
|
+
- [ ] Analysis and findings
|
|
54
|
+
- [ ] Publication preparation
|
|
55
|
+
|
|
56
|
+
## Research Questions
|
|
57
|
+
|
|
58
|
+
1. [Primary research question]
|
|
59
|
+
2. [Secondary research questions]
|
|
60
|
+
|
|
61
|
+
## Methodology
|
|
62
|
+
|
|
63
|
+
[Research methodology and approach]
|
|
64
|
+
|
|
65
|
+
## Timeline
|
|
66
|
+
|
|
67
|
+
- **Phase 1**: Literature review (4 weeks)
|
|
68
|
+
- **Phase 2**: Data collection (8 weeks)
|
|
69
|
+
- **Phase 3**: Analysis (4 weeks)
|
|
70
|
+
- **Phase 4**: Writing (4 weeks)
|
|
71
|
+
"""
|
|
72
|
+
|
|
73
|
+
TEAM_TEMPLATE = """
|
|
74
|
+
- [ ] Team onboarding
|
|
75
|
+
- [ ] Process documentation
|
|
76
|
+
- [ ] Workflow optimization
|
|
77
|
+
- [ ] Knowledge sharing
|
|
78
|
+
- [ ] Regular retrospectives
|
|
79
|
+
|
|
80
|
+
## Team Structure
|
|
81
|
+
|
|
82
|
+
- **Project Lead**: [Name]
|
|
83
|
+
- **Development Team**: [Names]
|
|
84
|
+
- **Stakeholders**: [Names]
|
|
85
|
+
|
|
86
|
+
## Communication
|
|
87
|
+
|
|
88
|
+
- **Daily Standups**: [Time/Location]
|
|
89
|
+
- **Sprint Planning**: [Schedule]
|
|
90
|
+
- **Retrospectives**: [Schedule]
|
|
91
|
+
|
|
92
|
+
## Processes
|
|
93
|
+
|
|
94
|
+
### Development Workflow
|
|
95
|
+
1. Issue creation and planning
|
|
96
|
+
2. Feature branch development
|
|
97
|
+
3. Code review process
|
|
98
|
+
4. Testing and validation
|
|
99
|
+
5. Deployment and monitoring
|
|
100
|
+
"""
|
|
101
|
+
|
|
102
|
+
BASIC_TEMPLATE = """
|
|
103
|
+
- [ ] Define project scope
|
|
104
|
+
- [ ] Create initial roadmap
|
|
105
|
+
- [ ] Begin implementation
|
|
106
|
+
- [ ] Regular progress reviews
|
|
107
|
+
- [ ] Project completion
|
|
108
|
+
|
|
109
|
+
## Milestones
|
|
110
|
+
|
|
111
|
+
### Milestone 1: Setup
|
|
112
|
+
- Initial project structure
|
|
113
|
+
- Team alignment on goals
|
|
114
|
+
|
|
115
|
+
### Milestone 2: Development
|
|
116
|
+
- Core functionality implementation
|
|
117
|
+
- Regular progress tracking
|
|
118
|
+
|
|
119
|
+
### Milestone 3: Completion
|
|
120
|
+
- Final deliverables
|
|
121
|
+
- Project retrospective
|
|
122
|
+
"""
|
|
123
|
+
|
|
124
|
+
TEMPLATE_FOOTER = """
|
|
125
|
+
|
|
126
|
+
## Resources
|
|
127
|
+
|
|
128
|
+
- [Link to documentation]
|
|
129
|
+
- [Link to repository]
|
|
130
|
+
- [Link to project tools]
|
|
131
|
+
|
|
132
|
+
## Notes
|
|
133
|
+
|
|
134
|
+
[Additional project notes and context]
|
|
135
|
+
"""
|
|
136
|
+
|
|
137
|
+
@staticmethod
|
|
138
|
+
def generate_project_template(
|
|
139
|
+
project_name: str, description: str, template: str, detected_info: dict
|
|
140
|
+
) -> str:
|
|
141
|
+
"""Generate project content based on template.
|
|
142
|
+
|
|
143
|
+
Args:
|
|
144
|
+
project_name: Name of the project
|
|
145
|
+
description: Project description
|
|
146
|
+
template: Template type (basic, software, research, team)
|
|
147
|
+
detected_info: Detected project context
|
|
148
|
+
|
|
149
|
+
Returns:
|
|
150
|
+
Project content as markdown string
|
|
151
|
+
"""
|
|
152
|
+
current_date = datetime.now(UTC).isoformat()
|
|
153
|
+
owner = detected_info.get("git_user", getpass.getuser())
|
|
154
|
+
|
|
155
|
+
# Base project content
|
|
156
|
+
content = f"""---
|
|
157
|
+
name: {project_name}
|
|
158
|
+
description: {description}
|
|
159
|
+
owner: {owner}
|
|
160
|
+
priority: high
|
|
161
|
+
status: active
|
|
162
|
+
created: {current_date}
|
|
163
|
+
updated: {current_date}
|
|
164
|
+
"""
|
|
165
|
+
|
|
166
|
+
if detected_info.get("git_repo"):
|
|
167
|
+
content += f"github_repo: {detected_info['git_repo']}\n"
|
|
168
|
+
|
|
169
|
+
content += (
|
|
170
|
+
"""timeline:
|
|
171
|
+
start_date: """
|
|
172
|
+
+ current_date
|
|
173
|
+
+ """
|
|
174
|
+
target_end_date: null
|
|
175
|
+
tags: []
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
# """
|
|
179
|
+
+ project_name
|
|
180
|
+
+ """
|
|
181
|
+
|
|
182
|
+
## Overview
|
|
183
|
+
|
|
184
|
+
"""
|
|
185
|
+
+ description
|
|
186
|
+
+ """
|
|
187
|
+
|
|
188
|
+
## Project Goals
|
|
189
|
+
|
|
190
|
+
"""
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
# Template-specific content
|
|
194
|
+
if template == "software":
|
|
195
|
+
content += ProjectTemplateService.SOFTWARE_TEMPLATE
|
|
196
|
+
elif template == "research":
|
|
197
|
+
content += ProjectTemplateService.RESEARCH_TEMPLATE
|
|
198
|
+
elif template == "team":
|
|
199
|
+
content += ProjectTemplateService.TEAM_TEMPLATE
|
|
200
|
+
else: # basic
|
|
201
|
+
content += ProjectTemplateService.BASIC_TEMPLATE
|
|
202
|
+
|
|
203
|
+
content += ProjectTemplateService.TEMPLATE_FOOTER
|
|
204
|
+
return content
|
|
205
|
+
|
|
206
|
+
@staticmethod
|
|
207
|
+
def load_custom_template(template_path: str) -> str | None:
|
|
208
|
+
"""Load custom template from file.
|
|
209
|
+
|
|
210
|
+
Args:
|
|
211
|
+
template_path: Path to template file
|
|
212
|
+
|
|
213
|
+
Returns:
|
|
214
|
+
Template content if valid, None otherwise
|
|
215
|
+
"""
|
|
216
|
+
try:
|
|
217
|
+
tpl_path = Path(template_path)
|
|
218
|
+
if tpl_path.exists() and tpl_path.is_file():
|
|
219
|
+
return tpl_path.read_text()
|
|
220
|
+
except Exception as e:
|
|
221
|
+
logger.debug(
|
|
222
|
+
"template_load_failed",
|
|
223
|
+
operation="load_template",
|
|
224
|
+
template_path=str(template_path),
|
|
225
|
+
error=str(e),
|
|
226
|
+
action="Returning None",
|
|
227
|
+
)
|
|
228
|
+
return None
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"""Status change parsing and extraction service for sync operations.
|
|
2
|
+
|
|
3
|
+
This service provides utilities for parsing and extracting information from
|
|
4
|
+
status change strings in the format "old_status -> new_status".
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import Any
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def parse_status_change(change_str: str) -> str | None:
|
|
11
|
+
"""Parse and validate change string in format 'old -> new'.
|
|
12
|
+
|
|
13
|
+
Args:
|
|
14
|
+
change_str: Change string in format "old -> new"
|
|
15
|
+
|
|
16
|
+
Returns:
|
|
17
|
+
The new status string (stripped), or None if format is invalid
|
|
18
|
+
"""
|
|
19
|
+
if not isinstance(change_str, str) or " -> " not in change_str:
|
|
20
|
+
return None
|
|
21
|
+
|
|
22
|
+
try:
|
|
23
|
+
parts = change_str.split(" -> ")
|
|
24
|
+
if len(parts) != 2:
|
|
25
|
+
return None
|
|
26
|
+
return parts[1].strip()
|
|
27
|
+
except (IndexError, AttributeError):
|
|
28
|
+
return None
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def extract_issue_status_update(
|
|
32
|
+
status_change: str,
|
|
33
|
+
) -> dict[str, Any] | None:
|
|
34
|
+
"""Extract and validate issue status update from change string.
|
|
35
|
+
|
|
36
|
+
Args:
|
|
37
|
+
status_change: Change string in format "old -> new"
|
|
38
|
+
|
|
39
|
+
Returns:
|
|
40
|
+
Dict with 'github_state' and 'status_enum', or None if invalid
|
|
41
|
+
"""
|
|
42
|
+
from roadmap.common.constants import Status
|
|
43
|
+
|
|
44
|
+
new_status = parse_status_change(status_change)
|
|
45
|
+
if new_status is None:
|
|
46
|
+
return None
|
|
47
|
+
|
|
48
|
+
try:
|
|
49
|
+
# Validate that it's a valid status
|
|
50
|
+
status_enum = Status(new_status)
|
|
51
|
+
# Map local status to GitHub state (closed -> closed, others -> open)
|
|
52
|
+
github_state = "closed" if new_status == Status.CLOSED.value else "open"
|
|
53
|
+
return {
|
|
54
|
+
"github_state": github_state,
|
|
55
|
+
"status_enum": status_enum,
|
|
56
|
+
}
|
|
57
|
+
except (ValueError, KeyError):
|
|
58
|
+
# Invalid status - skip the update
|
|
59
|
+
return None
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def extract_milestone_status_update(
|
|
63
|
+
status_change: str,
|
|
64
|
+
) -> dict[str, Any] | None:
|
|
65
|
+
"""Extract and validate milestone status update from change string.
|
|
66
|
+
|
|
67
|
+
Args:
|
|
68
|
+
status_change: Change string in format "old -> new"
|
|
69
|
+
|
|
70
|
+
Returns:
|
|
71
|
+
Dict with 'github_state' and 'status_enum', or None if invalid
|
|
72
|
+
"""
|
|
73
|
+
from roadmap.common.constants import MilestoneStatus
|
|
74
|
+
|
|
75
|
+
new_status = parse_status_change(status_change)
|
|
76
|
+
if new_status is None:
|
|
77
|
+
return None
|
|
78
|
+
|
|
79
|
+
github_state = "closed" if new_status == "closed" else "open"
|
|
80
|
+
|
|
81
|
+
try:
|
|
82
|
+
status_enum = MilestoneStatus(new_status)
|
|
83
|
+
return {
|
|
84
|
+
"github_state": github_state,
|
|
85
|
+
"status_enum": status_enum,
|
|
86
|
+
}
|
|
87
|
+
except (ValueError, KeyError):
|
|
88
|
+
return None
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Package initialization file."""
|