Technology Stack Evaluator Evaluate and compare technologies, frameworks, and cloud providers with data-driven analysis and actionable recommendations. Table of Contents - Capabilities - Quick Start - Input Formats - Analysis Types - Scripts - References --- Capabilities | Capability | Description | |------------|-------------| | Technology Comparison | Compare frameworks and libraries with weighted scoring | | TCO Analysis | Calculate 5-year total cost including hidden costs | | Ecosystem Health | Assess GitHub metrics, npm adoption, community strength | | Security Assessment | Evaluate vuln…

, # Trailing colons\n ]\n\n # Must not be JSON\n if self._is_json():\n return False\n\n # Check for YAML patterns\n lines = self.raw_input.split('\\n')\n yaml_line_count = 0\n\n for line in lines:\n for pattern in yaml_patterns:\n if re.match(pattern, line):\n yaml_line_count += 1\n break\n\n # If >50% of lines match YAML patterns, consider it YAML\n if len(lines) > 0 and yaml_line_count / len(lines) > 0.5:\n return True\n\n return False\n\n def _contains_urls(self) -> bool:\n \"\"\"Check if input contains URLs.\"\"\"\n url_pattern = r'https?://[^\\s]+'\n return bool(re.search(url_pattern, self.raw_input))\n\n def parse(self) -> Dict[str, Any]:\n \"\"\"\n Parse input based on detected format.\n\n Returns:\n Parsed data dictionary\n \"\"\"\n if self.detected_format is None:\n self.detect_format()\n\n if self.detected_format == 'json':\n self.parsed_data = self._parse_json()\n elif self.detected_format == 'yaml':\n self.parsed_data = self._parse_yaml()\n elif self.detected_format == 'url':\n self.parsed_data = self._parse_urls()\n else: # text\n self.parsed_data = self._parse_text()\n\n return self.parsed_data\n\n def _parse_json(self) -> Dict[str, Any]:\n \"\"\"Parse JSON input.\"\"\"\n try:\n data = json.loads(self.raw_input)\n return self._normalize_structure(data)\n except json.JSONDecodeError:\n return {'error': 'Invalid JSON', 'raw': self.raw_input}\n\n def _parse_yaml(self) -> Dict[str, Any]:\n \"\"\"\n Parse YAML-like input (simplified, no external dependencies).\n\n Returns:\n Parsed dictionary\n \"\"\"\n result = {}\n current_section = None\n current_list = None\n\n lines = self.raw_input.split('\\n')\n\n for line in lines:\n stripped = line.strip()\n if not stripped or stripped.startswith('#'):\n continue\n\n # Key-value pair\n if ':' in stripped:\n key, value = stripped.split(':', 1)\n key = key.strip()\n value = value.strip()\n\n # Empty value might indicate nested structure\n if not value:\n current_section = key\n result[current_section] = {}\n current_list = None\n else:\n if current_section:\n result[current_section][key] = self._parse_value(value)\n else:\n result[key] = self._parse_value(value)\n\n # List item\n elif stripped.startswith('-'):\n item = stripped[1:].strip()\n if current_section:\n if current_list is None:\n current_list = []\n result[current_section] = current_list\n current_list.append(self._parse_value(item))\n\n return self._normalize_structure(result)\n\n def _parse_value(self, value: str) -> Any:\n \"\"\"\n Parse a value string to appropriate type.\n\n Args:\n value: Value string\n\n Returns:\n Parsed value (str, int, float, bool)\n \"\"\"\n value = value.strip()\n\n # Boolean\n if value.lower() in ['true', 'yes']:\n return True\n if value.lower() in ['false', 'no']:\n return False\n\n # Number\n try:\n if '.' in value:\n return float(value)\n else:\n return int(value)\n except ValueError:\n pass\n\n # String (remove quotes if present)\n if value.startswith('\"') and value.endswith('\"'):\n return value[1:-1]\n if value.startswith(\"'\") and value.endswith(\"'\"):\n return value[1:-1]\n\n return value\n\n def _parse_urls(self) -> Dict[str, Any]:\n \"\"\"Parse URLs from input.\"\"\"\n url_pattern = r'https?://[^\\s]+'\n urls = re.findall(url_pattern, self.raw_input)\n\n # Categorize URLs\n github_urls = [u for u in urls if 'github.com' in u]\n npm_urls = [u for u in urls if 'npmjs.com' in u or 'npm.io' in u]\n other_urls = [u for u in urls if u not in github_urls and u not in npm_urls]\n\n # Also extract any text context\n text_without_urls = re.sub(url_pattern, '', self.raw_input).strip()\n\n result = {\n 'format': 'url',\n 'urls': {\n 'github': github_urls,\n 'npm': npm_urls,\n 'other': other_urls\n },\n 'context': text_without_urls\n }\n\n return self._normalize_structure(result)\n\n def _parse_text(self) -> Dict[str, Any]:\n \"\"\"Parse conversational text input.\"\"\"\n text = self.raw_input.lower()\n\n # Extract technologies being compared\n technologies = self._extract_technologies(text)\n\n # Extract use case\n use_case = self._extract_use_case(text)\n\n # Extract priorities\n priorities = self._extract_priorities(text)\n\n # Detect analysis type\n analysis_type = self._detect_analysis_type(text)\n\n result = {\n 'format': 'text',\n 'technologies': technologies,\n 'use_case': use_case,\n 'priorities': priorities,\n 'analysis_type': analysis_type,\n 'raw_text': self.raw_input\n }\n\n return self._normalize_structure(result)\n\n def _extract_technologies(self, text: str) -> list:\n \"\"\"\n Extract technology names from text.\n\n Args:\n text: Lowercase text\n\n Returns:\n List of identified technologies\n \"\"\"\n # Common technologies pattern\n tech_keywords = [\n 'react', 'vue', 'angular', 'svelte', 'next.js', 'nuxt.js',\n 'node.js', 'python', 'java', 'go', 'rust', 'ruby',\n 'postgresql', 'postgres', 'mysql', 'mongodb', 'redis',\n 'aws', 'azure', 'gcp', 'google cloud',\n 'docker', 'kubernetes', 'k8s',\n 'express', 'fastapi', 'django', 'flask', 'spring boot'\n ]\n\n found = []\n for tech in tech_keywords:\n if tech in text:\n # Normalize names\n normalized = {\n 'postgres': 'PostgreSQL',\n 'next.js': 'Next.js',\n 'nuxt.js': 'Nuxt.js',\n 'node.js': 'Node.js',\n 'k8s': 'Kubernetes',\n 'gcp': 'Google Cloud Platform'\n }.get(tech, tech.title())\n\n if normalized not in found:\n found.append(normalized)\n\n return found if found else ['Unknown']\n\n def _extract_use_case(self, text: str) -> str:\n \"\"\"\n Extract use case description from text.\n\n Args:\n text: Lowercase text\n\n Returns:\n Use case description\n \"\"\"\n use_case_keywords = {\n 'real-time': 'Real-time application',\n 'collaboration': 'Collaboration platform',\n 'saas': 'SaaS application',\n 'dashboard': 'Dashboard application',\n 'api': 'API-heavy application',\n 'data-intensive': 'Data-intensive application',\n 'e-commerce': 'E-commerce platform',\n 'enterprise': 'Enterprise application'\n }\n\n for keyword, description in use_case_keywords.items():\n if keyword in text:\n return description\n\n return 'General purpose application'\n\n def _extract_priorities(self, text: str) -> list:\n \"\"\"\n Extract priority criteria from text.\n\n Args:\n text: Lowercase text\n\n Returns:\n List of priorities\n \"\"\"\n priority_keywords = {\n 'performance': 'Performance',\n 'scalability': 'Scalability',\n 'developer experience': 'Developer experience',\n 'ecosystem': 'Ecosystem',\n 'learning curve': 'Learning curve',\n 'cost': 'Cost',\n 'security': 'Security',\n 'compliance': 'Compliance'\n }\n\n priorities = []\n for keyword, priority in priority_keywords.items():\n if keyword in text:\n priorities.append(priority)\n\n return priorities if priorities else ['Developer experience', 'Performance']\n\n def _detect_analysis_type(self, text: str) -> str:\n \"\"\"\n Detect type of analysis requested.\n\n Args:\n text: Lowercase text\n\n Returns:\n Analysis type\n \"\"\"\n type_keywords = {\n 'migration': 'migration_analysis',\n 'migrate': 'migration_analysis',\n 'tco': 'tco_analysis',\n 'total cost': 'tco_analysis',\n 'security': 'security_analysis',\n 'compliance': 'security_analysis',\n 'compare': 'comparison',\n 'vs': 'comparison',\n 'evaluate': 'evaluation'\n }\n\n for keyword, analysis_type in type_keywords.items():\n if keyword in text:\n return analysis_type\n\n return 'comparison' # Default\n\n def _normalize_structure(self, data: Dict[str, Any]) -> Dict[str, Any]:\n \"\"\"\n Normalize parsed data to standard structure.\n\n Args:\n data: Parsed data dictionary\n\n Returns:\n Normalized data structure\n \"\"\"\n # Ensure standard keys exist\n standard_keys = [\n 'technologies',\n 'use_case',\n 'priorities',\n 'analysis_type',\n 'format'\n ]\n\n normalized = data.copy()\n\n for key in standard_keys:\n if key not in normalized:\n # Set defaults\n defaults = {\n 'technologies': [],\n 'use_case': 'general',\n 'priorities': [],\n 'analysis_type': 'comparison',\n 'format': self.detected_format or 'unknown'\n }\n normalized[key] = defaults.get(key)\n\n return normalized\n\n def get_format_info(self) -> Dict[str, Any]:\n \"\"\"\n Get information about detected format.\n\n Returns:\n Format detection metadata\n \"\"\"\n return {\n 'detected_format': self.detected_format,\n 'input_length': len(self.raw_input),\n 'line_count': len(self.raw_input.split('\\n')),\n 'parsing_successful': self.parsed_data is not None\n }\n","content_type":"text/x-python; charset=utf-8","language":"python","size":12611,"content_sha256":"0df7dc8fd5dfe4ce8c4eb964d0c63f00590c20ebb1296419e9bc9997e149bced"},{"filename":"scripts/migration_analyzer.py","content":"\"\"\"\nMigration Path Analyzer.\n\nAnalyzes migration complexity, risks, timelines, and strategies for moving\nfrom legacy technology stacks to modern alternatives.\n\"\"\"\n\nfrom typing import Dict, List, Any, Optional, Tuple\n\n\nclass MigrationAnalyzer:\n \"\"\"Analyze migration paths and complexity for technology stack changes.\"\"\"\n\n # Migration complexity factors\n COMPLEXITY_FACTORS = [\n 'code_volume',\n 'architecture_changes',\n 'data_migration',\n 'api_compatibility',\n 'dependency_changes',\n 'testing_requirements'\n ]\n\n def __init__(self, migration_data: Dict[str, Any]):\n \"\"\"\n Initialize migration analyzer with migration parameters.\n\n Args:\n migration_data: Dictionary containing source/target technologies and constraints\n \"\"\"\n self.source_tech = migration_data.get('source_technology', 'Unknown')\n self.target_tech = migration_data.get('target_technology', 'Unknown')\n self.codebase_stats = migration_data.get('codebase_stats', {})\n self.constraints = migration_data.get('constraints', {})\n self.team_info = migration_data.get('team', {})\n\n def calculate_complexity_score(self) -> Dict[str, Any]:\n \"\"\"\n Calculate overall migration complexity (1-10 scale).\n\n Returns:\n Dictionary with complexity scores by factor\n \"\"\"\n scores = {\n 'code_volume': self._score_code_volume(),\n 'architecture_changes': self._score_architecture_changes(),\n 'data_migration': self._score_data_migration(),\n 'api_compatibility': self._score_api_compatibility(),\n 'dependency_changes': self._score_dependency_changes(),\n 'testing_requirements': self._score_testing_requirements()\n }\n\n # Calculate weighted average\n weights = {\n 'code_volume': 0.20,\n 'architecture_changes': 0.25,\n 'data_migration': 0.20,\n 'api_compatibility': 0.15,\n 'dependency_changes': 0.10,\n 'testing_requirements': 0.10\n }\n\n overall = sum(scores[k] * weights[k] for k in scores.keys())\n scores['overall_complexity'] = overall\n\n return scores\n\n def _score_code_volume(self) -> float:\n \"\"\"\n Score complexity based on codebase size.\n\n Returns:\n Code volume complexity score (1-10)\n \"\"\"\n lines_of_code = self.codebase_stats.get('lines_of_code', 10000)\n num_files = self.codebase_stats.get('num_files', 100)\n num_components = self.codebase_stats.get('num_components', 50)\n\n # Score based on lines of code (primary factor)\n if lines_of_code \u003c 5000:\n base_score = 2\n elif lines_of_code \u003c 20000:\n base_score = 4\n elif lines_of_code \u003c 50000:\n base_score = 6\n elif lines_of_code \u003c 100000:\n base_score = 8\n else:\n base_score = 10\n\n # Adjust for component count\n if num_components > 200:\n base_score = min(10, base_score + 1)\n elif num_components > 500:\n base_score = min(10, base_score + 2)\n\n return float(base_score)\n\n def _score_architecture_changes(self) -> float:\n \"\"\"\n Score complexity based on architectural changes.\n\n Returns:\n Architecture complexity score (1-10)\n \"\"\"\n arch_change_level = self.codebase_stats.get('architecture_change_level', 'moderate')\n\n scores = {\n 'minimal': 2, # Same patterns, just different framework\n 'moderate': 5, # Some pattern changes, similar concepts\n 'significant': 7, # Different patterns, major refactoring\n 'complete': 10 # Complete rewrite, different paradigm\n }\n\n return float(scores.get(arch_change_level, 5))\n\n def _score_data_migration(self) -> float:\n \"\"\"\n Score complexity based on data migration requirements.\n\n Returns:\n Data migration complexity score (1-10)\n \"\"\"\n has_database = self.codebase_stats.get('has_database', True)\n if not has_database:\n return 1.0\n\n database_size_gb = self.codebase_stats.get('database_size_gb', 10)\n schema_changes = self.codebase_stats.get('schema_changes_required', 'minimal')\n data_transformation = self.codebase_stats.get('data_transformation_required', False)\n\n # Base score from database size\n if database_size_gb \u003c 1:\n score = 2\n elif database_size_gb \u003c 10:\n score = 3\n elif database_size_gb \u003c 100:\n score = 5\n elif database_size_gb \u003c 1000:\n score = 7\n else:\n score = 9\n\n # Adjust for schema changes\n schema_adjustments = {\n 'none': 0,\n 'minimal': 1,\n 'moderate': 2,\n 'significant': 3\n }\n score += schema_adjustments.get(schema_changes, 1)\n\n # Adjust for data transformation\n if data_transformation:\n score += 2\n\n return min(10.0, float(score))\n\n def _score_api_compatibility(self) -> float:\n \"\"\"\n Score complexity based on API compatibility.\n\n Returns:\n API compatibility complexity score (1-10)\n \"\"\"\n breaking_api_changes = self.codebase_stats.get('breaking_api_changes', 'some')\n\n scores = {\n 'none': 1, # Fully compatible\n 'minimal': 3, # Few breaking changes\n 'some': 5, # Moderate breaking changes\n 'many': 7, # Significant breaking changes\n 'complete': 10 # Complete API rewrite\n }\n\n return float(scores.get(breaking_api_changes, 5))\n\n def _score_dependency_changes(self) -> float:\n \"\"\"\n Score complexity based on dependency changes.\n\n Returns:\n Dependency complexity score (1-10)\n \"\"\"\n num_dependencies = self.codebase_stats.get('num_dependencies', 20)\n dependencies_to_replace = self.codebase_stats.get('dependencies_to_replace', 5)\n\n # Score based on replacement percentage\n if num_dependencies == 0:\n return 1.0\n\n replacement_pct = (dependencies_to_replace / num_dependencies) * 100\n\n if replacement_pct \u003c 10:\n return 2.0\n elif replacement_pct \u003c 25:\n return 4.0\n elif replacement_pct \u003c 50:\n return 6.0\n elif replacement_pct \u003c 75:\n return 8.0\n else:\n return 10.0\n\n def _score_testing_requirements(self) -> float:\n \"\"\"\n Score complexity based on testing requirements.\n\n Returns:\n Testing complexity score (1-10)\n \"\"\"\n test_coverage = self.codebase_stats.get('current_test_coverage', 0.5) # 0-1 scale\n num_tests = self.codebase_stats.get('num_tests', 100)\n\n # If good test coverage, easier migration (can verify)\n if test_coverage >= 0.8:\n base_score = 3\n elif test_coverage >= 0.6:\n base_score = 5\n elif test_coverage >= 0.4:\n base_score = 7\n else:\n base_score = 9 # Poor coverage = hard to verify migration\n\n # Large test suites need updates\n if num_tests > 500:\n base_score = min(10, base_score + 1)\n\n return float(base_score)\n\n def estimate_effort(self) -> Dict[str, Any]:\n \"\"\"\n Estimate migration effort in person-hours and timeline.\n\n Returns:\n Dictionary with effort estimates\n \"\"\"\n complexity = self.calculate_complexity_score()\n overall_complexity = complexity['overall_complexity']\n\n # Base hours estimation\n lines_of_code = self.codebase_stats.get('lines_of_code', 10000)\n base_hours = lines_of_code / 50 # 50 lines per hour baseline\n\n # Complexity multiplier\n complexity_multiplier = 1 + (overall_complexity / 10)\n estimated_hours = base_hours * complexity_multiplier\n\n # Break down by phase\n phases = self._calculate_phase_breakdown(estimated_hours)\n\n # Calculate timeline\n team_size = self.team_info.get('team_size', 3)\n hours_per_week_per_dev = self.team_info.get('hours_per_week', 30) # Account for other work\n\n total_dev_weeks = estimated_hours / (team_size * hours_per_week_per_dev)\n total_calendar_weeks = total_dev_weeks * 1.2 # Buffer for blockers\n\n return {\n 'total_hours': estimated_hours,\n 'total_person_months': estimated_hours / 160, # 160 hours per person-month\n 'phases': phases,\n 'estimated_timeline': {\n 'dev_weeks': total_dev_weeks,\n 'calendar_weeks': total_calendar_weeks,\n 'calendar_months': total_calendar_weeks / 4.33\n },\n 'team_assumptions': {\n 'team_size': team_size,\n 'hours_per_week_per_dev': hours_per_week_per_dev\n }\n }\n\n def _calculate_phase_breakdown(self, total_hours: float) -> Dict[str, Dict[str, float]]:\n \"\"\"\n Calculate effort breakdown by migration phase.\n\n Args:\n total_hours: Total estimated hours\n\n Returns:\n Hours breakdown by phase\n \"\"\"\n # Standard phase percentages\n phase_percentages = {\n 'planning_and_prototyping': 0.15,\n 'core_migration': 0.45,\n 'testing_and_validation': 0.25,\n 'deployment_and_monitoring': 0.10,\n 'buffer_and_contingency': 0.05\n }\n\n phases = {}\n for phase, percentage in phase_percentages.items():\n hours = total_hours * percentage\n phases[phase] = {\n 'hours': hours,\n 'person_weeks': hours / 40,\n 'percentage': f\"{percentage * 100:.0f}%\"\n }\n\n return phases\n\n def assess_risks(self) -> Dict[str, List[Dict[str, str]]]:\n \"\"\"\n Identify and assess migration risks.\n\n Returns:\n Categorized risks with mitigation strategies\n \"\"\"\n complexity = self.calculate_complexity_score()\n\n risks = {\n 'technical_risks': self._identify_technical_risks(complexity),\n 'business_risks': self._identify_business_risks(),\n 'team_risks': self._identify_team_risks()\n }\n\n return risks\n\n def _identify_technical_risks(self, complexity: Dict[str, float]) -> List[Dict[str, str]]:\n \"\"\"\n Identify technical risks.\n\n Args:\n complexity: Complexity scores\n\n Returns:\n List of technical risks with mitigations\n \"\"\"\n risks = []\n\n # API compatibility risks\n if complexity['api_compatibility'] >= 7:\n risks.append({\n 'risk': 'Breaking API changes may cause integration failures',\n 'severity': 'High',\n 'mitigation': 'Create compatibility layer; implement feature flags for gradual rollout'\n })\n\n # Data migration risks\n if complexity['data_migration'] >= 7:\n risks.append({\n 'risk': 'Data migration could cause data loss or corruption',\n 'severity': 'Critical',\n 'mitigation': 'Implement robust backup strategy; run parallel systems during migration; extensive validation'\n })\n\n # Architecture risks\n if complexity['architecture_changes'] >= 8:\n risks.append({\n 'risk': 'Major architectural changes increase risk of performance regression',\n 'severity': 'High',\n 'mitigation': 'Extensive performance testing; staged rollout; monitoring and alerting'\n })\n\n # Testing risks\n if complexity['testing_requirements'] >= 7:\n risks.append({\n 'risk': 'Inadequate test coverage may miss critical bugs',\n 'severity': 'Medium',\n 'mitigation': 'Improve test coverage before migration; automated regression testing; user acceptance testing'\n })\n\n if not risks:\n risks.append({\n 'risk': 'Standard technical risks (bugs, edge cases)',\n 'severity': 'Low',\n 'mitigation': 'Standard QA processes and staged rollout'\n })\n\n return risks\n\n def _identify_business_risks(self) -> List[Dict[str, str]]:\n \"\"\"\n Identify business risks.\n\n Returns:\n List of business risks with mitigations\n \"\"\"\n risks = []\n\n # Downtime risk\n downtime_tolerance = self.constraints.get('downtime_tolerance', 'low')\n if downtime_tolerance == 'none':\n risks.append({\n 'risk': 'Zero-downtime migration increases complexity and risk',\n 'severity': 'High',\n 'mitigation': 'Blue-green deployment; feature flags; gradual traffic migration'\n })\n\n # Feature parity risk\n risks.append({\n 'risk': 'New implementation may lack feature parity',\n 'severity': 'Medium',\n 'mitigation': 'Comprehensive feature audit; prioritized feature list; clear communication'\n })\n\n # Timeline risk\n risks.append({\n 'risk': 'Migration may take longer than estimated',\n 'severity': 'Medium',\n 'mitigation': 'Build in 20% buffer; regular progress reviews; scope management'\n })\n\n return risks\n\n def _identify_team_risks(self) -> List[Dict[str, str]]:\n \"\"\"\n Identify team-related risks.\n\n Returns:\n List of team risks with mitigations\n \"\"\"\n risks = []\n\n # Learning curve\n team_experience = self.team_info.get('target_tech_experience', 'low')\n if team_experience in ['low', 'none']:\n risks.append({\n 'risk': 'Team lacks experience with target technology',\n 'severity': 'High',\n 'mitigation': 'Training program; hire experienced developers; external consulting'\n })\n\n # Team size\n team_size = self.team_info.get('team_size', 3)\n if team_size \u003c 3:\n risks.append({\n 'risk': 'Small team size may extend timeline',\n 'severity': 'Medium',\n 'mitigation': 'Consider augmenting team; reduce scope; extend timeline'\n })\n\n # Knowledge retention\n risks.append({\n 'risk': 'Loss of institutional knowledge during migration',\n 'severity': 'Medium',\n 'mitigation': 'Comprehensive documentation; knowledge sharing sessions; pair programming'\n })\n\n return risks\n\n def generate_migration_plan(self) -> Dict[str, Any]:\n \"\"\"\n Generate comprehensive migration plan.\n\n Returns:\n Complete migration plan with timeline and recommendations\n \"\"\"\n complexity = self.calculate_complexity_score()\n effort = self.estimate_effort()\n risks = self.assess_risks()\n\n # Generate phased approach\n approach = self._recommend_migration_approach(complexity['overall_complexity'])\n\n # Generate recommendation\n recommendation = self._generate_migration_recommendation(complexity, effort, risks)\n\n return {\n 'source_technology': self.source_tech,\n 'target_technology': self.target_tech,\n 'complexity_analysis': complexity,\n 'effort_estimation': effort,\n 'risk_assessment': risks,\n 'recommended_approach': approach,\n 'overall_recommendation': recommendation,\n 'success_criteria': self._define_success_criteria()\n }\n\n def _recommend_migration_approach(self, complexity_score: float) -> Dict[str, Any]:\n \"\"\"\n Recommend migration approach based on complexity.\n\n Args:\n complexity_score: Overall complexity score\n\n Returns:\n Recommended approach details\n \"\"\"\n if complexity_score \u003c= 3:\n approach = 'direct_migration'\n description = 'Direct migration - low complexity allows straightforward migration'\n timeline_multiplier = 1.0\n elif complexity_score \u003c= 6:\n approach = 'phased_migration'\n description = 'Phased migration - migrate components incrementally to manage risk'\n timeline_multiplier = 1.3\n else:\n approach = 'strangler_pattern'\n description = 'Strangler pattern - gradually replace old system while running in parallel'\n timeline_multiplier = 1.5\n\n return {\n 'approach': approach,\n 'description': description,\n 'timeline_multiplier': timeline_multiplier,\n 'phases': self._generate_approach_phases(approach)\n }\n\n def _generate_approach_phases(self, approach: str) -> List[str]:\n \"\"\"\n Generate phase descriptions for migration approach.\n\n Args:\n approach: Migration approach type\n\n Returns:\n List of phase descriptions\n \"\"\"\n phases = {\n 'direct_migration': [\n 'Phase 1: Set up target environment and migrate configuration',\n 'Phase 2: Migrate codebase and dependencies',\n 'Phase 3: Migrate data with validation',\n 'Phase 4: Comprehensive testing',\n 'Phase 5: Cutover and monitoring'\n ],\n 'phased_migration': [\n 'Phase 1: Identify and prioritize components for migration',\n 'Phase 2: Migrate non-critical components first',\n 'Phase 3: Migrate core components with parallel running',\n 'Phase 4: Migrate critical components with rollback plan',\n 'Phase 5: Decommission old system'\n ],\n 'strangler_pattern': [\n 'Phase 1: Set up routing layer between old and new systems',\n 'Phase 2: Implement new features in target technology only',\n 'Phase 3: Gradually migrate existing features (lowest risk first)',\n 'Phase 4: Migrate high-risk components last with extensive testing',\n 'Phase 5: Complete migration and remove routing layer'\n ]\n }\n\n return phases.get(approach, phases['phased_migration'])\n\n def _generate_migration_recommendation(\n self,\n complexity: Dict[str, float],\n effort: Dict[str, Any],\n risks: Dict[str, List[Dict[str, str]]]\n ) -> str:\n \"\"\"\n Generate overall migration recommendation.\n\n Args:\n complexity: Complexity analysis\n effort: Effort estimation\n risks: Risk assessment\n\n Returns:\n Recommendation string\n \"\"\"\n overall_complexity = complexity['overall_complexity']\n timeline_months = effort['estimated_timeline']['calendar_months']\n\n # Count high/critical severity risks\n high_risk_count = sum(\n 1 for risk_list in risks.values()\n for risk in risk_list\n if risk['severity'] in ['High', 'Critical']\n )\n\n if overall_complexity \u003c= 4 and high_risk_count \u003c= 2:\n return f\"Recommended - Low complexity migration achievable in {timeline_months:.1f} months with manageable risks\"\n elif overall_complexity \u003c= 7 and high_risk_count \u003c= 4:\n return f\"Proceed with caution - Moderate complexity migration requiring {timeline_months:.1f} months and careful risk management\"\n else:\n return f\"High risk - Complex migration requiring {timeline_months:.1f} months. Consider: incremental approach, additional resources, or alternative solutions\"\n\n def _define_success_criteria(self) -> List[str]:\n \"\"\"\n Define success criteria for migration.\n\n Returns:\n List of success criteria\n \"\"\"\n return [\n 'Feature parity with current system',\n 'Performance equal or better than current system',\n 'Zero data loss or corruption',\n 'All tests passing (unit, integration, E2E)',\n 'Successful production deployment with \u003c1% error rate',\n 'Team trained and comfortable with new technology',\n 'Documentation complete and up-to-date'\n ]\n","content_type":"text/x-python; charset=utf-8","language":"python","size":20589,"content_sha256":"acdacce2d54ade06ae6230e19638d74c706d9c5e8620bbd42dce7c76dbbe7790"},{"filename":"scripts/report_generator.py","content":"\"\"\"\nReport Generator - Context-aware report generation with progressive disclosure.\n\nGenerates reports adapted for Claude Desktop (rich markdown) or CLI (terminal-friendly),\nwith executive summaries and detailed breakdowns on demand.\n\"\"\"\n\nfrom typing import Dict, List, Any, Optional\nimport os\nimport platform\n\n\nclass ReportGenerator:\n \"\"\"Generate context-aware technology evaluation reports.\"\"\"\n\n def __init__(self, report_data: Dict[str, Any], output_context: Optional[str] = None):\n \"\"\"\n Initialize report generator.\n\n Args:\n report_data: Complete evaluation data\n output_context: 'desktop', 'cli', or None for auto-detect\n \"\"\"\n self.report_data = report_data\n self.output_context = output_context or self._detect_context()\n\n def _detect_context(self) -> str:\n \"\"\"\n Detect output context (Desktop vs CLI).\n\n Returns:\n Context type: 'desktop' or 'cli'\n \"\"\"\n # Check for Claude Desktop environment variables or indicators\n # This is a simplified detection - actual implementation would check for\n # Claude Desktop-specific environment variables\n\n if os.getenv('CLAUDE_DESKTOP'):\n return 'desktop'\n\n # Check if running in terminal\n if os.isatty(1): # stdout is a terminal\n return 'cli'\n\n # Default to desktop for rich formatting\n return 'desktop'\n\n def generate_executive_summary(self, max_tokens: int = 300) -> str:\n \"\"\"\n Generate executive summary (200-300 tokens).\n\n Args:\n max_tokens: Maximum tokens for summary\n\n Returns:\n Executive summary markdown\n \"\"\"\n summary_parts = []\n\n # Title\n technologies = self.report_data.get('technologies', [])\n tech_names = ', '.join(technologies[:3]) # First 3\n summary_parts.append(f\"# Technology Evaluation: {tech_names}\\n\")\n\n # Recommendation\n recommendation = self.report_data.get('recommendation', {})\n rec_text = recommendation.get('text', 'No recommendation available')\n confidence = recommendation.get('confidence', 0)\n\n summary_parts.append(f\"## Recommendation\\n\")\n summary_parts.append(f\"**{rec_text}**\\n\")\n summary_parts.append(f\"*Confidence: {confidence:.0f}%*\\n\")\n\n # Top 3 Pros\n pros = recommendation.get('pros', [])[:3]\n if pros:\n summary_parts.append(f\"\\n### Top Strengths\\n\")\n for pro in pros:\n summary_parts.append(f\"- {pro}\\n\")\n\n # Top 3 Cons\n cons = recommendation.get('cons', [])[:3]\n if cons:\n summary_parts.append(f\"\\n### Key Concerns\\n\")\n for con in cons:\n summary_parts.append(f\"- {con}\\n\")\n\n # Key Decision Factors\n decision_factors = self.report_data.get('decision_factors', [])[:3]\n if decision_factors:\n summary_parts.append(f\"\\n### Decision Factors\\n\")\n for factor in decision_factors:\n category = factor.get('category', 'Unknown')\n best = factor.get('best_performer', 'Unknown')\n summary_parts.append(f\"- **{category.replace('_', ' ').title()}**: {best}\\n\")\n\n summary_parts.append(f\"\\n---\\n\")\n summary_parts.append(f\"*For detailed analysis, request full report sections*\\n\")\n\n return ''.join(summary_parts)\n\n def generate_full_report(self, sections: Optional[List[str]] = None) -> str:\n \"\"\"\n Generate complete report with selected sections.\n\n Args:\n sections: List of sections to include, or None for all\n\n Returns:\n Complete report markdown\n \"\"\"\n if sections is None:\n sections = self._get_available_sections()\n\n report_parts = []\n\n # Title and metadata\n report_parts.append(self._generate_title())\n\n # Generate each requested section\n for section in sections:\n section_content = self._generate_section(section)\n if section_content:\n report_parts.append(section_content)\n\n return '\\n\\n'.join(report_parts)\n\n def _get_available_sections(self) -> List[str]:\n \"\"\"\n Get list of available report sections.\n\n Returns:\n List of section names\n \"\"\"\n sections = ['executive_summary']\n\n if 'comparison_matrix' in self.report_data:\n sections.append('comparison_matrix')\n\n if 'tco_analysis' in self.report_data:\n sections.append('tco_analysis')\n\n if 'ecosystem_health' in self.report_data:\n sections.append('ecosystem_health')\n\n if 'security_assessment' in self.report_data:\n sections.append('security_assessment')\n\n if 'migration_analysis' in self.report_data:\n sections.append('migration_analysis')\n\n if 'performance_benchmarks' in self.report_data:\n sections.append('performance_benchmarks')\n\n return sections\n\n def _generate_title(self) -> str:\n \"\"\"Generate report title section.\"\"\"\n technologies = self.report_data.get('technologies', [])\n tech_names = ' vs '.join(technologies)\n use_case = self.report_data.get('use_case', 'General Purpose')\n\n if self.output_context == 'desktop':\n return f\"\"\"# Technology Stack Evaluation Report\n\n**Technologies**: {tech_names}\n**Use Case**: {use_case}\n**Generated**: {self._get_timestamp()}\n\n---\n\"\"\"\n else: # CLI\n return f\"\"\"================================================================================\nTECHNOLOGY STACK EVALUATION REPORT\n================================================================================\n\nTechnologies: {tech_names}\nUse Case: {use_case}\nGenerated: {self._get_timestamp()}\n\n================================================================================\n\"\"\"\n\n def _generate_section(self, section_name: str) -> Optional[str]:\n \"\"\"\n Generate specific report section.\n\n Args:\n section_name: Name of section to generate\n\n Returns:\n Section markdown or None\n \"\"\"\n generators = {\n 'executive_summary': self._section_executive_summary,\n 'comparison_matrix': self._section_comparison_matrix,\n 'tco_analysis': self._section_tco_analysis,\n 'ecosystem_health': self._section_ecosystem_health,\n 'security_assessment': self._section_security_assessment,\n 'migration_analysis': self._section_migration_analysis,\n 'performance_benchmarks': self._section_performance_benchmarks\n }\n\n generator = generators.get(section_name)\n if generator:\n return generator()\n\n return None\n\n def _section_executive_summary(self) -> str:\n \"\"\"Generate executive summary section.\"\"\"\n return self.generate_executive_summary()\n\n def _section_comparison_matrix(self) -> str:\n \"\"\"Generate comparison matrix section.\"\"\"\n matrix_data = self.report_data.get('comparison_matrix', [])\n if not matrix_data:\n return \"\"\n\n if self.output_context == 'desktop':\n return self._render_matrix_desktop(matrix_data)\n else:\n return self._render_matrix_cli(matrix_data)\n\n def _render_matrix_desktop(self, matrix_data: List[Dict[str, Any]]) -> str:\n \"\"\"Render comparison matrix for desktop (rich markdown table).\"\"\"\n parts = [\"## Comparison Matrix\\n\"]\n\n if not matrix_data:\n return \"\"\n\n # Get technology names from first row\n tech_names = list(matrix_data[0].get('scores', {}).keys())\n\n # Build table header\n header = \"| Category | Weight |\"\n for tech in tech_names:\n header += f\" {tech} |\"\n parts.append(header)\n\n # Separator\n separator = \"|----------|--------|\"\n separator += \"--------|\" * len(tech_names)\n parts.append(separator)\n\n # Rows\n for row in matrix_data:\n category = row.get('category', '').replace('_', ' ').title()\n weight = row.get('weight', '')\n scores = row.get('scores', {})\n\n row_str = f\"| {category} | {weight} |\"\n for tech in tech_names:\n score = scores.get(tech, '0.0')\n row_str += f\" {score} |\"\n\n parts.append(row_str)\n\n return '\\n'.join(parts)\n\n def _render_matrix_cli(self, matrix_data: List[Dict[str, Any]]) -> str:\n \"\"\"Render comparison matrix for CLI (ASCII table).\"\"\"\n parts = [\"COMPARISON MATRIX\", \"=\" * 80, \"\"]\n\n if not matrix_data:\n return \"\"\n\n # Get technology names\n tech_names = list(matrix_data[0].get('scores', {}).keys())\n\n # Calculate column widths\n category_width = 25\n weight_width = 8\n score_width = 10\n\n # Header\n header = f\"{'Category':\u003c{category_width}} {'Weight':\u003c{weight_width}}\"\n for tech in tech_names:\n header += f\" {tech[:score_width-1]:\u003c{score_width}}\"\n parts.append(header)\n parts.append(\"-\" * 80)\n\n # Rows\n for row in matrix_data:\n category = row.get('category', '').replace('_', ' ').title()[:category_width-1]\n weight = row.get('weight', '')\n scores = row.get('scores', {})\n\n row_str = f\"{category:\u003c{category_width}} {weight:\u003c{weight_width}}\"\n for tech in tech_names:\n score = scores.get(tech, '0.0')\n row_str += f\" {score:\u003c{score_width}}\"\n\n parts.append(row_str)\n\n return '\\n'.join(parts)\n\n def _section_tco_analysis(self) -> str:\n \"\"\"Generate TCO analysis section.\"\"\"\n tco_data = self.report_data.get('tco_analysis', {})\n if not tco_data:\n return \"\"\n\n parts = [\"## Total Cost of Ownership Analysis\\n\"]\n\n # Summary\n total_tco = tco_data.get('total_tco', 0)\n timeline = tco_data.get('timeline_years', 5)\n avg_yearly = tco_data.get('average_yearly_cost', 0)\n\n parts.append(f\"**{timeline}-Year Total**: ${total_tco:,.2f}\")\n parts.append(f\"**Average Yearly**: ${avg_yearly:,.2f}\\n\")\n\n # Cost breakdown\n initial = tco_data.get('initial_costs', {})\n parts.append(f\"### Initial Costs: ${initial.get('total_initial', 0):,.2f}\")\n\n # Operational costs\n operational = tco_data.get('operational_costs', {})\n if operational:\n parts.append(f\"\\n### Operational Costs (Yearly)\")\n yearly_totals = operational.get('total_yearly', [])\n for year, cost in enumerate(yearly_totals, 1):\n parts.append(f\"- Year {year}: ${cost:,.2f}\")\n\n return '\\n'.join(parts)\n\n def _section_ecosystem_health(self) -> str:\n \"\"\"Generate ecosystem health section.\"\"\"\n ecosystem_data = self.report_data.get('ecosystem_health', {})\n if not ecosystem_data:\n return \"\"\n\n parts = [\"## Ecosystem Health Analysis\\n\"]\n\n # Overall score\n overall_score = ecosystem_data.get('overall_health', 0)\n parts.append(f\"**Overall Health Score**: {overall_score:.1f}/100\\n\")\n\n # Component scores\n scores = ecosystem_data.get('health_scores', {})\n parts.append(\"### Health Metrics\")\n for metric, score in scores.items():\n if metric != 'overall_health':\n metric_name = metric.replace('_', ' ').title()\n parts.append(f\"- {metric_name}: {score:.1f}/100\")\n\n # Viability assessment\n viability = ecosystem_data.get('viability_assessment', {})\n if viability:\n parts.append(f\"\\n### Viability: {viability.get('overall_viability', 'Unknown')}\")\n parts.append(f\"**Risk Level**: {viability.get('risk_level', 'Unknown')}\")\n\n return '\\n'.join(parts)\n\n def _section_security_assessment(self) -> str:\n \"\"\"Generate security assessment section.\"\"\"\n security_data = self.report_data.get('security_assessment', {})\n if not security_data:\n return \"\"\n\n parts = [\"## Security & Compliance Assessment\\n\"]\n\n # Security score\n security_score = security_data.get('security_score', {})\n overall = security_score.get('overall_security_score', 0)\n grade = security_score.get('security_grade', 'N/A')\n\n parts.append(f\"**Security Score**: {overall:.1f}/100 (Grade: {grade})\\n\")\n\n # Compliance\n compliance = security_data.get('compliance_assessment', {})\n if compliance:\n parts.append(\"### Compliance Readiness\")\n for standard, assessment in compliance.items():\n level = assessment.get('readiness_level', 'Unknown')\n pct = assessment.get('readiness_percentage', 0)\n parts.append(f\"- **{standard}**: {level} ({pct:.0f}%)\")\n\n return '\\n'.join(parts)\n\n def _section_migration_analysis(self) -> str:\n \"\"\"Generate migration analysis section.\"\"\"\n migration_data = self.report_data.get('migration_analysis', {})\n if not migration_data:\n return \"\"\n\n parts = [\"## Migration Path Analysis\\n\"]\n\n # Complexity\n complexity = migration_data.get('complexity_analysis', {})\n overall_complexity = complexity.get('overall_complexity', 0)\n parts.append(f\"**Migration Complexity**: {overall_complexity:.1f}/10\\n\")\n\n # Effort estimation\n effort = migration_data.get('effort_estimation', {})\n if effort:\n total_hours = effort.get('total_hours', 0)\n person_months = effort.get('total_person_months', 0)\n timeline = effort.get('estimated_timeline', {})\n calendar_months = timeline.get('calendar_months', 0)\n\n parts.append(f\"### Effort Estimate\")\n parts.append(f\"- Total Effort: {person_months:.1f} person-months ({total_hours:.0f} hours)\")\n parts.append(f\"- Timeline: {calendar_months:.1f} calendar months\")\n\n # Recommended approach\n approach = migration_data.get('recommended_approach', {})\n if approach:\n parts.append(f\"\\n### Recommended Approach: {approach.get('approach', 'Unknown').replace('_', ' ').title()}\")\n parts.append(f\"{approach.get('description', '')}\")\n\n return '\\n'.join(parts)\n\n def _section_performance_benchmarks(self) -> str:\n \"\"\"Generate performance benchmarks section.\"\"\"\n benchmark_data = self.report_data.get('performance_benchmarks', {})\n if not benchmark_data:\n return \"\"\n\n parts = [\"## Performance Benchmarks\\n\"]\n\n # Throughput\n throughput = benchmark_data.get('throughput', {})\n if throughput:\n parts.append(\"### Throughput\")\n for tech, rps in throughput.items():\n parts.append(f\"- {tech}: {rps:,} requests/sec\")\n\n # Latency\n latency = benchmark_data.get('latency', {})\n if latency:\n parts.append(\"\\n### Latency (P95)\")\n for tech, ms in latency.items():\n parts.append(f\"- {tech}: {ms}ms\")\n\n return '\\n'.join(parts)\n\n def _get_timestamp(self) -> str:\n \"\"\"Get current timestamp.\"\"\"\n from datetime import datetime\n return datetime.now().strftime(\"%Y-%m-%d %H:%M\")\n\n def export_to_file(self, filename: str, sections: Optional[List[str]] = None) -> str:\n \"\"\"\n Export report to file.\n\n Args:\n filename: Output filename\n sections: Sections to include\n\n Returns:\n Path to exported file\n \"\"\"\n report = self.generate_full_report(sections)\n\n with open(filename, 'w', encoding='utf-8') as f:\n f.write(report)\n\n return filename\n","content_type":"text/x-python; charset=utf-8","language":"python","size":15891,"content_sha256":"07e94126bd655bfe30a7fac7b46b4b6aca356aad75bf7d7f4e670feb362ccdd1"},{"filename":"scripts/security_assessor.py","content":"\"\"\"\nSecurity and Compliance Assessor.\n\nAnalyzes security vulnerabilities, compliance readiness (GDPR, SOC2, HIPAA),\nand overall security posture of technology stacks.\n\"\"\"\n\nfrom typing import Dict, List, Any, Optional\nfrom datetime import datetime, timedelta\n\n\nclass SecurityAssessor:\n \"\"\"Assess security and compliance readiness of technology stacks.\"\"\"\n\n # Compliance standards mapping\n COMPLIANCE_STANDARDS = {\n 'GDPR': ['data_privacy', 'consent_management', 'data_portability', 'right_to_deletion', 'audit_logging'],\n 'SOC2': ['access_controls', 'encryption_at_rest', 'encryption_in_transit', 'audit_logging', 'backup_recovery'],\n 'HIPAA': ['phi_protection', 'encryption_at_rest', 'encryption_in_transit', 'access_controls', 'audit_logging'],\n 'PCI_DSS': ['payment_data_encryption', 'access_controls', 'network_security', 'vulnerability_management']\n }\n\n def __init__(self, security_data: Dict[str, Any]):\n \"\"\"\n Initialize security assessor with security data.\n\n Args:\n security_data: Dictionary containing vulnerability and compliance data\n \"\"\"\n self.technology = security_data.get('technology', 'Unknown')\n self.vulnerabilities = security_data.get('vulnerabilities', {})\n self.security_features = security_data.get('security_features', {})\n self.compliance_requirements = security_data.get('compliance_requirements', [])\n\n def calculate_security_score(self) -> Dict[str, Any]:\n \"\"\"\n Calculate overall security score (0-100).\n\n Returns:\n Dictionary with security score components\n \"\"\"\n # Component scores\n vuln_score = self._score_vulnerabilities()\n patch_score = self._score_patch_responsiveness()\n features_score = self._score_security_features()\n track_record_score = self._score_track_record()\n\n # Weighted average\n weights = {\n 'vulnerability_score': 0.30,\n 'patch_responsiveness': 0.25,\n 'security_features': 0.30,\n 'track_record': 0.15\n }\n\n overall = (\n vuln_score * weights['vulnerability_score'] +\n patch_score * weights['patch_responsiveness'] +\n features_score * weights['security_features'] +\n track_record_score * weights['track_record']\n )\n\n return {\n 'overall_security_score': overall,\n 'vulnerability_score': vuln_score,\n 'patch_responsiveness': patch_score,\n 'security_features_score': features_score,\n 'track_record_score': track_record_score,\n 'security_grade': self._calculate_grade(overall)\n }\n\n def _score_vulnerabilities(self) -> float:\n \"\"\"\n Score based on vulnerability count and severity.\n\n Returns:\n Vulnerability score (0-100, higher is better)\n \"\"\"\n # Get vulnerability counts by severity (last 12 months)\n critical = self.vulnerabilities.get('critical_last_12m', 0)\n high = self.vulnerabilities.get('high_last_12m', 0)\n medium = self.vulnerabilities.get('medium_last_12m', 0)\n low = self.vulnerabilities.get('low_last_12m', 0)\n\n # Calculate weighted vulnerability count\n weighted_vulns = (critical * 4) + (high * 2) + (medium * 1) + (low * 0.5)\n\n # Score based on weighted count (fewer is better)\n if weighted_vulns == 0:\n score = 100\n elif weighted_vulns \u003c= 5:\n score = 90\n elif weighted_vulns \u003c= 10:\n score = 80\n elif weighted_vulns \u003c= 20:\n score = 70\n elif weighted_vulns \u003c= 30:\n score = 60\n elif weighted_vulns \u003c= 50:\n score = 50\n else:\n score = max(0, 50 - (weighted_vulns - 50) / 2)\n\n # Penalty for critical vulnerabilities\n if critical > 0:\n score = max(0, score - (critical * 10))\n\n return max(0.0, min(100.0, score))\n\n def _score_patch_responsiveness(self) -> float:\n \"\"\"\n Score based on patch response time.\n\n Returns:\n Patch responsiveness score (0-100)\n \"\"\"\n # Average days to patch critical vulnerabilities\n critical_patch_days = self.vulnerabilities.get('avg_critical_patch_days', 30)\n high_patch_days = self.vulnerabilities.get('avg_high_patch_days', 60)\n\n # Score critical patch time (most important)\n if critical_patch_days \u003c= 7:\n critical_score = 50\n elif critical_patch_days \u003c= 14:\n critical_score = 40\n elif critical_patch_days \u003c= 30:\n critical_score = 30\n elif critical_patch_days \u003c= 60:\n critical_score = 20\n else:\n critical_score = 10\n\n # Score high severity patch time\n if high_patch_days \u003c= 14:\n high_score = 30\n elif high_patch_days \u003c= 30:\n high_score = 25\n elif high_patch_days \u003c= 60:\n high_score = 20\n elif high_patch_days \u003c= 90:\n high_score = 15\n else:\n high_score = 10\n\n # Has active security team\n has_security_team = self.vulnerabilities.get('has_security_team', False)\n team_score = 20 if has_security_team else 0\n\n total_score = critical_score + high_score + team_score\n\n return min(100.0, total_score)\n\n def _score_security_features(self) -> float:\n \"\"\"\n Score based on built-in security features.\n\n Returns:\n Security features score (0-100)\n \"\"\"\n score = 0.0\n\n # Essential features (10 points each)\n essential_features = [\n 'encryption_at_rest',\n 'encryption_in_transit',\n 'authentication',\n 'authorization',\n 'input_validation'\n ]\n\n for feature in essential_features:\n if self.security_features.get(feature, False):\n score += 10\n\n # Advanced features (5 points each)\n advanced_features = [\n 'rate_limiting',\n 'csrf_protection',\n 'xss_protection',\n 'sql_injection_protection',\n 'audit_logging',\n 'mfa_support',\n 'rbac',\n 'secrets_management',\n 'security_headers',\n 'cors_configuration'\n ]\n\n for feature in advanced_features:\n if self.security_features.get(feature, False):\n score += 5\n\n return min(100.0, score)\n\n def _score_track_record(self) -> float:\n \"\"\"\n Score based on historical security track record.\n\n Returns:\n Track record score (0-100)\n \"\"\"\n score = 50.0 # Start at neutral\n\n # Years since major security incident\n years_since_major = self.vulnerabilities.get('years_since_major_incident', 5)\n if years_since_major >= 3:\n score += 30\n elif years_since_major >= 1:\n score += 15\n else:\n score -= 10\n\n # Security certifications\n has_certifications = self.vulnerabilities.get('has_security_certifications', False)\n if has_certifications:\n score += 20\n\n # Bug bounty program\n has_bug_bounty = self.vulnerabilities.get('has_bug_bounty_program', False)\n if has_bug_bounty:\n score += 10\n\n # Security audits\n security_audits = self.vulnerabilities.get('security_audits_per_year', 0)\n score += min(20, security_audits * 10)\n\n return min(100.0, max(0.0, score))\n\n def _calculate_grade(self, score: float) -> str:\n \"\"\"\n Convert score to letter grade.\n\n Args:\n score: Security score (0-100)\n\n Returns:\n Letter grade\n \"\"\"\n if score >= 90:\n return \"A\"\n elif score >= 80:\n return \"B\"\n elif score >= 70:\n return \"C\"\n elif score >= 60:\n return \"D\"\n else:\n return \"F\"\n\n def assess_compliance(self, standards: List[str] = None) -> Dict[str, Dict[str, Any]]:\n \"\"\"\n Assess compliance readiness for specified standards.\n\n Args:\n standards: List of compliance standards to assess (defaults to all required)\n\n Returns:\n Dictionary of compliance assessments by standard\n \"\"\"\n if standards is None:\n standards = self.compliance_requirements\n\n results = {}\n\n for standard in standards:\n if standard not in self.COMPLIANCE_STANDARDS:\n results[standard] = {\n 'readiness': 'Unknown',\n 'score': 0,\n 'status': 'Unknown standard'\n }\n continue\n\n readiness = self._assess_standard_readiness(standard)\n results[standard] = readiness\n\n return results\n\n def _assess_standard_readiness(self, standard: str) -> Dict[str, Any]:\n \"\"\"\n Assess readiness for a specific compliance standard.\n\n Args:\n standard: Compliance standard name\n\n Returns:\n Readiness assessment\n \"\"\"\n required_features = self.COMPLIANCE_STANDARDS[standard]\n met_count = 0\n total_count = len(required_features)\n missing_features = []\n\n for feature in required_features:\n if self.security_features.get(feature, False):\n met_count += 1\n else:\n missing_features.append(feature)\n\n # Calculate readiness percentage\n readiness_pct = (met_count / total_count * 100) if total_count > 0 else 0\n\n # Determine readiness level\n if readiness_pct >= 90:\n readiness_level = \"Ready\"\n status = \"Compliant - meets all requirements\"\n elif readiness_pct >= 70:\n readiness_level = \"Mostly Ready\"\n status = \"Minor gaps - additional configuration needed\"\n elif readiness_pct >= 50:\n readiness_level = \"Partial\"\n status = \"Significant work required\"\n else:\n readiness_level = \"Not Ready\"\n status = \"Major gaps - extensive implementation needed\"\n\n return {\n 'readiness_level': readiness_level,\n 'readiness_percentage': readiness_pct,\n 'status': status,\n 'features_met': met_count,\n 'features_required': total_count,\n 'missing_features': missing_features,\n 'recommendation': self._generate_compliance_recommendation(readiness_level, missing_features)\n }\n\n def _generate_compliance_recommendation(self, readiness_level: str, missing_features: List[str]) -> str:\n \"\"\"\n Generate compliance recommendation.\n\n Args:\n readiness_level: Current readiness level\n missing_features: List of missing features\n\n Returns:\n Recommendation string\n \"\"\"\n if readiness_level == \"Ready\":\n return \"Proceed with compliance audit and certification\"\n elif readiness_level == \"Mostly Ready\":\n return f\"Implement missing features: {', '.join(missing_features[:3])}\"\n elif readiness_level == \"Partial\":\n return f\"Significant implementation needed. Start with: {', '.join(missing_features[:3])}\"\n else:\n return \"Not recommended without major security enhancements\"\n\n def identify_vulnerabilities(self) -> Dict[str, Any]:\n \"\"\"\n Identify and categorize vulnerabilities.\n\n Returns:\n Categorized vulnerability report\n \"\"\"\n # Current vulnerabilities\n current = {\n 'critical': self.vulnerabilities.get('critical_last_12m', 0),\n 'high': self.vulnerabilities.get('high_last_12m', 0),\n 'medium': self.vulnerabilities.get('medium_last_12m', 0),\n 'low': self.vulnerabilities.get('low_last_12m', 0)\n }\n\n # Historical vulnerabilities (last 3 years)\n historical = {\n 'critical': self.vulnerabilities.get('critical_last_3y', 0),\n 'high': self.vulnerabilities.get('high_last_3y', 0),\n 'medium': self.vulnerabilities.get('medium_last_3y', 0),\n 'low': self.vulnerabilities.get('low_last_3y', 0)\n }\n\n # Common vulnerability types\n common_types = self.vulnerabilities.get('common_vulnerability_types', [\n 'SQL Injection',\n 'XSS',\n 'CSRF',\n 'Authentication Issues'\n ])\n\n return {\n 'current_vulnerabilities': current,\n 'total_current': sum(current.values()),\n 'historical_vulnerabilities': historical,\n 'total_historical': sum(historical.values()),\n 'common_types': common_types,\n 'severity_distribution': self._calculate_severity_distribution(current),\n 'trend': self._analyze_vulnerability_trend(current, historical)\n }\n\n def _calculate_severity_distribution(self, vulnerabilities: Dict[str, int]) -> Dict[str, str]:\n \"\"\"\n Calculate percentage distribution of vulnerability severities.\n\n Args:\n vulnerabilities: Vulnerability counts by severity\n\n Returns:\n Percentage distribution\n \"\"\"\n total = sum(vulnerabilities.values())\n if total == 0:\n return {k: \"0%\" for k in vulnerabilities.keys()}\n\n return {\n severity: f\"{(count / total * 100):.1f}%\"\n for severity, count in vulnerabilities.items()\n }\n\n def _analyze_vulnerability_trend(self, current: Dict[str, int], historical: Dict[str, int]) -> str:\n \"\"\"\n Analyze vulnerability trend.\n\n Args:\n current: Current vulnerabilities\n historical: Historical vulnerabilities\n\n Returns:\n Trend description\n \"\"\"\n current_total = sum(current.values())\n historical_avg = sum(historical.values()) / 3 # 3-year average\n\n if current_total \u003c historical_avg * 0.7:\n return \"Improving - fewer vulnerabilities than historical average\"\n elif current_total \u003c historical_avg * 1.2:\n return \"Stable - consistent with historical average\"\n else:\n return \"Concerning - more vulnerabilities than historical average\"\n\n def generate_security_report(self) -> Dict[str, Any]:\n \"\"\"\n Generate comprehensive security assessment report.\n\n Returns:\n Complete security analysis\n \"\"\"\n security_score = self.calculate_security_score()\n compliance = self.assess_compliance()\n vulnerabilities = self.identify_vulnerabilities()\n\n # Generate recommendations\n recommendations = self._generate_security_recommendations(\n security_score,\n compliance,\n vulnerabilities\n )\n\n return {\n 'technology': self.technology,\n 'security_score': security_score,\n 'compliance_assessment': compliance,\n 'vulnerability_analysis': vulnerabilities,\n 'recommendations': recommendations,\n 'overall_risk_level': self._determine_risk_level(security_score['overall_security_score'])\n }\n\n def _generate_security_recommendations(\n self,\n security_score: Dict[str, Any],\n compliance: Dict[str, Dict[str, Any]],\n vulnerabilities: Dict[str, Any]\n ) -> List[str]:\n \"\"\"\n Generate security recommendations.\n\n Args:\n security_score: Security score data\n compliance: Compliance assessment\n vulnerabilities: Vulnerability analysis\n\n Returns:\n List of recommendations\n \"\"\"\n recommendations = []\n\n # Security score recommendations\n if security_score['overall_security_score'] \u003c 70:\n recommendations.append(\"Improve overall security posture - score below acceptable threshold\")\n\n # Vulnerability recommendations\n current_critical = vulnerabilities['current_vulnerabilities']['critical']\n if current_critical > 0:\n recommendations.append(f\"Address {current_critical} critical vulnerabilities immediately\")\n\n # Patch responsiveness\n if security_score['patch_responsiveness'] \u003c 60:\n recommendations.append(\"Improve vulnerability patch response time\")\n\n # Security features\n if security_score['security_features_score'] \u003c 70:\n recommendations.append(\"Implement additional security features (MFA, audit logging, RBAC)\")\n\n # Compliance recommendations\n for standard, assessment in compliance.items():\n if assessment['readiness_level'] == \"Not Ready\":\n recommendations.append(f\"{standard}: {assessment['recommendation']}\")\n\n if not recommendations:\n recommendations.append(\"Security posture is strong - continue monitoring and maintenance\")\n\n return recommendations\n\n def _determine_risk_level(self, security_score: float) -> str:\n \"\"\"\n Determine overall risk level.\n\n Args:\n security_score: Overall security score\n\n Returns:\n Risk level description\n \"\"\"\n if security_score >= 85:\n return \"Low Risk - Strong security posture\"\n elif security_score >= 70:\n return \"Medium Risk - Acceptable with monitoring\"\n elif security_score >= 55:\n return \"High Risk - Security improvements needed\"\n else:\n return \"Critical Risk - Not recommended for production use\"\n","content_type":"text/x-python; charset=utf-8","language":"python","size":17733,"content_sha256":"0b498feeb302332978a2498c7a83de1a4b362eaba39ff598e07595e610359590"},{"filename":"scripts/stack_comparator.py","content":"\"\"\"\nTechnology Stack Comparator - Main comparison engine with weighted scoring.\n\nProvides comprehensive technology comparison with customizable weighted criteria,\nfeature matrices, and intelligent recommendation generation.\n\"\"\"\n\nfrom typing import Dict, List, Any, Optional, Tuple\nimport json\n\n\nclass StackComparator:\n \"\"\"Main comparison engine for technology stack evaluation.\"\"\"\n\n # Feature categories for evaluation\n FEATURE_CATEGORIES = [\n \"performance\",\n \"scalability\",\n \"developer_experience\",\n \"ecosystem\",\n \"learning_curve\",\n \"documentation\",\n \"community_support\",\n \"enterprise_readiness\"\n ]\n\n # Default weights if not provided\n DEFAULT_WEIGHTS = {\n \"performance\": 15,\n \"scalability\": 15,\n \"developer_experience\": 20,\n \"ecosystem\": 15,\n \"learning_curve\": 10,\n \"documentation\": 10,\n \"community_support\": 10,\n \"enterprise_readiness\": 5\n }\n\n def __init__(self, comparison_data: Dict[str, Any]):\n \"\"\"\n Initialize comparator with comparison data.\n\n Args:\n comparison_data: Dictionary containing technologies to compare and criteria\n \"\"\"\n self.technologies = comparison_data.get('technologies', [])\n self.use_case = comparison_data.get('use_case', 'general')\n self.priorities = comparison_data.get('priorities', {})\n self.weights = self._normalize_weights(comparison_data.get('weights', {}))\n self.scores = {}\n\n def _normalize_weights(self, custom_weights: Dict[str, float]) -> Dict[str, float]:\n \"\"\"\n Normalize weights to sum to 100.\n\n Args:\n custom_weights: User-provided weights\n\n Returns:\n Normalized weights dictionary\n \"\"\"\n # Start with defaults\n weights = self.DEFAULT_WEIGHTS.copy()\n\n # Override with custom weights\n weights.update(custom_weights)\n\n # Normalize to 100\n total = sum(weights.values())\n if total == 0:\n return self.DEFAULT_WEIGHTS\n\n return {k: (v / total) * 100 for k, v in weights.items()}\n\n def score_technology(self, tech_name: str, tech_data: Dict[str, Any]) -> Dict[str, float]:\n \"\"\"\n Score a single technology across all criteria.\n\n Args:\n tech_name: Name of technology\n tech_data: Technology feature and metric data\n\n Returns:\n Dictionary of category scores (0-100 scale)\n \"\"\"\n scores = {}\n\n for category in self.FEATURE_CATEGORIES:\n # Get raw score from tech data (0-100 scale)\n raw_score = tech_data.get(category, {}).get('score', 50.0)\n\n # Apply use-case specific adjustments\n adjusted_score = self._adjust_for_use_case(category, raw_score, tech_name)\n\n scores[category] = min(100.0, max(0.0, adjusted_score))\n\n return scores\n\n def _adjust_for_use_case(self, category: str, score: float, tech_name: str) -> float:\n \"\"\"\n Apply use-case specific adjustments to scores.\n\n Args:\n category: Feature category\n score: Raw score\n tech_name: Technology name\n\n Returns:\n Adjusted score\n \"\"\"\n # Use case specific bonuses/penalties\n adjustments = {\n 'real-time': {\n 'performance': 1.1, # 10% bonus for real-time use cases\n 'scalability': 1.1\n },\n 'enterprise': {\n 'enterprise_readiness': 1.2, # 20% bonus\n 'documentation': 1.1\n },\n 'startup': {\n 'developer_experience': 1.15,\n 'learning_curve': 1.1\n }\n }\n\n # Determine use case type\n use_case_lower = self.use_case.lower()\n use_case_type = None\n\n for uc_key in adjustments.keys():\n if uc_key in use_case_lower:\n use_case_type = uc_key\n break\n\n # Apply adjustment if applicable\n if use_case_type and category in adjustments[use_case_type]:\n multiplier = adjustments[use_case_type][category]\n return score * multiplier\n\n return score\n\n def calculate_weighted_score(self, category_scores: Dict[str, float]) -> float:\n \"\"\"\n Calculate weighted total score.\n\n Args:\n category_scores: Dictionary of category scores\n\n Returns:\n Weighted total score (0-100 scale)\n \"\"\"\n total = 0.0\n\n for category, score in category_scores.items():\n weight = self.weights.get(category, 0.0) / 100.0 # Convert to decimal\n total += score * weight\n\n return total\n\n def compare_technologies(self, tech_data_list: List[Dict[str, Any]]) -> Dict[str, Any]:\n \"\"\"\n Compare multiple technologies and generate recommendation.\n\n Args:\n tech_data_list: List of technology data dictionaries\n\n Returns:\n Comparison results with scores and recommendation\n \"\"\"\n results = {\n 'technologies': {},\n 'recommendation': None,\n 'confidence': 0.0,\n 'decision_factors': [],\n 'comparison_matrix': []\n }\n\n # Score each technology\n tech_scores = {}\n for tech_data in tech_data_list:\n tech_name = tech_data.get('name', 'Unknown')\n category_scores = self.score_technology(tech_name, tech_data)\n weighted_score = self.calculate_weighted_score(category_scores)\n\n tech_scores[tech_name] = {\n 'category_scores': category_scores,\n 'weighted_total': weighted_score,\n 'strengths': self._identify_strengths(category_scores),\n 'weaknesses': self._identify_weaknesses(category_scores)\n }\n\n results['technologies'] = tech_scores\n\n # Generate recommendation\n results['recommendation'], results['confidence'] = self._generate_recommendation(tech_scores)\n results['decision_factors'] = self._extract_decision_factors(tech_scores)\n results['comparison_matrix'] = self._build_comparison_matrix(tech_scores)\n\n return results\n\n def _identify_strengths(self, category_scores: Dict[str, float], threshold: float = 75.0) -> List[str]:\n \"\"\"\n Identify strength categories (scores above threshold).\n\n Args:\n category_scores: Category scores dictionary\n threshold: Score threshold for strength identification\n\n Returns:\n List of strength categories\n \"\"\"\n return [\n category for category, score in category_scores.items()\n if score >= threshold\n ]\n\n def _identify_weaknesses(self, category_scores: Dict[str, float], threshold: float = 50.0) -> List[str]:\n \"\"\"\n Identify weakness categories (scores below threshold).\n\n Args:\n category_scores: Category scores dictionary\n threshold: Score threshold for weakness identification\n\n Returns:\n List of weakness categories\n \"\"\"\n return [\n category for category, score in category_scores.items()\n if score \u003c threshold\n ]\n\n def _generate_recommendation(self, tech_scores: Dict[str, Dict[str, Any]]) -> Tuple[str, float]:\n \"\"\"\n Generate recommendation and confidence level.\n\n Args:\n tech_scores: Technology scores dictionary\n\n Returns:\n Tuple of (recommended_technology, confidence_score)\n \"\"\"\n if not tech_scores:\n return \"Insufficient data\", 0.0\n\n # Sort by weighted total score\n sorted_techs = sorted(\n tech_scores.items(),\n key=lambda x: x[1]['weighted_total'],\n reverse=True\n )\n\n top_tech = sorted_techs[0][0]\n top_score = sorted_techs[0][1]['weighted_total']\n\n # Calculate confidence based on score gap\n if len(sorted_techs) > 1:\n second_score = sorted_techs[1][1]['weighted_total']\n score_gap = top_score - second_score\n\n # Confidence increases with score gap\n # 0-5 gap: low confidence\n # 5-15 gap: medium confidence\n # 15+ gap: high confidence\n if score_gap \u003c 5:\n confidence = 40.0 + (score_gap * 2) # 40-50%\n elif score_gap \u003c 15:\n confidence = 50.0 + (score_gap - 5) * 2 # 50-70%\n else:\n confidence = 70.0 + min(score_gap - 15, 30) # 70-100%\n else:\n confidence = 100.0 # Only one option\n\n return top_tech, min(100.0, confidence)\n\n def _extract_decision_factors(self, tech_scores: Dict[str, Dict[str, Any]]) -> List[Dict[str, Any]]:\n \"\"\"\n Extract key decision factors from comparison.\n\n Args:\n tech_scores: Technology scores dictionary\n\n Returns:\n List of decision factors with importance weights\n \"\"\"\n factors = []\n\n # Get top weighted categories\n sorted_weights = sorted(\n self.weights.items(),\n key=lambda x: x[1],\n reverse=True\n )[:3] # Top 3 factors\n\n for category, weight in sorted_weights:\n # Get scores for this category across all techs\n category_scores = {\n tech: scores['category_scores'].get(category, 0.0)\n for tech, scores in tech_scores.items()\n }\n\n # Find best performer\n best_tech = max(category_scores.items(), key=lambda x: x[1])\n\n factors.append({\n 'category': category,\n 'importance': f\"{weight:.1f}%\",\n 'best_performer': best_tech[0],\n 'score': best_tech[1]\n })\n\n return factors\n\n def _build_comparison_matrix(self, tech_scores: Dict[str, Dict[str, Any]]) -> List[Dict[str, Any]]:\n \"\"\"\n Build comparison matrix for display.\n\n Args:\n tech_scores: Technology scores dictionary\n\n Returns:\n List of comparison matrix rows\n \"\"\"\n matrix = []\n\n for category in self.FEATURE_CATEGORIES:\n row = {\n 'category': category,\n 'weight': f\"{self.weights.get(category, 0):.1f}%\",\n 'scores': {}\n }\n\n for tech_name, scores in tech_scores.items():\n category_score = scores['category_scores'].get(category, 0.0)\n row['scores'][tech_name] = f\"{category_score:.1f}\"\n\n matrix.append(row)\n\n # Add weighted totals row\n totals_row = {\n 'category': 'WEIGHTED TOTAL',\n 'weight': '100%',\n 'scores': {}\n }\n\n for tech_name, scores in tech_scores.items():\n totals_row['scores'][tech_name] = f\"{scores['weighted_total']:.1f}\"\n\n matrix.append(totals_row)\n\n return matrix\n\n def generate_pros_cons(self, tech_name: str, tech_scores: Dict[str, Any]) -> Dict[str, List[str]]:\n \"\"\"\n Generate pros and cons for a technology.\n\n Args:\n tech_name: Technology name\n tech_scores: Technology scores dictionary\n\n Returns:\n Dictionary with 'pros' and 'cons' lists\n \"\"\"\n category_scores = tech_scores['category_scores']\n strengths = tech_scores['strengths']\n weaknesses = tech_scores['weaknesses']\n\n pros = []\n cons = []\n\n # Generate pros from strengths\n for strength in strengths[:3]: # Top 3\n score = category_scores[strength]\n pros.append(f\"Excellent {strength.replace('_', ' ')} (score: {score:.1f}/100)\")\n\n # Generate cons from weaknesses\n for weakness in weaknesses[:3]: # Top 3\n score = category_scores[weakness]\n cons.append(f\"Weaker {weakness.replace('_', ' ')} (score: {score:.1f}/100)\")\n\n # Add generic pros/cons if not enough specific ones\n if len(pros) == 0:\n pros.append(f\"Balanced performance across all categories\")\n\n if len(cons) == 0:\n cons.append(f\"No significant weaknesses identified\")\n\n return {'pros': pros, 'cons': cons}\n","content_type":"text/x-python; charset=utf-8","language":"python","size":12381,"content_sha256":"bd56d8776c5bbd6b7c7827b83facfbf26893ad28097febc5725fed45feae4cf4"},{"filename":"scripts/tco_calculator.py","content":"\"\"\"\nTotal Cost of Ownership (TCO) Calculator.\n\nCalculates comprehensive TCO including licensing, hosting, developer productivity,\nscaling costs, and hidden costs over multi-year projections.\n\"\"\"\n\nfrom typing import Dict, List, Any, Optional\nimport json\n\n\nclass TCOCalculator:\n \"\"\"Calculate Total Cost of Ownership for technology stacks.\"\"\"\n\n def __init__(self, tco_data: Dict[str, Any]):\n \"\"\"\n Initialize TCO calculator with cost parameters.\n\n Args:\n tco_data: Dictionary containing cost parameters and projections\n \"\"\"\n self.technology = tco_data.get('technology', 'Unknown')\n self.team_size = tco_data.get('team_size', 5)\n self.timeline_years = tco_data.get('timeline_years', 5)\n self.initial_costs = tco_data.get('initial_costs', {})\n self.operational_costs = tco_data.get('operational_costs', {})\n self.scaling_params = tco_data.get('scaling_params', {})\n self.productivity_factors = tco_data.get('productivity_factors', {})\n\n def calculate_initial_costs(self) -> Dict[str, float]:\n \"\"\"\n Calculate one-time initial costs.\n\n Returns:\n Dictionary of initial cost components\n \"\"\"\n costs = {\n 'licensing': self.initial_costs.get('licensing', 0.0),\n 'training': self._calculate_training_costs(),\n 'migration': self.initial_costs.get('migration', 0.0),\n 'setup': self.initial_costs.get('setup', 0.0),\n 'tooling': self.initial_costs.get('tooling', 0.0)\n }\n\n costs['total_initial'] = sum(costs.values())\n return costs\n\n def _calculate_training_costs(self) -> float:\n \"\"\"\n Calculate training costs based on team size and learning curve.\n\n Returns:\n Total training cost\n \"\"\"\n # Default training assumptions\n hours_per_developer = self.initial_costs.get('training_hours_per_dev', 40)\n avg_hourly_rate = self.initial_costs.get('developer_hourly_rate', 100)\n training_materials = self.initial_costs.get('training_materials', 500)\n\n total_hours = self.team_size * hours_per_developer\n total_cost = (total_hours * avg_hourly_rate) + training_materials\n\n return total_cost\n\n def calculate_operational_costs(self) -> Dict[str, List[float]]:\n \"\"\"\n Calculate ongoing operational costs per year.\n\n Returns:\n Dictionary with yearly cost projections\n \"\"\"\n yearly_costs = {\n 'licensing': [],\n 'hosting': [],\n 'support': [],\n 'maintenance': [],\n 'total_yearly': []\n }\n\n for year in range(1, self.timeline_years + 1):\n # Licensing costs (may include annual fees)\n license_cost = self.operational_costs.get('annual_licensing', 0.0)\n yearly_costs['licensing'].append(license_cost)\n\n # Hosting costs (scale with growth)\n hosting_cost = self._calculate_hosting_cost(year)\n yearly_costs['hosting'].append(hosting_cost)\n\n # Support costs\n support_cost = self.operational_costs.get('annual_support', 0.0)\n yearly_costs['support'].append(support_cost)\n\n # Maintenance costs (developer time)\n maintenance_cost = self._calculate_maintenance_cost(year)\n yearly_costs['maintenance'].append(maintenance_cost)\n\n # Total for year\n year_total = (\n license_cost + hosting_cost + support_cost + maintenance_cost\n )\n yearly_costs['total_yearly'].append(year_total)\n\n return yearly_costs\n\n def _calculate_hosting_cost(self, year: int) -> float:\n \"\"\"\n Calculate hosting costs with growth projection.\n\n Args:\n year: Year number (1-indexed)\n\n Returns:\n Hosting cost for the year\n \"\"\"\n base_cost = self.operational_costs.get('monthly_hosting', 1000.0) * 12\n growth_rate = self.scaling_params.get('annual_growth_rate', 0.20) # 20% default\n\n # Apply compound growth\n year_cost = base_cost * ((1 + growth_rate) ** (year - 1))\n\n return year_cost\n\n def _calculate_maintenance_cost(self, year: int) -> float:\n \"\"\"\n Calculate maintenance costs (developer time).\n\n Args:\n year: Year number (1-indexed)\n\n Returns:\n Maintenance cost for the year\n \"\"\"\n hours_per_dev_per_month = self.operational_costs.get('maintenance_hours_per_dev_monthly', 20)\n avg_hourly_rate = self.initial_costs.get('developer_hourly_rate', 100)\n\n monthly_cost = self.team_size * hours_per_dev_per_month * avg_hourly_rate\n yearly_cost = monthly_cost * 12\n\n return yearly_cost\n\n def calculate_scaling_costs(self) -> Dict[str, Any]:\n \"\"\"\n Calculate scaling-related costs and metrics.\n\n Returns:\n Dictionary with scaling cost analysis\n \"\"\"\n # Project user growth\n initial_users = self.scaling_params.get('initial_users', 1000)\n annual_growth_rate = self.scaling_params.get('annual_growth_rate', 0.20)\n\n user_projections = []\n for year in range(1, self.timeline_years + 1):\n users = initial_users * ((1 + annual_growth_rate) ** year)\n user_projections.append(int(users))\n\n # Calculate cost per user\n operational = self.calculate_operational_costs()\n cost_per_user = []\n\n for year_idx, year_cost in enumerate(operational['total_yearly']):\n users = user_projections[year_idx]\n cost_per_user.append(year_cost / users if users > 0 else 0)\n\n # Infrastructure scaling costs\n infra_scaling = self._calculate_infrastructure_scaling()\n\n return {\n 'user_projections': user_projections,\n 'cost_per_user': cost_per_user,\n 'infrastructure_scaling': infra_scaling,\n 'scaling_efficiency': self._calculate_scaling_efficiency(cost_per_user)\n }\n\n def _calculate_infrastructure_scaling(self) -> Dict[str, List[float]]:\n \"\"\"\n Calculate infrastructure scaling costs.\n\n Returns:\n Infrastructure cost projections\n \"\"\"\n base_servers = self.scaling_params.get('initial_servers', 5)\n cost_per_server_monthly = self.scaling_params.get('cost_per_server_monthly', 200)\n growth_rate = self.scaling_params.get('annual_growth_rate', 0.20)\n\n server_costs = []\n for year in range(1, self.timeline_years + 1):\n servers_needed = base_servers * ((1 + growth_rate) ** year)\n yearly_cost = servers_needed * cost_per_server_monthly * 12\n server_costs.append(yearly_cost)\n\n return {\n 'yearly_infrastructure_costs': server_costs\n }\n\n def _calculate_scaling_efficiency(self, cost_per_user: List[float]) -> str:\n \"\"\"\n Assess scaling efficiency based on cost per user trend.\n\n Args:\n cost_per_user: List of yearly cost per user\n\n Returns:\n Efficiency assessment\n \"\"\"\n if len(cost_per_user) \u003c 2:\n return \"Insufficient data\"\n\n # Compare first year to last year\n initial = cost_per_user[0]\n final = cost_per_user[-1]\n\n if final \u003c initial * 0.8:\n return \"Excellent - economies of scale achieved\"\n elif final \u003c initial:\n return \"Good - improving efficiency over time\"\n elif final \u003c initial * 1.2:\n return \"Moderate - costs growing with users\"\n else:\n return \"Poor - costs growing faster than users\"\n\n def calculate_productivity_impact(self) -> Dict[str, Any]:\n \"\"\"\n Calculate developer productivity impact.\n\n Returns:\n Productivity analysis\n \"\"\"\n # Productivity multiplier (1.0 = baseline)\n productivity_multiplier = self.productivity_factors.get('productivity_multiplier', 1.0)\n\n # Time to market impact (in days)\n ttm_reduction = self.productivity_factors.get('time_to_market_reduction_days', 0)\n\n # Calculate value of faster development\n avg_feature_time_days = self.productivity_factors.get('avg_feature_time_days', 30)\n features_per_year = 365 / avg_feature_time_days\n faster_features_per_year = 365 / max(1, avg_feature_time_days - ttm_reduction)\n\n additional_features = faster_features_per_year - features_per_year\n feature_value = self.productivity_factors.get('avg_feature_value', 10000)\n\n yearly_productivity_value = additional_features * feature_value\n\n return {\n 'productivity_multiplier': productivity_multiplier,\n 'time_to_market_reduction_days': ttm_reduction,\n 'additional_features_per_year': additional_features,\n 'yearly_productivity_value': yearly_productivity_value,\n 'five_year_productivity_value': yearly_productivity_value * self.timeline_years\n }\n\n def calculate_hidden_costs(self) -> Dict[str, float]:\n \"\"\"\n Identify and calculate hidden costs.\n\n Returns:\n Dictionary of hidden cost components\n \"\"\"\n costs = {\n 'technical_debt': self._estimate_technical_debt(),\n 'vendor_lock_in_risk': self._estimate_vendor_lock_in_cost(),\n 'security_incidents': self._estimate_security_costs(),\n 'downtime_risk': self._estimate_downtime_costs(),\n 'developer_turnover': self._estimate_turnover_costs()\n }\n\n costs['total_hidden_costs'] = sum(costs.values())\n return costs\n\n def _estimate_technical_debt(self) -> float:\n \"\"\"\n Estimate technical debt accumulation costs.\n\n Returns:\n Estimated technical debt cost\n \"\"\"\n # Percentage of development time spent on debt\n debt_percentage = self.productivity_factors.get('technical_debt_percentage', 0.15)\n yearly_dev_cost = self._calculate_maintenance_cost(1) # Year 1 baseline\n\n # Technical debt accumulates over time\n total_debt_cost = 0\n for year in range(1, self.timeline_years + 1):\n year_debt = yearly_dev_cost * debt_percentage * year # Increases each year\n total_debt_cost += year_debt\n\n return total_debt_cost\n\n def _estimate_vendor_lock_in_cost(self) -> float:\n \"\"\"\n Estimate cost of vendor lock-in.\n\n Returns:\n Estimated lock-in cost\n \"\"\"\n lock_in_risk = self.productivity_factors.get('vendor_lock_in_risk', 'low')\n\n # Migration cost if switching vendors\n migration_cost = self.initial_costs.get('migration', 10000)\n\n risk_multipliers = {\n 'low': 0.1,\n 'medium': 0.3,\n 'high': 0.6\n }\n\n multiplier = risk_multipliers.get(lock_in_risk, 0.2)\n return migration_cost * multiplier\n\n def _estimate_security_costs(self) -> float:\n \"\"\"\n Estimate potential security incident costs.\n\n Returns:\n Estimated security cost\n \"\"\"\n incidents_per_year = self.productivity_factors.get('security_incidents_per_year', 0.5)\n avg_incident_cost = self.productivity_factors.get('avg_security_incident_cost', 50000)\n\n total_cost = incidents_per_year * avg_incident_cost * self.timeline_years\n return total_cost\n\n def _estimate_downtime_costs(self) -> float:\n \"\"\"\n Estimate downtime costs.\n\n Returns:\n Estimated downtime cost\n \"\"\"\n hours_downtime_per_year = self.productivity_factors.get('downtime_hours_per_year', 2)\n cost_per_hour = self.productivity_factors.get('downtime_cost_per_hour', 5000)\n\n total_cost = hours_downtime_per_year * cost_per_hour * self.timeline_years\n return total_cost\n\n def _estimate_turnover_costs(self) -> float:\n \"\"\"\n Estimate costs from developer turnover.\n\n Returns:\n Estimated turnover cost\n \"\"\"\n turnover_rate = self.productivity_factors.get('annual_turnover_rate', 0.15)\n cost_per_hire = self.productivity_factors.get('cost_per_new_hire', 30000)\n\n hires_per_year = self.team_size * turnover_rate\n total_cost = hires_per_year * cost_per_hire * self.timeline_years\n\n return total_cost\n\n def calculate_total_tco(self) -> Dict[str, Any]:\n \"\"\"\n Calculate complete TCO over the timeline.\n\n Returns:\n Comprehensive TCO analysis\n \"\"\"\n initial = self.calculate_initial_costs()\n operational = self.calculate_operational_costs()\n scaling = self.calculate_scaling_costs()\n productivity = self.calculate_productivity_impact()\n hidden = self.calculate_hidden_costs()\n\n # Calculate total costs\n total_operational = sum(operational['total_yearly'])\n total_cost = initial['total_initial'] + total_operational + hidden['total_hidden_costs']\n\n # Adjust for productivity gains\n net_cost = total_cost - productivity['five_year_productivity_value']\n\n return {\n 'technology': self.technology,\n 'timeline_years': self.timeline_years,\n 'initial_costs': initial,\n 'operational_costs': operational,\n 'scaling_analysis': scaling,\n 'productivity_impact': productivity,\n 'hidden_costs': hidden,\n 'total_tco': total_cost,\n 'net_tco_after_productivity': net_cost,\n 'average_yearly_cost': total_cost / self.timeline_years\n }\n\n def generate_tco_summary(self) -> Dict[str, Any]:\n \"\"\"\n Generate executive summary of TCO.\n\n Returns:\n TCO summary for reporting\n \"\"\"\n tco = self.calculate_total_tco()\n\n return {\n 'technology': self.technology,\n 'total_tco': f\"${tco['total_tco']:,.2f}\",\n 'net_tco': f\"${tco['net_tco_after_productivity']:,.2f}\",\n 'average_yearly': f\"${tco['average_yearly_cost']:,.2f}\",\n 'initial_investment': f\"${tco['initial_costs']['total_initial']:,.2f}\",\n 'key_cost_drivers': self._identify_cost_drivers(tco),\n 'cost_optimization_opportunities': self._identify_optimizations(tco)\n }\n\n def _identify_cost_drivers(self, tco: Dict[str, Any]) -> List[str]:\n \"\"\"\n Identify top cost drivers.\n\n Args:\n tco: Complete TCO analysis\n\n Returns:\n List of top cost drivers\n \"\"\"\n drivers = []\n\n # Check operational costs\n operational = tco['operational_costs']\n total_hosting = sum(operational['hosting'])\n total_maintenance = sum(operational['maintenance'])\n\n if total_hosting > total_maintenance:\n drivers.append(f\"Infrastructure/hosting ({total_hosting:,.0f})\")\n else:\n drivers.append(f\"Developer maintenance time ({total_maintenance:,.0f})\")\n\n # Check hidden costs\n hidden = tco['hidden_costs']\n if hidden['technical_debt'] > 10000:\n drivers.append(f\"Technical debt ({hidden['technical_debt']:,.0f})\")\n\n return drivers[:3] # Top 3\n\n def _identify_optimizations(self, tco: Dict[str, Any]) -> List[str]:\n \"\"\"\n Identify cost optimization opportunities.\n\n Args:\n tco: Complete TCO analysis\n\n Returns:\n List of optimization suggestions\n \"\"\"\n optimizations = []\n\n # Check scaling efficiency\n scaling = tco['scaling_analysis']\n if scaling['scaling_efficiency'].startswith('Poor'):\n optimizations.append(\"Improve scaling efficiency - costs growing too fast\")\n\n # Check hidden costs\n hidden = tco['hidden_costs']\n if hidden['technical_debt'] > 20000:\n optimizations.append(\"Address technical debt accumulation\")\n\n if hidden['downtime_risk'] > 10000:\n optimizations.append(\"Invest in reliability to reduce downtime costs\")\n\n return optimizations\n","content_type":"text/x-python; charset=utf-8","language":"python","size":16153,"content_sha256":"55221bb79cb06c7890074beb08b4d59a38e2c3d4835495de230446272e065677"}],"content_json":{"type":"doc","content":[{"type":"heading","attrs":{"level":1},"content":[{"text":"Technology Stack Evaluator","type":"text"}]},{"type":"paragraph","content":[{"text":"Evaluate and compare technologies, frameworks, and cloud providers with data-driven analysis and actionable recommendations.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Table of Contents","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Capabilities","type":"text","marks":[{"type":"link","attrs":{"href":"#capabilities","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Quick Start","type":"text","marks":[{"type":"link","attrs":{"href":"#quick-start","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Input Formats","type":"text","marks":[{"type":"link","attrs":{"href":"#input-formats","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Analysis Types","type":"text","marks":[{"type":"link","attrs":{"href":"#analysis-types","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Scripts","type":"text","marks":[{"type":"link","attrs":{"href":"#scripts","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"References","type":"text","marks":[{"type":"link","attrs":{"href":"#references","title":null}}]}]}]}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Capabilities","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Capability","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Description","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Technology Comparison","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Compare frameworks and libraries with weighted scoring","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"TCO Analysis","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Calculate 5-year total cost including hidden costs","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Ecosystem Health","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Assess GitHub metrics, npm adoption, community strength","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Security Assessment","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Evaluate vulnerabilities and compliance readiness","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Migration Analysis","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Estimate effort, risks, and timeline for migrations","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Cloud Comparison","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Compare AWS, Azure, GCP for specific workloads","type":"text"}]}]}]}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Quick Start","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Compare Two Technologies","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"Compare React vs Vue for a SaaS dashboard.\nPriorities: developer productivity (40%), ecosystem (30%), performance (30%).","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Calculate TCO","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"Calculate 5-year TCO for Next.js on Vercel.\nTeam: 8 developers. Hosting: $2500/month. Growth: 40%/year.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Assess Migration","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"Evaluate migrating from Angular.js to React.\nCodebase: 50,000 lines, 200 components. Team: 6 developers.","type":"text"}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Input Formats","type":"text"}]},{"type":"paragraph","content":[{"text":"The evaluator accepts three input formats:","type":"text"}]},{"type":"paragraph","content":[{"text":"Text","type":"text","marks":[{"type":"strong"}]},{"text":" - Natural language queries","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"Compare PostgreSQL vs MongoDB for our e-commerce platform.","type":"text"}]},{"type":"paragraph","content":[{"text":"YAML","type":"text","marks":[{"type":"strong"}]},{"text":" - Structured input for automation","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"yaml"},"content":[{"text":"comparison:\n technologies: [\"React\", \"Vue\"]\n use_case: \"SaaS dashboard\"\n weights:\n ecosystem: 30\n performance: 25\n developer_experience: 45","type":"text"}]},{"type":"paragraph","content":[{"text":"JSON","type":"text","marks":[{"type":"strong"}]},{"text":" - Programmatic integration","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"json"},"content":[{"text":"{\n \"technologies\": [\"React\", \"Vue\"],\n \"use_case\": \"SaaS dashboard\"\n}","type":"text"}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Analysis Types","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Quick Comparison (200-300 tokens)","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Weighted scores and recommendation","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Top 3 decision factors","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Confidence level","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Standard Analysis (500-800 tokens)","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Comparison matrix","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"TCO overview","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Security summary","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Full Report (1200-1500 tokens)","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"All metrics and calculations","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Migration analysis","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Detailed recommendations","type":"text"}]}]}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Scripts","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"stack_comparator.py","type":"text"}]},{"type":"paragraph","content":[{"text":"Compare technologies with customizable weighted criteria.","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"python scripts/stack_comparator.py --help","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"tco_calculator.py","type":"text"}]},{"type":"paragraph","content":[{"text":"Calculate total cost of ownership over multi-year projections.","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"python scripts/tco_calculator.py --input assets/sample_input_tco.json","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"ecosystem_analyzer.py","type":"text"}]},{"type":"paragraph","content":[{"text":"Analyze ecosystem health from GitHub, npm, and community metrics.","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"python scripts/ecosystem_analyzer.py --technology react","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"security_assessor.py","type":"text"}]},{"type":"paragraph","content":[{"text":"Evaluate security posture and compliance readiness.","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"python scripts/security_assessor.py --technology express --compliance soc2,gdpr","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"migration_analyzer.py","type":"text"}]},{"type":"paragraph","content":[{"text":"Estimate migration complexity, effort, and risks.","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"python scripts/migration_analyzer.py --from angular-1.x --to react","type":"text"}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"References","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Document","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Content","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"references/metrics.md","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Detailed scoring algorithms and calculation formulas","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"references/examples.md","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Input/output examples for all analysis types","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"references/workflows.md","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Step-by-step evaluation workflows","type":"text"}]}]}]}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Confidence Levels","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Level","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Score","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Interpretation","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"High","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"80-100%","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Clear winner, strong data","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Medium","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"50-79%","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Trade-offs present, moderate uncertainty","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Low","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"\u003c 50%","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Close call, limited data","type":"text"}]}]}]}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"When to Use","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Comparing frontend/backend frameworks for new projects","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Evaluating cloud providers for specific workloads","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Planning technology migrations with risk assessment","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Calculating build vs. buy decisions with TCO","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Assessing open-source library viability","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"When NOT to Use","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Trivial decisions between similar tools (use team preference)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Mandated technology choices (decision already made)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Emergency production issues (use monitoring tools)","type":"text"}]}]}]}]},"metadata":{"date":"2026-11-02","name":"tech-stack-evaluator","author":"@skillopedia","source":{"stars":29164,"repo_name":"claude-skills","origin_url":"https://github.com/alirezarezvani/claude-skills/blob/HEAD/engineering-team/skills/tech-stack-evaluator/SKILL.md","repo_owner":"alirezarezvani","body_sha256":"6521c461e9c1aa818baffa4c0dcd3a4212b322faeb055273b2e50a6cdf10065c","cluster_key":"d6021a3a249c612a5910e037134d5dcc10e240761465e3c917a7440313f1459b","clean_bundle":{"format":"clean-skill-bundle-v1","source":"alirezarezvani/claude-skills/engineering-team/skills/tech-stack-evaluator/SKILL.md","text_bytes":141759,"source_commit":"9ef0c3c213932e645cc5cbeeb3c35c3a762a2437","skills_sh_rank":13813,"attachment_count":14,"text_attachments":14,"attachment_storage":"skill_attachments","binary_attachments":0},"cluster_size":1,"skill_md_path":"engineering-team/skills/tech-stack-evaluator/SKILL.md","import_metadata":{"date":"2026-11-02","author":"@skillopedia","version":"v1","category":"software-engineering","category_label":"Engineering"},"exact_dupes_collapsed_into_this":0},"version":"v1","category":"software-engineering","import_tag":"skills-sh-top20k-2026-11","description":"Use when comparing frameworks or technology stacks, or deciding on a migration, before committing. Compares with stack_comparator.py, computes TCO with tco_calculator.py, scores ecosystem health with ecosystem_analyzer.py and assesses migration with migration_analyzer.py."}},"renderedAt":1793676296004}

Technology Stack Evaluator Evaluate and compare technologies, frameworks, and cloud providers with data-driven analysis and actionable recommendations. Table of Contents - Capabilities - Quick Start - Input Formats - Analysis Types - Scripts - References --- Capabilities | Capability | Description | |------------|-------------| | Technology Comparison | Compare frameworks and libraries with weighted scoring | | TCO Analysis | Calculate 5-year total cost including hidden costs | | Ecosystem Health | Assess GitHub metrics, npm adoption, community strength | | Security Assessment | Evaluate vuln…