icdev 1.0.0__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.
- icdev/__init__.py +18 -0
- icdev/_paths.py +85 -0
- icdev/_version.py +3 -0
- icdev/data/__init__.py +1 -0
- icdev/data/args/__init__.py +1 -0
- icdev/data/args/agent_authority.yaml +61 -0
- icdev/data/args/agent_config.yaml +355 -0
- icdev/data/args/agentic_fitness.yaml +31 -0
- icdev/data/args/ai_governance_config.yaml +137 -0
- icdev/data/args/atlas_critique_config.yaml +66 -0
- icdev/data/args/bedrock_models.yaml +63 -0
- icdev/data/args/cicd_config.yaml +82 -0
- icdev/data/args/classification_config.yaml +232 -0
- icdev/data/args/cli_config.yaml +154 -0
- icdev/data/args/cloud_config.yaml +63 -0
- icdev/data/args/code_pattern_config.yaml +151 -0
- icdev/data/args/code_quality_config.yaml +47 -0
- icdev/data/args/companion_registry.yaml +202 -0
- icdev/data/args/context_config.yaml +82 -0
- icdev/data/args/csp_monitor_config.yaml +268 -0
- icdev/data/args/cui_markings.yaml +35 -0
- icdev/data/args/db_config.yaml +40 -0
- icdev/data/args/deployment_profiles.yaml +248 -0
- icdev/data/args/dev_profile_config.yaml +144 -0
- icdev/data/args/devsecops_config.yaml +286 -0
- icdev/data/args/endpoint_security_config.yaml +137 -0
- icdev/data/args/extension_config.yaml +79 -0
- icdev/data/args/file_access_tiers.yaml +88 -0
- icdev/data/args/framework_registry.yaml +415 -0
- icdev/data/args/innovation_config.yaml +431 -0
- icdev/data/args/installation_manifest.yaml +1087 -0
- icdev/data/args/llm_config.yaml +495 -0
- icdev/data/args/maintenance_config.yaml +55 -0
- icdev/data/args/memory_config.yaml +83 -0
- icdev/data/args/monitoring_config.yaml +127 -0
- icdev/data/args/mosa_config.yaml +190 -0
- icdev/data/args/nlq_config.yaml +35 -0
- icdev/data/args/observability_config.yaml +39 -0
- icdev/data/args/observability_tracing_config.yaml +170 -0
- icdev/data/args/oscal_tools_config.yaml +43 -0
- icdev/data/args/owasp_agentic_config.yaml +171 -0
- icdev/data/args/phase_registry.yaml +618 -0
- icdev/data/args/project_defaults.yaml +235 -0
- icdev/data/args/prompt_chains.yaml +163 -0
- icdev/data/args/resilience_config.yaml +50 -0
- icdev/data/args/ricoas_config.yaml +191 -0
- icdev/data/args/role_personas.yaml +362 -0
- icdev/data/args/scaling_config.yaml +176 -0
- icdev/data/args/security_gates.yaml +685 -0
- icdev/data/args/skill_injection_config.yaml +322 -0
- icdev/data/args/spec_config.yaml +53 -0
- icdev/data/args/supply_chain_config.yaml +76 -0
- icdev/data/args/translation_config.yaml +228 -0
- icdev/data/args/workflow_templates/ato_acceleration.yaml +54 -0
- icdev/data/args/workflow_templates/build_deploy.yaml +63 -0
- icdev/data/args/workflow_templates/full_compliance.yaml +43 -0
- icdev/data/args/workflow_templates/security_hardening.yaml +55 -0
- icdev/data/args/worktree_config.yaml +34 -0
- icdev/data/args/zta_config.yaml +247 -0
- icdev/data/context/__init__.py +1 -0
- icdev/data/context/agent/__init__.py +1 -0
- icdev/data/context/agent/response_schemas/__init__.py +1 -0
- icdev/data/context/agent/response_schemas/debate_position.json +46 -0
- icdev/data/context/agent/response_schemas/fitness_scorecard.json +74 -0
- icdev/data/context/agent/response_schemas/review_decision.json +39 -0
- icdev/data/context/agent/response_schemas/task_decomposition.json +82 -0
- icdev/data/context/agent/response_schemas/veto_decision.json +40 -0
- icdev/data/context/agentic/__init__.py +1 -0
- icdev/data/context/agentic/architecture_patterns.md +269 -0
- icdev/data/context/agentic/capability_registry.yaml +202 -0
- icdev/data/context/agentic/csp_mcp_registry.yaml +280 -0
- icdev/data/context/agentic/fitness_rubric.md +56 -0
- icdev/data/context/agentic/governance_baseline.md +205 -0
- icdev/data/context/ci/__init__.py +1 -0
- icdev/data/context/ci/worktree_templates.json +44 -0
- icdev/data/context/cloud/__init__.py +1 -0
- icdev/data/context/cloud/csp_service_registry.json +739 -0
- icdev/data/context/compliance/__init__.py +1 -0
- icdev/data/context/compliance/atlas_mitigations.json +293 -0
- icdev/data/context/compliance/atlas_techniques.json +833 -0
- icdev/data/context/compliance/cisa_sbd_requirements.json +432 -0
- icdev/data/context/compliance/cjis_security_policy.json +522 -0
- icdev/data/context/compliance/cmmc_practices.json +2494 -0
- icdev/data/context/compliance/cmmc_report_template.md +142 -0
- icdev/data/context/compliance/cnssi_1253_overlay.json +109 -0
- icdev/data/context/compliance/control_crosswalk.json +1914 -0
- icdev/data/context/compliance/control_families/__init__.py +1 -0
- icdev/data/context/compliance/csp_certifications.json +251 -0
- icdev/data/context/compliance/cssp_report_template.md +193 -0
- icdev/data/context/compliance/cui_templates/__init__.py +1 -0
- icdev/data/context/compliance/cui_templates/banner_block.txt +4 -0
- icdev/data/context/compliance/cui_templates/code_header.txt +8 -0
- icdev/data/context/compliance/cui_templates/document_template.md +35 -0
- icdev/data/context/compliance/data_type_framework_map.json +321 -0
- icdev/data/context/compliance/data_type_registry.json +147 -0
- icdev/data/context/compliance/dod_cssp_8530.json +463 -0
- icdev/data/context/compliance/eu_ai_act_annex_iii.json +108 -0
- icdev/data/context/compliance/export_templates/__init__.py +1 -0
- icdev/data/context/compliance/export_templates/emass_controls.csv.j2 +4 -0
- icdev/data/context/compliance/export_templates/evidence_package.md.j2 +39 -0
- icdev/data/context/compliance/export_templates/executive_summary.md.j2 +55 -0
- icdev/data/context/compliance/export_templates/poam_tracking.csv.j2 +4 -0
- icdev/data/context/compliance/fedramp_20x_ksi_schemas.json +133 -0
- icdev/data/context/compliance/fedramp_high_baseline.json +4370 -0
- icdev/data/context/compliance/fedramp_moderate_baseline.json +2183 -0
- icdev/data/context/compliance/fedramp_report_template.md +181 -0
- icdev/data/context/compliance/fips_200_areas.json +362 -0
- icdev/data/context/compliance/gao_ai_accountability.json +262 -0
- icdev/data/context/compliance/hipaa_security_rule.json +720 -0
- icdev/data/context/compliance/hitrust_csf_v11.json +930 -0
- icdev/data/context/compliance/impact_level_profiles.json +251 -0
- icdev/data/context/compliance/incident_response_template.md +1110 -0
- icdev/data/context/compliance/iso27001_2022_controls.json +750 -0
- icdev/data/context/compliance/iso27001_nist_bridge.json +382 -0
- icdev/data/context/compliance/iso42001_controls.json +254 -0
- icdev/data/context/compliance/ivv_checklist_template.md +80 -0
- icdev/data/context/compliance/ivv_report_template.md +116 -0
- icdev/data/context/compliance/ivv_requirements.json +372 -0
- icdev/data/context/compliance/mosa_crosswalk.json +327 -0
- icdev/data/context/compliance/mosa_framework.json +250 -0
- icdev/data/context/compliance/narrative_templates/AC.md.j2 +101 -0
- icdev/data/context/compliance/narrative_templates/AU.md.j2 +106 -0
- icdev/data/context/compliance/narrative_templates/IA.md.j2 +104 -0
- icdev/data/context/compliance/narrative_templates/SC.md.j2 +102 -0
- icdev/data/context/compliance/narrative_templates/SI.md.j2 +111 -0
- icdev/data/context/compliance/narrative_templates/__init__.py +1 -0
- icdev/data/context/compliance/narrative_templates/default.md.j2 +50 -0
- icdev/data/context/compliance/narrative_templates/executive_summary.j2 +27 -0
- icdev/data/context/compliance/narrative_templates/poam_milestone.j2 +19 -0
- icdev/data/context/compliance/narrative_templates/ssp_section.j2 +11 -0
- icdev/data/context/compliance/nist_800_171_controls.json +1552 -0
- icdev/data/context/compliance/nist_800_207_crosswalk.json +399 -0
- icdev/data/context/compliance/nist_800_207_zta.json +258 -0
- icdev/data/context/compliance/nist_800_53.json +324 -0
- icdev/data/context/compliance/nist_ai_600_1_genai.json +326 -0
- icdev/data/context/compliance/nist_ai_rmf.json +206 -0
- icdev/data/context/compliance/nist_sp_800_60_types.json +1667 -0
- icdev/data/context/compliance/omb_m25_21_high_impact_ai.json +248 -0
- icdev/data/context/compliance/omb_m26_04_unbiased_ai.json +262 -0
- icdev/data/context/compliance/owasp_agentic_asi.json +133 -0
- icdev/data/context/compliance/owasp_agentic_threats.json +285 -0
- icdev/data/context/compliance/owasp_llm_top10.json +274 -0
- icdev/data/context/compliance/pci_dss_v4.json +510 -0
- icdev/data/context/compliance/poam_template.md +117 -0
- icdev/data/context/compliance/safeai_controls.json +512 -0
- icdev/data/context/compliance/sbd_report_template.md +77 -0
- icdev/data/context/compliance/siem_config_templates/__init__.py +1 -0
- icdev/data/context/compliance/siem_config_templates/filebeat.yml +213 -0
- icdev/data/context/compliance/siem_config_templates/log_sources.json +208 -0
- icdev/data/context/compliance/soc2_trust_criteria.json +661 -0
- icdev/data/context/compliance/ssp_template.md +432 -0
- icdev/data/context/compliance/stig_templates/__init__.py +1 -0
- icdev/data/context/compliance/stig_templates/webapp_stig.json +139 -0
- icdev/data/context/compliance/xai_requirements.json +108 -0
- icdev/data/context/dashboard/__init__.py +1 -0
- icdev/data/context/dashboard/nlq_examples.json +50 -0
- icdev/data/context/dashboard/schema_descriptions.json +23 -0
- icdev/data/context/integration/__init__.py +1 -0
- icdev/data/context/integration/approval_workflows.json +32 -0
- icdev/data/context/integration/gitlab_field_mappings.json +33 -0
- icdev/data/context/integration/jira_field_mappings.json +32 -0
- icdev/data/context/integration/reqif_export_schema.json +23 -0
- icdev/data/context/integration/servicenow_field_mappings.json +22 -0
- icdev/data/context/languages/__init__.py +1 -0
- icdev/data/context/languages/framework_patterns.json +205 -0
- icdev/data/context/languages/language_registry.json +279 -0
- icdev/data/context/llm/__init__.py +1 -0
- icdev/data/context/llm/example_provider.py +86 -0
- icdev/data/context/mbse/__init__.py +1 -0
- icdev/data/context/mbse/des_report_template.md +162 -0
- icdev/data/context/mbse/des_requirements.json +411 -0
- icdev/data/context/mbse/digital_thread_patterns.json +403 -0
- icdev/data/context/mbse/reqif_schema.json +280 -0
- icdev/data/context/mbse/sysml_element_types.json +432 -0
- icdev/data/context/modernization/__init__.py +1 -0
- icdev/data/context/modernization/db_type_mappings.json +148 -0
- icdev/data/context/modernization/decomposition_patterns.json +284 -0
- icdev/data/context/modernization/framework_migration_patterns.json +359 -0
- icdev/data/context/modernization/migration_report_template.md +168 -0
- icdev/data/context/modernization/seven_rs_catalog.json +369 -0
- icdev/data/context/modernization/version_upgrade_rules.json +279 -0
- icdev/data/context/oscal/NIST_SP-800-53_rev5_catalog.json +254987 -0
- icdev/data/context/oscal/README.md +43 -0
- icdev/data/context/patterns/__init__.py +1 -0
- icdev/data/context/profiles/__init__.py +1 -0
- icdev/data/context/profiles/dod_baseline_v1.yaml +145 -0
- icdev/data/context/profiles/fedramp_baseline_v1.yaml +143 -0
- icdev/data/context/profiles/financial_baseline_v1.yaml +142 -0
- icdev/data/context/profiles/healthcare_baseline_v1.yaml +135 -0
- icdev/data/context/profiles/law_enforcement_v1.yaml +129 -0
- icdev/data/context/profiles/startup_v1.yaml +134 -0
- icdev/data/context/requirements/__init__.py +1 -0
- icdev/data/context/requirements/ambiguity_patterns.json +97 -0
- icdev/data/context/requirements/boundary_impact_rules.json +123 -0
- icdev/data/context/requirements/default_constitutions.json +67 -0
- icdev/data/context/requirements/document_extraction_rules.json +58 -0
- icdev/data/context/requirements/gap_patterns.json +108 -0
- icdev/data/context/requirements/readiness_rubric.json +78 -0
- icdev/data/context/requirements/red_alternative_patterns.json +210 -0
- icdev/data/context/requirements/safe_templates.json +72 -0
- icdev/data/context/requirements/spec_quality_checklist.json +122 -0
- icdev/data/context/simulation/__init__.py +1 -0
- icdev/data/context/simulation/architecture_patterns.json +36 -0
- icdev/data/context/simulation/coa_templates.json +38 -0
- icdev/data/context/simulation/cost_models.json +23 -0
- icdev/data/context/simulation/risk_categories.json +46 -0
- icdev/data/context/supply_chain/__init__.py +1 -0
- icdev/data/context/supply_chain/isa_templates.json +129 -0
- icdev/data/context/supply_chain/nist_800_161_controls.json +247 -0
- icdev/data/context/supply_chain/scrm_risk_matrix.json +147 -0
- icdev/data/context/templates/__init__.py +1 -0
- icdev/data/context/templates/ansible/__init__.py +1 -0
- icdev/data/context/templates/ansible/playbooks/__init__.py +1 -0
- icdev/data/context/templates/ansible/roles/__init__.py +1 -0
- icdev/data/context/templates/gitlab_ci/__init__.py +1 -0
- icdev/data/context/templates/grafana/__init__.py +1 -0
- icdev/data/context/templates/kubernetes/__init__.py +1 -0
- icdev/data/context/templates/project/__init__.py +1 -0
- icdev/data/context/templates/project/api/__init__.py +1 -0
- icdev/data/context/templates/project/cli/__init__.py +1 -0
- icdev/data/context/templates/project/data_pipeline/__init__.py +1 -0
- icdev/data/context/templates/project/iac/__init__.py +1 -0
- icdev/data/context/templates/project/javascript_frontend/__init__.py +1 -0
- icdev/data/context/templates/project/javascript_frontend/src/__init__.py +1 -0
- icdev/data/context/templates/project/javascript_frontend/tests/__init__.py +1 -0
- icdev/data/context/templates/project/microservice/__init__.py +1 -0
- icdev/data/context/templates/project/python_backend/__init__.py +1 -0
- icdev/data/context/templates/project/python_backend/src/__init__.py +1 -0
- icdev/data/context/templates/project/python_backend/tests/__init__.py +1 -0
- icdev/data/context/templates/project/python_backend/tests/features/__init__.py +1 -0
- icdev/data/context/templates/project/python_backend/tests/steps/__init__.py +1 -0
- icdev/data/context/templates/terraform/__init__.py +1 -0
- icdev/data/context/templates/terraform/govcloud_base/__init__.py +1 -0
- icdev/data/context/templates/terraform/modules/__init__.py +1 -0
- icdev/data/context/tone/__init__.py +1 -0
- icdev/data/context/translation/dependency_mappings.json +186 -0
- icdev/data/context/translation/type_mappings.json +149 -0
- icdev/data/docs/README.md +187 -0
- icdev/data/docs/__init__.py +1 -0
- icdev/data/docs/admin/gateway-guide.md +338 -0
- icdev/data/docs/admin/marketplace-guide.md +396 -0
- icdev/data/docs/admin/monitoring-guide.md +509 -0
- icdev/data/docs/architecture/compliance-framework.md +764 -0
- icdev/data/docs/architecture/database-schema.md +689 -0
- icdev/data/docs/architecture/gotcha-framework.md +518 -0
- icdev/data/docs/architecture/multi-agent-system.md +603 -0
- icdev/data/docs/dx/README.md +106 -0
- icdev/data/docs/dx/__init__.py +1 -0
- icdev/data/docs/dx/ci-cd-integration.md +378 -0
- icdev/data/docs/dx/claude-code-guide.md +213 -0
- icdev/data/docs/dx/companion-guide.md +232 -0
- icdev/data/docs/dx/dev-profiles.md +309 -0
- icdev/data/docs/dx/icdev-yaml-spec.md +219 -0
- icdev/data/docs/dx/integration-tiers.md +279 -0
- icdev/data/docs/dx/llm-routing-guide.md +456 -0
- icdev/data/docs/dx/quickstart.md +192 -0
- icdev/data/docs/dx/sdk-reference.md +356 -0
- icdev/data/docs/dx/unified-mcp-setup.md +525 -0
- icdev/data/docs/features/__init__.py +1 -0
- icdev/data/docs/features/phase-01-gotcha-framework.md +249 -0
- icdev/data/docs/features/phase-02-atlas-build-workflow.md +223 -0
- icdev/data/docs/features/phase-03-tdd-bdd-testing.md +261 -0
- icdev/data/docs/features/phase-04-nist-compliance.md +255 -0
- icdev/data/docs/features/phase-05-security-scanning.md +229 -0
- icdev/data/docs/features/phase-06-infrastructure-deployment.md +288 -0
- icdev/data/docs/features/phase-07-code-review-gates.md +276 -0
- icdev/data/docs/features/phase-08-self-healing.md +223 -0
- icdev/data/docs/features/phase-09-monitoring-observability.md +230 -0
- icdev/data/docs/features/phase-10-dashboard-web-ui.md +218 -0
- icdev/data/docs/features/phase-11-multi-agent-architecture.md +272 -0
- icdev/data/docs/features/phase-12-integration-testing.md +228 -0
- icdev/data/docs/features/phase-13-cicd-integration.md +257 -0
- icdev/data/docs/features/phase-14-secure-by-design-ivv.md +240 -0
- icdev/data/docs/features/phase-15-maintenance-audit.md +192 -0
- icdev/data/docs/features/phase-16-ato-acceleration.md +228 -0
- icdev/data/docs/features/phase-17-multi-framework-compliance.md +223 -0
- icdev/data/docs/features/phase-18-mbse-integration.md +242 -0
- icdev/data/docs/features/phase-19-agentic-generation.md +202 -0
- icdev/data/docs/features/phase-20-fips-security-categorization.md +198 -0
- icdev/data/docs/features/phase-21-saas-multi-tenancy.md +273 -0
- icdev/data/docs/features/phase-22-federated-gotcha-marketplace.md +242 -0
- icdev/data/docs/features/phase-23-universal-compliance-platform.md +238 -0
- icdev/data/docs/features/phase-24-devsecops-pipeline-security.md +198 -0
- icdev/data/docs/features/phase-25-zero-trust-architecture.md +220 -0
- icdev/data/docs/features/phase-26-dod-mosa.md +205 -0
- icdev/data/docs/features/phase-27-cli-capabilities.md +222 -0
- icdev/data/docs/features/phase-28-remote-command-gateway.md +235 -0
- icdev/data/docs/features/phase-29-proactive-monitoring.md +212 -0
- icdev/data/docs/features/phase-30-dashboard-auth.md +215 -0
- icdev/data/docs/features/phase-31-dashboard-ux-low-impact.md +188 -0
- icdev/data/docs/features/phase-32-dashboard-ux-medium-impact.md +223 -0
- icdev/data/docs/features/phase-33-modular-installation.md +218 -0
- icdev/data/docs/features/phase-34-dev-profiles.md +239 -0
- icdev/data/docs/features/phase-35-innovation-engine.md +257 -0
- icdev/data/docs/features/phase-36-evolutionary-intelligence.md +351 -0
- icdev/data/docs/features/phase-37-mitre-atlas-integration.md +485 -0
- icdev/data/docs/features/phase-38-cloud-agnostic-architecture.md +1033 -0
- icdev/data/docs/features/phase-39-observability-operations.md +178 -0
- icdev/data/docs/features/phase-40-nlq-compliance-queries.md +176 -0
- icdev/data/docs/features/phase-41-parallel-cicd.md +169 -0
- icdev/data/docs/features/phase-42-framework-planning.md +177 -0
- icdev/data/docs/features/phase-43-cross-language-translation.md +225 -0
- icdev/data/docs/features/phase-44-innovation-adaptation.md +227 -0
- icdev/data/docs/features/phase-45-owasp-agentic-security.md +239 -0
- icdev/data/docs/features/phase-46-observability-traceability-xai.md +240 -0
- icdev/data/docs/features/phase-47-unified-mcp-gateway.md +257 -0
- icdev/data/docs/features/phase-48-ai-transparency.md +203 -0
- icdev/data/docs/features/phase-49-ai-accountability.md +243 -0
- icdev/data/docs/features/phase-50-ai-governance-intake-chat.md +195 -0
- icdev/data/docs/features/phase-51-unified-chat-dashboard.md +240 -0
- icdev/data/docs/features/phase-52-code-intelligence.md +244 -0
- icdev/data/docs/features/phase-53-fedramp-20x-owasp-asi.md +359 -0
- icdev/data/docs/features/phase-54-slsa-swft-orchestration.md +379 -0
- icdev/data/docs/features/phase-55-a2a-v03-mcp-oauth.md +322 -0
- icdev/data/docs/features/phase-56-evidence-lineage.md +352 -0
- icdev/data/docs/features/phase-57-eu-ai-act-iron-bank.md +319 -0
- icdev/data/docs/features/phase-58-creative-engine.md +370 -0
- icdev/data/docs/features/phase-59-govcon-intelligence.md +535 -0
- icdev/data/docs/features/phase-60-cpmp.md +528 -0
- icdev/data/docs/features/phase-61-orchestration-improvements.md +534 -0
- icdev/data/docs/operations/dashboard-guide.md +354 -0
- icdev/data/docs/operations/deployment-guide.md +556 -0
- icdev/data/docs/operations/saas-admin-guide.md +439 -0
- icdev/data/docs/operations/security-operations-guide.md +733 -0
- icdev/data/docs/runbooks/backup-restore.md +412 -0
- icdev/data/docs/runbooks/troubleshooting.md +499 -0
- icdev/data/features/__init__.py +1 -0
- icdev/data/features/cicd_integration.feature +41 -0
- icdev/data/features/compliance_gates.feature +46 -0
- icdev/data/features/dashboard.feature +72 -0
- icdev/data/features/environment.py +25 -0
- icdev/data/features/project_management.feature +32 -0
- icdev/data/features/requirements_intake.feature +42 -0
- icdev/data/features/saas_platform.feature +53 -0
- icdev/data/features/security_scanning.feature +36 -0
- icdev/data/features/steps/__init__.py +1 -0
- icdev/data/features/steps/cicd_steps.py +465 -0
- icdev/data/features/steps/compliance_steps.py +308 -0
- icdev/data/features/steps/dashboard_steps.py +88 -0
- icdev/data/features/steps/project_steps.py +126 -0
- icdev/data/features/steps/requirements_intake_steps.py +689 -0
- icdev/data/features/steps/saas_platform_steps.py +572 -0
- icdev/data/features/steps/security_steps.py +236 -0
- icdev/data/features/steps/testing_steps.py +226 -0
- icdev/data/features/testing_pipeline.feature +42 -0
- icdev/data/goals/__init__.py +1 -0
- icdev/data/goals/agent_management.md +144 -0
- icdev/data/goals/agentic_generation.md +345 -0
- icdev/data/goals/agentic_threat_model.md +309 -0
- icdev/data/goals/ai_accountability.md +90 -0
- icdev/data/goals/ai_governance_intake.md +132 -0
- icdev/data/goals/ai_transparency.md +76 -0
- icdev/data/goals/atlas_integration.md +405 -0
- icdev/data/goals/ato_acceleration.md +139 -0
- icdev/data/goals/boundary_supply_chain.md +206 -0
- icdev/data/goals/build_app.md +544 -0
- icdev/data/goals/cicd_integration.md +86 -0
- icdev/data/goals/claude_dir_maintenance.md +77 -0
- icdev/data/goals/cli_capabilities.md +340 -0
- icdev/data/goals/cloud_agnostic.md +312 -0
- icdev/data/goals/code_intelligence.md +197 -0
- icdev/data/goals/code_review.md +94 -0
- icdev/data/goals/compliance_workflow.md +858 -0
- icdev/data/goals/continuous_harmonization.md +140 -0
- icdev/data/goals/cross_language_translation.md +171 -0
- icdev/data/goals/dashboard.md +142 -0
- icdev/data/goals/deploy_workflow.md +390 -0
- icdev/data/goals/devsecops_workflow.md +408 -0
- icdev/data/goals/evolutionary_intelligence.md +305 -0
- icdev/data/goals/external_integration.md +113 -0
- icdev/data/goals/framework_planning.md +63 -0
- icdev/data/goals/init_project.md +235 -0
- icdev/data/goals/innovation_engine.md +199 -0
- icdev/data/goals/integration_testing.md +189 -0
- icdev/data/goals/maintenance_audit.md +196 -0
- icdev/data/goals/manifest.md +56 -0
- icdev/data/goals/mbse_integration.md +504 -0
- icdev/data/goals/modernization_workflow.md +618 -0
- icdev/data/goals/monitoring.md +126 -0
- icdev/data/goals/mosa_workflow.md +463 -0
- icdev/data/goals/multi_agent_orchestration.md +68 -0
- icdev/data/goals/nlq_compliance.md +63 -0
- icdev/data/goals/observability.md +64 -0
- icdev/data/goals/observability_traceability_xai.md +154 -0
- icdev/data/goals/owasp_agentic_security.md +395 -0
- icdev/data/goals/parallel_cicd.md +61 -0
- icdev/data/goals/requirements_intake.md +213 -0
- icdev/data/goals/sbd_ivv_workflow.md +195 -0
- icdev/data/goals/security_categorization.md +133 -0
- icdev/data/goals/security_scan.md +381 -0
- icdev/data/goals/self_healing.md +120 -0
- icdev/data/goals/simulation_engine.md +111 -0
- icdev/data/goals/tdd_workflow.md +403 -0
- icdev/data/goals/zero_trust_architecture.md +403 -0
- icdev/data/hardprompts/__init__.py +1 -0
- icdev/data/hardprompts/agent/__init__.py +1 -0
- icdev/data/hardprompts/agent/agentic_architect.md +100 -0
- icdev/data/hardprompts/agent/debate_prompt.md +32 -0
- icdev/data/hardprompts/agent/fitness_evaluation.md +48 -0
- icdev/data/hardprompts/agent/governance_review.md +214 -0
- icdev/data/hardprompts/agent/reviewer_prompt.md +34 -0
- icdev/data/hardprompts/agent/skill_design.md +172 -0
- icdev/data/hardprompts/agent/task_decomposition.md +275 -0
- icdev/data/hardprompts/agent/veto_check_prompt.md +33 -0
- icdev/data/hardprompts/architect/__init__.py +1 -0
- icdev/data/hardprompts/architect/api_design.md +283 -0
- icdev/data/hardprompts/architect/data_model.md +277 -0
- icdev/data/hardprompts/architect/system_design.md +180 -0
- icdev/data/hardprompts/builder/__init__.py +1 -0
- icdev/data/hardprompts/builder/code_generation.md +59 -0
- icdev/data/hardprompts/builder/refactor.md +58 -0
- icdev/data/hardprompts/builder/scaffold_project.md +69 -0
- icdev/data/hardprompts/builder/test_generation.md +87 -0
- icdev/data/hardprompts/ci/__init__.py +1 -0
- icdev/data/hardprompts/ci/worktree_setup.md +35 -0
- icdev/data/hardprompts/compliance/__init__.py +1 -0
- icdev/data/hardprompts/compliance/cmmc_assessment.md +63 -0
- icdev/data/hardprompts/compliance/cssp_assessment.md +75 -0
- icdev/data/hardprompts/compliance/cui_marking.md +86 -0
- icdev/data/hardprompts/compliance/fedramp_assessment.md +55 -0
- icdev/data/hardprompts/compliance/ivv_assessment.md +96 -0
- icdev/data/hardprompts/compliance/poam_generation.md +57 -0
- icdev/data/hardprompts/compliance/sbd_assessment.md +101 -0
- icdev/data/hardprompts/compliance/security_categorization.md +74 -0
- icdev/data/hardprompts/compliance/ssp_generation.md +56 -0
- icdev/data/hardprompts/compliance/stig_evaluation.md +63 -0
- icdev/data/hardprompts/dashboard/__init__.py +1 -0
- icdev/data/hardprompts/dashboard/nlq_system_prompt.md +26 -0
- icdev/data/hardprompts/infra/__init__.py +1 -0
- icdev/data/hardprompts/infra/k8s_manifests.md +118 -0
- icdev/data/hardprompts/infra/pipeline_generation.md +160 -0
- icdev/data/hardprompts/infra/terraform_generation.md +92 -0
- icdev/data/hardprompts/integration/__init__.py +1 -0
- icdev/data/hardprompts/integration/approval_review.md +17 -0
- icdev/data/hardprompts/integration/jira_mapping.md +25 -0
- icdev/data/hardprompts/integration/servicenow_mapping.md +14 -0
- icdev/data/hardprompts/knowledge/__init__.py +1 -0
- icdev/data/hardprompts/knowledge/pattern_detection.md +73 -0
- icdev/data/hardprompts/knowledge/recommendation_engine.md +90 -0
- icdev/data/hardprompts/knowledge/root_cause_analysis.md +91 -0
- icdev/data/hardprompts/maintenance/__init__.py +1 -0
- icdev/data/hardprompts/maintenance/maintenance_assessment.md +82 -0
- icdev/data/hardprompts/mbse/__init__.py +1 -0
- icdev/data/hardprompts/mbse/digital_thread.md +67 -0
- icdev/data/hardprompts/mbse/model_import.md +62 -0
- icdev/data/hardprompts/mbse/model_to_code.md +65 -0
- icdev/data/hardprompts/modernization/__init__.py +1 -0
- icdev/data/hardprompts/modernization/legacy_analysis.md +93 -0
- icdev/data/hardprompts/modernization/migration_planning.md +150 -0
- icdev/data/hardprompts/modernization/seven_r_assessment.md +107 -0
- icdev/data/hardprompts/requirements/__init__.py +1 -0
- icdev/data/hardprompts/requirements/bdd_generation.md +35 -0
- icdev/data/hardprompts/requirements/clarification_prioritization.md +29 -0
- icdev/data/hardprompts/requirements/decomposition.md +60 -0
- icdev/data/hardprompts/requirements/document_extraction.md +45 -0
- icdev/data/hardprompts/requirements/gap_detection.md +70 -0
- icdev/data/hardprompts/requirements/intake_conversation.md +101 -0
- icdev/data/hardprompts/requirements/readiness_assessment.md +39 -0
- icdev/data/hardprompts/requirements/spec_quality.md +33 -0
- icdev/data/hardprompts/requirements/traceability_analysis.md +23 -0
- icdev/data/hardprompts/security/__init__.py +1 -0
- icdev/data/hardprompts/security/endpoint_security.md +78 -0
- icdev/data/hardprompts/security/threat_model.md +70 -0
- icdev/data/hardprompts/security/vulnerability_assessment.md +81 -0
- icdev/data/hardprompts/simulation/__init__.py +1 -0
- icdev/data/hardprompts/simulation/architecture_impact.md +27 -0
- icdev/data/hardprompts/simulation/coa_alternative.md +27 -0
- icdev/data/hardprompts/simulation/coa_generation.md +25 -0
- icdev/data/hardprompts/simulation/compliance_impact.md +28 -0
- icdev/data/hardprompts/simulation/cost_estimation.md +33 -0
- icdev/data/hardprompts/simulation/risk_assessment.md +28 -0
- icdev/data/hardprompts/translation/code_translation.md +68 -0
- icdev/data/hardprompts/translation/dependency_suggestion.md +44 -0
- icdev/data/hardprompts/translation/test_translation.md +64 -0
- icdev/data/hardprompts/translation/translation_repair.md +59 -0
- icdev/py.typed +0 -0
- icdev/tools/__init__.py +1 -0
- icdev/tools/_gen_formatter.py +12 -0
- icdev/tools/a2a/__init__.py +1 -0
- icdev/tools/a2a/agent_cards/architect.json +43 -0
- icdev/tools/a2a/agent_cards/builder.json +50 -0
- icdev/tools/a2a/agent_cards/compliance.json +57 -0
- icdev/tools/a2a/agent_cards/devsecops.json +71 -0
- icdev/tools/a2a/agent_cards/infra.json +57 -0
- icdev/tools/a2a/agent_cards/integration.json +57 -0
- icdev/tools/a2a/agent_cards/knowledge.json +43 -0
- icdev/tools/a2a/agent_cards/mbse.json +57 -0
- icdev/tools/a2a/agent_cards/modernization.json +50 -0
- icdev/tools/a2a/agent_cards/monitor.json +43 -0
- icdev/tools/a2a/agent_cards/orchestrator.json +36 -0
- icdev/tools/a2a/agent_cards/requirements_analyst.json +64 -0
- icdev/tools/a2a/agent_cards/security.json +50 -0
- icdev/tools/a2a/agent_cards/simulation.json +57 -0
- icdev/tools/a2a/agent_cards/supply_chain.json +50 -0
- icdev/tools/a2a/agent_client.py +349 -0
- icdev/tools/a2a/agent_registry.py +412 -0
- icdev/tools/a2a/agent_server.py +579 -0
- icdev/tools/a2a/task.py +200 -0
- icdev/tools/agent/__init__.py +2 -0
- icdev/tools/agent/a2a_agent_card_generator.py +285 -0
- icdev/tools/agent/a2a_discovery_server.py +250 -0
- icdev/tools/agent/agent_executor.py +529 -0
- icdev/tools/agent/agent_memory.py +557 -0
- icdev/tools/agent/agent_models.py +51 -0
- icdev/tools/agent/atlas_critique.py +908 -0
- icdev/tools/agent/authority.py +443 -0
- icdev/tools/agent/bedrock_client.py +1075 -0
- icdev/tools/agent/collaboration.py +871 -0
- icdev/tools/agent/dispatcher_mode.py +665 -0
- icdev/tools/agent/mailbox.py +575 -0
- icdev/tools/agent/prompt_chain_executor.py +1064 -0
- icdev/tools/agent/session_purpose.py +350 -0
- icdev/tools/agent/skill_router.py +638 -0
- icdev/tools/agent/skill_selector.py +486 -0
- icdev/tools/agent/team_orchestrator.py +1108 -0
- icdev/tools/agent/token_tracker.py +290 -0
- icdev/tools/analysis/__init__.py +1 -0
- icdev/tools/analysis/code_analyzer.py +780 -0
- icdev/tools/analysis/runtime_feedback.py +389 -0
- icdev/tools/audit/__init__.py +1 -0
- icdev/tools/audit/audit_logger.py +196 -0
- icdev/tools/audit/audit_query.py +157 -0
- icdev/tools/audit/decision_recorder.py +72 -0
- icdev/tools/builder/__init__.py +1 -0
- icdev/tools/builder/agentic_fitness.py +534 -0
- icdev/tools/builder/agentic_test_templates/test_a2a_callback.py +117 -0
- icdev/tools/builder/agentic_test_templates/test_a2a_lifecycle.feature +52 -0
- icdev/tools/builder/agentic_test_templates/test_agent_card.feature +37 -0
- icdev/tools/builder/agentic_test_templates/test_agent_health.py +128 -0
- icdev/tools/builder/agentic_test_templates/test_memory_system.feature +50 -0
- icdev/tools/builder/agentic_test_templates/test_skill_execution.feature +40 -0
- icdev/tools/builder/app_blueprint.py +1583 -0
- icdev/tools/builder/child_app_generator.py +2852 -0
- icdev/tools/builder/claude_md_generator.py +1734 -0
- icdev/tools/builder/code_generator.py +3703 -0
- icdev/tools/builder/db_init_generator.py +1709 -0
- icdev/tools/builder/dev_profile_manager.py +954 -0
- icdev/tools/builder/formatter.py +768 -0
- icdev/tools/builder/goal_adapter.py +592 -0
- icdev/tools/builder/gotcha_validator.py +812 -0
- icdev/tools/builder/language_support.py +441 -0
- icdev/tools/builder/linter.py +976 -0
- icdev/tools/builder/profile_detector.py +657 -0
- icdev/tools/builder/profile_md_generator.py +723 -0
- icdev/tools/builder/scaffolder.py +1590 -0
- icdev/tools/builder/scaffolder_extended.py +1771 -0
- icdev/tools/builder/test_writer.py +950 -0
- icdev/tools/ci/__init__.py +2 -0
- icdev/tools/ci/connectors/__init__.py +2 -0
- icdev/tools/ci/connectors/base_connector.py +80 -0
- icdev/tools/ci/connectors/connector_registry.py +188 -0
- icdev/tools/ci/connectors/mattermost_connector.py +159 -0
- icdev/tools/ci/connectors/slack_connector.py +197 -0
- icdev/tools/ci/core/__init__.py +2 -0
- icdev/tools/ci/core/air_gap_detector.py +115 -0
- icdev/tools/ci/core/comment_handler.py +192 -0
- icdev/tools/ci/core/conversation_manager.py +479 -0
- icdev/tools/ci/core/event_envelope.py +500 -0
- icdev/tools/ci/core/event_router.py +443 -0
- icdev/tools/ci/core/failure_parser.py +397 -0
- icdev/tools/ci/core/recovery_engine.py +527 -0
- icdev/tools/ci/modules/__init__.py +2 -0
- icdev/tools/ci/modules/agent.py +271 -0
- icdev/tools/ci/modules/git_ops.py +175 -0
- icdev/tools/ci/modules/state.py +117 -0
- icdev/tools/ci/modules/vcs.py +303 -0
- icdev/tools/ci/modules/workflow_ops.py +295 -0
- icdev/tools/ci/modules/worktree.py +340 -0
- icdev/tools/ci/pipeline_config_generator.py +558 -0
- icdev/tools/ci/triggers/__init__.py +2 -0
- icdev/tools/ci/triggers/gitlab_task_monitor.py +330 -0
- icdev/tools/ci/triggers/poll_trigger.py +237 -0
- icdev/tools/ci/triggers/webhook_server.py +356 -0
- icdev/tools/ci/workflows/__init__.py +2 -0
- icdev/tools/ci/workflows/icdev_build.py +140 -0
- icdev/tools/ci/workflows/icdev_comply.py +284 -0
- icdev/tools/ci/workflows/icdev_document.py +152 -0
- icdev/tools/ci/workflows/icdev_e2e.py +188 -0
- icdev/tools/ci/workflows/icdev_patch.py +186 -0
- icdev/tools/ci/workflows/icdev_plan.py +202 -0
- icdev/tools/ci/workflows/icdev_plan_build.py +41 -0
- icdev/tools/ci/workflows/icdev_plan_build_test.py +46 -0
- icdev/tools/ci/workflows/icdev_plan_build_test_review.py +47 -0
- icdev/tools/ci/workflows/icdev_review.py +126 -0
- icdev/tools/ci/workflows/icdev_sdlc.py +261 -0
- icdev/tools/ci/workflows/icdev_test.py +240 -0
- icdev/tools/cli/__init__.py +1 -0
- icdev/tools/cli/output_formatter.py +756 -0
- icdev/tools/cli_formatter.py +42 -0
- icdev/tools/cloud/__init__.py +11 -0
- icdev/tools/cloud/cloud_mode_manager.py +364 -0
- icdev/tools/cloud/csp_changelog.py +383 -0
- icdev/tools/cloud/csp_health_checker.py +268 -0
- icdev/tools/cloud/csp_monitor.py +951 -0
- icdev/tools/cloud/iam_provider.py +593 -0
- icdev/tools/cloud/kms_provider.py +346 -0
- icdev/tools/cloud/monitoring_provider.py +628 -0
- icdev/tools/cloud/provider_factory.py +376 -0
- icdev/tools/cloud/region_validator.py +345 -0
- icdev/tools/cloud/registry_provider.py +563 -0
- icdev/tools/cloud/secrets_provider.py +486 -0
- icdev/tools/cloud/storage_provider.py +446 -0
- icdev/tools/compat/__init__.py +21 -0
- icdev/tools/compat/cli_harmonizer.py +251 -0
- icdev/tools/compat/datetime_utils.py +18 -0
- icdev/tools/compat/db_utils.py +160 -0
- icdev/tools/compat/platform_utils.py +123 -0
- icdev/tools/compliance/__init__.py +1 -0
- icdev/tools/compliance/accountability_manager.py +397 -0
- icdev/tools/compliance/ai_accountability_audit.py +294 -0
- icdev/tools/compliance/ai_impact_assessor.py +273 -0
- icdev/tools/compliance/ai_incident_response.py +301 -0
- icdev/tools/compliance/ai_inventory_manager.py +239 -0
- icdev/tools/compliance/ai_reassessment_scheduler.py +256 -0
- icdev/tools/compliance/ai_transparency_audit.py +248 -0
- icdev/tools/compliance/atlas_assessor.py +278 -0
- icdev/tools/compliance/atlas_report_generator.py +1211 -0
- icdev/tools/compliance/base_assessor.py +597 -0
- icdev/tools/compliance/cato_monitor.py +1385 -0
- icdev/tools/compliance/cato_scheduler.py +699 -0
- icdev/tools/compliance/cjis_assessor.py +76 -0
- icdev/tools/compliance/classification_manager.py +1353 -0
- icdev/tools/compliance/cmmc_assessor.py +1491 -0
- icdev/tools/compliance/cmmc_report_generator.py +1100 -0
- icdev/tools/compliance/compliance_detector.py +463 -0
- icdev/tools/compliance/compliance_exporter.py +427 -0
- icdev/tools/compliance/compliance_status.py +825 -0
- icdev/tools/compliance/control_mapper.py +505 -0
- icdev/tools/compliance/crosswalk_engine.py +1203 -0
- icdev/tools/compliance/cssp_assessor.py +1045 -0
- icdev/tools/compliance/cssp_evidence_collector.py +729 -0
- icdev/tools/compliance/cssp_report_generator.py +1116 -0
- icdev/tools/compliance/cui_marker.py +388 -0
- icdev/tools/compliance/diagram_validator.py +600 -0
- icdev/tools/compliance/emass/__init__.py +2 -0
- icdev/tools/compliance/emass/emass_client.py +840 -0
- icdev/tools/compliance/emass/emass_export.py +777 -0
- icdev/tools/compliance/emass/emass_sync.py +826 -0
- icdev/tools/compliance/eu_ai_act_classifier.py +194 -0
- icdev/tools/compliance/evidence_collector.py +468 -0
- icdev/tools/compliance/fairness_assessor.py +316 -0
- icdev/tools/compliance/fedramp_assessor.py +1808 -0
- icdev/tools/compliance/fedramp_authorization_packager.py +137 -0
- icdev/tools/compliance/fedramp_ksi_generator.py +355 -0
- icdev/tools/compliance/fedramp_report_generator.py +1128 -0
- icdev/tools/compliance/fips199_categorizer.py +881 -0
- icdev/tools/compliance/fips200_validator.py +315 -0
- icdev/tools/compliance/gao_ai_assessor.py +231 -0
- icdev/tools/compliance/gao_evidence_builder.py +308 -0
- icdev/tools/compliance/hipaa_assessor.py +78 -0
- icdev/tools/compliance/hitrust_assessor.py +49 -0
- icdev/tools/compliance/incident_response_plan.py +718 -0
- icdev/tools/compliance/iso27001_assessor.py +92 -0
- icdev/tools/compliance/iso42001_assessor.py +114 -0
- icdev/tools/compliance/ivv_assessor.py +2327 -0
- icdev/tools/compliance/ivv_report_generator.py +1662 -0
- icdev/tools/compliance/model_card_generator.py +297 -0
- icdev/tools/compliance/mosa_assessor.py +117 -0
- icdev/tools/compliance/multi_regime_assessor.py +451 -0
- icdev/tools/compliance/narrative_generator.py +1013 -0
- icdev/tools/compliance/nist_800_207_assessor.py +191 -0
- icdev/tools/compliance/nist_ai_600_1_assessor.py +188 -0
- icdev/tools/compliance/nist_ai_rmf_assessor.py +110 -0
- icdev/tools/compliance/nist_lookup.py +245 -0
- icdev/tools/compliance/omb_m25_21_assessor.py +228 -0
- icdev/tools/compliance/omb_m26_04_assessor.py +188 -0
- icdev/tools/compliance/oscal_catalog_adapter.py +395 -0
- icdev/tools/compliance/oscal_generator.py +2170 -0
- icdev/tools/compliance/oscal_tools.py +1182 -0
- icdev/tools/compliance/owasp_agentic_assessor.py +226 -0
- icdev/tools/compliance/owasp_asi_assessor.py +200 -0
- icdev/tools/compliance/owasp_llm_assessor.py +244 -0
- icdev/tools/compliance/pci_dss_assessor.py +80 -0
- icdev/tools/compliance/pi_compliance_tracker.py +1461 -0
- icdev/tools/compliance/poam_generator.py +405 -0
- icdev/tools/compliance/resolve_marking.py +283 -0
- icdev/tools/compliance/sbd_assessor.py +2068 -0
- icdev/tools/compliance/sbd_report_generator.py +1236 -0
- icdev/tools/compliance/sbom_generator.py +1008 -0
- icdev/tools/compliance/siem_config_generator.py +674 -0
- icdev/tools/compliance/slsa_attestation_generator.py +490 -0
- icdev/tools/compliance/soc2_assessor.py +77 -0
- icdev/tools/compliance/ssp_generator.py +573 -0
- icdev/tools/compliance/stig_checker.py +727 -0
- icdev/tools/compliance/swft_evidence_bundler.py +337 -0
- icdev/tools/compliance/system_card_generator.py +309 -0
- icdev/tools/compliance/traceability_matrix.py +1281 -0
- icdev/tools/compliance/universal_classification_manager.py +1172 -0
- icdev/tools/compliance/xacta/__init__.py +2 -0
- icdev/tools/compliance/xacta/xacta_client.py +449 -0
- icdev/tools/compliance/xacta/xacta_export.py +557 -0
- icdev/tools/compliance/xacta/xacta_sync.py +333 -0
- icdev/tools/compliance/xai_assessor.py +231 -0
- icdev/tools/dashboard/__init__.py +1 -0
- icdev/tools/dashboard/api/__init__.py +1 -0
- icdev/tools/dashboard/api/_pipeline_state.py +17 -0
- icdev/tools/dashboard/api/activity.py +206 -0
- icdev/tools/dashboard/api/admin.py +176 -0
- icdev/tools/dashboard/api/agents.py +53 -0
- icdev/tools/dashboard/api/ai_accountability.py +163 -0
- icdev/tools/dashboard/api/ai_transparency.py +198 -0
- icdev/tools/dashboard/api/audit.py +58 -0
- icdev/tools/dashboard/api/batch.py +666 -0
- icdev/tools/dashboard/api/chat.py +241 -0
- icdev/tools/dashboard/api/cicd.py +219 -0
- icdev/tools/dashboard/api/code_quality.py +223 -0
- icdev/tools/dashboard/api/compliance.py +171 -0
- icdev/tools/dashboard/api/cpmp.py +915 -0
- icdev/tools/dashboard/api/diagrams.py +65 -0
- icdev/tools/dashboard/api/events.py +250 -0
- icdev/tools/dashboard/api/evidence.py +99 -0
- icdev/tools/dashboard/api/fedramp_20x.py +77 -0
- icdev/tools/dashboard/api/govcon.py +1095 -0
- icdev/tools/dashboard/api/intake.py +1171 -0
- icdev/tools/dashboard/api/lineage.py +163 -0
- icdev/tools/dashboard/api/metrics.py +155 -0
- icdev/tools/dashboard/api/nlq.py +72 -0
- icdev/tools/dashboard/api/orchestration.py +472 -0
- icdev/tools/dashboard/api/oscal.py +183 -0
- icdev/tools/dashboard/api/prod_audit.py +183 -0
- icdev/tools/dashboard/api/projects.py +191 -0
- icdev/tools/dashboard/api/proposals.py +1084 -0
- icdev/tools/dashboard/api/traces.py +363 -0
- icdev/tools/dashboard/api/usage.py +234 -0
- icdev/tools/dashboard/app.py +1986 -0
- icdev/tools/dashboard/auth.py +500 -0
- icdev/tools/dashboard/byok.py +245 -0
- icdev/tools/dashboard/chat_manager.py +675 -0
- icdev/tools/dashboard/config.py +116 -0
- icdev/tools/dashboard/diagram_definitions.py +642 -0
- icdev/tools/dashboard/nlq_processor.py +323 -0
- icdev/tools/dashboard/phase_loader.py +136 -0
- icdev/tools/dashboard/sse_manager.py +89 -0
- icdev/tools/dashboard/state_tracker.py +267 -0
- icdev/tools/dashboard/static/css/style.css +706 -0
- icdev/tools/dashboard/static/css/ux.css +2047 -0
- icdev/tools/dashboard/static/js/activity.js +322 -0
- icdev/tools/dashboard/static/js/api.js +161 -0
- icdev/tools/dashboard/static/js/batch.js +814 -0
- icdev/tools/dashboard/static/js/charts.js +618 -0
- icdev/tools/dashboard/static/js/chat.js +1514 -0
- icdev/tools/dashboard/static/js/kanban.js +113 -0
- icdev/tools/dashboard/static/js/live.js +569 -0
- icdev/tools/dashboard/static/js/mermaid-icdev.js +332 -0
- icdev/tools/dashboard/static/js/proposals.js +588 -0
- icdev/tools/dashboard/static/js/shortcuts.js +544 -0
- icdev/tools/dashboard/static/js/tables.js +652 -0
- icdev/tools/dashboard/static/js/tour.js +524 -0
- icdev/tools/dashboard/static/js/ux.js +942 -0
- icdev/tools/dashboard/templates/404.html +10 -0
- icdev/tools/dashboard/templates/activity.html +80 -0
- icdev/tools/dashboard/templates/admin/users.html +144 -0
- icdev/tools/dashboard/templates/ai_accountability.html +235 -0
- icdev/tools/dashboard/templates/ai_transparency.html +263 -0
- icdev/tools/dashboard/templates/base.html +104 -0
- icdev/tools/dashboard/templates/batch.html +23 -0
- icdev/tools/dashboard/templates/chat.html +332 -0
- icdev/tools/dashboard/templates/children.html +149 -0
- icdev/tools/dashboard/templates/cicd.html +253 -0
- icdev/tools/dashboard/templates/code_quality.html +214 -0
- icdev/tools/dashboard/templates/cpmp/cor_detail.html +220 -0
- icdev/tools/dashboard/templates/cpmp/cor_portal.html +91 -0
- icdev/tools/dashboard/templates/cpmp/deliverable_detail.html +197 -0
- icdev/tools/dashboard/templates/cpmp/detail.html +578 -0
- icdev/tools/dashboard/templates/cpmp/portfolio.html +202 -0
- icdev/tools/dashboard/templates/dev_profiles.html +304 -0
- icdev/tools/dashboard/templates/diagrams.html +224 -0
- icdev/tools/dashboard/templates/events/timeline.html +232 -0
- icdev/tools/dashboard/templates/evidence.html +134 -0
- icdev/tools/dashboard/templates/fedramp_20x.html +207 -0
- icdev/tools/dashboard/templates/gateway.html +244 -0
- icdev/tools/dashboard/templates/govcon/capabilities.html +135 -0
- icdev/tools/dashboard/templates/govcon/pipeline.html +214 -0
- icdev/tools/dashboard/templates/govcon/requirements.html +120 -0
- icdev/tools/dashboard/templates/index.html +254 -0
- icdev/tools/dashboard/templates/lineage.html +141 -0
- icdev/tools/dashboard/templates/login.html +51 -0
- icdev/tools/dashboard/templates/monitoring/overview.html +193 -0
- icdev/tools/dashboard/templates/orchestration/dashboard.html +545 -0
- icdev/tools/dashboard/templates/oscal.html +263 -0
- icdev/tools/dashboard/templates/phases.html +150 -0
- icdev/tools/dashboard/templates/prod_audit.html +280 -0
- icdev/tools/dashboard/templates/profile.html +183 -0
- icdev/tools/dashboard/templates/projects/detail.html +583 -0
- icdev/tools/dashboard/templates/projects/list.html +47 -0
- icdev/tools/dashboard/templates/proposals/detail.html +1253 -0
- icdev/tools/dashboard/templates/proposals/list.html +179 -0
- icdev/tools/dashboard/templates/proposals/section_detail.html +193 -0
- icdev/tools/dashboard/templates/provenance.html +181 -0
- icdev/tools/dashboard/templates/query/nlq.html +234 -0
- icdev/tools/dashboard/templates/quick_paths.html +69 -0
- icdev/tools/dashboard/templates/traces.html +155 -0
- icdev/tools/dashboard/templates/translation_detail.html +199 -0
- icdev/tools/dashboard/templates/translations.html +162 -0
- icdev/tools/dashboard/templates/usage.html +225 -0
- icdev/tools/dashboard/templates/wizard.html +539 -0
- icdev/tools/dashboard/templates/xai.html +208 -0
- icdev/tools/dashboard/ux_helpers.py +962 -0
- icdev/tools/dashboard/websocket.py +81 -0
- icdev/tools/db/__init__.py +1 -0
- icdev/tools/db/backup.py +312 -0
- icdev/tools/db/backup_manager.py +832 -0
- icdev/tools/db/init_icdev_db.py +5900 -0
- icdev/tools/db/migrate.py +178 -0
- icdev/tools/db/migration_runner.py +549 -0
- icdev/tools/db/migrations/001_baseline/meta.json +9 -0
- icdev/tools/db/migrations/001_baseline/up.py +68 -0
- icdev/tools/db/migrations/002_memory_enhancements/down.sql +8 -0
- icdev/tools/db/migrations/002_memory_enhancements/meta.json +9 -0
- icdev/tools/db/migrations/002_memory_enhancements/up.py +118 -0
- icdev/tools/db/migrations/003_dev_profiles/meta.json +8 -0
- icdev/tools/db/migrations/003_dev_profiles/up.py +93 -0
- icdev/tools/db/migrations/004_innovation_engine/down.py +19 -0
- icdev/tools/db/migrations/004_innovation_engine/up.py +227 -0
- icdev/tools/db/migrations/005_phase_37_ai_security/down.py +19 -0
- icdev/tools/db/migrations/005_phase_37_ai_security/up.py +258 -0
- icdev/tools/db/migrations/006_phase_36_evolution/down.py +21 -0
- icdev/tools/db/migrations/006_phase_36_evolution/up.py +323 -0
- icdev/tools/db/migrations/007_phase_38_cloud/down.py +14 -0
- icdev/tools/db/migrations/007_phase_38_cloud/up.py +110 -0
- icdev/tools/db/migrations/008_phase36_37_integration/up.py +55 -0
- icdev/tools/db/migrations/__init__.py +2 -0
- icdev/tools/devsecops/__init__.py +2 -0
- icdev/tools/devsecops/attestation_manager.py +458 -0
- icdev/tools/devsecops/network_segmentation_generator.py +614 -0
- icdev/tools/devsecops/pdp_config_generator.py +1256 -0
- icdev/tools/devsecops/pipeline_security_generator.py +484 -0
- icdev/tools/devsecops/policy_generator.py +653 -0
- icdev/tools/devsecops/profile_manager.py +388 -0
- icdev/tools/devsecops/service_mesh_generator.py +1073 -0
- icdev/tools/devsecops/zta_maturity_scorer.py +368 -0
- icdev/tools/devsecops/zta_terraform_generator.py +1303 -0
- icdev/tools/dx/__init__.py +3 -0
- icdev/tools/dx/companion.py +266 -0
- icdev/tools/dx/instruction_generator.py +753 -0
- icdev/tools/dx/mcp_config_generator.py +282 -0
- icdev/tools/dx/skill_translator.py +425 -0
- icdev/tools/dx/tool_detector.py +144 -0
- icdev/tools/extensions/__init__.py +21 -0
- icdev/tools/extensions/builtins/010_ai_governance_chat.py +277 -0
- icdev/tools/extensions/builtins/__init__.py +2 -0
- icdev/tools/extensions/extension_manager.py +455 -0
- icdev/tools/infra/__init__.py +1 -0
- icdev/tools/infra/ansible_generator.py +869 -0
- icdev/tools/infra/dockerfile_generator.py +361 -0
- icdev/tools/infra/infra_status.py +393 -0
- icdev/tools/infra/ironbank_metadata_generator.py +411 -0
- icdev/tools/infra/k8s_generator.py +1002 -0
- icdev/tools/infra/pipeline_generator.py +832 -0
- icdev/tools/infra/rollback.py +400 -0
- icdev/tools/infra/terraform_generator.py +1142 -0
- icdev/tools/infra/terraform_generator_azure.py +1254 -0
- icdev/tools/infra/terraform_generator_gcp.py +953 -0
- icdev/tools/infra/terraform_generator_ibm.py +360 -0
- icdev/tools/infra/terraform_generator_oci.py +919 -0
- icdev/tools/infra/terraform_generator_onprem.py +319 -0
- icdev/tools/innovation/__init__.py +8 -0
- icdev/tools/innovation/competitive_intel.py +492 -0
- icdev/tools/innovation/innovation_manager.py +681 -0
- icdev/tools/innovation/introspective_analyzer.py +774 -0
- icdev/tools/innovation/register_external_patterns.py +440 -0
- icdev/tools/innovation/signal_ranker.py +1038 -0
- icdev/tools/innovation/solution_generator.py +697 -0
- icdev/tools/innovation/standards_monitor.py +466 -0
- icdev/tools/innovation/trend_detector.py +1046 -0
- icdev/tools/innovation/triage_engine.py +1149 -0
- icdev/tools/innovation/web_scanner.py +894 -0
- icdev/tools/installer/__init__.py +1 -0
- icdev/tools/installer/compliance_configurator.py +637 -0
- icdev/tools/installer/installer.py +1711 -0
- icdev/tools/installer/module_registry.py +805 -0
- icdev/tools/installer/platform_setup.py +961 -0
- icdev/tools/integration/__init__.py +2 -0
- icdev/tools/integration/approval_manager.py +561 -0
- icdev/tools/integration/doors_exporter.py +627 -0
- icdev/tools/integration/gitlab_connector.py +784 -0
- icdev/tools/integration/jira_connector.py +774 -0
- icdev/tools/integration/servicenow_connector.py +693 -0
- icdev/tools/knowledge/__init__.py +1 -0
- icdev/tools/knowledge/knowledge_ingest.py +293 -0
- icdev/tools/knowledge/pattern_detector.py +693 -0
- icdev/tools/knowledge/recommendation_engine.py +461 -0
- icdev/tools/knowledge/self_heal_analyzer.py +504 -0
- icdev/tools/llm/__init__.py +72 -0
- icdev/tools/llm/anthropic_provider.py +170 -0
- icdev/tools/llm/azure_openai_provider.py +338 -0
- icdev/tools/llm/bedrock_provider.py +315 -0
- icdev/tools/llm/embedding_provider.py +438 -0
- icdev/tools/llm/gemini_provider.py +381 -0
- icdev/tools/llm/ibm_watsonx_provider.py +232 -0
- icdev/tools/llm/oci_genai_provider.py +462 -0
- icdev/tools/llm/ollama_provider.py +340 -0
- icdev/tools/llm/openai_provider.py +225 -0
- icdev/tools/llm/provider.py +355 -0
- icdev/tools/llm/provider_sdk.py +175 -0
- icdev/tools/llm/router.py +780 -0
- icdev/tools/llm/vertex_ai_provider.py +374 -0
- icdev/tools/maintenance/__init__.py +2 -0
- icdev/tools/maintenance/dependency_scanner.py +1030 -0
- icdev/tools/maintenance/maintenance_auditor.py +815 -0
- icdev/tools/maintenance/remediation_engine.py +966 -0
- icdev/tools/maintenance/vulnerability_checker.py +987 -0
- icdev/tools/mbse/__init__.py +3 -0
- icdev/tools/mbse/des_assessor.py +1186 -0
- icdev/tools/mbse/des_report_generator.py +800 -0
- icdev/tools/mbse/diagram_extractor.py +811 -0
- icdev/tools/mbse/digital_thread.py +1665 -0
- icdev/tools/mbse/model_code_generator.py +1122 -0
- icdev/tools/mbse/model_control_mapper.py +420 -0
- icdev/tools/mbse/pi_model_tracker.py +1093 -0
- icdev/tools/mbse/reqif_parser.py +1483 -0
- icdev/tools/mbse/sync_engine.py +1805 -0
- icdev/tools/mbse/xmi_parser.py +1573 -0
- icdev/tools/mcp/__init__.py +1 -0
- icdev/tools/mcp/base_server.py +535 -0
- icdev/tools/mcp/builder_server.py +725 -0
- icdev/tools/mcp/compliance_server.py +1407 -0
- icdev/tools/mcp/context_indexer.py +199 -0
- icdev/tools/mcp/context_server.py +305 -0
- icdev/tools/mcp/core_server.py +679 -0
- icdev/tools/mcp/devsecops_server.py +432 -0
- icdev/tools/mcp/gap_handlers.py +1079 -0
- icdev/tools/mcp/gateway_server.py +339 -0
- icdev/tools/mcp/generate_registry.py +623 -0
- icdev/tools/mcp/infra_server.py +264 -0
- icdev/tools/mcp/innovation_server.py +316 -0
- icdev/tools/mcp/integration_server.py +527 -0
- icdev/tools/mcp/knowledge_server.py +429 -0
- icdev/tools/mcp/maintenance_server.py +248 -0
- icdev/tools/mcp/marketplace_server.py +499 -0
- icdev/tools/mcp/mbse_server.py +398 -0
- icdev/tools/mcp/modernization_server.py +496 -0
- icdev/tools/mcp/observability_server.py +354 -0
- icdev/tools/mcp/requirements_server.py +415 -0
- icdev/tools/mcp/simulation_server.py +468 -0
- icdev/tools/mcp/standalone/__init__.py +2 -0
- icdev/tools/mcp/standalone/builder.py +59 -0
- icdev/tools/mcp/standalone/compliance.py +59 -0
- icdev/tools/mcp/standalone/core.py +59 -0
- icdev/tools/mcp/standalone/knowledge.py +59 -0
- icdev/tools/mcp/standalone/maintenance.py +59 -0
- icdev/tools/mcp/supply_chain_server.py +476 -0
- icdev/tools/mcp/tool_registry.py +2008 -0
- icdev/tools/mcp/unified_server.py +158 -0
- icdev/tools/memory/__init__.py +2 -0
- icdev/tools/memory/auto_capture.py +347 -0
- icdev/tools/memory/embed_memory.py +158 -0
- icdev/tools/memory/history_compressor.py +334 -0
- icdev/tools/memory/hybrid_search.py +236 -0
- icdev/tools/memory/maintenance_cron.py +289 -0
- icdev/tools/memory/memory_consolidation.py +444 -0
- icdev/tools/memory/memory_db.py +133 -0
- icdev/tools/memory/memory_read.py +102 -0
- icdev/tools/memory/memory_write.py +222 -0
- icdev/tools/memory/semantic_search.py +139 -0
- icdev/tools/memory/time_decay.py +435 -0
- icdev/tools/modernization/__init__.py +3 -0
- icdev/tools/modernization/architecture_extractor.py +734 -0
- icdev/tools/modernization/compliance_bridge.py +1499 -0
- icdev/tools/modernization/db_migration_planner.py +1385 -0
- icdev/tools/modernization/doc_generator.py +1428 -0
- icdev/tools/modernization/framework_migrator.py +1525 -0
- icdev/tools/modernization/legacy_analyzer.py +1948 -0
- icdev/tools/modernization/migration_code_generator.py +1639 -0
- icdev/tools/modernization/migration_report_generator.py +1653 -0
- icdev/tools/modernization/migration_tracker.py +1726 -0
- icdev/tools/modernization/monolith_decomposer.py +1508 -0
- icdev/tools/modernization/seven_r_assessor.py +1658 -0
- icdev/tools/modernization/strangler_fig_manager.py +1705 -0
- icdev/tools/modernization/ui_analyzer.py +771 -0
- icdev/tools/modernization/version_migrator.py +1392 -0
- icdev/tools/monitor/__init__.py +1 -0
- icdev/tools/monitor/alert_correlator.py +495 -0
- icdev/tools/monitor/auto_resolver.py +612 -0
- icdev/tools/monitor/health_checker.py +509 -0
- icdev/tools/monitor/heartbeat_daemon.py +792 -0
- icdev/tools/monitor/log_analyzer.py +516 -0
- icdev/tools/monitor/metric_collector.py +496 -0
- icdev/tools/mosa/__init__.py +10 -0
- icdev/tools/mosa/icd_generator.py +370 -0
- icdev/tools/mosa/modular_design_analyzer.py +683 -0
- icdev/tools/mosa/mosa_code_enforcer.py +349 -0
- icdev/tools/mosa/tsp_generator.py +265 -0
- icdev/tools/observability/__init__.py +100 -0
- icdev/tools/observability/genai_attributes.py +88 -0
- icdev/tools/observability/instrumentation.py +140 -0
- icdev/tools/observability/mlflow_exporter.py +194 -0
- icdev/tools/observability/otel_tracer.py +168 -0
- icdev/tools/observability/provenance/__init__.py +3 -0
- icdev/tools/observability/provenance/prov_recorder.py +324 -0
- icdev/tools/observability/shap/__init__.py +3 -0
- icdev/tools/observability/shap/agent_shap.py +275 -0
- icdev/tools/observability/sqlite_tracer.py +361 -0
- icdev/tools/observability/trace_context.py +205 -0
- icdev/tools/observability/tracer.py +230 -0
- icdev/tools/orchestration/__init__.py +2 -0
- icdev/tools/orchestration/workflow_composer.py +361 -0
- icdev/tools/project/__init__.py +1 -0
- icdev/tools/project/manifest_loader.py +418 -0
- icdev/tools/project/project_create.py +350 -0
- icdev/tools/project/project_list.py +174 -0
- icdev/tools/project/project_scaffold.py +1715 -0
- icdev/tools/project/project_status.py +479 -0
- icdev/tools/project/session_context_builder.py +757 -0
- icdev/tools/project/validate_manifest.py +55 -0
- icdev/tools/registry/__init__.py +10 -0
- icdev/tools/registry/absorption_engine.py +832 -0
- icdev/tools/registry/capability_evaluator.py +668 -0
- icdev/tools/registry/child_registry.py +617 -0
- icdev/tools/registry/cross_pollinator.py +1065 -0
- icdev/tools/registry/genome_manager.py +671 -0
- icdev/tools/registry/learning_collector.py +912 -0
- icdev/tools/registry/propagation_manager.py +942 -0
- icdev/tools/registry/staging_manager.py +742 -0
- icdev/tools/registry/telemetry_collector.py +423 -0
- icdev/tools/requirements/__init__.py +1 -0
- icdev/tools/requirements/ai_governance_scorer.py +208 -0
- icdev/tools/requirements/boundary_analyzer.py +1293 -0
- icdev/tools/requirements/clarification_engine.py +618 -0
- icdev/tools/requirements/complexity_scorer.py +387 -0
- icdev/tools/requirements/consistency_analyzer.py +803 -0
- icdev/tools/requirements/constitution_manager.py +605 -0
- icdev/tools/requirements/decomposition_engine.py +778 -0
- icdev/tools/requirements/document_extractor.py +1016 -0
- icdev/tools/requirements/elicitation_techniques.py +519 -0
- icdev/tools/requirements/gap_detector.py +271 -0
- icdev/tools/requirements/intake_engine.py +2188 -0
- icdev/tools/requirements/prd_generator.py +847 -0
- icdev/tools/requirements/prd_validator.py +595 -0
- icdev/tools/requirements/readiness_scorer.py +313 -0
- icdev/tools/requirements/spec_organizer.py +1029 -0
- icdev/tools/requirements/spec_quality_checker.py +1097 -0
- icdev/tools/requirements/traceability_builder.py +579 -0
- icdev/tools/resilience/__init__.py +34 -0
- icdev/tools/resilience/circuit_breaker.py +340 -0
- icdev/tools/resilience/correlation.py +150 -0
- icdev/tools/resilience/errors.py +81 -0
- icdev/tools/resilience/retry.py +95 -0
- icdev/tools/schemas/__init__.py +27 -0
- icdev/tools/schemas/chat.py +61 -0
- icdev/tools/schemas/compliance.py +56 -0
- icdev/tools/schemas/core.py +85 -0
- icdev/tools/schemas/innovation.py +37 -0
- icdev/tools/schemas/validation.py +109 -0
- icdev/tools/sdk/__init__.py +3 -0
- icdev/tools/sdk/icdev_client.py +218 -0
- icdev/tools/security/__init__.py +1 -0
- icdev/tools/security/agent_output_validator.py +330 -0
- icdev/tools/security/agent_trust_scorer.py +466 -0
- icdev/tools/security/ai_bom_generator.py +725 -0
- icdev/tools/security/ai_telemetry_logger.py +469 -0
- icdev/tools/security/atlas_red_team.py +543 -0
- icdev/tools/security/code_pattern_scanner.py +378 -0
- icdev/tools/security/confabulation_detector.py +271 -0
- icdev/tools/security/container_scanner.py +491 -0
- icdev/tools/security/dependency_auditor.py +944 -0
- icdev/tools/security/endpoint_security_scanner.py +579 -0
- icdev/tools/security/mcp_tool_authorizer.py +243 -0
- icdev/tools/security/prompt_injection_detector.py +737 -0
- icdev/tools/security/sast_runner.py +948 -0
- icdev/tools/security/secret_detector.py +378 -0
- icdev/tools/security/tool_chain_validator.py +357 -0
- icdev/tools/security/vuln_scanner.py +539 -0
- icdev/tools/simulation/__init__.py +2 -0
- icdev/tools/simulation/coa_generator.py +1552 -0
- icdev/tools/simulation/monte_carlo.py +758 -0
- icdev/tools/simulation/scenario_manager.py +1073 -0
- icdev/tools/simulation/simulation_engine.py +1104 -0
- icdev/tools/supply_chain/__init__.py +2 -0
- icdev/tools/supply_chain/cve_triager.py +705 -0
- icdev/tools/supply_chain/dependency_graph.py +645 -0
- icdev/tools/supply_chain/isa_manager.py +540 -0
- icdev/tools/supply_chain/scrm_assessor.py +546 -0
- icdev/tools/testing/__init__.py +2 -0
- icdev/tools/testing/acceptance_validator.py +411 -0
- icdev/tools/testing/claude_dir_validator.py +831 -0
- icdev/tools/testing/data_types.py +199 -0
- icdev/tools/testing/e2e_runner.py +715 -0
- icdev/tools/testing/fuzz_cli.py +306 -0
- icdev/tools/testing/health_check.py +483 -0
- icdev/tools/testing/platform_check.py +143 -0
- icdev/tools/testing/production_audit.py +1862 -0
- icdev/tools/testing/production_remediate.py +804 -0
- icdev/tools/testing/screenshot_validator.py +539 -0
- icdev/tools/testing/smoke_test.py +283 -0
- icdev/tools/testing/test_agent_models.py +117 -0
- icdev/tools/testing/test_orchestrator.py +957 -0
- icdev/tools/testing/utils.py +229 -0
- icdev/tools/translation/__init__.py +17 -0
- icdev/tools/translation/code_translator.py +550 -0
- icdev/tools/translation/dependency_mapper.py +277 -0
- icdev/tools/translation/feature_map.py +395 -0
- icdev/tools/translation/project_assembler.py +439 -0
- icdev/tools/translation/source_extractor.py +609 -0
- icdev/tools/translation/test_translator.py +333 -0
- icdev/tools/translation/translation_manager.py +582 -0
- icdev/tools/translation/translation_validator.py +662 -0
- icdev/tools/translation/type_checker.py +371 -0
- icdev-1.0.0.dist-info/METADATA +868 -0
- icdev-1.0.0.dist-info/RECORD +1105 -0
- icdev-1.0.0.dist-info/WHEEL +5 -0
- icdev-1.0.0.dist-info/entry_points.txt +9 -0
- icdev-1.0.0.dist-info/licenses/LICENSE +254 -0
- icdev-1.0.0.dist-info/licenses/NOTICE +268 -0
- icdev-1.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,1508 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# CUI // SP-CTI
|
|
3
|
+
"""Monolith Decomposition Planning Tool for ICDEV DoD Modernization System.
|
|
4
|
+
|
|
5
|
+
Analyzes legacy monolithic applications, detects bounded contexts via greedy
|
|
6
|
+
modularity optimization, suggests microservice boundaries, generates ordered
|
|
7
|
+
extraction plans, anti-corruption layers, API facades, effort estimates, and
|
|
8
|
+
persists migration plans/tasks to the ICDEV database.
|
|
9
|
+
|
|
10
|
+
Classification: CUI // SP-CTI
|
|
11
|
+
System: ICDEV Intelligent Certified Development Framework
|
|
12
|
+
NIST: SC-7 (Boundary Protection), SA-8 (Security Engineering Principles)
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
import argparse
|
|
16
|
+
import json
|
|
17
|
+
import sqlite3
|
|
18
|
+
import sys
|
|
19
|
+
import uuid
|
|
20
|
+
from collections import Counter, defaultdict
|
|
21
|
+
from datetime import datetime, timezone
|
|
22
|
+
from pathlib import Path
|
|
23
|
+
from icdev._paths import get_project_root
|
|
24
|
+
|
|
25
|
+
# ---------------------------------------------------------------------------
|
|
26
|
+
# Paths
|
|
27
|
+
# ---------------------------------------------------------------------------
|
|
28
|
+
BASE_DIR = get_project_root()
|
|
29
|
+
DB_PATH = BASE_DIR / "data" / "icdev.db"
|
|
30
|
+
PATTERNS_PATH = BASE_DIR / "context" / "modernization" / "decomposition_patterns.json"
|
|
31
|
+
|
|
32
|
+
# ---------------------------------------------------------------------------
|
|
33
|
+
# Valid strategy / approach / architecture enums (mirror DB CHECK constraints)
|
|
34
|
+
# ---------------------------------------------------------------------------
|
|
35
|
+
VALID_STRATEGIES = (
|
|
36
|
+
"rehost", "replatform", "refactor", "rearchitect",
|
|
37
|
+
"repurchase", "retire", "retain", "hybrid",
|
|
38
|
+
)
|
|
39
|
+
VALID_APPROACHES = (
|
|
40
|
+
"big_bang", "strangler_fig", "parallel_run",
|
|
41
|
+
"blue_green", "canary", "phased",
|
|
42
|
+
)
|
|
43
|
+
VALID_ARCHITECTURES = (
|
|
44
|
+
"microservices", "modular_monolith", "serverless",
|
|
45
|
+
"event_driven", "layered", "hexagonal",
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
# ---------------------------------------------------------------------------
|
|
49
|
+
# Task-type templates per strategy
|
|
50
|
+
# ---------------------------------------------------------------------------
|
|
51
|
+
STRATEGY_TASK_TEMPLATES = {
|
|
52
|
+
"rehost": [
|
|
53
|
+
("analyze", "Analyze {name} for containerization", "high", 4),
|
|
54
|
+
("document", "Document {name} runtime requirements", "medium", 2),
|
|
55
|
+
("deploy", "Containerize and deploy {name}", "high", 8),
|
|
56
|
+
("validate", "Validate {name} container deployment", "medium", 4),
|
|
57
|
+
],
|
|
58
|
+
"replatform": [
|
|
59
|
+
("analyze", "Analyze {name} platform dependencies", "high", 4),
|
|
60
|
+
("document", "Document {name} platform migration plan", "medium", 3),
|
|
61
|
+
("migrate_schema", "Migrate {name} database schema", "high", 8),
|
|
62
|
+
("deploy", "Containerize and deploy {name}", "high", 6),
|
|
63
|
+
("validate", "Validate {name} replatform deployment", "medium", 4),
|
|
64
|
+
],
|
|
65
|
+
"refactor": [
|
|
66
|
+
("analyze", "Analyze {name} for version/framework upgrade", "high", 4),
|
|
67
|
+
("upgrade_version", "Upgrade {name} language version", "high", 6),
|
|
68
|
+
("upgrade_framework", "Upgrade {name} framework", "high", 8),
|
|
69
|
+
("generate_test", "Generate regression tests for {name}", "medium", 6),
|
|
70
|
+
("validate", "Validate {name} refactored build", "medium", 4),
|
|
71
|
+
],
|
|
72
|
+
"retire": [
|
|
73
|
+
("analyze", "Assess {name} for retirement eligibility", "medium", 2),
|
|
74
|
+
("document", "Document {name} retirement justification", "high", 3),
|
|
75
|
+
("decommission", "Decommission {name}", "high", 4),
|
|
76
|
+
],
|
|
77
|
+
"retain": [
|
|
78
|
+
("document", "Document {name} retain decision and rationale", "low", 2),
|
|
79
|
+
],
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
# ===================================================================
|
|
84
|
+
# Database helpers
|
|
85
|
+
# ===================================================================
|
|
86
|
+
|
|
87
|
+
def _get_db(db_path=None):
|
|
88
|
+
"""Return an sqlite3 connection with Row factory enabled.
|
|
89
|
+
|
|
90
|
+
Raises FileNotFoundError if the database does not exist.
|
|
91
|
+
"""
|
|
92
|
+
path = db_path or DB_PATH
|
|
93
|
+
if not Path(path).exists():
|
|
94
|
+
raise FileNotFoundError(
|
|
95
|
+
f"Database not found: {path}\n"
|
|
96
|
+
"Run: python tools/db/init_icdev_db.py"
|
|
97
|
+
)
|
|
98
|
+
conn = sqlite3.connect(str(path))
|
|
99
|
+
conn.row_factory = sqlite3.Row
|
|
100
|
+
conn.execute("PRAGMA journal_mode=WAL")
|
|
101
|
+
conn.execute("PRAGMA foreign_keys=ON")
|
|
102
|
+
return conn
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def _gen_id(prefix):
|
|
106
|
+
"""Generate a prefixed UUID-based identifier."""
|
|
107
|
+
return f"{prefix}{uuid.uuid4().hex[:12]}"
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
# ===================================================================
|
|
111
|
+
# Pattern loading
|
|
112
|
+
# ===================================================================
|
|
113
|
+
|
|
114
|
+
def load_decomposition_patterns(patterns_path=None):
|
|
115
|
+
"""Load decomposition patterns from the context JSON file.
|
|
116
|
+
|
|
117
|
+
Returns a dict keyed by pattern ``id`` for quick lookup. If the file
|
|
118
|
+
is missing an empty dict is returned with a warning printed to stderr.
|
|
119
|
+
"""
|
|
120
|
+
path = Path(patterns_path) if patterns_path else PATTERNS_PATH
|
|
121
|
+
if not path.exists():
|
|
122
|
+
print(f"[WARN] Decomposition patterns not found: {path}", file=sys.stderr)
|
|
123
|
+
return {}
|
|
124
|
+
with open(path, "r", encoding="utf-8") as fh:
|
|
125
|
+
data = json.load(fh)
|
|
126
|
+
patterns = {}
|
|
127
|
+
for p in data.get("patterns", []):
|
|
128
|
+
patterns[p["id"]] = p
|
|
129
|
+
return patterns
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
# ===================================================================
|
|
133
|
+
# Bounded-context detection (greedy modularity / simplified Louvain)
|
|
134
|
+
# ===================================================================
|
|
135
|
+
|
|
136
|
+
def _build_adjacency(components, dependencies):
|
|
137
|
+
"""Build adjacency list and edge-weight lookup from DB rows.
|
|
138
|
+
|
|
139
|
+
Returns:
|
|
140
|
+
adj: dict[str, set[str]] — undirected neighbour sets
|
|
141
|
+
edge_weights: dict[(str,str), float] — edge weight (sum of dep weights)
|
|
142
|
+
total_weight: float — sum of all edge weights (m)
|
|
143
|
+
degree: dict[str, float] — weighted degree per node
|
|
144
|
+
"""
|
|
145
|
+
adj = defaultdict(set)
|
|
146
|
+
edge_weights = defaultdict(float)
|
|
147
|
+
degree = defaultdict(float)
|
|
148
|
+
|
|
149
|
+
for dep in dependencies:
|
|
150
|
+
src = dep["source_component_id"]
|
|
151
|
+
tgt = dep["target_component_id"]
|
|
152
|
+
w = dep["weight"] if dep["weight"] else 1.0
|
|
153
|
+
# Undirected for modularity
|
|
154
|
+
adj[src].add(tgt)
|
|
155
|
+
adj[tgt].add(src)
|
|
156
|
+
key = tuple(sorted([src, tgt]))
|
|
157
|
+
edge_weights[key] += w
|
|
158
|
+
degree[src] += w
|
|
159
|
+
degree[tgt] += w
|
|
160
|
+
|
|
161
|
+
total_weight = sum(edge_weights.values())
|
|
162
|
+
return adj, dict(edge_weights), total_weight, dict(degree)
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def _compute_modularity(clusters, edge_weights, degree, m):
|
|
166
|
+
"""Compute modularity Q for a given clustering.
|
|
167
|
+
|
|
168
|
+
Q = sum_c [ (L_c / m) - (d_c / (2*m))^2 ]
|
|
169
|
+
|
|
170
|
+
Where L_c = total edge weight within cluster c,
|
|
171
|
+
d_c = total weighted degree of nodes in cluster c,
|
|
172
|
+
m = total edge weight.
|
|
173
|
+
"""
|
|
174
|
+
if m == 0:
|
|
175
|
+
return 0.0
|
|
176
|
+
|
|
177
|
+
# Build reverse map: node -> cluster_id
|
|
178
|
+
node_cluster = {}
|
|
179
|
+
for cid, members in clusters.items():
|
|
180
|
+
for n in members:
|
|
181
|
+
node_cluster[n] = cid
|
|
182
|
+
|
|
183
|
+
# Aggregate per-cluster
|
|
184
|
+
L = defaultdict(float) # internal edges per cluster
|
|
185
|
+
D = defaultdict(float) # total degree per cluster
|
|
186
|
+
|
|
187
|
+
for (u, v), w in edge_weights.items():
|
|
188
|
+
cu = node_cluster.get(u)
|
|
189
|
+
cv = node_cluster.get(v)
|
|
190
|
+
if cu is not None and cv is not None and cu == cv:
|
|
191
|
+
L[cu] += w
|
|
192
|
+
# degree sums
|
|
193
|
+
for node, d in degree.items():
|
|
194
|
+
c = node_cluster.get(node)
|
|
195
|
+
if c is not None:
|
|
196
|
+
D[c] += d
|
|
197
|
+
|
|
198
|
+
q = 0.0
|
|
199
|
+
for cid in clusters:
|
|
200
|
+
lc = L.get(cid, 0.0)
|
|
201
|
+
dc = D.get(cid, 0.0)
|
|
202
|
+
q += (lc / m) - (dc / (2.0 * m)) ** 2
|
|
203
|
+
|
|
204
|
+
return q
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
def detect_bounded_contexts(app_id, db_path=None):
|
|
208
|
+
"""Cluster legacy components into bounded contexts using greedy modularity.
|
|
209
|
+
|
|
210
|
+
Algorithm (simplified Louvain, single pass):
|
|
211
|
+
1. Place each component in its own cluster.
|
|
212
|
+
2. For each component, try moving it to each neighbour's cluster.
|
|
213
|
+
3. Accept the move that yields the largest modularity increase.
|
|
214
|
+
4. Repeat until no move improves Q.
|
|
215
|
+
|
|
216
|
+
Returns a list of context dicts:
|
|
217
|
+
{id, name, components: [ids], internal_edges, external_edges,
|
|
218
|
+
cohesion, coupling}
|
|
219
|
+
"""
|
|
220
|
+
conn = _get_db(db_path)
|
|
221
|
+
try:
|
|
222
|
+
components = conn.execute(
|
|
223
|
+
"SELECT id, name, component_type, qualified_name "
|
|
224
|
+
"FROM legacy_components WHERE legacy_app_id = ?",
|
|
225
|
+
(app_id,),
|
|
226
|
+
).fetchall()
|
|
227
|
+
dependencies = conn.execute(
|
|
228
|
+
"SELECT source_component_id, target_component_id, weight "
|
|
229
|
+
"FROM legacy_dependencies WHERE legacy_app_id = ?",
|
|
230
|
+
(app_id,),
|
|
231
|
+
).fetchall()
|
|
232
|
+
finally:
|
|
233
|
+
conn.close()
|
|
234
|
+
|
|
235
|
+
if not components:
|
|
236
|
+
return []
|
|
237
|
+
|
|
238
|
+
comp_map = {c["id"]: dict(c) for c in components}
|
|
239
|
+
comp_ids = list(comp_map.keys())
|
|
240
|
+
|
|
241
|
+
adj, edge_weights, m, degree = _build_adjacency(components, dependencies)
|
|
242
|
+
|
|
243
|
+
if m == 0:
|
|
244
|
+
# No edges — every component is its own context
|
|
245
|
+
results = []
|
|
246
|
+
for idx, cid in enumerate(comp_ids):
|
|
247
|
+
c = comp_map[cid]
|
|
248
|
+
results.append({
|
|
249
|
+
"id": f"ctx-{idx}",
|
|
250
|
+
"name": f"{c['component_type']}_{c['name']}",
|
|
251
|
+
"components": [cid],
|
|
252
|
+
"internal_edges": 0,
|
|
253
|
+
"external_edges": 0,
|
|
254
|
+
"cohesion": 0.0,
|
|
255
|
+
"coupling": 0.0,
|
|
256
|
+
})
|
|
257
|
+
return results
|
|
258
|
+
|
|
259
|
+
# Initial clustering: each node in its own cluster
|
|
260
|
+
clusters = {cid: {cid} for cid in comp_ids}
|
|
261
|
+
node_cluster = {cid: cid for cid in comp_ids}
|
|
262
|
+
|
|
263
|
+
improved = True
|
|
264
|
+
max_iterations = 50
|
|
265
|
+
iteration = 0
|
|
266
|
+
|
|
267
|
+
while improved and iteration < max_iterations:
|
|
268
|
+
improved = False
|
|
269
|
+
iteration += 1
|
|
270
|
+
for node in comp_ids:
|
|
271
|
+
current_cluster = node_cluster[node]
|
|
272
|
+
best_cluster = current_cluster
|
|
273
|
+
best_q = _compute_modularity(clusters, edge_weights, degree, m)
|
|
274
|
+
|
|
275
|
+
# Candidate clusters: those of neighbours
|
|
276
|
+
neighbour_clusters = set()
|
|
277
|
+
for nb in adj.get(node, set()):
|
|
278
|
+
nc = node_cluster[nb]
|
|
279
|
+
if nc != current_cluster:
|
|
280
|
+
neighbour_clusters.add(nc)
|
|
281
|
+
|
|
282
|
+
for candidate in neighbour_clusters:
|
|
283
|
+
# Tentatively move node
|
|
284
|
+
clusters[current_cluster].discard(node)
|
|
285
|
+
clusters[candidate].add(node)
|
|
286
|
+
node_cluster[node] = candidate
|
|
287
|
+
|
|
288
|
+
q = _compute_modularity(clusters, edge_weights, degree, m)
|
|
289
|
+
if q > best_q + 1e-9:
|
|
290
|
+
best_q = q
|
|
291
|
+
best_cluster = candidate
|
|
292
|
+
|
|
293
|
+
# Revert
|
|
294
|
+
clusters[candidate].discard(node)
|
|
295
|
+
clusters[current_cluster].add(node)
|
|
296
|
+
node_cluster[node] = current_cluster
|
|
297
|
+
|
|
298
|
+
if best_cluster != current_cluster:
|
|
299
|
+
# Commit the move
|
|
300
|
+
clusters[current_cluster].discard(node)
|
|
301
|
+
clusters[best_cluster].add(node)
|
|
302
|
+
node_cluster[node] = best_cluster
|
|
303
|
+
# Remove empty clusters
|
|
304
|
+
if not clusters[current_cluster]:
|
|
305
|
+
del clusters[current_cluster]
|
|
306
|
+
improved = True
|
|
307
|
+
|
|
308
|
+
# Build result contexts
|
|
309
|
+
results = []
|
|
310
|
+
for idx, (cid, members) in enumerate(clusters.items()):
|
|
311
|
+
if not members:
|
|
312
|
+
continue
|
|
313
|
+
|
|
314
|
+
# Count internal and external edges
|
|
315
|
+
internal = 0
|
|
316
|
+
external = 0
|
|
317
|
+
for (u, v), w in edge_weights.items():
|
|
318
|
+
u_in = u in members
|
|
319
|
+
v_in = v in members
|
|
320
|
+
if u_in and v_in:
|
|
321
|
+
internal += w
|
|
322
|
+
elif u_in or v_in:
|
|
323
|
+
external += w
|
|
324
|
+
|
|
325
|
+
total_edges = internal + external
|
|
326
|
+
cohesion = internal / total_edges if total_edges > 0 else 0.0
|
|
327
|
+
coupling = external / total_edges if total_edges > 0 else 0.0
|
|
328
|
+
|
|
329
|
+
# Name: dominant component_type + most common package prefix
|
|
330
|
+
types = [comp_map[m_id]["component_type"] for m_id in members if m_id in comp_map]
|
|
331
|
+
type_counts = Counter(types)
|
|
332
|
+
dominant_type = type_counts.most_common(1)[0][0] if type_counts else "module"
|
|
333
|
+
|
|
334
|
+
# Extract package prefixes from qualified_name
|
|
335
|
+
prefixes = []
|
|
336
|
+
for m_id in members:
|
|
337
|
+
qn = comp_map.get(m_id, {}).get("qualified_name", "")
|
|
338
|
+
if qn and "." in str(qn):
|
|
339
|
+
parts = str(qn).split(".")
|
|
340
|
+
if len(parts) >= 2:
|
|
341
|
+
prefixes.append(parts[-2])
|
|
342
|
+
else:
|
|
343
|
+
prefixes.append(parts[0])
|
|
344
|
+
elif qn:
|
|
345
|
+
prefixes.append(str(qn))
|
|
346
|
+
prefix_counts = Counter(prefixes)
|
|
347
|
+
common_prefix = prefix_counts.most_common(1)[0][0] if prefix_counts else f"context_{idx}"
|
|
348
|
+
|
|
349
|
+
context_name = f"{common_prefix}_{dominant_type}_context"
|
|
350
|
+
|
|
351
|
+
results.append({
|
|
352
|
+
"id": f"ctx-{idx}",
|
|
353
|
+
"name": context_name,
|
|
354
|
+
"components": sorted(members),
|
|
355
|
+
"internal_edges": internal,
|
|
356
|
+
"external_edges": external,
|
|
357
|
+
"cohesion": round(cohesion, 4),
|
|
358
|
+
"coupling": round(coupling, 4),
|
|
359
|
+
})
|
|
360
|
+
|
|
361
|
+
# Sort by size descending
|
|
362
|
+
results.sort(key=lambda x: len(x["components"]), reverse=True)
|
|
363
|
+
return results
|
|
364
|
+
|
|
365
|
+
|
|
366
|
+
# ===================================================================
|
|
367
|
+
# Service boundary suggestion
|
|
368
|
+
# ===================================================================
|
|
369
|
+
|
|
370
|
+
def suggest_service_boundaries(app_id, db_path=None):
|
|
371
|
+
"""Suggest microservice boundaries based on bounded contexts.
|
|
372
|
+
|
|
373
|
+
For each context evaluates:
|
|
374
|
+
- has_apis: context components own API endpoints
|
|
375
|
+
- owns_data: context components own distinct DB tables
|
|
376
|
+
- low_coupling: external deps < 30 % of total deps
|
|
377
|
+
- sufficient_size: context has >= 2 components
|
|
378
|
+
|
|
379
|
+
service_readiness = has_apis*0.3 + owns_data*0.3 + low_coupling*0.2 + sufficient_size*0.2
|
|
380
|
+
|
|
381
|
+
Returns list sorted by extraction_order (lowest coupling first).
|
|
382
|
+
"""
|
|
383
|
+
contexts = detect_bounded_contexts(app_id, db_path)
|
|
384
|
+
if not contexts:
|
|
385
|
+
return []
|
|
386
|
+
|
|
387
|
+
conn = _get_db(db_path)
|
|
388
|
+
try:
|
|
389
|
+
# Load APIs
|
|
390
|
+
apis = conn.execute(
|
|
391
|
+
"SELECT id, component_id, method, path FROM legacy_apis "
|
|
392
|
+
"WHERE legacy_app_id = ?",
|
|
393
|
+
(app_id,),
|
|
394
|
+
).fetchall()
|
|
395
|
+
|
|
396
|
+
# Load DB schemas (distinct tables per component via qualified_name match)
|
|
397
|
+
db_schemas = conn.execute(
|
|
398
|
+
"SELECT id, table_name, column_name FROM legacy_db_schemas "
|
|
399
|
+
"WHERE legacy_app_id = ?",
|
|
400
|
+
(app_id,),
|
|
401
|
+
).fetchall()
|
|
402
|
+
|
|
403
|
+
# Load components for table ownership heuristic
|
|
404
|
+
components = conn.execute(
|
|
405
|
+
"SELECT id, name, qualified_name FROM legacy_components "
|
|
406
|
+
"WHERE legacy_app_id = ?",
|
|
407
|
+
(app_id,),
|
|
408
|
+
).fetchall()
|
|
409
|
+
finally:
|
|
410
|
+
conn.close()
|
|
411
|
+
|
|
412
|
+
# Build lookup: component_id -> set of API paths
|
|
413
|
+
comp_apis = defaultdict(list)
|
|
414
|
+
for api in apis:
|
|
415
|
+
comp_apis[api["component_id"]].append({
|
|
416
|
+
"id": api["id"],
|
|
417
|
+
"method": api["method"],
|
|
418
|
+
"path": api["path"],
|
|
419
|
+
})
|
|
420
|
+
|
|
421
|
+
# Build lookup: component name (lower) -> set of table names
|
|
422
|
+
# Heuristic: a component "owns" tables whose name includes the component name
|
|
423
|
+
comp_names = {}
|
|
424
|
+
for c in components:
|
|
425
|
+
comp_names[c["id"]] = c["name"].lower().replace("_", "").replace("-", "")
|
|
426
|
+
|
|
427
|
+
all_tables = set()
|
|
428
|
+
for s in db_schemas:
|
|
429
|
+
all_tables.add(s["table_name"])
|
|
430
|
+
|
|
431
|
+
comp_tables = defaultdict(set)
|
|
432
|
+
for comp_id, cname in comp_names.items():
|
|
433
|
+
for tbl in all_tables:
|
|
434
|
+
tbl_lower = tbl.lower().replace("_", "").replace("-", "")
|
|
435
|
+
# Component owns table if name overlaps significantly
|
|
436
|
+
if cname in tbl_lower or tbl_lower in cname:
|
|
437
|
+
comp_tables[comp_id].add(tbl)
|
|
438
|
+
|
|
439
|
+
# Evaluate each context
|
|
440
|
+
boundaries = []
|
|
441
|
+
for ctx in contexts:
|
|
442
|
+
members = set(ctx["components"])
|
|
443
|
+
|
|
444
|
+
# APIs owned by this context
|
|
445
|
+
context_apis = []
|
|
446
|
+
for cid in members:
|
|
447
|
+
context_apis.extend(comp_apis.get(cid, []))
|
|
448
|
+
has_apis = 1.0 if len(context_apis) > 0 else 0.0
|
|
449
|
+
|
|
450
|
+
# Tables owned by this context
|
|
451
|
+
context_tables = set()
|
|
452
|
+
for cid in members:
|
|
453
|
+
context_tables.update(comp_tables.get(cid, set()))
|
|
454
|
+
owns_data = 1.0 if len(context_tables) > 0 else 0.0
|
|
455
|
+
|
|
456
|
+
# Coupling check (< 30 % external)
|
|
457
|
+
total = ctx["internal_edges"] + ctx["external_edges"]
|
|
458
|
+
coupling_ratio = ctx["external_edges"] / total if total > 0 else 0.0
|
|
459
|
+
low_coupling = 1.0 if coupling_ratio < 0.30 else 0.0
|
|
460
|
+
|
|
461
|
+
# Sufficient size
|
|
462
|
+
sufficient_size = 1.0 if len(members) >= 2 else 0.0
|
|
463
|
+
|
|
464
|
+
readiness = (
|
|
465
|
+
has_apis * 0.3
|
|
466
|
+
+ owns_data * 0.3
|
|
467
|
+
+ low_coupling * 0.2
|
|
468
|
+
+ sufficient_size * 0.2
|
|
469
|
+
)
|
|
470
|
+
|
|
471
|
+
# Generate service name from context name
|
|
472
|
+
service_name = ctx["name"].replace("_context", "_service")
|
|
473
|
+
|
|
474
|
+
boundaries.append({
|
|
475
|
+
"service_name": service_name,
|
|
476
|
+
"context_id": ctx["id"],
|
|
477
|
+
"components": ctx["components"],
|
|
478
|
+
"apis": context_apis,
|
|
479
|
+
"tables": sorted(context_tables),
|
|
480
|
+
"readiness_score": round(readiness, 4),
|
|
481
|
+
"coupling_ratio": round(coupling_ratio, 4),
|
|
482
|
+
"has_apis": bool(has_apis),
|
|
483
|
+
"owns_data": bool(owns_data),
|
|
484
|
+
"low_coupling": bool(low_coupling),
|
|
485
|
+
"sufficient_size": bool(sufficient_size),
|
|
486
|
+
"extraction_order": 0, # filled below
|
|
487
|
+
})
|
|
488
|
+
|
|
489
|
+
# Sort by coupling_ratio ascending (least coupled first)
|
|
490
|
+
boundaries.sort(key=lambda b: b["coupling_ratio"])
|
|
491
|
+
for idx, b in enumerate(boundaries):
|
|
492
|
+
b["extraction_order"] = idx + 1
|
|
493
|
+
|
|
494
|
+
return boundaries
|
|
495
|
+
|
|
496
|
+
|
|
497
|
+
# ===================================================================
|
|
498
|
+
# Decomposition plan generation
|
|
499
|
+
# ===================================================================
|
|
500
|
+
|
|
501
|
+
def generate_decomposition_plan(app_id, target_architecture="microservices", db_path=None):
|
|
502
|
+
"""Generate an ordered decomposition extraction plan.
|
|
503
|
+
|
|
504
|
+
Phases:
|
|
505
|
+
0. Analysis & shared-kernel extraction
|
|
506
|
+
1..N. Service extraction in extraction_order
|
|
507
|
+
N+1. Anti-corruption layer tasks between services
|
|
508
|
+
N+2. Validation & cutover
|
|
509
|
+
|
|
510
|
+
Returns a plan dict with phases and tasks.
|
|
511
|
+
"""
|
|
512
|
+
boundaries = suggest_service_boundaries(app_id, db_path)
|
|
513
|
+
patterns = load_decomposition_patterns()
|
|
514
|
+
|
|
515
|
+
plan = {
|
|
516
|
+
"app_id": app_id,
|
|
517
|
+
"target_architecture": target_architecture,
|
|
518
|
+
"generated_at": datetime.now(timezone.utc).isoformat() + "Z",
|
|
519
|
+
"total_services": len(boundaries),
|
|
520
|
+
"phases": [],
|
|
521
|
+
"summary": {},
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
task_counter = 0
|
|
525
|
+
|
|
526
|
+
# --- Phase 0: Analysis & shared kernel ---
|
|
527
|
+
phase0_tasks = []
|
|
528
|
+
phase0_tasks.append({
|
|
529
|
+
"task_id": f"decomp-task-{task_counter}",
|
|
530
|
+
"task_type": "analyze",
|
|
531
|
+
"title": "Analyze monolith structure and dependency graph",
|
|
532
|
+
"description": "Map all components, dependencies, APIs, and DB schemas. "
|
|
533
|
+
"Identify shared utilities used across multiple bounded contexts.",
|
|
534
|
+
"priority": "critical",
|
|
535
|
+
"estimated_hours": 8,
|
|
536
|
+
})
|
|
537
|
+
task_counter += 1
|
|
538
|
+
|
|
539
|
+
# Identify shared-kernel candidates: components referenced by multiple contexts
|
|
540
|
+
comp_to_contexts = defaultdict(list)
|
|
541
|
+
for b in boundaries:
|
|
542
|
+
for cid in b["components"]:
|
|
543
|
+
comp_to_contexts[cid].append(b["service_name"])
|
|
544
|
+
shared_kernel_comps = [
|
|
545
|
+
cid for cid, ctxs in comp_to_contexts.items() if len(ctxs) > 1
|
|
546
|
+
]
|
|
547
|
+
|
|
548
|
+
if shared_kernel_comps:
|
|
549
|
+
phase0_tasks.append({
|
|
550
|
+
"task_id": f"decomp-task-{task_counter}",
|
|
551
|
+
"task_type": "decompose",
|
|
552
|
+
"title": "Extract shared kernel library",
|
|
553
|
+
"description": (
|
|
554
|
+
f"Extract {len(shared_kernel_comps)} shared components into a "
|
|
555
|
+
"versioned shared kernel library with semantic versioning. "
|
|
556
|
+
"Components: " + ", ".join(shared_kernel_comps[:10])
|
|
557
|
+
+ ("..." if len(shared_kernel_comps) > 10 else "")
|
|
558
|
+
),
|
|
559
|
+
"priority": "high",
|
|
560
|
+
"estimated_hours": max(4, len(shared_kernel_comps) * 2),
|
|
561
|
+
})
|
|
562
|
+
task_counter += 1
|
|
563
|
+
|
|
564
|
+
plan["phases"].append({
|
|
565
|
+
"phase": 0,
|
|
566
|
+
"name": "Analysis & Shared Kernel Extraction",
|
|
567
|
+
"tasks": phase0_tasks,
|
|
568
|
+
})
|
|
569
|
+
|
|
570
|
+
# --- Phases 1..N: Service extraction (ordered) ---
|
|
571
|
+
for boundary in boundaries:
|
|
572
|
+
phase_tasks = []
|
|
573
|
+
svc = boundary["service_name"]
|
|
574
|
+
order = boundary["extraction_order"]
|
|
575
|
+
|
|
576
|
+
# Analyze
|
|
577
|
+
phase_tasks.append({
|
|
578
|
+
"task_id": f"decomp-task-{task_counter}",
|
|
579
|
+
"task_type": "analyze",
|
|
580
|
+
"title": f"Analyze {svc} boundary components",
|
|
581
|
+
"description": f"Deep analysis of {len(boundary['components'])} components "
|
|
582
|
+
f"in {svc}. Readiness score: {boundary['readiness_score']}.",
|
|
583
|
+
"priority": "high",
|
|
584
|
+
"estimated_hours": 4,
|
|
585
|
+
})
|
|
586
|
+
task_counter += 1
|
|
587
|
+
|
|
588
|
+
# Create API
|
|
589
|
+
if boundary["apis"]:
|
|
590
|
+
phase_tasks.append({
|
|
591
|
+
"task_id": f"decomp-task-{task_counter}",
|
|
592
|
+
"task_type": "create_api",
|
|
593
|
+
"title": f"Define API contracts for {svc}",
|
|
594
|
+
"description": f"Define OpenAPI spec for {len(boundary['apis'])} endpoints "
|
|
595
|
+
f"migrating to {svc}.",
|
|
596
|
+
"priority": "high",
|
|
597
|
+
"estimated_hours": 6,
|
|
598
|
+
})
|
|
599
|
+
task_counter += 1
|
|
600
|
+
|
|
601
|
+
# Create ACL
|
|
602
|
+
if boundary["coupling_ratio"] > 0.0:
|
|
603
|
+
phase_tasks.append({
|
|
604
|
+
"task_id": f"decomp-task-{task_counter}",
|
|
605
|
+
"task_type": "create_acl",
|
|
606
|
+
"title": f"Create anti-corruption layer for {svc}",
|
|
607
|
+
"description": f"Build adapter layer to translate between legacy and "
|
|
608
|
+
f"{svc} domain models. Coupling ratio: "
|
|
609
|
+
f"{boundary['coupling_ratio']}.",
|
|
610
|
+
"priority": "high",
|
|
611
|
+
"estimated_hours": 8,
|
|
612
|
+
})
|
|
613
|
+
task_counter += 1
|
|
614
|
+
|
|
615
|
+
# Extract service
|
|
616
|
+
phase_tasks.append({
|
|
617
|
+
"task_id": f"decomp-task-{task_counter}",
|
|
618
|
+
"task_type": "extract_service",
|
|
619
|
+
"title": f"Extract {svc} from monolith",
|
|
620
|
+
"description": f"Move {len(boundary['components'])} components into "
|
|
621
|
+
f"standalone {target_architecture} service with its own "
|
|
622
|
+
f"build and deploy pipeline.",
|
|
623
|
+
"priority": "critical",
|
|
624
|
+
"estimated_hours": max(8, len(boundary["components"]) * 3),
|
|
625
|
+
})
|
|
626
|
+
task_counter += 1
|
|
627
|
+
|
|
628
|
+
# Database migration if service owns tables
|
|
629
|
+
if boundary["tables"]:
|
|
630
|
+
phase_tasks.append({
|
|
631
|
+
"task_id": f"decomp-task-{task_counter}",
|
|
632
|
+
"task_type": "migrate_schema",
|
|
633
|
+
"title": f"Migrate database schema for {svc}",
|
|
634
|
+
"description": f"Isolate {len(boundary['tables'])} tables into "
|
|
635
|
+
f"dedicated database for {svc}: "
|
|
636
|
+
+ ", ".join(boundary["tables"][:5])
|
|
637
|
+
+ ("..." if len(boundary["tables"]) > 5 else ""),
|
|
638
|
+
"priority": "high",
|
|
639
|
+
"estimated_hours": max(4, len(boundary["tables"]) * 2),
|
|
640
|
+
})
|
|
641
|
+
task_counter += 1
|
|
642
|
+
|
|
643
|
+
# Generate tests
|
|
644
|
+
phase_tasks.append({
|
|
645
|
+
"task_id": f"decomp-task-{task_counter}",
|
|
646
|
+
"task_type": "generate_test",
|
|
647
|
+
"title": f"Generate integration tests for {svc}",
|
|
648
|
+
"description": f"Create BDD/TDD test suites verifying {svc} correctness "
|
|
649
|
+
f"against legacy behavior (contract tests + regression).",
|
|
650
|
+
"priority": "high",
|
|
651
|
+
"estimated_hours": 6,
|
|
652
|
+
})
|
|
653
|
+
task_counter += 1
|
|
654
|
+
|
|
655
|
+
# Validate
|
|
656
|
+
phase_tasks.append({
|
|
657
|
+
"task_id": f"decomp-task-{task_counter}",
|
|
658
|
+
"task_type": "validate",
|
|
659
|
+
"title": f"Validate {svc} extraction",
|
|
660
|
+
"description": f"Run parallel validation comparing legacy and extracted "
|
|
661
|
+
f"{svc} responses. Verify data consistency and performance.",
|
|
662
|
+
"priority": "critical",
|
|
663
|
+
"estimated_hours": 4,
|
|
664
|
+
})
|
|
665
|
+
task_counter += 1
|
|
666
|
+
|
|
667
|
+
plan["phases"].append({
|
|
668
|
+
"phase": order,
|
|
669
|
+
"name": f"Extract {svc}",
|
|
670
|
+
"service": svc,
|
|
671
|
+
"readiness_score": boundary["readiness_score"],
|
|
672
|
+
"tasks": phase_tasks,
|
|
673
|
+
})
|
|
674
|
+
|
|
675
|
+
# --- Final phase: Cross-service ACL + cutover ---
|
|
676
|
+
final_tasks = []
|
|
677
|
+
# ACL tasks between every pair of services that share edges
|
|
678
|
+
for i, b1 in enumerate(boundaries):
|
|
679
|
+
for b2 in boundaries[i + 1:]:
|
|
680
|
+
# Check if they share external edges (simplified: both have coupling)
|
|
681
|
+
if b1["coupling_ratio"] > 0 and b2["coupling_ratio"] > 0:
|
|
682
|
+
final_tasks.append({
|
|
683
|
+
"task_id": f"decomp-task-{task_counter}",
|
|
684
|
+
"task_type": "create_acl",
|
|
685
|
+
"title": f"ACL: {b1['service_name']} <-> {b2['service_name']}",
|
|
686
|
+
"description": "Create cross-service anti-corruption layer adapters "
|
|
687
|
+
"for communication between extracted services.",
|
|
688
|
+
"priority": "medium",
|
|
689
|
+
"estimated_hours": 6,
|
|
690
|
+
})
|
|
691
|
+
task_counter += 1
|
|
692
|
+
|
|
693
|
+
final_tasks.append({
|
|
694
|
+
"task_id": f"decomp-task-{task_counter}",
|
|
695
|
+
"task_type": "validate",
|
|
696
|
+
"title": "End-to-end system validation",
|
|
697
|
+
"description": "Full integration test of all extracted services with ACLs, "
|
|
698
|
+
"API gateway routing, and database isolation verified.",
|
|
699
|
+
"priority": "critical",
|
|
700
|
+
"estimated_hours": 12,
|
|
701
|
+
})
|
|
702
|
+
task_counter += 1
|
|
703
|
+
|
|
704
|
+
final_tasks.append({
|
|
705
|
+
"task_id": f"decomp-task-{task_counter}",
|
|
706
|
+
"task_type": "cutover",
|
|
707
|
+
"title": "Production cutover and legacy decommission",
|
|
708
|
+
"description": "Switch production traffic to modern services via strangler fig "
|
|
709
|
+
"facade. Decommission legacy monolith after validation period.",
|
|
710
|
+
"priority": "critical",
|
|
711
|
+
"estimated_hours": 8,
|
|
712
|
+
})
|
|
713
|
+
task_counter += 1
|
|
714
|
+
|
|
715
|
+
plan["phases"].append({
|
|
716
|
+
"phase": len(boundaries) + 1,
|
|
717
|
+
"name": "Cross-Service Integration & Cutover",
|
|
718
|
+
"tasks": final_tasks,
|
|
719
|
+
})
|
|
720
|
+
|
|
721
|
+
# Summary
|
|
722
|
+
total_hours = sum(
|
|
723
|
+
t["estimated_hours"]
|
|
724
|
+
for phase in plan["phases"]
|
|
725
|
+
for t in phase["tasks"]
|
|
726
|
+
)
|
|
727
|
+
plan["summary"] = {
|
|
728
|
+
"total_phases": len(plan["phases"]),
|
|
729
|
+
"total_tasks": task_counter,
|
|
730
|
+
"total_estimated_hours": total_hours,
|
|
731
|
+
"shared_kernel_components": len(shared_kernel_comps),
|
|
732
|
+
"applicable_patterns": [
|
|
733
|
+
pid for pid in patterns
|
|
734
|
+
if pid in ("ddd_bounded_contexts", "strangler_fig", "anti_corruption_layer",
|
|
735
|
+
"database_per_service", "shared_kernel")
|
|
736
|
+
],
|
|
737
|
+
}
|
|
738
|
+
return plan
|
|
739
|
+
|
|
740
|
+
|
|
741
|
+
# ===================================================================
|
|
742
|
+
# Anti-corruption layer generation
|
|
743
|
+
# ===================================================================
|
|
744
|
+
|
|
745
|
+
def generate_anti_corruption_layer(app_id, service_boundary, db_path=None):
|
|
746
|
+
"""Generate ACL interface skeletons for a service boundary.
|
|
747
|
+
|
|
748
|
+
Identifies cross-boundary dependencies and generates adapter interface
|
|
749
|
+
definitions for each.
|
|
750
|
+
|
|
751
|
+
Args:
|
|
752
|
+
app_id: Legacy application ID.
|
|
753
|
+
service_boundary: A boundary dict from suggest_service_boundaries.
|
|
754
|
+
|
|
755
|
+
Returns dict: {interfaces: [{name, methods, legacy_side, modern_side}]}
|
|
756
|
+
"""
|
|
757
|
+
conn = _get_db(db_path)
|
|
758
|
+
try:
|
|
759
|
+
members = set(service_boundary.get("components", []))
|
|
760
|
+
if not members:
|
|
761
|
+
return {"interfaces": []}
|
|
762
|
+
|
|
763
|
+
placeholders = ",".join("?" for _ in members)
|
|
764
|
+
|
|
765
|
+
# Cross-boundary outgoing deps
|
|
766
|
+
outgoing = conn.execute(
|
|
767
|
+
f"SELECT d.source_component_id, d.target_component_id, "
|
|
768
|
+
f"d.dependency_type, d.weight, "
|
|
769
|
+
f"cs.name AS source_name, ct.name AS target_name, "
|
|
770
|
+
f"ct.qualified_name AS target_qualified "
|
|
771
|
+
f"FROM legacy_dependencies d "
|
|
772
|
+
f"JOIN legacy_components cs ON d.source_component_id = cs.id "
|
|
773
|
+
f"JOIN legacy_components ct ON d.target_component_id = ct.id "
|
|
774
|
+
f"WHERE d.legacy_app_id = ? "
|
|
775
|
+
f"AND d.source_component_id IN ({placeholders}) "
|
|
776
|
+
f"AND d.target_component_id NOT IN ({placeholders})",
|
|
777
|
+
(app_id, *members, *members),
|
|
778
|
+
).fetchall()
|
|
779
|
+
|
|
780
|
+
# Cross-boundary incoming deps
|
|
781
|
+
incoming = conn.execute(
|
|
782
|
+
f"SELECT d.source_component_id, d.target_component_id, "
|
|
783
|
+
f"d.dependency_type, d.weight, "
|
|
784
|
+
f"cs.name AS source_name, ct.name AS target_name, "
|
|
785
|
+
f"cs.qualified_name AS source_qualified "
|
|
786
|
+
f"FROM legacy_dependencies d "
|
|
787
|
+
f"JOIN legacy_components cs ON d.source_component_id = cs.id "
|
|
788
|
+
f"JOIN legacy_components ct ON d.target_component_id = ct.id "
|
|
789
|
+
f"WHERE d.legacy_app_id = ? "
|
|
790
|
+
f"AND d.target_component_id IN ({placeholders}) "
|
|
791
|
+
f"AND d.source_component_id NOT IN ({placeholders})",
|
|
792
|
+
(app_id, *members, *members),
|
|
793
|
+
).fetchall()
|
|
794
|
+
|
|
795
|
+
# Load app info for language hint
|
|
796
|
+
app_row = conn.execute(
|
|
797
|
+
"SELECT primary_language FROM legacy_applications WHERE id = ?",
|
|
798
|
+
(app_id,),
|
|
799
|
+
).fetchone()
|
|
800
|
+
finally:
|
|
801
|
+
conn.close()
|
|
802
|
+
|
|
803
|
+
language = app_row["primary_language"] if app_row else "python"
|
|
804
|
+
svc_name = service_boundary.get("service_name", "unknown_service")
|
|
805
|
+
|
|
806
|
+
interfaces = []
|
|
807
|
+
|
|
808
|
+
# Group outgoing by target component
|
|
809
|
+
outgoing_grouped = defaultdict(list)
|
|
810
|
+
for dep in outgoing:
|
|
811
|
+
outgoing_grouped[dep["target_component_id"]].append(dep)
|
|
812
|
+
|
|
813
|
+
for target_id, deps in outgoing_grouped.items():
|
|
814
|
+
target_name = deps[0]["target_name"]
|
|
815
|
+
target_qual = deps[0]["target_qualified"] or target_name
|
|
816
|
+
dep_types = [d["dependency_type"] for d in deps]
|
|
817
|
+
|
|
818
|
+
methods = []
|
|
819
|
+
for dep in deps:
|
|
820
|
+
dtype = dep["dependency_type"]
|
|
821
|
+
dep["source_name"]
|
|
822
|
+
if dtype == "method_call":
|
|
823
|
+
methods.append(f"call_{target_name.lower()}(request)")
|
|
824
|
+
elif dtype == "import":
|
|
825
|
+
methods.append(f"get_{target_name.lower()}_adapter()")
|
|
826
|
+
elif dtype in ("inheritance", "composition"):
|
|
827
|
+
methods.append(f"adapt_{target_name.lower()}()")
|
|
828
|
+
else:
|
|
829
|
+
methods.append(f"translate_{target_name.lower()}(data)")
|
|
830
|
+
|
|
831
|
+
# Deduplicate methods
|
|
832
|
+
methods = sorted(set(methods))
|
|
833
|
+
|
|
834
|
+
adapter_name = f"{svc_name}To{_to_pascal(target_name)}Adapter"
|
|
835
|
+
interfaces.append({
|
|
836
|
+
"name": adapter_name,
|
|
837
|
+
"methods": methods,
|
|
838
|
+
"legacy_side": target_qual,
|
|
839
|
+
"modern_side": f"{svc_name}.adapters.{adapter_name}",
|
|
840
|
+
"dependency_types": sorted(set(dep_types)),
|
|
841
|
+
"direction": "outgoing",
|
|
842
|
+
})
|
|
843
|
+
|
|
844
|
+
# Group incoming by source component
|
|
845
|
+
incoming_grouped = defaultdict(list)
|
|
846
|
+
for dep in incoming:
|
|
847
|
+
incoming_grouped[dep["source_component_id"]].append(dep)
|
|
848
|
+
|
|
849
|
+
for source_id, deps in incoming_grouped.items():
|
|
850
|
+
source_name = deps[0]["source_name"]
|
|
851
|
+
source_qual = deps[0]["source_qualified"] or source_name
|
|
852
|
+
dep_types = [d["dependency_type"] for d in deps]
|
|
853
|
+
|
|
854
|
+
methods = []
|
|
855
|
+
for dep in deps:
|
|
856
|
+
dtype = dep["dependency_type"]
|
|
857
|
+
tgt_name = dep["target_name"]
|
|
858
|
+
if dtype == "method_call":
|
|
859
|
+
methods.append(f"handle_{tgt_name.lower()}_call(request)")
|
|
860
|
+
elif dtype == "import":
|
|
861
|
+
methods.append(f"expose_{tgt_name.lower()}_interface()")
|
|
862
|
+
else:
|
|
863
|
+
methods.append(f"translate_from_{source_name.lower()}(data)")
|
|
864
|
+
|
|
865
|
+
methods = sorted(set(methods))
|
|
866
|
+
|
|
867
|
+
adapter_name = f"{_to_pascal(source_name)}To{svc_name}Adapter"
|
|
868
|
+
interfaces.append({
|
|
869
|
+
"name": adapter_name,
|
|
870
|
+
"methods": methods,
|
|
871
|
+
"legacy_side": source_qual,
|
|
872
|
+
"modern_side": f"{svc_name}.adapters.{adapter_name}",
|
|
873
|
+
"dependency_types": sorted(set(dep_types)),
|
|
874
|
+
"direction": "incoming",
|
|
875
|
+
})
|
|
876
|
+
|
|
877
|
+
return {
|
|
878
|
+
"service": svc_name,
|
|
879
|
+
"language": language,
|
|
880
|
+
"interface_count": len(interfaces),
|
|
881
|
+
"interfaces": interfaces,
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
|
|
885
|
+
def _to_pascal(name):
|
|
886
|
+
"""Convert a snake_case or kebab-case name to PascalCase."""
|
|
887
|
+
return "".join(
|
|
888
|
+
part.capitalize()
|
|
889
|
+
for part in name.replace("-", "_").split("_")
|
|
890
|
+
)
|
|
891
|
+
|
|
892
|
+
|
|
893
|
+
# ===================================================================
|
|
894
|
+
# API facade / gateway routing generation
|
|
895
|
+
# ===================================================================
|
|
896
|
+
|
|
897
|
+
def generate_api_facade(app_id, service_boundary=None, db_path=None):
|
|
898
|
+
"""Generate API facade routing configuration.
|
|
899
|
+
|
|
900
|
+
Maps legacy endpoints to service assignments so an API gateway can
|
|
901
|
+
route traffic to the correct extracted microservice.
|
|
902
|
+
|
|
903
|
+
If service_boundary is None, generates routing for ALL boundaries.
|
|
904
|
+
|
|
905
|
+
Returns:
|
|
906
|
+
{routes: [{path, method, service, legacy_path}], config: {...}}
|
|
907
|
+
"""
|
|
908
|
+
boundaries = (
|
|
909
|
+
[service_boundary] if service_boundary
|
|
910
|
+
else suggest_service_boundaries(app_id, db_path)
|
|
911
|
+
)
|
|
912
|
+
|
|
913
|
+
conn = _get_db(db_path)
|
|
914
|
+
try:
|
|
915
|
+
all_apis = conn.execute(
|
|
916
|
+
"SELECT id, component_id, method, path FROM legacy_apis "
|
|
917
|
+
"WHERE legacy_app_id = ?",
|
|
918
|
+
(app_id,),
|
|
919
|
+
).fetchall()
|
|
920
|
+
finally:
|
|
921
|
+
conn.close()
|
|
922
|
+
|
|
923
|
+
# Build component -> service mapping
|
|
924
|
+
comp_to_service = {}
|
|
925
|
+
for b in boundaries:
|
|
926
|
+
for cid in b["components"]:
|
|
927
|
+
comp_to_service[cid] = b["service_name"]
|
|
928
|
+
|
|
929
|
+
routes = []
|
|
930
|
+
unrouted = []
|
|
931
|
+
service_prefixes = defaultdict(set)
|
|
932
|
+
|
|
933
|
+
for api in all_apis:
|
|
934
|
+
service = comp_to_service.get(api["component_id"])
|
|
935
|
+
path = api["path"]
|
|
936
|
+
method = api["method"]
|
|
937
|
+
|
|
938
|
+
if service:
|
|
939
|
+
routes.append({
|
|
940
|
+
"path": path,
|
|
941
|
+
"method": method,
|
|
942
|
+
"service": service,
|
|
943
|
+
"legacy_path": path,
|
|
944
|
+
})
|
|
945
|
+
# Extract first path segment as prefix
|
|
946
|
+
parts = [p for p in path.split("/") if p]
|
|
947
|
+
if parts:
|
|
948
|
+
service_prefixes[service].add(f"/{parts[0]}")
|
|
949
|
+
else:
|
|
950
|
+
unrouted.append({
|
|
951
|
+
"path": path,
|
|
952
|
+
"method": method,
|
|
953
|
+
"service": "legacy_monolith",
|
|
954
|
+
"legacy_path": path,
|
|
955
|
+
})
|
|
956
|
+
|
|
957
|
+
# Build prefix routing config
|
|
958
|
+
prefix_routing = {}
|
|
959
|
+
for svc, prefixes in service_prefixes.items():
|
|
960
|
+
for prefix in sorted(prefixes):
|
|
961
|
+
prefix_routing[prefix] = svc
|
|
962
|
+
|
|
963
|
+
return {
|
|
964
|
+
"app_id": app_id,
|
|
965
|
+
"total_routes": len(routes),
|
|
966
|
+
"unrouted_endpoints": len(unrouted),
|
|
967
|
+
"routes": sorted(routes, key=lambda r: r["path"]),
|
|
968
|
+
"unrouted": sorted(unrouted, key=lambda r: r["path"]),
|
|
969
|
+
"prefix_routing": prefix_routing,
|
|
970
|
+
"config": {
|
|
971
|
+
"default_backend": "legacy_monolith",
|
|
972
|
+
"routing_strategy": "path_prefix",
|
|
973
|
+
"health_check_path": "/health",
|
|
974
|
+
"timeout_seconds": 30,
|
|
975
|
+
},
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
|
|
979
|
+
# ===================================================================
|
|
980
|
+
# Effort estimation
|
|
981
|
+
# ===================================================================
|
|
982
|
+
|
|
983
|
+
def estimate_decomposition_effort(app_id, db_path=None):
|
|
984
|
+
"""Estimate decomposition effort in hours per service.
|
|
985
|
+
|
|
986
|
+
Per service:
|
|
987
|
+
base_hours = sum(component LOC) / 15 (slower than greenfield)
|
|
988
|
+
complexity_factor = avg(cyclomatic_complexity) / 5
|
|
989
|
+
adjusted_hours = base_hours * max(1.0, complexity_factor)
|
|
990
|
+
acl_overhead = 20 hours per cross-boundary interface
|
|
991
|
+
testing = 30% of adjusted_hours
|
|
992
|
+
total = adjusted_hours + acl_overhead + testing
|
|
993
|
+
|
|
994
|
+
Returns per-service and total estimates.
|
|
995
|
+
"""
|
|
996
|
+
boundaries = suggest_service_boundaries(app_id, db_path)
|
|
997
|
+
if not boundaries:
|
|
998
|
+
return {"services": [], "total_hours": 0, "total_ftes_months": 0}
|
|
999
|
+
|
|
1000
|
+
conn = _get_db(db_path)
|
|
1001
|
+
try:
|
|
1002
|
+
components = conn.execute(
|
|
1003
|
+
"SELECT id, loc, cyclomatic_complexity FROM legacy_components "
|
|
1004
|
+
"WHERE legacy_app_id = ?",
|
|
1005
|
+
(app_id,),
|
|
1006
|
+
).fetchall()
|
|
1007
|
+
finally:
|
|
1008
|
+
conn.close()
|
|
1009
|
+
|
|
1010
|
+
comp_data = {c["id"]: dict(c) for c in components}
|
|
1011
|
+
|
|
1012
|
+
service_estimates = []
|
|
1013
|
+
grand_total = 0.0
|
|
1014
|
+
|
|
1015
|
+
for boundary in boundaries:
|
|
1016
|
+
members = boundary["components"]
|
|
1017
|
+
total_loc = sum(comp_data.get(m, {}).get("loc", 0) or 0 for m in members)
|
|
1018
|
+
complexities = [
|
|
1019
|
+
comp_data.get(m, {}).get("cyclomatic_complexity", 0) or 0
|
|
1020
|
+
for m in members
|
|
1021
|
+
]
|
|
1022
|
+
avg_complexity = (
|
|
1023
|
+
sum(complexities) / len(complexities) if complexities else 1.0
|
|
1024
|
+
)
|
|
1025
|
+
|
|
1026
|
+
base_hours = total_loc / 15.0
|
|
1027
|
+
complexity_factor = max(1.0, avg_complexity / 5.0)
|
|
1028
|
+
adjusted_hours = base_hours * complexity_factor
|
|
1029
|
+
|
|
1030
|
+
# ACL overhead: count cross-boundary interfaces
|
|
1031
|
+
acl = generate_anti_corruption_layer(app_id, boundary, db_path)
|
|
1032
|
+
acl_interface_count = acl.get("interface_count", 0)
|
|
1033
|
+
acl_overhead = acl_interface_count * 20.0
|
|
1034
|
+
|
|
1035
|
+
# Testing overhead: 30 % of adjusted hours
|
|
1036
|
+
testing_hours = adjusted_hours * 0.30
|
|
1037
|
+
|
|
1038
|
+
total = adjusted_hours + acl_overhead + testing_hours
|
|
1039
|
+
|
|
1040
|
+
service_estimates.append({
|
|
1041
|
+
"service_name": boundary["service_name"],
|
|
1042
|
+
"extraction_order": boundary["extraction_order"],
|
|
1043
|
+
"component_count": len(members),
|
|
1044
|
+
"total_loc": total_loc,
|
|
1045
|
+
"avg_complexity": round(avg_complexity, 2),
|
|
1046
|
+
"base_hours": round(base_hours, 1),
|
|
1047
|
+
"complexity_factor": round(complexity_factor, 2),
|
|
1048
|
+
"adjusted_hours": round(adjusted_hours, 1),
|
|
1049
|
+
"acl_interfaces": acl_interface_count,
|
|
1050
|
+
"acl_overhead_hours": round(acl_overhead, 1),
|
|
1051
|
+
"testing_hours": round(testing_hours, 1),
|
|
1052
|
+
"total_hours": round(total, 1),
|
|
1053
|
+
})
|
|
1054
|
+
grand_total += total
|
|
1055
|
+
|
|
1056
|
+
# FTE-months (assuming 160 hours/month)
|
|
1057
|
+
fte_months = grand_total / 160.0 if grand_total > 0 else 0.0
|
|
1058
|
+
|
|
1059
|
+
return {
|
|
1060
|
+
"app_id": app_id,
|
|
1061
|
+
"services": sorted(service_estimates, key=lambda s: s["extraction_order"]),
|
|
1062
|
+
"total_hours": round(grand_total, 1),
|
|
1063
|
+
"total_ftes_months": round(fte_months, 1),
|
|
1064
|
+
"assumptions": {
|
|
1065
|
+
"loc_per_hour": 15,
|
|
1066
|
+
"baseline_complexity_divisor": 5,
|
|
1067
|
+
"acl_hours_per_interface": 20,
|
|
1068
|
+
"testing_overhead_pct": 30,
|
|
1069
|
+
"fte_hours_per_month": 160,
|
|
1070
|
+
},
|
|
1071
|
+
}
|
|
1072
|
+
|
|
1073
|
+
|
|
1074
|
+
# ===================================================================
|
|
1075
|
+
# Migration plan persistence
|
|
1076
|
+
# ===================================================================
|
|
1077
|
+
|
|
1078
|
+
def create_migration_plan(
|
|
1079
|
+
project_id,
|
|
1080
|
+
app_id,
|
|
1081
|
+
strategy,
|
|
1082
|
+
target_lang=None,
|
|
1083
|
+
target_framework=None,
|
|
1084
|
+
target_db=None,
|
|
1085
|
+
target_arch="microservices",
|
|
1086
|
+
approach="strangler_fig",
|
|
1087
|
+
db_path=None,
|
|
1088
|
+
):
|
|
1089
|
+
"""Create a migration plan with tasks in the ICDEV database.
|
|
1090
|
+
|
|
1091
|
+
Generates appropriate tasks based on strategy:
|
|
1092
|
+
rehost — containerize, deploy
|
|
1093
|
+
replatform — containerize, db-migrate, deploy
|
|
1094
|
+
refactor — upgrade-version, upgrade-framework, test per component
|
|
1095
|
+
rearchitect — full decomposition tasks from generate_decomposition_plan
|
|
1096
|
+
retire — document, decommission
|
|
1097
|
+
retain — document only
|
|
1098
|
+
|
|
1099
|
+
Returns the plan dict with all tasks.
|
|
1100
|
+
"""
|
|
1101
|
+
if strategy not in VALID_STRATEGIES:
|
|
1102
|
+
raise ValueError(
|
|
1103
|
+
f"Invalid strategy '{strategy}'. Must be one of: {VALID_STRATEGIES}"
|
|
1104
|
+
)
|
|
1105
|
+
if approach not in VALID_APPROACHES:
|
|
1106
|
+
raise ValueError(
|
|
1107
|
+
f"Invalid approach '{approach}'. Must be one of: {VALID_APPROACHES}"
|
|
1108
|
+
)
|
|
1109
|
+
if target_arch and target_arch not in VALID_ARCHITECTURES:
|
|
1110
|
+
raise ValueError(
|
|
1111
|
+
f"Invalid architecture '{target_arch}'. Must be one of: {VALID_ARCHITECTURES}"
|
|
1112
|
+
)
|
|
1113
|
+
|
|
1114
|
+
conn = _get_db(db_path)
|
|
1115
|
+
try:
|
|
1116
|
+
# Verify app exists
|
|
1117
|
+
app_row = conn.execute(
|
|
1118
|
+
"SELECT id, name FROM legacy_applications WHERE id = ?",
|
|
1119
|
+
(app_id,),
|
|
1120
|
+
).fetchone()
|
|
1121
|
+
if not app_row:
|
|
1122
|
+
raise ValueError(f"Legacy application not found: {app_id}")
|
|
1123
|
+
|
|
1124
|
+
app_name = app_row["name"]
|
|
1125
|
+
plan_id = _gen_id("mplan-")
|
|
1126
|
+
plan_name = f"{strategy}_{app_name}_{datetime.now(timezone.utc).strftime('%Y%m%d')}"
|
|
1127
|
+
now = datetime.now(timezone.utc).isoformat() + "Z"
|
|
1128
|
+
|
|
1129
|
+
tasks = []
|
|
1130
|
+
|
|
1131
|
+
if strategy == "rearchitect":
|
|
1132
|
+
# Full decomposition
|
|
1133
|
+
decomp = generate_decomposition_plan(app_id, target_arch, db_path)
|
|
1134
|
+
task_order = 0
|
|
1135
|
+
prev_task_id = None
|
|
1136
|
+
|
|
1137
|
+
for phase in decomp.get("phases", []):
|
|
1138
|
+
for dtask in phase.get("tasks", []):
|
|
1139
|
+
task_id = _gen_id("mtask-")
|
|
1140
|
+
deps = json.dumps([prev_task_id] if prev_task_id else [])
|
|
1141
|
+
tasks.append({
|
|
1142
|
+
"id": task_id,
|
|
1143
|
+
"plan_id": plan_id,
|
|
1144
|
+
"legacy_component_id": None,
|
|
1145
|
+
"task_type": dtask["task_type"],
|
|
1146
|
+
"title": dtask["title"],
|
|
1147
|
+
"description": dtask.get("description", ""),
|
|
1148
|
+
"priority": dtask.get("priority", "medium"),
|
|
1149
|
+
"status": "pending",
|
|
1150
|
+
"estimated_hours": dtask.get("estimated_hours", 4),
|
|
1151
|
+
"dependencies": deps,
|
|
1152
|
+
"created_at": now,
|
|
1153
|
+
})
|
|
1154
|
+
prev_task_id = task_id
|
|
1155
|
+
task_order += 1
|
|
1156
|
+
else:
|
|
1157
|
+
# Strategy-based tasks per component
|
|
1158
|
+
components = conn.execute(
|
|
1159
|
+
"SELECT id, name FROM legacy_components WHERE legacy_app_id = ?",
|
|
1160
|
+
(app_id,),
|
|
1161
|
+
).fetchall()
|
|
1162
|
+
|
|
1163
|
+
templates = STRATEGY_TASK_TEMPLATES.get(strategy, [])
|
|
1164
|
+
if not templates:
|
|
1165
|
+
# Fallback: single document task
|
|
1166
|
+
templates = [
|
|
1167
|
+
("document", "Document {name} for {strategy}", "low", 2),
|
|
1168
|
+
]
|
|
1169
|
+
|
|
1170
|
+
prev_task_id = None
|
|
1171
|
+
if components:
|
|
1172
|
+
for comp in components:
|
|
1173
|
+
for ttype, title_tpl, priority, est_hours in templates:
|
|
1174
|
+
task_id = _gen_id("mtask-")
|
|
1175
|
+
title = title_tpl.format(
|
|
1176
|
+
name=comp["name"],
|
|
1177
|
+
strategy=strategy,
|
|
1178
|
+
)
|
|
1179
|
+
deps = json.dumps([prev_task_id] if prev_task_id else [])
|
|
1180
|
+
tasks.append({
|
|
1181
|
+
"id": task_id,
|
|
1182
|
+
"plan_id": plan_id,
|
|
1183
|
+
"legacy_component_id": comp["id"],
|
|
1184
|
+
"task_type": ttype,
|
|
1185
|
+
"title": title,
|
|
1186
|
+
"description": f"{strategy} task for component {comp['name']}",
|
|
1187
|
+
"priority": priority,
|
|
1188
|
+
"status": "pending",
|
|
1189
|
+
"estimated_hours": est_hours,
|
|
1190
|
+
"dependencies": deps,
|
|
1191
|
+
"created_at": now,
|
|
1192
|
+
})
|
|
1193
|
+
prev_task_id = task_id
|
|
1194
|
+
else:
|
|
1195
|
+
# No components found — create plan-level tasks
|
|
1196
|
+
for ttype, title_tpl, priority, est_hours in templates:
|
|
1197
|
+
task_id = _gen_id("mtask-")
|
|
1198
|
+
title = title_tpl.format(name=app_name, strategy=strategy)
|
|
1199
|
+
deps = json.dumps([prev_task_id] if prev_task_id else [])
|
|
1200
|
+
tasks.append({
|
|
1201
|
+
"id": task_id,
|
|
1202
|
+
"plan_id": plan_id,
|
|
1203
|
+
"legacy_component_id": None,
|
|
1204
|
+
"task_type": ttype,
|
|
1205
|
+
"title": title,
|
|
1206
|
+
"description": f"{strategy} task for application {app_name}",
|
|
1207
|
+
"priority": priority,
|
|
1208
|
+
"status": "pending",
|
|
1209
|
+
"estimated_hours": est_hours,
|
|
1210
|
+
"dependencies": deps,
|
|
1211
|
+
"created_at": now,
|
|
1212
|
+
})
|
|
1213
|
+
prev_task_id = task_id
|
|
1214
|
+
|
|
1215
|
+
total_estimated = sum(t["estimated_hours"] for t in tasks)
|
|
1216
|
+
|
|
1217
|
+
# Insert plan
|
|
1218
|
+
conn.execute(
|
|
1219
|
+
"INSERT INTO migration_plans "
|
|
1220
|
+
"(id, legacy_app_id, plan_name, strategy, target_language, "
|
|
1221
|
+
"target_framework, target_database, target_architecture, "
|
|
1222
|
+
"migration_approach, total_tasks, status, estimated_hours, "
|
|
1223
|
+
"created_at, updated_at) "
|
|
1224
|
+
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'draft', ?, ?, ?)",
|
|
1225
|
+
(
|
|
1226
|
+
plan_id, app_id, plan_name, strategy,
|
|
1227
|
+
target_lang, target_framework, target_db,
|
|
1228
|
+
target_arch, approach,
|
|
1229
|
+
len(tasks), total_estimated, now, now,
|
|
1230
|
+
),
|
|
1231
|
+
)
|
|
1232
|
+
|
|
1233
|
+
# Insert tasks
|
|
1234
|
+
for t in tasks:
|
|
1235
|
+
conn.execute(
|
|
1236
|
+
"INSERT INTO migration_tasks "
|
|
1237
|
+
"(id, plan_id, legacy_component_id, task_type, title, "
|
|
1238
|
+
"description, priority, status, estimated_hours, "
|
|
1239
|
+
"dependencies, created_at) "
|
|
1240
|
+
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
|
1241
|
+
(
|
|
1242
|
+
t["id"], t["plan_id"], t["legacy_component_id"],
|
|
1243
|
+
t["task_type"], t["title"], t["description"],
|
|
1244
|
+
t["priority"], t["status"], t["estimated_hours"],
|
|
1245
|
+
t["dependencies"], t["created_at"],
|
|
1246
|
+
),
|
|
1247
|
+
)
|
|
1248
|
+
|
|
1249
|
+
conn.commit()
|
|
1250
|
+
finally:
|
|
1251
|
+
conn.close()
|
|
1252
|
+
|
|
1253
|
+
plan_result = {
|
|
1254
|
+
"id": plan_id,
|
|
1255
|
+
"legacy_app_id": app_id,
|
|
1256
|
+
"plan_name": plan_name,
|
|
1257
|
+
"strategy": strategy,
|
|
1258
|
+
"target_language": target_lang,
|
|
1259
|
+
"target_framework": target_framework,
|
|
1260
|
+
"target_database": target_db,
|
|
1261
|
+
"target_architecture": target_arch,
|
|
1262
|
+
"migration_approach": approach,
|
|
1263
|
+
"total_tasks": len(tasks),
|
|
1264
|
+
"status": "draft",
|
|
1265
|
+
"estimated_hours": total_estimated,
|
|
1266
|
+
"created_at": now,
|
|
1267
|
+
"updated_at": now,
|
|
1268
|
+
"tasks": tasks,
|
|
1269
|
+
}
|
|
1270
|
+
return plan_result
|
|
1271
|
+
|
|
1272
|
+
|
|
1273
|
+
# ===================================================================
|
|
1274
|
+
# CLI
|
|
1275
|
+
# ===================================================================
|
|
1276
|
+
|
|
1277
|
+
def _format_output(data, as_json=False):
|
|
1278
|
+
"""Format output for terminal or JSON."""
|
|
1279
|
+
if as_json:
|
|
1280
|
+
return json.dumps(data, indent=2, default=str)
|
|
1281
|
+
return _pretty_print(data)
|
|
1282
|
+
|
|
1283
|
+
|
|
1284
|
+
def _pretty_print(data, indent=0):
|
|
1285
|
+
"""Recursively pretty-print a dict/list for human-readable terminal output."""
|
|
1286
|
+
lines = []
|
|
1287
|
+
prefix = " " * indent
|
|
1288
|
+
|
|
1289
|
+
if isinstance(data, dict):
|
|
1290
|
+
for key, value in data.items():
|
|
1291
|
+
if isinstance(value, (dict, list)):
|
|
1292
|
+
lines.append(f"{prefix}{key}:")
|
|
1293
|
+
lines.append(_pretty_print(value, indent + 1))
|
|
1294
|
+
else:
|
|
1295
|
+
lines.append(f"{prefix}{key}: {value}")
|
|
1296
|
+
elif isinstance(data, list):
|
|
1297
|
+
for idx, item in enumerate(data):
|
|
1298
|
+
if isinstance(item, dict):
|
|
1299
|
+
lines.append(f"{prefix}[{idx}]")
|
|
1300
|
+
lines.append(_pretty_print(item, indent + 1))
|
|
1301
|
+
else:
|
|
1302
|
+
lines.append(f"{prefix}- {item}")
|
|
1303
|
+
else:
|
|
1304
|
+
lines.append(f"{prefix}{data}")
|
|
1305
|
+
|
|
1306
|
+
return "\n".join(lines)
|
|
1307
|
+
|
|
1308
|
+
|
|
1309
|
+
def main():
|
|
1310
|
+
"""CLI entry point for monolith decomposition planning."""
|
|
1311
|
+
parser = argparse.ArgumentParser(
|
|
1312
|
+
description="CUI // SP-CTI — ICDEV Monolith Decomposition Planner",
|
|
1313
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
1314
|
+
epilog=(
|
|
1315
|
+
"Examples:\n"
|
|
1316
|
+
" # Detect bounded contexts\n"
|
|
1317
|
+
" python monolith_decomposer.py --app-id lapp-abc123 --detect-contexts --json\n"
|
|
1318
|
+
"\n"
|
|
1319
|
+
" # Suggest service boundaries\n"
|
|
1320
|
+
" python monolith_decomposer.py --app-id lapp-abc123 --suggest-boundaries\n"
|
|
1321
|
+
"\n"
|
|
1322
|
+
" # Create a full rearchitect migration plan\n"
|
|
1323
|
+
" python monolith_decomposer.py --app-id lapp-abc123 \\\n"
|
|
1324
|
+
" --create-plan --project-id proj-xyz \\\n"
|
|
1325
|
+
" --strategy rearchitect --target-arch microservices \\\n"
|
|
1326
|
+
" --target-language python --target-framework fastapi \\\n"
|
|
1327
|
+
" --target-db postgresql --approach strangler_fig --json\n"
|
|
1328
|
+
"\n"
|
|
1329
|
+
" # Estimate decomposition effort\n"
|
|
1330
|
+
" python monolith_decomposer.py --app-id lapp-abc123 --estimate-effort\n"
|
|
1331
|
+
),
|
|
1332
|
+
)
|
|
1333
|
+
|
|
1334
|
+
parser.add_argument(
|
|
1335
|
+
"--app-id", required=True,
|
|
1336
|
+
help="Legacy application ID (from legacy_applications table)",
|
|
1337
|
+
)
|
|
1338
|
+
parser.add_argument(
|
|
1339
|
+
"--detect-contexts", action="store_true",
|
|
1340
|
+
help="Detect bounded contexts using greedy modularity optimization",
|
|
1341
|
+
)
|
|
1342
|
+
parser.add_argument(
|
|
1343
|
+
"--suggest-boundaries", action="store_true",
|
|
1344
|
+
help="Suggest microservice service boundaries",
|
|
1345
|
+
)
|
|
1346
|
+
parser.add_argument(
|
|
1347
|
+
"--generate-plan", action="store_true",
|
|
1348
|
+
help="Generate a decomposition plan (does NOT persist to DB)",
|
|
1349
|
+
)
|
|
1350
|
+
parser.add_argument(
|
|
1351
|
+
"--generate-acl", action="store_true",
|
|
1352
|
+
help="Generate anti-corruption layer interface skeletons",
|
|
1353
|
+
)
|
|
1354
|
+
parser.add_argument(
|
|
1355
|
+
"--generate-facade", action="store_true",
|
|
1356
|
+
help="Generate API facade/gateway routing configuration",
|
|
1357
|
+
)
|
|
1358
|
+
parser.add_argument(
|
|
1359
|
+
"--estimate-effort", action="store_true",
|
|
1360
|
+
help="Estimate decomposition effort in hours per service",
|
|
1361
|
+
)
|
|
1362
|
+
parser.add_argument(
|
|
1363
|
+
"--create-plan", action="store_true",
|
|
1364
|
+
help="Create and persist a migration plan to the database",
|
|
1365
|
+
)
|
|
1366
|
+
parser.add_argument(
|
|
1367
|
+
"--project-id",
|
|
1368
|
+
help="Project ID (required for --create-plan)",
|
|
1369
|
+
)
|
|
1370
|
+
parser.add_argument(
|
|
1371
|
+
"--strategy",
|
|
1372
|
+
choices=VALID_STRATEGIES,
|
|
1373
|
+
default="rearchitect",
|
|
1374
|
+
help="Migration strategy (default: rearchitect)",
|
|
1375
|
+
)
|
|
1376
|
+
parser.add_argument(
|
|
1377
|
+
"--target-arch",
|
|
1378
|
+
choices=VALID_ARCHITECTURES,
|
|
1379
|
+
default="microservices",
|
|
1380
|
+
help="Target architecture (default: microservices)",
|
|
1381
|
+
)
|
|
1382
|
+
parser.add_argument(
|
|
1383
|
+
"--target-language",
|
|
1384
|
+
help="Target programming language (e.g., python, java, go)",
|
|
1385
|
+
)
|
|
1386
|
+
parser.add_argument(
|
|
1387
|
+
"--target-framework",
|
|
1388
|
+
help="Target framework (e.g., fastapi, spring-boot, gin)",
|
|
1389
|
+
)
|
|
1390
|
+
parser.add_argument(
|
|
1391
|
+
"--target-db",
|
|
1392
|
+
help="Target database (e.g., postgresql, dynamodb)",
|
|
1393
|
+
)
|
|
1394
|
+
parser.add_argument(
|
|
1395
|
+
"--approach",
|
|
1396
|
+
choices=VALID_APPROACHES,
|
|
1397
|
+
default="strangler_fig",
|
|
1398
|
+
help="Migration approach (default: strangler_fig)",
|
|
1399
|
+
)
|
|
1400
|
+
parser.add_argument(
|
|
1401
|
+
"--service-index", type=int, default=0,
|
|
1402
|
+
help="Service boundary index for --generate-acl / --generate-facade (default: 0)",
|
|
1403
|
+
)
|
|
1404
|
+
parser.add_argument(
|
|
1405
|
+
"--json", action="store_true", dest="output_json",
|
|
1406
|
+
help="Output as JSON",
|
|
1407
|
+
)
|
|
1408
|
+
parser.add_argument(
|
|
1409
|
+
"--db-path",
|
|
1410
|
+
help="Override database path (default: data/icdev.db)",
|
|
1411
|
+
)
|
|
1412
|
+
|
|
1413
|
+
args = parser.parse_args()
|
|
1414
|
+
db_path = args.db_path
|
|
1415
|
+
|
|
1416
|
+
# Ensure at least one action is requested
|
|
1417
|
+
actions = [
|
|
1418
|
+
args.detect_contexts, args.suggest_boundaries,
|
|
1419
|
+
args.generate_plan, args.generate_acl,
|
|
1420
|
+
args.generate_facade, args.estimate_effort,
|
|
1421
|
+
args.create_plan,
|
|
1422
|
+
]
|
|
1423
|
+
if not any(actions):
|
|
1424
|
+
parser.error(
|
|
1425
|
+
"No action specified. Use one of: --detect-contexts, "
|
|
1426
|
+
"--suggest-boundaries, --generate-plan, --generate-acl, "
|
|
1427
|
+
"--generate-facade, --estimate-effort, --create-plan"
|
|
1428
|
+
)
|
|
1429
|
+
|
|
1430
|
+
try:
|
|
1431
|
+
if args.detect_contexts:
|
|
1432
|
+
result = detect_bounded_contexts(args.app_id, db_path)
|
|
1433
|
+
print(_format_output(
|
|
1434
|
+
{"bounded_contexts": result, "count": len(result)},
|
|
1435
|
+
args.output_json,
|
|
1436
|
+
))
|
|
1437
|
+
|
|
1438
|
+
elif args.suggest_boundaries:
|
|
1439
|
+
result = suggest_service_boundaries(args.app_id, db_path)
|
|
1440
|
+
print(_format_output(
|
|
1441
|
+
{"service_boundaries": result, "count": len(result)},
|
|
1442
|
+
args.output_json,
|
|
1443
|
+
))
|
|
1444
|
+
|
|
1445
|
+
elif args.generate_plan:
|
|
1446
|
+
result = generate_decomposition_plan(
|
|
1447
|
+
args.app_id, args.target_arch, db_path,
|
|
1448
|
+
)
|
|
1449
|
+
print(_format_output(result, args.output_json))
|
|
1450
|
+
|
|
1451
|
+
elif args.generate_acl:
|
|
1452
|
+
boundaries = suggest_service_boundaries(args.app_id, db_path)
|
|
1453
|
+
if not boundaries:
|
|
1454
|
+
print("No service boundaries found.", file=sys.stderr)
|
|
1455
|
+
sys.exit(1)
|
|
1456
|
+
idx = min(args.service_index, len(boundaries) - 1)
|
|
1457
|
+
result = generate_anti_corruption_layer(
|
|
1458
|
+
args.app_id, boundaries[idx], db_path,
|
|
1459
|
+
)
|
|
1460
|
+
print(_format_output(result, args.output_json))
|
|
1461
|
+
|
|
1462
|
+
elif args.generate_facade:
|
|
1463
|
+
boundaries = suggest_service_boundaries(args.app_id, db_path)
|
|
1464
|
+
if not boundaries:
|
|
1465
|
+
# Generate with empty boundaries (all routes go to legacy)
|
|
1466
|
+
result = generate_api_facade(args.app_id, db_path=db_path)
|
|
1467
|
+
elif args.service_index >= 0 and args.service_index < len(boundaries):
|
|
1468
|
+
result = generate_api_facade(
|
|
1469
|
+
args.app_id, boundaries[args.service_index], db_path,
|
|
1470
|
+
)
|
|
1471
|
+
else:
|
|
1472
|
+
result = generate_api_facade(args.app_id, db_path=db_path)
|
|
1473
|
+
print(_format_output(result, args.output_json))
|
|
1474
|
+
|
|
1475
|
+
elif args.estimate_effort:
|
|
1476
|
+
result = estimate_decomposition_effort(args.app_id, db_path)
|
|
1477
|
+
print(_format_output(result, args.output_json))
|
|
1478
|
+
|
|
1479
|
+
elif args.create_plan:
|
|
1480
|
+
if not args.project_id:
|
|
1481
|
+
parser.error("--project-id is required for --create-plan")
|
|
1482
|
+
result = create_migration_plan(
|
|
1483
|
+
project_id=args.project_id,
|
|
1484
|
+
app_id=args.app_id,
|
|
1485
|
+
strategy=args.strategy,
|
|
1486
|
+
target_lang=args.target_language,
|
|
1487
|
+
target_framework=args.target_framework,
|
|
1488
|
+
target_db=args.target_db,
|
|
1489
|
+
target_arch=args.target_arch,
|
|
1490
|
+
approach=args.approach,
|
|
1491
|
+
db_path=db_path,
|
|
1492
|
+
)
|
|
1493
|
+
print(_format_output(result, args.output_json))
|
|
1494
|
+
|
|
1495
|
+
except FileNotFoundError as exc:
|
|
1496
|
+
print(f"[ERROR] {exc}", file=sys.stderr)
|
|
1497
|
+
sys.exit(1)
|
|
1498
|
+
except ValueError as exc:
|
|
1499
|
+
print(f"[ERROR] {exc}", file=sys.stderr)
|
|
1500
|
+
sys.exit(1)
|
|
1501
|
+
except sqlite3.Error as exc:
|
|
1502
|
+
print(f"[DB ERROR] {exc}", file=sys.stderr)
|
|
1503
|
+
sys.exit(1)
|
|
1504
|
+
|
|
1505
|
+
|
|
1506
|
+
if __name__ == "__main__":
|
|
1507
|
+
main()
|
|
1508
|
+
# [TEMPLATE: CUI // SP-CTI]
|