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.
Files changed (1105) hide show
  1. icdev/__init__.py +18 -0
  2. icdev/_paths.py +85 -0
  3. icdev/_version.py +3 -0
  4. icdev/data/__init__.py +1 -0
  5. icdev/data/args/__init__.py +1 -0
  6. icdev/data/args/agent_authority.yaml +61 -0
  7. icdev/data/args/agent_config.yaml +355 -0
  8. icdev/data/args/agentic_fitness.yaml +31 -0
  9. icdev/data/args/ai_governance_config.yaml +137 -0
  10. icdev/data/args/atlas_critique_config.yaml +66 -0
  11. icdev/data/args/bedrock_models.yaml +63 -0
  12. icdev/data/args/cicd_config.yaml +82 -0
  13. icdev/data/args/classification_config.yaml +232 -0
  14. icdev/data/args/cli_config.yaml +154 -0
  15. icdev/data/args/cloud_config.yaml +63 -0
  16. icdev/data/args/code_pattern_config.yaml +151 -0
  17. icdev/data/args/code_quality_config.yaml +47 -0
  18. icdev/data/args/companion_registry.yaml +202 -0
  19. icdev/data/args/context_config.yaml +82 -0
  20. icdev/data/args/csp_monitor_config.yaml +268 -0
  21. icdev/data/args/cui_markings.yaml +35 -0
  22. icdev/data/args/db_config.yaml +40 -0
  23. icdev/data/args/deployment_profiles.yaml +248 -0
  24. icdev/data/args/dev_profile_config.yaml +144 -0
  25. icdev/data/args/devsecops_config.yaml +286 -0
  26. icdev/data/args/endpoint_security_config.yaml +137 -0
  27. icdev/data/args/extension_config.yaml +79 -0
  28. icdev/data/args/file_access_tiers.yaml +88 -0
  29. icdev/data/args/framework_registry.yaml +415 -0
  30. icdev/data/args/innovation_config.yaml +431 -0
  31. icdev/data/args/installation_manifest.yaml +1087 -0
  32. icdev/data/args/llm_config.yaml +495 -0
  33. icdev/data/args/maintenance_config.yaml +55 -0
  34. icdev/data/args/memory_config.yaml +83 -0
  35. icdev/data/args/monitoring_config.yaml +127 -0
  36. icdev/data/args/mosa_config.yaml +190 -0
  37. icdev/data/args/nlq_config.yaml +35 -0
  38. icdev/data/args/observability_config.yaml +39 -0
  39. icdev/data/args/observability_tracing_config.yaml +170 -0
  40. icdev/data/args/oscal_tools_config.yaml +43 -0
  41. icdev/data/args/owasp_agentic_config.yaml +171 -0
  42. icdev/data/args/phase_registry.yaml +618 -0
  43. icdev/data/args/project_defaults.yaml +235 -0
  44. icdev/data/args/prompt_chains.yaml +163 -0
  45. icdev/data/args/resilience_config.yaml +50 -0
  46. icdev/data/args/ricoas_config.yaml +191 -0
  47. icdev/data/args/role_personas.yaml +362 -0
  48. icdev/data/args/scaling_config.yaml +176 -0
  49. icdev/data/args/security_gates.yaml +685 -0
  50. icdev/data/args/skill_injection_config.yaml +322 -0
  51. icdev/data/args/spec_config.yaml +53 -0
  52. icdev/data/args/supply_chain_config.yaml +76 -0
  53. icdev/data/args/translation_config.yaml +228 -0
  54. icdev/data/args/workflow_templates/ato_acceleration.yaml +54 -0
  55. icdev/data/args/workflow_templates/build_deploy.yaml +63 -0
  56. icdev/data/args/workflow_templates/full_compliance.yaml +43 -0
  57. icdev/data/args/workflow_templates/security_hardening.yaml +55 -0
  58. icdev/data/args/worktree_config.yaml +34 -0
  59. icdev/data/args/zta_config.yaml +247 -0
  60. icdev/data/context/__init__.py +1 -0
  61. icdev/data/context/agent/__init__.py +1 -0
  62. icdev/data/context/agent/response_schemas/__init__.py +1 -0
  63. icdev/data/context/agent/response_schemas/debate_position.json +46 -0
  64. icdev/data/context/agent/response_schemas/fitness_scorecard.json +74 -0
  65. icdev/data/context/agent/response_schemas/review_decision.json +39 -0
  66. icdev/data/context/agent/response_schemas/task_decomposition.json +82 -0
  67. icdev/data/context/agent/response_schemas/veto_decision.json +40 -0
  68. icdev/data/context/agentic/__init__.py +1 -0
  69. icdev/data/context/agentic/architecture_patterns.md +269 -0
  70. icdev/data/context/agentic/capability_registry.yaml +202 -0
  71. icdev/data/context/agentic/csp_mcp_registry.yaml +280 -0
  72. icdev/data/context/agentic/fitness_rubric.md +56 -0
  73. icdev/data/context/agentic/governance_baseline.md +205 -0
  74. icdev/data/context/ci/__init__.py +1 -0
  75. icdev/data/context/ci/worktree_templates.json +44 -0
  76. icdev/data/context/cloud/__init__.py +1 -0
  77. icdev/data/context/cloud/csp_service_registry.json +739 -0
  78. icdev/data/context/compliance/__init__.py +1 -0
  79. icdev/data/context/compliance/atlas_mitigations.json +293 -0
  80. icdev/data/context/compliance/atlas_techniques.json +833 -0
  81. icdev/data/context/compliance/cisa_sbd_requirements.json +432 -0
  82. icdev/data/context/compliance/cjis_security_policy.json +522 -0
  83. icdev/data/context/compliance/cmmc_practices.json +2494 -0
  84. icdev/data/context/compliance/cmmc_report_template.md +142 -0
  85. icdev/data/context/compliance/cnssi_1253_overlay.json +109 -0
  86. icdev/data/context/compliance/control_crosswalk.json +1914 -0
  87. icdev/data/context/compliance/control_families/__init__.py +1 -0
  88. icdev/data/context/compliance/csp_certifications.json +251 -0
  89. icdev/data/context/compliance/cssp_report_template.md +193 -0
  90. icdev/data/context/compliance/cui_templates/__init__.py +1 -0
  91. icdev/data/context/compliance/cui_templates/banner_block.txt +4 -0
  92. icdev/data/context/compliance/cui_templates/code_header.txt +8 -0
  93. icdev/data/context/compliance/cui_templates/document_template.md +35 -0
  94. icdev/data/context/compliance/data_type_framework_map.json +321 -0
  95. icdev/data/context/compliance/data_type_registry.json +147 -0
  96. icdev/data/context/compliance/dod_cssp_8530.json +463 -0
  97. icdev/data/context/compliance/eu_ai_act_annex_iii.json +108 -0
  98. icdev/data/context/compliance/export_templates/__init__.py +1 -0
  99. icdev/data/context/compliance/export_templates/emass_controls.csv.j2 +4 -0
  100. icdev/data/context/compliance/export_templates/evidence_package.md.j2 +39 -0
  101. icdev/data/context/compliance/export_templates/executive_summary.md.j2 +55 -0
  102. icdev/data/context/compliance/export_templates/poam_tracking.csv.j2 +4 -0
  103. icdev/data/context/compliance/fedramp_20x_ksi_schemas.json +133 -0
  104. icdev/data/context/compliance/fedramp_high_baseline.json +4370 -0
  105. icdev/data/context/compliance/fedramp_moderate_baseline.json +2183 -0
  106. icdev/data/context/compliance/fedramp_report_template.md +181 -0
  107. icdev/data/context/compliance/fips_200_areas.json +362 -0
  108. icdev/data/context/compliance/gao_ai_accountability.json +262 -0
  109. icdev/data/context/compliance/hipaa_security_rule.json +720 -0
  110. icdev/data/context/compliance/hitrust_csf_v11.json +930 -0
  111. icdev/data/context/compliance/impact_level_profiles.json +251 -0
  112. icdev/data/context/compliance/incident_response_template.md +1110 -0
  113. icdev/data/context/compliance/iso27001_2022_controls.json +750 -0
  114. icdev/data/context/compliance/iso27001_nist_bridge.json +382 -0
  115. icdev/data/context/compliance/iso42001_controls.json +254 -0
  116. icdev/data/context/compliance/ivv_checklist_template.md +80 -0
  117. icdev/data/context/compliance/ivv_report_template.md +116 -0
  118. icdev/data/context/compliance/ivv_requirements.json +372 -0
  119. icdev/data/context/compliance/mosa_crosswalk.json +327 -0
  120. icdev/data/context/compliance/mosa_framework.json +250 -0
  121. icdev/data/context/compliance/narrative_templates/AC.md.j2 +101 -0
  122. icdev/data/context/compliance/narrative_templates/AU.md.j2 +106 -0
  123. icdev/data/context/compliance/narrative_templates/IA.md.j2 +104 -0
  124. icdev/data/context/compliance/narrative_templates/SC.md.j2 +102 -0
  125. icdev/data/context/compliance/narrative_templates/SI.md.j2 +111 -0
  126. icdev/data/context/compliance/narrative_templates/__init__.py +1 -0
  127. icdev/data/context/compliance/narrative_templates/default.md.j2 +50 -0
  128. icdev/data/context/compliance/narrative_templates/executive_summary.j2 +27 -0
  129. icdev/data/context/compliance/narrative_templates/poam_milestone.j2 +19 -0
  130. icdev/data/context/compliance/narrative_templates/ssp_section.j2 +11 -0
  131. icdev/data/context/compliance/nist_800_171_controls.json +1552 -0
  132. icdev/data/context/compliance/nist_800_207_crosswalk.json +399 -0
  133. icdev/data/context/compliance/nist_800_207_zta.json +258 -0
  134. icdev/data/context/compliance/nist_800_53.json +324 -0
  135. icdev/data/context/compliance/nist_ai_600_1_genai.json +326 -0
  136. icdev/data/context/compliance/nist_ai_rmf.json +206 -0
  137. icdev/data/context/compliance/nist_sp_800_60_types.json +1667 -0
  138. icdev/data/context/compliance/omb_m25_21_high_impact_ai.json +248 -0
  139. icdev/data/context/compliance/omb_m26_04_unbiased_ai.json +262 -0
  140. icdev/data/context/compliance/owasp_agentic_asi.json +133 -0
  141. icdev/data/context/compliance/owasp_agentic_threats.json +285 -0
  142. icdev/data/context/compliance/owasp_llm_top10.json +274 -0
  143. icdev/data/context/compliance/pci_dss_v4.json +510 -0
  144. icdev/data/context/compliance/poam_template.md +117 -0
  145. icdev/data/context/compliance/safeai_controls.json +512 -0
  146. icdev/data/context/compliance/sbd_report_template.md +77 -0
  147. icdev/data/context/compliance/siem_config_templates/__init__.py +1 -0
  148. icdev/data/context/compliance/siem_config_templates/filebeat.yml +213 -0
  149. icdev/data/context/compliance/siem_config_templates/log_sources.json +208 -0
  150. icdev/data/context/compliance/soc2_trust_criteria.json +661 -0
  151. icdev/data/context/compliance/ssp_template.md +432 -0
  152. icdev/data/context/compliance/stig_templates/__init__.py +1 -0
  153. icdev/data/context/compliance/stig_templates/webapp_stig.json +139 -0
  154. icdev/data/context/compliance/xai_requirements.json +108 -0
  155. icdev/data/context/dashboard/__init__.py +1 -0
  156. icdev/data/context/dashboard/nlq_examples.json +50 -0
  157. icdev/data/context/dashboard/schema_descriptions.json +23 -0
  158. icdev/data/context/integration/__init__.py +1 -0
  159. icdev/data/context/integration/approval_workflows.json +32 -0
  160. icdev/data/context/integration/gitlab_field_mappings.json +33 -0
  161. icdev/data/context/integration/jira_field_mappings.json +32 -0
  162. icdev/data/context/integration/reqif_export_schema.json +23 -0
  163. icdev/data/context/integration/servicenow_field_mappings.json +22 -0
  164. icdev/data/context/languages/__init__.py +1 -0
  165. icdev/data/context/languages/framework_patterns.json +205 -0
  166. icdev/data/context/languages/language_registry.json +279 -0
  167. icdev/data/context/llm/__init__.py +1 -0
  168. icdev/data/context/llm/example_provider.py +86 -0
  169. icdev/data/context/mbse/__init__.py +1 -0
  170. icdev/data/context/mbse/des_report_template.md +162 -0
  171. icdev/data/context/mbse/des_requirements.json +411 -0
  172. icdev/data/context/mbse/digital_thread_patterns.json +403 -0
  173. icdev/data/context/mbse/reqif_schema.json +280 -0
  174. icdev/data/context/mbse/sysml_element_types.json +432 -0
  175. icdev/data/context/modernization/__init__.py +1 -0
  176. icdev/data/context/modernization/db_type_mappings.json +148 -0
  177. icdev/data/context/modernization/decomposition_patterns.json +284 -0
  178. icdev/data/context/modernization/framework_migration_patterns.json +359 -0
  179. icdev/data/context/modernization/migration_report_template.md +168 -0
  180. icdev/data/context/modernization/seven_rs_catalog.json +369 -0
  181. icdev/data/context/modernization/version_upgrade_rules.json +279 -0
  182. icdev/data/context/oscal/NIST_SP-800-53_rev5_catalog.json +254987 -0
  183. icdev/data/context/oscal/README.md +43 -0
  184. icdev/data/context/patterns/__init__.py +1 -0
  185. icdev/data/context/profiles/__init__.py +1 -0
  186. icdev/data/context/profiles/dod_baseline_v1.yaml +145 -0
  187. icdev/data/context/profiles/fedramp_baseline_v1.yaml +143 -0
  188. icdev/data/context/profiles/financial_baseline_v1.yaml +142 -0
  189. icdev/data/context/profiles/healthcare_baseline_v1.yaml +135 -0
  190. icdev/data/context/profiles/law_enforcement_v1.yaml +129 -0
  191. icdev/data/context/profiles/startup_v1.yaml +134 -0
  192. icdev/data/context/requirements/__init__.py +1 -0
  193. icdev/data/context/requirements/ambiguity_patterns.json +97 -0
  194. icdev/data/context/requirements/boundary_impact_rules.json +123 -0
  195. icdev/data/context/requirements/default_constitutions.json +67 -0
  196. icdev/data/context/requirements/document_extraction_rules.json +58 -0
  197. icdev/data/context/requirements/gap_patterns.json +108 -0
  198. icdev/data/context/requirements/readiness_rubric.json +78 -0
  199. icdev/data/context/requirements/red_alternative_patterns.json +210 -0
  200. icdev/data/context/requirements/safe_templates.json +72 -0
  201. icdev/data/context/requirements/spec_quality_checklist.json +122 -0
  202. icdev/data/context/simulation/__init__.py +1 -0
  203. icdev/data/context/simulation/architecture_patterns.json +36 -0
  204. icdev/data/context/simulation/coa_templates.json +38 -0
  205. icdev/data/context/simulation/cost_models.json +23 -0
  206. icdev/data/context/simulation/risk_categories.json +46 -0
  207. icdev/data/context/supply_chain/__init__.py +1 -0
  208. icdev/data/context/supply_chain/isa_templates.json +129 -0
  209. icdev/data/context/supply_chain/nist_800_161_controls.json +247 -0
  210. icdev/data/context/supply_chain/scrm_risk_matrix.json +147 -0
  211. icdev/data/context/templates/__init__.py +1 -0
  212. icdev/data/context/templates/ansible/__init__.py +1 -0
  213. icdev/data/context/templates/ansible/playbooks/__init__.py +1 -0
  214. icdev/data/context/templates/ansible/roles/__init__.py +1 -0
  215. icdev/data/context/templates/gitlab_ci/__init__.py +1 -0
  216. icdev/data/context/templates/grafana/__init__.py +1 -0
  217. icdev/data/context/templates/kubernetes/__init__.py +1 -0
  218. icdev/data/context/templates/project/__init__.py +1 -0
  219. icdev/data/context/templates/project/api/__init__.py +1 -0
  220. icdev/data/context/templates/project/cli/__init__.py +1 -0
  221. icdev/data/context/templates/project/data_pipeline/__init__.py +1 -0
  222. icdev/data/context/templates/project/iac/__init__.py +1 -0
  223. icdev/data/context/templates/project/javascript_frontend/__init__.py +1 -0
  224. icdev/data/context/templates/project/javascript_frontend/src/__init__.py +1 -0
  225. icdev/data/context/templates/project/javascript_frontend/tests/__init__.py +1 -0
  226. icdev/data/context/templates/project/microservice/__init__.py +1 -0
  227. icdev/data/context/templates/project/python_backend/__init__.py +1 -0
  228. icdev/data/context/templates/project/python_backend/src/__init__.py +1 -0
  229. icdev/data/context/templates/project/python_backend/tests/__init__.py +1 -0
  230. icdev/data/context/templates/project/python_backend/tests/features/__init__.py +1 -0
  231. icdev/data/context/templates/project/python_backend/tests/steps/__init__.py +1 -0
  232. icdev/data/context/templates/terraform/__init__.py +1 -0
  233. icdev/data/context/templates/terraform/govcloud_base/__init__.py +1 -0
  234. icdev/data/context/templates/terraform/modules/__init__.py +1 -0
  235. icdev/data/context/tone/__init__.py +1 -0
  236. icdev/data/context/translation/dependency_mappings.json +186 -0
  237. icdev/data/context/translation/type_mappings.json +149 -0
  238. icdev/data/docs/README.md +187 -0
  239. icdev/data/docs/__init__.py +1 -0
  240. icdev/data/docs/admin/gateway-guide.md +338 -0
  241. icdev/data/docs/admin/marketplace-guide.md +396 -0
  242. icdev/data/docs/admin/monitoring-guide.md +509 -0
  243. icdev/data/docs/architecture/compliance-framework.md +764 -0
  244. icdev/data/docs/architecture/database-schema.md +689 -0
  245. icdev/data/docs/architecture/gotcha-framework.md +518 -0
  246. icdev/data/docs/architecture/multi-agent-system.md +603 -0
  247. icdev/data/docs/dx/README.md +106 -0
  248. icdev/data/docs/dx/__init__.py +1 -0
  249. icdev/data/docs/dx/ci-cd-integration.md +378 -0
  250. icdev/data/docs/dx/claude-code-guide.md +213 -0
  251. icdev/data/docs/dx/companion-guide.md +232 -0
  252. icdev/data/docs/dx/dev-profiles.md +309 -0
  253. icdev/data/docs/dx/icdev-yaml-spec.md +219 -0
  254. icdev/data/docs/dx/integration-tiers.md +279 -0
  255. icdev/data/docs/dx/llm-routing-guide.md +456 -0
  256. icdev/data/docs/dx/quickstart.md +192 -0
  257. icdev/data/docs/dx/sdk-reference.md +356 -0
  258. icdev/data/docs/dx/unified-mcp-setup.md +525 -0
  259. icdev/data/docs/features/__init__.py +1 -0
  260. icdev/data/docs/features/phase-01-gotcha-framework.md +249 -0
  261. icdev/data/docs/features/phase-02-atlas-build-workflow.md +223 -0
  262. icdev/data/docs/features/phase-03-tdd-bdd-testing.md +261 -0
  263. icdev/data/docs/features/phase-04-nist-compliance.md +255 -0
  264. icdev/data/docs/features/phase-05-security-scanning.md +229 -0
  265. icdev/data/docs/features/phase-06-infrastructure-deployment.md +288 -0
  266. icdev/data/docs/features/phase-07-code-review-gates.md +276 -0
  267. icdev/data/docs/features/phase-08-self-healing.md +223 -0
  268. icdev/data/docs/features/phase-09-monitoring-observability.md +230 -0
  269. icdev/data/docs/features/phase-10-dashboard-web-ui.md +218 -0
  270. icdev/data/docs/features/phase-11-multi-agent-architecture.md +272 -0
  271. icdev/data/docs/features/phase-12-integration-testing.md +228 -0
  272. icdev/data/docs/features/phase-13-cicd-integration.md +257 -0
  273. icdev/data/docs/features/phase-14-secure-by-design-ivv.md +240 -0
  274. icdev/data/docs/features/phase-15-maintenance-audit.md +192 -0
  275. icdev/data/docs/features/phase-16-ato-acceleration.md +228 -0
  276. icdev/data/docs/features/phase-17-multi-framework-compliance.md +223 -0
  277. icdev/data/docs/features/phase-18-mbse-integration.md +242 -0
  278. icdev/data/docs/features/phase-19-agentic-generation.md +202 -0
  279. icdev/data/docs/features/phase-20-fips-security-categorization.md +198 -0
  280. icdev/data/docs/features/phase-21-saas-multi-tenancy.md +273 -0
  281. icdev/data/docs/features/phase-22-federated-gotcha-marketplace.md +242 -0
  282. icdev/data/docs/features/phase-23-universal-compliance-platform.md +238 -0
  283. icdev/data/docs/features/phase-24-devsecops-pipeline-security.md +198 -0
  284. icdev/data/docs/features/phase-25-zero-trust-architecture.md +220 -0
  285. icdev/data/docs/features/phase-26-dod-mosa.md +205 -0
  286. icdev/data/docs/features/phase-27-cli-capabilities.md +222 -0
  287. icdev/data/docs/features/phase-28-remote-command-gateway.md +235 -0
  288. icdev/data/docs/features/phase-29-proactive-monitoring.md +212 -0
  289. icdev/data/docs/features/phase-30-dashboard-auth.md +215 -0
  290. icdev/data/docs/features/phase-31-dashboard-ux-low-impact.md +188 -0
  291. icdev/data/docs/features/phase-32-dashboard-ux-medium-impact.md +223 -0
  292. icdev/data/docs/features/phase-33-modular-installation.md +218 -0
  293. icdev/data/docs/features/phase-34-dev-profiles.md +239 -0
  294. icdev/data/docs/features/phase-35-innovation-engine.md +257 -0
  295. icdev/data/docs/features/phase-36-evolutionary-intelligence.md +351 -0
  296. icdev/data/docs/features/phase-37-mitre-atlas-integration.md +485 -0
  297. icdev/data/docs/features/phase-38-cloud-agnostic-architecture.md +1033 -0
  298. icdev/data/docs/features/phase-39-observability-operations.md +178 -0
  299. icdev/data/docs/features/phase-40-nlq-compliance-queries.md +176 -0
  300. icdev/data/docs/features/phase-41-parallel-cicd.md +169 -0
  301. icdev/data/docs/features/phase-42-framework-planning.md +177 -0
  302. icdev/data/docs/features/phase-43-cross-language-translation.md +225 -0
  303. icdev/data/docs/features/phase-44-innovation-adaptation.md +227 -0
  304. icdev/data/docs/features/phase-45-owasp-agentic-security.md +239 -0
  305. icdev/data/docs/features/phase-46-observability-traceability-xai.md +240 -0
  306. icdev/data/docs/features/phase-47-unified-mcp-gateway.md +257 -0
  307. icdev/data/docs/features/phase-48-ai-transparency.md +203 -0
  308. icdev/data/docs/features/phase-49-ai-accountability.md +243 -0
  309. icdev/data/docs/features/phase-50-ai-governance-intake-chat.md +195 -0
  310. icdev/data/docs/features/phase-51-unified-chat-dashboard.md +240 -0
  311. icdev/data/docs/features/phase-52-code-intelligence.md +244 -0
  312. icdev/data/docs/features/phase-53-fedramp-20x-owasp-asi.md +359 -0
  313. icdev/data/docs/features/phase-54-slsa-swft-orchestration.md +379 -0
  314. icdev/data/docs/features/phase-55-a2a-v03-mcp-oauth.md +322 -0
  315. icdev/data/docs/features/phase-56-evidence-lineage.md +352 -0
  316. icdev/data/docs/features/phase-57-eu-ai-act-iron-bank.md +319 -0
  317. icdev/data/docs/features/phase-58-creative-engine.md +370 -0
  318. icdev/data/docs/features/phase-59-govcon-intelligence.md +535 -0
  319. icdev/data/docs/features/phase-60-cpmp.md +528 -0
  320. icdev/data/docs/features/phase-61-orchestration-improvements.md +534 -0
  321. icdev/data/docs/operations/dashboard-guide.md +354 -0
  322. icdev/data/docs/operations/deployment-guide.md +556 -0
  323. icdev/data/docs/operations/saas-admin-guide.md +439 -0
  324. icdev/data/docs/operations/security-operations-guide.md +733 -0
  325. icdev/data/docs/runbooks/backup-restore.md +412 -0
  326. icdev/data/docs/runbooks/troubleshooting.md +499 -0
  327. icdev/data/features/__init__.py +1 -0
  328. icdev/data/features/cicd_integration.feature +41 -0
  329. icdev/data/features/compliance_gates.feature +46 -0
  330. icdev/data/features/dashboard.feature +72 -0
  331. icdev/data/features/environment.py +25 -0
  332. icdev/data/features/project_management.feature +32 -0
  333. icdev/data/features/requirements_intake.feature +42 -0
  334. icdev/data/features/saas_platform.feature +53 -0
  335. icdev/data/features/security_scanning.feature +36 -0
  336. icdev/data/features/steps/__init__.py +1 -0
  337. icdev/data/features/steps/cicd_steps.py +465 -0
  338. icdev/data/features/steps/compliance_steps.py +308 -0
  339. icdev/data/features/steps/dashboard_steps.py +88 -0
  340. icdev/data/features/steps/project_steps.py +126 -0
  341. icdev/data/features/steps/requirements_intake_steps.py +689 -0
  342. icdev/data/features/steps/saas_platform_steps.py +572 -0
  343. icdev/data/features/steps/security_steps.py +236 -0
  344. icdev/data/features/steps/testing_steps.py +226 -0
  345. icdev/data/features/testing_pipeline.feature +42 -0
  346. icdev/data/goals/__init__.py +1 -0
  347. icdev/data/goals/agent_management.md +144 -0
  348. icdev/data/goals/agentic_generation.md +345 -0
  349. icdev/data/goals/agentic_threat_model.md +309 -0
  350. icdev/data/goals/ai_accountability.md +90 -0
  351. icdev/data/goals/ai_governance_intake.md +132 -0
  352. icdev/data/goals/ai_transparency.md +76 -0
  353. icdev/data/goals/atlas_integration.md +405 -0
  354. icdev/data/goals/ato_acceleration.md +139 -0
  355. icdev/data/goals/boundary_supply_chain.md +206 -0
  356. icdev/data/goals/build_app.md +544 -0
  357. icdev/data/goals/cicd_integration.md +86 -0
  358. icdev/data/goals/claude_dir_maintenance.md +77 -0
  359. icdev/data/goals/cli_capabilities.md +340 -0
  360. icdev/data/goals/cloud_agnostic.md +312 -0
  361. icdev/data/goals/code_intelligence.md +197 -0
  362. icdev/data/goals/code_review.md +94 -0
  363. icdev/data/goals/compliance_workflow.md +858 -0
  364. icdev/data/goals/continuous_harmonization.md +140 -0
  365. icdev/data/goals/cross_language_translation.md +171 -0
  366. icdev/data/goals/dashboard.md +142 -0
  367. icdev/data/goals/deploy_workflow.md +390 -0
  368. icdev/data/goals/devsecops_workflow.md +408 -0
  369. icdev/data/goals/evolutionary_intelligence.md +305 -0
  370. icdev/data/goals/external_integration.md +113 -0
  371. icdev/data/goals/framework_planning.md +63 -0
  372. icdev/data/goals/init_project.md +235 -0
  373. icdev/data/goals/innovation_engine.md +199 -0
  374. icdev/data/goals/integration_testing.md +189 -0
  375. icdev/data/goals/maintenance_audit.md +196 -0
  376. icdev/data/goals/manifest.md +56 -0
  377. icdev/data/goals/mbse_integration.md +504 -0
  378. icdev/data/goals/modernization_workflow.md +618 -0
  379. icdev/data/goals/monitoring.md +126 -0
  380. icdev/data/goals/mosa_workflow.md +463 -0
  381. icdev/data/goals/multi_agent_orchestration.md +68 -0
  382. icdev/data/goals/nlq_compliance.md +63 -0
  383. icdev/data/goals/observability.md +64 -0
  384. icdev/data/goals/observability_traceability_xai.md +154 -0
  385. icdev/data/goals/owasp_agentic_security.md +395 -0
  386. icdev/data/goals/parallel_cicd.md +61 -0
  387. icdev/data/goals/requirements_intake.md +213 -0
  388. icdev/data/goals/sbd_ivv_workflow.md +195 -0
  389. icdev/data/goals/security_categorization.md +133 -0
  390. icdev/data/goals/security_scan.md +381 -0
  391. icdev/data/goals/self_healing.md +120 -0
  392. icdev/data/goals/simulation_engine.md +111 -0
  393. icdev/data/goals/tdd_workflow.md +403 -0
  394. icdev/data/goals/zero_trust_architecture.md +403 -0
  395. icdev/data/hardprompts/__init__.py +1 -0
  396. icdev/data/hardprompts/agent/__init__.py +1 -0
  397. icdev/data/hardprompts/agent/agentic_architect.md +100 -0
  398. icdev/data/hardprompts/agent/debate_prompt.md +32 -0
  399. icdev/data/hardprompts/agent/fitness_evaluation.md +48 -0
  400. icdev/data/hardprompts/agent/governance_review.md +214 -0
  401. icdev/data/hardprompts/agent/reviewer_prompt.md +34 -0
  402. icdev/data/hardprompts/agent/skill_design.md +172 -0
  403. icdev/data/hardprompts/agent/task_decomposition.md +275 -0
  404. icdev/data/hardprompts/agent/veto_check_prompt.md +33 -0
  405. icdev/data/hardprompts/architect/__init__.py +1 -0
  406. icdev/data/hardprompts/architect/api_design.md +283 -0
  407. icdev/data/hardprompts/architect/data_model.md +277 -0
  408. icdev/data/hardprompts/architect/system_design.md +180 -0
  409. icdev/data/hardprompts/builder/__init__.py +1 -0
  410. icdev/data/hardprompts/builder/code_generation.md +59 -0
  411. icdev/data/hardprompts/builder/refactor.md +58 -0
  412. icdev/data/hardprompts/builder/scaffold_project.md +69 -0
  413. icdev/data/hardprompts/builder/test_generation.md +87 -0
  414. icdev/data/hardprompts/ci/__init__.py +1 -0
  415. icdev/data/hardprompts/ci/worktree_setup.md +35 -0
  416. icdev/data/hardprompts/compliance/__init__.py +1 -0
  417. icdev/data/hardprompts/compliance/cmmc_assessment.md +63 -0
  418. icdev/data/hardprompts/compliance/cssp_assessment.md +75 -0
  419. icdev/data/hardprompts/compliance/cui_marking.md +86 -0
  420. icdev/data/hardprompts/compliance/fedramp_assessment.md +55 -0
  421. icdev/data/hardprompts/compliance/ivv_assessment.md +96 -0
  422. icdev/data/hardprompts/compliance/poam_generation.md +57 -0
  423. icdev/data/hardprompts/compliance/sbd_assessment.md +101 -0
  424. icdev/data/hardprompts/compliance/security_categorization.md +74 -0
  425. icdev/data/hardprompts/compliance/ssp_generation.md +56 -0
  426. icdev/data/hardprompts/compliance/stig_evaluation.md +63 -0
  427. icdev/data/hardprompts/dashboard/__init__.py +1 -0
  428. icdev/data/hardprompts/dashboard/nlq_system_prompt.md +26 -0
  429. icdev/data/hardprompts/infra/__init__.py +1 -0
  430. icdev/data/hardprompts/infra/k8s_manifests.md +118 -0
  431. icdev/data/hardprompts/infra/pipeline_generation.md +160 -0
  432. icdev/data/hardprompts/infra/terraform_generation.md +92 -0
  433. icdev/data/hardprompts/integration/__init__.py +1 -0
  434. icdev/data/hardprompts/integration/approval_review.md +17 -0
  435. icdev/data/hardprompts/integration/jira_mapping.md +25 -0
  436. icdev/data/hardprompts/integration/servicenow_mapping.md +14 -0
  437. icdev/data/hardprompts/knowledge/__init__.py +1 -0
  438. icdev/data/hardprompts/knowledge/pattern_detection.md +73 -0
  439. icdev/data/hardprompts/knowledge/recommendation_engine.md +90 -0
  440. icdev/data/hardprompts/knowledge/root_cause_analysis.md +91 -0
  441. icdev/data/hardprompts/maintenance/__init__.py +1 -0
  442. icdev/data/hardprompts/maintenance/maintenance_assessment.md +82 -0
  443. icdev/data/hardprompts/mbse/__init__.py +1 -0
  444. icdev/data/hardprompts/mbse/digital_thread.md +67 -0
  445. icdev/data/hardprompts/mbse/model_import.md +62 -0
  446. icdev/data/hardprompts/mbse/model_to_code.md +65 -0
  447. icdev/data/hardprompts/modernization/__init__.py +1 -0
  448. icdev/data/hardprompts/modernization/legacy_analysis.md +93 -0
  449. icdev/data/hardprompts/modernization/migration_planning.md +150 -0
  450. icdev/data/hardprompts/modernization/seven_r_assessment.md +107 -0
  451. icdev/data/hardprompts/requirements/__init__.py +1 -0
  452. icdev/data/hardprompts/requirements/bdd_generation.md +35 -0
  453. icdev/data/hardprompts/requirements/clarification_prioritization.md +29 -0
  454. icdev/data/hardprompts/requirements/decomposition.md +60 -0
  455. icdev/data/hardprompts/requirements/document_extraction.md +45 -0
  456. icdev/data/hardprompts/requirements/gap_detection.md +70 -0
  457. icdev/data/hardprompts/requirements/intake_conversation.md +101 -0
  458. icdev/data/hardprompts/requirements/readiness_assessment.md +39 -0
  459. icdev/data/hardprompts/requirements/spec_quality.md +33 -0
  460. icdev/data/hardprompts/requirements/traceability_analysis.md +23 -0
  461. icdev/data/hardprompts/security/__init__.py +1 -0
  462. icdev/data/hardprompts/security/endpoint_security.md +78 -0
  463. icdev/data/hardprompts/security/threat_model.md +70 -0
  464. icdev/data/hardprompts/security/vulnerability_assessment.md +81 -0
  465. icdev/data/hardprompts/simulation/__init__.py +1 -0
  466. icdev/data/hardprompts/simulation/architecture_impact.md +27 -0
  467. icdev/data/hardprompts/simulation/coa_alternative.md +27 -0
  468. icdev/data/hardprompts/simulation/coa_generation.md +25 -0
  469. icdev/data/hardprompts/simulation/compliance_impact.md +28 -0
  470. icdev/data/hardprompts/simulation/cost_estimation.md +33 -0
  471. icdev/data/hardprompts/simulation/risk_assessment.md +28 -0
  472. icdev/data/hardprompts/translation/code_translation.md +68 -0
  473. icdev/data/hardprompts/translation/dependency_suggestion.md +44 -0
  474. icdev/data/hardprompts/translation/test_translation.md +64 -0
  475. icdev/data/hardprompts/translation/translation_repair.md +59 -0
  476. icdev/py.typed +0 -0
  477. icdev/tools/__init__.py +1 -0
  478. icdev/tools/_gen_formatter.py +12 -0
  479. icdev/tools/a2a/__init__.py +1 -0
  480. icdev/tools/a2a/agent_cards/architect.json +43 -0
  481. icdev/tools/a2a/agent_cards/builder.json +50 -0
  482. icdev/tools/a2a/agent_cards/compliance.json +57 -0
  483. icdev/tools/a2a/agent_cards/devsecops.json +71 -0
  484. icdev/tools/a2a/agent_cards/infra.json +57 -0
  485. icdev/tools/a2a/agent_cards/integration.json +57 -0
  486. icdev/tools/a2a/agent_cards/knowledge.json +43 -0
  487. icdev/tools/a2a/agent_cards/mbse.json +57 -0
  488. icdev/tools/a2a/agent_cards/modernization.json +50 -0
  489. icdev/tools/a2a/agent_cards/monitor.json +43 -0
  490. icdev/tools/a2a/agent_cards/orchestrator.json +36 -0
  491. icdev/tools/a2a/agent_cards/requirements_analyst.json +64 -0
  492. icdev/tools/a2a/agent_cards/security.json +50 -0
  493. icdev/tools/a2a/agent_cards/simulation.json +57 -0
  494. icdev/tools/a2a/agent_cards/supply_chain.json +50 -0
  495. icdev/tools/a2a/agent_client.py +349 -0
  496. icdev/tools/a2a/agent_registry.py +412 -0
  497. icdev/tools/a2a/agent_server.py +579 -0
  498. icdev/tools/a2a/task.py +200 -0
  499. icdev/tools/agent/__init__.py +2 -0
  500. icdev/tools/agent/a2a_agent_card_generator.py +285 -0
  501. icdev/tools/agent/a2a_discovery_server.py +250 -0
  502. icdev/tools/agent/agent_executor.py +529 -0
  503. icdev/tools/agent/agent_memory.py +557 -0
  504. icdev/tools/agent/agent_models.py +51 -0
  505. icdev/tools/agent/atlas_critique.py +908 -0
  506. icdev/tools/agent/authority.py +443 -0
  507. icdev/tools/agent/bedrock_client.py +1075 -0
  508. icdev/tools/agent/collaboration.py +871 -0
  509. icdev/tools/agent/dispatcher_mode.py +665 -0
  510. icdev/tools/agent/mailbox.py +575 -0
  511. icdev/tools/agent/prompt_chain_executor.py +1064 -0
  512. icdev/tools/agent/session_purpose.py +350 -0
  513. icdev/tools/agent/skill_router.py +638 -0
  514. icdev/tools/agent/skill_selector.py +486 -0
  515. icdev/tools/agent/team_orchestrator.py +1108 -0
  516. icdev/tools/agent/token_tracker.py +290 -0
  517. icdev/tools/analysis/__init__.py +1 -0
  518. icdev/tools/analysis/code_analyzer.py +780 -0
  519. icdev/tools/analysis/runtime_feedback.py +389 -0
  520. icdev/tools/audit/__init__.py +1 -0
  521. icdev/tools/audit/audit_logger.py +196 -0
  522. icdev/tools/audit/audit_query.py +157 -0
  523. icdev/tools/audit/decision_recorder.py +72 -0
  524. icdev/tools/builder/__init__.py +1 -0
  525. icdev/tools/builder/agentic_fitness.py +534 -0
  526. icdev/tools/builder/agentic_test_templates/test_a2a_callback.py +117 -0
  527. icdev/tools/builder/agentic_test_templates/test_a2a_lifecycle.feature +52 -0
  528. icdev/tools/builder/agentic_test_templates/test_agent_card.feature +37 -0
  529. icdev/tools/builder/agentic_test_templates/test_agent_health.py +128 -0
  530. icdev/tools/builder/agentic_test_templates/test_memory_system.feature +50 -0
  531. icdev/tools/builder/agentic_test_templates/test_skill_execution.feature +40 -0
  532. icdev/tools/builder/app_blueprint.py +1583 -0
  533. icdev/tools/builder/child_app_generator.py +2852 -0
  534. icdev/tools/builder/claude_md_generator.py +1734 -0
  535. icdev/tools/builder/code_generator.py +3703 -0
  536. icdev/tools/builder/db_init_generator.py +1709 -0
  537. icdev/tools/builder/dev_profile_manager.py +954 -0
  538. icdev/tools/builder/formatter.py +768 -0
  539. icdev/tools/builder/goal_adapter.py +592 -0
  540. icdev/tools/builder/gotcha_validator.py +812 -0
  541. icdev/tools/builder/language_support.py +441 -0
  542. icdev/tools/builder/linter.py +976 -0
  543. icdev/tools/builder/profile_detector.py +657 -0
  544. icdev/tools/builder/profile_md_generator.py +723 -0
  545. icdev/tools/builder/scaffolder.py +1590 -0
  546. icdev/tools/builder/scaffolder_extended.py +1771 -0
  547. icdev/tools/builder/test_writer.py +950 -0
  548. icdev/tools/ci/__init__.py +2 -0
  549. icdev/tools/ci/connectors/__init__.py +2 -0
  550. icdev/tools/ci/connectors/base_connector.py +80 -0
  551. icdev/tools/ci/connectors/connector_registry.py +188 -0
  552. icdev/tools/ci/connectors/mattermost_connector.py +159 -0
  553. icdev/tools/ci/connectors/slack_connector.py +197 -0
  554. icdev/tools/ci/core/__init__.py +2 -0
  555. icdev/tools/ci/core/air_gap_detector.py +115 -0
  556. icdev/tools/ci/core/comment_handler.py +192 -0
  557. icdev/tools/ci/core/conversation_manager.py +479 -0
  558. icdev/tools/ci/core/event_envelope.py +500 -0
  559. icdev/tools/ci/core/event_router.py +443 -0
  560. icdev/tools/ci/core/failure_parser.py +397 -0
  561. icdev/tools/ci/core/recovery_engine.py +527 -0
  562. icdev/tools/ci/modules/__init__.py +2 -0
  563. icdev/tools/ci/modules/agent.py +271 -0
  564. icdev/tools/ci/modules/git_ops.py +175 -0
  565. icdev/tools/ci/modules/state.py +117 -0
  566. icdev/tools/ci/modules/vcs.py +303 -0
  567. icdev/tools/ci/modules/workflow_ops.py +295 -0
  568. icdev/tools/ci/modules/worktree.py +340 -0
  569. icdev/tools/ci/pipeline_config_generator.py +558 -0
  570. icdev/tools/ci/triggers/__init__.py +2 -0
  571. icdev/tools/ci/triggers/gitlab_task_monitor.py +330 -0
  572. icdev/tools/ci/triggers/poll_trigger.py +237 -0
  573. icdev/tools/ci/triggers/webhook_server.py +356 -0
  574. icdev/tools/ci/workflows/__init__.py +2 -0
  575. icdev/tools/ci/workflows/icdev_build.py +140 -0
  576. icdev/tools/ci/workflows/icdev_comply.py +284 -0
  577. icdev/tools/ci/workflows/icdev_document.py +152 -0
  578. icdev/tools/ci/workflows/icdev_e2e.py +188 -0
  579. icdev/tools/ci/workflows/icdev_patch.py +186 -0
  580. icdev/tools/ci/workflows/icdev_plan.py +202 -0
  581. icdev/tools/ci/workflows/icdev_plan_build.py +41 -0
  582. icdev/tools/ci/workflows/icdev_plan_build_test.py +46 -0
  583. icdev/tools/ci/workflows/icdev_plan_build_test_review.py +47 -0
  584. icdev/tools/ci/workflows/icdev_review.py +126 -0
  585. icdev/tools/ci/workflows/icdev_sdlc.py +261 -0
  586. icdev/tools/ci/workflows/icdev_test.py +240 -0
  587. icdev/tools/cli/__init__.py +1 -0
  588. icdev/tools/cli/output_formatter.py +756 -0
  589. icdev/tools/cli_formatter.py +42 -0
  590. icdev/tools/cloud/__init__.py +11 -0
  591. icdev/tools/cloud/cloud_mode_manager.py +364 -0
  592. icdev/tools/cloud/csp_changelog.py +383 -0
  593. icdev/tools/cloud/csp_health_checker.py +268 -0
  594. icdev/tools/cloud/csp_monitor.py +951 -0
  595. icdev/tools/cloud/iam_provider.py +593 -0
  596. icdev/tools/cloud/kms_provider.py +346 -0
  597. icdev/tools/cloud/monitoring_provider.py +628 -0
  598. icdev/tools/cloud/provider_factory.py +376 -0
  599. icdev/tools/cloud/region_validator.py +345 -0
  600. icdev/tools/cloud/registry_provider.py +563 -0
  601. icdev/tools/cloud/secrets_provider.py +486 -0
  602. icdev/tools/cloud/storage_provider.py +446 -0
  603. icdev/tools/compat/__init__.py +21 -0
  604. icdev/tools/compat/cli_harmonizer.py +251 -0
  605. icdev/tools/compat/datetime_utils.py +18 -0
  606. icdev/tools/compat/db_utils.py +160 -0
  607. icdev/tools/compat/platform_utils.py +123 -0
  608. icdev/tools/compliance/__init__.py +1 -0
  609. icdev/tools/compliance/accountability_manager.py +397 -0
  610. icdev/tools/compliance/ai_accountability_audit.py +294 -0
  611. icdev/tools/compliance/ai_impact_assessor.py +273 -0
  612. icdev/tools/compliance/ai_incident_response.py +301 -0
  613. icdev/tools/compliance/ai_inventory_manager.py +239 -0
  614. icdev/tools/compliance/ai_reassessment_scheduler.py +256 -0
  615. icdev/tools/compliance/ai_transparency_audit.py +248 -0
  616. icdev/tools/compliance/atlas_assessor.py +278 -0
  617. icdev/tools/compliance/atlas_report_generator.py +1211 -0
  618. icdev/tools/compliance/base_assessor.py +597 -0
  619. icdev/tools/compliance/cato_monitor.py +1385 -0
  620. icdev/tools/compliance/cato_scheduler.py +699 -0
  621. icdev/tools/compliance/cjis_assessor.py +76 -0
  622. icdev/tools/compliance/classification_manager.py +1353 -0
  623. icdev/tools/compliance/cmmc_assessor.py +1491 -0
  624. icdev/tools/compliance/cmmc_report_generator.py +1100 -0
  625. icdev/tools/compliance/compliance_detector.py +463 -0
  626. icdev/tools/compliance/compliance_exporter.py +427 -0
  627. icdev/tools/compliance/compliance_status.py +825 -0
  628. icdev/tools/compliance/control_mapper.py +505 -0
  629. icdev/tools/compliance/crosswalk_engine.py +1203 -0
  630. icdev/tools/compliance/cssp_assessor.py +1045 -0
  631. icdev/tools/compliance/cssp_evidence_collector.py +729 -0
  632. icdev/tools/compliance/cssp_report_generator.py +1116 -0
  633. icdev/tools/compliance/cui_marker.py +388 -0
  634. icdev/tools/compliance/diagram_validator.py +600 -0
  635. icdev/tools/compliance/emass/__init__.py +2 -0
  636. icdev/tools/compliance/emass/emass_client.py +840 -0
  637. icdev/tools/compliance/emass/emass_export.py +777 -0
  638. icdev/tools/compliance/emass/emass_sync.py +826 -0
  639. icdev/tools/compliance/eu_ai_act_classifier.py +194 -0
  640. icdev/tools/compliance/evidence_collector.py +468 -0
  641. icdev/tools/compliance/fairness_assessor.py +316 -0
  642. icdev/tools/compliance/fedramp_assessor.py +1808 -0
  643. icdev/tools/compliance/fedramp_authorization_packager.py +137 -0
  644. icdev/tools/compliance/fedramp_ksi_generator.py +355 -0
  645. icdev/tools/compliance/fedramp_report_generator.py +1128 -0
  646. icdev/tools/compliance/fips199_categorizer.py +881 -0
  647. icdev/tools/compliance/fips200_validator.py +315 -0
  648. icdev/tools/compliance/gao_ai_assessor.py +231 -0
  649. icdev/tools/compliance/gao_evidence_builder.py +308 -0
  650. icdev/tools/compliance/hipaa_assessor.py +78 -0
  651. icdev/tools/compliance/hitrust_assessor.py +49 -0
  652. icdev/tools/compliance/incident_response_plan.py +718 -0
  653. icdev/tools/compliance/iso27001_assessor.py +92 -0
  654. icdev/tools/compliance/iso42001_assessor.py +114 -0
  655. icdev/tools/compliance/ivv_assessor.py +2327 -0
  656. icdev/tools/compliance/ivv_report_generator.py +1662 -0
  657. icdev/tools/compliance/model_card_generator.py +297 -0
  658. icdev/tools/compliance/mosa_assessor.py +117 -0
  659. icdev/tools/compliance/multi_regime_assessor.py +451 -0
  660. icdev/tools/compliance/narrative_generator.py +1013 -0
  661. icdev/tools/compliance/nist_800_207_assessor.py +191 -0
  662. icdev/tools/compliance/nist_ai_600_1_assessor.py +188 -0
  663. icdev/tools/compliance/nist_ai_rmf_assessor.py +110 -0
  664. icdev/tools/compliance/nist_lookup.py +245 -0
  665. icdev/tools/compliance/omb_m25_21_assessor.py +228 -0
  666. icdev/tools/compliance/omb_m26_04_assessor.py +188 -0
  667. icdev/tools/compliance/oscal_catalog_adapter.py +395 -0
  668. icdev/tools/compliance/oscal_generator.py +2170 -0
  669. icdev/tools/compliance/oscal_tools.py +1182 -0
  670. icdev/tools/compliance/owasp_agentic_assessor.py +226 -0
  671. icdev/tools/compliance/owasp_asi_assessor.py +200 -0
  672. icdev/tools/compliance/owasp_llm_assessor.py +244 -0
  673. icdev/tools/compliance/pci_dss_assessor.py +80 -0
  674. icdev/tools/compliance/pi_compliance_tracker.py +1461 -0
  675. icdev/tools/compliance/poam_generator.py +405 -0
  676. icdev/tools/compliance/resolve_marking.py +283 -0
  677. icdev/tools/compliance/sbd_assessor.py +2068 -0
  678. icdev/tools/compliance/sbd_report_generator.py +1236 -0
  679. icdev/tools/compliance/sbom_generator.py +1008 -0
  680. icdev/tools/compliance/siem_config_generator.py +674 -0
  681. icdev/tools/compliance/slsa_attestation_generator.py +490 -0
  682. icdev/tools/compliance/soc2_assessor.py +77 -0
  683. icdev/tools/compliance/ssp_generator.py +573 -0
  684. icdev/tools/compliance/stig_checker.py +727 -0
  685. icdev/tools/compliance/swft_evidence_bundler.py +337 -0
  686. icdev/tools/compliance/system_card_generator.py +309 -0
  687. icdev/tools/compliance/traceability_matrix.py +1281 -0
  688. icdev/tools/compliance/universal_classification_manager.py +1172 -0
  689. icdev/tools/compliance/xacta/__init__.py +2 -0
  690. icdev/tools/compliance/xacta/xacta_client.py +449 -0
  691. icdev/tools/compliance/xacta/xacta_export.py +557 -0
  692. icdev/tools/compliance/xacta/xacta_sync.py +333 -0
  693. icdev/tools/compliance/xai_assessor.py +231 -0
  694. icdev/tools/dashboard/__init__.py +1 -0
  695. icdev/tools/dashboard/api/__init__.py +1 -0
  696. icdev/tools/dashboard/api/_pipeline_state.py +17 -0
  697. icdev/tools/dashboard/api/activity.py +206 -0
  698. icdev/tools/dashboard/api/admin.py +176 -0
  699. icdev/tools/dashboard/api/agents.py +53 -0
  700. icdev/tools/dashboard/api/ai_accountability.py +163 -0
  701. icdev/tools/dashboard/api/ai_transparency.py +198 -0
  702. icdev/tools/dashboard/api/audit.py +58 -0
  703. icdev/tools/dashboard/api/batch.py +666 -0
  704. icdev/tools/dashboard/api/chat.py +241 -0
  705. icdev/tools/dashboard/api/cicd.py +219 -0
  706. icdev/tools/dashboard/api/code_quality.py +223 -0
  707. icdev/tools/dashboard/api/compliance.py +171 -0
  708. icdev/tools/dashboard/api/cpmp.py +915 -0
  709. icdev/tools/dashboard/api/diagrams.py +65 -0
  710. icdev/tools/dashboard/api/events.py +250 -0
  711. icdev/tools/dashboard/api/evidence.py +99 -0
  712. icdev/tools/dashboard/api/fedramp_20x.py +77 -0
  713. icdev/tools/dashboard/api/govcon.py +1095 -0
  714. icdev/tools/dashboard/api/intake.py +1171 -0
  715. icdev/tools/dashboard/api/lineage.py +163 -0
  716. icdev/tools/dashboard/api/metrics.py +155 -0
  717. icdev/tools/dashboard/api/nlq.py +72 -0
  718. icdev/tools/dashboard/api/orchestration.py +472 -0
  719. icdev/tools/dashboard/api/oscal.py +183 -0
  720. icdev/tools/dashboard/api/prod_audit.py +183 -0
  721. icdev/tools/dashboard/api/projects.py +191 -0
  722. icdev/tools/dashboard/api/proposals.py +1084 -0
  723. icdev/tools/dashboard/api/traces.py +363 -0
  724. icdev/tools/dashboard/api/usage.py +234 -0
  725. icdev/tools/dashboard/app.py +1986 -0
  726. icdev/tools/dashboard/auth.py +500 -0
  727. icdev/tools/dashboard/byok.py +245 -0
  728. icdev/tools/dashboard/chat_manager.py +675 -0
  729. icdev/tools/dashboard/config.py +116 -0
  730. icdev/tools/dashboard/diagram_definitions.py +642 -0
  731. icdev/tools/dashboard/nlq_processor.py +323 -0
  732. icdev/tools/dashboard/phase_loader.py +136 -0
  733. icdev/tools/dashboard/sse_manager.py +89 -0
  734. icdev/tools/dashboard/state_tracker.py +267 -0
  735. icdev/tools/dashboard/static/css/style.css +706 -0
  736. icdev/tools/dashboard/static/css/ux.css +2047 -0
  737. icdev/tools/dashboard/static/js/activity.js +322 -0
  738. icdev/tools/dashboard/static/js/api.js +161 -0
  739. icdev/tools/dashboard/static/js/batch.js +814 -0
  740. icdev/tools/dashboard/static/js/charts.js +618 -0
  741. icdev/tools/dashboard/static/js/chat.js +1514 -0
  742. icdev/tools/dashboard/static/js/kanban.js +113 -0
  743. icdev/tools/dashboard/static/js/live.js +569 -0
  744. icdev/tools/dashboard/static/js/mermaid-icdev.js +332 -0
  745. icdev/tools/dashboard/static/js/proposals.js +588 -0
  746. icdev/tools/dashboard/static/js/shortcuts.js +544 -0
  747. icdev/tools/dashboard/static/js/tables.js +652 -0
  748. icdev/tools/dashboard/static/js/tour.js +524 -0
  749. icdev/tools/dashboard/static/js/ux.js +942 -0
  750. icdev/tools/dashboard/templates/404.html +10 -0
  751. icdev/tools/dashboard/templates/activity.html +80 -0
  752. icdev/tools/dashboard/templates/admin/users.html +144 -0
  753. icdev/tools/dashboard/templates/ai_accountability.html +235 -0
  754. icdev/tools/dashboard/templates/ai_transparency.html +263 -0
  755. icdev/tools/dashboard/templates/base.html +104 -0
  756. icdev/tools/dashboard/templates/batch.html +23 -0
  757. icdev/tools/dashboard/templates/chat.html +332 -0
  758. icdev/tools/dashboard/templates/children.html +149 -0
  759. icdev/tools/dashboard/templates/cicd.html +253 -0
  760. icdev/tools/dashboard/templates/code_quality.html +214 -0
  761. icdev/tools/dashboard/templates/cpmp/cor_detail.html +220 -0
  762. icdev/tools/dashboard/templates/cpmp/cor_portal.html +91 -0
  763. icdev/tools/dashboard/templates/cpmp/deliverable_detail.html +197 -0
  764. icdev/tools/dashboard/templates/cpmp/detail.html +578 -0
  765. icdev/tools/dashboard/templates/cpmp/portfolio.html +202 -0
  766. icdev/tools/dashboard/templates/dev_profiles.html +304 -0
  767. icdev/tools/dashboard/templates/diagrams.html +224 -0
  768. icdev/tools/dashboard/templates/events/timeline.html +232 -0
  769. icdev/tools/dashboard/templates/evidence.html +134 -0
  770. icdev/tools/dashboard/templates/fedramp_20x.html +207 -0
  771. icdev/tools/dashboard/templates/gateway.html +244 -0
  772. icdev/tools/dashboard/templates/govcon/capabilities.html +135 -0
  773. icdev/tools/dashboard/templates/govcon/pipeline.html +214 -0
  774. icdev/tools/dashboard/templates/govcon/requirements.html +120 -0
  775. icdev/tools/dashboard/templates/index.html +254 -0
  776. icdev/tools/dashboard/templates/lineage.html +141 -0
  777. icdev/tools/dashboard/templates/login.html +51 -0
  778. icdev/tools/dashboard/templates/monitoring/overview.html +193 -0
  779. icdev/tools/dashboard/templates/orchestration/dashboard.html +545 -0
  780. icdev/tools/dashboard/templates/oscal.html +263 -0
  781. icdev/tools/dashboard/templates/phases.html +150 -0
  782. icdev/tools/dashboard/templates/prod_audit.html +280 -0
  783. icdev/tools/dashboard/templates/profile.html +183 -0
  784. icdev/tools/dashboard/templates/projects/detail.html +583 -0
  785. icdev/tools/dashboard/templates/projects/list.html +47 -0
  786. icdev/tools/dashboard/templates/proposals/detail.html +1253 -0
  787. icdev/tools/dashboard/templates/proposals/list.html +179 -0
  788. icdev/tools/dashboard/templates/proposals/section_detail.html +193 -0
  789. icdev/tools/dashboard/templates/provenance.html +181 -0
  790. icdev/tools/dashboard/templates/query/nlq.html +234 -0
  791. icdev/tools/dashboard/templates/quick_paths.html +69 -0
  792. icdev/tools/dashboard/templates/traces.html +155 -0
  793. icdev/tools/dashboard/templates/translation_detail.html +199 -0
  794. icdev/tools/dashboard/templates/translations.html +162 -0
  795. icdev/tools/dashboard/templates/usage.html +225 -0
  796. icdev/tools/dashboard/templates/wizard.html +539 -0
  797. icdev/tools/dashboard/templates/xai.html +208 -0
  798. icdev/tools/dashboard/ux_helpers.py +962 -0
  799. icdev/tools/dashboard/websocket.py +81 -0
  800. icdev/tools/db/__init__.py +1 -0
  801. icdev/tools/db/backup.py +312 -0
  802. icdev/tools/db/backup_manager.py +832 -0
  803. icdev/tools/db/init_icdev_db.py +5900 -0
  804. icdev/tools/db/migrate.py +178 -0
  805. icdev/tools/db/migration_runner.py +549 -0
  806. icdev/tools/db/migrations/001_baseline/meta.json +9 -0
  807. icdev/tools/db/migrations/001_baseline/up.py +68 -0
  808. icdev/tools/db/migrations/002_memory_enhancements/down.sql +8 -0
  809. icdev/tools/db/migrations/002_memory_enhancements/meta.json +9 -0
  810. icdev/tools/db/migrations/002_memory_enhancements/up.py +118 -0
  811. icdev/tools/db/migrations/003_dev_profiles/meta.json +8 -0
  812. icdev/tools/db/migrations/003_dev_profiles/up.py +93 -0
  813. icdev/tools/db/migrations/004_innovation_engine/down.py +19 -0
  814. icdev/tools/db/migrations/004_innovation_engine/up.py +227 -0
  815. icdev/tools/db/migrations/005_phase_37_ai_security/down.py +19 -0
  816. icdev/tools/db/migrations/005_phase_37_ai_security/up.py +258 -0
  817. icdev/tools/db/migrations/006_phase_36_evolution/down.py +21 -0
  818. icdev/tools/db/migrations/006_phase_36_evolution/up.py +323 -0
  819. icdev/tools/db/migrations/007_phase_38_cloud/down.py +14 -0
  820. icdev/tools/db/migrations/007_phase_38_cloud/up.py +110 -0
  821. icdev/tools/db/migrations/008_phase36_37_integration/up.py +55 -0
  822. icdev/tools/db/migrations/__init__.py +2 -0
  823. icdev/tools/devsecops/__init__.py +2 -0
  824. icdev/tools/devsecops/attestation_manager.py +458 -0
  825. icdev/tools/devsecops/network_segmentation_generator.py +614 -0
  826. icdev/tools/devsecops/pdp_config_generator.py +1256 -0
  827. icdev/tools/devsecops/pipeline_security_generator.py +484 -0
  828. icdev/tools/devsecops/policy_generator.py +653 -0
  829. icdev/tools/devsecops/profile_manager.py +388 -0
  830. icdev/tools/devsecops/service_mesh_generator.py +1073 -0
  831. icdev/tools/devsecops/zta_maturity_scorer.py +368 -0
  832. icdev/tools/devsecops/zta_terraform_generator.py +1303 -0
  833. icdev/tools/dx/__init__.py +3 -0
  834. icdev/tools/dx/companion.py +266 -0
  835. icdev/tools/dx/instruction_generator.py +753 -0
  836. icdev/tools/dx/mcp_config_generator.py +282 -0
  837. icdev/tools/dx/skill_translator.py +425 -0
  838. icdev/tools/dx/tool_detector.py +144 -0
  839. icdev/tools/extensions/__init__.py +21 -0
  840. icdev/tools/extensions/builtins/010_ai_governance_chat.py +277 -0
  841. icdev/tools/extensions/builtins/__init__.py +2 -0
  842. icdev/tools/extensions/extension_manager.py +455 -0
  843. icdev/tools/infra/__init__.py +1 -0
  844. icdev/tools/infra/ansible_generator.py +869 -0
  845. icdev/tools/infra/dockerfile_generator.py +361 -0
  846. icdev/tools/infra/infra_status.py +393 -0
  847. icdev/tools/infra/ironbank_metadata_generator.py +411 -0
  848. icdev/tools/infra/k8s_generator.py +1002 -0
  849. icdev/tools/infra/pipeline_generator.py +832 -0
  850. icdev/tools/infra/rollback.py +400 -0
  851. icdev/tools/infra/terraform_generator.py +1142 -0
  852. icdev/tools/infra/terraform_generator_azure.py +1254 -0
  853. icdev/tools/infra/terraform_generator_gcp.py +953 -0
  854. icdev/tools/infra/terraform_generator_ibm.py +360 -0
  855. icdev/tools/infra/terraform_generator_oci.py +919 -0
  856. icdev/tools/infra/terraform_generator_onprem.py +319 -0
  857. icdev/tools/innovation/__init__.py +8 -0
  858. icdev/tools/innovation/competitive_intel.py +492 -0
  859. icdev/tools/innovation/innovation_manager.py +681 -0
  860. icdev/tools/innovation/introspective_analyzer.py +774 -0
  861. icdev/tools/innovation/register_external_patterns.py +440 -0
  862. icdev/tools/innovation/signal_ranker.py +1038 -0
  863. icdev/tools/innovation/solution_generator.py +697 -0
  864. icdev/tools/innovation/standards_monitor.py +466 -0
  865. icdev/tools/innovation/trend_detector.py +1046 -0
  866. icdev/tools/innovation/triage_engine.py +1149 -0
  867. icdev/tools/innovation/web_scanner.py +894 -0
  868. icdev/tools/installer/__init__.py +1 -0
  869. icdev/tools/installer/compliance_configurator.py +637 -0
  870. icdev/tools/installer/installer.py +1711 -0
  871. icdev/tools/installer/module_registry.py +805 -0
  872. icdev/tools/installer/platform_setup.py +961 -0
  873. icdev/tools/integration/__init__.py +2 -0
  874. icdev/tools/integration/approval_manager.py +561 -0
  875. icdev/tools/integration/doors_exporter.py +627 -0
  876. icdev/tools/integration/gitlab_connector.py +784 -0
  877. icdev/tools/integration/jira_connector.py +774 -0
  878. icdev/tools/integration/servicenow_connector.py +693 -0
  879. icdev/tools/knowledge/__init__.py +1 -0
  880. icdev/tools/knowledge/knowledge_ingest.py +293 -0
  881. icdev/tools/knowledge/pattern_detector.py +693 -0
  882. icdev/tools/knowledge/recommendation_engine.py +461 -0
  883. icdev/tools/knowledge/self_heal_analyzer.py +504 -0
  884. icdev/tools/llm/__init__.py +72 -0
  885. icdev/tools/llm/anthropic_provider.py +170 -0
  886. icdev/tools/llm/azure_openai_provider.py +338 -0
  887. icdev/tools/llm/bedrock_provider.py +315 -0
  888. icdev/tools/llm/embedding_provider.py +438 -0
  889. icdev/tools/llm/gemini_provider.py +381 -0
  890. icdev/tools/llm/ibm_watsonx_provider.py +232 -0
  891. icdev/tools/llm/oci_genai_provider.py +462 -0
  892. icdev/tools/llm/ollama_provider.py +340 -0
  893. icdev/tools/llm/openai_provider.py +225 -0
  894. icdev/tools/llm/provider.py +355 -0
  895. icdev/tools/llm/provider_sdk.py +175 -0
  896. icdev/tools/llm/router.py +780 -0
  897. icdev/tools/llm/vertex_ai_provider.py +374 -0
  898. icdev/tools/maintenance/__init__.py +2 -0
  899. icdev/tools/maintenance/dependency_scanner.py +1030 -0
  900. icdev/tools/maintenance/maintenance_auditor.py +815 -0
  901. icdev/tools/maintenance/remediation_engine.py +966 -0
  902. icdev/tools/maintenance/vulnerability_checker.py +987 -0
  903. icdev/tools/mbse/__init__.py +3 -0
  904. icdev/tools/mbse/des_assessor.py +1186 -0
  905. icdev/tools/mbse/des_report_generator.py +800 -0
  906. icdev/tools/mbse/diagram_extractor.py +811 -0
  907. icdev/tools/mbse/digital_thread.py +1665 -0
  908. icdev/tools/mbse/model_code_generator.py +1122 -0
  909. icdev/tools/mbse/model_control_mapper.py +420 -0
  910. icdev/tools/mbse/pi_model_tracker.py +1093 -0
  911. icdev/tools/mbse/reqif_parser.py +1483 -0
  912. icdev/tools/mbse/sync_engine.py +1805 -0
  913. icdev/tools/mbse/xmi_parser.py +1573 -0
  914. icdev/tools/mcp/__init__.py +1 -0
  915. icdev/tools/mcp/base_server.py +535 -0
  916. icdev/tools/mcp/builder_server.py +725 -0
  917. icdev/tools/mcp/compliance_server.py +1407 -0
  918. icdev/tools/mcp/context_indexer.py +199 -0
  919. icdev/tools/mcp/context_server.py +305 -0
  920. icdev/tools/mcp/core_server.py +679 -0
  921. icdev/tools/mcp/devsecops_server.py +432 -0
  922. icdev/tools/mcp/gap_handlers.py +1079 -0
  923. icdev/tools/mcp/gateway_server.py +339 -0
  924. icdev/tools/mcp/generate_registry.py +623 -0
  925. icdev/tools/mcp/infra_server.py +264 -0
  926. icdev/tools/mcp/innovation_server.py +316 -0
  927. icdev/tools/mcp/integration_server.py +527 -0
  928. icdev/tools/mcp/knowledge_server.py +429 -0
  929. icdev/tools/mcp/maintenance_server.py +248 -0
  930. icdev/tools/mcp/marketplace_server.py +499 -0
  931. icdev/tools/mcp/mbse_server.py +398 -0
  932. icdev/tools/mcp/modernization_server.py +496 -0
  933. icdev/tools/mcp/observability_server.py +354 -0
  934. icdev/tools/mcp/requirements_server.py +415 -0
  935. icdev/tools/mcp/simulation_server.py +468 -0
  936. icdev/tools/mcp/standalone/__init__.py +2 -0
  937. icdev/tools/mcp/standalone/builder.py +59 -0
  938. icdev/tools/mcp/standalone/compliance.py +59 -0
  939. icdev/tools/mcp/standalone/core.py +59 -0
  940. icdev/tools/mcp/standalone/knowledge.py +59 -0
  941. icdev/tools/mcp/standalone/maintenance.py +59 -0
  942. icdev/tools/mcp/supply_chain_server.py +476 -0
  943. icdev/tools/mcp/tool_registry.py +2008 -0
  944. icdev/tools/mcp/unified_server.py +158 -0
  945. icdev/tools/memory/__init__.py +2 -0
  946. icdev/tools/memory/auto_capture.py +347 -0
  947. icdev/tools/memory/embed_memory.py +158 -0
  948. icdev/tools/memory/history_compressor.py +334 -0
  949. icdev/tools/memory/hybrid_search.py +236 -0
  950. icdev/tools/memory/maintenance_cron.py +289 -0
  951. icdev/tools/memory/memory_consolidation.py +444 -0
  952. icdev/tools/memory/memory_db.py +133 -0
  953. icdev/tools/memory/memory_read.py +102 -0
  954. icdev/tools/memory/memory_write.py +222 -0
  955. icdev/tools/memory/semantic_search.py +139 -0
  956. icdev/tools/memory/time_decay.py +435 -0
  957. icdev/tools/modernization/__init__.py +3 -0
  958. icdev/tools/modernization/architecture_extractor.py +734 -0
  959. icdev/tools/modernization/compliance_bridge.py +1499 -0
  960. icdev/tools/modernization/db_migration_planner.py +1385 -0
  961. icdev/tools/modernization/doc_generator.py +1428 -0
  962. icdev/tools/modernization/framework_migrator.py +1525 -0
  963. icdev/tools/modernization/legacy_analyzer.py +1948 -0
  964. icdev/tools/modernization/migration_code_generator.py +1639 -0
  965. icdev/tools/modernization/migration_report_generator.py +1653 -0
  966. icdev/tools/modernization/migration_tracker.py +1726 -0
  967. icdev/tools/modernization/monolith_decomposer.py +1508 -0
  968. icdev/tools/modernization/seven_r_assessor.py +1658 -0
  969. icdev/tools/modernization/strangler_fig_manager.py +1705 -0
  970. icdev/tools/modernization/ui_analyzer.py +771 -0
  971. icdev/tools/modernization/version_migrator.py +1392 -0
  972. icdev/tools/monitor/__init__.py +1 -0
  973. icdev/tools/monitor/alert_correlator.py +495 -0
  974. icdev/tools/monitor/auto_resolver.py +612 -0
  975. icdev/tools/monitor/health_checker.py +509 -0
  976. icdev/tools/monitor/heartbeat_daemon.py +792 -0
  977. icdev/tools/monitor/log_analyzer.py +516 -0
  978. icdev/tools/monitor/metric_collector.py +496 -0
  979. icdev/tools/mosa/__init__.py +10 -0
  980. icdev/tools/mosa/icd_generator.py +370 -0
  981. icdev/tools/mosa/modular_design_analyzer.py +683 -0
  982. icdev/tools/mosa/mosa_code_enforcer.py +349 -0
  983. icdev/tools/mosa/tsp_generator.py +265 -0
  984. icdev/tools/observability/__init__.py +100 -0
  985. icdev/tools/observability/genai_attributes.py +88 -0
  986. icdev/tools/observability/instrumentation.py +140 -0
  987. icdev/tools/observability/mlflow_exporter.py +194 -0
  988. icdev/tools/observability/otel_tracer.py +168 -0
  989. icdev/tools/observability/provenance/__init__.py +3 -0
  990. icdev/tools/observability/provenance/prov_recorder.py +324 -0
  991. icdev/tools/observability/shap/__init__.py +3 -0
  992. icdev/tools/observability/shap/agent_shap.py +275 -0
  993. icdev/tools/observability/sqlite_tracer.py +361 -0
  994. icdev/tools/observability/trace_context.py +205 -0
  995. icdev/tools/observability/tracer.py +230 -0
  996. icdev/tools/orchestration/__init__.py +2 -0
  997. icdev/tools/orchestration/workflow_composer.py +361 -0
  998. icdev/tools/project/__init__.py +1 -0
  999. icdev/tools/project/manifest_loader.py +418 -0
  1000. icdev/tools/project/project_create.py +350 -0
  1001. icdev/tools/project/project_list.py +174 -0
  1002. icdev/tools/project/project_scaffold.py +1715 -0
  1003. icdev/tools/project/project_status.py +479 -0
  1004. icdev/tools/project/session_context_builder.py +757 -0
  1005. icdev/tools/project/validate_manifest.py +55 -0
  1006. icdev/tools/registry/__init__.py +10 -0
  1007. icdev/tools/registry/absorption_engine.py +832 -0
  1008. icdev/tools/registry/capability_evaluator.py +668 -0
  1009. icdev/tools/registry/child_registry.py +617 -0
  1010. icdev/tools/registry/cross_pollinator.py +1065 -0
  1011. icdev/tools/registry/genome_manager.py +671 -0
  1012. icdev/tools/registry/learning_collector.py +912 -0
  1013. icdev/tools/registry/propagation_manager.py +942 -0
  1014. icdev/tools/registry/staging_manager.py +742 -0
  1015. icdev/tools/registry/telemetry_collector.py +423 -0
  1016. icdev/tools/requirements/__init__.py +1 -0
  1017. icdev/tools/requirements/ai_governance_scorer.py +208 -0
  1018. icdev/tools/requirements/boundary_analyzer.py +1293 -0
  1019. icdev/tools/requirements/clarification_engine.py +618 -0
  1020. icdev/tools/requirements/complexity_scorer.py +387 -0
  1021. icdev/tools/requirements/consistency_analyzer.py +803 -0
  1022. icdev/tools/requirements/constitution_manager.py +605 -0
  1023. icdev/tools/requirements/decomposition_engine.py +778 -0
  1024. icdev/tools/requirements/document_extractor.py +1016 -0
  1025. icdev/tools/requirements/elicitation_techniques.py +519 -0
  1026. icdev/tools/requirements/gap_detector.py +271 -0
  1027. icdev/tools/requirements/intake_engine.py +2188 -0
  1028. icdev/tools/requirements/prd_generator.py +847 -0
  1029. icdev/tools/requirements/prd_validator.py +595 -0
  1030. icdev/tools/requirements/readiness_scorer.py +313 -0
  1031. icdev/tools/requirements/spec_organizer.py +1029 -0
  1032. icdev/tools/requirements/spec_quality_checker.py +1097 -0
  1033. icdev/tools/requirements/traceability_builder.py +579 -0
  1034. icdev/tools/resilience/__init__.py +34 -0
  1035. icdev/tools/resilience/circuit_breaker.py +340 -0
  1036. icdev/tools/resilience/correlation.py +150 -0
  1037. icdev/tools/resilience/errors.py +81 -0
  1038. icdev/tools/resilience/retry.py +95 -0
  1039. icdev/tools/schemas/__init__.py +27 -0
  1040. icdev/tools/schemas/chat.py +61 -0
  1041. icdev/tools/schemas/compliance.py +56 -0
  1042. icdev/tools/schemas/core.py +85 -0
  1043. icdev/tools/schemas/innovation.py +37 -0
  1044. icdev/tools/schemas/validation.py +109 -0
  1045. icdev/tools/sdk/__init__.py +3 -0
  1046. icdev/tools/sdk/icdev_client.py +218 -0
  1047. icdev/tools/security/__init__.py +1 -0
  1048. icdev/tools/security/agent_output_validator.py +330 -0
  1049. icdev/tools/security/agent_trust_scorer.py +466 -0
  1050. icdev/tools/security/ai_bom_generator.py +725 -0
  1051. icdev/tools/security/ai_telemetry_logger.py +469 -0
  1052. icdev/tools/security/atlas_red_team.py +543 -0
  1053. icdev/tools/security/code_pattern_scanner.py +378 -0
  1054. icdev/tools/security/confabulation_detector.py +271 -0
  1055. icdev/tools/security/container_scanner.py +491 -0
  1056. icdev/tools/security/dependency_auditor.py +944 -0
  1057. icdev/tools/security/endpoint_security_scanner.py +579 -0
  1058. icdev/tools/security/mcp_tool_authorizer.py +243 -0
  1059. icdev/tools/security/prompt_injection_detector.py +737 -0
  1060. icdev/tools/security/sast_runner.py +948 -0
  1061. icdev/tools/security/secret_detector.py +378 -0
  1062. icdev/tools/security/tool_chain_validator.py +357 -0
  1063. icdev/tools/security/vuln_scanner.py +539 -0
  1064. icdev/tools/simulation/__init__.py +2 -0
  1065. icdev/tools/simulation/coa_generator.py +1552 -0
  1066. icdev/tools/simulation/monte_carlo.py +758 -0
  1067. icdev/tools/simulation/scenario_manager.py +1073 -0
  1068. icdev/tools/simulation/simulation_engine.py +1104 -0
  1069. icdev/tools/supply_chain/__init__.py +2 -0
  1070. icdev/tools/supply_chain/cve_triager.py +705 -0
  1071. icdev/tools/supply_chain/dependency_graph.py +645 -0
  1072. icdev/tools/supply_chain/isa_manager.py +540 -0
  1073. icdev/tools/supply_chain/scrm_assessor.py +546 -0
  1074. icdev/tools/testing/__init__.py +2 -0
  1075. icdev/tools/testing/acceptance_validator.py +411 -0
  1076. icdev/tools/testing/claude_dir_validator.py +831 -0
  1077. icdev/tools/testing/data_types.py +199 -0
  1078. icdev/tools/testing/e2e_runner.py +715 -0
  1079. icdev/tools/testing/fuzz_cli.py +306 -0
  1080. icdev/tools/testing/health_check.py +483 -0
  1081. icdev/tools/testing/platform_check.py +143 -0
  1082. icdev/tools/testing/production_audit.py +1862 -0
  1083. icdev/tools/testing/production_remediate.py +804 -0
  1084. icdev/tools/testing/screenshot_validator.py +539 -0
  1085. icdev/tools/testing/smoke_test.py +283 -0
  1086. icdev/tools/testing/test_agent_models.py +117 -0
  1087. icdev/tools/testing/test_orchestrator.py +957 -0
  1088. icdev/tools/testing/utils.py +229 -0
  1089. icdev/tools/translation/__init__.py +17 -0
  1090. icdev/tools/translation/code_translator.py +550 -0
  1091. icdev/tools/translation/dependency_mapper.py +277 -0
  1092. icdev/tools/translation/feature_map.py +395 -0
  1093. icdev/tools/translation/project_assembler.py +439 -0
  1094. icdev/tools/translation/source_extractor.py +609 -0
  1095. icdev/tools/translation/test_translator.py +333 -0
  1096. icdev/tools/translation/translation_manager.py +582 -0
  1097. icdev/tools/translation/translation_validator.py +662 -0
  1098. icdev/tools/translation/type_checker.py +371 -0
  1099. icdev-1.0.0.dist-info/METADATA +868 -0
  1100. icdev-1.0.0.dist-info/RECORD +1105 -0
  1101. icdev-1.0.0.dist-info/WHEEL +5 -0
  1102. icdev-1.0.0.dist-info/entry_points.txt +9 -0
  1103. icdev-1.0.0.dist-info/licenses/LICENSE +254 -0
  1104. icdev-1.0.0.dist-info/licenses/NOTICE +268 -0
  1105. icdev-1.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,1658 @@
1
+ # [TEMPLATE: CUI // SP-CTI]
2
+ #!/usr/bin/env python3
3
+ """7R Migration Strategy Recommendation Engine for ICDEV DoD Modernization.
4
+
5
+ Evaluates legacy applications against the 7 Rs of cloud migration:
6
+ Rehost, Replatform, Refactor, Rearchitect, Repurchase, Retire, Retain
7
+
8
+ Reads application profile data from legacy_* tables in icdev.db, scores each
9
+ strategy using configurable weighted criteria, and writes a ranked assessment
10
+ to the migration_assessments table. All scoring is deterministic — no LLM
11
+ calls, no external network access.
12
+
13
+ Usage:
14
+ python tools/modernization/seven_r_assessor.py --project-id P-001 --app-id A-001
15
+ python tools/modernization/seven_r_assessor.py --project-id P-001 --app-id A-001 --matrix
16
+ python tools/modernization/seven_r_assessor.py --project-id P-001 --app-id A-001 --json
17
+ python tools/modernization/seven_r_assessor.py --project-id P-001 --app-id A-001 --weights custom.json
18
+
19
+ Classification: CUI // SP-CTI
20
+ Environment: AWS GovCloud (us-gov-west-1)
21
+ Compliance: NIST 800-53 Rev 5 / RMF
22
+ """
23
+
24
+ import argparse
25
+ import json
26
+ import math
27
+ import sqlite3
28
+ import sys
29
+ import uuid
30
+ from datetime import datetime, timezone
31
+ from pathlib import Path
32
+ from icdev._paths import get_project_root
33
+
34
+ # ---------------------------------------------------------------------------
35
+ # Paths
36
+ # ---------------------------------------------------------------------------
37
+ BASE_DIR = get_project_root()
38
+ DB_PATH = BASE_DIR / "data" / "icdev.db"
39
+ CATALOG_PATH = BASE_DIR / "context" / "modernization" / "seven_rs_catalog.json"
40
+
41
+ # ---------------------------------------------------------------------------
42
+ # Known EOL frameworks / languages for fitness checks
43
+ # ---------------------------------------------------------------------------
44
+ EOL_FRAMEWORKS = {
45
+ "struts", "struts2", "ejb2", "jsf", "jsf1",
46
+ "spring2", "spring3",
47
+ "wcf", "webforms", "aspnet-webforms", "silverlight",
48
+ "django1", "flask0",
49
+ "rails3", "rails4",
50
+ "angularjs",
51
+ ".net-framework", "dotnet-framework",
52
+ }
53
+
54
+ EOL_LANGUAGES = {
55
+ ("python", "2"): True,
56
+ ("java", "6"): True,
57
+ ("java", "7"): True,
58
+ ("ruby", "1"): True,
59
+ ("ruby", "2.5"): True,
60
+ ("php", "5"): True,
61
+ ("php", "7.0"): True,
62
+ ("php", "7.1"): True,
63
+ ("php", "7.2"): True,
64
+ ("php", "7.3"): True,
65
+ }
66
+
67
+ # Known version upgrade paths
68
+ KNOWN_UPGRADE_PATHS = {
69
+ ("python", "2"): "3",
70
+ ("java", "8"): "17",
71
+ ("java", "11"): "17",
72
+ ("java", "7"): "17",
73
+ ("dotnet", "framework-4"): "net-8",
74
+ ("csharp", "framework-4"): "net-8",
75
+ ("ruby", "2"): "3",
76
+ ("php", "7"): "8",
77
+ }
78
+
79
+ # Known framework migration paths
80
+ KNOWN_FRAMEWORK_MIGRATIONS = {
81
+ "struts": "spring-boot",
82
+ "struts2": "spring-boot",
83
+ "ejb": "spring-boot",
84
+ "ejb2": "spring-boot",
85
+ "ejb3": "spring-boot",
86
+ "jsf": "spring-boot",
87
+ "wcf": "grpc",
88
+ "webforms": "blazor",
89
+ "aspnet-webforms": "blazor",
90
+ ".net-framework": ".net-8",
91
+ "dotnet-framework": ".net-8",
92
+ "django1": "django4",
93
+ "flask0": "flask3",
94
+ "angularjs": "angular",
95
+ "spring3": "spring-boot",
96
+ "spring4": "spring-boot",
97
+ "rails3": "rails7",
98
+ "rails4": "rails7",
99
+ }
100
+
101
+ # Standard databases that map well to managed services
102
+ STANDARD_DB_TYPES = {"postgres", "postgresql", "mysql", "mariadb", "aurora"}
103
+ MIGRATABLE_DB_TYPES = {"oracle", "mssql", "sqlserver", "sql-server", "db2"}
104
+ EXOTIC_DB_TYPES = {"informix", "sybase", "ingres", "pick", "mumps", "adabas"}
105
+
106
+ # Risk level numeric mapping
107
+ RISK_LEVEL_MAP = {
108
+ "none": 0.0,
109
+ "low": 0.2,
110
+ "medium": 0.5,
111
+ "high": 0.8,
112
+ "critical": 1.0,
113
+ }
114
+
115
+ # ATO impact ordering for display
116
+ ATO_IMPACT_ORDER = {
117
+ "none": 0,
118
+ "low": 1,
119
+ "medium": 2,
120
+ "high": 3,
121
+ "critical": 4,
122
+ }
123
+
124
+
125
+ # ============================================================================
126
+ # Database helper
127
+ # ============================================================================
128
+
129
+ def _get_db(db_path=None):
130
+ """Return a sqlite3 connection with Row factory for dict-like access.
131
+
132
+ Args:
133
+ db_path: Optional override path to the SQLite database.
134
+
135
+ Returns:
136
+ sqlite3.Connection with row_factory set to sqlite3.Row.
137
+
138
+ Raises:
139
+ FileNotFoundError: If the database file does not exist.
140
+ """
141
+ path = db_path or DB_PATH
142
+ if not path.exists():
143
+ raise FileNotFoundError(
144
+ f"Database not found: {path}\n"
145
+ "Run: python tools/db/init_icdev_db.py"
146
+ )
147
+ conn = sqlite3.connect(str(path))
148
+ conn.row_factory = sqlite3.Row
149
+ return conn
150
+
151
+
152
+ # ============================================================================
153
+ # Catalog loader
154
+ # ============================================================================
155
+
156
+ def load_seven_rs_catalog(catalog_path=None):
157
+ """Load the 7 Rs strategy catalog from JSON.
158
+
159
+ Args:
160
+ catalog_path: Optional override path to the catalog JSON file.
161
+
162
+ Returns:
163
+ Parsed dict containing metadata, default_weights, and strategies list.
164
+
165
+ Raises:
166
+ FileNotFoundError: If the catalog file does not exist.
167
+ json.JSONDecodeError: If the catalog contains invalid JSON.
168
+ """
169
+ path = catalog_path or CATALOG_PATH
170
+ if not path.exists():
171
+ raise FileNotFoundError(
172
+ f"Seven Rs catalog not found: {path}\n"
173
+ "Expected at: context/modernization/seven_rs_catalog.json"
174
+ )
175
+ with open(path, "r", encoding="utf-8") as fh:
176
+ catalog = json.load(fh)
177
+ return catalog
178
+
179
+
180
+ # ============================================================================
181
+ # Application profile builder
182
+ # ============================================================================
183
+
184
+ def _get_app_profile(app_id, db_path=None):
185
+ """Query legacy_applications and aggregate stats from related tables.
186
+
187
+ Builds a comprehensive profile dict containing:
188
+ - All columns from legacy_applications
189
+ - Aggregated component statistics (count, avg complexity, avg coupling, etc.)
190
+ - Dependency counts by type
191
+ - API count
192
+ - Database schema information
193
+ - Derived metrics (test ratio, package count, etc.)
194
+
195
+ Args:
196
+ app_id: The legacy application ID to look up.
197
+ db_path: Optional database path override.
198
+
199
+ Returns:
200
+ Dict with all metrics needed for scoring.
201
+
202
+ Raises:
203
+ ValueError: If the application ID is not found in the database.
204
+ """
205
+ conn = _get_db(db_path)
206
+ try:
207
+ # --- Core application row ---
208
+ row = conn.execute(
209
+ "SELECT * FROM legacy_applications WHERE id = ?", (app_id,)
210
+ ).fetchone()
211
+ if row is None:
212
+ raise ValueError(
213
+ f"Application '{app_id}' not found in legacy_applications."
214
+ )
215
+ profile = dict(row)
216
+
217
+ # --- Component aggregates ---
218
+ comp_rows = conn.execute(
219
+ "SELECT * FROM legacy_components WHERE legacy_app_id = ?",
220
+ (app_id,),
221
+ ).fetchall()
222
+
223
+ components = [dict(r) for r in comp_rows]
224
+ profile["components"] = components
225
+ profile["component_count"] = len(components)
226
+
227
+ if components:
228
+ complexities = [c.get("cyclomatic_complexity", 0) or 0 for c in components]
229
+ couplings = [c.get("coupling_score", 0) or 0 for c in components]
230
+ cohesions = [c.get("cohesion_score", 0) or 0 for c in components]
231
+ deps_in = [c.get("dependencies_in", 0) or 0 for c in components]
232
+ deps_out = [c.get("dependencies_out", 0) or 0 for c in components]
233
+ locs = [c.get("loc", 0) or 0 for c in components]
234
+ types = [c.get("component_type", "") for c in components]
235
+
236
+ profile["avg_complexity"] = sum(complexities) / len(complexities)
237
+ profile["max_complexity"] = max(complexities)
238
+ profile["avg_coupling"] = sum(couplings) / len(couplings)
239
+ profile["avg_cohesion"] = sum(cohesions) / len(cohesions)
240
+ profile["total_deps_in"] = sum(deps_in)
241
+ profile["total_deps_out"] = sum(deps_out)
242
+ profile["total_component_loc"] = sum(locs)
243
+ profile["component_types"] = list(set(types))
244
+
245
+ # Count test-related components
246
+ test_types = {"test", "tests", "test_suite", "unit_test", "integration_test", "spec"}
247
+ test_count = sum(1 for t in types if t and t.lower() in test_types)
248
+ profile["test_component_count"] = test_count
249
+ profile["test_component_ratio"] = test_count / len(components) if components else 0.0
250
+
251
+ # Count distinct packages / namespaces
252
+ namespaces = set()
253
+ for c in components:
254
+ ctype = (c.get("component_type") or "").lower()
255
+ if ctype in ("package", "namespace", "module"):
256
+ namespaces.add(c.get("id"))
257
+ profile["distinct_namespaces"] = len(namespaces) if namespaces else max(1, len(set(types)))
258
+ else:
259
+ profile["avg_complexity"] = 0
260
+ profile["max_complexity"] = 0
261
+ profile["avg_coupling"] = 0
262
+ profile["avg_cohesion"] = 0
263
+ profile["total_deps_in"] = 0
264
+ profile["total_deps_out"] = 0
265
+ profile["total_component_loc"] = 0
266
+ profile["component_types"] = []
267
+ profile["test_component_count"] = 0
268
+ profile["test_component_ratio"] = 0.0
269
+ profile["distinct_namespaces"] = 0
270
+
271
+ # --- Dependency aggregates ---
272
+ dep_rows = conn.execute(
273
+ "SELECT * FROM legacy_dependencies WHERE legacy_app_id = ?",
274
+ (app_id,),
275
+ ).fetchall()
276
+ dependencies = [dict(r) for r in dep_rows]
277
+ profile["dependencies"] = dependencies
278
+ profile["dependency_count"] = len(dependencies)
279
+
280
+ dep_type_counts = {}
281
+ for d in dependencies:
282
+ dtype = d.get("dependency_type", "unknown")
283
+ dep_type_counts[dtype] = dep_type_counts.get(dtype, 0) + 1
284
+ profile["dependency_type_counts"] = dep_type_counts
285
+ profile["external_dep_count"] = dep_type_counts.get("external", 0) + dep_type_counts.get("third_party", 0) + dep_type_counts.get("library", 0)
286
+
287
+ # --- API aggregates ---
288
+ api_rows = conn.execute(
289
+ "SELECT * FROM legacy_apis WHERE legacy_app_id = ?",
290
+ (app_id,),
291
+ ).fetchall()
292
+ profile["apis"] = [dict(r) for r in api_rows]
293
+ profile["api_count"] = len(api_rows)
294
+
295
+ # --- DB schema aggregates ---
296
+ db_rows = conn.execute(
297
+ "SELECT * FROM legacy_db_schemas WHERE legacy_app_id = ?",
298
+ (app_id,),
299
+ ).fetchall()
300
+ db_schemas = [dict(r) for r in db_rows]
301
+ profile["db_schemas"] = db_schemas
302
+ profile["db_schema_count"] = len(db_schemas)
303
+ profile["db_types"] = list(set(
304
+ (s.get("db_type") or "unknown").lower() for s in db_schemas
305
+ ))
306
+
307
+ # --- Normalize key fields with safe defaults ---
308
+ profile["loc_total"] = profile.get("loc_total") or 0
309
+ profile["loc_code"] = profile.get("loc_code") or 0
310
+ profile["file_count"] = profile.get("file_count") or 0
311
+ profile["complexity_score"] = profile.get("complexity_score") or 0.0
312
+ profile["tech_debt_hours"] = profile.get("tech_debt_hours") or 0.0
313
+ profile["maintainability_index"] = profile.get("maintainability_index") or 0.0
314
+ profile["primary_language"] = (profile.get("primary_language") or "unknown").lower()
315
+ profile["language_version"] = (profile.get("language_version") or "").lower()
316
+ profile["framework"] = (profile.get("framework") or "unknown").lower()
317
+ profile["framework_version"] = (profile.get("framework_version") or "").lower()
318
+ profile["app_type"] = (profile.get("app_type") or "unknown").lower()
319
+
320
+ return profile
321
+ finally:
322
+ conn.close()
323
+
324
+
325
+ # ============================================================================
326
+ # Fitness check functions — one per strategy
327
+ # ============================================================================
328
+
329
+ def _check_rehost_fitness(profile):
330
+ """Evaluate rehost (lift-and-shift) fitness.
331
+
332
+ Criteria:
333
+ containerizable — minimal OS/file-system coupling
334
+ external_deps_minimal — few external dependencies
335
+ config_externalizable — config separate from code
336
+ stateless — no heavy local state / file writes
337
+ security_clean — good maintainability, low complexity
338
+
339
+ Returns:
340
+ Dict mapping criterion name to float score in [0.0, 1.0].
341
+ """
342
+ scores = {}
343
+
344
+ # containerizable: heuristic based on dependency types
345
+ os_dep_keywords = {"os-specific", "hardware", "native", "driver", "kernel", "system"}
346
+ file_dep_keywords = {"file-io", "local-storage", "nfs", "smb", "cifs", "shared-drive"}
347
+
348
+ os_count = 0
349
+ file_count = 0
350
+ for d in profile.get("dependencies", []):
351
+ dtype = (d.get("dependency_type") or "").lower()
352
+ if any(k in dtype for k in os_dep_keywords):
353
+ os_count += 1
354
+ if any(k in dtype for k in file_dep_keywords):
355
+ file_count += 1
356
+
357
+ heavy_count = os_count + file_count
358
+ if heavy_count == 0:
359
+ scores["containerizable"] = 1.0
360
+ elif heavy_count <= 3:
361
+ scores["containerizable"] = 0.5
362
+ else:
363
+ scores["containerizable"] = 0.0
364
+
365
+ # external_deps_minimal
366
+ ext_count = profile.get("external_dep_count", 0)
367
+ if ext_count < 5:
368
+ scores["external_deps_minimal"] = 1.0
369
+ elif ext_count <= 15:
370
+ scores["external_deps_minimal"] = 0.5
371
+ else:
372
+ scores["external_deps_minimal"] = 0.0
373
+
374
+ # config_externalizable: heuristic — if file_count > 0 and complexity is
375
+ # low, config is likely separable. We use a proxy: maintainability > 50
376
+ # and low coupling suggest well-structured config.
377
+ maint = profile.get("maintainability_index", 0)
378
+ coupling = profile.get("avg_coupling", 0)
379
+ if maint > 50 and coupling < 0.5:
380
+ scores["config_externalizable"] = 1.0
381
+ elif maint > 30 or coupling < 0.7:
382
+ scores["config_externalizable"] = 0.5
383
+ else:
384
+ scores["config_externalizable"] = 0.0
385
+
386
+ # stateless: check for local-file write type dependencies
387
+ write_keywords = {"file-write", "local-write", "local-storage", "tmp-storage", "session-file"}
388
+ write_count = 0
389
+ for d in profile.get("dependencies", []):
390
+ dtype = (d.get("dependency_type") or "").lower()
391
+ if any(k in dtype for k in write_keywords):
392
+ write_count += 1
393
+ if write_count == 0:
394
+ scores["stateless"] = 1.0
395
+ elif write_count <= 2:
396
+ scores["stateless"] = 0.5
397
+ else:
398
+ scores["stateless"] = 0.0
399
+
400
+ # security_clean: maintainability > 60 AND avg complexity < 15
401
+ avg_cx = profile.get("avg_complexity", 0)
402
+ if maint > 60 and avg_cx < 15:
403
+ scores["security_clean"] = 1.0
404
+ elif maint > 40 and avg_cx < 25:
405
+ scores["security_clean"] = 0.5
406
+ else:
407
+ scores["security_clean"] = 0.0
408
+
409
+ return scores
410
+
411
+
412
+ def _check_replatform_fitness(profile):
413
+ """Evaluate replatform (lift-tinker-shift) fitness.
414
+
415
+ Criteria:
416
+ managed_db_candidate — database can move to managed service
417
+ container_ready_with_tweaks — mostly containerizable
418
+ config_separable — config extractable to env vars
419
+ cloud_services_available — standard service replacements exist
420
+ minor_code_changes_only — less than 10% code needs changes
421
+
422
+ Returns:
423
+ Dict mapping criterion name to float score in [0.0, 1.0].
424
+ """
425
+ scores = {}
426
+
427
+ # managed_db_candidate
428
+ db_types = set(profile.get("db_types", []))
429
+ if not db_types or db_types <= STANDARD_DB_TYPES:
430
+ scores["managed_db_candidate"] = 1.0
431
+ elif db_types & MIGRATABLE_DB_TYPES:
432
+ scores["managed_db_candidate"] = 0.5
433
+ elif db_types & EXOTIC_DB_TYPES:
434
+ scores["managed_db_candidate"] = 0.0
435
+ else:
436
+ # Unknown DB type — conservative score
437
+ scores["managed_db_candidate"] = 0.5
438
+
439
+ # container_ready_with_tweaks: reuse containerizable from rehost, but
440
+ # accept slightly worse scores.
441
+ rehost_fit = _check_rehost_fitness(profile)
442
+ container_score = rehost_fit.get("containerizable", 0.0)
443
+ if container_score >= 0.5:
444
+ scores["container_ready_with_tweaks"] = 1.0
445
+ elif container_score > 0.0:
446
+ scores["container_ready_with_tweaks"] = 0.5
447
+ else:
448
+ scores["container_ready_with_tweaks"] = 0.0
449
+
450
+ # config_separable
451
+ maint = profile.get("maintainability_index", 0)
452
+ coupling = profile.get("avg_coupling", 0)
453
+ if maint > 40 and coupling < 0.6:
454
+ scores["config_separable"] = 1.0
455
+ elif maint > 25 or coupling < 0.8:
456
+ scores["config_separable"] = 0.5
457
+ else:
458
+ scores["config_separable"] = 0.0
459
+
460
+ # cloud_services_available: standard app types have good cloud equivalents
461
+ app_type = profile.get("app_type", "unknown")
462
+ standard_app_types = {"web", "api", "microservice", "batch", "worker", "queue-consumer", "rest-api"}
463
+ custom_app_types = {"desktop", "embedded", "hardware-interface", "mainframe"}
464
+ if app_type in standard_app_types:
465
+ scores["cloud_services_available"] = 1.0
466
+ elif app_type in custom_app_types:
467
+ scores["cloud_services_available"] = 0.0
468
+ else:
469
+ scores["cloud_services_available"] = 0.5
470
+
471
+ # minor_code_changes_only: low tech debt + good maintainability means
472
+ # changes should be small
473
+ loc_total = profile.get("loc_total", 1)
474
+ tech_debt = profile.get("tech_debt_hours", 0)
475
+ # Rough heuristic: tech_debt_hours / (loc_total/100) gives a debt density
476
+ debt_density = (tech_debt / max(loc_total / 100.0, 1.0))
477
+ if debt_density < 5 and maint > 50:
478
+ scores["minor_code_changes_only"] = 1.0
479
+ elif debt_density < 15 and maint > 30:
480
+ scores["minor_code_changes_only"] = 0.5
481
+ else:
482
+ scores["minor_code_changes_only"] = 0.0
483
+
484
+ return scores
485
+
486
+
487
+ def _check_refactor_fitness(profile):
488
+ """Evaluate refactor (code-level modernization) fitness.
489
+
490
+ Criteria:
491
+ version_upgrade_path_exists — known upgrade path for language
492
+ framework_migration_path_exists — known migration for framework
493
+ test_coverage_adequate — sufficient test components
494
+ codebase_well_structured — maintainability index
495
+ dependencies_manageable — component count not overwhelming
496
+
497
+ Returns:
498
+ Dict mapping criterion name to float score in [0.0, 1.0].
499
+ """
500
+ scores = {}
501
+
502
+ # version_upgrade_path_exists
503
+ lang = profile.get("primary_language", "")
504
+ lang_ver = profile.get("language_version", "")
505
+ # Normalize: take just the major version for matching
506
+ lang_ver_major = lang_ver.split(".")[0] if lang_ver else ""
507
+ key = (lang, lang_ver_major)
508
+ if key in KNOWN_UPGRADE_PATHS:
509
+ scores["version_upgrade_path_exists"] = 1.0
510
+ elif lang_ver:
511
+ # Version specified but no known path — partial credit
512
+ scores["version_upgrade_path_exists"] = 0.3
513
+ else:
514
+ scores["version_upgrade_path_exists"] = 0.0
515
+
516
+ # framework_migration_path_exists
517
+ framework = profile.get("framework", "").lower().strip()
518
+ framework_normalized = framework.replace(" ", "-").replace("_", "-")
519
+ if framework_normalized in KNOWN_FRAMEWORK_MIGRATIONS:
520
+ scores["framework_migration_path_exists"] = 1.0
521
+ elif framework and framework != "unknown":
522
+ scores["framework_migration_path_exists"] = 0.3
523
+ else:
524
+ scores["framework_migration_path_exists"] = 0.0
525
+
526
+ # test_coverage_adequate: >20% test components is good, some is partial
527
+ test_ratio = profile.get("test_component_ratio", 0.0)
528
+ if test_ratio >= 0.20:
529
+ scores["test_coverage_adequate"] = 1.0
530
+ elif test_ratio > 0.0:
531
+ scores["test_coverage_adequate"] = 0.5
532
+ else:
533
+ scores["test_coverage_adequate"] = 0.0
534
+
535
+ # codebase_well_structured: maintainability index
536
+ maint = profile.get("maintainability_index", 0)
537
+ if maint > 50:
538
+ scores["codebase_well_structured"] = 1.0
539
+ elif maint >= 25:
540
+ scores["codebase_well_structured"] = 0.5
541
+ else:
542
+ scores["codebase_well_structured"] = 0.0
543
+
544
+ # dependencies_manageable: component count
545
+ comp_count = profile.get("component_count", 0)
546
+ if comp_count < 50:
547
+ scores["dependencies_manageable"] = 1.0
548
+ elif comp_count <= 200:
549
+ scores["dependencies_manageable"] = 0.5
550
+ else:
551
+ scores["dependencies_manageable"] = 0.0
552
+
553
+ return scores
554
+
555
+
556
+ def _check_rearchitect_fitness(profile):
557
+ """Evaluate rearchitect (rebuild cloud-native) fitness.
558
+
559
+ Criteria:
560
+ bounded_contexts_identifiable — distinct packages with low coupling
561
+ api_boundaries_clear — well-defined API endpoints
562
+ data_stores_separable — database schemas cluster
563
+ team_capacity_sufficient — default 0.5 (needs manual input)
564
+ business_value_high — default 0.5 (needs manual input)
565
+
566
+ Returns:
567
+ Dict mapping criterion name to float score in [0.0, 1.0].
568
+ """
569
+ scores = {}
570
+
571
+ # bounded_contexts_identifiable: >3 namespaces with avg_coupling < 0.5
572
+ namespaces = profile.get("distinct_namespaces", 0)
573
+ avg_coupling = profile.get("avg_coupling", 1.0)
574
+ if namespaces > 3 and avg_coupling < 0.5:
575
+ scores["bounded_contexts_identifiable"] = 1.0
576
+ elif namespaces > 2 and avg_coupling < 0.7:
577
+ scores["bounded_contexts_identifiable"] = 0.5
578
+ else:
579
+ scores["bounded_contexts_identifiable"] = 0.0
580
+
581
+ # api_boundaries_clear: >5 API endpoints suggest clear grouping
582
+ api_count = profile.get("api_count", 0)
583
+ if api_count >= 5:
584
+ scores["api_boundaries_clear"] = 1.0
585
+ elif api_count >= 2:
586
+ scores["api_boundaries_clear"] = 0.5
587
+ else:
588
+ scores["api_boundaries_clear"] = 0.0
589
+
590
+ # data_stores_separable: multiple DB schemas suggest separable data
591
+ db_count = profile.get("db_schema_count", 0)
592
+ if db_count >= 3:
593
+ scores["data_stores_separable"] = 1.0
594
+ elif db_count >= 2:
595
+ scores["data_stores_separable"] = 0.5
596
+ else:
597
+ scores["data_stores_separable"] = 0.0
598
+
599
+ # team_capacity_sufficient: requires manual assessment, default 0.5
600
+ scores["team_capacity_sufficient"] = 0.5
601
+
602
+ # business_value_high: requires manual assessment, default 0.5
603
+ scores["business_value_high"] = 0.5
604
+
605
+ return scores
606
+
607
+
608
+ def _check_repurchase_fitness(profile):
609
+ """Evaluate repurchase (buy COTS/GOTS replacement) fitness.
610
+
611
+ Criteria:
612
+ commodity_functionality — is it a common business function (default)
613
+ cots_alternative_available — needs manual assessment (default)
614
+ low_customization — LOC indicates customization level
615
+ data_migration_feasible — default, needs manual assessment
616
+
617
+ Returns:
618
+ Dict mapping criterion name to float score in [0.0, 1.0].
619
+ """
620
+ scores = {}
621
+
622
+ # commodity_functionality: default — needs manual assessment
623
+ scores["commodity_functionality"] = 0.5
624
+
625
+ # cots_alternative_available: default — needs manual assessment
626
+ scores["cots_alternative_available"] = 0.5
627
+
628
+ # low_customization: based on LOC
629
+ loc = profile.get("loc_code", 0) or profile.get("loc_total", 0)
630
+ if loc < 5000:
631
+ scores["low_customization"] = 1.0
632
+ elif loc <= 20000:
633
+ scores["low_customization"] = 0.5
634
+ else:
635
+ scores["low_customization"] = 0.0
636
+
637
+ # data_migration_feasible: default — needs manual assessment
638
+ scores["data_migration_feasible"] = 0.5
639
+
640
+ return scores
641
+
642
+
643
+ def _check_retire_fitness(profile):
644
+ """Evaluate retire (decommission) fitness.
645
+
646
+ Criteria:
647
+ low_usage — default 0.5 (needs usage data)
648
+ redundant_functionality — default 0.5
649
+ eol_dependencies — framework/language at end-of-life
650
+ no_active_development — default 0.5
651
+
652
+ Returns:
653
+ Dict mapping criterion name to float score in [0.0, 1.0].
654
+ """
655
+ scores = {}
656
+
657
+ # low_usage: requires usage telemetry, default 0.5
658
+ scores["low_usage"] = 0.5
659
+
660
+ # redundant_functionality: default 0.5
661
+ scores["redundant_functionality"] = 0.5
662
+
663
+ # eol_dependencies: check if framework or language version is EOL
664
+ framework = profile.get("framework", "").lower().strip().replace(" ", "-").replace("_", "-")
665
+ lang = profile.get("primary_language", "")
666
+ lang_ver = profile.get("language_version", "")
667
+ lang_ver_major = lang_ver.split(".")[0] if lang_ver else ""
668
+
669
+ is_eol = False
670
+ if framework in EOL_FRAMEWORKS:
671
+ is_eol = True
672
+ if (lang, lang_ver_major) in EOL_LANGUAGES:
673
+ is_eol = True
674
+ # Also check framework + major version combos
675
+ if framework and not is_eol:
676
+ fw_ver = profile.get("framework_version", "")
677
+ fw_ver_major = fw_ver.split(".")[0] if fw_ver else ""
678
+ combined = f"{framework}{fw_ver_major}"
679
+ if combined in EOL_FRAMEWORKS:
680
+ is_eol = True
681
+
682
+ scores["eol_dependencies"] = 1.0 if is_eol else 0.0
683
+
684
+ # no_active_development: default 0.5
685
+ scores["no_active_development"] = 0.5
686
+
687
+ return scores
688
+
689
+
690
+ def _check_retain_fitness(profile):
691
+ """Evaluate retain (keep in place) fitness.
692
+
693
+ Criteria:
694
+ stable_operation — low complexity and good maintainability
695
+ no_ato_blockers — maintainability > 40 and complexity < 20
696
+ low_risk — tech debt hours < 100
697
+ recent_framework — framework is not EOL
698
+
699
+ Returns:
700
+ Dict mapping criterion name to float score in [0.0, 1.0].
701
+ """
702
+ scores = {}
703
+
704
+ maint = profile.get("maintainability_index", 0)
705
+ avg_cx = profile.get("avg_complexity", 0)
706
+ tech_debt = profile.get("tech_debt_hours", 0)
707
+
708
+ # stable_operation: low complexity and good maintainability
709
+ if avg_cx < 10 and maint > 60:
710
+ scores["stable_operation"] = 1.0
711
+ elif avg_cx < 20 and maint > 40:
712
+ scores["stable_operation"] = 0.5
713
+ else:
714
+ scores["stable_operation"] = 0.0
715
+
716
+ # no_ato_blockers: maintainability > 40 and complexity < 20
717
+ if maint > 40 and avg_cx < 20:
718
+ scores["no_ato_blockers"] = 1.0
719
+ elif maint > 25 and avg_cx < 30:
720
+ scores["no_ato_blockers"] = 0.5
721
+ else:
722
+ scores["no_ato_blockers"] = 0.0
723
+
724
+ # low_risk: tech_debt_hours < 100
725
+ if tech_debt < 100:
726
+ scores["low_risk"] = 1.0
727
+ elif tech_debt < 500:
728
+ scores["low_risk"] = 0.5
729
+ else:
730
+ scores["low_risk"] = 0.0
731
+
732
+ # recent_framework: framework is NOT EOL
733
+ framework = profile.get("framework", "").lower().strip().replace(" ", "-").replace("_", "-")
734
+ lang = profile.get("primary_language", "")
735
+ lang_ver = profile.get("language_version", "")
736
+ lang_ver_major = lang_ver.split(".")[0] if lang_ver else ""
737
+
738
+ is_eol = False
739
+ if framework in EOL_FRAMEWORKS:
740
+ is_eol = True
741
+ if (lang, lang_ver_major) in EOL_LANGUAGES:
742
+ is_eol = True
743
+
744
+ scores["recent_framework"] = 0.0 if is_eol else 1.0
745
+
746
+ return scores
747
+
748
+
749
+ # ============================================================================
750
+ # Scoring engine
751
+ # ============================================================================
752
+
753
+ def _score_strategy(strategy_id, check_results, catalog_criteria, weights=None):
754
+ """Compute weighted score for a single strategy.
755
+
756
+ For each criterion in the catalog, multiply the check_result by the
757
+ criterion's weight. Sum all weighted scores. Apply the strategy's
758
+ effort_multiplier as a penalty (higher effort = lower attractiveness).
759
+
760
+ The raw weighted sum is in [0.0, 1.0] because criterion weights sum to
761
+ ~1.0 and check results are in [0.0, 1.0]. The effort penalty adjusts
762
+ the final score to favour lower-effort strategies when fitness is equal.
763
+
764
+ Args:
765
+ strategy_id: The strategy identifier (e.g. "rehost").
766
+ check_results: Dict of {criterion_name: score} from _check_*_fitness.
767
+ catalog_criteria: Dict of {criterion_name: {weight, description}} from
768
+ the catalog's scoring_criteria for this strategy.
769
+ weights: Optional dict of custom criterion weights to override
770
+ catalog defaults.
771
+
772
+ Returns:
773
+ Float score in [0.0, 1.0] (normalized).
774
+ """
775
+ if not catalog_criteria:
776
+ return 0.0
777
+
778
+ # Build effective weights: start with catalog, override with custom
779
+ effective_weights = {}
780
+ for crit_name, crit_info in catalog_criteria.items():
781
+ effective_weights[crit_name] = crit_info.get("weight", 0.0)
782
+
783
+ if weights and strategy_id in weights:
784
+ for crit_name, w in weights[strategy_id].items():
785
+ if crit_name in effective_weights:
786
+ effective_weights[crit_name] = w
787
+
788
+ # Calculate weighted sum. For catalog criteria that have no matching
789
+ # check_result key, we map by positional order (catalog criterion → check
790
+ # result) to bridge the gap between catalog criterion names and the
791
+ # check function criterion names.
792
+ catalog_crit_names = list(catalog_criteria.keys())
793
+ check_crit_names = list(check_results.keys())
794
+
795
+ weighted_sum = 0.0
796
+ total_weight = 0.0
797
+
798
+ for i, cat_crit in enumerate(catalog_crit_names):
799
+ weight = effective_weights.get(cat_crit, 0.0)
800
+ # Direct name match first
801
+ if cat_crit in check_results:
802
+ score = check_results[cat_crit]
803
+ elif i < len(check_crit_names):
804
+ # Positional fallback: map i-th catalog criterion to i-th check result
805
+ score = check_results[check_crit_names[i]]
806
+ else:
807
+ # No matching check result — assume neutral score
808
+ score = 0.5
809
+ weighted_sum += score * weight
810
+ total_weight += weight
811
+
812
+ # Normalize to [0.0, 1.0] if weights don't sum to 1.0
813
+ if total_weight > 0:
814
+ raw_score = weighted_sum / total_weight
815
+ else:
816
+ raw_score = 0.0
817
+
818
+ # Clamp to [0.0, 1.0]
819
+ return max(0.0, min(1.0, raw_score))
820
+
821
+
822
+ def _rank_strategies(scores):
823
+ """Sort strategies by score descending and assign ranks.
824
+
825
+ Args:
826
+ scores: Dict of {strategy_id: score_float}.
827
+
828
+ Returns:
829
+ List of dicts: [{rank, strategy_id, score}, ...] ordered by score desc.
830
+ """
831
+ sorted_items = sorted(scores.items(), key=lambda x: x[1], reverse=True)
832
+ ranked = []
833
+ for rank_idx, (strategy_id, score) in enumerate(sorted_items, start=1):
834
+ ranked.append({
835
+ "rank": rank_idx,
836
+ "strategy_id": strategy_id,
837
+ "score": round(score, 4),
838
+ })
839
+ return ranked
840
+
841
+
842
+ # ============================================================================
843
+ # ATO impact, cost, and timeline estimation
844
+ # ============================================================================
845
+
846
+ def _assess_ato_impact(profile, strategy):
847
+ """Determine the ATO impact level for the recommended strategy.
848
+
849
+ ATO impact levels:
850
+ none — rehost, retain, retire (no system change boundary)
851
+ low — replatform (minor infra changes)
852
+ medium — refactor (version change may affect compliance docs)
853
+ high — rearchitect (new architecture requires new ATO boundary)
854
+ critical — repurchase (completely new system, full new ATO)
855
+
856
+ Args:
857
+ profile: The application profile dict (unused in base impl but
858
+ available for future refinement).
859
+ strategy: Strategy ID string.
860
+
861
+ Returns:
862
+ String: one of 'none', 'low', 'medium', 'high', 'critical'.
863
+ """
864
+ impact_map = {
865
+ "rehost": "none",
866
+ "replatform": "low",
867
+ "refactor": "medium",
868
+ "rearchitect": "high",
869
+ "repurchase": "critical",
870
+ "retire": "none",
871
+ "retain": "none",
872
+ }
873
+ return impact_map.get(strategy, "medium")
874
+
875
+
876
+ def _estimate_cost(profile, strategy, catalog):
877
+ """Estimate migration cost in person-hours.
878
+
879
+ Formula: (LOC / 20) * effort_multiplier * complexity_factor
880
+
881
+ The complexity factor adjusts for codebase health:
882
+ - maintainability > 60: factor 0.8 (healthy code, faster work)
883
+ - maintainability 30-60: factor 1.0 (normal)
884
+ - maintainability < 30: factor 1.5 (poor code, slower work)
885
+
886
+ An additional adjustment is made for high cyclomatic complexity:
887
+ - avg_complexity > 25: +20%
888
+ - avg_complexity > 40: +40%
889
+
890
+ Args:
891
+ profile: Application profile dict.
892
+ strategy: Strategy ID string.
893
+ catalog: Parsed catalog dict.
894
+
895
+ Returns:
896
+ Integer: estimated person-hours.
897
+ """
898
+ loc = max(profile.get("loc_code", 0), profile.get("loc_total", 0), 1)
899
+
900
+ # Find effort_multiplier from catalog
901
+ effort_multiplier = 1.0
902
+ for s in catalog.get("strategies", []):
903
+ if s["id"] == strategy:
904
+ effort_multiplier = s.get("effort_multiplier", 1.0)
905
+ break
906
+
907
+ # Complexity factor based on maintainability index
908
+ maint = profile.get("maintainability_index", 50)
909
+ if maint > 60:
910
+ complexity_factor = 0.8
911
+ elif maint >= 30:
912
+ complexity_factor = 1.0
913
+ else:
914
+ complexity_factor = 1.5
915
+
916
+ # Cyclomatic complexity adjustment
917
+ avg_cx = profile.get("avg_complexity", 0)
918
+ cx_adjustment = 1.0
919
+ if avg_cx > 40:
920
+ cx_adjustment = 1.4
921
+ elif avg_cx > 25:
922
+ cx_adjustment = 1.2
923
+
924
+ base_hours = loc / 20.0
925
+ total_hours = base_hours * effort_multiplier * complexity_factor * cx_adjustment
926
+
927
+ # Minimum cost: 8 hours (1 day) for any migration activity
928
+ return max(8, int(math.ceil(total_hours)))
929
+
930
+
931
+ def _estimate_timeline(profile, strategy, catalog):
932
+ """Estimate migration timeline in weeks.
933
+
934
+ Formula: cost_hours / 40 (1 FTE equivalent per week).
935
+ Minimum 2 weeks for any strategy.
936
+
937
+ Also considers the catalog's typical_timeline_weeks as a floor/ceiling
938
+ sanity check.
939
+
940
+ Args:
941
+ profile: Application profile dict.
942
+ strategy: Strategy ID string.
943
+ catalog: Parsed catalog dict.
944
+
945
+ Returns:
946
+ Integer: estimated weeks.
947
+ """
948
+ cost_hours = _estimate_cost(profile, strategy, catalog)
949
+ raw_weeks = cost_hours / 40.0
950
+
951
+ # Look up catalog typical timeline for bounds checking
952
+ typical_min = 1
953
+ typical_max = 999
954
+ for s in catalog.get("strategies", []):
955
+ if s["id"] == strategy:
956
+ timeline = s.get("typical_timeline_weeks", {})
957
+ typical_min = timeline.get("min", 1)
958
+ typical_max = timeline.get("max", 999)
959
+ break
960
+
961
+ # Apply minimum of 2 weeks
962
+ weeks = max(2, int(math.ceil(raw_weeks)))
963
+
964
+ # Clamp to catalog bounds (with some flexibility — allow 50% over max)
965
+ weeks = max(weeks, typical_min)
966
+ weeks = min(weeks, int(typical_max * 1.5))
967
+
968
+ return weeks
969
+
970
+
971
+ # ============================================================================
972
+ # Tech debt reduction estimator
973
+ # ============================================================================
974
+
975
+ def _estimate_tech_debt_reduction(profile, strategy):
976
+ """Estimate the percentage of technical debt addressed by the strategy.
977
+
978
+ Different strategies address different amounts of existing tech debt:
979
+ retain: 0% — no changes
980
+ rehost: 5% — minimal infra-related debt resolved
981
+ replatform: 15% — platform-level debt resolved
982
+ refactor: 50% — direct code-level debt remediation
983
+ rearchitect: 80% — near-complete rebuild eliminates most debt
984
+ repurchase: 90% — new system eliminates legacy debt
985
+ retire: 100% — system removed entirely
986
+
987
+ Args:
988
+ profile: Application profile dict.
989
+ strategy: Strategy ID string.
990
+
991
+ Returns:
992
+ Float: percentage of tech debt reduction (0.0 to 100.0).
993
+ """
994
+ reduction_map = {
995
+ "retain": 0.0,
996
+ "rehost": 5.0,
997
+ "replatform": 15.0,
998
+ "refactor": 50.0,
999
+ "rearchitect": 80.0,
1000
+ "repurchase": 90.0,
1001
+ "retire": 100.0,
1002
+ }
1003
+ return reduction_map.get(strategy, 0.0)
1004
+
1005
+
1006
+ # ============================================================================
1007
+ # Risk scoring
1008
+ # ============================================================================
1009
+
1010
+ def _compute_risk_score(profile, strategy, catalog):
1011
+ """Compute a risk score in [0.0, 1.0] combining strategy risk, profile
1012
+ health, and ATO impact.
1013
+
1014
+ Components (weighted):
1015
+ - Strategy inherent risk (from catalog risk_level): 40%
1016
+ - Application health risk (inverse of maintainability): 30%
1017
+ - ATO impact risk: 20%
1018
+ - Dependency risk (count of external deps): 10%
1019
+
1020
+ Args:
1021
+ profile: Application profile dict.
1022
+ strategy: Strategy ID string.
1023
+ catalog: Parsed catalog dict.
1024
+
1025
+ Returns:
1026
+ Float risk score in [0.0, 1.0].
1027
+ """
1028
+ # Strategy inherent risk
1029
+ strategy_risk = 0.5
1030
+ for s in catalog.get("strategies", []):
1031
+ if s["id"] == strategy:
1032
+ strategy_risk = RISK_LEVEL_MAP.get(s.get("risk_level", "medium"), 0.5)
1033
+ break
1034
+
1035
+ # Application health risk: inverse maintainability (0-100 scale)
1036
+ maint = profile.get("maintainability_index", 50)
1037
+ health_risk = max(0.0, min(1.0, 1.0 - (maint / 100.0)))
1038
+
1039
+ # ATO impact risk
1040
+ ato_impact = _assess_ato_impact(profile, strategy)
1041
+ ato_risk = ATO_IMPACT_ORDER.get(ato_impact, 2) / 4.0
1042
+
1043
+ # Dependency risk
1044
+ ext_deps = profile.get("external_dep_count", 0)
1045
+ if ext_deps < 5:
1046
+ dep_risk = 0.0
1047
+ elif ext_deps <= 15:
1048
+ dep_risk = 0.3
1049
+ elif ext_deps <= 30:
1050
+ dep_risk = 0.6
1051
+ else:
1052
+ dep_risk = 1.0
1053
+
1054
+ # Weighted combination
1055
+ risk = (
1056
+ strategy_risk * 0.4
1057
+ + health_risk * 0.3
1058
+ + ato_risk * 0.2
1059
+ + dep_risk * 0.1
1060
+ )
1061
+ return round(max(0.0, min(1.0, risk)), 4)
1062
+
1063
+
1064
+ # ============================================================================
1065
+ # Main orchestrator
1066
+ # ============================================================================
1067
+
1068
+ def _get_ui_complexity(app_id, project_id, db_path=None):
1069
+ """Query stored UI analysis for a legacy application.
1070
+
1071
+ If tools/modernization/ui_analyzer.py has been run against screenshots
1072
+ of this application, the complexity score is stored as JSON in the
1073
+ legacy_applications metadata column.
1074
+
1075
+ Args:
1076
+ app_id: Legacy application ID.
1077
+ project_id: Project ID.
1078
+ db_path: Optional database path override.
1079
+
1080
+ Returns:
1081
+ Float complexity score (0.0-1.0) or None if no UI analysis exists.
1082
+ """
1083
+ try:
1084
+ conn = _get_db(db_path)
1085
+ row = conn.execute(
1086
+ "SELECT metadata FROM legacy_applications WHERE id = ?", (app_id,)
1087
+ ).fetchone()
1088
+ conn.close()
1089
+
1090
+ if row and row["metadata"]:
1091
+ metadata = json.loads(row["metadata"]) if isinstance(row["metadata"], str) else row["metadata"]
1092
+ ui_analysis = metadata.get("ui_analysis", {})
1093
+ if "complexity_score" in ui_analysis:
1094
+ return float(ui_analysis["complexity_score"])
1095
+ except Exception:
1096
+ pass
1097
+ return None
1098
+
1099
+
1100
+ def _apply_ui_complexity_adjustment(strategy_scores, ui_complexity):
1101
+ """Apply UI complexity adjustment to 7R strategy scores.
1102
+
1103
+ High UI complexity favors Rearchitect, penalizes Rehost.
1104
+ Low UI complexity favors Replatform.
1105
+ This is an optional dimension (D85 — backward compatible).
1106
+
1107
+ Args:
1108
+ strategy_scores: Dict of strategy_id -> score.
1109
+ ui_complexity: Float 0.0-1.0.
1110
+
1111
+ Returns:
1112
+ Adjusted strategy_scores dict.
1113
+ """
1114
+ if ui_complexity is None:
1115
+ return strategy_scores
1116
+
1117
+ # Weight for UI complexity dimension (10% of total)
1118
+ weight = 0.10
1119
+
1120
+ adjustments = {}
1121
+ if ui_complexity > 0.7:
1122
+ # High UI complexity → favors Rearchitect, penalizes Rehost
1123
+ adjustments = {
1124
+ "rehost": -weight * 0.5,
1125
+ "replatform": -weight * 0.2,
1126
+ "rearchitect": weight * 0.5,
1127
+ "refactor": weight * 0.3,
1128
+ }
1129
+ elif ui_complexity < 0.3:
1130
+ # Low UI complexity → favors Replatform
1131
+ adjustments = {
1132
+ "rehost": weight * 0.2,
1133
+ "replatform": weight * 0.4,
1134
+ "rearchitect": -weight * 0.1,
1135
+ }
1136
+ else:
1137
+ # Moderate UI complexity → slight Refactor bias
1138
+ adjustments = {
1139
+ "refactor": weight * 0.2,
1140
+ "rearchitect": weight * 0.1,
1141
+ }
1142
+
1143
+ adjusted = dict(strategy_scores)
1144
+ for strategy_id, adj in adjustments.items():
1145
+ if strategy_id in adjusted:
1146
+ adjusted[strategy_id] = max(0.0, min(1.0, adjusted[strategy_id] + adj))
1147
+
1148
+ return adjusted
1149
+
1150
+
1151
+ def run_seven_r_assessment(project_id, app_id, custom_weights=None, db_path=None):
1152
+ """Orchestrate a full 7R assessment for one legacy application.
1153
+
1154
+ Steps:
1155
+ 1. Load the 7Rs catalog
1156
+ 2. Build the application profile from legacy_* tables
1157
+ 3. Run all 7 fitness check functions
1158
+ 4. Score each strategy against its catalog criteria
1159
+ 4b. (Optional) Apply UI complexity adjustment if analysis available
1160
+ 5. Rank strategies by score
1161
+ 6. Assess ATO impact for recommended (top-ranked) strategy
1162
+ 7. Estimate cost and timeline
1163
+ 8. Store results in migration_assessments table (INSERT OR REPLACE)
1164
+ 9. Return the complete assessment dict
1165
+
1166
+ Args:
1167
+ project_id: The project ID for context.
1168
+ app_id: The legacy application ID to assess.
1169
+ custom_weights: Optional dict of custom weights per strategy.
1170
+ db_path: Optional database path override.
1171
+
1172
+ Returns:
1173
+ Dict containing the full assessment: scores, ranking, recommendation,
1174
+ cost, timeline, ATO impact, evidence, and metadata.
1175
+ """
1176
+ catalog = load_seven_rs_catalog()
1177
+ profile = _get_app_profile(app_id, db_path=db_path)
1178
+
1179
+ # Run all fitness checks
1180
+ fitness_results = {
1181
+ "rehost": _check_rehost_fitness(profile),
1182
+ "replatform": _check_replatform_fitness(profile),
1183
+ "refactor": _check_refactor_fitness(profile),
1184
+ "rearchitect": _check_rearchitect_fitness(profile),
1185
+ "repurchase": _check_repurchase_fitness(profile),
1186
+ "retire": _check_retire_fitness(profile),
1187
+ "retain": _check_retain_fitness(profile),
1188
+ }
1189
+
1190
+ # Build a lookup: strategy_id → scoring_criteria from catalog
1191
+ catalog_criteria_map = {}
1192
+ for strat in catalog.get("strategies", []):
1193
+ catalog_criteria_map[strat["id"]] = strat.get("scoring_criteria", {})
1194
+
1195
+ # Score each strategy
1196
+ strategy_scores = {}
1197
+ for strategy_id, check_results in fitness_results.items():
1198
+ cat_criteria = catalog_criteria_map.get(strategy_id, {})
1199
+ strategy_scores[strategy_id] = _score_strategy(
1200
+ strategy_id, check_results, cat_criteria, weights=custom_weights
1201
+ )
1202
+
1203
+ # Optional: Apply UI complexity adjustment (D85 — backward compatible)
1204
+ ui_complexity = _get_ui_complexity(app_id, project_id, db_path=db_path)
1205
+ if ui_complexity is not None:
1206
+ strategy_scores = _apply_ui_complexity_adjustment(strategy_scores, ui_complexity)
1207
+
1208
+ # Rank strategies
1209
+ ranking = _rank_strategies(strategy_scores)
1210
+ recommended = ranking[0]["strategy_id"] if ranking else "retain"
1211
+
1212
+ # ATO impact for recommended strategy
1213
+ ato_impact = _assess_ato_impact(profile, recommended)
1214
+
1215
+ # Cost and timeline for recommended strategy
1216
+ cost_hours = _estimate_cost(profile, recommended, catalog)
1217
+ timeline_weeks = _estimate_timeline(profile, recommended, catalog)
1218
+
1219
+ # Risk score for recommended strategy
1220
+ risk_score = _compute_risk_score(profile, recommended, catalog)
1221
+
1222
+ # Tech debt reduction for recommended strategy
1223
+ tech_debt_reduction = _estimate_tech_debt_reduction(profile, recommended)
1224
+
1225
+ # Compile the scoring weights used
1226
+ scoring_weights = {}
1227
+ for strat in catalog.get("strategies", []):
1228
+ weights_for_strat = {}
1229
+ for crit_name, crit_info in strat.get("scoring_criteria", {}).items():
1230
+ weights_for_strat[crit_name] = crit_info.get("weight", 0.0)
1231
+ scoring_weights[strat["id"]] = weights_for_strat
1232
+
1233
+ if custom_weights:
1234
+ for strat_id, overrides in custom_weights.items():
1235
+ if strat_id in scoring_weights:
1236
+ scoring_weights[strat_id].update(overrides)
1237
+
1238
+ # Compile evidence
1239
+ evidence = {
1240
+ "fitness_results": {k: {ck: round(cv, 4) for ck, cv in v.items()} for k, v in fitness_results.items()},
1241
+ "strategy_scores": {k: round(v, 4) for k, v in strategy_scores.items()},
1242
+ "ranking": ranking,
1243
+ "profile_summary": {
1244
+ "name": profile.get("name", "unknown"),
1245
+ "primary_language": profile.get("primary_language"),
1246
+ "language_version": profile.get("language_version"),
1247
+ "framework": profile.get("framework"),
1248
+ "framework_version": profile.get("framework_version"),
1249
+ "loc_total": profile.get("loc_total"),
1250
+ "loc_code": profile.get("loc_code"),
1251
+ "file_count": profile.get("file_count"),
1252
+ "component_count": profile.get("component_count"),
1253
+ "dependency_count": profile.get("dependency_count"),
1254
+ "api_count": profile.get("api_count"),
1255
+ "db_schema_count": profile.get("db_schema_count"),
1256
+ "complexity_score": profile.get("complexity_score"),
1257
+ "maintainability_index": profile.get("maintainability_index"),
1258
+ "tech_debt_hours": profile.get("tech_debt_hours"),
1259
+ "avg_complexity": round(profile.get("avg_complexity", 0), 2),
1260
+ "avg_coupling": round(profile.get("avg_coupling", 0), 2),
1261
+ "ui_complexity": round(ui_complexity, 2) if ui_complexity is not None else None,
1262
+ },
1263
+ }
1264
+
1265
+ # Build the assessment record
1266
+ assessment_id = str(uuid.uuid4())
1267
+ now = datetime.now(timezone.utc).isoformat()
1268
+
1269
+ assessment = {
1270
+ "id": assessment_id,
1271
+ "legacy_app_id": app_id,
1272
+ "component_id": None, # app-level assessment
1273
+ "assessment_scope": "application",
1274
+ "rehost_score": round(strategy_scores.get("rehost", 0.0), 4),
1275
+ "replatform_score": round(strategy_scores.get("replatform", 0.0), 4),
1276
+ "refactor_score": round(strategy_scores.get("refactor", 0.0), 4),
1277
+ "rearchitect_score": round(strategy_scores.get("rearchitect", 0.0), 4),
1278
+ "repurchase_score": round(strategy_scores.get("repurchase", 0.0), 4),
1279
+ "retire_score": round(strategy_scores.get("retire", 0.0), 4),
1280
+ "retain_score": round(strategy_scores.get("retain", 0.0), 4),
1281
+ "recommended_strategy": recommended,
1282
+ "cost_estimate_hours": cost_hours,
1283
+ "risk_score": risk_score,
1284
+ "timeline_weeks": timeline_weeks,
1285
+ "ato_impact": ato_impact,
1286
+ "tech_debt_reduction": tech_debt_reduction,
1287
+ "scoring_weights": json.dumps(scoring_weights),
1288
+ "evidence": json.dumps(evidence),
1289
+ "assessed_at": now,
1290
+ "project_id": project_id,
1291
+ "ranking": ranking,
1292
+ }
1293
+
1294
+ # Persist to database
1295
+ _persist_assessment(assessment, db_path=db_path)
1296
+
1297
+ return assessment
1298
+
1299
+
1300
+ def _persist_assessment(assessment, db_path=None):
1301
+ """Write the assessment record to migration_assessments via INSERT OR REPLACE.
1302
+
1303
+ Args:
1304
+ assessment: Dict with all assessment fields.
1305
+ db_path: Optional database path override.
1306
+ """
1307
+ conn = _get_db(db_path)
1308
+ try:
1309
+ conn.execute(
1310
+ """INSERT OR REPLACE INTO migration_assessments
1311
+ (id, legacy_app_id, component_id, assessment_scope,
1312
+ rehost_score, replatform_score, refactor_score,
1313
+ rearchitect_score, repurchase_score, retire_score,
1314
+ retain_score, recommended_strategy, cost_estimate_hours,
1315
+ risk_score, timeline_weeks, ato_impact, tech_debt_reduction,
1316
+ scoring_weights, evidence, assessed_at)
1317
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""",
1318
+ (
1319
+ assessment["id"],
1320
+ assessment["legacy_app_id"],
1321
+ assessment.get("component_id"),
1322
+ assessment["assessment_scope"],
1323
+ assessment["rehost_score"],
1324
+ assessment["replatform_score"],
1325
+ assessment["refactor_score"],
1326
+ assessment["rearchitect_score"],
1327
+ assessment["repurchase_score"],
1328
+ assessment["retire_score"],
1329
+ assessment["retain_score"],
1330
+ assessment["recommended_strategy"],
1331
+ assessment["cost_estimate_hours"],
1332
+ assessment["risk_score"],
1333
+ assessment["timeline_weeks"],
1334
+ assessment["ato_impact"],
1335
+ assessment["tech_debt_reduction"],
1336
+ assessment["scoring_weights"],
1337
+ assessment["evidence"],
1338
+ assessment["assessed_at"],
1339
+ ),
1340
+ )
1341
+ conn.commit()
1342
+ finally:
1343
+ conn.close()
1344
+
1345
+
1346
+ # ============================================================================
1347
+ # Decision matrix display
1348
+ # ============================================================================
1349
+
1350
+ def generate_decision_matrix(app_id, db_path=None):
1351
+ """Pretty-print a decision matrix with all 7 strategies scored.
1352
+
1353
+ Reads the most recent assessment for the given app from the database.
1354
+ If no assessment exists, returns a message indicating so.
1355
+
1356
+ The matrix includes:
1357
+ - Strategy name
1358
+ - Score (0.0-1.0)
1359
+ - Rank
1360
+ - Risk level
1361
+ - Estimated cost (hours)
1362
+ - Timeline (weeks)
1363
+ - ATO impact
1364
+ - Tech debt reduction
1365
+
1366
+ Ends with the recommended strategy and rationale.
1367
+
1368
+ Args:
1369
+ app_id: The legacy application ID.
1370
+ db_path: Optional database path override.
1371
+
1372
+ Returns:
1373
+ String containing the formatted decision matrix.
1374
+ """
1375
+ conn = _get_db(db_path)
1376
+ try:
1377
+ row = conn.execute(
1378
+ """SELECT * FROM migration_assessments
1379
+ WHERE legacy_app_id = ?
1380
+ ORDER BY assessed_at DESC LIMIT 1""",
1381
+ (app_id,),
1382
+ ).fetchone()
1383
+ finally:
1384
+ conn.close()
1385
+
1386
+ if row is None:
1387
+ return (
1388
+ f"No assessment found for application '{app_id}'.\n"
1389
+ "Run an assessment first with: --project-id <PID> --app-id <AID>"
1390
+ )
1391
+
1392
+ row_dict = dict(row)
1393
+ evidence = json.loads(row_dict.get("evidence", "{}"))
1394
+ ranking = evidence.get("ranking", [])
1395
+ profile_summary = evidence.get("profile_summary", {})
1396
+ fitness_results = evidence.get("fitness_results", {})
1397
+ strategy_scores = evidence.get("strategy_scores", {})
1398
+
1399
+ catalog = load_seven_rs_catalog()
1400
+
1401
+ # Build per-strategy detail rows
1402
+ strategy_details = []
1403
+ for entry in ranking:
1404
+ sid = entry["strategy_id"]
1405
+ score = entry["score"]
1406
+ rank = entry["rank"]
1407
+
1408
+ # Look up catalog info
1409
+ cat_info = {}
1410
+ for s in catalog.get("strategies", []):
1411
+ if s["id"] == sid:
1412
+ cat_info = s
1413
+ break
1414
+
1415
+ risk_level = cat_info.get("risk_level", "medium")
1416
+ ato = _assess_ato_impact(profile_summary, sid)
1417
+ cost_h = _estimate_cost(profile_summary if "loc_code" in profile_summary else {"loc_code": profile_summary.get("loc_code", 0), "loc_total": profile_summary.get("loc_total", 0), "maintainability_index": profile_summary.get("maintainability_index", 50), "avg_complexity": profile_summary.get("avg_complexity", 0)}, sid, catalog)
1418
+ timeline_w = _estimate_timeline({"loc_code": profile_summary.get("loc_code", 0), "loc_total": profile_summary.get("loc_total", 0), "maintainability_index": profile_summary.get("maintainability_index", 50), "avg_complexity": profile_summary.get("avg_complexity", 0)}, sid, catalog)
1419
+ tdr = _estimate_tech_debt_reduction(profile_summary, sid)
1420
+ risk_s = _compute_risk_score({"maintainability_index": profile_summary.get("maintainability_index", 50), "external_dep_count": profile_summary.get("dependency_count", 0)}, sid, catalog)
1421
+
1422
+ strategy_details.append({
1423
+ "rank": rank,
1424
+ "name": cat_info.get("name", sid.title()),
1425
+ "id": sid,
1426
+ "score": score,
1427
+ "risk_level": risk_level,
1428
+ "risk_score": risk_s,
1429
+ "cost_hours": cost_h,
1430
+ "timeline_weeks": timeline_w,
1431
+ "ato_impact": ato,
1432
+ "tech_debt_reduction": tdr,
1433
+ })
1434
+
1435
+ # Format the matrix
1436
+ lines = []
1437
+ lines.append("=" * 100)
1438
+ lines.append("CUI // SP-CTI")
1439
+ lines.append("=" * 100)
1440
+ lines.append("")
1441
+ lines.append("7R MIGRATION STRATEGY DECISION MATRIX")
1442
+ lines.append(f"Application: {profile_summary.get('name', app_id)}")
1443
+ lines.append(f"Language: {profile_summary.get('primary_language', 'N/A')} {profile_summary.get('language_version', '')}")
1444
+ lines.append(f"Framework: {profile_summary.get('framework', 'N/A')} {profile_summary.get('framework_version', '')}")
1445
+ lines.append(f"LOC: {profile_summary.get('loc_total', 'N/A'):,}" if isinstance(profile_summary.get('loc_total'), (int, float)) else f"LOC: {profile_summary.get('loc_total', 'N/A')}")
1446
+ lines.append(f"Components: {profile_summary.get('component_count', 'N/A')}")
1447
+ lines.append(f"Assessed: {row_dict.get('assessed_at', 'N/A')}")
1448
+ lines.append("")
1449
+ lines.append("-" * 100)
1450
+
1451
+ # Table header
1452
+ header = f"{'Rank':<6}{'Strategy':<15}{'Score':<9}{'Risk':<10}{'Cost (hrs)':<12}{'Timeline':<12}{'ATO Impact':<14}{'Debt Reduction':<15}"
1453
+ lines.append(header)
1454
+ lines.append("-" * 100)
1455
+
1456
+ # Table rows
1457
+ for sd in strategy_details:
1458
+ marker = " <<" if sd["rank"] == 1 else ""
1459
+ row_str = (
1460
+ f"{sd['rank']:<6}"
1461
+ f"{sd['name']:<15}"
1462
+ f"{sd['score']:<9.4f}"
1463
+ f"{sd['risk_level']:<10}"
1464
+ f"{sd['cost_hours']:<12,}"
1465
+ f"{sd['timeline_weeks']:<10} wk "
1466
+ f"{sd['ato_impact']:<14}"
1467
+ f"{sd['tech_debt_reduction']:<10.0f}%"
1468
+ f"{marker}"
1469
+ )
1470
+ lines.append(row_str)
1471
+
1472
+ lines.append("-" * 100)
1473
+ lines.append("")
1474
+
1475
+ # Recommendation section
1476
+ recommended = row_dict.get("recommended_strategy", "unknown")
1477
+ rec_details = None
1478
+ for sd in strategy_details:
1479
+ if sd["id"] == recommended:
1480
+ rec_details = sd
1481
+ break
1482
+
1483
+ lines.append("RECOMMENDATION")
1484
+ lines.append(f" Strategy: {rec_details['name'] if rec_details else recommended.title()}")
1485
+ lines.append(f" Score: {rec_details['score']:.4f}" if rec_details else " Score: N/A")
1486
+ lines.append(f" Risk: {rec_details['risk_level'] if rec_details else 'N/A'} ({rec_details['risk_score']:.2f})" if rec_details else "")
1487
+ lines.append(f" Estimated Cost: {rec_details['cost_hours']:,} hours" if rec_details else " Estimated Cost: N/A")
1488
+ lines.append(f" Timeline: {rec_details['timeline_weeks']} weeks" if rec_details else " Timeline: N/A")
1489
+ lines.append(f" ATO Impact: {rec_details['ato_impact']}" if rec_details else " ATO Impact: N/A")
1490
+ lines.append(f" Debt Reduction: {rec_details['tech_debt_reduction']:.0f}%" if rec_details else " Debt Reduction: N/A")
1491
+ lines.append("")
1492
+
1493
+ # Rationale
1494
+ lines.append("RATIONALE")
1495
+ if rec_details:
1496
+ # Build a short rationale from the fitness scores
1497
+ fit = fitness_results.get(recommended, {})
1498
+ high_fit = [k for k, v in fit.items() if v >= 0.8]
1499
+ low_fit = [k for k, v in fit.items() if v <= 0.2]
1500
+
1501
+ if high_fit:
1502
+ lines.append(f" Strengths: {', '.join(high_fit)}")
1503
+ if low_fit:
1504
+ lines.append(f" Weaknesses: {', '.join(low_fit)}")
1505
+
1506
+ # Compare top two
1507
+ if len(strategy_details) >= 2:
1508
+ second = strategy_details[1]
1509
+ delta = rec_details["score"] - second["score"]
1510
+ lines.append(
1511
+ f" Margin: {recommended} leads {second['id']} by "
1512
+ f"{delta:.4f} ({delta * 100:.1f}%)"
1513
+ )
1514
+ if delta < 0.05:
1515
+ lines.append(
1516
+ " NOTE: Scores are very close. Manual review of "
1517
+ "business context and team capacity is recommended."
1518
+ )
1519
+ else:
1520
+ lines.append(" No detailed rationale available.")
1521
+
1522
+ lines.append("")
1523
+
1524
+ # Fitness detail section
1525
+ lines.append("FITNESS BREAKDOWN")
1526
+ lines.append("-" * 100)
1527
+ for sid in ["rehost", "replatform", "refactor", "rearchitect", "repurchase", "retire", "retain"]:
1528
+ fit = fitness_results.get(sid, {})
1529
+ if not fit:
1530
+ continue
1531
+ score = strategy_scores.get(sid, 0.0)
1532
+ criteria_strs = [f"{k}={v:.1f}" for k, v in fit.items()]
1533
+ lines.append(f" {sid:<14} (score: {score:.4f}): {', '.join(criteria_strs)}")
1534
+ lines.append("-" * 100)
1535
+
1536
+ lines.append("")
1537
+ lines.append("CUI // SP-CTI")
1538
+ lines.append("=" * 100)
1539
+
1540
+ return "\n".join(lines)
1541
+
1542
+
1543
+ # ============================================================================
1544
+ # CLI entry point
1545
+ # ============================================================================
1546
+
1547
+ def main():
1548
+ """CLI entry point for the 7R assessment engine.
1549
+
1550
+ Arguments:
1551
+ --project-id (required): Project identifier
1552
+ --app-id (required): Legacy application identifier
1553
+ --weights (optional): Path to custom weights JSON file
1554
+ --json (flag): Output raw assessment as JSON
1555
+ --matrix (flag): Print the decision matrix table
1556
+ """
1557
+ parser = argparse.ArgumentParser(
1558
+ description=(
1559
+ "7R Migration Strategy Recommendation Engine — "
1560
+ "Evaluates legacy applications against 7 cloud migration strategies "
1561
+ "and recommends the optimal path for DoD/GovCloud environments."
1562
+ ),
1563
+ epilog="CUI // SP-CTI",
1564
+ )
1565
+ parser.add_argument(
1566
+ "--project-id",
1567
+ required=True,
1568
+ help="Project identifier (e.g., P-001)",
1569
+ )
1570
+ parser.add_argument(
1571
+ "--app-id",
1572
+ required=True,
1573
+ help="Legacy application identifier (e.g., A-001)",
1574
+ )
1575
+ parser.add_argument(
1576
+ "--weights",
1577
+ default=None,
1578
+ help="Path to custom weights JSON file (overrides catalog defaults)",
1579
+ )
1580
+ parser.add_argument(
1581
+ "--json",
1582
+ action="store_true",
1583
+ dest="output_json",
1584
+ help="Output the assessment as JSON",
1585
+ )
1586
+ parser.add_argument(
1587
+ "--matrix",
1588
+ action="store_true",
1589
+ help="Print the decision matrix table",
1590
+ )
1591
+
1592
+ args = parser.parse_args()
1593
+
1594
+ # Load custom weights if provided
1595
+ custom_weights = None
1596
+ if args.weights:
1597
+ weights_path = Path(args.weights)
1598
+ if not weights_path.exists():
1599
+ print(f"ERROR: Weights file not found: {weights_path}", file=sys.stderr)
1600
+ sys.exit(1)
1601
+ with open(weights_path, "r", encoding="utf-8") as fh:
1602
+ custom_weights = json.load(fh)
1603
+
1604
+ # Run the assessment
1605
+ try:
1606
+ assessment = run_seven_r_assessment(
1607
+ project_id=args.project_id,
1608
+ app_id=args.app_id,
1609
+ custom_weights=custom_weights,
1610
+ )
1611
+ except FileNotFoundError as exc:
1612
+ print(f"ERROR: {exc}", file=sys.stderr)
1613
+ sys.exit(1)
1614
+ except ValueError as exc:
1615
+ print(f"ERROR: {exc}", file=sys.stderr)
1616
+ sys.exit(1)
1617
+
1618
+ # Output
1619
+ if args.output_json:
1620
+ # Serialise — strip non-serializable fields
1621
+ output = dict(assessment)
1622
+ # ranking is already a list of dicts, safe to serialize
1623
+ output["scoring_weights"] = json.loads(output["scoring_weights"]) if isinstance(output["scoring_weights"], str) else output["scoring_weights"]
1624
+ output["evidence"] = json.loads(output["evidence"]) if isinstance(output["evidence"], str) else output["evidence"]
1625
+ print(json.dumps(output, indent=2, default=str))
1626
+ elif args.matrix:
1627
+ matrix_output = generate_decision_matrix(args.app_id)
1628
+ print(matrix_output)
1629
+ else:
1630
+ # Default: summary output
1631
+ print("=" * 60)
1632
+ print("CUI // SP-CTI")
1633
+ print("=" * 60)
1634
+ print(f"7R Assessment Complete — {assessment['legacy_app_id']}")
1635
+ print(f" Assessment ID: {assessment['id']}")
1636
+ print(f" Recommended Strategy: {assessment['recommended_strategy'].upper()}")
1637
+ print(f" Score: {assessment.get(assessment['recommended_strategy'] + '_score', 'N/A')}")
1638
+ print(f" Risk Score: {assessment['risk_score']}")
1639
+ print(f" Cost Estimate: {assessment['cost_estimate_hours']:,} hours")
1640
+ print(f" Timeline: {assessment['timeline_weeks']} weeks")
1641
+ print(f" ATO Impact: {assessment['ato_impact']}")
1642
+ print(f" Tech Debt Reduction: {assessment['tech_debt_reduction']:.0f}%")
1643
+ print()
1644
+ print("Strategy Rankings:")
1645
+ for entry in assessment["ranking"]:
1646
+ marker = " << RECOMMENDED" if entry["rank"] == 1 else ""
1647
+ print(f" #{entry['rank']} {entry['strategy_id']:<14} {entry['score']:.4f}{marker}")
1648
+ print()
1649
+ print("Run with --matrix for full decision matrix.")
1650
+ print("Run with --json for machine-readable output.")
1651
+ print("=" * 60)
1652
+ print("CUI // SP-CTI")
1653
+ print("=" * 60)
1654
+
1655
+
1656
+ if __name__ == "__main__":
1657
+ main()
1658
+ # [TEMPLATE: CUI // SP-CTI]